Final tidy of code following installation of new sensor, more comments added prior to submission

Dependencies:   mbed

main.cpp

Committer:
legstar85
Date:
2022-02-04
Revision:
18:fc63b51a0302
Parent:
17:793f819e1df6

File content as of revision 18:fc63b51a0302:

/* 
* Prints a string of characters to the screen buffer, string is cut off after the 83rd  pixel.
* @param x - the column number (0 to 83)
* @param y - the row number (0-5) - the display is split into 6 banks - each bank can be considered a row
*
* @ File main.cpp
* @ Author - David Leaming - 25574043
* @ Date - January 2022
*
* Acknowledgements 
* Craig A. Evans, University of Leeds, TMP102 Library, Feb 2016
* Dr Edmond Nurellari, University of Lincoln, Joystick, N5110 Libraries & SD Card Libraries
* Paul Staron, Piezo Buzzer utility, April 2019
*/ 

#include "mbed.h"                                                               // Include the library header, ensure the library has been imported into the project
#include "TMP102.h"                                                             // Inclusion of library to allow use of code within them as necessary
#include "N5110.h"                                                              // Inclusion of library to allow use of code within them as necessary
#include "Joystick.h"                                                           // Inclusion of library to allow use of code within them as necessary
#include "Bitmap.h"                                                             // Inclusion of library to allow use of code within them as necessary
#include "SDFileSystem.h"                                                       // Inclusion of library to allow use of code within them as necessary
                                                                                //
TMP102 tmp102(I2C_SDA,I2C_SCL);                                                 // Create TMP102 object  
                                                                                //
//        VCC,SCE,RST,D/C,MOSI,SCLK,LED                                         //    
N5110 lcd(PTC9,PTC0,PTC7,PTD2,PTD1,PTC11);                                      // Create Screen Object - K64F - pwr from 3V3, GND Pin also needs connecting
                                                                                //
//                  y     x     button                                          //    
Joystick joystick(PTB10,PTB11,PTC16);                                           // Define Joystick Object 
                                                                                //        
SDFileSystem sd(PTE3, PTE1, PTE2, PTE4, "sd");                                  // MOSI, MISO, SCK, CS - Connections to SD card holder on K64F (SPI interface)
                                                                                //
Serial pc(USBTX,USBRX);                                                         // UART connection for PC
                                                                                //
struct State {                                                                  // Struct for state
    int output;                                                                 // output value
    float time;                                                                 // time in state
    int nextState[9];                                                           // array of next states
};                                                                              //
                                                                                //
State fsm[11] = {                                                               //
    {15,0.5,{0,1,0,0,0,10,0,0,0}},                                              // State 0 - 15 Degrees
    {16,0.5,{1,2,1,1,1,0,1,1,1}},                                               // State 1 - 16 Degrees
    {17,0.5,{2,3,2,2,2,1,2,2,2}},                                               // State 2 - 17 Degrees
    {18,0.5,{3,4,3,3,3,2,3,3,3}},                                               // State 3 - 18 Degrees
    {19,0.5,{4,5,4,4,4,3,4,4,4}},                                               // State 4 - 19 Degrees
    {20,0.5,{5,6,5,5,5,4,5,5,5}},                                               // State 5 - 20 Degrees
    {21,0.5,{6,7,6,6,6,5,6,6,6}},                                               // State 6 - 21 Degrees
    {22,0.5,{7,8,7,7,7,6,7,7,7}},                                               // State 7 - 22 Degrees
    {23,0.5,{8,9,8,8,8,7,8,8,8}},                                               // State 8 - 23 Degrees
    {24,0.5,{9,10,9,9,9,8,9,9,9}},                                              // State 9 - 24 Degrees
    {25,0.5,{10,1,10,10,10,9,10,10,10}}                                         // State 10 - 25 Degrees   
};                                                                              //
                                                                                //
Ticker ticker_menu;                                                             // Create Menu ticker object
                                                                                //        
DigitalOut r_led(LED_RED);                                                      // K64F on-board LEDs 
DigitalOut g_led(LED_GREEN);                                                    // K64F on-board LEDs 
DigitalOut b_led(LED_BLUE);                                                     // K64F on-board LEDs 
                                                                                //
PwmOut LED01 (PTA1);                                                            // PCB Surface Mounted LED's - LED1
PwmOut LED02 (PTA2);                                                            // PCB Surface Mounted LED's - LED2
PwmOut LED03 (PTC2);                                                            // PCB Surface Mounted LED's - LED3
PwmOut LED04 (PTC3);                                                            // PCB Surface Mounted LED's - LED4
PwmOut LED05 (PTC4);                                                            // PCB Surface Mounted LED's - LED5
PwmOut LED06 (PTD3);                                                            // PCB Surface Mounted LED's - LED6
                                                                                //    
PwmOut Buzzer (PTC10);                                                          // PCB Surface Mounted Piezo Buzzer
                                                                                //
