Adding first version of STM32F7 discovery touch driver
This commit is contained in:
parent
78dc6e4b8e
commit
940eda4cd4
6 changed files with 222 additions and 206 deletions
|
@ -18,7 +18,8 @@ ifeq ($(OPT_OS),raw32)
|
||||||
GFXSRC += $(GFXLIB)/boards/base/STM32F746-Discovery/stm32f746g_raw32_startup.s \
|
GFXSRC += $(GFXLIB)/boards/base/STM32F746-Discovery/stm32f746g_raw32_startup.s \
|
||||||
$(GFXLIB)/boards/base/STM32F746-Discovery/stm32f746g_raw32_ugfx.c \
|
$(GFXLIB)/boards/base/STM32F746-Discovery/stm32f746g_raw32_ugfx.c \
|
||||||
$(GFXLIB)/boards/base/STM32F746-Discovery/stm32f746g_raw32_system.c \
|
$(GFXLIB)/boards/base/STM32F746-Discovery/stm32f746g_raw32_system.c \
|
||||||
$(GFXLIB)/boards/base/STM32F746-Discovery/stm32f746g_raw32_interrupts.c
|
$(GFXLIB)/boards/base/STM32F746-Discovery/stm32f746g_raw32_interrupts.c \
|
||||||
|
$(GFXLIB)/boards/base/STM32F746-Discovery/stm32f7_i2c.c
|
||||||
GFXDEFS += GFX_OS_EXTRA_INIT_FUNCTION=Raw32OSInit GFX_OS_INIT_NO_WARNING=TRUE
|
GFXDEFS += GFX_OS_EXTRA_INIT_FUNCTION=Raw32OSInit GFX_OS_INIT_NO_WARNING=TRUE
|
||||||
SRCFLAGS+= -std=c99
|
SRCFLAGS+= -std=c99
|
||||||
GFXINC += $(CMSIS)/Device/ST/STM32F7xx/Include \
|
GFXINC += $(CMSIS)/Device/ST/STM32F7xx/Include \
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
#define _GINPUT_LLD_MOUSE_BOARD_H
|
#define _GINPUT_LLD_MOUSE_BOARD_H
|
||||||
|
|
||||||
#include "stm32f7xx.h"
|
#include "stm32f7xx.h"
|
||||||
|
#include "stm32f7_i2c.h"
|
||||||
|
|
||||||
// Resolution and Accuracy Settings
|
// Resolution and Accuracy Settings
|
||||||
#define GMOUSE_FT5336_PEN_CALIBRATE_ERROR 8
|
#define GMOUSE_FT5336_PEN_CALIBRATE_ERROR 8
|
||||||
|
@ -21,14 +22,8 @@
|
||||||
// How much extra data to allocate at the end of the GMouse structure for the board's use
|
// How much extra data to allocate at the end of the GMouse structure for the board's use
|
||||||
#define GMOUSE_FT5336_BOARD_DATA_SIZE 0
|
#define GMOUSE_FT5336_BOARD_DATA_SIZE 0
|
||||||
|
|
||||||
// Set this to TRUE if you want self-calibration.
|
// The FT5336 I2C slave address (including the R/W bit)
|
||||||
// NOTE: This is not as accurate as real calibration.
|
#define FT5336_SLAVE_ADDR 0x70
|
||||||
// It requires the orientation of the touch panel to match the display.
|
|
||||||
// It requires the active area of the touch panel to exactly match the display size.
|
|
||||||
#define GMOUSE_FT5336_SELF_CALIBRATE FALSE
|
|
||||||
|
|
||||||
// The FT5336 slave address
|
|
||||||
#define FT5336_ADDR 0x70
|
|
||||||
|
|
||||||
static bool_t init_board(GMouse* m, unsigned instance)
|
static bool_t init_board(GMouse* m, unsigned instance)
|
||||||
{
|
{
|
||||||
|
@ -36,52 +31,23 @@ static bool_t init_board(GMouse* m, unsigned instance)
|
||||||
(void)instance;
|
(void)instance;
|
||||||
|
|
||||||
// I2C3_SCL GPIOH7, alternate, opendrain, highspeed
|
// I2C3_SCL GPIOH7, alternate, opendrain, highspeed
|
||||||
RCC->AHB1ENR |= RCC_AHB1ENR_GPIOBEN; // Enable clock for
|
RCC->AHB1ENR |= RCC_AHB1ENR_GPIOHEN; // Enable clock for
|
||||||
GPIOB->MODER |= GPIO_MODER_MODER7_1; // Alternate function
|
GPIOH->MODER |= GPIO_MODER_MODER7_1; // Alternate function
|
||||||
GPIOB->OTYPER |= GPIO_OTYPER_OT_7; // OpenDrain
|
GPIOH->OTYPER |= GPIO_OTYPER_OT_7; // OpenDrain
|
||||||
GPIOB->PUPDR |= GPIO_PUPDR_PUPDR7_0; // PullUp
|
GPIOH->OSPEEDR &= ~GPIO_OSPEEDER_OSPEEDR7; // LowSpeed
|
||||||
GPIOB->OSPEEDR |= GPIO_OSPEEDER_OSPEEDR7; // HighSpeed
|
GPIOH->AFR[0] |= (0b0100 << 4*7); // AF4
|
||||||
GPIOB->AFR[0] |= (0b0100 << 4*0); // AF4
|
|
||||||
|
|
||||||
// I2C3_SDA GPIOH8, alternate, opendrain, highspeed
|
// I2C3_SDA GPIOH8, alternate, opendrain, highspeed
|
||||||
RCC->AHB1ENR |= RCC_AHB1ENR_GPIOBEN; // Enable clock
|
RCC->AHB1ENR |= RCC_AHB1ENR_GPIOHEN; // Enable clock
|
||||||
GPIOB->MODER |= GPIO_MODER_MODER8_1; // Alternate function
|
GPIOH->MODER |= GPIO_MODER_MODER8_1; // Alternate function
|
||||||
GPIOB->OTYPER |= GPIO_OTYPER_OT_8; // OpenDrain
|
GPIOH->OTYPER |= GPIO_OTYPER_OT_8; // OpenDrain
|
||||||
GPIOB->PUPDR |= GPIO_PUPDR_PUPDR8_0; // PullUp
|
GPIOH->OSPEEDR &= ~GPIO_OSPEEDER_OSPEEDR8; // LowSpeed
|
||||||
GPIOB->OSPEEDR |= GPIO_OSPEEDER_OSPEEDR8; // HighSpeed
|
GPIOH->AFR[1] |= (0b0100 << 4*0); // AF4
|
||||||
GPIOB->AFR[1] |= (0b0100 << 4*0); // AF4
|
|
||||||
|
|
||||||
// Enable I2C3 peripheral clock
|
// Initialize the I2C3 peripheral
|
||||||
RCC->APB1ENR |= RCC_APB1ENR_I2C3EN;
|
if (!(i2cInit(I2C3))) {
|
||||||
|
return FALSE;
|
||||||
// Reset I2C3 peripheral
|
}
|
||||||
RCC->APB1RSTR |= RCC_APB1RSTR_I2C3RST;
|
|
||||||
RCC->APB1RSTR &= ~RCC_APB1RSTR_I2C3RST;
|
|
||||||
|
|
||||||
// Set Fm mode
|
|
||||||
I2C3->CCR |= I2C_CCR_FS;
|
|
||||||
|
|
||||||
// Set Duty to 50:50
|
|
||||||
I2C3->CCR &= ~I2C_CCR_DUTY;
|
|
||||||
|
|
||||||
// Set peripheral clock frequency (APB1 frequency)
|
|
||||||
// APB1CLK running at 42 MHz
|
|
||||||
I2C3->CR2 |= 42;
|
|
||||||
|
|
||||||
// Set I2C bus clock speed to 400 kHz
|
|
||||||
// Period of 400 kHz is 2.5 us, half of that is 1.25 us. TPCLK1 is
|
|
||||||
// 40 ns (see below). 1.25 us / 40 ns = 32.
|
|
||||||
I2C3->CCR |= (I2C_CCR_CCR & 32);
|
|
||||||
|
|
||||||
// Rise time
|
|
||||||
// Period of 42 MHz is 24 ns. Rise time is 1000 ns. 1000/24 = 42.
|
|
||||||
I2C3->TRISE |= (I2C_TRISE_TRISE & 42);
|
|
||||||
|
|
||||||
// Disable POS
|
|
||||||
I2C3->CR1 &=~ I2C_CR1_POS;
|
|
||||||
|
|
||||||
// Enable I2C3
|
|
||||||
I2C3->CR1 |= I2C_CR1_PE;
|
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
@ -90,137 +56,21 @@ static void write_reg(GMouse* m, uint8_t reg, uint8_t val)
|
||||||
{
|
{
|
||||||
(void)m;
|
(void)m;
|
||||||
|
|
||||||
// Generate start condition
|
i2cWriteReg(I2C3, FT5336_SLAVE_ADDR, reg, val);
|
||||||
I2C3->CR1 |= I2C_CR1_START;
|
|
||||||
while (!(I2C3->SR2 & I2C_SR2_MSL));
|
|
||||||
while (!(I2C3->SR1 & I2C_SR1_SB));
|
|
||||||
|
|
||||||
// Send slave address (Write = last bit is 0)
|
|
||||||
I2C3->DR = ((FT5336_ADDR | 0) & I2C_DR_DR);
|
|
||||||
while (!(I2C3->SR1 & I2C_SR1_ADDR));
|
|
||||||
|
|
||||||
// Read SR1/SR2 register to clear the SB bit (see STM32F4xx RM)
|
|
||||||
(void)I2C3->SR1;
|
|
||||||
(void)I2C3->SR2;
|
|
||||||
|
|
||||||
// Send register address
|
|
||||||
while (!(I2C3->SR1 & I2C_SR1_TXE));
|
|
||||||
I2C3->DR = (reg & I2C_DR_DR);
|
|
||||||
|
|
||||||
// Send data
|
|
||||||
while (!(I2C3->SR1 & I2C_SR1_TXE));
|
|
||||||
I2C3->DR = (val & I2C_DR_DR);
|
|
||||||
|
|
||||||
// Generate stop condition when we are done transmitting
|
|
||||||
while (!(I2C3->SR1 & I2C_SR1_TXE));
|
|
||||||
I2C3->CR1 |= I2C_CR1_STOP;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint8_t read_byte(GMouse* m, uint8_t reg)
|
static uint8_t read_byte(GMouse* m, uint8_t reg)
|
||||||
{
|
{
|
||||||
(void)m;
|
(void)m;
|
||||||
|
|
||||||
uint8_t ret = 0x00;
|
return i2cReadByte(I2C3, FT5336_SLAVE_ADDR, reg);
|
||||||
|
|
||||||
// Generate start condition
|
|
||||||
I2C3->CR1 |= I2C_CR1_START;
|
|
||||||
while (!(I2C3->SR2 & I2C_SR2_MSL));
|
|
||||||
while (!(I2C3->SR1 & I2C_SR1_SB));
|
|
||||||
|
|
||||||
// Send slave address (Write = last bit is 0)
|
|
||||||
I2C3->DR = ((FT5336_ADDR | 0) & I2C_DR_DR);
|
|
||||||
while (!(I2C3->SR1 & I2C_SR1_ADDR));
|
|
||||||
|
|
||||||
// Read SR1/SR2 register to clear the SB bit (see STM32F4xx RM)
|
|
||||||
(void)I2C3->SR1;
|
|
||||||
(void)I2C3->SR2;
|
|
||||||
|
|
||||||
// Send register address that we want to read
|
|
||||||
I2C3->DR = (reg & I2C_DR_DR);
|
|
||||||
while (!(I2C3->SR1 & I2C_SR1_BTF));
|
|
||||||
|
|
||||||
// Generate start condition (repeated start)
|
|
||||||
I2C3->CR1 |= I2C_CR1_START;
|
|
||||||
while (!(I2C3->SR2 & I2C_SR2_MSL));
|
|
||||||
while (!(I2C3->SR1 & I2C_SR1_SB));
|
|
||||||
|
|
||||||
// Send slave address (Read = last bit is 1)
|
|
||||||
I2C3->DR = ((FT5336_ADDR | 1) & I2C_DR_DR);
|
|
||||||
while (!(I2C3->SR1 & I2C_SR1_ADDR));
|
|
||||||
|
|
||||||
// Set up for one byte receival
|
|
||||||
I2C3->CR1 &= ~I2C_CR1_POS;
|
|
||||||
//I2C3->CR1 |= I2C_CR1_ACK;
|
|
||||||
|
|
||||||
// Read SR1/SR2 register to clear the SB bit (see STM32F4xx RM)
|
|
||||||
(void)I2C3->SR1;
|
|
||||||
(void)I2C3->SR2;
|
|
||||||
|
|
||||||
// Clean SR1_ACK. This needs to be done on the last byte received from slave
|
|
||||||
I2C3->CR1 &= ~I2C_CR1_ACK;
|
|
||||||
|
|
||||||
// Generate stop condition
|
|
||||||
I2C3->CR1 |= I2C_CR1_STOP;
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint16_t read_word(GMouse* m, uint8_t reg)
|
static uint16_t read_word(GMouse* m, uint8_t reg)
|
||||||
{
|
{
|
||||||
(void)m;
|
(void)m;
|
||||||
|
|
||||||
uint16_t ret = 0x00;
|
return i2cReadWord(I2C3, FT5336_SLAVE_ADDR, reg);
|
||||||
|
|
||||||
// Generate start condition
|
|
||||||
I2C3->CR1 |= I2C_CR1_START;
|
|
||||||
while (!(I2C3->SR2 & I2C_SR2_MSL));
|
|
||||||
while (!(I2C3->SR1 & I2C_SR1_SB));
|
|
||||||
|
|
||||||
// Send slave address (Write = last bit is 0)
|
|
||||||
I2C3->DR = ((FT5336_ADDR | 0) & I2C_DR_DR);
|
|
||||||
while (!(I2C3->SR1 & I2C_SR1_ADDR));
|
|
||||||
|
|
||||||
// Read SR1/SR2 register to clear the SB bit (see STM32F4xx RM)
|
|
||||||
(void)I2C3->SR1;
|
|
||||||
(void)I2C3->SR2;
|
|
||||||
|
|
||||||
// Send register address that we want to read
|
|
||||||
I2C3->DR = (reg & I2C_DR_DR);
|
|
||||||
while (!(I2C3->SR1 & I2C_SR1_BTF));
|
|
||||||
|
|
||||||
// Generate start condition (repeated start)
|
|
||||||
I2C3->CR1 |= I2C_CR1_START;
|
|
||||||
while (!(I2C3->SR2 & I2C_SR2_MSL));
|
|
||||||
while (!(I2C3->SR1 & I2C_SR1_SB));
|
|
||||||
|
|
||||||
// Send slave address (Read = last bit is 1)
|
|
||||||
I2C3->DR = ((FT5336_ADDR | 1) & I2C_DR_DR);
|
|
||||||
while (!(I2C3->SR1 & I2C_SR1_ADDR));
|
|
||||||
|
|
||||||
// Set up for two byte receival
|
|
||||||
I2C3->CR1 |= I2C_CR1_POS;
|
|
||||||
//I2C3->CR1 &= ~I2C_CR1_ACK;
|
|
||||||
I2C3->SR1 &= ~I2C_SR1_ADDR;
|
|
||||||
|
|
||||||
// Read SR1/SR2 register to clear the SB bit (see STM32F4xx RM)
|
|
||||||
(void)I2C3->SR1;
|
|
||||||
(void)I2C3->SR2;
|
|
||||||
|
|
||||||
// The slave should now send a byte to us.
|
|
||||||
while (!(I2C3->SR1 & I2C_SR1_RXNE));
|
|
||||||
ret = (uint16_t)((I2C3->DR & 0x00FF) << 8);
|
|
||||||
|
|
||||||
// Set STOP and clear ACK right after reading the second last byte
|
|
||||||
I2C3->CR1 |= I2C_CR1_STOP;
|
|
||||||
I2C3->CR1 &= ~I2C_CR1_ACK;
|
|
||||||
|
|
||||||
// The second byte becomes available after sending the stop condition
|
|
||||||
ret |= (I2C3->DR & 0x00FF);
|
|
||||||
|
|
||||||
// Get back to original state
|
|
||||||
I2C3->CR1 &= ~I2C_CR1_POS;
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* _GINPUT_LLD_MOUSE_BOARD_H */
|
#endif /* _GINPUT_LLD_MOUSE_BOARD_H */
|
||||||
|
|
164
boards/base/STM32F746-Discovery/stm32f7_i2c.c
Normal file
164
boards/base/STM32F746-Discovery/stm32f7_i2c.c
Normal file
|
@ -0,0 +1,164 @@
|
||||||
|
#include "stm32f7_i2c.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The CR2 register needs atomic access. Hence always use this function to setup a transfer configuration.
|
||||||
|
*/
|
||||||
|
static void _i2cConfigTransfer(I2C_TypeDef* i2c, uint16_t slaveAddr, uint8_t numBytes, uint32_t mode, uint32_t request)
|
||||||
|
{
|
||||||
|
uint32_t tmpreg = 0;
|
||||||
|
|
||||||
|
// Get the current CR2 register value
|
||||||
|
tmpreg = i2c->CR2;
|
||||||
|
|
||||||
|
// Clear tmpreg specific bits
|
||||||
|
tmpreg &= (uint32_t) ~((uint32_t) (I2C_CR2_SADD | I2C_CR2_NBYTES | I2C_CR2_RELOAD | I2C_CR2_AUTOEND | I2C_CR2_RD_WRN | I2C_CR2_START | I2C_CR2_STOP));
|
||||||
|
|
||||||
|
// update tmpreg
|
||||||
|
tmpreg |= (uint32_t) (((uint32_t) slaveAddr & I2C_CR2_SADD) | (((uint32_t) numBytes << 16) & I2C_CR2_NBYTES) | (uint32_t) mode | (uint32_t) request);
|
||||||
|
|
||||||
|
// Update the actual CR2 contents
|
||||||
|
i2c->CR2 = tmpreg;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* According to the STM32Cube HAL the CR2 register needs to be reset after each transaction.
|
||||||
|
*/
|
||||||
|
static void _i2cResetCr2(I2C_TypeDef* i2c)
|
||||||
|
{
|
||||||
|
i2c->CR2 &= (uint32_t) ~((uint32_t) (I2C_CR2_SADD | I2C_CR2_HEAD10R | I2C_CR2_NBYTES | I2C_CR2_RELOAD | I2C_CR2_RD_WRN));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool_t i2cInit(I2C_TypeDef* i2c)
|
||||||
|
{
|
||||||
|
// Enable I2Cx peripheral clock.
|
||||||
|
// Select APB1 as clock source
|
||||||
|
if (i2c == I2C1) {
|
||||||
|
RCC->DCKCFGR2 &= ~RCC_DCKCFGR2_I2C1SEL;
|
||||||
|
RCC->APB1ENR |= RCC_APB1ENR_I2C1EN;
|
||||||
|
} else if (i2c == I2C2) {
|
||||||
|
RCC->DCKCFGR2 &= ~RCC_DCKCFGR2_I2C2SEL;
|
||||||
|
RCC->APB1ENR |= RCC_APB1ENR_I2C2EN;
|
||||||
|
} else if (i2c == I2C3) {
|
||||||
|
RCC->DCKCFGR2 &= ~RCC_DCKCFGR2_I2C3SEL;
|
||||||
|
RCC->APB1ENR |= RCC_APB1ENR_I2C3EN;
|
||||||
|
} else if (i2c == I2C4) {
|
||||||
|
RCC->DCKCFGR2 &= ~RCC_DCKCFGR2_I2C4SEL;
|
||||||
|
RCC->APB1ENR |= RCC_APB1ENR_I2C4EN;
|
||||||
|
} else {
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Disable the I2Cx peripheral
|
||||||
|
i2c->CR1 &= ~I2C_CR1_PE;
|
||||||
|
while (i2c->CR1 & I2C_CR1_PE);
|
||||||
|
|
||||||
|
// Set timings. Asuming I2CCLK is 50 MHz (APB1 clock source)
|
||||||
|
i2c->TIMINGR = 0x40912732; // Discovery BSP code from ST examples
|
||||||
|
|
||||||
|
// Use 7-bit addresses
|
||||||
|
i2c->CR2 &=~ I2C_CR2_ADD10;
|
||||||
|
|
||||||
|
// Enable auto-end mode
|
||||||
|
i2c->CR2 |= I2C_CR2_AUTOEND;
|
||||||
|
|
||||||
|
// Disable the analog filter
|
||||||
|
i2c->CR1 |= I2C_CR1_ANFOFF;
|
||||||
|
|
||||||
|
// Disable NOSTRETCH
|
||||||
|
i2c->CR1 |= I2C_CR1_NOSTRETCH;
|
||||||
|
|
||||||
|
// Enable the I2Cx peripheral
|
||||||
|
i2c->CR1 |= I2C_CR1_PE;
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
void i2cSend(I2C_TypeDef* i2c, uint8_t slaveAddr, uint8_t* data, uint16_t length)
|
||||||
|
{
|
||||||
|
// We are currently not able to send more than 255 bytes at once
|
||||||
|
if (length > 255) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Setup the configuration
|
||||||
|
_i2cConfigTransfer(i2c, slaveAddr, length, (!I2C_CR2_RD_WRN) | I2C_CR2_AUTOEND, I2C_CR2_START);
|
||||||
|
|
||||||
|
// Transmit the whole buffer
|
||||||
|
while (length > 0) {
|
||||||
|
while (!(i2c->ISR & I2C_ISR_TXIS));
|
||||||
|
i2c->TXDR = *data++;
|
||||||
|
length--;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Wait until the transfer is complete
|
||||||
|
while (!(i2c->ISR & I2C_ISR_TXE));
|
||||||
|
|
||||||
|
// Wait until the stop condition was automagically sent
|
||||||
|
while (!(i2c->ISR & I2C_ISR_STOPF));
|
||||||
|
|
||||||
|
// Reset the STOP bit
|
||||||
|
i2c->ISR &= ~I2C_ISR_STOPF;
|
||||||
|
|
||||||
|
// Reset the CR2 register
|
||||||
|
_i2cResetCr2(i2c);
|
||||||
|
}
|
||||||
|
|
||||||
|
void i2cSendByte(I2C_TypeDef* i2c, uint8_t slaveAddr, uint8_t data)
|
||||||
|
{
|
||||||
|
i2cSend(i2c, slaveAddr, &data, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void i2cWriteReg(I2C_TypeDef* i2c, uint8_t slaveAddr, uint8_t regAddr, uint8_t value)
|
||||||
|
{
|
||||||
|
uint8_t txbuf[2];
|
||||||
|
txbuf[0] = regAddr;
|
||||||
|
txbuf[1] = value;
|
||||||
|
|
||||||
|
i2cSend(i2c, slaveAddr, txbuf, 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
void i2cRead(I2C_TypeDef* i2c, uint8_t slaveAddr, uint8_t* data, uint16_t length)
|
||||||
|
{
|
||||||
|
// We are currently not able to read more than 255 bytes at once
|
||||||
|
if (length > 255) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Setup the configuration
|
||||||
|
_i2cConfigTransfer(i2c, slaveAddr, length, I2C_CR2_RD_WRN | I2C_CR2_AUTOEND, I2C_CR2_START);
|
||||||
|
|
||||||
|
// Transmit the whole buffer
|
||||||
|
for (int i = 0; i < length; i++) {
|
||||||
|
while (!(i2c->ISR & I2C_ISR_RXNE));
|
||||||
|
data[i] = i2c->RXDR;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Wait until the stop condition was automagically sent
|
||||||
|
while (!(i2c->ISR & I2C_ISR_STOPF));
|
||||||
|
|
||||||
|
// Reset the STOP bit
|
||||||
|
i2c->ISR &= ~I2C_ISR_STOPF;
|
||||||
|
|
||||||
|
// Reset the CR2 register
|
||||||
|
_i2cResetCr2(i2c);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t i2cReadByte(I2C_TypeDef* i2c, uint8_t slaveAddr, uint8_t regAddr)
|
||||||
|
{
|
||||||
|
uint8_t ret = 0xAA;
|
||||||
|
|
||||||
|
i2cSend(i2c, slaveAddr, ®Addr, 1);
|
||||||
|
i2cRead(i2c, slaveAddr, &ret, 1);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t i2cReadWord(I2C_TypeDef* i2c, uint8_t slaveAddr, uint8_t regAddr)
|
||||||
|
{
|
||||||
|
uint8_t ret[2] = { 0xAA, 0xAA };
|
||||||
|
|
||||||
|
i2cSend(i2c, slaveAddr, ®Addr, 1);
|
||||||
|
i2cRead(i2c, slaveAddr, ret, 2);
|
||||||
|
|
||||||
|
return (uint16_t)((ret[0] << 8) | (ret[1] & 0x00FF));
|
||||||
|
}
|
14
boards/base/STM32F746-Discovery/stm32f7_i2c.h
Normal file
14
boards/base/STM32F746-Discovery/stm32f7_i2c.h
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "stm32f7xx.h"
|
||||||
|
#include "gfx.h"
|
||||||
|
|
||||||
|
bool_t i2cInit(I2C_TypeDef* i2c);
|
||||||
|
|
||||||
|
void i2cSend(I2C_TypeDef* i2c, uint8_t slaveAddr, uint8_t* data, uint16_t length);
|
||||||
|
void i2cSendByte(I2C_TypeDef* i2c, uint8_t slaveAddr, uint8_t data);
|
||||||
|
void i2cWriteReg(I2C_TypeDef* i2c, uint8_t slaveAddr, uint8_t regAddr, uint8_t value);
|
||||||
|
|
||||||
|
void i2cRead(I2C_TypeDef* i2c, uint8_t slaveAddr, uint8_t* data, uint16_t length);
|
||||||
|
uint8_t i2cReadByte(I2C_TypeDef* i2c, uint8_t slaveAddr, uint8_t regAddr);
|
||||||
|
uint16_t i2cReadWord(I2C_TypeDef* i2c, uint8_t slaveAddr, uint8_t regAddr);
|
|
@ -50,6 +50,7 @@
|
||||||
#define GDISP_NEED_CIRCLE TRUE
|
#define GDISP_NEED_CIRCLE TRUE
|
||||||
#define GDISP_NEED_TEXT TRUE
|
#define GDISP_NEED_TEXT TRUE
|
||||||
#define GDISP_NEED_MULTITHREAD TRUE
|
#define GDISP_NEED_MULTITHREAD TRUE
|
||||||
|
#define GDISP_NEED_CONTROL TRUE
|
||||||
|
|
||||||
/* GDISP fonts to include */
|
/* GDISP fonts to include */
|
||||||
#define GDISP_INCLUDE_FONT_UI2 TRUE
|
#define GDISP_INCLUDE_FONT_UI2 TRUE
|
||||||
|
|
|
@ -20,10 +20,23 @@
|
||||||
|
|
||||||
static bool_t ft5336Init(GMouse* m, unsigned driverinstance)
|
static bool_t ft5336Init(GMouse* m, unsigned driverinstance)
|
||||||
{
|
{
|
||||||
|
// Initialize the board stuff
|
||||||
if (!init_board(m, driverinstance)) {
|
if (!init_board(m, driverinstance)) {
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// We need at least 200 ms worth of delay here...
|
||||||
|
gfxSleepMilliseconds(200);
|
||||||
|
|
||||||
|
// Check Chip ID
|
||||||
|
if (read_byte(m, FT5336_CHIP_ID_REG) != FT5336_ID_VALUE) {
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Disable interrupts. We use this chip in polling mode
|
||||||
|
write_reg(m, FT5336_GMODE_REG, (FT5336_G_MODE_INTERRUPT_POLLING & (FT5336_G_MODE_INTERRUPT_MASK >> FT5336_G_MODE_INTERRUPT_SHIFT)) << FT5336_G_MODE_INTERRUPT_SHIFT);
|
||||||
|
|
||||||
|
/*
|
||||||
// Init default values. (From NHD-3.5-320240MF-ATXL-CTP-1 datasheet)
|
// Init default values. (From NHD-3.5-320240MF-ATXL-CTP-1 datasheet)
|
||||||
// Valid touching detect threshold
|
// Valid touching detect threshold
|
||||||
write_reg(m, FT5336_TH_GROUP_REG, 0x16);
|
write_reg(m, FT5336_TH_GROUP_REG, 0x16);
|
||||||
|
@ -39,7 +52,7 @@ static bool_t ft5336Init(GMouse* m, unsigned driverinstance)
|
||||||
|
|
||||||
// Timer to enter 'idle' when in 'Monitor' (ms)
|
// Timer to enter 'idle' when in 'Monitor' (ms)
|
||||||
write_reg(m, FT5336_PERIODMONITOR_REG, 0x28);
|
write_reg(m, FT5336_PERIODMONITOR_REG, 0x28);
|
||||||
|
*/
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -49,35 +62,12 @@ static bool_t ft5336ReadXYZ(GMouse* m, GMouseReading* pdr)
|
||||||
pdr->buttons = 0;
|
pdr->buttons = 0;
|
||||||
pdr->z = 0;
|
pdr->z = 0;
|
||||||
|
|
||||||
// Only take a reading if we are touched.
|
// Only take a reading if exactly one touch contact point
|
||||||
if ((read_byte(m, FT5336_TD_STAT_REG) & 0x07)) {
|
if (read_byte(m, FT5336_TD_STAT_REG) == 1) {
|
||||||
|
// Get and return X, Y an Z values
|
||||||
/* Get the X, Y, Z values */
|
pdr->y = (coord_t)(read_word(m, FT5336_P1_XH_REG) & 0x0FFF);
|
||||||
pdr->x = (coord_t)(read_word(m, FT5336_P1_XH_REG) & 0x0FFF);
|
pdr->x = (coord_t)(read_word(m, FT5336_P1_YH_REG) & 0x0FFF);
|
||||||
pdr->y = (coord_t)(read_word(m, FT5336_P1_YH_REG) & 0xFFFF);
|
|
||||||
pdr->z = 1;
|
pdr->z = 1;
|
||||||
|
|
||||||
// Rescale X,Y if we are using self-calibration
|
|
||||||
#if GMOUSE_FT5336_SELF_CALIBRATE
|
|
||||||
#if GDISP_NEED_CONTROL
|
|
||||||
switch(gdispGGetOrientation(m->display)) {
|
|
||||||
default:
|
|
||||||
case GDISP_ROTATE_0:
|
|
||||||
case GDISP_ROTATE_180:
|
|
||||||
pdr->x = gdispGGetWidth(m->display) - pdr->x / (4096/gdispGGetWidth(m->display));
|
|
||||||
pdr->y = pdr->y / (4096/gdispGGetHeight(m->display));
|
|
||||||
break;
|
|
||||||
case GDISP_ROTATE_90:
|
|
||||||
case GDISP_ROTATE_270:
|
|
||||||
pdr->x = gdispGGetHeight(m->display) - pdr->x / (4096/gdispGGetHeight(m->display));
|
|
||||||
pdr->y = pdr->y / (4096/gdispGGetWidth(m->display));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
pdr->x = gdispGGetWidth(m->display) - pdr->x / (4096/gdispGGetWidth(m->display));
|
|
||||||
pdr->y = pdr->y / (4096/gdispGGetHeight(m->display));
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
@ -86,11 +76,7 @@ static bool_t ft5336ReadXYZ(GMouse* m, GMouseReading* pdr)
|
||||||
const GMouseVMT const GMOUSE_DRIVER_VMT[1] = {{
|
const GMouseVMT const GMOUSE_DRIVER_VMT[1] = {{
|
||||||
{
|
{
|
||||||
GDRIVER_TYPE_TOUCH,
|
GDRIVER_TYPE_TOUCH,
|
||||||
#if GMOUSE_FT5336_SELF_CALIBRATE
|
GMOUSE_VFLG_TOUCH | GMOUSE_VFLG_ONLY_DOWN | GMOUSE_VFLG_POORUPDOWN,
|
||||||
GMOUSE_VFLG_TOUCH | GMOUSE_VFLG_ONLY_DOWN | GMOUSE_VFLG_POORUPDOWN,
|
|
||||||
#else
|
|
||||||
GMOUSE_VFLG_TOUCH | GMOUSE_VFLG_ONLY_DOWN | GMOUSE_VFLG_POORUPDOWN | GMOUSE_VFLG_CALIBRATE | GMOUSE_VFLG_CAL_TEST,
|
|
||||||
#endif
|
|
||||||
sizeof(GMouse) + GMOUSE_FT5336_BOARD_DATA_SIZE,
|
sizeof(GMouse) + GMOUSE_FT5336_BOARD_DATA_SIZE,
|
||||||
_gmouseInitDriver,
|
_gmouseInitDriver,
|
||||||
_gmousePostInitDriver,
|
_gmousePostInitDriver,
|
||||||
|
|
Loading…
Add table
Reference in a new issue