EmbedEd
/
mbed_theremin
xypad theremin for LPC1768
touch.cpp
- Committer:
- exopiped
- Date:
- 2016-03-14
- Revision:
- 1:aa184d2eb2e3
- Parent:
- 0:8ee38453bad9
- Child:
- 2:c5eeaf1c8e69
File content as of revision 1:aa184d2eb2e3:
/* * touch.cpp -- touch screen monitor */ #include "mbed.h" #include "debug.h" #include "touch.h" #define NIL (-1) /* * Connecting the touch screen * STMPE610 MODE pin is tied low for I2C interface * STMPE610 A0 pin tied low for I2C address 0x41 * (0x82 when shifted left 1) * STMPE610 A0 pin tied high for I2C address 0x44 * (0x88 when shifted left 1) * * I2C works on board pins 9 and 10. (SDA, SDL) * ( STMPE610 pins SDAT and SCLK ) * * Setting up the touch screen * * Disable Touch Screen and A/D clock -- SYS_CTRL2 * Set TSC_OFF bit high, ADC_OFF bit high * * ConfigureTouch Screen -- TSCFG register * Set up for 4 sample averaging * Touch detect delay of 1 msec * Settling time of 1 msec * * Touchscreen Window -- WDW_TR_X, WDW_TR_Y, WDW_BL_X, WDW_BLY * Set up for full screen ( default condition ) * */ typedef enum {TOUCH_NOTOUCH,TOUCH_DEBOUNCE,NOTOUCH_DEBOUNCE,TOUCH_PRESENT} TOUCH_STATE; #define TSC_ADDR 0x82 // (i2c address for touchscreen)<<1 // CHIP_ID register #define CHIP_ID 0x00 // 16 bit register // ID_VER register #define ID_VER 0x02 // 8 bit register // SYS_CTRL1 Reset control register #define SYS_CTRL1 0x03 #define SOFT_RESET 0x02 // SYS_CTRL2 clock control register #define SYS_CTRL2 0x04 #define ADC_OFF 0x01 #define TSC_OFF 0x02 #define GPIO_OFF 0x04 // ADC_CTRL registers #define ADC_CTRL1 0x20 #define ADC_CTRL2 0x21 // Interrupt control, enable and status registers #define INT_CTRL 0x09 #define INT_EN 0x0A #define INT_STA 0x0B // TSC_CTRL touchscreen control register #define TSC_CTRL 0x40 #define TSC_TOUCH_DET 0x80 // 1 when touch detected else 0 #define TSC_TRACK_MASK 0x70 // 0 => no window tracking #define TSC_OP_MOD_MASK 0x0E // 0 => XYZ acquisition #define TSC_EN_MASK 0x01 // enable touchscreen // TSC_CFG touchscreen config register #define TSC_CFG 0x41 #define TSC_AVG4 0x80 #define TSC_DLY_1MS 0x20 #define TSC_STL_1MS 0x03 #define TSC_I_DRIVE 0x58 #define MAMP_50 0x01 // FIFO_TH touchscreen fifo threshold register #define FIFO_TH 0x4A // TSC_DATA_X X data register #define TSC_DATA_X 0x4D // TSC_DATA_Y Y data register #define TSC_DATA_Y 0x4F // FIFO_STA touchscreen fifo control-status register #define FIFO_STA 0x4B #define FIFO_OFLOW 0x80 #define FIFO_FULL 0x40 #define FIFO_EMPTY 0x20 #define FIFO_TRGD 0x10 #define FIFO_RESET 0x01 // TSC_DATA touchscreen data register #define TSC_DATA 0xD7 // GPIO_AF -- GPIO Alternate FunctionRegister #define GPIO_AF 0x17 DigitalOut led1(LED1); DigitalOut led4(LED4); i2c_t touch_ctrl; // i2c interface struct for touch screen static int touch_present(void); static void touch_reset(void); static void touch_compute_params(void); static char tsc_reset[2]={SYS_CTRL1, SOFT_RESET}; static char clox_on[2]={SYS_CTRL2,0x00}; static char adc_ctrl1[2]={ADC_CTRL1,0x49}; static char adc_ctrl2[2]={ADC_CTRL2,0x01}; static char gpio_af[2]={GPIO_AF,0}; static char fifo_clear[2]={FIFO_STA,0x01}; static char fifo_operate[2]={FIFO_STA,0x00}; static char touch_int_en[2]={INT_EN,0x02};//enable FIFO_TH int static char clr_intrupts[2]={INT_STA,0xFF}; static char ena_intrupt[2]={INT_CTRL,0x02}; static char tsc_cfg[2]={TSC_CFG,( TSC_AVG4 | TSC_DLY_1MS | TSC_STL_1MS )}; static char tsc_enable[2]={TSC_CTRL,3}; static char tsc_ctrl=TSC_CTRL; static char tsc_i_drive[2]={TSC_I_DRIVE,MAMP_50}; static char fifo_th[2]={FIFO_TH,1}; static char fifo_ctrl_sta=FIFO_STA; static char tsc_data=TSC_DATA; static int touch_audio_freq = 1000; static int touch_audio_amplitude = 0; static char touch_status=0; // result of reading TSC_CTR static char fifo_status=0; // result of reading FIFO_CTRL_STA short touch_x,touch_y; // used by state machine that debounces touch detection TOUCH_STATE touch_state=TOUCH_NOTOUCH; #define GOOD_TOUCH_COUNT 4 #define NO_TOUCH_COUNT 4 bool touch_init(void) { touch_reset(); touch_state = TOUCH_NOTOUCH; return true; } void touch_reset(void) { char chipid[2]; i2c_init(&touch_ctrl,p28,p27); i2c_frequency(&touch_ctrl,100000); wait_ms(1); // read chip id i2c_write(&touch_ctrl,TSC_ADDR,CHIP_ID,2,0); i2c_read(&touch_ctrl,TSC_ADDR,chipid,2,1); wait_ms(1); // reset touch screen chip i2c_write(&touch_ctrl,TSC_ADDR,tsc_reset,2,1); wait_ms(5); i2c_write(&touch_ctrl,TSC_ADDR,tsc_i_drive,2,1); wait_ms(1); // turn on ADC and TSC clocks i2c_write(&touch_ctrl,TSC_ADDR,clox_on,2,1); wait_ms(3); // enable touch interrupt i2c_write(&touch_ctrl,TSC_ADDR,touch_int_en,2,1); wait_ms(1); // 80 clock cycles for ADC conv, 12 bit ADC, internal ref i2c_write(&touch_ctrl,TSC_ADDR,adc_ctrl1,2,1); wait_ms(2); // ADC clock = 3.25 MHz i2c_write(&touch_ctrl,TSC_ADDR,adc_ctrl2,2,1); wait_ms(1); // 4 sample averaging and 1ms delays i2c_write(&touch_ctrl,TSC_ADDR,tsc_cfg,2,1); wait_ms(1); // gpio alt function register to 0 i2c_write(&touch_ctrl,TSC_ADDR,gpio_af,2,1); wait_ms(1); // FIFO threshold not zero i2c_write(&touch_ctrl,TSC_ADDR,fifo_th,2,1); wait_ms(1); // FIFO Reset i2c_write(&touch_ctrl,TSC_ADDR,fifo_clear,2,1); wait_ms(1); // FIFO out of reset i2c_write(&touch_ctrl,TSC_ADDR,fifo_operate,2,1); wait_ms(1); // enable touchscreen, no window tracking, x,y mode i2c_write(&touch_ctrl,TSC_ADDR,tsc_enable,2,1); wait_ms(1); i2c_write(&touch_ctrl,TSC_ADDR,clr_intrupts,2,1); wait_ms(1); i2c_write(&touch_ctrl,TSC_ADDR,ena_intrupt,2,1); wait_ms(1); } bool touch_debounce(void) { static int debounce_count=0; int tret; tret=touch_present(); switch (touch_state) { case TOUCH_NOTOUCH: if (tret>0) { debounce_count=0; touch_state = TOUCH_DEBOUNCE; } break; case TOUCH_DEBOUNCE: if (tret>0) { if (++debounce_count > GOOD_TOUCH_COUNT) { touch_state = TOUCH_PRESENT; led1=1; } } else if(tret == 0) { touch_state = TOUCH_NOTOUCH; } break; case NOTOUCH_DEBOUNCE: if(tret>0) { touch_state = TOUCH_PRESENT; } else if(tret== 0) { if(++debounce_count > NO_TOUCH_COUNT) { debounce_count=0; touch_state=TOUCH_NOTOUCH; } } break; case TOUCH_PRESENT: if (tret>0) { touch_compute_params(); } else if(tret==0) { debounce_count=0; touch_state=NOTOUCH_DEBOUNCE; } break; } return ((touch_state==TOUCH_PRESENT) || (touch_state==NOTOUCH_DEBOUNCE)); } int touch_frequency(void) { return touch_audio_freq; } int touch_amplitude(void) { return touch_audio_amplitude; } void touch_compute_params(void) { if(0>touch_get_xy(&touch_x,&touch_y)) return; if((touch_y>0x3F) && (touch_y!=0xFFF)) { touch_audio_freq = (TOUCH_MIN_FREQUENCY + (TOUCH_MAX_FREQUENCY - TOUCH_MIN_FREQUENCY) * touch_y)>>12; } if((touch_x > 0x3F) && (touch_x != 0xFFF)) { touch_audio_amplitude = (TOUCH_MAX_AMPLITUDE*touch_x)>>12; } } /* * return 1 if touch present, 0 if touch absent, and -1 * if there was an i2c error */ int touch_present(void) { // <<<<< i2c_init(&touch_ctrl,p28,p27); // sync i2c routines // <<<<< i2c_frequency(&touch_ctrl,100000); // 100kHz clock i2c_write(&touch_ctrl,TSC_ADDR,&tsc_ctrl,1,0); i2c_read(&touch_ctrl,TSC_ADDR,&touch_status,1,1); if ((touch_status & TSC_EN_MASK)==0) { // i2c error led4=1; // disables screen touch_reset(); // re-init fixes return -1; } else if ((touch_status & TSC_TOUCH_DET)>0) { return 1; } return 0; } int touch_get_xy(short *x,short *y) { unsigned char packed_xy[3]; if(i2c_write(&touch_ctrl,TSC_ADDR,&fifo_ctrl_sta,1,0)<0) return NIL; if(i2c_read(&touch_ctrl,TSC_ADDR,&fifo_status,1,1)<0) return NIL; while ((fifo_status & FIFO_EMPTY)!=FIFO_EMPTY ) { if (i2c_write(&touch_ctrl,TSC_ADDR,&tsc_data,1,0) < 0) return NIL; if(i2c_read(&touch_ctrl,TSC_ADDR,(char *)packed_xy,3,1)<0) return NIL; if(i2c_write(&touch_ctrl,TSC_ADDR,&fifo_ctrl_sta,1,0)<0) return NIL; if(i2c_read(&touch_ctrl,TSC_ADDR,&fifo_status,1,1)<0) return NIL; } if(i2c_write(&touch_ctrl,TSC_ADDR,clr_intrupts,2,1)<0) return NIL; *x = (short)(packed_xy[0]<<4) | (short)((packed_xy[1] & 0xF0)>>4); *y = 0xFFF -((short)((packed_xy[1] & 0x0F)<<8) | (short)(packed_xy[2])); // 0xFFF or 0x000 is some kind of glitch if (*x==0xFFF && *y==0xFFF) return NIL; if (*x==0 && *y==0) return NIL; debug_hexshort(*x); debug_putch(','); debug_hexshort(*y); debug_crlf(); return 0; }