InterruptIn sw2(SW2);                                                           // K64F on-board switches
InterruptIn sw3(SW3);                                                           // K64F on-board switches
InterruptIn ButtonA (PTB9);                                                     // PCB Button - A
InterruptIn ButtonB (PTD0);                                                     // PCB Button - B
InterruptIn ButtonBack (PTB10);                                                 // PCB Button - Back
                                                                                //
volatile int g_ButtonA_flag = 0;                                                // Flag - must be volatile as changes within ISR - g_ prefix makes it easier to distinguish it as global
volatile int g_ButtonB_flag = 0;                                                // Flag - must be volatile as changes within ISR - g_ prefix makes it easier to distinguish it as global
volatile int g_ButtonBack_flag = 0;                                             // Flag - must be volatile as changes within ISR - g_ prefix makes it easier to distinguish it as global
volatile int g_sw2_flag = 0;                                                    // Flag - must be volatile as changes within ISR - g_ prefix makes it easier to distinguish it as global
volatile int g_menu_timer_flag = 0;                                             // Flag - must be volatile as changes within ISR - g_ prefix makes it easier to distinguish it as global
volatile int option = 0;                                                        // Menu option selection based on joystick direction
volatile int g_state = 0;                                                       // 
volatile int g_StartTemp = 0;                                                   // 
volatile float g_TempReading = 0.0f;                                            //
                                                                                //
void error();                                                                   // Error function hangs flashing an LED
void init_serial();                                                             // Setup serial port
void init_K64F();                                                               // Set-up the on-board LEDs and switches
void init_PCB();                                                                // Set-up the PCB LEDs and buttons
void ButtonA_isr();                                                             // Set-up Button A Interrupt
void ButtonB_isr();                                                             // Set-up Button B Interrupt
void ButtonBack_isr();                                                          // Set-up Button Back Interrupt
void sw2_isr();                                                                 // Set-up Switch 2 Interrupt
void menu_timer_isr();                                                          // Set-up menu timer
void OnStartup();                                                               // Set up function to run Welcom Screens
void Run();                                                                     // Set up function to run main programme
void StartTemp();                                                               // Set up function to run and control temperature selection
void delete_file(char filename[]);                                              // Set up function to delete files saved fromovernight temperature readings
void HighTemp();                                                                // Set up function that gives warning of temperature 2 to 4 degrees over starting temp
void SuperHighTemp();                                                           // Set up function that gives warning of temperature 4 to 6 degrees over starting temp
void UltraHighTemp();                                                           // Set up function that gives warning of temperature >= 6 degrees over starting temp
void LowTemp();                                                                 // Set up function that gives warning of temperature 2 to 4 degrees below starting temp
void SuperLowTemp();                                                            // Set up function that gives warning of temperature 4 to 6 degrees below starting temp
void UltraLowTemp();                                                            // Set up function that gives warning of temperature <= 6 degrees below starting temp
void PeripheralsOffHigh();                                                      // Set up function that turn off all Low Temp warnings
void PeripheralsOffLow();                                                       // Set up function that turn off all Low Temp warnings
                                                                                // 
int main()                                                                      //
{                                                                               //
    init_K64F();                                                                // Initialise the board
    init_serial();                                                              // initialise the serial port
    init_PCB();                                                                 // Initialise the PCB
                                                                                //
    tmp102.init();                                                              // Call the sensor init method using dot syntax
    lcd.init();                                                                 // Initialise display
    joystick.init();                                                            // Initialise joystick
                                                                                //        
    ticker_menu.attach(&menu_timer_isr,0.2);                                    // Attach ticker for the Joystick
                                                                                //
    sw2.fall(&sw2_isr);                                                         // SW2 has a pull-up resistor, so the pin will be at 3.3 V by default and fall to 0 V when pressed. We therefore need to look for a falling edge on the pin to fire the interrupt
    ButtonA.rise(&ButtonA_isr);                                                 // External push button, pin set to 0V by pull down command, means a rising edge is looked for
    ButtonB.rise(&ButtonB_isr);                                                 // External push button, pin set to 0V by pull down command, means a rising edge is looked for
                                                                                //
    lcd.setContrast(0.5);                                                       // change set contrast in range 0.0 to 1.0
                                                                                //
    OnStartup();                                                                // Call intro screen   
    Run();                                                                      // Call main-menu and functions
}                                                                               //
                                                                                //
void init_serial() {                                                            //
    pc.baud(115200);                                                            // set to highest baud - ensure terminal software matches
}                                                                               //        
                                                                                //
void init_K64F()                                                                //
{                                                                               // 
    r_led = 1;                                                                  // on-board LEDs are active-low, so set pin high to turn them off.
    g_led = 1;                                                                  // on-board LEDs are active-low, so set pin high to turn them off.
    b_led = 1;                                                                  // on-board LEDs are active-low, so set pin high to turn them off.
                                                                                //
    sw2.mode(PullNone);                                                         // since the on-board switches have external pull-ups, we should disable the internal pull-down
    sw3.mode(PullNone);                                                         // resistors that are enabled by default using InterruptIn
}                                                                               //
                                                                                //
