view src/ghostwriter.asm @ 278:dfac47ac2e1d

BUGFIX: There was a 1:4096 chance that a portion of a dive was not stored correctly resulting in download issues
author heinrichsweikamp
date Mon, 18 May 2015 21:25:56 +0200
parents 653a3ab08062
children 62c7af4795b0
line wrap: on
line source

;=============================================================================
;
;   File ghostwriter.asm
;
;   Ghostwriter (Log profile recorder)
;
;   Copyright (c) 2011, JD Gascuel, HeinrichsWeikamp, all right reserved.
;=============================================================================
; HISTORY
;  2011-11-27 : [mH] Creation

#include    "hwos.inc"                  ; Mandatory header
#include 	"shared_definitions.h"         ; Mailbox from/to p2_deco.c
#include	"external_flash.inc"
#include	"surfmode.inc"
#include    "eeprom_rs232.inc"
#include 	"strings.inc"
#include	"isr.inc"
#include	"tft_outputs.inc"
#include	"divemode.inc"
#include    "rtc.inc"

ghostwriter	CODE

	global	store_dive_data
store_dive_data:						; 5 seconds gone
	bcf		store_sample				; update only any 5 seconds

    ifndef __DEBUG
    	btfsc	simulatormode_active    ; Are we in simulator mode?
    	return                          ; Yes, discard everything
    endif

    btfsc	FLAG_apnoe_mode             ; In Apnoe mode?
    return                              ; Yes, discard everything

    SAFE_2BYTE_COPY rel_pressure, lo
	movf	lo,W				        ; store depth with every sample
	rcall   ghostwrite_byte_profile     ; WREG -> Profile in ext. Flash
	movf	hi,W
	rcall   ghostwrite_byte_profile     ; WREG -> Profile in ext. Flash

;First, find out how many bytes will append to this sample....
	clrf	ProfileFlagByte					; clear number of bytes to append

; Check Extented informations
	decfsz	divisor_temperature,W	; Check divisor
	bra		check_extended1		
	movlw	infolength_temperature
	addwf	ProfileFlagByte,F	; add to ProfileFlagByte
check_extended1:
	decfsz	divisor_deco,W		; Check divisor
	bra		check_extended2		
	movlw	infolength_deco
	addwf	ProfileFlagByte,F	; add to ProfileFlagByte
check_extended2:
	decfsz	divisor_gf,W		; Check divisor
	bra		check_extended3		
	movlw	infolength_gf
	addwf	ProfileFlagByte,F	; add to ProfileFlagByte
check_extended3:
	decfsz	divisor_ppo2_sensors,W		; Check divisor
	bra		check_extended4		
	movlw	infolength_ppo2_sensors
	addwf	ProfileFlagByte,F	; add to ProfileFlagByte
check_extended4:
	decfsz	divisor_decoplan,W     ; Check divisor
	bra		check_extended5		
	movlw	infolength_decoplan
	addwf	ProfileFlagByte,F	; add to ProfileFlagByte
check_extended5:
	decfsz	divisor_cns,W		; Check divisor
	bra		check_extended6		
	movlw	infolength_cns
	addwf	ProfileFlagByte,F	; add to ProfileFlagByte
check_extended6:
	decfsz	divisor_tank,W		; Check divisor
	bra		check_extended7
	movlw	infolength_tank
	addwf	ProfileFlagByte,F	; add to ProfileFlagByte
check_extended7:

; Second, check global event flag
	btfss	event_occured		; Check global event flag
	bra		store_dive_data3	; No Event

	incf    ProfileFlagByte,F	; add one byte (The EventByte)

	clrf	EventByte			; reset EventByte
    clrf	EventByte2			; reset EventByte2

	movf	AlarmType,W			; Type of Alarm Bit 0-3
	addwf	EventByte,F			; Copy to EventByte Bit 0-3
	clrf	AlarmType			; Reset AlarmType
	
; Third, check events and add aditional bytes
	btfss	gas6_changed    	; Check flag
	bra		check_event2
	movlw	d'2'				; Information length
	addwf	ProfileFlagByte,F	; add to ProfileFlagByte
	bsf		EventByte,4			; Also set Flag in EventByte!
check_event2:
	btfss	stored_gas_changed	; Check flag
	bra		check_event3
	movlw	d'1'				; Information length
	addwf	ProfileFlagByte,F	; add to ProfileFlagByte
	bsf		EventByte,5			; Also set Flag in EventByte!
check_event3:
    btfss	setpoint_changed	; Check flag
	bra		check_event4
	movlw	d'1'				; Information length
	addwf	ProfileFlagByte,F	; add to ProfileFlagByte
	bsf		EventByte,6			; Also set Flag in EventByte!
check_event4:
    btfss   bailoutgas_event    ; =1: bailout was selected or a gaschange during bailout
    bra     check_event5
	movlw	d'2'				; Information length
	addwf	ProfileFlagByte,F	; add to ProfileFlagByte
	bsf		EventByte2,0		; set flag in EventByte2!
    bsf     EventByte,7			; =1: Another Eventbyte is available

check_event5:
	; more events?

store_dive_data3:
    btfsc   EventByte,7                 ; =1: Another Eventbyte is available
    incf    ProfileFlagByte,F           ; add one byte (The EventByte2)

    btfsc	event_occured               ; Check global event flag
	bsf		ProfileFlagByte,7           ; Set EventByte Flag in ProfileFlagByte

	movf	ProfileFlagByte,W           ; finally, write ProfileFlagByte!
	rcall   ghostwrite_byte_profile     ; WREG -> Profile in ext. Flash

	btfss	event_occured               ; Check global event flag (again)
	bra		store_dive_data4            ; No Event

; Store the EventByte(s) + additional bytes now
	movf	EventByte,W		
	rcall   ghostwrite_byte_profile     ; WREG -> Profile in ext. Flash

    movf    EventByte2,W                ; Write second event byte...
    btfsc   EventByte,7                 ; =1: Another Eventbyte is available
    rcall   ghostwrite_byte_profile     ; WREG -> Profile in ext. Flash

	btfss	gas6_changed                ; Check flag
	bra		store_dive_data3b
    movff   char_I_O2_ratio,WREG
	rcall   ghostwrite_byte_profile     ; WREG -> Profile in ext. Flash
    movff   char_I_He_ratio,WREG
	rcall   ghostwrite_byte_profile     ; WREG -> Profile in ext. Flash
	bcf		gas6_changed    	; Clear this event
store_dive_data3b:
	btfss	stored_gas_changed	; Check flag
	bra		store_dive_data3c
	movf	active_gas,W		; Store active gas
	rcall   ghostwrite_byte_profile      ; WREG -> Profile in ext. Flash
	bcf		stored_gas_changed	; Clear this event
