drv_touch.c 7.2 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
/*
 * File      : drv_touch.c
 * This file is part of RT-Thread RTOS
 * COPYRIGHT (C) 2018 RT-Thread Develop Team
 *
 * The license and distribution terms for this file may be
 * found in the file LICENSE in this distribution or at
 * http://www.rt-thread.org/license/LICENSE
 *
 * Change Logs:
 * Date           Author       Notes
 * 2018-10-03     xuzhuoyi     first implementation.
 */

#include "drv_touch.h"
#include "drivers/i2c.h"

18 19 20 21
#ifdef PKG_USING_LITTLEVGL2RTT
#include "littlevgl2rtt.h"
#endif

22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99

#define TSC_I2C_ADDR    0x41            /* 7-bit I2C address                  */

static struct rt_i2c_bus_device *stmpe811_i2c_bus;


/**
  \fn          int32_t touch_readRegister (uint8_t reg, uint8_t *val)
  \brief       Read register value from Touchscreen controller
  \param[in]   reg    Register address
  \param[out]  val    Pointer where data will be read from register
  \returns
   - \b  0: function succeeded
   - \b -1: function failed
*/
static int32_t touch_read (uint8_t reg, uint8_t *val)
{
    struct rt_i2c_msg msgs[2];

    msgs[0].addr  = TSC_I2C_ADDR;
    msgs[0].flags = RT_I2C_WR;
    msgs[0].buf   = ®
    msgs[0].len   = 1;

    msgs[1].addr  = TSC_I2C_ADDR;
    msgs[1].flags = RT_I2C_RD;
    msgs[1].buf   = val;
    msgs[1].len   = 1;

    if (rt_i2c_transfer(stmpe811_i2c_bus, msgs, 2) == 2)
    {
        return RT_EOK;
    }
    else
    {
        return -RT_ERROR;
    }

}

/**
  \fn          int32_t touch_writeData (uint8_t reg, const uint8_t *val)
  \brief       Write value to Touchscreen controller register
  \param[in]   reg    Register address
  \param[in]   val    Pointer with data to write to register
  \returns
   - \b  0: function succeeded
   - \b -1: function failed
*/
static int32_t touch_write (uint8_t reg, uint8_t val)
{
    struct rt_i2c_msg msgs;
    rt_uint8_t buf[2] = {reg, val};

    msgs.addr  = TSC_I2C_ADDR;
    msgs.flags = RT_I2C_WR;
    msgs.buf   = buf;
    msgs.len   = 2;

    if (rt_i2c_transfer(stmpe811_i2c_bus, &msgs, 1) == 1)
    {
    return RT_EOK;
    }
    else
    {
    return -RT_ERROR;
    }

}


/**
  \fn          int32_t Touch_Initialize (void)
  \brief       Initialize touchscreen
  \returns
   - \b  0: function succeeded
   - \b -1: function failed
*/
100
static rt_err_t stmpe811_touch_init(rt_device_t dev)
101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137
{
    stmpe811_i2c_bus = rt_i2c_bus_device_find(STMPE811_I2CBUS_NAME);

//    ptrI2C->Initialize  (NULL);
//    ptrI2C->PowerControl(ARM_POWER_FULL);
//    ptrI2C->Control     (ARM_I2C_BUS_SPEED, ARM_I2C_BUS_SPEED_FAST);
//    ptrI2C->Control     (ARM_I2C_BUS_CLEAR, 0);

    touch_write(STMPE811_SYS_CTRL1,      0x02); /* Reset Touch-screen controller */
    rt_thread_mdelay(10);                              /* Wait 10ms                     */


    touch_write(STMPE811_SYS_CTRL2,      0x0C); /* Enable TSC and ADC            */
    touch_write(STMPE811_ADC_CTRL1,      0x68); /* Set sample time , 12-bit mode */
    rt_thread_mdelay(1);                               /* Wait 1ms                      */

    touch_write(STMPE811_ADC_CTRL2,      0x01); /* ADC frequency 3.25 MHz        */
    touch_write(STMPE811_TSC_CFG,        0xC2); /* Detect delay 10us,
                                                 Settle time 500us             */
    touch_write(STMPE811_FIFO_TH,        0x01); /* Threshold for FIFO            */
    touch_write(STMPE811_FIFO_STA,       0x01); /* FIFO reset                    */
    touch_write(STMPE811_FIFO_STA,       0x00); /* FIFO not reset                */
    touch_write(STMPE811_TSC_FRACTION_Z, 0x07); /* Fraction z                    */
    touch_write(STMPE811_TSC_I_DRIVE,    0x01); /* Drive 50 mA typical           */
    touch_write(STMPE811_GPIO_AF,        0x00); /* Pins are used for touchscreen */
    touch_write(STMPE811_TSC_CTRL,       0x01); /* Enable TSC                    */

    return 0;
}

