diff src/i2c.asm @ 656:8af5aefbcdaf default tip

Update to 3.31 beta
author heinrichsweikamp
date Thu, 27 Nov 2025 18:32:58 +0100
parents c7b7b8a358cd
children
line wrap: on
line diff
--- a/src/i2c.asm	Mon Apr 29 13:05:18 2024 +0200
+++ b/src/i2c.asm	Thu Nov 27 18:32:58 2025 +0100
@@ -42,6 +42,11 @@
 ;   -------------
 ;   LTC2942 read address  (8-Bit): 0xC9   
 ;   LTC2942 write address (8-Bit): 0xC8 
+;    
+;   Alternative Battery gauge    
+;   -------------
+;   LTC2959 read address  (8-Bit): 0xC7   
+;   LTC2959 write address (8-Bit): 0xC6 
 ;
 ;   Alternative pressure sensor
 ;   -----------
@@ -120,15 +125,12 @@
 	;bra	I2C_RX_accelerometer_compass0	; NO  - compass0 then
 
 ;I2C_RX_accelerometer_compass0:
-	bsf		SSP1CON2,SEN				; start condition
-	rcall	WaitMSSP					; wait for TX to complete
+	rcall	I2C_SEN						; start condition
 	movlw	0x38						; address
-	movff	WREG,i2c_error_vault+0				; Store address
 	rcall	I2C_TX						; send byte
 	movlw	0x00						; ??
 	rcall	I2C_TX						; send byte
-	bsf		SSP1CON2,RSEN				; repeated start condition
-	rcall	WaitMSSP					; wait for TX to complete
+	rcall	I2C_RSEN					; repeated start condition	
 	movlw	0x39						; address
 	rcall	I2C_TX						; send byte
 	rcall	I2C_OneByteRX				; get  status byte
@@ -170,9 +172,7 @@
 
 	rcall	I2C_OneByteRX				; receive 1 byte with acknowledge
 	movff	SSP1BUF,hi					; copy data byte to hi
-	bsf		SSP1CON2,RCEN				; enable receive mode
-	rcall	WaitMSSP					; wait for TX to complete
-	; according to data sheet there should be no master acknowledge for the last byte (accel_DZ+0)...
+	rcall	I2C_OneByteRX_NACK			; receive last byte with not acknowledge
 	movff	SSP1BUF,lo					; copy data byte to lo
 	rcall	I2C_TwoBytesRX_div16_2		; divide hi:lo/16 (signed)
 	comf	hi							; 16 bit sign change
@@ -180,21 +180,16 @@
 	btfsc	STATUS,C					; carry to propagate?
 	incf	hi,F						; YES - do it
 	MOVII	mpr,accel_DZ				; copy result to accel_DZ
-	bsf		SSP1CON2,PEN				; stop condition
-	rcall		WaitMSSP				; wait for TX to complete
-	return
+	bra	I2C_PEN						; stop condition
 
 
 I2C_RX_accelerometer_compass1:
-	bsf		SSP1CON2,SEN				; start condition
-	rcall	WaitMSSP					; wait for TX to complete
+	rcall	I2C_SEN						; start condition
 	movlw	0x3C						; address
-	movff	WREG,i2c_error_vault+0				; Store address
 	rcall	I2C_TX						; send byte
 	movlw	b'10101000'					; 0x28 with auto-increment (MSB=1)
 	rcall	I2C_TX						; send byte
-	bsf		SSP1CON2,RSEN				; repeated start condition (!)
-	rcall	WaitMSSP					; wait for TX to complete
+	rcall	I2C_RSEN					; repeated start condition	
 	movlw	0x3D						; address
 
 I2C_RX_accelerometer_common:			; common part for compass 1,2 and 3
@@ -260,12 +255,9 @@
 	MOVII	mpr,accel_DY				; copy result
 	rcall	I2C_OneByteRX				; receive 1 byte with acknowledge
 	movff	SSP1BUF,lo					; accel_DZ+0
-	bsf		SSP1CON2,RCEN				; enable receive mode
-	rcall	WaitMSSP					; wait for TX to complete
-	; according to data sheet there should be no master Acknowledge for the last byte (accel_DZ+1)...
+	rcall	I2C_OneByteRX_NACK			; receive last byte with not acknowledge
 	movff	SSP1BUF,hi					; accel_DZ+1
-	bsf		SSP1CON2,PEN				; stop condition
-	rcall	WaitMSSP					; wait for TX to complete
+	rcall	I2C_PEN						; stop condition
 	rcall	I2C_TwoBytesRX_div16_2		; divide lo:hi/16 (signed) only
 	comf	hi							; 16 bit sign change for Z
 	negf	lo							; ...
@@ -276,41 +268,26 @@
 
 
 I2C_RX_accelerometer_compass2:
-	bsf		SSP1CON2,SEN				; start condition
-	rcall	WaitMSSP					; wait for TX to complete
+	rcall	I2C_SEN						; start condition
 	movlw	0x32						; address
-	movff	WREG,i2c_error_vault+0				; Store address
 	rcall	I2C_TX						; send byte
 	movlw	b'10101000'					; 0x28 with auto-increment (MSB=1)
 	rcall	I2C_TX						; send byte
-	bsf		SSP1CON2,RSEN				; repeated start condition (!)
-	rcall	WaitMSSP					; wait for TX to complete
+	rcall	I2C_RSEN					; repeated start condition	
 	movlw	0x33						; address
 	bra		I2C_RX_accelerometer_common	; continue with common part
 
 I2C_RX_accelerometer_compass3:
-	bsf		SSP1CON2,SEN				; start condition
-	rcall	WaitMSSP					; wait for TX to complete
+	rcall	I2C_SEN						; start condition
 	movlw	0x3A						; address
-	movff	WREG,i2c_error_vault+0				; Store address
 	rcall	I2C_TX						; send byte
 	movlw	0x28						; 0x28 (OUT_X_L_A)
 	rcall	I2C_TX						; send byte
-	bsf		SSP1CON2,RSEN				; repeated start condition (!)
-	rcall	WaitMSSP					; wait for TX to complete
+	rcall	I2C_RSEN					; repeated start condition	
 	movlw	0x3B						; address
 	bra		I2C_RX_accelerometer_common	; continue with common part
 
 
-;-----------------------------------------------------------------------------
-; Helper Function - receive 1 Byte with Acknowledge
-;
-I2C_OneByteRX:
-	bsf		SSP1CON2,RCEN				; enable receive mode
-	rcall	WaitMSSP					; wait for TX to complete
-	bsf		SSP1CON2,ACKEN				; send master acknowledge
-	bra		WaitMSSP					; wait for TX to complete and return
-
 
 ;-----------------------------------------------------------------------------
 ; Read Compass
@@ -328,18 +305,14 @@
 	;bra	I2C_RX_compass0				; NO  - compass 0 then
 
 ;I2C_RX_compass0:
-	bsf		SSP1CON2,SEN				; start condition
-	rcall	WaitMSSP					; wait for TX to complete
-	movlw	0x3C						; address
-	movff	WREG,i2c_error_vault+0				; Store address
+	rcall	I2C_SEN						; start condition
+	movlw	0x3C						; address + write bit
 	rcall	I2C_TX						; send byte
-	movlw	0x03						; ??
+	movlw	0x03						; Point to Data Output X MSB Register (0x03)
 	rcall	I2C_TX						; send byte
-	bsf		SSP1CON2,PEN				; stop condition
-	rcall	WaitMSSP					; wait for TX to complete
-	bsf		SSP1CON2,SEN				; start condition
-	rcall	WaitMSSP					; wait for TX to complete
-	movlw	0x3D						; address
+	rcall	I2C_PEN						; stop condition
+	rcall	I2C_SEN						; start condition
+	movlw	0x3D						; address + read bit
 	rcall	I2C_TX						; send byte
 
 	; Compass IC sends data in following order:
@@ -383,11 +356,9 @@
 	movff	SSP1BUF,compass_DZ+0		; data byte
 	rcall	I2C_OneByteRX				; receive 1 byte with acknowledge
 	movff	SSP1BUF,compass_DX+1		; data byte
-	bsf		SSP1CON2,RCEN				; enable receive mode
-	rcall	WaitMSSP					; wait for TX to complete
+	rcall	I2C_RCEN					; enable receive mode
 	movff	SSP1BUF,compass_DX+0		; data byte
-	bsf		SSP1CON2,PEN				; stop condition
-	rcall	WaitMSSP					; wait for TX to complete
+	rcall	I2C_PEN						; stop condition
 	btfss	flip_screen					; 180° rotation?
 	return								; NO  - done
 	banksel	compass_DX					; YES - flip X
@@ -400,15 +371,12 @@
 
 
 I2C_RX_compass1:						; compass type 1
-	bsf		SSP1CON2,SEN				; start condition
-	rcall	WaitMSSP					; wait for TX to complete
+	rcall	I2C_SEN						; start condition
 	movlw	0x3C						; address
-	movff	WREG,i2c_error_vault+0				; Store address
 	rcall	I2C_TX						; send byte
 	movlw	b'10001000'					; 0x08 with auto-increment (MSB=1)
 	rcall	I2C_TX						; send byte
-	bsf		SSP1CON2,RSEN				; repeated start condition (!)
-	rcall	WaitMSSP					; wait for TX to complete
+	rcall	I2C_RSEN					; repeated start condition	
 	movlw	0x3D						; address
 	rcall	I2C_TX						; send byte
 	;rcall	WaitMSSP					; TODO needed? (mH)
@@ -444,27 +412,21 @@
 I2C_RX_compass1_2:
 	rcall	I2C_OneByteRX				; receive 1 byte with acknowledge
 	movff	SSP1BUF,lo					; data byte
-	bsf		SSP1CON2, RCEN				; Enable receive mode
-	rcall	WaitMSSP					; wait for TX to complete
+	rcall	I2C_OneByteRX_NACK			; receive last byte with not acknowledge
 	movff	SSP1BUF,hi					; data byte
 	rcall	I2C_TwoBytesRX_div8			; divide hi, lo by 8 (signed)
 	MOVII	mpr,compass_DZ				; copy result
-	bsf	SSP1CON2,PEN				; stop condition
-	rcall	WaitMSSP
-	return								; done
+	bra	I2C_PEN						; stop condition
 
 
 
 I2C_RX_compass2:						; compass type 2
-	bsf		SSP1CON2,SEN				; start condition
-	rcall	WaitMSSP					; wait for TX to complete
+	rcall	I2C_SEN						; start condition
 	movlw	0x3C						; address
-	movff	WREG,i2c_error_vault+0				; Store address
 	rcall	I2C_TX						; send byte
 	movlw	0xE8						; 0x68 with auto-increment (MSB=1)
 	rcall	I2C_TX						; send byte
