;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;Clino876.ASM Latest mod - 20/03/2008 ; ; ; ;Software for Inclinometer using ADXL202 accelerometer ; ;with laser pointer and LED display ; ; ; ; This version is for the PIC16F876 ; ; ; ; © Ian Todd 2001-2007 ; ; ; ;This software is for Clino hardware Version 2.0 ; ; ; ;arcsine LUT in PIC prog memory ; ; ; ;calibration values of K2 and K3 from calib routine are ; ;stored in PIC eeprom ; ;Calculates temperature corrected K2&K3 from calibration data ; ;in the PIC eeprom acquired at two different temperatures ; ;by the calibration routine. This now works correctly for ; ;temperatures below the cold calibration temperature 10/03/08 ; ; ; ;Uses PIC to directly drive individual LED segments ; ;uses PIC ccp1 to measure input from ADXL. ; ; ; ;Uses interrupt driven detection of key state ; ; ; ;works in tenth degrees ; ; ; ;display inverted when doing down measurement for ease of ; ;reading ; ; ; ; A/D converter now measures battery input voltage. ; ; At 7.5 volts the bottom segment of the leftmost 7 segment ; ; display will flash but the clino can still be used. ; ; At 7 volts the display will read FLAt and the clino will ; ; become inoperative ; ; ; ; The power shorting link powers the device continuously for ; ; programming or to enable the calibrate mode ; ; ; ;The correction "Corr" routine is now more user friendly ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; LIST P=PIC16F876 LIST n=1024 ;stops pagination of listing LIST f=INHX8M ;hex file output format #INCLUDE errorlevel +302 ;enables bank switch warning title "" ;suppresses page header radix dec ;use decimal numbers by default ;********************************************************************** ;Macros BANK0 macro bcf STATUS, RP0 ;Select bank 0 registers bcf STATUS, RP1 errorlevel +302 ;enables bank switch warning endm BANK1 macro bsf STATUS, RP0 ;Select bank 1 registers bcf STATUS, RP1 errorlevel -302 ;hides bank switch warning endm BANK2 macro bcf STATUS, RP0 ;Select bank 1 registers bsf STATUS, RP1 errorlevel -302 ;hides bank switch warning endm BANK3 macro bsf STATUS, RP0 ;Select bank 1 registers bsf STATUS, RP1 errorlevel -302 ;hides bank switch warning endm PAGE0 macro bcf PCLATH,4 ; Select page 0 bcf PCLATH,3 endm PAGE1 macro bcf PCLATH,4 ; Select page 1 bsf PCLATH,3 endm PAGE2 macro bsf PCLATH,4 ; Select page 2 bcf PCLATH,3 endm PAGE3 macro bsf PCLATH,4 ; Select page 3 bsf PCLATH,3 endm dis_i macro ;disable interrupts bcf INTCON,GIE btfsc INTCON,GIE goto $-2 endm en_i macro ;enable interrupts bsf INTCON,GIE endm ;********************************************************************** __CONFIG _LVP_OFF & _PWRTE_ON & _WDT_OFF & _XT_OSC ;low voltage programming off ;power up timer on ;watchdog timer off ;crystal oscillator __idlocs 0xC0DC ;Puts C0DC in the ID locs of the PIC ;********************************************************************** ; Start of BANK0 0x20 cblock 0x20 ;---------------------------------------------------------------------- ;registers used by interrupt routines i_fsr i_pclath i_count, i_count2,i_count3,i_count4 i_portdig i_st:2 i_fin:2 i_temp:2 i_Ttot:6 i_T:4 i_delay0, i_delay10, i_delay11 i_know, i_kprev, i_kdeb, i_kprevd ;---------------------------------------------------------------------- Tcal:8 disp:8 ;LED display digits dat1:2 Count1 Divisor Temp0,Temp1,Temp2 corrL,corrH ;minor signed correction value x10 tmpstor,tmpstor2 count ;serial bit counter tmp_FSR b_low stop0 ;keep as last entry, detects overflow endc ;---------------------------------------------- cblock h'70' ;common block shared across all 4 banks foricd ;reserved for icd use w_temp ;Copy of W during interrupt status_temp ;copy of STATUS during interrupt bcount ;bit or byte counter flag ;bits used as flags ;bit 0 = steep ;bit 1 = sign, set is positive ;bit 2 = set, invert display ;bit 3 = set, first result (discard) ;bit 4 =set, if A/D detects low voltage addr:2 ;program/data memory address i_kpres i_krel stop_com ;keep as last entry, detects overflow endc i_T1L equ i_T i_T1H equ i_T+1 i_T2L equ i_T+2 i_T2H equ i_T+3 i_stL equ i_st i_stH equ i_st+1 i_finL equ i_fin i_finH equ i_fin+1 i_T1totL equ i_Ttot i_T1totH equ i_Ttot+1 i_T1totU equ i_Ttot+2 i_T2totL equ i_Ttot+3 i_T2totH equ i_Ttot+4 i_T2totU equ i_Ttot+5 i_tempL equ i_temp i_tempH equ i_temp+1 Tmax equ Tcal T2_cal equ Tcal+2 Tmin equ Tcal+4 T2_cal2 equ Tcal+6 dig0 equ disp ;buffer for LED display digits dig1 equ disp+1 ;dig3 is msd, dig0 is lsd dig2 equ disp+2 dig3 equ disp+3 tdig0 equ disp+4 ;temporary digit store tdig1 equ disp+5 ;to prevent display flickering tdig2 equ disp+6 ;during calculation tdig3 equ disp+7 dataL equ dat1 dataH equ dat1+1 addrL equ addr addrH equ addr+1 c_count equ stop0 ; End of BANK0 0x7F if stop0 >=0x70 ;check the cblock hasn't overrun error "BANK0 cblock too big" endif if stop_com >0x7F ;check the common area hasn't overrun error "Too many entries in common area 0x70-0x7F" endif ;--------------------------------------------------------------------------- ; Start of BANK1 0xA0 cblock h'A0' cold:6 hot:6 K2:2 K3:2 T2_index:2 K2_range:2 K3_range:2 T2_range:2 T1andT2:4 ;T1 and T2 dividend:6 stop1 ;keep as last entry, detects overflow endc T2_coldL equ cold T2_coldH equ cold+1 K2_coldL equ cold+2 K2_coldH equ cold+3 K3_coldL equ cold+4 K3_coldH equ cold+5 T2_hotL equ hot T2_hotH equ hot+1 K2_hotL equ hot+2 K2_hotH equ hot+3 K3_hotL equ hot+4 K3_hotH equ hot+5 T2_indL equ T2_index T2_indH equ T2_index+1 K2L equ K2 K2H equ K2+1 K3L equ K3 K3H equ K3+1 K2_rangeL equ K2_range K2_rangeH equ K2_range+1 K3_rangeL equ K3_range K3_rangeH equ K3_range+1 T2_rangeL equ T2_range T2_rangeH equ T2_range+1 T1Lo equ T1andT2 T1Hi equ T1andT2+1 T2Lo equ T1andT2+2 T2Hi equ T1andT2+3 factor0 equ dividend factor1 equ dividend+1 factor2 equ dividend+2 factor3 equ dividend+3 factor4 equ dividend+4 factor5 equ dividend+5 divisorL equ dividend+4 divisorH equ dividend+5 ; End of BANK1 0xEF if stop1 >=0xEF ;check the cblock hasn't overrun error "BANK1 cblock too big" endif ;-------------------------------------------------------------------------------- ; Start of BANK2 0x110 cblock h'110' stop2 ;keep as last entry, detects overflow endc ; End of BANK2 0x16F if stop2 >=0x16F ;check the cblock hasn't overrun error "BANK2 cblock too big" endif ;---------------------------------------------------------------------- ; Start of BANK3 0x190 cblock h'190' stop3 ;keep as last entry, detects overflow endc ; End of BANK3 0x1EF ; last 5 locations used by Trevor's debbugger ; last 10 locations used by microchip debugger tho they don't say so if stop3 >=0x1E5 ;check the cblock hasn't overrun error "BANK3 cblock too big. 0x1E5-0x1Ef used by debugger" error "0x1e5-0x1e9 can be used if using Trevor's debugger" endif ;---------------------------------------------------------------------- ; These two are Special Function Registers reserved for the Debugger cblock 0x18e ickbug, bigbug endc ; ;---------------------------------------------------------------------- LASER equ PORTC POWER equ PORTC TRIGGER equ PORTA pwr equ 0 gate equ 1 ; Control line to laser switch adxl_cap equ 3 push equ 4 ; Trigger Switch rot equ 6 ;power of 2 of readings readings equ 1< ;segment patterns for LED chars #INCLUDE ;intcon setup equates #INCLUDE ;ccp1 setup equates #INCLUDE ;Option Register options list ;---------------------------------------------------------------------- opt_val equ rbpu_d | wp_128 |inte_n | t0cs_i ;portb pullups off. ;prescaler assigned to watchdog ;so is therefore disabled. ;External interrupt edge negative. ;Timer0 uses internal source. ;********************************************************************** org H'2100' ;Beginning of pic internal eeprom. ;Temporary look up table ;These values will be overwritten in the PIC by real calibrations ;lookup table in pic eeprom of T2, K2 and K3 at low and high temperatures ; de low 6805 ;T2_coldL de high 6805 ;T2_coldH de low 7491 ;K2_coldL de high 7491 ;K2_coldH de low 1507 ;K3_coldL de high 1507 ;K3_coldH de low 7363 ;T2_hotL de high 7363 ;T2_hotH de low 7991 ;K2_hotL de high 7991 ;K2_hotH de low 1661 ;K3_hotL de high 1661 ;K3_hotH de 0 ;default value of corrL ;0.0 degrees of correction ;********************************************************************** ;RESET ORG 0x0000 ;reset vector nop ;nop required for debugger goto START ;Skip around interrupt ;********************************************************************** ;********************************************************************** ;INTERRUPT ROUTINE ORG 0x0004 ;interrupt vector movwf w_temp ;copy W to a register in common area swapf STATUS,W ;swap STATUS and place into W movwf status_temp ;save STATUS to a temporary register BANK0 ;interrupts to work in BANK0 movf FSR,w movwf i_fsr movf PCLATH,w movwf i_pclath ;---------------------------------------------------------------------- ;Identify source of interrupt btfsc PIR1,CCP1IF ;was interrupt by ccp1 ? goto ccp btfsc INTCON,TMR0IF ;was interrupt by timer0 ? goto timer0 btfsc PIR1,TMR1IF ;was interrupt by timer1 ? goto timer1 btfsc PIR1,ADIF ;was interrupt by A/D ? goto AtoD ; movlw b'11100000' ;clear other interrupts and flags ; andwf INTCON,f movlw 1<| | ;0v _______| |____________| ; <------------------T2-------------> ; ; The averaged values of T1 and T2 are continuously retrieved by the ccp1 ; interrupt routine. ; This acquires 16 bit T1 and T2 from the ADXL202 (in usecs) ; Values are read 'readings' times and then averaged to reduce noise ; T1 is in registers i_T1Hi, i_T1Lo ; and T2 is in registers i_T2Hi, i_T2Lo ; Interrupts should be turned off while copying the values from the ; Interrupt registers. ;_____________________________________________________________________ ; org 0x100 ;256 byte boundary(PCL memory boundary) ;_____________________________________________________________________ ; nop ;********************************************************************** calcaccel ;Returns acceleration value to look up ;in dataH:dataL ;calcaccel works in Bank1 movlw T1Lo movwf FSR dis_i ;turn off interrupts and copy movf i_T1L,w ;T1 and T2 from interrupt registers movwf INDF ;in bank0 to bank1 incf FSR,f movf i_T1H,w movwf INDF incf FSR,f movf i_T2L,w movwf INDF incf FSR,f movf i_T2H,w movwf INDF en_i ;enable interrupts BANK1 ;The current values of K2 and K3 must be calculated using the hot and ;cold calibrations of T2, K2 and K3 retrieved from the PIC eeprom ;K2 at current measured value of T2 = ; (K2_hot - K2_cold) * (T2 - T2cold) ; K2_cold + ( ------------------- ) ; (T2_hot - T2cold) BANK1 movf T2_coldL,w ;T2_hot - T2_cold = T2_range subwf T2_hotL,w ;preserving T2_hot and T2_cold movwf T2_rangeL movf T2_coldH,w btfss STATUS,C incf T2_coldH,w subwf T2_hotH,w movwf T2_rangeH ; =T2_range movf T2_coldL,w ;T2 - T2_cold = T2_index subwf T2Lo,w ;preserving T2 and T2_cold movwf T2_indL movf T2_coldH,w btfss STATUS,C incf T2_coldH,w subwf T2Hi,w movwf T2_indH ;=T2_index can be negative ! ;if T2= 0x7xx goto lkup movlw 0xbb subwf addrL,w btfss STATUS,C ;dont lookup if address >= 0x7bb goto lkup bsf flag,steep ;reading too steep to be useful retlw 0 lkup movlw HIGH lut_st ;Add offset to start address of LUT addwf addrH,F ;in program memory(0x700) call p_read ;read program memory ex_lookup ;result in dataL and dataH retlw 0 ;____________________________________________________________________ org 0x300 ;256 byte boundary(PCL memory boundary) ;____________________________________________________________________ ; nop ;********************************************************************** convert btfsc flag,flat_v ;abort if battery is flat goto flat btfsc flag,steep goto over_range ;angle too steep to display call make_LED_digits ;binary to ASCII movlw chr_minus ;data for '-' sign btfsc flag, plus ;is it positive? movlw chr_blank ;data for blank digit movwf tdig0 ;put sign or blank in dig0 register movlw chr_0 ;if leading zero in dig1, then subwf tdig1,w ;put sign in it, and blank normal movlw chr_blank ;sign character (dig0) btfss STATUS,Z goto dec_pt movwf tdig0 movlw chr_minus ;data for '-' sign btfsc flag, plus ;is it negative? movlw chr_blank ;data for blank digit movwf tdig1 dec_pt movlw seg_dp iorwf tdig2,f ;set decimal point btfss flag,low_v goto load movlw seg_d ;light segment d of first LED xorwf b_low,f ;if battery voltage is getting low movf b_low,w iorwf tdig0,f load movf tdig0,w movwf dig0 movf tdig1,w movwf dig1 movf tdig2,w movwf dig2 movf tdig3,w movwf dig3 retlw 0 over_range bcf flag,steep movlw m_tilt-m_start call show ex_convert retlw 0 ;---------------------------------------------------------------------- flat movlw chr_F ;load display with "FLAt" movwf dig0 movlw chr_L movwf dig1 movlw chr_A movwf dig2 movlw chr_t movwf dig3 ; REMOVE POWER FROM PIC, turns everything off. Zero battery drain btfss i_kpres,push goto $-1 bcf POWER,pwr here goto here ;====================================================================== ;;make_LED_digits Enter with 16 bit integer number in dataH:dataL ; This is converted to decimal number for display ; then dataH:dataL/d'10' leaving remainder in tdig3 ; then dataH:dataL/d'10' leaving remainder in tdig2 ; then dataH:dataL/d'10' leaving remainder in tdig1 ; then dataH:dataL/d'10' leaving remainder in tdig0 ; changed to preserve FSR 24/04/07 iet ; changed for 876 4digit display 04/07/07 make_LED_digits clrf tmpstor ;clear registers we'll use clrf tmpstor2 clrf Divisor movf FSR,w movwf tmp_FSR movlw 4 movwf tmpstor movlw tdig0-1 btfss flag,invert ;invert set if display needs inverting movlw tdig3+1 movwf FSR movlw 10 movwf Divisor nxt_digit movlw 1 ;increment FSR if writing right to left btfss flag,invert ;ie inverted movlw -1 ;decrement FSR if writing left to right addwf FSR,F ;ie right way up movlw 16 movwf tmpstor2 clrf INDF nextbit bcf STATUS,C rlf dataL,F rlf dataH,F rlf INDF,F btfsc STATUS,C ;if C set then we can definitely do goto subtract_it ;a subtract test_sub movf Divisor,W ;do a test subtract first to check subwf INDF,W ;it will 'go' btfss STATUS,C goto Chek_cnt subtract_it movf Divisor,W ;real subtract as remain>DIV subwf INDF,F st_lsb bsf dataL,0 ;set LSB of dataL Chek_cnt decfsz tmpstor2,F ;have we done all 16 bits yet? goto nextbit ;no, so do another movlw HIGH bcd_seg movwf PCLATH movf INDF,w btfsc flag,invert addlw 16 ;move up table by 16 to access call bcd_seg ;inverted characters movwf INDF decfsz tmpstor,F goto nxt_digit stopit clrf tmpstor ;clear registers we used clrf tmpstor2 clrf Divisor movf tmp_FSR,w movwf FSR ;reinstate FSR ex_make_LED_digits retlw 0 ;---------------------------------------------------------------------- ;show displays messages with '&' as the terminating character. ;---------------------------------------------------------------------- ;Enter with start position (message beginning), in w show movwf Temp0 ;Temp0=current location movf FSR,w movwf tmp_FSR ;keep copy of FSR to reinstate movlw dig0 movwf FSR movlw high message movwf PCLATH movf Temp0,w nxt_ch movwf Temp0 call message movwf Temp1 xorlw "&" ;check for message end btfsc STATUS,Z goto show_e movf Temp1,W ;restore character movwf INDF movf Temp0,w addlw 1 ;next character incf FSR,f goto nxt_ch show_e movf tmp_FSR,w ;reinstate FSR movwf FSR ex_show return ;---------------------------------------------------------------------- ; ***** DON'T FORGET TO SET PCLATH BEFORE CALLING "message". message addwf PCL,F ;jump to correct start point m_start m_CAL DT chr_C,chr_A,chr_L,chr_blank,"&" m_Cold DT chr_C,chr_o,chr_l,chr_d,"&" m_Hot DT chr_H,chr_o,chr_t,chr_blank,"&" m_UP DT chr_U,chr_P,chr_blank,chr_blank,"&" m_dn DT chr_d,chr_n,chr_blank,chr_blank,"&" m_done DT chr_d,chr_o,chr_n,chr_E,"&" m_turn DT chr_t,chr_u,chr_r,chr_n,"&" m_tilt DT chr_t,chr_i,chr_l,chr_t,"&" m_Corr DT chr_C,chr_o,chr_r,chr_r,"&" m_nul DT chr_n,chr_u,chr_l,chr_blank,"&" m_Add DT chr_A,chr_d,chr_d,chr_blank,"&" m_Sub DT chr_S,chr_u,chr_b,chr_blank,"&" m_BLANK DT chr_blank,chr_blank,chr_blank,chr_blank,"&" m_End DT chr_E,chr_n,chr_d,chr_quest,"&" ;---------------------------------------------------------------------- ; Subroutine to return the segment pattern for the hex digit passed in ; the low nibble of W register. ; ***** DON'T FORGET TO SET PCLATH BEFORE CALLING "bcd_seg". bcd_seg andlw b'00011111' addwf PCL,f retlw chr_0 retlw chr_1 retlw chr_2 retlw chr_3 retlw chr_4 retlw chr_5 retlw chr_6 retlw chr_7 retlw chr_8 retlw chr_9 retlw chr_A retlw chr_b retlw chr_C retlw chr_d retlw chr_E retlw chr_F ; definitions of inverted characters retlw chr_0i retlw chr_1i retlw chr_2i retlw chr_3i retlw chr_4i retlw chr_5i retlw chr_6i retlw chr_7i retlw chr_8i retlw chr_9i ;_____________________________________________________________________ org 0x400 ;256 byte boundary(PCL memory boundary) ;_____________________________________________________________________ ; nop ;====================================================================== ;p_read reads 2 bytes (14 bit word) from Program memory. ; Location to read in addrH:addrL ; Returned value in dataH:dataL ;---------------------------------------------------------------------- p_read movf addrH, W BANK2 ;Select Bank of EEADRH movwf EEADRH ;MSByte of Program address to read BANK0 movf addrL, W BANK2 movwf EEADR ;LSByte of Program address to read BANK3 ;Select Bank of EECON1 bsf EECON1, EEPGD ;Point to PROGRAM memory bsf EECON1, RD ;EE Read nop nop BANK2 ;Select Bank of EEDATA movf EEDATA, W BANK0 movwf dataL BANK2 movf EEDATH, W BANK0 movwf dataH ex_p_read return ;---------------------------------------------------------------------- ;d_read Reads bytes of PIC data memory (eeprom). ; Enter with first address to read in addrL. ; Number of bytes to read in w. ; Bytes are written into INDF ;---------------------------------------------------------------------- d_read BANK0 movwf Count1 nextb movf addrL,w BANK2 ;Select Bank of EEADR movwf EEADR ;Data Memory Address to read BANK3 ;Select Bank of EECON1 bcf EECON1, EEPGD ;Point to Data memory bsf EECON1, RD ;EE Read BANK2 ;Select Bank of EEDATA movf EEDATA, w BANK0 movwf INDF incf FSR, F incf addrL, F decfsz Count1,F goto nextb ex_d_read return ;---------------------------------------------------------------------- ; writes a byte to PIC eeprom ;------------------------------------------------------------------------- d_write BANK2 movwf EEDATA ;data to write movf addrL,w ;addrL in common memory area movwf EEADR ;address to write to BANK3 bcf EECON1, EEPGD ;point to Data memory bsf EECON1, WREN ;enable writes movlw 0x55 ;write 0x55 to EECON2 movwf EECON2 movlw 0xAA ;Write 0xAA to EECON2 movwf EECON2 bsf EECON1, WR ;start write operation bcf EECON1, WREN ;disable writes btfsc EECON1, WR ;wait for write to finish goto $-1 BANK0 ex_d_write return ;---------------------------------------------------------------------- ;mul16x16 factor5:factor4 x factor1:factor0 ; = factor3:factor2:factor1:factor0 iet ; This works in BANK1 ;---------------------------------------------------------------------- mul16x16 BANK1 movlw 16 movwf bcount ;loop counter clrf factor3 clrf factor2 mult bcf STATUS,C ;clr carry before next rrf btfss factor0,0 ;do add if LSB=1 goto nxt_bit movf factor4,W ;add factor5:factor4 to addwf factor2,F ;factor3:factor2 movf factor5,W btfsc STATUS,C incfsz factor5,W addwf factor3,F ;carry may be set here nxt_bit rrf factor3,F ;roll result registers right rrf factor2,F rrf factor1,F rrf factor0,F decfsz bcount,F ;have we done 16 bits? goto mult BANK0 ex_mul16x16 return ;====================================================================== ;This is a 32-bit x 16-bit routine by T.Woolvin ;====================================================================== ; This works in BANK1 but resets to BANK0 on exit ; Dividend = dividend (3-0) ; Divisor = divisorH:DivisorL ; Quotient = dividend[1-0] ; Remainder = dividend[3-2] ; Check to see if the result will fit into 16-bits. div32x16 BANK1 movf divisorL,w ;See if divisor is bigger subwf dividend+2,w ;than the dividend[3-2]. movf divisorH,w btfss STATUS,C incfsz divisorH,w subwf dividend+3,w btfss STATUS,C goto div_do ;Divisor > dividend[3-2] so ;quotient will fit. movlw h'ff' ;Force invalid value into result then exit. movwf dividend movwf dividend+1 goto ex_div32x16 div_do movlw 16 movwf bcount div_lp bcf STATUS,C rlf dividend,f rlf dividend+1,f rlf dividend+2,f rlf dividend+3,f btfsc STATUS,C goto div_sub ;A '1' popped out of the top, ;always do subtract. movf divisorL,w ;See if the divisor is bigger subwf dividend+2,w ;than the dividend. movf divisorH,w btfss STATUS,C incfsz divisorH,w subwf dividend+3,w btfss STATUS,C goto div_nxt ;Divisor > dividend, skip the subtract div_sub movf divisorL,w ;Divisor <= dividend, do the subtract subwf dividend+2,f movf divisorH,w btfss STATUS,C incfsz divisorH,w subwf dividend+3,f incf dividend,f ;Did the subtract, put a '1' in ;the quotient bottom. div_nxt decfsz bcount,f goto div_lp ex_div32x16 BANK0 retlw 0 ;---------------------------------------------------------------------- finetune ;12/02/07 Once the laser has been mechanically ;set to be horiz, when the adlx202 ;reads horiz, any residual error can ;then be corrected in software here. ;Take dataH:dataL and add (subtract) corr movlw 0xFF ;expand to 16 bits movwf corrH btfss corrL,7 clrf corrH ;corrH:corrL now holds 16 bit signed ;correction x10 btfsc flag,plus ;skip if dataH:dataL neg (flag,1 clear) goto pos neg comf dataL,F ;as it's negative, 2's complement it comf dataH,F movlw 1 addwf dataL,F btfsc STATUS,C incf dataH,F pos ;dataH:dataL now holds signed value movf corrL,W addwf dataL,F movf corrH,w btfsc STATUS,C incf dataH,F addwf dataH,F bsf flag,plus btfss dataH,7 ;test sign bit goto ex_finetune ;result is positive so return bcf flag,plus ;result is negative so clear flag,plus comf dataL,F ;2's complement as display routine comf dataH,F ;expects positive number with flag,plus movlw 1 ;indicating sign (set=positive) addwf dataL,F btfsc STATUS,C incf dataH,F ex_finetune retlw 0 ;_____________________________________________________________________ org 0x500 ;256 byte boundary(PCL memory boundary) ;_____________________________________________________________________ ; nop ;====================================================================== ;CALIBRATION routine: acquires K2,K3,T2 at 2 different temperatures. ;and allows correction of minor alignment errors between ;laser and ADXL202 iet 29/04/2007 ;====================================================================== calib movlw m_CAL-m_start ;display says 'CAL' call show movlw secs2 ;delay needed for key debounce movwf i_delay10 ;interrupt routine to get set up tstf i_delay10 btfss STATUS,Z goto $-2 btfss i_kpres,push ;display 'CAL' until key pushed goto $-1 clrf i_krel clrf i_kpres ;---------------------------------------------------------------------- clrf c_count ;start with c-count set to zero movlw high caltab movwf PCLATH movf c_count,w round call caltab ;message retrieved from the call show ;calibrate table depends on the value movlw secs2 ;of c_count movwf i_delay11 movlw high caltab movwf PCLATH movf c_count,w addlw 4 btfsc i_kpres,push call caltab ;decide where to jump based on the tstf i_delay11 ;value of c_count btfss STATUS,Z goto $-4 incf c_count,w ;delay has expired so increment c_count andlw b'00000011' ;make it stay within range 0-3 movwf c_count goto round ;---------------------------------------------------------------------- ; DON'T FORGET TO SET PCLATH BEFORE CALLING "caltab". caltab addwf PCL,f retlw m_Cold-m_start retlw m_Hot-m_start retlw m_Corr-m_start retlw m_End-m_start goto cal_c goto cal_h goto cal_adj goto ex_cal ;---------------------------------------------------------------------- cal_c ;calibrate at low temperature movlw 0 ;cold readings start at addr0 in eeprom movwf addrL goto getcal cal_h ;calibrate at high temperature movlw 6 ;hot readings start at addr6 in eeprom movwf addrL goto getcal cal_adj movlw ad_corr ;get signed correction byte from eeprom movwf addrL ;and put in corrL movlw corrL movwf FSR movlw 1 call d_read movlw 0 ;clear temporary store for correction movf stop0,w ;value btfss i_krel,push goto $-1 ;keep on displaying "Corr" until clrf i_kpres ;button is pressed clrf i_krel movlw m_nul-m_start ;reset stored correction to zero call show movlw secs2 ;start delay (2secs) movwf i_delay11 btfsc i_kpres,push goto reset ;look for pushed, goto adj tstf i_delay11 btfss STATUS,Z goto $-4 ;if delay expires fall thro to Add movlw m_Add-m_start ;create a correction to Add. call show ;display says 'Add'until push bsf flag,add movlw secs2 ;start delay (2secs) movwf i_delay11 btfsc i_kpres,push goto adj ;look for pushed, goto adj tstf i_delay11 btfss STATUS,Z goto $-4 ;if delay expires fall thro to Sub. movlw m_Sub-m_start ;create a correction to Subtract call show ;display says 'Sub'until push bcf flag,add movlw secs2 ;start delay (2secs) movwf i_delay11 btfsc i_kpres,push goto adj ;look for pushed, goto adj tstf i_delay11 btfss STATUS,Z goto $-4 ;if delay expires goto ex_cal goto ex_cal reset movlw ad_corr ;reset to zero value of correction in movwf addrL ;corrL in PIC eeprom movlw 0 call d_write goto ex_cal ;---------------------------------------------------------------------- adj clrf i_kpres movlw 100 movwf i_delay11 ;timer one delay nokey movlw 0 movwf dataH movf stop0,w movwf dataL bsf flag,plus btfss dataL,7 goto posi bcf flag,plus comf dataL,f ;it's negative, 2's complement movlw 1 ;it, and display with a minus sign addwf dataL,f posi call convert tstf i_delay11 btfsc STATUS,Z goto save_it2 ;delay expired, so save result btfss i_kpres,push goto nokey clrf i_kpres movlw 1 ;increment dataL if it's positive btfss flag,add movlw -1 ;decrement dataL if it's negative addwf stop0,F goto adj ;reset delay and wait for further ;key presses save_it2 movlw ad_corr ;store value of correction in movwf addrL ;corrL in PIC eeprom movf stop0,w ;add new adjustment to old value addwf corrL,w call d_write ex_adj goto ex_cal ;---------------------------------------------------------------------- getcal btfss i_krel,push goto $-1 ;display "Hot" or "Cold" until clrf i_kpres ;button is released clrf i_krel movlw Tmax movwf FSR movlw m_UP-m_start ;display says 'UP'until push call disp1 ;returns Tmax and T2_cal call T1grab movlw Tmin ;point FSR at Tmin movwf FSR bsf flag,invert ;turn number display upside down movlw m_dn-m_start ;display says 'dn'until push call disp1 ;returns Tmin and T2_cal2 call T1grab call saveit ;write T2_cal to eeprom incf addrL,f ;put Tmax+Tmin(K2)in eeprom movf Tmax,w addwf Tmin,w movwf T2_cal ;this register is now spare movf Tmax+1,w btfsc STATUS,C incf Tmax+1,w addwf Tmin+1,w movwf T2_cal+1 call saveit ;write K2 to eeprom incf addrL,f ;put Tmax-Tmin(K3)in eeprom movf Tmin,w subwf Tmax,w movwf T2_cal ;this register is now spare movf Tmin+1,w btfss STATUS,C incf Tmin+1,w subwf Tmax+1,w movwf T2_cal+1 call saveit ;write K3 to eeprom goto ex_cal ;---------------------------------------------------------------------- saveit movf T2_cal,w call d_write incf addrL,f movf T2_cal+1,w call d_write return ;---------------------------------------------------------------------- disp1 clrf i_kpres ;clr previous key actions clrf i_krel call show ;retrieve message characters btfss i_kpres,push goto $-1 ;and wait for key press clrf i_kpres clrf i_krel return ;---------------------------------------------------------------------- T1grab ;display live T1 until button push then ;store T1 and T2 dis_i movf i_T1L,w movwf dataL movf i_T1H,w movwf dataH en_i btfsc flag,flat_v ;abort if battery is flat goto flat call make_LED_digits ;convert hex to decimal number movf tdig0,w movwf dig0 movf tdig1,w movwf dig1 movf tdig2,w movwf dig2 movf tdig3,w movwf dig3 btfss i_kpres,push goto T1grab clrf i_kpres clrf i_krel dis_i movf i_T1L,w ;save T1 value movwf INDF incf FSR,f movf i_T1H,w movwf INDF incf FSR,f movf i_T2L,w ;save T2 value movwf INDF incf FSR,f movf i_T2H,w movwf INDF en_i return ;---------------------------------------------------------------------- ex_cal movlw m_done-m_start ;displays "done" call show movlw 10 movwf i_delay10 tstf i_delay10 btfss STATUS,Z goto $-2 ; REMOVE POWER FROM PIC, turns everything off. Zero battery drain bcf POWER,pwr goto $-1 ;===================================================================== org 0x600 ;256 byte boundary(PCL memory boundary) ;===================================================================== nop ;===================================================================== org 0x700 ;256 byte boundary(PCL memory boundary) ;===================================================================== nop ;===================================================================== org 0x800 ;beginning of PAGE 1 ;===================================================================== ; nop lut_st #INCLUDE ;arcsine lookup table occupies ;all of PAGE 1 ;===================================================================== org 0x900 ;256 byte boundary(PCL memory boundary) ;===================================================================== ; nop ;_____________________________________________________________________ org 0xA00 ;256 byte boundary(PCL memory boundary) ;_____________________________________________________________________ ; nop ;_____________________________________________________________________ org 0xB00 ;256 byte boundary(PCL memory boundary) ;_____________________________________________________________________ ; nop ;_____________________________________________________________________ org 0xC00 ;256 byte boundary(PCL memory boundary) ;_____________________________________________________________________ ; nop ;_____________________________________________________________________ org 0xD00 ;256 byte boundary(PCL memory boundary) ;_____________________________________________________________________ ; nop ;_____________________________________________________________________ org 0xE00 ;256 byte boundary(PCL memory boundary) ;_____________________________________________________________________ ; nop ;_____________________________________________________________________ org 0xF00 ;256 byte boundary(PCL memory boundary) ;_____________________________________________________________________ ; nop ;===================================================================== org 0x1000 ;beginning of PAGE 2 ;===================================================================== nop ;===================================================================== org 0x1800 ;beginning of PAGE 3 ;===================================================================== nop ;_____________________________________________________________________ ;The last 256 bytes at top of memory reserved for the debugger code org 0x1F00 ;256 byte boundary(PCL memory boundary) ;_____________________________________________________________________ errorlevel -302 ;disables bank switch warning END