Added Soundboard

file.cpp: scan_root_files
proc_audiotx.cpp: bandwidth setting
ui_widget.cpp: button on_focus
This commit is contained in:
furrtek 2016-08-26 08:11:24 +02:00
parent 5de6349199
commit f7e0f36bd9
19 changed files with 462 additions and 121 deletions

View File

@ -165,7 +165,7 @@ set(CPPSRC
ui_handwrite.cpp
ui_afsksetup.cpp
# ui_closecall.cpp
# ui_soundboard.cpp
ui_soundboard.cpp
ui_rds.cpp
ui_lcr.cpp
ui_xylos.cpp

View File

@ -4062,6 +4062,30 @@ ui_setup.cpp.s:
cd /home/furrtek/portapack-hackrf && $(MAKE) -f firmware/application/CMakeFiles/application.elf.dir/build.make firmware/application/CMakeFiles/application.elf.dir/ui_setup.cpp.s
.PHONY : ui_setup.cpp.s
ui_soundboard.obj: ui_soundboard.cpp.obj
.PHONY : ui_soundboard.obj
# target to build an object file
ui_soundboard.cpp.obj:
cd /home/furrtek/portapack-hackrf && $(MAKE) -f firmware/application/CMakeFiles/application.elf.dir/build.make firmware/application/CMakeFiles/application.elf.dir/ui_soundboard.cpp.obj
.PHONY : ui_soundboard.cpp.obj
ui_soundboard.i: ui_soundboard.cpp.i
.PHONY : ui_soundboard.i
# target to preprocess a source file
ui_soundboard.cpp.i:
cd /home/furrtek/portapack-hackrf && $(MAKE) -f firmware/application/CMakeFiles/application.elf.dir/build.make firmware/application/CMakeFiles/application.elf.dir/ui_soundboard.cpp.i
.PHONY : ui_soundboard.cpp.i
ui_soundboard.s: ui_soundboard.cpp.s
.PHONY : ui_soundboard.s
# target to generate assembly for a file
ui_soundboard.cpp.s:
cd /home/furrtek/portapack-hackrf && $(MAKE) -f firmware/application/CMakeFiles/application.elf.dir/build.make firmware/application/CMakeFiles/application.elf.dir/ui_soundboard.cpp.s
.PHONY : ui_soundboard.cpp.s
ui_spectrum.obj: ui_spectrum.cpp.obj
.PHONY : ui_spectrum.obj
@ -4660,6 +4684,9 @@ help:
@echo "... ui_setup.obj"
@echo "... ui_setup.i"
@echo "... ui_setup.s"
@echo "... ui_soundboard.obj"
@echo "... ui_soundboard.i"
@echo "... ui_soundboard.s"
@echo "... ui_spectrum.obj"
@echo "... ui_spectrum.i"
@echo "... ui_spectrum.s"

View File

@ -1,5 +1,6 @@
/*
* Copyright (C) 2015 Jared Boone, ShareBrained Technology, Inc.
* Copyright (C) 2016 Furrtek
*
* This file is part of PortaPack.
*
@ -177,6 +178,28 @@ std::string next_filename_stem_matching_pattern(const std::string& filename_stem
return filename_stem;
}
std::vector<std::string> scan_root_files(const std::string& extension) {
std::vector<std::string> file_list { };
std::string fname;
FRESULT res;
DIR dir;
static FILINFO fno;
res = f_opendir(&dir, "/");
if (res == FR_OK) {
for (;;) {
res = f_readdir(&dir, &fno);
if (res != FR_OK || fno.fname[0] == 0) break;
fname.assign(fno.fname);
if (fname.find(extension) != std::string::npos)
file_list.push_back(fname);
}
f_closedir(&dir);
}
return file_list;
}
namespace std {
namespace filesystem {

View File

@ -1,5 +1,6 @@
/*
* Copyright (C) 2015 Jared Boone, ShareBrained Technology, Inc.
* Copyright (C) 2016 Furrtek
*
* This file is part of PortaPack.
*
@ -32,8 +33,10 @@
#include <array>
#include <memory>
#include <iterator>
#include <vector>
std::string next_filename_stem_matching_pattern(const std::string& filename_stem_pattern);
std::vector<std::string> scan_root_files(const std::string& extension);
namespace std {
namespace filesystem {

View File

@ -23,19 +23,21 @@
// Bitmaps generated with:
// Gimp image > indexed colors (16), then "xxd -i *.bmp"
//BUG: No audio in about when shown second time
//BUG (fixed ?): No audio in about when shown second time
//BUG: POCSAG RX sometimes misses the first codeword after SYNC
//TODO: Make frequency set button in afsksetup accept GHz frequencies (longer label buffer)
//TODO: POCSAG 512 and 2400 (all 3 at the same time, or parameter ?)
//TODO: Check AFSK transmit end, skips last bits ?
//TODO: Check jammer bandwidths
//TODO: Use msgpack for settings, lists... on sd card
//TODO: Frequency manager
//TODO: Morse coder
//TODO: Replay
//Multimon-style stuff:
//TODO: AFSK receiver
//TODO: Xylos receiver
//TODO: Xylos (CCIR) receiver
//TODO: Check jammer bandwidths
//TODO: Closecall wide range fix
//TODO: SD card wiper
//TODO: GSM channel detector

View File

@ -41,18 +41,18 @@ namespace format {
static std::string bitrate_str(BitRate bitrate) {
switch (bitrate) {
case BitRate::FSK512: return "F512 ";
case BitRate::FSK1200: return "F1200";
case BitRate::FSK2400: return "F2400";
default: return "F????";
case BitRate::FSK512: return "512 ";
case BitRate::FSK1200: return "1200";
case BitRate::FSK2400: return "2400";
default: return "????";
}
}
static std::string flag_str(PacketFlag packetflag) {
switch (packetflag) {
case PacketFlag::NORMAL: return "NORMAL ";
case PacketFlag::NORMAL: return "OK";
case PacketFlag::TIMED_OUT: return "TIMED OUT";
case PacketFlag::TOO_LONG: return "TOO LONG ";
case PacketFlag::TOO_LONG: return "TOO LONG";
default: return "";
}
}
@ -208,12 +208,12 @@ void POCSAGAppView::on_packet(const POCSAGPacketMessage * message) {
if (eom) {
std::string console_info;
console_info = to_string_time(message->packet.timestamp());
console_info = to_string_time(message->packet.timestamp()) + " ";
if (address || function) {
console_info += pocsag::format::bitrate_str( message->packet.bitrate()) + " ";
console_info += pocsag::format::flag_str(message->packet.flag()) + " ";
console_info += " ADDR:" + to_string_dec_uint(address, 7) + " F:" + to_string_dec_uint(function);
console_info += "ADDR:" + to_string_dec_uint(address) + " F:" + to_string_dec_uint(function);
console.writeln(console_info);

View File

@ -59,9 +59,7 @@ void AboutView::on_show() {
transmitter_model.set_baseband_bandwidth(1750000);
transmitter_model.enable();
baseband::set_audiotx_data(
0
);
baseband::set_audiotx_data(15);
//audio::headphone::set_volume(volume_t::decibel(0 - 99) + audio::headphone::volume_range().max);
}
@ -132,7 +130,7 @@ void AboutView::render_video() {
// Switch to next text
if (anim_state == 0) {
if (credits_index == 7)
if (credits_index == 9)
credits_index = 0;
else
credits_index++;
@ -221,7 +219,7 @@ void AboutView::render_audio() {
// Render 1024 music samples
for (ym_render_cnt = 0; ym_render_cnt < 1024; ym_render_cnt++) {
// Taken at 48000/960 = 50Hz
// Update registers at 48000/960 = 50Hz
if (ym_sample_cnt == 0) {
// "Decompress" on the fly and update YM registers
for (i = 0; i < 14; i++) {
@ -338,7 +336,7 @@ void AboutView::update() {
}
// Slowly increase volume to avoid jumpscare
if (headphone_vol < (70<<2)) {
if (headphone_vol < (70 << 2)) {
audio::headphone::set_volume(volume_t::decibel((headphone_vol/4) - 99) + audio::headphone::volume_range().max);
headphone_vol++;
}

View File

@ -56,12 +56,12 @@ private:
bool same;
} ymreg_t;
uint16_t headphone_vol = 5<<2;
uint16_t headphone_vol = 5 << 2;
ymreg_t ym_regs[14];
uint16_t ym_frames;
uint16_t ym_frame;
uint8_t drum;
uint8_t drum = 0;
uint16_t ym_osc_cnt[3];
uint32_t ym_rng = 1;
uint16_t ym_noise_cnt;
@ -80,8 +80,8 @@ private:
ui::Color paletteB[16];
ui::Color * framebuffer;
uint32_t phase = 0;
uint8_t copperbars[5] = {0};
uint8_t copperbuffer[72] = {0};
uint8_t copperbars[5] = { 0 };
uint8_t copperbuffer[72] = { 0 };
uint8_t anim_state = 0;
uint8_t credits_index = 0;
@ -98,12 +98,12 @@ private:
15, 16, 17, 18, 19, 20, 21, 22,
23, 24, 25, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
const uint8_t copperluma[16] = {8,7,6,5,4,3,2,1,1,2,3,4,5,6,7,8};
const uint8_t coppercolor[5][3] = { {255,0,0},
{0,255,0},
{0,0,255},
{255,0,255},
{255,255,0} };
const uint8_t copperluma[16] = { 8,7,6,5,4,3,2,1,1,2,3,4,5,6,7,8 };
const uint8_t coppercolor[5][3] = { { 255,0,0 },
{ 0,255,0 },
{ 0,0,255 },
{ 255,0,255 },
{ 255,255,0 } };
typedef struct credits_t {
char role[12];
@ -112,10 +112,12 @@ private:
} credits_t;
// 0123456789A 0123456789A
const credits_t credits[8] = { {"GURUS", "J. BOONE", false},
{"GURUS", "M. OSSMANN", true},
const credits_t credits[10] = { {"GURUS", "J. BOONE", false},
{"GURYS", "M. OSSMANN", true},
{"BUGS", "FURRTEK", true},
{"RDS TABLE", "C. JACQUET", true},
{"RDS WAVE", "C. JACQUET", true},
{"POCSAG RX", "T. SAILER", false},
{"POCSAG RX", "E. OENAL", true},
{"XYLOS DATA", "CLX", true},
{"GREETS TO", "SIGMOUNTE", false},
{"GREETS TO", "WINDYOONA", true},

View File

@ -266,7 +266,7 @@ void LCRView::start_tx(const bool scan) {
portapack::persistent_memory::afsk_mark_freq() * 437 * 5, //(0x40000 * 256) / (153600 / 25),
portapack::persistent_memory::afsk_space_freq() * 437 * 5, //(0x40000 * 256) / (153600 / 25),
afsk_repeats,
portapack::persistent_memory::afsk_bw() * 115, // See proc_fsk_lcr.cpp
portapack::persistent_memory::afsk_bw() * 115, // See proc_afsk.cpp
afsk_format
);
}

View File

@ -35,9 +35,9 @@
#include "ui_setup.hpp"
#include "ui_debug.hpp"
//#include "ui_soundboard.hpp" // DEBUG
//#include "ui_closecall.hpp" // DEBUG
#include "ui_freqman.hpp" // DEBUG
//#include "ui_freqman.hpp" // DEBUG
#include "ui_soundboard.hpp"
#include "ui_encoders.hpp"
#include "ui_debug.hpp"
@ -46,7 +46,7 @@
#include "ui_epar.hpp"
#include "ui_lcr.hpp"
#include "analog_audio_app.hpp"
#include "ui_audiotx.hpp" // DEBUG
//#include "ui_audiotx.hpp" // DEBUG
//#include "ui_jammer.hpp" // DEBUG
#include "analog_audio_app.hpp"
@ -246,9 +246,9 @@ SystemMenuView::SystemMenuView(NavigationView& nav) {
{ "Receiver RX", ui::Color::cyan(), [&nav](){ nav.push<ReceiverMenuView>(); } },
{ "Capture RX", ui::Color::cyan(), [&nav](){ nav.push<CaptureAppView>(); } },
//{ "Close Call RX", ui::Color::cyan(), [&nav](){ nav.push<CloseCallView>(); } },
{ "Numbers station TX", ui::Color::purple(), [&nav](){ nav.push<NotImplementedView>(); } }, //nav.push<NumbersStationView>();
//{ "Numbers station TX", ui::Color::purple(), [&nav](){ nav.push<NotImplementedView>(); } }, //nav.push<NumbersStationView>();
//{ "Pokemon GO Away TX", ui::Color::blue(), [&nav](){ nav.push<JammerView>(); } },
//{ "Soundboard TX", ui::Color::yellow(), [&nav](){ nav.push<LoadModuleView>(md5_baseband_tx, SoundBoard); } },
{ "Soundboard TX", ui::Color::yellow(), [&nav](){ nav.push<SoundBoardView>(); } },
//{ "Audio TX", ui::Color::yellow(), [&nav](){ nav.push<LoadModuleView>(md5_baseband_tx, AudioTX); } },
//{ "Frequency manager", ui::Color::white(), [&nav](){ nav.push<FreqManView>(); } },
//{ "EPAR TX", ui::Color::green(), [&nav](){ nav.push<LoadModuleView>(md5_baseband_tx, EPAR); } },

View File

@ -1,5 +1,6 @@
/*
* Copyright (C) 2015 Jared Boone, ShareBrained Technology, Inc.
* Copyright (C) 2016 Furrtek
*
* This file is part of PortaPack.
*
@ -19,6 +20,8 @@
* Boston, MA 02110-1301, USA.
*/
// To prepare samples: for f in ./*.wav; do sox "$f" -r 48000 -c 1 -b8 --norm "conv/$f"; done
#include "ui_soundboard.hpp"
#include "ch.h"
@ -35,28 +38,65 @@
#include "portapack_shared_memory.hpp"
#include <cstring>
#include <vector>
using namespace portapack;
namespace ui {
uint16_t SoundBoardView::shitty_rand() {
uint8_t bit;
void SoundBoardView::on_show() {
/*
// Just in case
EventDispatcher::message_map().unregister_handler(Message::ID::DisplayFrameSync);
bit = ((lfsr >> 0) ^ (lfsr >> 2) ^ (lfsr >> 3) ^ (lfsr >> 5) ) & 1;
// "Vertical blank interrupt"
EventDispatcher::message_map().register_handler(Message::ID::DisplayFrameSync,
[this](const Message* const) {
pbar_test.set_value(testv/4);
testv++;
}
);*/
return lfsr = (lfsr >> 1) | (bit << 15);
}
std::string SoundBoardView::title() const {
return "Sound board";
};
void SoundBoardView::do_random() {
uint16_t id;
chThdSleepMilliseconds(300); // 100ms
id = shitty_rand() % max_sound;
play_sound(id);
buttons[id % 21].focus();
page = id / 21;
refresh_buttons(id);
}
void SoundBoardView::prepare_audio() {
if (cnt >= sample_duration) {
if (tx_mode == NORMAL) {
if (!check_loop.value()) {
pbar.set_value(0);
transmitter_model.disable();
return;
} else {
file.seek(44);
cnt = 0;
}
} else {
pbar.set_value(0);
transmitter_model.disable();
do_random();
}
}
pbar.set_value(cnt);
file.read(audio_buffer, 1024);
for (size_t n = 0; n < 1024; n++)
audio_buffer[n] -= 0x80;
cnt += 1024;
baseband::set_fifo_data(audio_buffer);
}
void SoundBoardView::focus() {
buttons[0].focus();
@ -66,72 +106,218 @@ void SoundBoardView::on_tuning_frequency_changed(rf::Frequency f) {
transmitter_model.set_tuning_frequency(f);
}
void SoundBoardView::on_button(Button& button) {
text_test.set(to_string_dec_uint(button.id));
void SoundBoardView::play_sound(uint16_t id) {
auto error = file.open(sounds[id].filename);
if (error.is_valid()) return;
sample_duration = sounds[id].sample_duration;
pbar.set_max(sample_duration);
pbar.set_value(0);
cnt = 0;
file.seek(44); // Skip header
prepare_audio();
transmitter_model.set_baseband_configuration({
.mode = 0,
.sampling_rate = 1536000,
.decimation_factor = 1,
});
transmitter_model.set_rf_amp(true);
transmitter_model.set_lna(40);
transmitter_model.set_vga(40);
transmitter_model.set_baseband_bandwidth(1750000);
transmitter_model.enable();
baseband::set_audiotx_data(number_bw.value());
}
void SoundBoardView::show_infos(uint16_t id) {
uint32_t duration = sounds[id].ms_duration;
text_duration.set(to_string_dec_uint(duration / 1000) + "." + to_string_dec_uint((duration / 100) % 10) + "s");
}
void SoundBoardView::refresh_buttons(uint16_t id) {
size_t n = 0, n_sound;
text_page.set(to_string_dec_uint(page + 1) + "/" + to_string_dec_uint(max_page));
for (auto& button : buttons) {
n_sound = (page * 21) + n;
button.id = n_sound;
if (n_sound < max_sound) {
button.set_text(sounds[n_sound].shortname);
button.set_style(styles[sounds[n_sound].shortname[0] & 3]);
} else {
button.set_text("- - -");
button.set_style(styles[0]);
}
n++;
}
show_infos(id);
}
void SoundBoardView::change_page(Button& button, const KeyEvent key) {
// Stupid way to find out if the button is on the sides
if (button.screen_pos().x < 32) {
if ((key == KeyEvent::Left) && (page > 0)) {
page--;
refresh_buttons(button.id);
}
}
if (button.screen_pos().x > 120) {
if ((key == KeyEvent::Right) && (page < max_page - 1)) {
page++;
refresh_buttons(button.id);
}
}
}
uint16_t SoundBoardView::fb_to_uint16(const std::string& fb) {
return (fb[1] << 8) + fb[0];
}
uint32_t SoundBoardView::fb_to_uint32(const std::string& fb) {
return (fb[3] << 24) + (fb[2] << 16) + (fb[1] << 8) + fb[0];
}
SoundBoardView::SoundBoardView(
NavigationView& nav
)
{
size_t n;
std::vector<std::string> file_list;
std::string file_name;
uint32_t size;
uint8_t c;
for (n = 0; n < 12; n++) {
sounds[n].filename = "";
sounds[n].shortname = "Empty";
sounds[n].min = 0;
sounds[n].sec = 0;
char file_buffer[32];
baseband::run_image(portapack::spi_flash::image_tag_audio_tx);
file_list = scan_root_files(".WAV");
c = 0;
for (auto& file_name : file_list) {
auto error = file.open(file_name);
file.seek(40);
file.read(file_buffer, 4);
size = fb_to_uint32(file_buffer);
sounds[c].size = size;
file.seek(22);
file.read(file_buffer, 2);
if (fb_to_uint16(file_buffer) > 1) {
sounds[c].stereo = true;
size /= 2;
} else
sounds[c].stereo = false;
file.seek(24);
file.read(file_buffer, 4);
sounds[c].sample_rate = fb_to_uint32(file_buffer);
file.seek(34);
file.read(file_buffer, 2);
if (fb_to_uint16(file_buffer) > 8) {
sounds[c].sixteenbit = true;
size /= 2;
} else
sounds[c].sixteenbit = false;
sounds[c].ms_duration = (size * 1000) / sounds[c].sample_rate;
sounds[c].sample_duration = size;
sounds[c].filename = file_name;
sounds[c].shortname = file_name.substr(0, file_name.find_last_of("."));
c++;
if (c == 100) break;
}
max_sound = c;
max_page = max_sound / 21;
add_children({ {
&text_test,
&field_frequency,
&number_bw,
&pbar_test,
&button_load,
&text_kHz,
&text_page,
&text_duration,
&pbar,
&check_loop,
&button_random,
&button_exit
} });
const auto button_fn = [this](Button& button) {
this->on_button(button);
tx_mode = NORMAL;
this->play_sound(button.id);
};
const auto button_focus = [this](Button& button) {
this->show_infos(button.id);
};
const auto button_dir = [this](Button& button, const KeyEvent key) {
(void)button;
this->change_page(button, key);
};
size_t n = 0;
for(auto& button : buttons) {
add_child(&button);
button.id = n;
button.on_select = button_fn;
button.on_highlight = button_focus;
button.on_dir = button_dir;
button.set_parent_rect({
static_cast<Coord>((n % 3) * 70 + 15),
static_cast<Coord>((n / 3) * 50 + 30),
70, 50
static_cast<Coord>((n % 3) * 78 + 3),
static_cast<Coord>((n / 3) * 28 + 26),
78, 28
});
button.set_text(sounds[n].shortname);
n++;
}
refresh_buttons(0);
check_loop.set_value(false);
number_bw.set_value(15);
field_frequency.set_value(transmitter_model.tuning_frequency());
field_frequency.set_step(receiver_model.frequency_step());
field_frequency.set_step(10000);
field_frequency.on_change = [this](rf::Frequency f) {
this->on_tuning_frequency_changed(f);
};
field_frequency.on_edit = [this, &nav]() {
// TODO: Provide separate modal method/scheme?
auto new_view = nav.push<FrequencyKeypadView>(receiver_model.tuning_frequency());
auto new_view = nav.push<FrequencyKeypadView>(transmitter_model.tuning_frequency());
new_view->on_changed = [this](rf::Frequency f) {
this->on_tuning_frequency_changed(f);
this->field_frequency.set_value(f);
};
};
/*button_transmit.on_select = [](Button&){
transmitter_model.set_baseband_configuration({
.mode = 1,
.sampling_rate = 1536000,
.decimation_factor = 1,
});
transmitter_model.set_rf_amp(true);
transmitter_model.enable();
};*/
button_random.on_select = [this](Button&){
if (tx_mode == NORMAL) {
tx_mode = RANDOM;
button_random.set_text("STOP");
do_random();
} else {
tx_mode = NORMAL;
button_random.set_text("Random");
}
};
button_exit.on_select = [&nav](Button&){
nav.pop();
@ -140,6 +326,7 @@ SoundBoardView::SoundBoardView(
SoundBoardView::~SoundBoardView() {
transmitter_model.disable();
baseband::shutdown();
}
}

View File

@ -1,5 +1,6 @@
/*
* Copyright (C) 2015 Jared Boone, ShareBrained Technology, Inc.
* Copyright (C) 2016 Furrtek
*
* This file is part of PortaPack.
*
@ -19,19 +20,17 @@
* Boston, MA 02110-1301, USA.
*/
#ifndef __UI_SOUNDBOARD_H__
#define __UI_SOUNDBOARD_H__
#include "ui.hpp"
#include "ui_widget.hpp"
#include "ui_painter.hpp"
#include "ui_menu.hpp"
#include "ui_navigation.hpp"
#include "ui_font_fixed_8x16.hpp"
#include "clock_manager.hpp"
#include "message.hpp"
#include "rf_path.hpp"
#include "max2837.hpp"
#include "volume.hpp"
#include "baseband_api.hpp"
#include "ui_navigation.hpp"
#include "ui_receiver.hpp"
#include "transmitter_model.hpp"
#include "message.hpp"
#include "file.hpp"
namespace ui {
@ -40,27 +39,81 @@ public:
SoundBoardView(NavigationView& nav);
~SoundBoardView();
std::string title() const;
void on_show() override;
void focus() override;
std::string title() const override { return "Soundboard"; };
private:
enum tx_modes {
NORMAL = 0,
RANDOM
};
tx_modes tx_mode = NORMAL;
struct sound {
std::string filename;
std::string shortname;
uint8_t min;
uint8_t sec;
bool stereo;
bool sixteenbit;
uint32_t sample_rate;
uint32_t size;
uint32_t sample_duration;
uint32_t ms_duration;
};
sound sounds[12];
uint32_t cnt;
uint32_t sample_duration;
uint8_t page = 0;
File file;
uint16_t lfsr = 0x1337u;
sound sounds[100];
uint8_t max_sound;
uint8_t max_page;
std::array<Button, 12> buttons;
void on_button(Button& button);
int8_t audio_buffer[1024];
Style style_a {
.font = font::fixed_8x16,
.background = Color::black(),
.foreground = { 255, 51, 153 }
};
Style style_b {
.font = font::fixed_8x16,
.background = Color::black(),
.foreground = { 153, 204, 0 }
};
Style style_c {
.font = font::fixed_8x16,
.background = Color::black(),
.foreground = { 51, 204, 204 }
};
Style style_d {
.font = font::fixed_8x16,
.background = Color::black(),
.foreground = { 153, 102, 255 }
};
std::array<Button, 21> buttons;
const Style * styles[4] = { &style_a, &style_b, &style_c, &style_d };
void on_tuning_frequency_changed(rf::Frequency f);
Text text_test {
{ 120, 4, 64, 16 }
void do_random();
uint16_t shitty_rand();
void show_infos(uint16_t id);
void change_page(Button& button, const KeyEvent key);
void refresh_buttons(uint16_t id);
void play_sound(uint16_t id);
void prepare_audio();
uint16_t fb_to_uint16(const std::string& fb);
uint32_t fb_to_uint32(const std::string& fb);
Text text_duration {
{ 16, 236, 5 * 8, 16 }
};
FrequencyField field_frequency {
@ -68,26 +121,54 @@ private:
};
NumberField number_bw {
{ 16 * 8, 4 },
5,
{1000, 50000},
500,
{ 14 * 8, 4 },
2,
{1, 50},
1,
' '
};
ProgressBar pbar_test {
{ 45, 236, 150, 16 }
Text text_kHz {
{ 16 * 8, 4, 3 * 8, 16 },
"kHz"
};
Button button_load {
{ 8, 270, 64, 32 },
"Load"
Text text_page {
{ 22 * 8, 4, 3 * 8, 16 },
"-/-"
};
ProgressBar pbar {
{ 72, 236, 150, 16 }
};
Checkbox check_loop {
{ 16, 274 },
4,
"Loop"
};
Button button_random {
{ 80, 270, 72, 32 },
"Random"
};
Button button_exit {
{ 96, 270, 64, 32 },
{ 160, 270, 64, 32 },
"Exit"
};
MessageHandlerRegistration message_handler_fifo_signal {
Message::ID::FIFOSignal,
[this](const Message* const p) {
const auto message = static_cast<const FIFOSignalMessage*>(p);
if (message->signaltype == 1) {
this->prepare_audio();
}
}
};
};
} /* namespace ui */
#endif/*__UI_SOUNDBOARD_H__*/

View File

@ -106,7 +106,8 @@ void AFSKProcessor::execute(const buffer_c8_t& buffer) {
// FM
// 1<<18 = 262144
// m = (262144 * BW) / 2280000 (* 115, see ui_lcr afsk_bw setting)
// m = (262144 * a) / 2280000
// a = 262144 / 2280000 (*1000 = 115, see ui_lcr afsk_bw setting)
frq = tone_sample * afsk_bw;
phase = (phase + frq);

View File

@ -38,8 +38,8 @@ void AudioTXProcessor::execute(const buffer_c8_t& buffer){
for (size_t i = 0; i<buffer.count; i++) {
// Audio preview sample generation: 1536000/48000 = 32
if (as >= 31) {
as = 0;
if (!as) {
as = 32;
audio_fifo.out(sample);
//preview_audio_buffer.p[ai++] = sample << 8;
@ -50,11 +50,11 @@ void AudioTXProcessor::execute(const buffer_c8_t& buffer){
asked = true;
}
} else {
as++;
as--;
}
// FM
frq = sample * 8000;
frq = sample * bw;
phase = (phase + frq);
sphase = phase + (64 << 18);
@ -69,9 +69,17 @@ void AudioTXProcessor::execute(const buffer_c8_t& buffer){
}
void AudioTXProcessor::on_message(const Message* const msg) {
const auto message = static_cast<const AudioTXConfigMessage*>(msg);
switch(msg->id) {
case Message::ID::AudioTXConfig:
//const auto message = static_cast<const AudioTXConfigMessage*>(msg);
// 1<<18 = 262144
// m = (262144 * a) / 1536000
// a = 262144 / 1536000 (*1000 = 171)
bw = 171 * (message->bw);
as = 0;
configured = true;
break;

View File

@ -41,6 +41,7 @@ private:
int8_t audio_fifo_data[2048];
FIFO<int8_t> audio_fifo = { audio_fifo_data, 11 }; // 43ms @ 48000Hz
uint32_t bw;
uint8_t as = 0, ai;
int8_t re, im;
int8_t sample;

View File

@ -94,7 +94,7 @@ void POCSAGProcessor::execute(const buffer_c8_t& buffer) {
last_rx_data = rx_data;
rx_state = SYNC;
} else if (rx_data == POCSAG_IDLE) {
//rx_state = WAITING;
rx_state = WAITING;
}
} else {
@ -106,6 +106,7 @@ void POCSAGProcessor::execute(const buffer_c8_t& buffer) {
if (msg_timeout < 600) {
msg_timeout++;
rx_bit++;
if (rx_bit >= 32) {
rx_bit = 0;

View File

@ -434,13 +434,13 @@ ProgressBar::ProgressBar(
{
}
void ProgressBar::set_max(const uint16_t max) {
void ProgressBar::set_max(const uint32_t max) {
_value = 0;
_max = max;
set_dirty();
}
void ProgressBar::set_value(const uint16_t value) {
void ProgressBar::set_value(const uint32_t value) {
if (value > _max)
_value = _max;
else
@ -689,6 +689,11 @@ void Button::paint(Painter& painter) {
);
}
void Button::on_focus() {
if( on_highlight )
on_highlight(*this);
}
bool Button::on_key(const KeyEvent key) {
if( key == KeyEvent::Select ) {
if( on_select ) {

View File

@ -220,14 +220,14 @@ class ProgressBar : public Widget {
public:
ProgressBar(Rect parent_rect);
void set_max(const uint16_t max);
void set_value(const uint16_t value);
void set_max(const uint32_t max);
void set_value(const uint32_t value);
void paint(Painter& painter) override;
private:
uint16_t _value = 0;
uint16_t _max = 100;
uint32_t _value = 0;
uint32_t _max = 100;
};
class Console : public Widget {
@ -282,6 +282,7 @@ class Button : public Widget {
public:
std::function<void(Button&)> on_select;
std::function<void(Button&,KeyEvent)> on_dir;
std::function<void(Button&)> on_highlight;
Button(Rect parent_rect, std::string text);
@ -295,6 +296,7 @@ public:
void paint(Painter& painter) override;
void on_focus() override;
bool on_key(const KeyEvent key) override;
bool on_touch(const TouchEvent event) override;

Binary file not shown.