view src/isr.asm @ 592:05053910d668

BUGFIX: Re-enable Sensors after sleep in PSCR mode
author heinrichsweikamp
date Wed, 18 Apr 2018 17:03:52 +0200
parents b455b31ce022
children ca4556fb60b9
line wrap: on
line source

;=============================================================================
;
;   File isr.asm									REFACTORED VERSION V2.98
;
;   INTERUPT subroutines
;
;   Copyright (c) 2011, JD Gascuel, HeinrichsWeikamp, all right reserved.
;=============================================================================
; HISTORY
;  2011-05-24 : [jDG] Cleanups from initial Matthias code.

#include "hwos.inc"
#include "shared_definitions.h"			; Mailbox from/to p2_deco.c
#include "ms5541.inc"
#include "adc_lightsensor.inc"
#include "eeprom_rs232.inc"

;=============================================================================

	extern	start

isr_high	CODE	0x0008				; High Priority Interrupts
	bra		HighInt
	nop
	nop
	nop
	nop
	nop
	nop
	bra		HighInt

isr_low		CODE	0x00018				; Low Priority Interrupts
;	*** low priority interrupts not used
	retfie	FAST						; Restores BSR, STATUS and WREG

HighInt:
	movff	PRODL,isr_prod+0
	movff	PRODH,isr_prod+1

	; Buttons
	btfsc	PIR1,TMR1IF					; Timer1 INT (Button hold-down Timer)
	rcall	timer1int
	btfsc	INTCON,INT0IF				; Buttons
	rcall	isr_switch_right
	btfsc	INTCON3,INT1IF				; Buttons
	rcall	isr_switch_left

	; IR/S8 link timer int
	btfsc	PIR3,RC2IF					; UART2
	rcall	isr_uart2					; IR/S8-Link
	btfsc	PIR2,TMR3IF					; Timer 3
	rcall	isr_timer3					; IR-Link Timeout

	; Pressure sensor and others
	btfsc	PIR5,TMR7IF					; Timer 7
	rcall	isr_tmr7					; Every 62,5ms

	; RTCC
	btfsc	PIR3,RTCCIF					; Real-time-clock interrupt
	rcall	isr_rtcc					; May return in bank common!

	movff	isr_prod+1,PRODH
	movff	isr_prod+0,PRODL
	retfie	FAST						; Restores BSR, STATUS and WREG

isr_set_speed_to_normal:
	; Set speed to normal
	movlw	b'01110010'
	movwf	OSCCON						; 16MHz INTOSC
	movlw	b'00000000'
	movwf	OSCTUNE						; 4x PLL Disable (Bit6) - only works with 8 or 16MHz (=32 or 64MHz)
	movlw	b'00001101'					; 1:2 Postscaler, 1:4 Prescaler, Timer 2 start -> 1960Hz (no-flicker)
	movwf	T2CON
	btfss	OSCCON,HFIOFS
	bra		$-2							; Wait until clock is stable
	return

isr_dimm_tft:							; Adjust until max_CCPR1L=CCPR1L !
	banksel	common
	btfsc	tft_is_dimming				; Ignore while dimming
	return
	banksel	isr_backup
	movf	max_CCPR1L,W
	cpfsgt	CCPR1L						; CCPR1L>max_CCPR1L?
	bra		isr_dimm_tft2				; No, dimm up
	; dimm down
	decf	CCPR1L,F					; -1
	return
isr_dimm_tft2:
	movf	max_CCPR1L,W
	sublw	ambient_light_min_eco
	cpfsgt	CCPR1L						; CCPR1L>max_CCPR1L-ambient_light_min_eco?
	bra		isr_dimm_tft3				; No, dimm up slow
	; dimm up faster
	movlw	.10
	addwf	CCPR1L,F
isr_dimm_tft3:
	incf	CCPR1L,F					; +1
	return
	nop
	nop									; block flash here

isr_restore	CODE	0x00080				; Restore first flash page from EEPROM
restore_flash_0x00080:
	goto	restore_flash

isr_routines							;	CODE
;=============================================================================

