Fredric Rice / Mbed 2 deprecated NextGen-LaserMonitor

Dependencies:   LCD_DISCO_F429ZI mbed TS_DISCO_F429ZI mbed-os BSP_DISCO_F429ZI

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers LaserMon-ScanInput.cpp Source File

LaserMon-ScanInput.cpp

00001 
00002 // ----------------------------------------------------------------------
00003 // LaserMon-ScanInput.cpp
00004 //
00005 // Fredric L. Rice, June 2019
00006 //
00007 // ----------------------------------------------------------------------
00008 
00009 #include "mbed.h"                   // The mbed operating system
00010 #include "LCD_DISCO_F429ZI.h"       // For controlling the LCD
00011 #include "TS_DISCO_F429ZI.h"        // For controlling the touch screen
00012 #include "LaserMon-Main.h"          // For data exported to us
00013 #include "LaserMon-TestOutput.h"    // For test signal
00014 
00015 // ----------------------------------------------------------------------
00016 // Options, defined constants, and MACROs
00017 //
00018 // ----------------------------------------------------------------------
00019 
00020 #define WANT_TEST_SIGNAL        0
00021 
00022 // ----------------------------------------------------------------------
00023 // Local data storage
00024 //
00025 // ----------------------------------------------------------------------
00026 
00027     // We create an analog input
00028     static AnalogIn st_scanInput(LASER_SCAN_IN);
00029 
00030     // For diagnostic purposes to show that the Laser Scan is operating
00031     static DigitalOut st_scanInputLED(LED2);
00032     
00033     // There are LCD_HEIGHT possible scan lines with a height of
00034     // LCD_WIDTH -- yes, the defined constant names are swapped
00035     // because we plot sideways.
00036     //
00037     // This value contains the next scan line number to plot
00038     static uint16_t u16_nextScanLine;
00039     
00040     // We store the last pixel's height so we may plot
00041     static uint16_t u16_lastHeight = 0;
00042     
00043     // Flag indicates whether we believe we are receiving porch or not
00044     static bool b_inPorch;
00045     
00046     // We keep track of how many times we have had to search for porch.
00047     // Typically we could expect not to have to search for it when the
00048     // plot goes beyond the end of the screen, however we may need to
00049     // search on power-up and when the scan frequency changes
00050     static uint16_t u16_resyncCount;
00051     
00052     // For no reason at all we keep track of how many scans we detect
00053     static uint32_t u32_scanCount;
00054     
00055     // When we are searching for porch, we use this flag to indicate that
00056     static bool b_waitingForPorch;
00057     
00058     // We keep track of how many milliseconds there are between porch
00059     // detections. This indicates a fairly close timing of the scan
00060     // frequency.
00061     static uint16_t u16_scanFrequency;
00062     static uint16_t u16_msFromPorchToPorch;
00063    
00064 // ----------------------------------------------------------------------
00065 // ScanInputPlotThisValue()
00066 //
00067 // What percentage of LCD_HEIGHT is the voltage? We need to scale 0 to 
00068 // 3.3 volts across LCD_HEIGHT, with 0 being zero, and 3.3 volts being 
00069 // LCD_HEIGHT.
00070 //
00071 // We compute the percentage of 3.3 volts that the input signal is 
00072 // currently showing, then we compute that percentage of LCD_HEIGHT to
00073 // determine how many pixels on a scan line that percentage is. That
00074 // gives us the height of the plot line while u16_nextScanLine gives 
00075 // us the line to plot it on.
00076 //
00077 // This is easy because the value passed to this function is a value
00078 // from 0.0 to 1.0 which is a percentage of 3.3 volts, so we use the
00079 // value against LCD_HEIGHT to yield the percentage of height.
00080 //
00081 // ----------------------------------------------------------------------
00082 static void ScanInputPlotThisValue(float f_analogValue)
00083 {
00084     // Compute the percentage of LCD height
00085     uint16_t u16_pixelHeight = ((f_analogValue / 3.3f) * ((float)LCD_HEIGHT - 10.0f));
00086     
00087     u16_pixelHeight /= 2;
00088     u16_pixelHeight += 10;
00089     
00090     // Clear the entire current scan line to plot
00091     st_lcd.SetTextColor(LCD_COLOR_WHITE);
00092     st_lcd.DrawLine(1, u16_nextScanLine, LCD_WIDTH, u16_nextScanLine);
00093         
00094     // Plot from the previous pixel to the new one
00095     st_lcd.SetTextColor(LCD_COLOR_BLUE);
00096     
00097     // Are we currently in porch? We plot differently if so
00098     if (false == b_inPorch)
00099     {
00100         // We plot ramp from the previous scan line's height to the current scan line and height
00101         st_lcd.DrawLine(u16_lastHeight, u16_nextScanLine - 1, u16_pixelHeight, u16_nextScanLine);
00102     }
00103     else
00104     {
00105         // We plot the porch at a height of 10 pixels
00106         st_lcd.DrawLine(10, u16_nextScanLine - 1, 10, u16_nextScanLine);
00107     }
00108 
00109     // Keep track of the last height so we may plot
00110     u16_lastHeight = u16_pixelHeight;
00111 }
00112 
00113 // ----------------------------------------------------------------------
00114 //
00115 //
00116 // ----------------------------------------------------------------------
00117 static float ScanInputGetInputVoltage(void)
00118 {
00119     // Get the current analog input value and convert to volts
00120     float f_analogValue = st_scanInput.read() * 3.3f;
00121     
00122 #if WANT_TEST_SIGNAL
00123     // Use the test output signal voltage instead
00124     f_analogValue = f_rampVoltage;
00125 #endif
00126 
00127     // Return either the actual analog in or test voltage 
00128     return f_analogValue;
00129 }
00130 
00131 static void ScanInputUpdateScanFrequency(void)
00132 {
00133     // Store the last porch to porch counter
00134     u16_scanFrequency = u16_msFromPorchToPorch;
00135     
00136     // Restart the porch to porch counter
00137     u16_msFromPorchToPorch = 0;
00138 }
00139 
00140 // ----------------------------------------------------------------------
00141 // ScanInputWaitForPorch()
00142 //
00143 // ----------------------------------------------------------------------
00144 static void ScanInputWaitForPorch(void)
00145 {
00146     float f_analogValue = 5.0f;
00147 
00148     // While we're not seeing porch, loop
00149     if (f_analogValue > 0.5f)
00150     {
00151         return;
00152     }
00153         
00154     // Flag the fact that we're in porch
00155     b_inPorch = true;
00156     
00157     b_waitingForPorch = false;
00158     
00159     // Keep track of our scan frequency
00160     ScanInputUpdateScanFrequency();
00161     
00162     // Since we detected porch, start the plot over from the beginning
00163     u16_nextScanLine = 50;
00164     
00165     // The last height we consider to be 1 pixel on porch
00166     u16_lastHeight = 1;
00167     
00168     // Keep track of how many times we had to wait for locating porch
00169     // again after loosing it. Note that on power-up, if we are using
00170     // the test signal output, it is driven to porch co-incident with
00171     // the input test, so we start up with porch as the first sample
00172     ++u16_resyncCount;
00173 }
00174 
00175 // ----------------------------------------------------------------------
00176 // ScanInputGetNextValue()
00177 //
00178 //
00179 // ----------------------------------------------------------------------
00180 static void ScanInputGetNextValue(bool b_allowPlotting)
00181 {
00182     float f_analogValue = ScanInputGetInputVoltage();
00183 
00184     // Dows the input indicate that we are in porch?
00185     if (f_analogValue < 1.0f)
00186     {
00187         // Did we previously know that we were in porch?
00188         if (false == b_inPorch)
00189         {
00190             float f_plusFourPercent = 0.0f;
00191             
00192             // Flag the fact that we're in porch now
00193             b_inPorch = true;
00194     
00195             // Since we detected a new porch, start the plot over
00196             u16_nextScanLine = 49;
00197             
00198             // The last height we consider to be 1 pixel on porch
00199             u16_lastHeight = 1;
00200             
00201             // Update our scan frequency
00202             ScanInputUpdateScanFrequency();
00203             
00204             // Since our timing in this device is off, we add a correction
00205             f_plusFourPercent = (((float)u16_scanFrequency / 100.0f) * 4.3f);
00206             
00207             // Let the main module know what the scan rate is for display
00208             // and for testing and evaluating
00209             LaserMonMainInformScanInformation((uint16_t)((float)u16_scanFrequency + f_plusFourPercent), ++u32_scanCount);
00210         }
00211     }
00212     else
00213     {
00214         // We are in the ramp so flag the fact even if we already know
00215         b_inPorch = false;
00216         
00217         // Keep track of the scan frequency
00218         u16_msFromPorchToPorch++;
00219     }
00220 
00221     // Indicate the next line to plot this reading on to
00222     u16_nextScanLine++;
00223     
00224     // The display may be in use for other functionality so we
00225     // check to ensure that we are permitted to plot the input
00226     if (true == b_allowPlotting)
00227     {
00228         // Call the function which plots this value
00229         (void)ScanInputPlotThisValue(f_analogValue);
00230     }
00231     
00232     // Are we about to exceed the display?
00233     if (u16_nextScanLine >= (LCD_HEIGHT - 10))
00234     {
00235         // We have lost track of porch so we must search for it again
00236         b_waitingForPorch = true;
00237     }
00238     
00239     // Set the LED with whether we are at porch or not
00240     st_scanInputLED = b_inPorch;
00241 }
00242     
00243 // ----------------------------------------------------------------------
00244 // ScanInputThread()
00245 //
00246 // This is called once a millisecond however it is not a thread, the
00247 // thread class on this board ended up with timing that could not be
00248 // controlled so the main() loop calls us once a millisecond.
00249 //
00250 // ----------------------------------------------------------------------
00251 void ScanInputThread(bool b_allowPlotting)
00252 {
00253     // Are we waiting for porch synchronization?
00254     if (true == b_waitingForPorch)
00255     {
00256         // Start out searching for porch
00257         ScanInputWaitForPorch();
00258     }
00259 
00260     // Scan the signal coming in and optionally plot it
00261     ScanInputGetNextValue(b_allowPlotting);
00262 }
00263 
00264 // ----------------------------------------------------------------------
00265 // ScanInputInit()
00266 //
00267 // Initialize this module's locally-held data
00268 //
00269 // ----------------------------------------------------------------------
00270 void ScanInputInit(void)
00271 {
00272     // Start out with the LED turned ON
00273     st_scanInputLED = 1;
00274     
00275     // Initialize loc ally-held variables
00276     u16_nextScanLine       = 50;
00277     b_inPorch              = false;
00278     b_waitingForPorch      = true;
00279     u16_scanFrequency      = 0;    
00280     u16_resyncCount        = 0;
00281     u32_scanCount          = 0;
00282     u16_msFromPorchToPorch = 0;
00283 }
00284 
00285 // End of file
00286