view src/divemode.asm @ 647:357341239438

Merge
author heinrichs weikamp
date Thu, 14 Oct 2021 12:04:12 +0200
parents 7d8a4c60ec1a 5b7fe7777425
children ef2ed7e3a895
line wrap: on
line source

;=============================================================================
;
;   File divemode.asm                       * combined next generation V3.12.3
;
;   Dive Mode
;
;   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 "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"
#include "surfmode.inc"
#include "rx_ops.inc"


	extern	do_line_menu
	extern	do_main_divemenu
	extern	menu_draw_lines_divemode
	extern	menu_draw_cursor_dive
	extern	init_recording_params
	extern	option_check_and_store_all

 IFDEF _compass
	extern	TFT_dive_compass_heading
 ENDIF

 IFDEF _cave_mode
	extern	do_main_cavemenu
 ENDIF


;---- Private local Variables -------------------------------------------------

	CBLOCK	local1						; max size is 16 Byte !!!
		sensor_setpoint					; sensor ppo2 in 0.01bar for deco routine
		check_gas_num					; used in search for best gas/dil: current gas/dil number (1-5)
		check_gas_depth					; used in search for best gas/dil: current gas/dil change depth
		check_gas_type					; used in search for best gas/dil: current gas/dil type
		check_gas_O2_ratio				; used in search for best gas/dil: current gas/dil O2 ratio
		best_gas_num					; used in search for best gas/dil: best    gas/dil number (1-5)  CAUTION: there is also a variable named best_gas_number !
		best_gas_depth					; used in search for best gas/dil: best    gas/dil change depth
		last_pressure_velocity:2		; cached last absolute pressure for velocity calculation
		TFT_output_flags_1				; TFT update flags for output phase 1
		TFT_output_flags_2				; TFT update flags for output phase 2
		TFT_output_flags_3				; TFT update flags for output phase 3
		TFT_output_flags_4				; TFT update flags for output phase 4
		DM_flags_local					; various dive mode flags
	ENDC								; used: 14 byte, remaining: 2 byte

	CBLOCK	local2						; max size is 16 Byte !!!
		pressure_rel_accu_trip:4		; pressure accumulator for calculating the resettable average depth
		pressure_rel_accu_total:4		; pressure accumulator for calculating the total dive average depth
		ppO2_min:2						; used in search for best gas/dil: minimum ppO2 required
		ppO2_max_default:2				; used in search for best gas/dil: default  maximum ppO2
		ppO2_max_deco:2					; used in search for best gas/dil: deco     maximum ppO2
	ENDC								; used: 14 byte, remaining: 2 byte


;---- Private local Flags ----------------------------------------------------

; TFT_output_flags_1 - phase 1: every second - before deco calculations, all modes
#DEFINE FLAG_TFT_depth_current			TFT_output_flags_1,0	; =1: show  current depth
#DEFINE FLAG_TFT_depth_maximum			TFT_output_flags_1,1	; =1: show  maximum depth
#DEFINE FLAG_TFT_active_gas_divemode	TFT_output_flags_1,2	; =1: show  active gas and dive mode
#DEFINE FLAG_TFT_apnoe_surface_time		TFT_output_flags_1,3	; =1: show  apnoe mode surface time
#DEFINE FLAG_TFT_depth_maximum_apnoe	TFT_output_flags_1,4	; =1: show  maximum depth of last apnoe dive
#DEFINE FLAG_TFT_clear_apnoe_surface	TFT_output_flags_1,5	; =1: clear apnoe mode surface data from screen
#DEFINE FLAG_TFT_apnoe_divetime			TFT_output_flags_1,6	; =1: show  apnoe mode dive times
#DEFINE FLAG_TFT_temperature			TFT_output_flags_1,7	; =1: show  temperature (or resettable dive time when in compass view)

; TFT_output_flags_2 - phase 2: every second - before deco calculations, deco modes only
#DEFINE FLAG_TFT_divemode_mask			TFT_output_flags_2,0	; =1: show  dive mode mask
#DEFINE FLAG_TFT_divetime				TFT_output_flags_2,1	; =1: show  dive time
#DEFINE FLAG_TFT_safety_stop_show		TFT_output_flags_2,2	; =1: show  safety stop
#DEFINE FLAG_TFT_safety_stop_clear		TFT_output_flags_2,3	; =1: clear safety stop
;										TFT_output_flags_2,4	; --- unused
;										TFT_output_flags_2,5	; --- unused
;										TFT_output_flags_2,6	; --- unused
;										TFT_output_flags_2,7	; --- unused

; TFT_output_flags_3 - phase 3: every second - after deco calculations, deco modes only
#DEFINE FLAG_TFT_clear_deco_data		TFT_output_flags_3,0	; =1: clear deco data (NDL or stop & TTS)
#DEFINE FLAG_TFT_display_ndl_mask		TFT_output_flags_3,1	; =1: show  NDL  mask
#DEFINE FLAG_TFT_display_deco_mask		TFT_output_flags_3,2	; =1: show  deco mask
#DEFINE FLAG_TFT_display_ndl			TFT_output_flags_3,3	; =1: show  NDL  data
#DEFINE FLAG_TFT_display_deco			TFT_output_flags_3,4	; =1: show  deco stop data
#DEFINE FLAG_TFT_display_tts			TFT_output_flags_3,5	; =1: show  deco TTS  data
;										TFT_output_flags_3,6	; --- unused
;										TFT_output_flags_3,7	; --- unused

; TFT_output_flags_4 - phase 4: every second - after deco calculations, all modes
#DEFINE FLAG_TFT_customview_callup		TFT_output_flags_4,0	; =1: show  the custom view mask
#DEFINE FLAG_TFT_sign_show				TFT_output_flags_4,1	; =1: show  the advice / attention / warning sign
#DEFINE FLAG_TFT_sign_clear				TFT_output_flags_4,2	; =1: clear the advice / attention / warning sign
#DEFINE FLAG_TFT_message_clear_both		TFT_output_flags_4,3	; =1: clear messages, both rows
#DEFINE FLAG_TFT_message_clear_2nd		TFT_output_flags_4,4	; =1: clear messages, 2nd row only
#DEFINE FLAG_TFT_velocity_show			TFT_output_flags_4,5	; =1: show  vertical velocity
#DEFINE FLAG_TFT_velocity_clear			TFT_output_flags_4,6	; =1: clear vertical velocity
;										TFT_output_flags_4,7	; --- unused


; various Flags
#DEFINE new_deco_data_avail				DM_flags_local,0		; =1: new NDL or deco data available
#DEFINE update_menu						DM_flags_local,1		; =1: redraw the dive menu
#DEFINE FLAG_SP2_used					DM_flags_local,2		; =1: setpoint 2 has been auto-selected already
#DEFINE FLAG_SP3_used					DM_flags_local,3		; =1: setpoint 3 has been auto-selected already
#DEFINE FLAG_SP4_used					DM_flags_local,4		; =1: setpoint 4 has been auto-selected already
#DEFINE FLAG_SP5_used					DM_flags_local,5		; =1: setpoint 5 has been auto-selected already
;										DM_flags_local,6		; --- unused
;										DM_flags_local,7		; --- unused


;=============================================================================
dmode1	CODE
;=============================================================================


;-----------------------------------------------------------------------------
; Entry Point for Dive Mode
;
	global	diveloop
diveloop:
	clrf	STKPTR						; clear return addresses stack

	; start with a clean time base
	bsf		reset_timebase				; request ISR to reset the main timebase,
										; as we are in dive mode the dive timers will be reset as well

	; reset global flags
	clrf	DM_flags_state				; clear all flags for dive mode status
	clrf	DM_flags_event				; clear all flags for data recording events
	clrf	DM_flags_request			; clear all flags for user requests / general
 IFDEF _cave_mode
	clrf	DM_flags_cavereq			; clear all flags for user requests / cave mode
 ENDIF
	clrf	DM_flags_layout1			; clear all flags for display control / layout (1)
	clrf	DM_flags_layout2			; clear all flags for display control / layout (2)
	clrf	DM_flags_layout3			; clear all flags for display control / layout (3)
	clrf	DM_flags_message			; clear all flags for display control / messages
	clrf	DM_flags_gas_dil			; clear all flags for display control / gases, diluents, depth

	clrf	DM_flags_advc_det			; clear all flags for advices    detection
	clrf	DM_flags_advc_ack			; clear all flags for advices    acknowledged

	clrf	DM_flags_att1_det			; clear all flags for attentions detection
	clrf	DM_flags_att2_det			; ...
	clrf	DM_flags_att3_det			; ...

	clrf	DM_flags_att1_ack			; clear all flags for attentions acknowledged
	clrf	DM_flags_att2_ack			; ...
	clrf	DM_flags_att3_ack			; ...

	clrf	DM_flags_war1_det			; clear all flags for warnings   detection
	clrf	DM_flags_war2_det			; ...

	clrf	DM_flags_war1_ack			; clear all flags for warnings   acknowledged
	clrf	DM_flags_war2_ack			; ...

	clrf	DM_flags_shown1				; arm auto show-up of custom views
	clrf	DM_flags_shown2				; ...
	clrf	DM_flags_shown3				; ...

	bcf		dive_main_menu				; clear dive main menu flag
	bcf		dive_pre_menu				; clear dive  pre-menu flag

	; reset local flags
	clrf	TFT_output_flags_1			; clear all flags for TFT output phase 1
	clrf	TFT_output_flags_2			; clear all flags for TFT output phase 2
	clrf	TFT_output_flags_3			; clear all flags for TFT output phase 3
	clrf	TFT_output_flags_4			; clear all flags for TFT output phase 4
	clrf	DM_flags_local				; clear all the various other flags, too

	; boot tasks for all modes
	call	diveloop_boot				; initialize dive mode

	; startup tasks for all modes
	call	TFT_boot					; initialize TFT (includes clear screen)
	call	TFT_load_dive_color_pallet	; load dive color pallet
	call	TFT_show_divemode_mask		; display static dive mode mask
	call	TFT_Display_FadeIn			; dim up the display

	; arm dive start timer
	bcf		divetime_longer_1min		; the dive has just begun
	btfsc	FLAG_apnoe_mode				; in apnea mode?
	bsf		divetime_longer_1min		; YES - force dive to have lasted for longer than 1 minute already
	btfsc	sensor_override_active		; in simulator mode?
	bsf		divetime_longer_1min		; YES - force dive to have lasted for longer than 1 minute already

	; initiate initial display outputs
	bsf		trigger_pres_cur_changed	; flag that the pressures have changed to have all data...
	bsf		trigger_pres_max_changed	; ... written to the display on the first output round
	bsf		trigger_temp_changed		; flag that the temperature has changed to have the temperature ...
										; ... written to the display on the first output round
	bsf		new_deco_data_avail			; flag that new deco engine results are available to have the initial data ...
										; ... written to the display on the first output round

	; initialize the resettable average depth
	call	resettable_average_depth_init

	; reload and redraw last custom view
	movff	customview_divemode,active_customview
	bsf		FLAG_TFT_customview_callup

	btfsc	FLAG_apnoe_mode				; in apnoe mode?
	bra		diveloop_1					; YES - done with initialization
	btfsc	FLAG_gauge_mode				; NO  - in gauge mode?
	bra		diveloop_1					;       YES - done with initialization
	bsf		FLAG_TFT_display_ndl_mask	;       NO  - request initial display of NDL mask
	bsf		FLAG_TFT_active_gas_divemode;           - request initial display of gas and setpoint

diveloop_1:
	btfsc	reset_timebase				; has the ISR confirmed reset of the timebase meanwhile?
	bra		$-2							; NO  - not yet, loop waiting for confirmation before entering the dive loop
	;bra	diveloop_loop				; YES - enter the dive loop


;-----------------------------------------------------------------------------
; Dive Mode Mail Loop
;
diveloop_loop:
	btfss	trigger_quarter_second			; new 1/4 second?
	bra		diveloop_loop_0				;       No - continue

	;---- tasks any new 1/4 second -----
	bcf		trigger_quarter_second		; YES - clear flag

	movlw	.4					; 62,5ms * 4 = 1/4 second
	movff	WREG,isr_tmr7_helper			; to make sure at least 1/4 will pass before trigger_quarter_second is re-set

	btfss	press_sensor_type			; New sensor found?
	bra 	diveloop_loop_0				;       No - continue

	; Handle new pressure sensor every 1/4 second
	btfsc	ms5837_state				; =0: result of temperature is in the ADC
	bra	diveloop_loop_quarter_2
	call	I2C_get_temp_val_MS5837			; (Will set ms5837_state)
	bra	diveloop_loop_0				;  Done.
diveloop_loop_quarter_2:
	call	I2C_get_press_val_MS5837		; (Will clear ms5837_state)
	;---- tasks any new 1/4 second done -----

diveloop_loop_0:	
        btfsc	trigger_full_second			; new 1/1 second?
	bra		diveloop_loop_2				; YES - continue with tasks every 1/1 second
	btfsc	trigger_half_second			; NO  - new 1/2 second?
	bra		diveloop_loop_1				;       YES - continue with tasks every 1/2 second

	; tasks every round except every 1/1 or 1/2 second
 IFDEF _compass
	movlw	index_compass_dm			; index of compass view
	cpfseq	active_customview			; in compass view?
	bra		diveloop_loop_11			; NO  - continue with tasks every round
	call	TFT_dive_compass_heading	; YES - update compass heading value
	bsf		FLAG_TFT_temperature		;     - redraw temperature (will show resettable dive time now)
 ENDIF
	bra		diveloop_loop_11			;     - continue tasks every round

diveloop_loop_1:
	; tasks every 1/2 second
	bcf		trigger_half_second			; clear flag
	btfsc	FLAG_gauge_mode				; in gauge mode?
	bra		diveloop_loop_11			; YES - done with 1/2 second tasks
	btfsc	FLAG_apnoe_mode				; NO  - in apnoe mode?
	bra		diveloop_loop_11			; YES - done with 1/2 second tasks

	; tasks every 1/2 second in deco modes
	call	callup_deco_engine			; ##### manage and invoke the deco calculation engine #####
	bra		diveloop_loop_11			; done with 1/2 second tasks

diveloop_loop_2:
	; tasks every 1/1 second (code includes tasks every 1/2 second that fall onto the full second)
	bcf		trigger_full_second			; clear flag for new 1/1 second
	bcf		trigger_half_second			; clear flag for new 1/2 second as well

	btfss	trigger_temp_changed		; has the temperature changed?
	bra		diveloop_loop_3				; NO  - continue with tasks every 1/1 second

	bsf		FLAG_TFT_temperature		; YES - display temperature
	bcf		trigger_temp_changed		;     - clear flag

	; "future hardware will need min temperature checked every second..." (?)

	MOVII	temperature_min,sub_a		;     - copy last temperature_min to sub_a
	SMOVII	temperature_cur,sub_b		;     - ISR-safe 2 byte copy of current temperature to sub_b
	call	sub16						;     - sub_c = sub_a - sub_b = temperature_min - temperature
	btfsc	neg_flag					;     - temperature > temperature_min ?
	bra		diveloop_loop_3				;       YES - done
	MOVII	sub_b,temperature_min		;       NO  - store new minimum temperature

diveloop_loop_3:
	; tasks every 1/1 second
	btfss	trigger_pres_cur_changed	; has the pressure changed?
	bra		diveloop_loop_4				; NO  - continue with tasks every 1/1 second

	; set flags
	bcf		trigger_pres_cur_changed	; clear flag for pressure change
	bsf		FLAG_TFT_depth_current		; set flag to display updated depth

	; cache new absolute and relative pressure, ISR-safe 2 byte copies
	SMOVII	pressure_abs,    pressure_abs_cached
	SMOVII	pressure_rel_cur,pressure_rel_cur_cached

	; transfer absolute pressure to deco engine
	MOVII	pressure_abs_cached,int_I_pres_respiration

	; compute absolute pressure / 10, will be used later on a couple of times
	MOVII	pressure_abs_cached,xA
	MOVLI	.10,xB
	call	div16x16					; xC = xA / xB = absolute pressure / 10
	MOVII	xC,pressure_abs_10			; store result for later use

	; compute current depth in meters
	MOVII	pressure_rel_cur_cached,mpr	; copy current relative pressure in [mbar] to MPR
	call	convert_pres_to_depth		; convert pressure in [mbar] to depth in [cm]
	ADDLI	.50,mpr						; add 50 cm for rounding up/down around 0.5 meters
	MOVII	mpr, xA						; copy depth in [cm]   into xA
	MOVLI	.100,xB						; load factor 100 cm/m into xB
	call	div16x16					; xC = xA / xB = depth in full meters
	movff	xC+0,depth_meter			; store result as depth in [m], only low byte needed

	; check for new max pressure
	btfss	trigger_pres_max_changed	; has the max pressure changed?
	bra		diveloop_loop_4				; NO  - continue with tasks every 1/1 second
	bcf		trigger_pres_max_changed	; YES - clear flag for new max pressure
	bsf		FLAG_TFT_depth_maximum		;     - set   flag for displaying new max depth
	SMOVII	pressure_rel_max,pressure_rel_max_cached ; - cache new max depth

diveloop_loop_4:
	; continue tasks every 1/1 second

 IFDEF _ccr_pscr
	; adjust auto-setpoint
	btfsc	FLAG_ccr_mode				; in CCR mode?
	call	check_dive_autosp			; YES - check for Auto-SP
 ENDIF

 IFDEF _external_sensor
	btfsc	FLAG_ccr_mode				; in CCR mode?
	rcall	calc_deko_divemode_sensor	; YES - process sensor readings
	btfsc	FLAG_pscr_mode				; in pSCR mode?
	rcall	calc_deko_divemode_sensor	; YES - process sensor readings
 ENDIF

 IFDEF _cave_mode
	btfss	cave_mode					; cave mode switched on?
	bra		diveloop_loop_4a			; NO  - no backtracking depth recording
	btfsc	dive_turned					; dive turned?
	bra		diveloop_loop_4a			; YES - no backtracking depth recording
	btfsc	backtrack_entire_full		; backtracking storage entirely used up?
	bra		diveloop_loop_4a			; YES - no backtracking depth recording

	incf	backtrack_deltatime,F		; increment time elapsed since last depth recording
	movlw	.59							; load WREG with coding of last second of a minute
	cpfsgt	backtrack_deltatime			; time elapsed since last depth recording > 59 seconds?
	bra		diveloop_loop_4a			; NO  - no backtracking depth recording now
	rcall	write_backtrack_1min_depth	;     - store a backtracking depth data set
 ENDIF

diveloop_loop_4a:
	; continue tasks every 1/1 second

	btfsc	FLAG_apnoe_mode				; in apnoe mode?
	rcall	divemode_apnoe_tasks		; YES - do 1 sec. apnoe tasks

	; display all animated (blinking) values at the beginning of each full second to have a stable timebase
	rcall	TFT_output_1				; do display updates

	btfss	FLAG_apnoe_mode				; in apnoe mode?
	bra		diveloop_loop_5				; NO  - continue with deco mode tasks every 1/1 second

	; apnoe mode tasks every 1/1 second
	call	dive_customview_second		; do every second tasks for the custom view area
	bra		diveloop_loop_10			; continue with common tasks every 1/1 second

diveloop_loop_5:
	; deco mode tasks every 1/1 second
	bsf		FLAG_TFT_divetime			; display (new) dive time

	rcall	safety_stop_show			; serve safety stop

	rcall	TFT_output_2				; do display updates

	call	divemode_check_warnings		; check for warnings

 IFDEF _rx_functions
	btfss	tr_functions_activated		; TR functions activated?
	bra		diveloop_loop_6				; NO  - continue with deco mode tasks every 1/2 second
	call	get_pressure_readings		; YES - get  pressure readings
	call	configure_sac_calculation	;     - set up SAC calculation
 ENDIF

diveloop_loop_6:
	; deco mode tasks every 1/1 second
	INCI	divesecs_avg_trip			; increment the resettable dive time
	INCI	divesecs_avg_total			; increment the total      dive time

	btfsc	FLAG_gauge_mode				; in gauge mode?
	bra		diveloop_loop_7				; YES - skip deco calculations

	call	callup_deco_engine			; ##### manage and invoke the deco calculation engine #####

	btfsc	new_deco_data_avail			; new NDL or deco data available?
	call	show_new_deco_data			; YES - set-up display update requests

	btfsc	decostop_active				; in deco mode?
	bsf		FLAG_TFT_display_deco		; YES - update deco stop depth & time every second because of depth-dependent color-coding

	bsf		FLAG_TFT_depth_current		; set flag to display depth (in next round, needed in deco modes irrespectively of a pressure change for color-coding and blinking effects)

diveloop_loop_7:
	; deco mode tasks alternating every 2 seconds on timebase
	btfss	timebase_1sec				; on even second of timebase?
	rcall	calc_velocity				; YES - calculate velocity and display if > threshold
	btfsc	timebase_1sec				; on odd  second of timebase?
	call	check_gas_best				; YES - check if a better gas cue can be given

diveloop_loop_8:
	; deco mode tasks alternating every 2 seconds on resettable dive time
	btfss	divesecs_avg_trip+0,0		; on even second of resettable dive time?
	call	calc_average_depth			; YES - calculate average depth
	btfsc	divesecs_avg_trip+0,0		; on odd  second of resettable dive time?
	rcall	safety_stop_control			; YES - exercise safety stop control

diveloop_loop_9:
	; deco mode tasks every 1/1 second
	rcall	check_deco_states			; check and lock if in deco and in the deco stops region
	rcall	TFT_output_3				; do display updates

diveloop_loop_10:
	; common tasks every 1/1 second
	rcall	timeout_divemode			; check for timeout conditions
	call	check_dive_modes_dive		; test if depth still deeper than threshold

	btfsc	trigger_full_minute			; has next minute begun?
	rcall	update_divemode60			; YES - update clock, etc.

	btfss	FLAG_oc_mode				; are we in OC mode?
	bsf		FLAG_TFT_active_gas_divemode; NO - have the gas and setpoint redrawn on every second to update setpoint display, animate the blinking, etc.

	btfsc	dive_main_menu				; dive mode menu shown?
	bsf		update_menu					; YES - request update

	rcall	TFT_output_4				; do display updates

; tasks every round, every mode
diveloop_loop_11:
	call	test_switches_divemode		; check switches, in case branch into menu processor
	bra		diveloop_loop_12			; continue the dive loop


	; **** jump-in when returning from menu processor ****
	;
	global	divemode_option_divemenu_return
divemode_option_divemenu_return:
	clrf	STKPTR						; reset the stack
	call	menu_draw_cursor_dive		; show the cursor
	bsf		dive_main_menu				; set main menu   is     shown now
	clrf	active_premenu				; set pre-menu    is not shown any more
	bcf		safety_stop_active			; set safety stop is not shown any more
	movlw	divemode_timeout_mainmenu	; get timeout for main menu
	call	restart_timeout_time		; restart the timeout
	bra		diveloop_loop_12			; continue the dive loop


	; **** jump-in when returning from dive mode menu ****
	;
	global	diveloop_menu_exit
diveloop_menu_exit:
	clrf	STKPTR						; reset the stack
	call	divemenu_cleanup			; clean up menu area and restore dive data
	;bra	diveloop_loop_12			; continue the dive loop


diveloop_loop_12:
    	bsf		FLAG_TFT_active_gas_divemode; redraw gas and setpoint (eventually needed to restore the "Bailout" text)

	btfsc	request_next_custview		; shall show next custom view?
	call	dive_customview_toggle		; YES - show next custom view

	btfsc	request_gas_change			; shall change gas?
	call	gas_switch_common			; YES

	btfsc	request_gas_update			; shall update the gases?
	call	gas_update_common			; YES

	btfsc	request_toggle_GF			; shall toggle GF/aGF?
	call	divemodemode_togglegf		; YES

 IFDEF _cave_mode
	btfsc	request_cave_off_turned		; shall switch cave mode off and set the dive as turned?
	rcall	cavemode_switch_off_turned	; YES

	btfsc	request_cave_toggle			; shall toggle cave mode off/on?
	rcall	cavemode_toggle_onoff		; YES

	btfsc	request_turn_turn			; shall turn the dive?
	rcall	cavemode_turndive_turn		; YES

	btfsc	request_turn_toggle			; shall toggle the turn dive state?
	rcall	cavemode_turndive_toggle	; YES

	btfsc	request_waypoint_set		; shall set a waypoint?
	rcall	cavemode_waypoint_set		; YES

	btfsc	request_waypoint_out		; shall step one waypoint out of the cave?
	rcall	cavemode_waypoint_out		; YES

	btfsc	request_waypoint_in			; shall step one waypoint into the cave?
	rcall	cavemode_waypoint_in		; YES
 ENDIF

	btfsc	request_set_marker			; shall set a marker?
	call	set_logbook_marker			; YES

	btfsc	trigger_sample_divedata		; shall store new sample of dive data?
	call	store_dive_data				; YES - store profile data

	btfss	divemode					; dive finished?
	goto	ghostwriter_end_dive		; YES - dive finished

 IFDEF _screendump
	btfsc	screen_dump_avail			; screen dump function enabled?
	call	TFT_dump_screen_check		; YES - check if requested and do it
 ENDIF

	bra		diveloop_loop				; do next loop in dive mode


;-----------------------------------------------------------------------------
; Dive Mode Tasks every 1/1 Minute
;
update_divemode60:
	bcf		trigger_full_minute			; clear flag

	call	get_battery_voltage			; get battery voltage
	btfss	battery_low_condition		; battery low condition detected?
	bra		update_divemode60_1			; NO  - skip next
	movlw	d'7'						; YES - set type of alarm = battery low
	movwf	alarm_type					;     - copy to alarm register
	bsf		event_occured				;     - set event flag
	movlw	.0							;     - coding of brightness level ECO
	movff	WREG,opt_brightness_divemode			;     - set brightness to ECO

