;**************************************************************************** ; Altimeter DS ; This altimeter program will take readings from a Freescale pressure ; sensor then outputs a maximum pressure reading in feet. It also turns ; on an output when it starts to fall from it's maximum height. ; Note: The resolution is only 30 feet, and I don't make any promises on ; the accuracy. ; ; Original code and circuit design by: Jerry Baumeister ; http://www.jbgizmo.com/page27.htm ; Original high voltage solenoid deployment by: Bernard Willaert ; http://users.skynet.be/willaert/WR/pin_puller.htm ; Modified by: Doug Stier to Beep out the altitude in feet and ; deploy a chute. ; ; I also want to thank Freescale and Microchip for my free samples. ; ; Please bear with me, this is my first time to program a PIC ;**************************************************************************** list p=12F675 ; list directive to define processor #include ; processor specific variable definitions errorlevel -302 ; suppress message 302 from list file __CONFIG _CP_OFF & _CPD_OFF & _BODEN_OFF & _MCLRE_OFF & _WDT_OFF & _PWRTE_ON & _INTRC_OSC_NOCLKOUT ; '__CONFIG' directive is used to embed configuration word within .asm file. ; The lables following the directive are located in the respective .inc file. ; See data sheet for additional information on configuration word settings. ;**************************************************************************** ;******** Defines *********** ;**************************************************************************** #define BANK1 banksel 0x80 ;Select Bank1 #define BANK0 banksel 0x00 ;Select Bank0 cblock 0x20 Base_L ; first analog readings low byte Base_H ; first analog readings high byte SourceL ; substraction varable low byte SourceH ; substraction varable high byte DestL ; substraction varable low byte DestH ; substraction varable high byte TenK ; BCD ten thousands Thou ; BCD thousands Hund ; BCD hundreds Tens ; BCD tens Ones ; BCD ones factor ; Log curve variable factor2 count ; used to adjust the delay time max_alt ; maximum difference cur_alt ; current difference temp ; deployed ; stores status of chute n_1 ; multiplication variables n_2 ; n_3 ; n_4 ; q_1 ; q_2 ; q_3 ; q_4 ; freq ; Beep variables duration ; tempf ; tempd ; endc ;******************************************************************* ; Double Precision Multiplication Macro ; ; n_2 : n_1 * n_4 : n_3 -> q_4:q_3:q_2:q_1 ; ; Standard shift and add. ; Execution time: 215 to 295 clock cycles. ; Code space: 22 locations ; ; Cleaned up and corrected version from Microchip Ap note by BF. ; Note: Ap note has errors! Additional mods by Scott Dattalo. ;******************************************************************* mpy16b16: macro local m1, m2 clrf q_4 clrf q_3 clrf q_2 clrf q_1 bsf q_2, 7 m1: rrf n_2, f rrf n_1, f skpc goto m2 movf n_3, w addwf q_3, f movf n_4, w skpnc incfsz n_4, w addwf q_4, f m2: rrf q_4, f rrf q_3, f rrf q_2, f rrf q_1, f skpc goto m1 endm ;******************************************************************* ; Sound generating macro ; Original code from Mikroelektronika modified by Doug Stier ;******************************************************************* Beep: macro freq,duration local B1, B2, b_wait, b_wait2, B_End movlw duration movwf tempd movlw 0x9b movwf TMR0 ; reset timer B1: bcf INTCON,T0IF ; clear the timer overflow flag B2: bsf GPIO,2 ; turn ON buzzer, pin 3 call b_wait bcf GPIO,2 ; turn OFF buzzer, pin 3 call b_wait btfss INTCON,T0IF ; has the timer overflowed? goto B2 decfsz tempd,1 ; this sets the duration of beep goto B1 goto B_End b_wait: ; the wait sets the frequency square wave movlw freq movwf tempf b_wait2: decfsz tempf,1 goto b_wait2 return B_End: endm ;**************************************************************************** ;Reset Vector ;**************************************************************************** ORG 0x000 ; processor reset vector nop ; Inserted For ICD2 Use goto Init ; go to beginning of program ;**************************************************************************** ;Initialization ;**************************************************************************** Init BANK1 ; Switch to Bank1 call 0x3FF ; retrieve factory calibration value movwf OSCCAL ; update register with factory cal value movlw B'00000001' ; pins 3,5 & 6 are outputs and pins 2,4,7 are inputs_ movwf TRISIO ;_bit0=pin7,bit1=6,bit2=5,bit3=4,bit4=3,bit5=2, ;_1=input, 0=output movlw B'11010111' ; set internal clock(5),prescale =1:256 assigned to TIMER0_ movwf OPTION_REG ;_bit0-2=prescale(100=1:32),bit3=prescale=TIMER0 (=0)_ ;_bit4=trailing edge,bit5=internal clock(0) ;_bit6=int (1=rising), bit7=pullups (diabled=1) clrf VRCON ; Vref Off (power off the comparator voltage,saves power) movlw b'01010001' ; pin 7 as anlog, Tad=16us movwf ANSEL ;_bit0=7,bit1=6,bit2=5,bit3=3 (1=analog,0=digital) ;_bit4-6= A/D clock osc value (101=16) BANK0 ; BANK 0 clrf TMR0 ; clear TIMER1 clrf GPIO ; Clear Port movlw b'00000111' movwf CMCON ; Comparator Off, bit0,1,2=1 (00000111) bsf ADCON0,0 ; turn A to D converter to "on", bit0=1 bsf ADCON0,7 ; right justified A/D, bit 7=1 Beep 0xba,0x03 ; Charge!!! (sort of sick sounding) Beep 0xa3,0x03 Beep 0x92,0x03 Beep 0x89,0x06 Beep 0x92,0x02 Beep 0x89,0x10 movlw 0x02 movwf temp s1: ; do it again because of bad first readings movlw 0x02 ; used to pause for 2 TMR0 overflows_ movwf count ; to give everthing time to warmup_ call ShortDelay ; before starting A to D bsf ADCON0,1 ; Start A/D conversion of voltage on pin 7 Start btfss PIR1,6 ; PIR1 bit6 =1 when AD conversion is complete goto Start ; start taking and recording pressure changes bcf PIR1,6 Beep 0x20,0x01 Beep 0x01,0x02 decfsz temp,1 goto s1 bcf deployed,0 clrf max_alt call Baseline ; record the first pressure reading nop nop nop nop nop bsf ADCON0,1 ; Start A/D conversion of voltage on pin 7 ;**************************************************************************** ;********** MAIN - Main Routine *************** ;**************************************************************************** Main btfss PIR1,6 ; PIR1 bit6 =1 when AD conversion is complete goto Main bcf PIR1,6 ; call Update ; compare the ad result and update max and min values call Low_ nop nop nop nop nop nop nop nop nop bsf ADCON0,1 ; Start A/D conversion of voltage on pin 7 goto Main ;******************************************************************* ;************* *************** ;************* subroutines *************** ;************* *************** ;******************************************************************* Baseline ;establish the initial pressure readings movf ADRESH,0 ;move the AD result to w register movwf Base_H ;move to the First reading registers BANK1 movf ADRESL,0 BANK0 nop movwf Base_L return ;***************************************************************** Update ; sub routine which updates the registers BANK1 movf ADRESL,0 BANK0 movwf SourceL nop BANK0 nop movf ADRESH,0 ; move the AD presure result to Source movwf SourceH movf Base_H,0 movwf DestH movf Base_L,0 movwf DestL call Subtract ; subtract to get a difference btfss STATUS,C ; don't update if result was negative goto u2 movf DestL,0 ; move the result to current difference movwf cur_alt ; we always update the altitude ;********** Climing or Falling ************* MOVF cur_alt, 0 ; are we climing? SUBWF max_alt, 0 ; if cur_alt > max_alt then UPDATE max_alt BTFSC STATUS, C GOTO u1 MOVF cur_alt, 0 MOVWF max_alt Beep 0x30,0x03 u1: movf max_alt, 0 ; are we falling SUBWF cur_alt, 0 ; if cur_alt < (max_alt-1) then call deploy BTFSC STATUS, C GOTO u2 Beep 0xf0,0x01 call deploy u2: return ;***************************************************************** Subtract ; a 16 bit subtraction sub program. Dest - Source. Result in Dest ; will return a STATUS,0=1 if a negative result is produced. ; the high order byte is in "H" the low order byte is in "L" movf SourceL,W subwf DestL,1 movf SourceH,W btfss STATUS,C incfsz SourceH,W subwf DestH,1 return ;************************************************************************* Low_ ; this binks the LED on/off to show we are ready bcf INTCON,2 ; clear the interupt bit from the timer overflow bsf GPIO,4 ; turn on LED clrf TMR0 ; reset timer 1 movlw 0x01 ; used to turn LED on for 1 TMR0 overflow movwf count call ShortDelay ; delay 256*256 clock cycles bcf GPIO,4 ; turn LED off movlw 0x01 movwf count call ShortDelay ; delay 256*256 clock cycles return ;************************************************************************* Low2_ ; this routine turns on LED for outputing altitude bcf INTCON,2 ; clear the interupt bit from the timer overflow bsf GPIO,4 ; turn on LED clrf TMR0 ; reset timer 1 movlw 0x08 ; used to turn LED on for 8 TMR0 overflows movwf count call ShortDelay ; delay 256*256 clock cycles bcf GPIO,4 ; turn LED on pin 3 off movlw 0x03 movwf count call ShortDelay ; delay 256*256 clock cycles return ;*************************************************************** ShortDelay ;pauses until TMR0 over flows btfss INTCON,2 ; timer 0 overflow interup flag goto ShortDelay bcf INTCON,2 decfsz count,1 goto ShortDelay bcf INTCON,2 return ;*************************************************************** BCD ; convert number in q_2 and q_1 converts ; to 5 digit BCD number contained in ; registers TenK, Thou, Hund, Tens, Ones swapf q_2,w andlw b'00001111' addlw b'11110000' movwf Thou addwf Thou,f addlw b'11100010' movwf Hund addlw b'00110010' movwf Ones movf q_2,w andlw b'00001111' addwf Hund,f addwf Hund,f addwf Ones,f addlw b'11101001' movwf Tens addwf Tens,f addwf Tens,f swapf q_1,w andlw b'00001111' addwf Tens,f addwf Ones,f rlf Tens,f rlf Ones,f comf Ones,f rlf Ones,f movf q_1,w andlw b'00001111' addwf Ones,f rlf Thou,f movlw b'00000111' movwf TenK movlw b'00001010' Lb1 addwf Ones,f decf Tens,f btfss STATUS,0 goto Lb1 Lb2 addwf Tens,f decf Hund,f btfss STATUS,0 goto Lb2 Lb3 addwf Hund,f decf Thou,f btfss STATUS,0 goto Lb3 Lb4 addwf Thou,f decf TenK,f btfss STATUS,0 goto Lb4 return ;*************************************************************** Output_Alt ; Beeps to count out the ; contents of Thou Hund Tens and Ones registers movlw 0x10 ; used to wait for 16 TMR0 overflows movwf count call ShortDelay incf TenK,f decfsz TenK,f call beepTenK call Low2_ incf Thou,f decfsz Thou,f goto o1 ; goto beepThou Beep 0xff,0x0f ; turn on beeper to sound a Zero Beep 0x01,0x06 ; silent beep goto o2 ; we beeped a zero, so jump to Low2_ o1: call beepThou o2: call Low2_ incf Hund,f decfsz Hund,f goto o3 ; goto beepHun Beep 0xff,0x0f ; turn on beeper to sound a Zero Beep 0x01,0x06 ; silent beep goto o4 ; we beeped a zero, so jump to Low2_ o3: call beepHun o4: call Low2_ incf Tens,f decfsz Tens,f goto o5 ; goto beepTen Beep 0xff,0x0f ; turn on beeper to sound a Zero Beep 0x01,0x06 ; silent beep goto o6 ; we beeped a zero, so jump to Low2_ o5: call beepTen o6: call Low2_ ; the factor moves the decimal point over one_ ; so we skip the ones digit movlw 0x20 ; used to wait for 32 TMR0 overflows movwf count call ShortDelay return ;******* Beep the output *********** beepTenK ; Ten K is actually Thousands Beep 0xb0,0x03 ; turn on beeper with freq and duration Beep 0x01,0x04 ; silent beep decfsz TenK,f goto beepTenK return beepThou Beep 0x80,0x03 ; turn on beeper Beep 0x01,0x04 ; silent beep decfsz Thou,f goto beepThou return beepHun Beep 0xb0,0x03 ; turn on beeper Beep 0x01,0x04 ; silent beep decfsz Hund,f goto beepHun return beepTen Beep 0x80,0x03 ; turn on beeper Beep 0x01,0x04 ; silent beep decfsz Tens,f goto beepTen return ;*************************************************************** ;****************** Deploy the chute! ***************** ;****************** warning: ****************** ;** Altitude must reach at least 60 feet to deploy chute ** ;*************************************************************** deploy: BTFSC deployed,0 ; if we have already deployed skip ahead GOTO nogo MOVLW 2 ; if cur_alt < 2 then goto nogo BCF STATUS, RP1 BCF STATUS, RP0 SUBWF cur_alt, 0 BTFSS STATUS, C GOTO nogo bsf GPIO,5 ; Deploy the chute!!!!!!!!!! clrf TMR0 ; reset timer 1 movlw 0x0F ; used to turn output on for F TMR0 overflows movwf count call ShortDelay ; delay 256*256 clock cycles bcf GPIO,5 bsf deployed,0 nogo: ; ****************************************************************** ; * We have deployed the chute and now we are going to transmit * ; * the height of travel once we get below 90 feet. This will * ; * also act as an audible tracker if it falls in high weeds * ; ****************************************************************** ready_to_xmit: BTFSS deployed,0 ; if we have not already deployed skip ahead GOTO end_of_sub MOVLW 3 ; if cur_alt < 3 then call transmit SUBWF cur_alt, 0 BTFSC STATUS, C GOTO end_of_sub call transmit end_of_sub: return ;*************************************************************** ;*************** Transmit the Altitude **************** ;*************************************************************** transmit ; transmits the height by beeping movf max_alt, 0 movwf n_1 CLRF n_2 call FactorSub ; get the factor to multiply by MOVF factor, 0 MOVWF n_3 MOVF factor2, 0 MOVWF n_4 mpy16b16 ; macro for multiplying call BCD call Output_Alt goto $-2 ; this is an endless loop return ;*************************************************************** ;***** changes the factor for log curve ***** ;***** The pressure readings are not linear, so a factor ***** ;***** is used to correct for the curve. I have not ***** ;***** adjusted for anything over 1240 feet. ***** ;***** Each reading increment is approximately 31 feet ***** ;*************************************************************** FactorSub ; BCF STATUS, RP1 BCF STATUS, RP0 MOVLW .50 ; factor = 306 MOVWF factor MOVLW .1 MOVWF factor2 ; if max_alt <= 21 then MOVF max_alt, 0 SUBLW .21 BTFSS STATUS, C GOTO F2 F1: ; factor = 306 MOVLW .50 MOVWF factor MOVLW .1 MOVWF factor2 GOTO factor_end F2: ;end if F3: ;if max_alt <= 31 then MOVF max_alt, 0 SUBLW .31 BTFSS STATUS, C GOTO F5 F4: ;factor = 307 MOVLW .51 MOVWF factor MOVLW .1 MOVWF factor2 GOTO factor_end F5: ;end if F6: ;if max_alt <= 40 then MOVF max_alt, 0 SUBLW .40 BTFSS STATUS, C GOTO F8 F7: ;factor = 308 MOVLW .52 MOVWF factor MOVLW .1 MOVWF factor2 GOTO factor_end F8: ;end if F9: ;if max_alt is > 40 WOW, thats high! ; then factor = 309 MOVLW .53 MOVWF factor MOVLW .1 MOVWF factor2 factor_end: return ; That's all folks END