Lcd companion boards support (VKLCD50RTA & VKLCD70RT)

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers Touch.cpp Source File

Touch.cpp

00001 #include "Touch.h"
00002 
00003 const touch_config_t  STMPE811_cfg = {
00004     "STMPE811", LCD_VDC5_CH0_PANEL, RESISTIVE ,
00005     {I_2_C , TPIIC_SDA, TPIIC_SCL, NC, NC, NC, NC, 100000},
00006     {INT_ON_EDGE , FALLING_OR_ACTIVE_LO , TPIRQ_PIN}
00007 };
00008 
00009 bool    Touch::new_data;
00010 
00011 
00012 /**************************************************************************//**
00013  * @brief       Constructor of the Touch class
00014  * @param[in]   pointer to Config structure (touch_config_t)
00015 ******************************************************************************/
00016 //SPI(tp_cfg->interface.mosi, tp_cfg->interface.miso, tp_cfg->interface.sclk, tp_cfg->interface.ssel),
00017 Touch::Touch( const touch_config_t * tp_cfg ) : I2C(tp_cfg->interface.sda, tp_cfg->interface.scl), InterruptIn(tp_cfg->activity_irq.pin)
00018 {
00019     if(tp_cfg == NULL)
00020         touch_cfg = &STMPE811_cfg;
00021     else
00022         touch_cfg = tp_cfg;
00023 
00024     x = y = z = 0;    adc_x = adc_y = adc_z = 0;
00025     xyz_data = screen_data; adc_data = raw_data;
00026     last_xyz_idx = FIFO_DEPTH;
00027     new_data = false;
00028     calib.data.flag = 0;
00029 
00030 } /* End of constructor */
00031 
00032 
00033 /**************************************************************************//**
00034  * @brief       Touch controller initialization
00035  * @retval      error code
00036 ******************************************************************************/
00037 Touch::init_err_t  Touch::Init( void )
00038 {
00039     init_err_t  tp_err;
00040 
00041     if(touch_cfg->type  == RESISTIVE )
00042     {
00043         tp_err = Clb_Setup();
00044 
00045         if(tp_err != TOUCH_OK )
00046             return tp_err;
00047     }
00048 
00049     if(touch_cfg->interface.type  == I_2_C )
00050         I2C::frequency(touch_cfg->interface.freq);
00051     //else
00052         //SPI::frequency(touch_cfg->interface.freq);
00053 
00054     tp_err = Drv_Setup();
00055 
00056     if(tp_err != TOUCH_OK )
00057         return tp_err;
00058 
00059     if(touch_cfg->activity_irq.polarity == FALLING_OR_ACTIVE_LO )
00060     {
00061         rise(NULL);
00062         fall(&Irq_Alert);
00063     }
00064     else
00065     {
00066         rise(&Irq_Alert);
00067         fall(NULL);
00068     }
00069 
00070     if(tp_err == TOUCH_OK )
00071         enable_irq();
00072 
00073     return tp_err;
00074 } /* End of method Init() */
00075 
00076 
00077 /**************************************************************************//**
00078  * @brief       Set Calibration data
00079  * @retval      error code
00080 ******************************************************************************/
00081 Touch::init_err_t  Touch::Clb_Setup()
00082 {
00083     if(touch_cfg->name  == "STMPE811")
00084     {
00085         #ifndef __USE_DEFAULT_CALIBRATION_DATA__
00086             // extract calibration info from lcdpanel EEPROM
00087             char adr = 0;
00088 
00089             if( (touch_cfg->interface.sda == EEIIC_SDA) || (touch_cfg->interface.scl == EEIIC_SCL))
00090             {   // EEPROM is on the same I2C channel no need to initialize a new one !
00091                 if(I2C::write(EE_CALIB_DEVICE_ADDR, (const char *)&adr, 1, true) != 0)
00092                     return TOUCH_INIT_ERR ;
00093                 if(I2C::read(EE_CALIB_DEVICE_ADDR, (char*)calib.KX08, sizeof(calib.KX08)) != 0)
00094                     return TOUCH_INIT_ERR ;
00095             }
00096             else
00097             {
00098                 I2C clb_eeprom(EEIIC_SDA, EEIIC_SCL);
00099 
00100                 clb_eeprom.frequency(100000);
00101                 if(clb_eeprom.write(EE_CALIB_DEVICE_ADDR, (const char *)&adr, 1, true) != 0)
00102                     return TOUCH_INIT_ERR ;
00103                 if(clb_eeprom.read(EE_CALIB_DEVICE_ADDR, (char*)calib.KX08, sizeof(calib.KX08)) != 0)
00104                     return TOUCH_INIT_ERR ;
00105             }
00106         #endif
00107 
00108         if(calib.data.flag != 1)
00109         {   // load default calibration info
00110             unsigned char clb[] = {TPCALIBRATION_DATA};
00111             memcpy(calib.KX08, clb, sizeof(clb));
00112         }
00113 
00114         return TOUCH_OK ;
00115     }
00116     else
00117         return TOUCH_UNSUPP_ERR ;
00118 } /* End of method Clb_Setup() */
00119 
00120 
00121 /**************************************************************************//**
00122  * @brief       Set Touch Controller settings
00123  * @retval      error code
00124 ******************************************************************************/
00125 Touch::init_err_t  Touch::Drv_Setup()
00126 {
00127     if(touch_cfg->name  == "STMPE811")
00128     {
00129         unsigned char i, initdata[][2] = { INIT_DATA };
00130 
00131         for(i=0; i<(sizeof(initdata)>>1); i++)
00132         {
00133             if(initdata[i][0] == INT_CTRL)
00134             {   // reconfigure interrupt if needed
00135                 initdata[i][1] = 0x01;
00136                 initdata[i][1] |= (touch_cfg->activity_irq.trigger  == INT_ON_EDGE )? 0x02 : 0x00;
00137                 initdata[i][1] |= (touch_cfg->activity_irq.polarity == RISING_OR_ACTIVE_HI )? 0x04 : 0x00;
00138             }
00139 
00140             if ((I2C::write(STMPE811_DEVICE_ADDR, (const char *)&initdata[i][0], 2)) != 0)
00141                 return TOUCH_INIT_ERR ;
00142 
00143             while (I2C::write(STMPE811_DEVICE_ADDR, (const char *)initdata, 0) != 0);  // ACK polling
00144         }
00145 
00146         return TOUCH_OK ;
00147     }
00148     else
00149         return TOUCH_UNSUPP_ERR ;
00150 }
00151 
00152 
00153 /**************************************************************************//**
00154  * @brief       Get one sample of data
00155  * @param[in]   * raw   : pointer to ring buffer to store the samples
00156 ******************************************************************************/
00157 void Touch::Get_Data( unsigned long long * raw )
00158 {
00159     if(touch_cfg->name  == "STMPE811")
00160     {
00161         int idx = last_xyz_idx;
00162         unsigned char  i, packed_sample[16];
00163         unsigned short raw_x, raw_y;
00164         unsigned char  raw_z;
00165 
00166         i = TSC_DATA_FIFO;
00167         I2C::write(STMPE811_DEVICE_ADDR, (const char *)&i, 1, true);
00168         I2C::read(STMPE811_DEVICE_ADDR, (char *)packed_sample, sizeof(packed_sample));
00169         for(i=0; i<4; i++)
00170         {
00171             raw_x = (unsigned short)((packed_sample[(i*4)+0]<<4) | (packed_sample[(i*4)+1]>>4));
00172             raw_y = (unsigned short)(((0x0F & packed_sample[(i*4)+1])<<8) | packed_sample[(i*4)+2]);
00173             raw_z = packed_sample[(i*4)+3];
00174 
00175             idx = ((idx+1) < FIFO_DEPTH)? idx+1 : 0;
00176             raw[idx] = (unsigned long long)((raw_z<<32) + (raw_y<<16) + raw_x);
00177         }
00178     }
00179 } /* End of method Get_Data() */
00180 
00181 
00182 /**************************************************************************//**
00183  * @brief       Get all available samples of data
00184  * @param[in]   * raw   : pointer to ring buffer to store the samples
00185  * @retval                samples count
00186 ******************************************************************************/
00187 int Touch::Get_Fifo( unsigned long long * raw )
00188 {
00189     if(touch_cfg->name  == "STMPE811")
00190     {
00191       int idx = last_xyz_idx;
00192       unsigned char packets;
00193 
00194       packets = FIFO_SIZE;
00195       I2C::write(STMPE811_DEVICE_ADDR, (const char *)&packets, 1, true);
00196       packets = 0;
00197       I2C::read(STMPE811_DEVICE_ADDR, (char *)&packets, 1);
00198       if(packets)
00199       {
00200         unsigned char  packed_sample[FIFO_DEPTH*4];
00201         unsigned short raw_x, raw_y, i;
00202         unsigned char  raw_z;
00203 
00204         raw_z = TSC_DATA_FIFO;
00205         I2C::write(STMPE811_DEVICE_ADDR, (const char *)&raw_z, 1, true);
00206         I2C::read(STMPE811_DEVICE_ADDR, (char *)packed_sample, packets*4);
00207 
00208         for(i=0; i<packets; i++)
00209         {
00210           raw_x = (unsigned short)((packed_sample[(i*4)+0]<<4) | (packed_sample[(i*4)+1]>>4));
00211           raw_y = (unsigned short)(((0x0F & packed_sample[(i*4)+1])<<8) | packed_sample[(i*4)+2]);
00212           raw_z = packed_sample[(i*4)+3];
00213 
00214           idx = ((idx+1) < FIFO_DEPTH)? idx+1 : 0;
00215           raw[idx] = (raw_z<<32) + (raw_y<<16) + raw_x;
00216         }
00217 
00218         return packets;
00219       }
00220       return 0;
00221     }
00222     else
00223         return 0;
00224 } /* End of method Get_Fifo() */
00225 
00226 
00227 /**************************************************************************//**
00228  * @brief       Coordinates Transfer function
00229  * @param[in]   points      : number of samples which have to become meaningful
00230 ******************************************************************************/
00231 void Touch::Get_XYZ( int points)
00232 {
00233     if(touch_cfg->name  == "STMPE811")
00234     {
00235         int i, idx;
00236 
00237         for(i=0; i<points; i++)
00238         {
00239             idx = ((last_xyz_idx+1) < FIFO_DEPTH)? last_xyz_idx+1 : 0;
00240             screen_data[idx].axis.x = (signed short)(calib.data.KX1*((signed short)raw_data[idx].axis.x)+calib.data.KX2*((signed short)raw_data[idx].axis.y)+calib.data.KX3+0.5);
00241             screen_data[idx].axis.y = (signed short)(calib.data.KY1*((signed short)raw_data[idx].axis.x)+calib.data.KY2*((signed short)raw_data[idx].axis.y)+calib.data.KY3+0.5);
00242             //screen_data[idx].axis.z = 0;
00243             last_xyz_idx = idx;
00244             //printf("\r\n REC: idx-> %d", idx);
00245             //printf("\r\n TH: x-> %d, y-> %d, dots-> %d", screen_data[idx].axis.x, screen_data[idx].axis.y, idx);
00246         }
00247 
00248         x = screen_data[last_xyz_idx].axis.x; adc_x = raw_data[last_xyz_idx].axis.x;
00249         y = screen_data[last_xyz_idx].axis.y; adc_y = raw_data[last_xyz_idx].axis.y;
00250         //z = screen_data[last_xyz_idx].axis.z; adc_z = raw_data[last_xyz_idx].axis.z;
00251         //printf("\r\n TH: x-> %d, y-> %d, dots-> %d", x, y, last_xyz_idx);
00252 
00253     }
00254 } /* End of method Get_XYZ() */
00255 
00256 
00257 /**************************************************************************//**
00258  * @brief       IRQ interrupt handler : indicates "New Data available" which activates i2c data transfer in Handle_touch()
00259 ******************************************************************************/
00260 void Touch::Irq_Alert( void ) { new_data = true; } /* End of method Irq_Alert() */
00261 
00262 
00263 /**************************************************************************//**
00264  * @brief       Get index of the last sample in the ring buffer
00265  * @retval      idx
00266 ******************************************************************************/
00267 int Touch::Get_Last_Idx( void ) { return last_xyz_idx; }
00268 
00269 
00270 /**************************************************************************//**
00271  * @brief       Pull the new samples if new data is available
00272  * @param[in]   * pts               : pointer to a variable to put the count of the new samples
00273  * @retval      Status of the pen   (Stylus position up/down)
00274 ******************************************************************************/
00275 bool Touch::Handle_touch( unsigned char *pts )
00276 {
00277     static bool PenDown = false;
00278     unsigned char TP_IntStat = 0, rec[2];
00279     int dots = 0;
00280 
00281     *pts=0;
00282 
00283  if(new_data)
00284  {
00285     TP_IntStat = INT_STA;
00286     I2C::write(STMPE811_DEVICE_ADDR, (const char *)&TP_IntStat, 1, true);
00287     TP_IntStat = 0;
00288     I2C::read(STMPE811_DEVICE_ADDR, (char *)&TP_IntStat, 1);
00289 
00290     if(TP_IntStat & INT_FIFO_TH)
00291     {
00292         Get_Data(&raw_data[0].dot);
00293         Get_XYZ(4);
00294 
00295         *pts = 4;
00296 
00297         //Data = 1;
00298         //SET_TP_STATE(TP_FLAG_PEN_DATA_TH);
00299         //printf("\r\n TH: x-> %d, y-> %d", screen_data[3].axis.x, screen_data[3].axis.y);
00300     }
00301 
00302     if(TP_IntStat & INT_TOUCH_DET)
00303     {
00304         dots = Get_Fifo(&raw_data[0].dot);
00305         if(dots)
00306         {
00307             Get_XYZ(dots);
00308             //Data = 1;
00309             //CLR_TP_STATE(TP_FLAG_PEN_DATA_TH); //SET_TP_STATE(TP_FLAG_DATA_READY);
00310             //printf("\r\n Touch Sample: x-> %d, y-> %d", screen_data[v-1].axis.x, screen_data[v-1].axis.y);
00311         }
00312         *pts = dots;
00313 
00314         PenDown = (PenDown)? false : true;
00315     }
00316 
00317     if(TP_IntStat & INT_FIFO_OFLOW)
00318     {
00319         rec[0] = FIFO_STA;
00320         rec[1] = 0x01;      // Clear FIFO
00321         I2C::write(STMPE811_DEVICE_ADDR, (const char *)rec, 2);
00322 
00323         rec[1] = 0x00;      // Reset FIFO
00324         I2C::write(STMPE811_DEVICE_ADDR, (const char *)rec, 2);
00325     }
00326 
00327     rec[0] = INT_STA;
00328     rec[1] = TP_IntStat;
00329     I2C::write(STMPE811_DEVICE_ADDR, (const char *)rec, 2);
00330 
00331     new_data = false;
00332  }
00333 
00334   return PenDown;
00335 }
00336 
00337 /**************************************************************************//**
00338  * @brief       Destructor of the Touch class
00339 ******************************************************************************/
00340 Touch::~Touch( )
00341 {
00342     touch_cfg = NULL;
00343     xyz_data = NULL;
00344     adc_data = NULL;
00345 }
00346 
00347 /* End of file */
00348