-	bsf		SSP1CON2,RSEN				; repeated start condition (!)
-	rcall	WaitMSSP					; wait for TX to complete
+	rcall	I2C_RSEN					; repeated start condition	
 	movlw	0x3D						; address
 	rcall	I2C_TX						; send byte
 I2C_RX_compass2_xx:						; compass 3 joins in here
@@ -499,26 +461,21 @@
 	MOVII	mpr,compass_DY
 	rcall	I2C_OneByteRX				; receive 1 byte with acknowledge
 	movff	SSP1BUF,lo					; data byte
-	rcall	I2C_OneByteRX				; receive 1 byte with acknowledge
+	rcall	I2C_OneByteRX_NACK			; receive last byte with not acknowledge
 	movff	SSP1BUF,hi					; data byte
 ;	rcall	I2C_TwoBytesRX_div8			; divide hi, lo by 8 (signed)
 	MOVII	mpr,compass_DZ				; copy result
-	bsf		SSP1CON2,PEN				; stop condition
-	rcall	WaitMSSP					
-	return								; done
+	bra	I2C_PEN						; stop condition
 
 
 
 I2C_RX_compass3:						; compass type 3
-	bsf		SSP1CON2,SEN				; start condition
-	rcall	WaitMSSP					; wait for TX to complete
+	rcall	I2C_SEN						; start condition
 	movlw	0x3C						; address
-	movff	WREG,i2c_error_vault+0				; Store address
 	rcall	I2C_TX						; send byte
 	movlw	0xA8						; 0x28 with auto-increment (MSB=1)
 	rcall	I2C_TX						; send byte
-	bsf		SSP1CON2,RSEN				; repeated start condition (!)
-	rcall	WaitMSSP					; wait for TX to complete
+	rcall	I2C_RSEN					; repeated start condition	
 	movlw	0x3D						; address
 	rcall	I2C_TX						; send byte
 	bra		I2C_RX_compass2_xx			; join with compass 2 code
@@ -531,73 +488,85 @@
 ;
 	global	I2C_init_compass
 I2C_init_compass:
+	bsf		compass_present				; Set global compass flag
 	bsf		compass_enabled				; flag compass will be enabled
 	bcf		compass_type2				; clear in preparation of chip detection
 	bcf		compass_type3				; ...
 
 	; probe for compass 3
-	bsf		SSP1CON2,SEN				; start condition
-	rcall	WaitMSSP					; wait for TX to complete
+	rcall	I2C_SEN						; start condition
 	movlw	0x3A						; address byte + write bit
-	movff	WREG,i2c_error_vault+0				; Store address
 	movwf	SSP1BUF						; control byte
 	rcall	WaitMSSP					; wait for TX to complete
+	; we need the ACKSTAT bit! Do not use I2C_TX routine here which might reset this bit!
 	btfss	SSP1CON2,ACKSTAT			; ACK received?
 	bsf		compass_type3				; YES - ACK was send, compass 3 found
-	bsf		SSP1CON2,PEN				; stop condition
-	rcall	WaitMSSP					; wait for TX to complete
+	rcall	I2C_PEN						; stop condition
 
 	btfsc	compass_type3				; compass 3 found?
 	bra		I2C_init_compass3			; YES - initialize compass 3
 
 	; probe for compass 2
-	bsf		SSP1CON2,SEN				; start condition
-	rcall	WaitMSSP					; wait for TX to complete
+	rcall	I2C_SEN						; start condition
 	movlw	0x32						; address byte + write bit
-	movff	WREG,i2c_error_vault+0				; Store address
 	movwf	SSP1BUF						; control byte
 	rcall	WaitMSSP					; wait for TX to complete
-	btfss	SSP1CON2,ACKSTAT			; ACK received?
+	; we need the ACKSTAT bit! Do not use I2C_TX routine here which might reset this bit!
+        btfss	SSP1CON2,ACKSTAT			; ACK received?
 	bsf		compass_type2				; YES - ACK send, compass 2 found
-	bsf		SSP1CON2,PEN				; stop condition
-	rcall	WaitMSSP					; wait for TX to complete
+	rcall	I2C_PEN						; stop condition
 
 	btfsc	compass_type2				; compass 2 found?
 	bra		I2C_init_compass2			; YES - initialize compass 2
 
-	; probe for compass 0 or 1
+	; probe for compass 1
 	bsf		compass_type1				; assume compass 1 by default
-	bsf		SSP1CON2,SEN				; start condition
-	rcall	WaitMSSP					; wait for TX to complete
+	rcall	I2C_SEN						; start condition
 	movlw	0x3C						; address
-	movff	WREG,i2c_error_vault+0				; Store address
 	rcall	I2C_TX						; send byte
 	movlw	0x0F						; ??
 	rcall	I2C_TX						; send byte
-	bsf		SSP1CON2,PEN				; stop condition
-	rcall	WaitMSSP					; wait for TX to complete
-	bsf		SSP1CON2,SEN				; start condition
-	rcall	WaitMSSP					; wait for TX to complete
+	rcall	I2C_PEN						; stop condition
+	rcall	I2C_SEN						; start condition
 	movlw	0x3D						; address
 	rcall	I2C_TX						; send byte
 	rcall	I2C_OneByteRX				; receive 1 byte with acknowledge
 	movlw	0x49						; 0x49 = compass 1
 	cpfseq	SSP1BUF						; 0x49 received?
 	bcf		compass_type1				; NO - clear flag for compass 1
-	bsf		SSP1CON2,PEN				; stop condition
-	rcall	WaitMSSP					; wait for TX to complete
+	rcall	I2C_PEN						; stop condition
 
 	btfsc	compass_type1				; compass 1 found?
 	bra		I2C_init_compass1			; YES - initialize compass 1
-	;bra	I2C_init_compass0			; NO  - must be compass 0 then
+	
+	; probe for compass 0
+	bsf	compass_type0					; assume compass 0 by default
+	rcall	I2C_SEN						; start condition
+	movlw	0x3C						; address + write bit
+	rcall	I2C_TX						; send byte
+	movlw	0x0A						; Point to Identification Register A
+	rcall	I2C_TX						; send byte
+	rcall	I2C_PEN						; stop condition
+	rcall	I2C_SEN						; start condition
+	movlw	0x3D						; address + read bit
+	rcall	I2C_TX						; send byte
+	rcall	I2C_OneByteRX					; receive 1 byte with acknowledge
+	movlw	b'01001000'					; Identification Register A must be "H"
+	cpfseq	SSP1BUF						; Compare with received value
+	bcf	compass_type0					; Not equal -> Not compass 0
+	rcall	I2C_PEN						; stop condition
+	
+	btfsc	compass_type0				; compass 0 found?
+	bra	I2C_init_compass0			; YES - initialize compass 0
+;	; no compass of any type found
+	bcf	compass_present				; Delete global compass flag
+	return
 
 
 I2C_init_compass0:
 	; magnetic
-	bsf		SSP1CON2,SEN				; start condition
-	rcall	WaitMSSP					; wait for TX to complete
+	rcall	I2C_SEN						; start condition
 	movlw	0x3C						; address
-	movff	WREG,i2c_error_vault+0				; Store address
 	rcall	I2C_TX						; send byte
 	movlw	0x00						; ??
 	rcall	I2C_TX						; send byte
@@ -612,25 +581,20 @@
 	rcall	I2C_TX						; send byte
 	movlw	b'00000000'					; select continuous mode
 	rcall	I2C_TX						; send byte
-	bsf		SSP1CON2,PEN				; stop condition
-	rcall	WaitMSSP					; wait for TX to complete
+	rcall	I2C_PEN						; stop condition
 
 	; accelerometer
 	rcall	I2C_sleep_accelerometer0	; registers can only be changed in standby mode
 
-	bsf		SSP1CON2,SEN				; start condition
-	rcall	WaitMSSP					; wait for TX to complete
+	rcall	I2C_SEN						; start condition
 	movlw	0x38						; address
-	movff	WREG,i2c_error_vault+0				; Store address
 	rcall	I2C_TX						; send byte
 	movlw	0x0E						; XYZ_DATA_CFG
 	rcall	I2C_TX						; send byte
 	movlw	b'00000000'					; high pass filter = 0, +/- 2 g range
 	rcall	I2C_TX						; send byte
-	bsf		SSP1CON2,PEN				; stop condition
-	rcall	WaitMSSP					; wait for TX to complete
-	bsf		SSP1CON2,SEN				; start condition
-	rcall	WaitMSSP					; wait for TX to complete
+	rcall	I2C_PEN						; stop condition
+	rcall	I2C_SEN						; start condition
 	movlw	0x38						; address
 	rcall	I2C_TX						; send byte
 	movlw	0x2A						; CTRL_REG1
@@ -640,11 +604,9 @@
 	rcall	I2C_TX						; send byte
 	movlw	b'00000010'					; CTRL_REG2: high-res in active mode
 	rcall	I2C_TX						; send byte
-	bsf		SSP1CON2,PEN				; stop condition
-	rcall	WaitMSSP					; wait for TX to complete
+	rcall	I2C_PEN						; stop condition
 
-	bsf		SSP1CON2,SEN				; start condition
-	rcall	WaitMSSP					; wait for TX to complete
+	rcall	I2C_SEN						; start condition
 	movlw	0x38						; address
 	rcall	I2C_TX						; send byte
 	movlw	0x2A						; CTRL_REG1
@@ -652,17 +614,13 @@
 ;	movlw	b'00110001'					; CTRL_REG1: 160 ms data rate, active  mode
 	movlw	b'00110101'					; CTRL_REG1: 160 ms data rate, standby mode, reduced noise mode, active Mode
 	rcall	I2C_TX						; send byte
-	bsf		SSP1CON2,PEN				; stop condition
-	rcall	WaitMSSP					; wait for TX to complete
-	return							; done
+	bra	I2C_PEN						; stop condition
 
 
 
 I2C_init_compass1:
-	bsf		SSP1CON2,SEN				; start condition
-	rcall	WaitMSSP					; wait for TX to complete
+	rcall	I2C_SEN						; start condition
 	movlw	0x3C						; address
-	movff	WREG,i2c_error_vault+0				; Store address
 	rcall	I2C_TX						; send byte
 	movlw	0x9F						; 1F with auto-increment (MSB=1)
 	rcall	I2C_TX						; send byte
@@ -697,19 +655,15 @@
 	rcall	I2C_TX						; send byte
 	movlw	b'00000000'					; CTRL7 Continuous Mode
 	rcall	I2C_TX						; send byte
-	bsf		SSP1CON2,PEN				; stop condition
-	rcall	WaitMSSP					; wait for TX to complete
-	return							; done
+	bra	I2C_PEN						; stop condition
 
 	; accelerometer initializes along with magnetic sensor
 
 
 I2C_init_compass2:
 	; magnetic