update_divemode60_1:
	; max allowed runtime in simulator is 254 minutes in
	; order for the tissue calculation catch-up to work!

	btfss	sensor_override_active		; in simulator mode?
	return								; NO  - done
	movlw	simulator_timeout_normal	; YES - set simulation timeout
 IFDEF _cave_mode
	TSTOSC	opt_cave_mode				;     - cave mode switched on?
	movlw	simulator_timeout_cave		;       YES - replace with cave mode simulation timeout
 ENDIF
	cpfsgt	counted_divetime_mins+0		;     - timeout?
	return								;       NO  - done
 IFDEF _DEBUG
	return								;       YES - but we do not care in debug mode...
 ELSE
	goto	divemode_option_sim_quit	;       YES - set depth to 0 m and return
 ENDIF


;-----------------------------------------------------------------------------
; Helper Function - set-up Display Update Requests
;
show_new_deco_data:
	bcf		new_deco_data_avail			; reset flag for new NDL or deco data available
	movff	char_O_deco_info,WREG		; get the deco info vector
	btfsc	WREG,deco_stops_norm		; deco stops found?
	bra		show_new_deco_data_deco		; YES - in deco
	;bra	show_new_deco_data_ndl		; NO  - within NDL

show_new_deco_data_ndl:					; within NDL
	btfsc	decostop_active				; been in deco mode before?
	bsf		FLAG_TFT_clear_deco_data	; YES - clear old deco data
	btfsc	decostop_active				; been in deco mode before?
	bsf		FLAG_TFT_display_ndl_mask	; YES - display NDL data mask
	bcf		decostop_active				; clear flag for been in deco mode before
	bsf		FLAG_TFT_display_ndl		; display NDL time
	return								; done

show_new_deco_data_deco:				; in deco
	btfss	decostop_active				; been in deco mode before?
	bsf		FLAG_TFT_clear_deco_data	; NO - clear old NDL data
	btfss	decostop_active				; been in deco mode before?
	bsf		FLAG_TFT_display_deco_mask	; NO - display deco data mask
	bsf		decostop_active				; set flag for being in deco mode
	bsf		FLAG_TFT_display_tts		; display TTS time (display of stop data is managed separately)
	return								; done


;-----------------------------------------------------------------------------
; Helper Function - do all Phase 1 Display Outputs
;
TFT_output_1:								; every second - before deco calculations, all mode
	btfsc	FLAG_TFT_clear_apnoe_surface	; shall clear apnoe mode surface data from screen?
	call	TFT_clear_apnoe_surface			; YES - clear apnoe mode surface data from screen

	btfsc	FLAG_TFT_depth_current			; shall show depth?
	call	TFT_show_depth					; YES - display depth
	btfsc	FLAG_TFT_depth_maximum			; shall show max depth?
	call	TFT_show_max_depth				; YES - display max depth
	btfsc	FLAG_TFT_active_gas_divemode	; shall show active gas and dive mode?
	call	TFT_show_active_gas_divemode	; YES - display gas, setpoint and mode
	btfsc	FLAG_TFT_temperature			; shall show temperature?
	call	TFT_show_temp_divemode			; YES - display temperature (or resettable dive time)

	btfsc	FLAG_TFT_apnoe_surface_time		; shall show apnoe mode surface time?
	call	TFT_show_apnoe_surface			; YES - show apnoe mode surface time
	btfsc	FLAG_TFT_depth_maximum_apnoe	; shall show max. depth of last dive?
	call	TFT_show_apnoe_max_depth		; YES - show max. depth of last dive
	btfsc	FLAG_TFT_apnoe_divetime			; shall show apnoe dive time?
	call	TFT_show_apnoe_times			; YES - show apnoe dive time?

	clrf	TFT_output_flags_1				; mark all TFT updates done
	return									; done


;-----------------------------------------------------------------------------
; Helper Function - do all Phase 2 Display Outputs
;
TFT_output_2:								; every second - before deco calculations, deco modes only
	btfsc	FLAG_TFT_divemode_mask			; shall re-draw mask?
	call	TFT_show_divemode_mask			; YES - re-draw mask
	btfsc	FLAG_TFT_divetime				; shall show dive time?
	call	TFT_show_divetime				; YES - show dive time
	btfsc	FLAG_TFT_safety_stop_show		; shall show safety stop?
	call	TFT_safety_stop_show			; YES - show safety stop
	btfsc	FLAG_TFT_safety_stop_clear		; shall clear safety stop?
	call	TFT_safety_stop_clear			; YES - clear safety stop
	clrf	TFT_output_flags_2				; mark all TFT updates done
	goto	dive_customview_second			; do every-second tasks for the custom view area (in sync with the dive time) and return


;-----------------------------------------------------------------------------
; Helper Function - do all Phase 3 Display Outputs
;
TFT_output_3:								; every second - after deco calculations, deco modes only
	btfsc	FLAG_TFT_clear_deco_data		; shall clear deco data (NDL or stop & TTS)?
	call	TFT_clear_deco_data				; YES - clear deco data (NDL or stop & TTS)
	btfsc	FLAG_TFT_display_ndl_mask		; shall show NDL mask?
	call	TFT_show_ndl_mask				; YES - show NDL mask
	btfsc	FLAG_TFT_display_ndl			; shall show NDL data?
	call	TFT_show_ndl					; YES - show NDL data
	btfsc	FLAG_TFT_display_deco_mask		; shall show deco mask?
	call	TFT_show_deco_mask				; YES - show deco mask
	btfsc	FLAG_TFT_display_deco			; shall show deco stop?
	call	TFT_show_deco					; YES - show deco stop
	btfsc	FLAG_TFT_display_tts			; shall show deco TTS?
	call	TFT_show_tts					; YES - show deco TTS
	clrf	TFT_output_flags_3				; mark all TFT updates done
	return									; done


;-----------------------------------------------------------------------------
; Helper Function - do all Phase 4 Display Outputs
;
TFT_output_4:								; every second - after deco calculations, all modes
	btfsc	FLAG_TFT_customview_callup		; shall show a custom view?
	call	dive_customview_callup			; YES - show a custom view
	btfsc	FLAG_TFT_velocity_show			; shall show  vertical velocity?
	call	TFT_velocity_show				; YES - show  vertical velocity
	btfsc	FLAG_TFT_velocity_clear			; shall clear vertical velocity?
	call	TFT_velocity_clear				; YES - clear vertical velocity
	btfsc	FLAG_TFT_sign_show				; shall show  the advice / attention / warning sign?
	call	TFT_divemode_sign_show			; YES - show sign
	btfsc	FLAG_TFT_sign_clear				; shall clear the advice / attention / warning sign?
	call	TFT_divemode_sign_clear			; YES - clear sign
	btfsc	FLAG_TFT_message_clear_both		; shall clear all messages?
	call	TFT_clear_message_window		; YES - clear complete message area
	btfsc	FLAG_TFT_message_clear_2nd		; shall clear 2nd row of message area?
	call	TFT_clear_message_window_row2	; YES - clear 2nd row of message area
	clrf	TFT_output_flags_4				; mark all TFT updates done
	return									; done


;-----------------------------------------------------------------------------
; Apnoe Mode Tasks
;
divemode_apnoe_tasks:						; 1 sec. apnoe tasks
	bsf		FLAG_TFT_apnoe_divetime			; show apnoe dive times (current/last dive and total)
	btfsc	apnoe_at_surface				; at the surface?
	bra		divemode_apnoe_tasks_surf		; YES  - at the surface
	;bra	divemode_apnoe_tasks_dive		; NO   - in dive phase

divemode_apnoe_tasks_dive:					; apnoe mode, submerged
	btfss	apnoe_new_dive					; new dive begun?
	return									; NO  - done
	bcf		apnoe_new_dive					; YES - clear flag
	bsf		FLAG_TFT_clear_apnoe_surface	;     - clear apnoe mode surface data from screen
	return									;     - done

divemode_apnoe_tasks_surf:					; apnoe mode, at the surface
	bsf		FLAG_TFT_apnoe_surface_time		; show apnoe mode surface time
	; TODO: these outputs would need to be done only once after surfacing...
	bsf		FLAG_TFT_depth_maximum_apnoe	; show max. depth of last dive
	bsf		FLAG_TFT_depth_maximum			; show max. depth of all  dives
	;bra	apnoe_calc_maxdepth				; calculate overall max. depth and return


;-----------------------------------------------------------------------------
; Helper Function - calculate Apnoe Mode overall maximum Depth
;
	global	apnoe_calc_maxdepth
apnoe_calc_maxdepth:
	MOVII	apnoe_max_pressure,     sub_a				; get max depth from all dives to far
	MOVII	pressure_rel_max_cached,sub_b				; get max depth of last dive
	call	cmpU16										; sub_a - sub_b = apnoe_max_pressure - pressure_rel_max_cached
	btfss	neg_flag									; last dive deeper than all the others before?
	return												; NO  - done
	MOVII	pressure_rel_max_cached,apnoe_max_pressure	; YES - store new overall max depth
	return												;     - done


;-----------------------------------------------------------------------------
; Manage and invoke the Deco Calculation Engine
;
callup_deco_engine:

	; Any reconfiguration done here only affects the deco calculation (prediction), not the
	; settings for the calculations done on the real tissues. The later ones are only altered
	; in case of a gas change, in case of a real bailout, or in case a switchback to setpoint
	; or sensor is done.
	; On event of a gas change, a diluent change, a real bailout, or a switchback, the settings
	; for the deco calculation are also automatically changed to match with the settings for the
	; real tissues. This is all done in the function 'gas_switch_common' which is triggered by
	; the flag 'request_gas_change'.

	; Deco Engine Calculation Schedules:
	;
	; Schedule  Dive Mode  Bailout  fTTS   Gas Needs    Plan    Deco Mode  calculated Functions
	; -----------------------------------------------------------------------------------------------------
	;
	;   1a)        OC       no       no      (yes)      norm       OC      TTS, CNS, deco plan, (gas needs)
	;                                                no alt plan
	;
	;   1b)        OC       no       YES     (yes)      norm       OC      TTS,  CNS, deco plan
	;                                                   alt        OC      fTTS, fCNS, (gas needs)
	;
	;   2a)       Loop      no       no       no        norm      Loop     TTS,  CNS, deco plan
	;                                                no alt plan
	;
	;   2b)       Loop      no       yes      no        norm      Loop     TTS,  CNS, deco plan
	;                                                   alt       Loop     fTTS, fCNS
	;
	;   2c)       Loop      no      (yes)     YES       norm      Loop     TTS,  CNS, deco plan
	;                                                   alt        OC      fTTS*, fCNS*, gas needs      <- "what if" BAILOUT
	;
	;   3)        Loop      YES      n/a     (yes)      norm       OC      TTS, deco plan, (gas needs)  <-   real    BAILOUT
	;                                                no alt plan
	; _____________________________________________________________________________________________________
	; norm: normal plan, alt: alternative plan, (): optional, n/a: not applicable
	; * the fTTS time is set to zero when in cave mode and the dive is in turned state


	; get working copies of char_O_main_status and char_O_deco_status
	movff	char_O_main_status,hi		; get char_O_main_status into hi
	movff	char_O_deco_status,lo		; get char_O_deco_status into lo

	; check state of deco calculations
	btfsc	request_restart_engine		; restart of the deco engine requested?
	bra		calc_deco_engine_restart	; YES - start a new normal plan
	btfsc	lo,DECO_COMPLETED_NORM		; NO  - finished calculations for normal plan?
	bra		calc_deco_engine_alt		;       YES - eventually do an alternative plan next
	btfsc	lo,DECO_COMPLETED_ALT		;       NO  - finished calculations for alternative plan?
	bra		calc_deco_engine_norm		;             YES - do a normal plan next
	bra		calc_deco_engine_exec		;             NO  - continue executing current calculation

calc_deco_engine_restart:
	bcf		request_restart_engine		; clear request flag
	bcf		lo,DECO_COMPLETED_NORM		; clear completion flag from normal plan if applicable
	;bra	calc_deco_engine_norm		; continue with calculating a normal plan


	; ---- normal plans ----
	;
calc_deco_engine_norm:
	bcf		lo,DECO_COMPLETED_ALT		; clear completion flag from alternative plan
 IFDEF _ccr_pscr
	btfsc	bailout_mode				; in real bailout?
	bra		calc_deco_engine_norm_3		; YES - configure real bailout schedule
	btfss	FLAG_oc_mode				; in OC dive mode?
	bra		calc_deco_engine_norm_2		; NO  - configure loop schedules
	;bra	calc_deco_engine_norm_1		; YES - configure OC   schedules
 ENDIF

calc_deco_engine_norm_1:
	; normal OC schedules
	TSTOSC	char_I_extra_time			; delay mode activated?
	bra		calc_deco_engine_norm_1b	; YES - schedule 1b in normal plan
	;bra	calc_deco_engine_norm_1a	; NO  - schedule 1a in normal plan

calc_deco_engine_norm_1a:
	; normal schedule 1a: OC with optional gas needs
;	bcf		lo,DECO_BAILOUT_FLAG		; switch off bailout mode						(will never be activated in this plan)
;	bcf		lo,DECO_DELAY_FLAG			; switch off delay mode							(will never be activated in this plan)
;	bcf		hi,DECO_VOLUME_FLAG			; switch off gas needs calculation by default	(if on, will always be on)
	TSTOSC	opt_calc_gasvolume			; shall calculate gas needs?
	bsf		hi,DECO_VOLUME_FLAG			; YES - switch on gas needs calculation
	bra		calc_deco_engine_norm_start	; start deco engine in normal plan

calc_deco_engine_norm_1b:
	; normal schedule 1b: OC without delay and gas needs
;	bcf		lo,DECO_BAILOUT_FLAG		; switch off bailout mode						(will never be activated in this plan)
	bcf		lo,DECO_DELAY_FLAG			; switch off delay mode
	bcf		hi,DECO_VOLUME_FLAG			; switch off gas needs calculation
	bra		calc_deco_engine_norm_start	; start deco engine in normal plan

 IFDEF _ccr_pscr
calc_deco_engine_norm_2:
	; normal loop schedules
	TSTOSC	opt_calc_gasvolume			; gas needs calculation activated?
	bra		calc_deco_engine_norm_2c	; YES - schedule  2c in normal plan
	;bra	calc_deco_engine_norm_2ab	; NO  - schedules 2a and 2b in normal plan are identical

calc_deco_engine_norm_2ab:
	; normal schedule 2a & 2b: loop without anything
	bcf		lo,DECO_BAILOUT_FLAG		; switch off bailout mode						(may return from real bailout)
;	bcf		hi,DECO_VOLUME_FLAG			; switch off gas needs calculation				(will never be activated in this plans)
	bcf		lo,DECO_DELAY_FLAG			; switch off delay mode							(may have been set in alt. plan 2b)
	bra		calc_deco_engine_norm_start	; start deco engine in normal plan

calc_deco_engine_norm_2c:
	; normal schedule 2c: loop with switch-back from simulated bailout
	; switch to CCR/pSCR
	movf	active_dil,W				; get current diluent
	call	deco_setup_cc_diluents_pre	; set up deco calculation in CCR/pSCR mode with diluents
calc_deco_engine_norm_2c_XX:
	bcf		lo,DECO_BAILOUT_FLAG		; switch off bailout mode						(may return from real bailout)
	bcf		hi,DECO_VOLUME_FLAG			; switch off gas needs calculation
	bcf		lo,DECO_DELAY_FLAG			; switch off delay mode
	bra		calc_deco_engine_norm_start	; start deco engine in normal plan

calc_deco_engine_norm_3:
	; real bailout schedule
	bcf		lo,DECO_DELAY_FLAG			; switch off delay mode
	bcf		hi,DECO_VOLUME_FLAG			; switch off gas needs calculation by default
	TSTOSC	opt_calc_gasvolume			; shall calculate gas needs?
	bsf		hi,DECO_VOLUME_FLAG			; YES - switch on gas needs calculation
	bsf		lo,DECO_BAILOUT_FLAG		; switch on bailout mode
	;bra	calc_deco_engine_norm_start	; start deco engine in normal plan
 ENDIF	; _ccr_pscr

calc_deco_engine_norm_start:
	bsf		lo,DECO_START_NORM			; calculate a normal plan
	bra		calc_deco_engine_start		; start deco engine


	; ---- alternative plans ----
	;
calc_deco_engine_alt:
	bcf		lo,DECO_COMPLETED_NORM		; clear completion flag from normal plan
 IFDEF _ccr_pscr
	btfsc	bailout_mode				; in real bailout?
	bra		calc_deco_engine_norm_3		; YES - schedule 3 has no alternative plan
	btfss	FLAG_oc_mode				; in OC dive mode?
	bra		calc_deco_engine_alt_2		; NO  - loop schedules
	;bra	calc_deco_engine_alt_1		; YES - OC   schedules
 ENDIF	; _ccr_pscr

calc_deco_engine_alt_1:
	; alternative OC schedules
	TSTOSS	char_I_extra_time			; delay mode activated?
	bra		calc_deco_engine_norm_1a	; NO  - schedule 1a has no alternative plan
 IFDEF _cave_mode
	btfsc	dive_turned					; YES - in cave mode and dive turned?
	bra		calc_deco_engine_norm_1a	;       YES - suppress delay mode -> do schedule 1a in normal plan
 ENDIF
	;bra	calc_deco_engine_alt_1b		;       NO  - do schedule 1b in alternative plan

calc_deco_engine_alt_1b:
	; alternative schedule 1b: OC with delay and optional gas needs
;	bcf		lo,DECO_BAILOUT_FLAG		; switch off bailout mode						(will never be activated in this plan)
;	bcf		hi,DECO_VOLUME_FLAG			; switch off gas needs calculation by default	(comes in switched off state)
	TSTOSC	opt_calc_gasvolume			; shall calculate gas needs?
	bsf		hi,DECO_VOLUME_FLAG			; YES - switch on gas needs calculation
	bsf		lo,DECO_DELAY_FLAG			; switch on delay mode
	bra		calc_deco_engine_alt_start	; start deco engine in alternative plan

 IFDEF _ccr_pscr
calc_deco_engine_alt_2:
	; alternative loop schedules
	TSTOSC	opt_calc_gasvolume			; gas needs calculation activated?
	bra		calc_deco_engine_alt_2c		; YES - 2c in alternative plan
	TSTOSS	char_I_extra_time			; NO  - delay mode activated?
	bra		calc_deco_engine_norm_2ab	;       NO  - schedule 2a has no alternative plan
	;bra	calc_deco_engine_alt_2b		;       YES - schedule 2b in alternative plan

calc_deco_engine_alt_2b:
	; alternative schedule 2b: loop with delay
;	bcf		lo,DECO_BAILOUT_FLAG		; switch off bailout mode						(will be deactivated in normal plan)
;	bcf		hi,DECO_VOLUME_FLAG			; switch off gas needs calculation				(will never be activated in this plan)
	bsf		lo,DECO_DELAY_FLAG			; switch on  delay mode
	bra		calc_deco_engine_alt_start	; start deco engine in normal plan

calc_deco_engine_alt_2c:
	; alternative schedule 2c: simulated bailout (if possible)
	decf	best_gas_number,W			; get best gas number -1 into WREG. If not available, WREG will be 255 now. If not computed yet, WREG will be 254 now.
	btfsc	WREG,7						; WREG < 128 (a bailout gas is available)?
	bra		calc_deco_engine_alt_2c_XX	; NO  - no bailout plan possible because no bailout gas available to switch to
	movf	best_gas_number,W			; YES - get number of best gas into WREG
	call	deco_setup_oc_gases_pre		;     - set up deco calculation in OC mode with OC gases
;	bcf		lo,DECO_DELAY_FLAG			;     - switch off delay mode by default		(comes in switched off state)
	TSTOSC	char_I_extra_time			;     - delay mode activated?
	bsf		lo,DECO_DELAY_FLAG			;       YES - switch on delay mode
 IFDEF _cave_mode
	btfsc	dive_turned					;       in cave mode and dive turned?
	bcf		lo,DECO_DELAY_FLAG			;       YES - suppress delay mode
 ENDIF
	bsf		lo,DECO_BAILOUT_FLAG		;     - switch on bailout mode
	bsf		hi,DECO_VOLUME_FLAG			;     - switch on gas needs calculation
	bra		calc_deco_engine_alt_start	;     - start deco engine in alternative plan
calc_deco_engine_alt_2c_XX:
	call	inval_alternative_plan_data	; invalidate all alternative (bailout) plan data because they are not applicable any more
	bra		calc_deco_engine_norm_start	; continue calculating as normal plan
 ENDIF	; _ccr_pscr

calc_deco_engine_alt_start:
	bsf		lo,DECO_START_ALT			; calculate an alternative plan
	;bra	calc_deco_engine_start		; start deco engine


	; ---- start deco engine ----
	;
calc_deco_engine_start:
 IFDEF _cave_mode
	bcf		hi,DECO_CAVE_MODE			; deactivate cave mode by default
	btfss	cave_mode					; cave mode switched on?
	bra		calc_deco_engine_start_1	; NO  - keep deactivated, no backtracking depth recording
	bsf		hi,DECO_CAVE_MODE			; YES - activate cave mode
	btfss	dive_turned					;     - dive turned?
	call	write_backtrack_deltatime	;       NO  - update current delta time
 ENDIF
calc_deco_engine_start_1:
	movff	hi,char_O_main_status		; write-back char_O_main_status to deco engine interface
	movff	lo,char_O_deco_status		; write-back char_O_deco_status to deco engine interface

calc_deco_engine_exec:
;	+++++++++++++++++++++++++++++++++++++
	bsf		tmr5_preemtion_allowed		; grant  preemption allowance for timer 5 (deco engine)
	call	deco_calc_hauptroutine		; invoke the deco engine (C-code)
	banksel	common						; back to bank common
	bcf		tmr5_preemtion_allowed		; revoke preemption allowance
;	+++++++++++++++++++++++++++++++++++++

 ifdef _debug_output
	call	TFT_debug_output			; debug output of scheduling performance data
 endif

	; check if new calculation results for normal plan mode are available
	movff	char_O_deco_status,WREG		; get deco status of deco engine
	btfsc	WREG,DECO_COMPLETED_NORM	; new calculation results for normal plan available?
	bsf		new_deco_data_avail			; YES - set flag for new NDL or deco data available

	return								; done


 IFDEF _ccr_pscr
 IFDEF _external_sensor

;-----------------------------------------------------------------------------
; Process Sensor Readings
;
	global	calc_deko_divemode_sensor
calc_deko_divemode_sensor:
	btfsc	ext_input_optical				; do we have an optical interface?
	bra		calc_deko_divemode_sensor_opt	; YES - process received data
	btfss	ext_input_s8_ana				; NO  - do we have a S8/analog interface?
	return									;       NO  - nothing to do, done
	TSTOSS	opt_s8_mode						;       YES - shall use S8 interface?
	bra		calc_deko_divemode_sensor_ana	;           - NO  - use analog interface
	;bra	calc_deko_divemode_sensor_s8	;             YES - use S8     interface

calc_deko_divemode_sensor_s8:
	btfss	trigger_S8_data_update			; new data frame available?
	bra		calc_deko_divemode_sensor_common; NO  - use old values
	bcf		trigger_S8_data_update			; YES - clear update flag
	call	compute_mvolts_from_rawdata	;     - compute mV values from digital data
	bra		calc_deko_divemode_sensor_common;     - continue with common part

calc_deko_divemode_sensor_opt:
	; sensor1_ppO2, sensor2_ppO2 and sensor3_ppO2 are already filled in ISR
	btfss	sensor1_active					; check HUD status data and eventually clear use_O2_sensorX
	bcf		use_O2_sensor1					; ...
	btfss	sensor2_active					; ...
	bcf		use_O2_sensor2					; ...
	btfss	sensor3_active					; ...
	bcf		use_O2_sensor3					; ...
	bra		check_sensor_avg				; continue with calculating sensor average

calc_deko_divemode_sensor_ana:
	call	get_analog_inputs				; get the analog voltages and continue with the common part
	;bra	calc_deko_divemode_sensor_common; continue with common part

calc_deko_divemode_sensor_common:

	; Check 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 sensor 1
	btfss	sensor1_calibrated_ok		; check if sensor is usable at all
	bra		check_sensor_1_fail			; NO  - handle it as failed
	SMOVII	sensor1_mv,sub_a			; YES - load sensor mV value

	; check min threshold
	rcall	check_min_threshold			; check if sensor mV is outside minimum
	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_threshold
	rcall	check_max_threshold			; check if sensor mV is outside maximum
	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
	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 - HUD status ok?
	bra		check_sensor_1_fail			;       NO - HUD reports a fail

check_sensor_1_ok:
	; sensor1_ppO2 = sensor1_mv:2 * opt_x_s1:2 / 1000
	SMOVII	sensor1_mv,xA				; get sensor mV          into xA
	MOVII	opt_x_s1,  xB				; get calibration factor into xB
	rcall	compute_ppo2_helper			; compute ppO2
	movff	xC+0,sensor1_ppO2			; result in 0.01 bar
	bcf		attn_det_sensor1_lost		; clear attention
	bcf		shown_sensor1_fail			; re-arm custom-view show-up
	bra		check_sensor_2				; continue with next sensor

