diff --git a/firmware/application/external/audio_test/main.cpp b/firmware/application/external/audio_test/main.cpp new file mode 100644 index 000000000..48554ce19 --- /dev/null +++ b/firmware/application/external/audio_test/main.cpp @@ -0,0 +1,82 @@ +/* + * Copyright (C) 2024 Mark Thompson + * + * 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_audio_test.hpp" +#include "ui_navigation.hpp" +#include "external_app.hpp" + +namespace ui::external_app::audio_test { +void initialize_app(ui::NavigationView& nav) { + nav.push(); +} +} // namespace ui::external_app::audio_test + +extern "C" { + +__attribute__((section(".external_app.app_audio_test.application_information"), used)) application_information_t _application_information_audio_test = { + /*.memory_location = */ (uint8_t*)0x00000000, + /*.externalAppEntry = */ ui::external_app::audio_test::initialize_app, + /*.header_version = */ CURRENT_HEADER_VERSION, + /*.app_version = */ VERSION_MD5, + + /*.app_name = */ "Audio Test", + /*.bitmap_data = */ { + 0x00, + 0x00, + 0x40, + 0x10, + 0x60, + 0x20, + 0x70, + 0x44, + 0x78, + 0x48, + 0x7F, + 0x91, + 0x7F, + 0x92, + 0x7F, + 0x92, + 0x7F, + 0x92, + 0x7F, + 0x92, + 0x7F, + 0x92, + 0x7F, + 0x91, + 0x78, + 0x48, + 0x70, + 0x44, + 0x60, + 0x20, + 0x40, + 0x10, + }, + /*.icon_color = */ ui::Color::cyan().v, + /*.menu_location = */ app_location_t::DEBUG, + + /*.m4_app_tag = portapack::spi_flash::image_tag_none */ {'P', 'A', 'B', 'P'}, + /*.m4_app_offset = */ 0x00000000, // will be filled at compile time +}; +} diff --git a/firmware/application/external/audio_test/ui_audio_test.cpp b/firmware/application/external/audio_test/ui_audio_test.cpp new file mode 100644 index 000000000..66e00973c --- /dev/null +++ b/firmware/application/external/audio_test/ui_audio_test.cpp @@ -0,0 +1,82 @@ +/* + * Copyright (C) 2024 Mark Thompson + * + * 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_audio_test.hpp" +#include "baseband_api.hpp" +#include "audio.hpp" +#include "portapack.hpp" + +using namespace portapack; + +namespace ui { + +AudioTestView::AudioTestView(NavigationView& nav) + : nav_{nav} { + baseband::run_prepared_image(portapack::memory::map::m4_code.base()); // proc_audio_beep baseband is external too + + add_children({&labels, + &field_frequency, + &field_duration, + &field_volume, + &toggle_speaker}); + + field_frequency.set_value(1000); + field_frequency.on_change = [this](int32_t v) { + (void)v; + update_audio_beep(); + }; + + field_duration.set_value(100); + field_duration.on_change = [this](int32_t v) { + (void)v; + update_audio_beep(); + }; + + toggle_speaker.on_change = [this](bool v) { + beep = v; + update_audio_beep(); + }; + + field_volume.set_value(0); + field_volume.set_value(80); + + audio::set_rate(audio::Rate::Hz_24000); + audio::output::start(); +} + +AudioTestView::~AudioTestView() { + receiver_model.disable(); + baseband::shutdown(); + audio::output::stop(); +} + +void AudioTestView::focus() { + field_frequency.focus(); +} + +void AudioTestView::update_audio_beep() { + if (beep) + baseband::request_audio_beep(field_frequency.value(), field_duration.value()); + else + baseband::request_beep_stop(); +} + +} /* namespace ui */ diff --git a/firmware/application/external/audio_test/ui_audio_test.hpp b/firmware/application/external/audio_test/ui_audio_test.hpp new file mode 100644 index 000000000..34e36870c --- /dev/null +++ b/firmware/application/external/audio_test/ui_audio_test.hpp @@ -0,0 +1,83 @@ +/* + * Copyright (C) 2024 Mark Thompson + * + * 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_AUDIO_TEST_H__ +#define __UI_AUDIO_TEST_H__ + +#include "ui_navigation.hpp" +#include "ui_receiver.hpp" + +namespace ui { + +class AudioTestView : public View { + public: + AudioTestView(NavigationView& nav); + ~AudioTestView(); + AudioTestView(const AudioTestView& other) = delete; + AudioTestView& operator=(const AudioTestView& other) = delete; + + void focus() override; + void update_audio_beep(); + + std::string title() const override { return "Audio Test"; }; + + private: + NavigationView& nav_; + bool beep{false}; + + Labels labels{ + {{7 * 8, 3 * 16}, "Audio Beep Test", Color::light_grey()}, + {{0 * 8, 6 * 16}, "Frequency (Hz):", Color::light_grey()}, + {{0 * 8, 8 * 16}, "Duration (ms):", Color::light_grey()}, + {{0 * 8, 10 * 16}, "Volume:", Color::light_grey()}}; + + NumberField field_frequency{ + {16 * 8, 6 * 16}, + 5, + {100, 24000}, + 100, + ' ', + true}; + + NumberField field_duration{ + {16 * 8, 8 * 16}, + 5, + {0, 60000}, + 50, + ' ', + true}; + + AudioVolumeField field_volume{ + {19 * 8, 10 * 16}}; + + ImageToggle toggle_speaker{ + {19 * 8, 12 * 16, 2 * 8, 1 * 16}, + &bitmap_icon_speaker_mute, + &bitmap_icon_speaker, + Color::light_grey(), + Color::dark_grey(), + Color::green(), + Color::dark_grey()}; +}; + +} /* namespace ui */ + +#endif /*__UI_AUDIO_TEST_H__*/ diff --git a/firmware/application/external/external.cmake b/firmware/application/external/external.cmake index a84fa9319..120e58db4 100644 --- a/firmware/application/external/external.cmake +++ b/firmware/application/external/external.cmake @@ -73,6 +73,9 @@ set(EXTCPPSRC external/foxhunt/ui_foxhunt_rx.cpp external/foxhunt/ui_foxhunt_rx.hpp + #audio_test + external/audio_test/main.cpp + external/audio_test/ui_audio_test.cpp ) set(EXTAPPLIST @@ -93,4 +96,5 @@ set(EXTAPPLIST tetris extsensors foxhunt_rx + audio_test ) diff --git a/firmware/application/external/external.ld b/firmware/application/external/external.ld index c75276f39..4e3f12682 100644 --- a/firmware/application/external/external.ld +++ b/firmware/application/external/external.ld @@ -40,6 +40,7 @@ MEMORY 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 + ram_external_app_audio_test(rwx) : org = 0xADC10000, len = 32k } SECTIONS @@ -146,6 +147,10 @@ SECTIONS *(*ui*external_app*foxhunt_rx*); } > ram_external_app_foxhunt_rx - + .external_app_audio_test : ALIGN(4) SUBALIGN(4) + { + KEEP(*(.external_app.app_audio_test.application_information)); + *(*ui*external_app*audio_test*); + } > ram_external_app_audio_test } diff --git a/firmware/baseband/CMakeLists.txt b/firmware/baseband/CMakeLists.txt index 99f4dca39..5751c0c2b 100644 --- a/firmware/baseband/CMakeLists.txt +++ b/firmware/baseband/CMakeLists.txt @@ -609,7 +609,6 @@ set(MODE_CPPSRC ) DeclareTargets(PNRR nrfrx) - ### Jammer set(MODE_CPPSRC @@ -645,6 +644,12 @@ set(MODE_CPPSRC ) DeclareTargets(PTST test) +### Audio Beep + +set(MODE_CPPSRC + proc_audio_beep.cpp +) +DeclareTargets(PABP audio_beep) ### HackRF "factory" firmware diff --git a/firmware/baseband/proc_audio_beep.cpp b/firmware/baseband/proc_audio_beep.cpp new file mode 100644 index 000000000..879612d40 --- /dev/null +++ b/firmware/baseband/proc_audio_beep.cpp @@ -0,0 +1,63 @@ +/* + * Copyright (C) 2024 Mark Thompson + * + * 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 "proc_audio_beep.hpp" +#include "event_m4.hpp" +#include "audio_dma.hpp" + +AudioBeepProcessor::AudioBeepProcessor() { +} + +void AudioBeepProcessor::execute(const buffer_c8_t& buffer) { + (void)buffer; +} + +void AudioBeepProcessor::on_message(const Message* const msg) { + switch (msg->id) { + case Message::ID::RequestSignal: + on_signal_message(*reinterpret_cast(msg)); + break; + + case Message::ID::AudioBeep: + on_beep_message(*reinterpret_cast(msg)); + break; + + default: + break; + } +} + +void AudioBeepProcessor::on_signal_message(const RequestSignalMessage& message) { + if (message.signal == RequestSignalMessage::Signal::BeepStopRequest) { + audio::dma::beep_stop(); + } +} + +void AudioBeepProcessor::on_beep_message(const AudioBeepMessage& message) { + audio::dma::beep_start(message.freq, AUDIO_SAMPLE_RATE, message.duration_ms); +} + +int main() { + audio::dma::init_audio_out(); + EventDispatcher event_dispatcher{std::make_unique()}; + event_dispatcher.run(); + return 0; +} diff --git a/firmware/baseband/proc_audio_beep.hpp b/firmware/baseband/proc_audio_beep.hpp new file mode 100644 index 000000000..68166b910 --- /dev/null +++ b/firmware/baseband/proc_audio_beep.hpp @@ -0,0 +1,41 @@ +/* + * Copyright (C) 2024 Mark Thompson + * + * 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 __PROC_AUDIO_BEEP_H__ +#define __PROC_AUDIO_BEEP_H__ + +#include "baseband_processor.hpp" +#include "message.hpp" + +#define AUDIO_SAMPLE_RATE 24000 + +class AudioBeepProcessor : public BasebandProcessor { + public: + AudioBeepProcessor(); + void execute(const buffer_c8_t& buffer) override; + void on_message(const Message* const msg); + + private: + void on_signal_message(const RequestSignalMessage& message); + void on_beep_message(const AudioBeepMessage& message); +}; + +#endif /*__PROC_AUDIO_BEEP_H__*/ diff --git a/firmware/common/spi_image.hpp b/firmware/common/spi_image.hpp index 9ee84fb65..0a95455cb 100644 --- a/firmware/common/spi_image.hpp +++ b/firmware/common/spi_image.hpp @@ -74,6 +74,7 @@ struct image_tag_t { }; constexpr image_tag_t image_tag_none{0, 0, 0, 0}; +constexpr image_tag_t image_tag_audio_beep{'P', 'A', 'B', 'P'}; constexpr image_tag_t image_tag_acars{'P', 'A', 'C', 'A'}; constexpr image_tag_t image_tag_adsb_rx{'P', 'A', 'D', 'R'}; constexpr image_tag_t image_tag_afsk_rx{'P', 'A', 'F', 'R'};