From 1f4ed60838d2d13d5a58d53ecd910deeb11f0198 Mon Sep 17 00:00:00 2001 From: "Ben V. Brown" Date: Sat, 31 Oct 2020 00:15:30 +1100 Subject: [PATCH] Wake Halleffect correctly helps..... --- .../TS100/Core/BSP/Pine64/I2C_Wrapper.cpp | 107 ++++++++++++++++++ workspace/TS100/Core/BSP/Pine64/Setup.c | 2 +- workspace/TS100/Core/Drivers/I2C_Wrapper.hpp | 2 +- workspace/TS100/Core/Drivers/Si7210.cpp | 4 +- 4 files changed, 111 insertions(+), 4 deletions(-) diff --git a/workspace/TS100/Core/BSP/Pine64/I2C_Wrapper.cpp b/workspace/TS100/Core/BSP/Pine64/I2C_Wrapper.cpp index 3eb6e728..90818c4d 100644 --- a/workspace/TS100/Core/BSP/Pine64/I2C_Wrapper.cpp +++ b/workspace/TS100/Core/BSP/Pine64/I2C_Wrapper.cpp @@ -412,3 +412,110 @@ bool FRToSI2C::writeRegistersBulk(const uint8_t address, const I2C_REG *register } return true; } + +bool FRToSI2C::wakePart(uint16_t DevAddress) { + //wakepart is a special case where only the device address is sent + if (!lock()) + return false; + + i2c_interrupt_disable(I2C0, I2C_INT_ERR); + i2c_interrupt_disable(I2C0, I2C_INT_EV); + i2c_interrupt_disable(I2C0, I2C_INT_BUF); + dma_parameter_struct dma_init_struct; + + uint8_t state = I2C_START; + uint16_t timeout = 0; + bool done = false; + bool timedout = false; + while (!(done || timedout)) { + switch (state) { + case I2C_START: + /* i2c master sends start signal only when the bus is idle */ + while (i2c_flag_get(I2C0, I2C_FLAG_I2CBSY) && (timeout < I2C_TIME_OUT )) { + timeout++; + } + if (timeout < I2C_TIME_OUT) { + i2c_start_on_bus(I2C0); + timeout = 0; + state = I2C_SEND_ADDRESS; + } else { + I2C_Unstick(); + timeout = 0; + state = I2C_START; + } + break; + case I2C_SEND_ADDRESS: + /* i2c master sends START signal successfully */ + while ((!i2c_flag_get(I2C0, I2C_FLAG_SBSEND)) && (timeout < I2C_TIME_OUT )) { + timeout++; + } + if (timeout < I2C_TIME_OUT) { + i2c_master_addressing(I2C0, DevAddress, I2C_TRANSMITTER); + timeout = 0; + state = I2C_CLEAR_ADDRESS_FLAG; + } else { + timedout = true; + done = true; + timeout = 0; + state = I2C_START; + } + break; + case I2C_CLEAR_ADDRESS_FLAG: + /* address flag set means i2c slave sends ACK */ + while ((!i2c_flag_get(I2C0, I2C_FLAG_ADDSEND)) && (timeout < I2C_TIME_OUT )) { + timeout++; + if (i2c_flag_get(I2C0, I2C_FLAG_AERR)) { + i2c_flag_clear(I2C0, I2C_FLAG_AERR); + i2c_stop_on_bus(I2C0); + /* i2c master sends STOP signal successfully */ + while ((I2C_CTL0(I2C0) & 0x0200) && (timeout < I2C_TIME_OUT )) { + timeout++; + } + //Address NACK'd + unlock(); + return false; + } + } + if (timeout < I2C_TIME_OUT) { + i2c_flag_clear(I2C0, I2C_FLAG_ADDSEND); + timeout = 0; + state = I2C_STOP; + } else { + //Dont retry as this means a NAK + i2c_stop_on_bus(I2C0); + /* i2c master sends STOP signal successfully */ + while ((I2C_CTL0(I2C0) & 0x0200) && (timeout < I2C_TIME_OUT )) { + timeout++; + } + unlock(); + return false; + } + break; + + case I2C_STOP: + /* send a stop condition to I2C bus */ + i2c_stop_on_bus(I2C0); + /* i2c master sends STOP signal successfully */ + while ((I2C_CTL0(I2C0) & 0x0200) && (timeout < I2C_TIME_OUT )) { + timeout++; + } + if (timeout < I2C_TIME_OUT) { + timeout = 0; + state = I2C_END; + done = true; + } else { + timedout = true; + done = true; + timeout = 0; + state = I2C_START; + } + break; + default: + state = I2C_START; + timeout = 0; + break; + } + } + unlock(); + return timedout == false; +} diff --git a/workspace/TS100/Core/BSP/Pine64/Setup.c b/workspace/TS100/Core/BSP/Pine64/Setup.c index f48862be..314f894c 100644 --- a/workspace/TS100/Core/BSP/Pine64/Setup.c +++ b/workspace/TS100/Core/BSP/Pine64/Setup.c @@ -115,7 +115,7 @@ void setup_i2c() { /* enable I2C0 clock */ rcu_periph_clock_enable(RCU_I2C0); //Setup I20 at 400kHz - i2c_clock_config(I2C0, 400 * 1000, I2C_DTCY_2); + i2c_clock_config(I2C0, 400 * 1000, I2C_DTCY_16_9); i2c_mode_addr_config(I2C0, I2C_I2CMODE_ENABLE, I2C_ADDFORMAT_7BITS, 0x00); i2c_enable(I2C0); /* enable acknowledge */ diff --git a/workspace/TS100/Core/Drivers/I2C_Wrapper.hpp b/workspace/TS100/Core/Drivers/I2C_Wrapper.hpp index ca4a50a4..9d5996df 100644 --- a/workspace/TS100/Core/Drivers/I2C_Wrapper.hpp +++ b/workspace/TS100/Core/Drivers/I2C_Wrapper.hpp @@ -34,7 +34,7 @@ public: static bool Mem_Write(uint16_t DevAddress, uint16_t MemAddress, uint8_t *pData, uint16_t Size); //Returns true if device ACK's being addressed static bool probe(uint16_t DevAddress); - + static bool wakePart(uint16_t DevAddress); static bool Transmit(uint16_t DevAddress, uint8_t *pData, uint16_t Size); static void Receive(uint16_t DevAddress, uint8_t *pData, uint16_t Size); static void TransmitReceive(uint16_t DevAddress, uint8_t *pData_tx, uint16_t Size_tx, uint8_t *pData_rx, uint16_t Size_rx); diff --git a/workspace/TS100/Core/Drivers/Si7210.cpp b/workspace/TS100/Core/Drivers/Si7210.cpp index dbe60ace..d3ef1686 100644 --- a/workspace/TS100/Core/Drivers/Si7210.cpp +++ b/workspace/TS100/Core/Drivers/Si7210.cpp @@ -10,8 +10,8 @@ #include "I2C_Wrapper.hpp" bool Si7210::detect() { uint8_t temp; - return FRToSI2C::Mem_Read(SI7210_ADDRESS, SI7210_REG_ID, &temp, 1); - //Cant use normal probe as reg 0x00 is not used + return FRToSI2C::wakePart(SI7210_ADDRESS); + } bool Si7210::init() {