-	bsf		SSP1CON2,SEN				; start condition
-	rcall	WaitMSSP					; wait for TX to complete
+	rcall	I2C_SEN						; start condition
 	movlw	0x3C						; address
-	movff	WREG,i2c_error_vault+0				; Store address
 	rcall	I2C_TX						; send byte
 	movlw	0xE0						; 0x60 with auto-increment (MSB=1)
 	rcall	I2C_TX						; send byte
@@ -719,14 +673,11 @@
 	rcall	I2C_TX						; send byte
 	movlw	b'00010000'					; CFG_REG_C_M BDU=1 0x62 0x57
 	rcall	I2C_TX						; send byte
-	bsf		SSP1CON2,PEN				; stop condition
-	rcall	WaitMSSP					; wait for TX to complete
+	rcall	I2C_PEN						; stop condition
 
 	; accelerometer
-	bsf		SSP1CON2,SEN				; start condition
-	rcall	WaitMSSP					; wait for TX to complete
+	rcall	I2C_SEN						; start condition
 	movlw	0x32						; address
-	movff	WREG,i2c_error_vault+0				; Store address
 	rcall	I2C_TX						; send byte
 	movlw	0x9F						; 1F with auto-increment (MSB=1)
 	rcall	I2C_TX						; send byte
@@ -742,17 +693,13 @@
 	rcall	I2C_TX						; send byte
 ;	movlw	b'00000000'					; CTRL_REG5_A
 ;	rcall	I2C_TX						; send byte
-	bsf		SSP1CON2,PEN				; stop condition
-	rcall	WaitMSSP					; wait for TX to complete
-	return							; done
+	bra	I2C_PEN						; stop condition
 
 
 I2C_init_compass3:
 	; magnetic
-	bsf		SSP1CON2,SEN				; start condition
-	rcall	WaitMSSP					; wait for TX to complete
+	rcall	I2C_SEN						; start condition
 	movlw	0x3C						; address
-	movff	WREG,i2c_error_vault+0				; Store address
 	rcall	I2C_TX						; send byte
 	movlw	0xA0						; 0x20 with auto-increment (MSB=1)
 	rcall	I2C_TX						; send byte
@@ -768,14 +715,11 @@
 	rcall	I2C_TX						; send byte
 	movlw	b'00000000'					; CTRL_REG5_M 0x24
 	rcall	I2C_TX						; send byte
-	bsf		SSP1CON2,PEN				; Stop condition
-	rcall	WaitMSSP					; wait for TX to complete
+	rcall	I2C_PEN						; stop condition
 
 	;accelerometer
-	bsf	SSP1CON2,SEN					; start condition
-	rcall	WaitMSSP					; wait for TX to complete
+	rcall	I2C_SEN						; start condition
 	movlw	0x3A						; address
-	movff	WREG,i2c_error_vault+0				; Store address
 	rcall	I2C_TX						; send byte
 	movlw	0x20
 	rcall	I2C_TX						; send byte
@@ -787,18 +731,10 @@
 	rcall	I2C_TX						; send byte
 	movlw	b'11001100'					; CTRL_REG4_A 0x23
 	rcall	I2C_TX						; send byte
-	bsf		SSP1CON2,PEN				; stop condition
-	rcall	WaitMSSP					; wait for TX to complete
-	return							; done
+	bra	I2C_PEN						; stop condition
+	
 
-;-----------------------------------------------------------------------------
-; Helper Function - send 1 Byte, wait for end of transmission and check ackn
-;
-I2C_TX:
-	movwf	SSP1BUF						; put byte to be sent into TX buffer
-	rcall	WaitMSSP					; wait for TX to complete
-	bra		I2C_Check_ACK				; check for acknowledge by receiver and return
-
+	
 ;-----------------------------------------------------------------------------
 ; Deactivate Compass / Accelerometer
 ;
@@ -818,10 +754,8 @@
 
 I2C_sleep_compass0:
 	; magnetic
-	bsf		SSP1CON2,SEN				; start condition
-	rcall	WaitMSSP					; wait for TX to complete
+	rcall	I2C_SEN						; start condition
 	movlw	0x3C						; address
-	movff	WREG,i2c_error_vault+0				; Store address
 	rcall	I2C_TX						; send byte
 	movlw	0x00						; ??
 	rcall	I2C_TX						; send byte
@@ -831,58 +765,45 @@
 	rcall	I2C_TX						; send byte
 	movlw	b'00000010'					; idle mode
 	rcall	I2C_TX						; send byte
-	bsf		SSP1CON2,PEN				; stop condition
-	rcall	WaitMSSP					; wait for TX to complete
+	rcall	I2C_PEN						; stop condition
 
 I2C_sleep_accelerometer0:
 	; accelerometer
-	bsf		SSP1CON2,SEN				; start condition
-	rcall	WaitMSSP					; wait for TX to complete
+	rcall	I2C_SEN						; start condition
 	movlw	0x38						; address
-	movff	WREG,i2c_error_vault+0				; Store address
 	rcall	I2C_TX						; send byte
 	movlw	0x2A						; CTRL_REG1
 	rcall	I2C_TX						; send byte
 	movlw	b'00000000'					; standby mode
 	rcall	I2C_TX						; send byte
-	bsf		SSP1CON2,PEN				; stop condition
-	rcall	WaitMSSP					; wait for TX to complete
-	return							; done
+	bra	I2C_PEN						; stop condition
 
 
 I2C_sleep_compass1:
-	bsf		SSP1CON2,SEN				; start condition
-	rcall	WaitMSSP					; wait for TX to complete
+	rcall	I2C_SEN						; start condition
 	movlw	0x3C						; address
-	movff	WREG,i2c_error_vault+0				; Store address
 	rcall	I2C_TX						; send byte
 	movlw	0x20						; CTRL_REG1
 	rcall	I2C_TX						; send byte
 	movlw	b'00000000'					; data for CTRL_REG1: acceleration sensor power-down mode
 	rcall	I2C_TX						; send byte
-	bsf		SSP1CON2,PEN				; stop condition
-	rcall	WaitMSSP					; wait for TX to complete
-	bsf		SSP1CON2,SEN				; start condition
-	rcall	WaitMSSP					; wait for TX to complete
+	rcall	I2C_PEN						; stop condition
+	rcall	I2C_SEN						; start condition
 	movlw	0x3C						; address
 	rcall	I2C_TX						; send byte
 	movlw	0x26						; CTRL_REG7
 	rcall	I2C_TX						; send byte
 	movlw	b'00000010'					; data for CTRL_REG7: magnetic sensor power-down mode
 	rcall	I2C_TX						; send byte
-	bsf		SSP1CON2,PEN				; stop condition
-	rcall	WaitMSSP					; wait for TX to complete
-	return							; done
+	bra	I2C_PEN						; stop condition
 
 	; accelerometer sleeps with magnetic sensor
 
 
 I2C_sleep_compass2:
 	; magnetic
-	bsf		SSP1CON2,SEN				; start condition
-	rcall	WaitMSSP					; wait for TX to complete
+	rcall	I2C_SEN						; start condition
 	movlw	0x3C						; address
-	movff	WREG,i2c_error_vault+0				; Store address
 	rcall	I2C_TX						; send byte
 	movlw	0xE0						; 0x60 with auto-increment (MSB=1)
 	rcall	I2C_TX						; send byte
@@ -894,14 +815,11 @@
 	rcall	I2C_TX						; send byte
 	movlw	b'00000000'					; INT_CTRL_REG_M 0x63
 	rcall	I2C_TX						; send byte
-	bsf		SSP1CON2,PEN				; stop condition
-	rcall	WaitMSSP					; wait for TX to complete
+	rcall	I2C_PEN						; stop condition
 
 	; accelerometer
-	bsf		SSP1CON2,SEN				; start condition
-	rcall	WaitMSSP					; wait for TX to complete
+	rcall	I2C_SEN						; start condition
 	movlw	0x32						; address
-	movff	WREG,i2c_error_vault+0				; Store address
 	rcall	I2C_TX						; send byte
 	movlw	0x9F						; 1F with auto-increment (MSB=1)
 	rcall	I2C_TX						; send byte
@@ -909,45 +827,121 @@
 	rcall	I2C_TX						; send byte
 	movlw	b'00000000'					; CTRL_REG1_A     0x20 (all off)
 	rcall	I2C_TX						; send byte
-	bsf		SSP1CON2,PEN				; stop condition
-	rcall	WaitMSSP					; wait for TX to complete
-	return							; done
+	bra	I2C_PEN						; stop condition
 
 
 I2C_sleep_compass3:
 	; magnetic
-	bsf		SSP1CON2,SEN				; start condition
-	rcall	WaitMSSP					; wait for TX to complete
+	rcall	I2C_SEN						; start condition
 	movlw	0x3C						; address
-	movff	WREG,i2c_error_vault+0				; Store address
 	rcall	I2C_TX						; send byte
 	movlw	0xA2						; 0x22 with auto-increment (MSB=1)
 	rcall	I2C_TX						; send byte
 	movlw	b'01000010'					; CTRL_REG3_M (power-down) 0x22
 	rcall	I2C_TX						; send byte
-	bsf		SSP1CON2,PEN				; stop condition
-	rcall	WaitMSSP					; wait for TX to complete
+	rcall	I2C_PEN						; stop condition
 
 	; accelerometer
-	bsf		SSP1CON2,SEN				; start condition
-	rcall	WaitMSSP					; wait for TX to complete
+	rcall	I2C_SEN						; start condition
 	movlw	0x3A						; address
-	movff	WREG,i2c_error_vault+0				; Store address
 	rcall	I2C_TX						; send byte
 	movlw	0x20
 	rcall	I2C_TX						; send byte
 	movlw	b'00000000'					; CTRL_REG1_A (100Hz, x,y,z = OFF) 0x20
 	rcall	I2C_TX						; send byte
-	bsf		SSP1CON2,PEN				; stop condition
-	rcall	WaitMSSP					; wait for TX to complete
-	return							; done
+	bra	I2C_PEN						; stop condition
+	
+	
+;-----------------------------------------------------------------------------
+; Helper Function - receive 1 Byte with Not-Acknowledge
+;
+I2C_OneByteRX_NACK:
+	rcall	I2C_RCEN					; enable receive mode
+	bsf	SSP1CON2,ACKDT					; set ACKDT flag
+	rcall	I2C_ACKEN					; send master acknowledge
+	bcf	SSP1CON2,ACKDT					; reset ACKDT flag
+	return
 
 
 ;-----------------------------------------------------------------------------
