SER SCM Recv
Edit this on GitLab
SER SCM Recv Sample Application (SSK 2.x)
Overview
The SER SCM Recv sample application demonstrates how to receive Manchester-encoded packets via the SCM module’s channel 1 using the NAI Software Support Kit (SSK 2.x). The application enables the channel and receiver, then enters a loop that reads packets from the receive FIFO on demand. Each packet consists of a header word (containing the data word count), a variable number of data words, a CTW (Command/Time Word), and an OVPW (Overhead/Protocol Word).
This sample is exclusive to the SCM module. It is designed to work as the receiving half of a two-application pair — run the SER SCM Xmit sample to transmit packets that this application will receive.
Prerequisites
Before running this sample, make sure you have:
-
An NAI board with an SCM module installed.
-
SSK 2.x installed on your development host.
-
The sample applications built. Refer to the SSK 2.x Software Development Guide for platform-specific build instructions.
-
A Manchester-encoded link between the transmitter and receiver (or use the companion SER SCM Xmit sample on the same board).
Board Connection and Module Selection
|
Note
|
This startup sequence is common to all NAI sample applications. |
The main() function follows a standard SSK 2.x startup flow. After connecting to the board and selecting a module, the application verifies that the module ID is NAIBRD_MODULE_ID_SCM. If not, it prints an error and returns to the menu.
check_status(naibrd_GetModuleName(cardIndex, module, &moduleID));
if ((moduleID == NAIBRD_MODULE_ID_SCM))
{
Run_SER_SCM_Recv(cardIndex, module);
}
else
{
naiif_printf("\r\nThis sample app can only be run on SCM\r\n");
}
|
Important
|
|
Channel Setup
The application uses a fixed channel (channel 1) and enables it for reception:
const int32_t CHAN = 1;
naibrd_SER_ChannelReset(cardIndex, module, CHAN);
naibrd_SER_ClearRxFifo(cardIndex, module, CHAN);
naibrd_SER_ClearTxFifo(cardIndex, module, CHAN);
check_status(naibrd_SER_SetChannelEnable(cardIndex, module, CHAN, 1));
check_status(naibrd_SER_SetReceiverEnable(cardIndex, module, CHAN, NAI_TRUE));
Packet Reception
Each time the user presses Enter, the application checks the receive FIFO count and reads a packet in two steps:
-
Read the first word (header) to determine the packet size.
-
Read the remaining words based on the header value.
naibrd_SER_GetRxBufferCnt(cardIndex, module, CHAN, (uint32_t*)&numWordsToRead);
if(numWordsToRead == 0)
{
naiif_printf("\r\nNo data received\r\n");
continue;
}
naibrd_SER_ReceiveBufferWithTimeOut32(cardIndex, module, CHAN, RecvPacket, MAX_PACKET_SIZE, 1,
NAIBRD_FIFO_TIMEOUT_NONE, &numWordsToRead);
packetSize = RecvPacket[0] + 3;
status = naibrd_SER_ReceiveBufferWithTimeOut32(cardIndex, module, CHAN, RecvPacket + 1, MAX_PACKET_SIZE - 1, packetSize - 1,
NAIBRD_FIFO_TIMEOUT_NONE, &numWordsToRead);
The header word (RecvPacket[0]) contains the number of data words. The total packet size is data_words + 3 (header + data words + CTW + OVPW).
Packet Display
The Print_Packet() function displays the packet contents:
void Print_Packet(uint32_t *packet, uint32_t size)
{
uint32_t i;
uint32_t numDataWords = size - 3;
naiif_printf("\r\nHeader: 0x%02X\r\n", packet[0] & 0x1F);
for(i = 0; i < numDataWords; i++)
{
naiif_printf("Data[%u]: 0x%08X\r\n", i, packet[1 + i]);
}
naiif_printf("CTW: 0x%08X\r\n", packet[size - 2]);
naiif_printf("OVPW: 0x%08X\r\n", packet[size - 1]);
}
-
Header — the lower 5 bits contain the data word count (max 29).
-
Data words — the payload, up to 29 words.
-
CTW — Command/Time Word.
-
OVPW — Overhead/Protocol Word.
Troubleshooting Reference
| Error / Symptom | Possible Causes | Suggested Resolution |
|---|---|---|
Module not SCM |
A non-SCM module is installed |
This application only supports the SCM module. |
No data received |
Transmitter not running, cable not connected |
Ensure the SER SCM Xmit sample is running and transmitting. |
Partial packet received |
Packet not fully received, FIFO read too early |
Press Enter again to read remaining data. |
Error receiving packet |
FIFO underflow or packet corruption |
Check the status returned by |
No board found or connection timeout |
Board not powered, incorrect configuration file |
Verify hardware is powered and connected. |
Full Source
The complete source for this sample is provided below for reference.
Full Source — ser_scm_recv.c (SSK 2.x)
/* nailib include files */
#include "nai_libs/nailib/include/naitypes.h"
#include "nai_libs/nailib/include/nailib.h"
#include "nai_libs/nailib/include/nailib_utils.h"
/* naibrd include files */
#include "nai_libs/naibrd/include/naibrd.h"
#include "nai_libs/naibrd/include/functions/naibrd_ser.h"
/* naiif include files */
#include "nai_libs/naiif/include/naiif_stdio.h"
/* Common Sample Program include files */
#include "nai_sample_apps/naiapp_common/include/naiapp_boardaccess_menu.h"
#include "nai_sample_apps/naiapp_common/include/naiapp_boardaccess_query.h"
#include "nai_sample_apps/naiapp_common/include/naiapp_boardaccess_access.h"
#include "nai_sample_apps/naiapp_common/include/naiapp_boardaccess_display.h"
#include "nai_sample_apps/naiapp_common/include/naiapp_boardaccess_utils.h"
static const int8_t *CONFIG_FILE = (const int8_t *)"default_SerSCM_recv.txt";
#define MAX_NUM_DATA_WORDS 29 /* Maximum number of data words in a packet */
#define MAX_PACKET_SIZE (MAX_NUM_DATA_WORDS + 3)
/* Function prototypes */
void Run_SER_SCM_Recv(int32_t cardIndex, int32_t module);
/**************************************************************************************************************/
/** \defgroup SERSCMRecv
* Receives packets via SCM's channel 1 Manchester-encoded packet link.
*
* Only works on SCM.
*/
/**************************************************************************************************************/
#ifdef NAIBSP_CONFIG_SOFTWARE_OS_VXWORKS
int32_t SER_SCM_Recv_Sample(void)
#else
int32_t main(void)
#endif
{
bool_t stop = NAI_FALSE;
int32_t cardIndex;
int32_t moduleCnt;
int32_t module;
uint32_t moduleID = 0;
int8_t inputBuffer[80];
int32_t inputResponseCnt;
if (naiapp_RunBoardMenu(CONFIG_FILE) == NAI_TRUE)
{
while (stop != NAI_TRUE)
{
/* Query the user for the card index */
stop = naiapp_query_CardIndex(naiapp_GetBoardCnt(), 0, &cardIndex);
if (stop != NAI_TRUE)
{
check_status(naibrd_GetModuleCount(cardIndex, &moduleCnt));
/* Query the user for the module number */
stop = naiapp_query_ModuleNumber(moduleCnt, 1, &module);
if (stop != NAI_TRUE)
{
check_status(naibrd_GetModuleName(cardIndex, module, &moduleID));
if ((moduleID == NAIBRD_MODULE_ID_SCM))
{
Run_SER_SCM_Recv(cardIndex, module);
}
else
{
naiif_printf("\r\nThis sample app can only be run on SCM\r\n");
}
}
}
naiif_printf("\r\nType Q to quit or Enter key to restart application:\r\n");
stop = naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);
}
}
naiif_printf("\r\nType the Enter key to exit the program: ");
naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);
naiapp_access_CloseAllOpenCards();
return 0;
}
static void Print_Packet(uint32_t *packet, uint32_t size);
/**************************************************************************************************************/
/** \ingroup SERSCMRecv
\param cardIndex (Input) Logical Card Index assigned to connection with the NAI_BOARD (0 - NAI_MAX_CARDS-1).
\param module (Input) Module Number of the module to access (1 - [max modules for board]).
*/
/**************************************************************************************************************/
void Run_SER_SCM_Recv(int32_t cardIndex, int32_t module)
{
const int32_t CHAN = 1;
int32_t i;
uint32_t RecvPacket[MAX_PACKET_SIZE];
int32_t numWordsToRead = 0;
int8_t inputBuffer[80];
int32_t inputResponseCnt;
uint32_t packetSize;
nai_status_t status;
naibrd_SER_ChannelReset(cardIndex, module, CHAN);
naibrd_SER_ClearRxFifo(cardIndex, module, CHAN);
naibrd_SER_ClearTxFifo(cardIndex, module, CHAN);
naiif_printf("\r\nSerial Channel # %d\r\n", CHAN);
check_status(naibrd_SER_SetChannelEnable(cardIndex, module, CHAN, 1));
check_status(naibrd_SER_SetReceiverEnable(cardIndex, module, CHAN, NAI_TRUE));
while ( NAI_TRUE )
{
naiif_printf("\r\nPress ENTER to receive a packet, or '%c' to exit program : ", NAI_QUIT_CHAR);
if (naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt))
{
break;
}
naibrd_SER_GetRxBufferCnt(cardIndex, module, CHAN, (uint32_t*)&numWordsToRead);
if(numWordsToRead == 0)
{
naiif_printf("\r\nNo data received\r\n");
continue;
}
naibrd_SER_ReceiveBufferWithTimeOut32(cardIndex, module, CHAN, RecvPacket, MAX_PACKET_SIZE, 1,
NAIBRD_FIFO_TIMEOUT_NONE, &numWordsToRead);
packetSize = RecvPacket[0] + 3;
status = naibrd_SER_ReceiveBufferWithTimeOut32(cardIndex, module, CHAN, RecvPacket + 1, MAX_PACKET_SIZE - 1, packetSize - 1,
NAIBRD_FIFO_TIMEOUT_NONE, &numWordsToRead);
if(status == NAI_SUCCESS || status == NAI_ERROR_MORE_DATA)
{
naiif_printf("\r\nReceived the following packet:");
Print_Packet(RecvPacket, packetSize);
}
else
{
naiif_printf("\r\nError receiving packet: %s\r\n", naiif_GetStatusString(status));
}
}
return;
}
void Print_Packet(uint32_t *packet, uint32_t size)
{
uint32_t i;
uint32_t numDataWords = size - 3;
naiif_printf("\r\nHeader: 0x%02X\r\n", packet[0] & 0x1F);
for(i = 0; i < numDataWords; i++)
{
naiif_printf("Data[%u]: 0x%08X\r\n", i, packet[1 + i]);
}
naiif_printf("CTW: 0x%08X\r\n", packet[size - 2]);
naiif_printf("OVPW: 0x%08X\r\n", packet[size - 1]);
}