Mercurial > public > hwos_code
view src/divemode.asm @ 586:06642f6ffe59
2.97 release
author | heinrichsweikamp |
---|---|
date | Thu, 01 Mar 2018 11:12:47 +0100 |
parents | 6636cbe64c6d |
children | bf0c76e9b01b |
line wrap: on
line source
;============================================================================= ; ; File divemode.asm REFACTORED VERSION V2.98 ; ; 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" extern TFT_dive_compass_heading extern do_line_menu extern do_main_divemenu extern option_save_all extern init_recording_params ;---- Private local variables ------------------------------------------------- CBLOCK local1 ; max size is 16 Byte !!! apnoe_timeout_counter ; timeout counter for apnoe mode average_depth_hold:4 ; used in calculation of the average depth sensor_setpoint ; sensor ppo2 in 0.01bar for deco routine active_diluent ; backup of diluent gas for when switching back from bailout to CCR/pSCR loop average_depth_hold_total:4 ; used to calculate the average depth ENDC ; used: 11 byte, remaining: 5 byte 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) bsf FLAG_TFT_divemode_mask ; Display mask 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_start btfsc FLAG_gauge_mode ; Done for Apnoe or Gauge mode bra diveloop_loop_start bsf FLAG_TFT_display_ndl_mask ; display "NDL" ; +@5 init clrf WREG ; WAIT marker: display "---" movff WREG,char_I_sim_advance_time movff WREG,int_O_alternate_ascenttime+0 bsf WREG,int_not_yet_computed bsf WREG,int_invalid_flag movff WREG,int_O_alternate_ascenttime+1 diveloop_loop_start: btfsc FLAG_TFT_display_ndl_mask call TFT_display_ndl_mask diveloop_loop: ; The diveloop starts here btfss quarter_second_update bra diveloop_loop1 ; tasks any 1/4 second, any mode bcf quarter_second_update ; clear flag movlw .6 cpfseq menupos3 ; in compass view? bra diveloop_loop1 ; No, done. btfsc alternative_divelayout ; In alternative layout mode? bra diveloop_loop1 ; Yes, done. No Compass. ; TFT Output routines call TFT_dive_compass_heading ; Yes, update compass heading value bsf FLAG_TFT_temp_divemode ; Redraw temperature (is slightly affected from compass heading arrow) ; TFT Output routines diveloop_loop1: 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. ;bsf LEDg ; ### USE FOR DEBUG ONLY - RESETS RX CIRCUITRY ### ; display depth based on full seconds interval (nicer blinking) btfss alternative_divelayout rcall TFT_output4_normal btfsc alternative_divelayout rcall TFT_output4_alternative btfsc FLAG_apnoe_mode ; Only in apnoe mode bra diveloop_loop1_nonedeco ; One Second Tasks in Apnoe mode ; tasks any new second - only for deco modes diveloop_loop1_decomodes: bsf FLAG_TFT_divemins ; Display (new) divetime! btfsc show_safety_stop ; Show the safety stop? bsf FLAG_TFT_show_safety_stop ; Yes, show/delete if done. btfss alternative_divelayout rcall TFT_output1_normal btfsc alternative_divelayout rcall TFT_output1_alternative btfsc FLAG_ccr_mode ; in CCR mode... call check_dive_autosp ; ...check for Auto-SP call calc_deko_divemode ; calculate decompression and set resulting display flags btfss alternative_divelayout rcall TFT_output2_normal btfsc alternative_divelayout rcall TFT_output2_alternative call divemode_check_for_warnings ; Check for any warnings bra diveloop_loop2 ; Common Tasks ; tasks any new second - only for apnoe mode diveloop_loop1_nonedeco: rcall divemode_apnoe_tasks ; 1 sec. Apnoe tasks call customview_second ; Do every-second tasks for the custom view area ;bra diveloop_loop2 ; Common Tasks ; continue tasks any new second, any mode diveloop_loop2: rcall timeout_divemode ; ** menu timeout? ** This routine sets the required flags rcall set_dive_modes ; tests if depth > threshold rcall set_min_temp ; store min. temp if required (Future hardware will need this to be checked 1/second...) btfsc oneminupdate ; one minute tasks rcall update_divemode60 ; Update clock, etc. btfss alternative_divelayout rcall TFT_output3_normal btfsc alternative_divelayout rcall TFT_output3_alternative ;bcf LEDg ; ### USE FOR DEBUG ONLY - RESETS RX CIRCUITRY ### ; tasks any round, any mode diveloop_loop3: call test_switches_divemode ; Check switches in divemode global diveloop_loop4 diveloop_loop4: ; Menu-Exit returns here... btfsc divemode_menu ; in the big divemode menu? bra diveloop_loop4b ; YES - no space for CCR/pSCR info btfsc menuview ; NO - in the small yellow menu? bra diveloop_loop4b ; YES - no space for CCR/pSCR info btfsc alternative_divelayout ; NO - in the alternative layout? bra diveloop_loop4b ; YES - no space for CCR/pSCR info call TFT_show_mode_divemode ; NO - (re)write CCR/pSCR mode info to display diveloop_loop4b: btfsc toggle_customview ; Next view? call customview_toggle ; Yes, show next customview (and delete this flag) btfsc divemode_gaschange ; Gas switch flag set? call gas_switched_common ; YES btfsc toggle_gf ; Toggle GF/aGF? rcall divemodemode_togglegf ; YES btfsc FLAG_set_marker ; shall a marker be set? call set_logbook_marker ; YES btfsc store_sample ; store new sample? call store_dive_data ; Store profile data btfss divemode ; Dive finished? goto ghostwriter_end_dive ; Dive finished! btfsc pressure_refresh ; new pressure available? rcall set_max_depth ; update max. depth if required btfsc pressure_refresh ; new pressure available? bsf FLAG_TFT_depth ; Yes, update depth bcf pressure_refresh ; clear flag btfsc temp_changed bsf FLAG_TFT_temp_divemode ; Displays temperature ; display depth based on as-fast-as-possible (no nice blinking) ;btfss alternative_divelayout ;rcall TFT_output4_normal ;btfsc alternative_divelayout ;rcall TFT_output4_alternative 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_receive_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 ;-------------------------------------------------------------------------------------------------------- TFT_output1_normal: ; beginning of any new second - only for deco modes btfsc FLAG_TFT_divemode_mask call TFT_divemode_mask btfsc FLAG_TFT_divemins call TFT_divemins ; Display (new) divetime! call customview_second ; Do every-second tasks for the custom view area (In sync with the divetime) mH btfsc FLAG_TFT_show_safety_stop call TFT_show_safety_stop ; Show safety stop btfsc FLAG_TFT_clear_safety_stop call TFT_clear_safety_stop ; Clear safety stop return TFT_output1_alternative: ; beginning of any new second - only for deco modes btfsc FLAG_TFT_divemins call TFT_divemins_alternative ; Display (new) divetime! btfsc FLAG_TFT_divemode_mask_alt call TFT_divemode_mask_alternative ; Alt. mask call customview_alternative_second ; Do every-second tasks for the custom view area (In sync with the divetime) mH return TFT_output2_normal: ; any new second - only for deco modes btfsc FLAG_TFT_display_ndl_mask call TFT_display_ndl_mask btfsc FLAG_TFT_display_ndl call TFT_display_ndl btfsc FLAG_TFT_display_deko_mask call TFT_display_deko_mask btfsc FLAG_TFT_display_deko call TFT_display_deko btfsc FLAG_TFT_display_tts call TFT_display_tts return TFT_output2_alternative: ; any new second - only for deco modes return TFT_output3_normal: ; tasks any new second, any mode btfsc FLAG_TFT_max_depth call TFT_max_depth ; use normal max. depth btfsc FLAG_TFT_divemode_warning call TFT_divemode_warning btfsc FLAG_TFT_divemode_warning_clear call TFT_divemode_warning_clear btfsc FLAG_TFT_active_gas_divemode call TFT_active_gas_divemode ; Display gas/Setpoint btfsc FLAG_TFT_dive_warning_text_clear call TFT_clear_warning_text ; clear complete warnings area btfsc FLAG_TFT_dive_warning_text_clr2 call TFT_clear_warning_text_2nd_row; clear 2nd row of warnings return TFT_output3_alternative: ; tasks any new second, any mode btfsc FLAG_TFT_max_depth_alt call TFT_max_depth_alternative ; big max. depth btfsc FLAG_TFT_dive_warning_text_clear call TFT_clear_warning_text ; clear complete warnings area (In alt mode only 2nd. row...) btfsc FLAG_TFT_big_deco_alt call TFT_big_deco_alt ; Big deco return TFT_output4_normal: ; tasks any round, any mode btfsc FLAG_TFT_depth call TFT_depth ; Displays new depth btfsc FLAG_TFT_temp_divemode call TFT_temp_divemode ; Update temperature return TFT_output4_alternative: ; tasks any round, any mode btfsc FLAG_TFT_depth call TFT_depth ; Displays new depth return ;-------------------------------------------------------------------------------------------------------- divemode_apnoe_tasks: ; 1 sec. Apnoe tasks call TFT_display_apnoe_descent ; Yes, Show descent timer call TFT_max_depth ; 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: rcall calc_deko_divemode2 ; all deco relevant code is now invoked every second btfsc twosecupdate bra calc_deko_divemode1 bsf twosecupdate return calc_deko_divemode1: ; the following code is invoked every 2 seconds bcf twosecupdate 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 ; Check for a gas change goto check_gas_change ; Checks if a better gas should be selected (by user) and return... calc_deko_divemode2: btfsc FLAG_gauge_mode ; Done for Apnoe or Gauge mode return btfsc FLAG_ccr_mode ; In CCR mode? rcall calc_deko_divemode_sensor ; do sensor data acquisition if applicable by OSTC model btfsc FLAG_pscr_mode ; In PSCR mode? rcall calc_deko_divemode_sensor ; do sensor data acquisition if applicable by OSTC model SAFE_2BYTE_COPY amb_pressure,int_I_pres_respiration ; transfer ambient pressure to deco engine ; check deco engine state and switch between normal and alternative plan calculations ; ; Remark: Any reconfigurations done here do only affect the ascent & deco calculation settings, ; not the settings for the calculations done on the real tissues. The later ones are only ; altered in case of a gas change, or in case of a real bailout or switchback to setpoint ; or sensor, respectively. ; In case of a gas change or real bailout/switchback, the settings for the deco calculations ; are also changed to match the settings for the real tissues. This is done on signal through ; 'divemode_gaschange' and will also leave the deco engine status in state as if having done ; the alternative plan last. ; check state of ascent/deco calculations movff char_O_deco_status,lo ; get a working copy of char_O_deco_status into bank common movlw DECO_STATUS_MASK ; load bit mask covering the deco status bits andwf lo,W ; mask out bits showing deco engine computations state tstfsz WREG ; check if the last compute cycle has finished (bits 1 and 0 cleared) bra calc_deko_divemode2e ; NO - computations still in progress, needs more computation cycles btfss lo,DECO_PLAN_FLAG ; YES - computation cycle finished, so check what has been computed bra calc_deko_divemode2b ; PLAN bit is cleared i.e. normal plan was done, may do alternative next ; The PLAN bit is set, i.e. an alternative plan was computed in the last cycle, or the deco engine has ; been restarted because of a gas change etc. --> Reconfigure to normal plan for next computation cycle. ; reset flags for special calculations bcf lo,DECO_PLAN_FLAG ; clear flag for alternative plan bcf lo,DECO_ASCENT_FLAG ; clear flag for delayed ascent calculation bcf lo,DECO_VOLUME_FLAG ; clear flag for gas needs calculation movff lo,char_O_deco_status ; write-back char_O_deco_status to deco engine interface ; check if a switchback from CCR or pSCR bailout calculation is to be done btfsc FLAG_ccr_mode ; may a switchback from a CCR bailout calculation be needed? bra calc_deko_divemode2a ; in CCR mode, so may need to switch back from bailout calculation btfsc FLAG_pscr_mode ; may a switchback from a pSCR bailout calculation be needed? bra calc_deko_divemode2a ; in pSCR mode, so may need to switch back from bailout calculation bra calc_deko_divemode2e ; not in CCR nor pSCR, so no switchback needed, start normal plan now ; (first cycle omits gas needs calculation in OC without delayed ascent) ; switch back to loop calculation if last cycle was doing a bailout calculation calc_deko_divemode2a: movff opt_calc_asc_gasvolume,hi ; get the gas volume needs calculation setting movf hi,W ; are gas volume calculations turned on? bz calc_deko_divemode2e ; NO - can't have done a bailout calculation then, start normal plan btfsc is_bailout ; YES - check if a real bailout situation is present bra calc_deko_divemode2e ; YES - OC gases have been set by bailout action then, start normal plan movff active_gas,WREG ; NO - switch back to loop calculation: get current (diluent) gas, ... call deco_setup_cc_diluents ; ... set up deco calculations in CCR/pSCR mode with diluents, bra calc_deko_divemode2e ; ... and start in normal plan mode ; The PLAN bit was cleared, i.e. a normal plan was computed in the last cycle. For the next ; computation cycle the mode may be switched to alternative plan, or stay in normal mode... calc_deko_divemode2b: bcf lo,DECO_ASCENT_FLAG ; clear flag for delayed ascent calculation (for safety only) btfsc is_bailout ; check if a real bailout situation is present bra calc_deko_divemode2c ; YES - stay in normal plan mode and preclude delayed ascent calculation movff char_I_extra_time,hi ; NO - get the delayed ascent setting tstfsz hi ; check if delayed ascent calculation is enabled bsf lo,DECO_ASCENT_FLAG ; YES - set flag for delayed ascent calculation tstfsz hi ; check if delayed ascent calculation is enabled (again) bsf lo,DECO_PLAN_FLAG ; YES - set flag for alternative plan ; check if a gas needs calculation shall be done calc_deko_divemode2c: bsf lo,DECO_VOLUME_FLAG ; set gas needs calculation flag (may be cleared again next) TSTOSS opt_calc_asc_gasvolume ; check if gas needs calculation is enabled bcf lo,DECO_VOLUME_FLAG ; NO - reset flag again movff lo,char_O_deco_status ; write-back char_O_deco_status to deco engine interface TSTOSS opt_calc_asc_gasvolume ; check if gas volume calculation is enabled (again) bra calc_deko_divemode2e ; NO - no volume calculation, no simulated bailout plan in no case ; check if conditions are met to calculate a bailout plan btfsc is_bailout ; check if a real bailout situation is present bra calc_deko_divemode2e ; YES - normal plan already does bailout (OC) calculation "for real" btfss lo,DECO_MODE_LOOP_FLAG ; NO - have loop mode calculation been done during the normal plan? bra calc_deko_divemode2e ; NO - when not in loop mode, no simulated bailout to be done bsf lo,DECO_PLAN_FLAG ; YES - set flag for alternative plan movff lo,char_O_deco_status ; write-back char_O_deco_status to deco engine interface call get_first_gas_to_WREG ; get first OC gas, ... call deco_setup_oc_gases ; ... set up deco calculations in OC mode with OC gases, ;bra calc_deko_divemode2e ; ... and start in alternative plan mode calc_deko_divemode2e: clrf TMR5L clrf TMR5H ; 30,51757813µs/bit in TMR5L:TMR5H call deco_calc_hauptroutine ; calc_tissue banksel common ; Check if deco stops are necessary movff char_O_first_deco_depth,WREG; get ceiling tstfsz WREG ; ceiling < 0m (aka in deco) ? bra calc_deko_divemode3 ; YES ; NO - within NDL btfsc decostop_active ; already in no deco mode ? bsf FLAG_TFT_display_ndl_mask ; NO - clear deco data, display NDL time bsf FLAG_TFT_display_ndl ; display NDL time bcf decostop_active ; clear flag (again) return calc_deko_divemode3: ; YES - in deco btfss decostop_active ; already in deco mode ? bsf FLAG_TFT_display_deko_mask ; NO - clear NDL time, display deco data bsf FLAG_TFT_display_deko ; display deco data bsf FLAG_TFT_display_tts ; display TTS bsf decostop_active ; set flag (again) return ; -------------------------------------------------------------------------------------- global calc_deko_divemode_sensor calc_deko_divemode_sensor: ; sensor acquisition code btfss s8_digital ; check if we have a digital interface to the sensors bra calc_deko_divemode_sensor_analog ; NO - check if we have an analog interface btfss new_s8_data_available ; YES - check if a new data frame was received bra calc_deko_divemode_sensor_common ; NO - use old values -- TODO: add timeout for no new data call compute_mvolts_for_all_sensors ; YES - compute mV values from digital data bra calc_deko_divemode_sensor_common calc_deko_divemode_sensor_opt: btfss optical_input ; do we have an optical input? return ; No, return (We have no sensors at all. Not analog, not S8 and not optical) ;o2_ppo2_sensor1, o2_ppo2_sensor2 and o2_ppo2_sensor3 are already filled in ISR ;clear use_O2_sensorX for timeout case btfss sensor1_active bcf use_O2_sensor1 btfss sensor2_active bcf use_O2_sensor2 btfss sensor3_active bcf use_O2_sensor3 bra calc_deko_divemode_sensor1 calc_deko_divemode_sensor_analog: btfss analog_o2_input ; do we have an analog input? bra calc_deko_divemode_sensor_opt ; NO - check if we have an optical interface call get_analog_inputs ; YES - get the analog voltages and continue with the common part calc_deko_divemode_sensor_common: ; Check for each sensor if it is calibrated and if its mv value is within min_mv and max_mv limits. ; If ok: compute o2_ppo2_sensorX := o2_mv_sensorX * opt_x_sX / 1000 ; If not ok: reset o2_ppo2_sensorX, reset use_O2_sensorX and show the customview 1 in case the sensor was ok before ; Check min_mv of sensor 1 btfss sensor1_calibrated_ok ; check if sensor is usable at all bra check_sensor_1_fail ; NO - handle it as failed movff o2_mv_sensor1+0, sub_a+0 ; load sensor mV value movff o2_mv_sensor1+1, sub_a+1 movlw LOW min_mv ; load minimum mV value movwf sub_b+0 movlw HIGH min_mv movwf sub_b+1 call sub16 ; sub_c = sensor_mv - min_mv btfsc neg_flag ; check if result is negative, i.e. sensor_mv < min_mv bra check_sensor_1_fail ; YES - declare sensor as failed ; Check max_mv of sensor 1 ; NO - continue with next check movff o2_mv_sensor1+0, sub_a+0 movff o2_mv_sensor1+1, sub_a+1 movlw LOW max_mv movwf sub_b+0 movlw HIGH max_mv movwf sub_b+1 call sub16 ; sub_c = sensor_mv - max_mv btfss neg_flag ; check if result is negative, i.e. sensor_mv < max_mv bra check_sensor_1_fail ; NO - declare sensor as failed ; Check HUD data, if available ; YES - continue with next check btfss hud_connection_ok ; check if there is a HUD connected bra check_sensor_1_ok ; NO - all checks done then and positive btfss sensor1_active ; YES - check HUD report on sensor bra check_sensor_1_fail ; HUD reports a fail check_sensor_1_ok: ; o2_ppo2_sensor1 := o2_mv_sensor1:2 * opt_x_s1:2 / 1000 movff o2_mv_sensor1+0,xA+0 movff o2_mv_sensor1+1,xA+1 movff opt_x_s1+0,xB+0 movff opt_x_s1+1,xB+1 rcall compute_ppo2_helper movff xC+0,o2_ppo2_sensor1 ; result in 0.01bar bra check_sensor_2 ; continue with next sensor check_sensor_1_fail: clrf WREG movff WREG,o2_ppo2_sensor1 ; set ppO2 reading to zero btfss use_O2_sensor1 ; check if sensor was in use before bra check_sensor_1_fail_1 ; NO - no new news then call check_sensor_custview_helper; YES - show customview 1 (sensor values) on further conditions met check_sensor_1_fail_1: bcf use_O2_sensor1 ; revoke sensor from usage ;bra check_sensor_2 ; continue with next sensor check_sensor_2: ; Check min_mv of sensor 2 btfss sensor2_calibrated_ok ; check if sensor is usable at all bra check_sensor_2_fail ; NO - handle it as failed movff o2_mv_sensor2+0, sub_a+0 ; load sensor mV value movff o2_mv_sensor2+1, sub_a+1 movlw LOW min_mv ; load minimum mV value movwf sub_b+0 movlw HIGH min_mv movwf sub_b+1 call sub16 ; sub_c = sensor_mv - min_mv btfsc neg_flag ; check if result is negative, i.e. sensor_mv < min_mv bra check_sensor_2_fail ; YES - declare sensor as failed ; Check max_mv of sensor 2 ; NO - continue with next check movff o2_mv_sensor2+0, sub_a+0 movff o2_mv_sensor2+1, sub_a+1 movlw LOW max_mv movwf sub_b+0 movlw HIGH max_mv movwf sub_b+1 call sub16 ; sub_c = sensor_mv - max_mv btfss neg_flag ; check if result is nagative, i.e. sensor_mv < max_mv bra check_sensor_2_fail ; NO - declare sensor as failed ; Check HUD data, if available ; YES - continue with next check btfss hud_connection_ok ; check if there is a HUD connected bra check_sensor_2_ok ; NO - all checks done then and positive btfss sensor2_active ; YES - check HUD report on sensor bra check_sensor_2_fail ; HUD reports a fail check_sensor_2_ok: ; o2_ppo2_sensor2 := o2_mv_sensor2:2 * opt_x_s2:2 / 1000 movff o2_mv_sensor2+0,xA+0 movff o2_mv_sensor2+1,xA+1 movff opt_x_s2+0,xB+0 movff opt_x_s2+1,xB+1 rcall compute_ppo2_helper movff xC+0,o2_ppo2_sensor2 ; result in 0.01bar bra check_sensor_3 ; continue with next sensor check_sensor_2_fail: clrf WREG movff WREG,o2_ppo2_sensor2 ; set ppO2 reading to zero btfss use_O2_sensor2 ; check if sensor was in use before bra check_sensor_2_fail_1 ; NO - no new news then call check_sensor_custview_helper; YES - show customview 1 (sensor values) on further conditions met check_sensor_2_fail_1: bcf use_O2_sensor2 ; revoke sensor from usage ;bra check_sensor_3 ; continue with next sensor check_sensor_3: ; Check min_mv of sensor 2 btfss sensor3_calibrated_ok ; check if sensor is usable at all bra check_sensor_3_fail ; NO - handle it as failed movff o2_mv_sensor3+0, sub_a+0 ; load sensor mV value movff o2_mv_sensor3+1, sub_a+1 movlw LOW min_mv ; load minimum mV value movwf sub_b+0 movlw HIGH min_mv movwf sub_b+1 call sub16 ; sub_c = sensor_mv - min_mv btfsc neg_flag ; check if result is negative, i.e. sensor_mv < min_mv bra check_sensor_3_fail ; YES - declare sensor as failed ; Check max_mv of sensor 2 ; NO - continue with next check movff o2_mv_sensor3+0, sub_a+0 movff o2_mv_sensor3+1, sub_a+1 movlw LOW max_mv movwf sub_b+0 movlw HIGH max_mv movwf sub_b+1 call sub16 ; sub_c = sensor_mv - max_mv btfss neg_flag ; check if result is negative, i.e. sensor_mv < max_mv bra check_sensor_3_fail ; NO - declare sensor as failed ; Check HUD data, if available ; YES - continue with next check btfss hud_connection_ok ; check if there is a HUD connected bra check_sensor_3_ok ; NO - all checks done then and positive btfss sensor3_active ; YES - check HUD report on sensor bra check_sensor_3_fail ; HUD reports a fail check_sensor_3_ok: ; o2_ppo2_sensor3 := o2_mv_sensor3:2 * opt_x_s1:2 / 1000 movff o2_mv_sensor3+0,xA+0 movff o2_mv_sensor3+1,xA+1 movff opt_x_s3+0,xB+0 movff opt_x_s3+1,xB+1 rcall compute_ppo2_helper movff xC+0,o2_ppo2_sensor3 ; result in 0.01bar bra calc_deko_divemode_sensor1 ; continue with calculating sensor average check_sensor_3_fail: clrf WREG movff WREG,o2_ppo2_sensor3 ; set ppO2 reading to zero btfss use_O2_sensor3 ; check if sensor was in use before bra check_sensor_3_fail_1 ; NO - no new news then call check_sensor_custview_helper; YES - show customview 1 (sensor values) on further conditions met check_sensor_3_fail_1: bcf use_O2_sensor3 ; revoke sensor from usage ;bra calc_deko_divemode_sensor1 ; continue with calculating sensor average calc_deko_divemode_sensor1: ; calculate sensor average ; exit here if not in divemode btfss divemode return ; compute sensor_setpoint := average of all o2_ppo2_sensorX of those sensors that have use_O2_sensorX == true ; 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 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 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 movf o2_ppo2_sensor3,W addwf xA+0 movlw .0 addwfc xA+1 ; Add into xA:2 incf xB+0,F ; Add a sensor ; Divide sum of sensor values by number of active sensors found. divemode_setup_sensor_values4: call div16x16 ; xA/xB=xC with xA+0 as remainder movff xC+0,sensor_setpoint ; copy result ; set default value for pSCR mode: 0 = let p2_deco.c compute the ppO2 based on current dil gas and depth ; will be overwritten later in case we are in sensor mode and have at least one usable sensor clrf WREG ; preload a zero btfsc FLAG_pscr_mode ; check if we are in pSCR mode movff WREG,char_I_const_ppO2 ; YES - write 0 to char_I_const_ppo2, ; it will be overwritten if we have a usable sensor reading btfsc is_bailout ; check if we are in bailout bra calc_deko_divemode_sensor2 ; YES - no sensor data transfer to char_I_const_ppO2 in this case movff opt_ccr_mode,WREG ; =0: Fixed SP, =1: Sensor, =2: Auto SP sublw .1 ; opt_ccr_mode = 1 (Sensor)? bnz calc_deko_divemode_sensor2 ; not in sensor mode - no transfer of sensor data to char_I_const_ppO2 tstfsz xB+0 ; check if we have found at least one usable sensor bra calc_deko_divemode_sensor1a ; YES - we have at least one usable sensor bsf setpoint_fallback ; NO - we have NO usable sensors -> initiate fallback btfss FLAG_ccr_mode ; check if we are in CCR mode bra calc_deko_divemode_sensor2 ; NO - continue with voting logic flags movff char_I_setpoint_cbar+0,char_I_const_ppO2 ; YES - select fixed setpoint no. 1 for fallback bra calc_deko_divemode_sensor2 ; done - continue with voting logic flags calc_deko_divemode_sensor1a: ; we have at least one usable sensor with a value > 0 bcf setpoint_fallback ; clear fallback condition movff sensor_setpoint,char_I_const_ppO2 ; transfer average sensor value to p2_deco.c code ;bra calc_deko_divemode_sensor2 calc_deko_divemode_sensor2: bsf voting_logic_sensor1 movff o2_ppo2_sensor1,lo rcall check_sensor_voting_helper incfsz WREG ; Was WREG = 255? bcf voting_logic_sensor1 ; No, ignore this sensor bsf voting_logic_sensor2 movff o2_ppo2_sensor2,lo rcall check_sensor_voting_helper incfsz WREG ; Was WREG=255? bcf voting_logic_sensor2 ; No, ignore this sensor bsf voting_logic_sensor3 movff o2_ppo2_sensor3,lo rcall check_sensor_voting_helper incfsz WREG ; Was WREG=255? bcf voting_logic_sensor3 ; No, ignore this sensor ; check if a warning shall be issued on sensor disagreement btfsc FLAG_ccr_mode ; check if we are in CCR mode bra check_warn_sensor_1 ; YES - continue with further checks btfsc FLAG_pscr_mode ; check if we are in pSCR mode bra check_warn_sensor_1 ; YES - continue with further checks bra check_warn_sensor_agree ; not in CCR and not in pSCR, so no warning check_warn_sensor_1: ; we are in CCR or pSCR mode btfsc is_bailout ; check if we are in bailout bra check_warn_sensor_agree ; YES - no warning in this case movff opt_ccr_mode,WREG ; =0: Fixed SP, =1: Sensor, =2: Auto SP sublw .1 ; opt_ccr_mode = 1 (Sensor)? bnz check_warn_sensor_agree ; not in sensor mode - no warning in this case ; check sensor 1 btfss sensor1_calibrated_ok ; check if sensor has a valid calibration bra check_warn_sensor_2 ; NO - sensor can not cause a warning then btfss use_O2_sensor1 ; YES - check if sensor is in use bra check_warn_sensor_2 ; NO - sensor can not cause a warning then btfsc voting_logic_sensor1 ; YES - check if sensor value is within agreement range bra check_warn_sensor_2 ; YES - continue with next sensor bcf sensors_agree ; NO - issue a warning return check_warn_sensor_2: ; check sensor 2 btfss sensor2_calibrated_ok ; check if sensor has a valid calibration bra check_warn_sensor_3 ; NO - sensor can not cause a warning then btfss use_O2_sensor2 ; YES - check if sensor is in use bra check_warn_sensor_3 ; NO - sensor can not cause a warning then btfsc voting_logic_sensor2 ; YES - check if sensor value is within agreement range bra check_warn_sensor_3 ; YES - continue with next sensor bcf sensors_agree ; NO - issue a warning return check_warn_sensor_3: ; check sensor 2 btfss sensor3_calibrated_ok ; check if sensor has a valid calibration bra check_warn_sensor_agree ; NO - sensor can not cause a warning then btfss use_O2_sensor3 ; YES - check if sensor is in use bra check_warn_sensor_agree ; NO - sensor can not cause a warning then btfsc voting_logic_sensor3 ; YES - check if sensor value is within agreement range bra check_warn_sensor_agree ; YES - continue with next sensor bcf sensors_agree ; NO - issue a warning return check_warn_sensor_agree: bsf sensors_agree return compute_ppo2_helper: call mult16x16 ; xA:2*xB:2=xC:4 movlw LOW .1000 movwf xB+0 movlw HIGH .1000 movwf xB+1 call div32x16 ; xC:4 / xB:2 = xC+3:xC+2 with xC+1:xC+0 as remainder movlw d'1' addwf xC+0,W ; we are just interested in the carry flag movlw d'0' addwfc xC+1,W ; we are still just interested in the carry flag tstfsz WREG ; ppO2 is higher than 2.55bar? setf xC+0 ; Yes. return check_sensor_custview_helper: btfss divemode ; check if we are in divemode return ; NO - not in dive mode, return movff opt_ccr_mode,WREG ; =0: Fixed SP, =1: Sensor, =2: Auto SP sublw .1 ; opt_ccr_mode = 1 (Sensors)? bnz check_sensor_helper_1 ; NO - not using the sensors in the moment clrf menupos3 ; YES - arm customview 1 (sensor values) bsf toggle_customview ; and request a customview toggle check_sensor_helper_1: return check_sensor_voting_helper: movf lo,W cpfsgt sensor_setpoint bra check_sensor_voting_common2 ; lo < sensor_setpoint ; lo > sensor_setpoint movf lo,W subwf sensor_setpoint,W movwf lo check_sensor_voting_common1: movlw sensor_voting_logic_threshold ; Threshold in 0.01 bar cpfsgt lo retlw .255 ; Within range retlw .0 ; Out of range check_sensor_voting_common2: ; lo<sensor_setpoint movf sensor_setpoint,W subwf lo,F bra check_sensor_voting_common1 ;----------------------------------------------------------------------------- divemodemode_togglegf: ; Toggle aGF/GF bcf toggle_gf ; clear flag btg use_agf ; toggle GF btfsc use_agf ; switch to aGF? bra divemodemode_togglegf_1 ; YES - branch to using aGF movff opt_GF_low,char_I_GF_Low_percentage ; NO - use normal GF factors movff opt_GF_high,char_I_GF_High_percentage ; bra divemodemode_togglegf_2 ; continue with common part divemodemode_togglegf_1: ; use alternative GF factors movff opt_aGF_low,char_I_GF_Low_percentage movff opt_aGF_high,char_I_GF_High_percentage divemodemode_togglegf_2: call TFT_gf_mask ; update customview mask to show which one is in use ; the customview itself has been called from divemenu_tree before goto restart_deco_engine ; ...and 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 deeper 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 ; divided 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 bsf FLAG_TFT_clear_safety_stop ; Clear safety stop return ;============================================================================= timeout_menuview: decfsz timeout_counter2,F ; timeout for menuview return ; No timeout, return ; Timeout, clear e.g. "Menu?" goto menuview_toggle_reset ; "returns" timeout_divemode_menu: decfsz timeout_counter2,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 bsf FLAG_TFT_active_gas_divemode; Redraw gas/setpoint/diluent bcf blinking_better_gas ; Clear flag to have temperature updated once bsf FLAG_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 bsf FLAG_TFT_display_deko_mask bsf FLAG_TFT_display_deko bsf FLAG_TFT_display_tts return timeout_divemode_menu_ndl: ; Show NDL bsf FLAG_TFT_display_ndl_mask bsf FLAG_TFT_display_ndl 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_counter1+0,F incf timeout_counter1+1,F ; timeout is 16 bit counter movff opt_diveTimeout,WREG ; in [min] mullw .60 movff PRODL,sub_a+0 movff PRODH,sub_a+1 ; in [s] movff timeout_counter1+0,sub_b+0 movff timeout_counter1+1,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_counter1+0,F ; seconds... movlw d'60' cpfseq timeout_counter1+0 ; timeout_counter1+0 = 60 ? return ; No ; one minute timeout done clrf timeout_counter1+0 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_counter1+0,F movlw simulator_timeout ; simulator timeout cpfsgt timeout_counter1+0 bsf divemode return update_divemode60: ; update any minute call get_battery_voltage ; gets battery voltage rcall set_powersafe ; Battery low? 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 bsf FLAG_TFT_max_depth ; Set flag 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_counter1+0 ; Yes, reset timeout 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 LOW high_altitude_dive_threshold movwf sub_a+0 movlw HIGH high_altitude_dive_threshold movwf sub_a+1 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 ;bra test_switches_divemode2 ; Enter button pressed, check if we need to do something goto menuview_toggle ; Menu or Simulator tasks; and return... 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 menupos1 test_switches_divemode_menu2: incf menupos1,F incf menupos4,W ; menupos4+1 -> WREG cpfslt menupos1 ; > 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_counter2 ; timeout for divemode menu return test_switches_divemode_menu3: ; Enter submenu or do something bcf switch_right ; decf menupos1,F ; menu_processor needs 0-5... goto do_line_menu ; Warning! Trashes STKPTR and returns to diveloop_loop4: test_switches_divemode1: bcf switch_right movlw divemode_menuview_timeout movwf timeout_counter2 ; 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 dcfsnz WREG,F bra divemode_option8 ; Switch to alt. layout return gas_switched_common: bcf divemode_gaschange ; Clear flag btfss FLAG_back_to_loop ; check if it is a switchback from OC bailout to loop bra gas_switched_common0 ; NO - continue with checking if selected gas is valid bcf FLAG_back_to_loop ; YES - clear flag movff active_diluent,menupos1 ; reload last diluent bra gas_switched_common1 ; continue with common part gas_switched_common0: tstfsz menupos1 ; menupos1=0? bra gas_switched_common1 ; NO - valid gas return ; YES - something went wrong, invalid gas, abort gas_switched_common1: movf menupos1,W ; get selected gas into WREG (1-6) btfsc FLAG_ccr_mode ; in CCR mode? bra gas_switched_common2 ; YES - configure diluent or bailout btfsc FLAG_pscr_mode ; in pSCR mode? bra gas_switched_common2 ; YES - configure diluent or bailout ; OC rcall setup_gas_registers ; With WREG = Gas 1-6 rcall deco_setup_oc_gases ; With WREG = Gas 1-6 bra gas_switched_common3 ; loop or bailout gas_switched_common2: rcall setup_dil_registers ; With WREG = diluent 1-6, in case of is_bailout reverts to OC gases rcall deco_setup_cc_diluents ; With WREG = diluent 1-6, in case of is_bailout reverts to OC gases gas_switched_common3: bsf FLAG_TFT_active_gas_divemode ; Redraw gas/setpoint/diluent call restart_deco_engine_wo_ceiling ; abort any running deco calculations and restart the deco engine ; Set flags for profile recording bsf event_occured ; set event flag 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 ; Code to pass all parameters to the C code global get_first_gas_to_WREG get_first_gas_to_WREG: ; Gets first gas (1-5) into WREG lfsr FSR1,opt_gas_type ; Point to gas types clrf lo ; start with Gas0 get_first_gas_to_WREG2: movf lo,W movf PLUSW1,W ; Get Type of Gas #lo sublw .1 ; it is = 1 (First Gas) bz get_first_gas_to_WREG3 ; Found the first gas! incf lo,F ; ++ movlw NUM_GAS+1 cpfseq lo ; All done? bra get_first_gas_to_WREG2 ; Not yet ; No first gas found, use #1 movlw .0 movff WREG,opt_gas_type+0 ; Set Gas1 to First incf WREG,W ; 0 -> 1 return get_first_gas_to_WREG3: movf lo,W ; Put into Wreg incf WREG,W ; 0-4 -> 1-5 return ; Done global get_first_dil_to_WREG get_first_dil_to_WREG: ; Gets first dil (1-5) into WREG lfsr FSR1,opt_dil_type ; Point to dil types clrf lo ; start with Gas0 get_first_dil_to_WREG2: movf lo,W movf PLUSW1,W ; Get Type of Dil #lo sublw .1 ; it is = 1 (First Dil) bz get_first_dil_to_WREG3 ; Found the first dil! incf lo,F ; ++ movlw NUM_GAS+1 cpfseq lo ; All done? bra get_first_dil_to_WREG2 ; Not yet ; No first dil found, use #1 movlw .0 movff WREG,opt_dil_type+0 ; Set Dil1 to First incf WREG,W ; 0 -> 1 return get_first_dil_to_WREG3: movf lo,W ; Put into Wreg incf WREG,W ; 0-4 -> 1-5 return ; Done global deco_setup_oc_gases deco_setup_oc_gases: ; with currently breathed gas in WREG (1-5 or 6) movff WREG,char_I_current_gas ; gas to start with when doing the deco calculations banksel opt_gas_type ; opt_gas_type[] and opt_OC_bail_gas_change[] are together in bank common2 movff opt_gas_He_ratio+0,char_I_deco_He_ratio+0 movff opt_gas_O2_ratio+0,char_I_deco_O2_ratio+0 movlw .3 ; 3=Deco cpfseq opt_gas_type+0 ; Gas is deco type? clrf opt_OC_bail_gas_change+0 ; No, clear depth for 0=Disabled, 1=First and 2=Travel movff opt_gas_He_ratio+1,char_I_deco_He_ratio+1 movff opt_gas_O2_ratio+1,char_I_deco_O2_ratio+1 movlw .3 ; 3=Deco cpfseq opt_gas_type+1 ; Gas is deco type? clrf opt_OC_bail_gas_change+1 ; No, clear depth for 0=Disabled, 1=First and 2=Travel movff opt_gas_He_ratio+2,char_I_deco_He_ratio+2 movff opt_gas_O2_ratio+2,char_I_deco_O2_ratio+2 movlw .3 ; 3=Deco cpfseq opt_gas_type+2 ; Gas is deco type? clrf opt_OC_bail_gas_change+2 ; No, clear depth for 0=Disabled, 1=First and 2=Travel movff opt_gas_He_ratio+3,char_I_deco_He_ratio+3 movff opt_gas_O2_ratio+3,char_I_deco_O2_ratio+3 movlw .3 ; 3=Deco cpfseq opt_gas_type+3 ; Gas is deco type? clrf opt_OC_bail_gas_change+3 ; No, clear depth for 0=Disabled, 1=First and 2=Travel movff opt_gas_He_ratio+4,char_I_deco_He_ratio+4 movff opt_gas_O2_ratio+4,char_I_deco_O2_ratio+4 movlw .3 ; 3=Deco cpfseq opt_gas_type+4 ; Gas is deco type? clrf opt_OC_bail_gas_change+4 ; No, clear depth for 0=Disabled, 1=First and 2=Travel banksel common ; Setup char_I_deco_gas_change array movff opt_OC_bail_gas_change+0, char_I_deco_gas_change+0 movff opt_OC_bail_gas_change+1, char_I_deco_gas_change+1 movff opt_OC_bail_gas_change+2, char_I_deco_gas_change+2 movff opt_OC_bail_gas_change+3, char_I_deco_gas_change+3 movff opt_OC_bail_gas_change+4, char_I_deco_gas_change+4 ; switch to oc mode movff char_O_deco_status,lo ; working copy of char_O_deco_status in bank common bcf lo,DECO_MODE_PSCR_FLAG ; clear the pSCR-mode flag (may not be set, but never mind) bcf lo,DECO_MODE_LOOP_FLAG ; clear the loop/CCR-mode flag movff lo,char_O_deco_status ; bank safe write-back of char_O_deco_status return global deco_setup_cc_diluents deco_setup_cc_diluents: ; with currently breathed gas in WREG (1-5 or 6) btfsc is_bailout ; check if in bailout condition bra deco_setup_oc_gases ; revert to setting up OC gases in bailout condition movff WREG,char_I_current_gas ; gas to start with when doing the deco calculations movff opt_dil_He_ratio+0,char_I_deco_He_ratio+0 movff opt_dil_O2_ratio+0,char_I_deco_O2_ratio+0 movff opt_dil_type+0,WREG ; 0=Disabled, 1=First, 2=Normal tstfsz WREG ; Disabled? bra $+4 ; No movff WREG,char_I_dil_change+0 ; Yes, clear char_I_deco_gas_change (Bank safe) movff opt_dil_He_ratio+1,char_I_deco_He_ratio+1 movff opt_dil_O2_ratio+1,char_I_deco_O2_ratio+1 movff opt_dil_type+1,WREG ; 0=Disabled, 1=First, 2=Normal tstfsz WREG ; Disabled? bra $+4 ; No movff WREG,char_I_dil_change+1 ; Yes, clear char_I_dil_change movff opt_dil_He_ratio+2,char_I_deco_He_ratio+2 movff opt_dil_O2_ratio+2,char_I_deco_O2_ratio+2 movff opt_dil_type+2,WREG ; 0=Disabled, 1=First, 2=Normal tstfsz WREG ; Disabled? bra $+4 ; No movff WREG,char_I_dil_change+2 ; Yes, clear char_I_dil_change movff opt_dil_He_ratio+3,char_I_deco_He_ratio+3 movff opt_dil_O2_ratio+3,char_I_deco_O2_ratio+3 movff opt_dil_type+3,WREG ; 0=Disabled, 1=First, 2=Normal tstfsz WREG ; Disabled? bra $+4 ; No movff WREG,char_I_dil_change+3 ; Yes, clear char_I_dil_change movff opt_dil_He_ratio+4,char_I_deco_He_ratio+4 movff opt_dil_O2_ratio+4,char_I_deco_O2_ratio+4 movff opt_dil_type+4,WREG ; 0=Disabled, 1=First, 2=Normal tstfsz WREG ; Disabled? bra $+4 ; No movff WREG,char_I_dil_change+4 ; Yes, clear char_I_dil_change ; Setup char_I_deco_gas_change array movff char_I_dil_change+0, char_I_deco_gas_change+0 movff char_I_dil_change+1, char_I_deco_gas_change+1 movff char_I_dil_change+2, char_I_deco_gas_change+2 movff char_I_dil_change+3, char_I_deco_gas_change+3 movff char_I_dil_change+4, char_I_deco_gas_change+4 ; switch to CCR / pSCR mode movff char_O_deco_status,lo ; working copy of char_O_deco_status in bank common bsf lo,DECO_MODE_LOOP_FLAG ; loop flag is set in both, CCR and pSCR mode bcf lo,DECO_MODE_PSCR_FLAG ; clear pSCR mode flag by default btfsc FLAG_pscr_mode ; check if we are in pSCR mode bsf lo,DECO_MODE_PSCR_FLAG ; YES - set additional flag for pSCR mode movff lo,char_O_deco_status ; bank safe write-back of char_O_deco_status return global setup_gas_registers setup_gas_registers: ; with currently breathed gas in WREG (1-5 or 6) movwf active_gas ; set as current gas movlw .6 cpfseq active_gas ; gas = gas6 ? bra setup_gas_registers_15 ; NO - load gas 1-5 movff gas6_O2_ratio,char_I_O2_ratio ; copy gas6 O2 ratio to deco engine movff gas6_He_ratio,char_I_He_ratio ; copy gas6 H2 ratio to deco engine bra setup_gas_registers_com ; continue with common part setup_gas_registers_15: decf active_gas,W ; 1-5 -> 0-4 lfsr FSR1,opt_gas_O2_ratio+0 movff PLUSW1,char_I_O2_ratio ; copy gas 1-5 O2 ratio to deco engine lfsr FSR1,opt_gas_He_ratio+0 movff PLUSW1,char_I_He_ratio ; copy gas 1-5 He ratio to deco engine setup_gas_registers_com: ;lfsr FSR1,opt_gas_type ; commented out - currently not used anywhere ;movff PLUSW1,active_gas_type ; 0=Disabled, 1=First, 2=Travel, 3=Deco movff char_O_main_status,lo ; working copy of char_O_main_status in bank common bcf lo,DECO_MODE_PSCR_FLAG ; clear the pSCR-mode flag (may not be set, but never mind) bcf lo,DECO_MODE_LOOP_FLAG ; clear the loop/CCR-mode flag movff lo,char_O_main_status ; bank safe write-back of char_O_main_status movf active_gas,W ; reload WREG with diluent 1-5 or 6 (important!) return global setup_dil_registers setup_dil_registers: ; with currently breathed gas in WREG (1-5 or 6) btfsc is_bailout ; check if in bailout condition bra setup_gas_registers ; revert to setting up OC gases in bailout condition movwf active_gas ; set as current gas movff WREG,active_diluent ; remember for when switching back from bailout to loop movlw .6 cpfseq active_gas ; diluent = gas6 ? bra setup_dil_registers_15 ; NO - load diluent 1-5 movff gas6_O2_ratio,char_I_O2_ratio ; copy gas6 O2 ratio to deco engine movff gas6_He_ratio,char_I_He_ratio ; copy gas6 H2 ratio to deco engine bra setup_dil_registers_com ; continue with common part setup_dil_registers_15: decf active_gas,W ; 1-5 -> 0-4 lfsr FSR1,opt_dil_O2_ratio+0 movff PLUSW1,char_I_O2_ratio ; copy diluent 1-5 O2 ratio to deco engine lfsr FSR1,opt_dil_He_ratio+0 movff PLUSW1,char_I_He_ratio ; copy diluent 1-5 He ratio to deco engine setup_dil_registers_com: ;lfsr FSR1,opt_dil_type ; commented out - currently not used anywhere ;movff PLUSW1,active_gas_type ; 0=Disabled, 1=First, 2=Normal (there is no type 3 for diluents) movff char_O_main_status,lo ; working copy of char_O_main_status in bank common bsf lo,DECO_MODE_LOOP_FLAG ; loop flag is set in both, CCR and pSCR mode bcf lo,DECO_MODE_PSCR_FLAG ; clear pSCR mode flag by default btfsc FLAG_pscr_mode ; check if we are in pSCR mode bsf lo,DECO_MODE_PSCR_FLAG ; YES - set additional flag for pSCR mode movff lo,char_O_main_status ; bank safe write-back of char_O_main_status movf active_gas,W ; reload WREG with diluent 1-5 or 6 (important!) return divemode_option_gaschange: ; Switch to the better gas movff better_gas_number,menupos1 ; 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 call do_main_divemenu global divemode_option0_return divemode_option0_return: ; movlw .1 ; movwf menupos1 ; Set to first option in divemode menu call TFT_divemode_menu_cursor ; Show the cursor movlw divemode_menu_timeout movwf timeout_counter2 ; timeout for divemode menu bsf divemode_menu ; Set flag clrf menupos2 ; Clear option counter goto diveloop_loop4 ; Goto back to diveloop (menu processor trashes STKPTR!) divemode_option4: movlw d'58' ; two seconds left movwf timeout_counter1+0 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_counter1+0 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 ; + 5 minutes movff WREG,char_I_sim_advance_time; copy to mailbox bsf divemode2 ; continue divetime call restart_deco_engine 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_option8: bsf alternative_divelayout ; Set flag for mode bsf FLAG_TFT_divemode_mask_alt ; Set flag for mask movlw .1 movwf menupos3 ; For the customviews... call TFT_ClearScreen ; Clear screen 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 WREG movff WREG,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_pscr_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 check_gas_change2: btfsc is_bailout ; in bailout? bra check_gas_change_OC_bail ; YES - check for OC ; Check Diluents 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: 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: bsf FLAG_TFT_active_gas_divemode; redraw gas/setpoint/diluent btfss better_gas_available ; is a better gas available? bcf blinking_better_gas ; NO - clear blinking flag btfsc better_gas_available ; is a better gas available? return ; YES clrf WREG ; NO - clear better_gas_number (for gaslist display) movff WREG,better_gas_number 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 current gas? 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 movff WREG,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? bra check_gas_common4 ; Ok, now check the better gas ppO2<char_I_ppO2_max return check_gas_common3: incf hi,W ; 1-5 movff WREG,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<char_I_ppO2_max return check_gas_common4: movf hi,W ; gas 0-4 into WREG lfsr FSR1,char_I_deco_O2_ratio ; load base address char_I_deco_O2_ratio array movff PLUSW1,lo ; read O2 ratio from array into 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 char_I_ppO2_min,WREG mullw d'100' ; char_I_ppO2_min*100 movff PRODL,sub_a+0 movff PRODH,sub_a+1 call subU16 ; sub_c = sub_a - sub_b btfss neg_flag return ; Done (Too low). ;check if we are within our warning thresholds! movff xC+0,sub_a+0 movff xC+1,sub_a+1 movff char_I_ppO2_max_deco,WREG ; ppO2 max for MOD calculation and color coding in divemode addlw .1 ; e.g. >1.60 mullw d'100' ; char_I_ppO2_max*100 movff PRODL,sub_b+0 movff PRODH,sub_b+1 call subU16 ; sub_c = sub_a - sub_b btfsc 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 the current diluent? 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 movff WREG,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 check_dive_autosp2a ; No, continue bra check_dive_autosp3 ; Skip check check_dive_autosp2a: 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 check_dive_autosp3a ; No, continue bra check_dive_autosp4 ; Skip check check_dive_autosp3a: 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 check_dive_autosp4a ; No, continue bra check_dive_autosp5 ; Skip check check_dive_autosp4a: 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 check_dive_autosp5a ; No, continue bra check_dive_autosp6 ; Skip check check_dive_autosp5a: 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 event flag return set_logbook_marker: bcf FLAG_set_marker ; clear flag movlw d'6' ; set type of Alarm (manual marker) movwf AlarmType ; copy to Alarm Register bsf event_occured ; Set event flag return ;============================================================================= ; Setup everything to enter divemode. ; dive_boot_oc: rcall get_first_gas_to_WREG ; Gets first gas (1-5) into WREG rcall setup_gas_registers ; set-up of gas parameters of currently breathed gas (with WREG = gas 1-5) rcall deco_setup_oc_gases ; set-up of gas list for deco calculations (with WREG = gas 1-5) 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 ; revoke sensors from usage if they do not have a valid calibration bsf use_O2_sensor1 bsf use_O2_sensor2 bsf use_O2_sensor3 btfss sensor1_calibrated_ok bcf use_O2_sensor1 btfss sensor2_calibrated_ok bcf use_O2_sensor2 btfss sensor3_calibrated_ok bcf use_O2_sensor3 btfss optical_input ; do we have an optical input? bra dive_boot_cc_0 ; No ; Copy (initial) valid flags from HUD/ppO2 Monitor btfsc sensor1_active bsf use_O2_sensor1 btfsc sensor2_active bsf use_O2_sensor2 btfsc sensor3_active bsf use_O2_sensor3 dive_boot_cc_0: ; In pSCR mode, only settings 0 (calculated ppO2) and 1 (ppO2 from sensors) are defined. ; In case we still have 3 (auto SP) selected out of previous ccr mode, we reset to 0. btfss FLAG_pscr_mode bra dive_boot_cc_1 movff opt_ccr_mode,WREG ; =0: Fixed SP (CCR) / calculated SP (pSCR), =1: Sensor, =2: Auto SP sublw .2 ; opt_ccr_mode = 1 (Auto SP)? bnz dive_boot_cc_1 movlw .0 movff WREG,opt_ccr_mode dive_boot_cc_1: bsf setpoint_changed ; set flag (for profile) bcf sp2_switched ; =1: This setpoint has been auto-selected already bcf sp3_switched ; =1: This setpoint has been auto-selected already bcf sp4_switched ; =1: This setpoint has been auto-selected already bcf sp5_switched ; =1: This setpoint has been auto-selected already rcall get_first_dil_to_WREG ; get first gas (1-5) into WREG rcall setup_dil_registers ; set-up of gas parameters for currently breathed gas (with WREG = current gas 1-5) rcall deco_setup_cc_diluents ; set-up of gas list for deco calculations (with WREG = current gas 1-5) ; Start with SP1 (CCR) or 0 (pSCR) as default. ; If in sensor mode, this value will be overwritten by calc_deko_divemode_sensor clrf WREG ; preload WREG with setpoint value 0 for pSCR calculated btfss FLAG_ccr_mode ; are we in CCR mode? bra dive_boot_cc_2 ; NO - keep preloaded value movff char_I_setpoint_cbar+0,WREG ; YES - get value of setpoint 1 dive_boot_cc_2: movff WREG,char_I_const_ppO2 ; write setpoint to deco engine call transmit_setpoint ; transmit current setpoint from WREG (in cbar) to external electronics goto calc_deko_divemode_sensor ; read & process sensor data (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 ; init in invalid data state clrf WREG ; set WREG to 0 bsf WREG,int_invalid_flag ; set invalid flag bsf WREG,int_is_zero ; set zero flag movff WREG,int_O_tank_pres_need+1 ; Set flags for tank pressure needs = 0 before p2_deco.c movff WREG,int_O_tank_pres_need+3 ; can do it. If this is not done here and the gas needs movff WREG,int_O_tank_pres_need+5 ; custom view is shown before p2_deco.c completes the first movff WREG,int_O_tank_pres_need+7 ; deco calculation, some rubbish numbers from last dive of movff WREG,int_O_tank_pres_need+9 ; simulation may be shown ; configure the deco engine: movff char_O_deco_status,WREG ; bank-safe copy bsf WREG,DECO_STATUS_0_FLAG ; configure init ... bsf WREG,DECO_STATUS_1_FLAG ; ... state, bcf WREG,DECO_PLAN_FLAG ; normal plan mode, bsf WREG,DECO_CNS_FLAG ; enable CNS calculation (CNS at end of dive), bcf WREG,DECO_VOLUME_FLAG ; disable gas volume calculation, and bcf WREG,DECO_ASCENT_FLAG ; disable delayed ascent calculation movff WREG,char_O_deco_status ; bank-safe copy back clrf WREG movff WREG,char_O_main_status ; reset char_O_main_status movlw deco_distance movff WREG,char_I_deco_distance movff opt_last_stop,char_I_depth_last_deco movff opt_GF_low,char_I_GF_Low_percentage movff opt_GF_high,char_I_GF_High_percentage bcf use_agf ; Start with normal GF set bcf divemode_menu ; clear divemode menu flag bcf alternative_divelayout ; Start with default layout bcf blinking_depth_prev ; clear flag for blinking depth bcf blinking_depth_warning ; clear flag for blinking depth bcf blinking_depth_toggle ; clear flag for blinking depth 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 movff int_O_CNS_fraction+0,CNS_start+0 ; save CNS value at beginning of dive movff int_O_CNS_fraction+1,WREG ; get high byte to WREG bcf WREG,int_warning_flag ; clear warning flag bit movff WREG,CNS_start+1 ; move high byte on movff int_O_gradient_factor+0,GF_start ; save GF value at beginning of dive (only lower byte used for value) bcf no_more_divesecs ; =1: do no longer show seconds in divemode bcf divemode_menu_active clrf menupos1 clrf menupos2 ; Reset to zero (Zero=no premenu or simulator task) bsf sensors_agree ; init of sensors disagree warning system btfsc FLAG_ccr_mode bra diveloop_boot_cc btfsc FLAG_pscr_mode bra diveloop_boot_cc rcall dive_boot_oc bra diveloop_boot_cont diveloop_boot_cc: rcall dive_boot_cc diveloop_boot_cont: ; 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 char_I_dil_change+0,opt_dil_change_backup+0 ; Gas change depths Diluents movff char_I_dil_change+1,opt_dil_change_backup+1 ; Gas change depths Diluents movff char_I_dil_change+2,opt_dil_change_backup+2 ; Gas change depths Diluents movff char_I_dil_change+3,opt_dil_change_backup+3 ; Gas change depths Diluents movff char_I_dil_change+4,opt_dil_change_backup+4 ; Gas change depths Diluents ; 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 clrf WREG movff WREG,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_counter1+0 ; takes care of the timeout (low byte) clrf timeout_counter1+1 ; takes care of the timeout (high byte) clrf AlarmType ; Clear all alarms bcf event_occured ; clear flag 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 surface pressure to deco routine movlw HIGH .1000 movff WREG,int_I_pres_surface+1 ; HIGH copy surface pressure to deco routine diveloop_boot_2: SAFE_2BYTE_COPY temperature,minimum_temperature ; Reset Min-Temp registers call init_recording_params ; set up all the divisors bsf ccr_diluent_setup ; For CCR mode (Required to have better gas working) btfsc FLAG_ccr_mode ; =1: CCR mode (Fixed ppO2 or Sensor) active bra divemode_boot2 btfsc FLAG_pscr_mode bra divemode_boot2 bcf ccr_diluent_setup ; For OC mode (Required to have better gas working) divemode_boot2: bcf LEDg ; switch off green LED / release reset to RX circuitry bcf LEDr ; switch off red LED 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 clrf total_divetime_seconds+1 movwf divesecs movwf apnoe_secs bsf divemode2 ; displayed divetime is running (Divetime starts HERE) return ; Done with divemode boot divemode_check_for_warnings: movlw .1 ; One warning at a time in alt. layout mode btfss alternative_divelayout movlw .2 ; Two warnings at a time in default layout mode cpfsgt warning_counter ; only one (or 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: bcf warning_active ; Clear flag clrf warning_counter ; Clear counter ; warnings sorted by severity, highest severity first ; 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 rcall check_ppO2 ; check ppO2 and displays warning, if required btfss sensors_agree ; are the sensor values within the threshold range? rcall check_warn_sensors_disagree ; NO - further evaluate btfsc sensors_agree ; are the sensor values within the threshold range? bcf sensor_warning ; YES - revoke memorized sensor warning movff char_O_deco_warnings,WREG ; bank-safe copy for deco warnings btfsc WREG,outside_warning_lock ; are we outside of the ZH-L16 model? rcall warn_outside ; YES rcall check_IBCD ; check for IBCD attention or warning btfsc decostop_active ; In deco mode? rcall check_and_store_gf_violation; Yes, sets warnings, if required movff char_O_deco_warnings,WREG ; bank-safe copy for deco warnings btfsc WREG,mbubble_warning_lock ; do we have a microbubbles warning? rcall warn_mbubbles ; YES rcall check_cns_violation ; Check CNS value and display it, if required ;btfsc decostop_active ; In deco mode? rcall check_gas_needs ; show gas needs warning if any gas need is > threshold rcall check_eod_cns_violation ; Check CNS values for end-of-dive and display warning, if required call TFT_display_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? bsf FLAG_TFT_divemode_warning ; Yes btfss warning_active ; Any warning active? bsf FLAG_TFT_divemode_warning_clear ; No, clear warning icon ; Setup warning_page number incf warning_page,F movf warning_page,W bcf STATUS,C btfss alternative_divelayout rlcf warning_page,W ; *2 (But only in standard layout mode) cpfsgt warning_counter ; > warning_counter clrf warning_page ; No, clear ; Clear both rows of warnings if there is nothing to show at all tstfsz warning_counter ; any warnings? bra divemode_check_for_warnings3 ; YES - look if second row needs to be cleared bsf FLAG_TFT_dive_warning_text_clear ; Set flag return divemode_check_for_warnings3: ; 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 bsf FLAG_TFT_dive_warning_text_clr2 ; Set flag for 2nd 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 goto TFT_update_batt_percent_divemode ; Show percent (And 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: btfsc FLAG_ccr_mode ; are we in CCR mode? bra check_ppO2_loop ; YES btfsc FLAG_pscr_mode ; are we in pSCR mode? bra check_ppO2_loop ; YES bra check_ppO2_oc_1 ; NO - neither CCR nor pSCR check_ppO2_loop: btfsc is_bailout ; in bailout? bra check_ppO2_oc_1 ; YES - continue with OC movff int_O_pure_ppO2+1,hi ; NO - get upper part of int_O_pure_ppO2 btfsc hi,int_warning_flag ; ppO2 of the pure diluent to low or high? rcall check_ppo2_display ; YES - show warning and return on next line btfsc hi,int_attention_flag ; ppO2 of the pure diluent close to setpoint? rcall check_ppo2_display ; YES - show warning and return on next line bra check_ppO2_oc_2 ; skip attention threshold test on breathed ppO2 check_ppO2_oc_1: movff int_O_breathed_ppO2+1,WREG ; get upper part of int_O_breathed_ppO2 btfsc WREG,int_attention_flag ; breathed ppO2 just above attention threshold? bra check_ppo2_display ; YES - show ppO2 check_ppO2_oc_2: movff int_O_breathed_ppO2+1,WREG ; get upper part of int_O_breathed_ppO2 (perhaps again) btfsc WREG,int_low_flag ; breathed ppO2 to low? bra check_ppO2_low ; YES - record the warning and show ppO2 btfsc WREG,int_high_flag ; breathed ppO2 to high? bra check_ppO2_high ; YES - record the warning and show ppO2 TSTOSS opt_showppo2 ; show ppO2 anyhow? (0 = no, 1 = show always) return ; NO - no warnings, no show bra check_ppo2_display ; YES - just show ppO2 check_ppO2_low: movlw d'4' ; set type of alarm (ppO2 low) bra check_ppO2_common ; continue with common part check_ppO2_high: movlw d'5' ; set type of alarm (ppO2 high) check_ppO2_common: movwf AlarmType ; copy alarm type to alarm register bsf event_occured ; set event flag bsf warning_active ; set warning flag btfsc is_bailout ; are we in bailout? bra check_ppo2_display ; YES - skip CCR/pSCR checks btfsc FLAG_ccr_mode ; are we in CCR mode? return ; YES - no extra warning required btfsc FLAG_pscr_mode ; are we in pSCR mode? return ; YES - no extra warning required check_ppo2_display: ; display warning if ppO2 is not already shown in custom view 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: movlw .10 cpfseq menupos3 ; ppO2 shown in Custom View 10? bra check_ppO2_d ; No return ; Yes, do not show twice (in custom view and in warning area) check_ppO2_d: incf warning_counter,F ; increase counter goto TFT_display_ppo2 ; show breathed gas or diluent ppO2 warning (and return) global check_cns_violation check_cns_violation: ; Check if CNS should be displayed movff int_O_CNS_fraction+1,WREG ; get high byte btfsc WREG,int_warning_flag ; warning flag set? bra check_cns_violation2 ; Yes - issue warning btfsc WREG,int_attention_flag ; attention flag set? bra display_cns_violation ; YES - just display CNS return ; No - no display, no warning 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: movlw .8 cpfseq menupos3 ; CNS shown through Custom View 8 right now? bra display_cns_violation3 ; No return ; Yes, do not show twice (in custom view and in warning area) display_cns_violation3: incf warning_counter,F ; increase counter goto TFT_display_cns ; Show CNS (and return) global check_eod_cns_violation ; check end-of-dive CNS values check_eod_cns_violation: movff int_O_CNS_fraction+1,WREG ; get high-byte of current CNS value btfsc WREG,int_warning_flag ; current CNS value in warning state? return ; YES - inhibit eod warning if current CNS is already in warning movff int_O_normal_CNS_fraction+1,WREG btfsc WREG,int_invalid_flag ; flag for invalid value set? bra check_eod_cns_violation1 ; YES - continue with checking the other CNS value btfsc WREG,int_warning_flag ; NO - flag for warning set? bra check_eod_cns_violation2 ; YES - issue warning check_eod_cns_violation1: ; NO - continue with checking the other CNS value movff int_O_alternate_CNS_fraction+1,WREG btfsc WREG,int_invalid_flag ; flag for invalid value set? return ; YES - done with CNS checking btfsc WREG,int_warning_flag ; NO - flag for warning set? bra check_eod_cns_violation2 ; Yes - issue warning return ; NO - done with CNS checking check_eod_cns_violation2: ; YES - issue warning bsf warning_active ; set Warning flag movlw .8 ; issue textual warning if CNS values are not shown in the custom view right now cpfseq menupos3 ; CNS values shown through Custom View 8 right now? bra display_eod_cns_violation ; NO - issue textual warning return ; YES - do not show twice (in custom view and in warning area) display_eod_cns_violation: incf warning_counter,F ; increase counter goto TFT_display_eod_cns ; issue CNS at end-of-dive warning (and return) global check_and_store_gf_violation check_and_store_gf_violation: movff int_O_gradient_factor+1,WREG ; get upper byte of gradient factor btfss WREG,int_warning_flag ; check if the warning flag is set bra check_and_store_gf_violation2 ; NO - continue with checking for attention flag movlw d'2' ; YES - set type of alarm movwf AlarmType ; copy to alarm register bsf event_occured ; set event flag bsf warning_active ; set warning flag bra check_and_store_gf_violation3 ; show gf warning check_and_store_gf_violation2: btfsc WREG,int_attention_flag ; check if the attention flag is set bra check_and_store_gf_violation3 ; YES - show gf TSTOSS opt_enable_IBCD ; NO - IBCD warning activated? bra check_and_store_gf_violation4 ; NO - continue checking of deco info movff char_O_deco_warnings,WREG ; YES - get the deco warnings vector btfss WREG,IBCD_warning ; is the IBCD warning flag set? bra check_and_store_gf_violation4 ; NO - continue checking for deco info check_and_store_gf_violation3: ; YES - show gf bsf warning_active ; set Warning flag incf warning_counter,F ; increase counter goto TFT_warning_gf ; show GF (and return) check_and_store_gf_violation4: ; check for deco info btfss divemode ; in divemode? return ; NO - done, return movff char_O_deco_warnings,WREG ; YES - get the deco warnings vector btfss WREG,deco_flag ; check if the deco flag is set return ; NO - all done, return incf warning_counter,F ; YES - increase counter goto TFT_info_deco ; show deco info warn_outside: incf warning_counter,F ; increase counter bsf warning_active ; Set Warning flag goto TFT_warning_outside ; show outside warning (and return) global warn_mbubbles warn_mbubbles: incf warning_counter,F ; increase counter bsf warning_active ; Set Warning flag goto TFT_warning_mbubbles ; show microbubbles 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) check_gas_needs: banksel int_O_tank_pres_need movf int_O_tank_pres_need+1,w ; get HIGH(pres need of 1st tank) iorwf int_O_tank_pres_need+3,w ; inclusive or with HIGH(pres need of 2nd tank) iorwf int_O_tank_pres_need+5,w ; inclusive or with HIGH(pres need of 3rd tank) iorwf int_O_tank_pres_need+7,w ; inclusive or with HIGH(pres need of 4th tank) iorwf int_O_tank_pres_need+9,w ; inclusive or with HIGH(pres need of 5th tank) banksel common btfsc WREG,int_invalid_flag ; check if invalid flag is set return ; YES - no further checking required btfsc WREG,int_warning_flag ; NO - check if any gas has a pres_need >= pres_fill bsf warning_active ; YES - set warning flag btfsc WREG,int_warning_flag ; NO - check if any gas has a pres_need >= pres_fill goto TFT_warning_gas_needs_warn ; Yes - show a warning btfsc WREG,int_attention_flag ; NO - check if any gas has a pres_need >= pres_fill * threshold goto TFT_warning_gas_needs_att ; YES - show an attention bcf gas_needs_attention ; NO - clear flag for a new attention bcf gas_needs_warning ; clear flag for a new warning return check_warn_sensors_disagree: incf warning_counter,F ; increase counter bsf warning_active ; YES - set Warning flag goto TFT_warning_sensor_disagree ; show sensor disagree warning (and return) check_IBCD: TSTOSS opt_enable_IBCD ; IBCD warning activated? return ; NO - done movff char_O_deco_warnings,WREG ; YES - get deco warnings vector btfss WREG,IBCD_warning ; IBCD warning flag set? return ; NO - return incf warning_counter,F ; YES - increase counter goto TFT_warning_IBCD ; write warning to display global restart_deco_engine global restart_deco_engine_wo_ceiling restart_deco_engine: ; make bank save copies and set flags for invalid data movff int_O_ceiling+1,WREG bsf WREG,char_invalid_flag ; int_O_ceiling has its invalid flag on a char's position! movff WREG,int_O_ceiling+1 restart_deco_engine_wo_ceiling: ; make more bank save copies and set more flags for invalid data movff char_O_deco_gas+0,WREG bsf WREG,char_invalid_flag movff WREG,char_O_deco_gas+0 movff int_O_ascenttime+1,WREG bsf WREG,int_invalid_flag movff WREG,int_O_ascenttime+1 movff int_O_alternate_ascenttime+1,WREG bsf WREG,int_invalid_flag movff WREG,int_O_alternate_ascenttime+1 movff int_O_normal_CNS_fraction+1,WREG bsf WREG,int_invalid_flag movff WREG,int_O_normal_CNS_fraction+1 movff int_O_alternate_CNS_fraction+1,WREG bsf WREG,int_invalid_flag movff WREG,int_O_alternate_CNS_fraction+1 movff int_O_tank_pres_need+1,WREG bsf WREG,int_invalid_flag movff WREG,int_O_tank_pres_need+1 ; restart deco engine movff char_O_deco_status,WREG ; get current deco engine configuration bcf WREG,DECO_STATUS_0_FLAG ; set status flags to... bcf WREG,DECO_STATUS_1_FLAG ; ... DECO_STATUS_START bsf WREG,DECO_PLAN_FLAG ; fake we came from alternative plan to force normal plan to be done next movff WREG,char_O_deco_status ; write back new configuration to restart deco computations return ;============================================================================= ; simulator mode ; global do_demo_divemode do_demo_divemode: call option_save_all ; Save all settings into EEPROM before starting simulation call deco_push_tissues_to_vault ; C-code: back-up status of the real tissues banksel common ; Bank1 ; +++ COMMENTED OUT FOR TESTING PURPOSE ONLY !!! +++ ; +++ DO NOT COMMENT OUT IN OPERATIONAL USE !!! +++ ; bsf restore_deco_data ; Restore tissue and CNS after simulator use bcf pressure_refresh btfss pressure_refresh ; Wait for sensor bra $-2 bsf simulatormode_active ; Set Flag ; Compute dive ambient conditions banksel char_I_bottom_depth movf char_I_bottom_depth,W mullw .100 movff PRODL,rel_pressure+0 movff PRODH,rel_pressure+1 movlw LOW (.1000) addwf PRODL,W movff WREG,sim_pressure+0 movlw HIGH (.1000) addwfc PRODH,W movff WREG,sim_pressure+1 banksel common ; Bank1 bsf divemode goto diveloop ; Switch into Divemode! END