Copy_Assignment3

Dependencies:   mbed MCP23017 WattBob_TextLCD mbed-rtos

main.cpp

Committer:
aoc2
Date:
2018-03-28
Revision:
1:d980a57e422a
Parent:
0:8940db3353d7

File content as of revision 1:d980a57e422a:

/*******************************************************************************

  filename  ::  main.cpp
  ======================

 Description
    Assignment 3 of the B31DG Embedded Software Course.
    It consists in writing a simple microcontroller based on the MBED RTOS
    library for the LPC1768 board. The repetitive tasks have been implemented
    by using RTOS Timers, 4 to be specific. One for the car simulator, one
    launching tasks whose frequency is either 5 Hz or 10 Hz, one launching
    tasks whose frequency is either 2 Hz, 1 Hz or 0.5 Hz and the last one
    is launching tasks running at a frequency of 0.2 Hz and 0.5Hz.

 Version
    Antoine    V1.3    February 2018

 History
    v1.2        Wrote documentation     
    v1.1        Added timers calling tasks multiple of their execution frequency
    v1.0        First Complete Version (all tasks done and 11 Timers)
    ...
    v0.2        Build main structure of program
    v0.1        Initial Version
    ........................................................................

 Detailed Description
    11 tasks were to be performed:
        - SIMULATOR - 20 Hz
            Write a simple car simulator which will compute the car speed based
            on the values of the accelerator (%), the brake (%) and the state
            of the engine.
        - TASK 1    - 10 Hz
            Read the value of 2 analog inputs which correspond to the values of
            acceleration and brake.
        - TASK 2    - 2 Hz
            Read a digital input switch corresponding to the state of the engine
        - TASK 3    - 5 Hz
            Filter the speed with an averaging filter.
        - TASK 4    - 2 Hz
            Show the use of a brake with a digital output
        - TASK 5    - 1 Hz
            Monitor the speed, and if it goes above a given threshold, switch on
            a digital output
        - TASK 6    - 2 Hz
            Display on the screen travelled distance & the last average speed
        - TASK 7    - 0.2 Hz
            Send into a MAIL queue object the values of speed, accelerometer and
            brake. The queue has a size of 100.
        - TASK 8    - 0.05 Hz
            Dump the the content of the queue into the serial port.
        - TASK 9    - 1 Hz
            Read a digital switch and set a digital output based on its state
        - TASK 10   - 0.5 Hz
            Read two switches and set two LEDs according to their state. They
            blink at 1 Hz if only one of the switch is on, at 2 Hz is they
            are both on.
            
    .........................................................................
    
 Personnal Values           None
    ..............................

 Method
    I decided not to use global variables between the different functions called
    by the RTOS timer as a challenge and because it is not safe to use global
    variables in most of the case because you lose control on the origin of
    a modification on them.
    Hence, I declared a structure which is used by the different tasks and
    contains pointers to every variables, structures or object needed.
    To make it work, I had to slightly modify the RTOSTimer library and remove
    the 'const' keyword protecting the given pointer to function calls.
 
    The functions used by for the different task execution are located in the
    included files "my_tasks" while "my_tools" contains functions called by the 
    tasks in order to simplify their code.
    
    The header "my_stucture" contains 3 small structures:
        - engineRAWValues which stores the RAW values of the car
        - carStatistics which stores values about speed and distance
        - mailStruct which is the structure required by the mail Queue object    

    ..........................................................................



*******************************************************************************/


#include "mbed.h"
#include "rtos.h"
#include "my_tools.h"
#include "my_structures.h"
#include "my_tasks.h"

#define     BACK_LIGHT_ON(INTERFACE)    INTERFACE->write_bit(ON,BL_BIT)
#define     BACK_LIGHT_OFF(INTERFACE)   INTERFACE->write_bit(OFF,BL_BIT)

/*******************************************************************************
 *                            PIN DECLARATION
 ******************************************************************************/
#define     ANALOG_INPUT_1              p20
#define     ANALOG_INPUT_2              p18

#define     DIGITAL_IN_ENGINE           p15
#define     DIGITAL_IN_SIDE             p16
#define     DIGITAL_IN_LEFT             p11
#define     DIGITAL_IN_RIGHT            p14

#define     DIGITAL_OUT_OVERSPEED       p26
#define     DIGITAL_OUT_BRAKE           p25

using namespace std;

// ===============
//  System Inputs 
// ===============
AnalogIn    ACCELERATOR(ANALOG_INPUT_1);
AnalogIn    BRAKE(ANALOG_INPUT_2);
DigitalIn   ENGINE_SWITCH(DIGITAL_IN_ENGINE);
DigitalIn   SIDE_LIGHT_SWITCH(DIGITAL_IN_SIDE);
DigitalIn   LEFT_SWITCH(DIGITAL_IN_LEFT);
DigitalIn   RIGHT_SWITCH(DIGITAL_IN_RIGHT);

// ================
//  System Outputs
// ================
DigitalOut  SIDE_LIGHT_INDICATOR(LED1);
PwmOut      LEFT_LIGHT(LED2);
PwmOut      RIGHT_LIGHT(LED3);
DigitalOut  ENGINE_LIGHT(LED4);
DigitalOut  OVERSPEED_LIGHT(DIGITAL_OUT_OVERSPEED);
DigitalOut  BRAKE_LIGHT(DIGITAL_OUT_BRAKE);