store_dive_data3c:
	btfss	setpoint_changed	; Check flag
	bra		store_dive_data3d
	movff	char_I_const_ppO2,WREG
	rcall   ghostwrite_byte_profile      ; WREG -> Profile in ext. Flash
	bcf		setpoint_changed	; Clear this event
store_dive_data3d:
	btfss	bailoutgas_event	; Check flag
	bra		store_dive_data3e
    movff   char_I_O2_ratio,WREG
	rcall   ghostwrite_byte_profile      ; WREG -> Profile in ext. Flash
    movff   char_I_He_ratio,WREG
	rcall   ghostwrite_byte_profile      ; WREG -> Profile in ext. Flash
	bcf		bailoutgas_event	; Clear this event
store_dive_data3e:

store_dive_data4:

; Store extended informations
	decfsz	divisor_temperature,F	; Check divisor
	bra		store_extended1	
	rcall	store_dive_temperature
store_extended1:
	decfsz	divisor_deco,F			; Check divisor
	bra		store_extended2	
	rcall	store_dive_decodata
store_extended2:
	decfsz	divisor_gf,F			; Check divisor
	bra		store_extended3	
	rcall	store_dive_gf
store_extended3:
	decfsz	divisor_ppo2_sensors,F	; Check divisor
	bra		store_extended4	
	rcall	store_dive_ppO2_sensors
store_extended4:
	decfsz	divisor_decoplan,F		; Check divisor
	bra		store_extended5	
	rcall	store_dive_decoplan
store_extended5:
	decfsz	divisor_cns,F			; Check divisor
	bra		store_extended6	
	rcall	store_dive_cns
store_extended6:
	decfsz	divisor_tank,F			; Check divisor
	bra		store_extended7
	rcall	store_dive_tank
store_extended7:

; The next block is required to take care of "store never"
	btfsc	divisor_temperature,7	; Test highest Bit (Register must have been zero before the "decfsz" command!)
	clrf	divisor_temperature		; And clear register again, so it will never reach zero...
	btfsc	divisor_deco,7
	clrf	divisor_deco
	btfsc	divisor_gf,7
	clrf	divisor_gf
	btfsc	divisor_ppo2_sensors,7
	clrf	divisor_ppo2_sensors
	btfsc	divisor_decoplan,7
	clrf	divisor_decoplan
	btfsc	divisor_cns,7
	clrf	divisor_cns
	btfsc	divisor_tank,7
	clrf	divisor_tank

store_dive_data5:
	bcf		event_occured		; Clear the global event flag
	clrf	EventByte			; reset EventByte
    clrf	EventByte2			; reset EventByte2
	return						; Done. (Sample with all informations written to external flash)
	
store_dive_cns:
	movff	int_O_CNS_fraction+0,WREG
	rcall   ghostwrite_byte_profile      ; WREG -> Profile in ext. Flash
	movff	int_O_CNS_fraction+1,WREG
	rcall   ghostwrite_byte_profile      ; WREG -> Profile in ext. Flash
	movlw	div_cns
	movwf	divisor_cns						; Reload divisor from CF
	return

store_dive_tank:
	movlw	div_tank
	movwf	divisor_tank						; Reload divisor from CF
	return

store_dive_decoplan:
    ; Store the decoplan
    lfsr    FSR1,char_O_deco_time_for_log+.0
    movlw   .15
    movwf   lo
store_dive_decoplan_loop:
    movf    POSTINC1,W
    rcall   ghostwrite_byte_profile      ; WREG -> Profile in ext. Flash
    decfsz  lo,F
    bra     store_dive_decoplan_loop
	movlw	div_decoplan
	movwf	divisor_decoplan             ; Reload divisor from CF
	return

store_dive_ppO2_sensors:
    movf    o2_ppo2_sensor1,W            ; Sensor1 ppO2 (in 0.01bar steps)
	rcall   ghostwrite_byte_profile      ; WREG -> Profile in ext. Flash
    SAFE_2BYTE_COPY o2_mv_sensor1,lo     ; o2_mv_sensor may be modifified via ISR during the two writes here...
    movf    lo,W                         ; in 0.1mV steps
	rcall   ghostwrite_byte_profile      ; WREG -> Profile in ext. Flash
    movf    hi,W                         ; in 0.1mV steps
	rcall   ghostwrite_byte_profile      ; WREG -> Profile in ext. Flash

    movf    o2_ppo2_sensor2,W            ; Sensor2 ppO2 (in 0.01bar steps)
	rcall   ghostwrite_byte_profile      ; WREG -> Profile in ext. Flash
    SAFE_2BYTE_COPY o2_mv_sensor2,lo     ; o2_mv_sensor may be modifified via ISR during the two writes here...
    movf    lo,W                         ; in 0.1mV steps
	rcall   ghostwrite_byte_profile      ; WREG -> Profile in ext. Flash
    movf    hi,W                         ; in 0.1mV steps
	rcall   ghostwrite_byte_profile      ; WREG -> Profile in ext. Flash

    movf    o2_ppo2_sensor3,W            ; Sensor3 ppO2 (in 0.01bar steps)
	rcall   ghostwrite_byte_profile      ; WREG -> Profile in ext. Flash
    SAFE_2BYTE_COPY o2_mv_sensor3,lo     ; o2_mv_sensor may be modifified via ISR during the two writes here...
    movf    lo,W                         ; in 0.1mV steps
	rcall   ghostwrite_byte_profile      ; WREG -> Profile in ext. Flash
    movf    hi,W                         ; in 0.1mV steps
	rcall   ghostwrite_byte_profile      ; WREG -> Profile in ext. Flash

	movlw	div_ppo2_sensors
	movwf	divisor_ppo2_sensors        ; Reload divisor
	return

store_dive_gf:
	movff	char_O_gradient_factor,WREG		; gradient factor absolute
	rcall   ghostwrite_byte_profile      ; WREG -> Profile in ext. Flash
	movlw	div_gf
	movwf	divisor_gf						; Reload divisor
	return

store_dive_decodata:
	movf	decodata+0,W					; =0:no stop dive, if in deco mode: ceiling in m
	rcall   ghostwrite_byte_profile      ; WREG -> Profile in ext. Flash
	movf	decodata+1,W					; no stop time of length of first stop
	rcall   ghostwrite_byte_profile      ; WREG -> Profile in ext. Flash
	movlw	div_deco
	movwf	divisor_deco					; Reload divisor
	return

