static bool_t MouseXYZ(GMouse* m, GMouseReading* pdr) { (void)m; // No buttons pdr->buttons = 0; pdr->z = 0; if (getpin_pressed(m)) { pdr->z = 1; // Set to Z_MAX as we are pressed aquire_bus(m); read_value(m, CMD_X); // Dummy read - disable PenIRQ pdr->x = read_value(m, CMD_X); // Read X-Value read_value(m, CMD_Y); // Dummy read - disable PenIRQ pdr->y = read_value(m, CMD_Y); // Read Y-Value read_value(m, CMD_ENABLE_IRQ); // Enable IRQ release_bus(m); } return TRUE; }
/** * @brief Read the mouse/touch position. * * @param[in] pt A pointer to the structure to fill * * @note For drivers that don't support returning a position * when the touch is up (most touch devices), it should * return the previous position with the new Z value. * The z value is the pressure for those touch devices * that support it (-100 to 100 where > 0 is touched) * or, 0 or 100 for those drivers that don't. * * @notapi */ void ginput_lld_mouse_get_reading(MouseReading *pt) { uint16_t i; // If touch-off return the previous results if (!getpin_pressed()) { pt->x = lastx; pt->y = lasty; pt->z = 0; pt->buttons = 0; return; } // Read the port to get the touch settings aquire_bus(); /* Get the X value * Discard the first conversion - very noisy and keep the ADC on hereafter * till we are done with the sampling. Note that PENIRQ is disabled while reading. * Finally switch on PENIRQ once again - perform a dummy read. * Once we have the readings, find the medium using our filter function */ read_value(0xD1); for(i = 0; i < 7; i++) sampleBuf[i] = read_value(0xD1); read_value(0xD0); filter(); lastx = (coord_t)sampleBuf[3]; /* Get the Y value using the same process as above */ read_value(0x91); for(i = 0; i < 7; i++) sampleBuf[i] = read_value(0x91); read_value(0x90); filter(); lasty = (coord_t)sampleBuf[3]; // Release the bus release_bus(); // Return the results pt->x = lastx; pt->y = lasty; pt->z = 100; pt->buttons = GINPUT_TOUCH_PRESSED; }
/** * Notes: * * This chip has some problems which required careful coding to overcome. * * The interrupt pin seems to be unreliable, at least on some boards, so we at most * use the pin for filtering results to reduce cpu load. * The symptoms are that readings will just stop due to the irq not being asserted * even though there are items in the fifo. Another interrupt source such as a * touch transition will restart the irq. * * There is no fifo entry created when a touch up event occurs. We must therefore * generate a pseudo result on touch up. Fortunately the touch detection appears * reliable and so we turn off the driver GMOUSE_VFLG_POORUPDOWN setting. In practice * if touch is up we always return a pseudo event as this saves having to remember the * previous touch state. * * Z readings range from around 90 (fully touched) to around 150 (on the verge of non-touched). * Note the above is on the STM32F429i-Discovery board. Other boards may be different. * To be conservative we use 255 as touch off, anything else is a touch on. * * GMOUSE_STMPE811_TEST_MODE is designed to be used with the "touch_raw_readings" tool which shows * a steady stream of raw readings. * * Settings that may need tweaking on other hardware: * The settling times. We have set these conservatively at 1ms. * The reading window. We set this to 16 just to reduce noise. High-res panels may need a lower value. */ static bool_t MouseInit(GMouse* m, unsigned driverinstance) { if (!init_board(m, driverinstance)) return FALSE; aquire_bus(m); write_reg(m, STMPE811_REG_SYS_CTRL1, 0x02); // Software chip reset gfxSleepMilliseconds(10); write_reg(m, STMPE811_REG_SYS_CTRL2, 0x0C); // Temperature sensor clock off, GPIO clock off, touch clock on, ADC clock on #if GMOUSE_STMPE811_GPIO_IRQPIN write_reg(m, STMPE811_REG_INT_EN, 0x03); // Interrupt on INT pin when there is a sample or a touch transition. #else write_reg(m, STMPE811_REG_INT_EN, 0x00); // Don't Interrupt on INT pin #endif write_reg(m, STMPE811_REG_ADC_CTRL1, 0x48); // ADC conversion time = 80 clock ticks, 12-bit ADC, internal voltage refernce gfxSleepMilliseconds(2); write_reg(m, STMPE811_REG_ADC_CTRL2, 0x01); // ADC speed 3.25MHz write_reg(m, STMPE811_REG_GPIO_AF, 0x00); // GPIO alternate function - OFF write_reg(m, STMPE811_REG_TSC_CFG, 0xA3); // Averaging 4, touch detect delay 1ms, panel driver settling time 1ms write_reg(m, STMPE811_REG_FIFO_TH, 0x01); // FIFO threshold = 1 write_reg(m, STMPE811_REG_FIFO_STA, 0x01); // FIFO reset enable write_reg(m, STMPE811_REG_FIFO_STA, 0x00); // FIFO reset disable write_reg(m, STMPE811_REG_TSC_FRACT_XYZ, 0x07); // Z axis data format write_reg(m, STMPE811_REG_TSC_I_DRIVE, 0x01); // max 50mA touchscreen line current #if GMOUSE_STMPE811_READ_PRESSURE write_reg(m, STMPE811_REG_TSC_CTRL, 0x30); // X&Y&Z, 16 reading window write_reg(m, STMPE811_REG_TSC_CTRL, 0x31); // X&Y&Z, 16 reading window, TSC enable #else write_reg(m, STMPE811_REG_TSC_CTRL, 0x32); // X&Y, 16 reading window write_reg(m, STMPE811_REG_TSC_CTRL, 0x33); // X&Y, 16 reading window, TSC enable #endif write_reg(m, STMPE811_REG_INT_STA, 0xFF); // Clear all interrupts write_reg(m, STMPE811_REG_INT_CTRL, 0x01); // Level interrupt, enable interrupts release_bus(m); return TRUE; }
/** * @brief Get the color of a particular pixel. * @note Optional. * @note If x,y is off the screen, the result is undefined. * * @param[in] x, y The start of the text * * @notapi */ color_t GDISP_LLD(getpixelcolor)(coord_t x, coord_t y) { /* This routine is marked "DO NOT USE" in the original * GLCD driver. We just keep our GDISP_HARDWARE_READPIXEL * turned off for now. */ color_t color; #if GDISP_NEED_VALIDATION || GDISP_NEED_CLIP if (x < 0 || x >= GDISP.Width || y < 0 || y >= GDISP.Height) return 0; #endif aquire_bus(); set_cursor(x, y); stream_start(); color = lld_lcdReadData(); color = lld_lcdReadData(); stream_stop(); release_bus(); return color; }
static bool_t read_xyz(GMouse* m, GMouseReading* pdr) { #if GMOUSE_STMPE811_TEST_MODE static GMouseReading n; #endif uint8_t status; // Button information will be regenerated pdr->buttons = 0; #if GMOUSE_STMPE811_TEST_MODE aquire_bus(m); // Set the buttons to match various touch signals if ((read_byte(m, STMPE811_REG_TSC_CTRL) & 0x80)) pdr->buttons |= 0x02; status = read_byte(m, STMPE811_REG_FIFO_STA); if (!(status & 0x20)) pdr->buttons |= 0x04; #if GMOUSE_STMPE811_GPIO_IRQPIN if (getpin_irq(m)) pdr->buttons |= 0x08; #endif if ((status & 0x20)) { // Nothing in the fifo - just return the last position and pressure pdr->x = n.x; pdr->y = n.y; pdr->z = n.z; #if GMOUSE_STMPE811_GPIO_IRQPIN write_reg(m, STMPE811_REG_INT_STA, 0xFF); #endif release_bus(m); return TRUE; } #else // Is there a new sample or a touch transition #if GMOUSE_STMPE811_GPIO_IRQPIN if(!getpin_irq(m)) return FALSE; #endif // Is there something in the fifo status = read_byte(m, STMPE811_REG_FIFO_STA); if ((status & 0x20)) { // Nothing in the fifo. // If not touched return the pseudo result if (!(read_byte(m, STMPE811_REG_TSC_CTRL) & 0x80)) { pdr->z = gmvmt(m)->z_min; #if GMOUSE_STMPE811_GPIO_IRQPIN write_reg(m, STMPE811_REG_INT_STA, 0xFF); #endif release_bus(m); return TRUE; } // No new result #if GMOUSE_STMPE811_GPIO_IRQPIN write_reg(m, STMPE811_REG_INT_STA, 0xFF); #endif release_bus(m); return FALSE; } #endif // Time to get some readings pdr->x = (coord_t)read_word(m, STMPE811_REG_TSC_DATA_X); pdr->y = (coord_t)read_word(m, STMPE811_REG_TSC_DATA_Y); #if GMOUSE_STMPE811_READ_PRESSURE pdr->z = (coord_t)read_byte(m, STMPE811_REG_TSC_DATA_Z); #else pdr->z = gmvmt(m)->z_max; #endif #if !GMOUSE_STMPE811_SLOW_CPU if (!(status & 0xC0)) { // Is there more data to come if (!(read_byte(m, STMPE811_REG_FIFO_STA) & 0x20)) _gmouseWakeup(m); } else #endif // Clear the rest of the fifo { write_reg(m, STMPE811_REG_FIFO_STA, 0x01); // FIFO reset enable write_reg(m, STMPE811_REG_FIFO_STA, 0x00); // FIFO reset disable } // All done #if GMOUSE_STMPE811_GPIO_IRQPIN write_reg(m, STMPE811_REG_INT_STA, 0xFF); #endif release_bus(m); #if GMOUSE_STMPE811_TEST_MODE // Save the result for later n.x = pdr->x; n.y = pdr->y; n.z = pdr->z; #endif // Rescale X,Y if we are using self-calibration #if GMOUSE_STMPE811_SELF_CALIBRATE #if GDISP_NEED_CONTROL switch(gdispGGetOrientation(m->display)) { default: case GDISP_ROTATE_0: case GDISP_ROTATE_180: pdr->x = gdispGGetWidth(m->display) - pdr->x / (4096/gdispGGetWidth(m->display)); pdr->y = pdr->y / (4096/gdispGGetHeight(m->display)); break; case GDISP_ROTATE_90: case GDISP_ROTATE_270: pdr->x = gdispGGetHeight(m->display) - pdr->x / (4096/gdispGGetHeight(m->display)); pdr->y = pdr->y / (4096/gdispGGetWidth(m->display)); break; } #else pdr->x = gdispGGetWidth(m->display) - pdr->x / (4096/gdispGGetWidth(m->display)); pdr->y = pdr->y / (4096/gdispGGetHeight(m->display)); #endif #endif return TRUE; }