Added PWM RSSI output for NBFM and WFM

This commit is contained in:
furrtek 2016-07-28 05:25:33 +02:00
parent 1beac3bdbd
commit 1d697d2201
22 changed files with 274 additions and 118 deletions

View File

@ -100,6 +100,15 @@ void set_afsk_data(const char message_data[], const uint32_t afsk_samples_per_bi
send_message(&message); send_message(&message);
} }
void set_pwmrssi(int32_t avg, bool enabled) {
const PWMRSSIConfigureMessage message {
enabled,
1000, // 1kHz
avg
};
send_message(&message);
}
static bool baseband_image_running = false; static bool baseband_image_running = false;
void run_image(const portapack::spi_flash::image_tag_t image_tag) { void run_image(const portapack::spi_flash::image_tag_t image_tag) {

View File

@ -53,6 +53,7 @@ struct WFMConfig {
}; };
void set_xylos_data(const char ccir_message[]); void set_xylos_data(const char ccir_message[]);
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, 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 uint32_t afsk_phase_inc_space, const uint8_t afsk_repeat, const uint32_t afsk_bw,
const bool afsk_alt_format); const bool afsk_alt_format);

View File

@ -1,5 +1,6 @@
/* /*
* Copyright (C) 2015 Jared Boone, ShareBrained Technology, Inc. * Copyright (C) 2015 Jared Boone, ShareBrained Technology, Inc.
* Copyright (C) 2016 Furrtek
* *
* This file is part of PortaPack. * This file is part of PortaPack.
* *
@ -26,6 +27,48 @@
namespace ui { namespace ui {
/*
00000000 00000000 00000000
11110001 11100111 10111110
10001010 00001000 00001000
10001010 00001000 00001000
11110001 11000111 00001000
10010000 00100000 10001000
10001000 00100000 10001000
10001011 11001111 00111110
00000000 00000000 00000000
11111100 01111000 01111000
10000100 01001000 01001000
10000100 01001000 01001000
10000100 01001000 01001000
10000100 01001000 01001000
10000100 01001000 01001000
10000111 11001111 11001110
*/
static constexpr uint8_t bitmap_rssipwm_data[] = {
0x00, 0x00, 0x00,
0x8F, 0xE7, 0x7D,
0x51, 0x10, 0x10,
0x51, 0x10, 0x10,
0x8F, 0xE3, 0x10,
0x09, 0x04, 0x11,
0x11, 0x04, 0x11,
0xD1, 0xF3, 0x7C,
0x00, 0x00, 0x00,
0x3F, 0x1E, 0x1E,
0x21, 0x12, 0x12,
0x21, 0x12, 0x12,
0x21, 0x12, 0x12,
0x21, 0x12, 0x12,
0x21, 0x12, 0x12,
0xE1, 0xF3, 0x73
};
static constexpr Bitmap bitmap_rssipwm {
{ 24, 16 }, bitmap_rssipwm_data
};
static constexpr uint8_t bitmap_keyboard_data[] = { static constexpr uint8_t bitmap_keyboard_data[] = {
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,

View File

@ -1,5 +1,6 @@
/* /*
* Copyright (C) 2014 Jared Boone, ShareBrained Technology, Inc. * Copyright (C) 2014 Jared Boone, ShareBrained Technology, Inc.
* Copyright (C) 2016 Furrtek
* *
* This file is part of PortaPack. * This file is part of PortaPack.
* *

View File

@ -21,22 +21,12 @@
*/ */
#include "ui_lcr.hpp" #include "ui_lcr.hpp"
#include "ui_receiver.hpp"
#include "ui_afsksetup.hpp" #include "ui_afsksetup.hpp"
#include "ui_debug.hpp" #include "ui_debug.hpp"
#include "ch.h"
#include "ff.h"
#include "baseband_api.hpp" #include "baseband_api.hpp"
#include "hackrf_gpio.hpp"
#include "portapack.hpp"
#include "event_m0.hpp"
#include "string_format.hpp" #include "string_format.hpp"
#include "hackrf_hal.hpp"
#include "portapack_shared_memory.hpp"
#include "portapack_persistent_memory.hpp" #include "portapack_persistent_memory.hpp"
#include <cstring> #include <cstring>
@ -231,6 +221,7 @@ void LCRView::on_txdone(int n) {
char str[16]; char str[16];
if (n > 0) { if (n > 0) {
// Repeating...
repeat_index = n + 1; repeat_index = n + 1;
if (tx_mode == SCAN) { if (tx_mode == SCAN) {
scan_progress++; scan_progress++;
@ -239,9 +230,11 @@ void LCRView::on_txdone(int n) {
update_progress(); update_progress();
} }
} else { } else {
// Done transmitting
if ((tx_mode == SCAN) && (scan_index < (LCR_SCAN_COUNT - 1))) { if ((tx_mode == SCAN) && (scan_index < (LCR_SCAN_COUNT - 1))) {
transmitter_model.disable(); transmitter_model.disable();
if (abort_scan) { if (abort_scan) {
// Kill scan process
strcpy(str, "Abort @"); strcpy(str, "Abort @");
strcat(str, rgsb); strcat(str, rgsb);
text_status.set(str); text_status.set(str);
@ -415,16 +408,17 @@ LCRView::LCRView(NavigationView& nav) {
}; };
button_clear.on_select = [this, &nav](Button&) { button_clear.on_select = [this, &nav](Button&) {
uint8_t n;
if (tx_mode == IDLE) { if (tx_mode == IDLE) {
memset(litteral, 0, 5 * 8); memset(litteral, 0, 5 * 8);
options_ec.set_selected_index(0); options_ec.set_selected_index(0); // Auto
checkbox_am_a.set_value(true); for (n = 0; n < 5; n++)
checkbox_am_b.set_value(true); checkboxes[n].set_value(true);
checkbox_am_c.set_value(true);
checkbox_am_d.set_value(true);
checkbox_am_e.set_value(true);
set_dirty(); set_dirty();
start_tx(false); start_tx(false);
} else if (tx_mode == SCAN) {
abort_scan = true;
} }
}; };
} }

View File

@ -22,16 +22,8 @@
#include "ui.hpp" #include "ui.hpp"
#include "ui_widget.hpp" #include "ui_widget.hpp"
#include "ui_painter.hpp"
#include "ui_menu.hpp"
#include "ui_navigation.hpp"
#include "ui_textentry.hpp" #include "ui_textentry.hpp"
#include "ui_font_fixed_8x16.hpp"
#include "clock_manager.hpp"
#include "message.hpp" #include "message.hpp"
#include "rf_path.hpp"
#include "max2837.hpp"
#include "volume.hpp"
#include "transmitter_model.hpp" #include "transmitter_model.hpp"
namespace ui { namespace ui {
@ -149,36 +141,6 @@ private:
"TX setup" "TX setup"
}; };
Checkbox checkbox_am_a {
{ 16, 64 },
0,
""
};
Checkbox checkbox_am_b {
{ 16, 96 },
0,
""
};
Checkbox checkbox_am_c {
{ 16, 128 },
0,
""
};
Checkbox checkbox_am_d {
{ 16, 160 },
0,
""
};
Checkbox checkbox_am_e {
{ 16, 192 },
0,
""
};
Button button_lcrdebug { Button button_lcrdebug {
{ 168, 216, 56, 24 }, { 168, 216, 56, 24 },
"DEBUG" "DEBUG"

View File

@ -238,14 +238,15 @@ ReceiverMenuView::ReceiverMenuView(NavigationView& nav) {
/* SystemMenuView ********************************************************/ /* SystemMenuView ********************************************************/
SystemMenuView::SystemMenuView(NavigationView& nav) { SystemMenuView::SystemMenuView(NavigationView& nav) {
add_items<12>({ { add_items<11>({ {
{ "Play dead", ui::Color::red(), [&nav](){ nav.push<PlayDeadView>(false); } }, { "Play dead", ui::Color::red(), [&nav](){ nav.push<PlayDeadView>(false); } },
{ "Receiver RX", ui::Color::cyan(), [&nav](){ nav.push<ReceiverMenuView>(); } }, { "Receiver RX", ui::Color::cyan(), [&nav](){ nav.push<ReceiverMenuView>(); } },
{ "Capture RX", ui::Color::orange(), [&nav](){ nav.push<CaptureAppView>(); } },
{ "Close Call RX", ui::Color::cyan(), [&nav](){ nav.push<CloseCallView>(); } }, { "Close Call RX", ui::Color::cyan(), [&nav](){ nav.push<CloseCallView>(); } },
{ "Pokemon GO Away TX", ui::Color::blue(), [&nav](){ nav.push<JammerView>(); } }, //{ "Pokemon GO Away TX", ui::Color::blue(), [&nav](){ nav.push<JammerView>(); } },
//{ "Soundboard TX", ui::Color::yellow(), [&nav](){ nav.push<LoadModuleView>(md5_baseband_tx, SoundBoard); } }, //{ "Soundboard TX", ui::Color::yellow(), [&nav](){ nav.push<LoadModuleView>(md5_baseband_tx, SoundBoard); } },
//{ "Audio TX", ui::Color::yellow(), [&nav](){ nav.push<LoadModuleView>(md5_baseband_tx, AudioTX); } }, //{ "Audio TX", ui::Color::yellow(), [&nav](){ nav.push<LoadModuleView>(md5_baseband_tx, AudioTX); } },
{ "Frequency manager", ui::Color::white(), [&nav](){ nav.push<FreqManView>(); } }, //{ "Frequency manager", ui::Color::white(), [&nav](){ nav.push<FreqManView>(); } },
//{ "EPAR TX", ui::Color::green(), [&nav](){ nav.push<LoadModuleView>(md5_baseband_tx, EPAR); } }, //{ "EPAR TX", ui::Color::green(), [&nav](){ nav.push<LoadModuleView>(md5_baseband_tx, EPAR); } },
{ "Xylos TX", ui::Color::green(), [&nav](){ nav.push<XylosView>(); } }, { "Xylos TX", ui::Color::green(), [&nav](){ nav.push<XylosView>(); } },
{ "TEDI/LCR TX", ui::Color::orange(), [&nav](){ nav.push<LCRView>(); } }, { "TEDI/LCR TX", ui::Color::orange(), [&nav](){ nav.push<LCRView>(); } },

View File

@ -22,6 +22,8 @@
#include "ui_record_view.hpp" #include "ui_record_view.hpp"
#include "portapack.hpp" #include "portapack.hpp"
#include "message.hpp"
#include "portapack_shared_memory.hpp"
using namespace portapack; using namespace portapack;
#include "file.hpp" #include "file.hpp"
@ -176,6 +178,7 @@ RecordView::RecordView(
{ {
add_children({ { add_children({ {
&rect_background, &rect_background,
&button_pwmrssi,
&button_record, &button_record,
&text_record_filename, &text_record_filename,
&text_record_dropped, &text_record_dropped,
@ -183,6 +186,10 @@ RecordView::RecordView(
} }); } });
rect_background.set_parent_rect({ { 0, 0 }, size() }); rect_background.set_parent_rect({ { 0, 0 }, size() });
button_pwmrssi.on_select = [this](ImageButton&) {
this->toggle_pwmrssi();
};
button_record.on_select = [this](ImageButton&) { button_record.on_select = [this](ImageButton&) {
this->toggle(); this->toggle();
@ -228,6 +235,24 @@ void RecordView::toggle() {
} }
} }
void RecordView::toggle_pwmrssi() {
pwmrssi_enabled = !pwmrssi_enabled;
// Send to RSSI widget
const PWMRSSIConfigureMessage message {
pwmrssi_enabled,
1000,
0
};
shared_memory.application_queue.push(message);
if( !pwmrssi_enabled ) {
button_pwmrssi.set_foreground(Color::orange());
} else {
button_pwmrssi.set_foreground(Color::green());
}
}
void RecordView::start() { void RecordView::start() {
stop(); stop();
@ -342,6 +367,10 @@ void RecordView::update_status_display() {
const auto s = to_string_dec_uint(dropped_percent, 2, ' ') + "\%"; const auto s = to_string_dec_uint(dropped_percent, 2, ' ') + "\%";
text_record_dropped.set(s); text_record_dropped.set(s);
} }
if (pwmrssi_enabled) {
button_pwmrssi.invert_colors();
}
if( sampling_rate ) { if( sampling_rate ) {
const auto space_info = std::filesystem::space(""); const auto space_info = std::filesystem::space("");

View File

@ -64,6 +64,7 @@ public:
private: private:
void toggle(); void toggle();
void toggle_pwmrssi();
Optional<File::Error> write_metadata_file(const std::string& filename); Optional<File::Error> write_metadata_file(const std::string& filename);
void on_tick_second(); void on_tick_second();
@ -72,6 +73,7 @@ private:
void handle_capture_thread_done(const File::Error error); void handle_capture_thread_done(const File::Error error);
void handle_error(const File::Error error); void handle_error(const File::Error error);
bool pwmrssi_enabled = false;
const std::string filename_stem_pattern; const std::string filename_stem_pattern;
const FileType file_type; const FileType file_type;
const size_t write_size; const size_t write_size;
@ -82,16 +84,23 @@ private:
Rectangle rect_background { Rectangle rect_background {
Color::black() Color::black()
}; };
ImageButton button_pwmrssi {
{ 2, 0 * 16, 3 * 8, 1 * 16 },
&bitmap_rssipwm,
Color::orange(),
Color::black()
};
ImageButton button_record { ImageButton button_record {
{ 0 * 8, 0 * 16, 2 * 8, 1 * 16 }, { 4 * 8, 0 * 16, 2 * 8, 1 * 16 },
&bitmap_record, &bitmap_record,
Color::red(), Color::red(),
Color::black() Color::black()
}; };
Text text_record_filename { Text text_record_filename {
{ 3 * 8, 0 * 16, 8 * 8, 16 }, { 7 * 8, 0 * 16, 8 * 8, 16 },
"", "",
}; };

View File

@ -21,6 +21,7 @@
#include "ui_rssi.hpp" #include "ui_rssi.hpp"
#include "baseband_api.hpp"
#include "utility.hpp" #include "utility.hpp"
#include <algorithm> #include <algorithm>
@ -88,6 +89,17 @@ void RSSI::paint(Painter& painter) {
r4, r4,
Color::black() Color::black()
); );
if (pwmrssi_enabled) {
const range_t<int> pwmrssi_avg_range { 0, 96 };
const auto pwmrssi_avg = pwmrssi_avg_range.clip((avg_ - raw_min) * 96 / raw_delta);
baseband::set_pwmrssi(pwmrssi_avg, true);
}
}
void RSSI::set_pwmrssi(bool enabled) {
pwmrssi_enabled = enabled;
if (!enabled) baseband::set_pwmrssi(0, false);
} }
void RSSI::on_statistics_update(const RSSIStatistics& statistics) { void RSSI::on_statistics_update(const RSSIStatistics& statistics) {

View File

@ -46,11 +46,13 @@ public:
} }
void paint(Painter& painter) override; void paint(Painter& painter) override;
private: private:
int32_t min_; int32_t min_;
int32_t avg_; int32_t avg_;
int32_t max_; int32_t max_;
bool pwmrssi_enabled = false;
MessageHandlerRegistration message_handler_stats { MessageHandlerRegistration message_handler_stats {
Message::ID::RSSIStatistics, Message::ID::RSSIStatistics,
@ -58,8 +60,17 @@ private:
this->on_statistics_update(static_cast<const RSSIStatisticsMessage*>(p)->statistics); this->on_statistics_update(static_cast<const RSSIStatisticsMessage*>(p)->statistics);
} }
}; };
MessageHandlerRegistration message_handler_pwmrssi {
Message::ID::PWMRSSIConfigure,
[this](const Message* const p) {
const auto message = *reinterpret_cast<const PWMRSSIConfigureMessage*>(p);
this->set_pwmrssi(message.enabled);
}
};
void on_statistics_update(const RSSIStatistics& statistics); void on_statistics_update(const RSSIStatistics& statistics);
void set_pwmrssi(bool enabled);
}; };
} }

View File

@ -21,20 +21,11 @@
*/ */
#include "ui_xylos.hpp" #include "ui_xylos.hpp"
#include "ch.h"
#include "hackrf_hal.hpp"
#include "event_m0.hpp"
#include "audio.hpp"
#include "ui_alphanum.hpp" #include "ui_alphanum.hpp"
#include "ff.h"
#include "hackrf_gpio.hpp"
#include "portapack.hpp" #include "portapack.hpp"
#include "baseband_api.hpp" #include "baseband_api.hpp"
//#include "audio.hpp"
#include "hackrf_hal.hpp"
#include "portapack_shared_memory.hpp"
#include "portapack_persistent_memory.hpp" #include "portapack_persistent_memory.hpp"
#include <cstring> #include <cstring>

View File

@ -22,9 +22,7 @@
#include "ui.hpp" #include "ui.hpp"
#include "ui_widget.hpp" #include "ui_widget.hpp"
#include "ui_painter.hpp"
#include "ui_navigation.hpp" #include "ui_navigation.hpp"
#include "ui_menu.hpp"
#include "ui_font_fixed_8x16.hpp" #include "ui_font_fixed_8x16.hpp"
#include "bulb_on_bmp.hpp" #include "bulb_on_bmp.hpp"
@ -32,8 +30,7 @@
#include "bulb_ignore_bmp.hpp" #include "bulb_ignore_bmp.hpp"
#include "message.hpp" #include "message.hpp"
#include "max2837.hpp" //#include "volume.hpp"
#include "volume.hpp"
#include "transmitter_model.hpp" #include "transmitter_model.hpp"
//#include "receiver_model.hpp" //#include "receiver_model.hpp"
#include "portapack.hpp" #include "portapack.hpp"

View File

@ -32,7 +32,7 @@ void NarrowbandFMAudio::execute(const buffer_c8_t& buffer) {
if( !configured ) { if( !configured ) {
return; return;
} }
const auto decim_0_out = decim_0.execute(buffer, dst_buffer); const auto decim_0_out = decim_0.execute(buffer, dst_buffer);
const auto decim_1_out = decim_1.execute(decim_0_out, dst_buffer); const auto decim_1_out = decim_1.execute(decim_0_out, dst_buffer);
const auto channel_out = channel_filter.execute(decim_1_out, dst_buffer); const auto channel_out = channel_filter.execute(decim_1_out, dst_buffer);
@ -40,8 +40,23 @@ void NarrowbandFMAudio::execute(const buffer_c8_t& buffer) {
feed_channel_stats(channel_out); feed_channel_stats(channel_out);
channel_spectrum.feed(channel_out, channel_filter_pass_f, channel_filter_stop_f); channel_spectrum.feed(channel_out, channel_filter_pass_f, channel_filter_stop_f);
auto audio = demod.execute(channel_out, audio_buffer); if ( !pwmrssi_enabled ) {
audio_output.write(audio); auto audio = demod.execute(channel_out, audio_buffer);
audio_output.write(audio);
} else {
for (c = 0; c < 32; c++) {
if (synth_acc < pwmrssi_avg)
pwmrssi_audio_buffer.p[c] = 32767;
else
pwmrssi_audio_buffer.p[c] = -32768;
if (synth_acc < 30) // 24kHz / 30 = 800Hz (TODO: use pwmrssi_freq !)
synth_acc++;
else
synth_acc = 0;
}
audio_output.write(pwmrssi_audio_buffer);
}
} }
void NarrowbandFMAudio::on_message(const Message* const message) { void NarrowbandFMAudio::on_message(const Message* const message) {
@ -58,6 +73,10 @@ void NarrowbandFMAudio::on_message(const Message* const message) {
case Message::ID::CaptureConfig: case Message::ID::CaptureConfig:
capture_config(*reinterpret_cast<const CaptureConfigMessage*>(message)); capture_config(*reinterpret_cast<const CaptureConfigMessage*>(message));
break; break;
case Message::ID::PWMRSSIConfigure:
pwmrssi_config(*reinterpret_cast<const PWMRSSIConfigureMessage*>(message));
break;
default: default:
break; break;
@ -83,11 +102,19 @@ void NarrowbandFMAudio::configure(const NBFMConfigureMessage& message) {
channel_filter_pass_f = message.channel_filter.pass_frequency_normalized * channel_filter_input_fs; channel_filter_pass_f = message.channel_filter.pass_frequency_normalized * channel_filter_input_fs;
channel_filter_stop_f = message.channel_filter.stop_frequency_normalized * channel_filter_input_fs; channel_filter_stop_f = message.channel_filter.stop_frequency_normalized * channel_filter_input_fs;
channel_spectrum.set_decimation_factor(std::floor(channel_filter_output_fs / (channel_filter_pass_f + channel_filter_stop_f))); channel_spectrum.set_decimation_factor(std::floor(channel_filter_output_fs / (channel_filter_pass_f + channel_filter_stop_f)));
audio_output.configure(message.audio_hpf_config, message.audio_deemph_config, 0.8f); audio_output.configure(message.audio_hpf_config, message.audio_deemph_config); // , 0.8f
synth_acc = 0;
configured = true; configured = true;
} }
void NarrowbandFMAudio::pwmrssi_config(const PWMRSSIConfigureMessage& message) {
pwmrssi_enabled = message.enabled;
pwmrssi_freq = message.freq;
pwmrssi_avg = message.avg / 3;
}
void NarrowbandFMAudio::capture_config(const CaptureConfigMessage& message) { void NarrowbandFMAudio::capture_config(const CaptureConfigMessage& message) {
if( message.config ) { if( message.config ) {
audio_output.set_stream(std::make_unique<StreamInput>(message.config)); audio_output.set_stream(std::make_unique<StreamInput>(message.config));

View File

@ -56,6 +56,12 @@ private:
audio.data(), audio.data(),
audio.size() audio.size()
}; };
std::array<int16_t, 32> pwm;
const buffer_s16_t pwmrssi_audio_buffer {
(int16_t*)pwm.data(),
sizeof(pwm) / sizeof(int16_t)
};
dsp::decimate::FIRC8xR16x24FS4Decim8 decim_0; dsp::decimate::FIRC8xR16x24FS4Decim8 decim_0;
dsp::decimate::FIRC16xR16x32Decim8 decim_1; dsp::decimate::FIRC16xR16x32Decim8 decim_1;
@ -68,8 +74,14 @@ private:
AudioOutput audio_output; AudioOutput audio_output;
SpectrumCollector channel_spectrum; SpectrumCollector channel_spectrum;
unsigned int c, synth_acc = 0;
bool pwmrssi_enabled = false;
uint32_t pwmrssi_freq;
uint32_t pwmrssi_avg;
bool configured { false }; bool configured { false };
void pwmrssi_config(const PWMRSSIConfigureMessage& message);
void configure(const NBFMConfigureMessage& message); void configure(const NBFMConfigureMessage& message);
void capture_config(const CaptureConfigMessage& message); void capture_config(const CaptureConfigMessage& message);
}; };

View File

@ -31,7 +31,7 @@ void WidebandFMAudio::execute(const buffer_c8_t& buffer) {
if( !configured ) { if( !configured ) {
return; return;
} }
const auto decim_0_out = decim_0.execute(buffer, dst_buffer); const auto decim_0_out = decim_0.execute(buffer, dst_buffer);
const auto channel = decim_1.execute(decim_0_out, dst_buffer); const auto channel = decim_1.execute(decim_0_out, dst_buffer);
@ -44,32 +44,49 @@ void WidebandFMAudio::execute(const buffer_c8_t& buffer) {
channel_spectrum.feed(channel, channel_filter_pass_f, channel_filter_stop_f); channel_spectrum.feed(channel, channel_filter_pass_f, channel_filter_stop_f);
} }
/* 384kHz complex<int16_t>[256] if ( !pwmrssi_enabled ) {
* -> FM demodulation /* 384kHz complex<int16_t>[256]
* -> 384kHz int16_t[256] */ * -> FM demodulation
/* TODO: To improve adjacent channel rejection, implement complex channel filter: * -> 384kHz int16_t[256] */
* pass < +/- 100kHz, stop > +/- 200kHz /* TODO: To improve adjacent channel rejection, implement complex channel filter:
*/ * pass < +/- 100kHz, stop > +/- 200kHz
*/
auto audio_oversampled = demod.execute(channel, work_audio_buffer); auto audio_oversampled = demod.execute(channel, work_audio_buffer);
/* 384kHz int16_t[256] /* 384kHz int16_t[256]
* -> 4th order CIC decimation by 2, gain of 1 * -> 4th order CIC decimation by 2, gain of 1
* -> 192kHz int16_t[128] */ * -> 192kHz int16_t[128] */
auto audio_4fs = audio_dec_1.execute(audio_oversampled, work_audio_buffer); auto audio_4fs = audio_dec_1.execute(audio_oversampled, work_audio_buffer);
/* 192kHz int16_t[128] /* 192kHz int16_t[128]
* -> 4th order CIC decimation by 2, gain of 1 * -> 4th order CIC decimation by 2, gain of 1
* -> 96kHz int16_t[64] */ * -> 96kHz int16_t[64] */
auto audio_2fs = audio_dec_2.execute(audio_4fs, work_audio_buffer); auto audio_2fs = audio_dec_2.execute(audio_4fs, work_audio_buffer);
/* 96kHz int16_t[64] /* 96kHz int16_t[64]
* -> FIR filter, <15kHz (0.156fs) pass, >19kHz (0.198fs) stop, gain of 1 * -> FIR filter, <15kHz (0.156fs) pass, >19kHz (0.198fs) stop, gain of 1
* -> 48kHz int16_t[32] */ * -> 48kHz int16_t[32] */
auto audio = audio_filter.execute(audio_2fs, work_audio_buffer); auto audio = audio_filter.execute(audio_2fs, work_audio_buffer);
/* -> 48kHz int16_t[32] */
audio_output.write(audio);
} else {
for (c = 0; c < 32; c++) {
if (synth_acc < pwmrssi_avg)
pwmrssi_audio_buffer.p[c] = 32767;
else
pwmrssi_audio_buffer.p[c] = -32768;
if (synth_acc < 96) // 48kHz / 96 = 500Hz (TODO: use pwmrssi_freq !)
synth_acc++;
else
synth_acc = 0;
}
/* -> 48kHz int16_t[32] */ /* -> 48kHz int16_t[32] */
audio_output.write(audio); audio_output.write(pwmrssi_audio_buffer);
}
} }
void WidebandFMAudio::on_message(const Message* const message) { void WidebandFMAudio::on_message(const Message* const message) {
@ -86,6 +103,10 @@ void WidebandFMAudio::on_message(const Message* const message) {
case Message::ID::CaptureConfig: case Message::ID::CaptureConfig:
capture_config(*reinterpret_cast<const CaptureConfigMessage*>(message)); capture_config(*reinterpret_cast<const CaptureConfigMessage*>(message));
break; break;
case Message::ID::PWMRSSIConfigure:
pwmrssi_config(*reinterpret_cast<const PWMRSSIConfigureMessage*>(message));
break;
default: default:
break; break;
@ -114,9 +135,18 @@ void WidebandFMAudio::configure(const WFMConfigureMessage& message) {
channel_spectrum.set_decimation_factor(1); channel_spectrum.set_decimation_factor(1);
pwmrssi_enabled = false;
synth_acc = 0;
configured = true; configured = true;
} }
void WidebandFMAudio::pwmrssi_config(const PWMRSSIConfigureMessage& message) {
pwmrssi_enabled = message.enabled;
pwmrssi_freq = message.freq;
pwmrssi_avg = message.avg;
}
void WidebandFMAudio::capture_config(const CaptureConfigMessage& message) { void WidebandFMAudio::capture_config(const CaptureConfigMessage& message) {
if( message.config ) { if( message.config ) {
audio_output.set_stream(std::make_unique<StreamInput>(message.config)); audio_output.set_stream(std::make_unique<StreamInput>(message.config));

View File

@ -54,6 +54,12 @@ private:
(int16_t*)dst.data(), (int16_t*)dst.data(),
sizeof(dst) / sizeof(int16_t) sizeof(dst) / sizeof(int16_t)
}; };
std::array<int16_t, 32> pwm;
const buffer_s16_t pwmrssi_audio_buffer {
(int16_t*)pwm.data(),
sizeof(pwm) / sizeof(int16_t)
};
dsp::decimate::FIRC8xR16x24FS4Decim4 decim_0; dsp::decimate::FIRC8xR16x24FS4Decim4 decim_0;
dsp::decimate::FIRC16xR16x16Decim2 decim_1; dsp::decimate::FIRC16xR16x16Decim2 decim_1;
@ -70,8 +76,14 @@ private:
SpectrumCollector channel_spectrum; SpectrumCollector channel_spectrum;
size_t spectrum_interval_samples = 0; size_t spectrum_interval_samples = 0;
size_t spectrum_samples = 0; size_t spectrum_samples = 0;
unsigned int c, synth_acc = 0;
bool pwmrssi_enabled = false;
uint32_t pwmrssi_freq;
uint32_t pwmrssi_avg;
bool configured { false }; bool configured { false };
void pwmrssi_config(const PWMRSSIConfigureMessage& message);
void configure(const WFMConfigureMessage& message); void configure(const WFMConfigureMessage& message);
void capture_config(const CaptureConfigMessage& message); void capture_config(const CaptureConfigMessage& message);
}; };

View File

@ -21,10 +21,6 @@
*/ */
#include "proc_xylos.hpp" #include "proc_xylos.hpp"
#include "dsp_iir_config.hpp"
#include "audio_output.hpp"
#include "portapack_shared_memory.hpp" #include "portapack_shared_memory.hpp"
#include "sine_table_int8.hpp" #include "sine_table_int8.hpp"
#include "event_m4.hpp" #include "event_m4.hpp"

View File

@ -69,7 +69,7 @@ public:
Retune = 21, Retune = 21,
XylosConfigure = 22, XylosConfigure = 22,
AFSKConfigure = 23, AFSKConfigure = 23,
ModuleID = 24, PWMRSSIConfigure = 24,
FIFOSignal = 25, FIFOSignal = 25,
FIFOData = 26, FIFOData = 26,
MAX MAX
@ -479,15 +479,24 @@ public:
int n = 0; int n = 0;
}; };
class ModuleIDMessage : public Message {
class PWMRSSIConfigureMessage : public Message {
public: public:
ModuleIDMessage( PWMRSSIConfigureMessage(
) : Message { ID::ModuleID } const bool enabled,
const uint32_t freq,
const int32_t avg
) : Message { ID::PWMRSSIConfigure },
enabled(enabled),
freq(freq),
avg(avg)
{ {
} }
bool query; const bool enabled;
char md5_signature[16]; const uint32_t freq;
const int32_t avg;
}; };
class XylosConfigureMessage : public Message { class XylosConfigureMessage : public Message {

View File

@ -369,13 +369,13 @@ void BigFrequency::paint(Painter& painter) {
digit_y = rect.pos.y; digit_y = rect.pos.y;
if (digit < 16) { if (digit < 16) {
digit_def = big_segment_font[(uint8_t)digit]; digit_def = big_segment_font[(uint8_t)digit];
if (digit_def & 0x01) painter.fill_rectangle({{digit_x + 4, digit_y}, {20, 4}}, segment_color); if (digit_def & 0x01) painter.fill_rectangle({{digit_x + 4, digit_y}, {20, 4}}, segment_color);
if (digit_def & 0x02) painter.fill_rectangle({{digit_x + 24, digit_y + 4}, {4, 20}}, segment_color); if (digit_def & 0x02) painter.fill_rectangle({{digit_x + 24, digit_y + 4}, {4, 20}}, segment_color);
if (digit_def & 0x04) painter.fill_rectangle({{digit_x + 24, digit_y + 28}, {4, 20}}, segment_color); if (digit_def & 0x04) painter.fill_rectangle({{digit_x + 24, digit_y + 28}, {4, 20}}, segment_color);
if (digit_def & 0x08) painter.fill_rectangle({{digit_x + 4, digit_y + 48}, {20, 4}}, segment_color); if (digit_def & 0x08) painter.fill_rectangle({{digit_x + 4, digit_y + 48}, {20, 4}}, segment_color);
if (digit_def & 0x10) painter.fill_rectangle({{digit_x, digit_y + 28}, {4, 20}}, segment_color); if (digit_def & 0x10) painter.fill_rectangle({{digit_x, digit_y + 28}, {4, 20}}, segment_color);
if (digit_def & 0x20) painter.fill_rectangle({{digit_x, digit_y + 4}, {4, 20}}, segment_color); if (digit_def & 0x20) painter.fill_rectangle({{digit_x, digit_y + 4}, {4, 20}}, segment_color);
if (digit_def & 0x40) painter.fill_rectangle({{digit_x + 4, digit_y + 24}, {20, 4}}, segment_color); if (digit_def & 0x40) painter.fill_rectangle({{digit_x + 4, digit_y + 24}, {20, 4}}, segment_color);
} }
if (i == 3) { if (i == 3) {
// Dot // Dot
@ -665,6 +665,15 @@ void Image::set_background(const Color color) {
set_dirty(); set_dirty();
} }
void Image::invert_colors() {
Color temp;
temp = background_;
background_ = foreground_;
foreground_ = temp;
set_dirty();
}
void Image::paint(Painter& painter) { void Image::paint(Painter& painter) {
if( bitmap_ ) { if( bitmap_ ) {
// Code also handles ImageButton behavior. // Code also handles ImageButton behavior.

View File

@ -289,6 +289,7 @@ public:
void set_bitmap(const Bitmap* bitmap); void set_bitmap(const Bitmap* bitmap);
void set_foreground(const Color color); void set_foreground(const Color color);
void set_background(const Color color); void set_background(const Color color);
void invert_colors();
void paint(Painter& painter) override; void paint(Painter& painter) override;

Binary file not shown.