Project for PWM synchronized by GPS

Dependencies:   GPS MODSERIAL PowerControl mbed

main.cpp

Committer:
Deurklink
Date:
2014-03-10
Revision:
0:bc3d86a76707

File content as of revision 0:bc3d86a76707:

#include <mbed.h>
#include "GPS.h"
#include <string>
#include "EthernetPowerControl.h"
#include "MODSERIAL.h"

#define XBEETIMEOUT 5

//MODSERIAL pc(USBTX,USBRX);
MODSERIAL XBee(p13,p14);
char RxBuffer[256];
bool PWMon = false;
bool RxTO = false;

GPS gps(p9,p10);


int TimingOffset;
int BeaconNumber;

// Digital pins for setting the Timing offset
DigitalIn T1(p11);
DigitalIn T2(p12);
DigitalIn T3(p15);
DigitalIn T4(p16);
DigitalIn T5(p17);
DigitalIn T6(p18);
DigitalIn T7(p19);
DigitalIn T8(p20);

// Digital pins for setting the beacon number
DigitalIn B1(p24);
DigitalIn B2(p23);
DigitalIn B3(p22);
DigitalIn B4(p21);

// mBed LED 1
DigitalOut L1(LED1);

int PulseFrequency = 25;   //Hz
int Pulselength = 1000; //usec
int PWMclock; 
int Period;

InterruptIn PPS(p5);

// PPS pin interrupt
void ppsSync(){
    // Toggle LED1
    L1 = !L1; 
    if (PWMon == true){
        // Reset PWM timer value so that new cycle immediately starts
        LPC_PWM1->TC = Period;
    }
}    

Timeout _RxTimeOut;

// XBee Receive Timeout
void rxTimeOut(){
    RxTO = true;
}


//------------------------------------DIP-SWITCHES---------------------------
void readDipSwitch(){
    // Transform the dip switch binary numbers into integers
    // For the timing offset, the leftmost bit is the sign bit (2's complement)
    TimingOffset = -128*T1 + 64*T2 + 32*T3 + 16*T4 + 8*T5 + 4*T6 + 2*T7 + T8;
    BeaconNumber = 8*B1 + 4*B2 + 2*B3 + B4;
}

void initDipSwitch(){
    // Set pull-down resistor for dip switch inputs
    T1.mode(PullDown);
    T2.mode(PullDown);
    T3.mode(PullDown);
    T4.mode(PullDown);
    T5.mode(PullDown);
    T6.mode(PullDown);
    T7.mode(PullDown);
    T8.mode(PullDown);
    
    B1.mode(PullDown);
    B2.mode(PullDown);
    B3.mode(PullDown);
    B4.mode(PullDown);   
}
//---------------------------------------------------------------------------


//------------------------------------PWM------------------------------------
void startPWM(){
    // enable PWM mode and counting
    LPC_PWM1->TCR = (1 << 3) | 1;  
    PWMon = true;
}

void stopPWM(){
    // Reset PWM-counter; this also stops it
    LPC_PWM1->TCR = 2; 
    PWMon = false;
}

void resetPWM(int _PulseFrequency, int _Pulselength){
    // Note: wherever you read pin P2.0, it is pin 2[0] of the microcontroller.
    // This is wired to p26 of the mbed board.
    stopPWM();
    // First stop PWM if it is running
    
    PWMclock = SystemCoreClock / 96;
    Period = PWMclock / _PulseFrequency; 
    
    
    LPC_SC->PCONP |= 1 << 6;
    // Reset mode PWM timer
    LPC_PWM1->TCR = 2; 
    
    // configure P2.0 for PWM1.1 - O - Pulse Width Modulator 1, channel 1 output.
    LPC_PINCON->PINSEL4 = (LPC_PINCON->PINSEL4 & ~(0x3 << 0)) | (0x1 << 0);
    
    // Disable pullups for P2.0
    LPC_PINCON->PINMODE4 = (LPC_PINCON->PINMODE4 & ~0x3) | 0x2;

    // Set prescaler
    //LPC_PWM1->PR = SystemCoreClock / (4 * 1000000) - 1; 
    
    // Set up match registers
    LPC_PWM1->MR0 = Period*24+TimingOffset;     // Set MR0 (Period)  
    /*
       TimingOffset is there to compensate for crystal errors.
       It has to be calculated for every mbed, as every crystal is a little different
       It basically adds or detracts a few cycles from every period to keep the period equal for every module
    */
    LPC_PWM1->MR1 = _Pulselength*24; // Set MR1 (Pulse length)
    LPC_PWM1->LER = 0x07;       // set latch-enable register
    LPC_PWM1->MCR |= 0x02;      // Reset PWM1 on match
    LPC_PWM1->PCR = 1 << 9;     // enable PWM1 with single-edge operation
}
//------------------------------------/PWM------------------------------------



//------------------------------------XBee------------------------------------

void printStatus(){
    // Print the status of a Beacon
    XBee.printf("\r\n\nBeacon no.: %d; TimingOffset: %d",BeaconNumber, TimingOffset);
    XBee.printf("\r\nLast GPS update: %d:%d:%2.2f",gps.hours, gps.minutes, gps.seconds);
    XBee.printf("\r\nFlash frequency: %d Hz; Pulse length: %d usec", PulseFrequency, Pulselength);
    XBee.printf("\r\nPulse generation: %d (0=off,1=on)",PWMon);
    XBee.printf("\r\nGPS location: %f,%f", gps.latitude, gps.longitude);
    XBee.printf("\r\nFixtype: %d (0=no fix,1=gps,2=differential)",gps.fixtype);
    XBee.printf("\r\nNo. of satellites: %d",gps.satellites);
}