check_sensor_1_fail:
	clrf	WREG						; set ppO2 reading to zero
	movff	WREG,sensor1_ppO2			; ...
	btfsc	use_O2_sensor1				; check if sensor is in use
	bsf		attn_det_sensor1_lost		; YES - set an attention
	bcf		use_O2_sensor1				; revoke sensor from usage

check_sensor_2:
	; check sensor 2
	btfss	sensor2_calibrated_ok		; check if sensor is usable at all
	bra		check_sensor_2_fail			; NO  - handle it as failed
	SMOVII	sensor2_mv,sub_a			; YES - load sensor mV value

	; check min threshold
	rcall	check_min_threshold			; check if sensor mV is outside minimum
	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_threshold
	rcall	check_max_threshold			; check if sensor mV is outside maximum
	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
	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 - HUD status ok?
	bra		check_sensor_2_fail			;       NO - HUD reports a fail

check_sensor_2_ok:
	; sensor2_ppO2 = sensor2_mv:2 * opt_x_s2:2 / 1000
	SMOVII	sensor2_mv,xA				; get sensor mV          into xA
	MOVII	opt_x_s2,  xB				; get calibration factor into xB
	rcall	compute_ppo2_helper			; compute ppO2
	movff	xC+0,sensor2_ppO2			; result in 0.01 bar
	bcf		attn_det_sensor2_lost		; clear attention
	bcf		shown_sensor2_fail			; re-arm custom-view show-up
	bra		check_sensor_3				; continue with next sensor

check_sensor_2_fail:
	clrf	WREG						; set ppO2 reading to zero
	movff	WREG,sensor2_ppO2			; ...
	btfsc	use_O2_sensor2				; check if sensor is in use
	bsf		attn_det_sensor2_lost		; YES - set an attention
	bcf		use_O2_sensor2				; revoke sensor from usage

check_sensor_3:
	; check sensor 3
	btfss	sensor3_calibrated_ok		; check if sensor is usable at all
	bra		check_sensor_3_fail			; NO  - handle it as failed
	SMOVII	sensor3_mv,sub_a			; YES - load sensor mV value

	; check min threshold
	rcall	check_min_threshold			; check if sensor mV is outside minimum
	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 threshold
	rcall	check_max_threshold			; check if sensor mV is outside maximum
	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
	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 - HUD status ok?
	bra		check_sensor_3_fail			;       NO - HUD reports a fail

check_sensor_3_ok:
	; sensor3_ppO2 = sensor3_mv:2 * opt_x_s1:2 / 1000
	SMOVII	sensor3_mv,xA				; get sensor mV          into xA
	MOVII	opt_x_s3,  xB				; get calibration factor into xB
	rcall	compute_ppo2_helper			; compute ppO2
	movff	xC+0,sensor3_ppO2			; result in 0.01 bar
	bcf		attn_det_sensor3_lost		; clear attention
	bcf		shown_sensor3_fail			; re-arm custom-view show-up
	bra		check_sensor_avg			; continue with calculating sensor average

check_sensor_3_fail:
	clrf	WREG						; set ppO2 reading to zero
	movff	WREG,sensor3_ppO2			; ...
	btfsc	use_O2_sensor3				; check if sensor is in use
	bsf		attn_det_sensor3_lost		; YES - set an attention
	bcf		use_O2_sensor3				; revoke sensor from usage

check_sensor_avg:
	; calculate sensor average
	btfss	divemode					; in dive mode?
	return								; NO - done here if not in dive mode

	; compute sensor_setpoint = average of all o2_ppo2_sensorX of
	; those sensors that have use_O2_sensorX == true

	CLRI	xA							; clear sum of sensor values
	CLRI	xB							; clear number of active sensors found

check_sensor_avg_1:
	btfss	use_O2_sensor1				; sensor 1 active?
	bra		check_sensor_avg_2			; NO
	movff	sensor1_ppO2,WREG			; YES - get ppO2
	addwf	xA+0,F						;     - add into xA:2
	movlw	.0							;     - ...
	addwfc	xA+1,F						;     - ... 
	incf	xB+0,F						;     - add a sensor

check_sensor_avg_2:
	btfss	use_O2_sensor2				; sensor 2 active?
	bra		check_sensor_avg_3			; NO
	movff	sensor2_ppO2,WREG			; YES - get ppO2
	addwf	xA+0,F						;     - add into xA:2
	movlw	.0							;     - ...
	addwfc	xA+1,F						;     - ...
	incf	xB+0,F						;     - add a sensor

check_sensor_avg_3:
	btfss	use_O2_sensor3				; sensor 3 active?
	bra		check_sensor_avg_compute	; NO
	movff	sensor3_ppO2,WREG			; YES - get ppO2
	addwf	xA+0,F						;     - add into xA:2
	movlw	.0							;     - ...
	addwfc	xA+1,F						;     - ...
	incf	xB+0,F						;      add a sensor

check_sensor_avg_compute:
	; divide sum of sensor values by number of active sensors found
	clrf	xC+0						; set zero as default result
	tstfsz	xB+0						; pending div/0 ?
	call	div16x16					; NO - execute xC = xA / xB = summed ppO2 / number of sensors
	movff	xC+0,sensor_setpoint		; copy result (or its default)

	; 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						; pre-load 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	bailout_mode				; check if we are in bailout
	bra		check_sensor_vote			; YES - no sensor data transfer to char_I_const_ppO2 in this case
	movf	dive_ccr_mode,W				; NO  - get mode (0: Fixed SP, 1: Sensor, 2: Auto SP)
	sublw	.1							;     - in sensor mode?
	bnz		check_sensor_vote			;       NO  - not in sensor mode - no transfer of sensor data to char_I_const_ppO2
	tstfsz	xB+0						;       YES - check if we have found at least one usable sensor
	bra		check_sensor_avg_use		;             YES - we have at least one usable sensor
	bsf		warn_det_sensors_lost		;             NO  - we have NO usable sensors
	btfsc	FLAG_ccr_mode				;                 - check if we are in CCR mode
	movff	opt_setpoint_cbar+0,char_I_const_ppO2 ;         YES - select fixed setpoint no. 1 for fallback
	bra		check_sensor_vote			;                       - continue with voting logic flags

check_sensor_avg_use:
	; we have at least one usable sensor with a ppO2 value > 0
	bcf		warn_det_sensors_lost				; clear warning
	bcf		shown_sensors_lost					; re-arm custom view show-up
	movff	sensor_setpoint,char_I_const_ppO2	; transfer average sensor value to p2_deco.c code

check_sensor_vote:
	; check if individual sensors agree with their average
	bsf		voting_logic_sensor1		; default sensor to be within voting
	movff	sensor1_ppO2,WREG			; get sensor's ppO2
	rcall	check_sensor_voting_helper	; check if sensor is within +/- range around setpoint
	tstfsz	WREG						; sensor within range (WREG = 0)?
	bcf		voting_logic_sensor1		; NO - vote out this sensor

	bsf		voting_logic_sensor2		; default sensor to be within voting
	movff	sensor2_ppO2,WREG			; get sensor's ppO2
	rcall	check_sensor_voting_helper	; check if sensor is within +/- range around setpoint
	tstfsz	WREG						; sensor within range (WREG = 0)?
	bcf		voting_logic_sensor2		; NO - vote out this sensor

	bsf		voting_logic_sensor3		; default sensor to be within voting
	movff	sensor3_ppO2,WREG			; get sensor's ppO2
	rcall	check_sensor_voting_helper	; check if sensor is within +/- range around setpoint
	tstfsz	WREG						; sensor within range (WREG = 0)?
	bcf		voting_logic_sensor3		; NO - vote out 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_0			; YES - continue with further checks
	btfsc	FLAG_pscr_mode				; check if we are in pSCR mode
	bra		check_warn_sensor_0			; YES - continue with further checks
	bra		check_warn_sensor_done		; not in CCR and not in pSCR, so no warning

check_warn_sensor_0:					; we are in CCR or pSCR mode
	btfsc	bailout_mode				; check if we are in bailout
	bra		check_warn_sensor_done		; YES - no warning in this case
	movf	dive_ccr_mode,W				; get mode (0: Fixed SP, 1: Sensor, 2: Auto SP)
	sublw	.1							; in sensor mode?
	bnz		check_warn_sensor_done		; NO - not in sensor mode - no warning in this case

check_warn_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
	bsf		warn_det_sensors_div		;             NO  - sensors divergence
	return								;                 - done

check_warn_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
	bsf		warn_det_sensors_div		;             NO  - sensors divergence
	return								;                 - done

check_warn_sensor_3:
	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
	bsf		warn_det_sensors_div		;             NO  - set warning
	return								;                 - done

check_warn_sensor_done:
check_warn_sensor_agree:
	bcf		warn_det_sensors_div		; clear warning
	bcf		shown_sensors_diverg		; re-arm custom view show-up
	return								; done


;-----------------------------------------------------------------------------
; Helper Function - check if sensor mV is outside minimum
;
check_min_threshold:
	MOVLI	min_mv,sub_b				; load minimum mV value
	goto	sub16						; sub_c = sensor_mv - min_mv (and return)


;-----------------------------------------------------------------------------
; Helper Function - check if sensor mV is outside maximum
;
check_max_threshold:
	MOVLI	max_mv,sub_b				; load maximum mV value
	goto	sub16						; sub_c = sensor_mv - max_mv (and return)


;-----------------------------------------------------------------------------
; Helper Function - compute ppO2 from sensor mV and calibration factor
;
compute_ppo2_helper:
	call	mult16x16					; xC:4 = xA:2 * xB:2
	MOVLI	.1000,xB					; load scaling factor
	call	div32x16					; xC:4 = xC:4 / xB:2 with xA as remainder
	tstfsz	xC+1						; is the ppO2 higher than 2.55 bar?
	setf	xC+0						; YES - set result to 255 aka 2.55 bar
	return								; done


;-----------------------------------------------------------------------------
; Helper Function - check if sensor is within +/- range around setpoint
;
check_sensor_voting_helper:
	subwf	sensor_setpoint,W				; deviation = setpoint - sensor ppO2
	btfsc	STATUS,N						; result negative?
	negf	WREG,W							; YES - negate deviation
	sublw	sensor_voting_logic_threshold	; WREG = threshold - deviation
	btfss	STATUS,N						; result negative?
	retlw	.0								; NO  - within range
	retlw	.1								; YES - out of range

;	cpfsgt	sensor_setpoint					; sensor ppO2 > setpoint?
;	bra		check_sensor_voting_helper_2	; NO
;	;bra	check_sensor_voting_helper_1	; YES
;
;check_sensor_voting_helper_1:
;	subwf	sensor_setpoint,W				; WREG = setpoint - sensor ppO2
;	bra		check_sensor_voting_helper_com	; continue with common part
;
;check_sensor_voting_helper_2:
;	movwf	lo								; copy sensor ppO2 to lo
;	movf	sensor_setpoint,W				; copy setpoint    to WREG
;	subwf	lo,W							; WREG = sensor ppO2 - setpoint
;	;bra	check_sensor_voting_helper_com	; continue with common part
;
;check_sensor_voting_helper_com:
;	movwf	lo								; copy deviation to lo
;	movlw	sensor_voting_logic_threshold	; load threshold in 0.01 bar
;	cpfsgt	lo								; deviation > threshold ?
;	retlw	.0								; NO  - within range
;	retlw	.1								; YES - out of range

 ENDIF	; _external_sensor
 ENDIF	; _ccr_pscr


 IFDEF _cave_mode

;-----------------------------------------------------------------------------
; Cave Mode - on/off Switching
;
cavemode_toggle_onoff:
	bcf		request_cave_toggle			; clear request flag
	btg		cave_mode					; toggle the on/off state
	return								; done


;-----------------------------------------------------------------------------
; Cave Mode - switch off and set Dive as turned
;
cavemode_switch_off_turned:
	bcf		request_cave_off_turned		; clear request flag
	bcf		cave_mode					; switch cave mode off
	bra		cavemode_turndive_turn_exec ; set dive as turned (and return)


;-----------------------------------------------------------------------------
; Cave Mode - check if 'turn dive' is allowed
;
	global	cavemode_turndive_check
cavemode_turndive_check:
	btfss	cave_mode					; cave mode switched on?
	retlw	1							; NO - signal not allowed
	btfss	dive_turned					; YES - is the dive currently turned?
	retlw	0							;       NO  - command is allowed
	movf	backtrack_waypoint_turn,W	;       YES - copy turn point number to WREG
	cpfslt	backtrack_waypoint_num		;           - current waypoint number < turn point number ?
	retlw	1							;             NO  - signal not allowed
	retlw	0							;             YES - command is allowed


;-----------------------------------------------------------------------------
; Cave Mode - execute 'turn dive' toggle
;
cavemode_turndive_toggle:
	bcf		request_turn_toggle			; clear request flag
	rcall	cavemode_turndive_check		; check if command is allowed
	tstfsz	WREG						; command allowed?
	return								; NO  - abort
	btfss	dive_turned					; YES - is the dive currently turned?
	bra		cavemode_turndive_turn_exec	;       NO  - turn the dive
	bcf		dive_turned					;       YES - set dive         as not turned    any more
	bcf		backtrack_shutdown			;           - set backtracking as not shut down any more
	call	set_logbook_marker			;           - set a logbook marker
	goto	resume_backtrack_recording	;           - append further logging after current waypoint and return


;-----------------------------------------------------------------------------
; Cave Mode - set the dive as turned
;
cavemode_turndive_turn:
	bcf		request_turn_turn			; clear request flag
	btfss	cave_mode					; cave mode switched on?
	return								; NO  - abort
	btfsc	dive_turned					; YES - is the dive already turned?
	return								;       YES - nothing to do any more
cavemode_turndive_turn_exec:
	bsf		dive_turned					;       NO  - set dive as turned
	call	set_logbook_marker			;           - set a logbook marker
	goto	write_backtrack_turnpoint	;           - write a turn-point waypoint and return


;-----------------------------------------------------------------------------
; Cave Mode - check if setting a Waypoint is allowed
;
	global	cavemode_waypoint_set_check
cavemode_waypoint_set_check:
	btfss	cave_mode					; cave mode switched on?
	retlw	1							; NO - command not allowed
	btfsc	dive_turned					; YES - is the dive turned?
	retlw	1							;       YES - no setting of waypoints on way out, command not allowed
	btfsc	backtrack_entire_full		;       NO  - storage entirely used up?
	retlw	1							;             YES - out of storage capacity, command not allowed
	movlw	backtrack_waypoint_max		;             NO  - get highest allowed waypoint number
	cpfslt	backtrack_waypoint_num		;                 - current waypoint number < max allowed number?
	retlw	1							;                   NO  - command not allowed
	retlw	0							;                   YES - command is  allowed


;-----------------------------------------------------------------------------
; Cave Mode - set a Waypoint
;
cavemode_waypoint_set:
	bcf		request_waypoint_set		; clear request flag
	rcall	cavemode_waypoint_set_check	; check if command is allowed to execute
	tstfsz	WREG						; command allowed?
	return								; NO  - no waypoint setting possible, abort
	call	set_logbook_marker			; YES - set a logbook marker
	goto	write_backtrack_waypoint	;     - execute command (and return)


;-----------------------------------------------------------------------------
; Cave Mode - check if stepping one Waypoint outwards is allowed
;
	global	cavemode_waypoint_out_check
cavemode_waypoint_out_check:
	btfss	cave_mode					; cave mode switched on?
	retlw	1							; NO - command not allowed
	btfss	dive_turned					; YES - is the dive turned?
	retlw	1							;       NO  - no stepping back on way in, command not allowed
	btfsc	waypoint_reached_first		;       YES - already at first waypoint?
	retlw	1							;             YES - command not allowed
	retlw	0							;             NO  - command is  allowed


;-----------------------------------------------------------------------------
; Cave Mode - step one Waypoint outwards
;
cavemode_waypoint_out:
	bcf		request_waypoint_out		; clear request flag
	rcall	cavemode_waypoint_out_check	; check if command is allowed to execute
	tstfsz	WREG						; command allowed?
	return								; NO  - no further out possible, abort
	goto	backtrack_waypoint_go_out	; YES - execute the command (and return)


;-----------------------------------------------------------------------------
; Cave Mode - check if stepping one Waypoint inwards is allowed
;
	global	cavemode_waypoint_in_check
cavemode_waypoint_in_check:
	btfss	cave_mode					; cave mode switched on?
	retlw	1							; NO - command not allowed
	btfss	dive_turned					; YES - is the dive turned?
	retlw	1							;       NO  - no stepping forward on way in, command not allowed
	btfsc	waypoint_reached_last		;       YES - already at last waypoint?
	retlw	1							;             YES - command not allowed
	retlw	0							;             NO  - command is  allowed


;-----------------------------------------------------------------------------
; Cave Mode - step one Waypoint inwards
;
cavemode_waypoint_in:
	bcf		request_waypoint_in			; clear request flag
	rcall	cavemode_waypoint_in_check	; check if command is allowed to execute
	tstfsz	WREG						; command allowed?
	return								; NO  - no further in possible, abort
	goto	backtrack_waypoint_go_in	; YES - execute command (and return)


;-----------------------------------------------------------------------------
; Cave Mode - store current Delta Time
;
write_backtrack_deltatime:
	rcall	setup_backtrack_index				; setup writing position
	bra		write_backtrack_datum_deltatime		; store the current delta time (and return)


;-----------------------------------------------------------------------------
; Cave Mode - store a Backtracking Depth Data Set
;
write_backtrack_1min_depth:
	rcall	setup_backtrack_index				; setup writing position
	rcall	write_backtrack_datum_depth			; store depth
	rcall	write_backtrack_datum_zerotime		; reset the time elapsed since last depth recording and store it
	bra		write_backtrack_datum_check			; store new writing position, check remaining storage capacity ()and return)


;-----------------------------------------------------------------------------
; Cave Mode - store a Waypoint
;
write_backtrack_waypoint:
	rcall	setup_backtrack_index				; setup writing position
	rcall	write_backtrack_datum_deltatime		; store the time elapsed since last depth recording
	movf	POSTINC1,W							; dummy read to increment the writing position index
	rcall	write_backtrack_datum_depth			; store depth
	rcall	write_backtrack_datum_gas			; store gas availability vector
	rcall	write_backtrack_datum_waypoint		; store waypoint number
	rcall	write_backtrack_datum_zerotime		; reset the time elapsed since last depth recording and store it
	bra		write_backtrack_datum_check			; store new writing position, check remaining storage capacity (and return)


;-----------------------------------------------------------------------------
; Cave Mode - store a Turn Point
write_backtrack_turnpoint:
	rcall	write_backtrack_waypoint			; write a waypoint (see above)
	movf	POSTDEC1,W							; dummy read to decrement the position index to the waypoint number datum
	movff	FSR1L,char_I_backtrack_index		; store updated writing position
	movff	backtrack_waypoint_num,backtrack_waypoint_turn; memorize this waypoint as turn point
	return										; done


;-----------------------------------------------------------------------------
; Cave Mode - append further Logging after current Waypoint
;
resume_backtrack_recording:
	clrf	backtrack_waypoint_turn				; clear turn point reference
	bsf		waypoint_reached_last				; declare to be at last waypoint now
	rcall	setup_backtrack_index				; setup index position
	movf	POSTINC1,W							; dummy read to increment the position index to the delta time datum
	rcall	write_backtrack_datum_zerotime		; reset the time elapsed since last depth recording and store it
	bra		write_backtrack_datum_check			; store new writing position, check remaining storage capacity (and return)


;-----------------------------------------------------------------------------
; Cave Mode - execute stepping one Waypoint outwards
;
backtrack_waypoint_go_out:
	bcf		waypoint_reached_last				; not at last waypoint (or turn point) any more
	rcall	setup_backtrack_index				; setup index position
	movlw	b'11100000'-.1						; a waypoint datum has bits 5-7 set, -1 because of cpfsgt
backtrack_waypoint_go_out_loop:
	movff	POSTDEC1,lo							; dummy read current datum and go to previous datum (there is no PREDEC)
	cpfsgt	INDF1								; read datum, is it a waypoint datum?
	bra		backtrack_waypoint_go_out_loop		; NO - try next datum
	movff	FSR1L,char_I_backtrack_index		; store new index position
	movf	INDF1,W								; copy waypoint datum to WREG
	andlw	b'00011111'							; remove waypoint tag
	movwf	backtrack_waypoint_num				; store new waypoint number
	movlw	.1									; number of first waypoint
	cpfsgt	backtrack_waypoint_num				; current waypoint number > number of first waypoint ?
	bsf		waypoint_reached_first				; NO - reached first waypoint
	goto	restart_deco_engine_wo_norm			; invalidate all alternative plan data and restart deco engine


;-----------------------------------------------------------------------------
; Cave Mode - execute stepping one Waypoint inwards
;
backtrack_waypoint_go_in:
	bcf		waypoint_reached_first				; not at first waypoint any more
	rcall	setup_backtrack_index				; setup index position
	movlw	b'11100000'-.1						; a waypoint datum has bits 5-7 set, -1 because of cpfsgt
backtrack_waypoint_go_in_loop:
	cpfsgt	PREINC1								; go to next datum, read it, is it a waypoint datum?
	bra		backtrack_waypoint_go_in_loop		; NO - try next datum
	movff	FSR1L,char_I_backtrack_index		; store new index position
	movf	INDF1,W								; copy waypoint datum to WREG
	andlw	b'00011111'							; remove waypoint tag
	movwf	backtrack_waypoint_num				; store new waypoint number
	movf	backtrack_waypoint_turn,W			; load WREG with waypoint number of turn point
	cpfslt	backtrack_waypoint_num				; new waypoint number < number of turn point ?
	bsf		waypoint_reached_last				; NO - reached last waypoint
	goto	restart_deco_engine_wo_norm			; invalidate all alternative plan data and restart deco engine


;-----------------------------------------------------------------------------
; Cave Mode Helper Function - set up Index Position
;
setup_backtrack_index:
	lfsr	FSR1,char_I_backtrack_storage		; load   FSR1 with base address of the backtracking storage
	movff	char_I_backtrack_index,FSR1L		; adjust FSR1 to the current index position
	return


;-----------------------------------------------------------------------------
; Cave Mode Helper Function - reset Time since last Depth Recording and store it
;
write_backtrack_datum_zerotime:
	clrf	backtrack_deltatime					; reset the time elapsed since last depth recording
	;bra	write_backtrack_datum_deltatime		; store the time


;-----------------------------------------------------------------------------
; Cave Mode Helper Function - store Time elapsed since last Depth Recording
;
write_backtrack_datum_deltatime:
	movf	backtrack_deltatime,W				; get   the time elapsed since last depth recording
	bsf		WREG,7								; add   the time marker (bit 7 set) to the time stored in WREG
	movwf	INDF1								; write the time and keep the writing position index pointing on it
	return										; done


;-----------------------------------------------------------------------------
; Cave Mode Helper Function - store Depth
;
write_backtrack_datum_depth:
	movf	depth_meter,W						; get current depth in meters into WREG
	btfsc	WREG,7								; current depth < 128 m ?
	movlw	.127								; NO - clip depth to 127 meters (protect time marker bit)
	movwf	POSTINC1							; write the depth entry and increment the writing position index
	return										; done


;-----------------------------------------------------------------------------
; Cave Mode Helper Function - store Gas Availability Vector
;
write_backtrack_datum_gas:
	; Cave mode is currently only available with gas needs calculation enabled,
	; so deco mode is either OC anyhow or CCR/pSCR in bailout mode. Hence it is
	; always the OC (bailout) gases whose staging status needs to be stored.
	lfsr	FSR2,opt_gas_type					; load base address of the OC/bailout gas types
	movlw	NUM_GAS								; load number of gases
	movwf	lo									; initialize loop counter
	movlw	b'00000001'							; load  gas bit pattern for the first gas
	movwf	hi									; store gas bit pattern in hi
	movlw	b'11000000'							; initialize WREG with the gas staging status tag
write_backtrack_datum_gas_loop:
	movff	POSTINC2,up							; get gas type and increment index
	btfsc	up,gas_staged						; gas staged?
	iorwf	hi,W								; YES - set respective gas bit
	rlncf	hi,F								; rotate gas bit pattern to match the next gas
	decfsz	lo,F								; decrement loop counter, did it became zero?
	bra		write_backtrack_datum_gas_loop		; NO  - loop
	movwf	POSTINC1							; YES - write the gas staging status entry and increment the writing position index
	return										;     - done


;-----------------------------------------------------------------------------
; Cave Mode Helper Function - store a Waypoint Number
;
write_backtrack_datum_waypoint:
	incf	backtrack_waypoint_num,F			; increment the waypoint number
	movf	backtrack_waypoint_num,W			; copy waypoint number to WREG
	iorlw	b'11100000'							; add the waypoint marker (bit 7-5 set) to the number stored in WREG
	movwf	POSTINC1							; write the waypoint datum and increment the writing position index
	movlw	.2									; load a 2 into WREG
	cpfslt	backtrack_waypoint_num				; new waypoint number >= 2 ?
	bcf		waypoint_reached_first				; YES - not at first waypoint any more
	return										; done


;-----------------------------------------------------------------------------
; Cave Mode Helper Function - store new writing position and check remaining storage capacity
;
write_backtrack_datum_check:
	movff	FSR1L,char_I_backtrack_index		; store new index position
	movlw	backtrack_almost_full_threshold		; load threshold for backtracking storage almost full
	bcf		backtrack_almost_full				; clear almost full state
	cpfslt	FSR1L								; index < threshold ?
	bsf		backtrack_almost_full				; NO - flag backtracking storage is almost full
	movlw	backtrack_entire_full_threshold		; load threshold for backtracking storage entirely full
	bcf		backtrack_entire_full				; clear entirely full state
	cpfslt	FSR1L								; index < threshold ?
	bsf		backtrack_entire_full				; NO - flag backtracking storage is entirely full
	return										; done

 ENDIF	; _cave_mode


