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-ScanInput.cpp
- Committer:
- Damotclese
- Date:
- 2019-06-17
- Revision:
- 2:cbcf2695a4a1
- Parent:
- 1:b9d4b9b8884c
File content as of revision 2:cbcf2695a4a1:
// ---------------------------------------------------------------------- // LaserMon-ScanInput.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-Main.h" // For data exported to us #include "LaserMon-TestOutput.h" // For test signal // ---------------------------------------------------------------------- // Options, defined constants, and MACROs // // ---------------------------------------------------------------------- #define WANT_TEST_SIGNAL 0 // ---------------------------------------------------------------------- // Local data storage // // ---------------------------------------------------------------------- // We create an analog input static AnalogIn st_scanInput(LASER_SCAN_IN); // For diagnostic purposes to show that the Laser Scan is operating static DigitalOut st_scanInputLED(LED2); // There are LCD_HEIGHT possible scan lines with a height of // LCD_WIDTH -- yes, the defined constant names are swapped // because we plot sideways. // // This value contains the next scan line number to plot static uint16_t u16_nextScanLine; // We store the last pixel's height so we may plot static uint16_t u16_lastHeight = 0; // Flag indicates whether we believe we are receiving porch or not static bool b_inPorch; // We keep track of how many times we have had to search for porch. // Typically we could expect not to have to search for it when the // plot goes beyond the end of the screen, however we may need to // search on power-up and when the scan frequency changes static uint16_t u16_resyncCount; // For no reason at all we keep track of how many scans we detect static uint32_t u32_scanCount; // When we are searching for porch, we use this flag to indicate that static bool b_waitingForPorch; // We keep track of how many milliseconds there are between porch // detections. This indicates a fairly close timing of the scan // frequency. static uint16_t u16_scanFrequency; static uint16_t u16_msFromPorchToPorch; // ---------------------------------------------------------------------- // ScanInputPlotThisValue() // // What percentage of LCD_HEIGHT is the voltage? We need to scale 0 to // 3.3 volts across LCD_HEIGHT, with 0 being zero, and 3.3 volts being // LCD_HEIGHT. // // We compute the percentage of 3.3 volts that the input signal is // currently showing, then we compute that percentage of LCD_HEIGHT to // determine how many pixels on a scan line that percentage is. That // gives us the height of the plot line while u16_nextScanLine gives // us the line to plot it on. // // This is easy because the value passed to this function is a value // from 0.0 to 1.0 which is a percentage of 3.3 volts, so we use the // value against LCD_HEIGHT to yield the percentage of height. // // ---------------------------------------------------------------------- static void ScanInputPlotThisValue(float f_analogValue) { // Compute the percentage of LCD height uint16_t u16_pixelHeight = ((f_analogValue / 3.3f) * ((float)LCD_HEIGHT - 10.0f)); u16_pixelHeight /= 2; u16_pixelHeight += 10; // Clear the entire current scan line to plot st_lcd.SetTextColor(LCD_COLOR_WHITE); st_lcd.DrawLine(1, u16_nextScanLine, LCD_WIDTH, u16_nextScanLine); // Plot from the previous pixel to the new one st_lcd.SetTextColor(LCD_COLOR_BLUE); // Are we currently in porch? We plot differently if so if (false == b_inPorch) { // We plot ramp from the previous scan line's height to the current scan line and height st_lcd.DrawLine(u16_lastHeight, u16_nextScanLine - 1, u16_pixelHeight, u16_nextScanLine); } else { // We plot the porch at a height of 10 pixels st_lcd.DrawLine(10, u16_nextScanLine - 1, 10, u16_nextScanLine); } // Keep track of the last height so we may plot u16_lastHeight = u16_pixelHeight; } // ---------------------------------------------------------------------- // // // ---------------------------------------------------------------------- static float ScanInputGetInputVoltage(void) { // Get the current analog input value and convert to volts float f_analogValue = st_scanInput.read() * 3.3f; #if WANT_TEST_SIGNAL // Use the test output signal voltage instead f_analogValue = f_rampVoltage; #endif // Return either the actual analog in or test voltage return f_analogValue; } static void ScanInputUpdateScanFrequency(void) { // Store the last porch to porch counter u16_scanFrequency = u16_msFromPorchToPorch; // Restart the porch to porch counter u16_msFromPorchToPorch = 0; } // ---------------------------------------------------------------------- // ScanInputWaitForPorch() // // ---------------------------------------------------------------------- static void ScanInputWaitForPorch(void) { float f_analogValue = 5.0f; // While we're not seeing porch, loop if (f_analogValue > 0.5f) { return; } // Flag the fact that we're in porch b_inPorch = true; b_waitingForPorch = false; // Keep track of our scan frequency ScanInputUpdateScanFrequency(); // Since we detected porch, start the plot over from the beginning u16_nextScanLine = 50; // The last height we consider to be 1 pixel on porch u16_lastHeight = 1; // Keep track of how many times we had to wait for locating porch // again after loosing it. Note that on power-up, if we are using // the test signal output, it is driven to porch co-incident with // the input test, so we start up with porch as the first sample ++u16_resyncCount; } // ---------------------------------------------------------------------- // ScanInputGetNextValue() // // // ---------------------------------------------------------------------- static void ScanInputGetNextValue(bool b_allowPlotting) { float f_analogValue = ScanInputGetInputVoltage(); // Dows the input indicate that we are in porch? if (f_analogValue < 1.0f) { // Did we previously know that we were in porch? if (false == b_inPorch) { float f_plusFourPercent = 0.0f; // Flag the fact that we're in porch now b_inPorch = true; // Since we detected a new porch, start the plot over u16_nextScanLine = 49; // The last height we consider to be 1 pixel on porch u16_lastHeight = 1; // Update our scan frequency ScanInputUpdateScanFrequency(); // Since our timing in this device is off, we add a correction f_plusFourPercent = (((float)u16_scanFrequency / 100.0f) * 4.3f); // Let the main module know what the scan rate is for display // and for testing and evaluating LaserMonMainInformScanInformation((uint16_t)((float)u16_scanFrequency + f_plusFourPercent), ++u32_scanCount); } } else { // We are in the ramp so flag the fact even if we already know b_inPorch = false; // Keep track of the scan frequency u16_msFromPorchToPorch++; } // Indicate the next line to plot this reading on to u16_nextScanLine++; // The display may be in use for other functionality so we // check to ensure that we are permitted to plot the input if (true == b_allowPlotting) { // Call the function which plots this value (void)ScanInputPlotThisValue(f_analogValue); } // Are we about to exceed the display? if (u16_nextScanLine >= (LCD_HEIGHT - 10)) { // We have lost track of porch so we must search for it again b_waitingForPorch = true; } // Set the LED with whether we are at porch or not st_scanInputLED = b_inPorch; } // ---------------------------------------------------------------------- // ScanInputThread() // // This is called once a millisecond however it is not a thread, the // thread class on this board ended up with timing that could not be // controlled so the main() loop calls us once a millisecond. // // ---------------------------------------------------------------------- void ScanInputThread(bool b_allowPlotting) { // Are we waiting for porch synchronization? if (true == b_waitingForPorch) { // Start out searching for porch ScanInputWaitForPorch(); } // Scan the signal coming in and optionally plot it ScanInputGetNextValue(b_allowPlotting); } // ---------------------------------------------------------------------- // ScanInputInit() // // Initialize this module's locally-held data // // ---------------------------------------------------------------------- void ScanInputInit(void) { // Start out with the LED turned ON st_scanInputLED = 1; // Initialize loc ally-held variables u16_nextScanLine = 50; b_inPorch = false; b_waitingForPorch = true; u16_scanFrequency = 0; u16_resyncCount = 0; u32_scanCount = 0; u16_msFromPorchToPorch = 0; } // End of file