+; Helper Function - receive 1 Byte with Acknowledge
+;
+I2C_OneByteRX:
+	rcall	I2C_RCEN					; enable receive mode
+	bra	I2C_ACKEN					; send master acknowledge
+	
+;-----------------------------------------------------------------------------
+; Helper Function - send 1 Byte, wait for end of transmission and check ackn
+; add WREG to checksum byte first
+I2C_TX_CHKSUM:
+	addwf	sub_a+0,F					; add to checksum
+;	bra	I2C_TX
+;-----------------------------------------------------------------------------
+; Helper Function - send 1 Byte, wait for end of transmission and check ackn
+;
+I2C_TX:
+	movwf	SSP1BUF						; put byte to be sent into TX buffer
+	btfss	i2c_error_flag_lock				; vault in use already?
+	movff	WREG,i2c_error_vault+0				; NO, Store address	
+	rcall	WaitMSSP					; wait for TX to complete
+	bra		I2C_Check_ACK				; check for acknowledge by receiver and return
+
+	
+;-----------------------------------------------------------------------------
+; Helper Function - I2C Start Condition
+;
+I2C_SEN:
+	bsf	SSP1CON2,SEN					; start condition
+	bra	WaitMSSP					; wait for TX to complete (And return)
+
+;-----------------------------------------------------------------------------
+; Helper Function - I2C Repeated Start Condition
+;
+I2C_RSEN:
+	bsf	SSP1CON2,RSEN					; repeated start condition
+	bra	WaitMSSP					; wait for TX to complete (And return)
+	
+
+;-----------------------------------------------------------------------------
+; Helper Function - I2C Stop Condition
+;
+I2C_PEN:
+	bsf	SSP1CON2,PEN					; stop condition
+	rcall	WaitMSSP					; wait for TX to complete (And return)
+I2C_WAIT_100US:	
+	; add ~100µs bus free time (min. 66µs recommended for LTC2959)
+	; Remark: not exact: 122µs +/- 30.5 µs + worst case ISR latency
+	setf	TMR5H						; initialize timer 5, high byte first
+	movlw	.255-.4						; 4 x 31.5 µs = 126µs, min: 94,5µs
+	movwf	TMR5L						; initialize timer 5, low  byte thereafter
+	bcf	PIR5,TMR5IF					; clear timer 5 overrun flag
+I2C_PEN_Loop:
+	btfss	PIR5,TMR5IF					; did timer 5 overrun?
+	bra	I2C_PEN_Loop					; NO  - repeat inner loop
+	return
+
+;-----------------------------------------------------------------------------
+; Helper Function - Master Acknowledge	
+;
+I2C_ACKEN:
+	bsf	SSP1CON2,ACKEN					; master acknowledge	
+	bra	WaitMSSP					; wait for TX to complete (And return)
+
+;-----------------------------------------------------------------------------
+; Helper Function - Enable reeive mode
+;
+I2C_RCEN:
+    	bsf	SSP1CON2,RCEN					; enable receive mode
+	bra	WaitMSSP					; wait for TX to complete (And return)
+	
+;-----------------------------------------------------------------------------
 ; Helper Function - wait for TX to complete
 ;
 WaitMSSP:
-	movff	SSP1BUF,i2c_error_vault+1
+        btfss	i2c_error_flag_lock				; vault in use already?
+	movff	SSP1BUF,i2c_error_vault+1			; NO, store value
+	btfss	i2c_error_flag_lock				; vault in use already?
+	movff	SSP1CON2,i2c_error_vault+2			; NO, store value
 	clrf	i2c_temp1					; wait for max 256 loops
 WaitMSSP_loop:
 	decfsz	i2c_temp1,F					; decrement loop counter, timeout?
@@ -965,12 +959,10 @@
 ;
 I2C_MasterNotAckStop:
 	bsf		SSP1CON2,ACKDT				; set ACKDT flag
-	bsf		SSP1CON2,ACKEN				; master NOT acknowledge
-	rcall	WaitMSSP					; wait for TX to complete
+	rcall	I2C_ACKEN					; send master NOT acknowledge
 	bcf		SSP1CON2,ACKDT				; reset ACKDT flag
 
-	bsf	SSP1CON2,PEN					; stop condition
-	bra	WaitMSSP					; wait for TX to complete
+	bra	I2C_PEN						; stop condition
 	
 ;-----------------------------------------------------------------------------
 ; Helper Function - check for Acknowledge by Receiver
@@ -989,6 +981,7 @@
 	rcall	I2CReset					; reset I2C
 	bcf		PIR1,SSP1IF					; clear TX completion flag
 	bsf		i2c_error_flag				; set error flag
+	bsf		i2c_error_flag_lock			; lock the error vault
 	bcf		active_reset_ostc_rx		; release reset from RX circuitry
 ;	bcf	i2c_busy_temperature
 ;	bcf	i2c_busy_pressure
@@ -1000,6 +993,7 @@
 ;
 ; recover in case something went wrong, i.g. slave holds SDA low
 ;
+	global	I2CReset
 I2CReset:
 	clrf	SSP1CON1					; reset entire module
 	clrf	SSP1CON2					; ...
@@ -1028,7 +1022,7 @@
 I2CReset_2:
 	bsf		TRISC,3						; SCL as input
 	clrf	SSP1CON1					; setup I2C mode
-	WAITMS	d'10'						; wait 10 ms (reset-timeout for I2C devices)
+	rcall	I2C_WAIT_100US					; ISR-Safe 100µs wait
 	movlw	b'00000000'					; enable slew rate control
 	movwf	SSP1STAT					; ...
 	movlw	b'00101000'					; configure I2C module
@@ -1037,13 +1031,30 @@
 	movwf	SSP1CON2					; ...
 	movlw	i2c_speed_value
 	movwf	SSP1ADD						; ...
-	return								; done
+	rcall	I2C_WAIT_100US					; ISR-Safe 100µs wait
+	movlw	.1
+	addwf	i2c_error_counter+0
+	movlw	.0
+	addwfc	i2c_error_counter+1				; +1 on the error counter
+	btfss	press_sensor_type				; =1: pressure sensor MS5837, =0: Pressure sensor MS5541
+	return							; MS5541, Done.
+	; reset the sensor
+	rcall	I2C_SEN						; start condition
+	movlw	0xEC						; address byte + write bit
+	rcall	I2C_TX						; send byte
+	movlw	0x1E
+	rcall	I2C_TX						; send byte
+	rcall	I2C_PEN						; stop condition
+	WAITMS	.5						; 2.8ms according to datasheet
+	return							; done
 
 
 ;-----------------------------------------------------------------------------
 ; Helper Function - Initialize Gauge IC again after an UVLO Event
 ;
-lt2942_init_again:
+battery_gauge_init_again:
+	btfsc	battery_gauge_type				; =1: Gauge IC LTC2959, =0: LT2942
+	return
 	rcall   I2CReset
 	movlw	0x02									; point to accumulated charge registers
 	rcall	I2C_TX_GAUGE							; send byte to the LT2942 gauge IC
@@ -1053,78 +1064,76 @@
 	movff	battery_accumulated_charge+0,SSP1BUF	; data byte
 	rcall	WaitMSSP								; wait for TX to complete
 	rcall	I2C_Check_ACK							; check for acknowledge by receiver
-	bsf		SSP1CON2,PEN							; stop condition
-	rcall	WaitMSSP								; wait for TX to complete
+	rcall	I2C_PEN						; stop condition
 	MOVII	battery_accumulated_charge,sub_a		; copy result to sub_a
-	;bra	lt2942_init								; and initialize again...
+	;bra	battery_gauge_init								; and initialize again...
 
 
 ;-----------------------------------------------------------------------------
 ; Initialize Gauge IC
 ;
-	global	lt2942_init
-lt2942_init:
-	movlw	0x01						; point to control reg B
-	rcall	I2C_TX_GAUGE				; send byte to the LT2942 gauge IC
-	movlw	b'11111000'					; automatic conversion every two seconds
-	movwf	SSP1BUF				    ; data byte
-	rcall	WaitMSSP					; wait for TX to complete
-	rcall	I2C_Check_ACK				; check for acknowledge by receiver
-	bsf		SSP1CON2,PEN				; stop condition
-	rcall	WaitMSSP					; wait for TX to complete
-	return							; done
-
-;-----------------------------------------------------------------------------
-; Sleep Gauge IC
-;
-	global	lt2942_sleep
-lt2942_sleep:
-	movlw	0x01						; point to control reg B
-	rcall	I2C_TX_GAUGE				; send byte to the LT2942 gauge IC
-	movlw	b'00111000'					; sleep
-	movwf	SSP1BUF				    ; data byte
-	rcall	WaitMSSP					; wait for TX to complete
-	rcall	I2C_Check_ACK				; check for acknowledge by receiver
-	bsf		SSP1CON2,PEN				; stop condition
-	rcall	WaitMSSP					; wait for TX to complete
-	return							; done
+	global	battery_gauge_init
+battery_gauge_init:
+	movlw	0x01						; point to control reg B / ADC Control
+	rcall	I2C_TX_GAUGE					; send byte to the gauge IC
+	movlw	b'11111000'					; automatic conversion every two seconds (LT2942)
+	btfsc	battery_gauge_type				; =1: Gauge IC LTC2959, =0: LT2942
+	movlw	b'00111000'					; ADC Mode to "Smart Sleep" (converts V, I, T every 52 seconds (tolerance < ±5%)) (LTC2959)
+	rcall	I2C_TX						; send byte
+	btfsc	battery_gauge_type				; =1: Gauge IC LTC2959, =0: LT2942
+	movlw	b'01010000'					; 20µV deadband
+	btfsc	battery_gauge_type				; =1: Gauge IC LTC2959, =0: LT2942
+	rcall	I2C_TX						; send one byte more for the LTC2959
+	bra	I2C_PEN						; stop condition
 
 ;-----------------------------------------------------------------------------
 ; Read Gauge IC - Status Register
 ;
 	global	lt2942_get_status
 lt2942_get_status:
-	bcf		battery_gauge_available		; clear flag
-	movlw	0x00						; point to status register
-	rcall	I2C_TX_GAUGE				; send    byte to   the LT2942 gauge IC
-	rcall	I2C_RX_GAUGE				; receive byte from the LT2942 Gauge IC
+	bcf	battery_gauge_type				; =1: Gauge IC LTC2959, =0: LT2942
+	bcf	battery_gauge_available				; clear flag on default
 
-	bsf		SSP1CON2,ACKDT				; set ACKDT flag
-	bsf		SSP1CON2,ACKEN				; master NOT acknowledge
+	; try LTC2942
+	rcall	I2C_SEN						; start condition
+	movlw	0xC8						; address byte + Write bit
+	movwf	SSP1BUF						; put byte to be sent into TX buffer
 	rcall	WaitMSSP					; wait for TX to complete