void init_PCB ()                                                                //        
{                                                                               //        
    LED01 = 1;                                                                  // PCB surface mounted LED's are active low - write a 1 to turn them off initiallly
    LED02 = 1;                                                                  // PCB surface mounted LED's are active low - write a 1 to turn them off initiallly
    LED03 = 1;                                                                  // PCB surface mounted LED's are active low - write a 1 to turn them off initiallly
    LED04 = 1;                                                                  // PCB surface mounted LED's are active low - write a 1 to turn them off initiallly    
    LED05 = 1;                                                                  // PCB surface mounted LED's are active low - write a 1 to turn them off initiallly
    LED06 = 1;                                                                  // PCB surface mounted LED's are active low - write a 1 to turn them off initiallly    
                                                                                //
    Buzzer = 0;                                                                 // Ensure Piezo Buzzer is off
                                                                                //
    ButtonA.mode(PullDown);                                                     // Set pin to Pull Down to OV, meaning that a rising edge is looked for when button is pressed
    ButtonB.mode(PullDown);                                                     // Set pin to Pull Down to OV, meaning that a rising edge is looked for when button is pressed
}                                                                               //        
                                                                                //
void ButtonA_isr()                                                              // ButtonA event-triggered interrupt
{                                                                               //
    g_ButtonA_flag = 1;                                                         // set flag in ISR
}                                                                               //        
                                                                                //
void ButtonB_isr()                                                              // ButtonB event-triggered interrupt
{                                                                               //
    g_ButtonB_flag = 1;                                                         // set flag in ISR
}                                                                               //
                                                                                //
void ButtonBack_isr()                                                           // ButtonB event-triggered interrupt
{                                                                               //
    g_ButtonBack_flag = 1;                                                      // set flag in ISR
}                                                                               //
                                                                                //
void sw2_isr()                                                                  // SW2 event-triggered interrupt
{                                                                               //
    g_sw2_flag = 1;                                                             // set flag in ISR
}                                                                               //
                                                                                //    
void menu_timer_isr()                                                           //
{                                                                               //
    g_menu_timer_flag = 1;                                                      // set flag in ISR
}                                                                               //
                                                                                //        
void OnStartup()                                                                // Run some start up display 
{                                                                               //
    Buzzer.period(1.0/659.0);                                                   // Welcome sounds from Piezo buzzer
    Buzzer = 0.5;                                                               //                   
    wait(0.5);                                                                  // 
    Buzzer.period(1.0/494.0);                                                   // Welcome sounds from Piezo buzzer
    Buzzer = 0.5;                                                               //    
    wait(0.5);                                                                  // 
    Buzzer.period(1.0/554.0);                                                   // Welcome sounds from Piezo buzzer
    Buzzer = 0.5;                                                               // 
    wait(0.5);                                                                  // 
    Buzzer = 0;                                                                 // Turn off welcome sounds 
    lcd.clear();                                                                // Clear buffer at start of every loop
    lcd.printString("--------------",0,0);                                      // Can directly print strings at specified co-ordinates (must be less than 84 pixels to fit on display)
    lcd.printString("  Smart Cold",0,1);                                        // Just a welcome message before auto moving to main menu
    lcd.printString("   Storage",0,2);                                          //
    lcd.printString("  Monitoring",0,3);                                        // 
    lcd.printString("V19 - Jan 2022",0,4);                                      //
    lcd.printString("--------------",0,5);                                      //
    lcd.refresh();                                                              // Need to refresh display after setting pixels or writing strings 
    wait(5.0);                                                                  // Leave welcome screen on for designated amount of time
    lcd.clear();                                                                // Clear buffer at start of every loop
    lcd.refresh();                                                              // Need to refresh display after setting pixels or writing strings 
    lcd.printString("--------------",0,0);                                      //
    lcd.printString(" Use Joystick",0,1);                                       // Instruction for use of menu
    lcd.printString(" To Navigate",0,2);                                        //
    lcd.printString("",0,3);                                                    // Blank Line
    lcd.printString("  A = Select",0,4);                                        //
    lcd.printString("--------------",0,5);                                      //
    lcd.refresh();                                                              // Need to refresh display after setting pixels or writing strings
    wait(5.0);                                                                  //
    init_PCB();                                                                 // Ran again to ensure all LED's etc are turned off
    printf("Transition to Temp Selection %i\n",StartTemp);                      // Observe on serial port - ensure transition to correct screen
}                                                                               //
                                                                                //
