API changes for v1.0.0
[hackover2013-badge-firmware.git] / drivers / displays / tft / dialogues / alphanumeric.c
1 /**************************************************************************/
2 /*!
3 @file alphanumeric.c
4 @author K. Townsend (microBuilder.eu)
5
6 @brief Shows an alpha-numeric input dialogue
7
8 @section Example
9
10 @code
11 #include "drivers/displays/tft/dialogues/alphanumeric.h"
12
13 // Print results from an alpha-numeric dialogue
14 char* results = alphaShowDialogue();
15 printf("%s\r\n", results);
16
17 @endcode
18
19 @section LICENSE
20
21 Software License Agreement (BSD License)
22
23 Copyright (c) 2010, microBuilder SARL
24 All rights reserved.
25
26 Redistribution and use in source and binary forms, with or without
27 modification, are permitted provided that the following conditions are met:
28 1. Redistributions of source code must retain the above copyright
29 notice, this list of conditions and the following disclaimer.
30 2. Redistributions in binary form must reproduce the above copyright
31 notice, this list of conditions and the following disclaimer in the
32 documentation and/or other materials provided with the distribution.
33 3. Neither the name of the copyright holders nor the
34 names of its contributors may be used to endorse or promote products
35 derived from this software without specific prior written permission.
36
37 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
38 EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
39 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
40 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
41 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
42 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
43 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
44 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
45 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
46 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
47 */
48 /**************************************************************************/
49 #include <string.h>
50
51 #include "alphanumeric.h"
52
53 #include "core/systick/systick.h"
54 #include "drivers/displays/tft/lcd.h"
55 #include "drivers/displays/tft/drawing.h"
56 #include "drivers/displays/tft/touchscreen.h"
57 #include "drivers/displays/tft/fonts/dejavusans9.h"
58
59 // Background and text input region colors
60 #define ALPHA_COLOR_BACKGROUND COLOR_GRAY_15
61 #define ALPHA_COLOR_INPUTFILL COLOR_GRAY_30
62 #define ALPHA_COLOR_INPUTTEXT COLOR_WHITE
63 // Button colors
64 #define ALPHA_COLOR_BTN_BORDER COLOR_GRAY_30
65 #define ALPHA_COLOR_BTN_FILL COLOR_GRAY_30
66 #define ALPHA_COLOR_BTN_FONT COLOR_WHITE
67 // Active button colors
68 #define ALPHA_COLOR_BTNEN_BORDER COLOR_THEME_DEFAULT_DARKER
69 #define ALPHA_COLOR_BTNEN_FILL COLOR_THEME_DEFAULT_BASE
70 #define ALPHA_COLOR_BTNEN_FONT COLOR_BLACK
71
72 /* This kind of messes with your head, but defining the pixel locations
73 this way allows the calculator example to be rendered on another
74 TFT LCD with a different screen resolution or orientation without
75 having to rewrite all the individual pixel-level code */
76
77 #define ALPHA_BTN_SPACING (5)
78 #define ALPHA_BTN_WIDTH ((lcdGetWidth() - (ALPHA_BTN_SPACING * 6)) / 5)
79 #define ALPHA_KEYPAD_TOP ((lcdGetHeight() / 7) + (ALPHA_BTN_SPACING * 2))
80 #define ALPHA_BTN_HEIGHT (((lcdGetHeight() - ALPHA_KEYPAD_TOP) - (ALPHA_BTN_SPACING * 7)) / 6)
81 // #define ALPHA_BTN_WIDTH ((240 - (ALPHA_BTN_SPACING * 6)) / 5)
82 // #define ALPHA_KEYPAD_TOP ((320 / 6) + (ALPHA_BTN_SPACING * 2))
83 // #define ALPHA_BTN_HEIGHT (((320 - ALPHA_KEYPAD_TOP) - (ALPHA_BTN_SPACING * 7)) / 6)
84
85 /* X/Y positions for buttons */
86 #define ALPHA_ROW1_TOP (ALPHA_KEYPAD_TOP + ALPHA_BTN_SPACING)
87 #define ALPHA_ROW2_TOP (ALPHA_KEYPAD_TOP + ALPHA_BTN_HEIGHT + (ALPHA_BTN_SPACING * 2))
88 #define ALPHA_ROW3_TOP (ALPHA_KEYPAD_TOP + ((ALPHA_BTN_HEIGHT * 2) + ((ALPHA_BTN_SPACING) * 3)))
89 #define ALPHA_ROW4_TOP (ALPHA_KEYPAD_TOP + ((ALPHA_BTN_HEIGHT * 3) + ((ALPHA_BTN_SPACING) * 4)))
90 #define ALPHA_ROW5_TOP (ALPHA_KEYPAD_TOP + ((ALPHA_BTN_HEIGHT * 4) + ((ALPHA_BTN_SPACING) * 5)))
91 #define ALPHA_ROW6_TOP (ALPHA_KEYPAD_TOP + ((ALPHA_BTN_HEIGHT * 5) + ((ALPHA_BTN_SPACING) * 6)))
92 #define ALPHA_COL1_LEFT (ALPHA_BTN_SPACING)
93 #define ALPHA_COL2_LEFT ((ALPHA_BTN_SPACING * 2) + ALPHA_BTN_WIDTH)
94 #define ALPHA_COL3_LEFT ((ALPHA_BTN_SPACING * 3) + (ALPHA_BTN_WIDTH * 2))
95 #define ALPHA_COL4_LEFT ((ALPHA_BTN_SPACING * 4) + (ALPHA_BTN_WIDTH * 3))
96 #define ALPHA_COL5_LEFT ((ALPHA_BTN_SPACING * 5) + (ALPHA_BTN_WIDTH * 4))
97
98 /* Control which 'page' is currently shown on the keypad */
99 static uint8_t alphaPage = 0;
100
101 /* Keeps track of the string contents */
102 static uint8_t alphaString[80];
103 static uint8_t *alphaString_ptr;
104
105 /* For quick retrieval of button X/Y locqtions */
106 uint32_t alphaBtnX[5], alphaBtnY[6];
107
108 /* Array showing which characters should be displayed on each alphaPage */
109 /* You can rearrange the keypad by modifying the array contents below */
110 /* -------------------- -------------------- -------------------- --------------------
111 A B C D BACK a b c d BACK . , : ; BACK 7 8 9 BACK
112 E F G H I e f g h i ' " ( ) 4 5 6
113 J K L M N j k l m n ? ! { } 7 8 9
114 O P Q R S o p q r s # & @ ~ . 0 SPC
115 T U V W SHFT t u v w SHFT % = / \ SHFT SHFT
116 X Y Z SPC OK x y z SPC OK + - _ SPC OK OK
117 -------------------- -------------------- -------------------- -------------------- */
118 char alphaKeys[4][6][5] = { { { 'A', 'B', 'C', 'D', '<' },
119 { 'E', 'F', 'G', 'H', 'I' },
120 { 'J', 'K', 'L', 'M', 'N' },
121 { 'O', 'P', 'Q', 'R', 'S' },
122 { 'T', 'U', 'V', 'W', '*' },
123 { 'X', 'Y', 'Z', ' ', '>' } },
124
125 { { 'a', 'b', 'c', 'd', '<' },
126 { 'e', 'f', 'g', 'h', 'i' },
127 { 'j', 'k', 'l', 'm', 'n' },
128 { 'o', 'p', 'q', 'r', 's' },
129 { 't', 'u', 'v', 'w', '*' },
130 { 'x', 'y', 'z', ' ', '>' } },
131
132 { { '.', ',', ':', ';', '<' },
133 { '\'', '\"', '(', ')', ' ' },
134 { '?', '!', '{', '}', ' ' },
135 { '#', '&', '@', '~', ' ' },
136 { '%', '=', '/', '\\', '*' },
137 { '+', '-', '_', ' ', '>' } },
138
139 { { '7', '8', '9', ' ', '<' },
140 { '4', '5', '6', ' ', ' ' },
141 { '1', '2', '3', ' ', ' ' },
142 { '.', '0', ' ', ' ', ' ' },
143 { ' ', ' ', ' ', ' ', '*'},
144 { ' ', ' ', ' ', ' ', '>' } } };
145
146 /**************************************************************************/
147 /*!
148 @brief Renders the UI
149 */
150 /**************************************************************************/
151 void alphaRenderButton(uint8_t alphaPage, uint8_t col, uint8_t row, bool selected)
152 {
153 // Set colors depending on button state
154 uint16_t border, fill, font;
155 if (selected)
156 {
157 border = ALPHA_COLOR_BTNEN_BORDER;
158 fill = ALPHA_COLOR_BTNEN_FILL;
159 font = ALPHA_COLOR_BTNEN_FONT;
160 }
161 else
162 {
163 border = ALPHA_COLOR_BTN_BORDER;
164 fill = ALPHA_COLOR_BTN_FILL;
165 font = ALPHA_COLOR_BTN_FONT;
166 }
167
168 char c = alphaKeys[alphaPage][row][col];
169 char key[2] = { alphaKeys[alphaPage][row][col], '\0' };
170 // Handle special characters
171 switch (c)
172 {
173 case '<':
174 // Backspace
175 drawButton (alphaBtnX[col], alphaBtnY[row], ALPHA_BTN_WIDTH, &dejaVuSans9ptFontInfo, 7, border, fill, font, NULL);
176 drawArrow (alphaBtnX[col] + ALPHA_BTN_WIDTH / 2 - 3, alphaBtnY[row] + ALPHA_BTN_HEIGHT / 2, 7, DRAW_DIRECTION_LEFT, font);
177 break;
178 case '*':
179 // Page Shift
180 drawButton (alphaBtnX[col], alphaBtnY[row], ALPHA_BTN_WIDTH, &dejaVuSans9ptFontInfo, 7, border, fill, font, NULL);
181 drawArrow (alphaBtnX[col] + ALPHA_BTN_WIDTH / 2, (alphaBtnY[row] + ALPHA_BTN_HEIGHT / 2) - 3, 7, DRAW_DIRECTION_UP, font);
182 break;
183 case '>':
184 // OK
185 drawButton (alphaBtnX[col], alphaBtnY[row], ALPHA_BTN_WIDTH, &dejaVuSans9ptFontInfo, 7, border, fill, font, "OK");
186 break;
187 default:
188 // Standard character
189 drawButton (alphaBtnX[col], alphaBtnY[row], ALPHA_BTN_WIDTH, &dejaVuSans9ptFontInfo, 7, border, fill, font, key);
190 break;
191 }
192 }
193
194 /**************************************************************************/
195 /*!
196 @brief Renders the UI
197 */
198 /**************************************************************************/
199 void alphaRefreshScreen(void)
200 {
201 uint8_t x, y;
202
203 /* Draw keypad */
204 for (y = 0; y < 6; y++)
205 {
206 for (x = 0; x < 5; x++)
207 {
208 alphaRenderButton(alphaPage, x, y, false);
209 }
210 }
211
212 /* Render Text */
213 drawRectangleRounded(ALPHA_BTN_SPACING, ALPHA_BTN_SPACING, lcdGetWidth() - 1 - ALPHA_BTN_SPACING, ALPHA_KEYPAD_TOP - ALPHA_BTN_SPACING, ALPHA_COLOR_INPUTFILL, 10, DRAW_ROUNDEDCORNERS_ALL);
214 drawString(ALPHA_BTN_SPACING * 3, ALPHA_BTN_SPACING * 3, ALPHA_COLOR_INPUTTEXT, &dejaVuSans9ptFontInfo, (char *)&alphaString);
215 }
216
217 /**************************************************************************/
218 /*!
219 @brief Processes the supplied touch data
220 */
221 /**************************************************************************/
222 char alphaHandleTouchEvent(void)
223 {
224 tsTouchData_t data;
225 char result = '\0';
226 uint8_t row, col;
227 int32_t tsError = -1;
228
229 // Blocking delay until a valid touch event occurs
230 while (tsError)
231 {
232 tsError = tsWaitForEvent(&data, 0);
233 }
234
235 // Attempt to convert touch data to char
236 if ((data.ylcd < ALPHA_ROW1_TOP) || (data.ylcd > ALPHA_ROW6_TOP + ALPHA_BTN_HEIGHT))
237 {
238 return result;
239 }
240
241 // Get column
242 if ((data.xlcd > alphaBtnX[0]) && (data.xlcd < alphaBtnX[0] + ALPHA_BTN_WIDTH))
243 col = 0;
244 else if ((data.xlcd > alphaBtnX[1]) && (data.xlcd < alphaBtnX[1] + ALPHA_BTN_WIDTH))
245 col = 1;
246 else if ((data.xlcd > alphaBtnX[2]) && (data.xlcd < alphaBtnX[2] + ALPHA_BTN_WIDTH))
247 col = 2;
248 else if ((data.xlcd > alphaBtnX[3]) && (data.xlcd < alphaBtnX[3] + ALPHA_BTN_WIDTH))
249 col = 3;
250 else if ((data.xlcd > ALPHA_COL5_LEFT) && (data.xlcd < ALPHA_COL5_LEFT + ALPHA_BTN_WIDTH))
251 col = 4;
252 else
253 return result;
254
255 // Get row
256 if ((data.ylcd > ALPHA_ROW1_TOP) && (data.ylcd < ALPHA_ROW1_TOP + ALPHA_BTN_HEIGHT))
257 row = 0;
258 else if ((data.ylcd > ALPHA_ROW2_TOP) && (data.ylcd < ALPHA_ROW2_TOP + ALPHA_BTN_HEIGHT))
259 row = 1;
260 else if ((data.ylcd > ALPHA_ROW3_TOP) && (data.ylcd < ALPHA_ROW3_TOP + ALPHA_BTN_HEIGHT))
261 row = 2;
262 else if ((data.ylcd > ALPHA_ROW4_TOP) && (data.ylcd < ALPHA_ROW4_TOP + ALPHA_BTN_HEIGHT))
263 row = 3;
264 else if ((data.ylcd > ALPHA_ROW5_TOP) && (data.ylcd < ALPHA_ROW5_TOP + ALPHA_BTN_HEIGHT))
265 row = 4;
266 else if ((data.ylcd > ALPHA_ROW6_TOP) && (data.ylcd < ALPHA_ROW6_TOP + ALPHA_BTN_HEIGHT))
267 row = 5;
268 else
269 return result;
270
271 // Match found ... update button and process the results
272 alphaRenderButton(alphaPage, col, row, true);
273 result = alphaKeys[alphaPage][row][col];
274
275 if (result == '<')
276 {
277 // Trim character if backspace was pressed
278 if (alphaString_ptr > alphaString)
279 {
280 alphaString_ptr--;
281 *alphaString_ptr = '\0';
282 }
283 }
284 else if (result == '*')
285 {
286 // Switch page if the shift button was pressed
287 alphaPage++;
288 if (alphaPage > 3)
289 {
290 alphaPage = 0;
291 }
292 // Update the UI
293 alphaRefreshScreen();
294 }
295 else if (result == '>')
296 {
297 // OK button
298 systickDelay(CFG_TFTLCD_TS_KEYPADDELAY);
299 return '>';
300 }
301 else
302 {
303 // Add text to string buffer
304 *alphaString_ptr++ = result;
305 }
306
307 // Brief delay
308 systickDelay(CFG_TFTLCD_TS_KEYPADDELAY);
309
310 // Return button to deselected state
311 alphaRefreshScreen();
312 return result;
313 }
314
315 /**************************************************************************/
316 /*!
317 @brief Displays the dialogue box and waits for valid user input
318
319 @section Example
320
321 @code
322 #include "drivers/displays/tft/dialogues/alphanumeric.h"
323
324 // Print results from an alpha-numeric dialogue
325 char* results = alphaShowDialogue();
326 printf("%s\r\n", results);
327
328 @endcode
329 */
330 /**************************************************************************/
331 char* alphaShowDialogue(void)
332 {
333 char result;
334
335 /* These need to be instantiated here since the width and height of
336 the lcd is retrieved dynamically depending on screen orientation */
337 alphaBtnX[0] = ALPHA_COL1_LEFT;
338 alphaBtnX[1] = ALPHA_COL2_LEFT;
339 alphaBtnX[2] = ALPHA_COL3_LEFT;
340 alphaBtnX[3] = ALPHA_COL4_LEFT;
341 alphaBtnX[4] = ALPHA_COL5_LEFT;
342 alphaBtnY[0] = ALPHA_ROW1_TOP;
343 alphaBtnY[1] = ALPHA_ROW2_TOP;
344 alphaBtnY[2] = ALPHA_ROW3_TOP;
345 alphaBtnY[3] = ALPHA_ROW4_TOP;
346 alphaBtnY[4] = ALPHA_ROW5_TOP;
347 alphaBtnY[5] = ALPHA_ROW6_TOP;
348
349 /* Initialise the string buffer */
350 memset(&alphaString[0], 0, sizeof(alphaString));
351 alphaString_ptr = alphaString;
352 alphaPage = 0;
353
354 /* Draw the background and render the buttons */
355 drawFill(ALPHA_COLOR_BACKGROUND);
356 alphaRefreshScreen();
357
358 /* Capture results until the 'OK' button is pressed */
359 while(1)
360 {
361 result = alphaHandleTouchEvent();
362 if (result == '>') return (char *)&alphaString;
363 }
364 }
This page took 0.078464 seconds and 5 git commands to generate.