Embedded SDK
Embedded SDK
Loading...
Searching...
No Matches
nbgl_obj_keyboard_nanos.c
Go to the documentation of this file.
1
8#ifdef NBGL_KEYBOARD
9#ifndef HAVE_SE_TOUCH
10
11/*********************
12 * INCLUDES
13 *********************/
14#include <string.h>
15#include "nbgl_debug.h"
16#include "nbgl_front.h"
17#include "nbgl_draw.h"
18#include "nbgl_obj.h"
19#include "nbgl_fonts.h"
20#include "nbgl_touch.h"
21#include "glyphs.h"
22#include "os_io.h"
23
24/*********************
25 * DEFINES
26 *********************/
27
28#define BACKSPACE_KEY_INDEX 26
29#define VALIDATE_INDEX 27
30#define SHIFT_KEY_INDEX 28
31#define LETTER_TO_DIGITS_OFFSET (sizeof(keysByMode[DIGITS_AND_SPECIALS]) - 29)
32#define GET_CHAR(mode, char_idx) ((const char *) PIC(screen_keyboard_keys_by_mode[mode]))[char_idx]
33
34/**********************
35 * TYPEDEFS
36 **********************/
37typedef enum {
38 LOWER_LETTERS,
39 UPPER_LETTERS,
40 DIGITS_AND_SPECIALS
41} KbdMode_t;
42
43/**********************
44 * STATIC PROTOTYPES
45 **********************/
46
47/**********************
48 * STATIC VARIABLES
49 **********************/
50const char *const keysByMode[] = {
51 // when first letter is already entered
52 "abcdefghijklmnopqrstuvwxyz\b\n\r",
53 "ABCDEFGHIJKLMNOPQRSTUVWXYZ\b\n\r",
54 "0123456789 '\"`&/?!:;.,~*$=+-[](){}^<>\\_#@|%\b\n\r",
55};
56
57// these icons will be centered
58const nbgl_icon_details_t *const keyboardIcons[] = {
59 &C_icon_lowercase,
60 &C_icon_uppercase,
61 &C_icon_digits,
62 &C_icon_backspace,
63 &C_icon_validate,
64 &C_icon_classes,
65 &C_icon_lowercase_invert,
66 &C_icon_uppercase_invert,
67 &C_icon_digits_invert,
68 &C_icon_backspace_invert,
69 &C_icon_validate_invert,
70 &C_icon_classes_invert,
71};
72
73static const nbgl_icon_details_t *const modeIcons[] = {
74 &C_icon_lowercase,
75 &C_icon_uppercase,
76 &C_icon_digits,
77};
78
79/**********************
80 * VARIABLES
81 **********************/
82
83/**********************
84 * STATIC FUNCTIONS
85 **********************/
86
87static void keyboardDrawIcon(int16_t x0, int8_t y0, bool inverted, const nbgl_icon_details_t *icon)
88{
89 nbgl_area_t rectArea;
90
91 rectArea.backgroundColor = inverted ? WHITE : BLACK;
92 rectArea.width = icon->width;
93 rectArea.height = icon->height;
94 rectArea.bpp = NBGL_BPP_1;
95 // center
96 rectArea.x0 = x0 + (KEYBOARD_KEY_WIDTH - icon->width) / 2;
97 rectArea.y0 = y0 + (KEYBOARD_KEY_HEIGHT - icon->height) / 2;
98 nbgl_drawIcon(&rectArea, NO_TRANSFORMATION, inverted ? BLACK : WHITE, icon);
99}
100
101static void keyboardDrawChar(int16_t x0, int8_t y0, bool inverted, const char *charPtr)
102{
103 nbgl_area_t rectArea;
104
105 rectArea.backgroundColor = inverted ? WHITE : BLACK;
107 rectArea.height = 12;
108 rectArea.bpp = NBGL_BPP_1;
109 // center
110 rectArea.x0 = x0 + (KEYBOARD_KEY_WIDTH - rectArea.width) / 2;
111 rectArea.y0 = y0 + (KEYBOARD_KEY_HEIGHT - rectArea.height) / 2 - 3;
113 &rectArea, charPtr, 1, BAGL_FONT_OPEN_SANS_EXTRABOLD_11px_1bpp, inverted ? BLACK : WHITE);
114}
115
116static void keyboardDrawCommon(nbgl_keyboard_t *keyboard)
117{
118 nbgl_area_t rectArea;
119
120 // clean full area
121 rectArea.backgroundColor = BLACK;
122 rectArea.x0 = keyboard->obj.area.x0;
123 rectArea.y0 = keyboard->obj.area.y0;
124 rectArea.width = keyboard->obj.area.width;
125 rectArea.height = keyboard->obj.area.height;
126 nbgl_frontDrawRect(&rectArea);
127
128 // draw select 'key' in white
129 rectArea.x0 = keyboard->obj.area.x0 + 2 * KEYBOARD_KEY_WIDTH;
130 rectArea.y0 = keyboard->obj.area.y0;
131 rectArea.width = KEYBOARD_KEY_WIDTH;
132 rectArea.height = keyboard->obj.area.height;
133 nbgl_drawRoundedRect(&rectArea, RADIUS_3_PIXELS, WHITE);
134
135 // draw separating '-' in white
136 rectArea.backgroundColor = WHITE;
137 rectArea.x0 = keyboard->obj.area.x0 + KEYBOARD_KEY_WIDTH + 5;
138 rectArea.y0 = keyboard->obj.area.y0 + 6;
139 rectArea.width = 3;
140 rectArea.height = 1;
141 nbgl_frontDrawRect(&rectArea);
142 rectArea.x0 = keyboard->obj.area.x0 + 3 * KEYBOARD_KEY_WIDTH + 5;
143 nbgl_frontDrawRect(&rectArea);
144}
145
146// draw letters for letters mode
147static void keyboardDrawLettersOnly(nbgl_keyboard_t *keyboard)
148{
149 uint8_t i;
150 const char *keys = keysByMode[keyboard->mode];
151
152 if (keyboard->keyMask == 0x07FFFFFF) {
153 return;
154 }
155
156 keyboardDrawCommon(keyboard);
157
158 // if selectedChar is masked, move to the first unmasked
159 while (keyboard->keyMask & (1 << keyboard->selectedCharIndex)) {
160 if (keyboard->selectedCharIndex < BACKSPACE_KEY_INDEX) {
161 keyboard->selectedCharIndex++;
162 }
163 else {
164 keyboard->selectedCharIndex = 0;
165 }
166 }
167
168 // fill the letters at position middle and right
169 uint8_t j = 1;
170 i = keyboard->selectedCharIndex;
171 while (j < 3) {
172 // use the provided mask to check what letters(+backspace at 27th position) to use
173 if ((keyboard->keyMask & (1 << i)) == 0) {
174 if (i == BACKSPACE_KEY_INDEX) { // backspace
175 keyboardDrawIcon(keyboard->obj.area.x0 + 2 * j * KEYBOARD_KEY_WIDTH,
176 keyboard->obj.area.y0,
177 (j == 1),
178 &C_icon_backspace);
179 }
180 else { // any char
181 keyboardDrawChar(keyboard->obj.area.x0 + 2 * j * KEYBOARD_KEY_WIDTH,
182 keyboard->obj.area.y0,
183 (j == 1),
184 &keys[i]);
185 }
186 j++;
187 }
188 i++;
189 i %= 27;
190 // safe check in case mask is full of 1s
191 if (i == keyboard->selectedCharIndex) {
192 break;
193 }
194 }
195 // fill the letters at left position from end
196 i = (keyboard->selectedCharIndex + 26) % 27;
197 while (true) {
198 if ((keyboard->keyMask & (1 << i)) == 0) {
199 if (i == BACKSPACE_KEY_INDEX) { // backspace
200 keyboardDrawIcon(
201 keyboard->obj.area.x0, keyboard->obj.area.y0, false, &C_icon_backspace);
202 }
203 else { // any char
204 keyboardDrawChar(keyboard->obj.area.x0, keyboard->obj.area.y0, false, &keys[i]);
205 }
206 break;
207 }
208 if (i > 0) {
209 i--;
210 }
211 else {
213 }
214 // safe check in case mask is full of 1s
215 if (i == (keyboard->selectedCharIndex + 26) % 27) {
216 break;
217 }
218 }
219}
220
221// draw letters for regular mode
222static void keyboardDrawRegular(nbgl_keyboard_t *keyboard)
223{
224 int8_t i;
225
226 keyboardDrawCommon(keyboard);
227
228 // if mode is not already defined, display the 3 icons of keyboard modes to let user choose it:
229 // "ab, AB and 0? "
230 if (keyboard->mode == MODE_NONE) {
231 for (i = 0; i < 3; i++) {
232 uint8_t charIndex = (keyboard->selectedCharIndex + 2 + i) % 3;
233 keyboardDrawIcon(keyboard->obj.area.x0 + 2 * i * KEYBOARD_KEY_WIDTH,
234 keyboard->obj.area.y0,
235 (i == 1),
236 modeIcons[charIndex]);
237 }
238 return;
239 }
240
241 // if all keys are masked, exit immediately
242 if ((keyboard->keyMask & 0x1FFFFFFF) == 0x1FFFFFFF) {
243 return;
244 }
245
246 const char *keys = keysByMode[keyboard->mode];
247 uint8_t maxLen = strlen(keys);
248 char keysToDraw[3] = {0};
249
250 // fill the keys to draw in a temporary array, depending of keyMask
251 // start with central and right ones
252 uint8_t charIndex = keyboard->selectedCharIndex;
253 for (i = 1; i < 3; i++) {
254 while (keyboard->keyMask & (1 << charIndex)) {
255 charIndex++;
256 charIndex %= maxLen;
257 }
258 keysToDraw[i] = keys[charIndex];
259 charIndex++;
260 charIndex %= maxLen;
261 }
262 // then left one
263 charIndex = (keyboard->selectedCharIndex + maxLen - 1) % maxLen;
264 while (keyboard->keyMask & (1 << charIndex)) {
265 if (charIndex > 0) {
266 charIndex--;
267 }
268 else {
269 charIndex = maxLen - 1;
270 }
271 }
272 keysToDraw[0] = keys[charIndex];
273
274 // mode is defined, so draw the proper 3 letters (or icons)
275 for (i = 0; i < 3; i++) {
276 if (keysToDraw[i] == '\r') {
277 keyboardDrawIcon(keyboard->obj.area.x0 + 2 * i * KEYBOARD_KEY_WIDTH,
278 keyboard->obj.area.y0,
279 (i == 1),
280 &C_icon_classes);
281 }
282 else if (keysToDraw[i] == '\n') {
283 keyboardDrawIcon(keyboard->obj.area.x0 + 2 * i * KEYBOARD_KEY_WIDTH,
284 keyboard->obj.area.y0,
285 (i == 1),
286 &C_icon_validate_10);
287 }
288 else if (keysToDraw[i] == '\b') {
289 keyboardDrawIcon(keyboard->obj.area.x0 + 2 * i * KEYBOARD_KEY_WIDTH,
290 keyboard->obj.area.y0,
291 (i == 1),
292 &C_icon_backspace);
293 }
294 else if (keysToDraw[i] != 0) {
295 keyboardDrawChar(keyboard->obj.area.x0 + 2 * i * KEYBOARD_KEY_WIDTH,
296 keyboard->obj.area.y0,
297 (i == 1),
298 &keysToDraw[i]);
299 }
300 }
301}
302
303/**********************
304 * GLOBAL FUNCTIONS
305 **********************/
306
314void nbgl_keyboardCallback(nbgl_obj_t *obj, nbgl_buttonEvent_t buttonEvent)
315{
316 nbgl_keyboard_t *keyboard = (nbgl_keyboard_t *) obj;
317 uint8_t nbMax;
318
319 LOG_DEBUG(MISC_LOGGER, "nbgl_keyboardCallback(): buttonEvent = %d\n", buttonEvent);
320
321 if (keyboard->mode == MODE_NONE) {
322 nbMax = 2;
323 }
324 else {
325 if (keyboard->lettersOnly) {
326 nbMax = BACKSPACE_KEY_INDEX;
327 }
328 else {
329 nbMax = strlen(keysByMode[keyboard->mode]) - 1;
330 }
331 }
332 if (buttonEvent == BUTTON_BOTH_PRESSED) {
333 if (keyboard->mode == MODE_NONE) {
334 // apply the selected mode
335 keyboard->mode = keyboard->selectedCharIndex;
336 // reset the selected index to start with "a" (or first char of selected mode)
337 keyboard->selectedCharIndex = 0;
338 }
339 else {
340 if (keyboard->lettersOnly) {
341 if ((keyboard->selectedCharIndex < 26)
342 && ((keyboard->keyMask & (1 << keyboard->selectedCharIndex)) == 0)) {
343 const char *keys = keysByMode[keyboard->mode];
344 keyboard->callback(keys[keyboard->selectedCharIndex]);
345 }
346 else if (keyboard->selectedCharIndex == BACKSPACE_KEY_INDEX) { // backspace
347 keyboard->callback(BACKSPACE_KEY);
348 }
349 }
350 else {
351 char key = keysByMode[keyboard->mode][keyboard->selectedCharIndex];
352 if (key == '\r') {
353 // go back to mode choice
354 keyboard->mode = MODE_NONE;
355 // reset the selected index
356 keyboard->selectedCharIndex = 0;
357 nbgl_objDraw((nbgl_obj_t *) keyboard);
358 nbgl_refresh();
359 }
360 else if (key == '\n') {
361 keyboard->callback(VALIDATE_KEY);
362 }
363 else if (key == '\b') {
364 keyboard->callback(BACKSPACE_KEY);
365 }
366 else {
367 keyboard->callback(key);
368 }
369 }
370 return;
371 }
372 }
373 else if (buttonEvent == BUTTON_LEFT_PRESSED) {
374 do {
375 if (keyboard->selectedCharIndex > 0) {
376 keyboard->selectedCharIndex--;
377 }
378 else {
379 keyboard->selectedCharIndex = nbMax;
380 }
381 } while ((keyboard->mode != MODE_NONE)
382 && (keyboard->keyMask & (1 << keyboard->selectedCharIndex)));
383 }
384 else if (buttonEvent == BUTTON_RIGHT_PRESSED) {
385 do {
386 if (keyboard->selectedCharIndex < nbMax) {
387 keyboard->selectedCharIndex++;
388 }
389 else {
390 keyboard->selectedCharIndex = 0;
391 }
392 } while ((keyboard->mode != MODE_NONE)
393 && (keyboard->keyMask & (1 << keyboard->selectedCharIndex)));
394 }
395 else {
396 return;
397 }
398 nbgl_objDraw((nbgl_obj_t *) keyboard);
399 nbgl_refresh();
400}
401
408{
409 if (kbd->lettersOnly) {
410 keyboardDrawLettersOnly(kbd);
411 }
412 else {
413 keyboardDrawRegular(kbd);
414 }
415}
416#endif // HAVE_SE_TOUCH
417#endif // NBGL_KEYBOARD
debug traces management
#define LOG_DEBUG(__logger,...)
Definition nbgl_debug.h:86
@ MISC_LOGGER
Definition nbgl_debug.h:39
Middle Level API of the new BOLOS Graphical Library.
void nbgl_drawIcon(nbgl_area_t *area, nbgl_transformation_t transformation, nbgl_color_map_t color_map, const nbgl_icon_details_t *icon)
Helper function to render an icon directly from its nbgl_icon_details_t structure.
Definition nbgl_draw.c:535
nbgl_font_id_e nbgl_drawText(const nbgl_area_t *area, const char *text, uint16_t textLen, nbgl_font_id_e fontId, color_t fontColor)
This function draws the given single-line text, with the given parameters.
Definition nbgl_draw.c:584
void nbgl_drawRoundedRect(const nbgl_area_t *area, nbgl_radius_t radius, color_t innerColor)
This functions draws a rounded corners rectangle (without border), with the given parameters.
Definition nbgl_draw.c:270
uint8_t nbgl_getCharWidth(nbgl_font_id_e fontId, const char *text)
return the width in pixels of the given UTF-8 character
Definition nbgl_fonts.c:366
@ BAGL_FONT_OPEN_SANS_EXTRABOLD_11px_1bpp
Definition nbgl_fonts.h:150
Font screen low-Level driver API, to draw elementary forms.
void nbgl_frontDrawRect(const nbgl_area_t *area)
API to draw all basic graphic objects.
#define BACKSPACE_KEY_INDEX
Definition nbgl_obj.h:43
void nbgl_objDraw(nbgl_obj_t *obj)
This function draws or redraws the given object and its children (recursive version)
Definition nbgl_obj.c:1654
void nbgl_refresh(void)
This functions refreshes the actual screen on display with what has changed since the last refresh.
Definition nbgl_obj.c:1697
struct PACKED__ nbgl_keyboard_s nbgl_keyboard_t
struct to represent a keyboard (KEYBOARD type)
nbgl_buttonEvent_t
Definition nbgl_obj.h:307
@ BUTTON_BOTH_PRESSED
Sent when both buttons are released.
Definition nbgl_obj.h:314
@ BUTTON_LEFT_PRESSED
Sent when Left button is released.
Definition nbgl_obj.h:308
@ BUTTON_RIGHT_PRESSED
Send when Right button is released.
Definition nbgl_obj.h:309
#define BACKSPACE_KEY
Definition nbgl_obj.h:26
void nbgl_objDrawKeyboard(nbgl_keyboard_t *kbd)
This function draws a keyboard object.
#define VALIDATE_KEY
Definition nbgl_obj.h:27
struct PACKED__ nbgl_obj_s nbgl_obj_t
Common structure for all graphical objects.
@ WHITE
Definition nbgl_types.h:144
@ BLACK
Definition nbgl_types.h:141
struct PACKED__ nbgl_icon_details_s nbgl_icon_details_t
Represents all information about an icon.
#define NO_TRANSFORMATION
Definition nbgl_types.h:91
@ NBGL_BPP_1
1 bit per pixel
Definition nbgl_types.h:284
struct PACKED__ nbgl_area_s nbgl_area_t
Represents a rectangle area of the screen.