Generates a test signal on an AnalogOut and monitors a signal on an AnalogIn, plotting the test signal or the actual signal depending on a conditional compile. The wait() and wait_ms() library calls for this board are highly inaccurate so a new function is provided to wait for X number of milliseconds -- which is not very accurate.

Dependencies:   LCD_DISCO_F429ZI mbed TS_DISCO_F429ZI mbed-os BSP_DISCO_F429ZI

Revision:
2:cbcf2695a4a1
Parent:
1:b9d4b9b8884c
--- a/LaserMon-Main.cpp	Fri Jun 14 21:11:31 2019 +0000
+++ b/LaserMon-Main.cpp	Mon Jun 17 17:11:07 2019 +0000
@@ -11,6 +11,7 @@
 #include "TS_DISCO_F429ZI.h"        // For controlling the touch screen
 #include "LaserMon-TestOutput.h"    // For generating test output signal
 #include "LaserMon-ScanInput.h"     // For monitoring laser power pin
+#include "LaserMon-TEC.h"           // For monitoring the TEC output
 #include "LaserMon-Main.h"          // Always include ourself
 
 // ----------------------------------------------------------------------
@@ -19,8 +20,30 @@
 // ----------------------------------------------------------------------
 
     const char * pch_firstMessage  = "Test signal on PA_5";
-    const char * pch_secondMessage = "Laser Scan on PC_1";
+    const char * pch_secondMessage = "Laser Scan on  PC_1";
+    const char * pch_thirdMessage  = "TEC signal on  PC_3";
+
+    // Instantiate a digitial input mapped as our push button
+    static DigitalIn st_pushButton(PA_0);
 
+    // We must see the button down for a period of time, we
+    // do a debounce even though the class may do one already
+    static uint16_t u16_buttonDownCount;
+    
+    // This flag informs the laser scan input module whether
+    // it is permitted to plot the scan input or not
+    static bool b_allowPlotting;
+    
+    // We store the scan length in milliseconds offered to this
+    // module by the laser scanner, and we store the TEC voltage
+    // offered by the TEC scanner
+    static uint16_t u16_scanLength;
+    static uint16_t u16_TECVoltage;
+    static uint16_t u16_scanCount;
+
+    // We talk to Jenkins through an RS232 serial interface
+    static Serial st_Serial1(USE_SERIAL_TX, USE_SERIAL_RX);
+    
 // ----------------------------------------------------------------------
 // Define global data storage which we will export
 //
@@ -38,6 +61,13 @@
 // ----------------------------------------------------------------------
 static void MainInit(void)
 {
+    // Initialize locally-held data
+    u16_buttonDownCount = 0;
+    b_allowPlotting     = true;
+    u16_scanLength      = 0;
+    u16_TECVoltage      = 0;
+    u16_scanCount       = 0;
+    
     // Bring the LCD up 
     st_lcd.Clear(LCD_COLOR_WHITE);
     
@@ -49,6 +79,168 @@
 
     // Set the default font size
     BSP_LCD_SetFont(&Font16);
+    
+    // Set the push button to not have an internal pull-up or down
+    st_pushButton.mode(PullNone);
+    
+    // We configure the serial interface
+    st_Serial1.baud(115200);
+    st_Serial1.format(8, SerialBase::None, 1);
+}
+
+// ----------------------------------------------------------------------
+//
+//
+// ----------------------------------------------------------------------
+static void MainCheckInbound(void)
+{
+    // See if there is inbound serial data
+    if (st_Serial1.readable())
+    {
+        
+    }  
+}
+
+// ----------------------------------------------------------------------
+//
+//
+// ----------------------------------------------------------------------
+static void MainTransmitOutput(uint8_t * pu8_thisFrame, uint16_t u16_thisCount)
+{
+    st_Serial1.write(pu8_thisFrame, u16_thisCount, NULL);
+}
+
+// ----------------------------------------------------------------------
+// LaserMonMainInformScanInformation()
+//
+//
+// ----------------------------------------------------------------------
+void LaserMonMainInformScanInformation(uint16_t u16_thisScanLength, uint16_t u16_thisScanCount)
+{
+    // If we arte displaying information, the scan gets slowed down
+    // while we print the information to the screen, making the scan
+    // information inaccurate. To avoid displaying inaccurate values
+    // we refrain from storing the scan rate while displaying the
+    // information
+    if (true == b_allowPlotting)
+    {
+        // Allow the scan information to get updated
+        u16_scanLength = u16_thisScanLength;
+    }
+    
+    // Always store the scan counter value
+    u16_scanCount  = u16_thisScanCount;
+}
+
+// ----------------------------------------------------------------------
+// LaserMonMainInformTECVoltage()
+//
+// ----------------------------------------------------------------------
+void LaserMonMainInformTECVoltage(uint16_t u16_thisVoltage)
+{
+    u16_TECVoltage = u16_thisVoltage;    
+}
+
+// ----------------------------------------------------------------------
+// MainReportValues()
+//
+// ----------------------------------------------------------------------
+static void MainReportValues(void)
+{
+    char pch_holdMessage[101] = { 0 };
+    
+    (void)sprintf(pch_holdMessage, "Scan duration %u", u16_scanLength);
+    st_lcd.DisplayStringAt(1, LINE(1), (uint8_t *)pch_holdMessage, LEFT_MODE);
+
+    (void)sprintf(pch_holdMessage, "Scan count %u", u16_scanCount);
+    st_lcd.DisplayStringAt(1, LINE(2), (uint8_t *)pch_holdMessage, LEFT_MODE);
+
+    (void)sprintf(pch_holdMessage, "TEC voltage %1.02f", (float)u16_TECVoltage / 100.0f);
+    st_lcd.DisplayStringAt(1, LINE(3), (uint8_t *)pch_holdMessage, LEFT_MODE);
+
+    (void)sprintf(pch_holdMessage, "TEC average %1.02f", (float)TECGetLastTenAverage() / 100.0f);
+    st_lcd.DisplayStringAt(1, LINE(4), (uint8_t *)pch_holdMessage, LEFT_MODE);
+    
+    // Build a report for Jenkins or anything else to monitor
+    (void)sprintf(pch_holdMessage, "%u,%1.02f,%1.02f,%u%c%c",
+        u16_scanLength,
+        ((float)u16_TECVoltage / 100.0f),
+        ((float)TECGetLastTenAverage() / 100.0f),
+        u16_scanCount,
+        0x0d, 0x0a);
+    
+    // Send that report out the serial interface
+    MainTransmitOutput((uint8_t *)pch_holdMessage, (uint16_t)strlen(pch_holdMessage));
+}
+
+// ----------------------------------------------------------------------
+// MainHandleButtonDown()
+//
+// ----------------------------------------------------------------------
+static void MainHandleButtonDown(void)
+{
+    // Are we currently allowing the laser scan input to be plotted?
+    if (true == b_allowPlotting)
+    {
+        // Flag the fact that we are not allowing the plot
+        b_allowPlotting = false;
+
+        // Make sure that the display is cleared
+        st_lcd.Clear(LCD_COLOR_WHITE);    
+
+        // Report the lasr scan and TEC voltage values
+        MainReportValues();
+    }
+    else
+    {
+        // Clear the display
+        st_lcd.Clear(LCD_COLOR_WHITE);    
+        
+        // Clear the flag so that the plot of the scan may be displayed
+        b_allowPlotting = true;
+    }    
+}
+
+// ----------------------------------------------------------------------
+// MainThread()
+//
+// ----------------------------------------------------------------------
+static bool MainThread(void)
+{
+    bool b_restartOneSecondTimer = false;
+    
+    // Acquire / poll the state of the push button
+    int i_buttonState = st_pushButton.read();
+    
+    // Is the button down?
+    if (1 == i_buttonState)
+    {
+        // The button is not down, was the button down before?
+        // We need to see if the button is down for 10 milliseconds
+        // before we agree that the button is down
+        if (u16_buttonDownCount < 10)
+        {
+            if (10 == ++u16_buttonDownCount)
+            {
+                // The button has been held down long enough
+                MainHandleButtonDown();
+                
+                // We want to have the one second timer restarted
+                b_restartOneSecondTimer = true;
+            }
+        }
+    }
+    else
+    {
+        // The button is not down so clear the down counter
+        u16_buttonDownCount = 0;
+    }
+    
+    // See if there is inbouns serial data to be processed
+    MainCheckInbound();
+    
+    // Indicate whether we are displaying the running information or not
+    return b_restartOneSecondTimer;
 }
 
 // ----------------------------------------------------------------------
