V4

Dependencies:   BMP280

Fork of Thread_Communication_V4 by BDG

main.cpp

Committer:
dnonoo
Date:
2017-12-30
Revision:
9:b838c5787ed7
Parent:
8:ab6322afa341
Child:
10:c10d1337d754

File content as of revision 9:b838c5787ed7:

#include "mbed.h"
#include "main.h"
#include "stdio.h"

#define FallingEdge 0
#define RisingEdge 1
#define USER_BUTTON_PRESSED 1

LCD  lcd(PD_15, PF_12, PF_13, PE_9, PF_14, PF_15); 
BMP280 Sensor(D14, D15);

//Define Functions
void PrintLCD ();
void Rx_interrupt();
void serialCMD();
void sensorRead();
void readISR();
void circBuff();
void writeRemove_SD();
void Network1();

// USER_BUTTON ISRs (Debounce)

void userButtonRise();
void userButtonFall();
void userButtonTimeoutHandler();

// Tickers & Timeouts
Timeout userButtonTimeout; // FOR debouncing User Switch
Ticker read;            //  ***Sets sampling period!*** (ISR Signals sampling Thread)

/* LOCKS */ 
Mutex DataBuffer;
Mutex dataLock;

/* THREADS */
Thread _PrintLCD, _serialCMD, _circBuff;
Thread _sensorRead (osPriorityRealtime); //dataLock Thread
Thread _writeRemove_SD;
Thread _Network1;

/* GLOBAL DATA */
volatile float LDR = 0;
volatile double PRES = 0;
volatile double TEMP = 0;

// int to hold current switch state
int userButtonState = FallingEdge;

/* DEBOUNCER INTERRUPTS */
InterruptIn userButton(USER_BUTTON);

void userButtonRise () {
    userButton.rise(NULL);
    userButtonState = RisingEdge;
    userButtonTimeout.attach(&userButtonTimeoutHandler, 0.1);
}

void userButtonFall () {
    userButton.fall(NULL);
    _writeRemove_SD.signal_set(USER_BUTTON_PRESSED);
    userButtonState = FallingEdge;
    userButtonTimeout.attach(&userButtonTimeoutHandler, 0.1);
}

void userButtonTimeoutHandler() {
    userButtonTimeout.detach();
    
    switch (userButtonState) {
        case RisingEdge:
            userButton.fall(&userButtonFall);
            break;
        case FallingEdge:
            userButton.rise(userButtonRise);
            break;
    }// End Switch        
} //End ISR       
/*--------------------------------MAIN--------------------------------*/
int main() {
    
    pc.baud(9600);
    pc.attach(&Rx_interrupt, Serial::RxIrq);
    POST();
    
    _serialCMD.start(serialCMD);
    _PrintLCD.start(PrintLCD);
    _sensorRead.start(sensorRead);
    _circBuff.start(circBuff);
    _writeRemove_SD.start(writeRemove_SD);
    _Network1.start(Network1);
    
    userButton.rise(&userButtonRise);
    read.attach(readISR, SAMPLING_PERIOD);
    
    
    while (1) {
        Yellow_ext = ON;
        Thread::wait (200);
        Yellow_ext = OFF;
        Thread::wait(200);
        }// End While
} // End Main
/*--------------------------------------------------------------------*/
void circBuff () {
    
    while(1) { 
            Thread::signal_wait(DATA_READY); // wait for signal from sensorRead
            
            //Lock data buffer
            DataBuffer.lock();
            
            //Format samples, send to FIFO buffer head
            memset(data_buffer[sample_h],NULL,64);
            time( &raw_time );
            sample_epoch = localtime( &raw_time );
            char sample_time[20];
            strftime(sample_time,20,"%d/%m/%Y %X",sample_epoch);
            
            dataLock.lock(); //lock critical section
            sprintf(data_buffer[sample_h],"%s, %2.2f, %4.2f, %.4f\n\r", sample_time, TEMP, PRES, LDR);
            dataLock.unlock(); //unlock critical section
            
            memset(sample_time,NULL,20);
            
            //Set seperate FIFO head and tail for printing data
            data_h = sample_h;
            data_t = sample_t;
            
            //Move sample FIFO buffer head to next row in buffer
            sample_h++;
            //Check sample FIFO buffer head
            if(sample_h >= MAX_SAMPLES){
                sample_h = 0;
            }
            //Check sample FIFO buffer tail
            if(sample_t == sample_h){
                sample_t++;
                if(sample_t >= (MAX_SAMPLES)){
                    sample_t = 0;
                }
            }
            //Unlock data buffer
            DataBuffer.unlock();
    }
}

/*---------------------Read Sensors ---------------------------*/

