diff --git a/firmware/application/baseband_api.cpp b/firmware/application/baseband_api.cpp index 115f52d0b..08d493cb1 100644 --- a/firmware/application/baseband_api.cpp +++ b/firmware/application/baseband_api.cpp @@ -109,6 +109,16 @@ void set_pwmrssi(int32_t avg, bool enabled) { send_message(&message); } +void set_ook_data(const char ook_bitstream[], uint32_t stream_length, uint32_t samples_per_bit, uint8_t repeat) { + const OOKConfigureMessage message { + ook_bitstream, + stream_length, + samples_per_bit, + repeat + }; + send_message(&message); +} + static bool baseband_image_running = false; void run_image(const portapack::spi_flash::image_tag_t image_tag) { diff --git a/firmware/application/baseband_api.hpp b/firmware/application/baseband_api.hpp index 7797fd527..80a38b4ac 100644 --- a/firmware/application/baseband_api.hpp +++ b/firmware/application/baseband_api.hpp @@ -57,6 +57,7 @@ void set_pwmrssi(int32_t avg, bool enabled); void set_afsk_data(const char message_data[], const uint32_t afsk_samples_per_bit, const uint32_t afsk_phase_inc_mark, const uint32_t afsk_phase_inc_space, const uint8_t afsk_repeat, const uint32_t afsk_bw, const bool afsk_alt_format); +void set_ook_data(const char ook_bitstream[], uint32_t stream_length, uint32_t samples_per_bit, uint8_t repeat); void run_image(const portapack::spi_flash::image_tag_t image_tag); void shutdown(); diff --git a/firmware/application/ui_encoders.cpp b/firmware/application/ui_encoders.cpp index b2b92004d..f3e8c10ed 100644 --- a/firmware/application/ui_encoders.cpp +++ b/firmware/application/ui_encoders.cpp @@ -29,6 +29,7 @@ #include #include +#include using namespace portapack; @@ -46,55 +47,52 @@ EncodersView::~EncodersView() { void EncodersView::generate_frame() { uint8_t i; - debug_text.clear(); + debug_text = encoder_def->sync; + i = 0; - for (auto c : encoder_def->format) { + for (auto c : encoder_def->word_def) { if (c <= 'J') debug_text += encoder_def->bit_format.at(bitfields[i++].value()); } - //text_status.set(debug_text.substr(0, 28)); - if (visible()) parent()->set_dirty(); - - //afsk::generate_data(lcr_message, lcr_message_data); } void EncodersView::paint(Painter& painter) { - Coord x = 8, x_inc; - Coord y, prev_y = 0; + float x = 0, x_inc; + Coord y, prev_y = 1; + uint8_t prelude_length = encoder_def->sync.length(); - painter.fill_rectangle( { 0, 144, 240, 24 }, Color::black() ); + painter.fill_rectangle( { 0, 160, 240, 24 }, Color::black() ); - x_inc = 240 / debug_text.length(); + x_inc = 230.0 / (debug_text.length() - prelude_length); - for (auto c : debug_text) { + for (auto c : debug_text.substr(prelude_length)) { if (c == '0') y = 23; else y = 0; - if (prev_y != y) painter.draw_rectangle( { x, 144, 1, 24 }, Color::yellow() ); - painter.draw_rectangle( { x, 144 + y, x_inc, 1 }, Color::yellow() ); + if (prev_y != y) painter.draw_rectangle( { (Coord)x, 160, 1, 24 }, Color::yellow() ); + painter.draw_rectangle( { (Coord)x, 160 + y, ceil(x_inc), 1 }, Color::yellow() ); prev_y = y; x += x_inc; - if (x >= (240 - x_inc)) break; } } void EncodersView::update_progress() { - /*char str[16]; + char str[16]; text_status.set(" "); - if (tx_mode == SINGLE) { + //if (tx_mode == SINGLE) { strcpy(str, to_string_dec_uint(repeat_index).c_str()); strcat(str, "/"); - strcat(str, to_string_dec_uint(portapack::persistent_memory::afsk_repeats()).c_str()); + strcat(str, to_string_dec_uint(encoder_def->repeat_min).c_str()); text_status.set(str); progress.set_value(repeat_index); - } else if (tx_mode == SCAN) { + /*} else if (tx_mode == SCAN) { strcpy(str, to_string_dec_uint(repeat_index).c_str()); strcat(str, "/"); strcat(str, to_string_dec_uint(portapack::persistent_memory::afsk_repeats()).c_str()); @@ -111,20 +109,20 @@ void EncodersView::update_progress() { } void EncodersView::on_txdone(int n) { - /*char str[16]; + //char str[16]; if (n > 0) { // Repeating... repeat_index = n + 1; - if (tx_mode == SCAN) { + /*if (tx_mode == SCAN) { scan_progress++; update_progress(); - } else { + } else {*/ update_progress(); - } + //} } else { // Done transmitting - if ((tx_mode == SCAN) && (scan_index < (scan_count - 1))) { + /*if ((tx_mode == SCAN) && (scan_index < (scan_count - 1))) { transmitter_model.disable(); if (abort_scan) { // Kill scan process @@ -145,17 +143,19 @@ void EncodersView::on_txdone(int n) { update_progress(); start_tx(true); } - } else { + } else {*/ transmitter_model.disable(); tx_mode = IDLE; - update_progress(); - button_scan.set_style(&style_val); - button_scan.set_text("SCAN"); - } - }*/ + text_status.set("Done"); + progress.set_value(0); + //} + } } void EncodersView::start_tx(const bool scan) { + char ook_bitstream[64]; + uint32_t ook_bitstream_length; + /*if (scan) { if (tx_mode != SCAN) { scan_index = 0; @@ -167,17 +167,28 @@ void EncodersView::start_tx(const bool scan) { progress.set_max(scan_count * afsk_repeats); update_progress(); } - } else { + } else {*/ tx_mode = SINGLE; repeat_index = 1; - progress.set_max(afsk_repeats); + progress.set_max(encoder_def->repeat_min); update_progress(); - }*/ + //} generate_frame(); + + // Clear bitstream + memset(ook_bitstream, 0, 64); + + size_t n = 0; + for (auto c : debug_text) { + if (c != '0') + ook_bitstream[n >> 3] |= (1 << (7 - (n & 7))); + n++; + } + + ook_bitstream_length = n - 1; - /* - transmitter_model.set_tuning_frequency(portapack::persistent_memory::tuned_frequency()); + transmitter_model.set_tuning_frequency(433920000); // TODO: Change ! transmitter_model.set_baseband_configuration({ .mode = 0, .sampling_rate = 2280000U, @@ -189,15 +200,15 @@ void EncodersView::start_tx(const bool scan) { transmitter_model.set_baseband_bandwidth(1750000); transmitter_model.enable(); - baseband::set_afsk_data( - lcr_message_data, - 228000 / portapack::persistent_memory::afsk_bitrate(), - portapack::persistent_memory::afsk_mark_freq() * (0x40000 * 256) / (228000 / 25), - portapack::persistent_memory::afsk_space_freq() * (0x40000 * 256) / (228000 / 25), - afsk_repeats, - portapack::persistent_memory::afsk_bw() * 115, // See proc_fsk_lcr.cpp - afsk_format - );*/ + baseband::set_ook_data( + ook_bitstream, + ook_bitstream_length, + // 2280000/2 = 1140000Hz = 0,877192982us + // numberfield_clk.value() / encoder_def->clk_per_symbol + // 455000 / 12 = 37917Hz = 26,37339452us + 1140000 / ((numberfield_clk.value() * 1000) / encoder_def->clk_per_symbol), + encoder_def->repeat_min + ); } void EncodersView::on_bitfield() { @@ -205,6 +216,10 @@ void EncodersView::on_bitfield() { } void EncodersView::on_type_change(size_t index) { + std::string word_format; + size_t data_length; + size_t address_length; + enc_type = index; encoder_def = &encoder_defs[enc_type]; @@ -222,6 +237,45 @@ void EncodersView::on_type_change(size_t index) { n++; } + word_format = encoder_def->word_format; + size_t address_start = word_format.find_first_of("A"); + size_t data_start = word_format.find_first_of("D"); + size_t format_length = word_format.length(); + + if (address_start == std::string::npos) address_start = format_length; + if (data_start == std::string::npos) data_start = format_length; + + // Never did anything so dirty :( + if (!address_start) { + address_length = data_start; + data_length = format_length - address_length; + } else { + data_length = address_start; + address_length = format_length - data_length; + } + + if (address_length) { + text_format_a.hidden(false); + text_format_a.set_parent_rect( + { (2 + address_start) * 8, 12 * 8, address_length * 8, 16 } + ); + text_format_a.set_style(&style_address); + text_format_a.set(std::string(address_length, 'A')); + } else { + text_format_a.hidden(true); + } + + if (data_length) { + text_format_d.hidden(false); + text_format_d.set_parent_rect( + { (2 + data_start) * 8, 12 * 8, data_length * 8, 16 } + ); + text_format_d.set_style(&style_data); + text_format_d.set(std::string(data_length, 'D')); + } else { + text_format_d.hidden(true); + } + generate_frame(); } @@ -231,12 +285,13 @@ void EncodersView::on_show() { } EncodersView::EncodersView(NavigationView& nav) { - //baseband::run_image(portapack::spi_flash::image_tag_ook); + baseband::run_image(portapack::spi_flash::image_tag_ook); + + encoder_def = &encoder_defs[0]; add_children({ { &text_enctype, &options_enctype, - &text_bitfield, &text_clk, &numberfield_clk, &text_kHz, @@ -246,6 +301,9 @@ EncodersView::EncodersView(NavigationView& nav) { &text_wordduration, &numberfield_wordduration, &text_us2, + &text_bitfield, + &text_format_a, + &text_format_d, &text_waveform, &text_status, &progress, @@ -300,7 +358,7 @@ EncodersView::EncodersView(NavigationView& nav) { n++; } - options_enctype.set_selected_index(0); + //options_enctype.set_selected_index(0); button_transmit.set_style(&style_val); diff --git a/firmware/application/ui_encoders.hpp b/firmware/application/ui_encoders.hpp index 84acd9708..1f963a4e5 100644 --- a/firmware/application/ui_encoders.hpp +++ b/firmware/application/ui_encoders.hpp @@ -46,57 +46,92 @@ private: uint16_t clk_per_symbol; std::vector bit_format; uint8_t word_length; - std::string format; - bool sync_bit; + std::string word_def; + std::string word_format; + std::string sync; uint32_t default_frequency; uint8_t repeat_min; }; - // P = Prelude // S = Sync // 0~9 A~J = Address/data bits - const encoder_def_t encoder_defs[7] = { - // PT2260 + const encoder_def_t encoder_defs[11] = { + // PT2260: Data bits can only be 0 or 1 ! { 3, 1024, 128, { "10001000", "11101110", "10001110" }, - 12, "0123456789ABS", - true, 200000, 1 }, + 12, "0123456789ABS", "AAAAAAAAAADD", + "10000000000000000000000000000000", + 200000, 1 }, // PT2262 { 3, 32, 4, { "10001000", "11101110", "10001110" }, - 12, "0123456789ABS", - true, 30000, 4 }, + 12, "0123456789ABS", "AAAAAAAAADDD", + "10000000000000000000000000000000", + 30000, 4 }, // HK526E { 2, 24, 8, { "110", "100" }, - 12, "0123456789AB", - false, 20000, 4 }, + 12, "0123456789AB", "AAAAAAAAAAAA", + "", + 20000, 4 }, // HT12E { 2, 3, 1, { "011", "001" }, - 12, "PS0123456789AB", - true, 3000, 4 }, + 12, "S0123456789AB", "AAAAAAAADDDD", + "0000000000000000000000000000000000001", + 3000, 4 }, // VD5026 13 bits ? { 4, 128, 8, { "1000000010000000", "1111111011111110", "1111111010000000", "1000000011111110" }, - 12, "S0123456789AB", - true, 100000, 4 }, - + 12, "S0123456789AB", "AAAAAAAADDDD", + "000000000000000000000000000000000000000000000001", // ? + 100000, 4 }, + // UM3750 { 2, 96, 32, { "011", "001" }, - 12, "S0123456789AB", - true, 100000, 4 }, + 12, "S0123456789AB", "AAAAAAAAAAAA", + "1", + 100000, 4 }, // UM3758 { 3, 96, 16, { "011011", "001001", "011001" }, - 18, "S0123456789ABCDEFGH", - true, 160000, 4 } + 18, "S0123456789ABCDEFGH", "AAAAAAAAAADDDDDDDD", + "1", + 160000, 4 }, + + // BA5104 + { 2, 3072, 768, + { "1000", "1110" }, + 9, "S012345678", "DDAAAAAAA", + "", + 455000, 4 }, + + // MC145026 + { 3, 16, 1, + { "0111111101111111", "0100000001000000", "0111111101000000" }, + 9, "S012345678", "AAAAADDDD", + "000000000000000000", + 455000, 2 }, + + // HT6xxx + { 3, 198, 33, + { "011011", "001001", "001011" }, + 18, "S0123456789ABCDEFGH", "AAAAAAAAAAAADDDDDD", + "0000000000000000000000000000000000001011001011001", + 100000, 3 }, + + // TC9148 + { 2, 48, 12, + { "1000", "1110", }, + 12, "0123456789AB", "DDDDDDDDDDDD", + "", + 455000, 3 } }; enum tx_modes { @@ -106,7 +141,7 @@ private: }; uint8_t enc_type = 0; - const encoder_def_t * encoder_def = &encoder_defs[0]; + const encoder_def_t * encoder_def; tx_modes tx_mode = IDLE; //bool abort_scan = false; //uint8_t scan_count; @@ -114,7 +149,7 @@ private: //unsigned int scan_index; std::string debug_text = "0"; //rf::Frequency f; - //uint8_t repeat_index; + uint8_t repeat_index; void on_bitfield(); void on_type_change(size_t index); @@ -145,6 +180,17 @@ private: .foreground = Color::black(), }; + const Style style_address { + .font = font::fixed_8x16, + .background = Color::black(), + .foreground = Color::red(), + }; + const Style style_data { + .font = font::fixed_8x16, + .background = Color::black(), + .foreground = Color::blue(), + }; + std::array bitfields; Text text_enctype { @@ -153,15 +199,19 @@ private: }; OptionsField options_enctype { { 2 * 8, 5 * 8 }, - 7, + 8, { - { "PT2260 ", 0 }, - { "PT2262 ", 1 }, - { "HK526E ", 2 }, - { "HT12E ", 3 }, - { "VD5026 ", 4 }, - { "UM3750 ", 5 }, - { "UM3758 ", 6 } + { "PT2260 ", 0 }, + { "PT2262 ", 1 }, + { "HK526E ", 2 }, + { "HT12E ", 3 }, + { "VD5026 ", 4 }, + { "UM3750 ", 5 }, + { "UM3758 ", 6 }, + { "BA5104 ", 7 }, + { "MC145026", 8 }, + { "HT6xxx ", 9 }, + { "TC9148 ", 10 } } }; @@ -172,7 +222,7 @@ private: NumberField numberfield_clk { { 21 * 8, 3 * 8 }, 3, - { 1, 300 }, + { 1, 500 }, 1, ' ' }; @@ -188,7 +238,7 @@ private: NumberField numberfield_bitduration { { 20 * 8, 5 * 8 }, 4, - { 300, 9999 }, + { 50, 9999 }, 1, ' ' }; @@ -217,9 +267,11 @@ private: { 2 * 8, 8 * 8, 5 * 8, 16 }, "Word:" }; + Text text_format_a; + Text text_format_d; Text text_waveform { - { 1 * 8, 112, 9 * 8, 16 }, + { 1 * 8, 16 * 8, 9 * 8, 16 }, "Waveform:" }; diff --git a/firmware/baseband/CMakeLists.txt b/firmware/baseband/CMakeLists.txt index 7d571dbbb..1586c7cae 100644 --- a/firmware/baseband/CMakeLists.txt +++ b/firmware/baseband/CMakeLists.txt @@ -375,6 +375,13 @@ set(MODE_CPPSRC ) DeclareTargets(PRDS rds) +### OOK + +set(MODE_CPPSRC + proc_ook.cpp +) +DeclareTargets(POOK ook) + ### HackRF "factory" firmware add_custom_command( diff --git a/firmware/baseband/proc_ook.cpp b/firmware/baseband/proc_ook.cpp new file mode 100644 index 000000000..73a1ae56f --- /dev/null +++ b/firmware/baseband/proc_ook.cpp @@ -0,0 +1,108 @@ +/* + * Copyright (C) 2014 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_ook.hpp" +#include "portapack_shared_memory.hpp" +#include "sine_table_int8.hpp" +#include "event_m4.hpp" + +#include + +void OOKProcessor::execute(const buffer_c8_t& buffer) { + + // This is called at 2.28M/2048 = 1113Hz + + if (!configured) return; + + for (size_t i = 0; i= samples_per_bit) { + if (configured) { + cur_bit = (bitstream[bit_pos >> 3] << (bit_pos & 7)) & 0x80; + + bit_pos++; + + if (bit_pos >= stream_size) { + // End of data + if (repeat_counter < repeat) { + // Repeat + bit_pos = 0; + cur_bit = bitstream[0] & 0x80; + message.n = repeat_counter + 1; + shared_memory.application_queue.push(message); + repeat_counter++; + } else { + // Stop + cur_bit = 0; + message.n = 0; + shared_memory.application_queue.push(message); + configured = false; + } + } + } + + sample_count = 0; + } else { + sample_count++; + } + } else { + s--; + } + + if (cur_bit) phase += 100; // ? + + sphase = phase + (64 << 18); + + re = (sine_table_i8[(sphase & 0x03FC0000) >> 18]); + im = (sine_table_i8[(phase & 0x03FC0000) >> 18]); + + buffer.p[i] = {(int8_t)re, (int8_t)im}; + } +} + +void OOKProcessor::on_message(const Message* const p) { + const auto message = *reinterpret_cast(p); + + if (message.id == Message::ID::OOKConfigure) { + //memcpy(bitstream, message.ook_bitstream, 64); + + samples_per_bit = message.samples_per_bit; + stream_size = message.stream_length; + repeat = message.repeat - 1; + + s = 0; + sample_count = samples_per_bit; + repeat_counter = 0; + bit_pos = 0; + cur_bit = 0; + configured = true; + } +} + +int main() { + EventDispatcher event_dispatcher { std::make_unique() }; + event_dispatcher.run(); + return 0; +} diff --git a/firmware/baseband/proc_ook.hpp b/firmware/baseband/proc_ook.hpp new file mode 100644 index 000000000..400ec0498 --- /dev/null +++ b/firmware/baseband/proc_ook.hpp @@ -0,0 +1,58 @@ +/* + * Copyright (C) 2014 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_OOK_H__ +#define __PROC_OOK_H__ + +#include "baseband_processor.hpp" +#include "baseband_thread.hpp" + +class OOKProcessor : public BasebandProcessor { +public: + void execute(const buffer_c8_t& buffer) override; + + void on_message(const Message* const p) override; + +private: + bool configured = false; + + BasebandThread baseband_thread { 2280000, this, NORMALPRIO + 20, baseband::Direction::Transmit }; + + uint32_t samples_per_bit; + uint8_t repeat; + char bitstream[64]; + + uint8_t repeat_counter = 0; + int8_t re, im; + uint8_t s = 0; + + uint16_t bit_pos = 0; + uint8_t cur_bit = 0; + uint32_t sample_count; + uint32_t stream_size; + uint32_t phase, sphase; + int32_t tone_sample, sig, frq; + + TXDoneMessage message; +}; + +#endif diff --git a/firmware/common/message.hpp b/firmware/common/message.hpp index 71a9d64b8..fd3bc1ac7 100644 --- a/firmware/common/message.hpp +++ b/firmware/common/message.hpp @@ -70,8 +70,10 @@ public: XylosConfigure = 22, AFSKConfigure = 23, PWMRSSIConfigure = 24, - FIFOSignal = 25, - FIFOData = 26, + OOKConfigure = 25, + + FIFOSignal = 26, + FIFOData = 27, MAX }; @@ -511,6 +513,27 @@ public: char ccir_message[21]; }; +class OOKConfigureMessage : public Message { +public: + OOKConfigureMessage( + const char data[], + const uint32_t stream_length, + const uint32_t samples_per_bit, + const uint8_t repeat + ) : Message { ID::OOKConfigure }, + stream_length(stream_length), + samples_per_bit(samples_per_bit), + repeat(repeat) + { + memcpy(ook_bitstream, data, 64); + } + + char ook_bitstream[64]; + uint32_t stream_length; + uint32_t samples_per_bit; + uint8_t repeat; +}; + class RetuneMessage : public Message { public: RetuneMessage( diff --git a/firmware/common/spi_image.hpp b/firmware/common/spi_image.hpp index a6bf8eadc..c2378c848 100644 --- a/firmware/common/spi_image.hpp +++ b/firmware/common/spi_image.hpp @@ -78,6 +78,7 @@ constexpr image_tag_t image_tag_epar { 'P', 'E', 'P', 'R' }; constexpr image_tag_t image_tag_play_audio { 'P', 'P', 'A', 'U' }; constexpr image_tag_t image_tag_xylos { 'P', 'X', 'Y', 'L' }; constexpr image_tag_t image_tag_rds { 'P', 'R', 'D', 'S' }; +constexpr image_tag_t image_tag_ook { 'P', 'O', 'O', 'K' }; constexpr image_tag_t image_tag_hackrf { 'H', 'R', 'F', '1' }; diff --git a/firmware/portapack-h1-firmware.bin b/firmware/portapack-h1-firmware.bin index 1ff05982d..40420022b 100644 Binary files a/firmware/portapack-h1-firmware.bin and b/firmware/portapack-h1-firmware.bin differ