;-----------------------------------------------------------------------------
; Calculate vertical Velocity
;
calc_velocity:							; called every two seconds
	btfsc	velocity_active_num			; was velocity shown in last cycle?
	bra		calc_velocity_1				; YES - always update if shown before
	btfss	count_divetime				; NO  - is the dive time counted, i.e. deeper than dive threshold?
	return								;       NO - display velocity only if deeper than 1m,
										;            i.e. not at the surface after the dive
calc_velocity_1:
	; calculate pressure difference
	MOVII	pressure_abs_cached,   sub_a; current pressure
	MOVII	last_pressure_velocity,sub_b; last pressure
	call	subU16						; do an unsigned subtraction

	; decide if ascending or descending
	bcf		neg_flag_velocity			; set to ascending by default
	btfsc	neg_flag					; pressure differential negative?
	bsf		neg_flag_velocity			; YES - descending

	; store current pressure as last pressure for next round
	MOVII	pressure_abs_cached,last_pressure_velocity

	; calculate velocity in m/min
	MOVII	sub_c,xA					; copy pressure differential to xA
	MOVLI	.39,xB						; put scale coefficient into xB (use 77 when called every second)
	call	mult16x16					; compute differential pressure in mbar * scale coefficient
	MOVII	xC,divA						; copy result to divA
	ADDLI	.64,divA					; add some round-up
	movlw	.7							; divide by 2^7
	call	div16						; divA = divA / 2^WREG, yields velocity in m/min

	movlw	.99							; load a 99
	cpfslt	divA+0						; velocity < 99 m/min ?
	movwf	divA+0						; NO  - limit to 99 m/min

	bcf		STATUS,C					; clear carry flag
	movlw	velocity_display_threshold	; get threshold for displaying vertical velocity
	subwf	divA+0,W					; subtract threshold from velocity
	btfss	STATUS,C					; above threshold?
	bsf		FLAG_TFT_velocity_clear		; NO  - don't show / request to clear
	btfsc	STATUS,C					; above threshold?
	bsf		FLAG_TFT_velocity_show		; YES - request to show
	return								; done


;-----------------------------------------------------------------------------
; Check and Memorize if Dive went into Deco & Deco Region
;
check_deco_states:
	btfsc	deco_region					; been within the deco stops region before?
	return								; YES - been in deco then before too, done
	movff	char_O_deco_info,WREG		; NO  - get deco info vector
	btfss	WREG,deco_stops_norm		;       do we have a deco obligation right now?
	return								;       NO  - done
	bsf		deco_locked					;       YES - memorize dive was in deco
	movff	char_O_deco_depth+0,WREG	;           - get depth of first stop in meters into WREG
	addlw	deco_region_distance+.1		;           - add deco region start distance + 1 meter for the negative test to work
	subwf	depth_meter,W				;           - compute current depth - (first stop depth + deco region distance)
	btfss	STATUS,C					;           - result negative?
	bsf		deco_region					;             YES - memorize to have entered the deco stops region
	return								;           - done


;-----------------------------------------------------------------------------
; Exercise Safety Stop Control
;
safety_stop_control:
	TSTOSS	opt_safetystop				; safety stop enabled? (=1: show safety stop)
	return								; NO  - done

	btfsc	FLAG_gauge_mode				; in gauge mode?
	return								; YES - omit (well, else fix collision of safety stop output with avg depth label)

	; setup
	bcf		safety_stop_enabled			; disable safety stop by default

	; check for deco
	btfsc	decostop_active				; in deco mode?
	bra		safety_stop_finish			; YES - shut down safety stop

	; below "opt_safety_stop_reset"?
	MOVII	pressure_rel_cur_cached,mpr	; get current pressure into MPR
	call	convert_pres_to_depth		; convert pressure in [mbar] to depth in [cm]
	MOVII	mpr,sub_a					; move depth in [cm] to sub_a
	movff	opt_safety_stop_reset,WREG	; load safety stop reset threshold [dm]
	mullw	.10							; convert threshold from [dm] to [cm]
	MOVII	PROD,sub_b					; move threshold in [cm] to sub_b
	call	cmpU16						; sub_a - sub_b
	btfsc	neg_flag					; below threshold depth?
	bra		safety_stop_control_chk		; NO  - check if above end threshold
	;bra	safety_stop_reset			; YES - reset safety stop

safety_stop_reset:
	movff	opt_safety_stop_length,safety_stop_countdown	; rearm safety stop (load timer)
	incf	safety_stop_countdown,F							; +1 because safety_stop_show decrements first
	bsf		FLAG_TFT_safety_stop_clear						; request to clear safety stop
	return													; done

safety_stop_control_chk:
	; above "opt_safety_stop_end"?
	movff	opt_safety_stop_end,WREG	; load safety stop end threshold [dm]
	mullw	.10							; convert threshold from [dm] to [cm]
	MOVII	PROD,sub_b					; move threshold in [cm] to sub_b
	call	cmpU16						; sub_a - sub_b
	btfsc	neg_flag					; above or at threshold depth?
	bra		safety_stop_finish			; YES - finish with safety stop and return

	; above "opt_safety_stop_start"?
	movff	opt_safety_stop_start,WREG	; load safety stop start threshold [dm]
	mullw	.10							; convert threshold from [dm] to [cm]
	MOVII	PROD,sub_b					; move threshold in [cm] to sub_b
	call	cmpU16						; sub_a - sub_b
	btfss	neg_flag					; above or at threshold depth?
	return								; NO  - pause safety stop
	tstfsz	safety_stop_countdown		; YES - safety stop armed?
	bsf		safety_stop_enabled			;       YES - enable safety stop
	return								;     - done


;-----------------------------------------------------------------------------
; Show Safety Stop
;
safety_stop_show:
	btfss	safety_stop_enabled			; safety stop enabled?
	return								; NO  - done
	dcfsnz	safety_stop_countdown,F		; YES - decrement remaining stop time, reached zero?
	bra		safety_stop_finish			;       YES - finished with safety stop and return
	bsf		FLAG_TFT_safety_stop_show	;       NO  - request to show safety stop
	return								;           - done


;-----------------------------------------------------------------------------
; Finish Safety Stop
;
safety_stop_finish:
	clrf	safety_stop_countdown		; disarm  safety stop
	bcf		safety_stop_enabled			; disable safety stop
	bsf		FLAG_TFT_safety_stop_clear	; request to clear safety stop
	return								; done


;-----------------------------------------------------------------------------
; Check for Timeouts (called by tasks every 1/1 second)
;
timeout_divemode:
	btfss	dive_main_menu				; main dive menu shown?
	bra		timeout_divemode_1			; NO  - skip
	btfsc	trigger_timeout				; YES - timeout occurred?
	rcall	divemenu_cleanup			;       YES - clean up main menu and restore dive data

timeout_divemode_1:
	btfss	dive_pre_menu				; pre-menu shown?
	bra		timeout_divemode_2			; NO  - skip
	btfsc	trigger_timeout				; YES - timeout occurred?
	call	menuview_toggle_reset		;       YES - terminate the pre-menu

timeout_divemode_2:
	INCI	dive_timeout_timer			; increment timeout timer
	
	btfss	divetime_longer_1min		; does the dive already last for longer than one minute?
	bra	timeout_divemode_sub_1min	; NO  - use a short timeout to achieve some extra hysteris when starting the dive

	btfsc	FLAG_apnoe_mode				; in apnoe mode?
	bra		timeout_divemode_apnoe		; YES - use apnoe timeout

 IFNDEF _DEBUG
	btfsc	sensor_override_active		; in simulator mode?
	bra		timeout_divemode_sim		; YES - use simulator timeout
 ENDIF

	movff	opt_diveTimeout,WREG		; get dive timeout in minutes into WREG
	bra		timeout_divemode_com_min	; continue with common part for minutes

timeout_divemode_apnoe:
	movlw	apnoe_timeout				; get apnoe timeout in minutes into WREG
	bra		timeout_divemode_com_min	; continue with common part for minutes

timeout_divemode_sim:
	MOVLI	simulator_timeout,sub_a		; get simulator timeout in seconds directly into sub_a
	bra		timeout_divemode_com_sec	; continue with common part for seconds

timeout_divemode_sub_1min:
	MOVLI	divetime_less_1min_timeout,sub_a ; use a short timeout as an extra hysteresis during the descent
	bra		timeout_divemode_com_sec	; continue with common part for seconds
	
timeout_divemode_com_min:
	mullw	.60							; multiply with 60 to convert minutes in WREG to seconds
	MOVII	PRODL,sub_a					; copy resulting seconds to sub_a

timeout_divemode_com_sec:
	MOVII	dive_timeout_timer,sub_b	; copy current timeout timer value to sub_b
	call	cmpU16						; check sub_a - sub_b
	btfsc	neg_flag					; result negative, i.e. timeout?
	bcf		divemode					; YES - terminate dive mode
	return								; done


;-----------------------------------------------------------------------------
; Clean up Dive Menu Area and restore Dive Data
;
divemenu_cleanup:
	bcf		dive_main_menu				; clear flag for dive mode menu shown
	call	TFT_clear_divemode_menu		; clear menu area

	btfss	custom_view_locked			; was the custom view locked by the menu system?
	bra		divemenu_cleanup_1			; NO  - continue with redrawing the lower display
	bcf		custom_view_locked			; YES - release locked
	movf	backup_customview,W			;     - get previous custom view into WREG
	cpfseq	active_customview			;     - compare with current custom view, equal?
	call	dive_customview_recall		;       NO - redraw previous custom view

divemenu_cleanup_1:
	bsf		FLAG_TFT_active_gas_divemode; request redraw of gas/setpoint/diluent
	bsf		FLAG_TFT_temperature		; request redraw of temperature (or resettable dive)
	bcf		better_gas_blinking			; stop better gas cue
	bcf		better_dil_blinking			; stop better dil cue
	;bra	request_redraw_NDL_deco_data; request redraw of NDL/deco data and return


;-----------------------------------------------------------------------------
; Request redraw of NDL/Deco Data
;
request_redraw_NDL_deco_data:
	btfsc	FLAG_gauge_mode				; in gauge mode?
	return								; YES - done
	btfss	decostop_active				; NO  - in deco mode?
	bra		timeout_divemode_menu_ndl	;       NO  - show NDL  again
	;bra	timeout_divemode_menu_deco	;       YES - show deco again

timeout_divemode_menu_deco:
	bsf		FLAG_TFT_display_deco_mask	; show deco mask
	bsf		FLAG_TFT_display_deco		; show deco stop
	bsf		FLAG_TFT_display_tts		; show TTS time
	return								; done

timeout_divemode_menu_ndl:
	bsf		FLAG_TFT_display_ndl_mask	; show NDL mask
	bsf		FLAG_TFT_display_ndl		; show NDL time
	return								; done


;-----------------------------------------------------------------------------
; Check if Dive Mode needs to be started (called from Surface Mode)
;
	global	check_dive_modes_surf
check_dive_modes_surf:
	SMOVII	pressure_rel_cur,sub_a			; ISR-safe 2 byte copy of current relative pressure to sub_a
	bcf		divetime_longer_1min			; not diving when in surface mode
	bra		check_dive_modes				; continue with common part


;-----------------------------------------------------------------------------
; Check if Dive Mode needs to be finished (called from Dive Loop)
;
check_dive_modes_dive:
	MOVII	pressure_rel_cur_cached,sub_a	; copy cached relative pressure to sub_a
	;bra	check_dive_modes				; continue with common part


;-----------------------------------------------------------------------------
; Check for Dive Mode Start/Finish - common Part
;
check_dive_modes:
	btfss	high_altitude_mode					; in high altitude mode?
	bra		check_dive_modes_norm				; NO  - use normal start-dive threshold
	btfsc	divetime_longer_1min				; YES - diving since > one minute?
	bra		check_dive_modes_norm				;       YES - this is a real dive -> use normal start-dive threshold
	;bra	check_dive_modes_high				;       NO  - use hight-altitude start-dive threshold

check_dive_modes_high:
	; high altitude start/end dive thresholds
	btfss	count_divetime						; dive time counting, i.e. already in the dive?
	bra		check_dive_modes_high_start			; NO  - select start threshold
	;bra	check_dive_modes_high_end			; YES - select end   threshold

check_dive_modes_high_end:
	MOVLI	dive_threshold_high_alt_end,sub_b	; load high altitude end threshold
	bra		check_dive_modes_comm				; continue with common part

check_dive_modes_high_start:
	MOVLI	dive_threshold_high_alt_start,sub_b	; load high altitude start threshold
	bra		check_dive_modes_comm				; continue with common part

check_dive_modes_norm:
	; normal altitude start/end dive thresholds
	btfss	count_divetime						; dive time counting, i.e. already in the dive?
	bra		check_dive_modes_norm_start			; NO  - select start threshold
	;bra	check_dive_modes_norm_end			; YES - select end   threshold

check_dive_modes_norm_end:
	MOVLI	dive_threshold_norm_alt_end,sub_b	; load normal altitude end threshold
	bra		check_dive_modes_comm				; continue with common part

check_dive_modes_norm_start
	MOVLI	dive_threshold_norm_alt_start,sub_b	; load normal altitude start threshold
	;bra	check_dive_modes_comm				; continue with common part

check_dive_modes_comm:
	call	cmpU16								; sub_a - sub_b = pressure_rel_cur - start-dive threshold
	btfsc	neg_flag							; pressure_rel_cur > dive_threshold, i.e. deeper than threshold?
	bra		check_dive_modes_shallow			; NO  - shallower than threshold
	btfsc	divetime_longer_1min				; YES - diving > one minute?
	CLRI	dive_timeout_timer					;       YES - reset timeout counter
	decfsz	dive_threshold_debounce,F				    ; debounce counter
	return
	incf	dive_threshold_debounce,F				
	bsf		divemode							;     - set dive mode flag
	bsf		count_divetime						;     - count dive time
	return										;     - done

check_dive_modes_shallow:
	movlw	.5								; load debounce counter
	movwf	dive_threshold_debounce
	bcf		count_divetime						; stop counting dive time
;	btfss	divetime_longer_1min				; diving > one minute?
;	bcf		divemode							; NO  - quit dive mode as this was no real dive
	return										; done mH


;-----------------------------------------------------------------------------
; Initialize the resettable Depth and Timer
;
resettable_average_depth_init:
	CLRI	pressure_rel_avg_trip							; prime the resettable average depth with 0
	bra		resettable_average_depth_common					; clear pressure accumulator and timer


;-----------------------------------------------------------------------------
; Reset the resettable Depth and Timer
;
resettable_average_depth_reset:
	bcf		request_reset_avg								; clear request
	MOVII	pressure_rel_cur_cached,pressure_rel_avg_trip	; prime the resettable average depth
															; with the current relative pressure (depth)
	;bra	resettable_average_depth_common					; clear pressure accumulator and timer


;-----------------------------------------------------------------------------
; Helper Function - common Part for resettable Depth and Timer init/reset
;
resettable_average_depth_common:
	clrf	pressure_rel_accu_trip+0						; clear the resettable depth accumulator
	clrf	pressure_rel_accu_trip+1						; ....
	clrf	pressure_rel_accu_trip+2						; ....
	clrf	pressure_rel_accu_trip+3						; ....
	CLRI	divesecs_avg_trip								; clear the resettable time accumulator
	return													; done


;-----------------------------------------------------------------------------
; Calculate Average Depth
;
calc_average_depth:
	; 1. compute pressure_rel_cur_cached x 2, because this routine is called every 2nd second only
	MOVII	pressure_rel_cur_cached,xB		; copy current rel pressure to xB
	bcf		STATUS,C						; multiply rel pressure x 2 (via shift left)
	rlcf	xB+0,F							; ...
	rlcf	xB+1,F							; ...

	; 2a add (pressure_rel_cur_cached x 2) to the resettable depth accumulator
	;    will work up to 9999 mbar * 60 * 60 * 24 = 863913600 mbar (24h @ 90 m depth)
	movf	xB+0,W							; pressure_rel_accu_trip += xB
	addwf	pressure_rel_accu_trip+0,F		; ...
	movf	xB+1,W							; ...
	addwfc	pressure_rel_accu_trip+1,F		; ...
	movlw	.0								; ...
	addwfc	pressure_rel_accu_trip+2,F		; ...
	addwfc	pressure_rel_accu_trip+3,F		; ...

	; 2b add (pressure_rel_cur_cached x 2) to the total depth accumulator
	;    will work up to 9999 mbar * 60 * 60 * 24 = 863913600 mbar (24h @ 90 m depth)
	movf	xB+0,W							; pressure_rel_accu_total += xB
	addwf	pressure_rel_accu_total+0,F		; ...
	movf	xB+1,W							; ...
	addwfc	pressure_rel_accu_total+1,F		; ...
	movlw	.0								; ...
	addwfc	pressure_rel_accu_total+2,F		; ...
	addwfc	pressure_rel_accu_total+3,F		; ...

	; 3a compute the resettable average depth
	movff	pressure_rel_accu_trip+0,xC+0	; get the accumulated depth
	movff	pressure_rel_accu_trip+1,xC+1	; ...
	movff	pressure_rel_accu_trip+2,xC+2	; ...
	movff	pressure_rel_accu_trip+3,xC+3	; ...
	MOVII	divesecs_avg_trip,xB			; get the accumulated time

	; divide accumulated depth by accumulated time
	call	div32x16						; xC:4 / xB:2 = xC+3:xC+2 with xC+1:xC+0 as remainder

	; store result
	MOVII	xC,pressure_rel_avg_trip		; resettable average depth
	btfss	count_divetime					; is dive time counted?
	return									; NO (e.g. too shallow)

	; 3b compute the dive total average depth
	movff	pressure_rel_accu_total+0,xC+0	; get accumulated depth
	movff	pressure_rel_accu_total+1,xC+1	; ...
	movff	pressure_rel_accu_total+2,xC+2	; ...
	movff	pressure_rel_accu_total+3,xC+3	; ...
	MOVII	divesecs_avg_total,xB			; get accumulated time

	; divide accumulated depth by accumulated time
	call	div32x16						; xC:4 = xC:4 / xB:2 with xA as remainder

	; store result
	MOVII	xC,pressure_rel_avg_total		; total dive average depth

	btfsc	request_reset_avg				; shall reset the resettable average depth?
	rcall	resettable_average_depth_reset	; YES - reset the resettable average depth

	TSTOSC	opt_2ndDepthDisp				; drawing average depth instead of max depth?
	bsf		FLAG_TFT_depth_maximum			; YES - flag to update display

	btfsc	FLAG_gauge_mode					; in gauge mode?
	bsf		FLAG_TFT_depth_maximum			; YES - flag to update display (needed for alternative layout)

	return									; done


;-----------------------------------------------------------------------------
; Check Switches, execute Pre-Menu Items  (called every second)
;
test_switches_divemode:
	btfsc	dive_main_menu					; dive mode menu shown?
	bra		test_switches_divemode_menu		; YES - use menu processor
	btfsc	switch_left						; NO  - left button pressed?
	goto	menuview_toggle					;       YES - step through pre-menu
	btfss	switch_right					;       NO  - right button pressed?
	return									;             NO  - done
	bcf		switch_right					;             YES - clear button event
	tstfsz	active_premenu					;                 - any pre-menu task selected?
	bra		test_switches_divemode1			;                   YES - execute a pre-menu item
	bsf		request_next_custview			;                   NO  - request next custom view
	return									;                       - done

test_switches_divemode_menu:
	btfsc	switch_left						; left button pressed?
	bra		test_switches_divemode_menu2	; YES - move cursor
	btfsc	switch_right					; NO  - right button pressed?
	bra		test_switches_divemode_menu3	;       YES - do a menu operation
	btfss	update_menu						;       NO  - shall update the menu?
	return									;             NO  - done
	bcf		update_menu						;             YES - clear request
	goto	menu_draw_lines_divemode		;                 - redraw the menu (to update color coding) and return

test_switches_divemode_menu1:
	clrf	menu_pos_cur					; reset menu item number to zero
test_switches_divemode_menu2:
	bcf		switch_left						; clear left button event
	incf	menu_pos_cur,F					; increment menu item number
	incf	menu_pos_max,W					; get number of items + 1 into WREG
	cpfslt	menu_pos_cur					; incremented item number > number of items ?
	bra		test_switches_divemode_menu1	; YES - restart from first item
	call	menu_draw_cursor_dive			; draw cursor at new position
	movlw	divemode_timeout_mainmenu		; get timeout for main menu
	call	restart_timeout_time			; restart the timeout
	return									; done

test_switches_divemode_menu3:
	bcf		switch_right					; clear right button event
	goto	do_line_menu					; Warning! trashes STKPTR and returns to
											;          divemode_option_divemenu_return

test_switches_divemode1:
	movlw	divemode_timeout_premenu		; get timeout for pre-menu
	call	restart_timeout_time			; restart the timeout
	movf	active_premenu,W				; get active pre-menu item
	dcfsnz	WREG,F
	bra		divemode_option_gaschange		;  1: switch to the the "better gas" / "better diluent"
	dcfsnz	WREG,F
	bra		divemode_option_ackn			;  2: acknowledge current advice, attention, or warning
	dcfsnz	WREG,F
	bra		divemode_option_divemenu		;  3: enter dive mode menu
	dcfsnz	WREG,F
 IFDEF _cave_mode
	bra		divemode_option_cavemenu		;  4: enter cave mode menu
 ELSE
	return									;  4: (no cave mode compiled in)
 ENDIF
	dcfsnz	WREG,F
	bra		divemode_option_sim_quit		;  5: quit simulator mode
	dcfsnz	WREG,F
	bra		divemode_option_sim_down		;  6: simulator mode - descent
	dcfsnz	WREG,F
	bra		divemode_option_sim_up			;  7: simulator mode - ascend
	dcfsnz	WREG,F
	bra		divemode_option_sim_time		;  8: simulator mode - +5 min
	dcfsnz	WREG,F
	bra		divemode_option_apnoe_quit		;  9: quit apnoe dive
	dcfsnz	WREG,F
	bra		divemode_option_gauge_reset		; 10: reset stopwatch and avg depth (gauge mode)
	dcfsnz	WREG,F
 IFDEF _compass
	bra		divemode_option_course			; 11: set bearing
 ELSE
	return									; 11: (no compass compiled in)
 ENDIF
	dcfsnz	WREG,F
	bra		divemode_option_layout			; 12: switch layout
	return									; catch illegal item number


	; item  1: switch to the the "better gas" / "better diluent"
	;
divemode_option_gaschange:
 IFDEF _ccr_pscr
	btfsc	FLAG_oc_mode					; in OC mode?
	bra		divemode_option_gaschange_oc	; YES
	btfsc	bailout_mode					; in bailout?
	bra		divemode_option_gaschange_oc	; YES

	; in CCR/pSCR mode and not in bailout
	movff	best_dil_number,menu_pos_cur	; select best diluent
	bcf		better_dil_available			; clear flag immediately
	bra		divemode_option_gaschange3		; continue with common part
 ENDIF
divemode_option_gaschange_oc:
	movff	best_gas_number,menu_pos_cur	; select best gas
	bcf		better_gas_available			; clear better gas cue

divemode_option_gaschange3
	bsf		request_gas_change				; request a gas/diluent change
	goto	menuview_toggle_reset			; terminate the pre-menu (and return)


	; item  2: acknowledge current advice, attention, or warning
	;
divemode_option_ackn:
	btfss	sign_warning						; any warning active?
	bra		divemode_option_ackn_attn			; NO  - check for active attentions
	movff	DM_flags_war1_det,DM_flags_war1_ack	; YES - memorize active warnings as acknowledged
	movff	DM_flags_war2_det,DM_flags_war2_ack	;     - ...
	bra		divemode_option_ackn_common			;     - update screen

divemode_option_ackn_attn:
	btfss	sign_attention						; any attention active?
	bra		divemode_option_ackn_advc			; NO  - must be active advice then
	movff	DM_flags_att1_det,DM_flags_att1_ack	; YES - memorize active attentions as acknowledged
	movff	DM_flags_att2_det,DM_flags_att2_ack	;     - ...
	movff	DM_flags_att3_det,DM_flags_att3_ack	;     - ...
	bra		divemode_option_ackn_common			;     - update screen

divemode_option_ackn_advc:
	movff	DM_flags_advc_det,DM_flags_advc_ack	; memorize active advices as acknowledged
	;bra	divemode_option_ackn_common			; update screen

divemode_option_ackn_common:
	call	menuview_toggle_reset			; terminate pre-menu
	call	divemode_check_sign				; compute if  the advice / attention / warning sign shall be shown
	btfsc	FLAG_TFT_sign_show				; shall show  the advice / attention / warning sign?
	goto	TFT_divemode_sign_show			; YES - show  sign and return
	goto	TFT_divemode_sign_clear			; NO  - clear sign and return


	; item  3: enter dive mode menu
	;
divemode_option_divemenu:
	btfss	divemode						; in dive mode?
	goto	menuview_toggle_reset			; NO  - block menu, terminate the pre-menu
	call	TFT_clear_divemode_menu			; YES - clear menu area
	bcf		dive_pre_menu					;     - set pre-menu as not shown anymore
	goto	do_main_divemenu				;     - hand over to menu processor


	; item  4: enter cave mode menu
	;
 IFDEF _cave_mode
