rtouch.c File Reference

#include <stdint.h>
#include <stdbool.h>
#include "board.h"
#include "compiler.h"
#include "assert.h"
#include "gpio.h"
#include "intc.h"
#include "rtouch.h"
#include "conf_rtouch.h"
#include "adc.h"

Go to the source code of this file.

Data Structures

struct  rtouch_struct

Typedefs

typedef enum rtouch_state_enum rtouch_state_t

Enumerations

enum  rtouch_state_enum {
  RTOUCH_DISABLED, RTOUCH_NOT_TOUCHED, RTOUCH_READING_XL, RTOUCH_READING_XH,
  RTOUCH_READING_YL, RTOUCH_READING_YH, RTOUCH_PROCESSING, RTOUCH_TOUCHED
}
 Driver state names. More...

Functions

void rtouch_adc_int_handler (void)
 ADC conversion complete interrupt handler.
static void rtouch_clear_adc_flag (void)
static void rtouch_clear_detect_flag (void)
void rtouch_compute_calibration_matrix (rtouch_calibration_points_t const *points, rtouch_calibration_matrix_t *matrix)
 Compute a calibration matrix from three calibration points.
void rtouch_detect_int_handler (void)
 Low-level detect interrupt handler.
void rtouch_disable (void)
 Disable driver.
static void rtouch_disable_adc_int (void)
 Disable interrupts for the touch channels.
static void rtouch_disable_detect_int (void)
static void rtouch_disable_pullup_on_y_surface (void)
 Remove pullups from Y lines.
void rtouch_enable (void)
 Enable driver.
static void rtouch_enable_adc_int (void)
 Enable interrupts for the touch channels.
static void rtouch_enable_detect_int (void)
static uint32_t rtouch_get_adc_value (void)
 Return last converted value.
void rtouch_get_calibration_matrix (rtouch_calibration_matrix_t *destination)
 Get the current calibration matrix.
void rtouch_get_event (rtouch_event_t *event)
 Get last event.
rtouch_event_handler_t rtouch_get_event_handler (void)
 Get current event handler.
static void rtouch_gradient_x_surface (void)
 Drive voltage gradient on X surface (XL=GND, XH=VDD).
static void rtouch_gradient_y_surface (void)
 Drive voltage gradient on Y surface (YL=GND, YH=VDD).
void rtouch_ground_x_surface (void)
 Drive X lines to ground.
void rtouch_ground_y_surface (void)
 Drive Y lines to ground.
void rtouch_init (void)
 Initialize touch panel driver.
bool rtouch_is_detect (void)
 Test if a touch is detected.
bool rtouch_is_touched (void)
 True if touched.
static void rtouch_prepare_adc (void)
 Prepare ADC for touch measuring.
static void rtouch_prepare_detect (void)
 Prepare the rtouch detect function.
static void rtouch_process_samples (void)
 Called from soft IRQ or ADC ISR to compute coordinates from raw samples.
static void rtouch_pullup_y_surface (void)
static void rtouch_resample (void)
 Called from rtouch_process_samples or from timer module to start a.
void rtouch_set_calibration_matrix (rtouch_calibration_matrix_t const *source)
 Assign a calibration matrix to the driver.
void rtouch_set_event_handler (rtouch_event_handler_t handler)
 Set new event handler.
static void rtouch_start_read (uint32_t channel)
static void rtouch_tristate_x_surface (void)
static void rtouch_tristate_y_surface (void)

Variables

static struct rtouch_struct rtouch
static const gpio_map_t rtouch_gpio_xmap
static const gpio_map_t rtouch_gpio_ymap


Typedef Documentation


Enumeration Type Documentation

Driver state names.

Enumerator:
RTOUCH_DISABLED  Driver is disabled, no sampling will occur.
RTOUCH_NOT_TOUCHED  Driver enabled, but panel not touched.
RTOUCH_READING_XL  Waiting for XL line sample.
RTOUCH_READING_XH  Waiting for XH line sample.
RTOUCH_READING_YL  Waiting for YL line sample.
RTOUCH_READING_YH  Waiting for YH line sample.
RTOUCH_PROCESSING  Waiting for sample processing.
RTOUCH_TOUCHED  Panel is currently touched.

Definition at line 40 of file rtouch.c.


Function Documentation

void rtouch_adc_int_handler ( void   ) 

ADC conversion complete interrupt handler.

This interrupt handler is called repeatedly as multiple samples are taken from all touch panel lines in proper order. When all samples have been taken, the ISR defers further handling to the TOUCH_ProcessSamples() function, either through a soft IRQ or directly within interrupt domain, depending on the TOUCH_USE_SOFTIRQ setting from "config_touch.h".

Definition at line 894 of file rtouch.c.

References rtouch_struct::rawX, rtouch_struct::rawY, rtouch, RTOUCH_ADC, RTOUCH_ADC_XH_CHANNEL, RTOUCH_ADC_XL_CHANNEL, RTOUCH_ADC_YH_CHANNEL, RTOUCH_ADC_YL_CHANNEL, rtouch_get_adc_value(), rtouch_gradient_x_surface(), rtouch_ground_x_surface(), RTOUCH_OVERSAMPLING, rtouch_process_samples(), RTOUCH_PROCESSING, rtouch_pullup_y_surface(), RTOUCH_READING_XH, RTOUCH_READING_XL, RTOUCH_READING_YH, RTOUCH_READING_YL, rtouch_start_read(), rtouch_tristate_y_surface(), and rtouch_struct::state.

Referenced by rtouch_prepare_adc().

