Latest

Dependencies:   serial_terminal sample_hardware PLL_Config SDCard BMP280 Networkbits TextLCD SDBlockDevice

main.cpp

Committer:
Swabey89
Date:
2018-12-22
Revision:
28:7fccaef8fa72
Parent:
27:bb8d4c883e1b
Child:
29:806e9281af2f

File content as of revision 28:7fccaef8fa72:

#include "mbed.h"
#include "sample_hardware.hpp"
#include "Networking.hpp"
#include "serial_terminal.hpp"
#include "SDCard.hpp"
#include "rtos.h"
#include "events/mbed_events.h"
#include "LCDdisplay.hpp"

//Defines TEST FOR SD CARD MOUNT AND UNMOUNT
#define EDGE_FALLEN 0
#define EDGE_RISEN 1

//Signals
#define TAKE_SAMPLE 1
#define STORE_DATA 2


//Global variables


unsigned int newestIndex = BUFFERSIZE-1;    //First time it is incremented, it will be 0
unsigned int oldestIndex = BUFFERSIZE-1;
FILE* fp;
FATFileSystem* fs;

//Shared mutable variables VOLATILE
bool sd_init; //is it?
bool logging = false;
float sample_rate = 15; //is it?
struct tm* timeData;
char cmdBuffer[256];
sensorData buffer[BUFFERSIZE];
RawSerial* pc;

//Thread synchronisation primatives
Semaphore spaceAvailable(BUFFERSIZE);
Semaphore samplesInBuffer(0, BUFFERSIZE);
Mutex bufferLock;

//Queues
EventQueue SDqueue(32*EVENTS_EVENT_SIZE);
EventQueue LCDqueue(32*EVENTS_EVENT_SIZE);
EventQueue serialqueue(32*EVENTS_EVENT_SIZE);

//Threads
Thread producer_thread(osPriorityHigh);
Thread consumer_thread;
Thread serial_thread(osPriorityAboveNormal);
Thread SDqueue_thread; //remove
Thread LCDqueue_thread;
Thread Network_thread;

//TEST FOR SD CARD
Thread SDmount_thread;

//Timers
Ticker sample;

//Function prototypes
void sampleISR(void);
void sampleProducer(void);
void sampleConsumer(void);
void serialISR(void);
void serialData(void);



//TEST FOR SD CARD MOUNT AND UNMOUNT
Timeout userswTimeOut;
int userswState = EDGE_FALLEN;
InterruptIn   usersw(USER_BUTTON);
void userswTimeOutHandler();
void userswRisingEdge();
void userswFallingEdge();
void SDmount();

Mutex printlock;
Mutex LCDlock;
Mutex timeLock;
Mutex SDlock;


//TEST FOR BUFFER CHANGES
unsigned int saveIndex = BUFFERSIZE-1;

int32_t Nspaces = BUFFERSIZE;
int32_t Nsamples;


int main() {   
    timeData = new tm;
    pc = new RawSerial(USBTX, USBRX);
    
    //Initialisations
    SDcard();   
    
    //Power on self test
    post();
   
    //Start threads
    SDqueue_thread.start(callback(&SDqueue, &EventQueue::dispatch_forever));
    LCDqueue_thread.start(callback(&LCDqueue, &EventQueue::dispatch_forever));
    serial_thread.start(callback(&serialqueue, &EventQueue::dispatch_forever));
    Network_thread.start(network);
    producer_thread.start(sampleProducer);
    consumer_thread.start(sampleConsumer);
    
    //TEST FOR SD CARD
    SDmount_thread.start(SDmount);
    
   
    //Attach ISRs
    sample.attach(&sampleISR, sample_rate);  //Allow sampling to start  
    pc->attach(serialISR, Serial::RxIrq);
    
    //TEST FOR SD CARD MOUNT AND UNMOUNT
    usersw.rise(&userswRisingEdge);
    
    //Flash to indicate goodness
    while(true) {
        greenLED = !greenLED;
        Thread::wait(500);    
    }
}

/*
FUNCITONS BELOW NEED MOVING?
*/

void sampleISR()
{
    producer_thread.signal_set(TAKE_SAMPLE);   
}
    
void serialISR()
{
    pc->attach(NULL, Serial::RxIrq);
    serialqueue.call(serialData);
}

void serialData()
{    
    static int i = 0;
    if (pc->readable())
    {
        cmdBuffer[i] = pc->getc();
        if (cmdBuffer[i] == '\r')
        {
            cmdBuffer[i+1]==NULL;
            serialqueue.call(serialterm);
            i = 0;                                
        }
        else i++;
    }
    pc->attach(serialISR, Serial::RxIrq);
}


