'************************************************************************* ' AVV.BS2 Rev 0.4 ' ' Joe Everhart, N2CC ' 214 New Jersey Rd ' Brooklawn, NJ 08030 ' e-mail: n2cx@voicenet.com ' ' This program is written for TTAM13 to appear in the Oct 2002 issue of ' ARCI's QRP Quarterly. It is an expansion of the Audio Voltmeter from ' Quickie 43 that appears in the same issue. ' ' AVV stands for Audio/Visual Voltmeter. It is an 8-bit digital voltmeter ' using an ADC0831 in conjunction with a Parallax BASIC STAMP 2 chip, an ' LCD readout module and a loudspeaker. ' ' The AVV measures 0-2VDC and ouputs a 3-digit numeric display. The LCD ' output is always active while two audible "display" options can be ' chosen. The first is a variable pitch output that varies linearly within ' approx. 300 to 300 Hz and is proportional to the voltage value measured. ' The second audible output is sent as 3 digits of MORSE code at approx. ' 12 wpm. ' ' The audible outputs are chosen by pressing a pushbutton. Operation ' cycles through three modes - no audible output, variable tone output and ' MORSE audible output. ' ' Beginning with rev 0.4 this program uses the QuickieLab prototyping system ' described by George Heron, N2APB in the October 2002 QRP Quarterly. ' The "QL" adds a Ubicom SX-28 I/O Extender (IOX) to the BS-2 to provide ' a serial interface expansion. The IOX interfaces a '12-button keypad, ' a frequency counter, the ADC0831 ADC, a two-line LCD readout and a ' digital potentiometer. ' ' The original implementation was made using the Parallax Board of ' Education. The BOE provides a minimal BS-2 along with an Experimenter's ' Plugboard for connection of external components. The original setup was ' made on the BOE with the ADC and loudspeaker interfaced directly to . the BS2 chip. Once the algorithms were verified, the program was ' rewritten to operate on the QucikeLab platform. ' ' If the program is modified to read a different maximum voltage the ' variable Volts200 and voltage scaling in the MAIN ROUTINE must be ' suitably changed. Since Volts200 is also used in the MORSE subroutine ' The new variable must also be changed there. Naturally the associated ' circuitry must be modified as well. ' ' Revision History: ' ----------------- ' Rev 0 8/14/2002 Draft release #1 ' Rev 0.1 8/22/2002 Revised LCD routine, added LCD init on startup ' Note Volts 200 scaling interim 5V ' Rev 0.2 8/22/2002 Fixed Morse freq at 2000 Hz for piezo spkr ' Rev 0.3 10/3/2002 Redesigned to use QL with IOX ' Rev 0.4 10/5/2002 Comments revised to properly reflect QL usage. ' '************************************************************************* ' Copyright 2002, J. Everhart, N2CX All rights reserved. Permission is ' granted for personal, non-profit use. ' '************************************************************************* '{$STAMP BS2} '******************* ' VARIABLES '******************* DitTime con 100 'MORSE dit time, 100 ms is 12 wpm LcdClr con 1 'LCD clear screen instruction CMD con 254 'LCD instruction prefix Baud con 375 'IOX data rate 2400 baud L1C1 con 128 'LCD screene line 1, column 1 L2C6 con 198 'LCD screen line 2, column 6 TonePin con 5 'Tone output pin AdcOut var word '8-bit ADC outout value I var byte 'Loop index variable Volts200 var word '3-digit decimal ADC output scaled 0-200 Dig1 var byte 'Voltage least signif digit Dig2 var byte 'Volts middle digit Dig3 var byte 'Volts most signif digit Freq var word 'VARTONE frequency in Hz MorseChar var byte 'Hold packed Morse to be sent Mode var nib 'Operating mode TestChar var byte 'Variable used to check for DIT or DAH VoltDigit var byte 'Morse dit to be sent '*************************************************************************' ' MAIN PROGRAM '************************************************************************* INITSETUP: serout 0,Baud,20, [CMD,LcdClr] 'Clear the LCD screen START: serout 0,Baud,20,[CMD,80] 'Command ADC to take a reading serin 1,Baud,[ADCout] 'Get ADC reading ' Change next line to 50/64 for final 0-2V scaling Volts200 = AdcOut * 125 / 64 'Scale voltage to 0-500 - test Dig1 = Volts200 dig 2 'Grab indiv digits from Dig2 = Volts200 dig 1 'Volts200 Dig3 = Volts200 dig 0 gosub LCDDISP 'Visual display gosub CHECKMODE 'Check operating mode if Mode = 0 then START 'No audbile opt get new rdg if Mode = 1 then VARTONE 'Variable tone "bar graph" if Mode = 2 then MORSE 'Audible Morse "display" goto START 'By default get new reading '************************************************************************* ' LCDDISP - Visual LCD display routine using the IOX to access the ' display. Data rate is 2400 baud. '************************************************************************* LCDDISP: serout 0,Baud,7,[CMD,L1C1] 'Move cursor to start of display serout 0,Baud,7,["N2CX AVV"] 'Print vanity message serout 0,Baud,7,[CMD, L2C6] 'Move cursor to Line 2 Col 6 serout 0,Baud,7,[Dec Dig1,".",Dec Dig2, Dec Dig3, " V"] 'display voltage value return 'To main program '************************************************************************* ' CHECKMODE- This subroutine checks the Mode pushbutton switch on pin 3 and ' sets the operating mode appropriately. The program begins ' with only the LDC enabled and no audio outputs. When the MODE ' button is pressed and detected, operation changes to the ' VARTONE mode in which a tone is output whose frequency is ' proportional to the measured voltage. A second switch ' depression results in an audible MORSE output. The next ' detected button push begins operation with only the LCD on. ' since the BS2 has no interrupts, the switch must be polled ' and CHECKMODE follows display on the LCD. Thus the switch ' must be held long enough to cycle through the current ' operating mode then a new reading and LCD output. In order ' to avoid switch bounce and uncertainty of being detected, ' operation ceases until the switch is released. The new ' mode proceeds at that time. ' '************************************************************************ CHECKMODE: 'Checks mode select pushbutton if in3 = 1 then ENDOFCHECKMODE 'If not pressed no mode change if in3 = 0 and Mode = 0 then SETVARTONE 'Pressed and NOTONE set VARTONE if in3 = 0 and Mode = 1 then SETMORSE 'Pressed and VARTONE set MORSE goto SETNOTONE 'Pressed and MORSE set NOTONE SETVARTONE: if in3 = 0 then SETVARTONE 'Loop until key is released Mode = 1 'Mode 1 is VARTONE return 'To top of main program SETMORSE: if in3 = 0 then SETMORSE 'Loop until key is released Mode = 2 'Mode 2 is MORSE return 'To top of main program SETNOTONE: if in3 = 0 then SETNOTONE 'Loop until key is released Mode = 0 'Mode 0 is NOTONE ENDOFCHECKMODE return 'To top of main program '************************************************************************* '************************************************************************* ' VARTONE - This subroutine outputs a tone whose pitch varies directly ' with the measured voltage. In order to be compatible with ' transmission via a voice-quality communications path, the ' lowest input voltage produces an output at 300 Hz while a ' full-scale 8-bit reading of 255 gives a tone at 2850 Hz. ' '************************************************************************* VARTONE: Freq = AdcOut * 10 + 300 'Scale value between 300 and 2850 Hz freqout TonePin, 200, Freq 'Output VARTONE for 200 ms return 'To main program '************************************************************************* 'MORSE - This subroutine outputs a tone keyed with those digits. The 'letter "R" is sent as a decimal point. '************************************************************************* MORSE: Freq = 2000 'Morse tone freq = 2000 Hz for i = 2 to 0 'Pick off AD digits VoltDigit = Volts200 dig I 'Grab individual decimal digits 'Get packed Morse characters lookup VoltDigit,[$FC,$7C,$3C,$1C,$0C,$04,$84,$C4,$E4,$F4],MorseChar gosub SENDMORSE 'Send Morse character if I = 2 then SENDR 'Add "R' for decimal point after ms digit goto SKIPR 'If not most signif digit SENDR: MorseChar = $50 'Packed Morse representation for "R" gosub SENDMORSE SKIPR: next pause 500 '1/2 sec delay between MORSE readouts return 'To main program '************************************************************************* ' SENDMORSE - This subroutine picks apart packed morse characters stored in ' MorseChar and ouputs audible MORSE characters on TonePin of ' the BS2. Speed is set to 12 wpm initally by variable DitTime. '************************************************************************* SENDMORSE: 'Sends audible morse chars CHECKMORSE: 'Process packed morse variable if MorseChar = $80 then SENDCHARSPACE 'All dits and dahs shifted out TestChar = MorseChar & $80 'Get high bit MorseChar = MorseChar *2 'Shift out used char if TestChar = $80 then SENDDAH 'Char is a DAH so send it 'If not, it's a DIT so fall thru SENDDIT: freqout TonePin, DitTime, Freq 'Unit time dit tone freqout TonePin, DitTime, 0 'Unit time space goto CHECKMORSE 'Go back for next char SENDDAH freqout TonePin, 3*DitTime, Freq '3*Unit time dit tone freqout TonePin, DitTime, 0 'Unit time space goto CHECKMORSE 'Go back for next char SENDCHARSPACE: freqout TonePin, 2*DitTime, 0 '2*unit time space return 'To main program STOP 'Something has gone badly wrong 'to get here! '************************************************************************* ' END OF PROGRAM AVV '*************************************************************************