Embedded SDK
Embedded SDK
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  **********************/
37 typedef 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  **********************/
50 const 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
58 const 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 
73 static 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 
87 static 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 
101 static 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 
116 static 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
147 static 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
222 static 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  const char *keys = keysByMode[keyboard->mode];
242  uint8_t maxLen = strlen(keys);
243 
244  // mode is defined, so draw the proper 3 letters (or icons)
245  for (i = 0; i < 3; i++) {
246  uint8_t charIndex = (keyboard->selectedCharIndex + maxLen - 1 + i) % maxLen;
247  if (keys[charIndex] == '\r') {
248  keyboardDrawIcon(keyboard->obj.area.x0 + 2 * i * KEYBOARD_KEY_WIDTH,
249  keyboard->obj.area.y0,
250  (i == 1),
251  &C_icon_classes);
252  }
253  else if (keys[charIndex] == '\n') {
254  keyboardDrawIcon(keyboard->obj.area.x0 + 2 * i * KEYBOARD_KEY_WIDTH,
255  keyboard->obj.area.y0,
256  (i == 1),
257  &C_icon_validate_10);
258  }
259  else if (keys[charIndex] == '\b') {
260  keyboardDrawIcon(keyboard->obj.area.x0 + 2 * i * KEYBOARD_KEY_WIDTH,
261  keyboard->obj.area.y0,
262  (i == 1),
263  &C_icon_backspace);
264  }
265  else {
266  keyboardDrawChar(keyboard->obj.area.x0 + 2 * i * KEYBOARD_KEY_WIDTH,
267  keyboard->obj.area.y0,
268  (i == 1),
269  &keys[charIndex]);
270  }
271  }
272 }
273 
274 /**********************
275  * GLOBAL FUNCTIONS
276  **********************/
277 
285 void nbgl_keyboardCallback(nbgl_obj_t *obj, nbgl_buttonEvent_t buttonEvent)
286 {
287  nbgl_keyboard_t *keyboard = (nbgl_keyboard_t *) obj;
288  uint8_t nbMax;
289 
290  LOG_DEBUG(MISC_LOGGER, "nbgl_keyboardCallback(): buttonEvent = %d\n", buttonEvent);
291 
292  if (keyboard->mode == MODE_NONE) {
293  nbMax = 2;
294  }
295  else {
296  if (keyboard->lettersOnly) {
297  nbMax = BACKSPACE_KEY_INDEX;
298  }
299  else {
300  nbMax = strlen(keysByMode[keyboard->mode]) - 1;
301  }
302  }
303  if (buttonEvent == BUTTON_BOTH_PRESSED) {
304  if (keyboard->mode == MODE_NONE) {
305  // apply the selected mode
306  keyboard->mode = keyboard->selectedCharIndex;
307  // reset the selected index to start with "a" (or first char of selected mode)
308  keyboard->selectedCharIndex = 0;
309  }
310  else {
311  if (keyboard->lettersOnly) {
312  if ((keyboard->selectedCharIndex < 26)
313  && ((keyboard->keyMask & (1 << keyboard->selectedCharIndex)) == 0)) {
314  const char *keys = keysByMode[keyboard->mode];
315  keyboard->callback(keys[keyboard->selectedCharIndex]);
316  }
317  else if (keyboard->selectedCharIndex == BACKSPACE_KEY_INDEX) { // backspace
318  keyboard->callback(BACKSPACE_KEY);
319  }
320  }
321  else {
322  char key = keysByMode[keyboard->mode][keyboard->selectedCharIndex];
323  if (key == '\r') {
324  // go back to mode choice
325  keyboard->mode = MODE_NONE;
326  // reset the selected index
327  keyboard->selectedCharIndex = 0;
328  nbgl_objDraw((nbgl_obj_t *) keyboard);
329  nbgl_refresh();
330  }
331  else if (key == '\n') {
332  keyboard->callback(VALIDATE_KEY);
333  }
334  else if (key == '\b') {
335  keyboard->callback(BACKSPACE_KEY);
336  }
337  else {
338  keyboard->callback(key);
339  }
340  }
341  return;
342  }
343  }
344  else if (buttonEvent == BUTTON_LEFT_PRESSED) {
345  do {
346  if (keyboard->selectedCharIndex > 0) {
347  keyboard->selectedCharIndex--;
348  }
349  else {
350  keyboard->selectedCharIndex = nbMax;
351  }
352  } while (keyboard->keyMask & (1 << keyboard->selectedCharIndex));
353  }
354  else if (buttonEvent == BUTTON_RIGHT_PRESSED) {
355  do {
356  if (keyboard->selectedCharIndex < nbMax) {
357  keyboard->selectedCharIndex++;
358  }
359  else {
360  keyboard->selectedCharIndex = 0;
361  }
362  } while (keyboard->keyMask & (1 << keyboard->selectedCharIndex));
363  }
364  else {
365  return;
366  }
367  nbgl_objDraw((nbgl_obj_t *) keyboard);
368  nbgl_refresh();
369 }
370 
377 {
378  if (kbd->lettersOnly) {
379  keyboardDrawLettersOnly(kbd);
380  }
381  else {
382  keyboardDrawRegular(kbd);
383  }
384 }
385 #endif // HAVE_SE_TOUCH
386 #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:489
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:538
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:237
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:372
@ BAGL_FONT_OPEN_SANS_EXTRABOLD_11px_1bpp
Definition: nbgl_fonts.h:147
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:41
void nbgl_objDraw(nbgl_obj_t *obj)
This function draws or redraws the given object and its children (recursive version)
Definition: nbgl_obj.c:1521
void nbgl_refresh(void)
This functions refreshes the actual screen on display with what has changed since the last refresh.
Definition: nbgl_obj.c:1560
struct PACKED__ nbgl_keyboard_s nbgl_keyboard_t
struct to represent a keyboard (KEYBOARD type)
nbgl_buttonEvent_t
Definition: nbgl_obj.h:182
@ BUTTON_BOTH_PRESSED
Sent when both buttons are released.
Definition: nbgl_obj.h:189
@ BUTTON_LEFT_PRESSED
Sent when Left button is released.
Definition: nbgl_obj.h:183
@ BUTTON_RIGHT_PRESSED
Send when Right button is released.
Definition: nbgl_obj.h:184
#define BACKSPACE_KEY
Definition: nbgl_obj.h:26
void nbgl_objDrawKeyboard(nbgl_keyboard_t *kbd)
This function draws a keyboard object.
#define KEYBOARD_KEY_HEIGHT
Definition: nbgl_obj.h:35
#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:105
@ BLACK
Definition: nbgl_types.h:102
struct PACKED__ nbgl_icon_details_s nbgl_icon_details_t
Represents all information about an icon.
#define NO_TRANSFORMATION
Definition: nbgl_types.h:55
@ NBGL_BPP_1
1 bit per pixel
Definition: nbgl_types.h:245
struct PACKED__ nbgl_area_s nbgl_area_t
Represents a rectangle area of the screen.
signed short int16_t
Definition: usbd_conf.h:50
unsigned char uint8_t
Definition: usbd_conf.h:53
signed char int8_t
Definition: usbd_conf.h:49