PIC32MX7 MMB touchscreen driver update

git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@4806 42af7a65-404d-4744-a932-0658087f49c3
This commit is contained in:
patacongo 2012-06-06 16:10:45 +00:00
parent cb4999caa8
commit f0a7756f43
3 changed files with 135 additions and 45 deletions

View File

@ -2889,7 +2889,8 @@
* configs/pic32mx7mmb/src/up_mio283qt2.c: Add support for the MIO283QT2 * configs/pic32mx7mmb/src/up_mio283qt2.c: Add support for the MIO283QT2
LCD on the PIC32MX7 MMB board. LCD on the PIC32MX7 MMB board.
* configs/pic32mx7mmb/src/up_touchscreen.c: Add an ACD-based touchscreen * configs/pic32mx7mmb/src/up_touchscreen.c: Add an ACD-based touchscreen
driver for the PIC32MX7 MMB board. driver for the PIC32MX7 MMB board. Kind of works, but needs more
verification and tuning.
* arch/mips/src/common/up_idle.c: Strange but important fix. For some still- * arch/mips/src/common/up_idle.c: Strange but important fix. For some still-
unknown reason, interrupts are left in an unhealthy state in the IDLE unknown reason, interrupts are left in an unhealthy state in the IDLE
when the work queue is enabled. This is partially because some interrupt when the work queue is enabled. This is partially because some interrupt

View File

@ -8,7 +8,7 @@
<tr align="center" bgcolor="#e4e4e4"> <tr align="center" bgcolor="#e4e4e4">
<td> <td>
<h1><big><font color="#3c34ec"><i>NuttX RTOS</i></font></big></h1> <h1><big><font color="#3c34ec"><i>NuttX RTOS</i></font></big></h1>
<p>Last Updated: June 4, 2012</p> <p>Last Updated: June 6, 2012</p>
</td> </td>
</tr> </tr>
</table> </table>
@ -2281,7 +2281,14 @@
(2) Verified SPI driver, (2) Verified SPI driver,
(3) SPI-based SD Card support, (3) SPI-based SD Card support,
(4) USB device support (including configuration options for the USB mass storage device and the CDC/ACM serial class), and (4) USB device support (including configuration options for the USB mass storage device and the CDC/ACM serial class), and
(4) Support for the MIO873QT2 LCD on the PIC32MX7 MMB. (5) Support for the MIO873QT2 LCD on the PIC32MX7 MMB.
</p>
</p>
The PIC32MX7 MMB's touchscreen is connected directly to the MCU via ADC pins.
A touchscreen driver has been developed using the PIC32's ADC capabilities and can be enabled in the NSH configuration.
However, additional verification and tuning of this driver is required.
Further display/touchscreen verification would require C++ support (for NxWidgets and NxWM).
Since I there is no PIC32 C++ is the free version of the MPLAB C32 toolchain, further graphics development is stalled.
</p> </p>
</ul> </ul>
</td> </td>

View File

