0
+ − 1 ;=============================================================================
+ − 2 ;
+ − 3 ; File i2c.asm
+ − 4 ;
+ − 5 ; I2C Interface to HMC5883L and MMA8452Q
+ − 6 ;
+ − 7 ; HMC5883L's read address (8-Bit): 0x3D
+ − 8 ; HMC5883L's write address (8-Bit): 0x3C
+ − 9 ;
+ − 10 ; MMA8452Q's read address (8-Bit): 0x39
+ − 11 ; MMA8452Q's write address (8-Bit): 0x38
+ − 12 ;
+ − 13 ; Copyright (c) 2012, JD Gascuel, HeinrichsWeikamp, all right reserved.
+ − 14 ;=============================================================================
+ − 15 ; HISTORY
+ − 16 ; 2012-08-22 : [mH] Creation
+ − 17
+ − 18
275
+ − 19 #include "hwos.inc" ; Mandatory header
0
+ − 20 #include "wait.inc"
113
+ − 21 #include "math.inc"
+ − 22
200
+ − 23 #DEFINE battery_offset .29065 ; 65536-(3,1Ah/0,085mAh)
+ − 24 #DEFINE battery_devider .365 ; 3,1Ah/0,085mAh/100 [%]
0
+ − 25
+ − 26 i2c CODE
+ − 27
+ − 28 WaitMSSP:
+ − 29 decfsz i2c_temp,F ; check for timeout during I2C action
+ − 30 bra WaitMSSP2
+ − 31 bra I2CFail ; timeout occured
+ − 32 WaitMSSP2:
+ − 33 btfss PIR1,SSPIF
+ − 34 bra WaitMSSP
+ − 35 clrf i2c_temp
+ − 36 bcf PIR1,SSPIF
+ − 37 nop
+ − 38 return
+ − 39
+ − 40 I2C_WaitforACK:
+ − 41 btfss SSPCON2,ACKSTAT ; checks for ACK bit from slave
+ − 42 return
+ − 43 I2CFail:
+ − 44 rcall I2CReset ; I2C Reset
+ − 45 bcf PIR1,SSPIF
+ − 46 clrf i2c_temp
+ − 47 return
+ − 48
+ − 49 I2CReset: ; Something went wrong (Slave holds SDA low?)
+ − 50 clrf SSP1CON1 ; wake-up slave and reset entire module
+ − 51 clrf SSP1CON2
+ − 52 clrf SSP1STAT
+ − 53 bcf TRISC,3 ; SCL OUTPUT
+ − 54 bsf TRISC,4 ; SDA Input
+ − 55 bcf PORTC,3
+ − 56 movlw d'9'
+ − 57 movwf i2c_temp ; clock-out 9 clock cycles manually
+ − 58 I2CReset_1:
+ − 59 bsf PORTC,3 ; SCL=1
+ − 60 nop
+ − 61 nop
+ − 62 nop
+ − 63 nop
+ − 64 btfsc PORTC,4 ; SDA=1?
+ − 65 bra I2CReset_2 ; =1, SDA has been released from slave
+ − 66 bcf PORTC,3 ; SCL=0
+ − 67 nop
+ − 68 nop
+ − 69 bcf PORTC,3
+ − 70 nop
+ − 71 nop
+ − 72 decfsz i2c_temp,F
+ − 73 bra I2CReset_1 ; check for nine clock cycles
+ − 74 I2CReset_2:
+ − 75 bsf TRISC,3 ; SCL Input
+ − 76 clrf SSP1CON1 ; setup I²C Mode
+ − 77 WAITMS d'10' ; Reset-Timeout for I2C devices
+ − 78 movlw b'00000000' ; with slew rate control
+ − 79 movwf SSPSTAT
+ − 80 movlw b'00101000'
+ − 81 movwf SSP1CON1
+ − 82 movlw b'00000000'
+ − 83 movwf SSP1CON2
+ − 84 movlw 0x27
+ − 85 movwf SSP1ADD
+ − 86 return
+ − 87
+ − 88 I2C_TX:
+ − 89 movwf SSP1BUF
+ − 90 rcall WaitMSSP
+ − 91 bra I2C_WaitforACK ; Returns...
+ − 92
+ − 93 I2C_TwoBytesRX_div16: ; Get two bytes and devide lo:hi/16 (signed)
+ − 94 rcall I2C_OneByteRX ; Get one byte
+ − 95 movff SSP1BUF,hi ; Data Byte
+ − 96 rcall I2C_OneByteRX ; Get one byte
+ − 97 movff SSP1BUF,lo ; Data Byte
+ − 98 I2C_TwoBytesRX_div16_2: ; devide lo:hi/16 (signed) only
+ − 99 bcf STATUS,C
+ − 100 btfsc hi,7 ; Copy sign bit to carry
+ − 101 bsf STATUS,C
+ − 102 rrcf hi ; /2
+ − 103 rrcf lo
+ − 104 bcf STATUS,C
+ − 105 btfsc hi,7 ; Copy sign bit to carry
+ − 106 bsf STATUS,C
+ − 107 rrcf hi ; /4
+ − 108 rrcf lo
+ − 109 bcf STATUS,C
+ − 110 btfsc hi,7 ; Copy sign bit to carry
+ − 111 bsf STATUS,C
+ − 112 rrcf hi ; /8
+ − 113 rrcf lo
+ − 114 bcf STATUS,C
+ − 115 btfsc hi,7 ; Copy sign bit to carry
+ − 116 bsf STATUS,C
+ − 117 rrcf hi ; /16
+ − 118 rrcf lo
+ − 119 return
+ − 120
+ − 121 global I2C_RX_accelerometer
+ − 122 I2C_RX_accelerometer:
+ − 123 bsf SSP1CON2,SEN ; Start condition
+ − 124 rcall WaitMSSP
+ − 125 movlw 0x38 ; address
+ − 126 rcall I2C_TX
158
+ − 127 movlw 0x00
0
+ − 128 rcall I2C_TX
+ − 129 bsf SSP1CON2,RSEN ; Repeated start condition (!)
+ − 130 rcall WaitMSSP
+ − 131 movlw 0x39 ; address
+ − 132 rcall I2C_TX
+ − 133
158
+ − 134 rcall I2C_OneByteRX ; Get Status Byte
+ − 135 movf SSP1BUF,W
+ − 136
166
+ − 137 ; Non-flipped screen:
0
+ − 138 ; Chip orientation on the PCB requires
+ − 139 ; Original = Corrected
+ − 140 ; x = -x
+ − 141 ; y = -y
+ − 142 ; z = -z
+ − 143
166
+ − 144 ; Flipped screen:
+ − 145 ; Chip orientation on the PCB requires
+ − 146 ; Original = Corrected
+ − 147 ; x = x
+ − 148 ; y = y
+ − 149 ; z = -z
+ − 150
0
+ − 151 rcall I2C_TwoBytesRX_div16 ; Get two bytes and devide /16 (signed)
166
+ − 152 btfsc flip_screen ; 180° rotation ?
+ − 153 bra I2C_RX_accelerometer2 ; Yes
0
+ − 154 comf hi ; 16bit sign change.
+ − 155 negf lo
+ − 156 btfsc STATUS,C ; Carry to propagate ?
+ − 157 incf hi,F ; YES: do it.
166
+ − 158 I2C_RX_accelerometer2:
0
+ − 159 movff lo,accel_DX+0
+ − 160 movff hi,accel_DX+1 ; Copy result
+ − 161
+ − 162 rcall I2C_TwoBytesRX_div16 ; Get two bytes and devide /16 (signed)
166
+ − 163 btfsc flip_screen ; 180° rotation ?
+ − 164 bra I2C_RX_accelerometer3 ; Yes
0
+ − 165 comf hi ; 16bit sign change.
+ − 166 negf lo
+ − 167 btfsc STATUS,C ; Carry to propagate ?
+ − 168 incf hi,F ; YES: do it.
166
+ − 169 I2C_RX_accelerometer3:
0
+ − 170 movff lo,accel_DY+0
+ − 171 movff hi,accel_DY+1 ; Copy result
+ − 172
+ − 173 rcall I2C_OneByteRX ; Get one byte
+ − 174 movff SSP1BUF,hi ; Data Byte
+ − 175 bsf SSP1CON2, RCEN ; Enable recieve mode
+ − 176 rcall WaitMSSP
+ − 177 ; According to datasheet there should be no Master Acknowlegde for the last Byte (accel_DZ+0)...
+ − 178 movff SSP1BUF,lo ; Data Byte
+ − 179
+ − 180 rcall I2C_TwoBytesRX_div16_2; devide lo:hi/16 (signed) only
+ − 181 comf hi ; 16bit sign change.
+ − 182 negf lo
+ − 183 btfsc STATUS,C ; Carry to propagate ?
+ − 184 incf hi,F ; YES: do it.
+ − 185 movff lo,accel_DZ+0
+ − 186 movff hi,accel_DZ+1 ; Copy result
+ − 187
+ − 188 bsf SSP1CON2,PEN ; Stop condition
+ − 189 rcall WaitMSSP
+ − 190 return
+ − 191
+ − 192 I2C_OneByteRX:
+ − 193 bsf SSP1CON2, RCEN ; Enable recieve mode
+ − 194 rcall WaitMSSP
+ − 195 bsf SSP1CON2,ACKEN ; Master acknowlegde
+ − 196 rcall WaitMSSP
+ − 197 return
+ − 198
+ − 199 global I2C_RX_compass
+ − 200 I2C_RX_compass:
+ − 201 bsf SSP1CON2,SEN ; Start condition
+ − 202 rcall WaitMSSP
+ − 203 movlw 0x3C ; address
+ − 204 rcall I2C_TX
+ − 205 movlw 0x03
+ − 206 rcall I2C_TX
+ − 207 bsf SSP1CON2,PEN ; Stop condition
+ − 208 rcall WaitMSSP
+ − 209
+ − 210 bcf PIR1,SSPIF
+ − 211 bsf SSP1CON2,SEN ; Start condition
+ − 212 rcall WaitMSSP
+ − 213 movlw 0x3D ; address
+ − 214 rcall I2C_TX
+ − 215
+ − 216 ; Compass IC sends data in following order:
+ − 217 ; x MSB
+ − 218 ; x LSB
+ − 219 ; z MSB
+ − 220 ; z LSB
+ − 221 ; y MSB
+ − 222 ; y LSB
+ − 223
166
+ − 224 ; Non-flipped screen
0
+ − 225 ; Chip orientation on the PCB requires
+ − 226 ; Original = Corrected
+ − 227 ; x = -y
+ − 228 ; z = z
+ − 229 ; y = x
+ − 230
166
+ − 231 ; Flipped screen
+ − 232 ; Chip orientation on the PCB requires
+ − 233 ; Original = Corrected
+ − 234 ; x = y
+ − 235 ; z = z
+ − 236 ; y = -x
+ − 237
0
+ − 238 rcall I2C_OneByteRX ; Get one byte
+ − 239 movff SSP1BUF,compass_DY+1; Data Byte
+ − 240 rcall I2C_OneByteRX ; Get one byte
+ − 241 movff SSP1BUF,compass_DY+0; Data Byte
166
+ − 242 btfsc flip_screen ; 180° rotation ?
+ − 243 bra I2C_RX_compass2 ; Yes
0
+ − 244 banksel compass_DY
+ − 245 comf compass_DY+1 ; 16bit sign change.
+ − 246 negf compass_DY+0
+ − 247 btfsc STATUS,C ; Carry to propagate ?
+ − 248 incf compass_DY+1,F ; YES: do it.
166
+ − 249 I2C_RX_compass2:
0
+ − 250 banksel common
+ − 251 rcall I2C_OneByteRX ; Get one byte
+ − 252 movff SSP1BUF,compass_DZ+1; Data Byte
+ − 253 rcall I2C_OneByteRX ; Get one byte
+ − 254 movff SSP1BUF,compass_DZ+0; Data Byte
+ − 255 rcall I2C_OneByteRX ; Get one byte
+ − 256 movff SSP1BUF,compass_DX+1; Data Byte
+ − 257 bsf SSP1CON2, RCEN ; Enable recieve mode
+ − 258 rcall WaitMSSP
+ − 259 movff SSP1BUF,compass_DX+0; Data Byte
+ − 260 bsf SSP1CON2,PEN ; Stop condition
+ − 261 rcall WaitMSSP
166
+ − 262 btfss flip_screen ; 180° rotation ?
+ − 263 return ; No, done.
+ − 264 ; Yes, flip X
+ − 265 banksel compass_DX
+ − 266 comf compass_DX+1 ; 16bit sign change.
+ − 267 negf compass_DX+0
+ − 268 btfsc STATUS,C ; Carry to propagate ?
+ − 269 incf compass_DX+1,F ; YES: do it.
+ − 270 banksel common
0
+ − 271 return
+ − 272
+ − 273 global I2C_init_compass
+ − 274 I2C_init_compass:
+ − 275 bsf SSP1CON2,SEN ; Start condition
+ − 276 rcall WaitMSSP
+ − 277 movlw 0x3C ; address
+ − 278 rcall I2C_TX
+ − 279 movlw 0x00
+ − 280 rcall I2C_TX
+ − 281 ; movlw b'01101001' ; ConfigA: 3Hz, 8 Samples averaged, Test Mode (Positive Bias)
+ − 282 movlw b'01101000' ; ConfigA: 3Hz, 8 Samples averaged
+ − 283 rcall I2C_TX
20
+ − 284 bra I2C_init_compass_common
+ − 285
+ − 286 global I2C_init_compass_fast
+ − 287 I2C_init_compass_fast:
+ − 288 bsf SSP1CON2,SEN ; Start condition
+ − 289 rcall WaitMSSP
+ − 290 movlw 0x3C ; address
+ − 291 rcall I2C_TX
+ − 292 movlw 0x00
+ − 293 rcall I2C_TX
+ − 294 movlw b'00111000' ; ConfigA: 75Hz, 2 Samples averaged
+ − 295 ; movlw b'00111001' ; ConfigA: 75Hz, 2 Samples averaged, Test Mode (Positive Bias)
+ − 296 rcall I2C_TX
+ − 297 I2C_init_compass_common:
18
+ − 298 movff opt_compass_gain,i2c_temp ; 0-7 (230LSB/Gauss to 1370LSB/Gaus)
+ − 299 swapf i2c_temp,F
+ − 300 comf i2c_temp,F
+ − 301 bcf STATUS,C
+ − 302 rlcf i2c_temp
+ − 303 movf i2c_temp,W
+ − 304 clrf i2c_temp
0
+ − 305 rcall I2C_TX
+ − 306 movlw b'00000000' ; Continous Mode
+ − 307 rcall I2C_TX
+ − 308 bsf SSP1CON2,PEN ; Stop condition
+ − 309 rcall WaitMSSP
+ − 310 bsf compass_enabled
+ − 311 return
+ − 312
+ − 313 global I2C_sleep_compass
+ − 314 I2C_sleep_compass:
+ − 315 bsf SSP1CON2,SEN ; Start condition
+ − 316 rcall WaitMSSP
+ − 317 movlw 0x3C ; address
+ − 318 rcall I2C_TX
+ − 319 movlw 0x00
+ − 320 rcall I2C_TX
+ − 321 movlw b'01101000' ; ConfigA
+ − 322 rcall I2C_TX
+ − 323 movlw b'00100000' ; ConfigB
+ − 324 rcall I2C_TX
+ − 325 movlw b'00000010' ; Idle Mode
+ − 326 rcall I2C_TX
+ − 327 bsf SSP1CON2,PEN ; Stop condition
+ − 328 rcall WaitMSSP
+ − 329 bcf compass_enabled
+ − 330 return
+ − 331
+ − 332
+ − 333 global I2C_init_accelerometer
+ − 334 I2C_init_accelerometer:
+ − 335 rcall I2C_sleep_accelerometer ; Regs can only be changed in St.By mode
+ − 336
+ − 337 bsf SSP1CON2,SEN ; Start condition
+ − 338 rcall WaitMSSP
+ − 339 movlw 0x38 ; address
+ − 340 rcall I2C_TX
+ − 341 movlw 0x0E ; XYZ_DATA_CFG
+ − 342 rcall I2C_TX
+ − 343 movlw b'00000000' ; High pass Filter=0 , +/- 2g range
+ − 344 rcall I2C_TX
+ − 345 bsf SSP1CON2,PEN ; Stop condition
+ − 346 rcall WaitMSSP
+ − 347
+ − 348
+ − 349 bsf SSP1CON2,SEN ; Start condition
+ − 350 rcall WaitMSSP
+ − 351 movlw 0x38 ; address
+ − 352 rcall I2C_TX
+ − 353 movlw 0x2A ; CTRL_REG1
+ − 354 rcall I2C_TX
+ − 355 ; movlw b'00110000' ; CTRL_REG1: 160ms data rate, St.By Mode
+ − 356 movlw b'00110100' ; CTRL_REG1: 160ms data rate, St.By Mode, reduced noise mode
+ − 357 rcall I2C_TX
+ − 358 movlw b'00000010' ; CTRL_REG2: High Res in Active mode
+ − 359 rcall I2C_TX
+ − 360 bsf SSP1CON2,PEN ; Stop condition
+ − 361 rcall WaitMSSP
+ − 362
+ − 363 bsf SSP1CON2,SEN ; Start condition
+ − 364 rcall WaitMSSP
+ − 365 movlw 0x38 ; address
+ − 366 rcall I2C_TX
+ − 367 movlw 0x2A ; CTRL_REG1
+ − 368 rcall I2C_TX
+ − 369 ; movlw b'00110001' ; CTRL_REG1: 160ms data rate, Active Mode
+ − 370 movlw b'00110101' ; CTRL_REG1: 160ms data rate, St.By Mode, reduced noise mode, Active Mode
+ − 371 rcall I2C_TX
+ − 372 bsf SSP1CON2,PEN ; Stop condition
+ − 373 rcall WaitMSSP
+ − 374
+ − 375 return
+ − 376
+ − 377 global I2C_sleep_accelerometer
+ − 378 I2C_sleep_accelerometer:
+ − 379 bsf SSP1CON2,SEN ; Start condition
+ − 380 rcall WaitMSSP
+ − 381 movlw 0x38 ; address
+ − 382 rcall I2C_TX
+ − 383 movlw 0x2A ; CTRL_REG1
+ − 384 rcall I2C_TX
+ − 385 movlw b'00000000' ; St. By Mode
+ − 386 rcall I2C_TX
+ − 387 bsf SSP1CON2,PEN ; Stop condition
+ − 388 rcall WaitMSSP
+ − 389 return
+ − 390
113
+ − 391 global lt2942_init
+ − 392 lt2942_init: ; Setup Control register B
+ − 393 clrf i2c_temp
+ − 394 movlw 0x01 ; Point to control reg B
+ − 395 call I2C_TX_GAUGE
+ − 396 movlw b'11111000' ; Automatic conversion every two seconds
+ − 397 movff WREG, SSP1BUF ; Data Byte
+ − 398 rcall WaitMSSP
+ − 399 rcall I2C_WaitforACK
+ − 400 bsf SSP1CON2,PEN ; Stop condition
+ − 401 rcall WaitMSSP
+ − 402 return
+ − 403
+ − 404 global lt2942_get_status
+ − 405 lt2942_get_status: ; Read status register
235
+ − 406 bcf rechargeable ; Clear flag
113
+ − 407 clrf i2c_temp
+ − 408 movlw 0x00 ; Point to Status reg
+ − 409 call I2C_TX_GAUGE
+ − 410 call I2C_RX_GAUGE
+ − 411 movff SSP1BUF,WREG
+ − 412 btfss WREG,7 ; 2942 found?
235
+ − 413 bsf rechargeable ; Yes, set flag
113
+ − 414 bsf SSP1CON2,PEN ; Stop condition
+ − 415 rcall WaitMSSP
+ − 416 return
+ − 417
+ − 418
+ − 419 global lt2942_get_voltage
+ − 420 lt2942_get_voltage: ; Read battery voltage registers
+ − 421 clrf i2c_temp
+ − 422 movlw 0x08 ; Point to voltage registers
+ − 423 call I2C_TX_GAUGE
+ − 424 call I2C_RX_GAUGE
+ − 425 bsf SSP1CON2,ACKEN ; Master acknowlegde
+ − 426 rcall WaitMSSP
+ − 427 movff SSP1BUF,xA+1
+ − 428 bsf SSP1CON2, RCEN ; Enable recieve mode
+ − 429 rcall WaitMSSP
+ − 430 movff SSP1BUF,xA+0
+ − 431 bsf SSP1CON2,PEN ; Stop condition
+ − 432 rcall WaitMSSP
+ − 433
+ − 434 ; banksel common
+ − 435 ; xA:2 loaded with raw values
+ − 436 movlw LOW .6000
+ − 437 movwf xB+0
+ − 438 movlw HIGH .6000
+ − 439 movwf xB+1
+ − 440 call mult16x16 ;xA*xB=xC
+ − 441
+ − 442 ; devide xC (32bit)/65535 for result in mV (16bit)
+ − 443 movlw .16
+ − 444 movwf i2c_temp
+ − 445 lt2942_get_voltage2:
+ − 446 bcf STATUS,C
+ − 447 rrcf xC+3,F
+ − 448 rrcf xC+2,F
+ − 449 rrcf xC+1,F
+ − 450 rrcf xC+0,F
+ − 451 decfsz i2c_temp,F
+ − 452 bra lt2942_get_voltage2
+ − 453
+ − 454 ; Update battery voltage in mV
+ − 455 movff xC+1,batt_voltage+1
+ − 456 movff xC+0,batt_voltage+0
+ − 457 return
+ − 458
+ − 459 ; global lt2942_get_temperature
+ − 460 ;lt2942_get_temperature: ; Read temperature registers
+ − 461 ; clrf i2c_temp
+ − 462 ; movlw 0x0C ; Point to temperature registers
+ − 463 ; call I2C_TX_GAUGE
+ − 464 ; call I2C_RX
+ − 465 ; bsf SSP1CON2,ACKEN ; Master acknowlegde
+ − 466 ; rcall WaitMSSP
+ − 467 ; movff SSP1BUF,xA+1
+ − 468 ; bsf SSP1CON2, RCEN ; Enable recieve mode
+ − 469 ; rcall WaitMSSP
+ − 470 ; movff SSP1BUF,xA+0
+ − 471 ; bsf SSP1CON2,PEN ; Stop condition
+ − 472 ; rcall WaitMSSP
+ − 473 ;
+ − 474 ;; banksel common
+ − 475 ; ; xA:2 loaded with raw values
+ − 476 ; movlw LOW .6000
+ − 477 ; movwf xB+0
+ − 478 ; movlw HIGH .6000
+ − 479 ; movwf xB+1
+ − 480 ; call mult16x16 ;xA*xB=xC
+ − 481 ;
+ − 482 ; ; devide xC (32bit)/65535 for result in 0.1K (16bit)
+ − 483 ; movlw .16
+ − 484 ; movwf i2c_temp
+ − 485 ;lt2942_get_temperature2:
+ − 486 ; bcf STATUS,C
+ − 487 ; rrcf xC+3,F
+ − 488 ; rrcf xC+2,F
+ − 489 ; rrcf xC+1,F
+ − 490 ; rrcf xC+0,F
+ − 491 ; decfsz i2c_temp,F
+ − 492 ; bra lt2942_get_temperature2
+ − 493 ;
+ − 494 ; movff xC+1,sub_a+1
+ − 495 ; movff xC+0,sub_a+0
+ − 496 ; movlw LOW .2731 ; Kelvin to Celcius offset
+ − 497 ; movwf sub_b+0
+ − 498 ; movlw HIGH .2731 ; Kelvin to Celcius offset
+ − 499 ; movwf sub_b+1
+ − 500 ; call subU16 ; sub_c = sub_a - sub_b (with UNSIGNED values)
+ − 501 ;
+ − 502 ; ; Update batttery_temperature in 0.1°C
+ − 503 ; movff sub_c+1,battery_temperature+1
+ − 504 ; movff sub_c+0,battery_temperature+0
+ − 505 ; return
+ − 506
+ − 507 global lt2942_get_accumulated_charge
+ − 508 lt2942_get_accumulated_charge: ; Read accumulated charge and compute percent
+ − 509 clrf i2c_temp
+ − 510 movlw 0x02 ; Point to accumulated charge registers
+ − 511 call I2C_TX_GAUGE
+ − 512 call I2C_RX_GAUGE
+ − 513 bsf SSP1CON2,ACKEN ; Master acknowlegde
+ − 514 rcall WaitMSSP
+ − 515 movff SSP1BUF,sub_a+1 ; battery_acumulated_charge+1
+ − 516 bsf SSP1CON2, RCEN ; Enable recieve mode
+ − 517 rcall WaitMSSP
+ − 518 movff SSP1BUF,sub_a+0 ; battery_acumulated_charge+0
+ − 519 bsf SSP1CON2,PEN ; Stop condition
+ − 520 rcall WaitMSSP
+ − 521
+ − 522 ; Compute batt_percent
211
+ − 523 ; (charge-battery_offset)/365
113
+ − 524 movlw LOW battery_offset
+ − 525 movwf sub_b+0
+ − 526 movlw HIGH battery_offset
+ − 527 movwf sub_b+1
+ − 528 call subU16 ; sub_c = sub_a - sub_b (with signed values)
+ − 529
+ − 530 clrf batt_percent ; Set to zero
+ − 531 btfsc neg_flag ; result negative?
+ − 532 return ; Yes, done.
+ − 533
+ − 534 ; > Zero, set batt_percent properly
+ − 535 movff sub_c+0,xA+0
+ − 536 movff sub_c+1,xA+1
+ − 537 movlw LOW battery_devider
+ − 538 movwf xB+0
+ − 539 movlw HIGH battery_devider
+ − 540 movwf xB+1
+ − 541 call div16x16 ;xA/xB=xC with xA+0 as remainder, uses divB as temp variable
+ − 542 movff xC+0,batt_percent
+ − 543 return
+ − 544
+ − 545 global lt2942_charge_done
+ − 546 lt2942_charge_done: ; Reset accumulating registers to 0xFFFF
+ − 547 clrf i2c_temp
+ − 548 movlw 0x02 ; Point to accumulated charge registers
+ − 549 call I2C_TX_GAUGE
+ − 550 movlw 0xFF
+ − 551 movff WREG, SSP1BUF ; Data Byte
+ − 552 rcall WaitMSSP
+ − 553 rcall I2C_WaitforACK
+ − 554 movlw 0xFF
+ − 555 movff WREG, SSP1BUF ; Data Byte
+ − 556 rcall WaitMSSP
+ − 557 rcall I2C_WaitforACK
+ − 558 bsf SSP1CON2,PEN ; Stop condition
+ − 559 rcall WaitMSSP
+ − 560 return
+ − 561
+ − 562 I2C_TX_GAUGE: ; Sends a byte to the LT2942 Gauge IC
+ − 563 movwf i2c_temp+1 ; Data byte
+ − 564 bsf SSP1CON2,SEN ; Start condition
+ − 565 rcall WaitMSSP
+ − 566 movlw b'11001000' ; Address byte + Write bit
+ − 567 movwf SSP1BUF ; control byte
+ − 568 rcall WaitMSSP
+ − 569 rcall I2C_WaitforACK
+ − 570 movff i2c_temp+1, SSP1BUF ; Data Byte
+ − 571 rcall WaitMSSP
+ − 572 rcall I2C_WaitforACK
+ − 573 return
+ − 574
+ − 575 I2C_RX_GAUGE:
+ − 576 bsf SSP1CON2,SEN ; Start condition
+ − 577 rcall WaitMSSP
+ − 578 movlw b'11001001' ; Address byte + Read bit
+ − 579 movwf SSP1BUF ; control byte
+ − 580 rcall WaitMSSP
+ − 581 rcall I2C_WaitforACK
+ − 582 bsf SSP1CON2, RCEN ; Enable recieve mode
+ − 583 rcall WaitMSSP
+ − 584 return
+ − 585
+ − 586
0
+ − 587
+ − 588 END