From f65b1896733e3f8cfa2e0f074585e5c5d7657331 Mon Sep 17 00:00:00 2001 From: Joel Bodenmann Date: Sun, 9 Nov 2014 21:55:15 +0100 Subject: [PATCH] Added MAX11802 driver - NOT WORKING YET - read_xyz() not ported yet --- docs/releases.txt | 1 + drivers/ginput/touch/MAX11802/driver.mk | 2 + .../touch/MAX11802/gmouse_lld_MAX11802.c | 172 ++++++++++++++++++ .../gmouse_lld_MAX11802_board_template.h | 71 ++++++++ drivers/ginput/touch/MAX11802/max11802.h | 31 ++++ 5 files changed, 277 insertions(+) create mode 100644 drivers/ginput/touch/MAX11802/driver.mk create mode 100644 drivers/ginput/touch/MAX11802/gmouse_lld_MAX11802.c create mode 100644 drivers/ginput/touch/MAX11802/gmouse_lld_MAX11802_board_template.h create mode 100644 drivers/ginput/touch/MAX11802/max11802.h diff --git a/docs/releases.txt b/docs/releases.txt index b97b17d5..ef1e4547 100644 --- a/docs/releases.txt +++ b/docs/releases.txt @@ -35,6 +35,7 @@ FEATURE: Added gdispDrawArcSectors() and gdispFillArcSectors(). FEATURE: Ported GINPUT MOUSE to GDRIVER infrastructure. FEATURE: Mouse/Touch now support both pen and finger mode. DEPRECATE: gwinAttachMouse() is now handled automaticly. +FEATURE: Added MAX11802 touch driver by user steved *** Release 2.1 *** diff --git a/drivers/ginput/touch/MAX11802/driver.mk b/drivers/ginput/touch/MAX11802/driver.mk new file mode 100644 index 00000000..246e48b3 --- /dev/null +++ b/drivers/ginput/touch/MAX11802/driver.mk @@ -0,0 +1,2 @@ +# List the required driver. +GFXSRC += $(GFXLIB)/drivers/ginput/touch/MAX11802/gmouse_lld_MAX11802.c diff --git a/drivers/ginput/touch/MAX11802/gmouse_lld_MAX11802.c b/drivers/ginput/touch/MAX11802/gmouse_lld_MAX11802.c new file mode 100644 index 00000000..0adeddf5 --- /dev/null +++ b/drivers/ginput/touch/MAX11802/gmouse_lld_MAX11802.c @@ -0,0 +1,172 @@ +/* + * This file is subject to the terms of the GFX License. If a copy of + * the license was not distributed with this file, you can obtain one at: + * + * http://ugfx.org/license.html + */ + +#include "gfx.h" + +#if GFX_USE_GINPUT && GINPUT_NEED_MOUSE + +#define GMOUSE_DRIVER_VMT GMOUSEVMT_MAX11802 +#include "src/ginput/driver_mouse.h" + +#define GMOUSE_MAX11802_FLG_TOUCHED (GMOUSE_FLG_DRIVER_FIRST << 0) + +// Hardware definitions +#include "drivers/ginput/touch/MAX11802/max11802.h" + +// Get the hardware interface +#include "gmouse_lld_MAX11802_board.h" + +// Last values read from A-D channels +static uint16_t lastx, lasty; +static uint16_t lastz = { 100 << 4 }; // This may not be used, so initialise it (value is bits 15..4) + +static bool_t MouseInit(GMouse* m, unsigned driverinstance) +{ + uint8_t ret; + + const uint8_t commandList[][2] = { + { MAX11802_CMD_GEN_WR, 0xf0 }, // General config - leave TIRQ enabled, even though we ignore it ATM + { MAX11802_CMD_RES_WR, 0x00 }, // A-D resolution, hardware config - rewriting default; all 12-bit resolution + { MAX11802_CMD_AVG_WR, MAX11802_AVG }, // A-D averaging - 8 samples, average four median samples + { MAX11802_CMD_SAMPLE_WR, 0x00 }, // A-D sample time - use default + { MAX11802_CMD_TIMING_WR, MAX11802_TIMING }, // Setup timing + { MAX11802_CMD_DELAY_WR, MAX11802_DELAY }, // Conversion delays + { MAX11802_CMD_TDPULL_WR, 0x00 }, // A-D resolution, hardware config - rewrite default + //{ MAX11802_CMD_MDTIM_WR, 0x00 }, // Autonomous mode timing - write default + //{ MAX11802_CMD_APCONF_WR, 0x00 }, // Aperture config register - rewrite default + // Ignore aux config register - not used + { MAX11802_CMD_MODE_WR, MAX11802_MODE }, // Set mode last + }; + + if (!init_board(m, driverinstance)) + return FALSE; + + aquire_bus(m); + + for (ret = 0; ret < (sizeof(commandList) / (2 * sizeof(uint8_t))); ret++) { + write_command(m, commandList[ret][0], commandList[ret][1]); + } + + ret = write_command(m, MAX11802_CMD_MODE_RD, 0); // Read something as a test + if (ret != MAX11802_MODE) { + // Error here - @TODO: What can we do about it? + } + + release_bus(m); +} + +static void read_xyz(GMouse* m, GMouseReading* pdr) +{ + uint8_t readyCount; + uint8_t notReadyCount; + + // Assume not touched. + pdr->buttons = 0; + pdr->z = 0; + + aquire_bus(m); + +#if MAX11802_READ_Z_VALUE + gfintWriteCommand(m, MAX11802_CMD_MEASUREXYZ); // just write command +#else + gfintWriteCommand(m, MAX11802_CMD_MEASUREXY); // just write command +#endif + + /** + * put a delay in here, since conversion will take a finite time - longer if reading Z as well + * Potentially 1msec for 3 axes with 8us conversion time per sample, 8 samples per average + * Note Maxim AN5435-software to do calculation (www.maximintegrated.com/design/tools/appnotes/5435/AN5435-software.zip) + * + * We'll just use a fixed delay to avoid too much polling/bus activity + */ + gfxSleepMilliseconds(2); // Was 1 - try 2 + + /* Wait for data ready + * Note: MAX11802 signals the readiness of the results using the lowest 4 bits of the result. However, these are the + * last bits to be read out of the device. It is possible for the hardware value to change in the middle of the read, + * causing the analog value to still be invalid even though the tags indicate a valid result. + * + * We work around this by reading the registers once more after the tags indicate they are ready. + * There's also a separate counter to guard against never getting valid readings. + * + * Read the two or three readings required in a single burst, swapping x and y order if necessary + */ + + readyCount = 0; + notReadyCount = 0; + do { + gfintWriteCommand(m, MAX11802_CMD_XPOSITION); // This sets pointer to first byte of block + +#if defined(GINPUT_MOUSE_YX_INVERTED) && GINPUT_MOUSE_YX_INVERTED + lasty = read_value(m); + lastx = read_value(m); +#else + lastx = read_value(m); + lasty = read_value(m)); +#endif +#if MAX11802_READ_Z_VALUE + lastz = read_value(m); + if (((lastx & 0x0f) != 0xF) && ((lasty * 0xf0) != 0xF) && ((lastz * 0xf0) != 0xF)) +#else + if (((lastx & 0x0f) != 0xF) && ((lasty * 0xf0) != 0xF)) +#endif + { + readyCount++; + } + else + { + notReadyCount++; // Protect against infinite loops + } + } while ((readyCount < 2) && (notReadyCount < 20)); + + + /** + * format of each value returned by MAX11802: + * Bits 15..4 - analog value + * Bits 3..2 - tag value - measurement type (X, Y, Z1, Z2) + * Bits 1..0 - tag value - event type (00 = valid touch, 10 - no touch, 11 - measurement in progress) + */ + pt->x = lastx >> 4; // Delete the tags + pt->y = lasty >> 4; + pt->z = lastz >> 4; // If no Z-axis, lastz has been initialised to return 100 + + pt->buttons = ((0 == (lastx & 3)) && (0 == (lasty & 3)) && (0 == (lastz & 3))) ? GINPUT_TOUCH_PRESSED : 0; + + release_bus(m); +} + +const GMouseVMT const GMOUSE_DRIVER_VMT[1] = {{ + { + GDRIVER_TYPE_TOUCH, + GMOUSE_VFLG_TOUCH | GMOUSE_VFLG_ONLY_DOWN | GMOUSE_VFLG_POORUPDOWN | GMOUSE_VFLG_CALIBRATE | GMOUSE_VFLG_CAL_TEST, + sizeof(GMouse) + GMOUSE_MAX11802_BOARD_DATA_SIZE, + _gmouseInitDriver, + _gmousePostInitDriver, + _gmouseDeInitDriver + }, + 255, // z_max + 0, // z_min + 20, // z_touchoff + 200, // z_touchon + { // pen_jitter + GMOUSE_MAX11802_PEN_CALIBRATE_ERROR, // calibrate + GMOUSE_MAX11802_PEN_CLICK_ERROR, // click + GMOUSE_MAX11802_PEN_MOVE_ERROR // move + }, + { // finger_jitter + GMOUSE_MAX11802_FINGER_CALIBRATE_ERROR, // calibrate + GMOUSE_MAX11802_FINGER_CLICK_ERROR, // click + GMOUSE_MAX11802_FINGER_MOVE_ERROR // move + }, + MouseInit, // init + 0, // deinit + read_xyz, // get + 0, // calsave + 0 // calload +}}; + +#endif /* GFX_USE_GINPUT && GINPUT_NEED_MOUSE */ diff --git a/drivers/ginput/touch/MAX11802/gmouse_lld_MAX11802_board_template.h b/drivers/ginput/touch/MAX11802/gmouse_lld_MAX11802_board_template.h new file mode 100644 index 00000000..113b2a01 --- /dev/null +++ b/drivers/ginput/touch/MAX11802/gmouse_lld_MAX11802_board_template.h @@ -0,0 +1,71 @@ +/* + * This file is subject to the terms of the GFX License. If a copy of + * the license was not distributed with this file, you can obtain one at: + * + * http://ugfx.org/license.html + */ + +#ifndef _GINPUT_LLD_MOUSE_BOARD_H +#define _GINPUT_LLD_MOUSE_BOARD_H + +// Experimental to read pressure on Z1 as well +#define MAX11802_READ_Z_VALUE FALSE + +// Resolution and Accuracy Settings +#define GMOUSE_MAX11802_PEN_CALIBRATE_ERROR 8 +#define GMOUSE_MAX11802_PEN_CLICK_ERROR 6 +#define GMOUSE_MAX11802_PEN_MOVE_ERROR 4 +#define GMOUSE_MAX11802_FINGER_CALIBRATE_ERROR 14 +#define GMOUSE_MAX11802_FINGER_CLICK_ERROR 18 +#define GMOUSE_MAX11802_FINGER_MOVE_ERROR 14 + +// Register values to set +#define MAX11802_MODE 0x0E // Direct conversion with averaging +#define MAX11802_AVG 0x55 +#define MAX11802_TIMING 0x77 +#define MAX11802_DELAY 0x55 + +// How much extra data to allocate at the end of the GMouse structure for the board's use +#define GMOUSE_MAX11802_BOARD_DATA_SIZE 0 + +static inline void init_board(GMouse* m) { + +} + +static inline bool_t getpin_pressed(GMouse* m) { + +} + +static inline void aquire_bus(GMouse* m) { + +} + +static inline void release_bus(GMouse* m) { + +} + +/** + * Send command (with parameter) to the MAX11802 + * + * Return the second byte read in case of interest + */ +static inline uint8_t write_command(GMouse* m, uint8_t command, uint8_t value) { +} + +/** + * Send command (no parameter) to the MAX11802 + * + * Return the byte read in case of interest + */ +static inline uint8_t gfintWriteCommand(GMouse* m, uint8_t command) { +} + +/* + * Read 2 bytes as 16-bit value (command to read must have been sent previously) + * Note: Analog value is in bits 15..4, tags (reading status) in bits 3..0 +*/ +static inline uint16_t read_value(GMouse* m) { + +} + +#endif /* _GINPUT_LLD_MOUSE_BOARD_H */ diff --git a/drivers/ginput/touch/MAX11802/max11802.h b/drivers/ginput/touch/MAX11802/max11802.h new file mode 100644 index 00000000..2266bfa1 --- /dev/null +++ b/drivers/ginput/touch/MAX11802/max11802.h @@ -0,0 +1,31 @@ +/* + * This file is subject to the terms of the GFX License. If a copy of + * the license was not distributed with this file, you can obtain one at: + * + * http://ugfx.org/license.html + */ + +#ifndef _MAX11802_H +#define _MAX11802_H + +#define MAX11802_CMD_XPOSITION ((0x52 << 1) | 1) +#define MAX11802_CMD_YPOSITION ((0x54 << 1) | 1) +#define MAX11802_CMD_ZPOSITION ((0x56 << 1) | 1) + +// LSB of register addresses specifies read (1) or write (0) +#define MAX11802_CMD_MEASUREXY (0x70 << 1) +#define MAX11802_CMD_MEASUREXYZ (0x72 << 1) +#define MAX11802_CMD_GEN_WR (0x01 << 1) // General config register +#define MAX11802_CMD_RES_WR (0x02 << 1) +#define MAX11802_CMD_AVG_WR (0x03 << 1) +#define MAX11802_CMD_SAMPLE_WR (0x04 << 1) +#define MAX11802_CMD_TIMING_WR (0x05 << 1) +#define MAX11802_CMD_DELAY_WR (0x06 << 1) +#define MAX11802_CMD_TDPULL_WR (0x07 << 1) +#define MAX11802_CMD_MDTIM_WR (0x08 << 1) +#define MAX11802_CMD_APCONF_WR (0x09 << 1) +#define MAX11802_CMD_MODE_WR (0x0B << 1) +#define MAX11802_CMD_MODE_RD ((0x0B << 1) | 1) +#define MAX11802_CMD_GSR_RD ((0x00 << 1) | 1) // General status register - read-only + +#endif /* _MAX11802_H */