mirror of
https://github.com/eried/portapack-mayhem.git
synced 2024-12-24 23:09:26 -05:00
Added tone keys for some wireless mic brands
Renamed CTCSS stuff to Tone key Changed PTT key in mic TX (was left, now right) to allow easier exit Mic samplerate bumped to 48kHz Updated binary
This commit is contained in:
parent
bf3aa6e11a
commit
4465cfb905
@ -151,7 +151,7 @@ set(CPPSRC
|
|||||||
modems.cpp
|
modems.cpp
|
||||||
audio.cpp
|
audio.cpp
|
||||||
${COMMON}/bch_code.cpp
|
${COMMON}/bch_code.cpp
|
||||||
ctcss.cpp
|
tone_key.cpp
|
||||||
de_bruijn.cpp
|
de_bruijn.cpp
|
||||||
encoder.cpp
|
encoder.cpp
|
||||||
emu_cc1101.cpp
|
emu_cc1101.cpp
|
||||||
|
@ -1,99 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (C) 2015 Jared Boone, ShareBrained Technology, Inc.
|
|
||||||
* Copyright (C) 2016 Furrtek
|
|
||||||
*
|
|
||||||
* 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 "ctcss.hpp"
|
|
||||||
#include "string_format.hpp"
|
|
||||||
|
|
||||||
namespace ctcss {
|
|
||||||
|
|
||||||
const ctcss_tone ctcss_tones[CTCSS_TONES_NB] = {
|
|
||||||
{ "XZ", 0, 67.000 },
|
|
||||||
{ "WZ", 1, 69.400 },
|
|
||||||
{ "XA", 2, 71.900 },
|
|
||||||
{ "WA", 3, 74.400 },
|
|
||||||
{ "XB", 4, 77.000 },
|
|
||||||
{ "WB", 5, 79.700 },
|
|
||||||
{ "YZ", 6, 82.500 },
|
|
||||||
{ "YA", 7, 85.400 },
|
|
||||||
{ "YB", 8, 88.500 },
|
|
||||||
{ "ZZ", 9, 91.500 },
|
|
||||||
{ "ZA", 10, 94.800 },
|
|
||||||
{ "ZB", 11, 97.400 },
|
|
||||||
{ "1Z", 12, 100.000 },
|
|
||||||
{ "1A", 13, 103.500 },
|
|
||||||
{ "1B", 14, 107.200 },
|
|
||||||
{ "2Z", 15, 110.900 },
|
|
||||||
{ "2Z", 16, 114.800 },
|
|
||||||
{ "2B", 17, 118.800 },
|
|
||||||
{ "3Z", 18, 123.000 },
|
|
||||||
{ "3A", 19, 127.300 },
|
|
||||||
{ "3B", 20, 131.800 },
|
|
||||||
{ "4Z", 21, 136.500 },
|
|
||||||
{ "4A", 22, 141.300 },
|
|
||||||
{ "4B", 23, 146.200 },
|
|
||||||
{ "5Z", 24, 151.400 },
|
|
||||||
{ "5A", 25, 156.700 },
|
|
||||||
{ "--", 40, 159.800 },
|
|
||||||
{ "5B", 26, 162.200 },
|
|
||||||
{ "--", 41, 165.500 },
|
|
||||||
{ "6Z", 27, 167.900 },
|
|
||||||
{ "--", 42, 171.300 },
|
|
||||||
{ "6A", 28, 173.800 },
|
|
||||||
{ "--", 43, 177.300 },
|
|
||||||
{ "6B", 29, 179.900 },
|
|
||||||
{ "--", 44, 183.500 },
|
|
||||||
{ "7Z", 30, 186.200 },
|
|
||||||
{ "--", 45, 189.900 },
|
|
||||||
{ "7A", 31, 192.800 },
|
|
||||||
{ "--", 46, 196.600 },
|
|
||||||
{ "--", 47, 199.500 },
|
|
||||||
{ "M1", 32, 203.500 },
|
|
||||||
{ "8Z", 48, 206.500 },
|
|
||||||
{ "M2", 33, 210.700 },
|
|
||||||
{ "M3", 34, 218.100 },
|
|
||||||
{ "M4", 35, 225.700 },
|
|
||||||
{ "9Z", 49, 229.100 },
|
|
||||||
{ "--", 36, 233.600 },
|
|
||||||
{ "--", 37, 241.800 },
|
|
||||||
{ "--", 38, 250.300 },
|
|
||||||
{ "0Z", 50, 254.100 }
|
|
||||||
};
|
|
||||||
|
|
||||||
void ctcss_populate(OptionsField& field) {
|
|
||||||
using option_t = std::pair<std::string, int32_t>;
|
|
||||||
using options_t = std::vector<option_t>;
|
|
||||||
options_t ctcss_options;
|
|
||||||
std::string f_string;
|
|
||||||
uint32_t c, f;
|
|
||||||
|
|
||||||
ctcss_options.emplace_back(std::make_pair("None", 0));
|
|
||||||
for (c = 0; c < CTCSS_TONES_NB; c++) {
|
|
||||||
f = (uint32_t)(ctcss_tones[c].frequency * 10);
|
|
||||||
f_string = ctcss_tones[c].PL_code;
|
|
||||||
f_string += " " + to_string_dec_uint(f / 10) + "." + to_string_dec_uint(f % 10);
|
|
||||||
ctcss_options.emplace_back(f_string, c);
|
|
||||||
}
|
|
||||||
|
|
||||||
field.set_options(ctcss_options);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
102
firmware/application/tone_key.cpp
Normal file
102
firmware/application/tone_key.cpp
Normal file
@ -0,0 +1,102 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2015 Jared Boone, ShareBrained Technology, Inc.
|
||||||
|
* Copyright (C) 2017 Furrtek
|
||||||
|
*
|
||||||
|
* 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 "tone_key.hpp"
|
||||||
|
#include "string_format.hpp"
|
||||||
|
|
||||||
|
namespace tonekey {
|
||||||
|
|
||||||
|
const tone_key_t tone_keys[] = {
|
||||||
|
{ "0 XZ", 67.000 },
|
||||||
|
{ "1 WZ", 69.400 },
|
||||||
|
{ "2 XA", 71.900 },
|
||||||
|
{ "3 WA", 74.400 },
|
||||||
|
{ "4 XB", 77.000 },
|
||||||
|
{ "5 WB", 79.700 },
|
||||||
|
{ "6 YZ", 82.500 },
|
||||||
|
{ "7 YA", 85.400 },
|
||||||
|
{ "8 YB", 88.500 },
|
||||||
|
{ "9 ZZ", 91.500 },
|
||||||
|
{ "10 ZA", 94.800 },
|
||||||
|
{ "11 1ZB", 97.400 },
|
||||||
|
{ "12 21Z", 100.000 },
|
||||||
|
{ "13 1A", 103.500 },
|
||||||
|
{ "14 1B", 107.200 },
|
||||||
|
{ "15 2Z", 110.900 },
|
||||||
|
{ "16 2Z", 114.800 },
|
||||||
|
{ "17 2B", 118.800 },
|
||||||
|
{ "18 3Z", 123.000 },
|
||||||
|
{ "19 3A", 127.300 },
|
||||||
|
{ "20 3B", 131.800 },
|
||||||
|
{ "21 4Z", 136.500 },
|
||||||
|
{ "22 4A", 141.300 },
|
||||||
|
{ "23 4B", 146.200 },
|
||||||
|
{ "24 5Z", 151.400 },
|
||||||
|
{ "25 5A", 156.700 },
|
||||||
|
{ "40 --", 159.800 },
|
||||||
|
{ "26 5B", 162.200 },
|
||||||
|
{ "41 --", 165.500 },
|
||||||
|
{ "27 6Z", 167.900 },
|
||||||
|
{ "42 --", 171.300 },
|
||||||
|
{ "28 6A", 173.800 },
|
||||||
|
{ "43 --", 177.300 },
|
||||||
|
{ "29 6B", 179.900 },
|
||||||
|
{ "44 --", 183.500 },
|
||||||
|
{ "30 7Z", 186.200 },
|
||||||
|
{ "45 --", 189.900 },
|
||||||
|
{ "31 7A", 192.800 },
|
||||||
|
{ "46 --", 196.600 },
|
||||||
|
{ "47 --", 199.500 },
|
||||||
|
{ "32 M1", 203.500 },
|
||||||
|
{ "48 8Z", 206.500 },
|
||||||
|
{ "33 M2", 210.700 },
|
||||||
|
{ "34 M3", 218.100 },
|
||||||
|
{ "35 M4", 225.700 },
|
||||||
|
{ "49 9Z", 229.100 },
|
||||||
|
{ "36 --", 233.600 },
|
||||||
|
{ "37 --", 241.800 },
|
||||||
|
{ "38 --", 250.300 },
|
||||||
|
{ "50 0Z", 254.100 },
|
||||||
|
{ "Axient 28kHz", 28000.0 },
|
||||||
|
{ "Sennheiser 32.768k", 32768.0 },
|
||||||
|
{ "Sennheiser 32kHz", 32000.0 },
|
||||||
|
{ "Shure 19kHz", 19000.0 }
|
||||||
|
};
|
||||||
|
|
||||||
|
void tone_keys_populate(OptionsField& field) {
|
||||||
|
using option_t = std::pair<std::string, int32_t>;
|
||||||
|
using options_t = std::vector<option_t>;
|
||||||
|
options_t tone_key_options;
|
||||||
|
std::string tone_name;
|
||||||
|
|
||||||
|
tone_key_options.emplace_back(std::make_pair("None", 0));
|
||||||
|
for (size_t c = 0; c < KEY_TONES_NB; c++) {
|
||||||
|
if (c < 50)
|
||||||
|
tone_name = "CTCSS " + tone_keys[c].first;
|
||||||
|
else
|
||||||
|
tone_name = tone_keys[c].first;
|
||||||
|
tone_key_options.emplace_back(tone_name, c);
|
||||||
|
}
|
||||||
|
field.set_options(tone_key_options);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2015 Jared Boone, ShareBrained Technology, Inc.
|
* Copyright (C) 2015 Jared Boone, ShareBrained Technology, Inc.
|
||||||
* Copyright (C) 2016 Furrtek
|
* Copyright (C) 2017 Furrtek
|
||||||
*
|
*
|
||||||
* This file is part of PortaPack.
|
* This file is part of PortaPack.
|
||||||
*
|
*
|
||||||
@ -20,28 +20,24 @@
|
|||||||
* Boston, MA 02110-1301, USA.
|
* Boston, MA 02110-1301, USA.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef __CTCSS_H_
|
#ifndef __TONE_KEY_H_
|
||||||
#define __CTCSS_H_
|
#define __TONE_KEY_H_
|
||||||
|
|
||||||
#include "ui.hpp"
|
#include "ui.hpp"
|
||||||
#include "ui_widget.hpp"
|
#include "ui_widget.hpp"
|
||||||
|
|
||||||
using namespace ui;
|
using namespace ui;
|
||||||
|
|
||||||
#define CTCSS_TONES_NB 50
|
#define KEY_TONES_NB (sizeof(tone_keys) / sizeof(tone_keys[0]))
|
||||||
|
|
||||||
namespace ctcss {
|
namespace tonekey {
|
||||||
|
|
||||||
struct ctcss_tone {
|
|
||||||
char PL_code[3];
|
|
||||||
uint16_t num_code;
|
|
||||||
float frequency;
|
|
||||||
};
|
|
||||||
|
|
||||||
extern const ctcss_tone ctcss_tones[CTCSS_TONES_NB];
|
using tone_key_t = std::pair<std::string, float>;
|
||||||
|
|
||||||
void ctcss_populate(OptionsField& field);
|
extern const tone_key_t tone_keys[];
|
||||||
|
|
||||||
|
void tone_keys_populate(OptionsField& field);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif/*__CTCSS_H_*/
|
#endif/*__TONE_KEY_H_*/
|
@ -25,6 +25,7 @@
|
|||||||
#include "baseband_api.hpp"
|
#include "baseband_api.hpp"
|
||||||
#include "hackrf_gpio.hpp"
|
#include "hackrf_gpio.hpp"
|
||||||
#include "audio.hpp"
|
#include "audio.hpp"
|
||||||
|
#include "tonesets.hpp"
|
||||||
#include "portapack.hpp"
|
#include "portapack.hpp"
|
||||||
#include "pins.hpp"
|
#include "pins.hpp"
|
||||||
#include "string_format.hpp"
|
#include "string_format.hpp"
|
||||||
@ -33,7 +34,7 @@
|
|||||||
|
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
|
||||||
using namespace ctcss;
|
using namespace tonekey;
|
||||||
using namespace portapack;
|
using namespace portapack;
|
||||||
using namespace hackrf::one;
|
using namespace hackrf::one;
|
||||||
|
|
||||||
@ -47,52 +48,38 @@ void MicTXView::update_vumeter() {
|
|||||||
vumeter.set_value(audio_level);
|
vumeter.set_value(audio_level);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MicTXView::on_tx_progress(const uint32_t progress, const bool done) {
|
void MicTXView::on_tx_progress(const bool done) {
|
||||||
(void)progress;
|
// Roger beep played, stop transmitting
|
||||||
(void)done;
|
if (done)
|
||||||
|
set_tx(false);
|
||||||
// Roger beep transmitted, stop transmitting
|
}
|
||||||
set_tx(false);
|
|
||||||
|
void MicTXView::configure_baseband() {
|
||||||
|
baseband::set_audiotx_data(
|
||||||
|
sampling_rate / 20, // Update vu-meter at 20Hz
|
||||||
|
transmitting ? transmitter_model.channel_bandwidth() : 0,
|
||||||
|
mic_gain_x10,
|
||||||
|
transmitting ? tone_key_enabled : false,
|
||||||
|
TONES_F2D(tone_keys[tone_key_index].second)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MicTXView::set_tx(bool enable) {
|
void MicTXView::set_tx(bool enable) {
|
||||||
uint32_t ctcss_index;
|
|
||||||
bool ctcss_enabled;
|
|
||||||
|
|
||||||
if (enable) {
|
if (enable) {
|
||||||
ctcss_index = options_ctcss.selected_index();
|
transmitting = true;
|
||||||
|
configure_baseband();
|
||||||
if (ctcss_index) {
|
|
||||||
ctcss_enabled = true;
|
|
||||||
ctcss_index--;
|
|
||||||
} else
|
|
||||||
ctcss_enabled = false;
|
|
||||||
|
|
||||||
baseband::set_audiotx_data(
|
|
||||||
1536000U / 20, // 20Hz level update
|
|
||||||
transmitter_model.channel_bandwidth(),
|
|
||||||
mic_gain_x10,
|
|
||||||
ctcss_enabled,
|
|
||||||
(uint32_t)((ctcss_tones[ctcss_index].frequency / 1536000.0) * 0xFFFFFFFFULL)
|
|
||||||
);
|
|
||||||
gpio_tx.write(1);
|
gpio_tx.write(1);
|
||||||
led_tx.on();
|
led_tx.on();
|
||||||
transmitting = true;
|
|
||||||
} else {
|
} else {
|
||||||
if (transmitting && rogerbeep_enabled) {
|
if (transmitting && rogerbeep_enabled) {
|
||||||
baseband::request_beep();
|
baseband::request_beep();
|
||||||
|
transmitting = false;
|
||||||
} else {
|
} else {
|
||||||
baseband::set_audiotx_data(
|
transmitting = false;
|
||||||
1536000U / 20, // 20Hz level update
|
configure_baseband();
|
||||||
0, // BW 0 = TX off
|
|
||||||
mic_gain_x10,
|
|
||||||
false, // Ignore CTCSS
|
|
||||||
0
|
|
||||||
);
|
|
||||||
gpio_tx.write(0);
|
gpio_tx.write(0);
|
||||||
led_tx.off();
|
led_tx.off();
|
||||||
}
|
}
|
||||||
transmitting = false;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -106,7 +93,7 @@ void MicTXView::do_timing() {
|
|||||||
attack_timer = 0;
|
attack_timer = 0;
|
||||||
set_tx(true);
|
set_tx(true);
|
||||||
} else {
|
} else {
|
||||||
attack_timer += ((256 * 1000) / 60); // 1 frame @ 60fps in ms .8 fixed point
|
attack_timer += lcd_frame_duration;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
attack_timer = 0;
|
attack_timer = 0;
|
||||||
@ -119,16 +106,16 @@ void MicTXView::do_timing() {
|
|||||||
attack_timer = 0;
|
attack_timer = 0;
|
||||||
set_tx(false);
|
set_tx(false);
|
||||||
} else {
|
} else {
|
||||||
decay_timer += ((256 * 1000) / 60); // 1 frame @ 60fps in ms .8 fixed point
|
decay_timer += lcd_frame_duration;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
decay_timer = 0;
|
decay_timer = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// PTT disable :(
|
// Check for PTT release
|
||||||
const auto switches_state = get_switches_state();
|
const auto switches_state = get_switches_state();
|
||||||
if (!switches_state[1] && transmitting) // Left button
|
if (!switches_state[0] && transmitting) // Right button
|
||||||
set_tx(false);
|
set_tx(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -155,17 +142,26 @@ MicTXView::MicTXView(
|
|||||||
&field_va_decay,
|
&field_va_decay,
|
||||||
&field_bw,
|
&field_bw,
|
||||||
&field_frequency,
|
&field_frequency,
|
||||||
&options_ctcss,
|
&options_tone_key,
|
||||||
&check_rogerbeep,
|
&check_rogerbeep,
|
||||||
&text_ptt,
|
&text_ptt
|
||||||
&button_exit
|
|
||||||
});
|
});
|
||||||
|
|
||||||
ctcss_populate(options_ctcss);
|
tone_keys_populate(options_tone_key);
|
||||||
options_ctcss.set_selected_index(0);
|
options_tone_key.on_change = [this](size_t i, int32_t) {
|
||||||
|
tone_key_index = i;
|
||||||
|
|
||||||
|
if (tone_key_index) {
|
||||||
|
tone_key_enabled = true;
|
||||||
|
tone_key_index--;
|
||||||
|
} else
|
||||||
|
tone_key_enabled = false;
|
||||||
|
};
|
||||||
|
options_tone_key.set_selected_index(0);
|
||||||
|
|
||||||
options_gain.on_change = [this](size_t, int32_t v) {
|
options_gain.on_change = [this](size_t, int32_t v) {
|
||||||
mic_gain_x10 = v;
|
mic_gain_x10 = v;
|
||||||
|
configure_baseband();
|
||||||
};
|
};
|
||||||
options_gain.set_selected_index(1); // x1.0
|
options_gain.set_selected_index(1); // x1.0
|
||||||
|
|
||||||
@ -214,21 +210,17 @@ MicTXView::MicTXView(
|
|||||||
field_va_decay.on_change = [this](int32_t v) {
|
field_va_decay.on_change = [this](int32_t v) {
|
||||||
decay_ms = v;
|
decay_ms = v;
|
||||||
};
|
};
|
||||||
field_va_decay.set_value(2000);
|
field_va_decay.set_value(1000);
|
||||||
|
|
||||||
button_exit.on_select = [&nav](Button&){
|
|
||||||
nav.pop();
|
|
||||||
};
|
|
||||||
|
|
||||||
// Run baseband as soon as the app starts to get audio levels without transmitting (rf amp off)
|
// Run baseband as soon as the app starts to get audio levels without transmitting (rf amp off)
|
||||||
transmitter_model.set_sampling_rate(1536000U);
|
transmitter_model.set_sampling_rate(sampling_rate);
|
||||||
transmitter_model.set_rf_amp(true);
|
transmitter_model.set_rf_amp(true);
|
||||||
transmitter_model.set_baseband_bandwidth(1750000);
|
transmitter_model.set_baseband_bandwidth(1750000);
|
||||||
transmitter_model.enable();
|
transmitter_model.enable();
|
||||||
|
|
||||||
set_tx(false);
|
set_tx(false);
|
||||||
|
|
||||||
audio::set_rate(audio::Rate::Hz_24000);
|
audio::set_rate(audio::Rate::Hz_48000);
|
||||||
audio::input::start();
|
audio::input::start();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -28,10 +28,10 @@
|
|||||||
#include "ui_widget.hpp"
|
#include "ui_widget.hpp"
|
||||||
#include "ui_navigation.hpp"
|
#include "ui_navigation.hpp"
|
||||||
#include "ui_font_fixed_8x16.hpp"
|
#include "ui_font_fixed_8x16.hpp"
|
||||||
#include "message.hpp"
|
|
||||||
#include "ui_receiver.hpp"
|
#include "ui_receiver.hpp"
|
||||||
#include "transmitter_model.hpp"
|
#include "transmitter_model.hpp"
|
||||||
#include "ctcss.hpp"
|
#include "tone_key.hpp"
|
||||||
|
#include "message.hpp"
|
||||||
|
|
||||||
namespace ui {
|
namespace ui {
|
||||||
|
|
||||||
@ -49,7 +49,7 @@ public:
|
|||||||
|
|
||||||
// PTT: Enable through KeyEvent (only works with presses), disable by polling :(
|
// PTT: Enable through KeyEvent (only works with presses), disable by polling :(
|
||||||
bool on_key(const KeyEvent key) {
|
bool on_key(const KeyEvent key) {
|
||||||
if ((key == KeyEvent::Left) && (!va_enabled)) {
|
if ((key == KeyEvent::Right) && (!va_enabled)) {
|
||||||
set_tx(true);
|
set_tx(true);
|
||||||
return true;
|
return true;
|
||||||
} else
|
} else
|
||||||
@ -59,16 +59,21 @@ public:
|
|||||||
std::string title() const override { return "Microphone TX"; };
|
std::string title() const override { return "Microphone TX"; };
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
static constexpr uint32_t sampling_rate = 1536000U;
|
||||||
|
static constexpr uint32_t lcd_frame_duration = (256 * 1000UL) / 60; // 1 frame @ 60fps in ms .8 fixed point
|
||||||
|
|
||||||
void update_vumeter();
|
void update_vumeter();
|
||||||
void do_timing();
|
void do_timing();
|
||||||
void set_tx(bool enable);
|
void set_tx(bool enable);
|
||||||
void on_tuning_frequency_changed(rf::Frequency f);
|
void on_tuning_frequency_changed(rf::Frequency f);
|
||||||
void on_ctcss_changed(uint32_t v);
|
void on_tx_progress(const bool done);
|
||||||
void on_tx_progress(const uint32_t progress, const bool done);
|
void configure_baseband();
|
||||||
|
|
||||||
bool transmitting { false };
|
bool transmitting { false };
|
||||||
bool va_enabled { };
|
bool va_enabled { };
|
||||||
bool rogerbeep_enabled { };
|
bool rogerbeep_enabled { };
|
||||||
|
uint32_t tone_key_index { };
|
||||||
|
bool tone_key_enabled { };
|
||||||
uint32_t mic_gain_x10 { };
|
uint32_t mic_gain_x10 { };
|
||||||
uint32_t audio_level { 0 };
|
uint32_t audio_level { 0 };
|
||||||
uint32_t va_level { };
|
uint32_t va_level { };
|
||||||
@ -79,18 +84,17 @@ private:
|
|||||||
|
|
||||||
Labels labels {
|
Labels labels {
|
||||||
{ { 7 * 8, 1 * 8 }, "Mic. gain:", Color::light_grey() },
|
{ { 7 * 8, 1 * 8 }, "Mic. gain:", Color::light_grey() },
|
||||||
{ { 7 * 8, 4 * 8 }, "Voice activation:", Color::light_grey() },
|
{ { 7 * 8, 4 * 8 }, "Frequency:", Color::light_grey() },
|
||||||
{ { 8 * 8, 9 * 8 }, "Level: /255", Color::light_grey() },
|
{ { 7 * 8, 6 * 8 }, "Bandwidth: kHz", Color::light_grey() },
|
||||||
{ { 8 * 8, 11 * 8 }, "Attack: ms", Color::light_grey() },
|
{ { 9 * 8, 13 * 8 }, "Level: /255", Color::light_grey() },
|
||||||
{ { 8 * 8, 13 * 8 }, "Decay: ms", Color::light_grey() },
|
{ { 9 * 8, 15 * 8 }, "Attack: ms", Color::light_grey() },
|
||||||
{ { 7 * 8, 17 * 8 }, "Bandwidth: kHz", Color::light_grey() },
|
{ { 9 * 8, 17 * 8 }, "Decay: ms", Color::light_grey() },
|
||||||
{ { 7 * 8, 19 * 8 }, "Frequency:", Color::light_grey() },
|
{ { 7 * 8, 21 * 8 }, "Tone key:", Color::light_grey() }
|
||||||
{ { 11 * 8, 21 * 8 }, "CTCSS:", Color::light_grey() }
|
|
||||||
};
|
};
|
||||||
|
|
||||||
VuMeter vumeter {
|
VuMeter vumeter {
|
||||||
{ 1 * 8, 2 * 8, 5 * 8, 26 * 8 },
|
{ 1 * 8, 2 * 8, 5 * 8, 32 * 8 },
|
||||||
16,
|
20,
|
||||||
false
|
false
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -105,67 +109,62 @@ private:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
FrequencyField field_frequency {
|
||||||
|
{ 17 * 8, 4 * 8 },
|
||||||
|
};
|
||||||
|
NumberField field_bw {
|
||||||
|
{ 17 * 8, 6 * 8 },
|
||||||
|
3,
|
||||||
|
{ 0, 150 },
|
||||||
|
1,
|
||||||
|
' '
|
||||||
|
};
|
||||||
|
|
||||||
Checkbox check_va {
|
Checkbox check_va {
|
||||||
{ 8 * 8, 6 * 8 },
|
{ 7 * 8, 10 * 8 },
|
||||||
7,
|
7,
|
||||||
"Enabled",
|
"Voice activation",
|
||||||
false
|
false
|
||||||
};
|
};
|
||||||
|
|
||||||
NumberField field_va_level {
|
NumberField field_va_level {
|
||||||
{ 14 * 8, 9 * 8 },
|
{ 15 * 8, 13 * 8 },
|
||||||
3,
|
3,
|
||||||
{ 0, 255 },
|
{ 0, 255 },
|
||||||
2,
|
2,
|
||||||
' '
|
' '
|
||||||
};
|
};
|
||||||
NumberField field_va_attack {
|
NumberField field_va_attack {
|
||||||
{ 15 * 8, 11 * 8 },
|
{ 16 * 8, 15 * 8 },
|
||||||
3,
|
3,
|
||||||
{ 0, 999 },
|
{ 0, 999 },
|
||||||
20,
|
20,
|
||||||
' '
|
' '
|
||||||
};
|
};
|
||||||
NumberField field_va_decay {
|
NumberField field_va_decay {
|
||||||
{ 14 * 8, 13 * 8 },
|
{ 15 * 8, 17 * 8 },
|
||||||
4,
|
4,
|
||||||
{ 0, 9999 },
|
{ 0, 9999 },
|
||||||
100,
|
100,
|
||||||
' '
|
' '
|
||||||
};
|
};
|
||||||
|
|
||||||
NumberField field_bw {
|
OptionsField options_tone_key {
|
||||||
{ 17 * 8, 17 * 8 },
|
{ 7 * 8, 23 * 8 },
|
||||||
3,
|
23,
|
||||||
{ 0, 150 },
|
|
||||||
1,
|
|
||||||
' '
|
|
||||||
};
|
|
||||||
FrequencyField field_frequency {
|
|
||||||
{ 17 * 8, 19 * 8 },
|
|
||||||
};
|
|
||||||
|
|
||||||
OptionsField options_ctcss {
|
|
||||||
{ 17 * 8, 21 * 8 },
|
|
||||||
8,
|
|
||||||
{ }
|
{ }
|
||||||
};
|
};
|
||||||
|
|
||||||
Checkbox check_rogerbeep {
|
Checkbox check_rogerbeep {
|
||||||
{ 8 * 8, 23 * 8 },
|
{ 7 * 8, 26 * 8 },
|
||||||
10,
|
10,
|
||||||
"Roger beep",
|
"Roger beep",
|
||||||
false
|
false
|
||||||
};
|
};
|
||||||
|
|
||||||
Text text_ptt {
|
Text text_ptt {
|
||||||
{ 7 * 8, 28 * 8, 16 * 8, 16 },
|
{ 7 * 8, 17 * 16, 16 * 8, 16 },
|
||||||
"PTT: LEFT BUTTON"
|
"PTT: RIGHT BUTTON"
|
||||||
};
|
|
||||||
|
|
||||||
Button button_exit {
|
|
||||||
{ 18 * 8, 32 * 8, 10 * 8, 40 },
|
|
||||||
"Exit"
|
|
||||||
};
|
};
|
||||||
|
|
||||||
MessageHandlerRegistration message_handler_lcd_sync {
|
MessageHandlerRegistration message_handler_lcd_sync {
|
||||||
@ -188,7 +187,7 @@ private:
|
|||||||
Message::ID::TXProgress,
|
Message::ID::TXProgress,
|
||||||
[this](const Message* const p) {
|
[this](const Message* const p) {
|
||||||
const auto message = *reinterpret_cast<const TXProgressMessage*>(p);
|
const auto message = *reinterpret_cast<const TXProgressMessage*>(p);
|
||||||
this->on_tx_progress(message.progress, message.done);
|
this->on_tx_progress(message.done);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
@ -27,7 +27,7 @@
|
|||||||
#include "lfsr_random.hpp"
|
#include "lfsr_random.hpp"
|
||||||
#include "string_format.hpp"
|
#include "string_format.hpp"
|
||||||
|
|
||||||
using namespace ctcss;
|
using namespace tonekey;
|
||||||
using namespace portapack;
|
using namespace portapack;
|
||||||
|
|
||||||
namespace ui {
|
namespace ui {
|
||||||
@ -95,8 +95,8 @@ void SoundBoardView::on_tuning_frequency_changed(rf::Frequency f) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void SoundBoardView::play_sound(uint16_t id) {
|
void SoundBoardView::play_sound(uint16_t id) {
|
||||||
uint32_t ctcss_index;
|
uint32_t tone_key_index;
|
||||||
bool ctcss_enabled;
|
bool tone_key_enabled;
|
||||||
uint32_t divider;
|
uint32_t divider;
|
||||||
|
|
||||||
if (sounds[id].size == 0) return;
|
if (sounds[id].size == 0) return;
|
||||||
@ -119,13 +119,13 @@ void SoundBoardView::play_sound(uint16_t id) {
|
|||||||
transmitter_model.set_baseband_bandwidth(1750000);
|
transmitter_model.set_baseband_bandwidth(1750000);
|
||||||
transmitter_model.enable();
|
transmitter_model.enable();
|
||||||
|
|
||||||
ctcss_index = options_ctcss.selected_index();
|
tone_key_index = options_tone_key.selected_index();
|
||||||
|
|
||||||
if (ctcss_index) {
|
if (tone_key_index) {
|
||||||
ctcss_enabled = true;
|
tone_key_enabled = true;
|
||||||
ctcss_index--;
|
tone_key_index--;
|
||||||
} else
|
} else
|
||||||
ctcss_enabled = false;
|
tone_key_enabled = false;
|
||||||
|
|
||||||
divider = (1536000 / sounds[id].sample_rate) - 1;
|
divider = (1536000 / sounds[id].sample_rate) - 1;
|
||||||
|
|
||||||
@ -133,8 +133,8 @@ void SoundBoardView::play_sound(uint16_t id) {
|
|||||||
divider,
|
divider,
|
||||||
number_bw.value() * 1000,
|
number_bw.value() * 1000,
|
||||||
1,
|
1,
|
||||||
ctcss_enabled,
|
tone_key_enabled,
|
||||||
(uint32_t)((ctcss_tones[ctcss_index].frequency / 1536000.0) * 0xFFFFFFFFULL)
|
(uint32_t)((tone_keys[tone_key_index].second / 1536000.0) * 0xFFFFFFFFULL)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -230,7 +230,7 @@ SoundBoardView::SoundBoardView(
|
|||||||
&field_frequency,
|
&field_frequency,
|
||||||
&number_bw,
|
&number_bw,
|
||||||
&text_kHz,
|
&text_kHz,
|
||||||
&options_ctcss,
|
&options_tone_key,
|
||||||
&text_title,
|
&text_title,
|
||||||
&text_page,
|
&text_page,
|
||||||
&text_duration,
|
&text_duration,
|
||||||
@ -240,8 +240,8 @@ SoundBoardView::SoundBoardView(
|
|||||||
&button_exit
|
&button_exit
|
||||||
});
|
});
|
||||||
|
|
||||||
ctcss_populate(options_ctcss);
|
tone_keys_populate(options_tone_key);
|
||||||
options_ctcss.set_selected_index(0);
|
options_tone_key.set_selected_index(0);
|
||||||
|
|
||||||
const auto button_fn = [this](Button& button) {
|
const auto button_fn = [this](Button& button) {
|
||||||
tx_mode = NORMAL;
|
tx_mode = NORMAL;
|
||||||
|
@ -29,7 +29,7 @@
|
|||||||
#include "baseband_api.hpp"
|
#include "baseband_api.hpp"
|
||||||
#include "ui_receiver.hpp"
|
#include "ui_receiver.hpp"
|
||||||
#include "io_wave.hpp"
|
#include "io_wave.hpp"
|
||||||
#include "ctcss.hpp"
|
#include "tone_key.hpp"
|
||||||
|
|
||||||
namespace ui {
|
namespace ui {
|
||||||
|
|
||||||
@ -132,7 +132,7 @@ private:
|
|||||||
"k CTCSS:"
|
"k CTCSS:"
|
||||||
};
|
};
|
||||||
|
|
||||||
OptionsField options_ctcss {
|
OptionsField options_tone_key {
|
||||||
{ 21 * 8, 4 },
|
{ 21 * 8, 4 },
|
||||||
8,
|
8,
|
||||||
{ }
|
{ }
|
||||||
|
@ -36,10 +36,10 @@ void MicTXProcessor::execute(const buffer_c8_t& buffer){
|
|||||||
|
|
||||||
audio_input.read_audio_buffer(audio_buffer);
|
audio_input.read_audio_buffer(audio_buffer);
|
||||||
|
|
||||||
for (size_t i = 0; i<buffer.count; i++) {
|
for (size_t i = 0; i < buffer.count; i++) {
|
||||||
|
|
||||||
if (!play_beep) {
|
if (!play_beep) {
|
||||||
sample = audio_buffer.p[i >> 6] >> 8; // 1536000 / 64 = 24000
|
sample = audio_buffer.p[i >> 5] >> 8; // 1536000 / 32 = 48000
|
||||||
sample = (sample * (int32_t)gain_x10) / 10;
|
sample = (sample * (int32_t)gain_x10) / 10;
|
||||||
|
|
||||||
power += (sample < 0) ? -sample : sample; // Power average for UI vu-meter
|
power += (sample < 0) ? -sample : sample; // Power average for UI vu-meter
|
||||||
@ -56,10 +56,10 @@ void MicTXProcessor::execute(const buffer_c8_t& buffer){
|
|||||||
if (beep_timer) {
|
if (beep_timer) {
|
||||||
beep_timer--;
|
beep_timer--;
|
||||||
} else {
|
} else {
|
||||||
beep_timer = 76800; // 50ms @ 1536000Hz
|
beep_timer = 76800; // 50ms @ 1536000Hz
|
||||||
if (beep_index == BEEP_TONES_NB) {
|
if (beep_index == BEEP_TONES_NB) {
|
||||||
configured = false;
|
configured = false;
|
||||||
fm_delta = 0; // Zero-out the IQ output for the rest of the buffer
|
fm_delta = 0; // Zero-out the IQ output for the rest of the buffer
|
||||||
shared_memory.application_queue.push(txprogress_message);
|
shared_memory.application_queue.push(txprogress_message);
|
||||||
} else {
|
} else {
|
||||||
beep_phase_inc = beep_deltas[beep_index];
|
beep_phase_inc = beep_deltas[beep_index];
|
||||||
@ -102,7 +102,7 @@ void MicTXProcessor::on_message(const Message* const msg) {
|
|||||||
|
|
||||||
switch(msg->id) {
|
switch(msg->id) {
|
||||||
case Message::ID::AudioTXConfig:
|
case Message::ID::AudioTXConfig:
|
||||||
fm_delta = config_message.fm_delta * (0xFFFFFFULL / 1536000);
|
fm_delta = config_message.fm_delta * (0xFFFFFFULL / baseband_fs);
|
||||||
gain_x10 = config_message.gain_x10;
|
gain_x10 = config_message.gain_x10;
|
||||||
divider = config_message.divider;
|
divider = config_message.divider;
|
||||||
ctcss_enabled = config_message.ctcss_enabled;
|
ctcss_enabled = config_message.ctcss_enabled;
|
||||||
|
@ -34,9 +34,11 @@ public:
|
|||||||
void on_message(const Message* const msg) override;
|
void on_message(const Message* const msg) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
static constexpr size_t baseband_fs = 1536000U;
|
||||||
|
|
||||||
bool configured { false };
|
bool configured { false };
|
||||||
|
|
||||||
BasebandThread baseband_thread { 1536000, this, NORMALPRIO + 20, baseband::Direction::Transmit };
|
BasebandThread baseband_thread { baseband_fs, this, NORMALPRIO + 20, baseband::Direction::Transmit };
|
||||||
|
|
||||||
int16_t audio_data[64];
|
int16_t audio_data[64];
|
||||||
buffer_s16_t audio_buffer {
|
buffer_s16_t audio_buffer {
|
||||||
|
@ -1650,8 +1650,8 @@ void VuMeter::paint(Painter& painter) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Draw mark
|
// Draw mark (forced refresh)
|
||||||
if ((mark != prev_mark) && (mark)) {
|
if (mark) {
|
||||||
painter.draw_hline({ marks_x, bottom - (height * prev_mark) / 256 }, 8, Color::black());
|
painter.draw_hline({ marks_x, bottom - (height * prev_mark) / 256 }, 8, Color::black());
|
||||||
painter.draw_hline({ marks_x, bottom - (height * mark) / 256 }, 8, Color::grey());
|
painter.draw_hline({ marks_x, bottom - (height * mark) / 256 }, 8, Color::grey());
|
||||||
prev_mark = mark;
|
prev_mark = mark;
|
||||||
|
Binary file not shown.
Loading…
Reference in New Issue
Block a user