;********************************************************************** ; * ; Filename: navtex1_2.asm * ; Date: 24.12.2002 * ; File Version: 1.2 * ; * ; Author: Mikael Nordman * ; Copyright: Mikael Nordman * ; * ; * ;********************************************************************** ; * ; Files required: * ; * ; * ; * ;********************************************************************** ; * ; Notes: * ; * ; * ; * ; * ;********************************************************************** list p=16f876 ; list directive to define processor #include ; processor specific variable definitions __CONFIG _CP_OFF & _WDT_OFF & _PWRTE_ON & _HS_OSC & _LVP_OFF & _BODEN_OFF ; '__CONFIG' directive is used to embed configuration data within .asm file. ; The lables following the directive are located in the respective .inc file. ; See respective data sheet for additional information on configuration word. ;***** VARIABLE DEFINITIONS ram equ 0x20 fsr_temp equ h'7d' w_temp equ h'7e' status_temp equ h'7f' cp0 equ ram + 0 cp1 equ ram + 1 k_down equ ram + 2 fbits equ ram + 3 sample equ ram + 4 sbits equ ram + 5 sbitcnt equ ram + 6 rx equ ram + 7 dx equ ram + 8 dx1 equ ram + 9 dx2 equ ram + h'a' rxasc equ ram + h'b' dx2asc equ ram + h'c' shift equ ram + h'd' errors equ ram + h'e' m_delay equ ram + h'f' f_all equ ram + h'10' k_up equ ram + h'11' count1 equ ram + h'12' count2 equ ram + h'13' gchar equ ram + h'14' x equ ram + h'15' y equ ram + h'16' row equ ram + h'17' wsave equ ram + h'18' cp0_prev equ ram + h'19' cp1_prev equ ram + h'1a' diff0 equ ram + h'1b' diff1 equ ram + h'1c' result equ ram + h'1d' k_mode equ ram + h'1e' addr_lo equ ram + h'1f' addr_hi equ ram + h'20' base_lo equ ram + h'21' base_hi equ ram + h'22' sbase_lo equ ram + h'23' sbase_hi equ ram + h'24' srow equ ram + h'25' s_delay equ ram + h'26' flags equ ram + h'27' n_count equ ram + h'28' fbit equ ram + h'29' samplecnt equ ram + h'2a' setdelay equ ram + h'2b' setadjust equ ram + h'2c' msgstate equ ram + h'2d' lcdchar equ ram + h'32' ch0 equ ram + h'33' ch1 equ ram + h'34' ch2 equ ram + h'35' ch3 equ ram + h'36' ch4 equ ram + h'37' ch5 equ ram + h'38' ch6 equ ram + h'39' ch7 equ ram + h'3a' ch8 equ ram + h'3b' ch9 equ ram + h'3c' ch10 equ ram + h'3d' ch11 equ ram + h'3e' ch12 equ ram + h'3f' ch13 equ ram + h'40' ch14 equ ram + h'41' ch15 equ ram + h'42' ch16 equ ram + h'43' ch17 equ ram + h'44' ch18 equ ram + h'45' ch19 equ ram + h'46' rx_i equ ram + h'47' rx_state equ ram + h'48' rxt equ h'7c' rx0 equ h'a0' ; A0 - EF is the serial receive buffer, 80 bytes, bank 1 rx2 equ h'a2' rx3 equ h'a3' rx4 equ h'a4' rx6 equ h'a6' ; PORTA bits LCD_RESET equ 0 RD_ equ 1 CE equ 2 CD equ 3 K_MODE equ 4 WR_ equ 5 ; PORTC bits K_UP equ 0 CPT2 equ 1 LO equ 2 LED equ 3 K_DOWN equ 4 NC equ 5 ; flags bits WRAP_ON equ 0 LINE_WRAP equ 1 ;****************************************************************** ; define the nominal 18432 KHz crystal real frequency here !!!!!!!!!!!!!!!! ; 1 KHz accuracy needed here CRYSTAL equ d'18439000' ; 18439 KHz ;****************************************************************** ; calculations for the FSK demodulator central frequency constant local if = d'518000' - (CRYSTAL / d'36') local div = CRYSTAL / if local cnt_lo = div & d'255' local cnt_hi = div / d'256' ;********************************************************************** ORG 0x000 ; processor reset vector clrf PCLATH ; ensure page bits are cleared goto main ; go to beginning of program ;*********************************************************************** ; THE INTERRUPT ROUTINE ORG 0x004 ; interrupt vector location movwf w_temp ; save off current W register contents swapf STATUS, W ; move status register into W register clrf STATUS movwf status_temp ; save off contents of STATUS register movfw FSR movwf fsr_temp bcf INTCON, T0IF ; Only timer0 interrupt exists movlw d'17' ; divide by 240, load 17 movwf TMR0 chk_capt: btfss PIR2, CCP2IF goto chk_t0if ; This was not a capture event bcf PIR2, CCP2IF ; Clear capture interrupt flag movfw cp0 ; save previous captured timer1 value movwf cp0_prev movfw cp1 movwf cp1_prev movfw CCPR2L ; save new captured timer1 value movwf cp0 movfw CCPR2H movwf cp1 chk_t0if: call samplebit call checkkey btfsc PIR1, RCIF ; RCIF is cleared automagically by the HW call serial_int intret: movfw fsr_temp movwf FSR swapf 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 ;*********************************************************************************** ; Timer interrupt ; Sample sitor bits every 10 ms ; Sample bitsamples every 833,33 us ; 00001111 is considered to be a sitor signal rising edge. ; samplebit: rlf fbits, F ; Make place for new sample ;diff = cp - cp_old; movf cp0_prev, W subwf cp0, W movwf diff0 movf cp1_prev, W btfss STATUS, C incf cp1_prev, W subwf cp1, W movwf diff1 ;if (diff < 3161(0xc59)) { ;xtal = 18438 kHz mid = (58xx Hz) 3161(0xc59) ;xtal = 18432 kHz mid = (6000 Hz) 3072(0xc00), low = (5930 Hz), hi = (6070 Hz) ;xtal = 18440 kHz mid = (5777 Hz) 3191(0xc77), low = (5707 Hz), hi = (5847 Hz) ;xtal = 18439,5 mid = (5791 Hz) 3184(0xc70), low = (5720 Hz) 3223, hi = (5860 Hz) 3146 movlw cnt_hi subwf diff1, W movlw cnt_lo btfsc STATUS, Z subwf diff0, W btfsc STATUS, C goto intsam1 goto intsam0 intsam0: bcf fbits, 0 goto intsamcont intsam1: bsf fbits, 0 intsamcont: decfsz sample, F ; sample--; goto setsample ; if sample != 0, try to set the sampling time movlw D'12' ; else, take a sample movwf sample clrf fbit movlw 8 movwf samplecnt sampleloop: rlf fbits, F btfsc STATUS, C incf fbit, F decfsz samplecnt, F ; count the sum of the bits in fbits goto sampleloop rlf fbits, F ; Restore the last bit from the carry flag rlf sbits, F ; make space for a new bit movlw 5 ; Is it 1 or 0 ? subwf fbit, W bc sample0 ; Note inversion of sampled bit AND ; inversion of Carry flag after a SUB sample1: bsf sbits, 0 goto samcont sample0: bcf sbits, 0 samcont: incf sbitcnt, F ; sbitcnt++ return setsample: movlw 0xf subwf fbits, W btfss STATUS, Z return ; return if not an edge. movfw setadjust addwf setdelay, F ; set the bitclock adjustment delay btfss STATUS, C ; adjust the bitclock if setdelay wraps return movlw 6 ; sample should be 6, if we are in phase. subwf sample, W bz samret ; if sample = 6 then donothing bnc saminc decf sample, F ; if sample > 6 then sample-- return saminc: incf sample, F ; if sample < 6 then sample++ samret: return ;*************************************************************************** ; check if display should be scrolled up or down ; a key is considered pressed if all 8 samples are 0. pullup at port. checkkey: decf s_delay, F decf m_delay, F rlf k_up, F ; Make place for new sample btfsc PORTC, K_UP goto k_up1 bcf k_up, 0 goto k_up2 k_up1: bsf k_up, 0 k_up2: rlf k_down, F ; Make place for new sample btfsc PORTC, K_DOWN goto k_down1 bcf k_down, 0 goto k_down2 k_down1: bsf k_down, 0 k_down2: rlf k_mode, F ; Make place for new sample btfsc PORTA, K_MODE goto k_mode1 bcf k_mode, 0 goto k_mode2 k_mode1: bsf k_mode, 0 k_mode2: return ;*************************************************************************** serial_int: movfw RCREG movwf rxt movwf TXREG btfsc RCSTA, FERR goto seri_err btfsc RCSTA, OERR goto seri_err btfsc rx_state, 1 return movfw rxt sublw '$' bz ser_state1 btfss rx_state, 0 return movfw rx_i addlw rx0 movwf FSR movfw rxt movwf INDF sublw 0xd ;Carriage return bz ser_state2 movfw rx_i sublw d'79' bnc ser_state0 ; Carry meaning is inverted for subtraction incf rx_i, F return ser_state0: clrf rx_i bcf rx_state, 1 bcf rx_state, 0 return ser_state1: clrf rx_i bcf rx_state, 1 bsf rx_state, 0 return ser_state2: clrf rx_i bsf rx_state, 1 bcf rx_state, 0 return seri_err: clrf rx_i bcf rx_state, 0 bcf rx_state, 1 bcf RCSTA, CREN bsf RCSTA, CREN return ;*************************************************************************** ; THE MAIN LOOP main: clrf msgstate clrf rx_i clrf rx_state clrf sbits clrf fbits clrf sbitcnt clrf x clrf y clrf row clrf srow clrf addr_lo clrf addr_hi clrf base_lo clrf base_hi clrf sbase_lo clrf sbase_hi clrf flags bsf m_delay, 7 bsf s_delay, 7 clrf f_all movlw d'12' ; 12 samples per sitor bit movwf sample ; Configure timer0 ; xtal = 18.432 Mhz, timeout = 0,833333 ms, ; 12 samples / bit ; prescaler = 16, timer0 counts = 240 movlw b'00001111' movwf PORTA clrf PORTB clrf PORTC bsf STATUS, RP0 ; set file bank 1 movlw B'11010011' ; prescaler 16 movwf OPTION_REG movlw h'6' ; PORT A is all digital movwf ADCON1 clrf TRISA bsf TRISA, K_MODE ; Mode input clrf TRISB movlw b'10011010' ; b3, b4 are up down scroll inputs movwf TRISC bcf STATUS, RP0 ; set file bank 0 ; Init Module 2 for capture of the navtex fsk period movlw b'00000110' ; Capture on every fourth rising edge on RC1 movwf CCP2CON clrf TMR1H clrf TMR1L movlw b'00000001' ; Enable timer1 at the internal clock Fosc/4 movwf T1CON ; Init Module1 for PWM at 512 kHz ; Xtal = 18432, clk = 18432/4 = 4608, bsf STATUS, RP0 movlw 8 movwf PR2 ; PR = 8, division = (PR + 1) = 9 bcf STATUS, RP0 movlw 4 movwf CCPR1L ; Set duty cycle to about 50 % movlw b'00000100' ; TMR2 on, Prescaler=1, Crystal = 18432 movwf T2CON movlw b'00001111' ; PWM mode movwf CCP1CON ; Initalise the LCD display call init_lcd ; Initialise the RS port for reception ; 4800 baud, 8bit, no parity bsf STATUS, RP0 movlw d'59' ; 4800 baud movwf SPBRG clrf TXSTA bsf TXSTA, TXEN clrf STATUS bcf RCSTA, RX9 bsf RCSTA, SPEN ; RC7/RX, RC6/TX bsf RCSTA, CREN ; Enable asynchronous continuous receive ; Configure interrupt ; Enable the timer0 interrupt and peripheral interrupts movlw B'01100000' ; Enable peripheral and timer0 interrupt movwf INTCON ; START WITH CLEARING THE VARIABLES state0: movlw 0xff ; setadjust = ff, adjust sitor clock on every signal edge movwf setadjust clrf errors clrf shift clrf rx clrf dx clrf dx1 clrf dx2 bcf flags, LINE_WRAP movlw h'97' call cput ; text on, cursor blinking, graphics off ; SYNCRONISING TO THE SITOR SIGNAL state1: call get1bit ; returns with 7 latest bits in w sublw 0x78 btfss STATUS, Z goto state1 ; loop in state1 until 0x78 received state2: call get7bits sublw 0x33 btfss STATUS, Z goto state1 ; 0x33 must be received here state3: call get7bits sublw 0x78 btfss STATUS, Z goto state1 ; 0x78 must be received here clrf x call set_addr ; set writing address to navtex buffer call set_base ; display the navtex buffer movlw h'10' ; adjust sitor clock on every sixteenth signal edge movwf setadjust bcf rx_state, 7 ; make sure nmea is displayed after navtex is finished movlw h'96' call cput ; text on, cursor fixed, graphics off ;*************************************************************************** ; SYNCHRONISATION COMPLETE ; START RECEIVING ; GET FIRST CHARACTER receive1: movf dx1, W movwf dx2 movf dx, W movwf dx1 bcf PORTC, LED call get7bits movwf dx bsf PORTC, LED ; GET SECOND CHARACTER call get7bits movwf rx sublw 0x78 btfsc STATUS, Z ; If IDLE received, start from first character goto receive1 ; TRANSLATE RX to ASCII btfsc shift, 0 bsf rx, 7 ; set msb of rx according to shift movf rx, W call sitoasc movwf rxasc bcf rx, 7 ; clear msb of RX, only needed during translation ; TRANSLATE DX2 to ASCII btfsc shift, 0 bsf dx2, 7 movf dx2, W call sitoasc movwf dx2asc bcf dx2, 7 movf rxasc, F ; check rxasc btfsc STATUS, Z goto rxmutilated ; rx zero ; rxasc was OK, check dx2asc chkdx2: movf dx2asc, F ; check dx btfsc STATUS, Z ; goto testltrs ; rx is OK dx zero movf rxasc, W subwf dx2asc, W btfsc STATUS, Z goto rxisdx ; rx = dx goto bothdifferent ; dx2asc was zero rxisdx: movf errors, F bz testltrs ; if rx and dx are ok decf errors, F ; decrement errors until zero goto testltrs rxmutilated: movf dx2, W movwf rx ; dx2 -> rx movf dx2asc, W movwf rxasc movf rxasc, F btfsc STATUS, Z goto bothmutilated testltrs: movf rxasc, W sublw 'L' btfss STATUS, Z goto testfigs bcf shift, 0 goto chkerr testfigs: movf rxasc, W sublw 'F' btfss STATUS, Z goto printrx bsf shift, 0 goto chkerr bothmutilated: bothdifferent: incf errors, F ; errors++ goto chkerr printrx: movfw errors addlw h'a1' ; set cursor to errors + 2 lines high call cput movfw rxasc call filter chkerr: movf dx2, W sublw 0x78 btfsc STATUS, Z goto state0 movf errors, W sublw 0x6 btfss STATUS, Z goto receive1 goto state0 ;********************************************************************** ; SUBROUTINES ;********************************************************************** ; WAIT UNTIL 7 NEW BITS HAVE ARRIVED get7bits: bsf INTCON, GIE ; ENABLE GLOBAL INTERRUPT BIT nop bcf INTCON, GIE ; DISABLE GLOBAL INTERRUPT BIT movf sbitcnt, W sublw 6 bc get7bits clrf sbitcnt movf sbits, W andlw 0x7f ; mask bit 7 away bsf INTCON, GIE ; ENABLE GLOBAL INTERRUPT BIT return ; WAIT UNTIL 1 NEW BIT HAS ARRIVED get1bit: bsf INTCON, GIE ; ENABLE GLOBAL INTERRUPT BIT call mode call scroll goto serial ; Cannot use call due to exhausted stack get1bit_ret: bcf INTCON, GIE ; DISABLE GLOBAL INTERRUPT BIT movf sbitcnt, F bz get1bit clrf sbitcnt movf sbits, W andlw 0x7f ; mask bit 7 away bsf INTCON, GIE ; ENABLE GLOBAL INTERRUPT BIT return ;**************************************************************************** ;**************************************************************************** ; 6963c CONTROL ROUTINES ;**************************************************************************** ; LCD pin numbering for TOSHIBA TLX-711A-E0 (uses T6963C controller) ; ; LCD Pin ----- PIC Port Pin Status Reg. bit ; ------------------------------------------ ; C/D (8) <--> (RA3) /SEL 3 ; /WR (5) <--> (RA0) Init 2 ; /RD (6) <--> (RA1) /LF 1 ; /CE (7) <--> (RA2) /Strobe 0 ; ----------------------- ; D0 (11) <--> (RB0) D0 ; D1 (12) <--> (RB1) D1 ; D2 (13) <--> (RB2) D2 ; D3 (14) <--> (RB3) D3 ; D4 (15) <--> (RB4) D4 ; D5 (16) <--> (RB5) D5 ; D6 (17) <--> (RB6) D6 ; D7 (18) <--> (RB7) D7 ; GND (2) <--> (xxx) GND ; -------------------------------------------------------------- ; FG (1) frame ground ; +5V (3) LCD logic supply ; -7.8V (4) LCD display contrast ; FS (19) font select (FS0 = 0, FS1 = 1) ; RST (10) active low ; ;******************************************************* ; WAIT UNTIL LCD is READY TO RECEIVE DATA ;******************************************************* lcd_ready: bsf STATUS, RP0 ; Address TRISB movlw 0xff movwf TRISB ; Make Port B an input bcf STATUS, RP0 ; Address PORTB bsf PORTA, WR_ ; WR high bsf PORTA, CD ; CD high lcd_ready1: bcf PORTA, RD_ ; RD low bcf PORTA, CE ; CE low movf PORTB, W ; Read PORTB bsf PORTA, CE ; CE high andlw 3 ; Check 2 lowest bits sublw 3 bnz lcd_ready1 ; Wait until lcd is ready bsf PORTA, RD_ bcf PORTA, CD bsf STATUS, RP0 clrf TRISB ; Make PORTB an output bcf STATUS, RP0 return ;******************************************************** ; Write data byte (W) to LCD module ;******************************************************** dput: movwf wsave call lcd_ready movf wsave, W movwf PORTB ; write data to lcd bcf PORTA, CD ; CD low bcf PORTA, WR_ ; WR low bcf PORTA, CE ; CE low bsf PORTA, CE ; CE high return ;******************************************************** ; Write command byte to lcd module ;******************************************************** cput: movwf wsave call lcd_ready movf wsave, W movwf PORTB bsf PORTA, CD bcf PORTA, WR_ bcf PORTA, CE bsf PORTA, CE return ;******************************************************* ; Get data byte from lcd (not verified) ;******************************************************* ;dget: ; call lcd_ready ; bsf STATUS, RP0 ; Address TRISB ; movlw 0xff ; movwf TRISB ; Make Port B an input ; bcf STATUS, RP0 ; Address PORTB ; ; bsf PORTA, WR_ ; Not write mode ; bcf PORTA, CD ; Data mode ; bcf PORTA, RD_ ; Read Mode ; bcf PORTA, CE ; Chip enable ; nop ; movfw PORTB ; movwf lcd_byte_in ; bsf PORTA, CE ; Chip disable ; bsf PORTA, RD_ ; Disable Read mode ; ; bsf STATUS, RP0 ; clrf TRISB ; Make PORTB an output ; bcf STATUS, RP0 ; return ;********************************************************* ; init_lcd ;********************************************************* init_lcd: nop nop bsf PORTA, LCD_RESET; clear display reset line ; set GPS write address movlw d'160' call dput movlw d'30' call dput movlw h'24' call cput call clear_screen call set_base call set_addr ; set navtex write address call clear_screen ; clear screen call set_addr ; restore navtex write address movlw d'40' call dput movlw 0 call dput movlw h'41' ; set text area call cput ; set 40 bytes per text row movlw h'80' ; OR writing mode internal fonts call cput movlw h'a1' ; set cursor to 2 lines high call cput movlw 0 call dput movlw 0 call dput movlw 0x21 call cput ; put cursor at (0,0) movlw h'97' call cput ; text on, cursor blinking, graphics off return ;********************************************************************** clear_row: movlw d'40' movwf count1 clr_loop: movlw 0 call dput movlw h'c0' call cput decfsz count1, F goto clr_loop return ;********************************************************************** clear_screen: movlw h'40' movwf count1 movlw h'2' movwf count2 cls_loop: movlw 0 call dput movlw h'c0' call cput decfsz count1, F goto cls_loop decfsz count2, F goto cls_loop return ;***************************************************************** ; set base address to beginning of next row inc_base: movlw d'40' addwf base_lo, F bnc set_base incf base_hi, F ; write base address to display set_base: movfw base_lo movwf sbase_lo call dput movfw base_hi movwf sbase_hi call dput movlw h'40' call cput ; set text home address return ; write gps base address to display set_gbase: movlw d'160' call dput movlw d'30' call dput movlw h'40' call cput ; set text home address return ;***************************************************************** ; set ram address to beginning of next row inc_addr: movlw d'40' addwf addr_lo, F bnc set_addr incf addr_hi, F ; write ram address to display set_addr: movfw addr_lo call dput movfw addr_hi call dput movlw h'24' call cput return ;********************************************************* ; write one character to the lcd ;********************************************************* lcd_put: movwf lcdchar movf lcdchar, F btfsc STATUS, Z return ; return if zero char movfw y subwf row, W movwf srow movfw lcdchar sublw 'D' bz crlf ; CRLF btfss flags, LINE_WRAP goto eat_space line_wrap: bcf flags, LINE_WRAP movfw lcdchar sublw ' ' bz eat_space call move_word goto char_to_lcd eat_space: movf x, F bnz char_to_lcd movfw lcdchar sublw ' ' bz set_cursor char_to_lcd: incf x, F movlw h'20' subwf lcdchar, W ; Adjust to LCD character table call dput movlw h'c0' call cput check_x: movfw x sublw d'39' bc set_cursor bsf flags, LINE_WRAP clrf x incf y, F incf row, F call inc_addr goto check_row crlf: movf x, F bz set_cursor bcf flags, LINE_WRAP clrf x incf y, F incf row, F call inc_addr check_row: movfw row sublw d'195' bnc wraparound movfw y sublw d'7' bnc newrow goto set_cursor1 set_cursor: bcf flags, LINE_WRAP set_cursor1: movfw x call dput movfw y call dput movlw h'21' call cput ; set_cursor(x,y) return newrow: movlw 7 movwf y incf srow, F call inc_base call clear_row call set_addr goto set_cursor1 wraparound: clrf y clrf x clrf base_lo clrf base_hi clrf sbase_lo clrf sbase_hi clrf addr_lo clrf addr_hi clrf row clrf srow call set_base call set_addr call clear_screen call set_addr bsf flags, WRAP_ON goto set_cursor ;********************************************************* ; Check if all or selected messages should be displayed mode: movf k_mode, F bnz mode_ret movf m_delay, F bnz mode_ret mode_change: comf f_all, F mode_ret: movf f_all, F bz mode_selected btfss rx_state, 0 goto led_off goto led_on mode_selected: btfss rx_state, 0 goto led_on ; goto led_off led_off: bcf PORTC, LED return led_on: bsf PORTC, LED return ;********************************************************* ; check if display should be scrolled up or down scroll: movf k_up, F bz scroll_up movf k_down, F bz scroll_down movlw 10 movwf s_delay return scroll_up: bsf rx_state, 7 call scroll_set movf s_delay, F bnz scroll_ret movlw h'ff' movwf s_delay movlw h'94' call cput ; text on, cursor off, graphics off ; if (srow == row) return; movf row, W subwf srow, W bz scroll_ret ; if (srow != 0) { movf srow, F bz su_wrap ; srow--; decf srow, F ; sbase = sbase - 40 movlw d'40' subwf sbase_lo, F btfss STATUS, C decf sbase_hi, F goto scroll_set su_wrap: btfss flags, WRAP_ON goto scroll_ret ; if (row < 188) { movlw d'188' subwf row, W btfsc STATUS, C goto scroll_ret ; srow = 188 movlw d'188' movwf srow ; sbase = 188*40 movlw d'96' movwf sbase_lo movlw d'29' movwf sbase_hi goto scroll_set ;*************************************************************************** scroll_down: call scroll_set movf s_delay, F bnz scroll_ret movlw h'ff' movwf s_delay movlw h'94' call cput ; text on, cursor off, graphics off ; if (srow == (row - y)) return; movfw y subwf row, W subwf srow, W bnz sd_chk_wrap bcf rx_state, 7 ; allow gps display return sd_chk_wrap: ; if (srow < 188) { movlw d'187' subwf srow, W btfsc STATUS, C goto sd_wrap ; srow ++ incf srow, F ; sbase = sbase + 40 movlw d'40' addwf sbase_lo, F btfsc STATUS, C incf sbase_hi, F goto scroll_set sd_wrap: clrf srow clrf sbase_lo clrf sbase_hi scroll_set: movfw sbase_lo call dput movfw sbase_hi call dput movlw h'40' call cput ; set text home address scroll_ret: return ;********************************************************* ; filter messages ; find zczc_abxy ; zczc_ is start of message ; a is station id ; b is message type ; xy is message number ; ; nnnn is end of message, it should be moved here also ;********************************************************** filter: movwf lcdchar sublw h'a' bz filter_ret ; No LF into the fifo movfw lcdchar sublw 'A' ; No Phasing signal into the fifo bz filter_ret movfw lcdchar sublw 'B' ; No Phasing signal into the fifo bz filter_ret ; advance the fifo movlw d'20' movwf count1 ; moves also lcdchar to ch0 ! movlw ch18 movwf FSR filter1: movfw INDF incf FSR, F movwf INDF decf FSR, F decf FSR, F decfsz count1, F goto filter1 ; search for zczc_ movfw ch8 sublw 'z' bnz chk_nnnn movfw ch7 sublw 'c' bnz chk_nnnn movfw ch6 sublw 'z' bnz chk_nnnn movfw ch5 sublw 'c' bnz chk_nnnn movfw ch4 sublw ' ' bnz chk_nnnn movf f_all, F ; Print all messages bnz f_msgstate ; if f_all <> 0 f_st_id1: movlw 'u' ; Tallinn subwf ch3, W bz f_msgtype1 f_st_id2: movlw 'h' ; Härnösand subwf ch3, W bnz set_msgstate_0 f_msgtype1: movlw 'e' ; Weather forecast subwf ch2, W bz f_msgstate f_msgtype2: movlw 'b' ; Meteorogical warning subwf ch2, W bz f_msgstate f_msgtype3: movlw 'd' ; Search and rescue subwf ch2, W bnz set_msgstate_0 f_msgstate: movf msgstate, F bnz chk_nnnn ; state was 0 and ; it was an approved start of message ; print out the the string bsf msgstate, 0 ; msgstate = 1 receive message ; print message identification movlw 'D' ; CRLF call lcd_put movlw 9 movwf count1 movlw ch8 movwf FSR filter2: movfw INDF call lcd_put decf FSR, F decfsz count1, F goto filter2 movlw 'D' ; CRLF call lcd_put return ; search for nnnn set_msgstate_0: clrf msgstate chk_nnnn: movfw ch3 sublw 'n' bnz c_out movfw ch2 sublw 'n' bnz c_out movfw ch1 sublw 'n' bnz c_out movfw ch0 sublw 'n' bnz c_out movf msgstate, F bz msgstate_0 movfw ch0 call lcd_put movlw 'D' ; CRLF call lcd_put clrf msgstate ; msgstate = 0, end of message. stop printing return c_out: movf msgstate, F bz msgstate_0 movfw ch0 call lcd_put filter_ret: msgstate_0: return ;*********************************************************************** move_word: movfw ch1 sublw ' ' btfsc STATUS, Z return ; return if previous line ended in space incf x, F ; find space on previous line movlw d'18' movwf count1 movlw ch2 movwf FSR move_word0: movfw INDF sublw ' ' bz move_word1 incf x, F incf FSR, F decfsz count1, F goto move_word0 clrf x return ; return if no space was found move_word1: ; space was found ; set writing mode to decrement the address pointer ; write 'count1' spaces ; set writing mode to increment ; restore the write address by call set_addr ; write the string on the next row movfw x movwf count1 ; setup the amount of backspace incf count1, F move_word2: movlw 0 call dput movlw h'c2' ; write and decrease the address pointer call cput decfsz count1, F ; write as many zeroes as needed goto move_word2 call set_addr ; restore the address pointer to the beginning of the row movlw ch0 addwf x, W movwf FSR ; point to first character to print movfw x movwf count1 ; set the count of characters to print move_word3: movlw h'20' subwf INDF, W call dput movlw h'c0' call cput decf FSR, F decfsz count1, F goto move_word3 return ;*********************************************************************** g_out: movwf gchar movlw h'20' subwf gchar, W ; Adjust to LCD character table call dput movlw h'c0' call cput return ;*********************************************************************** serial: btfss rx_state, 1 goto get1bit_ret ; check for GLL message bcf rx_state, 1 btfss rx_state, 7 call set_gbase ; do not show gps screen in scroll mode movlw h'94' call cput ; text on, cursor off, graphics off ser_chk_gll: movlw rx2 movwf FSR movfw INDF sublw 'G' bnz ser_chk_vtg incf FSR, F movfw INDF sublw 'L' bnz ser_chk_vtg incf FSR, F movfw INDF sublw 'L' bnz ser_chk_vtg goto display_gll ser_chk_vtg: movlw rx2 movwf FSR movfw INDF sublw 'V' bnz ser_chk_apb incf FSR, F movfw INDF sublw 'T' bnz ser_chk_apb incf FSR, F movfw INDF sublw 'G' bnz ser_chk_apb goto display_vtg ser_chk_apb: movlw rx2 movwf FSR movfw INDF sublw 'A' bnz get1bit_ret incf FSR, F movfw INDF sublw 'P' bnz get1bit_ret incf FSR, F movfw INDF sublw 'B' bnz get1bit_ret goto display_apb ;************************************************* ; find next comma and point to the next information element next_element: movfw INDF sublw ',' bz next_element_ret incf FSR, F goto next_element next_element_ret: incf FSR, F return ;*********************************************************************** display_element_a: movfw INDF sublw ',' bz disp_elem_a_ret movfw INDF sublw '*' bz disp_elem_a_ret movfw INDF sublw 0xd bz disp_elem_a_ret movfw INDF call g_out incf FSR, F goto display_element_a disp_elem_a_ret: incf FSR, F return ;*********************************************************************** display_element_b: movfw INDF sublw '.' bz disp_elem_b_ret movfw INDF call g_out incf FSR, F goto display_element_b disp_elem_b_ret: incf FSR, F return ;*********************************************************************** display_gll: movlw d'160' call dput movlw d'30' call dput movlw h'24' call cput movlw 'L' call g_out movlw 'A' call g_out movlw 'T' call g_out movlw ':' call g_out movlw rx6 movwf FSR disp_lat: call display_element_a ; Latitude lat_sign: call display_element_a ; North Oder South movlw ' ' call g_out movlw 'L' call g_out movlw 'O' call g_out movlw 'N' call g_out movlw ':' call g_out disp_lon: call display_element_a ; Longitude lon_sign: call display_element_a ; East Oder West movlw ' ' call g_out movlw 'U' call g_out movlw 'T' call g_out movlw 'C' call g_out movlw ':' call g_out disp_time: call display_element_b ; Time goto get1bit_ret ;*********************************************************************** display_vtg: movlw d'240' call dput movlw d'30' call dput movlw h'24' call cput movlw rx6 movwf FSR call next_element call next_element movlw 'T' call g_out movlw 'R' call g_out movlw 'K' call g_out movlw ':' call g_out call display_element_a ; Track call display_element_a ; Magnetic movlw ' ' call g_out movlw 'S' call g_out movlw 'P' call g_out movlw 'D' call g_out movlw ':' call g_out call display_element_a ; Speed movlw 'K' call g_out movlw 't' call g_out movlw ' ' call g_out movlw ' ' call g_out movlw ' ' call g_out movlw ' ' call g_out goto get1bit_ret ;*********************************************************************** display_apb: movlw d'64' call dput movlw d'31' call dput movlw h'24' call cput movlw rx6 movwf FSR call next_element call next_element movlw 'X' call g_out movlw 'T' call g_out movlw 'E' call g_out movlw ':' call g_out call display_element_a ; Cross Track error movlw ' ' call g_out call display_element_a ; Direction to steer movlw ' ' call g_out call display_element_a ; XTE units movlw ' ' call g_out call display_element_a ; Status A = arrival circle entered movlw ' ' call g_out call display_element_a ; Status A = perpendicular passed att waypoint movlw ' ' call g_out movlw ' ' call g_out movlw ' ' call g_out movlw ' ' call g_out movlw d'104' call dput movlw d'31' call dput movlw h'24' call cput movlw 'B' call g_out movlw 'O' call g_out movlw 'D' call g_out movlw ':' call g_out call display_element_a ; Bearing origin to waypoint call display_element_a ; M/T call next_element ; Destination waypoint id movlw ' ' call g_out movlw 'B' call g_out movlw 'P' call g_out movlw 'D' call g_out movlw ':' call g_out call display_element_a ; Bearing, present position to waypoint call display_element_a ; M/T movlw ' ' call g_out movlw 'H' call g_out movlw 'D' call g_out movlw 'S' call g_out movlw ':' call g_out call display_element_a ; Heading to steer call display_element_a ; M/T movlw ' ' call g_out movlw ' ' call g_out movlw ' ' call g_out movlw ' ' call g_out goto get1bit_ret ;*********************************************************************** sitoasc: bsf PCLATH, 2 bsf PCLATH, 0 call translate bcf PCLATH, 2 bcf PCLATH, 0 return org 0x4ff translate: addwf PCL, F ; retlw 0x0 ; 0 addr = 0x500 retlw 0x0 ; 1 retlw 0x0 ; 2 retlw 0x0 ; 3 retlw 0x0 ; 4 retlw 0x0 ; 5 retlw 0x0 ; 6 retlw 0x0 ; 7 retlw 0x0 ; 8 retlw 0x0 ; 9 retlw 0x0 ; a retlw 0x0 ; b retlw 0x0 ; c retlw 0x0 ; d retlw 0x0 ; e retlw ' ' ; f CR 0xd retlw 0x0 ; 10 retlw 0x0 ; 11 retlw 0x0 ; 12 retlw 0x0 ; 13 retlw 0x0 ; 14 retlw 0x0 ; 15 retlw 0x0 ; 16 retlw 't' ; 17 T 5 retlw 0x0 ; 18 retlw 0x0 ; 19 retlw 0x0 ; 1a retlw 0xa ; 1b LF 0xa retlw 0x0 ; 1c retlw ' ' ; 1d SPACE retlw 'v' ; 1e V = retlw 0x0 ; 1f retlw 0x0 ; 20 retlw 0x0 ; 21 retlw 0x0 ; 22 retlw 0x0 ; 23 retlw 0x0 ; 24 retlw 0x0 ; 25 retlw 0x0 ; 26 retlw 'b' ; 27 B ? retlw 0x0 ; 28 retlw 0x0 ; 29 retlw 0x0 ; 2a retlw '_' ; 2b BLANK retlw 0x0 ; 2c retlw 'L' ; 2d LETTERS retlw 'x' ; 2e X / retlw 0x0 ; 2f retlw 0x0 ; 30 retlw 0x0 ; 31 retlw 0x0 ; 32 retlw 'B' ; 33 PHASE2 retlw 0x0 ; 34 retlw 'e' ; 35 E 3 retlw 'F' ; 36 FIGURES retlw 0x0 ; 37 retlw 0x0 ; 38 retlw 'u' ; 39 U 7 retlw 'q' ; 3a Q 1 retlw 0x0 ; 3b retlw 'k' ; 3c K ( retlw 0x0 ; 3d retlw 0x0 ; 3e retlw 0x0 ; 3f retlw 0x0 ; 40 retlw 0x0 ; 41 retlw 0x0 ; 42 retlw 0x0 ; 43 retlw 0x0 ; 44 retlw 0x0 ; 45 retlw 0x0 ; 46 retlw 'o' ; 47 O 9 retlw 0x0 ; 48 retlw 0x0 ; 49 retlw 0x0 ; 4a retlw 'h' ; 4b H # retlw 0x0 ; 4c retlw 'n' ; 4d N , retlw 'm' ; 4e M . retlw 0x0 ; 4f retlw 0x0 ; 50 retlw 0x0 ; 51 retlw 0x0 ; 52 retlw 'l' ; 53 L ) retlw 0x0 ; 54 retlw 'r' ; 55 R 4 retlw 'g' ; 56 G & retlw 0x0 ; 57 retlw 0x0 ; 58 retlw 'i' ; 59 I 8 retlw 'p' ; 5a P 0 retlw 0x0 ; 5b retlw 'c' ; 5c C : retlw 0x0 ; 5d retlw 0x0 ; 5e retlw 0x0 ; 5f retlw 0x0 ; 60 retlw 0x0 ; 61 retlw 0x0 ; 62 retlw 'z' ; 63 Z + retlw 0x0 ; 64 retlw 'd' ; 65 D $ retlw 0x0 ; 66 retlw 0x0 ; 67 retlw 0x0 ; 68 retlw 's' ; 69 S \ retlw 'y' ; 6a Y 6 retlw 0x0 ; 6b retlw 'f' ; 6c F ? retlw 0x0 ; 6d retlw 0x0 ; 6e retlw 0x0 ; 6f retlw 0x0 ; 70 retlw 'a' ; 71 A - retlw 'w' ; 72 W 2 retlw 0x0 ; 73 retlw 'j' ; 74 J 7 BELL retlw 0x0 ; 75 retlw 0x0 ; 76 retlw 0x0 ; 77 retlw 'A' ; 78 PHASE1 retlw 0x0 ; 79 retlw 0x0 ; 7a retlw 0x0 ; 7b retlw 0x0 ; 7c retlw 0x0 ; 7d retlw 0x0 ; 7e retlw 0x0 ; 7f retlw 0x0 ; 0 retlw 0x0 ; 1 retlw 0x0 ; 2 retlw 0x0 ; 3 retlw 0x0 ; 4 retlw 0x0 ; 5 retlw 0x0 ; 6 retlw 0x0 ; 7 retlw 0x0 ; 8 retlw 0x0 ; 9 retlw 0x0 ; a retlw 0x0 ; b retlw 0x0 ; c retlw 0x0 ; d retlw 0x0 ; e retlw ' ' ; f CR 0xd retlw 0x0 ; 10 retlw 0x0 ; 11 retlw 0x0 ; 12 retlw 0x0 ; 13 retlw 0x0 ; 14 retlw 0x0 ; 15 retlw 0x0 ; 16 retlw '5' ; 17 T 5 retlw 0x0 ; 18 retlw 0x0 ; 19 retlw 0x0 ; 1a retlw 0xa ; 1b LF retlw 0x0 ; 1c retlw ' ' ; 1d SPACE retlw '=' ; 1e V = retlw 0x0 ; 1f retlw 0x0 ; 20 retlw 0x0 ; 21 retlw 0x0 ; 22 retlw 0x0 ; 23 retlw 0x0 ; 24 retlw 0x0 ; 25 retlw 0x0 ; 26 retlw '?' ; 27 B ? retlw 0x0 ; 28 retlw 0x0 ; 29 retlw 0x0 ; 2a retlw '_' ; 2b BLANK retlw 0x0 ; 2c retlw 'L' ; 2d LETTERS retlw '/' ; 2e X / retlw 0x0 ; 2f retlw 0x0 ; 30 retlw 0x0 ; 31 retlw 0x0 ; 32 retlw 'B' ; 33 PHASE2 retlw 0x0 ; 34 retlw '3' ; 35 E 3 retlw 'F' ; 36 FIGURES retlw 0x0 ; 37 retlw 0x0 ; 38 retlw '7' ; 39 U 7 retlw '1' ; 3a Q 1 retlw 0x0 ; 3b retlw '(' ; 3c K ( retlw 0x0 ; 3d retlw 0x0 ; 3e retlw 0x0 ; 3f retlw 0x0 ; 40 retlw 0x0 ; 41 retlw 0x0 ; 42 retlw 0x0 ; 43 retlw 0x0 ; 44 retlw 0x0 ; 45 retlw 0x0 ; 46 retlw '9' ; 47 O 9 retlw 0x0 ; 48 retlw 0x0 ; 49 retlw 0x0 ; 4a retlw '#' ; 4b H # retlw 0x0 ; 4c retlw ',' ; 4d N , retlw '.' ; 4e M . retlw 0x0 ; 4f retlw 0x0 ; 50 retlw 0x0 ; 51 retlw 0x0 ; 52 retlw ')' ; 53 L ) retlw 0x0 ; 54 retlw '4' ; 55 R 4 retlw '&' ; 56 G & retlw 0x0 ; 57 retlw 0x0 ; 58 retlw '8' ; 59 I 8 retlw '0' ; 5a P 0 retlw 0x0 ; 5b retlw ':' ; 5c C : retlw 0x0 ; 5d retlw 0x0 ; 5e retlw 0x0 ; 5f retlw 0x0 ; 60 retlw 0x0 ; 61 retlw 0x0 ; 62 retlw '+' ; 63 Z + retlw 0x0 ; 64 retlw '$' ; 65 D $ retlw 0x0 ; 66 retlw 0x0 ; 67 retlw 0x0 ; 68 retlw '\\' ; 69 S \ retlw '6' ; 6a Y 6 retlw 0x0 ; 6b retlw '?' ; 6c F ? retlw 0x0 ; 6d retlw 0x0 ; 6e retlw 0x0 ; 6f retlw 0x0 ; 70 retlw '-' ; 71 A - retlw '2' ; 72 W 2 retlw 0x0 ; 73 retlw 0x0 ; 74 J 7 BELL retlw 0x0 ; 75 retlw 0x0 ; 76 retlw 0x0 ; 77 retlw 'A' ; 78 PHASE1 retlw 0x0 ; 79 retlw 0x0 ; 7a retlw 0x0 ; 7b retlw 0x0 ; 7c retlw 0x0 ; 7d retlw 0x0 ; 7e retlw 0x0 ; 7f END ; directive 'end of program'