@@ -58,26 +250,65 @@
 // ----------------------------------------------------------------------
 int main(void)
 {
+    uint16_t u16_oneSecondCounter    = 0;
+    bool     b_restartOneSecondTimer = false;
+    
     // Perform local module initialization, if any
     MainInit();
     
-    // Start generating the putput test signal
+    // Initialize the generating of the output test signal module
     TestOutputInit();
     
-    // Start scanning the laser drive power
+    // Initialize the scanning of the the laser drive power module
     ScanInputInit();
     
+    // Initialize the scanning of the TEC input and launch thread
+    TECInit();
+    
     // Display information about what signal pigs have what
-    st_lcd.DisplayStringAt(1, LINE(1), (uint8_t *)pch_firstMessage, LEFT_MODE);
-    st_lcd.DisplayStringAt(1, LINE(2), (uint8_t *)pch_secondMessage, LEFT_MODE);
+    st_lcd.DisplayStringAt(1, LINE(0), (uint8_t *)pch_firstMessage,  LEFT_MODE);
+    st_lcd.DisplayStringAt(1, LINE(1), (uint8_t *)pch_secondMessage, LEFT_MODE);
+    st_lcd.DisplayStringAt(1, LINE(2), (uint8_t *)pch_thirdMessage,  LEFT_MODE);
     
     // Go in to a forever loop for the main thread which does nothing
     while(true)
     {
         // Wait for 1 millisecond
         wait_us(899);
+        
+        // Instead of launching threads whose timing is a problem,
+        // we merely call the once-a-millisecond "thread" functions
+        // to drive the test signal out and the laser scan signal in
         TestOutputThread();
-        ScanInputThread();
+        ScanInputThread(b_allowPlotting);
+        b_restartOneSecondTimer = MainThread();
+        TECThread();
+        
+        // Have we just started displaying collected information?
+        if (true == b_restartOneSecondTimer)
+        {
+            // Yes, so we will count down the timer
+            u16_oneSecondCounter = 1000;
+        }
+        else
+        {
+            // In case the one second timer is running, stop it
+            b_restartOneSecondTimer = 0;
+        }
+        
+        // Is the one second counter running?
+        if (u16_oneSecondCounter > 0 && false == b_allowPlotting)
+        {
+            // Count down the one second timer and see if it's expired
+            if (0 == --u16_oneSecondCounter)
+            {
+                // Report the current values again
+                MainReportValues();
+                
+                // Restart the one second timer
+                u16_oneSecondCounter = 1000;
+            }
+        }
     }
 }