00895 {
00896     static uint8_t sample_count = 0;
00897 
00898 #ifdef AVR32_ADCIFA_100_H_INCLUDED
00899     volatile avr32_adcifa_t *adcifa = &RTOUCH_ADC;
00900     adcifa->scr = 0x1;
00901 #endif
00902     switch (rtouch.state) {
00903 
00904     case RTOUCH_READING_XL:
00905         // Store the raw sample value for later.
00906         rtouch.rawY += rtouch_get_adc_value();
00907 
00908         // Change state and start ADC reading of XH
00909         // when enough samples have been taken.
00910         ++sample_count;
00911         if (sample_count < RTOUCH_OVERSAMPLING) {
00912             rtouch_start_read(RTOUCH_ADC_XL_CHANNEL);
00913         } else {
00914             sample_count = 0;
00915 
00916             rtouch.state = RTOUCH_READING_XH;
00917             rtouch_start_read(RTOUCH_ADC_XH_CHANNEL);
00918         }
00919 
00920         break;
00921 
00922 
00923     case RTOUCH_READING_XH:
00924         // Add XL and XH samples to form a raw Y position reading.
00925         rtouch.rawY += rtouch_get_adc_value();
00926 
00927         // Change state and start ADC reading of X position from YL line
00928         // when enough samples have been taken.
00929         ++sample_count;
00930         if (sample_count < RTOUCH_OVERSAMPLING) {
00931             rtouch_start_read(RTOUCH_ADC_XH_CHANNEL);
00932         } else {
00933             sample_count = 0;
00934 
00935             rtouch.state = RTOUCH_READING_YL;
00936             rtouch_tristate_y_surface();
00937             rtouch_gradient_x_surface();
00938             rtouch_start_read(RTOUCH_ADC_YL_CHANNEL);
00939         }
00940 
00941         break;
00942 
00943 
00944     case RTOUCH_READING_YL:
00945         // Store the raw sample for later.
00946         rtouch.rawX += rtouch_get_adc_value();
00947 
00948         // Change state and start ADC reading of YH
00949         // when enough samples have been taken.
00950         ++sample_count;
00951         if (sample_count < RTOUCH_OVERSAMPLING) {
00952             rtouch_start_read(RTOUCH_ADC_YL_CHANNEL);
00953         } else {
00954             sample_count = 0;
00955 
00956             rtouch.state = RTOUCH_READING_YH;
00957             rtouch_start_read(RTOUCH_ADC_YH_CHANNEL);
00958         }
00959         break;
00960 
00961 
00962     case RTOUCH_READING_YH:
00963         // Add YL and YH samples to form a raw X reading.
00964         rtouch.rawX += rtouch_get_adc_value();
00965 
00966         // Configure for detect again
00967         // when enough samples have been taken.
00968         ++sample_count;
00969         if (sample_count < RTOUCH_OVERSAMPLING) {
00970             rtouch_start_read(RTOUCH_ADC_YH_CHANNEL);
00971         } else {
00972             sample_count = 0;
00973 
00974             //SLEEPMGR_Unlock( TOUCH_SAMPLE_SLEEP_MODE );
00975 
00976             //prepare for touch detection
00977             rtouch_ground_x_surface();
00978             rtouch_pullup_y_surface();
00979 
00980             rtouch.state = RTOUCH_PROCESSING;
00981 
00982             // The processing of sample or lack of touch is
00983             // deferred to the bottom half of the driver.
00984 #if (TOUCH_USE_SOFTIRQ == 1)
00985             //SOFTIRQ_Raise( TOUCH_SAMPLE_IRQ );
00986 #else
00987             rtouch_process_samples();
00988 #endif
00989         }
00990 
00991         break;
00992 
00993 
00994     default:
00995         assert(0); // Always fail on illegal state.
00996         break;
00997     }
00998 }

static void rtouch_clear_adc_flag ( void   )  [static]

Definition at line 440 of file rtouch.c.

Referenced by rtouch_enable().

00441 {
00442 }

static void rtouch_clear_detect_flag ( void   )  [inline, static]

Definition at line 147 of file rtouch.c.

References rtouch_gpio_ymap.

Referenced by rtouch_enable(), rtouch_process_samples(), and rtouch_resample().

00148 {
00149     gpio_clear_pin_interrupt_flag(rtouch_gpio_ymap[0].pin);
00150     //gpio_clear_pin_interrupt_flag(rtouch_gpio_ymap[1].pin);
00151 }

void rtouch_compute_calibration_matrix ( rtouch_calibration_points_t const *  points,
rtouch_calibration_matrix_t matrix 
)

Compute a calibration matrix from three calibration points.

This function computes a calibration matrix from a set of three calibration points povided by the caller. Use the raw sample values from the event struct when filling data into the calibration point struct. The calibration matrix will be copied into the struct also provided by the user. Use the TOUCH_SetCalibrationMatrix() function to assign a calibration matrix to the driver.

Parameters:
points Pointer to a calibration point set.
matrix Pointer to the struct where the matrix will be copied.

Definition at line 589 of file rtouch.c.

References rtouch_calibration_matrix_struct::A, rtouch_calibration_matrix_struct::B, rtouch_calibration_matrix_struct::C, rtouch_calibration_matrix_struct::D, rtouch_calibration_matrix_struct::E, rtouch_calibration_matrix_struct::F, rtouch_calibration_matrix_struct::K, rtouch_calibration_point_struct::panelX, rtouch_calibration_point_struct::panelY, rtouch_calibration_points_struct::point1, rtouch_calibration_points_struct::point2, rtouch_calibration_points_struct::point3, rtouch_calibration_point_struct::rawX, and rtouch_calibration_point_struct::rawY.

Referenced by rtouch_calibrate().