-	bcf		SSP1CON2,ACKDT				; reset ACKDT flag
-
-	movff	SSP1BUF,WREG				; copy received byte to WREG
-	btfss	WREG,7						; 2942 found?
-	bsf		battery_gauge_available		; YES - set flag
-	bsf		SSP1CON2,PEN				; stop condition
+	; we need the ACKSTAT bit! Do not use I2C_TX routine here which might reset this bit!
+	btfss	SSP1CON2,ACKSTAT				; ACK received from slave?
+	bsf	battery_gauge_available				; YES - set flag
+	rcall	I2C_MasterNotAckStop				; Master NOT acknowledge and Stop
+	btfsc	battery_gauge_available				; found?
+	return							; YES - done
+	
+	; try LTC2959
+	rcall	I2C_SEN						; start condition
+	movlw	0xC6						; address byte + Write bit
+	movwf	SSP1BUF						; put byte to be sent into TX buffer
 	rcall	WaitMSSP					; wait for TX to complete
-	return							; done
-
+	; we need the ACKSTAT bit! Do not use I2C_TX routine here which might reset this bit!
+	btfss	SSP1CON2,ACKSTAT				; ACK received from slave?
+	bsf	battery_gauge_available				; YES - set flag
+	rcall	I2C_MasterNotAckStop				; Master NOT acknowledge and Stop
+	btfsc	battery_gauge_available				; found?
+	bsf	battery_gauge_type				; =1: Gauge IC LTC2959, =0: LT2942
+	return							; NO, return
 
 ;-----------------------------------------------------------------------------
 ; Read Gauge IC - Voltage
 ;
 	global	lt2942_get_voltage
 lt2942_get_voltage:
+  
+	btfsc	battery_gauge_type			; =1: Gauge IC LTC2959, =0: LT2942
+	bra	LTC2959_get_voltage			; use new IC
+	
 	movlw	0x08						; point to voltage registers
 	rcall	I2C_TX_GAUGE				; send    byte to   the LT2942 gauge IC
 	rcall	I2C_RX_GAUGE				; receive byte from the LT2942 Gauge IC
-	bsf		SSP1CON2,ACKEN				; master acknowledge
-	rcall	WaitMSSP					; wait for TX to complete
+	rcall	I2C_ACKEN					; send master acknowledge
 	movff	SSP1BUF,xA+1				; copy received byte to xA+1
-	bsf		SSP1CON2,RCEN				; enable receive mode
-	rcall	WaitMSSP					; wait for TX to complete
+	rcall	I2C_RCEN					; enable receive mode
 	movff	SSP1BUF,xA+0				; copy received byte to xA+0
 	
 	rcall	I2C_MasterNotAckStop				; Master NOT acknowledge and Stop
@@ -1133,12 +1142,46 @@
 	MOVLI	.6000,xB					; load conversion multiplicand into xB
 	call	mult16x16					; xC = xA * xB -> multiply raw value in xA with conversion multiplicand
 										; divide by 65536 instead of 65535, introducing an error of 65536/65535 = 0.002 %
-	movff	xC+2,batt_voltage+0			; divide by 65536 can easily be done by just taking the 3rd and 4th byte of the multiplication result
-	movff	xC+3,batt_voltage+1			; ...
+	movff	xC+2,xC+0			; divide by 65536 can easily be done by just taking the 3rd and 4th byte of the multiplication result
+	movff	xC+3,xC+1			; use xC+0 and xC+1 as temp
 
-	tstfsz	batt_voltage+1				; < 256 mV ?
-	return						; NO  - done
-	bra	lt2942_init_again			; YES - initialize gauge and return
+	movlw	.4					; battery voltage < 4*256mV (1.024)?
+	cpfslt	xC+1					; < 1024 mV ?
+	bra	lt2942_get_voltage_check_high		; NO  - Continue checking
+	bra	battery_gauge_init_again			; YES - initialize gauge and return (and leave batt_voltage:2 untouched)
+	
+lt2942_get_voltage_check_high:
+    	movlw	.17					; battery voltage >= 17*256mV (4.352V)?
+	cpfslt	xC+1					;     - ... ?
+	bra	battery_gauge_init_again			; YES - initialize gauge and return (and leave batt_voltage:2 untouched)
+	; NO  - done
+	movff	xC+0, batt_voltage+0
+	movff	xC+1, batt_voltage+1
+	bra	lt2942_get_accumulated_charge	;     - read coulomb counter (And return)
+	
+LTC2959_get_voltage:
+	movlw	0x0F						; point to voltage registers
+	rcall	I2C_TX_GAUGE				; send    byte to   the gauge IC
+	rcall	I2C_RX_GAUGE				; receive byte from the Gauge IC
+	rcall	I2C_ACKEN					; send master acknowledge
+	movff	SSP1BUF,xA+1				; copy received byte to xA+1
+	rcall	I2C_RCEN					; enable receive mode
+	movff	SSP1BUF,xA+0				; copy received byte to xA+0
+	
+	rcall	I2C_MasterNotAckStop				; Master NOT acknowledge and Stop
+	
+	; convert voltage from raw value to mV
+	MOVLI	.62600,xB					; load conversion multiplicand into xB
+	call	mult16x16					; xC = xA * xB -> multiply raw value in xA with conversion multiplicand
+										; divide by 65536 instead of 65535, introducing an error of 65536/65535 = 0.002 %
+	;movff	xC+2,xC+0			; divide by 65536 can easily be done by just taking the 3rd and 4th byte of the multiplication result
+	;movff	xC+3,xC+1			; use xC+0 and xC+1 as temp
+
+	movff	xC+2, batt_voltage+0
+	movff	xC+3, batt_voltage+1
+	rcall	lt2942_get_accumulated_charge	;     - read coulomb counter (And return)
+
+	return								; done
 
 
 ;-----------------------------------------------------------------------------
@@ -1146,24 +1189,26 @@
 ;
 	global	lt2942_get_temperature
 lt2942_get_temperature:					; read battery temperature
+    	btfsc	battery_gauge_type			; =1: Gauge IC LTC2959, =0: LT2942
+	bra	LTC2959_get_temperature
+
 	movlw	0x0C						; point to temperature register
 	rcall	I2C_TX_GAUGE				; send    byte to   the LT2942 gauge IC
 	rcall	I2C_RX_GAUGE				; receive byte from the LT2942 Gauge IC
-	bsf		SSP1CON2,ACKEN				; master acknowledge
-	rcall	WaitMSSP					; wait for TX to complete
+	rcall	I2C_ACKEN					; send master acknowledge
 	movff	SSP1BUF,xA+1				; store raw temperature, high byte
-	bsf		SSP1CON2,RCEN				; enable receive mode
-	rcall	WaitMSSP					; wait for TX to complete
+	rcall	I2C_RCEN					; enable receive mode
 	movff	SSP1BUF,xA+0				; store raw temperature, low byte
 	rcall	I2C_MasterNotAckStop				; Master NOT acknowledge and Stop
 
-	; convert temperature from raw value to Kelvin
+	; convert temperature from raw value to Kelvin in 0.1K
 	MOVLI	.6000,xB					; load conversion multiplicand into xB
 	call	mult16x16					; xC = xA * xB -> multiply raw value in xA with conversion multiplicand
 										; divide by 65536 instead of 65535, introducing an error of 65536/65535 = 0.002 %
 	movff	xC+2,battery_temperature+0	; divide by 65536 can easily be done by just taking the 3rd and 4th byte of the multiplication result
 	movff	xC+3,battery_temperature+1	; ...
 
+lt2942_get_temperature_common:	
 	; check if battery is being charged right now
 	btfss	cc_active					; in CC charging mode?
 	return								; NO  - not charging, done
@@ -1189,43 +1234,43 @@
 	bsf		charge_disable				;     - set      charging-inhibit signal
 	bcf		charge_enable				;     - activate charging-inhibit signal
 	bsf		battery_overtemp			;     - flag that the battery charging over-temperature protection has tripped
-	return								;     - done
+	return							;     - done
 
+LTC2959_get_temperature:	
+	return
+    
 
 ;-----------------------------------------------------------------------------
 ; Read Gauge IC - Read State of Charge
 ;
-	global	lt2942_get_accumulated_charge
 lt2942_get_accumulated_charge:			; read accumulated charge and compute percent
+    	btfsc	battery_gauge_type			; =1: Gauge IC LTC2959, =0: LTC2942
+	bra	LTC2959_get_accumulated_charge
+    
+	; old LTC2942
 	movlw	0x00						; point to status register
 	rcall	I2C_TX_GAUGE				; send    byte to   the LT2942 gauge IC
 	rcall	I2C_RX_GAUGE				; receive byte from the LT2942 Gauge IC
-	bsf		SSP1CON2,ACKEN				; master acknowledge
-	rcall	WaitMSSP					; wait for TX to complete
+	rcall	I2C_ACKEN					; send master acknowledge
 	movff	SSP1BUF,gauge_status_byte	; copy received byte to gauge_status_byte
 
-	bsf		SSP1CON2,RCEN				; enable receive mode
-	rcall	WaitMSSP					; wait for TX to complete					; dummy read (control byte)
-	movf	SSP1BUF,W					; dump to WREG
-	bsf		SSP1CON2,ACKEN				; master acknowledge
-	rcall	WaitMSSP					; wait for TX to complete
+	rcall	I2C_RCEN					; enable receive mode
+	movf	SSP1BUF,W					; dump to WREG (Control)
+	rcall	I2C_ACKEN					; send master acknowledge
 
-	bsf		SSP1CON2,RCEN				; enable receive mode
-	rcall	WaitMSSP					; wait for TX to complete
+	rcall	I2C_RCEN					; enable receive mode
 	movff	SSP1BUF,sub_a+1				; copy received byte to sub_a+1
-	bsf		SSP1CON2,ACKEN				; master acknowledge
-	rcall	WaitMSSP					; wait for TX to complete
+	rcall	I2C_ACKEN					; send master acknowledge
 
-	bsf		SSP1CON2,RCEN				; enable receive mode
-	rcall	WaitMSSP					; wait for TX to complete
+	rcall	I2C_RCEN					; enable receive mode
 	movff	SSP1BUF,sub_a+0				; copy received byte to sub_a+0
 	rcall	I2C_MasterNotAckStop				; Master NOT acknowledge and Stop
 
+lt2942_get_accumulated_charge2:	
 	btfsc	gauge_status_byte,0			; UVLO event ?
-	rcall	lt2942_init_again			; YES - do an re-initialization
+	rcall	battery_gauge_init_again			; YES - do an re-initialization
 	MOVII	sub_a,battery_accumulated_charge	; save raw value