divemode_option_cavemenu:
	btfss	divemode						; in dive mode?
	goto	menuview_toggle_reset			; NO  - block menu, terminate the pre-menu
	call	TFT_clear_divemode_menu			; YES - clear menu area
	bcf		dive_pre_menu					;     - set pre-menu as not shown anymore
	goto	do_main_cavemenu				;     - hand over to menu processor
 ENDIF


	; item  5: quit simulator mode
	;
divemode_option_sim_quit:
	clrf	simulatormode_depth				; set target depth to zero
	bsf		quit_simulatormode				; request ISR to end simulator mode
	call	menuview_toggle_reset			; terminate the pre-menu
	btfsc	FLAG_apnoe_mode					; in apnoe mode?
	bcf		divemode						; YES - force end of dive mode
	return									; done


	; item  6: simulator mode - descent 1 meter
	;
divemode_option_sim_down:
	movlw	ostc_depth_max-1				; load depth limit into WREG
	cpfsgt	simulatormode_depth				; simulated depth < limit ?
	incf	simulatormode_depth,F			; YES - increment simulated depth
	return									; done


	; item  7: simulator mode - ascent 1 meter
	;
divemode_option_sim_up:
	tstfsz	simulatormode_depth				; simulated depth > 0 ?
	decf	simulatormode_depth,F			; YES - decrement simulated depth
	return									; done


	; item  8: simulator mode - +5 min
	;
divemode_option_sim_time:
	movff	char_I_sim_advance_time,WREG	; get mailbox content
	tstfsz	WREG							; mailbox clear (=0) ?
	return									; NO  - still having a pending +5' request, refuse new request
	bra		advance_time					; YES - advance time and return


	; item  9: quit apnoe dive
	;
divemode_option_apnoe_quit:
	btfsc	sensor_override_active			; in simulator mode?
	bra		divemode_option_sim_quit		; YES - use simulator quit procedure
	bcf		divemode						; NO  - force end of dive mode
	return									;     - done


	; item 10: reset stopwatch and avg depth (gauge mode only)
	;
divemode_option_gauge_reset:
	bsf		request_reset_avg				; request reset of average depth
	goto	menuview_toggle_reset			; terminate pre-menu and return


	; item 11: set bearing
	;
 IFDEF _compass
divemode_option_course:
	MOVII	compass_heading_shown,compass_bearing
	bsf		compass_bearing_set				; set flag to show heading
	goto	menuview_toggle_reset			; terminate the pre-menu and return
 ENDIF


	; item 12: switch layout
	;
divemode_option_layout:
	call	menuview_toggle_reset		; terminate the pre-menu
	call	TFT_ClearScreen				; clear the whole screen
	btg		alt_layout_active			; toggle layout

	bcf		depth_color_last			; set warning or attention on the depth   not shown
	bcf		depth_inverse_last			; set depth displayed in inverse as       not shown
	bcf		sign_shown					; set warning/attention/advice sign       not shown
	bcf		velocity_active_num			; set numerical vertical velocity display not shown
	bcf		velocity_active_vsi			; set vertical  vertical velocity display not shown
	bcf		safety_stop_active			; set safety stop                         not shown

	bsf		FLAG_TFT_divemode_mask		; request redraw of dive screen mask
	bsf		FLAG_TFT_divetime			; request redraw of dive time
	bsf		FLAG_TFT_depth_current		; request redraw of current depth
	bsf		FLAG_TFT_depth_maximum		; request redraw of maximum depth
	bsf		FLAG_TFT_active_gas_divemode; request redraw of gas and setpoint
	bsf		FLAG_TFT_temperature		; request redraw of temperature
	bsf		FLAG_TFT_customview_callup	; request redraw of custom view

	goto	request_redraw_NDL_deco_data; request redraw of NDL/deco data and return


;-----------------------------------------------------------------------------
; Helper Function - advance Time by 5 Minutes (Simulator Mode)
;
advance_time:
	; advance tissues pressures and deco obligation by 5 minutes
	movlw	.5								; + 5 minutes
	movff	WREG,char_I_sim_advance_time	; copy to mailbox
	call	restart_deco_engine				; condition deco engine to execute the +5 minutes

	bcf		count_divetime					; stop dive time incrementing in ISR
	ADDLI	.5,counted_divetime_mins		; add 5 minutes to counted_divetime_mins
	ADDLI	.300,total_divetime_secs		; add 5 minutes (300 seconds) to total_divetime_secs
	bsf		count_divetime					; continue dive time incrementing in ISR

	ADDLI	.300,divesecs_avg_trip			; add 5 minutes (300 seconds) to resettable time accumulator
	ADDLI	.300,divesecs_avg_total			; add 5 minutes (300 seconds) to total time accumulator

	MOVII	pressure_rel_cur_cached,xB		; calculate 300 x depth in mbar (300 = 5 min * 60 sec/min)
	MOVLI	.300,xA							; ...
	call	mult16x16						; xC = xA * xB

	movf	xC+0,W							; add to the resettable depth accumulator
	addwf	pressure_rel_accu_trip+0,F		; ...
	movf	xC+1,W							; ...
	addwfc	pressure_rel_accu_trip+1,F		; ...
	movf	xC+2,W							; ...
	addwfc	pressure_rel_accu_trip+2,F		; ...
	movf	xC+3,W							; ...
	addwfc	pressure_rel_accu_trip+3,F		; ...

	movf	xC+0,W							; add to the total depth accumulator
	addwf	pressure_rel_accu_total+0,F		; ...
	movf	xC+1,W							; ...
	addwfc	pressure_rel_accu_total+1,F		; ...
	movf	xC+2,W							; ...
	addwfc	pressure_rel_accu_total+2,F		; ...
	movf	xC+3,W							; ...
	addwfc	pressure_rel_accu_total+3,F		; ...

 IFDEF _cave_mode
	; update backtracking data
	btfss	cave_mode						; cave mode switched on?
	bra		divemode_option_sim_time_exit	; NO  - skip backtracking depth recording
	btfsc	dive_turned						; YES - dive turned?
	bra		divemode_option_sim_time_exit	;       YES - skip   backtracking depth recording
	;bra	divemode_option_sim_time_exec	;       NO  - update backtracking depth recording

divemode_option_sim_time_exec:
	movff	backtrack_deltatime,hi			; backup time elapsed since last depth recording
	movlw	.5								; configure 5 minutes
	movwf	lo								; use lo as loop counter

divemode_option_sim_time_loop:
	call	write_backtrack_1min_depth		; store a backtracking depth data set
	btfsc	backtrack_entire_full			; backtracking storage entirely used up?
	bra		divemode_option_sim_time_exit	; YES - abort backtracking depth recording
	decfsz	lo,F							; NO  - decrement loop counter, did it became zero?
	bra		divemode_option_sim_time_loop	;       NO  - loop
	;bra	divemode_option_sim_time_done	;       YES - done

divemode_option_sim_time_done:
	movff	hi,backtrack_deltatime			; restore time elapsed since last depth recording
 ENDIF	; _cave_mode

divemode_option_sim_time_exit:
	return									; done (leaving option avail for repeated selection)


;-----------------------------------------------------------------------------
; Change Gas / Diluent
;
gas_switch_common:
	bcf		request_gas_change				; clear request flag
 IFDEF _ccr_pscr
	btfss	request_back_to_loop			; is a switchback from OC bailout to loop requested?
	bra		gas_switched_common0			; NO  - continue with checking if selected gas is valid
	bcf		request_back_to_loop			; YES - clear flag
	movff	active_dil,menu_pos_cur			;     - reload last diluent
	bra		gas_switched_common1			;     - continue with common part
 ENDIF
gas_switched_common0:
	tstfsz	menu_pos_cur					; menu_pos_cur = 0 ?
	bra		gas_switched_common1			; NO  - valid gas
	return									; YES - something went wrong, invalid gas, abort
gas_switched_common1:
	movf	menu_pos_cur,W					; get selected gas into WREG (1-5)
 IFDEF _ccr_pscr
	btfsc	FLAG_oc_mode					; in OC mode?
	bra		gas_switched_common_OC			; YES
	btfsc	bailout_mode					; in bailout?
	bra		gas_switched_common_OC			; YES
gas_switched_common_loop:					; NO to both - must be loop mode then
	call	setup_dil_registers				; set up real tissues  with WREG = diluent 1-6
	call	deco_setup_cc_diluents			; set up deco planning with WREG = diluent 1-6
	bra		gas_switched_common3			; continue with common part
 ENDIF	; _ccr_pscr

gas_switched_common_OC:
	call	setup_gas_registers				; set up real tissues  with WREG = gas 1-6
	call	deco_setup_oc_gases				; set up deco planning with WREG = gas 1-6
	;bra	gas_switched_common3			; continue with common part

gas_switched_common3:
	banksel	int_O_breathed_ppO2
	bcf		int_O_breathed_ppO2+1,int_low_flag			; | clear all flags that control color-coding
	bcf		int_O_breathed_ppO2+1,int_high_flag			; | to have the new gas initially displayed in
	bcf		int_O_breathed_ppO2+1,int_attention_flag	; | memo color instead of a warning or attention
	bcf		int_O_breathed_ppO2+1,int_warning_flag		; | color that belonged to the previous gas
	banksel	common
	bsf		FLAG_TFT_active_gas_divemode	; redraw gas/setpoint/diluent
	bsf		FLAG_TFT_temperature			; redraw temperature
	bsf		event_occured					; set global event flag
 IFDEF _ccr_pscr
	btfsc	bailout_mode					; in bailout mode?
	bsf		event_bailout					; YES - set bailout event
	btfss	bailout_mode					; in bailout mode?
 ENDIF
	bsf		event_gas_change				; (NO) - set gas change event (normal change)
	goto	restart_deco_engine_wo_ceiling	; abort running deco calculations and restart (and return)


;-----------------------------------------------------------------------------
; Reload the current Gas / Diluent
;
gas_update_common:
	bcf		request_gas_update			; reset the request flag
	movf	active_gas,W				; load WREG with currently used gas
 IFDEF _ccr_pscr
	btfsc	FLAG_oc_mode				; in OC mode?
	bra		gas_switched_common_OC		; YES - reload OC gases
	btfsc	bailout_mode				; NO  - in bailout?
	bra		gas_switched_common_OC		;       YES - reload OC gases
	movf	active_dil,W				;       NO  - load WREG with currently used diluent
	bra		gas_switched_common_loop	;           - set up diluent gases
 ELSE
	bra		gas_switched_common_OC		; reload OC gases
 ENDIF


;-----------------------------------------------------------------------------
; Toggle GF/aGF  (finalization)
;
divemodemode_togglegf:
	bcf		request_toggle_GF			; clear request flag
	goto	restart_deco_engine			; restart the deco engine and return


;-----------------------------------------------------------------------------
; Set a Marker in the Dive Profile
;
set_logbook_marker:
	bcf		request_set_marker			; clear request flag
	movlw	d'6'						; set type of alarm: manual marker
	movwf	alarm_type					; copy to alarm register
	bsf		event_occured				; set event flag
	return								; done


;-----------------------------------------------------------------------------
; Find the best gas and diluent for the current depth
; and check if a gas/diluent change is to be advised.
;
; Output: best_gas_number      : number of best gas, 0= none avail, 255= not computed
;         best_dil_number      : number of best dil, 0= none avail, 255= not computed
;         better_gas_available : flag indicating if a change is advised
;         better_dil_available : flag indicating if a change is advised
;
;
; in CCR and pSCR mode: - checks both, gases and diluents for respective best gas / best diluent
;                       - if not in bailout, sets better_dil_available on diluents
;                       - if     in bailout, sets better_gas_available on OC gases
;
; in OC mode          : - checks only gases for best gas
;                       - sets better_gas_available on OC gases
;
	global	check_gas_best
check_gas_best:
	btfsc	FLAG_gauge_mode					; in gauge mode?
	return									; YES - done

	MOVII	pressure_abs_10,xA				; copy absolute pressure / 10 into xA:2, will be used by ppO2 min/max checks later

	; compute max. allowed deco ppO2
	movff	char_I_ppO2_max_deco,WREG		; max ppO2 [cbar] for deco phase
	mullw	.100							; compute max ppO2 * 100, result is in 0.1 mbar
	ADDLI	ppO2_margin_on_max,PROD			; add ppO2 margin on max value to compensate for surface pressures > 1000 hPa
	MOVII	PROD,ppO2_max_deco				; store as deco ppO2 max

	; compute max. allowed default ppO2
	movff	char_O_deco_info,lo				; bank-safe copy of deco info vector
	btfss	lo,deco_mode					; is the ppO2 deco limit enabled?
	bra		check_gas_best_1				; NO  - compute default ppO2 max
	MOVII	ppO2_max_deco,ppO2_max_default	; YES - copy default ppO2 max from deco max.
	bra		check_gas_best_2				;     - continue with common part

check_gas_best_1:
	movff	char_I_ppO2_max_work,WREG		; max ppO2 [cbar] for working phase
	mullw	.100							; compute max ppO2 * 100, result is in 0.1 mbar
	ADDLI	ppO2_margin_on_max,PROD			; add ppO2 margin on max value to compensate for surface pressures > 1000 hPa
	MOVII	PROD,ppO2_max_default			; store as default ppO2 max

check_gas_best_2:

 IFDEF _ccr_pscr
	; check dive mode
	btfsc	FLAG_oc_mode					; in OC mode?
	bra		check_gas_best_gas				; YES - skip diluents, check for best gas only

check_gas_best_dil:
	; set minimum ppO2 required
	movff	char_I_ppO2_min,WREG			; min ppO2 for pure diluent in CCR mode (default)
	btfsc	FLAG_pscr_mode					; in pSCR mode?
	movff	char_I_ppO2_min_loop,WREG		; YES - replace by min ppO2 for pure diluent in pSCR mode
	mullw	.100							; min ppO2 * 100, result in 0.1 mbar
	MOVII	PROD,ppO2_min					; store in ppO2_min
	; check diluents
	lfsr	FSR1,opt_dil_O2_ratio			; set base address for diluent arrays
	movff	active_dil,lo					; set number of currently used diluent
	; preset result to nothing found
	clrf	best_gas_num					; initialize best diluent to   0 = none found yet
	setf	best_gas_depth					; initialize change depth to 255 = any one will be better
	; check if current diluent is usable
	movff	lo,check_gas_num				; check if the current diluent is usable
	rcall	check_gas_best_common			; if yes, the current diluent will become the best diluent found so far
	rcall	check_gas_best_all				; check if any other  diluent is better
	; store result
	movff	best_gas_num,best_dil_number	; store new best diluent found (1-5 or 0 of no usable diluent available)
	; check if change advices shall be given in general
	btfsc	bailout_mode					; in bailout?
	bra		check_gas_best_gas				; YES - no better diluent advice when in bailout
check_gas_best_dil1:
	; check if a change advice shall be given right now
	bcf		better_dil_available			; default to no better diluent found
	movf	best_dil_number,W				; load number of best diluent into WREG (1-5)
	bz		check_gas_best_dil3				; has a best diluent been found at all?  NO - nothing to signal for
	cpfseq	active_dil						; is this the currently used diluent?
	bra		check_gas_best_dil2				; NO  - a better diluent has been found
	bra		check_gas_best_dil3				; YES - no need to signal a better diluent if this diluent is already in use
check_gas_best_dil2:
	btfsc	warn_det_sensors_lost			; all sensors lost?
	bra		check_gas_best_dil3				; YES - suppress better diluent prompt in this case
	; not using the best gas - show better diluent hint whenever a better diluent is available
	bsf		better_dil_available			; signal that a better diluent is available
	bsf		FLAG_TFT_active_gas_divemode	; redraw gas/setpoint/diluent
check_gas_best_dil3:
	btfss	better_dil_available			; shall a better diluent be signaled for?
	bcf		better_dil_blinking				; NO  - clear blinking flag
	;bra	check_gas_best_gas				; ; continue with checking for best bailout gas
 ENDIF	; _ccr_pscr


check_gas_best_gas:
	; set minimum ppO2 required
	movff	char_I_ppO2_min,WREG			; min ppO2 for OC and bailout
	mullw	.100							; min ppO2 * 100, result in 0.1 mbar
	MOVII	PROD,ppO2_min					; store in ppO2_min
	; check gases
	lfsr	FSR1,opt_gas_O2_ratio			; set base address for gas arrays
	movff	active_gas,lo					; set number of currently used gas
	; preset result to nothing found
	clrf	best_gas_num					; initialize best gas to       0 = none found yet
	setf	best_gas_depth					; initialize change depth to 255 = any one will be better
	; check if current gas is usable
	movff	lo,check_gas_num				; check if the current gas is usable
	rcall	check_gas_best_common			; if yes, the current gas will become the best gas found so far
	rcall	check_gas_best_all				; check if any other  gas is better
	; store result
	movff	best_gas_num,best_gas_number	; store new best gas found (1-5 or 0 of no usable gas available)
 IFDEF _ccr_pscr
	; check if change advices shall be given in general
	btfsc	FLAG_oc_mode					; in OC mode?
	bra		check_gas_best_gas1				; YES - give advice
	btfsc	bailout_mode					; NO  - in bailout?
	bra		check_gas_best_gas1				;       YES - give advice
	return									;       NO  - no better (OC) gas advice when not in OC or bailout mode
 ENDIF	; _ccr_pscr
check_gas_best_gas1:						; check if we are already on the best gas
	; check if a change advice shall be given right now
	bcf		better_gas_available			; default to no better gas found
	movf	best_gas_number,W				; load number of best gas into WREG (1-5)
	bz		check_gas_best_gas3				; has a best gas been found at all?  NO - nothing to signal for
	cpfseq	active_gas						; is this the currently used gas?
	bra		check_gas_best_gas2				; NO  - a better gas has been found
	bra		check_gas_best_gas3				; YES - no need to signal a better gas if this gas is already in use
check_gas_best_gas2:
	; not using the best gas - show better gas hint whenever a better gas is available
	bsf		better_gas_available			; YES - signal that a better gas is available
	bsf		FLAG_TFT_active_gas_divemode	; YES - redraw gas/setpoint/diluent
check_gas_best_gas3:
	btfss	better_gas_available			; shall a better gas be signaled for?
	bcf		better_gas_blinking				; NO - clear blinking flag
	return


check_gas_best_all:
	clrf	check_gas_num					; increment comes first, so initialize with zero
check_gas_best_loop:
	incf	check_gas_num,F					; increment number of gas to check
	movf	lo,W							; copy number of currently used gas to WREG
	cpfseq	check_gas_num					; gas to be checked = currently used gas ?
	rcall	check_gas_best_common			; NO - check the gas
	movlw	NUM_GAS							; get total number of gases
	cpfseq	check_gas_num					; reached last gas?
	bra		check_gas_best_loop				; NO  - loop
	return									; YES - done


check_gas_best_common:						; with gas to be checked in check_gas_num (1-5)
											; and  current gas       in lo            (1-5)
	;
	; Memory Map:
	; ---------------------------------------------------------------------------------------
	; opt_gas_O2_ratio		res 5	; base address for gases
	; opt_dil_O2_ratio		res 5	; base address for diluents
	; opt_gas_He_ratio		res 5	; (not needed here)
	; opt_dil_He_ratio		res 5	; (not needed here)
	; opt_gas_type			res 5	; has offset of 20 bytes from base address for gases
	; opt_dil_type			res 5	; has offset of 20 bytes from base address for diluents
	; opt_gas_change		res 5	; has offset of 10 bytes from opt_gas_type
	; opt_dil_change		res 5	; has offset of 10 bytes from opt_dil_type

	; get gas data
	decf	check_gas_num,W					; (1-5) -> (0-4) into WREG to be used as index
	movff	PLUSW1,check_gas_O2_ratio		; copy O2 ratio (%) of current gas/dil to check_gas_O2_ratio
	addlw	.20								; add offset of 20 bytes to index type in opt_gas_type/opt_dil_type
	movff	PLUSW1,check_gas_type			; copy type of current gas/dil to check_gas_type (0=disabled, 1=first, 2=travel/normal, 3=deco/-)
	addlw	.10								; add offset of 10 bytes to index change depth in opt_gas_change/opt_dil_change
	movff	PLUSW1,check_gas_depth			; copy change depth of current gas/dil to check_gas_depth
	MOVII	ppO2_max_default,sub_b			; select default ppO2 max for first / travel / normal gas
	; check if the gas is the current gas
	movf	check_gas_num,W					; get the number of the gas to be checked (1-5)
	cpfseq	lo								; is this the currently used gas?
	bra		check_gas_best_common0			; NO  - do the disabled & deco gas checks
	bra		check_gas_best_common3			; YES - a gas in use overrides disabled and deco status
check_gas_best_common0:
	; check if gas is available (i.e. not disabled)
	btfsc	check_gas_type,gas_lost			; gas/dil lost?
	return									; YES - skip as not available any more
	btfsc	check_gas_type,gas_staged		; gas/dil staged?
	return									; YES - skip as currently not available
	tstfsz	check_gas_type					; type = disabled (0) ?
	bra		check_gas_best_common1			; NO  - continue checks
	return									; YES - skip as not available at all
check_gas_best_common1:
	; skip deco gases (type=3) if there are no stops, but include them when in bailout mode
	movlw	.3								; coding for deco gas
	cpfseq	check_gas_type					; type = deco (3) ?
	bra		check_gas_best_common3			; NO  - first or travel/normal then, ok to use
 IFDEF _ccr_pscr
	btfsc	bailout_mode					; YES - in bailout?
	bra		check_gas_best_common2			;       YES - ok to use (using deco gases is always allowed when in bailout)
 ENDIF
	TSTOSS	opt_ext_stops					;       NO  - extended stops enabled?
	bra		check_gas_best_common1b			;             NO  - only ok if in deco region
	;bra	check_gas_best_common1a			;             YES - only ok if in deco mode
check_gas_best_common1a:
	movff	char_O_deco_info,WREG			; get deco info vector
	btfss	WREG,deco_mode					; are we in deco mode?
	return									; NO  - skip deco gas while not in deco mode
	bra		check_gas_best_common2			; YES - deco gases allowed
check_gas_best_common1b:
	btfss	deco_region						; are we in the deco region?
	return									; NO  - skip deco gas while not in the deco region
	;bra	check_gas_best_common2			; YES - deco gases allowed
check_gas_best_common2:
	MOVII	ppO2_max_deco,sub_b				; replace by ppO2 max for a deco gas
check_gas_best_common3:
	; check if gas is usable, i.e. its change depth is below or equal to the current depth
	movf	depth_meter,W					; load current depth (in m) into WREG
	cpfslt	check_gas_depth					; change depth of checked gas < (shallower than) current depth?
	bra		check_gas_best_common4			; NO  - gas is usable
	return									; YES - gas is not usable
check_gas_best_common4:
	; check if this gas is the first best gas candidate
	movf	best_gas_num,W					; get best gas found so far (1-5) or 0 if none found yet
	tstfsz	WREG							; has a best gas candidate been found yet?
	bra		check_gas_best_common5			; YES - check if the new one is better than the one we have so far
	bra		check_gas_best_common6			; NO  - no need to do the above mentioned check
check_gas_best_common5:
	; check if the change depth of the checked gas is < (shallower) than the change depth of the best gas found so far
	movf	best_gas_depth,W				; load change depth of best gas so far into WREG
	cpfslt	check_gas_depth					; change depth of checked gas < (shallower than) change depth of best gas so far?
	return									; NO  - this gas is not better than the best already found
	;bra	check_gas_best_common6			; YES - this gas is better, continue
check_gas_best_common6:
	; check if the gas fits into the ppO2 limits
	movff	check_gas_O2_ratio,xB+0			; xB = O2 ratio, xA is still loaded with (absolute pressure / 10)
	clrf	xB+1
	call	mult16x16						; xC = O2 ratio * (absolute pressure / 10), result in 0.1 mbar
	; check for very high ppO2
	tstfsz	xC+2							; O2_ratio * absolute pressure / 10 > 65536, i.e. ppO2 > 6.55 bar ?
	return									; YES - gas is not usable
	btfsc	xC+1,7							; ppO2 > 3.30 bar ?
	return									; YES - gas is not usable
	MOVII	xC,sub_a						; NO  - gas may be usable
	; check for high ppO2
	call	cmpU16							; sub_a - sub_b
	btfss	neg_flag						; within limit?
	return									; NO - too high, gas is not usable
	; check for low ppO2
	MOVII	ppO2_min,sub_b					; copy minimum ppO2 to sub_b
	call	cmpU16							; sub_a - sub_b
	btfsc	neg_flag						; within limit?
	return									; NO - too low, gas is not usable
	; we have a (new) best gas
	movff	check_gas_num,  best_gas_num	; YES - set checked gas (1-5) as best gas
	movff	check_gas_depth,best_gas_depth	;     - memorize its change depth
	return									;     - done

 IFDEF _ccr_pscr


;-----------------------------------------------------------------------------
; Check for Auto-SP
;
check_dive_autosp:
	movf	dive_ccr_mode,W				; =0: Fixed SP, =1: Sensor, =2: Auto SP
	sublw	.2							; dive_ccr_mode = 2 (Auto SP)?
	bz		check_dive_autosp2			; YES - check
	return								; NO  - return for sensor or fixed mode

check_dive_autosp2:
	; check for restart request
	btfss	restart_auto_sp				; shall restart from 1st SP?
	bra		check_dive_autosp2a			; NO  - skip next
	bcf		restart_auto_sp				; YES - clear request flag
	bcf		FLAG_SP2_used				;     - flag SP 2, ...
	bcf		FLAG_SP3_used				;     - flag SP 3, ...
	bcf		FLAG_SP4_used				;     - flag SP 4, ...
	bcf		FLAG_SP5_used				;     - flag SP 5 as unused so far

