mirror of
https://github.com/portapack-mayhem/mayhem-firmware.git
synced 2026-09-04 22:09:03 +00:00
Compare commits
10 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| e7359563c6 | |||
| 03ca87b13e | |||
| b2da21b88a | |||
| bb1b703dc1 | |||
| 990f63e5de | |||
| 6fe8ab4f99 | |||
| d6ed12191d | |||
| 8b159f447a | |||
| e9c32504d1 | |||
| 004799e1a3 |
@@ -1,6 +1,7 @@
|
||||
name: Bug report
|
||||
description: File a bug reports regarding the firmware.
|
||||
labels: ['bug']
|
||||
labels:
|
||||
- bug
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
name: Feature Request
|
||||
description: For feature requests regarding the firmware.
|
||||
labels: ['feature request']
|
||||
labels:
|
||||
- enhancement
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
|
||||
@@ -1,44 +0,0 @@
|
||||
---
|
||||
name: Problem upgrading the firmware or booting
|
||||
about: If you are having firmware upgrade or booting problems
|
||||
title: ''
|
||||
labels: 'firmware'
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
----
|
||||
Before creating this issue, **do the following**:
|
||||
* Read the Wiki on booting: https://github.com/portapack-mayhem/mayhem-firmware/wiki/Won't-boot
|
||||
* Read: https://github.com/portapack-mayhem/mayhem-firmware/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/portapack-mayhem/mayhem-firmware/wiki/PortaPack-Versions
|
||||
|
||||
**Affected versions**
|
||||
Please tell us what version you are running.
|
||||
If your device is still functional, try the latest nightly release before submitting this.
|
||||
You can find the latest nightly version here https://github.com/portapack-mayhem/mayhem-firmware/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.
|
||||
|
||||
**Can you try the upgrade with a different PC/Portapack/HackRF?**
|
||||
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**
|
||||
If the issue is difficult to explain, additionally to the text please include images and videos.
|
||||
@@ -0,0 +1,45 @@
|
||||
name: Firmware/boot issue
|
||||
description: If you are having firmware upgrade or booting problems.
|
||||
labels:
|
||||
- firmware
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: >2-
|
||||
Thank you for taking the time to fill out an issue, this template is meant for any issues related to the Mayhem firmware.
|
||||
Before creating this issue, **do the following**:
|
||||
* Read the Wiki on booting:
|
||||
https://github.com/portapack-mayhem/mayhem-firmware/wiki/Won't-boot
|
||||
|
||||
* Read:
|
||||
https://github.com/portapack-mayhem/mayhem-firmware/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
|
||||
|
||||
* Check hardware versions:
|
||||
https://github.com/portapack-mayhem/mayhem-firmware/wiki/PortaPack-Versions
|
||||
- type: textarea
|
||||
id: problem
|
||||
attributes:
|
||||
label: What happened?
|
||||
description: If after following the above troubleshooting the problem still remains
|
||||
placeholder: Describe what was is the problem
|
||||
- type: input
|
||||
id: hardware
|
||||
attributes:
|
||||
label: Your hardware
|
||||
description: Check the link with the versions above
|
||||
placeholder: Which device you have?
|
||||
- type: checkboxes
|
||||
id: firmware_update_before
|
||||
attributes:
|
||||
label: Tests
|
||||
description: >-
|
||||
Things might be confusing the first time, please check the documentation
|
||||
above
|
||||
options:
|
||||
- label: I managed to update/boot previously
|
||||
required: false
|
||||
@@ -51,6 +51,7 @@
|
||||
.dep/
|
||||
/build*
|
||||
CMakeFiles/
|
||||
cmake-build-debug/
|
||||
|
||||
# Debugging
|
||||
.gdbinit*
|
||||
|
||||
Vendored
+148
@@ -0,0 +1,148 @@
|
||||
{
|
||||
// Use IntelliSense to learn about possible attributes.
|
||||
// Hover to view descriptions of existing attributes.
|
||||
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
{
|
||||
"name": "(gdb) JTAG probe",
|
||||
"type": "cppdbg",
|
||||
"request": "launch",
|
||||
"miDebuggerPath": "arm-none-eabi-gdb",
|
||||
"targetArchitecture": "arm",
|
||||
"program": "${workspaceRoot}/build/firmware/baseband/baseband_adsbrx.elf",
|
||||
"cwd": "${workspaceRoot}",
|
||||
"setupCommands": [
|
||||
// use logging for troubleshooting
|
||||
//{"text": "set logging file ${workspaceRoot}/build/arm-none-eabi-gdb.log"},
|
||||
//{"text": "set logging on"},
|
||||
{
|
||||
"text": "file '${workspaceRoot}/build/firmware/baseband/baseband_adsbrx.elf'"
|
||||
},
|
||||
{
|
||||
"text": "target extended-remote /dev/ttyACM0"
|
||||
},
|
||||
{
|
||||
"text": "monitor swdp_scan"
|
||||
},
|
||||
{
|
||||
"text": "attach 1"
|
||||
},
|
||||
],
|
||||
"launchCompleteCommand": "None",
|
||||
"externalConsole": false,
|
||||
},
|
||||
{
|
||||
"name": "(gdb) OpenOCD m4 baseband",
|
||||
"type": "cppdbg",
|
||||
"request": "launch",
|
||||
"program": "${workspaceRoot}/build/firmware/baseband/baseband_sd_over_usb.elf",
|
||||
"args": [],
|
||||
"cwd": "${workspaceRoot}",
|
||||
// "environment": [
|
||||
// {
|
||||
// "name": "PATH",
|
||||
// "value": "${env:PATH}"
|
||||
// }
|
||||
// ],
|
||||
"externalConsole": false,
|
||||
"MIMode": "gdb",
|
||||
"miDebuggerPath": "arm-none-eabi-gdb",
|
||||
"targetArchitecture": "arm",
|
||||
"debugServerPath": "openocd",
|
||||
"debugServerArgs": "-f interface/ftdi/um232h.cfg -f target/lpc4350.cfg -c \"gdb_breakpoint_override hard\"",
|
||||
"serverStarted": "Listening on port [0-9]+ for gdb connections",
|
||||
"filterStderr": true,
|
||||
"filterStdout": false,
|
||||
"launchCompleteCommand": "None",
|
||||
"postRemoteConnectCommands": [
|
||||
{
|
||||
"description": "Target Remote Device on Port 3333",
|
||||
"text": "target extended-remote :3333",
|
||||
"ignoreFailures": false
|
||||
},
|
||||
{
|
||||
"description": "Respect Hardware Limitations",
|
||||
"text": "set remote hardware-watchpoint-limit 2",
|
||||
"ignoreFailures": false
|
||||
},
|
||||
{
|
||||
"description": "Respect Hardware Limitations",
|
||||
"text": "set remote hardware-breakpoint-limit 4",
|
||||
"ignoreFailures": false
|
||||
},
|
||||
{
|
||||
"description": "Shutdown GDB Server on GDB Detach",
|
||||
"text": "monitor [target current] configure -event gdb-detach { shutdown }",
|
||||
"ignoreFailures": false
|
||||
},
|
||||
],
|
||||
"stopAtConnect": false,
|
||||
"logging": {
|
||||
"exceptions": true,
|
||||
"engineLogging": false,
|
||||
"moduleLoad": true,
|
||||
"programOutput": true,
|
||||
"trace": false,
|
||||
"traceResponse": false
|
||||
},
|
||||
"useExtendedRemote": true
|
||||
},
|
||||
{
|
||||
"name": "(gdb) OpenOCD m0 application",
|
||||
"type": "cppdbg",
|
||||
"request": "launch",
|
||||
"program": "${workspaceRoot}/build/firmware/application/application.elf",
|
||||
"args": [],
|
||||
"cwd": "${workspaceRoot}",
|
||||
// "environment": [
|
||||
// {
|
||||
// "name": "PATH",
|
||||
// "value": "${env:PATH}"
|
||||
// }
|
||||
// ],
|
||||
"externalConsole": false,
|
||||
"MIMode": "gdb",
|
||||
"miDebuggerPath": "arm-none-eabi-gdb",
|
||||
"targetArchitecture": "arm",
|
||||
"debugServerPath": "openocd",
|
||||
"debugServerArgs": "-f interface/ftdi/um232h.cfg -f target/lpc4350.cfg -c \"gdb_breakpoint_override hard\"",
|
||||
"serverStarted": "Listening on port [0-9]+ for gdb connections",
|
||||
"filterStderr": true,
|
||||
"filterStdout": false,
|
||||
"launchCompleteCommand": "None",
|
||||
"postRemoteConnectCommands": [
|
||||
{
|
||||
"description": "Target Remote Device on Port 3334",
|
||||
"text": "target extended-remote :3334",
|
||||
"ignoreFailures": false
|
||||
},
|
||||
{
|
||||
"description": "Respect Hardware Limitations",
|
||||
"text": "set remote hardware-watchpoint-limit 1",
|
||||
"ignoreFailures": false
|
||||
},
|
||||
{
|
||||
"description": "Respect Hardware Limitations",
|
||||
"text": "set remote hardware-breakpoint-limit 2",
|
||||
"ignoreFailures": false
|
||||
},
|
||||
{
|
||||
"description": "Shutdown GDB Server on GDB Detach",
|
||||
"text": "monitor [target current] configure -event gdb-detach { shutdown }",
|
||||
"ignoreFailures": false
|
||||
},
|
||||
],
|
||||
"stopAtConnect": false,
|
||||
"logging": {
|
||||
"exceptions": true,
|
||||
"engineLogging": false,
|
||||
"moduleLoad": true,
|
||||
"programOutput": true,
|
||||
"trace": false,
|
||||
"traceResponse": false
|
||||
},
|
||||
"useExtendedRemote": true
|
||||
},
|
||||
]
|
||||
}
|
||||
@@ -225,6 +225,7 @@ set(CPPSRC
|
||||
tone_key.cpp
|
||||
transmitter_model.cpp
|
||||
tuning.cpp
|
||||
usb_serial_asyncmsg.hpp
|
||||
hw/debounce.cpp
|
||||
hw/encoder.cpp
|
||||
hw/max2837.cpp
|
||||
|
||||
@@ -1,83 +1,93 @@
|
||||
#include "ui_about_simple.hpp"
|
||||
|
||||
namespace ui {
|
||||
AboutView::AboutView(NavigationView& nav) {
|
||||
add_children({&console, &button_ok});
|
||||
|
||||
button_ok.on_select = [&nav](Button&) {
|
||||
nav.pop();
|
||||
};
|
||||
|
||||
console.writeln(STR_COLOR_LIGHT_GREY "List of contributors:");
|
||||
console.writeln("");
|
||||
}
|
||||
|
||||
void AboutView::update() {
|
||||
if (++timer > 400) {
|
||||
timer = 0;
|
||||
|
||||
switch (++frame) {
|
||||
case 1:
|
||||
// TODO: Generate this automatically from github
|
||||
// https://github.com/portapack-mayhem/mayhem-firmware/graphs/contributors?to=2022-01-01&from=2020-04-12&type=c
|
||||
console.writeln(STR_COLOR_DARK_YELLOW "Mayhem:");
|
||||
console.writeln("eried,euquiq,gregoryfenton");
|
||||
console.writeln("johnelder,jwetzell,nnemanjan00");
|
||||
console.writeln("N0vaPixel,klockee,gullradriel");
|
||||
console.writeln("jamesshao8,ITAxReal,rascafr");
|
||||
console.writeln("mcules,dqs105,strijar");
|
||||
console.writeln("zhang00963,RedFox-Fr,aldude999");
|
||||
console.writeln("East2West,fossum,ArjanOnwezen");
|
||||
console.writeln("vXxOinvizioNxX,teixeluis");
|
||||
console.writeln("Brumi-2021,texasyojimbo");
|
||||
console.writeln("heurist1,intoxsick,ckuethe");
|
||||
console.writeln("notpike,jLynx,zigad");
|
||||
console.writeln("MichalLeonBorsuk,jimilinuxguy");
|
||||
console.writeln("kallanreed,bernd-herzog");
|
||||
break;
|
||||
case 2:
|
||||
console.writeln("NotherNgineer,zxkmm,u-foka");
|
||||
console.writeln("Netro,HTotoo");
|
||||
console.writeln("");
|
||||
break;
|
||||
|
||||
case 3:
|
||||
// https://github.com/portapack-mayhem/mayhem-firmware/graphs/contributors?to=2020-04-12&from=2015-07-31&type=c
|
||||
console.writeln(STR_COLOR_DARK_YELLOW "Havoc:");
|
||||
console.writeln("furrtek,mrmookie,NotPike");
|
||||
console.writeln("mjwaxios,ImDroided,Giorgiofox");
|
||||
console.writeln("F4GEV,z4ziggy,xmycroftx");
|
||||
console.writeln("troussos,silascutler");
|
||||
console.writeln("nickbouwhuis,msoose,leres");
|
||||
console.writeln("joakar,dhoetger,clem-42");
|
||||
console.writeln("brianlechthaler,ZeroChaos-...");
|
||||
console.writeln("");
|
||||
break;
|
||||
|
||||
case 4:
|
||||
// https://github.com/portapack-mayhem/mayhem-firmware/graphs/contributors?from=2014-07-05&to=2015-07-31&type=c
|
||||
console.writeln(STR_COLOR_DARK_YELLOW "PortaPack:");
|
||||
console.writeln("jboone,argilo");
|
||||
console.writeln("");
|
||||
break;
|
||||
|
||||
case 5:
|
||||
// https://github.com/mossmann/hackrf/graphs/contributors
|
||||
console.writeln(STR_COLOR_DARK_YELLOW "HackRF:");
|
||||
console.writeln("mossmann,dominicgs,bvernoux");
|
||||
console.writeln("bgamari,schneider42,miek");
|
||||
console.writeln("willcode,hessu,Sec42");
|
||||
console.writeln("yhetti,ckuethe,smunaut");
|
||||
console.writeln("wishi,mrbubble62,scateu...");
|
||||
console.writeln("");
|
||||
frame = 0; // Loop
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AboutView::focus() {
|
||||
button_ok.focus();
|
||||
}
|
||||
|
||||
} /* namespace ui */
|
||||
#include "ui_about_simple.hpp"
|
||||
|
||||
namespace ui {
|
||||
|
||||
// TODO: Generate this automatically from github
|
||||
// Information: a line starting with a '#' will be yellow coloured
|
||||
const std::string authors_list[] = {
|
||||
" ",
|
||||
"# * List of contributors * ",
|
||||
" ",
|
||||
"#Mayhem:",
|
||||
" ",
|
||||
"eried,euquiq,gregoryfenton",
|
||||
"johnelder,jwetzell,nnemanjan00",
|
||||
"N0vaPixel,klockee,gullradriel",
|
||||
"jamesshao8,ITAxReal,rascafr",
|
||||
"mcules,dqs105,strijar",
|
||||
"zhang00963,RedFox-Fr,aldude999",
|
||||
"East2West,fossum,ArjanOnwezen",
|
||||
"vXxOinvizioNxX,teixeluis",
|
||||
"Brumi-2021,texasyojimbo",
|
||||
"heurist1,intoxsick,ckuethe",
|
||||
"notpike,jLynx,zigad",
|
||||
"MichalLeonBorsuk,jimilinuxguy",
|
||||
"kallanreed,bernd-herzog",
|
||||
"NotherNgineer,zxkmm,u-foka",
|
||||
"Netro,HTotoo",
|
||||
" ",
|
||||
"#Havoc:",
|
||||
" ",
|
||||
"furrtek,mrmookie,NotPike",
|
||||
"mjwaxios,ImDroided,Giorgiofox",
|
||||
"F4GEV,z4ziggy,xmycroftx",
|
||||
"troussos,silascutler",
|
||||
"nickbouwhuis,msoose,leres",
|
||||
"joakar,dhoetger,clem-42",
|
||||
"brianlechthaler,ZeroChaos-...",
|
||||
" ",
|
||||
"#PortaPack:",
|
||||
" ",
|
||||
"jboone,argilo",
|
||||
" ",
|
||||
"#HackRF:",
|
||||
" ",
|
||||
"mossmann,dominicgs,bvernoux",
|
||||
"bgamari,schneider42,miek",
|
||||
"willcode,hessu,Sec42",
|
||||
"yhetti,ckuethe,smunaut",
|
||||
"wishi,mrbubble62,scateu..."};
|
||||
|
||||
AboutView::AboutView(NavigationView& nav) {
|
||||
add_children({&menu_view,
|
||||
&button_ok});
|
||||
|
||||
button_ok.on_select = [&nav](Button&) {
|
||||
nav.pop();
|
||||
};
|
||||
|
||||
menu_view.on_left = [this]() {
|
||||
button_ok.focus();
|
||||
};
|
||||
|
||||
menu_view.on_right = [this]() {
|
||||
button_ok.focus();
|
||||
};
|
||||
|
||||
for (const std::string& authors_line : authors_list) {
|
||||
// if it's starting with #, it's a title and we have to substract the '#' and paint yellow
|
||||
if (authors_line.size() > 0) {
|
||||
if (authors_line[0] == '#') {
|
||||
menu_view.add_item(
|
||||
{authors_line.substr(1, authors_line.size() - 1),
|
||||
ui::Color::yellow(),
|
||||
nullptr,
|
||||
nullptr});
|
||||
} else {
|
||||
menu_view.add_item(
|
||||
{authors_line,
|
||||
ui::Color::white(),
|
||||
nullptr,
|
||||
nullptr});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AboutView::focus() {
|
||||
menu_view.focus();
|
||||
// put focus on first text line
|
||||
menu_view.set_highlighted(1);
|
||||
}
|
||||
|
||||
} /* namespace ui */
|
||||
|
||||
@@ -12,25 +12,16 @@ class AboutView : public View {
|
||||
AboutView(NavigationView& nav);
|
||||
void focus() override;
|
||||
std::string title() const override { return "About"; };
|
||||
int32_t timer{180};
|
||||
short frame{0};
|
||||
|
||||
private:
|
||||
void update();
|
||||
|
||||
Console console{
|
||||
{0, 10, 240, 240}};
|
||||
MenuView menu_view{
|
||||
{0, 0, 240, 240},
|
||||
true};
|
||||
|
||||
Button button_ok{
|
||||
{240 / 3, 270, 240 / 3, 24},
|
||||
"OK",
|
||||
};
|
||||
|
||||
MessageHandlerRegistration message_handler_update{
|
||||
Message::ID::DisplayFrameSync,
|
||||
[this](const Message* const) {
|
||||
this->update();
|
||||
}};
|
||||
};
|
||||
} // namespace ui
|
||||
|
||||
|
||||
@@ -42,6 +42,32 @@ POCSAGTXView::~POCSAGTXView() {
|
||||
baseband::shutdown();
|
||||
}
|
||||
|
||||
void POCSAGTXView::on_remote(const PocsagTosendMessage data) {
|
||||
// check if still sending or not
|
||||
size_t tmp = 0;
|
||||
if (data.baud == 1200) tmp = 1;
|
||||
if (data.baud == 2400) tmp = 2;
|
||||
options_bitrate.set_selected_index(tmp);
|
||||
tmp = 0;
|
||||
options_type.set_selected_index(data.type);
|
||||
if (data.function == 'B') tmp = 1;
|
||||
if (data.function == 'C') tmp = 2;
|
||||
if (data.function == 'D') tmp = 3;
|
||||
options_function.set_selected_index(tmp);
|
||||
options_phase.set_selected_index(data.phase == 'P' ? 0 : 1);
|
||||
field_address.set_value(data.addr);
|
||||
message = (char*)data.msg;
|
||||
text_message.set(message);
|
||||
options_bitrate.dirty();
|
||||
options_type.dirty();
|
||||
options_function.dirty();
|
||||
options_phase.dirty();
|
||||
field_address.dirty();
|
||||
text_message.dirty();
|
||||
tx_view.focus();
|
||||
start_tx();
|
||||
}
|
||||
|
||||
void POCSAGTXView::on_tx_progress(const uint32_t progress, const bool done) {
|
||||
if (done) {
|
||||
transmitter_model.disable();
|
||||
|
||||
@@ -76,6 +76,7 @@ class POCSAGTXView : public View {
|
||||
|
||||
void on_set_text(NavigationView& nav);
|
||||
void on_tx_progress(const uint32_t progress, const bool done);
|
||||
void on_remote(const PocsagTosendMessage data);
|
||||
bool start_tx();
|
||||
|
||||
Labels labels{
|
||||
@@ -142,6 +143,13 @@ class POCSAGTXView : public View {
|
||||
const auto message = *reinterpret_cast<const TXProgressMessage*>(p);
|
||||
this->on_tx_progress(message.progress, message.done);
|
||||
}};
|
||||
|
||||
MessageHandlerRegistration message_handler_tx_remote{
|
||||
Message::ID::PocsagTosend,
|
||||
[this](const Message* const p) {
|
||||
const auto message = *reinterpret_cast<const PocsagTosendMessage*>(p);
|
||||
this->on_remote(message);
|
||||
}};
|
||||
};
|
||||
|
||||
} /* namespace ui */
|
||||
|
||||
@@ -156,7 +156,6 @@ void SSTVTXView::start_tx() {
|
||||
// The baseband SSTV TX code (proc_sstv) has a 2-scanline buffer. It is preloaded before
|
||||
// TX start, and asks for fill-up when a new scanline starts being read. This should
|
||||
// leave enough time for the code in prepare_scanline() before it ends.
|
||||
|
||||
scanline_counter = 0;
|
||||
prepare_scanline(); // Preload one scanline
|
||||
|
||||
|
||||
@@ -81,7 +81,7 @@ SubGhzDView::SubGhzDView(NavigationView& nav)
|
||||
recent.clear();
|
||||
recent_entries_view.set_dirty();
|
||||
};
|
||||
field_frequency.set_step(100000);
|
||||
field_frequency.set_step(10000);
|
||||
|
||||
const Rect content_rect{0, header_height, screen_width, screen_height - header_height};
|
||||
recent_entries_view.set_parent_rect(content_rect);
|
||||
|
||||
@@ -105,7 +105,7 @@ WeatherView::WeatherView(NavigationView& nav)
|
||||
recent.clear();
|
||||
recent_entries_view.set_dirty();
|
||||
};
|
||||
field_frequency.set_step(100000);
|
||||
field_frequency.set_step(10000);
|
||||
|
||||
options_temperature.on_change = [this](size_t, int32_t i) {
|
||||
weather_units_fahr = (bool)i;
|
||||
|
||||
@@ -617,4 +617,6 @@ void setEventDispatcherToUSBSerial(EventDispatcher* evt) {
|
||||
usb_serial.setEventDispatcher(evt);
|
||||
}
|
||||
|
||||
bool async_tx_enabled = false; // this is for serial tx things, globally
|
||||
|
||||
} /* namespace portapack */
|
||||
|
||||
@@ -81,4 +81,6 @@ void setEventDispatcherToUSBSerial(EventDispatcher* evt);
|
||||
|
||||
Backlight* backlight();
|
||||
|
||||
extern bool async_tx_enabled; // this is for serial tx things, globally
|
||||
|
||||
} /* namespace portapack */
|
||||
|
||||
@@ -159,6 +159,7 @@ std::string to_string_decimal(float decimal, int8_t precision) {
|
||||
double fractional_part;
|
||||
|
||||
std::string result;
|
||||
if (precision > 9) precision = 9; // we will convert to uin32_t, and that is the max it can hold.
|
||||
|
||||
fractional_part = modf(decimal, &integer_part) * pow(10, precision);
|
||||
|
||||
|
||||
@@ -251,8 +251,12 @@ bool MenuView::on_key(const KeyEvent key) {
|
||||
case KeyEvent::Down:
|
||||
return set_highlighted(highlighted_item + 1);
|
||||
|
||||
case KeyEvent::Select:
|
||||
case KeyEvent::Right:
|
||||
if (on_right) {
|
||||
on_right();
|
||||
}
|
||||
[[fallthrough]];
|
||||
case KeyEvent::Select:
|
||||
if (menu_items[highlighted_item].on_select) {
|
||||
menu_items[highlighted_item].on_select(key);
|
||||
}
|
||||
|
||||
@@ -75,6 +75,7 @@ class MenuItemView : public Widget {
|
||||
class MenuView : public View {
|
||||
public:
|
||||
std::function<void(void)> on_left{};
|
||||
std::function<void(void)> on_right{};
|
||||
std::function<void(void)> on_highlight{nullptr};
|
||||
|
||||
MenuView(Rect new_parent_rect = {0, 0, screen_width, screen_height - 16},
|
||||
|
||||
@@ -0,0 +1,168 @@
|
||||
/*
|
||||
* Copyright (C) 2015 Jared Boone, ShareBrained Technology, Inc.
|
||||
* Copyright (C) 2017 Furrtek
|
||||
* Copyleft (ɔ) 2024 zxkmm with the GPL license
|
||||
*
|
||||
* This file is part of PortaPack.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, Inc., 51 Franklin Street,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#ifndef USB_SERIAL_AYNCMSG_HPP
|
||||
#define USB_SERIAL_AYNCMSG_HPP
|
||||
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
#include <chprintf.h>
|
||||
#include "usb_serial_device_to_host.h"
|
||||
|
||||
class UsbSerialAsyncmsg {
|
||||
public:
|
||||
template <typename STRINGCOVER>
|
||||
static void asyncmsg(const STRINGCOVER& data);
|
||||
|
||||
template <typename VECTORCOVER>
|
||||
static void asyncmsg(const std::vector<VECTORCOVER>& data);
|
||||
|
||||
static void asyncmsg(const char* data); // string literal
|
||||
};
|
||||
|
||||
/*Notes:
|
||||
* - Don't use MayhemHub since it currently not support real time serial output
|
||||
* - If you don't use this class linker will drop it so it won't use any space
|
||||
* - so delete all debug things before you push your code to production
|
||||
* - use this client to filter only PP devices: https://github.com/zxkmm/Pyserial-Demo-portapack
|
||||
* - usage:
|
||||
* portapack::async_tx_enabled = true; // note that use this when debugging, unless the msg would be forbidden. but don't use this in production, since it's not real async and multiple serial transmittions will broken each other. if this class is used in other scene in the future, just use command to cover (protect your serial tramsnitton) in your extern thing: asyncmsg enable --- your cmd --- asyncmsg disable
|
||||
* #include "usb_serial_asyncmsg.cpp"
|
||||
* UsbSerialAsyncmsg::asyncmsg("Hello PP");
|
||||
* */
|
||||
|
||||
/// value
|
||||
// to_string_bin/ to_string_decimal/ to_string_hex/ to_string_hex_array/ to_string_dec_uint/ to_string_dec_int etc seems usellss so i didn't add them here
|
||||
// usage: UsbSerialAsyncmsg::asyncmsg(num);
|
||||
|
||||
template <>
|
||||
void UsbSerialAsyncmsg::asyncmsg<int64_t>(const int64_t& data) {
|
||||
if (!portapack::async_tx_enabled) {
|
||||
return;
|
||||
}
|
||||
chprintf((BaseSequentialStream*)&SUSBD1, "%s\r\n", to_string_dec_int(data).c_str());
|
||||
}
|
||||
|
||||
template <>
|
||||
void UsbSerialAsyncmsg::asyncmsg<int32_t>(const int32_t& data) {
|
||||
if (!portapack::async_tx_enabled) {
|
||||
return;
|
||||
}
|
||||
chprintf((BaseSequentialStream*)&SUSBD1, "%s\r\n", to_string_dec_int(data).c_str());
|
||||
}
|
||||
|
||||
template <>
|
||||
void UsbSerialAsyncmsg::asyncmsg<int16_t>(const int16_t& data) {
|
||||
if (!portapack::async_tx_enabled) {
|
||||
return;
|
||||
}
|
||||
chprintf((BaseSequentialStream*)&SUSBD1, "%s\r\n", to_string_dec_int(data).c_str());
|
||||
}
|
||||
|
||||
template <>
|
||||
void UsbSerialAsyncmsg::asyncmsg<int8_t>(const int8_t& data) {
|
||||
if (!portapack::async_tx_enabled) {
|
||||
return;
|
||||
}
|
||||
chprintf((BaseSequentialStream*)&SUSBD1, "%s\r\n", to_string_dec_int(data).c_str());
|
||||
}
|
||||
|
||||
template <>
|
||||
void UsbSerialAsyncmsg::asyncmsg<uint8_t>(const uint8_t& data) {
|
||||
if (!portapack::async_tx_enabled) {
|
||||
return;
|
||||
}
|
||||
chprintf((BaseSequentialStream*)&SUSBD1, "%s\r\n", to_string_dec_int(data).c_str());
|
||||
}
|
||||
|
||||
template <>
|
||||
void UsbSerialAsyncmsg::asyncmsg<uint16_t>(const uint16_t& data) {
|
||||
if (!portapack::async_tx_enabled) {
|
||||
return;
|
||||
}
|
||||
chprintf((BaseSequentialStream*)&SUSBD1, "%s\r\n", to_string_dec_int(data).c_str());
|
||||
}
|
||||
|
||||
template <>
|
||||
void UsbSerialAsyncmsg::asyncmsg<uint32_t>(const uint32_t& data) {
|
||||
if (!portapack::async_tx_enabled) {
|
||||
return;
|
||||
}
|
||||
chprintf((BaseSequentialStream*)&SUSBD1, "%s\r\n", to_string_dec_int(data).c_str());
|
||||
}
|
||||
|
||||
template <>
|
||||
void UsbSerialAsyncmsg::asyncmsg<uint64_t>(const uint64_t& data) {
|
||||
if (!portapack::async_tx_enabled) {
|
||||
return;
|
||||
}
|
||||
chprintf((BaseSequentialStream*)&SUSBD1, "%s\r\n", to_string_dec_int(data).c_str());
|
||||
}
|
||||
|
||||
/// fs things
|
||||
|
||||
template <>
|
||||
// usage: UsbSerialAsyncmsg::asyncmsg(path);
|
||||
void UsbSerialAsyncmsg::asyncmsg<std::filesystem::path>(const std::filesystem::path& data) {
|
||||
if (!portapack::async_tx_enabled) {
|
||||
return;
|
||||
}
|
||||
std::string path_str = data.string();
|
||||
chprintf((BaseSequentialStream*)&SUSBD1, "%s\r\n", path_str.c_str());
|
||||
}
|
||||
|
||||
/// string
|
||||
|
||||
// string obj
|
||||
template <>
|
||||
// usage: UsbSerialAsyncmsg::asyncmsg(str);
|
||||
void UsbSerialAsyncmsg::asyncmsg<std::string>(const std::string& data) {
|
||||
if (!portapack::async_tx_enabled) {
|
||||
return;
|
||||
}
|
||||
chprintf((BaseSequentialStream*)&SUSBD1, "%s\r\n", data.c_str());
|
||||
}
|
||||
|
||||
// string literal AKA char[]
|
||||
// usage: UsbSerialAsyncmsg::asyncmsg("abc");
|
||||
void UsbSerialAsyncmsg::asyncmsg(const char* data) {
|
||||
if (!portapack::async_tx_enabled) {
|
||||
return;
|
||||
}
|
||||
chprintf((BaseSequentialStream*)&SUSBD1, "%s\r\n", data);
|
||||
}
|
||||
|
||||
/// vec worker
|
||||
// ussgae: UsbSerialAsyncmsg::asyncmsg(vec);
|
||||
template <typename VECTORCOVER>
|
||||
void UsbSerialAsyncmsg::asyncmsg(const std::vector<VECTORCOVER>& data) {
|
||||
if (!portapack::async_tx_enabled) {
|
||||
return;
|
||||
}
|
||||
for (const auto& item : data) {
|
||||
asyncmsg(item);
|
||||
}
|
||||
}
|
||||
|
||||
#endif // USB_SERIAL_AYNCMSG_HPP
|
||||
@@ -1053,6 +1053,101 @@ static void cmd_settingsreset(BaseSequentialStream* chp, int argc, char* argv[])
|
||||
chprintf(chp, "ok\r\n");
|
||||
}
|
||||
|
||||
static void cmd_sendpocsag(BaseSequentialStream* chp, int argc, char* argv[]) {
|
||||
const char* usage = "usage: sendpocsag <addr> <msglen> [baud] [type] [function] [phase] \r\n";
|
||||
(void)argv;
|
||||
if (argc < 2) {
|
||||
chprintf(chp, usage);
|
||||
return;
|
||||
}
|
||||
uint64_t addr = atol(argv[0]);
|
||||
int msglen = atoi(argv[1]); // without minimum limit, since addr only don't send anything
|
||||
if (msglen > 30 || msglen < 0) {
|
||||
chprintf(chp, "error, msglen max is 30\r\n");
|
||||
return;
|
||||
}
|
||||
|
||||
int baud = 1200;
|
||||
if (argc >= 3) {
|
||||
baud = atoi(argv[2]);
|
||||
if (baud != 512 && baud != 1200 && baud != 2400) {
|
||||
chprintf(chp, "error, baud can only be 512, 1200 or 2400\r\n");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
int type = 2;
|
||||
if (argc >= 4) {
|
||||
type = atoi(argv[3]);
|
||||
if (type > 2 || type < 0) {
|
||||
chprintf(chp, "error, type can be 0 (ADDRESS_ONLY) 1 (NUMERIC_ONLY) 2 (ALPHANUMERIC)\r\n");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
char function = 'D';
|
||||
if (argc >= 5) {
|
||||
function = *argv[4];
|
||||
if (function < 'A' && function > 'D') {
|
||||
chprintf(chp, "error, function can be A, B, C or D\r\n");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
char phase = 'P';
|
||||
if (argc >= 6) {
|
||||
phase = *argv[5];
|
||||
if (phase != 'P' && phase != 'N') {
|
||||
chprintf(chp, "error, phase can be P or N\r\n");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t msg[31] = {0};
|
||||
if (msglen > 0) {
|
||||
chprintf(chp, "send %d bytes\r\n", msglen);
|
||||
do {
|
||||
size_t bytes_to_read = msglen > USB_BULK_BUFFER_SIZE ? USB_BULK_BUFFER_SIZE : msglen;
|
||||
size_t bytes_read = chSequentialStreamRead(chp, &msg[0], bytes_to_read);
|
||||
if (bytes_read != bytes_to_read)
|
||||
return;
|
||||
msglen -= bytes_read;
|
||||
} while (msglen > 0);
|
||||
}
|
||||
|
||||
auto evtd = getEventDispatcherInstance();
|
||||
if (!evtd) return;
|
||||
auto top_widget = evtd->getTopWidget();
|
||||
if (!top_widget) return;
|
||||
auto nav = static_cast<ui::SystemView*>(top_widget)->get_navigation_view();
|
||||
if (!nav) return;
|
||||
if (!nav->StartAppByName("pocsagtx")) {
|
||||
chprintf(chp, "error starting pocsagtx\r\n");
|
||||
return;
|
||||
}
|
||||
chThdSleepMilliseconds(1000); // wait for app to start
|
||||
PocsagTosendMessage message{(uint16_t)baud, (uint8_t)type, function, phase, (uint8_t)msglen, msg, addr};
|
||||
EventDispatcher::send_message(message);
|
||||
chprintf(chp, "ok\r\n");
|
||||
}
|
||||
|
||||
static void cmd_asyncmsg(BaseSequentialStream* chp, int argc, char* argv[]) {
|
||||
const char* usage = "usage: asyncmsg x, x can be enable or disable\r\n";
|
||||
if (argc != 1) {
|
||||
chprintf(chp, usage);
|
||||
return;
|
||||
}
|
||||
if (strcmp(argv[0], "disable") == 0) {
|
||||
portapack::async_tx_enabled = false;
|
||||
chprintf(chp, "ok\r\n");
|
||||
} else if (strcmp(argv[0], "enable") == 0) {
|
||||
portapack::async_tx_enabled = true;
|
||||
chprintf(chp, "ok\r\n");
|
||||
} else {
|
||||
chprintf(chp, usage);
|
||||
}
|
||||
}
|
||||
|
||||
static const ShellCommand commands[] = {
|
||||
{"reboot", cmd_reboot},
|
||||
{"dfu", cmd_dfu},
|
||||
@@ -1083,6 +1178,8 @@ static const ShellCommand commands[] = {
|
||||
{"radioinfo", cmd_radioinfo},
|
||||
{"pmemreset", cmd_pmemreset},
|
||||
{"settingsreset", cmd_settingsreset},
|
||||
{"sendpocsag", cmd_sendpocsag},
|
||||
{"asyncmsg", cmd_asyncmsg},
|
||||
{NULL, NULL}};
|
||||
|
||||
static const ShellConfig shell_cfg1 = {
|
||||
|
||||
@@ -122,6 +122,7 @@ class Message {
|
||||
OrientationData = 64,
|
||||
EnvironmentData = 65,
|
||||
AudioBeep = 66,
|
||||
PocsagTosend = 67,
|
||||
MAX
|
||||
};
|
||||
|
||||
@@ -1379,4 +1380,33 @@ class AudioBeepMessage : public Message {
|
||||
uint32_t sample_rate = 24000;
|
||||
uint32_t duration_ms = 100;
|
||||
};
|
||||
|
||||
class PocsagTosendMessage : public Message {
|
||||
public:
|
||||
constexpr PocsagTosendMessage(
|
||||
uint16_t baud = 1200,
|
||||
uint8_t type = 2,
|
||||
char function = 'D',
|
||||
char phase = 'N',
|
||||
uint8_t msglen = 0,
|
||||
uint8_t msg[31] = {0},
|
||||
uint64_t addr = 0)
|
||||
: Message{ID::PocsagTosend},
|
||||
baud{baud},
|
||||
type{type},
|
||||
function{function},
|
||||
phase{phase},
|
||||
msglen{msglen},
|
||||
addr{addr} {
|
||||
memcpy(this->msg, msg, 31);
|
||||
}
|
||||
uint16_t baud = 1200;
|
||||
uint8_t type = 2;
|
||||
char function = 'D';
|
||||
char phase = 'N';
|
||||
uint8_t msglen = 0;
|
||||
uint8_t msg[31] = {0};
|
||||
uint64_t addr = 0;
|
||||
};
|
||||
|
||||
#endif /*__MESSAGE_H__*/
|
||||
|
||||
Reference in New Issue
Block a user