mirror of
https://github.com/eried/portapack-mayhem.git
synced 2024-10-01 01:26:06 -04:00
Added waveform widget and a frequency field in encoders tx
This commit is contained in:
parent
be3d477352
commit
a0c248d567
@ -172,7 +172,7 @@ static constexpr uint8_t bitmap_icon_codetx_data[] = {
|
|||||||
0xF0, 0x07,
|
0xF0, 0x07,
|
||||||
0x0C, 0x18,
|
0x0C, 0x18,
|
||||||
0x03, 0x60,
|
0x03, 0x60,
|
||||||
0xE0, 0x83,
|
0xE0, 0x03,
|
||||||
0x18, 0x0C,
|
0x18, 0x0C,
|
||||||
0x04, 0x10,
|
0x04, 0x10,
|
||||||
0xC0, 0x01,
|
0xC0, 0x01,
|
||||||
|
@ -109,7 +109,7 @@ namespace encoders {
|
|||||||
|
|
||||||
// HK526E
|
// HK526E
|
||||||
{
|
{
|
||||||
"526 ",
|
"526E ",
|
||||||
"01", "01",
|
"01", "01",
|
||||||
24, 8,
|
24, 8,
|
||||||
{ "110", "100" },
|
{ "110", "100" },
|
||||||
|
@ -28,10 +28,10 @@
|
|||||||
//TEST: Jammer
|
//TEST: Jammer
|
||||||
//TEST: Frequency manager + save/load
|
//TEST: Frequency manager + save/load
|
||||||
|
|
||||||
|
//TODO: "TX box" view or composite widget with frequency and bw settings, simple and advanced setup TX buttons...
|
||||||
//TODO: Morse coder for foxhunts
|
//TODO: Morse coder for foxhunts
|
||||||
//TODO: Finish EPAR tx
|
//TODO: Finish EPAR tx
|
||||||
//TODO: IQ replay
|
//TODO: IQ replay
|
||||||
//TODO: Waveform widget ?
|
|
||||||
//TODO: Wav visualizer
|
//TODO: Wav visualizer
|
||||||
|
|
||||||
//BUG: POCSAG RX sometimes misses the first codeword after SYNC
|
//BUG: POCSAG RX sometimes misses the first codeword after SYNC
|
||||||
|
@ -61,34 +61,21 @@ void EncodersView::generate_frame() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void EncodersView::draw_waveform() {
|
void EncodersView::draw_waveform() {
|
||||||
float x = 0, x_inc;
|
uint32_t n, p = 0, length;
|
||||||
Coord y, prev_y = 1;
|
|
||||||
uint8_t prelude_length = 0; //encoder_def->sync.length();
|
|
||||||
|
|
||||||
// Clear
|
length = debug_text.length();
|
||||||
painter_->fill_rectangle( { 0, 168, 240, 24 }, Color::black() );
|
|
||||||
|
|
||||||
x_inc = 230.0 / (debug_text.length() - prelude_length);
|
for (n = 0; n < length; n++) {
|
||||||
|
if (debug_text[n] == '0')
|
||||||
for (auto c : debug_text) { //.substr(prelude_length)
|
waveform_buffer[p] = -128;
|
||||||
if (c == '0')
|
|
||||||
y = 23;
|
|
||||||
else
|
else
|
||||||
y = 0;
|
waveform_buffer[p] = 127;
|
||||||
|
waveform_buffer[p + 1] = waveform_buffer[p];
|
||||||
// Edge
|
p += 2;
|
||||||
if (prev_y != y) painter_->draw_rectangle( { (Coord)x, 168, 1, 24 }, Color::yellow() );
|
|
||||||
// Level
|
|
||||||
painter_->draw_rectangle( { (Coord)x, 168 + y, (int)ceil(x_inc), 1 }, Color::yellow() );
|
|
||||||
|
|
||||||
prev_y = y;
|
|
||||||
x += x_inc;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void EncodersView::paint(Painter& painter) {
|
waveform.set_length(length * 2);
|
||||||
painter_ = &painter;
|
waveform.set_dirty();
|
||||||
draw_waveform();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void EncodersView::update_progress() {
|
void EncodersView::update_progress() {
|
||||||
@ -162,6 +149,10 @@ 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) {
|
void EncodersView::start_tx(const bool scan) {
|
||||||
char ook_bitstream[256];
|
char ook_bitstream[256];
|
||||||
uint32_t ook_bitstream_length;
|
uint32_t ook_bitstream_length;
|
||||||
@ -198,7 +189,6 @@ void EncodersView::start_tx(const bool scan) {
|
|||||||
|
|
||||||
ook_bitstream_length = n;
|
ook_bitstream_length = n;
|
||||||
|
|
||||||
transmitter_model.set_tuning_frequency(433920000); // TODO: Make modifiable !
|
|
||||||
transmitter_model.set_baseband_configuration({
|
transmitter_model.set_baseband_configuration({
|
||||||
.mode = 0,
|
.mode = 0,
|
||||||
.sampling_rate = 2280000U,
|
.sampling_rate = 2280000U,
|
||||||
@ -318,6 +308,7 @@ EncodersView::EncodersView(NavigationView& nav) {
|
|||||||
encoder_def = &encoder_defs[0];
|
encoder_def = &encoder_defs[0];
|
||||||
|
|
||||||
add_children({ {
|
add_children({ {
|
||||||
|
&field_frequency,
|
||||||
&text_enctype,
|
&text_enctype,
|
||||||
&options_enctype,
|
&options_enctype,
|
||||||
&text_clk,
|
&text_clk,
|
||||||
@ -335,11 +326,26 @@ EncodersView::EncodersView(NavigationView& nav) {
|
|||||||
//&text_format_a, // DEBUG
|
//&text_format_a, // DEBUG
|
||||||
//&text_format_d, // DEBUG
|
//&text_format_d, // DEBUG
|
||||||
&text_waveform,
|
&text_waveform,
|
||||||
|
&waveform,
|
||||||
&text_status,
|
&text_status,
|
||||||
&progress,
|
&progress,
|
||||||
&button_transmit
|
&button_transmit
|
||||||
} });
|
} });
|
||||||
|
|
||||||
|
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
|
// Load encoder types
|
||||||
for (i = 0; i < ENC_TYPES_COUNT; i++)
|
for (i = 0; i < ENC_TYPES_COUNT; i++)
|
||||||
enc_options.emplace_back(std::make_pair(encoder_defs[i].name, i));
|
enc_options.emplace_back(std::make_pair(encoder_defs[i].name, i));
|
||||||
|
@ -24,6 +24,7 @@
|
|||||||
#include "ui_widget.hpp"
|
#include "ui_widget.hpp"
|
||||||
#include "ui_navigation.hpp"
|
#include "ui_navigation.hpp"
|
||||||
#include "ui_font_fixed_8x16.hpp"
|
#include "ui_font_fixed_8x16.hpp"
|
||||||
|
#include "ui_receiver.hpp"
|
||||||
#include "encoders.hpp"
|
#include "encoders.hpp"
|
||||||
#include "message.hpp"
|
#include "message.hpp"
|
||||||
#include "transmitter_model.hpp"
|
#include "transmitter_model.hpp"
|
||||||
@ -39,18 +40,18 @@ public:
|
|||||||
|
|
||||||
void focus() override;
|
void focus() override;
|
||||||
void on_show() override;
|
void on_show() override;
|
||||||
void paint(Painter& painter) override;
|
|
||||||
|
|
||||||
std::string title() const override { return "Encoders TX"; };
|
std::string title() const override { return "Encoders TX"; };
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
void on_tuning_frequency_changed(rf::Frequency f);
|
||||||
|
|
||||||
enum tx_modes {
|
enum tx_modes {
|
||||||
IDLE = 0,
|
IDLE = 0,
|
||||||
SINGLE,
|
SINGLE,
|
||||||
SCAN
|
SCAN
|
||||||
};
|
};
|
||||||
|
|
||||||
Painter * painter_;
|
|
||||||
uint8_t enc_type = 0;
|
uint8_t enc_type = 0;
|
||||||
const encoder_def_t * encoder_def;
|
const encoder_def_t * encoder_def;
|
||||||
tx_modes tx_mode = IDLE;
|
tx_modes tx_mode = IDLE;
|
||||||
@ -59,8 +60,8 @@ private:
|
|||||||
//double scan_progress;
|
//double scan_progress;
|
||||||
//unsigned int scan_index;
|
//unsigned int scan_index;
|
||||||
std::string debug_text = "0";
|
std::string debug_text = "0";
|
||||||
//rf::Frequency f;
|
|
||||||
uint8_t repeat_index;
|
uint8_t repeat_index;
|
||||||
|
int8_t waveform_buffer[512];
|
||||||
|
|
||||||
void draw_waveform();
|
void draw_waveform();
|
||||||
void on_bitfield();
|
void on_bitfield();
|
||||||
@ -92,75 +93,79 @@ private:
|
|||||||
.foreground = Color::blue(),
|
.foreground = Color::blue(),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
FrequencyField field_frequency {
|
||||||
|
{ 1 * 8, 4 },
|
||||||
|
};
|
||||||
|
|
||||||
Text text_enctype {
|
Text text_enctype {
|
||||||
{ 1 * 8, 24, 5 * 8, 16 },
|
{ 1 * 8, 32, 5 * 8, 16 },
|
||||||
"Type:"
|
"Type:"
|
||||||
};
|
};
|
||||||
OptionsField options_enctype { // Options are loaded at runtime
|
OptionsField options_enctype { // Options are loaded at runtime
|
||||||
{ 6 * 8, 24 },
|
{ 6 * 8, 32 },
|
||||||
7,
|
7,
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
Text text_clk {
|
Text text_clk {
|
||||||
{ 16 * 8, 3 * 8, 4 * 8, 16 },
|
{ 16 * 8, 4 * 8, 4 * 8, 16 },
|
||||||
"Clk:"
|
"Clk:"
|
||||||
};
|
};
|
||||||
NumberField numberfield_clk {
|
NumberField numberfield_clk {
|
||||||
{ 21 * 8, 3 * 8 },
|
{ 21 * 8, 4 * 8 },
|
||||||
3,
|
3,
|
||||||
{ 1, 500 },
|
{ 1, 500 },
|
||||||
1,
|
1,
|
||||||
' '
|
' '
|
||||||
};
|
};
|
||||||
Text text_kHz {
|
Text text_kHz {
|
||||||
{ 24 * 8, 3 * 8, 3 * 8, 16 },
|
{ 24 * 8, 4 * 8, 3 * 8, 16 },
|
||||||
"kHz"
|
"kHz"
|
||||||
};
|
};
|
||||||
|
|
||||||
Text text_bitduration {
|
Text text_bitduration {
|
||||||
{ 16 * 8, 5 * 8, 4 * 8, 16 },
|
{ 16 * 8, 6 * 8, 4 * 8, 16 },
|
||||||
"Bit:"
|
"Bit:"
|
||||||
};
|
};
|
||||||
NumberField numberfield_bitduration {
|
NumberField numberfield_bitduration {
|
||||||
{ 21 * 8, 5 * 8 },
|
{ 21 * 8, 6 * 8 },
|
||||||
4,
|
4,
|
||||||
{ 50, 9999 },
|
{ 50, 9999 },
|
||||||
1,
|
1,
|
||||||
' '
|
' '
|
||||||
};
|
};
|
||||||
Text text_us1 {
|
Text text_us1 {
|
||||||
{ 25 * 8, 5 * 8, 2 * 8, 16 },
|
{ 25 * 8, 6 * 8, 2 * 8, 16 },
|
||||||
"us"
|
"us"
|
||||||
};
|
};
|
||||||
|
|
||||||
Text text_wordduration {
|
Text text_wordduration {
|
||||||
{ 15 * 8, 7 * 8, 5 * 8, 16 },
|
{ 15 * 8, 8 * 8, 5 * 8, 16 },
|
||||||
"Word:"
|
"Word:"
|
||||||
};
|
};
|
||||||
NumberField numberfield_wordduration {
|
NumberField numberfield_wordduration {
|
||||||
{ 21 * 8, 7 * 8 },
|
{ 21 * 8, 8 * 8 },
|
||||||
5,
|
5,
|
||||||
{ 300, 99999 },
|
{ 300, 99999 },
|
||||||
100,
|
100,
|
||||||
' '
|
' '
|
||||||
};
|
};
|
||||||
Text text_us2 {
|
Text text_us2 {
|
||||||
{ 26 * 8, 7 * 8, 2 * 8, 16 },
|
{ 26 * 8, 8 * 8, 2 * 8, 16 },
|
||||||
"us"
|
"us"
|
||||||
};
|
};
|
||||||
|
|
||||||
Text text_symfield {
|
Text text_symfield {
|
||||||
{ 2 * 8, 9 * 8, 5 * 8, 16 },
|
{ 2 * 8, 10 * 8, 5 * 8, 16 },
|
||||||
"Word:"
|
"Word:"
|
||||||
};
|
};
|
||||||
SymField symfield_word {
|
SymField symfield_word {
|
||||||
{ 2 * 8, 11 * 8 },
|
{ 2 * 8, 12 * 8 },
|
||||||
20
|
20
|
||||||
};
|
};
|
||||||
Text text_format {
|
Text text_format {
|
||||||
{ 2 * 8, 13 * 8, 24 * 8, 16 },
|
{ 2 * 8, 14 * 8, 24 * 8, 16 },
|
||||||
""
|
""
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -172,6 +177,14 @@ private:
|
|||||||
"Waveform:"
|
"Waveform:"
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Waveform waveform {
|
||||||
|
{ 0, 160, 240, 32 },
|
||||||
|
waveform_buffer,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
Color::yellow()
|
||||||
|
};
|
||||||
|
|
||||||
Text text_status {
|
Text text_status {
|
||||||
{ 2 * 8, 224, 128, 16 },
|
{ 2 * 8, 224, 128, 16 },
|
||||||
"Ready"
|
"Ready"
|
||||||
|
@ -39,7 +39,6 @@ Continuous (Fox-oring)
|
|||||||
|
|
||||||
using namespace portapack;
|
using namespace portapack;
|
||||||
|
|
||||||
// TODO: TX power setting
|
|
||||||
// TODO: Live keying mode: Dit on left key, dah on right ?
|
// TODO: Live keying mode: Dit on left key, dah on right ?
|
||||||
|
|
||||||
namespace ui {
|
namespace ui {
|
||||||
@ -98,10 +97,26 @@ void MorseView::generate_message(char * text) {
|
|||||||
(*tone_defs).delta = 0; // 7 unit silence
|
(*tone_defs).delta = 0; // 7 unit silence
|
||||||
(*tone_defs++).duration = MORSE_WORD_SPACE;
|
(*tone_defs++).duration = MORSE_WORD_SPACE;
|
||||||
|
|
||||||
audio::set_rate(audio::Rate::Hz_24000);
|
transmitter_model.set_tuning_frequency(81800000);
|
||||||
|
transmitter_model.set_baseband_configuration({
|
||||||
|
.mode = 0,
|
||||||
|
.sampling_rate = 1536000U,
|
||||||
|
.decimation_factor = 1,
|
||||||
|
});
|
||||||
|
transmitter_model.set_rf_amp(true);
|
||||||
|
transmitter_model.set_lna(40);
|
||||||
|
transmitter_model.set_vga(40);
|
||||||
|
transmitter_model.set_baseband_bandwidth(1750000);
|
||||||
|
transmitter_model.enable();
|
||||||
|
|
||||||
|
//audio::set_rate(audio::Rate::Hz_24000);
|
||||||
baseband::set_tones_data(5000, 0, i, false, false);
|
baseband::set_tones_data(5000, 0, i, false, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MorseView::transmit_done() {
|
||||||
|
transmitter_model.disable();
|
||||||
|
}
|
||||||
|
|
||||||
MorseView::MorseView(
|
MorseView::MorseView(
|
||||||
NavigationView& nav
|
NavigationView& nav
|
||||||
)
|
)
|
||||||
@ -114,25 +129,8 @@ MorseView::MorseView(
|
|||||||
} });
|
} });
|
||||||
|
|
||||||
button_transmit.on_select = [this](Button&){
|
button_transmit.on_select = [this](Button&){
|
||||||
/*uint16_t c;
|
//char strtest[] = "TEST";
|
||||||
ui::Context context;
|
//generate_message(strtest);
|
||||||
|
|
||||||
make_frame();
|
|
||||||
|
|
||||||
shared_memory.afsk_samples_per_bit = 228000/persistent_memory::afsk_bitrate();
|
|
||||||
shared_memory.afsk_phase_inc_mark = persistent_memory::afsk_mark_freq()*(65536*1024)/2280;
|
|
||||||
shared_memory.afsk_phase_inc_space = persistent_memory::afsk_space_freq()*(65536*1024)/2280;
|
|
||||||
|
|
||||||
for (c = 0; c < 256; c++) {
|
|
||||||
shared_memory.lcrdata[c] = this->lcrframe[c];
|
|
||||||
}
|
|
||||||
|
|
||||||
shared_memory.afsk_transmit_done = false;
|
|
||||||
shared_memory.afsk_repeat = 5; // DEFAULT
|
|
||||||
|
|
||||||
text_status.set("Send...");*/
|
|
||||||
|
|
||||||
//transmitter_model.enable();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
button_exit.on_select = [&nav](Button&){
|
button_exit.on_select = [&nav](Button&){
|
||||||
|
@ -28,7 +28,6 @@
|
|||||||
#include "message.hpp"
|
#include "message.hpp"
|
||||||
#include "volume.hpp"
|
#include "volume.hpp"
|
||||||
#include "audio.hpp"
|
#include "audio.hpp"
|
||||||
//#include "transmitter_model.hpp"
|
|
||||||
#include "receiver_model.hpp"
|
#include "receiver_model.hpp"
|
||||||
#include "portapack.hpp"
|
#include "portapack.hpp"
|
||||||
|
|
||||||
@ -54,6 +53,7 @@ private:
|
|||||||
//rf::Frequency f;
|
//rf::Frequency f;
|
||||||
|
|
||||||
void generate_message(char * text);
|
void generate_message(char * text);
|
||||||
|
void transmit_done();
|
||||||
|
|
||||||
const char foxhunt_codes[11][3] = {
|
const char foxhunt_codes[11][3] = {
|
||||||
{ 'M', 'O', 'E' }, // -----.
|
{ 'M', 'O', 'E' }, // -----.
|
||||||
@ -192,6 +192,15 @@ private:
|
|||||||
{ 160, 260, 64, 32 },
|
{ 160, 260, 64, 32 },
|
||||||
"Exit"
|
"Exit"
|
||||||
};
|
};
|
||||||
|
|
||||||
|
MessageHandlerRegistration message_handler_tx_done {
|
||||||
|
Message::ID::TXDone,
|
||||||
|
[this](const Message* const p) {
|
||||||
|
const auto message = *reinterpret_cast<const TXDoneMessage*>(p);
|
||||||
|
if (message.done)
|
||||||
|
transmit_done();
|
||||||
|
}
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
} /* namespace ui */
|
} /* namespace ui */
|
||||||
|
@ -279,7 +279,7 @@ ReceiverMenuView::ReceiverMenuView(NavigationView& nav) {
|
|||||||
// { "AFSK", ui::Color::grey(), nullptr, [&nav](){ nav.push<NotImplementedView>(); } }, // AFSKRXView
|
// { "AFSK", ui::Color::grey(), nullptr, [&nav](){ nav.push<NotImplementedView>(); } }, // AFSKRXView
|
||||||
{ "Audio", ui::Color::green(), nullptr, [&nav](){ nav.push<AnalogAudioView>(); } },
|
{ "Audio", ui::Color::green(), nullptr, [&nav](){ nav.push<AnalogAudioView>(); } },
|
||||||
{ "CCIR", ui::Color::grey(), nullptr, [&nav](){ nav.push<NotImplementedView>(); } },
|
{ "CCIR", ui::Color::grey(), nullptr, [&nav](){ nav.push<NotImplementedView>(); } },
|
||||||
{ "Nordic/BTLE", ui::Color::grey(), &bitmap_icon_nordic_data, [&nav](){ nav.push<NotImplementedView>(); } },
|
{ "Nordic/BTLE", ui::Color::grey(), &bitmap_icon_nordic, [&nav](){ nav.push<NotImplementedView>(); } },
|
||||||
{ "POCSAG 1200", ui::Color::cyan(), nullptr, [&nav](){ nav.push<POCSAGAppView>(); } },
|
{ "POCSAG 1200", ui::Color::cyan(), nullptr, [&nav](){ nav.push<POCSAGAppView>(); } },
|
||||||
{ "SIGFOX", ui::Color::grey(), &bitmap_icon_foxhunt, [&nav](){ nav.push<NotImplementedView>(); } }, // SIGFRXView
|
{ "SIGFOX", ui::Color::grey(), &bitmap_icon_foxhunt, [&nav](){ nav.push<NotImplementedView>(); } }, // SIGFRXView
|
||||||
{ "Transponders", ui::Color::green(), nullptr, [&nav](){ nav.push<TranspondersMenuView>(); } },
|
{ "Transponders", ui::Color::green(), nullptr, [&nav](){ nav.push<TranspondersMenuView>(); } },
|
||||||
|
@ -44,7 +44,7 @@
|
|||||||
#define DTMF_R2 (uint32_t)(852 * DTMF_DELTA_COEF)
|
#define DTMF_R2 (uint32_t)(852 * DTMF_DELTA_COEF)
|
||||||
#define DTMF_R3 (uint32_t)(941 * DTMF_DELTA_COEF)
|
#define DTMF_R3 (uint32_t)(941 * DTMF_DELTA_COEF)
|
||||||
|
|
||||||
#define NUOPTIX_TONE_LENGTH 75264 // 1536000*0.049
|
#define NUOPTIX_TONE_LENGTH 75264 // 1536000*0.049s
|
||||||
|
|
||||||
namespace ui {
|
namespace ui {
|
||||||
|
|
||||||
|
@ -1285,4 +1285,66 @@ int32_t SymField::clip_value(const uint32_t index, const uint32_t value) {
|
|||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Waveform **************************************************************/
|
||||||
|
|
||||||
|
Waveform::Waveform(
|
||||||
|
Rect parent_rect,
|
||||||
|
int8_t * data,
|
||||||
|
uint32_t length,
|
||||||
|
uint32_t offset,
|
||||||
|
Color color
|
||||||
|
) : Widget { parent_rect },
|
||||||
|
data_ { data },
|
||||||
|
length_ { length },
|
||||||
|
offset_ { offset },
|
||||||
|
color_ { color }
|
||||||
|
{
|
||||||
|
data_ += offset_;
|
||||||
|
//set_focusable(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Waveform::set_offset(const uint32_t new_offset) {
|
||||||
|
if (new_offset != offset_) {
|
||||||
|
offset_ = new_offset;
|
||||||
|
set_dirty();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Waveform::set_length(const uint32_t new_length) {
|
||||||
|
if (new_length != length_) {
|
||||||
|
length_ = new_length;
|
||||||
|
set_dirty();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Waveform::paint(Painter& painter) {
|
||||||
|
uint32_t n, point_count;
|
||||||
|
Coord y, y_offset = screen_rect().pos.y;
|
||||||
|
Coord prev_x = screen_rect().pos.x, prev_y;
|
||||||
|
float x, x_inc;
|
||||||
|
Dim h = screen_rect().size.h;
|
||||||
|
|
||||||
|
// Clear
|
||||||
|
painter.fill_rectangle(screen_rect(), Color::black());
|
||||||
|
|
||||||
|
x_inc = (float)screen_rect().size.w / length_;
|
||||||
|
point_count = length_;
|
||||||
|
const float y_scale = (float)(h - 1) / 256; // TODO: Make variable
|
||||||
|
|
||||||
|
if (!point_count) return;
|
||||||
|
|
||||||
|
x = prev_x + x_inc;
|
||||||
|
h = h / 2;
|
||||||
|
|
||||||
|
prev_y = y_offset + h - (*(data_) * y_scale);
|
||||||
|
for (n = 1; n < point_count; n++) {
|
||||||
|
y = y_offset + h - (*(data_ + n) * y_scale);
|
||||||
|
display.draw_line( {prev_x, prev_y}, {(Coord)x, y}, color_);
|
||||||
|
|
||||||
|
prev_x = x;
|
||||||
|
prev_y = y;
|
||||||
|
x += x_inc;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
} /* namespace ui */
|
} /* namespace ui */
|
||||||
|
@ -481,6 +481,26 @@ private:
|
|||||||
int32_t clip_value(const uint32_t index, const uint32_t value);
|
int32_t clip_value(const uint32_t index, const uint32_t value);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class Waveform : public Widget {
|
||||||
|
public:
|
||||||
|
|
||||||
|
Waveform(Rect parent_rect, int8_t * data, uint32_t length, uint32_t offset, Color color);
|
||||||
|
|
||||||
|
Waveform(const Waveform&) = delete;
|
||||||
|
Waveform(Waveform&&) = delete;
|
||||||
|
|
||||||
|
void set_offset(const uint32_t new_offset);
|
||||||
|
void set_length(const uint32_t new_length);
|
||||||
|
|
||||||
|
void paint(Painter& painter) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
int8_t * data_;
|
||||||
|
uint32_t length_;
|
||||||
|
uint32_t offset_;
|
||||||
|
Color color_;
|
||||||
|
};
|
||||||
|
|
||||||
} /* namespace ui */
|
} /* namespace ui */
|
||||||
|
|
||||||
#endif/*__UI_WIDGET_H__*/
|
#endif/*__UI_WIDGET_H__*/
|
||||||
|
Loading…
Reference in New Issue
Block a user