00592 {
00593     // Reference: http://www.embedded.com/story/OEG20020529S0046
00594 
00595     // Local copies of touch readings.
00596     int32_t Xr0 = points->point1.rawX;
00597     int32_t Yr0 = points->point1.rawY;
00598     int32_t Xr1 = points->point2.rawX;
00599     int32_t Yr1 = points->point2.rawY;
00600     int32_t Xr2 = points->point3.rawX;
00601     int32_t Yr2 = points->point3.rawY;
00602 
00603     // Local copies of display coordinates.
00604     int32_t Xp0 = points->point1.panelX;
00605     int32_t Yp0 = points->point1.panelY;
00606     int32_t Xp1 = points->point2.panelX;
00607     int32_t Yp1 = points->point2.panelY;
00608     int32_t Xp2 = points->point3.panelX;
00609     int32_t Yp2 = points->point3.panelY;
00610 
00611     // Compute coefficients for X calibration.
00612     matrix->A = ((Xp0 - Xp2) * (Yr1 - Yr2)) - ((Xp1 - Xp2) * (Yr0 - Yr2));
00613     matrix->B = ((Xr0 - Xr2) * (Xp1 - Xp2)) - ((Xp0 - Xp2) * (Xr1 - Xr2));
00614     matrix->C =
00615         Yr0 * ((Xr2 * Xp1) - (Xr1 * Xp2)) +
00616         Yr1 * ((Xr0 * Xp2) - (Xr2 * Xp0)) +
00617         Yr2 * ((Xr1 * Xp0) - (Xr0 * Xp1));
00618 
00619     // Compute coefficients for X calibration.
00620     matrix->D = ((Yp0 - Yp2) * (Yr1 - Yr2)) - ((Yp1 - Yp2) * (Yr0 - Yr2));
00621     matrix->E = ((Xr0 - Xr2) * (Yp1 - Yp2)) - ((Yp0 - Yp2) * (Xr1 - Xr2));
00622     matrix->F =
00623         Yr0 * ((Xr2 * Yp1) - (Xr1 * Yp2)) +
00624         Yr1 * ((Xr0 * Yp2) - (Xr2 * Yp0)) +
00625         Yr2 * ((Xr1 * Yp0) - (Xr0 * Yp1));
00626 
00627     // Compute common denominator.
00628     matrix->K = ((Xr0 - Xr2) * (Yr1 - Yr2)) - ((Xr1 - Xr2) * (Yr0 - Yr2));
00629 }

void rtouch_detect_int_handler ( void   ) 

Low-level detect interrupt handler.

This interrupt handler is called when a low level on the YL/YH lines is detected, which means the panel is touched. The driver sets up and starts a sample of the XL line, and defers further handling to the ADC interrupt.

Definition at line 855 of file rtouch.c.

References rtouch_struct::rawX, rtouch_struct::rawY, rtouch, RTOUCH_ADC_XL_CHANNEL, rtouch_disable_detect_int(), rtouch_gradient_y_surface(), RTOUCH_NOT_TOUCHED, RTOUCH_READING_XL, rtouch_start_read(), RTOUCH_TOUCHED, rtouch_tristate_x_surface(), and rtouch_struct::state.

Referenced by rtouch_prepare_detect().

00856 {
00857     // Change detection should only fire if previously untouched, or when
00858     // we need a resample while touched.
00859     assert( (rtouch.state == RTOUCH_NOT_TOUCHED) ||
00860         (rtouch.state == RTOUCH_TOUCHED) );
00861 
00862     // Keep change detection disabled until panel is not touched anymore.
00863     rtouch_disable_detect_int();
00864 
00865     // Clear accumulators.
00866     rtouch.rawX = 0;
00867     rtouch.rawY = 0;
00868 
00869     // Change state and start ADC reading of Y position from XL line.
00870     // ADC interrupt will take over further handling.
00871     rtouch.state = RTOUCH_READING_XL;
00872     rtouch_tristate_x_surface();
00873     rtouch_gradient_y_surface();
00874 
00875 
00876     rtouch_start_read(RTOUCH_ADC_XL_CHANNEL);
00877     //SLEEPMGR_Lock( TOUCH_SAMPLE_SLEEP_MODE );
00878 }

void rtouch_disable ( void   ) 

Disable driver.

This function disables the driver, stopping all touch detection and sampling. This will save power.

Definition at line 495 of file rtouch.c.

References rtouch, rtouch_disable_adc_int(), rtouch_disable_detect_int(), RTOUCH_DISABLED, rtouch_ground_x_surface(), rtouch_ground_y_surface(), and rtouch_struct::state.

Referenced by rtouch_init().

00496 {
00497     // Do not try to disable if already disabled. That will mess up the
00498     // sleep manager lock state.
00499     if (rtouch.state == RTOUCH_DISABLED) {
00500         return;
00501     }
00502 
00503     // Need this to be atomic, in case we are interrupting an ongoing sampling.
00504     //ENTER_CRITICAL_SECTION( DISABLE );
00505     // Shutdown driver.
00506     rtouch_disable_detect_int();
00507     rtouch_disable_adc_int();
00508     //LEAVE_CRITICAL_SECTION( DISABLE );
00509 
00510     // Continue shutdown.
00511     rtouch.state = RTOUCH_DISABLED;
00512 
00513     //SLEEPMGR_Unlock( TOUCH_DETECT_SLEEP_MODE );
00514 
00515     // Ground touch panel to save power.
00516     rtouch_ground_x_surface();
00517     rtouch_ground_y_surface();
00518 }

static void rtouch_disable_adc_int ( void   )  [inline, static]

Disable interrupts for the touch channels.

Definition at line 230 of file rtouch.c.

References RTOUCH_ADC, RTOUCH_ADC_XH_CHANNEL, RTOUCH_ADC_XL_CHANNEL, RTOUCH_ADC_YH_CHANNEL, and RTOUCH_ADC_YL_CHANNEL.

Referenced by rtouch_disable().

00231 {
00232 #ifdef AVR32_ADCIFA_100_H_INCLUDED
00233     volatile avr32_adcifa_t *adcifa = &RTOUCH_ADC;
00234   // Enable interrupt for sequencer 0.
00235   adcifa->idr = 0x1;
00236 #else
00237     volatile avr32_adc_t *adc = &RTOUCH_ADC;
00238     adc->idr = RTOUCH_ADC_XL_CHANNEL | RTOUCH_ADC_YL_CHANNEL
00239         | RTOUCH_ADC_XH_CHANNEL | RTOUCH_ADC_YH_CHANNEL;
00240 #endif
00241 }

static void rtouch_disable_detect_int ( void   )  [inline, static]

Definition at line 153 of file rtouch.c.

References rtouch_gpio_ymap.

Referenced by rtouch_detect_int_handler(), and rtouch_disable().

00154 {
00155     // disable interrupt for Y lines
00156     // clear the pin interrupt, or otherwise it will trigger when
00157     //enabled again
00158     gpio_clear_pin_interrupt_flag(rtouch_gpio_ymap[0].pin);
00159     gpio_disable_pin_interrupt(rtouch_gpio_ymap[0].pin);
00160 }

static void rtouch_disable_pullup_on_y_surface ( void   )  [inline, static]

Remove pullups from Y lines.

Definition at line 315 of file rtouch.c.

