Mercurial > public > hwos_code
diff src/divemode.asm @ 0:11d4fc797f74
init
author | heinrichsweikamp |
---|---|
date | Wed, 24 Apr 2013 19:22:45 +0200 |
parents | |
children | e402813343b6 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/divemode.asm Wed Apr 24 19:22:45 2013 +0200 @@ -0,0 +1,1385 @@ +;============================================================================= +; +; File divemode.asm +; +; Divemode +; +; Copyright (c) 2011, JD Gascuel, HeinrichsWeikamp, all right reserved. +;============================================================================= +; HISTORY +; 2011-08-15 : [mH] moving from OSTC code + +#include "ostc3.inc" ; Mandatory header +#include "shared_definitions.h" ; Mailbox from/to p2_deco.c +#include "tft_outputs.inc" +#include "strings.inc" +#include "tft.inc" +#include "eeprom_rs232.inc" +#include "isr.inc" +#include "math.inc" +#include "wait.inc" +#include "customview.inc" +#include "start.inc" +#include "adc_lightsensor.inc" +#include "ghostwriter.inc" +#include "i2c.inc" + +gui CODE + + global diveloop +diveloop: + banksel common + call speed_normal + call diveloop_boot ; Boot tasks for all modes + +; Startup Tasks for all modes + call TFT_ClearScreen ; clean up TFT + call TFT_divemode_mask ; Display mask + call TFT_temp_divemode ; Displays temperature + + btfsc FLAG_apnoe_mode + bsf realdive ; Set Realdive flag in Apnoe mode + + btfsc FLAG_apnoe_mode ; Done for Apnoe or Gauge mode + bra diveloop_loop + btfsc FLAG_gauge_mode ; Done for Apnoe or Gauge mode + bra diveloop_loop + + call TFT_active_gas_divemode ; Display gas/Setpoint + call TFT_display_ndl_mask ; display "NDL" + + ; +@5 init + setf WREG ; WAIT marker: display "---" + movff WREG,int_O_extra_ascenttime+0 + movff WREG,int_O_extra_ascenttime+1 + movlw 1 + movwf apnoe_mins ; Start compute after next cycle. + +;-------------------------------------------------------------------------------------------------------- +diveloop_loop: ; The diveloop starts here + btfss onesecupdate + bra diveloop_loop3 + +; tasks any new second... + btfsc FLAG_apnoe_mode ; Only in apnoe mode + bra diveloop_loop1b ; One Second Tasks in Apnoe mode + + call TFT_divemins ; Display (new) divetime! + call customview_second ; Do every-second tasks for the custom view area + +; Tasks only for deco modes + call calc_deko_divemode ; calculate decompression and display result (any two seconds) + bra diveloop_loop1x ; Common Tasks + +diveloop_loop1b: +; Tasks only for Apnoe mode + call divemode_apnoe_tasks ; 1 sec. Apnoe tasks + bra diveloop_loop1x ; Common Tasks + +diveloop_loop1x: +; Common 1sec. tasks for all modes + call timeout_divemode ; dive finished? This routine sets the required flags + call set_dive_modes ; tests if depth>threshold + call set_min_temp ; store min. temp if required + + btfsc store_sample ; store new sample? + call store_dive_data ; Store profile data + + btfss divemode ; Dive finished? + goto ghostwriter_end_dive ; Dive finished! + + btfsc divemode_gaschange ; Gas switch flag set? + rcall gas_switched_common ; Yes + + btfsc toggle_gf ; =1: Toggle GF/aGF + rcall divemodemode_togglegf ; Toggle aGF/GF + +; btfsc FLAG_ccr_mode ; In CCR mode +; call TFT_active_gas_divemode ; Update Setpoint every second + + bcf onesecupdate ; one seconds update done + +diveloop_loop3: + rcall test_switches_divemode ; Check switches in divemode + + global diveloop_loop4 +diveloop_loop4: ; Menu-Exit returns here... + btfsc toggle_customview ; Next view? + call customview_toggle ; Yes, show next customview (and delete this flag) + + btfsc pressure_refresh ; new pressure available? + rcall update_temp_and_or_depth ; Yes, display new depth and clear "pressure_refresh" flag + + btfsc oneminupdate ; one minute tasks + rcall update_divemode60 ; Update clock, etc. + + btfss quarter_second_update + bra diveloop_loop4a + bcf quarter_second_update + movlw .6 + cpfseq menupos3 ; in compass view? + bra diveloop_loop4a ; No + call TFT_dive_compass_heading ; Yes, update compass heading value +diveloop_loop4a: + btfsc enable_screen_dumps ; =1: Ignore vin_usb, wait for "l" command (Screen dump) + bra diveloop_loop5 + bra diveloop_loop6 +diveloop_loop5: + btfss vusb_in ; USB (still) plugged in? + bcf enable_screen_dumps ; No, clear flag + call rs232_get_byte + btfsc rs232_recieve_overflow + bra diveloop_loop6 + movlw "l" + cpfseq RCREG1 + bra diveloop_loop6 + call TFT_dump_screen ; Dump the screen contents +diveloop_loop6: + + bra diveloop_loop ; Loop the divemode +;-------------------------------------------------------------------------------------------------------- + + + + + + +divemode_apnoe_tasks: ; 1 sec. Apnoe tasks + call TFT_display_apnoe_descent ; Show descent timer + call TFT_max_pressure ; use normal max. depth + + btfsc divemode2 ; Time running? + bra divemode_apnoe_tasks2 ; New descent, reset data if flag is set + + rcall apnoe_calc_maxdepth + call TFT_display_apnoe_surface + call TFT_display_apnoe_last_max ; Show last max. depth + incf apnoe_surface_secs,F + movlw d'60' + cpfseq apnoe_surface_secs + bra divemode_apnoe_tasks1 + clrf apnoe_surface_secs + incf apnoe_surface_mins,F + +divemode_apnoe_tasks1: + bcf FLAG_active_descent ; Clear flag + btfsc divemode2 ; Time running? + return ; Yes, return + bsf FLAG_active_descent ; Set Flag + return + +divemode_apnoe_tasks2: + btfss FLAG_active_descent ; Are we descending? + return ; No, We are at the surface + rcall apnoe_calc_maxdepth ; Yes! + call TFT_apnoe_clear_surface ; Clear Surface timer + clrf apnoe_timeout_counter ; Delete timeout + clrf apnoe_surface_secs + clrf apnoe_surface_mins + clrf apnoe_secs + clrf apnoe_mins ; Reset Descent time + movlw .0 + movff WREG,max_pressure+0 + movff WREG,max_pressure+1 ; Reset Max. Depth + bcf FLAG_active_descent ; Clear flag + return + + global apnoe_calc_maxdepth +apnoe_calc_maxdepth: + movff apnoe_max_pressure+0,sub_a+0 + movff apnoe_max_pressure+1,sub_a+1 + movff max_pressure+0,sub_b+0 + movff max_pressure+1,sub_b+1 + call subU16 ; sub_c = sub_a - sub_b + ; apnoe_max_pressure<max_pressure -> neg_flag=1 + ; max_pressure<=apnoe_max_pressure -> neg_flag=0 + btfss neg_flag + return + ;apnoe_max_pressure<max_pressure + movff max_pressure+0,apnoe_max_pressure+0 + movff max_pressure+1,apnoe_max_pressure+1 + return + + +calc_deko_divemode: + btfsc twosecupdate ; two seconds after the last call + bra calc_deko_divemode2 ; Yes, calculate and display deco data ("first second") + + bsf twosecupdate ; No, but next second! + ; Routines used in the "other second" + call calc_average_depth ; calculate average depth + call calc_velocity ; calculate vertical velocity and display if > threshold (every two seconds) + call divemode_check_for_warnings ; Check for any warnings + call TFT_debug_output + + btfsc FLAG_apnoe_mode ; Done for Apnoe or Gauge mode + return + btfsc FLAG_gauge_mode ; Done for Apnoe or Gauge mode + return + +; Calculate CNS + rcall set_actual_ppo2 ; Set char_I_actual_ppO2 + clrf WREG + movff WREG,char_I_step_is_1min ; Make sure to be in 2sec mode. + call deco_calc_CNS_fraction ; calculate CNS + movlb b'00000001' ; rambank 1 selected + +; Check for a gas change + rcall check_gas_change ; Checks if a better gas should be selected (by user) + + return + + global set_actual_ppo2 +set_actual_ppo2: ; calculate ppO2 in 0.01bar (e.g. 150 = 1.50 bar ppO2) + SAFE_2BYTE_COPY amb_pressure, xA ; P_amb in millibar (1000 = 1.00 bar). + movlw d'10' + movwf xB+0 + clrf xB+1 + call div16x16 ; xC=p_amb/10 (100 = 1.00 bar). + movff xC+0,xA+0 + movff xC+1,xA+1 + movff char_I_O2_ratio,xB+0 + clrf xB+1 + call mult16x16 ; char_I_O2_ratio * (p_amb/10) + movff xC+0,xA+0 + movff xC+1,xA+1 + movlw d'100' + movwf xB+0 + clrf xB+1 + call div16x16 ; xC=(char_I_O2_ratio * p_amb/10)/100 + +; Copy ppO2 for CNS calculation + tstfsz xC+1 ; Is ppO2 > 2.55bar ? + setf xC+0 ; yes: bound to 2.55... better than wrap around. + + movff xC+0, char_I_actual_ppO2 ; copy last ppO2 to buffer register + btfsc is_bailout ; In Bailout? + return ; Yes, done. + ; No Bailout, check for ccr mode + btfsc FLAG_ccr_mode ; If FLAG_ccr_mode=1... + movff char_I_const_ppO2, char_I_actual_ppO2 ; ...copy last ppO2 to buffer register + return + + +calc_deko_divemode2: + bcf twosecupdate + + btfsc FLAG_apnoe_mode ; Done for Apnoe or Gauge mode + return + btfsc FLAG_gauge_mode ; Done for Apnoe or Gauge mode + return + + extern deco_setup_dive + call deco_setup_dive ; Pass all parameters to the C code + + TSTOSS opt_ccr_mode ; =0: Fixed SP, =1: Sensor + bra calc_deko_divemode2a + rcall divemode_setup_sensor_values ; Setup sensor values + +calc_deko_divemode2a: + SAFE_2BYTE_COPY amb_pressure,int_I_pres_respiration ; C-code needs the ambient pressure + clrf WREG + movff WREG,char_I_step_is_1min ; Force 2 second deco mode + + clrf TMR5L + clrf TMR5H ; 30,51757813µs/bit in TMR5L:TMR5H + call deco_calc_hauptroutine ; calc_tissue + movlb .1 + + movff char_O_deco_status,WREG ; Is a compute cycle finished ? + iorwf WREG,F + btfss STATUS,Z + return ; Return is status <> 0 + + ; Check if deco stops are necessary ? + movff char_O_first_deco_depth,wait_temp ; copy ceiling to temp register + tstfsz wait_temp ; Ceiling<0m? + bra calc_deko_divemode3 ; Yes! + + btfsc decostop_active ; Already in nodeco mode ? + call TFT_display_ndl_mask ; No, Clear deco data, display nostop time + bcf decostop_active ; clear flag (again) + + ; Copy for profile recording + clrf decodata+0 + movff char_O_nullzeit,decodata+1 ; NDL + + call TFT_display_ndl ; display no deco limit + return + +calc_deko_divemode3: + btfss decostop_active ; Already in deco mode ? + call TFT_display_deko_mask ; No, clear nostop time, display decodata + bsf decostop_active ; Set flag (again) + + ; Copy for profile recording + movff char_O_first_deco_depth,decodata+0 ; ceiling + movff char_O_first_deco_time,decodata+1 ; length of first stop in minues + call TFT_display_deko ; display decodata + call TFT_show_TTS_divemode ; display TTS + + movff char_I_extra_time,WREG + tstfsz WREG ; extra time = 0? + bra calc_deko_divemode4 ; No, compute it + return + +calc_deko_divemode4: + ; Check if extra cycles are needed to compute @5 variant: + decfsz apnoe_mins,F ; Reached count-down ? + return ; No: don't compute yet. + + movlw .6 + movff WREG,char_O_deco_status ; Stole next cycles for @5 variant. + + movlw .2 ; Restart countdown. + movwf apnoe_mins + return ; done. + +;----------------------------------------------------------------------------- + +divemodemode_togglegf: ; Toggle aGF/GF + bcf toggle_gf ; clear flag + btg use_agf ; Toggle GF + call TFT_gf_mask ; Setup Mask + clrf WREG + movff WREG,char_O_deco_status ; Restart decoplan computation + return + +divemode_setup_sensor_values: + ; sum up sensor values (in xA:2) and active sensors in (xB:2) + clrf xB+0 + clrf xB+1 + clrf xA+0 + clrf xA+1 + btfss hud_status_byte,3 ; Sensor1 active? + bra divemode_setup_sensor_values2 ; No + movf o2_ppo2_sensor1,W + addwf xA+0 + movlw .0 + addwfc xA+1 ; Add into xA:2 + incf xB+0,F ; Add a sensor +divemode_setup_sensor_values2: + btfss hud_status_byte,4 ; Sensor2 active? + bra divemode_setup_sensor_values3 ; No + movf o2_ppo2_sensor2,W + addwf xA+0 + movlw .0 + addwfc xA+1 ; Add into xA:2 + incf xB+0,F ; Add a sensor +divemode_setup_sensor_values3: + btfss hud_status_byte,5 ; Sensor3 active? + bra divemode_setup_sensor_values4 ; No + movf o2_ppo2_sensor3,W + addwf xA+0 + movlw .0 + addwfc xA+1 ; Add into xA:2 + incf xB+0,F ; Add a sensor +divemode_setup_sensor_values4: + call div16x16 ; xA/xB=xC with xA+0 as remainder + movff xC+0,sensor_setpoint ; Copy result + movff sensor_setpoint,char_I_const_ppO2 ; use sensor ppO2 + return + +calc_velocity: ; called every two seconds + btfss divemode + bra do_not_display_velocity ; display velocity only in divemode (Not at the surface after dive) + +calc_velocity2: + SAFE_2BYTE_COPY amb_pressure, sub_a + movff last_pressure_velocity+0,sub_b+0 + movff last_pressure_velocity+1,sub_b+1 + movff sub_a+0,last_pressure_velocity+0 ; store old value for velocity + movff sub_a+1,last_pressure_velocity+1 + + call subU16 ; sub_c = amb_pressure - last_pressure + + movff sub_c+0,xA+0 + movff sub_c+1,xA+1 + movlw d'39' ; 77 when called every second.... + movwf xB+0 + clrf xB+1 + call mult16x16 ; differential pressure in mbar*77... + movff xC+0,divA+0 + movff xC+1,divA+1 + movlw d'7' + movwf divB+0 + call div16 ; devided by 2^7 equals velocity in m/min + + movlw d'99' + cpfsgt divA+0 ; limit to 99m/min + bra calc_velocity3 + movwf divA+0 ; divA=99 + +calc_velocity3: + movlw velocity_warning_level_1 ; lowest threshold for display vertical velocity + subwf divA+0,W ; + btfss STATUS,C + bra do_not_display_velocity + + bsf display_velocity + call TFT_display_velocity ; With divA+0 = m/min... + return + +do_not_display_velocity: + btfss display_velocity ; Velocity was not displayed, do not delete + return + bcf display_velocity ; Velocity was displayed, delete velocity now + call TFT_display_velocity_clear + return + +;============================================================================= + +timeout_menuview: + decfsz timeout_counter3,F ; timeout for menuview + return ; No timeout, return + ; Timeout, clear e.g. "Menu?" + goto menuview_toggle_reset ; "returns" + +timeout_divemode_menu: + decfsz timeout_counter3,F ; timeout for divemode menu + return + + global timeout_divemode_menu2 +timeout_divemode_menu2: ; Called from divemenu_tree.asm + bcf divemode_menu ; Timeout! Clear flag + call TFT_clear_divemode_menu ; Clear menu + call TFT_active_gas_divemode ; Redraw gas/setpoint/diluent + bcf blinking_better_gas ; Clear flag to have temperature updated once + call TFT_temp_divemode ; Displays temperature + + btfss decostop_active ; In deco mode ? + bra timeout_divemode_menu_ndl ; No, show NDL again + ; Show deco + call TFT_display_deko_mask ; clear nostop time, display decodata + call TFT_display_deko + call TFT_show_TTS_divemode + return +timeout_divemode_menu_ndl: ; Show NDL + call TFT_display_ndl_mask ; Clear deco data, display nostop time + call TFT_display_ndl + return + +timeout_divemode: + btfsc divemode_menu ; Divemode menu active? + rcall timeout_divemode_menu ; Yes, check the timeout for it... + + btfsc menuview ; is a menuview shown? + rcall timeout_menuview ; Yes, check the timeout for it... + + btfss realdive ; Dive longer then one minute + return + + btfsc FLAG_apnoe_mode ; In Apnoe mode? + bra timeout_divemode2 ; Yes, use CF30 [min] for timeout + + ifndef __DEBUG + btfsc simulatormode_active ; In Simulator mode? + bra timeout_divemode3 ; Yes, use simulator timeout + endif + + bcf divemode + incf timeout_counter,F + movlw d'0' + addwfc timeout_counter2,F ; timeout is 15bits + + movlw LOW divemode_timeout + movwf sub_a+0 + movlw HIGH divemode_timeout + movwf sub_a+1 + + movff timeout_counter, sub_b+0 + movff timeout_counter2, sub_b+1 + call subU16 ; sub_c = sub_a - sub_b + btfss neg_flag ; Result negative? + bsf divemode ; No, set flag + return + +timeout_divemode2: + incf timeout_counter,F ; seconds... + movlw d'60' + cpfseq timeout_counter ; timeout_counter=60? + return ; No. +; One minute timeout done. + clrf timeout_counter + bcf divemode + incf apnoe_timeout_counter,F + movlw apnoe_timeout ; apnoe timeout [min] + cpfseq apnoe_timeout_counter + bsf divemode + return + +timeout_divemode3: + bcf divemode + incf timeout_counter,F + movlw simulator_timeout ; simulator timeout + cpfsgt timeout_counter + bsf divemode + return + +update_temp_and_or_depth: ; New sensor data arrived... + btfsc temp_changed + call TFT_temp_divemode ; Displays temperature + + btfsc pressure_refresh + call TFT_depth ; Displays new depth + + rcall set_max_depth ; update max. depth if required + bcf pressure_refresh ; until new pressure is available + return + +update_divemode60: ; update any minute + call get_battery_voltage ; gets battery voltage + call set_powersafe ; Battery low? + call TFT_max_pressure ; Update max. depth + call customview_minute ; Do every-minute tasks for the custom view area + bcf oneminupdate + + btfss simulatormode_active ; in simulator mode? + return ; No + ; Yes, quite dive mode simulation after 21*256s=89min:36s + movlw .20 + cpfsgt total_divetime_seconds+1 ; Timeout? + return ; No + ifdef __DEBUG + return ; No simulator timeout in debug mode + endif + bra divemode_option1 ; Yes, set to 0m and "return" + +set_max_depth: + movff max_pressure+0,sub_a+0 + movff max_pressure+1,sub_a+1 + SAFE_2BYTE_COPY rel_pressure, sub_b + call subU16 ; sub_c = sub_a - sub_b + ; max_pressure<rel_pressure -> neg_flag=1 + ; rel_pressure<=max_pressure -> neg_flag=0 + btfss neg_flag + return + ; max_pressure<rel_pressure + movff sub_b+0,max_pressure+0 + movff sub_b+1,max_pressure+1 + call TFT_max_pressure ; No, use normal max. depth + return + +set_min_temp: + movff minimum_temperature+0,sub_a+0 + movff minimum_temperature+1,sub_a+1 + SAFE_2BYTE_COPY temperature,sub_b + call sub16 ; sub_c = sub_a - sub_b + ; minimum_temperature<T -> neg_flag=1 + ; T<=minimum_temperature -> neg_flag=0 + btfsc neg_flag + return + ; minimum_temperature>=T + movff sub_b+0,minimum_temperature+0 + movff sub_b+1,minimum_temperature+1 + return + + global set_dive_modes +set_dive_modes: + btfsc high_altitude_mode ; In high altitude (Fly) mode? + bra set_dive_modes3 ; Yes! + +set_dive_modes0: + movlw LOW start_dive_threshold + movwf sub_a+0 ; dive_treshold is in cm + movlw HIGH start_dive_threshold + movwf sub_a+1 ; dive_treshold is in cm + +set_dive_modes1: + SAFE_2BYTE_COPY rel_pressure, sub_b + call subU16 ; sub_c = sub_a - sub_b + + btfss neg_flag + bra set_dive_modes2 ; too shallow (rel_pressure<dive_threshold) + + btfsc realdive ; Dive longer than one minute? + clrf timeout_counter ; Yes, reset timout counter + +set_dive_modes_common: + bsf divemode ; (Re-)Set divemode flag + bsf divemode2 ; displayed divetime is running + return + +set_dive_modes2: + bcf divemode2 ; Stop time + btfss realdive ; dive longer then one minute? + bcf divemode ; no -> this was no real dive + return ; No, return + + +set_dive_modes3: ; High-altitude mode + btfsc realdive ; dive longer then one minute? + bra set_dive_modes0 ; Yes -> this is a real dive -> Use start_dive_threshold or ascend + + movlw HIGH high_altitude_dive_threshold + movwf sub_a+1 + movlw LOW high_altitude_dive_threshold + movwf sub_a+0 + bra set_dive_modes1 + +set_powersafe: + movlw color_code_battery_low+1; [%] + cpfslt batt_percent + return + + movlw d'7' ; Type of Alarm (Battery Low) + movwf AlarmType ; Copy to Alarm Register + bsf event_occured ; Set Event Flag + movlw .0 + movff WREG,opt_brightness ; Set Brightness to ECO + return ; return + +calc_average_depth: + btfsc reset_average_depth ; Reset the Avewrage depth? + rcall reset_average1 ; Reset the resettable average depth + + ; 1. Add new 2xdepth to the Sum of depths registers + SAFE_2BYTE_COPY rel_pressure, xB ; Buffer... + bcf STATUS,C + rlcf xB+0,F + rlcf xB+1,F ; x2 + + movf xB+0,w + addwf average_depth_hold+0,F + movf xB+1,w + addwfc average_depth_hold+1,F + movlw d'0' + addwfc average_depth_hold+2,F + addwfc average_depth_hold+3,F ; Will work up to 9999mbar*60*60*24=863913600mbar + +; Do the same for the _total registers (Non-Resettable) + movf xB+0,w + addwf average_depth_hold_total+0,F + movf xB+1,w + addwfc average_depth_hold_total+1,F + movlw d'0' + addwfc average_depth_hold_total+2,F + addwfc average_depth_hold_total+3,F ; Will work up to 9999mbar*60*60*24=863913600mbar + + ; 2. Compute Average Depth on base of average_divesecs:2 + movff average_divesecs+0,xB+0 + movff average_divesecs+1,xB+1 ; Copy + movff average_depth_hold+0,xC+0 + movff average_depth_hold+1,xC+1 + movff average_depth_hold+2,xC+2 + movff average_depth_hold+3,xC+3 + + call div32x16 ; xC:4 / xB:2 = xC+3:xC+2 with xC+1:xC+0 as remainder + movff xC+0,avr_rel_pressure+0 + movff xC+1,avr_rel_pressure+1 + + ; 3. Compute Total Average Depth on base of total_divetime_seconds:2 + movff total_divetime_seconds+0,xB+0 + movff total_divetime_seconds+1,xB+1 ; Copy + movff average_depth_hold_total+0,xC+0 + movff average_depth_hold_total+1,xC+1 + movff average_depth_hold_total+2,xC+2 + movff average_depth_hold_total+3,xC+3 + call div32x16 ; xC:4 / xB:2 = xC+3:xC+2 with xC+1:xC+0 as remainder + movff xC+0,avr_rel_pressure_total+0 + movff xC+1,avr_rel_pressure_total+1 + +; ; Compute Total Average Depth on base of divemins:2 and divesecs +; movff divemins+0,xA+0 +; movff divemins+1,xA+1 +; movlw d'60' +; movwf xB+0 +; clrf xB+1 +; call mult16x16 ; xC:4=xA:2*xB:2 +; movf divesecs,W +; addwf xC+0,F +; movlw d'0' +; addwfc xC+1,F ; xC:2 holds total dive seconds +; movlw d'3' ; 2+1 +; btfss divesecs,0 ; divesecs even? +; movlw d'2' ; Yes, do not add +1 +; addwf xC+0,F +; movlw d'0' +; addwfc xC+1,F +; ; Ignore xC+2 and xC+3. Total Average will only work up to divetime=1092:16 +; movff xC+0,xB+0 +; movff xC+1,xB+1 ; Copy +; movff average_depth_hold_total+0,xC+0 +; movff average_depth_hold_total+1,xC+1 +; movff average_depth_hold_total+2,xC+2 +; movff average_depth_hold_total+3,xC+3 +; +; call div32x16 ; xC:4 / xB:2 = xC+3:xC+2 with xC+1:xC+0 as remainder +; movff xC+0,avr_rel_pressure_total+0 +; movff xC+1,avr_rel_pressure_total+1 + + return + +reset_average1: + clrf average_depth_hold+0 + clrf average_depth_hold+1 + clrf average_depth_hold+2 + clrf average_depth_hold+3 ; Clear average depth register + movlw d'2' + movwf average_divesecs+0 + clrf average_divesecs+1 + bcf reset_average_depth ; Clear flag + return + +test_switches_divemode: ; checks switches in divemode + btfsc divemode_menu ; Divemode menu shown? + bra test_switches_divemode_menu ; Yes, use menu processor + btfsc switch_left + bra test_switches_divemode2 ; Enter button pressed, check if we need to do something + btfss switch_right + return ; No button press + tstfsz menupos2 ; any option shown? + bra test_switches_divemode1 ; Yes, do option tasks + bsf toggle_customview ; No, toggle custom view + return + +test_switches_divemode_menu: + btfsc switch_left + bra test_switches_divemode_menu2 ; Move cursor + btfsc switch_right + bra test_switches_divemode_menu3 ; Enter submenu or do something + return ; No button press + +test_switches_divemode_menu1: + clrf menupos +test_switches_divemode_menu2: + incf menupos,F + incf menupos4,W ; menupos4+1 -> WREG + cpfslt menupos ; >menupos4 (Set in menu_processor.asm)? + bra test_switches_divemode_menu1; > Yes, set to 1 + call TFT_divemode_menu_cursor ; Update the cursor + bcf switch_left + movlw divemode_menu_timeout ; Reload timeout + movwf timeout_counter3 ; timeout for divemode menu + return + +test_switches_divemode_menu3: ; Enter submenu or do something + bcf switch_right +; decf menupos,F ; menu_processor needs 0-5... + extern do_line_menu + goto do_line_menu ; Warning! Trashes STKPTR and returns to diveloop_loop4: + +test_switches_divemode1: + bcf switch_right + movlw divemode_menuview_timeout + movwf timeout_counter3 ; Reload timeout + movff menupos2,WREG ; Menupos3 holds number of customview/divemode menu function + dcfsnz WREG,F + bra divemode_option0 ; Start/Setup Divemode menu + dcfsnz WREG,F + bra divemode_option1 ; Quit Simulation? + dcfsnz WREG,F + bra divemode_option2 ; Descent 1m + dcfsnz WREG,F + bra divemode_option3 ; Ascend 1m + dcfsnz WREG,F + bra divemode_option4 ; Quit Apnoe mode + dcfsnz WREG,F + bra divemode_option5 ; Reset Stopwatch (In Gauge mode) + return + +test_switches_divemode2: + bcf switch_left + call menuview_toggle ; Menu or Simulator tasks + return + +gas_switched_common: + decf menupos,W ; 1-5 -> 0-4 + btfss FLAG_ccr_mode ; Choose OC Gases + rcall setup_gas_registers ; With WREG=Gas 0-4 + btfsc FLAG_ccr_mode ; Choose CC Diluents + rcall setup_dil_registers ; With WREG=Gas 0-4 + + decf menupos,W ; 1-5 -> 0-4 + btfsc is_bailout ; Choose OC Bailouts (OC Gases) + rcall setup_gas_registers ; With WREG=Gas 0-4 + + call TFT_active_gas_divemode ; Display gas/Setpoint + bsf event_occured ; Set global event byte + bsf stored_gas_changed ; Set Flag for profile + bcf divemode_gaschange ; Clear flag + clrf WREG + movff WREG,char_O_deco_status ; Restart decoplan computation + return + + global setup_gas_registers +setup_gas_registers: ; With WREG=Gas 0-4 + lfsr FSR1,opt_gas_O2_ratio+0 + movff PLUSW1,char_I_O2_ratio ; O2 (For ppO2 calculations) + lfsr FSR1,opt_gas_He_ratio+0 + movff PLUSW1,char_I_He_ratio ; He + incf WREG,W ; Gas# 1-5 + movff WREG,char_I_current_gas ; Set gas + movff WREG,active_gas ; Set for logbook and display + banksel char_I_O2_ratio + movf char_I_O2_ratio,W ; Add O2... + addwf char_I_He_ratio,W ; ...and He... + sublw .100 ; ...subtract both from 100 + movwf char_I_N2_ratio ; -> N2! + banksel common + return + + global setup_dil_registers +setup_dil_registers: ; With WREG=dil 0-4 + lfsr FSR1,opt_dil_O2_ratio+0 + movff PLUSW1,char_I_O2_ratio ; O2 (For ppO2 calculations) + lfsr FSR1,opt_dil_He_ratio+0 + movff PLUSW1,char_I_He_ratio ; He + incf WREG,W ; Gas# 1-5 + movff WREG,char_I_current_gas ; Set gas + movff WREG,active_gas ; Set for logbook and display + banksel char_I_O2_ratio + movf char_I_O2_ratio,W ; Add O2... + addwf char_I_He_ratio,W ; ...and He... + sublw .100 ; ...subtract both from 100 + movwf char_I_N2_ratio ; -> N2! + banksel common + return + +divemode_option0: ; Start/Setup Divemode menu + call TFT_clear_divemode_menu ; Clear menu area + bcf menuview + extern do_main_divemenu + call do_main_divemenu + global divemode_option0_return +divemode_option0_return: +; movlw .1 +; movwf menupos ; Set to first option in divemode menu + call TFT_divemode_menu_cursor; Show the cursor + movlw divemode_menu_timeout + movwf timeout_counter3 ; timeout for divemode menu + bsf divemode_menu ; Set flag + clrf menupos2 ; Clear option counter + bra diveloop_loop4 ; Goto back to diveloop (Menuprocessor trashes STKPTR!) + +divemode_option4: + movlw d'58' ; two seconds left + movwf timeout_counter + movlw apnoe_timeout-1 ; apnoe timeout [min] + movwf apnoe_timeout_counter + btfss simulatormode_active ; in simulator mode? + return ; No +divemode_option1: ; Quit simulation mode + banksel isr_backup + movlw low .1000 + movwf sim_pressure+0 + movlw high .1000 + movwf sim_pressure+1 ; Set to 0m -> End of Dive + banksel common + call menuview_toggle_reset ; Reset to zero (Zero=no menuview) + + btfss FLAG_apnoe_mode ; In Apnoe mode? + return ; No + movlw d'58' ; two seconds left + movwf timeout_counter + movlw apnoe_timeout-1 ; apnoe timeout [min] + movwf apnoe_timeout_counter + return + +divemode_option3: ; minus 1m + banksel isr_backup + movlw d'100' + subwf sim_pressure+0 + movlw .0 + subwfb sim_pressure+1 + rcall divemode_simulator_check_limits + banksel common + return + +divemode_option2: ; plus 1m + banksel isr_backup + movlw d'100' + addwf sim_pressure+0 + movlw .0 + addwfc sim_pressure+1 + rcall divemode_simulator_check_limits + banksel common + return + +divemode_option5: + call menuview_toggle_reset ; Reset to zero (Zero=no menuview) + bsf reset_average_depth ; Set Flag + return + +divemode_simulator_check_limits: + ; Check limits (150m and 0m) + movlw LOW d'16000' ; Compare to 16bar=16000mbar (150m). + subwf sim_pressure+0,W + movlw HIGH d'16000' + subwfb sim_pressure+1,W + bnc divemode_simulator_check_limits2 ; No-carry = borrow = not deeper + + ; Too deep, limit to 150m + movlw LOW d'16000' + movwf sim_pressure+0 + movlw HIGH d'16000' + movwf sim_pressure+1 + return +divemode_simulator_check_limits2: + movlw LOW d'1000' ; Compare to 1bar == 0m == 1000 mbar. + subwf sim_pressure+0,W + movlw HIGH d'1000' + subwfb sim_pressure+1,W + btfsc STATUS,C ; No-carry = borrow = not deeper. + return ; Deeper than 0m == Ok. + ; Too shallow, limit to 0m + movlw LOW d'1000' + movwf sim_pressure+0 + movlw HIGH d'1000' + movwf sim_pressure+1 + return + +;============================================================================= +; Compare all enabled gas in list, to see if a better one is available. +; +; Output: better_gas_available, better_gas_number +; +check_gas_change: ; Checks if a better gas should be selected (by user) + bcf better_gas_available ;=1: A better gas is available and a gas change is advised in divemode + clrf better_gas_number ; Clear better gas register + + SAFE_2BYTE_COPY rel_pressure,xA + movlw d'100' + movwf xB+0 + clrf xB+1 + call div16x16 ; compute depth in full m -> result in xC+0 + + btfss FLAG_ccr_mode ; In CCR mode... + bra check_gas_change_OC_bail; No, check for OC or bailout + btfsc is_bailout ; Bailout? + bra check_gas_change_OC_bail; Yes, check for OC or bailout + + ; Check Diluents + movlw .0 + rcall check_dil_common ; With Gas 0-4 in WREG + movlw .1 + rcall check_dil_common ; With Gas 0-4 in WREG + movlw .2 + rcall check_dil_common ; With Gas 0-4 in WREG + movlw .3 + rcall check_dil_common ; With Gas 0-4 in WREG + movlw .4 + rcall check_dil_common ; With Gas 0-4 in WREG + bra check_gas_change_exit + +check_gas_change_OC_bail: + movlw .0 + rcall check_gas_common ; With Gas 0-4 in WREG + movlw .1 + rcall check_gas_common ; With Gas 0-4 in WREG + movlw .2 + rcall check_gas_common ; With Gas 0-4 in WREG + movlw .3 + rcall check_gas_common ; With Gas 0-4 in WREG + movlw .4 + rcall check_gas_common ; With Gas 0-4 in WREG +; bra check_gas_change_exit +check_gas_change_exit: + btfss better_gas_available ; Is a better gas available + bcf blinking_better_gas ; No, Clear blinking flag + btfss better_gas_available ; Is a better gas available + clrf better_gas_number ; No, Clear better_gas_number (For gaslist display) + call TFT_active_gas_divemode ; Display gas/Setpoint + return + +check_gas_common: ; With Gas 0-4 in WREG + btfsc better_gas_available ; Better Gas already found? + return ; Yes, return + lfsr FSR1,opt_gas_type ; 0=Disabled, 1=First, 2=Travel, 3=Deco + btfss PLUSW1,0 ; Test for Bit0 and 1 -> type=3 -> Deco + return ; No + btfss PLUSW1,1 ; Test for Bit0 and 1 -> type=3 -> Deco + return ; No + incf WREG,W ; 1-5 + cpfseq active_gas ; is this gas currently selected? + bra check_gas_common2 ; No + return ; Yes, skip test for active gas +check_gas_common2: + decf WREG,W ; 0-4 + movwf hi ; Save tested gas 0-4 + lfsr FSR1,char_I_deco_gas_change + movff PLUSW1,lo ; Change depth into lo + movlw minimum_change_depth + cpfsgt lo ; Change depth>minimum_change_depth? + return ; No, Change depth not deep enough, skip! + movf xC+0,W ; load depth in m into WREG + cpfsgt lo ; gas_change_depth < current depth? + return ; No, check next gas + incf hi,W ; 1-5 + movwf better_gas_number ; number (1-5) of the "better gas" in divemode, =0: no better gas available + movlw better_gas_window + subwf lo,W ; Change depth-better_gas_window + cpfslt xC+0 ; current depth<Change depth-better_gas_window? + bsf better_gas_available ;=1: A better gas is available and a gas change is advised in divemode + return + +check_dil_common: ; With Dil 0-4 in WREG + btfsc better_gas_available ; Better Diluent already found? + return ; Yes, return + lfsr FSR1,opt_dil_type ; 0=Disabled, 1=First, 2=Normal + tstfsz PLUSW1 ; =0? + bra check_dil_common1 ; No + return ; Yes, skip inactive diluents for test +check_dil_common1: + incf WREG,W ; 1-5 + cpfseq active_gas ; is this diluent currently selected? + bra check_dil_common2 ; No + return ; Yes, skip test for active diluent +check_dil_common2: + decf WREG,W ; 0-4 + movwf hi ; Save tested diluent 0-4 + lfsr FSR1,char_I_dil_change + movff PLUSW1,lo ; Change depth into lo + movlw minimum_change_depth + cpfsgt lo ; Change depth>minimum_change_depth? + return ; No, Change depth not deep enough, skip! + movf xC+0,W ; load depth in m into WREG + cpfsgt lo ; gas_change_depth < current depth? + return ; No, check next gas + incf hi,W ; 1-5 + addlw .5 ; 6-10 + movwf better_gas_number ; number (1-5) of the "better gas" in divemode, =0: no better gas available + movlw better_gas_window + subwf lo,W ; Change depth-better_gas_window + cpfslt xC+0 ; current depth<Change depth-better_gas_window? + bsf better_gas_available ;=1: A better gas is available and a gas change is advised in divemode + return + +;============================================================================= +; Setup everything to enter divemode. +; + +dive_boot_oc: + extern get_first_gas_to_WREG + call get_first_gas_to_WREG ; Gets first gas (0-4) into WREG + movff WREG,char_I_first_gas ; Copy for compatibility + movff WREG,active_gas ; Set for logbook and display + rcall setup_gas_registers ; With WREG=Gas 0-4 + return + +dive_boot_cc: + rcall divemode_setup_sensor_values ; setup sensor values + TSTOSS opt_ccr_mode ; =0: Fixed SP, =1: Sensor + movff char_I_setpoint_cbar+0,char_I_const_ppO2 ; Setup fixed Setpoint (Always start with SP1) + extern get_first_dil_to_WREG + call get_first_dil_to_WREG ; Gets first gas (0-4) into WREG + movff WREG,char_I_first_gas ; Copy for compatibility + movff WREG,active_gas ; Set for logbook and display + rcall setup_dil_registers ; With WREG=Gas 0-4 + return + +diveloop_boot: + call restart_set_modes_and_flags + + call I2C_sleep_accelerometer ; Stop accelerometer + call I2C_sleep_compass ; Stop compass + + clrf WREG + movff WREG,max_pressure+0 ; clear some variables + movff WREG,max_pressure+1 + + bcf use_agf ; Start with normal GF set + bcf divemode_menu ; clear divemode menu flag + movlw d'1' + movwf apnoe_max_pressure+0 + clrf apnoe_max_pressure+1 + clrf apnoe_surface_mins + clrf apnoe_surface_secs + clrf apnoe_mins + clrf apnoe_secs + clrf divemins+0 + clrf divemins+1 + bcf no_more_divesecs ; =1: Do no longer show seconds in divemode + bcf divemode_menu_active + clrf menupos + clrf menupos3 ; Reset to zero (Zero=no custom view) + clrf menupos2 ; Reset to zero (Zero=no premenu or simulator task) + + bcf is_bailout ; =1: Bailout + btfss FLAG_ccr_mode + rcall dive_boot_oc + btfsc FLAG_ccr_mode + rcall dive_boot_cc + + bcf better_gas_available ;=1: A better gas is available and a gas change is advised in divemode + clrf better_gas_number ; Clear better gas register + + clrf samplesecs + clrf apnoe_timeout_counter ; timeout in minutes + clrf timeout_counter ; takes care of the timeout (Low byte) + clrf timeout_counter2 ; takes care of the timeout (High byte) + clrf AlarmType ; Clear all alarms + bcf event_occured ; clear flag + clrf total_divetime_seconds+1 + clrf average_depth_hold_total+0 + clrf average_depth_hold_total+1 + clrf average_depth_hold_total+2 + clrf average_depth_hold_total+3 ; Clear Non-Resettable Average + rcall reset_average1 ; Reset the resettable average depth + bcf decostop_active + bcf better_gas_available ;=1: A better gas is available and a gas change is advised in divemode + call ghostwriter_short_header ; Write short header with divenumber into profile memory + + btfsc simulatormode_active + bra diveloop_boot_1 + ; Normal mode = Surface pressure is the pressure 30mn before dive. + SAFE_2BYTE_COPY last_surfpressure_30min, int_I_pres_surface ;copy surfacepressure to deco routine + SAFE_2BYTE_COPY last_surfpressure_30min, last_surfpressure ;copy surfacepressure to last_surfpressure for correct depth + bra diveloop_boot_2 + +diveloop_boot_1: + ; Simulator mode: Surface pressure is 1bar. + movlw LOW .1000 + movff WREG,int_I_pres_surface+0 ; LOW copy surfacepressure to deco routine + movlw HIGH .1000 + movff WREG,int_I_pres_surface+1 ; HIGH copy surfacepressure to deco routine + +diveloop_boot_2: + SAFE_2BYTE_COPY temperature,minimum_temperature ; Reset Min-Temp registers + +; Init profile recording parameters + movlw samplingrate + movwf samplesecs_value ; to avoid EEPROM access in the ISR + movlw div_temperature + movwf divisor_temperature ; load divisors for profile storage + movlw div_deco + movwf divisor_deco + movlw div_gf + movwf divisor_gf + movlw div_ppo2_sensors + movwf divisor_ppo2_sensors + movlw div_decoplan + movwf divisor_decoplan + movlw div_cns + movwf divisor_cns + movlw div_tank + movwf divisor_tank + + btfss FLAG_apnoe_mode ; In Apnoe mode? + bra divemode1 +; Overwrite some parameters in Apnoe mode.... + movlw samplingrate_apnoe + movwf samplesecs_value ; to avoid EEPROM access in the ISR + +divemode1: + bcf LEDg + bcf LEDr + bcf realdive + btfss simulatormode_active ; do not disable in simulator mode! + call disable_rs232 ; Disable RS232 + btfsc enable_screen_dumps ; =1: Ignore vin_usb, wait for "l" command (Screen dump) + call enable_rs232 ; Also sets to speed_normal ... + movlw .2 + movwf total_divetime_seconds+0 + movwf divesecs ; Start at 2seconds + bsf divemode2 ; displayed divetime is running (Divetime starts HERE) + + movff int_O_CNS_fraction+0,CNS_start+0 + movff int_O_CNS_fraction+1,CNS_start+1 ; Save CNS value at beginning of dive + movff char_O_relative_gradient_GF,GF_start ; Save GF value at beginning of dive + return ; Done with divemode boot + +divemode_check_for_warnings: + btfss secs,1 ; Every four seconds + return + + movf warning_counter_backup,W + cpfseq warning_counter ; warning_counter_backup = warning_counter? + call TFT_clear_warning_text ; No, clear all warnings + movff warning_counter,warning_counter_backup ; copy warning_counter + + bcf warning_active ; Clear flag + clrf warning_counter ; Clear counter + + ; Warnings for all modes + call check_warn_battery ; Check if the battery level should be displayed/warned + + btfsc FLAG_apnoe_mode ; Done for Apnoe or Gauge mode + bra divemode_check_for_warnings2 + btfsc FLAG_gauge_mode ; Done for Apnoe or Gauge mode + bra divemode_check_for_warnings2 + + ; Warnings only in deco modes + btfss FLAG_ccr_mode ; Don't check in CCR mode + rcall check_ppO2 ; check ppO2 and displays warning, if required + btfsc is_bailout ; But check in Bailout case... + rcall check_ppO2 ; check ppO2 and displays warning, if required + rcall check_cns_violation ; Check CNS value and display it, if required + btfsc decostop_active ; In deco mode? + rcall check_and_store_gf_violation ; Yes, Sets warnings, if required + btfsc decostop_active ; In deco mode? + call TFT_ftts ; Show @+x time + btfsc use_agf ; In aGF mode? + rcall warn_agf ; Yes, show a warning for it + +divemode_check_for_warnings2: +; Display the warning icon? + btfsc warning_active ; Any warning active? + call TFT_divemode_warning ; Yes + btfss warning_active ; Any warning active? + call TFT_divemode_warning_clear ; No, clear warning icon + +; Setup warning_page number + incf warning_page,F + bcf STATUS,C + rlcf warning_page,W ; *2 + cpfsgt warning_counter ; > warning_counter + clrf warning_page ; No, clear + +; Clear 2nd row of warnings if there is nothing to show (on this page) + btfss second_row_warning ; =1: The second row contains a warning + call TFT_clear_warning_text_2nd_row ; No, clear this row + return ; Done. + + global check_warn_battery +check_warn_battery: + movff batt_percent,lo + movlw battery_show_level+1 + cpfslt lo + return ; No Display, no warning + ; Display Battery, but warn? + incf warning_counter,F ; increase counter + call TFT_update_batt_percent_divemode ; Show percent + + movlw color_code_battery_low+1 + cpfslt lo ; + return ; No warning + bsf warning_active ; Set Warning flag + return + +check_ppO2: ; check current ppO2 and display warning if required + SAFE_2BYTE_COPY amb_pressure, xA + movlw d'10' + movwf xB+0 + clrf xB+1 + call div16x16 ; xC=p_amb/10 + + movff xC+0,xA+0 + movff xC+1,xA+1 + movff char_I_O2_ratio,xB+0 ; =O2 ratio + clrf xB+1 + call mult16x16 ; char_I_O2_ratio * p_amb/10 + + ; Check very high ppO2 manually + tstfsz xC+2 ; char_I_O2_ratio * p_amb/10 > 65536, ppO2>6,55bar? + bra check_ppO2_1 ; Yes, display Value! + ; Check if ppO2>3,30bar + btfsc xC+1,7 + bra check_ppO2_1 ; Yes! + + ; Check for low ppo2 + movff xC+0,sub_b+0 + movff xC+1,sub_b+1 + movff opt_ppO2_min,WREG + mullw d'100' ; opt_ppO2_min*100 + movff PRODL,sub_a+0 + movff PRODH,sub_a+1 + call subU16 + btfsc neg_flag + bra check_ppO2_0 ; Not too low + ; ppO2 low + incf warning_counter,F ; increase counter + call TFT_display_ppo2 ; Show ppO2 + movlw d'4' ; Type of Alarm (ppO2 low) + movwf AlarmType ; Copy to Alarm Register + bsf event_occured ; Set Event Flag + bsf warning_active ; Set Warning flag + return ; Done. + +check_ppO2_0: + ; Check if ppO2 should be displayed + movlw ppo2_display_high + mullw d'100' ; ppo2_display_high*100 + movff PRODL,sub_a+0 + movff PRODH,sub_a+1 + call subU16 + btfss neg_flag + return ; No Display, no warning + ; Display ppO2, but warn? + incf warning_counter,F ; increase counter + call TFT_display_ppo2 ; Show ppO2 + +;check if we are within our warning thresholds! + movff xC+0,sub_b+0 + movff xC+1,sub_b+1 + movff opt_ppO2_max,WREG ; PPO2 Max for MOD calculation and color coding in divemode + mullw d'100' ; opt_ppO2_max*100 + movff PRODL,sub_a+0 + movff PRODH,sub_a+1 + call subU16 + btfss neg_flag + return ; Done. Not too high + movlw d'5' ; Type of Alarm (ppO2 high) + movwf AlarmType ; Copy to Alarm Register + bsf event_occured ; Set Event Flag + bsf warning_active ; Set Warning flag + return ; Done. + +check_ppO2_1: ; ppO2 very high + incf warning_counter,F ; increase counter + call TFT_display_ppo2 ; Show ppO2 + movlw d'5' ; Type of Alarm + movwf AlarmType ; Copy to Alarm Register + bsf event_occured ; Set Event Flag + bsf warning_active ; Set Warning flag + return ; Done. + + global check_cns_violation +check_cns_violation: + ; Check if CNS should be displayed + movff int_O_CNS_fraction+1,lo ; copy into bank1 + tstfsz lo ; >255% ? + bra check_cns_violation2 ; Yes + movff int_O_CNS_fraction+0,lo ; copy into bank1 + + movlw cns_warning_high ; cns_warning_high + subwf lo,W + btfsc STATUS,C + bsf warning_active ; Set Warning flag + + movlw cns_display_high ; cns_display_high + subwf lo,W + btfss STATUS,C + return ; No Display, no warning + ; Display CNS + incf warning_counter,F ; increase counter + call TFT_display_cns ; Show CNS + return + +check_cns_violation2: + incf warning_counter,F ; increase counter + call TFT_display_cns ; Show CNS + bsf warning_active ; Set Warning flag + return + + global check_and_store_gf_violation +check_and_store_gf_violation: + movff char_O_gradient_factor,lo ; gradient factor absolute (Non-GF model) + movff char_I_deco_model,hi + decfsz hi,F ; jump over next line if char_I_deco_model == 1 + movff char_O_relative_gradient_GF,lo ; gradient factor relative (GF model) + + movlw gf_warning_high + cpfsgt lo + bra check_and_store_gf_violation2 ; No warning + movlw d'2' ; Type of Alarm + movwf AlarmType ; Copy to Alarm Register + bsf event_occured ; Set Event Flag + bsf warning_active ; Set Warning flag +check_and_store_gf_violation2: + movlw gf_display_high + cpfsgt lo + return ; No Display, no warning + ; Display GF + incf warning_counter,F ; increase counter + call TFT_warning_gf ; Show GF Warning + return + +warn_agf: + incf warning_counter,F ; increase counter + call TFT_warning_agf ; Show aGF warning + bsf warning_active ; Set Warning flag + return + + + END \ No newline at end of file