3rd Repo, trying to figure this out.

Dependencies:   LPS25H hts221

Fork of SOFT253_Template_Weather_OS_54 by Stage-1 Students SoCEM

Revision:
83:0d3572a8a851
Parent:
82:668b51a39148
Child:
85:422d0a1b95cf
diff -r 668b51a39148 -r 0d3572a8a851 main.cpp
--- a/main.cpp	Thu May 11 15:53:15 2017 +0000
+++ b/main.cpp	Thu May 11 19:23:55 2017 +0000
@@ -1,4 +1,3 @@
-
 #include "mbed.h"
 #include "rtos.h"
 #include "hts221.h"
@@ -20,6 +19,31 @@
 #define SWITCH1_RELEASE 90
 #define BUFFER_SIZE 120
  
+/**
+    @file :     main.cpp
+    @authors :   Radu Marcu, Jacob Williams, Niall Francis, Arron Burch
+    
+    @section DESCRIPTION
+    
+    This is the main class where the program runs on startup, this is
+    a multi-threaded application that will that make the ST F401 Nucleo Target board
+    take periodic measurements of senor data, including temperature,
+    pressure and humidity, at a fixed set sample rate. A max of 120 measurements are stored 
+    within RAM at any one time, available to be printed to a termial output via a serial port
+    connection.
+    Once 120 measurements are stored, the oldest measurements are overwritten using a circular
+    buffer, so that the most recent 120 measurements can always be stored on the device.
+    The application can provide logging data when measurements are taken if logging is turned
+    on using the logging command (See readme.md).
+    The application has been written to reduce power consumption where possible by utilising
+    Thread signals and sleeping when not in use.
+    Serial Communications are handled within a sepearate thread to ensure that no action will
+    block or interrupt the CPU when measuring samples.
+    The serial communications use a priority system, allowing errors to be printed with a higher
+    priority than logging messages and the application to be terminated and reset by user input
+    if required.
+*/
+
 //
 //  MBED DECLARATIONS
 //
@@ -31,19 +55,19 @@
 // SENSOR DECLARATIONS
 // MAKE SURE ONE OF THESE IS COMMENTED OUT
 // Real sensor
-// LPS25H barometer(i2c2, LPS25H_V_CHIP_ADDR);
-// HTS221 measurer(I2C_SDA, I2C_SCL);
+LPS25H barometer(i2c2, LPS25H_V_CHIP_ADDR);
+HTS221 measurer(I2C_SDA, I2C_SCL);
 // Fake sensor
-FakeBarometer barometer(1029.0, 1031.0);
-FakeMeasurer measurer(20.0, 25.0, 30.0, 50.0);
+// FakeBarometer barometer(1029.0, 1031.0);
+// FakeMeasurer measurer(20.0, 25.0, 30.0, 50.0);
 
 //
 // THREADS DECLARATION
 //
 osThreadId mainThreadId;
-Thread *produceThread;
-Thread *measureThread;
-Thread *consumeThread;
+Thread *producerThread;
+Thread *measurementThread;
+Thread *consumerThread;
 Thread *loggingThread;
 Ticker timer;
 Ticker realTimeDate;
@@ -52,7 +76,6 @@
 // 
 Mail<Measure, 16> mail_box;
 LocalDate *localDate;
-//Mail<>
 bool logging = false;
 bool measuring = true;
 double sampleRate = 15;
@@ -63,8 +86,9 @@
 
 CircularArray buffer(BUFFER_SIZE, &logger);
 // 
-//  Called by a TICKER
+//  Called by a ticker
 //  Adds 1 second every second to the clock
