All the commit done for assignment 3

Dependencies:   MCP23017 Servo WattBob_TextLCD mbed mbed-rtos

Revision:
1:b1b14911f265
Parent:
0:8bcf5bf1bbfb
Child:
2:b9c8c2e5fc90
diff -r 8bcf5bf1bbfb -r b1b14911f265 main.cpp
--- a/main.cpp	Tue Mar 21 13:44:42 2017 +0000
+++ b/main.cpp	Tue Apr 04 16:11:42 2017 +0000
@@ -1,12 +1,380 @@
+/*****************************************************************************************************
+Assigment 3 Embedded Software
+                                                
+                                                 
+This Software is a Car Control Software as no Real Car can be connected it Simulates a car as well.
+For the Display it uses an LCD Screen
+For the Speedometer it uses a Servo
+The Emulation and Synchronisation is implemented using TimerThreads and Semaphores
+for the reason of existing thread limits, conventional timers are helping to slicing timeslots
+
+@author Xavier Gouesnard
+H00258183
+******************************************************************************************************/
 #include "mbed.h"
+#include "MCP23017.h"                                               // include 16-bit parallel I/O header file
+#include "WattBob_TextLCD.h"                                        // include 2*16 character display header file
+#include "rtos.h"
+#include "Servo.h"
+#include <deque>
+
+//#define OS_TIMERCBQS 20 // define a new number of timers we want +1 timer!
+//#define OS_TASKCNT 20 // maximum threads
+
+MCP23017            *par_port;                                      // pointer to 16-bit parallel I/O object
+WattBob_TextLCD     *lcd;                                           // pointer to 2*16 chacater LCD object
+Serial              serpc(USBTX, USBRX);                            // serial usb connection tx, rx
+AnalogIn AinBreak(p15);                                             // Port for the Break Value
+AnalogIn AinAccel(p16);                                             // Port for the Accelerator Value
+DigitalIn DinSwitchEngine(p11);                                     // Port for the Engine Switch
+DigitalIn DinSwitchLight(p12);                                      // Port for the Light Switch
+DigitalIn DinSwitchRindic(p13);                                     // Port for the Right Indicator
+DigitalIn DinSwitchLindic(p14);                                     // Port for the Left Indicator
+Servo Odometer(p26);
+DigitalOut LEDSpeedWarning(p8);
+DigitalOut DoutLEDLight(LED1);                                      // Output Port for LED1
+DigitalOut DoutLEDLeft(LED2);                                       // Output Port for LED2
+DigitalOut DoutLEDRight(LED3);                                      // Output Port for LED3
+DigitalOut DoutLEDEngine(LED4);                                     // Output Port for LED4
+void Timer1_void(void const *args);                                 // Timer 1
+void Timer2_void(void const *args);                                 // Timer 2
+void Timer3_void(void const *args);                                 // Timer 3
+
 
-DigitalOut myled(LED1);
+// Task Functions
+void Task_1_break_accelerate();
+void Task_2_read_show_engine_state();
+void Task_3_show_odometer();
+void Task_4_speed_warning();
+void Task_5_update_odometer();
+void Task_6_fill_mail_queue();
+void Task_7_dump_mail_to_serial();
+void Task_8_read_single_side_light();
+void Task_9_read_indicators();
+void Task_10_calc_avg_speed();
+void Task_11_emulate_car();
+
+// Init Variables
+int Convert_Hz_to_Ms(double Hz);
+float accerlator(0);
+float speed(0);
+float avgSpeed(0);
+float brake(0);
+float dist(0);
+bool engine(0);
+bool indicator_L(1);
+bool indicator_R(1);
+bool sw_timer1(0);
+bool sw_timer11(0);
+bool sw_timer2(0);
+bool sw_timer21(0);
+int sw_timer3(4);                                                   // sw_timer3 initalize with a first run
+
+std::deque<float> AvgSpeedDB;                                       // used for storing the average speed
+Semaphore SemAvgSpeedDB(1);                                         // declare used Semaphores
+Semaphore SemAvgSpeed(1);
+Semaphore SemSpeed(1);
+Semaphore SemBreak_Accelerate(1);
+Semaphore SemDistance(1);
+Semaphore SemEngine(1);
+Semaphore SemMailCnT(1);
+
+typedef struct {
+float    speed;
+float    accel;
+float brake;
+} mail_t;
+int mailcounter(0);                                                 // counts the mails in the queue
+Mail<mail_t, 100> mail_box;                                         // the mail queue has a maximum size of 100 mails
 