/**
  \fn          int32_t Touch_Uninitialize (void)
  \brief       De-initialize touchscreen
  \returns
   - \b  0: function succeeded
   - \b -1: function failed
*/
138
int32_t touch_uninitialize (void) {
139 140 141 142 143 144 145 146 147 148 149 150
  touch_write(STMPE811_SYS_CTRL1, 0x02);  /* Reset Touch-screen controller    */
  return 0;
}

/**
  \fn          int32_t Touch_GetState (TOUCH_STATE *pState)
  \brief       Get touchscreen state
  \param[out]  pState  pointer to TOUCH_STATE structure
  \returns
   - \b  0: function succeeded
   - \b -1: function failed
*/
151
int32_t touch_get_state(struct touch_state *pState)
152
{
153 154 155 156
    uint8_t val;
    uint8_t num;
    uint8_t xyz[4];
    int32_t res;
157
    struct rt_i2c_msg msgs[2];
158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173

    /* Read touch status */
    res = touch_read(STMPE811_TSC_CTRL, &val);
    if (res < 0) return -1;
    pState->pressed = (val & (1 << 7)) ? 1 : 0;
  
    if (pState->pressed)
    {
        val = STMPE811_TSC_DATA;

        /* If FIFO overflow, discard all samples except the last one */
        res = touch_read(STMPE811_FIFO_SIZE, &num);
        if (res < 0 || num == 0) return -1;

        while (num--)
        {
174 175 176 177
            msgs[0].addr  = TSC_I2C_ADDR;
            msgs[0].flags = RT_I2C_WR;
            msgs[0].buf   = &val;
            msgs[0].len   = 1;
178

179
            //rt_i2c_transfer(stmpe811_i2c_bus, &msgs, 1);
180 181
          //ptrI2C->MasterTransmit (TSC_I2C_ADDR, &val, 1, true);
          //while (ptrI2C->GetStatus().busy);
182 183 184 185 186
            msgs[1].addr  = TSC_I2C_ADDR;
            msgs[1].flags = RT_I2C_RD;
            msgs[1].buf   = xyz;
            msgs[1].len   = 4;
            rt_i2c_transfer(stmpe811_i2c_bus, msgs, 2);
187 188 189 190 191 192 193 194
          //ptrI2C->MasterReceive (TSC_I2C_ADDR, xyz, 4, false);
          //while (ptrI2C->GetStatus().busy);
        }
        pState->x =  (int16_t)((xyz[0] << 4) | ((xyz[1] & 0xF0) >> 4));
        pState->y =  (int16_t) (xyz[2]       | ((xyz[1] & 0x0F) << 8));
    }
    else
    {
195
        /* Clear all data in FIFO */
196 197 198 199 200 201
        touch_write(STMPE811_FIFO_STA, 0x1);
        touch_write(STMPE811_FIFO_STA, 0x0);
    }

    return 0;
}
202 203 204

void touch_show_state()
{
205 206
    int16_t x;
    int16_t y;
207 208
    struct touch_state ts;
    touch_get_state(&ts);
209 210
    x = (3706 - ts.x) / 14;
    y = (-461 + ts.y) / 10.5;
211
    rt_kprintf("[drv_touch] touch_show_state, x: %d, y: %d, pressed: %d, padding: %d\n", ts.x , ts.y, ts.pressed, ts.padding);
212
    rt_kprintf("[drv_touch] touch_show_state, phy x: %d, phy y: %d\n", x , y);
213 214 215
}
MSH_CMD_EXPORT(touch_show_state, show screen coordinate in touching);

216
static void touch_timer(void *parameter)
217
{
218 219 220 221
    int16_t x;
    int16_t y;
    struct touch_state ts;
    touch_get_state(&ts);
222

223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238
#ifdef PKG_USING_LITTLEVGL2RTT    
    if(ts.pressed) 
    {
        x = (3706 - ts.x) / 14;
        y = (-461 + ts.y) / 10.5;
        
        littlevgl2rtt_send_input_event(x, y, LITTLEVGL2RTT_INPUT_DOWN);
    }
    else
        littlevgl2rtt_send_input_event(-1, -1, LITTLEVGL2RTT_INPUT_UP);
#endif
}

static int rt_hw_touch_init(void)
{
    static struct rt_device touch;
239 240

    /* init device structure */
241 242
    touch.type = RT_Device_Class_Unknown;
    touch.init = stmpe811_touch_init;
243 244 245

    /* create 1/8 second timer */

246 247
    touch.user_data = rt_timer_create("touch", touch_timer, RT_NULL,
                                      RT_TICK_PER_SECOND/8, RT_TIMER_FLAG_PERIODIC);
248 249

    /* register touch device to RT-Thread */
250
    rt_device_register(&touch, "touch", RT_DEVICE_FLAG_RDWR);
251 252 253 254
    
    return RT_EOK;
}
INIT_BOARD_EXPORT(rt_hw_touch_init);