Updated following fixing of Joystick 'Bounce'. Also insertion of a Starting Temp to be compared against following user selection.

Dependencies:   mbed N5110v02 TMP102 JoystickIoT

main.cpp

Committer:
legstar85
Date:
2022-01-16
Revision:
8:07323fcab6d1
Parent:
7:d77e95505e43
Child:
9:d71b92c916f8

File content as of revision 8:07323fcab6d1:

/* 
* @ File main.cpp
* @ Author - David Leaming - 25574043
* @ Date - December 2021
*
* Acknowledgements 
* Craig A. Evans, University of Leeds, TMP102 Library ,Feb 2016
* Dr Edmond Nurellari, University of Lincoln, Joystick & N5110 Libraries
*
*/ 

#include "mbed.h"                                                               // include the library header, ensure the library has been imported into the project
#include "TMP102.h"
#include "N5110.h"
#include "Joystick.h"
#include "Bitmap.h"

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 

Serial pc(USBTX,USBRX);                                                         // UART connection for PC

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

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();                                                             //
void ButtonB_isr();                                                             //
void ButtonBack_isr();                                                          //
void sw2_isr();                                                                 //
void menu_timer_isr();                                                          //
void OnStartup();                                                               // 
void Run();                                                                     // 
void ConstantMonitoring();                                                      //   

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();                                                                //    
    Run();                                                                      //
     
}      

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;                                     
    LED03 = 1;
    LED04 = 1;
    LED05 = 1;
    LED06 = 1;
    
    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 
{
    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("V09 - 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);                                                                  //
}

enum EMenuState                                                                 //An enum controlling the current state of the display.
{
    MENUSTATE_Main,
    MENUSTATE_Monitor,
    MENUSTATE_OneOff,
    MENUSTATE_About,
    MENUSTATE_Author,
    
    MENUSTATTE_Num,                                                             // This is a special enum value that just gives is a way to get the number of elements in the enum.
};

void Run()
{
    int MenuState;    
    int SelectedItem = 0;
    int NumMenuItems = 1;
    
    char buffer[14];                                                            // each character is 6 pixels wide, screen is 84 pixels (84/6 = 14)
    
    while(1){
        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;           
            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_Main:
                {

                    NumMenuItems = 4;                                           // Dont for get to set this when changing 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);
                    lcd.printString("M1 - Monitor",0,1);
                    lcd.printString("M2 - One-off",0,2);
                    lcd.printString("About",0,3);
                    lcd.printString("Author",0,4);
                    
                    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_About;
                        }
                        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_Author;
                        }
                    }
                }
                break;      
                case MENUSTATE_Monitor:
                {

                    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
                    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);
                    
                    float high_temp = tmp102.get_temperature();                 // read temperature   
                    if (high_temp >= 22) {                                      // High temp alarm condition - in real world would be lot lower!!
                        LED01 = 0;                                              // Light LED01 if temperature is over specified
                        LED02 = 0;                                              // Light LED02 if temperature is over specified
                        LED03 = 0;                                              // Light LED03 if temperature is over specified
                    } 
                    else {
                        LED01 = 1;                                              // LED01 off if temperature is below specified
                        LED02 = 1;                                              // LED01 off if temperature is below specified
                        LED03 = 1;                                              // LED01 off if temperature is below specified
                    } 
                                  
                    if(bAButtonWasPressed)
                    {
                        if(SelectedItem == 0)
                        {
                            NewMenuState = MENUSTATE_Main;
                        }
                    }
                }
                break;      
                case MENUSTATE_OneOff:
                {

                    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
                    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("-- 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)
                    {
                        if(SelectedItem == 0)
                        {
                            NewMenuState = MENUSTATE_Main;                      // Take us back to top menu
                        }
                    }                   
                    
                }
                break;      
                case MENUSTATE_About:
                {

                    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);
                    lcd.printString("ELE3006M - IoT",0,1);
                    lcd.printString("    Project",0,2);
                    lcd.printString("Uni of Lincoln",0,3);
                    lcd.printString(" 'A' to Menu",0,5); 
                    lcd.refresh();                       
                                        
                    if(bAButtonWasPressed)
                    {
                        if(SelectedItem == 0)
                        {
                            NewMenuState = MENUSTATE_Main;
                        }
                    }
                }
                break;
                case MENUSTATE_Author:
                {

                    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);
                    lcd.printString("David Leaming ",0,1);
                    lcd.printString("   25574043 ",0,2);
                    lcd.printString("  VolkerRail",0,3);
                    lcd.printString(" 'A' to Menu",0,5);                    
                                        
                    if(bAButtonWasPressed)
                    {
                        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.   
                
                lcd.clear();                                                    // Clear the display for one frame on state transition.
            }                                                                   // Could do something else like invert colour etc here.
            else
            {
                
                                                                                                            // If we have not selected to move to a new menu.
            unsigned int SelectionMarkerRadius = 4       ;                                                  // Draw a marker circle at end of line to show which is the currently selected item.
            unsigned int SelectionMarkerX = WIDTH - (2 * SelectionMarkerRadius);
            unsigned int SelectionMarkerY = (HEIGHT / 5) * (SelectedItem + 1);                              // +1 because of the menu title being on first row
            lcd.drawCircle(SelectionMarkerX, SelectionMarkerY, SelectionMarkerRadius, FILL_BLACK);                                                             
                            
                                                                                // Handle Joystick Input
                switch (joystick.get_direction())  {                            // Call to check direction joystick is pointing
                        printf("Direction = %i\n");                             //
                    case N:                                                     //
                    SelectedItem--;                                             //
                    break;                                                      //
                    case S:                                                     //
                    SelectedItem++;                                             //
                    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;
                }
                else if(SelectedItem >= NumMenuItems)
                {
                    SelectedItem = 0;
                }
            }
            
            lcd.refresh();                                                      //Finally update the display.
        }
    }       
}