-int main() {
-    while(1) {
-        myled = 1;
-        wait(0.2);
-        myled = 0;
-        wait(0.2);
+int main()
+{
+// 10.0 Hz = 00100 ms
+// 2.0  Hz = 00500 ms
+// 5.0  Hz = 00200 ms
+// 1.0  Hz = 01000 ms
+// 0.5  Hz = 02000 ms
+// 0.2  Hz = 05000 ms
+// 0.05 Hz = 20000 ms
+
+
+
+
+    serpc.baud(19200);                                              // setup the bautrate
+    serpc.printf("Init Software\r\n");
+    par_port = new MCP23017(p9, p10, 0x40);                         // initialise 16-bit I/O chip (0x40 = 64)
+    lcd = new WattBob_TextLCD(par_port);                            // initialise 2*26 char display
+    par_port->write_bit(1,BL_BIT);                                  // turn LCD backlight ON
+    lcd->cls();                                                     // clear display
+    lcd->locate(0,0);                                               // set cursor to location (0,0) - top left corner
+    RtosTimer Timer1(Timer1_void,osTimerPeriodic,(void *)NULL);     // create the necesarry timers to overcome a thread issue (max threads)
+    Timer1.start(Convert_Hz_to_Ms(20.0));
+    RtosTimer Timer2(Timer2_void,osTimerPeriodic,(void *)NULL);
+    Timer2.start(Convert_Hz_to_Ms(2.0));
+    RtosTimer Timer3(Timer3_void,osTimerPeriodic,(void *)NULL);
+    Timer3.start(Convert_Hz_to_Ms(0.2));
+Thread::wait(osWaitForever);
+}
+
+/*
+##############################################################
+Timer 1 runs at 10 Hz
+    Task_11_emulate_car();
+    Task_1_break_accelerate();
+    Task_10_calc_avg_speed();
+#############################################################
+*/
+
+void Timer1_void(void const *args)
+{
+Task_11_emulate_car();                                           // runs every time, so at 20 Hz
+    sw_timer1 = !sw_timer1;
+if(sw_timer1) {                                                 // runs just every second time, so at 10 hz
+Task_1_break_accelerate();
+        sw_timer11 = !sw_timer11;
+if(sw_timer11) {                                            // runs just every fourth time, so at 5 hz
+Task_10_calc_avg_speed();
+        }
+    }
+}
+
+/*
+##############################################################
+Timer 2 runs at 2 Hz, but starts tasks at 2 Hz, 1 Hz, 0.5 Hz
+    Task_2_read_show_engine_state();
+    Task_5_update_odometer();
+    Updates Indicators
+    Task_3_show_odometer();
+    Task_8_read_single_side_light();
+    Task_4_speed_warning();
+    Task_9_read_indicators();
+#############################################################
+*/
+
+
+void Timer2_void(void const *args) // timer runs at 2 hz
+{
+    
+Task_2_read_show_engine_state();
+Task_5_update_odometer();
+    sw_timer2 = !sw_timer2;
+    
+if(indicator_L && indicator_R ) {                               // Sets the Left and Right Inidcators
+        DoutLEDLeft=!DoutLEDRight;                              // needs to get the inverted status of led1 before led1 is changed
+        DoutLEDRight=!DoutLEDRight;
+        
+    } else if (!indicator_R && !indicator_L) {
+        DoutLEDLeft=0;
+        DoutLEDRight=0;
+    }
+    
+if(sw_timer2) 
+{                                                               // runs just every second time, so at 1 hz
+Task_3_show_odometer();
+Task_8_read_single_side_light();
+        sw_timer21 = !sw_timer21;
+        
+if (!indicator_R && indicator_L) 
+{                                                               // switch the left / right indicator
+            DoutLEDRight=0;
+            DoutLEDLeft=!DoutLEDLeft;
+        } else if(indicator_R && !indicator_L) {
+            DoutLEDRight=!DoutLEDRight;
+            DoutLEDLeft=0;
+        }
+if(sw_timer21) {                                            // runs just every second time, so at 0.5 hz
+Task_4_speed_warning();
+Task_9_read_indicators();
+        }
     }
 }
+/*
+##############################################################
+Timer 3 runs at 0.2 Hz, but starts tasks at 0.2 Hz and 0.05 Hz
+    Task_6_fill_mail_queue();
+    Task_7_dump_mail_to_serial();
+##############################################################
+*/
+void Timer3_void(void const *args)                                  // timer runs at 0.2 hz
+{
+Task_6_fill_mail_queue();
+if((sw_timer3%4)==0) {                                          // task runs at 0.05 Hz
+Task_7_dump_mail_to_serial();                                // dump the queue to serial
+        sw_timer3=0;                                                // reset the timer
+    }
+    sw_timer3++;
+}
+/*
+Reads the brake / acceleration of the car
+*/
+void Task_1_break_accelerate()
+{
+// Let the Semaphores wait
+    SemBreak_Accelerate.wait();
+    accerlator = AinAccel;                                              // save the accerlator value
+    brake = AinBreak;                                                   // save the brake value
+// Let the Semaphores release
+    SemBreak_Accelerate.release();
+}
+/*
+Reads the Engine On/Off Switch and displays its state
+*/
+void Task_2_read_show_engine_state()
+{
+// Let the Semaphores wait
+    SemEngine.wait();
+    engine = DinSwitchEngine;                                           // read the engine state
+    DoutLEDEngine = engine;                                             // write the engine state
+// Let the Semaphores release
+    SemEngine.release();
+}
+/*
+Updates the Odometer (Servo Motor)
+*/
+void Task_3_show_odometer()
+{
+// Let the Semaphores wait
+    SemAvgSpeed.wait();                                                 
+    Odometer = avgSpeed/250.0;                                          // Calculate the odometer
+// Let the Semaphores release
+    SemAvgSpeed.release();
+}
+/*
+Indicates a Speed warning at 75 Mph
+*/
+void Task_4_speed_warning()
+{
+// Let the Semaphores wait
+    SemAvgSpeed.wait();
+if(avgSpeed>75.0)                                                   // check our speed
+        LEDSpeedWarning = !LEDSpeedWarning;                             // and switch the Warning on/off
+else
+        LEDSpeedWarning = 0;
+// Let the Semaphores release
+    SemAvgSpeed.release();
+}
+/*
+Updates the LCD Display
+*/
+void Task_5_update_odometer()
+{
+// Let the Semaphores wait
+    SemDistance.wait();
+    SemAvgSpeed.wait();
+    lcd->locate(0,0);                                               // set cursor to location (0,0) - top left corner
+    lcd->printf("s: %5.0f",avgSpeed);
+    lcd->locate(1,0);
+    lcd->printf("d: %5.0f",dist);
+// Let the Semaphores release
+    SemDistance.release();
+    SemAvgSpeed.release();
+}
+/*
+Reads the Left and Right Inidcator
+*/
+void Task_6_fill_mail_queue()
+{
+// Let the Semaphores wait
+    SemMailCnT.wait();
+    SemBreak_Accelerate.wait();
+    SemSpeed.wait();
+mail_t *mail = mail_box.alloc();                                            // reserve the space for our new message
+    mail->speed = speed;                                                        // fill with values
+    mail->accel = accerlator;
+    mail->brake = brake;
+    mail_box.put(mail);                                                         // put the new message into the mail queue
+    mailcounter++;
+// Let the Semaphores release
+    SemBreak_Accelerate.release();
+    SemSpeed.release();
+    SemMailCnT.release();
+}
+/*
+Reads the Mail Queue and Sends the Content to the Serial Port
+*/
+void Task_7_dump_mail_to_serial()
+{
+// Let the Semaphores wait
+    SemMailCnT.wait();
+while(mailcounter) {                                                        // as long as we got mail
+        osEvent evt = mail_box.get();                                           // we are getting them
+if (evt.status == osEventMail) {
+mail_t *mail = (mail_t*)evt.value.p;                                // print the mail to serial
+            serpc.printf("\nspeed: %.0f \n\r"   , mail->speed);
+            serpc.printf("accerlator: %.2f\n\r"     , mail->accel);
+            serpc.printf("brake: %.2f\n\r", mail->brake);
+            mail_box.free(mail);                                                // clear up the mailbox
+        }
+        mailcounter--;
+    }
+// Release the Semaphores
+    SemMailCnT.release();
+}
+/*
+Single Side Light
+*/
+void Task_8_read_single_side_light()
+{
+    DoutLEDLight = DinSwitchLight;                                             // Reading the value
+}
+/*
+Reads the Left and Right Inidcator
+*/
+void Task_9_read_indicators()
+{
+    indicator_R = DinSwitchRindic;                                            // Reading the value
+    indicator_L = DinSwitchLindic;                                            // Reading the value
+}
+/*
+Calculates the Average Speed
+*/
+void Task_10_calc_avg_speed()
+{
+// Let the Semaphores wait
+    SemAvgSpeed.wait();
+    SemAvgSpeedDB.wait();
+float sum(0);
+for(deque<float>::const_iterator i = AvgSpeedDB.begin(); i != AvgSpeedDB.end(); ++i)
+        sum+= *i;                                                             // calculate the average by iterating over the queue
+    avgSpeed = sum/AvgSpeedDB.size();
+// Release the Semaphores
+    SemAvgSpeedDB.release();
+    SemAvgSpeed.release();
+}
+/*
+Emulates the car
+*/
+void Task_11_emulate_car()
+{
+// Let the Semaphores wait
+    SemAvgSpeed.wait();
+    SemAvgSpeedDB.wait();
+    SemDistance.wait();
+    SemBreak_Accelerate.wait();
+    SemSpeed.wait();
+    SemEngine.wait();
+if(accerlator<=brake || !engine)                                        // are we braking more than accelerating? is the engine on?
+        speed = 0;
+else
+        speed = (accerlator-brake) *0.5 +speed;
+if(speed>250)
+        speed=250;                                                           // maximum speed
+if(AvgSpeedDB.size()>=4)                                                 // if we already got 4 values, we have to
+        AvgSpeedDB.pop_front();                                              // make space by deleting the oldest value
+    AvgSpeedDB.push_back(speed);                                             // safe a new reading
+    dist += speed * 1.0/20.0;                                                // runs at 20 Hz so we have to take this into account
+// Release the Semaphores
+    SemDistance.release();
+    SemAvgSpeed.release();
+    SemAvgSpeedDB.release();
+    SemBreak_Accelerate.release();
+    SemSpeed.release();
+    SemEngine.release();
+}
+/*
+Function used for converting Hz to Ms for a Steps
+*/
+int Convert_Hz_to_Ms(double Hz)
+{
+return 1000.0 / Hz;
+}