+//
 void RealTimeDate()
 {
     localDate->TickSecond();
@@ -75,13 +99,14 @@
 //
  void SendSignalDoMeasure()
 {
-    measureThread->signal_set(SIGNAL_doMeasure);    
+    measurementThread->signal_set(SIGNAL_doMeasure);    
 }
 
 //
-//  SIGNALED BY Ticker at a frequency of <T> Hz
-//  Reads values from sensor board, sends over through mail queue
-void MeasureThread() 
+//  Called by ticker every T seconds
+//  Reads values from sensor board, sends between threads using a mail queue
+//
+void MeasurementThread() 
 {
     float temperature , humidity, pressure;
 
@@ -90,7 +115,7 @@
         temperature = 0;
         humidity = 0;
         pressure = 0;
-        //Await signal from ticker
+        
         Thread::signal_wait(SIGNAL_doMeasure);
         
         Measure *measure = mail_box.alloc();
@@ -100,7 +125,7 @@
            return;   
         }
     
-        //Read and fill in data
+        //Read data from measurer, puts data into a measure object.
         measurer.ReadTempHumi(&temperature,&humidity);
         barometer.get();
         pressure = barometer.pressure();
@@ -112,80 +137,83 @@
 
         osStatus stat = mail_box.put(measure);
     
-        //Check if succesful
-        if (stat == osErrorResource) {
+        // Check if mailbox allocation was unsuccessful 
+        if (stat == osErrorResource)
+        {
             snprintf(temp, 256, "queue->put() Error code: %4Xh, Resource not available\r\n", stat);   
             logger.SendError(temp);
             mail_box.free(measure);
             return;
         }
         
+        // Print measurement taken if logging is enabled
         if(logging)
         {
             logger.SendMessage("Measurement Taken:\r\n");
             char *ptr = localDate->ToString();
-            snprintf(temp, 256, "    %s T: %f | H: %f | P: %f |\n\r",ptr, temperature, humidity, pressure);
+            snprintf(temp, 256, "    %s T: %f, H: %f, P: %f\n\r",ptr, temperature, humidity, pressure);
             logger.SendMessage(temp);
         }
     }
 }
  
 //
-//  Receives data through mail queue, then adds it to the global declared list
-//  A.K.A. Producer Thread
+//  Receives data through mail queue, then adds it to the circular array buffer.
+//
 void ProducerThread() 
 {      
     while (true) 
     {
-        //Block on the queue
         osEvent evt = mail_box.get();
         
-        //Check status
-        if (evt.status == osEventMail) {
-            
+        // Check if mailbox retrieval was successful
+        if (evt.status == osEventMail) 
+        {
             Measure *measure = (Measure*)evt.value.p;          
             Measure msr(measure->date,measure->temperature, measure->humidity,measure->pressure);
             
-            // Changed to use circlar buffer rather than list buffer
             buffer.pushValue(msr);
             mail_box.free(measure);
-        } else {
+        } 
+        else
+        {
             snprintf(temp, 256, "ERROR: %x\r\n", evt.status);   
             logger.SendError(temp);
-        }          
+        }
     }
 }
+
 int i;
-//
-//  Compares two char arrays and returns result
-//  Param1: First char Array / pointer
-//  Param2: Second char Array / pointer
-//  Param3. Size of the smallest char arrays (between param1 and param2)
-//  Return: "-1" IF NOT EQUAL
-//          "1 " IF EQUAL
-bool CompareCommands(char command[],char targetcommand[], int size)
+/**
+  Compares two char arrays and returns result
+
+  @param command :        First char Array / pointer
+  @param targetCommand :  Second char Array / pointer
+  @param size :           Size of the smallest char arrays (between param1 and param2)
+  @return :               TRUE if equal, FALSE if not equal
+*/
+bool CompareCommands(char command[],char targetCommand[], int size)
 {
-       for(i = 0; i < size; i ++)
-       {
-            if(command[i] != targetcommand[i])
-            {
-                return false;
-            }
+    for(i = 0; i < size; i ++)
+    {
+        if(command[i] != targetCommand[i])
+        {
+            return false;
         }
-        return true;
-}
+    }
+    return true;
+} 
 
