Mercurial > public > hwos_code
view src/sleepmode.asm @ 632:0347acdf6d8e
changelog updates
author | heinrichsweikamp |
---|---|
date | Sat, 29 Feb 2020 16:57:45 +0100 |
parents | 185ba2f91f59 |
children | 4050675965ea |
line wrap: on
line source
;============================================================================= ; ; File sleepmode.asm combined next generation V3.08.8 ; ; Sleep Mode ; ; Copyright (c) 2011, JD Gascuel, HeinrichsWeikamp, all right reserved. ;============================================================================== ; HISTORY ; 2011-08-12 : [mH] moving from OSTC code #include "hwos.inc" ; Mandatory header #include "shared_definitions.h" ; Mailbox from/to p2_deco.c #include "surfmode.inc" #include "tft.inc" #include "start.inc" #include "adc_lightsensor.inc" #include "math.inc" #include "ms5541.inc" #include "eeprom_rs232.inc" #include "external_flash.inc" #include "ghostwriter.inc" #include "i2c.inc" #include "mcp.inc" #include "wait.inc" #include "tft_outputs.inc" extern eeprom_deco_data_write extern option_check_and_store_all extern power_up_switches ; from hwos.asm ;---- Private local Variables ------------------------------------------------- CBLOCK local1 ; max size is 16 Byte !!! accel_reference ; acceleration reference value for detecting movement / terminating deep sleep sm_timer_10sec ; timer for 10 seconds tasks (pressure check) sm_timer_10min ; timer for 10 minutes tasks (tissue updating) ;sm_timer_15min ; timer for 15 minutes tasks (entering deep sleep) sm_10min_counter ; count #of 10 minutes loop_counter ; loop counter, used in init_avg_switches routine sm_flags ; local flags ENDC ; used: 6 byte, remaining: 10 byte ;---- Private local Flags ----------------------------------------------------- #DEFINE deep_sleep sm_flags,0 ; =1: in deep sleep mode, =0: normal sleep #DEFINE desat_on_10_mins sm_flags,1 ; =1: calculate desaturation every 10 minutes, =0: every minute #DEFINE charge_in_sleep sm_flags,2 ; =1: show charging screen ; sm_flags,3 ; unused ; sm_flags,4 ; unused ; sm_flags,5 ; unused ; sm_flags,6 ; unused ; sm_flags,7 ; unused slmode CODE ;============================================================================== global sleeploop sleeploop: clrf STKPTR ; clear return addresses stack call request_speed_normal ; request CPU speed switch to normal speed bcf LEDg ; turn off green LED / release reset to RX circuitry bcf LEDr ; turn off red LED IFDEF _screendump bcf screen_dump_avail ; disable screen dump function ENDIF bsf sleepmode ; flag being in sleep mode bsf block_sensor_interrupt ; suspend ISR from executing sensor interrupts call disable_ir_s8 ; power-down IR/S8 interrupts call mcp_sleep ; power-down RX power supply clrf ADCON0 ; power-down ADC module call disable_rs232 ; power-down USB call I2C_sleep_compass ; power-down compass call eeprom_deco_data_write ; update deco data in EEPROM call eeprom_battery_gauge_write ; update battery gauge in EEPROM btfsc options_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 bcf options_changed ; clear flag call ext_flash_enable_protection ; enable write protection on external flash clrf sm_timer_10sec ; clear 10 seconds timer clrf sm_timer_10min ; clear 10 minutes timer clrf sm_10min_counter ; clear 10mins counter clrf sm_flags ; clear all local flags call TFT_Display_FadeOut ; power-down backlight call TFT_DisplayOff ; power-down display sleeploop_loop: btfsc trigger_full_second ; one second in sleep? rcall one_sec_sleep ; YES - check switches, pressure sensor, etc. btfss sleepmode ; shall terminate sleep mode? bra sleeploop_exit ; YES rcall sleepmode_sleep ; wait at least 35 ms (every 62.5 ms timer7 wakeup) btfss deep_sleep ; shall enter deep sleep? bra sleeploop_loop ; NO - remain in normal sleep loop ;bra deepsleep_pre ; YES - enter deep sleep loop deepsleep_pre: bcf PIE1,0 ; disable timer 1 interrupt bcf PIE2,1 ; disable timer 2 interrupt bcf PIE5,3 ; disable timer 7 interrupt bcf INTCON,4 ; disable INT0 interrupt bcf INTCON3,3 ; disable INT1 interrupt bcf power_sw1 ; power-down switch 1 bcf power_sw2 ; power-down switch 2 rcall deepsleep_get_accel ; read accelerometer into WREG movwf accel_reference ; store as reference value tstfsz accel_reference ; = 0 ? bra deepsleep_loop ; NO - continue bra deepsleep_loop_exit ; YES - no deep sleep (fail-safe) deepsleep_loop: btfsc trigger_full_second ; one second in deep sleep? rcall check_accelerometer ; YES - check accelerometer btfsc trigger_full_second ; one second in deep sleep? rcall one_sec_sleep ; YES - check switches, check pressure sensor, etc. rcall sleepmode_sleep ; wait at least 35 ms (every 62.5 ms timer7 wakeup) btfss sleepmode ; shall leave sleep mode? bcf deep_sleep ; YES - leave deep sleep mode then, too btfsc deep_sleep ; shall leave deep sleep mode? bra deepsleep_loop ; NO - loop in deep sleep loop deepsleep_loop_exit: bcf deep_sleep ; clear flag (again) clrf sm_10min_counter ; clear 10mins counter call power_up_switches ; turn on the analog switches rcall init_avg_switches ; initialize the averaging system bsf PIE1,0 ; enable timer 1 interrupt bsf PIE2,1 ; enable timer 2 interrupt bsf PIE5,3 ; enable timer 7 interrupt bsf INTCON,4 ; enable INT0 interrupt bsf INTCON3,3 ; enable INT1 interrupt bra sleeploop_loop ; enter normal sleep loop sleeploop_exit: bcf switch_left ; eventually clear left button event bcf switch_right ; eventually clear right button event movlw .0 ; reset ISR sensor state machine movff WREG,sensor_state_counter ; ... bcf PIR5,TMR7IF ; clear timer 7, driving the ISR sensor interrupts bcf block_sensor_interrupt ; re-enable execution of the ISR sensor interrupts goto restart ; restart one_sec_sleep: ; tasks every second in sleep mode bcf trigger_full_second ; clear trigger flag btfsc switch_left ; left switch pressed? bcf sleepmode ; YES - terminate sleep mode btfsc switch_right ; right switch pressed? bcf sleepmode ; YES - terminate sleep mode btfsc battery_gauge_available ; is a battery gauge IC available? bra one_sec_sleep_1 ; YES - check for charger btfsc ble_available ; Skip "USB" check in all Bluetooth models (Required for very old OSTC sport) bra one_sec_sleep_2 ; - continue btfsc vusb_in ; NO - USB plugged in? bcf sleepmode ; YES - terminate sleep mode bra one_sec_sleep_2 ; - continue one_sec_sleep_1: call get_battery_voltage ; check for charger ; Test if charging btfss cc_active ; charging? bra one_sec_sleep_1a ; NO btfsc charge_in_sleep ; YES - already showing charge screen? bra one_sec_sleep_1b ; YES - only update data bsf charge_in_sleep bcf deep_sleep ; wake-up from deepsleep call TFT_boot ; initialize TFT (includes clear screen) movlw .32 movff WREG,max_CCPR1L ; bank safe call TFT_Display_FadeIn ; dim up the display one_sec_sleep_1b: call TFT_batt_surfmode ; show battery type, voltage and color-coded percentage bra one_sec_sleep_2 ; continue one_sec_sleep_1a: btfss charge_in_sleep ; was showing charge screen? bra one_sec_sleep_2 ; NO ; yes, power-down screen call TFT_Display_FadeOut ; power-down backlight call TFT_DisplayOff ; power-down display bcf charge_in_sleep one_sec_sleep_2: incf sm_timer_10sec,F ; increment 10 seconds timer movlw .10 ; load a 10 into WREG cpfslt sm_timer_10sec ; timer < 10 yet? rcall ten_sec_sleep ; NO - do the every 10 second tasks btfsc trigger_full_minute ; one minute in sleep? rcall one_min_sleep ; YES - do the every minute tasks btfsc trigger_full_hour ; one hour in sleep? rcall one_hour_sleep ; YES - do the every hour tasks return ; done ten_sec_sleep: ; tasks every 10 seconds in sleep mode clrf sm_timer_10sec ; clear timer rcall pressuretest_sleep_fast ; get pressure without averaging (faster) MOVLI wake_up_from_sleep,sub_a ; load wake-up pressure (1160 mbar) into sub_a MOVII pressure_abs, sub_b ; load current absolute pressure into sub_b call cmpU16 ; sub_a - sub_b = wake-up pressure - current absolute pressure btfsc neg_flag ; is the current absolute pressure > 1160 mbar ? bcf sleepmode ; YES - terminate sleep mode return ; done one_min_sleep: ; tasks every minute in sleep mode bcf trigger_full_minute ; clear flag ; tick the 10 minutes timer incf sm_timer_10min,F ; increment 10 minutes timer movlw .10 ; load a 10 into WREG cpfslt sm_timer_10min ; timer < 10 yet? rcall ten_min_sleep ; NO - do the every 10 minutes tasks one_min_sleep_1: ; continue tasks every minute btfsc desat_on_10_mins ; shall do desaturation calculation on 10 minute intervals? return ; YES - that's not here then, so done call deco_calc_dive_interval_1min ; NO - calculate 1 minute at surface conditions (C-code) banksel common ; - back to bank common return ; - done ten_min_sleep: ; tasks every 10 minutes in sleep mode clrf sm_timer_10min ; reset timer to 0 call sample_surface_pressure ; sample surface pressure and update ISR and deco engine btfss analog_switches ; OSTC with analog switches? bra ten_min_sleep_0 ; NO - no analog switches, no deep sleep required ; check if we need to enter deep sleep incf sm_10min_counter,F ; count movlw deep_sleep_10mins ; threshold cpfseq sm_10min_counter ; threshold reached? bra ten_min_sleep_0 ; NO - threshold not reached yet decf sm_10min_counter,F ; -1 to re-trigger every 10mins (in case of charging) btfss cc_active ; charging? bsf deep_sleep ; NO - activate deep-sleep mode ten_min_sleep_0: btfss desat_on_10_mins ; shall do desaturation calculation on 10 minute intervals? bra ten_min_sleep_1 ; NO - continue checking if schedule can be switched to 10 minutes call deco_calc_dive_interval_10min ; YES - calculate 10 minutes at surface conditions (C-code) banksel common ; - back to bank common return ; - done ten_min_sleep_1: movff int_O_lead_supersat+0,WREG ; get leading tissue's supersaturation (only the lower byte is used for the value) bsf desat_on_10_mins ; switch to 10 minute intervals by default tstfsz WREG ; gradient factor = 0 ? bcf desat_on_10_mins ; NO - stay on 1 minute intervals return ; done one_hour_sleep: ; tasks every hour in sleep mode mode bcf trigger_full_hour ; clear one hour flag call eeprom_deco_data_write ; update deco data into EEPROM call eeprom_battery_gauge_write ; update battery gauge into EEPROM return ; done init_avg_switches: ; pause 4 seconds using CPU sleep mode to conserve on battery movlw .4 ; time to pause movwf loop_counter ; initialize loop counter bcf trigger_full_second ; clear 'one second elapsed' flag activate_switches_1: rcall sleepmode_sleep ; wait at least 35 ms (every 62.5 ms timer7 wakeup) btfss trigger_full_second ; did 1 second elapsed meanwhile? bra activate_switches_1 ; NO - loop bcf trigger_full_second ; YES - clear flag decfsz loop_counter,F ; - decrement loop counter, done? bra activate_switches_1 ; NO - loop ; initialize the averaging system movlw .32 ; number of readout cycles movwf loop_counter ; initialize loop counter activate_switches_2: call get_analog_switches ; do a analog switch readout decfsz loop_counter,F ; decrement loop counter, done? bra activate_switches_2 ; NO - loop ; clear all button events that may have intermediately occurred bcf PIR1,TMR1IF ; clear button-hold-down timer bcf INTCON,INT0IF ; clear right button activity bcf INTCON3,INT1IF ; clear left button activity bcf analog_sw1_pressed ; clear analog switch 1 activity bcf analog_sw2_pressed ; clear analog switch 2 activity bcf switch_right ; clear right button event bcf switch_left ; clear left button event ; done return check_accelerometer: rcall deepsleep_get_accel ; read accelerometer into WREG subwf accel_reference,W ; reference value - accel_DZ+0 -> WREG btfsc STATUS,N ; result negative? negf WREG ; YES - negate it movwf lo ; save as change of acceleration in Z-axis movlw .100 ; load threshold (mg) cpfslt lo ; change of acceleration > threshold ? bcf deep_sleep ; YES - terminate deep sleep mode return ; done deepsleep_get_accel: call I2C_init_compass ; start compass rcall sleepmode_sleep ; wait a little bit call I2C_RX_accelerometer ; read accelerometer call I2C_RX_accelerometer ; read accelerometer call I2C_sleep_compass ; shut down compass movff accel_DZ+0,WREG ; transfer result to WREG return ; done pressuretest_sleep_fast: ; get pressure without averaging (faster to save some power in sleep mode) banksel isr_backup ; select bank ISR data CLRI pressure_abs_avg ; clear pressure average register CLRI temperature_avg ; clear temperature average register call get_temperature_start ; start temperature integration (73.5 us) rcall sleepmode_sleep ; wait at least 35 ms (every 62.5 ms timer7 wakeup) rcall sleepmode_sleep ; wait at least 35 ms (every 62.5 ms timer7 wakeup) call get_temperature_value ; state 1: get temperature call get_pressure_start ; start pressure integration rcall sleepmode_sleep ; wait at least 35 ms (every 62.5 ms timer7 wakeup) rcall sleepmode_sleep ; wait at least 35 ms (every 62.5 ms timer7 wakeup) call get_pressure_value ; state2: get pressure (51 us) call calculate_compensation ; calculate temperature compensated pressure (27 us) MOVII pressure_abs_avg,pressure_abs ; get result, bypassing the averaging banksel common ; back to bank common return sleepmode_sleep: movff BSR,BSR_backup ; backup BSR banksel common btfsc charge_in_sleep ; already showing charge screen? bra sleepmode_sleepwalk ; YES - skip the actual sleep (But wait) ; banksel T7GCON ; switch bank, T7* is outside access RAM ; clrf T7GCON ; reset timer7 gate control register ; movlw b'10001101' ; 1:1 prescaler -> 2 seconds @ 32768 Hz, not synced ; movwf T7CON sleep sleep ; clrf T7GCON ; reset timer7 gate control register ; movlw b'10001001' ; 1:1 prescaler -> 2 seconds @ 32768 Hz, synced ; movwf T7CON sleepmode_sleep_1: movff BSR_backup,BSR ; restore BSR return sleepmode_sleepwalk: WAITMS d'65' bra sleepmode_sleep_1 END