diff --git a/firmware/application/CMakeLists.txt b/firmware/application/CMakeLists.txt index 6a1dff411..e0c756db2 100644 --- a/firmware/application/CMakeLists.txt +++ b/firmware/application/CMakeLists.txt @@ -199,6 +199,7 @@ set(CPPSRC ${COMMON}/ais_packet.cpp ${COMMON}/pocsag_packet.cpp ${COMMON}/pocsag.cpp + ${COMMON}/morse.cpp ais_app.cpp tpms_app.cpp pocsag_app.cpp diff --git a/firmware/application/ui_morse.cpp b/firmware/application/ui_morse.cpp index 77c9a6e89..20638b70d 100644 --- a/firmware/application/ui_morse.cpp +++ b/firmware/application/ui_morse.cpp @@ -32,17 +32,25 @@ Continuous (Fox-oring) #include "portapack.hpp" #include "baseband_api.hpp" +#include "hackrf_gpio.hpp" +#include "portapack_shared_memory.hpp" +#include "ui_textentry.hpp" #include #include using namespace portapack; using namespace morse; +using namespace hackrf::one; // TODO: Live keying mode: Dit on left key, dah on right ? namespace ui { +void MorseView::on_set_text(NavigationView& nav) { + textentry(nav, buffer, 28); +} + void MorseView::focus() { tx_view.focus(); } @@ -52,21 +60,58 @@ MorseView::~MorseView() { baseband::shutdown(); } -void MorseView::paint(Painter& painter) { - (void)painter; +void MorseView::paint(Painter&) { + message = buffer; + text_message.set(message); +} + +static WORKING_AREA(ookthread_wa, 256); +static msg_t ookthread_fn(void * arg) { + uint32_t v = 0, delay = 0; + size_t i = 0; + uint8_t * message = shared_memory.bb_data.tones_data.message; + MorseView * arg_c = (MorseView*)arg; + + chRegSetThreadName("ookthread"); + for (i = 0; i < arg_c->symbol_count; i++) { + if (chThdShouldTerminate()) break; + + if (message[i] == 0) { + v = 1; + delay = MORSE_DOT; + } else if (message[i] == 1) { + v = 1; + delay = MORSE_DASH; + } else if (message[i] == 2) { + v = 0; + delay = MORSE_SYMBOL_SPACE; + } else if (message[i] == 3) { + v = 0; + delay = MORSE_LETTER_SPACE; + } else if (message[i] == 4) { + v = 0; + delay = MORSE_WORD_SPACE; + } + + gpio_tx.write(v); + arg_c->on_tx_progress(i, false); + + chThdSleepMilliseconds(delay * arg_c->time_unit_ms); + } + + gpio_tx.write(0); + arg_c->on_tx_progress(0, true); + chThdExit(0); + + return 0; } bool MorseView::start_tx() { - size_t symbol_count; - std::string message; - - if (checkbox_foxhunt.value()) { + if (checkbox_foxhunt.value()) message = foxhunt_codes[options_foxhunt.selected_index_value()]; - } else { - message = "ABCDEFGHIJKLMN"; - } - symbol_count = morse_encode(message, field_time_unit.value(), field_tone.value()); + time_unit_ms = field_time_unit.value(); + symbol_count = morse_encode(message, time_unit_ms, field_tone.value()); if (!symbol_count) { nav_.display_modal("Error", "Message too long.", INFO, nullptr); @@ -82,7 +127,11 @@ bool MorseView::start_tx() { transmitter_model.set_baseband_bandwidth(1750000); transmitter_model.enable(); - baseband::set_tones_data(transmitter_model.bandwidth(), 0, symbol_count, false, false); + if (options_modulation.selected_index() == 0) { + ookthread = chThdCreateStatic(ookthread_wa, sizeof(ookthread_wa), NORMALPRIO + 10, ookthread_fn, this); + } else { + baseband::set_tones_data(transmitter_model.bandwidth(), 0, symbol_count, false, false); + } return true; } @@ -100,21 +149,29 @@ MorseView::MorseView( NavigationView& nav ) : nav_ (nav) { + baseband::run_image(portapack::spi_flash::image_tag_tones); add_children({ + &labels, &checkbox_foxhunt, &options_foxhunt, - &text_time_unit, &field_time_unit, - &text_tone, &field_tone, + &options_modulation, + &text_message, + &button_message, &progressbar, &tx_view }); - field_time_unit.set_value(50); // 50ms - field_tone.set_value(700); // 700Hz + field_time_unit.set_value(50); // 50ms + field_tone.set_value(700); // 700Hz + options_modulation.set_selected_index(0); // CW + + button_message.on_select = [this, &nav](Button&) { + this->on_set_text(nav); + }; tx_view.on_edit_frequency = [this, &nav]() { auto new_view = nav.push(receiver_model.tuning_frequency()); @@ -129,6 +186,7 @@ MorseView::MorseView( }; tx_view.on_stop = [this]() { + chThdTerminate(ookthread); tx_view.set_transmitting(false); }; diff --git a/firmware/application/ui_morse.hpp b/firmware/application/ui_morse.hpp index b826b60c7..1f535e45e 100644 --- a/firmware/application/ui_morse.hpp +++ b/firmware/application/ui_morse.hpp @@ -34,6 +34,8 @@ #include "audio.hpp" #include "morse.hpp" +#include + using namespace morse; namespace ui { @@ -43,37 +45,32 @@ public: MorseView(NavigationView& nav); ~MorseView(); + MorseView(const MorseView&) = delete; + MorseView(MorseView&&) = delete; + MorseView& operator=(const MorseView&) = delete; + MorseView& operator=(MorseView&&) = delete; + void focus() override; void paint(Painter& painter) override; + void on_tx_progress(const int progress, const bool done); + uint32_t time_unit_ms { 0 }; + size_t symbol_count { 0 }; private: NavigationView& nav_; + char buffer[29] = "PORTAPACK"; + std::string message { }; bool start_tx(); - void on_tx_progress(const int progress, const bool done); + void on_set_text(NavigationView& nav); - Text text_time_unit { - { 4 * 8, 6 * 8, 15 * 8, 16 }, - "Time unit: ms" - }; - NumberField field_time_unit { - { 14 * 8, 6 * 8 }, - 3, - { 1, 999 }, - 1, - ' ' - }; + size_t modulation { 0 }; + Thread * ookthread { }; - Text text_tone { - { 4 * 8, 8 * 8, 11 * 8, 16 }, - "Tone: Hz" - }; - NumberField field_tone { - { 9 * 8, 8 * 8 }, - 4, - { 100, 9999 }, - 20, - ' ' + Labels labels { + { { 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() }, }; Checkbox checkbox_foxhunt { @@ -99,6 +96,41 @@ private: } }; + NumberField field_time_unit { + { 14 * 8, 6 * 8 }, + 3, + { 10, 999 }, + 1, + ' ' + }; + + NumberField field_tone { + { 9 * 8, 8 * 8 }, + 4, + { 100, 9999 }, + 20, + ' ' + }; + + OptionsField options_modulation { + { 15 * 8, 10 * 8 }, + 2, + { + { "CW", 0 }, + { "FM", 1 } + } + }; + + Text text_message { + { 1 * 8, 14 * 8, 28 * 8, 16 }, + "" + }; + + Button button_message { + { 1 * 8, 16 * 8, 12 * 8, 28 }, + "Set message" + }; + ProgressBar progressbar { { 2 * 8, 14 * 16, 208, 16 } }; diff --git a/firmware/application/ui_pocsag_tx.cpp b/firmware/application/ui_pocsag_tx.cpp index 7756c4fa6..0d981bfc7 100644 --- a/firmware/application/ui_pocsag_tx.cpp +++ b/firmware/application/ui_pocsag_tx.cpp @@ -24,6 +24,7 @@ #include "baseband_api.hpp" #include "string_format.hpp" +#include "ui_textentry.hpp" #include "portapack_persistent_memory.hpp" diff --git a/firmware/application/ui_pocsag_tx.hpp b/firmware/application/ui_pocsag_tx.hpp index 19cd2ada4..1b795158c 100644 --- a/firmware/application/ui_pocsag_tx.hpp +++ b/firmware/application/ui_pocsag_tx.hpp @@ -28,7 +28,6 @@ #include "ui_navigation.hpp" #include "ui_receiver.hpp" #include "ui_transmitter.hpp" -#include "ui_textentry.hpp" #include "bch_code.hpp" #include "message.hpp" #include "transmitter_model.hpp" @@ -106,8 +105,8 @@ private: }; Button button_message { - { 3 * 8, 14 * 8, 8 * 8, 28 }, - "Set" + { 3 * 8, 14 * 8, 12 * 8, 28 }, + "Set message" }; ProgressBar progressbar { diff --git a/firmware/baseband/proc_epar.cpp b/firmware/baseband/proc_epar.cpp deleted file mode 100644 index 3129feb3c..000000000 --- a/firmware/baseband/proc_epar.cpp +++ /dev/null @@ -1,110 +0,0 @@ -/* - * Copyright (C) 2015 Jared Boone, ShareBrained Technology, Inc. - * Copyright (C) 2016 Furrtek - * - * This file is part of PortaPack. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - -#include "proc_epar.hpp" - -#include "dsp_iir_config.hpp" -#include "audio_output.hpp" -#include "event_m4.hpp" -#include "portapack_shared_memory.hpp" -#include "sine_table.hpp" - -#include - -void EPARProcessor::execute(const buffer_c8_t& buffer) { - - // This is called at 1536000/2048 = 750Hz - - for (size_t i = 0; i= 9) { - s = 0; - - if (sample_count >= EPAR_TU) { - - if (state) { - // Send code - if (current_tu == 2) { - current_bit = shared_memory.epardata[bit_pos]; - if (bit_pos == 12) { - bit_pos = 0; - current_tu = 0; - state = 0; - } else { - bit_pos++; - } - - current_tu = 0; - } else { - current_tu++; - } - - sample = bitdef[current_bit][current_tu]; - } else { - // Pause - if (current_tu == EPAR_SPACE) { - if (repeat_count == EPAR_REPEAT) { - message.n = 100; // End of transmission code - transmit_done = true; - shared_memory.application_queue.push(message); - } - if (transmit_done == false) { - message.n = repeat_count; // Inform UI about progress (just as eye candy) - shared_memory.application_queue.push(message); - state = 1; - } - repeat_count++; - current_tu = 0; - } else { - current_tu++; - } - sample = -127; - } - - sample_count = 0; - } else { - sample_count++; - } - - } else { - s++; - } - - //FM - frq = sample * shared_memory.excursion; // 500=~3kHz wide - - phase = (phase + frq); - sphase = phase + (256<<16); - - re = (sine_table_f32[(sphase & 0x03FF0000)>>18]*127); - im = (sine_table_f32[(phase & 0x03FF0000)>>18]*127); - - buffer.p[i] = {(int8_t)re,(int8_t)im}; - } -} - -int main() { - EventDispatcher event_dispatcher { std::make_unique() }; - event_dispatcher.run(); - return 0; -} diff --git a/firmware/baseband/proc_epar.hpp b/firmware/baseband/proc_epar.hpp deleted file mode 100644 index 407feb01a..000000000 --- a/firmware/baseband/proc_epar.hpp +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Copyright (C) 2015 Jared Boone, ShareBrained Technology, Inc. - * Copyright (C) 2016 Furrtek - * - * This file is part of PortaPack. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - -#ifndef __PROC_EPAR_H__ -#define __PROC_EPAR_H__ - -#include "baseband_processor.hpp" -#include "baseband_thread.hpp" - -#include "dsp_decimate.hpp" -#include "dsp_demodulate.hpp" - -#include "audio_output.hpp" - -// One bit is 0.005119048s (~200bps ?) -// Time unit is 0.001706349s (586Hz) - -#define EPAR_TU 262-1 // 1536000/10/586 -#define EPAR_SPACE 33-1 -#define EPAR_REPEAT 26*2 // DEBUG - -// 0: 011 -// 1: 001 - -// Good: 1001110111111 -// Bad: 1100111011111 - -class EPARProcessor : public BasebandProcessor { -public: - void execute(const buffer_c8_t& buffer) override; - -private: - bool transmit_done; - const int8_t bitdef[2][3] = { - {-127, 127, 127}, - {-127, -127, 127} - }; - int8_t re, im; - uint8_t s; - uint8_t state_length = 0; - uint8_t current_bit = 0; - uint8_t current_tu = 0; - uint8_t bit_pos = 0; - uint8_t repeat_count = 0; - uint32_t sample_count = 0; - uint32_t aphase, phase, sphase; - int32_t sample, frq; - uint8_t state = 1; - TXDoneMessage message; -}; - -#endif diff --git a/firmware/portapack-h1-havoc.bin b/firmware/portapack-h1-havoc.bin index a49f5742c..5692c201c 100644 Binary files a/firmware/portapack-h1-havoc.bin and b/firmware/portapack-h1-havoc.bin differ