__config 3f79 ; 3/13/23 cm TX Control and Display Module ; Code Version 51 tested 20 Nov 09 ; ; Channel Switch connected to RA0 to RA2 Binary 0 - 7 ; Up button RA3 Active low ; Down button RA4 Active low ; Store button RA5 Active low ; Display select ( Binary 0-7) connected to RC1 thru RC2 ; Digit (0-9 BCD) connected to RC4 thru RC7 (high 4 bits of Port C) ; 8 Bit parallel to TX is RB0-7 ; EEPROM 0-7 are used for Channels 0-7 ; EEPROM 8 is used for BAND ; EEPROM 9 is set to 55 after first boot up ; Definitions ;-------PIC Registers------------------------- INDR EQU 0 ; the indirect data register PCL EQU 2 ; program counter low bits STATUS EQU 3 ; Used for Zero bit FSR EQU 4 ; the indirect address register PORTA EQU 5 ; Switch inouts PORTB EQU 6 ; 8 Bit code to TX PORTC EQU 7 ; Low 3 bits select digit, High 4 bits are BCD PCLATH EQU 0x0A ; Program Counter High Bits INTCON EQU 0x0B ; Interrupt Control T1CON EQU 0x10 ; Counter Control TRISA EQU 0x85 ADCON1 EQU 0x9F EEDATA EQU 0x010C EEADR EQU 0x010D EEDATH EQU 0x010E EEADRH EQU 0x010F EECON1 EQU 0x018C EECON2 EQU 0x018D ;-------PIC Bits-------------------------------- W EQU 0 ; indicates result goes to working register F EQU 1 ; indicates result goes to file (named register) CARRY EQU 0 ZERO EQU 2 RP1 EQU 0x06 RP0 EQU 0x05 EEPGD EQU 0x07 WREN EQU 0x02 WR EQU 0x01 RD EQU 0x00 ;-------Project Registers------------------ D7 EQU 0x20 ; Digit 7 Right LSB D6 EQU 0x21 ; Digit 6 D5 EQU 0x22 ; Digit 5 D4 EQU 0x23 ; Digit 4 MSB for 2300 D3 EQU 0x24 ; Digit 3 MB or blanked D2 EQU 0x25 ; Digit 2 Blanked D1 EQU 0x26 ; Digit 1 Blanked D0 EQU 0x27 ; Digit 0 Left, MSB, used for channel DIGIT EQU 0x28 ; The digit currently illuminated CHAR EQU 0x29 ; the character in the digit currently illuminated DELAY EQU 0x2B ; delay counter in SUB TICK LCOUNT EQU 0x2C ; loop counter in main loop HDATA EQU 0x32 ; Used to pass the high byte into SUB HEX2BCD HTEMP EQU 0x33 ; used in SUB HEX2BCD HCARRY EQU 0x34 ; used in SUB HEX2BCD HOFFSET EQU 0x35 ; used in SUB HEX2BCD HOFFBIT EQU 0x36 ; used in SUB HEX2BCD FREQL EQU 0x37 ; Frequency low byte FREQH EQU 0x38 ; Frequency high byte CHAN EQU 0x39 ; 00=Man, 01-07=channels CHMODE EQU 0x3A ; Status word for button presses TMPFREQ EQU 0x3B ; used in EEPROM read loop SWITCH EQU 0x3C ; switch state as read DEBONCE EQU 0x3D ; debounce counter FLASH EQU 0x3E ; used to count time for flashing digits TWITCH EQU 0x3F ; Inverse of SWITCH bits 3-5 only MANFREQ EQU 0x40 ; the last selected man freq and chan 0 CHAN1 EQU 0x41 ; Chan 1 in RAM CHAN2 EQU 0x42 ; Chan 2 in RAM CHAN3 EQU 0x43 ; Chan 3 in RAM CHAN4 EQU 0x44 ; Chan 4 in RAM CHAN5 EQU 0x45 ; Chan 5 in RAM CHAN6 EQU 0x46 ; Chan 6 in RAM CHAN7 EQU 0x47 ; Chan 7 in RAM BAND EQU 0x48 ; Band. 0=binary, 1=1240, 2=2300, 3=9200 TFREQL EQU 0x4A ; temporary store for low byte of frequency TFREQH EQU 0x4B ; temporary store for high byte of frequency DP EQU 0x4C ; Digit number of decimal point DPWORD EQU 0x4D ; bit map of decimal point for Port C (bit 3 low active) BANDCH EQU 0x4E ; status for band change 0x00 null, 0x01 possible MCOUNT EQU 0x4F ; Counter for EEPROM Read loop WADR EQU 0x50 ; EEPROM Write address MWADR EQU 0x0150 ; Mirrored EEPROM Write address WDATA EQU 0x51 ; EEPROM Write data MWDATA EQU 0x0151 ; Mirrored EEPROM Write data CHANCNT EQU 0x52 ; Counter for writing channels to EEPROM BAND8 EQU 0x53 ; Band shifted 3 places left for lookup ;-------Project Bits------------------------- ; None ;-------START of Program-------------------- ORG 0x10 ; Load from Program Memory 16 onwards ;Initialise CLRF PORTA ; Clear output latches BSF 3, 5 ; Bank x1 BCF 3, 6 ; Bank 01 (1). Now set Port directions MOVLW 0x06 ; Configure all pins MOVWF ADCON1 ; as digital inputs MOVLW 0xFF ; Initialize data direction MOVWF TRISA ; Set RA0-5 as inputs (0-2=Chan, 3=Up, 4=down, 5=Store) CLRF PORTB ; PORTB = Output (8 bit 0-255 to TX) CLRF PORTC ; All Outputs - digit select (0-2), DP (3) and BCD (4-7) BCF 3, 5 ; Bank 00 (0) CLRF PCLATH CLRF DIGIT CLRF D0 CLRF D1 CLRF D2 CLRF D3 CLRF D4 CLRF D5 CLRF D6 CLRF D7 CLRF T1CON ; Turn off Timer 1 CLRF CHMODE ; Clear button status register CLRF BANDCH ; Set Band Change not in progress BSF STATUS, RP1 ; Bank 1x BCF STATUS, RP0 ; Bank 10 (2) CLRF EEDATH ; Clear EEPROM high byte CLRF EEADRH ; Clear EEPROM high byte BCF STATUS, RP1 ; Bank 00 (0) ;------ Make sure the EEPROM is set up ----------------- ; Read EEPROM location 0x09 to check if channels are loaded in EEPROM ; 0x09 is set to 0x55 if band and channels have been loaded. MOVLW 0x09 ; Load EEPROM Addresss (0x09) CALL EPRD ; Read EEPROM 0x09. Put result in W SUBLW 0x55 ; Set zero bit if 55 = Channels loaded BTFSS STATUS, ZERO ; skip next if channels already loaded CALL FSTART ; First start after Code reprogram ;------ Load the band from EEPROM and read in the preset channels MOVLW 0x08 ; Load EEPROM Addresss for band (0x08) CALL EPRD ; Read EEPROM 0x08. Put result in W MOVWF BAND ; Set the BAND CALL RCHAN ; Call the sub to read channels from EEPROM into RAM ;------ SET UP FOR FIRST PASS ----------------------- ;Read Current channel selection MOVF PORTA, W ; Read switches ANDLW 0x3F ; Mask unused bits MOVWF SWITCH ; Store for later ANDLW 0x07 ; Mask to leave channel number MOVWF CHAN ;Set RAM address to read from ADDLW 0x40 ; Calculate RAM address MOVWF FSR ; Load address ;Read Preset Frequency from RAM and set it MOVF INDR, W ; Read frequency to W MOVWF PORTB ; Set frequency ;------ Start Main Loop - Approx 10 Hz ------------------------- LONG MOVLW 0x60 ; start of main loop, set w to 96 MOVWF LCOUNT ; move w (96) to LCOUNT INCF FLASH, F ; increment the flash counter ;Reset Counters etc CLRF DIGIT ; reset display to digit 0 ;Blank display before calculations MOVF PORTC, W ; obtain bit states of port C into W IORLW 0xF0 ; set high 4 bits high (which will blank display) MOVWF PORTC ; Clear Display by sending 15 ;Decode display CLRF D3 ; set registers D3 - D7 to zero CLRF D4 CLRF D5 CLRF D6 CLRF D7 CALL PANEL ; Checks Panel buttons and Chan switch CALL ADDOFST ; sub to add offset value or multiplier MOVF FREQH, W ; read Frequency high byte to W MOVWF HDATA ; load frequency high byte into HDATA CALL HEX2BCD ; convert and return when less than 10 MOVF FREQL, W ; read frequency low byte to W MOVWF HDATA ; load load frquency low byte to HDATA CALL HEX2BCD ; convert and return when less than 10 CALL DISPCAL ; sort out the display digits ; Display loop - Approx 1 KHz. Each digit (of 8) gets displayed each time for 12 goes NDIGIT CALL TICK ; Display each digit in turn, 0 first DECFSZ LCOUNT, F ; decrement LCOUNT and test GOTO NDIGIT ; if LCOUNT <> 0 goto NDIGIT ;End display loop GOTO LONG ; End of main loop ;Main flow never gets beyond here ;----------------------------------------------------------- ;----- TICK ------------------------------------------------ ;TICK is called 1000 times a second and displays one digit each time TICK MOVF PORTC, W ; Obtain bit states of port C. Put in W IORLW 0xF8 ; Set high 5 bits high (which will blank display and DP) MOVWF PORTC ; Clear Display by sending 15 and 1 for DP INCF DIGIT, W ; Increment the digit number. Put in W ANDLW 0x07 ; mask the digit number to the range 0-7 MOVWF DIGIT ; write the masked digit number to the digit variable MOVF PORTC, W ; Obtain bit states of port C ANDLW 0xF8 ; Set low 3 bits low IORWF DIGIT, W ; Set low 3 bits to DIGIT MOVWF PORTC ; Write the DP and digit number to PORTC MOVF DIGIT, W ; Load digit number back into W ADDLW 0x20 ; Add the Register Offset to W MOVWF FSR ; move w to the indirect address register SWAPF INDR, W ; Get number fron digit register ANDLW 0xF0 ; mask W MOVWF CHAR ; store bcd in CHAR BTFSS CHMODE, 1 ; skip next if in store mode GOTO DISP ; normal BTFSS FLASH, 2 ; skip next if flash off not required GOTO DISP ; no flash MOVLW 0xF0 ; Blank character MOVWF CHAR ; load blank DISP NOP ; Check DP MOVLW 0xFF ; set W all high MOVWF DPWORD ; set DP Word all high MOVF DIGIT, W ; Load digit number back into W SUBWF DP, W ; Set zero bit if DP this digit BTFSC STATUS, ZERO ; skip next if no DP BCF DPWORD, 3 ; Set bit 3 low for DP MOVF PORTC, W ; read port c into W ANDLW 0x0F ; remove old bcd data IORWF CHAR, W ; add new bcd data ANDWF DPWORD, W ; set bit 3 low if DP MOVWF PORTC ; write back to port c ; Time delay 994 cycles MOVLW 0xC8 MOVWF DELAY LOOP1 DECFSZ DELAY, F GOTO LOOP1 NOP ;602uS in Loop1 =200*3+2 MOVLW 0x7C MOVWF DELAY LOOP2 DECFSZ DELAY, F GOTO LOOP2 NOP ;376uS in Loop2 =124*3+2 RETURN ; return after 16+602+376 ;------ End of Tick ---------------------------------- ;------ HEX2BCD ------------------------------------- ; HEX 2 BCD - Called twice, 10 times a second ; Registers used are HDATA, HTEMP, HCARRY, HOFFSET, HOFFBIT ; Digits are in registers 32 - 39 ; This routine converts full bytes only. ; Before calling this routine, HDATA must contain data byte to be converted HEX2BCD CLRF HTEMP ; clear HTEMP CLRF HOFFBIT ; clear HOFFBIT HLOOP CLRF HCARRY CLRF HOFFSET BTFSC HDATA, 7 ;Is bit 7 set? INCF HCARRY, F ;Yes so set HCARRY HNXTDGT MOVF HOFFSET, W ;Next Digit ADDLW 0x20 MOVWF FSR BCF STATUS, CARRY ;Clear carry bit RLF INDR, F ;Multiply data by two BTFSC HCARRY, 0 INCF INDR, F MOVF INDR, W ADDLW 0x06 ;Add 6 MOVWF HTEMP CLRF HCARRY ;Prepare by clearing HCARRY BTFSS HTEMP, 4 ;Is data > 10? (HTEMP > 16?) GOTO HINCOFF ;No INCF HCARRY, F ;Yes so set HCARRY & subtract 10 MOVLW 0x0A SUBWF INDR, F HINCOFF INCF HOFFSET, F ;Increment offset MOVLW 0x07 SUBWF HOFFSET, W BTFSS STATUS, ZERO ;Is it past last digit GOTO HNXTDGT ;No so do next digit HNXTBIT INCF HOFFBIT, F ;Yes so do next bit MOVLW 0x08 SUBWF HOFFBIT, W BTFSC STATUS, ZERO ;Is it past last bit RETURN ;Yes,all done so return RLF HDATA, F ;No so shift data GOTO HLOOP ;------ End of HEX2BCD ----------------------------------- ;------ ADDOFST ------------- called 10 times a second before hex2bcd ; Adds the right offset and multiplier for the band ; Reads PORTB, leaves result in FREQL and FREQH ADDOFST NOP ; Choose offset based on BAND ; then need to multiply by 5 or 4 based on BAND ; Try band 0 MOVF BAND, F ; Set zero bit if Band is 00 (binary) BTFSS STATUS, ZERO ; skip next if BAND is 00 GOTO BAND1 ; Try band 01 ; Band 0 (binary) MOVF PORTB, W ; Load binary to W MOVWF FREQL ; Display Binary directly CLRF FREQH ; High byte is zeros MOVLW 0x0F ; Load 15 for no decimal point MOVWF DP ; Set no decimal point GOTO OFSTEND ; Try Band 1 (1240) BAND1 MOVF BAND, W ; Load band SUBLW 0x01 ; Zero flag set if band 1 BTFSS STATUS, ZERO ; skip next if BAND is 01 GOTO BAND2 ; Try band 10 ; Band 1 (1240) ; Add offset (2480= 0x09, 0xB0) store numbers, multiply by 4, add original numbers CLRF FREQH ; Clear HIGH BYTE MOVF PORTB, W ; Load input value to W ADDLW 0xB0 ; Add 176 to W MOVWF FREQL ; Put result in FREQL MOVWF TFREQL ; Put in TFREQL for later use BTFSC STATUS, CARRY ; Skip next if carry not set INCF FREQH, F ; Add 1 to High byte if carry was set MOVLW 0x09 ; Add 9 (x256 = 2304) to W so Total 2480 ADDWF FREQH, F ; Add offset in W to FREQH MOVF FREQH, W ; Load FREQH into W MOVWF TFREQH ; Put in TFREQH for later use ; Multiply by 4 BCF STATUS, CARRY ; Clear Carry bit RLF FREQL, F ; Multiply low byte by 2 and with carry RLF FREQH, F ; Multiply high byte by 2 with carry from low BCF STATUS, CARRY ; Clear Carry bit RLF FREQL, F ; Multiply low byte by 2 and with carry RLF FREQH, F ; Multiply high byte by 2 with carry from low ; Add original number MOVF TFREQL, W ; Load Freq/5 into W ADDWF FREQL, F ; Add to 4 Freq/5 to get freq BTFSC STATUS, CARRY ; Skip next if carry not set INCF TFREQH, F ; Add 1 to High byte Freq/5 if carry was set MOVF TFREQH, W ; Load high byte Freq/5 into W ADDWF FREQH, F ; Add to high byte 4 freq/5 to get freq MOVLW 0x01 ; Load 1 for decimal point position MOVWF DP ; Set decimal point GOTO OFSTEND ; Finish ; Try Band 2 and 3. Both start with this: ; Note that Band 2 is the default so there is no testing of Band here BAND2 CLRF FREQL ; Clear lOW BYTE CLRF FREQH ; Clear HIGH BYTE MOVF PORTB, W ; Load input value to W ADDLW 0xFC ; Add 252 to W MOVWF FREQL ; Put result in FREQL BTFSC STATUS, CARRY ; Skip next if carry not set INCF FREQH, F ; Add 1 to High byte if carry was set MOVLW 0x08 ; Add 8 (x256 = 2048) to W so Total 2300 ADDWF FREQH, F ; Add offset in W to FREQH MOVLW 0x0F ; Load 15 for no decimal point MOVWF DP ; Set no decimal point ; Test for Band 3 MOVF BAND, W ; Load band SUBLW 0x03 ; Zero flag set if band 3 BTFSS STATUS, ZERO ; skip next if BAND is 11 GOTO OFSTEND ; Exit with these values ; Band 3 (9200). Multiply by 4 BCF STATUS, CARRY ; Clear Carry bit RLF FREQL, F ; Multiply low byte by 2 and with carry RLF FREQH, F ; Multiply high byte by 2 with carry from low BCF STATUS, CARRY ; Clear Carry bit RLF FREQL, F ; Multiply low byte by 2 and with carry RLF FREQH, F ; Multiply high byte by 2 with carry from low ; End band 3 OFSTEND RETURN ;------ End of Addoffset ------------------------------------------------- ;------ PANEL ----------------- Called 10 times a second before DISPCAL and TICK PANEL NOP ; Checks and acts on switches and buttons MOVF PORTA, W ; Read switches ANDLW 0x3F ; Mask unused bits MOVWF SWITCH ; Store for use COMF SWITCH, W ; Invert switch into W so that 1 = pressed ANDLW 0x38 ; Mask the 3 buttons MOVWF TWITCH ; Store for use ; Start looking at buttons ; Check that nothing is already in progress by looking at CHMODE MOVF CHMODE, F ; Set zero bit if CHMODE is zero BTFSS STATUS, ZERO ; skip next if CHMODE all zeros GOTO INPROG ; jump because something is in progress ; Nothing going on so check buttons. Exit if not pressed MOVF TWITCH, F ; Set zero bit if TWITCH is zero BTFSC STATUS, ZERO ; skip next if any button pressed GOTO BUTFIN ; Exit because no button is pressed ; To get here, CHMODE is zero and a button is pressed BTFSC TWITCH, 3 ; skip if up not pressed GOTO BUTUP ; Up button pressed BTFSC TWITCH, 4 ; skip if down not pressed GOTO BUTDN ; Down button pressed INPROG BTFSC CHMODE, 3 ; Skip if UP in not in progress GOTO BUTUP ; Up in progress BTFSC CHMODE, 5 ; Skip if Down not in progress GOTO BUTDN ; Down in progress ; To get here, CHMODE=store or store has been pressed GOTO BUTST ; No switches pressed, update channel BUTFIN MOVF SWITCH, W ; Load switch state ANDLW 0x07 ; Mask to leave SWITCH channel number SUBWF CHAN, W ; test if same as stored CHANNEL number BTFSC STATUS, ZERO ; skip next if not equal GOTO PANEND ; Equal, so exit ; Channel has changed MOVF SWITCH, W ; Load switch state ANDLW 0x07 ; Mask to leave channel number MOVWF D0 ; Put Channel in left digit MOVWF CHAN ; Change channel ; Don't change current frequency if in store routine BTFSC CHMODE, 1 ; skip next if not in store routine GOTO PANEND ; exit if storing ; Set RAM address to read from ADDLW 0x40 ; Calculate RAM address MOVWF FSR ; Load address ; Read Preset Frequency from RAM and set it MOVF INDR, W ; Read frequency to W MOVWF PORTB ; Set frequency PANEND RETURN ;-------DISPCAL----------------- Sort out the display DISPCAL NOP ; Display channel number in left digit MOVF SWITCH, W ; Load switch state ANDLW 0x07 ; Mask to leave channel number MOVWF D0 ; Put Channel in left digit ; Blank spare digits MOVLW 0x0F ; Set up a blank MOVWF D1 ; Blank D1 MOVWF D2 ; Blank D2 ; Blank D3 if it is zero MOVF D3,F ; Set zero flag if D3 zero BTFSS STATUS, ZERO ; skip next if D3 zero GOTO ENDISP ; Exit and display D3 if it not zero MOVLW 0x0F ; Set up a blank MOVWF D3 ; Blank D3 if zero ENDISP RETURN ;-------BUTUP------------------- In up routine or up button pressed BUTUP NOP ; ; Check for Case P - first press of up button MOVF CHMODE, F ; Set zero bit if CHMODE is zero BTFSS STATUS, ZERO ; skip next if CHMODE all zeros GOTO CASEV ; jump out because something is in progress BTFSS TWITCH, 3 ; skip if UP pressed GOTO CLRUP ; UP not pressed. Something wrong > exit ; To get here, must be Case P BSF CHMODE, 3 ; Set "UP in Progress" MOVLW 0x02 ; 0.2 second debounce MOVWF DEBONCE ; put in DEBONCE GOTO INCFQ ; Increment freq and exit CASEV NOP ; Check for Case V - exit after button release and debounce MOVF CHMODE, W ; load CHMODE SUBLW 0x18 ; Result is zero if CHMODE was 0001 1000 BTFSS STATUS, ZERO ; skip next if CHMODE was 0001 1000 GOTO CASEQ ; not case V so try Q next MOVF DEBONCE, W ; load DEBONCE SUBLW 0x01 ; Result is zero if DEBONCE was 1 BTFSS STATUS, ZERO ; skip next if DEBONCE was 1 GOTO CASEQ ; not case V so try Q next ; To get here, must be Case V GOTO CLRUP ; Reset CHMODE and DEBONCE, then exit CASEQ NOP ; Cases Q, R and u. Counting down debounce ; debounce is one or greater. Decrement and exit MOVF DEBONCE, F ; Set zero bit if DEBONCE is zero BTFSC STATUS, ZERO ; skip next if DEBONCE not zero GOTO CASES ; jump out because DEBONCE is zero ; To get here must be case Q, R or U DECF DEBONCE, F ; decrement DEBONCE GOTO UPFIN ; exit, wait for next time CASES NOP ; Button still pressed, inc freq MOVF CHMODE, W ; load CHMODE SUBLW 0x08 ; Result is zero if CHMODE was 0000 1000 BTFSS STATUS, ZERO ; skip next if CHMODE was 0000 1000 GOTO CLRUP ; not case S or T so exit on error - should not happen! BTFSC TWITCH, 3 ; skip next if button not pressed GOTO INCFQ ; Case S - continued button press so inc freq and exit ; To get here, must be Case T, first detect of button release BSF CHMODE, 4 ; Set control bit MOVLW 0x01 ; Set debounce 0.1 sec MOVWF DEBONCE ; put in DEBONCE GOTO UPFIN ; Exit INCFQ MOVF PORTB, W ; Called by Cases P and S. Load current frequency MOVWF MANFREQ ; set Manual frequency INCF MANFREQ, F ; Increment manual freq MOVF MANFREQ, W ; Load into W MOVWF PORTB ; Set frequency GOTO UPFIN ; Exit CLRUP CLRF CHMODE ; Exit with reset, so clear CHMODE CLRF DEBONCE ; Reset debounce UPFIN GOTO BUTFIN ;-------BUTDN------------------- In down routine or down button pressed BUTDN NOP ; ; Check for Case P - first press of down button MOVF CHMODE, F ; Set zero bit if CHMODE is zero BTFSS STATUS, ZERO ; skip next if CHMODE all zeros GOTO CASV ; jump out because something is in progress BTFSS TWITCH, 4 ; skip if Down pressed GOTO CLRDN ; DOWN not pressed. Something wrong > exit ; To get here, must be Case P BSF CHMODE, 5 ; Set "DOWN in Progress" MOVLW 0x02 ; 0.2 second debounce MOVWF DEBONCE ; put in DEBONCE GOTO DECFQ ; Decrement freq and exit CASV NOP ; Check for Case V - exit after button release and debounce MOVF CHMODE, W ; load CHMODE SUBLW 0x60 ; Result is zero if CHMODE was 0110 0000 BTFSS STATUS, ZERO ; skip next if CHMODE was 0110 0000 GOTO CASQ ; not case V so try Q next MOVF DEBONCE, W ; load DEBONCE SUBLW 0x01 ; Result is zero if DEBONCE was 1 BTFSS STATUS, ZERO ; skip next if DEBONCE was 1 GOTO CASQ ; not case V so try Q next ; To get here, must be Case V GOTO CLRDN ; Reset CHMODE and DEBONCE, then exit CASQ NOP ; Cases Q, R and u. Counting down debounce ; debounce is one or greater. Decrement and exit MOVF DEBONCE, F ; Set zero bit if DEBONCE is zero BTFSC STATUS, ZERO ; skip next if DEBONCE not zero GOTO CASS ; jump out because DEBONCE is zero ; To get here must be case Q, R or U DECF DEBONCE, F ; decrement DEBONCE GOTO DNFIN ; exit, wait for next time CASS NOP ; Button still pressed, dec freq MOVF CHMODE, W ; load CHMODE SUBLW 0x20 ; Result is zero if CHMODE was 0010 0000 BTFSS STATUS, ZERO ; skip next if CHMODE was 0010 0000 GOTO CLRDN ; not case S or T so exit on error - should not happen! BTFSC TWITCH, 4 ; skip next if button not pressed GOTO DECFQ ; Case S - continued button press so dec freq and exit ; To get here, must be Case T, first detect of button release BSF CHMODE, 6 ; Set control bit MOVLW 0x01 ; Set debounce 0.1 sec MOVWF DEBONCE ; put in DEBONCE GOTO DNFIN ; Exit DECFQ MOVF PORTB, W ; Called by Cases P and S. Load current frequency MOVWF MANFREQ ; set Manual frequency DECF MANFREQ, F ; Decrement manual freq MOVF MANFREQ, W ; Load into W MOVWF PORTB ; Set frequency GOTO DNFIN ; Exit CLRDN CLRF CHMODE ; Exit with reset, so clear CHMODE CLRF DEBONCE ; Reset debounce DNFIN GOTO BUTFIN ;-------BUTST------------------- In store routine or Store button pressed ; BUTST BTFSC TWITCH, 3 ; Skip if up not pressed GOTO CLROUT ; In store routine and up pressed > Dirty exit BTFSC TWITCH, 4 ; Skip if down not pressed GOTO CLROUT ; In store routine and dn pressed > Dirty exit ; Check for Case A - first press of store button MOVF CHMODE, F ; Set zero bit if CHMODE is zero BTFSS STATUS, ZERO ; skip next if CHMODE all zeros GOTO CASEO ; jump out because something is in progress BTFSS TWITCH, 5 ; skip if store pressed GOTO CLROUT ; STORE not pressed. Something wrong > dirty exit ; To get here, must be Case A MOVLW 0x03 ; Set "in store routine", and "flash" MOVWF CHMODE ; put in CHMODE MOVLW 0x02 ; 0.2 second debounce MOVWF DEBONCE ; put in DEBONCE GOTO STFIN ; Exit CASEO NOP ; Check for Case O - ; end of debounce after release of second press MOVF CHMODE, W ; Get current mode SUBLW 0x01 ; W is zero only if Bit zero was set BTFSS STATUS, ZERO ; skip next if CHMODE was 0000 0001 GOTO CASEB ; not CASE O, so try CASE B MOVF DEBONCE, W ; Check debounce count SUBLW 0x01 ; W is zero only if count was one BTFSS STATUS, ZERO ; skip next if debounce was one GOTO CASEB ; not CASE O, so try CASE B ; To get here, must be CASE O GOTO CLROUT ; Clean exit. End of store sequence CASEB NOP ; Check for cases B, C, F, G, J, K and N ; debounce is one or greater. Decrement and exit MOVF DEBONCE, F ; Set zero bit if DEBONCE is zero BTFSC STATUS, ZERO ; skip next if DEBONCE not zero GOTO CASED ; jump out because DEBONCE is zero ; To get here must be case B, C, F, G, J, K or N DECF DEBONCE, F ; decrement DEBONCE GOTO STFIN ; exit, wait for next time CASED NOP ; Check for case D or E BTFSC CHMODE, 2 ; Check control bit GOTO CASEH ; Control set so try CASE H next MOVF TWITCH, F ; Set zero bit if TWITCH all zero BTFSS STATUS, ZERO ; skip next if TWITCH zero GOTO STFIN ; Case D > exit and wait for button release ; To get here must be case E BSF CHMODE, 2 ; Set control bit MOVLW 0x02 ; 0.2 second debounce MOVWF DEBONCE ; put in DEBONCE CASEH NOP ; Check for Case H or I BTFSS CHMODE, 1 ; Check flash bit GOTO CASEL ; Flash not set so try CASE L next MOVF TWITCH, F ; Set zero bit if TWITCH all zero BTFSC STATUS, ZERO ; skip next if TWITCH not zero GOTO STFIN ; Case H > exit and wait for button release ; To get here must be Case I - Store in EEPROM ; Store first MOVF CHAN, W ; Load write address ANDLW 0x07 ; Mask CHAN to 0-7 MOVWF WADR ; MOVF MANFREQ, W ; Load Frequency to Data MOVWF WDATA ; CALL EPWR ; Write to EEPROM ; Then update frequency in RAM MOVF CHAN, W ; Put Channel in W ANDLW 0x07 ; Mask CHAN to 0-7 ADDLW 0x40 ; Calculate RAM address MOVWF FSR ; Load address MOVF MANFREQ, W ; Put freq in W MOVWF INDR ; Load into RAM at calculated address ; Tidy up after storing BCF CHMODE, 1 ; Clear flash MOVLW 0x02 ; 0.2 second debounce MOVWF DEBONCE ; put in DEBONCE ; Check if 0x00 written in Chan 7, if so set flag or increment band MOVF CHAN7, F ; Set zero bit if freq was 0x00 BTFSS STATUS, ZERO ; skip next if freq was zero GOTO NOTBND ; Go and clear thoughts of band change MOVF CHAN, W ; Put Channel in W ANDLW 0x07 ; Mask CHAN to 0-7 SUBLW 0x07 ; set zero bit if Chan was 7 BTFSS STATUS, ZERO ; skip next if Chan was zero GOTO NOTBND ; Go and clear thoughts of band change ; So 0x00 has been written to Chan 7. Check if first or second time MOVF BANDCH, F ; Set zero bit if first time BTFSC STATUS, ZERO ; skip next if second time GOTO INCBCH ; First time - so go and increment BANDCH ; Band change requested INCF BAND, F ; Increase the Band by one MOVF BAND, W ; Put the band in W ANDLW 0x03 ; Mask the band for 0 - 3 MOVWF BAND ; Write back to Band CLRF BANDCH ; Reset Band Change Status ; Store Band in EEPROM MOVLW 0x08 ; Load Address for band = 08 MOVWF WADR ; MOVF BAND, W ; Load BAND into Data MOVWF WDATA ; CALL EPWR ; Write to EEPROM ; Reload the new default channels CALL BANDDF ; Load new band default freqs to EEPROM CALL RCHAN ; Read new channels from EEPROM into RAM ; Set the freq and display to the current channel MOVF CHAN, W ; Read Channel into W (should be 0x07) ADDLW 0x40 ; Calculate RAM address MOVWF FSR ; Load address MOVF INDR, W ; Read frequency to W MOVWF PORTB ; Set frequency GOTO STFIN ; Exit after Band Change INCBCH INCF BANDCH, F ; Add one to band change status = 0x01 GOTO STFIN ; First write > exit and debounce NOTBND CLRF BANDCH ; this channel store not part of band change GOTO STFIN ; Case I > exit into debounce CASEL NOP ; Check for case M or M MOVF TWITCH, F ; Set zero bit if TWITCH all zero BTFSS STATUS, ZERO ; skip next if TWITCH all zero GOTO STFIN ; Case L > exit and wait for button release ; To get here must be case M BCF CHMODE, 2 ; Clear control bit MOVLW 0x02 ; 0.2 second debounce MOVWF DEBONCE ; put in DEBONCE GOTO STFIN CLROUT CLRF CHMODE ; Exit with reset, so clear CHMODE CLRF DEBONCE ; Reset debounce STFIN GOTO BUTFIN ;-------End of BUTST--------------------------------------- ;------ RCHAN ------------------------------------------------ ; RCHAN is called on startup and after band change to read ; frequencies from EEPROM ; Read Chan 0, 7 - 1 into MANFREQ and CHAN7 - CHAN1 RCHAN MOVLW 0x08 ; Initialise loop, set w to 8 MOVWF MCOUNT ; move w (8) to MCOUNT RDCHAN NOP DECF MCOUNT, F ; MCOUNT goes from 7 to 0 MOVF MCOUNT, W ; Load current count to W CALL EPRD ; Read address W, load value back to W MOVWF TMPFREQ ; temp store for freq MOVF MCOUNT, W ; Put count in W ADDLW 0x40 ; Calculate RAM address MOVWF FSR ; Load address MOVF TMPFREQ, W ; Put freq in W MOVWF INDR ; Load into RAM at calculated address MOVF MCOUNT, F ; Set zero bit if MCOUNT is zero BTFSS STATUS, ZERO ; Skip next if MCOUNT is zero (bit set) GOTO RDCHAN ; Loop again RETURN ;------ End of Sub RCHAN ----------------------------------------- ;------ FSTART --------------------------------------------------- ; FSTART is called on first ever startup to set the band and load the presets FSTART NOP MOVLW 0x02 MOVWF BAND ; set band to 2300 ; Store Band in EEPROM MOVLW 0x08 ; Load Address for Band = 08 MOVWF WADR ; MOVF BAND, W ; Load Band into Data MOVWF WDATA ; CALL EPWR ; Write to EEPROM ; Set EEPROM 0x09 to 0x55 to indicate that next start is not the first MOVLW 0x09 ; Load Address 09 MOVWF WADR ; MOVLW 0x55 ; Load Data 55 MOVWF WDATA ; CALL EPWR ; write to EEPROM CALL BANDDF ; read presets from program memory into EEPROM RETURN ;------ End of Sub FSTART ----------------------------------------- ;------ BANDDF --------------------------------------------------- ; BANDDF is called after a band change (or on first ever startup) ; to read the presets for a band and load them into EEPROM ; Arrive here with BAND set. BAND8 and CHANCNT are used by LOOKUP BANDDF NOP MOVLW 0x04 ; Load High byte of PC MOVWF PCLATH ; set high byte of PC for lookup MOVLW 0x08 ; Load 8 MOVWF CHANCNT ; Set Channel Counter to 8 (decremented to 7 before first pass) MOVF BAND, W ; Load the band into W MOVWF BAND8 ; Put BAND into BAND8 BCF STATUS, CARRY ; Clear carry bit so it doesn't get shifted in RLF BAND8, F ; Multiply BAND8 by two RLF BAND8, F ; Multiply BAND8 by two RLF BAND8, F ; Multiply BAND8 by two LULOOP DECF CHANCNT, F ; Start Loop and decrement channel CALL LOOKUP ; Return with the FREQ in W MOVWF WDATA ; Put the Frequency in data to be written MOVF CHANCNT, W ; Load Address (Chan) MOVWF WADR ; Put the Channel as EEPROM address CALL EPWR ; Write to EEPROM MOVF CHANCNT, F ; Set zero bit if CHANCNT is zero BTFSS STATUS, ZERO ; Skip next if CHANCNT is zero (bit set) GOTO LULOOP ; Go to next channel ; End Loop CLRF PCLATH ; Clear High byte of Program Counter RETURN ;------ End of Sub BANDDF ----------------------------------------- ;------ EPRD --------------------------------------------------- ; EPRD is called to read the EEPROM ; The read address is in W when called, the data is returned in W EPRD NOP BSF STATUS, RP1 ; Bank 1x BCF STATUS, RP0 ; Bank 10 (2) MOVWF EEADR ; Load address from W BSF STATUS, RP0 ; Bank 11 (3) BCF EECON1, EEPGD ; Point to Data memory BSF EECON1, RD ; Start read operation BCF STATUS, RP0 ; Bank 10 (2) NOP NOP MOVF EEDATA, W ; W = EEDATA BCF STATUS, RP1 ; Bank 00 (0) RETURN ;------ End of Sub EPRD ----------------------------------------- ;------ EPWR --------------------------------------------------- ; EPWR is called to write to the EEPROM ; The write address is in WADR when called, the data is in WDATA ; These are mirrored on Bank 2 MWADR and MWDATA EPWR NOP BSF STATUS, RP1 ; Bank 1x BCF STATUS, RP0 ; Bank 10 (2) MOVF MWADR, W ; Load write address from WADR MOVWF EEADR ; Put in Address register MOVF MWDATA, W ; Load Data from WDATA MOVWF EEDATA ; Put in data register BSF STATUS, RP0 ; Bank 11 (3) BCF EECON1, EEPGD ; Point to Data memory BSF EECON1, WREN ; Enable writes MOVLW 0x55 ; load 55 MOVWF EECON2 ; Write 55h to EECON2 MOVLW 0xAA ; Load AA MOVWF EECON2 ; Write AAh to EECON2 BSF EECON1, WR ; Start write operation WRIPX BTFSC EECON1, WR ; Check if still writing GOTO WRIPX ; Loop if still writing BCF EECON1, WREN ; Clear write enable BCF STATUS, RP1 ; Bank 0x BCF STATUS, RP0 ; Bank 00 (0) RETURN ;------ End of Sub EPWR ----------------------------------------- ORG 0X400 ; Place program segment at 0x400 ;------ LOOKUP -------------------------------------------------- LOOKUP NOP ; Arrive here with BAND8 and CHANCNT set. ; Return with freq in W ; ; Amend lines below to Change presets MOVF CHANCNT, W ; Put CHANCNT (7-0) into W ADDWF BAND8, W ; Add band as bits 3 and 4 ADDWF PCL, F ; calculate Program Counter jump based on W RETLW 0x01 ; Band 0 Chan 0 Bin 1 01 RETLW 0x02 ; Band 0 Chan 1 Bin 2 02 RETLW 0x04 ; Band 0 Chan 2 Bin 4 04 RETLW 0x08 ; Band 0 Chan 3 Bin 8 08 RETLW 0x10 ; Band 0 Chan 4 Bin 16 10 RETLW 0x20 ; Band 0 Chan 5 Bin 32 20 RETLW 0x40 ; Band 0 Chan 6 Bin 64 40 RETLW 0x80 ; Band 0 Chan 7 Bin 128 80 ; 0x00 is 1240.0 Step 0.5 RETLW 0x1E ; Band 1 Chan 0 1255 30 1E RETLW 0x10 ; Band 1 Chan 1 1248 16 10 RETLW 0x12 ; Band 1 Chan 2 1249 17 12 RETLW 0x46 ; Band 1 Chan 3 1275 70 46 RETLW 0x50 ; Band 1 Chan 4 1280 80 50 RETLW 0x70 ; Band 1 Chan 5 1296 112 70 RETLW 0x88 ; Band 1 Chan 6 1308 136 88 RETLW 0x98 ; Band 1 Chan 7 1316 152 98 ; 0x00 is 2300 Step 1 RETLW 0x64 ; Band 2 Chan 0 2400 100 64 RETLW 0x14 ; Band 2 Chan 1 2320 20 14 RETLW 0x28 ; Band 2 Chan 2 2340 40 28 RETLW 0x50 ; Band 2 Chan 3 2380 80 50 RETLW 0x58 ; Band 2 Chan 4 2388 88 58 RETLW 0x84 ; Band 2 Chan 5 2432 132 84 RETLW 0x8C ; Band 2 Chan 6 2440 140 8C RETLW 0x91 ; Band 2 Chan 7 2445 145 91 ; 0x00 is 9200 Step 4 RETLW 0xE1 ; Band 3 Chan 0 10100 225 E1 RETLW 0xC8 ; Band 3 Chan 1 10000 200 C8 RETLW 0xD8 ; Band 3 Chan 2 10064 216 D8 RETLW 0xDC ; Band 3 Chan 3 10080 220 DC RETLW 0xE6 ; Band 3 Chan 4 10120 230 E6 RETLW 0xF0 ; Band 3 Chan 5 10160 240 F0 RETLW 0xFA ; Band 3 Chan 6 10200 250 FA RETLW 0xFF ; Band 3 Chan 7 10220 255 FF ;------ End of Sub LOOKUP ----------------------------------------- END