bool I2C_writeRegBuf(I2cDevice devId, u8 regAddr, const u8 *in, u32 size) { const u8 busId = i2cDevTable[devId].busId; I2cRegs *const regs = i2cGetBusRegsBase(busId); if(!i2cStartTransfer(devId, regAddr, false, regs)) return false; while(--size) { 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 true; }
static bool i2cStartTransfer(I2cDevice devId, u8 regAddr, bool read, I2cRegs *const regs) { const u8 devAddr = i2cDevTable[devId].devAddr; u32 i = 0; for(; i < 8; i++) { i2cWaitBusy(regs); // Select device and start. regs->REG_I2C_DATA = devAddr; regs->REG_I2C_CNT = I2C_ENABLE | I2C_IRQ_ENABLE | I2C_START; 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; continue; } // Select register and change direction to write. regs->REG_I2C_DATA = regAddr; 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; continue; } // Select device in read mode for read transfer. if(read) { regs->REG_I2C_DATA = devAddr | 1u; // Set bit 0 for read. regs->REG_I2C_CNT = I2C_ENABLE | I2C_IRQ_ENABLE | I2C_START; 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; continue; } } break; } if(i < 8) return true; else return false; }
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 i2cSelectDevice(u8 bus_id, u8 dev_reg) { i2cWaitBusy(bus_id); *i2cGetDataReg(bus_id) = dev_reg; *i2cGetCntReg(bus_id) = 0xC2; return i2cGetResult(bus_id); }
static bool i2cSelectRegister(u8 bus_id, u8 reg) { i2cWaitBusy(bus_id); *i2cGetDataReg(bus_id) = reg; *i2cGetCntReg(bus_id) = 0xC0; return i2cGetResult(bus_id); }
u8 i2cReadRegister(u8 dev_id, u8 reg) { u8 bus_id = i2cGetDeviceBusId(dev_id); u8 dev_addr = i2cGetDeviceRegAddr(dev_id); for (size_t i = 0; i < 8; i++) { if (i2cSelectDevice(bus_id, dev_addr) && i2cSelectRegister(bus_id, reg)) { if (i2cSelectDevice(bus_id, dev_addr | 1)) { i2cWaitBusy(bus_id); i2cStop(bus_id, 1); i2cWaitBusy(bus_id); return *i2cGetDataReg(bus_id); } } *i2cGetCntReg(bus_id) = 0xC5; i2cWaitBusy(bus_id); } return 0xff; }
bool i2cWriteRegister(u8 dev_id, u8 reg, u8 data) { u8 bus_id = i2cGetDeviceBusId(dev_id); u8 dev_addr = i2cGetDeviceRegAddr(dev_id); for (int i = 0; i < 8; i++) { if (i2cSelectDevice(bus_id, dev_addr) && i2cSelectRegister(bus_id, reg)) { i2cWaitBusy(bus_id); *i2cGetDataReg(bus_id) = data; *i2cGetCntReg(bus_id) = 0xC1; i2cStop(bus_id, 0); if (i2cGetResult(bus_id)) return true; } *i2cGetCntReg(bus_id) = 0xC5; i2cWaitBusy(bus_id); } return false; }
bool I2C_readRegBuf(I2cDevice devId, u8 regAddr, u8 *out, u32 size) { const u8 busId = i2cDevTable[devId].busId; I2cRegs *const regs = i2cGetBusRegsBase(busId); if(!i2cStartTransfer(devId, regAddr, true, regs)) return false; while(--size) { regs->REG_I2C_CNT = I2C_ENABLE | I2C_IRQ_ENABLE | I2C_DIRE_READ | I2C_ACK; i2cWaitBusy(regs); *out++ = regs->REG_I2C_DATA; } regs->REG_I2C_CNT = I2C_ENABLE | I2C_IRQ_ENABLE | I2C_DIRE_READ | I2C_STOP; i2cWaitBusy(regs); *out = regs->REG_I2C_DATA; // Last byte return true; }
bool i2cReadRegisterBuffer(unsigned int dev_id, int reg, u8* buffer, size_t buf_size) { u8 bus_id = i2cGetDeviceBusId(dev_id); u8 dev_addr = i2cGetDeviceRegAddr(dev_id); size_t j = 0; while (!i2cSelectDevice(bus_id, dev_addr) || !i2cSelectRegister(bus_id, reg) || !i2cSelectDevice(bus_id, dev_addr | 1)) { i2cWaitBusy(bus_id); *i2cGetCntReg(bus_id) = 0xC5; i2cWaitBusy(bus_id); if (++j >= 8) return false; } if (buf_size != 1) { for (int i = 0; i < buf_size - 1; i++) { i2cWaitBusy(bus_id); *i2cGetCntReg(bus_id) = 0xF0; i2cWaitBusy(bus_id); buffer[i] = *i2cGetDataReg(bus_id); } } i2cWaitBusy(bus_id); *i2cGetCntReg(bus_id) = 0xE1; i2cWaitBusy(bus_id); *buffer = *i2cGetDataReg(bus_id); return true; }
void i2cStop(u8 bus_id, u8 arg0) { *i2cGetCntReg(bus_id) = (arg0 << 5) | 0xC0; i2cWaitBusy(bus_id); *i2cGetCntReg(bus_id) = 0xC5; }
inline bool i2cGetResult(u8 bus_id) { i2cWaitBusy(bus_id); return (*i2cGetCntReg(bus_id) >> 4) & 1; }