-
-	; Compute batt_percent = (charge - battery_offset) / 365
+	; Compute batt_percent = (charge - battery_offset) / capacity_xxxxxx
 	MOVII	battery_offset,sub_b		; get battery offset
 	call	subU16						; sub_c = sub_a - sub_b (with signed values)
 	clrf	batt_percent				; default batt_percent to zero
@@ -1240,12 +1285,64 @@
 	movlw	.100						; max. value is  100 %
 	cpfslt	batt_percent				; batt_percent < 100 % ?
 	movwf	batt_percent				; NO  - limit to 100 %
-	movlw	.95						; < 95 %
-	cpfsgt	batt_percent
+	movlw	battery_cycle_counter_unlock
+	cpfsgt	batt_percent				; < threshold ?
 	bcf	lock_cycle_counter			; Yes, unlock cycle counter
 	return								; done
 
+LTC2959_get_accumulated_charge:
+	movlw	0x00						; point to status register
+	rcall	I2C_TX_GAUGE				; send    byte to   the LT2942 gauge IC
+	rcall	I2C_RX_GAUGE				; receive byte from the LT2942 Gauge IC
+	rcall	I2C_ACKEN					; send master acknowledge
+	movff	SSP1BUF,gauge_status_byte	; copy received byte to gauge_status_byte
+
+	rcall	I2C_RCEN					; enable receive mode
+	movf	SSP1BUF,W					; dump to WREG (ADC Control)
+	rcall	I2C_ACKEN					; send master acknowledge
+
+	rcall	I2C_RCEN					; enable receive mode
+	movf	SSP1BUF,W					; dump to WREG (Coulumb Counter Control)
+	rcall	I2C_ACKEN					; send master acknowledge
+
+	rcall	I2C_RCEN					; enable receive mode
+	movff	SSP1BUF,xC+3				; copy received byte to xC+3
+	rcall	I2C_ACKEN					; send master acknowledge
+
+	rcall	I2C_RCEN					; enable receive mode
+	movff	SSP1BUF,xC+2				; copy received byte to xC+2
+	rcall	I2C_ACKEN					; send master acknowledge
+	
+	rcall	I2C_RCEN					; enable receive mode
+	movff	SSP1BUF,xC+1				; copy received byte to xC+1
+	rcall	I2C_ACKEN					; send master acknowledge
+
+	rcall	I2C_RCEN					; enable receive mode
+	movff	SSP1BUF,xC+0				; copy received byte to xC+0
+	rcall	I2C_MasterNotAckStop				; Master NOT acknowledge and Stop
+
+	MOVLI	.159,xB					; 159,4745717 (0,085mAh/533nAh)
+	call	div32x16				; xC:4 = xC:4 / xB:2 with xA as remainder
+
+	; clamp to 100% here
+	tstfsz	xC+2					; Devision result > 0xFFFF
+	setf	xC+0					; Yes, make sure xC:2 is 0xFFFF
+	tstfsz	xC+2					; Devision result > 0xFFFF
+	setf	xC+1					; Yes, make sure xC:2 is 0xFFFF
+	
+	movff	xC+1,sub_a+1
+	movff	xC+0,sub_a+0				; put result in sub_a:2
+;	
+;	movff	sub_a+1,gp_debug+1
+;	movff	sub_a+0,gp_debug+0
+;	
+	bra	lt2942_get_accumulated_charge2		; continue as with LT2942
+	
+	
 lt2942_set_to_zero_percent:
+    	btfsc	battery_gauge_type			; =1: Gauge IC LTC2959, =0: LT2942
+	bra	LTC2959_set_to_zero_percent
+    
 	movlw	0x02						; point to accumulated charge registers
 	rcall	I2C_TX_GAUGE				; send byte to the LT2942 gauge IC
 	movff	battery_offset+1,SSP1BUF	; send battery offset, high byte
@@ -1254,16 +1351,40 @@
 	movff	battery_offset+0,SSP1BUF	; send battery offset, low  byte
 	rcall	WaitMSSP					; wait for TX to complete
 	rcall	I2C_Check_ACK				; check for acknowledge by receiver
-	bsf		SSP1CON2,PEN				; stop condition
+	bra	I2C_PEN						; stop condition (and return)
+
+LTC2959_set_to_zero_percent:
+	; multiply battery_offset:2 with 159 and write result to LTC2959
+	
+	MOVII	battery_offset,xA
+	MOVLI	.159,xB					; 159,4745717 (0,085mAh/533nAh)
+	call	mult16x16				; xC:4 = xA:2 * xB:2
+	
+	movlw	0x03						; point to accumulated charge registers
+	rcall	I2C_TX_GAUGE				; send byte to the LT2942 gauge IC
+	movff	xC+3,SSP1BUF				; send battery offset
 	rcall	WaitMSSP					; wait for TX to complete
-	return							; done
-
+	rcall	I2C_Check_ACK				; check for acknowledge by receiver
+	movff	xC+2,SSP1BUF				; send battery offset
+	rcall	WaitMSSP					; wait for TX to complete
+	rcall	I2C_Check_ACK				; check for acknowledge by receiver
+	movff	xC+1,SSP1BUF				; send battery offset
+	rcall	WaitMSSP					; wait for TX to complete
+	rcall	I2C_Check_ACK				; check for acknowledge by receiver
+	movff	xC+0,SSP1BUF				; send battery offset
+	rcall	WaitMSSP					; wait for TX to complete
+	rcall	I2C_Check_ACK				; check for acknowledge by receiver
+	bra	I2C_PEN						; stop condition (and return)
+    
 
 ;-----------------------------------------------------------------------------
 ; Read Gauge IC - Reset Accumulating Register to 0xFFFF
 ;
 	global	lt2942_charge_done
 lt2942_charge_done:
+        btfsc	battery_gauge_type			; =1: Gauge IC LTC2959, =0: LT2942
+	bra	lt2959_charge_done
+
 	movlw	0x02						; point to accumulated charge registers
 	rcall	I2C_TX_GAUGE				; send byte to the LT2942 gauge IC
 	setf	SSP1BUF						; data byte
@@ -1272,40 +1393,55 @@
 	setf	SSP1BUF						; data byte
 	rcall	WaitMSSP					; wait for TX to complete
 	rcall	I2C_Check_ACK				; check for acknowledge by receiver
-	bsf		SSP1CON2,PEN				; stop condition
+	bra	I2C_PEN						; stop condition (and return)
+
+lt2959_charge_done:
+	; Reset Accumulating Register to 0x009EFF61 (0xFFFF * .159)
+	movlw	0x03						; point to accumulated charge registers
+	rcall	I2C_TX_GAUGE				; send byte to the LT2942 gauge IC
+	movlw	0x00
+	movwf	SSP1BUF						; data byte
+	rcall	WaitMSSP					; wait for TX to complete
+	rcall	I2C_Check_ACK				; check for acknowledge by receiver
+	movlw	0x9E
+	movwf	SSP1BUF						; data byte
 	rcall	WaitMSSP					; wait for TX to complete
-	return							; done
+	rcall	I2C_Check_ACK				; check for acknowledge by receiver
+	movlw	0xFF
+	movwf	SSP1BUF						; data byte
+	rcall	WaitMSSP					; wait for TX to complete
+	rcall	I2C_Check_ACK				; check for acknowledge by receiver
+	movlw	0x61
+	movwf	SSP1BUF						; data byte
+	rcall	WaitMSSP					; wait for TX to complete
+	rcall	I2C_Check_ACK				; check for acknowledge by receiver
+	bra	I2C_PEN						; stop condition (and return)
 
-
+	
 ;-----------------------------------------------------------------------------
 ; Helper Function - send 1 Byte to the LT2942 Gauge IC
 ;
 I2C_TX_GAUGE:
 	movwf	i2c_temp2					; save data byte to be sent
-	bsf		SSP1CON2,SEN				; start condition
-	rcall	WaitMSSP					; wait for TX to complete
-	movlw	0xC8						; address byte + Write bit
-	movff	WREG,i2c_error_vault+0				; Store address
-	movwf	SSP1BUF						; control byte
-	rcall	WaitMSSP					; wait for TX to complete
-	rcall	I2C_Check_ACK				; check for acknowledge by receiver
+	rcall	I2C_SEN						; start condition
+	movlw	0xC8						; address byte + Write bit LT2942
+	btfsc	battery_gauge_type				; =1: Gauge IC LTC2959, =0: LT2942
+	movlw	0xC6						; address byte + Write bit LTC2559
+	rcall	I2C_TX						; send byte
 	movf	i2c_temp2,W					; restore data byte to be sent
-	bra		I2C_TX						; send byte and return
+	bra	I2C_TX						; send byte and return
 
 
 ;-----------------------------------------------------------------------------
 ; Helper Function - receive 1 Byte from the LT2942 Gauge IC
 ;
 I2C_RX_GAUGE:
-	bsf		SSP1CON2,RSEN				; repeated start condition
-	rcall	WaitMSSP					; wait for TX to complete
-	movlw	0xC9	    					; address byte + Read bit
-	movff	WREG,i2c_error_vault+0				; Store address
-	movwf	SSP1BUF						; control byte
-	rcall	WaitMSSP					; wait for TX to complete
-	rcall	I2C_Check_ACK				; check for acknowledge by receiver
-	bsf		SSP1CON2,RCEN				; enable receive mode
-	bra		WaitMSSP					; wait for reception and return
+	rcall	I2C_RSEN					; repeated start condition	
+	movlw	0xC9	    					; address byte + Read bit LT2942
+	btfsc	battery_gauge_type				; =1: Gauge IC LTC2959, =0: LT2942
+	movlw	0xC7						; address byte + Read bit LTC2959
+	rcall	I2C_TX						; send byte
+	bra	I2C_RCEN					; enable receive mode
 
 
 ;-----------------------------------------------------------------------------
@@ -1315,7 +1451,7 @@
 ;
 	global	reset_battery_gauge_and_lt2942
 reset_battery_gauge_and_lt2942:
-	btfsc	battery_gauge_available		; battery gauge chip available?
+	btfsc	battery_gauge_available			; battery gauge chip available?
 	call	lt2942_charge_done			; YES - reset meter to 0xFFFF
 	;bra	reset_battery_gauge			; continue resetting gauge registers
 
@@ -1357,49 +1493,34 @@
 	movlw	.5							; max number of tries for detecting a TR module
 	movwf	hy							; initialize loop counter for tries
 I2C_probe_OSTC_rx_1:
-	bsf		SSP1CON2,SEN				; start condition
-	rcall	WaitMSSP					; wait for TX to complete
+	rcall	I2C_SEN						; start condition
 	movlw	0x50						; address byte + write bit
-	movff	WREG,i2c_error_vault+0				; Store address
-	movwf	SSP1BUF						; control byte
-	rcall	WaitMSSP					; wait for TX to complete
-	btfss	SSP1CON2,ACKSTAT			; ACK received?
+	rcall	I2C_TX						; send byte
 	bsf		ostc_rx_present				; YES - TR module detected
