Mercurial > public > hwos_code
view src/divemode.asm @ 501:69a98f3f3b84
minor
author | heinrichsweikamp |
---|---|
date | Mon, 22 May 2017 23:03:21 +0200 |
parents | 18e047102e49 |
children | b9f06f1a1f74 |
line wrap: on
line source
;============================================================================= ; ; File divemode.asm ; ; Divemode ; ; Copyright (c) 2011, JD Gascuel, HeinrichsWeikamp, all right reserved. ;============================================================================= ; HISTORY ; 2011-08-15 : [mH] moving from OSTC code #include "hwos.inc" ; Mandatory header #include "shared_definitions.h" ; Mailbox from/to p2_deco.c #include "tft_outputs.inc" #include "strings.inc" #include "tft.inc" #include "eeprom_rs232.inc" #include "isr.inc" #include "math.inc" #include "wait.inc" #include "customview.inc" #include "start.inc" #include "adc_lightsensor.inc" #include "ghostwriter.inc" #include "i2c.inc" #include "calibrate.inc" #include "convert.inc" gui CODE global diveloop diveloop: banksel common call speed_normal call diveloop_boot ; Boot tasks for all modes ; Startup Tasks for all modes call TFT_boot ; Initialize TFT (includes clear screen) call TFT_divemode_mask ; Display mask call TFT_temp_divemode ; Displays temperature movff customview_divemode,menupos3 ; Reload last customview call customview_mask ; Redraw last custom view btfsc FLAG_apnoe_mode bsf realdive ; Set Realdive flag in Apnoe mode btfsc FLAG_apnoe_mode ; Done for Apnoe or Gauge mode bra diveloop_loop btfsc FLAG_gauge_mode ; Done for Apnoe or Gauge mode bra diveloop_loop call TFT_active_gas_divemode ; Display gas/Setpoint call TFT_display_ndl_mask ; display "NDL" ; +@5 init setf WREG ; WAIT marker: display "---" movff WREG,int_O_extra_ascenttime+0 movff WREG,int_O_extra_ascenttime+1 movlw 1 movwf apnoe_mins ; Start compute after next cycle. ;-------------------------------------------------------------------------------------------------------- diveloop_loop: ; The diveloop starts here btfss onesecupdate bra diveloop_loop3 ; tasks any new second... bcf onesecupdate ; one seconds update, clear flag here in case it's set again in ISR before all tasks are done. btfsc FLAG_apnoe_mode ; Only in apnoe mode bra diveloop_loop1b ; One Second Tasks in Apnoe mode call TFT_divemins ; Display (new) divetime! call customview_second ; Do every-second tasks for the custom view area call divemode_check_for_warnings ; Check for any warnings ; Tasks only for deco modes btfsc show_safety_stop ; Show the safety stop? call TFT_show_safety_stop ; Yes, show/delete if done. call calc_deko_divemode ; calculate decompression and display result (any two seconds) bra diveloop_loop1x ; Common Tasks diveloop_loop1b: ; Tasks only for Apnoe mode rcall divemode_apnoe_tasks ; 1 sec. Apnoe tasks call customview_second ; Do every-second tasks for the custom view area bra diveloop_loop1x ; Common Tasks diveloop_loop1x: ; Common 1sec. tasks for all modes rcall timeout_divemode ; dive finished? This routine sets the required flags rcall set_dive_modes ; tests if depth>threshold rcall set_min_temp ; store min. temp if required btfsc store_sample ; store new sample? call store_dive_data ; Store profile data btfss divemode ; Dive finished? goto ghostwriter_end_dive ; Dive finished! btfsc divemode_gaschange ; Gas switch flag set? rcall gas_switched_common ; Yes btfsc toggle_gf ; =1: Toggle GF/aGF rcall divemodemode_togglegf ; Toggle aGF/GF btfsc FLAG_ccr_mode ; In CCR mode... call check_dive_autosp ; ...check for Auto-SP call compute_ppo2 ; compute mv_sensorX and ppo2_sensorX arrays diveloop_loop3: rcall test_switches_divemode ; Check switches in divemode global diveloop_loop4 diveloop_loop4: ; Menu-Exit returns here... btfsc toggle_customview ; Next view? call customview_toggle ; Yes, show next customview (and delete this flag) btfsc pressure_refresh ; new pressure available? rcall update_temp_and_or_depth ; Yes, display new depth and clear "pressure_refresh" flag btfsc oneminupdate ; one minute tasks rcall update_divemode60 ; Update clock, etc. ; btfss quarter_second_update ; bra diveloop_loop4a bcf quarter_second_update movlw .6 cpfseq menupos3 ; in compass view? bra diveloop_loop4a ; No extern TFT_dive_compass_heading call TFT_dive_compass_heading ; Yes, update compass heading value diveloop_loop4a: btfsc enable_screen_dumps ; =1: Ignore vin_usb, wait for "l" command (Screen dump) bra diveloop_loop5 bra diveloop_loop6 diveloop_loop5: btfss vusb_in ; USB (still) plugged in? bcf enable_screen_dumps ; No, clear flag call rs232_get_byte btfsc rs232_recieve_overflow bra diveloop_loop6 movlw "l" cpfseq RCREG1 bra diveloop_loop6 call TFT_dump_screen ; Dump the screen contents diveloop_loop6: bra diveloop_loop ; Loop the divemode ;-------------------------------------------------------------------------------------------------------- divemode_apnoe_tasks: ; 1 sec. Apnoe tasks call TFT_display_apnoe_descent ; Yes, Show descent timer call TFT_max_pressure ; use normal max. depth btfsc divemode2 ; Time running? bra divemode_apnoe_tasks2 ; New descent, reset data if flag is set rcall apnoe_calc_maxdepth call TFT_display_apnoe_surface call TFT_display_apnoe_last_max ; Show last max. depth incf apnoe_surface_secs,F movlw d'60' cpfseq apnoe_surface_secs bra divemode_apnoe_tasks1 clrf apnoe_surface_secs incf apnoe_surface_mins,F divemode_apnoe_tasks1: bcf FLAG_active_descent ; Clear flag btfsc divemode2 ; Time running? return ; Yes, return bsf FLAG_active_descent ; Set Flag return divemode_apnoe_tasks2: btfss FLAG_active_descent ; Are we descending? return ; No, We are at the surface rcall apnoe_calc_maxdepth ; Yes! call TFT_apnoe_clear_surface ; Clear Surface timer clrf apnoe_timeout_counter ; Delete timeout clrf apnoe_surface_secs clrf apnoe_surface_mins clrf apnoe_secs clrf apnoe_mins ; Reset Descent time movlw .0 movff WREG,max_pressure+0 movff WREG,max_pressure+1 ; Reset Max. Depth bcf FLAG_active_descent ; Clear flag return global apnoe_calc_maxdepth apnoe_calc_maxdepth: movff apnoe_max_pressure+0,sub_a+0 movff apnoe_max_pressure+1,sub_a+1 movff max_pressure+0,sub_b+0 movff max_pressure+1,sub_b+1 call subU16 ; sub_c = sub_a - sub_b ; apnoe_max_pressure<max_pressure -> neg_flag=1 ; max_pressure<=apnoe_max_pressure -> neg_flag=0 btfss neg_flag return ;apnoe_max_pressure<max_pressure movff max_pressure+0,apnoe_max_pressure+0 movff max_pressure+1,apnoe_max_pressure+1 return calc_deko_divemode: btfsc twosecupdate ; two seconds after the last call bra calc_deko_divemode2 ; Yes, calculate and display deco data ("first second") bsf twosecupdate ; No, but next second! ; Routines used in the "other second" call calc_average_depth ; calculate average depth call calc_velocity ; calculate vertical velocity and display if > threshold (every two seconds) call set_reset_safety_stop ; Set flags for safety stop and/or reset safety stop call TFT_debug_output btfsc FLAG_apnoe_mode ; Done for Apnoe or Gauge mode return btfsc FLAG_gauge_mode ; Done for Apnoe or Gauge mode return ; Calculate CNS btfss FLAG_pscr_mode ; in PSCR mode? rcall set_actual_ppo2 ; No, set char_I_actual_ppO2 btfsc is_bailout ; Always in bailout... rcall set_actual_ppo2 ; ...set char_I_actual_ppO2 clrf WREG movff WREG,char_I_step_is_1min ; Make sure to be in 2sec mode. call deco_calc_CNS_fraction ; calculate CNS movlb b'00000001' ; rambank 1 selected ; Check for a gas change bra check_gas_change ; Checks if a better gas should be selected (by user) and return... global set_actual_ppo2 set_actual_ppo2: ; calculate ppO2 in 0.01bar (e.g. 150 = 1.50 bar ppO2) btfsc divemode ; in divemode bra set_actual_ppo2_dive ; Yes ; No, use simulated ambient pressure for char_I_actual_ppO2 movff char_I_bottom_depth,WREG mullw .100 movlw LOW(.1000) addwf PRODL,W movwf xA+0 movlw HIGH(.1000) addwfc PRODH,W movwf xA+1 ; P_amb in millibar (1000 = 1.00 bar). bra set_actual_ppo2_common set_actual_ppo2_dive: SAFE_2BYTE_COPY amb_pressure, xA ; P_amb in millibar (1000 = 1.00 bar). set_actual_ppo2_common: movlw d'10' movwf xB+0 clrf xB+1 call div16x16 ; xC=p_amb/10 (100 = 1.00 bar). movff xC+0,xA+0 movff xC+1,xA+1 movff char_I_O2_ratio,xB+0 clrf xB+1 call mult16x16 ; char_I_O2_ratio * (p_amb/10) movff xC+0,xA+0 movff xC+1,xA+1 movlw d'100' movwf xB+0 clrf xB+1 call div16x16 ; xC=(char_I_O2_ratio * p_amb/10)/100 ; Copy ppO2 for CNS calculation tstfsz xC+1 ; Is ppO2 > 2.55bar ? setf xC+0 ; yes: bound to 2.55... better than wrap around. movff xC+0, char_I_actual_ppO2 ; copy last ppO2 to buffer register btfsc is_bailout ; In Bailout? return ; Yes, done. ; No Bailout, check for ccr mode btfsc FLAG_ccr_mode ; If FLAG_ccr_mode=1... movff char_I_const_ppO2, char_I_actual_ppO2 ; ...copy last ppO2 to buffer register return check_fallback_clear: call check_sensors ; Setups "use_O2_sensorX" flags ; Copy use flags to voting logic flags in case we are no longer in fallback btfsc use_O2_sensor1 bsf voting_logic_sensor1 btfsc use_O2_sensor2 bsf voting_logic_sensor2 btfsc use_O2_sensor3 bsf voting_logic_sensor3 rcall divemode_setup_sensor_values ; Setup sensor values goto check_sensors ; Check O2 sensor thresholds for fallback customview_minute calc_deko_divemode2: bcf twosecupdate btfsc FLAG_apnoe_mode ; Done for Apnoe or Gauge mode return btfsc FLAG_gauge_mode ; Done for Apnoe or Gauge mode return extern deco_setup_dive call deco_setup_dive ; Pass all parameters to the C code btfsc setpoint_fallback ; Are we in Fallback? rcall check_fallback_clear ; Yes, check if we still have fallback condition bcf setpoint_fallback ; =1: Fallback to SP1 due to external O2 sensor failure btfsc FLAG_ccr_mode ; In CCR mode? rcall calc_deko_divemode_sensor ; External sensor stuff ; btfsc FLAG_pscr_mode ; In PSCR mode? ; rcall calc_deko_divemode_sensor ; External sensor stuff SAFE_2BYTE_COPY amb_pressure,int_I_pres_respiration ; C-code needs the ambient pressure clrf WREG movff WREG,char_I_step_is_1min ; Force 2 second deco mode movff char_I_O2_ratio,lo_temp ; Backup original value for everything movff char_I_N2_ratio,hi_temp ; Backup original value for everything btfss FLAG_pscr_mode bra calc_deko_divemode2a ; Non-PSCR modes... btfsc is_bailout bra calc_deko_divemode2a ; Skip in bailout ; in PSCR mode, compute fO2 into char_I_O2_ratio call compute_pscr_ppo2 ; pSCR ppO2 into sub_c:2 movff sub_c+0,xA+0 movff sub_c+1,xA+1 movlw LOW .10 movwf xB+0 movlw HIGH .10 movwf xB+1 call mult16x16 ;xA*xB=xC -> xC:4 = ppO2*10 SAFE_2BYTE_COPY amb_pressure, xB call div32x16 ; xC:4 / xB:2 = xC+3:xC+2 with xC+1:xC+0 as remainder ; xC+0 has O2 in percent movff xC+0,char_I_O2_ratio movff char_I_He_ratio, wait_temp ; copy into bank1 register bsf STATUS,C ; Borrow bit movlw d'100' ; 100% subfwb wait_temp,W ; minus He bsf STATUS,C ; Borrow bit subfwb xC+0,W ; minus O2 movff WREG, char_I_N2_ratio ; = N2! calc_deko_divemode2a: clrf TMR5L clrf TMR5H ; 30,51757813µs/bit in TMR5L:TMR5H call deco_calc_hauptroutine ; calc_tissue movlb .1 movff lo_temp,char_I_O2_ratio ; Restore original value for everything movff hi_temp,char_I_N2_ratio ; Restore original value for everything movff char_O_deco_status,WREG ; Is a compute cycle finished ? iorwf WREG,F btfss STATUS,Z return ; Return is status <> 0 ; Check if deco stops are necessary ? movff char_O_first_deco_depth,wait_temp ; copy ceiling to temp register tstfsz wait_temp ; Ceiling<0m? bra calc_deko_divemode3 ; Yes! btfsc decostop_active ; Already in nodeco mode ? call TFT_display_ndl_mask ; No, Clear deco data, display nostop time bcf decostop_active ; clear flag (again) ; Copy for profile recording clrf decodata+0 movff char_O_nullzeit,decodata+1 ; NDL goto TFT_display_ndl ; display no deco limit, and return... calc_deko_divemode3: btfss decostop_active ; Already in deco mode ? call TFT_display_deko_mask ; No, clear nostop time, display decodata bsf decostop_active ; Set flag (again) ; Copy for profile recording movff char_O_first_deco_depth,decodata+0 ; ceiling movff char_O_first_deco_time,decodata+1 ; length of first stop in minues call TFT_display_deko ; display decodata call TFT_show_TTS_divemode ; display TTS movff char_I_extra_time,WREG tstfsz WREG ; extra time = 0? bra calc_deko_divemode4 ; No, compute it return calc_deko_divemode4: ; Check if extra cycles are needed to compute @5 variant: decfsz apnoe_mins,F ; Reached count-down ? return ; No: don't compute yet. movlw .6 movff WREG,char_O_deco_status ; Stole next cycles for @5 variant. movlw .2 ; Restart countdown. movwf apnoe_mins return ; done. calc_deko_divemode_sensor: ; External sensor stuff movff opt_ccr_mode,WREG ; =0: Fixed SP, =1: Sensor, =2: Auto SP sublw .1 ; opt_ccr_mode = 1 (Sensor)? bnz calc_deko_divemode_sensor_done ; No, return rcall divemode_setup_sensor_values ; Setup sensor values call check_sensors ; Check O2 sensor thresholds for fallback movff sensor_setpoint,char_I_const_ppO2; Copy sensor result TSTOSS opt_sensor_fallback ; =1: Fallback to SP1 when sensor is lost return ; Never fallback btfsc is_bailout ; In bailout? return ; Never fallback in bailout ; Check if we should fallback to SP1 btfsc use_O2_sensor1 return ; At least one sensor is active, no fallback btfsc use_O2_sensor2 return ; At least one sensor is active, no fallback btfsc use_O2_sensor3 return ; At least one sensor is active, no fallback ; No sensor in use -> fallback movff char_I_setpoint_cbar+0,char_I_const_ppO2 ; Setup fixed Setpoint (Always fallback to SP1), overwrite sensor result bsf setpoint_fallback ; =1: Fallback to SP1 due to external O2 sensor failure calc_deko_divemode_sensor_done: return ;----------------------------------------------------------------------------- divemodemode_togglegf: ; Toggle aGF/GF bcf toggle_gf ; clear flag btg use_agf ; Toggle GF call TFT_gf_mask ; Setup Mask clrf WREG movff WREG,char_O_deco_status ; Restart decoplan computation return global divemode_setup_sensor_values divemode_setup_sensor_values: ; sum up sensor values (in xA:2) and active sensors in (xB:2) clrf xB+0 clrf xB+1 clrf xA+0 clrf xA+1 btfss use_O2_sensor1 ; Sensor1 active? bra divemode_setup_sensor_values2 ; No btfss voting_logic_sensor1 ; Sensor within voting logic? bra divemode_setup_sensor_values2 ; No movf o2_ppo2_sensor1,W addwf xA+0 movlw .0 addwfc xA+1 ; Add into xA:2 incf xB+0,F ; Add a sensor divemode_setup_sensor_values2: btfss use_O2_sensor2 ; Sensor2 active? bra divemode_setup_sensor_values3 ; No btfss voting_logic_sensor2 ; Sensor within voting logic? bra divemode_setup_sensor_values3 ; No movf o2_ppo2_sensor2,W addwf xA+0 movlw .0 addwfc xA+1 ; Add into xA:2 incf xB+0,F ; Add a sensor divemode_setup_sensor_values3: btfss use_O2_sensor3 ; Sensor3 active? bra divemode_setup_sensor_values4 ; No btfss voting_logic_sensor3 ; Sensor within voting logic? bra divemode_setup_sensor_values4 ; No movf o2_ppo2_sensor3,W addwf xA+0 movlw .0 addwfc xA+1 ; Add into xA:2 incf xB+0,F ; Add a sensor divemode_setup_sensor_values4: call div16x16 ; xA/xB=xC with xA+0 as remainder movff xC+0,sensor_setpoint ; Copy result return calc_velocity: ; called every two seconds btfsc display_velocity bra calc_velocity1 ; Always update if already displayed btfss divemode2 return ; display velocity only if deepter then 1m (Not at the surface after the dive) calc_velocity1: SAFE_2BYTE_COPY amb_pressure, sub_a movff last_pressure_velocity+0,sub_b+0 movff last_pressure_velocity+1,sub_b+1 movff sub_a+0,last_pressure_velocity+0 ; store old value for velocity movff sub_a+1,last_pressure_velocity+1 call subU16 ; sub_c = amb_pressure - last_pressure bcf neg_flag_velocity btfsc neg_flag bsf neg_flag_velocity movff sub_c+0,xA+0 movff sub_c+1,xA+1 movlw d'39' ; 77 when called every second.... movwf xB+0 clrf xB+1 call mult16x16 ; differential pressure in mbar*77... movff xC+0,divA+0 movff xC+1,divA+1 movlw d'7' movwf divB+0 call div16 ; devided by 2^7 equals velocity in m/min movlw d'99' cpfsgt divA+0 ; limit to 99m/min bra calc_velocity3 movwf divA+0 ; divA=99 calc_velocity3: ; Copy old speeds movff old_velocity+2,old_velocity+3 movff old_velocity+1,old_velocity+2 movff old_velocity+0,old_velocity+1 movff divA+0,old_velocity+0 ; movff old_velocity+3,WREG ; addwf divA+0,F ; add old speed ; bcf STATUS,C ; rrcf divA+0,F ; /2 ; movff old_velocity+2,WREG ; addwf divA+0,F ; add old speed ; bcf STATUS,C ; rrcf divA+0,F ; /2 ; movff old_velocity+1,WREG ; addwf divA+0,F ; add old speed ; bcf STATUS,C ; rrcf divA+0,F ; /2 ; movff old_velocity+0,WREG ; addwf divA+0,F ; add old speed ; bcf STATUS,C ; rrcf divA+0,F ; /2 goto TFT_display_velocity ; With divA+0 = m/min..., and return... ;============================================================================= set_reset_safety_stop: ; Set flags for safety stop and/or reset safety stop TSTOSS opt_enable_safetystop ; =1: A safety stop is shown bra delete_safety_stop ; No, don't show safety stop btfsc decostop_active ; Is a deco stop displayed? bra delete_safety_stop ; Yes, don't show safety stop ; Below "opt_safety_stop_reset"? Set flag and reset count-down timer SAFE_2BYTE_COPY rel_pressure, lo call adjust_depth_with_salinity ; computes salinity setting into lo:hi [mbar] movff lo,sub_a+0 movff hi,sub_a+1 movff opt_safety_stop_reset,WREG ; [cbar] mullw .10 ; mbar in PRODL:H movff PRODL,sub_b+0 movff PRODH,sub_b+1 call subU16 ; sub_c = sub_a - sub_b btfss neg_flag bra reset_safety_stop ; Below 10m, reset safety stop ; Above "opt_safety_stop_end"? Clear flag. SAFE_2BYTE_COPY rel_pressure, lo call adjust_depth_with_salinity ; computes salinity setting into lo:hi [mbar] movff lo,sub_a+0 movff hi,sub_a+1 movff opt_safety_stop_end,WREG ; [cbar] mullw .10 ; mbar in PRODL:H movff PRODL,sub_b+0 movff PRODH,sub_b+1 call subU16 ; sub_c = sub_a - sub_b btfsc neg_flag bra delete_safety_stop ; Above 3m, remove safety stop ; Above "opt_safety_stop_start"? Activate safety stop SAFE_2BYTE_COPY rel_pressure, lo call adjust_depth_with_salinity ; computes salinity setting into lo:hi [mbar] movff lo,sub_a+0 movff hi,sub_a+1 movff opt_safety_stop_start,WREG ; [cbar] mullw .10 ; mbar in PRODL:H movff PRODL,sub_b+0 movff PRODH,sub_b+1 call subU16 ; sub_c = sub_a - sub_b btfsc neg_flag bra acivate_safety_stop ; Above 5m, activate safety stop bra reset_safety_stop2 ; Pause safety stop acivate_safety_stop: tstfsz safety_stop_countdown ; Countdown at zero? bsf show_safety_stop ; No, Set flag! return delete_safety_stop: clrf safety_stop_countdown ; reset timer bra reset_safety_stop2 ; Remove safety stop from display reset_safety_stop: movff opt_safety_stop_length,safety_stop_countdown ; reset timer reset_safety_stop2: bcf show_safety_stop ; Clear flag btfss safety_stop_active ; Safety stop shown return ; No, don't delete it bcf safety_stop_active ; Clear flag goto TFT_clear_safety_stop ; Clear safety stop, and return... ;============================================================================= timeout_menuview: decfsz timeout_counter3,F ; timeout for menuview return ; No timeout, return ; Timeout, clear e.g. "Menu?" goto menuview_toggle_reset ; "returns" timeout_divemode_menu: decfsz timeout_counter3,F ; timeout for divemode menu return global timeout_divemode_menu2 timeout_divemode_menu2: ; Called from divemenu_tree.asm bcf divemode_menu ; Timeout! Clear flag call TFT_clear_divemode_menu ; Clear menu call TFT_active_gas_divemode ; Redraw gas/setpoint/diluent bcf blinking_better_gas ; Clear flag to have temperature updated once call TFT_temp_divemode ; Displays temperature call TFT_draw_gassep_line ; Gas separator grid in spec mode only btfss decostop_active ; In deco mode ? bra timeout_divemode_menu_ndl ; No, show NDL again ; Show deco call TFT_display_deko_mask ; clear nostop time, display decodata call TFT_display_deko goto TFT_show_TTS_divemode; and return... timeout_divemode_menu_ndl: ; Show NDL call TFT_display_ndl_mask ; Clear deco data, display nostop time goto TFT_display_ndl; and return... timeout_divemode: btfsc divemode_menu ; Divemode menu active? rcall timeout_divemode_menu ; Yes, check the timeout for it... btfsc menuview ; is a menuview shown? rcall timeout_menuview ; Yes, check the timeout for it... btfss realdive ; Dive longer then one minute return btfsc FLAG_apnoe_mode ; In Apnoe mode? bra timeout_divemode2 ; Yes, use apnoe_timeout [min] for timeout ifndef __DEBUG btfsc simulatormode_active ; In Simulator mode? bra timeout_divemode3 ; Yes, use simulator timeout endif bcf divemode infsnz timeout_counter,F incf timeout_counter2,F ; timeout is 15bits movff opt_diveTimeout,WREG ; in [min] mullw .60 movff PRODL,sub_a+0 movff PRODH,sub_a+1 ; in [s] movff timeout_counter, sub_b+0 movff timeout_counter2, sub_b+1 call subU16 ; sub_c = sub_a - sub_b btfss neg_flag ; Result negative? bsf divemode ; No, set flag return timeout_divemode2: incf timeout_counter,F ; seconds... movlw d'60' cpfseq timeout_counter ; timeout_counter=60? return ; No. ; One minute timeout done. clrf timeout_counter bcf divemode incf apnoe_timeout_counter,F movlw apnoe_timeout ; apnoe timeout [min] cpfseq apnoe_timeout_counter bsf divemode return timeout_divemode3: bcf divemode incf timeout_counter,F movlw simulator_timeout ; simulator timeout cpfsgt timeout_counter bsf divemode return update_temp_and_or_depth: ; New sensor data arrived... btfsc temp_changed call TFT_temp_divemode ; Displays temperature btfsc pressure_refresh call TFT_depth ; Displays new depth rcall set_max_depth ; update max. depth if required bcf pressure_refresh ; until new pressure is available return update_divemode60: ; update any minute call get_battery_voltage ; gets battery voltage rcall set_powersafe ; Battery low? call TFT_max_pressure ; Update max. depth call customview_minute ; Do every-minute tasks for the custom view area bcf oneminupdate btfss simulatormode_active ; in simulator mode? return ; No ; Yes, quite dive mode simulation after 21*256s=89min:36s movlw .20 cpfsgt total_divetime_seconds+1 ; Timeout? return ; No ifdef __DEBUG return ; No simulator timeout in debug mode endif bra divemode_option1 ; Yes, set to 0m and "return" set_max_depth: movff max_pressure+0,sub_a+0 movff max_pressure+1,sub_a+1 SAFE_2BYTE_COPY rel_pressure, sub_b call subU16 ; sub_c = sub_a - sub_b ; max_pressure<rel_pressure -> neg_flag=1 ; rel_pressure<=max_pressure -> neg_flag=0 btfss neg_flag return ; max_pressure<rel_pressure movff sub_b+0,max_pressure+0 movff sub_b+1,max_pressure+1 goto TFT_max_pressure ; No, use normal max. depth; and return... set_min_temp: movff minimum_temperature+0,sub_a+0 movff minimum_temperature+1,sub_a+1 SAFE_2BYTE_COPY temperature,sub_b call sub16 ; sub_c = sub_a - sub_b ; minimum_temperature<T -> neg_flag=1 ; T<=minimum_temperature -> neg_flag=0 btfsc neg_flag return ; minimum_temperature>=T movff sub_b+0,minimum_temperature+0 movff sub_b+1,minimum_temperature+1 return global set_dive_modes set_dive_modes: btfsc high_altitude_mode ; In high altitude (Fly) mode? bra set_dive_modes3 ; Yes! set_dive_modes0: movlw LOW start_dive_threshold movwf sub_a+0 ; dive_treshold is in cm movlw HIGH start_dive_threshold movwf sub_a+1 ; dive_treshold is in cm set_dive_modes1: SAFE_2BYTE_COPY rel_pressure, sub_b call subU16 ; sub_c = sub_a - sub_b btfss neg_flag bra set_dive_modes2 ; too shallow (rel_pressure<dive_threshold) btfsc realdive ; Dive longer than one minute? clrf timeout_counter ; Yes, reset timout counter bsf divemode ; (Re-)Set divemode flag bsf divemode2 ; displayed divetime is running return set_dive_modes2: bcf divemode2 ; Stop time btfss realdive ; dive longer then one minute? bcf divemode ; no -> this was no real dive return ; No, return set_dive_modes3: ; High-altitude mode btfsc realdive ; dive longer then one minute? bra set_dive_modes0 ; Yes -> this is a real dive -> Use start_dive_threshold or ascend movlw HIGH high_altitude_dive_threshold movwf sub_a+1 movlw LOW high_altitude_dive_threshold movwf sub_a+0 bra set_dive_modes1 set_powersafe: movlw color_code_battery_low+1; [%] cpfslt batt_percent return movlw d'7' ; Type of Alarm (Battery Low) movwf AlarmType ; Copy to Alarm Register bsf event_occured ; Set Event Flag movlw .0 movff WREG,opt_brightness ; Set Brightness to ECO return ; return calc_average_depth: btfsc reset_average_depth ; Reset the Average depth? rcall reset_average1 ; Reset the resettable average depth ; 1. Add new 2xdepth to the Sum of depths registers SAFE_2BYTE_COPY rel_pressure, xB ; Buffer... bcf STATUS,C rlcf xB+0,F rlcf xB+1,F ; x2 movf xB+0,w addwf average_depth_hold+0,F movf xB+1,w addwfc average_depth_hold+1,F movlw d'0' addwfc average_depth_hold+2,F addwfc average_depth_hold+3,F ; Will work up to 9999mbar*60*60*24=863913600mbar ; Do the same for the _total registers (Non-Resettable) movf xB+0,w addwf average_depth_hold_total+0,F movf xB+1,w addwfc average_depth_hold_total+1,F movlw d'0' addwfc average_depth_hold_total+2,F addwfc average_depth_hold_total+3,F ; Will work up to 9999mbar*60*60*24=863913600mbar ; 2. Compute Average Depth on base of average_divesecs:2 movff average_divesecs+0,xB+0 movff average_divesecs+1,xB+1 ; Copy movff average_depth_hold+0,xC+0 movff average_depth_hold+1,xC+1 movff average_depth_hold+2,xC+2 movff average_depth_hold+3,xC+3 call div32x16 ; xC:4 / xB:2 = xC+3:xC+2 with xC+1:xC+0 as remainder movff xC+0,avg_rel_pressure+0 movff xC+1,avg_rel_pressure+1 btfss divemode2 ; displayed divetime is running? return ; No (e.g. too shallow) ; 3. Compute Total Average Depth on base of total_divetime_seconds:2 movff total_divetime_seconds+0,xB+0 movff total_divetime_seconds+1,xB+1 ; Copy movff average_depth_hold_total+0,xC+0 movff average_depth_hold_total+1,xC+1 movff average_depth_hold_total+2,xC+2 movff average_depth_hold_total+3,xC+3 call div32x16 ; xC:4 / xB:2 = xC+3:xC+2 with xC+1:xC+0 as remainder movff xC+0,avg_rel_pressure_total+0 movff xC+1,avg_rel_pressure_total+1 return reset_average1: clrf average_depth_hold+0 clrf average_depth_hold+1 clrf average_depth_hold+2 clrf average_depth_hold+3 ; Clear average depth register movlw d'2' movwf average_divesecs+0 clrf average_divesecs+1 bcf reset_average_depth ; Clear flag return test_switches_divemode: ; checks switches in divemode btfsc divemode_menu ; Divemode menu shown? bra test_switches_divemode_menu ; Yes, use menu processor btfsc switch_left goto menuview_toggle ; Menu or Simulator tasks; and return...; bra test_switches_divemode2 ; Enter button pressed, check if we need to do something btfss switch_right return ; No button press tstfsz menupos2 ; any option shown? bra test_switches_divemode1 ; Yes, do option tasks bsf toggle_customview ; No, toggle custom view return test_switches_divemode_menu: btfsc switch_left bra test_switches_divemode_menu2 ; Move cursor btfsc switch_right bra test_switches_divemode_menu3 ; Enter submenu or do something return ; No button press test_switches_divemode_menu1: clrf menupos test_switches_divemode_menu2: incf menupos,F incf menupos4,W ; menupos4+1 -> WREG cpfslt menupos ; >menupos4 (Set in menu_processor.asm)? bra test_switches_divemode_menu1; > Yes, set to 1 call TFT_divemode_menu_cursor ; Update the cursor bcf switch_left movlw divemode_menu_timeout ; Reload timeout movwf timeout_counter3 ; timeout for divemode menu return test_switches_divemode_menu3: ; Enter submenu or do something bcf switch_right ; decf menupos,F ; menu_processor needs 0-5... extern do_line_menu goto do_line_menu ; Warning! Trashes STKPTR and returns to diveloop_loop4: test_switches_divemode1: bcf switch_right movlw divemode_menuview_timeout movwf timeout_counter3 ; Reload timeout movff menupos2,WREG ; menupos2 holds number of customview/divemode menu function dcfsnz WREG,F bra divemode_option_gaschange ; Switch to the indicated "better gas" dcfsnz WREG,F bra divemode_option0 ; Start/Setup Divemode menu dcfsnz WREG,F bra divemode_option1 ; Quit Simulation? dcfsnz WREG,F bra divemode_option2 ; Descent 1m dcfsnz WREG,F bra divemode_option3 ; Ascend 1m dcfsnz WREG,F bra divemode_option4 ; Quit Apnoe mode dcfsnz WREG,F bra divemode_option5 ; Reset Stopwatch (In Gauge mode) dcfsnz WREG,F bra divemode_option6 ; +5mins simulation dcfsnz WREG,F bra divemode_option7 ; Store heading return ;test_switches_divemode2: ; goto menuview_toggle ; Menu or Simulator tasks; and return... ; return gas_switched_common: bcf divemode_gaschange ; Clear flag tstfsz menupos ; menupos=0? bra $+4 ; No return ; Yes, do not switch gas (There is no Gas #0 !) decf menupos,W ; 1-5 -> 0-4 btfss FLAG_ccr_mode ; Choose OC Gases rcall setup_gas_registers ; With WREG=Gas 0-4 decf menupos,W ; 1-5 -> 0-4 btfsc FLAG_ccr_mode ; Choose CC Diluents rcall setup_dil_registers ; With WREG=Gas 0-4 decf menupos,W ; 1-5 -> 0-4 btfsc FLAG_pscr_mode ; Choose CC Diluents rcall setup_dil_registers ; With WREG=Gas 0-4 decf menupos,W ; 1-5 -> 0-4 btfsc is_bailout ; Choose OC Bailouts (OC Gases) rcall setup_gas_registers ; With WREG=Gas 0-4 call TFT_active_gas_divemode ; Display gas/Setpoint clrf WREG movff WREG,char_O_deco_status ; Restart decoplan computation ; Set flags for profile recording bsf event_occured ; Set global event byte btfsc is_bailout ; Choose OC Bailouts (OC Gases) bsf bailoutgas_event ; Bailout gas change btfss is_bailout ; Choose OC Bailouts (OC Gases) bsf stored_gas_changed ; OC gas change return global setup_gas_registers setup_gas_registers: ; With WREG=Gas 0-4 lfsr FSR1,opt_gas_O2_ratio+0 movff PLUSW1,char_I_O2_ratio ; O2 (For ppO2 calculations) lfsr FSR1,opt_gas_He_ratio+0 movff PLUSW1,char_I_He_ratio ; He incf WREG,W ; Gas# 1-5 movff WREG,char_I_current_gas ; Set gas movff WREG,active_gas ; Set for logbook and display banksel char_I_O2_ratio movf char_I_O2_ratio,W ; Add O2... addwf char_I_He_ratio,W ; ...and He... sublw .100 ; ...subtract both from 100 movwf char_I_N2_ratio ; -> N2! banksel common return global setup_dil_registers setup_dil_registers: ; With WREG=dil 0-4 btfsc is_bailout return ; Ignore in bailout lfsr FSR1,opt_dil_O2_ratio+0 movff PLUSW1,char_I_O2_ratio ; O2 (For ppO2 calculations) lfsr FSR1,opt_dil_He_ratio+0 movff PLUSW1,char_I_He_ratio ; He incf WREG,W ; Gas# 1-5 movff WREG,char_I_current_gas ; Set gas movff WREG,active_gas ; Set for logbook and display movff WREG,active_diluent ; As a backup when switching back from Bailout to CCR banksel char_I_O2_ratio movf char_I_O2_ratio,W ; Add O2... addwf char_I_He_ratio,W ; ...and He... sublw .100 ; ...subtract both from 100 movwf char_I_N2_ratio ; -> N2! banksel common return divemode_option_gaschange: ; Switch to the better gas movff better_gas_number,menupos; 1-5 bsf divemode_gaschange ; Change the gas in the dive mode loop... call menuview_toggle_reset ; Reset to zero (Zero=no menuview) bcf better_gas_available ; Clear flag immediately return divemode_option0: ; Start/Setup Divemode menu call TFT_clear_divemode_menu ; Clear menu area bcf menuview extern do_main_divemenu call do_main_divemenu global divemode_option0_return divemode_option0_return: ; movlw .1 ; movwf menupos ; Set to first option in divemode menu call TFT_divemode_menu_cursor; Show the cursor movlw divemode_menu_timeout movwf timeout_counter3 ; timeout for divemode menu bsf divemode_menu ; Set flag clrf menupos2 ; Clear option counter bra diveloop_loop4 ; Goto back to diveloop (Menuprocessor trashes STKPTR!) divemode_option4: movlw d'58' ; two seconds left movwf timeout_counter movlw apnoe_timeout-1 ; apnoe timeout [min] movwf apnoe_timeout_counter btfss simulatormode_active ; in simulator mode? return ; No divemode_option1: ; Quit simulation mode banksel isr_backup movlw low .1000 movwf sim_pressure+0 movlw high .1000 movwf sim_pressure+1 ; Set to 0m -> End of Dive banksel common call menuview_toggle_reset ; Reset to zero (Zero=no menuview) btfss FLAG_apnoe_mode ; In Apnoe mode? return ; No movlw d'58' ; two seconds left movwf timeout_counter movlw apnoe_timeout-1 ; apnoe timeout [min] movwf apnoe_timeout_counter return divemode_option3: ; minus 1m banksel isr_backup movlw d'100' subwf sim_pressure+0 movlw .0 subwfb sim_pressure+1 rcall divemode_simulator_check_limits banksel common return divemode_option2: ; plus 1m banksel isr_backup movlw d'100' addwf sim_pressure+0 movlw .0 addwfc sim_pressure+1 rcall divemode_simulator_check_limits banksel common return divemode_option5: call menuview_toggle_reset ; Reset to zero (Zero=no menuview) bsf reset_average_depth ; Set Flag return divemode_option6: bcf divemode2 ; Stop divetime movlw .5 addwf divemins+0,F movlw .0 addwfc divemins+1,F ; Add 5 mins movlw LOW (.5*.60) addwf average_divesecs+0,F movlw HIGH (.5*.60) addwfc average_divesecs+1,F ; Add 5*60 seconds movlw LOW (.5*.60) addwf total_divetime_seconds+0,F movlw HIGH (.5*.60) addwfc total_divetime_seconds+1,F ; Add 5*60 seconds ; 1. Add 300xdepth to the Sum of depths registers SAFE_2BYTE_COPY rel_pressure, xB ; Buffer... movlw LOW (.5*.60) movwf xA+0 movlw HIGH (.5*.60) movwf xA+1 call mult16x16 ;xA*xB=xC movf xC+0,w addwf average_depth_hold+0,F movf xC+1,w addwfc average_depth_hold+1,F movf xC+2,w addwfc average_depth_hold+2,F movf xC+3,w addwfc average_depth_hold+3,F ; Will work up to 9999mbar*60*60*24=863913600mbar ; Do the same for the _total registers (Non-Resettable) movf xC+0,w addwf average_depth_hold_total+0,F movf xC+1,w addwfc average_depth_hold_total+1,F movf xC+2,w addwfc average_depth_hold_total+2,F movf xC+3,w addwfc average_depth_hold_total+3,F ; Will work up to 9999mbar*60*60*24=863913600mbar movlw .5 movwf up ; counter ; 1min mode divemode_option6_2: movlw .1 movff WREG,char_I_step_is_1min ; Force 1min mode clrf TMR5L clrf TMR5H ; 30,51757813µs/bit in TMR5L:TMR5H call deco_calc_hauptroutine ; calc_tissue movlb .1 decfsz up,F ; Done? bra divemode_option6_2 ; Not yet bsf divemode2 ; continue divetime goto menuview_toggle_reset ; and return... divemode_option7: ; Store heading for compass view movff compass_heading_shown+0,compass_bearing+0 movff compass_heading_shown+1,compass_bearing+1 bsf compass_bearing_set ; set flag goto menuview_toggle_reset ; Done and return... divemode_simulator_check_limits: ; Check limits (150m and 0m) movlw LOW d'16000' ; Compare to 16bar=16000mbar (150m). subwf sim_pressure+0,W movlw HIGH d'16000' subwfb sim_pressure+1,W bnc divemode_simulator_check_limits2 ; No-carry = borrow = not deeper ; Too deep, limit to 150m movlw LOW d'16000' movwf sim_pressure+0 movlw HIGH d'16000' movwf sim_pressure+1 return divemode_simulator_check_limits2: movlw LOW d'1000' ; Compare to 1bar == 0m == 1000 mbar. subwf sim_pressure+0,W movlw HIGH d'1000' subwfb sim_pressure+1,W btfsc STATUS,C ; No-carry = borrow = not deeper. return ; Deeper than 0m == Ok. ; Too shallow, limit to 0m movlw LOW d'1000' movwf sim_pressure+0 movlw HIGH d'1000' movwf sim_pressure+1 return ;============================================================================= ; Compare all enabled gas in list, to see if a better one is available. ; ; Output: better_gas_available, better_gas_number ; check_gas_change: ; Checks if a better gas should be selected (by user) bcf better_gas_available ;=1: A better gas is available and a gas change is advised in divemode clrf better_gas_number ; Clear better gas register SAFE_2BYTE_COPY rel_pressure,xA movlw d'100' movwf xB+0 clrf xB+1 call div16x16 ; compute depth in full m -> result in xC+0 btfsc FLAG_ccr_mode ; In PSCR mode... bra check_gas_change2 ; Yes, check for diluents btfss FLAG_ccr_mode ; In CCR mode... bra check_gas_change_OC_bail; No, check for OC or bailout check_gas_change2: btfsc is_bailout ; Bailout? bra check_gas_change_OC_bail; Yes, check for OC or bailout ; Check Diluents bsf ccr_diluent_setup ; in CCR menus movlw .0 rcall check_dil_common ; With Gas 0-4 in WREG movlw .1 rcall check_dil_common ; With Gas 0-4 in WREG movlw .2 rcall check_dil_common ; With Gas 0-4 in WREG movlw .3 rcall check_dil_common ; With Gas 0-4 in WREG movlw .4 rcall check_dil_common ; With Gas 0-4 in WREG bra check_gas_change_exit check_gas_change_OC_bail: bcf ccr_diluent_setup ; in OC menus movlw .0 rcall check_gas_common ; With Gas 0-4 in WREG movlw .1 rcall check_gas_common ; With Gas 0-4 in WREG movlw .2 rcall check_gas_common ; With Gas 0-4 in WREG movlw .3 rcall check_gas_common ; With Gas 0-4 in WREG movlw .4 rcall check_gas_common ; With Gas 0-4 in WREG ; bra check_gas_change_exit check_gas_change_exit: btfss better_gas_available ; Is a better gas available bcf blinking_better_gas ; No, Clear blinking flag btfss better_gas_available ; Is a better gas available clrf better_gas_number ; No, Clear better_gas_number (For gaslist display) goto TFT_active_gas_divemode ; Display gas/Setpoint and return... check_gas_common: ; With Gas 0-4 in WREG btfsc better_gas_available ; Better Gas already found? return ; Yes, return lfsr FSR1,opt_gas_type ; 0=Disabled, 1=First, 2=Travel, 3=Deco btfss PLUSW1,0 ; Test for Bit0 and 1 -> type=3 -> Deco return ; No btfss PLUSW1,1 ; Test for Bit0 and 1 -> type=3 -> Deco return ; No incf WREG,W ; 1-5 cpfseq active_gas ; is this gas currently selected? bra check_gas_common2 ; No return ; Yes, skip test for active gas check_gas_common2: decf WREG,W ; 0-4 movwf hi ; Save tested gas 0-4 lfsr FSR1,opt_OC_bail_gas_change movff PLUSW1,lo ; Change depth into lo movlw minimum_change_depth cpfsgt lo ; Change depth>minimum_change_depth? return ; No, Change depth not deep enough, skip! movf xC+0,W ; load depth in m into WREG cpfsgt lo ; gas_change_depth < current depth? bra check_gas_common3 ; No, check if we are within the better_gas_window_pos window incf hi,W ; 1-5 movwf better_gas_number ; number (1-5) of the "better gas" in divemode, =0: no better gas available movlw better_gas_window_neg subwf lo,W ; Change depth-better_gas_window_neg cpfslt xC+0 ; current depth<Change depth-better_gas_window_neg? bsf better_gas_available ;=1: A better gas is available and a gas change is advised in divemode return check_gas_common3: incf hi,W ; 1-5 movwf better_gas_number ; number (1-5) of the "better gas" in divemode, =0: no better gas available movlw better_gas_window_pos addwf lo,W ; Change depth+better_gas_window_pos cpfsgt xC+0 ; current depth>Change depth+better_gas_window_pos? bra check_gas_common4 ; Ok, now check the better gas ppO2<opt_ppO2_max return check_gas_common4: movf hi,W ; 0-4 lfsr FSR1,char_I_deco_N2_ratio movff PLUSW1,lo ; N2 ratio into lo lfsr FSR1,char_I_deco_He_ratio movff PLUSW1,xB+0 ; He ratio into xB+0 movf xB+0,W addwf lo,F movlw .101 bcf STATUS,C subfwb lo,F ; O2 ratio in lo SAFE_2BYTE_COPY amb_pressure, xA movlw d'10' movwf xB+0 clrf xB+1 call div16x16 ; xC=p_amb/10 movff xC+0,xA+0 movff xC+1,xA+1 movff lo,xB+0 ; =O2 ratio clrf xB+1 call mult16x16 ; lo * p_amb/10 ; Check very high ppO2 manually tstfsz xC+2 ; char_I_O2_ratio * p_amb/10 > 65536, ppO2>6,55bar? return ; Done. ; Check if ppO2>3,30bar btfsc xC+1,7 return ; Done. ; ; Check for low ppo2 ; movff xC+0,sub_b+0 ; movff xC+1,sub_b+1 ; movff opt_ppO2_min,WREG ; mullw d'100' ; opt_ppO2_min*100 ; movff PRODL,sub_a+0 ; movff PRODH,sub_a+1 ; call subU16 ; btfss neg_flag ; return ; Done (Too low). ;check if we are within our warning thresholds! movff xC+0,sub_b+0 movff xC+1,sub_b+1 movff opt_ppO2_max,WREG ; PPO2 Max for MOD calculation and color coding in divemode addlw .1 ; e.g. >1.60 mullw d'100' ; opt_ppO2_max*100 movff PRODL,sub_a+0 movff PRODH,sub_a+1 call subU16 btfss neg_flag bsf better_gas_available ;=1: A better gas is available and a gas change is advised in divemode return ; Done. check_dil_common: ; With Dil 0-4 in WREG btfsc better_gas_available ; Better Diluent already found? return ; Yes, return lfsr FSR1,opt_dil_type ; 0=Disabled, 1=First, 2=Normal tstfsz PLUSW1 ; =0? bra check_dil_common1 ; No return ; Yes, skip inactive diluents for test check_dil_common1: incf WREG,W ; 1-5 cpfseq active_gas ; is this diluent currently selected? bra check_dil_common2 ; No return ; Yes, skip test for active diluent check_dil_common2: decf WREG,W ; 0-4 movwf hi ; Save tested diluent 0-4 lfsr FSR1,char_I_dil_change movff PLUSW1,lo ; Change depth into lo movlw minimum_change_depth cpfsgt lo ; Change depth>minimum_change_depth? return ; No, Change depth not deep enough, skip! movf xC+0,W ; load depth in m into WREG cpfsgt lo ; gas_change_depth < current depth? return ; No, check next gas incf hi,W ; 1-5 movwf better_gas_number ; number (1-5) of the "better gas" in divemode, =0: no better gas available movlw better_gas_window_neg subwf lo,W ; Change depth-better_gas_window_neg cpfslt xC+0 ; current depth<Change depth-better_gas_window_neg? bsf better_gas_available ;=1: A better gas is available and a gas change is advised in divemode return ;============================================================================= ; Check for Auto-SP ; check_dive_autosp: ; Check for Auto-SP movff opt_ccr_mode,WREG ; =0: Fixed SP, =1: Sensor, =2: Auto SP sublw .2 ; opt_ccr_mode = 2 (Auto SP)? bz check_dive_autosp2 ; Yes, check return ; No, return for Sensor or Fixed mode check_dive_autosp2: SAFE_2BYTE_COPY rel_pressure,xA movlw d'100' movwf xB+0 clrf xB+1 call div16x16 ; compute depth in full m -> result in xC+0 ; Check SP2 btfsc sp2_switched ;=1: This setpoint has been autoselected already bra check_dive_autosp3 ; Skip check movff char_I_setpoint_change+1,lo ; Get depth in m tstfsz lo ; =0? bra $+4 ; No, continue bra check_dive_autosp3 ; Skip check decf lo,W ; -1 -> WREG cpfsgt xC+0 ; Compare with depth bra check_dive_autosp3 ; lower depth, do not switch ; auto switch to SP2 movff char_I_setpoint_cbar+1, char_I_const_ppO2 ; Use SetPoint rcall xmit_sp_set_flag bsf sp2_switched ; Set flag check_dive_autosp3: ; Check SP3 btfsc sp3_switched ;=1: This setpoint has been autoselected already bra check_dive_autosp4 ; Skip check movff char_I_setpoint_change+2,lo ; Get depth in m tstfsz lo ; =0? bra $+4 ; No, continue bra check_dive_autosp4 ; Skip check decf lo,W ; -1 -> WREG cpfsgt xC+0 ; Compare with depth bra check_dive_autosp4 ; lower depth, do not switch ; auto switch to SP3 movff char_I_setpoint_cbar+2, char_I_const_ppO2 ; Use SetPoint rcall xmit_sp_set_flag bsf sp3_switched ; Set flag check_dive_autosp4: ; Check SP4 btfsc sp4_switched ;=1: This setpoint has been autoselected already bra check_dive_autosp5 ; Skip check movff char_I_setpoint_change+3,lo ; Get depth in m tstfsz lo ; =0? bra $+4 ; No, continue bra check_dive_autosp5 ; Skip check decf lo,W ; -1 -> WREG cpfsgt xC+0 ; Compare with depth bra check_dive_autosp5 ; lower depth, do not switch ; auto switch to SP4 movff char_I_setpoint_cbar+3, char_I_const_ppO2 ; Use SetPoint rcall xmit_sp_set_flag bsf sp4_switched ; Set flag check_dive_autosp5: ; Check SP5 btfsc sp5_switched ;=1: This setpoint has been autoselected already bra check_dive_autosp6 ; Skip check movff char_I_setpoint_change+4,lo ; Get depth in m tstfsz lo ; =0? bra $+4 ; No, continue bra check_dive_autosp6 ; Skip check decf lo,W ; -1 -> WREG cpfsgt xC+0 ; Compare with depth bra check_dive_autosp6 ; lower depth, do not switch ; auto switch to SP5 movff char_I_setpoint_cbar+4, char_I_const_ppO2 ; Use SetPoint rcall xmit_sp_set_flag bsf sp5_switched ; Set flag check_dive_autosp6: return xmit_sp_set_flag: movff char_I_const_ppO2,WREG call transmit_setpoint ; Transmit current setpoint from WREG (in cbar) to external electronics bsf setpoint_changed ; Set flag (For profile) bsf event_occured ; Set global event byte return ;============================================================================= ; Setup everything to enter divemode. ; dive_boot_oc: extern get_first_gas_to_WREG call get_first_gas_to_WREG ; Gets first gas (0-4) into WREG movff WREG,char_I_first_gas ; Copy for compatibility rcall setup_gas_registers ; With WREG=Gas 0-4 banksel char_I_first_gas incf char_I_first_gas,F ; 0-4 -> 1-5 banksel common return dive_boot_cc: bcf is_bailout ; =1: Bailout bcf setpoint_fallback ; =1: Fallback to SP1 due to external O2 sensor failure bcf blinking_setpoint ; Reset blinking SP flag call compute_ppo2 ; compute mv_sensorX and ppo2_sensorX arrays bsf voting_logic_sensor1 bsf voting_logic_sensor2 bsf voting_logic_sensor3 call divemode_setup_sensor_values ; setup sensor values ; Setup first SP for Fixed or Auto mode movff opt_ccr_mode,WREG ; =0: Fixed SP, =1: Sensor, =2: Auto SP sublw .1 ; opt_ccr_mode = 1 (Sensor)? movff char_I_setpoint_cbar+0,char_I_const_ppO2 ; No, setup fixed Setpoint (Always start with SP1) movff char_I_const_ppO2,WREG call transmit_setpoint ; Transmit current setpoint from WREG (in cbar) to external electronics bsf setpoint_changed ; Set flag (For profile) bcf sp2_switched ; =1: This setpoint has been autoselected already bcf sp3_switched ; =1: This setpoint has been autoselected already bcf sp4_switched ; =1: This setpoint has been autoselected already bcf sp5_switched ; =1: This setpoint has been autoselected already extern get_first_dil_to_WREG call get_first_dil_to_WREG ; Gets first gas (0-4) into WREG movff WREG,char_I_first_gas ; Copy for compatibility rcall setup_dil_registers ; With WREG=Gas 0-4 banksel char_I_first_gas incf char_I_first_gas,F ; 0-4 -> 1-5 banksel common goto calc_deko_divemode_sensor ; External sensor stuff and return... diveloop_boot: call restart_set_modes_and_flags call I2C_sleep_accelerometer ; Stop accelerometer call I2C_sleep_compass ; Stop compass clrf WREG movff WREG,max_pressure+0 ; clear some variables movff WREG,max_pressure+1 bcf use_agf ; Start with normal GF set bcf divemode_menu ; clear divemode menu flag movlw d'1' movwf apnoe_max_pressure+0 clrf apnoe_max_pressure+1 ; clrf apnoe_surface_mins ; clrf apnoe_surface_secs clrf apnoe_mins clrf divemins+0 clrf divemins+1 ; Copy date and time for logbook movff year,start_year movff month,start_month movff day,start_day movff hours,start_hours movff mins,start_mins bcf no_more_divesecs ; =1: Do no longer show seconds in divemode bcf divemode_menu_active clrf menupos clrf menupos2 ; Reset to zero (Zero=no premenu or simulator task) btfss FLAG_ccr_mode rcall dive_boot_oc btfsc FLAG_ccr_mode rcall dive_boot_cc btfsc FLAG_pscr_mode rcall dive_boot_cc ; Copy opt_dil_types into backup (For "lost gas" feature) movff opt_dil_type+0,opt_dil_type_backup+0 ; 0=Disabled, 1=First, 2=Normal movff opt_dil_type+1,opt_dil_type_backup+1 ; 0=Disabled, 1=First, 2=Normal movff opt_dil_type+2,opt_dil_type_backup+2 ; 0=Disabled, 1=First, 2=Normal movff opt_dil_type+3,opt_dil_type_backup+3 ; 0=Disabled, 1=First, 2=Normal movff opt_dil_type+4,opt_dil_type_backup+4 ; 0=Disabled, 1=First, 2=Normal ; Copy opt_gas_types into backup (For "lost gas" feature) movff opt_gas_type+0,opt_gas_type_backup+0 ; 0=Disabled, 1=First, 2=Travel, 3=Deco movff opt_gas_type+1,opt_gas_type_backup+1 ; 0=Disabled, 1=First, 2=Travel, 3=Deco movff opt_gas_type+2,opt_gas_type_backup+2 ; 0=Disabled, 1=First, 2=Travel, 3=Deco movff opt_gas_type+3,opt_gas_type_backup+3 ; 0=Disabled, 1=First, 2=Travel, 3=Deco movff opt_gas_type+4,opt_gas_type_backup+4 ; 0=Disabled, 1=First, 2=Travel, 3=Deco ; Also copy change depths into backup (For "lost gas" feature) movff opt_OC_bail_gas_change+0,opt_OC_bail_gas_change_backup+0 ; Gas change depths OC/Bailout movff opt_OC_bail_gas_change+1,opt_OC_bail_gas_change_backup+1 ; Gas change depths OC/Bailout movff opt_OC_bail_gas_change+2,opt_OC_bail_gas_change_backup+2 ; Gas change depths OC/Bailout movff opt_OC_bail_gas_change+3,opt_OC_bail_gas_change_backup+3 ; Gas change depths OC/Bailout movff opt_OC_bail_gas_change+4,opt_OC_bail_gas_change_backup+4 ; Gas change depths OC/Bailout bcf better_gas_available ;=1: A better gas is available and a gas change is advised in divemode clrf better_gas_number ; Clear better gas register bcf show_safety_stop ;=1: Show the safety stop clrf safety_stop_countdown ; Clear count-down clrf samplesecs clrf apnoe_timeout_counter ; timeout in minutes clrf timeout_counter ; takes care of the timeout (Low byte) clrf timeout_counter2 ; takes care of the timeout (High byte) clrf AlarmType ; Clear all alarms bcf event_occured ; clear flag clrf total_divetime_seconds+1 clrf average_depth_hold_total+0 clrf average_depth_hold_total+1 clrf average_depth_hold_total+2 clrf average_depth_hold_total+3 ; Clear Non-Resettable Average rcall reset_average1 ; Reset the resettable average depth bcf decostop_active bcf better_gas_available ;=1: A better gas is available and a gas change is advised in divemode call ghostwriter_short_header ; Write short header with divenumber into profile memory btfsc simulatormode_active bra diveloop_boot_1 ; Normal mode = Surface pressure is the pressure 30mn before dive. SAFE_2BYTE_COPY last_surfpressure_30min, int_I_pres_surface ;copy surfacepressure to deco routine SAFE_2BYTE_COPY last_surfpressure_30min, last_surfpressure ;copy surfacepressure to last_surfpressure for correct depth bra diveloop_boot_2 diveloop_boot_1: ; Simulator mode: Surface pressure is 1bar. movlw LOW .1000 movff WREG,int_I_pres_surface+0 ; LOW copy surfacepressure to deco routine movlw HIGH .1000 movff WREG,int_I_pres_surface+1 ; HIGH copy surfacepressure to deco routine diveloop_boot_2: SAFE_2BYTE_COPY temperature,minimum_temperature ; Reset Min-Temp registers ; Init profile recording parameters movff samplingrate,samplesecs_value ; to avoid EEPROM access in the ISR movlw div_temperature movwf divisor_temperature ; load divisors for profile storage movlw div_deco movwf divisor_deco movlw div_gf movwf divisor_gf movlw div_ppo2_sensors movwf divisor_ppo2_sensors movlw div_decoplan movwf divisor_decoplan movlw div_cns movwf divisor_cns movlw div_tank movwf divisor_tank btfss FLAG_apnoe_mode ; In Apnoe mode? bra divemode_boot1 ; Overwrite some parameters in Apnoe mode.... movlw samplingrate_apnoe movwf samplesecs_value ; to avoid EEPROM access in the ISR divemode_boot1: btfsc FLAG_ccr_mode ; =1: CCR mode (Fixed ppO2 or Sensor) active bra divemode_boot2 btfsc FLAG_pscr_mode bra divemode_boot2 ; in OC Mode, disable ppO2 logging movlw .0 movwf divisor_ppo2_sensors divemode_boot2: bcf LEDg bcf LEDr bcf realdive btfss simulatormode_active ; do not disable in simulator mode! call disable_rs232 ; Disable RS232 btfsc enable_screen_dumps ; =1: Ignore vin_usb, wait for "l" command (Screen dump) call enable_rs232 ; Also sets to speed_normal ... ; Reset divetime seconds movlw .2 ; Start at 2seconds movwf total_divetime_seconds+0 movwf divesecs movwf apnoe_secs bsf divemode2 ; displayed divetime is running (Divetime starts HERE) movff int_O_CNS_fraction+0,CNS_start+0 movff int_O_CNS_fraction+1,CNS_start+1 ; Save CNS value at beginning of dive movff char_O_relative_gradient_GF,GF_start ; Save GF value at beginning of dive return ; Done with divemode boot divemode_check_for_warnings: movlw .2 cpfsgt warning_counter ; only two warnings active? bra divemode_check_for_warnings1 ; Yes, update every second btfss secs,0 ; Every two seconds... return btfss secs,1 ; Every four seconds... return divemode_check_for_warnings1: movf warning_counter_backup,W cpfseq warning_counter ; warning_counter_backup = warning_counter? call TFT_clear_warning_text ; No, clear all warnings movff warning_counter,warning_counter_backup ; copy warning_counter bcf warning_active ; Clear flag clrf warning_counter ; Clear counter ; Warnings for all modes call check_warn_battery ; Check if the battery level should be displayed/warned call check_divetimeout ; Not actually a warning. Check and show the divemode timeout btfsc FLAG_apnoe_mode ; Done for Apnoe or Gauge mode bra divemode_check_for_warnings2 btfsc FLAG_gauge_mode ; Done for Apnoe or Gauge mode bra divemode_check_for_warnings2 ; Warnings only in deco modes btfss FLAG_ccr_mode ; Don't check in CCR mode rcall check_ppO2 ; check ppO2 and displays warning, if required ; mH: PSCR handling missing here (Not critical but should be done...) btfsc is_bailout ; But check in Bailout case... rcall check_ppO2 ; check ppO2 and displays warning, if required rcall check_cns_violation ; Check CNS value and display it, if required btfsc decostop_active ; In deco mode? rcall check_and_store_gf_violation ; Yes, Sets warnings, if required btfsc decostop_active ; In deco mode? call TFT_ftts ; Show @+x time btfsc use_agf ; In aGF mode? rcall warn_agf ; Yes, show a warning for it btfsc setpoint_fallback ; =1: Fallback to SP1 due to external O2 sensor failure rcall warn_fallback ; Show the warning divemode_check_for_warnings2: ; Display the warning icon? btfsc warning_active ; Any warning active? call TFT_divemode_warning ; Yes btfss warning_active ; Any warning active? call TFT_divemode_warning_clear ; No, clear warning icon ; Setup warning_page number incf warning_page,F bcf STATUS,C rlcf warning_page,W ; *2 cpfsgt warning_counter ; > warning_counter clrf warning_page ; No, clear ; Clear 2nd row of warnings if there is nothing to show (on this page) btfss second_row_warning ; =1: The second row contains a warning call TFT_clear_warning_text_2nd_row ; No, clear this row return ; Done. global check_warn_battery check_warn_battery: movff batt_percent,lo movlw battery_show_level+1 cpfslt lo return ; No Display, no warning ; Display Battery, but warn? movff batt_percent,lo movlw color_code_battery_low+1 cpfsgt lo ; bsf warning_active ; Set Warning flag movlw .4 cpfseq menupos3 ; battery shown in Custom View 4? bra check_warn_battery2 ; No return ; Yes, do not show twice (in custom view and in warning area) check_warn_battery2: incf warning_counter,F ; increase counter call TFT_update_batt_percent_divemode ; Show percent return check_divetimeout: btfsc divemode2 return ; displayed divetime is not running incf warning_counter,F ; increase counter goto TFT_divetimeout ; Show timeout counter (and return) check_ppO2: ; check current ppO2 and display warning if required btfss FLAG_pscr_mode bra check_ppO2_non_pscr ; Non-PSCR modes... ; in PSCR mode btfsc is_bailout bra check_ppO2_non_pscr ; Non-PSCR modes... call compute_pscr_ppo2 ; pSCR ppO2 into sub_c:2 movff sub_c+0,xA+0 movff sub_c+1,xA+1 movlw d'100' movwf xB+0 clrf xB+1 call div16x16 ; /100 tstfsz xC+1 ; Is ppO2 > 2.55bar ? setf xC+0 ; yes: bound to 2.55... better than wrap around. movff xC+0,char_I_actual_ppO2 ; copy last ppO2 to buffer register (for pSCR CNS) clrf xC+2 clrf xC+3 movff sub_c+0,xC+0 movff sub_c+1,xC+1 ; copy for comptibility bra check_ppO2_check check_ppO2_non_pscr: SAFE_2BYTE_COPY amb_pressure, xA movlw d'10' movwf xB+0 clrf xB+1 call div16x16 ; xC=p_amb/10 movff xC+0,xA+0 movff xC+1,xA+1 movff char_I_O2_ratio,xB+0 ; =O2 ratio clrf xB+1 call mult16x16 ; char_I_O2_ratio * p_amb/10 check_ppO2_check: ; Check very high ppO2 manually tstfsz xC+2 ; char_I_O2_ratio * p_amb/10 > 65536, ppO2>6,55bar? bra check_ppO2_1 ; Yes, display Value! ; Check if ppO2>3,30bar btfsc xC+1,7 bra check_ppO2_1 ; Yes! ; Check for low ppo2 movff xC+0,sub_b+0 movff xC+1,sub_b+1 movff opt_ppO2_min,WREG mullw d'100' ; opt_ppO2_min*100 movff PRODL,sub_a+0 movff PRODH,sub_a+1 call subU16 btfsc neg_flag bra check_ppO2_0 ; Not too low ; ppO2 low rcall check_ppo2_display ; display if not already shown in custom view movlw d'4' ; Type of Alarm (ppO2 low) movwf AlarmType ; Copy to Alarm Register bsf event_occured ; Set Event Flag bsf warning_active ; Set Warning flag return ; Done. check_ppO2_0: ; Check if ppO2 should be displayed movlw .0 TSTOSS opt_showppo2 ; 0=no, 1=always show movlw ppo2_display_high mullw d'100' ; ppo2_display_high*100 movff PRODL,sub_a+0 movff PRODH,sub_a+1 call subU16 btfss neg_flag return ; No Display, no warning ; Display ppO2, but warn? rcall check_ppo2_display ; display if not already shown in custom view ;check if we are within our warning thresholds! movff xC+0,sub_b+0 movff xC+1,sub_b+1 movff opt_ppO2_max,WREG ; PPO2 Max for MOD calculation and color coding in divemode addlw .1 ; e.g. >1.60 mullw d'100' ; opt_ppO2_max*100 movff PRODL,sub_a+0 movff PRODH,sub_a+1 call subU16 btfss neg_flag return ; Done. Not too high movlw d'5' ; Type of Alarm (ppO2 high) movwf AlarmType ; Copy to Alarm Register bsf event_occured ; Set Event Flag bsf warning_active ; Set Warning flag return ; Done. check_ppO2_1: ; ppO2 very high rcall check_ppo2_display ; display if not already shown in custom view movlw d'5' ; Type of Alarm movwf AlarmType ; Copy to Alarm Register bsf event_occured ; Set Event Flag bsf warning_active ; Set Warning flag return ; Done. check_ppo2_display: movlw .9 cpfseq menupos3 ; ppO2 shown in Custom View 9? bra check_ppO2_a ; No return ; Yes, do not show twice (in custom view and in warning area) check_ppO2_a: movlw .11 cpfseq menupos3 ; ppO2 shown in Custom View 11? bra check_ppO2_b ; No return ; Yes, do not show twice (in custom view and in warning area) check_ppO2_b: movlw .12 cpfseq menupos3 ; ppO2 shown in Custom View 12? bra check_ppO2_c ; No return ; Yes, do not show twice (in custom view and in warning area) check_ppO2_c: incf warning_counter,F ; increase counter goto TFT_display_ppo2 ; Show ppO2 (and return) global check_cns_violation check_cns_violation: ; Check if CNS should be displayed movff int_O_CNS_fraction+1,lo ; copy into bank1 tstfsz lo ; >255% ? bra check_cns_violation2 ; Yes movff int_O_CNS_fraction+0,lo ; copy into bank1 movlw cns_warning_high ; cns_warning_high subwf lo,W btfsc STATUS,C bsf warning_active ; Set Warning flag movlw cns_display_high ; cns_display_high subwf lo,W btfss STATUS,C return ; No Display, no warning ; Display CNS bra display_cns_violation check_cns_violation2: bsf warning_active ; Set Warning flag display_cns_violation: ; Show CNS if not shown in the custom view movlw .11 cpfseq menupos3 ; CNS shown in Custom View? bra display_cns_violation2 ; No return ; Yes, do not show twice (in custom view and in warning area) display_cns_violation2: incf warning_counter,F ; increase counter goto TFT_display_cns ; Show CNS (and return) global check_and_store_gf_violation check_and_store_gf_violation: movff char_O_gradient_factor,lo ; gradient factor absolute (Non-GF model) movff char_I_deco_model,hi decfsz hi,F ; jump over next line if char_I_deco_model == 1 movff char_O_relative_gradient_GF,lo ; gradient factor relative (GF model) movlw gf_warning_high cpfsgt lo bra check_and_store_gf_violation2 ; No warning movlw d'2' ; Type of Alarm movwf AlarmType ; Copy to Alarm Register bsf event_occured ; Set Event Flag bsf warning_active ; Set Warning flag check_and_store_gf_violation2: movlw gf_display_high cpfsgt lo return ; No Display, no warning ; Display GF incf warning_counter,F ; increase counter goto TFT_warning_gf ; Show GF Warning (and return) warn_agf: incf warning_counter,F ; increase counter goto TFT_warning_agf ; Show aGF warning (and return) warn_fallback: incf warning_counter,F ; increase counter bsf warning_active ; Set Warning flag goto TFT_warning_fallback ; Show fallback warning (and return) END