Bias-T now works in capture mode

Simplified soundboard app, still some work to do
Merge remote-tracking branch 'upstream/master'
This commit is contained in:
furrtek 2018-12-18 16:25:21 +00:00
commit 1d13389b5a
21 changed files with 557 additions and 125 deletions

View File

@ -36,7 +36,7 @@ set(USE_OPT "-Os -g --specs=nano.specs")
set(USE_COPT "-std=gnu99")
# C++ specific options here (added to USE_OPT).
set(USE_CPPOPT "-std=c++14 -fno-rtti -fno-exceptions -Weffc++ -Wuninitialized")
set(USE_CPPOPT "-std=c++17 -fno-rtti -fno-exceptions -Weffc++ -Wuninitialized")
# Enable this if you want the linker to remove unused code and data
set(USE_LINK_GC yes)
@ -238,7 +238,6 @@ set(CPPSRC
apps/ui_settings.cpp
apps/ui_siggen.cpp
apps/ui_sonde.cpp
apps/ui_soundboard.cpp
apps/ui_sstvtx.cpp
# apps/ui_test.cpp
apps/ui_tone_search.cpp
@ -247,13 +246,14 @@ set(CPPSRC
apps/ui_view_wav.cpp
apps/ui_whipcalc.cpp
apps/acars_app.cpp
apps/analog_audio_app.cpp
apps/ais_app.cpp
apps/tpms_app.cpp
apps/pocsag_app.cpp
apps/ert_app.cpp
apps/analog_audio_app.cpp
apps/capture_app.cpp
apps/ert_app.cpp
apps/pocsag_app.cpp
apps/replay_app.cpp
apps/soundboard_app.cpp
apps/tpms_app.cpp
protocols/aprs.cpp
protocols/ax25.cpp
protocols/bht.cpp

View File

@ -27,9 +27,6 @@
#include "portapack.hpp"
using namespace portapack;
#include "portapack_persistent_memory.hpp"
using namespace portapack;
namespace ui {
CaptureAppView::CaptureAppView(NavigationView& nav) {
@ -49,16 +46,16 @@ CaptureAppView::CaptureAppView(NavigationView& nav) {
&waterfall,
});
field_frequency.set_value(target_frequency());
field_frequency.set_value(receiver_model.tuning_frequency());
field_frequency.set_step(receiver_model.frequency_step());
field_frequency.on_change = [this](rf::Frequency f) {
this->on_target_frequency_changed(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>(this->target_frequency());
auto new_view = nav.push<FrequencyKeypadView>(receiver_model.tuning_frequency());
new_view->on_changed = [this](rf::Frequency f) {
this->on_target_frequency_changed(f);
this->on_tuning_frequency_changed(f);
this->field_frequency.set_value(f);
};
};
@ -70,35 +67,27 @@ CaptureAppView::CaptureAppView(NavigationView& nav) {
};
option_bandwidth.on_change = [this](size_t, uint32_t base_rate) {
sampling_rate = 8 * base_rate;
sampling_rate = 8 * base_rate; // Decimation by 8 done on baseband side
waterfall.on_hide();
set_target_frequency(target_frequency());
record_view.set_sampling_rate(sampling_rate);
radio::set_baseband_rate(sampling_rate);
receiver_model.set_sampling_rate(sampling_rate);
waterfall.on_show();
};
radio::enable({
tuning_frequency(),
sampling_rate,
baseband_bandwidth,
rf::Direction::Receive,
receiver_model.rf_amp(),
static_cast<int8_t>(receiver_model.lna()),
static_cast<int8_t>(receiver_model.vga()),
});
option_bandwidth.set_selected_index(7); // 500k
receiver_model.set_modulation(ReceiverModel::Mode::Capture);
receiver_model.set_baseband_bandwidth(baseband_bandwidth);
receiver_model.enable();
record_view.on_error = [&nav](std::string message) {
nav.display_modal("Error", message);
};
}
CaptureAppView::~CaptureAppView() {
radio::disable();
receiver_model.disable();
baseband::shutdown();
}
@ -120,21 +109,8 @@ void CaptureAppView::focus() {
record_view.focus();
}
void CaptureAppView::on_target_frequency_changed(rf::Frequency f) {
set_target_frequency(f);
}
void CaptureAppView::set_target_frequency(const rf::Frequency new_value) {
persistent_memory::set_tuned_frequency(new_value);;
radio::set_tuning_frequency(tuning_frequency());
}
rf::Frequency CaptureAppView::target_frequency() const {
return persistent_memory::tuned_frequency();
}
rf::Frequency CaptureAppView::tuning_frequency() const {
return target_frequency() - (sampling_rate / 4);
void CaptureAppView::on_tuning_frequency_changed(rf::Frequency f) {
receiver_model.set_tuning_frequency(f);
}
} /* namespace ui */

View File

@ -29,9 +29,6 @@
#include "ui_record_view.hpp"
#include "ui_spectrum.hpp"
#include <string>
#include <memory>
namespace ui {
class CaptureAppView : public View {
@ -53,12 +50,7 @@ private:
uint32_t sampling_rate = 0;
static constexpr uint32_t baseband_bandwidth = 2500000;
void on_target_frequency_changed(rf::Frequency f);
rf::Frequency target_frequency() const;
void set_target_frequency(const rf::Frequency new_value);
rf::Frequency tuning_frequency() const;
void on_tuning_frequency_changed(rf::Frequency f);
Labels labels {
{ { 0 * 8, 1 * 16 }, "Rate:", Color::light_grey() },

View File

@ -0,0 +1,250 @@
/*
* Copyright (C) 2015 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.
*/
// To prepare samples: for f in ./*.wav; do sox "$f" -r 48000 -c 1 -b8 --norm "conv/$f"; done
#include "soundboard_app.hpp"
#include "string_format.hpp"
#include "tonesets.hpp"
using namespace tonekey;
using namespace portapack;
namespace ui {
bool SoundBoardView::is_active() const {
return (bool)replay_thread;
}
void SoundBoardView::stop() {
if (is_active())
replay_thread.reset();
transmitter_model.disable();
tx_view.set_transmitting(false);
//button_play.set_bitmap(&bitmap_play);
ready_signal = false;
}
void SoundBoardView::handle_replay_thread_done(const uint32_t return_code) {
stop();
progressbar.set_value(0);
if (return_code == ReplayThread::END_OF_FILE) {
if (check_random.value()) {
lfsr_v = lfsr_iterate(lfsr_v);
playing_id = lfsr_v % file_list.size();
menu_view.set_highlighted(playing_id);
start_tx(playing_id);
} else if (check_loop.value()) {
start_tx(playing_id);
}
} else if (return_code == ReplayThread::READ_ERROR) {
file_error();
}
}
void SoundBoardView::set_ready() {
ready_signal = true;
}
void SoundBoardView::focus() {
menu_view.focus();
}
void SoundBoardView::file_error() {
nav_.display_modal("Error", "File read error.");
}
void SoundBoardView::start_tx(const uint32_t id) {
auto reader = std::make_unique<WAVFileReader>();
uint32_t tone_key_index = options_tone_key.selected_index();
uint32_t sample_rate;
stop();
if (!reader->open(u"/WAV/" + file_list[id].native())) {
file_error();
return;
}
playing_id = id;
progressbar.set_max(reader->sample_count());
//button_play.set_bitmap(&bitmap_stop);
sample_rate = reader->sample_rate();
replay_thread = std::make_unique<ReplayThread>(
std::move(reader),
read_size, buffer_count,
&ready_signal,
[](uint32_t return_code) {
ReplayThreadDoneMessage message { return_code };
EventDispatcher::send_message(message);
}
);
baseband::set_audiotx_config(
1536000 / 20, // Update vu-meter at 20Hz
transmitter_model.channel_bandwidth(),
0, // Gain is unused
TONES_F2D(tone_key_frequency(tone_key_index), 1536000)
);
baseband::set_sample_rate(sample_rate);
transmitter_model.set_sampling_rate(1536000);
transmitter_model.set_baseband_bandwidth(1750000);
transmitter_model.enable();
tx_view.set_transmitting(true);
}
/*void SoundBoardView::show_infos() {
if (!reader->open(file_list[menu_view.highlighted_index()]))
return;
text_duration.set(to_string_time_ms(reader->ms_duration()));
text_title.set(reader->title().substr(0, 15));
}*/
void SoundBoardView::on_tx_progress(const uint32_t progress) {
progressbar.set_value(progress);
}
void SoundBoardView::on_select_entry() {
tx_view.focus();
}
void SoundBoardView::refresh_list() {
auto reader = std::make_unique<WAVFileReader>();
file_list.clear();
// List directories and files, put directories up top
for (const auto& entry : std::filesystem::directory_iterator(u"WAV", u"*")) {
if (std::filesystem::is_regular_file(entry.status())) {
if (entry.path().string().length()) {
auto entry_extension = entry.path().extension().string();
for (auto &c: entry_extension)
c = toupper(c);
if (entry_extension == ".WAV") {
if (reader->open(u"/WAV/" + entry.path().native())) {
if ((reader->channels() == 1) && (reader->bits_per_sample() == 8)) {
//sounds[c].ms_duration = reader->ms_duration();
//sounds[c].path = u"WAV/" + entry.path().native();
file_list.push_back(entry.path());
if (file_list.size() == 100)
break;
}
}
}
}
}
}
if (!file_list.size()) {
// Hide widgets, show warning
menu_view.hidden(true);
text_empty.hidden(false);
set_dirty();
} else {
// Hide warning, show widgets
menu_view.hidden(false);
text_empty.hidden(true);
set_dirty();
menu_view.clear();
for (size_t n = 0; n < file_list.size(); n++) {
menu_view.add_item({
file_list[n].string().substr(0, 30),
ui::Color::white(),
nullptr,
[this](){
on_select_entry();
}
});
}
menu_view.set_highlighted(0); // Refresh
}
}
SoundBoardView::SoundBoardView(
NavigationView& nav
) : nav_ (nav)
{
baseband::run_image(portapack::spi_flash::image_tag_audio_tx);
add_children({
&labels,
&menu_view,
&text_empty,
&options_tone_key,
&text_title,
&text_duration,
&progressbar,
&check_loop,
&check_random,
&tx_view
});
refresh_list();
text_title.set(to_string_dec_uint(file_list.size()));
tone_keys_populate(options_tone_key);
options_tone_key.set_selected_index(0);
check_loop.set_value(false);
check_random.set_value(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) {
transmitter_model.set_tuning_frequency(f);
};
};
tx_view.on_start = [this]() {
start_tx(menu_view.highlighted_index());
};
tx_view.on_stop = [this]() {
tx_view.set_transmitting(false);
stop();
};
}
SoundBoardView::~SoundBoardView() {
transmitter_model.disable();
baseband::shutdown();
}
}

View File

@ -0,0 +1,161 @@
/*
* Copyright (C) 2015 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 __UI_SOUNDBOARD_H__
#define __UI_SOUNDBOARD_H__
#include "ui_widget.hpp"
#include "ui_transmitter.hpp"
#include "replay_thread.hpp"
#include "baseband_api.hpp"
#include "lfsr_random.hpp"
#include "io_wave.hpp"
#include "tone_key.hpp"
namespace ui {
class SoundBoardView : public View {
public:
SoundBoardView(NavigationView& nav);
~SoundBoardView();
SoundBoardView(const SoundBoardView&) = delete;
SoundBoardView(SoundBoardView&&) = delete;
SoundBoardView& operator=(const SoundBoardView&) = delete;
SoundBoardView& operator=(SoundBoardView&&) = delete;
void focus() override;
std::string title() const override { return "Soundboard"; };
private:
NavigationView& nav_;
enum tx_modes {
NORMAL = 0,
RANDOM
};
tx_modes tx_mode = NORMAL;
uint32_t playing_id { };
std::vector<std::filesystem::path> file_list { };
const size_t read_size { 2048 }; // Less ?
const size_t buffer_count { 3 };
std::unique_ptr<ReplayThread> replay_thread { };
bool ready_signal { false };
lfsr_word_t lfsr_v = 1;
//void show_infos();
void start_tx(const uint32_t id);
//void on_ctcss_changed(uint32_t v);
void stop();
bool is_active() const;
void set_ready();
void handle_replay_thread_done(const uint32_t return_code);
void file_error();
void on_tx_progress(const uint32_t progress);
void refresh_list();
void on_select_entry();
Labels labels {
{ { 0, 20 * 8 + 4 }, "Title:", Color::light_grey() },
{ { 0, 23 * 8 }, "Key:", Color::light_grey() }
};
MenuView menu_view {
{ 0, 2 * 8, 240, 20 * 8 },
true
};
Text text_empty {
{ 7 * 8, 12 * 8, 16 * 8, 16 },
"Empty directory !",
};
Text text_title {
{ 6 * 8, 20 * 8 + 4, 15 * 8, 16 }
};
Text text_duration {
{ 22 * 8, 20 * 8 + 4, 6 * 8, 16 }
};
OptionsField options_tone_key {
{ 4 * 8, 23 * 8 },
18,
{ }
};
Checkbox check_loop {
{ 8, 25 * 8 + 4 },
4,
"Loop"
};
Checkbox check_random {
{ 10 * 8, 25 * 8 + 4 },
6,
"Random"
};
ProgressBar progressbar {
{ 0 * 8, 30 * 8 - 4, 30 * 8, 16 }
};
TransmitterView tx_view {
16 * 16,
5000,
12
};
MessageHandlerRegistration message_handler_replay_thread_error {
Message::ID::ReplayThreadDone,
[this](const Message* const p) {
const auto message = *reinterpret_cast<const ReplayThreadDoneMessage*>(p);
this->handle_replay_thread_done(message.return_code);
}
};
MessageHandlerRegistration message_handler_fifo_signal {
Message::ID::RequestSignal,
[this](const Message* const p) {
const auto message = static_cast<const RequestSignalMessage*>(p);
if (message->signal == RequestSignalMessage::Signal::FillRequest) {
this->set_ready();
}
}
};
MessageHandlerRegistration message_handler_tx_progress {
Message::ID::TXProgress,
[this](const Message* const p) {
const auto message = *reinterpret_cast<const TXProgressMessage*>(p);
this->on_tx_progress(message.progress);
}
};
};
} /* namespace ui */
#endif/*__UI_SOUNDBOARD_H__*/

View File

@ -247,10 +247,10 @@ constexpr ClockControls si5351_clock_control_clkin {
si5351_clock_control_common[4] | si5351_clock_control_ms_src_clkin,
si5351_clock_control_common[5] | si5351_clock_control_ms_src_clkin,
si5351_clock_control_common[6] | si5351_clock_control_ms_src_clkin,
si5351_clock_control_common[7] | si5351_clock_control_ms_src_xtal,
si5351_clock_control_common[7] | si5351_clock_control_ms_src_clkin,
};
void ClockManager::init(const bool use_clkin) {
void ClockManager::init() {
/* Must be sure to run the M4 core from IRC when messing with the signal
* generator that sources the GP_CLKIN signal that drives the micro-
* controller's PLL1 input.
@ -269,11 +269,23 @@ void ClockManager::init(const bool use_clkin) {
clock_generator.enable_fanout();
clock_generator.set_pll_input_sources(si5351_pll_input_sources);
//const bool use_clkin = false;
const auto clkin_present = !clock_generator.clkin_loss_of_signal();
auto clkin_valid = false;
if( clkin_present ) {
// Measure Si5351B CLKIN frequency against LPC43xx IRC oscillator
set_gp_clkin_to_clkin_direct();
start_frequency_monitor_measurement(cgu::CLK_SEL::GP_CLKIN);
wait_For_frequency_monitor_measurement_done();
const auto clkin_frequency = get_frequency_monitor_measurement_in_hertz();
// CLKIN is required to be 10MHz. FREQ_MON measurement is accurate to 1.5%
// due to LPC43xx IRC oscillator precision.
clkin_valid = (clkin_frequency >= 9850000) && (clkin_frequency <= 10150000);
}
clock_generator.set_clock_control(
use_clkin ?
si5351_clock_control_clkin
: si5351_clock_control_xtal
clkin_valid ? si5351_clock_control_clkin : si5351_clock_control_xtal
);
clock_generator.write(si5351_pll_a_xtal_reg);
@ -422,6 +434,38 @@ void ClockManager::disable_gp_clkin_source() {
clock_generator.disable_output(clock_generator_output_mcu_clkin);
}
void ClockManager::set_gp_clkin_to_clkin_direct() {
clock_generator.set_clock_control(
clock_generator_output_mcu_clkin,
{ ClockControl::CLK_IDRV_2mA | ClockControl::CLK_SRC_CLKIN | ClockControl::CLK_INV_Normal | ClockControl::MS_INT_Integer | ClockControl::CLK_PDN_Power_On }
);
enable_gp_clkin_source();
}
void ClockManager::start_frequency_monitor_measurement(const cgu::CLK_SEL clk_sel) {
// Measure a clock input for 480 cycles of the LPC43xx IRC.
LPC_CGU->FREQ_MON = LPC_CGU_FREQ_MON_Type {
.RCNT = 480,
.FCNT = 0,
.MEAS = 0,
.CLK_SEL = toUType(clk_sel),
.RESERVED0 = 0
};
LPC_CGU->FREQ_MON.MEAS = 1;
}
void ClockManager::wait_For_frequency_monitor_measurement_done() {
// FREQ_MON mechanism fails to finish if there's no clock present on selected input?!
while(LPC_CGU->FREQ_MON.MEAS == 1);
}
uint32_t ClockManager::get_frequency_monitor_measurement_in_hertz() {
// Measurement is only as accurate as the LPC43xx IRC oscillator,
// which is +/- 1.5%. Measurement is for 480 IRC clcocks. Scale
// the cycle count to get a value in Hertz.
return LPC_CGU->FREQ_MON.FCNT * 25000;
}
void ClockManager::enable_xtal_oscillator() {
LPC_CGU->XTAL_OSC_CTRL.BYPASS = 0;
LPC_CGU->XTAL_OSC_CTRL.ENABLE = 1;

View File

@ -42,7 +42,7 @@ public:
{
}
void init(const bool use_clkin);
void init();
void shutdown();
void run_from_irc();
@ -66,6 +66,8 @@ public:
void set_reference_ppb(const int32_t ppb);
uint32_t get_frequency_monitor_measurement_in_hertz();
private:
I2C& i2c0;
si5351::Si5351& clock_generator;
@ -75,6 +77,10 @@ private:
void enable_gp_clkin_source();
void disable_gp_clkin_source();
void set_gp_clkin_to_clkin_direct();
void start_frequency_monitor_measurement(const cgu::CLK_SEL clk_sel);
void wait_For_frequency_monitor_measurement_done();
void enable_xtal_oscillator();
void disable_xtal_oscillator();

View File

@ -306,6 +306,10 @@ public:
while(device_status() & 0x80);
}
bool clkin_loss_of_signal() {
return (device_status() >> 4) & 1;
}
void enable_fanout() {
write_register(Register::FanoutEnable, 0b11010000);
}
@ -369,6 +373,11 @@ public:
update_all_clock_control();
}
void set_clock_control(const size_t n, const ClockControl::Type clock_control) {
_clock_control[n] = clock_control;
write_register(Register::CLKControl_Base + n, _clock_control[n]);
}
void enable_clock(const size_t n) {
_clock_control[n] &= ~ClockControl::CLK_PDN_Mask;
write_register(Register::CLKControl_Base + n, _clock_control[n]);

View File

@ -104,7 +104,7 @@ void poll_ext_clock() {
if (clkin_status != prev_clkin_status) {
StatusRefreshMessage message { };
EventDispatcher::send_message(message);
clock_manager.init(clkin_status);
clock_manager.init();
}
prev_clkin_status = clkin_status;
@ -296,7 +296,7 @@ bool init() {
led_rx.setup();
led_tx.setup();
clock_manager.init(false);
clock_manager.init();
clock_manager.set_reference_ppb(persistent_memory::correction_ppb());
clock_manager.run_at_full_speed();

View File

@ -275,6 +275,7 @@ void ReceiverModel::update_modulation() {
break;
case Mode::SpectrumAnalysis:
case Mode::Capture:
break;
}
}

View File

@ -37,6 +37,7 @@ public:
NarrowbandFMAudio = 1,
WidebandFMAudio = 2,
SpectrumAnalysis = 3,
Capture = 4
};
rf::Frequency tuning_frequency() const;

View File

@ -78,8 +78,8 @@ const tone_key_t tone_keys = {
{ "38 --", 250.300 },
{ "50 0Z", 254.100 },
{ "Axient 28kHz", 28000.0 },
{ "Sennheiser 32.768k", 32768.0 },
{ "Sennheiser 32.000k", 32000.0 },
{ "Senn. 32.768k", 32768.0 },
{ "Senn. 32.000k", 32000.0 },
{ "Sony 32.382k", 32382.0 },
{ "Shure 19kHz", 19000.0 }
};

View File

@ -58,7 +58,6 @@
#include "ui_settings.hpp"
#include "ui_siggen.hpp"
#include "ui_sonde.hpp"
#include "ui_soundboard.hpp"
#include "ui_sstvtx.hpp"
//#include "ui_test.hpp"
#include "ui_tone_search.hpp"
@ -73,6 +72,7 @@
#include "ert_app.hpp"
#include "pocsag_app.hpp"
#include "replay_app.hpp"
#include "soundboard_app.hpp"
#include "tpms_app.hpp"
#include "core_control.hpp"
@ -166,6 +166,8 @@ void SystemStatusView::refresh() {
image_clock_status.set_bitmap(&bitmap_icon_clk_int);
button_bias_tee.set_foreground(ui::Color::light_grey());
}
set_dirty();
}
void SystemStatusView::set_back_enabled(bool new_value) {
@ -186,9 +188,7 @@ void SystemStatusView::on_stealth() {
portapack::persistent_memory::set_stealth_mode(mode);
button_stealth.set_foreground(mode ? ui::Color::green() : ui::Color::light_grey());
button_stealth.set_dirty();
button_stealth.set_foreground(mode ? Color::green() : Color::light_grey());
}
void SystemStatusView::on_bias_tee() {
@ -196,6 +196,7 @@ void SystemStatusView::on_bias_tee() {
nav_.display_modal("Bias voltage", "Enable DC voltage on\nantenna connector ?", YESNO, [this](bool v) {
if (v) {
portapack::set_antenna_bias(true);
//radio::set_antenna_bias(true);
receiver_model.set_antenna_bias();
transmitter_model.set_antenna_bias();
refresh();
@ -203,6 +204,7 @@ void SystemStatusView::on_bias_tee() {
});
} else {
portapack::set_antenna_bias(false);
//radio::set_antenna_bias(false);
receiver_model.set_antenna_bias();
transmitter_model.set_antenna_bias();
refresh();
@ -371,7 +373,7 @@ TransmittersMenuView::TransmittersMenuView(NavigationView& nav) {
{ "Key fob", ui::Color::orange(), &bitmap_icon_keyfob, [&nav](){ nav.push<KeyfobView>(); } },
{ "Microphone", ui::Color::green(), &bitmap_icon_microphone, [&nav](){ nav.push<MicTXView>(); } },
{ "Morse code", ui::Color::green(), &bitmap_icon_morse, [&nav](){ nav.push<MorseView>(); } },
{ "NTTWorks burger pager", ui::Color::yellow(), &bitmap_icon_burger, [&nav](){ nav.push<CoasterPagerView>(); } },
{ "Burger pagers", ui::Color::yellow(), &bitmap_icon_burger, [&nav](){ nav.push<CoasterPagerView>(); } },
//{ "Nuoptix DTMF timecode", ui::Color::green(), &bitmap_icon_nuoptix, [&nav](){ nav.push<NuoptixView>(); } },
{ "OOK encoders", ui::Color::yellow(), &bitmap_icon_remote, [&nav](){ nav.push<EncodersView>(); } },
{ "POCSAG", ui::Color::green(), &bitmap_icon_pocsag, [&nav](){ nav.push<POCSAGTXView>(); } },
@ -478,10 +480,12 @@ SystemView::SystemView(
navigation_view.push<PlayDeadView>();
} else {*/
navigation_view.push<SystemMenuView>();
if (portapack::persistent_memory::config_splash())
navigation_view.push<BMPView>();
else
navigation_view.push<SystemMenuView>();
//else
// navigation_view.push<SystemMenuView>();
//}
}
@ -504,7 +508,6 @@ BMPView::BMPView(NavigationView& nav) {
button_done.on_select = [this, &nav](Button&){
nav.pop();
nav.push<SystemMenuView>();
};
}

View File

@ -36,7 +36,7 @@ set(USE_OPT "-O3 -g -falign-functions=16 -fno-math-errno --specs=nano.specs")
set(USE_COPT "-std=gnu99")
# C++ specific options here (added to USE_OPT).
set(USE_CPPOPT "-std=c++14 -fno-rtti -fno-exceptions -Weffc++ -Wuninitialized")
set(USE_CPPOPT "-std=c++17 -fno-rtti -fno-exceptions -Weffc++ -Wuninitialized")
# Enable this if you want the linker to remove unused code and data
set(USE_LINK_GC yes)

View File

@ -23,7 +23,6 @@
#include "proc_audiotx.hpp"
#include "portapack_shared_memory.hpp"
#include "sine_table_int8.hpp"
//#include "audio_output.hpp"
#include "event_m4.hpp"
#include <cstdint>
@ -32,17 +31,18 @@ void AudioTXProcessor::execute(const buffer_c8_t& buffer){
if (!configured) return;
// Zero-order hold (poop)
for (size_t i = 0; i < buffer.count; i++) {
resample_acc += resample_inc;
if (resample_acc >= 0x10000) {
resample_acc -= 0x10000;
if (stream) {
const size_t bytes_to_read = (buffer.count / 32); // /32 (oversampling) should be == 64
bytes_read += stream->read(audio_buffer.p, bytes_to_read);
stream->read(&audio_sample, 1);
bytes_read++;
}
}
// Fill and "stretch"
for (size_t i = 0; i < buffer.count; i++) {
if (!(i & 31))
audio_sample = audio_buffer.p[i >> 5] - 0x80;
sample = tone_gen.process(audio_sample);
sample = tone_gen.process(audio_sample - 0x80);
// FM
delta = sample * fm_delta;
@ -50,22 +50,20 @@ void AudioTXProcessor::execute(const buffer_c8_t& buffer){
phase += delta;
sphase = phase + (64 << 24);
re = (sine_table_i8[(sphase & 0xFF000000U) >> 24]);
im = (sine_table_i8[(phase & 0xFF000000U) >> 24]);
re = sine_table_i8[(sphase & 0xFF000000U) >> 24];
im = sine_table_i8[(phase & 0xFF000000U) >> 24];
buffer.p[i] = { (int8_t)re, (int8_t)im };
}
spectrum_samples += buffer.count;
if( spectrum_samples >= spectrum_interval_samples ) {
spectrum_samples -= spectrum_interval_samples;
progress_samples += buffer.count;
if (progress_samples >= progress_interval_samples) {
progress_samples -= progress_interval_samples;
txprogress_message.progress = bytes_read; // Inform UI about progress
txprogress_message.done = false;
shared_memory.application_queue.push(txprogress_message);
}
//AudioOutput::fill_audio_buffer(preview_audio_buffer, true);
}
void AudioTXProcessor::on_message(const Message* const message) {
@ -96,12 +94,8 @@ void AudioTXProcessor::on_message(const Message* const message) {
void AudioTXProcessor::audio_config(const AudioTXConfigMessage& message) {
fm_delta = message.deviation_hz * (0xFFFFFFULL / baseband_fs);
tone_gen.configure(message.tone_key_delta, message.tone_key_mix_weight);
}
void AudioTXProcessor::samplerate_config(const SamplerateConfigMessage& message) {
baseband_fs = message.sample_rate;
baseband_thread.set_sampling_rate(baseband_fs);
spectrum_interval_samples = baseband_fs / 20;
progress_interval_samples = message.divider;
resample_acc = 0;
}
void AudioTXProcessor::replay_config(const ReplayConfigMessage& message) {
@ -116,6 +110,10 @@ void AudioTXProcessor::replay_config(const ReplayConfigMessage& message) {
}
}
void AudioTXProcessor::samplerate_config(const SamplerateConfigMessage& message) {
resample_inc = (((uint64_t)message.sample_rate) << 16) / baseband_fs; // 16.16 fixed point message.sample_rate
}
int main() {
EventDispatcher event_dispatcher { std::make_unique<AudioTXProcessor>() };
event_dispatcher.run();

View File

@ -35,35 +35,22 @@ public:
void on_message(const Message* const msg) override;
private:
size_t baseband_fs = 0;
static constexpr size_t baseband_fs = 1536000;
BasebandThread baseband_thread { baseband_fs, this, NORMALPRIO + 20, baseband::Direction::Transmit };
std::array<uint8_t, 64> audio { };
const buffer_t<uint8_t> audio_buffer {
audio.data(),
audio.size(),
baseband_fs / 8
};
std::unique_ptr<StreamOutput> stream { };
ToneGen tone_gen { };
uint32_t resample_inc { }, resample_acc { };
uint32_t fm_delta { 0 };
uint32_t phase { 0 }, sphase { 0 };
int8_t out_sample { };
int32_t sample { 0 }, audio_sample { 0 }, delta { };
uint8_t audio_sample { };
int32_t sample { 0 }, delta { };
int8_t re { 0 }, im { 0 };
size_t spectrum_interval_samples = 0;
size_t spectrum_samples = 0;
//int16_t audio_data[64];
/*const buffer_s16_t preview_audio_buffer {
audio_data,
sizeof(int16_t)*64
};*/
size_t progress_interval_samples, progress_samples = 0;
bool configured { false };
uint32_t bytes_read { 0 };

View File

@ -35,7 +35,7 @@ set(USE_OPT "-Os -g -falign-functions=16 -fno-math-errno --specs=nano.specs")
set(USE_COPT "-std=gnu99")
# C++ specific options here (added to USE_OPT).
set(USE_CPPOPT "-std=c++14 -fno-rtti -fno-exceptions -Weffc++ -Wuninitialized")
set(USE_CPPOPT "-std=c++17 -fno-rtti -fno-exceptions -Weffc++ -Wuninitialized")
# Enable this if you want the linker to remove unused code and data
set(USE_LINK_GC yes)

View File

@ -307,6 +307,10 @@ __STATIC_INLINE void __set_FPSCR(uint32_t fpscr)
#elif defined ( __GNUC__ ) /*------------------ GNU Compiler ---------------------*/
/* GNU gcc specific functions */
#ifndef __STATIC_FORCEINLINE
#define __STATIC_FORCEINLINE __attribute__((always_inline)) static inline
#endif
/** \brief Enable IRQ Interrupts
This function enables IRQ interrupts by clearing the I-bit in the CPSR.
@ -403,15 +407,15 @@ __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_xPSR(void)
/** \brief Get Process Stack Pointer
This function returns the current value of the Process Stack Pointer (PSP).
\details Returns the current value of the Process Stack Pointer (PSP).
\return PSP Register value
*/
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_PSP(void)
__STATIC_FORCEINLINE uint32_t __get_PSP(void)
{
register uint32_t result;
uint32_t result;
__ASM volatile ("MRS %0, psp\n" : "=r" (result) );
__ASM volatile ("MRS %0, psp" : "=r" (result) );
return(result);
}
@ -430,19 +434,18 @@ __attribute__( ( always_inline ) ) __STATIC_INLINE void __set_PSP(uint32_t topOf
/** \brief Get Main Stack Pointer
This function returns the current value of the Main Stack Pointer (MSP).
\details Returns the current value of the Main Stack Pointer (MSP).
\return MSP Register value
*/
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_MSP(void)
__STATIC_FORCEINLINE uint32_t __get_MSP(void)
{
register uint32_t result;
uint32_t result;
__ASM volatile ("MRS %0, msp\n" : "=r" (result) );
__ASM volatile ("MRS %0, msp" : "=r" (result) );
return(result);
}
/** \brief Set Main Stack Pointer
This function assigns the given value to the Main Stack Pointer (MSP).

View File

@ -108,7 +108,7 @@ inline void clear() {
namespace cgu {
enum class CLK_SEL {
enum class CLK_SEL : uint8_t {
RTC_32KHZ = 0x00,
IRC = 0x01,
ENET_RX_CLK = 0x02,

View File

@ -37,6 +37,7 @@
#include <memory>
#include <vector>
#include <string>
#include <functional>
namespace ui {

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB