[FL-938] Keyboard widget changes (#398)
* inputs: add repeat event * byte_input: change draw * text_input, byte_input: process repeat event
This commit is contained in:
		| @@ -36,8 +36,8 @@ typedef struct { | |||||||
| #define MIN(x, y) (((x) < (y)) ? (x) : (y)) | #define MIN(x, y) (((x) < (y)) ? (x) : (y)) | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
| static const uint8_t keyboard_origin_x = 8; | static const uint8_t keyboard_origin_x = 7; | ||||||
| static const uint8_t keyboard_origin_y = 32; | static const uint8_t keyboard_origin_y = 31; | ||||||
| static const uint8_t keyboard_row_count = 2; | static const uint8_t keyboard_row_count = 2; | ||||||
| static const uint8_t enter_symbol = '\r'; | static const uint8_t enter_symbol = '\r'; | ||||||
| static const uint8_t backspace_symbol = '\b'; | static const uint8_t backspace_symbol = '\b'; | ||||||
| @@ -52,7 +52,7 @@ static const ByteInputKey keyboard_keys_row_1[] = { | |||||||
|     {'5', 55, 12}, |     {'5', 55, 12}, | ||||||
|     {'6', 66, 12}, |     {'6', 66, 12}, | ||||||
|     {'7', 77, 12}, |     {'7', 77, 12}, | ||||||
|     {backspace_symbol, 101, 4}, |     {backspace_symbol, 103, 4}, | ||||||
| }; | }; | ||||||
|  |  | ||||||
| static const ByteInputKey keyboard_keys_row_2[] = { | static const ByteInputKey keyboard_keys_row_2[] = { | ||||||
| @@ -64,7 +64,7 @@ static const ByteInputKey keyboard_keys_row_2[] = { | |||||||
|     {'D', 55, 26}, |     {'D', 55, 26}, | ||||||
|     {'E', 66, 26}, |     {'E', 66, 26}, | ||||||
|     {'F', 77, 26}, |     {'F', 77, 26}, | ||||||
|     {enter_symbol, 93, 17}, |     {enter_symbol, 95, 17}, | ||||||
| }; | }; | ||||||
|  |  | ||||||
| /** | /** | ||||||
| @@ -158,10 +158,10 @@ static char byte_input_get_nibble_text(uint8_t byte, bool high_nibble) { | |||||||
|  * @param model  |  * @param model  | ||||||
|  */ |  */ | ||||||
| static void byte_input_draw_input(Canvas* canvas, ByteInputModel* model) { | static void byte_input_draw_input(Canvas* canvas, ByteInputModel* model) { | ||||||
|     const uint8_t text_x = 7; |     const uint8_t text_x = 3; | ||||||
|     const uint8_t text_y = 27; |     const uint8_t text_y = 25; | ||||||
|  |  | ||||||
|     elements_slightly_rounded_frame(canvas, 5, 16, 117, 15); |     elements_slightly_rounded_frame(canvas, 1, 14, 126, 15); | ||||||
|  |  | ||||||
|     for(uint8_t i = model->first_visible_byte; |     for(uint8_t i = model->first_visible_byte; | ||||||
|         i < model->first_visible_byte + MIN(model->bytes_count, max_drawable_bytes); |         i < model->first_visible_byte + MIN(model->bytes_count, max_drawable_bytes); | ||||||
| @@ -242,12 +242,12 @@ static void byte_input_draw_input(Canvas* canvas, ByteInputModel* model) { | |||||||
|  * @param model  |  * @param model  | ||||||
|  */ |  */ | ||||||
| static void byte_input_draw_input_selected(Canvas* canvas, ByteInputModel* model) { | static void byte_input_draw_input_selected(Canvas* canvas, ByteInputModel* model) { | ||||||
|     const uint8_t text_x = 7; |     const uint8_t text_x = 3; | ||||||
|     const uint8_t text_y = 27; |     const uint8_t text_y = 25; | ||||||
|  |  | ||||||
|     canvas_draw_box(canvas, 0, 14, 128, 19); |     canvas_draw_box(canvas, 0, 12, 128, 19); | ||||||
|     canvas_invert_color(canvas); |     canvas_invert_color(canvas); | ||||||
|     elements_slightly_rounded_frame(canvas, 5, 16, 117, 15); |     elements_slightly_rounded_frame(canvas, 1, 14, 126, 15); | ||||||
|  |  | ||||||
|     for(uint8_t i = model->first_visible_byte; |     for(uint8_t i = model->first_visible_byte; | ||||||
|         i < model->first_visible_byte + MIN(model->bytes_count, max_drawable_bytes); |         i < model->first_visible_byte + MIN(model->bytes_count, max_drawable_bytes); | ||||||
| @@ -518,7 +518,7 @@ static void byte_input_view_draw_callback(Canvas* canvas, void* _model) { | |||||||
|     canvas_clear(canvas); |     canvas_clear(canvas); | ||||||
|     canvas_set_color(canvas, ColorBlack); |     canvas_set_color(canvas, ColorBlack); | ||||||
|  |  | ||||||
|     canvas_draw_str(canvas, 5, 10, model->header); |     canvas_draw_str(canvas, 2, 9, model->header); | ||||||
|  |  | ||||||
|     canvas_set_font(canvas, FontKeyboard); |     canvas_set_font(canvas, FontKeyboard); | ||||||
|  |  | ||||||
| @@ -608,7 +608,7 @@ static bool byte_input_view_input_callback(InputEvent* event, void* context) { | |||||||
|     furi_assert(byte_input); |     furi_assert(byte_input); | ||||||
|     bool consumed = false; |     bool consumed = false; | ||||||
|  |  | ||||||
|     if(event->type == InputTypeShort) { |     if(event->type == InputTypeShort || event->type == InputTypeRepeat) { | ||||||
|         switch(event->key) { |         switch(event->key) { | ||||||
|         case InputKeyLeft: |         case InputKeyLeft: | ||||||
|             with_view_model( |             with_view_model( | ||||||
|   | |||||||
| @@ -292,7 +292,7 @@ static bool text_input_view_input_callback(InputEvent* event, void* context) { | |||||||
|     furi_assert(text_input); |     furi_assert(text_input); | ||||||
|     bool consumed = false; |     bool consumed = false; | ||||||
|  |  | ||||||
|     if(event->type == InputTypeShort) { |     if(event->type == InputTypeShort || event->type == InputTypeRepeat) { | ||||||
|         switch(event->key) { |         switch(event->key) { | ||||||
|         case InputKeyUp: |         case InputKeyUp: | ||||||
|             text_input_handle_up(text_input); |             text_input_handle_up(text_input); | ||||||
|   | |||||||
| @@ -11,8 +11,15 @@ void input_press_timer_callback(void* arg) { | |||||||
|     InputPinState* input_pin = arg; |     InputPinState* input_pin = arg; | ||||||
|     InputEvent event; |     InputEvent event; | ||||||
|     event.key = input_pin->pin->key; |     event.key = input_pin->pin->key; | ||||||
|  |     if(!input_pin->repeat_event) { | ||||||
|         event.type = InputTypeLong; |         event.type = InputTypeLong; | ||||||
|         notify_pubsub(&input->event_pubsub, &event); |         notify_pubsub(&input->event_pubsub, &event); | ||||||
|  |         input_pin->repeat_event = true; | ||||||
|  |     } else { | ||||||
|  |         event.type = InputTypeRepeat; | ||||||
|  |         notify_pubsub(&input->event_pubsub, &event); | ||||||
|  |     } | ||||||
|  |     osTimerStart(input_pin->press_timer, INPUT_REPEATE_PRESS_TICKS); | ||||||
| } | } | ||||||
|  |  | ||||||
| void input_isr(void* _pin, void* _ctx) { | void input_isr(void* _pin, void* _ctx) { | ||||||
| @@ -90,6 +97,7 @@ int32_t input_task() { | |||||||
|     for(size_t i = 0; i < pin_count; i++) { |     for(size_t i = 0; i < pin_count; i++) { | ||||||
|         input->pin_states[i].pin = &input_pins[i]; |         input->pin_states[i].pin = &input_pins[i]; | ||||||
|         input->pin_states[i].state = GPIO_Read(input->pin_states[i]); |         input->pin_states[i].state = GPIO_Read(input->pin_states[i]); | ||||||
|  |         input->pin_states[i].repeat_event = false; | ||||||
|         input->pin_states[i].debounce = INPUT_DEBOUNCE_TICKS_HALF; |         input->pin_states[i].debounce = INPUT_DEBOUNCE_TICKS_HALF; | ||||||
|         input->pin_states[i].press_timer = |         input->pin_states[i].press_timer = | ||||||
|             osTimerNew(input_press_timer_callback, osTimerOnce, &input->pin_states[i], NULL); |             osTimerNew(input_press_timer_callback, osTimerOnce, &input->pin_states[i], NULL); | ||||||
| @@ -114,6 +122,9 @@ int32_t input_task() { | |||||||
|                 // Short/Long press logic |                 // Short/Long press logic | ||||||
|                 if(state) { |                 if(state) { | ||||||
|                     osTimerStart(input->pin_states[i].press_timer, INPUT_LONG_PRESS_TICKS); |                     osTimerStart(input->pin_states[i].press_timer, INPUT_LONG_PRESS_TICKS); | ||||||
|  |                 } else if(input->pin_states[i].repeat_event) { | ||||||
|  |                     osTimerStop(input->pin_states[i].press_timer); | ||||||
|  |                     input->pin_states[i].repeat_event = false; | ||||||
|                 } else if(osTimerStop(input->pin_states[i].press_timer) == osOK) { |                 } else if(osTimerStop(input->pin_states[i].press_timer) == osOK) { | ||||||
|                     event.type = InputTypeShort; |                     event.type = InputTypeShort; | ||||||
|                     notify_pubsub(&input->event_pubsub, &event); |                     notify_pubsub(&input->event_pubsub, &event); | ||||||
|   | |||||||
| @@ -10,6 +10,7 @@ typedef enum { | |||||||
|     InputTypeRelease, /* Release event, emitted after debounce */ |     InputTypeRelease, /* Release event, emitted after debounce */ | ||||||
|     InputTypeShort, /* Short event, emitted after InputTypeRelease done withing INPUT_LONG_PRESS interval */ |     InputTypeShort, /* Short event, emitted after InputTypeRelease done withing INPUT_LONG_PRESS interval */ | ||||||
|     InputTypeLong, /* Long event, emmited after INPUT_LONG_PRESS interval, asynchronouse to InputTypeRelease  */ |     InputTypeLong, /* Long event, emmited after INPUT_LONG_PRESS interval, asynchronouse to InputTypeRelease  */ | ||||||
|  |     InputTypeRepeat, /* Repeat event, emmited with INPUT_REPEATE_PRESS period after InputTypeLong event */ | ||||||
| } InputType; | } InputType; | ||||||
|  |  | ||||||
| /* Input Event, dispatches with PubSub */ | /* Input Event, dispatches with PubSub */ | ||||||
|   | |||||||
| @@ -10,6 +10,7 @@ | |||||||
|  |  | ||||||
| #define INPUT_DEBOUNCE_TICKS_HALF (INPUT_DEBOUNCE_TICKS / 2) | #define INPUT_DEBOUNCE_TICKS_HALF (INPUT_DEBOUNCE_TICKS / 2) | ||||||
| #define INPUT_LONG_PRESS_TICKS 2048 | #define INPUT_LONG_PRESS_TICKS 2048 | ||||||
|  | #define INPUT_REPEATE_PRESS_TICKS 256 | ||||||
| #define INPUT_THREAD_FLAG_ISR 0x00000001 | #define INPUT_THREAD_FLAG_ISR 0x00000001 | ||||||
|  |  | ||||||
| /* Input pin state */ | /* Input pin state */ | ||||||
| @@ -17,6 +18,7 @@ typedef struct { | |||||||
|     const InputPin* pin; |     const InputPin* pin; | ||||||
|     // State |     // State | ||||||
|     volatile bool state; |     volatile bool state; | ||||||
|  |     volatile bool repeat_event; | ||||||
|     volatile uint8_t debounce; |     volatile uint8_t debounce; | ||||||
|     volatile osTimerId_t press_timer; |     volatile osTimerId_t press_timer; | ||||||
| } InputPinState; | } InputPinState; | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user