V4

Dependencies:   BMP280

Fork of Thread_Communication_V4_fortest by BDG

main.cpp

Committer:
benparkes
Date:
2018-01-06
Revision:
18:728fddea6d9c
Parent:
17:aa585f901750

File content as of revision 18:728fddea6d9c:

#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();
void LCD_timerISR();

// 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)
Ticker refresh;
/* 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;
volatile char TIME[21];

volatile double sampleTime = 15.0;
//int LCD_refresh = 1;
// 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(57600);
    pc.attach(&Rx_interrupt, Serial::RxIrq);
    POST();

    pc.printf("\n\n\nType HELP for list of available Commands\n\n\n\r");
    _serialCMD.start(serialCMD);
    _sensorRead.start(sensorRead);
    _PrintLCD.start(PrintLCD);
    _circBuff.start(circBuff);
    _writeRemove_SD.start(writeRemove_SD);
    _Network1.start(Network1);

    userButton.rise(&userButtonRise);
    read.attach(&readISR, sampleTime);
    refresh.attach(&LCD_timerISR, LCD_REFRESH);

    while (1) {
        Yellow_ext = ON;
        Thread::wait (200);
        Yellow_ext = OFF;
        Thread::wait(200);
    }// End While
} // End Main
/*--------------------------------------------------------------------*/
/*-----------------Circular Buffer------------------------------------*/
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);

        osEvent evt = mail_FIFO.get();

        if (evt.status == osEventMail) {
            mail_t *mail = (mail_t*)evt.value.p;
            char sample_time[21];
            int rTime = mail->Time_Date;
            time((time_t*)rTime);
            sample_epoch = localtime((time_t*)rTime);
            strftime(sample_time, 21,"%d/%m/%Y, %X", sample_epoch);
            sprintf(data_buffer[sample_h],"%s, %2.2f, %4.2f, %.4f\n\r", sample_time, mail->temp_Value, mail->press_Value, mail->LDR_Value);

            mail_FIFO.free(mail);
        }




        //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();
    }// End While
}// End Circular buffer
/*-------------------------------------------------------------*/
/*---------------------Read Sensors ---------------------------*/

void readISR ()   // Ticker interrupt defined in main
{

    _sensorRead.signal_set(SENSOR_UPDATE);
}
// Keep short
void sensorRead ()
{
    volatile float LDR = 0;
    volatile double PRES = 0;
    volatile double TEMP = 0;
    
    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_LCD.alloc();
        mail->LDR_Value = LDR;
        mail->temp_Value = TEMP;
        mail->press_Value = PRES;
        mail_LCD.put(mail);

        mail_t *mail1 = mail_FIFO.alloc();
        mail1->Time_Date =  raw_time;
        mail1->LDR_Value = LDR;
        mail1->temp_Value = TEMP;
        mail1->press_Value = PRES;
        mail_FIFO.put(mail);

        mail_t *mail2 = mail_Network.alloc();
        mail1->Time_Date =  raw_time;
        mail2->LDR_Value = LDR;
        mail2->temp_Value = TEMP;
        mail2->press_Value = PRES;
        mail_Network.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 LCD_timerISR ()
{
    _PrintLCD.signal_set(LCD_READY);
}

void PrintLCD ()
{

    int i = 0;
    int j = 4;
    char lightString[16];
    char tempString[16];
    char pressString[16];
    char lcd_TIME[21];

    while(1) {

        lcd.RowSelect(3);


        if (j == 4) {

            lcd.Clear();
            lcd.RowSelect(0);
            switch (i) {
                case 0: {
                    osEvent evt = mail_LCD.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_LCD.free(mail);
                    }

                    lcd.Write("Light:");
                    lcd.RowSelect(1);
                    lcd.Write(lightString);
                    i++;
                    j = 0;
                    break;
                }
                case 1:
                    lcd.Write("Temperature(C):");
                    lcd.RowSelect(1);
                    lcd.Write(tempString);
                    i++;
                    j = 0;
                    break;

                case 2:
                    lcd.Write("Pressure(mBar):");
                    lcd.RowSelect(1);
                    lcd.Write(pressString);
                    i =0;
                    j = 0;
                    break;

                default:
                    i = 0;
                    j = 0;
                    break;
            }//end switch
        }// end if
        else {
            j++;
        }
        lcd.RowSelect(3);

        dataLock.lock();
        memset(lcd_TIME, NULL, 21);
        time(&raw_time);
        sample_epoch = localtime(&raw_time);
        strftime( lcd_TIME,21,"%d/%m/%Y  %X", sample_epoch);
        dataLock.unlock();

        lcd.Write(lcd_TIME);
        Thread::signal_wait(LCD_READY);
        Red_int = !Red_int;
    }//end while
}// end thread
/*--------------------------------------------------------------------*/