void readISR () { // Ticker interrupt defined in main
    
    _sensorRead.signal_set(SENSOR_UPDATE);
}
// Keep short
void sensorRead () {
    
    while (1) {
        
        dataLock.lock(); // Entering Critial Section
    
        // Store Data in global Variables
        LDR = LDR_In.read();
        TEMP = Sensor.getTemperature();
        PRES = Sensor.getPressure();
        
        dataLock.unlock(); // Exiting Critical Section
    
        Green_int = !Green_int; // debugging
            
        //Read sensors, send to mail-queue
        mail_t *mail = mail_box.alloc();
        mail->LDR_Value = LDR; 
        mail->temp_Value = TEMP;
        mail->press_Value = PRES;
        mail_box.put(mail);
        
        _circBuff.signal_set(DATA_READY);  // Set signal to buffer to store updated values
        Thread::signal_wait(SENSOR_UPDATE); // Wait for the Timer interrupt
    }
}
    

/*--------------------------------LCD---------------------------------*/
void PrintLCD () {
    
    int i = 0;
    while(1){
        char lightString[16];
        char tempString[16];
        char pressString[16];

        lcd.Clear();
        lcd.RowSelect(0);
         
        switch (i){
            case 0:{
                osEvent evt = mail_box.get();
        
                if (evt.status == osEventMail) {
                    mail_t *mail = (mail_t*)evt.value.p;
            
                    sprintf(lightString,"%.4f", mail->LDR_Value);
                    sprintf(tempString,"%2.2f", mail->temp_Value);
                    sprintf(pressString,"%4.2f", mail->press_Value);    
                
                    mail_box.free(mail);
                }
               
                lcd.Write("Light Level:");
                lcd.RowSelect(1);
                lcd.Write(lightString);
                i++;                
            break;
            }
            case 1:
                lcd.Write("Temperature:");
                lcd.RowSelect(1);
                lcd.Write(tempString);
                i++;
            break;
        
            case 2:
                lcd.Write("Pressure:");
                lcd.RowSelect(1);
                lcd.Write(pressString);
                i =0;                
            break;
            
            default:            
                i = 0;                
            break;
        }
        
        Red_int = !Red_int;        

        Thread::wait (5000);
    }
}
/*--------------------------------------------------------------------*/

/*------------------------------SERIAL_CMD----------------------------*/
//Interrupt when recieving from serial port
void Rx_interrupt() {
    
    //Wait for serial input
    while (pc.readable()) {
    
        //Return input to serial
        rx_buffer[rx_in] = pc.getc();
        pc.putc(rx_buffer[rx_in]);
    
        //If enter key is pressed, set serial thread signal
        if(rx_buffer[rx_in] == 0xD){
            _serialCMD.signal_set(ENTER_KEY);
        }
    
        //Increment buffer head
        else{
            rx_in = (rx_in + 1);
        }
    }
}

