To give the user a better explanation of our project we will discuss in detail some of the more interesting parts of our code. All topics will not be covered since many, like the denouncer, have been well covered in previous labs and others are more tedious than illustrative. Refer to the Appendix 1 for code comments and listing.
VT 100 Formatting
The display to Hyper Terminal can be extensively formatted using the VT100 code set. These codes, usually beginning with the escape character can do everything from setting screen location, to changing display modes, to erasing the screen. We wrote a number of macros at the beginning of our code to execute these commands. They are all very similar so lets look at BigDowner as an illustration. This macro moves the curser a distance down and to the right of the home position according to macro input. We load the characters 0x27 and '[' into a string and follow it by the x and y change represented in ASCII and separated by character code 0x59. We then terminate this string with the character code 'H'. This will move the curser x spaces to the right from home position and y lines down.
Time / Division Setting
This fairly complicated section of our code is used to set the time per division calibration as one of 6 predefined values .1 sec, 50 ms, 20 ms, 10 ms, 5ms,or 2 ms. Note we could to have gone to ever faster times but that would have required a faster CPU. Set at 2 ms we have a compare match on Timer 1 or about 80 cycles, close to our Timer 1 length. Though we could have acquired one we felt we the change would not have allowed us to demonstrate anything new.
We used two strings to store Timer1 compare match values, low and high, for the 6 time per division calibrations and index through them by the appropriate factor depending on user selection. Note we do not have to change the Timer1 prescaler since we do not see a time per division of less than .1 sec being useful for practical purposes. The Timer 1 compare match values were calculated on the premise that if we had a input signal with wavelength equal to the time/division setting we would want a minimum of 10 samples per division. These calculations yielded the following results
To display the appropriate text labels to the screen we created an array with a all the labels, 6 characters follows by a null terminator, in it. We then indexed through this array by 7 and outputted to the UART, the UART code detecting the end of the label based on null termination
We choose to sample all data in the Timer1 ISR and write it to RAM for manipulation later. The main reason we did this is that the data manipulation, especially the formatting for the screen which involves a divide, takes many clock cycles. If we tried to do this on the fly in the ISR we would have a dramatically higher minimum time per division.
The data takes up 160 blocks since we have 80 samples and each point i has both a high and a low bit. We would have liked to have taken more samples (we could have easily used external RAM to store them) but the limiting factor was the width of the Hyper Terminal screen under the VT100 instruction set. We would have had t create a Java applet to obtain better resolution and given the complexity of the project already it would be too much.
In order to generate the waveform we took the extended data set of 80 points from RAM which range from 0-4 volts and did an integer division to by 200mv to receive a value between 0 and 20. We then called our Convert_Screen subroutine and converted this number into two separate ASCII values. This subroutine is very similar to the decimal to ASCII subroutine we wrote in earlier labs, but writes to registers rather than memory. These register values are fed into the Bigdowner macro along with an x index (also converted to ASCII) value to determine our screen location to print a point. We print a point using the standard UART commands and then loop back.
The screen was drawn through extensive use of theVT100 formatting macros we wrote and described above. We looped through and to draw the grid separating by 10 lines each way. This gives us a resolution of 200mv and a range of 0-4 volts in the y direction and a resolution of up to .2 ms in the x direction with our lowest time per division setting. Note we would have liked to have used the extended ASCII instruction set since it contains a number of boarder and line characters much cleaner looking than the basic ASCII set. Unfortunately we determined that they are not compatible with the UART and the VT100 instruction set. We were limited to ASCII character lower than 128.
Vpp and Vave
We calculated Vpp and Vave to make the output of our oscilloscope more illustrative. Vpp was found by updating a max and min register in the TIMER1 ISR each time a sample was taken and later subtracting the two values. Similarly Vave was found by summing all the data points and then performing a divide. We considered displaying Vrms, but it would contain divides, multiplies and a square root. This would add a large amount of code overhead and our scope already has a significant delay due to the 9600 baud of the UART and the extensive output across it. It was a question of how long we wanted the user to wait from pressing the sample button to seeing the waveform.