References rtouch_gpio_ymap.

00316 {
00317     gpio_disable_pin_pull_up(rtouch_gpio_ymap[0].pin);
00318     gpio_disable_pin_pull_up(rtouch_gpio_ymap[1].pin);
00319 
00320 }

void rtouch_enable ( void   ) 

Enable driver.

This function enables the driver, resuming touch detecting and sampling.

Definition at line 524 of file rtouch.c.

References rtouch_struct::last_event, rtouch, rtouch_clear_adc_flag(), rtouch_clear_detect_flag(), RTOUCH_DISABLED, rtouch_enable_adc_int(), rtouch_enable_detect_int(), rtouch_ground_x_surface(), RTOUCH_NO_EVENT, RTOUCH_NOT_TOUCHED, rtouch_pullup_y_surface(), rtouch_struct::state, and rtouch_event_struct::type.

Referenced by main().

00525 {
00526     // Do not try to enable if already enabled. That will mess up the
00527     // sleep manager lock state.
00528     if (rtouch.state != RTOUCH_DISABLED) {
00529         return;
00530     }
00531 
00532     // Setup panel for touch detection.
00533     rtouch_ground_x_surface();
00534     rtouch_pullup_y_surface();
00535 
00536     // Initial state is untouched, but if touched, the change detect ISR
00537     // will fire immediately.
00538     rtouch.state = RTOUCH_NOT_TOUCHED;
00539     rtouch.last_event.type = RTOUCH_NO_EVENT;
00540 
00541     // Start driver.
00542     //SLEEPMGR_Lock( TOUCH_DETECT_SLEEP_MODE );
00543     rtouch_clear_adc_flag();
00544     rtouch_enable_adc_int();
00545 
00546     rtouch_clear_detect_flag();
00547     rtouch_enable_detect_int();
00548 }

static void rtouch_enable_adc_int ( void   )  [inline, static]

Enable interrupts for the touch channels.

Definition at line 215 of file rtouch.c.

References RTOUCH_ADC, RTOUCH_ADC_XH_CHANNEL, RTOUCH_ADC_XL_CHANNEL, RTOUCH_ADC_YH_CHANNEL, and RTOUCH_ADC_YL_CHANNEL.

Referenced by rtouch_enable().

00216 {
00217 #ifdef AVR32_ADCIFA_100_H_INCLUDED
00218     volatile avr32_adcifa_t *adcifa = &RTOUCH_ADC;
00219   // Enable interrupt for sequencer 0.
00220   adcifa->ier = 0x1;
00221 #else
00222     volatile avr32_adc_t *adc = &RTOUCH_ADC;
00223     adc->ier = RTOUCH_ADC_XL_CHANNEL | RTOUCH_ADC_YL_CHANNEL
00224         | RTOUCH_ADC_XH_CHANNEL | RTOUCH_ADC_YH_CHANNEL;
00225 #endif
00226 }

static void rtouch_enable_detect_int ( void   )  [inline, static]

Definition at line 140 of file rtouch.c.

References rtouch_gpio_ymap.

Referenced by rtouch_enable(), rtouch_process_samples(), and rtouch_resample().

00141 {
00142     //enable interrupt for Y lines
00143     gpio_enable_pin_interrupt(rtouch_gpio_ymap[0].pin, GPIO_FALLING_EDGE);
00144 
00145 }

static uint32_t rtouch_get_adc_value ( void   )  [inline, static]

Return last converted value.

Definition at line 420 of file rtouch.c.

References RTOUCH_ADC.

Referenced by rtouch_adc_int_handler().

00421 {
00422 #ifdef AVR32_ADCIFA_100_H_INCLUDED
00423     uint32_t value;
00424     
00425   if (s_current_channel < 8)
00426   {
00427     value = ADCIFA_read_resx_sequencer_0(0);
00428   }
00429   else
00430   {
00431     value = (~ADCIFA_read_resx_sequencer_0(0));            
00432   }  
00433     
00434   return value;
00435 #else
00436     volatile avr32_adc_t *adc = &RTOUCH_ADC;
00437     return adc->lcdr;
00438 #endif
00439 }

void rtouch_get_calibration_matrix ( rtouch_calibration_matrix_t destination  ) 

Get the current calibration matrix.

This function retrieves the current calibration matrix from the driver. Use this function to store a calibration matrix to e.g. EEPROM.

Parameters:
destination Pointer to struct where matrix will be copied.

Definition at line 649 of file rtouch.c.

References rtouch_struct::calibration_matrix, and rtouch.

00650 {
00651     destination = rtouch.calibration_matrix;
00652 }

void rtouch_get_event ( rtouch_event_t event  ) 

Get last event.

This function will copy the last event information to a struct. The caller is reponsible for providing memory.

Parameters:
event Pointer to the struct where event will be copied.

Definition at line 557 of file rtouch.c.

References rtouch_struct::last_event, and rtouch.

Referenced by rtouch_calibrate().

00558 {
00559     *event = rtouch.last_event;
00560 }

rtouch_event_handler_t rtouch_get_event_handler ( void   ) 

Get current event handler.

This function returns the old event handler. Use this to store the old handler while replacing it for a short while, e.g. for calibration.

Returns:
Current event handler pointer.

Definition at line 678 of file rtouch.c.

References rtouch_struct::event_handler, and rtouch.

Referenced by rtouch_calibrate().

00679 {
00680     return rtouch.event_handler;
00681 }

static void rtouch_gradient_x_surface ( void   )  [inline, static]

Drive voltage gradient on X surface (XL=GND, XH=VDD).

Definition at line 324 of file rtouch.c.

References rtouch_gpio_xmap.

Referenced by rtouch_adc_int_handler().

00325 {
00326     // control pins by gpio controller
00327     gpio_enable_gpio(rtouch_gpio_xmap,
00328         sizeof(rtouch_gpio_xmap)/ sizeof(rtouch_gpio_xmap[0]));
00329     gpio_disable_pin_pull_up(rtouch_gpio_xmap[0].pin);
00330     gpio_disable_pin_pull_up(rtouch_gpio_xmap[1].pin);
00331 
00332     gpio_clr_gpio_pin(rtouch_gpio_xmap[0].pin);
00333     gpio_set_gpio_pin(rtouch_gpio_xmap[1].pin);
00334 }

