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

 

In this post I will start development of the firmware for the prototype by setting up the microcontroller's clock, setting up a timer that can be used for counting time elapsed in milliseconds, and use GPIO to confirm the timing.

 

I have started a spreadsheet to document what peripherals I will be using as shown below.

At this point I just want to make sure the clocks are running the way I want and that the GPIO is working.   The master clock will be set at 8 MHz and I will run the sub master at the same speed.  The lower frequency / low power ACLK will be set to 32768 Hz.  I will be using the internal oscillator since I don't expect to need high accuracy.  I can always add an external crystal to the final product if needed.

 

I am setting up functions that initialize the various peripherals and then testing them as I go along.  I've also written a function milliSecs() that returns the number of milliseconds since the start.  Timer B0 is used to increment a global variable MILLIS in an ISR.

/*
 * dAISy_Alarm_V001 - implements millisecond timer and blinks LED
 *
 * MCLK, SCLK set to 8 MHz
 * Milliseconds counted on timer B0
 *
 * Frank Milburn    29 December 2017
 * Developed on MSP430FR2111 with CCS V7.2, compiler TIv17.9.0.STS
 */
#include "driverlib.h"
// Miscellaneous
#define DEBUG           2                      // 0 = no debug, 1...3 is increasing debug
// Clock and Timer related definitions
#define TIMER_UP_COUNT        8000             // approximately 1 millisecond @ 8 MHz
// GPIO related definitions
#define LED_WARN  GPIO_PORT_P1,GPIO_PIN0       // warning LED
// Function prototypes
void initClocks(void);                         // initialize clocks
void initGPIO(void);                           // initialize GPIO
void initTimerB0(void);                        // initialize timer B0
unsigned long milliSecs(void);                 // returns milliseconds since counter started
// Global variable declarations
const unsigned long BEEP_LEN  = 10;            // beep length in milliseconds
volatile unsigned long MILLIS = 0;             // running count of milliseconds
int main(void) {

    WDT_A_hold(WDT_A_BASE);                    // stop the watch dog
    PMM_unlockLPM5();                          // activate port settings after power on
    initClocks();
    initGPIO();
    initTimerB0();
    __bis_SR_register(GIE);                    // globally enable interrupts
    unsigned long startTime = milliSecs();
    for(;;){
         // run forever
    }
}
// -------------------------------------------------------------------------------------
void initClocks(void){
    __bis_SR_register(SCG0);                    // disable FLL
    CSCTL3 |= SELREF__REFOCLK;                  // Set REFO as FLL reference source
    CSCTL1 = DCOFTRIMEN_1 | DCOFTRIM0
                          | DCOFTRIM1
                          | DCORSEL_3;          // DCOFTRIM=3, DCO Range = 8MHz
    CSCTL2 = FLLD_0 + 243;                      // DCODIV = 8MHz
    __delay_cycles(3);
    __bic_SR_register(SCG0);                    // enable FLL
    CSCTL4 = SELMS__DCOCLKDIV | SELA__REFOCLK;  // set default REFO(~32768Hz) as
                                                // ACLK source, ACLK = 32768Hz
                                                // default DCODIV as MCLK, SMCLK source
}
// -------------------------------------------------------------------------------------
void initGPIO(void){
    GPIO_setAsOutputPin(LED_WARN);
    GPIO_setOutputLowOnPin(LED_WARN);
}
// -------------------------------------------------------------------------------------
unsigned long milliSecs(void){
    return MILLIS;                                // return milliseconds
}
// -------------------------------------------------------------------------------------
void initTimerB0(void){
    TB0CCTL0 |= CCIE;                             // TBCCR0 interrupt enabled
    TB0CCR0 = TIMER_UP_COUNT;                     // approx 1 millisecond
    TB0CTL |= TBSSEL__SMCLK | MC__UP;             // SMCLK, Up mode
}
// Timer B0 interrupt service routine
#if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__)
#pragma vector = TIMER0_B0_VECTOR
__interrupt void Timer_B (void)
#elif defined(__GNUC__)
void __attribute__ ((interrupt(TIMER0_B0_VECTOR))) Timer_B (void)
#else
#error Compiler not supported!
#endif
{
    MILLIS++;
    GPIO_toggleOutputOnPin(LED_WARN);           // remove this after testing accuracy     REMOVE
}

 

I need to clean this up and set up an h file :-).  Let's test and see how accurate the timer is by putting an oscilloscope on P1.0 which is being toggled in the ISR that is counting milliseconds.

Check timer accuracy

It is running within 0.5 percent which is what the datasheet shows so good to go.

 

By the way, I am skipping through this fairly fast now (depending on whether you are familiar with the MSP430 or not) but if there are questions I am happy to attempt an answer.  As must be obvious by now I am a hobbyist level programmer so if someone more knowledgeable has a better way to do things or just a different way please comment.

 

Past Posts on this Project:

AIS Alarm

AIS Alarm - The Process

AIS Alarm - Prototype Hardware

 

References and Links:

WEGMATT LLC - dAISy AIS Receiver - low cost AIS receiver

Texas Instruments MSP430FR2xx FRAM Microcontrollers - Post No. 4