Rework _all_ of the I2C
This moves all of the I2C code to IRQ based (not DMA _yet_). But it does drastically improve reliability, especially of reads.
This commit is contained in:
@@ -84,7 +84,24 @@ uint16_t getInputVoltageX10(uint16_t divisor, uint8_t sample) {
|
||||
}
|
||||
|
||||
void unstick_I2C() {
|
||||
// TODO
|
||||
/* configure SDA/SCL for GPIO */
|
||||
GPIO_BC(GPIOB) |= SDA_Pin|SCL_Pin;
|
||||
gpio_init(SDA_GPIO_Port,GPIO_MODE_OUT_PP, GPIO_OSPEED_50MHZ, SDA_Pin | SCL_Pin);
|
||||
asm ("nop");
|
||||
asm ("nop");
|
||||
asm ("nop");
|
||||
asm ("nop");
|
||||
asm ("nop");
|
||||
GPIO_BOP(GPIOB) |= SCL_Pin;
|
||||
asm ("nop");
|
||||
asm ("nop");
|
||||
asm ("nop");
|
||||
asm ("nop");
|
||||
asm ("nop");
|
||||
GPIO_BOP(GPIOB) |= SDA_Pin;
|
||||
/* connect PB6 to I2C0_SCL */
|
||||
/* connect PB7 to I2C0_SDA */
|
||||
gpio_init(SDA_GPIO_Port, GPIO_MODE_AF_OD, GPIO_OSPEED_50MHZ, SDA_Pin | SCL_Pin);
|
||||
}
|
||||
|
||||
uint8_t getButtonA() {
|
||||
|
||||
@@ -6,233 +6,15 @@
|
||||
*/
|
||||
#include "BSP.h"
|
||||
#include "Setup.h"
|
||||
#include "IRQ.h"
|
||||
#include <I2C_Wrapper.hpp>
|
||||
SemaphoreHandle_t FRToSI2C::I2CSemaphore = nullptr;
|
||||
StaticSemaphore_t FRToSI2C::xSemaphoreBuffer;
|
||||
#define FLAG_TIMEOUT 1000
|
||||
|
||||
void FRToSI2C::CpltCallback() {
|
||||
//TODO
|
||||
}
|
||||
|
||||
/** Send START command
|
||||
*
|
||||
* @param obj The I2C object
|
||||
*/
|
||||
int i2c_start() {
|
||||
int timeout;
|
||||
|
||||
/* clear I2C_FLAG_AERR Flag */
|
||||
i2c_flag_clear(I2C0, I2C_FLAG_AERR);
|
||||
|
||||
/* wait until I2C_FLAG_I2CBSY flag is reset */
|
||||
timeout = FLAG_TIMEOUT;
|
||||
while ((i2c_flag_get(I2C0, I2C_FLAG_I2CBSY)) == SET) {
|
||||
if ((timeout--) == 0) {
|
||||
|
||||
return (int) -1;
|
||||
}
|
||||
}
|
||||
|
||||
/* ensure the i2c has been stopped */
|
||||
timeout = FLAG_TIMEOUT;
|
||||
while ((I2C_CTL0(I2C0) & I2C_CTL0_STOP) == I2C_CTL0_STOP) {
|
||||
if ((timeout--) == 0) {
|
||||
return (int) -1;
|
||||
}
|
||||
}
|
||||
|
||||
/* generate a START condition */
|
||||
i2c_start_on_bus(I2C0);
|
||||
|
||||
/* ensure the i2c has been started successfully */
|
||||
timeout = FLAG_TIMEOUT;
|
||||
while ((i2c_flag_get(I2C0, I2C_FLAG_SBSEND)) == RESET) {
|
||||
if ((timeout--) == 0) {
|
||||
return (int) -1;
|
||||
}
|
||||
}
|
||||
|
||||
return (int) 0;
|
||||
}
|
||||
|
||||
/** Send STOP command
|
||||
*
|
||||
* @param obj The I2C object
|
||||
*/
|
||||
int i2c_stop() {
|
||||
|
||||
/* generate a STOP condition */
|
||||
i2c_stop_on_bus(I2C0);
|
||||
|
||||
/* wait for STOP bit reset */
|
||||
int timeout = FLAG_TIMEOUT;
|
||||
while ((I2C_CTL0(I2C0) & I2C_CTL0_STOP)) {
|
||||
if ((timeout--) == 0) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** Read one byte
|
||||
*
|
||||
* @param obj The I2C object
|
||||
* @param last Acknoledge
|
||||
* @return The read byte
|
||||
*/
|
||||
int i2c_byte_read(int last) {
|
||||
int timeout;
|
||||
|
||||
if (last) {
|
||||
/* disable acknowledge */
|
||||
i2c_ack_config(I2C0, I2C_ACK_DISABLE);
|
||||
} else {
|
||||
/* enable acknowledge */
|
||||
i2c_ack_config(I2C0, I2C_ACK_ENABLE);
|
||||
}
|
||||
|
||||
/* wait until the byte is received */
|
||||
timeout = FLAG_TIMEOUT;
|
||||
while ((i2c_flag_get(I2C0, I2C_FLAG_RBNE)) == RESET) {
|
||||
if ((timeout--) == 0) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return (int) i2c_data_receive(I2C0);
|
||||
}
|
||||
|
||||
/** Write one byte
|
||||
*
|
||||
* @param obj The I2C object
|
||||
* @param data Byte to be written
|
||||
* @return 0 if NAK was received, 1 if ACK was received, 2 for timeout.
|
||||
*/
|
||||
int i2c_byte_write(int data) {
|
||||
int timeout;
|
||||
i2c_data_transmit(I2C0, data);
|
||||
|
||||
/* wait until the byte is transmitted */
|
||||
timeout = FLAG_TIMEOUT;
|
||||
while (((i2c_flag_get(I2C0, I2C_FLAG_TBE)) == RESET) || ((i2c_flag_get(I2C0, I2C_FLAG_BTC)) == RESET)) {
|
||||
if ((timeout--) == 0) {
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
bool FRToSI2C::Mem_Read(uint16_t DevAddress, uint16_t MemAddress, uint8_t *pData, uint16_t Size) {
|
||||
if (!lock())
|
||||
return false;
|
||||
|
||||
uint32_t count = 0;
|
||||
int timeout = 0;
|
||||
|
||||
/* wait until I2C_FLAG_I2CBSY flag is reset */
|
||||
timeout = FLAG_TIMEOUT;
|
||||
while ((i2c_flag_get(I2C0, I2C_FLAG_I2CBSY)) == SET) {
|
||||
if ((timeout--) == 0) {
|
||||
i2c_stop();
|
||||
unlock();
|
||||
return false;
|
||||
} else {
|
||||
if (timeout % 5 == 0) {
|
||||
i2c_stop();
|
||||
}
|
||||
}
|
||||
}
|
||||
/* generate a START condition */
|
||||
i2c_start_on_bus(I2C0);
|
||||
|
||||
/* ensure the i2c has been started successfully */
|
||||
timeout = FLAG_TIMEOUT;
|
||||
while ((i2c_flag_get(I2C0, I2C_FLAG_SBSEND)) == RESET) {
|
||||
if ((timeout--) == 0) {
|
||||
i2c_stop();
|
||||
unlock();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/* send slave address */
|
||||
i2c_master_addressing(I2C0, DevAddress, I2C_TRANSMITTER);
|
||||
|
||||
timeout = 0;
|
||||
/* wait until I2C_FLAG_ADDSEND flag is set */
|
||||
while (!i2c_flag_get(I2C0, I2C_FLAG_ADDSEND)) {
|
||||
timeout++;
|
||||
if (timeout > 100000) {
|
||||
i2c_stop();
|
||||
unlock();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
bool no_ack = i2c_flag_get(I2C0, I2C_FLAG_AERR);
|
||||
no_ack |= i2c_flag_get(I2C0, I2C_FLAG_BERR);
|
||||
if (no_ack) {
|
||||
i2c_stop();
|
||||
unlock();
|
||||
return false;
|
||||
}
|
||||
/* clear ADDSEND */
|
||||
i2c_flag_clear(I2C0, I2C_FLAG_ADDSEND);
|
||||
int status = i2c_byte_write(MemAddress);
|
||||
no_ack |= i2c_flag_get(I2C0, I2C_FLAG_BERR);
|
||||
no_ack |= i2c_flag_get(I2C0, I2C_FLAG_LOSTARB);
|
||||
if (status == 2 || no_ack) {
|
||||
i2c_stop();
|
||||
unlock();
|
||||
return false;
|
||||
}
|
||||
//////////////////////////// //Restart into read
|
||||
|
||||
/* generate a START condition */
|
||||
i2c_start_on_bus(I2C0);
|
||||
|
||||
/* ensure the i2c has been started successfully */
|
||||
timeout = FLAG_TIMEOUT;
|
||||
while ((i2c_flag_get(I2C0, I2C_FLAG_SBSEND)) == RESET) {
|
||||
if ((timeout--) == 0) {
|
||||
i2c_stop();
|
||||
unlock();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/* send slave address */
|
||||
i2c_master_addressing(I2C0, DevAddress, I2C_RECEIVER);
|
||||
|
||||
timeout = 0;
|
||||
/* wait until I2C_FLAG_ADDSEND flag is set */
|
||||
while (!i2c_flag_get(I2C0, I2C_FLAG_ADDSEND)) {
|
||||
timeout++;
|
||||
if (timeout > 100000) {
|
||||
i2c_stop();
|
||||
unlock();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/* clear ADDSEND */
|
||||
i2c_flag_clear(I2C0, I2C_FLAG_ADDSEND);
|
||||
no_ack = i2c_flag_get(I2C0, I2C_FLAG_AERR);
|
||||
if (no_ack) {
|
||||
i2c_stop();
|
||||
unlock();
|
||||
return false;
|
||||
}
|
||||
for (count = 0; count < Size; count++) {
|
||||
pData[count] = i2c_byte_read(count == (Size - 1));
|
||||
}
|
||||
//Have nacked last data, so have to generate the stop sequence
|
||||
i2c_stop();
|
||||
unlock();
|
||||
return true;
|
||||
}
|
||||
bool FRToSI2C::I2C_RegisterWrite(uint8_t address, uint8_t reg, uint8_t data) {
|
||||
return Mem_Write(address, reg, &data, 1);
|
||||
}
|
||||
@@ -242,140 +24,114 @@ uint8_t FRToSI2C::I2C_RegisterRead(uint8_t add, uint8_t reg) {
|
||||
Mem_Read(add, reg, &temp, 1);
|
||||
return temp;
|
||||
}
|
||||
bool FRToSI2C::Mem_Write(uint16_t DevAddress, uint16_t MemAddress, uint8_t *pData, uint16_t Size) {
|
||||
|
||||
bool FRToSI2C::Mem_Read(uint16_t DevAddress, uint16_t read_address, uint8_t *p_buffer, uint16_t number_of_byte) {
|
||||
if (!lock())
|
||||
return false;
|
||||
i2c_interrupt_disable(I2C0, I2C_INT_ERR);
|
||||
i2c_interrupt_disable(I2C0, I2C_INT_BUF);
|
||||
i2c_interrupt_disable(I2C0, I2C_INT_EV);
|
||||
i2c_interrupt_flag_clear(I2C0, I2C_INT_FLAG_AERR);
|
||||
i2c_interrupt_flag_clear(I2C0, I2C_INT_FLAG_SMBALT);
|
||||
i2c_interrupt_flag_clear(I2C0, I2C_INT_FLAG_SMBTO);
|
||||
i2c_interrupt_flag_clear(I2C0, I2C_INT_FLAG_OUERR);
|
||||
i2c_interrupt_flag_clear(I2C0, I2C_INT_FLAG_LOSTARB);
|
||||
i2c_interrupt_flag_clear(I2C0, I2C_INT_FLAG_BERR);
|
||||
i2c_interrupt_flag_clear(I2C0, I2C_INT_FLAG_PECERR);
|
||||
/* wait until I2C bus is idle */
|
||||
uint8_t timeout = 0;
|
||||
while (i2c_flag_get(I2C0, I2C_FLAG_I2CBSY)) {
|
||||
timeout++;
|
||||
osDelay(1);
|
||||
if (timeout > 20) {
|
||||
unlock();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
i2c_slave_address = DevAddress;
|
||||
i2c_read = p_buffer;
|
||||
i2c_read_dress = read_address;
|
||||
i2c_nbytes = number_of_byte;
|
||||
i2c_error_code = 0;
|
||||
i2c_process_flag = 1;
|
||||
i2c_write_process = I2C_SEND_ADDRESS_FIRST;
|
||||
i2c_read_process = I2C_SEND_ADDRESS_FIRST;
|
||||
|
||||
// if (2 == number_of_byte) {
|
||||
// i2c_ackpos_config(I2C0, I2C_ACKPOS_NEXT);
|
||||
// }
|
||||
/* enable the I2C0 interrupt */
|
||||
i2c_interrupt_enable(I2C0, I2C_INT_ERR);
|
||||
i2c_interrupt_enable(I2C0, I2C_INT_EV);
|
||||
i2c_interrupt_enable(I2C0, I2C_INT_BUF);
|
||||
/* send a start condition to I2C bus */
|
||||
i2c_start_on_bus(I2C0);
|
||||
while ((i2c_nbytes > 0)) {
|
||||
osDelay(1);
|
||||
if (i2c_error_code != 0) {
|
||||
unlock();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
unlock();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool FRToSI2C::Mem_Write(uint16_t DevAddress, uint16_t MemAddress, uint8_t *p_buffer, uint16_t number_of_byte) {
|
||||
if (!lock())
|
||||
return false;
|
||||
|
||||
uint32_t count = 0;
|
||||
int timeout = 0;
|
||||
|
||||
/* wait until I2C_FLAG_I2CBSY flag is reset */
|
||||
timeout = FLAG_TIMEOUT;
|
||||
while ((i2c_flag_get(I2C0, I2C_FLAG_I2CBSY)) == SET) {
|
||||
if ((timeout--) == 0) {
|
||||
i2c_stop();
|
||||
unlock();
|
||||
return false;
|
||||
} else {
|
||||
if (timeout % 5 == 0) {
|
||||
i2c_stop();
|
||||
}
|
||||
}
|
||||
}
|
||||
/* generate a START condition */
|
||||
i2c_start_on_bus(I2C0);
|
||||
|
||||
/* ensure the i2c has been started successfully */
|
||||
timeout = FLAG_TIMEOUT;
|
||||
while ((i2c_flag_get(I2C0, I2C_FLAG_SBSEND)) == RESET) {
|
||||
if ((timeout--) == 0) {
|
||||
i2c_stop();
|
||||
unlock();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/* send slave address */
|
||||
i2c_master_addressing(I2C0, DevAddress, I2C_TRANSMITTER);
|
||||
|
||||
timeout = 0;
|
||||
/* wait until I2C_FLAG_ADDSEND flag is set */
|
||||
while (!i2c_flag_get(I2C0, I2C_FLAG_ADDSEND)) {
|
||||
i2c_slave_address = DevAddress;
|
||||
i2c_write = p_buffer;
|
||||
i2c_write_dress = MemAddress;
|
||||
i2c_nbytes = number_of_byte;
|
||||
i2c_error_code = 0;
|
||||
i2c_process_flag = 0;
|
||||
i2c_write_process = I2C_SEND_ADDRESS_FIRST;
|
||||
i2c_read_process = I2C_SEND_ADDRESS_FIRST;
|
||||
i2c_interrupt_flag_clear(I2C0, I2C_INT_FLAG_AERR);
|
||||
i2c_interrupt_flag_clear(I2C0, I2C_INT_FLAG_SMBALT);
|
||||
i2c_interrupt_flag_clear(I2C0, I2C_INT_FLAG_SMBTO);
|
||||
i2c_interrupt_flag_clear(I2C0, I2C_INT_FLAG_OUERR);
|
||||
i2c_interrupt_flag_clear(I2C0, I2C_INT_FLAG_LOSTARB);
|
||||
i2c_interrupt_flag_clear(I2C0, I2C_INT_FLAG_BERR);
|
||||
i2c_interrupt_flag_clear(I2C0, I2C_INT_FLAG_PECERR);
|
||||
/* enable the I2C0 interrupt */
|
||||
i2c_interrupt_enable(I2C0, I2C_INT_ERR);
|
||||
i2c_interrupt_enable(I2C0, I2C_INT_EV);
|
||||
i2c_interrupt_enable(I2C0, I2C_INT_BUF);
|
||||
/* wait until I2C bus is idle */
|
||||
uint8_t timeout = 0;
|
||||
while (i2c_flag_get(I2C0, I2C_FLAG_I2CBSY)) {
|
||||
timeout++;
|
||||
if (timeout > 100000) {
|
||||
i2c_stop();
|
||||
osDelay(1);
|
||||
if (timeout > 20) {
|
||||
unlock();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/* clear ADDSEND */
|
||||
i2c_flag_clear(I2C0, I2C_FLAG_ADDSEND);
|
||||
int status = i2c_byte_write(MemAddress);
|
||||
for (count = 0; count < Size; count++) {
|
||||
status = i2c_byte_write(pData[count]);
|
||||
if (status != 1) {
|
||||
i2c_stop();
|
||||
/* send a start condition to I2C bus */
|
||||
//This sending will kickoff the IRQ's
|
||||
i2c_start_on_bus(I2C0);
|
||||
while ((i2c_nbytes > 0)) {
|
||||
osDelay(1);
|
||||
if (i2c_error_code != 0) {
|
||||
unlock();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/* if not sequential write, then send stop */
|
||||
|
||||
i2c_stop();
|
||||
unlock();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool FRToSI2C::Transmit(uint16_t DevAddress, uint8_t *pData, uint16_t Size) {
|
||||
if (!lock())
|
||||
return false;
|
||||
uint32_t count = 0;
|
||||
int timeout = 0;
|
||||
|
||||
/* wait until I2C_FLAG_I2CBSY flag is reset */
|
||||
timeout = FLAG_TIMEOUT;
|
||||
while ((i2c_flag_get(I2C0, I2C_FLAG_I2CBSY)) == SET) {
|
||||
if ((timeout--) == 0) {
|
||||
i2c_stop();
|
||||
unlock();
|
||||
return false;
|
||||
} else {
|
||||
if (timeout % 5 == 0) {
|
||||
i2c_stop();
|
||||
}
|
||||
}
|
||||
}
|
||||
/* generate a START condition */
|
||||
i2c_start_on_bus(I2C0);
|
||||
|
||||
/* ensure the i2c has been started successfully */
|
||||
timeout = FLAG_TIMEOUT;
|
||||
while ((i2c_flag_get(I2C0, I2C_FLAG_SBSEND)) == RESET) {
|
||||
if ((timeout--) == 0) {
|
||||
i2c_stop();
|
||||
unlock();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/* send slave address */
|
||||
i2c_master_addressing(I2C0, DevAddress, I2C_TRANSMITTER);
|
||||
|
||||
timeout = 0;
|
||||
/* wait until I2C_FLAG_ADDSEND flag is set */
|
||||
while (!i2c_flag_get(I2C0, I2C_FLAG_ADDSEND)) {
|
||||
timeout++;
|
||||
if (timeout > 100000) {
|
||||
i2c_stop();
|
||||
unlock();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/* clear ADDSEND */
|
||||
i2c_flag_clear(I2C0, I2C_FLAG_ADDSEND);
|
||||
|
||||
for (count = 0; count < Size; count++) {
|
||||
int status = i2c_byte_write(pData[count]);
|
||||
if (status != 1) {
|
||||
i2c_stop();
|
||||
unlock();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/* if not sequential write, then send stop */
|
||||
|
||||
i2c_stop();
|
||||
unlock();
|
||||
return true;
|
||||
return Mem_Write(DevAddress, pData[0], pData + 1, Size - 1);
|
||||
}
|
||||
|
||||
bool FRToSI2C::probe(uint16_t DevAddress) {
|
||||
uint8_t temp = 0;
|
||||
return Mem_Read(DevAddress, 0x00, &temp, 1);
|
||||
uint8_t temp[1];
|
||||
return Mem_Read(DevAddress, 0x00, temp, sizeof(temp));
|
||||
}
|
||||
|
||||
void FRToSI2C::I2C_Unstick() {
|
||||
@@ -384,15 +140,12 @@ void FRToSI2C::I2C_Unstick() {
|
||||
|
||||
bool FRToSI2C::lock() {
|
||||
if (I2CSemaphore == nullptr) {
|
||||
for (;;) { //
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return xSemaphoreTake(I2CSemaphore,1000) == pdTRUE;
|
||||
}
|
||||
|
||||
void FRToSI2C::unlock() {
|
||||
if (I2CSemaphore == nullptr)
|
||||
return;
|
||||
xSemaphoreGive(I2CSemaphore);
|
||||
}
|
||||
|
||||
|
||||
@@ -8,6 +8,16 @@
|
||||
#include "IRQ.h"
|
||||
#include "Pins.h"
|
||||
#include "int_n.h"
|
||||
volatile uint8_t i2c_read_process = 0;
|
||||
volatile uint8_t i2c_write_process = 0;
|
||||
volatile uint8_t i2c_slave_address = 0;
|
||||
volatile uint8_t i2c_error_code = 0;
|
||||
volatile uint8_t* i2c_write;
|
||||
volatile uint8_t* i2c_read;
|
||||
volatile uint16_t i2c_nbytes;
|
||||
volatile uint16_t i2c_write_dress;
|
||||
volatile uint16_t i2c_read_dress;
|
||||
volatile uint8_t i2c_process_flag = 0;
|
||||
void ADC0_1_IRQHandler(void) {
|
||||
|
||||
adc_interrupt_flag_clear(ADC0, ADC_INT_FLAG_EOIC);
|
||||
@@ -39,8 +49,7 @@ void TIMER1_IRQHandler(void) {
|
||||
|
||||
timer_channel_output_pulse_value_config(TIMER2, TIMER_CH_0, 0);
|
||||
if (pendingPWM) {
|
||||
timer_channel_output_pulse_value_config(TIMER1, TIMER_CH_1,
|
||||
pendingPWM);
|
||||
timer_channel_output_pulse_value_config(TIMER1, TIMER_CH_1, pendingPWM);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -53,16 +62,221 @@ void setTipPWM(uint8_t pulse) {
|
||||
pendingPWM = pulse;
|
||||
}
|
||||
|
||||
|
||||
void EXTI5_9_IRQHandler(void)
|
||||
{
|
||||
void EXTI5_9_IRQHandler(void) {
|
||||
#ifdef POW_PD
|
||||
if (RESET != exti_interrupt_flag_get(EXTI_5)){
|
||||
exti_interrupt_flag_clear(EXTI_5);
|
||||
if (RESET != exti_interrupt_flag_get(EXTI_5)) {
|
||||
exti_interrupt_flag_clear(EXTI_5);
|
||||
|
||||
if(RESET == gpio_input_bit_get(FUSB302_IRQ_GPIO_Port, FUSB302_IRQ_Pin)){
|
||||
InterruptHandler::irqCallback();
|
||||
}
|
||||
}
|
||||
if (RESET == gpio_input_bit_get(FUSB302_IRQ_GPIO_Port, FUSB302_IRQ_Pin)) {
|
||||
InterruptHandler::irqCallback();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief handle I2C0 event interrupt request
|
||||
\param[in] none
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void I2C0_EV_IRQHandler(void) {
|
||||
if (RESET == i2c_process_flag) {
|
||||
switch (i2c_write_process) {
|
||||
case I2C_SEND_ADDRESS_FIRST:
|
||||
if (i2c_interrupt_flag_get(I2C0, I2C_INT_FLAG_SBSEND)) {
|
||||
/* send slave address */
|
||||
i2c_master_addressing(I2C0, i2c_slave_address, I2C_TRANSMITTER);
|
||||
i2c_write_process = I2C_CLEAR_ADDRESS_FLAG_FIRST;
|
||||
}
|
||||
break;
|
||||
case I2C_CLEAR_ADDRESS_FLAG_FIRST:
|
||||
if (i2c_interrupt_flag_get(I2C0, I2C_INT_FLAG_ADDSEND)) {
|
||||
/*clear ADDSEND bit */
|
||||
i2c_interrupt_flag_clear(I2C0, I2C_INT_FLAG_ADDSEND);
|
||||
i2c_write_process = I2C_TRANSMIT_WRITE_READ_ADD;
|
||||
}
|
||||
break;
|
||||
case I2C_TRANSMIT_WRITE_READ_ADD:
|
||||
if (i2c_interrupt_flag_get(I2C0, I2C_INT_FLAG_TBE)) {
|
||||
i2c_data_transmit(I2C0, i2c_write_dress);
|
||||
/* wait until BTC bit is set */
|
||||
while (!i2c_flag_get(I2C0, I2C_FLAG_BTC))
|
||||
;
|
||||
i2c_write_process = I2C_TRANSMIT_DATA;
|
||||
}
|
||||
break;
|
||||
case I2C_TRANSMIT_DATA:
|
||||
if (i2c_interrupt_flag_get(I2C0, I2C_INT_FLAG_TBE)) {
|
||||
/* the master sends a data byte */
|
||||
i2c_data_transmit(I2C0, *i2c_write++);
|
||||
i2c_nbytes--;
|
||||
if (RESET == i2c_nbytes) {
|
||||
i2c_write_process = I2C_STOP;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case I2C_STOP:
|
||||
/* the master sends a stop condition to I2C bus */
|
||||
i2c_stop_on_bus(I2C0);
|
||||
/* disable the I2C0 interrupt */
|
||||
i2c_interrupt_disable(I2C0, I2C_INT_ERR);
|
||||
i2c_interrupt_disable(I2C0, I2C_INT_BUF);
|
||||
i2c_interrupt_disable(I2C0, I2C_INT_EV);
|
||||
i2c_write_process = I2C_SEND_ADDRESS_FIRST;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
} else if (SET == i2c_process_flag) {
|
||||
switch (i2c_read_process) {
|
||||
case I2C_SEND_ADDRESS_FIRST:
|
||||
if (i2c_interrupt_flag_get(I2C0, I2C_INT_FLAG_SBSEND)) {
|
||||
/* send slave address */
|
||||
i2c_master_addressing(I2C0, i2c_slave_address, I2C_TRANSMITTER);
|
||||
i2c_read_process = I2C_CLEAR_ADDRESS_FLAG_FIRST;
|
||||
}
|
||||
break;
|
||||
case I2C_CLEAR_ADDRESS_FLAG_FIRST:
|
||||
if (i2c_interrupt_flag_get(I2C0, I2C_INT_FLAG_ADDSEND)) {
|
||||
/*clear ADDSEND bit */
|
||||
i2c_interrupt_flag_clear(I2C0, I2C_INT_FLAG_ADDSEND);
|
||||
i2c_read_process = I2C_TRANSMIT_WRITE_READ_ADD;
|
||||
}
|
||||
break;
|
||||
case I2C_TRANSMIT_WRITE_READ_ADD:
|
||||
if (i2c_interrupt_flag_get(I2C0, I2C_INT_FLAG_TBE)) {
|
||||
i2c_data_transmit(I2C0, i2c_read_dress);
|
||||
/* wait until BTC bit is set */
|
||||
while (!i2c_flag_get(I2C0, I2C_FLAG_BTC))
|
||||
;
|
||||
/* send a start condition to I2C bus */
|
||||
i2c_start_on_bus(I2C0);
|
||||
i2c_read_process = I2C_SEND_ADDRESS_SECOND;
|
||||
}
|
||||
break;
|
||||
case I2C_SEND_ADDRESS_SECOND:
|
||||
if (i2c_interrupt_flag_get(I2C0, I2C_INT_FLAG_SBSEND)) {
|
||||
i2c_master_addressing(I2C0, i2c_slave_address, I2C_RECEIVER);
|
||||
if ((1 == i2c_nbytes) || (2 == i2c_nbytes)) {
|
||||
i2c_ackpos_config(I2C0, i2c_nbytes == 1 ? I2C_ACKPOS_CURRENT : I2C_ACKPOS_NEXT);
|
||||
/* clear the ACKEN before the ADDSEND is cleared */
|
||||
i2c_ack_config(I2C0, I2C_ACK_DISABLE);
|
||||
} else {
|
||||
i2c_ack_config(I2C0, I2C_ACK_ENABLE);
|
||||
|
||||
}
|
||||
i2c_read_process = I2C_CLEAR_ADDRESS_FLAG_SECOND;
|
||||
}
|
||||
break;
|
||||
case I2C_CLEAR_ADDRESS_FLAG_SECOND:
|
||||
if (i2c_interrupt_flag_get(I2C0, I2C_INT_FLAG_ADDSEND)) {
|
||||
|
||||
/*clear ADDSEND bit */
|
||||
i2c_interrupt_flag_clear(I2C0, I2C_INT_FLAG_ADDSEND);
|
||||
i2c_read_process = I2C_TRANSMIT_DATA;
|
||||
|
||||
}
|
||||
break;
|
||||
case I2C_TRANSMIT_DATA:
|
||||
if (i2c_nbytes > 0) {
|
||||
/* read a byte from the EEPROM */
|
||||
if (i2c_nbytes == 2) {
|
||||
/* wait until BTC bit is set */
|
||||
i2c_ackpos_config(I2C0, I2C_ACKPOS_CURRENT);
|
||||
/* clear the ACKEN before the ADDSEND is cleared */
|
||||
i2c_ack_config(I2C0, I2C_ACK_DISABLE);
|
||||
}
|
||||
*i2c_read = i2c_data_receive(I2C0);
|
||||
i2c_read++;
|
||||
i2c_nbytes--;
|
||||
if (i2c_nbytes == 0) {
|
||||
/* the master sends a stop condition to I2C bus */
|
||||
i2c_stop_on_bus(I2C0);
|
||||
/* disable the I2C0 interrupt */
|
||||
i2c_interrupt_disable(I2C0, I2C_INT_ERR);
|
||||
i2c_interrupt_disable(I2C0, I2C_INT_BUF);
|
||||
i2c_interrupt_disable(I2C0, I2C_INT_EV);
|
||||
i2c_process_flag = RESET;
|
||||
i2c_read_process = I2C_DONE;
|
||||
}
|
||||
} else {
|
||||
i2c_read_process = I2C_STOP;
|
||||
/* the master sends a stop condition to I2C bus */
|
||||
i2c_stop_on_bus(I2C0);
|
||||
/* disable the I2C0 interrupt */
|
||||
i2c_interrupt_disable(I2C0, I2C_INT_ERR);
|
||||
i2c_interrupt_disable(I2C0, I2C_INT_BUF);
|
||||
i2c_interrupt_disable(I2C0, I2C_INT_EV);
|
||||
i2c_process_flag = RESET;
|
||||
i2c_read_process = I2C_DONE;
|
||||
}
|
||||
break;
|
||||
case I2C_STOP:
|
||||
/* the master sends a stop condition to I2C bus */
|
||||
i2c_stop_on_bus(I2C0);
|
||||
/* disable the I2C0 interrupt */
|
||||
i2c_interrupt_disable(I2C0, I2C_INT_ERR);
|
||||
i2c_interrupt_disable(I2C0, I2C_INT_BUF);
|
||||
i2c_interrupt_disable(I2C0, I2C_INT_EV);
|
||||
i2c_process_flag = RESET;
|
||||
i2c_read_process = I2C_DONE;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief handle I2C0 error interrupt request
|
||||
\param[in] none
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void I2C0_ER_IRQHandler(void) {
|
||||
/* no acknowledge received */
|
||||
if (i2c_interrupt_flag_get(I2C0, I2C_INT_FLAG_AERR)) {
|
||||
i2c_interrupt_flag_clear(I2C0, I2C_INT_FLAG_AERR);
|
||||
i2c_error_code = 1; //NAK
|
||||
}
|
||||
|
||||
/* SMBus alert */
|
||||
if (i2c_interrupt_flag_get(I2C0, I2C_INT_FLAG_SMBALT)) {
|
||||
i2c_interrupt_flag_clear(I2C0, I2C_INT_FLAG_SMBALT);
|
||||
i2c_error_code = 2; //SMB Alert
|
||||
}
|
||||
|
||||
/* bus timeout in SMBus mode */
|
||||
if (i2c_interrupt_flag_get(I2C0, I2C_INT_FLAG_SMBTO)) {
|
||||
i2c_interrupt_flag_clear(I2C0, I2C_INT_FLAG_SMBTO);
|
||||
i2c_error_code = 3; //SMB Timeout
|
||||
}
|
||||
|
||||
/* over-run or under-run when SCL stretch is disabled */
|
||||
if (i2c_interrupt_flag_get(I2C0, I2C_INT_FLAG_OUERR)) {
|
||||
i2c_interrupt_flag_clear(I2C0, I2C_INT_FLAG_OUERR);
|
||||
i2c_error_code = 4; //OverRun
|
||||
}
|
||||
|
||||
/* arbitration lost */
|
||||
if (i2c_interrupt_flag_get(I2C0, I2C_INT_FLAG_LOSTARB)) {
|
||||
i2c_interrupt_flag_clear(I2C0, I2C_INT_FLAG_LOSTARB);
|
||||
i2c_error_code = 5; //Lost ARB -- multi master -- shouldnt happen
|
||||
}
|
||||
|
||||
/* bus error */
|
||||
if (i2c_interrupt_flag_get(I2C0, I2C_INT_FLAG_BERR)) {
|
||||
i2c_interrupt_flag_clear(I2C0, I2C_INT_FLAG_BERR);
|
||||
i2c_error_code = 6; //Bus Error
|
||||
}
|
||||
|
||||
/* CRC value doesn't match */
|
||||
if (i2c_interrupt_flag_get(I2C0, I2C_INT_FLAG_PECERR)) {
|
||||
i2c_interrupt_flag_clear(I2C0, I2C_INT_FLAG_PECERR);
|
||||
i2c_error_code = 7; //CRC Fail -- Shouldnt Happen
|
||||
}
|
||||
|
||||
i2c_stop_on_bus(I2C0);
|
||||
|
||||
}
|
||||
|
||||
@@ -20,6 +20,31 @@ extern "C" {
|
||||
void ADC0_1_IRQHandler(void);
|
||||
void TIMER1_IRQHandler(void);
|
||||
void EXTI5_9_IRQHandler(void);
|
||||
/* handle I2C0 event interrupt request */
|
||||
void I2C0_EV_IRQHandler(void);
|
||||
/* handle I2C0 error interrupt request */
|
||||
void I2C0_ER_IRQHandler(void);
|
||||
typedef enum {
|
||||
I2C_SEND_ADDRESS_FIRST = 0, //Sending slave address
|
||||
I2C_CLEAR_ADDRESS_FLAG_FIRST, // Clear address send
|
||||
I2C_TRANSMIT_WRITE_READ_ADD, //Transmit the memory address to read/write from
|
||||
I2C_SEND_ADDRESS_SECOND, //Send address again for read
|
||||
I2C_CLEAR_ADDRESS_FLAG_SECOND, //Clear address again
|
||||
I2C_TRANSMIT_DATA, //Transmit recieve data
|
||||
I2C_STOP, //Send stop
|
||||
I2C_ABORTED, //
|
||||
I2C_DONE,// I2C transfer is complete
|
||||
} i2c_process_enum;
|
||||
extern volatile uint8_t i2c_slave_address;
|
||||
extern volatile uint8_t i2c_read_process;
|
||||
extern volatile uint8_t i2c_write_process;
|
||||
extern volatile uint8_t i2c_error_code;
|
||||
extern volatile uint8_t* i2c_write;
|
||||
extern volatile uint8_t* i2c_read;
|
||||
extern volatile uint16_t i2c_nbytes;
|
||||
extern volatile uint16_t i2c_write_dress;
|
||||
extern volatile uint16_t i2c_read_dress;
|
||||
extern volatile uint8_t i2c_process_flag;
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -20,6 +20,8 @@
|
||||
#define POW_QC
|
||||
#define TEMP_TMP36
|
||||
#define ACCEL_BMA
|
||||
|
||||
|
||||
#define BATTFILTERDEPTH 32
|
||||
#endif
|
||||
|
||||
|
||||
@@ -65,8 +65,7 @@ void setup_gpio() {
|
||||
gpio_init(OLED_RESET_GPIO_Port, GPIO_MODE_OUT_PP, GPIO_OSPEED_2MHZ,
|
||||
OLED_RESET_Pin);
|
||||
//I2C as AF Open Drain
|
||||
gpio_init(SDA_GPIO_Port, GPIO_MODE_AF_OD, GPIO_OSPEED_50MHZ, SDA_Pin);
|
||||
gpio_init(SCL_GPIO_Port, GPIO_MODE_AF_OD, GPIO_OSPEED_50MHZ, SCL_Pin);
|
||||
gpio_init(SDA_GPIO_Port, GPIO_MODE_AF_OD, GPIO_OSPEED_50MHZ, SDA_Pin | SCL_Pin);
|
||||
//PWM output as AF Push Pull
|
||||
gpio_init(PWM_Out_GPIO_Port, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ,
|
||||
PWM_Out_Pin);
|
||||
@@ -126,11 +125,13 @@ void setup_i2c() {
|
||||
/* enable I2C0 clock */
|
||||
rcu_periph_clock_enable(RCU_I2C0);
|
||||
//Setup I20 at 400kHz
|
||||
i2c_clock_config(I2C0, 100 * 1000, I2C_DTCY_16_9);
|
||||
i2c_clock_config(I2C0, 400 * 1000, I2C_DTCY_2);
|
||||
i2c_mode_addr_config(I2C0, I2C_I2CMODE_ENABLE, I2C_ADDFORMAT_7BITS, 0x00);
|
||||
i2c_enable(I2C0);
|
||||
/* enable acknowledge */
|
||||
i2c_ack_config(I2C0, I2C_ACK_ENABLE);
|
||||
eclic_irq_enable(I2C0_EV_IRQn,1,0);
|
||||
eclic_irq_enable(I2C0_ER_IRQn,2,0);
|
||||
}
|
||||
void setup_adc() {
|
||||
|
||||
|
||||
117
workspace/TS100/Core/BSP/Pine64/Vendor/Lib/I2C0_IE.c
vendored
117
workspace/TS100/Core/BSP/Pine64/Vendor/Lib/I2C0_IE.c
vendored
@@ -1,117 +0,0 @@
|
||||
/*!
|
||||
\file I2C0_IE.c
|
||||
\brief I2C0 master transmitter interrupt program
|
||||
|
||||
\version 2019-06-05, V1.0.0, firmware for GD32VF103
|
||||
|
||||
*/
|
||||
|
||||
/*
|
||||
Copyright (c) 2019, GigaDevice Semiconductor Inc.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
3. Neither the name of the copyright holder nor the names of its contributors
|
||||
may be used to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||
OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "gd32vf103_i2c.h"
|
||||
|
||||
#include "I2C_IE.h"
|
||||
|
||||
uint32_t event1;
|
||||
|
||||
/*!
|
||||
\brief handle I2C0 event interrupt request
|
||||
\param[in] none
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void I2C0_EventIRQ_Handler(void) {
|
||||
if (i2c_interrupt_flag_get(I2C0, I2C_INT_FLAG_SBSEND)) {
|
||||
/* send slave address */
|
||||
i2c_master_addressing(I2C0, I2C1_SLAVE_ADDRESS7, I2C_TRANSMITTER);
|
||||
} else if (i2c_interrupt_flag_get(I2C0, I2C_INT_FLAG_ADDSEND)) {
|
||||
/*clear ADDSEND bit */
|
||||
i2c_interrupt_flag_clear(I2C0, I2C_INT_FLAG_ADDSEND);
|
||||
} else if (i2c_interrupt_flag_get(I2C0, I2C_INT_FLAG_TBE)) {
|
||||
if (I2C_nBytes > 0) {
|
||||
/* the master sends a data byte */
|
||||
i2c_data_transmit(I2C0, *i2c_txbuffer++);
|
||||
I2C_nBytes--;
|
||||
} else {
|
||||
/* the master sends a stop condition to I2C bus */
|
||||
i2c_stop_on_bus(I2C0);
|
||||
/* disable the I2C0 interrupt */
|
||||
i2c_interrupt_disable(I2C0, I2C_INT_ERR);
|
||||
i2c_interrupt_disable(I2C0, I2C_INT_BUF);
|
||||
i2c_interrupt_disable(I2C0, I2C_INT_EV);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief handle I2C0 error interrupt request
|
||||
\param[in] none
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void I2C0_ErrorIRQ_Handler(void) {
|
||||
/* no acknowledge received */
|
||||
if (i2c_interrupt_flag_get(I2C0, I2C_INT_FLAG_AERR)) {
|
||||
i2c_interrupt_flag_clear(I2C0, I2C_INT_FLAG_AERR);
|
||||
}
|
||||
|
||||
/* SMBus alert */
|
||||
if (i2c_interrupt_flag_get(I2C0, I2C_INT_FLAG_SMBALT)) {
|
||||
i2c_interrupt_flag_clear(I2C0, I2C_INT_FLAG_SMBALT);
|
||||
}
|
||||
|
||||
/* bus timeout in SMBus mode */
|
||||
if (i2c_interrupt_flag_get(I2C0, I2C_INT_FLAG_SMBTO)) {
|
||||
i2c_interrupt_flag_clear(I2C0, I2C_INT_FLAG_SMBTO);
|
||||
}
|
||||
|
||||
/* over-run or under-run when SCL stretch is disabled */
|
||||
if (i2c_interrupt_flag_get(I2C0, I2C_INT_FLAG_OUERR)) {
|
||||
i2c_interrupt_flag_clear(I2C0, I2C_INT_FLAG_OUERR);
|
||||
}
|
||||
|
||||
/* arbitration lost */
|
||||
if (i2c_interrupt_flag_get(I2C0, I2C_INT_FLAG_LOSTARB)) {
|
||||
i2c_interrupt_flag_clear(I2C0, I2C_INT_FLAG_LOSTARB);
|
||||
}
|
||||
|
||||
/* bus error */
|
||||
if (i2c_interrupt_flag_get(I2C0, I2C_INT_FLAG_BERR)) {
|
||||
i2c_interrupt_flag_clear(I2C0, I2C_INT_FLAG_BERR);
|
||||
}
|
||||
|
||||
/* CRC value doesn't match */
|
||||
if (i2c_interrupt_flag_get(I2C0, I2C_INT_FLAG_PECERR)) {
|
||||
i2c_interrupt_flag_clear(I2C0, I2C_INT_FLAG_PECERR);
|
||||
}
|
||||
|
||||
/* disable the error interrupt */
|
||||
i2c_interrupt_disable(I2C0, I2C_INT_ERR);
|
||||
i2c_interrupt_disable(I2C0, I2C_INT_BUF);
|
||||
i2c_interrupt_disable(I2C0, I2C_INT_EV);
|
||||
}
|
||||
112
workspace/TS100/Core/BSP/Pine64/Vendor/Lib/I2C1_IE.c
vendored
112
workspace/TS100/Core/BSP/Pine64/Vendor/Lib/I2C1_IE.c
vendored
@@ -1,112 +0,0 @@
|
||||
/*!
|
||||
\file I2C1_IE.c
|
||||
\brief I2C1 slave receiver interrupt program
|
||||
|
||||
\version 2019-06-05, V1.0.0, firmware for GD32VF103
|
||||
|
||||
*/
|
||||
|
||||
/*
|
||||
Copyright (c) 2019, GigaDevice Semiconductor Inc.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
3. Neither the name of the copyright holder nor the names of its contributors
|
||||
may be used to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||
OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "gd32vf103_i2c.h"
|
||||
|
||||
#include "I2C_IE.h"
|
||||
|
||||
uint32_t event2;
|
||||
|
||||
/*!
|
||||
\brief handle I2C1 event interrupt request
|
||||
\param[in] none
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void I2C1_EventIRQ_Handler(void) {
|
||||
if (i2c_interrupt_flag_get(I2C1, I2C_INT_FLAG_ADDSEND)) {
|
||||
/* clear the ADDSEND bit */
|
||||
i2c_interrupt_flag_clear(I2C1, I2C_INT_FLAG_ADDSEND);
|
||||
} else if (i2c_interrupt_flag_get(I2C1, I2C_INT_FLAG_RBNE)) {
|
||||
/* if reception data register is not empty ,I2C1 will read a data from I2C_DATA */
|
||||
*i2c_rxbuffer++ = i2c_data_receive(I2C1);
|
||||
} else if (i2c_interrupt_flag_get(I2C1, I2C_INT_FLAG_STPDET)) {
|
||||
status = SUCCESS;
|
||||
/* clear the STPDET bit */
|
||||
i2c_enable(I2C1);
|
||||
/* disable I2C1 interrupt */
|
||||
i2c_interrupt_disable(I2C1, I2C_INT_ERR);
|
||||
i2c_interrupt_disable(I2C1, I2C_INT_BUF);
|
||||
i2c_interrupt_disable(I2C1, I2C_INT_EV);
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief handle I2C1 error interrupt request
|
||||
\param[in] none
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void I2C1_ErrorIRQ_Handler(void) {
|
||||
/* no acknowledge received */
|
||||
if (i2c_interrupt_flag_get(I2C1, I2C_INT_FLAG_AERR)) {
|
||||
i2c_interrupt_flag_clear(I2C1, I2C_INT_FLAG_AERR);
|
||||
}
|
||||
|
||||
/* SMBus alert */
|
||||
if (i2c_interrupt_flag_get(I2C1, I2C_INT_FLAG_SMBALT)) {
|
||||
i2c_interrupt_flag_clear(I2C1, I2C_INT_FLAG_SMBALT);
|
||||
}
|
||||
|
||||
/* bus timeout in SMBus mode */
|
||||
if (i2c_interrupt_flag_get(I2C1, I2C_INT_FLAG_SMBTO)) {
|
||||
i2c_interrupt_flag_clear(I2C1, I2C_INT_FLAG_SMBTO);
|
||||
}
|
||||
|
||||
/* over-run or under-run when SCL stretch is disabled */
|
||||
if (i2c_interrupt_flag_get(I2C1, I2C_INT_FLAG_OUERR)) {
|
||||
i2c_interrupt_flag_clear(I2C1, I2C_INT_FLAG_OUERR);
|
||||
}
|
||||
|
||||
/* arbitration lost */
|
||||
if (i2c_interrupt_flag_get(I2C1, I2C_INT_FLAG_LOSTARB)) {
|
||||
i2c_interrupt_flag_clear(I2C1, I2C_INT_FLAG_LOSTARB);
|
||||
}
|
||||
|
||||
/* bus error */
|
||||
if (i2c_interrupt_flag_get(I2C1, I2C_INT_FLAG_BERR)) {
|
||||
i2c_interrupt_flag_clear(I2C1, I2C_INT_FLAG_BERR);
|
||||
}
|
||||
|
||||
/* CRC value doesn't match */
|
||||
if (i2c_interrupt_flag_get(I2C1, I2C_INT_FLAG_PECERR)) {
|
||||
i2c_interrupt_flag_clear(I2C1, I2C_INT_FLAG_PECERR);
|
||||
}
|
||||
|
||||
/* disable the error interrupt */
|
||||
i2c_interrupt_disable(I2C1, I2C_INT_ERR);
|
||||
i2c_interrupt_disable(I2C1, I2C_INT_BUF);
|
||||
i2c_interrupt_disable(I2C1, I2C_INT_EV);
|
||||
}
|
||||
@@ -1,65 +0,0 @@
|
||||
/*!
|
||||
\file I2C1_IE.c
|
||||
\brief The header file of I2C0 and I2C1 interrupt
|
||||
|
||||
\version 2019-06-05, V1.0.0, firmware for GD32VF103
|
||||
|
||||
*/
|
||||
|
||||
/*
|
||||
Copyright (c) 2019, GigaDevice Semiconductor Inc.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
3. Neither the name of the copyright holder nor the names of its contributors
|
||||
may be used to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||
OF SUCH DAMAGE.
|
||||
*/
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
#ifndef I2C_IE_H
|
||||
#define I2C_IE_H
|
||||
|
||||
#include "gd32vf103.h"
|
||||
|
||||
#define I2C0_SLAVE_ADDRESS7 0x82
|
||||
#define I2C1_SLAVE_ADDRESS7 0x72
|
||||
|
||||
extern volatile ErrStatus status;
|
||||
extern volatile uint8_t *i2c_txbuffer;
|
||||
extern volatile uint8_t *i2c_rxbuffer;
|
||||
extern volatile uint16_t I2C_nBytes;
|
||||
|
||||
/* function declarations */
|
||||
/* handle I2C0 event interrupt request */
|
||||
void I2C0_EventIRQ_Handler(void);
|
||||
/* handle I2C0 error interrupt request */
|
||||
void I2C0_ErrorIRQ_Handler(void);
|
||||
/* handle I2C1 event interrupt request */
|
||||
void I2C1_EventIRQ_Handler(void);
|
||||
/* handle I2C1 error interrupt request */
|
||||
void I2C1_ErrorIRQ_Handler(void);
|
||||
|
||||
#endif /* I2C_IE_H */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load Diff
@@ -134,12 +134,19 @@ void fusb_send_hardrst() {
|
||||
}
|
||||
|
||||
void fusb_setup() {
|
||||
|
||||
if (!FRToSI2C::probe(FUSB302B_ADDR)) {
|
||||
return;
|
||||
}
|
||||
/* Fully reset the FUSB302B */
|
||||
fusb_write_byte( FUSB_RESET, FUSB_RESET_SW_RES);
|
||||
osDelay(2);
|
||||
uint8_t tries = 0;
|
||||
while (!fusb_read_id()) {
|
||||
osDelay(10);
|
||||
tries++;
|
||||
if (tries > 5) {
|
||||
return; //Welp :(
|
||||
}
|
||||
}
|
||||
|
||||
/* Turn on all power */
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
#include <BMA223.hpp>
|
||||
#include "BMA223_defines.h"
|
||||
#include <array>
|
||||
#define BMA223_ADDRESS 0b00110000
|
||||
#define BMA223_ADDRESS 0x18<<1
|
||||
|
||||
bool BMA223::detect() {
|
||||
return FRToSI2C::probe(BMA223_ADDRESS);
|
||||
@@ -16,16 +16,17 @@ bool BMA223::detect() {
|
||||
|
||||
static const FRToSI2C::I2C_REG i2c_registers[] = { //
|
||||
//
|
||||
{ BMA223_PMU_RANGE, 0b0011, 0 }, //2G range
|
||||
{ BMA223_PMU_BW, 0b1101, 0 }, //250Hz filter
|
||||
{ BMA223_PMU_LPW, 0x00, 0 }, //Full power
|
||||
{ BMA223_ACCD_HBW, 0b01000000, 0 }, //filtered data out
|
||||
{ BMA223_INT_OUT_CTRL, 0b1111, 0 }, //interrupt active high and OD to get it hi-z
|
||||
{ BMA223_OFC_CTRL, 0b00000111, 0 }, //High pass en
|
||||
{ BMA223_PMU_RANGE, 0b00000011, 0 }, //2G range
|
||||
{ BMA223_PMU_BW, 0b00001101, 0 }, //250Hz filter
|
||||
{ BMA223_PMU_LPW, 0b00000000, 0 }, //Full power
|
||||
{ BMA223_ACCD_HBW, 0b00000000, 0 }, //filtered data out
|
||||
{ BMA223_INT_OUT_CTRL, 0b00001010, 0 }, //interrupt active low and OD to get it hi-z
|
||||
{ BMA223_INT_RST_LATCH, 0b10000000, 0 }, //interrupt active low and OD to get it hi-z
|
||||
// { BMA223_OFC_CTRL, 0b00000111, 0 }, //High pass en
|
||||
|
||||
//
|
||||
};
|
||||
void BMA223::initalize() {
|
||||
bool BMA223::initalize() {
|
||||
//Setup acceleration readings
|
||||
//2G range
|
||||
//bandwidth = 250Hz
|
||||
@@ -35,19 +36,22 @@ void BMA223::initalize() {
|
||||
// Hysteresis is set to ~ 16 counts
|
||||
//Theta blocking is set to 0b10
|
||||
|
||||
FRToSI2C::writeRegistersBulk(BMA223_ADDRESS, i2c_registers, sizeof(i2c_registers) / sizeof(i2c_registers[0]));
|
||||
return FRToSI2C::writeRegistersBulk(BMA223_ADDRESS, i2c_registers, sizeof(i2c_registers) / sizeof(i2c_registers[0]));
|
||||
|
||||
}
|
||||
|
||||
void BMA223::getAxisReadings(int16_t& x, int16_t& y, int16_t& z) {
|
||||
//The BMA is odd in that its output data width is only 8 bits
|
||||
//And yet there are MSB and LSB registers _sigh_.
|
||||
uint8_t sensorData[6];
|
||||
uint8_t sensorData[6] = { 0, 0, 0, 0, 0, 0 };
|
||||
|
||||
FRToSI2C::Mem_Read(BMA223_ADDRESS, BMA223_ACCD_X_LSB, sensorData, 6);
|
||||
if (FRToSI2C::Mem_Read(BMA223_ADDRESS, BMA223_ACCD_X_LSB, sensorData, 6) == false) {
|
||||
x = 0xAAFF;
|
||||
return;
|
||||
}
|
||||
|
||||
x = sensorData[1] << 2;
|
||||
y = sensorData[3] << 2;
|
||||
z = sensorData[5] << 2;
|
||||
x = sensorData[1] << 4;
|
||||
y = sensorData[3] << 4;
|
||||
z = sensorData[5] << 4;
|
||||
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
class BMA223 {
|
||||
public:
|
||||
static bool detect();
|
||||
static void initalize();
|
||||
static bool initalize();
|
||||
//1 = rh, 2,=lh, 8=flat
|
||||
static Orientation getOrientation() {
|
||||
#ifdef ACCEL_ORI_FLIP
|
||||
|
||||
@@ -24,8 +24,8 @@ static const FRToSI2C::I2C_REG i2c_registers[] = { { LIS_CTRL_REG1, 0x17, 0 }, /
|
||||
{ LIS_INT1_THS, 0x28, 0 }, //
|
||||
{ LIS_INT1_DURATION, 64, 0 } };
|
||||
|
||||
void LIS2DH12::initalize() {
|
||||
FRToSI2C::writeRegistersBulk(LIS2DH_I2C_ADDRESS, i2c_registers, sizeof(i2c_registers) / sizeof(i2c_registers[0]));
|
||||
bool LIS2DH12::initalize() {
|
||||
return FRToSI2C::writeRegistersBulk(LIS2DH_I2C_ADDRESS, i2c_registers, sizeof(i2c_registers) / sizeof(i2c_registers[0]));
|
||||
}
|
||||
|
||||
void LIS2DH12::getAxisReadings(int16_t &x, int16_t &y, int16_t &z) {
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
class LIS2DH12 {
|
||||
public:
|
||||
static bool detect();
|
||||
static void initalize();
|
||||
static bool initalize();
|
||||
//1 = rh, 2,=lh, 8=flat
|
||||
static Orientation getOrientation() {
|
||||
#ifdef LIS_ORI_FLIP
|
||||
|
||||
@@ -26,8 +26,8 @@ static const FRToSI2C::I2C_REG i2c_registers[] = { { CTRL_REG2, 0, 0 }, //Nor
|
||||
{ CTRL_REG1, 0x19, 0 } // ODR=12 Hz, Active mode
|
||||
};
|
||||
|
||||
void MMA8652FC::initalize() {
|
||||
FRToSI2C::writeRegistersBulk(MMA8652FC_I2C_ADDRESS, i2c_registers, sizeof(i2c_registers) / sizeof(i2c_registers[0]));
|
||||
bool MMA8652FC::initalize() {
|
||||
return FRToSI2C::writeRegistersBulk(MMA8652FC_I2C_ADDRESS, i2c_registers, sizeof(i2c_registers) / sizeof(i2c_registers[0]));
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@ public:
|
||||
//Returns true if this accelerometer is detected
|
||||
static bool detect();
|
||||
//Init any internal state
|
||||
static void initalize();
|
||||
static bool initalize();
|
||||
static Orientation getOrientation(); // Reads the I2C register and returns the orientation (true == left)
|
||||
static void getAxisReadings(int16_t &x, int16_t &y, int16_t &z);
|
||||
|
||||
|
||||
@@ -25,7 +25,7 @@ static const size_t PIDTaskStackSize = 512 / 4;
|
||||
uint32_t PIDTaskBuffer[PIDTaskStackSize];
|
||||
osStaticThreadDef_t PIDTaskControlBlock;
|
||||
osThreadId MOVTaskHandle;
|
||||
static const size_t MOVTaskStackSize = 512 / 4;
|
||||
static const size_t MOVTaskStackSize = 1024 / 4;
|
||||
uint32_t MOVTaskBuffer[MOVTaskStackSize];
|
||||
osStaticThreadDef_t MOVTaskControlBlock;
|
||||
|
||||
|
||||
@@ -603,7 +603,9 @@ uint8_t idleScreenBGF[sizeof(idleScreenBG)];
|
||||
/* StartGUITask function */
|
||||
void startGUITask(void const *argument __unused) {
|
||||
OLED::initialize(); // start up the LCD
|
||||
|
||||
// for (;;) {
|
||||
// osDelay(2000);
|
||||
// }
|
||||
uint8_t tempWarningState = 0;
|
||||
bool buttonLockout = false;
|
||||
bool tempOnDisplay = false;
|
||||
|
||||
@@ -27,21 +27,27 @@ void detectAccelerometerVersion() {
|
||||
#ifdef ACCEL_MMA
|
||||
if (MMA8652FC::detect()) {
|
||||
PCBVersion = 1;
|
||||
MMA8652FC::initalize(); // this sets up the I2C registers
|
||||
if(!MMA8652FC::initalize()) {
|
||||
PCBVersion = 99;
|
||||
}
|
||||
} else
|
||||
#endif
|
||||
#ifdef ACCEL_LIS
|
||||
if (LIS2DH12::detect()) {
|
||||
PCBVersion = 2;
|
||||
// Setup the ST Accelerometer
|
||||
LIS2DH12::initalize();// startup the accelerometer
|
||||
if(!LIS2DH12::initalize()) {
|
||||
PCBVersion = 99;
|
||||
}
|
||||
} else
|
||||
#endif
|
||||
#ifdef ACCEL_BMA
|
||||
if (BMA223::detect()) {
|
||||
PCBVersion = 3;
|
||||
// Setup the ST Accelerometer
|
||||
BMA223::initalize(); // startup the accelerometer
|
||||
if (!BMA223::initalize()) {
|
||||
PCBVersion = 99;
|
||||
}
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
@@ -76,7 +82,7 @@ inline void readAccelerometer(int16_t& tx, int16_t& ty, int16_t& tz, Orientation
|
||||
}
|
||||
}
|
||||
void startMOVTask(void const *argument __unused) {
|
||||
|
||||
osDelay(10);//Make oled init happen first
|
||||
postRToSInit();
|
||||
OLED::setRotation(systemSettings.OrientationMode & 1);
|
||||
detectAccelerometerVersion();
|
||||
@@ -93,6 +99,17 @@ void startMOVTask(void const *argument __unused) {
|
||||
if (systemSettings.sensitivity > 9)
|
||||
systemSettings.sensitivity = 9;
|
||||
Orientation rotation = ORIENTATION_FLAT;
|
||||
// OLED::setFont(1);
|
||||
// for (;;) {
|
||||
// OLED::clearScreen();
|
||||
// OLED::setCursor(0, 0);
|
||||
// readAccelerometer(tx, ty, tz, rotation);
|
||||
// OLED::printNumber(tx, 5, 0);
|
||||
// OLED::setCursor(0, 8);
|
||||
// OLED::printNumber(xTaskGetTickCount() / 10, 5, 1);
|
||||
// OLED::refresh();
|
||||
// osDelay(50);
|
||||
// }
|
||||
for (;;) {
|
||||
int32_t threshold = 1500 + (9 * 200);
|
||||
threshold -= systemSettings.sensitivity * 200; // 200 is the step size
|
||||
|
||||
Reference in New Issue
Block a user