-//
-//  Reads commands through PUTTY and 'consumes the data' accordingly
-//  A.K.A. Consumer Thread
-void ConsumeThread()
+/**
+  Reads commands from the terminal and 'consumes' the data accordingly.
+*/
+void ConsumerThread()
 {
-    //Last character pressed read (last key input)
     char charCmd;
-    //Char array that stores the command after user presses ENTER
+    //Char array that stores the chars entered when user presses enter.
     char command[40];
     //Current Command Size
-    int crtChar = 0; 
+    int crtSize = 0; 
     logger.SendMessage("\r\nAwaiting Command: \r\n");
     while(1)
     {
@@ -194,49 +222,47 @@
         if(logging)
         {
             logging = false;
-            logger.SendMessage("\r\033[1AKey Pressed. Debug logging disabled.\r\n");
+            logger.SendMessage("\rKey Pressed. Debug logging disabled.\r\n");
             charCmd = NULL;
         }
         
         if(charCmd != NULL)
         {
             //If BACKSPACE is pressed, Print "DEL" so it deletes last character typed.
-            if (charCmd == 127 && crtChar > 0 )
+            if (charCmd == 127 && crtSize > 0 )
             {
-                command[--crtChar] = '\0';
+                command[--crtSize] = '\0';
             }
             //If NOT enter AND NOT Backspace is pressed, SAVE the char
             else if(charCmd != 13 && charCmd != 127) 
             {
-                command[crtChar++] = charCmd;
+                command[crtSize++] = charCmd;
             }
-            //If ENTER is pressed, PROCESS it
-            else if(charCmd == 13) // If Enter is pressed
+            // If enter is pressed, process the command.
+            else if(charCmd == 13)
             {   
-                //Get first word of command:
+                logger.SendMessage("\n");
+                // Get first word of command.
                 char *charPos;
                 charPos = strtok(command," -,");
                 
-                //Check if it's a "LIST" command
+                // Check if it's a "read" command
                 if(CompareCommands(charPos, "read",4))
                 {
                     charPos = strtok(NULL," -,");
-                    //Check if it's a "LIST ALL" command
+                    // Check if it's a "read all" command
                     if(CompareCommands(charPos, "all",3))
                     {                        
                         // Changed to use circular buffer rather than list buffer
                         buffer.readAll();
                         logger.SendMessage("D O N E ! \r\n");
                     }
-                    //Check if it's a "LIST X" command
+                    // Check if it's a "read n" command
                     else if(strtol(charPos,NULL,10) != 0)
                     {
                         int num = atoi(charPos);
                         
-                        logger.SendMessage(temp);
-                        
-                        // Changed to use circular buffer rather than list buffer
-                        buffer.readX(num);
+                        buffer.readN(num);
                         logger.SendMessage("D O N E ! \r\n");
                     }
                     else
@@ -244,23 +270,22 @@
                         logger.SendMessage("Expected parameters: \"all\" | \"n\", where n is a number.\r\n");
                     }
                 }
-                //Check if it's a "DELETE" command
+                // Check if it's a "delete" command
                 else if (CompareCommands(charPos,"delete",6))
                 {
                     charPos = strtok(NULL," -,");
-                    //Check if it's a "DELETE ALL" command
+                    // Check if it's a "delete all" command
                     if(CompareCommands(charPos,"all",3))
                     {
                         logger.SendMessage("Deleting all measures performed so far: \r\n");
                         
-                        // Changed to use circular buffer rather than list buffer
                         buffer.deleteAll();
                     }
-                    //Check if it's a "DELETE X" command
+                    // Check if it's a "delete n" command
                     else if (strtol(charPos,NULL,10) != 0)
                     {
                         // Changed to use circular buffer rather than list buffer
-                        buffer.deleteX(atoi(charPos));
+                        buffer.deleteN(atoi(charPos));
                         logger.SendMessage("Elements deleted!\r\n");
                     }
                     else
@@ -268,12 +293,11 @@
                         logger.SendMessage("Expected parameters: \"all\" | \"n\", where n is a number.");
                     }                       
                 }
-                //Check if it's a "STATUS" command
+                // Check if it's a "status" command
                 else if (CompareCommands(charPos,"status",6))
                 {
                     char *ptr = localDate->ToString();
                     
-                    // Changed to use circular buffer rather than list buffer
                     snprintf(temp, 256, "\nStatus: \r\n");
                     logger.SendMessage(temp);                    
                     snprintf(temp, 256, "    # of measures: %i \r\n", buffer.getSize());
@@ -287,29 +311,26 @@
                     snprintf(temp, 256, "    Sample Rate(s): %2.2f \r\n", sampleRate);
                     logger.SendMessage(temp);
                 }
-                //Check if it's a "SETTIME" command
+                //Check if it's a "settime" command
                 else if (CompareCommands(charPos,"settime",7))
                 {
                     int h,m,s;
-                    //Fetch 1st Param
+                    
                     charPos = strtok(NULL," -,");
                     if(strtol(charPos,NULL,10) != 0)
                     {
                         h = atoi(charPos);   
                     }
-                    //Fech 2nd Param
                     charPos = strtok(NULL," -,");
                     if(strtol(charPos,NULL,10) != 0)
                     {
                         m = atoi(charPos);   
                     }
-                    //Fetch 3rd Param
                     charPos = strtok(NULL," -,");
                     if(strtol(charPos,NULL,10) != 0)
                     {
                         s = atoi(charPos);   
                     }
-                    //Check if parameters are valid
                     if((h>=0 && h < 24) && (m>=0 && m<60) && (s>=0 && s<60))
                     {
                         localDate->hour = h;
@@ -319,35 +340,34 @@
                         snprintf(temp, 256, "Updated Date to: %s \r\n", ptr);
                         logger.SendMessage(temp);
                     } 
-                    //If not valid, prompt user
                     else
                     {
                         logger.SendMessage("\r\nWrong format! please use HH-MM-SS. \r\n");
                     }
                 }
-                //Check if it's a "SETDATE" command
+                //Check if it's a "setdate" command
                 else if (CompareCommands(charPos,"setdate",7))
                 {
                     int d,m,y;
-                    //Fetch 1st Parameter
+                    
                     charPos = strtok(NULL," ,-");
                     if(strtol(charPos,NULL,10) != 0)
                     {
                         d = atoi(charPos);   
                     }
-                    //Fetch 2nd Parameter
+                    
                     charPos = strtok(NULL," ,-");
                     if(strtol(charPos,NULL,10) != 0)
                     {
                         m = atoi(charPos);   
                     }
-                    //Fetch 3rd Parameter
+                    
                     charPos = strtok(NULL," ,-");
                     if(strtol(charPos,NULL,10) != 0)
                     {
                         y = atoi(charPos);   
                     }
-                    //Check if parameters are valid
+                    
                     if((d>=0 && d < 31) && (m>=0 && m<13))
                     {
                         localDate->day = d;
@@ -357,27 +377,27 @@
                         snprintf(temp, 256, "Updated Date to: %s \r\n", ptr);
                         logger.SendMessage(temp);
                     } 
-                    // Prompt user if they are not.
                     else
                     {
                         logger.SendMessage("Wrong format! please use DD-MM-YYYY. \r\n");  
                     }
                 }
-                // Check if it's a "STATE" command
+                // Check if it's a "state" command
                 else if(CompareCommands(charPos,"state",5))
                 {
                     charPos = strtok(NULL," ,");
-                    //Check if it should be turned ON / OFF
+                    
+                    // Check if it should be turned on / off
                     if(CompareCommands(charPos,"on",2))
                     {
-                        logger.SendMessage("Sampling turned ON!\r\n");
+                        logger.SendMessage("Sampling turned on!\r\n");
                         timer.attach(&SendSignalDoMeasure, sampleRate);
                         SendSignalDoMeasure();
                         measuring = true;
                     }
                     else if (CompareCommands(charPos,"off",3))
                     {
-                        logger.SendMessage("Sampling turned OFF!\r\n");
+                        logger.SendMessage("Sampling turned off!\r\n");
                         timer.detach();
                         measuring = false;
                     }
@@ -386,7 +406,7 @@
                         logger.SendMessage("Expected parameters: \"on\" | \"off\"\r\n");   
                     }
                 }
-                // Check if it's a "LOGGING" command
+                // Check if it's a "logging" command
                 else if(CompareCommands(charPos,"logging",7))
                 {
                     charPos = strtok(NULL," ,");
@@ -394,7 +414,7 @@
                     if(CompareCommands(charPos,"on",2))
                     {
                         logging = true;   
-                        logger.SendMessage("Debug logging turned ON!\r\n");
+                        logger.SendMessage("Debug logging turned on!\r\n");
                         logger.SendMessage("Press any key to deactivate\r\n");
                     }
                     else if (CompareCommands(charPos,"off",3))
@@ -406,7 +426,7 @@
                         logger.SendMessage("Expected parameters: \"on\" | \"off\"\r\n");   
                     }
                 }
