; Stand-Alone processor for 3100 processor interface title "Stand-Alone Processor for 3100 project" ;current status: ; 24-02-2004 Basic functions working but MF command cause crashes. ; 25-02-2004 MF bug fixed. Added SAP/EXT automatic changeover. ; 29-02-2004 Fixed bug that caused drop beeps when inputs other than ; the main RX lost video. Added code to ensure the SAP ; and SYSPROC synchronised correctly at power-up. ; 15-03-2004 Timing changed for 4.096MHz clock. Added VCR power down ; and start-up routine. ; 18-03-2004 Bug fix in video selection routine that could cause func_timer ; fail to start. Bug fix in tx_to_sys that could cause data ; loss if program had to wait for UART TX buffer to empty. ; 22-03-2004 Complete re-write of MF video selection routines. Fixed ; bug in MF antenna selection routine. Added VCR auto-rewind. ; Added code to ensure TX and monitor channels carry same o/p. ; Added minutes counter and used instead of counting TCG ; cycles to time ID and rewind periods. Added code to prevent ; MF tones being decoded unless RX video is present (accessed). ; 12-04-2004 Re-mapped MF tones for star and hash to 0E and 0F to allow ; use of column 4 MF tones. ; 13-04-2004 Made VCR channel step controllable by config link.(change ; in IR_CTRL processor reqd)Cleared timers prior to main loop ; running. Added MF command 'DC' to allow remote reset. ;Uncommenting the following line will bypass UART drivers to allow debugging. ;It MUST be commented to work at all when driving real hardware! ;#define debug 1 __config _CP_OFF & _PWRTE_ON & _WDT_ON & _XT_OSC #include "P16F84A.INC" #include "\repeater\include\sa_proc.inc" #define bank_0 bcf STATUS,5 #define bank_1 bsf STATUS,5 page_0 macro bcf PCLATH,0 bcf PCLATH,1 endm page_1 macro bsf PCLATH,0 bcf PCLATH,1 endm page_2 macro bcf PCLATH,0 bsf PCLATH,1 endm ;System configuration: ;PIC register usage: cblock H'0C' TXL ;UART transmit word TXH RXL ;UART receive word RXH SHFTO ;transmit shift data to UART SHFTI ;receive shift data from UART LPCNT ;bit shift counter status_temp ;STATUS register holder during interrupts w_temp ;W register holder during interrupts tx_temp ;temporary store for W while checking UART TX status sel_temp ;temporary store for W while selecting mux channels sys_flags ;various flags of system status osg_timeout ;timer for on-screen ident display func_timeout ;timer for other functions delay ;counts TMR0 interrupts to time 1 second tcg_timer ;seconds before testcard page is changed mf_timeout ;seconds before mf sequence validation times out min_counter ;seconds counter to time one minute intervals id_timer ;minutes before auto ident is due rw_timer ;minutes remaining before automatic VCR rewind mf_data ;data from MF detector translated to real digits mf_digits ;received two-digit mf sequence mf_count ;mf queue length port_data ;last data read from a port port_address ;address of selected port resprot ;used in response type decoding sync_status ;bit map of sync detector states page_timer ;time before cancelling special functions tcg_page ;current testcard page FSRSAVE ;saves FSR during UART interrupt TXHSAVE ;saves TXH during UART interrupt TXLSAVE ;saves TXL during UART interrupt RXQHEAD ;receive queue write position RXQTAIL ;receive queue read position RXQ1 ;first queue location RXQ2 RXQ3 RXQ4 endc org 0000 ;tell assembler to start at 000H start clrwdt ;clear watchdog goto init ORG 0x004 ;interrupt vector location isr_save clrwdt movwf w_temp ;save current W register contents movf STATUS,w ;move status register into W register movwf status_temp ;save contents of STATUS register btfss INTCON,2 ;see if TMR0 caused interrupt... goto rx_int ;not TMR0 so must be UART bcf INTCON,2 ;clear TMR0 interrupt flag decfsz delay,f ;counts 225 to delay 1 second goto isr_restore ;not time yet so carry on ;here once per second movf mf_timeout,f ;set Z if already at zero btfss STATUS,Z ;skip if 0, otherwise... decf mf_timeout,f ;...count down movf tcg_timer,f ;set Z if already at zero btfss STATUS,Z ;skip if 0, otherwise... decf tcg_timer,f ;...count down movf osg_timeout,f ;set Z if already at zero btfss STATUS,Z ;skip if 0, otherwise... decf osg_timeout,f ;...count down movf func_timeout,f ;set Z if already at zero btfss STATUS,Z ;skip if 0, otherwise decf func_timeout,f ;...count down decfsz min_counter ;count seconds down goto delay_reload ;not zero yet movlw .60 ;set count for one minute movwf min_counter ;here once per minute movf id_timer,f ;set Z if already at zero btfss STATUS,Z ;skip if 0, otherwise... decf id_timer,f ;count down movf rw_timer,f ;set Z if already at zero btfss STATUS,Z ;skip if 0, otherwise... decf rw_timer,f ;count down delay_reload movlw H'FA' ;reload with 250 (clk/4/16/256/250 = 1) movwf delay rx_int btfss INTCON,1 ;see if UART caused interrupt goto isr_restore ;no so tidy up and leave isr bcf INTCON,1 ;clear the INTF interrupt flag movf FSR,w ;save the FSR (TX might be using it) movwf FSRSAVE movf TXH,w ;save TXH movwf TXHSAVE movf TXL,w ;save TXL movwf TXLSAVE clrf TXH ;0000 = UART read data command clrf TXL call utlk ;send command and receive the data ; add the received byte to the 'head' of the queue movf RXQHEAD,w ;use FSR to point to memory movwf FSR movf RXL,w ;pick up the data to write movwf INDF ;store in the queue incf RXQHEAD,f ;advance head position movf RXQHEAD,w ;check for wrap around sublw RXQ4+1 ;Z if beyond end of the queue btfsc STATUS,Z ;skip if not beyond the end goto reset_head rx_end movf TXHSAVE,w ;restore TXH and TXL movwf TXH movf TXLSAVE,w movwf TXL movf FSRSAVE,w ;restore the FSR movwf FSR isr_restore movf status_temp,w ; retrieve copy of STATUS register movwf STATUS ; restore pre-isr STATUS register contents swapf w_temp,f swapf w_temp,w ; restore pre-isr W register contents retfie ; return from interrupt reset_head movlw RXQ1 ;wrap head position back to start movwf RXQHEAD goto rx_end ; UART serial support routines. These are derived from the MAX3100 data ; sheet with port numbers modified for this application. ; send 16 bits from TXH and TXL, receive 16 bits to RXH and RXL. utlk bcf PORTB,CS ;lower the UART CS pin movf TXH,w ;get TXH to w call byt8 ;send byte 1, receive byte 1 movwf RXH ;stash receive byte 1 movf TXL,w ;get TXL to w call byt8 ;send byte 2, receive byte 2 movwf RXL ;stash byte 2 bsf PORTB,CS ;raise chip select when done return ;done byt8 movwf SHFTO ;put in shift out movlw D'8' ;load loop counter movwf LPCNT b8lp rlf SHFTO,f ;get high bit to send bcf PORTB,SDOUT ;pre-clear data out to UART btfsc STATUS,C ;see if D0 should be set bsf PORTB,SDOUT bsf PORTB,SCLK ;raise the SCLK line bcf STATUS,C ;pre-clear the carry flag btfsc PORTB,SDIN ;check data in from UART bsf STATUS,C ;set carry flag rlf SHFTI,f ;rotate D1 into shift in reg. bcf PORTB,SCLK ;drop the SCLK line decfsz LPCNT,f ;loop for all 8 bits goto b8lp movf SHFTI,w ;put result in w return ; UART transmit routine, enter with data in W. Check TX buffer empty before ; sending to SYS. tx_to_sys movwf tx_temp ;save W tbe_loop clrwdt ;before possibly looping #ifndef debug ;skip buffer check when simulating clrf TXH ;dummy read config to load UART 'T' bit bsf TXH,6 ;TXH = H'40' (read config command) clrf TXL call utlk btfss RXH,6 ;'T' (bit 6) = 1 = TX buffer is empty goto tbe_loop ;loop until buffer empties #endif movf tx_temp,w ;recover W movwf TXL movlw H'80' ;80 is the UART write data command movwf TXH call utlk return select_port andlw H'1F' ;mask for valid address bits addlw H'80' ;make into 80-9F range call tx_to_sys return send_port_data andlw H'0F' ;mask for valid data bits iorlw H'40' ;add sysproc 'write data' cmd bits call tx_to_sys return ; select the video channel that is to be routed to the transmitter output. ; enter with channel number in W. select_tx_vid_chan movwf sel_temp movlw VSEL1t ;main video router address goto tx_send ; select the audio channel that is to be routed to the transmitter output. ; enter with channel number in W. select_tx_aud_chan movwf sel_temp movlw AMUX1 ;main audio router address goto tx_send ; select the video channel that is to be routed to the monitor output. ; enter with channel number in W. select_mon_vid_chan movwf sel_temp movlw VSEL1m ;main video router address goto tx_send ; select the audio channel that is to be routed to the monitor output. ; enter with channel number in W. select_mon_aud_chan movwf sel_temp movlw AMUX2 ;main audio router address goto tx_send ; select the TCG page number select_tcg_page movwf sel_temp movlw TCGSEL ;TCG paging port address goto tx_send ;select ID message number select_ID_message movwf sel_temp movlw IDSEL ;audio ID generator address goto tx_send ;select on-screen inserted video message select_osg_message movwf sel_temp movlw OSGSEL ;OSG message selector address goto tx_send ;select an antenna number select_antenna movwf sel_temp movlw ANTSEL ;antenna selector address goto tx_send ;select a VCR function select_vcr movwf sel_temp movlw VCRSEL ;VCR IR generator port address goto tx_send ;select a weather satellite function select_wesat_function movwf sel_temp movlw METSEL ;WX satellite control address tx_send call select_port movf sel_temp,w call send_port_data ;transmit channel number movf sel_temp,w ;return with W restored return ;-------------------------------------------------------------------- ; set up the PIC configuration, interrupts and default port contents. init bank_1 movlw H'1F' movwf TRISA ;PORTA is always an input movlw H'E9' ;PORTB b0, b3 and b567 are i/p movwf TRISB bank_0 ; wait if RA4 is low, this means the external computer is in control. ; the SAP should resume control when RA4 goes high. btfss PORTA,4 ;monitor the EXT control line goto start ;loop while its low (ext controller) ; set power-up defaults: clrf PORTA ;initial port values clrf PORTB movlw RXQ1 ;queue head and tail to start movwf RXQHEAD movwf RXQTAIL movlw H'01' ;ident on first TCG page change movwf id_timer movwf tcg_timer ;change tcg page ASAP clrf mf_count ;flush the mf queue clrf mf_digits clrf func_timeout clrf sys_flags init_UART movlw H'E4' ;top of config word movwf TXH movlw BAUD ;bottom of config word movwf TXL call utlk ;write config to UART movlw H'40' ;confirm config by reading back movwf TXH clrf TXL call utlk #ifdef debug goto set_interrupt ;skip UART test if simulating #endif movf RXL,w ;compare baud rates sublw BAUD btfss STATUS,Z ;Z set if baud bits match goto init_UART ;try again set_interrupt bank_1 movlw H'83' movwf OPTION_REG ;RBPU off, TMR0 internal, prescale 16 bank_0 movlw H'30' ;INT(RB0) & TMR ints enabled movwf INTCON bsf INTCON,7 ;global interrupts enabled ; Configure the SYSPROC movlw H'F0' ;SYSPROC loopback off call tx_to_sys movlw H'F7' ;SYSPROC sync detect on call tx_to_sys movlw H'F5' ;SYSPROC initialise from EE call tx_to_sys movlw H'FD' ;SYSPROC store mode to EE call tx_to_sys movlw H'FF' ;SYSPROC reset call tx_to_sys movlw H'04' ;delay for sysproc to initialise movwf func_timeout sys_init_delay movf func_timeout,f ;check for zero btfss STATUS,Z goto sys_init_delay ;loop until timed out ; Set-up the VCR and repeater start conditions. clrw call select_osg_message clrw call select_tcg_page clrw call select_tx_vid_chan movlw H'0A' ;VCR start-up command call select_vcr movlw H'0A' ;time for VCR to start up movwf func_timeout vcr_start_delay movf func_timeout,w ;check for zero btfss STATUS,Z goto vcr_start_delay btfss PORTB,6 ;check link for auto step down goto check_id_link movlw VCR_stepdown ;command to step channel down call select_vcr check_id_link movlw H'01' ;send "1" (long ident 1) btfss PORTB,7 ;see if cfg link is fitted movlw H'03' call select_ID_message ; establish the current video status. PROC will automatically notify SAP ; when the sync status changes but at this time we need to know the status ; without waiting for a change. movlw H'FB' ;PROC command to force sync report call tx_to_sys ; misc setups clrf osg_timeout clrf func_timeout clrf rw_timer page_1 ;all running routines in page 1 goto main_loop org H'0100' ; Main program loop. main_loop clrwdt ;prevent WDT resets btfss PORTA,4 ;check if SAP still in control goto start ;if EXT is low, wait then restart movf osg_timeout,w ;check if = 1 sublw H'01' btfsc STATUS,Z ;if Z, cancel the OSG display call cancel_OSG movf func_timeout,w ;check if = 1 sublw H'01' btfsc STATUS,Z ;if Z, cancel the function call cancel_function movf rw_timer,w ;check if = 1 sublw H'01' btfsc STATUS,Z ;if Z, send 'rewind' cmd to VCR call auto_rewind movf RXQHEAD,w ;if head=tail theres nothing to do subwf RXQTAIL,w btfsc STATUS,Z ;Z if nothing queued goto check_tcg ;see if time to switch TCG page decode_incoming movf RXQTAIL,w ;pick up pointer into queue bcf INTCON,INTE ;prevent FSR changing movwf FSR incf RXQTAIL,f ;advance tail position movf RXQTAIL,w ;check for wrap around sublw RXQ4+1 ;Z if beyond end of the queue btfss STATUS,Z ;skip if not beyond the end goto decode movlw RXQ1 ;reset tail to start of queue movwf RXQTAIL ; the incoming response decoder routine ; Possible data types are: ; 0x - data has been read from a port ; 2x - data has been read from an EE address in Sysproc ; 4x - data is from the MF detector ; 6x - data contains the status byte ; 8x - data is bits 3:0 of sync detector byte. ; Ax - data is bits 7:4 of sync detector byte ; Cx - data is a loopback response ((byte sent to Sysproc) & 0x0F | C0) ; F5 - the Sysproc has reset. ; ; 0x,2x,6x and Cx should only been seen if a command requesting them is sent, ; 4x should only be received if an MF tone is detected ; 8x and Ax should only be seen if there is a change in video input status. decode movf INDF,w ;pick up data from the queue andlw H'0F' ;mask for data bits movwf port_data ;save for later movf INDF,w ;get data again bsf INTCON,INTE ;allow UART interrupts again andlw H'F0' ;mask for command bits movwf resprot ;prepare to move 7:4 to 3:0 swapf resprot,f ;response type now in 3:0 bcf STATUS,C ;must not shift carry into b7 rrf resprot,w ;now in W at 2:0 addwf PCL,f ;form offset into table goto portdata ;000 = data read from a port goto check_tcg ;001 = data from EE memory(not used) goto mf_received ;010 = data from MF decoder goto check_tcg ;011 = status byte (not used) goto sd30 ;100 = sync detect, channels 3 - 0 goto sd74 ;101 = sync detect, channels 7 - 4 goto check_tcg ;110 = data looped back (not used) goto stat_data ;111 = status information received ; if the TCG timer has reached zero, move to next page. Depending upon the ; state of RB7, either select pages 0-7 or 8-F by controlling TCG bit 3. check_tcg movf tcg_timer,f ;if zero its time to change page btfss STATUS,Z ;skip if zero goto check_id_time ;nothing to do, see if its ID time incf tcg_page,f bcf tcg_page,3 ;assume pages 0-7 btfss PORTB,7 ;if cfg link fitted, skip next bsf tcg_page,3 ;change to pages 8-F movf tcg_page,w ;page to select call select_tcg_page movlw PAGETIME ;re-load page timer movwf tcg_timer check_id_time movf id_timer,w ;read the ID timer sublw H'01' ;set Z if = 1 btfss STATUS,Z goto main_loop ;not time yet call send_vol ;send ID if it was = 1 goto main_loop ; activate the audible ID generator. If accessed, also activate visual ID. send_vol movlw ID_TIME + 1 ;reload the ID counter movwf id_timer btfss sync_status,RX_VID ;drop volume if accessed goto send_id movlw H'0F' ;reduced volume for next message call select_ID_message send_id movlw H'00' ;send "0" (callsign 1) btfss PORTB,7 ;see if cfg link is fitted movlw H'02' call select_ID_message btfss sync_status,RX_VID ;is video on receiver input? return ;no so no video ident needed movlw H'01' ;visual ID 1 btfss PORTB,7 ;see if cfg link is fitted movlw H'05' call select_osg_message movlw OSG_DISP_TIME + 1 ;start the display time timer movwf osg_timeout return auto_rewind clrf rw_timer ;zero timer to prevent more rewinds movlw VCR_rewind ;send rewind command to VCR call select_vcr return cancel_OSG clrf osg_timeout clrw ;send command 0 (display off) call select_osg_message return cancel_function clrf func_timeout ;in case user used mf reset command movlw RX_VID ;restore RX or TCG video source btfss sync_status,RX_VID movlw TCG_VID call select_tx_vid_chan return mf_received page_2 goto process_mf_data portdata goto main_loop stat_data goto main_loop ; sd30 and sd74 are always called in sequence. sd30 movf sync_status,w ;get old status andlw H'F0' ;wipe out bottom bits movwf sync_status movf port_data,w ;get the response byte in 3:0 iorwf sync_status,f goto check_func_running sd74 movf sync_status,w ;get old status andlw H'0F' ;wipe out top bits movwf sync_status swapf port_data,w ;get the response byte in 7:4 iorwf sync_status,f ;merge into top bits sd_update btfss sys_flags,0 ;skip if accessed last check goto check_new_access check_new_drop btfsc sync_status,RX_VID ;see if accessed at the moment goto check_func_running ;was accessed and still accessed bcf sys_flags,0 ;was accessed but now dropped movlw H'0D' ;send drop tones call select_ID_message clrw ;select antenna 0 call select_antenna goto check_func_running check_new_access btfss sync_status,RX_VID ;see if accessed at the moment goto check_func_running ;wasn't accessed and still isn't bsf sys_flags,0 ;wasn't accessed but is now movlw H'0E' ;send access tones call select_ID_message check_func_running movf func_timeout,f ;don't change source if func running btfss STATUS,Z ;skip if function timer not running goto main_loop ;function running - do nothing yet movlw RX_VID ;prepare to switch to RX video btfss sync_status,RX_VID ;check RX video is present... movlw TCG_VID ;use TCG instead if it isn't call select_tx_vid_chan call select_mon_vid_chan movlw RX_AUD ;prepare to switch to RX audio btfss sync_status,RX_VID ;check RX video is present... movlw EXT5_AUD ;no audio if it isn't call select_tx_aud_chan call select_mon_aud_chan movlw H'01' ;send ID shortly movwf id_timer goto main_loop ; MF processing routines all in page 2 ; an mf digit has arrived, if a '*', clear any existing digits and start the ; timeout timer. Check the next digit matches the ID and confirm the fifth ; is a '#'. Use the 2nd and 3rd digits to form a jump table ; to MF functions. Note: 'mf_translate converts * to E and # to F. org H'200' process_mf_data btfss sync_status,RX_VID ;check if accessed goto mf_end ;MF illegal without RX video movf port_data,w call mf_translate ;convert MF to real number movwf mf_data sublw H'0E' ;set Z if '*' btfss STATUS,Z goto not_star clrf mf_count ;star so clear the digit counter movlw MF_WINDOW ;start the mf sequence timeout timer movwf mf_timeout goto mf_end ;wait for more mf digits not_star movf mf_timeout,f ;if timeout isn't set, just exit btfsc STATUS,Z goto mf_invalid ;timed out or timer not started incf mf_count,f ;start counting digits movf mf_count,w ;form a jump table andlw H'07' ;restrict jump range addwf PCL,f ;jump goto mf_invalid ;zero isn't an option! goto mf_id_check ;2nd digit should be the ID goto mf_1 ;3rd digit is MS part of command goto mf_2 ;4th digit is LS part of command goto mf_check_hash ;5th digit must be a '#' goto mf_invalid ;trap stray digits goto mf_invalid mf_invalid ;atually last entry in jump table clrf mf_count clrf mf_timeout mf_end page_1 ;reset page switching goto main_loop ;MF routine exit mf_id_check movf mf_data,w btfss PORTB,7 ;if cfg link not fitted, skip next goto mf_id_2 sublw MY_ID ;check if matches first ID btfss STATUS,Z ;skip if ID matches goto mf_invalid ;no match goto mf_end mf_id_2 sublw MY_ID + 1 ;link fitted, try 2nd ID btfss STATUS,Z ;skip if ID matches goto mf_invalid ;no match goto mf_end mf_1 swapf mf_data,w ;move 1st (MSB part) to top bits movwf mf_digits ;save for later goto mf_end mf_2 movf mf_data,w iorwf mf_digits,f ;merge MSB and LSB into mf_digits goto mf_end mf_check_hash movf mf_data,w sublw H'0F' ;set Z if a '#' btfss STATUS,Z ;skip next if sequence validated goto mf_invalid ; a sequence [*] [ID] [digit] [digit] [#] has been received and ID is valid mf_check_timeout movf mf_timeout,f ;if zero a timeout ocurred btfsc STATUS,Z ;skip next if not timedout goto mf_invalid ; decode mf commands and reject those not applicable to the SAP clrf mf_timeout ;cancel timeout so ready for next mf clrf mf_count swapf mf_digits,w ;form look up table from MSD andlw H'0F' addwf PCL,f goto mf_antenna ;0x are antenna selector commands goto mf_invalid ;1x are not used with SAP goto mf_invalid ;2x are not used with SAP goto mf_invalid ;3x are not used with SAP goto mf_invalid ;4x are not used with SAP goto mf_invalid ;5x are not used with SAP goto mf_vidsel ;6x select alternative vid sources goto mf_vcr ;7x are VCR control commands goto mf_misc ;8x some commands for misc functions goto mf_cancel ;9x - only 99 used as cancel cmd goto mf_invalid ;Ax are not used with SAP goto mf_invalid ;Bx are not used with SAP goto mf_invalid ;Cx are not used with SAP goto mf_dx ;Dx (DC used for reset) goto mf_invalid ;Ex are not used with SAP goto mf_invalid ;Fx are not used with SAP mf_dx movf mf_digits,w ;only DC is to be accepted sublw H'DC' btfss STATUS,Z ;Z set if it was DC goto mf_invalid ;reject all other Dx numbers bcf INTCON,GIE ;kill ints, they reset watchdog mf_reset goto mf_reset ;wait for watchdog reset mf_antenna movf mf_digits,w ;use LSD as antenna number andlw H'0F' call select_antenna goto mf_invalid ;use as a reset of mf commands mf_vcr movlw REWIND_TIME + 1 ;reload the auto rewind timer movwf rw_timer movf mf_digits,w ;use LSD as VCR command number andlw H'0F' call select_vcr goto mf_invalid mf_misc movf mf_digits,w sublw H'82' ;set Z if cmd was 82 (send ID) btfss STATUS,Z goto try_cap_request movlw H'00' ;send "0" (callsign 1) btfss PORTB,7 ;see if cfg link is fitted movlw H'02' call select_ID_message goto mf_invalid try_cap_request movf mf_digits,w sublw H'81' ;set Z if cmd was 81 (caption on) btfss STATUS,Z goto mf_invalid movlw H'01' ;visual ID btfss PORTB,7 ;see if cfg link is fitted movlw H'05' call select_osg_message movlw OSG_DISP_TIME + 1 ;start the display time timer movwf osg_timeout goto mf_invalid mf_cancel movf mf_digits,w ;check for '99' sublw H'99' ;set Z if a reset command btfss STATUS,Z goto mf_invalid ;it wasn't 99 clrf func_timeout ;in case user used mf reset command movlw RX_VID ;restore RX or TCG video source btfss sync_status,RX_VID movlw TCG_VID call select_tx_vid_chan goto mf_invalid mf_vidsel movf mf_digits,w andlw H'07' ;only use lower bits movwf mf_digits ;save back for later call bin_map ;convert to binary bit map andwf sync_status,w ;AND bit map with sync map btfsc STATUS,Z ;skip if video is present goto mf_invalid ;Z set means no sync present movf mf_digits,w ;get the LSB of MF digit back call vid_map ;translate to video channel number call select_tx_vid_chan ;select TX video channel call select_mon_vid_chan ;select monitor video channel movf mf_digits,w ;get the LSB of MF digit back call aud_map ;translate to audio channel number call select_tx_aud_chan ;select TX audio channel call select_mon_aud_chan ;select monitor audio channel clrw ;assume WX channel 0 btfsc mf_digits,0 ;see which WXSAT channel to select movlw H'01' ;select WX channel 1 call select_wesat_function ;all WXSAT bits to zero movlw FUNCTION_TIME ;start the function timer movwf func_timeout goto mf_invalid bin_map addwf PCL,f ;form a jump table retlw B'00001000' ;bit 3 (60) EXT1 (WX) - back 2 retlw B'00001000' ;bit 3 (61) EXT1 (WX) - back 2 retlw B'00010000' ;bit 4 (62) EXT2 - back 3 retlw B'00100000' ;bit 5 (63) EXT3 - front 1 retlw B'01000000' ;bit 6 (64) EXT4 - front 2 retlw B'10000000' ;bit 7 (65) EXT5 - not connected retlw B'00000010' ;bit 1 (66) ISO - front 'D' retlw B'00000100' ;bit 2 (67) RX - back 1 vid_map addwf PCL,f ;table maps MF digit to channel retlw EXT1_VID ;(60) WX sat - back panel retlw EXT1_VID ;(61) WX sat retlw EXT2_VID ;(62) back panel retlw EXT3_VID ;(63) retlw EXT4_VID ;(64) retlw EXT5_VID ;(65) retlw ISO_VID ;(66) retlw TCG_VID ;(67) aud_map addwf PCL,f ;table maps MF digit to channel retlw EXT1_AUD ;(60) retlw EXT1_AUD ;(61) retlw EXT2_AUD ;(62) retlw EXT3_AUD ;(63) retlw EXT4_AUD ;(64) retlw EXT5_AUD ;(65) retlw ISO_AUD ;(66) retlw RX_AUD ;(67) mf_translate addwf PCL,f ;jump into look-up table retlw H'0D' ;tone 0 = digit 'D' retlw H'01' ;1 = '1' retlw H'02' ;2 = '2' retlw H'03' ;3 = '3' retlw H'04' ;4 = '4' retlw H'05' ;5 = '5' retlw H'06' ;6 = '6' retlw H'07' ;7 = '7' retlw H'08' ;8 = '8' retlw H'09' ;9 = '9' retlw H'00' ;A = '0' retlw H'0E' ;B = '*' retlw H'0F' ;C = '#' retlw H'0A' ;D = 'A' retlw H'0B' ;E = 'B' retlw H'0C' ;F = 'C' end