//Check what command what recieved and execute
void serialCMD(){
    
    while(1){
        //Wait for thread signal
        Thread::signal_wait(ENTER_KEY);
        
        //Detach serial interrupt
        pc.attach(NULL, Serial::RxIrq);

        struct tm * s_time;
        char tm_n[4];
        
/*----CARRAGE RETURN-------------*/        
        if(rx_buffer[0] == 0xD){
            pc.puts("\n\r");
            }
/*----READ ALL----------------------------------*/
        else if(strstr(rx_buffer, "READ ALL")){
            pc.puts(" READ ALL\n\r");
        
            //Lock data buffer
            DataBuffer.lock();
        
            //Print all samples to serial
            for(int n=data_t; n<=MAX_SAMPLES; n++){
                pc.puts(data_buffer[n]);
            }
            if(data_t>data_h){
                for(int n=0; n<=(data_t-1); n++){
                    pc.puts(data_buffer[n]);
                }
            }
            
            //Lock data buffer
            DataBuffer.unlock();
        }
/*----DELETE ALL----------------------------------*/
        else if(strstr(rx_buffer, "DELETE ALL")){
            pc.puts(" DELETE ALL\n\r");
            
        //Lock data buffer
            DataBuffer.lock();
            
        //Delete all sampled data
            for(int n=0; n<=MAX_SAMPLES; n++){
                memset(data_buffer[n], NULL, 64);
            }
            data_h = data_t;
            sample_h = sample_t;
            
        //Unlock data buffer
            DataBuffer.unlock();
        }
/*----READ----------------------------------*/
        else if(strstr(rx_buffer, "READ")){
            pc.puts(" READ     \n\r");
            int N = atoi(strncpy(tm_n,&rx_buffer[5],4));
            int S = 0;
            pc.printf("N = %d\n\r",N);
            
        //Lock data buffer
            DataBuffer.lock();
        
        //Check if N is greater than buffer size
            if(N >= MAX_SAMPLES){
                N = MAX_SAMPLES;
            }
            
        //Read N samples from FIFO buffer
            if(N <= 0){
                pc.puts("####ERROR####\n\r");
            }
            else{
                for(int n=data_t; n<=MAX_SAMPLES-1; n++){
                    if(S>=N){}
                    else{
                        pc.puts(data_buffer[n]);
                        S++;
                    }
                }
                for(int n=0; n<=data_t; n++){
                    if(S>=N){}
                    else{
                        pc.puts(data_buffer[n]);
                        S++;
                    }
                }
            }

        //Unlock data buffer
            DataBuffer.unlock();
        }
/*----DELETE----------------------------------*/
        else if(strstr(rx_buffer, "DELETE")){
            pc.puts(" DELETE     \n\r");
        }
/*----SETDATE----------------------------------*/
        else if(strstr(rx_buffer, "SETDATE")){
            time(&raw_time);
            s_time = localtime(&raw_time);
            
        //Update day in time structure            
            int dd = atoi(strncpy(tm_n,&rx_buffer[8],2));
            s_time->tm_mday = dd;
            memset(tm_n, NULL, 4);
            
        //Update month in time structure
            int mm = atoi(strncpy(tm_n,&rx_buffer[11],2));
            s_time->tm_mon = mm-1;
            memset(tm_n, NULL, 4);
            
        //Update year in time structure
            int yyyy = atoi(strncpy(tm_n,&rx_buffer[14],4));
            s_time->tm_year = yyyy-1900;
            memset(tm_n, NULL, 4);
            
        //Set date from updated time structure
            set_time(mktime(s_time));
            strftime(serial_buffer, 80, "\n\r Set Date: %d/%m/%Y\n\r", s_time);
            pc.puts(serial_buffer);
        }
/*----SETTIME---------------------------------*/
        else if(strstr(rx_buffer, "SETTIME")){
            time(&raw_time);
            s_time = localtime(&raw_time);
            
        //Update seconds in time structure
            int ss = atoi(strncpy(tm_n,&rx_buffer[14],2));
            s_time->tm_sec = ss;
            memset(tm_n, NULL, 4);
        
        //Update minutes in time structure
            int mm = atoi(strncpy(tm_n,&rx_buffer[11],2));
            s_time->tm_min = mm;
            memset(tm_n, NULL, 4);
            
        //Update hour in time structure
            int hh = atoi(strncpy(tm_n,&rx_buffer[8],2));
            s_time->tm_hour = hh;
            memset(tm_n, NULL, 4);
        
        //Set time from updated time structure
            set_time(mktime(s_time));
            strftime(serial_buffer, 80, "\n\r Set Time: %X\n\r", s_time);
            pc.puts(serial_buffer);
        }
/*----SETT----------------------------------*/
        else if(strstr(rx_buffer, "SETT")){
            pc.puts(" SETT\n\r");
        }
/*----STATE----------------------------------*/
        else if(strstr(rx_buffer, "STATE")){
            pc.puts(" STATE\n\r");
        }
/*----LOGGING----------------------------------*/
        else if(strstr(rx_buffer, "LOGGING")){
            pc.puts(" LOGGING\n\r");
        }
/*----ERROR---*/
        else{
            pc.puts("####ERROR####\n\r");    
        }
/*----------------------------------------------*/
    
    //Clear serial buffers
        memset(serial_buffer, NULL, 80);
        memset(rx_buffer, NULL, 32);
        rx_in = 0;
    
    //Attach serial interrupt
        pc.attach(&Rx_interrupt, Serial::RxIrq);
    }
}
/*------------------------------------------------*/

void POST () {
    
    pc.printf(" ALL Leds should be flashing\n\r");
    
    for(unsigned int n = 0; n<10; n++) {
        Green_int = ON;
        Blue_int = ON;
        Red_int = ON;
        Green_ext = ON;
        Yellow_ext = ON;
        Red_ext = ON;
    
        wait (0.2);
        Green_int = OFF;
        Blue_int = OFF;
        Red_int = OFF;
        Green_ext = OFF;
        Yellow_ext = OFF;
        Red_ext = OFF;
        wait (0.2);
    }
    
    pc.printf("Switch states:\n\r");
    pc.printf("\tSW_L: %d\n\r\tSW_R %d\n\r", SW_L.read(), SW_R.read());
    
    float Temp = Sensor.getTemperature();
    float Pres = Sensor.getPressure();
    float ldrs = LDR_In.read();
    
    pc.printf("Sensor test:\n\r");
    pc.printf("T: %f\tP: %f\tL: %f\n\r",Temp,Pres,ldrs);
    
    pc.printf("LCD Test\n\r");
    
    lcd.Clear();
    lcd.RowSelect(1);
    lcd.Write("*******LCD******");
    lcd.RowSelect(2);
    lcd.Write("******TEST******");
    wait(1);
    lcd.Clear();    
}

