Encoders, Nuoptix DTMF and RDS transmitters now use TransmitterView

Bigger buttons in AlphanumView, 3 pages
Scary yellow stripes around TransmitterView
This commit is contained in:
furrtek 2017-02-07 22:12:20 +00:00
parent fc8279aa30
commit c72b490d49
16 changed files with 180 additions and 184 deletions

View File

@ -117,6 +117,20 @@ static constexpr Bitmap bitmap_icon_unistroke {
{ 16, 16 }, bitmap_icon_unistroke_data
};
static constexpr uint8_t bitmap_stripes_data[] = {
0xFF, 0x03, 0xC0,
0xFF, 0x01, 0xE0,
0xFF, 0x00, 0xF0,
0x7F, 0x00, 0xF8,
0x3F, 0x00, 0xFC,
0x1F, 0x00, 0xFE,
0x0F, 0x00, 0xFF,
0x07, 0x80, 0xFF,
};
static constexpr Bitmap bitmap_stripes {
{ 24, 8 }, bitmap_stripes_data
};
static constexpr uint8_t bitmap_icon_adsb_data[] = {
0x80, 0x01,
0xC0, 0x03,

View File

@ -23,7 +23,8 @@
// Color bitmaps generated with:
// Gimp image > indexed colors (16), then "xxd -i *.bmp"
//BUG: POCSAG TX: Chops off the few last chars on long messages ?
//BUG: RDS Radiotext is not recognized in Redsea (and car radio)
//BUG: POCSAG TX: Chops off the last few chars on long messages ?
//BUG: (fixed ?) POCSAG: Bad console scroll init
//BUG: (fixed ?) POCSAG misses alphanum messages, cuts them off sometimes
//BUG: Check AFSK transmit end, skips last bits ?
@ -32,7 +33,7 @@
//TEST: Imperial in whipcalc
//TEST: Numbers
//TODO: Use TransmitterView everywhere possible
//TODO: Use TransmitterView in ADSB, Morse, TEDI/LCR, Numbers, whistle, jammer...
//TODO: FreqMan: Add and rename categories
//TODO: FreqMan: Sort by category in edit screen
//TODO: FreqMan: Cap entry count per category (only done for total entries right now)

View File

@ -57,9 +57,6 @@ public:
~POCSAGAppView();
void set_parent_rect(const Rect new_parent_rect) override;
void paint(Painter&) override { };
void focus() override;
std::string title() const override { return "POCSAG RX"; };

View File

@ -32,8 +32,7 @@ using namespace hackrf::one;
namespace ui {
void AlphanumView::paint(Painter& painter) {
(void)painter;
void AlphanumView::paint(Painter&) {
move_cursor();
}
@ -43,21 +42,8 @@ AlphanumView::AlphanumView(
size_t max_length
) : _max_length(max_length)
{
_lowercase = false;
size_t n;
static constexpr Style style_alpha {
.font = font::fixed_8x16,
.background = Color::black(),
.foreground = Color(255, 63, 63)
};
static constexpr Style style_num {
.font = font::fixed_8x16,
.background = Color::black(),
.foreground = Color(191, 191, 31)
};
txtidx = strlen(txt);
memcpy(txtinput, txt, _max_length + 1);
n = txtidx;
@ -68,8 +54,9 @@ AlphanumView::AlphanumView(
add_children({
&text_input,
&button_lowercase,
&raw_char,
&button_mode,
&text_raw,
&field_raw,
&button_ok
});
@ -82,33 +69,21 @@ AlphanumView::AlphanumView(
button.on_select = button_fn;
button.set_parent_rect({
static_cast<Coord>((n % 5) * (240 / 5)),
static_cast<Coord>((n / 5) * 28 + 24),
240 / 5, 28
static_cast<Coord>((n / 5) * 38 + 24),
240 / 5, 38
});
if ((n < 10) || (n == 39))
button.set_style(&style_num);
else
button.set_style(&style_alpha);
add_child(&button);
n++;
}
set_keys(keys_upper);
set_mode(mode);
button_lowercase.on_select = [this, &nav](Button&) {
if (_lowercase == true) {
_lowercase = false;
button_lowercase.set_text("UC");
set_keys(keys_upper);
} else {
_lowercase = true;
button_lowercase.set_text("LC");
set_keys(keys_lower);
}
button_mode.on_select = [this, &nav](Button&) {
set_mode(mode + 1);
};
raw_char.set_value('0');
raw_char.on_select = [this, &nav](NumberField&) {
char_add(raw_char.value());
field_raw.set_value('0');
field_raw.on_select = [this, &nav](NumberField&) {
char_add(field_raw.value());
update_text();
};
@ -124,7 +99,7 @@ AlphanumView::AlphanumView(
void AlphanumView::move_cursor() {
Point cursor_pos;
cursor_pos = {text_input.screen_rect().location().x() + (txtidx * 8),
cursor_pos = {text_input.screen_rect().location().x() + (Coord)(txtidx * 8),
text_input.screen_rect().location().y() + 16};
portapack::display.fill_rectangle(
@ -137,9 +112,16 @@ void AlphanumView::move_cursor() {
);
}
void AlphanumView::set_keys(const char * const key_list) {
void AlphanumView::set_mode(const uint32_t new_mode) {
size_t n = 0;
if (new_mode < 3)
mode = new_mode;
else
mode = 0;
const char * key_list = pages[mode].second;
for (auto& button : buttons) {
const std::string label {
key_list[n]
@ -147,6 +129,11 @@ void AlphanumView::set_keys(const char * const key_list) {
button.set_text(label);
n++;
}
if (mode < 2)
button_mode.set_text(pages[mode + 1].first);
else
button_mode.set_text(pages[0].first);
}
void AlphanumView::focus() {

View File

@ -52,17 +52,24 @@ public:
std::string title() const override { return "Text entry"; };
private:
const char * const keys_upper = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ. !<";
const char * const keys_lower = "0123456789abcdefghijklmnopqrstuvwxyz:=?<";
const char * const keys_upper = "ABCDEFGHIJKLMNOPQRSTUVWXYZ' .<";
const char * const keys_lower = "abcdefghijklmnopqrstuvwxyz' .<";
const char * const keys_digit = "0123456789!\"#'()*+-/:;=>?@[\\]<";
const std::pair<std::string, const char *> pages[3] = {
{ "Upper", keys_upper },
{ "Lower", keys_lower },
{ "Digit", keys_digit }
};
size_t _max_length { };
uint8_t txtidx { 0 };
bool _lowercase = false;
uint32_t txtidx { 0 };
uint32_t mode = 0; // Upper
char txtinput[29] = { 0 }; // 28 chars max
void char_add(const char c);
void char_delete();
void set_keys(const char * const key_list);
void set_mode(const uint32_t new_mode);
void move_cursor();
void on_button(Button& button);
void update_text();
@ -71,15 +78,19 @@ private:
{ 8, 0, 232, 16 }
};
std::array<Button, 40> buttons { };
std::array<Button, 30> buttons { };
Button button_lowercase {
{ 21 * 8, 270, 32, 24 },
"UC"
Button button_mode {
{ 21 * 8, 33 * 8, 8 * 8, 32 },
""
};
NumberField raw_char {
{ 16, 270 },
Text text_raw {
{ 1 * 8, 33 * 8, 4 * 8, 16 },
"Raw:"
};
NumberField field_raw {
{ 5 * 8, 33 * 8 },
3,
{ 1, 255 },
1,
@ -87,7 +98,7 @@ private:
};
Button button_ok {
{ 88, 270, 64, 24 },
{ 10 * 8, 33 * 8, 9 * 8, 32 },
"OK"
};
};

View File

@ -143,6 +143,7 @@ void EncodersView::on_txdone(int n, const bool txdone) {
tx_mode = IDLE;
text_status.set("Done");
progress.set_value(0);
tx_view.set_transmitting(false);
//}
}
}
@ -154,6 +155,7 @@ void EncodersView::on_tuning_frequency_changed(rf::Frequency f) {
void EncodersView::start_tx(const bool scan) {
char ook_bitstream[256];
uint32_t ook_bitstream_length;
(void)scan;
/*if (scan) {
if (tx_mode != SCAN) {
@ -263,7 +265,6 @@ EncodersView::EncodersView(NavigationView& nav) {
encoder_def = &encoder_defs[0];
add_children({
&field_frequency,
&text_enctype,
&options_enctype,
&text_clk,
@ -284,23 +285,9 @@ EncodersView::EncodersView(NavigationView& nav) {
&waveform,
&text_status,
&progress,
&button_transmit
&tx_view
});
field_frequency.set_value(transmitter_model.tuning_frequency());
field_frequency.set_step(50000);
field_frequency.on_change = [this](rf::Frequency f) {
this->on_tuning_frequency_changed(f);
};
field_frequency.on_edit = [this, &nav]() {
// TODO: Provide separate modal method/scheme?
auto new_view = nav.push<FrequencyKeypadView>(transmitter_model.tuning_frequency());
new_view->on_changed = [this](rf::Frequency f) {
this->on_tuning_frequency_changed(f);
this->field_frequency.set_value(f);
};
};
// Load encoder types
for (i = 0; i < ENC_TYPES_COUNT; i++)
enc_options.emplace_back(std::make_pair(encoder_defs[i].name, i));
@ -317,8 +304,6 @@ EncodersView::EncodersView(NavigationView& nav) {
this->generate_frame();
};
button_transmit.set_style(&style_val);
// 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);
@ -348,8 +333,20 @@ EncodersView::EncodersView(NavigationView& nav) {
}
};
button_transmit.on_select = [this, &nav](Button&) {
if (tx_mode == IDLE) start_tx(false);
tx_view.on_edit_frequency = [this, &nav]() {
auto new_view = nav.push<FrequencyKeypadView>(receiver_model.tuning_frequency());
new_view->on_changed = [this](rf::Frequency f) {
receiver_model.set_tuning_frequency(f);
};
};
tx_view.on_start = [this]() {
tx_view.set_transmitting(true);
start_tx(false);
};
tx_view.on_stop = [this]() {
tx_view.set_transmitting(false);
};
}

View File

@ -25,6 +25,7 @@
#include "ui_navigation.hpp"
#include "ui_font_fixed_8x16.hpp"
#include "ui_receiver.hpp"
#include "ui_transmitter.hpp"
#include "encoders.hpp"
#include "message.hpp"
#include "transmitter_model.hpp"
@ -58,14 +59,14 @@ private:
};
uint8_t enc_type = 0;
const encoder_def_t * encoder_def;
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;
uint8_t repeat_index { 0 };
int8_t waveform_buffer[512];
void draw_waveform();
@ -98,10 +99,6 @@ private:
.foreground = Color::blue(),
};
FrequencyField field_frequency {
{ 1 * 8, 4 },
};
Text text_enctype {
{ 1 * 8, 32, 5 * 8, 16 },
"Type:"
@ -193,16 +190,17 @@ private:
};
Text text_status {
{ 2 * 8, 224, 128, 16 },
{ 2 * 8, 13 * 16, 128, 16 },
"Ready"
};
ProgressBar progress {
{ 16, 224 + 20, 208, 16 }
{ 2 * 8, 13 * 16 + 20, 208, 16 }
};
Button button_transmit {
{ 16, 270, 80, 32 },
"TX"
TransmitterView tx_view {
16 * 16,
50000,
9
};
MessageHandlerRegistration message_handler_tx_done {

View File

@ -80,15 +80,15 @@ private:
tx_modes tx_mode = IDLE;
bool abort_scan = false;
uint8_t scan_count, scan_index;
double scan_progress;
uint8_t scan_count { 0 }, scan_index { 0 };
double scan_progress { 0 };
char litteral[5][8] = { { 0 }, { 0 }, { 0 }, { 0 }, { 0 } };
char rgsb[5] = { 0 };
char lcr_message[512];
char lcr_message_data[512];
char checksum = 0;
rf::Frequency f;
uint8_t repeat_index;
rf::Frequency f { 0 };
uint8_t repeat_index { 0 };
void generate_message();
void update_progress();
@ -107,9 +107,9 @@ private:
.foreground = Color::red(),
};
std::array<Button, 5> buttons;
std::array<Checkbox, 5> checkboxes;
std::array<Rectangle, 5> rectangles;
std::array<Button, 5> buttons { };
std::array<Checkbox, 5> checkboxes { };
std::array<Rectangle, 5> rectangles { };
Text text_recap {
{ 8, 6, 18 * 8, 16 },

View File

@ -60,7 +60,7 @@ void NuoptixView::transmit(bool setup) {
timecode = lfsr_iterate(timecode) % 1999; // Could be 9999 but that would be one long audio track !
if (setup) {
pbar.set_max(6 * 2);
progressbar.set_max(6 * 2);
if (tx_mode == IMPROVISE) {
// Seed from RTC
@ -86,7 +86,7 @@ void NuoptixView::transmit(bool setup) {
number_timecode.set_value(timecode);
}
pbar.set_value(0);
progressbar.set_value(0);
dtmf_message[2] = (timecode / 100) % 10;
dtmf_message[3] = (timecode / 10) % 10;
@ -145,12 +145,11 @@ NuoptixView::NuoptixView(
baseband::run_image(portapack::spi_flash::image_tag_tones);
add_children({
&tx_view,
&number_timecode,
&text_timecode,
&text_mod,
&pbar,
&button_exit
&progressbar,
&tx_view
});
number_timecode.set_value(1);
@ -183,10 +182,6 @@ NuoptixView::NuoptixView(
transmit(true);
}
};*/
button_exit.on_select = [&nav](Button&){
nav.pop();
};
}
}

View File

@ -62,19 +62,13 @@ private:
uint32_t timecode { 0 };
TransmitterView tx_view {
11 * 16,
10000,
15
};
Text text_timecode {
{ 10 * 8, 32, 9 * 8, 16 },
{ 10 * 8, 2 * 16, 9 * 8, 16 },
"Timecode:"
};
NumberField number_timecode {
{ 13 * 8, 48 },
{ 13 * 8, 3 * 16 },
4,
{ 1, 9999 },
1,
@ -82,12 +76,12 @@ private:
};
Text text_mod {
{ 10 * 8, 80, 6 * 8, 16 },
{ 10 * 8, 5 * 16, 6 * 8, 16 },
"Mod: "
};
ProgressBar pbar {
{ 16, 236, 208, 16 }
ProgressBar progressbar {
{ 16, 14 * 16, 208, 16 }
};
/*Button button_impro {
@ -95,9 +89,10 @@ private:
"IMPROVISE"
};*/
Button button_exit {
{ 88, 270, 64, 32 },
"Exit"
TransmitterView tx_view {
16 * 16,
10000,
15
};
MessageHandlerRegistration message_handler_tx_done {
@ -107,7 +102,7 @@ private:
if (message.done)
transmit(false);
else
pbar.set_value(message.progress);
progressbar.set_value(message.progress);
}
};
};

View File

@ -57,8 +57,7 @@ void RDSView::start_tx() {
baseband::set_rds_data(message_length);
}
void RDSView::paint(Painter& painter) {
(void)painter;
void RDSView::paint(Painter&) {
char RadioTextA[17];
text_psn.set(PSN);
@ -78,7 +77,6 @@ RDSView::RDSView(NavigationView& nav) {
strcpy(RadioText, "Radiotext test ABCD1234");
add_children({
&field_frequency,
&text_pty,
&options_pty,
&text_countrycode,
@ -99,23 +97,43 @@ RDSView::RDSView(NavigationView& nav) {
&text_radiotext,
&text_radiotexta,
&text_radiotextb,
&button_tx,
&button_exit
&tx_view,
});
field_frequency.set_value(transmitter_model.tuning_frequency());
field_frequency.set_step(50000); // 50kHz steps
field_frequency.on_change = [this](rf::Frequency f) {
this->on_tuning_frequency_changed(f);
};
field_frequency.on_edit = [this, &nav]() {
auto new_view = nav.push<FrequencyKeypadView>(field_frequency.value());
tx_view.on_edit_frequency = [this, &nav]() {
auto new_view = nav.push<FrequencyKeypadView>(receiver_model.tuning_frequency());
new_view->on_changed = [this](rf::Frequency f) {
this->field_frequency.set_value(f);
receiver_model.set_tuning_frequency(f);
this->on_tuning_frequency_changed(f);
};
};
tx_view.on_start = [this]() {
tx_view.set_transmitting(true);
rds_flags.PI_code = sym_pi_code.value_hex_u64();
rds_flags.PTY = options_pty.selected_index_value();
rds_flags.DI = check_mono_stereo.value() ? 1 : 0;
rds_flags.TP = check_TP.value();
rds_flags.TA = check_TA.value();
rds_flags.MS = check_MS.value();
if (options_tx.selected_index() == 0)
message_length = gen_PSN(PSN, &rds_flags);
else if (options_tx.selected_index() == 1)
message_length = gen_RadioText(RadioText, 0, &rds_flags);
else
message_length = gen_ClockTime(&rds_flags, 2016, 12, 1, 9, 23, 2);
txing = true;
start_tx();
};
tx_view.on_stop = [this]() {
tx_view.set_transmitting(false);
transmitter_model.disable();
txing = false;
};
check_TA.set_value(true);
check_TP.set_value(true);
@ -145,40 +163,10 @@ RDSView::RDSView(NavigationView& nav) {
button_editpsn.on_select = [this, &nav](Button&) {
textentry(nav, PSN, 8);
};
button_tx.on_select = [this](Button&) {
if (txing) {
transmitter_model.disable();
button_tx.set_text("START");
txing = false;
} else {
rds_flags.PI_code = sym_pi_code.value_hex_u64();
rds_flags.PTY = options_pty.selected_index_value();
rds_flags.DI = check_mono_stereo.value() ? 1 : 0;
rds_flags.TP = check_TP.value();
rds_flags.TA = check_TA.value();
rds_flags.MS = check_MS.value();
if (options_tx.selected_index() == 0)
message_length = gen_PSN(PSN, &rds_flags);
else if (options_tx.selected_index() == 1)
message_length = gen_RadioText(RadioText, 0, &rds_flags);
else
message_length = gen_ClockTime(&rds_flags, 2016, 12, 1, 9, 23, 2);
button_tx.set_text("STOP");
txing = true;
start_tx();
}
};
button_editradiotext.on_select = [this, &nav](Button&){
textentry(nav, RadioText, 24);
};
button_exit.on_select = [&nav](Button&){
nav.pop();
};
}
} /* namespace ui */

View File

@ -25,6 +25,7 @@
#include "ui_navigation.hpp"
#include "ui_font_fixed_8x16.hpp"
#include "ui_receiver.hpp"
#include "ui_transmitter.hpp"
#include "ui_textentry.hpp"
#include "message.hpp"
#include "rds.hpp"
@ -44,20 +45,16 @@ public:
std::string title() const override { return "RDS transmit"; };
private:
char PSN[9];
char RadioText[25];
char PSN[9] { 0 };
char RadioText[25] { 0 };
bool txing = false;
RDS_flags rds_flags;
RDS_flags rds_flags { };
uint16_t message_length;
uint16_t message_length { 0 };
void start_tx();
void on_tuning_frequency_changed(rf::Frequency f);
FrequencyField field_frequency {
{ 1 * 8, 4 },
};
Text text_pty {
{ 1 * 8, 16 + 8, 4 * 8, 16 },
"PTY:"
@ -272,13 +269,10 @@ private:
}
};
Button button_tx {
{ 3 * 8, 16 * 16, 80, 32 },
"START"
};
Button button_exit {
{ 19 * 8, 16 * 16, 64, 32 },
"Exit"
TransmitterView tx_view {
16 * 16,
50000,
9
};
};

View File

@ -51,6 +51,24 @@ TXGainField::TXGainField(
/* TransmitterView *******************************************************/
void TransmitterView::paint(Painter& painter) {
size_t c;
Point pos = { 0, screen_pos().y() };
for (c = 0; c < 20; c++) {
painter.draw_bitmap(
pos,
bitmap_stripes,
ui::Color(191, 191, 0),
ui::Color::black()
);
if (c != 9)
pos += { 24, 0 };
else
pos = { 0, screen_pos().y() + 32 + 8 };
}
}
void TransmitterView::on_tuning_frequency_changed(rf::Frequency f) {
receiver_model.set_tuning_frequency(f);
}
@ -82,7 +100,7 @@ void TransmitterView::focus() {
TransmitterView::TransmitterView(
const Coord y, const uint32_t frequency_step, const uint32_t bandwidth
) {
set_parent_rect({ 0 * 8, y, 30 * 8, 2 * 16 });
set_parent_rect({ 0 * 8, y, 30 * 8, 6 * 8 });
add_children({
&field_frequency,

View File

@ -56,6 +56,7 @@ public:
~TransmitterView();
void on_show() override;
void paint(Painter& painter) override;
void focus() override;
void set_transmitting(const bool transmitting);
@ -75,27 +76,27 @@ private:
bool transmitting_ { false };
FrequencyField field_frequency {
{ 0 * 8, 0 * 16 }
{ 0 * 8, 1 * 8 }
};
TXGainField field_gain {
{ 10 * 8, 0 * 16 }
{ 10 * 8, 1 * 8 }
};
NumberField field_bw {
{ 13 * 8, 0 * 16 },
{ 13 * 8, 1 * 8 },
3,
{ 1, 150 },
1,
' '
};
Text text_kHz {
{ 16 * 8, 0 * 16, 3 * 8, 1 * 16 },
{ 16 * 8, 1 * 8, 3 * 8, 1 * 16 },
"kHz"
};
Button button_start {
{ 20 * 8, 0 * 16, 9 * 8, 32 },
{ 20 * 8, 1 * 8, 9 * 8, 32 },
"START"
};

Binary file not shown.

After

Width:  |  Height:  |  Size: 112 B

Binary file not shown.