check_dive_autosp2a:
	; check SP2
	btfsc	FLAG_SP2_used				; SP 2 used so far?
	bra		check_dive_autosp3			; YES - continue with SP 3
	movff	opt_setpoint_change+1,lo	; NO  - get depth in m
	tstfsz	lo							;     - SP change depth = 0 ?
	bra		check_dive_autosp2b			;       NO  - continue
	bra		check_dive_autosp3			;       YES - continue with SP 3
check_dive_autosp2b:
	decf	lo,W						; SP change depth -1 -> WREG
	cpfsgt	depth_meter					; current depth > change depth - 1 ?
	bra		check_dive_autosp3			; NO  - continue with SP 3
	; auto switch to SP2
	movff	opt_setpoint_cbar+1,char_I_const_ppO2 ; YES - use SP
	rcall	xmit_sp_set_flag			;     - send SP to external devices
	bsf		FLAG_SP2_used				;     - set SP 2 used flag

check_dive_autosp3:
	; check SP3
	btfsc	FLAG_SP3_used				; SP 3 used so far?
	bra		check_dive_autosp4			; YES - continue with SP 4
	movff	opt_setpoint_change+2,lo	; NO  - get depth in m
	tstfsz	lo							;     - SP change depth = 0 ?
	bra		check_dive_autosp3a			;       NO  - continue
	bra		check_dive_autosp4			;       YES - continue with SP 4
check_dive_autosp3a:
	decf	lo,W						; SP change depth -1 -> WREG
	cpfsgt	depth_meter					; current depth > change depth - 1 ?
	bra		check_dive_autosp4			; NO  - continue with SP 4
	; auto switch to SP3
	movff	opt_setpoint_cbar+2,char_I_const_ppO2 ; YES - use SP
	rcall	xmit_sp_set_flag			;     - send SP to external devices
	bsf		FLAG_SP3_used				;     - set SP 3 used flag

check_dive_autosp4:
	; check SP4
	btfsc	FLAG_SP4_used				; SP 4 used so far?
	bra		check_dive_autosp5			; YES - continue with SP 5
	movff	opt_setpoint_change+3,lo	; NO  - get depth in m
	tstfsz	lo							;     - SP change depth = 0 ?
	bra		check_dive_autosp4a			;       NO  - continue
	bra		check_dive_autosp5			;       YES - continue with SP 5
check_dive_autosp4a:
	decf	lo,W						; SP change depth -1 -> WREG
	cpfsgt	depth_meter					; current depth > change depth - 1 ?
	bra		check_dive_autosp5			; NO  - continue with SP 5
	; auto switch to SP4
	movff	opt_setpoint_cbar+3,char_I_const_ppO2 ; YES - use SP
	rcall	xmit_sp_set_flag			;     - send SP to external devices
	bsf		FLAG_SP4_used				;     - set SP 4 used flag

check_dive_autosp5:
	; check SP5
	btfsc	FLAG_SP5_used				; SP 5 used so far?
	bra		check_dive_autosp6			; YES - done
	movff	opt_setpoint_change+4,lo	; NO  - get depth in m
	tstfsz	lo							;     - SP change depth = 0 ?
	bra		check_dive_autosp5a			;       NO  - continue
	bra		check_dive_autosp6			;       YES - done
check_dive_autosp5a:
	decf	lo,W						; SP change depth -1 -> WREG
	cpfsgt	depth_meter					; current depth > change depth - 1 ?
	bra		check_dive_autosp6			; NO  - done
	; auto switch to SP5
	movff	opt_setpoint_cbar+4,char_I_const_ppO2 ; YES - use SP
	rcall	xmit_sp_set_flag			;     - send SP to external devices
	bsf		FLAG_SP5_used				;     - set SP 5 used flag

check_dive_autosp6:
	return								; done


;-----------------------------------------------------------------------------
; Helper Function - transmit new Setpoint to external Electronics and flag Change
;
xmit_sp_set_flag:
 IFDEF _external_sensor
	call	transmit_setpoint			; transmit current setpoint from WREG (in cbar) to external electronics
 ENDIF
	bsf		event_occured				; set global   event flag
	bsf		event_SP_change				; set setpoint event flag
	return

 ENDIF	; _ccr_pscr


;=============================================================================
dmode2	CODE
;=============================================================================


;-----------------------------------------------------------------------------
; Setup everything to enter OC Dive Mode
;
	global	dive_boot_oc
dive_boot_oc:
	rcall	get_first_gas_to_WREG		; get 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								; done


;-----------------------------------------------------------------------------
; Helper Function - get first Gas (1-5) into WREG
;
	global	get_first_gas_to_WREG
get_first_gas_to_WREG:
	lfsr	FSR1,opt_gas_type			; load base address of the gas types
	clrf	lo							; start with gas 0
get_first_gas_to_WREG2:
	movf	lo,W						; set index
	movf	PLUSW1,W					; get type of gas (0=Disabled, 1=First, 2=Travel, 3=Deco)
	sublw	.1							; is it of type First?
	bz		get_first_gas_to_WREG3		; YES - found the First gas
	incf	lo,F						; NO  - increment index
	movlw	NUM_GAS+1					;     - get highest index+1
	cpfseq	lo							;     - all gases checked?
	bra		get_first_gas_to_WREG2		;       NO  - not yet
	movlw	.1							;       YES - default to gas 1
	movff	WREG,opt_gas_type+0			;           - force it to be of type First
	return								;           - done
get_first_gas_to_WREG3:
	movf	lo,W						; copy index of gas found to be the First to WREG
	incf	WREG,W						; turn index into gas number (0-4 -> 1-5)
	return								; done


;-----------------------------------------------------------------------------
; Helper Function - load currently breathed Gas into Deco Engine
;
	global	setup_gas_registers
setup_gas_registers:
	movwf	active_gas						; set as current gas
	movlw	.6								; gas = gas6 ?
	cpfseq	active_gas						; ...
	bra		setup_gas_registers_15			; NO - load gas 1-5

	; load gas 6
	movff	opt_gas6_O2_ratio,char_I_O2_ratio	; copy gas6 O2 ratio to deco engine
 IFDEF _helium
	movff	opt_gas6_He_ratio,char_I_He_ratio	; copy gas6 H2 ratio to deco engine
 ENDIF
	movlw	.3								; declare gas6 as a deco gas
	movff	WREG,char_I_current_gas_type	; copy gas type to deco engine
	movff	depth_meter,char_I_gas6_depth	;set current depth as change depth
	bra		setup_gas_registers_com			; continue with common part

setup_gas_registers_15:
	lfsr	FSR1,opt_gas_O2_ratio			; load base address of gas data
	decf	active_gas,W					; set index to O2 ratio of current gas (1-5 -> 0-4)
	movff	PLUSW1,char_I_O2_ratio			; copy         O2 ratio to deco engine
	addlw	.10								; advance index from O2 ratio to He ratio
 IFDEF _helium
	movff	PLUSW1,char_I_He_ratio			; copy         He ratio to deco engine
 ENDIF
	addlw	.10								; advance index from He ratio to gas type
	movff	PLUSW1,char_I_current_gas_type	; copy gas type (0=Disabled, 1=First, 2=Travel, 3=Deco)
setup_gas_registers_com:
	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 (if applicable)
	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 gas 1-5 or 6 (important!)
	return									; done


;-----------------------------------------------------------------------------
; Helper Function - load OC Gases into Deco Engine (currently breathed gas in WREG)
;
	global	deco_setup_oc_gases
deco_setup_oc_gases:
	movff	char_O_deco_status,lo			; get working copy of char_O_deco_status in bank common
deco_setup_oc_gases_pre:					; entry point with lo preloaded
	movff	WREG,char_I_current_gas_num		; set gas to start with when doing the deco calculations
	;
	; Memory Map:
	; ---------------------------------------------------------------------------------
	; opt_gas_O2_ratio		res NUM_GAS		|	char_I_deco_O2_ratio		res NUM_GAS
	; opt_dil_O2_ratio		res NUM_GAS		|
	; opt_gas_He_ratio		res NUM_GAS		|	char_I_deco_He_ratio		res NUM_GAS
	; opt_dil_He_ratio		res NUM_GAS		|
	; opt_gas_type			res NUM_GAS		|	char_I_deco_gas_type		res NUM_GAS
	; opt_dil_type			res NUM_GAS		|
	; opt_gas_change		res NUM_GAS		|	char_I_deco_gas_change		res NUM_GAS
	; opt_dil_change		res NUM_GAS		|
	;
	lfsr	FSR2,char_I_deco_O2_ratio		; load FSR2 with base address of char_I_deco_O2_ratio
											; FSR2 will step through all char_I_deco_... vars
	lfsr	FSR1,opt_gas_O2_ratio			; load FSR1 with base address of opt_gas_O2_ratio
	rcall	deco_setup_copy					; copy all OC O2 ratios
	lfsr	FSR1,opt_gas_He_ratio			; load FSR1 with base address of opt_gas_He_ratio
	rcall	deco_setup_copy					; copy all OC He ratios
	lfsr	FSR1,opt_gas_type				; load FSR1 with base address of opt_gas_type
	rcall	deco_setup_copy					; copy all gas types
	lfsr	FSR1,opt_gas_change				; load FSR1 with base address of opt_gas_change
	rcall	deco_setup_copy					; copy all gas change depths

	; switch deco engine to oc mode
	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									; done


;-----------------------------------------------------------------------------
; Helper Function - dedicated Memory Copy
deco_setup_copy:
	movlw	NUM_GAS						; load loop counter with number of gases (5)
deco_setup_copy_loop:
	movff	POSTINC1,POSTINC2			; copy from (FSR1) to (FSR2)
	decfsz	WREG						; decrement loop counter and check if it became 0
	bra		deco_setup_copy_loop		; NO  - not yet, loop
	return								; YES - done



 IFDEF _ccr_pscr

;-----------------------------------------------------------------------------
; Setup everything to enter CCR/pSCR Dive Mode - Part 1
;
	global	dive_boot_cc
dive_boot_cc:
	rcall	get_first_dil_to_WREG		; get first diluent (1-5) into WREG
	rcall	setup_dil_registers			; set-up of diluent parameters for currently breathed diluent (with WREG = current diluent 1-5)
	rcall	deco_setup_cc_diluents		; set-up of diluent list for deco calculations                (with WREG = current diluent 1-5)
	return								; done


;-----------------------------------------------------------------------------
; Helper Function - get first Diluent (1-5) into WREG
;
	global	get_first_dil_to_WREG
get_first_dil_to_WREG:					; gets first dil (1-5) into WREG
	lfsr	FSR1,opt_dil_type			; load base address of the dil types
	clrf	lo							; start with dil 0
get_first_dil_to_WREG2:
	movf	lo,W						; set index
	movf	PLUSW1,W					; get type of Dil (0=Disabled, 1=First, 2=Normal)
	sublw	.1							; is it of type First?
	bz		get_first_dil_to_WREG3		; YES - found the First dil
	incf	lo,F						; NO  - increment index
	movlw	NUM_GAS+1					;     - get highest index+1
	cpfseq	lo							;     - dils checked?
	bra		get_first_dil_to_WREG2		;       NO  - not yet
	movlw	.1							;       YES - default to dil 1
	movff	WREG,opt_dil_type+0			;           - force it to be of type First
	return								;           - done
get_first_dil_to_WREG3:
	movf	lo,W						; copy index of dil found to be the First to WREG
	incf	WREG,W						; turn index into dil number (0-4 -> 1-5)
	return								; done


;-----------------------------------------------------------------------------
; Helper Function - load currently breathed Diluent into Deco Engine
;
	global	setup_dil_registers
setup_dil_registers:
	btfsc	bailout_mode					; check if in bailout condition                      | --------------- FOR SAFETY ONLY --------------
	bra		setup_gas_registers				; revert to setting up OC gases in bailout condition | This branch should never happen to be taken...
	movwf	active_dil						; set as current diluent
	movlw	.6								; diluent = gas6 ?
	cpfseq	active_dil						; ...
	bra		setup_dil_registers_15			; NO - load diluent 1-5

	; load gas 6
	movff	opt_gas6_O2_ratio,char_I_O2_ratio	; copy gas6 O2 ratio to deco engine
 IFDEF _helium
	movff	opt_gas6_He_ratio,char_I_He_ratio	; copy gas6 He ratio to deco engine
 ENDIF
	movlw	.2								; declare gas6 as a normal diluent
	movff	WREG,char_I_current_gas_type	; copy gas type to deco engine
	movff	depth_meter,char_I_gas6_depth	;set current depth as change depth
	bra		setup_dil_registers_com			; continue with common part

setup_dil_registers_15:
	lfsr	FSR1,opt_dil_O2_ratio			; load base address of diluent data
	decf	active_dil,W					; set index to O2 ratio of current diluent (1-5 -> 0-4)
	movff	PLUSW1,char_I_O2_ratio			; copy         O2 ratio to deco engine
	addlw	.10								; advance index from O2 ratio to He ratio
 IFDEF _helium
	movff	PLUSW1,char_I_He_ratio			; copy         He ratio to deco engine
 ENDIF
	addlw	.10								; advance index from He ratio to diluent type
	movff	PLUSW1,char_I_current_gas_type	; copy diluent type (0=Disabled, 1=First, 2=Normal)
setup_dil_registers_com:
	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_dil,W					; reload WREG with diluent 1-5 or 6 (important!)
	return									; done


;-----------------------------------------------------------------------------
; Helper Function - load Diluents into Deco Engine (currently breathed dil in WREG)
;
	global	deco_setup_cc_diluents
deco_setup_cc_diluents:
	movff	char_O_deco_status,lo			; working copy of char_O_deco_status in bank common
deco_setup_cc_diluents_pre:					; entry point with lo preloaded
	btfsc	bailout_mode					; check if in bailout condition       | --------------- FOR SAFETY ONLY --------------
	bra		deco_setup_oc_gases_pre			; YES - revert to setting up OC gases | This branch should never happen to be taken...
	movff	WREG,char_I_current_gas_num		; NO  - set diluent to start with when doing the deco calculations
	;
	; Memory Map:
	; ---------------------------------------------------------------------------------
	; opt_gas_O2_ratio		res NUM_GAS		|
	; opt_dil_O2_ratio		res NUM_GAS		|	char_I_deco_O2_ratio		res NUM_GAS
	; opt_gas_He_ratio		res NUM_GAS		|
	; opt_dil_He_ratio		res NUM_GAS		|	char_I_deco_He_ratio		res NUM_GAS
	; opt_gas_type			res NUM_GAS		|
	; opt_dil_type			res NUM_GAS		|	char_I_deco_gas_type		res NUM_GAS
	; opt_gas_change		res NUM_GAS		|
	; opt_dil_change		res NUM_GAS		|	char_I_deco_gas_change		res NUM_GAS
	;
	lfsr	FSR2,char_I_deco_O2_ratio		; load FSR2 with base address of char_I_deco_O2_ratio.
											; FSR2 will step through all char_I_deco_... vars.
	lfsr	FSR1,opt_dil_O2_ratio			; load FSR1 with base address of opt_dil_O2_ratio
	rcall	deco_setup_copy					; copy all dil O2 ratios
	lfsr	FSR1,opt_dil_He_ratio			; load FSR1 with base address of opt_dil_He_ratio
	rcall	deco_setup_copy					; copy all dil He ratios
	lfsr	FSR1,opt_dil_type				; load FSR1 with base address of opt_dil_type
	rcall	deco_setup_copy					; copy all dil types
	lfsr	FSR1,opt_dil_change				; load FSR1 with base address of opt_dil_change
	rcall	deco_setup_copy					; copy all dil change depths
											; switch to CCR / pSCR mode:
	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									; done


;-----------------------------------------------------------------------------
; Setup everything to enter CCR / pSCR Dive Mode - Part 2
;
dive_boot_cc_part2:
	; revoke sensors from usage if they do not have a valid calibration
	bsf		use_O2_sensor1
	btfss	sensor1_calibrated_ok
	bcf		use_O2_sensor1

	bsf		use_O2_sensor2
	btfss	sensor2_calibrated_ok
	bcf		use_O2_sensor2

	bsf		use_O2_sensor3
	btfss	sensor3_calibrated_ok
	bcf		use_O2_sensor3

 IFDEF _external_sensor
	; check for external HUD/ppO2 Monitor
	btfss	ext_input_optical			; do we have an optical input?
	bra		dive_boot_cc_part2_1		; NO
	btfsc	sensor1_active				; YES - process flags from HUD/ppO2 Monitor
	bsf		use_O2_sensor1				;     - ...
	btfsc	sensor2_active				;     - ...
	bsf		use_O2_sensor2				;     - ...
	btfsc	sensor3_active				;     - ...
	bsf		use_O2_sensor3				;     - ...
 ENDIF

dive_boot_cc_part2_1:
	; 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				; in pSCR mode?
	bra		dive_boot_cc_part2_2		; NO
	movf	dive_ccr_mode,W				; YES - get mode (=0: Fixed SP (CCR) / calculated SP (pSCR), =1: Sensor, =2: Auto SP)
	sublw	.2							; dive_ccr_mode = 1 (Auto SP)?
	bnz		dive_boot_cc_part2_2		; NO  - ok
	clrf	dive_ccr_mode				; YES - revert to calculated SP

dive_boot_cc_part2_2:
	bsf		event_SP_change				; set setpoint event flag

	; 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						; pre-load WREG with setpoint value 0 for pSCR calculated
	btfsc	FLAG_ccr_mode				; in CCR mode?
	movff	opt_setpoint_cbar+0,WREG	; YES - get value of setpoint 1 into WREG
	movff	WREG,char_I_const_ppO2		; write setpoint to deco engine

 IFDEF _external_sensor
	call	transmit_setpoint			; transmit current setpoint from WREG (in cbar) to external electronics
	goto	calc_deko_divemode_sensor	; process sensor readings and return
 ELSE
	return								; done
 ENDIF

 ENDIF	; _ccr_pscr


;=============================================================================
dmode3	CODE
;=============================================================================


;-----------------------------------------------------------------------------
; Initialize Dive Mode
;
diveloop_boot:
	; do the basic initialization
	call	restart_set_modes_and_flags	; basic settings depending on deco mode

	; save on energy
	call	I2C_sleep_compass			; stop accelerometer and compass

	; do an early initialization of all deco engine output variables to
	; avoid glitches in the display outputs during deco engine start-up
	call	deco_init_output_vars;		; (C-code)
	banksel	common						; back to bank common

	; configure screen layout
	TSTOSC	opt_layout					; alternative layout enabled?
	bsf		alt_layout_active			; YES - start with alternative layout

	; configure tissue graphics
	TSTOSC	opt_tissue_graphics			; shall show: 0= pres+sat, 1= N2+He
	bsf		tissue_graphic_layout		; YES - show press+sat
	TSTOSC	char_I_model				; GF factors enabled?
	bsf		tissue_graphic_gf			; YES - show GF lines

	; reset max relative pressure (max depth)
	bsf		reset_max_pressure			; request ISR to reset the max pressure

	; make working copy of opt_ccr_mode
	movff	opt_ccr_mode,dive_ccr_mode	; copy option setting


 IFDEF _min_depth_option
	; reset the resettable min/max relative pressure (trip-wise min/max depth)
	bsf		reset_trip_pressure			; request ISR to reset the resettable min/max pressure
 ENDIF

 IFDEF _cave_mode
	; initialize the cave mode
	bcf		cave_mode					; disable cave mode by default
	TSTOSC	opt_cave_mode				; cave mode switched on?
	bsf		cave_mode					; YES - enable cave mode

	bcf		dive_turned					; dive is not turned yet
	bcf		backtrack_almost_full		; backtracking storage is not almost   full yet
	bcf		backtrack_entire_full		; backtracking storage is not entirely full yet
	bsf		waypoint_reached_first		; current waypoint is the first recorded waypoint
	bsf		waypoint_reached_last		; current waypoint is the last  recorded waypoint

	clrf	backtrack_waypoint_num		; initialize the waypoint number
	clrf	backtrack_waypoint_turn		; no turn point yet

	movlw	.0							; initialize backtracking index to first position in storage
	movff	WREG,char_I_backtrack_index	; ...

	clrf	depth_meter					; store initial depth data set with depth = surface
	call	write_backtrack_1min_depth	; ...
 ENDIF	; _cave_mode

	; base configuration of the deco engine
	clrf	hi							; start with everything disabled
	TSTOSC	opt_ext_stops				; shall make extended stops?
	bsf		hi,DECO_EXTENDED_STOPS		; YES - enable extended stops
 IFDEF _rx_functions
	btfsc	tr_functions_activated		; TR functions activated?
	bsf		hi,DECO_TR_FUNCTIONS		; YES - enable TR functions
 ENDIF
 IFDEF _gas_contingency
	; set contingency mode on/off
	TSTOSC	opt_gas_contingency_dive	; gas contingency for dive mode switched on?
	bsf		hi,DECO_GAS_CONTINGENCY		; YES - activate gas contingency mode
 ENDIF	; _gas_contingency
	movff	hi,char_O_main_status		; bank-safe copy to deco engine

	clrf	lo							; start with everything disabled
	bsf		lo,DECO_START_NORM			; set flag for doing a normal plan
	bsf		lo,DECO_INITIALIZE			; set flag for initializing the deco engine
	movff	lo,char_O_deco_status		; bank-safe copy back to deco engine

	; disable "fast forward" function
	movlw	.0							; set fast forward to zero
	movff	WREG,char_I_sim_advance_time; ...

	; write last stop depth to deco engine
	movff	opt_last_stop,char_I_last_stop_depth

	; initialize max depth for apnoe mode
	CLRI	apnoe_max_pressure			; reset to zero

	; reset minimum temperature, ISR-safe 2 byte copy
	SMOVII	temperature_cur,temperature_min

	; ISR-safe copy of start-of-dive date and time for logbook (6 bytes in total)
	SMOVSS	rtc_year,start_year

	MOVII	int_O_CNS_current,CNS_start		; save current CNS at beginning of dive, but
	bcf		CNS_start+1,int_warning_flag	; without warning   flag
	bcf		CNS_start+1,int_attention_flag	; without attention flag

	; save supersaturation at beginning of dive (only lower byte is used for value)
	movff	int_O_lead_supersat+0,supersat_start

	clrf	menu_pos_cur				; reset current menu position
	clrf	active_premenu				; no pre-menu task active

	clrf	safety_stop_countdown		; clear safety stop count-down

	CLRI	last_pressure_velocity		; initialize last pressure for velocity calculation
	CLRI	dive_timeout_timer			; initialize timeout counter

	movlw	.1							; initialize the sampling timer such that the 1st sampling ...
	movwf	sampling_timer				; ... trigger will be given as soon as possible

	clrf	message_page				; initialize message page counter
	clrf	alarm_type					; clear all alarms

	; clear the total dive average depth
	CLRI	pressure_rel_avg_total		; average depth
	CLRI	divesecs_avg_total			; time  accumulator
	clrf	pressure_rel_accu_total+0	; depth accumulator
	clrf	pressure_rel_accu_total+1	; ...
	clrf	pressure_rel_accu_total+2	; ...
	clrf	pressure_rel_accu_total+3	; ...

 IFDEF _rx_functions

	btfss	tr_functions_activated		; TR functions activated?
	bra		diveloop_boot_0				; NO  - skip TR function initialization

	banksel	int_IO_pressure_value

	clrf	WREG						; set WREG to coding for integer numbers -> data not available
	bsf		WREG,int_not_avail_flag		; ...
	clrf	int_IO_pressure_value+0		; clear   low  byte   of 1st pressure reading value
	movwf	int_IO_pressure_value+1		; copy to high byte   of 1st pressure reading value
	clrf	int_IO_pressure_value+2		; clear   low  byte   of 2nd pressure reading value
	movwf	int_IO_pressure_value+3		; copy to high byte   of 2nd pressure reading value
	clrf	int_I_pressure_drop+0		; clear   low  byte   of 1st pressure drop    value
	movwf	int_I_pressure_drop+1		; copy to high byte   of 1st pressure drop    value
	clrf	int_I_pressure_drop+2		; clear   low  byte   of 2nd pressure drop    value
	movwf	int_I_pressure_drop+3		; copy to high byte   of 1st pressure drop    value
	clrf	char_I_pressure_gas+0		; clear gas selection of 1st pressure reading
	clrf	char_I_pressure_gas+1		; clear gas selection of 2nd pressure reading
	clrf	char_I_pressure_age+0		; clear age           of 1st pressure reading
	clrf	char_I_pressure_age+1		; clear age           of 2nd pressure reading
	clrf	char_I_pressure_stat+0		; clear status        of 1st pressure reading
	clrf	char_I_pressure_stat+1		; clear status        of 2nd pressure reading

	banksel	gas__last_1st				; select bank with vars for pressure drop calculation
	setf	gas__last_1st				; invalidate last gas of 1st reading
	setf	gas__last_2nd				; invalidate last gas of 2nd reading

	banksel	common						; back to bank common

 ENDIF	; _rx_functions


