Project Objective: Develop an open source AIS Alarm that alerts sailors that a new marine vessel with AIS is within range


The prototype is now receiving AIS messages from the dAISy module.  In this post a method for storing the messages in a persistent FRAM ring buffer will be described.  This is important to the project because persistent storage means the messages will not be lost when the device is unplugged from power.


The screen shot below taken from the CCS debug view shows that 1) the ring buffer is being updated with AIS messages, and 2) that FRAM usage is 3372 bytes which gives confidence that the MSP430FR2111 will have enough memory for the job at hand.

Debug Window showing FRAM Ring Buffer

The highlighted values show the variables that have changed since the debug window was last paused.  It indicates that 3 messages were received. 


Here is how the ring buffer was defined and set up:

// Global ring buffer variable declarations
#define MBUF_SIZE 16                           // buffer size must be power of 2
#define MSG_LEN  120                           // maximum length of a NMEA message
#define FRAM_enableWrite()    SYSCFG0=FRWPPW       // macro for FRAM writing
#define FRAM_disableWrite()   SYSCFG0=FRWPPW|PFWP  // macro for disabling FRAM writing
#pragma PERSISTENT(nmea)                       // put nmea in FRAM
struct msg_s{                                  // struct for messages in circular buffer
  char msg[MSG_LEN];
} nmea[MBUF_SIZE] = {                          // initialize nmea circular buffer - must be done explicitly
//    ....+....1....+....2....+....3....+....4....+....5....+....6....+....7....+....8....+....9....+....0....+....1....+....2
     "                                                                                                                        ", // 0
     "                                                                                                                        ", // 1
     "                                                                                                                        ", // 2
     "                                                                                                                        ", // 3
     "                                                                                                                        ", // 4
     "                                                                                                                        ", // 5
     "                                                                                                                        ", // 6
     "                                                                                                                        ", // 7
     "                                                                                                                        ", // 8
     "                                                                                                                        ", // 9
     "                                                                                                                        ", // 10
     "                                                                                                                        ", // 11
     "                                                                                                                        ", // 12
     "                                                                                                                        ", // 13
     "                                                                                                                        ", // 14
     "                                                                                                                        "  // 15
char incoming[MSG_LEN];                        // temporary buffer to build incoming NMEA sentences
unsigned int msgBufHead = 0;                   // circular FIFO buffer head pointer
unsigned int msgBufTail = 0;                   // circular FIFO buffer tail pointer


I am using a ring buffer algorithm that I  have not fully tested so will leave that for a future post.  The interesting thing here (at least to me) is the way variables are designated to be placed in FRAM and made persistent (i.e. won't be lost between powering and repowering after the initial upload).  I made a previous post that went into more detail on persistent FRAM here.  But let's take the code above line by line.


  • Line 2 defines the buffer length to be 16 - it must be a power of 2 for the ring buffer that is being used.
  • Line 3 sets the message size to be 120 - AIS messages would not normally exceed a length of 100 but this provides some headroom
  • Lines 4 and 5 turn the cryptic FRAM write enable and disable register into a macro more human readable
  • Line 6 specifies that the "nmea" shall be put into FRAM and made persistent
  • Lines 7 through 9 initialize nmea as 16 messages of length 120 characters in the form of a struct
  • Lines 10 through 27 then explicitly initialize the values - this must be done or the buffer will not be placed in FRAM
  • Line 28 is the same temporary buffer used previously to build the NMEA sentences as they come in over UART
  • Lines 29 and 30 are used in the yet to be described ring buffer algorithm


The coding took longer to write than normal because the compiler had to barf all over my attempts to explicitly initialize nmea.  In the end is clear what is going on but it seems unwieldy and specifying this way prone to error.  I will investigate further because my C skills aren't that great, particularly with character manipulation.  Of course C is not exactly know for easy character manipulation.  If you have a better way, please outline in the comments.


Let's check and make sure it did what was wanted with a screen shot of the .map file.

Map File showing FRAM Persistent Storage

The output section titled .TI.persistent shows the origin and length of anything placed in FRAM and made persistent.  In this case it shows nmea was made persistent at starts at

0000f100 and is of length 00000780.  Using my trusty Windows calculator in programming mode I calculate the length to be 1,920 in decimal which is equal to the desired 16 messages x 120 characters.


In upcoming posts the ring buffer will be described and tested.  It is also time to start thinking about the hardware and what enclosure will be used.  As always, thanks for reading - comments and suggestions for improvement are very welcome.



Past Posts from this Project:

AIS Alarm

AIS Alarm - The Process

AIS Alarm - Prototype Hardware

AIS Alarm - Timers and GPIO

AIS Alarm - Prototype Code Outline

AIS Alarm - UART

AIS Alarm - First AIS Messages


References and Links:

WEGMATT LLC - dAISy AIS Receiver - low cost AIS receiver

Texas Instruments MSP430FR2xx FRAM Microcontrollers - Post No. 4

TI MSP430FR2111