store_dive_temperature:
    SAFE_2BYTE_COPY temperature,lo
	movf	lo,W			            	; append temperature to current sample!
	rcall   ghostwrite_byte_profile      ; WREG -> Profile in ext. Flash
	movf	hi,W
	rcall   ghostwrite_byte_profile      ; WREG -> Profile in ext. Flash
	movlw	div_temperature
	movwf	divisor_temperature				; Reload divisor
	return

ghostwrite_byte_header:
	goto	write_byte_ext_flash_plus_header	; (This call will also delete the 4kB TOC entry first)
    ; returns...

ghostwrite_byte_profile:
    goto    write_byte_ext_flash_plus	; writes byte and increases address with banking at 0x200000
    ; returns...

	global	ghostwriter_end_dive
ghostwriter_end_dive:
	movff	ext_flash_address+0,ext_flash_log_pointer+0
	movff	ext_flash_address+1,ext_flash_log_pointer+1
	movff	ext_flash_address+2,ext_flash_log_pointer+2	; Save end-of-profile pointer to store in header

    movff   menupos3,customview_divemode            ; store last customview

	btfss	realdive					; dive longer then one minute
	goto	ghostwriter_end_dive_common				; No, discard everything

; In DEBUG compile, keep all simulated dives in logbook, Desat time, nofly, etc...
    ifndef __DEBUG
    	btfsc	simulatormode_active		; Are we in simulator mode?
    	goto	ghostwriter_end_dive_common_sim		; Yes, discard everything
    endif

    btfsc	FLAG_apnoe_mode                         ; In Apnoe mode?
    goto	ghostwriter_end_dive_common				; Yes, discard everything

	; Dive finished (and longer then one minute)

	btfsc	FLAG_apnoe_mode					; Calc max. depth (again) for very short apnoe dives
	call	apnoe_calc_maxdepth

	; calculate desaturation time
	movff	last_surfpressure_30min+0,int_I_pres_surface+0          ; Pass surface to desat routine !
	movff	last_surfpressure_30min+1,int_I_pres_surface+1

	call	deco_calc_desaturation_time ; calculate desaturation time
	movlb	b'00000001'                 ; select ram bank 1
	movff	int_O_desaturation_time+0, desaturation_time+0
	movff	int_O_desaturation_time+1, desaturation_time+1	; Buffer
    call	calc_deko_surfmode
	rcall	calculate_noflytime         ; Calc NoFly time

										; store header and ...
	movlw	0xFD						; .... End-of-Profile Bytes
	rcall   ghostwrite_byte_profile      ; WREG -> Profile in ext. Flash
	movlw	0xFD
	rcall   ghostwrite_byte_profile      ; WREG -> Profile in ext. Flash
	movff	ext_flash_address+0,ext_flash_log_pointer+0
	movff	ext_flash_address+1,ext_flash_log_pointer+1
	movff	ext_flash_address+2,ext_flash_log_pointer+2	; Save end-of-profile pointer to store in header

    ; Set to first address again to store dive length ext_flash_dive_counter:3
    rcall   ghostwriter_load_pointer        ; Load ext_flash_address:3 from EEPROM .4-.6

    incf_ext_flash_address_0x20	d'6'        ; Skip internal "0xFA 0xFA #Divenumber:2 0xFA 0xFA" Header
    ; Store dive length
    movf   ext_flash_dive_counter+0,W
	call    write_byte_ext_flash_plus_nodel ; WREG -> Profile in ext. flash (No ext_flash_dive_counter:3 increase) and does NOT delete 4kB page
    movf   ext_flash_dive_counter+1,W
	call    write_byte_ext_flash_plus_nodel ; WREG -> Profile in ext. flash (No ext_flash_dive_counter:3 increase) and does NOT delete 4kB page
    movf   ext_flash_dive_counter+2,W
	call    write_byte_ext_flash_plus_nodel ; WREG -> Profile in ext. flash (No ext_flash_dive_counter:3 increase) and does NOT delete 4kB page

; profile recording done.

	; Load total number of dives
	read_int_eeprom .2
	movff	EEDATA,lo
	read_int_eeprom .3
	movff	EEDATA,hi
	; +1                        increase total dive counter
    infsnz  lo,F
	incf	hi,F
	; Store new number in EEPROM
	movff	lo,EEDATA
	write_int_eeprom	.2
	movff	hi,EEDATA
	write_int_eeprom	.3

	decf	lo,F		; -1
	; Set ext_flash_address:3 to TOC entry of this dive
	; 1st: 200000h-200FFFh -> lo=0
	; 2nd: 201000h-201FFFh -> lo=1
	; 3rd: 202000h-202FFFh -> lo=2
	; 255: 2FF000h-2FFFFFh -> lo=255

	clrf	ext_flash_address+0
	clrf	ext_flash_address+1
	movlw	0x20
	movwf	ext_flash_address+2
	movlw	.16
	mulwf	lo							; lo*16 = offset to 0x2000 (up:hi)
	movf	PRODL,W
	addwf	ext_flash_address+1,F
	movf	PRODH,W
	addwfc	ext_flash_address+2,F
	
; Now, write header

	movlw	0xFA						; Header start
    rcall   ghostwrite_byte_header  ; (This call will also delete the 4kB TOC entry first)
	movlw	0xFA
	rcall	ghostwrite_byte_header	; WREG -> Header in ext. flash

	; store pointer to begin of diveprofile
	read_int_eeprom	.4
	movf	EEDATA,W
	rcall	ghostwrite_byte_header	; WREG -> Header in ext. flash
	read_int_eeprom	.5
	movf	EEDATA,W
	rcall	ghostwrite_byte_header	; WREG -> Header in ext. flash
	read_int_eeprom	.6
	movf	EEDATA,W
	rcall	ghostwrite_byte_header	; WREG -> Header in ext. flash

		; store pointer to end of diveprofile
	movf	ext_flash_log_pointer+0,W
	rcall	ghostwrite_byte_header	; WREG -> Header in ext. flash
	movf	ext_flash_log_pointer+1,W
	rcall	ghostwrite_byte_header	; WREG -> Header in ext. flash
	movf	ext_flash_log_pointer+2,W
	rcall	ghostwrite_byte_header	; WREG -> Header in ext. flash

	; write rest of header
	movlw	logbook_profile_version     ; Defined in hwos.inc
	rcall	ghostwrite_byte_header	; WREG -> Header in ext. flash

    ; Store dive length
    movf    ext_flash_dive_counter+0,W
	rcall	ghostwrite_byte_header	; WREG -> Header in ext. flash
    movf    ext_flash_dive_counter+1,W
	rcall	ghostwrite_byte_header	; WREG -> Header in ext. flash
    movf    ext_flash_dive_counter+2,W
	rcall	ghostwrite_byte_header	; WREG -> Header in ext. flash

	movf	year,W                     ; Date
	rcall	ghostwrite_byte_header	; WREG -> Header in ext. flash
	movf	month,W
	rcall	ghostwrite_byte_header	; WREG -> Header in ext. flash
	movf	day,W
	rcall	ghostwrite_byte_header	; WREG -> Header in ext. flash
	movf	hours,W						; End of dive time
	rcall	ghostwrite_byte_header	; WREG -> Header in ext. flash
	movf	mins,W
	rcall	ghostwrite_byte_header	; WREG -> Header in ext. flash

	btfss	FLAG_apnoe_mode				; Store apnoe max or normal max (Which is only max from the last descent)
	bra		end_dive1					; Store normal depth

	movff	apnoe_max_pressure+0,lo
	movff	apnoe_max_pressure+1,hi
	call	adjust_depth_with_salinity	; computes salinity setting into lo:hi [mbar]
	movff	lo,apnoe_max_pressure+0
	movff	hi,apnoe_max_pressure+1
	
	movf	apnoe_max_pressure+0,W		; Max. depth
	rcall	ghostwrite_byte_header	; WREG -> Header in ext. flash
	movf	apnoe_max_pressure+1,W
	rcall	ghostwrite_byte_header	; WREG -> Header in ext. flash
	bra		end_dive2					; skip normal max. depth
		