enum EMenuState                                                                 // An enum controlling the current state of the display.
{                                                                               //
    MENUSTATE_StartTemp,                                                        // Defining each menu state to be called upon later (Integer Value of 0)
    MENUSTATE_Main,                                                             // Defining each menu state to be called upon later (Integer Value of 1)
    MENUSTATE_Monitor,                                                          // Defining each menu state to be called upon later (Integer Value of 2)
    MENUSTATE_OneOff,                                                           // Defining each menu state to be called upon later (Integer Value of 3)
    MENUSTATE_Results,                                                          // Defining each menu state to be called upon later (Integer Value of 4)
    MENUSTATE_About,                                                            // Defining each menu state to be called upon later (Integer Value of 5)
    MENUSTATE_Author,                                                           // Defining each menu state to be called upon later (Integer Value of 6)
                                                                                //    
    MENUSTATTE_Num,                                                             // This is a special enum value that allows us to check and see how many menus we have, +1 of menu integer value
};                                                                              //
                                                                                //
void Run()                                                                      // 
{                                                                               //    
    int MenuState = MENUSTATE_StartTemp;                                        // Ensuring that the first Menu State to be brought up is the Temperature Selection Page 
    int SelectedItem = 0;                                                       // 
    int NumMenuItems = 1;                                                       // 
    int NumFramesInState = 0;                                                   // How many frames have we been in the current menu state.
                                                                                //    
    char buffer[14];                                                            // Each character is 6 pixels wide, screen is 84 pixels (84/6 = 14)
                                                                                //
    FILE *fp = NULL;                                                            // This is our file pointer
                                                                                //
    while(1){                                                                   // Project infinite while loop       
        if (g_menu_timer_flag){                                                 //        
            g_menu_timer_flag = 0;                                              // 
                                                                                //
            bool bAButtonWasPressed = g_ButtonA_flag;                           // Get the value of the input flags and reset them
            bool bBButtonWasPressed = g_ButtonB_flag;                           // Get the value of the input flags and reset them
            g_ButtonA_flag = 0;                                                 // 
            g_ButtonB_flag = 0;                                                 // 
                                                                                //
            lcd.clear();                                                        // Clear buffer at start of every loop
                                                                                //
            int NewMenuState = MENUSTATTE_Num;                                  // The new menu we want to transition to, if any.
                                                                                //
            switch(MenuState)                                                   // Update and Draw whichever menu we're on.
            {                                                                   //
                case MENUSTATE_StartTemp:                                       //
                {                                                               //
                    NumMenuItems = 1;                                           // Details number of items in the menu. We need this to wrap the selection around properly etc.
                    if(SelectedItem >= NumMenuItems)                            // 
                    {                                                           //
                        SelectedItem = 0;                                       // Something has gone wrong, reset selected item.
                    }                                                           //
                    Direction d = joystick.get_direction();                     // Get direction of joystick and set it as 'd'         
                                                                                //    
                    StartTemp();                                                // Run Start Temp function
                                                                                //
                    float g_StartTemp = fsm[g_state].output;                    // Read temperature from FSM and print selection to LCD
                    pc.printf("T = %f C\n",g_StartTemp);                        // Print to serial - allows testing without device attached
                    printf ("Joystick Direction Points = %i\n",d);              //
                    printf ("State selected = %i\n", g_state);                  //
                    int length = sprintf(buffer," T = %.2f C",g_StartTemp);     // Print formatted data to buffer - it is important the format specifier ensures the length will fit in the buffer
                    if (length <= 14){                                          // If string will fit on display (assuming printing at x=0)
                        lcd.printString("- Set Target -",0,0);                  // 
                        lcd.printString("---- Temp ----",0,1);                  // 
                        lcd.printString(buffer,0,3);                            // Display on screen
                        lcd.printString("'A' to Select",0,5);                   //                      
                        lcd.refresh();                                          //
                    }                                                           // need to refresh display after setting pixels or writing strings 
                                                                                //
                    if(bAButtonWasPressed)                                      // If A was pressed then we transition to the selected screen.
                    {                                                           //    
                        if(SelectedItem == 0)                                   // If 0 line is selected, move to detailed menu 
                        {                                                       // Actually 0 line + 1, see circle draw and selection below
                            NewMenuState = MENUSTATE_Main;                      // 
                        }                                                       //
                    }                                                           //
                }                                                               //
                break;                                                          //         
                case MENUSTATE_Main:                                            //
                {                                                               //    
                    NumMenuItems = 5;                                           // Details number of items in the menu. We need this to wrap the selection around properly etc.
                    if(SelectedItem >= NumMenuItems)                            // 
                    {                                                           //
                        SelectedItem = 0;                                       // Something has gone wrong, reset selected item.
                    }                                                           // 
                    lcd.printString("---- MENU ----",0,0);                      // Menu title and selectable options Printed to the LCD screen    
                    lcd.printString("M1 - Monitor",0,1);                        // Selectable menu option
                    lcd.printString("M2 - One-off",0,2);                        // Selectable menu option
                    lcd.printString("Results",0,3);                             // Selectable menu option
                    lcd.printString("About",0,4);                               // Selectable menu option
                    lcd.printString("Author",0,5);                              // Selectable menu option
                                                                                // 
                    if(bAButtonWasPressed)                                      // If A was pressed then we transition to the selected screen.
                    {                                                           // 
                        if(SelectedItem == 0)                                   // If 0 line is selected, move to detailed menu 
                        {                                                       // Actually 0 line + 1, see circle draw and selection below
                            NewMenuState = MENUSTATE_Monitor;                   // 
                        }                                                       // 
                        else if(SelectedItem == 1)                              // If 1 line is selected, move to detailed menu 
                        {                                                       // Actually 1 line + 1, see circle draw and selection below
                            NewMenuState = MENUSTATE_OneOff;                    // 
                        }                                                       // 
                        else if(SelectedItem == 2)                              // If 2 line is selected, move to detailed menu 
                        {                                                       // Actually 2 line + 1, see circle draw and selection below
                            NewMenuState = MENUSTATE_Results;                   // 
                        }                                                       //
                        else if(SelectedItem == 3)                              // If 3 line is selected, move to detailed menu 
                        {                                                       // Actually 3 line + 1, see circle draw and selection below
                            NewMenuState = MENUSTATE_About;                     // 
                        }                                                       //        
                        else if(SelectedItem == 4)                              // If 4 line is selected, move to detailed menu 
                        {                                                       // Actually 4 line + 1, see circle draw and selection below
                            NewMenuState = MENUSTATE_Author;                    // 
                        }                                                       //
                    }                                                           //
                }                                                               //
                break;                                                          // 
                case MENUSTATE_Monitor:                                         // Call constant measurement menu following top menu selection
                {                                                               //
                    NumMenuItems = 1;                                           // Detail the number of items in Menu -  need this to wrap the selection around properly etc.
                                                                                //
                    if(SelectedItem >= NumMenuItems)                            // 
                    {                                                           //
                        NewMenuState = MENUSTATE_Main;                          // Something has gone wrong, drop back to the main menu.
                    }                                                           //        
                                                                                //
                    float T = tmp102.get_temperature();                         // read temperature and print to lcd
                    pc.printf("T = %f C\n",T);                                  // Print to serial - allows testing without device attached
                    int length = sprintf(buffer," T = %.2f C",T);               // print formatted data to buffer - it is important the format specifier ensures the length will fit in the buffer
                    if (length <= 14)                                           // if string will fit on display (assuming printing at x=0)
                    lcd.printString("-- Constant --",0,0);                      // 
                    lcd.printString("- Monitoring -",0,1);                      // 
                    lcd.printString(buffer,0,3);                                // display on screen
                    lcd.printString(" 'A' to Menu",0,5);                        // 
                    lcd.refresh();                                              // need to refresh display after setting pixels or writing strings 
                    wait(0.5);                                                  // 
                                                                                //
                    if (T >= g_StartTemp + 2 and T < g_StartTemp + 4) {         // High temp alarm condition - in real world would be lot lower!!
                        HighTemp();                                             // Run High temp function if temperture is 2 to 4 degrees over selected start temp 
                    }                                                           //
                    else  {                                                     //
                        PeripheralsOffHigh();                                   // Run function to turn off all high temp peripherals
                    }                                                           //
                    if (T >= g_StartTemp + 4 and T < g_StartTemp + 6) {         // Super High temp alarm condition - in real world would be lot lower!!
                        SuperHighTemp();                                        // Run Super High temp function if temperture is 4 to 6 degrees over selected start temp  
                    }                                                           //
                    else  {                                                     // 
                        PeripheralsOffHigh();                                   // Run function to turn off all high temp peripherals
                    }                                                           // 
                    if (T >= g_StartTemp + 6) {                                 // Ultra High temp alarm condition - in real world would be lot lower!!
                        UltraHighTemp();                                        // Run Ultra High temp function if temperture is 6 degrees or more over selected start temp  
                    }                                                           // 
                    else  {                                                     //
                        PeripheralsOffHigh();                                   // Run function to turn off all high temp peripherals
                    }                                                           //
                    if (T <= g_StartTemp - 2 and T > g_StartTemp - 4) {         // Low temp alarm condition - in real world would be lot lower!!
                        LowTemp();                                              // Run Low Temp function if temperture is 2 to 4 degrees below selected start temp
                    }                                                           //
                    else  {                                                     //    
                        PeripheralsOffLow();                                    // Run function to turn off all low temp peripherals            
                    }                                                           // 
                    if (T <= g_StartTemp - 4 and T > g_StartTemp - 6) {         // Super low temp alarm condition - in real world would be lot lower!!
                        SuperLowTemp();                                         // Run Super Low Temp function if temperture is 2 to 4 degrees below selected start temp
                    }                                                           //
                    else  {                                                     //    
                        PeripheralsOffLow();                                    // Run function to turn off all low temp peripherals            
                    }                                                           // 
                    if (T <= g_StartTemp - 6) {                                 // Ultra low temp alarm condition - in real world would be lot lower!!
                        UltraLowTemp();                                         // Run Ultra Low Temp function if temperture is 2 to 4 degrees below selected start temp
                    }                                                           //
                    else  {                                                     //    
                        PeripheralsOffLow();                                    // Run function to turn off all low temp peripherals            
                    }   
                    if(bAButtonWasPressed)                                      // Check if button was pressed
                    {                                                           //
                        if(SelectedItem == 0)                                   // 
                        {                                                       //
                            NewMenuState = MENUSTATE_Main;                      // Transition back to the main menu
                            PeripheralsOffHigh();                               // 
                            PeripheralsOffLow();                                //
                        }                                                       //
                    }                                                           //
                }                                                               //
                break;                                                          //
                case MENUSTATE_OneOff:                                          // Call a one off measurement menu following top menu selection
                {                                                               //
                    NumMenuItems = 1;                                           // Detail the number of items in Menu -  need this to wrap the selection around properly etc.
                    if(SelectedItem >= NumMenuItems)                            // 
                    {                                                           //
                        NewMenuState = MENUSTATE_Main;                          // Something has gone wrong, drop back to the main menu.
                    }                                                           //
                                                                                //        
                    if(NumFramesInState == 0)                                   //
                    {                                                           //
                        g_TempReading = tmp102.get_temperature();               // Gather the temp readings only on the frame we enter this state and keep printing this same temp, not to refresh and read new temp.
                    }                                                           //
                                                                                //
                    pc.printf("T = %f C\n",g_TempReading);                      // Print to serial - allows testing without device attached
                    int length = sprintf(buffer," T = %.2f C",g_TempReading);   // print formatted data to buffer - it is important the format specifier ensures the length will fit in the buffer
                    if (length <= 14){                                          // if string will fit on display (assuming printing at x=0)
                        lcd.printString("-- One-Off --",0,0);                   // 
                        lcd.printString("-- Measure --",0,1);                   // 
                        lcd.printString(buffer,0,3);                            // display on screen
                        lcd.printString(" 'A' to Menu",0,5);                    // 
                    }                                                           //
                                                                                //
                    if(bAButtonWasPressed)                                      // Check if button was pressed
                    {                                                           //
                        if(SelectedItem == 0)                                   // 
                        {                                                       //
                            NewMenuState = MENUSTATE_Main;                      // Take us back to top menu
                        }                                                       //
                    }                                                           //                                                                         
                }                                                               //
                break;                                                          //
                case MENUSTATE_Results:                                         // Call results menu following top menu selection
                {                                                               //
                    NumMenuItems = 1;                                           // Detail the number of items in Menu -  need this to wrap the selection around properly etc.
                    if(SelectedItem >= NumMenuItems)                            // 
                    {                                                           //
                        NewMenuState = MENUSTATE_Main;                          // Something has gone wrong, drop back to the main menu.
                    }                                                           //
                                                                                //
                    if(NumFramesInState == 0)                                   // 
                    {                                                           //
                        if(fp != NULL){                                         //        
                            printf("Error! File already open!\n");              //
                            fclose(fp);                                         //
                        }                                                       //
                                                                                //
                        fp = fopen("/sd/overnighttemp.csv", "w");               // Open our file handle on the first frame.  
                    }                                                           //                                    
                                                                                //
                    if (fp == NULL) {                                           // if it can't open the file then print error message
                        printf("Error! Unable to open file! Returning to main menu.\n");  //                        
                        NewMenuState = MENUSTATE_Main;                          // Something has gone wrong, drop back to the main menu.
                    }                                                           //
                    else                                                        //
                    {                                                           //
                        float T = tmp102.get_temperature();                     // Read temperature and print to lcd
                        pc.printf("T = %f C\n",T);                              // Print to serial - allows testing without device attached
                        fprintf(fp, "%d,%f\n",NumFramesInState,T);              // Print formatted string to file (CSV)
                                                                                //
                        lcd.printString("-- Results --",0,0);                   // Menu Title
                        lcd.printString(" Writing",0,1);                        // Instructions showing what the function is doing - displayed on screen
                        lcd.printString(" results to ",0,2);                    // Instructions showing what the function is doing - displayed on screen
                        lcd.printString(" file...",0,3);                        // Instructions showing what the function is doing - displayed on screen
                        lcd.printString(" ",0,4);                               // Blank Line
                        lcd.printString(" 'A' to Menu",0,5);                    // Instructions to return to main
                    }                                                           //
                                                                                //
                    if(bAButtonWasPressed)                                      // Check if button was pressed
                    {                                                           //            
                        if(SelectedItem == 0)                                   // 
                        {                                                       //
                            NewMenuState = MENUSTATE_Main;                      // Take us back to top menu 
                        }                                                       //
                    }                                                           //
                }                                                               //
                break;                                                          //
                case MENUSTATE_About:                                           // Call About menu following top menu selection
                {                                                               //
                    NumMenuItems = 1;                                           // Detail the number of items in Menu -  need this to wrap the selection around properly etc.
                    if(SelectedItem >= NumMenuItems)                            // 
                    {                                                           //
                        NewMenuState = MENUSTATE_Main;                          // Something has gone wrong, drop back to the main menu.
                    }                                                           //  
                                                                                //    
                    lcd.printString("--- About ---",0,0);                       // Menu Title
                    lcd.printString("ELE3006M - IoT",0,1);                      // Data within menu
                    lcd.printString("    Project",0,2);                         // Data within menu
                    lcd.printString("Uni of Lincoln",0,3);                      // Data within menu
                    lcd.printString(" 'A' to Menu",0,5);                        // Instructions to return to Main menu
                    lcd.refresh();                                              // 
                                                                                //
                    if(bAButtonWasPressed)                                      // Check if button was pressed
                    {                                                           //
                        if(SelectedItem == 0)                                   // 
                        {                                                       //
                            NewMenuState = MENUSTATE_Main;                      // Transition back to Main Menu
                        }                                                       //
                    }                                                           //    
                }                                                               //    
                break;                                                          //
                case MENUSTATE_Author:                                          // Call Author menu following top menu selection
                {                                                               //
                    NumMenuItems = 1;                                           // Detail the number of items in Menu -  need this to wrap the selection around properly etc.
                    if(SelectedItem >= NumMenuItems)                            // 
                    {                                                           //
                        NewMenuState = MENUSTATE_Main;                          // Something has gone wrong, drop back to the main menu.
                    }                                                           //
                                                                                //
                    lcd.printString("--- Author ---",0,0);                      // Menu Title
                    lcd.printString("David Leaming ",0,1);                      // Data within menu
                    lcd.printString("   25574043 ",0,2);                        // Data within menu
                    lcd.printString("  VolkerRail",0,3);                        // Data within menu
                    lcd.printString(" 'A' to Menu",0,5);                        // Instructions to return to Main menu
                                                                                //
                    if(bAButtonWasPressed)                                      // Check if button was pressed
                    {                                                           //
                        if(SelectedItem == 0)                                   // 
                        {                                                       //
                            NewMenuState = MENUSTATE_Main;                      // Take us back to top menu 
                        }                                                       //    
                    }                                                           // 
                }                                                               //
                break;                                                          //        
                default:                                                        //
                {                                                               //
                    NewMenuState = MENUSTATE_Main;                              // Something has gone wrong, drop back to the main menu.
                }                                                               //
            };                                                                  //
                                                                                //
            if(NewMenuState != MENUSTATTE_Num)                                  // If we have requested a new menu state.
            {                                                                   //
                printf("Transitioning to MenuState: %i\n", NewMenuState);       // Observe on serial port - ensure transition to correct screen
                                                                                //    
                MenuState = NewMenuState;                                       // We want to transition the menu to a new state.
                                                                                //
                                                                                // Do any bookkeeping needed when moving to new state.
                SelectedItem = 0;                                               // Reset the selected item.
                NumFramesInState = 0;                                           // Reset the frames in current state count.
                                                                                //
                if(fp){                                                         //
                    fclose(fp);                                                 // Ensure we close the file if the current state had one open.
                    fp = NULL;                                                  //
                }                                                               //
                lcd.clear();                                                    // Clear the display for one frame on state transition.
            }                                                                   //
            else                                                                //
            {                                                                   //    
                ++NumFramesInState;                                             //            
                                                                                
                unsigned int SelectionMarkerRadius = 4;                                                         // If we have not selected to move to a new menu.
                unsigned int SelectionMarkerX = WIDTH - (2 * SelectionMarkerRadius);                            // Draw a marker circle at end of line to show which is the currently selected item.
                unsigned int SelectionMarkerY = (HEIGHT / 5) * (SelectedItem + 1);                              // +1 because of the menu title being on first row
                lcd.drawCircle(SelectionMarkerX, SelectionMarkerY, SelectionMarkerRadius, FILL_BLACK);          // Fill the circle black so it can be seen easily                                                   
                            
                                                                                // Handle Joystick Input
                Direction d = joystick.get_direction();                         //                                        
                printf("Direction = %i\n", d);                                  //
                switch (joystick.get_direction())  {                            // Call to check direction joystick is pointing                                     
                    case N:                                                     //
                    {                                                           //        
                        SelectedItem--;                                         //  
                        printf("Selection decremented to %i\n", SelectedItem);  // Selection pointer move down
                    }                                                           //
                    break;                                                      //
                    case S:                                                     //
                    {                                                           //
                        SelectedItem++;                                         //    
                        printf("Selection incremented to %i\n", SelectedItem);  // Selection pointer move up
                    }                                                           //
                    break;                                                      //
                }                                                               //
                if(SelectedItem < 0)                                            // Wrap the selection around to the start/end of the menu if it goes below 0 or above NumMenuItems.
                {                                                               //
                    SelectedItem = NumMenuItems - 1;                            // Move to bottom of menu
                }                                                               //
                else if(SelectedItem >= NumMenuItems)                           // 
                {                                                               //
                    SelectedItem = 0;                                           // Move to top of menu
                }                                                               //
            }                                                                   //
            lcd.refresh();                                                      // Finally update the display.
        }                                                                       //    
    }                                                                           //
}                                                                               //
                                                                                //