static void rtouch_gradient_y_surface ( void   )  [inline, static]

Drive voltage gradient on Y surface (YL=GND, YH=VDD).

Definition at line 338 of file rtouch.c.

References rtouch_gpio_ymap.

Referenced by rtouch_detect_int_handler(), and rtouch_resample().

00339 {
00340     // control pins by gpio controller
00341     gpio_enable_gpio(rtouch_gpio_ymap,
00342         sizeof(rtouch_gpio_ymap)/ sizeof(rtouch_gpio_ymap[0]));
00343     gpio_disable_pin_pull_up(rtouch_gpio_ymap[0].pin);
00344     gpio_disable_pin_pull_up(rtouch_gpio_ymap[1].pin);
00345     gpio_clr_gpio_pin(rtouch_gpio_ymap[0].pin);
00346     gpio_set_gpio_pin(rtouch_gpio_ymap[1].pin);
00347 }

void rtouch_ground_x_surface ( void   )  [inline]

Drive X lines to ground.

Definition at line 264 of file rtouch.c.

References rtouch_gpio_xmap.

Referenced by rtouch_adc_int_handler(), rtouch_disable(), and rtouch_enable().

00265 {
00266     // control pins by gpio controller
00267     //gpio_enable_gpio(rtouch_gpio_xmap,
00268     //  sizeof(rtouch_gpio_xmap)/ sizeof(rtouch_gpio_xmap[0]));
00269 
00270     // enable pins as gpio (sets as input)
00271     // to avoid a spike due to a Y-surface that is tristatet and
00272     // X-surface that was gradiented we need to set XH as input first.
00273     // Otherwise the voltage on the signal line will rise to VDD. This is
00274     // not an issue to the measurement but it helps to let the signal look
00275     // nice and thus we perhaps improve the EMI a bit.
00276     gpio_enable_gpio_pin(rtouch_gpio_xmap[1].pin);
00277     gpio_enable_gpio_pin(rtouch_gpio_xmap[0].pin);
00278 
00279     // set ouput low
00280     gpio_clr_gpio_pin(rtouch_gpio_xmap[1].pin);
00281     gpio_clr_gpio_pin(rtouch_gpio_xmap[0].pin);
00282 }

void rtouch_ground_y_surface ( void   )  [inline]

Drive Y lines to ground.

Definition at line 286 of file rtouch.c.

References rtouch_gpio_ymap.

Referenced by rtouch_disable().

00287 {
00288     // control pins by gpio controller
00289     //gpio_enable_gpio(rtouch_gpio_ymap,
00290     //  sizeof(rtouch_gpio_ymap)/ sizeof(rtouch_gpio_ymap[0]));
00291 
00292     gpio_enable_gpio_pin(rtouch_gpio_ymap[1].pin);
00293     gpio_enable_gpio_pin(rtouch_gpio_ymap[0].pin);
00294     // set ouput low
00295     gpio_clr_gpio_pin(rtouch_gpio_ymap[0].pin);
00296     gpio_clr_gpio_pin(rtouch_gpio_ymap[1].pin);
00297 }

void rtouch_init ( void   ) 

Initialize touch panel driver.

This function initializes all peripherals required to detect a touch and sample its position on a resistive touch panel. Call this function before using any other features of this driver.

The driver is disabled initially, so you must call TOUCH_Enable() before any touch events will be detected.

Definition at line 453 of file rtouch.c.

References rtouch_struct::event_handler, rtouch_struct::last_event, rtouch, rtouch_disable(), RTOUCH_NO_EVENT, RTOUCH_NOT_TOUCHED, rtouch_prepare_adc(), rtouch_prepare_detect(), rtouch_struct::state, TOUCH_SAMPLE_IRQ, and rtouch_event_struct::type.

Referenced by main().

00454 {
00455     // Start with no event handler.
00456     rtouch.event_handler = NULL;
00457 
00458 #ifdef AVR32_ADCIFA_100_H_INCLUDED
00459   // GPIO pin/adc-function map.
00460   static const gpio_map_t ADCIFA_GPIO_MAP =
00461   {
00462     {AVR32_ADCREF0_PIN,AVR32_ADCREF0_FUNCTION},
00463     {AVR32_ADCREFP_PIN,AVR32_ADCREFP_FUNCTION},
00464     {AVR32_ADCREFN_PIN,AVR32_ADCREFN_FUNCTION}
00465   };
00466   gpio_enable_module(ADCIFA_GPIO_MAP, sizeof(ADCIFA_GPIO_MAP) / sizeof(ADCIFA_GPIO_MAP[0]));
00467 #endif
00468 
00469     // Prepare required peripherals.
00470     rtouch_prepare_adc();
00471     rtouch_prepare_detect();
00472 
00473 #if (TOUCH_USE_SOFTIRQ == 1)
00474     // Use a soft IRQ for bottom half of driver.
00475     SOFTIRQ_SetHandler( TOUCH_SAMPLE_IRQ, TOUCH_ProcessSamples );
00476     SOFTIRQ_Enable( TOUCH_SAMPLE_IRQ );
00477 #endif
00478 
00479     // TOUCH_Disable() will take care of the rest of the initialization.
00480     // We need to lock the sleep mode, and set a non-disable state for the
00481     // driver, since TOUCH_Disable() will unlock the sleep mode, and also
00482     // check that the driver is not disabled already.
00483 
00484     //SLEEPMGR_Lock( TOUCH_DETECT_SLEEP_MODE );
00485     rtouch.state = RTOUCH_NOT_TOUCHED;
00486     rtouch.last_event.type = RTOUCH_NO_EVENT;
00487     rtouch_disable();
00488 }

bool rtouch_is_detect ( void   )  [inline]

Test if a touch is detected.

Checks if one of the Y lines is pulled low due to a touch on the surface. The Y lines must be pulled up and the X lines must be GND in order to work.

return True if a touch is detected and false if no touch is detected.

Definition at line 250 of file rtouch.c.

References rtouch_gpio_ymap.

Referenced by rtouch_process_samples(), and rtouch_resample().