end_dive1:
	movff	max_pressure+0,lo
	movff	max_pressure+1,hi
	call	adjust_depth_with_salinity	; computes salinity setting into lo:hi [mbar]
	movff	lo,max_pressure+0
	movff	hi,max_pressure+1
	
	movff	max_pressure+0,WREG			; Max. depth
	rcall	ghostwrite_byte_header	; WREG -> Header in ext. flash
	movff	max_pressure+1,WREG
	rcall	ghostwrite_byte_header	; WREG -> Header in ext. flash

end_dive2:
	movf	divemins+0,W            ; divetime minutes
	rcall	ghostwrite_byte_header	; WREG -> Header in ext. flash
	movf	divemins+1,W
	rcall	ghostwrite_byte_header	; WREG -> Header in ext. flash
	movf	divesecs,W				; divetime seconds
	rcall	ghostwrite_byte_header	; WREG -> Header in ext. flash
	movff	minimum_temperature+0,WREG			; minimum temperature
	rcall	ghostwrite_byte_header	; WREG -> Header in ext. flash
	movff	minimum_temperature+1,WREG		
	rcall	ghostwrite_byte_header	; WREG -> Header in ext. flash
	movff	last_surfpressure_30min+0,WREG		; airpressure before dive
	rcall	ghostwrite_byte_header	; WREG -> Header in ext. flash
	movff	last_surfpressure_30min+1,WREG		
	rcall	ghostwrite_byte_header	; WREG -> Header in ext. flash
	movff	int_O_desaturation_time+0,WREG		; desaturation time in minutes
	rcall	ghostwrite_byte_header	; WREG -> Header in ext. flash
	movff	int_O_desaturation_time+1,WREG
	rcall	ghostwrite_byte_header	; WREG -> Header in ext. flash

    btfss   FLAG_ccr_mode           ; In CCR mode...
    bra     end_dive_oc_gaslist     ; No, write OC gases
    ; Write Diluents...
	movff	opt_dil_O2_ratio+0,WREG
	rcall	ghostwrite_byte_header	; %O2
	movff	opt_dil_He_ratio+0,WREG
	rcall	ghostwrite_byte_header	; %He
	movff	char_I_dil_change+0,WREG
	rcall	ghostwrite_byte_header	; Configured change depth in m
    movff   opt_dil_type+0,WREG                   
    rcall	ghostwrite_byte_header	; 0=Disabled, 1=First, 2=Normal

	movff	opt_dil_O2_ratio+1,WREG
	rcall	ghostwrite_byte_header	; %O2
	movff	opt_dil_He_ratio+1,WREG
	rcall	ghostwrite_byte_header	; %He
	movff	char_I_dil_change+1,WREG
	rcall	ghostwrite_byte_header	; Configured change depth in m
    movff   opt_dil_type+1,WREG
    rcall	ghostwrite_byte_header	; 0=Disabled, 1=First, 2=Normal

	movff	opt_dil_O2_ratio+2,WREG
	rcall	ghostwrite_byte_header	; %O2
	movff	opt_dil_He_ratio+2,WREG
	rcall	ghostwrite_byte_header	; %He
	movff	char_I_dil_change+2,WREG
	rcall	ghostwrite_byte_header	; Configured change depth in m
    movff   opt_dil_type+2,WREG
    rcall	ghostwrite_byte_header	; 0=Disabled, 1=First, 2=Normal

	movff	opt_dil_O2_ratio+3,WREG
	rcall	ghostwrite_byte_header	; %O2
	movff	opt_dil_He_ratio+3,WREG
	rcall	ghostwrite_byte_header	; %He
	movff	char_I_dil_change+3,WREG
	rcall	ghostwrite_byte_header	; Configured change depth in m
    movff   opt_dil_type+3,WREG
    rcall	ghostwrite_byte_header	; 0=Disabled, 1=First, 2=Normal

	movff	opt_dil_O2_ratio+4,WREG
	rcall	ghostwrite_byte_header	; %O2
	movff	opt_dil_He_ratio+4,WREG
	rcall	ghostwrite_byte_header	; %He
	movff	char_I_dil_change+4,WREG
	rcall	ghostwrite_byte_header	; Configured change depth in m
    movff   opt_dil_type+4,WREG
    rcall	ghostwrite_byte_header	; 0=Disabled, 1=First, 2=Normal
    bra     end_dive_oc_cc_common

