Mercurial > public > hwos_code
view src/compass_ops.asm @ 623:c40025d8e750
3.03 beta released
author | heinrichsweikamp |
---|---|
date | Mon, 03 Jun 2019 14:01:48 +0200 |
parents | 1ad0531e9078 |
children | cd58f7fc86db |
line wrap: on
line source
;============================================================================= ; ; File compass_ops.asm combined next generation V3.03.2 ; ; Compass Operations ; ; Copyright (c) 2011, JD Gascuel, HeinrichsWeikamp, all right reserved. ;============================================================================= #include "hwos.inc" #include "i2c.inc" #include "tft_outputs.inc" #include "tft.inc" #include "strings.inc" #include "wait.inc" #include "surfmode.inc" #include "divemode.inc" #include "math.inc" #include "convert.inc" IFDEF _compass ; local flags #DEFINE compass_show_cardinal compass_flags,0 ; =1: show the cardinal (N, NE, E, ...) #DEFINE compass_bearing_eq compass_flags,1 ; =1: bearing is in direction, do not show << or >> #DEFINE compass_bearing_lft compass_flags,2 ; =1: bearing is to the left/<<, =0: to the right/>> #DEFINE compass_bearing_vis compass_flags,3 ; =1: bearing is visible (either ahead or behind/-180°) #DEFINE compass_bearing_ahd compass_flags,4 ; =1: bearing is ahead, =0: behind ; compass_flags,5 ; --- unused ; compass_flags,6 ; --- unused ; compass_flags,7 ; --- unused ; Make sure symbols from the .inc are available to the C code: ; filtered data - Compass global compass_DX_f global compass_DY_f global compass_DZ_f ; filtered Data - Accelerometer global accel_DX_f global accel_DY_f global accel_DZ_f ; Calibration Data global compass_CX_f global compass_CY_f global compass_CZ_f ; Temporary Values to pass Q15 Arithmetics around global compass_a global compass_b ; Result global compass_heading_new extern compass extern compass_reset_calibration extern compass_add_calibration extern compass_solve_calibration extern option_save_all compass_ops code ;============================================================================= ;----------------------------------------------------------------------------- ; Filter compass values ; ; Apply linear filtering to input parameters. ; Apply filtering formula: reg_f += (reg - reg_f) / 4 FILTER16 MACRO reg, reg_f movf reg_f+0,W subwf reg+0,W movwf PRODL movf reg_f+1,W subwfb reg+1,W rcall filter_16_common addwf reg_f+0,F movf PRODH,W addwfc reg_f+1,F ENDM filter_16_common: movwf PRODH bcf STATUS,C ; copy sign bit into carry btfsc PRODH,7 bsf STATUS,C rrcf PRODH,F ; 16 bit shift right rrcf PRODL,F bcf STATUS,C ; copy sign bit into carry btfsc PRODH,7 bsf STATUS,C rrcf PRODH,F ; 16 bit shift right rrcf PRODL,W return global compass_filter compass_filter: banksel compass_DX ; select bank common2 FILTER16 compass_DX, compass_DX_f FILTER16 compass_DY, compass_DY_f FILTER16 compass_DZ, compass_DZ_f FILTER16 accel_DX, accel_DX_f FILTER16 accel_DY, accel_DY_f FILTER16 accel_DZ, accel_DZ_f banksel common ; back to bank common return ;----------------------------------------------------------------------------- compass_filter_init: MOVII compass_DX,compass_DX_f MOVII compass_DY,compass_DY_f MOVII compass_DZ,compass_DZ_f MOVII accel_DX,accel_DX_f MOVII accel_DY,accel_DY_f MOVII accel_DZ,accel_DZ_f return ;----------------------------------------------------------------------------- ; Q15 fractional numbers: a * b / 2**16 (UNSIGNED) ; ; Uses 16x16->16 multiply, for positive integers, keeping only the most ; relevant bits. ; ; Used to multiply two Q15 numbers, in the range 0..1, ; represented as 0..32767, that is a / 2**15. ; ; (a/2**15) * (b/2**15) = a*b / 2**30 = (a*b/2**16) / 2**14. ; So to get back a Q15 number, we need a shift-left... global compass_umul ; called from compass.c compass_umul: banksel compass_a ; select bank common2 rcall compass_mul_16 ; The 2x time, by left-shifting inserting the missing bit: compass_mul_2: rlcf compass_r+2,F ; missing bit into carry rlcf compass_r+0,F rlcf compass_r+1,F MOVII compass_r,PROD ; return value into PROD return ; The 16x16-> multiply: compass_mul_16: movf compass_a+1,W ; block ah*bh mulwf compass_b+1 movff PRODL,compass_r+0 ; and copy movff PRODH,compass_r+1 movf compass_a+0,W ; block al*bl mulwf compass_b+0 movff PRODH,compass_r+2 ; into fraction byte movf compass_a+1,W ; block ah*bl mulwf compass_b+0 movf PRODL,W addwf compass_r+2,F ; fraction part to carry movf PRODH,W ; and add16 addwfc compass_r+0,F movlw 0 addwfc compass_r+1,F movf compass_a+0,W ; block al*bh mulwf compass_b+1 movf PRODL,W addwf compass_r+2,F ; fraction part to carry movf PRODH,W ; and add16 addwfc compass_r+0,F movlw 0 addwfc compass_r+1,F return ;----------------------------------------------------------------------------- ; Q15 fractional numbers: a * b / 2**16 (SIGNED) global compass_imul ; called from compass.c compass_imul: banksel compass_a ; select bank common2 rcall compass_mul_16 btfss compass_b+1,7 bra compass_mul_3 movf compass_a+0,W subwf compass_r+0,F movf compass_a+1,W subwfb compass_r+1,F compass_mul_3: btfss compass_a+1,7 bra compass_mul_4 movf compass_b+0,W subwf compass_r+0,F movf compass_b+1,W subwfb compass_r+1,F compass_mul_4: bcf compass_r+1,6 ; copy bit 7 to 6, so keep it after 2x btfsc compass_r+1,7 bsf compass_r+1,6 bra compass_mul_2 global compass_calibration_loop compass_calibration_loop: ; compass calibration bsf block_sensor_interrupt ; disable sensor interrupts call I2C_sleep_accelerometer ; stop accelerometer call I2C_sleep_compass ; stop compass call TFT_ClearScreen ; Mask WIN_COLOR color_greenish WIN_SMALL .16,.0 STRCPY_TEXT_PRINT tCompassMenu btfss switch_right2 ; wait until button is released bra $-2 call TFT_standard_color ; WIN_SMALL .0,.215 ; STRCPY_TEXT_PRINT tExit WAITMS d'255' WAITMS d'255' call request_speed_fastest ; request CPU speed change to fastest speed movlw .7 ; initialize gain movff WREG,opt_compass_gain movlw .60 ; initialize timeout to 60 seconds movwf isr_timeout_reload ; copy WREG to isr_timeout_reload bsf reset_timeout ; request ISR to reset the timeout bcf trigger_timeout ; clear any pending timeout trigger compass_calibration_gainset: ; reduce the gain, set bank here! banksel opt_compass_gain ; select bank options table decf opt_compass_gain,F ; reduce by one btfsc STATUS,N ; < 0 ? clrf opt_compass_gain ; YES - keep at zero banksel common ; bank to bank common call I2C_init_accelerometer call I2C_init_compass ; btfsc compass_type ; compass1 ? ; bra compass_calibration_loop1 ; YES - skip gain stuff rcall TFT_compass_show_gain ; show the current compass gain WAITMS d'250' WAITMS d'250' ; wait for first reading... movlw .60 ; calibration shall run for 60 seconds call reset_timeout_time ; set timeout call I2C_RX_compass ; read compass call I2C_RX_accelerometer ; read accelerometer ; Test all axes for +4096 (Hi byte=16) banksel compass_DX ; select bank common2 movlw .16 cpfseq compass_DX+1 bra $+4 bra compass_calibration_gainset cpfseq compass_DY+1 bra $+4 bra compass_calibration_gainset cpfseq compass_DZ+1 bra $+4 bra compass_calibration_gainset ; Test all axes for -4096 (Hi byte=240) movlw .240 cpfseq compass_DX+1 bra $+4 bra compass_calibration_gainset cpfseq compass_DY+1 bra $+4 bra compass_calibration_gainset cpfseq compass_DZ+1 bra $+4 bra compass_calibration_gainset banksel common ; back to bank common compass_calibration_loop1: ; done with gain rcall compass_filter_init ; set DX_f values call compass_reset_calibration ; reset CX_f values (C-code) banksel common ; back to bank common compass_calibration_loop2: call I2C_RX_compass ; read compass call I2C_RX_accelerometer ; test accelerometer rcall compass_filter ; filter compass raw data ; Twice call I2C_RX_compass ; read compass call I2C_RX_accelerometer ; test accelerometer rcall compass_filter ; filter compass raw data ; btfsc compass_type ; compass1? ; bra compass_calibration_loop3 ; YES - skip gain stuff ; Test all axes for +4096 (Hi byte=16) banksel compass_DX ; select bank common2 movlw .16 cpfseq compass_DX+1 bra $+4 bra compass_calibration_gainset cpfseq compass_DY+1 bra $+4 bra compass_calibration_gainset cpfseq compass_DZ+1 bra $+4 bra compass_calibration_gainset ; Test all axes for -4096 (Hi byte=240) movlw .240 cpfseq compass_DX+1 bra $+4 bra compass_calibration_gainset cpfseq compass_DY+1 bra $+4 bra compass_calibration_gainset cpfseq compass_DZ+1 bra $+4 bra compass_calibration_gainset banksel common ; back to bank common ; ; ; Three ; call I2C_RX_compass ; read compass ; call I2C_RX_accelerometer ; test accelerometer ; call compass_filter ; filter compass raw data ; ; ; Four times to get cleaner values ; call I2C_RX_compass ; read compass ; call I2C_RX_accelerometer ; test accelerometer ; call compass_filter ; filter compass raw data compass_calibration_loop3: ; and register only one value out of four: call compass_add_calibration ; check and store new max/min values (C-code) banksel common ; back to bank common rcall TFT_compass_fast ; show values btfsc trigger_timeout ; timeout (calibration done)? bra compass_calibration_exit ; YES - exit btfss trigger_full_second ; NO - new second begun? bra compass_calibration_loop2 ; NO - loop bcf trigger_full_second ; YES - clear flag rcall TFT_show_timeout_testmode ; - show remaining time bra compass_calibration_loop2 ; - loop compass_calibration_exit: bcf block_sensor_interrupt ; re-enable sensor interrupts call compass_solve_calibration ; calculate calibration factors (C-code) banksel common ; back to bank common call request_speed_normal ; request CPU speed change to normal speed call option_save_all ; save all settings into EEPROM movlw .6 movff WREG,customview_surfmode ; set to compass view... goto surfloop ; ...and exit global TFT_compass_fast TFT_compass_fast: WIN_TINY .20,.50 STRCPY "X:" MOVII compass_DX,mpr call TFT_convert_signed_16bit ; convert lo:hi into signed-short and add '-' to POSTINC2 if required output_16 STRCAT " Y:" MOVII compass_DY,mpr call TFT_convert_signed_16bit ; convert lo:hi into signed-short and add '-' to POSTINC2 if required output_16 STRCAT " Z:" MOVII compass_DZ,mpr call TFT_convert_signed_16bit ; convert lo:hi into signed-short and add '-' to POSTINC2 if required output_16 STRCAT_PRINT " " return TFT_show_timeout_testmode: WIN_TINY .20,.68 STRCPY "T:" movff isr_timeout_timer,lo bsf leftbind output_8 ; display remaining time bcf leftbind STRCAT_PRINT "s " return TFT_compass_show_gain: ; show the current compass gain ; movff opt_compass_gain,lo ; 0-7 (230 LSB/Gauss to 1370 LSB/Gauss) ; tstfsz lo ; return ; do not show unless gain=0 WIN_TINY .20,.86 STRCPY_TEXT tCompassGain movff opt_compass_gain,lo ; 0-7 (230 LSB/Gauss to 1370 LSB/Gauss) bsf leftbind output_8 bcf leftbind STRCAT_PRINT "" return TFT_surface_compass_bearing: WIN_SMALL surf_compass_bear_column,surf_compass_bear_row MOVII compass_bearing,mpr PUTC "(" bsf leftbind output_16dp .2 ; result is "0.000" bcf leftbind ; rearrange figures to "000" movff buffer+3,buffer+1 movff buffer+4,buffer+2 movff buffer+5,buffer+3 lfsr FSR2,buffer+4 STRCAT "° " rcall tft_compass_cardinal ; add cardinal and ordinal to POSTINC2 STRCAT_PRINT ")" return global TFT_surface_compass_mask TFT_surface_compass_mask: WIN_SMALL surf_compass_mask_column,surf_compass_mask_row call TFT_standard_color STRCPY_TEXT_PRINT tHeading ; Heading: return global TFT_dive_compass_mask ; draws the white box around the heading tape TFT_dive_compass_mask: WIN_FRAME_STD dm_custom_compass_graph_row, dm_custom_compass_graph_row+dm_custom_compass_graph_height, .0, .159 return global TFT_surface_compass_heading TFT_surface_compass_heading: rcall compass_heading_common WIN_STD surf_compass_head_column,surf_compass_head_row call TFT_standard_color TFT_surface_compass_heading_com: ; show "000° N" MOVII compass_heading_new,mpr btfss mpr+1,7 ; compass calibrated? bra TFT_surface_compass_heading_com0 ; YES STRCAT_PRINT "---°" ; NO - print "---°" return ; - done TFT_surface_compass_heading_com0: ; Shown and actual identical? movff compass_heading_shown+0,WREG ; get heading shown, low byte cpfseq mpr+0 ; compare with current heading, equal? bra TFT_surface_compass_heading_com1 ; NO - not equal movff compass_heading_shown+1,WREG ; get heading shown, high byte cpfseq mpr+1 ; compare with current heading, equal? bra TFT_surface_compass_heading_com1 ; NO - not equal bra TFT_surface_compass_heading_com3 ; YES - skip smoothing TFT_surface_compass_heading_com1: MOVII mpr,sub_a MOVII compass_heading_shown,sub_b call subU16 btfsc neg_flag bra TFT_surface_compass_heading_com2 ; shown > actual ; shown < actual banksel compass_heading_shown ; select bank common2 INCI compass_heading_shown ; compass_heading_shown++ banksel common ; back to bank common bra TFT_surface_compass_heading_com3 TFT_surface_compass_heading_com2: banksel compass_heading_shown ; select bank common2 DECI compass_heading_shown ; compass_heading_shown-- banksel common ; back to bank common TFT_surface_compass_heading_com3: MOVII compass_heading_shown,mpr bsf leftbind output_16dp .2 ; result is "0.000" bcf leftbind ; rearrange figures to "000" movff buffer+2,buffer+0 movff buffer+3,buffer+1 movff buffer+4,buffer+2 lfsr FSR2,buffer+3 STRCAT "° " rcall tft_compass_cardinal ; add cardinal and ordinal to POSTINC2 clrf WREG movff WREG,buffer+.7 ; limit to 7 chars STRCAT_PRINT "" btfsc divemode ; in dive mode? return ; YES - done for dive mode ; show bearing on the surface? btfss compass_bearing_set ; is a bearing set? return ; NO - return btfsc compass_menu ; is the "set bearing" selection shown? return ; YES - return bra TFT_surface_compass_bearing ; NO - show bearing and return global TFT_dive_compass_heading TFT_dive_compass_heading: WIN_FONT FT_SMALL ; set font size TODO - needed ??? rcall compass_heading_common ; ; ### for development only, hard-coding the bearing ### ; ; 244° : SW - W ; MOVLI .244,xA ; xA used as temp ; MOVII xA,compass_bearing ; compass_bearing is stored in bank isr_backup MOVII compass_heading_shown,xA ; 160° viewing angle: add +360 offset if xA <= 292 for non-negative scale MOVLI .292,sub_a MOVII xA, sub_b call subU16 ; sub_c = sub_a - sub_b btfsc neg_flag ; xA > 292 ? bra TFT_dive_compass_heading_1 ; YES ADDLI .360,xA ; NO - add offset TFT_dive_compass_heading_1: SUBLI .80,xA ; subtract 80 (left pixel offset from the center) MOVII xA,xRD ; save result to xRD ADDLI .160,xA ; add 160 (display with in pixels) MOVII xA,xRDr ; save result to xRDr btfss compass_bearing_set ; is a bearing set? bra TFT_dive_compass_ruler ; NO - skip next calculations MOVII xRDr,sub_a ; YES - calculate xRD180 = xRDr - 180 MOVLI .180,sub_b call subU16 ; sub_c = sub_a - sub_b MOVII sub_c,xRD180 TFT_dive_compass_bearing_1: ; calculate bearing position and visibility (ahead or behind) bcf compass_bearing_vis ; default is not-visible bcf compass_bearing_ahd ; default is behind MOVII compass_bearing,xA ADDLI .360,xA ; calculate the bearing virtual display offset MOVII xA,divA ; save it for reuse for upper/lower turns and ahead/behind checks ; check if bearing is ahead MOVII divA,sub_a ; load the bearing offset into sub_a MOVII xRD, sub_b ; load the display offset back to sub_b rcall TFT_dive_compass_bearing_ap btfsc compass_bearing_vis ; bearing visible? bra TFT_dive_compass_bearing_dir ; YES ; check if it's ahead with an upper turn MOVII divA,sub_a ; load the bearing offset into sub_a MOVII xRD, sub_b ; load the display offset back to sub_b ADDLI .360,sub_b rcall TFT_dive_compass_bearing_ap btfsc compass_bearing_vis ; bearing visible? bra TFT_dive_compass_bearing_dir ; YES ; check if it's ahead with a lower turn MOVII divA,sub_a ; load the bearing offset into sub_a ADDLI .360,sub_a MOVII xRD, sub_b ; load the display offset back to sub_b rcall TFT_dive_compass_bearing_ap btfsc compass_bearing_vis ; bearing visible? bra TFT_dive_compass_bearing_dir ; YES ; marker is not ahead of us, check if it is behind of us ; use the (160 - (xRD180 - xCM)) formula to see if it's on the display MOVII xRD180,sub_a ; load the display offset back to sub_a MOVII divA, sub_b ; load the marker's offset into sub_b rcall TFT_dive_compass_bearing_bp btfsc compass_bearing_vis ; bearing behind of us? bra TFT_dive_compass_bearing_dir ; YES ; check if it's behind with the upper turn MOVII xRD180,sub_a MOVII divA, sub_b ADDLI .360, sub_b rcall TFT_dive_compass_bearing_bp btfsc compass_bearing_vis ; bearing behind of us? bra TFT_dive_compass_bearing_dir ; YES ; check if it's behind with the lower turn MOVII xRD180,sub_a ADDLI .360, sub_a MOVII divA, sub_b ; load the marker's offset into sub_b rcall TFT_dive_compass_bearing_bp bra TFT_dive_compass_bearing_dir TFT_dive_compass_bearing_ap: ; xCM received in sub_a ; xRD received in sub_b ; 1/a. check if it's viewable from the left side call subU16 ; sub_c = sub_a - sub_b btfsc neg_flag ; xRD > divA ? return ; NO - done MOVII sub_c,xC ; YES - store the RO=RP-RD for drawing ; 1/b. check if it's viewable from the right side ADDLI .2,sub_a ; avoid thin mess on the side of the display ADDLI .158,sub_b ; load the display offset right side into sub_b call subU16 ; sub_c = sub_a - sub_b btfss neg_flag ; xRDr > xA(+2) ? return ; NO - done ; YES - print the bearing lines on the screen movff xC+0,xCM bsf compass_bearing_vis ; set visible bsf compass_bearing_ahd ; set ahead return ; done TFT_dive_compass_bearing_bp: ; use the (160 - (xRD180 - xCM)) formula to see if it's on the display ; the marker's offset received in sub_b ; the xRD180 display offset received in sub_a ; xRD180 - xCM call subU16 ; sub_c = sub_a - sub_b btfsc neg_flag ; CM > xRD180 ? return ; NO - not on screen, done ; YES - check 160 - (X) MOVLI .158, sub_a ; 158 to avoid thin mess on the side of the display MOVII sub_c,sub_b call subU16 ; sub_c = sub_a - sub_b btfsc neg_flag ; X > 160 ? return ; NO - not on screen, done ; check if not overflow - this sounds like a double check... tstfsz sub_c+1 ; high byte = 0 ? return ; NO - sub_c must be > 160 then, done movlw d'158' cpfslt sub_c+0 ; low byte < 158 ? return ; NO - done movff sub_c+0,xCM ; YES to both - print the bearing lines on the screen bsf compass_bearing_vis return ; done TFT_dive_compass_bearing_dir: ; check if bearing to heading, and calculate the direction bcf compass_bearing_eq btfss compass_bearing_vis bra TFT_dive_compass_bearing_lr btfss compass_bearing_ahd bra TFT_dive_compass_bearing_lr movff xCM,xA+0 movlw d'80' cpfseq xA+0 bra TFT_dive_compass_bearing_lr bsf compass_bearing_eq bra TFT_dive_compass_ruler ; bearing points to heading, no signs are required, go to the ruler TFT_dive_compass_bearing_lr: ; get the bearing virtual display offset MOVII compass_bearing,xA ; xA = xA > 292 ? xA : xA+360 MOVLI .292,sub_a MOVII xA, sub_b call subU16 ; sub_c = sub_a - sub_b btfsc neg_flag ; xA > 292 ? bra TFT_dive_compass_bearing_lr_1 ; YES ADDLI .360,xA ; NO - add 360 TFT_dive_compass_bearing_lr_1: ; 1. calculate whether bearing is to left or to right bsf compass_bearing_lft ; to the left by default ; xC: save center value to compare the direction to front value MOVII xA,xC ; xB: we need the left side for comparison... left = -180 MOVII xA, sub_a MOVLI .180,sub_b call subU16 ; sub_c = sub_a - sub_b MOVII sub_c,xB ; xB has the left side of the 180° distance center ; xA = xRD > (xC+100) ? RD-280 : xRD+80 MOVII xC, sub_a ADDLI .100,sub_a MOVII xRD, sub_b call subU16 ; sub_c = sub_a - sub_b btfsc neg_flag ; xRD > xC + 100 ? bra TFT_dive_compass_bearing_lr_2 ; YES - xA = xRD - 280 ; NO - xA = xRD + 80 MOVII xRD,xA ADDLI .80,xA bra TFT_dive_compass_bearing_lr_c TFT_dive_compass_bearing_lr_2: MOVII xRD,sub_a MOVLI .280,sub_b call subU16 ; sub_c = sub_a - sub_b MOVII sub_c,xA ;bra TFT_dive_compass_bearing_lr_c TFT_dive_compass_bearing_lr_c: ; xB < xA < xC => right, otherwise left (default) MOVII xA,sub_b MOVII xB,sub_a call subU16 ; sub_c = sub_a - sub_b btfss neg_flag ; xA > xB ? bra TFT_dive_compass_ruler ; NO - xB >= xA, keep default left MOVII xA,sub_a MOVII xC,sub_b call subU16 ; sub_c = sub_a - sub_b btfss neg_flag ; xC > xA ? bra TFT_dive_compass_ruler ; NO - xA >= xC, keep default left bcf compass_bearing_lft TFT_dive_compass_ruler: ; calculate mod15 for the ticks MOVII xRD,xA MOVLI .15,xB call div16x16 ; xA/xB=xC with xA+0 as remainder ; check the remainder movlw d'0' cpfsgt xA+0 ; mod15 > 0 ? bra TFT_dive_compass_ruler_1 ; NO - RM = 0 ; YES - RM = 15 - RDmod15 movlw d'15' subfwb xA+0,F TFT_dive_compass_ruler_1: movff xA+0,lo ; xA+0 holds the RM, store it to 'lo' clrf hi ; initialize DD to zero, store it to 'hi' TFT_dive_compass_ruler_loop: ; 1. check if we run out of the display movlw d'159' ; looks like 159 works because TFT_box limits the display cpfslt lo,1 bra TFT_dive_compass_ruler_lend ; xRM >= W ; 2. Clear the tick area from DD to RM - in segments to avoid blinking ; don't do a clear if we are at 0 (zero) otherwise it will blink ; because of the width underflow movlw d'0' cpfsgt lo,1 bra TFT_dive_compass_ruler_loop_zz rcall TFT_dive_compass_clr_ruler TFT_dive_compass_ruler_loop_zz: ; 3. Draw the markers @ RM ; we receive RM in lo and DD in hi movlw dm_custom_compass_tick_top_top movwf win_top movlw dm_custom_compass_tick_height movwf win_height movlw d'2' movwf win_bargraph movwf win_width+0 clrf win_width+1 movff lo,win_leftx2 ; 0..159 call TFT_standard_color call TFT_box movlw dm_custom_compass_tick_bot_top movwf win_top movlw dm_custom_compass_tick_height movwf win_height call TFT_standard_color ; color in WREG is trashed, must be set again! call TFT_box ; 4. If D<82 and RM>79: means we put something over the center line ; redraw the center line movlw d'82' cpfslt hi,1 bra TFT_dive_compass_ruler_loop_zz2 movlw d'79' cpfsgt lo,1 bra TFT_dive_compass_ruler_loop_zz2 ; enough to print center line as bearing marker is not in the ticker area movlw color_yellow WIN_BOX_COLOR dm_custom_compass_tick_top_top, dm_custom_compass_tick_bot_bot,.80,.81 ; center line in yellow TFT_dive_compass_ruler_loop_zz2: ; 5. set D = RM + 2 : position after the 2px tick movff lo,hi movlw d'2' addwf hi,F ; 6. set RM = RM + 15 : position to the next tick movlw d'15' addwf lo,F ; 7. loop bra TFT_dive_compass_ruler_loop TFT_dive_compass_ruler_lend: ; loop end ; 8. clear the rest of the tick area if D<160 movlw d'160' cpfslt hi bra TFT_dive_compass_ruler_lend2 ; D >= W ; 9. position left to end of display to clear the remaining area movlw d'159' movwf lo ; 10. clear it rcall TFT_dive_compass_clr_ruler TFT_dive_compass_ruler_lend2: ; done with the compass ruler, put the labels on the screen clrf hi ; hi stores the display position movff hi,xHI ; bank-safe clear of xHI clrf lo ; lo stores the last item's display position movff lo,xLO ; bank-safe clear of xLO MOVLI .219,sub_a ; position of the cardinal MOVII xRD, sub_b ; get the RD back to sub_b rcall TFT_dive_compass_label_proc ; check if the cardinal should be on screen btfss compass_show_cardinal ; shall show cardinal? bra dcr_1 ; NO STRCPY_TEXT_PRINT tSW ; YES - print it dcr_1: rcall TFT_dive_compass_c_mk ; check if cardinal is on the center line or the marker MOVLI .267,sub_a ; position of the cardinal rcall TFT_dive_compass_label_proc ; check if the cardinal should be on screen btfss compass_show_cardinal ; shall show cardinal? bra dcr_2 ; NO STRCPY_TEXT_PRINT tW ; YES - print it dcr_2: rcall TFT_dive_compass_c_mk ; check if cardinal is on the center line or the marker MOVLI .309,sub_a ; position of the cardinal rcall TFT_dive_compass_label_proc ; check if the cardinal should be on screen btfss compass_show_cardinal ; shall show cardinal? bra dcr_3 ; NO STRCPY_TEXT_PRINT tNW ; YES - print it dcr_3: rcall TFT_dive_compass_c_mk ; check if cardinal is on the center line or the marker MOVLI .358,sub_a ; position of the cardinal rcall TFT_dive_compass_label_proc ; check if the cardinal should be on screen btfss compass_show_cardinal ; shall show cardinal? bra dcr_4 ; NO STRCPY_TEXT_PRINT tN ; YES - print it dcr_4: rcall TFT_dive_compass_c_mk ; check if cardinal is on the center line or the marker MOVLI .399,sub_a ; position of the cardinal rcall TFT_dive_compass_label_proc ; check if the cardinal should be on screen btfss compass_show_cardinal ; shall show cardinal? bra dcr_5 ; NO STRCPY_TEXT_PRINT tNE ; YES - print it dcr_5: rcall TFT_dive_compass_c_mk ; check if cardinal is on the center line or the marker MOVLI .448,sub_a ; position of the cardinal rcall TFT_dive_compass_label_proc ; check if the cardinal should be on screen btfss compass_show_cardinal ; shall show cardinal? bra dcr_6 ; NO STRCPY_TEXT_PRINT tE ; YES - print it dcr_6: rcall TFT_dive_compass_c_mk ; check if cardinal is on the center line or the marker MOVLI .489,sub_a ; position of the cardinal rcall TFT_dive_compass_label_proc ; check if the cardinal should be on screen btfss compass_show_cardinal ; shall show cardinal? bra dcr_7 ; NO STRCPY_TEXT_PRINT tSE ; YES - print it dcr_7: rcall TFT_dive_compass_c_mk ; check if cardinal is on the center line or the marker MOVLI .538,sub_a ; position of the cardinal rcall TFT_dive_compass_label_proc ; check if the cardinal should be on screen btfss compass_show_cardinal ;shall show cardinal? bra dcr_8 ; NO STRCPY_TEXT_PRINT tS ; YES - print it dcr_8: rcall TFT_dive_compass_c_mk ; check if cardinal is on the center line or the marker MOVLI .579,sub_a ; position of the cardinal rcall TFT_dive_compass_label_proc ; check if the cardinal should be on screen btfss compass_show_cardinal ; shall show cardinal? bra dcr_9 ; NO STRCPY_TEXT_PRINT tSW ; YES - print it dcr_9: rcall TFT_dive_compass_c_mk ; check if cardinal is on the center line or the marker MOVLI .627,sub_a ; position of the cardinal rcall TFT_dive_compass_label_proc ; check if the cardinal should be on screen btfss compass_show_cardinal ; shall show cardinal? bra dcr_10 ; NO STRCPY_TEXT_PRINT tW ; YES - print it dcr_10: rcall TFT_dive_compass_c_mk ; check if cardinal is on the center line or the marker MOVLI .669,sub_a ; position of the cardinal rcall TFT_dive_compass_label_proc ; check if the cardinal should be on screen btfss compass_show_cardinal ; shall show cardinal? bra dcr_11 ; NO STRCPY_TEXT_PRINT tNW ; YES - print it dcr_11: rcall TFT_dive_compass_c_mk ; check if cardinal is on the center line or the marker MOVLI .718,sub_a ; position of the cardinal rcall TFT_dive_compass_label_proc ; check if the cardinal should be on screen btfss compass_show_cardinal ; shall show? bra dcr_12 ; NO STRCPY_TEXT_PRINT tN ; YES - print it dcr_12: rcall TFT_dive_compass_c_mk ; check if cardinal is on the center line or the marker TFT_dive_compass_label_end: rcall TFT_dive_compass_c_mk ; check if cardinal is on the center line or the marker ; restore lo and hi for the final cleanup movff xLO,lo ; xLO and xHI are stored in bank isr_backup movff xHI,hi ; clear the rest of the SQ area if there are more space movlw d'159' cpfslt hi bra TFT_dive_compass_label_end2 ; D >= 160, no more space ; position left to end of display to clear the remaining area movlw d'158' movwf lo ; clear it rcall TFT_dive_compass_clr_label TFT_dive_compass_label_end2: rcall TFT_dive_compass_c_mk ; check if cardinal is on the center line or the marker ; do we have bearing set? btfsc compass_bearing_set ; bearing set? bra TFT_dive_compass_dir_text ; YES - print the direction (<< or >>) rcall TFT_dive_compass_dir_lclr ; NO - clear the area (e.g. we had but removed) rcall TFT_dive_compass_dir_rclr bra TFT_dive_compass_text TFT_dive_compass_dir_text: ; bearing set, but does it point to heading? btfss compass_bearing_eq bra TFT_dive_compass_dir_text_2 ; bearing != heading - go and print the direction rcall TFT_dive_compass_dir_lclr ; bearing == heading - no need for direction markers rcall TFT_dive_compass_dir_rclr bra TFT_dive_compass_text TFT_dive_compass_dir_text_2: movlw color_green call TFT_set_color btfsc compass_bearing_lft bra TFT_dive_compass_dir_ldir ; bearing_lft=1, print the left marker ;TFT_dive_compass_text_rdir: WIN_SMALL dm_custom_compass_rdir_column, dm_custom_compass_head_row-.2 STRCPY_PRINT ">>" rcall TFT_dive_compass_dir_lclr ; do not forget to clear the left bra TFT_dive_compass_text TFT_dive_compass_dir_ldir: WIN_SMALL dm_custom_compass_ldir_column, dm_custom_compass_head_row-.2 STRCPY_PRINT "<<" rcall TFT_dive_compass_dir_rclr ; do not forget to clear the right ;bra TFT_dive_compass_text TFT_dive_compass_text: ; Clear some unused space on the right mH WIN_BOX_BLACK dm_custom_compass_tick_top_bot+.1,dm_custom_compass_tick_bot_top-.1,.158,.159 ; top, bottom, left, right ; Text output call TFT_standard_color WIN_SMALL dm_custom_compass_head_column, dm_custom_compass_head_row rcall TFT_surface_compass_heading_com ; show "000° N" return TFT_dive_compass_dir_lclr: WIN_SMALL dm_custom_compass_ldir_column, dm_custom_compass_head_row-.2 STRCPY_PRINT " " return TFT_dive_compass_dir_rclr: WIN_SMALL dm_custom_compass_rdir_column, dm_custom_compass_head_row-.2 STRCPY_PRINT " " return TFT_dive_compass_label_proc: movlw d'14' movwf up ; cardinal width in px bcf compass_show_cardinal ; 1/a. check if it's viewable ? sub_a(RP) >= sub_b(RD) ? ; set the carry flag if sub_b(xRD) is equal to or greater than sub_a(xRP): MOVII xRD,sub_b call subU16 ; sub_c = sub_a - sub_b btfsc neg_flag ; >= 0 ? return ; NO ; store the RO=RP-RD for drawing MOVII sub_c,xC ; 1/b. check if it's viewable ? sub_a(RP)+up(width) < sub_b(RD)+160 ; if already above, no need to process the rest of the labels movff up,WREG ; take care about the width addwf sub_a+0,1 btfsc STATUS, C incf sub_a+1 MOVII xRDr,sub_b call subU16 ; sub_c = sub_a - sub_b btfss neg_flag ; < 0 ? bra TFT_dive_compass_label_end ; NO ; 2. restore RO=RP-RD from 1/a. movff xC+0,lo ; 3. Clear the segment from DD(hi) to lo ; don't do a clear if we are at 0 (zero) otherwise it will blink ; ?because of the width underflow? movlw d'1' cpfsgt lo bra TFT_dive_compass_label_proc_p rcall TFT_dive_compass_clr_label TFT_dive_compass_label_proc_p: ; 4. print the SQ on the screen call TFT_standard_color bsf compass_show_cardinal ;TFT_dive_compass_label_print: movlw dm_custom_compass_label_row movff WREG,win_top movff lo,win_leftx2 WIN_FONT FT_SMALL ; 6. retain the new display positions movff lo,hi movff up,WREG addwf hi,F movff lo,xLO movff hi,xHI return TFT_dive_compass_c_mk: ; Common task to draw center line and marker ; until a proper implementation make it simple: rcall TFT_dive_compass_mk movlw color_yellow WIN_BOX_COLOR dm_custom_compass_tick_top_top, dm_custom_compass_tick_bot_bot,.80,.81 ; center line in yellow return TFT_dive_compass_mk: ; draw the bearing on the screen if visible and if we just put something over it btfss compass_bearing_set return ; bearing_set=0 nothing to display btfss compass_bearing_vis return ; bearing set but not visible ; save lo/hi from trashing MOVII mpr,xA ; did we just update the marker's position? ; DD.......DD ; CM+2>=DD(old) or CM-2<=DD ; ToDo btfss compass_bearing_ahd bra TFT_dive_compass_mk_rear ;TFT_dive_compass_mk_front: clrf lo movff xCM,lo bsf compass_show_cardinal ; set=green marker rcall TFT_dive_compass_mk_print bcf compass_show_cardinal bra TFT_dive_compass_mk_end TFT_dive_compass_mk_rear: clrf lo movff xCM,lo bcf compass_show_cardinal ; set=red marker rcall TFT_dive_compass_mk_print TFT_dive_compass_mk_end: MOVII xA,mpr return TFT_dive_compass_mk_print: movlw d'1' cpfsgt lo bra TFT_dive_compass_mk_print_2 ; lo <= 1, skip the first line movlw d'2' subwf lo,0 ; movff WREG,win_leftx2 rcall TFT_dive_compass_mk_print_3 TFT_dive_compass_mk_print_2: ; save hi/lo MOVII mpr,divA ; clear the middle of the bearing marker movff lo,hi movlw d'2' addwf lo,1 rcall TFT_dive_compass_clr_label ; restore hi/lo MOVII divA,mpr ; print a dot on the middle movf lo,W rcall TFT_dive_compass_mk_print_dot ; finally print the right marker line movlw d'2' addwf lo,0 ; rcall TFT_dive_compass_mk_print_3 ; return TFT_dive_compass_mk_print_3: movwf win_leftx2 movlw dm_custom_compass_label_row movwf win_top movlw dm_custom_compass_label_height-.2 movwf win_height bra TFT_dive_compass_mk_print_4 TFT_dive_compass_mk_print_dot: movwf win_leftx2 movlw dm_custom_compass_label_row + .9 movwf win_top movlw d'4' movwf win_height TFT_dive_compass_mk_print_4: movlw .158 cpfslt win_leftx2 bra TFT_dive_compass_mk_print_5 movlw d'2' movwf win_bargraph movwf win_width+0 clrf win_width+1 movlw color_green btfss compass_show_cardinal movlw color_red call TFT_set_color call TFT_box TFT_dive_compass_mk_print_5: return TFT_dive_compass_clr_label: movlw dm_custom_compass_label_row-.2 ; set top & height movwf win_top movlw dm_custom_compass_label_height+.2 movwf win_height rcall TFT_dive_compass_clear return TFT_dive_compass_clr_ruler: ; top tick movlw dm_custom_compass_tick_top_top ; set top & height movwf win_top movlw dm_custom_compass_tick_height movwf win_height rcall TFT_dive_compass_clear ;bottom tick movlw dm_custom_compass_tick_bot_top ; set top & height movwf win_top movlw dm_custom_compass_tick_height movwf win_height ; rcall TFT_dive_compass_clear ; return TFT_dive_compass_clear: ; we receive RM in lo and DD in hi ; calculate width = RM-D movf hi,W subwf lo,W bz TFT_dive_compass_clear3 ; do nothing if there is nothing to do movwf win_width+0 ; RM-DD movwf win_bargraph clrf win_width+1 movlw .1 cpfsgt win_width+0 bra TFT_dive_compass_clear3 ; do not clear a single pixel (or less) movff hi,win_leftx2 movlw color_black call TFT_set_color call TFT_box TFT_dive_compass_clear3: return tft_compass_cardinal: btfsc hi,0 ; heading > 255° ? bra tft_compass_cardinal2 ; YES - must be W, NW or N ; NO - must be W, SW, S, SE, E, NE or N movlw .23 subwf lo,W btfss STATUS,C bra tft_compass_cardinal_N movlw .68 subwf lo,W btfss STATUS,C bra tft_compass_cardinal_NE movlw .113 subwf lo,W btfss STATUS,C bra tft_compass_cardinal_E movlw .158 subwf lo,W btfss STATUS,C bra tft_compass_cardinal_SE movlw .203 subwf lo,W btfss STATUS,C bra tft_compass_cardinal_S movlw .248 subwf lo,W btfss STATUS,C bra tft_compass_cardinal_SW bra tft_compass_cardinal_W tft_compass_cardinal2: movlw .37 subwf lo,W btfss STATUS,C bra tft_compass_cardinal_W movlw .82 subwf lo,W btfss STATUS,C bra tft_compass_cardinal_NW ; bra tft_compass_cardinal_N tft_compass_cardinal_N: STRCAT_TEXT tN return tft_compass_cardinal_NE: STRCAT_TEXT tNE return tft_compass_cardinal_E: STRCAT_TEXT tE return tft_compass_cardinal_SE: STRCAT_TEXT tSE return tft_compass_cardinal_S: STRCAT_TEXT tS return tft_compass_cardinal_SW: STRCAT_TEXT tSW return tft_compass_cardinal_W: STRCAT_TEXT tW return tft_compass_cardinal_NW: STRCAT_TEXT tNW return compass_heading_common: btfss compass_enabled ; compass enabled? bra compass_heading_common3 ; NO movlw compass_averaging ; number of averaging cycles movwf up ; initialize loop counter compass_heading_common1: call I2C_RX_compass ; test compass call I2C_RX_accelerometer ; test accelerometer call compass_filter ; filter raw compass + accelerometer readings decfsz up,F ; decrement loop counter, done? bra compass_heading_common1 ; NO - loop call compass ; do compass corrections (C-code) banksel common ; back to bank common MOVII compass_heading_old,sub_a ; transfer old heading to sub16 input MOVII compass_heading_new,sub_b ; transfer new heading to sub16 input btfsc sub_b+1,7 ; valid compass calibration? bra compass_heading_common3 ; NO call sub16 ; calculate compass_heading_old - compass_heading_new btfss neg_flag ; result < 0 ? bra compass_heading_common2 ; NO - test for threshold MOVII compass_heading_new,sub_a ; YES - subtract the other way round MOVII compass_heading_old,sub_b ; - ... call sub16 ; - calculate compass_heading_new - compass_heading_old compass_heading_common2: MOVII compass_heading_new,compass_heading_old ; copy new to old movlw compass_fast_treshold ; get threshold for fast cpfsgt sub_c+0 ; heading difference > compass_fast_treshold ? return ; NO - done MOVII compass_heading_new,compass_heading_shown ; YES - copy heading return ; - done compass_heading_common3: clrf mpr+0 ; NO - create encoding of 0° clrf mpr+1 ; - ... MOVII mpr,compass_heading_shown ; - copy to compass_heading_shown return ; - done ENDIF ; _compass END