-	bsf		SSP1CON2,PEN				; stop condition
-	rcall	WaitMSSP					; wait for TX to complete
+	rcall	I2C_PEN						; stop condition
 	btfss	ostc_rx_present				; was a TR module detected?
 	return								; NO  - done
 
 	WAITMS	.1							; wait 1 ms
-	bsf		SSP1CON2,SEN				; start condition
-	rcall	WaitMSSP					; wait for TX to complete
+	rcall	I2C_SEN						; start condition
 	movlw	0x50						; address byte + write bit
-	movwf	SSP1BUF						; control byte
-	rcall	WaitMSSP					; wait for TX to complete
-	rcall	I2C_Check_ACK				; check for acknowledge by receiver
+	rcall	I2C_TX						; send byte
 	movlw	0x1B						; command: get firmware
-	movwf	SSP1BUF						; send command
-	rcall	WaitMSSP					; wait for TX to complete
-	rcall	I2C_Check_ACK				; check for acknowledge by receiver
-	bsf		SSP1CON2,PEN				; stop condition
-	rcall	WaitMSSP					; wait for TX to complete
+	rcall	I2C_TX						; send byte
+	rcall	I2C_PEN						; stop condition
 
 	WAITMS	.1							; wait 1 ms
 
-	bsf		SSP1CON2,SEN				; start condition
-	rcall	WaitMSSP					; wait for TX to complete
+	rcall	I2C_SEN						; start condition
 	movlw	0x51						; address byte + Read bit
 	movwf	SSP1BUF						; control byte
 	rcall	WaitMSSP					; wait for TX to complete
-	bsf		SSP1CON2,RCEN				; enable receive mode
-	rcall	WaitMSSP					; wait for TX to complete
+	rcall	I2C_RCEN					; enable receive mode
 	movff	SSP1BUF,rx_firmware_cur_major ; store as firmware version, major
-	bsf		SSP1CON2,ACKEN				  ; master acknowledge
-	rcall	WaitMSSP					; wait for TX to complete
+	rcall	I2C_ACKEN					; send master acknowledge
 
 	; last byte in read from RX circuity always with a NACK!
-	bsf		SSP1CON2,RCEN				; enable receive mode
-	rcall	WaitMSSP					; wait for TX to complete
+	rcall	I2C_RCEN					; enable receive mode
 	movff	SSP1BUF,rx_firmware_cur_minor ; store as firmware version, minor
 	rcall	I2C_MasterNotAckStop				; Master NOT acknowledge and Stop
 	
@@ -1428,44 +1549,31 @@
 ;
 	global	I2C_get_tankdata
 I2C_get_tankdata:
-	bsf		SSP1CON2,SEN				; start condition
-	rcall	WaitMSSP					; wait for TX to complete
+	rcall	I2C_SEN						; start condition
 	movlw	0x50						; address byte + write bit
-	movff	WREG,i2c_error_vault+0				; Store address
-	movwf	SSP1BUF						; control byte
-	rcall	WaitMSSP					; wait for TX to complete
-	rcall	I2C_Check_ACK				; check for acknowledge by receiver
+	rcall	I2C_TX						; send byte
 	movlw	0x1E						; read buffer2 (48 bytes)
-	movwf	SSP1BUF						; data byte
-	rcall	WaitMSSP					; wait for TX to complete
-	rcall	I2C_Check_ACK				; check for acknowledge by receiver
-	bsf		SSP1CON2,PEN				; stop condition
-	rcall	WaitMSSP					; wait for TX to complete
+	rcall	I2C_TX						; send byte
+	rcall	I2C_PEN						; stop condition
 
 	WAITMS	.1							; wait 1 ms
 
 	; read 48 bytes
-	bsf		SSP1CON2,SEN				; start condition
-	rcall	WaitMSSP					; wait for TX to complete
+	rcall	I2C_SEN						; start condition
 	movlw	0x51						; address byte + read bit
-	movwf	SSP1BUF						; control byte
-	rcall	WaitMSSP					; wait for TX to complete
-	rcall	I2C_Check_ACK				; check for acknowledge by receiver
+	rcall	I2C_TX						; send byte
 	movlw	.47							; 47 with ACK + 1 w/o ACK
 	movwf	i2c_temp2					; initialize loop counter
 	lfsr	FSR2,rx_buffer				; point to start of rx data buffer 
 I2C_get_tankdata_loop_read:
-	bsf		SSP1CON2,RCEN				; enable receive mode
-	rcall	WaitMSSP					; wait for TX to complete
+	rcall	I2C_RCEN					; enable receive mode
 	movff	SSP1BUF,POSTINC2			; copy received byte to the rx buffer
 	bcf		SSP1CON2,ACKDT				; reset ACKDT flag
-	bsf		SSP1CON2,ACKEN				; master acknowledge
-	rcall	WaitMSSP					; wait for TX to complete
+	rcall	I2C_ACKEN					; send master acknowledge
 	decfsz	i2c_temp2,F					; decrement loop counter, done?
 	bra		I2C_get_tankdata_loop_read	; NO  - loop
 	; read last byte without ACK
-	bsf		SSP1CON2,RCEN				; enable receive mode
-	rcall	WaitMSSP					; wait for TX to complete
+	rcall	I2C_RCEN					; enable receive mode
 	movff	SSP1BUF,POSTINC2			; copy received byte to the rx buffer
 	rcall	I2C_MasterNotAckStop				; Master NOT acknowledge and Stop
 	return							; done
@@ -1485,46 +1593,35 @@
 	movlw	.64							; initialize loop counter: 64 byte with ACK
 	movwf	i2c_temp2					; ...
 	; address write
-	bsf		SSP1CON2,SEN				; start condition
-	rcall	WaitMSSP					; wait for TX to complete
+	rcall	I2C_SEN						; start condition
 	movlw	0x50						; address byte + write bit
-	movff	WREG,i2c_error_vault+0				; Store address
-	movwf	SSP1BUF						; control byte
-	rcall	WaitMSSP					; wait for TX to complete
-	rcall	I2C_Check_ACK				; check for acknowledge by receiver
+	rcall	I2C_TX						; send byte
 	; write 64 bytes
 I2C_update_OSTC_loop:
 	TBLRD*+								; read a byte from program memory
 	movff	TABLAT,POSTINC2				; copy to send buffer
-	movff	TABLAT,SSP1BUF				; copy to I2C data buffer
-	rcall	WaitMSSP					; wait for TX to complete
-	rcall	I2C_Check_ACK				; check for acknowledge by receiver
+	movf	TABLAT,W				; copy to W
+	rcall	I2C_TX						; send byte
 	decfsz	i2c_temp2,F					;decrement loop counter, became zero?
 	bra		I2C_update_OSTC_loop		; NO  - loop
-	bsf		SSP1CON2,PEN				; YES - stop condition
-	rcall	WaitMSSP					;     - wait for TX to complete
+	rcall	I2C_PEN						; stop condition
 	WAITMS	.1							;     - wait another 1 ms
 	; setup for read-back
 	lfsr	FSR2,buffer					; reset pointer to begin of send buffer
 	movlw	.63							; initialize loop counter: 63 byte with ACK + 1 w/o ACK
 	movwf	i2c_temp2					; ...
 	; address read-back
-	bsf		SSP1CON2,SEN				; start condition
-	rcall	WaitMSSP					; wait for TX to complete
+	rcall	I2C_SEN						; start condition
 	movlw	0x51						; address byte + read bit
-	movwf	SSP1BUF						; control byte
-	rcall	WaitMSSP					; wait for TX to complete
-	rcall	I2C_Check_ACK				; check for acknowledge by receiver
+	rcall	I2C_TX						; send byte
 	; read-back 64 bytes
 I2C_update_OSTC_loop_read:
-	bsf		SSP1CON2,RCEN				; enable receive mode
-	rcall	WaitMSSP					; wait for TX to complete
+	rcall	I2C_RCEN					; enable receive mode
 	movf	SSP1BUF,W					; copy received byte to WREG
 	cpfseq	POSTINC2					; compare read-back byte with sent byte, equal?
 	bsf		i2c_error_flag				; NO  - not equal, set error flag
 	bcf		SSP1CON2,ACKDT				; reset ACKDT flag
-	bsf		SSP1CON2,ACKEN				; master acknowledge
-	rcall	WaitMSSP					; wait for TX to complete
+	rcall	I2C_ACKEN					; send master acknowledge
 	decfsz	i2c_temp2,F					; decrement loop counter, became zero?
 	bra		I2C_update_OSTC_loop_read	; NO  - loop
 	; 1 w/o ACK
@@ -1536,18 +1633,12 @@
 	rcall	I2C_MasterNotAckStop				; Master NOT acknowledge and Stop
 	WAITMS	.1
 	; address commit
-	bsf		SSP1CON2,SEN				; start condition
-	rcall	WaitMSSP					; wait for TX to complete
+	rcall	I2C_SEN						; start condition
 	movlw	0x50						; address byte + write bit
-	movwf	SSP1BUF						; control byte
-	rcall	WaitMSSP					; wait for TX to complete
-	rcall	I2C_Check_ACK				; check for acknowledge by receiver
+	rcall	I2C_TX						; send byte
 	movlw	0x1F						; write command
-	movwf	SSP1BUF						; data byte
-	rcall	WaitMSSP					; wait for TX to complete
-	rcall	I2C_Check_ACK				; check for acknowledge by receiver
-	bsf		SSP1CON2,PEN				; stop condition
-	rcall	WaitMSSP					; wait for TX to complete
+	rcall	I2C_TX						; send byte
+	rcall	I2C_PEN						; stop condition
 	WAITMS	.5							; required waiting time
 	; error check
 	btfss	i2c_error_flag				; did an error occur?
@@ -1564,70 +1655,49 @@
  	global	I2C_probe_pressure_sensor	; Do not call from ISR!
 I2C_probe_pressure_sensor:						; Probe the type of sensor, set/clear press_sensor_type
 	bcf	press_sensor_type				; MS5541 as default
-	bsf	SSP1CON2,SEN					; start condition
-	rcall	WaitMSSP					; wait for TX to complete
+	rcall	I2C_SEN						; start condition
 	movlw	0xEC						; address byte + write bit
-	movff	WREG,i2c_error_vault+0				; Store address
 	movwf	SSP1BUF						; control byte
 	rcall	WaitMSSP					; wait for TX to complete
+	; we need the ACKSTAT bit! Do not use I2C_TX routine here which might reset this bit!
 	btfss	SSP1CON2,ACKSTAT				; ACK received?
 	bsf	press_sensor_type				; MS5837 sensor found