-                // Check if it's a "SETT" command
+                // Check if it's a "sett" command
                 else if(CompareCommands(charPos,"sett",4))
                 {
                     charPos = strtok(NULL," ,");
@@ -421,13 +441,12 @@
                         snprintf(temp, 256, "Successfully updated sample rate to: %2.2f .\r\n",sampleRate);
                         logger.SendMessage(temp);
                     }
-                    // if rate is not valid, prompt:
                     else
                     {
                         logger.SendMessage("Sample rate must be between 0.1 and 60.\r\n");  
                     }
                 }
-                // Check if it's a "HELP" command
+                // Check if it's a "help" command
                 else if (CompareCommands(charPos,"help",4) || CompareCommands(charPos,"?",1))
                 {
                     logger.SendMessage("\nAvailable Commands:\r\n");
@@ -439,46 +458,44 @@
                     logger.SendMessage("    status - Status report of device.\r\n");
                     logger.SendMessage("    state - <on|off> - Turn sampling on or off.\r\n");
                     logger.SendMessage("    logging <on|off> - Turn logging on or off.\r\n");
+                    logger.SendMessage("    reset - Resets the current session of the application.\r\n");
                 }
-                // Check if it's a "HELP" command
+                // Check if it's a "reset" command
                 else if (CompareCommands(charPos,"reset",5))
                 {
                     logger.SendError("Program Terminating...\r\n");
                 }
