diff --git a/firmware/application/main.cpp b/firmware/application/main.cpp index 39652aa4f..471400926 100755 --- a/firmware/application/main.cpp +++ b/firmware/application/main.cpp @@ -29,7 +29,7 @@ //TEST: Imperial in whipcalc -//TODO: Morse transmition time estimate +//TODO: Morse use prosigns //TODO: Morse live keying mode ? /* Keying speed: 60 or 75 PARIS diff --git a/firmware/application/ui_morse.cpp b/firmware/application/ui_morse.cpp index c95a85341..bed6cb7c3 100644 --- a/firmware/application/ui_morse.cpp +++ b/firmware/application/ui_morse.cpp @@ -27,6 +27,7 @@ #include "hackrf_gpio.hpp" #include "portapack_shared_memory.hpp" #include "ui_textentry.hpp" +#include "string_format.hpp" #include #include @@ -53,6 +54,7 @@ MorseView::~MorseView() { void MorseView::paint(Painter&) { message = buffer; text_message.set(message); + update_tx_duration(); } static WORKING_AREA(ookthread_wa, 256); @@ -87,11 +89,9 @@ static msg_t ookthread_fn(void * arg) { } bool MorseView::start_tx() { - if (checkbox_foxhunt.value()) - message = foxhunt_codes[options_foxhunt.selected_index_value()]; - + // Re-generate message, just in case time_unit_ms = field_time_unit.value(); - symbol_count = morse_encode(message, time_unit_ms, field_tone.value()); + symbol_count = morse_encode(message, time_unit_ms, field_tone.value(), &time_units); if (!symbol_count) { nav_.display_modal("Error", "Message too long.", INFO, nullptr); @@ -116,6 +116,20 @@ bool MorseView::start_tx() { return true; } +void MorseView::update_tx_duration() { + uint32_t duration_ms; + + time_unit_ms = field_time_unit.value(); + symbol_count = morse_encode(message, time_unit_ms, field_tone.value(), &time_units); + + if (symbol_count) { + duration_ms = time_units * time_unit_ms; + text_tx_duration.set(to_string_dec_uint(duration_ms / 1000) + "." + to_string_dec_uint((duration_ms / 100) % 10, 1) + "s "); + } else { + text_tx_duration.set("-"); + } +} + void MorseView::on_tx_progress(const int progress, const bool done) { if (done) { transmitter_model.disable(); @@ -129,7 +143,6 @@ MorseView::MorseView( NavigationView& nav ) : nav_ (nav) { - baseband::run_image(portapack::spi_flash::image_tag_tones); add_children({ @@ -139,6 +152,7 @@ MorseView::MorseView( &field_time_unit, &field_tone, &options_modulation, + &text_tx_duration, &text_message, &button_message, &progressbar, @@ -149,6 +163,24 @@ MorseView::MorseView( field_tone.set_value(700); // 700Hz options_modulation.set_selected_index(0); // CW + checkbox_foxhunt.on_select = [this](Checkbox&, bool v) { + if (v) { + message = foxhunt_codes[options_foxhunt.selected_index_value()]; + strncpy(buffer, message.c_str(), sizeof(buffer)); + text_message.set(message); + update_tx_duration(); + } + }; + + options_foxhunt.on_change = [this](size_t, int32_t) { + if (checkbox_foxhunt.value()) + update_tx_duration(); + }; + + field_time_unit.on_change = [this](int32_t) { + update_tx_duration(); + }; + button_message.on_select = [this, &nav](Button&) { this->on_set_text(nav); }; @@ -169,7 +201,6 @@ MorseView::MorseView( chThdTerminate(ookthread); tx_view.set_transmitting(false); }; - } } /* namespace ui */ diff --git a/firmware/application/ui_morse.hpp b/firmware/application/ui_morse.hpp index 4deacbd2e..551625c61 100644 --- a/firmware/application/ui_morse.hpp +++ b/firmware/application/ui_morse.hpp @@ -63,8 +63,10 @@ private: NavigationView& nav_; char buffer[29] = "PORTAPACK"; std::string message { }; + uint32_t time_units { 0 }; bool start_tx(); + void update_tx_duration(); void on_set_text(NavigationView& nav); size_t modulation { 0 }; @@ -74,6 +76,7 @@ private: { { 4 * 8, 6 * 8 }, "Time unit: ms", Color::light_grey() }, { { 4 * 8, 8 * 8 }, "Tone: Hz", Color::light_grey() }, { { 4 * 8, 10 * 8 }, "Modulation:", Color::light_grey() }, + { { 1 * 8, 14 * 8 }, "TX will last", Color::light_grey() } }; Checkbox checkbox_foxhunt { @@ -124,18 +127,23 @@ private: } }; + Text text_tx_duration { + { 14 * 8, 14 * 8, 4 * 8, 16 }, + "-" + }; + Text text_message { - { 1 * 8, 14 * 8, 28 * 8, 16 }, + { 1 * 8, 18 * 8, 28 * 8, 16 }, "" }; Button button_message { - { 1 * 8, 16 * 8, 12 * 8, 28 }, + { 1 * 8, 20 * 8, 12 * 8, 28 }, "Set message" }; ProgressBar progressbar { - { 2 * 8, 14 * 16, 208, 16 } + { 2 * 8, 28 * 8, 208, 16 } }; TransmitterView tx_view { diff --git a/firmware/common/morse.cpp b/firmware/common/morse.cpp index e8c6a7527..3ec2e5590 100644 --- a/firmware/common/morse.cpp +++ b/firmware/common/morse.cpp @@ -31,43 +31,48 @@ using namespace portapack; namespace morse { // Returns 0 if message is too long -size_t morse_encode(std::string& message, const uint32_t time_unit_ms, const uint32_t tone) { +size_t morse_encode(std::string& message, const uint32_t time_unit_ms, + const uint32_t tone, uint32_t * const time_units) { + size_t i, c; - uint8_t code, code_size; + uint16_t code, code_size; uint8_t morse_message[256]; + *time_units = 0; + ToneDef * tone_defs = shared_memory.bb_data.tones_data.tone_defs; i = 0; for (char& ch : message) { - if ((ch >= 'a') && (ch <= 'z')) // Make uppercase + if (i > 256) return 0; + + if ((ch >= 'a') && (ch <= 'z')) // Make uppercase ch -= 32; - if ((ch >= 'A') && (ch <= 'Z')) { - code = morse_ITU[ch - 'A' + 10]; - } else if ((ch >= '0') && (ch <= '9')) { - code = morse_ITU[ch - '0']; - } else { - ch = ' '; // Default to space char - code = 0; + if ((ch >= '!') && (ch <= '_')) { + code = morse_ITU[ch - '!']; + } else { + code = 0; // Default to space char } - if (ch == ' ') { + if (!code) { if (i) - morse_message[i - 1] = 4; // Word space + morse_message[i - 1] = 4; // Word space } else { code_size = code & 7; for (c = 0; c < code_size; c++) { - morse_message[i++] = ((code << c) & 0x80) ? 1 : 0; // Dot/dash - morse_message[i++] = 2; // Symbol space + morse_message[i++] = ((code << c) & 0x8000) ? 1 : 0; // Dot/dash + morse_message[i++] = 2; // Symbol space } - morse_message[i - 1] = 3; // Letter space + morse_message[i - 1] = 3; // Letter space } - } - if (i > 256) return 0; + // Count time units + for (c = 0; c < i; c++) { + *time_units += morse_symbols[morse_message[c]]; + } memcpy(shared_memory.bb_data.tones_data.message, morse_message, i); diff --git a/firmware/common/morse.hpp b/firmware/common/morse.hpp index 92ad98098..00384a08c 100644 --- a/firmware/common/morse.hpp +++ b/firmware/common/morse.hpp @@ -26,7 +26,6 @@ #include "tonesets.hpp" #include "portapack_shared_memory.hpp" -//#define MORSE_UNIT (MORSE_SAMPLE_RATE * 0.05) // 1536000*0.05 (50ms) #define MORSE_DOT 1 #define MORSE_DASH 3 #define MORSE_SYMBOL_SPACE 1 @@ -43,7 +42,8 @@ const uint32_t morse_symbols[5] = { MORSE_WORD_SPACE }; -size_t morse_encode(std::string& message, const uint32_t time_unit_ms, const uint32_t tone); +size_t morse_encode(std::string& message, const uint32_t time_unit_ms, + const uint32_t tone, uint32_t * const time_units); const std::string foxhunt_codes[11] = { { "MOE" }, // -----. @@ -60,48 +60,8 @@ const std::string foxhunt_codes[11] = { }; // 0=dot 1=dash -const uint8_t morse_ITU[36] = { - // Code Size - 0b11111101, // 0: 11111 101 - 0b01111101, // 1: 01111 101 - 0b00111101, // 2: 00111 101 - 0b00011101, // 3: 00011 101 - 0b00001101, // 4: 00001 101 - 0b00000101, // 5: 00000 101 - 0b10000101, // 6: 10000 101 - 0b11000101, // 7: 11000 101 - 0b11100101, // 8: 11100 101 - 0b11110101, // 9: 11110 101 - 0b01000010, // A: 01--- 010 - 0b10000100, // B: 1000- 100 - 0b10100100, // C: 1010- 100 - 0b10000011, // D: 100-- 011 - 0b00000001, // E: 0---- 001 - 0b00100100, // F: 0010- 100 - 0b11000011, // G: 110-- 011 - 0b00000100, // H: 0000- 100 - 0b00000010, // I: 00--- 010 - 0b01110100, // J: 0111- 100 - 0b10100011, // K: 101-- 011 - 0b01000100, // L: 0100- 100 - 0b11000010, // M: 11--- 010 - 0b10000010, // N: 10--- 010 - 0b11100011, // O: 111-- 011 - 0b01100100, // P: 0110- 100 .#-###-###.# ##.#-### ##.#-###.# ##.#.# ##.#.#.# = 48 units - 0b11010100, // Q: 1101- 100 60s: 1.25s/unit - 0b01000011, // R: 010-- 011 75s: 1.5625s/unit - 0b00000011, // S: 000-- 011 - 0b10000001, // T: 1---- 001 - 0b00100011, // U: 001-- 011 - 0b00010100, // V: 0001- 100 - 0b01100011, // W: 011-- 011 - 0b10010100, // X: 1001- 100 - 0b10110100, // Y: 1011- 100 - 0b11000100 // Z: 1100- 100 -}; - -const uint16_t morse_special[23] = { - // Code Size +const uint16_t morse_ITU[63] = { + // Code Size 0b1010110000000110, // !: 101011- 110 0b0100100000000110, // ": 010010- 110 0, // # @@ -117,7 +77,16 @@ const uint16_t morse_special[23] = { 0b1000010000000110, // -: 100001- 110 0b0101010000000110, // .: 010101- 110 0b1001000000000101, // /: 10010-- 101 - + 0b1111100000000101, // 0: 11111-- 101 + 0b0111100000000101, // 1: 01111-- 101 + 0b0011100000000101, // 2: 00111-- 101 + 0b0001100000000101, // 3: 00011-- 101 + 0b0000100000000101, // 4: 00001-- 101 + 0b0000000000000101, // 5: 00000-- 101 + 0b1000000000000101, // 6: 10000-- 101 + 0b1100000000000101, // 7: 11000-- 101 + 0b1110000000000101, // 8: 11100-- 101 + 0b1111000000000101, // 9: 11110-- 101 0b1110000000000110, // :: 111000- 110 0b1010100000000110, // ;: 101010- 110 0, // < @@ -125,7 +94,36 @@ const uint16_t morse_special[23] = { 0, // > 0b0011000000000110, // ?: 001100- 110 0b0110100000000110, // @: 011010- 110 - + 0b0100000000000010, // A: 01----- 010 + 0b1000000000000100, // B: 1000--- 100 + 0b1010000000000100, // C: 1010--- 100 + 0b1000000000000011, // D: 100---- 011 + 0b0000000000000001, // E: 0------ 001 + 0b0010000000000100, // F: 0010--- 100 + 0b1100000000000011, // G: 110---- 011 + 0b0000000000000100, // H: 0000--- 100 + 0b0000000000000010, // I: 00----- 010 + 0b0111000000000100, // J: 0111--- 100 + 0b1010000000000011, // K: 101---- 011 + 0b0100000000000100, // L: 0100--- 100 + 0b1100000000000010, // M: 11----- 010 + 0b1000000000000010, // N: 10----- 010 + 0b1110000000000011, // O: 111---- 011 + 0b0110000000000100, // P: 0110--- 100 .#-###-###.# ##.#-### ##.#-###.# ##.#.# ##.#.#.# = 48 units + 0b1101000000000100, // Q: 1101--- 100 + 0b0100000000000011, // R: 010---- 011 + 0b0000000000000011, // S: 000---- 011 + 0b1000000000000001, // T: 1------ 001 + 0b0010000000000011, // U: 001---- 011 + 0b0001000000000100, // V: 0001--- 100 + 0b0110000000000011, // W: 011---- 011 + 0b1001000000000100, // X: 1001--- 100 + 0b1011000000000100, // Y: 1011--- 100 + 0b1100000000000100, // Z: 1100--- 100 + 0, // [ + 0, // Back-slash + 0, // ] + 0, // ^ 0b0011010000000110 // _: 001101- 110 }; diff --git a/firmware/hackrf_one_usb_ram.dfu b/firmware/hackrf_one_usb_ram.dfu index 49e0eee10..f87be5129 100644 Binary files a/firmware/hackrf_one_usb_ram.dfu and b/firmware/hackrf_one_usb_ram.dfu differ diff --git a/firmware/portapack-h1-havoc.bin b/firmware/portapack-h1-havoc.bin index ebb101846..a488f07c1 100644 Binary files a/firmware/portapack-h1-havoc.bin and b/firmware/portapack-h1-havoc.bin differ