Using the Analog in and LCD, turn the MBED into a simple Oscilloscope

Dependencies:   C12832_lcd DebounceIn mbed

/media/uploads/trichards1138/snapshot_20140609.jpg /media/uploads/trichards1138/snapshot_20140609_2.jpg

Introduction:

The MBED Oscilloscope uses the Analog Input on pin 17 to display connected waveforms from another MBED or a function generator. Note that the above left photo shows the Ain 1/8" phone jack on the side of the MBED being used as the input for a function generator. The crude photo on the right shows the waveform displayed on the MBED LCD screen (this is using the Application board available to plug the MBED processor board into. It includes the LCD screen as well as buttons, pots, temperature sensor, wifly socket, speaker, etc).

The waveform that is displayed on the MBED Oscilloscope is: /media/uploads/trichards1138/waveform.jpg This is from a Digilent combination function generator, Oscilloscope, and logic analyzer. The arbitrary waveform generator shown is one of the features of the unit and allows output of several types of signals from its analog output.

Notice that the frequency is set to 1kHz. The MBED Oscilloscope is set to 512 uS per division (due to display limitations, the settings cannot be displayed with the waveform). The displayed waveform shows a complete period in approximately 2 divisions. The scope is indicating that the period is 1mS or 1kHz.

Capabilities and Limitations:

The scope can display waveforms up to 5kHz with some clarity (although 5kHz is pushing its resolution 2-3kHz is a good practical limit). For displaying waveforms from a function generator running on another MBED, this is not a significant limitation. Except for the square-wave function, the function generator output of the MBED is around 1kHz realistically (the square-wave can output much higher frequencies since it only has two levels). (NOTE: this limitation is not strictly due to the ADC input. it also has to do with loop delay i.e. display update times...etc)

