first compiled version

Dependencies:   mbed-rtos mbed C12832_lcd LM75B

main.cpp

Committer:
nleoni
Date:
2014-03-11
Revision:
9:f40c7c08d1c2
Parent:
8:4fcba095bdf0

File content as of revision 9:f40c7c08d1c2:

//LAB 6: RTOS AND IPC
//WRITTEN BY: ROBERT HARRELL AND NAPOLEON LEONI

//IPC: INTER PROGRAMMER COMMUNICATION....
//This program tests IPC for the mbed RTOS
//It features an LCD thread that updates the Pot value,
//Temperature and the fortune cookie using IPC methods with timeout
//The POT thread reads the POT value in a polling loop every 10 seconds
//and uses the IPC queue to send the data to the LCD thread
//The TEMP thread reads the temp value in a polling loop every 60 seconds
//and uses the IPC queue to send the data to the LCD thread
//The fortune cookie thread reads a fortune from a user using getc on a polling loop
//every 100 ms and sends the fortune cookie via an IPC memory pool to the LCD thread
//The TOD thread updates the time of date once a minute, it uses a mutex to share the LCD
//with the LCD thread.


//***************************** TESTING ********************************************************//
//  TEST        TEST DESCRIPTION                                                STATUS          //
//  1           POT thread updates to a in less than 10 s when pot              PASS            //
//              value is changed                                                                //
//  2           Temp thread updates to a in less than 60 s when sensor          PASS            //
//              sensor temperature changes                                                      //
//  3           Strings entered with the terminal are faithfully displayed      PASS            //
//              in the LCD, no missing characters regardless of typing                          //
//              speed                                                                           //
//  4           Enetering a fortune cookie in the terminal does not block       PASS            //
//              normsl executions o the other threads                                           //
//  5           There is no risk of overunning the fortune cookie buffer        PASS            //
//              if the user continues to type beyond the allowable cookie                       //
//              length the program trims the fortune cookie and reads the                       //
//              reamining characters for the next cookie, no missing characters                 //
//  6           Pressing center joystick button at reset allows entering date   PASS            //
//              from the terminal.             
//**********************************************************************************************//


#include "mbed.h"
#include "rtos.h"
#include "C12832_lcd.h"
#include "LM75B.h"
#include <string>

//#define _DEBUGMODE  //Uncomment to enter debug mode which prints some diagnostic strings to the terminal
#define BUFFER 17
#define COOKIEQUEUE 30
#define TIMEOUT 200

C12832_LCD lcd;
Serial pc(USBTX, USBRX);   //To differentiate from LCD functions

Mutex lcdMutex;

AnalogIn pot1(p19);
MemoryPool<float, 10> potReadingBuffer;
Queue<float,10> potReadingQueue;

//Temperature Sensor
LM75B      tmp(p28,p27);
Queue<float,10> tempReadingQueue;

MemoryPool<char[BUFFER], COOKIEQUEUE> cookieReadingBuffer;
Queue<char[BUFFER],COOKIEQUEUE> cookieReadingQueue;

DigitalIn   center(p14);    //Initiate RTC clock setup

/******************************************************************
*
*An LCD thread that updates the LCD based on information 
*received from other threads via IPC
*
*Uses the top 3 lines of the LCD to reflect the pot, the 
*temperature, and the cookie. This task must use IPC (with 
*timeout) methods to get data from each of the previous threads
*
*******************************************************************/
void lcdUpdate(void const*){
while(1){
        osStatus lcdStatus = lcdMutex.lock(TIMEOUT);
        if(lcdStatus == osOK){
            osEvent evtPot = potReadingQueue.get(TIMEOUT);
            if (evtPot.status == osEventMessage) {
                float *queuePot = (float*)evtPot.value.p;
                lcd.locate(0,0);
                lcd.printf("Volt: %.2f V", *queuePot);
                potReadingBuffer.free(queuePot);      
            }
            osEvent evtTemp = tempReadingQueue.get(TIMEOUT);
            if (evtPot.status == osEventMessage) {
                float *queueTemp = (float*)evtTemp.value.p;
                lcd.locate(0,8);
                lcd.printf("Temp: %.2f F", *queueTemp);      
            }
            osEvent evtCookie = cookieReadingQueue.get(TIMEOUT);
            if (evtCookie.status == osEventMessage) {
                char (*queueCookie)[BUFFER] = (char (*)[BUFFER])evtCookie.value.p;
                lcd.locate(0,16);
                string str(*queueCookie);
                lcd.printf("F.Cookie: %s", str);    
                cookieReadingBuffer.free(queueCookie);      
            }
        }
        lcdMutex.unlock();
        Thread::wait(1000);
    }
}

