Compare commits
70 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 934f4b07c4 | |||
| bf3f9cfe75 | |||
| 3c304b9fe3 | |||
| 2d765f8120 | |||
| e4c9287af3 | |||
| 15c6285639 | |||
| d525f9a9b3 | |||
| 89f953c75e | |||
| 0bda172f5e | |||
| 086f3098c4 | |||
| 7ca0d1eb3d | |||
| c232287023 | |||
| 222e2c8530 | |||
| c406e7b631 | |||
| 7426c7a7a5 | |||
| 4d839ea44e | |||
| 07e9b50abe | |||
| a5721c5444 | |||
| 64bc4d4068 | |||
| 0afc88ea7b | |||
| 4b4aab640a | |||
| cc75ed5eee | |||
| 43870e97bc | |||
| 0e75cfea12 | |||
| 993396a048 | |||
| cb0a4da7e1 | |||
| 81d5ac4923 | |||
| ef0336ac4f | |||
| e3533594de | |||
| db9d80dc0c | |||
| b2286eec7e | |||
| e737d3c678 | |||
| 7fa92868d7 | |||
| 79700fcddd | |||
| bf01462bd6 | |||
| eab4567ae8 | |||
| dfe1ddfa9f | |||
| 38b6f334b2 | |||
| 92d9b677f7 | |||
| 8a6e04fc0b | |||
| 9446e64784 | |||
| 74f76348b3 | |||
| a1a417d94b | |||
| 1c11a25571 | |||
| eb3b7ac585 | |||
| d7f3539cd9 | |||
| 853912733e | |||
| 21b69e1793 | |||
| 4b33d98cf8 | |||
| 2e65ce8f85 | |||
| 2437a510ed | |||
| 4dd73d201b | |||
| 4acaeea698 | |||
| 4e850df0fc | |||
| f58b6b95c0 | |||
| fd55c8e8e7 | |||
| ce29411aa4 | |||
| ae569cbd65 | |||
| 0d5798ac30 | |||
| 2cd2443eb2 | |||
| e8792e446a | |||
| 59b310dff5 | |||
| 52b951f705 | |||
| b6aa8e9b01 | |||
| 29457f0e46 | |||
| 7ef617946b | |||
| b539b17a50 | |||
| 2cdd11d96a | |||
| 0d64da4a23 | |||
| 38a392e3ea |
@@ -19,5 +19,11 @@ Steps to reproduce the behavior:
|
||||
**Expected behavior**
|
||||
A clear and concise description of what you expected to happen.
|
||||
|
||||
**Affected versions**
|
||||
Please try to reproduce the problem, and write any difference related with the Expected behavior, on the maximum number of versions:
|
||||
* Latest Stable Release
|
||||
* Original PortaPack (if possible; this firmware is also included inside the Release package)
|
||||
* Any previous version (if possible; i.e.: you remember this working on a previous Release)
|
||||
|
||||
**Additional**
|
||||
If the bug is difficult to explain, additionally to the text please include images and videos.
|
||||
|
||||
@@ -1,25 +1,50 @@
|
||||
## Fork of the unofficial HAVOC
|
||||
# PortaPack Mayhem
|
||||
|
||||
Keeping the latest release files and all features I found, and possible my own features in the future, around here. Check Releases
|
||||
[](https://travis-ci.com/eried/portapack-mayhem) [](https://app.buddy.works/eried/portapack/pipelines/pipeline/252276) [](https://codescene.io/projects/8381) [](https://hub.docker.com/r/eried/portapack)
|
||||
|
||||
[](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=CBPQA4HRRPJQ6&source=url)
|
||||
This is a fork of the [Havoc](https://github.com/furrtek/portapack-havoc/), which was a fork of the [PortaPack](https://github.com/sharebrained/portapack-hackrf) firmware, an add-on for the [HackRF](http://greatscottgadgets.com/hackrf/). A fork means it is a derivated, so it is basically a clone that has extra features and fixes over the older versions.
|
||||
|
||||
I only have this [Portapack H2+HackRF+battery](https://s.click.aliexpress.com/e/_dSMPvNo), so that's the version I'll be using for testing the releases before I post them here. BTW, if you have the same H2 (I know... I know it is a *dirty* clone) you could print my case:
|
||||
[](https://www.thingiverse.com/thing:4260973)
|
||||
[<img src="https://raw.githubusercontent.com/wiki/eried/portapack-mayhem/img/hw_overview_h2_front.png" height="400">](https://github.com/eried/portapack-mayhem/wiki/Hardware-overview) [<img src="https://raw.githubusercontent.com/wiki/eried/portapack-mayhem/img/hw_overview_h2_inside.png" height="400">](https://github.com/eried/portapack-mayhem/wiki/Hardware-overview#portapack-internals)
|
||||
|
||||
<details>
|
||||
<summary>More details about the H2 case</summary>
|
||||
|
||||
[STL files](https://www.thingiverse.com/thing:4260973)
|
||||
*[PortaPack H2](https://s.click.aliexpress.com/e/_dSMPvNo) (clone) with a custom [3d printed case](https://github.com/eried/portapack-mayhem/wiki/H2-Enclosure)*
|
||||
|
||||
|
||||
</details>
|
||||
## FAQ
|
||||
|
||||
<details>
|
||||
<summary>Printed magnetic cover for the H2 case</summary>
|
||||
|
||||
[](https://www.thingiverse.com/thing:4278961)
|
||||
|
||||
[STL files](https://www.thingiverse.com/thing:4278961)
|
||||
|
||||
</details>
|
||||
The intention of the current repository is to try to get all the latest features and cleanest documentation for them, embracing any colaboration. To clarify any basic question, please read the following common ones:
|
||||
|
||||
### Does it work on H1/H2 PortaPack?
|
||||
|
||||
Yes, those are the [same](https://github.com/eried/portapack-mayhem/wiki/First-steps). The one I am using to test all changes is this [Portapack H2+HackRF+battery](https://s.click.aliexpress.com/e/_dSMPvNo), which is a clone that includes everything you need. Sadly, the people making the H2 never published the updated PCB, so it is not "optimal" for the community.
|
||||
|
||||
### Where is the latest firmware?
|
||||
|
||||
The current stable release is on the [Release](https://github.com/eried/portapack-mayhem/releases/latest) page. Follow the instructions you can find in the release description.
|
||||
|
||||
There is also [nightly builds](https://github.com/eried/portapack-mayhem/releases/tag/nightly) generated frequently, but these may contain incomplete functionality.
|
||||
|
||||
### Is this the newest firmware for my PortaPack?
|
||||
Probably **YES**.
|
||||
|
||||
### Which one is actually the newest?
|
||||
There is a lot of confusion of which is the latest version because no old version used any actual "version number". Additionally, since the files were distributed on facebook groups, github issue links and similar temporal sources, then there was no central location for them.
|
||||
|
||||
This fork (**Mayhem**) uses *major.minor.release* [semantic versioning](https://en.wikipedia.org/wiki/Software_versioning), so you can always compare your current version with the latest from [Releases](https://github.com/eried/portapack-mayhem/releases/latest).
|
||||
|
||||
### What about Havoc/GridRF/jamesshao8/jboone's?
|
||||
* jboone's PortaPack: the [vainilla](https://en.wikipedia.org/wiki/Vanilla_software) experience
|
||||
* Havoc: It was the most popular fork of jboone's PortaPack, right now is readonly so it is not being developed
|
||||
* jamesshao8: He keeps his own version of the fork, while not attached as a fork to anything
|
||||
* GridRF: They sell PortaPack clones with their own firmware based on a old version, which has no sourcecode available
|
||||
|
||||
### How can I colaborate
|
||||
You can write [documentation](https://github.com/eried/portapack-mayhem/wiki), fix bugs and [answer issues](https://github.com/eried/portapack-mayhem/issues) or add new functionality. Please check the following [guide](https://github.com/eried/portapack-mayhem/wiki/How-to-colaborate) with details.
|
||||
|
||||
Consider that the hardware and firmware has been created and maintain by a [lot](https://github.com/mossmann/hackrf/graphs/contributors) of [people](https://github.com/eried/portapack-mayhem/graphs/contributors), so always try colaborating your time and effort first.
|
||||
|
||||
As a last option, if you want to send money directly to me for getting more boards, antennas and such, please use:
|
||||
[](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=CBPQA4HRRPJQ6&source=url)
|
||||
|
||||
### What if I need help?
|
||||
First, check the [documentation](https://github.com/eried/portapack-mayhem/wiki). If you find a bug or you think the problem is related to the current repository, please open an [issue](https://github.com/eried/portapack-mayhem/issues/new/choose).
|
||||
|
||||
You can reach the [official community](https://www.facebook.com/groups/177623356165819) in Facebook.
|
||||
|
||||
@@ -321,37 +321,39 @@ void DebugControlsView::focus() {
|
||||
|
||||
DebugPeripheralsMenuView::DebugPeripheralsMenuView(NavigationView& nav) {
|
||||
add_items({
|
||||
{ "RFFC5072", ui::Color::white(), nullptr, [&nav](){ nav.push<RegistersView>(
|
||||
{ "RFFC5072", ui::Color::dark_cyan(), &bitmap_icon_peripherals_details, [&nav](){ nav.push<RegistersView>(
|
||||
"RFFC5072", RegistersWidgetConfig { 31, 16 },
|
||||
[](const size_t register_number) { return radio::debug::first_if::register_read(register_number); }
|
||||
); } },
|
||||
{ "MAX2837", ui::Color::white(), nullptr, [&nav](){ nav.push<RegistersView>(
|
||||
{ "MAX2837", ui::Color::dark_cyan(), &bitmap_icon_peripherals_details, [&nav](){ nav.push<RegistersView>(
|
||||
"MAX2837", RegistersWidgetConfig { 32, 10 },
|
||||
[](const size_t register_number) { return radio::debug::second_if::register_read(register_number); }
|
||||
); } },
|
||||
{ "Si5351C", ui::Color::white(), nullptr, [&nav](){ nav.push<RegistersView>(
|
||||
{ "Si5351C", ui::Color::dark_cyan(), &bitmap_icon_peripherals_details, [&nav](){ nav.push<RegistersView>(
|
||||
"Si5351C", RegistersWidgetConfig { 96, 8 },
|
||||
[](const size_t register_number) { return portapack::clock_generator.read_register(register_number); }
|
||||
); } },
|
||||
{ audio::debug::codec_name(), ui::Color::white(), nullptr, [&nav](){ nav.push<RegistersView>(
|
||||
{ audio::debug::codec_name(), ui::Color::dark_cyan(), &bitmap_icon_peripherals_details, [&nav](){ nav.push<RegistersView>(
|
||||
audio::debug::codec_name(), RegistersWidgetConfig { audio::debug::reg_count(), audio::debug::reg_bits() },
|
||||
[](const size_t register_number) { return audio::debug::reg_read(register_number); }
|
||||
); } },
|
||||
});
|
||||
on_left = [&nav](){ nav.pop(); };
|
||||
set_max_rows(2); // allow wider buttons
|
||||
}
|
||||
|
||||
/* DebugMenuView *********************************************************/
|
||||
|
||||
DebugMenuView::DebugMenuView(NavigationView& nav) {
|
||||
add_items({
|
||||
{ "Memory", ui::Color::white(), nullptr, [&nav](){ nav.push<DebugMemoryView>(); } },
|
||||
//{ "..", ui::Color::light_grey(),&bitmap_icon_previous, [&nav](){ nav.pop(); } },
|
||||
{ "Memory", ui::Color::dark_cyan(), &bitmap_icon_memory, [&nav](){ nav.push<DebugMemoryView>(); } },
|
||||
//{ "Radio State", ui::Color::white(), nullptr, [&nav](){ nav.push<NotImplementedView>(); } },
|
||||
{ "SD Card", ui::Color::white(), nullptr, [&nav](){ nav.push<SDCardDebugView>(); } },
|
||||
{ "Peripherals", ui::Color::white(), nullptr, [&nav](){ nav.push<DebugPeripheralsMenuView>(); } },
|
||||
{ "Temperature", ui::Color::white(), nullptr, [&nav](){ nav.push<TemperatureView>(); } },
|
||||
{ "Controls", ui::Color::white(), nullptr, [&nav](){ nav.push<DebugControlsView>(); } }, });
|
||||
on_left = [&nav](){ nav.pop(); };
|
||||
{ "SD Card", ui::Color::dark_cyan(), &bitmap_icon_sdcard, [&nav](){ nav.push<SDCardDebugView>(); } },
|
||||
{ "Peripherals", ui::Color::dark_cyan(), &bitmap_icon_peripherals, [&nav](){ nav.push<DebugPeripheralsMenuView>(); } },
|
||||
{ "Temperature", ui::Color::dark_cyan(), &bitmap_icon_temperature, [&nav](){ nav.push<TemperatureView>(); } },
|
||||
{ "Buttons test", ui::Color::dark_cyan(), &bitmap_icon_controls, [&nav](){ nav.push<DebugControlsView>(); } },
|
||||
});
|
||||
set_max_rows(2); // allow wider buttons
|
||||
}
|
||||
|
||||
/*DebugLCRView::DebugLCRView(NavigationView& nav, std::string lcr_string) {
|
||||
|
||||
@@ -287,14 +287,16 @@ private:
|
||||
};
|
||||
};*/
|
||||
|
||||
class DebugPeripheralsMenuView : public MenuView {
|
||||
class DebugPeripheralsMenuView : public BtnGridView {
|
||||
public:
|
||||
DebugPeripheralsMenuView(NavigationView& nav);
|
||||
std::string title() const override { return "Peripherals"; };
|
||||
};
|
||||
|
||||
class DebugMenuView : public MenuView {
|
||||
class DebugMenuView : public BtnGridView {
|
||||
public:
|
||||
DebugMenuView(NavigationView& nav);
|
||||
std::string title() const override { return "Debug"; };
|
||||
};
|
||||
|
||||
} /* namespace ui */
|
||||
|
||||
@@ -32,8 +32,8 @@ namespace ui {
|
||||
void FileManBaseView::load_directory_contents(const std::filesystem::path& dir_path) {
|
||||
current_path = dir_path;
|
||||
|
||||
text_current.set(dir_path.string().substr(0, 30 - 8));
|
||||
|
||||
text_current.set(dir_path.string().length()? dir_path.string().substr(0, 30 - 6):"(sd root)");
|
||||
|
||||
entry_list.clear();
|
||||
|
||||
auto filtering = (bool)extension_filter.size();
|
||||
@@ -315,7 +315,7 @@ FileManagerView::FileManagerView(
|
||||
|
||||
button_delete.on_select = [this, &nav](Button&) {
|
||||
// Use display_modal ?
|
||||
nav.push<ModalMessageView>("Delete", "Delete " + entry_list[menu_view.highlighted_index()].entry_path.filename().string() + "\nAre you sure ?", YESNO,
|
||||
nav.push<ModalMessageView>("Delete", "Delete " + entry_list[menu_view.highlighted_index()].entry_path.filename().string() + "\nAre you sure?", YESNO,
|
||||
[this](bool choice) {
|
||||
if (choice)
|
||||
on_delete();
|
||||
|
||||
@@ -67,8 +67,9 @@ protected:
|
||||
{ ".TXT", &bitmap_icon_file_text, ui::Color::white() },
|
||||
{ ".PNG", &bitmap_icon_file_image, ui::Color::green() },
|
||||
{ ".BMP", &bitmap_icon_file_image, ui::Color::green() },
|
||||
{ ".C8", &bitmap_icon_file_iq, ui::Color::blue() },
|
||||
{ ".C16", &bitmap_icon_file_iq, ui::Color::blue() },
|
||||
{ ".WAV", &bitmap_icon_speaker, ui::Color::dark_magenta() },
|
||||
{ ".WAV", &bitmap_icon_file_wav, ui::Color::dark_magenta() },
|
||||
{ "", &bitmap_icon_file, ui::Color::light_grey() }
|
||||
};
|
||||
|
||||
@@ -84,10 +85,10 @@ protected:
|
||||
void refresh_list();
|
||||
|
||||
Labels labels {
|
||||
{ { 0, 0 }, "Current:", Color::light_grey() }
|
||||
{ { 0, 0 }, "Path:", Color::light_grey() }
|
||||
};
|
||||
Text text_current {
|
||||
{ 8 * 8, 0 * 8, 22 * 8, 16 },
|
||||
{ 6 * 8, 0 * 8, 24 * 8, 16 },
|
||||
"",
|
||||
};
|
||||
|
||||
|
||||
@@ -81,6 +81,7 @@ void ScannerView::handle_retune(uint32_t i) {
|
||||
text_cycle.set( to_string_dec_uint(i) + "/" +
|
||||
to_string_dec_uint(frequency_list.size()) + " : " +
|
||||
to_string_dec_uint(frequency_list[i]) );
|
||||
desc_cycle.set( description_list[i] );
|
||||
}
|
||||
|
||||
void ScannerView::focus() {
|
||||
@@ -104,10 +105,12 @@ ScannerView::ScannerView(
|
||||
&field_rf_amp,
|
||||
&field_volume,
|
||||
&field_bw,
|
||||
&field_trigger,
|
||||
&field_squelch,
|
||||
&field_wait,
|
||||
//&record_view,
|
||||
&text_cycle,
|
||||
&desc_cycle,
|
||||
//&waterfall,
|
||||
});
|
||||
|
||||
@@ -118,19 +121,28 @@ ScannerView::ScannerView(
|
||||
if (entry.type == RANGE) {
|
||||
for (uint32_t i=entry.frequency_a; i < entry.frequency_b; i+= 1000000) {
|
||||
frequency_list.push_back(i);
|
||||
description_list.push_back("RNG " + to_string_dec_uint(entry.frequency_a) + ">" + to_string_dec_uint(entry.frequency_b));
|
||||
}
|
||||
} else {
|
||||
frequency_list.push_back(entry.frequency_a);
|
||||
description_list.push_back(entry.description);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// DEBUG
|
||||
// TODO: Clean this
|
||||
frequency_list.push_back(466025000);
|
||||
description_list.push_back("POCSAG-France");
|
||||
frequency_list.push_back(466050000);
|
||||
description_list.push_back("POCSAG-France");
|
||||
frequency_list.push_back(466075000);
|
||||
description_list.push_back("POCSAG-France");
|
||||
frequency_list.push_back(466175000);
|
||||
description_list.push_back("POCSAG-France");
|
||||
frequency_list.push_back(466206250);
|
||||
description_list.push_back("POCSAG-France");
|
||||
frequency_list.push_back(466231250);
|
||||
description_list.push_back("POCSAG-France");
|
||||
}
|
||||
|
||||
field_bw.set_selected_index(2);
|
||||
@@ -143,10 +155,17 @@ ScannerView::ScannerView(
|
||||
};
|
||||
field_wait.set_value(5);
|
||||
|
||||
field_trigger.on_change = [this](int32_t v) {
|
||||
trigger = v;
|
||||
};
|
||||
field_trigger.set_value(30);
|
||||
|
||||
field_squelch.set_value(receiver_model.squelch_level());
|
||||
field_squelch.on_change = [this](int32_t v) {
|
||||
squelch = v;
|
||||
receiver_model.set_squelch_level(v);
|
||||
};
|
||||
field_squelch.set_value(30);
|
||||
|
||||
|
||||
field_volume.set_value((receiver_model.headphone_volume() - audio::headphone::volume_range().max).decibel() + 99);
|
||||
field_volume.on_change = [this](int32_t v) {
|
||||
@@ -175,7 +194,7 @@ void ScannerView::on_statistics_update(const ChannelStatistics& statistics) {
|
||||
if (timer <= wait)
|
||||
timer++;
|
||||
|
||||
if (max_db < -squelch) {
|
||||
if (max_db < -trigger) {
|
||||
if (timer == wait) {
|
||||
//audio::output::stop();
|
||||
scan_thread->set_scanning(true);
|
||||
|
||||
@@ -66,15 +66,17 @@ private:
|
||||
void handle_retune(uint32_t i);
|
||||
|
||||
std::vector<rf::Frequency> frequency_list { };
|
||||
std::vector<string> description_list { };
|
||||
int32_t trigger { 0 };
|
||||
int32_t squelch { 0 };
|
||||
uint32_t timer { 0 };
|
||||
uint32_t wait { 0 };
|
||||
freqman_db database { };
|
||||
|
||||
Labels labels {
|
||||
{ { 0 * 8, 0 * 16 }, "LNA: VGA: AMP: VOL:", Color::light_grey() },
|
||||
{ { 0 * 8, 1 * 16 }, "BW: SQUELCH: /99 WAIT:", Color::light_grey() },
|
||||
{ { 0 * 8, 3 * 16 }, "Work in progress...", Color::light_grey() }
|
||||
{ { 0 * 8, 0 * 16 }, "LNA: TRIGGER: /99 VOL:", Color::light_grey() },
|
||||
{ { 0 * 8, 1 * 16 }, "VGA: SQUELCH: /99 AMP:", Color::light_grey() },
|
||||
{ { 0 * 8, 2 * 16 }, " BW: WAIT:", Color::light_grey() },
|
||||
};
|
||||
|
||||
LNAGainField field_lna {
|
||||
@@ -82,15 +84,15 @@ private:
|
||||
};
|
||||
|
||||
VGAGainField field_vga {
|
||||
{ 11 * 8, 0 * 16 }
|
||||
{ 4 * 8, 1 * 16 }
|
||||
};
|
||||
|
||||
RFAmpField field_rf_amp {
|
||||
{ 18 * 8, 0 * 16 }
|
||||
{ 28 * 8, 1 * 16 }
|
||||
};
|
||||
|
||||
NumberField field_volume {
|
||||
{ 24 * 8, 0 * 16 },
|
||||
{ 28 * 8, 0 * 16 },
|
||||
2,
|
||||
{ 0, 99 },
|
||||
1,
|
||||
@@ -98,7 +100,7 @@ private:
|
||||
};
|
||||
|
||||
OptionsField field_bw {
|
||||
{ 3 * 8, 1 * 16 },
|
||||
{ 4 * 8, 2 * 16 },
|
||||
3,
|
||||
{
|
||||
{ "8k5", 0 },
|
||||
@@ -107,8 +109,16 @@ private:
|
||||
}
|
||||
};
|
||||
|
||||
NumberField field_trigger {
|
||||
{ 16 * 8, 0 * 16 },
|
||||
2,
|
||||
{ 0, 99 },
|
||||
1,
|
||||
' ',
|
||||
};
|
||||
|
||||
NumberField field_squelch {
|
||||
{ 15 * 8, 1 * 16 },
|
||||
{ 16 * 8, 1 * 16 },
|
||||
2,
|
||||
{ 0, 99 },
|
||||
1,
|
||||
@@ -116,7 +126,7 @@ private:
|
||||
};
|
||||
|
||||
NumberField field_wait {
|
||||
{ 26 * 8, 1 * 16 },
|
||||
{ 16 * 8, 2 * 16 },
|
||||
2,
|
||||
{ 0, 99 },
|
||||
1,
|
||||
@@ -127,6 +137,10 @@ private:
|
||||
{ 0, 5 * 16, 240, 16 },
|
||||
"--/--"
|
||||
};
|
||||
Text desc_cycle {
|
||||
{0, 6 * 16, 240, 16 },
|
||||
" "
|
||||
};
|
||||
|
||||
std::unique_ptr<ScannerThread> scan_thread { };
|
||||
|
||||
|
||||
@@ -94,7 +94,7 @@ ScriptView::ScriptView(
|
||||
};
|
||||
|
||||
button_del.on_select = [this, &nav](Button&) {
|
||||
nav.push<ModalMessageView>("Confirm", "Are you sure ?", YESNO,
|
||||
nav.push<ModalMessageView>("Confirm", "Are you sure?", YESNO,
|
||||
[this](bool choice) {
|
||||
if (choice) {
|
||||
on_delete();
|
||||
|
||||
@@ -45,7 +45,7 @@ void WipeSDView::focus() {
|
||||
dummy.focus();
|
||||
|
||||
if (!confirmed) {
|
||||
nav_.push<ModalMessageView>("Warning !", "Wipe FAT of SD card ?", YESCANCEL, [this](bool choice) {
|
||||
nav_.push<ModalMessageView>("Warning !", "Wipe FAT of SD card?", YESCANCEL, [this](bool choice) {
|
||||
if (choice)
|
||||
confirmed = true;
|
||||
}
|
||||
|
||||
@@ -29,6 +29,7 @@
|
||||
#include "lpc43xx_cpp.hpp"
|
||||
using namespace lpc43xx;
|
||||
|
||||
#include "audio.hpp"
|
||||
#include "portapack.hpp"
|
||||
using portapack::receiver_model;
|
||||
using namespace portapack;
|
||||
@@ -240,12 +241,14 @@ void SetPlayDeadView::focus() {
|
||||
SetUIView::SetUIView(NavigationView& nav) {
|
||||
add_children({
|
||||
//&checkbox_login,
|
||||
&checkbox_speaker,
|
||||
&checkbox_bloff,
|
||||
&options_bloff,
|
||||
&checkbox_showsplash,
|
||||
&button_ok
|
||||
});
|
||||
|
||||
checkbox_speaker.set_value(persistent_memory::config_speaker());
|
||||
checkbox_showsplash.set_value(persistent_memory::config_splash());
|
||||
//checkbox_login.set_value(persistent_memory::config_login());
|
||||
|
||||
@@ -258,6 +261,15 @@ SetUIView::SetUIView(NavigationView& nav) {
|
||||
options_bloff.set_selected_index(0);
|
||||
}
|
||||
|
||||
checkbox_speaker.on_select = [this](Checkbox&, bool v) {
|
||||
if (v) audio::output::speaker_mute(); //Just mute audio if speaker is disabled
|
||||
|
||||
persistent_memory::set_config_speaker(v); //Store Speaker status
|
||||
|
||||
StatusRefreshMessage message { }; //Refresh status bar with/out speaker
|
||||
EventDispatcher::send_message(message);
|
||||
};
|
||||
|
||||
button_ok.on_select = [&nav, this](Button&) {
|
||||
if (checkbox_bloff.value())
|
||||
persistent_memory::set_config_backlight_timer(options_bloff.selected_index() + 1);
|
||||
@@ -473,14 +485,14 @@ void ModInfoView::focus() {
|
||||
|
||||
SettingsMenuView::SettingsMenuView(NavigationView& nav) {
|
||||
add_items({
|
||||
//{ "..", ui::Color::light_grey(), &bitmap_icon_previous, [&nav](){ nav.pop(); } },
|
||||
{ "Audio", ui::Color::dark_cyan(), &bitmap_icon_speaker, [&nav](){ nav.push<SetAudioView>(); } },
|
||||
{ "Radio", ui::Color::dark_cyan(), nullptr, [&nav](){ nav.push<SetRadioView>(); } },
|
||||
{ "UI", ui::Color::dark_cyan(), nullptr, [&nav](){ nav.push<SetUIView>(); } },
|
||||
//{ "SD card modules", ui::Color::dark_cyan(), [&nav](){ nav.push<ModInfoView>(); } },
|
||||
{ "Date/Time", ui::Color::dark_cyan(), nullptr, [&nav](){ nav.push<SetDateTimeView>(); } },
|
||||
{ "Touch screen", ui::Color::dark_cyan(), nullptr, [&nav](){ nav.push<TouchCalibrationView>(); } },
|
||||
//{ "Play dead", ui::Color::dark_cyan(), &bitmap_icon_playdead, [&nav](){ nav.push<SetPlayDeadView>(); } }
|
||||
//{ "..", ui::Color::light_grey(), &bitmap_icon_previous, [&nav](){ nav.pop(); } },
|
||||
{ "Audio", ui::Color::dark_cyan(), &bitmap_icon_speaker, [&nav](){ nav.push<SetAudioView>(); } },
|
||||
{ "Radio", ui::Color::dark_cyan(), &bitmap_icon_options_radio, [&nav](){ nav.push<SetRadioView>(); } },
|
||||
{ "Interface", ui::Color::dark_cyan(), &bitmap_icon_options_ui, [&nav](){ nav.push<SetUIView>(); } },
|
||||
//{ "SD card modules", ui::Color::dark_cyan(), [&nav](){ nav.push<ModInfoView>(); } },
|
||||
{ "Date/Time", ui::Color::dark_cyan(), &bitmap_icon_options_datetime, [&nav](){ nav.push<SetDateTimeView>(); } },
|
||||
{ "Touchscreen", ui::Color::dark_cyan(), &bitmap_icon_options_touch, [&nav](){ nav.push<TouchCalibrationView>(); } },
|
||||
//{ "Play dead", ui::Color::dark_cyan(), &bitmap_icon_playdead, [&nav](){ nav.push<SetPlayDeadView>(); } }
|
||||
});
|
||||
set_max_rows(2); // allow wider buttons
|
||||
}
|
||||
|
||||
@@ -200,6 +200,11 @@ private:
|
||||
"Login with play dead"
|
||||
};*/
|
||||
|
||||
Checkbox checkbox_speaker {
|
||||
{ 3 * 8, 2 * 16 },
|
||||
20,
|
||||
"Hide H1 Speaker option"
|
||||
};
|
||||
Checkbox checkbox_bloff {
|
||||
{ 3 * 8, 5 * 16 },
|
||||
20,
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
using portapack::clock_manager;
|
||||
|
||||
#include "portapack_hal.hpp"
|
||||
#include "portapack_persistent_memory.hpp"
|
||||
|
||||
#include "i2s.hpp"
|
||||
using namespace lpc43xx;
|
||||
@@ -153,6 +154,16 @@ void unmute() {
|
||||
audio_codec->headphone_enable();
|
||||
}
|
||||
|
||||
void speaker_mute() {
|
||||
i2s::i2s0::tx_mute();
|
||||
audio_codec->speaker_disable();
|
||||
}
|
||||
|
||||
void speaker_unmute() {
|
||||
i2s::i2s0::tx_unmute();
|
||||
audio_codec->speaker_enable();
|
||||
}
|
||||
|
||||
} /* namespace output */
|
||||
|
||||
namespace input {
|
||||
|
||||
@@ -41,6 +41,9 @@ public:
|
||||
virtual bool reset() = 0;
|
||||
virtual void init() = 0;
|
||||
|
||||
virtual void speaker_enable() = 0;
|
||||
virtual void speaker_disable() = 0;
|
||||
|
||||
virtual void headphone_enable() = 0;
|
||||
virtual void headphone_disable() = 0;
|
||||
virtual volume_range_t headphone_gain_range() const = 0;
|
||||
@@ -62,6 +65,9 @@ void stop();
|
||||
void mute();
|
||||
void unmute();
|
||||
|
||||
void speaker_mute();
|
||||
void speaker_unmute();
|
||||
|
||||
} /* namespace output */
|
||||
|
||||
namespace input {
|
||||
@@ -79,6 +85,14 @@ void set_volume(const volume_t volume);
|
||||
|
||||
} /* namespace headphone */
|
||||
|
||||
namespace speaker {
|
||||
|
||||
volume_range_t volume_range();
|
||||
|
||||
void set_volume(const volume_t volume);
|
||||
|
||||
} /* namespace speaker */
|
||||
|
||||
namespace debug {
|
||||
|
||||
size_t reg_count();
|
||||
|
||||
@@ -185,6 +185,28 @@ static constexpr Bitmap bitmap_icon_aprs {
|
||||
{ 16, 16 }, bitmap_icon_aprs_data
|
||||
};
|
||||
|
||||
static constexpr uint8_t bitmap_icon_back_data[] = {
|
||||
0x00, 0x00,
|
||||
0x30, 0x00,
|
||||
0x38, 0x00,
|
||||
0x1C, 0x00,
|
||||
0x0E, 0x00,
|
||||
0xFF, 0x3F,
|
||||
0xFF, 0x7F,
|
||||
0x0E, 0xE0,
|
||||
0x1C, 0xC0,
|
||||
0x38, 0xC0,
|
||||
0x30, 0xC0,
|
||||
0x00, 0xE0,
|
||||
0x00, 0x7F,
|
||||
0x00, 0x3F,
|
||||
0x00, 0x00,
|
||||
0x00, 0x00,
|
||||
};
|
||||
static constexpr Bitmap bitmap_icon_back {
|
||||
{ 16, 16 }, bitmap_icon_back_data
|
||||
};
|
||||
|
||||
static constexpr uint8_t bitmap_icon_bht_data[] = {
|
||||
0x00, 0x00,
|
||||
0xE0, 0x07,
|
||||
@@ -405,6 +427,28 @@ static constexpr Bitmap bitmap_icon_codetx {
|
||||
{ 16, 16 }, bitmap_icon_codetx_data
|
||||
};
|
||||
|
||||
static constexpr uint8_t bitmap_icon_controls_data[] = {
|
||||
0x8C, 0x31,
|
||||
0x5A, 0x6B,
|
||||
0xDE, 0x7B,
|
||||
0x8C, 0x31,
|
||||
0x00, 0x00,
|
||||
0x8C, 0x31,
|
||||
0x5A, 0x7B,
|
||||
0xDE, 0x7B,
|
||||
0x8C, 0x31,
|
||||
0x00, 0x00,
|
||||
0x8C, 0x31,
|
||||
0xDA, 0x7B,
|
||||
0xDE, 0x7B,
|
||||
0x8C, 0x31,
|
||||
0x00, 0x00,
|
||||
0x00, 0x00,
|
||||
};
|
||||
static constexpr Bitmap bitmap_icon_controls {
|
||||
{ 16, 16 }, bitmap_icon_controls_data
|
||||
};
|
||||
|
||||
static constexpr uint8_t bitmap_icon_cwgen_data[] = {
|
||||
0x18, 0x00,
|
||||
0x24, 0x00,
|
||||
@@ -449,6 +493,28 @@ static constexpr Bitmap bitmap_icon_debug {
|
||||
{ 16, 16 }, bitmap_icon_debug_data
|
||||
};
|
||||
|
||||
static constexpr uint8_t bitmap_icon_delete_data[] = {
|
||||
0x00, 0x00,
|
||||
0x00, 0x00,
|
||||
0x0C, 0x30,
|
||||
0x1C, 0x38,
|
||||
0x38, 0x1C,
|
||||
0x70, 0x0E,
|
||||
0xE0, 0x07,
|
||||
0xC0, 0x03,
|
||||
0xC0, 0x03,
|
||||
0xE0, 0x07,
|
||||
0x70, 0x0E,
|
||||
0x38, 0x1C,
|
||||
0x1C, 0x38,
|
||||
0x0C, 0x30,
|
||||
0x00, 0x00,
|
||||
0x00, 0x00,
|
||||
};
|
||||
static constexpr Bitmap bitmap_icon_delete {
|
||||
{ 16, 16 }, bitmap_icon_delete_data
|
||||
};
|
||||
|
||||
static constexpr uint8_t bitmap_icon_dir_data[] = {
|
||||
0x00, 0x00,
|
||||
0x3E, 0x00,
|
||||
@@ -582,27 +648,49 @@ static constexpr Bitmap bitmap_icon_file_iq {
|
||||
};
|
||||
|
||||
static constexpr uint8_t bitmap_icon_file_text_data[] = {
|
||||
0x00, 0x20,
|
||||
0x00, 0x30,
|
||||
0x00, 0x38,
|
||||
0x00, 0x38,
|
||||
0x00, 0x34,
|
||||
0x00, 0x32,
|
||||
0x00, 0x31,
|
||||
0x80, 0x30,
|
||||
0xC0, 0x30,
|
||||
0xE0, 0x3F,
|
||||
0x30, 0x30,
|
||||
0x18, 0x30,
|
||||
0x0C, 0x30,
|
||||
0x0E, 0x78,
|
||||
0x1F, 0xFC,
|
||||
0x00, 0x00,
|
||||
0xFC, 0x03,
|
||||
0x04, 0x06,
|
||||
0x04, 0x0E,
|
||||
0x04, 0x1E,
|
||||
0xF4, 0x3E,
|
||||
0x04, 0x20,
|
||||
0xF4, 0x2F,
|
||||
0x04, 0x20,
|
||||
0xF4, 0x2F,
|
||||
0x04, 0x20,
|
||||
0xF4, 0x2F,
|
||||
0x04, 0x20,
|
||||
0xF4, 0x2F,
|
||||
0x04, 0x20,
|
||||
0x04, 0x20,
|
||||
0xFC, 0x3F,
|
||||
};
|
||||
static constexpr Bitmap bitmap_icon_file_text {
|
||||
{ 16, 16 }, bitmap_icon_file_text_data
|
||||
};
|
||||
|
||||
static constexpr uint8_t bitmap_icon_file_wav_data[] = {
|
||||
0xFC, 0x03,
|
||||
0x04, 0x06,
|
||||
0x04, 0x0E,
|
||||
0x04, 0x1E,
|
||||
0x04, 0x3E,
|
||||
0x84, 0x20,
|
||||
0xC4, 0x22,
|
||||
0xF4, 0x20,
|
||||
0xF4, 0x2E,
|
||||
0xF4, 0x20,
|
||||
0xC4, 0x22,
|
||||
0x84, 0x24,
|
||||
0x04, 0x28,
|
||||
0x04, 0x20,
|
||||
0x04, 0x20,
|
||||
0xFC, 0x3F,
|
||||
};
|
||||
static constexpr Bitmap bitmap_icon_file_wav {
|
||||
{ 16, 16 }, bitmap_icon_file_wav_data
|
||||
};
|
||||
|
||||
static constexpr uint8_t bitmap_icon_fox_data[] = {
|
||||
0x18, 0x18,
|
||||
0x28, 0x14,
|
||||
@@ -779,6 +867,28 @@ static constexpr Bitmap bitmap_icon_lge {
|
||||
{ 16, 16 }, bitmap_icon_lge_data
|
||||
};
|
||||
|
||||
static constexpr uint8_t bitmap_icon_load_data[] = {
|
||||
0x00, 0x01,
|
||||
0x80, 0x03,
|
||||
0x40, 0x05,
|
||||
0x00, 0x01,
|
||||
0x0E, 0x01,
|
||||
0x11, 0x01,
|
||||
0x7F, 0x1D,
|
||||
0x01, 0x20,
|
||||
0xF9, 0xFF,
|
||||
0xF9, 0xFF,
|
||||
0xFD, 0x7F,
|
||||
0xFD, 0x7F,
|
||||
0xFF, 0x3F,
|
||||
0xFF, 0x3F,
|
||||
0xFF, 0x1F,
|
||||
0xFF, 0x1F,
|
||||
};
|
||||
static constexpr Bitmap bitmap_icon_load {
|
||||
{ 16, 16 }, bitmap_icon_load_data
|
||||
};
|
||||
|
||||
static constexpr uint8_t bitmap_icon_lora_data[] = {
|
||||
0xC0, 0x03,
|
||||
0x30, 0x0C,
|
||||
@@ -801,6 +911,28 @@ static constexpr Bitmap bitmap_icon_lora {
|
||||
{ 16, 16 }, bitmap_icon_lora_data
|
||||
};
|
||||
|
||||
static constexpr uint8_t bitmap_icon_memory_data[] = {
|
||||
0x54, 0x15,
|
||||
0x54, 0x15,
|
||||
0xFF, 0x7F,
|
||||
0xFC, 0x1F,
|
||||
0xFF, 0x7F,
|
||||
0xCC, 0x19,
|
||||
0xAF, 0x7A,
|
||||
0x6C, 0x1B,
|
||||
0xEF, 0x7B,
|
||||
0xEC, 0x1B,
|
||||
0xFF, 0x7F,
|
||||
0xFC, 0x1F,
|
||||
0xFF, 0x7F,
|
||||
0x54, 0x15,
|
||||
0x54, 0x15,
|
||||
0x00, 0x00,
|
||||
};
|
||||
static constexpr Bitmap bitmap_icon_memory {
|
||||
{ 16, 16 }, bitmap_icon_memory_data
|
||||
};
|
||||
|
||||
static constexpr uint8_t bitmap_icon_microphone_data[] = {
|
||||
0xC0, 0x03,
|
||||
0xE0, 0x07,
|
||||
@@ -847,26 +979,48 @@ static constexpr Bitmap bitmap_icon_modem {
|
||||
|
||||
static constexpr uint8_t bitmap_icon_morse_data[] = {
|
||||
0x00, 0x00,
|
||||
0x18, 0x00,
|
||||
0x18, 0x00,
|
||||
0x18, 0x00,
|
||||
0x0C, 0x00,
|
||||
0x0C, 0x00,
|
||||
0x0C, 0x00,
|
||||
0x0C, 0x1F,
|
||||
0x06, 0x1F,
|
||||
0x06, 0x00,
|
||||
0x66, 0xC0,
|
||||
0x66, 0xC0,
|
||||
0x03, 0x00,
|
||||
0x03, 0x00,
|
||||
0x03, 0x00,
|
||||
0xFE, 0x7F,
|
||||
0xFF, 0xFF,
|
||||
0xBB, 0xD0,
|
||||
0xFF, 0xFF,
|
||||
0xFF, 0xFF,
|
||||
0x0B, 0xE1,
|
||||
0xFF, 0xFF,
|
||||
0xFF, 0xFF,
|
||||
0xEB, 0xD0,
|
||||
0xFF, 0xFF,
|
||||
0xFE, 0x7F,
|
||||
0x70, 0x00,
|
||||
0x30, 0x00,
|
||||
0x10, 0x00,
|
||||
0x00, 0x00,
|
||||
};
|
||||
static constexpr Bitmap bitmap_icon_morse {
|
||||
{ 16, 16 }, bitmap_icon_morse_data
|
||||
};
|
||||
|
||||
static constexpr uint8_t bitmap_icon_new_category_data[] = {
|
||||
0x00, 0x18,
|
||||
0x3E, 0x18,
|
||||
0x41, 0x7E,
|
||||
0xC1, 0x7E,
|
||||
0xFF, 0x18,
|
||||
0xFF, 0xDB,
|
||||
0xFF, 0xC3,
|
||||
0xFF, 0xFF,
|
||||
0xFF, 0xFF,
|
||||
0xFF, 0xFF,
|
||||
0xAF, 0xEA,
|
||||
0x57, 0xF5,
|
||||
0xEF, 0xEF,
|
||||
0xF7, 0xF7,
|
||||
0xEE, 0x6F,
|
||||
0x00, 0x00,
|
||||
};
|
||||
static constexpr Bitmap bitmap_icon_new_category {
|
||||
{ 16, 16 }, bitmap_icon_new_category_data
|
||||
};
|
||||
|
||||
static constexpr uint8_t bitmap_icon_notepad_data[] = {
|
||||
0x0C, 0x00,
|
||||
0x1E, 0x00,
|
||||
@@ -933,6 +1087,138 @@ static constexpr Bitmap bitmap_icon_nuoptix {
|
||||
{ 16, 16 }, bitmap_icon_nuoptix_data
|
||||
};
|
||||
|
||||
static constexpr uint8_t bitmap_icon_options_datetime_data[] = {
|
||||
0x0C, 0x06,
|
||||
0xFF, 0x1F,
|
||||
0x49, 0x12,
|
||||
0x49, 0x12,
|
||||
0xFF, 0x1F,
|
||||
0x49, 0x00,
|
||||
0x49, 0x1C,
|
||||
0x7F, 0x63,
|
||||
0x09, 0x49,
|
||||
0x89, 0x88,
|
||||
0xBE, 0xB8,
|
||||
0x80, 0x80,
|
||||
0x00, 0x41,
|
||||
0x00, 0x63,
|
||||
0x00, 0x1C,
|
||||
0x00, 0x00,
|
||||
};
|
||||
static constexpr Bitmap bitmap_icon_options_datetime {
|
||||
{ 16, 16 }, bitmap_icon_options_datetime_data
|
||||
};
|
||||
|
||||
static constexpr uint8_t bitmap_icon_options_radio_data[] = {
|
||||
0x00, 0x00,
|
||||
0x00, 0x00,
|
||||
0x04, 0x20,
|
||||
0x12, 0x48,
|
||||
0x8A, 0x51,
|
||||
0xCA, 0x53,
|
||||
0xCA, 0x53,
|
||||
0x8A, 0x51,
|
||||
0x12, 0x48,
|
||||
0x84, 0x21,
|
||||
0xC0, 0x03,
|
||||
0x40, 0x02,
|
||||
0x60, 0x06,
|
||||
0x20, 0x04,
|
||||
0x30, 0x0C,
|
||||
0xF0, 0x0F,
|
||||
};
|
||||
static constexpr Bitmap bitmap_icon_options_radio {
|
||||
{ 16, 16 }, bitmap_icon_options_radio_data
|
||||
};
|
||||
|
||||
static constexpr uint8_t bitmap_icon_options_touch_data[] = {
|
||||
0xC7, 0xF1,
|
||||
0x97, 0xF4,
|
||||
0x27, 0xF2,
|
||||
0x8F, 0xF8,
|
||||
0x5F, 0xFD,
|
||||
0x47, 0xFD,
|
||||
0x53, 0xC1,
|
||||
0x4B, 0x9F,
|
||||
0x43, 0xB5,
|
||||
0x6F, 0xA0,
|
||||
0x2F, 0xA0,
|
||||
0x20, 0x20,
|
||||
0x60, 0x20,
|
||||
0x40, 0x10,
|
||||
0xC0, 0x1F,
|
||||
0x00, 0x00,
|
||||
};
|
||||
static constexpr Bitmap bitmap_icon_options_touch {
|
||||
{ 16, 16 }, bitmap_icon_options_touch_data
|
||||
};
|
||||
|
||||
static constexpr uint8_t bitmap_icon_options_ui_data[] = {
|
||||
0xFF, 0x1F,
|
||||
0xFF, 0x13,
|
||||
0xFF, 0x1F,
|
||||
0x01, 0x10,
|
||||
0x01, 0x10,
|
||||
0x01, 0x10,
|
||||
0x01, 0x04,
|
||||
0x01, 0x0C,
|
||||
0x01, 0x1C,
|
||||
0x01, 0x3C,
|
||||
0xFF, 0x7D,
|
||||
0x00, 0xFC,
|
||||
0x00, 0x34,
|
||||
0x00, 0x20,
|
||||
0x00, 0x60,
|
||||
0x00, 0x00,
|
||||
};
|
||||
static constexpr Bitmap bitmap_icon_options_ui {
|
||||
{ 16, 16 }, bitmap_icon_options_ui_data
|
||||
};
|
||||
|
||||
static constexpr uint8_t bitmap_icon_peripherals_data[] = {
|
||||
0x54, 0x01,
|
||||
0x54, 0x01,
|
||||
0xFF, 0x07,
|
||||
0x7C, 0x01,
|
||||
0xBF, 0x07,
|
||||
0xDC, 0x18,
|
||||
0x6F, 0x10,
|
||||
0x2C, 0x21,
|
||||
0xAF, 0x20,
|
||||
0x34, 0x20,
|
||||
0x54, 0x10,
|
||||
0xC0, 0x38,
|
||||
0x00, 0x77,
|
||||
0x00, 0xE0,
|
||||
0x00, 0xC0,
|
||||
0x00, 0x00,
|
||||
};
|
||||
static constexpr Bitmap bitmap_icon_peripherals {
|
||||
{ 16, 16 }, bitmap_icon_peripherals_data
|
||||
};
|
||||
|
||||
static constexpr uint8_t bitmap_icon_peripherals_details_data[] = {
|
||||
0x54, 0x01,
|
||||
0x54, 0x01,
|
||||
0xFF, 0x07,
|
||||
0xFC, 0x01,
|
||||
0x3F, 0x00,
|
||||
0xBC, 0x3F,
|
||||
0xBF, 0x60,
|
||||
0xBC, 0xEE,
|
||||
0xBF, 0x80,
|
||||
0x94, 0xBE,
|
||||
0x94, 0x80,
|
||||
0x80, 0xBE,
|
||||
0x80, 0x80,
|
||||
0x80, 0xBE,
|
||||
0x80, 0x80,
|
||||
0x80, 0xFF,
|
||||
};
|
||||
static constexpr Bitmap bitmap_icon_peripherals_details {
|
||||
{ 16, 16 }, bitmap_icon_peripherals_details_data
|
||||
};
|
||||
|
||||
static constexpr uint8_t bitmap_icon_pocsag_data[] = {
|
||||
0x00, 0x00,
|
||||
0x00, 0x00,
|
||||
@@ -1043,28 +1329,94 @@ static constexpr Bitmap bitmap_icon_remote {
|
||||
{ 16, 16 }, bitmap_icon_remote_data
|
||||
};
|
||||
|
||||
static constexpr uint8_t bitmap_icon_rename_data[] = {
|
||||
0x00, 0x00,
|
||||
0x00, 0x00,
|
||||
0x00, 0x0E,
|
||||
0x00, 0x04,
|
||||
0xFF, 0xF5,
|
||||
0x01, 0x84,
|
||||
0xC9, 0x84,
|
||||
0x55, 0x85,
|
||||
0xDD, 0x84,
|
||||
0x55, 0x85,
|
||||
0xD5, 0x84,
|
||||
0x01, 0x84,
|
||||
0xFF, 0xF5,
|
||||
0x00, 0x04,
|
||||
0x00, 0x0E,
|
||||
0x00, 0x00,
|
||||
};
|
||||
static constexpr Bitmap bitmap_icon_rename {
|
||||
{ 16, 16 }, bitmap_icon_rename_data
|
||||
};
|
||||
|
||||
static constexpr uint8_t bitmap_icon_rename_numeric_data[] = {
|
||||
0x00, 0x00,
|
||||
0x00, 0x00,
|
||||
0x00, 0x0E,
|
||||
0x00, 0x04,
|
||||
0xFF, 0xF5,
|
||||
0x01, 0x84,
|
||||
0xC9, 0x85,
|
||||
0x0D, 0x85,
|
||||
0xC9, 0x85,
|
||||
0x49, 0x84,
|
||||
0xDD, 0x85,
|
||||
0x01, 0x84,
|
||||
0xFF, 0xF5,
|
||||
0x00, 0x04,
|
||||
0x00, 0x0E,
|
||||
0x00, 0x00,
|
||||
};
|
||||
static constexpr Bitmap bitmap_icon_rename_numeric {
|
||||
{ 16, 16 }, bitmap_icon_rename_numeric_data
|
||||
};
|
||||
|
||||
static constexpr uint8_t bitmap_icon_replay_data[] = {
|
||||
0x60, 0x00,
|
||||
0xE0, 0x00,
|
||||
0xE0, 0x01,
|
||||
0xE0, 0x03,
|
||||
0xE0, 0x07,
|
||||
0xE0, 0x0F,
|
||||
0xE0, 0x1F,
|
||||
0xE0, 0x3F,
|
||||
0xE0, 0x3F,
|
||||
0xE0, 0x1F,
|
||||
0xE0, 0x0F,
|
||||
0xE0, 0x07,
|
||||
0xE0, 0x03,
|
||||
0xE0, 0x01,
|
||||
0xE0, 0x00,
|
||||
0x60, 0x00,
|
||||
0x00, 0x00,
|
||||
0x00, 0x00,
|
||||
0x0C, 0x00,
|
||||
0x3C, 0x00,
|
||||
0xFC, 0x00,
|
||||
0xFC, 0x03,
|
||||
0xFC, 0x0F,
|
||||
0xFC, 0x3F,
|
||||
0xFC, 0x3F,
|
||||
0xFC, 0x0F,
|
||||
0xFC, 0x03,
|
||||
0xFC, 0x00,
|
||||
0x3C, 0x00,
|
||||
0x0C, 0x00,
|
||||
0x00, 0x00,
|
||||
0x00, 0x00,
|
||||
};
|
||||
static constexpr Bitmap bitmap_icon_replay {
|
||||
{ 16, 16 }, bitmap_icon_replay_data
|
||||
};
|
||||
|
||||
static constexpr uint8_t bitmap_icon_save_data[] = {
|
||||
0x00, 0x01,
|
||||
0x00, 0x01,
|
||||
0x00, 0x01,
|
||||
0x00, 0x01,
|
||||
0x4E, 0x05,
|
||||
0x91, 0x03,
|
||||
0x3F, 0x19,
|
||||
0x01, 0x20,
|
||||
0xF9, 0xFF,
|
||||
0xF9, 0xFF,
|
||||
0xFD, 0x7F,
|
||||
0xFD, 0x7F,
|
||||
0xFF, 0x3F,
|
||||
0xFF, 0x3F,
|
||||
0xFF, 0x1F,
|
||||
0xFF, 0x1F,
|
||||
};
|
||||
static constexpr Bitmap bitmap_icon_save {
|
||||
{ 16, 16 }, bitmap_icon_save_data
|
||||
};
|
||||
|
||||
static constexpr uint8_t bitmap_icon_scanner_data[] = {
|
||||
0x03, 0x00,
|
||||
0x00, 0x00,
|
||||
@@ -1131,6 +1483,28 @@ static constexpr Bitmap bitmap_icon_sd {
|
||||
{ 16, 16 }, bitmap_icon_sd_data
|
||||
};
|
||||
|
||||
static constexpr uint8_t bitmap_icon_sdcard_data[] = {
|
||||
0xF0, 0x3F,
|
||||
0x58, 0x35,
|
||||
0x5C, 0x35,
|
||||
0xFC, 0x3F,
|
||||
0xFC, 0x3F,
|
||||
0xFC, 0x3F,
|
||||
0xFC, 0x3F,
|
||||
0xFC, 0x3F,
|
||||
0xFC, 0x3F,
|
||||
0xAC, 0x3A,
|
||||
0x5C, 0x35,
|
||||
0xAC, 0x3A,
|
||||
0x5C, 0x35,
|
||||
0xAC, 0x3A,
|
||||
0x5C, 0x35,
|
||||
0xAC, 0x3A,
|
||||
};
|
||||
static constexpr Bitmap bitmap_icon_sdcard {
|
||||
{ 16, 16 }, bitmap_icon_sdcard_data
|
||||
};
|
||||
|
||||
static constexpr uint8_t bitmap_icon_search_data[] = {
|
||||
0xF8, 0x01,
|
||||
0xFC, 0x03,
|
||||
@@ -1220,22 +1594,22 @@ static constexpr Bitmap bitmap_icon_sonde {
|
||||
};
|
||||
|
||||
static constexpr uint8_t bitmap_icon_soundboard_data[] = {
|
||||
0xFF, 0xAA,
|
||||
0x81, 0x00,
|
||||
0xA1, 0x42,
|
||||
0xB1, 0x20,
|
||||
0xBD, 0x52,
|
||||
0xBD, 0x28,
|
||||
0xBD, 0x52,
|
||||
0xB1, 0x20,
|
||||
0xA1, 0x42,
|
||||
0x81, 0x00,
|
||||
0xFF, 0xAA,
|
||||
0x00, 0x00,
|
||||
0xAA, 0xAA,
|
||||
0x01, 0x00,
|
||||
0xA0, 0x42,
|
||||
0x11, 0x20,
|
||||
0xF0, 0x0F,
|
||||
0x1C, 0x18,
|
||||
0x17, 0x38,
|
||||
0x15, 0x78,
|
||||
0x15, 0xF8,
|
||||
0x15, 0x82,
|
||||
0x15, 0x8B,
|
||||
0xD5, 0x83,
|
||||
0xD5, 0xBB,
|
||||
0xD5, 0x83,
|
||||
0x15, 0x8B,
|
||||
0x15, 0x92,
|
||||
0x15, 0xA0,
|
||||
0x17, 0x80,
|
||||
0x1C, 0x80,
|
||||
0xF0, 0xFF,
|
||||
};
|
||||
static constexpr Bitmap bitmap_icon_soundboard {
|
||||
{ 16, 16 }, bitmap_icon_soundboard_data
|
||||
@@ -1243,26 +1617,48 @@ static constexpr Bitmap bitmap_icon_soundboard {
|
||||
|
||||
static constexpr uint8_t bitmap_icon_speaker_data[] = {
|
||||
0x00, 0x00,
|
||||
0x00, 0x20,
|
||||
0x00, 0x30,
|
||||
0x00, 0x38,
|
||||
0x00, 0x3C,
|
||||
0xDC, 0x3E,
|
||||
0xDC, 0x3F,
|
||||
0xDC, 0x3F,
|
||||
0xDC, 0x3F,
|
||||
0xDC, 0x3F,
|
||||
0xDC, 0x3E,
|
||||
0x00, 0x3C,
|
||||
0x00, 0x38,
|
||||
0x00, 0x30,
|
||||
0x00, 0x20,
|
||||
0x00, 0x00,
|
||||
0x40, 0x10,
|
||||
0x60, 0x20,
|
||||
0x70, 0x44,
|
||||
0x78, 0x48,
|
||||
0x7F, 0x91,
|
||||
0x7F, 0x92,
|
||||
0x7F, 0x92,
|
||||
0x7F, 0x92,
|
||||
0x7F, 0x92,
|
||||
0x7F, 0x92,
|
||||
0x7F, 0x91,
|
||||
0x78, 0x48,
|
||||
0x70, 0x44,
|
||||
0x60, 0x20,
|
||||
0x40, 0x10,
|
||||
};
|
||||
static constexpr Bitmap bitmap_icon_speaker {
|
||||
{ 16, 16 }, bitmap_icon_speaker_data
|
||||
};
|
||||
|
||||
static constexpr uint8_t bitmap_icon_speaker_mute_data[] = {
|
||||
0x00, 0x00,
|
||||
0x40, 0x00,
|
||||
0x60, 0x00,
|
||||
0x70, 0x00,
|
||||
0x78, 0x00,
|
||||
0x7F, 0x22,
|
||||
0x7F, 0x36,
|
||||
0x7F, 0x1C,
|
||||
0x7F, 0x08,
|
||||
0x7F, 0x1C,
|
||||
0x7F, 0x36,
|
||||
0x7F, 0x22,
|
||||
0x78, 0x00,
|
||||
0x70, 0x00,
|
||||
0x60, 0x00,
|
||||
0x40, 0x00,
|
||||
};
|
||||
static constexpr Bitmap bitmap_icon_speaker_mute {
|
||||
{ 16, 16 }, bitmap_icon_speaker_mute_data
|
||||
};
|
||||
|
||||
static constexpr uint8_t bitmap_icon_sstv_data[] = {
|
||||
0x00, 0x00,
|
||||
0x00, 0x00,
|
||||
@@ -1307,6 +1703,28 @@ static constexpr Bitmap bitmap_icon_stealth {
|
||||
{ 16, 16 }, bitmap_icon_stealth_data
|
||||
};
|
||||
|
||||
static constexpr uint8_t bitmap_icon_temperature_data[] = {
|
||||
0x00, 0x01,
|
||||
0x80, 0x01,
|
||||
0x80, 0x05,
|
||||
0xC0, 0x0D,
|
||||
0x40, 0x0D,
|
||||
0xD0, 0x1F,
|
||||
0x70, 0x15,
|
||||
0xB0, 0x1A,
|
||||
0x58, 0x35,
|
||||
0xB8, 0x3A,
|
||||
0x58, 0x34,
|
||||
0x28, 0x28,
|
||||
0x18, 0x30,
|
||||
0x30, 0x18,
|
||||
0x60, 0x0C,
|
||||
0xC0, 0x07,
|
||||
};
|
||||
static constexpr Bitmap bitmap_icon_temperature {
|
||||
{ 16, 16 }, bitmap_icon_temperature_data
|
||||
};
|
||||
|
||||
static constexpr uint8_t bitmap_icon_tetra_data[] = {
|
||||
0xE0, 0x0F,
|
||||
0x18, 0x38,
|
||||
@@ -1329,6 +1747,50 @@ static constexpr Bitmap bitmap_icon_tetra {
|
||||
{ 16, 16 }, bitmap_icon_tetra_data
|
||||
};
|
||||
|
||||
static constexpr uint8_t bitmap_icon_tools_antenna_data[] = {
|
||||
0x38, 0x3E,
|
||||
0x10, 0x22,
|
||||
0x10, 0x26,
|
||||
0x10, 0x22,
|
||||
0x10, 0x2E,
|
||||
0x10, 0x22,
|
||||
0x10, 0x26,
|
||||
0x10, 0x22,
|
||||
0x38, 0x2E,
|
||||
0x38, 0x22,
|
||||
0x38, 0x26,
|
||||
0x38, 0x22,
|
||||
0x38, 0x2E,
|
||||
0x38, 0x22,
|
||||
0x38, 0x3E,
|
||||
0x00, 0x00,
|
||||
};
|
||||
static constexpr Bitmap bitmap_icon_tools_antenna {
|
||||
{ 16, 16 }, bitmap_icon_tools_antenna_data
|
||||
};
|
||||
|
||||
static constexpr uint8_t bitmap_icon_tools_wipesd_data[] = {
|
||||
0xF0, 0x3F,
|
||||
0x58, 0x35,
|
||||
0x5C, 0x35,
|
||||
0xFC, 0x3F,
|
||||
0xFC, 0x3F,
|
||||
0xFC, 0x3F,
|
||||
0x3C, 0x1C,
|
||||
0xBC, 0xC9,
|
||||
0xBC, 0xE3,
|
||||
0x2C, 0x77,
|
||||
0x5C, 0x3E,
|
||||
0xAC, 0x1C,
|
||||
0x5C, 0x3E,
|
||||
0x2C, 0x77,
|
||||
0x9C, 0xE3,
|
||||
0xAC, 0xC1,
|
||||
};
|
||||
static constexpr Bitmap bitmap_icon_tools_wipesd {
|
||||
{ 16, 16 }, bitmap_icon_tools_wipesd_data
|
||||
};
|
||||
|
||||
static constexpr uint8_t bitmap_icon_tpms_data[] = {
|
||||
0xC0, 0x03,
|
||||
0xF0, 0x0F,
|
||||
|
||||
@@ -93,6 +93,15 @@ bool get_antenna_bias() {
|
||||
return antenna_bias;
|
||||
}
|
||||
|
||||
bool speaker_mode { false };
|
||||
void set_speaker_mode(const bool v) {
|
||||
speaker_mode = v;
|
||||
if (speaker_mode)
|
||||
audio::output::speaker_unmute();
|
||||
else
|
||||
audio::output::speaker_mute();
|
||||
}
|
||||
|
||||
static constexpr uint32_t systick_count(const uint32_t clock_source_f) {
|
||||
return clock_source_f / CH_FREQUENCY;
|
||||
}
|
||||
|
||||
@@ -51,6 +51,9 @@ extern ClockManager clock_manager;
|
||||
extern ReceiverModel receiver_model;
|
||||
extern TransmitterModel transmitter_model;
|
||||
|
||||
extern bool speaker_mode;
|
||||
void set_speaker_mode(const bool v);
|
||||
|
||||
extern uint8_t bl_tick_counter;
|
||||
extern bool antenna_bias;
|
||||
|
||||
|
||||
@@ -106,6 +106,7 @@ SystemStatusView::SystemStatusView(
|
||||
&backdrop,
|
||||
&button_back,
|
||||
&title,
|
||||
&button_speaker,
|
||||
&button_stealth,
|
||||
//&button_textentry,
|
||||
&button_camera,
|
||||
@@ -115,6 +116,11 @@ SystemStatusView::SystemStatusView(
|
||||
&sd_card_status_view,
|
||||
});
|
||||
|
||||
if (portapack::persistent_memory::config_speaker())
|
||||
button_speaker.hidden(false);
|
||||
else
|
||||
button_speaker.hidden(true);
|
||||
|
||||
button_back.id = -1; // Special ID used by FocusManager
|
||||
title.set_style(&style_systemstatus);
|
||||
|
||||
@@ -133,6 +139,10 @@ SystemStatusView::SystemStatusView(
|
||||
this->on_back();
|
||||
};
|
||||
|
||||
button_speaker.on_select = [this](ImageButton&) {
|
||||
this->on_speaker();
|
||||
};
|
||||
|
||||
button_stealth.on_select = [this](ImageButton&) {
|
||||
this->on_stealth();
|
||||
};
|
||||
@@ -156,6 +166,14 @@ SystemStatusView::SystemStatusView(
|
||||
}
|
||||
|
||||
void SystemStatusView::refresh() {
|
||||
if (!portapack::persistent_memory::config_speaker()) {
|
||||
button_speaker.set_foreground(Color::light_grey());
|
||||
button_speaker.set_bitmap(&bitmap_icon_speaker_mute);
|
||||
button_speaker.hidden(false);
|
||||
}
|
||||
else {
|
||||
button_speaker.hidden(true);
|
||||
}
|
||||
if (portapack::get_antenna_bias()) {
|
||||
button_bias_tee.set_bitmap(&bitmap_icon_biast_on);
|
||||
button_bias_tee.set_foreground(ui::Color::yellow());
|
||||
@@ -188,6 +206,23 @@ void SystemStatusView::set_title(const std::string new_value) {
|
||||
}
|
||||
}
|
||||
|
||||
void SystemStatusView::on_speaker() {
|
||||
if (!portapack::speaker_mode)
|
||||
{
|
||||
portapack::set_speaker_mode(true);
|
||||
button_speaker.set_foreground(Color::green());
|
||||
button_speaker.set_bitmap(&bitmap_icon_speaker);
|
||||
}
|
||||
else
|
||||
{
|
||||
portapack::set_speaker_mode(false);
|
||||
button_speaker.set_foreground(Color::light_grey());
|
||||
button_speaker.set_bitmap(&bitmap_icon_speaker_mute);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
void SystemStatusView::on_stealth() {
|
||||
bool mode = not portapack::persistent_memory::stealth_mode();
|
||||
|
||||
@@ -198,7 +233,7 @@ void SystemStatusView::on_stealth() {
|
||||
|
||||
void SystemStatusView::on_bias_tee() {
|
||||
if (!portapack::antenna_bias) {
|
||||
nav_.display_modal("Bias voltage", "Enable DC voltage on\nantenna connector ?", YESNO, [this](bool v) {
|
||||
nav_.display_modal("Bias voltage", "Enable DC voltage on\nantenna connector?", YESNO, [this](bool v) {
|
||||
if (v) {
|
||||
portapack::set_antenna_bias(true);
|
||||
//radio::set_antenna_bias(true);
|
||||
@@ -402,15 +437,15 @@ TransmittersMenuView::TransmittersMenuView(NavigationView& nav) {
|
||||
UtilitiesMenuView::UtilitiesMenuView(NavigationView& nav) {
|
||||
add_items({
|
||||
//{ "Test app", ui::Color::dark_grey(), nullptr, [&nav](){ nav.push<TestView>(); } },
|
||||
//{ "..", ui::Color::light_grey(),&bitmap_icon_previous, [&nav](){ nav.pop(); } },
|
||||
{ "Freq manager", ui::Color::green(), &bitmap_icon_freqman, [&nav](){ nav.push<FrequencyManagerView>(); } },
|
||||
{ "File manager", ui::Color::yellow(), &bitmap_icon_file, [&nav](){ nav.push<FileManagerView>(); } },
|
||||
//{ "Notepad", ui::Color::dark_grey(), &bitmap_icon_notepad, [&nav](){ nav.push<NotImplementedView>(); } },
|
||||
{ "Signal gen", ui::Color::green(), &bitmap_icon_cwgen, [&nav](){ nav.push<SigGenView>(); } },
|
||||
//{ "Tone search", ui::Color::dark_grey(), nullptr, [&nav](){ nav.push<ToneSearchView>(); } },
|
||||
{ "Wave viewer", ui::Color::blue(), nullptr, [&nav](){ nav.push<ViewWavView>(); } },
|
||||
{ "Antenna length", ui::Color::yellow(), nullptr, [&nav](){ nav.push<WhipCalcView>(); } },
|
||||
{ "Wipe SD card", ui::Color::red(), nullptr, [&nav](){ nav.push<WipeSDView>(); } },
|
||||
//{ "..", ui::Color::light_grey(),&bitmap_icon_previous, [&nav](){ nav.pop(); } },
|
||||
{ "Freq manager", ui::Color::green(), &bitmap_icon_freqman, [&nav](){ nav.push<FrequencyManagerView>(); } },
|
||||
{ "File manager", ui::Color::yellow(), &bitmap_icon_dir, [&nav](){ nav.push<FileManagerView>(); } },
|
||||
//{ "Notepad", ui::Color::dark_grey(), &bitmap_icon_notepad, [&nav](){ nav.push<NotImplementedView>(); } },
|
||||
{ "Signal gen", ui::Color::green(), &bitmap_icon_cwgen, [&nav](){ nav.push<SigGenView>(); } },
|
||||
//{ "Tone search", ui::Color::dark_grey(), nullptr, [&nav](){ nav.push<ToneSearchView>(); } },
|
||||
{ "Wave viewer", ui::Color::yellow(), &bitmap_icon_soundboard, [&nav](){ nav.push<ViewWavView>(); } },
|
||||
{ "Antenna length", ui::Color::green(), &bitmap_icon_tools_antenna, [&nav](){ nav.push<WhipCalcView>(); } },
|
||||
{ "Wipe SD card", ui::Color::red(), &bitmap_icon_tools_wipesd, [&nav](){ nav.push<WipeSDView>(); } },
|
||||
});
|
||||
set_max_rows(2); // allow wider buttons
|
||||
}
|
||||
@@ -418,7 +453,7 @@ UtilitiesMenuView::UtilitiesMenuView(NavigationView& nav) {
|
||||
/* SystemMenuView ********************************************************/
|
||||
|
||||
void SystemMenuView::hackrf_mode(NavigationView& nav) {
|
||||
nav.push<ModalMessageView>("HackRF mode", "This mode enables the USB\nfunctionality. Reset the\ndevice to get back.\n\nDo you want to Switch now?", YESNO,
|
||||
nav.push<ModalMessageView>("HackRF mode", " This mode enables HackRF\n functionality. To return,\n press the reset button.\n\n Switch to HackRF mode?", YESNO,
|
||||
[this](bool choice) {
|
||||
if (choice) {
|
||||
EventDispatcher::request_stop();
|
||||
|
||||
@@ -126,9 +126,16 @@ private:
|
||||
};
|
||||
|
||||
Text title {
|
||||
{ 20, 0, 16 * 8, 1 * 16 },
|
||||
{ 20, 0, 14 * 8, 1 * 16 },
|
||||
default_title,
|
||||
};
|
||||
|
||||
ImageButton button_speaker {
|
||||
{ 17 * 8, 0, 2 * 8, 1 * 16 },
|
||||
&bitmap_icon_speaker_mute,
|
||||
Color::light_grey(),
|
||||
Color::dark_grey()
|
||||
};
|
||||
|
||||
ImageButton button_stealth {
|
||||
{ 19 * 8, 0, 2 * 8, 1 * 16 },
|
||||
@@ -176,6 +183,7 @@ private:
|
||||
{ 28 * 8, 0 * 16, 2 * 8, 1 * 16 }
|
||||
};
|
||||
|
||||
void on_speaker();
|
||||
void on_stealth();
|
||||
void on_bias_tee();
|
||||
//void on_textentry();
|
||||
|
||||
@@ -218,10 +218,17 @@ void set_playdead_sequence(const uint32_t new_value) {
|
||||
data->playdead_magic = playdead_magic;
|
||||
}
|
||||
|
||||
bool config_speaker() {
|
||||
return (data->ui_config & 0x10000000UL) ? false : true; // Default true
|
||||
}
|
||||
bool stealth_mode() {
|
||||
return (data->ui_config & 0x20000000UL) ? true : false;
|
||||
}
|
||||
|
||||
void set_config_speaker(bool new_value) {
|
||||
data->ui_config = (data->ui_config & ~0x10000000UL) | (!new_value << 28);
|
||||
}
|
||||
|
||||
void set_stealth_mode(const bool v) {
|
||||
data->ui_config = (data->ui_config & ~0x20000000UL) | (v << 29);
|
||||
}
|
||||
|
||||
@@ -76,10 +76,12 @@ void set_stealth_mode(const bool v);
|
||||
|
||||
bool config_splash();
|
||||
bool config_login();
|
||||
bool config_speaker();
|
||||
uint32_t config_backlight_timer();
|
||||
|
||||
void set_config_splash(bool v);
|
||||
void set_config_login(bool v);
|
||||
void set_config_speaker(bool new_value);
|
||||
void set_config_backlight_timer(uint32_t i);
|
||||
|
||||
//uint8_t ui_config_textentry();
|
||||
|
||||
@@ -341,6 +341,10 @@ public:
|
||||
headphone_mute();
|
||||
}
|
||||
|
||||
void speaker_enable() {};
|
||||
void speaker_disable() {};
|
||||
|
||||
|
||||
void microphone_enable() override {
|
||||
// TODO: Implement
|
||||
}
|
||||
|
||||
|
After Width: | Height: | Size: 168 B |
|
After Width: | Height: | Size: 144 B |
|
After Width: | Height: | Size: 153 B |
|
Before Width: | Height: | Size: 143 B After Width: | Height: | Size: 156 B |
|
After Width: | Height: | Size: 168 B |
|
After Width: | Height: | Size: 174 B |
|
After Width: | Height: | Size: 168 B |
|
Before Width: | Height: | Size: 117 B After Width: | Height: | Size: 159 B |
|
After Width: | Height: | Size: 186 B |
|
After Width: | Height: | Size: 186 B |
|
After Width: | Height: | Size: 183 B |
|
After Width: | Height: | Size: 207 B |
|
After Width: | Height: | Size: 168 B |
|
After Width: | Height: | Size: 198 B |
|
After Width: | Height: | Size: 174 B |
|
After Width: | Height: | Size: 171 B |
|
After Width: | Height: | Size: 171 B |
|
Before Width: | Height: | Size: 149 B After Width: | Height: | Size: 116 B |
|
After Width: | Height: | Size: 171 B |
|
After Width: | Height: | Size: 132 B |
|
Before Width: | Height: | Size: 183 B After Width: | Height: | Size: 183 B |
|
Before Width: | Height: | Size: 121 B After Width: | Height: | Size: 165 B |
|
After Width: | Height: | Size: 162 B |
|
After Width: | Height: | Size: 189 B |
|
After Width: | Height: | Size: 153 B |
|
After Width: | Height: | Size: 192 B |