mirror of
https://github.com/d0k3/GodMode9.git
synced 2025-06-26 13:42:47 +00:00
Update I2C code to newest version
This commit is contained in:
parent
7466e0a4ea
commit
9217116a68
@ -17,28 +17,25 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
#include "types.h"
|
||||||
#include "i2c.h"
|
#include "i2c.h"
|
||||||
|
|
||||||
|
|
||||||
#define I2C1_REGS_BASE (0x10161000)
|
#define I2C1_REGS_BASE (0x10161000)
|
||||||
#define REG_I2C1_DATA *((vu8* )(I2C1_REGS_BASE + 0x00))
|
|
||||||
#define REG_I2C1_CNT *((vu8* )(I2C1_REGS_BASE + 0x01))
|
|
||||||
#define REG_I2C1_CNTEX *((vu16*)(I2C1_REGS_BASE + 0x02))
|
|
||||||
#define REG_I2C1_SCL *((vu16*)(I2C1_REGS_BASE + 0x04))
|
|
||||||
|
|
||||||
#define I2C2_REGS_BASE (0x10144000)
|
#define I2C2_REGS_BASE (0x10144000)
|
||||||
#define REG_I2C2_DATA *((vu8* )(I2C2_REGS_BASE + 0x00))
|
|
||||||
#define REG_I2C2_CNT *((vu8* )(I2C2_REGS_BASE + 0x01))
|
|
||||||
#define REG_I2C2_CNTEX *((vu16*)(I2C2_REGS_BASE + 0x02))
|
|
||||||
#define REG_I2C2_SCL *((vu16*)(I2C2_REGS_BASE + 0x04))
|
|
||||||
|
|
||||||
#define I2C3_REGS_BASE (0x10148000)
|
#define I2C3_REGS_BASE (0x10148000)
|
||||||
#define REG_I2C3_DATA *((vu8* )(I2C3_REGS_BASE + 0x00))
|
|
||||||
#define REG_I2C3_CNT *((vu8* )(I2C3_REGS_BASE + 0x01))
|
|
||||||
#define REG_I2C3_CNTEX *((vu16*)(I2C3_REGS_BASE + 0x02))
|
|
||||||
#define REG_I2C3_SCL *((vu16*)(I2C3_REGS_BASE + 0x04))
|
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
vu8 REG_I2C_DATA;
|
||||||
|
vu8 REG_I2C_CNT;
|
||||||
|
vu16 REG_I2C_CNTEX;
|
||||||
|
vu16 REG_I2C_SCL;
|
||||||
|
} I2cRegs;
|
||||||
|
|
||||||
static const struct
|
static const struct
|
||||||
{
|
{
|
||||||
u8 busId;
|
u8 busId;
|
||||||
@ -67,62 +64,89 @@ static const struct
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
static void i2cWaitBusy(vu8 *cntReg)
|
static void i2cWaitBusy(I2cRegs *const regs)
|
||||||
{
|
{
|
||||||
while(*cntReg & I2C_ENABLE);
|
while(regs->REG_I2C_CNT & I2C_ENABLE);
|
||||||
}
|
}
|
||||||
|
|
||||||
static vu8* i2cGetBusRegsBase(u8 busId)
|
static I2cRegs* i2cGetBusRegsBase(u8 busId)
|
||||||
{
|
{
|
||||||
vu8 *base;
|
I2cRegs *base;
|
||||||
if(!busId) base = (vu8*)I2C1_REGS_BASE;
|
switch(busId)
|
||||||
else if(busId == 1) base = (vu8*)I2C2_REGS_BASE;
|
{
|
||||||
else base = (vu8*)I2C3_REGS_BASE;
|
case 0:
|
||||||
|
base = (I2cRegs*)I2C1_REGS_BASE;
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
base = (I2cRegs*)I2C2_REGS_BASE;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
base = (I2cRegs*)I2C3_REGS_BASE;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
base = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
return base;
|
return base;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool i2cStartTransfer(I2cDevice devId, u8 regAddr, bool read, vu8 *regsBase)
|
void I2C_init(void)
|
||||||
|
{
|
||||||
|
I2cRegs *regs = i2cGetBusRegsBase(0); // Bus 1
|
||||||
|
i2cWaitBusy(regs);
|
||||||
|
regs->REG_I2C_CNTEX = 2; // ?
|
||||||
|
regs->REG_I2C_SCL = 1280; // ?
|
||||||
|
|
||||||
|
regs = i2cGetBusRegsBase(1); // Bus 2
|
||||||
|
i2cWaitBusy(regs);
|
||||||
|
regs->REG_I2C_CNTEX = 2; // ?
|
||||||
|
regs->REG_I2C_SCL = 1280; // ?
|
||||||
|
|
||||||
|
regs = i2cGetBusRegsBase(2); // Bus 3
|
||||||
|
i2cWaitBusy(regs);
|
||||||
|
regs->REG_I2C_CNTEX = 2; // ?
|
||||||
|
regs->REG_I2C_SCL = 1280; // ?
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool i2cStartTransfer(I2cDevice devId, u8 regAddr, bool read, I2cRegs *const regs)
|
||||||
{
|
{
|
||||||
const u8 devAddr = i2cDevTable[devId].devAddr;
|
const u8 devAddr = i2cDevTable[devId].devAddr;
|
||||||
vu8 *const i2cData = regsBase;
|
|
||||||
vu8 *const i2cCnt = regsBase + 1;
|
|
||||||
|
|
||||||
|
|
||||||
u32 i = 0;
|
u32 i = 0;
|
||||||
for(; i < 8; i++)
|
for(; i < 8; i++)
|
||||||
{
|
{
|
||||||
i2cWaitBusy(i2cCnt);
|
i2cWaitBusy(regs);
|
||||||
|
|
||||||
// Select device and start.
|
// Select device and start.
|
||||||
*i2cData = devAddr;
|
regs->REG_I2C_DATA = devAddr;
|
||||||
*i2cCnt = I2C_ENABLE | I2C_IRQ_ENABLE | I2C_START;
|
regs->REG_I2C_CNT = I2C_ENABLE | I2C_IRQ_ENABLE | I2C_START;
|
||||||
i2cWaitBusy(i2cCnt);
|
i2cWaitBusy(regs);
|
||||||
if(!I2C_GET_ACK(*i2cCnt)) // If ack flag is 0 it failed.
|
if(!I2C_GET_ACK(regs->REG_I2C_CNT)) // If ack flag is 0 it failed.
|
||||||
{
|
{
|
||||||
*i2cCnt = I2C_ENABLE | I2C_IRQ_ENABLE | I2C_ERROR | I2C_STOP;
|
regs->REG_I2C_CNT = I2C_ENABLE | I2C_IRQ_ENABLE | I2C_ERROR | I2C_STOP;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Select register and change direction to write.
|
// Select register and change direction to write.
|
||||||
*i2cData = regAddr;
|
regs->REG_I2C_DATA = regAddr;
|
||||||
*i2cCnt = I2C_ENABLE | I2C_IRQ_ENABLE | I2C_DIRE_WRITE;
|
regs->REG_I2C_CNT = I2C_ENABLE | I2C_IRQ_ENABLE | I2C_DIRE_WRITE;
|
||||||
i2cWaitBusy(i2cCnt);
|
i2cWaitBusy(regs);
|
||||||
if(!I2C_GET_ACK(*i2cCnt)) // If ack flag is 0 it failed.
|
if(!I2C_GET_ACK(regs->REG_I2C_CNT)) // If ack flag is 0 it failed.
|
||||||
{
|
{
|
||||||
*i2cCnt = I2C_ENABLE | I2C_IRQ_ENABLE | I2C_ERROR | I2C_STOP;
|
regs->REG_I2C_CNT = I2C_ENABLE | I2C_IRQ_ENABLE | I2C_ERROR | I2C_STOP;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Select device in read mode for read transfer.
|
// Select device in read mode for read transfer.
|
||||||
if(read)
|
if(read)
|
||||||
{
|
{
|
||||||
*i2cData = devAddr | 1u; // Set bit 0 for read.
|
regs->REG_I2C_DATA = devAddr | 1u; // Set bit 0 for read.
|
||||||
*i2cCnt = I2C_ENABLE | I2C_IRQ_ENABLE | I2C_START;
|
regs->REG_I2C_CNT = I2C_ENABLE | I2C_IRQ_ENABLE | I2C_START;
|
||||||
i2cWaitBusy(i2cCnt);
|
i2cWaitBusy(regs);
|
||||||
if(!I2C_GET_ACK(*i2cCnt)) // If ack flag is 0 it failed.
|
if(!I2C_GET_ACK(regs->REG_I2C_CNT)) // If ack flag is 0 it failed.
|
||||||
{
|
{
|
||||||
*i2cCnt = I2C_ENABLE | I2C_IRQ_ENABLE | I2C_ERROR | I2C_STOP;
|
regs->REG_I2C_CNT = I2C_ENABLE | I2C_IRQ_ENABLE | I2C_ERROR | I2C_STOP;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -134,62 +158,68 @@ static bool i2cStartTransfer(I2cDevice devId, u8 regAddr, bool read, vu8 *regsBa
|
|||||||
else return false;
|
else return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void I2C_init(void)
|
|
||||||
{
|
|
||||||
i2cWaitBusy(i2cGetBusRegsBase(0) + 1);
|
|
||||||
REG_I2C1_CNTEX = 2; // ?
|
|
||||||
REG_I2C1_SCL = 1280; // ?
|
|
||||||
|
|
||||||
i2cWaitBusy(i2cGetBusRegsBase(1) + 1);
|
|
||||||
REG_I2C2_CNTEX = 2; // ?
|
|
||||||
REG_I2C2_SCL = 1280; // ?
|
|
||||||
|
|
||||||
i2cWaitBusy(i2cGetBusRegsBase(2) + 1);
|
|
||||||
REG_I2C3_CNTEX = 2; // ?
|
|
||||||
REG_I2C3_SCL = 1280; // ?
|
|
||||||
}
|
|
||||||
|
|
||||||
bool I2C_readRegBuf(I2cDevice devId, u8 regAddr, u8 *out, u32 size)
|
bool I2C_readRegBuf(I2cDevice devId, u8 regAddr, u8 *out, u32 size)
|
||||||
{
|
{
|
||||||
const u8 busId = i2cDevTable[devId].busId;
|
const u8 busId = i2cDevTable[devId].busId;
|
||||||
vu8 *const i2cData = i2cGetBusRegsBase(busId);
|
I2cRegs *const regs = i2cGetBusRegsBase(busId);
|
||||||
vu8 *const i2cCnt = i2cData + 1;
|
|
||||||
|
|
||||||
|
|
||||||
if(!i2cStartTransfer(devId, regAddr, true, i2cData)) return false;
|
if(!i2cStartTransfer(devId, regAddr, true, regs)) return false;
|
||||||
|
|
||||||
while(--size)
|
while(--size)
|
||||||
{
|
{
|
||||||
*i2cCnt = I2C_ENABLE | I2C_IRQ_ENABLE | I2C_DIRE_READ | I2C_ACK;
|
regs->REG_I2C_CNT = I2C_ENABLE | I2C_IRQ_ENABLE | I2C_DIRE_READ | I2C_ACK;
|
||||||
i2cWaitBusy(i2cCnt);
|
i2cWaitBusy(regs);
|
||||||
*out++ = *i2cData;
|
*out++ = regs->REG_I2C_DATA;
|
||||||
}
|
}
|
||||||
|
|
||||||
*i2cCnt = I2C_ENABLE | I2C_IRQ_ENABLE | I2C_DIRE_READ | I2C_STOP;
|
regs->REG_I2C_CNT = I2C_ENABLE | I2C_IRQ_ENABLE | I2C_DIRE_READ | I2C_STOP;
|
||||||
i2cWaitBusy(i2cCnt);
|
i2cWaitBusy(regs);
|
||||||
*out = *i2cData; // Last byte
|
*out = regs->REG_I2C_DATA; // Last byte
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool I2C_writeReg(I2cDevice devId, u8 regAddr, u8 data)
|
bool I2C_writeRegBuf(I2cDevice devId, u8 regAddr, const u8 *in, u32 size)
|
||||||
{
|
{
|
||||||
const u8 busId = i2cDevTable[devId].busId;
|
const u8 busId = i2cDevTable[devId].busId;
|
||||||
vu8 *const i2cData = i2cGetBusRegsBase(busId);
|
I2cRegs *const regs = i2cGetBusRegsBase(busId);
|
||||||
vu8 *const i2cCnt = i2cData + 1;
|
|
||||||
|
|
||||||
|
|
||||||
if(!i2cStartTransfer(devId, regAddr, false, i2cData)) return false;
|
if(!i2cStartTransfer(devId, regAddr, false, regs)) return false;
|
||||||
|
|
||||||
*i2cData = data;
|
while(--size)
|
||||||
*i2cCnt = I2C_ENABLE | I2C_IRQ_ENABLE | I2C_DIRE_WRITE | I2C_STOP;
|
|
||||||
i2cWaitBusy(i2cCnt);
|
|
||||||
|
|
||||||
if(!I2C_GET_ACK(*i2cCnt)) // If ack flag is 0 it failed.
|
|
||||||
{
|
{
|
||||||
*i2cCnt = I2C_ENABLE | I2C_IRQ_ENABLE | I2C_ERROR | I2C_STOP;
|
regs->REG_I2C_DATA = *in++;
|
||||||
|
regs->REG_I2C_CNT = I2C_ENABLE | I2C_IRQ_ENABLE | I2C_DIRE_WRITE;
|
||||||
|
i2cWaitBusy(regs);
|
||||||
|
if(!I2C_GET_ACK(regs->REG_I2C_CNT)) // If ack flag is 0 it failed.
|
||||||
|
{
|
||||||
|
regs->REG_I2C_CNT = I2C_ENABLE | I2C_IRQ_ENABLE | I2C_ERROR | I2C_STOP;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
regs->REG_I2C_DATA = *in;
|
||||||
|
regs->REG_I2C_CNT = I2C_ENABLE | I2C_IRQ_ENABLE | I2C_DIRE_WRITE | I2C_STOP;
|
||||||
|
i2cWaitBusy(regs);
|
||||||
|
if(!I2C_GET_ACK(regs->REG_I2C_CNT)) // If ack flag is 0 it failed.
|
||||||
|
{
|
||||||
|
regs->REG_I2C_CNT = I2C_ENABLE | I2C_IRQ_ENABLE | I2C_ERROR | I2C_STOP;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
u8 I2C_readReg(I2cDevice devId, u8 regAddr)
|
||||||
|
{
|
||||||
|
u8 data;
|
||||||
|
if(!I2C_readRegBuf(devId, regAddr, &data, 1)) return 0xFF;
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool I2C_writeReg(I2cDevice devId, u8 regAddr, u8 data)
|
||||||
|
{
|
||||||
|
return I2C_writeRegBuf(devId, regAddr, &data, 1);
|
||||||
|
}
|
||||||
|
@ -19,7 +19,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include "common.h"
|
#include "types.h"
|
||||||
|
|
||||||
|
|
||||||
#define I2C_STOP (1u)
|
#define I2C_STOP (1u)
|
||||||
@ -51,6 +51,52 @@ typedef enum
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Initializes the I2C buses. Call this only once.
|
||||||
|
*/
|
||||||
void I2C_init(void);
|
void I2C_init(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Reads data from a I2C register to a buffer.
|
||||||
|
*
|
||||||
|
* @param[in] devId The device ID. Use the enum above.
|
||||||
|
* @param[in] regAddr The register address.
|
||||||
|
* @param out The output buffer pointer.
|
||||||
|
* @param[in] size The read size.
|
||||||
|
*
|
||||||
|
* @return Returns true on success and false on failure.
|
||||||
|
*/
|
||||||
bool I2C_readRegBuf(I2cDevice devId, u8 regAddr, u8 *out, u32 size);
|
bool I2C_readRegBuf(I2cDevice devId, u8 regAddr, u8 *out, u32 size);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Writes a buffer to a I2C register.
|
||||||
|
*
|
||||||
|
* @param[in] devId The device ID. Use the enum above.
|
||||||
|
* @param[in] regAddr The register address.
|
||||||
|
* @param[in] in The input buffer pointer.
|
||||||
|
* @param[in] size The write size.
|
||||||
|
*
|
||||||
|
* @return Returns true on success and false on failure.
|
||||||
|
*/
|
||||||
|
bool I2C_writeRegBuf(I2cDevice devId, u8 regAddr, const u8 *in, u32 size);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Reads a byte from a I2C register.
|
||||||
|
*
|
||||||
|
* @param[in] devId The device ID. Use the enum above.
|
||||||
|
* @param[in] regAddr The register address.
|
||||||
|
*
|
||||||
|
* @return Returns the value read on success otherwise 0xFF.
|
||||||
|
*/
|
||||||
|
u8 I2C_readReg(I2cDevice devId, u8 regAddr);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Writes a byte to a I2C register.
|
||||||
|
*
|
||||||
|
* @param[in] devId The device ID. Use the enum above.
|
||||||
|
* @param[in] regAddr The register address.
|
||||||
|
* @param[in] data The data to write.
|
||||||
|
*
|
||||||
|
* @return Returns true on success and false on failure.
|
||||||
|
*/
|
||||||
bool I2C_writeReg(I2cDevice devId, u8 regAddr, u8 data);
|
bool I2C_writeReg(I2cDevice devId, u8 regAddr, u8 data);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user