/******************************************************************
*
*A POT thread that reads the pot value in a polling loop 
*every 10 seconds and sends value to LCD thread via IPC Queue 
*
*******************************************************************/
void readPOT(void const*){    
while(1){
        float *queue = potReadingBuffer.alloc();
        *queue = pot1; 
        potReadingQueue.put(queue,TIMEOUT);
        #ifdef _DEBUGMODE
        pc.printf("POT read");
        #endif
        Thread::wait(10000);
    }
    
}

/******************************************************************
*
*A TEMP thread that read the temperature every 60 seconds 
*and sends the value to the LCD task via IPC Queue
*
*******************************************************************/

void readTemp(void const*){
    float temp = 0.0;
    float *temp_ptr;
    
    while(1){
        //pc.printf("TEMP read");
        temp = tmp.read()*9/5+32;
        temp_ptr = &temp;
        tempReadingQueue.put(temp_ptr);
        Thread::wait(5000);
    }
    
}

/******************************************************************
*
*A SCANF thread that reads in a fortune cookie from user 
*and sends it to the LCD task via IPC Memory Pool
*
*******************************************************************/
void readCookie(void const*){
    pc.printf(">Enter your fortune cookie\n>");
    char (*ptrBuffer)[BUFFER] = cookieReadingBuffer.alloc();
    char *ptrChar;
    ptrChar=*ptrBuffer;
    while(1){
    //Note the choice of using getc instead of scanf to read the fortune cookie,
    //this is a non-blocking call and allows the rest of our threads to continue operating
    //only when a new character is typed this thread executes its body otherwise
    //it immediately yields to other threads.
        if(pc.readable()){
            *ptrChar=pc.getc();
            pc.putc(*ptrChar);
            if((*ptrChar=='\n') || ((ptrChar-*ptrBuffer)>=(BUFFER-1)) ){
                   if((ptrChar-*ptrBuffer)>=(BUFFER-1)) *++ptrChar='\n';
                   while((ptrChar-*ptrBuffer)<=(BUFFER-1)){
                       *ptrChar++=' ';
                    }
                   *ptrChar='\0';
                   cookieReadingQueue.put(ptrBuffer,TIMEOUT);
                   pc.printf(">Enter your fortune cookie\n>");
                   ptrChar=*ptrBuffer;
            } else {
                ptrChar++;
            }
        }
    //A 100 ms wait seems like reasonable delay which allows operation of the remaining threads.
    Thread::wait(100);
    }  
}


/******************************************************************
*
*A TOD thread that updates the 4th line of the LCD with time 
*of day once a minute. It shares the LCD with the LCD thread 
*using mutual exclusion
*
*******************************************************************/
void readTOD(void const*){
    struct tm   dt, *dtp;
    time_t      t;
    char        s[ 30 ];
    dtp = &dt;
    
    while(1){
        osStatus lcdStatus = lcdMutex.lock(TIMEOUT);
        if(lcdStatus == osOK){
            //pc.printf("TOD updated");
            t       = time( NULL );
            dtp     = localtime( &t );

            strftime( s, 20, "%b %d, %Y", dtp );
            lcd.locate( 70, 0 );
            lcd.printf( "%s", s );
    
            strftime( s, 10, "%H:%M", dtp );
            lcd.locate( 70, 8 );
            lcd.printf( "%s", s );
        }
        lcdMutex.unlock();
        Thread::wait(60000);
    } 
}

//Using a terminal, set the RTC to current date and time
void rtc_setup(void)
{
    // get the current time from the terminal
    struct tm t;
  
    lcd.locate( 0, 0 );
    lcd.printf( "Please set time from serial terminal\n\r" );

    pc.printf("Enter current date and time:\n\r");
    pc.printf("YYYY MM DD HH MM[enter]\n\r");
    pc.scanf("%d %d %d %d %d", &t.tm_year, &t.tm_mon, &t.tm_mday
              , &t.tm_hour, &t.tm_min);

    // adjust for tm structure required values
    t.tm_year = t.tm_year - 1900;
    t.tm_mon = t.tm_mon - 1;

    // set the time
    set_time(mktime(&t));
}

DigitalOut myled(LED1);

int main() {
    //RTC setup if Center Button is held down
    if (center) {  rtc_setup();   }
    lcd.cls();

    Thread threadLCD(lcdUpdate);
    Thread threadPOT(readPOT);
    Thread threadTemp(readTemp);
    Thread threadCookie(readCookie);
    Thread threadTOD(readTOD);

    while(1) {
        Thread::wait(250);       
        
    }
}