/*------------------------------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 {
            if(rx_in>=32) {
                puts("\n\rERROR - Stop typing so much!\n\r");
                rx_in = 0;
                memset(rx_buffer, NULL, 32);
            } else {
                rx_in = (rx_in + 1);
            }
        }
    }
}

//Check what command what recieved and execute
void serialCMD()
{
    bool xx = 1; // State for CMD STATE
    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("\n\r Reading all samples...\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();
            pc.puts(" All Samples read!\n\r");
        }
        /*----DELETE ALL----------------------------------*/
        else if(strstr(rx_buffer, "DELETE ALL")) {
            pc.puts("\n\r Deleting all samples...\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();
            pc.puts(" All previous samples deleted!\n\r");
        }
        /*----READ----------------------------------*/
        else if(strstr(rx_buffer, "READ")) {
            pc.puts("\n\r Reading N samples...\n\r");
            int N = atoi(strncpy(tm_n,&rx_buffer[5],4));
            int S = 0;

            //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 must be greater than 0\n\r");
                N = 0;
            } else {
                for(int n=data_h; n>=0; n--) {
                    if(S>=N) {}
                    else {
                        pc.puts(data_buffer[n]);
                        S++;
                    }
                }
                for(int n=MAX_SAMPLES-1; n<=data_t; n--) {
                    if(S>=N) {}
                    else {
                        pc.puts(data_buffer[n]);
                        S++;
                    }
                }
            }
            pc.printf(" Read %d samples\n\r",N);
            //Unlock data buffer
            DataBuffer.unlock();
        }
        /*----DELETE----------------------------------*/
        else if(strstr(rx_buffer, "DELETE")) {
            pc.puts("\n\r Deleting N samples...\n\r");
            int N = atoi(strncpy(tm_n,&rx_buffer[6],4));
            int S = 0;

            //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 must be greater than 0\n\r");
                N = 0;
            } else {
                for(int n=data_t; n<=MAX_SAMPLES; n++) {
                    if(S>=N) {}
                    else {
                        memset(data_buffer[n], NULL, 64);
                        S++;
                        data_t = n;
                        sample_t = n;
                    }
                }
                for(int n=MAX_SAMPLES-1; n<=data_t; n--) {
                    if(S>=N) {}
                    else {
                        memset(data_buffer[n], NULL, 64);
                        S++;
                        data_t = n;
                        sample_t = n;
                    }
                }
            }
            pc.printf(" Deleted %d samples\n\r",N);
            //Unlock data buffer
            DataBuffer.unlock();
        }
        /*----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 Date updated to: %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 Time updated to: %X\n\r", s_time);
            pc.puts(serial_buffer);
        }
        /*----SETT----------------------------------*/
        else if(strstr(rx_buffer, "SETT")) {
            read.detach();
            double AA = atof(strncpy(tm_n,&rx_buffer[5],4));

            if (AA < 0.1 || AA > 60) {
                AA = 15;
                pc.puts("ERROR - Sample Time out of range (0.1<=T<=60)\n\r");
            }
            sampleTime = AA;
            pc.printf("\n\r Sample Time updated to: %2.1f seconds\n\r", sampleTime);
            read.attach(readISR, sampleTime);
            memset(tm_n, NULL, 4);
        }
        /*----STATE----------------------------------*/
        else if(strstr(rx_buffer, "STATE")) {

            strncpy(tm_n,&rx_buffer[6],3);
            if  (strstr(tm_n, "ON")) {
                if (xx == 1) {
                    pc.puts("\n\r Already Sampling\n\r");
                } else {
                    read.attach(&readISR, sampleTime);
                    pc.puts("\n\r Sampling ON\n\r");
                    xx = 1;
                }
            } else if (strstr(tm_n, "OFF")) {
                if ( xx == 0 ) {
                    pc.puts("\n\r Already not Sampling\n\r");
                } else {
                    read.detach();
                    pc.puts("\n\r Sampling OFF\n\r");
                    xx = 0;
                }
            } else {
                pc.puts("Error - STATE can only be ON or OFF\n\r");
            }
            //pc.puts(" STATE\n\r");
        }
        /*----LOGGING----------------------------------*/
        else if(strstr(rx_buffer, "LOGGING")) {
            pc.puts(" LOGGING\n\r");
        }
        /*----HELP--------------------------------------*/
        else if (strstr(rx_buffer, "HELP")) {
            pc.puts("\n\n\r Currently Available Commands:\n\r");
            pc.puts("\tREAD n   - Read n previous samples\n\r");
            pc.puts("\tREAD ALL - Read All previous samples held in memory\n\r");
            pc.puts("\tSETTIME hh:mm::ss  - Set time in 24hr format\n\r");
            pc.puts("\tSETDATE dd/mm/yyyy - Set time in specified format\n\r");
            pc.puts("\tDELETE ALL   - Delete all sampled held in internal memory\n\r");
            pc.puts("\tSETT - Set sample period. must be an integer in range 0 < T < 61\n\r");
        } else if (strstr(rx_buffer,"tell me a joke")) {
            pc.puts("\n\r Why do programmers always get Halloween and Christmas mixed up...?\n\r");
            Thread::wait(5000);
            pc.puts(" Because Oct 31 == Dec 25! LOL");
        }
        /*----ERROR---*/
        else {
            pc.puts("Error - Command not recognised. Type HELP for a list of available commands\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);
    }
}
/*------------------------------------------------*/
/*---------------SD THread------------------------*/
void writeRemove_SD()
{

    while(1) {
        Thread::signal_wait(USER_BUTTON_PRESSED); //wait for debounce signal
        int sd_state = sdIn;

        switch (sd_state) {
            case 1:
                pc.printf("SD Card not inserted!\n\r");
                pc.printf("Insert SD Card and press User button again\n\r");
                break;
            default:
                pc.printf("This should never happen\n\r");
                break;
            case 0:
                pc.printf("Initalising SD Card\n\r");

                //check init
                if (sd.init() != 0) {
                    pc.printf(" ERROR - SD card failed to initialise.\n\rRestart board\n\r PROBABLY wires come out\n\r");
                } else {
                    // 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", "a"); //"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 if
        }//End Switch
    }// End While
}// End Thread
/*--------------------------------------------------------------------------*/

/*---------------------------Networking Thread------------------------------*/
void Network1 ()
{

    printf("Setting up server\n\r");

    //Configure an ethernet connection
    EthernetInterface eth;
    eth.set_network(IP, NETMASK, GATEWAY);
    eth.connect();
    if (eth.get_ip_address() == NULL) {
        pc.printf("Error - Can't get IP. Network not setup\n\r");
        pc.printf("Reset Required. Make sure network cables are plugged in\n\r");
    } else {
        printf("The target IP address is '%s'\n\r", 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);

        TCPSocket clt_sock;      //Socket for communication

        pc.printf("\rServer Ready\n\r");

        while (true) {

            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): ";
            string strDT ="Date/Time:  ,";

            //This is a C string

            char X_str[128];

            /*//Read the LDR value
            dataLock.lock(); // add watchdog?
            float L = LDR ;
            float T = TEMP;
            float P = PRES;
            char DT[21];
            strcpy((char*)TIME,DT);
            dataLock.unlock();

            //Convert to a C String
            //sprintf(l_str, "%1.3f", L ); // try \n\r??
            //sprintf(t_str, "%2.2f", T);
            //sprintf(p_str, "%4.2f", P);*/
            osEvent evt = mail_Network.get();

            if (evt.status == osEventMail) {
                mail_t *mail = (mail_t*)evt.value.p;
                char sample_time[21];
                int rTime = mail->Time_Date;
                time((time_t*)rTime);
                sample_epoch = localtime((time_t*)rTime);
                strftime(sample_time, 21,"%d/%m/%Y, %X", sample_epoch);
                sprintf(X_str,"%s, \n\rTemperature: %2.2f, \n\rPressure: %4.2f, \n\rLight: %.4f", sample_time, mail->temp_Value, mail->press_Value, mail->LDR_Value);

                mail_Network.free(mail);
            }



            //Build the C++ string response
            response = HTTP_MESSAGE_BODY1;
            response += X_str;
            /* response += strL;
            response += strDT;
            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);

        }// end While
    }//end if
}// end thread
/*---------------------------POST--------------------------------------------*/
void POST ()
{
    pc.printf(" Basic POST\n\r");
    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(0);
    lcd.Write("1******LCD*********1");
    lcd.RowSelect(1);
    lcd.Write("2******TEST********2");
    lcd.RowSelect(2);
    lcd.Write("3******LCD*********3");
    lcd.RowSelect(3);
    lcd.Write("4******TEST********4");

    wait(1);
    lcd.Clear();
    pc.printf("Basic POST end\n\r");
}