void getXBeeData(){
    // Function used by parse data function
    // Read data from the Xbee serial Buffer
    // Wait until $ is read, then put characters received after that in RxBuffer[] until # is read.
    
    RxTO = false; // Reset time-out
    bool dollarSignRcv = false;
    bool dashRcv = false;
    
    _RxTimeOut.attach(&rxTimeOut,XBEETIMEOUT); // timeout after XBEETIMEOUT seconds
    
    while(!dollarSignRcv){
        // Read XBee until dollarsign received or timeout
        if (XBee.readable()){
            if (XBee.getc() == '$'){
                dollarSignRcv = true;
                //XBee.printf("$ received");
            }
        }
        // Timeout if no $ is received within XBEETIMEOUT seconds
        if (RxTO == true){
            wait(BeaconNumber);
            XBee.printf("\r\nBeacon %d rx time out",BeaconNumber);
            return;
        }
    }
    
    int i = 0;
    while(!dashRcv){
        // Fill buffer until dash is received, buffer is full or timeout
        if (XBee.readable()){
            RxBuffer[i] = XBee.getc();
            if(RxBuffer[i] == '#') {
                RxBuffer[i] = 0;
                dashRcv = true;
                //XBee.printf("# received");
            }
            i++;
        }
        // Return if buffer is full
        if (i > 255){
            wait(BeaconNumber);
            XBee.printf("\r\nBeacon %d rx buffer overflow",BeaconNumber);
            return;
        }
        // Timeout if no '#' is received within XBEETIMEOUT seconds
        if (RxTO == true){
            wait(BeaconNumber);
            XBee.printf("\r\nBeacon %d rx time out",BeaconNumber);
            XBee.printf("\r\nReceived: %s",RxBuffer);
            return;
        }
    }
}

void parseXBee(){
    // This function collects data from RxBuffer[] and reads it
    
    // put data into RxBuffer[]
    getXBeeData();    
    // $STATUS#
    if (strncmp(RxBuffer, "STATUS",6) == 0){
        wait(BeaconNumber);
        printStatus();
    }
    
    // $STARTPULSE#
    else if (strncmp(RxBuffer, "STARTPULSE",10) == 0){
        // Only start PWM if GPS module has a fix
        if (gps.fixtype > 0){
            startPWM();
            wait(BeaconNumber);
            XBee.printf("\r\nBeacon %d pulses started",BeaconNumber);
        }
        else{
            wait(BeaconNumber);
            XBee.printf("\r\nBeacon %d has no GPS fix",BeaconNumber);
        }   
    }
    
    // $STOPPULSE#
    else if (strncmp(RxBuffer, "STOPPULSE",10) == 0){
        if (PWMon == true){
            stopPWM();
            wait(BeaconNumber);
            XBee.printf("\r\nBeacon %d pulses stopped",BeaconNumber);
        }
        else{
            wait(BeaconNumber);
            XBee.printf("\r\nBeacon %d has not been started yet. No action",BeaconNumber);
        }
    }
    
    // $CHANGEPULSE,freq(hz),pulselength(us)#
    else if (strncmp(RxBuffer, "CHANGEPULSE",11) == 0){ 
        if(sscanf(RxBuffer, "%*s %d %d", &PulseFrequency, &Pulselength) ==2){
            resetPWM(PulseFrequency, Pulselength);
            wait(BeaconNumber);
            XBee.printf("\r\nBeacon %d frequency  set to: %d Hz. Pulselength set to %d us",BeaconNumber,PulseFrequency,Pulselength);
            XBee.printf("\r\nWaiting for start pulse command");
        }
        else{
            wait(BeaconNumber);
            XBee.printf("\r\nBeacon %d pulselength or frequency not received correctly, please try again (CHANGEPULSE,freq,pulselength)",BeaconNumber);
        }
    }
    else{
        wait(BeaconNumber);
        XBee.printf("\r\nBeacon %d did not understand message",BeaconNumber);
        XBee.printf("\r\nReceived: %s",RxBuffer);
    }
    // Flush buffer
    for (int i=0;i<255;i++){
        RxBuffer[i] = '0';
    }
}
//-----------------------------------/XBee------------------------------------


int main(void){
    // Power down ethernet module
    PHY_PowerDown();
    
    // Initialize dipswitches
    initDipSwitch();
    
    // Read beacon number and timing offset
    readDipSwitch();
    
    // Set baud rate
    XBee.baud(9600);
    
    XBee.printf("\r\n.. Beacon %d Initializing ..\n",BeaconNumber);

    // Initialize GPS unit
    gps.Init();
    
    //Attach interrupt to rising edge of GPS PPS pin
    PPS.rise(&ppsSync);     
    
    // Initialize PWM
    resetPWM(PulseFrequency, Pulselength);

    //pc.printf("\r\n.. Beacon %d Initialization finished ..\n",BeaconNumber);
    XBee.printf("\r\n.. Beacon %d Initialization finished ..\n",BeaconNumber);
    
    while(1){
       // Parse GPS data until data is received on XBee serial port
       
       if (XBee.readable()){
          parseXBee();
       }
       gps.parseData();
       readDipSwitch();
       
    }
}