-                // If command not recognized
+                // If command is not recognized
                 else
                 {
                     logger.SendMessage("Command not recognized. Type \"help\" for more info.\r\n");
                 }
-                if(!logging)
+                
+                if(!logging) 
                 {
                     logger.SendMessage("\r\nAwaiting Command:\r\n");
                 }
-                //Clear command!
-                //* NOTE * Setting first char in array to '\0' WILL NOT RESET IT...for some reason.
+                
+                // Clear currently stored command
                 int i = 0;
-                for(i =0 ; i < crtChar; i++)
+                for(i =0 ; i < crtSize; i++)
                     command[i] = ' ';
                 command[0] = 0;
-                crtChar = 0;
+                crtSize = 0;
             }
         }
     }
 }
 
+/**
+  Waits for a signal from the MessageLogger before confirming a message is to be printed,
+  ensuring messages are displayed in the correct order.
+  
+  If an error is recieved, error is prioritised and signal is sent to the main thread for the
+  program to be terminated, waiting for user input to reset.
+*/
 void LoggingThread()
-{
-     //Thread::wait(300000);
-     // ARRON: TODO
-     
-     // - Printing messages
-     // - Out of memory
-     // - Current status
-     // - Display time every X seconds/minutes
-     
-     // Some queue system holding lines to print
-     // If the queue has something to print, print it.
-     
+{    
     while(true)
     {
         Thread::signal_wait(SIGNAL_printMessage);
@@ -497,32 +514,37 @@
     }
 }
  
-// Main thread
+/**
+  Main Thread: Entry point to program.
+*/
 int main() {
-           mainThreadId = osThreadGetId();
-    //Initialize all stuff you need here:
+    
+    mainThreadId = osThreadGetId();
+    
     measurer.init();
     measurer.calib();
     
-    localDate = new LocalDate();
-    //Start message         
+    localDate = new LocalDate();      
    
-    //Hook up timer interrupt   
+    // Timer initialised for measurements to be collected every sampleRate seconds.
     timer.attach(&SendSignalDoMeasure, sampleRate);
     realTimeDate.attach(&RealTimeDate,1.0);
                
-    //Run Threads
+    // Start Threads
+    
     loggingThread = new Thread();
     loggingThread->start(LoggingThread);
     
     logger.SetThread(loggingThread);
     
-    produceThread = new Thread();
-    produceThread->start(ProducerThread); 
-    measureThread = new Thread();
-    measureThread->start(MeasureThread);
-    consumeThread = new Thread();
-    consumeThread->start(ConsumeThread);
+    producerThread = new Thread();
+    producerThread->start(ProducerThread); 
+    
+    measurementThread = new Thread();
+    measurementThread->start(MeasurementThread);
+    
+    consumerThread = new Thread();
+    consumerThread->start(ConsumerThread);
     
     logger.SendMessage("\r\n--- W E L C O M E ---\r\n");
     
@@ -530,16 +552,18 @@
     
     while(true) 
     {
+        // Waits for temination signal from logging thread when an error is received.
         osSignalWait(SIGNAL_terminate, osWaitForever);
         
-        produceThread->terminate();
-        measureThread->terminate();
-        consumeThread->terminate();
+        producerThread->terminate();
+        measurementThread->terminate();
+        consumerThread->terminate();
         loggingThread->terminate();
         
+        // Waits for user input before resetting the system.
         printf("Press any key to restart...");
         char c = getchar();    
-            
+        printf("===============================\n\n\n");
         NVIC_SystemReset();        
     }
 } 
\ No newline at end of file