From 940eda4cd4aec6389cd260b400d866830ba1dcd8 Mon Sep 17 00:00:00 2001 From: Joel Bodenmann Date: Wed, 22 Jul 2015 21:11:28 +0200 Subject: [PATCH] Adding first version of STM32F7 discovery touch driver --- boards/base/STM32F746-Discovery/board.mk | 3 +- .../gmouse_lld_FT5336_board.h | 190 ++---------------- boards/base/STM32F746-Discovery/stm32f7_i2c.c | 164 +++++++++++++++ boards/base/STM32F746-Discovery/stm32f7_i2c.h | 14 ++ demos/modules/gwin/slider/gfxconf.h | 1 + .../ginput/touch/FT5336/gmouse_lld_FT5336.c | 56 ++---- 6 files changed, 222 insertions(+), 206 deletions(-) create mode 100644 boards/base/STM32F746-Discovery/stm32f7_i2c.c create mode 100644 boards/base/STM32F746-Discovery/stm32f7_i2c.h diff --git a/boards/base/STM32F746-Discovery/board.mk b/boards/base/STM32F746-Discovery/board.mk index 864f2220..9386fae0 100644 --- a/boards/base/STM32F746-Discovery/board.mk +++ b/boards/base/STM32F746-Discovery/board.mk @@ -18,7 +18,8 @@ ifeq ($(OPT_OS),raw32) 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_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 SRCFLAGS+= -std=c99 GFXINC += $(CMSIS)/Device/ST/STM32F7xx/Include \ diff --git a/boards/base/STM32F746-Discovery/gmouse_lld_FT5336_board.h b/boards/base/STM32F746-Discovery/gmouse_lld_FT5336_board.h index bf523212..8031eca5 100644 --- a/boards/base/STM32F746-Discovery/gmouse_lld_FT5336_board.h +++ b/boards/base/STM32F746-Discovery/gmouse_lld_FT5336_board.h @@ -9,6 +9,7 @@ #define _GINPUT_LLD_MOUSE_BOARD_H #include "stm32f7xx.h" +#include "stm32f7_i2c.h" // Resolution and Accuracy Settings #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 #define GMOUSE_FT5336_BOARD_DATA_SIZE 0 -// Set this to TRUE if you want self-calibration. -// NOTE: This is not as accurate as real calibration. -// 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 +// The FT5336 I2C slave address (including the R/W bit) +#define FT5336_SLAVE_ADDR 0x70 static bool_t init_board(GMouse* m, unsigned instance) { @@ -36,52 +31,23 @@ static bool_t init_board(GMouse* m, unsigned instance) (void)instance; // I2C3_SCL GPIOH7, alternate, opendrain, highspeed - RCC->AHB1ENR |= RCC_AHB1ENR_GPIOBEN; // Enable clock for - GPIOB->MODER |= GPIO_MODER_MODER7_1; // Alternate function - GPIOB->OTYPER |= GPIO_OTYPER_OT_7; // OpenDrain - GPIOB->PUPDR |= GPIO_PUPDR_PUPDR7_0; // PullUp - GPIOB->OSPEEDR |= GPIO_OSPEEDER_OSPEEDR7; // HighSpeed - GPIOB->AFR[0] |= (0b0100 << 4*0); // AF4 + RCC->AHB1ENR |= RCC_AHB1ENR_GPIOHEN; // Enable clock for + GPIOH->MODER |= GPIO_MODER_MODER7_1; // Alternate function + GPIOH->OTYPER |= GPIO_OTYPER_OT_7; // OpenDrain + GPIOH->OSPEEDR &= ~GPIO_OSPEEDER_OSPEEDR7; // LowSpeed + GPIOH->AFR[0] |= (0b0100 << 4*7); // AF4 // I2C3_SDA GPIOH8, alternate, opendrain, highspeed - RCC->AHB1ENR |= RCC_AHB1ENR_GPIOBEN; // Enable clock - GPIOB->MODER |= GPIO_MODER_MODER8_1; // Alternate function - GPIOB->OTYPER |= GPIO_OTYPER_OT_8; // OpenDrain - GPIOB->PUPDR |= GPIO_PUPDR_PUPDR8_0; // PullUp - GPIOB->OSPEEDR |= GPIO_OSPEEDER_OSPEEDR8; // HighSpeed - GPIOB->AFR[1] |= (0b0100 << 4*0); // AF4 + RCC->AHB1ENR |= RCC_AHB1ENR_GPIOHEN; // Enable clock + GPIOH->MODER |= GPIO_MODER_MODER8_1; // Alternate function + GPIOH->OTYPER |= GPIO_OTYPER_OT_8; // OpenDrain + GPIOH->OSPEEDR &= ~GPIO_OSPEEDER_OSPEEDR8; // LowSpeed + GPIOH->AFR[1] |= (0b0100 << 4*0); // AF4 - // Enable I2C3 peripheral clock - RCC->APB1ENR |= RCC_APB1ENR_I2C3EN; - - // 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; + // Initialize the I2C3 peripheral + if (!(i2cInit(I2C3))) { + return FALSE; + } return TRUE; } @@ -90,137 +56,21 @@ static void write_reg(GMouse* m, uint8_t reg, uint8_t val) { (void)m; - // 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 - 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; + i2cWriteReg(I2C3, FT5336_SLAVE_ADDR, reg, val); } static uint8_t read_byte(GMouse* m, uint8_t reg) { (void)m; - uint8_t ret = 0x00; - - // 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; + return i2cReadByte(I2C3, FT5336_SLAVE_ADDR, reg); } static uint16_t read_word(GMouse* m, uint8_t reg) { (void)m; - uint16_t ret = 0x00; - - // 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; + return i2cReadWord(I2C3, FT5336_SLAVE_ADDR, reg); } #endif /* _GINPUT_LLD_MOUSE_BOARD_H */ diff --git a/boards/base/STM32F746-Discovery/stm32f7_i2c.c b/boards/base/STM32F746-Discovery/stm32f7_i2c.c new file mode 100644 index 00000000..b0fa8163 --- /dev/null +++ b/boards/base/STM32F746-Discovery/stm32f7_i2c.c @@ -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)); +} diff --git a/boards/base/STM32F746-Discovery/stm32f7_i2c.h b/boards/base/STM32F746-Discovery/stm32f7_i2c.h new file mode 100644 index 00000000..625aeed8 --- /dev/null +++ b/boards/base/STM32F746-Discovery/stm32f7_i2c.h @@ -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); diff --git a/demos/modules/gwin/slider/gfxconf.h b/demos/modules/gwin/slider/gfxconf.h index 9d55d29f..ac2d04ee 100644 --- a/demos/modules/gwin/slider/gfxconf.h +++ b/demos/modules/gwin/slider/gfxconf.h @@ -50,6 +50,7 @@ #define GDISP_NEED_CIRCLE TRUE #define GDISP_NEED_TEXT TRUE #define GDISP_NEED_MULTITHREAD TRUE +#define GDISP_NEED_CONTROL TRUE /* GDISP fonts to include */ #define GDISP_INCLUDE_FONT_UI2 TRUE diff --git a/drivers/ginput/touch/FT5336/gmouse_lld_FT5336.c b/drivers/ginput/touch/FT5336/gmouse_lld_FT5336.c index 70a3cdb9..a55bef65 100644 --- a/drivers/ginput/touch/FT5336/gmouse_lld_FT5336.c +++ b/drivers/ginput/touch/FT5336/gmouse_lld_FT5336.c @@ -20,10 +20,23 @@ static bool_t ft5336Init(GMouse* m, unsigned driverinstance) { + // Initialize the board stuff if (!init_board(m, driverinstance)) { 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) // Valid touching detect threshold 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) write_reg(m, FT5336_PERIODMONITOR_REG, 0x28); - +*/ return TRUE; } @@ -47,37 +60,14 @@ static bool_t ft5336ReadXYZ(GMouse* m, GMouseReading* pdr) { // Assume not touched. pdr->buttons = 0; - pdr->z = 0; + pdr->z = 0; - // Only take a reading if we are touched. - if ((read_byte(m, FT5336_TD_STAT_REG) & 0x07)) { - - /* Get the X, Y, Z values */ - pdr->x = (coord_t)(read_word(m, FT5336_P1_XH_REG) & 0x0FFF); - pdr->y = (coord_t)(read_word(m, FT5336_P1_YH_REG) & 0xFFFF); + // Only take a reading if exactly one touch contact point + if (read_byte(m, FT5336_TD_STAT_REG) == 1) { + // Get and return X, Y an Z values + pdr->y = (coord_t)(read_word(m, FT5336_P1_XH_REG) & 0x0FFF); + pdr->x = (coord_t)(read_word(m, FT5336_P1_YH_REG) & 0x0FFF); 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; @@ -86,11 +76,7 @@ static bool_t ft5336ReadXYZ(GMouse* m, GMouseReading* pdr) const GMouseVMT const GMOUSE_DRIVER_VMT[1] = {{ { GDRIVER_TYPE_TOUCH, - #if GMOUSE_FT5336_SELF_CALIBRATE - 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 + GMOUSE_VFLG_TOUCH | GMOUSE_VFLG_ONLY_DOWN | GMOUSE_VFLG_POORUPDOWN, sizeof(GMouse) + GMOUSE_FT5336_BOARD_DATA_SIZE, _gmouseInitDriver, _gmousePostInitDriver,