Compare commits

...

21 Commits

Author SHA1 Message Date
jLynx 15f3d81798 Update version.txt 2022-06-08 19:21:01 +12:00
jLynx fa2791004f Update past_version.txt 2022-06-08 19:20:52 +12:00
Timo Taskinen 50bd08d9ff Fix AM bandwidth and sampling rate in scanner (#671)
In scanner app, the bandwidth and sampling rate for AM modulation was incorrect. This resulted in high pitched and distorted sound. I have now copied the settings from the Audio receiver app, and now the sound in Scanner sounds good also in AM mode.
2022-06-07 11:05:17 +12:00
jLynx 39134b62c3 Fix for new H2+ devices (#666)
* WIP Fix for new h2+ devices

* reset

* Updated sub module
2022-06-05 14:15:44 +12:00
Jared Boone e5a30b4309 Persistent memory check value verification, defaulting when fails. (#662)
* Make default constructor for touch calibration

* Add persistent memory check value and access abstraction.

* Add persistent data_t default constructor with reasonable defaults.

* serial_format_t default constructor.

* Tidy up backlight timeout type.

* Add persistent data struct version/checking.

* Make range_t functions constexpr.

* Move ui_config and functions into class.

* Add backlight_config_t struct, separate enable and time settings.
2022-05-29 08:55:18 +12:00
ArjanOnwezen 2031a79b34 Update problem-upgrading-the-firmware.md
Typo
2022-05-21 10:12:52 +02:00
ArjanOnwezen deff646e36 Update problem-upgrading-the-firmware.md
Typo
2022-05-21 10:11:36 +02:00
jLynx 4aa3314906 Updated templates (#655)
* Update problem-upgrading-the-firmware.md

* Update problem-upgrading-the-firmware.md

* Update bug_report.md
2022-05-21 13:41:44 +12:00
jLynx e3da9d4cb2 Included DLL files (#654) 2022-05-21 12:11:03 +12:00
jLynx 2f10fe2fe4 v1.5.3 (#649)
* Update create_stable_release.yml

* Update version.txt
2022-05-21 08:03:17 +12:00
jLynx 5a7b12f920 Update version.txt 2022-05-20 11:00:41 +12:00
jLynx f8a4134973 Update past_version.txt 2022-05-20 11:00:34 +12:00
ArjanOnwezen a3ee160e27 Merge pull request #643 from ArjanOnwezen/save-more-app-settings
Save most common settings for TX apps
2022-05-13 21:42:51 +02:00
Arjan Onwezen ade0d6c68f French translations. 2022-05-13 09:31:58 -04:00
ArjanOnwezen 8e9355b57a Merge pull request #644 from ArjanOnwezen/set-fixed-modulation-for-pocsag
Set fixed modulation (NFM) for Pocsag app. (#569)
2022-05-13 15:11:43 +02:00
Arjan Onwezen e97ffd42ef Set fixed modulation (WFM) for Pocsag app. 2022-05-13 09:04:53 -04:00
Arjan Onwezen cccc92cc34 Save most common settings for TX apps. And translated some French apps along the way. 2022-05-13 08:38:04 -04:00
ArjanOnwezen 3387b59eab Add AMD64 folder #632
Added AMD64 folder #632
2022-05-11 17:33:33 +02:00
MattLodge 6c5f8a38e0 Update generate_world_map.bin.py (#640)
Use bytes instead of strings to write ADSB map binary for python3
2022-05-09 07:27:15 +12:00
Brumi-2021 de1570d8af Allow change initial gain amp values just opened file (#634)
* Update spectrum_collector.cpp

lower case correction

* Update spectrum_collector.cpp

Description changed , better explanation.

* Revert "Update spectrum_collector.cpp"

This reverts commit 4a6fc35384.

* Revert "Update spectrum_collector.cpp"

This reverts commit 35cece1cb0.

* Revert "Solving Compile error on gcc10 . Keeping same safety protection about the size of the array ,but with slightly different sintax."

This reverts commit f4db4e2b53.

* Allow initial GAIN ,AMP changes after opened  file
2022-05-07 11:43:55 +12:00
Brumi-2021 1027e80d53 Recovered lost ctcss/roger beep/correct mic gain in mic app from 1.5.1 without ALC (Auto mic Limit Control-AK) (#633)
* Update spectrum_collector.cpp

lower case correction

* Update spectrum_collector.cpp

Description changed , better explanation.

* Revert "Update spectrum_collector.cpp"

This reverts commit 4a6fc35384.

* Revert "Update spectrum_collector.cpp"

This reverts commit 35cece1cb0.

* Revert "Solving Compile error on gcc10 . Keeping same safety protection about the size of the array ,but with slightly different sintax."

This reverts commit f4db4e2b53.

* Recovered CTCSS-Roger_beep-MIC-GAIN from 1.5.1

* Temporary removing ALC-( for AK4951 platorm)
2022-05-07 11:43:14 +12:00
69 changed files with 1253 additions and 705 deletions
+10 -4
View File
@@ -1,12 +1,18 @@
---
name: Bug report
about: Create a report to help us improve
about: Create a report to help us improve the software
title: ''
labels: bug
assignees: ''
---
----
(Please try the latest nightly release before submitting this. You can find the latest nightly verison here: https://github.com/eried/portapack-mayhem/releases)
----
**Describe the bug**
A clear and concise description of what the bug is.
@@ -21,9 +27,9 @@ A clear and concise description of what you expected to happen.
**Affected versions**
Please write any difference related with the Expected behavior, on the following versions:
* Latest Stable Release
* Previous one (if any) that did not presented the issue
* Old versions available here: https://github.com/eried/Research/tree/master/HackRF/PortaPack/old_legacy_firmware
* Latest Stable release:
* Latest Nightly release:
* Previous working release:
**Additional**
If the bug is difficult to explain, additionally to the text please include images and videos.
@@ -1,18 +1,39 @@
---
name: Problem upgrading the firmware
about: Deal with the firmware upgrade problems
title: Problem upgrading the firmware
labels: ''
name: Problem upgrading the firmware or booting
about: If you are having firmware upgrade or booting problems
title: ''
labels: 'firmware'
assignees: ''
---
**What is happening?**
Describe here why you are unable to upgrade the firmware. Before describing your problems, **do the following**:
----
Before creating this issue, **do the following**:
* Read the Wiki on booting: https://github.com/eried/portapack-mayhem/wiki/Won't-boot
* Read: https://github.com/eried/portapack-havoc/wiki/Update-firmware
* Watch carefully: https://www.youtube.com/watch?v=_zx4ZvurgOs
* (if you are not in Windows) also check: https://www.youtube.com/watch?v=kjFB58Y1TAo
----
**Describe the issue**
A clear and concise description of what the issue you are facing is.
**To Reproduce**
Steps to reproduce the behavior:
1. Go to '...'
2. Tap on '....'
**My Hardware**
Please specify what PortaPack hardware version you are using.
You can find the list of versions here: https://github.com/eried/portapack-mayhem/wiki/PortaPack-Versions
**Affected versions**
Please tell us what version you are running.
Also please try the latest nightly release before submitting this.
You can find the latest nightly version here https://github.com/eried/portapack-mayhem/releases
**Were you able to update the firmware before?**
Things might be confusing the first time, please check the video available on the link above.
@@ -20,4 +41,4 @@ Things might be confusing the first time, please check the video available on th
If is possible, swap hardware and try again. Also, try different USB cables, even if the one you are using works fine for other purposes.
**Additional**
Add photos and videos of your procedure.
If the issue is difficult to explain, additionally to the text please include images and videos.
+1 -1
View File
@@ -51,7 +51,7 @@ jobs:
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
tag_name: v1.5.1
tag_name: ${{ steps.version.outputs.version }}
release_name: Mayhem firmware ${{ steps.version.outputs.version }}
body: |
**Stable release - ${{ steps.version.outputs.version }}**
+1 -1
View File
@@ -1 +1 @@
v1.5.0
v1.5.3
+1 -1
View File
@@ -1 +1 @@
v1.5.1
v1.5.4
-1
View File
@@ -27,7 +27,6 @@
# Compiled Dynamic libraries
*.so
*.dylib
*.dll
# Fortran module files
*.mod
+30 -41
View File
@@ -27,56 +27,30 @@
#include "portapack.hpp"
#include "portapack_persistent_memory.hpp"
#include <cstring>
#include <algorithm>
namespace std {
int app_settings::load(std::string application, AppSettings* settings){
int app_settings::load(std::string application, AppSettings* settings) {
if (portapack::persistent_memory::load_app_settings()) {
file_path = folder+"/"+application+".ini";
auto error = settings_file.open(file_path);
if (!error.is_valid()) {
auto error = settings_file.read(file_content, 256);
// Retrieve settings
auto position1 = strstr(file_content, "baseband_bandwidth=");
if (position1) {
position1 += 19;
settings->baseband_bandwidth=strtoll(position1, nullptr, 10);
}
auto position2 = strstr(file_content, "rx_frequency=");
if (position2) {
position2 += 13;
settings->rx_frequency=strtoll(position2, nullptr, 10);
}
auto position3 = strstr(file_content, "lna=");
if (position3) {
position3 += 4;
settings->lna=strtoll(position3, nullptr, 10);
}
auto position4 = strstr(file_content, "rx_amp=");
if (position4) {
position4 += 7;
settings->rx_amp=strtoll(position4, nullptr, 10);
}
auto position5 = strstr(file_content, "sampling_rate=");
if (position5) {
position5 += 13;
settings->sampling_rate=strtoll(position5, nullptr, 10);
}
auto position6 = strstr(file_content, "vga=");
if (position6) {
position6 += 4;
settings->vga=strtoll(position6, nullptr, 10);
}
auto error = settings_file.read(file_content, std::min((int)settings_file.size(), MAX_FILE_CONTENT_SIZE));
settings->baseband_bandwidth=std::app_settings::read_long_long(file_content, "baseband_bandwidth=");
settings->channel_bandwidth=std::app_settings::read_long_long(file_content, "channel_bandwidth=");
settings->lna=std::app_settings::read_long_long(file_content, "lna=");
settings->modulation=std::app_settings::read_long_long(file_content, "modulation=");
settings->rx_amp=std::app_settings::read_long_long(file_content, "rx_amp=");
settings->rx_frequency=std::app_settings::read_long_long(file_content, "rx_frequency=");
settings->sampling_rate=std::app_settings::read_long_long(file_content, "sampling_rate=");
settings->vga=std::app_settings::read_long_long(file_content, "vga=");
settings->tx_amp=std::app_settings::read_long_long(file_content, "tx_amp=");
settings->tx_frequency=std::app_settings::read_long_long(file_content, "tx_frequency=");
settings->tx_gain=std::app_settings::read_long_long(file_content, "tx_gain=");
rc = SETTINGS_OK;
}
else rc = SETTINGS_UNABLE_TO_LOAD;
@@ -85,7 +59,7 @@ int app_settings::load(std::string application, AppSettings* settings){
return(rc);
}
int app_settings::save(std::string application, AppSettings* settings){
int app_settings::save(std::string application, AppSettings* settings) {
if (portapack::persistent_memory::save_app_settings()) {
file_path = folder+"/"+application+".ini";
@@ -95,12 +69,16 @@ int app_settings::save(std::string application, AppSettings* settings){
if (!error.is_valid()) {
// Save common setting
settings_file.write_line("baseband_bandwidth="+to_string_dec_uint(portapack::receiver_model.baseband_bandwidth()));
settings_file.write_line("channel_bandwidth="+to_string_dec_uint(portapack::transmitter_model.channel_bandwidth()));
settings_file.write_line("lna="+to_string_dec_uint(portapack::receiver_model.lna()));
settings_file.write_line("rx_amp="+to_string_dec_uint(portapack::receiver_model.rf_amp()));
settings_file.write_line("sampling_rate="+to_string_dec_uint(portapack::receiver_model.sampling_rate()));
settings_file.write_line("tx_amp="+to_string_dec_uint(portapack::transmitter_model.rf_amp()));
settings_file.write_line("tx_gain="+to_string_dec_uint(portapack::transmitter_model.tx_gain()));
settings_file.write_line("vga="+to_string_dec_uint(portapack::receiver_model.vga()));
// Save other settings from struct
settings_file.write_line("rx_frequency="+to_string_dec_uint(settings->rx_frequency));
settings_file.write_line("tx_frequency="+to_string_dec_uint(settings->tx_frequency));
rc = SETTINGS_OK;
}
@@ -110,4 +88,15 @@ int app_settings::save(std::string application, AppSettings* settings){
return(rc);
}
long long int app_settings::read_long_long(char* file_content, const char* setting_text) {
auto position = strstr(file_content, (char *)setting_text);
if (position) {
position += strlen((char *)setting_text);
setting_value = strtoll(position, nullptr, 10);
}
return(setting_value);
}
} /* namespace std */
+12 -3
View File
@@ -46,13 +46,18 @@ public:
#define SETTINGS_DISABLED -3 // load/save settings disabled in settings
// store settings that can't be set directly, but have to be stored in app
struct AppSettings {
uint32_t baseband_bandwidth;
uint32_t channel_bandwidth;
uint8_t lna;
uint8_t modulation;
uint8_t rx_amp;
uint32_t rx_frequency;
uint32_t sampling_rate;
uint8_t tx_amp;
uint32_t tx_frequency;
uint8_t tx_gain;
uint8_t vga;
};
@@ -62,12 +67,16 @@ public:
private:
#define MAX_FILE_CONTENT_SIZE 1000
char file_content[257] = {};
char file_content[MAX_FILE_CONTENT_SIZE] = {};
std::string file_path = "";
std::string folder = "SETTINGS";
int rc = SETTINGS_OK;
File settings_file { };
File settings_file { };
long long int setting_value {} ;
long long int read_long_long(char* file_content, const char* setting_text);
}; // class app_settings
@@ -139,7 +139,6 @@ AnalogAudioView::AnalogAudioView(
}
else field_frequency.set_value(receiver_model.tuning_frequency());
//Filename Datetime and Frequency
record_view.set_filename_date_frequency(true);
@@ -170,6 +169,7 @@ AnalogAudioView::AnalogAudioView(
const auto modulation = receiver_model.modulation();
options_modulation.set_by_value(toUType(modulation));
options_modulation.on_change = [this](size_t, OptionsField::value_t v) {
this->on_modulation_changed(static_cast<ReceiverModel::Mode>(v));
};
@@ -193,7 +193,7 @@ AnalogAudioView::AnalogAudioView(
audio::output::start();
update_modulation(static_cast<ReceiverModel::Mode>(modulation));
on_modulation_changed(static_cast<ReceiverModel::Mode>(modulation));
on_modulation_changed(static_cast<ReceiverModel::Mode>(modulation));
}
size_t AnalogAudioView::get_spec_bw_index() {
@@ -412,9 +412,6 @@ void AnalogAudioView::update_modulation(const ReceiverModel::Mode modulation) {
}
}
/*void AnalogAudioView::squelched() {
if (exit_on_squelch) nav_.pop();
}*/
void AnalogAudioView::handle_coded_squelch(const uint32_t value) {
float diff, min_diff = value;
+53 -40
View File
@@ -39,10 +39,14 @@ using namespace portapack;
namespace ui {
void LGEView::focus() {
options_trame.focus();
options_frame.focus();
}
LGEView::~LGEView() {
// save app settings
app_settings.tx_frequency = transmitter_model.tuning_frequency();
settings.save("tx_lge", &app_settings);
transmitter_model.disable();
baseband::shutdown();
}
@@ -70,10 +74,10 @@ void LGEView::generate_frame_touche() {
std::vector<uint8_t> data { 0x46, 0x28, 0x01, 0x45, 0x27, 0x01, 0x44, 0x23 };
console.write("\n\x1B\x07Touche:\x1B\x10");
generate_lge_frame(0x96, (field_joueur.value() << 8) | field_salle.value(), 0x0001, data);
generate_lge_frame(0x96, (field_player.value() << 8) | field_room.value(), 0x0001, data);
}
void LGEView::generate_frame_pseudo() {
void LGEView::generate_frame_nickname() {
// 0040.48s:
// 30 02 1A 00 19 00 FF 00 02 19 42 52 45 42 49 53 20 00 00 00 00 00 00 00 00 00
// 04 01 B0 04 7F 1F 11 33 40 1F 22 01 07 00 00 01 07 00 00 63 05 00 00 99 A2
@@ -90,15 +94,15 @@ void LGEView::generate_frame_pseudo() {
};
uint32_t c;
//data_header[2] = field_salle.value(); // ?
//data_footer[0] = field_salle.value(); // ?
//data_header[2] = field_room.value(); // ?
//data_footer[0] = field_room.value(); // ?
data.insert(data.begin(), data_header.begin(), data_header.end());
data.push_back(field_joueur.value());
data.push_back(field_player.value());
c = 0;
for (auto &ch : pseudo) {
for (auto &ch : nickname) {
data.push_back(ch);
c++;
}
@@ -108,16 +112,16 @@ void LGEView::generate_frame_pseudo() {
while (++c < 16)
data.push_back(0x00);
data.push_back(field_equipe.value());
data.push_back(field_team.value());
data.insert(data.end(), data_footer.begin(), data_footer.end());
console.write("\n\x1B\x0ESet pseudo:\x1B\x10");
console.write("\n\x1B\x0ESet nickname:\x1B\x10");
generate_lge_frame(0x02, 0x001A, field_joueur.value(), data);
generate_lge_frame(0x02, 0x001A, field_player.value(), data);
}
void LGEView::generate_frame_equipe() {
void LGEView::generate_frame_team() {
// 0041.83s:
// 3D 03 FF FF FF FF 02 03 01 52 4F 55 47 45 00 00 00 00 00 00 00 00 00 00 00 00
// 02 56 45 52 54 45 00 00 00 00 00 00 00 00 00 00 00 01 03 42 4C 45 55 45 00 00
@@ -129,10 +133,10 @@ void LGEView::generate_frame_equipe() {
data.insert(data.begin(), data_header.begin(), data_header.end());
data.push_back(field_equipe.value());
data.push_back(field_team.value());
c = 0;
for (auto &ch : pseudo) {
for (auto &ch : nickname) {
data.push_back(ch);
c++;
}
@@ -140,14 +144,14 @@ void LGEView::generate_frame_equipe() {
while (c++ < 16)
data.push_back(0x00);
data.push_back(field_equipe.value() - 1); // Color ?
data.push_back(field_team.value() - 1); // Color ?
console.write("\n\x1B\x0ASet equipe:\x1B\x10");
console.write("\n\x1B\x0ASet team:\x1B\x10");
generate_lge_frame(0x03, data);
}
void LGEView::generate_frame_broadcast_pseudo() {
void LGEView::generate_frame_broadcast_nickname() {
// 0043.86s:
// 3D 04 FF FF FF FF 02 03 19 42 52 45 42 49 53 20 00 00 00 00 00 00 00 00 00 04
// 07 50 4F 4E 45 59 20 00 00 00 00 00 00 00 00 00 00 05 1B 41 42 42 59 20 00 00
@@ -159,10 +163,10 @@ void LGEView::generate_frame_broadcast_pseudo() {
data.insert(data.begin(), data_header.begin(), data_header.end());
data.push_back(field_joueur.value());
data.push_back(field_player.value());
c = 0;
for (auto &ch : pseudo) {
for (auto &ch : nickname) {
data.push_back(ch);
c++;
}
@@ -172,9 +176,9 @@ void LGEView::generate_frame_broadcast_pseudo() {
while (++c < 16)
data.push_back(0x00);
data.push_back(field_equipe.value());
data.push_back(field_team.value());
console.write("\n\x1B\x09" "Broadcast pseudo:\x1B\x10");
console.write("\n\x1B\x09" "Broadcast nickname:\x1B\x10");
generate_lge_frame(0x04, data);
}
@@ -184,14 +188,14 @@ void LGEView::generate_frame_start() {
// 0A 05 FF FF FF FF 02 EC FF FF FF A3 35
std::vector<uint8_t> data { 0x02, 0xEC, 0xFF, 0xFF, 0xFF };
//data[0] = field_salle.value(); // ?
//data[0] = field_room.value(); // ?
console.write("\n\x1B\x0DStart:\x1B\x10");
generate_lge_frame(0x05, data);
}
void LGEView::generate_frame_gameover() {
std::vector<uint8_t> data { (uint8_t)field_salle.value() };
std::vector<uint8_t> data { (uint8_t)field_room.value() };
console.write("\n\x1B\x0CGameover:\x1B\x10");
generate_lge_frame(0x0D, data);
@@ -203,7 +207,7 @@ void LGEView::generate_frame_collier() {
// Custom
// 0C 00 13 37 13 37 id flags channel playerid zapduty zaptime checksum CRC CRC
// channel: field_channel
// playerid: field_joueur
// playerid: field_player
// zapduty: field_power
// zaptime: field_duration
@@ -218,8 +222,8 @@ void LGEView::generate_frame_collier() {
std::vector<uint8_t> data {
id,
flags,
(uint8_t)field_salle.value(),
(uint8_t)field_joueur.value(),
(uint8_t)field_room.value(),
(uint8_t)field_player.value(),
(uint8_t)field_power.value(),
(uint8_t)(field_duration.value() * 10)
};
@@ -285,11 +289,11 @@ LGEView::LGEView(NavigationView& nav) {
add_children({
&labels,
&options_trame,
&field_salle,
&button_texte,
&field_equipe,
&field_joueur,
&options_frame,
&field_room,
&button_text,
&field_team,
&field_player,
&field_id,
&field_power,
&field_duration,
@@ -300,20 +304,29 @@ LGEView::LGEView(NavigationView& nav) {
&tx_view
});
field_salle.set_value(1);
field_equipe.set_value(1);
field_joueur.set_value(1);
// load app settings
auto rc = settings.load("tx_lge", &app_settings);
if(rc == SETTINGS_OK) {
transmitter_model.set_rf_amp(app_settings.tx_amp);
transmitter_model.set_channel_bandwidth(app_settings.channel_bandwidth);
transmitter_model.set_tuning_frequency(app_settings.tx_frequency);
transmitter_model.set_tx_gain(app_settings.tx_gain);
}
field_room.set_value(1);
field_team.set_value(1);
field_player.set_value(1);
field_id.set_value(1);
field_power.set_value(1);
field_duration.set_value(2);
button_texte.on_select = [this, &nav](Button&) {
button_text.on_select = [this, &nav](Button&) {
text_prompt(
nav,
pseudo,
nickname,
15,
[this](std::string& buffer) {
button_texte.set_text(buffer);
button_text.set_text(buffer);
});
};
@@ -326,15 +339,15 @@ LGEView::LGEView(NavigationView& nav) {
tx_view.on_start = [this]() {
if (tx_mode == IDLE) {
auto i = options_trame.selected_index_value();
auto i = options_frame.selected_index_value();
if (i == 0)
generate_frame_touche();
else if (i == 1)
generate_frame_pseudo();
generate_frame_nickname();
else if (i == 2)
generate_frame_equipe();
generate_frame_team();
else if (i == 3)
generate_frame_broadcast_pseudo();
generate_frame_broadcast_nickname();
else if (i == 4)
generate_frame_start();
else if (i == 5)
+27 -22
View File
@@ -30,6 +30,7 @@
#include "message.hpp"
#include "transmitter_model.hpp"
#include "portapack.hpp"
#include "app_settings.hpp"
namespace ui {
@@ -48,15 +49,19 @@ private:
SINGLE,
ALL
};
// app save settings
std::app_settings settings { };
std::app_settings::AppSettings app_settings { };
tx_modes tx_mode = IDLE;
RFM69 rfm69 { 5, 0x2DD4, true, true };
RFM69 rfm69 { 5, 0x2DD4, true, true };
uint32_t frame_size { 0 };
uint32_t repeats { 0 };
uint32_t channel_index { 0 };
std::string pseudo { "ABCDEF" };
std::string nickname { "ABCDEF" };
rf::Frequency channels[3] = { 868067000, 868183000, 868295000 };
@@ -68,9 +73,9 @@ private:
}
void generate_lge_frame(const uint8_t command, const uint16_t address_a, const uint16_t address_b, std::vector<uint8_t>& data);
void generate_frame_touche();
void generate_frame_pseudo();
void generate_frame_equipe();
void generate_frame_broadcast_pseudo();
void generate_frame_nickname();
void generate_frame_team();
void generate_frame_broadcast_nickname();
void generate_frame_start();
void generate_frame_gameover();
void generate_frame_collier();
@@ -79,28 +84,28 @@ private:
Labels labels {
//{ { 7 * 8, 1 * 8 }, "NO FUN ALLOWED !", Color::red() },
{ { 1 * 8, 1 * 8 }, "Trame:", Color::light_grey() },
{ { 1 * 8, 3 * 8 }, "Salle:", Color::light_grey() },
{ { 14 * 8, 3 * 8 }, "Texte:", Color::light_grey() },
{ { 0 * 8, 5 * 8 }, "Equipe:", Color::light_grey() },
{ { 0 * 8, 7 * 8 }, "Joueur:", Color::light_grey() },
{ { 0 * 8, 10 * 8 }, "Collier:", Color::light_grey() },
{ { 1 * 8, 1 * 8 }, "Frame:", Color::light_grey() },
{ { 2 * 8, 3 * 8 }, "Room:", Color::light_grey() },
{ { 14 * 8, 3 * 8 }, "Text:", Color::light_grey() },
{ { 2 * 8, 5 * 8 }, "Team:", Color::light_grey() },
{ { 0 * 8, 7 * 8 }, "Player:", Color::light_grey() },
{ { 0 * 8, 10 * 8 }, "Vest:", Color::light_grey() },
{ { 4 * 8, 12 * 8 }, "ID:", Color::light_grey() },
{ { 3 * 8, 14 * 8 }, "Pow: /10", Color::light_grey() },
{ { 1 * 8, 16 * 8 }, "Duree: x100ms", Color::light_grey() }
{ { 2 * 8, 16 * 8 }, "Time: x100ms", Color::light_grey() }
};
OptionsField options_trame {
OptionsField options_frame {
{ 7 * 8, 1 * 8 },
13,
{
{ "Touche", 0 },
{ "Set pseudo", 1 },
{ "Set equipe", 2 },
{ "Brdcst pseudo", 3 },
{ "Key", 0 },
{ "Set nickname", 1 },
{ "Set team", 2 },
{ "Brdcst nick", 3 },
{ "Start", 4 },
{ "Game over", 5 },
{ "Set collier", 6 }
{ "Set vest", 6 }
}
};
@@ -111,7 +116,7 @@ private:
true
};
NumberField field_salle {
NumberField field_room {
{ 7 * 8, 3 * 8 },
1,
{ 1, 2 },
@@ -119,12 +124,12 @@ private:
'0'
};
Button button_texte {
Button button_text {
{ 14 * 8, 5 * 8, 16 * 8, 3 * 8 },
"ABCDEF"
};
NumberField field_equipe {
NumberField field_team {
{ 7 * 8, 5 * 8 },
1,
{ 1, 6 },
@@ -132,7 +137,7 @@ private:
'0'
};
NumberField field_joueur {
NumberField field_player {
{ 7 * 8, 7 * 8 },
2,
{ 1, 50 },
+2
View File
@@ -87,6 +87,8 @@ POCSAGAppView::POCSAGAppView(NavigationView& nav) {
}
else field_frequency.set_value(receiver_model.tuning_frequency());
receiver_model.set_modulation(ReceiverModel::Mode::NarrowbandFMAudio);
receiver_model.set_sampling_rate(3072000);
receiver_model.set_baseband_bandwidth(1750000);
receiver_model.enable();
+10
View File
@@ -201,6 +201,16 @@ ReplayAppView::ReplayAppView(
tx_gain = 35;field_rfgain.set_value(tx_gain); // Initial default value (-12 dB's max ).
field_rfamp.set_value(rf_amp ? 14 : 0); // Initial default value True. (TX RF amp on , +14dB's)
field_rfamp.on_change = [this](int32_t v) { // allow initial value change just after opened file.
rf_amp = (bool)v;
};
field_rfamp.set_value(rf_amp ? 14 : 0);
field_rfgain.on_change = [this](int32_t v) { // allow initial value change just after opened file.
tx_gain = v;
};
field_rfgain.set_value(tx_gain);
baseband::run_image(portapack::spi_flash::image_tag_replay);
add_children({
@@ -240,6 +240,15 @@ SoundBoardView::SoundBoardView(
&button_next_page,
&tx_view
});
// load app settings
auto rc = settings.load("tx_soundboard", &app_settings);
if(rc == SETTINGS_OK) {
transmitter_model.set_rf_amp(app_settings.tx_amp);
transmitter_model.set_channel_bandwidth(app_settings.channel_bandwidth);
transmitter_model.set_tuning_frequency(app_settings.tx_frequency);
transmitter_model.set_tx_gain(app_settings.tx_gain);
}
refresh_list();
@@ -280,6 +289,10 @@ SoundBoardView::SoundBoardView(
}
SoundBoardView::~SoundBoardView() {
// save app settings
app_settings.tx_frequency = transmitter_model.tuning_frequency();
settings.save("tx_soundboard", &app_settings);
stop();
transmitter_model.disable();
baseband::shutdown();
@@ -30,6 +30,7 @@
#include "lfsr_random.hpp"
#include "io_wave.hpp"
#include "tone_key.hpp"
#include "app_settings.hpp"
namespace ui {
@@ -49,6 +50,10 @@ public:
private:
NavigationView& nav_;
// app save settings
std::app_settings settings { };
std::app_settings::AppSettings app_settings { };
enum tx_modes {
NORMAL = 0,
+1
View File
@@ -313,6 +313,7 @@ ADSBRxView::~ADSBRxView() {
// save app settings
settings.save("rx_adsb", &app_settings);
//TODO: once all apps keep there own settin previous frequency logic can be removed
receiver_model.set_tuning_frequency(prevFreq);
rtc_time::signal_tick_second -= signal_token_tick_second;
receiver_model.disable();
+15 -2
View File
@@ -284,6 +284,11 @@ void ADSBTxView::focus() {
}
ADSBTxView::~ADSBTxView() {
// save app settings
app_settings.tx_frequency = transmitter_model.tuning_frequency();
settings.save("tx_adsb", &app_settings);
transmitter_model.disable();
baseband::shutdown();
}
@@ -334,8 +339,16 @@ ADSBTxView::ADSBTxView(
&view_squawk,
&text_frame,
&tx_view
});
});
// load app settings
auto rc = settings.load("tx_adsb", &app_settings);
if(rc == SETTINGS_OK) {
transmitter_model.set_tuning_frequency(app_settings.tx_frequency);
transmitter_model.set_rf_amp(app_settings.tx_amp);
transmitter_model.set_tx_gain(app_settings.tx_gain);
}
tx_view.on_edit_frequency = [this, &nav]() {
auto new_view = nav.push<FrequencyKeypadView>(receiver_model.tuning_frequency());
new_view->on_changed = [this](rf::Frequency f) {
+5
View File
@@ -28,6 +28,7 @@
#include "ui_transmitter.hpp"
#include "message.hpp"
#include "transmitter_model.hpp"
#include "app_settings.hpp"
#include "portapack.hpp"
using namespace adsb;
@@ -189,6 +190,10 @@ private:
-1,
-1
};*/
// app save settings
std::app_settings settings { };
std::app_settings::AppSettings app_settings { };
//tx_modes tx_mode = IDLE;
NavigationView& nav_;
+14 -1
View File
@@ -43,6 +43,10 @@ void APRSTXView::focus() {
}
APRSTXView::~APRSTXView() {
// save app settings
app_settings.tx_frequency = transmitter_model.tuning_frequency();
settings.save("tx_aprs", &app_settings);
transmitter_model.disable();
baseband::shutdown();
}
@@ -66,7 +70,7 @@ void APRSTXView::start_tx() {
1200,
2200,
1,
10000, //transmitter_model.channel_bandwidth(),
10000, //APRS uses fixed 10k bandwidth
8
);
}
@@ -95,6 +99,15 @@ APRSTXView::APRSTXView(NavigationView& nav) {
&tx_view
});
// load app settings
auto rc = settings.load("tx_aprs", &app_settings);
if(rc == SETTINGS_OK) {
transmitter_model.set_rf_amp(app_settings.tx_amp);
transmitter_model.set_tuning_frequency(app_settings.tx_frequency);
transmitter_model.set_tx_gain(app_settings.tx_gain);
}
button_set.on_select = [this, &nav](Button&) {
text_prompt(
nav,
+7 -9
View File
@@ -29,6 +29,7 @@
#include "message.hpp"
#include "transmitter_model.hpp"
#include "app_settings.hpp"
#include "portapack.hpp"
namespace ui {
@@ -40,17 +41,14 @@ public:
void focus() override;
std::string title() const override { return "APRS TX (beta)"; };
std::string title() const override { return "APRS TX"; };
private:
/*enum tx_modes {
IDLE = 0,
SINGLE,
SEQUENCE
};
tx_modes tx_mode = IDLE;*/
// app save settings
std::app_settings settings { };
std::app_settings::AppSettings app_settings { };
std::string payload { "" };
void start_tx();
@@ -103,7 +101,7 @@ private:
TransmitterView tx_view {
16 * 16,
5000,
10
0 // disable setting bandwith, since APRS used fixed 10k bandwidth
};
MessageHandlerRegistration message_handler_tx_progress {
+20 -7
View File
@@ -96,9 +96,9 @@ void BHTView::on_tx_progress(const uint32_t progress, const bool done) {
if (target_system == XYLOS) {
if (done) {
if (tx_mode == SINGLE) {
if (checkbox_cligno.value()) {
if (checkbox_flashing.value()) {
// TODO: Thread !
chThdSleepMilliseconds(field_tempo.value() * 1000); // Dirty :(
chThdSleepMilliseconds(field_speed.value() * 1000); // Dirty :(
view_xylos.flip_relays();
start_tx();
} else
@@ -120,9 +120,9 @@ void BHTView::on_tx_progress(const uint32_t progress, const bool done) {
} else {
view_EPAR.half = false;
if (tx_mode == SINGLE) {
if (checkbox_cligno.value()) {
if (checkbox_flashing.value()) {
// TODO: Thread !
chThdSleepMilliseconds(field_tempo.value() * 1000); // Dirty :(
chThdSleepMilliseconds(field_speed.value() * 1000); // Dirty :(
view_EPAR.flip_relays();
start_tx();
} else
@@ -140,6 +140,10 @@ void BHTView::on_tx_progress(const uint32_t progress, const bool done) {
}
BHTView::~BHTView() {
// save app settings
app_settings.tx_frequency = transmitter_model.tuning_frequency();
settings.save("tx_bht", &app_settings);
transmitter_model.disable();
}
@@ -150,13 +154,22 @@ BHTView::BHTView(NavigationView& nav) {
&view_xylos,
&view_EPAR,
&checkbox_scan,
&checkbox_cligno,
&field_tempo,
&checkbox_flashing,
&field_speed,
&progressbar,
&tx_view
});
field_tempo.set_value(1);
// load app settings
auto rc = settings.load("tx_bht", &app_settings);
if(rc == SETTINGS_OK) {
transmitter_model.set_rf_amp(app_settings.tx_amp);
transmitter_model.set_channel_bandwidth(app_settings.channel_bandwidth);
transmitter_model.set_tuning_frequency(app_settings.tx_frequency);
transmitter_model.set_tx_gain(app_settings.tx_gain);
}
field_speed.set_value(1);
tx_view.on_edit_frequency = [this, &nav]() {
auto new_view = nav.push<FrequencyKeypadView>(receiver_model.tuning_frequency());
+21 -16
View File
@@ -32,6 +32,7 @@
#include "message.hpp"
#include "transmitter_model.hpp"
#include "encoders.hpp"
#include "app_settings.hpp"
#include "portapack.hpp"
namespace ui {
@@ -50,11 +51,11 @@ public:
private:
Labels labels {
{ { 8 * 8, 1 * 8 }, "Header:", Color::light_grey() },
{ { 4 * 8, 3 * 8 }, "Code ville:", Color::light_grey() },
{ { 7 * 8, 5 * 8 }, "Famille:", Color::light_grey() },
{ { 2 * 8, 7 * 8 + 2 }, "Sous-famille:", Color::light_grey() },
{ { 2 * 8, 11 * 8 }, "ID recepteur:", Color::light_grey() },
{ { 2 * 8, 14 * 8 }, "Relais:", Color::light_grey() }
{ { 4 * 8, 3 * 8 }, "City code:", Color::light_grey() },
{ { 7 * 8, 5 * 8 }, "Family:", Color::light_grey() },
{ { 2 * 8, 7 * 8 + 2 }, "Subfamily:", Color::light_grey() },
{ { 2 * 8, 11 * 8 }, "Receiver ID:", Color::light_grey() },
{ { 2 * 8, 14 * 8 }, "Relay:", Color::light_grey() }
};
NumberField field_header_a {
@@ -98,8 +99,8 @@ private:
Checkbox checkbox_wcsubfamily {
{ 20 * 8, 6 * 8 + 6 },
6,
"Toutes"
3,
"All"
};
NumberField field_receiver {
@@ -111,8 +112,8 @@ private:
};
Checkbox checkbox_wcid {
{ 20 * 8, 10 * 8 + 4 },
4,
"Tous"
3,
"All"
};
std::array<ImageOptionsField, 4> relay_states { };
@@ -139,9 +140,9 @@ public:
private:
Labels labels {
{ { 4 * 8, 1 * 8 }, "Code ville:", Color::light_grey() },
{ { 8 * 8, 3 * 8 }, "Groupe:", Color::light_grey() },
{ { 8 * 8, 7 * 8 }, "Relais:", Color::light_grey() }
{ { 4 * 8, 1 * 8 }, "City code:", Color::light_grey() },
{ { 8 * 8, 3 * 8 }, "Group:", Color::light_grey() },
{ { 8 * 8, 7 * 8 }, "Relay:", Color::light_grey() }
};
NumberField field_city {
@@ -181,6 +182,10 @@ public:
std::string title() const override { return "BHT Xy/EP TX"; };
private:
// app save settings
std::app_settings settings { };
std::app_settings::AppSettings app_settings { };
void on_tx_progress(const uint32_t progress, const bool done);
void start_tx();
void stop_tx();
@@ -220,12 +225,12 @@ private:
"Scan"
};
Checkbox checkbox_cligno {
Checkbox checkbox_flashing {
{ 16 * 8, 25 * 8 },
6,
"Cligno"
8,
"Flashing"
};
NumberField field_tempo {
NumberField field_speed {
{ 26 * 8, 25 * 8 + 4 },
2,
{ 1, 99 },
+13
View File
@@ -37,6 +37,10 @@ void CoasterPagerView::focus() {
}
CoasterPagerView::~CoasterPagerView() {
// save app settings
app_settings.tx_frequency = transmitter_model.tuning_frequency();
settings.save("tx_coaster", &app_settings);
transmitter_model.disable();
baseband::shutdown();
}
@@ -119,6 +123,15 @@ CoasterPagerView::CoasterPagerView(NavigationView& nav) {
&tx_view
});
// load app settings
auto rc = settings.load("tx_coaster", &app_settings);
if(rc == SETTINGS_OK) {
transmitter_model.set_rf_amp(app_settings.tx_amp);
transmitter_model.set_channel_bandwidth(app_settings.channel_bandwidth);
transmitter_model.set_tuning_frequency(app_settings.tx_frequency);
transmitter_model.set_tx_gain(app_settings.tx_gain);
}
// Bytes to nibbles
for (c = 0; c < 16; c++)
sym_data.set_sym(c, (data_init[c >> 1] >> ((c & 1) ? 0 : 4)) & 0x0F);
@@ -28,6 +28,7 @@
#include "message.hpp"
#include "transmitter_model.hpp"
#include "app_settings.hpp"
#include "portapack.hpp"
namespace ui {
@@ -50,6 +51,10 @@ private:
tx_modes tx_mode = IDLE;
// app save settings
std::app_settings settings { };
std::app_settings::AppSettings app_settings { };
void start_tx();
void generate_frame();
void on_tx_progress(const uint32_t progress, const bool done);
+13
View File
@@ -203,6 +203,10 @@ void EncodersView::focus() {
}
EncodersView::~EncodersView() {
// save app settings
app_settings.tx_frequency = transmitter_model.tuning_frequency();
settings.save("tx_ook", &app_settings);
transmitter_model.disable();
baseband::shutdown();
}
@@ -335,6 +339,15 @@ EncodersView::EncodersView(
&tx_view
});
// load app settings
auto rc = settings.load("tx_ook", &app_settings);
if(rc == SETTINGS_OK) {
transmitter_model.set_rf_amp(app_settings.tx_amp);
transmitter_model.set_channel_bandwidth(app_settings.channel_bandwidth);
transmitter_model.set_tuning_frequency(app_settings.tx_frequency);
transmitter_model.set_tx_gain(app_settings.tx_gain);
}
tx_view.on_edit_frequency = [this, &nav]() {
auto new_view = nav.push<FrequencyKeypadView>(transmitter_model.tuning_frequency());
new_view->on_changed = [this](rf::Frequency f) {
@@ -26,6 +26,7 @@
#include "transmitter_model.hpp"
#include "encoders.hpp"
#include "de_bruijn.hpp"
#include "app_settings.hpp"
using namespace encoders;
@@ -169,6 +170,10 @@ private:
SCAN
};
// app save settings
std::app_settings settings { };
std::app_settings::AppSettings app_settings { };
tx_modes tx_mode = IDLE;
uint8_t repeat_index { 0 };
uint8_t repeat_min { 0 };
+10
View File
@@ -136,6 +136,9 @@ void KeyfobView::focus() {
}
KeyfobView::~KeyfobView() {
// save app settings
settings.save("tx_keyfob", &app_settings);
transmitter_model.disable();
baseband::shutdown();
}
@@ -214,6 +217,13 @@ KeyfobView::KeyfobView(
&tx_view
});
// load app settings
auto rc = settings.load("tx_keyfob", &app_settings);
if(rc == SETTINGS_OK) {
transmitter_model.set_rf_amp(app_settings.tx_amp);
transmitter_model.set_tx_gain(app_settings.tx_gain);
}
frame[0] = 0x55;
update_symfields();
+5
View File
@@ -23,6 +23,7 @@
#include "ui.hpp"
#include "ui_transmitter.hpp"
#include "transmitter_model.hpp"
#include "app_settings.hpp"
#include "encoders.hpp"
using namespace encoders;
@@ -41,6 +42,10 @@ public:
private:
NavigationView& nav_;
// app save settings
std::app_settings settings { };
std::app_settings::AppSettings app_settings { };
// 1013210ns / bit
static constexpr uint32_t subaru_samples_per_bit = (OOK_SAMPLERATE * 0.00101321);
static constexpr uint32_t repeats = 4;
+13
View File
@@ -39,6 +39,10 @@ void LCRView::focus() {
}
LCRView::~LCRView() {
// save app settings
app_settings.tx_frequency = transmitter_model.tuning_frequency();
settings.save("tx_lcr", &app_settings);
transmitter_model.disable();
baseband::shutdown();
}
@@ -173,6 +177,15 @@ LCRView::LCRView(NavigationView& nav) {
&tx_view
});
// load app settings
auto rc = settings.load("tx_lcr", &app_settings);
if(rc == SETTINGS_OK) {
transmitter_model.set_rf_amp(app_settings.tx_amp);
transmitter_model.set_channel_bandwidth(app_settings.channel_bandwidth);
transmitter_model.set_tuning_frequency(app_settings.tx_frequency);
transmitter_model.set_tx_gain(app_settings.tx_gain);
}
options_scanlist.set_selected_index(0);
const auto button_set_am_fn = [this, &nav](Button& button) {
+5
View File
@@ -27,6 +27,7 @@
#include "message.hpp"
#include "transmitter_model.hpp"
#include "app_settings.hpp"
namespace ui {
@@ -81,6 +82,10 @@ private:
SCAN
};
// app save settings
std::app_settings settings { };
std::app_settings::AppSettings app_settings { };
tx_modes tx_mode = IDLE;
uint8_t scan_count { 0 }, scan_index { 0 };
uint32_t scan_progress { 0 };
+23 -9
View File
@@ -186,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_GUI_selected); // set up audio input = mic config of any audio coded AK4951/WM8731, (in WM8731 parameter will be ignored)
audio::input::start(); // set up audio input = mic config of any audio coded AK4951/WM8731, (in WM8731 parameter will be ignored)
portapack::pin_i2s0_rx_sda.mode(3);
configure_baseband();
}
@@ -212,7 +212,7 @@ MicTXView::MicTXView(
baseband::run_image(portapack::spi_flash::image_tag_mic_tx);
if ( audio_codec_wm8731.detected() ) {
if (true ) { // Temporary , disabling ALC feature , (pending to solve -No Audio in Mic app ,in some H2/H2+ WM /QFP100 CPLS users- if ( audio_codec_wm8731.detected() ) {
add_children({
&labels_WM8731, // we have audio codec WM8731, same MIC menu as original.
&vumeter,
@@ -285,7 +285,7 @@ MicTXView::MicTXView(
options_ak4951_alc_mode.on_change = [this](size_t, int8_t v) {
ak4951_alc_GUI_selected = v;
audio::input::start(ak4951_alc_GUI_selected);
audio::input::start();
};
// options_ak4951_alc_mode.set_selected_index(0);
@@ -341,23 +341,37 @@ MicTXView::MicTXView(
enable_dsb = false;
field_bw.set_value(transmitter_model.channel_bandwidth() / 1000);
//if (rx_enabled)
rxaudio(rx_enabled); //Update now if we have RX audio on
rxaudio(rx_enabled); //Update now if we have RX audio on
options_tone_key.hidden(0); // we are in FM mode , we should have active the Key-tones & CTCSS option.
field_rxbw.hidden(0); // we are in FM mode, we need to allow the user set up of the RX NFM BW selection (8K5, 11K, 16K)
break;
case 1:
enable_am = true;
rxaudio(rx_enabled); //Update now if we have RX audio on
rxaudio(rx_enabled); //Update now if we have RX audio on
options_tone_key.set_selected_index(0); // we are NOT in FM mode , we reset the possible previous key-tones &CTCSS selection.
set_dirty(); // Refresh display
options_tone_key.hidden(1); // we hide that Key-tones & CTCSS input selecction, (no meaning in AM/DSB/SSB).
field_rxbw.hidden(1); // we hide the NFM BW selection in other modes non_FM (no meaning in AM/DSB/SSB)
check_rogerbeep.hidden(0); // make visible again the "rogerbeep" selection.
break;
case 2:
enable_usb = true;
rxaudio(rx_enabled); //Update now if we have RX audio on
rxaudio(rx_enabled); //Update now if we have RX audio on
check_rogerbeep.set_value(false); // reset the possible activation of roger beep, because it is not compatible with SSB , by now.
check_rogerbeep.hidden(1); // hide that roger beep selection.
set_dirty(); // Refresh display
break;
case 3:
enable_lsb = true;
rxaudio(rx_enabled); //Update now if we have RX audio on
rxaudio(rx_enabled); //Update now if we have RX audio on
check_rogerbeep.set_value(false); // reset the possible activation of roger beep, because it is not compatible with SSB , by now.
check_rogerbeep.hidden(1); // hide that roger beep selection.
set_dirty(); // Refresh display
break;
case 4:
enable_dsb = true;
rxaudio(rx_enabled); //Update now if we have RX audio on
rxaudio(rx_enabled); //Update now if we have RX audio on
check_rogerbeep.hidden(0); // make visible again the "rogerbeep" selection.
break;
}
//configure_baseband();
@@ -525,7 +539,7 @@ MicTXView::MicTXView(
set_tx(false);
audio::set_rate(audio::Rate::Hz_24000);
audio::input::start(ak4951_alc_GUI_selected); // originally , audio::input::start(); (we added parameter)
audio::input::start(); // originally , audio::input::start(); (we added parameter)
}
MicTXView::~MicTXView() {
+13
View File
@@ -97,6 +97,10 @@ void MorseView::focus() {
}
MorseView::~MorseView() {
// save app settings
app_settings.tx_frequency = transmitter_model.tuning_frequency();
settings.save("tx_morse", &app_settings);
transmitter_model.disable();
baseband::shutdown();
}
@@ -203,6 +207,15 @@ MorseView::MorseView(
&tx_view
});
// load app settings
auto rc = settings.load("tx_morse", &app_settings);
if(rc == SETTINGS_OK) {
transmitter_model.set_rf_amp(app_settings.tx_amp);
transmitter_model.set_channel_bandwidth(app_settings.channel_bandwidth);
transmitter_model.set_tuning_frequency(app_settings.tx_frequency);
transmitter_model.set_tx_gain(app_settings.tx_gain);
}
// Default settings
field_speed.set_value(15); // 15wps
field_tone.set_value(700); // 700Hz FM tone
+5 -1
View File
@@ -27,7 +27,7 @@
#include "ui_widget.hpp"
#include "ui_navigation.hpp"
#include "ui_transmitter.hpp"
#include "app_settings.hpp"
#include "portapack.hpp"
#include "message.hpp"
#include "volume.hpp"
@@ -67,6 +67,10 @@ private:
std::string message { };
uint32_t time_units { 0 };
// app save settings
std::app_settings settings { };
std::app_settings::AppSettings app_settings { };
enum modulation_t {
CW = 0,
FM = 1
@@ -38,6 +38,10 @@ void POCSAGTXView::focus() {
}
POCSAGTXView::~POCSAGTXView() {
// save app settings
app_settings.tx_frequency = transmitter_model.tuning_frequency();
settings.save("tx_pocsag", &app_settings);
transmitter_model.disable();
baseband::shutdown();
}
@@ -141,6 +145,15 @@ POCSAGTXView::POCSAGTXView(
&tx_view
});
// load app settings
auto rc = settings.load("tx_pocsag", &app_settings);
if(rc == SETTINGS_OK) {
transmitter_model.set_rf_amp(app_settings.tx_amp);
transmitter_model.set_channel_bandwidth(app_settings.channel_bandwidth);
transmitter_model.set_tuning_frequency(app_settings.tx_frequency);
transmitter_model.set_tx_gain(app_settings.tx_gain);
}
options_bitrate.set_selected_index(1); // 1200bps
options_type.set_selected_index(0); // Address only
@@ -31,6 +31,7 @@
#include "bch_code.hpp"
#include "message.hpp"
#include "transmitter_model.hpp"
#include "app_settings.hpp"
#include "pocsag.hpp"
using namespace pocsag;
@@ -62,6 +63,10 @@ private:
5, 31, 21, 2
};
// app save settings
std::app_settings settings { };
std::app_settings::AppSettings app_settings { };
void on_set_text(NavigationView& nav);
void on_tx_progress(const uint32_t progress, const bool done);
bool start_tx();
+13 -5
View File
@@ -175,6 +175,10 @@ void RDSView::focus() {
}
RDSView::~RDSView() {
// save app settings
app_settings.tx_frequency = transmitter_model.tuning_frequency();
settings.save("tx_rds", &app_settings);
transmitter_model.disable();
baseband::shutdown();
}
@@ -226,11 +230,17 @@ RDSView::RDSView(
&view_radiotext,
&view_datetime,
&view_audio,
//&options_countrycode,
//&options_coverage,
&tx_view,
});
// load app settings
auto rc = settings.load("tx_rds", &app_settings);
if(rc == SETTINGS_OK) {
transmitter_model.set_rf_amp(app_settings.tx_amp);
transmitter_model.set_channel_bandwidth(app_settings.channel_bandwidth);
transmitter_model.set_tuning_frequency(app_settings.tx_frequency);
transmitter_model.set_tx_gain(app_settings.tx_gain);
}
check_TP.set_value(true);
sym_pi_code.set_sym(0, 0xF);
@@ -242,8 +252,6 @@ RDSView::RDSView(
};
options_pty.set_selected_index(0); // None
//options_countrycode.set_selected_index(18); // Baguette du fromage
//options_coverage.set_selected_index(0); // Local
tx_view.on_edit_frequency = [this, &nav]() {
auto new_view = nav.push<FrequencyKeypadView>(receiver_model.tuning_frequency());
+6 -1
View File
@@ -24,7 +24,7 @@
#include "ui_transmitter.hpp"
#include "ui_textentry.hpp"
#include "ui_tabview.hpp"
#include "app_settings.hpp"
#include "rds.hpp"
using namespace rds;
@@ -150,6 +150,11 @@ private:
NavigationView& nav_;
RDS_flags rds_flags { };
// app save settings
std::app_settings settings { };
std::app_settings::AppSettings app_settings { };
std::vector<RDSGroup> frame_psn { };
std::vector<RDSGroup> frame_radiotext { };
std::vector<RDSGroup> frame_datetime { };
+1 -1
View File
@@ -540,7 +540,7 @@ size_t ScannerView::change_mode(uint8_t new_mod) { //Before this, do a scan_thre
field_bw.set_selected_index(0);
receiver_model.set_am_configuration(field_bw.selected_index());
field_bw.on_change = [this](size_t n, OptionsField::value_t) { receiver_model.set_am_configuration(n); };
receiver_model.set_sampling_rate(2000000);receiver_model.set_baseband_bandwidth(2000000);
receiver_model.set_sampling_rate(3072000); receiver_model.set_baseband_bandwidth(1750000);
break;
case WFM:
bw.emplace_back("16k", 0);
+8 -12
View File
@@ -245,13 +245,9 @@ SetUIView::SetUIView(NavigationView& nav) {
checkbox_showclock.set_value(!persistent_memory::hide_clock());
checkbox_guireturnflag.set_value(persistent_memory::show_gui_return_icon());
uint32_t backlight_timer = persistent_memory::config_backlight_timer();
if (backlight_timer) {
checkbox_bloff.set_value(true);
options_bloff.set_by_value(backlight_timer);
} else {
options_bloff.set_selected_index(0);
}
const auto backlight_config = persistent_memory::config_backlight_timer();
checkbox_bloff.set_value(backlight_config.timeout_enabled());
options_bloff.set_by_value(backlight_config.timeout_enum());
if (persistent_memory::clock_with_date()) {
options_clockformat.set_selected_index(1);
@@ -261,11 +257,11 @@ SetUIView::SetUIView(NavigationView& nav) {
button_save.on_select = [&nav, this](Button&) {
if (checkbox_bloff.value())
persistent_memory::set_config_backlight_timer(options_bloff.selected_index() + 1);
else
persistent_memory::set_config_backlight_timer(0);
persistent_memory::set_config_backlight_timer({
(persistent_memory::backlight_timeout_t)options_bloff.selected_index_value(),
checkbox_bloff.value()
});
if (checkbox_showclock.value()){
if (options_clockformat.selected_index() == 1)
persistent_memory::set_clock_with_date(true);
+11 -7
View File
@@ -27,6 +27,7 @@
#include "ui_menu.hpp"
#include "ui_navigation.hpp"
#include "ff.h"
#include "portapack_persistent_memory.hpp"
#include <cstdint>
@@ -210,6 +211,8 @@ private:
SetFrequencyCorrectionModel form_collect();
};
using portapack::persistent_memory::backlight_timeout_t;
class SetUIView : public View {
public:
SetUIView(NavigationView& nav);
@@ -241,13 +244,14 @@ private:
{ 52, 7 * 16 + 8 },
20,
{
{ "5 seconds", 5 },
{ "15 seconds", 15 },
{ "30 seconds", 30 },
{ "1 minute", 60 },
{ "3 minutes", 180 },
{ "5 minutes", 300 },
{ "10 minutes", 600 }
{ "5 seconds", backlight_timeout_t::Timeout5Sec },
{ "15 seconds", backlight_timeout_t::Timeout15Sec },
{ "30 seconds", backlight_timeout_t::Timeout30Sec },
{ "1 minute", backlight_timeout_t::Timeout60Sec },
{ "3 minutes", backlight_timeout_t::Timeout180Sec },
{ "5 minutes", backlight_timeout_t::Timeout300Sec },
{ "10 minutes", backlight_timeout_t::Timeout600Sec },
{ "1 hour", backlight_timeout_t::Timeout3600Sec },
}
};
+13
View File
@@ -88,6 +88,10 @@ void SSTVTXView::paint(Painter&) {
}
SSTVTXView::~SSTVTXView() {
// save app settings
app_settings.tx_frequency = transmitter_model.tuning_frequency();
settings.save("tx_sstv", &app_settings);
transmitter_model.disable();
baseband::shutdown();
}
@@ -215,6 +219,15 @@ SSTVTXView::SSTVTXView(
options_t mode_options;
uint32_t c;
// load app settings
auto rc = settings.load("tx_sstv", &app_settings);
if(rc == SETTINGS_OK) {
transmitter_model.set_rf_amp(app_settings.tx_amp);
transmitter_model.set_channel_bandwidth(app_settings.channel_bandwidth);
transmitter_model.set_tuning_frequency(app_settings.tx_frequency);
transmitter_model.set_tx_gain(app_settings.tx_gain);
}
// Search for valid bitmaps
file_list = scan_root_files(u"/sstv", u"*.bmp");
if (!file_list.size()) {
+5 -1
View File
@@ -34,6 +34,7 @@
#include "sstv.hpp"
#include "file.hpp"
#include "bmp.hpp"
#include "app_settings.hpp"
using namespace sstv;
@@ -58,7 +59,10 @@ private:
NavigationView& nav_;
sstv_scanline scanline_buffer { };
// app save settings
std::app_settings settings { };
std::app_settings::AppSettings app_settings { };
bool file_error { false };
File bmp_file { };
bmp_header_t bmp_header { };
@@ -31,7 +31,7 @@ namespace ui {
TouchCalibrationView::TouchCalibrationView(
NavigationView& nav
) : nav { nav },
calibration { touch::default_calibration() }
calibration { touch::Calibration() }
{
add_children({
&image_calibrate_0,
+2 -2
View File
@@ -168,8 +168,8 @@ void speaker_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() {
audio_codec->microphone_enable();
i2s::i2s0::rx_start();
}
+3 -3
View File
@@ -49,7 +49,7 @@ public:
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() = 0;
virtual void microphone_disable() = 0;
virtual size_t reg_count() const = 0;
@@ -59,7 +59,7 @@ public:
namespace output {
void start(); // this other start(),no changed. ,in namespace output , used to config audio playback mode,
void start();
void stop();
void mute();
@@ -72,7 +72,7 @@ void speaker_unmute();
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();
void stop();
} /* namespace input */
+5 -3
View File
@@ -226,15 +226,17 @@ void EventDispatcher::handle_rtc_tick() {
portapack::temperature_logger.second_tick();
uint32_t backlight_timer = portapack::persistent_memory::config_backlight_timer();
if (backlight_timer) {
if (portapack::bl_tick_counter == backlight_timer)
const auto backlight_timer = portapack::persistent_memory::config_backlight_timer();
if (backlight_timer.timeout_enabled()) {
if (portapack::bl_tick_counter == backlight_timer.timeout_seconds())
set_display_sleep(true);
else
portapack::bl_tick_counter++;
}
rtc_time::on_tick_second();
portapack::persistent_memory::cache::persist();
}
ui::Widget* EventDispatcher::touch_widget(ui::Widget* const w, ui::TouchEvent event) {
+16 -4
View File
@@ -215,7 +215,7 @@ static int load_config(){
static Optional<int> config_value;
if(!config_value.is_valid()){
int8_t value = portapack::persistent_memory::config_cpld();
if((value <= 0 || value >= 4) && sd_card::status() == sd_card::Status::Mounted){
if((value <= 0 || value >= 5) && sd_card::status() == sd_card::Status::Mounted){
int data = read_file("/hardware/settings.txt");
if(data != -1) {
config_value = data;
@@ -235,14 +235,19 @@ static PortaPackModel portapack_model() {
const auto switches_state = get_switches_state();
if (switches_state[(size_t)ui::KeyEvent::Up]){
save_config(1);
model = PortaPackModel::R2_20170522;
// model = PortaPackModel::R2_20170522; // Commented these out as they should be set down below anyway
}
else if (switches_state[(size_t)ui::KeyEvent::Down]){
save_config(2);
model = PortaPackModel::R1_20150901;
// model = PortaPackModel::R1_20150901;
}
else if (switches_state[(size_t)ui::KeyEvent::Left]){
save_config(3);
// model = PortaPackModel::R1_20150901;
}
else if (switches_state[(size_t)ui::KeyEvent::Right]){
save_config(4);
// model = PortaPackModel::R2_20170522;
}
else if (switches_state[(size_t)ui::KeyEvent::Select]){
save_config(0);
@@ -253,6 +258,10 @@ static PortaPackModel portapack_model() {
model = PortaPackModel::R2_20170522;
} else if (load_config() == 2) {
model = PortaPackModel::R1_20150901;
} else if (load_config() == 3) {
model = PortaPackModel::R1_20150901;
} else if (load_config() == 4) {
model = PortaPackModel::R2_20170522;
} else {
if( audio_codec_wm8731.detected() ) {
model = PortaPackModel::R1_20150901; // H1R1
@@ -457,6 +466,9 @@ bool init() {
i2c0.start(i2c_config_fast_clock);
chThdSleepMilliseconds(10);
/* Cache some configuration data from persistent memory. */
persistent_memory::cache::init();
touch::adc::init();
controls_init();
chThdSleepMilliseconds(10);
@@ -475,7 +487,7 @@ bool init() {
if( !portapack::cpld::update_if_necessary(portapack_cpld_config()) ) {
chThdSleepMilliseconds(10);
// If using a "2021/12 QFP100", press and hold the left button while booting. Should only need to do once.
if (load_config() != 3){
if (load_config() != 3 && load_config() != 4){
shutdown_base();
return false;
}
+8
View File
@@ -45,6 +45,14 @@ struct serial_format_t {
parity_enum parity;
uint8_t stop_bits;
order_enum bit_order;
constexpr serial_format_t() :
data_bits(7),
parity(parity_enum::EVEN),
stop_bits(1),
bit_order(order_enum::LSB_FIRST)
{
}
};
size_t symbol_count(const serial_format_t& serial_format);
-8
View File
@@ -76,14 +76,6 @@ ui::Point Calibration::translate(const DigitizerPoint& p) const {
return { x_clipped, y_clipped };
}
const Calibration default_calibration() {
/* Values derived from one PortaPack H1 unit. */
return {
{ { { 256, 731 }, { 880, 432 }, { 568, 146 } } },
{ { { 32, 48 }, { 208, 168 }, { 120, 288 } } }
};
};
void Manager::feed(const Frame& frame) {
// touch_debounce.feed(touch_raw);
const auto touch_raw = frame.touch;
+9 -2
View File
@@ -137,6 +137,15 @@ struct Calibration {
{
}
constexpr Calibration() :
Calibration(
/* Values derived from one PortaPack H1 unit. */
{ { { 256, 731 }, { 880, 432 }, { 568, 146 } } },
{ { { 32, 48 }, { 208, 168 }, { 120, 288 } } }
)
{
}
ui::Point translate(const DigitizerPoint& p) const;
private:
@@ -149,8 +158,6 @@ private:
int32_t f;
};
const Calibration default_calibration();
template<size_t N>
class Filter {
public:
+97 -9
View File
@@ -21,6 +21,8 @@
#include "dsp_modulate.hpp"
#include "sine_table_int8.hpp"
#include "portapack_shared_memory.hpp"
#include "tonesets.hpp"
namespace dsp {
namespace modulate {
@@ -40,13 +42,42 @@ void Modulator::set_over(uint32_t new_over) {
over = new_over;
}
void Modulator::set_gain_vumeter_beep(float new_audio_gain , bool new_play_beep ) {
audio_gain = new_audio_gain ;
play_beep = new_play_beep;
}
int32_t Modulator::apply_beep(int32_t sample_in, bool& configured_in, uint32_t& new_beep_index, uint32_t& new_beep_timer, TXProgressMessage& new_txprogress_message ) {
if (play_beep) { // We need to add audio beep sample.
if (new_beep_timer) {
new_beep_timer--;
} else {
new_beep_timer = baseband_fs * 0.05; // 50ms
if (new_beep_index == BEEP_TONES_NB) {
configured_in = false;
shared_memory.application_queue.push(new_txprogress_message);
} else {
beep_gen.configure(beep_deltas[new_beep_index], 1.0); // config sequentially the audio beep tone.
new_beep_index++;
}
}
sample_in = beep_gen.process(0); // Get sample of the selected sequence of 6 beep tones , and overwrite audio sample. Mix 0%.
}
return sample_in; // Return audio mic scaled with gain , 8 bit sample or audio beep sample.
}
///
SSB::SSB() : hilbert() {
mode = Mode::LSB;
}
void SSB::execute(const buffer_s16_t& audio, const buffer_c8_t& buffer) {
void SSB::execute(const buffer_s16_t& audio, const buffer_c8_t& buffer, bool& configured_in, uint32_t& new_beep_index, uint32_t& new_beep_timer,TXProgressMessage& new_txprogress_message, AudioLevelReportMessage& new_level_message, uint32_t& new_power_acc_count, uint32_t& new_divider ) {
// No way to activate correctly the roger beep in this option, Maybe not enough M4 CPU power , Let's block roger beep in SSB selection by now .
int32_t sample = 0;
int8_t re = 0, im = 0;
@@ -55,7 +86,9 @@ void SSB::execute(const buffer_s16_t& audio, const buffer_c8_t& buffer) {
float i = 0.0, q = 0.0;
sample = audio.p[counter / over] >> 2;
//switch (mode) {
sample *= audio_gain; // Apply GAIN Scale factor to the audio TX modulation.
//switch (mode) {
//case Mode::LSB:
hilbert.execute(sample / 32768.0f, i, q);
//case Mode::USB: hilbert.execute(sample / 32768.0f, q, i);
@@ -72,9 +105,23 @@ void SSB::execute(const buffer_s16_t& audio, const buffer_c8_t& buffer) {
//re = q;
//im = i;
//break;
}
buffer.p[counter] = { re, im };
// Update vu-meter bar in the LCD screen.
power_acc += (sample < 0) ? -sample : sample; // Power average for UI vu-meter
if (new_power_acc_count) {
new_power_acc_count--;
} else { // power_acc_count = 0
new_power_acc_count = new_divider;
new_level_message.value = power_acc / (new_divider *8); // Why ? . This division is to adj vu-meter sentitivity, to match saturation point to red-muter .
shared_memory.application_queue.push(new_level_message);
power_acc = 0;
}
}
}
@@ -88,15 +135,39 @@ void FM::set_fm_delta(uint32_t new_delta) {
fm_delta = new_delta;
}
void FM::execute(const buffer_s16_t& audio, const buffer_c8_t& buffer) {
void FM::set_tone_gen_configure(const uint32_t set_delta, const float set_tone_mix_weight) {
tone_gen.configure(set_delta, set_tone_mix_weight);
}
void FM::execute(const buffer_s16_t& audio, const buffer_c8_t& buffer, bool& configured_in, uint32_t& new_beep_index, uint32_t& new_beep_timer, TXProgressMessage& new_txprogress_message, AudioLevelReportMessage& new_level_message, uint32_t& new_power_acc_count, uint32_t& new_divider ) {
int32_t sample = 0;
int8_t re, im;
for (size_t counter = 0; counter < buffer.count; counter++) {
if (counter % over == 0) {
sample = audio.p[counter / over] >> 8;
delta = sample * fm_delta;
}
sample = audio.p[counter>>6] >> 8; // sample = audio.p[counter / over] >> 8; (not enough efficient running code, over = 1536000/240000= 64 )
sample *= audio_gain; // Apply GAIN Scale factor to the audio TX modulation.
if (play_beep) {
sample = apply_beep(sample, configured_in, new_beep_index, new_beep_timer, new_txprogress_message ); // Apply beep -if selected - atom ,sample by sample.
} else {
// Update vu-meter bar in the LCD screen.
power_acc += (sample < 0) ? -sample : sample; // Power average for UI vu-meter
if (new_power_acc_count) {
new_power_acc_count--;
} else { // power_acc_count = 0
new_power_acc_count = new_divider;
new_level_message.value = power_acc / (new_divider / 4); // Why ? . This division is to adj vu-meter sentitivity, to match saturation point to red-muter .
shared_memory.application_queue.push(new_level_message);
power_acc = 0;
}
// TODO: pending to optimize CPU running code.
// So far , we can not handle all 3 issues at the same time (vu-meter , CTCSS, beep).
sample = tone_gen.process(sample); // Add selected Key_Tone or CTCSS subtone , atom function() , sample by sample.
}
delta = sample * fm_delta; // Modulate FM
phase += delta;
sphase = phase >> 24;
@@ -112,16 +183,33 @@ AM::AM() {
mode = Mode::AM;
}
void AM::execute(const buffer_s16_t& audio, const buffer_c8_t& buffer) {
void AM::execute(const buffer_s16_t& audio, const buffer_c8_t& buffer, bool& configured_in, uint32_t& new_beep_index, uint32_t& new_beep_timer, TXProgressMessage& new_txprogress_message, AudioLevelReportMessage& new_level_message, uint32_t& new_power_acc_count, uint32_t& new_divider ) {
int32_t sample = 0;
int8_t re = 0, im = 0;
float q = 0.0;
float q = 0.0;
for (size_t counter = 0; counter < buffer.count; counter++) {
if (counter % 128 == 0) {
sample = audio.p[counter / over] >> 2;
sample *= audio_gain; // Apply GAIN Scale factor to the audio TX modulation.
}
if (play_beep) {
sample = apply_beep(sample, configured_in, new_beep_index, new_beep_timer, new_txprogress_message )<<5; // Apply beep -if selected - atom sample by sample.
} else {
// Update vu-meter bar in the LCD screen.
power_acc += (sample < 0) ? -sample : sample; // Power average for UI vu-meter
if (new_power_acc_count) {
new_power_acc_count--;
} else { // power_acc_count = 0
new_power_acc_count = new_divider;
new_level_message.value = power_acc / (new_divider *8); // Why ?orig / (new_divider / 4); // Why ?
shared_memory.application_queue.push(new_level_message);
power_acc = 0;
}
}
q = sample / 32768.0f;
q *= 256.0f; // Original 64.0f,now x4 (+12 dB's BB_modulation in AM & DSB)
switch (mode) {
+25 -4
View File
@@ -24,6 +24,8 @@
#include "dsp_types.hpp"
#include "dsp_hilbert.hpp"
#include "tone_gen.hpp"
#include "baseband_processor.hpp"
namespace dsp {
namespace modulate {
@@ -41,13 +43,28 @@ enum class Mode {
class Modulator {
public:
virtual void execute(const buffer_s16_t& audio, const buffer_c8_t& buffer) = 0;
virtual void execute(const buffer_s16_t& audio, const buffer_c8_t& buffer,bool& configured_in, uint32_t& new_beep_index, uint32_t& new_beep_timer, TXProgressMessage& new_txprogress_message, AudioLevelReportMessage& new_level_message, uint32_t& new_power_acc_count, uint32_t& new_divider ) = 0;
virtual ~Modulator();
Mode get_mode();
void set_mode(Mode new_mode);
void set_over(uint32_t new_over);
void set_gain_vumeter_beep(float new_audio_gain , bool new_play_beep );
int32_t apply_beep(int32_t sample_in, bool& configured_in, uint32_t& new_beep_index, uint32_t& new_beep_timer, TXProgressMessage& new_txprogress_message );
float audio_gain { };
bool play_beep { false };
uint32_t power_acc_count { 0 }; // this var it is initialized from Proc_mictx.cpp
uint32_t divider { }; // this var it is initialized from Proc_mictx.cpp
uint64_t power_acc { 0 }; // it is aux Accumulated sum (Absolute sample signal) , initialitzed to zero.
AudioLevelReportMessage level_message { };
private:
static constexpr size_t baseband_fs = 1536000U;
TXProgressMessage txprogress_message { };
ToneGen beep_gen { };
uint32_t beep_index { }, beep_timer { };
protected:
uint32_t over = 1;
@@ -60,7 +77,7 @@ class SSB : public Modulator {
public:
SSB();
virtual void execute(const buffer_s16_t& audio, const buffer_c8_t& buffer);
virtual void execute(const buffer_s16_t& audio, const buffer_c8_t& buffer, bool& configured_in, uint32_t& new_beep_index, uint32_t& new_beep_timer, TXProgressMessage& new_txprogress_message, AudioLevelReportMessage& new_level_message, uint32_t& new_power_acc_count, uint32_t& new_divider );
private:
dsp::HilbertTransform hilbert;
@@ -72,8 +89,9 @@ class FM : public Modulator {
public:
FM();
virtual void execute(const buffer_s16_t& audio, const buffer_c8_t& buffer);
virtual void execute(const buffer_s16_t& audio, const buffer_c8_t& buffer, bool& configured_in, uint32_t& new_beep_index, uint32_t& new_beep_timer, TXProgressMessage& new_txprogress_message, AudioLevelReportMessage& new_level_message, uint32_t& new_power_acc_count, uint32_t& new_divider ) ;
void set_fm_delta(uint32_t new_delta);
void set_tone_gen_configure(const uint32_t delta, const float tone_mix_weight);
///
@@ -81,13 +99,16 @@ private:
uint32_t fm_delta { 0 };
uint32_t phase { 0 }, sphase { 0 };
int32_t sample { 0 }, delta { };
ToneGen tone_gen { };
};
class AM : public Modulator {
public:
AM();
virtual void execute(const buffer_s16_t& audio, const buffer_c8_t& buffer);
virtual void execute(const buffer_s16_t& audio, const buffer_c8_t& buffer, bool& configured_in, uint32_t& new_beep_index, uint32_t& new_beep_timer, TXProgressMessage& new_txprogress_message, AudioLevelReportMessage& new_level_message, uint32_t& new_power_acc_count, uint32_t& new_divider );
};
} /* namespace modulate */
+24 -17
View File
@@ -35,8 +35,10 @@ void MicTXProcessor::execute(const buffer_c8_t& buffer){
if (!configured) return;
audio_input.read_audio_buffer(audio_buffer);
modulator->execute(audio_buffer, buffer);
modulator->set_gain_vumeter_beep(audio_gain, play_beep ) ;
modulator->execute(audio_buffer, buffer, configured, beep_index, beep_timer, txprogress_message, level_message, power_acc_count, divider ); // Now "Key Tones & CTCSS" baseband additon inside FM mod. dsp_modulate.cpp"
/* Original fw 1.3.1 good reference, beep and vu-meter
for (size_t i = 0; i < buffer.count; i++) {
if (!play_beep) {
@@ -67,13 +69,13 @@ void MicTXProcessor::execute(const buffer_c8_t& buffer){
beep_index++;
}
}
sample = beep_gen.process(0);
}
/*
sample = beep_gen.process(0); // TODO : Pending how to move inside modulate.cpp
}
*/
/* Original fw 1.3.1 good reference FM moulation version, including "key tones CTCSS" fw 1.3.1
sample = tone_gen.process(sample);
// FM
if (configured) {
delta = sample * fm_delta;
@@ -89,8 +91,8 @@ void MicTXProcessor::execute(const buffer_c8_t& buffer){
}
buffer.p[i] = { re, im };
*/
}
} */
}
void MicTXProcessor::on_message(const Message* const msg) {
@@ -100,12 +102,16 @@ void MicTXProcessor::on_message(const Message* const msg) {
switch(msg->id) {
case Message::ID::AudioTXConfig:
if (fm_enabled) {
dsp::modulate::FM *fm = new dsp::modulate::FM();
fm->set_fm_delta(config_message.deviation_hz * (0xFFFFFFUL / baseband_fs));
dsp::modulate::FM *fm = new dsp::modulate::FM();
// Config fm_delta private var inside DSP modulate.cpp
fm->set_fm_delta(config_message.deviation_hz * (0xFFFFFFUL / baseband_fs));
// Config properly the private tone_gen function parameters inside DSP modulate.cpp
fm->set_tone_gen_configure(config_message.tone_key_delta, config_message.tone_key_mix_weight);
modulator = fm;
}
if (usb_enabled) {
modulator = new dsp::modulate::SSB();
modulator->set_mode(dsp::modulate::Mode::USB);
@@ -124,7 +130,7 @@ void MicTXProcessor::on_message(const Message* const msg) {
modulator->set_mode(dsp::modulate::Mode::DSB);
}
modulator->set_over(baseband_fs / 24000);
modulator->set_over(baseband_fs / 24000); // Keep no change.
am_enabled = config_message.am_enabled;
usb_enabled = config_message.usb_enabled;
@@ -137,8 +143,9 @@ void MicTXProcessor::on_message(const Message* const msg) {
audio_gain = config_message.audio_gain;
divider = config_message.divider;
power_acc_count = 0;
tone_gen.configure(config_message.tone_key_delta, config_message.tone_key_mix_weight);
// now this config moved, in the case Message::ID::AudioTXConfig , only FM case.
// tone_gen.configure(config_message.tone_key_delta, config_message.tone_key_mix_weight);
txprogress_message.done = true;
+2 -2
View File
@@ -49,8 +49,8 @@ private:
};
AudioInput audio_input { };
ToneGen tone_gen { };
ToneGen beep_gen { };
// ToneGen tone_gen { }; moved to dsp_modulate.cpp
// ToneGen beep_gen { }; moved to dsp_modulate.cpp
dsp::modulate::Modulator *modulator = NULL ;
bool am_enabled { false };
+3 -17
View File
@@ -103,27 +103,13 @@ void SpectrumCollector::post_message(const buffer_c16_t& data) {
}
}
/* 3 types of Windowing time domain shapes declaration , but only used Hamming , shapes for FFT
GCC10 compile sintax error c/m (1/2),
The primary diff. between const and constexpr variables is that
the initialization of a const var can be deferred until run time.
A constexpr var. must be initialized at compile time. ...
A var. can be declared with constexpr , when it has a literal type and is initialized.
GCC compile sintax error c/m (2/2)
Static assert --> Tests a software assertion at compile time for debugging.
we keep the same safety compile protection , just changing slightly the sintax checking that the size of the called array is power of 2.
if the bool "constant expression" is TRUE (normal case) , the declaration has no effect.
if the bool "constant expression" is FALSE (abnormal array size) , it is aborted the compile with a msg error.
*/
template<typename T> // Although currently we are not using that Windowing shape, we apply the same GCC10 compile error c/m
template<typename T>
static typename T::value_type spectrum_window_none(const T& s, const size_t i) {
static_assert(power_of_two(ARRAY_ELEMENTS(s)), "Array number of elements must be power of 2"); // c/m compile error GCC10 , OK for all GCC versions.
return s[i];
};
template<typename T> // Currently we are calling and using that Window shape.
template<typename T>
static typename T::value_type spectrum_window_hamming_3(const T& s, const size_t i) {
static_assert(power_of_two(ARRAY_ELEMENTS(s)), "Array number of elements must be power of 2"); // c/m compile error GCC10 , OK for all GCC versions.
const size_t mask = s.size() - 1; // c/m compile error GCC10 , constexpr->const
@@ -131,7 +117,7 @@ static typename T::value_type spectrum_window_hamming_3(const T& s, const size_t
return s[i] * 0.54f + (s[(i-1) & mask] + s[(i+1) & mask]) * -0.23f;
};
template<typename T> // Although currently we are not using that Windowing shape, we apply the same GCC10 compile error c/m
template<typename T>
static typename T::value_type spectrum_window_blackman_3(const T& s, const size_t i) {
static_assert(power_of_two(ARRAY_ELEMENTS(s)), "Array number of elements must be power of 2"); // c/m compile error GCC10 , OK for all GCC versions.
const size_t mask = s.size() - 1; // c/m compile error GCC10 , constexpr->const
+48 -9
View File
@@ -24,14 +24,20 @@
#include "sine_table_int8.hpp"
/*
int32_t ToneGen::tone_sine() {
// TODO : Added for Sonde App. We keep it by now , but it needs to be reviewed in Sonde
// Hoepfully we can manage without it , same as previous fw 1.3.1
int32_t tone_sample = sine_table_i8[tone_phase_] * 0x1000000;
tone_phase_ += delta_;
return tone_sample;
}
*/
int32_t ToneGen::tone_square() {
// TODO : Added for Sonde App. We keep it by now , but it needs to be reviewed in Sonde
int32_t tone_sample = 0;
if(tone_phase_ < (UINT32_MAX / 2)) {
@@ -46,33 +52,66 @@ int32_t ToneGen::tone_square() {
return tone_sample;
}
/*
void ToneGen::configure(const uint32_t delta, const float tone_mix_weight) {
// Confirmed ! It is not working well in the fw 1.4.4 Mic App , CTCSS generation, (but added for Sonde App)
// I Think it should be deleted or modified but not use it as it is in Mic App .
delta_ = (uint8_t) ((delta & 0xFF000000U) >> 24);
delta_ = delta;
tone_mix_weight_ = tone_mix_weight;
input_mix_weight_ = 1.0 - tone_mix_weight;
current_tone_type_ = sine;
}
*/
void ToneGen::configure(const uint32_t freq, const float tone_mix_weight, const tone_type tone_type, const uint32_t sample_rate) {
// TODO : Added for Sonde App. We keep it by now to avoid compile errors, but it needs to be reviewed in Sonde
delta_ = (uint8_t) ((freq * sizeof(sine_table_i8)) / sample_rate);
tone_mix_weight_ = tone_mix_weight;
input_mix_weight_ = 1.0 - tone_mix_weight;
current_tone_type_ = tone_type;
}
// ----Original available core SW code from fw 1.3.1 , Working also well in Mic App CTCSS Gen from fw 1.4.0 onwards
// Original direct-look-up synthesis algorithm with Fractional delta phase. It is OK
// Delta and Accumulator fase are stored in 32 bits (4 bytes), 1st top byte used as Modulo-256 Sine look-up table [index]
// the lower 3 bytes (24 bits) are used as a Fractional Detla and Accumulator phase, to have very finer Fstep control.
void ToneGen::configure(const uint32_t delta, const float tone_mix_weight) {
delta_ = delta;
tone_mix_weight_ = tone_mix_weight;
input_mix_weight_ = 1.0 - tone_mix_weight;
}
int32_t ToneGen::process(const int32_t sample_in) {
if (!delta_)
return sample_in;
int32_t tone_sample = 0;
if(current_tone_type_ == sine) {
tone_sample = tone_sine();
}
else if(current_tone_type_ == square) {
tone_sample = tone_square();
}
int32_t tone_sample = sine_table_i8[(tone_phase_ & 0xFF000000U) >> 24];
tone_phase_ += delta_;
return (sample_in * input_mix_weight_) + (tone_sample * tone_mix_weight_);
}
// -------------------------------------------------------------
int32_t ToneGen::process_square(const int32_t sample_in) {
// TODO : Added for Sonde App. We keep it by now , but it needs to be reviewed in Sonde
if (!delta_)
return sample_in;
int32_t tone_sample = 0;
tone_sample = tone_square();
return (sample_in * input_mix_weight_) + (tone_sample * tone_mix_weight_);
}
+10 -5
View File
@@ -28,7 +28,7 @@
class ToneGen {
public:
enum tone_type { sine, square };
enum tone_type { sine, square }; // TODO: Added for Radio Sonde.cpp PR 376, 381 , we need to check if keep or not.
/*ToneGen(const size_t sample_rate
) : sample_rate_ { sample_rate }
@@ -38,6 +38,7 @@ public:
void configure(const uint32_t freq, const float tone_mix_weight, const tone_type tone_type, const uint32_t sample_rate);
int32_t process(const int32_t sample_in);
int32_t process_square(const int32_t sample_in);
private:
tone_type current_tone_type_ { sine };
@@ -45,19 +46,23 @@ private:
float input_mix_weight_ { 1 };
float tone_mix_weight_ { 0 };
uint8_t delta_ { 0 };
uint8_t tone_phase_ { 0 };
uint32_t delta_ { 0 };
uint32_t tone_phase_ { 0 };
// uint8_t delta_ { 0 }; // TODO: Added for Radio Sonde.cpp PR 376, 381 , we need to check if keep or not.
// uint8_t tone_phase_ { 0 }; // TODO: Added for Radio Sonde.cpp PR 376, 381 , we need to check if keep or not.
/**
* Generator function which selects every other sample from the reference sine waveform to the output sample:
*/
int32_t tone_sine();
int32_t tone_sine();// TODO: Added for Radio Sonde.cpp PR 376, 381 , we need to check if keep or not.
/**
* Generator function for square waves:
*/
int32_t tone_square();
int32_t tone_square(); // TODO: Added for Radio Sonde.cpp PR 376, 381 , we need to check if keep or not.
};
#endif /* __TONE_GEN_H__ */
+64 -321
View File
@@ -216,347 +216,90 @@ void AK4951::speaker_disable() {
set_speaker_power(false);
}
void AK4951::microphone_enable(int8_t alc_mode) {
// 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), ...)
// map.r.digital_mic.DMIC = 0; // originally commented code
// update(Register::DigitalMic); // originally commented code
uint_fast8_t mgain =0b0111; // Pre-amp mic (Original code, =0b0111 (+21dB's=7x3dBs),(Max is NOT 0b1111!, it is 0b1010=+30dBs=10x3dBs)
map.r.signal_select_2.INL = 0b01; // Lch input signal = LIN2 , our ext. MONO MIC is connected here LIN2 in Portapack.
map.r.signal_select_2.INR = 0b01; // Rch input signal = RIN2 , Not used ,not connected ,but no problem.
map.r.signal_select_2.MICL = 0; // MPWR = 2.4V (it has two possible settings , 2.4V or 2.0V) , (majority smarthphones around 2V , range 1V-5V)
update(Register::SignalSelect2);
// ------Common code part, = original setting conditions, it is fine for all user-GUI alc_modes: OFF , and ALC modes .*/
map.r.digital_filter_select_1.HPFAD = 1; // HPF1 ON (after ADC);page 40 datasheet, HPFAD bit controls the ON/OFF of the HPF1 (HPF ON is recommended).
map.r.digital_filter_select_1.HPFC = 0b11; // HPF Cut off frequency of high pass filter from 236.8 Hz @fs=48k ("00":3.7Hz, "01":14,8Hz, "10":118,4Hz)
update(Register::DigitalFilterSelect1);
// map.r.r_ch_mic_gain_setting.MGR = 0x80; // Microphone sensitivity correction = 0dB., (not used by now , original code cond.)
// update(Register::RchMicGainSetting); // (those two lines , not activated, same as original)
// pre-load 4 byes LPF coefficicients (.lpf_coefficient_0,1,2,3), FSA 14..0, FSB 14..0 , (fcut initial 6kHz, fs 48Khz).
// it will be default pre-loading coeff. for al ALC modes, LPF bit is activated down, for all ALC digital modes.
map.r.lpf_coefficient_0.l = 0x5F; // Pre-loading here LPF 6kHz, 1st Order from digital Block , Fc=6000 Hz, fs = 48khz
map.r.lpf_coefficient_1.h = 0x09; // LPF bit is activated down, for all ALC digital modes.
map.r.lpf_coefficient_2.l = 0xBF; // Writting reg to AK4951, with "update", following instructions.
map.r.lpf_coefficient_3.h = 0x32;
update(Register::LPFCoefficient0); // Writing pre-loaded 4 bytes LPF CoefFiecients 14 bits (FSA13..0, FSB13..0
update(Register::LPFCoefficient1); // In this case , LPF 6KHz , when we activate the LPF block.
update(Register::LPFCoefficient2);
update(Register::LPFCoefficient3);
// Reset , setting OFF all 5 x Digital Equalizer filters
map.r.digital_filter_select_3.EQ1 = 0; // EQ1 Coeffic Setting , (0: Disable-default, audio data passes EQ1 block by 0dB gain). When EQ1="1”, the settings of E1A15-0, E1B15-0 and E1C15-0 bits are enabled
map.r.digital_filter_select_3.EQ2 = 0; // EQ2 Coeffic Setting , (0: Disable-default, audio data passes EQ2 block by 0dB gain). When EQ2="1”, the settings of E2A15-0, E2B15-0 and E2C15-0 bits are enabled
map.r.digital_filter_select_3.EQ3 = 0; // EQ3 Coeffic Setting , (0: Disable-default, audio data passes EQ3 block by 0dB gain). When EQ3="1”, the settings of E3A15-0, E3B15-0 and E3C15-0 bits are enabled
map.r.digital_filter_select_3.EQ4 = 0; // EQ4 Coeffic Setting , (0: Disable-default, audio data passes EQ4 block by 0dB gain). When EQ4="1”, the settings of E4A15-0, E4B15-0 and E4C15-0 bits are enabled
map.r.digital_filter_select_3.EQ5 = 0; // EQ5 Coeffic Setting , (0: Disable-default, audio data passes EQ5 block by 0dB gain). When EQ5="1”, the settings of E5A15-0, E5B15-0 and E5C15-0 bits are enabled
update(Register::DigitalFilterSelect3); // A,B,C EQ1 Coefficients are already pre-loaded in ak4951.hpp
if (alc_mode==0) { // Programmable Digital Filter OFF, same as original condition., no Digital ALC, nor Wind Noise Filter, LPF , EQ
map.r.digital_filter_select_2.LPF = 0; // LPF-Block, Coeffic Setting Enable (OFF-Default), When LPF bit is “0”, audio data passes the LPF block by 0dB gain.
update(Register::DigitalFilterSelect2);
// Pre-loading AUDIO PATH with all DIGITAL BLOCK by pased, see, audio path block diagramm AK4951 datasheet + Table Playback mode -Recording mode.
// Digital filter block PATH is BY PASSED (we can swith off DIG. BLOCK power , PMPFIL=0) .The Path in Recording Mode 2 & Playback Mode 2 (NO DIG FILTER BLOCK AT ALL, not for MIC recording, nor for Playback)
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 = 0; // ADC bit switch ("0" : 1st order HPF) connectedto the Output. By bass DIGITAL block .
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 : 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.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 )
// 1059/fs, 22ms @ 48kHz
chThdSleepMilliseconds(22);
} else { // ( alc_mode !=0)
switch(alc_mode) { // Pre-loading register values depending on user-GUI selection (they will be sended below, with "update(Register_name::xxx )".
case 1: // ALC-> on, (+12dB's) Auto Vol max + Wind Noise cancel + LPF 6kHz + Pre-amp Mic (+21dB=original)
map.r.alc_mode_control_2.REF = 0xC0; // REF7-0 bits,max gain at ALC recovery operation,(FFH +36dBs , D0H +18dBs, A0H 0dBs, C0H=+12dBs)
map.r.l_ch_input_volume_control.IV = 0xC0; // Left, Input Digital Volume Setting, (FFH +36dBs , D0H +18dBs, A0H 0dBs, 70H=-18dBs)
map.r.r_ch_input_volume_control.IV = 0xC0; // Right Input Dig Vol Setting, same comment as above , The value of IVOL should be <= than REFs
// Already Pre-loaded, "map.r.lpf_coefficient", 6Khz - LPF 1st Order from digital Block,Fc=6000Hz,fs = 48khz
// LPF bit is activated down, for all ALC digital modes.
break;
case 2: // ALC-> on, (+09dB's) Auto Vol max + Wind Noise cancel + LPF 6kHz + Pre-amp Mic (+21dB=original)
map.r.alc_mode_control_2.REF = 0xB8; // REF7-0 bits,max gain at ALC recoveryoperation,(FFH +36dBs , D0H +18dBs, A0H 0dBs, B8H= +9dBs)
map.r.l_ch_input_volume_control.IV = 0xB8; // Left, Input Digital Volume Setting, (FFH +36dBs , D0H +18dBs, A0H 0dBs, 70H=-18dBs)
map.r.r_ch_input_volume_control.IV = 0xB8; // Right Input Dig Vol Setting, same comment as above , The value of IVOL should be <= than REFs
// Already Pre-loaded, "map.r.lpf_coefficient", 6Khz - LPF 1st Order from digital Block,Fc=6000Hz,fs = 48khz
// LPF bit is activated down, for all ALC digital modes.
break;
case 3: // ALC-> on, (+06dB's) Auto Vol max + Wind Noise cancel + LPF 6kHz + Pre-amp Mic (+21dB=original)
map.r.alc_mode_control_2.REF = 0xB0; // 0xB8 , REF7-0 bits,max gain at ALC recoveryoperation,(FFH +36dBs , D0H +18dBs, A0H 0dBs, B0H= +6dBs)
map.r.l_ch_input_volume_control.IV = 0xB0; // Left, Input Digital Volume Setting, (FFH +36dBs , D0H +18dBs, A0H 0dBs, 70H=-18dBs)
map.r.r_ch_input_volume_control.IV = 0xB0; // Right Input Dig Vol Setting, same comment as above , Then value of IVOL should be <= than REFs
// Already Pre-loaded, "map.r.lpf_coefficient", 6Khz - LPF 1st Order from digital Block,Fc=6000Hz,fs = 48khz
// LPF bit is activated down, for all ALC digital modes.
break;
case 4: // ALC-> on, (+03dB's) Auto Vol max + Wind Noise cancel + Pre-amp Mic (+21dB=original)
// + EQ boosting ~<2kHz (f0:1,1k, fb:1,7K, k=1,8) && + LPF 3,5k
map.r.alc_mode_control_2.REF = 0xA8; // 0xA8 , REF7-0 bits,max gain at ALC recoveryoperation,(FFH +36dBs , D0H +18dBs, A0H 0dBs, A8H= +3dBs)
map.r.l_ch_input_volume_control.IV = 0xA8; // Left, Input Digital Volume Setting, (FFH +36dBs , D0H +18dBs, A0H 0dBs, 70H=-18dBs)
map.r.r_ch_input_volume_control.IV = 0xA8; // Right Input Dig Vol Setting, same comment as above , Then value of IVOL should be <= than REFs
//The EQn (n=1, 2, 3, 4 or 5) coefficient must be set when EQn bit = “0” or PMPFIL bit = “0”.
map.r.digital_filter_select_3.EQ1 = 1; // EQ1 Coeffic Setting , (0: Disable-default, audio data passes EQ1 block by 0dB gain). When EQ1="1”, the settings of E1A15-0, E1B15-0 and E1C15-0 bits are enabled
update(Register::DigitalFilterSelect3); // A,B,C EQ1 Coefficients are already pre-loaded in ak4951.hpp
map.r.lpf_coefficient_0.l = 0x0D; // Pre-loading here LPF 3,5k , 1st Order from digital Block , Fc=3.500 Hz, fs = 48khz
map.r.lpf_coefficient_1.h = 0x06; // LPF bit is activated down, for all ALC digital modes.
map.r.lpf_coefficient_2.l = 0x1A; // Writting reg to AK4951 , down with update....
map.r.lpf_coefficient_3.h = 0x2C;
// LPF bit is activated down, for all ALC digital modes.
break;
case 5: // ALC-> on, (+03dB's) Auto Vol max + Wind Noise cancel + Pre-amp Mic (+21dB=original)
// + EQ boosting ~<3kHz (f0~1k4,fb~2,4k,k=1,8) && LPF 4kHz
map.r.alc_mode_control_2.REF = 0xA8; // 0xA0 , REF7-0 bits,max gain at ALC recoveryoperation,(FFH +36dBs , D0H +18dBs, A0H 0dBs, A8H= +3dBs)
map.r.l_ch_input_volume_control.IV = 0xA8; // Left, Input Digital Volume Setting, (FFH +36dBs , D0H +18dBs, A0H 0dBs, 70H=-18dBs)
map.r.r_ch_input_volume_control.IV = 0xA8; // Right Input Dig Vol Setting, same comment as above , Then value of IVOL should be <= than REFs
map.r.digital_filter_select_3.EQ2 = 1; // EQ2 Coeffic Setting , (0: Disable-default, audio data passes EQ2 block by 0dB gain). When EQ2="1”, the settings of E2A15-0, E2B15-0 and E2C15-0 bits are enabled
update(Register::DigitalFilterSelect3);
map.r.lpf_coefficient_0.l = 0xC3; // Pre-loading here LPF 4k , 1st Order from digital Block , Fc=4000 Hz, fs = 48khz
map.r.lpf_coefficient_1.h = 0x06; // LPF bit is activated down, for all ALC digital modes.
map.r.lpf_coefficient_2.l = 0x86; // Writting reg to AK4951 , down with update....
map.r.lpf_coefficient_3.h = 0x2D;
// LPF bit is activated down, for all ALC digital modes.
break;
case 6: // ALC-> on, (+03dB's) Auto Vol max + Wind Noise cancel + LPF 6kHz + Pre-amp Mic (+21dB=original)
map.r.alc_mode_control_2.REF = 0xA8; // REF7-0 bits,max gain at ALC recoveryoperation,(FFH +36dBs , D0H +18dBs, A0H 0dBs, A0H= 0dBs)
map.r.l_ch_input_volume_control.IV = 0xA8; // Left, Input Digital Volume Setting, (FFH +36dBs , D0H +18dBs, A0H 0dBs, 70H=-18dBs)
map.r.r_ch_input_volume_control.IV = 0xA8; // Right Input Dig Vol Setting, same comment as above , Then value of IVOL should be <= than REFs
// Already Pre-loaded, "map.r.lpf_coefficient", 6Khz - LPF 1st Order from digital Block,Fc=6000Hz,fs = 48khz
// LPF bit is activated down, for all ALC digital modes.
break;
case 7: // ALC-> on, (+00dB's) Auto Vol max + Wind Noise cancel + LPF 6kHz + Pre-amp Mic (+21dB=original)
map.r.alc_mode_control_2.REF = 0xA0; // REF7-0 bits,max gain at ALC recoveryoperation,(FFH +36dBs , D0H +18dBs, A0H 0dBs, A0H= 0dBs)
map.r.l_ch_input_volume_control.IV = 0xA0; // Left, Input Digital Volume Setting, (FFH +36dBs , D0H +18dBs, A0H 0dBs, 70H=-18dBs)
map.r.r_ch_input_volume_control.IV = 0xA0; // Right Input Dig Vol Setting, same comment as above , Then value of IVOL should be <= than REFs
// Already Pre-loaded, "map.r.lpf_coefficient", 6Khz - LPF 1st Order from digital Block,Fc=6000Hz,fs = 48khz
// LPF bit is activated down, for all ALC digital modes.
break;
case 8: // ALC-> on, (-03dB's) Auto Vol max + Wind Noise cancel + LPF 6kHz + Pre-amp Mic (+21dB=original)
map.r.alc_mode_control_2.REF = 0x98; //REF7-0 bits,max gain at ALC recovery operation,(FFH +36dBs , D0H +18dBs, A0H 0dBs, 98H=-03dBs)
map.r.l_ch_input_volume_control.IV = 0x98; // Left, Input Digital Volume Setting, (FFH +36dBs , D0H +18dBs, A0H 0dBs, 70H=-18dBs)
map.r.r_ch_input_volume_control.IV = 0x98; // Right Input Dig Vol Setting, same comment as above , Then value of IVOL should be <= than REFs
void AK4951::microphone_enable() {
// map.r.digital_mic.DMIC = 0;
// update(Register::DigitalMic);
// Already Pre-loaded, "map.r.lpf_coefficient", 6Khz - LPF 1st Order from digital Block,Fc=6000Hz,fs = 48khz
// LPF bit is activated down, for all ALC digital modes.
break;
const uint_fast8_t mgain = 0b0111;
map.r.signal_select_1.MGAIN20 = mgain & 7;
map.r.signal_select_1.PMMP = 1;
map.r.signal_select_1.MPSEL = 1; // MPWR2 pin
map.r.signal_select_1.MGAIN3 = (mgain >> 3) & 1;
update(Register::SignalSelect1);
case 9: // ALC-> on, (-06dB's) Auto Vol max + Wind Noise cancel + LPF 6kHz + Pre-amp Mic (+21dB=original)
map.r.alc_mode_control_2.REF = 0x90; // REF7-0 bits,max gain at ALC recovery operation,(FFH +36dBs , D0H +18dBs, A0H 0dBs, 90H=-06dBs)
map.r.l_ch_input_volume_control.IV = 0x90; // Left, Input Digital Volume Setting, (FFH +36dBs , D0H +18dBs, A0H 0dBs, 70H=-18dBs)
map.r.r_ch_input_volume_control.IV = 0x90; // Right Input Dig Vol Setting, same comment as above , Then value of IVOL should be <= than REFs
map.r.signal_select_2.INL = 0b01; // Lch input signal = LIN2
map.r.signal_select_2.INR = 0b01; // Rch input signal = RIN2
map.r.signal_select_2.MICL = 0; // MPWR = 2.4V
update(Register::SignalSelect2);
// Already Pre-loaded, "map.r.lpf_coefficient", 6Khz - LPF 1st Order from digital Block,Fc=6000Hz,fs = 48khz
// LPF bit is activated down, for all ALC digital modes.
break;
case 10: // ALC-> on, (-09dB's) Auto Vol max + Wind Noise cancel + LPF 6kHz - Pre-amp MIC -3dB (18dB's)
// Reduce also Pre-amp Mic -3dB's (+18dB's)
mgain = 0b0110; // Pre-amp mic Mic Gain Pre-amp (+18dB), Original=0b0111 (+21dB's =7x3dBs),
map.r.alc_mode_control_2.REF = 0x88; // REF7-0 bits,max gain at ALC recovery operation,(FFH +36dBs , D0H +18dBs, A0H 0dBs, 88H=-09dBs)
map.r.l_ch_input_volume_control.IV = 0x88; // Left, Input Digital Volume Setting, (FFH +36dBs , D0H +18dBs, A0H 0dBs, 70H=-18dBs)
map.r.r_ch_input_volume_control.IV = 0x88; // Right Input Dig Vol Setting, same comment as above , Then value of IVOL should be <= than REFs
// Already Pre-loaded, "map.r.lpf_coefficient", 6Khz - LPF 1st Order from digital Block,Fc=6000Hz,fs = 48khz
// LPF bit is activated down, for all ALC digital modes.
break;
case 11: // ALC-> on, (-12dB's) Auto Vol max + Wind Noise cancel + LPF 6kHz - Pre-amp MIC -6dB (15dB's)
// Reduce also Pre-amp Mic -6dB's (+15dB's)
mgain = 0b0101; // Pre-amp mic Mic Gain Pre-amp (+15dB), (Original=0b0111 (+21dB's= 7x3dBs),
map.r.alc_mode_control_2.REF = 0x80; // REF7-0 bits,max gain at ALC recovery operation,(FFH +36dBs , D0H +18dBs, A0H 0dBs, 80H=-12dBs)
map.r.l_ch_input_volume_control.IV = 0x80; // Left, Input Digital Volume Setting, (FFH +36dBs , D0H +18dBs, A0H 0dBs, 70H=-18dBs)
map.r.r_ch_input_volume_control.IV = 0x80; // Right Input Dig Vol Setting, same comment as above , Then value of IVOL should be <= than REFs
// Already Pre-loaded, "map.r.lpf_coefficient", 6Khz - LPF 1st Order from digital Block,Fc=6000Hz,fs = 48khz
// LPF bit is activated down, for all ALC digital modes.
break;
}
//-------------------------------DIGITAL ALC (Automatic Level Control ) --- --------
map.r.alc_mode_control_1.ALC = 0; // LMTH2-0, WTM1-0, RGAIN2-0, REF7-0, RFST1-0, EQFC1-0, FRATT, FRN and ALCEQN bits (needs to be set up with ALC disable = 0)
update(Register::ALCModeControl1);
map.r.timer_select.FRN = 0; // (FRN= 0 Fast Recovery mode , enable )
map.r.timer_select.FRATT = 0; // Fast Recovery Ref. Volume Atten. Amount -0,00106dB's, timing 4/fs (default)
map.r.timer_select.ADRST = 0b00; // initial offset ADC cycles , 22ms @fs=48Khz.
// map.r.r_ch_mic_gain_setting.MGR = 0x80; // Microphone sensitivity correction = 0dB.
// update(Register::RchMicGainSetting);
/*
map.r.timer_select.FRN = ?;
map.r.timer_select.FRATT = ?;
map.r.timer_select.ADRST = 0b??;
update(Register::TimerSelect);
map.r.alc_timer_select.RFST = 0b00; // RFST1-0: ALC Fast Recovery Speed Default: “00” (0.0032dB)
map.r.alc_timer_select.WTM = 0b00; // ALC Recovery Operation Waiting Period 128/fs = 2,7 mseg (min=default)
map.r.alc_timer_select.EQFC = 0b10; // Selecting default, fs 48Khz , ALCEQ: First order zero pole high pass filter fc2=100Hz, fc1=150Hz
map.r.alc_timer_select.IVTM = 0; // IVTM bit set the vol transition time ,236/fs = 4,9msecs (min) (default was 19,7msegs.)
map.r.alc_timer_select. = ?;
update(Register::ALCTimerSelect);
map.r.alc_mode_control_1.LMTH10 = 0b11; // ALC Limiter Detec Level/ Recovery Counter Reset; lower 2 bits (Ob111=-8,4dbs), (default 0b000=-2,5dBs)
map.r.alc_mode_control_1.RGAIN = 0b000; // ALC Recovery Gain Step, max step , max speed. Default: “000” (0.00424dB)
map.r.alc_mode_control_1.ALC = 1; // ALC Enable . (we are now, NOT in MANUAL volume mode, only becomes manual when (ALC=“0” while ADCPF=“1”. )
map.r.alc_mode_control_1.LMTH2 = 1; // ALC Limiter Detection Level/ Recovery Counter Reset Level,Upper bit,default 0b000
map.r.alc_mode_control_1.ALCEQN = 1; // ALC EQ Off =1 not used by now, 0: ALC EQ On (default)
map.r.alc_mode_control_1. = ?;
map.r.alc_mode_control_1.ALC = 1;
update(Register::ALCModeControl1);
// map.r.alc_mode_control_2.REF = 0x??; // Pre-loaded in top part. Maximum gain at ALC recovery operation,.(FFH +36dBs , D0H +18dBs, A0H 0dBs, 70H=-18dBs)
map.r.alc_mode_control_2.REF = ?;
update(Register::ALCModeControl2);
// map.r.l_ch_input_volume_control.IV = 0x??; // Pre-loaded in top part. Left, Input Digital Volume Setting, (FFH +36dBs , D0H +18dBs, A0H 0dBs, 70H=-18dBs)
update(Register::LchInputVolumeControl);
// map.r.r_ch_input_volume_control.IV = 0x??; // Pre-loaded in top part. Right,Input Digital Volume Setting, (FFH +36dBs , D0H +18dBs, A0H 0dBs, 70H=-18dBs)
update(Register::RchInputVolumeControl);
//---------------Switch ON, Digital Automatic Wind Noise Filter reduction -------------------
// Difficult to realise that Dynamic HPF Wind noise filter benefit, maybe because we have another fixed HPF 236.8 Hz .
// Anyway , we propose to activate it , with default setting conditions.
map.r.power_management_1.PMPFIL = 0; // (*1) To programm SENC, STG , we need PMPFIL = 0 . (but this disconnect Digital block power supply.
update(Register::PowerManagement1); // Updated PMPFIL to 0 . (*1)
map.r.auto_hpf_control.STG = 0b00; // (00=LOW ATTENUATION Level), lets put 11 (HIGH ATTENUATION Level) (default 00)
map.r.auto_hpf_control.SENC = 0b011; // (000=LOW sensitivity detection)… 111((MAX sensitivity detection) (default 011)
map.r.auto_hpf_control.AHPF = 1; // Autom. Wind noise filter ON (AHPF bit=“1”).It atten. wind noise when detecting ,and adjusts the atten. level dynamically.
update(Register::AutoHPFControl);
// We are in Digital Block ON , (Wind Noise Filter+ALC+LPF+EQ),==> needs at the end , PMPFIL=1 , Program. Dig.filter ON
// map.r.power_management_1.PMPFIL = 1; // that instruction is at the end , we can skp pre-loading Programmable Dig. filter ON (*1)
//---------------------------------------------------------------------
// Writing AUDIO PATH diagramm, Changing Audio mode path : Playback mode1 /-Recording mode2. (Figure 37 AK4951 datasheet, Table 27. Recording Playback 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)
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)
// map.r.power_management_1.PMPFIL = 0; // In the previous Wind Noise Filter , we already set up PPFIL = 0
// update(Register::PowerManagement1); // Activating the Power management of the used blocks . (Mic ADC always + Dig Block filter , when used )
// ... Set EQ & LPF coefficients ---------------------------------
// writting to the IC ak4951 reg. settings defined in Ak4951.hpp , the 30 bytes , EQ coefficient = 5 (EQ1,2,3,4,5) x 3 (A,B,C coefficients) x 2 bytes (16 bits)
update(Register::E1Coefficient0); // we could pre-load here,ex ,"map.r.e1_coefficient_0.l = 0x50;" , EQ1 Coefficient A : A7...A0, but already done in ak4951.hpp
update(Register::E1Coefficient1); // we could pre-load here,ex ,"map.r.e1_coefficient_1.h = 0xFE;" , EQ1 Coefficient A : A15..A8, " "
update(Register::E1Coefficient2); // we could pre-load here,ex ,"map.r.e1_coefficient_2.l = 0x29;" , EQ1 Coefficient B : B7...B0, " "
update(Register::E1Coefficient3); // we could pre-load here,ex ,"map.r.e1_coefficient_3.h = 0xC5;" , EQ1 Coefficient B : B15..B8, " "
update(Register::E1Coefficient4); // we could pre-load here,ex ,"map.r.e1_coefficient_4.l = 0xA0;" , EQ1 Coefficient C : C7...C0, " "
update(Register::E1Coefficient5); // we could pre-load here,ex ,"map.r.e1_coefficient_5.h = 0x1C;" , EQ1 Coefficient C : C15..C8, " "
update(Register::E2Coefficient0); // writing pre-loaded EQ2 coefficcients
update(Register::E2Coefficient1);
update(Register::E2Coefficient2);
update(Register::E2Coefficient3);
update(Register::E2Coefficient4);
update(Register::E2Coefficient5);
// Already pre-loaded LPF coefficients to 6k, 3,5k or 4k ,(LPF 6Khz all digital alc modes top , except when 3k5 , 4k)
update(Register::LPFCoefficient0); // Writing pre-loaded 4 bytes LPF CoefFiecients 14 bits (FSA13..0, FSB13..0
update(Register::LPFCoefficient1);
update(Register::LPFCoefficient2);
update(Register::LPFCoefficient3);
// Activating LPF block , (and re-configuring the rest of bits of the same register)
map.r.digital_filter_select_2.HPF = 0; // HPF2-Block, Coeffic Setting Enable (OFF-Default), When HPF bit is “0”, audio data passes the HPF2 block by is 0dB gain.
map.r.digital_filter_select_2.LPF = 1; // LPF-Block, Coeffic Setting Enable (OFF-Default), When LPF bit is “0”, audio data passes the LPF block by 0dB gain.
map.r.digital_filter_select_2.FIL3 = 0; // Stereo_Emphasis_Filter-Block,(OFF-Default) Coefficient Setting Enable , OFF , Disable.
map.r.digital_filter_select_2.EQ0 = 0; // Gain Compensation-Block, (OFF-Default) Coeffic Setting Enable, When EQ0 bit = “0” audio data passes the EQ0 block by 0dB gain.
map.r.digital_filter_select_2.GN = 0b00; // Gain Setting of the Gain Compensation Block Default: “00”-Default (0dB)
*/
// map.r.l_ch_input_volume_control.IV = 0xe1;
// update(Register::LchInputVolumeControl);
// map.r.r_ch_input_volume_control.IV = 0xe1;
// update(Register::RchInputVolumeControl);
/*
map.r.auto_hpf_control.STG = 0b00;
map.r.auto_hpf_control.SENC = 0b011;
map.r.auto_hpf_control.AHPF = 0;
update(Register::AutoHPFControl);
*/
map.r.digital_filter_select_1.HPFAD = 1; // HPF1 (after ADC) = on
map.r.digital_filter_select_1.HPFC = 0b11; // 2336.8 Hz @ fs=48k
update(Register::DigitalFilterSelect1);
/*
map.r.digital_filter_select_2.HPF = 0;
map.r.digital_filter_select_2.LPF = 0;
map.r.digital_filter_select_2.FIL3 = 0;
map.r.digital_filter_select_2.EQ0 = 0;
map.r.digital_filter_select_2.GN = 0b00;
update(Register::DigitalFilterSelect2);
// 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.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 )
map.r.digital_filter_select_3.EQ1 = 0;
map.r.digital_filter_select_3.EQ2 = 0;
map.r.digital_filter_select_3.EQ3 = 0;
map.r.digital_filter_select_3.EQ4 = 0;
map.r.digital_filter_select_3.EQ5 = 0;
update(Register::DigitalFilterSelect3);
*/
map.r.digital_filter_mode.PFSDO = 0; // ADC (+ 1st order HPF) Output
map.r.digital_filter_mode.ADCPF = 1; // ADC Output (default)
update(Register::DigitalFilterMode);
// ... Set coefficients ...
map.r.power_management_1.PMADL = 1; // ADC Lch = Lch input signal
map.r.power_management_1.PMADR = 1; // ADC Rch = Rch input signal
map.r.power_management_1.PMPFIL = 0; // Programmable filter unused, routed around.
update(Register::PowerManagement1);
// 1059/fs, 22ms @ 48kHz
chThdSleepMilliseconds(22);
}
// Common part for all alc_mode , --------------------------
// const uint_fast8_t mgain = 0b0111; // Already pre-loaded , in above switch case .
map.r.signal_select_1.MGAIN20 = mgain & 7; // writing 3 lower bits of mgain , (pre-amp mic gain).
map.r.signal_select_1.PMMP = 1; // Activating DC Mic Power supply through 2kohms res., similar majority smartphones headphone+mic jack, "plug-in-power"
map.r.signal_select_1.MPSEL = 1; // MPWR2 pin ,selecting output voltage to MPWR2 pin, that we are using in portapack ext. MIC)
map.r.signal_select_1.MGAIN3 = (mgain >> 3) & 1; // writing 4th upper bit of mgain (pre-amp mic gain).
update(Register::SignalSelect1);
}
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.PMADL = 0;
map.r.power_management_1.PMADR = 0;
map.r.power_management_1.PMPFIL = 0;
update(Register::PowerManagement1);
map.r.alc_mode_control_1.ALC = 0; // original code , Restore , disable ALC block.
map.r.alc_mode_control_1.ALC = 0;
update(Register::ALCModeControl1);
map.r.auto_hpf_control.AHPF = 0; //----------- new code addition , Restore disable Wind noise filter OFF (AHPF bit=“0”).
update(Register::AutoHPFControl);
//Restore original AUDIO PATH , condition, (Digital filter block PATH is BY PASSED) (we can also swith off DIG. BLOCK power , PMPFIL=0)
// The Path in Recording Mode 2 & Playback Mode 2 , (NO DIG FILTER BLOCK AT ALL, not for MIC recording, nor for Playback)
map.r.digital_filter_mode.ADCPF = 1; // new code addition , 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 = 0; // new code addition , ADC bit switch ("0" : 1st order HPF) connectedto the Output. By bass DIGITAL block .
map.r.digital_filter_mode.PFDAC = 0b00; // new code addition , (Input selector for DAC (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.
// Restore original condition , LPF , OFF . same as when not using DIGITAL Programmable block
map.r.digital_filter_select_2.LPF = 0; // LPF-Block, Coeffic Setting Enable (OFF-Default), When LPF bit is “0”, audio data passes the LPF block by 0dB gain.
update(Register::DigitalFilterSelect2);
map.r.lpf_coefficient_0.l = 0x00; // Pre-loading here LPF 6k , 1st Order from digital Block , Fc=6000 Hz, fs = 48khz
map.r.lpf_coefficient_1.h = 0x00; // LPF bit is activated down, for all ALC digital modes.
map.r.lpf_coefficient_2.l = 0x00; // Writting reg to AK4951 , down with update....
map.r.lpf_coefficient_3.h = 0x00;
update(Register::LPFCoefficient0); // Writing pre-loaded 4 bytes LPF CoefFiecients 14 bits (FSA13..0, FSB13..0
update(Register::LPFCoefficient1);
update(Register::LPFCoefficient2);
update(Register::LPFCoefficient3);
// Switch off all EQ 1,2,3,4,5
map.r.digital_filter_select_3.EQ1 = 0; // EQ1 Coeffic Setting , (0: Disable-default, audio data passes EQ1 block by 0dB gain). When EQ1="1”, the settings of E1A15-0, E1B15-0 and E1C15-0 bits are enabled
map.r.digital_filter_select_3.EQ2 = 0; // EQ2 Coeffic Setting , (0: Disable-default, audio data passes EQ2 block by 0dB gain). When EQ2="1”, the settings of E2A15-0, E2B15-0 and E2C15-0 bits are enabled
map.r.digital_filter_select_3.EQ3 = 0; // EQ3 Coeffic Setting , (0: Disable-default, audio data passes EQ3 block by 0dB gain). When EQ3="1”, the settings of E3A15-0, E3B15-0 and E3C15-0 bits are enabled
map.r.digital_filter_select_3.EQ4 = 0; // EQ4 Coeffic Setting , (0: Disable-default, audio data passes EQ4 block by 0dB gain). When EQ4="1”, the settings of E4A15-0, E4B15-0 and E4C15-0 bits are enabled
map.r.digital_filter_select_3.EQ5 = 0; // EQ5 Coeffic Setting , (0: Disable-default, audio data passes EQ5 block by 0dB gain). When EQ5="1”, the settings of E5A15-0, E5B15-0 and E5C15-0 bits are enabled
update(Register::DigitalFilterSelect3);
}
reg_t AK4951::read(const address_t reg_address) {
+31 -32
View File
@@ -773,41 +773,40 @@ constexpr RegisterMap default_after_reset { Register_Type {
.REV = 0b1100,
},
// just pre-loading into memory, 30 bytes = EQ 1,2,3,4,5 x A,B,C (2 x bytes) coefficients, but it will be written from ak4951.cpp
.e1_coefficient_0 = { .l = 0xCA }, //EQ1 Coefficient A : A7...A0, BW : 300Hz - 1700Hz (fo = 1150Hz , fb= 1700Hz) , k=1,8 peaking
.e1_coefficient_1 = { .h = 0x05 }, //EQ1 Coefficient A : A15..A8
.e1_coefficient_2 = { .l = 0xEB }, //EQ1 Coefficient B : B7...B0
.e1_coefficient_3 = { .h = 0x38 }, //EQ1 Coefficient B : B15...B8
.e1_coefficient_4 = { .l = 0x6F }, //EQ1 Coefficient C : C7...C0
.e1_coefficient_5 = { .h = 0xE6 }, //EQ1 Coefficient C : C15..C8
.e1_coefficient_0 = { .l = 0x00 },
.e1_coefficient_1 = { .h = 0x00 },
.e1_coefficient_2 = { .l = 0x00 },
.e1_coefficient_3 = { .h = 0x00 },
.e1_coefficient_4 = { .l = 0x00 },
.e1_coefficient_5 = { .h = 0x00 },
.e2_coefficient_0 = { .l = 0x05 }, //EQ2 Coefficient A : A7...A0, BW : 250Hz - 2700Hz (fo = 1475Hz , fb= 2450Hz) , k=1,8 peaking
.e2_coefficient_1 = { .h = 0x08 }, //EQ2 Coefficient A : A15..A8
.e2_coefficient_2 = { .l = 0x11 }, //EQ2 Coefficient B : B7...B0
.e2_coefficient_3 = { .h = 0x36 }, //EQ2 Coefficient B : B15...B8
.e2_coefficient_4 = { .l = 0xE9 }, //EQ2 Coefficient C : C7...C0
.e2_coefficient_5 = { .h = 0xE8 }, //EQ2 Coefficient C : C15..C8
.e2_coefficient_0 = { .l = 0x00 },
.e2_coefficient_1 = { .h = 0x00 },
.e2_coefficient_2 = { .l = 0x00 },
.e2_coefficient_3 = { .h = 0x00 },
.e2_coefficient_4 = { .l = 0x00 },
.e2_coefficient_5 = { .h = 0x00 },
.e3_coefficient_0 = { .l = 0x00 }, //EQ3 Coefficient A : A7...A0, not used currently
.e3_coefficient_1 = { .h = 0x00 }, //EQ3 Coefficient A : A15..A8
.e3_coefficient_2 = { .l = 0x00 }, //EQ3 Coefficient B : B7...B0
.e3_coefficient_3 = { .h = 0x00 }, //EQ3 Coefficient B : B15...B8
.e3_coefficient_4 = { .l = 0x00 }, //EQ3 Coefficient C : C7...C0
.e3_coefficient_5 = { .h = 0x00 }, //EQ3 Coefficient C : C15..C8
.e3_coefficient_0 = { .l = 0x00 },
.e3_coefficient_1 = { .h = 0x00 },
.e3_coefficient_2 = { .l = 0x00 },
.e3_coefficient_3 = { .h = 0x00 },
.e3_coefficient_4 = { .l = 0x00 },
.e3_coefficient_5 = { .h = 0x00 },
.e4_coefficient_0 = { .l = 0x00 }, //EQ4 Coefficient A : A7...A0, not used currently
.e4_coefficient_1 = { .h = 0x00 }, //EQ4 Coefficient A : A15..A8
.e4_coefficient_2 = { .l = 0x00 }, //EQ4 Coefficient B : B7...B0
.e4_coefficient_3 = { .h = 0x00 }, //EQ4 Coefficient B : B15...B8
.e4_coefficient_4 = { .l = 0x00 }, //EQ4 Coefficient C : C7...C0
.e4_coefficient_5 = { .h = 0x00 }, //EQ4 Coefficient C : C15..C8
.e4_coefficient_0 = { .l = 0x00 },
.e4_coefficient_1 = { .h = 0x00 },
.e4_coefficient_2 = { .l = 0x00 },
.e4_coefficient_3 = { .h = 0x00 },
.e4_coefficient_4 = { .l = 0x00 },
.e4_coefficient_5 = { .h = 0x00 },
.e5_coefficient_0 = { .l = 0x00 }, //EQ5 Coefficient A : A7...A0, not used currently
.e5_coefficient_1 = { .h = 0x00 }, //EQ5 Coefficient A : A15..A8
.e5_coefficient_2 = { .l = 0x00 }, //EQ5 Coefficient B : B7...B0
.e5_coefficient_3 = { .h = 0x00 }, //EQ5 Coefficient B : B15...B8
.e5_coefficient_4 = { .l = 0x00 }, //EQ5 Coefficient C : C7...C0
.e5_coefficient_5 = { .h = 0x00 }, //EQ5 Coefficient C : C15..C8
.e5_coefficient_0 = { .l = 0x00 },
.e5_coefficient_1 = { .h = 0x00 },
.e5_coefficient_2 = { .l = 0x00 },
.e5_coefficient_3 = { .h = 0x00 },
.e5_coefficient_4 = { .l = 0x00 },
.e5_coefficient_5 = { .h = 0x00 },
} };
class AK4951 : public audio::Codec {
@@ -842,7 +841,7 @@ public:
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();
void microphone_disable();
size_t reg_count() const override {
+356 -54
View File
@@ -28,7 +28,8 @@
#include "utility.hpp"
#include "memory_map.hpp"
using portapack::memory::map::backup_ram;
#include "crc.hpp"
#include <algorithm>
#include <utility>
@@ -67,8 +68,193 @@ using clkout_freq_range_t = range_t<uint32_t>;
constexpr clkout_freq_range_t clkout_freq_range { 10, 60000 };
constexpr uint32_t clkout_freq_reset_value { 10000 };
enum data_structure_version_enum : uint32_t {
VERSION_CURRENT = 0x10000002,
};
static const uint32_t TOUCH_CALIBRATION_MAGIC = 0x074af82f;
struct ui_config_t {
private:
enum bits_t {
BacklightTimeoutLSB = 0,
BacklightTimeoutEnable = 3,
ClkoutFreqLSB = 4,
ShowGUIReturnIcon = 20,
LoadAppSettings = 21,
SaveAppSettings = 22,
ShowBiggerQRCode = 23,
DisableTouchscreen = 24,
HideClock = 25,
ClockWithDate = 26,
ClkOutEnabled = 27,
ConfigSpeaker = 28,
StealthMode = 29,
ConfigLogin = 30,
ConfigSplash = 31,
};
enum bits_mask_t : uint32_t {
BacklightTimeoutMask = ((1 << 3) - 1) << bits_t::BacklightTimeoutLSB,
ClkoutFreqMask = ((1 << 16) - 1) << bits_t::ClkoutFreqLSB,
};
uint32_t values;
constexpr bool bit_read(const bits_t n) const {
return ((values >> n) & 1) != 0;
}
constexpr void bit_write(const bits_t n, const bool v) {
if(bit_read(n) != v) {
values ^= 1 << n;
}
}
public:
backlight_config_t config_backlight_timer() {
const auto timeout_enum = (backlight_timeout_t)((values & bits_mask_t::BacklightTimeoutMask) >> bits_t::BacklightTimeoutLSB);
const bool timeout_enabled = bit_read(bits_t::BacklightTimeoutEnable);
return backlight_config_t(timeout_enum, timeout_enabled);
}
void set_config_backlight_timer(const backlight_config_t& new_value) {
values = (values & ~bits_mask_t::BacklightTimeoutMask)
| ((new_value.timeout_enum() << bits_t::BacklightTimeoutLSB) & bits_mask_t::BacklightTimeoutMask);
bit_write(bits_t::BacklightTimeoutEnable, new_value.timeout_enabled());
}
constexpr uint32_t clkout_freq() {
uint32_t freq = (values & bits_mask_t::ClkoutFreqMask) >> bits_t::ClkoutFreqLSB;
if(freq < clkout_freq_range.minimum || freq > clkout_freq_range.maximum) {
values = (values & ~bits_mask_t::ClkoutFreqMask) | (clkout_freq_reset_value << bits_t::ClkoutFreqLSB);
return clkout_freq_reset_value;
}
else {
return freq;
}
}
constexpr void set_clkout_freq(uint32_t freq) {
values = (values & ~bits_mask_t::ClkoutFreqMask) | (clkout_freq_range.clip(freq) << bits_t::ClkoutFreqLSB);
}
// ui_config is an uint32_t var storing information bitwise
// bits 0-2 store the backlight timer
// bits 4-19 (16 bits) store the clkout frequency
// bits 21-31 store the different single bit configs depicted below
// bit 20 store the display state of the gui return icon, hidden (0) or shown (1)
constexpr bool show_gui_return_icon() const { // add return icon in touchscreen menue
return bit_read(bits_t::ShowGUIReturnIcon);
}
constexpr void set_gui_return_icon(bool v) {
bit_write(bits_t::ShowGUIReturnIcon, v);
}
constexpr bool load_app_settings() const { // load (last saved) app settings on startup of app
return bit_read(bits_t::LoadAppSettings);
}
constexpr void set_load_app_settings(bool v) {
bit_write(bits_t::LoadAppSettings, v);
}
constexpr bool save_app_settings() const { // save app settings when closing app
return bit_read(bits_t::SaveAppSettings);
}
constexpr void set_save_app_settings(bool v) {
bit_write(bits_t::SaveAppSettings, v);
}
constexpr bool show_bigger_qr_code() const { // show bigger QR code
return bit_read(bits_t::ShowBiggerQRCode);
}
constexpr void set_show_bigger_qr_code(bool v) {
bit_write(bits_t::ShowBiggerQRCode, v);
}
constexpr bool disable_touchscreen() const { // Option to disable touch screen
return bit_read(bits_t::DisableTouchscreen);
}
constexpr void set_disable_touchscreen(bool v) {
bit_write(bits_t::DisableTouchscreen, v);
}
constexpr bool hide_clock() const { // clock hidden from main menu
return bit_read(bits_t::HideClock);
}
constexpr void set_clock_hidden(bool v) {
bit_write(bits_t::HideClock, v);
}
constexpr bool clock_with_date() const { // show clock with date, if not hidden
return bit_read(bits_t::ClockWithDate);
}
constexpr void set_clock_with_date(bool v) {
bit_write(bits_t::ClockWithDate, v);
}
constexpr bool clkout_enabled() const {
return bit_read(bits_t::ClkOutEnabled);
}
constexpr void set_clkout_enabled(bool v) {
bit_write(bits_t::ClkOutEnabled, v);
}
constexpr bool config_speaker() const {
return bit_read(bits_t::ConfigSpeaker);
}
constexpr void set_config_speaker(bool v) {
bit_write(bits_t::ConfigSpeaker, v);
}
constexpr bool stealth_mode() const {
return bit_read(bits_t::StealthMode);
}
constexpr void set_stealth_mode(bool v) {
bit_write(bits_t::StealthMode, v);
}
constexpr bool config_login() const {
return bit_read(bits_t::ConfigLogin);
}
constexpr void set_config_login(bool v) {
bit_write(bits_t::ConfigLogin, v);
}
constexpr bool config_splash() const {
return bit_read(bits_t::ConfigSplash);
}
constexpr void set_config_splash(bool v) {
bit_write(bits_t::ConfigSplash, v);
}
constexpr ui_config_t() :
values(
(1 << ConfigSplash)
| (1 << ConfigSpeaker)
| (clkout_freq_reset_value << ClkoutFreqLSB)
| (7 << BacklightTimeoutLSB)
)
{
}
};
/* struct must pack the same way on M4 and M0 cores. */
struct data_t {
data_structure_version_enum structure_version;
int64_t tuned_frequency;
int32_t correction_ppb;
uint32_t touch_calibration_magic;
@@ -89,7 +275,7 @@ struct data_t {
uint32_t playdead_sequence;
// UI
uint32_t ui_config;
ui_config_t ui_config;
uint32_t pocsag_last_address;
uint32_t pocsag_ignore_address;
@@ -98,11 +284,142 @@ struct data_t {
// Hardware
uint32_t hardware_config;
constexpr data_t() :
structure_version(data_structure_version_enum::VERSION_CURRENT),
tuned_frequency(tuned_frequency_reset_value),
correction_ppb(ppb_reset_value),
touch_calibration_magic(TOUCH_CALIBRATION_MAGIC),
touch_calibration(touch::Calibration()),
modem_def_index(0), // TODO: Unused?
serial_format(),
modem_bw(15000), // TODO: Unused?
afsk_mark_freq(afsk_mark_reset_value),
afsk_space_freq(afsk_space_reset_value),
modem_baudrate(modem_baudrate_reset_value),
modem_repeat(modem_repeat_reset_value),
playdead_magic(), // TODO: Unused?
playing_dead(), // TODO: Unused?
playdead_sequence(), // TODO: Unused?
ui_config(),
pocsag_last_address(0), // TODO: A better default?
pocsag_ignore_address(0), // TODO: A better default?
tone_mix(tone_mix_reset_value),
hardware_config(0)
{
}
};
static_assert(sizeof(data_t) <= backup_ram.size(), "Persistent memory structure too large for VBAT-maintained region");
struct backup_ram_t {
private:
uint32_t regfile[63];
uint32_t check_value;
static data_t* const data = reinterpret_cast<data_t*>(backup_ram.base());
static void copy(const backup_ram_t& src, backup_ram_t& dst) {
for(size_t i=0; i<63; i++) {
dst.regfile[i] = src.regfile[i];
}
dst.check_value = src.check_value;
}
static void copy_from_data_t(const data_t& src, backup_ram_t& dst) {
const uint32_t* const src_words = (uint32_t*)&src;
const size_t word_count = (sizeof(data_t) + 3) / 4;
for(size_t i=0; i<63; i++) {
if(i<word_count) {
dst.regfile[i] = src_words[i];
} else {
dst.regfile[i] = 0;
}
}
}
uint32_t compute_check_value() {
CRC<32> crc { 0x04c11db7, 0xffffffff, 0xffffffff };
for(size_t i=0; i<63; i++) {
const auto word = regfile[i];
crc.process_byte((word >> 0) & 0xff);
crc.process_byte((word >> 8) & 0xff);
crc.process_byte((word >> 16) & 0xff);
crc.process_byte((word >> 24) & 0xff);
}
return crc.checksum();
}
public:
/* default constructor */
backup_ram_t() :
check_value(0)
{
const data_t defaults = data_t();
copy_from_data_t(defaults, *this);
}
/* copy-assignment operator */
backup_ram_t& operator=(const backup_ram_t& src) {
copy(src, *this);
return *this;
}
/* Calculate a check value from `this`, and check against
* the stored value.
*/
bool is_valid() {
return compute_check_value() == check_value;
}
/* Assuming `this` contains valid data, update the checksum
* and copy to the destination.
*/
void persist_to(backup_ram_t& dst) {
check_value = compute_check_value();
copy(*this, dst);
}
};
static_assert(sizeof(backup_ram_t) == memory::map::backup_ram.size());
static_assert(sizeof(data_t) <= sizeof(backup_ram_t) - sizeof(uint32_t));
static backup_ram_t* const backup_ram = reinterpret_cast<backup_ram_t*>(memory::map::backup_ram.base());
static backup_ram_t cached_backup_ram;
static data_t* const data = reinterpret_cast<data_t*>(&cached_backup_ram);
namespace cache {
void defaults() {
cached_backup_ram = backup_ram_t();
}
void init() {
if(backup_ram->is_valid()) {
// Copy valid persistent data into cache.
cached_backup_ram = *backup_ram;
// Check that structure data we copied into cache is the expected
// version. If not, initialize cache to defaults.
if(data->structure_version != data_structure_version_enum::VERSION_CURRENT) {
// TODO: Can provide version-to-version upgrade functions here,
// if we want to be fancy.
defaults();
}
} else {
// Copy defaults into cache.
defaults();
}
}
void persist() {
cached_backup_ram.persist_to(*backup_ram);
}
} /* namespace cache */
rf::Frequency tuned_frequency() {
rf::tuning_range.reset_if_outside(data->tuned_frequency, tuned_frequency_reset_value);
@@ -124,16 +441,14 @@ void set_correction_ppb(const ppb_t new_value) {
portapack::clock_manager.set_reference_ppb(clipped_value);
}
static constexpr uint32_t touch_calibration_magic = 0x074af82f;
void set_touch_calibration(const touch::Calibration& new_value) {
data->touch_calibration = new_value;
data->touch_calibration_magic = touch_calibration_magic;
data->touch_calibration_magic = TOUCH_CALIBRATION_MAGIC;
}
const touch::Calibration& touch_calibration() {
if( data->touch_calibration_magic != touch_calibration_magic ) {
set_touch_calibration(touch::default_calibration());
if( data->touch_calibration_magic != TOUCH_CALIBRATION_MAGIC ) {
set_touch_calibration(touch::Calibration());
}
return data->touch_calibration;
}
@@ -200,122 +515,116 @@ void set_serial_format(const serial_format_t new_value) {
data->serial_format = new_value;
}
// ui_config is an uint32_t var storing information bitwise
// bits 0-2 store the backlight timer
// bits 4-19 (16 bits) store the clkout frequency
// bits 21-31 store the different single bit configs depicted below
// bit 20 store the display state of the gui return icon, hidden (0) or shown (1)
bool show_gui_return_icon(){ // add return icon in touchscreen menue
return data->ui_config & (1 << 20);
bool show_gui_return_icon() { // add return icon in touchscreen menue
return data->ui_config.show_gui_return_icon();
}
bool load_app_settings() { // load (last saved) app settings on startup of app
return data->ui_config & (1 << 21);
return data->ui_config.load_app_settings();
}
bool save_app_settings() { // save app settings when closing app
return data->ui_config & (1 << 22);
return data->ui_config.save_app_settings();
}
bool show_bigger_qr_code() { // show bigger QR code
return data->ui_config & (1 << 23);
return data->ui_config.show_bigger_qr_code();
}
bool disable_touchscreen() { // Option to disable touch screen
return data->ui_config & (1 << 24);
return data->ui_config.disable_touchscreen();
}
bool hide_clock() { // clock hidden from main menu
return data->ui_config & (1 << 25);
return data->ui_config.hide_clock();
}
bool clock_with_date() { // show clock with date, if not hidden
return data->ui_config & (1 << 26);
return data->ui_config.clock_with_date();
}
bool clkout_enabled() {
return data->ui_config & (1 << 27);
return data->ui_config.clkout_enabled();
}
bool config_speaker() {
return data->ui_config & (1 << 28);
return data->ui_config.config_speaker();
}
bool stealth_mode() {
return data->ui_config & (1 << 29);
return data->ui_config.stealth_mode();
}
bool config_login() {
return data->ui_config & (1 << 30);
return data->ui_config.config_login();
}
bool config_splash() {
return data->ui_config & (1 << 31);
return data->ui_config.config_splash();
}
uint8_t config_cpld() {
return data->hardware_config;
}
uint32_t config_backlight_timer() {
const uint32_t timer_seconds[8] = { 0, 5, 15, 30, 60, 180, 300, 600 };
return timer_seconds[data->ui_config & 7]; //first three bits, 8 possible values
backlight_config_t config_backlight_timer() {
return data->ui_config.config_backlight_timer();
}
void set_gui_return_icon(bool v) {
data->ui_config = (data->ui_config & ~(1 << 20)) | (v << 20);
data->ui_config.set_gui_return_icon(v);
}
void set_load_app_settings(bool v) {
data->ui_config = (data->ui_config & ~(1 << 21)) | (v << 21);
data->ui_config.set_load_app_settings(v);
}
void set_save_app_settings(bool v) {
data->ui_config = (data->ui_config & ~(1 << 22)) | (v << 22);
data->ui_config.set_save_app_settings(v);
}
void set_show_bigger_qr_code(bool v) {
data->ui_config = (data->ui_config & ~(1 << 23)) | (v << 23);
data->ui_config.set_show_bigger_qr_code(v);
}
void set_disable_touchscreen(bool v) {
data->ui_config = (data->ui_config & ~(1 << 24)) | (v << 24);
data->ui_config.set_disable_touchscreen(v);
}
void set_clock_hidden(bool v) {
data->ui_config = (data->ui_config & ~(1 << 25)) | (v << 25);
data->ui_config.set_clock_hidden(v);
}
void set_clock_with_date(bool v) {
data->ui_config = (data->ui_config & ~(1 << 26)) | (v << 26);
data->ui_config.set_clock_with_date(v);
}
void set_clkout_enabled(bool v) {
data->ui_config = (data->ui_config & ~(1 << 27)) | (v << 27);
data->ui_config.set_clkout_enabled(v);
}
void set_config_speaker(bool v) {
data->ui_config = (data->ui_config & ~(1 << 28)) | (v << 28);
data->ui_config.set_config_speaker(v);
}
void set_stealth_mode(bool v) {
data->ui_config = (data->ui_config & ~(1 << 29)) | (v << 29);
data->ui_config.set_stealth_mode(v);
}
void set_config_login(bool v) {
data->ui_config = (data->ui_config & ~(1 << 30)) | (v << 30);
data->ui_config.set_config_login(v);
}
void set_config_splash(bool v) {
data->ui_config = (data->ui_config & ~(1 << 31)) | (v << 31);
data->ui_config.set_config_splash(v);
}
void set_config_cpld(uint8_t i) {
data->hardware_config = i;
}
void set_config_backlight_timer(uint32_t i) {
data->ui_config = (data->ui_config & ~7) | (i & 7);
void set_config_backlight_timer(const backlight_config_t& new_value) {
data->ui_config.set_config_backlight_timer(new_value);
}
/*void set_config_textentry(uint8_t new_value) {
@@ -347,18 +656,11 @@ void set_pocsag_ignore_address(uint32_t address) {
}
uint32_t clkout_freq() {
uint16_t freq = (data->ui_config & 0x000FFFF0) >> 4;
if(freq < clkout_freq_range.minimum || freq > clkout_freq_range.maximum) {
data->ui_config = (data->ui_config & ~0x000FFFF0) | clkout_freq_reset_value << 4;
return clkout_freq_reset_value;
}
else {
return freq;
}
return data->ui_config.clkout_freq();
}
void set_clkout_freq(uint32_t freq) {
data->ui_config = (data->ui_config & ~0x000FFFF0) | (clkout_freq_range.clip(freq) << 4);
data->ui_config.set_clkout_freq(freq);
}
@@ -25,6 +25,8 @@
#include <cstdint>
#include "optional.hpp"
#include "rf_path.hpp"
#include "touch.hpp"
#include "modems.hpp"
@@ -36,6 +38,77 @@ using namespace serializer;
namespace portapack {
namespace persistent_memory {
enum backlight_timeout_t {
Timeout5Sec = 0,
Timeout15Sec = 1,
Timeout30Sec = 2,
Timeout60Sec = 3,
Timeout180Sec = 4,
Timeout300Sec = 5,
Timeout600Sec = 6,
Timeout3600Sec = 7,
};
struct backlight_config_t {
public:
backlight_config_t() :
_timeout_enum(backlight_timeout_t::Timeout600Sec),
_timeout_enabled(false)
{
}
backlight_config_t(
backlight_timeout_t timeout_enum,
bool timeout_enabled
) :
_timeout_enum(timeout_enum),
_timeout_enabled(timeout_enabled)
{
}
bool timeout_enabled() const {
return _timeout_enabled;
}
backlight_timeout_t timeout_enum() const {
return _timeout_enum;
}
uint32_t timeout_seconds() const {
switch(timeout_enum()) {
case Timeout5Sec: return 5;
case Timeout15Sec: return 15;
case Timeout30Sec: return 30;
case Timeout60Sec: return 60;
case Timeout180Sec: return 180;
case Timeout300Sec: return 300;
default:
case Timeout600Sec: return 600;
case Timeout3600Sec: return 3600;
}
}
private:
backlight_timeout_t _timeout_enum;
bool _timeout_enabled;
};
namespace cache {
/* Set values in cache to sensible defaults. */
void defaults();
/* Load cached settings from values in persistent RAM, replacing with defaults
* if persistent RAM contents appear to be invalid. */
void init();
/* Calculate a check value for cached settings, and copy the check value and
* settings into persistent RAM. Intended to be called periodically to update
* persistent settings with current settings. */
void persist();
} /* namespace cache */
using ppb_t = int32_t;
rf::Frequency tuned_frequency();
@@ -86,7 +159,7 @@ bool hide_clock();
bool clock_with_date();
bool config_login();
bool config_speaker();
uint32_t config_backlight_timer();
backlight_config_t config_backlight_timer();
bool disable_touchscreen();
void set_gui_return_icon(bool v);
@@ -98,7 +171,7 @@ void set_clock_hidden(bool v);
void set_clock_with_date(bool v);
void set_config_login(bool v);
void set_config_speaker(bool v);
void set_config_backlight_timer(uint32_t i);
void set_config_backlight_timer(const backlight_config_t& new_value);
void set_disable_touchscreen(bool v);
//uint8_t ui_config_textentry();
+5 -5
View File
@@ -95,27 +95,27 @@ struct range_t {
const T minimum;
const T maximum;
const T& clip(const T& value) const {
constexpr const T& clip(const T& value) const {
return std::max(std::min(value, maximum), minimum);
}
void reset_if_outside(T& value, const T& reset_value) const {
constexpr void reset_if_outside(T& value, const T& reset_value) const {
if( (value < minimum ) ||
(value > maximum ) ) {
value = reset_value;
}
}
bool below_range(const T& value) const {
constexpr bool below_range(const T& value) const {
return value < minimum;
}
bool contains(const T& value) const {
constexpr bool contains(const T& value) const {
// TODO: Subtle gotcha here! Range test doesn't include maximum!
return (value >= minimum) && (value < maximum);
}
bool out_of_range(const T& value) const {
constexpr bool out_of_range(const T& value) const {
// TODO: Subtle gotcha here! Range test in contains() doesn't include maximum!
return !contains(value);
}
+2 -3
View File
@@ -345,9 +345,8 @@ public:
void speaker_disable() {};
void microphone_enable(int8_t alc_mode) override {
(void)alc_mode; // to avoid "unused warning" when compiling. (@WM8731 we do not use that parameter)
// TODO: Implement,
void microphone_enable() override {
// TODO: Implement
}
void microphone_disable() override {
+3 -3
View File
@@ -36,7 +36,7 @@ outfile.write(struct.pack('H', im.size[1]))
print("Generating: \t" + outfile.name + "\n from\t\t" + im.filename + "\n please wait...");
for y in range (0, im.size[1]):
line = ''
line = b''
for x in range (0, im.size[0]):
# RRRRRGGGGGGBBBBB
pixel_lcd = (pix[x, y][0] >> 3) << 11
@@ -47,8 +47,8 @@ for y in range (0, im.size[1]):
# pixel_lcd = (pix[x, y][0] >> 5) << 5
# pixel_lcd |= (pix[x, y][1] >> 5) << 2
# pixel_lcd |= (pix[x, y][2] >> 6)
line += str(struct.pack('H', pixel_lcd))
outfile.write(line.encode('utf-8'))
line += struct.pack('H', pixel_lcd)
outfile.write(line)
print(str(y) + '/' + str(im.size[1]) + '\r', end="")
print("Ready.");
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+1 -1
Submodule hackrf updated: e6eb4ba29b...dfadf6a31c