diff --git a/firmware/application/main.cpp b/firmware/application/main.cpp index 36a81e1c..ac1c0108 100755 --- a/firmware/application/main.cpp +++ b/firmware/application/main.cpp @@ -21,6 +21,10 @@ //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) +//TODO: Setting: Prefered input method +//TODO: LCR emergency clear all +//TODO: LCR receiver +//TODO: Xylos receiver //TODO: Morse coder //TODO: Playdead amnesia and login //TODO: Touch screen calibration @@ -33,8 +37,7 @@ //TODO: SIGFOX RX/TX //TODO: Reset baseband if module not found (instead of lockup in RAM loop) //TODO: Module name/filename in modules.hpp to indicate requirement in case it's not found ui_loadmodule -//TODO: LCD backlight PWM -//TODO: BUG: Crash after TX stop (unregister message !) +//BUG: Crash after TX stop (unregister message !) //TODO: Check bw setting in LCR TX //TODO: BUG: Crash after PSN entry in RDS TX //TODO: Bodet :) diff --git a/firmware/application/ui_handwrite.cpp b/firmware/application/ui_handwrite.cpp index fd67019a..f5b0e987 100644 --- a/firmware/application/ui_handwrite.cpp +++ b/firmware/application/ui_handwrite.cpp @@ -1,5 +1,6 @@ /* * Copyright (C) 2015 Jared Boone, ShareBrained Technology, Inc. + * Copyright (C) 2016 Furrtek * * This file is part of PortaPack. * @@ -98,47 +99,7 @@ HandWriteView::HandWriteView( //update_text(); } -bool HandWriteView::MM(uint8_t idx, char cmp) { - if (idx < move_index) { - if ((cmp == 'U') && ((move_list[idx] & 0xF0) == 0x00)) return true; - if ((cmp == 'D') && ((move_list[idx] & 0xF0) == 0x10)) return true; - if ((cmp == 'L') && ((move_list[idx] & 0x0F) == 0x00)) return true; - if ((cmp == 'R') && ((move_list[idx] & 0x0F) == 0x01)) return true; - } - return false; -} - -bool HandWriteView::MM(uint8_t idx, char cmpud, char cmplr) { - if (idx < move_index) { - if (cmpud == 'U') cmpud = 0; - if (cmpud == 'D') cmpud = 1; - if (cmpud == '?') cmpud = 2; - if (cmplr == 'L') cmplr = 0; - if (cmplr == 'R') cmplr = 1; - if (cmplr == '?') cmplr = 2; - if (((move_list[idx] >> 4) == cmpud) && ((move_list[idx] & 0x0F) == cmplr)) return true; - } - return false; -} - -bool HandWriteView::MI(uint8_t idx) { - if (move_index - 1 < idx) - return true; - else - return false; -} - -bool HandWriteView::MLAST(char cmp) { - if ((cmp == 'U') && ((move_list[move_index - 1] & 0xF0) == 0x00)) return true; - if ((cmp == 'D') && ((move_list[move_index - 1] & 0xF0) == 0x10)) return true; - if ((cmp == 'L') && ((move_list[move_index - 1] & 0x0F) == 0x00)) return true; - if ((cmp == 'R') && ((move_list[move_index - 1] & 0x0F) == 0x01)) return true; - return false; -} - bool HandWriteView::on_touch(const TouchEvent event) { - char guess; - if (event.type == ui::TouchEvent::Type::Start) { move_index = 0; move_wait = 4; @@ -146,92 +107,7 @@ bool HandWriteView::on_touch(const TouchEvent event) { } if (event.type == ui::TouchEvent::Type::End) { tracing = false; - - display.fill_rectangle( - {{0, 16}, {240, 230}}, - Color::black() - ); - - // Letter guessing - guess = ' '; - - if (MM(0, 'U')) { - if (MM(0, 'U', '?')) { - if (MI(1)) - guess = 'A'; - else - guess = 'F'; - } else if (MM(0, 'U', 'R')) { - if (MI(1)) { - guess = 'K'; - } else { - if (MM(1, 'L')) { - if (txtidx > 0) { - txtinput[--txtidx] = 0; // Erase - guess = '!'; - } - } else { - guess = 'N'; - } - } - } else if (MM(0, 'U', 'L')) { - if (MM(1, 'U', 'R')) guess = 'C'; - if (MM(1, 'D', 'L')) guess = 'M'; - } - } else if (MM(0, 'D')) { - if (MM(0, 'D', 'R') || MM(1, 'R')) - guess = 'P'; - else - guess = 'Q'; - if (MM(0, 'D', '?')) { - if (MI(1)) { - guess = 'I'; - } else { - if (MM(1, 'R') && MI(2)) { - guess = 'L'; - } else if (MM(1, 'L')) { - if (MI(2)) guess = 'J'; - } else if (MM(1, 'U', 'R')) { - if (MM(2, 'D')) guess = 'W'; - } - } - } - if (MM(0, 'D', 'R')) { - if (MI(1)) guess = 'R'; - if (MM(1, 'U', 'R') && MI(2)) guess = 'V'; - if (MM(1, 'D', 'L')) guess = 'B'; - } else if (MM(0, 'D', 'L')) { - if (MI(1)) guess = 'Y'; - if (MM(1, 'U', 'L') && MI(2)) guess = 'U'; - if (MM(1, 'D', 'R')) guess = 'D'; - } - } - - if (MM(0, 'L')) { - if (!MI(2) && (MLAST('U') || MLAST('L'))) guess = 'O'; - if (MM(0, '?', 'L')) { - if (MI(1)) - guess = 'E'; - else - if (MM(1, 'R')) guess = 'S'; - } - } else if (MM(0, 'R')) { - if (!MI(2) && (MLAST('U') || MLAST('R'))) guess = 'X'; - if (MM(0, '?', 'R')) { - if (MM(1, 'U') && MI(2)) { - guess = 'G'; - } else if (MM(1, 'D', '?') && MI(2)) { - guess = 'H'; - } else if (MM(1, 'L')) { - guess = 'Z'; - } else if (MI(1)) { - guess = 'T'; - } - } - } - - if (guess != '!') txtinput[txtidx++] = guess; - update_text(); + guess_letter(); } if (event.type == ui::TouchEvent::Type::Move) { if (tracing) { @@ -241,9 +117,90 @@ bool HandWriteView::on_touch(const TouchEvent event) { return true; } +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; + 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; + } 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; + if ((cond != cond_empty) && (dir != dir_empty)) { + if (cond == last) { + if (move_index) + stroke_idx = move_index - 1; + else + stroke_idx = 0; + } else if (cond == stroke_a) + stroke_idx = 0; + else if (cond == stroke_b) + stroke_idx = 1; + else if (cond == stroke_c) + stroke_idx = 2; + else + stroke_idx = 3; + stroke_data = move_list[stroke_idx]; + if ((dir & 0xF0) == 0xF0) { + if ((dir & 0x0F) != (stroke_data & 0x0F)) break; + } else if ((dir & 0x0F) == 0x0F) { + if ((dir & 0xF0) != (stroke_data & 0xF0)) break; + } else { + if (dir != stroke_data) break; + } + } + } + if (match == 3) + break; + else + matched = false; + } + } + if (matched) { + if (symbol) + txtinput[txtidx++] = 'A' + symbol - 1; + else + txtinput[--txtidx] = 0; // Erase + } + } else { + txtinput[txtidx++] = ' '; + } + update_text(); + move_index = 0; +} + +void HandWriteView::add_stroke(uint8_t dir) { + if (move_index < 8) { + move_list[move_index] = dir; + move_index++; + } else { + guess_letter(); + } +} + void HandWriteView::sample_pen() { int16_t diff_x, diff_y; - uint8_t dir; + uint8_t dir, dir_ud, dir_lr; // Blink cursor if (!(sample_skip & 15)) { @@ -277,10 +234,12 @@ void HandWriteView::sample_pen() { text_debug_x.set(to_string_dec_int(diff_x)); text_debug_y.set(to_string_dec_int(diff_y)); - display.fill_rectangle( - {{current_pos.x, current_pos.y}, {4, 4}}, - Color::grey() - ); + if (current_pos.y <= 240) { + display.fill_rectangle( + {{current_pos.x, current_pos.y}, {4, 4}}, + Color::grey() + ); + } dir = 0; if (abs(diff_x) > 7) { @@ -308,67 +267,40 @@ void HandWriteView::sample_pen() { dir_cnt = 0; if (move_index) { if ((move_list[move_index - 1] != dir) && (dir != 0x22)) { - if ((dir & 0xF0) == 0x20) { - if ((move_list[move_index - 1] & 0x0F) != (dir & 0x0F)) { - move_list[move_index] = dir; - move_index++; - } - } else if ((dir & 0x0F) == 0x02) { - if ((move_list[move_index - 1] & 0xF0) != (dir & 0xF0)) { - move_list[move_index] = dir; - move_index++; - } + dir_ud = (dir & 0xF0); + dir_lr = (dir & 0x0F); + if (dir_ud == 0x20) { + if ((move_list[move_index - 1] & 0x0F) != dir_lr) add_stroke(dir); + } else if (dir_lr == 0x02) { + if ((move_list[move_index - 1] & 0xF0) != dir_ud) add_stroke(dir); } else { // Replacement ? - if (((move_list[move_index - 1] & 0xF0) == 0x20) && ((dir & 0xF0) != 0x20)) { - if ((move_list[move_index - 1] & 0x0F) == (dir & 0x0F)) { + 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 & 0xF0) | (move_list[move_index - 1] & 0x0F); + move_list[move_index - 1] = dir_ud | (move_list[move_index - 1] & 0x0F); } else { - move_list[move_index] = dir; - move_index++; + add_stroke(dir); } - } else if (((move_list[move_index - 1] & 0x0F) == 0x02) && ((dir & 0x0F) != 0x02)) { - if ((move_list[move_index - 1] & 0xF0) == (dir & 0xF0)) { + } 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 ((dir & 0xF0) == 0x20) { + } else if (dir_ud == 0x20) { // Merge - move_list[move_index - 1] = (dir & 0x0F) | (move_list[move_index - 1] & 0xF0); + move_list[move_index - 1] = dir_lr | (move_list[move_index - 1] & 0xF0); } else { - move_list[move_index] = dir; - move_index++; + add_stroke(dir); } } else { - move_list[move_index] = dir; - move_index++; + add_stroke(dir); } } } } else { - if (dir != 0x22) { - move_list[move_index] = dir; - move_index++; - } + if (dir != 0x22) add_stroke(dir); } - - // DEBUG - /*if (move_index) { - memset(txtinput, 0, 20); - txtidx = 0; - for (i = 0; i < move_index; i++) { - if ((move_list[i] & 0x03) == 0) char_add('L'); - if ((move_list[i] & 0x03) == 1) char_add('R'); - if ((move_list[i] & 0x03) == 2) char_add('?'); - if ((move_list[i] >> 4) == 0) char_add('U'); - if ((move_list[i] >> 4) == 1) char_add('D'); - if ((move_list[i] >> 4) == 2) char_add('?'); - char_add(' '); - } - update_text(); - }*/ - } } @@ -405,13 +337,6 @@ void HandWriteView::char_add(const char c) { } } -void HandWriteView::char_delete() { - if (txtidx) { - txtidx--; - txtinput[txtidx] = ' '; - } -} - void HandWriteView::update_text() { text_input.set(txtinput); } diff --git a/firmware/application/ui_handwrite.hpp b/firmware/application/ui_handwrite.hpp index eedb7d23..46e9b036 100644 --- a/firmware/application/ui_handwrite.hpp +++ b/firmware/application/ui_handwrite.hpp @@ -1,5 +1,6 @@ /* * Copyright (C) 2015 Jared Boone, ShareBrained Technology, Inc. + * Copyright (C) 2016 Furrtek * * This file is part of PortaPack. * @@ -42,32 +43,26 @@ public: char * value(); - uint8_t txtidx; - void char_add(const char c); - void char_delete(); private: uint8_t _max_len; uint8_t dir_cnt = 0; uint8_t dir_prev; + uint8_t txtidx; bool cursor = false; bool tracing = false; uint8_t move_index; uint8_t sample_skip, move_wait; - uint8_t move_list[32]; // TODO: Cap ! + uint8_t move_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; - char txtinput[21] = {0}; // DEBUG - - bool MM(uint8_t idx, char cmp); - bool MM(uint8_t idx, char cmpud, char cmplr); - bool MI(uint8_t idx); - bool MLAST(char cmp); - + char txtinput[25] = {0}; void sample_pen(); + void add_stroke(uint8_t dir); + void guess_letter(); Text text_input { { 8, 0, 224, 16 } @@ -81,7 +76,7 @@ private: }; std::array num_buttons; - Button button_lowercase { + Button button_case { { 88+64+16, 270, 32, 24 }, "UC" }; diff --git a/firmware/application/ui_navigation.cpp b/firmware/application/ui_navigation.cpp index 6391690d..0a7133e4 100644 --- a/firmware/application/ui_navigation.cpp +++ b/firmware/application/ui_navigation.cpp @@ -229,7 +229,6 @@ SystemView::SystemView( set_style(&style_default); constexpr ui::Dim status_view_height = 16; - char debugtxt[21] = {0}; add_child(&status_view); status_view.set_parent_rect({ @@ -262,8 +261,8 @@ SystemView::SystemView( navigation_view.push(); else //navigation_view.push(); - //navigation_view.push(); - navigation_view.push(debugtxt, 20); + //navigation_view.push(debugtxt, 20); + navigation_view.push(); } Context& SystemView::context() const { diff --git a/firmware/application/unistroke.hpp b/firmware/application/unistroke.hpp index 1e19e9c3..03eb6161 100644 --- a/firmware/application/unistroke.hpp +++ b/firmware/application/unistroke.hpp @@ -1,5 +1,6 @@ /* * Copyright (C) 2015 Jared Boone, ShareBrained Technology, Inc. + * Copyright (C) 2016 Furrtek * * This file is part of PortaPack. * @@ -19,9 +20,6 @@ * Boston, MA 02110-1301, USA. */ -#define HWDIR_TWO 0x40 -#define HWDIR_ONLY 0x80 - enum Condition { cond_empty = -1, stroke_a = 0, @@ -33,55 +31,60 @@ enum Condition { enum Direction { dir_empty = -1, - Uw = 0x00, - Dw = 0x10, - Lw = 0x00, - Rw = 0x01, - U = 0x00 | HWDIR_ONLY, - D = 0x10 | HWDIR_ONLY, - L = 0x00 | HWDIR_ONLY, - R = 0x01 | HWDIR_ONLY, - UL = 0x00 | HWDIR_TWO, - DL = 0x10 | HWDIR_TWO, - UR = 0x01 | HWDIR_TWO, - DR = 0x11 | HWDIR_TWO + Uw = 0x0F, // 0x + Dw = 0x1F, // 1x + Lw = 0xF0, // x0 + Rw = 0xF1, // x1 + U = 0x02, + D = 0x12, + L = 0x20, + R = 0x21, + UL = 0x00, + DL = 0x10, + UR = 0x01, + DR = 0x11 }; struct HandWriting { + uint8_t letter_count; struct HandWritingLetter { - Condition cond; - Direction dir; - } letter[3]; - int8_t count; + struct HandWritingMatch { + Condition cond; + Direction dir; + } match[3]; + uint8_t count; + } letter[32]; }; -const HandWriting handwriting_unistroke[32] = { +const HandWriting handwriting_unistroke = { + 27, + { + {{{stroke_a, UL}, {cond_empty, dir_empty}, {cond_empty, dir_empty}}, 1}, // BS< 0=UL MI=1 {{{stroke_a, U}, {cond_empty, dir_empty}, {cond_empty, dir_empty}}, 1}, // A 0=U MI=1 - {{{stroke_a, DR}, {stroke_b, DL}, {cond_empty, dir_empty}}, 0}, // B 0=DR 1=DL + {{{stroke_a, DR}, {stroke_b, DL}, {cond_empty, dir_empty}}, 2}, // B 0=DR 1=DL MI=2 {{{stroke_a, UL}, {stroke_b, UR}, {cond_empty, dir_empty}}, 0}, // C 0=UL 1=UR {{{stroke_a, DL}, {stroke_b, DR}, {cond_empty, dir_empty}}, 0}, // D 0=DL 1=DR {{{stroke_a, L}, {cond_empty, dir_empty}, {cond_empty, dir_empty}}, 1}, // E 0=L MI=1 {{{stroke_a, U}, {stroke_b, R}, {cond_empty, dir_empty}}, 0}, // F 0=U 1=R {{{stroke_a, R}, {stroke_b, U}, {cond_empty, dir_empty}}, 0}, // G 0=R 1=U - {{{stroke_a, R}, {stroke_b, D}, {cond_empty, dir_empty}}, 0}, // H 0=R 1=D + {{{stroke_a, R}, {stroke_b, D}, {cond_empty, dir_empty}}, 2}, // H 0=R 1=D MI=2 {{{stroke_a, D}, {cond_empty, dir_empty}, {cond_empty, dir_empty}}, 1}, // I 0=D MI=1 - {{{stroke_a, D}, {stroke_b, L}, {cond_empty, dir_empty}}, 0}, // J 0=D 1=L + {{{stroke_a, D}, {stroke_b, L}, {cond_empty, dir_empty}}, 2}, // J 0=D 1=L MI=2 {{{stroke_a, UR}, {cond_empty, dir_empty}, {cond_empty, dir_empty}}, 1}, // K 0=UR MI=1 - {{{stroke_a, D}, {stroke_b, R}, {cond_empty, dir_empty}}, 0}, // L 0=D 1=R - {{{stroke_a, UL}, {stroke_b, DL}, {cond_empty, dir_empty}}, 0}, // M 0=UL 1=DL - {{{stroke_a, UR}, {stroke_b, DR}, {cond_empty, dir_empty}}, 0}, // N 0=UR 1=DR - {{{stroke_a, Lw}, {last, Lw}, {cond_empty, dir_empty}}, 2}, // O 0=Lw MI>2 -=Lw !!! - {{{stroke_a, Dw}, {last, Dw}, {cond_empty, dir_empty}}, 2}, // P 0=Dw MI>2 -=Dw !!! - {{{stroke_a, Dw}, {stroke_b, Lw}, {cond_empty, dir_empty}}, 2}, // Q 0=Dw MI>2 1=Lw + {{{stroke_a, D}, {stroke_b, R}, {cond_empty, dir_empty}}, 2}, // L 0=D 1=R MI=2 + {{{stroke_a, UL}, {stroke_b, DL}, {cond_empty, dir_empty}}, 2}, // M 0=UL 1=DL MI=2 + {{{stroke_a, UR}, {stroke_b, DR}, {cond_empty, dir_empty}}, 2}, // N 0=UR 1=DR MI=2 + {{{stroke_a, DL}, {last, Lw}, {cond_empty, dir_empty}}, 3}, // O 0=DL MI>2 -=Uw + {{{stroke_a, DR}, {last, Dw}, {cond_empty, dir_empty}}, 3}, // P 0=DR MI>2 -=Dw + {{{stroke_a, DL}, {last, Dw}, {cond_empty, dir_empty}}, 3}, // Q 0=DL MI>2 -=Dw {{{stroke_a, DR}, {cond_empty, dir_empty}, {cond_empty, dir_empty}}, 1}, // R 0=DR MI=1 - {{{stroke_a, Lw}, {stroke_b, Rw}, {cond_empty, dir_empty}}, 0}, // S 0=Lw 1=Rw + {{{stroke_a, Lw}, {stroke_b, DR}, {cond_empty, dir_empty}}, 0}, // S 0=Lw 1=DR {{{stroke_a, R}, {cond_empty, dir_empty}, {cond_empty, dir_empty}}, 1}, // T 0=R MI=1 - {{{stroke_a, DL}, {stroke_b, UL}, {cond_empty, dir_empty}}, 2}, // U 0=DL 1=UL MI=2 - {{{stroke_a, DR}, {stroke_b, UR}, {cond_empty, dir_empty}}, 2}, // V 0=DR 1=UR MI=2 + {{{stroke_a, DL}, {stroke_b, UL}, {cond_empty, dir_empty}}, 2}, // U 0=DL 1=UL + {{{stroke_a, DR}, {stroke_b, UR}, {cond_empty, dir_empty}}, 2}, // V 0=DR 1=UR {{{stroke_a, D}, {stroke_b, UR}, {stroke_c, D}}, 0}, // W 0=D 1=UR 2=D - {{{stroke_a, Rw}, {last, Rw}, {cond_empty, dir_empty}}, 0}, // X 0=Rw MI>2 -=Rw + {{{stroke_a, DR}, {last, Uw}, {cond_empty, dir_empty}}, 3}, // X 0=DR MI>2 -=Uw {{{stroke_a, DL}, {cond_empty, dir_empty}, {cond_empty, dir_empty}}, 1}, // Y 0=DL MI=1 {{{stroke_a, Rw}, {stroke_b, DL}, {cond_empty, dir_empty}}, 0}, // Z 0=Rw 1=DL - - // Erase 0=UR MI!1 1=L + } }; diff --git a/firmware/portapack-h1-firmware.bin b/firmware/portapack-h1-firmware.bin index ff7dd341..d131f1db 100644 Binary files a/firmware/portapack-h1-firmware.bin and b/firmware/portapack-h1-firmware.bin differ