00251 {
00252     // check if one of the Y lines is pulled low
00253     if( !gpio_get_pin_value(rtouch_gpio_ymap[0].pin)
00254         || !gpio_get_pin_value(rtouch_gpio_ymap[1].pin))
00255     {
00256         return true;
00257     }
00258     else
00259         return false;
00260 }

bool rtouch_is_touched ( void   ) 

True if touched.

This function returns true if the touch panel is currently touched.

Returns:
True if panel touched.

Definition at line 568 of file rtouch.c.

References rtouch_struct::last_event, rtouch, RTOUCH_MOVE, RTOUCH_PRESS, and rtouch_event_struct::type.

Referenced by rtouch_calibrate().

00569 {
00570     bool is_touched = (rtouch.last_event.type == RTOUCH_PRESS)
00571         || (rtouch.last_event.type == RTOUCH_MOVE);
00572 
00573     return is_touched;
00574 }

static void rtouch_prepare_adc ( void   )  [inline, static]

Prepare ADC for touch measuring.

Register the interrupt handler, set sample, hold and startup time.

Definition at line 193 of file rtouch.c.

References RTOUCH_ADC, rtouch_adc_int_handler(), RTOUCH_ADC_INT_LEVEL, and RTOUCH_ADC_IRQ.

Referenced by rtouch_init().

00194 {
00195     Disable_global_interrupt();
00196     INTC_register_interrupt(&rtouch_adc_int_handler, RTOUCH_ADC_IRQ,
00197         RTOUCH_ADC_INT_LEVEL);
00198     Enable_global_interrupt();
00199 
00200 #ifdef AVR32_ADCIFA_100_H_INCLUDED
00201     volatile avr32_adcifa_t *adcifa = &RTOUCH_ADC;
00202   // configure ADCIFA
00203   adcifa_configure(adcifa, &adcifa_opt, FOSC0);
00204 #else
00205     volatile avr32_adc_t *adc = &RTOUCH_ADC;
00206     adc_configure(adc);
00207     // we need to lower the adc clock under 5MHz
00208     // adc_clock = adc_input_clock /((prescaler + 1)*2)
00209     adc->mr |= 0x1 << AVR32_ADC_MR_PRESCAL_OFFSET;
00210 #endif
00211 }

static void rtouch_prepare_detect ( void   )  [inline, static]

Prepare the rtouch detect function.

A touch can be detected by setting the Y lines (or X lines) as inputs and enabling the internal pull-ups for these pins. The other lines, X in this case are connected to GND. By a touch the Y lines will be pulled low and an interrupt can be triggered on a low level detect.

This function does the registering of the interrupt handler for the touch detect. Currently we use a GPIO interrupt, but here it is only possible to trigger on edges but actually we should trigger on a low level. Anyway this should work too. Here we use the YL line as source input for the edge detection but it is also possible to use YH.

Definition at line 132 of file rtouch.c.

References rtouch_detect_int_handler(), and rtouch_gpio_ymap.

Referenced by rtouch_init().

00133 {
00134     Disable_global_interrupt();
00135     INTC_register_interrupt(&rtouch_detect_int_handler,
00136         AVR32_GPIO_IRQ_0 + rtouch_gpio_ymap[0].pin/8, 0);
00137     Enable_global_interrupt();
00138 }

void rtouch_process_samples ( void   )  [static]

Called from soft IRQ or ADC ISR to compute coordinates from raw samples.

This function takes care of the final processing and calibration of the raw panel sample values, or lack of touch. This function is called by the ADC interrupt handler, either via the soft IRQ module or directly from the ISR, depending on the TOUCH_USE_SOFTIRQ setting from "config_touch.h".

This function will also automatically start a resample of the panel, either immediately or delayed via the timer module, depending on the TOUCH_USE_IMMEDIATE_RESAMPLE setting from "config_touch.h".

Definition at line 696 of file rtouch.c.

References rtouch_calibration_matrix_struct::A, rtouch_calibration_matrix_struct::B, rtouch_calibration_matrix_struct::C, rtouch_struct::calibration_matrix, rtouch_calibration_matrix_struct::D, rtouch_calibration_matrix_struct::E, rtouch_struct::event_handler, rtouch_calibration_matrix_struct::F, rtouch_calibration_matrix_struct::K, rtouch_struct::last_event, rtouch_event_struct::panelX, rtouch_event_struct::panelY, rtouch_event_struct::rawX, rtouch_struct::rawX, rtouch_event_struct::rawY, rtouch_struct::rawY, rtouch, rtouch_clear_detect_flag(), rtouch_enable_detect_int(), rtouch_is_detect(), RTOUCH_MOVE, RTOUCH_NO_EVENT, RTOUCH_NOT_TOUCHED, RTOUCH_PRESS, RTOUCH_RELEASE, rtouch_resample(), RTOUCH_SAMPLESCALE, RTOUCH_TOUCHED, rtouch_struct::state, and rtouch_event_struct::type.

Referenced by rtouch_adc_int_handler().

