//------------------------------------------------- // Shenzhen TOPWAY Technology Co.,Ltd. // System: NXP LPC11U23 (12MHz) // LCD Module: LMT050DICFWD-NNC CTP // Driver/Controller: GT911 // Interface: I2C interface // By: ChenQiang // Rev 01: 2018-06-25 // - single touch // - new //------------------------------------------------- // // CONFIG REGISTER Structure... // typedef struct _GT911_CONFIG { uint8_t GTVersion; // version 0x42 uint8_t xmax[2]; // x maximal value 800 uint8_t ymax[2]; // y maximal value 480 uint8_t MaxTNum; // maximal number of touch uint8_t GTMode; // way of interrupt }GT911_CONFIG; #define GTP_Head_LEN sizeof(GT911_CONFIG) #define GTP_CFG_LEN 184 // the size of config Table #define TOUCH_CONFIG_DATA_LENGTH (GTP_CFG_LEN + 2) // includes the checksum = 186 #define GT_CFGS_REG 0x8047 // the address of config register // // GT911 READ REGISTER // #define FALSE 0 #define TRUE 1 #define GT_PID_REG 0X8140 // the address of pid register #define GTP_READ_COOR_ADDR 0x814E // the address of coordinate #define GTP_MAX_TOUCH 1 // the maximal number of touch = 1 #define GTP_Version 0x43 // set version as C #define GTP_INT_WAY 0x0E // 0x0C:rising edge 0x0D:falling edge 0x0E:low level 0x0F:high level #define LCD_XSIZE 4096 // x resolution #define LCD_YSIZE 4096 // y resolution #define TOUCH_STATUS_SIZE 1 // the bytes of touching status #define POINT_DATA_SIZE 8 // the bytes of points information // // default config data // #define CREATE_DEFAULT_CONFIG \ {\ GTP_Version,\ (uint8_t)LCD_XSIZE,\ (uint8_t)(LCD_XSIZE>>8),\ (uint8_t)LCD_YSIZE,\ (uint8_t)(LCD_YSIZE>>8),\ GTP_MAX_TOUCH,\ GTP_INT_WAY,\ } // // I2C DEFINE // #define GT_ADR 0xBA // for alternative address 0xBA set INT to low while asserting /RST #define I2C_ERROR (-1) #define I2C_LAST FALSE // SendAck: no more bytes to send #define I2C_MORE TRUE // SendAck: more bytes to send unsigned char I2C_DEV_ADR; // device address // // // //********************************************************************** // * // SUPPORT ROUTINES * // * // * // __delay_us * // * // * //********************************************************************** // int __delay_us(unsigned int Time) { volatile unsigned int i = 0; Time <<= 2; while (i < Time) { i++; // 2ns i--; // 2ns i++; // 2ns i--; // 2ns i++; // 2ns => 14ns } return 0; } // // //********************************************************************** // * // SEND START CONDITION * // * // - Data high -> low while clock high * // * //********************************************************************** // void i2c_Start(void) { } // //********************************************************************** // * // SEND STOP CONDITION * // * // - Data low -> high while clock high * // * //********************************************************************** // void i2c_Stop(void) { } // // //********************************************************************** // * // SEND BYTE * // * // - Send one byte to slave * // - Returns true on error * // * //********************************************************************** // unsigned char i2c_SendByte(unsigned char byte) { return FALSE; } // // //********************************************************************** // * // I2C SEND ADDRESS * // * // - Sends a 7 Bit device address and data direction to the slave * // - 7-bit address (upper 7 Bit used, Bit 0 must be 0) * // - Direction (FALSE = write) * // - Returns I2C_ERROR, ack or ~ack * // * // * //********************************************************************** // unsigned char i2c_SendAddress(unsigned char address, unsigned char rw) { return i2c_SendByte(address | (rw?1:0)); } // // //********************************************************************** // * // I2C READ BYTE * // * // - Reads one byte from the slave * // - Returns the byte or I2C_ERROR if a bus error * // * //********************************************************************** // int i2c_ReadByte(void) { return 0; } // // //********************************************************************** // * // I2C CHECK ACKNOWLEDGE * // * // - Checks for an acknowledge * // - Returns ack or ~ack, or ERROR (-1) if a bus error occured * // * //********************************************************************** // signed char i2c_ReadAcknowledge(void) { return 0; } //********************************************************************** // * // I2C OPEN * // * // - Opens communication with a device at address * // - Mode indicates I2C_READ (1) or I2C_WRITE (0) * // - Returns TRUE if device address is not acknowledged * // * //********************************************************************** // unsigned char i2c_Open(unsigned char address, unsigned char mode) { i2c_Start(); i2c_SendAddress(address, mode); if (i2c_ReadAcknowledge()) { return TRUE; // No ACK } return FALSE; // ACK OK } // // //********************************************************************** // * // I2C PUT BYTE * // * // - Sends a byte to the slave and acknowledges the transfer * // - Returns I2C_ERROR, ack or ~ack * // * //********************************************************************** // signed char i2c_PutByte(unsigned char data) { if (i2c_SendByte(data)) { return I2C_ERROR; } return i2c_ReadAcknowledge(); // returns ack or ~ack } // // //********************************************************************** // * // I2C GET BYTE * // * // - Get a byte from the slave and acknowledges the transfer * // - Returns true on I2C_ERROR or byte * // * //********************************************************************** // int i2c_GetByte(unsigned char more) { int byte; if((byte = i2c_ReadByte()) == I2C_ERROR) { return I2C_ERROR; } i2c_SendAcknowledge(more); return byte; } // //*************************************************************// // // // GT911_WR_Reg() // // // // - Write to multiple GT911 Registers // // - Author: Chen Qiang // // // // // //*************************************************************// // uint8_t GT911_WR_Reg(uint16_t reg, uint8_t *buf, uint8_t len) { uint32_t i; uint8_t ret = 0; if (len > 0) { I2C_DEV_ADR = GT_ADR; if (i2c_Open(I2C_DEV_ADR, 0) == 0) // opens communication with a device at address { if (i2c_PutByte(reg >> 8) == 0) // set register H-address { if (i2c_PutByte(reg & 0xFF) == 0) // set register L-address { for (i = 0; i < len; i++) { i2c_PutByte(*buf++); // write datas } } } } } i2c_Stop(); // send stop condition return ret; } // // //*************************************************************// // // // GT911_RD_Reg() // // // // - Read from multiple GT911 Registers // // - Author: Chen Qiang // // // // // //*************************************************************// // void GT911_RD_Reg(uint16_t reg, uint8_t *buf, uint8_t len) { uint32_t i; if (len > 0) { I2C_DEV_ADR = GT_ADR; if (i2c_Open(I2C_DEV_ADR, 0) == 0) // opens communication with a device at address { if (i2c_PutByte(reg >> 8) == 0) // set register H-address { if (i2c_PutByte(reg & 0xFF) == 0) // set register L-address { i2c_Stop(); // send stop condition __delay_us(25); if (i2c_Open(I2C_DEV_ADR, 1) == 0) // opens communication with a device at address { for (i = 0; i < len; i++) { if (i < (len - 1)) { *buf++ = i2c_GetByte(I2C_MORE); // read datas } else { *buf = i2c_GetByte(I2C_LAST); // read datas } } } } } } } i2c_Stop(); // send stop condition } // // // // //*************************************************************// // // // Support Routines // // // // - memcpy8 // // - memset8 // // - memcmp8 // // // // // //*************************************************************// // void memcpy8(char * pdst, char * psrc, unsigned char count) { unsigned char i = 0; while (i < count) { *pdst++ = *psrc++; i++; } } // // void memset8(char * pdst, char val, unsigned char count) { unsigned char i = 0; while (i < count) { *pdst++ = val; i++; } } // // bool memcmp8(char * psrc1, char * psrc2, unsigned char count) { unsigned char i = 0; bool Result = true; // Prsset both are the same while (i < count) { if (*psrc1++ != *psrc2++) { Result = false; // Return false if the not the same! break; } i++; } return Result; } // static Variables... const static GT911_CONFIG Defaultcfg = CREATE_DEFAULT_CONFIG; // // //***************************************************************// // // // GT911_Delayms() // // // // - Wait some ms // // - Author: Axel // // // // // //***************************************************************// // void GT911_Delayms(uint32_t _delaytime) { } // // //***************************************************************// // // // GT911_Update() // // - update the config register // // - Author: Chen Qiang // // // // // //***************************************************************// // void GT911_Update(void) { uint8_t i=0; uint8_t dest_configdata[GTP_CFG_LEN + 2]; // config table to be written uint8_t check_sum = 0; GT911_RD_Reg(GT_CFGS_REG,dest_configdata,GTP_CFG_LEN); // reading the config data memcpy(dest_configdata+1, ((char*)&Defaultcfg)+1, GTP_Head_LEN-1); // getting old config data if(Defaultcfg.GTVersion=3) { break; } }while((ReadConfig[0] != 9) || (ReadConfig[1] != 1) || (ReadConfig[2] != 1)); if(retry_count<3) { Valid_GT911 = true; // GT911 is valid } GT911_Delayms(10); while(1) // loop until CFG Data are correctly loaded to GT911... { GT911_Delayms(10); GT911_RD_Reg(GT_CFGS_REG, ReadConfig, GTP_Head_LEN); if (memcmp8((char*) &ReadConfig[1], ((char*) &Defaultcfg) + 1, GTP_Head_LEN - 1)) // comparing the current config data with default { break; } else { GT911_Update(); // update config data } } } // // // //********************************************************// // // // GT911_GetXY() // // // // - Author: Chen Qiang // // // // // //********************************************************// // uint16_t GT911_GetXY(uint16_t* px, uint16_t* py) { uint8_t point_data[TOUCH_STATUS_SIZE + (POINT_DATA_SIZE * GTP_MAX_TOUCH) + 1]; uint8_t touch_num = 0; uint8_t * coor_data = 0; GT911_RD_Reg(GTP_READ_COOR_ADDR, point_data, 6); if ((point_data[0] & 0x80) == 0) // checking if data are valid... { return 0; // no valid data found } touch_num = point_data[0] & 0x0f; // getting the quantity of point if ((touch_num > GTP_MAX_TOUCH) || (touch_num == 0)) // checking if touch point quantity is valid... { point_data[0] = 0; GT911_WR_Reg(GTP_READ_COOR_ADDR, point_data, 1); // resetting the touch status g_u8PEN_DOWN = FALSE; // marking pen release return 0; } coor_data = &point_data[1]; // getting the coordinate *px = (coor_data[1] | (coor_data[2] << 8)); // x *py = (coor_data[3] | (coor_data[4] << 8)); // y if (!(*px) && !(*py)) { return 0; } point_data[0] = 0; GT911_WR_Reg(GTP_READ_COOR_ADDR, point_data, 1); // resetting the touch status return 1; } // //*************************************************************// // // // M A I N // // // // - init GT911 cap touch controller // // - getting touch coordinates // // - reporting coordinates // //*************************************************************// // int main(void) // { // unsigned short int x=0, y=0; GT911_Init(); // init GT911 cap touch controller g_u32X_VALUE = 0xFFFFFFFF; // g_u32Y_VALUE = 0xFFFFFFFF; // GT911_Delayms(800); // waitting 800ms while(1) // main Loop... { if (TP_IRQ_DOWN() == TRUE) // detecting the signal of interrupt { if (GT911_GetXY(&x, &y)) // reading data successful { g_u8PEN_DOWN = TRUE; // marking pen down g_u32X_VALUE = x; // save x position g_u32Y_VALUE = y; // save y position } } else { g_u8PEN_DOWN = FALSE; // marking pen release g_u32X_VALUE = 0xFFFFFFFF; g_u32Y_VALUE = 0xFFFFFFFF; } } }