CAN Transmit
Edit this on GitLab
CAN Transmit Sample Application (SSK 1.x)
Overview
This sample application demonstrates how to configure a CAN channel and transmit CAN frames using the NAI Software Support Kit (SSK 1.x). It serves as a practical API reference for building your own CAN transmit functionality with NAI embedded function modules.
The application supports two payload modes:
-
Generated mode — the application creates a random payload of a specified size and transmits it.
-
File mode — the application reads payload bytes from an external text file (
transmitInputFile.txt) and transmits them.
Both CAN A/B (standard/extended) and SAE J1939 protocols are supported. The protocol determines the frame structure, maximum payload size, and whether address claiming is required before transmission.
Supported modules: CB1, CB2, CB3, CB4, CB5, CB6
Related samples:
-
CAN Receive Sample Application — receive CAN frames on one or more channels
-
CAN Interrupt Basic Sample Application — handle CAN interrupts
Prerequisites:
-
NAI board with a supported CAN module installed
-
SSK 1.x built and ready to run
-
(File mode only) A
transmitInputFile.txtin the working directory
How to run:
Launch the CAN_Transmit executable. On the first run the board menu appears so you can configure your connection. Subsequent runs skip the menu if a saved configuration file exists.
Board Connection and Module Selection
|
Note
|
This startup sequence is common to all NAI sample applications. The board connection and module selection code shown here is not specific to CAN. For details on board connection configuration, see the First Time Setup Guide. |
When the application starts, it calls naiapp_RunBoardMenu() with the configuration file default_CANTx.txt. This file does not ship with the SSK — it is created when you save your connection settings from the board menu. On the first run the board menu always appears. On subsequent runs, if the saved configuration file exists, the menu is skipped and the saved settings are loaded automatically.
After the board connection is established, you are prompted to select a card index and module number. The application verifies that the selected module is a CAN module by calling naibrd_CAN_GetChannelCount(). If the channel count is zero, the module is rejected.
inputCANConfig.modid = naibrd_GetModuleID(inputCANConfig.cardIndex, inputCANConfig.module);
channelCount = naibrd_CAN_GetChannelCount(inputCANConfig.modid);
if ((channelCount != 0))
{
Run_CAN_Transmit();
}
In your own application, use naibrd_GetModuleID() and naibrd_CAN_GetChannelCount() to confirm that a module slot contains a supported CAN module before attempting any CAN operations.
|
Important
|
Common Connection Errors
|
Program Structure
Entry Point
The application entry point is main() (or Run_CAN_Transmit_Main() on VxWorks). It initializes the CAN configuration defaults and enters the board selection loop.
initializeCANConfigurations(0, 0, 0, 0, 0, 0, MAX_CAN_PAYLOAD_AB, 8, NAI_CAN_500K_BAUD);
initializeCANConfigurations() populates the global inputCANConfig structure with safe defaults: CAN A/B maximum payload (MAX_CAN_PAYLOAD_AB), minimum payload of 8 bytes, and a 500 Kbaud bit rate. In your own code, set these values to match your system requirements before calling any channel configuration functions.
Application Parameters
The application tracks all configuration state in a global CanConfig structure:
| Field | Description |
|---|---|
|
Zero-based index of the connected board. |
|
One-based module slot number. |
|
Module ID returned by |
|
Channel range for the current operation (set to the single selected channel for transmit). |
|
Payload size limits in bytes. Protocol-dependent. |
|
Bit timing selection ( |
Your application will need to track the same values. The menu system is a sample convenience — in your own code, set these fields directly and call the API functions.
Channel Selection and Protocol Configuration
After board and module selection, you choose which CAN channel to transmit on.
maxChannel = naibrd_CAN_GetChannelCount(inputCANConfig.modid);
inputCANConfig.minChannel = 1;
inputCANConfig.maxChannel = maxChannel;
bQuit = naiapp_query_ChannelNumber(inputCANConfig.maxChannel, inputCANConfig.minChannel, &channel);
Protocol Selection
The protocol depends on the module type:
| Module | Protocol Behavior |
|---|---|
CB1 |
CAN A/B only. No protocol prompt. |
CB2 |
J1939 only. No protocol prompt. |
CB3, CB6 |
Dual-protocol. The application prompts you to select J1939 or CAN A/B. |
CB4, CB5 |
Protocol determined by module firmware configuration. |
On CB3 and CB6 modules, to set the protocol in your own application, call naibrd_CAN_SetProtocol():
/* Set channel to J1939 */
naibrd_CAN_SetProtocol(cardIndex, module, channel, NAI_CAN_PROTOCOL_J1939);
/* Or set channel to CAN A/B */
naibrd_CAN_SetProtocol(cardIndex, module, channel, NAI_CAN_PROTOCOL_AB);
The protocol selection determines several downstream behaviors:
-
CAN A/B — maximum payload is
MAX_CAN_PAYLOAD_AB(8 bytes for standard CAN). Minimum payload is 1 byte. No address claiming is required. -
J1939 — maximum payload is
NAI_J1939_MAX_DATA_LEN(up to 1785 bytes for transport protocol messages). Standard J1939 messages require exactly 8 bytes. Proprietary B messages (PGN 0xFF00—0xFFFF) allow fewer than 8 bytes. Address claiming is required before transmission.
CAN Frame Structure
Understanding the CAN frame structure helps clarify the API parameters used throughout this sample.
CAN A/B frames contain:
-
An arbitration ID (11-bit for CAN A / standard, 29-bit for CAN B / extended)
-
A data payload of 0—8 bytes
-
The
naibrd_CAN_QueueTransmit_Ex()call accepts a mode flag (isModeA) to select standard or extended framing
J1939 frames contain:
-
A Parameter Group Number (PGN) identifying the message type
-
A priority field (0—7)
-
A source address (assigned during address claiming)
-
A destination address (0xFF for broadcast)
-
A data payload of up to 8 bytes for single-frame messages, or up to 1785 bytes for multi-frame transport protocol messages
|
Important
|
Common Errors
|
Baud Rate Configuration
After protocol selection, the application prompts for a baud rate via QueryUserForCANTiming(). The supported rates are:
-
NAI_CAN_250K_BAUD— 250 Kbaud -
NAI_CAN_500K_BAUD— 500 Kbaud (default) -
NAI_CAN_1M_BAUD— 1 Mbaud
The baud rate is stored in inputCANConfig.baudRate and applied later when Cfg_Tx_CAN() configures the channel. Internally, Cfg_Tx_CAN() translates the baud rate selection into bit timing parameters (prescaler, SJW, TSEG1, TSEG2) and calls naibrd_CAN_SetBitTiming():
getCANTimingParameters(inputCANConfig.baudRate, &prescaler, &sjw, &tseg1, &tseg2);
naibrd_CAN_SetBitTiming(cardIndex, module, channel, prescaler, sjw, tseg1, tseg2);
naibrd_CAN_SetTxEnable(cardIndex, module, channel, TRUE);
To configure CAN bit timing in your own application, call naibrd_CAN_SetBitTiming() directly with the appropriate timing values for your target baud rate. Consult your module’s manual for supported baud rates and timing parameter details.
|
Important
|
Common Errors
|
Payload Source Selection
The application offers two modes for providing transmit data.
Generated Payload
When you select generated input (the default), the application prompts for a payload size in bytes. The size must fall within the protocol-dependent limits (minPayload to maxPayload).
bQuit = QueryForPayload(&payload, inputCANConfig.minPayload, inputCANConfig.maxPayload);
At transmit time, generateFIFOData() fills the FIFO buffer with random bytes of the specified length:
static void generateFIFOData(FIFO* fifoData[NAI_GEN5_CAN_MAX_CHANNEL_COUNT],
int32_t numOfFrames, int32_t minPayload,
int32_t maxPayload, int32_t min, int32_t max)
{
srand((unsigned int)time(NULL));
for (channel = min; channel <= max; channel++)
{
for (frames = 0; frames < numOfFrames; frames++)
{
length = -1;
while (length < minPayload)
{
length = rand() % (maxPayload + 1);
}
generateFrame(fifoData[channel-1]->buffer[frames].data, length);
fifoData[channel-1]->buffer[frames].length = length;
fifoData[channel-1]->numOfFramesOnFifo++;
}
}
}
Each byte in the generated frame is a random value from 0 to 15 (one hex nibble). In your own application, replace this with your actual application data.
File-Based Payload
When you select file-based input, the application opens transmitInputFile.txt from the current working directory.
fifoInputFile = fopen("transmitInputFile.txt", "r");
The file format is comma-separated hexadecimal bytes. Lines beginning with # are treated as comments and skipped. For example:
# Example CAN payload (8 bytes) A1,B2,C3,D4,E5,F6,07,18
The parser in readPayloadFromFile() reads each two-character hex value and stores it in the frame data buffer:
if (line[lineIndex] == ',')
{
byte[0] = line[lineIndex + 1];
byte[1] = line[lineIndex + 2];
frame->data[byteNum] = (uint8_t)strtol(byte, &ptr, 16);
byteNum++;
}
The file is re-read from the beginning on each transmission cycle, so you can modify the file between transmissions without restarting the application.
|
Important
|
Common Errors
|
J1939 PGN Configuration
When operating in J1939 mode, the application prompts for a Parameter Group Number (PGN) via QueryForPGN(). The PGN identifies the type of J1939 message being transmitted.
if (IsCAN_J1939(inputCANConfig.cardIndex, inputCANConfig.module, channel))
{
bQuit = QueryForPGN(&PGN);
if (PGN >= 0xFF00 && PGN <= 0xFFFF) /* Proprietary B */
{
inputCANConfig.minPayload = 0;
}
else
{
inputCANConfig.minPayload = 8;
}
inputCANConfig.maxPayload = NAI_J1939_MAX_DATA_LEN;
}
PGN values in the range 0xFF00—0xFFFF are SAE J1939 Proprietary B messages, which allow variable-length payloads (including zero bytes). All other PGN values require a minimum payload of 8 bytes per the J1939 standard.
In your own application, set the PGN to match the message type defined in the J1939 specification for your application domain (e.g., engine parameters, vehicle diagnostics).
Channel Configuration and Transmission
Once all parameters are collected, the application configures the channel and enters the transmit loop.
Configuring the Transmit Channel
inputCANConfig.minChannel = channel;
inputCANConfig.maxChannel = channel;
Cfg_Tx_CAN(inputCANConfig);
Cfg_Tx_CAN() is a shared utility that configures bit timing and enables the transmit path for the specified channel range. Internally, it calls:
-
naibrd_CAN_SetBitTiming()— sets the baud rate timing parameters -
naibrd_CAN_SetTxEnable()— enables the transmit FIFO for the channel
J1939 Address Claiming
If the channel is configured for J1939, the application performs the address claiming procedure before transmitting:
if (IsCAN_J1939(inputCANConfig.cardIndex, inputCANConfig.module, channel))
{
nai_msDelay(250);
claimAddresses(inputCANConfig.cardIndex, inputCANConfig.module, channel, channel);
}
claimAddresses() enables both transmit and receive on the channel (via naibrd_CAN_StartConfigChanges() / naibrd_CAN_SetRxEnable() / naibrd_CAN_SetTxEnable() / naibrd_CAN_ApplyConfigChanges()), then calls naibrd_CAN_SetAddress() to initiate the J1939 address claim process. It waits up to several seconds for the address to be successfully claimed, polling with naibrd_CAN_GetAddress().
Address claiming is mandatory for J1939 communication. Without a claimed source address, the CAN controller will not transmit J1939 messages.
Enabling Receive
Even though this is a transmit application, the receive path is also enabled:
setRxEnable(inputCANConfig.cardIndex, inputCANConfig.module, channel, channel, TRUE);
This is required for J1939 address claiming, which involves receiving address claim messages from other devices on the bus. For CAN A/B, enabling receive is not strictly necessary for transmission, but the sample enables it for completeness.
FIFO Allocation
The application allocates a FIFO buffer to hold one frame with the maximum payload size for the configured protocol:
fifoData[channel - 1] = allocateSpaceForFIFO(numOfFramesToTransmit, inputCANConfig.maxPayload);
allocateSpaceForFIFO() dynamically allocates a FIFO structure containing an array of CanDataFrame buffers. Each frame buffer is sized to hold maxPayload bytes.
Transmit Loop
The application enters a loop that transmits one frame each time you press Enter:
while (bContinue)
{
bQuit = naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR,
inputBuffer, &inputResponseCnt);
if (!bQuit)
{
if (generateInput)
{
generateFIFOData(fifoData, numOfFramesToTransmit, payload, payload,
channel, channel);
}
else
{
readPayloadFromFile(fifoInputFile, channel, fifoData);
}
transmitAllFIFOData_PGN(inputCANConfig.cardIndex, inputCANConfig.module,
PGN, fifoData,
inputCANConfig.minChannel, inputCANConfig.maxChannel);
printAllFIFOData(fifoData, stdout,
inputCANConfig.minChannel, inputCANConfig.maxChannel);
}
else
{
bContinue = FALSE;
}
}
On each iteration:
-
The FIFO buffer is filled — either with generated random data or by re-reading the input file.
-
transmitAllFIFOData_PGN()transmits the data. Internally, it calls eithernaibrd_CAN_QueueTransmit_J1939_Ex()(for J1939) ornaibrd_CAN_QueueTransmit_Ex()(for CAN A/B) for each frame. -
The transmitted data is printed to the console for verification.
The underlying transmit sequence for each frame is:
/* Disable Tx, queue the frame, verify it is ready, then enable Tx */
naibrd_CAN_SetTxEnable(cardIndex, module, channel, FALSE);
/* J1939: */
naibrd_CAN_QueueTransmit_J1939_Ex(cardIndex, module, channel,
PGN, priority, destination,
4, frameData[frame].data, frameData[frame].length);
/* CAN A/B: */
naibrd_CAN_QueueTransmit_Ex(cardIndex, module, channel,
isModeA, PGN, 4,
frameData[frame].data, frameData[frame].length);
naibrd_CAN_GetTxMessageWaiting(cardIndex, module, channel, &txMsgWaiting);
if (txMsgWaiting)
naibrd_CAN_SetTxEnable(cardIndex, module, channel, TRUE);
The pattern is: disable transmit, queue the frame data, confirm the message is waiting, then enable transmit to send it onto the bus.
Cleanup
When you quit the transmit loop, the application deallocates the FIFO buffer and closes the input file if one was opened:
deallocSpaceForFIFO(fifoData[channel - 1]);
if (!generateInput && fifoInputFile != NULL)
fclose(fifoInputFile);
|
Important
|
Common Errors
|
Troubleshooting Reference
|
Note
|
This section summarizes errors covered in the preceding sections. Consult your module’s manual for hardware-specific diagnostics and error register definitions. |
| Error / Symptom | Possible Causes | Suggested Resolution |
|---|---|---|
No board found |
Physical connection issue; incorrect connection type in board menu. |
Verify cabling and connection type (PCI, Ethernet, etc.). Re-run the board menu to reconfigure. |
Module not recognized |
Selected slot does not contain a CAN module; wrong module number. |
Verify hardware layout and use the correct one-based module number. |
"message not ready!" |
Transmit FIFO full; channel in error state; bus disconnected. |
Check CAN bus wiring and termination. Read the channel error status registers. Reduce transmit rate. |
J1939 address claim timeout |
Address conflict on the bus; bus not terminated; no other J1939 nodes responding. |
Verify bus termination (120 ohm at each end). Check for address conflicts. Ensure at least one other J1939 node is on the bus. |
"No input file found" |
|
Place the file in the directory where you launch the application. |
Garbled or truncated payload |
Malformed hex values in input file; missing commas; payload exceeds protocol limit. |
Verify file format: comma-separated two-character hex values, |
No bus communication |
Baud rate mismatch between transmitter and receiver. |
Ensure all nodes on the CAN bus are configured to the same baud rate. |
|
Protocol not supported by the installed module type. |
Verify the module type supports the requested protocol (CAN A/B or J1939). See the protocol selection table above. |
CAN controller in error state |
Incorrect bit timing parameters; bus wiring issues; excessive noise. |
Verify bit timing values against the module manual. Check bus wiring and termination. Inspect error counters. |
Full Source
Full Source — CAN_Transmit.c (SSK 1.x)
/**************************************************************************************************************/
/**
<summary>
This sample application lets you select a channel from a Gen5 CAN module and transmit on it.
</summary>
*/
/**************************************************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
/* Common Sample Program include files */
#include "include/naiapp_boardaccess_menu.h"
#include "include/naiapp_boardaccess_query.h"
#include "include/naiapp_boardaccess_access.h"
#include "include/naiapp_boardaccess_display.h"
#include "include/naiapp_boardaccess_utils.h"
/* Common CAN Sample Program include files */
#include "nai_can_cfg.h"
/* naibrd include files */
#include "nai.h"
#include "naibrd.h"
#include "functions/naibrd_can.h"
#include "naibrd_ether.h"
#include "advanced/nai_ether_adv.h"
/* Extern Functions or Variables*/
extern CanConfig inputCANConfig;
/********************/
/* Application Name */
/********************/
static const int8_t *CONFIG_FILE = (int8_t *)"default_CANTx.txt";
/********************************/
/* Internal Function Prototypes */
/********************************/
static bool_t Run_CAN_Transmit(void);
int32_t Run_CAN_Transmit_Main(void);
static void generateFrame(uint32_t* buffer,int32_t length);
static void generateFIFOData(FIFO* fifoData[NAI_GEN5_CAN_MAX_CHANNEL_COUNT],int32_t numOfFrames,int32_t minPayload,int32_t maxPayload,int32_t min, int32_t max);
static bool_t QueryForTransmissionSource(bool_t* generateInput);
static void readPayloadFromFile(FILE* inputFile,int32_t channel,FIFO* fifoData[NAI_GEN5_CAN_MAX_CHANNEL_COUNT]);
/**************************************************************************************************************/
/**
<summary>
The main routine assists in gaining access to the board.
The following routines from the nai_sys_cfg.c file are
called to assist with accessing and configuring the board.
- ConfigDevice
- DisplayDeviceCfg
- GetBoardSNModCfg
- CheckModule
</summary>
*/
/*****************************************************************************/
#if defined (__VXWORKS__)
int32_t Run_CAN_Transmit_Main(void)
#else
int32_t main(void)
#endif
{
bool_t stop = FALSE;
int32_t moduleCnt;
int32_t channelCount;
int8_t inputBuffer[80];
int32_t inputResponseCnt;
initializeCANConfigurations(0, 0, 0, 0, 0, 0, MAX_CAN_PAYLOAD_AB, 8, NAI_CAN_500K_BAUD);
if (naiapp_RunBoardMenu(CONFIG_FILE) == (bool_t)TRUE)
{
while (stop != TRUE)
{
/* Select Card Index */
stop = naiapp_query_CardIndex(naiapp_GetBoardCnt(), 0, &inputCANConfig.cardIndex);
if (stop != TRUE)
{
check_status(naibrd_GetModuleCount(inputCANConfig.cardIndex, &moduleCnt));
/* Select Module */
stop = naiapp_query_ModuleNumber(moduleCnt, 1, &inputCANConfig.module);
if (stop != TRUE)
{
inputCANConfig.modid = naibrd_GetModuleID(inputCANConfig.cardIndex, inputCANConfig.module);
channelCount = naibrd_CAN_GetChannelCount(inputCANConfig.modid);
if ((channelCount != 0))
{
Run_CAN_Transmit();
}
else
{
printf(" *** Module selection not recognized as valid module type for this application. ***\n\n");
}
}
printf("\nType Q to quit or Enter key to restart application:\n");
stop = naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);
}
}
}
printf("\nType the Enter key to exit the program: ");
naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);
naiapp_access_CloseAllOpenCards();
return 0;
}
/**************************************************************************************************************/
/**
<summary>
CAN_Transmit lets you generate or read data from a file and transmit it on a particular can channel.
</summary>
*/
/**************************************************************************************************************/
static bool_t Run_CAN_Transmit(void)
{
int32_t numOfFramesToTransmit;
FIFO* fifoData[NAI_GEN5_CAN_MAX_CHANNEL_COUNT];
FILE* fifoInputFile = NULL;
bool_t generateInput = FALSE;
bool_t bContinue;
int32_t maxChannel;
int32_t payload = 0;
uint32_t PGN = 0;
int32_t channel;
bool_t isJ1939 = TRUE;
bool_t bQuit = FALSE;
int8_t inputBuffer[80];
int32_t inputResponseCnt;
maxChannel = naibrd_CAN_GetChannelCount(inputCANConfig.modid);
inputCANConfig.minChannel = 1;
inputCANConfig.maxChannel = maxChannel;
printf("\nWhich channel would you like to Transmit on? \n");
bQuit = naiapp_query_ChannelNumber(inputCANConfig.maxChannel, inputCANConfig.minChannel, &channel);
if(!bQuit)
{
if( inputCANConfig.modid == NAI_MODULE_ID_CB3 || inputCANConfig.modid == NAI_MODULE_ID_CB6 )
{
bQuit = QueryForChannelProtocol(&isJ1939);
if(isJ1939 && !bQuit)
{
check_status(naibrd_CAN_SetProtocol(inputCANConfig.cardIndex, inputCANConfig.module, channel, NAI_CAN_PROTOCOL_J1939));
}
else if(!bQuit)
{
check_status(naibrd_CAN_SetProtocol(inputCANConfig.cardIndex, inputCANConfig.module, channel, NAI_CAN_PROTOCOL_AB));
}
}
else if(inputCANConfig.modid == NAI_MODULE_ID_CB2)
isJ1939 = TRUE;
else if(inputCANConfig.modid == NAI_MODULE_ID_CB1)
isJ1939 = FALSE;
}
numOfFramesToTransmit = 1;
if(!bQuit)
{
bQuit = QueryUserForCANTiming(&inputCANConfig.baudRate,isJ1939);
}
if(!bQuit)
{
bQuit = QueryForTransmissionSource(&generateInput);
}
if(IsCAN_AB(inputCANConfig.cardIndex, inputCANConfig.module,channel))
{
inputCANConfig.maxPayload = MAX_CAN_PAYLOAD_AB;
inputCANConfig.minPayload = 1;
}
else if(IsCAN_J1939(inputCANConfig.cardIndex, inputCANConfig.module,channel))
{
/* prompt user for pgn */
if(!bQuit)
bQuit = QueryForPGN(&PGN);
if(PGN >= 0xFF00 && PGN <= 0xFFFF) /*proprietary B message can have less than 8 bytes*/
{
inputCANConfig.minPayload = 0;
}
else
{
inputCANConfig.minPayload = 8;
}
inputCANConfig.maxPayload = NAI_J1939_MAX_DATA_LEN;
}
printf("\n");
if( !bQuit && generateInput )
{
bQuit = QueryForPayload(&payload,inputCANConfig.minPayload,inputCANConfig.maxPayload);
}
else if(!bQuit)
{
fifoInputFile = fopen("transmitInputFile.txt","r");
if(fifoInputFile == NULL)
{
printf("No input file found. Please provide the inputFile transmitInputFile.txt in the working directory. \n\n");
bQuit = TRUE;
}
else if(!bQuit)
{
printf("Reading Input from file \n");
}
}
if (!bQuit)
{
bContinue = TRUE;
/* Configure channel to transmit */
inputCANConfig.minChannel = channel;
inputCANConfig.maxChannel = channel;
Cfg_Tx_CAN(inputCANConfig);
if(IsCAN_J1939(inputCANConfig.cardIndex, inputCANConfig.module,channel))
{
nai_msDelay(250);
printf("\n");
claimAddresses(inputCANConfig.cardIndex,inputCANConfig.module, channel, channel);
}
/* Configure channel to Rx (Needed by other devices wishing to claim addresses) */
setRxEnable(inputCANConfig.cardIndex,inputCANConfig.module,channel , channel ,TRUE);
/* allocate fifo */
fifoData[channel - 1] = allocateSpaceForFIFO(numOfFramesToTransmit,inputCANConfig.maxPayload);
while (bContinue)
{
printf("\nPress Enter to Begin Transmission...Or Press Q to quit:\n");
bQuit = naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);
if (!bQuit)
{
if(generateInput)
{
generateFIFOData(fifoData, numOfFramesToTransmit,payload,payload,channel,channel);
}
else
{
readPayloadFromFile(fifoInputFile,channel,fifoData);
}
transmitAllFIFOData_PGN(inputCANConfig.cardIndex,inputCANConfig.module, PGN,fifoData,inputCANConfig.minChannel,inputCANConfig.maxChannel);
printf("fifo DATA Transmitted\n");
printf("-----------------------");
printf("\n");
printAllFIFOData(fifoData,stdout,inputCANConfig.minChannel,inputCANConfig.maxChannel);
printf("\n");
printf("\n");
}
else
{
bContinue = FALSE;
}
}
deallocSpaceForFIFO(fifoData[channel -1]);
}
if(!generateInput && fifoInputFile != NULL)
fclose(fifoInputFile);
return bQuit;
}
static void generateFIFOData(FIFO* fifoData[NAI_GEN5_CAN_MAX_CHANNEL_COUNT],int32_t numOfFrames,int32_t minPayload,int32_t maxPayload,int32_t min, int32_t max)
{
int32_t frames;
int32_t channel;
int32_t length;
srand((unsigned int)time(NULL));
for(channel = min; channel <= max; channel++)
{
fifoData[channel-1]->numOfFramesOnFifo = 0;
if(fifoData[channel-1] != NULL)
{
for(frames = 0; frames < numOfFrames && frames < fifoData[channel-1]->maxFramesOnFifo; frames++)
{
length = -1;
while(length < minPayload)
{
length = rand() % (maxPayload+1);
}
generateFrame(fifoData[channel-1]->buffer[frames].data,length);
fifoData[channel-1]->buffer[frames].length = length;
fifoData[channel-1]->numOfFramesOnFifo++;
}
}
}
}
static void generateFrame(uint32_t* buffer,int32_t length)
{
int32_t i;
uint8_t byte;
for(i = 0; i < length; i++)
{
byte = rand() % 16;
buffer[i] = byte;
}
}
/**************************************************************************************************************/
/**
<summary>
query user to get transmission data from file or from generating.
</summary>
*/
/**************************************************************************************************************/
static bool_t QueryForTransmissionSource(bool_t* generateInput)
{
bool_t bQuit = FALSE;
int8_t inputBuffer[80];
int32_t inputResponseCnt;
printf("\nWould you like to generate input? No(N) or Yes(Y) (Default: Y): ");
bQuit = naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);
if (!bQuit)
{
if ((inputBuffer[0] == 'N') || (inputBuffer[0] == 'n'))
{
*generateInput = FALSE;
}
else
{
*generateInput = TRUE;
}
}
return bQuit;
}
/**************************************************************************************************************/
/**
<summary>
Takes file open for reading and reads line by line and extracts CAN payload.
</summary>
*/
/**************************************************************************************************************/
static void readPayloadFromFile(FILE* inputFile,int32_t channel,FIFO* fifoData[NAI_GEN5_CAN_MAX_CHANNEL_COUNT])
{
char line[1000];
uint32_t lineIndex;
int32_t byteNum = 0;
char byte[2];
char* ptr;
CanDataFrame* frame = fifoData[channel-1]->buffer;
/* byteArray */
rewind(inputFile);
if(frame != NULL)
{
while( fgets(line,1000,inputFile) != NULL )
{
for(lineIndex = 0; lineIndex < strlen(line) && byteNum < frame->maxLength ;lineIndex++)
{
if(line[lineIndex] != '#' ) /* Line is not comment in txt file */
{
if(line[lineIndex] == ',')
{
byte[0] = line[lineIndex + 1];
byte[1] = line[lineIndex + 2];
frame->data[byteNum] = (uint8_t)strtol(byte,&ptr,16);
byteNum++;
}
else if(lineIndex == 0)
{
byte[0] = line[lineIndex];
byte[1] = line[lineIndex + 1];
frame->data[byteNum] = (uint8_t)strtol(byte,&ptr,16);
byteNum++;
}
}
else
{
lineIndex = (uint32_t)strlen(line);
}
}
}
frame->length = byteNum;
fifoData[channel-1]->numOfFramesOnFifo = 1;
}
}