isr_uart2:								; IR/S8-Link
	banksel	RCREG2
	movf	RCREG2,W
	bcf		RCSTA2,CREN					; Clear receiver status
	bsf		RCSTA2,CREN
	banksel	isr_backup
	incf	ir_s8_counter,F				; Increase counter
	movff	ir_s8_counter,isr1_temp		; Copy
	dcfsnz	isr1_temp,F
	movwf	ir_s8_buffer+.0
	dcfsnz	isr1_temp,F
	movwf	ir_s8_buffer+.1
	dcfsnz	isr1_temp,F
	movwf	ir_s8_buffer+.2
	dcfsnz	isr1_temp,F
	movwf	ir_s8_buffer+.3
	dcfsnz	isr1_temp,F
	movwf	ir_s8_buffer+.4
	dcfsnz	isr1_temp,F
	movwf	ir_s8_buffer+.5
	dcfsnz	isr1_temp,F
	movwf	ir_s8_buffer+.6
	dcfsnz	isr1_temp,F
	movwf	ir_s8_buffer+.7
	dcfsnz	isr1_temp,F
	movwf	ir_s8_buffer+.8
	dcfsnz	isr1_temp,F
	movwf	ir_s8_buffer+.9
	dcfsnz	isr1_temp,F
	movwf	ir_s8_buffer+.10
	dcfsnz	isr1_temp,F
	movwf	ir_s8_buffer+.11
	dcfsnz	isr1_temp,F
	movwf	ir_s8_buffer+.12
	dcfsnz	isr1_temp,F
	movwf	ir_s8_buffer+.13
	dcfsnz	isr1_temp,F
	movwf	ir_s8_buffer+.14
	dcfsnz	isr1_temp,F
	movwf	ir_s8_buffer+.15
	dcfsnz	isr1_temp,F
	movwf	ir_s8_buffer+.16
	dcfsnz	isr1_temp,F
	movwf	ir_s8_buffer+.17

	clrf	TMR3L						; Preload timer
	movlw	.253
	movwf	TMR3H
	bsf		T3CON,TMR3ON				; (Re)Start Timeout counter
	return

isr_timer3:								; IR/S8-Link Timeout
	bcf		T3CON,TMR3ON				; Stop Timer3
	banksel	isr_backup					; Select Bank0 for ISR data.
	movlw	.15
	cpfseq	ir_s8_counter				; Got exact 15bytes?
	bra		isr_timer3_1				; No, test for 16bytes
	bra		isr_timer3_ir				; Got 15 bytes, compute local checksum
isr_timer3_1:
	movlw	.16
	cpfseq	ir_s8_counter				; Got exact 16bytes?
	bra		isr_timer3_2				; No, test for 17bytes
	tstfsz	ir_s8_buffer+.15			; Last byte=0x00
	bra		isr_timer3_exit				; No, exit
	bra		isr_timer3_ir				; Got 16 bytes, compute local checksum
isr_timer3_2:
	movlw	.17
	cpfseq	ir_s8_counter				; Got exact 17bytes?
	bra		isr_timer3_exit				; No, exit
	bra		isr_timer3_s8				; S8 data

isr_timer3_ir:							; IR input
	movff	ir_s8_buffer+.0,PRODL
	clrf	PRODH
	movf	ir_s8_buffer+.1,W
	rcall	isr_timer3_checksum
	movf	ir_s8_buffer+.2,W
	rcall	isr_timer3_checksum
	movf	ir_s8_buffer+.3,W
	rcall	isr_timer3_checksum
	movf	ir_s8_buffer+.4,W
	rcall	isr_timer3_checksum
	movf	ir_s8_buffer+.5,W
	rcall	isr_timer3_checksum
	movf	ir_s8_buffer+.6,W
	rcall	isr_timer3_checksum
	movf	ir_s8_buffer+.7,W
	rcall	isr_timer3_checksum
	movf	ir_s8_buffer+.8,W
	rcall	isr_timer3_checksum
	movf	ir_s8_buffer+.9,W
	rcall	isr_timer3_checksum
	movf	ir_s8_buffer+.10,W
	rcall	isr_timer3_checksum
	movf	ir_s8_buffer+.11,W
	rcall	isr_timer3_checksum
	movf	ir_s8_buffer+.12,W
	rcall	isr_timer3_checksum

	; Compare checksum
	movf	ir_s8_buffer+.13,W
	cpfseq	PRODL						; Checksum ok?
	bra		isr_timer3_exit				; No, exit
	movf	ir_s8_buffer+.14,W
	cpfseq	PRODH						; Checksum ok?
	bra		isr_timer3_exit				; No, exit

	; Checksum OK, copy results
	movff	ir_s8_buffer+.1,hud_status_byte
	movff	ir_s8_buffer+.2,o2_mv_sensor1+0
	movff	ir_s8_buffer+.3,o2_mv_sensor1+1
	movff	ir_s8_buffer+.4,o2_mv_sensor2+0
	movff	ir_s8_buffer+.5,o2_mv_sensor2+1
	movff	ir_s8_buffer+.6,o2_mv_sensor3+0
	movff	ir_s8_buffer+.7,o2_mv_sensor3+1
	movff	ir_s8_buffer+.8,o2_ppo2_sensor1
	movff	ir_s8_buffer+.9,o2_ppo2_sensor2
	movff	ir_s8_buffer+.10,o2_ppo2_sensor3
	movff	ir_s8_buffer+.11,hud_battery_mv+0
	movff	ir_s8_buffer+.12,hud_battery_mv+1

	movlw	ir_timeout_value			; multiples of 62,5ms
	movwf	ir_s8_timeout				; Reload timeout

	banksel	hud_status_byte
	bsf		hud_connection_ok			; Set manually for hwHUD w/o the HUD module...
	banksel	isr_backup					; Select Bank0 for ISR data.