diveloop_boot_0:
	setf	best_gas_number				; initialize best gas     as not computed yet (255)
 IFDEF _ccr_pscr
	setf	best_dil_number				; initialize best diluent as not computed yet (255)
 ENDIF

	btfsc	FLAG_oc_mode				; in OC mode?
	call	dive_boot_oc				; YES - add OC mode settings

 IFDEF _ccr_pscr
	btfsc	FLAG_ccr_mode				; in CCR mode?
	call	dive_boot_cc				; YES - add CC mode settings
	btfsc	FLAG_ccr_mode				; in CCR mode?
	call	dive_boot_cc_part2			; YES - add CC sensor and SP settings

	btfsc	FLAG_pscr_mode				; in pSCR mode?
	call	dive_boot_cc				; YES - add CC mode settings
	btfsc	FLAG_pscr_mode				; in pSCR mode?
	call	dive_boot_cc_part2			; YES - add CC sensor and SP settings
 ENDIF

	bcf		bailout_mode				; not in bailout mode

	call	ghostwriter_short_header	; write short header with dive number into profile memory
	call	init_recording_params		; set up all the divisors for dive data recording

	; setup gas selector flag (required to have better gas working)
	bsf		is_diluent_menu				; default to using diluents
	btfsc	FLAG_ccr_mode				; in CCR mode?
	bra		diveloop_boot_3				; YES - default was right
	btfsc	FLAG_pscr_mode				; in pSCR mode?
	bra		diveloop_boot_3				; YES - default was right
	bcf		is_diluent_menu				; NO to both - revert to using OC gases

diveloop_boot_3:
	bcf		LEDg						; switch off green LED / release reset to RX circuitry
	bcf		LEDr						; switch off red   LED

	btfss	sensor_override_active		; in simulator mode?
	call	disable_rs232				; NO - disable RS232

 IFDEF _screendump
	btfsc	screen_dump_avail			; screen dump function enabled?
	call	enable_rs232				; enable interface (also sets CPU speed to normal)
 ENDIF

	clrf	apnoe_surface_mins			; clear apnoe surface time, minutes (8 bit)
	clrf	apnoe_surface_secs			; clear apnoe surface time, seconds (8 bit)
	clrf	apnoe_dive_mins				; clear apnoe dive    time, minutes (8 bit)
	clrf	apnoe_dive_secs				; clear apnoe dive    time, seconds (8 bit)

	return								; done with dive mode boot


;=============================================================================
dmode4	CODE
;=============================================================================


;-----------------------------------------------------------------------------
; Check all Sorts of Parameters and issue Warnings and Attentions if applicable
;
divemode_check_warnings:
	movlw	.1							; one message at a time in alternative layout
	btfss	alt_layout_active			; in alternative layout?
	movlw	.2							; NO - two messages at a time in normal layout
	cpfsgt	message_counter				; had more than 1 / 2 messages in the last round?
	bra		divemode_check_warnings1	; NO  - update messages every second

;										; YES - update every 4 seconds:
;	btfss	timebase_1sec				;     - on second 1 or 3 ?
;	return								;       NO  - no update in this cycle
;	btfss	timebase_2sec				;       YES - on second 3 ?
;	return								;             NO  - no update in this cycle
;	;bra	divemode_check_warnings1	;             YES - update messages

										; YES - update every 2 seconds
	btfsc	timebase_1sec				;     - on even second?
	return								;       NO  - done
	;bra	divemode_check_warnings1	;       YES - update messages

divemode_check_warnings1:
	clrf	message_counter				; clear message counter

	; messages sorted by severity: highest severity warnings first, then attentions, advices and last info

	; warnings for all modes
	call	check_battery				; check battery status
	rcall	check_depth_limit			; check current depth
	call	check_divetimeout			; check dive timeout

	btfsc	FLAG_apnoe_mode				; in apnoe mode?
	bra		divemode_check_warnings2	; YES - skip deco mode checks

	btfsc	FLAG_gauge_mode				; in gauge mode?
	bra		divemode_check_warnings2	; YES - skip deco mode checks

	; warnings applicable only in deco modes

 IFDEF _cave_mode
	rcall	check_cavemode				; check cave mode status
 ENDIF

	rcall	check_display_ftts			; show  fTTS time (or cave mode cTTS)
	rcall	check_ppO2					; check ppO2

 IFDEF _external_sensor
	rcall	check_ext_sensors			; check external sensors
 ENDIF

	rcall	check_outside				; check of ZHL16 model violation

 IFDEF _ccr_pscr
	btfsc	FLAG_ccr_mode				; in CCR mode?
	rcall	check_OC_gas_avail			; YES - check if a breathable OC (bailout) gas is available
	btfsc	FLAG_pscr_mode				; in pSCR mode?
	rcall	check_OC_gas_avail			; YES - check if a breathable OC (bailout) gas is available
 ENDIF

	btfsc	decostop_active				; in deco mode?
	rcall	check_saturation			; YES - check tissue saturation

	rcall	check_mbubbles				; check for micro bubbles
	rcall	check_cns_violation_now		; check current     CNS value
	rcall	check_cns_violation_eod		; check end-of-dive CNS value (needs to be done after check_cns_violation_now)
	rcall	check_gas_needs				; check for gas needs
	rcall	check_gas_change			; check for diluent or gas change advice

 IFDEF _ccr_pscr
	btfsc	FLAG_ccr_mode				; in CCR mode?
	rcall	check_gas_density			; YES - check gas density
	btfsc	FLAG_pscr_mode				; in pSCR mode?
	rcall	check_gas_density			; YES - check gas density
 ENDIF

	btfsc	use_aGF						; using alternative GF factors?
	rcall	remind_agf_in_use			; YES - show reminder

divemode_check_warnings2:

 IFDEF _rx_functions
	btfss	tr_functions_activated		; TR functions activated?
	bra		divemode_check_warnings3	; NO  - skip
	call	check_tr_functions			; YES - check transmitter functions
	call	check_tr_messages			;     - check SAC attention and switch advice
 ENDIF

divemode_check_warnings3:

	; compute if an advice / attention / warning sign shall be shown
	rcall	divemode_check_sign

	; increment message page number
	incf	message_page,F				; increment page number
	bcf		STATUS,C					; clear carry bit
	movf	message_page,W				; get page number into WREG
	btfss	alt_layout_active			; in alternative layout?
	rlcf	WREG,W						; NO - each page can take two messages
	cpfsgt	message_counter				; number of actual messages > message capacity ?
	clrf	message_page				; NO - all messages could be shown, restart from first page next time

	; clear both rows of messages if there is nothing to show at all
	tstfsz	message_counter				; any message to show?
	bra		divemode_check_warnings4	; YES - look if second row needs to be cleared
	bsf		FLAG_TFT_message_clear_both	; NO  - request clearing of left-over messages
	return								;     - done

divemode_check_warnings4:
	; clear 2nd row of messages if there is nothing to show (on this page)
	btfss	message_2nd_row_used		; does the 2nd row contain a message?
	bsf		FLAG_TFT_message_clear_2nd	; NO - set flag to clear the 2nd row
	return								; done


;-----------------------------------------------------------------------------
; Helper Function - check if an Advice / Attention / Warning Sign shall be shown
;
divemode_check_sign:
	; clear sign flags
	bcf		sign_advice					; clear flag for showing advice    sign
	bcf		sign_attention				; clear flag for showing attention sign
	bcf		sign_warning				; clear flag for showing warning   sign

	; check for new advices
	movf	DM_flags_advc_det,W			; get current advices
	andwf	DM_flags_advc_ack,W			; keep only those acknowledgments that have current advices
	movwf	DM_flags_advc_ack			; store updated acknowledgments
	xorwf	DM_flags_advc_det,W			; find advices that have not been acknowledged yet
	tstfsz	WREG						; any new advice?
	bsf		sign_advice					; YES - set flag for showing advice sign

	; check for new attentions (1)
	movf	DM_flags_att1_det,W			; get current attentions
	andwf	DM_flags_att1_ack,W			; keep only those acknowledgments that have current attentions
	movwf	DM_flags_att1_ack			; store updated acknowledgments
	xorwf	DM_flags_att1_det,W			; find attentions that have not been acknowledged yet
	tstfsz	WREG						; any new attention?
	bsf		sign_attention				; YES - set flag for showing attention sign

	; check for new attentions (2)
	movf	DM_flags_att2_det,W			; get current attentions
	andwf	DM_flags_att2_ack,W			; keep only those acknowledgments that have current attentions
	movwf	DM_flags_att2_ack			; store updated acknowledgments
	xorwf	DM_flags_att2_det,W			; find attentions that have not been acknowledged yet
	tstfsz	WREG						; any new attention?
	bsf		sign_attention				; YES - set flag for showing attention sign

	; check for new attentions (3)
	movf	DM_flags_att3_det,W			; get current attentions
	andwf	DM_flags_att3_ack,W			; keep only those acknowledgments that have current attentions
	movwf	DM_flags_att3_ack			; store updated acknowledgments
	xorwf	DM_flags_att3_det,W			; find attentions that have not been acknowledged yet
	tstfsz	WREG						; any new attention?
	bsf		sign_attention				; YES - set flag for showing attention sign

	; check for new warnings (1)
	movf	DM_flags_war1_det,W			; get current warnings
	andwf	DM_flags_war1_ack,W			; keep only those acknowledgments that have current warnings
	movwf	DM_flags_war1_ack			; store updated acknowledgments
	xorwf	DM_flags_war1_det,W			; find warnings that have not been acknowledged yet
	tstfsz	WREG						; any new warning?
	bsf		sign_warning				; YES - set flag for showing warning sign

	; check for new warnings (2)
	movf	DM_flags_war2_det,W			; get current warnings
	andwf	DM_flags_war2_ack,W			; keep only those acknowledgments that have current warnings
	movwf	DM_flags_war2_ack			; store updated acknowledgments
	xorwf	DM_flags_war2_det,W			; find warnings that have not been acknowledged yet
	tstfsz	WREG						; any new warning?
	bsf		sign_warning				; YES - set flag for showing warning sign

	; show or clear the advice / attention / warning sign
	btfsc	sign_advice					; shall show advice sign?
	bsf		FLAG_TFT_sign_show			; YES - show sign
	btfsc	sign_attention				; shall show attention sign?
	bsf		FLAG_TFT_sign_show			; YES - show sign
	btfsc	sign_warning				; shall show warning sign?
	bsf		FLAG_TFT_sign_show			; YES - show sign
	btfss	FLAG_TFT_sign_show			; shall show any sign?
	bsf		FLAG_TFT_sign_clear			; NO  - then clear the sign

	return								; done


;-----------------------------------------------------------------------------
; Check Battery Power
;
	global	check_battery
check_battery:
	bcf		warn_det_batt_low			; clear warning for battery low
	movlw	battery_show_level+1		; get threshold for showing battery level, incremented by 1
	cpfslt	batt_percent				; battery percentage ok?
	return								; YES - done
	btfsc	battery_low_condition		; NO  - battery low condition detected?
	bsf		warn_det_batt_low			;       YES - set warning for battery low
	movf	active_customview,W			;     - get current custom view
	xorlw	index_clock_batt_surfpress	;     - battery shown in custom view?
	bnz		check_battery_mesg			;       NO  - show message
	return								;       YES - do not show twice, done

check_battery_mesg:
	incf	message_counter,F			; increase message counter
	goto	TFT_message_battery_percent	; show message for battery low (battery percent) and return


;-----------------------------------------------------------------------------
; Show Dive Timeout Counter if Dive Time is not counted
;
check_divetimeout:
	btfsc	count_divetime				; is dive time counted?
	return								; YES - nothing to do, done
	incf	message_counter,F			; NO  - increase message counter
	goto	TFT_message_divetimeout		;     - show timeout counter and return


;-----------------------------------------------------------------------------
; Check ppO2 of all Gases / Diluents in use
;
check_ppO2:
 IFDEF _ccr_pscr
	; check if breathing from the loop
	btfsc	FLAG_oc_mode				; in OC mode?
	bra		check_ppO2_1				; YES - continue with breathed gas
	btfsc	bailout_mode				; NO  - in bailout?
	bra		check_ppO2_1				;       YES - continue with breathed gas
	; CCR / pSCR mode - check the pure diluent
	bcf		warn_det_ppO2_diluent		; clear warning   for pure diluent ppO2
	bcf		attn_det_ppo2_diluent		; clear attention for pure diluent ppO2
	MOVII	int_O_pure_ppO2,mpr			; get value and attention/warning flags for the pure diluent
	btfsc	hi,int_warning_flag			; ppO2 of the pure diluent in warning state?
	bra		check_ppO2_dil_warn			; YES - show warning
	btfsc	hi,int_attention_flag		; ppO2 of the pure diluent in attention state?
	bra		check_ppO2_dil_attn			; YES - show attention
	bra		check_ppO2_1				; continue with checking breathed gas

check_ppO2_dil_warn:
	bsf		warn_det_ppO2_diluent		; set warning   for pure diluent ppO2
	rcall	check_ppO2_show_mesg		; show ppO2 message
	bra		check_ppO2_1				; continue with checking breathed gas

check_ppO2_dil_attn:
	bsf		attn_det_ppo2_diluent		; set attention for pure diluent ppO2
	rcall	check_ppO2_show_mesg		; show ppO2 message
	;bra	check_ppO2_1				; continue with checking breathed gas
 ENDIF	; _ccr_pscr

check_ppO2_1:
	; all modes - check breathed gas (OC or loop)
	bcf		attn_det_ppo2_breathed		; clear attention for breathed ppO2
	bcf		warn_det_ppO2_breathed		; clear warning   for breathed ppO2
	MOVII	int_O_breathed_ppO2,mpr		; get value and attention/warning flags for the breathed gas
	btfsc	hi,int_attention_flag		; breathed ppO2 in attention state (when in loop mode, no attention will be generated)?
	bra		check_ppO2_breath_attn		; YES - set attention flag and show ppO2
	btfsc	hi,int_low_flag				; NO  - breathed ppO2 too low?
	bra		check_ppO2_breath_warn_low	;       YES - record the warning and show ppO2
	btfsc	hi,int_high_flag			;       NO  - breathed ppO2 too high?
	bra		check_ppO2_breath_warn_high	;             YES - record the warning and show ppO2
	bra		check_ppO2_breath_ok		;             NO  - ppO2 is ok

check_ppO2_breath_attn:
	bsf		attn_det_ppo2_breathed		; set attention for breathed ppO2
	bra		check_ppO2_show				; show ppO2 message

check_ppO2_breath_warn_low:
	movlw	d'4'						; set type of alarm (ppO2 low)
	bra		check_ppO2_breath_common	; continue with common part

check_ppO2_breath_warn_high:
	movlw	d'5'						; set type of alarm (ppO2 high)
	;bra	check_ppO2_breath_common	; continue with common part

check_ppO2_breath_common:
	movwf	alarm_type					; copy alarm type to alarm register
	bsf		event_occured				; set event flag
	bsf		warn_det_ppO2_breathed		; set warning for breathed ppO2
	bra		check_ppO2_show				; show ppO2 message

check_ppO2_breath_ok:
	TSTOSS	opt_showppo2				; shall always show ppO2 (0 = no, 1 = yes)
	return								; NO  - done
	;bra	check_ppO2_show				; YES - show ppO2 message

check_ppO2_show:
 IFDEF _ccr_pscr
	btfsc	FLAG_oc_mode				; in OC mode?
	bra		check_ppO2_show_1			; YES - show ppO2 message
	btfsc	bailout_mode				; in bailout mode?
	bra		check_ppO2_show_1			; YES - show ppO2 message
	return								; NO  - in loop mode, ppO2 is already shown via setpoint display
 ENDIF
check_ppO2_show_1:
	movf	active_customview,W			; get current custom view
	xorlw	index_ppo2_ead_end_cns		; ppO2 shown already via custom view?
	bz		check_ppO2_done				; YES - done
	movf	active_customview,W			; get current custom view (again)
	xorlw	index_pscr_info				; ppO2 shown already via custom view?
	bz		check_ppO2_done				; YES - done
	;bra	check_ppO2_show_mesg		; NO  - show ppO2 message

check_ppO2_show_mesg:
	incf	message_counter,F			; increase message counter
	goto	TFT_message_ppo2			; show ppO2 message and return

check_ppO2_done:
	return								; done


;-----------------------------------------------------------------------------
; Show fTTS Message
;
check_display_ftts:
 IFDEF _ccr_pscr
	btfsc	bailout_mode				; in bailout mode?
	return								; YES - in bailout no fTTS is computed, done
 ENDIF
	btfss	count_divetime				; is dive time counted?
	return								; NO  - omit, done
	movff	char_I_extra_time,lo		; YES - get extra time
	tstfsz	lo							;     - extra time > 0 ?
	bra		check_display_ftts_mesg		;       YES - show fTTS
	return								;       NO  - no fTTS computed, done

check_display_ftts_mesg:
	incf	message_counter,F			; increase counter
	goto	TFT_message_ftts			; show @+x time


;-----------------------------------------------------------------------------
; check current CNS Value
;
	global	check_cns_violation_now
check_cns_violation_now:
	bcf		warn_det_cns_current		; clear warning   for CNS
	bcf		attn_det_cns_current		; clear attention for CNS
	movff	int_O_CNS_current+1,WREG	; get current CNS, high byte
	btfsc	WREG,int_warning_flag		; warning flag set?
	bra		check_cns_violation_now_warn; YES - show a warning
	btfsc	WREG,int_attention_flag		; attention flag set?
	bra		check_cns_violation_now_attn; YES - show an attention
	return								; NO  - done

check_cns_violation_now_warn:
	bsf		warn_det_cns_current		; set warning for CNS
	bra		check_cns_violation_now_mesg; show message

check_cns_violation_now_attn:
	bsf		attn_det_cns_current		; set attention for CNS
	;bra	check_cns_violation_now_mesg; show message

check_cns_violation_now_mesg:
 IFNDEF _helium
	movf	active_customview,W			; get current custom view
	xorlw	index_ppo2_ead_end_cns		; CNS shown?
	bz		check_cns_violation_now_done; YES - done
 ENDIF
	movf	active_customview,W			; get current custom view (again)
	xorlw	index_CNS					; CNS shown?
	bz		check_cns_violation_now_done; YES - done
	incf	message_counter,F			; NO  - increase counter
	goto	TFT_message_cns				;     - show message and return

check_cns_violation_now_done:
	return								; done


;-----------------------------------------------------------------------------
; check end-of-Dive CNS Value
;
	global	check_cns_violation_eod
check_cns_violation_eod:
	bcf		attn_det_cns_eod			; clear attention for end-of-dive CNS
	btfsc	warn_det_cns_current		; current CNS value in warning state?
	return								; YES - inhibit end-of-dive CNS checks if current CNS is already in warning
	;bra	check_cns_violation_eod_norm; NO  - check normal plan

check_cns_violation_eod_norm:
	movff	int_O_CNS_norm+1,WREG		; get CNS at end of dive in normal plan, high byte
	btfsc	WREG,int_invalid_flag		; flag for invalid value set?
	bra		check_cns_violation_eod_alt	; YES - continue with checking alternative plan
	btfsc	WREG,int_warning_flag		; NO  - flag for warning set?
	bra		check_cns_violation_eod_warn;       YES - show message
	;bra	check_cns_violation_eod_alt	;       NO  - check alternative plan

check_cns_violation_eod_alt:
	movff	int_O_CNS_alt+1,WREG		; get CNS at end of dive in alternative plan, high byte
	btfsc	WREG,int_invalid_flag		; flag for invalid value set?
	return								; YES - done
	btfsc	WREG,int_warning_flag		; NO  - flag for warning set?
	bra		check_cns_violation_eod_warn;       YES - show message
	return								;       NO  - done

check_cns_violation_eod_warn:
	bsf		attn_det_cns_eod			; set attention(!) for end-of-dive CNS
	movf	active_customview,W			; get current custom view
	xorlw	index_CNS					; CNS shown?
	bz		check_cns_violation_eod_done; YES - done
	incf	message_counter,F			; NO  - increase message counter
	goto	TFT_message_cns_eod			;     - show message for end-of-dive CNS and return

check_cns_violation_eod_done:
	return								; done


;-----------------------------------------------------------------------------
; Check current Tissue Supersaturation
;
	global	check_saturation
check_saturation:
	bcf		attn_det_saturation			; clear attention for saturation
	bcf		warn_det_saturation			; clear warning   for saturation
	bcf		attn_det_ibcd				; clear attention for IBCD
	movff	int_O_lead_supersat+1,WREG	; get upper byte of leading tissue's supersaturation
	btfss	WREG,int_warning_flag		; warning flag set?
	bra		check_saturation_1			; NO  - continue with checking for attention flag
	movlw	d'2'						; YES - set type of alarm
	movwf	alarm_type					;     - copy to alarm register
	bsf		event_occured				;     - set event flag
	bsf		warn_det_saturation			;     - set   warning
	bra		check_saturation_mesg		;     - show saturation message

check_saturation_1:
	btfss	WREG,int_attention_flag		; attention flag set?
	bra		check_saturation_2			; NO  - continue with checking for IBCD
	bsf		attn_det_saturation			; YES - set   attention
	bra		check_saturation_mesg		;     - show saturation message

check_saturation_2:
 IFDEF _helium
	TSTOSS	opt_enable_IBCD				; IBCD warning activated?
	bra		check_saturation_3			; NO  - continue with checking deco info
	movff	char_O_deco_warnings,WREG	; YES - get the deco warnings vector
	btfss	WREG,IBCD_warning			;     - IBCD warning flag set?
	bra		check_saturation_3			;       NO  - continue with checking deco info
	bsf		attn_det_ibcd				;       YES - set attention
	bra		check_saturation_mesg		;           - show saturation message
 ENDIF

check_saturation_3:
	btfss	divemode					; in dive mode?
	return								; NO  - done
 IFDEF _ccr_pscr
	btfsc	bailout_mode				; YES - in bailout mode?
	return								;       YES - done (deco zone flag is not updated when in bailout mode)
 ENDIF
	movff	char_O_deco_info,WREG		;       NO  - get the deco info vector
	btfss	WREG,deco_zone				;             deco zone flag set?
	return								;             NO  - done
	btfsc	use_aGF						;             YES - using alternative GF factors?
	return								;                   YES - suppress deco zone info
	btfsc	alt_layout_active			;                   NO  - in alternative layout?
	return								;                         YES - suppress deco zone info
	incf	message_counter,F			;                         NO  - increase message counter
	goto	TFT_message_deco_info		;                             - show deco info and return

check_saturation_mesg:
 IFDEF _helium
	btfss	attn_det_ibcd				; IBCD detected?
	bra		check_saturation_mesg_1		; NO  - show saturation message
	incf	message_counter,F			; YES - increase message counter
	call	TFT_message_IBCD			;     - show IBCD message
 ENDIF
check_saturation_mesg_1:
	incf	message_counter,F			; increase message counter
	goto	TFT_message_saturation		; show saturation message and return


;-----------------------------------------------------------------------------
; Check Depth Limit
;
check_depth_limit:
	bcf		warn_det_depth_limit		; clear warning by default
	movff	opt_max_depth,WREG			; get depth limit
	cpfsgt	depth_meter					; current depth > depth limit?
	return								; NO  - done
	bsf		warn_det_depth_limit		; YES - set warning
	incf	message_counter,F			;     - increase message counter
	goto	TFT_message_depth_limit		;     - show message


;-----------------------------------------------------------------------------
; Check Bühlmann Model Violation
;
check_outside:
	bcf		warn_det_outside			; clear warning
	bcf		attn_det_outside			; clear attention
	movff	char_O_deco_warnings,WREG	; bank-safe copy of deco warnings
	btfss	WREG,outside_warning		; currently outside the ZH-L16 model?
	bra		check_outside_1				; NO
	bsf		warn_det_outside			; YES - set warning
	bra		check_outside_mesg			;     - show message

check_outside_1:
	btfss	WREG,outside_warning_lock	; had been outside of the ZH-L16 model?
	return								; NO  - done
	bsf		attn_det_outside			; YES - set attention
	;bra	check_outside_mesg			;     - show message

check_outside_mesg:
	incf	message_counter,F			; increase message counter
	goto	TFT_message_outside			; show message and return


;-----------------------------------------------------------------------------
; Check raised Probability for Micro-Bubbles
;
	global	check_mbubbles
check_mbubbles:
	bcf		warn_det_microbubble		; clear warning
	bcf		attn_det_microbubble		; clear attention
	movff	char_O_deco_warnings,WREG	; bank-safe copy for deco warnings
	btfss	WREG,mbubble_warning		; currently in micro bubbling zone?
	bra		check_mbubbles_1			; NO
	bsf		warn_det_microbubble		; YES - set warning
	bra		check_mbubbles_mesg			;     - show message

check_mbubbles_1
	btfss	WREG,mbubble_warning_lock	; had been in micro bubbling zone?
	return								; NO  - done
	bsf		attn_det_microbubble		; YES - set attention
	;bra	check_mbubbles_mesg			;     - show message

check_mbubbles_mesg:
	incf	message_counter,F			; increase message counter
	goto	TFT_message_mbubbles		; show message and return


 IFDEF _ccr_pscr
;-----------------------------------------------------------------------------
; Check Gas Density
;
check_gas_density:
	TSTOSS	opt_gas_density_check		; shall check gas density?
	return								; NO - done
	bcf		warn_det_gas_density		; YES - clear attention for gas density by default
	bcf		attn_det_gas_density		;     - clear warning   for gas density by default
	movff	int_O_gas_density+1,WREG	;     - get upper byte of current gas density
	btfsc	WREG,int_warning_flag		;     - warning flag set?
	bra		check_gas_density_warn		;       YES - generate a warning
	btfsc	WREG,int_attention_flag		;       NO  - attention flag set?
	bra		check_gas_density_attn		;             YES - generate an attention
	;bra	check_gas_density_ok		;             NO  - gas density ok

check_gas_density_ok:
	bcf		shown_gas_density_attn		; re-arm custom view show-up for warning
	bcf		shown_gas_density_warn		; re-arm custom view show-up for attention
	return								; done

