mirror of
https://github.com/eried/portapack-mayhem.git
synced 2024-12-24 06:49:24 -05:00
Added beep on radiosonde packet decoding, and volume widget to control its level.
This commit is contained in:
parent
182059b3c6
commit
9040e780bc
@ -22,6 +22,7 @@
|
|||||||
|
|
||||||
#include "ui_sonde.hpp"
|
#include "ui_sonde.hpp"
|
||||||
#include "baseband_api.hpp"
|
#include "baseband_api.hpp"
|
||||||
|
#include "audio.hpp"
|
||||||
|
|
||||||
#include "portapack.hpp"
|
#include "portapack.hpp"
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
@ -50,6 +51,8 @@ SondeView::SondeView(NavigationView& nav) {
|
|||||||
&field_lna,
|
&field_lna,
|
||||||
&field_vga,
|
&field_vga,
|
||||||
&rssi,
|
&rssi,
|
||||||
|
&field_volume,
|
||||||
|
&check_beep,
|
||||||
&check_log,
|
&check_log,
|
||||||
&check_crc,
|
&check_crc,
|
||||||
&text_signature,
|
&text_signature,
|
||||||
@ -80,6 +83,10 @@ SondeView::SondeView(NavigationView& nav) {
|
|||||||
|
|
||||||
geopos.set_read_only(true);
|
geopos.set_read_only(true);
|
||||||
|
|
||||||
|
check_beep.on_select = [this](Checkbox&, bool v) {
|
||||||
|
beep = v;
|
||||||
|
};
|
||||||
|
|
||||||
check_log.on_select = [this](Checkbox&, bool v) {
|
check_log.on_select = [this](Checkbox&, bool v) {
|
||||||
logging = v;
|
logging = v;
|
||||||
};
|
};
|
||||||
@ -107,16 +114,30 @@ SondeView::SondeView(NavigationView& nav) {
|
|||||||
gps_info.lon,
|
gps_info.lon,
|
||||||
999); //set a dummy heading out of range to draw a cross...probably not ideal?
|
999); //set a dummy heading out of range to draw a cross...probably not ideal?
|
||||||
};
|
};
|
||||||
|
|
||||||
logger = std::make_unique<SondeLogger>();
|
logger = std::make_unique<SondeLogger>();
|
||||||
if (logger)
|
if (logger)
|
||||||
logger->append(u"sonde.txt");
|
logger->append(u"sonde.txt");
|
||||||
|
|
||||||
|
// initialize audio:
|
||||||
|
|
||||||
|
field_volume.set_value((receiver_model.headphone_volume() - audio::headphone::volume_range().max).decibel() + 99);
|
||||||
|
|
||||||
|
field_volume.on_change = [this](int32_t v) {
|
||||||
|
this->on_headphone_volume_changed(v);
|
||||||
|
};
|
||||||
|
|
||||||
|
audio::output::start();
|
||||||
|
audio::output::speaker_unmute();
|
||||||
|
|
||||||
|
baseband::set_pitch_rssi(0, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
SondeView::~SondeView() {
|
SondeView::~SondeView() {
|
||||||
|
baseband::set_pitch_rssi(0, false);
|
||||||
radio::disable();
|
radio::disable();
|
||||||
baseband::shutdown();
|
baseband::shutdown();
|
||||||
|
audio::output::stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
void SondeView::focus() {
|
void SondeView::focus() {
|
||||||
@ -156,15 +177,26 @@ void SondeView::on_packet(const sonde::Packet &packet)
|
|||||||
}
|
}
|
||||||
|
|
||||||
gps_info = packet.get_GPS_data();
|
gps_info = packet.get_GPS_data();
|
||||||
|
|
||||||
geopos.set_altitude(gps_info.alt);
|
geopos.set_altitude(gps_info.alt);
|
||||||
geopos.set_lat(gps_info.lat);
|
geopos.set_lat(gps_info.lat);
|
||||||
geopos.set_lon(gps_info.lon);
|
geopos.set_lon(gps_info.lon);
|
||||||
|
|
||||||
if (logger && logging)
|
if (logger && logging) {
|
||||||
logger->on_packet(packet);
|
logger->on_packet(packet);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(beep) {
|
||||||
|
baseband::request_beep();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SondeView::on_headphone_volume_changed(int32_t v) {
|
||||||
|
const auto new_volume = volume_t::decibel(v - 99) + audio::headphone::volume_range().max;
|
||||||
|
receiver_model.set_headphone_volume(new_volume);
|
||||||
|
}
|
||||||
|
|
||||||
void SondeView::set_target_frequency(const uint32_t new_value) {
|
void SondeView::set_target_frequency(const uint32_t new_value) {
|
||||||
target_frequency_ = new_value;
|
target_frequency_ = new_value;
|
||||||
radio::set_tuning_frequency(tuning_frequency());
|
radio::set_tuning_frequency(tuning_frequency());
|
||||||
|
@ -55,7 +55,15 @@ class SondeView : public View {
|
|||||||
public:
|
public:
|
||||||
static constexpr uint32_t sampling_rate = 2457600;
|
static constexpr uint32_t sampling_rate = 2457600;
|
||||||
static constexpr uint32_t baseband_bandwidth = 1750000;
|
static constexpr uint32_t baseband_bandwidth = 1750000;
|
||||||
|
static constexpr int rssi_sample_range = 256;
|
||||||
|
static constexpr float rssi_voltage_min = 0.4;
|
||||||
|
static constexpr float rssi_voltage_max = 2.2;
|
||||||
|
static constexpr float adc_voltage_max = 3.3;
|
||||||
|
|
||||||
|
static constexpr int raw_min = rssi_sample_range * rssi_voltage_min / adc_voltage_max;
|
||||||
|
static constexpr int raw_max = rssi_sample_range * rssi_voltage_max / adc_voltage_max;
|
||||||
|
static constexpr int raw_delta = raw_max - raw_min;
|
||||||
|
|
||||||
SondeView(NavigationView& nav);
|
SondeView(NavigationView& nav);
|
||||||
~SondeView();
|
~SondeView();
|
||||||
|
|
||||||
@ -68,10 +76,14 @@ private:
|
|||||||
uint32_t target_frequency_ { 402700000 };
|
uint32_t target_frequency_ { 402700000 };
|
||||||
bool logging { false };
|
bool logging { false };
|
||||||
bool use_crc { false };
|
bool use_crc { false };
|
||||||
|
bool beep { false };
|
||||||
|
|
||||||
sonde::GPS_data gps_info { };
|
sonde::GPS_data gps_info { };
|
||||||
sonde::temp_humid temp_humid_info { };
|
sonde::temp_humid temp_humid_info { };
|
||||||
std::string sonde_id { };
|
std::string sonde_id { };
|
||||||
|
|
||||||
|
// AudioOutput audio_output { };
|
||||||
|
|
||||||
Labels labels {
|
Labels labels {
|
||||||
{ { 4 * 8, 2 * 16 }, "Type:", Color::light_grey() },
|
{ { 4 * 8, 2 * 16 }, "Type:", Color::light_grey() },
|
||||||
{ { 6 * 8, 3 * 16 }, "ID:", Color::light_grey() },
|
{ { 6 * 8, 3 * 16 }, "ID:", Color::light_grey() },
|
||||||
@ -103,14 +115,29 @@ private:
|
|||||||
{ 21 * 8, 0, 6 * 8, 4 },
|
{ 21 * 8, 0, 6 * 8, 4 },
|
||||||
};
|
};
|
||||||
|
|
||||||
|
NumberField field_volume {
|
||||||
|
{ 28 * 8, 0 * 16 },
|
||||||
|
2,
|
||||||
|
{ 0, 99 },
|
||||||
|
1,
|
||||||
|
' ',
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
Checkbox check_beep {
|
||||||
|
{ 22 * 8, 6 * 16 },
|
||||||
|
3,
|
||||||
|
"Beep"
|
||||||
|
};
|
||||||
|
|
||||||
Checkbox check_log {
|
Checkbox check_log {
|
||||||
{ 23 * 8, 6 * 16 },
|
{ 22 * 8, 8 * 16 },
|
||||||
3,
|
3,
|
||||||
"Log"
|
"Log"
|
||||||
};
|
};
|
||||||
|
|
||||||
Checkbox check_crc {
|
Checkbox check_crc {
|
||||||
{ 23 * 8, 8 * 16 },
|
{ 22 * 8, 10 * 16 },
|
||||||
3,
|
3,
|
||||||
"CRC"
|
"CRC"
|
||||||
};
|
};
|
||||||
@ -170,7 +197,10 @@ private:
|
|||||||
};
|
};
|
||||||
|
|
||||||
void on_packet(const sonde::Packet& packet);
|
void on_packet(const sonde::Packet& packet);
|
||||||
|
void on_headphone_volume_changed(int32_t v);
|
||||||
|
|
||||||
void set_target_frequency(const uint32_t new_value);
|
void set_target_frequency(const uint32_t new_value);
|
||||||
|
|
||||||
uint32_t tuning_frequency() const;
|
uint32_t tuning_frequency() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -26,9 +26,14 @@
|
|||||||
|
|
||||||
#include "event_m4.hpp"
|
#include "event_m4.hpp"
|
||||||
|
|
||||||
|
#include "audio_output.hpp"
|
||||||
|
|
||||||
SondeProcessor::SondeProcessor() {
|
SondeProcessor::SondeProcessor() {
|
||||||
|
|
||||||
decim_0.configure(taps_11k0_decim_0.taps, 33554432);
|
decim_0.configure(taps_11k0_decim_0.taps, 33554432);
|
||||||
decim_1.configure(taps_11k0_decim_1.taps, 131072);
|
decim_1.configure(taps_11k0_decim_1.taps, 131072);
|
||||||
|
|
||||||
|
audio_output.configure(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SondeProcessor::execute(const buffer_c8_t& buffer) {
|
void SondeProcessor::execute(const buffer_c8_t& buffer) {
|
||||||
@ -47,10 +52,76 @@ void SondeProcessor::execute(const buffer_c8_t& buffer) {
|
|||||||
clock_recovery_fsk_4800(mf.get_output());
|
clock_recovery_fsk_4800(mf.get_output());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(pitch_rssi_enabled) {
|
||||||
|
if(beep_playing) {
|
||||||
|
beep_loop();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
silence_loop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SondeProcessor::on_message(const Message* const msg) {
|
||||||
|
switch(msg->id) {
|
||||||
|
case Message::ID::RequestSignal:
|
||||||
|
if ((*reinterpret_cast<const RequestSignalMessage*>(msg)).signal == RequestSignalMessage::Signal::BeepRequest) {
|
||||||
|
play_beep();
|
||||||
|
chThdSleepMilliseconds(100);
|
||||||
|
stop_beep();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Message::ID::PitchRSSIConfigure:
|
||||||
|
pitch_rssi_config(*reinterpret_cast<const PitchRSSIConfigureMessage*>(msg));
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SondeProcessor::play_beep() {
|
||||||
|
beep_playing = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SondeProcessor::stop_beep() {
|
||||||
|
beep_playing = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SondeProcessor::beep_loop() {
|
||||||
|
for (size_t i = 0; i < sizeof(audio_buffer.p); i++) {
|
||||||
|
audio_buffer.p[i] = (sine_table_i8[(tone_phase & 0xFF000000U) >> 24]) * 128;
|
||||||
|
tone_phase += tone_delta;
|
||||||
|
}
|
||||||
|
|
||||||
|
audio_output.write(audio_buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SondeProcessor::silence_loop() {
|
||||||
|
for (size_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) {
|
||||||
|
// rtc::RTC datetime;
|
||||||
|
// rtcGetTime(&RTCD1, &datetime);
|
||||||
|
|
||||||
|
// log_file.write_entry(datetime, "pitch_rssi_config: message.rssi: " + message.rssi);
|
||||||
|
|
||||||
|
pitch_rssi_enabled = message.enabled;
|
||||||
|
tone_delta = (message.rssi * 10 + 1000) * ((1ULL << 32) / 24000);
|
||||||
|
|
||||||
|
// log_file.write_entry(datetime, "pitch_rssi_config: tone_delta: " + tone_delta);
|
||||||
}
|
}
|
||||||
|
|
||||||
int main() {
|
int main() {
|
||||||
EventDispatcher event_dispatcher { std::make_unique<SondeProcessor>() };
|
EventDispatcher event_dispatcher { std::make_unique<SondeProcessor>() };
|
||||||
event_dispatcher.run();
|
event_dispatcher.run();
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -88,6 +88,13 @@
|
|||||||
#include "message.hpp"
|
#include "message.hpp"
|
||||||
#include "portapack_shared_memory.hpp"
|
#include "portapack_shared_memory.hpp"
|
||||||
|
|
||||||
|
#include "audio_output.hpp"
|
||||||
|
#include "tone_gen.hpp"
|
||||||
|
#include "tonesets.hpp"
|
||||||
|
#include "sine_table_int8.hpp"
|
||||||
|
|
||||||
|
#include "buffer.hpp"
|
||||||
|
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
#include <bitset>
|
#include <bitset>
|
||||||
@ -97,10 +104,27 @@ public:
|
|||||||
SondeProcessor();
|
SondeProcessor();
|
||||||
|
|
||||||
void execute(const buffer_c8_t& buffer) override;
|
void execute(const buffer_c8_t& buffer) override;
|
||||||
|
void on_message(const Message* const msg);
|
||||||
private:
|
private:
|
||||||
|
|
||||||
static constexpr size_t baseband_fs = 2457600;
|
static constexpr size_t baseband_fs = 2457600;
|
||||||
|
static constexpr size_t beep_iterations = 60;
|
||||||
|
|
||||||
|
std::array<int16_t, 16> audio { };
|
||||||
|
|
||||||
|
const buffer_s16_t audio_buffer {
|
||||||
|
(int16_t*) audio.data(),
|
||||||
|
sizeof(audio) / sizeof(int16_t)
|
||||||
|
};
|
||||||
|
|
||||||
|
AudioOutput audio_output { };
|
||||||
|
|
||||||
|
bool beep_playing { false };
|
||||||
|
bool pitch_rssi_enabled { false };
|
||||||
|
|
||||||
|
uint32_t tone_delta { 0 };
|
||||||
|
uint32_t tone_phase { 0 };
|
||||||
|
|
||||||
BasebandThread baseband_thread { baseband_fs, this, NORMALPRIO + 20, baseband::Direction::Receive };
|
BasebandThread baseband_thread { baseband_fs, this, NORMALPRIO + 20, baseband::Direction::Receive };
|
||||||
RSSIThread rssi_thread { NORMALPRIO + 10 };
|
RSSIThread rssi_thread { NORMALPRIO + 10 };
|
||||||
|
|
||||||
@ -149,6 +173,14 @@ private:
|
|||||||
shared_memory.application_queue.push(message);
|
shared_memory.application_queue.push(message);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
void play_beep();
|
||||||
|
void stop_beep();
|
||||||
|
|
||||||
|
void beep_loop();
|
||||||
|
void silence_loop();
|
||||||
|
|
||||||
|
void pitch_rssi_config(const PitchRSSIConfigureMessage& message);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif/*__PROC_ERT_H__*/
|
#endif/*__PROC_ERT_H__*/
|
||||||
|
Loading…
Reference in New Issue
Block a user