-	bsf	SSP1CON2,PEN					; stop condition
-	rcall	WaitMSSP					; wait for TX to complete
-	return
+	bra	I2C_PEN						; stop condition
  
 ;--------------------------------------------------------------------
 ; Helper Function - get the calibration parameter from # WREG address
 ; Do not call from ISR!
 I2C_get_calib_parameter:
 	movwf	lo						; store address
-	bsf	SSP1CON2,SEN					; start condition
-	rcall	WaitMSSP					; wait for TX to complete
+	rcall	I2C_SEN						; start condition
 	movlw	0xEC						; address byte + write bit
-	movff	WREG,i2c_error_vault+0				; Store address
 	rcall	I2C_TX						; send byte
 	movf	lo,W						; Point to calibration register
 	rcall	I2C_TX						; send byte
-	bsf	SSP1CON2,PEN					; stop condition
-	rcall	WaitMSSP					; wait for TX to complete
+	rcall	I2C_PEN						; stop condition
 	
-	bsf	SSP1CON2,SEN				; start condition
-	rcall	WaitMSSP				; wait for TX to complete
+	rcall	I2C_SEN						; start condition
 	movlw	0xED					; address byte + read bit
-	movff	WREG,i2c_error_vault+0				; Store address
-	movwf	SSP1BUF					; control byte
-	rcall	WaitMSSP				; wait for TX to complete
-	rcall	I2C_Check_ACK				; check for acknowledge by receiver
-	bsf	SSP1CON2,RCEN				; enable receive mode
-	rcall	WaitMSSP				; wait for reception and return
+	rcall	I2C_TX						; send byte 
+	rcall	I2C_RCEN					; enable receive mode
 	movff	SSP1BUF,dMSB				; High byte
-	bsf	SSP1CON2,ACKEN					; master acknowledge
-	rcall	WaitMSSP					; wait for TX to complete
-	
-	bsf	SSP1CON2,RCEN					; enable receive mode
-	rcall	WaitMSSP					; wait for reception
+	rcall	I2C_ACKEN					; send master acknowledge
+
+	rcall	I2C_OneByteRX_NACK			; receive last byte with not acknowledge
 	movff	SSP1BUF,dLSB				; Low byte
-;	bsf	SSP1CON2,ACKDT					; set ACKDT flag
-	bsf	SSP1CON2,ACKEN					; master acknowledge
-	rcall	WaitMSSP					; wait for TX to complete
-;	bcf	SSP1CON2,ACKDT					; reset ACKDT flag
-	bsf	SSP1CON2,PEN					; stop condition
-	bra	WaitMSSP					; wait for TX to complete (And return)
+	bra	I2C_PEN						; stop condition
     
 	
 	global	I2C_get_calib_MS5837 ; Do not call from ISR!
 I2C_get_calib_MS5837:	
 	banksel	common
 	; first, send a reset
-	bsf	SSP1CON2,SEN					; start condition
-	rcall	WaitMSSP					; wait for TX to complete
+	rcall	I2C_SEN						; start condition
 	movlw	0xEC						; address byte + write bit
-	movff	WREG,i2c_error_vault+0				; Store address
 	rcall	I2C_TX						; send byte
 	movlw	0x1E
 	rcall	I2C_TX						; send byte
-	bsf	SSP1CON2,PEN					; stop condition
-	rcall	WaitMSSP					; wait for TX to complete
+	rcall	I2C_PEN						; stop condition
 	WAITMS	.5						; 2.8ms according to datasheet
 	
 	movlw	0xA2						; Point to C1
@@ -1664,98 +1734,86 @@
 
 	global	I2C_get_press_val_MS5837
 I2C_get_press_val_MS5837:
-	bsf	SSP1CON2,SEN					; start condition
-	rcall	WaitMSSP					; wait for TX to complete
+    	btfsc	i2c_reinit_sensor2				; Sensor ok?
+	rcall	I2CReset					; Try a I2C reset first
+	btfsc	i2c_reinit_sensor2				; Sensor ok?
+	bra	I2C_get_press_val_MS5837_skip			; We did a reset, restart conversion first
+	
+	rcall	I2C_SEN						; start condition
 	movlw	0xEC						; address byte + write bit
-	movff	WREG,i2c_error_vault+0				; Store address
 	rcall	I2C_TX						; send byte
 	movlw	0x00						; command byte (0x00, read ADC)
 	rcall	I2C_TX						; send byte
 	
-	bsf	SSP1CON2,RSEN				; repeated start condition
-	rcall	WaitMSSP				; wait for TX to complete
+	rcall	I2C_RSEN					; repeated start condition	
 	movlw	0xED					; address byte + read bit
-	movff	WREG,i2c_error_vault+0				; Store address
-	movwf	SSP1BUF					; control byte
-	rcall	WaitMSSP				; wait for TX to complete
-	rcall	I2C_Check_ACK				; check for acknowledge by receiver
+	rcall	I2C_TX						; send byte
 
 	bsf	i2c_busy_pressure				; reading new pressure
-	bsf	SSP1CON2,RCEN				; enable receive mode
-	rcall	WaitMSSP				; wait for reception and return
+	rcall	I2C_RCEN					; enable receive mode
 	movff	SSP1BUF,D1_buffer+2					; Upper byte
-	bsf	SSP1CON2,ACKEN					; master acknowledge
-	rcall	WaitMSSP					; wait for TX to complete
-	bsf	SSP1CON2,RCEN					; enable receive mode
-	rcall	WaitMSSP					; wait for reception
+	rcall	I2C_ACKEN					; send master acknowledge
+	rcall	I2C_RCEN					; enable receive mode
 	movff	SSP1BUF,D1_buffer+1					; high byte
-	bsf	SSP1CON2,ACKEN					; master acknowledge
-	rcall	WaitMSSP					; wait for TX to complete
-	bsf	SSP1CON2,RCEN					; enable receive mode
-	rcall	WaitMSSP					; wait for reception
+	rcall	I2C_ACKEN					; send master acknowledge
+	rcall	I2C_RCEN					; enable receive mode
 	movff	SSP1BUF,D1_buffer+0					; Low byte
 
 	rcall	I2C_MasterNotAckStop				; Master NOT acknowledge and Stop
 	bcf	i2c_busy_pressure				; reading new pressure done.
-	
+
+I2C_get_press_val_MS5837_skip:	
 	; Start temperature measurement
-	bsf	SSP1CON2,SEN					; start condition
-	rcall	WaitMSSP					; wait for TX to complete
+	rcall	I2C_SEN						; start condition
 	movlw	0xEC						; address byte + write bit
 	rcall	I2C_TX						; send byte
 	movlw	0x58						; OSR=4096, type=D2
 	rcall	I2C_TX						; send byte
-	bsf	SSP1CON2,PEN					; stop condition
-	rcall	WaitMSSP					; wait for TX to complete
+	rcall	I2C_PEN						; stop condition
 	bcf	ms5837_state					; =0: result of temperature will be in the ADC
+	bcf	i2c_reinit_sensor2				; Clear error flag
     	return
 	
 	global	I2C_get_temp_val_MS5837	
 I2C_get_temp_val_MS5837:
-	bsf	SSP1CON2,SEN					; start condition
-	rcall	WaitMSSP					; wait for TX to complete
+	btfsc	i2c_reinit_sensor2				; Sensor ok?
+	rcall	I2CReset					; Try a I2C reset first
+	btfsc	i2c_reinit_sensor2				; Sensor ok?
+	bra	I2C_get_temp_val_MS5837_skip			; We did a reset, restart conversion first
+	
+	rcall	I2C_SEN						; start condition
 	movlw	0xEC						; address byte + write bit
-	movff	WREG,i2c_error_vault+0				; Store address
 	rcall	I2C_TX						; send byte
 	movlw	0x00						; command byte (0x00, read ADC)
 	rcall	I2C_TX						; send byte
 	
-	bsf	SSP1CON2,RSEN				; repeated start condition
-	rcall	WaitMSSP				; wait for TX to complete
+	rcall	I2C_RSEN					; repeated start condition	
 	movlw	0xED					; address byte + read bit
-	movff	WREG,i2c_error_vault+0				; Store address
-	movwf	SSP1BUF					; control byte
-	rcall	WaitMSSP				; wait for TX to complete
-	rcall	I2C_Check_ACK				; check for acknowledge by receiver
+	rcall	I2C_TX						; send byte
 
 	bsf	i2c_busy_temperature				; reading new temperature
-	bsf	SSP1CON2,RCEN				; enable receive mode
-	rcall	WaitMSSP				; wait for reception and return
+	rcall	I2C_RCEN					; enable receive mode
 	movff	SSP1BUF,D2_buffer+2					; Upper byte
-	bsf	SSP1CON2,ACKEN					; master acknowledge
-	rcall	WaitMSSP					; wait for TX to complete
-	bsf	SSP1CON2,RCEN					; enable receive mode
-	rcall	WaitMSSP					; wait for reception
+	rcall	I2C_ACKEN					; send master acknowledge
+	rcall	I2C_RCEN					; enable receive mode
 	movff	SSP1BUF,D2_buffer+1					; high byte
-	bsf	SSP1CON2,ACKEN					; master acknowledge
-	rcall	WaitMSSP					; wait for TX to complete
-	bsf	SSP1CON2,RCEN					; enable receive mode
-	rcall	WaitMSSP					; wait for reception
+	rcall	I2C_ACKEN					; send master acknowledge
+	rcall	I2C_RCEN					; enable receive mode
 	movff	SSP1BUF,D2_buffer+0					; Low byte
 
 	rcall	I2C_MasterNotAckStop				; Master NOT acknowledge and Stop
 	bcf	i2c_busy_temperature				; reading new temperature done.
-	
+
+I2C_get_temp_val_MS5837_skip:	
 	; Start pressure measurement
-	bsf	SSP1CON2,SEN					; start condition
-	rcall	WaitMSSP					; wait for TX to complete
+	rcall	I2C_SEN						; start condition
 	movlw	0xEC						; address byte + write bit
 	rcall	I2C_TX						; send byte
 	movlw	0x48						; OSR=4096, type=D1
 	rcall	I2C_TX						; send byte
-	bsf	SSP1CON2,PEN					; stop condition
-	rcall	WaitMSSP					; wait for TX to complete
+	rcall	I2C_PEN						; stop condition
 	bsf	ms5837_state					; =0: result of pressure will be in the ADC
+	bcf	i2c_reinit_sensor2				; Clear error flag
 	return
 	
 	
@@ -1767,6 +1825,7 @@
 check_i2c_error:
 	btfss	i2c_error_flag
 	return
+	bcf	i2c_error_flag_lock				; arm error vault again
 	incf	message_counter,F				; increase message counter
 	goto	TFT_message_i2c_error				; show message for battery low (battery percent) and return