end_dive_oc_gaslist:            	; OC Gases...
	movff	opt_gas_O2_ratio+0,WREG
	rcall	ghostwrite_byte_header	; %O2
	movff	opt_gas_He_ratio+0,WREG
	rcall	ghostwrite_byte_header	; %He
	movff	opt_OC_bail_gas_change+0,WREG
	rcall	ghostwrite_byte_header	; Configured change depth in m
    movff   opt_gas_type+0,WREG                   
    rcall	ghostwrite_byte_header	; 0=Disabled, 1=First, 2= Travel, 3= Deco

	movff	opt_gas_O2_ratio+1,WREG
	rcall	ghostwrite_byte_header	; %O2
	movff	opt_gas_He_ratio+1,WREG
	rcall	ghostwrite_byte_header	; %He
	movff	opt_OC_bail_gas_change+1,WREG
	rcall	ghostwrite_byte_header	; Configured change depth in m
    movff   opt_gas_type+1,WREG
    rcall	ghostwrite_byte_header	; 0=Disabled, 1=First, 2= Travel, 3= Deco

	movff	opt_gas_O2_ratio+2,WREG
	rcall	ghostwrite_byte_header	; %O2
	movff	opt_gas_He_ratio+2,WREG
	rcall	ghostwrite_byte_header	; %He
	movff	opt_OC_bail_gas_change+2,WREG
	rcall	ghostwrite_byte_header	; Configured change depth in m
    movff   opt_gas_type+2,WREG
    rcall	ghostwrite_byte_header	; 0=Disabled, 1=First, 2= Travel, 3= Deco

	movff	opt_gas_O2_ratio+3,WREG
	rcall	ghostwrite_byte_header	; %O2
	movff	opt_gas_He_ratio+3,WREG
	rcall	ghostwrite_byte_header	; %He
	movff	opt_OC_bail_gas_change+3,WREG
	rcall	ghostwrite_byte_header	; Configured change depth in m
    movff   opt_gas_type+3,WREG
    rcall	ghostwrite_byte_header	; 0=Disabled, 1=First, 2= Travel, 3= Deco

	movff	opt_gas_O2_ratio+4,WREG
	rcall	ghostwrite_byte_header	; %O2
	movff	opt_gas_He_ratio+4,WREG
	rcall	ghostwrite_byte_header	; %He
	movff	opt_OC_bail_gas_change+4,WREG
	rcall	ghostwrite_byte_header	; Configured change depth in m
    movff   opt_gas_type+4,WREG
    rcall	ghostwrite_byte_header	; 0=Disabled, 1=First, 2= Travel, 3= Deco
;    bra     end_dive_oc_cc_common

end_dive_oc_cc_common:
	movlw	softwareversion_x			; Firmware version
	rcall	ghostwrite_byte_header
	movlw	softwareversion_y
	rcall	ghostwrite_byte_header
	movf	batt_voltage+0,W			; Battery voltage 
	rcall	ghostwrite_byte_header
	movf	batt_voltage+1,W
	rcall	ghostwrite_byte_header

	movf    samplingrate,W			; Sampling rate
    btfsc	FLAG_apnoe_mode         ; Apnoe mode?
	movlw	samplingrate_apnoe		; Apnoe sampling rate
	rcall	ghostwrite_byte_header	; WREG -> Header in ext. flash

    ; CNS at beginning of dive
	movff	CNS_start+0,WREG
    rcall	ghostwrite_byte_header	; WREG -> Header in ext. flash
    movff	CNS_start+1,WREG
    rcall	ghostwrite_byte_header	; WREG -> Header in ext. flash
    ; Gradient factor
    movff	GF_start,WREG
    rcall	ghostwrite_byte_header	; WREG -> Header in ext. flash
    movff   char_O_relative_gradient_GF,WREG
    rcall	ghostwrite_byte_header	; WREG -> Header in ext. flash

    ; Logbook offset
    call    do_logoffset_common_read; Read into lo:hi
    movf    lo,W
    rcall	ghostwrite_byte_header	; WREG -> Header in ext. flash
    movf    hi,W
    rcall	ghostwrite_byte_header	; WREG -> Header in ext. flash

    ; Spare at Byte 59
    movlw   0xFF
    rcall	ghostwrite_byte_header	; WREG -> Header in ext. flash
    ; Store 5 Setpoints
    movff   char_I_setpoint_cbar+0,WREG
    rcall	ghostwrite_byte_header	; Setpoint in cbar
    movff   char_I_setpoint_change+0,WREG
    rcall	ghostwrite_byte_header	; Change depth
    movff   char_I_setpoint_cbar+1,WREG
    rcall	ghostwrite_byte_header	; Setpoint in cbar
    movff   char_I_setpoint_change+1,WREG
    rcall	ghostwrite_byte_header	; Change depth
    movff   char_I_setpoint_cbar+2,WREG
    rcall	ghostwrite_byte_header	; Setpoint in cbar
    movff   char_I_setpoint_change+2,WREG
    rcall	ghostwrite_byte_header	; Change depth
    movff   char_I_setpoint_cbar+3,WREG
    rcall	ghostwrite_byte_header	; Setpoint in cbar
    movff   char_I_setpoint_change+3,WREG
    rcall	ghostwrite_byte_header	; Change depth
    movff   char_I_setpoint_cbar+4,WREG
    rcall	ghostwrite_byte_header	; Setpoint in cbar
    movff   char_I_setpoint_change+4,WREG
    rcall	ghostwrite_byte_header	; Change depth

    movff   opt_salinity,WREG       ; Salinity (0-4%)
	rcall	ghostwrite_byte_header	; Store Salinity to Dive

	movff	int_O_CNS_fraction+0,WREG		; copy into bank1
    rcall	ghostwrite_byte_header; Stores CNS%
    movff	int_O_CNS_fraction+1,WREG		; copy into bank1
	rcall	ghostwrite_byte_header; Stores CNS%

	movff	avr_rel_pressure_total+0,WREG	; Average Depth
	rcall	ghostwrite_byte_header	; WREG -> Header in ext. flash
	movff	avr_rel_pressure_total+1,WREG	; Average Depth
	rcall	ghostwrite_byte_header	; WREG -> Header in ext. flash

	movff	total_divetime_seconds+0,WREG	; Total dive time (Regardless of start_dive_threshold)
	rcall	ghostwrite_byte_header	; WREG -> Header in ext. flash
	movff	total_divetime_seconds+1,WREG	; Total dive time (Regardless of start_dive_threshold)
	rcall	ghostwrite_byte_header	; WREG -> Header in ext. flash

	movff	char_I_GF_Low_percentage,WREG	; GF_lo
	movff	char_I_deco_model,lo
	decfsz	lo,F							; jump over next line if char_I_deco_model == 1
	movff	char_I_saturation_multiplier,WREG ; Saturation Multiplier
	rcall	ghostwrite_byte_header	; WREG -> Header in ext. flash

	movff	char_I_GF_High_percentage,WREG	; GF_hi
	movff	char_I_deco_model,lo
	decfsz	lo,F							; jump over next line if char_I_deco_model == 1
	movff	char_I_desaturation_multiplier,WREG ; Desaturation Multiplier
	rcall	ghostwrite_byte_header	; WREG -> Header in ext. flash

	movff	char_I_deco_model,WREG			; 0 = ZH-L16, 1 = ZH-L16-GF
	rcall	ghostwrite_byte_header; writes byte and increases address (no banking)

	read_int_eeprom	.2
	movf	EEDATA,W
	rcall	ghostwrite_byte_header  ; Total dive counter, low
	read_int_eeprom	.3
	movf	EEDATA,W
	rcall	ghostwrite_byte_header  ; Total dive counter, high

    movff   opt_dive_mode,WREG
	rcall	ghostwrite_byte_header  ; 0=OC, 1=CC, 2=Gauge, 3=Apnea

