mirror of
https://github.com/portapack-mayhem/mayhem-firmware.git
synced 2026-09-14 18:43:01 +00:00
Compare commits
6 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 8391ca8052 | |||
| 807c76346b | |||
| 308573918c | |||
| 74442f197d | |||
| b53c8e1f80 | |||
| c5f73cf8f4 |
@@ -694,7 +694,7 @@ FileManagerView::FileManagerView(
|
||||
|
||||
button_show_hidden_files.on_select = [this]() {
|
||||
show_hidden_files = !show_hidden_files;
|
||||
button_show_hidden_files.set_color(show_hidden_files ? Color::green() : Color::dark_grey());
|
||||
button_show_hidden_files.set_color(show_hidden_files ? Color::dark_green() : Color::dark_grey());
|
||||
reload_current();
|
||||
};
|
||||
}
|
||||
|
||||
@@ -261,26 +261,26 @@ class FileManagerView : public FileManBaseView {
|
||||
{22 * 8, 29 * 8, 4 * 8, 32},
|
||||
{},
|
||||
&bitmap_icon_new_dir,
|
||||
Color::green()};
|
||||
Color::dark_green()};
|
||||
|
||||
NewButton button_new_file{
|
||||
{26 * 8, 29 * 8, 4 * 8, 32},
|
||||
{},
|
||||
&bitmap_icon_new_file,
|
||||
Color::green()};
|
||||
Color::dark_green()};
|
||||
|
||||
NewButton button_open_notepad{
|
||||
{0 * 8, 34 * 8, 4 * 8, 32},
|
||||
{},
|
||||
&bitmap_icon_notepad,
|
||||
Color::orange()};
|
||||
Color::dark_orange()};
|
||||
|
||||
NewButton button_rename_timestamp{
|
||||
|
||||
{4 * 8, 29 * 8, 4 * 8, 32},
|
||||
{},
|
||||
&bitmap_icon_options_datetime,
|
||||
Color::orange(),
|
||||
Color::dark_blue(),
|
||||
/*vcenter*/ true};
|
||||
|
||||
NewButton button_open_iq_trim{
|
||||
@@ -288,7 +288,7 @@ class FileManagerView : public FileManBaseView {
|
||||
{4 * 8, 34 * 8, 4 * 8, 32},
|
||||
{},
|
||||
&bitmap_icon_trim,
|
||||
Color::orange()};
|
||||
Color::dark_orange()};
|
||||
|
||||
NewButton button_show_hidden_files{
|
||||
{17 * 8, 34 * 8, 4 * 8, 32},
|
||||
|
||||
@@ -72,6 +72,8 @@ SondeView::SondeView(NavigationView& nav)
|
||||
|
||||
check_beep.on_select = [this](Checkbox&, bool v) {
|
||||
beep = v;
|
||||
if (v)
|
||||
baseband::request_beep();
|
||||
};
|
||||
|
||||
check_log.on_select = [this](Checkbox&, bool v) {
|
||||
|
||||
@@ -67,6 +67,12 @@ set(EXTCPPSRC
|
||||
external/extsensors/main.cpp
|
||||
external/extsensors/ui_extsensors.cpp
|
||||
external/extsensors/ui_extsensors.hpp
|
||||
|
||||
#foxhunt
|
||||
external/foxhunt/main.cpp
|
||||
external/foxhunt/ui_foxhunt_rx.cpp
|
||||
external/foxhunt/ui_foxhunt_rx.hpp
|
||||
|
||||
)
|
||||
|
||||
set(EXTAPPLIST
|
||||
@@ -86,4 +92,5 @@ set(EXTAPPLIST
|
||||
keyfob
|
||||
tetris
|
||||
extsensors
|
||||
foxhunt_rx
|
||||
)
|
||||
|
||||
+7
@@ -39,6 +39,7 @@ MEMORY
|
||||
ram_external_app_keyfob(rwx) : org = 0xADBD0000, len = 32k
|
||||
ram_external_app_tetris(rwx) : org = 0xADBE0000, len = 32k
|
||||
ram_external_app_extsensors(rwx) : org = 0xADBF0000, len = 32k
|
||||
ram_external_app_foxhunt_rx(rwx) : org = 0xADC00000, len = 32k
|
||||
}
|
||||
|
||||
SECTIONS
|
||||
@@ -139,6 +140,12 @@ SECTIONS
|
||||
*(*ui*external_app*extsensors*);
|
||||
} > ram_external_app_extsensors
|
||||
|
||||
.external_app_foxhunt_rx : ALIGN(4) SUBALIGN(4)
|
||||
{
|
||||
KEEP(*(.external_app.app_foxhunt_rx.application_information));
|
||||
*(*ui*external_app*foxhunt_rx*);
|
||||
} > ram_external_app_foxhunt_rx
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
+82
@@ -0,0 +1,82 @@
|
||||
/*
|
||||
* Copyright (C) 2024 HTotoo
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "ui.hpp"
|
||||
#include "ui_foxhunt_rx.hpp"
|
||||
#include "ui_navigation.hpp"
|
||||
#include "external_app.hpp"
|
||||
|
||||
namespace ui::external_app::foxhunt_rx {
|
||||
void initialize_app(ui::NavigationView& nav) {
|
||||
nav.push<FoxhuntRxView>();
|
||||
}
|
||||
} // namespace ui::external_app::foxhunt_rx
|
||||
|
||||
extern "C" {
|
||||
|
||||
__attribute__((section(".external_app.app_foxhunt_rx.application_information"), used)) application_information_t _application_information_foxhunt_rx = {
|
||||
/*.memory_location = */ (uint8_t*)0x00000000,
|
||||
/*.externalAppEntry = */ ui::external_app::foxhunt_rx::initialize_app,
|
||||
/*.header_version = */ CURRENT_HEADER_VERSION,
|
||||
/*.app_version = */ VERSION_MD5,
|
||||
|
||||
/*.app_name = */ "Fox hunt",
|
||||
/*.bitmap_data = */ {
|
||||
0x18,
|
||||
0x18,
|
||||
0x28,
|
||||
0x14,
|
||||
0x68,
|
||||
0x16,
|
||||
0x68,
|
||||
0x16,
|
||||
0xC8,
|
||||
0x13,
|
||||
0x88,
|
||||
0x11,
|
||||
0x04,
|
||||
0x20,
|
||||
0x24,
|
||||
0x24,
|
||||
0x22,
|
||||
0x44,
|
||||
0x01,
|
||||
0x80,
|
||||
0x06,
|
||||
0x60,
|
||||
0x98,
|
||||
0x19,
|
||||
0x20,
|
||||
0x04,
|
||||
0x40,
|
||||
0x02,
|
||||
0x80,
|
||||
0x01,
|
||||
0x00,
|
||||
0x00,
|
||||
},
|
||||
/*.icon_color = */ ui::Color::yellow().v,
|
||||
/*.menu_location = */ app_location_t::RX,
|
||||
|
||||
/*.m4_app_tag = portapack::spi_flash::image_tag_am_audio */ {'P', 'A', 'M', 'A'},
|
||||
/*.m4_app_offset = */ 0x00000000, // will be filled at compile time
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,107 @@
|
||||
/*
|
||||
* Copyright (C) 2024 HTotoo
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "ui_foxhunt_rx.hpp"
|
||||
|
||||
#include "audio.hpp"
|
||||
#include "rtc_time.hpp"
|
||||
#include "baseband_api.hpp"
|
||||
#include "string_format.hpp"
|
||||
#include "portapack_persistent_memory.hpp"
|
||||
|
||||
using namespace portapack;
|
||||
using namespace modems;
|
||||
using namespace ui;
|
||||
|
||||
namespace ui::external_app::foxhunt_rx {
|
||||
|
||||
void FoxhuntRxView::focus() {
|
||||
field_frequency.focus();
|
||||
}
|
||||
|
||||
FoxhuntRxView::FoxhuntRxView(NavigationView& nav)
|
||||
: nav_{nav} {
|
||||
baseband::run_image(portapack::spi_flash::image_tag_am_audio);
|
||||
|
||||
add_children({&rssi,
|
||||
&field_rf_amp,
|
||||
&field_lna,
|
||||
&field_vga,
|
||||
&field_volume,
|
||||
&field_frequency,
|
||||
&freq_stats_db,
|
||||
&rssi_graph,
|
||||
&geomap,
|
||||
&clear_markers,
|
||||
&add_current_marker});
|
||||
|
||||
clear_markers.on_select = [this](Button&) {
|
||||
geomap.clear_markers();
|
||||
};
|
||||
add_current_marker.on_select = [this](Button&) {
|
||||
GeoMarker tmp{my_lat, my_lon, my_orientation};
|
||||
geomap.store_marker(tmp);
|
||||
};
|
||||
geomap.set_mode(DISPLAY);
|
||||
geomap.set_manual_panning(false);
|
||||
// geomap.set_enable_additional_zoom(true);
|
||||
// geomap.set_hide_center_marker(true); //todo hide again after testing
|
||||
geomap.set_focusable(true);
|
||||
geomap.clear_markers();
|
||||
receiver_model.set_modulation(ReceiverModel::Mode::AMAudio);
|
||||
field_frequency.set_step(100);
|
||||
receiver_model.enable();
|
||||
audio::output::start();
|
||||
rssi_graph.set_nb_columns(64);
|
||||
geomap.init();
|
||||
}
|
||||
|
||||
FoxhuntRxView::~FoxhuntRxView() {
|
||||
receiver_model.disable();
|
||||
baseband::shutdown();
|
||||
audio::output::stop();
|
||||
}
|
||||
|
||||
void FoxhuntRxView::on_statistics_update(const ChannelStatistics& statistics) {
|
||||
static int16_t last_max_db = -1000;
|
||||
rssi_graph.add_values(rssi.get_min(), rssi.get_avg(), rssi.get_max(), statistics.max_db);
|
||||
// refresh db
|
||||
if (last_max_db != statistics.max_db) {
|
||||
last_max_db = statistics.max_db;
|
||||
freq_stats_db.set("Power: " + to_string_dec_int(statistics.max_db) + " db");
|
||||
}
|
||||
|
||||
} /* on_statistic_updates */
|
||||
|
||||
void FoxhuntRxView::on_gps(const GPSPosDataMessage* msg) {
|
||||
my_lat = msg->lat;
|
||||
my_lon = msg->lon;
|
||||
geomap.update_my_position(msg->lat, msg->lon, msg->altitude);
|
||||
geomap.move(my_lon, my_lat);
|
||||
geomap.set_dirty();
|
||||
}
|
||||
void FoxhuntRxView::on_orientation(const OrientationDataMessage* msg) {
|
||||
my_orientation = msg->angle;
|
||||
geomap.set_angle(msg->angle);
|
||||
geomap.update_my_orientation(msg->angle, true);
|
||||
}
|
||||
|
||||
} // namespace ui::external_app::foxhunt_rx
|
||||
@@ -0,0 +1,118 @@
|
||||
/*
|
||||
* Copyright (C) 2024 HTotoo
|
||||
*
|
||||
* 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_FOXHUNT_RX_H__
|
||||
#define __UI_FOXHUNT_RX_H__
|
||||
|
||||
#include "ui.hpp"
|
||||
#include "ui_language.hpp"
|
||||
#include "ui_navigation.hpp"
|
||||
#include "ui_receiver.hpp"
|
||||
#include "ui_geomap.hpp"
|
||||
#include "ui_freq_field.hpp"
|
||||
#include "ui_record_view.hpp"
|
||||
#include "app_settings.hpp"
|
||||
#include "radio_state.hpp"
|
||||
#include "log_file.hpp"
|
||||
#include "utility.hpp"
|
||||
|
||||
using namespace ui;
|
||||
|
||||
namespace ui::external_app::foxhunt_rx {
|
||||
|
||||
class FoxhuntRxView : public View {
|
||||
public:
|
||||
FoxhuntRxView(NavigationView& nav);
|
||||
~FoxhuntRxView();
|
||||
|
||||
void focus() override;
|
||||
|
||||
std::string title() const override { return "Fox hunt"; };
|
||||
|
||||
private:
|
||||
NavigationView& nav_;
|
||||
RxRadioState radio_state_{};
|
||||
app_settings::SettingsManager settings_{
|
||||
"rx_foxhunt", app_settings::Mode::RX};
|
||||
|
||||
RFAmpField field_rf_amp{
|
||||
{13 * 8, 0 * 16}};
|
||||
LNAGainField field_lna{
|
||||
{15 * 8, 0 * 16}};
|
||||
VGAGainField field_vga{
|
||||
{18 * 8, 0 * 16}};
|
||||
RSSI rssi{
|
||||
{21 * 8, 0, 6 * 8, 4}};
|
||||
AudioVolumeField field_volume{
|
||||
{28 * 8, 0 * 16}};
|
||||
|
||||
RxFrequencyField field_frequency{
|
||||
{0 * 8, 0 * 16},
|
||||
nav_};
|
||||
|
||||
// Power: -XXX db
|
||||
Text freq_stats_db{
|
||||
{0 * 8, 2 * 16 + 4, 14 * 8, 14},
|
||||
};
|
||||
RSSIGraph rssi_graph{
|
||||
{0, 50, 240, 30},
|
||||
};
|
||||
|
||||
Button clear_markers{
|
||||
{10 * 8, 18, 8 * 8, 16},
|
||||
LanguageHelper::currentMessages[LANG_CLEAR]};
|
||||
|
||||
Button add_current_marker{
|
||||
{2, 18, 7 * 8, 16},
|
||||
"Mark"};
|
||||
|
||||
GeoMap geomap{{0, 80, 240, 240}};
|
||||
|
||||
MessageHandlerRegistration message_handler_gps{
|
||||
Message::ID::GPSPosData,
|
||||
[this](Message* const p) {
|
||||
const auto message = static_cast<const GPSPosDataMessage*>(p);
|
||||
this->on_gps(message);
|
||||
}};
|
||||
MessageHandlerRegistration message_handler_orientation{
|
||||
Message::ID::OrientationData,
|
||||
[this](Message* const p) {
|
||||
const auto message = static_cast<const OrientationDataMessage*>(p);
|
||||
this->on_orientation(message);
|
||||
}};
|
||||
MessageHandlerRegistration message_handler_stats{
|
||||
Message::ID::ChannelStatistics,
|
||||
[this](const Message* const p) {
|
||||
this->on_statistics_update(static_cast<const ChannelStatisticsMessage*>(p)->statistics);
|
||||
}};
|
||||
|
||||
float my_lat = 200;
|
||||
float my_lon = 200;
|
||||
uint16_t my_orientation = 400;
|
||||
|
||||
void on_gps(const GPSPosDataMessage* msg);
|
||||
void on_orientation(const OrientationDataMessage* msg);
|
||||
void on_statistics_update(const ChannelStatistics& statistics);
|
||||
};
|
||||
|
||||
} // namespace ui::external_app::foxhunt_rx
|
||||
|
||||
#endif /*__UI_FOXHUNT_RX_H__*/
|
||||
@@ -25,9 +25,11 @@
|
||||
#include <cstdint>
|
||||
#include <cstddef>
|
||||
#include <array>
|
||||
#include <cstring>
|
||||
|
||||
#include "hal.h"
|
||||
#include "gpdma.hpp"
|
||||
#include "tone_gen.hpp"
|
||||
|
||||
using namespace lpc43xx;
|
||||
|
||||
@@ -36,6 +38,8 @@ using namespace lpc43xx;
|
||||
namespace audio {
|
||||
namespace dma {
|
||||
|
||||
ToneGen tone_gen{};
|
||||
|
||||
constexpr uint32_t gpdma_ahb_master_peripheral = 1;
|
||||
constexpr uint32_t gpdma_ahb_master_memory = 0;
|
||||
constexpr uint32_t gpdma_ahb_master_lli_fetch = 0;
|
||||
@@ -145,9 +149,14 @@ static volatile const gpdma::channel::LLI* tx_next_lli = nullptr;
|
||||
static volatile const gpdma::channel::LLI* rx_next_lli = nullptr;
|
||||
|
||||
static bool single_tx_buffer = false;
|
||||
static uint32_t beep_duration_downcounter = 0;
|
||||
|
||||
static void tx_transfer_complete() {
|
||||
tx_next_lli = gpdma_channel_i2s0_tx.next_lli();
|
||||
|
||||
if (beep_duration_downcounter != 0)
|
||||
if (--beep_duration_downcounter == 0)
|
||||
beep_stop();
|
||||
}
|
||||
|
||||
static void tx_error() {
|
||||
@@ -229,6 +238,44 @@ void shrink_tx_buffer(bool shrink) {
|
||||
lli_tx_loop[0].lli = lli_pointer(&lli_tx_loop[1]);
|
||||
}
|
||||
|
||||
void beep_start(uint32_t freq, uint32_t sample_rate, uint32_t beep_duration_ms) {
|
||||
// Prevent divide-by-0
|
||||
if (freq == 0 || sample_rate == 0)
|
||||
return;
|
||||
|
||||
// Fill entire buffer with sine waves
|
||||
tone_gen.configure_beep(freq, sample_rate);
|
||||
for (size_t i = 0; i < buffer_samples; i++)
|
||||
buffer_tx[i].left = buffer_tx[i].right = tone_gen.process_beep();
|
||||
|
||||
// Try to adjust DMA transfer count to align with full sine waves for a better tone
|
||||
float samples_per_sine_wave = float(sample_rate) / freq;
|
||||
uint32_t sine_waves_per_buffer = buffer_samples / samples_per_sine_wave;
|
||||
size_t sample_count = (sine_waves_per_buffer == 0) ? buffer_samples : sine_waves_per_buffer * samples_per_sine_wave + 0.5;
|
||||
|
||||
// Use single larger transfer buffer with sample count determined above
|
||||
lli_tx_loop[0].lli = lli_pointer(&lli_tx_loop[0]);
|
||||
lli_tx_loop[0].control = control_tx(sample_count * sizeof(sample_t));
|
||||
|
||||
// Convert duration ms to number of buffers to send before stopping
|
||||
// NB: beep_duration_ms==0 means beep continuously until stopped
|
||||
uint32_t beep_interrupt_count = beep_duration_ms * sample_rate / (1000 * sample_count);
|
||||
if ((beep_duration_ms != 0) && (beep_interrupt_count == 0))
|
||||
beep_interrupt_count = 1;
|
||||
beep_duration_downcounter = beep_interrupt_count;
|
||||
}
|
||||
|
||||
void beep_stop() {
|
||||
// Clear audio DMA buffer
|
||||
memset(&buffer_tx, 0, buffer_bytes);
|
||||
|
||||
// Restore DMA linked list to use multiple smaller buffers
|
||||
lli_tx_loop[0].control = control_tx(transfer_bytes);
|
||||
if (!single_tx_buffer && (transfers_per_buffer > 1)) {
|
||||
lli_tx_loop[0].lli = lli_pointer(&lli_tx_loop[1]);
|
||||
}
|
||||
}
|
||||
|
||||
buffer_t tx_empty_buffer() {
|
||||
const auto next_lli = tx_next_lli;
|
||||
if (next_lli) {
|
||||
|
||||
@@ -47,6 +47,8 @@ void init_audio_in();
|
||||
void init_audio_out();
|
||||
void disable();
|
||||
void shrink_tx_buffer(bool shrink);
|
||||
void beep_start(uint32_t freq, uint32_t sample_rate, uint32_t beep_duration_ms);
|
||||
void beep_stop();
|
||||
|
||||
audio::buffer_t tx_empty_buffer();
|
||||
audio::buffer_t rx_empty_buffer();
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
#include "portapack_dma.hpp"
|
||||
|
||||
#include "gpdma.hpp"
|
||||
#include "audio_dma.hpp"
|
||||
|
||||
static void init() {
|
||||
// Audio DMA initialization was moved to baseband proc's that actually use DMA audio, to save memory.
|
||||
@@ -65,6 +66,8 @@ void __late_init(void) {
|
||||
void _default_exit(void) {
|
||||
// TODO: Is this complete?
|
||||
|
||||
audio::dma::disable();
|
||||
|
||||
nvicDisableVector(DMA_IRQn);
|
||||
|
||||
chSysDisable();
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
/*
|
||||
* Copyright (C) 2015 Jared Boone, ShareBrained Technology, Inc.
|
||||
* Copyright (C) 2017 Furrtek
|
||||
* Copyright (C) 2024 Mark Thompson
|
||||
*
|
||||
* This file is part of PortaPack.
|
||||
*
|
||||
@@ -26,16 +27,12 @@
|
||||
|
||||
#include "event_m4.hpp"
|
||||
|
||||
#include "audio_output.hpp"
|
||||
#include "audio_dma.hpp"
|
||||
|
||||
SondeProcessor::SondeProcessor() {
|
||||
decim_0.configure(taps_11k0_decim_0.taps);
|
||||
decim_1.configure(taps_11k0_decim_1.taps);
|
||||
|
||||
audio_output.configure(false);
|
||||
|
||||
tone_gen.configure(BEEP_BASE_FREQ, 1.0, ToneGen::tone_type::sine, AUDIO_SAMPLE_RATE);
|
||||
baseband_thread.start();
|
||||
}
|
||||
|
||||
@@ -55,23 +52,6 @@ void SondeProcessor::execute(const buffer_c8_t& buffer) {
|
||||
clock_recovery_fsk_4800(mf.get_output());
|
||||
}
|
||||
}
|
||||
|
||||
if (pitch_rssi_enabled) {
|
||||
if (beep_play) {
|
||||
// if we let the buffer underrun, for some reason
|
||||
// once it starts looping it ignores zero (silence)
|
||||
// samples, so we need to keep feeding the buffer
|
||||
// and not be able to take advantage of the circular
|
||||
// buffer loop:
|
||||
// beep_play = false;
|
||||
generate_beep();
|
||||
}
|
||||
|
||||
if (silence_play) {
|
||||
// silence_play = false;
|
||||
generate_silence();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SondeProcessor::on_message(const Message* const msg) {
|
||||
@@ -79,7 +59,7 @@ void SondeProcessor::on_message(const Message* const msg) {
|
||||
case Message::ID::RequestSignal:
|
||||
if ((*reinterpret_cast<const RequestSignalMessage*>(msg)).signal == RequestSignalMessage::Signal::BeepRequest) {
|
||||
float rssi_ratio = (float)last_rssi / (float)RSSI_CEILING;
|
||||
int beep_duration = 0;
|
||||
uint32_t beep_duration = 0;
|
||||
|
||||
if (rssi_ratio <= PROPORTIONAL_BEEP_THRES) {
|
||||
beep_duration = BEEP_MIN_DURATION;
|
||||
@@ -89,9 +69,7 @@ void SondeProcessor::on_message(const Message* const msg) {
|
||||
beep_duration = BEEP_DURATION_RANGE + BEEP_MIN_DURATION;
|
||||
}
|
||||
|
||||
play_beep();
|
||||
chThdSleepMilliseconds(beep_duration);
|
||||
stop_beep();
|
||||
audio::dma::beep_start(beep_freq, AUDIO_SAMPLE_RATE, beep_duration);
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -104,41 +82,11 @@ void SondeProcessor::on_message(const Message* const msg) {
|
||||
}
|
||||
}
|
||||
|
||||
void SondeProcessor::play_beep() {
|
||||
beep_play = true;
|
||||
silence_play = false;
|
||||
}
|
||||
|
||||
void SondeProcessor::stop_beep() {
|
||||
beep_play = false;
|
||||
silence_play = true;
|
||||
}
|
||||
|
||||
void SondeProcessor::generate_beep() {
|
||||
// here we let the samples be created using the ToneGen class:
|
||||
|
||||
for (uint8_t i = 0; i < sizeof(audio_buffer.p); i++) {
|
||||
audio_buffer.p[i] = (int16_t)((tone_gen.process(0) >> 16) & 0x0000FFFF);
|
||||
}
|
||||
|
||||
audio_output.write(audio_buffer);
|
||||
}
|
||||
|
||||
void SondeProcessor::generate_silence() {
|
||||
for (uint8_t i = 0; i < sizeof(audio_buffer.p); i++) {
|
||||
audio_buffer.p[i] = 0;
|
||||
}
|
||||
|
||||
audio_output.write(audio_buffer);
|
||||
}
|
||||
|
||||
void SondeProcessor::pitch_rssi_config(const PitchRSSIConfigureMessage& message) {
|
||||
pitch_rssi_enabled = message.enabled;
|
||||
|
||||
uint32_t freq = (int)((float)message.rssi * (float)RSSI_PITCH_WEIGHT + (float)BEEP_BASE_FREQ);
|
||||
|
||||
beep_freq = (int)((float)message.rssi * (float)RSSI_PITCH_WEIGHT + (float)BEEP_BASE_FREQ);
|
||||
last_rssi = message.rssi;
|
||||
tone_gen.configure(freq, 1.0, ToneGen::tone_type::sine, AUDIO_SAMPLE_RATE);
|
||||
}
|
||||
|
||||
int main() {
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
* Copyright (C) 2015 Jared Boone, ShareBrained Technology, Inc.
|
||||
* Copyright (C) 2017 Furrtek
|
||||
* Copyright (C) 2014 zilog80
|
||||
* Copyright (C) 2024 Mark Thompson
|
||||
*
|
||||
* This file is part of PortaPack.
|
||||
*
|
||||
@@ -88,9 +89,6 @@
|
||||
#include "message.hpp"
|
||||
#include "portapack_shared_memory.hpp"
|
||||
|
||||
#include "audio_output.hpp"
|
||||
#include "tone_gen.hpp"
|
||||
|
||||
#include "buffer.hpp"
|
||||
|
||||
#include <cstdint>
|
||||
@@ -115,21 +113,10 @@ class SondeProcessor : public BasebandProcessor {
|
||||
private:
|
||||
static constexpr size_t baseband_fs = 2457600;
|
||||
|
||||
std::array<int16_t, 32> audio{};
|
||||
|
||||
const buffer_s16_t audio_buffer{
|
||||
(int16_t*)audio.data(),
|
||||
sizeof(audio) / sizeof(int16_t)};
|
||||
|
||||
AudioOutput audio_output{};
|
||||
|
||||
bool beep_play{false};
|
||||
bool silence_play{false};
|
||||
bool pitch_rssi_enabled{false};
|
||||
|
||||
uint32_t last_rssi{0};
|
||||
|
||||
ToneGen tone_gen{};
|
||||
uint32_t beep_freq{0};
|
||||
|
||||
std::array<complex16_t, 512> dst{};
|
||||
const buffer_c16_t dst_buffer{
|
||||
@@ -181,21 +168,6 @@ class SondeProcessor : public BasebandProcessor {
|
||||
baseband_fs, this, baseband::Direction::Receive, /*auto_start*/ false};
|
||||
RSSIThread rssi_thread{};
|
||||
|
||||
void play_beep();
|
||||
void stop_beep();
|
||||
|
||||
/**
|
||||
* Used for filling the audio buffer with the waveform
|
||||
* generated by the ToneGen class:
|
||||
*
|
||||
*/
|
||||
void generate_beep();
|
||||
|
||||
/**
|
||||
* Used for filling the audio buffer with silence:
|
||||
*/
|
||||
void generate_silence();
|
||||
|
||||
void pitch_rssi_config(const PitchRSSIConfigureMessage& message);
|
||||
};
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
/*
|
||||
* Copyright (C) 2015 Jared Boone, ShareBrained Technology, Inc.
|
||||
* Copyright (C) 2017 Furrtek
|
||||
* Copyright (C) 2024 Mark Thompson
|
||||
*
|
||||
* This file is part of PortaPack.
|
||||
*
|
||||
@@ -23,53 +24,19 @@
|
||||
#include "tone_gen.hpp"
|
||||
#include "sine_table_int8.hpp"
|
||||
|
||||
/*
|
||||
int32_t ToneGen::tone_sine() {
|
||||
// TODO : Added for Sonde App. We keep it by now , but it needs to be reviewed in Sonde
|
||||
// Hoepfully we can manage without it , same as previous fw 1.3.1
|
||||
int32_t tone_sample = sine_table_i8[tone_phase_] * 0x1000000;
|
||||
tone_phase_ += delta_;
|
||||
|
||||
return tone_sample;
|
||||
// Functions for audio beep (used by Sonde RSSI)
|
||||
void ToneGen::configure_beep(const uint32_t freq, const uint32_t sample_rate) {
|
||||
f_delta_ = (float)(freq * sizeof(sine_table_i8)) / sample_rate;
|
||||
f_tone_phase_ = 0.0;
|
||||
}
|
||||
*/
|
||||
|
||||
int32_t ToneGen::tone_square() {
|
||||
// TODO : Added for Sonde App. We keep it by now , but it needs to be reviewed in Sonde
|
||||
int32_t tone_sample = 0;
|
||||
|
||||
if (tone_phase_ < (UINT32_MAX / 2)) {
|
||||
tone_sample = INT32_MAX;
|
||||
} else {
|
||||
tone_sample = INT32_MIN;
|
||||
}
|
||||
|
||||
tone_phase_ += delta_;
|
||||
int16_t ToneGen::process_beep() {
|
||||
int16_t tone_sample = sine_table_i8[(uint32_t)f_tone_phase_ & 0xFF] * 256;
|
||||
f_tone_phase_ += f_delta_;
|
||||
|
||||
return tone_sample;
|
||||
}
|
||||
|
||||
/*
|
||||
void ToneGen::configure(const uint32_t delta, const float tone_mix_weight) {
|
||||
// Confirmed ! It is not working well in the fw 1.4.4 Mic App , CTCSS generation, (but added for Sonde App)
|
||||
// I Think it should be deleted or modified but not use it as it is in Mic App .
|
||||
|
||||
delta_ = (uint8_t) ((delta & 0xFF000000U) >> 24);
|
||||
delta_ = delta;
|
||||
tone_mix_weight_ = tone_mix_weight;
|
||||
input_mix_weight_ = 1.0 - tone_mix_weight;
|
||||
current_tone_type_ = sine;
|
||||
}
|
||||
*/
|
||||
|
||||
void ToneGen::configure(const uint32_t freq, const float tone_mix_weight, const tone_type tone_type, const uint32_t sample_rate) {
|
||||
// TODO : Added for Sonde App. We keep it by now to avoid compile errors, but it needs to be reviewed in Sonde
|
||||
delta_ = (uint8_t)((freq * sizeof(sine_table_i8)) / sample_rate);
|
||||
tone_mix_weight_ = tone_mix_weight;
|
||||
input_mix_weight_ = 1.0 - tone_mix_weight;
|
||||
current_tone_type_ = tone_type;
|
||||
}
|
||||
|
||||
// ----Original available core SW code from fw 1.3.1 , Working also well in Mic App CTCSS Gen from fw 1.4.0 onwards
|
||||
|
||||
// Original direct-look-up synthesis algorithm with Fractional delta phase. It is OK
|
||||
@@ -78,6 +45,7 @@ void ToneGen::configure(const uint32_t freq, const float tone_mix_weight, const
|
||||
|
||||
void ToneGen::configure(const uint32_t delta, const float tone_mix_weight) {
|
||||
delta_ = delta;
|
||||
tone_phase_ = 0;
|
||||
tone_mix_weight_ = tone_mix_weight;
|
||||
input_mix_weight_ = 1.0 - tone_mix_weight;
|
||||
}
|
||||
@@ -90,17 +58,4 @@ int32_t ToneGen::process(const int32_t sample_in) {
|
||||
tone_phase_ += delta_;
|
||||
|
||||
return (sample_in * input_mix_weight_) + (tone_sample * tone_mix_weight_);
|
||||
}
|
||||
// -------------------------------------------------------------
|
||||
|
||||
int32_t ToneGen::process_square(const int32_t sample_in) {
|
||||
// TODO : Added for Sonde App. We keep it by now , but it needs to be reviewed in Sonde
|
||||
if (!delta_)
|
||||
return sample_in;
|
||||
|
||||
int32_t tone_sample = 0;
|
||||
|
||||
tone_sample = tone_square();
|
||||
|
||||
return (sample_in * input_mix_weight_) + (tone_sample * tone_mix_weight_);
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
/*
|
||||
* Copyright (C) 2015 Jared Boone, ShareBrained Technology, Inc.
|
||||
* Copyright (C) 2017 Furrtek
|
||||
* Copyright (C) 2024 Mark Thompson
|
||||
*
|
||||
* This file is part of PortaPack.
|
||||
*
|
||||
@@ -28,40 +29,21 @@
|
||||
|
||||
class ToneGen {
|
||||
public:
|
||||
enum tone_type { sine,
|
||||
square }; // TODO: Added for Radio Sonde.cpp PR 376, 381 , we need to check if keep or not.
|
||||
|
||||
/*ToneGen(const size_t sample_rate
|
||||
) : sample_rate_ { sample_rate }
|
||||
{};*/
|
||||
|
||||
void configure(const uint32_t delta, const float tone_mix_weight);
|
||||
void configure(const uint32_t freq, const float tone_mix_weight, const tone_type tone_type, const uint32_t sample_rate);
|
||||
|
||||
int32_t process(const int32_t sample_in);
|
||||
int32_t process_square(const int32_t sample_in);
|
||||
|
||||
void configure_beep(const uint32_t freq, const uint32_t sample_rate);
|
||||
int16_t process_beep();
|
||||
|
||||
private:
|
||||
tone_type current_tone_type_{sine};
|
||||
|
||||
float input_mix_weight_{1};
|
||||
float tone_mix_weight_{0};
|
||||
|
||||
float f_delta_{0.0};
|
||||
float f_tone_phase_{0.0};
|
||||
|
||||
uint32_t delta_{0};
|
||||
uint32_t tone_phase_{0};
|
||||
|
||||
// uint8_t delta_ { 0 }; // TODO: Added for Radio Sonde.cpp PR 376, 381 , we need to check if keep or not.
|
||||
// uint8_t tone_phase_ { 0 }; // TODO: Added for Radio Sonde.cpp PR 376, 381 , we need to check if keep or not.
|
||||
|
||||
/**
|
||||
* Generator function which selects every other sample from the reference sine waveform to the output sample:
|
||||
*/
|
||||
int32_t tone_sine(); // TODO: Added for Radio Sonde.cpp PR 376, 381 , we need to check if keep or not.
|
||||
|
||||
/**
|
||||
* Generator function for square waves:
|
||||
*/
|
||||
int32_t tone_square(); // TODO: Added for Radio Sonde.cpp PR 376, 381 , we need to check if keep or not.
|
||||
};
|
||||
|
||||
#endif /* __TONE_GEN_H__ */
|
||||
|
||||
Reference in New Issue
Block a user