Compare commits

...

27 Commits

Author SHA1 Message Date
gullradriel ae9d6de093 added sysinfo and radioinfo (#1769)
* added sysinfo and radioinfo

* using fillObuffer instead of chprintf

---------

Co-authored-by: GullCode <gullradriel@hotmail.com>
2024-01-15 15:54:27 +13:00
Bernd Herzog 7a4c3184a1 reworked usb serial communication (#1766) 2024-01-13 18:05:29 +01:00
Mark Thompson 58307aee9c Make use of "ensure_directory" function (#1765) 2024-01-13 07:57:32 +01:00
Bernd Herzog 409242507c Usb serial fix queue full crash (#1763)
* fixed usb serial queue crashing

* fixed usb input buffer handling

* fixed black screen issue
2024-01-12 21:49:10 +01:00
E.T 0a8194fa10 Really go home before starting app from serial (#1762) 2024-01-12 17:33:41 +01:00
Bernd Herzog eaac40df3a fixed usb serial queue crashing (#1761) 2024-01-12 16:04:32 +01:00
Mark Thompson 58b488b840 Added new "App Setting" app (#1759)
* New "App Settings" app for quicker settings access
2024-01-12 13:41:13 +01:00
Totoo 1676702a09 Shows a message when flashing from serial (#1758) 2024-01-12 10:30:24 +13:00
Totoo 3943848add GPS + orientation for Sonde (#1757)
* RadioSonde has gpsdata
* Orientation update in Sonde
2024-01-11 22:17:06 +01:00
Totoo 831dbeaab5 Add extra info from serial (#1754)
* Inject GPS postition from serial
2024-01-11 17:46:35 +01:00
jLynx 49e719ded8 Update repo links (#1750)
* Update repo links to new link

* Removed travis

* Removed travis

* Updated more links
2024-01-10 21:13:43 +13:00
Mark Thompson c2d2409bff Modify encoder handler to not call "on_encoder" functions if no change (#1749) 2024-01-09 23:32:58 -06:00
Mark Thompson 485f57d86b Added Audio Out to Soundboard app (#1748) 2024-01-09 13:50:45 -06:00
Totoo 0e6f303eec fix buffer size bug (#1747)
* fix buffer size bug

* faster file over usbcdc - wip

* minimal faster display tx
2024-01-10 06:30:43 +13:00
Totoo ad94ae05c1 Fwrite fix (#1744) 2024-01-09 09:09:25 +13:00
Bernd Herzog 89dc8c0463 found missing revert (#1743) 2024-01-09 08:13:51 +13:00
Bernd Herzog 77640c5cc0 Usb serial filesystem improvements (#1742)
* refactoring

* improved file system commands

* added binary read/write
2024-01-08 19:53:40 +01:00
Erwin Ried cdc8cfeb7d Update README.md (#1740) 2024-01-08 22:45:46 +13:00
Bernd Herzog 4740df2e2c Usb serial shell workerthread #2 (#1738) 2024-01-07 22:25:43 +01:00
Bernd Herzog ec0f45a488 added sys locks to time critical lcd updates (#1737) 2024-01-07 19:50:26 +01:00
Totoo 9d7e06c255 Appstart and applist from serial (#1736)
* Start app, and list fixed ones.
* Add ext app support
2024-01-07 18:56:09 +01:00
sommermoregentraum 4b93e78dd9 make pacman's face (mouse) face to the dir which he hits the wall (#1735) 2024-01-07 16:55:45 +01:00
Bernd Herzog 5ced8c90d3 added radio saturation to performance counter (#1734) 2024-01-07 15:31:08 +01:00
Bernd Herzog 9d22711368 added usb event to not wait for the next frame (#1733) 2024-01-07 14:09:22 +01:00
Bernd Herzog 23e6295dd2 removed the use of the hackrf cpld eeprom (#1732)
* removed the use of the hackrf cpld eeprom

* readded comment
2024-01-07 12:29:53 +01:00
Bernd Herzog bbd75ab7ef fixed usb descriptor product string length (#1731) 2024-01-07 11:57:16 +01:00
jLynx 7508fee62c Fixed sdcard zip folder structure (#1730)
* Fixed sd card zip folder structure

* Update create_nightly_release.yml

Updated zip for work map

* Update create_stable_release.yml

Replicated on stable release
2024-01-07 19:51:27 +13:00
66 changed files with 1580 additions and 426 deletions
+1 -1
View File
@@ -9,7 +9,7 @@ assignees: ''
----
(Please try the latest nightly release before submitting this. You can find the latest nightly version here: https://github.com/eried/portapack-mayhem/releases)
(Please try the latest nightly release before submitting this. You can find the latest nightly version here: https://github.com/portapack-mayhem/mayhem-firmware/releases)
----
@@ -9,8 +9,8 @@ assignees: ''
----
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
* 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
@@ -27,12 +27,12 @@ Steps to reproduce the behavior:
**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
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/eried/portapack-mayhem/releases
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.
+2 -2
View File
@@ -6,8 +6,8 @@ from datetime import datetime, timedelta, timezone
# Set up your personal access token and the repository details
token = os.environ.get('GH_TOKEN')
repo_owner = "eried"
repo_name = "portapack-mayhem"
repo_owner = "portapack-mayhem"
repo_name = "mayhem-firmware"
def print_stable_changelog(previous_sha):
+3 -3
View File
@@ -54,10 +54,10 @@ jobs:
run: docker run -e VERSION_STRING=${{ steps.version_date.outputs.date }} -i -v ${{ github.workspace }}:/havoc portapack-dev
- name: Create Small SD Card ZIP - No World Map
run: |
mkdir -p sdcard/FIRMWARE && cp build/firmware/portapack-h1_h2-mayhem.bin sdcard/FIRMWARE/portapack-mayhem_${{ steps.version_date.outputs.date }}.bin && mkdir -p sdcard/APPS && cp build/firmware/application/*.ppma sdcard/APPS && zip -r sdcard-no-map.zip sdcard
mkdir -p sdcard/FIRMWARE && cp build/firmware/portapack-h1_h2-mayhem.bin sdcard/FIRMWARE/portapack-mayhem_${{ steps.version_date.outputs.date }}.bin && mkdir -p sdcard/APPS && cp build/firmware/application/*.ppma sdcard/APPS && cd sdcard && zip -r ../sdcard-no-map.zip . && cd ..
- name: Download world map
run: |
wget https://github.com/eried/portapack-mayhem/releases/download/world_map/world_map.zip
wget https://github.com/portapack-mayhem/mayhem-firmware/releases/download/world_map/world_map.zip
- name: Unzip world map
run: |
unzip world_map.zip -d sdcard/ADSB
@@ -66,7 +66,7 @@ jobs:
zip -j firmware.zip build/firmware/portapack-h1_h2-mayhem.bin && cd flashing && zip -r ../firmware.zip *
- name: Create SD Card ZIP
run: |
mkdir -p sdcard/FIRMWARE && cp build/firmware/portapack-h1_h2-mayhem.bin sdcard/FIRMWARE/portapack-mayhem_${{ steps.version_date.outputs.date }}.bin && mkdir -p sdcard/APPS && cp build/firmware/application/*.ppma sdcard/APPS && zip -r sdcard.zip sdcard
mkdir -p sdcard/FIRMWARE && cp build/firmware/portapack-h1_h2-mayhem.bin sdcard/FIRMWARE/portapack-mayhem_${{ steps.version_date.outputs.date }}.bin && mkdir -p sdcard/APPS && cp build/firmware/application/*.ppma sdcard/APPS && cd sdcard && zip -r ../sdcard.zip . && cd ..
- name: Create changelog
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+6 -6
View File
@@ -38,10 +38,10 @@ jobs:
run: docker run -e VERSION_STRING=${{ steps.version.outputs.version }} -i -v ${{ github.workspace }}:/havoc portapack-dev
- name: Create Small SD Card ZIP - No World Map
run: |
mkdir -p sdcard/FIRMWARE && cp build/firmware/portapack-h1_h2-mayhem.bin sdcard/FIRMWARE/portapack-mayhem_${{ steps.version.outputs.version }}.bin && mkdir -p sdcard/APPS && cp build/firmware/application/*.ppma sdcard/APPS && zip -r sdcard-no-map.zip sdcard
mkdir -p sdcard/FIRMWARE && cp build/firmware/portapack-h1_h2-mayhem.bin sdcard/FIRMWARE/portapack-mayhem_${{ steps.version.outputs.version }}.bin && mkdir -p sdcard/APPS && cp build/firmware/application/*.ppma sdcard/APPS && cd sdcard && zip -r ../sdcard-no-map.zip . && cd ..
- name: Download world map
run: |
wget https://github.com/eried/portapack-mayhem/releases/download/world_map/world_map.zip
wget https://github.com/portapack-mayhem/mayhem-firmware/releases/download/world_map/world_map.zip
- name: Unzip world map
run: |
unzip world_map.zip -d sdcard/ADSB
@@ -50,7 +50,7 @@ jobs:
zip -j firmware.zip build/firmware/portapack-h1_h2-mayhem.bin && cd flashing && zip -r ../firmware.zip *
- name: Create SD Card ZIP
run: |
mkdir -p sdcard/FIRMWARE && cp build/firmware/portapack-h1_h2-mayhem.bin sdcard/FIRMWARE/portapack-mayhem_${{ steps.version.outputs.version }}.bin && mkdir -p sdcard/APPS && cp build/firmware/application/*.ppma sdcard/APPS && zip -r sdcard.zip sdcard
mkdir -p sdcard/FIRMWARE && cp build/firmware/portapack-h1_h2-mayhem.bin sdcard/FIRMWARE/portapack-mayhem_${{ steps.version.outputs.version }}.bin && mkdir -p sdcard/APPS && cp build/firmware/application/*.ppma sdcard/APPS && cd sdcard && zip -r ../sdcard.zip . && cd ..
- name: Create changelog
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
@@ -71,15 +71,15 @@ jobs:
release_name: Mayhem firmware ${{ steps.version.outputs.version }}
body: |
**Stable release - ${{ steps.version.outputs.version }}**
This is a fork of the [Havoc](https://github.com/furrtek/portapack-havoc/) firmware, which itself was a fork of the [PortaPack](https://github.com/sharebrained/portapack-hackrf) firmware, an add-on for the [HackRF](http://greatscottgadgets.com/hackrf/). Please check the [readme](https://github.com/eried/portapack-mayhem/blob/master/README.md) for details.
This is a fork of the [Havoc](https://github.com/furrtek/portapack-havoc/) firmware, which itself was a fork of the [PortaPack](https://github.com/sharebrained/portapack-hackrf) firmware, an add-on for the [HackRF](http://greatscottgadgets.com/hackrf/). Please check the [readme](https://github.com/portapack-mayhem/mayhem-firmware/blob/master/README.md) for details.
## Release notes
### Revision (${{ steps.version.outputs.version }}):
${{ steps.changelog.outputs.content }}
**Full Changelog**: https://github.com/eried/portapack-mayhem/compare/${{ steps.past_version.outputs.past_version }}...${{ steps.version.outputs.version }}
**Full Changelog**: https://github.com/portapack-mayhem/mayhem-firmware/compare/${{ steps.past_version.outputs.past_version }}...${{ steps.version.outputs.version }}
## Installation
Check the [wiki](https://github.com/eried/portapack-havoc/wiki/Update-firmware) for details how to upgrade.
Check the [wiki](https://github.com/portapack-mayhem/mayhem-firmware/wiki/Update-firmware) for details how to upgrade.
__Warning:__ Since release 1.8.0, some applications has been moved to the SD card as we ran out of flash space.
### MicroSD card files
+14 -14
View File
@@ -1,15 +1,15 @@
> [!IMPORTANT]
> *Shortly*, this repository **will be moved** from my personal GitHub [eried/portapack-mayhem](https://github.com/eried/portapack-mayhem) to an organization: [portapack-mayhem/portapack-mayhem](https://github.com/portapack-mayhem/portapack-mayhem). Please keep this in mind to **update your links** accordingly.
> this repository **has just been moved** from my personal GitHub [eried/portapack-mayhem](https://github.com/eried/portapack-mayhem) to an organization: [portapack-mayhem](https://github.com/portapack-mayhem/mayhem-firmware). Please keep this in mind to **update your links** accordingly.
# PortaPack Mayhem
[![Build Status](https://travis-ci.com/eried/portapack-mayhem.svg?branch=master)](https://travis-ci.com/eried/portapack-mayhem) [![Nightly Release](https://github.com/eried/portapack-mayhem/actions/workflows/create_nightly_release.yml/badge.svg?branch=next)](https://github.com/eried/portapack-mayhem/actions/workflows/create_nightly_release.yml) [![CodeScene Code Health](https://codescene.io/projects/8381/status-badges/code-health)](https://codescene.io/projects/8381) [![GitHub All Releases](https://img.shields.io/github/downloads/eried/portapack-mayhem/total)](https://github.com/eried/portapack-mayhem/releases) [![GitHub Releases](https://img.shields.io/github/downloads/eried/portapack-mayhem/latest/total)](https://github.com/eried/portapack-mayhem/releases/latest) [![Docker Hub Pulls](https://img.shields.io/docker/pulls/eried/portapack.svg)](https://hub.docker.com/r/eried/portapack) [![Discord Chat](https://dcbadge.vercel.app/api/server/tuwVMv3?style=flat)](https://discord.gg/tuwVMv3)
[![Nightly Release](https://github.com/portapack-mayhem/mayhem-firmware/actions/workflows/create_nightly_release.yml/badge.svg?branch=next)](https://github.com/portapack-mayhem/mayhem-firmware/actions/workflows/create_nightly_release.yml) [![CodeScene Code Health](https://codescene.io/projects/8381/status-badges/code-health)](https://codescene.io/projects/8381) [![GitHub All Releases](https://img.shields.io/github/downloads/portapack-mayhem/mayhem-firmware/total)](https://github.com/portapack-mayhem/mayhem-firmware/releases) [![GitHub Releases](https://img.shields.io/github/downloads/portapack-mayhem/mayhem-firmware/latest/total)](https://github.com/portapack-mayhem/mayhem-firmware/releases/latest) [![Docker Hub Pulls](https://img.shields.io/docker/pulls/eried/portapack.svg)](https://hub.docker.com/r/eried/portapack) [![Discord Chat](https://dcbadge.vercel.app/api/server/tuwVMv3?style=flat)](https://discord.gg/tuwVMv3)
This is a fork of the [Havoc](https://github.com/furrtek/portapack-havoc/) firmware, which itself 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 is a derivate, in this case one that has extra features and fixes when compared to the older versions.
[<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)
[<img src="https://raw.githubusercontent.com/wiki/portapack-mayhem/mayhem-firmware/img/hw_overview_h2_front.png" height="400">](https://github.com/portapack-mayhem/mayhem-firmware/wiki/Hardware-overview) [<img src="https://raw.githubusercontent.com/wiki/portapack-mayhem/mayhem-firmware/img/hw_overview_h2_inside.png" height="400">](https://github.com/portapack-mayhem/mayhem-firmware/wiki/Hardware-overview#portapack-internals)
*[PortaPack H2+HackRF+battery](https://s.click.aliexpress.com/e/_DmU7GQX) (clone) with a custom [3d printed case](https://github.com/eried/portapack-mayhem/wiki/H2-Enclosure)*
*[PortaPack H2+HackRF+battery](https://s.click.aliexpress.com/e/_DmU7GQX) (clone) with a custom [3d printed case](https://github.com/portapack-mayhem/mayhem-firmware/wiki/H2-Enclosure)*
# What is this?
@@ -21,11 +21,11 @@ For people familiar with the [Flipper Zero](https://github.com/flipperdevices/fl
# Frequently Asked Questions
This repository expands upon the previous work by many people and aims to constantly add new features, bugfixes and generate documentation to make further development easier. [Collaboration](https://github.com/eried/portapack-mayhem/wiki/How-to-collaborate) is always welcomed and appreciated.
This repository expands upon the previous work by many people and aims to constantly add new features, bugfixes and generate documentation to make further development easier. [Collaboration](https://github.com/portapack-mayhem/mayhem-firmware/wiki/How-to-collaborate) is always welcomed and appreciated.
## What to buy?
:heavy_check_mark: A recommended one is this [PortaPack H2](https://s.click.aliexpress.com/e/_DmU7GQX), that includes everything you need with the plastic case "inspired" on [this](https://github.com/eried/portapack-mayhem/wiki/H2-Enclosure).
:heavy_check_mark: A recommended one is this [PortaPack H2](https://s.click.aliexpress.com/e/_DmU7GQX), that includes everything you need with the plastic case "inspired" on [this](https://github.com/portapack-mayhem/mayhem-firmware/wiki/H2-Enclosure).
:heavy_check_mark: Our friends at OpenSourceSDRLab give away five units every three months in our discord (check the badge on top) of their [PortaPack H2](https://www.aliexpress.com/item/4000247041639.html?gatewayAdapt=4itemAdapt), you can support them too by ordering.
@@ -35,33 +35,33 @@ This repository expands upon the previous work by many people and aims to consta
![image](https://user-images.githubusercontent.com/1091420/214579017-9ad970b9-0917-48f6-a550-588226d3f89b.png)
:warning: If it looks **too different**, this might mean that they are using their own recipe, check the [different models](https://github.com/eried/portapack-mayhem/wiki/PortaPack-Versions) in our wiki. For example all the H3 and clones of that version use their own version of the firmware. They do not contribute the changes back and eventually you will be left with a device that nobody maintains:
:warning: If it looks **too different**, this might mean that they are using their own recipe, check the [different models](https://github.com/portapack-mayhem/mayhem-firmware/wiki/PortaPack-Versions) in our wiki. For example all the H3 and clones of that version use their own version of the firmware. They do not contribute the changes back and eventually you will be left with a device that nobody maintains:
![image](https://user-images.githubusercontent.com/1091420/214581333-424900ee-26f8-4e96-be2f-69d8dc995ba9.png)
## Where is the latest version?
The current **stable release** is on the [![GitHub release (latest by date)](https://img.shields.io/github/v/release/eried/portapack-mayhem?label=Releases&style=social)](https://github.com/eried/portapack-mayhem/releases/latest) page. Follow the instructions you can find in the release description. The **latest (nightly) release** can be found [here](https://github.com/eried/portapack-mayhem/releases/).
The current **stable release** is on the [![GitHub release (latest by date)](https://img.shields.io/github/v/release/portapack-mayhem/mayhem-firmware?label=Releases&style=social)](https://github.com/portapack-mayhem/mayhem-firmware/releases/latest) page. Follow the instructions you can find in the release description. The **latest (nightly) release** can be found [here](https://github.com/portapack-mayhem/mayhem-firmware/releases/).
## How can I collaborate
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-collaborate) with details.
You can write [documentation](https://github.com/portapack-mayhem/mayhem-firmware/wiki), fix bugs and [answer issues](https://github.com/portapack-mayhem/mayhem-firmware/issues) or add new functionality. Please check the following [guide](https://github.com/portapack-mayhem/mayhem-firmware/wiki/How-to-collaborate) 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 collaborating your time and effort first. For coding related questions, if something does not fit as an issue, please join our Discord by clicking the chat badge on [top](#portapack-mayhem).
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/portapack-mayhem/mayhem-firmware/graphs/contributors), so always try collaborating your time and effort first. For coding related questions, if something does not fit as an issue, please join our Discord by clicking the chat badge on [top](#portapack-mayhem).
[![Contributors](https://contrib.rocks/image?repo=eried/portapack-mayhem)](https://github.com/eried/portapack-mayhem/graphs/contributors)
[![Contributors](https://contrib.rocks/image?repo=portapack-mayhem/mayhem-firmware)](https://github.com/portapack-mayhem/mayhem-firmware/graphs/contributors)
To support the people behind the hardware, please buy a genuine [HackRF](https://greatscottgadgets.com/hackrf/) and [PortaPack](https://store.sharebrained.com/products/portapack-for-hackrf-one-kit).
## What if I really want something specific?
If what you need can be relevant in general, you can [request a feature](https://github.com/eried/portapack-mayhem/issues/new?labels=enhancement&template=feature_request.md).
If what you need can be relevant in general, you can [request a feature](https://github.com/portapack-mayhem/mayhem-firmware/issues/new?labels=enhancement&template=feature_request.md).
<del>You can create a bounty and invite people to your own bounty. This will incentivize coders to work on a new feature, solving a bug or even writting documentation. Start a bounty by [creating](https://github.com/eried/portapack-mayhem/issues/new/choose) or [choosing](https://github.com/eried/portapack-mayhem/issues/) an existing issue. Then, go to [Bountysource](https://www.bountysource.com/) and post a bounty using the link to that specific [issue](https://www.bountysource.com/teams/portapack-mayhem/issues).</del>
<del>You can create a bounty and invite people to your own bounty. This will incentivize coders to work on a new feature, solving a bug or even writting documentation. Start a bounty by [creating](https://github.com/portapack-mayhem/mayhem-firmware/issues/new/choose) or [choosing](https://github.com/portapack-mayhem/mayhem-firmware/issues/) an existing issue. Then, go to [Bountysource](https://www.bountysource.com/) and post a bounty using the link to that specific [issue](https://www.bountysource.com/teams/portapack-mayhem/issues).</del>
<del>Promote your bounty over our Discord by clicking the chat badge on [top](#portapack-mayhem).</del>
Bountysource has not been reliable lately, so until this changes, please **DO NOT** post a bounty there. Go to our Discord by clicking the chat badge on [top](#portapack-mayhem) and discuss there.
## 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).
First, check the [documentation](https://github.com/portapack-mayhem/mayhem-firmware/wiki). If you find a bug or you think the problem is related to the current repository, please open an [issue](https://github.com/portapack-mayhem/mayhem-firmware/issues/new/choose).
You can reach the [official community](https://www.facebook.com/groups/177623356165819) in Facebook, and our Discord by clicking the chat badge on [top](#portapack-mayhem).
+2 -2
View File
@@ -1,6 +1,6 @@
<head>
<meta http-equiv="refresh" content="0; URL=https://github.com/eried/portapack-mayhem/" />
<meta http-equiv="refresh" content="0; URL=https://github.com/portapack-mayhem/mayhem-firmware/" />
</head>
<body>
<p>If you are not redirected, <a href="https://github.com/eried/portapack-mayhem/">click here</a>.</p>
<p>If you are not redirected, <a href="https://github.com/portapack-mayhem/mayhem-firmware/">click here</a>.</p>
</body>
+3 -1
View File
@@ -116,7 +116,7 @@ set(CSRC
usb_serial_cdc.c
usb_serial_descriptor.c
usb_serial_endpoints.c
usb_serial_io.c
usb_serial_device_to_host.c
${HACKRF_PATH}/firmware/common/usb.c
${HACKRF_PATH}/firmware/common/usb_queue.c
${HACKRF_PATH}/firmware/hackrf_usb/usb_device.c
@@ -203,9 +203,11 @@ set(CPPSRC
metadata_file.cpp
portapack.cpp
usb_serial_shell.cpp
usb_serial_shell_filesystem.cpp
usb_serial_event.cpp
usb_serial_thread.cpp
usb_serial.cpp
usb_serial_host_to_device.cpp
qrcodegen.cpp
radio.cpp
receiver_model.cpp
+2 -2
View File
@@ -40,7 +40,7 @@ using namespace portapack;
namespace {
fs::path get_settings_path(const std::string& app_name) {
return fs::path{u"/SETTINGS"} / app_name + u".ini";
return fs::path{SETTINGS_DIR} / app_name + u".ini";
}
} // namespace
@@ -156,7 +156,7 @@ bool save_settings(std::string_view store_name, const SettingBindings& bindings)
File f;
auto path = get_settings_path(std::string{store_name});
make_new_directory(SETTINGS_DIR);
ensure_directory(SETTINGS_DIR);
auto error = f.create(path);
if (error)
return false;
+5 -1
View File
@@ -26,6 +26,7 @@
#include "string_format.hpp"
#include "tonesets.hpp"
#include "ui_tone_key.hpp"
#include "audio.hpp"
using namespace tonekey;
using namespace portapack;
@@ -40,6 +41,7 @@ void SoundBoardView::stop() {
if (is_active())
replay_thread.reset();
audio::output::stop();
transmitter_model.disable();
tx_view.set_transmitting(false);
@@ -123,6 +125,8 @@ void SoundBoardView::start_tx(const uint32_t id) {
transmitter_model.enable();
tx_view.set_transmitting(true);
audio::output::start();
}
/*void SoundBoardView::show_infos() {
@@ -227,6 +231,7 @@ SoundBoardView::SoundBoardView(
//&text_title,
//&text_duration,
//&progressbar,
&field_volume,
&page_info,
&check_loop,
&check_random,
@@ -274,7 +279,6 @@ SoundBoardView::SoundBoardView(
SoundBoardView::~SoundBoardView() {
stop();
transmitter_model.disable();
baseband::shutdown();
}
+5 -2
View File
@@ -91,7 +91,7 @@ class SoundBoardView : public View {
void on_select_entry();
Labels labels{
//{ { 0, 20 * 8 + 4 }, "Title:", Color::light_grey() },
{{24 * 8, 180}, "Vol:", Color::light_grey()},
{{0, 180}, "Key:", Color::light_grey()}};
Button button_next_page{
@@ -122,10 +122,13 @@ class SoundBoardView : public View {
};*/
OptionsField options_tone_key{
{32, 180},
{4 * 8, 180},
18,
{}};
AudioVolumeField field_volume{
{28 * 8, 180}};
Checkbox check_loop{
{0, 25 * 8 + 4},
4,
@@ -19,7 +19,7 @@ void AboutView::update() {
switch (++frame) {
case 1:
// TODO: Generate this automatically from github
// https://github.com/eried/portapack-mayhem/graphs/contributors?to=2022-01-01&from=2020-04-12&type=c
// 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");
@@ -42,7 +42,7 @@ void AboutView::update() {
break;
case 3:
// https://github.com/eried/portapack-mayhem/graphs/contributors?to=2020-04-12&from=2015-07-31&type=c
// 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");
@@ -55,7 +55,7 @@ void AboutView::update() {
break;
case 4:
// https://github.com/eried/portapack-mayhem/graphs/contributors?from=2014-07-05&to=2015-07-31&type=c
// 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("");
+11
View File
@@ -318,6 +318,17 @@ bool ADSBRxDetailsView::add_map_marker(const AircraftRecentEntry& entry) {
return markerStored == MARKER_STORED;
}
void ADSBRxDetailsView::on_gps(const GPSPosDataMessage* msg) {
if (!geomap_view_)
return;
geomap_view_->update_my_position(msg->lat, msg->lon, msg->altitude);
}
void ADSBRxDetailsView::on_orientation(const OrientationDataMessage* msg) {
if (!geomap_view_)
return;
geomap_view_->update_my_orientation(msg->angle);
}
void ADSBRxDetailsView::refresh_ui() {
auto age = entry_.age;
if (age < 60)
+15
View File
@@ -271,6 +271,8 @@ class ADSBRxDetailsView : public View {
private:
void refresh_ui();
void on_gps(const GPSPosDataMessage* msg);
void on_orientation(const OrientationDataMessage* msg);
GeoMapView* geomap_view_{nullptr};
ADSBRxAircraftDetailsView* aircraft_details_view_{nullptr};
@@ -330,6 +332,19 @@ class ADSBRxDetailsView : public View {
Button button_see_map{
{16 * 8, 9 * 16, 12 * 8, 3 * 16},
"See on map"};
MessageHandlerRegistration message_handler_gps{
Message::ID::GPSPosData,
[this](Message* const p) {
const auto message = static_cast<const GPSPosDataMessage*>(p);
this->on_gps(message);
}};
MessageHandlerRegistration message_handler_orientation{
Message::ID::OrientationData,
[this](Message* const p) {
const auto message = static_cast<const OrientationDataMessage*>(p);
this->on_orientation(message);
}};
};
/* Main ADSB application view and message dispatch. */
+12 -10
View File
@@ -48,7 +48,7 @@ void DfuMenu::paint(Painter& painter) {
text_info_line_3.set(to_string_dec_uint(utilisation, 6));
text_info_line_4.set(to_string_dec_uint(shared_memory.m4_heap_usage, 6));
text_info_line_5.set(to_string_dec_uint(shared_memory.m4_stack_usage, 6));
text_info_line_6.set(to_string_dec_uint(shared_memory.m4_cpu_usage, 6));
text_info_line_6.set(to_string_dec_uint(shared_memory.m4_performance_counter, 6));
text_info_line_7.set(to_string_dec_uint(shared_memory.m4_buffer_missed, 6));
text_info_line_8.set(to_string_dec_uint(chTimeNow() / 1000, 6));
@@ -94,23 +94,25 @@ DfuMenu2::DfuMenu2(NavigationView& nav)
&text_info_line_7,
&text_info_line_8,
&text_info_line_9,
&text_info_line_10});
&text_info_line_10,
&text_info_line_11});
}
void DfuMenu2::paint(Painter& painter) {
text_info_line_1.set(to_string_dec_uint(portapack::receiver_model.target_frequency(), 10));
text_info_line_2.set(to_string_dec_uint(portapack::receiver_model.baseband_bandwidth(), 10));
text_info_line_3.set(to_string_dec_uint(portapack::receiver_model.sampling_rate(), 10));
text_info_line_4.set(to_string_dec_uint((uint32_t)portapack::receiver_model.modulation(), 10));
text_info_line_5.set(to_string_dec_uint(portapack::receiver_model.am_configuration(), 10));
text_info_line_6.set(to_string_dec_uint(portapack::receiver_model.nbfm_configuration(), 10));
text_info_line_7.set(to_string_dec_uint(portapack::receiver_model.wfm_configuration(), 10));
text_info_line_8.set(to_string_dec_uint(portapack::transmitter_model.target_frequency(), 10));
text_info_line_9.set(to_string_dec_uint(portapack::transmitter_model.baseband_bandwidth(), 10));
text_info_line_10.set(to_string_dec_uint(portapack::transmitter_model.sampling_rate(), 10));
text_info_line_4.set(to_string_dec_uint(((uint32_t)shared_memory.m4_performance_counter) * 100 / 127, 10));
text_info_line_5.set(to_string_dec_uint((uint32_t)portapack::receiver_model.modulation(), 10));
text_info_line_6.set(to_string_dec_uint(portapack::receiver_model.am_configuration(), 10));
text_info_line_7.set(to_string_dec_uint(portapack::receiver_model.nbfm_configuration(), 10));
text_info_line_8.set(to_string_dec_uint(portapack::receiver_model.wfm_configuration(), 10));
text_info_line_9.set(to_string_dec_uint(portapack::transmitter_model.target_frequency(), 10));
text_info_line_10.set(to_string_dec_uint(portapack::transmitter_model.baseband_bandwidth(), 10));
text_info_line_11.set(to_string_dec_uint(portapack::transmitter_model.sampling_rate(), 10));
constexpr auto margin = 5;
constexpr auto lines = 10 + 2;
constexpr auto lines = 11 + 2;
painter.fill_rectangle(
{{5 * CHARACTER_WIDTH - margin, 3 * LINE_HEIGHT - margin},
+10 -7
View File
@@ -83,13 +83,15 @@ class DfuMenu2 : public View {
{{5 * CHARACTER_WIDTH, 5 * LINE_HEIGHT}, "RX Freq:", Color::dark_cyan()},
{{5 * CHARACTER_WIDTH, 6 * LINE_HEIGHT}, "RX BW:", Color::dark_cyan()},
{{5 * CHARACTER_WIDTH, 7 * LINE_HEIGHT}, "RX SampR:", Color::dark_cyan()},
{{5 * CHARACTER_WIDTH, 8 * LINE_HEIGHT}, "Modulatn:", Color::dark_cyan()},
{{5 * CHARACTER_WIDTH, 9 * LINE_HEIGHT}, "AM cfg:", Color::dark_cyan()},
{{5 * CHARACTER_WIDTH, 10 * LINE_HEIGHT}, "NBFM cfg:", Color::dark_cyan()},
{{5 * CHARACTER_WIDTH, 11 * LINE_HEIGHT}, "WFM cfg:", Color::dark_cyan()},
{{5 * CHARACTER_WIDTH, 12 * LINE_HEIGHT}, "TX Freq:", Color::dark_cyan()},
{{5 * CHARACTER_WIDTH, 13 * LINE_HEIGHT}, "TX BW:", Color::dark_cyan()},
{{5 * CHARACTER_WIDTH, 14 * LINE_HEIGHT}, "TX SampR:", Color::dark_cyan()}};
{{5 * CHARACTER_WIDTH, 8 * LINE_HEIGHT}, "RX Satu%:", Color::dark_cyan()},
{{5 * CHARACTER_WIDTH, 9 * LINE_HEIGHT}, "Modulatn:", Color::dark_cyan()},
{{5 * CHARACTER_WIDTH, 10 * LINE_HEIGHT}, "AM cfg:", Color::dark_cyan()},
{{5 * CHARACTER_WIDTH, 11 * LINE_HEIGHT}, "NBFM cfg:", Color::dark_cyan()},
{{5 * CHARACTER_WIDTH, 12 * LINE_HEIGHT}, "WFM cfg:", Color::dark_cyan()},
{{5 * CHARACTER_WIDTH, 13 * LINE_HEIGHT}, "TX Freq:", Color::dark_cyan()},
{{5 * CHARACTER_WIDTH, 14 * LINE_HEIGHT}, "TX BW:", Color::dark_cyan()},
{{5 * CHARACTER_WIDTH, 15 * LINE_HEIGHT}, "TX SampR:", Color::dark_cyan()},
};
Text text_info_line_1{{14 * CHARACTER_WIDTH, 5 * LINE_HEIGHT, 10 * CHARACTER_WIDTH, 1 * LINE_HEIGHT}, ""};
Text text_info_line_2{{14 * CHARACTER_WIDTH, 6 * LINE_HEIGHT, 10 * CHARACTER_WIDTH, 1 * LINE_HEIGHT}, ""};
@@ -101,6 +103,7 @@ class DfuMenu2 : public View {
Text text_info_line_8{{14 * CHARACTER_WIDTH, 12 * LINE_HEIGHT, 10 * CHARACTER_WIDTH, 1 * LINE_HEIGHT}, ""};
Text text_info_line_9{{14 * CHARACTER_WIDTH, 13 * LINE_HEIGHT, 10 * CHARACTER_WIDTH, 1 * LINE_HEIGHT}, ""};
Text text_info_line_10{{14 * CHARACTER_WIDTH, 14 * LINE_HEIGHT, 10 * CHARACTER_WIDTH, 1 * LINE_HEIGHT}, ""};
Text text_info_line_11{{14 * CHARACTER_WIDTH, 15 * LINE_HEIGHT, 10 * CHARACTER_WIDTH, 1 * LINE_HEIGHT}, ""};
};
} /* namespace ui */
-2
View File
@@ -54,8 +54,6 @@
namespace ui {
#define RECON_CFG_FILE u"SETTINGS/recon.cfg"
enum class recon_mode : uint8_t {
Recon,
Scanner,
+1 -1
View File
@@ -275,7 +275,7 @@ ScannerView::~ScannerView() {
}
void ScannerView::show_max_index() { // show total number of freqs to scan
field_current_index.set_text("---");
field_current_index.set_text("<->");
if (entries.size() == FREQMAN_MAX_PER_FILE) {
text_max_index.set_style(&Styles::red);
+30
View File
@@ -27,6 +27,7 @@
#include "ui_navigation.hpp"
#include "ui_receiver.hpp"
#include "ui_touch_calibration.hpp"
#include "ui_text_editor.hpp"
#include "portapack_persistent_memory.hpp"
#include "lpc43xx_cpp.hpp"
@@ -628,6 +629,34 @@ void SetEncoderDialView::focus() {
button_save.focus();
}
/* AppSettingsView ************************************/
AppSettingsView::AppSettingsView(
NavigationView& nav)
: nav_{nav} {
add_children({&labels,
&menu_view});
menu_view.set_parent_rect({0, 3 * 8, 240, 33 * 8});
ensure_directory(SETTINGS_DIR);
for (const auto& entry : std::filesystem::directory_iterator(SETTINGS_DIR, u"*.ini")) {
auto path = (std::filesystem::path)SETTINGS_DIR / entry.path();
menu_view.add_item({path.filename().string().substr(0, 26),
ui::Color::dark_cyan(),
&bitmap_icon_file_text,
[this, path](KeyEvent) {
nav_.push<TextEditorView>(path);
}});
}
}
void AppSettingsView::focus() {
menu_view.focus();
}
/* SettingsMenuView **************************************/
SettingsMenuView::SettingsMenuView(NavigationView& nav) {
@@ -635,6 +664,7 @@ SettingsMenuView::SettingsMenuView(NavigationView& nav) {
add_items({{"..", ui::Color::light_grey(), &bitmap_icon_previous, [&nav]() { nav.pop(); }}});
}
add_items({
{"App Settings", ui::Color::dark_cyan(), &bitmap_icon_notepad, [&nav]() { nav.push<AppSettingsView>(); }},
{"Audio", ui::Color::dark_cyan(), &bitmap_icon_speaker, [&nav]() { nav.push<SetAudioView>(); }},
{"Calibration", ui::Color::dark_cyan(), &bitmap_icon_options_touch, [&nav]() { nav.push<TouchCalibrationView>(); }},
{"Converter", ui::Color::dark_cyan(), &bitmap_icon_options_radio, [&nav]() { nav.push<SetConverterSettingsView>(); }},
+17
View File
@@ -564,6 +564,23 @@ class SetPersistentMemoryView : public View {
};
};
class AppSettingsView : public View {
public:
AppSettingsView(NavigationView& nav);
std::string title() const override { return "App Settings"; };
void focus() override;
private:
NavigationView& nav_;
Labels labels{
{{0, 4}, "Select file to edit:", Color::white()}};
MenuView menu_view{
{0, 2 * 8, 240, 26 * 8},
true};
};
class SettingsMenuView : public BtnGridView {
public:
SettingsMenuView(NavigationView& nav);
+15 -1
View File
@@ -90,7 +90,7 @@ SondeView::SondeView(NavigationView& nav)
};
button_see_map.on_select = [this, &nav](Button&) {
nav.push<GeoMapView>(
geomap_view_ = nav.push<GeoMapView>(
sonde_id,
gps_info.alt,
GeoPos::alt_unit::METERS,
@@ -98,6 +98,9 @@ SondeView::SondeView(NavigationView& nav)
gps_info.lat,
gps_info.lon,
999); // set a dummy heading out of range to draw a cross...probably not ideal?
nav.set_on_pop([this]() {
geomap_view_ = nullptr;
});
};
logger = std::make_unique<SondeLogger>();
@@ -124,6 +127,17 @@ SondeView::~SondeView() {
audio::output::stop();
}
void SondeView::on_gps(const GPSPosDataMessage* msg) {
if (!geomap_view_)
return;
geomap_view_->update_my_position(msg->lat, msg->lon, msg->altitude);
}
void SondeView::on_orientation(const OrientationDataMessage* msg) {
if (!geomap_view_)
return;
geomap_view_->update_my_orientation(msg->angle, true);
}
void SondeView::focus() {
field_frequency.focus();
}
+19
View File
@@ -60,6 +60,8 @@ class SondeView : public View {
SondeView(NavigationView& nav);
~SondeView();
SondeView(const SondeView& other) = delete;
SondeView& operator=(const SondeView& other) = delete;
void focus() override;
@@ -173,6 +175,8 @@ class SondeView : public View {
{16 * 8, 15 * 16, 12 * 8, 3 * 16},
"See on map"};
GeoMapView* geomap_view_{nullptr};
MessageHandlerRegistration message_handler_packet{
Message::ID::SondePacket,
[this](Message* const p) {
@@ -181,6 +185,21 @@ class SondeView : public View {
this->on_packet(packet);
}};
MessageHandlerRegistration message_handler_gps{
Message::ID::GPSPosData,
[this](Message* const p) {
const auto message = static_cast<const GPSPosDataMessage*>(p);
this->on_gps(message);
}};
MessageHandlerRegistration message_handler_orientation{
Message::ID::OrientationData,
[this](Message* const p) {
const auto message = static_cast<const OrientationDataMessage*>(p);
this->on_orientation(message);
}};
void on_gps(const GPSPosDataMessage* msg);
void on_orientation(const OrientationDataMessage* msg);
void on_packet(const sonde::Packet& packet);
char* float_to_char(float x, char* p);
};
+1 -1
View File
@@ -275,7 +275,7 @@ bool memory_dump(uint32_t* addr_start, uint32_t num_words, bool stack_flag) {
int n{0};
bool data_found{false};
make_new_directory(debug_dir);
ensure_directory(debug_dir);
filename = next_filename_matching_pattern(debug_dir + "/" + (stack_flag ? "STACK" : "MEMORY") + "_DUMP_????.TXT");
error = filename.empty();
if (!error)
+68 -3
View File
@@ -113,7 +113,6 @@ void EventDispatcher::run() {
while (is_running) {
const auto events = wait();
dispatch(events);
portapack::usb_serial.dispatch();
}
}
@@ -151,6 +150,8 @@ void EventDispatcher::dispatch(const eventmask_t events) {
*(uint32_t*)&shared_memory.bb_data.data[4]);
}
handle_shell();
if (events & EVT_MASK_APPLICATION) {
handle_application_queue();
}
@@ -163,6 +164,9 @@ void EventDispatcher::dispatch(const eventmask_t events) {
handle_rtc_tick();
}
handle_usb_transfer();
handle_usb();
if (events & EVT_MASK_SWITCHES) {
handle_switches();
}
@@ -216,6 +220,34 @@ void EventDispatcher::handle_rtc_tick() {
portapack::persistent_memory::cache::persist();
}
void EventDispatcher::handle_usb() {
portapack::usb_serial.dispatch();
}
void EventDispatcher::handle_usb_transfer() {
portapack::usb_serial.dispatch_transfer();
}
void EventDispatcher::handle_shell() {
if (waiting_for_shellmode) {
waiting_for_shellmode = false;
shellmode_active = true;
while (shellmode_active) {
chThdSleepMilliseconds(5);
}
}
if (injected_touch_event != nullptr) {
on_touch_event(*injected_touch_event);
injected_touch_event = nullptr;
}
if (injected_keyboard_event != nullptr) {
on_keyboard_event(*injected_keyboard_event);
injected_keyboard_event = nullptr;
}
}
ui::Widget* EventDispatcher::touch_widget(ui::Widget* const w, ui::TouchEvent event) {
if (!w->hidden()) {
// To achieve reverse depth ordering (last object drawn is
@@ -239,11 +271,17 @@ ui::Widget* EventDispatcher::touch_widget(ui::Widget* const w, ui::TouchEvent ev
}
void EventDispatcher::emulateTouch(ui::TouchEvent event) {
on_touch_event(event);
injected_touch_event = &event;
while (injected_touch_event != nullptr) {
chThdSleepMilliseconds(5);
}
}
void EventDispatcher::emulateKeyboard(ui::KeyboardEvent event) {
on_keyboard_event(event);
injected_keyboard_event = &event;
while (injected_keyboard_event != nullptr) {
chThdSleepMilliseconds(5);
}
}
void EventDispatcher::on_keyboard_event(ui::KeyboardEvent event) {
@@ -283,6 +321,8 @@ ui::Widget* EventDispatcher::getFocusedWidget() {
}
void EventDispatcher::handle_lcd_frame_sync() {
bool waiting_for_frame = this->waiting_for_frame;
DisplayFrameSyncMessage message;
message_map.send(&message);
@@ -290,6 +330,28 @@ void EventDispatcher::handle_lcd_frame_sync() {
painter.paint_widget_tree(top_widget);
portapack::backlight()->on();
if (waiting_for_frame)
this->waiting_for_frame = false;
}
void EventDispatcher::wait_finish_frame() {
waiting_for_frame = true;
while (waiting_for_frame) {
chThdSleepMilliseconds(5);
}
}
void EventDispatcher::enter_shell_working_mode() {
waiting_for_shellmode = true;
while (waiting_for_shellmode) {
chThdSleepMilliseconds(5);
}
}
void EventDispatcher::exit_shell_working_mode() {
shellmode_active = false;
}
void EventDispatcher::handle_switches() {
@@ -351,6 +413,9 @@ void EventDispatcher::handle_encoder() {
const uint32_t encoder_now = get_encoder_position();
const int32_t delta = static_cast<int32_t>(encoder_now - encoder_last);
if (delta == 0)
return;
encoder_last = encoder_now;
const auto event = static_cast<ui::EncoderEvent>(delta);
event_bubble_encoder(event);
+13
View File
@@ -45,6 +45,7 @@ constexpr auto EVT_MASK_ENCODER = EVENT_MASK(4);
constexpr auto EVT_MASK_TOUCH = EVENT_MASK(5);
constexpr auto EVT_MASK_APPLICATION = EVENT_MASK(6);
constexpr auto EVT_MASK_LOCAL = EVENT_MASK(7);
constexpr auto EVT_MASK_USB = EVENT_MASK(8);
class EventDispatcher {
public:
@@ -89,6 +90,10 @@ class EventDispatcher {
void emulateTouch(ui::TouchEvent event);
void emulateKeyboard(ui::KeyboardEvent event);
void wait_finish_frame();
void enter_shell_working_mode();
void exit_shell_working_mode();
ui::Widget* getTopWidget();
ui::Widget* getFocusedWidget();
@@ -104,6 +109,11 @@ class EventDispatcher {
bool sd_card_present = false;
static bool display_sleep;
bool in_key_event = false;
volatile bool waiting_for_frame = false;
volatile bool waiting_for_shellmode = false;
volatile bool shellmode_active = false;
ui::TouchEvent* volatile injected_touch_event = nullptr;
ui::KeyboardEvent* volatile injected_keyboard_event = nullptr;
eventmask_t wait();
void dispatch(const eventmask_t events);
@@ -111,6 +121,9 @@ class EventDispatcher {
void handle_application_queue();
void handle_local_queue();
void handle_rtc_tick();
void handle_usb();
void handle_usb_transfer();
void handle_shell();
static ui::Widget* touch_widget(ui::Widget* const w, ui::TouchEvent event);
+21 -7
View File
@@ -205,11 +205,13 @@ class Sprite {
byte who;
byte _speed;
byte dir;
byte lastDir;
byte phase;
// Sprite bits
byte palette2; // 4->16 color map index
byte bits; // index of sprite bits
signed char sy;
void Init(const byte* s) {
@@ -274,9 +276,17 @@ class Sprite {
f = pgm_read_byte(_pacLeftAnim + f);
else if (dir == MRight)
f = pgm_read_byte(_pacRightAnim + f);
else
else if (dir == MDown || dir == MUp)
f = pgm_read_byte(_pacVAnim + f);
if (dir == MUp)
else if (dir == MStopped) {
if (lastDir == MLeft)
f = pgm_read_byte(_pacLeftAnim + f);
else if (lastDir == MRight)
f = pgm_read_byte(_pacRightAnim + f);
else if (lastDir == MDown || lastDir == MUp)
f = pgm_read_byte(_pacVAnim + f);
}
if ((dir == MUp) || (dir == MStopped && lastDir == MUp))
sy = -1;
bits = f + PACMANSPRITE;
}
@@ -838,15 +848,19 @@ class Playfield {
else if (DEMO == 0 && s->who == PACMAN && choice[3] < 0x7FFF && but_RIGHT)
dir = MRight;
else if (DEMO == 0 && choice[0] < 0x7FFF && s->who == PACMAN && dir == MUp)
else if (DEMO == 0 && choice[0] < 0x7FFF && s->who == PACMAN && dir == MUp) {
dir = MUp;
else if (DEMO == 0 && choice[1] < 0x7FFF && s->who == PACMAN && dir == MLeft)
s->lastDir = MUp;
} else if (DEMO == 0 && choice[1] < 0x7FFF && s->who == PACMAN && dir == MLeft) {
dir = MLeft;
else if (DEMO == 0 && choice[2] < 0x7FFF && s->who == PACMAN && dir == MDown)
s->lastDir = MLeft;
} else if (DEMO == 0 && choice[2] < 0x7FFF && s->who == PACMAN && dir == MDown) {
dir = MDown;
else if (DEMO == 0 && choice[3] < 0x7FFF && s->who == PACMAN && dir == MRight)
s->lastDir = MDown;
} else if (DEMO == 0 && choice[3] < 0x7FFF && s->who == PACMAN && dir == MRight) {
dir = MRight;
else if ((DEMO == 0 && s->who != PACMAN) || DEMO == 1) {
s->lastDir = MRight;
} else if ((DEMO == 0 && s->who != PACMAN) || DEMO == 1) {
// Don't choose opposite of current direction?
int16_t dist = choice[4 - dir]; // favor current direction
+1 -1
View File
@@ -177,7 +177,7 @@ enum class PortaPackModel {
static bool save_config(int8_t value) {
persistent_memory::set_config_cpld(value);
if (sd_card::status() == sd_card::Status::Mounted) {
make_new_directory("/hardware");
ensure_directory("/hardware");
File file;
auto sucess = file.create("/hardware/settings.txt");
if (!sucess.is_valid()) {
+2 -10
View File
@@ -116,16 +116,8 @@ void set_direction(const rf::Direction new_direction) {
/* TODO: Refactor all the various "Direction" enumerations into one. */
/* TODO: Only make changes if direction changes, but beware of clock enabling. */
// Hack to fix the CPLD (clocking ?) bug: toggle CPLD SRAM overlay depending on new direction.
// Use CPLD's EEPROM config when transmitting
// Use the SRAM overlay when receiving
if (direction != new_direction) {
if (new_direction == rf::Direction::Transmit)
hackrf::cpld::init_from_eeprom();
else
// Prevents ghosting when switching back to RX from TX mode.
hackrf::cpld::load_sram_no_verify();
}
// Prevents ghosting when switching back to RX from TX mode.
hackrf::cpld::load_sram_no_verify();
direction = new_direction;
+58
View File
@@ -305,6 +305,7 @@ void GeoMap::paint(Painter& painter) {
// Draw the other markers
draw_markers(painter);
draw_scale(painter);
draw_mypos();
markerListUpdated = false;
set_clean();
}
@@ -447,6 +448,41 @@ void GeoMap::draw_marker(Painter& painter, const ui::Point itemPoint, const uint
}
}
void GeoMap::draw_mypos() {
const auto r = screen_rect();
if (my_lat >= 200 || my_lon >= 200) return; // invalid
int x = (map_width * (my_lon + 180) / 360) - x_pos;
double lat_rad = sin(my_lat * pi / 180);
int y = (map_height - ((map_world_lon / 2 * log((1 + lat_rad) / (1 - lat_rad))) - map_offset)) - y_pos; // Offset added for the GUI
auto color = Color::yellow();
if (map_zoom > 1) {
x = ((x - (r.width() / 2)) * map_zoom) + (r.width() / 2);
y = ((y - (r.height() / 2)) * map_zoom) + (r.height() / 2);
} else if (map_zoom < 0) {
x = ((x - (r.width() / 2)) / (-map_zoom)) + (r.width() / 2);
y = ((y - (r.height() / 2)) / (-map_zoom)) + (r.height() / 2);
}
if ((x >= 0) && (x < r.width()) &&
(y > 10) && (y < r.height())) // Dont draw within symbol size of top
{
ui::Point itemPoint(x, y + r.top());
if (mode_ == PROMPT) {
// Cross
display.fill_rectangle({itemPoint - Point(16, 1), {32, 2}}, color);
display.fill_rectangle({itemPoint - Point(1, 16), {2, 32}}, color);
} else if (my_angle < 360) {
// if we have a valid angle draw bearing
draw_bearing(itemPoint, my_angle, 10, color);
} else {
// draw a small cross
display.fill_rectangle({itemPoint - Point(8, 1), {16, 2}}, color);
display.fill_rectangle({itemPoint - Point(1, 8), {2, 16}}, color);
}
}
}
void GeoMap::clear_markers() {
markerListLen = 0;
}
@@ -473,6 +509,21 @@ MapMarkerStored GeoMap::store_marker(GeoMarker& marker) {
return ret;
}
void GeoMap::update_my_position(float lat, float lon, int32_t altitude) {
my_lat = lat;
my_lon = lon;
my_altitude = altitude;
markerListUpdated = true;
set_dirty();
}
void GeoMap::update_my_orientation(uint16_t angle, bool refresh) {
my_angle = angle;
if (refresh) {
markerListUpdated = true;
set_dirty();
}
}
void GeoMapView::focus() {
geopos.focus();
@@ -480,6 +531,13 @@ void GeoMapView::focus() {
nav_.display_modal("No map", "No world_map.bin file in\n/ADSB/ directory", ABORT);
}
void GeoMapView::update_my_position(float lat, float lon, int32_t altitude) {
geomap.update_my_position(lat, lon, altitude);
}
void GeoMapView::update_my_orientation(uint16_t angle, bool refresh) {
geomap.update_my_orientation(angle, refresh);
}
void GeoMapView::update_position(float lat, float lon, uint16_t angle, int32_t altitude, int32_t speed) {
if (geomap.manual_panning()) {
geomap.set_dirty();
+12
View File
@@ -185,6 +185,9 @@ class GeoMap : public Widget {
bool on_encoder(const EncoderEvent delta) override;
bool on_keyboard(const KeyboardEvent event) override;
void update_my_position(float lat, float lon, int32_t altitude);
void update_my_orientation(uint16_t angle, bool refresh = false);
bool init();
void set_mode(GeoMapMode mode);
void set_manual_panning(bool v);
@@ -212,6 +215,7 @@ class GeoMap : public Widget {
void draw_bearing(const Point origin, const uint16_t angle, uint32_t size, const Color color);
void draw_marker(Painter& painter, const ui::Point itemPoint, const uint16_t itemAngle, const std::string itemTag, const Color color = Color::red(), const Color fontColor = Color::white(), const Color backColor = Color::black());
void draw_markers(Painter& painter);
void draw_mypos();
void map_read_line(ui::Color* buffer, uint16_t pixels);
bool manual_panning_{false};
@@ -233,6 +237,12 @@ class GeoMap : public Widget {
uint16_t angle_{};
std::string tag_{};
// the portapack's position data ( for example injected from serial )
float my_lat{200};
float my_lon{200};
int32_t my_altitude{0};
uint16_t my_angle{400};
int markerListLen{0};
GeoMarker markerList[NumMarkerListElements];
bool markerListUpdated{false};
@@ -267,6 +277,8 @@ class GeoMapView : public View {
void focus() override;
void update_position(float lat, float lon, uint16_t angle, int32_t altitude, int32_t speed = 0);
void update_my_position(float lat, float lon, int32_t altitude);
void update_my_orientation(uint16_t angle, bool refresh = false);
std::string title() const override { return "Map view"; };
@@ -6,6 +6,44 @@ namespace ui {
/* static */ std::vector<DynamicBitmap<16, 16>> ExternalItemsMenuLoader::bitmaps;
// iterates over all ppma-s, and if it is runnable on the current system, it'll call the callback, and pass info.
/* static */ void ExternalItemsMenuLoader::load_all_external_items_callback(std::function<void(AppInfoConsole&)> callback) {
if (!callback) return;
if (sd_card::status() != sd_card::Status::Mounted)
return;
for (const auto& entry : std::filesystem::directory_iterator(u"APPS", u"*.ppma")) {
auto filePath = u"/APPS/" + entry.path();
File app;
auto openError = app.open(filePath);
if (openError)
continue;
application_information_t application_information = {};
auto readResult = app.read(&application_information, sizeof(application_information_t));
if (!readResult)
continue;
if (application_information.header_version != CURRENT_HEADER_VERSION)
continue;
bool versionMatches = VERSION_MD5 == application_information.app_version;
if (!versionMatches) continue;
// here the app is startable and good.
std::string appshortname = filePath.filename().string();
if (appshortname.size() >= 5 && appshortname.substr(appshortname.size() - 5) == ".ppma") {
// Remove the ".ppma" suffix
appshortname = appshortname.substr(0, appshortname.size() - 5);
}
AppInfoConsole info{
.appCallName = appshortname.c_str(),
.appFriendlyName = reinterpret_cast<char*>(&application_information.app_name[0]),
.appLocation = application_information.menu_location};
callback(info);
}
}
/* static */ std::vector<GridItem> ExternalItemsMenuLoader::load_external_items(app_location_t app_location, NavigationView& nav) {
bitmaps.clear();
@@ -47,7 +85,9 @@ namespace ui {
bitmaps.push_back(std::move(dyn_bmp));
gridItem.on_select = [&nav, app_location, filePath]() {
run_external_app(nav, filePath);
if (!run_external_app(nav, filePath)) {
nav.display_modal("Error", "The .ppma file in your APPS\nfolder can't be read. Please\nupdate your SD Card content.");
}
};
} else {
gridItem.color = Color::light_grey();
@@ -65,19 +105,19 @@ namespace ui {
return external_apps;
}
/* static */ void ExternalItemsMenuLoader::run_external_app(ui::NavigationView& nav, std::filesystem::path filePath) {
/* static */ bool ExternalItemsMenuLoader::run_external_app(ui::NavigationView& nav, std::filesystem::path filePath) {
File app;
auto openError = app.open(filePath);
if (openError)
chDbgPanic("file gone");
return false;
application_information_t application_information = {};
auto readResult = app.read(&application_information, sizeof(application_information_t));
if (!readResult)
chDbgPanic("no data");
return false;
app.seek(0);
@@ -93,7 +133,7 @@ namespace ui {
readResult = app.read(&application_information.memory_location[file_read_index], bytes_to_read);
if (!readResult)
chDbgPanic("read error");
return false;
if (readResult.value() < std::filesystem::max_file_block_size)
break;
@@ -114,7 +154,7 @@ namespace ui {
readResult = app.read(target_memory, bytes_to_read);
if (!readResult)
chDbgPanic("read error #2");
return false;
if (readResult.value() != bytes_to_read)
break;
@@ -126,7 +166,7 @@ namespace ui {
readResult = app.read(&application_information.memory_location[file_read_index], bytes_to_read);
if (!readResult)
chDbgPanic("read error #3");
return false;
if (readResult.value() < std::filesystem::max_file_block_size)
break;
@@ -134,6 +174,7 @@ namespace ui {
}
application_information.externalAppEntry(nav);
return true;
}
} // namespace ui
@@ -54,11 +54,11 @@ class ExternalItemsMenuLoader {
public:
static std::vector<GridItem> load_external_items(app_location_t, NavigationView&);
ExternalItemsMenuLoader() = delete;
static bool run_external_app(ui::NavigationView&, std::filesystem::path);
static void load_all_external_items_callback(std::function<void(AppInfoConsole&)> callback);
private:
static std::vector<DynamicBitmap<16, 16>> bitmaps;
static void run_external_app(ui::NavigationView&, std::filesystem::path);
};
} // namespace ui
+178 -3
View File
@@ -111,6 +111,169 @@ namespace pmem = portapack::persistent_memory;
namespace ui {
// When adding or removing apps from the Menu, please update it here:
std::vector<AppInfoConsole> NavigationView::fixedAppListFC = {
{"adsbrx", "ADS-B", RX},
{"ais", "AIS Boats", RX},
{"aprsrx", "APRS", RX},
{"audio", "Audio", RX},
{"blerx", "BLE Rx", RX},
{"ert", "ERT Meter", RX},
{"level", "Level", RX},
{"pocsagrx", "POCSAG", RX},
{"radiosnde", "Radiosnde", RX},
{"recon", "Recon", RX},
{"search", "Search", RX},
{"tpms", "TPMS Cars", RX},
{"weather", "Weather", RX},
{"subghzd", "SubGhzD", RX},
{"adsbtx", "ADS-B", TX},
{"aprstx", "APRS TX", TX},
{"bht", "BHT Xy/EP", TX},
{"bletx", "BLE Tx", TX},
{"morsetx", "Morse", TX},
{"ooktx", "OOK", TX},
{"pocsatx", "POCSAG TX", TX},
{"rdstx", "RDS TX", TX},
{"soundbrd", "Soundbrd", TX},
{"sstvtx", "SSTV", TX},
{"touchtune", "TouchTune", TX},
{"capture", "Capture", RX},
{"replay", "Replay", TX},
{"remote", "Remote", TX},
{"scanner", "Scanner", RX},
{"microphone", "Microphone", TX},
{"lookingglass", "Looking Glass", RX}};
bool NavigationView::StartAppByName(const char* name) {
home(false);
if (strcmp(name, "adsbrx") == 0) {
push<ADSBRxView>();
return true;
}
if (strcmp(name, "ais") == 0) {
push<AISAppView>();
return true;
}
if (strcmp(name, "aprsrx") == 0) {
push<APRSRXView>();
return true;
}
if (strcmp(name, "audio") == 0) {
push<AnalogAudioView>();
return true;
}
if (strcmp(name, "blerx") == 0) {
push<BLERxView>();
return true;
}
if (strcmp(name, "ert") == 0) {
push<ERTAppView>();
return true;
}
if (strcmp(name, "level") == 0) {
push<LevelView>();
return true;
}
if (strcmp(name, "pocsagrx") == 0) {
push<POCSAGAppView>();
return true;
}
if (strcmp(name, "radiosnode") == 0) {
push<SondeView>();
return true;
}
if (strcmp(name, "recon") == 0) {
push<ReconView>();
return true;
}
if (strcmp(name, "search") == 0) {
push<SearchView>();
return true;
}
if (strcmp(name, "tpms") == 0) {
push<TPMSAppView>();
return true;
}
if (strcmp(name, "weather") == 0) {
push<WeatherView>();
return true;
}
if (strcmp(name, "subghzd") == 0) {
push<SubGhzDView>();
return true;
}
if (strcmp(name, "adsbtx") == 0) {
push<ADSBTxView>();
return true;
}
if (strcmp(name, "aprstx") == 0) {
push<APRSTXView>();
return true;
}
if (strcmp(name, "bht") == 0) {
push<BHTView>();
return true;
}
if (strcmp(name, "bletx") == 0) {
push<BLETxView>();
return true;
}
if (strcmp(name, "morsetx") == 0) {
push<MorseView>();
return true;
}
if (strcmp(name, "ooktx") == 0) {
push<EncodersView>();
return true;
}
if (strcmp(name, "pocsatx") == 0) {
push<POCSAGTXView>();
return true;
}
if (strcmp(name, "rdstx") == 0) {
push<RDSView>();
return true;
}
if (strcmp(name, "soundbrd") == 0) {
push<SoundBoardView>();
return true;
}
if (strcmp(name, "sstvtx") == 0) {
push<SSTVTXView>();
return true;
}
if (strcmp(name, "touchtune") == 0) {
push<TouchTunesView>();
return true;
}
if (strcmp(name, "capture") == 0) {
push<CaptureAppView>();
return true;
}
if (strcmp(name, "replay") == 0) {
push<PlaylistView>();
return true;
}
if (strcmp(name, "remote") == 0) {
push<RemoteView>();
return true;
}
if (strcmp(name, "scanner") == 0) {
push<ScannerView>();
return true;
}
if (strcmp(name, "microphone") == 0) {
push<MicTXView>();
return true;
}
if (strcmp(name, "lookingglass") == 0) {
push<GlassView>();
return true;
}
return false;
}
/* StatusTray ************************************************************/
StatusTray::StatusTray(Point pos)
@@ -407,7 +570,7 @@ void SystemStatusView::rtc_battery_workaround() {
}
}
} else {
make_new_directory(SETTINGS_DIR);
ensure_directory(SETTINGS_DIR);
make_new_file(DATE_FILEFLAG);
year = 1980;
@@ -497,6 +660,14 @@ void NavigationView::pop(bool trigger_update) {
if (on_pop) on_pop();
}
void NavigationView::home(bool trigger_update) {
while (view_stack.size() > 1) {
pop(false);
}
if (trigger_update) update_view();
}
void NavigationView::display_modal(
const std::string& title,
const std::string& message) {
@@ -751,6 +922,9 @@ SystemView::SystemView(
Context& SystemView::context() const {
return context_;
}
NavigationView* SystemView::get_navigation_view() {
return &navigation_view;
}
void SystemView::toggle_overlay() {
switch (++overlay_active) {
@@ -758,7 +932,7 @@ void SystemView::toggle_overlay() {
this->add_child(&this->overlay);
this->set_dirty();
shared_memory.request_m4_performance_counter = 1;
shared_memory.m4_cpu_usage = 0;
shared_memory.m4_performance_counter = 0;
shared_memory.m4_heap_usage = 0;
shared_memory.m4_stack_usage = 0;
break;
@@ -766,11 +940,12 @@ void SystemView::toggle_overlay() {
this->remove_child(&this->overlay);
this->add_child(&this->overlay2);
this->set_dirty();
shared_memory.request_m4_performance_counter = 0;
shared_memory.request_m4_performance_counter = 2;
break;
case 3:
this->remove_child(&this->overlay2);
this->set_dirty();
shared_memory.request_m4_performance_counter = 0;
overlay_active = 0;
break;
}
+12 -1
View File
@@ -40,7 +40,7 @@
#include "diskio.h"
#include "lfsr_random.hpp"
#include "sd_card.hpp"
#include "external_app.hpp"
#include <vector>
#include <utility>
@@ -57,6 +57,12 @@ enum modal_t {
ABORT
};
struct AppInfoConsole {
const char* appCallName;
const char* appFriendlyName;
const app_location_t appLocation;
};
class NavigationView : public View {
public:
std::function<void(const View&)> on_view_changed{};
@@ -85,6 +91,7 @@ class NavigationView : public View {
View* push_view(std::unique_ptr<View> new_view);
void replace(View* v);
void pop(bool trigger_update = true);
void home(bool trigger_update);
void display_modal(const std::string& title, const std::string& message);
void display_modal(
@@ -99,6 +106,8 @@ class NavigationView : public View {
* Returns true if the handler was bound successfully. */
bool set_on_pop(std::function<void()> on_pop);
static std::vector<AppInfoConsole> fixedAppListFC; // fixed app list for console. vector, so can be incomplete and still iterateable
bool StartAppByName(const char* name); // Starts a View (app) by name stored in fixedAppListFC. This is to start apps from console
private:
struct ViewState {
std::unique_ptr<View> view;
@@ -321,6 +330,8 @@ class SystemView : public View {
void toggle_overlay();
void paint_overlay();
NavigationView* get_navigation_view();
private:
uint8_t overlay_active{0};
+8 -2
View File
@@ -1,11 +1,12 @@
extern "C" {
#include "usb_serial_io.h"
#include "usb_serial_device_to_host.h"
#include "usb_serial_cdc.h"
}
#include "usb_serial_shell.hpp"
#include "usb_serial.hpp"
#include "portapack.hpp"
#include "usb_serial_host_to_device.hpp"
#include <libopencm3/cm3/common.h>
#include <libopencm3/lpc43xx/usb.h>
@@ -24,6 +25,7 @@ void USBSerial::initialize() {
init_serial_usb_driver(&SUSBD1);
shellInit();
init_host_to_device();
}
void USBSerial::dispatch() {
@@ -35,7 +37,11 @@ void USBSerial::dispatch() {
create_shell(_eventDispatcher);
}
bulk_out_receive();
schedule_host_to_device_transfer();
}
void USBSerial::dispatch_transfer() {
complete_host_to_device_transfer();
}
void USBSerial::on_channel_opened() {
+1
View File
@@ -32,6 +32,7 @@ class USBSerial {
public:
void initialize();
void dispatch();
void dispatch_transfer();
void on_channel_opened();
void on_channel_closed();
void setEventDispatcher(EventDispatcher* ed) { _eventDispatcher = ed; }
+16
View File
@@ -23,10 +23,25 @@
#include "usb_serial_endpoints.h"
#include "usb_serial_event.hpp"
uint32_t EVT_MASK_USB = EVENT_MASK(8);
extern void usb0_isr(void);
static Thread* thread_usb_event = NULL;
CH_IRQ_HANDLER(USB0_IRQHandler) {
CH_IRQ_PROLOGUE();
const uint32_t status = USB0_USBSTS_D & USB0_USBINTR_D;
usb0_isr();
if (status & USB0_USBSTS_D_UI) {
chSysLockFromIsr();
chEvtSignalI(thread_usb_event, EVT_MASK_USB);
chSysUnlockFromIsr();
}
CH_IRQ_EPILOGUE();
}
@@ -46,6 +61,7 @@ uint32_t __strex(uint32_t val, volatile uint32_t* addr) {
void nvic_enable_irq(uint8_t irqn) {
NVIC_ISER(irqn / 32) = (1 << (irqn % 32));
thread_usb_event = chThdSelf();
}
void usb_configuration_changed(usb_device_t* const device) {
+1 -1
View File
@@ -264,7 +264,7 @@ uint8_t usb_descriptor_string_manufacturer[] = {
};
uint8_t usb_descriptor_string_product[] = {
43, // bLength
34, // bLength
USB_DESCRIPTOR_TYPE_STRING, // bDescriptorType
'P', 0x00,
'o', 0x00,
@@ -19,7 +19,7 @@
* Boston, MA 02110-1301, USA.
*/
#include "usb_serial_io.h"
#include "usb_serial_device_to_host.h"
#include "usb_serial_endpoints.h"
@@ -40,42 +40,11 @@
SerialUSBDriver SUSBD1;
void bulk_out_receive(void) {
int ret;
do {
ret = usb_transfer_schedule(
&usb_endpoint_bulk_out,
&usb_endpoint_bulk_out.buffer[0],
32,
serial_bulk_transfer_complete,
NULL);
} while (ret != -1);
}
void serial_bulk_transfer_complete(void* user_data, unsigned int bytes_transferred) {
(void)user_data;
chSysLockFromIsr();
for (unsigned int i = 0; i < bytes_transferred; i++) {
msg_t ret;
do {
ret = chIQPutI(&SUSBD1.iqueue, usb_endpoint_bulk_out.buffer[i]);
if (ret == Q_FULL)
chThdSleepMilliseconds(1);
} while (ret == Q_FULL);
}
chSysUnlockFromIsr();
}
static void onotify(GenericQueue* qp) {
SerialUSBDriver* sdp = chQGetLink(qp);
uint8_t buff[64];
uint8_t buff[USBSERIAL_BUFFERS_SIZE];
int n = chOQGetFullI(&sdp->oqueue);
if (n > 64) n = 64; // don't overflow
if (n > USBSERIAL_BUFFERS_SIZE) n = USBSERIAL_BUFFERS_SIZE; // don't overflow
if (n > 0) {
for (int i = 0; i < n; i++) {
buff[i] = chOQGetI(&sdp->oqueue);
@@ -139,6 +108,45 @@ static const struct SerialUSBDriverVMT vmt = {
void init_serial_usb_driver(SerialUSBDriver* sdp) {
sdp->vmt = &vmt;
chIQInit(&sdp->iqueue, sdp->ib, SERIAL_BUFFERS_SIZE, NULL, sdp);
chOQInit(&sdp->oqueue, sdp->ob, SERIAL_BUFFERS_SIZE, onotify, sdp);
chIQInit(&sdp->iqueue, sdp->ib, USBSERIAL_BUFFERS_SIZE, NULL, sdp);
chOQInit(&sdp->oqueue, sdp->ob, USBSERIAL_BUFFERS_SIZE, onotify, sdp);
}
// queue handler from ch
static msg_t qwait(GenericQueue* qp, systime_t time) {
if (TIME_IMMEDIATE == time)
return Q_TIMEOUT;
currp->p_u.wtobjp = qp;
queue_insert(currp, &qp->q_waiting);
return chSchGoSleepTimeoutS(THD_STATE_WTQUEUE, time);
}
// This function fills the output buffer, and sends all data in 1 packet
size_t fillOBuffer(OutputQueue* oqp, const uint8_t* bp, size_t n) {
qnotify_t nfy = oqp->q_notify;
size_t w = 0;
chDbgCheck(n > 0, "chOQWriteTimeout");
chSysLock();
while (TRUE) {
while (chOQIsFullI(oqp)) {
if (qwait((GenericQueue*)oqp, TIME_INFINITE) != Q_OK) {
chSysUnlock();
return w;
}
}
while (!chOQIsFullI(oqp) && n > 0) {
oqp->q_counter--;
*oqp->q_wrptr++ = *bp++;
if (oqp->q_wrptr >= oqp->q_top)
oqp->q_wrptr = oqp->q_buffer;
w++;
--n;
}
if (nfy) nfy(oqp);
chSysUnlock(); /* Gives a preemption chance in a controlled point.*/
if (n == 0) return w;
chSysLock();
}
}
@@ -24,6 +24,12 @@
#include "ch.h"
#include "hal.h"
#define USB_BULK_BUFFER_SIZE 64
#ifndef USBSERIAL_BUFFERS_SIZE
#define USBSERIAL_BUFFERS_SIZE 128
#endif
struct SerialUSBDriverVMT {
_base_asynchronous_channel_methods
};
@@ -31,10 +37,10 @@ struct SerialUSBDriverVMT {
struct SerialUSBDriver {
/** @brief Virtual Methods Table.*/
const struct SerialUSBDriverVMT* vmt;
InputQueue iqueue; /* Output queue.*/
OutputQueue oqueue; /* Input circular buffer.*/
uint8_t ib[SERIAL_BUFFERS_SIZE]; /* Output circular buffer.*/
uint8_t ob[SERIAL_BUFFERS_SIZE];
InputQueue iqueue; /* Output queue.*/
OutputQueue oqueue; /* Input circular buffer.*/
uint8_t ib[USBSERIAL_BUFFERS_SIZE]; /* Output circular buffer.*/
uint8_t ob[USBSERIAL_BUFFERS_SIZE];
};
typedef struct SerialUSBDriver SerialUSBDriver;
@@ -42,5 +48,11 @@ typedef struct SerialUSBDriver SerialUSBDriver;
extern SerialUSBDriver SUSBD1;
void init_serial_usb_driver(SerialUSBDriver* sdp);
void bulk_out_receive(void);
void serial_bulk_transfer_complete(void* user_data, unsigned int bytes_transferred);
#ifdef __cplusplus
extern "C" {
#endif
size_t fillOBuffer(OutputQueue* oqp, const uint8_t* bp, size_t n);
#ifdef __cplusplus
}
#endif
@@ -0,0 +1,122 @@
/*
* Copyright (C) 2023 Bernd Herzog
*
* This file is part of PortaPack.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street,
* Boston, MA 02110-1301, USA.
*/
#include "usb_serial_host_to_device.hpp"
#include "event_m0.hpp"
#include "usb_serial_device_to_host.h"
extern "C" {
#include <common/usb.h>
#include <hackrf_usb/usb_device.h>
#include <hackrf_usb/usb_endpoint.h>
}
#include <queue>
#include <vector>
static Thread* thread_usb_event = NULL;
struct usb_bulk_buffer_t {
uint8_t* data;
size_t length;
bool completed;
};
std::queue<usb_bulk_buffer_t*> usb_bulk_buffer_queue;
std::queue<usb_bulk_buffer_t*> usb_bulk_buffer_spare;
void serial_bulk_transfer_complete(void* user_data, unsigned int bytes_transferred) {
usb_bulk_buffer_t* transfer_data = (usb_bulk_buffer_t*)user_data;
transfer_data->length = bytes_transferred;
transfer_data->completed = true;
}
void init_host_to_device() {
thread_usb_event = chThdSelf();
}
void schedule_host_to_device_transfer() {
if (usb_bulk_buffer_queue.size() >= 8)
return;
static usb_bulk_buffer_t* transfer_data = nullptr;
int ret;
do {
if (transfer_data == nullptr) {
if (usb_bulk_buffer_spare.empty() == false) {
transfer_data = usb_bulk_buffer_spare.front();
transfer_data->length = 0;
transfer_data->completed = false;
usb_bulk_buffer_spare.pop();
} else {
transfer_data = new usb_bulk_buffer_t{
.data = new uint8_t[USB_BULK_BUFFER_SIZE],
.length = 0,
.completed = false};
}
}
ret = usb_transfer_schedule(
&usb_endpoint_bulk_out,
transfer_data->data,
USB_BULK_BUFFER_SIZE,
serial_bulk_transfer_complete,
transfer_data);
if (ret != -1) {
usb_bulk_buffer_queue.push(transfer_data);
transfer_data = nullptr;
if (usb_bulk_buffer_queue.size() >= 8)
return;
}
} while (ret != -1);
}
void complete_host_to_device_transfer() {
for (; !usb_bulk_buffer_queue.empty(); usb_bulk_buffer_queue.pop()) {
usb_bulk_buffer_t* transfer_data = usb_bulk_buffer_queue.front();
while (transfer_data->completed == false)
return;
chSysLock();
for (unsigned int i = 0; i < transfer_data->length; i++) {
msg_t ret;
do {
ret = chIQPutI(&SUSBD1.iqueue, transfer_data->data[i]);
if (ret == Q_FULL) {
chSysUnlock();
chThdSleepMilliseconds(1); // wait for shell thread when buffer is full
chSysLock();
}
} while (ret == Q_FULL);
}
chSysUnlock();
usb_bulk_buffer_spare.push(transfer_data);
}
}
@@ -0,0 +1,32 @@
/*
* Copyright (C) 2023 Bernd Herzog
*
* 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.
*/
#pragma once
#include "ch.h"
#include "hal.h"
#define USB_BULK_BUFFER_SIZE 64
void init_host_to_device();
void serial_bulk_transfer_complete(void* user_data, unsigned int bytes_transferred);
void schedule_host_to_device_transfer();
void complete_host_to_device_transfer();
+201 -244
View File
@@ -35,18 +35,20 @@
#include "portapack_cpld_data.hpp"
#include "crc.hpp"
#include "hackrf_cpld_data.hpp"
#include "performance_counter.hpp"
#include "usb_serial_io.h"
#include "ff.h"
#include "usb_serial_device_to_host.h"
#include "chprintf.h"
#include "chqueues.h"
#include "ui_external_items_menu_loader.hpp"
#include "untar.hpp"
#include "ui_widget.hpp"
#include "ui_navigation.hpp"
#include "usb_serial_shell_filesystem.hpp"
#include <string>
#include <codecvt>
#include <cstring>
#include <locale>
#include <libopencm3/lpc43xx/wwdt.h>
#define SHELL_WA_SIZE THD_WA_SIZE(1024 * 3)
@@ -57,45 +59,6 @@ static EventDispatcher* getEventDispatcherInstance() {
return _eventDispatcherInstance;
}
// queue handler from ch
static msg_t qwait(GenericQueue* qp, systime_t time) {
if (TIME_IMMEDIATE == time)
return Q_TIMEOUT;
currp->p_u.wtobjp = qp;
queue_insert(currp, &qp->q_waiting);
return chSchGoSleepTimeoutS(THD_STATE_WTQUEUE, time);
}
// This function fills the output buffer, and sends all data in 1 packet
static size_t fillOBuffer(OutputQueue* oqp, const uint8_t* bp, size_t n) {
qnotify_t nfy = oqp->q_notify;
size_t w = 0;
chDbgCheck(n > 0, "chOQWriteTimeout");
chSysLock();
while (TRUE) {
while (chOQIsFullI(oqp)) {
if (qwait((GenericQueue*)oqp, TIME_INFINITE) != Q_OK) {
chSysUnlock();
return w;
}
}
while (!chOQIsFullI(oqp) && n > 0) {
oqp->q_counter--;
*oqp->q_wrptr++ = *bp++;
if (oqp->q_wrptr >= oqp->q_top)
oqp->q_wrptr = oqp->q_buffer;
w++;
--n;
}
if (nfy) nfy(oqp);
chSysUnlock(); /* Gives a preemption chance in a controlled point.*/
if (n == 0) return w;
chSysLock();
}
}
static void cmd_reboot(BaseSequentialStream* chp, int argc, char* argv[]) {
(void)chp;
(void)argc;
@@ -158,11 +121,6 @@ static void cmd_sd_over_usb(BaseSequentialStream* chp, int argc, char* argv[]) {
m0_halt();
}
std::filesystem::path path_from_string8(char* path) {
std::wstring_convert<std::codecvt_utf8_utf16<char16_t>, char16_t> conv;
return conv.from_bytes(path);
}
bool strEndsWith(const std::u16string& str, const std::u16string& suffix) {
if (str.length() >= suffix.length()) {
std::u16string endOfString = str.substr(str.length() - suffix.length());
@@ -185,6 +143,13 @@ static void cmd_flash(BaseSequentialStream* chp, int argc, char* argv[]) {
return;
}
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;
nav->display_modal("Flashing", "Flashing from serial.\rPlease wait!\nDevice will restart.");
// check file extensions
if (strEndsWith(path.native(), u".ppfw.tar")) {
// extract tar
@@ -196,6 +161,7 @@ static void cmd_flash(BaseSequentialStream* chp, int argc, char* argv[]) {
});
if (res.empty()) {
chprintf(chp, "error bad TAR file.\r\n");
nav->pop();
return;
}
path = res; // it will contain the last bin file in tar
@@ -203,8 +169,10 @@ static void cmd_flash(BaseSequentialStream* chp, int argc, char* argv[]) {
// nothing to do for this case yet.
} else {
chprintf(chp, "error only .bin or .ppfw.tar files canbe flashed.\r\n");
nav->pop();
return;
}
chprintf(chp, "Flashing: ");
chprintf(chp, path.string().c_str());
chprintf(chp, "\r\n");
@@ -245,6 +213,9 @@ static void cmd_screenframe(BaseSequentialStream* chp, int argc, char* argv[]) {
(void)argc;
(void)argv;
auto evtd = getEventDispatcherInstance();
evtd->enter_shell_working_mode();
for (int i = 0; i < ui::screen_height; i++) {
std::array<ui::ColorRGB888, ui::screen_width> row;
portapack::display.read_pixels({0, i, ui::screen_width, 1}, row);
@@ -255,6 +226,9 @@ static void cmd_screenframe(BaseSequentialStream* chp, int argc, char* argv[]) {
}
chprintf(chp, "\r\n");
}
evtd->exit_shell_working_mode();
chprintf(chp, "ok\r\n");
}
@@ -272,21 +246,25 @@ static void cmd_screenframeshort(BaseSequentialStream* chp, int argc, char* argv
(void)argc;
(void)argv;
auto evtd = getEventDispatcherInstance();
evtd->enter_shell_working_mode();
for (int y = 0; y < ui::screen_height; y++) {
std::array<ui::ColorRGB888, ui::screen_width> row;
portapack::display.read_pixels({0, y, ui::screen_width, 1}, row);
for (int px = 0; px < ui::screen_width; px += 60) {
char buffer[60];
for (int i = 0; i < 60; ++i) {
buffer[i] = getChrFromRgb(row[px + i].r, row[px + i].g, row[px + i].b);
}
fillOBuffer(&((SerialUSBDriver*)chp)->oqueue, (const uint8_t*)buffer, 60);
char buffer[242];
for (int i = 0; i < 240; ++i) {
buffer[i] = getChrFromRgb(row[i].r, row[i].g, row[i].b);
}
chprintf(chp, "\r\n");
buffer[240] = '\r';
buffer[241] = '\n';
fillOBuffer(&((SerialUSBDriver*)chp)->oqueue, (const uint8_t*)buffer, 242);
}
chprintf(chp, "ok\r\n");
evtd->exit_shell_working_mode();
chprintf(chp, "\r\nok\r\n");
}
static void cmd_write_memory(BaseSequentialStream* chp, int argc, char* argv[]) {
if (argc != 2) {
chprintf(chp, "usage: write_memory <address> <value (1 or 4 bytes)>\r\n");
@@ -341,6 +319,11 @@ static void cmd_button(BaseSequentialStream* chp, int argc, char* argv[]) {
control::debug::inject_switch(button);
// Wait two frame syncs to ensure action has painted
auto evtd = getEventDispatcherInstance();
evtd->wait_finish_frame();
evtd->wait_finish_frame();
chprintf(chp, "ok\r\n");
}
@@ -363,6 +346,11 @@ static void cmd_touch(BaseSequentialStream* chp, int argc, char* argv[]) {
}
evtd->emulateTouch({{x, y}, ui::TouchEvent::Type::Start});
evtd->emulateTouch({{x, y}, ui::TouchEvent::Type::End});
// Wait two frame syncs to ensure action has painted
evtd->wait_finish_frame();
evtd->wait_finish_frame();
chprintf(chp, "ok\r\n");
}
@@ -401,185 +389,9 @@ static void cmd_keyboard(BaseSequentialStream* chp, int argc, char* argv[]) {
evtd->emulateKeyboard(chr);
}
chprintf(chp, "ok\r\n");
}
static void cmd_sd_list_dir(BaseSequentialStream* chp, int argc, char* argv[]) {
if (argc != 1) {
chprintf(chp, "usage: ls /\r\n");
return;
}
auto path = path_from_string8(argv[0]);
for (const auto& entry : std::filesystem::directory_iterator(path, "*")) {
if (std::filesystem::is_directory(entry.status())) {
chprintf(chp, "%s/\r\n", entry.path().string().c_str());
} else if (std::filesystem::is_regular_file(entry.status())) {
chprintf(chp, "%s\r\n", entry.path().string().c_str());
} else {
chprintf(chp, "%s *\r\n", entry.path().string().c_str());
}
}
}
static void cmd_sd_delete(BaseSequentialStream* chp, int argc, char* argv[]) {
if (argc != 1) {
chprintf(chp, "usage: rm <path>\r\n");
return;
}
auto path = path_from_string8(argv[0]);
if (!std::filesystem::file_exists(path)) {
chprintf(chp, "file not found.\r\n");
return;
}
delete_file(path);
chprintf(chp, "ok\r\n");
}
File* shell_file = nullptr;
static void cmd_sd_filesize(BaseSequentialStream* chp, int argc, char* argv[]) {
if (argc != 1) {
chprintf(chp, "usage: filesize <path>\r\n");
return;
}
auto path = path_from_string8(argv[0]);
FILINFO res;
auto stat = f_stat(path.tchar(), &res);
if (stat == FR_OK) {
chprintf(chp, "%lu\r\n", res.fsize);
chprintf(chp, "ok\r\n");
} else {
chprintf(chp, "error\r\n");
}
}
static void cmd_sd_open(BaseSequentialStream* chp, int argc, char* argv[]) {
if (argc != 1) {
chprintf(chp, "usage: open <path>\r\n");
return;
}
if (shell_file != nullptr) {
chprintf(chp, "file already open\r\n");
return;
}
auto path = path_from_string8(argv[0]);
shell_file = new File();
shell_file->open(path, false, true);
chprintf(chp, "ok\r\n");
}
static void cmd_sd_seek(BaseSequentialStream* chp, int argc, char* argv[]) {
if (argc != 1) {
chprintf(chp, "usage: seek <offset>\r\n");
return;
}
if (shell_file == nullptr) {
chprintf(chp, "no open file\r\n");
return;
}
int address = (int)strtol(argv[0], NULL, 10);
shell_file->seek(address);
chprintf(chp, "ok\r\n");
}
static void cmd_sd_close(BaseSequentialStream* chp, int argc, char* argv[]) {
(void)argv;
if (argc != 0) {
chprintf(chp, "usage: close\r\n");
return;
}
if (shell_file == nullptr) {
chprintf(chp, "no open file\r\n");
return;
}
delete shell_file;
shell_file = nullptr;
chprintf(chp, "ok\r\n");
}
static void cmd_sd_read(BaseSequentialStream* chp, int argc, char* argv[]) {
if (argc != 1) {
chprintf(chp, "usage: read <number of bytes>\r\n");
return;
}
if (shell_file == nullptr) {
chprintf(chp, "no open file\r\n");
return;
}
int size = (int)strtol(argv[0], NULL, 10);
uint8_t buffer[62];
do {
File::Size bytes_to_read = size > 62 ? 62 : size;
auto bytes_read = shell_file->read(buffer, bytes_to_read);
if (bytes_read.is_error()) {
chprintf(chp, "error %d\r\n", bytes_read.error());
return;
}
std::string res = to_string_hex_array(buffer, bytes_read.value());
res += "\r\n";
fillOBuffer(&((SerialUSBDriver*)chp)->oqueue, (const uint8_t*)res.c_str(), res.size());
if (bytes_to_read != bytes_read.value())
return;
size -= bytes_to_read;
} while (size > 0);
chprintf(chp, "ok\r\n");
}
static void cmd_sd_write(BaseSequentialStream* chp, int argc, char* argv[]) {
const char* usage = "usage: write 0123456789ABCDEF\r\n";
if (argc != 1) {
chprintf(chp, usage);
return;
}
if (shell_file == nullptr) {
chprintf(chp, "no open file\r\n");
return;
}
size_t data_string_len = strlen(argv[0]);
if (data_string_len % 2 != 0) {
chprintf(chp, usage);
return;
}
for (size_t i = 0; i < data_string_len; i++) {
char c = argv[0][i];
if ((c < '0' || c > '9') && (c < 'A' || c > 'F')) {
chprintf(chp, usage);
return;
}
}
char buffer[3] = {0, 0, 0};
for (size_t i = 0; i < data_string_len / 2; i++) {
buffer[0] = argv[0][i * 2];
buffer[1] = argv[0][i * 2 + 1];
uint8_t value = (uint8_t)strtol(buffer, NULL, 16);
shell_file->write(&value, 1);
}
// Wait two frame syncs to ensure action has painted
evtd->wait_finish_frame();
evtd->wait_finish_frame();
chprintf(chp, "ok\r\n");
}
@@ -843,6 +655,78 @@ static void cmd_accessibility_readcurr(BaseSequentialStream* chp, int argc, char
chprintf(chp, "\r\nok\r\n");
}
static void cmd_appstart(BaseSequentialStream* chp, int argc, char* argv[]) {
(void)argc;
(void)argv;
if (argc != 1) {
chprintf(chp, "Usage: appstart APPCALLNAME");
return;
}
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(argv[0])) {
chprintf(chp, "ok\r\n");
return;
}
// since ext app loader changed, we can just pass the string to it, and it"ll return if started or not.
std::string appwithpath = "/APPS/";
appwithpath += argv[0];
appwithpath += ".ppma";
bool ret = ui::ExternalItemsMenuLoader::run_external_app(*nav, path_from_string8((char*)appwithpath.c_str()));
if (!ret) {
chprintf(chp, "error\r\n");
return;
}
chprintf(chp, "ok\r\n");
}
static void printAppInfo(BaseSequentialStream* chp, ui::AppInfoConsole& element) {
if (strlen(element.appCallName) == 0) return;
chprintf(chp, element.appCallName);
chprintf(chp, " ");
chprintf(chp, element.appFriendlyName);
chprintf(chp, " ");
switch (element.appLocation) {
case RX:
chprintf(chp, "[RX]\r\n");
break;
case TX:
chprintf(chp, "[TX]\r\n");
break;
case UTILITIES:
chprintf(chp, "[UTIL]\r\n");
break;
case DEBUG:
chprintf(chp, "[DEBUG]\r\n");
break;
default:
break;
}
}
// returns the installed apps, those can be called by appstart APPNAME
static void cmd_applist(BaseSequentialStream* chp, int argc, char* argv[]) {
(void)argc;
(void)argv;
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;
for (auto element : ui::NavigationView::fixedAppListFC) {
printAppInfo(chp, element);
}
ui::ExternalItemsMenuLoader::load_all_external_items_callback([chp](ui::AppInfoConsole& info) {
printAppInfo(chp, info);
});
chprintf(chp, "ok\r\n");
}
static void cmd_cpld_read(BaseSequentialStream* chp, int argc, char* argv[]) {
const char* usage =
"usage: cpld_read <device> <target>\r\n"
@@ -1004,6 +888,80 @@ static void cmd_cpld_read(BaseSequentialStream* chp, int argc, char* argv[]) {
}
}
static void cmd_gotgps(BaseSequentialStream* chp, int argc, char* argv[]) {
const char* usage = "usage: gotgps <lat> <lon> [altitude] [speed]\r\n";
if (argc < 2 || argc > 4) {
chprintf(chp, usage);
return;
}
float lat = atof(argv[0]);
float lon = atof(argv[1]);
int32_t altitude = 0;
int32_t speed = 0;
if (argc >= 3) altitude = strtol(argv[2], NULL, 10);
if (argc >= 4) speed = strtol(argv[3], NULL, 10);
GPSPosDataMessage msg{lat, lon, altitude, speed};
EventDispatcher::send_message(msg);
chprintf(chp, "ok\r\n");
}
static void cmd_gotorientation(BaseSequentialStream* chp, int argc, char* argv[]) {
const char* usage = "usage: gotorientation <angle>\r\n";
if (argc != 1) {
chprintf(chp, usage);
return;
}
uint16_t angle = strtol(argv[0], NULL, 10);
OrientationDataMessage msg{angle};
EventDispatcher::send_message(msg);
chprintf(chp, "ok\r\n");
}
static void cmd_sysinfo(BaseSequentialStream* chp, int argc, char* argv[]) {
const char* usage = "usage: sysinfo\r\n";
(void)argv;
if (argc > 0) {
chprintf(chp, usage);
return;
}
auto utilisation = get_cpu_utilisation_in_percent();
std::string info =
"M0 heap: " + to_string_dec_uint(chCoreStatus()) + "\r\n" +
"M0 stack: " + to_string_dec_uint((uint32_t)get_free_stack_space()) + "\r\n" +
"M0 cpu%: " + to_string_dec_uint(utilisation) + "\r\n" +
"M4 heap: " + to_string_dec_uint(shared_memory.m4_heap_usage) + "\r\n" +
"M4 stack: " + to_string_dec_uint(shared_memory.m4_stack_usage) + "\r\n" +
"M0 cpu%: " + to_string_dec_uint(shared_memory.m4_performance_counter) + "\r\n" +
"M4 miss: " + to_string_dec_uint(shared_memory.m4_buffer_missed) + "\r\n" +
"uptime: " + to_string_dec_uint(chTimeNow() / 1000) + "\r\n";
fillOBuffer(&((SerialUSBDriver*)chp)->oqueue, (const uint8_t*)info.c_str(), info.length());
return;
}
static void cmd_radioinfo(BaseSequentialStream* chp, int argc, char* argv[]) {
const char* usage = "usage: radioinfo\r\n";
(void)argv;
if (argc > 0) {
chprintf(chp, usage);
return;
}
std::string info =
"receiver_model.target_frequency: " + to_string_dec_uint(portapack::receiver_model.target_frequency()) + "\r\n" +
"receiver_model.baseband_bandwidth: " + to_string_dec_uint(portapack::receiver_model.baseband_bandwidth()) + "\r\n" +
"receiver_model.sampling_rate: " + to_string_dec_uint(portapack::receiver_model.sampling_rate()) + "\r\n" +
"receiver_model.modulation: " + to_string_dec_uint((uint32_t)portapack::receiver_model.modulation()) + "\r\n" +
"receiver_model.am_configuration: " + to_string_dec_uint(portapack::receiver_model.am_configuration()) + "\r\n" +
"receiver_model.nbfm_configuration: " + to_string_dec_uint(portapack::receiver_model.nbfm_configuration()) + "\r\n" +
"receiver_model.wfm_configuration: " + to_string_dec_uint(portapack::receiver_model.wfm_configuration()) + "\r\n" +
"transmitter_model.target_frequency: " + to_string_dec_uint(portapack::transmitter_model.target_frequency()) + "\r\n" +
"transmitter_model.baseband_bandwidth: " + to_string_dec_uint(portapack::transmitter_model.baseband_bandwidth()) + "\r\n" +
"transmitter_model.sampling_rate: " + to_string_dec_uint(portapack::transmitter_model.sampling_rate()) + "\r\n";
fillOBuffer(&((SerialUSBDriver*)chp)->oqueue, (const uint8_t*)info.c_str(), info.length());
return;
}
static const ShellCommand commands[] = {
{"reboot", cmd_reboot},
{"dfu", cmd_dfu},
@@ -1018,20 +976,19 @@ static const ShellCommand commands[] = {
{"button", cmd_button},
{"touch", cmd_touch},
{"keyboard", cmd_keyboard},
{"ls", cmd_sd_list_dir},
{"rm", cmd_sd_delete},
{"open", cmd_sd_open},
{"seek", cmd_sd_seek},
{"close", cmd_sd_close},
{"read", cmd_sd_read},
{"write", cmd_sd_write},
{"filesize", cmd_sd_filesize},
USB_SERIAL_SHELL_SD_COMMANDS,
{"rtcget", cmd_rtcget},
{"rtcset", cmd_rtcset},
{"cpld_info", cpld_info},
{"cpld_read", cmd_cpld_read},
{"accessibility_readall", cmd_accessibility_readall},
{"accessibility_readcurr", cmd_accessibility_readcurr},
{"applist", cmd_applist},
{"appstart", cmd_appstart},
{"gotgps", cmd_gotgps},
{"gotorientation", cmd_gotorientation},
{"sysinfo", cmd_sysinfo},
{"radioinfo", cmd_radioinfo},
{NULL, NULL}};
static const ShellConfig shell_cfg1 = {
@@ -1040,5 +997,5 @@ static const ShellConfig shell_cfg1 = {
void create_shell(EventDispatcher* evtd) {
_eventDispatcherInstance = evtd;
shellCreate(&shell_cfg1, SHELL_WA_SIZE, NORMALPRIO);
shellCreate(&shell_cfg1, SHELL_WA_SIZE, NORMALPRIO + 10);
}
@@ -0,0 +1,373 @@
/*
* Copyright (C) 2023 Bernd Herzog
*
* This file is part of PortaPack.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street,
* Boston, MA 02110-1301, USA.
*/
#include "usb_serial_shell_filesystem.hpp"
#include "usb_serial_device_to_host.h"
#include "chprintf.h"
#include "string_format.hpp"
#include <cstring>
static File* shell_file = nullptr;
static bool report_on_error(BaseSequentialStream* chp, File::Error& error) {
if (error.ok() == false) {
chprintf(chp, "Error calling delete_file: %d %s\r\n", error.code(), error.what().c_str());
return true;
}
return false;
}
static bool report_on_error(BaseSequentialStream* chp, FRESULT error_code) {
std::filesystem::filesystem_error error = error_code;
return report_on_error(chp, error);
}
static bool report_on_error(BaseSequentialStream* chp, Optional<File::Error>& error) {
if (error.is_valid())
return report_on_error(chp, error.value());
return false;
}
static bool report_on_error(BaseSequentialStream* chp, File::Result<uint64_t> error) {
if (error.is_error()) {
return report_on_error(chp, error.error());
}
return false;
}
void cmd_sd_list_dir(BaseSequentialStream* chp, int argc, char* argv[]) {
if (argc != 1) {
chprintf(chp, "usage: ls /\r\n");
return;
}
auto path = path_from_string8(argv[0]);
for (const auto& entry : std::filesystem::directory_iterator(path, "*")) {
if (std::filesystem::is_directory(entry.status())) {
chprintf(chp, "%s/\r\n", entry.path().string().c_str());
} else if (std::filesystem::is_regular_file(entry.status())) {
chprintf(chp, "%s\r\n", entry.path().string().c_str());
} else {
chprintf(chp, "%s *\r\n", entry.path().string().c_str());
}
}
}
void cmd_sd_unlink(BaseSequentialStream* chp, int argc, char* argv[]) {
if (argc != 1) {
chprintf(chp, "usage: unlink <path>\r\n");
return;
}
auto path = path_from_string8(argv[0]);
auto error = delete_file(path);
if (report_on_error(chp, error)) return;
chprintf(chp, "ok\r\n");
}
void cmd_sd_mkdir(BaseSequentialStream* chp, int argc, char* argv[]) {
if (argc != 1) {
chprintf(chp, "usage: mkdir <path>\r\n");
return;
}
auto path = path_from_string8(argv[0]);
if (!std::filesystem::is_directory(path)) {
chprintf(chp, "directory already exists.\r\n");
return;
}
auto error = make_new_directory(path);
if (report_on_error(chp, error)) return;
chprintf(chp, "ok\r\n");
}
void cmd_sd_filesize(BaseSequentialStream* chp, int argc, char* argv[]) {
if (argc != 1) {
chprintf(chp, "usage: filesize <path>\r\n");
return;
}
auto path = path_from_string8(argv[0]);
FILINFO res;
auto stat = f_stat(path.tchar(), &res);
if (report_on_error(chp, stat)) return;
chprintf(chp, "%lu\r\n", res.fsize);
chprintf(chp, "ok\r\n");
}
void cmd_sd_open(BaseSequentialStream* chp, int argc, char* argv[]) {
if (argc != 1) {
chprintf(chp, "usage: fopen <path>\r\n");
return;
}
if (shell_file != nullptr) {
chprintf(chp, "file already open\r\n");
return;
}
auto path = path_from_string8(argv[0]);
shell_file = new File();
auto error = shell_file->open(path, false, true);
if (report_on_error(chp, error)) return;
chprintf(chp, "ok\r\n");
}
void cmd_sd_seek(BaseSequentialStream* chp, int argc, char* argv[]) {
if (argc != 1) {
chprintf(chp, "usage: fseek <offset>\r\n");
return;
}
if (shell_file == nullptr) {
chprintf(chp, "no open file\r\n");
return;
}
int address = (int)strtol(argv[0], NULL, 10);
auto error = shell_file->seek(address);
if (report_on_error(chp, error)) return;
chprintf(chp, "ok\r\n");
}
void cmd_sd_close(BaseSequentialStream* chp, int argc, char* argv[]) {
(void)argv;
if (argc != 0) {
chprintf(chp, "usage: fclose\r\n");
return;
}
if (shell_file == nullptr) {
chprintf(chp, "no open file\r\n");
return;
}
auto error = shell_file->sync();
if (report_on_error(chp, error)) return;
delete shell_file;
shell_file = nullptr;
chprintf(chp, "ok\r\n");
}
void cmd_sd_truncate(BaseSequentialStream* chp, int argc, char* argv[]) {
(void)argv;
if (argc != 0) {
chprintf(chp, "usage: ftruncate\r\n");
return;
}
if (shell_file == nullptr) {
chprintf(chp, "no open file\r\n");
return;
}
auto error = shell_file->truncate();
if (report_on_error(chp, error)) return;
chprintf(chp, "ok\r\n");
}
void cmd_sd_sync(BaseSequentialStream* chp, int argc, char* argv[]) {
(void)argv;
if (argc != 0) {
chprintf(chp, "usage: fsync\r\n");
return;
}
if (shell_file == nullptr) {
chprintf(chp, "no open file\r\n");
return;
}
auto error = shell_file->sync();
if (report_on_error(chp, error)) return;
chprintf(chp, "ok\r\n");
}
void cmd_sd_tell(BaseSequentialStream* chp, int argc, char* argv[]) {
(void)argv;
if (argc != 0) {
chprintf(chp, "usage: ftell\r\n");
return;
}
if (shell_file == nullptr) {
chprintf(chp, "no open file\r\n");
return;
}
auto current_position = shell_file->tell();
chprintf(chp, "%d\r\n", current_position);
chprintf(chp, "ok\r\n");
}
void cmd_sd_read(BaseSequentialStream* chp, int argc, char* argv[]) {
if (argc != 1) {
chprintf(chp, "usage: fread <number of bytes>\r\n");
return;
}
if (shell_file == nullptr) {
chprintf(chp, "no open file\r\n");
return;
}
int size = (int)strtol(argv[0], NULL, 10);
uint8_t buffer[62];
do {
File::Size bytes_to_read = size > 62 ? 62 : size;
auto bytes_read = shell_file->read(buffer, bytes_to_read);
if (report_on_error(chp, bytes_read)) return;
std::string res = to_string_hex_array(buffer, bytes_read.value());
res += "\r\n";
fillOBuffer(&((SerialUSBDriver*)chp)->oqueue, (const uint8_t*)res.c_str(), res.size());
if (bytes_to_read != bytes_read.value())
return;
size -= bytes_to_read;
} while (size > 0);
chprintf(chp, "ok\r\n");
}
void cmd_sd_read_binary(BaseSequentialStream* chp, int argc, char* argv[]) {
if (argc != 1) {
chprintf(chp, "usage: frb <number of bytes>\r\n");
return;
}
if (shell_file == nullptr) {
chprintf(chp, "no open file\r\n");
return;
}
int size = (int)strtol(argv[0], NULL, 10);
uint8_t buffer[64];
do {
File::Size bytes_to_read = size > 64 ? 64 : size;
auto bytes_read = shell_file->read(buffer, bytes_to_read);
if (report_on_error(chp, bytes_read)) return;
if (bytes_read.value() > 0)
fillOBuffer(&((SerialUSBDriver*)chp)->oqueue, buffer, bytes_read.value());
if (bytes_to_read != bytes_read.value())
return;
size -= bytes_to_read;
} while (size > 0);
chprintf(chp, "\r\nok\r\n");
}
void cmd_sd_write(BaseSequentialStream* chp, int argc, char* argv[]) {
const char* usage = "usage: fwrite 0123456789ABCDEF\r\n";
if (argc != 1) {
chprintf(chp, usage);
return;
}
if (shell_file == nullptr) {
chprintf(chp, "no open file\r\n");
return;
}
size_t data_string_len = strlen(argv[0]);
if (data_string_len % 2 != 0) {
chprintf(chp, usage);
return;
}
for (size_t i = 0; i < data_string_len; i++) {
char c = argv[0][i];
if ((c < '0' || c > '9') && (c < 'A' || c > 'F')) {
chprintf(chp, usage);
return;
}
}
char buffer[3] = {0, 0, 0};
for (size_t i = 0; i < data_string_len / 2; i++) {
buffer[0] = argv[0][i * 2];
buffer[1] = argv[0][i * 2 + 1];
uint8_t value = (uint8_t)strtol(buffer, NULL, 16);
auto error = shell_file->write(&value, 1);
if (report_on_error(chp, error)) return;
}
chprintf(chp, "ok\r\n");
}
void cmd_sd_write_binary(BaseSequentialStream* chp, int argc, char* argv[]) {
const char* usage = "usage: fwb <number of bytes>\r\nfollowed by <number of bytes> of data";
if (argc != 1) {
chprintf(chp, usage);
return;
}
if (shell_file == nullptr) {
chprintf(chp, "no open file\r\n");
return;
}
size_t size = (size_t)strtol(argv[0], NULL, 10);
chprintf(chp, "send %d bytes\r\n", size);
uint8_t buffer[USB_BULK_BUFFER_SIZE];
do {
size_t bytes_to_read = size > USB_BULK_BUFFER_SIZE ? USB_BULK_BUFFER_SIZE : size;
size_t bytes_read = chSequentialStreamRead(chp, &buffer[0], bytes_to_read);
if (bytes_read != bytes_to_read)
return;
auto error = shell_file->write(&buffer[0], bytes_read);
if (report_on_error(chp, error)) return;
size -= bytes_read;
} while (size > 0);
chprintf(chp, "ok\r\n");
}
@@ -0,0 +1,67 @@
/*
* Copyright (C) 2023 Bernd Herzog
*
* This file is part of PortaPack.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street,
* Boston, MA 02110-1301, USA.
*/
#include "ch.h"
#include "hal.h"
#include <locale>
#include <codecvt>
#include "ff.h"
#include "file.hpp"
void cmd_sd_list_dir(BaseSequentialStream* chp, int argc, char* argv[]);
void cmd_sd_unlink(BaseSequentialStream* chp, int argc, char* argv[]);
void cmd_sd_mkdir(BaseSequentialStream* chp, int argc, char* argv[]);
void cmd_sd_filesize(BaseSequentialStream* chp, int argc, char* argv[]);
void cmd_sd_open(BaseSequentialStream* chp, int argc, char* argv[]);
void cmd_sd_seek(BaseSequentialStream* chp, int argc, char* argv[]);
void cmd_sd_close(BaseSequentialStream* chp, int argc, char* argv[]);
void cmd_sd_truncate(BaseSequentialStream* chp, int argc, char* argv[]);
void cmd_sd_sync(BaseSequentialStream* chp, int argc, char* argv[]);
void cmd_sd_tell(BaseSequentialStream* chp, int argc, char* argv[]);
void cmd_sd_read(BaseSequentialStream* chp, int argc, char* argv[]);
void cmd_sd_read_binary(BaseSequentialStream* chp, int argc, char* argv[]);
void cmd_sd_write(BaseSequentialStream* chp, int argc, char* argv[]);
void cmd_sd_write_binary(BaseSequentialStream* chp, int argc, char* argv[]);
static std::filesystem::path path_from_string8(char* path) {
std::wstring_convert<std::codecvt_utf8_utf16<char16_t>, char16_t> conv;
return conv.from_bytes(path);
}
// clang-format off
#define USB_SERIAL_SHELL_SD_COMMANDS \
{"ls", cmd_sd_list_dir}, \
{"unlink", cmd_sd_unlink}, \
{"mkdir", cmd_sd_mkdir}, \
{"filesize", cmd_sd_filesize}, \
{"fopen", cmd_sd_open}, \
{"fseek", cmd_sd_seek}, \
{"fclose", cmd_sd_close}, \
{"ftruncate", cmd_sd_truncate}, \
{"fsync", cmd_sd_sync}, \
{"ftell", cmd_sd_tell}, \
{"fread", cmd_sd_read}, \
{"frb", cmd_sd_read_binary}, \
{"fwrite", cmd_sd_write}, \
{"fwb", cmd_sd_write_binary}
// clang-format on
+1 -1
View File
@@ -30,7 +30,7 @@
#include "optional.hpp"
#include "chprintf.h"
#include "usb_serial_io.h"
#include "usb_serial_device_to_host.h"
#include <cstdint>
#include <cstddef>
+11 -4
View File
@@ -123,10 +123,10 @@ constexpr gpdma::channel::Config config_rx() {
/* TODO: Clean up terminology around "buffer", "transfer", "samples" */
constexpr size_t buffer_samples_log2n = 7;
constexpr size_t buffer_samples = (1 << buffer_samples_log2n);
constexpr size_t buffer_samples = (1 << buffer_samples_log2n); // 2^7 = 128 byte circular DMA buffer
constexpr size_t transfers_per_buffer_log2n = 2;
constexpr size_t transfers_per_buffer = (1 << transfers_per_buffer_log2n);
constexpr size_t transfer_samples = buffer_samples / transfers_per_buffer;
constexpr size_t transfers_per_buffer = (1 << transfers_per_buffer_log2n); // 2^2 = 4 transfer buffers in the circular buffer
constexpr size_t transfer_samples = buffer_samples / transfers_per_buffer; // 128/4 = 32 samples in each transfer buffer
constexpr size_t transfers_mask = transfers_per_buffer - 1;
constexpr size_t buffer_bytes = buffer_samples * sizeof(sample_t);
@@ -144,6 +144,8 @@ static constexpr auto& gpdma_channel_i2s0_rx = gpdma::channels[portapack::i2s0_r
static volatile const gpdma::channel::LLI* tx_next_lli = nullptr;
static volatile const gpdma::channel::LLI* rx_next_lli = nullptr;
static bool single_tx_buffer = false;
static void tx_transfer_complete() {
tx_next_lli = gpdma_channel_i2s0_tx.next_lli();
}
@@ -213,11 +215,16 @@ void disable() {
gpdma_channel_i2s0_rx.disable();
}
void shrink_tx_buffer() {
single_tx_buffer = true;
lli_tx_loop[0].lli = lli_pointer(&lli_tx_loop[0]);
}
buffer_t tx_empty_buffer() {
const auto next_lli = tx_next_lli;
if (next_lli) {
const size_t next_index = next_lli - &lli_tx_loop[0];
const size_t free_index = (next_index + transfers_per_buffer - 2) & transfers_mask;
const size_t free_index = (single_tx_buffer) ? 0 : (next_index + transfers_per_buffer - 2) & transfers_mask;
return {reinterpret_cast<sample_t*>(lli_tx_loop[free_index].srcaddr), transfer_samples};
} else {
return {nullptr, 0};
+1
View File
@@ -47,6 +47,7 @@ void init();
void configure();
void enable();
void disable();
void shrink_tx_buffer();
audio::buffer_t tx_empty_buffer();
audio::buffer_t rx_empty_buffer();
+14
View File
@@ -95,6 +95,20 @@ void BasebandThread::run() {
buffer_c8_t buffer{
buffer_tmp.p, buffer_tmp.count, sampling_rate_};
if (shared_memory.request_m4_performance_counter == 0x02) {
uint8_t max = shared_memory.m4_performance_counter;
for (size_t i = 0; i < buffer_tmp.count; i++) {
int8_t a = buffer_tmp.p[i].real();
if (a < 0)
a = -a;
if (a > max)
max = a;
}
shared_memory.m4_performance_counter = max;
}
if (baseband_processor_) {
baseband_processor_->execute(buffer);
}
+10 -6
View File
@@ -135,13 +135,17 @@ void update_performance_counters() {
last_paint_state = !last_paint_state;
auto utilisation = get_cpu_utilisation_in_percent();
auto free_stack = (uint32_t)get_free_stack_space();
auto free_heap = chCoreStatus();
if (performance_counter_active == 0x01) {
auto utilisation = get_cpu_utilisation_in_percent();
auto free_stack = (uint32_t)get_free_stack_space();
auto free_heap = chCoreStatus();
shared_memory.m4_cpu_usage = utilisation;
shared_memory.m4_stack_usage = free_stack;
shared_memory.m4_heap_usage = free_heap;
shared_memory.m4_performance_counter = utilisation;
shared_memory.m4_stack_usage = free_stack;
shared_memory.m4_heap_usage = free_heap;
} else if (performance_counter_active == 0x02) {
shared_memory.m4_performance_counter = 0;
}
}
} /* extern "C" */
+8
View File
@@ -41,6 +41,12 @@ void AudioTXProcessor::execute(const buffer_c8_t& buffer) {
}
}
// Output to speaker too
uint32_t imod32 = i & (AUDIO_OUTPUT_BUFFER_SIZE - 1);
audio_data[imod32] = ((int16_t)audio_sample - 0x80) * (1.0f / 128.0f);
if (imod32 == (AUDIO_OUTPUT_BUFFER_SIZE - 1))
audio_output.write(audio_buffer);
sample = tone_gen.process(audio_sample - 0x80);
// FM
@@ -95,6 +101,8 @@ void AudioTXProcessor::audio_config(const AudioTXConfigMessage& message) {
tone_gen.configure(message.tone_key_delta, message.tone_key_mix_weight);
progress_interval_samples = message.divider;
resample_acc = 0;
audio_output.configure(false);
audio::dma::shrink_tx_buffer();
}
void AudioTXProcessor::replay_config(const ReplayConfigMessage& message) {
+8
View File
@@ -27,6 +27,10 @@
#include "baseband_thread.hpp"
#include "tone_gen.hpp"
#include "stream_output.hpp"
#include "audio_output.hpp"
#include "audio_dma.hpp"
#define AUDIO_OUTPUT_BUFFER_SIZE 32
class AudioTXProcessor : public BasebandProcessor {
public:
@@ -48,6 +52,10 @@ class AudioTXProcessor : public BasebandProcessor {
int32_t sample{0}, delta{};
int8_t re{0}, im{0};
float audio_data[AUDIO_OUTPUT_BUFFER_SIZE];
buffer_f32_t audio_buffer{audio_data, AUDIO_OUTPUT_BUFFER_SIZE, 48000};
AudioOutput audio_output{};
size_t progress_interval_samples = 0, progress_samples = 0;
bool configured{false};
@@ -186,7 +186,7 @@ uint8_t usb_descriptor_string_manufacturer[] = {
uint8_t usb_descriptor_string_product[] = {
#ifdef HACKRF_ONE
43, // bLength
34, // bLength
USB_DESCRIPTOR_TYPE_STRING, // bDescriptorType
'P', 0x00,
'o', 0x00,
+31
View File
@@ -118,6 +118,8 @@ class Message {
SubGhzFPRxConfigure = 60,
WeatherData = 61,
SubGhzDData = 62,
GPSPosData = 63,
OrientationData = 64,
MAX
};
@@ -1301,4 +1303,33 @@ class SubGhzDDataMessage : public Message {
uint64_t data = 0;
};
class GPSPosDataMessage : public Message {
public:
constexpr GPSPosDataMessage(
float lat = 200.0,
float lon = 200.0,
int32_t altitude = 0,
int32_t speed = 0)
: Message{ID::GPSPosData},
lat{lat},
lon{lon},
altitude{altitude},
speed{speed} {
}
float lat = 200.0;
float lon = 200.0;
int32_t altitude = 0;
int32_t speed = 0;
};
class OrientationDataMessage : public Message {
public:
constexpr OrientationDataMessage(
uint16_t angle = 400)
: Message{ID::OrientationData},
angle{angle} {
}
uint16_t angle = 400; //>360 -> no orientation set
};
#endif /*__MESSAGE_H__*/
@@ -963,7 +963,7 @@ bool should_use_sdcard_for_pmem() {
int save_persistent_settings_to_file() {
File outfile;
make_new_directory(SETTINGS_DIR);
ensure_directory(SETTINGS_DIR);
auto error = outfile.create(PMEM_SETTING_FILE);
if (error)
return false;
@@ -996,7 +996,7 @@ bool debug_dump() {
std::filesystem::path filename{};
File pmem_dump_file{};
// create new dump file name and DEBUG directory
make_new_directory(debug_dir);
ensure_directory(debug_dir);
filename = next_filename_matching_pattern(debug_dir + "/DEBUG_DUMP_????.TXT");
if (filename.empty()) {
painter.draw_string({0, 320 - 16}, ui::Styles::red, "COULD NOT GET DUMP NAME !");
@@ -33,10 +33,10 @@
#include "serializer.hpp"
#include "volume.hpp"
// persistant memory from/to sdcard flag file
// persistent memory from/to sdcard flag file
#define PMEM_FILEFLAG u"/SETTINGS/PMEM_FILEFLAG"
// persistant memory from/to sdcard flag file
// persistent memory from/to sdcard flag file
#define PMEM_SETTING_FILE u"/SETTINGS/pmem_settings"
#define PMEM_SIZE_BYTES 256 // total amount of pmem space in bytes, including checksum
+1 -1
View File
@@ -71,7 +71,7 @@ struct SharedMemory {
void set_baseband_ready() { baseband_ready = true; }
uint8_t volatile request_m4_performance_counter{0};
uint8_t volatile m4_cpu_usage{0};
uint8_t volatile m4_performance_counter{0};
uint16_t volatile m4_stack_usage{0};
uint32_t volatile m4_heap_usage{0};
uint16_t volatile m4_buffer_missed{0};
+1 -1
View File
@@ -31,7 +31,7 @@
#include "chprintf.h"
#include "irq_controls.hpp"
#include "string_format.hpp"
#include "usb_serial_io.h"
#include "usb_serial_device_to_host.h"
using namespace portapack;
+1 -13
View File
@@ -53,7 +53,6 @@ class UnTar {
}
static bool create_dir(char* pathname) {
char* p;
std::filesystem::filesystem_error r;
if (!isValidName(pathname)) return false;
@@ -65,18 +64,7 @@ class UnTar {
std::string dirnameStr = u'/' + pathname;
std::filesystem::path dirname = dirnameStr;
r = make_new_directory(dirname);
if (!r.ok()) {
/* On failure, try creating parent directory. */
p = strrchr(pathname, '/');
if (p != NULL) {
*p = '\0';
create_dir(pathname);
*p = '/';
r = make_new_directory(dirname);
}
}
r = ensure_directory(dirname);
return (r.ok());
}
+1 -1
View File
@@ -1,2 +1,2 @@
[InternetShortcut]
URL=https://github.com/eried/portapack-mayhem/releases
URL=https://github.com/portapack-mayhem/mayhem-firmware/releases
+1 -1
View File
@@ -1,2 +1,2 @@
[InternetShortcut]
URL=https://github.com/eried/portapack-mayhem/wiki/Update-firmware
URL=https://github.com/portapack-mayhem/mayhem-firmware/wiki/Update-firmware
+1 -1
View File
@@ -1,3 +1,3 @@
Plug HackRF+Portapack, set it in HackRF mode, launch flash_portapack_mayhem.bat
Read https://github.com/eried/portapack-mayhem/wiki/Update-firmware for more detailed information
Read https://github.com/portapack-mayhem/mayhem-firmware/wiki/Update-firmware for more detailed information
+2 -2
View File
@@ -15,7 +15,7 @@ REM Check if the firmware file exists
if not exist portapack-h1_h2-mayhem.bin (
echo The firmware file "portapack-h1_h2-mayhem.bin" does not exist.
echo Please ensure that you have downloaded the latest release from:
echo https://github.com/eried/portapack-mayhem/releases/
echo https://github.com/portapack-mayhem/mayhem-firmware/releases/
echo.
pause
exit /b
@@ -23,6 +23,6 @@ if not exist portapack-h1_h2-mayhem.bin (
"utils/hackrf_update.exe" portapack-h1_h2-mayhem.bin
echo.
echo If your device never boot after flashing, please refer to https://github.com/eried/portapack-mayhem/wiki/Won't-boot
echo If your device never boot after flashing, please refer to https://github.com/portapack-mayhem/mayhem-firmware/wiki/Won't-boot
echo.
pause
@@ -1,2 +1,2 @@
[InternetShortcut]
URL=https://github.com/eried/portapack-havoc/wiki/GPS-Sim
URL=https://github.com/portapack-mayhem/mayhem-firmware/wiki/GPS-Sim
+1 -1
View File
@@ -2,7 +2,7 @@
Sample files below can be used with Replay app.
See [Wiki](https://github.com/eried/portapack-mayhem/wiki/C16-format) for more info over C16 file format.
See [Wiki](https://github.com/portapack-mayhem/mayhem-firmware/wiki/C16-format) for more info over C16 file format.
| file | description | frequency |
| ------ | ------ | ------: |
+2 -2
View File
@@ -8,8 +8,8 @@ for the current splash screen to appear at power up, the "Show splash screen" op
must also be enabled under Settings->UserInterface.
For more information on Splash Screens, see the following Wiki pages:
https://github.com/eried/portapack-mayhem/wiki/Create-a-custom-splash-screen
https://github.com/eried/portapack-mayhem/wiki/File-manager
https://github.com/portapack-mayhem/mayhem-firmware/wiki/Create-a-custom-splash-screen
https://github.com/portapack-mayhem/mayhem-firmware/wiki/File-manager
Many additional Mayhem splash screens that users have shared online may be found in
the Mayhem #splash-screens channel on Discord.