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