isr_timer3_exit:
	clrf	ir_s8_counter				; Clear pointer
	bcf		PIR2,TMR3IF					; Clear flag
	return

isr_timer3_checksum:
	addwf	PRODL,F
	movlw	.0
	addwfc	PRODH,F
	return

isr_timer3_s8:							; S8 input
	movff	ir_s8_buffer+.0,PRODL
	clrf	PRODH
	movf	ir_s8_buffer+.1,W
	rcall	isr_timer3_checksum
	movf	ir_s8_buffer+.2,W
	rcall	isr_timer3_checksum
	movf	ir_s8_buffer+.3,W
	rcall	isr_timer3_checksum
	movf	ir_s8_buffer+.4,W
	rcall	isr_timer3_checksum
	movf	ir_s8_buffer+.5,W
	rcall	isr_timer3_checksum
	movf	ir_s8_buffer+.6,W
	rcall	isr_timer3_checksum
	movf	ir_s8_buffer+.7,W
	rcall	isr_timer3_checksum
	movf	ir_s8_buffer+.8,W
	rcall	isr_timer3_checksum
	movf	ir_s8_buffer+.9,W
	rcall	isr_timer3_checksum
	movf	ir_s8_buffer+.10,W
	rcall	isr_timer3_checksum
	movf	ir_s8_buffer+.11,W
	rcall	isr_timer3_checksum
	movf	ir_s8_buffer+.12,W
	rcall	isr_timer3_checksum
	movf	ir_s8_buffer+.13,W
	rcall	isr_timer3_checksum
	movf	ir_s8_buffer+.14,W
	rcall	isr_timer3_checksum

	; Compare checksum
	movf	ir_s8_buffer+.15,W
	cpfseq	PRODL						; Checksum ok?
	bra		isr_timer3_exit				; No, exit
	movf	ir_s8_buffer+.16,W
	cpfseq	PRODH						; Checksum ok?
	bra		isr_timer3_exit				; No, exit

	; Checksum OK, copy results
	movff	ir_s8_buffer+.3,hud_status_byte
	movff	ir_s8_buffer+.13,hud_battery_mv+0
	movff	ir_s8_buffer+.14,hud_battery_mv+1

	banksel	common
	btfsc	new_s8_data_available		; =1: Old data already processed?
	bra		isr_timer3_skip				; No, skip copying new results

	movff	ir_s8_buffer+.6,s8_rawdata_sensor1+2
	movff	ir_s8_buffer+.5,s8_rawdata_sensor1+1
	movff	ir_s8_buffer+.4,s8_rawdata_sensor1+0
	movff	ir_s8_buffer+.9,s8_rawdata_sensor2+2
	movff	ir_s8_buffer+.8,s8_rawdata_sensor2+1
	movff	ir_s8_buffer+.7,s8_rawdata_sensor2+0
	movff	ir_s8_buffer+.12,s8_rawdata_sensor3+2
	movff	ir_s8_buffer+.11,s8_rawdata_sensor3+1
	movff	ir_s8_buffer+.10,s8_rawdata_sensor3+0
	banksel	common
	bsf		new_s8_data_available		; set flag

isr_timer3_skip:
	banksel	ir_s8_timeout
	movlw	ir_timeout_value			; multiples of 62,5ms
	movwf	ir_s8_timeout				; Reload timeout
	bra		isr_timer3_exit				; Exit


;=============================================================================

isr_tmr7:								; each 62,5ms
	bcf		PIR5,TMR7IF					; clear flag
	banksel	0xF16						; Addresses, F16h through F5Fh, are also used by SFRs, but are not part of the Access RAM.
	movlw	.248
	movwf	TMR7H						; -> Rollover after 2048 cycles -> 62,5ms

	banksel	common
	call	get_analog_switches			; Get analog readings
	btfss	INTCON3,INT1IE
	bra		isr_tmr7_a
	btfsc	analog_sw2_pressed
	rcall	isr_switch_left
isr_tmr7_a:
	banksel	common
	btfss	INTCON,INT0IE
	bra		isr_tmr7_b
	btfsc	analog_sw1_pressed
	rcall	isr_switch_right