void StartTemp()                                                                //
{                                                                               //
    Direction d = joystick.get_direction();                                     //
                                                                                //
        g_StartTemp = fsm[g_state].output;                                      // Set ouput depending on current state
        wait(fsm[g_state].time);                                                // Wait in that state for desired time           
        g_state = fsm[g_state].nextState[d];                                    // Read input and update curent state 
}                                                                               //
                                                                                // 
void HighTemp()                                                                 //
{                                                                               // 
    LED01 = 0;                                                                  // LED01 on if temperature is over specified - Simulated starting of cold blowers
    printf("WARNING - High Temp!! \n");                                         //
    Buzzer.period(1.0/554.0);                                                   // Warning Buzzer to extremely high 
    Buzzer = 0.5;                                                               // 
    wait(0.5);                                                                  // 
    Buzzer = 0;                                                                 //
}                                                                               //
                                                                                // 
void SuperHighTemp()                                                            //
{                                                                               // 
    LED01 = 0;                                                                  // LED01 on if temperature is over specified - Simulated starting of cold blowers
    LED02 = 0;                                                                  // LED02 on if temperature is over specified - Simulated starting of cold blowers
    printf("WARNING - Super High Temp!! \n");                                   //
    Buzzer.period(1.0/554.0);                                                   // Warning Buzzer to extremely high 
    Buzzer = 0.5;                                                               // 
    wait(0.5);                                                                  // 
    Buzzer = 0;                                                                 //
}                                                                               //
                                                                                // 
