circuitcellar.com
Magazine Support   Digital Library   Products & Services   Suppliers Directory 
 
 





 

November 2006, Issue 196

TV-Based Oscilloscope


by llya Mamontov


Start Simple Video Signal Video with the LPC2138 Video Algorithm Tricks Used Vertical Sync & Resolution Video for other Apps Oscilloscope Implementation Construction & Results Generate Video Sources and PDF

IMPLEMENTATION

The firmware consists of two parts, one for the video controller and one for the oscilloscope. All of the oscilloscope routines are in the Oscilloscope.c file posted on the Circuit Cellar FTP site. The main thread is in main.c file (see Figure 5).

(Click here to enlarge)

Figure 5—The GetKey procedure doesn’t suspend the loop; it just returns the code. Code = 0 when the keys aren’t pressed.

The main loop, which starts after initialization, manages data collection, visualization, and the device control. The special Menu flag assigns the current action for the Down and Up buttons. This flag is toggled with the Store button.

During normal operation (the Menu flag is 0), the Down and Up buttons make the timebase (horizontal scale) one step faster or slower. It’s achieved by processing several ADC samples (the “N” in Figure 5) to obtain a single display sample, not by a variation of the ADC sample rate. This allows the system to implement Envelope mode in which the highest value and the lowest value are calculated for each group of N ADC samples and stored as the data of a single display sample. On the plot, a vertical line between the two values is drawn so glitches or other high-frequency components of the signal will always be visible. A line between two adjacent samples is also drawn.

The data collection thread fills the special array of samples and signals to the main loop that the data is ready. The main loop then waits in the TV frame to start the visualization of data. This is necessary to prevent any problems caused by interference between the video controller’s refresh rate and the data collection rate. Four visualization algorithms are used for this purpose.

The first algorithm is for high data collection rates (i.e., horizontal scales). It waits until the data array is completely filled for one record view.

The second and third algorithms are for middle and low rates. They immediately visualize the current portion of data, which is collected between two adjacent TV frames. The difference between them is in a Trigger mode. At low collection rates, it isn’t necessary to wait for the trigger event because there is enough time to consider the graph. As a result, the trigger system is off here.

The fourth algorithm (transient recorder) is intended for super-slow data collection rates. It immediately draws the new sample and also uses Roll mode. This means that the each new sample causes a change in the record view offset and makes the space for the new sample. For measuring slowly changing signals, it looks nicer than Scan mode, where the display area is filled on the left side when the graph reaches the right side.

The data collection thread is written as an ADC interrupt service routine (ISR) that’s rich in functionality. It serves all of the visualization algorithms and uses the different conditions to start a data collection cycle. One condition is a trigger event that occurs when the signal crosses a threshold (trigger level). In this version, I detect the crossings of the rising parts of a curve. Comparing the current sample value and the trigger level value does this. The trigger value is calculated using the voltage from the rotating control located on the front panel.

The real signal has a noise component that causes false triggers near the cross points. The falling edge can be recognized as rising. To prevent this, I used a debouncing algorithm like the one commonly used for mechanical switches (see Figure 6, p. 55). Of course, this isn’t the only solution. Many devices use variable hysteresis algorithms or HF filters.

(Click here to enlarge)

Figure 6—This is the debouncing algorithm in the trigger mechanism.

The voltages from rotating controls also have a noise component, but another algorithm should be applied to kill it: math filtering. I implemented a simple procedure, moving average:

GetVoltages_TrigLevel=(GetVoltages
_TrigLevel+val)>>1; //New (filtered)
value of trigger level

Another function of the data collection thread is to create a delay between the trigger event and the start of data collection. This is equivalent to the beam offset function in analog oscilloscopes. The value for the delay is obtained like the value for a trigger level from the rotating control at the front panel.

The Store button stops the data collection process, captures the graph, and calls the Store menu. You can use the Down and Up buttons to move the special cursor along the row of numbers. The stored graphs are shown when you move the cursor to the required position. Each number corresponds to a stored graph that can be replaced by the current waveform when the Store button is repeatedly pressed. The Exit position causes the return to normal operation without saving anything.

Ample flash memory (512 KB in the LPC2138) enables you to implement a life-prolonging algorithm for a storage system. Normally, a single flash memory block has a limited number of erasure cycles. The data for one graph (1 KB) is considerably less than a block size (32 KB), so one flash memory block can contain a set of 32 (32 KB/1 KB) stored graphs. I use this technique when the flash memory block isn’t erased every time a new graph is stored. The new data is written in the free space, and the flash memory block is completely erased only when it’s filled by all 32 graphs. For visualization, a procedure seeks the last stored data and draws a graph.