;********************************************************************** ; * ; Filename: navtex.asm * ; Date: 14.5.2007 * ; File Version: 1.5 * ; * ; Author: Mikael Nordman OH2AUN * ; Copyright: Mikael Nordman OH2AUN * ; * ; * ;********************************************************************** ; * ; Files required: * ; * ; * ; * ;********************************************************************** ; * ; Notes: This file is for the 16F876. It also also works with the * ; 16F870, without a PWM, but in that case an external * ; divider must be provided to generate the local * ; oscillator frequency of 500/512 KHz * ; This program has been tested with an 8 MHz crystal, * ; and with a 18.439(18.432) MHz crystal. * ; * ; The LCD display used is a graphics display with * ; 240*64 pixels controlled by a Toshiba T6963C. * ; My display is called TOSHIBA TLX-711A-E0. * ; The graphic memory of 8 Kbyte is used for storing * ; the received navtex messages. * ; Normal LCD text displays are of no use here since they * ; do not have any memory. * ; It is also possible to operate without the LCD display * ; and output the messages via RS232. * ;********************************************************************** 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_ON ; '__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 k_up equ ram + h'11' k_mode equ ram + h'1e' fbit equ ram + h'29' 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'32' dx2asc equ ram + h'c' errors equ ram + h'e' m_delay equ ram + h'f' s_delay equ ram + h'26' d_delay equ ram + h'4e' count1 equ ram + h'12' count2 equ ram + h'13' gchar equ ram + h'14' wsave equ ram + h'18' addr_lo equ ram + h'1f' addr_hi equ ram + h'20' gaddr_lo equ ram + h'48' gaddr_hi equ ram + h'49' base_lo equ ram + h'21' base_hi equ ram + h'22' sbase_lo equ ram + h'23' sbase_hi equ ram + h'24' x equ ram + h'15' y equ ram + h'16' row equ ram + h'17' srow equ ram + h'25' state equ ram + h'27' samplecnt equ ram + h'2a' lcdchar equ ram + h'b' 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' last_mode_char equ ram + h'4a' mode_p equ ram + h'4b' mx equ ram + h'4c' my equ ram + h'4d' count_i equ ram + h'd' rxt equ h'7c' rx0 equ h'a0' ; A0 - BF is the serial receive buffer, 32 bytes, bank 1 rx2 equ h'a2' ; only A0 to BF is available on 16F870, 32 bytes rx3 equ h'a3' rx4 equ h'a4' rx6 equ h'a6' nmea_cmd equ h'70' ; describe which nmea command is beeing analysed ; 0 = no nmea command ; 1 = start of nmea string received ($) ; 2 = command name received ; 3 = apb ; 4 = gll ; 5 = vtg ; 6 = control command nmea_param equ h'71' ; the number of nmea parameter that has been received ; 0 = no parameter ; 1 = first parameter + comma/asterisk ; 2 = second parameter + comma/asterisk ; 3 = third + comma/asterix ; 4 = und so weiter eedata equ h'72' eeaddr equ h'73' set_mode equ h'74' ; indicates if the filter parameters are beeing changed ; 0 = normal operation ; 1 = st1 ; 2 = st2 ; 3 = st3 ; 4 = a ; 5 = c ; 6 = f ; 7 = g ; 8 = h ; 9 = i ; 10 = j ; 11 = k ; 12 = l ; 13 = z ; 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 LO equ 1 CPT equ 2 LED equ 3 K_DOWN equ 4 LCD_MODE equ 5 SERIAL_IN equ 7 TRISC_MAP equ 0xb5 ; (1 | 4 | 10 |20 | 80) 10110101 ; state bits WRAP_ON equ 0 LINE_WRAP equ 1 SHIFT equ 2 MSGSTATE equ 3 RXSTATE equ 4 NMEA_PARAM equ 6 SCROLL_MODE equ 7 ;****************************************************************** ; define the 8000 KHz (16000, 8192, 16384, 18432) crystal real frequency here !! ; 8000 KHz and 18439 KHz has been tested. ; 1 KHz accuracy needed here local crystal = d'18439250' ; local crystal = d'8000000' ; local crystal = d'8192000' local clock = crystal / 4 local if_div = clock / d'500000' local pwm_cycle = if_div - 1 ; pulse width modulator cycle local pwm_duty = pwm_cycle / 2 local if = d'518000' - clock / if_div if (if > d'16000') local capture_prescaler = d'16' local ccp1con_value = b'00000111' local samples = d'10' local inphase = d'5' local tick = d'1000' else local capture_prescaler = 4 local ccp1con_value = b'00000110' local samples = d'12' local inphase = d'6' local tick = d'1200' endif local capture_mid = clock * capture_prescaler / if local capture_lo = capture_mid & d'255' local capture_hi = capture_mid / d'256' if (capture_mid < 0x7ff) local capture_ofl = d'3' else local capture_ofl = d'4' endif local timer0_prescaler = d'16' local option_reg_val = B'11010011' local t0div = (clock / timer0_prescaler / tick) - 1 local t0value = d'256' - t0div ; 1 or 0.8888 millisecond tick from timer 0 ;****************************************************************** ; Asynchronous serial baud rate = 4800 local baud = d'4800' local baud_prescaler = d'16' local spbrg_val = (clock / baud_prescaler / baud) - 1 ;********************************************************************** ORG 0x000 ; processor reset vector clrf PCLATH ; ensure page bits are cleared movlw ram movwf FSR goto main ; go to beginning of program ;*********************************************************************** ; THE INTERRUPT ROUTINE ORG 0x004 ; interrupt vector location goto irq_start ;****************************************************************************** ;serial routine is on first program page to make jump tables easy serial: movfw nmea_cmd addwf PCL, F ; jump table for nmea_status goto get1bit_ret ; 0 no nmea command goto get1bit_ret ; 1 start of nmea string goto ser_chk_gll ; 2 check which nmea command has been received goto display_gll goto display_vtg goto display_apb goto check_cmd ; 6 control cmd ;******************************************************************************* display_gll: btfss state, SCROLL_MODE call set_gbase ; do not show gps screen in scroll mode btfss state, NMEA_PARAM goto get1bit_ret bcf state, NMEA_PARAM movfw nmea_param sublw d'5' bnc get1bit_ret movfw nmea_param addwf PCL, F goto get1bit_ret ; no parameter is available goto disp_lat ; latitude goto disp_lat1 ; N/W goto disp_lon ; longitude goto disp_lon1 ; E/W goto disp_utc ; Universal Time Coordinates ;******************************************************************************* display_vtg: btfss state, SCROLL_MODE call set_gbase ; do not show gps screen in scroll mode btfss state, NMEA_PARAM goto get1bit_ret bcf state, NMEA_PARAM movfw nmea_param sublw d'5' bnc get1bit_ret movfw nmea_param addwf PCL, F goto get1bit_ret ; no parameter is available goto get1bit_ret ; skip first parameter goto get1bit_ret ; skip second parameter goto disp_track ; track goto disp_track1 ; True/Magnetic goto disp_speed ; Speed ;******************************************************************************* display_apb: btfss state, SCROLL_MODE call set_gbase ; do not show gps screen in scroll mode btfss state, NMEA_PARAM goto get1bit_ret bcf state, NMEA_PARAM movfw nmea_param sublw d'14' bnc get1bit_ret movfw nmea_param addwf PCL, F goto get1bit_ret ; no parameter is available goto get1bit_ret ; skip first parameter goto get1bit_ret ; skip second parameter goto disp_xte ; cross track error goto disp_dts ; direction to steer goto disp_xteu ; cross track error unit goto disp_status1 ; arrival circle entered goto disp_status2 ; perpendicular passed at waypoint goto disp_bod ; bearing, origin to waypoint goto disp_bod1 ; true/magnetic goto get1bit_ret ; skip destination waypoint id goto disp_bpd ; bearing, current position to waypoint goto disp_bpd1 ; true/magnetic goto disp_hds ; heading, direction to steer goto disp_hds1 ; true/magnetic ;******************************************************************************* ; mode update branch table mode_branch: movfw set_mode addwf PCL, F goto mode_ret goto set_mode_1 goto set_mode_2 goto set_mode_3 goto set_mode_4 goto set_mode_5 goto set_mode_5 goto set_mode_5 goto set_mode_5 goto set_mode_5 goto set_mode_5 goto set_mode_5 goto set_mode_5 goto set_mode_5 set_mode_branch: movfw set_mode addwf PCL, F goto mode_ret goto set_mode_ud_st goto set_mode_ud_st goto set_mode_ud_st goto set_mode_ud_msg_n goto set_mode_ud_msg_n goto set_mode_ud_msg_n goto set_mode_ud_msg_n goto set_mode_ud_msg_n goto set_mode_ud_msg_n goto set_mode_ud_msg_n goto set_mode_ud_msg_n goto set_mode_ud_msg_n goto set_mode_ud_msg_n ;******************************************************************************* serial_int: movfw RCREG movwf rxt btfsc RCSTA, FERR goto seri_err btfsc RCSTA, OERR goto seri_err btfsc state, SCROLL_MODE goto serial_skip btfsc state, RXSTATE ; dont receive serial information during goto serial_skip ; navtex reception movf set_mode, W ; Mode adjustement bnz serial_skip movf rxt, W call serial_out ; Don't get here during navtex reception. ; There will be return stack overflow, and random crashes. serial_int1: movfw nmea_cmd addwf PCL, F ; jump table for nmea_cmd goto seri_get_start ; 0 no command goto seri_get_cmd ; 1 start of nmea string goto seri_get_param ; 2 check which nmea command has been received goto seri_get_param goto seri_get_param goto seri_get_param goto seri_get_param seri_get_start: movf rx_i, W bnz seri_add_char movfw rxt sublw '$' bz seri_state_start goto seri_add_char seri_get_cmd: movfw rx_i sublw 6 bz seri_state_cmd goto seri_add_char seri_get_param: movfw rxt sublw ',' bz seri_state_param movfw rxt sublw '*' bz seri_state_param goto seri_add_char seri_add_char: movfw rxt sublw 8 ; backspace bnz seri_add_char1 movf rx_i, F bz seri_add_char_ret decf rx_i, F movlw ' ' call serial_out movlw 8 call serial_out goto seri_add_char_ret seri_add_char1: movfw rx_i addlw rx0 movwf FSR movfw rxt movwf INDF bcf PORTC, LED sublw 0xa ; Line feed bz seri_state_end movfw rx_i sublw d'31' bnc seri_state_end ; Carry meaning is inverted for subtraction incf rx_i, F seri_add_char_ret: return ; start of NMEA command '$' seri_state_start: movlw 1 movwf nmea_cmd clrf nmea_param clrf rx_i goto seri_add_char1 seri_state_cmd: movlw 2 movwf nmea_cmd clrf rx_i return seri_state_param: incf nmea_param, F movfw rx_i addlw rx0 movwf FSR movfw rxt movwf INDF clrf rx_i bsf state, NMEA_PARAM bcf PORTC, LED return ; end of command, carriage return or overflow seri_state_end: bsf PORTC, LED clrf rx_i clrf nmea_param bcf state, NMEA_PARAM movf nmea_cmd, F bnz seri_state_end1 movlw 6 movwf nmea_cmd ; this is a control cmd return seri_state_end1: clrf nmea_cmd return seri_err: bcf RCSTA, CREN bsf RCSTA, CREN serial_skip: bcf state, NMEA_PARAM clrf rx_i clrf nmea_cmd return ;*************************************************************************** ; THE INTERRUPT ROUTINE irq_start: 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 t0value movwf TMR0 call samplebit call checkkey btfsc PIR1, RCIF ; RCIF is cleared automagically by the HW call serial_int 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 1 ms (18 KHz IF) or 833 us (6 KHz IF) ; A new capture event occurs at 888 us (18 KHz IF) or 733 us (6KHz IF) intervals ; 00001111 is considered to be a sitor signal rising edge. ; samplebit: rlf fbits, F ; Make place for new sample ; diff = cp + not(cp_old) comf cp0, F comf cp1, F movf cp0, W addwf CCPR1L, W movwf cp0 movf cp1, W btfsc STATUS, 0 incf cp1, W addwf CCPR1H, W movwf cp1 btfss cp1, capture_ofl goto intsam_diff bcf STATUS, C ; two sample periods have been captured rrf cp1, F ; divide by 2 rrf cp0, F ;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 ;xtal = 8000 KHz mid = (18000 Hz) 0x6f0 ; if (diff < capture) then ; result = 0 ; else ; result = 1 ; endif intsam_diff: movlw capture_hi ; middle frequency subwf cp1, W ; captured frequency movlw capture_lo ; middle frequency btfsc STATUS, Z ; captured frequency subwf cp0, W btfsc STATUS, C goto intsam1 goto intsam0 intsam0: bcf fbits, 0 goto intsamcont intsam1: bsf fbits, 0 intsamcont: movfw CCPR1L ; save the captured timer1 value movwf cp0 movfw CCPR1H movwf cp1 decfsz sample, F ; sample--; goto setsample ; if sample != 0, try to set the sampling time movlw samples ; 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++ setsample: movlw 0xf subwf fbits, W btfss STATUS, Z return ; return if not an edge. movlw inphase ; sample should be inphase, if we are in phase. subwf sample, W bz samret ; if sample = inphase then donothing bnc saminc decf sample, F ; if sample > inphase then sample-- return saminc: incf sample, F ; if sample < inphase 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 m_delay, F bnz check_key1 incf s_delay, F movfw d_delay subwf s_delay, W bnz check_key1 clrf s_delay check_key1: 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 ;*************************************************************************** ; THE MAIN LOOP main: clrf INDF incf FSR, F btfss FSR, 7 goto main bsf k_mode, 0 bsf k_up, 0 bsf k_down, 0 movlw 2 movwf d_delay bsf STATUS, RP1 clrf EEADRH bcf STATUS, RP1 movlw samples ; 10/12 samples per sitor bit movwf sample ; Configure timer0 ; timeout = 1 ms or 833 us, ; 10/12 samples / sitor bit movlw b'00011110' movwf PORTA clrf PORTB clrf PORTC bsf STATUS, RP0 ; set file bank 1 movlw option_reg_val ; timer0 prescaler is 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 TRISC_MAP movwf TRISC bcf STATUS, RP0 ; set file bank 0 ; Init Module 1 for capture of the navtex fsk period movlw ccp1con_value ; Capture on every fourth or sixteenth rising edge on RC2 movwf CCP1CON bsf T1CON, TMR1ON ; Enable timer1 at the internal clock Fosc/4 ; Init Module2 for PWM at 500 KHz or 512 KHz ; This only works with 16f876-16f877. ; 16f870-16f872 has only one ccp module, which is used for the capture function bsf STATUS, RP0 movlw pwm_cycle ; movwf PR2 ; pwm cycle = (PR2 + 1) bcf STATUS, RP0 movlw b'00001111' ; PWM mode movwf CCP2CON movlw pwm_duty movwf CCPR2L ; Set duty cycle to about 50 % bsf T2CON, TMR2ON ; TMR2 on, Prescaler=1 ; Initialise the RS port for reception ; 4800 baud, 8bit, no parity bsf STATUS, RP0 movlw spbrg_val ; define the baud rate movwf SPBRG bsf TXSTA, TXEN ; Enable serial transmission bcf STATUS, RP0 bcf RCSTA, RX9 bsf RCSTA, SPEN ; RC7/RX, RC6/TX bsf RCSTA, CREN ; Enable asynchronous continuous receive ; Initalise the LCD display call init_lcd ; Configure interrupt ; Enable the timer0 interrupt and peripheral interrupts movlw B'01100000' ; Enable peripheral and timer0 interrupt movwf INTCON ; START RECEPTION state0: movlw h'97' call cput ; text on, cursor blinking, graphics off ; SYNCRONISING TO THE SITOR SIGNAL state1: clrf errors clrf rx clrf dx clrf dx1 bcf state, RXSTATE bcf state, LINE_WRAP call get1bit ; returns with 7 latest bits in w sublw 0x78 btfss STATUS, Z goto state1 ; loop in state1 until 0x78 received state2: movf set_mode, F ; Dont receive if mode change is in progress. bnz state1 bsf state, RXSTATE 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 bcf state, SCROLL_MODE ; 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 ; Display error status movfw errors addlw h'a1' ; set cursor to errors + 2 lines high call cput ; TRANSLATE RX to ASCII btfsc state, SHIFT 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 state, SHIFT 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 state, SHIFT goto chkerr testfigs: movf rxasc, W sublw 'F' btfss STATUS, Z goto printrx bsf state, SHIFT goto chkerr bothmutilated: bothdifferent: incf errors, F ; errors++ ; goto chkerr movlw '_' movwf rxasc printrx: call filter ; character is in rxasc ! chkerr: movf dx2, W sublw 0x78 ; end of transmission 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 btfsc PORTC, LCD_MODE ; check if LCD is present goto get1bit1 ; dont check buttons if there is no display call mode ; check mode button call scroll ; check scroll buttons get1bit1: goto serial ; check serial buffer ; 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 ; ------------------------------------------ ; RST (10)<--> (RA0) ; /RD (6) <--> (RA1) ; /CE (7) <--> (RA2) ; C/D (8) <--> (RA3) ; /WR (5) <--> (RA5) ; ----------------------- ; D0 (11) <--> (RB0) ; D1 (12) <--> (RB1) ; D2 (13) <--> (RB2) ; D3 (14) <--> (RB3) ; D4 (15) <--> (RB4) ; D5 (16) <--> (RB5) ; D6 (17) <--> (RB6) ; D7 (18) <--> (RB7) ; GND (2) <--> (xxx) ; -------------------------------------------------------------- ; FG (1) frame ground ; +5V (3) LCD logic supply ; -7.8V (4) LCD display contrast ; FS (19) font select (FS0 = 0, FS1 = 1) ; ;******************************************************* ; WAIT UNTIL LCD is READY TO RECEIVE DATA ;******************************************************* lcd_ready: btfsc PORTC, LCD_MODE ; check if LCD is present return 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: btfsc PORTC, LCD_MODE ; check if LCD is present return 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: btfsc PORTC, LCD_MODE ; check if LCD is present return 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: movlw cr_lf call see_out movlw version call see_out bsf PORTA, LCD_RESET; clear display reset line call init_gaddr ; clear the gps/mode screen call clear_screen call set_base ; display the navtex screen 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 1 lines high call cput movlw 0 call dput ; dput does not destroy W call dput movlw 0x21 call cput ; put cursor at (0,0) movlw 'R' call g_out movlw 'e' call g_out movlw 'v' call g_out movlw ' ' call g_out movlw '1' call g_out movlw '.' call g_out movlw '5' call g_out call set_addr 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 ;***************************************************************** ; display set routines for the navtex text display 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 movfw y ; cursor screen row w = y subwf row, W ; cursor buffer row w = row -w movwf srow ; srow = row - y return ;***************************************************************** ; display the gps / mode screen set_gbase: movlw d'160' call dput movlw d'30' call dput movlw h'40' call cput ; set text home address return ;***************************************************************** ; set dsiplay ram write pointer 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 ;***************************************************************** inc_gaddr: movlw d'40' addwf gaddr_lo, F bnc set_gaddr incf gaddr_hi, F ;***************************************************************** ; set the gps/mode screen write pointer set_gaddr: movfw gaddr_lo call dput movfw gaddr_hi call dput movlw h'24' call cput ; set text writing address return ;***************************************************************** init_gaddr: movlw d'160' movwf gaddr_lo movlw d'30' movwf gaddr_hi goto set_gaddr ;********************************************************* ; write one character to the lcd ;********************************************************* lcd_put: movwf lcdchar movfw y subwf row, W movwf srow movfw lcdchar sublw 'D' bz crlf btfss state, LINE_WRAP goto eat_space line_wrap: bcf state, 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 state, LINE_WRAP clrf x incf y, F incf row, F call inc_addr goto check_row crlf: movf x, F bz set_cursor bcf state, 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 state, 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 state, WRAP_ON goto set_cursor ;*********************************************************************** filter_crlf: movfw ch0 sublw 0xa bnz filter_crlf1 movlw ' ' movwf ch0 filter_crlf1: movfw ch0 sublw 0xd bnz filter_crlf2 movlw ' ' movwf ch0 filter_crlf2: return ;*********************************************************************** serial_out: bsf STATUS, RP0 btfss TXSTA, TRMT ; Wait for TX register to become empty goto $-1 bcf STATUS, RP0 movwf TXREG ; send data to serial line 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 ; THE MODE SCREEN ; Station ; ST1:* Select the first station id here. a-z, * means any station ; ST2:* Select the second station id here, * has no meaning here ; ST3:* Select the third station here, * has no meaning here ; Message ; ACFGHIJKLZ ; ynnnnnnnnn ; Select the message types here. BDE are always received ; In addition ACFLZ may be received, the others are not supported ; A - Navigational warning ; B - Meterological warning ; C - Ice report ; D - Search and rescue information / piracy and armed robbery ; E - Meteorologial forecast ; F - Pilot message ; G - Decca message ; H - Loran-C message ; I - Omega message ; J - Differential omega message ; K - Other electronic navigational aid and system message ; L - Navigational warning ; Z - QRU (no message at hand) ; ; The serial command interface ; st1=[a,*] ; st2=[a,*] ; st3=[a,*] ; msg_a=[y,n] ; . ; . ; . ; msg_z=[y,n] ; print ; help ; Here are the north european stations on 518 KHz. ; UTC schedule. ; ! ID ; ! ! Call sign ; ! ! ! Country ; ! ! ! ! Station Name ; ! ! ! ! ! Latitude Longitude ; 00,04,08,12,16,2010 B LGP NOR Bodø 67 16 29 N 14 23 29 E ; 00,04,08,12,16,2030 D SAG SWE Gothenburg 57 06 N 12 23 E ; 01,05,09,13,17,2100 G GCC GBR Cullercoats 55 02 N 01 26 W ; 01,05,09,13,17,2110 H SAH SWE Härnösand 64 28 N 21 36 E ; 01,05,09,13,17,2130 J SAA SWE Karlskrona 55 29 N 14 19 E ; 01,05,09,13,17,2140 K GNI GBR Niton 50 35 N 01 18 W ; 01,05,09,13,17,2150 L LGQ NOR Rogaland 58 39 23 N 05 36 17 E ; 02,06,10,14,18,2200 M OST BEL Ostend 51 11 N 02 48 E ; 02,06,10,14,18,2210 N LGD NOR Ørlandet 63 40 N 09 33 E ; 02,06,10,14,18,2220 O GPK GBR Portpatrick 54 51 N 05 07 W ; 02,06,10,14,18,2230 P PBK HOL Netherlands 52 05 45 N 04 15 29 E ; 02,06,10,14,18,2240 Q EJM IRL Malin Head 55 22 N 07 21 W ; 02,06,10,14,18,2250 R TFA ISL Reykjavik 64 05 N 21 51 W ; 03,07,11,15,19,2300 S GNI GBR Niton 50 35 N 01 18 W ; 03,07,11,15,19,2310 T OST BEL Ostend 51 11 N 02 48 E ; 03,07,11,15,19,2320 U ESA EST Tallinn 59 30 N 24 30 E ; 03,07,11,15,19,2340 W EJK IRL Valentia 51 56 N 10 21 W ; 03,07,11,15,19,2350 X TFA ISL Reykjavik 64 05 N 21 51 W ;************************************************************************** filter: movfw rxasc sublw 'A' ; No Phasing signal into the fifo bz filter_ret movfw rxasc sublw 'B' ; No Phasing signal into the fifo bz filter_ret ; advance the fifo movlw d'20' movwf count1 ; moves also rxasc 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 f_st_id1: movlw stid1 movwf eeaddr call get_eeprom sublw '*' bz f_msgtype_e movfw eedata subwf ch3, W bz f_msgtype_e f_st_id2: movlw stid2 movwf eeaddr call get_eeprom subwf ch3, W bz f_msgtype_e f_st_id3: movlw stid3 movwf eeaddr call get_eeprom subwf ch3, W bnz set_msgstate_0 f_msgtype_e: movlw 'e' ; Weather forecast subwf ch2, W bz f_msgstate f_msgtype_b: movlw 'b' ; Meteorogical warning subwf ch2, W bz f_msgstate f_msgtype_d: movlw 'd' ; Search and rescue subwf ch2, W bz f_msgstate f_msgtype_a: movlw msg_a movwf eeaddr call get_eeprom sublw 'y' bnz f_msgtype_c movlw 'a' subwf ch2, W bz f_msgstate f_msgtype_c: movlw msg_c movwf eeaddr call get_eeprom sublw 'y' bnz f_msgtype_f movlw 'c' subwf ch2, W bz f_msgstate f_msgtype_f: incf eeaddr, F call get_eeprom sublw 'y' bnz f_msgtype_g movlw 'f' subwf ch2, W bz f_msgstate f_msgtype_g: incf eeaddr, F call get_eeprom sublw 'y' bnz f_msgtype_h movlw 'g' subwf ch2, W bz f_msgstate f_msgtype_h: incf eeaddr, F call get_eeprom sublw 'y' bnz f_msgtype_i movlw 'h' subwf ch2, W bz f_msgstate f_msgtype_i: incf eeaddr, F call get_eeprom sublw 'y' bnz f_msgtype_j movlw 'i' subwf ch2, W bz f_msgstate f_msgtype_j: incf eeaddr, F call get_eeprom sublw 'y' bnz f_msgtype_k movlw 'j' subwf ch2, W bz f_msgstate f_msgtype_k: incf eeaddr, F call get_eeprom sublw 'y' bnz f_msgtype_l movlw 'k' subwf ch2, W bz f_msgstate f_msgtype_l: incf eeaddr, F call get_eeprom sublw 'y' bnz f_msgtype_z movlw 'l' subwf ch2, W bz f_msgstate f_msgtype_z: incf eeaddr, F call get_eeprom sublw 'y' bnz set_msgstate_0 movlw 'z' subwf ch2, W bnz set_msgstate_0 f_msgstate: btfsc state, MSGSTATE goto chk_nnnn ; state was 0 and ; it was an approved start of message ; print out the the string bsf state, MSGSTATE ; 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 serial_out call filter_crlf 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: bcf state, 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 btfss state, MSGSTATE return movfw ch0 call serial_out movlw 0xd call serial_out movlw 0xa call serial_out movfw ch0 call lcd_put movlw 'D' ; CRLF call lcd_put bcf state, MSGSTATE ; msgstate = 0, end of message. stop printing return c_out: btfss state, MSGSTATE goto msgstate_0 movfw ch0 call serial_out call filter_crlf 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 ;*************************************************************** set_mode_cursor: movfw mx call dput movfw my call dput movlw h'21' call cput return ;********************************************************* ; Check if all or selected messages should be displayed mode: movf k_mode, F bnz led_on movf s_delay, F bnz mode_ret incf s_delay, F incf set_mode, F bcf PORTC, LED ; led is off when key is pressed movlw 4 movwf d_delay movf set_mode, W sublw d'14' bz mode_end goto mode_branch ; go to the branch table mode_end: call init_gaddr call clear_screen clrf set_mode call set_base call set_cursor1 bcf state, SCROLL_MODE ; make sure nmea is displayed led_on: movfw k_mode andwf k_up, W andwf k_down, W bz mode_ret led_on1: movf rx_i, F btfsc STATUS, Z bsf PORTC, LED ; led is on after key has been released mode_ret: return st_out: movlw 'S' call g_out movlw 'T' call g_out return set_mode_1: movlw h'97' call cput ; text on, cursor blinking, graphics off movlw h'a1' call cput ; two line cursor movlw 4 movwf mx clrf my call set_mode_cursor movlw stid1 movwf mode_p call init_gaddr call clear_screen call set_gaddr call set_gbase set_mode_st1: call st_out movlw '1' call g_out set_mode_stn: movlw ':' call g_out movfw mode_p movwf eeaddr call get_eeprom call put_lcd goto mode_ret set_mode_2: incf my, F call set_mode_cursor movlw stid2 movwf mode_p call inc_gaddr call st_out movlw '2' call g_out goto set_mode_stn set_mode_3: incf my, F call set_mode_cursor movlw stid3 movwf mode_p call inc_gaddr call st_out movlw '3' call g_out goto set_mode_stn set_mode_4: ; A clrf mx incf my, F incf my, F call set_mode_cursor call inc_gaddr movlw 'A' call g_out movlw 'C' call g_out movlw 'F' call g_out movlw 'G' call g_out movlw 'H' call g_out movlw 'I' call g_out movlw 'J' call g_out movlw 'K' call g_out movlw 'L' call g_out movlw 'Z' call g_out call inc_gaddr movlw msg_a movwf mode_p movwf eeaddr movlw d'10' movwf count1 set_mode_4_1: call get_eeprom call g_out incf eeaddr, F decfsz count1, F goto set_mode_4_1 call set_gaddr goto mode_ret set_mode_5: ; CFGHIJKLZ incf mx, F call set_mode_cursor movfw mode_p movwf eeaddr call get_eeprom call g_out incf mode_p, F goto mode_ret ;********************************************************* put_lcd: ; Adjust to LCD character table addlw h'e0' ; W = W - h'20' call dput movlw h'c4' call cput return ;********************************************************* set_mode_ud_st: movf k_down, F bz set_mode_down_stn movf k_up, F bz set_mode_up_stn return set_mode_up_stn: movfw mode_p call get_eeprom movwf last_mode_char sublw '*' bz set_mode_up_a movfw last_mode_char sublw 'y' bc set_mode_up_stn1 movlw '*' movwf last_mode_char goto set_mode_up_stn2 set_mode_up_a: movlw h'60' movwf last_mode_char set_mode_up_stn1: incf last_mode_char, F set_mode_up_stn2: movfw last_mode_char movwf eedata movfw mode_p set_mode_up_down_n: movwf eeaddr call put_eeprom movfw last_mode_char call put_lcd return set_mode_down_stn: movfw mode_p call get_eeprom movwf last_mode_char sublw '*' bz set_mode_down_z movfw last_mode_char sublw h'61' ; a - last_mode_char bnc set_mode_down_stn1 movlw '*' movwf last_mode_char goto set_mode_down_stn2 set_mode_down_z: movlw '{' movwf last_mode_char set_mode_down_stn1: decf last_mode_char, F set_mode_down_stn2: movfw last_mode_char movwf eedata movfw mode_p goto set_mode_up_down_n ;********************************************************** set_mode_ud_msg_n: movfw mode_p movwf eeaddr call get_eeprom sublw 'y' bnz set_mode_ud_y movlw 'n' goto set_mode_ud_save set_mode_ud_y: movlw 'y' set_mode_ud_save: movwf last_mode_char movwf eedata movfw mode_p movwf eeaddr call put_eeprom movfw last_mode_char call put_lcd return ;********************************************************* ; check if display should be scrolled up or down scroll: movf s_delay, F bnz scroll_ret incf s_delay, F movf k_up, F bz scroll_up movf k_down, F bz scroll_down goto led_on scroll_up: bcf PORTC, LED ; Led is off if key is pressed movf set_mode, F bnz set_mode_branch bsf state, SCROLL_MODE call scroll_set movlw 2 movwf d_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 state, 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: bcf PORTC, LED ; Led is off if key is pressed movf set_mode, F bnz set_mode_branch call scroll_set movlw 2 movwf d_delay movlw h'94' call cput ; text on, cursor off, graphics off ; if (srow == (row - y)) return; movfw y ; cursor screen row w = y subwf row, W ; cursor buffer row w = row -w subwf srow, W ; scroll text first visible row w = srow - w bnz sd_chk_wrap bcf state, SCROLL_MODE ; 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 ;****************************************************************************** ser_chk_gll: movlw h'94' call cput ; text on, cursor off, graphics off movlw rx3 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 movlw 3 movwf nmea_cmd movlw d'160' call dput movlw d'30' call dput movlw h'24' call cput goto get1bit_ret ser_chk_vtg: movlw rx3 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 movlw 4 movwf nmea_cmd movlw d'240' call dput movlw d'30' call dput movlw h'24' call cput goto get1bit_ret ser_chk_apb: movlw rx3 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 movlw 5 movwf nmea_cmd movlw d'64' call dput movlw d'31' call dput movlw h'24' call cput goto get1bit_ret ;*********************************************************************** g_out: movwf gchar addlw h'e0' ; Adjust to LCD character table W=W-h'20' call dput movlw h'c0' call cput movfw gchar return ;*********************************************************************** display_element_a: movlw rx0 movwf FSR display_el_a_loop: movfw INDF sublw ',' bz disp_elem_a_ret movfw INDF sublw '*' bz disp_elem_a_ret movfw INDF call g_out incf FSR, F goto display_el_a_loop disp_elem_a_ret: movlw ' ' call g_out return ;*********************************************************************** display_element_b: movlw rx0 movwf FSR display_el_b_loop movfw INDF sublw '.' bz disp_elem_b_ret movfw INDF call g_out incf FSR, F goto display_el_b_loop disp_elem_b_ret: incf FSR, F return ;*********************************************************************** ; GLL parameters ;*********************************************************************** disp_lat: movlw 'L' call g_out movlw 'A' call g_out movlw 'T' call g_out movlw ':' call g_out call display_element_a ; Latitude goto get1bit_ret disp_lat1: call display_element_a ; North Oder South goto get1bit_ret disp_lon: movlw 'L' call g_out movlw 'O' call g_out movlw 'N' call g_out movlw ':' call g_out call display_element_a ; Longitude goto get1bit_ret disp_lon1: call display_element_a ; East Oder West goto get1bit_ret disp_utc: movlw d'184' call dput movlw d'31' call dput movlw h'24' call cput movlw 'U' call g_out movlw 'T' call g_out movlw 'C' call g_out movlw ':' call g_out disp_time: call display_element_a ; Time goto get1bit_ret ;*********************************************************************** disp_track: movlw 'T' call g_out movlw 'R' call g_out movlw 'K' call g_out movlw ':' call g_out call display_element_a ; Track goto get1bit_ret disp_track1: call display_element_a ; Magnetic/True goto get1bit_ret disp_speed: 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 call g_out call g_out call g_out goto get1bit_ret ;*********************************************************************** ; Auto Pilot B message ;*********************************************************************** disp_xte: 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 goto get1bit_ret disp_dts: call display_element_a ; Direction to steer goto get1bit_ret disp_xteu: call display_element_a ; XTE units goto get1bit_ret disp_status1: call display_element_a ; Status A = arrival circle entered goto get1bit_ret disp_status2: call display_element_a ; Status A = perpendicular passed att waypoint call g_out call g_out call g_out goto get1bit_ret disp_bod: 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 goto get1bit_ret disp_bod1: call display_element_a ; M/T goto get1bit_ret disp_bpd: 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 goto get1bit_ret disp_bpd1: call display_element_a ; M/T goto get1bit_ret disp_hds: 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 goto get1bit_ret disp_hds1: call display_element_a ; M/T call g_out call g_out call g_out goto get1bit_ret ;*********************************************************************** check_cmd: clrf nmea_cmd movlw rx0 movwf FSR chk_cmd_0: movfw INDF sublw 'h' bz do_help movfw INDF sublw 'p' bz do_print movfw INDF sublw 's' bz do_st movfw INDF sublw 'm' bz do_msg chk_cmd_help: chk_cmd_ret: goto get1bit_ret ;********************************************************************** ;Print zero terminated string from EEPROM to the serial port see_out: movwf eeaddr see_out_1: call get_eeprom bz see_out_ret movfw eedata call serial_out incf eeaddr, F goto see_out_1 see_out_ret: return ;*********************************************************************** do_help: movlw help_text call see_out goto get1bit_ret do_print: movlw '1' call serial_out movlw '2' call serial_out movlw '3' call serial_out movlw 'a' call serial_out movlw 'c' call serial_out movlw 'f' call serial_out movlw 'g' call serial_out movlw 'h' call serial_out movlw 'i' call serial_out movlw 'j' call serial_out movlw 'k' call serial_out movlw 'l' call serial_out movlw 'z' call serial_out movlw 0xd call serial_out movlw 0xa call serial_out movlw stid1 call see_out goto get1bit_ret ;********************************************************* do_st: incf FSR, F movfw INDF sublw 't' bnz get1bit_ret incf FSR, F movfw INDF sublw '1' bz do_st1 movfw INDF sublw '2' bz do_st2 movfw INDF sublw '3' bnz get1bit_ret movlw stid3 movwf eeaddr goto do_st4 do_st2: movlw stid2 movwf eeaddr goto do_st4 do_st1: movlw stid1 movwf eeaddr do_st4: incf FSR, F incf FSR, F movfw INDF movwf eedata call put_eeprom goto get1bit_ret ;********************************************************************** do_msg: movlw 4 addwf FSR, F movlw msg_a movwf eeaddr movfw INDF sublw 'a' bz do_msg_1 incf eeaddr, F movfw INDF sublw 'c' bz do_msg_1 incf eeaddr, F movfw INDF sublw 'f' bz do_msg_1 incf eeaddr, F movfw INDF sublw 'g' bz do_msg_1 incf eeaddr, F movfw INDF sublw 'h' bz do_msg_1 incf eeaddr, F movfw INDF sublw 'i' bz do_msg_1 incf eeaddr, F movfw INDF sublw 'j' bz do_msg_1 incf eeaddr, F movfw INDF sublw 'k' bz do_msg_1 incf eeaddr, F movfw INDF sublw 'l' bz do_msg_1 incf eeaddr, F movfw INDF sublw 'z' bz do_msg_1 goto get1bit_ret do_msg_1: incf FSR, F incf FSR, F movfw INDF movwf eedata call put_eeprom goto get1bit_ret ;*********************************************************************** put_eeprom: bsf STATUS, RP1 bsf STATUS, RP0 btfsc EECON1, WR goto $-1 bcf STATUS, RP0 movfw eeaddr movwf EEADR movfw eedata movwf EEDATA bsf STATUS, RP0 bcf EECON1, EEPGD bsf EECON1, WREN bcf INTCON, GIE movlw 0x55 movwf EECON2 movlw 0xaa movwf EECON2 bsf EECON1, WR bcf EECON1, WREN bsf INTCON, GIE bcf STATUS, RP0 bcf STATUS, RP1 return ;*********************************************************************** get_eeprom: bsf STATUS, RP1 bcf STATUS, RP0 movfw eeaddr movwf EEADR bsf STATUS, RP0 bcf EECON1, EEPGD bsf EECON1, RD bcf STATUS, RP0 movf EEDATA, W bcf STATUS, RP1 movwf eedata return ;*********************************************************************** sitoasc: bsf PCLATH, 2 bsf PCLATH, 1 bsf PCLATH, 0 call translate clrf PCLATH return org 0x6ff translate: addwf PCL, F ; retlw 0x0 ; 0 addr = 0x700 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 0xd ; 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 0xd ; 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 ;************************************************************************ org H'2100' help_text equ ($ - h'2100') de "stn=[a,*]", 0xd, 0xa de "msg_x=[y,n]", 0xd, 0xa de "print" 0xd,0xa de "help", 0xd,0xa,0 stid1 equ $-h'2100' de "*hjyynnnnnnnn", 0xd, 0xa, 0 stid2 equ stid1+1 stid3 equ stid1+2 msg_a equ stid1+3 msg_c equ stid1+4 msg_f equ stid1+5 msg_g equ stid1+6 msg_h equ stid1+7 msg_i equ stid1+8 msg_j equ stid1+9 msg_k equ stid1+0xa msg_l equ stid1+0xb msg_z equ stid1+0xc version equ $-h'2100' de "Rev 1.5" cr_lf equ $-h'2100' de 0xd,0xa,0 ;************************************************************************ END ; directive 'end of program' ;************************************************************************ org 0x0800