; ; COMPASS INTERFACE PROGRAM ; VERSION 1.1 : 26 OCTOBER 2000 ; FILENAME : COMPASS1.asm ; ; COPYRIGHT 2000 BOB SIMMONS / WB6EYV ; www.silcom.com/~pelican2 ; pelican2@silcom.com ; ;--------------------------------------------------------------------- ; ; PROVIDES AN INTERFACE WITH "VECTOR 2X" OEM E-COMPASS MODULE ; PERFORMS VARIOUS OPERATIONS TO EXTRACT INFO FROM THE MODULE ; GENERATES A SERIAL DATA STREAM WITH ASCII COMPASS INFO ; ; USES A PIC 16F84 CHIP ; WITH A 3.58 MHZ CRYSTAL ; ; OUTPUT DATA STREAM FORMAT : %XXX/Y ; XXX = COMPASS HEADING: HDGX100, HDGX10, HDGX1 ; Y = 7 ( FIXED IN THIS SOFTWARE ) ; COMPLIES WITH APRS AGRELO DF FORMAT FOR REPORTED DF BEARINGS ; ; COMPASS MFGR : PRECISION NAVIGATION... SANTA ROSA CALIFORNIA ; MODE OF OPERATION : POLLED, LOW RES, EXT CLK, BCD OUTPUT ; ; VECTOR 2X OUTPUT MESSAGE FORMAT : ; BITS 0-5 = ALWAYS 0 ( BCD MODE ONLY ) ; BIT 6 = BCD DEG X200 ; BIT 7 = BCD DEG X100 ; BIT 8 = BCD DEG X80 ; BIT 9 = BCD DEG X40 ; BIT 10 = BCD DEG X20 ; BIT 11 = BCD DEG X10 ; BIT 12 = BCD DEG X8 ; BIT 13 = BCD DEG X4 ; BIT 14 = BCD DEG X2 ; BIT 15 = BCD DEG X1 ; ; PIC / COMPASS PIN ASSIGNMENTS : ; RB5 (PIN 11) = POLL (OUTPUT)(LOW = START MEASUREMENT ) ; RB1 (PIN 7) = EOC (INPUT)(HIGH = MEASUREMENT COMPLETED) ; RB2 (PIN 8) = SS (OUTPUT)(LOW = ENABLE COMPASS OUTPUT) ; RB6 (PIN 12) = SCLK (OUTPUT)(RISING EDGE = GET NEXT DATA BIT) ; RB4 (PIN 10) = SDO (INPUT)(HIGH IF DATA BIT = 1) ; ; OTHER COMPASS PINS : ; YFLIP = GND ; BCD/BIN = GND ; RES = GND ; VCC = +5 VOLTS ; GND = GND ; ; ANY OTHER COMPASS PINS NOT IDENTIFIED HERE ARE LEFT "OPEN CIRCUIT" ; ;--------------------------------------------------------------------- ; START-UP ROUTINES ; ; WAIT 1/4 SECOND AFTER POWER ON BEFORE CONFIGURING PIC PINS ; PIC PINS ARE IN "INPUT" MODE DURING THIS TIME INTERVAL ; COMPASS REQUIRES THIS TO "WAKE UP" PROPERLY. ; CONFIGURE PIC PINS AFTER DELAY AND PROCEED ; START_UP MOVLW H'FF' ;START_UP DELAY TIME MOVWF WAIT_HI ; MOVWF WAIT_LO ; START_UP1 DECFSZ WAIT_LO,1 ; GOTO START_UP1 ; DECFSZ WAIT_HI,1 ; GOTO START_UP1 ; ; ; DELAY DONE, CONFIGURE THE PIC PINS ; START_UP2 CLRF PORTB ; CLRF PORTA ; BSF STATUS,5 ;= BANK 1 SELECT MOVLW H'9B' ;DEFINE I/O PINS MOVWF TRISB ; MOVLW H'F7' ; MOVWF TRISA ; BCF STATUS,5 ;= BANK 0 SELECT ; ;--------------------------------------------------------------------- ; TAKE A COMPASS READING ; ; TAKE POLL LOW ; WAIT FOR 10 mSEC ; TAKE POLL HI ; WAIT 10 mSEC ; START_MEAS BCF PORTB,POLL ;START MEASUREMENT CALL TEN_MSEC ;WAIT 10 MSEC BSF PORTB,POLL ;PULSE ONLY CALL TEN_MSEC ;WAIT 10 MSEC ; ; EXAMINE EOC... WAIT FOR EOC = HIGH ; WAIT 10 MILLISECONDS AFTER MEASUREMENT IS DONE ; THEN ENABLE THE SERIAL OUTPUT OF THE COMPASS ; WAIT 10 MILLISECONDS MORE BEFORE GETTING DATA ; DONE_YET BTFSS PORTB,EOC ;MEASUREMENT DONE YET ? GOTO DONE_YET ;IF NOT, LOOP CALL TEN_MSEC ;WAIT 10 MSEC BCF PORTB,SS ;ENABLE THE SERIAL OUTPUT CALL TEN_MSEC ;WAIT 10 MSEC ; ;--------------------------------------------------------------------- ; GET_ANSWER ROUTINE ; ; CLEAR OUT THE PREVIOUS DATA ; READ BCD X100 DATA ; READ BCD X10 DATA ; READ BCD X1 DATA ; PROCEED TO COMP_FINISH ROUTINE WHEN DONE ; GET_ANSWER CLRF BCDX100 ;CLEAR BCD X100 CLRF BCDX10 ;CLEAR BCD X10 CLRF BCDX1 ;CLEAR BCD X1 CALL GET_BIT ;THROW AWAY BIT 0 CALL GET_BIT ;THROW AWAY BIT 1 CALL GET_BIT ;THROW AWAY BIT 2 CALL GET_BIT ;THROW AWAY BIT 3 CALL GET_BIT ;THROW AWAY BIT 4 CALL GET_BIT ;THROW AWAY BIT 5 GET_X100 CALL GET_BIT ;GET BCD X200 BIT MOVWF BCDX100 ;SAVE BIT CALL GET_BIT ;GET BCD X100 BIT RLF BCDX100,1 ;MAKE ROOM FOR IT BCF BCDX100,0 ; IORWF BCDX100,1 ;SAVE IT GET_X10 CALL GET_BIT ;GET BCD X80 BIT RLF BCDX10,1 ;MAKE ROOM FOR IT BCF BCDX10,0 ; IORWF BCDX10,1 ;SAVE IT CALL GET_BIT ;GET BCD X40 BIT RLF BCDX10,1 ;MAKE ROOM FOR IT BCF BCDX10,0 ; IORWF BCDX10,1 ;SAVE IT CALL GET_BIT ;GET BCD X20 BIT RLF BCDX10,1 ;MAKE ROOM FOR IT BCF BCDX10,0 ; IORWF BCDX10,1 ;SAVE IT CALL GET_BIT ;GET BCD X10 BIT RLF BCDX10,1 ;MAKE ROOM FOR IT BCF BCDX10,0 ; IORWF BCDX10,1 ;SAVE IT GET_X1 CALL GET_BIT ;GET BCD X8 BIT RLF BCDX1,1 ;MAKE ROOM FOR IT BCF BCDX1,0 ; IORWF BCDX1,1 ;SAVE IT CALL GET_BIT ;GET BCD X4 BIT RLF BCDX1,1 ;MAKE ROOM FOR IT BCF BCDX1,0 ; IORWF BCDX1,1 ;SAVE IT CALL GET_BIT ;GET BCD X2 BIT RLF BCDX1,1 ;MAKE ROOM FOR IT BCF BCDX1,0 ; IORWF BCDX1,1 ;SAVE IT CALL GET_BIT ;GET BCD X1 BIT RLF BCDX1,1 ;MAKE ROOM FOR IT BCF BCDX1,0 ; IORWF BCDX1,1 ;SAVE IT GOTO COMP_DONE ; ; ;--------------------------------------------------------------------- ; GET_BIT SUBROUTINE ; GET ONE BIT OF COMPASS DATA ; ; WAIT A SMALL TIME INTERVAL ; TAKE SCLK LO ; WAIT A SMALL TIME INTERVAL ; TAKE SCLK HI ; WAIT A VERY SMALL TIME INTERVAL ; READ SDO BIT ; MASK UNUSED BITS AND RETURN ; GET_BIT MOVLW BIT_DELAY ;GET BIT DELAY MOVWF BIT_TIME ;SAVE IT GET_BIT_1 DECFSZ BIT_TIME,1 ;BIT_TIME = BIT_TIME - 1 GOTO GET_BIT_1 ;LOOP IF NOT DONE BCF PORTB,SCLK ;CLOCK = LO MOVLW BIT_DELAY ;GET BIT DELAY MOVWF BIT_TIME ;SAVE IT GET_BIT_2 DECFSZ BIT_TIME,1 ;BIT_TIME = BIT_TIME - 1 GOTO GET_BIT_2 ;LOOP IF NOT DONE BSF PORTB,SCLK ;CLOCK = HI NOP ;GIVE IT A LITTLE TIME NOP ; NOP ; MOVF PORTB,0 ;GET PORT BYTE MOVWF IN_BUFFER ;SAVE IT RRF IN_BUFFER,1 ;MOVE BIT 4 TO BIT 0 RRF IN_BUFFER,1 ; RRF IN_BUFFER,1 ; RRF IN_BUFFER,1 ; MOVF IN_BUFFER,0 ;BACK TO W REG ANDLW H'01' ;BIT 0, ONLY RETURN ;DONE ; ;--------------------------------------------------------------------- ; COMP_DONE ROUTINE ; ; TAKE SS HI ; WAIT 10 mSEC ; PROCEED TO BCDASC ROUTINE WHEN DONE ; COMP_DONE BSF PORTB,SS ;DISABLE THE SERIAL OUTPUT CALL TEN_MSEC ;WAIT 10 MSEC ; ;--------------------------------------------------------------------- ; BCDASC ROUTINE ; ; 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 3 ASCII DIGITS AND A CARRIAGE RETURN CHARACTER ; 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 H'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 ; FINISH GOTO START_MEAS ;REPEAT ; ;--------------------------------------------------------------------- ; 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 ; ;--------------------------------------------------------------------- ;TEN_MSEC SUBROUTINE ; ;PROVIDES 10 MILLISECONDS OF TIME DELAY ;REQUIRED BY COMPASS HARDWARE FOR VARIOUS OPERATIONS ; TEN_MSEC MOVLW MSEC_COUNT ;START VALUE FOR MSEC_DLY MOVWF MSEC_DLY ;SAVE IT IN MSEC_DLY TEN_MSEC_1 CALL BAUDTIMER1 ;WAIT 0.8 MILLISECONDS DECFSZ MSEC_DLY,1 ;DELAY = DELAY - 1 GOTO TEN_MSEC_1 ;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 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" MSEC_DLY EQU H'0F' ;10 MSEC DELAY COUNT REGISTER BIT_TIME EQU H'10' ;REGISTER FOR BIT_DELAY WAIT_HI EQU H'11' ;REGISTER FOR START_UP DELAY WAIT_LO EQU H'12' ;REGISTER FOR START_UP DELAY ASCOUT EQU H'13' ;ASCII CHARACTER FOR OUTPUT DELAYCNT EQU H'14' ;REGISTER FOR BAUD RATE DELAY IN_BUFFER EQU H'15' ;REGISTER FOR DATA INPUT BUFFER ; ; NUMERIC CONSTANTS ; MSEC_COUNT EQU H'0F' ;15 X 0.8 MSEC > 10 MSEC BIT_DELAY EQU H'0F' ;SLIGHT DELAY TIME FOR BIT READ POLL EQU H'05' ; EOC EQU H'01' ; SS EQU H'02' ; SCLK EQU H'06' ; SDO EQU H'04' ; 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