;   Store all tissue data available
    movlw   .16
    movwf   lo
    lfsr    FSR1,char_O_tissue_N2_saturation+0
end_dive_store_tissues_N2:
    movf    POSTINC1,W
    rcall	ghostwrite_byte_header      ; WREG -> Header in ext. flash
    decfsz  lo,F
    bra     end_dive_store_tissues_N2   ; No

    movlw   .64
    movwf   lo
    lfsr    FSR1,0x700;pres_tissue_N2+0       ; 16*4Byte Float = 64Bytes
end_dive_store_tissues_N2_2:
    movf    POSTINC1,W
    rcall	ghostwrite_byte_header      ; WREG -> Header in ext. flash
    decfsz  lo,F
    bra     end_dive_store_tissues_N2_2 ; No

    movlw   .16
    movwf   lo
    lfsr    FSR1,char_O_tissue_He_saturation+0
end_dive_store_tissues_He:
    movf    POSTINC1,W
    rcall	ghostwrite_byte_header      ; WREG -> Header in ext. flash
    decfsz  lo,F
    bra     end_dive_store_tissues_He   ; No

    movlw   .64
    movwf   lo
    lfsr    FSR1,0x740;pres_tissue_He+0       ; 16*4Byte Float = 64Bytes
end_dive_store_tissues_He_2:
    movf    POSTINC1,W
    rcall	ghostwrite_byte_header      ; WREG -> Header in ext. flash
    decfsz  lo,F
    bra     end_dive_store_tissues_He_2 ; No

    ; Some deco stuff
    movff   char_I_depth_last_deco,WREG ; last stop [m]
	rcall	ghostwrite_byte_header      ; WREG -> Header in ext. flash
    movff   char_I_deco_distance,WREG   ; assumed distance to shown stop
	rcall	ghostwrite_byte_header      ; WREG -> Header in ext. flash

    ; Last HUD data
    movff   hud_battery_mv+0,WREG       ; Last HUD battery value
	rcall	ghostwrite_byte_header      ; WREG -> Header in ext. flash
    movff   hud_battery_mv+1,WREG       ; Last HUD battery value
	rcall	ghostwrite_byte_header      ; WREG -> Header in ext. flash
    movff   hud_status_byte,WREG        ; Last HUD status
	rcall	ghostwrite_byte_header      ; WREG -> Header in ext. flash

    ; Battery gauge registers [nAs]
    movff   battery_gauge+0,WREG        ; Battery gauge register
	rcall	ghostwrite_byte_header      ; WREG -> Header in ext. flash
    movff   battery_gauge+1,WREG        ; Battery gauge register
	rcall	ghostwrite_byte_header      ; WREG -> Header in ext. flash
    movff   battery_gauge+2,WREG        ; Battery gauge register
	rcall	ghostwrite_byte_header      ; WREG -> Header in ext. flash
    movff   battery_gauge+3,WREG        ; Battery gauge register
	rcall	ghostwrite_byte_header      ; WREG -> Header in ext. flash
    movff   battery_gauge+4,WREG        ; Battery gauge register
	rcall	ghostwrite_byte_header      ; WREG -> Header in ext. flash
    movff   battery_gauge+5,WREG        ; Battery gauge register
	rcall	ghostwrite_byte_header      ; WREG -> Header in ext. flash

    ; Header stop
	movlw	0xFB
	rcall	ghostwrite_byte_header	; WREG -> Header in ext. flash
	movlw	0xFB
	rcall	ghostwrite_byte_header	; WREG -> Header in ext. flash
	
	call	divemode_store_statistics		; Store/update statistics for this unit

	clrf	surface_interval+0
	clrf	surface_interval+1				; Clear surface interval timer

ghostwriter_end_dive_common:
; Update ext_flash_log_pointer into EEPROM
	clrf	EEADRH
	movff	ext_flash_log_pointer+0,EEDATA
	write_int_eeprom .4
	movff	ext_flash_log_pointer+1,EEDATA
	write_int_eeprom .5
	movff	ext_flash_log_pointer+2,EEDATA
	write_int_eeprom .6

	bcf		simulatormode_active			; if we were in simulator mode

; In DEBUG compile, keep all simulated dives in logbook, Desat time, nofly, etc...
    ifndef __DEBUG
		extern	deco_pull_tissues_from_vault
		btfsc	restore_deco_data			; Restore decodata?
	    call    deco_pull_tissues_from_vault
        banksel common                  ; Bank1
	endif
	call	update_battery_registers	; update battery registers into EEPROM
	goto	surfloop					; and return to surfaceloop

ghostwriter_end_dive_common_sim:
    tstfsz  surface_interval+0              ; Was interval zero?
    bra     ghostwriter_end_dive_common_sim2    ; No
    tstfsz  surface_interval+1              ; Was interval zero?
    bra     ghostwriter_end_dive_common_sim2    ; No
    bra     ghostwriter_end_dive_common     ; Yes, done.

ghostwriter_end_dive_common_sim2:
    movf    divemins+0,W
    addwf   surface_interval+0,F
    movf    divemins+1,W
	addwfc  surface_interval+1				; Add simulated divetime to surface interval
    bra     ghostwriter_end_dive_common

ghostwriter_load_pointer:               ; Load ext_flash_address:3 from EEPROM .4-.6
	clrf    EEADRH                      ; Make sure to select eeprom bank 0
	read_int_eeprom	.4
	movff	EEDATA,ext_flash_address+0
	read_int_eeprom	.5
	movff	EEDATA,ext_flash_address+1
	read_int_eeprom	.6
	movff	EEDATA,ext_flash_address+2
    return

ghostwriter_short_header_init:          ; Proceed one page forward
    clrf    EEDATA
    write_int_eeprom .4                 ; ext_flash_address+0 = 0
    movlw   .16
    addwf   ext_flash_address+1,F
    movlw   .0
    addwfc  ext_flash_address+2,F
    movlw	0x20
	cpfseq	ext_flash_address+2			; at address 0x200000?
	bra     ghostwriter_short_header_init2  ; No
	clrf	ext_flash_address+2			; Yes, rollover to 0x000000
ghostwriter_short_header_init2:
    movlw   0xF0
    andwf   ext_flash_address+1,F       ; keep higher nibble, set lower nibble to 0

    movff   ext_flash_address+1,EEDATA
    write_int_eeprom .5                 ; Write new pointer
    movff   ext_flash_address+2,EEDATA
    write_int_eeprom .6                 ; Write new pointer
    bra     ghostwriter_short_header2   ; Done.

	global	ghostwriter_short_header
