view src/sleepmode.asm @ 623:c40025d8e750

3.03 beta released
author heinrichsweikamp
date Mon, 03 Jun 2019 14:01:48 +0200
parents ca4556fb60b9
children cd58f7fc86db
line wrap: on
line source

;=============================================================================
;
;   File sleepmode.asm                        combined next generation V3.03.1
;
;   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"


	extern	vault_decodata_into_eeprom
	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)
		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
;							sm_flags,2	; unused
;							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

 IFDEF _external_sensor
	call	disable_ir_s8					; power-down IR/S8 interrupts
	call	mcp_sleep						; power-down RX power supply
 ENDIF

	clrf	ADCON0							; power-down ADC module
	call	TFT_Display_FadeOut				; power-down backlight
	call	TFT_DisplayOff					; power-down display
	call	disable_rs232					; power-down USB
	call	I2C_sleep_accelerometer			; power-down accelerometer
	call	I2C_sleep_compass				; power-down compass

	call	vault_decodata_into_eeprom		; store deco data
	call	ext_flash_enable_protection		; enable write protection on external flash
	call	update_battery_registers		; update battery registers into EEPROM

	clrf	sm_timer_10sec					; clear 10 seconds timer
	clrf	sm_timer_10min					; clear 10 minutes timer
	clrf	sm_timer_15min					; clear 15 minutes timer
	clrf	sm_flags						; clear all local  flags

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

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

	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	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

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

	; the 15 minutes timer only ticks on OSTC with analog switches
	btfss	analog_switches					; OSTC with analog switches?
	bra		one_min_sleep_1					; NO  - no analog switches, no deep sleep required

	; the 15 minutes timer also ticks only when not in deep sleep
	btfsc	deep_sleep						; in deep sleep mode?
	bra		one_min_sleep_1					; YES - already in deep sleep

	; tick the 15 minutes timer
	incf	sm_timer_15min,F				; increment 15 minutes timer
	movlw	.15								; load  a 15 into WREG
	cpfslt	sm_timer_15min					; timer < 15 yet?
	rcall	fifteen_min_sleep				; NO - do the every 15 minute 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	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


fifteen_min_sleep:
	; tasks every 15 minutes in sleep mode
	clrf	sm_timer_15min					; reset timer to 0
	bsf		deep_sleep						; enable deep-sleep mode
	return


one_hour_sleep:
	; tasks every hour in sleep mode mode
	bcf		trigger_full_hour				; clear one hour flag
	call	update_battery_registers		; update battery registers into EEPROM
	call	vault_decodata_into_eeprom		; update tissue  pressures into EEPROM
	return


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	.50								; 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,           required for compass1
	call	I2C_init_accelerometer			; start accelerometer,     required for compass2
	call	I2C_RX_accelerometer			; read accelerometer
	call	I2C_sleep_compass				; shut down compass,       required for compass1
	call	I2C_sleep_accelerometer			; shut down accelerometer, required for compass2
	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	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
	movff	BSR_backup,BSR					; restore BSR
	return

 END