drv_touch.c 6.7 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 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
/*
 * 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"


#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
*/
96
static rt_err_t stmpe811_touch_init(rt_device_t dev)
97 98 99 100 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
{
    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
*/
134
int32_t touch_uninitialize (void) {
135 136 137 138 139 140 141 142 143 144 145 146
  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
*/
147 148
int32_t touch_get_state (struct touch_state *pState)
{
149 150 151 152
    uint8_t val;
    uint8_t num;
    uint8_t xyz[4];
    int32_t res;
153
    struct rt_i2c_msg msgs[2];
154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169

    /* 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--)
        {
170 171 172 173
            msgs[0].addr  = TSC_I2C_ADDR;
            msgs[0].flags = RT_I2C_WR;
            msgs[0].buf   = &val;
            msgs[0].len   = 1;
174

175
            //rt_i2c_transfer(stmpe811_i2c_bus, &msgs, 1);
176 177
          //ptrI2C->MasterTransmit (TSC_I2C_ADDR, &val, 1, true);
          //while (ptrI2C->GetStatus().busy);
178 179 180 181 182
            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);
183 184 185 186 187 188 189 190
          //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
    {
191
        /* Clear all data in FIFO */
192 193 194 195 196 197
        touch_write(STMPE811_FIFO_STA, 0x1);
        touch_write(STMPE811_FIFO_STA, 0x0);
    }

    return 0;
}
198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230

void touch_show_state()
{
    struct touch_state ts;
    touch_get_state(&ts);
    rt_kprintf("[drv_touch] touch_show_state, x: %d, y: %d, pressed: %d, padding: %d\n", ts.x , ts.y, ts.pressed, ts.padding);
}
MSH_CMD_EXPORT(touch_show_state, show screen coordinate in touching);

static int rt_hw_touch_init(void)
{
    rt_device_t touch = RT_NULL;

    touch = (struct rt_device *)rt_malloc(sizeof(struct rt_device));
    if (touch == RT_NULL)
        return RT_ENOMEM; /* no memory yet */

    /* init device structure */
    touch->type = RT_Device_Class_Unknown;
    touch->init = stmpe811_touch_init;
    touch->user_data = RT_NULL;

    /* create 1/8 second timer */

    //rt_timer_create("touch", touch_timer, RT_NULL,
    //                RT_TICK_PER_SECOND/8, RT_TIMER_FLAG_PERIODIC);

    /* register touch device to RT-Thread */
    rt_device_register(touch, "touch", RT_DEVICE_FLAG_RDWR);
    
    return RT_EOK;
}
INIT_BOARD_EXPORT(rt_hw_touch_init);