; TITLE 'Dinsmore Compass Reader' ; ;Copyright Dennis Clark and TTT Enterprises. This code is free to use and ;distribute according to the Free Software Copyleft rules and conventions. ;You may not publish or sell it without written permission from me, the ;author. ; ; I included the "include" file for the 508 for reference while programming ; LIST P = 12C508, F = INHX8M ; P12C508.INC Standard Header File, Version 1.02 Microchip Technology, Inc. ;========================================================================== ; Verify Processor ;========================================================================== IFNDEF __12C508 MESSG "Processor-header file mismatch. Verify selected processor." ENDIF ;========================================================================== ; Register Definitions ;========================================================================== W EQU H'0000' F EQU H'0001' ;----- Register Files ----------------------------------------------------- INDF EQU H'0000' ; Uses FSR to address data mem. TMR0 EQU H'0001' ; 8 bit real time clock/counter PCL EQU H'0002' ; Low order 8 bits of PC STATUS EQU H'0003' ; STATUS FSR EQU H'0004' ; Indirect data memory addr pointer OSCCAL EQU H'0005' ; Calibration data for osc. GPIO EQU H'0006' ; General Purpose I/O ;----- STATUS Bits -----------Page 14-------------------------------------- GPWUF EQU H'0007' ; GPIO reset bit PA0 EQU H'0005' ; Program Page preselect NOT_TO EQU H'0004' ; Time Out bit NOT_PD EQU H'0003' ; Power Down bit ZERO EQU H'0002' ; Zero bit DC EQU H'0001' ; Digit carry/*borrow bit CARRY EQU H'0000' ; carry/*borrow bit ;----- OPTION Bits -----------Page 15-------------------------------------- NOT_GPWU EQU H'0007' ; Enable wake-up on pin change NOT_GPPU EQU H'0006' ; Enable weak pull-ups T0CS EQU H'0005' ; Timer0 clock source select T0SE EQU H'0004' ; Timer0 sources edge select PSA EQU H'0003' ; Prescalar assignment bit PS2 EQU H'0002' ;\ PS1 EQU H'0001' ; > Prescalar rate select bits PS0 EQU H'0000' ;/ ;========================================================================== ; RAM Definition ;========================================================================== __MAXRAM H'3F' ;========================================================================== ; Configuration Bits ;========================================================================== _MCLRE_ON EQU H'0FFF' _MCLRE_OFF EQU H'0FEF' _CP_ON EQU H'0FF7' _CP_OFF EQU H'0FFF' _WDT_ON EQU H'0FFF' _WDT_OFF EQU H'0FFB' _LP_OSC EQU H'0FFC' _XT_OSC EQU H'0FFD' _IntRC_OSC EQU H'0FFE' _ExtRC_OSC EQU H'0FFF' __CONFIG ( _MCLRE_OFF & _CP_OFF & _WDT_OFF & _IntRC_OSC ) ;========================================================================== ; Program Variables ;========================================================================== ;Port definitions and other constants or macros #define TRIGGER GPIO,5 ; Pin 2 = GP5 = trigger reading input #define DATA GPIO,5 ; Pin 2 = GP5 = data out too #define ENABLE GPIO,4 ; Pin 3 = GP4 = Bit 4 O #define WEST GPIO,3 ; Pin 4 = GP3 = Bit 3 I #define SOUTH GPIO,2 ; Pin 5 = GP2 = Bit 2 I #define EAST GPIO,1 ; Pin 6 = GP1 = Bit 1 I #define NORTH GPIO,0 ; Pin 7 = GP0 = Bit 0 I #define WAITFORIT B'11101111' ; pattern to wait for trigger #define SENDIT B'11001111' ; Now GP5 sends data back #define DELAY D'51' ; 2400 BAUD delay amount (417us) ;#define DELAY D'1' ; MPLAB test line #define LDELAY D'56' ; Long delay (333ms), 85= 500ms ;#define LDELAY D'1' ; MPLAB test line #define TABLE D'16' ; Start of look up table LIST ;Register locations for important stuff,only 9-15 are available before table DELAY1 EQU D'8' ; First counter for time delays DELAY2 EQU D'9' ; Second counter for time delay READING EQU D'10' ; Location of port reading DOUT EQU D'11' ; Location of data to be sent BCOUNT EQU D'12' ; bit count register ;================================ ; Main Code = ;================================ ORG 0x1FF ; MOVLW 0x50 ; My EPROM calibration value,remove for OTPs start ORG 0x000 MOVWF OSCCAL ; Store the factory osc. calibration value MOVLW WAITFORIT ; Set pin 3 as output, 7,6,5,4,2 as inputs TRIS GPIO ; Configure pins as either I or O MOVLW B'01000000' ; Set OPTION bits (Weak pullups enabled) OPTION ; Implement OPTION bits BSF ENABLE ; disable the compass for now ;Set up the look up table of readings and translations ;D16+READING = the register that has the translation value MOVLW 0xFF ; 16 MOVWF D'16' MOVLW 4 ; South MOVWF D'17' MOVLW 2 ; East MOVWF D'18' MOVLW 3 ; South East MOVWF D'19' MOVLW 0 ; North MOVWF D'20' MOVLW 0xFF MOVWF D'21' MOVLW 1 ; North East MOVWF D'22' MOVLW 0xFF MOVWF D'23' MOVLW 6 ; West MOVWF D'24' MOVLW 5 ; South West MOVWF D'25' MOVLW 0xFF MOVWF D'26' MOVLW 0xFF MOVWF D'27' MOVLW 7 ; North West MOVWF D'28' MOVLW 0xFF MOVWF D'29' ; These last three are for completeness MOVLW 0xFF ; they can't be hit, no 255 can be hit. MOVWF D'30' MOVLW 0xFF MOVWF D'31' BSF DATA ; Make sure this line is high for serial main ;=========================================================================== ; This program will read the four outputs of the Dinsmore compass and encode ;what it sees. It takes a reading when the TRIGGER/DATA line is brought low ;and raised high again. It then turns the TRIGGER port into the DATA output ;port and sends the results encoded into a number from 0 to 7 via a 2400 ;BAUD RS232 formatted port. Multiply this number by 45 = compass degrees. ; If I can find tilt switches, it will also send tilt data back as well as ;any detected error conditions. # + 64 = transitioning condition, settling. ;Copyright Revision 2/5/99 Dennis Clark and TTT Enterprises ;=========================================================================== wloop BTFSS TRIGGER ; Look for a '0' GOTO wforup ; TRIGGER = 0 so now wait for it to go high GOTO wloop ; Keep looking wforup BTFSC TRIGGER ; Now look for it to go high GOTO takerdng ; OK, it now went high, we take a compass reading GOTO wforup ; Wait for it... takerdng BCF ENABLE ; Pull enable line low to turn on compass MOVLW TABLE ; Start address of the table MOVWF FSR ; Lookup table set now CALL sdelay ; let it settle MOVF GPIO,W ; Get all of the I/O pins XORLW 0xFF ; Active low inputs need reversing ANDLW 0x0F ; Only interested in the lower 4 bits ADDWF FSR,F ; Add in the offset to table start address MOVF INDF,W ; get the table value for that offset MOVWF READING ; and save the reading here CALL longdelay ; 333ms+ delay MOVLW TABLE ; table start address MOVWF FSR ; put in address offset register MOVF GPIO,W ; get another reading XORLW 0xFF ; reverse bits, negative true compass logic ANDLW 0x0F ; only lower 4 bits ADDWF FSR,F ; add offset MOVF INDF,W ; get translation SUBWF READING,F ; subtract W from READING =>READING MOVWF READING ; get the reading back! BTFSC STATUS,ZERO ; check for ==, if ZERO is set they are equal GOTO sendit ; OK, we can send this direction MOVWF READING ; put this reading in xmit register instead MOVLW 0x40 ; bit 6 (64) ADDWF READING,F ; READING + 64 = error, not settled yet sendit BSF ENABLE ; turn off the compass BSF DATA ; make sure that data line starts high CALL sendbyte ; transmit the data back GOTO wloop ; and wait for the next request ;================================ ;SUBROUTINES ;================================ longdelay ;This will delay 333ms (256*23us*56) MOVLW 0x00 MOVWF DELAY1 ; inner loop MOVLW LDELAY ; 333ms delay MOVWF DELAY2 ; outer loop oloop ; outer loop iloop ; inner loop NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP DECFSZ DELAY1,F ;decrement the inner loop GOTO iloop ;and repeat inner loop DECFSZ DELAY2,F ;decrement outer loop GOTO oloop ; and repeat outer loop RETLW 0 ; we are done here sdelay ;Short 2400 BAUD delay 8*1E-6*51(+3)=417us (416.7 is perfect) MOVLW DELAY ; 416us delay MOVWF DELAY1 ; loop siloop ; loop NOP NOP NOP NOP NOP DECFSZ DELAY1,F ; decrement the loop GOTO siloop ; and repeat loop NOP NOP NOP RETLW 0 ; all done sendbyte ;This will send the data back via 2400 baud RS232 BSF DATA ; Keep data line high right now MOVLW SENDIT ; Set pins 3,2 as outputs, 7,6,5,4 as inputs TRIS GPIO ; Configure pins as either I or O CALL sdelay ; for at least one baud cycle MOVLW 8 ; 8bit data byte MOVWF BCOUNT ; save this number here BCF DATA ; send start bit snext CALL sdelay ; 417us delay (416.7 is perfect) RRF READING,F ; start sending the data BTFSC STATUS,CARRY ; Test for bit to be transmitted BSF DATA ; Bit is a 1 BTFSS STATUS,CARRY BCF DATA ; Bit is a 0 DECFSZ BCOUNT,F ; if = 0 then we are done GOTO snext ; send the next bit otherwise CALL sdelay BSF DATA ; sending stop bit MOVLW WAITFORIT ; Set pin 3 as output, 7,6,5,4,2 as inputs TRIS GPIO ; Configure pins as either I or O RETLW 0 ; END ; directive 'end of program'