/*******************************************************************************
 *                          FUNCTION PROTOTYPES
 ******************************************************************************/

/** Initialize the main structure used in the program
 *
 *  @param: Set a arguments used to initalize the structure, all pointers
 */
void initializeStructure(carStructure           &car, 
                         engineRAWValues        *rawValues,
                         carStatistics          *carStat,
                         Mail<mailStruct,100>   *mailQueue,
                         Mutex                  *rawMutex, 
                         Mutex                  *speedMutex,
                         Mutex                  *mailMutex,
                         MCP23017               *par_port,
                         WattBob_TextLCD        *lcd,
                         Serial                 *pcSerial
                        );

/*******************************************************************************
 *                              MAIN FUNCTION
 ******************************************************************************/
int main()
{
    /****************************
     *       MAIN SETUP
     ****************************/
    // ---------------------------------------------------------------------- //
    // Screen Variables
    MCP23017            *par_port;
    WattBob_TextLCD     *lcd;
    par_port = new MCP23017(p9, p10, 0x40);     // initialise 16-bit I/O chip
    lcd      = new WattBob_TextLCD(par_port);   // initialise 2*26 char display
    
    // Turn LCD backlight ON
    par_port->write_bit(ON,BL_BIT);
    
    // Init Message on Screen
    lcd->cls();
    lcd->locate(0,0);
    lcd->printf("Init...");
    wait(0.5);
    
    
    // ---------------------------------------------------------------------- //
    // USB Connection to PC
    Serial PCSerial(USBTX,USBRX);
    // Increase Baud Rate of Serial Connection
    PCSerial.baud(115200);
    
    /****************************
     *   DECLARE STRUCTURES
     ****************************/ 
    // ---------------------------------------------------------------------- //
    // ENGINE RAW VALUES   
    Mutex           rawMutex;
    engineRAWValues rawValues;
    initRAWValuesStruct(rawValues);
    // ---------------------------------------------------------------------- //
    // CAR STATISTICS VALUES
    vector<float>   speedVec(SIZE_SPEED_VECTOR);
    Mutex           speedMutex;
    carStatistics   carStats;
    initCarStatisticsStruct(carStats, &speedVec);

    // ---------------------------------------------------------------------- //
    // MAIL QUEUE STRUCTURE
    Mail<mailStruct,100> mailQueue;
    Mutex                mailMutex;
    
    // ---------------------------------------------------------------------- //
    // Declare structure to be used by the different task functions
    carStructure myCar;
    initializeStructure(myCar, 
                        &rawValues, &carStats, 
                        &mailQueue,
                        &rawMutex, &speedMutex, &mailMutex,
                        par_port, lcd,
                        &PCSerial
                       );

    // ---------------------------------------------------------------------- //
    // ---------------------------------------------------------------------- //
    /****************************
     *   DECLARE RTOS TIMER
     ****************************/
    RtosTimer carSimulator(task0_carSim,    osTimerPeriodic, (void *) &myCar);
    RtosTimer timer_1(timer1, osTimerPeriodic, (void *) &myCar);
    RtosTimer timer_2(timer2, osTimerPeriodic, (void *) &myCar);
    RtosTimer timer_3(timer3, osTimerPeriodic, (void *) &myCar);
    

    /****************************
    *     START RTOS TIMER
    ****************************/
    carSimulator.start(50); // 20Hz
    timer_1.start(100);     // 10 Hz
    timer_2.start(500);     // 2 Hz
    timer_3.start(5000);    // 0.2 Hz
    
    // RtosTimer will run forever
    Thread::wait(osWaitForever);

    return 0;
}


void initializeStructure(carStructure           &car, 
                         engineRAWValues        *rawValues,
                         carStatistics          *carStat,
                         Mail<mailStruct,100>   *mailQueue,
                         Mutex                  *rawMutex, 
                         Mutex                  *speedMutex,
                         Mutex                  *mailMutex,
                         MCP23017               *par_port,
                         WattBob_TextLCD        *lcd,
                         Serial                 *pcSerial
                        )
{
    //  System Inputs 
    car.p_accelerator         = &ACCELERATOR ;
    car.p_brake               = &BRAKE ;
    car.p_engineSwitch        = &ENGINE_SWITCH ;
    car.p_sideLightSwitch     = &SIDE_LIGHT_SWITCH ;
    car.p_leftSwitch          = &LEFT_SWITCH ;
    car.p_rightSwitch         = &RIGHT_SWITCH ;
    
    //  System Outputs
    car.p_sideLightIndicator  = &SIDE_LIGHT_INDICATOR ;
    car.p_leftLight           = &LEFT_LIGHT ;
    car.p_rightLight          = &RIGHT_LIGHT ;
    car.p_engineLight         = &ENGINE_LIGHT ;
    car.p_overspeedLight      = &OVERSPEED_LIGHT ;
    car.p_brakeLight          = &BRAKE_LIGHT ;
    
    // Values Structure;
    car.p_rawValues          = rawValues;
    car.p_carStats           = carStat;
    car.p_mailQueue          = mailQueue;
    car.nbElementInQueue     = 0;
    
    // Mutex
    car.p_rawMutex           = rawMutex;
    car.p_statMutex          = speedMutex;
    car.p_mailMutex          = mailMutex;
    
    // Serial Connection
    car.p_PC                 = pcSerial;
    
    // Screen variables
    car.p_par_port           = par_port;
    car.p_lcd                = lcd;
}