kopia lustrzana https://github.com/UU5JPP/Wolf-LITE
271 wiersze
4.6 KiB
C
271 wiersze
4.6 KiB
C
#include "stm32f4xx_hal.h"
|
|
#include "main.h"
|
|
#include "functions.h"
|
|
#include "i2c.h"
|
|
|
|
/* low level conventions:
|
|
* - SDA/SCL idle high (expected high)
|
|
* - always start with i2c_delay rather than end
|
|
*/
|
|
|
|
I2C_DEVICE I2C_WM8731 = {
|
|
.SDA_PORT = WM8731_SDA_GPIO_Port,
|
|
.SDA_PIN = WM8731_SDA_Pin,
|
|
.SCK_PORT = WM8731_SCK_GPIO_Port,
|
|
.SCK_PIN = WM8731_SCK_Pin,
|
|
.i2c_tx_addr = 0,
|
|
.i2c_tx_buf = {0},
|
|
.i2c_tx_buf_idx = 0,
|
|
.i2c_tx_buf_overflow = false,
|
|
};
|
|
|
|
#ifdef HAS_TOUCHPAD
|
|
I2C_DEVICE I2C_TOUCHPAD = {
|
|
.SDA_PORT = ENC2_CLK_GPIO_Port,
|
|
.SDA_PIN = ENC2_CLK_Pin,
|
|
.SCK_PORT = ENC2_DT_GPIO_Port,
|
|
.SCK_PIN = ENC2_DT_Pin,
|
|
.i2c_tx_addr = 0,
|
|
.i2c_tx_buf = {0},
|
|
.i2c_tx_buf_idx = 0,
|
|
.i2c_tx_buf_overflow = false,
|
|
};
|
|
#endif
|
|
|
|
static uint8_t i2c_writeOneByte(I2C_DEVICE *dev, uint8_t);
|
|
|
|
static void SDA_OUT(I2C_DEVICE *dev)
|
|
{
|
|
GPIO_InitTypeDef GPIO_InitStruct;
|
|
GPIO_InitStruct.Pin = dev->SDA_PIN;
|
|
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_OD;
|
|
GPIO_InitStruct.Pull = GPIO_PULLUP;
|
|
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
|
|
HAL_GPIO_Init(dev->SDA_PORT, &GPIO_InitStruct);
|
|
}
|
|
|
|
static void SDA_IN(I2C_DEVICE *dev)
|
|
{
|
|
GPIO_InitTypeDef GPIO_InitStruct;
|
|
GPIO_InitStruct.Pin = dev->SDA_PIN;
|
|
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
|
|
GPIO_InitStruct.Pull = GPIO_PULLUP;
|
|
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
|
|
HAL_GPIO_Init(dev->SDA_PORT, &GPIO_InitStruct);
|
|
}
|
|
|
|
static void SCK_OUT(I2C_DEVICE *dev)
|
|
{
|
|
GPIO_InitTypeDef GPIO_InitStruct;
|
|
GPIO_InitStruct.Pin = dev->SCK_PIN;
|
|
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_OD;
|
|
GPIO_InitStruct.Pull = GPIO_PULLUP;
|
|
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
|
|
HAL_GPIO_Init(dev->SCK_PORT, &GPIO_InitStruct);
|
|
}
|
|
|
|
void i2c_start(I2C_DEVICE *dev)
|
|
{
|
|
SDA_SET;
|
|
SCK_SET;
|
|
I2C_DELAY
|
|
SDA_CLR;
|
|
I2C_DELAY
|
|
SCK_CLR;
|
|
}
|
|
|
|
void i2c_stop(I2C_DEVICE *dev)
|
|
{
|
|
SDA_OUT(dev);
|
|
SDA_CLR;
|
|
SCK_SET;
|
|
I2C_DELAY
|
|
I2C_DELAY
|
|
I2C_DELAY
|
|
I2C_DELAY
|
|
SDA_SET;
|
|
I2C_DELAY
|
|
}
|
|
|
|
bool i2c_get_ack(I2C_DEVICE *dev)
|
|
{
|
|
uint32_t time = 0;
|
|
|
|
SDA_IN(dev);
|
|
|
|
I2C_DELAY
|
|
I2C_DELAY
|
|
SCK_SET;
|
|
I2C_DELAY
|
|
I2C_DELAY
|
|
|
|
while (HAL_GPIO_ReadPin(dev->SDA_PORT, dev->SDA_PIN))
|
|
{
|
|
time++;
|
|
if (time > 50)
|
|
{
|
|
i2c_stop(dev);
|
|
return false;
|
|
}
|
|
I2C_DELAY
|
|
I2C_DELAY
|
|
}
|
|
|
|
SCK_CLR;
|
|
|
|
return true;
|
|
}
|
|
|
|
void i2c_shift_out(I2C_DEVICE *dev, uint8_t val)
|
|
{
|
|
SDA_OUT(dev);
|
|
int i;
|
|
for (i = 0; i < 8; i++)
|
|
{
|
|
|
|
I2C_DELAY
|
|
HAL_GPIO_WritePin(dev->SDA_PORT, dev->SDA_PIN, (GPIO_PinState) !!(val & (1 << (7 - i))));
|
|
SDA_OUT(dev);
|
|
|
|
I2C_DELAY
|
|
SCK_SET;
|
|
|
|
I2C_DELAY
|
|
I2C_DELAY
|
|
SCK_CLR;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Joins I2C bus as master on given SDA and SCL pins.
|
|
*/
|
|
void i2c_begin(I2C_DEVICE *dev)
|
|
{
|
|
SCK_SET;
|
|
SDA_SET;
|
|
|
|
SCK_OUT(dev);
|
|
SDA_OUT(dev);
|
|
}
|
|
|
|
void i2c_beginTransmission_u8(I2C_DEVICE *dev, uint8_t slave_address)
|
|
{
|
|
i2c_begin(dev);
|
|
dev->i2c_tx_addr = slave_address;
|
|
dev->i2c_tx_buf_idx = 0;
|
|
dev->i2c_tx_buf_overflow = false;
|
|
}
|
|
|
|
bool i2c_beginReceive_u8(I2C_DEVICE *dev, uint8_t slave_address)
|
|
{
|
|
i2c_begin(dev);
|
|
dev->i2c_tx_addr = slave_address;
|
|
dev->i2c_tx_buf_idx = 0;
|
|
dev->i2c_tx_buf_overflow = false;
|
|
i2c_start(dev);
|
|
i2c_shift_out(dev, (uint8_t)((dev->i2c_tx_addr << 1) | I2C_READ));
|
|
if (!i2c_get_ack(dev))
|
|
{
|
|
//sendToDebug_strln("no ack");
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
uint8_t i2c_endTransmission(I2C_DEVICE *dev)
|
|
{
|
|
if (dev->i2c_tx_buf_overflow)
|
|
return EDATA;
|
|
i2c_start(dev);
|
|
|
|
//I2C_DELAY;
|
|
i2c_shift_out(dev, (uint8_t)((dev->i2c_tx_addr << 1) | I2C_WRITE));
|
|
if (!i2c_get_ack(dev))
|
|
return ENACKADDR;
|
|
|
|
// shift out the address we're transmitting to
|
|
for (uint8_t i = 0; i < dev->i2c_tx_buf_idx; i++)
|
|
{
|
|
uint8_t ret = i2c_writeOneByte(dev, dev->i2c_tx_buf[i]);
|
|
if (ret)
|
|
return ret; // SUCCESS is 0
|
|
}
|
|
I2C_DELAY
|
|
I2C_DELAY
|
|
i2c_stop(dev);
|
|
|
|
dev->i2c_tx_buf_idx = 0;
|
|
dev->i2c_tx_buf_overflow = false;
|
|
return SUCCESS;
|
|
}
|
|
|
|
void i2c_write_u8(I2C_DEVICE *dev, uint8_t value)
|
|
{
|
|
if (dev->i2c_tx_buf_idx == WIRE_BUFSIZ)
|
|
{
|
|
dev->i2c_tx_buf_overflow = true;
|
|
return;
|
|
}
|
|
|
|
dev->i2c_tx_buf[dev->i2c_tx_buf_idx++] = value;
|
|
}
|
|
|
|
// private methods
|
|
static uint8_t i2c_writeOneByte(I2C_DEVICE *dev, uint8_t byte)
|
|
{
|
|
i2c_shift_out(dev, byte);
|
|
if (!i2c_get_ack(dev))
|
|
return ENACKTRNS;
|
|
return SUCCESS;
|
|
}
|
|
|
|
uint8_t i2c_Read_Byte(I2C_DEVICE *dev, uint8_t ack)
|
|
{
|
|
unsigned char i,receive=0;
|
|
SDA_IN(dev);
|
|
I2C_DELAY
|
|
I2C_DELAY
|
|
|
|
for(i=0;i<8;i++ )
|
|
{
|
|
SCK_CLR;
|
|
I2C_DELAY
|
|
I2C_DELAY
|
|
SCK_SET;
|
|
receive<<=1;
|
|
I2C_DELAY
|
|
I2C_DELAY
|
|
if(HAL_GPIO_ReadPin(dev->SDA_PORT,dev->SDA_PIN))
|
|
receive++;
|
|
}
|
|
if (!ack)
|
|
{
|
|
//NAck
|
|
SCK_CLR;
|
|
SDA_OUT(dev);
|
|
SDA_SET;
|
|
I2C_DELAY
|
|
I2C_DELAY
|
|
SCK_SET;
|
|
I2C_DELAY
|
|
I2C_DELAY
|
|
SCK_CLR;
|
|
SDA_IN(dev);
|
|
}
|
|
else
|
|
{
|
|
//Ack
|
|
SCK_CLR;
|
|
SDA_OUT(dev);
|
|
SDA_CLR;
|
|
I2C_DELAY
|
|
I2C_DELAY
|
|
SCK_SET;
|
|
I2C_DELAY
|
|
I2C_DELAY
|
|
SCK_CLR;
|
|
SDA_IN(dev);
|
|
}
|
|
return receive;
|
|
}
|