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

LaserMon-Main.cpp

Committer:
Damotclese
Date:
2019-06-17
Revision:
2:cbcf2695a4a1
Parent:
1:b9d4b9b8884c

File content as of revision 2:cbcf2695a4a1:


// ----------------------------------------------------------------------
// LaserMon-Main.cpp
//
// Fredric L. Rice, June 2019
//
// ----------------------------------------------------------------------

#include "mbed.h"                   // The mbed operating system
#include "LCD_DISCO_F429ZI.h"       // For controlling the LCD
#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

// ----------------------------------------------------------------------
// Local data storage
//
// ----------------------------------------------------------------------

    const char * pch_firstMessage  = "Test signal on PA_5";
    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
//
// ----------------------------------------------------------------------

    // We will be using the LCD so instantiate an object locally
    LCD_DISCO_F429ZI st_lcd;

    // We will be using the touch screen so instantiate an object
    TS_DISCO_F429ZI st_touchScreen;
    
// ----------------------------------------------------------------------
// MainInit()
//
// ----------------------------------------------------------------------
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);
    
    // Set the default text color
    st_lcd.SetTextColor(LCD_COLOR_BLUE);
    
    // Set the background color
    st_lcd.SetBackColor(LCD_COLOR_WHITE);        

    // 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;
}

// ----------------------------------------------------------------------
// main()
//
//
// ----------------------------------------------------------------------
int main(void)
{
    uint16_t u16_oneSecondCounter    = 0;
    bool     b_restartOneSecondTimer = false;
    
    // Perform local module initialization, if any
    MainInit();
    
    // Initialize the generating of the output test signal module
    TestOutputInit();
    
    // 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(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(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;
            }
        }
    }
}

// End of file