@ -74,6 +74,10 @@
#undef CONFIG_TOUCHSCREEN_REFCNT #undef CONFIG_TOUCHSCREEN_REFCNT
/* Should we try again on bad samples? */
#undef CONFIG_TOUCHSCREEN_RESAMPLE
/* Work queue support is required */ /* Work queue support is required */
#ifndef CONFIG_SCHED_WORKQUEUE #ifndef CONFIG_SCHED_WORKQUEUE
@ -130,12 +134,19 @@
#define MAX_ADC (1023) #define MAX_ADC (1023)
/* A measured value has to be within this range to be considered */
#define UPPER_THRESHOLD (MAX_ADC-1)
#define LOWER_THRESHOLD (1)
/* Delays ***************************************************************************/ /* Delays ***************************************************************************/
/* All values will be increased by one system timer tick (probably 10MS). */
#define TC_PENUP_POLL_TICKS (100 / MSEC_PER_TICK) /* IDLE polling rate: 100 MSec */ #define TC_PENUP_POLL_TICKS (100 / MSEC_PER_TICK) /* IDLE polling rate: 100 MSec */
#define TC_PENDOWN_POLL_TICKS (80 / MSEC_PER_TICK) /* Active polling rate: 80 MSec */ #define TC_PENDOWN_POLL_TICKS (60 / MSEC_PER_TICK) /* Active polling rate: 60 MSec */
#define TC_DEBOUNCE_TICKS (30 / MSEC_PER_TICK) /* Delay before re-sampling: 30 MSec */ #define TC_DEBOUNCE_TICKS (30 / MSEC_PER_TICK) /* Delay before re-sampling: 30 MSec */
#define TC_SAMPLE_TICKS (80 / MSEC_PER_TICK) /* Delay for A/D conversion: 80 MSec */ #define TC_SAMPLE_TICKS (4 / MSEC_PER_TICK) /* Delay for A/D sampling: 4 MSec */
#define TC_RESAMPLE_TICKS TC_SAMPLE_TICKS
/************************************************************************************ /************************************************************************************
* Private Types * Private Types
@ -147,6 +158,7 @@ enum tc_state_e
TC_READY = 0, /* Ready to begin next sample */ TC_READY = 0, /* Ready to begin next sample */
TC_YMPENDOWN, /* Allowing time for the Y- pen down sampling */ TC_YMPENDOWN, /* Allowing time for the Y- pen down sampling */
TC_DEBOUNCE, /* Allowing a debounce time for the first sample */ TC_DEBOUNCE, /* Allowing a debounce time for the first sample */
TC_RESAMPLE, /* Restart sampling on a bad measurement */
TC_YMSAMPLE, /* Allowing time for the Y- sampling */ TC_YMSAMPLE, /* Allowing time for the Y- sampling */
TC_YPSAMPLE, /* Allowing time for the Y+ sampling */ TC_YPSAMPLE, /* Allowing time for the Y+ sampling */
TC_XPSAMPLE, /* Allowing time for the X+ sampling */ TC_XPSAMPLE, /* Allowing time for the X+ sampling */
@ -214,6 +226,7 @@ static void tc_yminus_sample(void);
static void tc_yplus_sample(void); static void tc_yplus_sample(void);
static void tc_xplus_sample(void); static void tc_xplus_sample(void);
static void tc_xminus_sample(void); static void tc_xminus_sample(void);
static inline bool tc_valid_sample(uint16_t sample);
static void tc_notify(FAR struct tc_dev_s *priv); static void tc_notify(FAR struct tc_dev_s *priv);
static int tc_sample(FAR struct tc_dev_s *priv, static int tc_sample(FAR struct tc_dev_s *priv,
@ -363,8 +376,7 @@ static void tc_yminus_sample(void)
{ {
/* Configure X- as an input and X+, Y+, and Y- as outputs */ /* Configure X- as an input and X+, Y+, and Y- as outputs */
putreg32(LCD_XPLUS_BIT | LCD_YPLUS_BIT | LCD_YMINUS_BIT, putreg32(LCD_XPLUS_BIT | LCD_YPLUS_BIT | LCD_YMINUS_BIT, PIC32MX_IOPORTB_TRISCLR);
PIC32MX_IOPORTB_TRISCLR);
putreg32(LCD_XMINUS_BIT, PIC32MX_IOPORTB_TRISSET); putreg32(LCD_XMINUS_BIT, PIC32MX_IOPORTB_TRISSET);
/* Energize the X plate: Y+ and Y- high, X+ low */ /* Energize the X plate: Y+ and Y- high, X+ low */
@ -389,11 +401,10 @@ static void tc_yplus_sample(void)
{ {
/* Configure X+ as an input and X-, Y+, and Y- as outputs */ /* Configure X+ as an input and X-, Y+, and Y- as outputs */
putreg32(LCD_XMINUS_BIT | LCD_YPLUS_BIT | LCD_YMINUS_BIT, putreg32(LCD_XMINUS_BIT | LCD_YPLUS_BIT | LCD_YMINUS_BIT, PIC32MX_IOPORTB_TRISCLR);
PIC32MX_IOPORTB_TRISCLR);
putreg32(LCD_XPLUS_BIT, PIC32MX_IOPORTB_TRISSET); putreg32(LCD_XPLUS_BIT, PIC32MX_IOPORTB_TRISSET);
/* Energize the X plate: Y+ and Y- High, X- low*/ /* Energize the X plate: Y+ and Y- High, X- low (X+ is an input) */
putreg32(LCD_XMINUS_BIT, PIC32MX_IOPORTB_PORTCLR); putreg32(LCD_XMINUS_BIT, PIC32MX_IOPORTB_PORTCLR);
putreg32(LCD_YPLUS_BIT | LCD_YMINUS_BIT, PIC32MX_IOPORTB_PORTSET); putreg32(LCD_YPLUS_BIT | LCD_YMINUS_BIT, PIC32MX_IOPORTB_PORTSET);
@ -415,11 +426,10 @@ static void tc_xplus_sample(void)
{ {
/* Configure Y+ as an input and X+, X-, and Y- as outputs */ /* Configure Y+ as an input and X+, X-, and Y- as outputs */
putreg32(LCD_XPLUS_BIT | LCD_XMINUS_BIT | LCD_YMINUS_BIT, putreg32(LCD_XPLUS_BIT | LCD_XMINUS_BIT | LCD_YMINUS_BIT, PIC32MX_IOPORTB_TRISCLR);
PIC32MX_IOPORTB_TRISCLR);
putreg32(LCD_YPLUS_BIT, PIC32MX_IOPORTB_TRISSET); putreg32(LCD_YPLUS_BIT, PIC32MX_IOPORTB_TRISSET);
/* Energize the Y plate: X+ and X- high, Y- low*/ /* Energize the Y plate: X+ and X- high, Y- low (Y+ is an input) */
putreg32(LCD_YMINUS_BIT, PIC32MX_IOPORTB_PORTCLR); putreg32(LCD_YMINUS_BIT, PIC32MX_IOPORTB_PORTCLR);
putreg32(LCD_XPLUS_BIT | LCD_XMINUS_BIT, PIC32MX_IOPORTB_PORTSET); putreg32(LCD_XPLUS_BIT | LCD_XMINUS_BIT, PIC32MX_IOPORTB_PORTSET);
@ -441,11 +451,10 @@ static void tc_xminus_sample(void)
{ {
/* Configure Y- as an input and X+, Y+, and X- as outputs */ /* Configure Y- as an input and X+, Y+, and X- as outputs */
putreg32(LCD_XPLUS_BIT | LCD_XMINUS_BIT | LCD_YPLUS_BIT, putreg32(LCD_XPLUS_BIT | LCD_XMINUS_BIT | LCD_YPLUS_BIT, PIC32MX_IOPORTB_TRISCLR);
PIC32MX_IOPORTB_TRISCLR);
putreg32(LCD_YMINUS_BIT, PIC32MX_IOPORTB_TRISSET); putreg32(LCD_YMINUS_BIT, PIC32MX_IOPORTB_TRISSET);
/* Energize the Y plate: X+ and X- high, Y+ low */ /* Energize the Y plate: X+ and X- high, Y+ low (Y- is an input) */
putreg32(LCD_YPLUS_BIT, PIC32MX_IOPORTB_PORTCLR); putreg32(LCD_YPLUS_BIT, PIC32MX_IOPORTB_PORTCLR);
putreg32(LCD_XPLUS_BIT | LCD_XMINUS_BIT, PIC32MX_IOPORTB_PORTSET); putreg32(LCD_XPLUS_BIT | LCD_XMINUS_BIT, PIC32MX_IOPORTB_PORTSET);
@ -455,6 +464,15 @@ static void tc_xminus_sample(void)
tc_adc_sample(LCD_YMINUS_PIN); tc_adc_sample(LCD_YMINUS_PIN);
} }
/****************************************************************************
* Name: tc_valid_sample
****************************************************************************/
static inline bool tc_valid_sample(uint16_t sample)
{
return (sample > LOWER_THRESHOLD /* && sample < UPPER_THRESHOLD */);
}
/**************************************************************************** /****************************************************************************
* Name: tc_notify * Name: tc_notify
****************************************************************************/ ****************************************************************************/
@ -655,11 +673,11 @@ static void tc_worker(FAR void *arg)
value = tc_adc_convert(); value = tc_adc_convert();
/* A converted value of zero would mean that there is no touch /* A converted value at the minimum would mean that there is no touch
* and that the sampling period is complete. * and that the sampling period is complete.
*/ */
if (value == 0) if (!tc_valid_sample(value))
{ {
priv->state = TC_PENUP; priv->state = TC_PENUP;
} }
@ -677,6 +695,7 @@ static void tc_worker(FAR void *arg)
* the touchscreen. * the touchscreen.
*/ */
case TC_RESAMPLE:
case TC_DEBOUNCE: case TC_DEBOUNCE:
{ {
/* (Re-)start Y- sampling */ /* (Re-)start Y- sampling */
@ -700,11 +719,12 @@ static void tc_worker(FAR void *arg)
value = tc_adc_convert(); value = tc_adc_convert();
/* A converted value of zero would mean that the there is no touch /* A converted value at the minimum would mean that there is no touch
* and that the sampling period is complete. * and that the sampling period is complete. At converted value at
* the maximum value is probably bad too.
*/ */
if (value == 0) if (!tc_valid_sample(value))
{ {
priv->state = TC_PENUP; priv->state = TC_PENUP;
} }
@ -729,20 +749,39 @@ static void tc_worker(FAR void *arg)
case TC_YPSAMPLE: /* Allowing time for the Y+ sampling */ case TC_YPSAMPLE: /* Allowing time for the Y+ sampling */
{ {
/* Read and calculate the Y+ axis position */ /* Read the Y+ axis position */
value = MAX_ADC - tc_adc_convert(); value = tc_adc_convert();
priv->newy = (value + priv->value) >> 1;
ivdbg("Y-=%d Y+=%d Y=%d\n", priv->value, value, priv->newy);
/* Start X+ sampling */ /* A converted value at the minimum would mean that we lost the contact
* before all of the conversions were completed. At converted value at
* the maximum value is probably bad too.
*/
tc_xplus_sample(); if (!tc_valid_sample(value))
{
#ifdef CONFIG_TOUCHSCREEN_RESAMPLE
priv->state = TC_RESAMPLE;
delay = TC_RESAMPLE_TICKS;
#else
priv->state = TC_PENUP;
#endif
}
else
{
value = MAX_ADC - value;
priv->newy = (value + priv->value) >> 1;
ivdbg("Y-=%d Y+=%d[%d] Y=%d\n", priv->value, value, MAX_ADC - value, priv->newy);
/* Allow time for the X+ sampling */ /* Start X+ sampling */
tc_xplus_sample();
/* Allow time for the X+ sampling */
priv->state = TC_XPSAMPLE; priv->state = TC_XPSAMPLE;
delay = TC_SAMPLE_TICKS; delay = TC_SAMPLE_TICKS;
}
} }
break; break;
@ -752,18 +791,39 @@ static void tc_worker(FAR void *arg)
case TC_XPSAMPLE: case TC_XPSAMPLE:
{ {
/* Convert and save the X+ sample value */ /* Convert the X+ sample value */
priv->value = tc_adc_convert(); value = tc_adc_convert();
/* Start X- sampling */ /* A converted value at the minimum would mean that we lost the contact
* before all of the conversions were completed. At converted value at
* the maximum value is probably bad too.
*/
tc_xminus_sample(); if (!tc_valid_sample(value))
{
#ifdef CONFIG_TOUCHSCREEN_RESAMPLE
priv->state = TC_RESAMPLE;
delay = TC_RESAMPLE_TICKS;
#else
priv->state = TC_PENUP;
#endif
}
else
{
/* Save the X+ sample value */
/* Allow time for the X- pend down sampling */ priv->value = value;
/* Start X- sampling */
tc_xminus_sample();
/* Allow time for the X- pend down sampling */
priv->state = TC_XMSAMPLE; priv->state = TC_XMSAMPLE;
delay = TC_SAMPLE_TICKS; delay = TC_SAMPLE_TICKS;
}
} }
break; break;
@ -773,15 +833,36 @@ static void tc_worker(FAR void *arg)
case TC_XMSAMPLE: /* Allowing time for the X- sampling */ case TC_XMSAMPLE: /* Allowing time for the X- sampling */
{ {
/* Read and calculate the X- axis position */ /* Read the converted X- axis position */
value = MAX_ADC - tc_adc_convert(); value = tc_adc_convert();
newx = (value + priv->value) >> 1;
ivdbg("X+=%d X-=%d Y=%d\n", priv->value, value, newx);
/* Samples are available */ /* A converted value at the minimum would mean that we lost the contact
* before all of the conversions were completed. At converted value at
* the maximum value is probably bad too.
*/
priv->state = TC_PENDOWN; if (!tc_valid_sample(value))
{
#ifdef CONFIG_TOUCHSCREEN_RESAMPLE
priv->state = TC_RESAMPLE;
delay = TC_RESAMPLE_TICKS;
#else
priv->state = TC_PENUP;
#endif
}
else
{
/* Calculate the X- axis position */
value = MAX_ADC - value;
newx = (value + priv->value) >> 1;
ivdbg("X+=%d X-=%d[%d] X=%d\n", priv->value, value, MAX_ADC - value, newx);
/* Samples are available */
priv->state = TC_PENDOWN;
}
} }
break; break;
} }
@ -851,9 +932,10 @@ static void tc_worker(FAR void *arg)
ydiff = -ydiff; ydiff = -ydiff;
} }
if (xdiff >= CONFIG_TOUCHSCREEN_THRESHX && ydiff >= CONFIG_TOUCHSCREEN_THRESHY) if (xdiff >= CONFIG_TOUCHSCREEN_THRESHX ||
ydiff >= CONFIG_TOUCHSCREEN_THRESHY)
{ {
/* There is some change above the threshole... Report the change. */ /* There is some change above the threshold... Report the change. */
priv->sample.x = newx; priv->sample.x = newx;
priv->sample.y = priv->newy; priv->sample.y = priv->newy;