ghostwriter_short_header:	; Write short header with divenumber into profile memory
	; load pointer for profile storing into RAM (Updated in EEPROM after the dive)
    rcall   ghostwriter_load_pointer        ; Load ext_flash_address:3 from EEPROM .4-.6

    ; The following code is used to write a clean new dive after the previous hasn't been
    ; stored correctly. e.g. after a battery fail during the dive
    call    ext_flash_byte_read_plus_0x20   ; Into temp1
    incfsz  temp1,F
    bra     ghostwriter_short_header_init   ; Not 0xFF -> init page
    call    ext_flash_byte_read_plus_0x20   ; Into temp1
    incfsz  temp1,F
    bra     ghostwriter_short_header_init   ; Not 0xFF -> init page

ghostwriter_short_header2:
    ; All ok, reload the pointer and start
    rcall   ghostwriter_load_pointer        ; Load ext_flash_address:3 from EEPROM .4-.6

    ; Clear dive length counter
    clrf    ext_flash_dive_counter+0
    clrf    ext_flash_dive_counter+1
    clrf    ext_flash_dive_counter+2

	; Write short header with divenumber into profile memory
	movlw	0xFA
	rcall	ghostwrite_byte_profile 	; WREG -> Profile in ext. flash
	movlw	0xFA
	rcall	ghostwrite_byte_profile 	; WREG -> Profile in ext. flash
	; Load total number of dives (low byte only)
	read_int_eeprom .2
	incf	EEDATA,W							;+1	
	rcall	ghostwrite_byte_profile 	; WREG -> Profile in ext. flash
	read_int_eeprom .3
	movf	EEDATA,W
	rcall	ghostwrite_byte_profile 	; WREG -> Profile in ext. flash
	movlw	0xFA
	rcall	ghostwrite_byte_profile 	; WREG -> Profile in ext. flash
	movlw	0xFA
	rcall	ghostwrite_byte_profile 	; WREG -> Profile in ext. flash

    ; Keep room for dive length ext_flash_dive_counter:3 (Stored at the end of the dive)
    ; Writing 0xFF three times here is mandatory
    ; - 0xFF can be overwritten after the dive
    ; - ghostwrite_byte_profile takes care of 4kB Page switching
    ; - fixes an issue when we are at exactly 0xXXX000 here...

    movlw   0xFF
    rcall	ghostwrite_byte_profile 	; WREG -> Profile in ext. flash
    movlw   0xFF
    rcall	ghostwrite_byte_profile 	; WREG -> Profile in ext. flash
    movlw   0xFF
    rcall	ghostwrite_byte_profile 	; WREG -> Profile in ext. flash

	movf	samplingrate,W  			; Sampling rate
	btfsc	FLAG_apnoe_mode				; Apnoe mode?
	movlw	samplingrate_apnoe			; Apnoe sampling rate
	rcall	ghostwrite_byte_profile 	; WREG -> Profile in ext. flash

    movlw   .7                          ; Number of divisors
    rcall	ghostwrite_byte_profile 	; WREG -> Profile in ext. flash

    movlw   .0                          ; Type
    rcall	ghostwrite_byte_profile 	; WREG -> Profile in ext. flash
	movlw	infolength_temperature
    rcall	ghostwrite_byte_profile 	; WREG -> Profile in ext. flash
	movlw	div_temperature             ; Divisor temperature
    rcall	ghostwrite_byte_profile 	; WREG -> Profile in ext. flash

    movlw   .1                          ; Type
    rcall	ghostwrite_byte_profile 	; WREG -> Profile in ext. flash
	movlw	infolength_deco
    rcall	ghostwrite_byte_profile 	; WREG -> Profile in ext. flash
	movlw	div_deco                    ; Divisor decodata
    rcall	ghostwrite_byte_profile 	; WREG -> Profile in ext. flash

    movlw   .2                          ; Type
    rcall	ghostwrite_byte_profile 	; WREG -> Profile in ext. flash
	movlw	infolength_gf
    rcall	ghostwrite_byte_profile 	; WREG -> Profile in ext. flash
	movlw	div_gf                      ; Divisor gf
    rcall	ghostwrite_byte_profile 	; WREG -> Profile in ext. flash

    movlw   .3                          ; Type
    rcall	ghostwrite_byte_profile 	; WREG -> Profile in ext. flash
	movlw	infolength_ppo2_sensors
    rcall	ghostwrite_byte_profile 	; WREG -> Profile in ext. flash
	movlw	div_ppo2_sensors            ; Divisor ppO2
    btfss   FLAG_ccr_mode               ; =1: CCR mode (Fixed ppO2 or Sensor) active
    movlw   .0                          ; No ppO2 data in OC mode
    rcall	ghostwrite_byte_profile 	; WREG -> Profile in ext. flash

    movlw   .4                          ; Type
    rcall	ghostwrite_byte_profile 	; WREG -> Profile in ext. flash
	movlw	infolength_decoplan
    rcall	ghostwrite_byte_profile 	; WREG -> Profile in ext. flash
	movlw	div_decoplan                ; Divisor debug
    rcall	ghostwrite_byte_profile 	; WREG -> Profile in ext. flash

    movlw   .5                          ; Type
    rcall	ghostwrite_byte_profile 	; WREG -> Profile in ext. flash
	movlw	infolength_cns
    rcall	ghostwrite_byte_profile 	; WREG -> Profile in ext. flash
	movlw	div_cns                     ; Divisor CNS
    rcall	ghostwrite_byte_profile 	; WREG -> Profile in ext. flash

    movlw   .6                          ; Type
    rcall	ghostwrite_byte_profile 	; WREG -> Profile in ext. flash
	movlw	infolength_tank
    rcall	ghostwrite_byte_profile 	; WREG -> Profile in ext. flash
	movlw	div_tank                    ; Divisor Tank
    rcall	ghostwrite_byte_profile 	; WREG -> Profile in ext. flash

	return

calculate_noflytime:
	; calculate nofly time
	movff	int_O_desaturation_time+0,xA+0
	movff	int_O_desaturation_time+1,xA+1

    btfsc   xA+1,7                  ; Is desat time negative ?
    bra     calculate_noflytime_3   ; Then surely not valid !

	tstfsz	xA+0			; Desat=0?
	bra		calculate_noflytime2
	tstfsz	xA+1			; Desat=0?
	bra		calculate_noflytime2

calculate_noflytime_3:	
	; Desaturation time = zero
	clrf	nofly_time+0			; Clear nofly time
	clrf	nofly_time+1			; Clear nofly time
	return