00697 {
00698     // Catch divide-by-zero, in case matrix is not initialized.
00699     // The calibrated values will be unusable anyway, so setting tempK to 1
00700     // is ok.
00701     int32_t tempK = rtouch.calibration_matrix->K;
00702     if (tempK == 0) {
00703         tempK = 1;
00704     }
00705 
00706     // Scale sample values down to 10 bit, to avoid matrix computing
00707     // overflow.
00708     // The extra 1 compensates for XL/XH and YL/YH being added together.
00709     rtouch.rawX >>= (RTOUCH_SAMPLESCALE + 1);
00710     rtouch.rawY >>= (RTOUCH_SAMPLESCALE + 1);
00711 
00712     // Compute calibrated X position.
00713     int32_t panelX =
00714         (rtouch.calibration_matrix->A * rtouch.rawX) +
00715         (rtouch.calibration_matrix->B * rtouch.rawY) +
00716         rtouch.calibration_matrix->C;
00717     panelX /= tempK;
00718 
00719     // Compute calibrated Y position.
00720     int32_t panelY =
00721         (rtouch.calibration_matrix->D * rtouch.rawX) +
00722         (rtouch.calibration_matrix->E * rtouch.rawY) +
00723         rtouch.calibration_matrix->F;
00724     panelY /= tempK;
00725 
00726     // Finished processing, so state is now "touched".
00727     rtouch.state = RTOUCH_TOUCHED;
00728 
00729     // If both YL and YH are high, the Y surface is not in contact
00730     // with the X surface anymore, so we change state.
00731     // This will happen if the release action happened while we
00732     // computed the panel coordinates.
00733     rtouch_clear_detect_flag();
00734     if (rtouch_is_detect() == false) {
00735         rtouch.state = RTOUCH_NOT_TOUCHED;
00736 
00737         // If the last event was "press" or "move",
00738         // we now have to send a "release" event.
00739         if ((rtouch.last_event.type == RTOUCH_PRESS) ||
00740             (rtouch.last_event.type == RTOUCH_MOVE))
00741         {
00742             rtouch.last_event.type = RTOUCH_RELEASE;
00743 
00744             // Call event handler if registered.
00745             if (rtouch.event_handler != NULL) {
00746                 rtouch.event_handler( &rtouch.last_event );
00747             }
00748         }
00749 
00750         // Enable detect ISR so that the next touch will be detected.
00751         rtouch_enable_detect_int();
00752     } else {
00753         // Any change since last time we sampled? Just touched?
00754         // Perhaps only moved?
00755         bool sendEvent = false;
00756 
00757         // If it _was_ released or no event at all, it's now touched.
00758         if ((rtouch.last_event.type == RTOUCH_NO_EVENT) ||
00759             (rtouch.last_event.type == RTOUCH_RELEASE))
00760         {
00761             rtouch.last_event.type = RTOUCH_PRESS;
00762             sendEvent = true;
00763         }
00764         // If this was not a new touch, was the "touch" moved then?
00765         else if ((rtouch.last_event.panelX != panelX) ||
00766                  (rtouch.last_event.panelY != panelY))
00767         {
00768             rtouch.last_event.type = RTOUCH_MOVE;
00769             sendEvent = true;
00770         }
00771 
00772         // Update coordinates and call event handler if something new
00773         // happened.
00774         if (sendEvent) {
00775             rtouch.last_event.rawX = rtouch.rawX;
00776             rtouch.last_event.rawY = rtouch.rawY;
00777             rtouch.last_event.panelX = panelX;
00778             rtouch.last_event.panelY = panelY;
00779 
00780             // Call event handler if registered.
00781             if (rtouch.event_handler != NULL) {
00782                 rtouch.event_handler( &rtouch.last_event );
00783             }
00784         }
00785 
00786 #if (TOUCH_USE_IMMEDIATE_RESAMPLE == 1)
00787         // Now, start an immediate resample, to keep up to date
00788         // with touch position.
00789         rtouch_resample();
00790 #else
00791 #  error "Delayed resample not implemented yet."
00792 #endif
00793     }
00794 }

static void rtouch_pullup_y_surface ( void   )  [inline, static]

Enable pull-ups for Y lines. Used to be able to trigger an interrupt upon a touch.

Definition at line 303 of file rtouch.c.

References rtouch_gpio_ymap.

Referenced by rtouch_adc_int_handler(), and rtouch_enable().

00304 {
00305     // control pins by gpio controller
00306     // this means implicitely: set as input
00307     gpio_enable_gpio(rtouch_gpio_ymap,
00308             sizeof(rtouch_gpio_ymap)/ sizeof(rtouch_gpio_ymap[0]));
00309     gpio_enable_pin_pull_up(rtouch_gpio_ymap[0].pin);
00310     gpio_enable_pin_pull_up(rtouch_gpio_ymap[1].pin);
00311 }

void rtouch_resample ( void   )  [static]

Called from rtouch_process_samples or from timer module to start a.

This function starts a new sampling of the touch panel. It will be called by the driver repeatedly as long as the touch panel stays touched.

Definition at line 801 of file rtouch.c.

References rtouch_struct::event_handler, rtouch_struct::last_event, rtouch_struct::rawX, rtouch_struct::rawY, rtouch, RTOUCH_ADC_XL_CHANNEL, rtouch_clear_detect_flag(), rtouch_enable_detect_int(), rtouch_gradient_y_surface(), rtouch_is_detect(), RTOUCH_NOT_TOUCHED, RTOUCH_READING_XL, RTOUCH_RELEASE, rtouch_start_read(), RTOUCH_TOUCHED, rtouch_tristate_x_surface(), rtouch_struct::state, and rtouch_event_struct::type.

Referenced by rtouch_process_samples().

00802 {
00803     // Resampling should only occur when panel is touched.
00804     assert(rtouch.state == RTOUCH_TOUCHED );
00805 
00806     // If both YL and YH are high, the Y surface is not in contact
00807     // with the X surface anymore, so we change state.
00808     rtouch_clear_detect_flag();
00809     if (rtouch_is_detect() == false) {
00810         // Update state.
00811         rtouch.state = RTOUCH_NOT_TOUCHED;
00812         rtouch.last_event.type = RTOUCH_RELEASE;
00813 
00814         // Call event handler, if registered.
00815         if (rtouch.event_handler != NULL) {
00816             rtouch.event_handler( &rtouch.last_event );
00817         }
00818         rtouch_enable_detect_int();
00819         return;
00820     }
00821 
00822     // Enable touch detection again. If the panel is still pressed, then the
00823     // detect ISR will fire immediately and start sampling.
00824     // TODO revisit since we can not trigger on low level interrupt, so we
00825     // have to think about something else here
00826     //rtouch_enable_detect_int();
00827     // Clear accumulators.
00828         rtouch.rawX = 0;
00829         rtouch.rawY = 0;
00830 
00831         // Change state and start ADC reading of Y position from XL line.
00832         // ADC interrupt will take over further handling.
00833         rtouch.state = RTOUCH_READING_XL;
00834         rtouch_gradient_y_surface();
00835         rtouch_tristate_x_surface();
00836 
00837         rtouch_start_read(RTOUCH_ADC_XL_CHANNEL);
00838 }

void rtouch_set_calibration_matrix ( rtouch_calibration_matrix_t const *  source  ) 

Assign a calibration matrix to the driver.

This function assigns a calibration matrix to the driver.

Parameters:
source Pointer to matrix data.

