Added tabs in OOK encoders app

Simplified credits scrolling
This commit is contained in:
furrtek 2017-08-28 22:17:02 +01:00
parent 6fcb2efdcf
commit cd6a1a7f3f
7 changed files with 479 additions and 428 deletions

View File

@ -29,6 +29,7 @@
namespace encoders {
#define ENC_TYPES_COUNT 14
#define OOK_SAMPLERATE 2280000U
struct encoder_def_t {
std::string name; // Encoder chip ref/name

View File

@ -38,111 +38,100 @@ using namespace portapack;
namespace ui {
void AboutView::update() {
size_t c;
int32_t n;
std::string text;
Coord y_val, x_pos = 0;
uint32_t flag;
if (scroll & 1) {
if (!((scroll >> 1) & 15)) {
if (line_feed) {
line_feed = false;
} else {
// Find a free text widget
for (c = 0; c < 10; c++)
if (text_line[c].screen_pos().y() >= 200) break;
if (c < 10) {
flag = credits[credits_index].flag & 0x3F;
line_feed = (credits[credits_index].flag & 0x40) ? true : false;
if (flag == SECTION) {
if (!second) {
text = credits[credits_index].role;
if (credits[credits_index].name != "")
second = true;
else {
credits_index++;
line_feed = true;
}
} else {
text = credits[credits_index].name;
second = false;
line_feed = true;
credits_index++;
}
x_pos = (240 - (text.size() * 8)) / 2;
} else if (flag == TITLE) {
text = credits[credits_index].role;
x_pos = 120 - (text.size() * 8);
if (credits[credits_index].name != "")
text += " " + credits[credits_index].name;
credits_index++;
} else if (flag == MEMBER) {
if (!second) {
text = credits[credits_index].role;
if (credits[credits_index].name != "")
second = true;
else
credits_index++;
} else {
text = credits[credits_index].name;
second = false;
credits_index++;
}
x_pos = 136;
}
if (!(flag & 0x80)) {
text_line[c].set_parent_rect({{ x_pos, 200 - 16 }, { (Dim)text.size() * 8, 17 }});
text_line[c].set(text);
text_line[c].hidden(false);
}
}
}
}
// This is pretty much WaterfallView but in the opposite direction
CreditsWidget::CreditsWidget(
Rect parent_rect
) : Widget { parent_rect }
{
}
// Scroll text lines
for (c = 0; c < 10; c++) {
y_val = text_line[c].screen_pos().y() - 16;
if (y_val < 32) {
text_line[c].set_parent_rect({{ text_line[c].screen_pos().x(), 200 }, { text_line[c].size() }});
text_line[c].hidden(true);
} else {
if (y_val < 200) {
text_line[c].set_parent_rect({{ text_line[c].screen_pos().x(), y_val - 1 }, { text_line[c].size() }});
n = (y_val - 32) >> 2;
if (n > 19)
n = (38 - n);
else
n -= 3;
if (n > 3) n = 3;
if (n < 0) n = 0;
text_line[c].set_style(&styles[n]);
}
}
void CreditsWidget::paint(Painter&) {
}
void CreditsWidget::on_show() {
clear();
const auto screen_r = screen_rect();
display.scroll_set_area(screen_r.top(), screen_r.bottom());
}
void CreditsWidget::on_hide() {
display.scroll_disable();
}
void CreditsWidget::new_row(
const std::array<Color, 240>& pixel_row
) {
const auto draw_y = display.scroll(-1);
display.draw_pixels(
{ { 0, draw_y }, { 240, 1 } },
pixel_row
);
}
void CreditsWidget::clear() {
display.fill_rectangle(
screen_rect(),
Color::black()
);
}
void AboutView::update() {
size_t i = 0;
std::array<Color, 240> pixel_row;
slow_down++;
if (slow_down & 1) return;
if (!timer) {
if (loop) {
credits_index = 0;
loop = false;
}
text = credits[credits_index].text;
timer = credits[credits_index].delay;
start_pos = credits[credits_index].start_pos;
if (timer < 0) {
timer = 240;
loop = true;
} else {
timer += 16;
}
render_line = 0;
credits_index++;
} else
timer--;
if (render_line < 16) {
for (const auto c : text) {
const auto glyph = style().font.glyph(c);
const size_t start = (glyph.size().width() / 8) * render_line;
for(Dim c=0; c<glyph.size().width(); c++) {
const auto pixel = glyph.pixels()[start + (c >> 3)] & (1U << (c & 0x7));
pixel_row[start_pos + i + c] = pixel ? Color::white() : Color::black();
}
const auto advance = glyph.advance();
i += advance.x();
}
render_line++;
}
scroll++;
credits_display.new_row(pixel_row);
}
AboutView::AboutView(
NavigationView& nav
)
{
add_child(&button_ok);
for (auto& text : text_line) {
text.set("");
text.set_parent_rect({
static_cast<Coord>(0),
static_cast<Coord>(200),
0, 0
});
add_child(&text);
}
) {
add_children({
&credits_display,
&button_ok
});
button_ok.on_select = [&nav](Button&){
nav.pop();

View File

@ -24,7 +24,6 @@
#define __UI_ABOUT_H__
#include "ui_widget.hpp"
#include "ui_menu.hpp"
#include "ui_navigation.hpp"
#include "ui_font_fixed_8x16.hpp"
@ -32,6 +31,21 @@
namespace ui {
class CreditsWidget : public Widget {
public:
CreditsWidget(Rect parent_rect);
void on_show() override;
void on_hide() override;
void paint(Painter&) override;
void new_row(const std::array<Color, 240>& pixel_row);
private:
void clear();
};
class AboutView : public View {
public:
AboutView(NavigationView& nav);
@ -43,33 +57,14 @@ public:
private:
void update();
uint8_t credits_index = 0;
uint32_t scroll = 0;
bool second = false;
bool line_feed = false;
uint8_t credits_index { 0 };
uint8_t render_line { 0 };
Coord start_pos { 0 };
uint8_t slow_down { 0 };
int32_t timer { 0 };
bool loop { false };
Style styles[4] = { style_black, style_dark_grey, style_light_grey, style_white };
static constexpr Style style_white {
.font = font::fixed_8x16,
.background = Color::black(),
.foreground = Color(255, 255, 255)
};
static constexpr Style style_light_grey {
.font = font::fixed_8x16,
.background = Color::black(),
.foreground = Color(170, 170, 170)
};
static constexpr Style style_dark_grey {
.font = font::fixed_8x16,
.background = Color::black(),
.foreground = Color(85, 85, 85)
};
static constexpr Style style_black {
.font = font::fixed_8x16,
.background = Color::black(),
.foreground = Color(0, 0, 0)
};
std::string text { };
enum flags {
SECTION = 0,
@ -81,30 +76,35 @@ private:
};
typedef struct credits_t {
std::string role;
std::string name;
flags flag;
size_t start_pos;
std::string text;
int32_t delay;
} credits_t;
const credits_t credits[16] = { {"Portapack|HAVOC", "Git hash " GIT_REVISION, SECTION},
{"Gurus", "J. Boone", TITLE},
{"M. Ossmann", "", MEMBER_LF},
{"HAVOC", "Furrtek", TITLE_LF},
{"POCSAG rx", "T. Sailer", TITLE},
{"E. Oenal", "", MEMBER_LF},
{"RDS waveform", "C. Jacquet", TITLE_LF},
{"Xy. infos", "cLx", TITLE_LF},
{"World map", "NASA", TITLE_LF},
{"Thanks", "", SECTION},
{"Rainer Matla", "Keld Norman", TITLE},
{"Giorgio C.", "DC1RDB", TITLE},
{"Sigmounte", "Waax", TITLE},
{"Windyoona", "Channels", TITLE},
{"F4GEV", "", TITLE_LF},
{"", "MMXVII", END}
};
std::array<Text, 10> text_line { };
const credits_t credits[19] = {
{ 60, "PortaPack|HAVOC", 0 },
{ 7 * 8, "Git hash " GIT_REVISION, 16 },
{ 9 * 8, "Gurus J. Boone", 0 },
{ 16 * 8, "M. Ossmann", 16 },
{ 9 * 8, "HAVOC Furrtek", 16 },
{ 5 * 8, "POCSAG rx T. Sailer", 0 },
{ 16 * 8, "E. Oenal", 16 },
{ 2 * 8, "RDS waveform C. Jacquet", 16 },
{ 5 * 8, "Xy. infos cLx", 16 },
{ 0, "OOK scan trick Samy Kamkar", 16 },
{ 5 * 8, "World map NASA", 24 },
{ 12 * 8, "Thanks", 16 },
{ 1 * 8, "Rainer Matla Keld Norman", 0 },
{ 1 * 8, " Giorgio C. DC1RDB", 0 },
{ 1 * 8, " Sigmounte Waax", 0 },
{ 1 * 8, " Windyoona Channels", 0 },
{ 1 * 8, " F4GEV", 24 },
{ 12 * 8, "MMXVII", -1 }
};
CreditsWidget credits_display {
{ 0, 16, 240, 240 }
};
Button button_ok {
{ 72, 272, 96, 24 },

View File

@ -25,47 +25,131 @@
#include "baseband_api.hpp"
#include "string_format.hpp"
#include "portapack_persistent_memory.hpp"
#include <cstring>
#include <stdio.h>
using namespace portapack;
namespace ui {
void EncodersView::focus() {
EncodersConfigView::EncodersConfigView(
NavigationView& nav, Rect parent_rect
) {
using name_t = std::string;
using value_t = int32_t;
using option_t = std::pair<name_t, value_t>;
std::vector<option_t> enc_options;
size_t i;
set_parent_rect(parent_rect);
hidden(true);
// Default encoder def
encoder_def = &encoder_defs[0];
add_children({
&labels,
&options_enctype,
&numberfield_clk,
&numberfield_bitduration,
&numberfield_wordduration,
&symfield_word,
&text_format,
&waveform
});
// Load encoder types in option field
for (i = 0; i < ENC_TYPES_COUNT; i++)
enc_options.emplace_back(std::make_pair(encoder_defs[i].name, i));
options_enctype.on_change = [this](size_t index, int32_t) {
on_type_change(index);
};
options_enctype.set_options(enc_options);
options_enctype.set_selected_index(0);
symfield_word.on_change = [this]() {
generate_frame();
};
// Selecting input clock changes symbol and word duration
numberfield_clk.on_change = [this](int32_t value) {
// value is in kHz, new_value is in us
int32_t new_value = 1000000 / ((value * 1000) / encoder_def->clk_per_symbol);
if (new_value != numberfield_bitduration.value()) {
numberfield_bitduration.set_value(new_value, false);
numberfield_wordduration.set_value(new_value * encoder_def->word_length, false);
}
};
// Selecting symbol duration changes input clock and word duration
numberfield_bitduration.on_change = [this](int32_t value) {
int32_t new_value = 1000000 / (((float)value * 1000) / encoder_def->clk_per_symbol);
if (new_value != numberfield_clk.value()) {
numberfield_clk.set_value(new_value, false);
numberfield_wordduration.set_value(value * encoder_def->word_length, false);
}
};
// Selecting word duration changes input clock and symbol duration
numberfield_wordduration.on_change = [this](int32_t value) {
int32_t new_value = value / encoder_def->word_length;
if (new_value != numberfield_bitduration.value()) {
numberfield_bitduration.set_value(new_value, false);
numberfield_clk.set_value(1000000 / (((float)new_value * 1000) / encoder_def->clk_per_symbol), false);
}
};
}
void EncodersConfigView::focus() {
options_enctype.focus();
}
EncodersView::~EncodersView() {
transmitter_model.disable();
baseband::shutdown();
}
void EncodersConfigView::on_type_change(size_t index) {
std::string word_format, format_string = "";
size_t word_length;
char symbol_type;
//size_t address_length;
//enc_type = index;
void EncodersView::generate_frame() {
size_t i;
encoder_def = &encoder_defs[index];
numberfield_clk.set_value(encoder_def->default_speed / 1000);
debug_text.clear();
i = 0;
for (auto c : encoder_def->word_format) {
if (c == 'S')
debug_text += encoder_def->sync;
else
debug_text += encoder_def->bit_format[symfield_word.get_sym(i++)];
// SymField setup
word_length = encoder_def->word_length;
symfield_word.set_length(word_length);
size_t n = 0, i = 0;
while (n < word_length) {
symbol_type = encoder_def->word_format.at(i++);
if (symbol_type == 'A') {
symfield_word.set_symbol_list(n++, encoder_def->address_symbols);
format_string += 'A';
} else if (symbol_type == 'D') {
symfield_word.set_symbol_list(n++, encoder_def->data_symbols);
format_string += 'D';
}
}
draw_waveform();
// Ugly :( Pad to erase
format_string.append(24 - format_string.size(), ' ');
text_format.set(format_string);
generate_frame();
}
void EncodersView::draw_waveform() {
uint32_t n, length;
void EncodersConfigView::on_show() {
// TODO: Remove ?
//options_enctype.set_selected_index(enc_type);
//on_type_change(enc_type);
}
length = debug_text.length();
void EncodersConfigView::draw_waveform() {
size_t length = frame_symbols.length();
size_t n;
for (n = 0; n < length; n++) {
if (debug_text[n] == '0')
if (frame_symbols[n] == '0')
waveform_buffer[n] = 0;
else
waveform_buffer[n] = 1;
@ -75,17 +159,82 @@ void EncodersView::draw_waveform() {
waveform.set_dirty();
}
void EncodersConfigView::generate_frame() {
size_t i = 0;
frame_symbols.clear();
for (auto c : encoder_def->word_format) {
if (c == 'S')
frame_symbols += encoder_def->sync;
else
frame_symbols += encoder_def->bit_format[symfield_word.get_sym(i++)];
}
draw_waveform();
}
uint8_t EncodersConfigView::repeat_min() {
return encoder_def->repeat_min;
}
uint32_t EncodersConfigView::samples_per_bit() {
return OOK_SAMPLERATE / ((numberfield_clk.value() * 1000) / encoder_def->clk_per_fragment);
}
uint32_t EncodersConfigView::pause_symbols() {
return encoder_def->pause_symbols;
}
void EncodersScanView::focus() {
field_debug.focus();
}
EncodersScanView::EncodersScanView(
NavigationView& nav, Rect parent_rect
) {
set_parent_rect(parent_rect);
hidden(true);
add_children({
&labels,
&field_debug,
&text_debug
});
// DEBUG
field_debug.on_change = [this](int32_t value) {
uint32_t l;
de_bruijn debruijn_seq;
debruijn_seq.init(value);
l = 1;
l <<= value;
l--;
if (l > 25)
l = 25;
text_debug.set(to_string_bin(debruijn_seq.compute(l), 25));
};
}
void EncodersView::focus() {
tab_view.focus();
}
EncodersView::~EncodersView() {
transmitter_model.disable();
baseband::shutdown();
}
void EncodersView::update_progress() {
char str[16];
std::string str_buffer;
// text_status.set(" ");
if (tx_mode == SINGLE) {
strcpy(str, to_string_dec_uint(repeat_index).c_str());
strcat(str, "/");
strcat(str, to_string_dec_uint(encoder_def->repeat_min).c_str());
text_status.set(str);
str_buffer = to_string_dec_uint(repeat_index) + "/" + to_string_dec_uint(repeat_min);
text_status.set(str_buffer);
progress.set_value(repeat_index);
/*} else if (tx_mode == SCAN) {
strcpy(str, to_string_dec_uint(repeat_index).c_str());
strcat(str, "/");
@ -107,7 +256,8 @@ void EncodersView::on_txdone(int n, const bool txdone) {
if (!txdone) {
// Repeating...
repeat_index = n + 1;
//repeat_index = n + 1;
/*if (tx_mode == SCAN) {
scan_progress++;
update_progress();
@ -147,14 +297,12 @@ void EncodersView::on_txdone(int n, const bool txdone) {
}
}
void EncodersView::on_tuning_frequency_changed(rf::Frequency f) {
transmitter_model.set_tuning_frequency(f);
}
void EncodersView::start_tx(const bool scan) {
char ook_bitstream[256];
uint32_t ook_bitstream_length;
(void)scan;
uint8_t* ook_bitstream = shared_memory.bb_data.data;
uint32_t ook_bitstream_length;
repeat_min = view_config.repeat_min();
/*if (scan) {
if (tx_mode != SCAN) {
@ -170,17 +318,17 @@ void EncodersView::start_tx(const bool scan) {
} else {*/
tx_mode = SINGLE;
repeat_index = 1;
progress.set_max(encoder_def->repeat_min);
progress.set_max(repeat_min);
update_progress();
//}
generate_frame();
view_config.generate_frame();
// Clear bitstream
memset(ook_bitstream, 0, 256);
size_t n = 0;
for (auto c : debug_text) {
for (auto c : view_config.frame_symbols) {
if (c != '0')
ook_bitstream[n >> 3] |= (1 << (7 - (n & 7)));
n++;
@ -188,158 +336,41 @@ void EncodersView::start_tx(const bool scan) {
ook_bitstream_length = n;
transmitter_model.set_sampling_rate(2280000U);
transmitter_model.set_sampling_rate(OOK_SAMPLERATE);
transmitter_model.set_rf_amp(true);
transmitter_model.set_baseband_bandwidth(1750000);
transmitter_model.enable();
memcpy(shared_memory.bb_data.data, ook_bitstream, 256);
baseband::set_ook_data(
ook_bitstream_length,
// 2280000/2 = 1140000Hz = 0,877192982us
// numberfield_clk.value() / encoder_def->clk_per_fragment
// 455000 / 12 = 37917Hz = 26,37339452us
228000 / ((numberfield_clk.value() * 1000) / encoder_def->clk_per_fragment),
encoder_def->repeat_min,
encoder_def->pause_symbols
view_config.samples_per_bit(),
repeat_min,
view_config.pause_symbols()
);
}
void EncodersView::on_type_change(size_t index) {
std::string word_format, format_string = "";
size_t word_length;
char symbol_type;
//size_t address_length;
enc_type = index;
encoder_def = &encoder_defs[enc_type];
numberfield_clk.set_value(encoder_def->default_speed / 1000);
// SymField setup
word_length = encoder_def->word_length;
symfield_word.set_length(word_length);
size_t n = 0, i = 0;
while (n < word_length) {
symbol_type = encoder_def->word_format.at(i++);
if (symbol_type == 'A') {
symfield_word.set_symbol_list(n++, encoder_def->address_symbols);
format_string += 'A';
} else if (symbol_type == 'D') {
symfield_word.set_symbol_list(n++, encoder_def->data_symbols);
format_string += 'D';
}
}
// Ugly :( Pad to erase
while (format_string.length() < 24)
format_string += ' ';
text_format.set(format_string);
generate_frame();
}
void EncodersView::on_show() {
// TODO: Remove ?
options_enctype.set_selected_index(enc_type);
on_type_change(enc_type);
}
EncodersView::EncodersView(NavigationView& nav) {
using name_t = std::string;
using value_t = int32_t;
using option_t = std::pair<name_t, value_t>;
using options_t = std::vector<option_t>;
options_t enc_options;
size_t i;
EncodersView::EncodersView(
NavigationView& nav
) : nav_ { nav }
{
baseband::run_image(portapack::spi_flash::image_tag_ook);
// Default encoder def
encoder_def = &encoder_defs[0];
add_children({
&labels,
&options_enctype,
&numberfield_clk,
&numberfield_bitduration,
&numberfield_wordduration,
//&field_debug,
&symfield_word,
&text_format,
//&text_format_a, // DEBUG
//&text_format_d, // DEBUG
&waveform,
&tab_view,
&view_config,
&view_scan,
&text_status,
&progress,
&tx_view
});
// Load encoder types
for (i = 0; i < ENC_TYPES_COUNT; i++)
enc_options.emplace_back(std::make_pair(encoder_defs[i].name, i));
options_enctype.on_change = [this](size_t index, int32_t value) {
(void)value;
this->on_type_change(index);
};
options_enctype.set_options(enc_options);
options_enctype.set_selected_index(0);
symfield_word.on_change = [this]() {
this->generate_frame();
};
// DEBUG
/*field_debug.on_change = [this](int32_t value) {
uint32_t l;
de_bruijn debruijn_seq;
debruijn_seq.init(value);
l = 1;
l <<= value;
l--;
if (l > 25)
l = 25;
text_format.set(to_string_bin(debruijn_seq.compute(l), 25));
};*/
// Selecting input clock changes symbol and word duration
numberfield_clk.on_change = [this](int32_t value) {
//int32_t new_value = 1000000 / (((float)value * 1000) / encoder_def->clk_per_symbol);
// value is in kHz, new_value is in us
int32_t new_value = 1000000 / ((value * 1000) / encoder_def->clk_per_symbol);
if (new_value != numberfield_bitduration.value()) {
numberfield_bitduration.set_value(new_value, false);
numberfield_wordduration.set_value(new_value * encoder_def->word_length, false);
}
};
// Selecting symbol duration changes input clock and word duration
numberfield_bitduration.on_change = [this](int32_t value) {
int32_t new_value = 1000000 / (((float)value * 1000) / encoder_def->clk_per_symbol);
if (new_value != numberfield_clk.value()) {
numberfield_clk.set_value(new_value, false);
numberfield_wordduration.set_value(value * encoder_def->word_length, false);
}
};
// Selecting word duration changes input clock and symbol duration
numberfield_wordduration.on_change = [this](int32_t value) {
int32_t new_value = value / encoder_def->word_length;
if (new_value != numberfield_bitduration.value()) {
numberfield_bitduration.set_value(new_value, false);
numberfield_clk.set_value(1000000 / (((float)new_value * 1000) / encoder_def->clk_per_symbol), false);
}
};
tx_view.on_edit_frequency = [this, &nav]() {
auto new_view = nav.push<FrequencyKeypadView>(receiver_model.tuning_frequency());
auto new_view = nav.push<FrequencyKeypadView>(transmitter_model.tuning_frequency());
new_view->on_changed = [this](rf::Frequency f) {
receiver_model.set_tuning_frequency(f);
transmitter_model.set_tuning_frequency(f);
};
};

View File

@ -21,37 +21,151 @@
*/
#include "ui.hpp"
#include "ui_widget.hpp"
#include "ui_navigation.hpp"
#include "ui_font_fixed_8x16.hpp"
#include "ui_receiver.hpp"
#include "ui_tabview.hpp"
#include "ui_transmitter.hpp"
#include "transmitter_model.hpp"
#include "encoders.hpp"
#include "de_bruijn.hpp"
#include "message.hpp"
#include "transmitter_model.hpp"
using namespace encoders;
namespace ui {
class EncodersConfigView : public View {
public:
EncodersConfigView(NavigationView& nav, Rect parent_rect);
EncodersConfigView(const EncodersConfigView&) = delete;
EncodersConfigView(EncodersConfigView&&) = delete;
EncodersConfigView& operator=(const EncodersConfigView&) = delete;
EncodersConfigView& operator=(EncodersConfigView&&) = delete;
void focus() override;
void on_show() override;
uint8_t repeat_min();
uint32_t samples_per_bit();
uint32_t pause_symbols();
void generate_frame();
std::string frame_symbols = "0";
private:
//bool abort_scan = false;
//uint8_t scan_count;
//double scan_progress;
//unsigned int scan_index;
int8_t waveform_buffer[512];
const encoder_def_t * encoder_def { };
//uint8_t enc_type = 0;
void draw_waveform();
void on_bitfield();
void on_type_change(size_t index);
Labels labels {
{ { 1 * 8, 0 }, "Type:", Color::light_grey() },
{ { 16 * 8, 0 }, "Clk:", Color::light_grey() },
{ { 24 * 8, 0 }, "kHz", Color::light_grey() },
{ { 16 * 8, 2 * 8 }, "Bit:", Color::light_grey() },
{ { 25 * 8, 2 * 8 }, "us", Color::light_grey() },
{ { 15 * 8, 4 * 8 }, "Word:", Color::light_grey() },
{ { 26 * 8, 4 * 8 }, "us", Color::light_grey() },
{ { 2 * 8, 6 * 8 }, "Word:", Color::light_grey() },
{ { 1 * 8, 13 * 8 }, "Waveform:", Color::light_grey() }
};
OptionsField options_enctype { // Options are loaded at runtime
{ 6 * 8, 0 },
7,
{
}
};
NumberField numberfield_clk {
{ 21 * 8, 0 },
3,
{ 1, 500 },
1,
' '
};
NumberField numberfield_bitduration {
{ 21 * 8, 2 * 8 },
4,
{ 50, 9999 },
1,
' '
};
NumberField numberfield_wordduration {
{ 21 * 8, 4 * 8 },
5,
{ 300, 99999 },
100,
' '
};
SymField symfield_word {
{ 2 * 8, 8 * 8 },
20,
SymField::SYMFIELD_DEF
};
Text text_format {
{ 2 * 8, 10 * 8, 24 * 8, 16 },
""
};
Waveform waveform {
{ 0, 16 * 8, 240, 32 },
waveform_buffer,
0,
0,
true,
Color::yellow()
};
};
class EncodersScanView : public View {
public:
EncodersScanView(NavigationView& nav, Rect parent_rect);
void focus() override;
private:
Labels labels {
{ { 1 * 8, 1 * 8 }, "Test", Color::light_grey() }
};
// DEBUG
NumberField field_debug {
{ 1 * 8, 6 * 8 },
2,
{ 3, 16 },
1,
' '
};
// DEBUG
Text text_debug {
{ 1 * 8, 8 * 8, 24 * 8, 16 },
""
};
};
class EncodersView : public View {
public:
EncodersView(NavigationView& nav);
~EncodersView();
EncodersView(const EncodersView&) = delete;
EncodersView(EncodersView&&) = delete;
EncodersView& operator=(const EncodersView&) = delete;
EncodersView& operator=(EncodersView&&) = delete;
void focus() override;
void on_show() override;
std::string title() const override { return "Encoders TX"; };
std::string title() const override { return "OOK transmit"; };
private:
void on_tuning_frequency_changed(rf::Frequency f);
NavigationView& nav_;
enum tx_modes {
IDLE = 0,
@ -59,36 +173,14 @@ private:
SCAN
};
uint8_t enc_type = 0;
const encoder_def_t * encoder_def { };
tx_modes tx_mode = IDLE;
//bool abort_scan = false;
//uint8_t scan_count;
//double scan_progress;
//unsigned int scan_index;
std::string debug_text = "0";
uint8_t repeat_index { 0 };
int8_t waveform_buffer[512];
uint8_t repeat_min { 0 };
void draw_waveform();
void on_bitfield();
void on_type_change(size_t index);
void generate_frame();
void update_progress();
void start_tx(const bool scan);
void on_txdone(int n, const bool txdone);
const Style style_val {
.font = font::fixed_8x16,
.background = Color::black(),
.foreground = Color::green(),
};
const Style style_cancel {
.font = font::fixed_8x16,
.background = Color::black(),
.foreground = Color::red(),
};
const Style style_address {
.font = font::fixed_8x16,
.background = Color::black(),
@ -100,85 +192,21 @@ private:
.foreground = Color::blue(),
};
Labels labels {
{ { 1 * 8, 4 * 8 }, "Type:", Color::light_grey() },
{ { 16 * 8, 4 * 8 }, "Clk:", Color::light_grey() },
{ { 24 * 8, 4 * 8 }, "kHz", Color::light_grey() },
{ { 16 * 8, 6 * 8 }, "Bit:", Color::light_grey() },
{ { 25 * 8, 6 * 8 }, "us", Color::light_grey() },
{ { 15 * 8, 8 * 8 }, "Word:", Color::light_grey() },
{ { 26 * 8, 8 * 8 }, "us", Color::light_grey() },
{ { 2 * 8, 10 * 8 }, "Word:", Color::light_grey() },
{ { 1 * 8, 17 * 8 }, "Waveform:", Color::light_grey() }
Rect view_rect = { 0, 5 * 8, 240, 168 };
EncodersConfigView view_config { nav_, view_rect };
EncodersScanView view_scan { nav_, view_rect };
TabView tab_view {
{ "Config", Color::cyan(), &view_config },
{ "Scan", Color::green(), &view_scan },
};
OptionsField options_enctype { // Options are loaded at runtime
{ 6 * 8, 32 },
7,
{
}
};
NumberField numberfield_clk {
{ 21 * 8, 4 * 8 },
3,
{ 1, 500 },
1,
' '
};
NumberField numberfield_bitduration {
{ 21 * 8, 6 * 8 },
4,
{ 50, 9999 },
1,
' '
};
NumberField numberfield_wordduration {
{ 21 * 8, 8 * 8 },
5,
{ 300, 99999 },
100,
' '
};
// DEBUG
/*NumberField field_debug {
{ 21 * 8, 10 * 8 },
2,
{ 3, 16 },
1,
' '
};*/
SymField symfield_word {
{ 2 * 8, 12 * 8 },
20,
SymField::SYMFIELD_DEF
};
Text text_format {
{ 2 * 8, 14 * 8, 24 * 8, 16 },
""
};
//Text text_format_a; // DEBUG
//Text text_format_d; // DEBUG
Waveform waveform {
{ 0, 160, 240, 32 },
waveform_buffer,
0,
0,
true,
Color::yellow()
};
Text text_status {
{ 2 * 8, 13 * 16, 128, 16 },
"Ready"
};
ProgressBar progress {
{ 2 * 8, 13 * 16 + 20, 208, 16 }
};

View File

@ -219,6 +219,8 @@ void GeoMapView::focus() {
void GeoMapView::update_position(float lat, float lon) {
lat_ = lat;
lon_ = lon;
geopos.set_lat(lat_);
geopos.set_lon(lon_);
geomap.move(lon_, lat_);
geomap.set_dirty();
}

View File

@ -98,7 +98,7 @@ void OOKProcessor::on_message(const Message* const p) {
const auto message = *reinterpret_cast<const OOKConfigureMessage*>(p);
if (message.id == Message::ID::OOKConfigure) {
samples_per_bit = message.samples_per_bit;
samples_per_bit = message.samples_per_bit / 10;
repeat = message.repeat - 1;
length = message.stream_length - 1;
pause = message.pause_symbols + 1;