When an input is configured as an Analog input to the ADC, it is not 5V tolerant. The voltage on the pin must not exceed the reference-voltage-plus (set to approx 3V on the MBED board). So the amplitude input is limited to 3V (Although I've input signals at 3.3V with no immediate issues). Again this is not a significant limitation if debugging signals from another MBED. However, if you are using an external function generator, you must ensure you do not overdrive the input.

Usage:

Using the scope is fairly straight forward. Once you have the waveform source connected to pin 17 (either via the 1/8" phone jack or a wire directly connected to p17 through the header), the waveform should be displayed.

To change the time-base, use the right and left joystick buttons. You can check the current setting by pressing the middle button of the joystick. As long as you keep the middle button pressed, the settings page will be displayed. It shows the current settings of the time-base, vertical or volt-base, and the trigger mode. The photo below shows the settings page: /media/uploads/trichards1138/snapshot_20140609_8.jpg

Again, I apologize for the crudeness of the photo (a photographer I am not). Note that the time-base will change based on whether the grid is turned on. In the first photo above you see the grid lines painted on the display. You have the option to turn those off and there are instances where it is desirable. When this is done, the entire horizontal screen is viewed as one division. So the time-base will change accordingly.

Once you release the center button, the display will return to the waveform screen after about a second. If however you press the center button again within that window, you will be taken to the trigger selection window: /media/uploads/trichards1138/snapshot_20140609_9.jpg

There are five trigger modes:

1. Rising-Edge Main Signal (this finds the rising edge on the signal connected to pin 17)

2. Falling-Edge Main Signal (Same as above but finds the falling edge)

3. Rising-Edge Ext Signal (this finds the rising edge on the signal connected to pin 18)

4. Falling-Edge Ext Signal (Sam as in 3 for falling edge)

5. Auto or No Trigger (this does not look for a trigger - useful for dc signals)

Note that only three modes are displayed on the screen. The screen will scroll as you move the selection down. This is done with the "up" and "down" buttons on the joystick. Make your selection by pressing the center button again.

Once you make your trigger selection, you will then be taken to the grid selection menu: /media/uploads/trichards1138/snapshot_20140609_10.jpg

This allows the choice of whether to display the grid. Again there are situations you may want to disable the grid. Make the grid selection in the same way by pressing the center button of the joystick.

Once this selection is made, you will return the the waveform display.

The only additional control it connected to pot2. This is the pot furthest from the display. It controls the trigger level.

Know Issues:

1. The External triggering is not working at all right now. For some reason having two active signals connected to two different ADC inputs causes crosstalk that distorts both signals. I haven't looked into this yet so avoid using external triggering for the present. I will update when and if it is fixed. (any input or pointers would be appreciated)

2. The time base needs to be calibrated a little better. It is pretty close in most cases and good enough for rough work, but you would not want to keep time with it. It is a little like whack-a-mole and may never be perfect, but it can be improved.

3. The timeouts for the triggering mechanism may need some tweaking at some point as well. I think it is pretty good but may cause some fringe problems.

4. The trigger level is not currently displayed anywhere and should be part of the settings page. This would need to be added to a second settings page (and the menu system might get cumbersome at some point).

5. The pot is a little jittery for the trigger level. However, adding another menu to set it with the joystick will further push the problem in 4 of the menu system getting cumbersome. It may be good enough with some tweaks.

Future enhancements:

1. Getting the external triggering working is the first order of business.

2. Getting the time-base closer to reality will make things nicer.

3. I believe the grid would be nicer if the lines were dotted.

4. A classmate suggested adding FFT capabilities for a limited spectrum analyzer.

Any other suggestions?

Accessories:

I put together some faux scope probes by purchasing an inexpensive 3-foot audio cable (it is not shielded as the frequencies we are dealing with are fairly low). I cut this in half and soldered on some clips to connect the center and ground connections for the Ain 1/8" phone jack. The cable I got was actually stereo and I used a DMM to find which bare-wire was connected to pin 17 on the MBED. This accessory does make it nice in most cases.

However you can achieve the same results by connecting two wires directly one to pin 17 and the other to GND on the header connections of the application board directly to the input signal and GND of your waveform output.

Committer:
trichards1138
Date:
Mon Jun 09 07:31:58 2014 +0000
Revision:
4:8eeaddfebd37
Parent:
3:fe3bab42f046
final project code commit

Who changed what in which revision?

UserRevisionLine numberNew contents of line
trichards1138 4:8eeaddfebd37 1 //************************************************************************************
trichards1138 4:8eeaddfebd37 2 // Main.cpp - main entry point and code for MBED based Oscilloscope.
trichards1138 4:8eeaddfebd37 3 //
trichards1138 4:8eeaddfebd37 4 // Author: Terry Richards
trichards1138 4:8eeaddfebd37 5 // Date: June 10, 2014
trichards1138 4:8eeaddfebd37 6 //
trichards1138 0:9ccc4b6355a8 7 #include "mbed.h"
trichards1138 0:9ccc4b6355a8 8 #include "C12832_lcd.h"
trichards1138 1:4080ce288aea 9 #include "DebounceIn.h"
trichards1138 3:fe3bab42f046 10 #include "osc.h"
trichards1138 0:9ccc4b6355a8 11
trichards1138 3:fe3bab42f046 12 Serial pc(USBTX, USBRX);//debug output
trichards1138 3:fe3bab42f046 13 C12832_LCD LCD; //main LCD class
trichards1138 3:fe3bab42f046 14 AnalogIn Ain(p17); //main analog input
trichards1138 3:fe3bab42f046 15 AnalogIn Aintrig(p18); //External trigger input
trichards1138 1:4080ce288aea 16
trichards1138 1:4080ce288aea 17 //AnalogIn pot1(p19);
trichards1138 3:fe3bab42f046 18 AnalogIn pot2(p20); //sets trigger level
trichards1138 3:fe3bab42f046 19 DebounceIn Update(p14); //menu selection
trichards1138 3:fe3bab42f046 20 DebounceIn Up(p15); //menu selection and vert base set
trichards1138 3:fe3bab42f046 21 DebounceIn Down(p12); //menu selection and vert base set
trichards1138 3:fe3bab42f046 22 DebounceIn Left(p13); //horiz (time) base set
trichards1138 3:fe3bab42f046 23 DebounceIn Right(p16); //horiz (time) base set
trichards1138 2:71767eb23ac2 24
trichards1138 3:fe3bab42f046 25 //Repaint the LCD with the menu strings for the
trichards1138 3:fe3bab42f046 26 //current menu.
trichards1138 3:fe3bab42f046 27 //Inputs - An array of menustrings and the first string
trichards1138 3:fe3bab42f046 28 // to put on the display
trichards1138 3:fe3bab42f046 29 //Outputs - a freshly painted display with the menu
trichards1138 3:fe3bab42f046 30 #define FIRST_TEXTLINE 3 //Positions on the LCD
trichards1138 3:fe3bab42f046 31 #define SECOND_TEXTLINE 13
trichards1138 3:fe3bab42f046 32 #define THIRD_TEXTLINE 23
trichards1138 4:8eeaddfebd37 33 int rePaint(char menustrings[][MENU_LENGTH], int first)
trichards1138 2:71767eb23ac2 34 {
trichards1138 3:fe3bab42f046 35 LCD.cls();
trichards1138 3:fe3bab42f046 36 LCD.locate( 0, FIRST_TEXTLINE );
trichards1138 3:fe3bab42f046 37 LCD.printf(menustrings[first]);
trichards1138 3:fe3bab42f046 38 LCD.locate( 0, SECOND_TEXTLINE );
trichards1138 3:fe3bab42f046 39 LCD.printf(menustrings[first+1]);
trichards1138 3:fe3bab42f046 40 LCD.locate( 0, THIRD_TEXTLINE );
trichards1138 3:fe3bab42f046 41 LCD.printf(menustrings[first+2]);
trichards1138 3:fe3bab42f046 42 return 0;
trichards1138 2:71767eb23ac2 43 }
trichards1138 3:fe3bab42f046 44 // Display a menu and allow scrolling until user
trichards1138 3:fe3bab42f046 45 // makes a selection. Show the current selection
trichards1138 3:fe3bab42f046 46 // with a row of asterisks (which scroll with the
trichards1138 3:fe3bab42f046 47 // up and down buttons).
trichards1138 3:fe3bab42f046 48 // Inputs - The current selection and window min
trichards1138 3:fe3bab42f046 49 // and max and strings for the current menu.
trichards1138 3:fe3bab42f046 50 // These will change depending on the menu
trichards1138 3:fe3bab42f046 51 // being displayed. The sel_start is where
trichards1138 3:fe3bab42f046 52 // the selection asterisks start for the
trichards1138 3:fe3bab42f046 53 // current display stings.
trichards1138 3:fe3bab42f046 54 // Outputs - A selection from the user from the current
trichards1138 3:fe3bab42f046 55 // menu.
trichards1138 3:fe3bab42f046 56 //
trichards1138 3:fe3bab42f046 57 #define CLEARTORUN 6
trichards1138 3:fe3bab42f046 58 #define SETTORUN 4
trichards1138 3:fe3bab42f046 59 int display_menu( int *cur_sel,
trichards1138 3:fe3bab42f046 60 int *cur_min,
trichards1138 3:fe3bab42f046 61 int *cur_max,
trichards1138 4:8eeaddfebd37 62 char menustrings[][MENU_LENGTH],
trichards1138 3:fe3bab42f046 63 int sel_start,
trichards1138 3:fe3bab42f046 64 int menu_end )
trichards1138 2:71767eb23ac2 65 {
trichards1138 3:fe3bab42f046 66 while( 1 ) {
trichards1138 2:71767eb23ac2 67 if( Down ) {
trichards1138 3:fe3bab42f046 68 if( *cur_sel != menu_end ) {
trichards1138 3:fe3bab42f046 69 memset( &menustrings[*cur_sel][sel_start-1], ' ' , CLEARTORUN);
trichards1138 3:fe3bab42f046 70 *cur_sel += 1;
trichards1138 3:fe3bab42f046 71 memset( &menustrings[*cur_sel][sel_start], '*', SETTORUN);
trichards1138 3:fe3bab42f046 72 if( *cur_sel > *cur_max ) {
trichards1138 3:fe3bab42f046 73 *cur_max += 1;
trichards1138 3:fe3bab42f046 74 *cur_min += 1;
trichards1138 3:fe3bab42f046 75 rePaint(menustrings, *cur_min);
trichards1138 2:71767eb23ac2 76 }
trichards1138 2:71767eb23ac2 77 else
trichards1138 3:fe3bab42f046 78 rePaint(menustrings, *cur_min);
trichards1138 2:71767eb23ac2 79 }
trichards1138 2:71767eb23ac2 80 while( Down )
trichards1138 2:71767eb23ac2 81 wait_ms(50);
trichards1138 2:71767eb23ac2 82 }
trichards1138 2:71767eb23ac2 83 if( Up ) {
trichards1138 3:fe3bab42f046 84 if( *cur_sel != 0 ) {
trichards1138 3:fe3bab42f046 85 memset( &menustrings[*cur_sel][sel_start-1], ' ', CLEARTORUN);
trichards1138 3:fe3bab42f046 86 *cur_sel -= 1;
trichards1138 3:fe3bab42f046 87 memset( &menustrings[*cur_sel][sel_start], '*', SETTORUN);
trichards1138 3:fe3bab42f046 88 if( *cur_sel < *cur_min ) {
trichards1138 3:fe3bab42f046 89 *cur_max -= 1;
trichards1138 3:fe3bab42f046 90 *cur_min -= 1;
trichards1138 3:fe3bab42f046 91 rePaint(menustrings, *cur_min);
trichards1138 2:71767eb23ac2 92 }
trichards1138 2:71767eb23ac2 93 else
trichards1138 3:fe3bab42f046 94 rePaint(menustrings, *cur_min);
trichards1138 2:71767eb23ac2 95 }
trichards1138 2:71767eb23ac2 96 while( Up )
trichards1138 3:fe3bab42f046 97 wait_ms(50); //Smooth things out
trichards1138 2:71767eb23ac2 98 }
trichards1138 3:fe3bab42f046 99 if( Update ) { //When user presses center button, cur_sel has his selection
trichards1138 3:fe3bab42f046 100 return 0;
trichards1138 2:71767eb23ac2 101 }
trichards1138 2:71767eb23ac2 102 }
trichards1138 2:71767eb23ac2 103 }
trichards1138 3:fe3bab42f046 104 //Update the vertical and horizontal bases when the user presses the up or down joystick
trichards1138 3:fe3bab42f046 105 // buttons. The horizontal is the time base, and the vertical is the volt base.
trichards1138 3:fe3bab42f046 106 // Inputs - none
trichards1138 3:fe3bab42f046 107 // Outputs - updated vertical and horizontal bases
trichards1138 3:fe3bab42f046 108 #define VBASEMAX 17
trichards1138 1:4080ce288aea 109 #define TBASEMAX 9
trichards1138 1:4080ce288aea 110 void Update_params(void)
trichards1138 1:4080ce288aea 111 { //divisions 1=128uS, 5=640uS, 10=1280uS, 20=2560uS, 50=6.4mS, 100=12.8mS, 500=64mS, 1000=128mS
trichards1138 1:4080ce288aea 112 unsigned int next_tbase[] = { 1, 5, 10, 20, 50, 100, 500, 700, 1000 };
trichards1138 3:fe3bab42f046 113 float next_vbase[] = { 0.2, 0.4, 0.6, 0.8, 1.0, 1.4, 1.8, 2.0, 2.4, 2.8, 3.0, 3.5, 4.0, 4.5, 5.0, 5.5, 6.0 };
trichards1138 3:fe3bab42f046 114 static int vsel=4, tsel=0;
trichards1138 1:4080ce288aea 115 if( Up ) {
trichards1138 1:4080ce288aea 116 while( Up )
trichards1138 1:4080ce288aea 117 wait_ms(1);
trichards1138 3:fe3bab42f046 118 vsel++;
trichards1138 1:4080ce288aea 119 if( vsel == VBASEMAX )
trichards1138 1:4080ce288aea 120 vsel = VBASEMAX-1;
trichards1138 3:fe3bab42f046 121 volt_base = next_vbase[vsel];
trichards1138 1:4080ce288aea 122 }
trichards1138 1:4080ce288aea 123 if( Down ) {
trichards1138 1:4080ce288aea 124 while( Down )
trichards1138 1:4080ce288aea 125 wait_ms(1);
trichards1138 3:fe3bab42f046 126 vsel--;
trichards1138 1:4080ce288aea 127 if( vsel == -1 )
trichards1138 3:fe3bab42f046 128 vsel = 0;
trichards1138 3:fe3bab42f046 129 volt_base = next_vbase[vsel];
trichards1138 1:4080ce288aea 130 }
trichards1138 1:4080ce288aea 131 if( Right ) {
trichards1138 1:4080ce288aea 132 while( Right )
trichards1138 1:4080ce288aea 133 wait_ms(1);
trichards1138 3:fe3bab42f046 134 tsel++;
trichards1138 1:4080ce288aea 135 if( tsel == TBASEMAX )
trichards1138 1:4080ce288aea 136 tsel = TBASEMAX-1;
trichards1138 3:fe3bab42f046 137 time_base = next_tbase[tsel];
trichards1138 1:4080ce288aea 138 }
trichards1138 1:4080ce288aea 139 if( Left ) {
trichards1138 1:4080ce288aea 140 while( Left )
trichards1138 1:4080ce288aea 141 wait_ms(1);
trichards1138 3:fe3bab42f046 142 tsel--;
trichards1138 1:4080ce288aea 143 if( tsel == -1 )
trichards1138 1:4080ce288aea 144 tsel = 0;
trichards1138 3:fe3bab42f046 145 time_base = next_tbase[tsel];
trichards1138 1:4080ce288aea 146 }
trichards1138 3:fe3bab42f046 147 tbsel = tsel; //Global copy for menu
trichards1138 4:8eeaddfebd37 148 //TODO: may need to add menu to update the trigger
trichards1138 4:8eeaddfebd37 149 //level with the joystick. Pot is a little twitchy
trichards1138 3:fe3bab42f046 150 trigger = pot2.read(); //set the trigger level
trichards1138 3:fe3bab42f046 151 }
trichards1138 3:fe3bab42f046 152 // Find an edge (either rising or falling based on trigger mode) and use
trichards1138 3:fe3bab42f046 153 // it to trigger a sweep of the scope display. The search for an edge is
trichards1138 3:fe3bab42f046 154 // timed in case there is not a periodic waveform currently connected to
trichards1138 3:fe3bab42f046 155 // Ain. This ensures the menu is not delayed too much.
trichards1138 3:fe3bab42f046 156 // Inputs - none
trichards1138 3:fe3bab42f046 157 // Outputs - time sync with a correct edge of the waveform
trichards1138 3:fe3bab42f046 158 // or quick return if "no_trigger" is selected.
trichards1138 4:8eeaddfebd37 159 //The trigger loops below take approx 20us per loop
trichards1138 4:8eeaddfebd37 160 #define TRIG_TIMEOUT 1000 //1000*20us=20milliseconds
trichards1138 3:fe3bab42f046 161 bool get_trigger(void)
trichards1138 3:fe3bab42f046 162 {
trichards1138 4:8eeaddfebd37 163 //add more timeout as the timebase increases
trichards1138 4:8eeaddfebd37 164 //TODO: may need to be calibrated more fine grain at some point
trichards1138 4:8eeaddfebd37 165 int timeout=TRIG_TIMEOUT + (tbsel*tbsel*TRIG_TIMEOUT);
trichards1138 3:fe3bab42f046 166 //capture a rising edge on the main signal - default mode
trichards1138 3:fe3bab42f046 167 if( trigger_mode == main_rising_edge ) {
trichards1138 4:8eeaddfebd37 168 while( (Ain.read() > trigger) && timeout )
trichards1138 4:8eeaddfebd37 169 timeout--;
trichards1138 3:fe3bab42f046 170 if( !timeout )
trichards1138 3:fe3bab42f046 171 return false;
trichards1138 3:fe3bab42f046 172 else
trichards1138 4:8eeaddfebd37 173 timeout = TRIG_TIMEOUT + (tbsel*TRIG_TIMEOUT);
trichards1138 4:8eeaddfebd37 174 while( (Ain.read() < trigger) && timeout )
trichards1138 4:8eeaddfebd37 175 timeout--;
trichards1138 3:fe3bab42f046 176 if( !timeout )
trichards1138 3:fe3bab42f046 177 return false;
trichards1138 3:fe3bab42f046 178 else
trichards1138 3:fe3bab42f046 179 return true;
trichards1138 3:fe3bab42f046 180 //capture a falling edge on the main signal
trichards1138 3:fe3bab42f046 181 } else if( trigger_mode == main_falling_edge ) {
trichards1138 4:8eeaddfebd37 182 while( (Ain.read() < trigger) && timeout )
trichards1138 4:8eeaddfebd37 183 timeout--;
trichards1138 3:fe3bab42f046 184 if( !timeout )
trichards1138 3:fe3bab42f046 185 return false;
trichards1138 3:fe3bab42f046 186 else
trichards1138 4:8eeaddfebd37 187 timeout = TRIG_TIMEOUT + (tbsel*TRIG_TIMEOUT);
trichards1138 4:8eeaddfebd37 188 while( (Ain.read() > trigger) && timeout )
trichards1138 4:8eeaddfebd37 189 timeout--;
trichards1138 3:fe3bab42f046 190 if( !timeout )
trichards1138 3:fe3bab42f046 191 return false;
trichards1138 3:fe3bab42f046 192 else
trichards1138 3:fe3bab42f046 193 return true;
trichards1138 3:fe3bab42f046 194 //capture a rising edge on an external signal
trichards1138 3:fe3bab42f046 195 } else if( trigger_mode == ext_rising_edge ) {
trichards1138 4:8eeaddfebd37 196 while( (Aintrig.read() > trigger) && timeout )
trichards1138 4:8eeaddfebd37 197 timeout--;
trichards1138 3:fe3bab42f046 198 if( !timeout )
trichards1138 3:fe3bab42f046 199 return false;
trichards1138 3:fe3bab42f046 200 else
trichards1138 4:8eeaddfebd37 201 timeout = TRIG_TIMEOUT + (tbsel*TRIG_TIMEOUT);
trichards1138 4:8eeaddfebd37 202 while( (Aintrig.read() < trigger) && timeout )
trichards1138 4:8eeaddfebd37 203 timeout--;
trichards1138 3:fe3bab42f046 204 if( !timeout )
trichards1138 3:fe3bab42f046 205 return false;
trichards1138 3:fe3bab42f046 206 else
trichards1138 3:fe3bab42f046 207 return true;
trichards1138 3:fe3bab42f046 208 //capture a falling edge on an external signal
trichards1138 3:fe3bab42f046 209 } else if( trigger_mode == ext_falling_edge ) {
trichards1138 4:8eeaddfebd37 210 while( (Aintrig.read() < trigger) && timeout )
trichards1138 4:8eeaddfebd37 211 timeout--;
trichards1138 3:fe3bab42f046 212 if( !timeout )
trichards1138 3:fe3bab42f046 213 return false;
trichards1138 3:fe3bab42f046 214 else
trichards1138 4:8eeaddfebd37 215 timeout = TRIG_TIMEOUT + (tbsel*TRIG_TIMEOUT);
trichards1138 4:8eeaddfebd37 216 while( (Aintrig.read() > trigger) && timeout )
trichards1138 4:8eeaddfebd37 217 timeout--;
trichards1138 3:fe3bab42f046 218 if( !timeout )
trichards1138 3:fe3bab42f046 219 return false;
trichards1138 3:fe3bab42f046 220 else
trichards1138 3:fe3bab42f046 221 return true;
trichards1138 3:fe3bab42f046 222 } else if( trigger_mode == auto_no_trigger )
trichards1138 3:fe3bab42f046 223 //if auto no-trigger...do nothing. just return
trichards1138 3:fe3bab42f046 224 return true;
trichards1138 3:fe3bab42f046 225 return false; //Can't get here, but silence the warning
trichards1138 0:9ccc4b6355a8 226 }
trichards1138 0:9ccc4b6355a8 227
trichards1138 3:fe3bab42f046 228 //This routine only gets called if the "draw grid" mode is selected. The
trichards1138 3:fe3bab42f046 229 // default is "no grid" so the display is a continuous display with no
trichards1138 3:fe3bab42f046 230 // lines. The grid is more useful for some waveforms than others. It is
trichards1138 3:fe3bab42f046 231 // a matter of taste as to if the user wants to display with or without grid.
trichards1138 3:fe3bab42f046 232 // Inputs - none
trichards1138 3:fe3bab42f046 233 // Outputs - the display with grid lines painted.
trichards1138 3:fe3bab42f046 234 #define NUMHORIZPIXELS 128
trichards1138 3:fe3bab42f046 235 #define NUMVERTPIXELS 32
trichards1138 3:fe3bab42f046 236 #define FIRSTVERT 21
trichards1138 3:fe3bab42f046 237 #define SECONDVERT 42
trichards1138 3:fe3bab42f046 238 #define THIRDVERT 63
trichards1138 3:fe3bab42f046 239 #define FOURTHVERT 84
trichards1138 3:fe3bab42f046 240 #define FIFTHVERT 105
trichards1138 3:fe3bab42f046 241 #define FIRSTHORIZ 11
trichards1138 3:fe3bab42f046 242 #define SECONDHORIZ 22
trichards1138 3:fe3bab42f046 243 void place_grid(void)
trichards1138 3:fe3bab42f046 244 {
trichards1138 3:fe3bab42f046 245 LCD.line(FIRSTVERT, 0, FIRSTVERT, NUMVERTPIXELS-1, 1);
trichards1138 3:fe3bab42f046 246 LCD.line(SECONDVERT, 0, SECONDVERT, NUMVERTPIXELS-1, 1);
trichards1138 3:fe3bab42f046 247 LCD.line(THIRDVERT, 0, THIRDVERT, NUMVERTPIXELS-1, 1);
trichards1138 3:fe3bab42f046 248 LCD.line(FOURTHVERT, 0, FOURTHVERT, NUMVERTPIXELS-1, 1);
trichards1138 3:fe3bab42f046 249 LCD.line(FIFTHVERT, 0, FIFTHVERT, NUMVERTPIXELS-1, 1);
trichards1138 3:fe3bab42f046 250 LCD.line(0, FIRSTHORIZ, NUMHORIZPIXELS-1, FIRSTHORIZ, 1);
trichards1138 3:fe3bab42f046 251 LCD.line(0, SECONDHORIZ, NUMHORIZPIXELS-1, SECONDHORIZ, 1);
trichards1138 3:fe3bab42f046 252 }
trichards1138 3:fe3bab42f046 253
trichards1138 3:fe3bab42f046 254 void menu(void)
trichards1138 0:9ccc4b6355a8 255 {
trichards1138 3:fe3bab42f046 256 int timeout=100;
trichards1138 3:fe3bab42f046 257 //Corrects the faster time bases for loop delay
trichards1138 4:8eeaddfebd37 258 //TODO: These need to be further calibrated. Maybe re-architected.
trichards1138 3:fe3bab42f046 259 unsigned int tbase_correction[] = { 24, 6, 3, 3, 1, 1, 1, 1, 1 };
trichards1138 3:fe3bab42f046 260 //While user has center button pressed, display the settings
trichards1138 3:fe3bab42f046 261 while( Update ) {
trichards1138 3:fe3bab42f046 262 LCD.cls();
trichards1138 3:fe3bab42f046 263 LCD.locate( 0, FIRST_TEXTLINE );
trichards1138 3:fe3bab42f046 264 LCD.printf("Vertical Base: %3.1f V/div", draw_grid? volt_base/3: volt_base );
trichards1138 3:fe3bab42f046 265 LCD.locate( 0, SECOND_TEXTLINE );
trichards1138 3:fe3bab42f046 266 LCD.printf("Horiz Base: %d uS/div", draw_grid? (((time_base*tbase_correction[tbsel])*128)/6): ((time_base*24)*128));
trichards1138 3:fe3bab42f046 267 LCD.locate( 0, THIRD_TEXTLINE );
trichards1138 3:fe3bab42f046 268 switch( trigger_mode ) {
trichards1138 3:fe3bab42f046 269 case main_rising_edge:
trichards1138 3:fe3bab42f046 270 LCD.printf("Trigger Mode: Main rising");
trichards1138 3:fe3bab42f046 271 break;
trichards1138 3:fe3bab42f046 272 case main_falling_edge:
trichards1138 3:fe3bab42f046 273 LCD.printf("Trigger Mode: Main falling");
trichards1138 3:fe3bab42f046 274 break;
trichards1138 3:fe3bab42f046 275 case ext_rising_edge:
trichards1138 3:fe3bab42f046 276 LCD.printf("Trigger Mode: Ext rising");
trichards1138 3:fe3bab42f046 277 break;
trichards1138 3:fe3bab42f046 278 case ext_falling_edge:
trichards1138 3:fe3bab42f046 279 LCD.printf("Trigger Mode: Ext falling");
trichards1138 3:fe3bab42f046 280 break;
trichards1138 3:fe3bab42f046 281 case auto_no_trigger:
trichards1138 3:fe3bab42f046 282 LCD.printf("Trigger Mode: No Trigger");
trichards1138 3:fe3bab42f046 283 }
trichards1138 3:fe3bab42f046 284 wait_ms(200);
trichards1138 3:fe3bab42f046 285 }
trichards1138 3:fe3bab42f046 286 //Wait a while in case user presses center again
trichards1138 3:fe3bab42f046 287 while( !Update ) {
trichards1138 3:fe3bab42f046 288 --timeout;
trichards1138 3:fe3bab42f046 289 if( !timeout )
trichards1138 3:fe3bab42f046 290 break; //If we hit time out, break out
trichards1138 3:fe3bab42f046 291 wait_ms(10);
trichards1138 3:fe3bab42f046 292 }
trichards1138 3:fe3bab42f046 293 if( timeout ) { //If we didn't time out...continue
trichards1138 3:fe3bab42f046 294 timeout = 100; //If we did..we just exit and go back to scope
trichards1138 3:fe3bab42f046 295 //User may be hitting center again, if so display tigger menu
trichards1138 3:fe3bab42f046 296 if( Update ) { //user hit update again
trichards1138 3:fe3bab42f046 297 while( Update )
trichards1138 3:fe3bab42f046 298 wait_ms(1); //ensure we only process on hit
trichards1138 3:fe3bab42f046 299 rePaint(trigstrings, trig_cur_min);
trichards1138 3:fe3bab42f046 300 //Get a new trigger mode
trichards1138 3:fe3bab42f046 301 display_menu(&trig_cur_sel, &trig_cur_min, &trig_cur_max,
trichards1138 3:fe3bab42f046 302 trigstrings, SELECTION_START, MAX_TRIG_MENU );
trichards1138 3:fe3bab42f046 303 trigger_mode = (trigger_mode_type)trig_cur_sel;
trichards1138 3:fe3bab42f046 304 }
trichards1138 3:fe3bab42f046 305 while( !Update ) { //See if user wants to update grid settings
trichards1138 3:fe3bab42f046 306 --timeout;
trichards1138 3:fe3bab42f046 307 if( !timeout )
trichards1138 3:fe3bab42f046 308 break; //If we hit time out, break out
trichards1138 3:fe3bab42f046 309 wait_ms(10);
trichards1138 3:fe3bab42f046 310 }
trichards1138 3:fe3bab42f046 311 if( timeout ) { //If we didn't time out..continue
trichards1138 3:fe3bab42f046 312 if( Update ) { //user hit update again
trichards1138 3:fe3bab42f046 313 while( Update )
trichards1138 3:fe3bab42f046 314 wait_ms(1); //ensure we only process one hit
trichards1138 3:fe3bab42f046 315 rePaint(gridstrings, grid_cur_min);
trichards1138 3:fe3bab42f046 316 //Get new grid settings
trichards1138 3:fe3bab42f046 317 display_menu(&grid_cur_sel, &grid_cur_min, &grid_cur_max,
trichards1138 3:fe3bab42f046 318 gridstrings, SELECTION_START, MAX_GRID_MENU );
trichards1138 3:fe3bab42f046 319 if( grid_cur_sel )
trichards1138 3:fe3bab42f046 320 draw_grid = true;
trichards1138 3:fe3bab42f046 321 else
trichards1138 3:fe3bab42f046 322 draw_grid = false;
trichards1138 3:fe3bab42f046 323 }
trichards1138 3:fe3bab42f046 324 while( Update ) //trickle out last switch hits
trichards1138 3:fe3bab42f046 325 wait_ms(1);
trichards1138 3:fe3bab42f046 326 }
trichards1138 1:4080ce288aea 327 }
trichards1138 0:9ccc4b6355a8 328 }
trichards1138 0:9ccc4b6355a8 329
trichards1138 3:fe3bab42f046 330 //Main entry point and control loop for the program. All routines
trichards1138 3:fe3bab42f046 331 // are called from here (and return here).
trichards1138 3:fe3bab42f046 332 //
trichards1138 1:4080ce288aea 333 int main()
trichards1138 0:9ccc4b6355a8 334 {
trichards1138 3:fe3bab42f046 335 pc.baud(115200); //debug output
trichards1138 3:fe3bab42f046 336 bool skip_first_trig = false;
trichards1138 0:9ccc4b6355a8 337 unsigned int i;
trichards1138 0:9ccc4b6355a8 338 unsigned int h = LCD.height()-2, w = LCD.width(), hhh;
trichards1138 0:9ccc4b6355a8 339 while(true) { // thread loop
trichards1138 4:8eeaddfebd37 340 if( get_trigger() || skip_first_trig ) { //go get a trigger
trichards1138 3:fe3bab42f046 341 LCD.cls();
trichards1138 3:fe3bab42f046 342 LCD.rect(0,0,NUMHORIZPIXELS-1, NUMVERTPIXELS-1, 1); //place boarder
trichards1138 3:fe3bab42f046 343 if(draw_grid)
trichards1138 3:fe3bab42f046 344 place_grid();
trichards1138 3:fe3bab42f046 345 for (i=0; i<w; i++) { //do a sweep
trichards1138 3:fe3bab42f046 346 //scale the incoming signal to the screen size and vertical
trichards1138 3:fe3bab42f046 347 //base setting.
trichards1138 3:fe3bab42f046 348 hhh = (int)((h)-(h*volt_base*Ain.read()));
trichards1138 3:fe3bab42f046 349 //does not paint the screen
trichards1138 3:fe3bab42f046 350 LCD.pixel(i, hhh ,1); // print pixel
trichards1138 3:fe3bab42f046 351 //implements the horizontal or time-base
trichards1138 3:fe3bab42f046 352 wait_us(time_base);
trichards1138 3:fe3bab42f046 353 }
trichards1138 3:fe3bab42f046 354 //paint the screen
trichards1138 3:fe3bab42f046 355 LCD.copy_to_lcd(); // LCD.pixel does not update the lcd
trichards1138 0:9ccc4b6355a8 356 }
trichards1138 3:fe3bab42f046 357 skip_first_trig = false;
trichards1138 4:8eeaddfebd37 358 Update_params(); //see if we changed time or volt bases
trichards1138 2:71767eb23ac2 359 if( Update ) { //Hit the center button once to display stats
trichards1138 3:fe3bab42f046 360 skip_first_trig = true; //ensure quick screen update after menu
trichards1138 4:8eeaddfebd37 361 menu(); //go get user input..Now on HID time
trichards1138 3:fe3bab42f046 362 } else
trichards1138 3:fe3bab42f046 363 wait_ms(50); //Delay to smooth twitchy waveforms
trichards1138 0:9ccc4b6355a8 364 }
trichards1138 0:9ccc4b6355a8 365 }
trichards1138 0:9ccc4b6355a8 366
trichards1138 4:8eeaddfebd37 367 #if 0
trichards1138 4:8eeaddfebd37 368 Testing:
trichards1138 4:8eeaddfebd37 369 1. You need another MBED with a function generator running, or a suitable waveform generator (suitable in
trichards1138 4:8eeaddfebd37 370 that it must generate waveforms in the frequency band of 1Hz to 2kHz, and amplitudes between 0 and 3.3 Volts).
trichards1138 4:8eeaddfebd37 371 2. Waveforms greater than 2kHz are displayable on the MBED Oscilloscope, but are not very interesting. They
trichards1138 4:8eeaddfebd37 372 are two fast for the MBED processor to keep up with. The Analog Input takes 20 uS to get a reading so it is
trichards1138 4:8eeaddfebd37 373 limited in the frequencies it can handle.
trichards1138 4:8eeaddfebd37 374 3. See the writeup on the MBED site for instructons for the menuing system that sets the scope parameters.
trichards1138 4:8eeaddfebd37 375 4. Connect the output of the other MBED or the function generator to pin 17 of the MBED running the Osc
trichards1138 4:8eeaddfebd37 376 software, or use a "scope probe" connected to the Ain 1/8 phone jack on the side of the MBED running the Osc
trichards1138 4:8eeaddfebd37 377 software. Note that the other jack (Aout) can be used as an external trigger if desired, however the two jacks are
trichards1138 4:8eeaddfebd37 378 so close together on the application board that you will need to find very small 1/8 phone jacks to fit two
trichards1138 4:8eeaddfebd37 379 together side-by-side.
trichards1138 4:8eeaddfebd37 380 5. "Scope probes" can be constructed by obtaining an audio cable (stereo or mono will work), cut it in half so
trichards1138 4:8eeaddfebd37 381 you have two cables with bare wires on one end and an 1/8 phone jack on the other. Use a DMM to determine the
trichards1138 4:8eeaddfebd37 382 bare wires that are connected to the p17 and GND on the MBED (you can do this most easily by plugging the cable
trichards1138 4:8eeaddfebd37 383 into the Ain jack and connecting one probe of the DMM to p17 and the other to the bare wires and see which one
trichards1138 4:8eeaddfebd37 384 has continuity. Then do the same with GND). Now solder a clip to both the p17 wire and the GND wire so you
trichards1138 4:8eeaddfebd37 385 can connect these to your device-under-test.
trichards1138 4:8eeaddfebd37 386 #endif