discoverpixy
touch.c
Go to the documentation of this file.
1 /**************************************************************************************************************************************
2 * Project: discoverpixy
3 * Website: https://github.com/t-moe/discoverpixy
4 * Authors: Aaron Schmocker, Timo Lang
5 * Institution: BFH Bern University of Applied Sciences
6 * File: common/touch/touch.c
7 *
8 * Version History:
9 * Date Autor Email SHA Changes
10 * 2015-04-27 timolang@gmail.com 259d446 Added touch support to emulator. Implemented basic touch function.
11 * 2015-05-02 timolang@gmail.com 3281616 Added some more touch functions. Improved pixy test. Drag the Image around!
12 * 2015-05-17 timolang@gmail.com 2d46336 Improved comments in implementation of button, checkbox, numupdown, tft, touch and screen modules/submodules.
13 * 2015-06-01 timolang@gmail.com 06227da Added calibrate screen (WIP). fixed bug in emulator drawing.
14 * 2015-06-01 timolang@gmail.com eb573bc Finalized calibration. Fixed a bug in screen module.
15 * 2015-06-06 timolang@gmail.com c06661d Fixed some outdated comments in source code. Documented Gui Module in docu.
16 *
17 **************************************************************************************************************************************/
18 
19 #include "touch.h"
20 #include "ll_touch.h"
21 #include "screen_calibrate.h"
22 #include <stdio.h>
23 
24 /* The idea is as follows:
25  * The user can add "touch-areas" which basically represent a rectangles on the screen.
26  * Once the user touches such a rectangle with the pen, we forward events to his provided callback.
27  * Touch events are provided to us from the low level implementation via touch_add_raw_event().
28  * We then need to check which touch areas are effected by that event
29  */
30 
31 /* Possible improvements:
32  * Exchange pointer-list "areas" with a linked list. This would ensure that we can always accept new regions
33  */
34 
35 #define NUM_AREAS 50 //Number of Touch Areas we can manage
36 TOUCH_AREA_STRUCT* areas[NUM_AREAS] = {NULL}; //list with pointers to all managed touch area's
37 
38 volatile POINT_STRUCT pos; //the last touch point
39 volatile TOUCH_STATE oldState = TOUCH_UP; //the last touch state
40 volatile bool calibration = false; //whether or not we're currently calibrating
41 
42 bool use_calibration = false; //Whether or not the current platform needs calibration and recalc of the values
43 
44 //Calibration parameters (dummy values).
45 int cal_xs = 10;
46 int cal_dx = 100;
47 int cal_ys = 10;
48 int cal_dy = 100;
49 
50 
51 void touch_set_calibration_values(int xs, int dx, int ys, int dy)
52 {
53  cal_xs = xs;
54  cal_ys = ys;
55  cal_dx = dx;
56  cal_dy = dy;
57 }
58 
59 
60 
61 bool touch_init()
62 {
63  return ll_touch_init();
64 }
65 
67 {
68  use_calibration = uc;
69 }
70 
71 
72 bool touch_add_raw_event(uint16_t touchX, uint16_t touchY, TOUCH_STATE state)
73 {
74  //Update current and old position/state
75  bool penDown = (state == TOUCH_DOWN);
76  bool oldPenDown = (oldState == TOUCH_DOWN);
77  oldState = state;
78 
79  if (calibration) { //If in Calibration mode
80  if (penDown) {
81  pos.x = touchX;
82  pos.y = touchY;
83  } else {
84  if (oldPenDown) { //Run only if we got at least one pen down
85  calibration = 0; //Calibration finish (Touch X and Y are the values from the last measure, where the pen was down)
86  }
87  }
88 
89  return true;
90  }
91 
92  //If we reach this point we're not in calibration mode and we need to process the event and call the registred handlers..
93 
94  if (use_calibration) { //the underlying touch hardware uses calibration
95  //Calculate the real touch position out of the passed ones, and the calibration values
96  pos.x = touchX = (((long)(DWIDTH - 2 * CCENTER) * 2 * (long)((long)touchX - cal_xs) / cal_dx + 1) >> 1) + CCENTER;
97  pos.y = touchY = (((long)(DHEIGHT - 2 * CCENTER) * 2 * (long)((long)touchY - cal_ys) / cal_dy + 1) >> 1) + CCENTER;
98  } else { //no conversion needed for the underlying hardware
99  pos.x = touchX;
100  pos.y = touchY;
101  }
102 
103  if (penDown) { //pen is down now
104  //tft_draw_pixel(touchX,touchY,WHITE);
105  if (!oldPenDown) { //pen wasn't down before (positive edge) => First Touch
106  for (int z = 0; z < NUM_AREAS; z++) { // For every touch area
107  //Check if pos is inside area
108  if (areas[z] != NULL && touchX >= areas[z]->x1 && touchX <= areas[z]->x2 && touchY >= areas[z]->y1 && touchY <= areas[z]->y2) {
109  areas[z]->flags = 1; //Save PenInside=1
110 
111  if (areas[z]->hookedActions & PEN_DOWN) { //The user wants to receive pen down events
112  areas[z]->callback(areas[z], PEN_DOWN); //Send event to user callback
113  }
114  }
115  }
116  } else { //Pen was down before => Second, Third event in row
117  for (int z = 0; z < NUM_AREAS; z++) { // For every touch area
118  if (areas[z] != NULL) {
119  //Check if pos is inside area
120  if (touchX >= areas[z]->x1 && touchX <= areas[z]->x2 && touchY >= areas[z]->y1 && touchY <= areas[z]->y2) {
121  if (areas[z]->flags == 0) { //Pen was not inside before (PenInside==0)
122  areas[z]->flags = 1; //Pen is inside now (PenInside=1)
123 
124  if (areas[z]->hookedActions & PEN_ENTER) { //The user wants to receive pen enter events
125  areas[z]->callback(areas[z], PEN_ENTER);
126  }
127  }
128  } else if (areas[z]->flags) { //Pos not inside area, but it was before (PenInside==1)
129  areas[z]->flags = 0; //Pen is no longer inside (PenInside=0)
130 
131  if (areas[z]->hookedActions & PEN_LEAVE) { //The user wants to receive pen leave events
132  areas[z]->callback(areas[z], PEN_LEAVE);
133  }
134  }
135  }
136  }
137  }
138 
139  for (int z = 0; z < NUM_AREAS; z++) { // For every touch area
140  if (areas[z] != NULL && (areas[z]->hookedActions & PEN_MOVE)) { //User want's to receive pen move events
141  //Check if pos is inside area
142  if (touchX >= areas[z]->x1 && touchX <= areas[z]->x2 && touchY >= areas[z]->y1 && touchY <= areas[z]->y2) {
143  areas[z]->callback(areas[z], PEN_MOVE);
144  }
145  }
146  }
147  } else { //pen is not down now
148  if (oldPenDown) { //but it was down before (negative edge)
149  for (int z = 0; z < NUM_AREAS; z++) { // For every touch area
150  //Check if pos is inside area
151  if (areas[z] != NULL && touchX >= areas[z]->x1 && touchX <= areas[z]->x2 && touchY >= areas[z]->y1 && touchY <= areas[z]->y2) {
152  areas[z]->flags = 0; //The pen is no longer inside (PenInside = 0);
153 
154  if (areas[z]->hookedActions & PEN_UP) { //user want's to receive pen up events
155  areas[z]->callback(areas[z], PEN_UP);
156  }
157  }
158  }
159  }
160  }
161 
162  return true;
163 }
164 
165 bool touch_have_empty(unsigned char num)
166 {
167  //go through pointer array and check for free spaces
168  for (unsigned char i = 0; i < NUM_AREAS; i++) {
169  if (areas[i] == NULL) {
170  num--; //a free space was found, we need one less
171  }
172 
173  if (num == 0) {
174  return true; //enough free spaces found
175  }
176  }
177 
178  return false; //not enough free spaces found
179 }
180 
182 {
183  //go through pointer array and check for free space
184  for (unsigned char i = 0; i < NUM_AREAS; i++) {
185  if (areas[i] == NULL) { //free space found
186  area->flags = 0; //we start with empty flags (PenInside=0)
187  areas[i] = area; //save pointer into list
188  return true;
189  }
190  }
191 
192  return false; //no free space found
193 }
194 
196 {
197  if (area == NULL) {
198  return;
199  }
200 
201  //go through pointer array and find the area to remove
202  for (unsigned char i = 0; i < NUM_AREAS; i++) {
203  if (areas[i] == area) { //area found in pointer array at pos i
204  areas[i] = NULL; //set pointer in list to NULL again
205  break;
206  }
207  }
208 }
209 
210 
212 {
213  return pos;
214 }
bool touch_register_area(TOUCH_AREA_STRUCT *area)
Definition: touch.c:181
Receive an event when the pen moves inside the region (pen is down)
Definition: touch.h:58
Receive an event when the pen goes down inside the region.
Definition: touch.h:54
#define CCENTER
Receive an event when the pen goes up inside the region.
Definition: touch.h:55
uint16_t y
The Y-Coordinate of the point.
Definition: touch.h:88
int cal_ys
Definition: touch.c:47
uint8_t flags
For internal use, don't change, don't initialize.
Definition: touch.h:79
uint16_t x
The X-Coordinate of the point.
Definition: touch.h:87
#define DHEIGHT
void touch_unregister_area(TOUCH_AREA_STRUCT *area)
Definition: touch.c:195
bool touch_add_raw_event(uint16_t touchX, uint16_t touchY, TOUCH_STATE state)
Definition: touch.c:72
The display is currently not touched.
Definition: touch.h:44
The display is currently touched at some point.
Definition: touch.h:45
static enum @0 state
volatile POINT_STRUCT pos
Definition: touch.c:38
volatile TOUCH_STATE oldState
Definition: touch.c:39
bool ll_touch_init()
TOUCH_CALLBACK callback
Callback which is executed when an event occurred in this Area.
Definition: touch.h:78
void touch_set_value_convert_mode(bool uc)
Definition: touch.c:66
#define NUM_AREAS
Definition: touch.c:35
Receive an event when the pen enters the region (pen was down before)
Definition: touch.h:56
POINT_STRUCT touch_get_last_point()
Definition: touch.c:211
volatile bool calibration
Definition: touch.c:40
bool use_calibration
Definition: touch.c:42
int cal_xs
Definition: touch.c:45
#define DWIDTH
TOUCH_AREA_STRUCT * areas[NUM_AREAS]
Definition: touch.c:36
TOUCH_STATE
Definition: touch.h:43
int cal_dy
Definition: touch.c:48
bool touch_have_empty(unsigned char num)
Definition: touch.c:165
void touch_set_calibration_values(int xs, int dx, int ys, int dy)
Definition: touch.c:51
int cal_dx
Definition: touch.c:46
bool touch_init()
Definition: touch.c:61
Receive an event when the pen leaves the region (pen was inside region before)
Definition: touch.h:57