void writeRemove_SD() {
    
    while(1) {
        Thread::signal_wait(USER_BUTTON_PRESSED); //wait for debounce signal
        pc.printf("Initalising SD Card\n\r");
        
        //check init
        if (sd.init() != 0) {
            pc.printf("******SD Initialise FAIL*******\n\r");
        }
        
        // Create Filing system for SD Card
        FATFileSystem fs("sd", &sd);
        
        //OpenFiles to write/append to
        pc.printf("Writing to SDC\n\r");
        
        FILE* fp = fopen("/sd/TheChamberOfSecrets.txt", "w"); //"w" to overwrite file ftb
        
        // Check for error in opening file
        if (fp == NULL) {
            pc.printf("*****ERROR - Could not open file for write*****\n\r");
        }
         //HERE IS WHERE TO PRINT DATA TO SD CARD FROM BUFFER (REMEMBER TO EMPTY BUFFER???)
         //Lock data buffer
        DataBuffer.lock();
        dataLock.lock();
        //Print all samples to SD
        for(int n=data_t; n<=MAX_SAMPLES; n++){
             fputs(data_buffer[n], fp);
             fprintf(fp, "\n\r");
            }
            if(data_t>data_h){
                for(int n=0; n<=(data_t-1); n++){
                    fputs(data_buffer[n], fp);
                    
                }
            }
            
            //Lock data buffer
            DataBuffer.unlock();
            dataLock.unlock();
        //fprintf(fp, "dd/mm/yy hh:mm:ss, TEMPERATURE, PRESSURE, LIGHT\n\r");
        
        fclose(fp); 
        
        pc.printf("Write Sucessful!\n\r");
        
        sd.deinit();
        pc.printf("SD Card Ready to Remove\n\r");
        Green_ext = 1;
        Thread::wait(500);
        Green_ext = 0;
        Thread::wait(500);
        Green_ext = 1;
        Thread::wait(500);
        Green_ext = 0;
        Thread::wait(500);
        Green_ext = 1;
        Thread::wait(500);
        Green_ext = 0;
        Thread::wait(500);
        Green_ext = 1;
        Thread::wait(500);
        Green_ext = 0;
        Thread::wait(500);
    }// End While
}// End Thread

void Network1 () {
    
    printf("Basic HTTP server example\n");
    
    //Configure an ethernet connection
    EthernetInterface eth;
    eth.set_network(IP, NETMASK, GATEWAY);
    eth.connect();
    printf("The target IP address is '%s'\n", eth.get_ip_address());
    
    //Now setup a web server
    TCPServer srv;           //TCP/IP Server
    
    SocketAddress clt_addr;  //Address of incoming connection
    
    /* Open the server on ethernet stack */
    srv.open(&eth);
    
    /* Bind the HTTP port (TCP 80) to the server */
    srv.bind(eth.get_ip_address(), 80);
    
    /* Can handle 5 simultaneous connections */
    srv.listen(5);
    
    while (true) {
        
        TCPSocket clt_sock;      //Socket for communication
        using namespace std;
        //Block and wait on an incoming connection
        srv.accept(&clt_sock, &clt_addr);
        printf("accept %s:%d\n\r", clt_addr.get_ip_address(), clt_addr.get_port());
        
        //Uses a C++ string to make it easier to concatinate
        string response;
        string strL = "LDR:";
        string strP = ", Pressure(mBar): ";
        string strT = ",  Temp(C): ";
        //This is a C string
        char l_str[64];
        char p_str[64];
        char t_str[64];
        
        //Read the LDR value
        dataLock.lock();
        float L = LDR ;
        float T = TEMP;
        float P = PRES;
        dataLock.unlock();
        
        //Convert to a C String
        sprintf(l_str, "%1.3f", L );
        sprintf(t_str, "%2.2f", T);
        sprintf(p_str, "%4.2f", P);
        
        
        //Build the C++ string response
        response = HTTP_MESSAGE_BODY1;
       // response += strL;
        response += l_str;
        response += strT;
        response += t_str;
        response += strP;
        response += p_str;
        response += HTTP_MESSAGE_BODY2;
        
        //Send static HTML response (as a C string)
        clt_sock.send(response.c_str(), response.size()+6);    
    }
}