isr_tmr7_b:
	banksel	common
	btfss	no_sensor_int				; No sensor interrupt (because it's addressed during sleep)
	bra		isr_tmr7_c					; No, continue
	banksel	isr_backup					; Back to Bank0 ISR data
	return
isr_tmr7_c:
	banksel	isr_backup
	movf	max_CCPR1L,W				; Dimm value
	cpfseq	CCPR1L						; = current PWM value?
	rcall	isr_dimm_tft				; No, adjust until max_CCPR1L=CCPR1L !

	banksel	isr_backup
	decfsz	ir_s8_timeout,F				; IR Data still valid?
	bra		isr_tmr7_2					; Yes, continue
	; timeout, clear IR-Data

	movlw	ir_timeout_value			; multiples of 62,5ms
	movwf	ir_s8_timeout				; Reload timeout

	banksel	common
	btfss	analog_o2_input
	bra		isr_tmr7_1a					; Always with normal ostc3 hardware
	btfss	s8_digital
	bra		isr_tmr7_2					; only when digital
isr_tmr7_1a:
	clrf	o2_mv_sensor1+0				; S8/IR timeout clears all analog input readings to zero -> Fallback will be triggered when sensor mode was used
	clrf	o2_mv_sensor1+1
	clrf	o2_mv_sensor2+0
	clrf	o2_mv_sensor2+1
	clrf	o2_mv_sensor3+0
	clrf	o2_mv_sensor3+1
	banksel	hud_battery_mv
	clrf	hud_battery_mv+0
	clrf	hud_battery_mv+1
	banksel	hud_status_byte
	clrf	hud_status_byte
	clrf	o2_ppo2_sensor1				; for IR/S8 UD
	clrf	o2_ppo2_sensor2
	clrf	o2_ppo2_sensor3

	banksel	common
	bsf		new_s8_data_available		; set flag to update in surface mode

isr_tmr7_2:
	banksel	common
	btfss	no_sensor_int				; No sensor interrupt (because it's addressed during sleep)
	bra		isr_sensor_state2			; No, continue
	banksel	isr_backup					; Back to Bank0 ISR data
	return

isr_sensor_state2:
	banksel	common
	movff	sensor_state_counter,WREG
	btfss	WREG,0						; every 1/4 second
	bsf		quarter_second_update		; Set flag
	banksel	isr_backup					; Back to Bank0 ISR data
	movlw	d'2'
	cpfseq	speed_setting				; Set to normal in case it's not already in normal speed mode
	rcall	isr_set_speed_to_normal

	incf	sensor_state_counter,F		; counts to eight for state machine

; State 1: Clear flags and average registers, get temperature (51us) and start pressure integration (73,5us)
; State 2: Get pressure (51us), start temperature integration (73,5us) and calculate temperature compensated pressure (233us)
; State 3: Get temperature (51us) and start pressure integration (73,5us)
; State 4: Get pressure (51us), start temperature integration (73,5us) and calculate temperature compensated pressure (233us)
; State 5: Get temperature (51us) and start pressure integration (73,5us)
; State 6: Get pressure (51us), start temperature integration (73,5us) and calculate temperature compensated pressure (233us)
; State 7: Get temperature (51us) and start pressure integration (73,5us)
; State 8: Get pressure (51us), start temperature integration (73,5us), calculate temperature compensated pressure (233us) and build average for half-second update of tempperature and pressure

	movff	sensor_state_counter,WREG		; WREG used as temp here...
	dcfsnz	WREG,F
	bra		sensor_int_state1_plus_restart	; Do State 1
	dcfsnz	WREG,F
	bra		sensor_int_state2				; Do State 2
	dcfsnz	WREG,F
	bra		sensor_int_state1				; Do State 3
	dcfsnz	WREG,F
	bra		sensor_int_state2				; Do State 4
	dcfsnz	WREG,F
	bra		sensor_int_state1				; Do State 5
	dcfsnz	WREG,F
	bra		sensor_int_state2				; Do State 6
	dcfsnz	WREG,F
	bra		sensor_int_state1				; Do State 7
;	bra		sensor_int2_plus_average		; Do State 8
;sensor_int2_plus_average:
	; First, do state2:
	call	get_pressure_value			; State2: Get pressure (51us)
	call	get_temperature_start		; and start temperature integration (73,5us)
	call	calculate_compensation		; calculate temperature compensated pressure (27us)
; Build average
	bcf		STATUS,C					; clear carry bit.
	rrcf	amb_pressure_avg+1			; amb_pressure sum / 2
	rrcf	amb_pressure_avg+0
	bcf		STATUS,C					; clear carry bit, twice.
	rrcf	amb_pressure_avg+1			; amb_pressure sum / 4
	rrcf	amb_pressure_avg+0

	movff	amb_pressure_avg+1,amb_pressure+1	; copy into actual register
	movff	amb_pressure_avg+0,amb_pressure+0

	bcf		STATUS,C
	btfsc	temperature_avg+1,7			; Copy sign bit to carry
	bsf		STATUS,C
	rrcf	temperature_avg+1			; Signed temperature /2
	rrcf	temperature_avg+0
	bcf		STATUS,C
	btfsc	temperature_avg+1,7			; Copy sign bit to carry
	bsf		STATUS,C
	rrcf	temperature_avg+1			; Signed temperature /4
	rrcf	temperature_avg+0

	movff	temperature_avg+1,temperature+1		; copy into actual register
	movff	temperature_avg+0,temperature+0

	banksel	common						; flag1 is in Bank1
	bcf		temp_changed				; Clear flag for temperature update
	bcf		pressure_refresh			; Clear flag for pressure update
	banksel	isr_backup					; Back to Bank0 ISR data

	; Temp changed?
	movf	temperature+0,W
	cpfseq	last_temperature+0
	bra		isr_sensor_state2_2			; Yes
	movf	temperature+1,W
	cpfseq	last_temperature+1
	bra		isr_sensor_state2_2			; Yes

	bra		isr_sensor_state2_3			; no change

isr_sensor_state2_2:
	banksel	common						; flag1 is in Bank1
	bsf		temp_changed				; Yes
	banksel	isr_backup					; Back to Bank0 ISR data
isr_sensor_state2_3:
	movff	temperature+0,last_temperature+0	; Copy for compare
	movff	temperature+1,last_temperature+1

	movf	amb_pressure+0,W
	cpfseq	last_pressure+0
	bra		isr_sensor_state2_4			; Yes
	movf	amb_pressure+1,W
	cpfseq	last_pressure+1
	bra		isr_sensor_state2_4			; Yes

	bra		isr_sensor_state2_5			; No change
isr_sensor_state2_4:
	banksel	common						; flag1 is in Bank1
	bsf		pressure_refresh			; Yes
	banksel	isr_backup					; Back to Bank0 ISR data
isr_sensor_state2_5:
	movff	amb_pressure+0,last_pressure+0	; Copy for compare
	movff	amb_pressure+1,last_pressure+1

	clrf	sensor_state_counter		; Then reset State counter
	banksel	common						; flag2 is in Bank1
	btfss	simulatormode_active		; are we in simulator mode?
	bra		comp_air_pressure			; no
	; Always set pressure_refresh flag in simulator mode
	bsf		pressure_refresh			; Yes
	banksel	isr_backup					; Back to Bank0 ISR data
	movlw	LOW  d'1000'				; yes, so simulate 1000mbar surface pressure
	movwf	last_surfpressure+0
	movlw	HIGH d'1000'
	movwf	last_surfpressure+1

comp_air_pressure:
	banksel	isr_backup					; Back to Bank0 ISR data
	movf	last_surfpressure+0,W		; compensate air pressure
	subwf	amb_pressure+0,W
	movwf	rel_pressure+0				; rel_pressure stores depth!

	movf	last_surfpressure+1,W
	subwfb	amb_pressure+1,W
	movwf	rel_pressure+1
	btfss	STATUS,N					; result is below zero?
	bra		sensor_int_state_exit
	clrf	rel_pressure+0				; Yes, do not display negative depths
	clrf	rel_pressure+1				; e.g. when surface air pressure dropped during the dive
	bra		sensor_int_state_exit

sensor_int_state1_plus_restart:
	clrf	amb_pressure_avg+0			; pressure average registers
	clrf	amb_pressure_avg+1
	clrf	temperature_avg+0
	clrf	temperature_avg+1

sensor_int_state1:
	call	get_temperature_value		; State 1: Get temperature
	call	get_pressure_start			; and start pressure integration.
	bra		sensor_int_state_exit

sensor_int_state2:
	call	get_pressure_value			; State2: Get pressure (51us)
	call	get_temperature_start		; and start temperature integration (73,5us)
	call	calculate_compensation		; calculate temperature compensated pressure (233us)
	;bra	sensor_int_state_exit

sensor_int_state_exit:
	rcall	isr_restore_clock			; Restore clock
	return

;=============================================================================

isr_rtcc:								; each second
	bcf		PIR3,RTCCIF					; clear flag
	banksel	0xF16						; Addresses, F16h through F5Fh, are also used by SFRs, but are not part of the Access RAM.
	bsf		RTCCFG,RTCPTR1
	bsf		RTCCFG,RTCPTR0				; year
	movff	RTCVALL,year				; format is BCD!
	movff	RTCVALH,day					; dummy read
	movff	RTCVALL,day					; format is BCD!
	movff	RTCVALH,month				; format is BCD!
	movff	RTCVALL,hours				; format is BCD!
	movff	RTCVALH,secs				; format is BCD!
	movff	RTCVALL,secs				; format is BCD!
	movff	RTCVALH,mins				; format is BCD!
	banksel	isr_backup					; Back to Bank0 ISR data

	; Convert BCD to DEC and set registers
	movff	mins, isr1_temp
	rcall	isr_rtcc_convert			; Converts to dec with result in WREG
	movff	WREG,mins
	movff	secs, isr1_temp
	rcall	isr_rtcc_convert			; Converts to dec with result in WREG
	movff	WREG,secs
	movff	hours, isr1_temp
	rcall	isr_rtcc_convert			; Converts to dec with result in WREG
	movff	WREG,hours
	movff	month, isr1_temp
	rcall	isr_rtcc_convert			; Converts to dec with result in WREG
	movff	WREG,month
	movff	day, isr1_temp
	rcall	isr_rtcc_convert			; Converts to dec with result in WREG
	movff	WREG,day
	movff	year, isr1_temp
	rcall	isr_rtcc_convert			; Converts to dec with result in WREG
	movff	WREG,year

	; Place once/second tasks for ISR here (Be sure of the right bank!)
	banksel	common						; flag1 is in Bank1
	btfss	sleepmode					; in Sleepmode?
	call	get_ambient_level			; No, get ambient light level and set max_CCPR1L

	rcall	isr_battery_gauge			; Add amount of battery consumption to battery_gauge:6

	; update uptime
	banksel	uptime+0
	incf	uptime+0,F
	movlw	.0
	addwfc	uptime+1,F
	addwfc	uptime+2,F
	addwfc	uptime+3,F

	banksel	common						; flag1 is in Bank1
	bsf		onesecupdate				; A new second has begun
	btfsc	divemode					; in divemode?
	rcall	isr_divemode_1sec			; Yes, do some divemode stuff in bank common

	btfss	divemode					; in divemode?
	rcall	isr_update_lastdive_time	; No, update the lastdive timer

	tstfsz	secs						; secs == 0 ?
	return								; No, Done.

	bsf		oneminupdate				; A new minute has begun

	btfss	divemode					; In Divemode?
	rcall	check_nofly_desat_time		; No, so increase interval

	; Check if a new hour has just begun
	tstfsz	mins						; mins == 0?
	bra		isr_rtcc2					; No
	bsf		onehourupdate				; Yes, set flag

isr_rtcc2:
	banksel	isr_backup					; Back to Bank0 ISR data
	return								; Done.

isr_update_lastdive_time:				; called every second when not in divemode
	; update uptime
	banksel	lastdive_time+0
	incf	lastdive_time+0,F
	movlw	.0
	addwfc	lastdive_time+1,F
	addwfc	lastdive_time+2,F
	addwfc	lastdive_time+3,F
	banksel	common
	return

isr_battery_gauge:
	banksel	isr_backup					; Bank0 ISR data
	movlw	current_sleepmode			; 100ľA/3600 -> nAs	(Sleepmode current)
	movwf	isr1_temp					; Store value (low byte)
	clrf	isr2_temp					; High byte

	banksel	common						; flag1 is in Bank1
	btfss	sleepmode					; in Sleepmode?
	rcall	isr_battery_gauge2			; No, compute current consumption value into isr1_temp and isr2_temp

	banksel	isr_backup					; Bank0 ISR data
	movf	isr1_temp,W					; 48Bit add of isr1_temp and isr2_temp into battery_gauge:6
	addwf	battery_gauge+0,F
	movf	isr2_temp,W
	addwfc	battery_gauge+1,F
	movlw	.0
	addwfc	battery_gauge+2,F
	addwfc	battery_gauge+3,F
	addwfc	battery_gauge+4,F
	addwfc	battery_gauge+5,F
	return

isr_battery_gauge2:
	; set consumption rate in nAs for an one second interval
	; Example:
	; movlw	LOW  .55556					; 0,2A/3600*1e9s = nAs
	; movwf	isr1_temp					; Low byte
	; movlw	HIGH .55556					; 0,2A/3600*1e9s = nAs
	; movwf	isr2_temp					; High byte

	; Current consumption for LED backlight is 47*CCPR1L+272
	movf	CCPR1L,W
	mullw	current_backlight_multi
	movlw	LOW  current_backlight_offset
	addwf	PRODL,F
	movlw	HIGH current_backlight_offset
	addwfc	PRODH,F
	movff	PRODL,isr1_temp
	movff	PRODH,isr2_temp				; isr1_temp and isr2_temp hold value for backlight

	; Add current for CPU and GPU 
	; speed_setting=1: ECO (3,1mA -> 861nAs), =2: NORMAL (5,50mA -> 1528nAs) or =3: FASTEST (8,04mA -> 2233nAs)
	banksel	isr_backup					; Bank0 ISR data
	movlw	.1
	cpfseq	speed_setting
	bra		isr_battery_gauge3
	movlw	LOW  current_speed_eco
	addwf	isr1_temp,F
	movlw	HIGH current_speed_eco
	addwfc	isr2_temp,F
	bra		isr_battery_gauge5
isr_battery_gauge3:
	movlw	.2
	cpfseq	speed_setting
	bra		isr_battery_gauge4
	movlw	LOW  current_speed_normal
	addwf	isr1_temp,F
	movlw	HIGH current_speed_normal
	addwfc	isr2_temp,F
	bra		isr_battery_gauge5
isr_battery_gauge4:
	movlw	LOW  current_speed_fastest
	addwf	isr1_temp,F
	movlw	HIGH current_speed_fastest
	addwfc	isr2_temp,F
isr_battery_gauge5:
	; Add current if IR receiver is on
	btfss	ir_power					; IR enabled?
	bra		isr_battery_gauge6			; no
	movlw	LOW  current_ir_receiver
	addwf	isr1_temp,F
	movlw	HIGH current_ir_receiver
	addwfc	isr2_temp,F
isr_battery_gauge6:
	; Add current for compass/accelerometer
	btfss	compass_enabled				; compass active?
	bra		isr_battery_gauge7			; no
	movlw	LOW  current_compass
	addwf	isr1_temp,F
	movlw	HIGH current_compass
	addwfc	isr2_temp,F
isr_battery_gauge7:
	return

isr_divemode_1sec:
	incf	samplesecs,F				; "samplingrate" diving seconds done 
	decf	samplesecs_value,W			; holds "samplingrate" value (minus 1 into WREG)
	cpfsgt	samplesecs					; Done?
	bra		isr_divemode_1sec2			; no

	clrf	samplesecs					; clear counter...
	bsf		store_sample				; ...and set bit for profile storage
isr_divemode_1sec2:
	; Increase re-setable average depth divetime counter
	infsnz	average_divesecs+0,F		; increase stopwatch registers
	incf	average_divesecs+1,F		; increase stopwatch registers
	; Increase total divetime (Regardless of start_dive_threshold)
	infsnz	total_divetime_seconds+0,F
	incf	total_divetime_seconds+1,F	; Total dive time (Regardless of start_dive_threshold)

	btfss	divemode2					; displayed divetime is running?
	return								; No (e.g. too shallow)

	; increase divetime registers (Displayed dive time)
	incf	divesecs,F
	movlw	d'59'
	cpfsgt	divesecs
	bra		isr_divemode_1sec2a

	clrf	divesecs
	bsf		realdive					; this bit is always set (again) if the dive is longer then one minute
	infsnz	divemins+0,F
	incf	divemins+1,F				; increase divemins

isr_divemode_1sec2a:
	btfss	FLAG_apnoe_mode				; Are we in Apnoe mode?
	return								; No

	incf	apnoe_secs,F				; increase descent registers
	movlw	d'59'
	cpfsgt	apnoe_secs					; full minute?
	return								; No
	clrf	apnoe_secs
	incf	apnoe_mins,F				; increase descent mins
	return

;=============================================================================
; BCD to Binary conversion.
; Input: isr1_temp = Value in BCD
; Output WREG = value in binary.
isr_rtcc_convert:
	swapf	isr1_temp, W
	andlw	0x0F						; W = tens
	rlncf	WREG, W						; W = 2*tens
	subwf	isr1_temp, F				; 16*tens + ones - 2*tens
	subwf	isr1_temp, F				; 14*tens + ones - 2*tens
	subwf	isr1_temp, W				; 12*tens + ones - 2*tens
	return

;=============================================================================

isr_switch_right:
	bcf		INTCON,INT0IE				; Disable INT0
	banksel	common						; flag1 is in Bank1
	btfss	flip_screen					; 180° flipped?
	bsf		switch_right				; Set flag
	btfsc	flip_screen					; 180° flipped?
	bsf		switch_left					; Set flag
	bra		isr_switch_common			; Continue...

isr_switch_left:
	bcf		INTCON3,INT1IE				; Disable INT1
	banksel	common						; flag1 is in Bank1
	btfss	flip_screen					; 180° flipped?
	bsf		switch_left					; Set flag
	btfsc	flip_screen					; 180° flipped?
	bsf		switch_right				; Set flag
isr_switch_common:
	; load timer1 for first press
	clrf	TMR1L
	movlw	TMR1H_VALUE_FIRST			; in steps of 7,8125ms
	movwf	TMR1H
	bsf		T1CON,TMR1ON				; Start Timer 1
	banksel	isr_backup					; Select Bank0 for ISR data.
	bcf		INTCON3,INT1IF				; Clear flag
	bcf		INTCON,INT0IF				; Clear flag
	return

timer1int:
	bcf		PIR1,TMR1IF					; Clear flag
	banksel	common						; flag1 is in Bank1
	bcf		INTCON,INT0IF				; Clear flag
	bcf		INTCON3,INT1IF				; Clear flag
	; digital
	btfss	switch_left1				; Left button hold-down?
	bra		timer1int_left				; Yes
	btfss	switch_right2				; Right button hold-down?
	bra		timer1int_right				; Yes

	; Analog
	btfsc	analog_sw2_pressed			; Left button hold-down?
	bra		timer1int_left				; Yes
	btfsc	analog_sw1_pressed			; Right button hold-down?
	bra		timer1int_right				; Yes

	; No button hold-down, stop Timer 1
	bcf		T1CON,TMR1ON				; Stop Timer 1
	bsf		INTCON,INT0IE				; Enable INT0
	bsf		INTCON3,INT1IE				; Enable INT1
	return

timer1int_left:
	btfss	flip_screen					; 180° flipped?
	bsf		switch_left					; (Re-)Set flag
	btfsc	flip_screen					; 180° flipped?
	bsf		switch_right				; (Re-)Set flag
	bra		timer1int_common			; Continue
timer1int_right:
	btfss	flip_screen					; 180° flipped?
	bsf		switch_right				; Set flag
	btfsc	flip_screen					; 180° flipped?
	bsf		switch_left					; Set flag
timer1int_common:
	; load timer1 for next press
	clrf	TMR1L
	movlw	TMR1H_VALUE_CONT			; Surface mode
	btfsc	divemode
	movlw	TMR1H_VALUE_CONT_DIVE		; Dive mode
	movwf	TMR1H
	return								; Return from timer1int with timer1 kept running

;=============================================================================

check_nofly_desat_time:					; called every minute when not in divemode
	banksel	int_O_desaturation_time
	movf	int_O_desaturation_time+0,W	; Is Desat null ?
	iorwf	int_O_desaturation_time+1,W
	bz		check_nofly_desat_time_1	; yes...

	; int_O_desaturation_time is only computed while in start, surface mode, menue_tree or ghostwriter.
	; So the ISR may clock surface_interval past the actual surface interval time. But TFT_surface_lastdive
	; will check int_O_desaturation_time and in case int_O_desaturation_time is zero it will not show
	; surface_interval but lastdive_time instead. So this glitch remains invisible.

	; Increase surface interval timer
	banksel	common
	infsnz	surface_interval+0,F
	incf	surface_interval+1,F
	return								; Done

check_nofly_desat_time_1:
	banksel	common
	clrf	surface_interval+0
	clrf	surface_interval+1			; Clear surface interval timer
	return								; Done.

;=============================================================================

isr_restore_clock:
	banksel	isr_backup
	movlw	d'1'
	cpfseq	speed_setting
	bra		isr_restore_speed2
	; Reset to eco
	movlw	b'00000000'
	movwf	OSCTUNE						; 4x PLL Disable (Bit6) - only works with 8 or 16MHz (=32 or 64MHz)
	movlw	b'00110010'
	movwf	OSCCON						; 1MHz INTOSC
	movlw	T2CON_ECO
	movwf	T2CON
	bra		isr_restore_exit
isr_restore_speed2:
	movlw	d'2'
	cpfseq	speed_setting
	bra		isr_restore_speed3
	; Reset to normal
	movlw	b'01110010'
	movwf	OSCCON						; 16MHz INTOSC
	movlw	b'00000000'
	movwf	OSCTUNE						; 4x PLL Disable (Bit6) - only works with 8 or 16MHz (=32 or 64MHz)
	movlw	T2CON_NORMAL
	movwf	T2CON
	bra		isr_restore_exit

isr_restore_speed3:
	; Reset to fastest
	movlw	b'01110010'					; 16MHz INTOSC
	movwf	OSCCON
	movlw	b'01000000'
	movwf	OSCTUNE						; 4x PLL Enable (Bit6) - only works with 8 or 16MHz (=32 or 64MHz)
	movlw	T2CON_FASTEST
	movwf	T2CON
	;bra	isr_restore_exit

isr_restore_exit:
	btfss	OSCCON,HFIOFS
	bra		isr_restore_exit			; loop until PLL is stable
	return


restore_flash:							; Restore first flash page from eeprom
	banksel	common
	; Start address in internal flash
	movlw	0x00
	movwf	TBLPTRL
	movwf	TBLPTRH
	movwf	TBLPTRU

	movlw	b'10010100'					; Setup erase
	rcall	Write						; Write!

	movlw	.128
	movwf	lo							; Byte counter
	clrf	EEADR
	movlw	.3
	movwf	EEADRH						; Setup backup address

	TBLRD*-								; Dummy read to be in 128 byte block
restore_flash_loop:
	call	read_eeprom
	incf	EEADR,F
	movff	EEDATA,TABLAT				; put 1 byte
	tblwt+*								; Table Write with Pre-Increment
	decfsz	lo,F						; 128byte done?
	bra		restore_flash_loop			; No

	movlw	b'10000100'					; Setup writes
	rcall	Write						; Write!

	reset								; Done, reset CPU

Write:
	movwf	EECON1						; Type of memory to write in
	movlw	0x55
	movwf	EECON2
	movlw	0xAA
	movwf	EECON2
	bsf		EECON1,WR					; Write
	nop
	nop
	return

	END