Integrator Resources

The official home for NAI Support

Not sure where to start? Try Quick Start Guide or ask a question below!

Toggle Components with Visual Button
JavaScript Form Processing

CAN Transmit

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:

Prerequisites:

  • NAI board with a supported CAN module installed

  • SSK 1.x built and ready to run

  • (File mode only) A transmitInputFile.txt in 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

  • No board found — verify physical connection and that the correct connection type (PCI, Ethernet, etc.) is configured in the board menu.

  • Connection timeout — check network settings and confirm the board IP address is reachable.

  • Invalid card/module index — the card index is zero-based; the module number is one-based. Ensure your values match the hardware layout.

  • Module not present — naibrd_CAN_GetChannelCount() returns 0 if the slot does not contain a CAN module.

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

cardIndex

Zero-based index of the connected board.

module

One-based module slot number.

modid

Module ID returned by naibrd_GetModuleID(). Used to determine protocol support.

maxChannel / minChannel

Channel range for the current operation (set to the single selected channel for transmit).

maxPayload / minPayload

Payload size limits in bytes. Protocol-dependent.

baudRate

Bit timing selection (NAI_CAN_250K_BAUD, NAI_CAN_500K_BAUD, or NAI_CAN_1M_BAUD).

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

  • NAI_ERROR_NOT_SUPPORTED — the selected module does not support the requested protocol. Verify the module type before calling naibrd_CAN_SetProtocol().

  • Channel count is zero — the module in the selected slot is not a CAN module. Re-check your module number.

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

  • No communication on the bus — both ends of the CAN bus must be configured to the same baud rate. Mismatched timing causes all frames to be rejected at the physical layer.

  • Bus error indicators — incorrect timing parameters can put the CAN controller into an error state. Verify prescaler, SJW, TSEG1, and TSEG2 values against your module’s manual.

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

  • "No input file found" — the file transmitInputFile.txt must be in the working directory where you launched the application. Verify the file name and path.

  • Garbled data — each byte must be exactly two hex characters. Single-character values or missing commas will cause the parser to read incorrect data.

  • Payload too large — the file parser reads bytes until it reaches frame→maxLength. Excess bytes are silently ignored. Ensure your file does not exceed the protocol payload limit.

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:

  1. The FIFO buffer is filled — either with generated random data or by re-reading the input file.

  2. transmitAllFIFOData_PGN() transmits the data. Internally, it calls either naibrd_CAN_QueueTransmit_J1939_Ex() (for J1939) or naibrd_CAN_QueueTransmit_Ex() (for CAN A/B) for each frame.

  3. 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

  • "message not ready!" — naibrd_CAN_GetTxMessageWaiting() returned FALSE after queuing. The frame was not accepted by the CAN controller. This can occur if the transmit FIFO is full or if the channel is in an error state. Check the CAN bus connection and error status registers.

  • J1939 address claim failure — if claimAddresses() times out, the source address was not successfully claimed. Another device on the bus may already hold that address, or the bus may not be properly terminated. Verify bus wiring, termination resistors, and that no address conflicts exist.

  • No data transmitted — ensure naibrd_CAN_SetTxEnable() is called with TRUE after queuing the frame. The sample disables transmit before queuing and re-enables it afterward.

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"

transmitInputFile.txt is missing or not in the working directory.

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, # for comments. Check payload size against protocol limits.

No bus communication

Baud rate mismatch between transmitter and receiver.

Ensure all nodes on the CAN bus are configured to the same baud rate.

NAI_ERROR_NOT_SUPPORTED

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;
   }
}

Help Bot

X