📄 lh7a400_lcd_evb_touchscreen_driver.c
字号:
/**********************************************************************
* $Workfile: lh7a400_lcd_evb_touchscreen_driver.c $
* $Revision: 1.4 $
* $Author: FergisJ $
* $Date: Aug 20 2002 16:55:16 $
*
* Project: LH7A400
*
* Description:
*
* This is driver for the LH7A400 EVB system's ADS7843 touchscreen
* controller from TI (formerly Burr-Brown). The AD7843 is mounted
* on the LCD board. It communicates with the LH7A400 via the SSP.
* This driver consumes the SSP, a timer, GPIO port F, bit 0,
* GPIO Port K, bits 0 and 1, two IRQ interrupt priorities, and one
* FIQ priority.
*
* The following user functions are provided:
* lcd_touchscreen_init()--Initialize the touchscreen driver. You
* must call this function before calling
* any other function
* lcd_touchscreen_controller_disable()--Disable the touchscreen
* driver, free interrupts, etc.
* lcd_touchscreen_q_accept()--remove the next touchscreen pen state
* and coordinates structure from this
* driver's software queue and return it.
* lcd_touchscreen_q_empty()--return true if the touchscreen
* controller driver's software queue
* contains no pen state and coordinate
* structures.
*
* Configuration options:
*
* A number of factors may need to be tweaked depending on the
* application. Also, resources such as interrupt priorities and
* timers have to be allocated. LH7A400_lcd_evb_touchscreen_driver.h
* contains all parameters that may need to be adjusted by the user.
*
* Porting to an operating system environment:
*
* If this driver is to exist within an operating system, it is
* recommended that the function lcd_coordinate_read_handler()
* post measurement results to an OS queue rather than to the
* queue this driver creates. Also, it is recommended that an OS
* timer is used rather than a physical timer. The functions
* lcd_timer_handler(), lcd_touchscreen_init(),
* lcd_touchscreen_controller_disable(), lcd_coordinate_read_handler()
* will have to be rewritten to use an OS timer.
*
* Driver Strategy:
*
* Use SSP in microwire mode with 8-bit command and
* 12-bit data for 21 (8 bits of command, 1 bit of busy, 12 bits
* of data) bits per conversion. Use a clock rate of 1 MHz (or less,
* need to experiment) for a 3 us acquisition time. Use differential
* mode with two consecutive reads to allow for panel settling per
* the ADS7843 APP note. This will require tweaking based on noise
* performance. The ADS7843 sleeps between conversions to save power.
* If 100 KHz clock works, this double conversion works at about 24 kHz
* (about 42 us). We need two conversions per coordinate and two
* coordinates (x and y) so the total time is about 840 us. We will
* sample the touch screen every 100 ms or so in real life, so
* the device is asleep over 99% of the time.
*
* Measured X-Y coordinate pairs are stored in a software queue
* (not the same as the SSP transmit and receive FIFOS)
* if the coordinate pair is sufficiently different from the previously
* measured coordiante pair.
*
* ALGORITHM:
* Once the touchscreen controller is initialized, the LH7A400 waits for
* a Pen down interrupt from the touchscreen controller. On receipt of
* a Pen down interrupt (see lcd_touchscreen_pen_down_handler()),
* the LH7A400 first verifies that the pen is still
* down by polling the status of the Pen IRQ bit of the ADS7843. If the
* pen is still down, the LH7A400 masks the Pen interrupt and sends
* enough data out the SSP to start a coordiante measurement. (see
* measurexy() );
*
* When the coordinate measurement is complete, there will be 4 data
* elements in the SSP receiver FIFO. This triggers an SSP receiver
* FIFO interrupt (see lcd_coordinate_read_handler() ). Since the first
* measurement in the X and Y directions represents data taken during
* the settling time, these measurements are discarded. If the X and
* Y coordinates are sufficiently different from the last X and Y
* coordinates, then the data are place in the Touchscreen driver's
* queue. The touchscreen timer is started.
*
* When the the sampling interval specified by the timer elapses, (see
* lcd_timer_handler() ), the LH7A400 stops the timer. The LH7A400 then
* checks the ADS7843 pen IRQ status to make sure the pen is still
* down. If the pen is still down, then the LH7A400 calls measurexy()
* and repeats the process in the preceding paragraph. If the pen is
* up, the LH7A400 posts a pen-up message in the software queue and
* waits for a new Pen down interrupt again.
*
* Revision History:
* $Log: //smaicnt2/pvcs/VM/CHIPS/archives/LH7A400/Touchscreen/Drivers/lh7a400_lcd_evb_touchscreen_driver.c-arc $
*
* Rev 1.4 Aug 20 2002 16:55:16 FergisJ
* Update for new priority_int_driver: uses bit-number not 1-in-bit-position.
*
* Rev 1.3 Jun 05 2002 17:59:38 MaysR
* Corrected errors in lcd_touchscreen_controller_disable function.
* Changed parameter passed to int_enable/disable_interrupt function for compatibility with priority driver.
*
* Rev 1.2 Jun 05 2002 16:59:58 KovitzP
* changed CORE_FIQ to ARM_FIQ
*
* Rev 1.1 Nov 20 2001 17:01:26 KovitzP
* Added block comments to all functions and improved
* comments. Corrected minor errors.
*
* Rev 1.0 Nov 19 2001 10:26:06 KovitzP
* Initial revision.
*
*
* COPYRIGHT (C) 2001 SHARP MICROELECTRONICS OF THE AMERICAS, INC.
* CAMAS, WA
*********************************************************************/
#include "lh7a400_lcd_evb_touchscreen_driver.h"
/*
A circular buffer (queue) is implemented from the array ts_q and
the array indicies front and back. Data goes into the queue at
ts_q[back] and is read from the queue at ts_q[front]. The queue is
empty if front == back (one array location is wasted).
*/
static LCD_TS_STATE ts_q[TS_Q_LENGTH];
static INT_32 front = 0, back = 0;
/**********************************************************************
*
* Function: lcd_touchscreen_q_empty
*
* Purpose:
* Return true if the touchscreen controller driver's software queue
* contains no pen state and coordinate structures. Poll this function
* to see if any data are available.
*
* Processing:
* return front == back
*
* Parameters: None
*
* Outputs: None
*
* Returns:
* 0 if the queue contains data
* 1 if the queue is empty
*
* Notes:
*
**********************************************************************/
INT_32 lcd_touchscreen_q_empty(void)
{
return front == back;
}
/**********************************************************************
*
* Function: lcd_touchscreen_q_post
*
* Purpose:
* Add a touchscreen measurement to the touchscreen queue for later
* removal by lcd_touchscreen_q_accept()
*
* Processing:
* Check to make sure that adding data to the queue won't make the
* new value of back == front. If it will, the queue is already full,
* so return. Otherwise, ts_q[back] = point.
* back = (back + 1) % TS_Q_LENGTH
*
* Parameters:
* point: the data to add to the queue.
*
* Outputs: None
*
* Returns: Nothing
*
* Notes:
* If the queue is full, the function returns with no complaint;
* however, the data will not be enqueued.
*
**********************************************************************/
static void lcd_touchscreen_q_post(LCD_TS_STATE point)
{
INT_32 temp_back = back + 1;
if (temp_back >= TS_Q_LENGTH)
temp_back = 0;
if (temp_back == front)
return; /* queue is full */
ts_q[back] = point;
back = temp_back;
}
/**********************************************************************
*
* Function: lcd_touchscreen_q_accept
*
* Purpose:
* remove the next touchscreen pen state and coordinates structure
* from this driver's software queue and return it.
*
* Processing:
* Initialize an LCD_TS_STATE point structure to contain
* an illegal coordinate pair with pen down.
* If the queue is empty, return point. Otherwise, point
* is ts_q[front]. Increment front. If front is out of
* bounds for the ts_q[] array's length, then front = 0.
* Return point.
*
*
* Parameters: None
*
* Outputs: None
*
* Returns:
* an LCD_TS_STATE structure from the front of the queue.
* if the queue was empty, return with PEN_DOWN at an illegal
* coordinate pair
*
* Notes:
*
**********************************************************************/
LCD_TS_STATE lcd_touchscreen_q_accept(void)
{
LCD_TS_STATE point={TOUCHSCREEN_PEN_DOWN,
TOUCHSCREEN_ILLEGAL_COORDINATE,
TOUCHSCREEN_ILLEGAL_COORDINATE};
if (lcd_touchscreen_q_empty())
return point;
point = ts_q[front++];
if (front >= TS_Q_LENGTH)
front = 0;
return point;
}
/**********************************************************************
*
* Function: measurexy
*
* Purpose:
* Send enough commands to the touchscreen controller chip via the SSP
* to perform a differential measurement.
*
* Processing:
* Write commands to measure in the x direction twice followed by
* commands to measure in the y direction twice. During the first
* measurement in a given direction, the FET switches connect for
* that measurement. During the second measurement command in a
* given direction, the data will be used. See the function
* lcd_coordinate_read_handler().
*
* Parameters: None
*
* Outputs: None
*
* Returns: Nothing
*
* Notes:
* This function is not static because the pen down handler, an
* FIQ function coded in assembly language, needs to IMPORT this
* symbol during linking.
*
**********************************************************************/
void measurexy(void)
{
/* measure X twice */
ssp_transmit(LCD_TS_START | LCD_TS_DIFFERENTIAL
| LCD_TS_MEASURE_X | LCD_TS_POWER_ON);
ssp_transmit(LCD_TS_START | LCD_TS_DIFFERENTIAL
| LCD_TS_MEASURE_X | LCD_TS_POWER_ON);
/* measure Y twice and end in sleep mode*/
ssp_transmit(LCD_TS_START | LCD_TS_DIFFERENTIAL
| LCD_TS_MEASURE_Y | LCD_TS_POWER_ON);
ssp_transmit(LCD_TS_START | LCD_TS_DIFFERENTIAL
| LCD_TS_MEASURE_Y | LCD_TS_POWER_DOWN_PEN_IRQ);
}
/**********************************************************************
*
* Function: lcd_coordinate_read_handler
*
* Purpose:
* read a complete measurement from the SSP receive FIFO and
* start a new measurement if the pen is still down. This function
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -