Mercurial > public > hwos_code
diff src/i2c.asm @ 0:11d4fc797f74
init
author | heinrichsweikamp |
---|---|
date | Wed, 24 Apr 2013 19:22:45 +0200 |
parents | |
children | 4e3f133dfbf4 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/i2c.asm Wed Apr 24 19:22:45 2013 +0200 @@ -0,0 +1,354 @@ +;============================================================================= +; +; File i2c.asm +; +; I2C Interface to HMC5883L and MMA8452Q +; +; HMC5883L's read address (8-Bit): 0x3D +; HMC5883L's write address (8-Bit): 0x3C +; +; MMA8452Q's read address (8-Bit): 0x39 +; MMA8452Q's write address (8-Bit): 0x38 +; +; Copyright (c) 2012, JD Gascuel, HeinrichsWeikamp, all right reserved. +;============================================================================= +; HISTORY +; 2012-08-22 : [mH] Creation + + +#include "ostc3.inc" ; Mandatory header +#include "wait.inc" + +i2c CODE + +WaitMSSP: + decfsz i2c_temp,F ; check for timeout during I2C action + bra WaitMSSP2 + bra I2CFail ; timeout occured +WaitMSSP2: + btfss PIR1,SSPIF + bra WaitMSSP + clrf i2c_temp + bcf PIR1,SSPIF + nop + return + +I2C_WaitforACK: + btfss SSPCON2,ACKSTAT ; checks for ACK bit from slave + return +I2CFail: + rcall I2CReset ; I2C Reset + bcf PIR1,SSPIF + clrf i2c_temp + return + +I2CReset: ; Something went wrong (Slave holds SDA low?) + clrf SSP1CON1 ; wake-up slave and reset entire module + clrf SSP1CON2 + clrf SSP1STAT + bcf TRISC,3 ; SCL OUTPUT + bsf TRISC,4 ; SDA Input + bcf PORTC,3 + movlw d'9' + movwf i2c_temp ; clock-out 9 clock cycles manually +I2CReset_1: + bsf PORTC,3 ; SCL=1 + nop + nop + nop + nop + btfsc PORTC,4 ; SDA=1? + bra I2CReset_2 ; =1, SDA has been released from slave + bcf PORTC,3 ; SCL=0 + nop + nop + bcf PORTC,3 + nop + nop + decfsz i2c_temp,F + bra I2CReset_1 ; check for nine clock cycles +I2CReset_2: + bsf TRISC,3 ; SCL Input + clrf SSP1CON1 ; setup I²C Mode + WAITMS d'10' ; Reset-Timeout for I2C devices + movlw b'00000000' ; with slew rate control + movwf SSPSTAT + movlw b'00101000' + movwf SSP1CON1 + movlw b'00000000' + movwf SSP1CON2 + movlw 0x27 + movwf SSP1ADD + return + +I2C_TX: + movwf SSP1BUF + rcall WaitMSSP + bra I2C_WaitforACK ; Returns... + +I2C_TwoBytesRX_div16: ; Get two bytes and devide lo:hi/16 (signed) + rcall I2C_OneByteRX ; Get one byte + movff SSP1BUF,hi ; Data Byte + rcall I2C_OneByteRX ; Get one byte + movff SSP1BUF,lo ; Data Byte +I2C_TwoBytesRX_div16_2: ; devide lo:hi/16 (signed) only + bcf STATUS,C + btfsc hi,7 ; Copy sign bit to carry + bsf STATUS,C + rrcf hi ; /2 + rrcf lo + bcf STATUS,C + btfsc hi,7 ; Copy sign bit to carry + bsf STATUS,C + rrcf hi ; /4 + rrcf lo + bcf STATUS,C + btfsc hi,7 ; Copy sign bit to carry + bsf STATUS,C + rrcf hi ; /8 + rrcf lo + bcf STATUS,C + btfsc hi,7 ; Copy sign bit to carry + bsf STATUS,C + rrcf hi ; /16 + rrcf lo + return + + global I2C_RX_accelerometer +I2C_RX_accelerometer: + bsf SSP1CON2,SEN ; Start condition + rcall WaitMSSP + movlw 0x38 ; address + rcall I2C_TX + movlw 0x01 + rcall I2C_TX + bsf SSP1CON2,RSEN ; Repeated start condition (!) + rcall WaitMSSP + movlw 0x39 ; address + rcall I2C_TX + + ; Chip orientation on the PCB requires + ; Original = Corrected + ; x = -x + ; y = -y + ; z = -z + + + rcall I2C_TwoBytesRX_div16 ; Get two bytes and devide /16 (signed) + comf hi ; 16bit sign change. + negf lo + btfsc STATUS,C ; Carry to propagate ? + incf hi,F ; YES: do it. + movff lo,accel_DX+0 + movff hi,accel_DX+1 ; Copy result + + rcall I2C_TwoBytesRX_div16 ; Get two bytes and devide /16 (signed) + comf hi ; 16bit sign change. + negf lo + btfsc STATUS,C ; Carry to propagate ? + incf hi,F ; YES: do it. + movff lo,accel_DY+0 + movff hi,accel_DY+1 ; Copy result + + rcall I2C_OneByteRX ; Get one byte + movff SSP1BUF,hi ; Data Byte + bsf SSP1CON2, RCEN ; Enable recieve mode + rcall WaitMSSP +; According to datasheet there should be no Master Acknowlegde for the last Byte (accel_DZ+0)... + movff SSP1BUF,lo ; Data Byte + + rcall I2C_TwoBytesRX_div16_2; devide lo:hi/16 (signed) only + comf hi ; 16bit sign change. + negf lo + btfsc STATUS,C ; Carry to propagate ? + incf hi,F ; YES: do it. + movff lo,accel_DZ+0 + movff hi,accel_DZ+1 ; Copy result + + bsf SSP1CON2,PEN ; Stop condition + rcall WaitMSSP + return + +I2C_OneByteRX: + bsf SSP1CON2, RCEN ; Enable recieve mode + rcall WaitMSSP + bsf SSP1CON2,ACKEN ; Master acknowlegde + rcall WaitMSSP + return + + global I2C_RX_compass +I2C_RX_compass: + bsf SSP1CON2,SEN ; Start condition + rcall WaitMSSP + movlw 0x3C ; address + rcall I2C_TX + movlw 0x03 + rcall I2C_TX + bsf SSP1CON2,PEN ; Stop condition + rcall WaitMSSP + + bcf PIR1,SSPIF + bsf SSP1CON2,SEN ; Start condition + rcall WaitMSSP + movlw 0x3D ; address + rcall I2C_TX + + ; Compass IC sends data in following order: + ; x MSB + ; x LSB + ; z MSB + ; z LSB + ; y MSB + ; y LSB + + ; Chip orientation on the PCB requires + ; Original = Corrected + ; x = -y + ; z = z + ; y = x + + rcall I2C_OneByteRX ; Get one byte + movff SSP1BUF,compass_DY+1; Data Byte + rcall I2C_OneByteRX ; Get one byte + movff SSP1BUF,compass_DY+0; Data Byte + banksel compass_DY + comf compass_DY+1 ; 16bit sign change. + negf compass_DY+0 + btfsc STATUS,C ; Carry to propagate ? + incf compass_DY+1,F ; YES: do it. + banksel common + rcall I2C_OneByteRX ; Get one byte + movff SSP1BUF,compass_DZ+1; Data Byte + rcall I2C_OneByteRX ; Get one byte + movff SSP1BUF,compass_DZ+0; Data Byte + rcall I2C_OneByteRX ; Get one byte + movff SSP1BUF,compass_DX+1; Data Byte + bsf SSP1CON2, RCEN ; Enable recieve mode + rcall WaitMSSP + movff SSP1BUF,compass_DX+0; Data Byte + bsf SSP1CON2,PEN ; Stop condition + rcall WaitMSSP + return + + global I2C_init_compass +I2C_init_compass: + bsf SSP1CON2,SEN ; Start condition + rcall WaitMSSP + movlw 0x3C ; address + rcall I2C_TX + movlw 0x00 + rcall I2C_TX +; movlw b'01101001' ; ConfigA: 3Hz, 8 Samples averaged, Test Mode (Positive Bias) + movlw b'01101000' ; ConfigA: 3Hz, 8 Samples averaged +; movlw b'00111000' ; ConfigA: 75Hz, 2 Samples averaged + rcall I2C_TX + movlw b'00100000' ; ConfigB, 1090Gauss Gain +; movlw b'10000000' ; ConfigB, 440Gauss Gain + rcall I2C_TX + movlw b'00000000' ; Continous Mode + rcall I2C_TX + bsf SSP1CON2,PEN ; Stop condition + rcall WaitMSSP + bsf compass_enabled + return + + global I2C_init_compass_fast +I2C_init_compass_fast: + bsf SSP1CON2,SEN ; Start condition + rcall WaitMSSP + movlw 0x3C ; address + rcall I2C_TX + movlw 0x00 + rcall I2C_TX + movlw b'00111000' ; ConfigA: 75Hz, 2 Samples averaged + rcall I2C_TX + movlw b'00100000' ; ConfigB, 1090Gauss Gain + rcall I2C_TX + movlw b'00000000' ; Continous Mode + rcall I2C_TX + bsf SSP1CON2,PEN ; Stop condition + rcall WaitMSSP + bsf compass_enabled + return + + + global I2C_sleep_compass +I2C_sleep_compass: + bsf SSP1CON2,SEN ; Start condition + rcall WaitMSSP + movlw 0x3C ; address + rcall I2C_TX + movlw 0x00 + rcall I2C_TX + movlw b'01101000' ; ConfigA + rcall I2C_TX + movlw b'00100000' ; ConfigB + rcall I2C_TX + movlw b'00000010' ; Idle Mode + rcall I2C_TX + bsf SSP1CON2,PEN ; Stop condition + rcall WaitMSSP + bcf compass_enabled + return + + + global I2C_init_accelerometer +I2C_init_accelerometer: + rcall I2C_sleep_accelerometer ; Regs can only be changed in St.By mode + + bsf SSP1CON2,SEN ; Start condition + rcall WaitMSSP + movlw 0x38 ; address + rcall I2C_TX + movlw 0x0E ; XYZ_DATA_CFG + rcall I2C_TX + movlw b'00000000' ; High pass Filter=0 , +/- 2g range + rcall I2C_TX + bsf SSP1CON2,PEN ; Stop condition + rcall WaitMSSP + + + bsf SSP1CON2,SEN ; Start condition + rcall WaitMSSP + movlw 0x38 ; address + rcall I2C_TX + movlw 0x2A ; CTRL_REG1 + rcall I2C_TX +; movlw b'00110000' ; CTRL_REG1: 160ms data rate, St.By Mode + movlw b'00110100' ; CTRL_REG1: 160ms data rate, St.By Mode, reduced noise mode + rcall I2C_TX + movlw b'00000010' ; CTRL_REG2: High Res in Active mode + rcall I2C_TX + bsf SSP1CON2,PEN ; Stop condition + rcall WaitMSSP + + bsf SSP1CON2,SEN ; Start condition + rcall WaitMSSP + movlw 0x38 ; address + rcall I2C_TX + movlw 0x2A ; CTRL_REG1 + rcall I2C_TX +; movlw b'00110001' ; CTRL_REG1: 160ms data rate, Active Mode + movlw b'00110101' ; CTRL_REG1: 160ms data rate, St.By Mode, reduced noise mode, Active Mode + rcall I2C_TX + bsf SSP1CON2,PEN ; Stop condition + rcall WaitMSSP + + return + + global I2C_sleep_accelerometer +I2C_sleep_accelerometer: + bsf SSP1CON2,SEN ; Start condition + rcall WaitMSSP + movlw 0x38 ; address + rcall I2C_TX + movlw 0x2A ; CTRL_REG1 + rcall I2C_TX + movlw b'00000000' ; St. By Mode + rcall I2C_TX + bsf SSP1CON2,PEN ; Stop condition + rcall WaitMSSP + return + + + END \ No newline at end of file