Definition at line 637 of file rtouch.c.

References rtouch_struct::calibration_matrix, and rtouch.

Referenced by rtouch_calibrate().

00638 {
00639     rtouch.calibration_matrix = (rtouch_calibration_matrix_t *)source;
00640 }

void rtouch_set_event_handler ( rtouch_event_handler_t  handler  ) 

Set new event handler.

This function sets a new touch event handler. The handler is called whenever the position or state of the touch screen changes. The handler is called from the TOUCH_ProcessSamples and TOUCH_Resample functions.

Parameters:
handler Pointer to new event handler, or NULL to disable handler.

Definition at line 662 of file rtouch.c.

References rtouch_struct::event_handler, and rtouch.

Referenced by main(), and rtouch_calibrate().

00663 {
00664     // This needs to be an atomic operation, in case an interrupt
00665     // fires while we change the handler.
00666     //ENTER_CRITICAL_SECTION( SET_HANDLER );
00667     rtouch.event_handler = handler;
00668     //LEAVE_CRITICAL_SECTION( SET_HANDLER );
00669 }

static void rtouch_start_read ( uint32_t  channel  )  [static]

Definition at line 386 of file rtouch.c.

References RTOUCH_ADC, RTOUCH_ADC_XH_CHANNEL, RTOUCH_ADC_XL_CHANNEL, RTOUCH_ADC_YH_CHANNEL, and RTOUCH_ADC_YL_CHANNEL.

Referenced by rtouch_adc_int_handler(), rtouch_detect_int_handler(), and rtouch_resample().

00387 {
00388 #ifdef AVR32_ADCIFA_100_H_INCLUDED
00389     volatile avr32_adcifa_t *adcifa = &RTOUCH_ADC;
00390   s_current_channel = channel;
00391   
00392   if (channel < 8)
00393   {
00394     adcifa_sequence_conversion_opt[0].channel_p = channel;                              // Positive Channel
00395     adcifa_sequence_conversion_opt[0].channel_n = AVR32_ADCIFA_INN_GNDANA;              // Negative Channel
00396     adcifa_sequence_conversion_opt[0].gain      = ADCIFA_SHG_1;                         // Gain of the conversion
00397   }
00398   else
00399   {
00400     adcifa_sequence_conversion_opt[0].channel_p = AVR32_ADCIFA_INP_GNDANA;              // Positive Channel
00401     adcifa_sequence_conversion_opt[0].channel_n = channel;                              // Negative Channel
00402     adcifa_sequence_conversion_opt[0].gain      = ADCIFA_SHG_1;                         // Gain of the conversion  
00403   }  
00404   adcifa_configure_sequencer(adcifa, 0, &adcifa_sequence_opt, adcifa_sequence_conversion_opt);
00405   
00406   adcifa_start_sequencer(adcifa, 0);
00407 #else
00408     volatile avr32_adc_t *adc = &RTOUCH_ADC;
00409     // disable all touch channels
00410     adc->chdr = RTOUCH_ADC_XL_CHANNEL | RTOUCH_ADC_YL_CHANNEL
00411         | RTOUCH_ADC_XH_CHANNEL | RTOUCH_ADC_YH_CHANNEL;
00412     // enable current touch channel
00413     adc->cher = channel;
00414     adc_start(adc);
00415 #endif
00416 }

static void rtouch_tristate_x_surface ( void   )  [inline, static]

Definition at line 349 of file rtouch.c.

References rtouch_gpio_xmap.

Referenced by rtouch_detect_int_handler(), and rtouch_resample().

00350 {
00351     // tristate by setting as input
00352     //gpio_enable_gpio(rtouch_gpio_xmap,
00353     //  sizeof(rtouch_gpio_xmap)/ sizeof(rtouch_gpio_xmap[0]));
00354 
00355     gpio_enable_gpio_pin(rtouch_gpio_xmap[1].pin);
00356     gpio_enable_gpio_pin(rtouch_gpio_xmap[0].pin);
00357 
00358 
00359     gpio_disable_pin_pull_up(rtouch_gpio_xmap[0].pin);
00360     gpio_disable_pin_pull_up(rtouch_gpio_xmap[1].pin);
00361     // enable ADC to control the pins
00362     gpio_enable_module(rtouch_gpio_xmap,
00363         sizeof(rtouch_gpio_xmap)/ sizeof(rtouch_gpio_xmap[0]));
00364 }

static void rtouch_tristate_y_surface ( void   )  [inline, static]

Definition at line 366 of file rtouch.c.

References rtouch_gpio_ymap.

Referenced by rtouch_adc_int_handler().

00367 {
00368     // tristate by setting as input
00369     //gpio_enable_gpio(rtouch_gpio_ymap,
00370     //  sizeof(rtouch_gpio_ymap)/ sizeof(rtouch_gpio_ymap[0]));
00371 
00372     gpio_enable_gpio_pin(rtouch_gpio_ymap[1].pin);
00373     gpio_enable_gpio_pin(rtouch_gpio_ymap[0].pin);
00374 
00375 
00376     gpio_disable_pin_pull_up(rtouch_gpio_ymap[0].pin);
00377     gpio_disable_pin_pull_up(rtouch_gpio_ymap[1].pin);
00378     // enable ADC to control the pins
00379     gpio_enable_module(rtouch_gpio_ymap,
00380         sizeof(rtouch_gpio_ymap)/ sizeof(rtouch_gpio_ymap[0]));
00381 }


Variable Documentation

struct rtouch_struct rtouch [static]

const gpio_map_t rtouch_gpio_xmap [static]

Initial value:

 {
    {
        .pin = RTOUCH_XL_PIN,
        .function = RTOUCH_XL_PIN_FUNCTION
    },
    {
        .pin = RTOUCH_XH_PIN,
        .function = RTOUCH_XH_PIN_FUNCTION
    }
}

Definition at line 84 of file rtouch.c.

Referenced by rtouch_gradient_x_surface(), rtouch_ground_x_surface(), and rtouch_tristate_x_surface().

const gpio_map_t rtouch_gpio_ymap [static]


Generated on Fri Feb 19 02:24:05 2010 for AVR32 - Resistive Driver by  doxygen 1.5.5