'***********************************************************
'**                                                       **
'**             I2C Routines for the BX-24                **
'**       to demonstrate the use of Compass module        **
'**                                                       **
'**           Copyright 2002 - Devantech Ltd              **
'**     Commercial use of this software is prohibited     **
'**     Private and educational use only is permitted     **
'**                                                       **
'**         Written by Gerald Coe - February 2002         **
'**                                                       **
'**      Retrieved From                                   **
'** http://www.robot-electronics.co.uk/htm/cmpsbx24.shtml **                                                 **
'***********************************************************

Const SCL As Byte = 14          ' I2C clock - choose any pins you wish for SCL and SDA
Const SDA As Byte = 13          ' I2C data
'Const CmdReg  As Byte = 0        ' command register
'Const GainReg As Byte = 1        ' Max Gain register
'Const RngHigh As Byte = 2        ' High Range register
'Const RngLow  As Byte = 3        ' LowRange register

'Const Sensor1 As Byte = &He0     'Sensor 1 Hex Address

Dim I2cAck As Boolean            ' Acknowledge flag


'--------------------------------------------------------------------------------------------
' I2C subroutines follow
'--------------------------------------------------------------------------------------------

' writes I2cData to I2cReg at I2cAddr
'Write(Addr, Reg, Data)
Sub I2cByteWrite(ByVal I2cAddr As Byte, ByVal I2cReg As Byte, ByVal I2cData As Byte)
    Call I2cStart()
    Call I2cOutByte(I2cAddr)                  ' send device address
    Call I2cOutByte(I2cReg)                   ' send register address
    Call I2cOutByte(I2cData)                  ' send the data
    Call I2cStop()
End Sub

'Read(Addr, Reg) Return Byte
Function I2CByteRead(ByVal I2cAddr As Byte, ByVal I2cReg As Byte) As Byte
    Call I2cStart()
    Call I2cOutByte(I2cAddr)                  ' send device address
    Call I2cOutByte(I2cReg)                   ' send register address
    Call I2cStart()                           ' repeated start
    I2cAddr = I2cAddr+1
    Call I2cOutByte(I2cAddr)                  ' send device address with read set
    I2cAck = False                            ' setup to send Nak
    I2cByteRead = I2cInByte()                 ' get data byte with Nak
    Call I2cStop()
End Function

'Read(Addr, Reg) return Word
Function I2CWordRead(ByVal I2cAddr As Byte, ByVal I2cReg As Byte) As UnsignedInteger
    Set I2CWordRead = New UnsignedInteger
    Call I2cStart()
    Call I2cOutByte(I2cAddr)                  ' send device address
    Call I2cOutByte(I2cReg)                   ' send register address
    Call I2cStart()                           ' repeated start
    I2cAddr = I2cAddr+1
    Call I2cOutByte(I2cAddr)                  ' send device address with read set
    I2cAck = True                             ' setup to send Ack
    I2cWordRead = CuInt(I2cInByte()*256)
    I2cAck = False                            ' setup to send Nak
    I2cWordRead = I2cWordRead + CuInt(I2cInByte())
    Call I2cStop()
End Function

Sub I2cOutByte(I2cData As Byte)
    Call ShiftOut(SDA, SCL, 8, I2cData)       ' shift data out
    Call PutPin(SDA, bxInputTristate)         ' turn SDA around
    Call PutPin(SCL, bxOutputHigh)            ' and clock in the ack' bit
    Call PutPin(SCL, bxOutputLow)
End Sub

Function I2cInByte() As Byte
    I2cInByte = ShiftIn(SDA, SCL, 8)
    If I2cAck=True Then
        Call PutPin(SDA, bxOutputLow)
    Else
        Call PutPin(SDA, bxOutputHigh)
    End If
    Call PutPin(SCL, bxOutputHigh)            ' clock out the ack' bit
    Call PutPin(SCL, bxOutputLow)
End Function

Sub I2cStart()                                ' I2C start bit sequence
    Call PutPin(SDA, bxOutputHigh)
    Call PutPin(SCL, bxOutputHigh)
    Call PutPin(SDA, bxOutputLow)
    Call PutPin(SCL, bxOutputLow)
End Sub

Sub I2cStop()                                 ' I2C stop bit sequence
    Call PutPin(SDA, bxOutputLow)
    Call PutPin(SCL, bxOutputHigh)
    Call PutPin(SDA, bxOutputHigh)
End Sub
