diff --git a/firmware/application/baseband_api.cpp b/firmware/application/baseband_api.cpp index a117285eb..0028fac00 100644 --- a/firmware/application/baseband_api.cpp +++ b/firmware/application/baseband_api.cpp @@ -99,10 +99,12 @@ void set_afsk_data(const uint32_t afsk_samples_per_bit, const uint32_t afsk_phas send_message(&message); } -void set_audiotx_data(const uint32_t divider, const uint32_t bw) { +void set_audiotx_data(const uint32_t divider, const uint32_t bw, const bool ctcss_enabled, const uint32_t ctcss_phase_inc) { const AudioTXConfigMessage message { divider, - bw + bw, + ctcss_phase_inc, + ctcss_enabled }; send_message(&message); } diff --git a/firmware/application/baseband_api.hpp b/firmware/application/baseband_api.hpp index d1c185020..7a7620b93 100644 --- a/firmware/application/baseband_api.hpp +++ b/firmware/application/baseband_api.hpp @@ -53,7 +53,7 @@ struct WFMConfig { }; void set_ccir_data( const uint32_t samples_per_tone, const uint16_t tone_count); -void set_audiotx_data(const uint32_t divider, const uint32_t bw); +void set_audiotx_data(const uint32_t divider, const uint32_t bw, const bool ctcss_enabled, const uint32_t ctcss_phase_inc); void set_fifo_data(const int8_t * data); void set_pwmrssi(int32_t avg, bool enabled); void set_afsk_data(const uint32_t afsk_samples_per_bit, const uint32_t afsk_phase_inc_mark, const uint32_t afsk_phase_inc_space, diff --git a/firmware/application/ui_about.cpp b/firmware/application/ui_about.cpp index 2be3ce2ce..dfb6e2726 100644 --- a/firmware/application/ui_about.cpp +++ b/firmware/application/ui_about.cpp @@ -59,7 +59,7 @@ void AboutView::on_show() { transmitter_model.set_baseband_bandwidth(1750000); transmitter_model.enable(); - baseband::set_audiotx_data(32, 15); + baseband::set_audiotx_data(32, 15, false, 0); //audio::headphone::set_volume(volume_t::decibel(0 - 99) + audio::headphone::volume_range().max); } diff --git a/firmware/application/ui_soundboard.cpp b/firmware/application/ui_soundboard.cpp index e78e87a15..72931fc0a 100644 --- a/firmware/application/ui_soundboard.cpp +++ b/firmware/application/ui_soundboard.cpp @@ -96,6 +96,9 @@ void SoundBoardView::on_tuning_frequency_changed(rf::Frequency f) { } void SoundBoardView::play_sound(uint16_t id) { + uint32_t ctcss_option; + bool ctcss_enabled; + uint32_t divider; if (sounds[id].size == 0) return; @@ -123,7 +126,21 @@ void SoundBoardView::play_sound(uint16_t id) { transmitter_model.set_baseband_bandwidth(1750000); transmitter_model.enable(); - baseband::set_audiotx_data(1536000 / sounds[id].sample_rate, number_bw.value()); + ctcss_option = options_ctcss.selected_index(); + + if (ctcss_option) + ctcss_enabled = true; + else + ctcss_enabled = false; + + divider = (1536000 / sounds[id].sample_rate) - 1; + + baseband::set_audiotx_data( + divider, + number_bw.value(), + ctcss_enabled, + (67109.0 * (float)_ctcss_freq)/1536000.0 // TODO: Might not be precise enough + ); } void SoundBoardView::show_infos(uint16_t id) { @@ -181,6 +198,10 @@ uint32_t SoundBoardView::fb_to_uint32(const std::string& fb) { return (fb[3] << 24) + (fb[2] << 16) + (fb[1] << 8) + fb[0]; } +void SoundBoardView::on_ctcss_changed(uint32_t v) { + _ctcss_freq = v; +} + SoundBoardView::SoundBoardView( NavigationView& nav ) @@ -244,6 +265,7 @@ SoundBoardView::SoundBoardView( &field_frequency, &number_bw, &text_kHz, + &options_ctcss, &text_page, &text_duration, &pbar, @@ -251,6 +273,12 @@ SoundBoardView::SoundBoardView( &button_random, &button_exit } }); + + options_ctcss.on_change = [this](size_t, OptionsField::value_t v) { + this->on_ctcss_changed(v); + }; + + options_ctcss.set_selected_index(0); const auto button_fn = [this](Button& button) { tx_mode = NORMAL; diff --git a/firmware/application/ui_soundboard.hpp b/firmware/application/ui_soundboard.hpp index 9f07c2f93..b544f27ee 100644 --- a/firmware/application/ui_soundboard.hpp +++ b/firmware/application/ui_soundboard.hpp @@ -33,7 +33,7 @@ #include "file.hpp" namespace ui { - + class SoundBoardView : public View { public: SoundBoardView(NavigationView& nav); @@ -72,6 +72,8 @@ private: sound sounds[100]; uint8_t max_sound; uint8_t max_page; + + uint32_t _ctcss_freq; int8_t audio_buffer[1024]; @@ -107,6 +109,7 @@ private: void refresh_buttons(uint16_t id); void play_sound(uint16_t id); void prepare_audio(); + void on_ctcss_changed(uint32_t v); uint16_t fb_to_uint16(const std::string& fb); uint32_t fb_to_uint32(const std::string& fb); @@ -119,7 +122,7 @@ private: }; NumberField number_bw { - { 13 * 8, 4 }, + { 11 * 8, 4 }, 3, {1, 150}, 1, @@ -127,12 +130,71 @@ private: }; Text text_kHz { - { 16 * 8, 4, 3 * 8, 16 }, + { 14 * 8, 4, 3 * 8, 16 }, "kHz" }; + OptionsField options_ctcss { + { 18 * 8, 4 }, + 6, + { + { "None ", 0 }, + { "XZ 000", 67000 }, + { "WZ 001", 69400 }, + { "XA 039", 71900 }, + { "WA 003", 74400 }, + { "XB 004", 77000 }, + { "WB 005", 79700 }, + { "YZ 006", 82500 }, + { "YA 007", 85400 }, + { "YB 008", 88500 }, + { "ZZ 009", 91500 }, + { "ZA 010", 94800 }, + { "ZB 011", 97400 }, + { "1Z 012", 100000 }, + { "1A 013", 103500 }, + { "1B 014", 107200 }, + { "2Z 015", 110900 }, + { "2Z 016", 114800 }, + { "2B 017", 118800 }, + { "3Z 018", 123000 }, + { "3A 019", 127300 }, + { "3B 020", 131800 }, + { "4Z 021", 136500 }, + { "4A 022", 141300 }, + { "4B 023", 146200 }, + { "MIL ", 150000 }, + { "5Z 024", 151400 }, + { "5A 025", 156700 }, + { "-- 040", 159800 }, + { "5B 026", 162200 }, + { "-- 041", 165500 }, + { "6Z 027", 167900 }, + { "-- 042", 171300 }, + { "6A 028", 173800 }, + { "-- 043", 177300 }, + { "6B 029", 179900 }, + { "-- 044", 183500 }, + { "7Z 030", 186200 }, + { "-- 045", 189900 }, + { "7A 031", 192800 }, + { "-- 046", 196600 }, + { "-- 047", 199500 }, + { "M1 032", 203500 }, + { "8Z 048", 206500 }, + { "M2 033", 210700 }, + { "M3 034", 218100 }, + { "M4 035", 225700 }, + { "9Z 049", 229100 }, + { "-- 036", 233600 }, + { "-- 037", 241800 }, + { "-- 038", 250300 }, + { "0Z 050", 254100 } + } + }; + Text text_page { - { 22 * 8, 4, 3 * 8, 16 }, + { 25 * 8, 4, 3 * 8, 16 }, "-/-" }; diff --git a/firmware/baseband/proc_audiotx.cpp b/firmware/baseband/proc_audiotx.cpp index 05ef3e1c5..84471c5f2 100644 --- a/firmware/baseband/proc_audiotx.cpp +++ b/firmware/baseband/proc_audiotx.cpp @@ -43,6 +43,12 @@ void AudioTXProcessor::execute(const buffer_c8_t& buffer){ audio_fifo.out(sample); //preview_audio_buffer.p[ai++] = sample << 8; + if (ctcss_enabled) { + ctcss_sample = sine_table_i8[(ctcss_phase & 0x03FC0000) >> 18]; + int16_t mix = (sample * 218) + (ctcss_sample * 37); // ~15% + sample = mix >> 8; + } + if ((audio_fifo.len() < 1024) && (asked == false)) { // Ask application to fill up fifo sigmessage.signaltype = 1; @@ -53,6 +59,8 @@ void AudioTXProcessor::execute(const buffer_c8_t& buffer){ as--; } + ctcss_phase += ctcss_phase_inc; + // FM frq = sample * bw; @@ -79,6 +87,8 @@ void AudioTXProcessor::on_message(const Message* const msg) { // a = 262144 / 1536000 (*1000 = 171) bw = 171 * (message->bw); divider = message->divider; + ctcss_phase_inc = message->ctcss_phase_inc; + ctcss_enabled = message->ctcss_enabled; as = 0; configured = true; diff --git a/firmware/baseband/proc_audiotx.hpp b/firmware/baseband/proc_audiotx.hpp index fc23f0bd5..7e23d1807 100644 --- a/firmware/baseband/proc_audiotx.hpp +++ b/firmware/baseband/proc_audiotx.hpp @@ -44,9 +44,11 @@ private: uint32_t bw; uint32_t divider; uint8_t as = 0; + uint32_t ctcss_phase_inc; + bool ctcss_enabled; int8_t re, im; - int8_t sample; + int8_t ctcss_sample, sample; bool asked = false; @@ -58,7 +60,7 @@ private: FIFOSignalMessage sigmessage; - uint32_t aphase, phase, sphase; + uint32_t ctcss_phase, phase, sphase; int32_t frq; }; diff --git a/firmware/common/message.hpp b/firmware/common/message.hpp index fc85fa82e..379f0965d 100644 --- a/firmware/common/message.hpp +++ b/firmware/common/message.hpp @@ -563,15 +563,21 @@ class AudioTXConfigMessage : public Message { public: constexpr AudioTXConfigMessage( const uint32_t divider, - const uint32_t bw + const uint32_t bw, + const uint32_t ctcss_phase_inc, + const bool ctcss_enabled ) : Message { ID::AudioTXConfig }, divider(divider), - bw(bw) + bw(bw), + ctcss_phase_inc(ctcss_phase_inc), + ctcss_enabled(ctcss_enabled) { } const uint32_t divider; const uint32_t bw; + const uint32_t ctcss_phase_inc; + const bool ctcss_enabled; }; class AFSKConfigureMessage : public Message { diff --git a/firmware/portapack-h1-havoc.bin b/firmware/portapack-h1-havoc.bin index d652b5a46..d08eb5494 100644 Binary files a/firmware/portapack-h1-havoc.bin and b/firmware/portapack-h1-havoc.bin differ