void UltraHighTemp()                                                            //
{                                                                               // 
    LED01 = 0;                                                                  // LED01 on if temperature is over specified - Simulated starting of cold blowers
    LED02 = 0;                                                                  // LED02 on if temperature is over specified - Simulated starting of cold blowers
    LED03 = 0;                                                                  // LED02 on if temperature is over specified - Simulated starting of cold blowers
    printf("WARNING - Ultra High Temp!! \n");                                   //
    Buzzer.period(1.0/554.0);                                                   // Warning Buzzer to extremely high 
    Buzzer = 0.5;                                                               // 
    wait(0.5);                                                                  // 
    Buzzer = 0;                                                                 //
}                                                                               //
                                                                                //
void LowTemp()                                                                  //
{                                                                               //
    LED04 = 0;                                                                  // LED04 on if temperature is over specified - Simulated starting of heaters
    printf("WARNING - Low Temp!! \n");                                          //
    Buzzer.period(1.0/554.0);                                                   // Warning Buzzer to extremely low
    wait(0.5);                                                                  // 
    Buzzer = 0;                                                                 //
}                                                                               //
                                                                                //                                                                                                                                           //
void SuperLowTemp()                                                             //
{                                                                               //
    LED04 = 0;                                                                  // LED04 on if temperature is over specified - Simulated starting of heaters
    LED05 = 0;                                                                  // LED05 on if temperature is over specified - Simulated starting of heaters
    printf("WARNING - Super Low Temp!! \n");                                    //
    Buzzer.period(1.0/554.0);                                                   // Warning Buzzer to extremely low
    wait(0.5);                                                                  // 
    Buzzer = 0;                                                                 //
}                                                                               //
                                                                                //
