'**************************************************************** '* Name : ADC_blue_box_05.BAS * '* Author : df99 * '* Notice : Copyright (c) 2008 * '* : All Rights Reserved * '* Date : 3/11/2008 * '* Version : 0.6 * '* Notes : PWM blue box with single pin * '* : keyboard decode. Memory storage with six slots * '* : of up to 32 tones each * '**************************************************************** ' Resistor network detection values assume a network of 14-1KOhm ' resistors in series, from Vdd to Vss, with a tap between each ' resistor pair. Taps at Vdd and Vss are not used, to avoid ADC ' issues when trying to read at the voltage rails. ' The slight effect of a 250KOhm pull-down resistor on the ADC input ' pin is also factored into the calculations, although the effect is ' almost negligible. ' On power up, a mode change, or a memory store operation, the device ' Saves the next 32 keypresses in a buffer. This buffer may be written ' to one of the six non-volatile memory locations (1-6) by pressing and ' holding the corresponding digit for two seconds. The tone played when the ' key is first pressed to store will not be recorded. Reset the digit buffer ' by cycling power, saving a previous buffer to EEPROM, or changing modes. ' The box operates in two modes. In the default mode, it plays MF and ' the 2600 tone manually. Pressing and holding the 2600 button more than ' two seconds toggles to the playback mode. In this mode, sequences stored ' in the 6 memories may be played by pressing the corresponding key. Another two ' second press of the 2600 key, or power cycling, returns to normal mode. ' Memory locations may be cleared by pressing and holding the corresponding ' key in normal mode immediately after the buffer has been cleared at power-up, ' after a mode change back to normal mode, or after storing a digit sequence. ' Set PIC configuration fuses. PICBASIC PRO refreshes WDT automatically. ' HS_OSC works well for the Murata 20 MHz ceramic resonator. No parallel ' resistor required. @ DEVICE PIC12F683,HS_OSC,WDT_ON,PWRT_ON,MCLR_ON,BOD_OFF,CPD_OFF,PROTECT_OFF,IESO_OFF,FCMEN_OFF DEFINE OSC 20 ' 20 MHz clock DEFINE ADC_BITS 10 'Use 10 bit resolution with ADCIN DEFINE ADC_CLOCK 3 'Use internal RC clock for ADC only DEFINE ADC_SAMPLEUS 50 'Wait 50 uS before read after ADCIN turns on ADC ADCON0 = %10001001 'Right justify ADC, Vdd ref, Chan 2, enable ADC KEY VAR WORD 'Define variable for ADC input value KEYDOWN VAR WORD 'Keydown loop counter MODE VAR WORD number VAR byte[34] 'Array for storage of up to 32 keypresses pointer var byte 'Pointer for writing or reading the above array rpointer var byte 'EEPROM read pointer wpointer var byte 'EEPROM write pointer digit var byte 'The code of the most recently pressed key NORMAL CON 0 'Alias for NORMAL mode PLAYBACK CON 1 'Alias for memory PLAYBACK mode eeprom 0*33,255 'Set eof indicator at beginning of first eeprom bank when programmed eeprom 1*33,255 'Set eof indicator at beginning of next eeprom bank when programmed eeprom 2*33,255 'Set eof indicator at beginning of next eeprom bank when programmed eeprom 3*33,255 'Set eof indicator at beginning of next eeprom bank when programmed eeprom 4*33,255 'Set eof indicator at beginning of next eeprom bank when programmed eeprom 5*33,255 'Set eof indicator at beginning of next eeprom bank when programmed pointer = 0 'Reset keypress array pointer number(0) = 255 'Set eof marker to beginning of array mode = normal loop: ADCIN 2, KEY 'Get keypad value again keydown = 0 'Clear keydown value IF (KEY > 37) THEN GOSUB keytest 'If any keypress detected, decode Pause 10 'Allow ADC to settle between reads GOTO loop 'Do it again - idle loop ' Any key value <= 37 is essentially 0 VDC because of the pull-down ' resistor, with some margin for noise. This means that no key has ' been pressed. keytest: ' 4.64 volts calculated, with Vdd = 5VDC. ADC value=949 ' Prototype measured value with 5% resistors: 4.65 VDC IF ((KEY > 914) AND (KEY <= 1023) and (mode = normal)) THEN digit = 1 gosub play2 gosub update endif IF ((KEY > 914) AND (KEY <= 1023) and (mode = PLAYBACK)) THEN digit = 1 gosub play endif ' 4.29 volts calculated, with Vdd = 5VDC. ADC value=878 ' Mean with previous value = 914 ' Prototype measured value with 5% resistors: 4.29 VDC IF ((KEY > 841) AND (KEY <= 914) and (mode = normal)) THEN digit = 2 gosub play2 gosub update endif IF ((KEY > 841) AND (KEY <= 914) and (mode = playback)) THEN digit = 2 gosub play endif ' 3.93 volts calculated, with Vdd = 5VDC. ADC value=804 ' Mean with previous value = 841 ' Prototype measured value with 5% resistors: 3.94 VDC IF ((KEY > 767) AND (KEY <= 841) and (mode = normal)) THEN digit = 3 gosub play2 gosub update endif IF ((KEY > 767) AND (KEY <= 841) and (mode = playback)) THEN digit = 3 gosub play endif ' 3.57 volts calculated, with Vdd = 5VDC. ADC value=730 ' Mean with previous value = 767 ' Prototype measured value with 5% resistors: 3.58 VDC IF ((KEY > 694) AND (KEY <= 767) and (mode = normal)) THEN digit = 4 gosub play2 gosub update endif IF ((KEY > 694) AND (KEY <= 767) and (mode = playback)) THEN digit = 4 gosub play endif ' 3.21 volts calculated, with Vdd = 5VDC. ADC value=657 ' Mean with previous value = 694 ' Prototype measured value with 5% resistors: 3.22 VDC IF ((KEY > 621) AND (KEY <= 694) and (mode = normal)) THEN digit = 5 gosub play2 gosub update endif IF ((KEY > 621) AND (KEY <= 694) and (mode = playback)) THEN digit = 5 gosub play endif ' 2.86 volts calculated, with Vdd = 5VDC. ADC value=585 ' Mean with previous value = 621 ' Prototype measured value with 5% resistors: 2.86 VDC IF ((KEY > 549) AND (KEY <= 621) and (mode = normal)) THEN digit = 6 gosub play2 gosub update endif IF ((KEY > 549) AND (KEY <= 621) and (mode = playback)) THEN digit = 6 gosub play endif ' 2.50 volts calculated, with Vdd = 5VDC. ADC value=512 ' Mean with previous value = 549 ' Prototype measured value with 5% resistors: 2.51 VDC IF ((KEY > 475) AND (KEY <= 549) and (mode = normal)) THEN digit = 7 gosub play2 gosub update endif ' 2.14 volts calculated, with Vdd = 5VDC. ADC value=438 ' Mean with previous value = 475 ' Prototype measured value with 5% resistors: 2.15 VDC IF ((KEY > 401) AND (KEY <= 475) and (mode = normal)) THEN digit = 8 gosub play2 gosub update endif ' 1.78 volts calculated, with Vdd = 5VDC. ADC value=364 ' Mean with previous value = 401 ' Prototype measured value with 5% resistors: 1.79 VDC IF ((KEY > 329) AND (KEY <= 401) and (mode = normal)) THEN digit = 9 gosub play2 gosub update endif ' 1.43 volts calculated, with Vdd = 5VDC. ADC value=293 ' Mean with previous value = 329 ' Prototype measured value with 5% resistors: 1.43 VDC IF ((KEY > 256) AND (KEY <= 329) and (mode = normal)) THEN digit = 10 gosub play2 gosub update endif ' 1.07 volts calculated, with Vdd = 5VDC. ADC value=219 ' Mean with previous value = 256 ' Prototype measured value with 5% resistors: 1.07 VDC IF ((KEY > 182) AND (KEY <= 256) and (mode = normal)) THEN digit = 11 gosub play2 gosub update endif ' 0.71 volts calculated, with Vdd = 5VDC. ADC value=145 ' Mean with previous value = 182 ' Prototype measured value with 5% resistors: 0.72 VDC IF ((KEY > 110) AND (KEY <= 182) and (mode = normal)) THEN digit = 12 gosub play2 gosub update endif ' 0.36 volts calculated, with Vdd = 5VDC. ADC value=74 ' Mean with previous value = 110 ' Mean with ground (0VDC) = 37 ' Prototype measured value with 5% resistors: 0.36 VDC IF ((KEY > 37) AND (KEY <= 110) and (mode = normal)) THEN digit = 13 '2600 gosub play2 gosub update endif ' The following code waits until the key is released (if pressed) to insure ' one tone burst per keypress. Delay seems needed for reliable ADC settling, ' since loop is so small. A counter tracks the number of 10 ms iterations ' through the loop to time the keydown period to trigger a mode change. again: 'Get keypad value again after tone ADCIN 2, KEY 'Increment keydown count KEYDOWN = KEYDOWN + 1 'Toggle modes between NORMAL and PLAYBACK after 2 seconds 'of 2600 key keydown if ((KEYDOWN > 200)and(KEY > 37)AND(KEY <= 110))then gosub modechg 'Detect EEPROM write request if keys 1-6 held down for > 2 seconds IF mode = normal then if ((KEYDOWN > 200)and(KEY > 914)AND(KEY <= 1023))then gosub eewrite if ((KEYDOWN > 200)and(KEY > 841)AND(KEY <= 914))then gosub eewrite if ((KEYDOWN > 200)and(KEY > 767)AND(KEY <= 841))then gosub eewrite if ((KEYDOWN > 200)and(KEY > 694)AND(KEY <= 767))then gosub eewrite if ((KEYDOWN > 200)and(KEY > 621)AND(KEY <= 694))then gosub eewrite if ((KEYDOWN > 200)and(KEY > 549)AND(KEY <= 621))then gosub eewrite endif 'Allow ADC to settle between reads Pause 10 'Loop through again if key is still pressed IF (KEY > 37) THEN again RETURN 'Save the first 32 keypresses after power up or a mode change 'back to normal mode from PLAYBACK mode. These keypresses may be 'written to locations 1-6 by pressing the corresponding button ' for > 2 seconds. Buffer is cleared by power cycle, ee write, ' or mode change. update: if pointer = 32 then return number(pointer) = digit pointer = pointer + 1 number(pointer) = 255 return 'Routine to wite the buffer array described above to EEPROM 'Banks 1-6. eewrite: 'Adjust temporary array for extra digit stored when requesting an 'ee write. if pointer < 32 then number(pointer - 1) = 255 'Remove extra digit pointer = 0 'Set pointer to 0 to start buffer read wpointer = 33 * (digit - 1) 'Select the 32-byte correct bank to write agn: if number(pointer) = 255 then 'Detect keypress buffer eof write wpointer,255 'Write eof to flash if at end of buffer pointer = 0 'Clear out keypress buffer pointer number(0) = 255 'Reset buffer EOF to empty buffer FREQOUT 0,1000,1700 'Beep after ee write complete hold: ADCIN 2, KEY 'Get keypad value again Pause 10 'Allow ADC to settle between reads IF (KEY > 37) THEN hold 'Wait for key release return endif write wpointer,number(pointer)'Write the next buffer location to ee pointer = pointer + 1 'Increment the buffer pointer wpointer = wpointer + 1 'Increment the ee pointer goto agn 'Do until the end of buffer 'Dual purpose routine to play the decoded keys in NORMAL mode or 'to read and play back the stored ee digit strings, depending upon 'entry point and mode. play: rpointer = 33 * (digit - 1) 'Set the correct EE bank to play back agn2: read rpointer,digit 'Get the digit from the next ee location play2: if digit = 255 then return 'Stop playback when eof reached in ee IF (digit = 1)then FREQOUT 0,75,700,900 'MF1 IF (digit = 2)then FREQOUT 0,75,700,1100 'MF2 IF (digit = 3)then FREQOUT 0,75,900,1100 'MF3 IF (digit = 4)then FREQOUT 0,75,700,1300 'MF4 IF (digit = 5)then FREQOUT 0,75,900,1300 'MF5 IF (digit = 6)then FREQOUT 0,75,1100,1300 'MF6 IF (digit = 7)then FREQOUT 0,75,700,1500 'MF7 IF (digit = 8)then FREQOUT 0,75,900,1500 'MF8 IF (digit = 9)then FREQOUT 0,75,1100,1500 'MF9 IF (digit = 10)then FREQOUT 0,120,1100,1700 'KP IF (digit = 11)then FREQOUT 0,75,1300,1500 'MF0 IF (digit = 12)then FREQOUT 0,75,1500,1700 'ST IF (digit = 13)then FREQOUT 0,1000,2600 'Seize if (mode = normal) then return 'Stop here if decoding manual keypresses rpointer = rpointer + 1 'Go to the next ee location pause 75 'Insert pause between digits played goto agn2 'Get the next digit in ee return 'Routine to toggle the mode if 2600 button held for > 2 seconds modechg: if (mode = playback) then mode = normal 'Toggle mode to NORMAL keydown = 0 'Play high to low beep to confirm mode change to NORMAL freqout 0,75,1700 'Play high beep freqout 0,75,1300 'Play low beep return else if (mode = normal) then mode = playback 'Toggle mode to PLAYBACK keydown = 0 'Play low to high beep to confirm mode change to PLAYBACK Freqout 0,75,1300 'Play low beep freqout 0,75,1700 'Play high beep pointer = 0 'Reset so move to playback mode clears buffer number(0) = 255 'Reset so move to playback mode clears buffer return endif endif return