void sampleProducer()
{
    while(true)
    {
        //High priority thread 
        Thread::signal_wait(TAKE_SAMPLE);        
        Nspaces = spaceAvailable.wait(0); //Non-blocking
        bufferLock.lock();   
        //Update buffer     
        newestIndex = (newestIndex+1) % BUFFERSIZE;  //CIRCULAR  
        
         if (newestIndex == oldestIndex)
        {
            oldestIndex = (oldestIndex+1) % BUFFERSIZE;     
        }        
              
        buffer[newestIndex].updatetemp(sensor.getTemperature());
        buffer[newestIndex].updatepress(sensor.getPressure());
        buffer[newestIndex].updatelight(adcIn.read());
        buffer[newestIndex].updateTime();        
        //bufferLock.unlock(); //normally here, moved due to updating queues.
               
        if (Nspaces != 0)
        {   
            Nspaces--;            
        } 
          
        samplesInBuffer.release();
             
        //Pass onto queues
        LCDqueue.call(LCD_display, buffer[newestIndex].gettemp(),buffer[newestIndex].getpress(),buffer[newestIndex].getlight());
        
        if(logging)
        {
            printlock.lock();
            pc->printf("%s: Sample placed in buffer at position %d\r\n", buffer[newestIndex].getTime(), newestIndex);
            pc->printf("Number of spaces available in buffer:%d\r\n\n",Nspaces);
            printlock.unlock();   
        }
        
        bufferLock.unlock();
        
    }
}

void sampleConsumer()
{
    while(true)
    {
        static time_t seconds; //possibly move into if(sd_init)
        //write to the SD card from oldestindex up to newestIndex.
        
        Nsamples = samplesInBuffer.wait(); //Block if no samples to take - acquires
        
        if (sd_init)
        {     
            char fileDate[30];
            timeLock.lock();
            seconds = time(NULL);
            timeData = localtime(&seconds);
            
            //set_time(mktime(timeData));
            
            strftime(fileDate, 30, "sd/log_%d_%m_%y.csv", timeData);
            timeLock.unlock();
            
            fp = fopen(fileDate,"a");
            if (fp == NULL)
            {
                printlock.lock();
                pc->printf("WARNING: SD card could not be updated\r\n\n");
                sd_init = false;
                printlock.unlock();  
                samplesInBuffer.release();
            }
            else
            {
                //Nested locks probably a bad idea!
                bufferLock.lock();
                SDlock.lock();             
                oldestIndex = (oldestIndex+1) % BUFFERSIZE;
                fprintf(fp,"%s,%5.2f,%5.2f,%5.2f\r", buffer[oldestIndex].getTime(), buffer[oldestIndex].gettemp(), buffer[oldestIndex].getpress(), buffer[oldestIndex].getlight());                
                SDlock.unlock();
                
                if(logging)
                {
                    printlock.lock();
                    pc->printf("Log file %s updated with sample from position %d in buffer\r\n",fileDate,oldestIndex);
                    pc->printf("newestIndex position %d\r\n",newestIndex);
                    pc->printf("oldestIndex position %d\r\n",oldestIndex);
                    printlock.unlock();  
                }
                
                bufferLock.unlock();          
                fclose(fp);
            }           
            redLED = 0;  
        }  
        else
        {
            samplesInBuffer.release();   
        } 
        
               
    }   
}

//TEST FOR MOUNTING AND UNMOUNTING SD CARD
//Interrupt service routine for handling the timeout


void userswTimeOutHandler() {
    userswTimeOut.detach();            //Stop the timeout counter firing

    //Which event does this follow?
    switch (userswState) {
    case EDGE_RISEN:    
        usersw.fall(&userswFallingEdge);  //Now wait for a falling edge
        break;
    case EDGE_FALLEN:
        usersw.rise(&userswRisingEdge);   //Now wait for a rising edge
        break;
    } //end switch 
}

//Interrupt service routine for a rising edge (press)
void userswRisingEdge() {
    usersw.rise(NULL);             //Disable detecting more rising edges
    userswState = EDGE_RISEN;      //Flag state
    userswTimeOut.attach(&userswTimeOutHandler, 0.2);    //Start timeout timer
}

//Interrupt service routive for SW1 falling edge (release)
void userswFallingEdge() {
    usersw.fall(NULL);                         //Disable this interrupt    
    SDmount_thread.signal_set(SIGNAL_SD);
    userswState = EDGE_FALLEN;                 //Flag state
    userswTimeOut.attach(&userswTimeOutHandler, 0.2);    //Start timeout counter - may want to increase this  
}