check_gas_density_warn:
	bsf		warn_det_gas_density		; set warning
	bcf		shown_gas_density_attn		; re-arm custom view show-up for attention
	btfsc	shown_gas_density_warn		; has the custom view been shown before on warning level?
	bra		check_gas_density_mesg		; YES - do not show the gas needs custom view again
	btfsc	custom_view_locked			; NO  - custom view locked?
	bra		check_gas_density_mesg		;       YES - do not show it now
	bsf		shown_gas_density_warn		;       NO  - set custom view as shown now
	bra		check_gas_density_cv		;           - show gas needs custom view

check_gas_density_attn:
	bsf		attn_det_gas_density		; set attention
	bcf		shown_gas_density_warn		; re-arm custom view show-up for warning
	btfsc	shown_gas_density_attn		; has the custom view been shown before on attention level?
	bra		check_gas_density_mesg		; YES - do not show the gas needs custom view again
	btfsc	custom_view_locked			; NO  - custom view locked?
	bra		check_gas_density_mesg		;       YES - do not show it now
	bsf		shown_gas_density_attn		;       NO  - set custom view as shown now
	;bra	check_gas_density_cv		;           - show gas needs custom view

check_gas_density_cv:
	movlw	index_ppo2_ead_end_cns		; get  custom view number of gas density
	call	dive_customview_show		; show custom view
	;bra	check_gas_density_mesg		; show message

check_gas_density_mesg:
	incf	message_counter,F			; increase message counter
	goto	TFT_message_gas_density		; show gas density message and return


;-----------------------------------------------------------------------------
; Check if an OC Bailout Gas is available
;
check_OC_gas_avail:
	bcf		warn_det_no_bo_gas			; clear warning by default
	tstfsz	best_gas_number				; is a breathable OC (bailout) gas available?
	return								; YES - a breathable gas is available, done
	btfsc	bailout_mode				; NO  - in bailout?
	return								;       YES - suppress warning, done
	bsf		warn_det_no_bo_gas			;       NO  - set warning for no bailout gas
	incf	message_counter,F			;           - increase message counter
	goto	TFT_message_no_BO_gas		;           - show message and return

 ENDIF	; _ccr_pscr


 IFDEF _cave_mode

;-----------------------------------------------------------------------------
; Check Cave Profile Storage Usage
;
check_cavemode:
	bcf		warn_det_cave_shut_down		; clear warning   by default
	bcf		attn_det_cave_shut_down		; clear attention by default
	btfsc	backtrack_entire_full		; is the backtracking storage entirely used up?
	bra		check_cavemode_full			; YES - turn dive, switch off cave mode and show warning message
	btfsc	backtrack_almost_full		; NO  - backtracking storage almost full?
	bra		check_cavemode_almost_full	;       YES - show attention message that cave mode will stop soon
	btfss	cave_mode					;       NO  - cave mode switched on?
	return								;             NO  - do not show info
	btfsc	alt_layout_active			;             YES - alternative layout active?
	return								;                   YES - suppress info message
	;bra	check_cavemode_mesg			;                   NO  - show cave mode active info

check_cavemode_mesg:
	incf	message_counter,F			; increase message counter
	goto	TFT_message_cave_mode		; show cave mode message

check_cavemode_full:
	btfss	backtrack_shutdown			; backtracking shut down already?
	bsf		request_cave_off_turned		; NO  - request to switch cave mode off and to set the dive as turned
	bsf		backtrack_shutdown			; remember shut down as been executed (anyhow)
	btfss	cave_mode					; has the cave mode been switched on again meanwhile?
	bsf		warn_det_cave_shut_down		; NO  - set warning level
	btfsc	cave_mode					; has the cave mode been switched on again meanwhile?
	bsf		attn_det_cave_shut_down		; YES - set attention level
	bra		check_cavemode_mesg			; show message

check_cavemode_almost_full:
	btfss	cave_mode					; cave mode switched on?
	return								; NO  - suppress message
	bsf		attn_det_cave_shut_down		; YES - set an attention
	bra		check_cavemode_mesg			;     - show message

 ENDIF	; _cave_mode


;-----------------------------------------------------------------------------
; Show aGF Reminder
;
remind_agf_in_use:
	incf	message_counter,F			; increase message counter
	goto	TFT_message_agf				; show aGF reminder and return


;-----------------------------------------------------------------------------
; Check better Gas / Diluent Advice
;
check_gas_change:
	bcf		advc_det_change_gas			; clear advice by default
 IFDEF _ccr_pscr
	btfsc	better_dil_available		; is a better diluent available?
	bra		check_gas_change_mesg		; YES - show a gas change advice
 ENDIF
	btfsc	better_gas_available		; is a better gas     available?
	bra		check_gas_change_mesg		; YES - show a gas change advice
	return								; NO  - done

check_gas_change_mesg:
	bsf		advc_det_change_gas			; set advice
	incf	message_counter,F			; increase message counter
	goto	TFT_message_gas_change		; show advice and return


 IFDEF _rx_functions

;-----------------------------------------------------------------------------
; Check SAC and Swap-Tank Advice
;
check_tr_messages:
	bcf		attn_det_sac_rate			; clear SAC attention by default
	bcf		advc_det_switch_tank		; clear switch advice by default
	btfss	count_divetime				; is the dive time counted, i.e. deeper than dive threshold?
	return								; NO  - suppress check
	movff	int_O_SAC_measured+1,WREG	; YES - bank-safe copy of measured SAC rate
	btfss	WREG,int_attention_flag		;     - attention flag set?
	bra		check_tr_messages_chk_swap	;       NO  - continue with checking for swap advice
	btfsc	WREG,int_not_avail_flag		;       SAC rate available?
	bra		check_tr_messages_chk_swap	;       NO  - continue with checking for swap advice
	bsf		attn_det_sac_rate			;       YES - set attention for SAC rate
	movf	active_customview,W			;           - get current custom view
	xorlw	index_pressures_SAC			;           - SAC rate shown?
	bz		check_tr_messages_chk_swap	;             YES - do not show twice, continue with swap advice
	;bra	check_tr_messages_mesg_sac	;             NO  - show SAC message

check_tr_messages_mesg_sac:
	incf	message_counter,F			; increase message counter
	call	TFT_message_sac				; show message for SAC rate
	;bra	check_tr_messages_chk_swap	; continue with switch advice

check_tr_messages_chk_swap:
	movff	char_O_deco_info,WREG		; bank-safe copy of deco info vector
	btfss	WREG,ind_double_switch		; swap tank flag set?
	return								; NO  - done
	;bra	check_tr_messages_mesg_swap	; YES - show swap message

check_tr_messages_mesg_swap:
	bsf		advc_det_switch_tank		; set advice
	incf	message_counter,F			; increase message counter
	goto	TFT_message_switch_tanks	; show message for switching tanks and return


;-----------------------------------------------------------------------------
; Check Transmitter States
;
check_tr_functions:
	; check transmitter 1
	movff	char_I_pressure_stat+0,WREG		; get status of 1st pressure reading
	rcall	check_tr_functions_helper1		; check for transmitter 1 lost
	rcall	check_tr_functions_helper2		; check for transmitter 1 low battery
	movff	int_IO_pressure_value+1,WREG	; get high byte of 1st pressure reading
	rcall	check_tr_functions_helper3		; check for transmitter 1 pressure warning
	rcall	check_tr_functions_helper4		; check for transmitter 1 pressure attention
	; check transmitter 2
	movff	char_I_pressure_stat+1,WREG		; get status of 2nd pressure reading
	rcall	check_tr_functions_helper5		; check for transmitter 2 lost
	rcall	check_tr_functions_helper6		; check for transmitter 2 low battery
	movff	int_IO_pressure_value+3,WREG	; get high byte of 2nd pressure reading
	rcall	check_tr_functions_helper7		; check for transmitter 2 pressure warning
	rcall	check_tr_functions_helper8		; check for transmitter 2 pressure attention

	; results for transmitter
	btfsc	attn_det_xmit1_bat				; do we have a transmitter 1 attention?
	bra		check_tr_functions_xmitter_mesg	; YES - show transmitter message
	btfsc	attn_det_xmit2_bat				; do we have a transmitter 2 attention?
	bra		check_tr_functions_xmitter_mesg	; YES - show transmitter message
check_tr_functions_1:
	btfsc	warn_det_pressure1				; do we have a pressure 1 warning?
	bra		check_tr_functions_pres_mesg	; YES - show pressure message
	btfsc	warn_det_pressure2				; do we have a pressure 2 warning?
	bra		check_tr_functions_pres_mesg	; YES - show pressure message
	btfsc	attn_det_pressure1				; do we have a pressure 1 attention?
	bra		check_tr_functions_pres_mesg	; YES - show pressure message
	btfsc	attn_det_pressure2				; do we have a pressure 2 attention?
	bra		check_tr_functions_pres_mesg	; YES - show pressure message
	return									; done

check_tr_functions_xmitter_mesg:
	incf	message_counter,F				; increase message counter
	call	TFT_message_transmitter			; show transmitter message
	bra		check_tr_functions_1			; continue with pressure messages

check_tr_functions_pres_mesg:
	incf	message_counter,F				; increase message counter
	goto	TFT_message_pressure			; show pressure message and return

check_tr_functions_helper1:
	btfsc	WREG,char_transmitter_lost		; transmitter 1 lost?
	bra		check_tr_functions_helper1a		; YES - show transmitter attention message
	bcf		shown_xmit1_lost				; NO  - clear flag for old message
	return									;     - done
check_tr_functions_helper1a:
	btfsc	shown_xmit1_lost				; is it a new message?
	return									; NO  - do not show the pressure readings custom view again
	bsf		shown_xmit1_lost				; YES - memorize it's an old message now
	rcall	check_tr_functions_show_cv		;     - show custom view

check_tr_functions_helper2:
	btfsc	WREG,char_transmitter_low_bat	; transmitter 1 low battery?
	bra		check_tr_functions_helper2a		; YES - show transmitter attention message
	bcf		shown_xmit1_battery				; NO  - clear flag for old message
	bcf		attn_det_xmit1_bat				;     - clear transmitter 1 attention
	return									;     - done
check_tr_functions_helper2a:
	bsf		attn_det_xmit1_bat				; set transmitter 1 attention
	btfsc	shown_xmit1_battery				; is it a new message?
	return									; NO  - do not show the pressure readings custom view again
	bsf		shown_xmit1_battery				; YES - memorize it's an old message now
	rcall	check_tr_functions_show_cv		;     - show custom view

check_tr_functions_helper3:
	btfsc	WREG,int_warning_flag			; transmitter 1 pressure warning?
	bra		check_tr_functions_helper3a		; YES - show pressure reading message as warning
	bcf		shown_xmit1_pres_warn			; NO  - clear flag for old message
	bcf		warn_det_pressure1				;     - clear pressure 1 warning
	return									;     - done
check_tr_functions_helper3a:
	bsf		warn_det_pressure1				; set pressure 1 warning
	btfsc	shown_xmit1_pres_warn			; is it a new message?
	return									; NO  - do not show the pressure readings custom view again
	bsf		shown_xmit1_pres_warn			; YES - memorize it's an old message now
	bra		check_tr_functions_show_cv		;     - show custom view

check_tr_functions_helper4:
	btfsc	WREG,int_attention_flag			; transmitter 1 pressure attention?
	bra		check_tr_functions_helper4a		; YES - show pressure reading message as attention
	bcf		shown_xmit1_pres_attn			; NO  - clear flag for old message
	bcf		attn_det_pressure1				;     - clear pressure 1 attention
	return									;     - done
check_tr_functions_helper4a
	bsf		attn_det_pressure1				; set pressure 1 attention
	btfsc	shown_xmit1_pres_attn			; is it a new message?
	return									; NO  - do not show the pressure readings custom view again
	bsf		shown_xmit1_pres_attn			; YES - memorize it's an old message now
	bra		check_tr_functions_show_cv		;     - show custom view

check_tr_functions_helper5:
	btfsc	WREG,char_transmitter_lost		; transmitter 2 lost?
	bra		check_tr_functions_helper5a		; YES - show transmitter attention message
	bcf		shown_xmit2_lost				; NO  - clear flag for old lost message
	return									;     - done
check_tr_functions_helper5a:
	btfsc	shown_xmit2_lost				; is it a new message?
	return									; NO  - do not show the pressure readings custom view again
	bsf		shown_xmit2_lost				; YES - memorize it's an old message now
	bra		check_tr_functions_show_cv		;     - show custom view

check_tr_functions_helper6:
	btfsc	WREG,char_transmitter_low_bat	; transmitter 2 low battery?
	bra		check_tr_functions_helper6a		; YES - show transmitter attention message
	bcf		shown_xmit2_battery				; NO  - clear flag for old battery message
	bcf		attn_det_xmit2_bat				;     - clear transmitter 2 attention
	return									;     - done
check_tr_functions_helper6a:
	bsf		attn_det_xmit2_bat				; set transmitter 2 attention
	btfsc	shown_xmit2_battery				; is it a new message?
	return									; NO  - do not show the pressure readings custom view again
	bsf		shown_xmit2_battery				; YES - memorize it's an old message now
	bra		check_tr_functions_show_cv		;     - show custom view

check_tr_functions_helper7:
	btfsc	WREG,int_warning_flag			; transmitter 2 pressure warning?
	bra		check_tr_functions_helper7a		; YES - show pressure reading message as warning
	bcf		shown_xmit2_pres_warn			; NO  - clear flag for old message
	bcf		warn_det_pressure2				;     - clear pressure 2 warning
	return									;     - done
check_tr_functions_helper7a:
	bsf		warn_det_pressure2				; set pressure 2 warning
	btfsc	shown_xmit2_pres_warn			; is it a new message?
	return									; NO  - do not show the pressure readings custom view again
	bsf		shown_xmit2_pres_warn			; YES - memorize it's an old message now
	bra		check_tr_functions_show_cv		;     - show custom view

check_tr_functions_helper8:
	btfsc	WREG,int_attention_flag			; transmitter 2 pressure attention?
	bra		check_tr_functions_helper8a		; YES - show pressure reading message as attention
	bcf		shown_xmit2_pres_attn			; NO  - clear flag for old message
	bcf		attn_det_pressure2				;     - clear pressure 2 attention
	return									;     - done
check_tr_functions_helper8a
	bsf		attn_det_pressure2				; set pressure 2 attention
	btfsc	shown_xmit2_pres_attn			; is it a new message?
	return									; NO  - do not show the pressure readings custom view again
	bsf		shown_xmit2_pres_attn			; YES - memorize it's an old message now
	;bra	check_tr_functions_show_cv		;     - show custom view

check_tr_functions_show_cv:
	btfsc	custom_view_locked				; NO  - custom view locked?
	return									;       YES - do not show now
	movlw	index_pressures_SAC				;       NO  - get  custom view number of pressure readings
	goto	dive_customview_show			;           - show custom view and return

 ENDIF	; _rx_functions


;-----------------------------------------------------------------------------
; Check Gas Needs
;
check_gas_needs:
	bcf		attn_det_gas_needs			; clear attention by default
	bcf		warn_det_gas_needs			; clear warning   by default
	banksel	int_O_gas_need_pres			; switch to bank where int_O_gas_need_pres is stored
	movf	int_O_gas_need_pres+1,W		; get               high byte from pres need of 1st tank
	iorwf	int_O_gas_need_pres+3,W		; inclusive or with high byte from pres need of 2nd tank
	iorwf	int_O_gas_need_pres+5,W		; inclusive or with high byte from pres need of 3rd tank
	iorwf	int_O_gas_need_pres+7,W		; inclusive or with high byte from pres need of 4th tank
	iorwf	int_O_gas_need_pres+9,W		; inclusive or with high byte from pres need of 5th tank
	banksel	common						; back to bank common
	btfsc	WREG,int_invalid_flag		; any invalid flag set?
	bra		check_gas_needs_ok			; YES - no further checking required
	btfsc	WREG,int_warning_flag		; NO  - any gas with pres_need >= pres_fill ?
	bra		check_gas_needs_warn		;       YES - generate a warning
	btfsc	WREG,int_attention_flag		;       NO  - any gas with pres_need >= pres_fill * threshold ?
	bra		check_gas_needs_attn		;             YES - generate an attention
	;bra	check_gas_needs_ok			;             NO  - gas needs ok

check_gas_needs_ok:
	bcf		shown_gas_needs_warn		; re-arm custom view show-up for warning
	bcf		shown_gas_needs_attn		; re-arm custom view show-up for attention
	return								; done

check_gas_needs_warn:
	bsf		warn_det_gas_needs			; set warning
	bcf		shown_gas_needs_attn		; re-arm custom view show-up for attention
	btfsc	shown_gas_needs_warn		; has the custom view been shown before on warning level?
	bra		check_gas_needs_mesg		; YES - do not show the gas needs custom view again
	btfsc	custom_view_locked			; NO  - custom view locked?
	bra		check_gas_needs_mesg		;       YES - do not show it now
	bsf		shown_gas_needs_warn		;       NO  - set custom view as shown now
	bra		check_gas_needs_cv			;           - show gas needs custom view

check_gas_needs_attn:
	bsf		attn_det_gas_needs			; set attention
	bcf		shown_gas_needs_warn		; re-arm custom view show-up for warning
	btfsc	shown_gas_needs_attn		; has the custom view been shown before on attention level?
	bra		check_gas_needs_mesg		; YES - do not show the gas needs custom view again
	btfsc	custom_view_locked			; NO  - custom view locked?
	bra		check_gas_needs_mesg		;       YES - do not show it now
	bsf		shown_gas_needs_attn		;       NO  - set custom view as shown now
	;bra	check_gas_needs_cv			;           - show gas needs custom view

check_gas_needs_cv:
	movlw	index_gas_needs_ascent		; get  custom view number of gas needs
	call	dive_customview_show		; show custom view
	;bra	check_gas_needs_mesg		; show message

check_gas_needs_mesg:
	incf	message_counter,F			; increase message counter
	goto	TFT_message_gas_needs		; show message for gas needs and return


 IFDEF _external_sensor

;-----------------------------------------------------------------------------
; Check external Sensors for Loss and Divergence
;
check_ext_sensors:
	btfsc	warn_det_sensors_lost		; all sensors lost?
	bra		check_ext_sensors_lost_all	; YES - show a warning and return

	btfsc	attn_det_sensor1_lost		; sensor 1 lost?
	rcall	check_ext_sensors_lost_1	; YES - show an attention

	btfsc	attn_det_sensor2_lost		; sensor 2 lost?
	rcall	check_ext_sensors_lost_2	; YES - show an attention

	btfsc	attn_det_sensor3_lost		; sensor 3 lost?
	rcall	check_ext_sensors_lost_3	; YES - show an attention

	btfsc	warn_det_sensors_div		; sensor values divergence?
	bra		check_ext_sensors_diverg	; YES - show a warning and return

	return								; done

check_ext_sensors_lost_all:
	btfsc	shown_sensors_lost			; has the custom view been shown before?
	bra		warn_sensors_lost_mesg		; YES - do not show the sensor custom view again
	btfsc	custom_view_locked			; NO  - custom view locked?
	bra		warn_sensors_lost_mesg		;       YES - do not show it now
	bsf		shown_sensors_lost			;       NO  - set it as shown now
	movlw	index_ppo2_sensors			;           - get  custom view number of sensors
	call	dive_customview_show		;           - show custom view
	;bra	warn_sensors_lost_mesg		;           - show message

warn_sensors_lost_mesg:
	incf	message_counter,F			; increase message counter
	goto	TFT_message_fallback		; show message and return

check_ext_sensors_lost_1:
	btfsc	shown_sensor1_fail			; has the custom view been shown before for sensor 1?
	return								; YES - do not show the sensor custom view again
	btfsc	custom_view_locked			; NO  - custom view locked?
	return								;       YES - do not show it now
	bsf		shown_sensor1_fail			;       NO  - set it as shown now
	bra		check_ext_sensors_show_cv	;           - show sensor custom view

check_ext_sensors_lost_2:
	btfsc	shown_sensor2_fail			; has the custom view been shown before for sensor 2?
	return								; YES - do not show the sensor custom view again
	btfsc	custom_view_locked			; NO  - custom view locked?
	return								;       YES - do not show it now
	bsf		shown_sensor2_fail			;       NO  - set it as shown now
	bra		check_ext_sensors_show_cv	;           - show sensor custom view

check_ext_sensors_lost_3:
	btfsc	shown_sensor3_fail			; has the custom view been shown before for sensor 3?
	return								; YES - do not show the sensor custom view again
	btfsc	custom_view_locked			; NO  - custom view locked?
	return								;       YES - do not show it now
	bsf		shown_sensor3_fail			;       NO  - set it as shown now
	;bra	check_ext_sensors_show_cv	;           - show sensor custom view

check_ext_sensors_show_cv:
	movlw	index_ppo2_sensors			; get  custom view number of sensors
	goto	dive_customview_show		; show custom view and return

check_ext_sensors_diverg:
	btfsc	shown_sensors_diverg			; has the custom view been shown before for divergence?
	bra		check_ext_sensors_diverg_mesg	; YES - do not show the sensor custom view again
	btfsc	custom_view_locked				; NO  - custom view locked?
	bra		check_ext_sensors_diverg_mesg	;       YES - do not show it now
	bsf		shown_sensors_diverg			;       NO  - set it as shown now
	movlw	index_ppo2_sensors				;           - get  custom view number of sensors
	call	dive_customview_show			;           - show custom view
	;bra	check_ext_sensors_diverg_mesg	;           - show message

check_ext_sensors_diverg_mesg:
	incf	message_counter,F			; increase message counter
	goto	TFT_message_divergence		; show message and return

 ENDIF	; _external_sensor


;=============================================================================
dmode5	CODE
;=============================================================================


;-----------------------------------------------------------------------------
; Restart the Deco Engine
;
	global	restart_deco_engine
	global	restart_deco_engine_wo_ceiling
restart_deco_engine:
	banksel	int_O_ceiling								; switch to bank where the shared "_O_" variables are stored
	bsf		int_O_ceiling+1,char_invalid_flag			; invalidate ceiling (int_O_ceiling has its invalid flag on a char's position!)

restart_deco_engine_wo_ceiling:
	banksel	char_O_deco_gas								; switch to bank where the stops table is stored
	bsf		char_O_deco_gas+0,char_invalid_flag			; invalidate deco data (stop table data)
	banksel	int_O_NDL_norm								; switch to bank where the shared "_O_" variables are stored
	bsf		int_O_NDL_norm+1,int_invalid_flag			; invalidate NDL time (normal plan)
	bsf		int_O_TTS_norm+1,int_invalid_flag			; invalidate TTS time (normal plan)
	bsf		int_O_TST_norm+1,int_invalid_flag			; invalidate TST time (normal plan)
	bsf		int_O_CNS_norm+1,int_invalid_flag			; invalidate CNS at end of dive in normal plan

restart_deco_engine_wo_norm:
	banksel	common										; bank to bank common
	bsf		request_restart_engine						; request restart of the deco engine

inval_alternative_plan_data:
	banksel	int_O_NDL_alt								; switch to bank where the shared "_O_" variables are stored
	bsf		int_O_NDL_alt+1,int_invalid_flag			; invalidate NDL time (alternative plan)
	bsf		int_O_TTS_alt+1,int_invalid_flag			; invalidate TTS time (alternative plan)
	bsf		int_O_TST_alt+1,int_invalid_flag			; invalidate TST time (alternative plan)
	bsf		int_O_CNS_alt+1,int_invalid_flag			; invalidate CNS at end of dive in alternative plan
	bsf		int_O_gas_need_pres+1,int_invalid_flag		; invalidate ascent gas needs

 IFDEF _rx_functions
	bsf		int_O_pressure_need+1,int_not_avail_flag	; invalidate pressure needs to reading 1 (TR functions)
	bsf		int_O_pressure_need+3,int_not_avail_flag	; invalidate pressure needs to reading 2 (TR functions)
 ENDIF

	banksel	common										; bank to bank common
	bsf		new_deco_data_avail							; set flag for new NDL and deco data available to have the display updated

	return												; done


;=============================================================================
dmode6	CODE
;=============================================================================


;-----------------------------------------------------------------------------
; Start-up Simulator Mode
;
	global	demo_divemode
demo_divemode:
	call	TFT_ClearScreen					; blank screen

	; leaving menu mode, so have option values in EEPROM up-to-date
	btfsc	option_changed					; do the options need to be stored to EEPROM ?
	call	option_check_and_store_all		; YES - check and store all option values in EEPROM

	; +++ COMMENT OUT FOR TESTING PURPOSE ONLY  !!! +++
	bsf		simulatormode					; restore tissue pressures and CNS value after finishing simulator use
	; +++ DO NOT COMMENT OUT IN OPERATIONAL USE !!! +++

	call	deco_push_tissues_to_vault		; back-up the tissue pressures (C-code)
	banksel	common							; back to bank common

	; set simulated target depth
	movff	char_I_bottom_depth,simulatormode_depth

	; set initial simulated depth (needed to overcome end-of-dive detection)
	banksel	pressure_rel_sim
	MOVLI	simulator_startdepth,pressure_rel_sim
	banksel	common

	; switch ISR pressure calculations to simulator mode
	bcf		quit_simulatormode				; clear flag for fast abort request
	bcf		sensor_override_active			; make sure ISR mode switch confirmation is not older than from now on
	bsf		sensor_override_request			; request ISR to switch to simulator mode
	btfss	sensor_override_active			; has the ISR confirmed switch to simulator mode?
	bra		$-2								; NO - not yet, loop waiting for the ISR to kick in

	; branch into dive mode
	bsf		divemode						; activate  dive mode (to be done after simulator mode is activated)
	goto	diveloop						; start dive mode

;-----------------------------------------------------------------------------

	END