From b4a113be5921c8a30c809fc596826bd1820bb31b Mon Sep 17 00:00:00 2001 From: furrtek Date: Wed, 11 May 2016 01:03:42 +0200 Subject: [PATCH] Handwriting fixes --- .gitignore | 3 + firmware/Makefile | 2 +- firmware/application/main.cpp | 7 +- firmware/application/ui_handwrite.cpp | 218 ++++++++++++++++--------- firmware/application/ui_handwrite.hpp | 34 ++-- firmware/application/ui_loadmodule.cpp | 1 + firmware/application/ui_navigation.cpp | 9 +- firmware/application/unistroke.hpp | 12 +- firmware/portapack-h1-firmware.bin | Bin 459128 -> 459128 bytes 9 files changed, 176 insertions(+), 110 deletions(-) diff --git a/.gitignore b/.gitignore index 1aa5ca1e..6a804ef9 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,6 @@ +/firmware/application/fox.bmp +/firmware/application/fox_rle.bmp +/firmware/test.wav # Compiled Object files *.slo *.lo diff --git a/firmware/Makefile b/firmware/Makefile index 5bce1a9f..0def504c 100644 --- a/firmware/Makefile +++ b/firmware/Makefile @@ -65,7 +65,7 @@ modules: $(TARGET_BASEBAND).bin $(TARGET_BASEBAND_TX).bin cp $(PATH_BASEBAND_TX).bin ../sdcard/$(PATH_BASEBAND_TX).bin $(TARGET).bin: modules $(MAKE_SPI_IMAGE) $(TARGET_BOOTSTRAP).bin $(TARGET_HACKRF_FIRMWARE).dfu $(TARGET_BASEBAND_TX)_inc.bin $(TARGET_APPLICATION).bin - $(MAKE_SPI_IMAGE) $(TARGET_BOOTSTRAP).bin $(TARGET_HACKRF_FIRMWARE).dfu $(TARGET_BASEBAND)_inc.bin $(TARGET_APPLICATION).bin $(TARGET).bin + $(MAKE_SPI_IMAGE) $(TARGET_BOOTSTRAP).bin $(TARGET_HACKRF_FIRMWARE).dfu $(TARGET_BASEBAND_TX)_inc.bin $(TARGET_APPLICATION).bin $(TARGET).bin $(TARGET_BOOTSTRAP).bin: $(TARGET_BOOTSTRAP).elf $(CP) -O binary $(TARGET_BOOTSTRAP).elf $(TARGET_BOOTSTRAP).bin diff --git a/firmware/application/main.cpp b/firmware/application/main.cpp index ac1c0108..412c74bc 100755 --- a/firmware/application/main.cpp +++ b/firmware/application/main.cpp @@ -19,8 +19,11 @@ * Boston, MA 02110-1301, USA. */ -//BUG: No audio in about when shown second time -//BUG: Description doesn't show up first time going to system>module info (UI drawn on top) +//BUG: No audio in about when shown second time +//BUG: Description doesn't show up first time going to system>module info (UI drawn on top) +//BUG: Module load and return to systemview +//TODO: EPAR transmit +//TODO: Use progressbars //TODO: Setting: Prefered input method //TODO: LCR emergency clear all //TODO: LCR receiver diff --git a/firmware/application/ui_handwrite.cpp b/firmware/application/ui_handwrite.cpp index f5b0e987..a6276091 100644 --- a/firmware/application/ui_handwrite.cpp +++ b/firmware/application/ui_handwrite.cpp @@ -25,32 +25,39 @@ #include "ch.h" #include "ff.h" -#include "unistroke.hpp" #include "portapack.hpp" #include "event_m0.hpp" -#include "string_format.hpp" #include "hackrf_hal.hpp" #include "portapack_shared_memory.hpp" -#include "time.hpp" #include using namespace portapack; namespace ui { + +void HandWriteView::paint(Painter& painter) { + _painter = &painter; +} HandWriteView::HandWriteView( NavigationView& nav, char txt[], uint8_t max_len ) { + const char special_chars[5] = {'\'', '.', '?', '!', '='}; _max_len = max_len; - _lowercase = false; - txtidx = 0; + // Handwriting alphabet definition here + handwriting = &handwriting_unistroke; + //memcpy(txtinput, txt, max_len+1); - - add_child(&text_input); + + add_children({ { + &text_input, + &button_case, + &button_ok + } }); const auto button_fn = [this](Button& button) { this->on_button(button); @@ -62,35 +69,45 @@ HandWriteView::HandWriteView( button.on_select = button_fn; button.set_parent_rect({ static_cast(n * 24), - static_cast(240), - 24, 20 + static_cast(236), + 24, 28 }); const std::string label { (char)(n + 0x30) }; button.set_text(label); - button.id = n; + button.id = n + 0x30; n++; } - //set_uppercase(); - /*add_child(&button_lowercase); - button_lowercase.on_select = [this, &nav, txt, max_len](Button&) { + n = 0; + for(auto& button : special_buttons) { + add_child(&button); + button.on_select = button_fn; + button.set_parent_rect({ + static_cast(50 + n * 24), + static_cast(270), + 24, 28 + }); + const std::string label { + (char)(special_chars[n]) + }; + button.set_text(label); + button.id = special_chars[n]; + n++; + } + + button_case.on_select = [this, &nav](Button&) { if (_lowercase == true) { _lowercase = false; - button_lowercase.set_text("UC"); - set_uppercase(); + button_case.set_text("LC"); } else { _lowercase = true; - button_lowercase.set_text("LC"); - set_lowercase(); + button_case.set_text("UC"); } - };*/ + }; - add_child(&text_debug_x); - add_child(&text_debug_y); - add_child(&button_done); - button_done.on_select = [this, &nav, txt, max_len](Button&) { + button_ok.on_select = [this, &nav, txt, max_len](Button&) { //memcpy(txt, txtinput, max_len+1); //on_changed(this->value()); nav.pop(); @@ -101,8 +118,8 @@ HandWriteView::HandWriteView( bool HandWriteView::on_touch(const TouchEvent event) { if (event.type == ui::TouchEvent::Type::Start) { - move_index = 0; - move_wait = 4; + stroke_index = 0; + move_wait = 3; tracing = true; } if (event.type == ui::TouchEvent::Type::End) { @@ -117,39 +134,60 @@ bool HandWriteView::on_touch(const TouchEvent event) { return true; } +void HandWriteView::clear_zone(Color color, bool flash) { + display.fill_rectangle( + {{0, 32}, {240, 216}}, + color + ); + if (flash) { + flash_timer = 4; + } else { + _painter->draw_rectangle( + {{0, 32}, {80, 216}}, + Color::grey() + ); + _painter->draw_rectangle( + {{80, 32}, {80, 216}}, + Color::grey() + ); + _painter->draw_rectangle( + {{160, 32}, {80, 216}}, + Color::grey() + ); + _painter->draw_rectangle( + {{0, 104}, {240, 72}}, + Color::grey() + ); + } +} + void HandWriteView::guess_letter() { uint8_t symbol, match, count, stroke_idx, stroke_data; Condition cond; Direction dir; bool matched; - // Clear drawing zone - display.fill_rectangle( - {{0, 16}, {240, 240}}, - Color::black() - ); - // Letter guessing - if (move_index) { - for (symbol = 0; symbol < handwriting_unistroke.letter_count; symbol++) { - count = handwriting_unistroke.letter[symbol].count; + if (stroke_index) { + for (symbol = 0; symbol < handwriting->letter_count; symbol++) { + count = handwriting->letter[symbol].count; matched = false; if (count) { // We have a count match to do - if ((count == 1) && (move_index == 1)) matched = true; - if ((count == 2) && (move_index == 2)) matched = true; - if ((count == 3) && (move_index > 2)) matched = true; + if ((count == 1) && (stroke_index == 1)) matched = true; + if ((count == 2) && (stroke_index == 2)) matched = true; + if ((count == 3) && (stroke_index > 2)) matched = true; } else { matched = true; } if (matched) { for (match = 0; match < 3; match++) { - cond = handwriting_unistroke.letter[symbol].match[match].cond; - dir = handwriting_unistroke.letter[symbol].match[match].dir; + cond = handwriting->letter[symbol].match[match].cond; + dir = handwriting->letter[symbol].match[match].dir; if ((cond != cond_empty) && (dir != dir_empty)) { if (cond == last) { - if (move_index) - stroke_idx = move_index - 1; + if (stroke_index) + stroke_idx = stroke_index - 1; else stroke_idx = 0; } else if (cond == stroke_a) @@ -160,7 +198,8 @@ void HandWriteView::guess_letter() { stroke_idx = 2; else stroke_idx = 3; - stroke_data = move_list[stroke_idx]; + if (stroke_idx >= stroke_index) break; + stroke_data = stroke_list[stroke_idx]; if ((dir & 0xF0) == 0xF0) { if ((dir & 0x0F) != (stroke_data & 0x0F)) break; } else if ((dir & 0x0F) == 0x0F) { @@ -177,22 +216,36 @@ void HandWriteView::guess_letter() { } } if (matched) { - if (symbol) - txtinput[txtidx++] = 'A' + symbol - 1; - else - txtinput[--txtidx] = 0; // Erase + if (symbol) { + if (_lowercase) + char_add('a' + symbol - 1); + else + char_add('A' + symbol - 1); + clear_zone(Color::green(), true); // Green flash + } else { + if (txtidx) { + txtinput[--txtidx] = 0; // Erase + clear_zone(Color::yellow(), true); // Yellow flash + } else { + clear_zone(Color::red(), true); // Red flash + } + } + } else { + clear_zone(Color::red(), true); // Red flash } } else { + // Short tap is space txtinput[txtidx++] = ' '; + clear_zone(Color::green(), true); // Green flash } update_text(); - move_index = 0; + stroke_index = 0; } void HandWriteView::add_stroke(uint8_t dir) { - if (move_index < 8) { - move_list[move_index] = dir; - move_index++; + if (stroke_index < 8) { + stroke_list[stroke_index] = dir; + stroke_index++; } else { guess_letter(); } @@ -200,18 +253,18 @@ void HandWriteView::add_stroke(uint8_t dir) { void HandWriteView::sample_pen() { int16_t diff_x, diff_y; - uint8_t dir, dir_ud, dir_lr; + uint8_t dir, dir_ud, dir_lr, stroke_prev; // Blink cursor if (!(sample_skip & 15)) { Point cursor_pos; cursor_pos.x = text_input.screen_rect().pos.x + (txtidx * 8); - cursor_pos.y = text_input.screen_rect().pos.y + 17; + cursor_pos.y = text_input.screen_rect().pos.y + 16 - 4; if (cursor) { display.fill_rectangle( - {{text_input.screen_rect().pos.x, cursor_pos.y}, {text_input.screen_rect().size.w, 4}}, + {cursor_pos, {text_input.screen_rect().size.w - cursor_pos.x, 4}}, Color::black() ); } else { @@ -223,17 +276,19 @@ void HandWriteView::sample_pen() { cursor = !cursor; } + if (flash_timer) { + if (flash_timer == 1) clear_zone(Color::black(), false); + flash_timer--; + } + if (!(sample_skip & 1)) { if (tracing) { if (move_wait) { - move_wait--; // ~133ms delay + move_wait--; // ~100ms delay to get rid of jitter from touch start } else { diff_x = current_pos.x - last_pos.x; diff_y = current_pos.y - last_pos.y; - - text_debug_x.set(to_string_dec_int(diff_x)); - text_debug_y.set(to_string_dec_int(diff_y)); - + if (current_pos.y <= 240) { display.fill_rectangle( {{current_pos.x, current_pos.y}, {4, 4}}, @@ -241,7 +296,7 @@ void HandWriteView::sample_pen() { ); } - dir = 0; + dir = 0; // UL by default if (abs(diff_x) > 7) { if (diff_x > 0) dir |= 0x01; // R @@ -255,41 +310,48 @@ void HandWriteView::sample_pen() { dir |= 0x20; // ? } + // Need at least two identical directions to validate stroke if ((dir & 0x11) == (dir_prev & 0x11)) dir_cnt++; else dir_cnt = 0; dir_prev = dir; - // text_debug_d.set(to_string_dec_uint(dir)); - if (dir_cnt > 1) { dir_cnt = 0; - if (move_index) { - if ((move_list[move_index - 1] != dir) && (dir != 0x22)) { + if (stroke_index) { + if ((stroke_list[stroke_index - 1] != dir) && (dir != 0x22)) { + // Register stroke if different from last one dir_ud = (dir & 0xF0); dir_lr = (dir & 0x0F); + stroke_prev = stroke_list[stroke_index - 1]; if (dir_ud == 0x20) { - if ((move_list[move_index - 1] & 0x0F) != dir_lr) add_stroke(dir); + // LR changed + if ((stroke_prev & 0x0F) != dir_lr) add_stroke(dir); } else if (dir_lr == 0x02) { - if ((move_list[move_index - 1] & 0xF0) != dir_ud) add_stroke(dir); + // UD changed + if ((stroke_prev & 0xF0) != dir_ud) add_stroke(dir); } else { - // Replacement ? - if (((move_list[move_index - 1] & 0xF0) == 0x20) && (dir_ud != 0x20)) { - if ((move_list[move_index - 1] & 0x0F) == dir_lr) { - move_list[move_index - 1] = dir; - } else if ((dir & 0x0F) == 0x02) { - // Merge - move_list[move_index - 1] = dir_ud | (move_list[move_index - 1] & 0x0F); + // Add direction + if (((stroke_prev & 0xF0) == 0x20) && (dir_ud != 0x20)) { + // Add UD + if ((stroke_prev & 0x0F) == dir_lr) { + // Replace totally + stroke_list[stroke_index - 1] = dir; + } else if (dir_lr == 0x02) { + // Merge UD + stroke_list[stroke_index - 1] = dir_ud | (stroke_prev & 0x0F); } else { add_stroke(dir); } - } else if (((move_list[move_index - 1] & 0x0F) == 0x02) && (dir_lr != 0x02)) { - if ((move_list[move_index - 1] & 0xF0) == dir_ud) { - move_list[move_index - 1] = dir; + } else if (((stroke_prev & 0x0F) == 0x02) && (dir_lr != 0x02)) { + // Add LR + if ((stroke_prev & 0xF0) == dir_ud) { + // Replace totally + stroke_list[stroke_index - 1] = dir; } else if (dir_ud == 0x20) { - // Merge - move_list[move_index - 1] = dir_lr | (move_list[move_index - 1] & 0xF0); + // Merge LR + stroke_list[stroke_index - 1] = dir_lr | (stroke_prev & 0xF0); } else { add_stroke(dir); } @@ -299,6 +361,7 @@ void HandWriteView::sample_pen() { } } } else { + // Register first stroke if (dir != 0x22) add_stroke(dir); } } @@ -319,6 +382,7 @@ void HandWriteView::on_show() { sample_pen(); } ); + clear_zone(Color::black(), false); } char * HandWriteView::value() { @@ -326,7 +390,7 @@ char * HandWriteView::value() { } void HandWriteView::on_button(Button& button) { - char_add(button.id + 0x30); + char_add(button.id); update_text(); } diff --git a/firmware/application/ui_handwrite.hpp b/firmware/application/ui_handwrite.hpp index 46e9b036..29add26c 100644 --- a/firmware/application/ui_handwrite.hpp +++ b/firmware/application/ui_handwrite.hpp @@ -25,10 +25,8 @@ #include "ui_painter.hpp" #include "ui_menu.hpp" #include "ui_navigation.hpp" -#include "ui_font_fixed_8x16.hpp" -#include "clock_manager.hpp" +#include "unistroke.hpp" #include "message.hpp" -#include "signal.hpp" namespace ui { @@ -38,6 +36,7 @@ public: HandWriteView(NavigationView& nav, char txt[], uint8_t max_len); + void paint(Painter& painter) override; void on_show() override; bool on_touch(const TouchEvent event) override; @@ -46,44 +45,41 @@ public: void char_add(const char c); private: + const HandWriting * handwriting; + Painter * _painter; uint8_t _max_len; uint8_t dir_cnt = 0; uint8_t dir_prev; - uint8_t txtidx; + uint8_t flash_timer = 0; + uint8_t txtidx = 0; bool cursor = false; bool tracing = false; - uint8_t move_index; + uint8_t stroke_index; uint8_t sample_skip, move_wait; - uint8_t move_list[8]; + uint8_t stroke_list[8]; Point start_pos, current_pos, last_pos; - bool _lowercase = false; - static constexpr size_t button_w = 240 / 5; - static constexpr size_t button_h = 28; + bool _lowercase = true; char txtinput[25] = {0}; void sample_pen(); void add_stroke(uint8_t dir); void guess_letter(); + void clear_zone(Color color, bool flash); Text text_input { { 8, 0, 224, 16 } }; - Text text_debug_x { - { 0, 16, 32, 16 } - }; - Text text_debug_y { - { 0, 32, 32, 16 } - }; std::array num_buttons; + std::array special_buttons; Button button_case { - { 88+64+16, 270, 32, 24 }, + { 8, 270, 32, 28 }, "UC" }; - Button button_done { - { 88, 270, 64, 24 }, - "Done" + Button button_ok { + { 190, 270, 40, 28 }, + "OK" }; void on_button(Button& button); diff --git a/firmware/application/ui_loadmodule.cpp b/firmware/application/ui_loadmodule.cpp index b045bee2..c6525ed6 100644 --- a/firmware/application/ui_loadmodule.cpp +++ b/firmware/application/ui_loadmodule.cpp @@ -172,6 +172,7 @@ LoadModuleView::LoadModuleView( if (ViewID == 1) nav.push(); if (ViewID == 2) nav.push(); if (ViewID == 3) nav.push(); + if (ViewID == 10) nav.push(); } else { nav.pop(); diff --git a/firmware/application/ui_navigation.cpp b/firmware/application/ui_navigation.cpp index 0a7133e4..f0712098 100644 --- a/firmware/application/ui_navigation.cpp +++ b/firmware/application/ui_navigation.cpp @@ -174,8 +174,6 @@ TranspondersMenuView::TranspondersMenuView(NavigationView& nav) { ReceiverMenuView::ReceiverMenuView(NavigationView& nav) { add_items<2>({ { { "Audio", ui::Color::white(), [&nav](){ nav.push(md5_baseband, 10, true); } }, - - //{ "Audio", ui::Color::white(), [&nav](){ nav.push(); } }, { "Transponders", ui::Color::white(), [&nav](){ nav.push(); } }, } }); on_left = [&nav](){ nav.pop(); }; @@ -199,9 +197,8 @@ SystemMenuView::SystemMenuView(NavigationView& nav) { { "HackRF", ui::Color::white(), [&nav](){ nav.push(); } }, } }); -/* //{ "Nordic/BTLE RX", ui::Color::cyan(), [&nav](){ nav.push(new NotImplementedView { nav }); } }, - { "Jammer", ui::Color::white(), [&nav](){ nav.push(md5_baseband, new JammerView(nav)); } }, + //{ "Jammer", ui::Color::white(), [&nav](){ nav.push(md5_baseband, new JammerView(nav)); } }, //{ "Audio file TX", ui::Color::white(), [&nav](){ nav.push(new NotImplementedView { nav }); } }, //{ "Encoder TX", ui::Color::green(), [&nav](){ nav.push(new NotImplementedView { nav }); } }, //{ "Whistle", ui::Color::purple(), [&nav](){ nav.push(new LoadModuleView { nav, md5_baseband, new WhistleView { nav, transmitter_model }}); } }, @@ -209,7 +206,7 @@ SystemMenuView::SystemMenuView(NavigationView& nav) { //{ "Xylos RX", ui::Color::green(), [&nav](){ nav.push(new LoadModuleView { nav, md5_baseband_tx, new XylosRXView { nav, receiver_model }}); } }, //{ "AFSK RX", ui::Color::cyan(), [&nav](){ nav.push(new LoadModuleView { nav, md5_baseband, new AFSKRXView { nav, receiver_model }}); } }, //{ "Numbers station", ui::Color::purple(), [&nav](){ nav.push(new LoadModuleView { nav, md5_baseband_tx, new NumbersStationView { nav, transmitter_model }}); } }, -*/ + } /* SystemView ************************************************************/ @@ -227,6 +224,8 @@ SystemView::SystemView( context_(context) { set_style(&style_default); + + char debugtxt[21]; // DEBUG constexpr ui::Dim status_view_height = 16; diff --git a/firmware/application/unistroke.hpp b/firmware/application/unistroke.hpp index 03eb6161..a654f541 100644 --- a/firmware/application/unistroke.hpp +++ b/firmware/application/unistroke.hpp @@ -31,15 +31,15 @@ enum Condition { enum Direction { dir_empty = -1, - Uw = 0x0F, // 0x - Dw = 0x1F, // 1x - Lw = 0xF0, // x0 - Rw = 0xF1, // x1 - U = 0x02, + Uw = 0x0F, // Wildcards + Dw = 0x1F, + Lw = 0xF0, + Rw = 0xF1, + U = 0x02, // Orthos D = 0x12, L = 0x20, R = 0x21, - UL = 0x00, + UL = 0x00, // Diagonals DL = 0x10, UR = 0x01, DR = 0x11 diff --git a/firmware/portapack-h1-firmware.bin b/firmware/portapack-h1-firmware.bin index d131f1db67f5cb43053f489b336910726474b477..adaf61ac2afa5c62bbf4a906c89b77a5325115b9 100644 GIT binary patch delta 6182 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