void UltraLowTemp()                                                             //
{                                                                               //
    LED04 = 0;                                                                  // LED04 on if temperature is over specified - Simulated starting of heaters
    LED05 = 0;                                                                  // LED05 on if temperature is over specified - Simulated starting of heaters
    LED06 = 0;                                                                  // LED06 on if temperature is over specified - Simulated starting of heaters
    printf("WARNING - Ultra Low Temp!! \n");                                    //
    Buzzer.period(1.0/554.0);                                                   // Warning Buzzer to extremely low
    wait(0.5);                                                                  // 
    Buzzer = 0;                                                                 //
}                                                                               //
                                                                                // 
void PeripheralsOffHigh()                                                       //
{                                                                               // 
    LED01 = 1;                                                                  // LED01 off if temperature is below specified - Simulated stopping of cold blowers
    LED02 = 1;                                                                  // LED02 off if temperature is below specified - Simulated stopping of cold blowers
    LED03 = 1;                                                                  // LED03 off if temperature is below specified - Simulated stopping of cold blowers
    Buzzer = 0;                                                                 // Buzzer off if temperature is below specified - Simulated stopping of cold blowers
    printf("All High Temp Peripherals = OFF \n");                               // 
}                                                                               // 
                                                                                // 
void PeripheralsOffLow()                                                        // 
{                                                                               //
    LED04 = 1;                                                                  // LED04 off if temperature is below specified - Simulated stopping of heaters
    LED05 = 1;                                                                  // LED05 off if temperature is below specified - Simulated stopping of heaters
    LED06 = 1;                                                                  // LED06 off if temperature is below specified - Simulated stopping of heaters
    Buzzer = 0;                                                                 // Buzzer off if temperature is below specified - Simulated stopping of heaters
    printf("All LOW Temp Peripherals = OFF \n");                                // 
}                                                                               //