In my experience, a touch screen needs to provide position updates to the higher-level software at a minimum 20Hz rate, or every 50ms. Faster is better, assuming the higher-level software can keep up, and we aren't too concerned with power usage. If the touch input response is much slower than this, there will be a noticeable and annoying lag between touch input by the user and visual response on the display.
The 20Hz update rate might not sound too challenging, but providing updates at 20Hz actually requires sampling at approximately 200Hz, depending on how many readings we are going to take before deciding we have a stable input. We need to oversample in order to debounce and average the touch input position values. Resistive touch screens, especially the inexpensive variety, are notoriously noisy and bouncy.
The driver needs to sample the input for each axis several times before sending a position update to the higher-level software. The provided drivers default to configuring ADC clocks on the respective processors for a minimum 200Hz (5ms) sampling rate. This allows the driver to sufficiently debounce and filter the incoming raw data and still provide a 20Hz true position update rate to the high-level user interface software.
For the Freescale i.MX processor the touch controller module is named the Analog Signal Processor (ASP). The processor provides two peripheral clocks that are derived by dividing the core CPU clock. The course input to the ASP block is PERCLK2 (Peripheral Clock 2), which can again be divided to produce the final input clock to the ASP. Note that PERCLK2 drives other sub-modules in addition to the ASP block, including the internal LCD controller, and therefore the touch driver cannot program PERCLK2 just for a good fit for touch sampling. PERCLK2 is programmed to the highest rate required by all attached peripherals, which in most cases would be the LCD controller, and further divided as required for the slower peripherals. The MC9328MX1 reference manual includes a table that specifies the clock programming values needed to achieve a 200Hz output data rate.
Hardware configuration for the Sharp LH79524 requires programming a few GPIO pins so that they are assigned to the ADC function, programming and enabling the ADC clock, and programming the ADC sequencer.
The LH79524 ADC is a full programmable state machine and sequencer that is quite an amazing bit of circuitry all by itself. The ADC can be programmed to drive one touch plane; delay; take a measurement; drive the opposite plane; delay; take a measurement, and so on all without any core CPU intervention whatsoever. Understanding how to program the LH79524 ADC Sequencer control banks could be a challenge but this is made much easier by an application note provided by Sharp (www.sharpsma.com). The provided driver precisely follows the recommendations of this application note regarding how to configure the Sharp ADC sequence controller.
Is the screen touched?
Once the basic hardware setup is complete, we need a reliable method to determine if the screen is touched. It makes no sense to run the ADC and get conversion readings if the user is not touching the screen. Both controllers provide a mechanism to detect if the screen is touched, and optionally to interrupt the main processor when a touch down event occurs. The driver function that determines if the screen is touched or not is named WaitForTouchState().
When the controller is in the touch detection mode the y-axis touch plane is tied high through a pull-up resister. The x-axis touch plane is tied to ground. When the user touches anywhere on the screen, the planes are shorted together and the y-axis plane is pulled low. This can be connected internally to an interrupt generation mechanism known as the PEN_DOWN IRQ.
During normal operation the drivers use the PEN_DOWN IRQ to wake up the touch driver task when a touch-down event occurs. This allows the driver task to block itself and not consume any CPU time when the screen is not touched and wake up and go into conversion mode once the user touches the screen. We can also save power by disabling the ADC clock while not in active conversion mode.
During calibration and active sampling the drivers use the same basic mechanism to detect a screen touch; however, in these modes the drivers mask the actual interrupt and simply check the touch status manually. For the Freescale processor, this requires programming the controller to touch detect mode and checking the PEN_DOWN IRQ bit. For the Sharp processor, touch detection is built into the ADC command sequence and no extra steps are required.
Reading touch data
During calibration and normal operation, we need a procedure to read and debounce the x- and y-axis raw data values and determine if we have a stable reading while the screen is touched. This procedure is named TouchScan() in both drivers. The outline of this procedure is:
- Check to see if the screen is touched.
- Take several raw readings on each axis for later filtering.
- Check to see if the screen is still touched.
While performing analog-to-digital conversions, both controllers provide means to program a delay between powering the touch planes and beginning an actual analog-to-digital conversion. Freescale calls this delay the
Data Setup Count (DSCNT), and it's a number of ASP input clocks to delay after switching between planes. Sharp calls this the
pre-charge delay.
In either case this time delay is needed because the resistive touch panel is two large conductors separated by a thin insulator, which is the textbook definition of a capacitor. A delay is required when switching which plane we're powering and from which plane we'll perform an analog-to-digital conversion to allow this capacitor to settle to steady state.
For the Freescale i.MX1 processor, once we initiate conversions the data produced by the ADC is stored in a 16-bit wide by 12-entry deep FIFO. The ADC produces 9-bit unsigned results, so the upper seven bits of each 16-bit entry are discarded. This means the full-scale data range of this touch controller is 0 to 511, although in reality no ADC or resistive touch screen produces results near the limit values.
We can program the processor to generate an interrupt when the FIFO has any data available or program to interrupt when the input FIFO is full. Since we always want to take multiple readings, the driver programs the FIFO to interrupt when full. When this interrupt occurs, we have 12 raw analog-to-digital conversions ready for processing, corresponding to six readings for the x-axis and six readings for the y-axis.
The Sharp LH79524 processor allows us to program a precise sequence of steps to complete before generating an interrupt. As each step is performed, results are likewise stored in an input FIFO to be retrieved by our driver software. Results are stored as 16-bit values. The most significant 10 bits of each result are the analog-to-digital conversion value, and the least significant four bits are the sequence index. The 10-bit conversion result means that this touch controller has a full-scale range of 0 to 1,023 counts, although again you will never observe results exactly at the limit values.
Once the sequencer control words are programmed on the LH79524, all the driver needs to do to acquire raw readings is command the sequencer to go. When the EOS (End Of Sequence) interrupt is generated, our results are ready to be picked up and examined. The sequencer can be configured to trigger automatically when the screen is touched, trigger on software command, or trigger continuously.
Be aware that there will always be some noise and variation in raw converter readings; this is normal. You'd be hard-pressed to take two consecutive readings on a resistive touch screen and get back identical 9-bit or 10-bit raw data values. You will find however that as the stylus or finger enters or leaves the touch screen, the readings vary much more than if you are holding steady pressure. Remember that the user is mechanically connecting together two flat resistors, the touch planes. Some small amount of time will pass during which the electrical connection between the two planes is marginal, as the user presses and releases the touch panel. We need to reject these readings until the system stabilizes, otherwise our reported touch position will jump about wildly and the higher level software will not act appropriately.
There is an unavoidable tradeoff here. If we require a narrow stability window, the driver won't be able to track fast "drag" operations. This is important for things like scrolling or pen-tracking during signature input. If we widen the stability window, we run the risk of accepting touch values that are inaccurate and the result of the marginal plane connection described above. You will need to experiment to determine the best values to use on your system. Intelligent touch controllers likewise allow you to tune these parameters via software commands.
The number of readings to take for each sample, the allowable variation in consecutive readings, and the speed at which samples are taken are all progammable parameters of each driver. These parameters can be adjusted via #defines to produce the best results on your system. An intelligent external touch controller will often take dozens or hundreds of readings at a very fast rate for improved accuracy. Since we are doing this filtering using our core CPU, we need to decide how much time we can reasonably afford to spend in our touch-sampling task. Embedded systems involve tradeoffs, and it's your job to make good compromises to produce a system your user is happy with.
As a sort of game, I like to test the commercial touch systems I run into in daily life. The next time you sign for a purchase or package using a touch screen, try flailing away with fast broad pen movements. Watch the result and see how well the screen tracks your movements. If you see nice smooth tracking, you know the driver is sampling pretty fast, probably 200Hz or more. Often you will observe your strokes turned into straight lines (slow sampling) or missed entirely (rejected input due to large value changes). Try not to shout "yee haa" while you're performing this little test in a retail store or you might get some strange looks. Normal people just don't understand what excites engineers.
Calibration
To this point we have been describing support functions of the drivers, the dirty work that has to be done and working before we can get to the cool stuff. Now that these functions are in place we're ready to actually ask the user to touch the screen.
Resistive touch screens require calibration. We need some reference values to be able to convert the raw A-to-D numbers we'ill receive into screen pixel coordinates required by the higher-level software. In an ideal case the calibration routine might be run once during initial product power-up testing, and the reference values saved to nonvolatile memory. I've organized the touch drivers to run the calibration routine once on entry, but keep in mind that you can save the reference values and not bother the user with calibration on subsequent power-up cycles. In any case you'll want to provide the user with a method of entering the calibration routine just in case the calibration becomes inaccurate due to temperature drift or other factors.
The calibration routine, named CalibrateTouchScreen(), is a simple step-by-step procedure that provides the user with a graphical target on the screen, asks the user to touch the target, and records the raw ADC readings for use later in our raw-data to pixel-position scaling routine. The graphical target and user prompts are displayed by using the Portable Embedded GUI (PEG) graphics software API, but this can be implemented using any similar graphics software.
In a perfect world we'd need only two sets (x and y) of raw values, the minimum and maximum values read at opposite corners of the screen. In reality many resistive touch screens are notably nonlinear, meaning that simply interpolating positions between the min and max values will yield a highly inaccurate driver.
By nonlinear, I mean that equidistant physical movements across the screen won't return equal increments in the raw data. Worse still, the value read for one axis, say the y-axis, might vary significantly even if we only change the x-axis touch position. To demonstrate this phenomenon I charted y-axis data readings as I moved a stylus across a typical resistive touch screen from left to right, keeping the y-axis position as constant as possible. You would reasonably expect the y-axis readings to remaining somewhat constant as we slide from left to right across the x-axis, but as Figure 3 shows this is not the case.
Figure 3: Y-axis variation with x-axis motion
[此贴子已经被作者于2007-07-18 10:37:04编辑过]