calculate_noflytime2:	
	movff	xA+0,int_I_temp+0
	movff	xA+1,int_I_temp+1
	movlw	no_fly_time_ratio		; nofly_time_ratio                
	movff	WREG,char_I_temp
	call	deco_calc_percentage
	movlb	b'00000001'				; select ram bank 1
	movff	int_I_temp+0,xA+0
	movff	int_I_temp+1,xA+1
	tstfsz	xA+0			; Desat=0?
	bra		calculate_noflytime_2_final
	tstfsz	xA+1			; Desat=0?
	bra		calculate_noflytime_2_final
	bra     calculate_noflytime_3

calculate_noflytime_2_final:
	movff	xA+0,nofly_time+0
	movff	xA+1,nofly_time+1
	return


divemode_store_statistics:	; Store/update statistics for this unit
    rcall   vault_decodata_into_eeprom  ; update deco data
	rcall	do_logoffset_common_read	; Existing logbook offset into lo:hi
	
	tstfsz	lo							; lo=0?
	bra		change_logbook_offset1		; No, adjust offset	
	tstfsz	hi							; hi=0?
	bra		change_logbook_offset1		; No, adjust offset
	bra		change_logbook_offset2		; lo=0 and hi=0 -> skip Offset routine
change_logbook_offset1:
	movlw	d'1'
	addwf	lo
	movlw	d'0'
	addwfc	hi
	rcall	do_logoffset_common_write	; lo:hi -> EEPROM
change_logbook_offset2:
	; Add more here...
	return	

	global	do_logoffset_common_write
do_logoffset_common_write:
	movff	lo,EEDATA
	write_int_eeprom	0x0D
	movff	hi,EEDATA
	write_int_eeprom	0x0E
	return

	global	do_logoffset_common_read
do_logoffset_common_read:
	clrf	EEADRH
	read_int_eeprom		0x0D
	movff	EEDATA,lo
	read_int_eeprom		0x0E
	movff	EEDATA,hi					; Existing logbook offset into lo:hi
	return


	global		update_battery_registers
update_battery_registers:
	; save battery_gauge:6 into EEPROM 0x07-0x0C
	clrf	EEADRH
	movff	battery_gauge+0,EEDATA
	write_int_eeprom 0x07
	movff	battery_gauge+1,EEDATA
	write_int_eeprom 0x08
	movff	battery_gauge+2,EEDATA
	write_int_eeprom 0x09
	movff	battery_gauge+3,EEDATA
	write_int_eeprom 0x0A
	movff	battery_gauge+4,EEDATA
	write_int_eeprom 0x0B
	movff	battery_gauge+5,EEDATA
	write_int_eeprom 0x0C
	return


    global  vault_decodata_into_eeprom
vault_decodata_into_eeprom:
    ; Vault in EEPROM 512...1023
    ; Write 0xAA at 512 to indicate valid data in vault
    ; Store last time/date
    ; Store 0x700 to 0x780 (pres_tissue_N2 and pres_tissue_He)
    movlw   HIGH .512           ; =2
    movwf   EEADRH
    movlw   0xAA
    movwf   EEDATA
    write_int_eeprom .0
    ; Store date/time
    movff   year,EEDATA
    write_int_eeprom .1
    movff   month,EEDATA
    write_int_eeprom .2
    movff   day,EEDATA
    write_int_eeprom .3
    movff   hours,EEDATA
    write_int_eeprom .4
    movff   mins,EEDATA
    write_int_eeprom .5
    movff   secs,EEDATA
    write_int_eeprom .6

    movff   int_O_CNS_fraction+0,EEDATA
    write_int_eeprom .7
    movff   int_O_CNS_fraction+1,EEDATA
    write_int_eeprom .8
    movff   desaturation_time+0,EEDATA
    write_int_eeprom .9
    movff   desaturation_time+1,EEDATA
    write_int_eeprom .10
    movff   surface_interval+0,EEDATA
    write_int_eeprom .11
    movff   surface_interval+1,EEDATA
    write_int_eeprom .12
    movff   char_O_gradient_factor,EEDATA
    write_int_eeprom .13
    movff   nofly_time+0,EEDATA
    write_int_eeprom .14
    movff   nofly_time+1,EEDATA
    write_int_eeprom .15

    ; Tissue data from 16 to 144
    movlw   .16
    movwf   EEADR
    movlw   .128
    movwf   lo
    lfsr    FSR1,0x700;pres_tissue_N2+0       ; 32*4Byte Float = 128Bytes
vault_decodata_into_eeprom2:
    movff   POSTINC1,EEDATA
    call    write_eeprom                ; EEDATA into EEPROM@EEADR
    incf    EEADR,F
    decfsz  lo,F                        ; All done?
    bra     vault_decodata_into_eeprom2 ; No
    clrf    EEADRH
    return

    global  restore_decodata_from_eeprom
restore_decodata_from_eeprom:
    movlw   LOW  .512           ; =0
    movwf   EEADR
    movlw   HIGH .512           ; =2
    movwf   EEADRH

    ; Restore date/time
    read_int_eeprom .1
    movff   EEDATA,year
    read_int_eeprom .2
    movff   EEDATA,month
    read_int_eeprom .3
    movff   EEDATA,day
    read_int_eeprom .4
    movff   EEDATA,hours
    read_int_eeprom .5
    movff   EEDATA,mins
    read_int_eeprom .6
    movff   EEDATA,secs
    call    rtc_set_rtc

    read_int_eeprom .7
    movff   EEDATA,int_O_CNS_fraction+0
    read_int_eeprom .8
    movff   EEDATA,int_O_CNS_fraction+1
    read_int_eeprom .9
    movff   EEDATA,desaturation_time+0
    read_int_eeprom .10
    movff   EEDATA,desaturation_time+1
    read_int_eeprom .11
    movff   EEDATA,surface_interval+0
    read_int_eeprom .12
    movff   EEDATA,surface_interval+1
    read_int_eeprom .13
    movff   EEDATA,char_O_gradient_factor
    read_int_eeprom .14
    movff   EEDATA,nofly_time+0
    read_int_eeprom .15
    movff   EEDATA,nofly_time+1

    ; Tissue data from 16 to 144
    movlw   .16
    movwf   EEADR
    movlw   .128
    movwf   lo
    lfsr    FSR1,0x700;pres_tissue_N2+0       ; 32*4Byte Float = 128Bytes
restore_decodata_from_eeprom2:
    call    read_eeprom                ; EEPROM@EEADR into EEDATA
    movff   EEDATA,POSTINC1
    incf    EEADR,F
    decfsz  lo,F                        ; All done?
    bra     restore_decodata_from_eeprom2   ; No
    clrf    EEADRH
    return


 END