Compare commits

...

15 Commits

Author SHA1 Message Date
Brumi-2021 a1496c1b79 Allowing to hear Mic at TX time with Receiver ON (#1522) 2023-10-22 01:13:32 +02:00
Brumi-2021 1b73a138b6 Mic to hp refactoring (#1521)
* Refactoring previous "Hear Mic" PR

* Missed file
2023-10-21 17:31:17 +02:00
Brumi-2021 efcedd9005 Add "Hear Mic" feature to the Mic App (#1518)
* Add "Hear Mic" feature to the Mic App

* Following consensus change about ternary operators
2023-10-20 18:43:22 -05:00
Mark Thompson 86d4b17257 Simple amplification option in IQ Trim app (#1506)
* Add files via upload

* Add files via upload

* Add files via upload

* Add files via upload

* Add files via upload

* Add files via upload
2023-10-19 20:14:25 +02:00
Mark Thompson f6a437f7fb Create SETTINGS folder if one does not exist (#1512)
* Add files via upload

* Add files via upload

* Add files via upload

* Add files via upload

* Add files via upload

* Add files via upload
2023-10-19 20:09:49 +02:00
jLynx 3db8a5ac5b Stable v1.8.0 release (#1504)
* Update version.txt

* Update past_version.txt
2023-10-17 15:20:40 +13:00
Mark Thompson 266a626acf POCSAG TX default freq (#1503)
* Changed name for blacklist
* Set default POCSAG TX freq to same as in POCSAG RX
2023-10-16 21:32:07 +02:00
Mark Thompson 411e2fb93a Hide unwanted apps by naming them in SETTINGS/blacklist file (#1502)
* Add files via upload

* Add files via upload

* Add files via upload

* Add files via upload

* Changed some app name strings for blacklist
2023-10-15 18:04:26 -05:00
Mark Thompson 6ed83c08e3 Renamed .ini file for Burger Pager app (#1500) 2023-10-14 21:08:39 +02:00
Mark Thompson 9929376acf Added Freq to Radio State, only update specified App Settings, always Load/Save Settings (#1498)
* Add files via upload

* Add files via upload

* Add files via upload

* Add files via upload

* Add files via upload

* Add files via upload

* Add files via upload

* Add files via upload
2023-10-14 11:33:52 -05:00
Mark Thompson 5135b6404d Prevent unnecessary CPLD SRAM load on first RX operation (#1494) 2023-10-14 10:28:44 +02:00
Mark Thompson 790669c242 Added Transmitter settings to 2nd DFU overlay screen (#1497)
* Added Transmitter settings to 2nd DFU overlay
2023-10-14 10:25:40 +02:00
Brumi-2021 4bb8b1882c Error correction. Now comments matching with value (#1496) 2023-10-12 19:56:27 +02:00
Brumi-2021 56702ca7c2 Applying a proper TX_LPF to all remaining TX App (#1495) 2023-10-12 18:02:38 +02:00
Erwin Ried 9be4b9596d Update README.md (#1491)
Changing the introductory video with a newer one with a guy with weird danish accented english
2023-10-12 07:57:34 +02:00
80 changed files with 400 additions and 231 deletions
+1 -1
View File
@@ -1 +1 @@
v1.7.3
v1.7.4
+1 -1
View File
@@ -1 +1 @@
v1.7.4
v1.8.0
+3 -3
View File
@@ -8,11 +8,11 @@ This is a fork of the [Havoc](https://github.com/furrtek/portapack-havoc/) firmw
*[PortaPack H2+HackRF+battery](https://s.click.aliexpress.com/e/_DmU7GQX) (clone) with a custom [3d printed case](https://github.com/eried/portapack-mayhem/wiki/H2-Enclosure)*
# Quick overview
# What is this?
If you are new to *HackRF+PortaPack+Mayhem*, there is an awesome introductory video by [Tech Minds](https://www.youtube.com/channel/UC9a8Z6Sp6eb2s3O79pX5Zvg) available:
If you are new to *HackRF+PortaPack+Mayhem*, check this video:
[![Setup and overview](https://img.youtube.com/vi/kjFB58Y1TAo/0.jpg)](https://www.youtube.com/watch?v=kjFB58Y1TAo)
[![What is?](https://img.youtube.com/vi/alrFbY5vxt4/0.jpg)](https://www.youtube.com/watch?v=alrFbY5vxt4)
# Frequently Asked Questions
+36 -39
View File
@@ -156,6 +156,7 @@ bool save_settings(std::string_view store_name, const SettingBindings& bindings)
File f;
auto path = get_settings_path(std::string{store_name});
make_new_directory(SETTINGS_DIR);
auto error = f.create(path);
if (error)
return false;
@@ -244,8 +245,7 @@ SettingsManager::SettingsManager(
: app_name_{app_name},
settings_{},
bindings_{},
loaded_{false},
radio_loaded_{false} {
loaded_{false} {
settings_.mode = mode;
settings_.options = options;
@@ -253,53 +253,50 @@ SettingsManager::SettingsManager(
additional_settings.reserve(17 + additional_settings.size());
bindings_ = std::move(additional_settings);
// Additional settings should always be loaded because apps now rely
// on being able to store UI settings, config, etc. The radio settings
// are only loaded if the global option has been enabled.
// Add the radio setting bindings if either load or save are enabled.
if (portapack::persistent_memory::load_app_settings() ||
portapack::persistent_memory::save_app_settings()) {
// Transmitter model settings.
if (flags_enabled(mode, Mode::TX)) {
bindings_.emplace_back("tx_frequency"sv, &settings_.tx_frequency);
bindings_.emplace_back("tx_amp"sv, &settings_.tx_amp);
bindings_.emplace_back("tx_gain"sv, &settings_.tx_gain);
bindings_.emplace_back("channel_bandwidth"sv, &settings_.channel_bandwidth);
}
// Settings should always be loaded because apps now rely
// on being able to store UI settings, config, etc.
// Receiver model settings.
if (flags_enabled(mode, Mode::RX)) {
bindings_.emplace_back("rx_frequency"sv, &settings_.rx_frequency);
bindings_.emplace_back("lna"sv, &settings_.lna);
bindings_.emplace_back("vga"sv, &settings_.vga);
bindings_.emplace_back("rx_amp"sv, &settings_.rx_amp);
bindings_.emplace_back("modulation"sv, &settings_.modulation);
bindings_.emplace_back("am_config_index"sv, &settings_.am_config_index);
bindings_.emplace_back("nbfm_config_index"sv, &settings_.nbfm_config_index);
bindings_.emplace_back("wfm_config_index"sv, &settings_.wfm_config_index);
bindings_.emplace_back("squelch"sv, &settings_.squelch);
}
// Common model settings.
bindings_.emplace_back("baseband_bandwidth"sv, &settings_.baseband_bandwidth);
bindings_.emplace_back("sampling_rate"sv, &settings_.sampling_rate);
bindings_.emplace_back("step"sv, &settings_.step);
bindings_.emplace_back("volume"sv, &settings_.volume);
// Transmitter model settings.
if (flags_enabled(mode, Mode::TX)) {
bindings_.emplace_back("tx_frequency"sv, &settings_.tx_frequency);
bindings_.emplace_back("tx_amp"sv, &settings_.tx_amp);
bindings_.emplace_back("tx_gain"sv, &settings_.tx_gain);
bindings_.emplace_back("channel_bandwidth"sv, &settings_.channel_bandwidth);
}
// Receiver model settings.
if (flags_enabled(mode, Mode::RX)) {
bindings_.emplace_back("rx_frequency"sv, &settings_.rx_frequency);
bindings_.emplace_back("lna"sv, &settings_.lna);
bindings_.emplace_back("vga"sv, &settings_.vga);
bindings_.emplace_back("rx_amp"sv, &settings_.rx_amp);
bindings_.emplace_back("modulation"sv, &settings_.modulation);
bindings_.emplace_back("am_config_index"sv, &settings_.am_config_index);
bindings_.emplace_back("nbfm_config_index"sv, &settings_.nbfm_config_index);
bindings_.emplace_back("wfm_config_index"sv, &settings_.wfm_config_index);
bindings_.emplace_back("squelch"sv, &settings_.squelch);
}
// Common model settings.
bindings_.emplace_back("baseband_bandwidth"sv, &settings_.baseband_bandwidth);
bindings_.emplace_back("sampling_rate"sv, &settings_.sampling_rate);
bindings_.emplace_back("step"sv, &settings_.step);
bindings_.emplace_back("volume"sv, &settings_.volume);
// RadioState should have initialized default radio parameters before this function;
// copy them to settings_ before checking settings .ini file (in case the file doesn't exist
// or doesn't include all parameters). Settings in the file can overwrite all, or a subset of parameters.
copy_from_radio_model(settings_);
loaded_ = load_settings(app_name_, bindings_);
// Only copy to the radio if load was successful.
if (loaded_ && portapack::persistent_memory::load_app_settings()) {
radio_loaded_ = true;
if (loaded_)
copy_to_radio_model(settings_);
}
}
SettingsManager::~SettingsManager() {
// Only save radio settings when the option is enabled.
if (portapack::persistent_memory::save_app_settings())
copy_from_radio_model(settings_);
copy_from_radio_model(settings_);
save_settings(app_name_, bindings_);
}
+3 -3
View File
@@ -36,6 +36,9 @@
#include "max283x.hpp"
#include "string_format.hpp"
// Folder to store app settings, pmem_fileflag, and date_fileflag
#define SETTINGS_DIR u"/SETTINGS"
// Bring in the string_view literal.
using std::literals::operator""sv;
@@ -170,8 +173,6 @@ class SettingsManager {
/* True if settings were successfully loaded from file. */
bool loaded() const { return loaded_; }
/* True if radio settings were successfully loaded from file. */
bool radio_loaded() const { return radio_loaded_; }
Mode mode() const { return settings_.mode; }
AppSettings& raw() { return settings_; }
@@ -181,7 +182,6 @@ class SettingsManager {
AppSettings settings_;
SettingBindings bindings_;
bool loaded_;
bool radio_loaded_;
};
} // namespace app_settings
+2 -1
View File
@@ -60,11 +60,12 @@ class ACARSAppView : public View {
private:
NavigationView& nav_;
RxRadioState radio_state_{
131550000 /* frequency */,
1750000 /* bandwidth */,
2457600 /* sampling rate */
};
app_settings::SettingsManager settings_{
"rx_acars.hpp", app_settings::Mode::RX};
"rx_acars", app_settings::Mode::RX};
bool logging{false};
uint32_t packet_counter{0};
-3
View File
@@ -382,9 +382,6 @@ AISAppView::AISAppView(NavigationView& nav)
recent_entry_detail_view.hidden(true);
if (!settings_.radio_loaded())
receiver_model.set_target_frequency(initial_target_frequency);
receiver_model.enable();
options_channel.on_change = [this](size_t, OptionsField::value_t v) {
+1 -2
View File
@@ -162,9 +162,8 @@ class AISAppView : public View {
std::string title() const override { return "AIS RX"; };
private:
static constexpr uint32_t initial_target_frequency = 162025000;
RxRadioState radio_state_{
162025000 /* frequency*/,
1750000 /* bandwidth */,
2457600 /* sampling rate */
};
-3
View File
@@ -110,9 +110,6 @@ ERTAppView::ERTAppView(NavigationView&) {
&recent_entries_view,
});
if (!settings_.radio_loaded())
receiver_model.set_target_frequency(initial_target_frequency);
receiver_model.enable();
logger = std::make_unique<ERTLogger>();
+1 -2
View File
@@ -123,12 +123,11 @@ class ERTAppView : public View {
std::string title() const override { return "ERT RX"; };
private:
static constexpr uint32_t initial_target_frequency = 911600000;
ERTRecentEntries recent{};
std::unique_ptr<ERTLogger> logger{};
RxRadioState radio_state_{
911600000 /* frequency */,
2500000 /* bandwidth */,
4194304 /* sampling rate */};
app_settings::SettingsManager settings_{
@@ -176,13 +176,6 @@ GpsSimAppView::GpsSimAppView(
&waterfall,
});
transmitter_model.set_baseband_bandwidth(15'000'000); // GPS L1 signal use to have wide band spectrum, still with lobule energy -30dB's at + - 15 Mhz
if (!settings_.radio_loaded()) {
field_frequency.set_value(initial_target_frequency);
transmitter_model.set_sampling_rate(2600000);
}
field_frequency.set_step(5000);
button_play.on_select = [this](ImageButton&) {
+4 -8
View File
@@ -51,21 +51,17 @@ class GpsSimAppView : public View {
std::string title() const override { return "GPS Sim TX"; };
private:
static constexpr uint32_t initial_target_frequency = 1575420000;
NavigationView& nav_;
RxRadioState radio_state_{
3000000 /* bandwidth */,
500000 /* sampling rate */
TxRadioState radio_state_{
1575420000 /* frequency */,
15000000 /* bandwidth */,
2600000 /* sampling rate */
};
app_settings::SettingsManager settings_{
"tx_gps", app_settings::Mode::TX};
static constexpr ui::Dim header_height = 3 * 16;
int32_t tx_gain{47};
bool rf_amp{true}; // aux private var to store temporal, same as Replay App rf_amp user selection.
static constexpr uint32_t baseband_bandwidth = 3000000; // filter bandwidth
const size_t read_size{16384};
const size_t buffer_count{3};
+4
View File
@@ -238,6 +238,10 @@ void LGEView::start_tx() {
tx_view.set_dirty();
}
/* By experimental test, previous fw 1.7.4 seems to have setting , tx LPF = 5Mhz
This LGE - seems to be for controlling a "laser tag equipment" (Havoc app) , modulated FSK , low bauds,
and using max GUI fm dev 150k , we are still in NBFM, let's reduce slightly original TX LPF 5M ->2M5*/
transmitter_model.set_baseband_bandwidth(2'500'000);
transmitter_model.enable();
chThdSleep(100);
+1
View File
@@ -51,6 +51,7 @@ class LGEView : public View {
};
TxRadioState radio_state_{
868067000 /* frequency */,
1750000 /* bandwidth */,
2280000 /* sampling rate */
};
-3
View File
@@ -114,9 +114,6 @@ POCSAGAppView::POCSAGAppView(NavigationView& nav)
? FILTER_NONE
: FILTER_DROP;
}
if (!app_settings_.radio_loaded()) {
field_frequency.set_value(initial_target_frequency);
}
logger.append(LOG_ROOT_DIR "/POCSAG.TXT");
+5 -2
View File
@@ -197,14 +197,17 @@ class POCSAGAppView : public View {
void focus() override;
private:
static constexpr uint32_t initial_target_frequency = 466'175'000;
bool logging() const { return settings_.enable_logging; };
bool logging_raw() const { return settings_.enable_raw_log; };
bool hide_bad_data() const { return settings_.hide_bad_data; };
bool hide_addr_only() const { return settings_.hide_addr_only; };
NavigationView& nav_;
RxRadioState radio_state_{};
RxRadioState radio_state_{
466175000 /* frequency*/,
max283x::filter::bandwidth_minimum /* bandwidth */,
3072000 /* sampling rate */
};
// Settings
POCSAGSettings settings_{};
@@ -120,7 +120,6 @@ void SoundBoardView::start_tx(const uint32_t id) {
);
baseband::set_sample_rate(sample_rate);
transmitter_model.set_baseband_bandwidth(1'750'000); // the Minimum TX LPF 1M75 is fine.
transmitter_model.enable();
tx_view.set_transmitting(true);
@@ -50,6 +50,7 @@ class SoundBoardView : public View {
private:
TxRadioState radio_state_{
0 /* frequency */,
1750000 /* bandwidth */,
1536000 /* sampling rate */
};
-3
View File
@@ -157,9 +157,6 @@ TPMSAppView::TPMSAppView(NavigationView&) {
&field_vga,
&recent_entries_view});
if (!settings_.radio_loaded())
receiver_model.set_target_frequency(initial_target_frequency);
receiver_model.enable();
options_band.on_change = [this](size_t, OptionsField::value_t v) {
+2 -3
View File
@@ -102,9 +102,8 @@ class TPMSAppView : public View {
std::string title() const override { return "TPMS RX"; };
private:
static constexpr uint32_t initial_target_frequency = 315000000;
RxRadioState radio_state_{
315000000 /* frequency*/,
1750000 /* bandwidth */,
2457600 /* sampling rate */};
app_settings::SettingsManager settings_{
@@ -135,7 +134,7 @@ class TPMSAppView : public View {
3,
{
{"315", 315000000},
{"433", 433920000},
{"434", 433920000},
}};
OptionsField options_pressure{
-1
View File
@@ -521,7 +521,6 @@ ADSBRxView::ADSBRxView(NavigationView& nav) {
baseband::set_adsb();
receiver_model.set_target_frequency(1'090'000'000);
receiver_model.enable();
}
+1
View File
@@ -342,6 +342,7 @@ class ADSBRxView : public View {
private:
RxRadioState radio_state_{
1090000000 /* frequency */,
2500000 /* bandwidth */,
2000000 /* sampling rate */,
ReceiverModel::Mode::SpectrumAnalysis};
-1
View File
@@ -299,7 +299,6 @@ void ADSBTxView::start_tx() {
/* Already tested , with SDR Angel + another Hackrf RX and dump1090 + SDR RLT. Final conclusion is TX LPF 6 Mhz is
* the best settings to fulfill ADSB transponder spectrum mask requirements (<=-20 dB's at +-7Mhz , <=-40 dB's at +-23Mhz )
* and not showing any ADSB data decoding degradation.*/
transmitter_model.set_baseband_bandwidth(6'000'000); // best settings for ADSB TX.
transmitter_model.enable();
baseband::set_adsb();
+2 -1
View File
@@ -203,7 +203,8 @@ class ADSBTxView : public View {
};*/
TxRadioState radio_state_{
10000000 /* bandwidth */,
1090000000 /* frequency */,
6000000 /* bandwidth */,
4000000 /* sampling rate */
};
app_settings::SettingsManager settings_{
+5 -1
View File
@@ -190,7 +190,11 @@ class APRSRxView : public View {
bool reset_console = false;
NavigationView& nav_;
RxRadioState radio_state_{};
RxRadioState radio_state_{
144390000 /* frequency */,
1750000 /* bandwidth */,
3072000 /* sampling rate */
};
app_settings::SettingsManager settings_{
"rx_aprs", app_settings::Mode::RX};
-1
View File
@@ -57,7 +57,6 @@ void APRSTXView::start_tx() {
// uint8_t * bb_data_ptr = shared_memory.bb_data.data;
// text_payload.set(to_string_hex_array(bb_data_ptr + 56, 15));
transmitter_model.set_baseband_bandwidth(1'750'000); // APRS Automatic Packet Reporting System (APRS).AFSK with NBFM , max BW= 12k5 , then TX LPF min 1M75
transmitter_model.enable();
baseband::set_afsk_data(
+1
View File
@@ -46,6 +46,7 @@ class APRSTXView : public View {
private:
TxRadioState radio_state_{
144390000 /* frequency */,
1750000 /* bandwidth */,
AFSK_TX_SAMPLERATE /* sampling rate */
};
-1
View File
@@ -54,7 +54,6 @@ BTLERxView::BTLERxView(NavigationView& nav)
&console});
// Auto-configure modem for LCR RX (TODO: remove later)
field_frequency.set_value(2426000000);
auto def_bell202 = &modem_defs[0];
persistent_memory::set_modem_baudrate(def_bell202->baudrate);
serial_format_t serial_format;
+1
View File
@@ -50,6 +50,7 @@ class BTLERxView : public View {
NavigationView& nav_;
RxRadioState radio_state_{
2426000000 /* frequency */,
4000000 /* bandwidth */,
4000000 /* sampling rate */,
ReceiverModel::Mode::WidebandFMAudio};
@@ -67,7 +67,6 @@ void CoasterPagerView::generate_frame() {
void CoasterPagerView::start_tx() {
generate_frame();
transmitter_model.set_baseband_bandwidth(1'750'000); // AFSK narrowband ,low baud, max FM dev 150khz , std 10khz. TX LPF=1M75 the min.
transmitter_model.enable();
baseband::set_fsk_data(19 * 8, 2280000 / 1000, 5000, 32);
+2 -1
View File
@@ -52,11 +52,12 @@ class CoasterPagerView : public View {
tx_modes tx_mode = IDLE;
TxRadioState radio_state_{
433920000, /* frequency */
1750000 /* bandwidth */,
2280000 /* sampling rate */
};
app_settings::SettingsManager settings_{
"tx_coaster", app_settings::Mode::TX};
"tx_burger", app_settings::Mode::TX};
void start_tx();
void generate_frame();
+7 -3
View File
@@ -92,7 +92,9 @@ DfuMenu2::DfuMenu2(NavigationView& nav)
&text_info_line_5,
&text_info_line_6,
&text_info_line_7,
&text_info_line_8});
&text_info_line_8,
&text_info_line_9,
&text_info_line_10});
}
void DfuMenu2::paint(Painter& painter) {
@@ -103,10 +105,12 @@ void DfuMenu2::paint(Painter& painter) {
text_info_line_5.set(to_string_dec_uint(portapack::receiver_model.am_configuration(), 10));
text_info_line_6.set(to_string_dec_uint(portapack::receiver_model.nbfm_configuration(), 10));
text_info_line_7.set(to_string_dec_uint(portapack::receiver_model.wfm_configuration(), 10));
text_info_line_8.set("");
text_info_line_8.set(to_string_dec_uint(portapack::transmitter_model.target_frequency(), 10));
text_info_line_9.set(to_string_dec_uint(portapack::transmitter_model.baseband_bandwidth(), 10));
text_info_line_10.set(to_string_dec_uint(portapack::transmitter_model.sampling_rate(), 10));
constexpr auto margin = 5;
constexpr auto lines = 8 + 2;
constexpr auto lines = 10 + 2;
painter.fill_rectangle(
{{5 * CHARACTER_WIDTH - margin, 3 * LINE_HEIGHT - margin},
+9 -5
View File
@@ -77,17 +77,19 @@ class DfuMenu2 : public View {
private:
NavigationView& nav_;
Text text_head{{6 * CHARACTER_WIDTH, 3 * LINE_HEIGHT, 8 * CHARACTER_WIDTH, 1 * LINE_HEIGHT}, "Receiver"};
Text text_head{{6 * CHARACTER_WIDTH, 3 * LINE_HEIGHT, 14 * CHARACTER_WIDTH, 1 * LINE_HEIGHT}, "Radio Settings"};
Labels labels{
{{5 * CHARACTER_WIDTH, 5 * LINE_HEIGHT}, "Tgt freq:", Color::dark_cyan()},
{{5 * CHARACTER_WIDTH, 6 * LINE_HEIGHT}, "Bandwidt:", Color::dark_cyan()},
{{5 * CHARACTER_WIDTH, 7 * LINE_HEIGHT}, "Sampl Rt:", Color::dark_cyan()},
{{5 * CHARACTER_WIDTH, 5 * LINE_HEIGHT}, "RX Freq:", Color::dark_cyan()},
{{5 * CHARACTER_WIDTH, 6 * LINE_HEIGHT}, "RX BW:", Color::dark_cyan()},
{{5 * CHARACTER_WIDTH, 7 * LINE_HEIGHT}, "RX SampR:", Color::dark_cyan()},
{{5 * CHARACTER_WIDTH, 8 * LINE_HEIGHT}, "Modulatn:", Color::dark_cyan()},
{{5 * CHARACTER_WIDTH, 9 * LINE_HEIGHT}, "AM cfg:", Color::dark_cyan()},
{{5 * CHARACTER_WIDTH, 10 * LINE_HEIGHT}, "NBFM cfg:", Color::dark_cyan()},
{{5 * CHARACTER_WIDTH, 11 * LINE_HEIGHT}, "WFM cfg:", Color::dark_cyan()},
{{5 * CHARACTER_WIDTH, 12 * LINE_HEIGHT}, "", Color::dark_cyan()}};
{{5 * CHARACTER_WIDTH, 12 * LINE_HEIGHT}, "TX Freq:", Color::dark_cyan()},
{{5 * CHARACTER_WIDTH, 13 * LINE_HEIGHT}, "TX BW:", Color::dark_cyan()},
{{5 * CHARACTER_WIDTH, 14 * LINE_HEIGHT}, "TX SampR:", Color::dark_cyan()}};
Text text_info_line_1{{14 * CHARACTER_WIDTH, 5 * LINE_HEIGHT, 10 * CHARACTER_WIDTH, 1 * LINE_HEIGHT}, ""};
Text text_info_line_2{{14 * CHARACTER_WIDTH, 6 * LINE_HEIGHT, 10 * CHARACTER_WIDTH, 1 * LINE_HEIGHT}, ""};
@@ -97,6 +99,8 @@ class DfuMenu2 : public View {
Text text_info_line_6{{14 * CHARACTER_WIDTH, 10 * LINE_HEIGHT, 10 * CHARACTER_WIDTH, 1 * LINE_HEIGHT}, ""};
Text text_info_line_7{{14 * CHARACTER_WIDTH, 11 * LINE_HEIGHT, 10 * CHARACTER_WIDTH, 1 * LINE_HEIGHT}, ""};
Text text_info_line_8{{14 * CHARACTER_WIDTH, 12 * LINE_HEIGHT, 10 * CHARACTER_WIDTH, 1 * LINE_HEIGHT}, ""};
Text text_info_line_9{{14 * CHARACTER_WIDTH, 13 * LINE_HEIGHT, 10 * CHARACTER_WIDTH, 1 * LINE_HEIGHT}, ""};
Text text_info_line_10{{14 * CHARACTER_WIDTH, 14 * LINE_HEIGHT, 10 * CHARACTER_WIDTH, 1 * LINE_HEIGHT}, ""};
};
} /* namespace ui */
@@ -269,6 +269,9 @@ void EncodersView::start_tx(const bool scan) {
repeat_index = 1;
update_progress();
/* Setting TX LPF 1M75 in this TX OOK App , We got same results as fw 1.7.4
* Looking max BW of this app, we tested , Selecting OOK type 145026 with CLK 455K and max DEV. 150k,
* and we got BW +-2Mhz , with that TX LPF 1M75, it is fine.*/
transmitter_model.enable();
baseband::set_ook_data(
@@ -185,6 +185,7 @@ class EncodersView : public View {
};
TxRadioState radio_state_{
433920000 /* frequency */,
1750000 /* bandwidth */,
OOK_SAMPLERATE /* sampling rate */
};
+19 -2
View File
@@ -40,6 +40,7 @@ IQTrimView::IQTrimView(NavigationView& nav)
&text_samples,
&text_max,
&field_cutoff,
&field_amplify,
&button_trim,
});
@@ -72,6 +73,11 @@ IQTrimView::IQTrimView(NavigationView& nav)
refresh_ui();
};
field_amplify.set_value(1); // 1X is default (no amplification)
field_amplify.on_change = [this](int32_t) {
refresh_ui();
};
button_trim.on_select = [this](Button&) {
if (trim_capture()) {
profile_capture();
@@ -133,7 +139,18 @@ void IQTrimView::focus() {
void IQTrimView::refresh_ui() {
field_path.set_text(path_.filename().string());
text_samples.set(to_string_dec_uint(info_->sample_count));
text_max.set(to_string_dec_uint(info_->max_power));
// show max power after amplification applied
uint64_t power_amp = field_amplify.value() * field_amplify.value() * field_amplify.value() * field_amplify.value();
text_max.set(to_string_dec_uint(info_->max_power * power_amp));
// show max power in red if amplification is too high, causing clipping
uint32_t clipping_limit = (fs::capture_file_sample_size(path_) == sizeof(complex8_t)) ? 0x80 : 0x8000;
if ((field_amplify.value() * info_->max_iq) > clipping_limit)
text_max.set_style(&Styles::red);
else
text_max.set_style(&Styles::light_grey);
set_dirty();
}
@@ -191,7 +208,7 @@ bool IQTrimView::trim_capture() {
}
progress_ui.show_trimming();
trimmed = iq::trim_capture_with_range(path_, trim_range, progress_ui.get_callback());
trimmed = iq::trim_capture_with_range(path_, trim_range, progress_ui.get_callback(), field_amplify.value());
progress_ui.clear();
if (!trimmed)
+10 -1
View File
@@ -107,6 +107,8 @@ class IQTrimView : public View {
{{0 * 8, 9 * 16}, "Max Pwr:", Color::light_grey()},
{{0 * 8, 10 * 16}, "Cutoff :", Color::light_grey()},
{{12 * 8, 10 * 16}, "%", Color::light_grey()},
{{0 * 8, 12 * 16}, "Amplify:", Color::light_grey()},
{{10 * 8, 12 * 16}, "x", Color::light_grey()},
};
TextField field_path{
@@ -135,7 +137,7 @@ class IQTrimView : public View {
"0"};
Text text_max{
{9 * 8, 9 * 16, 10 * 8, 1 * 16},
{9 * 8, 9 * 16, 20 * 8, 1 * 16},
"0"};
NumberField field_cutoff{
@@ -145,6 +147,13 @@ class IQTrimView : public View {
1,
' '};
NumberField field_amplify{
{9 * 8, 12 * 16},
1,
{1, 9},
1,
' '};
Button button_trim{
{20 * 8, 16 * 16, 8 * 8, 2 * 16},
"Trim"};
+1
View File
@@ -101,6 +101,7 @@ class JammerView : public View {
private:
NavigationView& nav_;
TxRadioState radio_state_{
0 /* frequency */,
3500000 /* bandwidth */,
3072000 /* sampling rate */
};
-2
View File
@@ -222,8 +222,6 @@ KeyfobView::KeyfobView(
options_make.set_selected_index(0);
transmitter_model.set_target_frequency(433920000); // Fixed 433.92MHz
tx_view.on_edit_frequency = [this, &nav]() {
auto new_view = nav.push<FrequencyKeypadView>(transmitter_model.target_frequency());
new_view->on_changed = [this](rf::Frequency f) {
+1
View File
@@ -44,6 +44,7 @@ class KeyfobView : public View {
NavigationView& nav_;
TxRadioState radio_state_{
433920000 /* frequency */,
1750000 /* bandwidth */,
OOK_SAMPLERATE /* sampling rate */
};
+2
View File
@@ -127,6 +127,8 @@ void LCRView::start_tx(const bool scan) {
modems::generate_data(lcr::generate_message(rgsb, litterals_list, options_ec.selected_index()), lcr_message_data);
/* It is AFSK modulation , measuring original fw 1.7.4 spectrum BW is just around 30khz , NBFM */
transmitter_model.set_baseband_bandwidth(1'750'000); // Min TX LPF 1M75, same spectrum as previous fw 1.7.4
transmitter_model.enable();
memcpy(shared_memory.bb_data.data, lcr_message_data, sizeof(lcr_message_data));
+1
View File
@@ -82,6 +82,7 @@ class LCRView : public View {
};
TxRadioState radio_state_{
0 /* frequency */,
1750000 /* bandwidth */,
AFSK_TX_SAMPLERATE /* sampling rate */
};
+34 -11
View File
@@ -101,8 +101,11 @@ void MicTXView::set_tx(bool enable) {
transmitting = false;
configure_baseband();
transmitter_model.disable();
if (rx_enabled) // If audio RX is enabled and we've been transmitting
rxaudio(true); // Turn back on audio RX
if (rx_enabled) { // If audio RX is enabled and we've been transmitting
rxaudio(true); // Turn back on audio RX
vumeter.set_value(0); // Reset vumeter
vumeter.dirty(); // Force to refresh vumeter.
}
}
}
}
@@ -183,7 +186,7 @@ void MicTXView::rxaudio(bool is_on) {
baseband::run_image(portapack::spi_flash::image_tag_mic_tx);
audio::output::stop();
audio::input::start(ak4951_alc_and_wm8731_boost_GUI); // When detected AK4951 => set up ALC mode; when detected WM8731 => set up mic_boost ON/OFF.
audio::input::start(ak4951_alc_and_wm8731_boost_GUI, mic_to_HP_enabled); // set up ALC mode (AK4951) or set up mic_boost ON/OFF (WM8731). and the check box "Hear Mic"
portapack::pin_i2s0_rx_sda.mode(3);
configure_baseband();
}
@@ -215,6 +218,7 @@ MicTXView::MicTXView(
&field_frequency,
&options_tone_key,
&check_rogerbeep,
&check_mic_to_HP, // check box to activate "hear mic"
&check_common_freq_tx_rx, // added to handle common or separate freq- TX/RX
&check_rxactive,
&field_volume,
@@ -242,6 +246,7 @@ MicTXView::MicTXView(
&field_frequency,
&options_tone_key,
&check_rogerbeep,
&check_mic_to_HP, // check box to activate "hear mic"
&check_common_freq_tx_rx, // added to handle common or separate freq- TX/RX
&check_rxactive,
&field_volume,
@@ -285,17 +290,17 @@ MicTXView::MicTXView(
shift_bits_s16 = 6; // -08 dBs respect ref level, (when +20dB's boost OFF)
break; // now mic-boost off (+00dBs) shift bits (6) (+0+12dB's)=12 dBs => -08dB's respect ref.
}
ak4951_alc_and_wm8731_boost_GUI = v; // 0..4, WM8731_boost dB's options, (combination boost on/off, and effective gain in captured data >>x)
audio::input::start(ak4951_alc_and_wm8731_boost_GUI); // Detected (WM8731), set up the proper wm_boost on/off, 0..4 (0,1) boost_on, (2,3,4) boost_off
configure_baseband(); // to update in real time, sending msg, var-parameters >>shift_bits FM msg, to audio_tx from M0 to M4 Proc -
ak4951_alc_and_wm8731_boost_GUI = v; // 0..4, WM8731_boost dB's options, (combination boost on/off, and effective gain in captured data >>x)
audio::input::start(ak4951_alc_and_wm8731_boost_GUI, mic_to_HP_enabled); // Detected (WM8731), set up the proper wm_boost on/off, 0..4 (0,1) boost_on, (2,3,4) boost_off,and the check box "Hear Mic"
configure_baseband(); // to update in real time, sending msg, var-parameters >>shift_bits FM msg, to audio_tx from M0 to M4 Proc -
};
options_wm8731_boost_mode.set_selected_index(3); // preset GUI index 3 as default WM -> -02 dB's.
} else {
shift_bits_s16 = 8; // Initialized default fixed >>8_FM for FM tx mod, shift audio data for AK4951, using top 8 bits s16 data (>>8)
options_ak4951_alc_mode.on_change = [this](size_t, int8_t v) {
ak4951_alc_and_wm8731_boost_GUI = v; // 0..11, AK4951 Mic -Automatic volume Level Control options,
audio::input::start(ak4951_alc_and_wm8731_boost_GUI); // Detected (AK4951) ==> Set up proper ALC mode from 0..11 options
configure_baseband(); // sending fixed >>8_FM, var-parameters msg, to audiotx from this M0 to M4 process.
ak4951_alc_and_wm8731_boost_GUI = v; // 0..11, AK4951 Mic -Automatic volume Level Control options,
audio::input::start(ak4951_alc_and_wm8731_boost_GUI, mic_to_HP_enabled); // Detected (AK4951) ==> Set up proper ALC mode from 0..11 options, and the check box "Hear Mic"
configure_baseband(); // sending fixed >>8_FM, var-parameters msg, to audiotx from this M0 to M4 process.
};
}
@@ -475,6 +480,20 @@ MicTXView::MicTXView(
rogerbeep_enabled = v;
};
check_mic_to_HP.on_select = [this](Checkbox&, bool v) {
mic_to_HP_enabled = v;
if (mic_to_HP_enabled)
audio::input::loopback_mic_to_hp_enable();
else
audio::input::loopback_mic_to_hp_disable();
if (mic_to_HP_enabled) { // When user click to "hear mic to HP", we will select the higher acoustic sound Option MODE ALC or BOOST-
if (audio::debug::codec_name() == "WM8731") {
options_wm8731_boost_mode.set_selected_index(0); // In WM we always go to Boost +12 dBs respect reference level
} else if (ak4951_alc_and_wm8731_boost_GUI == 0) // In AK we are changing only that ALC index =0, because in that option, there is no sound.
options_ak4951_alc_mode.set_selected_index(1); // alc_mode =0 , means no ALC,no DIGITAL filter block (by passed), and that mode has no loopback mode.
}
};
check_common_freq_tx_rx.on_select = [this](Checkbox&, bool v) {
bool_same_F_tx_rx_enabled = v;
field_rxfrequency.hidden(v); // Hide or show separated freq RX field. (When no hide user can enter down indep. freq for RX)
@@ -501,8 +520,12 @@ MicTXView::MicTXView(
check_rxactive.on_select = [this](Checkbox&, bool v) {
// vumeter.set_value(0); //Start with a clean vumeter
rx_enabled = v;
check_mic_to_HP.hidden(rx_enabled); // Togle Hide / show "Hear Mic" checkbox depending if we activate or not the receiver. (if RX on => no visible "Mic Hear" option)
if ((rx_enabled) && (transmitting))
check_mic_to_HP.set_value(transmitting); // Once we activate the "Rx audio" in reception time we disable "Hear Mic", but we allow it again in TX time.
// check_va.hidden(v); //Hide or show voice activation
rxaudio(v); // Activate-Deactivate audio rx accordingly
rxaudio(v); // Activate-Deactivate audio RX (receiver) accordingly
set_dirty(); // Refresh interface
};
@@ -602,7 +625,7 @@ MicTXView::MicTXView(
set_tx(false);
audio::set_rate(audio::Rate::Hz_24000);
audio::input::start(ak4951_alc_and_wm8731_boost_GUI); // When detected AK4951 => set up ALC mode; when detected WM8731 => set up mic_boost ON/OFF.
audio::input::start(ak4951_alc_and_wm8731_boost_GUI, mic_to_HP_enabled); // set up ALC mode (AK4951) or set up mic_boost ON/OFF (WM8731). and the check box "Hear Mic"
}
MicTXView::MicTXView(
+8
View File
@@ -82,6 +82,7 @@ class MicTXView : public View {
RxRadioState rx_radio_state_{};
TxRadioState tx_radio_state_{
0 /* frequency */,
1750000 /* bandwidth */,
sampling_rate /* sampling rate */
};
@@ -93,6 +94,7 @@ class MicTXView : public View {
bool va_enabled{false};
bool ptt_enabled{true};
bool rogerbeep_enabled{false};
bool mic_to_HP_enabled{false};
bool bool_same_F_tx_rx_enabled{false};
bool rx_enabled{false};
uint32_t tone_key_index{};
@@ -276,6 +278,12 @@ class MicTXView : public View {
"Roger beep",
false};
Checkbox check_mic_to_HP{
{18 * 8, (14 * 8) + 4},
10,
"Hear Mic",
false};
Checkbox check_rxactive{
{3 * 8, (21 * 8) - 7},
8, // it was 18, but if it is string size should be 8
+2
View File
@@ -117,6 +117,8 @@ bool MorseView::start_tx() {
}
progressbar.set_max(symbol_count);
// By experimental spectrum measurment, we left exactly same TX LPF settings as previous fw 1.7.4, TX LPF= 1M75 (min).
transmitter_model.set_baseband_bandwidth(1'750'000); // Min TX LPF .already tested in FM morse max tone 9,999k , max dev 150khz
transmitter_model.enable();
if (modulation == CW) {
+1
View File
@@ -70,6 +70,7 @@ class MorseView : public View {
uint32_t time_units{0};
TxRadioState radio_state_{
0 /* frequency */,
1750000 /* bandwidth */,
1536000 /* sampling rate */
};
-1
View File
@@ -54,7 +54,6 @@ NRFRxView::NRFRxView(NavigationView& nav)
&console});
// Auto-configure modem for LCR RX (will be removed later)
field_frequency.set_value(2480000000);
auto def_bell202 = &modem_defs[0];
persistent_memory::set_modem_baudrate(def_bell202->baudrate);
serial_format_t serial_format;
+1
View File
@@ -50,6 +50,7 @@ class NRFRxView : public View {
NavigationView& nav_;
RxRadioState radio_state_{
2480000000 /* frequency */,
4000000 /* bandwidth */,
4000000 /* sampling rate */,
ReceiverModel::Mode::WidebandFMAudio};
+1
View File
@@ -56,6 +56,7 @@ class NumbersStationView : public View {
NavigationView& nav_;
TxRadioState radio_state_{
0 /* frequency */,
1750000 /* bandwidth */,
1536000 /* sampling rate */
};
+1
View File
@@ -56,6 +56,7 @@ class NuoptixView : public View {
};
TxRadioState radio_state_{
0 /* frequency */,
1750000 /* bandwidth */,
1536000 /* sampling rate */
};
@@ -81,6 +81,8 @@ bool POCSAGTXView::start_tx() {
transmitter_model.set_rf_amp(true);
transmitter_model.set_tx_gain(40);
// We left exactly same TX LPF settings as previous fw 1.7.4, TX LPF= 1M75 (min). It is fine even in max FM dev. 150khz and 2400 bauds.
transmitter_model.set_baseband_bandwidth(1'750'000); // Min TX LPF . Pocsag is NBFM , using BW channel 25khz or 12khz
transmitter_model.enable();
uint8_t* data_ptr = shared_memory.bb_data.data;
@@ -60,6 +60,7 @@ class POCSAGTXView : public View {
NavigationView& nav_;
TxRadioState radio_state_{
466175000 /* frequency */,
1750000 /* bandwidth */,
2280000 /* sampling rate */
};
-1
View File
@@ -187,7 +187,6 @@ void RDSView::start_tx() {
else
frame_datetime.clear();
transmitter_model.set_baseband_bandwidth(1'750'000); // Big Spectrum harmonics reduction, and now quicker decoding time.
transmitter_model.enable();
tx_thread = std::make_unique<RDSThread>(frames);
+1
View File
@@ -142,6 +142,7 @@ class RDSView : public View {
RDS_flags rds_flags{};
TxRadioState radio_state_{
0 /* frequency */,
1750000 /* bandwidth */,
2280000 /* sampling rate */
};
+1
View File
@@ -90,6 +90,7 @@ class SearchView : public View {
private:
NavigationView& nav_;
RxRadioState radio_state_{
100'000'000 /* frequency */,
2500000 /* bandwidth */,
SEARCH_SLICE_WIDTH /* sampling rate */,
ReceiverModel::Mode::SpectrumAnalysis};
-29
View File
@@ -343,34 +343,6 @@ void SetUIView::focus() {
button_save.focus();
}
/* SetAppSettingsView ************************************/
SetAppSettingsView::SetAppSettingsView(NavigationView& nav) {
add_children({
&labels,
&checkbox_load_app_settings,
&checkbox_save_app_settings,
&button_save,
&button_cancel,
});
checkbox_load_app_settings.set_value(pmem::load_app_settings());
checkbox_save_app_settings.set_value(pmem::save_app_settings());
button_save.on_select = [&nav, this](Button&) {
pmem::set_load_app_settings(checkbox_load_app_settings.value());
pmem::set_save_app_settings(checkbox_save_app_settings.value());
nav.pop();
};
button_cancel.on_select = [&nav, this](Button&) {
nav.pop();
};
}
void SetAppSettingsView::focus() {
button_save.focus();
}
/* SetConverterSettingsView ******************************/
SetConverterSettingsView::SetConverterSettingsView(NavigationView& nav) {
@@ -654,7 +626,6 @@ SettingsMenuView::SettingsMenuView(NavigationView& nav) {
add_items({{"..", ui::Color::light_grey(), &bitmap_icon_previous, [&nav]() { nav.pop(); }}});
}
add_items({
{"App Settings", ui::Color::dark_cyan(), &bitmap_icon_setup, [&nav]() { nav.push<SetAppSettingsView>(); }},
{"Audio", ui::Color::dark_cyan(), &bitmap_icon_speaker, [&nav]() { nav.push<SetAudioView>(); }},
{"Calibration", ui::Color::dark_cyan(), &bitmap_icon_options_touch, [&nav]() { nav.push<TouchCalibrationView>(); }},
{"Converter", ui::Color::dark_cyan(), &bitmap_icon_options_radio, [&nav]() { nav.push<SetConverterSettingsView>(); }},
-35
View File
@@ -310,41 +310,6 @@ class SetUIView : public View {
};
};
class SetAppSettingsView : public View {
public:
SetAppSettingsView(NavigationView& nav);
void focus() override;
std::string title() const override { return "App Settings"; };
private:
Labels labels{
{{1 * 8, 1 * 16}, "App settings are saved to", Color::light_grey()},
{{1 * 8, 2 * 16}, "the SD card in /SETTINGS.", Color::light_grey()},
{{1 * 8, 3 * 16}, "Radio settings may also be", Color::light_grey()},
{{1 * 8, 4 * 16}, "loaded or saved per app.", Color::light_grey()},
};
Checkbox checkbox_load_app_settings{
{3 * 8, 6 * 16},
25,
"Load radio settings"};
Checkbox checkbox_save_app_settings{
{3 * 8, 8 * 16},
25,
"Save radio settings"};
Button button_save{
{2 * 8, 16 * 16, 12 * 8, 32},
"Save"};
Button button_cancel{
{16 * 8, 16 * 16, 12 * 8, 32},
"Cancel",
};
};
class SetConverterSettingsView : public View {
public:
SetConverterSettingsView(NavigationView& nav);
+1
View File
@@ -51,6 +51,7 @@ class SigGenView : public View {
void on_tx_progress(const uint32_t progress, const bool done);
TxRadioState radio_state_{
0 /* frequency */,
1750000 /* bandwidth */,
1536000 /* sampling rate */
};
-3
View File
@@ -66,9 +66,6 @@ SondeView::SondeView(NavigationView& nav)
&button_see_qr,
&button_see_map});
if (!settings_.radio_loaded())
field_frequency.set_value(initial_target_frequency);
field_frequency.set_step(500); // euquiq: was 10000, but we are using this for fine-tunning
geopos.set_read_only(true);
+1 -1
View File
@@ -68,6 +68,7 @@ class SondeView : public View {
private:
NavigationView& nav_;
RxRadioState radio_state_{
402700000 /* frequency */,
1750000 /* bandwidth */,
2457600 /* sampling rate */
};
@@ -75,7 +76,6 @@ class SondeView : public View {
"rx_sonde", app_settings::Mode::RX};
std::unique_ptr<SondeLogger> logger{};
uint32_t target_frequency_{402700000};
bool logging{false};
bool use_crc{false};
bool beep{false};
@@ -85,7 +85,11 @@ SpectrumPainterView::SpectrumPainterView(
if (tx_mode == 0 && image_input_avaliable == false)
return;
/* By experimental test measurement, we got a good painted spectrum quality when selecting
a BW GUI App range from 100k ... 2M aprox. In that range , the best TX LPF filter = 1M75 (the min)
With this min TX LPF filter , we minimized the harmonics aliasing multipicture overlapped.
So original fw 1.7.4., was already selecting the best setting (1M75) */
transmitter_model.set_baseband_bandwidth(1'750'000); // Already tested, is the best setting for this App.
transmitter_model.enable();
if (persistent_memory::stealth_mode()) {
+1
View File
@@ -160,6 +160,7 @@ void SSTVTXView::start_tx() {
scanline_counter = 0;
prepare_scanline(); // Preload one scanline
transmitter_model.set_baseband_bandwidth(1'750'000); // Min TX LPF 1M75, same spectrum as previous fw 1.7.4
transmitter_model.enable();
baseband::set_sstv_data(
+1
View File
@@ -62,6 +62,7 @@ class TestView : public View {
private:
NavigationView& nav_;
RxRadioState radio_state_{
0 /* frequency */,
1750000 /* bandwidth */,
2457600 * 2 /* sampling rate */
};
@@ -85,7 +85,6 @@ void TouchTunesView::on_tx_progress(const uint32_t progress, const bool done) {
// transmission events.
void TouchTunesView::start_ew() {
// Radio
transmitter_model.set_target_frequency(433920000);
transmitter_model.set_rf_amp(true);
transmitter_model.set_tx_gain(47);
transmitter_model.enable();
@@ -151,10 +150,7 @@ void TouchTunesView::start_tx(const uint32_t button_index) {
size_t bitstream_length = make_bitstream(fragments);
transmitter_model.set_target_frequency(433920000);
transmitter_model.set_sampling_rate(OOK_SAMPLERATE);
transmitter_model.set_rf_amp(true);
transmitter_model.set_baseband_bandwidth(1750000);
transmitter_model.enable();
baseband::set_ook_data(
+4 -2
View File
@@ -25,6 +25,7 @@
#include "ui_transmitter.hpp"
#include "transmitter_model.hpp"
#include "radio_state.hpp"
#include "encoders.hpp"
// The coding in notpike's script is quite complex, using multiple LUTs to form the data sent to the YSO.
// The format is actually very simple if it is rather seen as short and long gaps between pulses (as seen in many OOK remotes).
@@ -115,8 +116,9 @@ class TouchTunesView : public View {
private:
TxRadioState radio_state_{
3500000 /* bandwidth */,
3072000 /* sampling rate */
433920000 /* frequency */,
1750000 /* bandwidth */,
OOK_SAMPLERATE /* sampling rate */
};
uint32_t scan_button_index{};
+10 -2
View File
@@ -198,8 +198,8 @@ void update_audio_mute() {
namespace input {
void start(int8_t alc_mode) {
audio_codec->microphone_enable(alc_mode); // added user-GUI selection for AK4951, ALC mode parameter.
void start(int8_t alc_mode, bool mic_to_HP_enabled) {
audio_codec->microphone_enable(alc_mode, mic_to_HP_enabled); // added user-GUI selection for AK4951, ALC mode parameter. and the check box "Hear Mic"
i2s::i2s0::rx_start();
}
@@ -208,6 +208,14 @@ void stop() {
audio_codec->microphone_disable();
}
void loopback_mic_to_hp_enable() {
audio_codec->microphone_to_HP_enable();
}
void loopback_mic_to_hp_disable() {
audio_codec->microphone_to_HP_disable();
}
} /* namespace input */
namespace headphone {
+8 -2
View File
@@ -50,9 +50,12 @@ class Codec {
virtual volume_range_t headphone_gain_range() const = 0;
virtual void set_headphone_volume(const volume_t volume) = 0;
virtual void microphone_enable(int8_t alc_mode) = 0; // added user-GUI AK4951 ,selected ALC mode.
virtual void microphone_enable(int8_t alc_mode, bool mic_to_HP_enabled) = 0; // added user-GUI AK4951 ,selected ALC mode.
virtual void microphone_disable() = 0;
virtual void microphone_to_HP_enable() = 0;
virtual void microphone_to_HP_disable() = 0;
virtual size_t reg_count() const = 0;
virtual size_t reg_bits() const = 0;
virtual uint32_t reg_read(const size_t register_number) = 0;
@@ -76,9 +79,12 @@ void update_audio_mute();
namespace input {
void start(int8_t alc_mode); // added parameter user-GUI select AK4951-ALC mode for config mic path,(recording mode in datasheet),
void start(int8_t alc_mode, bool mic_to_HP_enabled); // added parameters -GUI select AK4951-ALC mode for config mic path,(recording mode),and the check box "Hear Mic"
void stop();
void loopback_mic_to_hp_enable();
void loopback_mic_to_hp_disable();
} /* namespace input */
namespace headphone {
+54 -3
View File
@@ -36,6 +36,13 @@ uint32_t power(T value) {
return (real * real) + (imag * imag);
}
template <typename T>
uint32_t iq_max(T value) {
auto real = abs(value.real());
auto imag = abs(value.imag());
return (real > imag) ? real : imag;
}
/* Collects capture file metadata and sample power buckets. */
template <typename T>
Optional<CaptureInfo> profile_capture(
@@ -51,7 +58,8 @@ Optional<CaptureInfo> profile_capture(
.file_size = f.size(),
.sample_count = f.size() / sizeof(T),
.sample_size = sizeof(T),
.max_power = 0};
.max_power = 0,
.max_iq = 0};
auto profile_samples = buckets.size * samples_per_bucket;
auto sample_interval = info.sample_count / profile_samples;
@@ -67,8 +75,11 @@ Optional<CaptureInfo> profile_capture(
if (*result != info.sample_size)
break; // EOF
auto mag_squared = power(value);
auto max_iq = iq_max(value);
if (max_iq > info.max_iq)
info.max_iq = max_iq;
auto mag_squared = power(value);
if (mag_squared > info.max_power)
info.max_power = mag_squared;
@@ -133,13 +144,50 @@ TrimRange compute_trim_range(
info.sample_size};
}
void amplify_iq_buffer(uint8_t* buffer, uint32_t length, uint32_t amplification, uint8_t sample_size) {
uint32_t mult_count = length / sample_size / 2;
switch (sample_size) {
case sizeof(complex16_t): {
int16_t* buf_ptr = (int16_t*)buffer;
for (uint32_t i = 0; i < mult_count; i++) {
int32_t val = *buf_ptr * amplification;
if (val > 0x7FFF)
val = 0x7FFF;
else if (val < -0x7FFF)
val = -0x7FFF;
*buf_ptr++ = val;
}
break;
}
case sizeof(complex8_t): {
int8_t* buf_ptr = (int8_t*)buffer;
for (uint32_t i = 0; i < mult_count; i++) {
int32_t val = *buf_ptr * amplification;
if (val > 0x7F)
val = 0x7F;
else if (val < -0x7F)
val = -0x7F;
*buf_ptr++ = val;
}
break;
}
default:
break;
}
}
bool trim_capture_with_range(
const fs::path& path,
TrimRange range,
const std::function<void(uint8_t)>& on_progress) {
const std::function<void(uint8_t)>& on_progress,
const uint32_t amplification) {
constexpr size_t buffer_size = std::filesystem::max_file_block_size;
uint8_t buffer[buffer_size];
auto temp_path = path + u"-tmp";
auto sample_size = fs::capture_file_sample_size(path);
// end_sample is the first sample to _not_ include.
auto start_byte = range.start_sample * range.sample_size;
@@ -168,6 +216,9 @@ bool trim_capture_with_range(
auto remaining = length - processed;
auto to_write = std::min(remaining, *result);
if (amplification > 1)
amplify_iq_buffer(buffer, to_write, amplification, sample_size);
result = dst->write(buffer, to_write);
if (result.is_error()) return false;
+10 -1
View File
@@ -37,6 +37,7 @@ struct CaptureInfo {
uint64_t sample_count;
uint8_t sample_size;
uint32_t max_power;
uint32_t max_iq;
};
/* Holds sample average power by bucket. */
@@ -82,11 +83,19 @@ TrimRange compute_trim_range(
const PowerBuckets& buckets,
uint8_t cutoff_percent);
/* Multiplies samples in an IQ buffer by amplification value */
void amplify_iq_buffer(
uint8_t* buffer,
uint32_t length,
uint32_t amplification,
uint8_t sample_size);
/* Trims the capture file with the specified range. */
bool trim_capture_with_range(
const std::filesystem::path& path,
TrimRange range,
const std::function<void(uint8_t)>& on_progress);
const std::function<void(uint8_t)>& on_progress,
const uint32_t amplification);
} // namespace iq
+2 -2
View File
@@ -92,8 +92,8 @@ max2839::MAX2839 second_if_max2839{ssp1_target_max283x};
static max5864::MAX5864 baseband_codec{ssp1_target_max5864};
static baseband::CPLD baseband_cpld;
// Set invalid to force the set_direction CPLD workaround to run.
static rf::Direction direction{-1};
// load_sram() is called at boot in portapack.cpp, including verify CPLD part, so default direction is Receive
static rf::Direction direction{rf::Direction::Receive};
static bool baseband_invert = false;
static bool mixer_invert = false;
+6 -1
View File
@@ -41,8 +41,10 @@ class RadioState {
model->initialize();
}
RadioState(uint32_t new_bandwidth, uint32_t new_sampling_rate) {
RadioState(uint32_t new_frequency, uint32_t new_bandwidth, uint32_t new_sampling_rate) {
model->initialize();
if (new_frequency != 0)
model->set_target_frequency(new_frequency);
model->set_sampling_rate(new_sampling_rate);
model->set_baseband_bandwidth(new_bandwidth);
}
@@ -61,10 +63,13 @@ class RadioState {
typename U = TModel,
typename Mode = std::enable_if_t<sizeof(typename U::Mode), typename U::Mode> >
RadioState(
uint32_t new_frequency,
uint32_t new_bandwidth,
uint32_t new_sampling_rate,
Mode new_mode) {
model->initialize();
if (new_frequency != 0)
model->set_target_frequency(new_frequency);
model->set_sampling_rate(new_sampling_rate);
model->set_baseband_bandwidth(new_bandwidth);
model->settings().mode = new_mode;
+32 -4
View File
@@ -110,16 +110,18 @@ void BtnGridView::clear() {
void BtnGridView::add_items(std::initializer_list<GridItem> new_items) {
for (auto item : new_items) {
menu_items.push_back(item);
if (!blacklisted_app(item))
menu_items.push_back(item);
}
update_items();
}
void BtnGridView::add_item(GridItem new_item) {
menu_items.push_back(new_item);
update_items();
if (!blacklisted_app(new_item)) {
menu_items.push_back(new_item);
update_items();
}
}
void BtnGridView::update_items() {
@@ -232,4 +234,30 @@ bool BtnGridView::on_encoder(const EncoderEvent event) {
return set_highlighted(highlighted_item + event);
}
/* BlackList ******************************************************/
std::unique_ptr<char> blacklist_ptr{};
size_t blacklist_len{};
void load_blacklist() {
File f;
auto error = f.open(BLACKLIST);
if (error)
return;
blacklist_ptr = std::unique_ptr<char>(new char[f.size()]);
if (f.read(blacklist_ptr.get(), f.size()))
blacklist_len = f.size();
}
bool BtnGridView::blacklisted_app(GridItem new_item) {
std::string app_name = new_item.text;
if (blacklist_len < app_name.size())
return false;
return std::search(blacklist_ptr.get(), blacklist_ptr.get() + blacklist_len, app_name.begin(), app_name.end()) < blacklist_ptr.get() + blacklist_len;
}
} /* namespace ui */
+6
View File
@@ -36,6 +36,9 @@
#include <string>
#include <vector>
// file used for listing apps to hide from menu
#define BLACKLIST u"/SETTINGS/blacklist"
namespace ui {
struct GridItem {
@@ -47,6 +50,8 @@ struct GridItem {
// TODO: Prevent default-constructed GridItems.
};
void load_blacklist();
class BtnGridView : public View {
public:
BtnGridView(Rect new_parent_rect = {0, 0, 240, 304}, bool keep_highlight = false);
@@ -70,6 +75,7 @@ class BtnGridView : public View {
void on_blur() override;
bool on_key(const KeyEvent event) override;
bool on_encoder(const EncoderEvent event) override;
bool blacklisted_app(GridItem new_item);
private:
int rows_{3};
+6 -3
View File
@@ -161,6 +161,8 @@ SystemStatusView::SystemStatusView(
rtc_battery_workaround();
ui::load_blacklist();
if (pmem::should_use_sdcard_for_pmem()) {
pmem::load_persistent_settings_from_file();
}
@@ -393,6 +395,7 @@ void SystemStatusView::rtc_battery_workaround() {
}
}
} else {
make_new_directory(SETTINGS_DIR);
make_new_file(DATE_FILEFLAG);
year = 1980;
@@ -572,8 +575,8 @@ TransmittersMenuView::TransmittersMenuView(NavigationView& nav) {
add_items({{"..", Color::light_grey(), &bitmap_icon_previous, [&nav]() { nav.pop(); }}});
}
add_items({
{"ADS-B", ui::Color::green(), &bitmap_icon_adsb, [&nav]() { nav.push<ADSBTxView>(); }},
{"APRS", ui::Color::green(), &bitmap_icon_aprs, [&nav]() { nav.push<APRSTXView>(); }},
{"ADS-B TX", ui::Color::green(), &bitmap_icon_adsb, [&nav]() { nav.push<ADSBTxView>(); }},
{"APRS TX", ui::Color::green(), &bitmap_icon_aprs, [&nav]() { nav.push<APRSTXView>(); }},
{"BHT Xy/EP", ui::Color::green(), &bitmap_icon_bht, [&nav]() { nav.push<BHTView>(); }},
{"BurgerPgr", ui::Color::yellow(), &bitmap_icon_burger, [&nav]() { nav.push<CoasterPagerView>(); }},
{"GPS Sim", ui::Color::green(), &bitmap_icon_gps_sim, [&nav]() { nav.push<GpsSimAppView>(); }},
@@ -583,7 +586,7 @@ TransmittersMenuView::TransmittersMenuView(NavigationView& nav) {
{"Morse", ui::Color::green(), &bitmap_icon_morse, [&nav]() { nav.push<MorseView>(); }},
// { "Nuoptix DTMF", ui::Color::green(), &bitmap_icon_nuoptix, [&nav](){ nav.push<NuoptixView>(); }},
{"OOK", ui::Color::yellow(), &bitmap_icon_remote, [&nav]() { nav.push<EncodersView>(); }},
{"POCSAG", ui::Color::green(), &bitmap_icon_pocsag, [&nav]() { nav.push<POCSAGTXView>(); }},
{"POCSAG TX", ui::Color::green(), &bitmap_icon_pocsag, [&nav]() { nav.push<POCSAGTXView>(); }},
{"RDS", ui::Color::green(), &bitmap_icon_rds, [&nav]() { nav.push<RDSView>(); }},
{"Soundbrd", ui::Color::green(), &bitmap_icon_soundboard, [&nav]() { nav.push<SoundBoardView>(); }},
{"S.Painter", ui::Color::orange(), &bitmap_icon_paint, [&nav]() { nav.push<SpectrumPainterView>(); }},
+1 -1
View File
@@ -322,7 +322,7 @@ void RecordView::trim_capture() {
auto trim_range = iq::compute_trim_range(*info, power_buckets, 7);
trim_ui.show_trimming();
iq::trim_capture_with_range(trim_path, trim_range, trim_ui.get_callback());
iq::trim_capture_with_range(trim_path, trim_range, trim_ui.get_callback(), 1);
}
trim_ui.clear();
+38 -4
View File
@@ -224,7 +224,7 @@ void AK4951::speaker_disable() {
set_speaker_power(false);
}
void AK4951::microphone_enable(int8_t alc_mode) {
void AK4951::microphone_enable(int8_t alc_mode, bool mic_to_HP_enabled) {
// alc_mode =0 = (OFF =same as original code = NOT using AK4951 Programmable digital filter block),
// alc_mode >1 (with DIGITAL FILTER BLOCK , example : 1:(+12dB) , 2:(+9dB)", 3:(+6dB), ...)
@@ -279,7 +279,7 @@ void AK4951::microphone_enable(int8_t alc_mode) {
update(Register::DigitalFilterMode); // Writing the Audio Path : NO DIGITAL BLOCK or DIG BLOCK FOR MIC , Audio mode path : Playback mode /-Recording mode.
map.r.power_management_1.PMADL = 1; // ADC Lch = Lch input signal. Mic Amp Lch and ADC Lch Power Management
map.r.power_management_1.PMADR = 1; // ADC Rch = Rch input signal. Mic Amp Rch and ADC Rch Power Management
map.r.power_management_1.PMADR = 0; // ADC Rch = Rch input signal. Mic Amp Rch and ADC Rch Power Management. (PMADL=1, PMADR=0) means MONO MIC input connected to Left pin.
map.r.power_management_1.PMPFIL = 0; // Pre-loading , Programmable Dig. filter OFF ,filter unused, routed around.(original value = 0 )
update(Register::PowerManagement1); // Activating the Power management of the used blocks . (Mic ADC always + Dig Block filter , when used )
@@ -461,7 +461,7 @@ void AK4951::microphone_enable(int8_t alc_mode) {
// When changing those modes, PMPFIL bit must be “0”, it is OK (*1)
map.r.digital_filter_mode.ADCPF = 1; // ADCPF bit swith ("0" Mic after ADC Output connected (recording mode) to the DIGITAL FILTER BLOCK. ("1" Playback mode)
map.r.digital_filter_mode.PFSDO = 1; // ADC (+ 1st order HPF) Output
map.r.digital_filter_mode.PFDAC = 0b00; // (Input selector for DAC (not used in MIC), SDTI= Audio Serial Data Input Pin)
map.r.digital_filter_mode.PFDAC = 0b00; // (Input selector for DAC (initially not used in MIC), SDTI= Audio Serial Data Input Pin)
update(Register::DigitalFilterMode); // Writing the Audio Path : NO DIGITAL BLOCK or DIG BLOCK FOR MIC , Audio mode path : Playback mode /-Recording mode.
// The EQn (n=1, 2, 3, 4 or 5) coefficient must be set when EQn bit = “0” or PMPFIL bit = “0”., but we are already (*1)
@@ -501,10 +501,15 @@ void AK4951::microphone_enable(int8_t alc_mode) {
// Acitivating digital block , power supply
map.r.power_management_1.PMADL = 1; // ADC Lch = Lch input signal. Mic Amp Lch and ADC Lch Power Management
map.r.power_management_1.PMADR = 1; // ADC Rch = Rch input signal. Mic Amp Rch and ADC Rch Power Management
map.r.power_management_1.PMADR = 0; // ADC Rch = Rch input signal. Mic Amp Rch and ADC Rch Power Management. (PMADL=1, PMADR=0) means MONO MIC input connected to Left pin.
map.r.power_management_1.PMPFIL = 1; // Pre-loaded in top part. Orig value=0, Programmable Digital filter unused (not power up), routed around.
update(Register::PowerManagement1); // Activating the Power management of the used blocks . (Mic ADC always + Dig Block filter , when used )
if (mic_to_HP_enabled)
microphone_to_HP_enable();
else
microphone_to_HP_disable();
// 1059/fs, 22ms @ 48kHz
chThdSleepMilliseconds(22);
}
@@ -522,8 +527,13 @@ void AK4951::microphone_disable() {
map.r.power_management_1.PMADL = 0; // original code , disable Power managem.Mic ADC L
map.r.power_management_1.PMADR = 0; // original code , disable Power managem.Mic ADC R
map.r.power_management_1.PMPFIL = 0; // original code , disable Power managem. all Programmable Dig. block
map.r.power_management_1.PMDAC = 0; // Pre-loaded power management DAC block OFF
update(Register::PowerManagement1);
map.r.power_management_2.PMHPL = 0; // Pre-loaded power management HP LEFT block OFF
map.r.power_management_2.PMHPR = 0; // Pre-loaded power management HP RIGHT block OFF
update(Register::PowerManagement2); // Deactivating the Power management of the HP L&R blocks.
map.r.alc_mode_control_1.ALC = 0; // original code , Restore , disable ALC block.
update(Register::ALCModeControl1);
@@ -560,6 +570,30 @@ void AK4951::microphone_disable() {
update(Register::DigitalFilterSelect3);
}
void AK4951::microphone_to_HP_enable() {
map.r.digital_filter_mode.PFDAC = 0b01; // (Input selector for DAC, audio Loopback Mode .
update(Register::DigitalFilterMode); // Writing the Audio Path , Audio mode path : Loopback Mode .
map.r.power_management_1.PMDAC = 1; // Pre-loaded power management DAC block ON
update(Register::PowerManagement1); // Activating the Power management of the DAC block for the loopback mode
map.r.power_management_2.PMHPL = 1; // Pre-loaded power management HP LEFT block ON
map.r.power_management_2.PMHPR = 1; // Pre-loaded power management HP RIGHT block ON
update(Register::PowerManagement2); // Activating the Power management of the HP L&R blocks.
}
void AK4951::microphone_to_HP_disable() {
map.r.digital_filter_mode.PFDAC = 0b00; // (Input selector for DAC (not used in MIC), SDTI= Audio Serial Data Input Pin)
update(Register::DigitalFilterMode); // Writing the Audio Path , Audio mode path : Loopback Mode .
map.r.power_management_1.PMDAC = 0; // Pre-loaded power management DAC block OFF
update(Register::PowerManagement1); // Deactivating the Power management of the DAC block for the loopback mode
map.r.power_management_2.PMHPL = 0; // Pre-loaded power management HP LEFT block OFF
map.r.power_management_2.PMHPR = 0; // Pre-loaded power management HP RIGHT block OFF
update(Register::PowerManagement2); // Deactivating the Power management of the HP L&R blocks.
}
reg_t AK4951::read(const address_t reg_address) {
const std::array<uint8_t, 1> tx{reg_address};
std::array<uint8_t, 1> rx{0x00};
+4 -1
View File
@@ -844,9 +844,12 @@ class AK4951 : public audio::Codec {
void set_headphone_volume(const volume_t volume) override;
void headphone_mute();
void microphone_enable(int8_t alc_mode); // added user GUI parameter , to set up AK4951 ALC mode.
void microphone_enable(int8_t alc_mode, bool mic_to_HP_enabled); // added user GUI parameter , to set up AK4951 ALC mode, and mic_to_HP_enabled to control "Hear to Mic"
void microphone_disable();
void microphone_to_HP_enable();
void microphone_to_HP_disable();
size_t reg_count() const override {
return asahi_kasei::ak4951::reg_count;
}
@@ -524,14 +524,6 @@ bool show_gui_return_icon() { // add return icon in touchscreen menu
return data->ui_config.show_gui_return_icon != 0;
}
bool load_app_settings() { // load (last saved) app settings on startup of app
return data->ui_config.load_app_settings != 0;
}
bool save_app_settings() { // save app settings when closing app
return data->ui_config.save_app_settings != 0;
}
bool show_bigger_qr_code() { // show bigger QR code
return data->ui_config.show_large_qr_code != 0;
}
@@ -876,6 +868,8 @@ bool should_use_sdcard_for_pmem() {
int save_persistent_settings_to_file() {
File outfile;
make_new_directory(SETTINGS_DIR);
auto error = outfile.create(PMEM_SETTING_FILE);
if (error)
return false;
@@ -920,7 +914,9 @@ bool debug_dump() {
painter.draw_string({0, 320 - 16}, ui::Styles::red, "ERROR DUMPING " + filename.filename().string() + " !");
return false;
}
pmem_dump_file.write_line("FW version " VERSION_STRING);
pmem_dump_file.write_line("FW version: " VERSION_STRING);
pmem_dump_file.write_line("Ext APPS version req'd: 0x" + to_string_hex(VERSION_MD5));
pmem_dump_file.write_line("GCC version: " + to_string_dec_int(__GNUC__) + "." + to_string_dec_int(__GNUC_MINOR__) + "." + to_string_dec_int(__GNUC_PATCHLEVEL__));
// write persistent memory
pmem_dump_file.write_line("\n[Persistent Memory]");
@@ -179,8 +179,6 @@ bool config_converter();
bool config_updown_converter();
int64_t config_converter_freq();
bool show_gui_return_icon();
bool load_app_settings();
bool save_app_settings();
bool show_bigger_qr_code();
bool hide_clock();
bool clock_with_date();
+21 -2
View File
@@ -349,17 +349,36 @@ class WM8731 : public audio::Codec {
return false;
}
void microphone_enable(int8_t wm8731_boost_GUI) override {
void microphone_enable(int8_t wm8731_boost_GUI, bool mic_to_HP_enabled) override {
microphone_mute(true); // c/m to reduce "plop noise" when changing wm8731_boost_GUI.
// chThdSleepMilliseconds(20); // does not help to reduce the "plop noise"
microphone_boost((wm8731_boost_GUI < 2) ? 1 : 0); // 1 = Enable Boost (+20 dBs) . 0 = Disable Boost (0dBs).
chThdSleepMilliseconds(120); // >50 msegs, very effective , >100 msegs minor improvement ,120 msegs trade off speed .
microphone_mute(false);
// (void)alc_mode; In prev. fw version , when we did not use at all param., to avoid "unused warning" when compiling.)
if (mic_to_HP_enabled)
microphone_to_HP_enable();
else
microphone_to_HP_disable();
}
void microphone_disable() override {
// TODO: Implement
microphone_mute(true);
microphone_to_HP_disable();
}
void microphone_to_HP_enable() override {
map.r.analog_audio_path_control.sidetone = 1; // Side Tone Switch (Analogue) 1 = Enable Side Tone
map.r.analog_audio_path_control.sideatt = 0b00; // Side Tone Attenuation 00 = -6dB
write(Register::AnalogAudioPathControl);
headphone_enable();
}
void microphone_to_HP_disable() override {
map.r.analog_audio_path_control.sidetone = 0; // Side Tone Switch (Analogue) 0 = Disable Side Tone
map.r.analog_audio_path_control.sideatt = 0b11; // Side Tone Attenuation 11 = -15dB
write(Register::AnalogAudioPathControl);
}
void microphone_boost(const bool boost) {