It was again updated on 26 October 2000, to correct a really dumb flaw in the ASCII output routine, which was only obvious when tested with the Palm display... The baud rate was also corrected, very slightly... see UPDATES for details.
;-------------------------------------------------------------------- ; ; DOPPLER SERIAL INTERFACE PROGRAM ; FILENAME : DOPPLER.asm ; REVISION DATE : 26 OCTOBER 2000 ; ;-------------------------------------------------------------------- ; ; SERIAL RS232 OUTPUT OF DOPPLER BEARING DATA ; 1200 BAUD, 1 START BIT, 7 DATA BITS, NO PARITY, 2 STOP BITS ; OUTPUT DATA = ASCII BEARING, 3 DIGITS PER TRANSMISSION ; MESSAGE FORMAT : AGRELO DF ( APRS COMPATIBLE ) ; BYTE 1 : "%" CHARACTER ( APRS "DF BEARING" IDENTIFIER ) ; BYTE 2 : BRGX100 ; BYTE 3 : BRGX10 ; BYTE 4 : BRGX1 ; BYTE 5 : "/" CHARACTER ; BYTE 6 : "7" CHARACTER ( RELATIVE SIGNAL QUALITY, 0-7 ) ; BYTE 7 : "CARRIAGE RETURN" ; ; MESSAGE OUTPUT IS SQUELCHED WHEN NO SIGNAL IS PRESENT ; ; USES PIC 16F84 uP ; 3.58 MHZ CRYSTAL CLOCK ; PIN 1 = RA2 = 360 BEARING COUNTER RESET ( FROM MAIN PC BOARD ) ; PIN 6 = RB0/INT = CALIB 1-SHOT INPUT ( FROM MAIN PC BOARD ) ; PIN 3 = RA4/T0CKI = X720 CLOCK INPUT ( FROM DIVIDER BOARD ) ; PIN 2 = RA3 = RS232 DATA OUTPUT ; ; GENERAL DESCRIPTION ; ; ; THE INTERNAL TMR0 ( = 8 BITS ) + TMR0 OVERFLOW BIT IN STATUS REGISTER ; ARE USED TOGETHER AS A 9 - BIT BINARY "SIGNAL BEARING" COUNTER. THE ; CLOCK FOR TMR0 COMES FROM PIN 3, ( THROUGH THE PRESCALER, SET FOR 2:1 ; DIVISION RATION ) AND IS GENERATED BY THE LS/TTL DIVIDER CIRCUITS ON ; THE DIVIDER BOARD. CLOCK INPUT FREQUENCY =720X ANTENNA SCAN RATE ; ; TMR0 IS RESET TO ZERO WHENEVER PIN 1 GOES LOW, (= RA2) WHICH INDICATES ; THE DIVIDE-BY-16 CHIP ON THE MAIN BOARD HAS OVERFLOWED. (= 000 DEGREES) ; ; WHENEVER AN INTERRUPT PULSE IS DETECTED ON PIN 6, ( = CALIB 1-SHOT, ; FROM THE MAIN BOARD ) THE NUMBER IN TMR0 IS "LATCHED"... THIS ( 9 BIT, ; BINARY ) NUMBER REPRESENTS THE SIGNAL BEARING. ; ; THE NUMBER IS CONVERTED FROM 9-BIT BINARY INTO 3 DIGITS OF BCD DATA, ; THEN FURTHER CONVERTED TO ASCII CHARACTERS, AND TRANSMITTED OUT ; THROUGH PIN 2. A CARRIAGE RETURN CHARACTER ( 'CR' ) IS ADDED TO THE ; OUTPUT STRING. ; ; NO AVERAGING, ERROR CHECKING, OR OTHER PROCESSING IS PERFORMED ON ; THE TRANSMITTED DATA. ; ;-------------------------------------------------------------------- ; ; COLDSTART ROUTINE ; ; CODE EXECUTION BEGINS HERE AT POWER ON ; ;-------------------------------------------------------------------- ORG H'00' ;COLDSTART ADDRESS COLDSTART GOTO STARTUP ;JUMP AROUND INTERRUPT AREA ORG H'04' ;INTERRUPT ADDRESS GOTO INTERRUPT ;JUMP OVER STARTUP ROUTINES ; ;-------------------------------------------------------------------- ; ; STARTUP ROUTINE ; ; CPU JUMPS HERE FROM COLDSTART ROUTINE ; NO SUBROUTINES ARE CALLED ; INITIALIZE THE VARIOUS REGISTERS AND I/O PORTS ; CPU PROCEEDS TO RESET ROUTINE WHEN DONE ; ;-------------------------------------------------------------------- ; ; SWITCH BANK SELECT = 1 FOR ACCESS TO CTRL REGISTERS ; INIT "A" PORT, BIT 3 = OUTPUT ( FOR RS232 OUTPUT, PIN 2 ) ; INIT "A" PORT, BIT 2 = INPUT ( FOR 360 RESET, PIN 1 ) ; INIT "A" PORT, BIT 4 = INPUT ( FOR X720 CLOCK, PIN 3 ) ; INIT "B" PORT, BIT 0 = INPUT ( FOR CALIB 1-SHOT, PIN 6 ) ; INIT TMR0 = TRIGGER FROM PIN 3 ; INIT TMR0 = POSITIVE EDGE TRIGGER ; INIT TMR0 = PRESCALER OUTPUT ; INIT PRESCALER RATIO = 2:1 ; SWITCH BANK SELECT = 0 FOR MAIN PROGRAM ; ENABLE ZC DETECT INTERRUPT ; INIT STROBE_COUNT = 7 ( FOR DIGITAL READOUT ONLY ) ; ORG H'10' ; STARTUP CLRF PORTA ;A PORT, BIT 2 = RS232 OUT ; ; SWITCH TO BANK 1 FOR ACCESS TO CONTROL REGISTERS ; BSF STATUS,5 ;SELECT BANK 1 FOR TRISA REG CLRF TRISA ;INIT PORT A, = ALL OUTPUTS BSF TRISA,2 ;360 RESET = INPUT BSF TRISA,4 ;X720 CLOCK = INPUT CLRF TRISB ;INIT PORT B = ALL OUTPUTS BSF TRISB,0 ;ZC DETECT = INPUT BSF OPT,6 ;ZC DETECT = RISING EDGE BSF OPT,5 ;COUNTER CLK = PIN 3 BCF OPT,4 ;CLOCK = RISING EDGE BCF OPT,3 ;PRESCALER = ON BCF OPT,0 ;PRESCALER = 2:1 BCF OPT,1 ;SAME BCF OPT,2 ;SAME ; ; BACK TO BANK 0 FOR MAIN PROGRAM ; BCF STATUS,5 ;BACK TO BANK 0 BSF INTCON,4 ;ENABLE ZC DETECT INTERRUPT MOVLW H'07' ;INIT STROBE_COUNT MOVWF STROBE_COUNT ; = 7 ; ;-------------------------------------------------------------------- ; ; RESET ROUTINE ; ; CPU ARRIVES HERE FROM STARTUP ROUTINE ; NO SUBROUTINES ARE CALLED ; CLEARS THE BEARING COUNTER AND ENABLES INTERRUPTS ; WHENEVER 74LS93 ON MAIN PC BOARD "OVERFLOWS" ( = 000 DEGREES ) ; CPU REMAINS HERE ( LOOPS ENDLESSLY ) UNTIL INTERRUPTED ; ;-------------------------------------------------------------------- ; WATCH "A" PORT, BIT 2 ( = PIN 1 ) FOR FALLING EDGE SIGNAL ; WHEN DETECTED, CHECK IF THIS ROUTINE WAS PREVIOUSLY INTERRUPTED ; IF SO, IGNORE IT... MIGHT BE A MISTAKE ; OTHERWISE, RESET TMR0 + OVERFLOW BIT AND ENABLE ; THE ZERO CROSSING INTERRUPT. ALSO RESET THE PRESCALER RATIO ; TO 2:1 FOR THE TMR0 REGISTER. ( = BEARING COUNTER ) ; ; THIS ROUTINE WILL LOOP ENDLESSLY UNLESS INTERRUPTED BY A ; ZERO-CROSSING DETECT PULSE ON PIN 6. WHEN THE INTERRUPT IS ; PROCESSED, ( = MESSAGE TRANSMITTED ) CONTROL WILL RETURN HERE. ; ; LOOK FOR FALLING EDGE SIGNAL ON PIN 1 ; RESET1 MOVF PORTA,0 ;GET PORT A DATA ANDLW H'04' ;ONLY BIT 2 XORWF LAST,0 ;LOOK FOR A CHANGE MOVWF RESULT ;SAVE RESULT FOR BIT TEST BTFSS RESULT,2 ;CHANGED IF BIT 2 = 1 GOTO RESET1 ;LOOP IF NO CHANGE MOVF PORTA,0 ;GET THE NEW BYTE ANDLW H'04' ;ONLY BIT 2 MOVWF LAST ;SAVE IT BTFSC LAST,2 ;CHANGED TO 0 ? GOTO RESET1 ;IF NOT, LOOP ; ; FALLING EDGE SIGNAL WAS DETECTED ON PIN 1 ; CHECK IF THIS ROUTINE WAS INTERRUPTED. ( "SKIP" BIT 0 = 1 ) ; IF SO, THIS MIGHT BE A MISTAKE... CLEAR THE "SKIP" FLAG AND LOOP AGAIN ; RESET2 BTFSS SKIP,0 ;INTERRUPTED ? GOTO RESET3 ;IF NOT, PROCEED BCF SKIP,0 ;CLEAR THE SKIP FLAG BIT GOTO RESET1 ;LOOP ONCE MORE ; ; NOT A MISTAKE... PROCEED ; CLEAR THE BEARING COUNTER AND OVERFLOW BIT ; CLEAR THE LAST INTERRUPT AND RE-ENABLE IT ; RESET3 CLRF TMR0 ;CLEAR TIMER REGISTER BCF INTCON,2 ;CLEAR THE OVERFLOW BIT BCF INTCON,1 ;CLEAR INTERRUPT FLAG BIT BSF INTCON,7 ;ENABLE GIE BIT GOTO RESET1 ;LOOP TIL INTERRUPTED ; ;-------------------------------------------------------------------- ; ; INTERRUPT ROUTINE ; ; CPU JUMPS HERE WHEN CALIB 1-SHOT GENERATES AN INTERRUPT ; NO SUBROUTINES ARE CALLED ; REGISTER CONTENTS ARE SAVED AND PRESCALER IS "SLOWED DOWN" TO ; PREVENT FURTHER CHANGES OF BEARING DATA ; CPU PROCEEDS TO STROBE ROUTINE WHEN DONE ; ;-------------------------------------------------------------------- ; CALIB 1-SHOT TRIGGER WAS DETECTED AT B PORT, BIT 0 ( = PIN 6 ) ; ; FURTHER INTERRUPTS ARE AUTOMATICALLY DISABLED UNTIL THE GIE ; BIT IN INTCON REGISTER IS SET ; ; SAVE W AND STATUS REGISTER CONTENTS ; SWITCH PRESCALER RATIO FROM 2 TO 256 ; PROCEED TO THE OUTPUT ROUTINES ; ; INTERRUPT MOVWF W_TEMP ;SAVE W REGISTER CONTENTS SWAPF STATUS,W ;MOVE STATUS TO W REGISTER MOVWF STATUS_TEMP ;SAVE STATUS REGISTER ; ; SWITCH TO BANK 1 TO ACCESS THE OPTION REGISTER ; BSF STATUS,5 ;GO TO BANK 1 FOR OPTION REG BSF OPT,2 ;PRESCALER RATIO TO 256 BSF OPT,1 ;SAME BSF OPT,0 ;SAME, PROCEED TO BINBCD ; ; SWITCH BACK TO BANK 0 FOR MAIN PROGRAM ; BCF STATUS,5 ;BACK TO BANK 0 ; ;-------------------------------------------------------------------- ; ; STROBE ROUTINE ; ; CPU ARRIVES HERE FROM INTERRUPT ROUTINE ; NO SUBROUTINES ARE CALLED ; PROCEEDS TO BINBCD ROUTINE WHEN DONE ; ; THIS ROUTINE WAS ADDED ONLY FOR THE BENEFIT OF ; THE DIGITAL READOUT OPTION... IT IS NOT NECESSARY ; FOR THE SERIAL OUTPUT FUNCTION. IT GENERATES A STROBE ; PULSE FOR THE DATA LATCHES OF THE DIGITAL READOUT ONCE ; EVERY 7 ( RS232 ) "MESSAGES" ; ( SLOWS DOWN THE DISPLAY UPDATE RATE TO PREVENT ; EXCESSIVE "JITTER" OF THE READOUT ) ; ;------------------------------------------------------------------- ; ; DECREMENT STROBE_COUNTER ; CHECK IF STROBE_COUNTER = 0 ; IF NOT, JUMP TO BINBCD ROUTINE ; OTHERWISE, RESET STROBE_COUNTER TO = 7 ; AND GENERATE A STROBE PULSE ON RB3 ( = PIN 9 ) ; THEN PROCEED TO BCDBIN ROUTINE ; STROBE DECFSZ STROBE_COUNT,1 ;TIME TO STROBE ? GOTO BINBCD ;IF NOT, JUMP MOVLW H'07' ;RESET STROBE_COUNT MOVWF STROBE_COUNT ;SAME BSF PORTB,3 ;MAKE A PULSE NOP ;GIVE IT TIME NOP ; BCF PORTB,3 ;END PULSE ; ;-------------------------------------------------------------------- ; ; BINBCD ROUTINE ; ; CPU ARRIVES HERE FROM STROBE ROUTINE ; EXAMINE THE 9-BIT BINARY NUMBER WHICH REPRESENTS SIGNAL BEARING ; CONVERT EACH BIT TO AN EQUIVALENT 3 DIGIT BCD NUMBER ; THIS ROUTINE CALLS THE SUM SUBROUTINE IF TESTED BIT = 1 ; CPU JUMPS TO MAXLIMIT WHEN DONE ; ;-------------------------------------------------------------------- ; ; CHECKS EACH OF 9 BINARY BITS ( 8 TMR0 BITS + TMR0 "OVERFLOW" BIT ) ; IF BIT = 0, SKIP TO NEXT BIT ; IF BIT = 1, STORE CORRESPONDING BCD DIGITS IN TEMPORARY REGISTERS ; AND CALL THE SUM SUBROUTINE ; ; BEGIN BY CLEARING THE TOTAL REGISTERS. ( TOTAL = 000 ) ; THE FIRST BIT DOES NOT CALL THE SUM SUBROUTINE, BECAUSE THERE IS ; NOTHING ( = 000 ) IN THE TOTAL REGISTERS, AT THIS POINT. ; TESTS FOR ALL OTHER BITS CALL THE SUM SUBROUTINE, IF TESTED BIT = 1 ; ; CLEAR THE 3 BCD DIGIT "RESULT" REGISTERS ; BINBCD MOVLW 0 ;CLEAR W REGISTER MOVWF BCDX100 ;CLEAR BCD X100 BYTE MOVWF BCDX10 ;CLEAR BCD X10 BYTE MOVWF BCDX1 ;CLEAR BCD X1 BYTE ; ; CONVERT 2^8 BIT TO BCD DIGITS 2-5-6 ; MOVE RESULT TO TOTAL ; BIN2E8 BTFSS INTCON,2 ;BIT 8 = 1 ? GOTO BIN2E7 ;IF NOT, JUMP MOVLW BCD2 ;LOAD BCD DIGIT 2 MOVWF BCDX100 ;STORE IT IN BCD X100 MOVLW BCD5 ;LOAD BCD DIGIT 5 MOVWF BCDX10 ;STORE IT IN BCD X10 MOVLW BCD6 ;LOAD BCD DIGIT 6 MOVWF BCDX1 ;STORE IT IN BCD X1 BCF INTCON,2 ;RESET COUNTER OVERFLOW BIT ; ; CONVERT 2^7 BIT TO BCD DIGITS 1-2-8 ; ADD RESULT TO TOTAL ( = CALL SUM1 ) ; BIN2E7 BTFSS TMR0,7 ;BIT 7 = 1 ? GOTO BIN2E6 ;IF NOT, JUMP MOVLW BCD1 ;LOAD BCD DIGIT 1 MOVWF BCDX100T ;STORE IT IN BCD X100 TEMP MOVLW BCD2 ;LOAD BCD DIGIT 2 MOVWF BCDX10T ;STORE IT IN BCD X10 TEMP MOVLW BCD8 ;LOAD BCD DIGIT 8 MOVWF BCDX1T ;STORE IT IN BCD X1 TEMP CALL BCDSUM1 ;ADD 1-2-8 TO TOTAL ; ; CONVERT 2^6 BIT TO BCD DIGITS 0-6-4 ; ADD RESULT TO TOTAL ( = CALL SUM1 ) ; BIN2E6 BTFSS TMR0,6 ;BIT 6 = 1 ? GOTO BIN2E5 ;IF NOT, JUMP MOVLW BCD0 ;LOAD BCD DIGIT 0 MOVWF BCDX100T ;STORE IT IN BCD X100 TEMP MOVLW BCD6 ;LOAD BCD DIGIT 6 MOVWF BCDX10T ;STORE IT IN BCD X10 TEMP MOVLW BCD4 ;LOAD BCD DIGIT 4 MOVWF BCDX1T ;STORE IT IN BCD X1 TEMP CALL BCDSUM1 ;ADD 0-6-4 TO TOTAL ; ; CONVERT 2^5 BIT TO BCD DIGITS 0-3-2 ; ADD RESULT TO TOTAL ( = CALL SUM1 ) ; BIN2E5 BTFSS TMR0,5 ;BIT 5 = 1 ? GOTO BIN2E4 ;IF NOT, JUMP MOVLW BCD0 ;LOAD BCD DIGIT 0 MOVWF BCDX100T ;STORE IT IN BCD X100 TEMP MOVLW BCD3 ;LOAD BCD DIGIT 3 MOVWF BCDX10T ;STORE IT IN BCD X10 TEMP MOVLW BCD2 ;LOAD BCD DIGIT 2 MOVWF BCDX1T ;STORE IT IN BCD X1 TEMP CALL BCDSUM1 ;ADD 0-3-2 TO TOTAL ; ; CONVERT 2^4 BIT TO BCD DIGITS 0-1-6 ; ADD RESULT TO TOTAL ( = CALL SUM1 ) ; BIN2E4 BTFSS TMR0,4 ;BIT 4 = 1 ? GOTO BIN2E3 ;IF NOT, JUMP MOVLW BCD0 ;LOAD BCD DIGIT 0 MOVWF BCDX100T ;STORE IT IN BCD X100 TEMP MOVLW BCD1 ;LOAD BCD DIGIT 1 MOVWF BCDX10T ;STORE IT IN BCD X10 TEMP MOVLW BCD6 ;LOAD BCD DIGIT 6 MOVWF BCDX1T ;STORE IT IN BCD X1 TEMP CALL BCDSUM1 ;ADD 0-1-6 TO TOTAL ; ; CONVERT 2^3 BIT TO BCD DIGITS 0-0-8 ; ADD RESULT TO TOTAL ( = CALL SUM1 ) ; BIN2E3 BTFSS TMR0,3 ;BIT 3 = 1 ? GOTO BIN2E2 ;IF NOT, JUMP MOVLW BCD0 ;LOAD BCD DIGIT 0 MOVWF BCDX100T ;STORE IT IN BCD X100 TEMP MOVLW BCD0 ;LOAD BCD DIGIT 0 MOVWF BCDX10T ;STORE IT IN BCD X10 TEMP MOVLW BCD8 ;LOAD BCD DIGIT 8 MOVWF BCDX1T ;STORE IT IN BCD X1 TEMP CALL BCDSUM1 ;ADD 0-0-8 TO TOTAL ; ; CONVERT 2^2 BIT TO BCD DIGITS 0-0-4 ; ADD RESULT TO TOTAL ( = CALL SUM1 ) ; BIN2E2 BTFSS TMR0,2 ;BIT 2 = 1 ? GOTO BIN2E1 ;IF NOT, JUMP MOVLW BCD0 ;LOAD BCD DIGIT 0 MOVWF BCDX100T ;STORE IT IN BCD X100 TEMP MOVLW BCD0 ;LOAD BCD DIGIT 0 MOVWF BCDX10T ;STORE IT IN BCD X10 TEMP MOVLW BCD4 ;LOAD BCD DIGIT 4 MOVWF BCDX1T ;STORE IT IN BCD X1 TEMP CALL BCDSUM1 ;ADD 0-0-4 TO TOTAL ; ; CONVERT 2^1 BIT TO BCD DIGITS 0-0-2 ; ADD RESULT TO TOTAL ( = CALL SUM1 ) ; BIN2E1 BTFSS TMR0,1 ;BIT 1 = 1 ? GOTO BIN2E0 ;IF NOT, JUMP MOVLW BCD0 ;LOAD BCD DIGIT 0 MOVWF BCDX100T ;STORE IT IN BCD X100 TEMP MOVLW BCD0 ;LOAD BCD DIGIT 0 MOVWF BCDX10T ;STORE IT IN BCD X10 TEMP MOVLW BCD2 ;LOAD BCD DIGIT 2 MOVWF BCDX1T ;STORE IT IN BCD X1 TEMP CALL BCDSUM1 ;ADD 0-0-2 TO TOTAL ; ; CONVERT 2^0 BIT TO BCD DIGITS 0-0-1 ; ADD RESULT TO TOTAL ( = CALL SUM1 ) ; BIN2E0 BTFSS TMR0,0 ;BIT 0 = 1 ? GOTO MAXLIMIT ;IF NOT, JUMP MOVLW BCD0 ;LOAD BCD DIGIT 0 MOVWF BCDX100T ;STORE IT IN BCD X100 TEMP MOVLW BCD0 ;LOAD BCD DIGIT 0 MOVWF BCDX10T ;STORE IT IN BCD X10 TEMP MOVLW BCD1 ;LOAD BCD DIGIT 1 MOVWF BCDX1T ;STORE IT IN BCD X1 TEMP CALL BCDSUM1 ;ADD 0-0-1 TO TOTAL GOTO MAXLIMIT ;DONE, NEXT ROUTINE ; ;-------------------------------------------------------------------- ; ; SUM SUBROUTINE ; ; CALLED BY BCDBIN ROUTINE IF TESTED BIT = 1 ; CALLS NO SUBROUTINES ; ADDS 3 BCD DIGITS IN "TEMPORARY" REGISTERS TO 3 BCD "TOTAL" REGISTERS ; RESULT PLACED IN 3 BCD "TOTAL" REGISTERS ; RETURNS WHEN ALL 3 DIGITS ARE SUMMED TO "TOTAL" ; ;-------------------------------------------------------------------- ; ; ADD BCDX1T TO BCDX1, PUT RESULT IN BCDX1 ; CHECK IF CARRY TO BCDX10 WAS GENERATED AND DO IT ( IF REQUIRED ) ; ADD BCDX10T AND BCDX10, PUT RESULT IN BCDX10 ; CHECK IF CARRY TO BCDX100 WAS GENERATED AND DO IT ( IF REQUIRED ) ; ADD BCDX100T TO BCDX100, PUT RESULT IN BCDX100 ; BCDSUM1 CLRW ;CLEAR W REGISTER ADDWF BCDX1,0 ;GET PREVIOUS BCD X1 ANSWER ADDWF BCDX1T,0 ;ADD NEW PART MOVWF BCDX1 ;STORE RESULT ADDLW OFLOW ;CHECK IF ANSWER < 10 BTFSS STATUS,DC ; GOTO BCDSUM10 ;IF ANSWER < 10, JUMP INCF BCDX10,1 ;CARRY 1 TO NEXT DIGIT MOVLW TEN ;SUBTRACT 10 FROM BCD X1 ANSWER SUBWF BCDX1,1 ;SAVE IT BCDSUM10 CLRW ;CLEAR W REGISTER ADDWF BCDX10,0 ;GET PREVIOUS BCD X10 ANSWER ADDWF BCDX10T,0 ;ADD NEW PART MOVWF BCDX10 ;STORE RESULT ADDLW OFLOW ;CHECK IF ANSWER < 10 BTFSS STATUS,DC ; GOTO BCDSUM100 ;IF ANSWER < 10, JUMP INCF BCDX100,1 ;CARRY 1 TO NEXT DIGIT MOVLW TEN ;SUBTRACT 10 FROM BCD X10 ANSWER SUBWF BCDX10,1 ;SAVE IT BCDSUM100 CLRW ;CLEAR W REGISTER ADDWF BCDX100,0 ;GET PREVIOUS BCD X100 ANSWER ADDWF BCDX100T,0 ;ADD NEW PART MOVWF BCDX100 ;STORE RESULT RETURN ;DONE ; ;-------------------------------------------------------------------- ; ; MAXLIMIT ROUTINE ; ; CPU JUMPS HERE FROM BINBCD ROUTINE ; NO SUBROUTINES ARE CALLED ; CHECKS IF RESULT = 360 ( OR GREATER ) ; REPLACE RESULT WITH 000, IF TRUE ; CPU PROCEEDS TO BCDASC ROUTINE WHEN DONE ; ;-------------------------------------------------------------------- ; ; CHECK IF BCD X100 = 3 ; MAXLIMIT BTFSS BCDX100,1 ; = XX1X ? GOTO BCDASC ;JUMP IF NOT BTFSS BCDX100,0 ; = XXX1 ? GOTO BCDASC ;JUMP IF NOT ; ; CHECK IF BCD X10 = 6 ; BTFSS BCDX10,2 ; = X1XX ? GOTO BCDASC ;JUMP IF NOT BTFSS BCDX10,1 ; = XX1X ? GOTO BCDASC ;JUMP IF NOT ; ; BCD = 36X ( OR 37X ) ... REPLACE IT WITH 000 ; CLRF BCDX100 ;CLEAR BCD X100 CLRF BCDX10 ;CLEAR BCD X10 CLRF BCDX1 ;CLEAR BCD X1 GOTO BCDASC ;DONE ; ;-------------------------------------------------------------------- ; ; BCDASC ROUTINE ; ; CPU JUMPS HERE FROM BINBCD ROUTINE ; NO SUBROUTINES ARE CALLED ; CONVERTS 3 DIGITS OF BCD DATA TO CORRESPONDING ASCII CHARACTERS ; CPU PROCEEDS TO SERIAL ROUTINE WHEN DONE ; ;-------------------------------------------------------------------- ; ; CONVERT ALL 3 BCD DIGITS TO ASCII CHARACTERS ; ASCII CHARACTER = BCD DIGIT + HEX '30' ; BCDASC MOVLW H'30' ;ASCII = BCD + H'30' ADDWF BCDX1,1 ;CONVERT BCDX1 TO ACSX1 ADDWF BCDX10,1 ;CONVERT BCDX10 TO ASC10 ADDWF BCDX100,1 ;CONVERT BCDX00 TO ASCX100 GOTO SERIAL ;OUTPUT ASCII CHARACTERS ; ;-------------------------------------------------------------------- ; ; SERIAL ROUTINE ; ; CPU ARRIVES HERE FROM "BCDASC" ROUTINE ; CALLS SEROUT SUBROUTINE ONCE FOR EACH CHARACTER ; OUTPUTS "%" CHARACTER ( COMPLY WITH APRS SPEC, = START OF DF MESSAGE ) ; OUTPUT 3 ASCII DIGITS ( BCD X100, BCD X10, BCD X1 DEG RELATIVE ) ; OUTPUT A "/" CHARACTER ( COMPLY WITH APRS SPEC, = FIELD DELIMITER ) ; OUTPUT A "7" CHARACTER ( COMPLY WITH APRS SPEC, = SIG QUALITY 0-7 ) ; OUTPUT A CARRIAGE RETURN CHARACTER ( COMPLY WITH APRS SPEC, = EOM ) ; CPU PROCEEDS TO FINISH SUBROUTINE WHEN DONE ; ;-------------------------------------------------------------------- ; ; MOVE "%" (= HEX 25) TO OUTPUT BUFFER AND CALL "SEROUT" SUBROUTINE ; MOVE ASCII BCDX100 TO OUTPUT BUFFER AND CALL "SEROUT" SUBROUTINE ; MOVE ASCII BCDX10 TO OUTPUT BUFFER AND CALL "SEROUT" SUBROUTINE ; MOVE ASCII BCDX1 TO OUTPUT BUFFER AND CALL "SEROUT" SUBROUTINE ; MOVE "/" (= HEX 2F) TO OUTPUT BUFFER AND CALL "SEROUT" SUBROUTINE ; MOVE "7" (= HEX 37) TO OUTPUT BUFFER AND CALL "SEROUT" SUBROUTINE ; MOVE ASCII 'CR' TO OUTPUT BUFFER AND CALL "SEROUT" SUBROUTINE ; SERIAL MOVLW H'25' ;= ASCII % MOVWF ASCOUT ;STORE IT CALL SEROUT ;SEND IT MOVF BCDX100,0 ;GET ASCII BCDX100 CHARACTER MOVWF ASCOUT ;STORE IN OUTPUT REGISTER CALL SEROUT ;OUTPUT IT MOVF BCDX10,0 ;GET ASCII BCDX10 CHARACTER MOVWF ASCOUT ;STORE IT IN OUTPUT REGISTER CALL SEROUT ;OUTPUT IT MOVF BCDX1,0 ;GET ASCII BCDX1 CHARACTER MOVWF ASCOUT ;STORE IT IN OUTPUT REGISTER CALL SEROUT ;OUTPUT IT MOVLW H'2F' ;= ASCII / MOVWF ASCOUT ;STORE IT CALL SEROUT ;SEND IT MOVLW H'37' ;= ASCII 7 MOVWF ASCOUT ;STORE IT CALL SEROUT ;SEND IT MOVLW '0D' ;HEX 0D = CARRIAGE RETURN MOVWF ASCOUT ;STORE IT IN OUTPUT REGISTER CALL SEROUT ;OUTPUT IT ; ;-------------------------------------------------------------------- ; ; FINISH ROUTINE ; ; CPU ARRIVES HERE FROM SERIAL ROUTINE ; NO SUBROUTINES ARE CALLED ; SET "SKIP" BIT 0 TO IGNORE NEXT ANTENNA CYCLE ; RESTORES PRESCALER TO DIVIDE BY 2 ; RESTORES CPU REGISTERS TO ORIGINAL CONDITION ; ; THIS IS THE FINAL ROUTINE IN THE INTERRUPT HANDLER... ; IT RETURNS EXECUTION TO MAIN PROGRAM WHEN DONE ; ;-------------------------------------------------------------------- ; FINISH BSF SKIP,0 ; = IGNORE NEXT CYCLE ; ; SWITCH TO BANK 1 FOR ACCESS TO OPTION REGISTER ; CHANGE THE PRESCALER RATIO BACK TO DIVIDE BY 2 ; BSF STATUS,5 ;GO TO BANK 1 FOR OPTION REG BCF OPT,2 ;PRESCALER RATIO = 2:1 BCF OPT,1 ;SAME BCF OPT,0 ;SAME ; ; SWITCH BACK TO BANK 0 FOR MAIN PROGRAM ; RESTORE CPU REGISTERS AND RETURN ; BCF STATUS,5 ;GO TO BANK 0 FOR MAIN PGM SWAPF STATUS_TEMP,W ;RETRIEVE STATUS REGISTER MOVWF STATUS ;RESTORE STATUS REGISTER SWAPF W_TEMP,1 ;RESTORE W REGISTER SWAPF W_TEMP,W ; RETURN ;RETURN TO MAIN PROGRAM ; ;-------------------------------------------------------------------- ; ; SEROUT SUBROUTINE ; ; OUTPUTS A SINGLE ASCII CHARACTER ; CALLED BY SERIAL ROUTINE ; CALLS BAUD0 OR BAUD1 SUBROUTINE FOR EACH BIT ; RETURNS WHEN LAST STOP BIT IS OUTPUT ; ;-------------------------------------------------------------------- ; ; OUTPUT A START BIT ; SEROUT CALL BAUD0 ;OUTPUT A START BIT ; ; OUTPUT ASCII BIT 1 ( = DATA BIT 0 ) ; BTFSS ASCOUT,0 ;ASCII BIT 0 = LOW ? CALL BAUD0 ;YES, OUTPUT A 0 BIT BTFSC ASCOUT,0 ;ASCII BIT 0 = HIGH ? CALL BAUD1 ;YES, OUTPUT A 1 BIT ; ; OUTPUT ASCII BIT 2 ( = DATA BIT 1 ) ; BTFSS ASCOUT,1 ;ASCII BIT 0 = LOW ? CALL BAUD0 ;YES, OUTPUT A 0 BIT BTFSC ASCOUT,1 ;ASCII BIT 0 = HIGH ? CALL BAUD1 ;YES, OUTPUT A 1 BIT ; ; OUTPUT ASCII BIT 3 ( = DATA BIT 2 ) ; BTFSS ASCOUT,2 ;ASCII BIT 0 = LOW ? CALL BAUD0 ;YES, OUTPUT A 0 BIT BTFSC ASCOUT,2 ;ASCII BIT 0 = HIGH ? CALL BAUD1 ;YES, OUTPUT A 1 BIT ; ; OUTPUT ASCII BIT 4 ( = DATA BIT 3 ) ; BTFSS ASCOUT,3 ;ASCII BIT 0 = LOW ? CALL BAUD0 ;YES, OUTPUT A 0 BIT BTFSC ASCOUT,3 ;ASCII BIT 0 = HIGH ? CALL BAUD1 ;YES, OUTPUT A 1 BIT ; ; OUTPUT ASCII BIT 5 ( = DATA BIT 4 ) ; BTFSS ASCOUT,4 ;ASCII BIT 0 = LOW ? CALL BAUD0 ;YES, OUTPUT A 0 BIT BTFSC ASCOUT,4 ;ASCII BIT 0 = HIGH ? CALL BAUD1 ;YES, OUTPUT A 1 BIT ; ; OUTPUT ASCII BIT 6 ( = DATA BIT 5 ) ; BTFSS ASCOUT,5 ;ASCII BIT 0 = LOW ? CALL BAUD0 ;YES, OUTPUT A 0 BIT BTFSC ASCOUT,5 ;ASCII BIT 0 = HIGH ? CALL BAUD1 ;YES, OUTPUT A 1 BIT ; ; OUTPUT ASCII BIT 7 ( = DATA BIT 6 ) ; BTFSS ASCOUT,6 ;ASCII BIT 0 = LOW ? CALL BAUD0 ;YES, OUTPUT A 0 BIT BTFSC ASCOUT,6 ;ASCII BIT 0 = HIGH ? CALL BAUD1 ;YES, OUTPUT A 1 BIT ; ; OUTPUT A "NO PARITY" BIT ( = 0 ) FOR BIT 8 ; CALL BAUD0 ;OUTPUT A 0 BIT ; ; OUTPUT STOP BIT NO. 1 ; CALL BAUD1 ;OUTPUT STOP BIT 1 ; ; OUTPUT STOP BIT NO. 2 ; CALL BAUD1 ;OUTPUT STOP BIT 2 RETURN ;DONE WITH THIS CHARACTER ;-------------------------------------------------------------------- ; ; BAUD0 AND BAUD1 SUBROUTINES ; ; CALLED BY SEROUT SUBROUTINE ; CALLS BAUDTIMER SUBROUTINE ; RETURNS WHEN BIT IS OUTPUT AND 1 BAUD OF TIME IS FINISHED ; ;-------------------------------------------------------------------- ; ; THESE ARE THE ROUTINES THAT ACTUALLY TOGGLE THE RS232 OUTPUT PIN ; BAUD0 WILL OUTPUT A '0' BIT, THEN RETURN TO CALLING ROUTINE ; BAUD1 WILL OUTPUT A '1' BIT, THEN RETURN TO CALLING ROUTINE ; BAUD0 BCF PORTA,3 ;MAKE OUTPUT BIT = 0 CALL BAUDTIMER1 ;DELAY FOR BAUD RATE RETURN ;DONE, RETURN BAUD1 BSF PORTA,3 ;MAKE OUTPUT BIT = 1 CALL BAUDTIMER1 ;DELAY FOR BAUD RATE RETURN ;DONE ;-------------------------------------------------------------------- ; ; BAUDTIMER SUBROUTINE ; ; PROVIDES TIME DELAY FOR 1 BIT OF OUTPUT DATA ; CALLED BY EITHER BAUD0 OR BAUD1 SUBROUTINES ; RETURNS WHEN TIME DELAY = FINISHED ( = 1 BAUD OF TIME ) ; ;-------------------------------------------------------------------- ; BAUDTIMER1 MOVLW DELAY ;TIME DELAY VALUE MOVWF DELAYCNT ;SAVE IT BAUDTIMER2 DECFSZ DELAYCNT,1 ;DECREMENT THE COUNTER GOTO BAUDTIMER2 ;LOOP IF NOT DONE RETURN ;OTHERWISE, RETURN ; ;-------------------------------------------------------------------- ; ; END OF EXECUTABLE CODE ; ;-------------------------------------------------------------------- ; ; LABEL DEFINITION AREA ; ;-------------------------------------------------------------------- ; ; REGISTERS ; PORTA EQU H'05' ;PORT A ADDRESS PORTB EQU H'06' ;PORT B ADDRESS TRISA EQU H'85' ;TRISA ADDRESS = PORT A CONTROL REG TRISB EQU H'86' ;TRISB ADDRESS = PORT B CONTROL REG OPT EQU H'81' ;OPTION REGISTER ADDRESS INTCON EQU H'0B' ;INTCON REGISTER ADDRESS TMR0 EQU H'01' ;TIMER REGISTER ADDRESS STATUS EQU H'03' ;STATUS REGISTER ADDRESS BCDX100 EQU H'0C' ;BCDX100 SUM "ANSWER" BCDX10 EQU H'0D' ;BCDX10 SUM "ANSWER" BCDX1 EQU H'0E' ;BCDX1 SUM "ANSWER" BCDX100T EQU H'0F' ;BCDX100 TEMPORARY ( NEXT TERM TO ADD ) BCDX10T EQU H'10' ;BCDX10 TEMPORARY ( NEXT TERM TO ADD ) BCDX1T EQU H'11' ;BCDX1 TEMPORARY ( NEXT TERM TO ADD ) ASCOUT EQU H'12' ;ASCII CHARACTER FOR OUTPUT LAST EQU H'13' ;LAST VALUE OF 360 RESET INPUT DELAYCNT EQU H'14' ;REGISTER FOR BAUD RATE DELAY RESULT EQU H'15' ;RESULT OF LAST 360 RESET COMPARISON STATUS_TEMP EQU H'16' ;INTERRUPT STORAGE FOR STATUS REGISTER W_TEMP EQU H'17' ;INTERRUPT STORAGE FOR W REGISTER SKIP EQU H'18' ;SKIP FLAG REGISTER STROBE_COUNT EQU H'19' ;COUNTER FOR DIGITAL READOUT ONLY ; ; NUMERIC CONSTANTS ; DELAY EQU H'F0' ;CONSTANT (1200 BAUD DELAY) BCD0 EQU 0 ;CONSTANT BCD1 EQU 1 ;CONSTANT BCD2 EQU 2 ;CONSTANT BCD3 EQU 3 ;CONSTANT BCD4 EQU 4 ;CONSTANT BCD5 EQU 5 ;CONSTANT BCD6 EQU 6 ;CONSTANT BCD7 EQU 7 ;CONSTANT BCD8 EQU 8 ;CONSTANT BCD9 EQU 9 ;CONSTANT ZERO EQU 0 ;CONSTANT OFLOW EQU D'246' ;CONSTANT (BCD OVERFLOW TEST) TEN EQU D'10' ;CONSTANT DC EQU 0 ;BCD CARRY (STATUS REG BIT 0) ; ;-------------------------------------------------------------------- ; ; END OF SOURCE CODE ; ;-------------------------------------------------------------------- END