diff --git a/firmware/application/apps/ui_sonde.cpp b/firmware/application/apps/ui_sonde.cpp index 278037dd..419ad579 100644 --- a/firmware/application/apps/ui_sonde.cpp +++ b/firmware/application/apps/ui_sonde.cpp @@ -66,6 +66,9 @@ SondeView::SondeView(NavigationView& nav) { &button_see_map }); + // start from the frequency currently stored in the receiver_model: + target_frequency_ = receiver_model.tuning_frequency(); + field_frequency.set_value(target_frequency_); field_frequency.set_step(500); //euquiq: was 10000, but we are using this for fine-tunning field_frequency.on_change = [this](rf::Frequency f) { @@ -130,6 +133,13 @@ SondeView::SondeView(NavigationView& nav) { audio::output::start(); audio::output::speaker_unmute(); + // inject a PitchRSSIConfigureMessage in order to arm + // the pitch rssi events that will be used by the + // processor: + const PitchRSSIConfigureMessage message { true, 0 }; + + shared_memory.application_queue.push(message); + baseband::set_pitch_rssi(0, true); } @@ -199,7 +209,9 @@ void SondeView::on_headphone_volume_changed(int32_t v) { void SondeView::set_target_frequency(const uint32_t new_value) { target_frequency_ = new_value; - radio::set_tuning_frequency(tuning_frequency()); + //radio::set_tuning_frequency(tuning_frequency()); + // we better remember the tuned frequency, by using this function instead: + receiver_model.set_tuning_frequency(tuning_frequency()); } uint32_t SondeView::tuning_frequency() const { diff --git a/firmware/application/apps/ui_sonde.hpp b/firmware/application/apps/ui_sonde.hpp index 73591eb3..afc2bbec 100644 --- a/firmware/application/apps/ui_sonde.hpp +++ b/firmware/application/apps/ui_sonde.hpp @@ -55,14 +55,6 @@ class SondeView : public View { public: static constexpr uint32_t sampling_rate = 2457600; 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(); diff --git a/firmware/application/ui/ui_rssi.cpp b/firmware/application/ui/ui_rssi.cpp index 98cfed63..84487b16 100644 --- a/firmware/application/ui/ui_rssi.cpp +++ b/firmware/application/ui/ui_rssi.cpp @@ -75,8 +75,9 @@ void RSSI::paint(Painter& painter) { Color::black() ); - if (pitch_rssi_enabled) + if (pitch_rssi_enabled) { baseband::set_pitch_rssi((avg_ - raw_min) * 2000 / raw_delta, true); + } } void RSSI::set_pitch_rssi(bool enabled) { diff --git a/firmware/baseband/proc_sonde.cpp b/firmware/baseband/proc_sonde.cpp index a593bec9..d956372f 100644 --- a/firmware/baseband/proc_sonde.cpp +++ b/firmware/baseband/proc_sonde.cpp @@ -34,6 +34,8 @@ SondeProcessor::SondeProcessor() { decim_1.configure(taps_11k0_decim_1.taps, 131072); audio_output.configure(false); + + tone_gen.configure(0, 1, ToneGen::tone_type::square); } void SondeProcessor::execute(const buffer_c8_t& buffer) { @@ -54,11 +56,19 @@ void SondeProcessor::execute(const buffer_c8_t& buffer) { } if(pitch_rssi_enabled) { - if(beep_playing) { - beep_loop(); + 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(); } - else { - silence_loop(); + + if(silence_play) { + //silence_play = false; + generate_silence(); } } } @@ -67,8 +77,21 @@ void SondeProcessor::on_message(const Message* const msg) { switch(msg->id) { case Message::ID::RequestSignal: if ((*reinterpret_cast(msg)).signal == RequestSignalMessage::Signal::BeepRequest) { + float rssi_ratio = (float) last_rssi / (float) RSSI_CEILING; + int beep_duration = 0; + + if(rssi_ratio <= PROPORTIONAL_BEEP_THRES) { + beep_duration = BEEP_MIN_DURATION; + } + else if(rssi_ratio < 1) { + beep_duration = (int) rssi_ratio * BEEP_DURATION_RANGE + BEEP_MIN_DURATION; + } + else { + beep_duration = BEEP_DURATION_RANGE + BEEP_MIN_DURATION; + } + play_beep(); - chThdSleepMilliseconds(100); + chThdSleepMilliseconds(beep_duration); stop_beep(); } break; @@ -83,24 +106,27 @@ void SondeProcessor::on_message(const Message* const msg) { } void SondeProcessor::play_beep() { - beep_playing = true; + beep_play = true; + silence_play = false; } void SondeProcessor::stop_beep() { - beep_playing = false; + beep_play = false; + silence_play = true; } -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; +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::silence_loop() { - for (size_t i = 0; i < sizeof(audio_buffer.p); i++) { +void SondeProcessor::generate_silence() { + for(uint8_t i = 0; i < sizeof(audio_buffer.p); i++) { audio_buffer.p[i] = 0; } @@ -108,15 +134,10 @@ void SondeProcessor::silence_loop() { } 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); + uint32_t tone_delta = (int) ((float) message.rssi * (float) RSSI_PITCH_WEIGHT + (float) 1000) * ((float) (1ULL << 32) / (float) 24000); + last_rssi = message.rssi; + tone_gen.configure(tone_delta, 1.0, ToneGen::tone_type::square); } int main() { diff --git a/firmware/baseband/proc_sonde.hpp b/firmware/baseband/proc_sonde.hpp index a7b4574f..fcf4d20b 100644 --- a/firmware/baseband/proc_sonde.hpp +++ b/firmware/baseband/proc_sonde.hpp @@ -90,8 +90,6 @@ #include "audio_output.hpp" #include "tone_gen.hpp" -#include "tonesets.hpp" -#include "sine_table_int8.hpp" #include "buffer.hpp" @@ -99,6 +97,13 @@ #include #include + +#define BEEP_MIN_DURATION 80 +#define BEEP_DURATION_RANGE 150 +#define RSSI_CEILING 1000 +#define PROPORTIONAL_BEEP_THRES 0.8 +#define RSSI_PITCH_WEIGHT 0.7 + class SondeProcessor : public BasebandProcessor { public: SondeProcessor(); @@ -108,9 +113,8 @@ public: private: static constexpr size_t baseband_fs = 2457600; - static constexpr size_t beep_iterations = 60; - std::array audio { }; + std::array audio { }; const buffer_s16_t audio_buffer { (int16_t*) audio.data(), @@ -119,11 +123,13 @@ private: AudioOutput audio_output { }; - bool beep_playing { false }; + bool beep_play { false }; + bool silence_play { false }; bool pitch_rssi_enabled { false }; - uint32_t tone_delta { 0 }; - uint32_t tone_phase { 0 }; + uint32_t last_rssi { 0 }; + + ToneGen tone_gen { }; BasebandThread baseband_thread { baseband_fs, this, NORMALPRIO + 20, baseband::Direction::Receive }; RSSIThread rssi_thread { NORMALPRIO + 10 }; @@ -177,8 +183,17 @@ private: void play_beep(); void stop_beep(); - void beep_loop(); - void silence_loop(); + /** + * 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); }; diff --git a/firmware/baseband/tone_gen.cpp b/firmware/baseband/tone_gen.cpp index bbe5587e..d2185f53 100644 --- a/firmware/baseband/tone_gen.cpp +++ b/firmware/baseband/tone_gen.cpp @@ -23,18 +23,55 @@ #include "tone_gen.hpp" #include "sine_table_int8.hpp" + +int32_t ToneGen::tone_from_sine_table() { + int32_t tone_sample = sine_table_i8[(tone_phase_ & 0xFF000000U) >> 24] << 24; + tone_phase_ += delta_; + + return tone_sample; +} + +int32_t ToneGen::tone_square() { + int32_t tone_sample = 0; + + if(tone_phase_ < (UINT32_MAX / 2)) { + tone_sample = INT32_MAX; + } + else { + tone_sample = INT32_MIN; + } + + tone_phase_ += delta_; + + return tone_sample; +} + void ToneGen::configure(const uint32_t delta, const float tone_mix_weight) { 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 delta, const float tone_mix_weight, const tone_type tone_type) { + delta_ = delta; + tone_mix_weight_ = tone_mix_weight; + input_mix_weight_ = 1.0 - tone_mix_weight; + current_tone_type_ = tone_type; } int32_t ToneGen::process(const int32_t sample_in) { if (!delta_) return sample_in; - int32_t tone_sample = sine_table_i8[(tone_phase_ & 0xFF000000U) >> 24]; - tone_phase_ += delta_; + int32_t tone_sample = 0; + + if(current_tone_type_ == sine) { + tone_sample = tone_from_sine_table(); + } + else if(current_tone_type_ == square) { + tone_sample = tone_square(); + } return (sample_in * input_mix_weight_) + (tone_sample * tone_mix_weight_); } diff --git a/firmware/baseband/tone_gen.hpp b/firmware/baseband/tone_gen.hpp index ef547f26..d12782c1 100644 --- a/firmware/baseband/tone_gen.hpp +++ b/firmware/baseband/tone_gen.hpp @@ -25,22 +25,41 @@ #include #include +#include + +static const std::bitset<2048> wave_bits (0xFFFFFF); class ToneGen { public: + enum tone_type { sine, square }; + /*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 delta, const float tone_mix_weight, const tone_type tone_type); + int32_t process(const int32_t sample_in); private: + tone_type current_tone_type_ { sine }; + //size_t sample_rate_; float input_mix_weight_ { 1 }; float tone_mix_weight_ { 0 }; uint32_t delta_ { 0 }; uint32_t tone_phase_ { 0 }; + + /** + * Generator function for sine waves: + */ + int32_t tone_from_sine_table(); + + /** + * Generator function for square waves: + */ + int32_t tone_square(); }; -#endif +#endif /* __TONE_GEN_H__ */ diff --git a/firmware/common/sine_table_int8.hpp b/firmware/common/sine_table_int8.hpp index 828b6db5..0583fa67 100644 --- a/firmware/common/sine_table_int8.hpp +++ b/firmware/common/sine_table_int8.hpp @@ -44,4 +44,5 @@ static const int8_t sine_table_i8[256] = { -49, -46, -43, -40, -37, -34, -31, -28, -25, -22, -19, -16, -13, -9, -6, -3 }; + #endif/*__SINE_TABLE_I8_H__*/