diff --git a/arch/arm/src/sama5/sam_tsd.c b/arch/arm/src/sama5/sam_tsd.c index 8323f43e03..515b90ec53 100644 --- a/arch/arm/src/sama5/sam_tsd.c +++ b/arch/arm/src/sama5/sam_tsd.c @@ -172,19 +172,23 @@ struct sam_sample_s struct sam_tsd_s { - uint8_t nwaiters; /* Number of threads waiting for touchscreen data */ - uint8_t id; /* Current touch point ID */ - uint8_t valid; /* Data ready bit set */ - uint8_t crefs; /* The number of times the device has been opened */ - volatile bool penchange; /* An unreported event is buffered */ - uint32_t threshx; /* Thresholding X value */ - uint32_t threshy; /* Thresholding Y value */ - sem_t waitsem; /* Used to wait for the availability of data */ + uint8_t nwaiters; /* Num threads waiting for TSD data */ + uint8_t id; /* Current touch point ID */ + uint8_t valid; /* Data ready bit set */ + uint8_t crefs; /* Number of times device opened */ + volatile bool penchange; /* An unreported event is buffered */ + uint32_t threshx; /* Thresholding X value */ + uint32_t threshy; /* Thresholding Y value */ + sem_t waitsem; /* Used to wait for data available */ - struct sam_adc_s *adc; /* ADC device handle */ - struct work_s work; /* Supports the interrupt handling "bottom half" */ - struct sam_sample_s sample; /* Last sampled touch point data */ - struct wdog_s wdog; /* Poll the position while the pen is down */ + struct sam_adc_s *adc; /* ADC device handle */ + struct work_s work; /* Supports int. handling "bottom half" */ + struct sam_sample_s sample; /* Last sampled touch point data */ + struct wdog_s wdog; /* Poll position while the pen is down */ + struct g_tscaldata_s caldata; /* Touchscreen Calibration Data */ + bool scaled; /* Character dreiver read should return + * scaled values (true) or not (false). + */ /* The following is a list if poll structures of threads waiting for * driver events. The 'struct pollfd' reference for each open is also @@ -689,11 +693,11 @@ static void sam_tsd_bottomhalf(void *arg) */ #ifdef CONFIG_SAMA5_TSD_SWAPXY - x = ((yraw << 12) - yraw) / yscale; - y = ((xraw << 12) - xraw) / xscale; + x = ((yraw << 12)) / yscale; + y = ((xraw << 12)) / xscale; #else - x = ((xraw << 12) - xraw) / xscale; - y = ((yraw << 12) - yraw) / yscale; + x = ((xraw << 12)) / xscale; + y = ((yraw << 12)) / yscale; #endif /* Perform a thresholding operation so that the results will be @@ -1025,10 +1029,22 @@ static ssize_t sam_tsd_read(struct file *filep, char *buffer, size_t len) report = (struct touch_sample_s *)buffer; memset(report, 0, SIZEOF_TOUCH_SAMPLE_S(1)); - report->npoints = 1; - report->point[0].id = sample.id; - report->point[0].x = sample.x; - report->point[0].y = sample.y; + report->npoints = 1; + report->point[0].id = sample.id; + + if (priv->scaled) + { + report->point[0].x = SCALE_TS(itob16(sample.x), priv->caldata.offset_x, + priv->caldata.slope_x); + report->point[0].y = SCALE_TS(itob16(sample.y), priv->caldata.offset_y, + priv->caldata.slope_y); + } + else + { + report->point[0].x = sample.x; + report->point[0].y = sample.y; + } + #ifdef CONFIG_SAMA5_TSD_4WIRE report->point[0].pressure = sample.p; #endif @@ -1085,7 +1101,8 @@ static int sam_tsd_ioctl(struct file *filep, int cmd, unsigned long arg) { struct inode *inode; struct sam_tsd_s *priv; - int ret; + int ret = OK; + int regval; iinfo("cmd: %d arg: %ld\n", cmd, arg); DEBUGASSERT(filep); @@ -1102,6 +1119,30 @@ static int sam_tsd_ioctl(struct file *filep, int cmd, unsigned long arg) switch (cmd) { + case TSIOC_DOACALIB: + { + /* Initiate auto-calibration sequence */ + + regval = sam_adc_getreg(priv->adc, SAM_ADC_ACR); + regval = ADC_CR_TSCALIB | ADC_CR_START; + sam_adc_putreg(priv->adc, SAM_ADC_CR, regval); + } + break; + case TSIOC_CALDATA: + { + /* Receive calibration data for the touchscreen */ + + struct g_tscaldata_s *ptr = + (struct g_tscaldata_s *)((uintptr_t)arg); + DEBUGASSERT(ptr != NULL); + priv->caldata = *ptr; + } + break; + case TSIOC_USESCALED: + { + priv->scaled = (bool)(arg); + } + break; default: ret = -ENOTTY; break; diff --git a/include/nuttx/input/touchscreen.h b/include/nuttx/input/touchscreen.h index dc80f49ce0..64315bad71 100644 --- a/include/nuttx/input/touchscreen.h +++ b/include/nuttx/input/touchscreen.h @@ -39,6 +39,8 @@ #include #include #include +#include +#include /**************************************************************************** * Pre-processor Definitions @@ -48,12 +50,32 @@ /* Common TSC IOCTL commands */ -#define TSIOC_SETCALIB _TSIOC(0x0001) /* arg: Pointer to int calibration value */ -#define TSIOC_GETCALIB _TSIOC(0x0002) /* arg: Pointer to int calibration value */ -#define TSIOC_SETFREQUENCY _TSIOC(0x0003) /* arg: Pointer to uint32_t frequency value */ -#define TSIOC_GETFREQUENCY _TSIOC(0x0004) /* arg: Pointer to uint32_t frequency value */ -#define TSIOC_GETFWVERSION _TSIOC(0x0005) /* arg: Pointer to uint32_t firmware version value */ -#define TSIOC_ENABLEGESTURE _TSIOC(0x0006) /* arg: Pointer to int for enable gesture feature */ +#define TSIOC_SETCALIB _TSIOC(0x0001) /* arg: Pointer to + * int Xplate R calibration value + */ +#define TSIOC_GETCALIB _TSIOC(0x0002) /* arg: Pointer to + * int Xplate R calibration value + */ +#define TSIOC_SETFREQUENCY _TSIOC(0x0003) /* arg: Pointer to + * uint32_t frequency value + */ +#define TSIOC_GETFREQUENCY _TSIOC(0x0004) /* arg: Pointer to + * uint32_t frequency value + */ +#define TSIOC_GETFWVERSION _TSIOC(0x0005) /* arg: Pointer to + * uint32_t firmware version + * value + * */ +#define TSIOC_ENABLEGESTURE _TSIOC(0x0006) /* arg: Pointer to + * int for enable gesture feature + */ +#define TSIOC_DOACALIB _TSIOC(0x0007) /* arg: none. + * Initiate TS auto calibration + */ +#define TSIOC_CALDATA _TSIOC(0x0008) /* arg: Pointer to + * struct g_tscaldata_s + */ +#define TSIOC_USESCALED _TSIOC(0x0009) /* arg: bool, yes/no */ #define TSC_FIRST 0x0001 /* First common command */ #define TSC_NCMDS 6 /* Six common commands */ @@ -105,10 +127,43 @@ #define TOUCH_SLIDE_RIGHT (0x04) #define TOUCH_PALM (0x05) +/* Help function */ + +#define SCALE_TS(x, o, s) (b16toi(b16divb16(((x) - (o)), (s)))) + /**************************************************************************** * Public Types ****************************************************************************/ +/* This struct is used to store touchscreen calibration data for use by + * low level touichscreen drivers. + * + * It is used as follows: + * + * scaledX = (raw_x - offset_x) / slope_x + * scaledY = (raw_y - offset_y) / slope_y + * + * The calibration values would typically be derived by taking top left and + * bottom right measurements on the actual LCD/touchscreen used: + * + * xSlope = (ActualRightX - ActualLeftX) / (WantedRightX - WantedLeftX) + * xOffset = ActualLeftX - (WantedLeftX * xSlope) + * + * And similarly for the Y values. + * + * ySlope = (ActualBottomY - ActualTopY) / (WantedBottomY - WantedTopY) + * yOffset = ActualTopY - (WantedTopY * ySlope) + * + */ + + struct g_tscaldata_s + { + b16_t slope_x; + b16_t offset_x; + b16_t slope_y; + b16_t offset_y; + }; + /* This structure contains information about a single touch point. * Positional units are device specific. */