mirror of
https://github.com/eried/portapack-mayhem.git
synced 2024-10-01 01:26:06 -04:00
commit
22f490e8d3
3
.github/ISSUE_TEMPLATE/01_bug_report.yml
vendored
3
.github/ISSUE_TEMPLATE/01_bug_report.yml
vendored
@ -1,6 +1,7 @@
|
|||||||
name: Bug report
|
name: Bug report
|
||||||
description: File a bug reports regarding the firmware.
|
description: File a bug reports regarding the firmware.
|
||||||
labels: ['bug']
|
labels:
|
||||||
|
- bug
|
||||||
body:
|
body:
|
||||||
- type: markdown
|
- type: markdown
|
||||||
attributes:
|
attributes:
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
name: Feature Request
|
name: Feature Request
|
||||||
description: For feature requests regarding the firmware.
|
description: For feature requests regarding the firmware.
|
||||||
labels: ['feature request']
|
labels:
|
||||||
|
- enhancement
|
||||||
body:
|
body:
|
||||||
- type: markdown
|
- type: markdown
|
||||||
attributes:
|
attributes:
|
||||||
|
@ -1,44 +0,0 @@
|
|||||||
---
|
|
||||||
name: Problem upgrading the firmware or booting
|
|
||||||
about: If you are having firmware upgrade or booting problems
|
|
||||||
title: ''
|
|
||||||
labels: 'firmware'
|
|
||||||
assignees: ''
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
----
|
|
||||||
Before creating this issue, **do the following**:
|
|
||||||
* Read the Wiki on booting: https://github.com/portapack-mayhem/mayhem-firmware/wiki/Won't-boot
|
|
||||||
* Read: https://github.com/portapack-mayhem/mayhem-firmware/wiki/Update-firmware
|
|
||||||
* Watch carefully: https://www.youtube.com/watch?v=_zx4ZvurgOs
|
|
||||||
* (if you are not in Windows) also check: https://www.youtube.com/watch?v=kjFB58Y1TAo
|
|
||||||
|
|
||||||
----
|
|
||||||
|
|
||||||
**Describe the issue**
|
|
||||||
A clear and concise description of what the issue you are facing is.
|
|
||||||
|
|
||||||
**To Reproduce**
|
|
||||||
Steps to reproduce the behavior:
|
|
||||||
1. Go to '...'
|
|
||||||
2. Tap on '....'
|
|
||||||
|
|
||||||
|
|
||||||
**My Hardware**
|
|
||||||
Please specify what PortaPack hardware version you are using.
|
|
||||||
You can find the list of versions here: https://github.com/portapack-mayhem/mayhem-firmware/wiki/PortaPack-Versions
|
|
||||||
|
|
||||||
**Affected versions**
|
|
||||||
Please tell us what version you are running.
|
|
||||||
If your device is still functional, try the latest nightly release before submitting this.
|
|
||||||
You can find the latest nightly version here https://github.com/portapack-mayhem/mayhem-firmware/releases
|
|
||||||
|
|
||||||
**Were you able to update the firmware before?**
|
|
||||||
Things might be confusing the first time, please check the video available on the link above.
|
|
||||||
|
|
||||||
**Can you try the upgrade with a different PC/Portapack/HackRF?**
|
|
||||||
If is possible, swap hardware and try again. Also, try different USB cables, even if the one you are using works fine for other purposes.
|
|
||||||
|
|
||||||
**Additional**
|
|
||||||
If the issue is difficult to explain, additionally to the text please include images and videos.
|
|
45
.github/ISSUE_TEMPLATE/03_problem-upgrading-the-firmware.yml
vendored
Normal file
45
.github/ISSUE_TEMPLATE/03_problem-upgrading-the-firmware.yml
vendored
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
name: Firmware/boot issue
|
||||||
|
description: If you are having firmware upgrade or booting problems.
|
||||||
|
labels:
|
||||||
|
- firmware
|
||||||
|
body:
|
||||||
|
- type: markdown
|
||||||
|
attributes:
|
||||||
|
value: >2-
|
||||||
|
Thank you for taking the time to fill out an issue, this template is meant for any issues related to the Mayhem firmware.
|
||||||
|
Before creating this issue, **do the following**:
|
||||||
|
* Read the Wiki on booting:
|
||||||
|
https://github.com/portapack-mayhem/mayhem-firmware/wiki/Won't-boot
|
||||||
|
|
||||||
|
* Read:
|
||||||
|
https://github.com/portapack-mayhem/mayhem-firmware/wiki/Update-firmware
|
||||||
|
|
||||||
|
* Watch carefully: https://www.youtube.com/watch?v=_zx4ZvurgOs
|
||||||
|
|
||||||
|
* (if you are not in Windows) also check:
|
||||||
|
https://www.youtube.com/watch?v=kjFB58Y1TAo
|
||||||
|
|
||||||
|
* Check hardware versions:
|
||||||
|
https://github.com/portapack-mayhem/mayhem-firmware/wiki/PortaPack-Versions
|
||||||
|
- type: textarea
|
||||||
|
id: problem
|
||||||
|
attributes:
|
||||||
|
label: What happened?
|
||||||
|
description: If after following the above troubleshooting the problem still remains
|
||||||
|
placeholder: Describe what was is the problem
|
||||||
|
- type: input
|
||||||
|
id: hardware
|
||||||
|
attributes:
|
||||||
|
label: Your hardware
|
||||||
|
description: Check the link with the versions above
|
||||||
|
placeholder: Which device you have?
|
||||||
|
- type: checkboxes
|
||||||
|
id: firmware_update_before
|
||||||
|
attributes:
|
||||||
|
label: Tests
|
||||||
|
description: >-
|
||||||
|
Things might be confusing the first time, please check the documentation
|
||||||
|
above
|
||||||
|
options:
|
||||||
|
- label: I managed to update/boot previously
|
||||||
|
required: false
|
4
.github/workflows/create_nightly_release.yml
vendored
4
.github/workflows/create_nightly_release.yml
vendored
@ -54,7 +54,7 @@ jobs:
|
|||||||
run: docker run -e VERSION_STRING=${{ steps.version_date.outputs.date }} -i -v ${{ github.workspace }}:/havoc portapack-dev
|
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
|
- name: Create Small SD Card ZIP - No World Map
|
||||||
run: |
|
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 && cd sdcard && zip -r ../sdcard-no-map.zip . && cd ..
|
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 && cp build/firmware/standalone/*/*.ppmp sdcard/APPS && cd sdcard && zip -r ../sdcard-no-map.zip . && cd ..
|
||||||
- name: Download world map
|
- name: Download world map
|
||||||
run: |
|
run: |
|
||||||
wget https://github.com/portapack-mayhem/mayhem-firmware/releases/download/world_map/world_map.zip
|
wget https://github.com/portapack-mayhem/mayhem-firmware/releases/download/world_map/world_map.zip
|
||||||
@ -66,7 +66,7 @@ jobs:
|
|||||||
zip -j firmware.zip build/firmware/portapack-h1_h2-mayhem.bin && cd flashing && zip -r ../firmware.zip *
|
zip -j firmware.zip build/firmware/portapack-h1_h2-mayhem.bin && cd flashing && zip -r ../firmware.zip *
|
||||||
- name: Create SD Card ZIP
|
- name: Create SD Card ZIP
|
||||||
run: |
|
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 && cd sdcard && zip -r ../sdcard.zip . && cd ..
|
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 && cp build/firmware/standalone/*/*.ppmp sdcard/APPS && cd sdcard && zip -r ../sdcard.zip . && cd ..
|
||||||
- name: Create changelog
|
- name: Create changelog
|
||||||
env:
|
env:
|
||||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
4
.github/workflows/create_stable_release.yml
vendored
4
.github/workflows/create_stable_release.yml
vendored
@ -38,7 +38,7 @@ jobs:
|
|||||||
run: docker run -e VERSION_STRING=${{ steps.version.outputs.version }} -i -v ${{ github.workspace }}:/havoc portapack-dev
|
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
|
- name: Create Small SD Card ZIP - No World Map
|
||||||
run: |
|
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 && cd sdcard && zip -r ../sdcard-no-map.zip . && cd ..
|
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 && cp build/firmware/standalone/*/*.ppmp sdcard/APPS && cd sdcard && zip -r ../sdcard-no-map.zip . && cd ..
|
||||||
- name: Download world map
|
- name: Download world map
|
||||||
run: |
|
run: |
|
||||||
wget https://github.com/portapack-mayhem/mayhem-firmware/releases/download/world_map/world_map.zip
|
wget https://github.com/portapack-mayhem/mayhem-firmware/releases/download/world_map/world_map.zip
|
||||||
@ -50,7 +50,7 @@ jobs:
|
|||||||
zip -j firmware.zip build/firmware/portapack-h1_h2-mayhem.bin && cd flashing && zip -r ../firmware.zip *
|
zip -j firmware.zip build/firmware/portapack-h1_h2-mayhem.bin && cd flashing && zip -r ../firmware.zip *
|
||||||
- name: Create SD Card ZIP
|
- name: Create SD Card ZIP
|
||||||
run: |
|
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 && cd sdcard && zip -r ../sdcard.zip . && cd ..
|
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 && cp build/firmware/standalone/*/*.ppmp sdcard/APPS && cd sdcard && zip -r ../sdcard.zip . && cd ..
|
||||||
- name: Create changelog
|
- name: Create changelog
|
||||||
env:
|
env:
|
||||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
2
.github/workflows/past_version.txt
vendored
2
.github/workflows/past_version.txt
vendored
@ -1 +1 @@
|
|||||||
v2.0.0
|
v2.0.1
|
||||||
|
2
.github/workflows/version.txt
vendored
2
.github/workflows/version.txt
vendored
@ -1 +1 @@
|
|||||||
v2.0.1
|
v2.0.2
|
||||||
|
1
.gitignore
vendored
1
.gitignore
vendored
@ -51,6 +51,7 @@
|
|||||||
.dep/
|
.dep/
|
||||||
/build*
|
/build*
|
||||||
CMakeFiles/
|
CMakeFiles/
|
||||||
|
cmake-build-debug/
|
||||||
|
|
||||||
# Debugging
|
# Debugging
|
||||||
.gdbinit*
|
.gdbinit*
|
||||||
|
148
.vscode/launch.json
vendored
Normal file
148
.vscode/launch.json
vendored
Normal file
@ -0,0 +1,148 @@
|
|||||||
|
{
|
||||||
|
// Use IntelliSense to learn about possible attributes.
|
||||||
|
// Hover to view descriptions of existing attributes.
|
||||||
|
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
|
||||||
|
"version": "0.2.0",
|
||||||
|
"configurations": [
|
||||||
|
{
|
||||||
|
"name": "(gdb) JTAG probe",
|
||||||
|
"type": "cppdbg",
|
||||||
|
"request": "launch",
|
||||||
|
"miDebuggerPath": "arm-none-eabi-gdb",
|
||||||
|
"targetArchitecture": "arm",
|
||||||
|
"program": "${workspaceRoot}/build/firmware/baseband/baseband_adsbrx.elf",
|
||||||
|
"cwd": "${workspaceRoot}",
|
||||||
|
"setupCommands": [
|
||||||
|
// use logging for troubleshooting
|
||||||
|
//{"text": "set logging file ${workspaceRoot}/build/arm-none-eabi-gdb.log"},
|
||||||
|
//{"text": "set logging on"},
|
||||||
|
{
|
||||||
|
"text": "file '${workspaceRoot}/build/firmware/baseband/baseband_adsbrx.elf'"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"text": "target extended-remote /dev/ttyACM0"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"text": "monitor swdp_scan"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"text": "attach 1"
|
||||||
|
},
|
||||||
|
],
|
||||||
|
"launchCompleteCommand": "None",
|
||||||
|
"externalConsole": false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "(gdb) OpenOCD m4 baseband",
|
||||||
|
"type": "cppdbg",
|
||||||
|
"request": "launch",
|
||||||
|
"program": "${workspaceRoot}/build/firmware/baseband/baseband_sd_over_usb.elf",
|
||||||
|
"args": [],
|
||||||
|
"cwd": "${workspaceRoot}",
|
||||||
|
// "environment": [
|
||||||
|
// {
|
||||||
|
// "name": "PATH",
|
||||||
|
// "value": "${env:PATH}"
|
||||||
|
// }
|
||||||
|
// ],
|
||||||
|
"externalConsole": false,
|
||||||
|
"MIMode": "gdb",
|
||||||
|
"miDebuggerPath": "arm-none-eabi-gdb",
|
||||||
|
"targetArchitecture": "arm",
|
||||||
|
"debugServerPath": "openocd",
|
||||||
|
"debugServerArgs": "-f interface/ftdi/um232h.cfg -f target/lpc4350.cfg -c \"gdb_breakpoint_override hard\"",
|
||||||
|
"serverStarted": "Listening on port [0-9]+ for gdb connections",
|
||||||
|
"filterStderr": true,
|
||||||
|
"filterStdout": false,
|
||||||
|
"launchCompleteCommand": "None",
|
||||||
|
"postRemoteConnectCommands": [
|
||||||
|
{
|
||||||
|
"description": "Target Remote Device on Port 3333",
|
||||||
|
"text": "target extended-remote :3333",
|
||||||
|
"ignoreFailures": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"description": "Respect Hardware Limitations",
|
||||||
|
"text": "set remote hardware-watchpoint-limit 2",
|
||||||
|
"ignoreFailures": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"description": "Respect Hardware Limitations",
|
||||||
|
"text": "set remote hardware-breakpoint-limit 4",
|
||||||
|
"ignoreFailures": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"description": "Shutdown GDB Server on GDB Detach",
|
||||||
|
"text": "monitor [target current] configure -event gdb-detach { shutdown }",
|
||||||
|
"ignoreFailures": false
|
||||||
|
},
|
||||||
|
],
|
||||||
|
"stopAtConnect": false,
|
||||||
|
"logging": {
|
||||||
|
"exceptions": true,
|
||||||
|
"engineLogging": false,
|
||||||
|
"moduleLoad": true,
|
||||||
|
"programOutput": true,
|
||||||
|
"trace": false,
|
||||||
|
"traceResponse": false
|
||||||
|
},
|
||||||
|
"useExtendedRemote": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "(gdb) OpenOCD m0 application",
|
||||||
|
"type": "cppdbg",
|
||||||
|
"request": "launch",
|
||||||
|
"program": "${workspaceRoot}/build/firmware/application/application.elf",
|
||||||
|
"args": [],
|
||||||
|
"cwd": "${workspaceRoot}",
|
||||||
|
// "environment": [
|
||||||
|
// {
|
||||||
|
// "name": "PATH",
|
||||||
|
// "value": "${env:PATH}"
|
||||||
|
// }
|
||||||
|
// ],
|
||||||
|
"externalConsole": false,
|
||||||
|
"MIMode": "gdb",
|
||||||
|
"miDebuggerPath": "arm-none-eabi-gdb",
|
||||||
|
"targetArchitecture": "arm",
|
||||||
|
"debugServerPath": "openocd",
|
||||||
|
"debugServerArgs": "-f interface/ftdi/um232h.cfg -f target/lpc4350.cfg -c \"gdb_breakpoint_override hard\"",
|
||||||
|
"serverStarted": "Listening on port [0-9]+ for gdb connections",
|
||||||
|
"filterStderr": true,
|
||||||
|
"filterStdout": false,
|
||||||
|
"launchCompleteCommand": "None",
|
||||||
|
"postRemoteConnectCommands": [
|
||||||
|
{
|
||||||
|
"description": "Target Remote Device on Port 3334",
|
||||||
|
"text": "target extended-remote :3334",
|
||||||
|
"ignoreFailures": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"description": "Respect Hardware Limitations",
|
||||||
|
"text": "set remote hardware-watchpoint-limit 1",
|
||||||
|
"ignoreFailures": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"description": "Respect Hardware Limitations",
|
||||||
|
"text": "set remote hardware-breakpoint-limit 2",
|
||||||
|
"ignoreFailures": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"description": "Shutdown GDB Server on GDB Detach",
|
||||||
|
"text": "monitor [target current] configure -event gdb-detach { shutdown }",
|
||||||
|
"ignoreFailures": false
|
||||||
|
},
|
||||||
|
],
|
||||||
|
"stopAtConnect": false,
|
||||||
|
"logging": {
|
||||||
|
"exceptions": true,
|
||||||
|
"engineLogging": false,
|
||||||
|
"moduleLoad": true,
|
||||||
|
"programOutput": true,
|
||||||
|
"trace": false,
|
||||||
|
"traceResponse": false
|
||||||
|
},
|
||||||
|
"useExtendedRemote": true
|
||||||
|
},
|
||||||
|
]
|
||||||
|
}
|
@ -72,12 +72,13 @@ set(HACKRF_CPLD_XSVF_PATH ${HACKRF_PATH}/firmware/cpld/sgpio_if/${HACKRF_CPLD_XS
|
|||||||
set(HACKRF_FIRMWARE_DFU_IMAGE ${hackrf_usb_BINARY_DIR}/${HACKRF_FIRMWARE_DFU_FILENAME})
|
set(HACKRF_FIRMWARE_DFU_IMAGE ${hackrf_usb_BINARY_DIR}/${HACKRF_FIRMWARE_DFU_FILENAME})
|
||||||
set(HACKRF_FIRMWARE_BIN_IMAGE ${hackrf_usb_BINARY_DIR}/${HACKRF_FIRMWARE_BIN_FILENAME})
|
set(HACKRF_FIRMWARE_BIN_IMAGE ${hackrf_usb_BINARY_DIR}/${HACKRF_FIRMWARE_BIN_FILENAME})
|
||||||
|
|
||||||
find_program(CCACHE "ccache")
|
# this seems causing some issues (ref. in discord discussions), so temporarily disabled, until figure out the pros and cons and bugs of this tool.
|
||||||
if(CCACHE)
|
#find_program(CCACHE "ccache")
|
||||||
set(CMAKE_C_COMPILER_LAUNCHER ${CCACHE})
|
#if(CCACHE)
|
||||||
set(CMAKE_CXX_COMPILER_LAUNCHER ${CCACHE})
|
# set(CMAKE_C_COMPILER_LAUNCHER ${CCACHE})
|
||||||
set(ENV{CCACHE_SLOPPINESS} pch_defines,time_macros)
|
# set(CMAKE_CXX_COMPILER_LAUNCHER ${CCACHE})
|
||||||
endif(CCACHE)
|
# set(ENV{CCACHE_SLOPPINESS} pch_defines,time_macros)
|
||||||
|
#endif(CCACHE)
|
||||||
|
|
||||||
enable_testing()
|
enable_testing()
|
||||||
add_subdirectory(firmware)
|
add_subdirectory(firmware)
|
||||||
|
25
README.md
25
README.md
@ -1,6 +1,7 @@
|
|||||||
> [!WARNING]
|
> [!WARNING]
|
||||||
> __IF YOU'VE PAID FOR MAYHEM OR ANY PREPACKAGED PACKAGES, YOU'RE BEING SCAMMED.__
|
> __IF YOU'VE PAID FOR MAYHEM OR ANY PREPACKAGED VERSIONS, YOU'RE BEING SCAMMED.__
|
||||||
> The only legitimate link leading to our repositories is the organization [portapack-mayhem](https://github.com/portapack-mayhem/mayhem-firmware).
|
>
|
||||||
|
> The only legitimate link to our repositories is the [portapack-mayhem](https://github.com/portapack-mayhem/mayhem-firmware) organization on GitHub.
|
||||||
|
|
||||||
# PortaPack Mayhem
|
# PortaPack Mayhem
|
||||||
|
|
||||||
@ -10,15 +11,15 @@ This is a fork of the [Havoc](https://github.com/furrtek/portapack-havoc/) firmw
|
|||||||
|
|
||||||
[<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)
|
[<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/portapack-mayhem/mayhem-firmware/wiki/H2-Enclosure)*
|
*[PortaPack H2+HackRF+battery](https://grabify.link/7T28JP) (clone) with a custom [3d printed case](https://github.com/portapack-mayhem/mayhem-firmware/wiki/H2-Enclosure)*
|
||||||
|
|
||||||
# What is this?
|
# What is this?
|
||||||
|
|
||||||
If you are new to *HackRF+PortaPack+Mayhem*, check these:
|
If you are new to *HackRF+PortaPack+Mayhem*, check these:
|
||||||
|
|
||||||
[<img alt="HackRF 101 : Everything You Need to Know to Get Started!" src="https://img.youtube.com/vi/xGR_PMD9LeU/maxresdefault.jpg" width="512">](https://grabify.link/C0J6ZR)
|
[<img alt="It’s TOO Easy to Accidentally Do Illegal Stuff with This" src="https://img.youtube.com/vi/OPckpjBSAOw/maxresdefault.jpg" width="700">](https://grabify.link/X4D5TF)
|
||||||
|
|
||||||
[<img alt="Beginner's Guide To The HackRF & Portapak With Mayhem" src="https://img.youtube.com/vi/H-bqdWfbhpg/maxresdefault.jpg" width="254">](https://grabify.link/5MU2VH) [<img alt="What is the HackRF One Portapack H2+?" src="https://img.youtube.com/vi/alrFbY5vxt4/maxresdefault.jpg" width="254">](https://grabify.link/9UZGEW)
|
[<img alt="What is the HackRF One Portapack H2+?" src="https://img.youtube.com/vi/alrFbY5vxt4/maxresdefault.jpg" width="230">](https://grabify.link/9UZGEW) [<img alt="Beginner's Guide To The HackRF & Portapak With Mayhem" src="https://img.youtube.com/vi/H-bqdWfbhpg/maxresdefault.jpg" width="230">](https://grabify.link/5MU2VH) [<img alt="HackRF 101 : Everything You Need to Know to Get Started!" src="https://img.youtube.com/vi/xGR_PMD9LeU/maxresdefault.jpg" width="230">](https://grabify.link/C0J6ZR)
|
||||||
|
|
||||||
# Frequently Asked Questions
|
# Frequently Asked Questions
|
||||||
|
|
||||||
@ -26,9 +27,11 @@ This repository expands upon the previous work by many people and aims to consta
|
|||||||
|
|
||||||
## What to buy?
|
## 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/portapack-mayhem/mayhem-firmware/wiki/H2-Enclosure).
|
:heavy_check_mark: ![Static Badge](https://img.shields.io/badge/NEW-yellow) The fabulous [PortaPack H4M Mayhem](https://grabify.link/VPMPSL), featuring numerous improvements and accessories. Sold by our friends at OpenSourceSDRLab. Join their giveaways on discord (check the badge on top).
|
||||||
|
|
||||||
: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.
|
:heavy_check_mark: A recommended one is this [PortaPack H2](https://grabify.link/7T28JP), 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: Some individuals lean towards the [H2 with a metal enclosure](https://grabify.link/HTDXG5), but its advantages remain debated. Share your insights on our [wiki](https://github.com/portapack-mayhem/mayhem-firmware/wiki/Hardware-overview).
|
||||||
|
|
||||||
:warning: Be cautious , *ask* the seller about compatibility with the latest releases. Look out for the description of the item, if they provide the firmware files for an older version or they have custom setup instructions, this means it might be **NOT compatible**, for example:
|
:warning: Be cautious , *ask* the seller about compatibility with the latest releases. Look out for the description of the item, if they provide the firmware files for an older version or they have custom setup instructions, this means it might be **NOT compatible**, for example:
|
||||||
|
|
||||||
@ -52,13 +55,7 @@ Consider that the hardware and firmware has been created and maintain by a [lot]
|
|||||||
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).
|
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?
|
## What if I really want something specific?
|
||||||
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).
|
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). Alternatively, go to our Discord by clicking the chat badge on [top](#portapack-mayhem) and discuss there.
|
||||||
|
|
||||||
<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?
|
## What if I need help?
|
||||||
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).
|
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).
|
||||||
|
@ -50,6 +50,7 @@ endif()
|
|||||||
|
|
||||||
add_subdirectory(application)
|
add_subdirectory(application)
|
||||||
add_subdirectory(baseband)
|
add_subdirectory(baseband)
|
||||||
|
add_subdirectory(standalone)
|
||||||
add_subdirectory(test)
|
add_subdirectory(test)
|
||||||
|
|
||||||
# NOTE: Dependencies break if the .bin files aren't included in DEPENDS. WTF, CMake?
|
# NOTE: Dependencies break if the .bin files aren't included in DEPENDS. WTF, CMake?
|
||||||
@ -88,7 +89,7 @@ add_custom_target(
|
|||||||
program-external-apps
|
program-external-apps
|
||||||
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
|
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
|
||||||
COMMAND ${PROJECT_SOURCE_DIR}/tools/copy_external_apps.sh
|
COMMAND ${PROJECT_SOURCE_DIR}/tools/copy_external_apps.sh
|
||||||
DEPENDS program
|
DEPENDS program standalone_apps
|
||||||
)
|
)
|
||||||
|
|
||||||
add_custom_command(
|
add_custom_command(
|
||||||
@ -100,8 +101,9 @@ add_custom_command(
|
|||||||
COMMAND cp ${FIRMWARE_FILENAME} firmware_tar/FIRMWARE/portapack-mayhem_${VERSION_NOHASH}.bin
|
COMMAND cp ${FIRMWARE_FILENAME} firmware_tar/FIRMWARE/portapack-mayhem_${VERSION_NOHASH}.bin
|
||||||
COMMAND mkdir -p firmware_tar/APPS
|
COMMAND mkdir -p firmware_tar/APPS
|
||||||
COMMAND cp application/*.ppma firmware_tar/APPS
|
COMMAND cp application/*.ppma firmware_tar/APPS
|
||||||
|
COMMAND cp standalone/*/*.ppmp firmware_tar/APPS
|
||||||
COMMAND cd firmware_tar && tar -cvaf ../${PPFW_FILENAME} *
|
COMMAND cd firmware_tar && tar -cvaf ../${PPFW_FILENAME} *
|
||||||
DEPENDS firmware ${FIRMWARE_FILENAME}
|
DEPENDS firmware ${FIRMWARE_FILENAME} standalone_apps
|
||||||
# Dont use VERBATIM here as it prevents usage of globbing (*)
|
# Dont use VERBATIM here as it prevents usage of globbing (*)
|
||||||
# There shouldnt be any funny business in the filenames above :)
|
# There shouldnt be any funny business in the filenames above :)
|
||||||
)
|
)
|
||||||
|
@ -176,7 +176,11 @@ set(CPPSRC
|
|||||||
${COMMON}/ui_language.cpp
|
${COMMON}/ui_language.cpp
|
||||||
${COMMON}/utility.cpp
|
${COMMON}/utility.cpp
|
||||||
${COMMON}/wm8731.cpp
|
${COMMON}/wm8731.cpp
|
||||||
|
${COMMON}/ads1110.cpp
|
||||||
|
${COMMON}/max17055.cpp
|
||||||
|
${COMMON}/battery.cpp
|
||||||
${COMMON}/performance_counter.cpp
|
${COMMON}/performance_counter.cpp
|
||||||
|
${COMMON}/bmpfile.cpp
|
||||||
app_settings.cpp
|
app_settings.cpp
|
||||||
audio.cpp
|
audio.cpp
|
||||||
baseband_api.cpp
|
baseband_api.cpp
|
||||||
@ -202,6 +206,7 @@ set(CPPSRC
|
|||||||
irq_rtc.cpp
|
irq_rtc.cpp
|
||||||
log_file.cpp
|
log_file.cpp
|
||||||
metadata_file.cpp
|
metadata_file.cpp
|
||||||
|
flipper_subfile.cpp
|
||||||
portapack.cpp
|
portapack.cpp
|
||||||
usb_serial_shell.cpp
|
usb_serial_shell.cpp
|
||||||
usb_serial_shell_filesystem.cpp
|
usb_serial_shell_filesystem.cpp
|
||||||
@ -209,6 +214,7 @@ set(CPPSRC
|
|||||||
usb_serial_thread.cpp
|
usb_serial_thread.cpp
|
||||||
usb_serial.cpp
|
usb_serial.cpp
|
||||||
usb_serial_host_to_device.cpp
|
usb_serial_host_to_device.cpp
|
||||||
|
usb_serial_asyncmsg.cpp
|
||||||
qrcodegen.cpp
|
qrcodegen.cpp
|
||||||
radio.cpp
|
radio.cpp
|
||||||
receiver_model.cpp
|
receiver_model.cpp
|
||||||
@ -221,6 +227,7 @@ set(CPPSRC
|
|||||||
spectrum_color_lut.cpp
|
spectrum_color_lut.cpp
|
||||||
string_format.cpp
|
string_format.cpp
|
||||||
temperature_logger.cpp
|
temperature_logger.cpp
|
||||||
|
theme.cpp
|
||||||
touch.cpp
|
touch.cpp
|
||||||
tone_key.cpp
|
tone_key.cpp
|
||||||
transmitter_model.cpp
|
transmitter_model.cpp
|
||||||
@ -254,11 +261,11 @@ set(CPPSRC
|
|||||||
ui/ui_freqlist.cpp
|
ui/ui_freqlist.cpp
|
||||||
ui/ui_tv.cpp
|
ui/ui_tv.cpp
|
||||||
ui/ui_spectrum.cpp
|
ui/ui_spectrum.cpp
|
||||||
ui/ui_styles.cpp
|
|
||||||
ui/ui_tabview.cpp
|
ui/ui_tabview.cpp
|
||||||
ui/ui_textentry.cpp
|
ui/ui_textentry.cpp
|
||||||
ui/ui_tone_key.cpp
|
ui/ui_tone_key.cpp
|
||||||
ui/ui_transmitter.cpp
|
ui/ui_transmitter.cpp
|
||||||
|
ui/ui_bmpview.cpp
|
||||||
apps/acars_app.cpp
|
apps/acars_app.cpp
|
||||||
apps/ais_app.cpp
|
apps/ais_app.cpp
|
||||||
apps/analog_audio_app.cpp
|
apps/analog_audio_app.cpp
|
||||||
@ -273,17 +280,19 @@ set(CPPSRC
|
|||||||
apps/pocsag_app.cpp
|
apps/pocsag_app.cpp
|
||||||
# apps/replay_app.cpp
|
# apps/replay_app.cpp
|
||||||
apps/soundboard_app.cpp
|
apps/soundboard_app.cpp
|
||||||
apps/tpms_app.cpp
|
# apps/tpms_app.cpp
|
||||||
apps/tpms_app.cpp
|
|
||||||
apps/ui_about_simple.cpp
|
apps/ui_about_simple.cpp
|
||||||
apps/ui_adsb_rx.cpp
|
apps/ui_adsb_rx.cpp
|
||||||
apps/ui_adsb_tx.cpp
|
# apps/ui_adsb_tx.cpp #moved to ext
|
||||||
apps/ui_aprs_rx.cpp
|
apps/ui_aprs_rx.cpp
|
||||||
apps/ui_aprs_tx.cpp
|
apps/ui_aprs_tx.cpp
|
||||||
|
apps/ui_battinfo.cpp
|
||||||
apps/ui_bht_tx.cpp
|
apps/ui_bht_tx.cpp
|
||||||
|
apps/ui_bmp_file_viewer.cpp
|
||||||
apps/ui_btle_rx.cpp
|
apps/ui_btle_rx.cpp
|
||||||
# apps/ui_coasterp.cpp
|
# apps/ui_coasterp.cpp
|
||||||
apps/ui_debug.cpp
|
apps/ui_debug.cpp
|
||||||
|
apps/ui_debug_battery.cpp
|
||||||
apps/ui_dfu_menu.cpp
|
apps/ui_dfu_menu.cpp
|
||||||
apps/ui_encoders.cpp
|
apps/ui_encoders.cpp
|
||||||
apps/ui_fileman.cpp
|
apps/ui_fileman.cpp
|
||||||
@ -298,7 +307,7 @@ set(CPPSRC
|
|||||||
apps/ui_looking_glass_app.cpp
|
apps/ui_looking_glass_app.cpp
|
||||||
apps/ui_mictx.cpp
|
apps/ui_mictx.cpp
|
||||||
apps/ui_modemsetup.cpp
|
apps/ui_modemsetup.cpp
|
||||||
apps/ui_morse.cpp
|
# apps/ui_morse.cpp
|
||||||
# apps/ui_nrf_rx.cpp
|
# apps/ui_nrf_rx.cpp
|
||||||
# apps/ui_nuoptix.cpp
|
# apps/ui_nuoptix.cpp
|
||||||
apps/ui_playlist.cpp
|
apps/ui_playlist.cpp
|
||||||
@ -318,7 +327,8 @@ set(CPPSRC
|
|||||||
# apps/ui_spectrum_painter_text.cpp
|
# apps/ui_spectrum_painter_text.cpp
|
||||||
# apps/ui_spectrum_painter.cpp
|
# apps/ui_spectrum_painter.cpp
|
||||||
apps/ui_ss_viewer.cpp
|
apps/ui_ss_viewer.cpp
|
||||||
apps/ui_sstvtx.cpp
|
# apps/ui_sstvtx.cpp #moved to ext
|
||||||
|
apps/ui_standalone_view.cpp
|
||||||
apps/ui_subghzd.cpp
|
apps/ui_subghzd.cpp
|
||||||
# apps/ui_test.cpp
|
# apps/ui_test.cpp
|
||||||
apps/ui_text_editor.cpp
|
apps/ui_text_editor.cpp
|
||||||
@ -501,6 +511,7 @@ include_directories(. ${INCDIR})
|
|||||||
link_directories(${LLIBDIR})
|
link_directories(${LLIBDIR})
|
||||||
target_link_libraries(${PROJECT_NAME}.elf ${LIBS} "-L${CMAKE_CURRENT_LIST_DIR}/external")
|
target_link_libraries(${PROJECT_NAME}.elf ${LIBS} "-L${CMAKE_CURRENT_LIST_DIR}/external")
|
||||||
target_link_libraries(${PROJECT_NAME}.elf -Wl,-Map=${PROJECT_NAME}.map)
|
target_link_libraries(${PROJECT_NAME}.elf -Wl,-Map=${PROJECT_NAME}.map)
|
||||||
|
target_link_libraries(${PROJECT_NAME}.elf -Wl,--print-memory-usage)
|
||||||
|
|
||||||
add_custom_command(
|
add_custom_command(
|
||||||
OUTPUT ${PROJECT_NAME}.bin
|
OUTPUT ${PROJECT_NAME}.bin
|
||||||
|
@ -39,8 +39,6 @@ namespace ui {
|
|||||||
|
|
||||||
/* AMOptionsView *********************************************************/
|
/* AMOptionsView *********************************************************/
|
||||||
|
|
||||||
static const Style& style_options_group = Styles::bg_blue;
|
|
||||||
|
|
||||||
AMOptionsView::AMOptionsView(
|
AMOptionsView::AMOptionsView(
|
||||||
Rect parent_rect,
|
Rect parent_rect,
|
||||||
const Style* style)
|
const Style* style)
|
||||||
@ -297,13 +295,13 @@ void AnalogAudioView::set_options_widget(std::unique_ptr<Widget> new_widget) {
|
|||||||
options_widget = std::move(new_widget);
|
options_widget = std::move(new_widget);
|
||||||
} else {
|
} else {
|
||||||
// TODO: Lame hack to hide options view due to my bad paint/damage algorithm.
|
// TODO: Lame hack to hide options view due to my bad paint/damage algorithm.
|
||||||
options_widget = std::make_unique<Rectangle>(options_view_rect, style_options_group.background);
|
options_widget = std::make_unique<Rectangle>(options_view_rect, Theme::getInstance()->option_active->background);
|
||||||
}
|
}
|
||||||
add_child(options_widget.get());
|
add_child(options_widget.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
void AnalogAudioView::on_show_options_frequency() {
|
void AnalogAudioView::on_show_options_frequency() {
|
||||||
auto widget = std::make_unique<FrequencyOptionsView>(options_view_rect, &style_options_group);
|
auto widget = std::make_unique<FrequencyOptionsView>(options_view_rect, Theme::getInstance()->option_active);
|
||||||
|
|
||||||
widget->set_step(receiver_model.frequency_step());
|
widget->set_step(receiver_model.frequency_step());
|
||||||
widget->on_change_step = [this](rf::Frequency f) {
|
widget->on_change_step = [this](rf::Frequency f) {
|
||||||
@ -315,14 +313,14 @@ void AnalogAudioView::on_show_options_frequency() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
set_options_widget(std::move(widget));
|
set_options_widget(std::move(widget));
|
||||||
field_frequency.set_style(&style_options_group);
|
field_frequency.set_style(Theme::getInstance()->option_active);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AnalogAudioView::on_show_options_rf_gain() {
|
void AnalogAudioView::on_show_options_rf_gain() {
|
||||||
auto widget = std::make_unique<RadioGainOptionsView>(options_view_rect, &style_options_group);
|
auto widget = std::make_unique<RadioGainOptionsView>(options_view_rect, Theme::getInstance()->option_active);
|
||||||
|
|
||||||
set_options_widget(std::move(widget));
|
set_options_widget(std::move(widget));
|
||||||
field_lna.set_style(&style_options_group);
|
field_lna.set_style(Theme::getInstance()->option_active);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AnalogAudioView::on_show_options_modulation() {
|
void AnalogAudioView::on_show_options_modulation() {
|
||||||
@ -331,25 +329,25 @@ void AnalogAudioView::on_show_options_modulation() {
|
|||||||
const auto modulation = receiver_model.modulation();
|
const auto modulation = receiver_model.modulation();
|
||||||
switch (modulation) {
|
switch (modulation) {
|
||||||
case ReceiverModel::Mode::AMAudio:
|
case ReceiverModel::Mode::AMAudio:
|
||||||
widget = std::make_unique<AMOptionsView>(options_view_rect, &style_options_group);
|
widget = std::make_unique<AMOptionsView>(options_view_rect, Theme::getInstance()->option_active);
|
||||||
waterfall.show_audio_spectrum_view(false);
|
waterfall.show_audio_spectrum_view(false);
|
||||||
text_ctcss.hidden(true);
|
text_ctcss.hidden(true);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ReceiverModel::Mode::NarrowbandFMAudio:
|
case ReceiverModel::Mode::NarrowbandFMAudio:
|
||||||
widget = std::make_unique<NBFMOptionsView>(nbfm_view_rect, &style_options_group);
|
widget = std::make_unique<NBFMOptionsView>(nbfm_view_rect, Theme::getInstance()->option_active);
|
||||||
waterfall.show_audio_spectrum_view(false);
|
waterfall.show_audio_spectrum_view(false);
|
||||||
text_ctcss.hidden(false);
|
text_ctcss.hidden(false);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ReceiverModel::Mode::WidebandFMAudio:
|
case ReceiverModel::Mode::WidebandFMAudio:
|
||||||
widget = std::make_unique<WFMOptionsView>(options_view_rect, &style_options_group);
|
widget = std::make_unique<WFMOptionsView>(options_view_rect, Theme::getInstance()->option_active);
|
||||||
waterfall.show_audio_spectrum_view(true);
|
waterfall.show_audio_spectrum_view(true);
|
||||||
text_ctcss.hidden(true);
|
text_ctcss.hidden(true);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ReceiverModel::Mode::SpectrumAnalysis:
|
case ReceiverModel::Mode::SpectrumAnalysis:
|
||||||
widget = std::make_unique<SPECOptionsView>(this, nbfm_view_rect, &style_options_group);
|
widget = std::make_unique<SPECOptionsView>(this, nbfm_view_rect, Theme::getInstance()->option_active);
|
||||||
waterfall.show_audio_spectrum_view(false);
|
waterfall.show_audio_spectrum_view(false);
|
||||||
text_ctcss.hidden(true);
|
text_ctcss.hidden(true);
|
||||||
break;
|
break;
|
||||||
@ -360,7 +358,7 @@ void AnalogAudioView::on_show_options_modulation() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
set_options_widget(std::move(widget));
|
set_options_widget(std::move(widget));
|
||||||
options_modulation.set_style(&style_options_group);
|
options_modulation.set_style(Theme::getInstance()->option_active);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AnalogAudioView::on_frequency_step_changed(rf::Frequency f) {
|
void AnalogAudioView::on_frequency_step_changed(rf::Frequency f) {
|
||||||
@ -437,4 +435,7 @@ void AnalogAudioView::handle_coded_squelch(uint32_t value) {
|
|||||||
text_ctcss.set(tone_key_string_by_value(value, text_ctcss.parent_rect().width() / 8));
|
text_ctcss.set(tone_key_string_by_value(value, text_ctcss.parent_rect().width() / 8));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void AnalogAudioView::on_freqchg(int64_t freq) {
|
||||||
|
field_frequency.set_value(freq);
|
||||||
|
}
|
||||||
} /* namespace ui */
|
} /* namespace ui */
|
||||||
|
@ -29,7 +29,6 @@
|
|||||||
#include "ui_freq_field.hpp"
|
#include "ui_freq_field.hpp"
|
||||||
#include "ui_spectrum.hpp"
|
#include "ui_spectrum.hpp"
|
||||||
#include "ui_record_view.hpp"
|
#include "ui_record_view.hpp"
|
||||||
#include "ui_styles.hpp"
|
|
||||||
#include "app_settings.hpp"
|
#include "app_settings.hpp"
|
||||||
#include "radio_state.hpp"
|
#include "radio_state.hpp"
|
||||||
#include "tone_key.hpp"
|
#include "tone_key.hpp"
|
||||||
@ -248,12 +247,21 @@ class AnalogAudioView : public View {
|
|||||||
|
|
||||||
void handle_coded_squelch(uint32_t value);
|
void handle_coded_squelch(uint32_t value);
|
||||||
|
|
||||||
|
void on_freqchg(int64_t freq);
|
||||||
|
|
||||||
MessageHandlerRegistration message_handler_coded_squelch{
|
MessageHandlerRegistration message_handler_coded_squelch{
|
||||||
Message::ID::CodedSquelch,
|
Message::ID::CodedSquelch,
|
||||||
[this](const Message* p) {
|
[this](const Message* p) {
|
||||||
const auto message = *reinterpret_cast<const CodedSquelchMessage*>(p);
|
const auto message = *reinterpret_cast<const CodedSquelchMessage*>(p);
|
||||||
this->handle_coded_squelch(message.value);
|
this->handle_coded_squelch(message.value);
|
||||||
}};
|
}};
|
||||||
|
|
||||||
|
MessageHandlerRegistration message_handler_freqchg{
|
||||||
|
Message::ID::FreqChangeCommand,
|
||||||
|
[this](Message* const p) {
|
||||||
|
const auto message = static_cast<const FreqChangeCommandMessage*>(p);
|
||||||
|
this->on_freqchg(message->freq);
|
||||||
|
}};
|
||||||
};
|
};
|
||||||
|
|
||||||
} /* namespace ui */
|
} /* namespace ui */
|
||||||
|
@ -148,13 +148,13 @@ class BLECommView : public View {
|
|||||||
{24 * 8, 5, 6 * 8, 4}};
|
{24 * 8, 5, 6 * 8, 4}};
|
||||||
|
|
||||||
Labels label_send_adv{
|
Labels label_send_adv{
|
||||||
{{0 * 8, 2 * 8}, "Send Advertisement:", Color::light_grey()}};
|
{{0 * 8, 2 * 8}, "Send Advertisement:", Theme::getInstance()->fg_light->foreground}};
|
||||||
|
|
||||||
ImageButton button_send_adv{
|
ImageButton button_send_adv{
|
||||||
{21 * 8, 1 * 16, 10 * 8, 2 * 16},
|
{21 * 8, 1 * 16, 10 * 8, 2 * 16},
|
||||||
&bitmap_play,
|
&bitmap_play,
|
||||||
Color::green(),
|
Theme::getInstance()->fg_green->foreground,
|
||||||
Color::black()};
|
Theme::getInstance()->fg_green->background};
|
||||||
|
|
||||||
Checkbox check_log{
|
Checkbox check_log{
|
||||||
{24 * 8, 2 * 8},
|
{24 * 8, 2 * 8},
|
||||||
@ -163,7 +163,7 @@ class BLECommView : public View {
|
|||||||
true};
|
true};
|
||||||
|
|
||||||
Labels label_packets_sent{
|
Labels label_packets_sent{
|
||||||
{{0 * 8, 4 * 8}, "Packets Left:", Color::light_grey()}};
|
{{0 * 8, 4 * 8}, "Packets Left:", Theme::getInstance()->fg_light->foreground}};
|
||||||
|
|
||||||
Text text_packets_sent{
|
Text text_packets_sent{
|
||||||
{13 * 8, 2 * 16, 12 * 8, 16},
|
{13 * 8, 2 * 16, 12 * 8, 16},
|
||||||
|
@ -428,6 +428,7 @@ BLERxView::BLERxView(NavigationView& nav)
|
|||||||
&text_found_count,
|
&text_found_count,
|
||||||
&check_serial_log,
|
&check_serial_log,
|
||||||
&button_filter,
|
&button_filter,
|
||||||
|
&options_filter,
|
||||||
&button_save_list,
|
&button_save_list,
|
||||||
&button_clear_list,
|
&button_clear_list,
|
||||||
&button_switch,
|
&button_switch,
|
||||||
@ -499,6 +500,7 @@ BLERxView::BLERxView(NavigationView& nav)
|
|||||||
|
|
||||||
check_name.on_select = [this](Checkbox&, bool v) {
|
check_name.on_select = [this](Checkbox&, bool v) {
|
||||||
name_enable = v;
|
name_enable = v;
|
||||||
|
// update the include_name instance variable value of each entry in recent entries
|
||||||
setAllMembersToValue(recent, &BleRecentEntry::include_name, v);
|
setAllMembersToValue(recent, &BleRecentEntry::include_name, v);
|
||||||
recent_entries_view.set_dirty();
|
recent_entries_view.set_dirty();
|
||||||
};
|
};
|
||||||
@ -525,8 +527,14 @@ BLERxView::BLERxView(NavigationView& nav)
|
|||||||
handle_entries_sort(v);
|
handle_entries_sort(v);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
options_filter.on_change = [this](size_t index, int32_t v) {
|
||||||
|
filter_index = (uint8_t)index;
|
||||||
|
handle_filter_options(v);
|
||||||
|
};
|
||||||
|
|
||||||
options_channel.set_selected_index(channel_index, true);
|
options_channel.set_selected_index(channel_index, true);
|
||||||
options_sort.set_selected_index(sort_index, true);
|
options_sort.set_selected_index(sort_index, true);
|
||||||
|
options_filter.set_selected_index(filter_index, true);
|
||||||
|
|
||||||
button_find.on_select = [this](Button&) {
|
button_find.on_select = [this](Button&) {
|
||||||
auto open_view = nav_.push<FileLoadView>(".TXT");
|
auto open_view = nav_.push<FileLoadView>(".TXT");
|
||||||
@ -716,10 +724,11 @@ void BLERxView::on_data(BlePacketData* packet) {
|
|||||||
updateEntry(packet, entry, (ADV_PDU_TYPE)packet->type);
|
updateEntry(packet, entry, (ADV_PDU_TYPE)packet->type);
|
||||||
|
|
||||||
// Add entries if they meet the criteria.
|
// Add entries if they meet the criteria.
|
||||||
auto value = filter;
|
// auto value = filter;
|
||||||
resetFilteredEntries(recent, [&value](const BleRecentEntry& entry) {
|
// resetFilteredEntries(recent, [&value](const BleRecentEntry& entry) {
|
||||||
return (entry.dataString.find(value) == std::string::npos) && (entry.nameString.find(value) == std::string::npos);
|
// return (entry.dataString.find(value) == std::string::npos) && (entry.nameString.find(value) == std::string::npos);
|
||||||
});
|
// });
|
||||||
|
handle_filter_options(options_filter.selected_index());
|
||||||
|
|
||||||
handle_entries_sort(options_sort.selected_index());
|
handle_entries_sort(options_sort.selected_index());
|
||||||
|
|
||||||
@ -756,12 +765,13 @@ void BLERxView::on_data(BlePacketData* packet) {
|
|||||||
void BLERxView::on_filter_change(std::string value) {
|
void BLERxView::on_filter_change(std::string value) {
|
||||||
// New filter? Reset list from recent entries.
|
// New filter? Reset list from recent entries.
|
||||||
if (filter != value) {
|
if (filter != value) {
|
||||||
resetFilteredEntries(recent, [&value](const BleRecentEntry& entry) {
|
// resetFilteredEntries(recent, [&value](const BleRecentEntry& entry) {
|
||||||
return (entry.dataString.find(value) == std::string::npos) && (entry.nameString.find(value) == std::string::npos);
|
// // return (entry.dataString.find(value) == std::string::npos) && (entry.nameString.find(value) == std::string::npos);
|
||||||
});
|
// return (entry.dataString.find(value) == std::string::npos) && (entry.nameString.find(value) == std::string::npos) && (to_string_mac_address(entry.packetData.macAddress, 6, false).find(value) == std::string::npos);
|
||||||
}
|
// });
|
||||||
|
|
||||||
filter = value;
|
filter = value;
|
||||||
|
handle_filter_options(options_filter.selected_index());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void BLERxView::on_file_changed(const std::filesystem::path& new_file_path) {
|
void BLERxView::on_file_changed(const std::filesystem::path& new_file_path) {
|
||||||
@ -852,6 +862,24 @@ void BLERxView::handle_entries_sort(uint8_t index) {
|
|||||||
recent_entries_view.set_dirty();
|
recent_entries_view.set_dirty();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void BLERxView::handle_filter_options(uint8_t index) {
|
||||||
|
auto value = filter;
|
||||||
|
switch (index) {
|
||||||
|
case 0: // filter by Data
|
||||||
|
resetFilteredEntries(recent, [&value](const BleRecentEntry& entry) {
|
||||||
|
return (entry.dataString.find(value) == std::string::npos) && (entry.nameString.find(value) == std::string::npos);
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
case 1: // filter by MAC address (All caps: e.g. AA:BB:CC:DD:EE:FF)
|
||||||
|
resetFilteredEntries(recent, [&value](const BleRecentEntry& entry) {
|
||||||
|
return (to_string_mac_address(entry.packetData.macAddress, 6, false).find(value) == std::string::npos);
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void BLERxView::set_parent_rect(const Rect new_parent_rect) {
|
void BLERxView::set_parent_rect(const Rect new_parent_rect) {
|
||||||
View::set_parent_rect(new_parent_rect);
|
View::set_parent_rect(new_parent_rect);
|
||||||
const Rect content_rect{0, header_height, new_parent_rect.width(), new_parent_rect.height() - header_height - switch_button_height};
|
const Rect content_rect{0, header_height, new_parent_rect.width(), new_parent_rect.height() - header_height - switch_button_height};
|
||||||
@ -914,6 +942,7 @@ void BLERxView::updateEntry(const BlePacketData* packet, BleRecentEntry& entry,
|
|||||||
|
|
||||||
// Subtract 1 because type is part of the length.
|
// Subtract 1 because type is part of the length.
|
||||||
for (int i = 0; i < length - 1; i++) {
|
for (int i = 0; i < length - 1; i++) {
|
||||||
|
// parse the name of bluetooth device: 0x08->Shortened Local Name; 0x09->Complete Local Name
|
||||||
if (type == 0x08 || type == 0x09) {
|
if (type == 0x08 || type == 0x09) {
|
||||||
decoded_data += (char)advertiseData->Data[currentByte];
|
decoded_data += (char)advertiseData->Data[currentByte];
|
||||||
}
|
}
|
||||||
|
@ -139,23 +139,23 @@ class BleRecentEntryDetailView : public View {
|
|||||||
static constexpr uint8_t total_data_lines{5};
|
static constexpr uint8_t total_data_lines{5};
|
||||||
|
|
||||||
Labels label_mac_address{
|
Labels label_mac_address{
|
||||||
{{0 * 8, 0 * 16}, "Mac Address:", Color::light_grey()}};
|
{{0 * 8, 0 * 16}, "Mac Address:", Theme::getInstance()->fg_light->foreground}};
|
||||||
|
|
||||||
Text text_mac_address{
|
Text text_mac_address{
|
||||||
{12 * 8, 0 * 16, 17 * 8, 16},
|
{12 * 8, 0 * 16, 17 * 8, 16},
|
||||||
"-"};
|
"-"};
|
||||||
|
|
||||||
Labels label_pdu_type{
|
Labels label_pdu_type{
|
||||||
{{0 * 8, 1 * 16}, "PDU Type:", Color::light_grey()}};
|
{{0 * 8, 1 * 16}, "PDU Type:", Theme::getInstance()->fg_light->foreground}};
|
||||||
|
|
||||||
Text text_pdu_type{
|
Text text_pdu_type{
|
||||||
{9 * 8, 1 * 16, 17 * 8, 16},
|
{9 * 8, 1 * 16, 17 * 8, 16},
|
||||||
"-"};
|
"-"};
|
||||||
|
|
||||||
Labels labels{
|
Labels labels{
|
||||||
{{0 * 8, 3 * 16}, "Len", Color::light_grey()},
|
{{0 * 8, 3 * 16}, "Len", Theme::getInstance()->fg_light->foreground},
|
||||||
{{5 * 8, 3 * 16}, "Type", Color::light_grey()},
|
{{5 * 8, 3 * 16}, "Type", Theme::getInstance()->fg_light->foreground},
|
||||||
{{10 * 8, 3 * 16}, "Value", Color::light_grey()},
|
{{10 * 8, 3 * 16}, "Value", Theme::getInstance()->fg_light->foreground},
|
||||||
};
|
};
|
||||||
|
|
||||||
Button button_send{
|
Button button_send{
|
||||||
@ -203,6 +203,7 @@ class BLERxView : public View {
|
|||||||
void file_error();
|
void file_error();
|
||||||
void on_timer();
|
void on_timer();
|
||||||
void handle_entries_sort(uint8_t index);
|
void handle_entries_sort(uint8_t index);
|
||||||
|
void handle_filter_options(uint8_t index);
|
||||||
void updateEntry(const BlePacketData* packet, BleRecentEntry& entry, ADV_PDU_TYPE pdu_type);
|
void updateEntry(const BlePacketData* packet, BleRecentEntry& entry, ADV_PDU_TYPE pdu_type);
|
||||||
|
|
||||||
NavigationView& nav_;
|
NavigationView& nav_;
|
||||||
@ -214,6 +215,7 @@ class BLERxView : public View {
|
|||||||
|
|
||||||
uint8_t channel_index{0};
|
uint8_t channel_index{0};
|
||||||
uint8_t sort_index{0};
|
uint8_t sort_index{0};
|
||||||
|
uint8_t filter_index{0};
|
||||||
std::string filter{};
|
std::string filter{};
|
||||||
bool logging{false};
|
bool logging{false};
|
||||||
bool serial_logging{false};
|
bool serial_logging{false};
|
||||||
@ -227,6 +229,7 @@ class BLERxView : public View {
|
|||||||
{"sort_index"sv, &sort_index},
|
{"sort_index"sv, &sort_index},
|
||||||
{"filter"sv, &filter},
|
{"filter"sv, &filter},
|
||||||
{"log"sv, &logging},
|
{"log"sv, &logging},
|
||||||
|
{"filter_index"sv, &filter_index},
|
||||||
// disabled to always start without USB serial activated until we can make it non blocking if not connected
|
// disabled to always start without USB serial activated until we can make it non blocking if not connected
|
||||||
// {"serial_log"sv, &serial_logging},
|
// {"serial_log"sv, &serial_logging},
|
||||||
{"name"sv, &name_enable},
|
{"name"sv, &name_enable},
|
||||||
@ -255,7 +258,7 @@ class BLERxView : public View {
|
|||||||
std::filesystem::path log_packets_path{blerx_dir / u"Logs/????.TXT"};
|
std::filesystem::path log_packets_path{blerx_dir / u"Logs/????.TXT"};
|
||||||
std::filesystem::path packet_save_path{blerx_dir / u"Lists/????.csv"};
|
std::filesystem::path packet_save_path{blerx_dir / u"Lists/????.csv"};
|
||||||
|
|
||||||
static constexpr auto header_height = 4 * 16;
|
static constexpr auto header_height = 9 * 8;
|
||||||
static constexpr auto switch_button_height = 3 * 16;
|
static constexpr auto switch_button_height = 3 * 16;
|
||||||
|
|
||||||
OptionsField options_channel{
|
OptionsField options_channel{
|
||||||
@ -286,10 +289,10 @@ class BLERxView : public View {
|
|||||||
{24 * 8, 5, 6 * 8, 4}};
|
{24 * 8, 5, 6 * 8, 4}};
|
||||||
|
|
||||||
Labels label_sort{
|
Labels label_sort{
|
||||||
{{0 * 8, 3 * 8}, "Sort:", Color::light_grey()}};
|
{{0 * 8, 2 * 8}, "Sort:", Theme::getInstance()->fg_light->foreground}};
|
||||||
|
|
||||||
OptionsField options_sort{
|
OptionsField options_sort{
|
||||||
{5 * 8, 3 * 8},
|
{5 * 8, 2 * 8},
|
||||||
4,
|
4,
|
||||||
{{"MAC", 0},
|
{{"MAC", 0},
|
||||||
{"Hits", 1},
|
{"Hits", 1},
|
||||||
@ -298,40 +301,46 @@ class BLERxView : public View {
|
|||||||
{"Name", 4}}};
|
{"Name", 4}}};
|
||||||
|
|
||||||
Button button_filter{
|
Button button_filter{
|
||||||
{11 * 8, 3 * 8, 4 * 8, 16},
|
{11 * 8, 2 * 8, 7 * 8, 16},
|
||||||
"Filter"};
|
"Filter:"};
|
||||||
|
|
||||||
|
OptionsField options_filter{
|
||||||
|
{18 * 8 + 2, 2 * 8},
|
||||||
|
4,
|
||||||
|
{{"Data", 0},
|
||||||
|
{"MAC", 1}}};
|
||||||
|
|
||||||
Checkbox check_log{
|
Checkbox check_log{
|
||||||
{17 * 8, 3 * 8},
|
{10 * 8, 4 * 8 + 2},
|
||||||
3,
|
3,
|
||||||
"Log",
|
"Log",
|
||||||
true};
|
true};
|
||||||
|
|
||||||
Checkbox check_name{
|
Checkbox check_name{
|
||||||
{23 * 8, 3 * 8},
|
{0 * 8, 4 * 8 + 2},
|
||||||
3,
|
3,
|
||||||
"Name",
|
"Name",
|
||||||
true};
|
true};
|
||||||
|
|
||||||
Button button_find{
|
Button button_find{
|
||||||
{0 * 8, 6 * 8, 4 * 8, 16},
|
{0 * 8, 7 * 8 - 2, 4 * 8, 16},
|
||||||
"Find"};
|
"Find"};
|
||||||
|
|
||||||
Labels label_found{
|
Labels label_found{
|
||||||
{{5 * 8, 6 * 8}, "Found:", Color::light_grey()}};
|
{{5 * 8, 7 * 8 - 2}, "Found:", Theme::getInstance()->fg_light->foreground}};
|
||||||
|
|
||||||
Text text_found_count{
|
Text text_found_count{
|
||||||
{11 * 8, 3 * 16, 20 * 8, 16},
|
{11 * 8, 7 * 8 - 2, 20 * 8, 16},
|
||||||
"0/0"};
|
"0/0"};
|
||||||
|
|
||||||
Checkbox check_serial_log{
|
Checkbox check_serial_log{
|
||||||
{17 * 8, 3 * 16 - 2},
|
{18 * 8 + 2, 4 * 8 + 2},
|
||||||
7,
|
7,
|
||||||
"USB Log",
|
"USB Log",
|
||||||
true};
|
true};
|
||||||
|
|
||||||
Console console{
|
// Console console{
|
||||||
{0, 4 * 16, 240, 240}};
|
// {0, 10 * 8, 240, 240}};
|
||||||
|
|
||||||
Button button_clear_list{
|
Button button_clear_list{
|
||||||
{2 * 8, 320 - (16 + 32), 7 * 8, 32},
|
{2 * 8, 320 - (16 + 32), 7 * 8, 32},
|
||||||
@ -371,7 +380,7 @@ class BLERxView : public View {
|
|||||||
[this](const Message* const) {
|
[this](const Message* const) {
|
||||||
this->on_timer();
|
this->on_timer();
|
||||||
}};
|
}};
|
||||||
};
|
}; /* BLERxView */
|
||||||
|
|
||||||
} /* namespace ui */
|
} /* namespace ui */
|
||||||
|
|
||||||
|
@ -218,11 +218,11 @@ class BLETxView : public View {
|
|||||||
ImageButton button_play{
|
ImageButton button_play{
|
||||||
{28 * 8, 2 * 16, 2 * 8, 1 * 16},
|
{28 * 8, 2 * 16, 2 * 8, 1 * 16},
|
||||||
&bitmap_play,
|
&bitmap_play,
|
||||||
Color::green(),
|
Theme::getInstance()->fg_green->foreground,
|
||||||
Color::black()};
|
Theme::getInstance()->fg_green->background};
|
||||||
|
|
||||||
Labels label_speed{
|
Labels label_speed{
|
||||||
{{0 * 8, 6 * 8}, "Speed:", Color::light_grey()}};
|
{{0 * 8, 6 * 8}, "Speed:", Theme::getInstance()->fg_light->foreground}};
|
||||||
|
|
||||||
OptionsField options_speed{
|
OptionsField options_speed{
|
||||||
{7 * 8, 6 * 8},
|
{7 * 8, 6 * 8},
|
||||||
@ -254,7 +254,7 @@ class BLETxView : public View {
|
|||||||
{"CONNECT_REQ", PKT_TYPE_CONNECT_REQ}}};
|
{"CONNECT_REQ", PKT_TYPE_CONNECT_REQ}}};
|
||||||
|
|
||||||
Labels label_marked_data{
|
Labels label_marked_data{
|
||||||
{{0 * 8, 4 * 16}, "Marked Data:", Color::light_grey()}};
|
{{0 * 8, 4 * 16}, "Marked Data:", Theme::getInstance()->fg_light->foreground}};
|
||||||
|
|
||||||
OptionsField marked_data_sequence{
|
OptionsField marked_data_sequence{
|
||||||
{12 * 8, 8 * 8},
|
{12 * 8, 8 * 8},
|
||||||
@ -264,28 +264,28 @@ class BLETxView : public View {
|
|||||||
{"Random", 2}}};
|
{"Random", 2}}};
|
||||||
|
|
||||||
Labels label_packet_index{
|
Labels label_packet_index{
|
||||||
{{0 * 8, 12 * 8}, "Packet Index:", Color::light_grey()}};
|
{{0 * 8, 12 * 8}, "Packet Index:", Theme::getInstance()->fg_light->foreground}};
|
||||||
|
|
||||||
Text text_packet_index{
|
Text text_packet_index{
|
||||||
{13 * 8, 6 * 16, 12 * 8, 16},
|
{13 * 8, 6 * 16, 12 * 8, 16},
|
||||||
"-"};
|
"-"};
|
||||||
|
|
||||||
Labels label_packets_sent{
|
Labels label_packets_sent{
|
||||||
{{0 * 8, 14 * 8}, "Repeat Count:", Color::light_grey()}};
|
{{0 * 8, 14 * 8}, "Repeat Count:", Theme::getInstance()->fg_light->foreground}};
|
||||||
|
|
||||||
Text text_packets_sent{
|
Text text_packets_sent{
|
||||||
{13 * 8, 7 * 16, 12 * 8, 16},
|
{13 * 8, 7 * 16, 12 * 8, 16},
|
||||||
"-"};
|
"-"};
|
||||||
|
|
||||||
Labels label_mac_address{
|
Labels label_mac_address{
|
||||||
{{0 * 8, 16 * 8}, "Mac Address:", Color::light_grey()}};
|
{{0 * 8, 16 * 8}, "Mac Address:", Theme::getInstance()->fg_light->foreground}};
|
||||||
|
|
||||||
Text text_mac_address{
|
Text text_mac_address{
|
||||||
{12 * 8, 8 * 16, 20 * 8, 16},
|
{12 * 8, 8 * 16, 20 * 8, 16},
|
||||||
"-"};
|
"-"};
|
||||||
|
|
||||||
Labels label_data_packet{
|
Labels label_data_packet{
|
||||||
{{0 * 8, 9 * 16}, "Packet Data:", Color::light_grey()}};
|
{{0 * 8, 9 * 16}, "Packet Data:", Theme::getInstance()->fg_light->foreground}};
|
||||||
|
|
||||||
Console console{
|
Console console{
|
||||||
{0, 9 * 18, 240, 240}};
|
{0, 9 * 18, 240, 240}};
|
||||||
|
@ -128,4 +128,8 @@ void CaptureAppView::focus() {
|
|||||||
record_view.focus();
|
record_view.focus();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CaptureAppView::on_freqchg(int64_t freq) {
|
||||||
|
field_frequency.set_value(freq);
|
||||||
|
}
|
||||||
|
|
||||||
} /* namespace ui */
|
} /* namespace ui */
|
||||||
|
@ -56,8 +56,8 @@ class CaptureAppView : public View {
|
|||||||
"rx_capture", app_settings::Mode::RX};
|
"rx_capture", app_settings::Mode::RX};
|
||||||
|
|
||||||
Labels labels{
|
Labels labels{
|
||||||
{{0 * 8, 1 * 16}, "Rate:", Color::light_grey()},
|
{{0 * 8, 1 * 16}, "Rate:", Theme::getInstance()->fg_light->foreground},
|
||||||
{{11 * 8, 1 * 16}, "Format:", Color::light_grey()},
|
{{11 * 8, 1 * 16}, "Format:", Theme::getInstance()->fg_light->foreground},
|
||||||
};
|
};
|
||||||
|
|
||||||
RSSI rssi{
|
RSSI rssi{
|
||||||
@ -108,6 +108,15 @@ class CaptureAppView : public View {
|
|||||||
3};
|
3};
|
||||||
|
|
||||||
spectrum::WaterfallView waterfall{};
|
spectrum::WaterfallView waterfall{};
|
||||||
|
|
||||||
|
MessageHandlerRegistration message_handler_freqchg{
|
||||||
|
Message::ID::FreqChangeCommand,
|
||||||
|
[this](Message* const p) {
|
||||||
|
const auto message = static_cast<const FreqChangeCommandMessage*>(p);
|
||||||
|
this->on_freqchg(message->freq);
|
||||||
|
}};
|
||||||
|
|
||||||
|
void on_freqchg(int64_t freq);
|
||||||
};
|
};
|
||||||
|
|
||||||
} /* namespace ui */
|
} /* namespace ui */
|
||||||
|
@ -178,4 +178,8 @@ void ERTAppView::on_show_list() {
|
|||||||
recent_entries_view.focus();
|
recent_entries_view.focus();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ERTAppView::on_freqchg(int64_t freq) {
|
||||||
|
field_frequency.set_value(freq);
|
||||||
|
}
|
||||||
|
|
||||||
} /* namespace ui */
|
} /* namespace ui */
|
||||||
|
@ -176,6 +176,14 @@ class ERTAppView : public View {
|
|||||||
this->on_packet(packet);
|
this->on_packet(packet);
|
||||||
}};
|
}};
|
||||||
|
|
||||||
|
MessageHandlerRegistration message_handler_freqchg{
|
||||||
|
Message::ID::FreqChangeCommand,
|
||||||
|
[this](Message* const p) {
|
||||||
|
const auto message = static_cast<const FreqChangeCommandMessage*>(p);
|
||||||
|
this->on_freqchg(message->freq);
|
||||||
|
}};
|
||||||
|
|
||||||
|
void on_freqchg(int64_t freq);
|
||||||
void on_packet(const ert::Packet& packet);
|
void on_packet(const ert::Packet& packet);
|
||||||
void on_show_list();
|
void on_show_list();
|
||||||
};
|
};
|
||||||
|
@ -163,8 +163,8 @@ void POCSAGAppView::refresh_ui() {
|
|||||||
// Set console font style.
|
// Set console font style.
|
||||||
console.set_style(
|
console.set_style(
|
||||||
settings_.enable_small_font
|
settings_.enable_small_font
|
||||||
? &Styles::white_small
|
? Theme::getInstance()->bg_darkest_small
|
||||||
: &Styles::white);
|
: Theme::getInstance()->bg_darkest);
|
||||||
|
|
||||||
// Update filter button text.
|
// Update filter button text.
|
||||||
std::string btn_text = "Filter Last";
|
std::string btn_text = "Filter Last";
|
||||||
@ -260,19 +260,19 @@ void POCSAGAppView::handle_decoded(Timestamp timestamp, const std::string& prefi
|
|||||||
|
|
||||||
static Color get_status_color(const POCSAGState& state) {
|
static Color get_status_color(const POCSAGState& state) {
|
||||||
if (state.out_type == IDLE)
|
if (state.out_type == IDLE)
|
||||||
return Color::white();
|
return Theme::getInstance()->bg_darkest->foreground;
|
||||||
|
|
||||||
switch (state.mode) {
|
switch (state.mode) {
|
||||||
case STATE_CLEAR:
|
case STATE_CLEAR:
|
||||||
return Color::cyan();
|
return Theme::getInstance()->fg_cyan->foreground;
|
||||||
case STATE_HAVE_ADDRESS:
|
case STATE_HAVE_ADDRESS:
|
||||||
return Color::yellow();
|
return Theme::getInstance()->fg_yellow->foreground;
|
||||||
case STATE_GETTING_MSG:
|
case STATE_GETTING_MSG:
|
||||||
return Color::green();
|
return Theme::getInstance()->fg_green->foreground;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Shouldn't get here...
|
// Shouldn't get here...
|
||||||
return Color::red();
|
return Theme::getInstance()->fg_red->foreground;
|
||||||
}
|
}
|
||||||
|
|
||||||
void POCSAGAppView::on_packet(const POCSAGPacketMessage* message) {
|
void POCSAGAppView::on_packet(const POCSAGPacketMessage* message) {
|
||||||
@ -294,7 +294,7 @@ void POCSAGAppView::on_packet(const POCSAGPacketMessage* message) {
|
|||||||
last_address = 0;
|
last_address = 0;
|
||||||
} else {
|
} else {
|
||||||
// Set color before to be able to see if decode gets stuck.
|
// Set color before to be able to see if decode gets stuck.
|
||||||
image_status.set_foreground(Color::magenta());
|
image_status.set_foreground(Theme::getInstance()->fg_magenta->foreground);
|
||||||
pocsag_state.codeword_index = 0;
|
pocsag_state.codeword_index = 0;
|
||||||
pocsag_state.errors = 0;
|
pocsag_state.errors = 0;
|
||||||
|
|
||||||
@ -321,6 +321,10 @@ void POCSAGAppView::on_stats(const POCSAGStatsMessage* stats) {
|
|||||||
widget_frames.set_sync(stats->has_sync);
|
widget_frames.set_sync(stats->has_sync);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void POCSAGAppView::on_freqchg(int64_t freq) {
|
||||||
|
field_frequency.set_value(freq);
|
||||||
|
}
|
||||||
|
|
||||||
void BaudIndicator::paint(Painter& painter) {
|
void BaudIndicator::paint(Painter& painter) {
|
||||||
auto p = screen_pos();
|
auto p = screen_pos();
|
||||||
char top = '-';
|
char top = '-';
|
||||||
@ -332,8 +336,8 @@ void BaudIndicator::paint(Painter& painter) {
|
|||||||
bot = (r % 10) + '0';
|
bot = (r % 10) + '0';
|
||||||
}
|
}
|
||||||
|
|
||||||
painter.draw_char(p, Styles::white_small, top);
|
painter.draw_char(p, *Theme::getInstance()->bg_darkest_small, top);
|
||||||
painter.draw_char({p.x(), p.y() + 8}, Styles::white_small, bot);
|
painter.draw_char({p.x(), p.y() + 8}, *Theme::getInstance()->bg_darkest_small, bot);
|
||||||
}
|
}
|
||||||
|
|
||||||
void BitsIndicator::paint(Painter&) {
|
void BitsIndicator::paint(Painter&) {
|
||||||
@ -343,17 +347,17 @@ void BitsIndicator::paint(Painter&) {
|
|||||||
|
|
||||||
int x = p.x() + (i / height);
|
int x = p.x() + (i / height);
|
||||||
int y = p.y() + (i % height);
|
int y = p.y() + (i % height);
|
||||||
display.draw_pixel({x, y}, is_set ? Color::white() : Color::black());
|
display.draw_pixel({x, y}, is_set ? Theme::getInstance()->bg_darkest->foreground : Theme::getInstance()->bg_darkest->background);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void FrameIndicator::paint(Painter& painter) {
|
void FrameIndicator::paint(Painter& painter) {
|
||||||
auto p = screen_pos();
|
auto p = screen_pos();
|
||||||
painter.draw_rectangle({p, {2, height}}, has_sync_ ? Color::green() : Color::grey());
|
painter.draw_rectangle({p, {2, height}}, has_sync_ ? Theme::getInstance()->fg_green->foreground : Theme::getInstance()->bg_medium->background);
|
||||||
|
|
||||||
for (size_t i = 0; i < height; ++i) {
|
for (size_t i = 0; i < height; ++i) {
|
||||||
auto p2 = p + Point{2, 15 - (int)i};
|
auto p2 = p + Point{2, 15 - (int)i};
|
||||||
painter.draw_hline(p2, 2, i < frame_count_ ? Color::white() : Color::black());
|
painter.draw_hline(p2, 2, i < frame_count_ ? Theme::getInstance()->bg_darkest->foreground : Theme::getInstance()->bg_darkest->background);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -27,7 +27,6 @@
|
|||||||
#include "ui_freq_field.hpp"
|
#include "ui_freq_field.hpp"
|
||||||
#include "ui_receiver.hpp"
|
#include "ui_receiver.hpp"
|
||||||
#include "ui_rssi.hpp"
|
#include "ui_rssi.hpp"
|
||||||
#include "ui_styles.hpp"
|
|
||||||
|
|
||||||
#include "app_settings.hpp"
|
#include "app_settings.hpp"
|
||||||
#include "log_file.hpp"
|
#include "log_file.hpp"
|
||||||
@ -141,8 +140,8 @@ class POCSAGSettingsView : public View {
|
|||||||
POCSAGSettings& settings_;
|
POCSAGSettings& settings_;
|
||||||
|
|
||||||
Labels labels{
|
Labels labels{
|
||||||
{{2 * 8, 12 * 16}, "Filter Mode:", Color::light_grey()},
|
{{2 * 8, 12 * 16}, "Filter Mode:", Theme::getInstance()->fg_light->foreground},
|
||||||
{{2 * 8, 13 * 16}, "Filter Addr:", Color::light_grey()},
|
{{2 * 8, 13 * 16}, "Filter Addr:", Theme::getInstance()->fg_light->foreground},
|
||||||
};
|
};
|
||||||
|
|
||||||
Checkbox check_log{
|
Checkbox check_log{
|
||||||
@ -265,8 +264,8 @@ class POCSAGAppView : public View {
|
|||||||
Image image_status{
|
Image image_status{
|
||||||
{0 * 8 + 4, 1 * 16 + 2, 16, 16},
|
{0 * 8 + 4, 1 * 16 + 2, 16, 16},
|
||||||
&bitmap_icon_pocsag,
|
&bitmap_icon_pocsag,
|
||||||
Color::white(),
|
Theme::getInstance()->bg_darkest->foreground,
|
||||||
Color::black()};
|
Theme::getInstance()->bg_darkest->background};
|
||||||
|
|
||||||
Text text_packet_count{
|
Text text_packet_count{
|
||||||
{3 * 8, 1 * 16 + 2, 5 * 8, 16},
|
{3 * 8, 1 * 16 + 2, 5 * 8, 16},
|
||||||
@ -293,6 +292,15 @@ class POCSAGAppView : public View {
|
|||||||
Console console{
|
Console console{
|
||||||
{0, 2 * 16 + 6, screen_width, screen_height - 54}};
|
{0, 2 * 16 + 6, screen_width, screen_height - 54}};
|
||||||
|
|
||||||
|
void on_freqchg(int64_t freq);
|
||||||
|
|
||||||
|
MessageHandlerRegistration message_handler_freqchg{
|
||||||
|
Message::ID::FreqChangeCommand,
|
||||||
|
[this](Message* const p) {
|
||||||
|
const auto message = static_cast<const FreqChangeCommandMessage*>(p);
|
||||||
|
this->on_freqchg(message->freq);
|
||||||
|
}};
|
||||||
|
|
||||||
MessageHandlerRegistration message_handler_packet{
|
MessageHandlerRegistration message_handler_packet{
|
||||||
Message::ID::POCSAGPacket,
|
Message::ID::POCSAGPacket,
|
||||||
[this](Message* const p) {
|
[this](Message* const p) {
|
||||||
|
@ -112,8 +112,8 @@ class ReplayAppView : public View {
|
|||||||
ImageButton button_play{
|
ImageButton button_play{
|
||||||
{28 * 8, 2 * 16, 2 * 8, 1 * 16},
|
{28 * 8, 2 * 16, 2 * 8, 1 * 16},
|
||||||
&bitmap_play,
|
&bitmap_play,
|
||||||
Color::green(),
|
Theme::getInstance()->fg_green->foreground,
|
||||||
Color::black()};
|
Theme::getInstance()->fg_green->background};
|
||||||
|
|
||||||
spectrum::WaterfallView waterfall{};
|
spectrum::WaterfallView waterfall{};
|
||||||
|
|
||||||
|
@ -214,7 +214,7 @@ void SoundBoardView::refresh_list() {
|
|||||||
|
|
||||||
for (size_t n = 0; n < file_list.size(); n++) {
|
for (size_t n = 0; n < file_list.size(); n++) {
|
||||||
menu_view.add_item({file_list[n].string().substr(0, 30),
|
menu_view.add_item({file_list[n].string().substr(0, 30),
|
||||||
ui::Color::dark_magenta(),
|
ui::Theme::getInstance()->fg_magenta->foreground,
|
||||||
nullptr,
|
nullptr,
|
||||||
[this](KeyEvent) {
|
[this](KeyEvent) {
|
||||||
on_select_entry();
|
on_select_entry();
|
||||||
|
@ -92,8 +92,8 @@ class SoundBoardView : public View {
|
|||||||
void on_select_entry();
|
void on_select_entry();
|
||||||
|
|
||||||
Labels labels{
|
Labels labels{
|
||||||
{{24 * 8, 180}, "Vol:", Color::light_grey()},
|
{{24 * 8, 180}, "Vol:", Theme::getInstance()->fg_light->foreground},
|
||||||
{{0, 180}, "Key:", Color::light_grey()}};
|
{{0, 180}, "Key:", Theme::getInstance()->fg_light->foreground}};
|
||||||
|
|
||||||
Button button_next_page{
|
Button button_next_page{
|
||||||
{30 * 7, 25 * 8, 10 * 3, 2 * 14},
|
{30 * 7, 25 * 8, 10 * 3, 2 * 14},
|
||||||
|
@ -71,7 +71,7 @@ void CreditsWidget::new_row(
|
|||||||
void CreditsWidget::clear() {
|
void CreditsWidget::clear() {
|
||||||
display.fill_rectangle(
|
display.fill_rectangle(
|
||||||
screen_rect(),
|
screen_rect(),
|
||||||
Color::black());
|
Theme::getInstance()->bg_darkest->background);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AboutView::update() {
|
void AboutView::update() {
|
||||||
@ -109,7 +109,7 @@ void AboutView::update() {
|
|||||||
const size_t start = (glyph.size().width() / 8) * render_line;
|
const size_t start = (glyph.size().width() / 8) * render_line;
|
||||||
for (Dim c = 0; c < glyph.size().width(); c++) {
|
for (Dim c = 0; c < glyph.size().width(); c++) {
|
||||||
const auto pixel = glyph.pixels()[start + (c >> 3)] & (1U << (c & 0x7));
|
const auto pixel = glyph.pixels()[start + (c >> 3)] & (1U << (c & 0x7));
|
||||||
pixel_row[start_pos + i + c] = pixel ? Color::white() : Color::black();
|
pixel_row[start_pos + i + c] = pixel ? Theme::getInstance()->bg_darkest->foreground : Theme::getInstance()->bg_darkest->background;
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto advance = glyph.advance();
|
const auto advance = glyph.advance();
|
||||||
|
@ -1,83 +1,88 @@
|
|||||||
#include "ui_about_simple.hpp"
|
#include "ui_about_simple.hpp"
|
||||||
|
|
||||||
namespace ui {
|
namespace ui {
|
||||||
|
|
||||||
|
// TODO: Generate this automatically from github
|
||||||
|
// Information: a line starting with a '#' will be yellow coloured
|
||||||
|
const std::string authors_list[] = {
|
||||||
|
"# * List of contributors * ",
|
||||||
|
" ",
|
||||||
|
"#Mayhem:",
|
||||||
|
"eried,euquiq,gregoryfenton",
|
||||||
|
"johnelder,jwetzell,nnemanjan00",
|
||||||
|
"N0vaPixel,klockee,gullradriel",
|
||||||
|
"jamesshao8,ITAxReal,rascafr",
|
||||||
|
"mcules,dqs105,strijar",
|
||||||
|
"zhang00963,RedFox-Fr,aldude999",
|
||||||
|
"East2West,fossum,ArjanOnwezen",
|
||||||
|
"vXxOinvizioNxX,teixeluis",
|
||||||
|
"Brumi-2021,texasyojimbo",
|
||||||
|
"heurist1,intoxsick,ckuethe",
|
||||||
|
"notpike,jLynx,zigad",
|
||||||
|
"MichalLeonBorsuk,jimilinuxguy",
|
||||||
|
"kallanreed,bernd-herzog",
|
||||||
|
"NotherNgineer,zxkmm,u-foka",
|
||||||
|
"Netro,HTotoo",
|
||||||
|
" ",
|
||||||
|
"#Havoc:",
|
||||||
|
"furrtek,mrmookie,NotPike",
|
||||||
|
"mjwaxios,ImDroided,Giorgiofox",
|
||||||
|
"F4GEV,z4ziggy,xmycroftx",
|
||||||
|
"troussos,silascutler",
|
||||||
|
"nickbouwhuis,msoose,leres",
|
||||||
|
"joakar,dhoetger,clem-42",
|
||||||
|
"brianlechthaler,ZeroChaos-...",
|
||||||
|
" ",
|
||||||
|
"#PortaPack:",
|
||||||
|
"jboone,argilo",
|
||||||
|
" ",
|
||||||
|
"#HackRF:",
|
||||||
|
"mossmann,dominicgs,bvernoux",
|
||||||
|
"bgamari,schneider42,miek",
|
||||||
|
"willcode,hessu,Sec42",
|
||||||
|
"yhetti,ckuethe,smunaut",
|
||||||
|
"wishi,mrbubble62,scateu..."};
|
||||||
|
|
||||||
AboutView::AboutView(NavigationView& nav) {
|
AboutView::AboutView(NavigationView& nav) {
|
||||||
add_children({&console, &button_ok});
|
add_children({&menu_view,
|
||||||
|
&button_ok});
|
||||||
|
|
||||||
button_ok.on_select = [&nav](Button&) {
|
button_ok.on_select = [&nav](Button&) {
|
||||||
nav.pop();
|
nav.pop();
|
||||||
};
|
};
|
||||||
|
|
||||||
console.writeln(STR_COLOR_LIGHT_GREY "List of contributors:");
|
menu_view.on_left = [this]() {
|
||||||
console.writeln("");
|
button_ok.focus();
|
||||||
|
};
|
||||||
|
|
||||||
|
menu_view.on_right = [this]() {
|
||||||
|
button_ok.focus();
|
||||||
|
};
|
||||||
|
|
||||||
|
for (const std::string& authors_line : authors_list) {
|
||||||
|
// if it's starting with #, it's a title and we have to substract the '#' and paint yellow
|
||||||
|
if (authors_line.size() > 0) {
|
||||||
|
if (authors_line[0] == '#') {
|
||||||
|
menu_view.add_item(
|
||||||
|
{authors_line.substr(1, authors_line.size() - 1),
|
||||||
|
ui::Theme::getInstance()->fg_yellow->foreground,
|
||||||
|
nullptr,
|
||||||
|
nullptr});
|
||||||
|
} else {
|
||||||
|
menu_view.add_item(
|
||||||
|
{authors_line,
|
||||||
|
Theme::getInstance()->bg_darkest->foreground,
|
||||||
|
nullptr,
|
||||||
|
nullptr});
|
||||||
}
|
}
|
||||||
|
|
||||||
void AboutView::update() {
|
|
||||||
if (++timer > 400) {
|
|
||||||
timer = 0;
|
|
||||||
|
|
||||||
switch (++frame) {
|
|
||||||
case 1:
|
|
||||||
// TODO: Generate this automatically from github
|
|
||||||
// https://github.com/portapack-mayhem/mayhem-firmware/graphs/contributors?to=2022-01-01&from=2020-04-12&type=c
|
|
||||||
console.writeln(STR_COLOR_DARK_YELLOW "Mayhem:");
|
|
||||||
console.writeln("eried,euquiq,gregoryfenton");
|
|
||||||
console.writeln("johnelder,jwetzell,nnemanjan00");
|
|
||||||
console.writeln("N0vaPixel,klockee,gullradriel");
|
|
||||||
console.writeln("jamesshao8,ITAxReal,rascafr");
|
|
||||||
console.writeln("mcules,dqs105,strijar");
|
|
||||||
console.writeln("zhang00963,RedFox-Fr,aldude999");
|
|
||||||
console.writeln("East2West,fossum,ArjanOnwezen");
|
|
||||||
console.writeln("vXxOinvizioNxX,teixeluis");
|
|
||||||
console.writeln("Brumi-2021,texasyojimbo");
|
|
||||||
console.writeln("heurist1,intoxsick,ckuethe");
|
|
||||||
console.writeln("notpike,jLynx,zigad");
|
|
||||||
console.writeln("MichalLeonBorsuk,jimilinuxguy");
|
|
||||||
console.writeln("kallanreed,bernd-herzog");
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
console.writeln("NotherNgineer,zxkmm,u-foka");
|
|
||||||
console.writeln("Netro,HTotoo");
|
|
||||||
console.writeln("");
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 3:
|
|
||||||
// https://github.com/portapack-mayhem/mayhem-firmware/graphs/contributors?to=2020-04-12&from=2015-07-31&type=c
|
|
||||||
console.writeln(STR_COLOR_DARK_YELLOW "Havoc:");
|
|
||||||
console.writeln("furrtek,mrmookie,NotPike");
|
|
||||||
console.writeln("mjwaxios,ImDroided,Giorgiofox");
|
|
||||||
console.writeln("F4GEV,z4ziggy,xmycroftx");
|
|
||||||
console.writeln("troussos,silascutler");
|
|
||||||
console.writeln("nickbouwhuis,msoose,leres");
|
|
||||||
console.writeln("joakar,dhoetger,clem-42");
|
|
||||||
console.writeln("brianlechthaler,ZeroChaos-...");
|
|
||||||
console.writeln("");
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 4:
|
|
||||||
// https://github.com/portapack-mayhem/mayhem-firmware/graphs/contributors?from=2014-07-05&to=2015-07-31&type=c
|
|
||||||
console.writeln(STR_COLOR_DARK_YELLOW "PortaPack:");
|
|
||||||
console.writeln("jboone,argilo");
|
|
||||||
console.writeln("");
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 5:
|
|
||||||
// https://github.com/mossmann/hackrf/graphs/contributors
|
|
||||||
console.writeln(STR_COLOR_DARK_YELLOW "HackRF:");
|
|
||||||
console.writeln("mossmann,dominicgs,bvernoux");
|
|
||||||
console.writeln("bgamari,schneider42,miek");
|
|
||||||
console.writeln("willcode,hessu,Sec42");
|
|
||||||
console.writeln("yhetti,ckuethe,smunaut");
|
|
||||||
console.writeln("wishi,mrbubble62,scateu...");
|
|
||||||
console.writeln("");
|
|
||||||
frame = 0; // Loop
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void AboutView::focus() {
|
void AboutView::focus() {
|
||||||
button_ok.focus();
|
menu_view.focus();
|
||||||
|
// put focus on last text line to make it more obvious that list is scrollable
|
||||||
|
menu_view.set_highlighted(10);
|
||||||
}
|
}
|
||||||
|
|
||||||
} /* namespace ui */
|
} /* namespace ui */
|
||||||
|
@ -12,25 +12,16 @@ class AboutView : public View {
|
|||||||
AboutView(NavigationView& nav);
|
AboutView(NavigationView& nav);
|
||||||
void focus() override;
|
void focus() override;
|
||||||
std::string title() const override { return "About"; };
|
std::string title() const override { return "About"; };
|
||||||
int32_t timer{180};
|
|
||||||
short frame{0};
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void update();
|
MenuView menu_view{
|
||||||
|
{0, 0, 240, 264},
|
||||||
Console console{
|
true};
|
||||||
{0, 10, 240, 240}};
|
|
||||||
|
|
||||||
Button button_ok{
|
Button button_ok{
|
||||||
{240 / 3, 270, 240 / 3, 24},
|
{240 / 3, 270, 240 / 3, 24},
|
||||||
"OK",
|
"OK",
|
||||||
};
|
};
|
||||||
|
|
||||||
MessageHandlerRegistration message_handler_update{
|
|
||||||
Message::ID::DisplayFrameSync,
|
|
||||||
[this](const Message* const) {
|
|
||||||
this->update();
|
|
||||||
}};
|
|
||||||
};
|
};
|
||||||
} // namespace ui
|
} // namespace ui
|
||||||
|
|
||||||
|
@ -57,15 +57,15 @@ void RecentEntriesTable<AircraftRecentEntries>::draw(
|
|||||||
case ADSBAgeState::Invalid:
|
case ADSBAgeState::Invalid:
|
||||||
case ADSBAgeState::Current:
|
case ADSBAgeState::Current:
|
||||||
entry_string = "";
|
entry_string = "";
|
||||||
target_color = Color::green();
|
target_color = Theme::getInstance()->fg_green->foreground;
|
||||||
break;
|
break;
|
||||||
case ADSBAgeState::Recent:
|
case ADSBAgeState::Recent:
|
||||||
entry_string = STR_COLOR_LIGHT_GREY;
|
entry_string = STR_COLOR_LIGHT_GREY;
|
||||||
target_color = Color::light_grey();
|
target_color = Theme::getInstance()->fg_light->foreground;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
entry_string = STR_COLOR_DARK_GREY;
|
entry_string = STR_COLOR_DARK_GREY;
|
||||||
target_color = Color::grey();
|
target_color = Theme::getInstance()->fg_medium->foreground;
|
||||||
};
|
};
|
||||||
|
|
||||||
entry_string +=
|
entry_string +=
|
||||||
|
@ -205,15 +205,15 @@ class ADSBRxAircraftDetailsView : public View {
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
Labels labels{
|
Labels labels{
|
||||||
{{0 * 8, 1 * 16}, "ICAO:", Color::light_grey()},
|
{{0 * 8, 1 * 16}, "ICAO:", Theme::getInstance()->fg_light->foreground},
|
||||||
{{0 * 8, 2 * 16}, "Registration:", Color::light_grey()},
|
{{0 * 8, 2 * 16}, "Registration:", Theme::getInstance()->fg_light->foreground},
|
||||||
{{0 * 8, 3 * 16}, "Manufacturer:", Color::light_grey()},
|
{{0 * 8, 3 * 16}, "Manufacturer:", Theme::getInstance()->fg_light->foreground},
|
||||||
{{0 * 8, 5 * 16}, "Model:", Color::light_grey()},
|
{{0 * 8, 5 * 16}, "Model:", Theme::getInstance()->fg_light->foreground},
|
||||||
{{0 * 8, 7 * 16}, "Type:", Color::light_grey()},
|
{{0 * 8, 7 * 16}, "Type:", Theme::getInstance()->fg_light->foreground},
|
||||||
{{0 * 8, 8 * 16}, "Number of engines:", Color::light_grey()},
|
{{0 * 8, 8 * 16}, "Number of engines:", Theme::getInstance()->fg_light->foreground},
|
||||||
{{0 * 8, 9 * 16}, "Engine type:", Color::light_grey()},
|
{{0 * 8, 9 * 16}, "Engine type:", Theme::getInstance()->fg_light->foreground},
|
||||||
{{0 * 8, 11 * 16}, "Owner:", Color::light_grey()},
|
{{0 * 8, 11 * 16}, "Owner:", Theme::getInstance()->fg_light->foreground},
|
||||||
{{0 * 8, 13 * 16}, "Operator:", Color::light_grey()}};
|
{{0 * 8, 13 * 16}, "Operator:", Theme::getInstance()->fg_light->foreground}};
|
||||||
|
|
||||||
Text text_icao_address{
|
Text text_icao_address{
|
||||||
{5 * 8, 1 * 16, 6 * 8, 16},
|
{5 * 8, 1 * 16, 6 * 8, 16},
|
||||||
@ -289,13 +289,13 @@ class ADSBRxDetailsView : public View {
|
|||||||
bool airline_checked{false};
|
bool airline_checked{false};
|
||||||
|
|
||||||
Labels labels{
|
Labels labels{
|
||||||
{{0 * 8, 1 * 16}, "ICAO:", Color::light_grey()},
|
{{0 * 8, 1 * 16}, "ICAO:", Theme::getInstance()->fg_light->foreground},
|
||||||
{{13 * 8, 1 * 16}, "Callsign:", Color::light_grey()},
|
{{13 * 8, 1 * 16}, "Callsign:", Theme::getInstance()->fg_light->foreground},
|
||||||
{{0 * 8, 2 * 16}, "Last seen:", Color::light_grey()},
|
{{0 * 8, 2 * 16}, "Last seen:", Theme::getInstance()->fg_light->foreground},
|
||||||
{{0 * 8, 3 * 16}, "Airline:", Color::light_grey()},
|
{{0 * 8, 3 * 16}, "Airline:", Theme::getInstance()->fg_light->foreground},
|
||||||
{{0 * 8, 5 * 16}, "Country:", Color::light_grey()},
|
{{0 * 8, 5 * 16}, "Country:", Theme::getInstance()->fg_light->foreground},
|
||||||
{{0 * 8, 13 * 16}, "Even position frame:", Color::light_grey()},
|
{{0 * 8, 13 * 16}, "Even position frame:", Theme::getInstance()->fg_light->foreground},
|
||||||
{{0 * 8, 15 * 16}, "Odd position frame:", Color::light_grey()}};
|
{{0 * 8, 15 * 16}, "Odd position frame:", Theme::getInstance()->fg_light->foreground}};
|
||||||
|
|
||||||
Text text_icao_address{
|
Text text_icao_address{
|
||||||
{5 * 8, 1 * 16, 6 * 8, 16},
|
{5 * 8, 1 * 16, 6 * 8, 16},
|
||||||
@ -414,7 +414,7 @@ class ADSBRxView : public View {
|
|||||||
ADSBRxDetailsView* details_view{nullptr};
|
ADSBRxDetailsView* details_view{nullptr};
|
||||||
|
|
||||||
Labels labels{
|
Labels labels{
|
||||||
{{0 * 8, 0 * 8}, "LNA: VGA: AMP:", Color::light_grey()}};
|
{{0 * 8, 0 * 8}, "LNA: VGA: AMP:", Theme::getInstance()->fg_light->foreground}};
|
||||||
|
|
||||||
LNAGainField field_lna{
|
LNAGainField field_lna{
|
||||||
{4 * 8, 0 * 16}};
|
{4 * 8, 0 * 16}};
|
||||||
@ -431,12 +431,12 @@ class ADSBRxView : public View {
|
|||||||
|
|
||||||
ActivityDot status_frame{
|
ActivityDot status_frame{
|
||||||
{27 * 8 + 2, 5, 2, 2},
|
{27 * 8 + 2, 5, 2, 2},
|
||||||
Color::white(),
|
Theme::getInstance()->bg_darkest->foreground,
|
||||||
};
|
};
|
||||||
|
|
||||||
ActivityDot status_good_frame{
|
ActivityDot status_good_frame{
|
||||||
{27 * 8 + 2, 9, 2, 2},
|
{27 * 8 + 2, 9, 2, 2},
|
||||||
Color::green(),
|
Theme::getInstance()->fg_green->foreground,
|
||||||
};
|
};
|
||||||
|
|
||||||
AudioVolumeField field_volume{
|
AudioVolumeField field_volume{
|
||||||
|
@ -46,7 +46,7 @@ void RecentEntriesTable<APRSRecentEntries>::draw(
|
|||||||
Color target_color;
|
Color target_color;
|
||||||
// auto entry_age = entry.age;
|
// auto entry_age = entry.age;
|
||||||
|
|
||||||
target_color = Color::green();
|
target_color = Theme::getInstance()->fg_green->foreground;
|
||||||
|
|
||||||
std::string entry_string = "";
|
std::string entry_string = "";
|
||||||
|
|
||||||
@ -122,6 +122,10 @@ APRSRxView::APRSRxView(NavigationView& nav, Rect parent_rect)
|
|||||||
receiver_model.enable();
|
receiver_model.enable();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void APRSRxView::on_freqchg(int64_t freq) {
|
||||||
|
field_frequency.set_value(freq);
|
||||||
|
}
|
||||||
|
|
||||||
void APRSRxView::on_packet(const APRSPacketMessage* message) {
|
void APRSRxView::on_packet(const APRSPacketMessage* message) {
|
||||||
std::string str_console = "\x1B";
|
std::string str_console = "\x1B";
|
||||||
|
|
||||||
|
@ -185,6 +185,7 @@ class APRSRxView : public View {
|
|||||||
|
|
||||||
std::string title() const override { return "APRS RX"; };
|
std::string title() const override { return "APRS RX"; };
|
||||||
void on_packet(const APRSPacketMessage* message);
|
void on_packet(const APRSPacketMessage* message);
|
||||||
|
void on_freqchg(int64_t freq);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void on_data(uint32_t value, bool is_data);
|
void on_data(uint32_t value, bool is_data);
|
||||||
@ -261,8 +262,8 @@ class APRSRXView : public View {
|
|||||||
APRSTableView view_table{nav_, view_rect};
|
APRSTableView view_table{nav_, view_rect};
|
||||||
|
|
||||||
TabView tab_view{
|
TabView tab_view{
|
||||||
{"Stream", Color::cyan(), &view_stream},
|
{"Stream", Theme::getInstance()->fg_cyan->foreground, &view_stream},
|
||||||
{"List", Color::yellow(), &view_table}};
|
{"List", Theme::getInstance()->fg_yellow->foreground, &view_table}};
|
||||||
|
|
||||||
MessageHandlerRegistration message_handler_packet{
|
MessageHandlerRegistration message_handler_packet{
|
||||||
Message::ID::APRSPacket,
|
Message::ID::APRSPacket,
|
||||||
@ -271,6 +272,13 @@ class APRSRXView : public View {
|
|||||||
this->view_stream.on_packet(message);
|
this->view_stream.on_packet(message);
|
||||||
this->view_table.on_pkt(message);
|
this->view_table.on_pkt(message);
|
||||||
}};
|
}};
|
||||||
|
|
||||||
|
MessageHandlerRegistration message_handler_freqchg{
|
||||||
|
Message::ID::FreqChangeCommand,
|
||||||
|
[this](Message* const p) {
|
||||||
|
const auto message = static_cast<const FreqChangeCommandMessage*>(p);
|
||||||
|
this->view_stream.on_freqchg(message->freq);
|
||||||
|
}};
|
||||||
};
|
};
|
||||||
|
|
||||||
} /* namespace ui */
|
} /* namespace ui */
|
||||||
|
@ -61,9 +61,9 @@ class APRSTXView : public View {
|
|||||||
void on_tx_progress(const uint32_t progress, const bool done);
|
void on_tx_progress(const uint32_t progress, const bool done);
|
||||||
|
|
||||||
Labels labels{
|
Labels labels{
|
||||||
{{0 * 8, 1 * 16}, "Source: SSID:", Color::light_grey()}, // 6 alphanum + SSID
|
{{0 * 8, 1 * 16}, "Source: SSID:", Theme::getInstance()->fg_light->foreground}, // 6 alphanum + SSID
|
||||||
{{0 * 8, 2 * 16}, " Dest.: SSID:", Color::light_grey()},
|
{{0 * 8, 2 * 16}, " Dest.: SSID:", Theme::getInstance()->fg_light->foreground},
|
||||||
{{0 * 8, 4 * 16}, "Info field:", Color::light_grey()},
|
{{0 * 8, 4 * 16}, "Info field:", Theme::getInstance()->fg_light->foreground},
|
||||||
};
|
};
|
||||||
|
|
||||||
SymField sym_source{
|
SymField sym_source{
|
||||||
|
188
firmware/application/apps/ui_battinfo.cpp
Normal file
188
firmware/application/apps/ui_battinfo.cpp
Normal file
@ -0,0 +1,188 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2015 Jared Boone, ShareBrained Technology, Inc.
|
||||||
|
* Copyright (C) 2016 Furrtek
|
||||||
|
*
|
||||||
|
* 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 "ui_battinfo.hpp"
|
||||||
|
|
||||||
|
#include "event_m0.hpp"
|
||||||
|
#include "portapack.hpp"
|
||||||
|
#include "battery.hpp"
|
||||||
|
#include <cstring>
|
||||||
|
|
||||||
|
using namespace portapack;
|
||||||
|
|
||||||
|
namespace ui {
|
||||||
|
|
||||||
|
void BattinfoView::focus() {
|
||||||
|
button_exit.focus();
|
||||||
|
}
|
||||||
|
|
||||||
|
// called each 1/60th of second, so 6 = 100ms
|
||||||
|
void BattinfoView::on_timer() {
|
||||||
|
if (++timer_counter == timer_period) {
|
||||||
|
timer_counter = 0;
|
||||||
|
update_result();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void BattinfoView::update_result() {
|
||||||
|
if (!battery::BatteryManagement::isDetected()) {
|
||||||
|
text_percent.set("UNKNOWN");
|
||||||
|
text_voltage.set("UNKNOWN");
|
||||||
|
text_current.set("-");
|
||||||
|
text_charge.set("-");
|
||||||
|
text_cycles.set("-");
|
||||||
|
text_ttef.set("-");
|
||||||
|
text_method.set("-");
|
||||||
|
text_warn.set("");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
bool uichg = false;
|
||||||
|
uint8_t valid_mask = 0;
|
||||||
|
battery::BatteryManagement::getBatteryInfo(valid_mask, percent, voltage, current);
|
||||||
|
// update text fields
|
||||||
|
if (percent <= 100 && (valid_mask & battery::BatteryManagement::BATT_VALID_VOLTAGE) == battery::BatteryManagement::BATT_VALID_VOLTAGE)
|
||||||
|
text_percent.set(to_string_dec_uint(percent) + " %");
|
||||||
|
else
|
||||||
|
text_percent.set("UNKNOWN");
|
||||||
|
if (voltage > 1 && (valid_mask & battery::BatteryManagement::BATT_VALID_VOLTAGE) == battery::BatteryManagement::BATT_VALID_VOLTAGE) {
|
||||||
|
text_voltage.set(to_string_decimal(voltage / 1000.0, 3) + " V");
|
||||||
|
} else {
|
||||||
|
text_voltage.set("UNKNOWN");
|
||||||
|
}
|
||||||
|
if ((valid_mask & battery::BatteryManagement::BATT_VALID_CURRENT) == battery::BatteryManagement::BATT_VALID_CURRENT) {
|
||||||
|
if (labels_opt.hidden()) uichg = true;
|
||||||
|
labels_opt.hidden(false);
|
||||||
|
text_current.hidden(false);
|
||||||
|
text_charge.hidden(false);
|
||||||
|
text_current.set(to_string_dec_int(current) + " mA");
|
||||||
|
text_charge.set(current >= 0 ? "Charging" : "Discharging");
|
||||||
|
labels_opt.hidden(false);
|
||||||
|
|
||||||
|
text_ttef.hidden(false);
|
||||||
|
} else {
|
||||||
|
if (!labels_opt.hidden()) uichg = true;
|
||||||
|
labels_opt.hidden(true);
|
||||||
|
text_current.hidden(true);
|
||||||
|
text_charge.hidden(true);
|
||||||
|
text_cycles.hidden(true);
|
||||||
|
text_ttef.hidden(true);
|
||||||
|
text_warn.set("");
|
||||||
|
}
|
||||||
|
if ((valid_mask & battery::BatteryManagement::BATT_VALID_CYCLES) == battery::BatteryManagement::BATT_VALID_CYCLES) {
|
||||||
|
text_cycles.hidden(false);
|
||||||
|
uint16_t cycles = battery::BatteryManagement::get_cycles();
|
||||||
|
if (cycles < 2)
|
||||||
|
text_warn.set("SoC improves after 2 cycles");
|
||||||
|
else
|
||||||
|
text_warn.set("");
|
||||||
|
text_cycles.set(to_string_dec_uint(cycles));
|
||||||
|
} else {
|
||||||
|
text_cycles.hidden(true);
|
||||||
|
text_warn.set("");
|
||||||
|
}
|
||||||
|
if ((valid_mask & battery::BatteryManagement::BATT_VALID_TTEF) == battery::BatteryManagement::BATT_VALID_TTEF) {
|
||||||
|
text_ttef.hidden(false);
|
||||||
|
float ttef = 0;
|
||||||
|
if (current <= 0) {
|
||||||
|
ttef = battery::BatteryManagement::get_tte();
|
||||||
|
} else {
|
||||||
|
ttef = battery::BatteryManagement::get_ttf();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convert ttef to hours and minutes
|
||||||
|
uint8_t hours = static_cast<uint8_t>(ttef);
|
||||||
|
uint8_t minutes = static_cast<uint8_t>((ttef - hours) * 60 + 0.5); // +0.5 for rounding
|
||||||
|
|
||||||
|
// Create the formatted string
|
||||||
|
std::string formatted_time;
|
||||||
|
if (hours > 0) {
|
||||||
|
formatted_time += to_string_dec_uint(hours) + "h ";
|
||||||
|
}
|
||||||
|
formatted_time += to_string_dec_uint(minutes) + "m";
|
||||||
|
|
||||||
|
text_ttef.set(formatted_time);
|
||||||
|
} else {
|
||||||
|
text_ttef.hidden(true);
|
||||||
|
}
|
||||||
|
if ((valid_mask & battery::BatteryManagement::BATT_VALID_PERCENT) == battery::BatteryManagement::BATT_VALID_PERCENT) {
|
||||||
|
text_method.set("IC");
|
||||||
|
button_mode.set_text("Volt");
|
||||||
|
} else {
|
||||||
|
text_method.set("Voltage");
|
||||||
|
button_mode.set_text("IC");
|
||||||
|
}
|
||||||
|
if (uichg) set_dirty();
|
||||||
|
// to update status bar too, send message in behalf of batt manager
|
||||||
|
BatteryStateMessage msg{valid_mask, percent, current >= 0, voltage};
|
||||||
|
EventDispatcher::send_message(msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
BattinfoView::BattinfoView(NavigationView& nav)
|
||||||
|
: nav_{nav} {
|
||||||
|
add_children({&labels,
|
||||||
|
&labels_opt,
|
||||||
|
&text_percent,
|
||||||
|
&text_voltage,
|
||||||
|
&text_current,
|
||||||
|
&text_charge,
|
||||||
|
&text_method,
|
||||||
|
&button_mode,
|
||||||
|
&button_exit,
|
||||||
|
&text_cycles,
|
||||||
|
&text_warn,
|
||||||
|
&text_ttef});
|
||||||
|
|
||||||
|
button_exit.on_select = [this, &nav](Button&) {
|
||||||
|
nav.pop();
|
||||||
|
};
|
||||||
|
button_mode.on_select = [this, &nav](Button&) {
|
||||||
|
if (button_mode.text() == "IC") {
|
||||||
|
battery::BatteryManagement::set_calc_override(false);
|
||||||
|
persistent_memory::set_ui_override_batt_calc(false);
|
||||||
|
button_mode.set_text("Volt");
|
||||||
|
} else {
|
||||||
|
battery::BatteryManagement::set_calc_override(true);
|
||||||
|
persistent_memory::set_ui_override_batt_calc(true);
|
||||||
|
button_mode.set_text("IC");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
update_result();
|
||||||
|
if (thread == nullptr) thread = chThdCreateFromHeap(NULL, 1024, NORMALPRIO + 10, BattinfoView::static_fn, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
msg_t BattinfoView::static_fn(void* arg) {
|
||||||
|
auto obj = static_cast<BattinfoView*>(arg);
|
||||||
|
while (!chThdShouldTerminate()) {
|
||||||
|
chThdSleepMilliseconds(16);
|
||||||
|
obj->on_timer();
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
BattinfoView::~BattinfoView() {
|
||||||
|
if (thread) {
|
||||||
|
chThdTerminate(thread);
|
||||||
|
chThdWait(thread);
|
||||||
|
thread = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} // namespace ui
|
107
firmware/application/apps/ui_battinfo.hpp
Normal file
107
firmware/application/apps/ui_battinfo.hpp
Normal file
@ -0,0 +1,107 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2015 Jared Boone, ShareBrained Technology, Inc.
|
||||||
|
* Copyright (C) 2016 Furrtek
|
||||||
|
*
|
||||||
|
* This file is part of PortaPack.
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2, or (at your option)
|
||||||
|
* any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; see the file COPYING. If not, write to
|
||||||
|
* the Free Software Foundation, Inc., 51 Franklin Street,
|
||||||
|
* Boston, MA 02110-1301, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __UI_BATTINFO_H__
|
||||||
|
#define __UI_BATTINFO_H__
|
||||||
|
|
||||||
|
#include "ui.hpp"
|
||||||
|
#include "ui_widget.hpp"
|
||||||
|
#include "ui_navigation.hpp"
|
||||||
|
#include "string_format.hpp"
|
||||||
|
|
||||||
|
namespace ui {
|
||||||
|
class BattinfoView : public View {
|
||||||
|
public:
|
||||||
|
~BattinfoView();
|
||||||
|
BattinfoView(NavigationView& nav);
|
||||||
|
BattinfoView(const BattinfoView&) = delete;
|
||||||
|
BattinfoView(BattinfoView&&) = delete;
|
||||||
|
BattinfoView& operator=(const BattinfoView&) = delete;
|
||||||
|
BattinfoView& operator=(BattinfoView&&) = delete;
|
||||||
|
|
||||||
|
void focus() override;
|
||||||
|
std::string title() const override { return "Battery"; };
|
||||||
|
|
||||||
|
private:
|
||||||
|
void update_result();
|
||||||
|
void on_timer();
|
||||||
|
NavigationView& nav_;
|
||||||
|
uint16_t timer_period = 60;
|
||||||
|
uint16_t timer_counter = 0;
|
||||||
|
uint8_t percent = 0;
|
||||||
|
uint16_t voltage = 0;
|
||||||
|
int32_t current = 0;
|
||||||
|
|
||||||
|
Labels labels{
|
||||||
|
{{2 * 8, 1 * 16}, "Percent:", Theme::getInstance()->fg_light->foreground},
|
||||||
|
{{2 * 8, 2 * 16}, "Voltage:", Theme::getInstance()->fg_light->foreground},
|
||||||
|
{{2 * 8, 3 * 16}, "Method:", Theme::getInstance()->fg_light->foreground},
|
||||||
|
};
|
||||||
|
|
||||||
|
Labels labels_opt{
|
||||||
|
{{2 * 8, 4 * 16}, "Current:", Theme::getInstance()->fg_light->foreground},
|
||||||
|
{{2 * 8, 5 * 16}, "Charge:", Theme::getInstance()->fg_light->foreground},
|
||||||
|
{{2 * 8, 6 * 16}, "TTF/E:", Theme::getInstance()->fg_light->foreground},
|
||||||
|
{{2 * 8, 7 * 16}, "Cycles:", Theme::getInstance()->fg_light->foreground},
|
||||||
|
{{2 * 8, 10 * 16}, "Change method:", Theme::getInstance()->fg_light->foreground},
|
||||||
|
};
|
||||||
|
|
||||||
|
Text text_percent{
|
||||||
|
{13 * 8, 1 * 16, 10 * 16, 16},
|
||||||
|
"-"};
|
||||||
|
Text text_voltage{
|
||||||
|
{13 * 8, 2 * 16, 10 * 16, 16},
|
||||||
|
"-"};
|
||||||
|
Text text_method{
|
||||||
|
{13 * 8, 3 * 16, 10 * 16, 16},
|
||||||
|
"-"};
|
||||||
|
Text text_current{
|
||||||
|
{13 * 8, 4 * 16, 10 * 16, 16},
|
||||||
|
"-"};
|
||||||
|
Text text_charge{
|
||||||
|
{13 * 8, 5 * 16, 10 * 16, 16},
|
||||||
|
"-"};
|
||||||
|
Text text_ttef{
|
||||||
|
{13 * 8, 6 * 16, 10 * 16, 16},
|
||||||
|
"-"};
|
||||||
|
Text text_cycles{
|
||||||
|
{13 * 8, 7 * 16, 10 * 16, 16},
|
||||||
|
"-"};
|
||||||
|
|
||||||
|
Text text_warn{
|
||||||
|
{2 * 8, 8 * 16, 30 * 8, 2 * 16},
|
||||||
|
""};
|
||||||
|
|
||||||
|
Button button_mode{
|
||||||
|
{2 * 8, 11 * 16 + 5, 5 * 16, 32},
|
||||||
|
"Volt"};
|
||||||
|
|
||||||
|
Button button_exit{
|
||||||
|
{72, 17 * 16, 96, 32},
|
||||||
|
"Back"};
|
||||||
|
static msg_t static_fn(void* arg);
|
||||||
|
Thread* thread{nullptr};
|
||||||
|
};
|
||||||
|
|
||||||
|
} /* namespace ui */
|
||||||
|
|
||||||
|
#endif /*__UI_BATTINFO__*/
|
@ -50,12 +50,12 @@ class XylosView : public View {
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
Labels labels{
|
Labels labels{
|
||||||
{{8 * 8, 1 * 8}, "Header:", Color::light_grey()},
|
{{8 * 8, 1 * 8}, "Header:", Theme::getInstance()->fg_light->foreground},
|
||||||
{{4 * 8, 3 * 8}, "City code:", Color::light_grey()},
|
{{4 * 8, 3 * 8}, "City code:", Theme::getInstance()->fg_light->foreground},
|
||||||
{{7 * 8, 5 * 8}, "Family:", Color::light_grey()},
|
{{7 * 8, 5 * 8}, "Family:", Theme::getInstance()->fg_light->foreground},
|
||||||
{{2 * 8, 7 * 8 + 2}, "Subfamily:", Color::light_grey()},
|
{{2 * 8, 7 * 8 + 2}, "Subfamily:", Theme::getInstance()->fg_light->foreground},
|
||||||
{{2 * 8, 11 * 8}, "Receiver ID:", Color::light_grey()},
|
{{2 * 8, 11 * 8}, "Receiver ID:", Theme::getInstance()->fg_light->foreground},
|
||||||
{{2 * 8, 14 * 8}, "Relay:", Color::light_grey()}};
|
{{2 * 8, 14 * 8}, "Relay:", Theme::getInstance()->fg_light->foreground}};
|
||||||
|
|
||||||
NumberField field_header_a{
|
NumberField field_header_a{
|
||||||
{16 * 8, 1 * 8},
|
{16 * 8, 1 * 8},
|
||||||
@ -130,9 +130,9 @@ class EPARView : public View {
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
Labels labels{
|
Labels labels{
|
||||||
{{4 * 8, 1 * 8}, "City code:", Color::light_grey()},
|
{{4 * 8, 1 * 8}, "City code:", Theme::getInstance()->fg_light->foreground},
|
||||||
{{8 * 8, 3 * 8}, "Group:", Color::light_grey()},
|
{{8 * 8, 3 * 8}, "Group:", Theme::getInstance()->fg_light->foreground},
|
||||||
{{8 * 8, 7 * 8}, "Relay:", Color::light_grey()}};
|
{{8 * 8, 7 * 8}, "Relay:", Theme::getInstance()->fg_light->foreground}};
|
||||||
|
|
||||||
NumberField field_city{
|
NumberField field_city{
|
||||||
{16 * 8, 1 * 8},
|
{16 * 8, 1 * 8},
|
||||||
@ -195,11 +195,11 @@ class BHTView : public View {
|
|||||||
EPARView view_EPAR{view_rect};
|
EPARView view_EPAR{view_rect};
|
||||||
|
|
||||||
TabView tab_view{
|
TabView tab_view{
|
||||||
{"Xylos", Color::cyan(), &view_xylos},
|
{"Xylos", Theme::getInstance()->fg_cyan->foreground, &view_xylos},
|
||||||
{"EPAR", Color::green(), &view_EPAR}};
|
{"EPAR", Theme::getInstance()->fg_green->foreground, &view_EPAR}};
|
||||||
|
|
||||||
Labels labels{
|
Labels labels{
|
||||||
{{29 * 8, 14 * 16 + 4}, "s", Color::light_grey()}};
|
{{29 * 8, 14 * 16 + 4}, "s", Theme::getInstance()->fg_light->foreground}};
|
||||||
|
|
||||||
Checkbox checkbox_scan{
|
Checkbox checkbox_scan{
|
||||||
{1 * 8, 25 * 8},
|
{1 * 8, 25 * 8},
|
||||||
|
63
firmware/application/apps/ui_bmp_file_viewer.cpp
Normal file
63
firmware/application/apps/ui_bmp_file_viewer.cpp
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2024 HTotoo
|
||||||
|
*
|
||||||
|
* 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 "ui_bmp_file_viewer.hpp"
|
||||||
|
|
||||||
|
extern ui::SystemView* system_view_ptr;
|
||||||
|
|
||||||
|
using namespace portapack;
|
||||||
|
namespace fs = std::filesystem;
|
||||||
|
|
||||||
|
namespace ui {
|
||||||
|
|
||||||
|
BMPFileViewer::BMPFileViewer(
|
||||||
|
NavigationView& nav,
|
||||||
|
const std::filesystem::path& path)
|
||||||
|
: nav_{nav},
|
||||||
|
path_{path} {
|
||||||
|
add_children(
|
||||||
|
{&bmp});
|
||||||
|
bmp.set_enter_pass(true); // pass the enter key to me, so i can exit. this will disable zoom + pos reset
|
||||||
|
set_focusable(true);
|
||||||
|
system_view_ptr->set_app_fullscreen(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
BMPFileViewer::~BMPFileViewer() {
|
||||||
|
system_view_ptr->set_app_fullscreen(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
void BMPFileViewer::focus() {
|
||||||
|
bmp.focus();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool BMPFileViewer::on_key(KeyEvent k) {
|
||||||
|
if (k == KeyEvent::Select) {
|
||||||
|
nav_.pop();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void BMPFileViewer::paint(Painter&) {
|
||||||
|
bmp.load_bmp(path_);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace ui
|
50
firmware/application/apps/ui_bmp_file_viewer.hpp
Normal file
50
firmware/application/apps/ui_bmp_file_viewer.hpp
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2024 HTotoo
|
||||||
|
*
|
||||||
|
* This file is part of PortaPack.
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2, or (at your option)
|
||||||
|
* any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; see the file COPYING. If not, write to
|
||||||
|
* the Free Software Foundation, Inc., 51 Franklin Street,
|
||||||
|
* Boston, MA 02110-1301, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __UI_BMP_FILE_VIEWER_H__
|
||||||
|
#define __UI_BMP_FILE_VIEWER_H__
|
||||||
|
|
||||||
|
#include "ui.hpp"
|
||||||
|
#include "ui_navigation.hpp"
|
||||||
|
#include "ui_painter.hpp"
|
||||||
|
#include "ui_widget.hpp"
|
||||||
|
#include "file.hpp"
|
||||||
|
#include "ui_bmpview.hpp"
|
||||||
|
|
||||||
|
namespace ui {
|
||||||
|
|
||||||
|
class BMPFileViewer : public View {
|
||||||
|
public:
|
||||||
|
BMPFileViewer(NavigationView& nav, const std::filesystem::path& path);
|
||||||
|
~BMPFileViewer();
|
||||||
|
bool on_key(KeyEvent key) override;
|
||||||
|
void paint(Painter& painter) override;
|
||||||
|
void focus() override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
NavigationView& nav_;
|
||||||
|
std::filesystem::path path_{};
|
||||||
|
BMPViewer bmp{{0, 0, 240, 320}};
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace ui
|
||||||
|
|
||||||
|
#endif // __UI_BMP_FILE_VIEWER_H__
|
@ -34,9 +34,9 @@
|
|||||||
|
|
||||||
#include "ui_sd_card_debug.hpp"
|
#include "ui_sd_card_debug.hpp"
|
||||||
#include "ui_font_fixed_8x16.hpp"
|
#include "ui_font_fixed_8x16.hpp"
|
||||||
#include "ui_styles.hpp"
|
|
||||||
#include "ui_painter.hpp"
|
#include "ui_painter.hpp"
|
||||||
#include "ui_external_items_menu_loader.hpp"
|
#include "ui_external_items_menu_loader.hpp"
|
||||||
|
#include "ui_debug_battery.hpp"
|
||||||
|
|
||||||
#include "portapack.hpp"
|
#include "portapack.hpp"
|
||||||
#include "portapack_persistent_memory.hpp"
|
#include "portapack_persistent_memory.hpp"
|
||||||
@ -80,7 +80,7 @@ void TemperatureWidget::paint(Painter& painter) {
|
|||||||
|
|
||||||
const auto rect = screen_rect();
|
const auto rect = screen_rect();
|
||||||
const Color color_background{0, 0, 64};
|
const Color color_background{0, 0, 64};
|
||||||
const Color color_foreground = Color::green();
|
const Color color_foreground = Theme::getInstance()->fg_green->foreground;
|
||||||
const Color color_reticle{128, 128, 128};
|
const Color color_reticle{128, 128, 128};
|
||||||
|
|
||||||
const auto graph_width = static_cast<int>(logger.capacity()) * bar_width;
|
const auto graph_width = static_cast<int>(logger.capacity()) * bar_width;
|
||||||
@ -226,6 +226,8 @@ uint32_t RegistersWidget::reg_read(const uint32_t register_number) {
|
|||||||
return radio::debug::second_if::register_read(register_number);
|
return radio::debug::second_if::register_read(register_number);
|
||||||
case CT_SI5351:
|
case CT_SI5351:
|
||||||
return portapack::clock_generator.read_register(register_number);
|
return portapack::clock_generator.read_register(register_number);
|
||||||
|
case CT_BATTERY:
|
||||||
|
return battery::BatteryManagement::read_register(register_number);
|
||||||
case CT_AUDIO:
|
case CT_AUDIO:
|
||||||
return audio::debug::reg_read(register_number);
|
return audio::debug::reg_read(register_number);
|
||||||
}
|
}
|
||||||
@ -247,6 +249,9 @@ void RegistersWidget::reg_write(const uint32_t register_number, const uint32_t v
|
|||||||
case CT_SI5351:
|
case CT_SI5351:
|
||||||
portapack::clock_generator.write_register(register_number, value);
|
portapack::clock_generator.write_register(register_number, value);
|
||||||
break;
|
break;
|
||||||
|
case CT_BATTERY:
|
||||||
|
battery::BatteryManagement::write_register(register_number, value);
|
||||||
|
break;
|
||||||
case CT_AUDIO:
|
case CT_AUDIO:
|
||||||
audio::debug::reg_write(register_number, value);
|
audio::debug::reg_write(register_number, value);
|
||||||
break;
|
break;
|
||||||
@ -292,7 +297,7 @@ RegistersView::RegistersView(
|
|||||||
const auto value = registers_widget.reg_read(0);
|
const auto value = registers_widget.reg_read(0);
|
||||||
field_write_data_val.set_value(value);
|
field_write_data_val.set_value(value);
|
||||||
|
|
||||||
button_write.set_style(&Styles::red);
|
button_write.set_style(Theme::getInstance()->fg_red);
|
||||||
button_write.on_select = [this](Button&) {
|
button_write.on_select = [this](Button&) {
|
||||||
this->registers_widget.reg_write(field_write_reg_num.to_integer(), field_write_data_val.to_integer());
|
this->registers_widget.reg_write(field_write_reg_num.to_integer(), field_write_data_val.to_integer());
|
||||||
this->registers_widget.update();
|
this->registers_widget.update();
|
||||||
@ -315,7 +320,7 @@ bool RegistersView::on_encoder(const EncoderEvent delta) {
|
|||||||
void ControlsSwitchesWidget::on_show() {
|
void ControlsSwitchesWidget::on_show() {
|
||||||
display.fill_rectangle(
|
display.fill_rectangle(
|
||||||
screen_rect(),
|
screen_rect(),
|
||||||
Color::black());
|
Theme::getInstance()->bg_darkest->background);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ControlsSwitchesWidget::on_key(const KeyEvent key) {
|
bool ControlsSwitchesWidget::on_key(const KeyEvent key) {
|
||||||
@ -345,11 +350,11 @@ void ControlsSwitchesWidget::paint(Painter& painter) {
|
|||||||
}};
|
}};
|
||||||
|
|
||||||
for (const auto r : button_rects) {
|
for (const auto r : button_rects) {
|
||||||
painter.fill_rectangle(r + pos, Color::blue());
|
painter.fill_rectangle(r + pos, Theme::getInstance()->fg_blue->foreground);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (get_touch_frame().touch)
|
if (get_touch_frame().touch)
|
||||||
painter.fill_rectangle(button_rects[8] + pos, Color::yellow());
|
painter.fill_rectangle(button_rects[8] + pos, Theme::getInstance()->fg_yellow->foreground);
|
||||||
|
|
||||||
const std::array<Rect, 8> raw_rects{{
|
const std::array<Rect, 8> raw_rects{{
|
||||||
{64 + 1, 32 + 1, 16 - 2, 16 - 2}, // Right
|
{64 + 1, 32 + 1, 16 - 2, 16 - 2}, // Right
|
||||||
@ -365,7 +370,7 @@ void ControlsSwitchesWidget::paint(Painter& painter) {
|
|||||||
auto switches_raw = control::debug::switches();
|
auto switches_raw = control::debug::switches();
|
||||||
for (const auto r : raw_rects) {
|
for (const auto r : raw_rects) {
|
||||||
if (switches_raw & 1)
|
if (switches_raw & 1)
|
||||||
painter.fill_rectangle(r + pos, Color::yellow());
|
painter.fill_rectangle(r + pos, Theme::getInstance()->fg_yellow->foreground);
|
||||||
|
|
||||||
switches_raw >>= 1;
|
switches_raw >>= 1;
|
||||||
}
|
}
|
||||||
@ -382,7 +387,7 @@ void ControlsSwitchesWidget::paint(Painter& painter) {
|
|||||||
auto switches_debounced = get_switches_state().to_ulong();
|
auto switches_debounced = get_switches_state().to_ulong();
|
||||||
for (const auto r : debounced_rects) {
|
for (const auto r : debounced_rects) {
|
||||||
if (switches_debounced & 1)
|
if (switches_debounced & 1)
|
||||||
painter.fill_rectangle(r + pos, Color::green());
|
painter.fill_rectangle(r + pos, Theme::getInstance()->fg_green->foreground);
|
||||||
|
|
||||||
switches_debounced >>= 1;
|
switches_debounced >>= 1;
|
||||||
}
|
}
|
||||||
@ -399,7 +404,7 @@ void ControlsSwitchesWidget::paint(Painter& painter) {
|
|||||||
auto switches_event = key_event_mask;
|
auto switches_event = key_event_mask;
|
||||||
for (const auto r : events_rects) {
|
for (const auto r : events_rects) {
|
||||||
if (switches_event & 1)
|
if (switches_event & 1)
|
||||||
painter.fill_rectangle(r + pos, Color::red());
|
painter.fill_rectangle(r + pos, Theme::getInstance()->fg_red->foreground);
|
||||||
|
|
||||||
switches_event >>= 1;
|
switches_event >>= 1;
|
||||||
}
|
}
|
||||||
@ -407,12 +412,12 @@ void ControlsSwitchesWidget::paint(Painter& painter) {
|
|||||||
switches_event = long_press_key_event_mask;
|
switches_event = long_press_key_event_mask;
|
||||||
for (const auto r : events_rects) {
|
for (const auto r : events_rects) {
|
||||||
if (switches_event & 1)
|
if (switches_event & 1)
|
||||||
painter.fill_rectangle(r + pos, Color::cyan());
|
painter.fill_rectangle(r + pos, Theme::getInstance()->fg_cyan->foreground);
|
||||||
|
|
||||||
switches_event >>= 1;
|
switches_event >>= 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
painter.draw_string({5 * 8, 12 * 16}, Styles::light_grey, to_string_dec_int(last_delta, 3));
|
painter.draw_string({5 * 8, 12 * 16}, *Theme::getInstance()->fg_light, to_string_dec_int(last_delta, 3));
|
||||||
}
|
}
|
||||||
|
|
||||||
void ControlsSwitchesWidget::on_frame_sync() {
|
void ControlsSwitchesWidget::on_frame_sync() {
|
||||||
@ -455,11 +460,15 @@ void DebugPeripheralsMenuView::on_populate() {
|
|||||||
const char* max283x = hackrf_r9 ? "MAX2839" : "MAX2837";
|
const char* max283x = hackrf_r9 ? "MAX2839" : "MAX2837";
|
||||||
const char* si5351x = hackrf_r9 ? "Si5351A" : "Si5351C";
|
const char* si5351x = hackrf_r9 ? "Si5351A" : "Si5351C";
|
||||||
add_items({
|
add_items({
|
||||||
{"RFFC5072", ui::Color::dark_cyan(), &bitmap_icon_peripherals_details, [this]() { nav_.push<RegistersView>("RFFC5072", RegistersWidgetConfig{CT_RFFC5072, 31, 31, 16}); }},
|
{"RFFC5072", Theme::getInstance()->fg_darkcyan->foreground, &bitmap_icon_peripherals_details, [this]() { nav_.push<RegistersView>("RFFC5072", RegistersWidgetConfig{CT_RFFC5072, 31, 31, 16}); }},
|
||||||
{max283x, ui::Color::dark_cyan(), &bitmap_icon_peripherals_details, [this, max283x]() { nav_.push<RegistersView>(max283x, RegistersWidgetConfig{CT_MAX283X, 32, 32, 10}); }},
|
{max283x, Theme::getInstance()->fg_darkcyan->foreground, &bitmap_icon_peripherals_details, [this, max283x]() { nav_.push<RegistersView>(max283x, RegistersWidgetConfig{CT_MAX283X, 32, 32, 10}); }},
|
||||||
{si5351x, ui::Color::dark_cyan(), &bitmap_icon_peripherals_details, [this, si5351x]() { nav_.push<RegistersView>(si5351x, RegistersWidgetConfig{CT_SI5351, 188, 96, 8}); }},
|
{si5351x, Theme::getInstance()->fg_darkcyan->foreground, &bitmap_icon_peripherals_details, [this, si5351x]() { nav_.push<RegistersView>(si5351x, RegistersWidgetConfig{CT_SI5351, 188, 96, 8}); }},
|
||||||
{audio::debug::codec_name(), ui::Color::dark_cyan(), &bitmap_icon_peripherals_details, [this]() { nav_.push<RegistersView>(audio::debug::codec_name(), RegistersWidgetConfig{CT_AUDIO, audio::debug::reg_count(), audio::debug::reg_count(), audio::debug::reg_bits()}); }},
|
{audio::debug::codec_name(), Theme::getInstance()->fg_darkcyan->foreground, &bitmap_icon_peripherals_details, [this]() { nav_.push<RegistersView>(audio::debug::codec_name(), RegistersWidgetConfig{CT_AUDIO, audio::debug::reg_count(), audio::debug::reg_count(), audio::debug::reg_bits()}); }},
|
||||||
});
|
});
|
||||||
|
if (battery::BatteryManagement::detectedModule() == battery::BatteryManagement::BatteryModules::BATT_MAX17055) {
|
||||||
|
add_item(
|
||||||
|
{"MAX17055", Theme::getInstance()->fg_darkcyan->foreground, &bitmap_icon_peripherals_details, [this]() { nav_.push<RegistersView>("MAX17055", RegistersWidgetConfig{CT_BATTERY, 256, 16, 16}); }});
|
||||||
|
}
|
||||||
set_max_rows(2); // allow wider buttons
|
set_max_rows(2); // allow wider buttons
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -486,23 +495,28 @@ DebugMenuView::DebugMenuView(NavigationView& nav)
|
|||||||
|
|
||||||
void DebugMenuView::on_populate() {
|
void DebugMenuView::on_populate() {
|
||||||
if (portapack::persistent_memory::show_gui_return_icon()) {
|
if (portapack::persistent_memory::show_gui_return_icon()) {
|
||||||
add_items({{"..", ui::Color::light_grey(), &bitmap_icon_previous, [this]() { nav_.pop(); }}});
|
add_items({{"..", ui::Theme::getInstance()->fg_light->foreground, &bitmap_icon_previous, [this]() { nav_.pop(); }}});
|
||||||
}
|
}
|
||||||
add_items({
|
add_items({
|
||||||
{"Buttons Test", ui::Color::dark_cyan(), &bitmap_icon_controls, [this]() { nav_.push<DebugControlsView>(); }},
|
{"Buttons Test", ui::Theme::getInstance()->fg_darkcyan->foreground, &bitmap_icon_controls, [this]() { nav_.push<DebugControlsView>(); }},
|
||||||
{"Debug Dump", ui::Color::dark_cyan(), &bitmap_icon_memory, [this]() { portapack::persistent_memory::debug_dump(); }},
|
{"Debug Dump", ui::Theme::getInstance()->fg_darkcyan->foreground, &bitmap_icon_memory, [this]() { portapack::persistent_memory::debug_dump(); }},
|
||||||
{"M0 Stack Dump", ui::Color::dark_cyan(), &bitmap_icon_memory, [this]() { stack_dump(); }},
|
{"M0 Stack Dump", ui::Theme::getInstance()->fg_darkcyan->foreground, &bitmap_icon_memory, [this]() { stack_dump(); }},
|
||||||
{"Memory Dump", ui::Color::dark_cyan(), &bitmap_icon_memory, [this]() { nav_.push<DebugMemoryDumpView>(); }},
|
{"Memory Dump", ui::Theme::getInstance()->fg_darkcyan->foreground, &bitmap_icon_memory, [this]() { nav_.push<DebugMemoryDumpView>(); }},
|
||||||
//{"Memory Usage", ui::Color::dark_cyan(), &bitmap_icon_memory, [this]() { nav_.push<DebugMemoryView>(); }},
|
//{"Memory Usage", ui::Theme::getInstance()->fg_darkcyan->foreground, &bitmap_icon_memory, [this]() { nav_.push<DebugMemoryView>(); }},
|
||||||
{"Peripherals", ui::Color::dark_cyan(), &bitmap_icon_peripherals, [this]() { nav_.push<DebugPeripheralsMenuView>(); }},
|
{"Peripherals", ui::Theme::getInstance()->fg_darkcyan->foreground, &bitmap_icon_peripherals, [this]() { nav_.push<DebugPeripheralsMenuView>(); }},
|
||||||
{"Pers. Memory", ui::Color::dark_cyan(), &bitmap_icon_memory, [this]() { nav_.push<DebugPmemView>(); }},
|
{"Pers. Memory", ui::Theme::getInstance()->fg_darkcyan->foreground, &bitmap_icon_memory, [this]() { nav_.push<DebugPmemView>(); }},
|
||||||
//{ "Radio State", ui::Color::white(), nullptr, [this](){ nav_.push<NotImplementedView>(); } },
|
//{ "Radio State", ui::Theme::getInstance()->bg_darkest->foreground, nullptr, [this](){ nav_.push<NotImplementedView>(); } },
|
||||||
{"Reboot", ui::Color::dark_cyan(), &bitmap_icon_setup, [this]() { nav_.push<DebugReboot>(); }},
|
{"SD Card", ui::Theme::getInstance()->fg_darkcyan->foreground, &bitmap_icon_sdcard, [this]() { nav_.push<SDCardDebugView>(); }},
|
||||||
{"SD Card", ui::Color::dark_cyan(), &bitmap_icon_sdcard, [this]() { nav_.push<SDCardDebugView>(); }},
|
{"Temperature", ui::Theme::getInstance()->fg_darkcyan->foreground, &bitmap_icon_temperature, [this]() { nav_.push<TemperatureView>(); }},
|
||||||
{"Temperature", ui::Color::dark_cyan(), &bitmap_icon_temperature, [this]() { nav_.push<TemperatureView>(); }},
|
{"Touch Test", ui::Theme::getInstance()->fg_darkcyan->foreground, &bitmap_icon_notepad, [this]() { nav_.push<DebugScreenTest>(); }},
|
||||||
{"Touch Test", ui::Color::dark_cyan(), &bitmap_icon_notepad, [this]() { nav_.push<DebugScreenTest>(); }},
|
{"Reboot", ui::Theme::getInstance()->fg_darkcyan->foreground, &bitmap_icon_setup, [this]() { nav_.push<DebugReboot>(); }},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (battery::BatteryManagement::detectedModule() == battery::BatteryManagement::BatteryModules::BATT_MAX17055) {
|
||||||
|
add_item(
|
||||||
|
{"Battery", ui::Theme::getInstance()->fg_darkcyan->foreground, &bitmap_icon_batt_icon, [this]() { nav_.push<BatteryCapacityView>(); }});
|
||||||
|
}
|
||||||
|
|
||||||
for (auto const& gridItem : ExternalItemsMenuLoader::load_external_items(app_location_t::DEBUG, nav_)) {
|
for (auto const& gridItem : ExternalItemsMenuLoader::load_external_items(app_location_t::DEBUG, nav_)) {
|
||||||
add_item(gridItem);
|
add_item(gridItem);
|
||||||
};
|
};
|
||||||
@ -535,7 +549,7 @@ DebugMemoryDumpView::DebugMemoryDumpView(NavigationView& nav) {
|
|||||||
field_data_value.set_dirty();
|
field_data_value.set_dirty();
|
||||||
};
|
};
|
||||||
|
|
||||||
button_write.set_style(&Styles::red);
|
button_write.set_style(Theme::getInstance()->fg_red);
|
||||||
button_write.on_select = [this](Button&) {
|
button_write.on_select = [this](Button&) {
|
||||||
*(uint32_t*)field_rw_address.to_integer() = (uint32_t)field_data_value.to_integer();
|
*(uint32_t*)field_rw_address.to_integer() = (uint32_t)field_data_value.to_integer();
|
||||||
};
|
};
|
||||||
@ -618,8 +632,8 @@ bool DebugScreenTest::on_touch(const TouchEvent event) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void DebugScreenTest::paint(Painter& painter) {
|
void DebugScreenTest::paint(Painter& painter) {
|
||||||
painter.fill_rectangle({0, 16, screen_width, screen_height - 16}, Color::white());
|
painter.fill_rectangle({0, 16, screen_width, screen_height - 16}, Theme::getInstance()->bg_darkest->foreground);
|
||||||
painter.draw_string({10 * 8, screen_height / 2}, Styles::white, "Use Stylus");
|
painter.draw_string({10 * 8, screen_height / 2}, *Theme::getInstance()->bg_darkest, "Use Stylus");
|
||||||
pen_color = std::rand();
|
pen_color = std::rand();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -139,6 +139,7 @@ typedef enum {
|
|||||||
CT_MAX283X,
|
CT_MAX283X,
|
||||||
CT_SI5351,
|
CT_SI5351,
|
||||||
CT_AUDIO,
|
CT_AUDIO,
|
||||||
|
CT_BATTERY,
|
||||||
} chip_type_t;
|
} chip_type_t;
|
||||||
|
|
||||||
struct RegistersWidgetConfig {
|
struct RegistersWidgetConfig {
|
||||||
@ -233,8 +234,8 @@ class RegistersView : public View {
|
|||||||
"Write"};
|
"Write"};
|
||||||
|
|
||||||
Labels labels{
|
Labels labels{
|
||||||
{{1 * 8, 248}, "Reg:", Color::light_grey()},
|
{{1 * 8, 248}, "Reg:", Theme::getInstance()->fg_light->foreground},
|
||||||
{{8 * 8, 248}, "Data:", Color::light_grey()}};
|
{{8 * 8, 248}, "Data:", Theme::getInstance()->fg_light->foreground}};
|
||||||
|
|
||||||
SymField field_write_reg_num{
|
SymField field_write_reg_num{
|
||||||
{5 * 8, 248},
|
{5 * 8, 248},
|
||||||
@ -288,9 +289,9 @@ class DebugControlsView : public View {
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
Labels labels{
|
Labels labels{
|
||||||
{{8 * 8, 1 * 16}, "Controls State", Color::white()},
|
{{8 * 8, 1 * 16}, "Controls State", Theme::getInstance()->bg_darkest->foreground},
|
||||||
{{0 * 8, 11 * 16}, "Dial:", Color::grey()},
|
{{0 * 8, 11 * 16}, "Dial:", Theme::getInstance()->fg_medium->foreground},
|
||||||
{{0 * 8, 14 * 16}, "Long-Press Mode:", Color::grey()}};
|
{{0 * 8, 14 * 16}, "Long-Press Mode:", Theme::getInstance()->fg_medium->foreground}};
|
||||||
|
|
||||||
ControlsSwitchesWidget switches_widget{
|
ControlsSwitchesWidget switches_widget{
|
||||||
{80, 80, 80, 112},
|
{80, 80, 80, 112},
|
||||||
@ -333,12 +334,12 @@ class DebugMemoryDumpView : public View {
|
|||||||
"Done"};
|
"Done"};
|
||||||
|
|
||||||
Labels labels{
|
Labels labels{
|
||||||
{{5 * 8, 1 * 16}, "Dump Range to File", Color::yellow()},
|
{{5 * 8, 1 * 16}, "Dump Range to File", Theme::getInstance()->fg_yellow->foreground},
|
||||||
{{0 * 8, 2 * 16}, "Starting Address: 0x", Color::light_grey()},
|
{{0 * 8, 2 * 16}, "Starting Address: 0x", Theme::getInstance()->fg_light->foreground},
|
||||||
{{0 * 8, 3 * 16}, "Byte Count: 0x", Color::light_grey()},
|
{{0 * 8, 3 * 16}, "Byte Count: 0x", Theme::getInstance()->fg_light->foreground},
|
||||||
{{3 * 8, 8 * 16}, "Read/Write Single Word", Color::yellow()},
|
{{3 * 8, 8 * 16}, "Read/Write Single Word", Theme::getInstance()->fg_yellow->foreground},
|
||||||
{{0 * 8, 9 * 16}, "Memory Address: 0x", Color::light_grey()},
|
{{0 * 8, 9 * 16}, "Memory Address: 0x", Theme::getInstance()->fg_light->foreground},
|
||||||
{{0 * 8, 10 * 16}, "Data Value: 0x", Color::light_grey()}};
|
{{0 * 8, 10 * 16}, "Data Value: 0x", Theme::getInstance()->fg_light->foreground}};
|
||||||
|
|
||||||
SymField field_starting_address{
|
SymField field_starting_address{
|
||||||
{20 * 8, 2 * 16},
|
{20 * 8, 2 * 16},
|
||||||
|
104
firmware/application/apps/ui_debug_battery.cpp
Normal file
104
firmware/application/apps/ui_debug_battery.cpp
Normal file
@ -0,0 +1,104 @@
|
|||||||
|
#include "ui_debug_battery.hpp"
|
||||||
|
#include "string_format.hpp"
|
||||||
|
|
||||||
|
namespace ui {
|
||||||
|
|
||||||
|
BatteryCapacityView::RegisterEntry BatteryCapacityView::get_entry(size_t index) {
|
||||||
|
if (index < battery::max17055::MAX17055::entries_count) {
|
||||||
|
return battery::max17055::MAX17055::entries[index];
|
||||||
|
}
|
||||||
|
return {"", 0, "", 0, false, "", false, 0, false, false, false, 0, false};
|
||||||
|
}
|
||||||
|
|
||||||
|
BatteryCapacityView::BatteryCapacityView(NavigationView& nav) {
|
||||||
|
for (size_t i = 0; i < ENTRIES_PER_PAGE; ++i) {
|
||||||
|
name_texts[i].set_parent_rect({0 * 8, static_cast<int>((i + 1) * 16), 8 * 8, 16});
|
||||||
|
addr_texts[i].set_parent_rect({9 * 8, static_cast<int>((i + 1) * 16), 4 * 8, 16});
|
||||||
|
hex_texts[i].set_parent_rect({14 * 8, static_cast<int>((i + 1) * 16), 6 * 8, 16});
|
||||||
|
value_texts[i].set_parent_rect({21 * 8, static_cast<int>((i + 1) * 16), 10 * 8, 16});
|
||||||
|
|
||||||
|
add_child(&name_texts[i]);
|
||||||
|
add_child(&addr_texts[i]);
|
||||||
|
add_child(&hex_texts[i]);
|
||||||
|
add_child(&value_texts[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
add_children({&labels, &page_text, &button_done});
|
||||||
|
|
||||||
|
button_done.on_select = [&nav](Button&) { nav.pop(); };
|
||||||
|
|
||||||
|
populate_page(0);
|
||||||
|
update_page_text();
|
||||||
|
}
|
||||||
|
|
||||||
|
void BatteryCapacityView::focus() {
|
||||||
|
button_done.focus();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool BatteryCapacityView::on_encoder(const EncoderEvent delta) {
|
||||||
|
int32_t new_page = current_page + delta;
|
||||||
|
if (new_page >= 0 && new_page < ((int32_t)battery::max17055::MAX17055::entries_count + ENTRIES_PER_PAGE - 1) / ENTRIES_PER_PAGE) {
|
||||||
|
current_page = new_page;
|
||||||
|
populate_page(current_page * ENTRIES_PER_PAGE);
|
||||||
|
update_page_text();
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void BatteryCapacityView::update_values() {
|
||||||
|
for (size_t i = 0; i < ENTRIES_PER_PAGE; ++i) {
|
||||||
|
size_t entry_index = current_page * ENTRIES_PER_PAGE + i;
|
||||||
|
if (entry_index < battery::max17055::MAX17055::entries_count) {
|
||||||
|
const auto entry = get_entry(entry_index);
|
||||||
|
uint16_t raw_value = battery::BatteryManagement::read_register(entry.address);
|
||||||
|
|
||||||
|
hex_texts[i].set("0x" + to_string_hex(raw_value, 4));
|
||||||
|
|
||||||
|
float scaled_value;
|
||||||
|
if (entry.is_signed) {
|
||||||
|
int16_t signed_value = static_cast<int16_t>(raw_value);
|
||||||
|
scaled_value = signed_value * entry.scalar;
|
||||||
|
} else {
|
||||||
|
scaled_value = raw_value * entry.scalar;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Format the value with appropriate decimal places
|
||||||
|
std::string formatted_value;
|
||||||
|
if (entry.resolution > 0) {
|
||||||
|
formatted_value = to_string_decimal(scaled_value, std::min(entry.resolution, 3));
|
||||||
|
} else {
|
||||||
|
formatted_value = to_string_dec_int(scaled_value); // Show up to 3 decimal places
|
||||||
|
}
|
||||||
|
|
||||||
|
value_texts[i].set(formatted_value + " " + entry.unit);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void BatteryCapacityView::populate_page(int start_index) {
|
||||||
|
for (size_t i = 0; i < ENTRIES_PER_PAGE; ++i) {
|
||||||
|
size_t entry_index = start_index + i;
|
||||||
|
if (entry_index < battery::max17055::MAX17055::entries_count) {
|
||||||
|
const auto entry = get_entry(entry_index);
|
||||||
|
name_texts[i].set(entry.name);
|
||||||
|
addr_texts[i].set("0x" + to_string_hex(entry.address, 2));
|
||||||
|
name_texts[i].hidden(false);
|
||||||
|
addr_texts[i].hidden(false);
|
||||||
|
hex_texts[i].hidden(false);
|
||||||
|
value_texts[i].hidden(false);
|
||||||
|
} else {
|
||||||
|
name_texts[i].hidden(true);
|
||||||
|
addr_texts[i].hidden(true);
|
||||||
|
hex_texts[i].hidden(true);
|
||||||
|
value_texts[i].hidden(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
update_values();
|
||||||
|
}
|
||||||
|
|
||||||
|
void BatteryCapacityView::update_page_text() {
|
||||||
|
int total_pages = (battery::max17055::MAX17055::entries_count + ENTRIES_PER_PAGE - 1) / ENTRIES_PER_PAGE;
|
||||||
|
page_text.set("Page " + to_string_dec_uint(current_page + 1) + "/" + to_string_dec_uint(total_pages));
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace ui
|
48
firmware/application/apps/ui_debug_battery.hpp
Normal file
48
firmware/application/apps/ui_debug_battery.hpp
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
#ifndef __UI_DEBUG_BATTERY_HPP__
|
||||||
|
#define __UI_DEBUG_BATTERY_HPP__
|
||||||
|
|
||||||
|
#include "ui.hpp"
|
||||||
|
#include "ui_widget.hpp"
|
||||||
|
#include "ui_navigation.hpp"
|
||||||
|
#include "battery.hpp"
|
||||||
|
#include "max17055.hpp"
|
||||||
|
|
||||||
|
namespace ui {
|
||||||
|
|
||||||
|
class BatteryCapacityView : public View {
|
||||||
|
public:
|
||||||
|
BatteryCapacityView(NavigationView& nav);
|
||||||
|
void focus() override;
|
||||||
|
std::string title() const override { return "Battery Registers"; }
|
||||||
|
|
||||||
|
bool on_encoder(const EncoderEvent delta) override;
|
||||||
|
|
||||||
|
using RegisterEntry = battery::max17055::RegisterEntry;
|
||||||
|
|
||||||
|
private:
|
||||||
|
static RegisterEntry get_entry(size_t index);
|
||||||
|
|
||||||
|
Labels labels{
|
||||||
|
{{0 * 8, 0 * 16}, "Reg", Theme::getInstance()->fg_yellow->foreground},
|
||||||
|
{{9 * 8, 0 * 16}, "Addr", Theme::getInstance()->fg_yellow->foreground},
|
||||||
|
{{14 * 8, 0 * 16}, "Hex", Theme::getInstance()->fg_yellow->foreground},
|
||||||
|
{{21 * 8, 0 * 16}, "Value", Theme::getInstance()->fg_yellow->foreground},
|
||||||
|
};
|
||||||
|
std::array<Text, 16> name_texts = {};
|
||||||
|
std::array<Text, 16> addr_texts = {};
|
||||||
|
std::array<Text, 16> hex_texts = {};
|
||||||
|
std::array<Text, 16> value_texts = {};
|
||||||
|
|
||||||
|
Text page_text{{144, 284, 80, 16}, "Page 1/1"};
|
||||||
|
Button button_done{{16, 280, 96, 24}, "Done"};
|
||||||
|
|
||||||
|
void update_values();
|
||||||
|
void populate_page(int start_index);
|
||||||
|
void update_page_text();
|
||||||
|
int current_page = 0;
|
||||||
|
static constexpr int ENTRIES_PER_PAGE = 16;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace ui
|
||||||
|
|
||||||
|
#endif // __UI_DEBUG_BATTERY_HPP__
|
@ -41,6 +41,11 @@ DfuMenu::DfuMenu(NavigationView& nav)
|
|||||||
&text_info_line_8,
|
&text_info_line_8,
|
||||||
&text_info_line_9,
|
&text_info_line_9,
|
||||||
&text_info_line_10});
|
&text_info_line_10});
|
||||||
|
|
||||||
|
if (battery::BatteryManagement::isDetected()) {
|
||||||
|
add_child(&voltage_label);
|
||||||
|
add_child(&text_info_line_11);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void DfuMenu::paint(Painter& painter) {
|
void DfuMenu::paint(Painter& painter) {
|
||||||
@ -48,6 +53,8 @@ void DfuMenu::paint(Painter& painter) {
|
|||||||
size_t m0_fragmented_free_space = 0;
|
size_t m0_fragmented_free_space = 0;
|
||||||
const auto m0_fragments = chHeapStatus(NULL, &m0_fragmented_free_space);
|
const auto m0_fragments = chHeapStatus(NULL, &m0_fragmented_free_space);
|
||||||
|
|
||||||
|
auto lines = (battery::BatteryManagement::isDetected() ? 11 : 10) + 2;
|
||||||
|
|
||||||
text_info_line_1.set(to_string_dec_uint(chCoreStatus(), 6));
|
text_info_line_1.set(to_string_dec_uint(chCoreStatus(), 6));
|
||||||
text_info_line_2.set(to_string_dec_uint(m0_fragmented_free_space, 6));
|
text_info_line_2.set(to_string_dec_uint(m0_fragmented_free_space, 6));
|
||||||
text_info_line_3.set(to_string_dec_uint(m0_fragments, 6));
|
text_info_line_3.set(to_string_dec_uint(m0_fragments, 6));
|
||||||
@ -58,34 +65,36 @@ void DfuMenu::paint(Painter& painter) {
|
|||||||
text_info_line_8.set(to_string_dec_uint(shared_memory.m4_performance_counter, 6));
|
text_info_line_8.set(to_string_dec_uint(shared_memory.m4_performance_counter, 6));
|
||||||
text_info_line_9.set(to_string_dec_uint(shared_memory.m4_buffer_missed, 6));
|
text_info_line_9.set(to_string_dec_uint(shared_memory.m4_buffer_missed, 6));
|
||||||
text_info_line_10.set(to_string_dec_uint(chTimeNow() / 1000, 6));
|
text_info_line_10.set(to_string_dec_uint(chTimeNow() / 1000, 6));
|
||||||
|
if (battery::BatteryManagement::isDetected()) {
|
||||||
|
text_info_line_11.set(to_string_decimal_padding((float)battery::BatteryManagement::getVoltage() / 1000.0, 3, 6));
|
||||||
|
}
|
||||||
|
|
||||||
constexpr auto margin = 5;
|
constexpr auto margin = 5;
|
||||||
constexpr auto lines = 10 + 2;
|
|
||||||
|
|
||||||
painter.fill_rectangle(
|
painter.fill_rectangle(
|
||||||
{{6 * CHARACTER_WIDTH - margin, 3 * LINE_HEIGHT - margin},
|
{{6 * CHARACTER_WIDTH - margin, 3 * LINE_HEIGHT - margin},
|
||||||
{15 * CHARACTER_WIDTH + margin * 2, lines * LINE_HEIGHT + margin * 2}},
|
{15 * CHARACTER_WIDTH + margin * 2, lines * LINE_HEIGHT + margin * 2}},
|
||||||
ui::Color::black());
|
Theme::getInstance()->bg_darkest->background);
|
||||||
|
|
||||||
painter.fill_rectangle(
|
painter.fill_rectangle(
|
||||||
{{5 * CHARACTER_WIDTH - margin, 3 * LINE_HEIGHT - margin},
|
{{5 * CHARACTER_WIDTH - margin, 3 * LINE_HEIGHT - margin},
|
||||||
{CHARACTER_WIDTH, lines * LINE_HEIGHT + margin * 2}},
|
{CHARACTER_WIDTH, lines * LINE_HEIGHT + margin * 2}},
|
||||||
ui::Color::dark_cyan());
|
ui::Theme::getInstance()->fg_darkcyan->foreground);
|
||||||
|
|
||||||
painter.fill_rectangle(
|
painter.fill_rectangle(
|
||||||
{{21 * CHARACTER_WIDTH + margin, 3 * LINE_HEIGHT - margin},
|
{{21 * CHARACTER_WIDTH + margin, 3 * LINE_HEIGHT - margin},
|
||||||
{CHARACTER_WIDTH, lines * LINE_HEIGHT + margin * 2}},
|
{CHARACTER_WIDTH, lines * LINE_HEIGHT + margin * 2}},
|
||||||
ui::Color::dark_cyan());
|
ui::Theme::getInstance()->fg_darkcyan->foreground);
|
||||||
|
|
||||||
painter.fill_rectangle(
|
painter.fill_rectangle(
|
||||||
{{5 * CHARACTER_WIDTH - margin, 3 * LINE_HEIGHT - margin - 8},
|
{{5 * CHARACTER_WIDTH - margin, 3 * LINE_HEIGHT - margin - 8},
|
||||||
{17 * CHARACTER_WIDTH + margin * 2, 8}},
|
{17 * CHARACTER_WIDTH + margin * 2, 8}},
|
||||||
ui::Color::dark_cyan());
|
ui::Theme::getInstance()->fg_darkcyan->foreground);
|
||||||
|
|
||||||
painter.fill_rectangle(
|
painter.fill_rectangle(
|
||||||
{{5 * CHARACTER_WIDTH - margin, (lines + 3) * LINE_HEIGHT + margin},
|
{{5 * CHARACTER_WIDTH - margin, (lines + 3) * LINE_HEIGHT + margin},
|
||||||
{17 * CHARACTER_WIDTH + margin * 2, 8}},
|
{17 * CHARACTER_WIDTH + margin * 2, 8}},
|
||||||
ui::Color::dark_cyan());
|
ui::Theme::getInstance()->fg_darkcyan->foreground);
|
||||||
}
|
}
|
||||||
|
|
||||||
DfuMenu2::DfuMenu2(NavigationView& nav)
|
DfuMenu2::DfuMenu2(NavigationView& nav)
|
||||||
@ -124,27 +133,27 @@ void DfuMenu2::paint(Painter& painter) {
|
|||||||
painter.fill_rectangle(
|
painter.fill_rectangle(
|
||||||
{{5 * CHARACTER_WIDTH - margin, 3 * LINE_HEIGHT - margin},
|
{{5 * CHARACTER_WIDTH - margin, 3 * LINE_HEIGHT - margin},
|
||||||
{19 * CHARACTER_WIDTH + margin * 2, lines * LINE_HEIGHT + margin * 2}},
|
{19 * CHARACTER_WIDTH + margin * 2, lines * LINE_HEIGHT + margin * 2}},
|
||||||
ui::Color::black());
|
Theme::getInstance()->bg_darkest->background);
|
||||||
|
|
||||||
painter.fill_rectangle(
|
painter.fill_rectangle(
|
||||||
{{4 * CHARACTER_WIDTH - margin, 3 * LINE_HEIGHT - margin},
|
{{4 * CHARACTER_WIDTH - margin, 3 * LINE_HEIGHT - margin},
|
||||||
{CHARACTER_WIDTH, lines * LINE_HEIGHT + margin * 2}},
|
{CHARACTER_WIDTH, lines * LINE_HEIGHT + margin * 2}},
|
||||||
ui::Color::dark_cyan());
|
ui::Theme::getInstance()->fg_darkcyan->foreground);
|
||||||
|
|
||||||
painter.fill_rectangle(
|
painter.fill_rectangle(
|
||||||
{{24 * CHARACTER_WIDTH + margin, 3 * LINE_HEIGHT - margin},
|
{{24 * CHARACTER_WIDTH + margin, 3 * LINE_HEIGHT - margin},
|
||||||
{CHARACTER_WIDTH, lines * LINE_HEIGHT + margin * 2}},
|
{CHARACTER_WIDTH, lines * LINE_HEIGHT + margin * 2}},
|
||||||
ui::Color::dark_cyan());
|
ui::Theme::getInstance()->fg_darkcyan->foreground);
|
||||||
|
|
||||||
painter.fill_rectangle(
|
painter.fill_rectangle(
|
||||||
{{4 * CHARACTER_WIDTH - margin, 3 * LINE_HEIGHT - margin - 8},
|
{{4 * CHARACTER_WIDTH - margin, 3 * LINE_HEIGHT - margin - 8},
|
||||||
{21 * CHARACTER_WIDTH + margin * 2, 8}},
|
{21 * CHARACTER_WIDTH + margin * 2, 8}},
|
||||||
ui::Color::dark_cyan());
|
ui::Theme::getInstance()->fg_darkcyan->foreground);
|
||||||
|
|
||||||
painter.fill_rectangle(
|
painter.fill_rectangle(
|
||||||
{{4 * CHARACTER_WIDTH - margin, (lines + 3) * LINE_HEIGHT + margin},
|
{{4 * CHARACTER_WIDTH - margin, (lines + 3) * LINE_HEIGHT + margin},
|
||||||
{21 * CHARACTER_WIDTH + margin * 2, 8}},
|
{21 * CHARACTER_WIDTH + margin * 2, 8}},
|
||||||
ui::Color::dark_cyan());
|
ui::Theme::getInstance()->fg_darkcyan->foreground);
|
||||||
}
|
}
|
||||||
|
|
||||||
} /* namespace ui */
|
} /* namespace ui */
|
||||||
|
@ -49,16 +49,18 @@ class DfuMenu : public View {
|
|||||||
Text text_head{{6 * CHARACTER_WIDTH, 3 * LINE_HEIGHT, 11 * CHARACTER_WIDTH, 1 * LINE_HEIGHT}, "Performance"};
|
Text text_head{{6 * CHARACTER_WIDTH, 3 * LINE_HEIGHT, 11 * CHARACTER_WIDTH, 1 * LINE_HEIGHT}, "Performance"};
|
||||||
|
|
||||||
Labels labels{
|
Labels labels{
|
||||||
{{6 * CHARACTER_WIDTH, 5 * LINE_HEIGHT}, "M0 core:", Color::dark_cyan()},
|
{{6 * CHARACTER_WIDTH, 5 * LINE_HEIGHT}, "M0 core:", Theme::getInstance()->fg_darkcyan->foreground},
|
||||||
{{6 * CHARACTER_WIDTH, 6 * LINE_HEIGHT}, "M0 heap:", Color::dark_cyan()},
|
{{6 * CHARACTER_WIDTH, 6 * LINE_HEIGHT}, "M0 heap:", Theme::getInstance()->fg_darkcyan->foreground},
|
||||||
{{6 * CHARACTER_WIDTH, 7 * LINE_HEIGHT}, "M0 frags:", Color::dark_cyan()},
|
{{6 * CHARACTER_WIDTH, 7 * LINE_HEIGHT}, "M0 frags:", Theme::getInstance()->fg_darkcyan->foreground},
|
||||||
{{6 * CHARACTER_WIDTH, 8 * LINE_HEIGHT}, "M0 stack:", Color::dark_cyan()},
|
{{6 * CHARACTER_WIDTH, 8 * LINE_HEIGHT}, "M0 stack:", Theme::getInstance()->fg_darkcyan->foreground},
|
||||||
{{6 * CHARACTER_WIDTH, 9 * LINE_HEIGHT}, "M0 cpu %:", Color::dark_cyan()},
|
{{6 * CHARACTER_WIDTH, 9 * LINE_HEIGHT}, "M0 cpu %:", Theme::getInstance()->fg_darkcyan->foreground},
|
||||||
{{6 * CHARACTER_WIDTH, 10 * LINE_HEIGHT}, "M4 heap:", Color::dark_cyan()},
|
{{6 * CHARACTER_WIDTH, 10 * LINE_HEIGHT}, "M4 heap:", Theme::getInstance()->fg_darkcyan->foreground},
|
||||||
{{6 * CHARACTER_WIDTH, 11 * LINE_HEIGHT}, "M4 stack:", Color::dark_cyan()},
|
{{6 * CHARACTER_WIDTH, 11 * LINE_HEIGHT}, "M4 stack:", Theme::getInstance()->fg_darkcyan->foreground},
|
||||||
{{6 * CHARACTER_WIDTH, 12 * LINE_HEIGHT}, "M4 cpu %:", Color::dark_cyan()},
|
{{6 * CHARACTER_WIDTH, 12 * LINE_HEIGHT}, "M4 cpu %:", Theme::getInstance()->fg_darkcyan->foreground},
|
||||||
{{6 * CHARACTER_WIDTH, 13 * LINE_HEIGHT}, "M4 miss:", Color::dark_cyan()},
|
{{6 * CHARACTER_WIDTH, 13 * LINE_HEIGHT}, "M4 miss:", Theme::getInstance()->fg_darkcyan->foreground},
|
||||||
{{6 * CHARACTER_WIDTH, 14 * LINE_HEIGHT}, "uptime:", Color::dark_cyan()}};
|
{{6 * CHARACTER_WIDTH, 14 * LINE_HEIGHT}, "Uptime:", Theme::getInstance()->fg_darkcyan->foreground}};
|
||||||
|
|
||||||
|
Labels voltage_label{{{6 * CHARACTER_WIDTH, 15 * LINE_HEIGHT}, "Voltage:", Theme::getInstance()->fg_darkcyan->foreground}};
|
||||||
|
|
||||||
Text text_info_line_1{{15 * CHARACTER_WIDTH, 5 * LINE_HEIGHT, 6 * CHARACTER_WIDTH, 1 * LINE_HEIGHT}, ""};
|
Text text_info_line_1{{15 * CHARACTER_WIDTH, 5 * LINE_HEIGHT, 6 * CHARACTER_WIDTH, 1 * LINE_HEIGHT}, ""};
|
||||||
Text text_info_line_2{{15 * CHARACTER_WIDTH, 6 * LINE_HEIGHT, 6 * CHARACTER_WIDTH, 1 * LINE_HEIGHT}, ""};
|
Text text_info_line_2{{15 * CHARACTER_WIDTH, 6 * LINE_HEIGHT, 6 * CHARACTER_WIDTH, 1 * LINE_HEIGHT}, ""};
|
||||||
@ -70,6 +72,7 @@ class DfuMenu : public View {
|
|||||||
Text text_info_line_8{{15 * CHARACTER_WIDTH, 12 * LINE_HEIGHT, 6 * CHARACTER_WIDTH, 1 * LINE_HEIGHT}, ""};
|
Text text_info_line_8{{15 * CHARACTER_WIDTH, 12 * LINE_HEIGHT, 6 * CHARACTER_WIDTH, 1 * LINE_HEIGHT}, ""};
|
||||||
Text text_info_line_9{{15 * CHARACTER_WIDTH, 13 * LINE_HEIGHT, 6 * CHARACTER_WIDTH, 1 * LINE_HEIGHT}, ""};
|
Text text_info_line_9{{15 * CHARACTER_WIDTH, 13 * LINE_HEIGHT, 6 * CHARACTER_WIDTH, 1 * LINE_HEIGHT}, ""};
|
||||||
Text text_info_line_10{{15 * CHARACTER_WIDTH, 14 * LINE_HEIGHT, 6 * CHARACTER_WIDTH, 1 * LINE_HEIGHT}, ""};
|
Text text_info_line_10{{15 * CHARACTER_WIDTH, 14 * LINE_HEIGHT, 6 * CHARACTER_WIDTH, 1 * LINE_HEIGHT}, ""};
|
||||||
|
Text text_info_line_11{{15 * CHARACTER_WIDTH, 15 * LINE_HEIGHT, 6 * CHARACTER_WIDTH, 1 * LINE_HEIGHT}, ""};
|
||||||
};
|
};
|
||||||
|
|
||||||
class DfuMenu2 : public View {
|
class DfuMenu2 : public View {
|
||||||
@ -85,17 +88,17 @@ class DfuMenu2 : public View {
|
|||||||
Text text_head{{6 * CHARACTER_WIDTH, 3 * LINE_HEIGHT, 14 * CHARACTER_WIDTH, 1 * LINE_HEIGHT}, "Radio Settings"};
|
Text text_head{{6 * CHARACTER_WIDTH, 3 * LINE_HEIGHT, 14 * CHARACTER_WIDTH, 1 * LINE_HEIGHT}, "Radio Settings"};
|
||||||
|
|
||||||
Labels labels{
|
Labels labels{
|
||||||
{{5 * CHARACTER_WIDTH, 5 * LINE_HEIGHT}, "RX Freq:", Color::dark_cyan()},
|
{{5 * CHARACTER_WIDTH, 5 * LINE_HEIGHT}, "RX Freq:", Theme::getInstance()->fg_darkcyan->foreground},
|
||||||
{{5 * CHARACTER_WIDTH, 6 * LINE_HEIGHT}, "RX BW:", Color::dark_cyan()},
|
{{5 * CHARACTER_WIDTH, 6 * LINE_HEIGHT}, "RX BW:", Theme::getInstance()->fg_darkcyan->foreground},
|
||||||
{{5 * CHARACTER_WIDTH, 7 * LINE_HEIGHT}, "RX SampR:", Color::dark_cyan()},
|
{{5 * CHARACTER_WIDTH, 7 * LINE_HEIGHT}, "RX SampR:", Theme::getInstance()->fg_darkcyan->foreground},
|
||||||
{{5 * CHARACTER_WIDTH, 8 * LINE_HEIGHT}, "RX Satu%:", Color::dark_cyan()},
|
{{5 * CHARACTER_WIDTH, 8 * LINE_HEIGHT}, "RX Satu%:", Theme::getInstance()->fg_darkcyan->foreground},
|
||||||
{{5 * CHARACTER_WIDTH, 9 * LINE_HEIGHT}, "Modulatn:", Color::dark_cyan()},
|
{{5 * CHARACTER_WIDTH, 9 * LINE_HEIGHT}, "Modulatn:", Theme::getInstance()->fg_darkcyan->foreground},
|
||||||
{{5 * CHARACTER_WIDTH, 10 * LINE_HEIGHT}, "AM cfg:", Color::dark_cyan()},
|
{{5 * CHARACTER_WIDTH, 10 * LINE_HEIGHT}, "AM cfg:", Theme::getInstance()->fg_darkcyan->foreground},
|
||||||
{{5 * CHARACTER_WIDTH, 11 * LINE_HEIGHT}, "NBFM cfg:", Color::dark_cyan()},
|
{{5 * CHARACTER_WIDTH, 11 * LINE_HEIGHT}, "NBFM cfg:", Theme::getInstance()->fg_darkcyan->foreground},
|
||||||
{{5 * CHARACTER_WIDTH, 12 * LINE_HEIGHT}, "WFM cfg:", Color::dark_cyan()},
|
{{5 * CHARACTER_WIDTH, 12 * LINE_HEIGHT}, "WFM cfg:", Theme::getInstance()->fg_darkcyan->foreground},
|
||||||
{{5 * CHARACTER_WIDTH, 13 * LINE_HEIGHT}, "TX Freq:", Color::dark_cyan()},
|
{{5 * CHARACTER_WIDTH, 13 * LINE_HEIGHT}, "TX Freq:", Theme::getInstance()->fg_darkcyan->foreground},
|
||||||
{{5 * CHARACTER_WIDTH, 14 * LINE_HEIGHT}, "TX BW:", Color::dark_cyan()},
|
{{5 * CHARACTER_WIDTH, 14 * LINE_HEIGHT}, "TX BW:", Theme::getInstance()->fg_darkcyan->foreground},
|
||||||
{{5 * CHARACTER_WIDTH, 15 * LINE_HEIGHT}, "TX SampR:", Color::dark_cyan()},
|
{{5 * CHARACTER_WIDTH, 15 * LINE_HEIGHT}, "TX SampR:", Theme::getInstance()->fg_darkcyan->foreground},
|
||||||
};
|
};
|
||||||
|
|
||||||
Text text_info_line_1{{14 * CHARACTER_WIDTH, 5 * LINE_HEIGHT, 10 * CHARACTER_WIDTH, 1 * LINE_HEIGHT}, ""};
|
Text text_info_line_1{{14 * CHARACTER_WIDTH, 5 * LINE_HEIGHT, 10 * CHARACTER_WIDTH, 1 * LINE_HEIGHT}, ""};
|
||||||
|
@ -64,16 +64,16 @@ class EncodersConfigView : public View {
|
|||||||
void on_type_change(size_t index);
|
void on_type_change(size_t index);
|
||||||
|
|
||||||
Labels labels{
|
Labels labels{
|
||||||
{{1 * 8, 0}, "Type:", Color::light_grey()},
|
{{1 * 8, 0}, "Type:", Theme::getInstance()->fg_light->foreground},
|
||||||
{{17 * 8, 0}, "Repeat:", Color::light_grey()},
|
{{17 * 8, 0}, "Repeat:", Theme::getInstance()->fg_light->foreground},
|
||||||
{{1 * 8, 2 * 8}, "Clk:", Color::light_grey()},
|
{{1 * 8, 2 * 8}, "Clk:", Theme::getInstance()->fg_light->foreground},
|
||||||
{{10 * 8, 2 * 8}, "kHz", Color::light_grey()},
|
{{10 * 8, 2 * 8}, "kHz", Theme::getInstance()->fg_light->foreground},
|
||||||
{{17 * 8, 2 * 8}, "Step:", Color::light_grey()},
|
{{17 * 8, 2 * 8}, "Step:", Theme::getInstance()->fg_light->foreground},
|
||||||
{{1 * 8, 4 * 8}, "Frame:", Color::light_grey()},
|
{{1 * 8, 4 * 8}, "Frame:", Theme::getInstance()->fg_light->foreground},
|
||||||
{{13 * 8, 4 * 8}, "us", Color::light_grey()},
|
{{13 * 8, 4 * 8}, "us", Theme::getInstance()->fg_light->foreground},
|
||||||
{{17 * 8, 4 * 8}, "Step:", Color::light_grey()},
|
{{17 * 8, 4 * 8}, "Step:", Theme::getInstance()->fg_light->foreground},
|
||||||
{{2 * 8, 7 * 8}, "Symbols:", Color::light_grey()},
|
{{2 * 8, 7 * 8}, "Symbols:", Theme::getInstance()->fg_light->foreground},
|
||||||
{{1 * 8, 14 * 8}, "Waveform:", Color::light_grey()}};
|
{{1 * 8, 14 * 8}, "Waveform:", Theme::getInstance()->fg_light->foreground}};
|
||||||
|
|
||||||
OptionsField options_enctype{// Options are loaded at runtime
|
OptionsField options_enctype{// Options are loaded at runtime
|
||||||
{6 * 8, 0},
|
{6 * 8, 0},
|
||||||
@ -128,7 +128,7 @@ class EncodersConfigView : public View {
|
|||||||
0,
|
0,
|
||||||
0,
|
0,
|
||||||
true,
|
true,
|
||||||
Color::yellow()};
|
Theme::getInstance()->fg_yellow->foreground};
|
||||||
};
|
};
|
||||||
|
|
||||||
class EncodersScanView : public View {
|
class EncodersScanView : public View {
|
||||||
@ -160,9 +160,9 @@ class EncodersScanView : public View {
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
Labels labels{
|
Labels labels{
|
||||||
{{1 * 8, 0 * 8}, "Length:", Color::light_grey()},
|
{{1 * 8, 0 * 8}, "Length:", Theme::getInstance()->fg_light->foreground},
|
||||||
{{1 * 8, 2 * 8}, "Bit length:", Color::light_grey()},
|
{{1 * 8, 2 * 8}, "Bit length:", Theme::getInstance()->fg_light->foreground},
|
||||||
{{16 * 8, 2 * 8}, "us", Color::light_grey()},
|
{{16 * 8, 2 * 8}, "us", Theme::getInstance()->fg_light->foreground},
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -206,8 +206,8 @@ class EncodersView : public View {
|
|||||||
EncodersScanView view_scan{nav_, view_rect};
|
EncodersScanView view_scan{nav_, view_rect};
|
||||||
|
|
||||||
TabView tab_view{
|
TabView tab_view{
|
||||||
{"Config", Color::cyan(), &view_config},
|
{"Config", Theme::getInstance()->fg_cyan->foreground, &view_config},
|
||||||
{"de Bruijn", Color::green(), &view_scan},
|
{"de Bruijn", Theme::getInstance()->fg_green->foreground, &view_scan},
|
||||||
};
|
};
|
||||||
|
|
||||||
Text text_status{
|
Text text_status{
|
||||||
|
@ -29,11 +29,13 @@
|
|||||||
#include "ui_playlist.hpp"
|
#include "ui_playlist.hpp"
|
||||||
#include "ui_remote.hpp"
|
#include "ui_remote.hpp"
|
||||||
#include "ui_ss_viewer.hpp"
|
#include "ui_ss_viewer.hpp"
|
||||||
|
#include "ui_bmp_file_viewer.hpp"
|
||||||
#include "ui_text_editor.hpp"
|
#include "ui_text_editor.hpp"
|
||||||
#include "ui_iq_trim.hpp"
|
#include "ui_iq_trim.hpp"
|
||||||
#include "string_format.hpp"
|
#include "string_format.hpp"
|
||||||
#include "portapack.hpp"
|
#include "portapack.hpp"
|
||||||
#include "event_m0.hpp"
|
#include "event_m0.hpp"
|
||||||
|
#include "file_path.hpp"
|
||||||
|
|
||||||
using namespace portapack;
|
using namespace portapack;
|
||||||
namespace fs = std::filesystem;
|
namespace fs = std::filesystem;
|
||||||
@ -387,7 +389,7 @@ void FileManBaseView::refresh_list() {
|
|||||||
|
|
||||||
menu_view.add_item(
|
menu_view.add_item(
|
||||||
{entry_name.substr(0, max_filename_length) + std::string(21 - entry_name.length(), ' ') + size_str,
|
{entry_name.substr(0, max_filename_length) + std::string(21 - entry_name.length(), ' ') + size_str,
|
||||||
ui::Color::yellow(),
|
Theme::getInstance()->fg_yellow->foreground,
|
||||||
&bitmap_icon_dir,
|
&bitmap_icon_dir,
|
||||||
[this](KeyEvent key) {
|
[this](KeyEvent key) {
|
||||||
if (on_select_entry)
|
if (on_select_entry)
|
||||||
@ -694,7 +696,12 @@ bool FileManagerView::handle_file_open() {
|
|||||||
nav_.push<ScreenshotViewer>(path);
|
nav_.push<ScreenshotViewer>(path);
|
||||||
return true;
|
return true;
|
||||||
} else if (path_iequal(bmp_ext, ext)) {
|
} else if (path_iequal(bmp_ext, ext)) {
|
||||||
nav_.push<SplashViewer>(path);
|
if (path_iequal(current_path, u"/" + splash_dir)) {
|
||||||
|
nav_.push<SplashViewer>(path); // splash, so load that viewer
|
||||||
|
} else {
|
||||||
|
nav_.push<BMPFileViewer>(path); // any other bmp
|
||||||
|
}
|
||||||
|
|
||||||
reload_current(false);
|
reload_current(false);
|
||||||
return true;
|
return true;
|
||||||
} else if (path_iequal(rem_ext, ext)) {
|
} else if (path_iequal(rem_ext, ext)) {
|
||||||
@ -740,10 +747,10 @@ FileManagerView::FileManagerView(
|
|||||||
|
|
||||||
menu_view.on_highlight = [this]() {
|
menu_view.on_highlight = [this]() {
|
||||||
if (menu_view.highlighted_index() >= max_items_loaded - 1) { // todo check this if correct
|
if (menu_view.highlighted_index() >= max_items_loaded - 1) { // todo check this if correct
|
||||||
text_date.set_style(&Styles::red);
|
text_date.set_style(Theme::getInstance()->fg_red);
|
||||||
text_date.set("Too many files!");
|
text_date.set("Too many files!");
|
||||||
} else {
|
} else {
|
||||||
text_date.set_style(&Styles::grey);
|
text_date.set_style(Theme::getInstance()->fg_medium);
|
||||||
if (selected_is_valid())
|
if (selected_is_valid())
|
||||||
text_date.set((is_directory(get_selected_full_path()) ? "Created " : "Modified ") + to_string_FAT_timestamp(file_created_date(get_selected_full_path())));
|
text_date.set((is_directory(get_selected_full_path()) ? "Created " : "Modified ") + to_string_FAT_timestamp(file_created_date(get_selected_full_path())));
|
||||||
else
|
else
|
||||||
@ -851,7 +858,7 @@ FileManagerView::FileManagerView(
|
|||||||
|
|
||||||
button_show_hidden_files.on_select = [this]() {
|
button_show_hidden_files.on_select = [this]() {
|
||||||
show_hidden_files = !show_hidden_files;
|
show_hidden_files = !show_hidden_files;
|
||||||
button_show_hidden_files.set_color(show_hidden_files ? Color::green() : Color::dark_grey());
|
button_show_hidden_files.set_color(show_hidden_files ? *Theme::getInstance()->status_active : Theme::getInstance()->bg_dark->background);
|
||||||
reload_current();
|
reload_current();
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -83,7 +83,7 @@ class FileManBaseView : public View {
|
|||||||
{u".WAV", &bitmap_icon_file_wav, ui::Color::dark_magenta()},
|
{u".WAV", &bitmap_icon_file_wav, ui::Color::dark_magenta()},
|
||||||
{u".PPL", &bitmap_icon_file_iq, ui::Color::white()}, // Playlist/Replay
|
{u".PPL", &bitmap_icon_file_iq, ui::Color::white()}, // Playlist/Replay
|
||||||
{u".REM", &bitmap_icon_remote, ui::Color::orange()}, // Remote
|
{u".REM", &bitmap_icon_remote, ui::Color::orange()}, // Remote
|
||||||
{u"", &bitmap_icon_file, ui::Color::light_grey()} // NB: Must be last.
|
{u"", &bitmap_icon_file, Theme::getInstance()->fg_light->foreground} // NB: Must be last.
|
||||||
};
|
};
|
||||||
|
|
||||||
std::filesystem::path get_selected_full_path() const;
|
std::filesystem::path get_selected_full_path() const;
|
||||||
@ -116,7 +116,7 @@ class FileManBaseView : public View {
|
|||||||
bool show_hidden_files{false};
|
bool show_hidden_files{false};
|
||||||
|
|
||||||
Labels labels{
|
Labels labels{
|
||||||
{{0, 0}, "Path:", Color::light_grey()}};
|
{{0, 0}, "Path:", Theme::getInstance()->fg_light->foreground}};
|
||||||
|
|
||||||
Text text_current{
|
Text text_current{
|
||||||
{6 * 8, 0 * 8, 24 * 8, 16},
|
{6 * 8, 0 * 8, 24 * 8, 16},
|
||||||
@ -166,8 +166,8 @@ private:
|
|||||||
std::string buffer_ { };
|
std::string buffer_ { };
|
||||||
|
|
||||||
Labels labels {
|
Labels labels {
|
||||||
{ { 0 * 8, 1 * 16 }, "Path:", Color::light_grey() },
|
{ { 0 * 8, 1 * 16 }, "Path:", Theme::getInstance()->fg_light->foreground },
|
||||||
{ { 0 * 8, 6 * 16 }, "Filename:", Color::light_grey() },
|
{ { 0 * 8, 6 * 16 }, "Filename:",Theme::getInstance()->fg_light->foreground },
|
||||||
};
|
};
|
||||||
|
|
||||||
Text text_path {
|
Text text_path {
|
||||||
@ -234,62 +234,62 @@ class FileManagerView : public FileManBaseView {
|
|||||||
{0 * 8, 29 * 8, 4 * 8, 32},
|
{0 * 8, 29 * 8, 4 * 8, 32},
|
||||||
{},
|
{},
|
||||||
&bitmap_icon_rename,
|
&bitmap_icon_rename,
|
||||||
Color::dark_blue()};
|
Theme::getInstance()->fg_blue->foreground};
|
||||||
|
|
||||||
NewButton button_delete{
|
NewButton button_delete{
|
||||||
{9 * 8, 34 * 8, 4 * 8, 32},
|
{9 * 8, 34 * 8, 4 * 8, 32},
|
||||||
{},
|
{},
|
||||||
&bitmap_icon_trash,
|
&bitmap_icon_trash,
|
||||||
Color::red()};
|
Theme::getInstance()->fg_red->foreground};
|
||||||
|
|
||||||
NewButton button_clean{
|
NewButton button_clean{
|
||||||
{13 * 8, 34 * 8, 4 * 8, 32},
|
{13 * 8, 34 * 8, 4 * 8, 32},
|
||||||
{},
|
{},
|
||||||
&bitmap_icon_clean,
|
&bitmap_icon_clean,
|
||||||
Color::red()};
|
Theme::getInstance()->fg_red->foreground};
|
||||||
|
|
||||||
NewButton button_cut{
|
NewButton button_cut{
|
||||||
{9 * 8, 29 * 8, 4 * 8, 32},
|
{9 * 8, 29 * 8, 4 * 8, 32},
|
||||||
{},
|
{},
|
||||||
&bitmap_icon_cut,
|
&bitmap_icon_cut,
|
||||||
Color::dark_grey()};
|
Theme::getInstance()->fg_dark->foreground};
|
||||||
|
|
||||||
NewButton button_copy{
|
NewButton button_copy{
|
||||||
{13 * 8, 29 * 8, 4 * 8, 32},
|
{13 * 8, 29 * 8, 4 * 8, 32},
|
||||||
{},
|
{},
|
||||||
&bitmap_icon_copy,
|
&bitmap_icon_copy,
|
||||||
Color::dark_grey()};
|
Theme::getInstance()->fg_dark->foreground};
|
||||||
|
|
||||||
NewButton button_paste{
|
NewButton button_paste{
|
||||||
{17 * 8, 29 * 8, 4 * 8, 32},
|
{17 * 8, 29 * 8, 4 * 8, 32},
|
||||||
{},
|
{},
|
||||||
&bitmap_icon_paste,
|
&bitmap_icon_paste,
|
||||||
Color::dark_grey()};
|
Theme::getInstance()->fg_dark->foreground};
|
||||||
|
|
||||||
NewButton button_new_dir{
|
NewButton button_new_dir{
|
||||||
{22 * 8, 29 * 8, 4 * 8, 32},
|
{22 * 8, 29 * 8, 4 * 8, 32},
|
||||||
{},
|
{},
|
||||||
&bitmap_icon_new_dir,
|
&bitmap_icon_new_dir,
|
||||||
Color::green()};
|
Theme::getInstance()->fg_green->foreground};
|
||||||
|
|
||||||
NewButton button_new_file{
|
NewButton button_new_file{
|
||||||
{26 * 8, 29 * 8, 4 * 8, 32},
|
{26 * 8, 29 * 8, 4 * 8, 32},
|
||||||
{},
|
{},
|
||||||
&bitmap_icon_new_file,
|
&bitmap_icon_new_file,
|
||||||
Color::green()};
|
Theme::getInstance()->fg_green->foreground};
|
||||||
|
|
||||||
NewButton button_open_notepad{
|
NewButton button_open_notepad{
|
||||||
{0 * 8, 34 * 8, 4 * 8, 32},
|
{0 * 8, 34 * 8, 4 * 8, 32},
|
||||||
{},
|
{},
|
||||||
&bitmap_icon_notepad,
|
&bitmap_icon_notepad,
|
||||||
Color::orange()};
|
Theme::getInstance()->fg_orange->foreground};
|
||||||
|
|
||||||
NewButton button_rename_timestamp{
|
NewButton button_rename_timestamp{
|
||||||
|
|
||||||
{4 * 8, 29 * 8, 4 * 8, 32},
|
{4 * 8, 29 * 8, 4 * 8, 32},
|
||||||
{},
|
{},
|
||||||
&bitmap_icon_options_datetime,
|
&bitmap_icon_options_datetime,
|
||||||
Color::dark_blue(),
|
Theme::getInstance()->fg_blue->foreground,
|
||||||
/*vcenter*/ true};
|
/*vcenter*/ true};
|
||||||
|
|
||||||
NewButton button_open_iq_trim{
|
NewButton button_open_iq_trim{
|
||||||
@ -297,13 +297,13 @@ class FileManagerView : public FileManBaseView {
|
|||||||
{4 * 8, 34 * 8, 4 * 8, 32},
|
{4 * 8, 34 * 8, 4 * 8, 32},
|
||||||
{},
|
{},
|
||||||
&bitmap_icon_trim,
|
&bitmap_icon_trim,
|
||||||
Color::orange()};
|
Theme::getInstance()->fg_orange->foreground};
|
||||||
|
|
||||||
NewButton button_show_hidden_files{
|
NewButton button_show_hidden_files{
|
||||||
{17 * 8, 34 * 8, 4 * 8, 32},
|
{17 * 8, 34 * 8, 4 * 8, 32},
|
||||||
{},
|
{},
|
||||||
&bitmap_icon_hide,
|
&bitmap_icon_hide,
|
||||||
Color::dark_grey()};
|
Theme::getInstance()->fg_dark->foreground};
|
||||||
};
|
};
|
||||||
|
|
||||||
} /* namespace ui */
|
} /* namespace ui */
|
||||||
|
@ -21,7 +21,6 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "ui_flash_utility.hpp"
|
#include "ui_flash_utility.hpp"
|
||||||
#include "ui_styles.hpp"
|
|
||||||
#include "portapack_shared_memory.hpp"
|
#include "portapack_shared_memory.hpp"
|
||||||
#include "file_path.hpp"
|
#include "file_path.hpp"
|
||||||
|
|
||||||
@ -83,6 +82,7 @@ FlashUtilityView::FlashUtilityView(NavigationView& nav)
|
|||||||
|
|
||||||
menu_view.set_parent_rect({0, 3 * 8, 240, 33 * 8});
|
menu_view.set_parent_rect({0, 3 * 8, 240, 33 * 8});
|
||||||
|
|
||||||
|
ensure_directory(apps_dir);
|
||||||
ensure_directory(firmware_dir);
|
ensure_directory(firmware_dir);
|
||||||
|
|
||||||
auto add_firmware_items = [&](
|
auto add_firmware_items = [&](
|
||||||
@ -102,10 +102,10 @@ FlashUtilityView::FlashUtilityView(NavigationView& nav)
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
add_firmware_items(firmware_dir, u"*.bin", ui::Color::red());
|
add_firmware_items(firmware_dir, u"*.bin", ui::Theme::getInstance()->fg_red->foreground);
|
||||||
add_firmware_items(firmware_dir, u"*.tar", ui::Color::purple());
|
add_firmware_items(firmware_dir, u"*.tar", ui::Theme::getInstance()->fg_cyan->foreground);
|
||||||
|
|
||||||
// add_firmware_items(user_firmware_folder,u"*.bin", ui::Color::purple());
|
// add_firmware_items(user_firmware_folder,u"*.bin", ui::Theme::getInstance()->fg_cyan->foreground);
|
||||||
}
|
}
|
||||||
|
|
||||||
void FlashUtilityView::firmware_selected(std::filesystem::path::string_type path) {
|
void FlashUtilityView::firmware_selected(std::filesystem::path::string_type path) {
|
||||||
@ -134,12 +134,12 @@ std::filesystem::path FlashUtilityView::extract_tar(std::filesystem::path::strin
|
|||||||
//
|
//
|
||||||
painter.fill_rectangle(
|
painter.fill_rectangle(
|
||||||
{0, 0, portapack::display.width(), portapack::display.height()},
|
{0, 0, portapack::display.width(), portapack::display.height()},
|
||||||
ui::Color::black());
|
Theme::getInstance()->bg_darkest->background);
|
||||||
painter.draw_string({12, 24}, this->nav_.style(), "Unpacking TAR file...");
|
painter.draw_string({12, 24}, this->nav_.style(), "Unpacking TAR file...");
|
||||||
|
|
||||||
auto res = UnTar::untar(path, [this](const std::string fileName) {
|
auto res = UnTar::untar(path, [this](const std::string fileName) {
|
||||||
ui::Painter painter;
|
ui::Painter painter;
|
||||||
painter.fill_rectangle({0, 50, portapack::display.width(), 90}, ui::Color::black());
|
painter.fill_rectangle({0, 50, portapack::display.width(), 90}, Theme::getInstance()->bg_darkest->background);
|
||||||
painter.draw_string({0, 60}, this->nav_.style(), fileName);
|
painter.draw_string({0, 60}, this->nav_.style(), fileName);
|
||||||
});
|
});
|
||||||
return res;
|
return res;
|
||||||
@ -153,18 +153,18 @@ bool FlashUtilityView::flash_firmware(std::filesystem::path::string_type path) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (path.empty() || !valid_firmware_file(path.c_str())) {
|
if (path.empty() || !valid_firmware_file(path.c_str())) {
|
||||||
painter.fill_rectangle({0, 50, portapack::display.width(), 90}, ui::Color::black());
|
painter.fill_rectangle({0, 50, portapack::display.width(), 90}, Theme::getInstance()->bg_darkest->background);
|
||||||
painter.draw_string({0, 60}, Styles::red, "BAD FIRMWARE FILE");
|
painter.draw_string({0, 60}, *Theme::getInstance()->fg_red, "BAD FIRMWARE FILE OR W/R ERR");
|
||||||
chThdSleepMilliseconds(5000);
|
chThdSleepMilliseconds(5000);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
painter.fill_rectangle(
|
painter.fill_rectangle(
|
||||||
{0, 0, portapack::display.width(), portapack::display.height()},
|
{0, 0, portapack::display.width(), portapack::display.height()},
|
||||||
ui::Color::black());
|
Theme::getInstance()->bg_darkest->background);
|
||||||
|
|
||||||
painter.draw_string({12, 24}, this->nav_.style(), "This will take 15 seconds.");
|
painter.draw_string({12, 24}, this->nav_.style(), "This will take 15 seconds.");
|
||||||
painter.draw_string({12, 64}, this->nav_.style(), "Please wait while LEDs RX");
|
painter.draw_string({12, 64}, this->nav_.style(), "Please wait while LED RX");
|
||||||
painter.draw_string({12, 84}, this->nav_.style(), "and TX are flashing.");
|
painter.draw_string({12, 84}, this->nav_.style(), "is on and TX is flashing.");
|
||||||
painter.draw_string({12, 124}, this->nav_.style(), "Device will then restart.");
|
painter.draw_string({12, 124}, this->nav_.style(), "Device will then restart.");
|
||||||
|
|
||||||
std::memcpy(&shared_memory.bb_data.data[0], path.c_str(), (path.length() + 1) * 2);
|
std::memcpy(&shared_memory.bb_data.data[0], path.c_str(), (path.length() + 1) * 2);
|
||||||
|
@ -57,7 +57,7 @@ class FlashUtilityView : public View {
|
|||||||
static Thread* thread;
|
static Thread* thread;
|
||||||
|
|
||||||
Labels labels{
|
Labels labels{
|
||||||
{{4, 4}, "Select firmware to flash:", Color::white()}};
|
{{4, 4}, "Select firmware to flash:", Theme::getInstance()->bg_darkest->foreground}};
|
||||||
|
|
||||||
MenuView menu_view{
|
MenuView menu_view{
|
||||||
{0, 2 * 8, 240, 26 * 8},
|
{0, 2 * 8, 240, 26 * 8},
|
||||||
|
@ -29,7 +29,6 @@
|
|||||||
#include "rtc_time.hpp"
|
#include "rtc_time.hpp"
|
||||||
#include "tone_key.hpp"
|
#include "tone_key.hpp"
|
||||||
#include "ui_receiver.hpp"
|
#include "ui_receiver.hpp"
|
||||||
#include "ui_styles.hpp"
|
|
||||||
#include "utility.hpp"
|
#include "utility.hpp"
|
||||||
#include "file_path.hpp"
|
#include "file_path.hpp"
|
||||||
|
|
||||||
@ -416,16 +415,16 @@ void FrequencyEditView::refresh_ui() {
|
|||||||
auto is_repeater = entry_.type == freqman_type::Repeater;
|
auto is_repeater = entry_.type == freqman_type::Repeater;
|
||||||
auto has_freq_b = is_range || is_ham || is_repeater;
|
auto has_freq_b = is_range || is_ham || is_repeater;
|
||||||
|
|
||||||
field_freq_b.set_style(has_freq_b ? &Styles::white : &Styles::grey);
|
field_freq_b.set_style(has_freq_b ? Theme::getInstance()->bg_darkest : Theme::getInstance()->fg_medium);
|
||||||
field_step.set_style(is_range ? &Styles::white : &Styles::grey);
|
field_step.set_style(is_range ? Theme::getInstance()->bg_darkest : Theme::getInstance()->fg_medium);
|
||||||
field_tone.set_style(is_ham ? &Styles::white : &Styles::grey);
|
field_tone.set_style(is_ham ? Theme::getInstance()->bg_darkest : Theme::getInstance()->fg_medium);
|
||||||
|
|
||||||
if (is_valid(entry_)) {
|
if (is_valid(entry_)) {
|
||||||
text_validation.set("Valid");
|
text_validation.set("Valid");
|
||||||
text_validation.set_style(&Styles::green);
|
text_validation.set_style(Theme::getInstance()->fg_green);
|
||||||
} else {
|
} else {
|
||||||
text_validation.set("Error");
|
text_validation.set("Error");
|
||||||
text_validation.set_style(&Styles::red);
|
text_validation.set_style(Theme::getInstance()->fg_red);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -61,7 +61,7 @@ class FreqManBaseView : public View {
|
|||||||
|
|
||||||
/* The top section (category) is 20px tall. */
|
/* The top section (category) is 20px tall. */
|
||||||
Labels label_category{
|
Labels label_category{
|
||||||
{{0, 2}, "F:", Color::light_grey()}};
|
{{0, 2}, "F:", Theme::getInstance()->fg_light->foreground}};
|
||||||
|
|
||||||
OptionsField options_category{
|
OptionsField options_category{
|
||||||
{3 * 8, 2},
|
{3 * 8, 2},
|
||||||
@ -97,7 +97,7 @@ class FrequencySaveView : public FreqManBaseView {
|
|||||||
0};
|
0};
|
||||||
|
|
||||||
Labels labels{
|
Labels labels{
|
||||||
{{0 * 8, 6 * 16}, "Description:", Color::white()}};
|
{{0 * 8, 6 * 16}, "Description:", Theme::getInstance()->bg_darkest->foreground}};
|
||||||
|
|
||||||
TextField field_description{
|
TextField field_description{
|
||||||
{0 * 8, 7 * 16, 30 * 8, 1 * 16},
|
{0 * 8, 7 * 16, 30 * 8, 1 * 16},
|
||||||
@ -137,14 +137,14 @@ class FrequencyManagerView : public FreqManBaseView {
|
|||||||
{23 * 8, 0 * 16, 7 * 4, 20},
|
{23 * 8, 0 * 16, 7 * 4, 20},
|
||||||
{},
|
{},
|
||||||
&bitmap_icon_new_file,
|
&bitmap_icon_new_file,
|
||||||
Color::white(),
|
Theme::getInstance()->bg_darkest->foreground,
|
||||||
true};
|
true};
|
||||||
|
|
||||||
NewButton button_del_category{
|
NewButton button_del_category{
|
||||||
{26 * 8 + 4, 0 * 16, 7 * 4, 20},
|
{26 * 8 + 4, 0 * 16, 7 * 4, 20},
|
||||||
{},
|
{},
|
||||||
&bitmap_icon_trash,
|
&bitmap_icon_trash,
|
||||||
Color::red(),
|
Theme::getInstance()->fg_red->foreground,
|
||||||
true};
|
true};
|
||||||
|
|
||||||
Button button_edit_entry{
|
Button button_edit_entry{
|
||||||
@ -153,7 +153,7 @@ class FrequencyManagerView : public FreqManBaseView {
|
|||||||
|
|
||||||
Rectangle rect_padding{
|
Rectangle rect_padding{
|
||||||
{15 * 8, 14 * 16 - 4, 15 * 8, 1 * 16 + 4},
|
{15 * 8, 14 * 16 - 4, 15 * 8, 1 * 16 + 4},
|
||||||
Color::grey()};
|
Theme::getInstance()->fg_medium->background};
|
||||||
|
|
||||||
Button button_edit_freq{
|
Button button_edit_freq{
|
||||||
{0 * 8, 15 * 16, 15 * 8, 2 * 16},
|
{0 * 8, 15 * 16, 15 * 8, 2 * 16},
|
||||||
@ -167,14 +167,14 @@ class FrequencyManagerView : public FreqManBaseView {
|
|||||||
{15 * 8, 15 * 16, 7 * 8 + 4, 2 * 16},
|
{15 * 8, 15 * 16, 7 * 8 + 4, 2 * 16},
|
||||||
{},
|
{},
|
||||||
&bitmap_icon_add,
|
&bitmap_icon_add,
|
||||||
Color::white(),
|
Theme::getInstance()->bg_darkest->foreground,
|
||||||
true};
|
true};
|
||||||
|
|
||||||
NewButton button_del_entry{
|
NewButton button_del_entry{
|
||||||
{22 * 8 + 4, 15 * 16, 7 * 8 + 4, 2 * 16},
|
{22 * 8 + 4, 15 * 16, 7 * 8 + 4, 2 * 16},
|
||||||
{},
|
{},
|
||||||
&bitmap_icon_delete,
|
&bitmap_icon_delete,
|
||||||
Color::red(),
|
Theme::getInstance()->fg_red->foreground,
|
||||||
true};
|
true};
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -200,15 +200,15 @@ class FrequencyEditView : public View {
|
|||||||
void populate_tone_options();
|
void populate_tone_options();
|
||||||
|
|
||||||
Labels labels{
|
Labels labels{
|
||||||
{{5 * 8, 1 * 16}, "Edit Frequency Entry", Color::white()},
|
{{5 * 8, 1 * 16}, "Edit Frequency Entry", Theme::getInstance()->bg_darkest->foreground},
|
||||||
{{0 * 8, 3 * 16}, "Entry Type :", Color::light_grey()},
|
{{0 * 8, 3 * 16}, "Entry Type :", Theme::getInstance()->fg_light->foreground},
|
||||||
{{0 * 8, 4 * 16}, "Frequency A:", Color::light_grey()},
|
{{0 * 8, 4 * 16}, "Frequency A:", Theme::getInstance()->fg_light->foreground},
|
||||||
{{0 * 8, 5 * 16}, "Frequency B:", Color::light_grey()},
|
{{0 * 8, 5 * 16}, "Frequency B:", Theme::getInstance()->fg_light->foreground},
|
||||||
{{0 * 8, 6 * 16}, "Modulation :", Color::light_grey()},
|
{{0 * 8, 6 * 16}, "Modulation :", Theme::getInstance()->fg_light->foreground},
|
||||||
{{0 * 8, 7 * 16}, "Bandwidth :", Color::light_grey()},
|
{{0 * 8, 7 * 16}, "Bandwidth :", Theme::getInstance()->fg_light->foreground},
|
||||||
{{0 * 8, 8 * 16}, "Step :", Color::light_grey()},
|
{{0 * 8, 8 * 16}, "Step :", Theme::getInstance()->fg_light->foreground},
|
||||||
{{0 * 8, 9 * 16}, "Tone Freq :", Color::light_grey()},
|
{{0 * 8, 9 * 16}, "Tone Freq :", Theme::getInstance()->fg_light->foreground},
|
||||||
{{0 * 8, 10 * 16}, "Description:", Color::light_grey()},
|
{{0 * 8, 10 * 16}, "Description:", Theme::getInstance()->fg_light->foreground},
|
||||||
};
|
};
|
||||||
|
|
||||||
OptionsField field_type{
|
OptionsField field_type{
|
||||||
|
@ -30,7 +30,6 @@
|
|||||||
#include "ui_record_view.hpp"
|
#include "ui_record_view.hpp"
|
||||||
#include "ui_rssi.hpp"
|
#include "ui_rssi.hpp"
|
||||||
#include "ui_spectrum.hpp"
|
#include "ui_spectrum.hpp"
|
||||||
#include "ui_styles.hpp"
|
|
||||||
#include "ui_tabview.hpp"
|
#include "ui_tabview.hpp"
|
||||||
|
|
||||||
#include "app_settings.hpp"
|
#include "app_settings.hpp"
|
||||||
@ -117,8 +116,8 @@ class FskxRxMainView : public View {
|
|||||||
FskRxAppConsoleView view_data{nav_, view_rect};
|
FskRxAppConsoleView view_data{nav_, view_rect};
|
||||||
|
|
||||||
TabView tab_view{
|
TabView tab_view{
|
||||||
{"Data", Color::yellow(), &view_data},
|
{"Data", Theme::getInstance()->fg_yellow->foreground, &view_data},
|
||||||
{"Stream", Color::cyan(), &view_stream}};
|
{"Stream", Theme::getInstance()->fg_cyan->foreground, &view_stream}};
|
||||||
|
|
||||||
void refresh_ui(rf::Frequency f);
|
void refresh_ui(rf::Frequency f);
|
||||||
void on_packet(uint32_t value, bool is_data);
|
void on_packet(uint32_t value, bool is_data);
|
||||||
@ -148,7 +147,7 @@ class FskxRxMainView : public View {
|
|||||||
{19 * 8 - 4, 40, 6 * 8, 4}};
|
{19 * 8 - 4, 40, 6 * 8, 4}};
|
||||||
|
|
||||||
Labels labels{
|
Labels labels{
|
||||||
{{0 * 8, 3 * 16}, "Deviation:", Color::light_grey()},
|
{{0 * 8, 3 * 16}, "Deviation:", Theme::getInstance()->fg_light->foreground},
|
||||||
};
|
};
|
||||||
|
|
||||||
FrequencyField deviation_frequency{
|
FrequencyField deviation_frequency{
|
||||||
|
@ -54,8 +54,8 @@ IQTrimView::IQTrimView(NavigationView& nav)
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
text_samples.set_style(&Styles::light_grey);
|
text_samples.set_style(Theme::getInstance()->fg_light);
|
||||||
text_max.set_style(&Styles::light_grey);
|
text_max.set_style(Theme::getInstance()->fg_light);
|
||||||
|
|
||||||
field_start.on_change = [this](int32_t v) {
|
field_start.on_change = [this](int32_t v) {
|
||||||
if (field_end.value() < v)
|
if (field_end.value() < v)
|
||||||
@ -149,9 +149,9 @@ void IQTrimView::refresh_ui() {
|
|||||||
// show max power in red if amplification is too high, causing clipping
|
// show max power in red if amplification is too high, causing clipping
|
||||||
uint32_t clipping_limit = (fs::capture_file_sample_size(path_) == sizeof(complex8_t)) ? 0x80 : 0x8000;
|
uint32_t clipping_limit = (fs::capture_file_sample_size(path_) == sizeof(complex8_t)) ? 0x80 : 0x8000;
|
||||||
if ((field_amplify.value() * info_->max_iq) > clipping_limit)
|
if ((field_amplify.value() * info_->max_iq) > clipping_limit)
|
||||||
text_max.set_style(&Styles::red);
|
text_max.set_style(Theme::getInstance()->fg_red);
|
||||||
else
|
else
|
||||||
text_max.set_style(&Styles::light_grey);
|
text_max.set_style(Theme::getInstance()->fg_light);
|
||||||
|
|
||||||
set_dirty();
|
set_dirty();
|
||||||
}
|
}
|
||||||
|
@ -28,7 +28,6 @@
|
|||||||
#include "optional.hpp"
|
#include "optional.hpp"
|
||||||
#include "ui.hpp"
|
#include "ui.hpp"
|
||||||
#include "ui_navigation.hpp"
|
#include "ui_navigation.hpp"
|
||||||
#include "ui_styles.hpp"
|
|
||||||
#include "ui_widget.hpp"
|
#include "ui_widget.hpp"
|
||||||
|
|
||||||
#include <array>
|
#include <array>
|
||||||
@ -41,21 +40,21 @@ class TrimProgressUI {
|
|||||||
public:
|
public:
|
||||||
void show_reading() {
|
void show_reading() {
|
||||||
clear();
|
clear();
|
||||||
p.draw_string({6 * 8, 5 * 16}, Styles::yellow, "Reading Capture...");
|
p.draw_string({6 * 8, 5 * 16}, *Theme::getInstance()->fg_yellow, "Reading Capture...");
|
||||||
}
|
}
|
||||||
|
|
||||||
void show_trimming() {
|
void show_trimming() {
|
||||||
clear();
|
clear();
|
||||||
p.draw_string({5 * 8, 5 * 16}, Styles::yellow, "Trimming Capture...");
|
p.draw_string({5 * 8, 5 * 16}, *Theme::getInstance()->fg_yellow, "Trimming Capture...");
|
||||||
}
|
}
|
||||||
|
|
||||||
void show_progress(uint8_t percent) {
|
void show_progress(uint8_t percent) {
|
||||||
auto width = percent * screen_width / 100;
|
auto width = percent * screen_width / 100;
|
||||||
p.draw_hline({0, 6 * 16 + 2}, width, Color::yellow());
|
p.draw_hline({0, 6 * 16 + 2}, width, Theme::getInstance()->fg_yellow->foreground);
|
||||||
}
|
}
|
||||||
|
|
||||||
void clear() {
|
void clear() {
|
||||||
p.fill_rectangle({0 * 8, 4 * 16, screen_width, 3 * 16}, Color::black());
|
p.fill_rectangle({0 * 8, 4 * 16, screen_width, 3 * 16}, Theme::getInstance()->bg_darkest->background);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto get_callback() {
|
auto get_callback() {
|
||||||
@ -101,15 +100,15 @@ class IQTrimView : public View {
|
|||||||
TrimProgressUI progress_ui{};
|
TrimProgressUI progress_ui{};
|
||||||
|
|
||||||
Labels labels{
|
Labels labels{
|
||||||
{{0 * 8, 0 * 16}, "Capture File:", Color::light_grey()},
|
{{0 * 8, 0 * 16}, "Capture File:", Theme::getInstance()->fg_light->foreground},
|
||||||
{{0 * 8, 6 * 16}, "Start :", Color::light_grey()},
|
{{0 * 8, 6 * 16}, "Start :", Theme::getInstance()->fg_light->foreground},
|
||||||
{{0 * 8, 7 * 16}, "End :", Color::light_grey()},
|
{{0 * 8, 7 * 16}, "End :", Theme::getInstance()->fg_light->foreground},
|
||||||
{{0 * 8, 8 * 16}, "Samples:", Color::light_grey()},
|
{{0 * 8, 8 * 16}, "Samples:", Theme::getInstance()->fg_light->foreground},
|
||||||
{{0 * 8, 9 * 16}, "Max Pwr:", Color::light_grey()},
|
{{0 * 8, 9 * 16}, "Max Pwr:", Theme::getInstance()->fg_light->foreground},
|
||||||
{{0 * 8, 10 * 16}, "Cutoff :", Color::light_grey()},
|
{{0 * 8, 10 * 16}, "Cutoff :", Theme::getInstance()->fg_light->foreground},
|
||||||
{{12 * 8, 10 * 16}, "%", Color::light_grey()},
|
{{12 * 8, 10 * 16}, "%", Theme::getInstance()->fg_light->foreground},
|
||||||
{{0 * 8, 12 * 16}, "Amplify:", Color::light_grey()},
|
{{0 * 8, 12 * 16}, "Amplify:", Theme::getInstance()->fg_light->foreground},
|
||||||
{{10 * 8, 12 * 16}, "x", Color::light_grey()},
|
{{10 * 8, 12 * 16}, "x", Theme::getInstance()->fg_light->foreground},
|
||||||
};
|
};
|
||||||
|
|
||||||
TextField field_path{
|
TextField field_path{
|
||||||
|
@ -169,9 +169,9 @@ LevelView::LevelView(NavigationView& nav)
|
|||||||
rssi_resolution.set_selected_index(1);
|
rssi_resolution.set_selected_index(1);
|
||||||
// FILL STEP OPTIONS
|
// FILL STEP OPTIONS
|
||||||
freqman_set_step_option_short(step_mode);
|
freqman_set_step_option_short(step_mode);
|
||||||
freq_stats_rssi.set_style(&Styles::white);
|
freq_stats_rssi.set_style(Theme::getInstance()->bg_darkest);
|
||||||
freq_stats_db.set_style(&Styles::white);
|
freq_stats_db.set_style(Theme::getInstance()->bg_darkest);
|
||||||
freq_stats_rx.set_style(&Styles::white);
|
freq_stats_rx.set_style(Theme::getInstance()->bg_darkest);
|
||||||
}
|
}
|
||||||
|
|
||||||
void LevelView::on_statistics_update(const ChannelStatistics& statistics) {
|
void LevelView::on_statistics_update(const ChannelStatistics& statistics) {
|
||||||
@ -323,4 +323,9 @@ void LevelView::handle_coded_squelch(const uint32_t value) {
|
|||||||
text_ctcss.set(" ");
|
text_ctcss.set(" ");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void LevelView::on_freqchg(int64_t freq) {
|
||||||
|
receiver_model.set_target_frequency(freq);
|
||||||
|
button_frequency.set_text("<" + to_string_short_freq(freq) + " MHz>");
|
||||||
|
}
|
||||||
|
|
||||||
} /* namespace ui */
|
} /* namespace ui */
|
||||||
|
@ -38,7 +38,6 @@
|
|||||||
#include "ui_mictx.hpp"
|
#include "ui_mictx.hpp"
|
||||||
#include "ui_receiver.hpp"
|
#include "ui_receiver.hpp"
|
||||||
#include "ui_spectrum.hpp"
|
#include "ui_spectrum.hpp"
|
||||||
#include "ui_styles.hpp"
|
|
||||||
|
|
||||||
namespace ui {
|
namespace ui {
|
||||||
|
|
||||||
@ -81,8 +80,8 @@ class LevelView : public View {
|
|||||||
}};
|
}};
|
||||||
|
|
||||||
Labels labels{
|
Labels labels{
|
||||||
{{0 * 8, 0 * 16}, "LNA: VGA: AMP: VOL: ", Color::light_grey()},
|
{{0 * 8, 0 * 16}, "LNA: VGA: AMP: VOL: ", Theme::getInstance()->fg_light->foreground},
|
||||||
{{0 * 8, 1 * 16}, "BW: MODE: S: ", Color::light_grey()},
|
{{0 * 8, 1 * 16}, "BW: MODE: S: ", Theme::getInstance()->fg_light->foreground},
|
||||||
};
|
};
|
||||||
|
|
||||||
LNAGainField field_lna{
|
LNAGainField field_lna{
|
||||||
@ -189,6 +188,15 @@ class LevelView : public View {
|
|||||||
|
|
||||||
void handle_coded_squelch(const uint32_t value);
|
void handle_coded_squelch(const uint32_t value);
|
||||||
|
|
||||||
|
void on_freqchg(int64_t freq);
|
||||||
|
|
||||||
|
MessageHandlerRegistration message_handler_freqchg{
|
||||||
|
Message::ID::FreqChangeCommand,
|
||||||
|
[this](Message* const p) {
|
||||||
|
const auto message = static_cast<const FreqChangeCommandMessage*>(p);
|
||||||
|
this->on_freqchg(message->freq);
|
||||||
|
}};
|
||||||
|
|
||||||
MessageHandlerRegistration message_handler_coded_squelch{
|
MessageHandlerRegistration message_handler_coded_squelch{
|
||||||
Message::ID::CodedSquelch,
|
Message::ID::CodedSquelch,
|
||||||
[this](const Message* const p) {
|
[this](const Message* const p) {
|
||||||
|
@ -49,12 +49,12 @@ int32_t GlassView::map(int32_t value, int32_t fromLow, int32_t fromHigh, int32_t
|
|||||||
|
|
||||||
void GlassView::update_display_beep() {
|
void GlassView::update_display_beep() {
|
||||||
if (beep_enabled) {
|
if (beep_enabled) {
|
||||||
button_beep_squelch.set_style(&Styles::green);
|
button_beep_squelch.set_style(Theme::getInstance()->fg_green);
|
||||||
// bip-XXdb
|
// bip-XXdb
|
||||||
button_beep_squelch.set_text("bip" + to_string_dec_int(beep_squelch, 3) + "db");
|
button_beep_squelch.set_text("bip" + to_string_dec_int(beep_squelch, 3) + "db");
|
||||||
receiver_model.set_headphone_volume(receiver_model.headphone_volume()); // WM8731 hack.
|
receiver_model.set_headphone_volume(receiver_model.headphone_volume()); // WM8731 hack.
|
||||||
} else {
|
} else {
|
||||||
button_beep_squelch.set_style(&Styles::white);
|
button_beep_squelch.set_style(Theme::getInstance()->bg_darkest);
|
||||||
button_beep_squelch.set_text("bip OFF ");
|
button_beep_squelch.set_text("bip OFF ");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -305,10 +305,10 @@ void GlassView::plot_marker(uint8_t pos) {
|
|||||||
{
|
{
|
||||||
shift_y = 16;
|
shift_y = 16;
|
||||||
}
|
}
|
||||||
portapack::display.fill_rectangle({0, 100 + shift_y, SCREEN_W, 8}, Color::black()); // Clear old marker and whole marker rectangle btw
|
portapack::display.fill_rectangle({0, 100 + shift_y, SCREEN_W, 8}, Theme::getInstance()->bg_darkest->background); // Clear old marker and whole marker rectangle btw
|
||||||
portapack::display.fill_rectangle({pos - 2, 100 + shift_y, 5, 3}, Color::red()); // Red marker top
|
portapack::display.fill_rectangle({pos - 2, 100 + shift_y, 5, 3}, Theme::getInstance()->fg_red->foreground); // Red marker top
|
||||||
portapack::display.fill_rectangle({pos - 1, 103 + shift_y, 3, 3}, Color::red()); // Red marker middle
|
portapack::display.fill_rectangle({pos - 1, 103 + shift_y, 3, 3}, Theme::getInstance()->fg_red->foreground); // Red marker middle
|
||||||
portapack::display.fill_rectangle({pos, 106 + shift_y, 1, 2}, Color::red()); // Red marker bottom
|
portapack::display.fill_rectangle({pos, 106 + shift_y, 1, 2}, Theme::getInstance()->fg_red->foreground); // Red marker bottom
|
||||||
}
|
}
|
||||||
|
|
||||||
void GlassView::update_min(int32_t v) {
|
void GlassView::update_min(int32_t v) {
|
||||||
@ -347,10 +347,10 @@ void GlassView::update_max(int32_t v) {
|
|||||||
|
|
||||||
void GlassView::update_range_field() {
|
void GlassView::update_range_field() {
|
||||||
if (!locked_range) {
|
if (!locked_range) {
|
||||||
field_range.set_style(&Styles::white);
|
field_range.set_style(Theme::getInstance()->bg_darkest);
|
||||||
field_range.set_text(" " + to_string_dec_uint(search_span) + " ");
|
field_range.set_text(" " + to_string_dec_uint(search_span) + " ");
|
||||||
} else {
|
} else {
|
||||||
field_range.set_style(&Styles::red);
|
field_range.set_style(Theme::getInstance()->fg_red);
|
||||||
field_range.set_text(">" + to_string_dec_uint(search_span) + "<");
|
field_range.set_text(">" + to_string_dec_uint(search_span) + "<");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -561,6 +561,17 @@ GlassView::GlassView(
|
|||||||
update_display_beep();
|
update_display_beep();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GlassView::on_freqchg(int64_t freq) {
|
||||||
|
int64_t half_range = abs(field_frequency_max.value() - field_frequency_max.value()) / 2;
|
||||||
|
if (half_range < 1) {
|
||||||
|
half_range = 1;
|
||||||
|
}
|
||||||
|
range_presets.set_selected_index(0); // Manual
|
||||||
|
update_min(freq - half_range);
|
||||||
|
update_max(freq + half_range);
|
||||||
|
on_range_changed();
|
||||||
|
}
|
||||||
|
|
||||||
uint8_t GlassView::get_spec_iq_phase_calibration_value() { // define accessor functions inside AnalogAudioView to read & write real iq_phase_calibration_value
|
uint8_t GlassView::get_spec_iq_phase_calibration_value() { // define accessor functions inside AnalogAudioView to read & write real iq_phase_calibration_value
|
||||||
return iq_phase_calibration_value;
|
return iq_phase_calibration_value;
|
||||||
}
|
}
|
||||||
|
@ -33,7 +33,6 @@
|
|||||||
#include "ui_widget.hpp"
|
#include "ui_widget.hpp"
|
||||||
#include "ui_navigation.hpp"
|
#include "ui_navigation.hpp"
|
||||||
#include "ui_receiver.hpp"
|
#include "ui_receiver.hpp"
|
||||||
#include "ui_styles.hpp"
|
|
||||||
#include "string_format.hpp"
|
#include "string_format.hpp"
|
||||||
#include "analog_audio_app.hpp"
|
#include "analog_audio_app.hpp"
|
||||||
#include "spectrum_color_lut.hpp"
|
#include "spectrum_color_lut.hpp"
|
||||||
@ -110,6 +109,7 @@ class GlassView : public View {
|
|||||||
std::string label{};
|
std::string label{};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
void on_freqchg(int64_t freq);
|
||||||
int32_t map(int32_t value, int32_t fromLow, int32_t fromHigh, int32_t toLow, int32_t toHigh);
|
int32_t map(int32_t value, int32_t fromLow, int32_t fromHigh, int32_t toLow, int32_t toHigh);
|
||||||
std::vector<preset_entry> presets_db{};
|
std::vector<preset_entry> presets_db{};
|
||||||
void manage_beep_audio();
|
void manage_beep_audio();
|
||||||
@ -171,12 +171,12 @@ class GlassView : public View {
|
|||||||
uint8_t ignore_dc = 0;
|
uint8_t ignore_dc = 0;
|
||||||
|
|
||||||
Labels labels{
|
Labels labels{
|
||||||
{{0, 0 * 16}, "MIN: MAX: LNA VGA ", Color::light_grey()},
|
{{0, 0 * 16}, "MIN: MAX: LNA VGA ", Theme::getInstance()->fg_light->foreground},
|
||||||
{{0, 1 * 16}, "RANGE: FILTER: AMP:", Color::light_grey()},
|
{{0, 1 * 16}, "RANGE: FILTER: AMP:", Theme::getInstance()->fg_light->foreground},
|
||||||
{{0, 2 * 16}, "P:", Color::light_grey()},
|
{{0, 2 * 16}, "P:", Theme::getInstance()->fg_light->foreground},
|
||||||
{{0, 3 * 16}, "MARKER: MHz RXIQCAL", Color::light_grey()},
|
{{0, 3 * 16}, "MARKER: MHz RXIQCAL", Theme::getInstance()->fg_light->foreground},
|
||||||
//{{0, 4 * 16}, "RES: STEPS:", Color::light_grey()}};
|
//{{0, 4 * 16}, "RES: STEPS:", Theme::getInstance()->fg_light->foreground}};
|
||||||
{{0, 4 * 16}, "RES: VOL:", Color::light_grey()}};
|
{{0, 4 * 16}, "RES: VOL:", Theme::getInstance()->fg_light->foreground}};
|
||||||
|
|
||||||
NumberField field_frequency_min{
|
NumberField field_frequency_min{
|
||||||
{4 * 8, 0 * 16},
|
{4 * 8, 0 * 16},
|
||||||
@ -308,6 +308,7 @@ class GlassView : public View {
|
|||||||
const auto message = *reinterpret_cast<const ChannelSpectrumConfigMessage*>(p);
|
const auto message = *reinterpret_cast<const ChannelSpectrumConfigMessage*>(p);
|
||||||
this->fifo = message.fifo;
|
this->fifo = message.fifo;
|
||||||
}};
|
}};
|
||||||
|
|
||||||
MessageHandlerRegistration message_handler_frame_sync{
|
MessageHandlerRegistration message_handler_frame_sync{
|
||||||
Message::ID::DisplayFrameSync,
|
Message::ID::DisplayFrameSync,
|
||||||
[this](const Message* const) {
|
[this](const Message* const) {
|
||||||
@ -318,6 +319,13 @@ class GlassView : public View {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}};
|
}};
|
||||||
|
|
||||||
|
MessageHandlerRegistration message_handler_freqchg{
|
||||||
|
Message::ID::FreqChangeCommand,
|
||||||
|
[this](Message* const p) {
|
||||||
|
const auto message = static_cast<const FreqChangeCommandMessage*>(p);
|
||||||
|
this->on_freqchg(message->freq);
|
||||||
|
}};
|
||||||
};
|
};
|
||||||
} // namespace ui
|
} // namespace ui
|
||||||
#endif
|
#endif
|
||||||
|
@ -63,8 +63,8 @@ void MicTXView::update_vumeter() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void MicTXView::update_tx_icon() {
|
void MicTXView::update_tx_icon() {
|
||||||
tx_icon.set_foreground(transmitting ? Color::red() : Color::black());
|
tx_icon.set_foreground(transmitting ? Theme::getInstance()->fg_red->foreground : Theme::getInstance()->bg_darkest->background);
|
||||||
tx_icon.set_background(transmitting ? Color::yellow() : Color::black());
|
tx_icon.set_background(transmitting ? Theme::getInstance()->fg_yellow->foreground : Theme::getInstance()->bg_darkest->background);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MicTXView::on_tx_progress(const bool done) {
|
void MicTXView::on_tx_progress(const bool done) {
|
||||||
@ -269,16 +269,24 @@ void MicTXView::set_rxbw_options(void) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void MicTXView::set_rxbw_defaults(bool use_app_settings) {
|
void MicTXView::set_rxbw_defaults(bool use_app_settings) { // Initially in that function we set up rxbw, but now also txbw.
|
||||||
if (use_app_settings) {
|
if (use_app_settings) {
|
||||||
field_bw.set_value(transmitter_model.channel_bandwidth() / 1000);
|
field_bw.set_value(transmitter_model.channel_bandwidth() / 1000);
|
||||||
field_rxbw.set_by_value(rxbw_index);
|
field_rxbw.set_by_value(rxbw_index);
|
||||||
} else if (mic_mod_index == MIC_MOD_NFM) {
|
} else if (mic_mod_index == MIC_MOD_NFM) {
|
||||||
field_bw.set_value(10); // NFM TX bw 10k, RX bw 16k (2) default
|
field_bw.set_value(10); // NFM TX bw 10k, RX bw 16k (index 2) default
|
||||||
field_rxbw.set_by_value(2);
|
field_bw.set_range(1, 60); // In NFM , FM , we are limitting index modulation range (0.08 ..5) ; (Ex max dev 60khz/12k = 5)
|
||||||
|
field_bw.set_step(1);
|
||||||
|
field_rxbw.set_by_value(2); // 16k from the three options (8k5,11k,16k)
|
||||||
} else if (mic_mod_index == MIC_MOD_WFM) {
|
} else if (mic_mod_index == MIC_MOD_WFM) {
|
||||||
field_bw.set_value(75); // WFM TX bw 75K, RX bw 200k (0) default
|
field_bw.set_value(75); // WFM TX bw 75K, RX bw 200k (index 0) default
|
||||||
|
field_bw.set_range(1, 150); // In our case Mod. Index range (1,67 ...12,5) ; 150k/12k=12,5
|
||||||
|
field_bw.set_step(1);
|
||||||
field_rxbw.set_by_value(0);
|
field_rxbw.set_by_value(0);
|
||||||
|
} else if ((mic_mod_index == MIC_MOD_USB) | (mic_mod_index == MIC_MOD_LSB)) {
|
||||||
|
field_bw.set_value(3); // In SSB by default let's limit TX_BW to 3kHz.
|
||||||
|
field_bw.set_range(2, 3); // User TXBW GUI range to modify that SSB TX_BW to limit SSB radiated spectrum.
|
||||||
|
field_bw.set_step(1);
|
||||||
}
|
}
|
||||||
// field_bw is hidden in other modulation cases
|
// field_bw is hidden in other modulation cases
|
||||||
}
|
}
|
||||||
@ -481,8 +489,12 @@ MicTXView::MicTXView(
|
|||||||
if ((mic_mod_index == MIC_MOD_NFM) || (mic_mod_index == MIC_MOD_WFM)) {
|
if ((mic_mod_index == MIC_MOD_NFM) || (mic_mod_index == MIC_MOD_WFM)) {
|
||||||
field_bw.hidden(false);
|
field_bw.hidden(false);
|
||||||
options_tone_key.hidden(false);
|
options_tone_key.hidden(false);
|
||||||
|
} else {
|
||||||
|
if ((mic_mod_index == MIC_MOD_USB) || (mic_mod_index == MIC_MOD_LSB)) {
|
||||||
|
field_bw.hidden(false);
|
||||||
} else {
|
} else {
|
||||||
field_bw.hidden(true);
|
field_bw.hidden(true);
|
||||||
|
}
|
||||||
options_tone_key.set_selected_index(0);
|
options_tone_key.set_selected_index(0);
|
||||||
options_tone_key.hidden(true);
|
options_tone_key.hidden(true);
|
||||||
}
|
}
|
||||||
|
@ -147,27 +147,27 @@ class MicTXView : public View {
|
|||||||
bool button_touch{false};
|
bool button_touch{false};
|
||||||
|
|
||||||
Labels labels_both{
|
Labels labels_both{
|
||||||
{{3 * 8, 1 * 8}, "MIC-GAIN:", Color::light_grey()},
|
{{3 * 8, 1 * 8}, "MIC-GAIN:", Theme::getInstance()->fg_light->foreground},
|
||||||
{{3 * 8, 3 * 8}, "F:", Color::light_grey()},
|
{{3 * 8, 3 * 8}, "F: MHz", Theme::getInstance()->fg_light->foreground},
|
||||||
{{15 * 8, 3 * 8}, "FM TXBW: kHz", Color::light_grey()}, // to be more symetric and consistent to the below FM RXBW
|
{{18 * 8, 3 * 8}, "TXBW: kHz", Theme::getInstance()->fg_light->foreground}, // to be more symetric and consistent to the below FM RXBW
|
||||||
{{18 * 8, (5 * 8)}, "Mode:", Color::light_grey()}, // now, no need to handle GAIN, Amp here It is handled by ui_transmitter.cpp
|
{{18 * 8, (5 * 8)}, "Mode:", Theme::getInstance()->fg_light->foreground}, // now, no need to handle GAIN, Amp here It is handled by ui_transmitter.cpp
|
||||||
{{4 * 8, 10 * 8}, "LVL:", Color::light_grey()}, // we delete { {11 * 8, 5 * 8 }, "Amp:", Color::light_grey() },
|
{{4 * 8, 10 * 8}, "LVL:", Theme::getInstance()->fg_light->foreground}, // we delete { {11 * 8, 5 * 8 }, "Amp:", Theme::getInstance()->fg_light->foreground },
|
||||||
{{12 * 8, 10 * 8}, "ATT:", Color::light_grey()},
|
{{12 * 8, 10 * 8}, "ATT:", Theme::getInstance()->fg_light->foreground},
|
||||||
{{20 * 8, 10 * 8}, "DEC:", Color::light_grey()},
|
{{20 * 8, 10 * 8}, "DEC:", Theme::getInstance()->fg_light->foreground},
|
||||||
{{3 * 8, (13 * 8) - 5}, "TONE KEY:", Color::light_grey()},
|
{{3 * 8, (13 * 8) - 5}, "TONE KEY:", Theme::getInstance()->fg_light->foreground},
|
||||||
{{3 * 8, (18 * 8) - 1}, "======== Receiver ========", Color::green()},
|
{{3 * 8, (18 * 8) - 1}, "======== Receiver ========", Theme::getInstance()->fg_green->foreground},
|
||||||
{{5 * 8, (23 * 8) + 2}, "VOL:", Color::light_grey()},
|
{{5 * 8, (23 * 8) + 2}, "VOL:", Theme::getInstance()->fg_light->foreground},
|
||||||
{{14 * 8, (23 * 8) + 2}, "RXBW:", Color::light_grey()}, // we remove the label "FM" because we will display all MOD types RX_BW.
|
{{14 * 8, (23 * 8) + 2}, "RXBW:", Theme::getInstance()->fg_light->foreground}, // we remove the label "FM" because we will display all MOD types RX_BW.
|
||||||
{{20 * 8, (25 * 8) + 2}, "SQ:", Color::light_grey()},
|
{{20 * 8, (25 * 8) + 2}, "SQ:", Theme::getInstance()->fg_light->foreground},
|
||||||
{{5 * 8, (25 * 8) + 2}, "F_RX:", Color::light_grey()},
|
{{5 * 8, (25 * 8) + 2}, "F_RX:", Theme::getInstance()->fg_light->foreground},
|
||||||
{{5 * 8, (27 * 8) + 2}, "LNA:", Color::light_grey()},
|
{{5 * 8, (27 * 8) + 2}, "LNA:", Theme::getInstance()->fg_light->foreground},
|
||||||
{{12 * 8, (27 * 8) + 2}, "VGA:", Color::light_grey()},
|
{{12 * 8, (27 * 8) + 2}, "VGA:", Theme::getInstance()->fg_light->foreground},
|
||||||
{{19 * 8, (27 * 8) + 2}, "AMP:", Color::light_grey()},
|
{{19 * 8, (27 * 8) + 2}, "AMP:", Theme::getInstance()->fg_light->foreground},
|
||||||
{{21 * 8, (31 * 8)}, "TX-IQ-CAL:", Color::light_grey()}};
|
{{21 * 8, (31 * 8)}, "TX-IQ-CAL:", Theme::getInstance()->fg_light->foreground}};
|
||||||
Labels labels_WM8731{
|
Labels labels_WM8731{
|
||||||
{{17 * 8, 1 * 8}, "Boost", Color::light_grey()}};
|
{{17 * 8, 1 * 8}, "Boost", Theme::getInstance()->fg_light->foreground}};
|
||||||
Labels labels_AK4951{
|
Labels labels_AK4951{
|
||||||
{{17 * 8, 1 * 8}, "ALC", Color::light_grey()}};
|
{{17 * 8, 1 * 8}, "ALC", Theme::getInstance()->fg_light->foreground}};
|
||||||
|
|
||||||
VuMeter vumeter{
|
VuMeter vumeter{
|
||||||
{0 * 8, 1 * 8, 2 * 8, 33 * 8},
|
{0 * 8, 1 * 8, 2 * 8, 33 * 8},
|
||||||
@ -357,8 +357,8 @@ class MicTXView : public View {
|
|||||||
Image tx_icon{
|
Image tx_icon{
|
||||||
{6 * 8, 31 * 8 + 4, 16, 16},
|
{6 * 8, 31 * 8 + 4, 16, 16},
|
||||||
&bitmap_icon_microphone,
|
&bitmap_icon_microphone,
|
||||||
Color::black(),
|
Theme::getInstance()->bg_darkest->background,
|
||||||
Color::black()};
|
Theme::getInstance()->bg_darkest->background};
|
||||||
|
|
||||||
MessageHandlerRegistration message_handler_lcd_sync{
|
MessageHandlerRegistration message_handler_lcd_sync{
|
||||||
Message::ID::DisplayFrameSync,
|
Message::ID::DisplayFrameSync,
|
||||||
|
@ -39,12 +39,12 @@ class ModemSetupView : public View {
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
Labels labels{
|
Labels labels{
|
||||||
{{2 * 8, 11 * 8}, "Baudrate:", Color::light_grey()},
|
{{2 * 8, 11 * 8}, "Baudrate:", Theme::getInstance()->fg_light->foreground},
|
||||||
{{2 * 8, 13 * 8}, "Mark: Hz", Color::light_grey()},
|
{{2 * 8, 13 * 8}, "Mark: Hz", Theme::getInstance()->fg_light->foreground},
|
||||||
{{2 * 8, 15 * 8}, "Space: Hz", Color::light_grey()},
|
{{2 * 8, 15 * 8}, "Space: Hz", Theme::getInstance()->fg_light->foreground},
|
||||||
{{140, 15 * 8}, "Repeat:", Color::light_grey()},
|
{{140, 15 * 8}, "Repeat:", Theme::getInstance()->fg_light->foreground},
|
||||||
{{1 * 8, 6 * 8}, "Modem preset:", Color::light_grey()},
|
{{1 * 8, 6 * 8}, "Modem preset:", Theme::getInstance()->fg_light->foreground},
|
||||||
{{2 * 8, 22 * 8}, "Serial format:", Color::light_grey()}};
|
{{2 * 8, 22 * 8}, "Serial format:", Theme::getInstance()->fg_light->foreground}};
|
||||||
|
|
||||||
NumberField field_baudrate{
|
NumberField field_baudrate{
|
||||||
{11 * 8, 11 * 8},
|
{11 * 8, 11 * 8},
|
||||||
|
@ -21,7 +21,6 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "ui_numbers.hpp"
|
#include "ui_numbers.hpp"
|
||||||
#include "ui_styles.hpp"
|
|
||||||
#include "string_format.hpp"
|
#include "string_format.hpp"
|
||||||
|
|
||||||
#include "portapack.hpp"
|
#include "portapack.hpp"
|
||||||
@ -145,7 +144,7 @@ void NumbersStationView::on_tick_second() {
|
|||||||
armed_blink = not armed_blink;
|
armed_blink = not armed_blink;
|
||||||
|
|
||||||
if (armed_blink)
|
if (armed_blink)
|
||||||
check_armed.set_style(&Styles::red);
|
check_armed.set_style(Theme::getInstance()->fg_red);
|
||||||
else
|
else
|
||||||
check_armed.set_style(&style());
|
check_armed.set_style(&style());
|
||||||
|
|
||||||
|
@ -129,8 +129,8 @@ class NumbersStationView : public View {
|
|||||||
void start_tx();
|
void start_tx();
|
||||||
|
|
||||||
Labels labels{
|
Labels labels{
|
||||||
{{2 * 8, 5 * 8}, "Voice: Flags:", Color::light_grey()},
|
{{2 * 8, 5 * 8}, "Voice: Flags:", Theme::getInstance()->fg_light->foreground},
|
||||||
{{1 * 8, 8 * 8}, "Code:", Color::light_grey()}};
|
{{1 * 8, 8 * 8}, "Code:", Theme::getInstance()->fg_light->foreground}};
|
||||||
|
|
||||||
OptionsField options_voices{
|
OptionsField options_voices{
|
||||||
{8 * 8, 1 * 8},
|
{8 * 8, 1 * 8},
|
||||||
|
@ -141,8 +141,8 @@ class PlaylistView : public View {
|
|||||||
ImageButton button_play{
|
ImageButton button_play{
|
||||||
{28 * 8, 2 * 16, 2 * 8, 1 * 16},
|
{28 * 8, 2 * 16, 2 * 8, 1 * 16},
|
||||||
&bitmap_play,
|
&bitmap_play,
|
||||||
Color::green(),
|
Theme::getInstance()->fg_green->foreground,
|
||||||
Color::black()};
|
Theme::getInstance()->fg_green->background};
|
||||||
|
|
||||||
Text text_track{
|
Text text_track{
|
||||||
{0 * 8, 3 * 16, 30 * 8, 16}};
|
{0 * 8, 3 * 16, 30 * 8, 16}};
|
||||||
@ -151,37 +151,37 @@ class PlaylistView : public View {
|
|||||||
{2 * 8, 4 * 16, 4 * 8, 2 * 16},
|
{2 * 8, 4 * 16, 4 * 8, 2 * 16},
|
||||||
"",
|
"",
|
||||||
&bitmap_arrow_left,
|
&bitmap_arrow_left,
|
||||||
Color::dark_grey()};
|
Theme::getInstance()->bg_dark->background};
|
||||||
|
|
||||||
NewButton button_next{
|
NewButton button_next{
|
||||||
{6 * 8, 4 * 16, 4 * 8, 2 * 16},
|
{6 * 8, 4 * 16, 4 * 8, 2 * 16},
|
||||||
"",
|
"",
|
||||||
&bitmap_arrow_right,
|
&bitmap_arrow_right,
|
||||||
Color::dark_grey()};
|
Theme::getInstance()->bg_dark->background};
|
||||||
|
|
||||||
NewButton button_add{
|
NewButton button_add{
|
||||||
{11 * 8, 4 * 16, 4 * 8, 2 * 16},
|
{11 * 8, 4 * 16, 4 * 8, 2 * 16},
|
||||||
"",
|
"",
|
||||||
&bitmap_icon_new_file,
|
&bitmap_icon_new_file,
|
||||||
Color::orange()};
|
Theme::getInstance()->fg_orange->foreground};
|
||||||
|
|
||||||
NewButton button_delete{
|
NewButton button_delete{
|
||||||
{15 * 8, 4 * 16, 4 * 8, 2 * 16},
|
{15 * 8, 4 * 16, 4 * 8, 2 * 16},
|
||||||
"",
|
"",
|
||||||
&bitmap_icon_delete,
|
&bitmap_icon_delete,
|
||||||
Color::orange()};
|
Theme::getInstance()->fg_orange->foreground};
|
||||||
|
|
||||||
NewButton button_open{
|
NewButton button_open{
|
||||||
{20 * 8, 4 * 16, 4 * 8, 2 * 16},
|
{20 * 8, 4 * 16, 4 * 8, 2 * 16},
|
||||||
"",
|
"",
|
||||||
&bitmap_icon_load,
|
&bitmap_icon_load,
|
||||||
Color::dark_blue()};
|
Theme::getInstance()->fg_blue->foreground};
|
||||||
|
|
||||||
NewButton button_save{
|
NewButton button_save{
|
||||||
{24 * 8, 4 * 16, 4 * 8, 2 * 16},
|
{24 * 8, 4 * 16, 4 * 8, 2 * 16},
|
||||||
"",
|
"",
|
||||||
&bitmap_icon_save,
|
&bitmap_icon_save,
|
||||||
Color::dark_blue()};
|
Theme::getInstance()->fg_blue->foreground};
|
||||||
|
|
||||||
spectrum::WaterfallView waterfall{};
|
spectrum::WaterfallView waterfall{};
|
||||||
|
|
||||||
|
@ -42,6 +42,32 @@ POCSAGTXView::~POCSAGTXView() {
|
|||||||
baseband::shutdown();
|
baseband::shutdown();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void POCSAGTXView::on_remote(const PocsagTosendMessage data) {
|
||||||
|
// check if still sending or not
|
||||||
|
size_t tmp = 0;
|
||||||
|
if (data.baud == 1200) tmp = 1;
|
||||||
|
if (data.baud == 2400) tmp = 2;
|
||||||
|
options_bitrate.set_selected_index(tmp);
|
||||||
|
tmp = 0;
|
||||||
|
options_type.set_selected_index(data.type);
|
||||||
|
if (data.function == 'B') tmp = 1;
|
||||||
|
if (data.function == 'C') tmp = 2;
|
||||||
|
if (data.function == 'D') tmp = 3;
|
||||||
|
options_function.set_selected_index(tmp);
|
||||||
|
options_phase.set_selected_index(data.phase == 'P' ? 0 : 1);
|
||||||
|
field_address.set_value(data.addr);
|
||||||
|
message = (char*)data.msg;
|
||||||
|
text_message.set(message);
|
||||||
|
options_bitrate.dirty();
|
||||||
|
options_type.dirty();
|
||||||
|
options_function.dirty();
|
||||||
|
options_phase.dirty();
|
||||||
|
field_address.dirty();
|
||||||
|
text_message.dirty();
|
||||||
|
tx_view.focus();
|
||||||
|
start_tx();
|
||||||
|
}
|
||||||
|
|
||||||
void POCSAGTXView::on_tx_progress(const uint32_t progress, const bool done) {
|
void POCSAGTXView::on_tx_progress(const uint32_t progress, const bool done) {
|
||||||
if (done) {
|
if (done) {
|
||||||
transmitter_model.disable();
|
transmitter_model.disable();
|
||||||
|
@ -76,15 +76,16 @@ class POCSAGTXView : public View {
|
|||||||
|
|
||||||
void on_set_text(NavigationView& nav);
|
void on_set_text(NavigationView& nav);
|
||||||
void on_tx_progress(const uint32_t progress, const bool done);
|
void on_tx_progress(const uint32_t progress, const bool done);
|
||||||
|
void on_remote(const PocsagTosendMessage data);
|
||||||
bool start_tx();
|
bool start_tx();
|
||||||
|
|
||||||
Labels labels{
|
Labels labels{
|
||||||
{{3 * 8, 4 * 8}, "Bitrate:", Color::light_grey()},
|
{{3 * 8, 4 * 8}, "Bitrate:", Theme::getInstance()->fg_light->foreground},
|
||||||
{{3 * 8, 6 * 8}, "Address:", Color::light_grey()},
|
{{3 * 8, 6 * 8}, "Address:", Theme::getInstance()->fg_light->foreground},
|
||||||
{{6 * 8, 8 * 8}, "Type:", Color::light_grey()},
|
{{6 * 8, 8 * 8}, "Type:", Theme::getInstance()->fg_light->foreground},
|
||||||
{{2 * 8, 10 * 8}, "Function:", Color::light_grey()},
|
{{2 * 8, 10 * 8}, "Function:", Theme::getInstance()->fg_light->foreground},
|
||||||
{{5 * 8, 12 * 8}, "Phase:", Color::light_grey()},
|
{{5 * 8, 12 * 8}, "Phase:", Theme::getInstance()->fg_light->foreground},
|
||||||
{{0 * 8, 14 * 8}, "Message:", Color::light_grey()}};
|
{{0 * 8, 14 * 8}, "Message:", Theme::getInstance()->fg_light->foreground}};
|
||||||
|
|
||||||
OptionsField options_bitrate{
|
OptionsField options_bitrate{
|
||||||
{11 * 8, 4 * 8},
|
{11 * 8, 4 * 8},
|
||||||
@ -142,6 +143,13 @@ class POCSAGTXView : public View {
|
|||||||
const auto message = *reinterpret_cast<const TXProgressMessage*>(p);
|
const auto message = *reinterpret_cast<const TXProgressMessage*>(p);
|
||||||
this->on_tx_progress(message.progress, message.done);
|
this->on_tx_progress(message.progress, message.done);
|
||||||
}};
|
}};
|
||||||
|
|
||||||
|
MessageHandlerRegistration message_handler_tx_remote{
|
||||||
|
Message::ID::PocsagTosend,
|
||||||
|
[this](const Message* const p) {
|
||||||
|
const auto message = *reinterpret_cast<const PocsagTosendMessage*>(p);
|
||||||
|
this->on_remote(message);
|
||||||
|
}};
|
||||||
};
|
};
|
||||||
|
|
||||||
} /* namespace ui */
|
} /* namespace ui */
|
||||||
|
@ -43,8 +43,8 @@ class RDSPSNView : public OptionTabView {
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
Labels labels{
|
Labels labels{
|
||||||
{{1 * 8, 3 * 8}, "Program Service Name", Color::light_grey()},
|
{{1 * 8, 3 * 8}, "Program Service Name", Theme::getInstance()->fg_light->foreground},
|
||||||
{{2 * 8, 7 * 8}, "PSN:", Color::light_grey()}};
|
{{2 * 8, 7 * 8}, "PSN:", Theme::getInstance()->fg_light->foreground}};
|
||||||
|
|
||||||
Button button_set{
|
Button button_set{
|
||||||
{18 * 8, 3 * 16, 80, 32},
|
{18 * 8, 3 * 16, 80, 32},
|
||||||
@ -75,8 +75,8 @@ class RDSRadioTextView : public OptionTabView {
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
Labels labels{
|
Labels labels{
|
||||||
{{2 * 8, 3 * 8}, "Radiotext", Color::light_grey()},
|
{{2 * 8, 3 * 8}, "Radiotext", Theme::getInstance()->fg_light->foreground},
|
||||||
{{1 * 8, 6 * 8}, "Text:", Color::light_grey()}};
|
{{1 * 8, 6 * 8}, "Text:", Theme::getInstance()->fg_light->foreground}};
|
||||||
|
|
||||||
Text text_radiotext{
|
Text text_radiotext{
|
||||||
{1 * 8, 4 * 16, 28 * 8, 16},
|
{1 * 8, 4 * 16, 28 * 8, 16},
|
||||||
@ -92,7 +92,7 @@ class RDSDateTimeView : public OptionTabView {
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
Labels labels{
|
Labels labels{
|
||||||
{{44, 5 * 16}, "Not yet implemented", Color::red()}};
|
{{44, 5 * 16}, "Not yet implemented", Theme::getInstance()->error_dark->foreground}};
|
||||||
};
|
};
|
||||||
|
|
||||||
class RDSAudioView : public OptionTabView {
|
class RDSAudioView : public OptionTabView {
|
||||||
@ -101,7 +101,7 @@ class RDSAudioView : public OptionTabView {
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
Labels labels{
|
Labels labels{
|
||||||
{{44, 5 * 16}, "Not yet implemented", Color::red()}};
|
{{44, 5 * 16}, "Not yet implemented", Theme::getInstance()->error_dark->foreground}};
|
||||||
};
|
};
|
||||||
|
|
||||||
class RDSThread {
|
class RDSThread {
|
||||||
@ -168,16 +168,16 @@ class RDSView : public View {
|
|||||||
RDSAudioView view_audio{view_rect};
|
RDSAudioView view_audio{view_rect};
|
||||||
|
|
||||||
TabView tab_view{
|
TabView tab_view{
|
||||||
{"Name", Color::cyan(), &view_PSN},
|
{"Name", Theme::getInstance()->fg_cyan->foreground, &view_PSN},
|
||||||
{"Text", Color::green(), &view_radiotext},
|
{"Text", Theme::getInstance()->fg_green->foreground, &view_radiotext},
|
||||||
{"Time", Color::yellow(), &view_datetime},
|
{"Time", Theme::getInstance()->fg_yellow->foreground, &view_datetime},
|
||||||
{"Audio", Color::orange(), &view_audio}};
|
{"Audio", Theme::getInstance()->fg_orange->foreground, &view_audio}};
|
||||||
|
|
||||||
Labels labels{
|
Labels labels{
|
||||||
{{0 * 8, 28}, "Program type:", Color::light_grey()},
|
{{0 * 8, 28}, "Program type:", Theme::getInstance()->fg_light->foreground},
|
||||||
//{ { 14 * 8, 16 + 8 }, "CC:", Color::light_grey() },
|
//{ { 14 * 8, 16 + 8 }, "CC:", Theme::getInstance()->fg_light->foreground },
|
||||||
{{2 * 8, 28 + 16}, "Program ID:", Color::light_grey()},
|
{{2 * 8, 28 + 16}, "Program ID:", Theme::getInstance()->fg_light->foreground},
|
||||||
//{ { 13 * 8, 32 + 8 }, "Cov:", Color::light_grey() },
|
//{ { 13 * 8, 32 + 8 }, "Cov:",Theme::getInstance()->fg_light->foreground },
|
||||||
};
|
};
|
||||||
|
|
||||||
OptionsField options_pty{
|
OptionsField options_pty{
|
||||||
|
@ -65,16 +65,16 @@ void ReconView::reload_restart_recon() {
|
|||||||
recon_resume();
|
recon_resume();
|
||||||
}
|
}
|
||||||
if (scanner_mode) {
|
if (scanner_mode) {
|
||||||
file_name.set_style(&Styles::red);
|
file_name.set_style(Theme::getInstance()->fg_red);
|
||||||
button_scanner_mode.set_style(&Styles::red);
|
button_scanner_mode.set_style(Theme::getInstance()->fg_red);
|
||||||
button_scanner_mode.set_text("SCAN");
|
button_scanner_mode.set_text("SCAN");
|
||||||
} else {
|
} else {
|
||||||
file_name.set_style(&Styles::blue);
|
file_name.set_style(Theme::getInstance()->fg_blue);
|
||||||
button_scanner_mode.set_style(&Styles::blue);
|
button_scanner_mode.set_style(Theme::getInstance()->fg_blue);
|
||||||
button_scanner_mode.set_text("RECON");
|
button_scanner_mode.set_text("RECON");
|
||||||
}
|
}
|
||||||
if (frequency_list.size() > FREQMAN_MAX_PER_FILE) {
|
if (frequency_list.size() > FREQMAN_MAX_PER_FILE) {
|
||||||
file_name.set_style(&Styles::yellow);
|
file_name.set_style(Theme::getInstance()->fg_yellow);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -104,7 +104,7 @@ freqman_entry& ReconView::current_entry() {
|
|||||||
|
|
||||||
void ReconView::set_loop_config(bool v) {
|
void ReconView::set_loop_config(bool v) {
|
||||||
continuous = v;
|
continuous = v;
|
||||||
button_loop_config.set_style(v ? &Styles::green : &Styles::white);
|
button_loop_config.set_style(v ? Theme::getInstance()->fg_green : Theme::getInstance()->bg_darkest);
|
||||||
persistent_memory::set_recon_continuous(continuous);
|
persistent_memory::set_recon_continuous(continuous);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -121,8 +121,8 @@ void ReconView::recon_stop_recording(bool exiting) {
|
|||||||
} else {
|
} else {
|
||||||
button_audio_app.set_text("AUDIO");
|
button_audio_app.set_text("AUDIO");
|
||||||
}
|
}
|
||||||
button_audio_app.set_style(&Styles::white);
|
button_audio_app.set_style(Theme::getInstance()->bg_darkest);
|
||||||
button_config.set_style(&Styles::white);
|
button_config.set_style(Theme::getInstance()->bg_darkest);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -171,23 +171,23 @@ void ReconView::update_description() {
|
|||||||
void ReconView::colorize_waits() {
|
void ReconView::colorize_waits() {
|
||||||
// colorize wait on match
|
// colorize wait on match
|
||||||
if (wait == 0) {
|
if (wait == 0) {
|
||||||
field_wait.set_style(&Styles::blue);
|
field_wait.set_style(Theme::getInstance()->fg_blue);
|
||||||
} else if (wait >= 500) {
|
} else if (wait >= 500) {
|
||||||
field_wait.set_style(&Styles::white);
|
field_wait.set_style(Theme::getInstance()->bg_darkest);
|
||||||
} else if (wait > -500 && wait < 500) {
|
} else if (wait > -500 && wait < 500) {
|
||||||
field_wait.set_style(&Styles::red);
|
field_wait.set_style(Theme::getInstance()->fg_red);
|
||||||
} else if (wait <= -500) {
|
} else if (wait <= -500) {
|
||||||
field_wait.set_style(&Styles::green);
|
field_wait.set_style(Theme::getInstance()->fg_green);
|
||||||
}
|
}
|
||||||
// colorize lock time if in SPARSE mode as in continuous the lock_wait time is disarmed at first lock count
|
// colorize lock time if in SPARSE mode as in continuous the lock_wait time is disarmed at first lock count
|
||||||
if (recon_match_mode == RECON_MATCH_SPARSE) {
|
if (recon_match_mode == RECON_MATCH_SPARSE) {
|
||||||
if ((recon_lock_duration / STATS_UPDATE_INTERVAL) <= recon_lock_nb_match) {
|
if ((recon_lock_duration / STATS_UPDATE_INTERVAL) <= recon_lock_nb_match) {
|
||||||
field_lock_wait.set_style(&Styles::yellow);
|
field_lock_wait.set_style(Theme::getInstance()->fg_yellow);
|
||||||
} else {
|
} else {
|
||||||
field_lock_wait.set_style(&Styles::white);
|
field_lock_wait.set_style(Theme::getInstance()->bg_darkest);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
field_lock_wait.set_style(&Styles::white);
|
field_lock_wait.set_style(Theme::getInstance()->bg_darkest);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -259,17 +259,17 @@ void ReconView::recon_redraw() {
|
|||||||
text_nb_locks.set(to_string_dec_uint(freq_lock) + "/" + to_string_dec_uint(recon_lock_nb_match));
|
text_nb_locks.set(to_string_dec_uint(freq_lock) + "/" + to_string_dec_uint(recon_lock_nb_match));
|
||||||
if (freq_lock == 0) {
|
if (freq_lock == 0) {
|
||||||
// NO FREQ LOCK, ONGOING STANDARD SCANNING
|
// NO FREQ LOCK, ONGOING STANDARD SCANNING
|
||||||
big_display.set_style(&Styles::white);
|
big_display.set_style(Theme::getInstance()->bg_darkest);
|
||||||
if (recon)
|
if (recon)
|
||||||
button_pause.set_text("<PAUSE>");
|
button_pause.set_text("<PAUSE>");
|
||||||
else
|
else
|
||||||
button_pause.set_text("<RESUME>");
|
button_pause.set_text("<RESUME>");
|
||||||
} else if (freq_lock == 1 && recon_lock_nb_match != 1) {
|
} else if (freq_lock == 1 && recon_lock_nb_match != 1) {
|
||||||
// STARTING LOCK FREQ
|
// STARTING LOCK FREQ
|
||||||
big_display.set_style(&Styles::yellow);
|
big_display.set_style(Theme::getInstance()->fg_yellow);
|
||||||
button_pause.set_text("<SKPLCK>");
|
button_pause.set_text("<SKPLCK>");
|
||||||
} else if (freq_lock >= recon_lock_nb_match) {
|
} else if (freq_lock >= recon_lock_nb_match) {
|
||||||
big_display.set_style(&Styles::green);
|
big_display.set_style(Theme::getInstance()->fg_green);
|
||||||
button_pause.set_text("<UNLOCK>");
|
button_pause.set_text("<UNLOCK>");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -591,18 +591,18 @@ ReconView::ReconView(NavigationView& nav)
|
|||||||
current_entry().bandwidth = freqman_invalid_index;
|
current_entry().bandwidth = freqman_invalid_index;
|
||||||
current_entry().step = def_step;
|
current_entry().step = def_step;
|
||||||
|
|
||||||
big_display.set_style(&Styles::white); // Back to white color
|
big_display.set_style(Theme::getInstance()->bg_darkest); // Back to white color
|
||||||
|
|
||||||
freq_stats.set_style(&Styles::white);
|
freq_stats.set_style(Theme::getInstance()->bg_darkest);
|
||||||
freq_stats.set("0/0/0");
|
freq_stats.set("0/0/0");
|
||||||
|
|
||||||
text_cycle.set_text("1");
|
text_cycle.set_text("1");
|
||||||
text_max.set("/1");
|
text_max.set("/1");
|
||||||
button_scanner_mode.set_style(&Styles::white);
|
button_scanner_mode.set_style(Theme::getInstance()->bg_darkest);
|
||||||
button_scanner_mode.set_text("MANUAL");
|
button_scanner_mode.set_text("MANUAL");
|
||||||
file_name.set_style(&Styles::white);
|
file_name.set_style(Theme::getInstance()->bg_darkest);
|
||||||
file_name.set("MANUAL => " + output_file);
|
file_name.set("MANUAL => " + output_file);
|
||||||
desc_cycle.set_style(&Styles::white);
|
desc_cycle.set_style(Theme::getInstance()->bg_darkest);
|
||||||
|
|
||||||
last_entry.modulation = freqman_invalid_index;
|
last_entry.modulation = freqman_invalid_index;
|
||||||
last_entry.bandwidth = freqman_invalid_index;
|
last_entry.bandwidth = freqman_invalid_index;
|
||||||
@ -648,12 +648,12 @@ ReconView::ReconView(NavigationView& nav)
|
|||||||
manual_mode = false;
|
manual_mode = false;
|
||||||
if (scanner_mode) {
|
if (scanner_mode) {
|
||||||
scanner_mode = false;
|
scanner_mode = false;
|
||||||
button_scanner_mode.set_style(&Styles::blue);
|
button_scanner_mode.set_style(Theme::getInstance()->fg_blue);
|
||||||
button_scanner_mode.set_text("RECON");
|
button_scanner_mode.set_text("RECON");
|
||||||
button_remove.set_text("<REMOVE>");
|
button_remove.set_text("<REMOVE>");
|
||||||
} else {
|
} else {
|
||||||
scanner_mode = true;
|
scanner_mode = true;
|
||||||
button_scanner_mode.set_style(&Styles::red);
|
button_scanner_mode.set_style(Theme::getInstance()->fg_red);
|
||||||
button_scanner_mode.set_text("SCAN");
|
button_scanner_mode.set_text("SCAN");
|
||||||
button_remove.set_text("<DELETE>");
|
button_remove.set_text("<DELETE>");
|
||||||
}
|
}
|
||||||
@ -726,7 +726,7 @@ ReconView::ReconView(NavigationView& nav)
|
|||||||
};
|
};
|
||||||
|
|
||||||
// PRE-CONFIGURATION:
|
// PRE-CONFIGURATION:
|
||||||
button_scanner_mode.set_style(&Styles::blue);
|
button_scanner_mode.set_style(Theme::getInstance()->fg_blue);
|
||||||
button_scanner_mode.set_text("RECON");
|
button_scanner_mode.set_text("RECON");
|
||||||
file_name.set("=>");
|
file_name.set("=>");
|
||||||
|
|
||||||
@ -772,14 +772,14 @@ void ReconView::frequency_file_load() {
|
|||||||
std::string file_input = input_file; // default recon mode
|
std::string file_input = input_file; // default recon mode
|
||||||
if (scanner_mode) {
|
if (scanner_mode) {
|
||||||
file_input = output_file;
|
file_input = output_file;
|
||||||
file_name.set_style(&Styles::red);
|
file_name.set_style(Theme::getInstance()->fg_red);
|
||||||
button_scanner_mode.set_style(&Styles::red);
|
button_scanner_mode.set_style(Theme::getInstance()->fg_red);
|
||||||
desc_cycle.set_style(&Styles::red);
|
desc_cycle.set_style(Theme::getInstance()->fg_red);
|
||||||
button_scanner_mode.set_text("SCAN");
|
button_scanner_mode.set_text("SCAN");
|
||||||
} else {
|
} else {
|
||||||
file_name.set_style(&Styles::blue);
|
file_name.set_style(Theme::getInstance()->fg_blue);
|
||||||
button_scanner_mode.set_style(&Styles::blue);
|
button_scanner_mode.set_style(Theme::getInstance()->fg_blue);
|
||||||
desc_cycle.set_style(&Styles::blue);
|
desc_cycle.set_style(Theme::getInstance()->fg_blue);
|
||||||
button_scanner_mode.set_text("RECON");
|
button_scanner_mode.set_text("RECON");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -791,7 +791,7 @@ void ReconView::frequency_file_load() {
|
|||||||
.load_hamradios = load_hamradios,
|
.load_hamradios = load_hamradios,
|
||||||
.load_repeaters = load_repeaters};
|
.load_repeaters = load_repeaters};
|
||||||
if (!load_freqman_file(file_input, frequency_list, options) || frequency_list.empty()) {
|
if (!load_freqman_file(file_input, frequency_list, options) || frequency_list.empty()) {
|
||||||
file_name.set_style(&Styles::red);
|
file_name.set_style(Theme::getInstance()->fg_red);
|
||||||
desc_cycle.set("...empty file...");
|
desc_cycle.set("...empty file...");
|
||||||
frequency_list.clear();
|
frequency_list.clear();
|
||||||
text_cycle.set_text(" ");
|
text_cycle.set_text(" ");
|
||||||
@ -799,7 +799,7 @@ void ReconView::frequency_file_load() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (frequency_list.size() > FREQMAN_MAX_PER_FILE) {
|
if (frequency_list.size() > FREQMAN_MAX_PER_FILE) {
|
||||||
file_name.set_style(&Styles::yellow);
|
file_name.set_style(Theme::getInstance()->fg_yellow);
|
||||||
}
|
}
|
||||||
|
|
||||||
reset_indexes();
|
reset_indexes();
|
||||||
@ -888,13 +888,13 @@ void ReconView::on_statistics_update(const ChannelStatistics& statistics) {
|
|||||||
audio_output_start();
|
audio_output_start();
|
||||||
// contents of a possible recon_start_recording(), but not yet since it's only called once
|
// contents of a possible recon_start_recording(), but not yet since it's only called once
|
||||||
if (auto_record_locked && !is_recording) {
|
if (auto_record_locked && !is_recording) {
|
||||||
button_audio_app.set_style(&Styles::red);
|
button_audio_app.set_style(Theme::getInstance()->fg_red);
|
||||||
if (field_mode.selected_index_value() == SPEC_MODULATION) {
|
if (field_mode.selected_index_value() == SPEC_MODULATION) {
|
||||||
button_audio_app.set_text("RAW REC");
|
button_audio_app.set_text("RAW REC");
|
||||||
} else
|
} else
|
||||||
button_audio_app.set_text("WAV REC");
|
button_audio_app.set_text("WAV REC");
|
||||||
record_view->start();
|
record_view->start();
|
||||||
button_config.set_style(&Styles::light_grey); // disable config while recording as it's causing an IO error pop up at exit
|
button_config.set_style(Theme::getInstance()->fg_light); // disable config while recording as it's causing an IO error pop up at exit
|
||||||
is_recording = true;
|
is_recording = true;
|
||||||
}
|
}
|
||||||
// FREQ IS STRONG: GREEN and recon will pause when on_statistics_update()
|
// FREQ IS STRONG: GREEN and recon will pause when on_statistics_update()
|
||||||
@ -1106,7 +1106,7 @@ void ReconView::recon_pause() {
|
|||||||
if (field_mode.selected_index_value() != SPEC_MODULATION)
|
if (field_mode.selected_index_value() != SPEC_MODULATION)
|
||||||
audio_output_start();
|
audio_output_start();
|
||||||
|
|
||||||
big_display.set_style(&Styles::white);
|
big_display.set_style(Theme::getInstance()->bg_darkest);
|
||||||
button_pause.set_text("<RESUME>"); // PAUSED, show resume
|
button_pause.set_text("<RESUME>"); // PAUSED, show resume
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1118,7 +1118,7 @@ void ReconView::recon_resume() {
|
|||||||
if (field_mode.selected_index_value() != SPEC_MODULATION)
|
if (field_mode.selected_index_value() != SPEC_MODULATION)
|
||||||
audio::output::stop();
|
audio::output::stop();
|
||||||
|
|
||||||
big_display.set_style(&Styles::white);
|
big_display.set_style(Theme::getInstance()->bg_darkest);
|
||||||
button_pause.set_text("<PAUSE>");
|
button_pause.set_text("<PAUSE>");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1401,8 +1401,8 @@ void ReconView::start_repeat() {
|
|||||||
std::string delay_message = "TX DELAY: " + to_string_dec_uint(delay) + "s";
|
std::string delay_message = "TX DELAY: " + to_string_dec_uint(delay) + "s";
|
||||||
|
|
||||||
// update display information
|
// update display information
|
||||||
p.fill_rectangle({0, (SCREEN_H / 2) - 16, SCREEN_W, 64}, Color::light_grey());
|
p.fill_rectangle({0, (SCREEN_H / 2) - 16, SCREEN_W, 64}, Theme::getInstance()->fg_light->foreground);
|
||||||
p.draw_string({(SCREEN_W / 2) - 7 * 8, SCREEN_H / 2}, Styles::red, delay_message);
|
p.draw_string({(SCREEN_W / 2) - 7 * 8, SCREEN_H / 2}, *Theme::getInstance()->fg_red, delay_message);
|
||||||
|
|
||||||
// sleep 1 second
|
// sleep 1 second
|
||||||
chThdSleepMilliseconds(1000);
|
chThdSleepMilliseconds(1000);
|
||||||
|
@ -27,7 +27,6 @@
|
|||||||
#include "ui.hpp"
|
#include "ui.hpp"
|
||||||
#include "receiver_model.hpp"
|
#include "receiver_model.hpp"
|
||||||
#include "ui_receiver.hpp"
|
#include "ui_receiver.hpp"
|
||||||
#include "ui_styles.hpp"
|
|
||||||
#include "freqman.hpp"
|
#include "freqman.hpp"
|
||||||
#include "analog_audio_app.hpp"
|
#include "analog_audio_app.hpp"
|
||||||
#include "audio.hpp"
|
#include "audio.hpp"
|
||||||
@ -219,11 +218,11 @@ class ReconView : public View {
|
|||||||
std::unique_ptr<RecordView> record_view{};
|
std::unique_ptr<RecordView> record_view{};
|
||||||
|
|
||||||
Labels labels{
|
Labels labels{
|
||||||
{{0 * 8, 0 * 16}, "LNA: VGA: AMP: VOL: ", Color::light_grey()},
|
{{0 * 8, 0 * 16}, "LNA: VGA: AMP: VOL: ", Theme::getInstance()->fg_light->foreground},
|
||||||
{{3 * 8, 8 * 16}, "START END", Color::light_grey()},
|
{{3 * 8, 8 * 16}, "START END", Theme::getInstance()->fg_light->foreground},
|
||||||
{{0 * 8, (22 * 8)}, " S: ", Color::light_grey()},
|
{{0 * 8, (22 * 8)}, " S: ", Theme::getInstance()->fg_light->foreground},
|
||||||
{{0 * 8, (24 * 8) + 4}, "NBLCKS:x W,L: , ", Color::light_grey()},
|
{{0 * 8, (24 * 8) + 4}, "NBLCKS:x W,L: , ", Theme::getInstance()->fg_light->foreground},
|
||||||
{{0 * 8, (26 * 8) + 4}, "MODE: , SQUELCH: ", Color::light_grey()}};
|
{{0 * 8, (26 * 8) + 4}, "MODE: , SQUELCH: ", Theme::getInstance()->fg_light->foreground}};
|
||||||
|
|
||||||
LNAGainField field_lna{
|
LNAGainField field_lna{
|
||||||
{4 * 8, 0 * 16}};
|
{4 * 8, 0 * 16}};
|
||||||
|
@ -137,15 +137,15 @@ ReconSetupViewMore::ReconSetupViewMore(NavigationView& nav, Rect parent_rect)
|
|||||||
&field_repeat_delay});
|
&field_repeat_delay});
|
||||||
|
|
||||||
// tx options have to be in yellow to inform the users that activating them will make the device transmit
|
// tx options have to be in yellow to inform the users that activating them will make the device transmit
|
||||||
checkbox_repeat_recorded.set_style(&Styles::yellow);
|
checkbox_repeat_recorded.set_style(Theme::getInstance()->fg_yellow);
|
||||||
field_repeat_file_mode.set_style(&Styles::yellow);
|
field_repeat_file_mode.set_style(Theme::getInstance()->fg_yellow);
|
||||||
text_repeat_nb.set_style(&Styles::yellow);
|
text_repeat_nb.set_style(Theme::getInstance()->fg_yellow);
|
||||||
field_repeat_nb.set_style(&Styles::yellow);
|
field_repeat_nb.set_style(Theme::getInstance()->fg_yellow);
|
||||||
checkbox_repeat_amp.set_style(&Styles::yellow);
|
checkbox_repeat_amp.set_style(Theme::getInstance()->fg_yellow);
|
||||||
text_repeat_gain.set_style(&Styles::yellow);
|
text_repeat_gain.set_style(Theme::getInstance()->fg_yellow);
|
||||||
field_repeat_gain.set_style(&Styles::yellow);
|
field_repeat_gain.set_style(Theme::getInstance()->fg_yellow);
|
||||||
text_repeat_delay.set_style(&Styles::yellow);
|
text_repeat_delay.set_style(Theme::getInstance()->fg_yellow);
|
||||||
field_repeat_delay.set_style(&Styles::yellow);
|
field_repeat_delay.set_style(Theme::getInstance()->fg_yellow);
|
||||||
|
|
||||||
checkbox_load_freqs.set_value(persistent_memory::recon_load_freqs());
|
checkbox_load_freqs.set_value(persistent_memory::recon_load_freqs());
|
||||||
checkbox_load_repeaters.set_value(persistent_memory::recon_load_repeaters());
|
checkbox_load_repeaters.set_value(persistent_memory::recon_load_repeaters());
|
||||||
|
@ -30,7 +30,6 @@
|
|||||||
#include "ui_tabview.hpp"
|
#include "ui_tabview.hpp"
|
||||||
#include "ui_navigation.hpp"
|
#include "ui_navigation.hpp"
|
||||||
#include "string_format.hpp"
|
#include "string_format.hpp"
|
||||||
#include "ui_styles.hpp"
|
|
||||||
|
|
||||||
// 1Mhz helper
|
// 1Mhz helper
|
||||||
#ifdef OneMHz
|
#ifdef OneMHz
|
||||||
@ -226,8 +225,8 @@ class ReconSetupView : public View {
|
|||||||
ReconSetupViewMore viewMore{nav_, view_rect};
|
ReconSetupViewMore viewMore{nav_, view_rect};
|
||||||
|
|
||||||
TabView tab_view{
|
TabView tab_view{
|
||||||
{"Main", Color::cyan(), &viewMain},
|
{"Main", Theme::getInstance()->fg_cyan->foreground, &viewMain},
|
||||||
{"More", Color::green(), &viewMore}};
|
{"More", Theme::getInstance()->fg_green->foreground, &viewMore}};
|
||||||
|
|
||||||
Button button_save{
|
Button button_save{
|
||||||
{9 * 8, 255, 14 * 8, 40},
|
{9 * 8, 255, 14 * 8, 40},
|
||||||
|
@ -177,11 +177,11 @@ void RemoteButton::paint(Painter& painter) {
|
|||||||
// Add a border on the highlighted button.
|
// Add a border on the highlighted button.
|
||||||
if (has_focus() || highlighted()) {
|
if (has_focus() || highlighted()) {
|
||||||
auto r = screen_rect();
|
auto r = screen_rect();
|
||||||
painter.draw_rectangle(r, Color::white());
|
painter.draw_rectangle(r, Theme::getInstance()->bg_darkest->foreground);
|
||||||
|
|
||||||
auto p = r.location() + Point{1, 1};
|
auto p = r.location() + Point{1, 1};
|
||||||
auto s = Size{r.size().width() - 2, r.size().height() - 2};
|
auto s = Size{r.size().width() - 2, r.size().height() - 2};
|
||||||
painter.draw_rectangle({p, s}, Color::light_grey());
|
painter.draw_rectangle({p, s}, Theme::getInstance()->fg_light->foreground);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -200,15 +200,15 @@ class RemoteEntryEditView : public View {
|
|||||||
void load_path(std::filesystem::path&& path);
|
void load_path(std::filesystem::path&& path);
|
||||||
|
|
||||||
Labels labels{
|
Labels labels{
|
||||||
{{2 * 8, 1 * 16}, "Name:", Color::light_grey()},
|
{{2 * 8, 1 * 16}, "Name:", Theme::getInstance()->fg_light->foreground},
|
||||||
{{2 * 8, 2 * 16}, "Path:", Color::light_grey()},
|
{{2 * 8, 2 * 16}, "Path:", Theme::getInstance()->fg_light->foreground},
|
||||||
{{2 * 8, 3 * 16}, "Freq:", Color::light_grey()},
|
{{2 * 8, 3 * 16}, "Freq:", Theme::getInstance()->fg_light->foreground},
|
||||||
{{17 * 8, 3 * 16}, "MHz", Color::light_grey()},
|
{{17 * 8, 3 * 16}, "MHz", Theme::getInstance()->fg_light->foreground},
|
||||||
{{2 * 8, 4 * 16}, "Rate:", Color::light_grey()},
|
{{2 * 8, 4 * 16}, "Rate:", Theme::getInstance()->fg_light->foreground},
|
||||||
{{2 * 8, 5 * 16}, "Icon:", Color::light_grey()},
|
{{2 * 8, 5 * 16}, "Icon:", Theme::getInstance()->fg_light->foreground},
|
||||||
{{2 * 8, 6 * 16}, "FG Color:", Color::light_grey()},
|
{{2 * 8, 6 * 16}, "FG Color:", Theme::getInstance()->fg_light->foreground},
|
||||||
{{2 * 8, 7 * 16}, "BG Color:", Color::light_grey()},
|
{{2 * 8, 7 * 16}, "BG Color:", Theme::getInstance()->fg_light->foreground},
|
||||||
{{8 * 8, 9 * 16}, "Button preview", Color::light_grey()},
|
{{8 * 8, 9 * 16}, "Button preview", Theme::getInstance()->fg_light->foreground},
|
||||||
};
|
};
|
||||||
|
|
||||||
TextField field_name{{8 * 8, 1 * 16, 20 * 8, 1 * 16}, {}};
|
TextField field_name{{8 * 8, 1 * 16, 20 * 8, 1 * 16}, {}};
|
||||||
|
@ -185,16 +185,16 @@ void ScannerView::bigdisplay_update(int32_t v) {
|
|||||||
|
|
||||||
switch (bigdisplay_current_color) {
|
switch (bigdisplay_current_color) {
|
||||||
case BDC_GREY:
|
case BDC_GREY:
|
||||||
big_display.set_style(&Styles::grey);
|
big_display.set_style(Theme::getInstance()->fg_medium);
|
||||||
break;
|
break;
|
||||||
case BDC_YELLOW:
|
case BDC_YELLOW:
|
||||||
big_display.set_style(&Styles::yellow);
|
big_display.set_style(Theme::getInstance()->fg_yellow);
|
||||||
break;
|
break;
|
||||||
case BDC_GREEN:
|
case BDC_GREEN:
|
||||||
big_display.set_style(&Styles::green);
|
big_display.set_style(Theme::getInstance()->fg_green);
|
||||||
break;
|
break;
|
||||||
case BDC_RED:
|
case BDC_RED:
|
||||||
big_display.set_style(&Styles::red);
|
big_display.set_style(Theme::getInstance()->fg_red);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
@ -280,10 +280,10 @@ 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) {
|
if (entries.size() == FREQMAN_MAX_PER_FILE) {
|
||||||
text_max_index.set_style(&Styles::red);
|
text_max_index.set_style(Theme::getInstance()->fg_red);
|
||||||
text_max_index.set("/ " + to_string_dec_uint(FREQMAN_MAX_PER_FILE) + " (DB MAX!)");
|
text_max_index.set("/ " + to_string_dec_uint(FREQMAN_MAX_PER_FILE) + " (DB MAX!)");
|
||||||
} else {
|
} else {
|
||||||
text_max_index.set_style(&Styles::grey);
|
text_max_index.set_style(Theme::getInstance()->fg_medium);
|
||||||
text_max_index.set("/ " + to_string_dec_uint(entries.size()));
|
text_max_index.set("/ " + to_string_dec_uint(entries.size()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -34,7 +34,6 @@
|
|||||||
#include "ui.hpp"
|
#include "ui.hpp"
|
||||||
#include "ui_mictx.hpp"
|
#include "ui_mictx.hpp"
|
||||||
#include "ui_receiver.hpp"
|
#include "ui_receiver.hpp"
|
||||||
#include "ui_styles.hpp"
|
|
||||||
|
|
||||||
#define SCANNER_SLEEP_MS 50 // ms that Scanner Thread sleeps per loop
|
#define SCANNER_SLEEP_MS 50 // ms that Scanner Thread sleeps per loop
|
||||||
#define STATISTICS_UPDATES_PER_SEC 10
|
#define STATISTICS_UPDATES_PER_SEC 10
|
||||||
@ -172,12 +171,12 @@ class ScannerView : public View {
|
|||||||
};
|
};
|
||||||
|
|
||||||
Labels labels{
|
Labels labels{
|
||||||
{{0 * 8, 0 * 16}, "LNA: VGA: AMP: VOL:", Color::light_grey()},
|
{{0 * 8, 0 * 16}, "LNA: VGA: AMP: VOL:", Theme::getInstance()->fg_light->foreground},
|
||||||
{{0 * 8, 1 * 16}, "BW: SQ: Wsa: Wsl:", Color::light_grey()},
|
{{0 * 8, 1 * 16}, "BW: SQ: Wsa: Wsl:", Theme::getInstance()->fg_light->foreground},
|
||||||
{{0 * 8, 10 * 16}, "SRCH START SEARCH END SWITCH", Color::light_grey()},
|
{{0 * 8, 10 * 16}, "SRCH START SEARCH END SWITCH", Theme::getInstance()->fg_light->foreground},
|
||||||
|
|
||||||
{{0 * 8, (26 * 8) + 4}, "MODE:", Color::light_grey()},
|
{{0 * 8, (26 * 8) + 4}, "MODE:", Theme::getInstance()->fg_light->foreground},
|
||||||
{{11 * 8, (26 * 8) + 4}, "STEP:", Color::light_grey()},
|
{{11 * 8, (26 * 8) + 4}, "STEP:", Theme::getInstance()->fg_light->foreground},
|
||||||
};
|
};
|
||||||
|
|
||||||
LNAGainField field_lna{
|
LNAGainField field_lna{
|
||||||
|
@ -56,7 +56,7 @@ void ScriptView::setup_list() {
|
|||||||
menu_view.clear();
|
menu_view.clear();
|
||||||
|
|
||||||
/*for (n = 0; n < frequencies.size(); n++) {
|
/*for (n = 0; n < frequencies.size(); n++) {
|
||||||
menu_view.add_item({ freqman_item_string(frequencies[n]), ui::Color::white(), nullptr, [this](){ on_frequency_select(); } });
|
menu_view.add_item({ freqman_item_string(frequencies[n]), Theme::getInstance()->bg_darkest->foreground, nullptr, [this](){ on_frequency_select(); } });
|
||||||
}*/
|
}*/
|
||||||
|
|
||||||
menu_view.set_parent_rect({0, 0, 240, 168});
|
menu_view.set_parent_rect({0, 0, 240, 168});
|
||||||
|
@ -34,13 +34,13 @@ SdOverUsbView::SdOverUsbView(NavigationView& nav)
|
|||||||
ui::Painter painter;
|
ui::Painter painter;
|
||||||
painter.fill_rectangle(
|
painter.fill_rectangle(
|
||||||
{0, 0, portapack::display.width(), portapack::display.height()},
|
{0, 0, portapack::display.width(), portapack::display.height()},
|
||||||
ui::Color::black());
|
Theme::getInstance()->bg_darkest->background);
|
||||||
|
|
||||||
painter.draw_bitmap(
|
painter.draw_bitmap(
|
||||||
{portapack::display.width() / 2 - 8, portapack::display.height() / 2 - 8},
|
{portapack::display.width() / 2 - 8, portapack::display.height() / 2 - 8},
|
||||||
bitmap_icon_hackrf,
|
bitmap_icon_hackrf,
|
||||||
ui::Color::yellow(),
|
Theme::getInstance()->bg_darkest->foreground,
|
||||||
ui::Color::black());
|
Theme::getInstance()->bg_darkest->background);
|
||||||
|
|
||||||
sdcDisconnect(&SDCD1);
|
sdcDisconnect(&SDCD1);
|
||||||
sdcStop(&SDCD1);
|
sdcStop(&SDCD1);
|
||||||
|
@ -46,11 +46,11 @@ class SdOverUsbView : public View {
|
|||||||
NavigationView& nav_;
|
NavigationView& nav_;
|
||||||
|
|
||||||
Labels labels{
|
Labels labels{
|
||||||
{{3 * 8, 2 * 16}, "Click Run to start the", Color::white()},
|
{{3 * 8, 2 * 16}, "Click Run to start the", Theme::getInstance()->bg_darkest->foreground},
|
||||||
{{3 * 8, 3 * 16}, "USB Mass Storage Mode.", Color::white()},
|
{{3 * 8, 3 * 16}, "USB Mass Storage Mode.", Theme::getInstance()->bg_darkest->foreground},
|
||||||
{{3 * 8, 5 * 16}, "It can take up to 20s", Color::white()},
|
{{3 * 8, 5 * 16}, "It can take up to 20s", Theme::getInstance()->bg_darkest->foreground},
|
||||||
{{3 * 8, 6 * 16}, "for the drive to be", Color::white()},
|
{{3 * 8, 6 * 16}, "for the drive to be", Theme::getInstance()->bg_darkest->foreground},
|
||||||
{{3 * 8, 7 * 16}, "available.", Color::white()},
|
{{3 * 8, 7 * 16}, "available.", Theme::getInstance()->bg_darkest->foreground},
|
||||||
};
|
};
|
||||||
|
|
||||||
Button button_run{
|
Button button_run{
|
||||||
|
@ -80,11 +80,11 @@ SearchView::SearchView(
|
|||||||
nav.push<FrequencySaveView>(entry.frequency);
|
nav.push<FrequencySaveView>(entry.frequency);
|
||||||
};
|
};
|
||||||
|
|
||||||
text_mean.set_style(&Styles::grey);
|
text_mean.set_style(Theme::getInstance()->fg_medium);
|
||||||
text_slices.set_style(&Styles::grey);
|
text_slices.set_style(Theme::getInstance()->fg_medium);
|
||||||
text_rate.set_style(&Styles::grey);
|
text_rate.set_style(Theme::getInstance()->fg_medium);
|
||||||
progress_timers.set_style(&Styles::grey);
|
progress_timers.set_style(Theme::getInstance()->fg_medium);
|
||||||
big_display.set_style(&Styles::grey);
|
big_display.set_style(Theme::getInstance()->fg_medium);
|
||||||
|
|
||||||
field_frequency_min.set_step(100'000);
|
field_frequency_min.set_step(100'000);
|
||||||
bind(field_frequency_min, settings_.freq_min, nav, [this](auto) {
|
bind(field_frequency_min, settings_.freq_min, nav, [this](auto) {
|
||||||
@ -184,7 +184,7 @@ void SearchView::do_detection() {
|
|||||||
recent_entries_view.set_dirty();
|
recent_entries_view.set_dirty();
|
||||||
|
|
||||||
text_infos.set("Locked ! ");
|
text_infos.set("Locked ! ");
|
||||||
big_display.set_style(&Styles::green);
|
big_display.set_style(Theme::getInstance()->fg_green);
|
||||||
|
|
||||||
locked = true;
|
locked = true;
|
||||||
locked_bin = bin_max;
|
locked_bin = bin_max;
|
||||||
@ -209,7 +209,7 @@ void SearchView::do_detection() {
|
|||||||
recent_entries_view.set_dirty();
|
recent_entries_view.set_dirty();
|
||||||
|
|
||||||
text_infos.set("Listening");
|
text_infos.set("Listening");
|
||||||
big_display.set_style(&Styles::grey);
|
big_display.set_style(Theme::getInstance()->fg_medium);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -219,10 +219,10 @@ void SearchView::do_detection() {
|
|||||||
search_counter++;
|
search_counter++;
|
||||||
|
|
||||||
// Refresh red tick
|
// Refresh red tick
|
||||||
portapack::display.fill_rectangle({last_tick_pos, 90, 1, 6}, Color::black());
|
portapack::display.fill_rectangle({last_tick_pos, 90, 1, 6}, Theme::getInstance()->fg_red->background);
|
||||||
if (bin_max > -1) {
|
if (bin_max > -1) {
|
||||||
last_tick_pos = (Coord)(bin_max / slices_nb);
|
last_tick_pos = (Coord)(bin_max / slices_nb);
|
||||||
portapack::display.fill_rectangle({last_tick_pos, 90, 1, 6}, Color::red());
|
portapack::display.fill_rectangle({last_tick_pos, 90, 1, 6}, Theme::getInstance()->fg_red->foreground);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -26,7 +26,6 @@
|
|||||||
#include "radio_state.hpp"
|
#include "radio_state.hpp"
|
||||||
#include "spectrum_color_lut.hpp"
|
#include "spectrum_color_lut.hpp"
|
||||||
#include "ui_receiver.hpp"
|
#include "ui_receiver.hpp"
|
||||||
#include "ui_styles.hpp"
|
|
||||||
|
|
||||||
namespace ui {
|
namespace ui {
|
||||||
|
|
||||||
@ -162,12 +161,12 @@ class SearchView : public View {
|
|||||||
RecentEntriesView<RecentEntries<SearchRecentEntry>> recent_entries_view{columns, recent};
|
RecentEntriesView<RecentEntries<SearchRecentEntry>> recent_entries_view{columns, recent};
|
||||||
|
|
||||||
Labels labels{
|
Labels labels{
|
||||||
{{1 * 8, 0}, "Min: Max: LNA VGA", Color::light_grey()},
|
{{1 * 8, 0}, "Min: Max: LNA VGA", Theme::getInstance()->fg_light->foreground},
|
||||||
{{1 * 8, 4 * 8}, "Trig: /255 Mean: /255", Color::light_grey()},
|
{{1 * 8, 4 * 8}, "Trig: /255 Mean: /255", Theme::getInstance()->fg_light->foreground},
|
||||||
{{1 * 8, 6 * 8}, "Slices: /32 Rate: Hz", Color::light_grey()},
|
{{1 * 8, 6 * 8}, "Slices: /32 Rate: Hz", Theme::getInstance()->fg_light->foreground},
|
||||||
{{6 * 8, 10 * 8}, "Timer Status", Color::light_grey()},
|
{{6 * 8, 10 * 8}, "Timer Status", Theme::getInstance()->fg_light->foreground},
|
||||||
{{1 * 8, 25 * 8}, "Accuracy +/-4.9kHz", Color::light_grey()},
|
{{1 * 8, 25 * 8}, "Accuracy +/-4.9kHz", Theme::getInstance()->fg_light->foreground},
|
||||||
{{26 * 8, 25 * 8}, "MHz", Color::light_grey()}};
|
{{26 * 8, 25 * 8}, "MHz", Theme::getInstance()->fg_light->foreground}};
|
||||||
|
|
||||||
FrequencyField field_frequency_min{
|
FrequencyField field_frequency_min{
|
||||||
{1 * 8, 1 * 16}};
|
{1 * 8, 1 * 16}};
|
||||||
|
@ -46,11 +46,12 @@ using namespace portapack;
|
|||||||
namespace fs = std::filesystem;
|
namespace fs = std::filesystem;
|
||||||
|
|
||||||
#include "string_format.hpp"
|
#include "string_format.hpp"
|
||||||
#include "ui_styles.hpp"
|
|
||||||
#include "ui_font_fixed_8x16.hpp"
|
#include "ui_font_fixed_8x16.hpp"
|
||||||
#include "cpld_update.hpp"
|
#include "cpld_update.hpp"
|
||||||
#include "config_mode.hpp"
|
#include "config_mode.hpp"
|
||||||
|
|
||||||
|
extern ui::SystemView* system_view_ptr;
|
||||||
|
|
||||||
namespace pmem = portapack::persistent_memory;
|
namespace pmem = portapack::persistent_memory;
|
||||||
|
|
||||||
namespace ui {
|
namespace ui {
|
||||||
@ -228,9 +229,9 @@ SetRadioView::SetRadioView(
|
|||||||
value_source_frequency.set(clock_manager.get_freq());
|
value_source_frequency.set(clock_manager.get_freq());
|
||||||
|
|
||||||
// Make these Text controls look like Labels.
|
// Make these Text controls look like Labels.
|
||||||
label_source.set_style(&Styles::light_grey);
|
label_source.set_style(Theme::getInstance()->fg_light);
|
||||||
value_source.set_style(&Styles::light_grey);
|
value_source.set_style(Theme::getInstance()->fg_light);
|
||||||
value_source_frequency.set_style(&Styles::light_grey);
|
value_source_frequency.set_style(Theme::getInstance()->fg_light);
|
||||||
|
|
||||||
SetFrequencyCorrectionModel model{
|
SetFrequencyCorrectionModel model{
|
||||||
static_cast<int8_t>(pmem::correction_ppb() / 1000), 0};
|
static_cast<int8_t>(pmem::correction_ppb() / 1000), 0};
|
||||||
@ -329,6 +330,10 @@ SetUIView::SetUIView(NavigationView& nav) {
|
|||||||
if (audio::speaker_disable_supported()) {
|
if (audio::speaker_disable_supported()) {
|
||||||
add_child(&toggle_speaker);
|
add_child(&toggle_speaker);
|
||||||
}
|
}
|
||||||
|
if (battery::BatteryManagement::isDetected()) {
|
||||||
|
add_child(&toggle_battery_icon);
|
||||||
|
add_child(&toggle_battery_text);
|
||||||
|
}
|
||||||
|
|
||||||
checkbox_disable_touchscreen.set_value(pmem::disable_touchscreen());
|
checkbox_disable_touchscreen.set_value(pmem::disable_touchscreen());
|
||||||
checkbox_showsplash.set_value(pmem::config_splash());
|
checkbox_showsplash.set_value(pmem::config_splash());
|
||||||
@ -355,6 +360,8 @@ SetUIView::SetUIView(NavigationView& nav) {
|
|||||||
toggle_speaker.set_value(!pmem::ui_hide_speaker());
|
toggle_speaker.set_value(!pmem::ui_hide_speaker());
|
||||||
toggle_mute.set_value(!pmem::ui_hide_mute());
|
toggle_mute.set_value(!pmem::ui_hide_mute());
|
||||||
toggle_fake_brightness.set_value(!pmem::ui_hide_fake_brightness());
|
toggle_fake_brightness.set_value(!pmem::ui_hide_fake_brightness());
|
||||||
|
toggle_battery_icon.set_value(!pmem::ui_hide_battery_icon());
|
||||||
|
toggle_battery_text.set_value(!pmem::ui_hide_numeric_battery());
|
||||||
toggle_sd_card.set_value(!pmem::ui_hide_sd_card());
|
toggle_sd_card.set_value(!pmem::ui_hide_sd_card());
|
||||||
|
|
||||||
button_save.on_select = [&nav, this](Button&) {
|
button_save.on_select = [&nav, this](Button&) {
|
||||||
@ -382,6 +389,8 @@ SetUIView::SetUIView(NavigationView& nav) {
|
|||||||
pmem::set_ui_hide_speaker(!toggle_speaker.value());
|
pmem::set_ui_hide_speaker(!toggle_speaker.value());
|
||||||
pmem::set_ui_hide_mute(!toggle_mute.value());
|
pmem::set_ui_hide_mute(!toggle_mute.value());
|
||||||
pmem::set_ui_hide_fake_brightness(!toggle_fake_brightness.value());
|
pmem::set_ui_hide_fake_brightness(!toggle_fake_brightness.value());
|
||||||
|
pmem::set_ui_hide_battery_icon(!toggle_battery_icon.value());
|
||||||
|
pmem::set_ui_hide_numeric_battery(!toggle_battery_text.value());
|
||||||
pmem::set_ui_hide_sd_card(!toggle_sd_card.value());
|
pmem::set_ui_hide_sd_card(!toggle_sd_card.value());
|
||||||
send_system_refresh();
|
send_system_refresh();
|
||||||
|
|
||||||
@ -567,7 +576,7 @@ SetPersistentMemoryView::SetPersistentMemoryView(NavigationView& nav) {
|
|||||||
&button_return,
|
&button_return,
|
||||||
});
|
});
|
||||||
|
|
||||||
text_pmem_status.set_style(&Styles::yellow);
|
text_pmem_status.set_style(Theme::getInstance()->fg_yellow);
|
||||||
|
|
||||||
check_use_sdcard_for_pmem.set_value(pmem::should_use_sdcard_for_pmem());
|
check_use_sdcard_for_pmem.set_value(pmem::should_use_sdcard_for_pmem());
|
||||||
check_use_sdcard_for_pmem.on_select = [this](Checkbox&, bool v) {
|
check_use_sdcard_for_pmem.on_select = [this](Checkbox&, bool v) {
|
||||||
@ -729,7 +738,7 @@ AppSettingsView::AppSettingsView(
|
|||||||
auto path = settings_dir / entry.path();
|
auto path = settings_dir / entry.path();
|
||||||
|
|
||||||
menu_view.add_item({path.filename().string().substr(0, 26),
|
menu_view.add_item({path.filename().string().substr(0, 26),
|
||||||
ui::Color::dark_cyan(),
|
ui::Theme::getInstance()->fg_darkcyan->foreground,
|
||||||
&bitmap_icon_file_text,
|
&bitmap_icon_file_text,
|
||||||
[this, path](KeyEvent) {
|
[this, path](KeyEvent) {
|
||||||
nav_.push<TextEditorView>(path);
|
nav_.push<TextEditorView>(path);
|
||||||
@ -765,31 +774,44 @@ void SetConfigModeView::focus() {
|
|||||||
button_save.focus();
|
button_save.focus();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* SetFakeBrightnessView ************************************/
|
/* SetDisplayView ************************************/
|
||||||
|
|
||||||
SetFakeBrightnessView::SetFakeBrightnessView(NavigationView& nav) {
|
SetDisplayView::SetDisplayView(NavigationView& nav) {
|
||||||
add_children({&labels,
|
add_children({&labels,
|
||||||
&field_fake_brightness,
|
&field_fake_brightness,
|
||||||
&button_save,
|
&button_save,
|
||||||
&button_cancel,
|
&button_cancel,
|
||||||
|
&checkbox_invert_switch,
|
||||||
&checkbox_brightness_switch});
|
&checkbox_brightness_switch});
|
||||||
|
|
||||||
field_fake_brightness.set_by_value(pmem::fake_brightness_level());
|
field_fake_brightness.set_by_value(pmem::fake_brightness_level());
|
||||||
checkbox_brightness_switch.set_value(pmem::apply_fake_brightness());
|
checkbox_brightness_switch.set_value(pmem::apply_fake_brightness());
|
||||||
|
checkbox_invert_switch.set_value(pmem::config_lcd_inverted_mode());
|
||||||
|
|
||||||
button_save.on_select = [&nav, this](Button&) {
|
button_save.on_select = [&nav, this](Button&) {
|
||||||
pmem::set_apply_fake_brightness(checkbox_brightness_switch.value());
|
pmem::set_apply_fake_brightness(checkbox_brightness_switch.value());
|
||||||
pmem::set_fake_brightness_level(field_fake_brightness.selected_index_value());
|
pmem::set_fake_brightness_level(field_fake_brightness.selected_index_value());
|
||||||
|
if (checkbox_invert_switch.value() != pmem::config_lcd_inverted_mode()) {
|
||||||
|
display.set_inverted(checkbox_invert_switch.value());
|
||||||
|
pmem::set_lcd_inverted_mode(checkbox_invert_switch.value());
|
||||||
|
}
|
||||||
send_system_refresh();
|
send_system_refresh();
|
||||||
nav.pop();
|
nav.pop();
|
||||||
};
|
};
|
||||||
|
// only enable invert OR fake brightness
|
||||||
|
checkbox_invert_switch.on_select = [this](Checkbox&, bool v) {
|
||||||
|
if (v) checkbox_brightness_switch.set_value(false);
|
||||||
|
};
|
||||||
|
checkbox_brightness_switch.on_select = [this](Checkbox&, bool v) {
|
||||||
|
if (v) checkbox_invert_switch.set_value(false);
|
||||||
|
};
|
||||||
|
|
||||||
button_cancel.on_select = [&nav, this](Button&) {
|
button_cancel.on_select = [&nav, this](Button&) {
|
||||||
nav.pop();
|
nav.pop();
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetFakeBrightnessView::focus() {
|
void SetDisplayView::focus() {
|
||||||
button_save.focus();
|
button_save.focus();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -807,6 +829,7 @@ SetMenuColorView::SetMenuColorView(NavigationView& nav) {
|
|||||||
&field_green_level,
|
&field_green_level,
|
||||||
&field_blue_level,
|
&field_blue_level,
|
||||||
&button_save,
|
&button_save,
|
||||||
|
&button_reset,
|
||||||
&button_cancel});
|
&button_cancel});
|
||||||
|
|
||||||
button_sample.set_focusable(false);
|
button_sample.set_focusable(false);
|
||||||
@ -824,6 +847,13 @@ SetMenuColorView::SetMenuColorView(NavigationView& nav) {
|
|||||||
field_green_level.on_change = color_changed_fn;
|
field_green_level.on_change = color_changed_fn;
|
||||||
field_blue_level.on_change = color_changed_fn;
|
field_blue_level.on_change = color_changed_fn;
|
||||||
|
|
||||||
|
button_reset.on_select = [&nav, this](Button&) {
|
||||||
|
field_red_level.set_value(127);
|
||||||
|
field_green_level.set_value(127);
|
||||||
|
field_blue_level.set_value(127);
|
||||||
|
set_dirty();
|
||||||
|
};
|
||||||
|
|
||||||
button_save.on_select = [&nav, this](Button&) {
|
button_save.on_select = [&nav, this](Button&) {
|
||||||
Color c = Color(field_red_level.value(), field_green_level.value(), field_blue_level.value());
|
Color c = Color(field_red_level.value(), field_green_level.value(), field_blue_level.value());
|
||||||
pmem::set_menu_color(c);
|
pmem::set_menu_color(c);
|
||||||
@ -894,6 +924,78 @@ void SetAutostartView::focus() {
|
|||||||
options.focus();
|
options.focus();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* SetThemeView ************************************/
|
||||||
|
|
||||||
|
SetThemeView::SetThemeView(NavigationView& nav) {
|
||||||
|
add_children({&labels,
|
||||||
|
&button_save,
|
||||||
|
&button_cancel,
|
||||||
|
&options,
|
||||||
|
&checkbox_menuset});
|
||||||
|
|
||||||
|
button_save.on_select = [&nav, this](Button&) {
|
||||||
|
if (selected < Theme::ThemeId::MAX && (uint8_t)selected != portapack::persistent_memory::ui_theme_id()) {
|
||||||
|
portapack::persistent_memory::set_ui_theme_id((uint8_t)selected);
|
||||||
|
Theme::SetTheme((Theme::ThemeId)selected);
|
||||||
|
if (checkbox_menuset.value()) {
|
||||||
|
pmem::set_menu_color(Theme::getInstance()->bg_medium->background);
|
||||||
|
}
|
||||||
|
send_system_refresh();
|
||||||
|
}
|
||||||
|
nav.pop();
|
||||||
|
};
|
||||||
|
|
||||||
|
checkbox_menuset.set_value(true);
|
||||||
|
|
||||||
|
button_cancel.on_select = [&nav, this](Button&) {
|
||||||
|
nav.pop();
|
||||||
|
};
|
||||||
|
|
||||||
|
options.on_change = [this](size_t, OptionsField::value_t v) {
|
||||||
|
selected = v;
|
||||||
|
};
|
||||||
|
options.set_selected_index(portapack::persistent_memory::ui_theme_id());
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetThemeView::focus() {
|
||||||
|
options.focus();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* SetBatteryView ************************************/
|
||||||
|
|
||||||
|
SetBatteryView::SetBatteryView(NavigationView& nav) {
|
||||||
|
add_children({&labels,
|
||||||
|
&button_save,
|
||||||
|
&button_cancel,
|
||||||
|
&checkbox_overridebatt});
|
||||||
|
|
||||||
|
if (battery::BatteryManagement::detectedModule() == battery::BatteryManagement::BATT_MAX17055) add_children({&button_reset, &labels2});
|
||||||
|
|
||||||
|
button_save.on_select = [&nav, this](Button&) {
|
||||||
|
pmem::set_ui_override_batt_calc(checkbox_overridebatt.value());
|
||||||
|
battery::BatteryManagement::set_calc_override(checkbox_overridebatt.value());
|
||||||
|
send_system_refresh();
|
||||||
|
nav.pop();
|
||||||
|
};
|
||||||
|
|
||||||
|
button_reset.on_select = [&nav, this](Button&) {
|
||||||
|
if (battery::BatteryManagement::reset_learned())
|
||||||
|
nav.display_modal("Reset", "Battery parameters reset");
|
||||||
|
else
|
||||||
|
nav.display_modal("Error", "Error parameter reset");
|
||||||
|
};
|
||||||
|
|
||||||
|
checkbox_overridebatt.set_value(pmem::ui_override_batt_calc());
|
||||||
|
|
||||||
|
button_cancel.on_select = [&nav, this](Button&) {
|
||||||
|
nav.pop();
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetBatteryView::focus() {
|
||||||
|
button_cancel.focus();
|
||||||
|
}
|
||||||
|
|
||||||
/* SettingsMenuView **************************************/
|
/* SettingsMenuView **************************************/
|
||||||
|
|
||||||
SettingsMenuView::SettingsMenuView(NavigationView& nav)
|
SettingsMenuView::SettingsMenuView(NavigationView& nav)
|
||||||
@ -919,10 +1021,12 @@ void SettingsMenuView::on_populate() {
|
|||||||
{"SD Card", ui::Color::dark_cyan(), &bitmap_icon_sdcard, [this]() { nav_.push<SetSDCardView>(); }},
|
{"SD Card", ui::Color::dark_cyan(), &bitmap_icon_sdcard, [this]() { nav_.push<SetSDCardView>(); }},
|
||||||
{"User Interface", ui::Color::dark_cyan(), &bitmap_icon_options_ui, [this]() { nav_.push<SetUIView>(); }},
|
{"User Interface", ui::Color::dark_cyan(), &bitmap_icon_options_ui, [this]() { nav_.push<SetUIView>(); }},
|
||||||
//{"QR Code", ui::Color::dark_cyan(), &bitmap_icon_qr_code, [this]() { nav_.push<SetQRCodeView>(); }},
|
//{"QR Code", ui::Color::dark_cyan(), &bitmap_icon_qr_code, [this]() { nav_.push<SetQRCodeView>(); }},
|
||||||
{"Brightness", ui::Color::dark_cyan(), &bitmap_icon_brightness, [this]() { nav_.push<SetFakeBrightnessView>(); }},
|
{"Display", ui::Color::dark_cyan(), &bitmap_icon_brightness, [this]() { nav_.push<SetDisplayView>(); }},
|
||||||
{"Menu Color", ui::Color::dark_cyan(), &bitmap_icon_brightness, [this]() { nav_.push<SetMenuColorView>(); }},
|
{"Menu Color", ui::Color::dark_cyan(), &bitmap_icon_brightness, [this]() { nav_.push<SetMenuColorView>(); }},
|
||||||
|
{"Theme", ui::Color::dark_cyan(), &bitmap_icon_setup, [this]() { nav_.push<SetThemeView>(); }},
|
||||||
{"Autostart", ui::Color::dark_cyan(), &bitmap_icon_setup, [this]() { nav_.push<SetAutostartView>(); }},
|
{"Autostart", ui::Color::dark_cyan(), &bitmap_icon_setup, [this]() { nav_.push<SetAutostartView>(); }},
|
||||||
});
|
});
|
||||||
|
if (battery::BatteryManagement::isDetected()) add_item({"Battery", ui::Color::dark_cyan(), &bitmap_icon_batt_icon, [this]() { nav_.push<SetBatteryView>(); }});
|
||||||
}
|
}
|
||||||
|
|
||||||
} /* namespace ui */
|
} /* namespace ui */
|
||||||
|
@ -65,14 +65,14 @@ class SetDateTimeView : public View {
|
|||||||
std::vector<option_t> month_options = {{"Jan", 1}, {"Feb", 2}, {"Mar", 3}, {"Apr", 4}, {"May", 5}, {"Jun", 6}, {"Jul", 7}, {"Aug", 8}, {"Sep", 9}, {"Oct", 10}, {"Nov", 11}, {"Dec", 12}};
|
std::vector<option_t> month_options = {{"Jan", 1}, {"Feb", 2}, {"Mar", 3}, {"Apr", 4}, {"May", 5}, {"Jun", 6}, {"Jul", 7}, {"Aug", 8}, {"Sep", 9}, {"Oct", 10}, {"Nov", 11}, {"Dec", 12}};
|
||||||
|
|
||||||
Labels labels{
|
Labels labels{
|
||||||
{{1 * 8, 1 * 16}, "Adjust the RTC clock date &", Color::light_grey()},
|
{{1 * 8, 1 * 16}, "Adjust the RTC clock date &", Theme::getInstance()->fg_light->foreground},
|
||||||
{{1 * 8, 2 * 16}, "time. If clock resets after", Color::light_grey()},
|
{{1 * 8, 2 * 16}, "time. If clock resets after", Theme::getInstance()->fg_light->foreground},
|
||||||
{{1 * 8, 3 * 16}, "reboot, coin batt. is dead. ", Color::light_grey()},
|
{{1 * 8, 3 * 16}, "reboot, coin batt. is dead. ", Theme::getInstance()->fg_light->foreground},
|
||||||
{{1 * 8, 5 * 16 - 2}, "YYYY-MM-DD HH:MM:SS DoW DoY", Color::grey()},
|
{{1 * 8, 5 * 16 - 2}, "YYYY-MM-DD HH:MM:SS DoW DoY", Theme::getInstance()->fg_medium->foreground},
|
||||||
{{5 * 8, 6 * 16}, "- - : :", Color::light_grey()},
|
{{5 * 8, 6 * 16}, "- - : :", Theme::getInstance()->fg_light->foreground},
|
||||||
{{1 * 8, 11 * 16}, "DST adds 1 hour to RTC time.", Color::light_grey()},
|
{{1 * 8, 11 * 16}, "DST adds 1 hour to RTC time.", Theme::getInstance()->fg_light->foreground},
|
||||||
{{0 * 8, 12 * 16}, "Start: 0:00 on Nth DDD in", Color::light_grey()},
|
{{0 * 8, 12 * 16}, "Start: 0:00 on Nth DDD in", Theme::getInstance()->fg_light->foreground},
|
||||||
{{0 * 8, 13 * 16}, "End: 1:00 on Nth DDD in", Color::light_grey()}};
|
{{0 * 8, 13 * 16}, "End: 1:00 on Nth DDD in", Theme::getInstance()->fg_light->foreground}};
|
||||||
|
|
||||||
NumberField field_year{
|
NumberField field_year{
|
||||||
{1 * 8, 6 * 16},
|
{1 * 8, 6 * 16},
|
||||||
@ -210,8 +210,8 @@ class SetRadioView : public View {
|
|||||||
""};
|
""};
|
||||||
|
|
||||||
Labels labels_correction{
|
Labels labels_correction{
|
||||||
{{2 * 8, 3 * 16}, "Frequency correction:", Color::light_grey()},
|
{{2 * 8, 3 * 16}, "Frequency correction:", Theme::getInstance()->fg_light->foreground},
|
||||||
{{6 * 8, 4 * 16}, "PPM", Color::light_grey()},
|
{{6 * 8, 4 * 16}, "PPM", Theme::getInstance()->fg_light->foreground},
|
||||||
};
|
};
|
||||||
|
|
||||||
NumberField field_ppm{
|
NumberField field_ppm{
|
||||||
@ -233,13 +233,13 @@ class SetRadioView : public View {
|
|||||||
SymField::Type::Dec};
|
SymField::Type::Dec};
|
||||||
|
|
||||||
Labels labels_clkout_khz{
|
Labels labels_clkout_khz{
|
||||||
{{26 * 8, 6 * 16}, "kHz", Color::light_grey()}};
|
{{26 * 8, 6 * 16}, "kHz", Theme::getInstance()->fg_light->foreground}};
|
||||||
|
|
||||||
Labels labels_bias{
|
Labels labels_bias{
|
||||||
{{4 * 8 + 4, 8 * 16}, "CAUTION: Ensure that all", Color::red()},
|
{{4 * 8 + 4, 8 * 16}, "CAUTION: Ensure that all", Theme::getInstance()->error_dark->foreground},
|
||||||
{{5 * 8 + 0, 9 * 16}, "devices attached to the", Color::red()},
|
{{5 * 8 + 0, 9 * 16}, "devices attached to the", Theme::getInstance()->error_dark->foreground},
|
||||||
{{6 * 8 + 0, 10 * 16}, "antenna connector can", Color::red()},
|
{{6 * 8 + 0, 10 * 16}, "antenna connector can", Theme::getInstance()->error_dark->foreground},
|
||||||
{{6 * 8 + 4, 11 * 16}, "accept a DC voltage!", Color::red()}};
|
{{6 * 8 + 4, 11 * 16}, "accept a DC voltage!", Theme::getInstance()->error_dark->foreground}};
|
||||||
|
|
||||||
Checkbox check_bias{
|
Checkbox check_bias{
|
||||||
{18, 12 * 16},
|
{18, 12 * 16},
|
||||||
@ -319,41 +319,49 @@ class SetUIView : public View {
|
|||||||
"Back button in menu"};
|
"Back button in menu"};
|
||||||
|
|
||||||
Labels labels{
|
Labels labels{
|
||||||
{{3 * 8, 13 * 16}, "Show/Hide Status Icons", Color::light_grey()},
|
{{3 * 8, 13 * 16}, "Show/Hide Status Icons", Theme::getInstance()->fg_light->foreground},
|
||||||
};
|
};
|
||||||
|
|
||||||
ImageToggle toggle_camera{
|
ImageToggle toggle_camera{
|
||||||
{6 * 8, 14 * 16 + 2, 16, 16},
|
{2 * 8, 14 * 16 + 2, 16, 16},
|
||||||
&bitmap_icon_camera};
|
&bitmap_icon_camera};
|
||||||
|
|
||||||
ImageToggle toggle_sleep{
|
ImageToggle toggle_sleep{
|
||||||
{8 * 8, 14 * 16 + 2, 16, 16},
|
{4 * 8, 14 * 16 + 2, 16, 16},
|
||||||
&bitmap_icon_sleep};
|
&bitmap_icon_sleep};
|
||||||
|
|
||||||
ImageToggle toggle_stealth{
|
ImageToggle toggle_stealth{
|
||||||
{10 * 8, 14 * 16 + 2, 16, 16},
|
{6 * 8, 14 * 16 + 2, 16, 16},
|
||||||
&bitmap_icon_stealth};
|
&bitmap_icon_stealth};
|
||||||
|
|
||||||
ImageToggle toggle_converter{
|
ImageToggle toggle_converter{
|
||||||
{12 * 8, 14 * 16 + 2, 16, 16},
|
{8 * 8, 14 * 16 + 2, 16, 16},
|
||||||
&bitmap_icon_upconvert};
|
&bitmap_icon_upconvert};
|
||||||
|
|
||||||
ImageToggle toggle_bias_tee{
|
ImageToggle toggle_bias_tee{
|
||||||
{14 * 8, 14 * 16 + 2, 16, 16},
|
{10 * 8, 14 * 16 + 2, 16, 16},
|
||||||
&bitmap_icon_biast_off};
|
&bitmap_icon_biast_off};
|
||||||
|
|
||||||
ImageToggle toggle_clock{
|
ImageToggle toggle_clock{
|
||||||
{16 * 8, 14 * 16 + 2, 8, 16},
|
{12 * 8, 14 * 16 + 2, 8, 16},
|
||||||
&bitmap_icon_clk_ext};
|
&bitmap_icon_clk_ext};
|
||||||
|
|
||||||
ImageToggle toggle_mute{
|
ImageToggle toggle_mute{
|
||||||
{17 * 8, 14 * 16 + 2, 16, 16},
|
{13 * 8, 14 * 16 + 2, 16, 16},
|
||||||
&bitmap_icon_speaker_and_headphones_mute};
|
&bitmap_icon_speaker_and_headphones_mute};
|
||||||
|
|
||||||
ImageToggle toggle_speaker{
|
ImageToggle toggle_speaker{
|
||||||
{19 * 8, 14 * 16 + 2, 16, 16},
|
{15 * 8, 14 * 16 + 2, 16, 16},
|
||||||
&bitmap_icon_speaker_mute};
|
&bitmap_icon_speaker_mute};
|
||||||
|
|
||||||
|
ImageToggle toggle_battery_icon{
|
||||||
|
{17 * 8, 14 * 16 + 2, 16, 16},
|
||||||
|
&bitmap_icon_batt_icon};
|
||||||
|
|
||||||
|
ImageToggle toggle_battery_text{
|
||||||
|
{19 * 8, 14 * 16 + 2, 16, 16},
|
||||||
|
&bitmap_icon_batt_text};
|
||||||
|
|
||||||
ImageToggle toggle_fake_brightness{
|
ImageToggle toggle_fake_brightness{
|
||||||
{21 * 8, 14 * 16 + 2, 16, 16},
|
{21 * 8, 14 * 16 + 2, 16, 16},
|
||||||
&bitmap_icon_brightness};
|
&bitmap_icon_brightness};
|
||||||
@ -382,8 +390,8 @@ class SetSDCardView : public View {
|
|||||||
private:
|
private:
|
||||||
Labels labels{
|
Labels labels{
|
||||||
// 01234567890123456789012345678
|
// 01234567890123456789012345678
|
||||||
{{1 * 8, 120 - 48}, " HIGH SPEED SDCARD IO ", Color::light_grey()},
|
{{1 * 8, 120 - 48}, " HIGH SPEED SDCARD IO ", Theme::getInstance()->fg_light->foreground},
|
||||||
{{1 * 8, 120 - 32}, " May or may not work !! ", Color::light_grey()}};
|
{{1 * 8, 120 - 32}, " May or may not work !! ", Theme::getInstance()->fg_light->foreground}};
|
||||||
|
|
||||||
Checkbox checkbox_sdcard_speed{
|
Checkbox checkbox_sdcard_speed{
|
||||||
{2 * 8, 120},
|
{2 * 8, 120},
|
||||||
@ -417,11 +425,11 @@ class SetConverterSettingsView : public View {
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
Labels labels{
|
Labels labels{
|
||||||
{{1 * 8, 1 * 16}, "Options for working with", Color::light_grey()},
|
{{1 * 8, 1 * 16}, "Options for working with", Theme::getInstance()->fg_light->foreground},
|
||||||
{{1 * 8, 2 * 16}, "up/down converter hardware", Color::light_grey()},
|
{{1 * 8, 2 * 16}, "up/down converter hardware", Theme::getInstance()->fg_light->foreground},
|
||||||
{{1 * 8, 3 * 16}, "like a Ham It Up.", Color::light_grey()},
|
{{1 * 8, 3 * 16}, "like a Ham It Up.", Theme::getInstance()->fg_light->foreground},
|
||||||
{{2 * 8, 9 * 16 - 2}, "Conversion frequency:", Color::light_grey()},
|
{{2 * 8, 9 * 16 - 2}, "Conversion frequency:", Theme::getInstance()->fg_light->foreground},
|
||||||
{{18 * 8, 10 * 16}, "MHz", Color::light_grey()},
|
{{18 * 8, 10 * 16}, "MHz", Theme::getInstance()->fg_light->foreground},
|
||||||
};
|
};
|
||||||
|
|
||||||
Checkbox check_show_converter{
|
Checkbox check_show_converter{
|
||||||
@ -461,13 +469,13 @@ class SetFrequencyCorrectionView : public View {
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
Labels labels{
|
Labels labels{
|
||||||
{{1 * 8, 1 * 16}, "Frequency correction allows", Color::light_grey()},
|
{{1 * 8, 1 * 16}, "Frequency correction allows", Theme::getInstance()->fg_light->foreground},
|
||||||
{{1 * 8, 2 * 16}, "RX and TX frequencies to be", Color::light_grey()},
|
{{1 * 8, 2 * 16}, "RX and TX frequencies to be", Theme::getInstance()->fg_light->foreground},
|
||||||
{{1 * 8, 3 * 16}, "adjusted for all apps.", Color::light_grey()},
|
{{1 * 8, 3 * 16}, "adjusted for all apps.", Theme::getInstance()->fg_light->foreground},
|
||||||
{{2 * 8, 6 * 16}, "RX Adjustment Frequency", Color::light_grey()},
|
{{2 * 8, 6 * 16}, "RX Adjustment Frequency", Theme::getInstance()->fg_light->foreground},
|
||||||
{{18 * 8, 7 * 16}, "MHz", Color::light_grey()},
|
{{18 * 8, 7 * 16}, "MHz", Theme::getInstance()->fg_light->foreground},
|
||||||
{{2 * 8, 9 * 16}, "TX Adjustment Frequency", Color::light_grey()},
|
{{2 * 8, 9 * 16}, "TX Adjustment Frequency", Theme::getInstance()->fg_light->foreground},
|
||||||
{{18 * 8, 10 * 16}, "MHz", Color::light_grey()},
|
{{18 * 8, 10 * 16}, "MHz", Theme::getInstance()->fg_light->foreground},
|
||||||
};
|
};
|
||||||
|
|
||||||
OptionsField opt_rx_correction_mode{
|
OptionsField opt_rx_correction_mode{
|
||||||
@ -504,14 +512,14 @@ class SetAudioView : public View {
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
Labels labels{
|
Labels labels{
|
||||||
{{1 * 8, 1 * 16}, "Controls the volume of the", Color::light_grey()},
|
{{1 * 8, 1 * 16}, "Controls the volume of the", Theme::getInstance()->fg_light->foreground},
|
||||||
{{1 * 8, 2 * 16}, "tone when transmitting in", Color::light_grey()},
|
{{1 * 8, 2 * 16}, "tone when transmitting in", Theme::getInstance()->fg_light->foreground},
|
||||||
{{1 * 8, 3 * 16}, "Soundboard or Mic apps:", Color::light_grey()},
|
{{1 * 8, 3 * 16}, "Soundboard or Mic apps:", Theme::getInstance()->fg_light->foreground},
|
||||||
{{2 * 8, 5 * 16}, "Tone key mix: %", Color::light_grey()},
|
{{2 * 8, 5 * 16}, "Tone key mix: %", Theme::getInstance()->fg_light->foreground},
|
||||||
{{1 * 8, 8 * 16}, "Controls whether apps should", Color::light_grey()},
|
{{1 * 8, 8 * 16}, "Controls whether apps should", Theme::getInstance()->fg_light->foreground},
|
||||||
{{1 * 8, 9 * 16}, "beep on speaker & headphone", Color::light_grey()},
|
{{1 * 8, 9 * 16}, "beep on speaker & headphone", Theme::getInstance()->fg_light->foreground},
|
||||||
{{1 * 8, 10 * 16}, "when a packet is received", Color::light_grey()},
|
{{1 * 8, 10 * 16}, "when a packet is received", Theme::getInstance()->fg_light->foreground},
|
||||||
{{1 * 8, 11 * 16}, "(not all apps support this):", Color::light_grey()},
|
{{1 * 8, 11 * 16}, "(not all apps support this):", Theme::getInstance()->fg_light->foreground},
|
||||||
};
|
};
|
||||||
|
|
||||||
NumberField field_tone_mix{
|
NumberField field_tone_mix{
|
||||||
@ -546,8 +554,8 @@ class SetQRCodeView : public View {
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
Labels labels{
|
Labels labels{
|
||||||
{{1 * 8, 1 * 16}, "Change the size of the QR", Color::light_grey()},
|
{{1 * 8, 1 * 16}, "Change the size of the QR", Theme::getInstance()->fg_light->foreground},
|
||||||
{{1 * 8, 2 * 16}, "code shown in Radiosonde.", Color::light_grey()},
|
{{1 * 8, 2 * 16}, "code shown in Radiosonde.", Theme::getInstance()->fg_light->foreground},
|
||||||
};
|
};
|
||||||
|
|
||||||
Checkbox checkbox_bigger_qr{
|
Checkbox checkbox_bigger_qr{
|
||||||
@ -578,14 +586,14 @@ class SetEncoderDialView : public View {
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
Labels labels{
|
Labels labels{
|
||||||
{{1 * 8, 1 * 16}, "Adjusts sensitivity to dial", Color::light_grey()},
|
{{1 * 8, 1 * 16}, "Adjusts sensitivity to dial", Theme::getInstance()->fg_light->foreground},
|
||||||
{{1 * 8, 2 * 16}, "rotation position (number of", Color::light_grey()},
|
{{1 * 8, 2 * 16}, "rotation position (number of", Theme::getInstance()->fg_light->foreground},
|
||||||
{{1 * 8, 3 * 16}, "steps per full rotation):", Color::light_grey()},
|
{{1 * 8, 3 * 16}, "steps per full rotation):", Theme::getInstance()->fg_light->foreground},
|
||||||
{{2 * 8, 5 * 16}, "Dial sensitivity:", Color::light_grey()},
|
{{2 * 8, 5 * 16}, "Dial sensitivity:", Theme::getInstance()->fg_light->foreground},
|
||||||
{{1 * 8, 8 * 16}, "Adjusts sensitivity to dial", Color::light_grey()},
|
{{1 * 8, 8 * 16}, "Adjusts sensitivity to dial", Theme::getInstance()->fg_light->foreground},
|
||||||
{{1 * 8, 9 * 16}, "rotation rate (default 1", Color::light_grey()},
|
{{1 * 8, 9 * 16}, "rotation rate (default 1", Theme::getInstance()->fg_light->foreground},
|
||||||
{{1 * 8, 10 * 16}, "means no rate dependency):", Color::light_grey()},
|
{{1 * 8, 10 * 16}, "means no rate dependency):", Theme::getInstance()->fg_light->foreground},
|
||||||
{{3 * 8, 12 * 16}, "Rate multiplier:", Color::light_grey()},
|
{{3 * 8, 12 * 16}, "Rate multiplier:", Theme::getInstance()->fg_light->foreground},
|
||||||
};
|
};
|
||||||
|
|
||||||
OptionsField field_encoder_dial_sensitivity{
|
OptionsField field_encoder_dial_sensitivity{
|
||||||
@ -622,9 +630,9 @@ class SetPersistentMemoryView : public View {
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
Labels labels{
|
Labels labels{
|
||||||
{{1 * 8, 1 * 16}, "Save persistent memory on SD", Color::light_grey()},
|
{{1 * 8, 1 * 16}, "Save persistent memory on SD", Theme::getInstance()->fg_light->foreground},
|
||||||
{{1 * 8, 2 * 16}, "card. Needed when device has", Color::light_grey()},
|
{{1 * 8, 2 * 16}, "card. Needed when device has", Theme::getInstance()->fg_light->foreground},
|
||||||
{{1 * 8, 3 * 16}, "dead/missing coin battery.", Color::light_grey()},
|
{{1 * 8, 3 * 16}, "dead/missing coin battery.", Theme::getInstance()->fg_light->foreground},
|
||||||
};
|
};
|
||||||
|
|
||||||
Text text_pmem_status{
|
Text text_pmem_status{
|
||||||
@ -664,7 +672,7 @@ class AppSettingsView : public View {
|
|||||||
NavigationView& nav_;
|
NavigationView& nav_;
|
||||||
|
|
||||||
Labels labels{
|
Labels labels{
|
||||||
{{0, 4}, "Select file to edit:", Color::white()}};
|
{{0, 4}, "Select file to edit:", Theme::getInstance()->bg_darkest->foreground}};
|
||||||
|
|
||||||
MenuView menu_view{
|
MenuView menu_view{
|
||||||
{0, 2 * 8, 240, 26 * 8},
|
{0, 2 * 8, 240, 26 * 8},
|
||||||
@ -681,9 +689,9 @@ class SetConfigModeView : public View {
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
Labels labels{
|
Labels labels{
|
||||||
{{1 * 8, 1 * 16}, "Controls whether firmware", Color::light_grey()},
|
{{1 * 8, 1 * 16}, "Controls whether firmware", Theme::getInstance()->fg_light->foreground},
|
||||||
{{1 * 8, 2 * 16}, "will enter Config Mode", Color::light_grey()},
|
{{1 * 8, 2 * 16}, "will enter Config Mode", Theme::getInstance()->fg_light->foreground},
|
||||||
{{1 * 8, 3 * 16}, "after a boot failure.", Color::light_grey()},
|
{{1 * 8, 3 * 16}, "after a boot failure.", Theme::getInstance()->fg_light->foreground},
|
||||||
};
|
};
|
||||||
|
|
||||||
Checkbox checkbox_config_mode_enabled{
|
Checkbox checkbox_config_mode_enabled{
|
||||||
@ -703,20 +711,20 @@ class SetConfigModeView : public View {
|
|||||||
|
|
||||||
using portapack::persistent_memory::fake_brightness_level_options;
|
using portapack::persistent_memory::fake_brightness_level_options;
|
||||||
|
|
||||||
class SetFakeBrightnessView : public View {
|
class SetDisplayView : public View {
|
||||||
public:
|
public:
|
||||||
SetFakeBrightnessView(NavigationView& nav);
|
SetDisplayView(NavigationView& nav);
|
||||||
|
|
||||||
void focus() override;
|
void focus() override;
|
||||||
|
|
||||||
std::string title() const override { return "Brightness"; };
|
std::string title() const override { return "Display"; };
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Labels labels{
|
Labels labels{
|
||||||
{{1 * 8, 1 * 16}, "Limits screen brightness", Color::light_grey()},
|
{{1 * 8, 1 * 16}, "Limits screen brightness", Theme::getInstance()->fg_light->foreground},
|
||||||
{{1 * 8, 2 * 16}, "(has a small performance", Color::light_grey()},
|
{{1 * 8, 2 * 16}, "(has a small performance", Theme::getInstance()->fg_light->foreground},
|
||||||
{{1 * 8, 3 * 16}, "impact when enabled).", Color::light_grey()},
|
{{1 * 8, 3 * 16}, "impact when enabled).", Theme::getInstance()->fg_light->foreground},
|
||||||
{{2 * 8, 8 * 16}, "Brightness:", Color::light_grey()},
|
{{2 * 8, 8 * 16}, "Brightness:", Theme::getInstance()->fg_light->foreground},
|
||||||
};
|
};
|
||||||
|
|
||||||
OptionsField field_fake_brightness{
|
OptionsField field_fake_brightness{
|
||||||
@ -731,6 +739,11 @@ class SetFakeBrightnessView : public View {
|
|||||||
16,
|
16,
|
||||||
"Enable brightness adjust"};
|
"Enable brightness adjust"};
|
||||||
|
|
||||||
|
Checkbox checkbox_invert_switch{
|
||||||
|
{1 * 8, 10 * 16},
|
||||||
|
23,
|
||||||
|
"Invert colors (For IPS)"};
|
||||||
|
|
||||||
Button button_save{
|
Button button_save{
|
||||||
{2 * 8, 16 * 16, 12 * 8, 32},
|
{2 * 8, 16 * 16, 12 * 8, 32},
|
||||||
"Save"};
|
"Save"};
|
||||||
@ -753,10 +766,10 @@ class SetMenuColorView : public View {
|
|||||||
void paint_sample();
|
void paint_sample();
|
||||||
|
|
||||||
Labels labels{
|
Labels labels{
|
||||||
{{3 * 8, 1 * 16}, "Menu Button Color Scheme", Color::light_grey()},
|
{{3 * 8, 1 * 16}, "Menu Button Color Scheme", Theme::getInstance()->fg_light->foreground},
|
||||||
{{2 * 8, 8 * 16}, "Red Level:", Color::light_grey()},
|
{{2 * 8, 8 * 16}, "Red Level:", Theme::getInstance()->fg_light->foreground},
|
||||||
{{2 * 8, 9 * 16}, "Green Level:", Color::light_grey()},
|
{{2 * 8, 9 * 16}, "Green Level:", Theme::getInstance()->fg_light->foreground},
|
||||||
{{2 * 8, 10 * 16}, "Blue Level:", Color::light_grey()},
|
{{2 * 8, 10 * 16}, "Blue Level:", Theme::getInstance()->fg_light->foreground},
|
||||||
};
|
};
|
||||||
|
|
||||||
NewButton button_sample{
|
NewButton button_sample{
|
||||||
@ -789,6 +802,11 @@ class SetMenuColorView : public View {
|
|||||||
' ',
|
' ',
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Button button_reset{
|
||||||
|
{2 * 8, 13 * 16, 12 * 8, 32},
|
||||||
|
"Reset",
|
||||||
|
};
|
||||||
|
|
||||||
Button button_save{
|
Button button_save{
|
||||||
{2 * 8, 16 * 16, 12 * 8, 32},
|
{2 * 8, 16 * 16, 12 * 8, 32},
|
||||||
"Save"};
|
"Save"};
|
||||||
@ -817,8 +835,8 @@ class SetAutostartView : public View {
|
|||||||
"nav"sv,
|
"nav"sv,
|
||||||
{{"autostart_app"sv, &autostart_app}}};
|
{{"autostart_app"sv, &autostart_app}}};
|
||||||
Labels labels{
|
Labels labels{
|
||||||
{{1 * 8, 1 * 16}, "Select app to start on boot", Color::light_grey()},
|
{{1 * 8, 1 * 16}, "Select app to start on boot", Theme::getInstance()->fg_light->foreground},
|
||||||
{{2 * 8, 2 * 16}, "(an SD Card is required)", Color::light_grey()}};
|
{{2 * 8, 2 * 16}, "(an SD Card is required)", Theme::getInstance()->fg_light->foreground}};
|
||||||
|
|
||||||
Button button_save{
|
Button button_save{
|
||||||
{2 * 8, 16 * 16, 12 * 8, 32},
|
{2 * 8, 16 * 16, 12 * 8, 32},
|
||||||
@ -835,6 +853,81 @@ class SetAutostartView : public View {
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class SetThemeView : public View {
|
||||||
|
public:
|
||||||
|
SetThemeView(NavigationView& nav);
|
||||||
|
|
||||||
|
void focus() override;
|
||||||
|
|
||||||
|
std::string title() const override { return "Theme"; };
|
||||||
|
|
||||||
|
private:
|
||||||
|
int32_t selected = 0;
|
||||||
|
Labels labels{
|
||||||
|
{{1 * 8, 1 * 16}, "Select a theme.", Theme::getInstance()->fg_light->foreground},
|
||||||
|
{{1 * 8, 2 * 16}, "Restart PP to fully apply!", Theme::getInstance()->fg_light->foreground}};
|
||||||
|
|
||||||
|
Button button_save{
|
||||||
|
{2 * 8, 16 * 16, 12 * 8, 32},
|
||||||
|
"Save"};
|
||||||
|
|
||||||
|
OptionsField options{
|
||||||
|
{8 * 8, 4 * 16},
|
||||||
|
30,
|
||||||
|
{
|
||||||
|
{"Default - Grey", 0},
|
||||||
|
{"Yellow", 1},
|
||||||
|
{"Aqua", 2},
|
||||||
|
{"Green", 3},
|
||||||
|
{"Red", 4},
|
||||||
|
}};
|
||||||
|
|
||||||
|
Checkbox checkbox_menuset{
|
||||||
|
{2 * 8, 6 * 16},
|
||||||
|
23,
|
||||||
|
"Set Menu color too"};
|
||||||
|
|
||||||
|
Button button_cancel{
|
||||||
|
{16 * 8, 16 * 16, 12 * 8, 32},
|
||||||
|
"Cancel",
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
class SetBatteryView : public View {
|
||||||
|
public:
|
||||||
|
SetBatteryView(NavigationView& nav);
|
||||||
|
|
||||||
|
void focus() override;
|
||||||
|
|
||||||
|
std::string title() const override { return "Battery"; };
|
||||||
|
|
||||||
|
private:
|
||||||
|
int32_t selected = 0;
|
||||||
|
Labels labels{
|
||||||
|
{{1 * 8, 1 * 16}, "Override batt calculation", Theme::getInstance()->fg_light->foreground},
|
||||||
|
{{1 * 8, 2 * 16}, "method to voltage based", Theme::getInstance()->fg_light->foreground}};
|
||||||
|
Labels labels2{
|
||||||
|
{{1 * 8, 6 * 16}, "Reset IC's learned params.", Theme::getInstance()->fg_light->foreground}};
|
||||||
|
Button button_save{
|
||||||
|
{2 * 8, 16 * 16, 12 * 8, 32},
|
||||||
|
"Save"};
|
||||||
|
|
||||||
|
Checkbox checkbox_overridebatt{
|
||||||
|
{2 * 8, 4 * 16},
|
||||||
|
23,
|
||||||
|
"Override"};
|
||||||
|
|
||||||
|
Button button_cancel{
|
||||||
|
{16 * 8, 16 * 16, 12 * 8, 32},
|
||||||
|
"Cancel",
|
||||||
|
};
|
||||||
|
|
||||||
|
Button button_reset{
|
||||||
|
{2 * 8, 8 * 16, 12 * 8, 32},
|
||||||
|
"Reset",
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
class SettingsMenuView : public BtnGridView {
|
class SettingsMenuView : public BtnGridView {
|
||||||
public:
|
public:
|
||||||
SettingsMenuView(NavigationView& nav);
|
SettingsMenuView(NavigationView& nav);
|
||||||
|
@ -57,16 +57,16 @@ void SIGFRXView::paint(Painter& painter) {
|
|||||||
uint8_t i, xp;
|
uint8_t i, xp;
|
||||||
|
|
||||||
// portapack::display.drawBMP({0, 302-160}, fox_bmp);
|
// portapack::display.drawBMP({0, 302-160}, fox_bmp);
|
||||||
portapack::display.fill_rectangle({0, 16, 240, 160 - 16}, ui::Color::white());
|
portapack::display.fill_rectangle({0, 16, 240, 160 - 16}, Theme::getInstance()->bg_darkest->foreground);
|
||||||
for (i = 0; i < 6; i++) {
|
for (i = 0; i < 6; i++) {
|
||||||
xp = sigfrx_marks[i * 3];
|
xp = sigfrx_marks[i * 3];
|
||||||
painter.draw_string({(ui::Coord)sigfrx_marks[(i * 3) + 1], 144 - 20}, style_white, to_string_dec_uint(sigfrx_marks[(i * 3) + 2]));
|
painter.draw_string({(ui::Coord)sigfrx_marks[(i * 3) + 1], 144 - 20}, style_white, to_string_dec_uint(sigfrx_marks[(i * 3) + 2]));
|
||||||
portapack::display.draw_line({xp, 144 - 4}, {xp, 144}, ui::Color::black());
|
portapack::display.draw_line({xp, 144 - 4}, {xp, 144}, Theme::getInstance()->bg_darkest->background);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SIGFRXView::on_channel_spectrum(const ChannelSpectrum& spectrum) {
|
void SIGFRXView::on_channel_spectrum(const ChannelSpectrum& spectrum) {
|
||||||
portapack::display.fill_rectangle({0, 144, 240, 4}, ui::Color::white());
|
portapack::display.fill_rectangle({0, 144, 240, 4}, Theme::getInstance()->bg_darkest->foreground);
|
||||||
|
|
||||||
uint8_t xmax = 0, imax = 0;
|
uint8_t xmax = 0, imax = 0;
|
||||||
size_t i;
|
size_t i;
|
||||||
@ -97,7 +97,7 @@ void SIGFRXView::on_channel_spectrum(const ChannelSpectrum& spectrum) {
|
|||||||
|
|
||||||
last_channel = imax;
|
last_channel = imax;
|
||||||
|
|
||||||
portapack::display.fill_rectangle({(ui::Coord)(imax - 2), 144, 4, 4}, ui::Color::red());
|
portapack::display.fill_rectangle({(ui::Coord)(imax - 2), 144, 4, 4}, Theme::getInstance()->fg_red->foreground);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SIGFRXView::on_show() {
|
void SIGFRXView::on_show() {
|
||||||
@ -129,9 +129,9 @@ SIGFRXView::SIGFRXView(
|
|||||||
&text_data,
|
&text_data,
|
||||||
&button_exit});
|
&button_exit});
|
||||||
|
|
||||||
text_type.set_style(&Styles::bg_white);
|
text_type.set_style(Theme::getInstance()->bg_lightest);
|
||||||
text_channel.set_style(&Styles::bg_white);
|
text_channel.set_style(Theme::getInstance()->bg_lightest);
|
||||||
text_data.set_style(&Styles::bg_white);
|
text_data.set_style(Theme::getInstance()->bg_lightest);
|
||||||
|
|
||||||
button_exit.on_select = [&nav](Button&) {
|
button_exit.on_select = [&nav](Button&) {
|
||||||
nav.pop();
|
nav.pop();
|
||||||
|
@ -24,7 +24,6 @@
|
|||||||
#include "ui_widget.hpp"
|
#include "ui_widget.hpp"
|
||||||
#include "ui_painter.hpp"
|
#include "ui_painter.hpp"
|
||||||
#include "ui_menu.hpp"
|
#include "ui_menu.hpp"
|
||||||
#include "ui_styles.hpp"
|
|
||||||
#include "ui_navigation.hpp"
|
#include "ui_navigation.hpp"
|
||||||
#include "clock_manager.hpp"
|
#include "clock_manager.hpp"
|
||||||
#include "message.hpp"
|
#include "message.hpp"
|
||||||
|
@ -72,15 +72,15 @@ class SigGenView : public View {
|
|||||||
bool auto_update{false};
|
bool auto_update{false};
|
||||||
|
|
||||||
Labels labels{
|
Labels labels{
|
||||||
{{3 * 8, 4 + 10}, "Shape:", Color::light_grey()},
|
{{3 * 8, 4 + 10}, "Shape:", Theme::getInstance()->fg_light->foreground},
|
||||||
{{6 * 8, 7 * 8}, "Tone: Hz", Color::light_grey()},
|
{{6 * 8, 7 * 8}, "Tone: Hz", Theme::getInstance()->fg_light->foreground},
|
||||||
{{22 * 8, 15 * 8 + 4}, "s.", Color::light_grey()},
|
{{22 * 8, 15 * 8 + 4}, "s.", Theme::getInstance()->fg_light->foreground},
|
||||||
{{8 * 8, 20 * 8}, "Modulation: FM", Color::light_grey()}};
|
{{8 * 8, 20 * 8}, "Modulation: FM", Theme::getInstance()->fg_light->foreground}};
|
||||||
|
|
||||||
ImageOptionsField options_shape{
|
ImageOptionsField options_shape{
|
||||||
{10 * 8, 4, 32, 32},
|
{10 * 8, 4, 32, 32},
|
||||||
Color::white(),
|
Theme::getInstance()->bg_darkest->foreground,
|
||||||
Color::black(),
|
Theme::getInstance()->bg_darkest->background,
|
||||||
{{&bitmap_sig_cw, 0},
|
{{&bitmap_sig_cw, 0},
|
||||||
{&bitmap_sig_sine, 1},
|
{&bitmap_sig_sine, 1},
|
||||||
{&bitmap_sig_tri, 2},
|
{&bitmap_sig_tri, 2},
|
||||||
|
@ -187,4 +187,8 @@ void SondeView::on_packet(const sonde::Packet& packet) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SondeView::on_freqchg(int64_t freq) {
|
||||||
|
field_frequency.set_value(freq);
|
||||||
|
}
|
||||||
|
|
||||||
} /* namespace ui */
|
} /* namespace ui */
|
||||||
|
@ -94,14 +94,14 @@ class SondeView : public View {
|
|||||||
// AudioOutput audio_output { };
|
// AudioOutput audio_output { };
|
||||||
|
|
||||||
Labels labels{
|
Labels labels{
|
||||||
{{4 * 8, 2 * 16}, "Type:", Color::light_grey()},
|
{{4 * 8, 2 * 16}, "Type:", Theme::getInstance()->fg_light->foreground},
|
||||||
{{6 * 8, 3 * 16}, "ID:", Color::light_grey()},
|
{{6 * 8, 3 * 16}, "ID:", Theme::getInstance()->fg_light->foreground},
|
||||||
{{0 * 8, 4 * 16}, "DateTime:", Color::light_grey()},
|
{{0 * 8, 4 * 16}, "DateTime:", Theme::getInstance()->fg_light->foreground},
|
||||||
|
|
||||||
{{3 * 8, 5 * 16}, "Vbatt:", Color::light_grey()},
|
{{3 * 8, 5 * 16}, "Vbatt:", Theme::getInstance()->fg_light->foreground},
|
||||||
{{3 * 8, 6 * 16}, "Frame:", Color::light_grey()},
|
{{3 * 8, 6 * 16}, "Frame:", Theme::getInstance()->fg_light->foreground},
|
||||||
{{4 * 8, 7 * 16}, "Temp:", Color::light_grey()},
|
{{4 * 8, 7 * 16}, "Temp:", Theme::getInstance()->fg_light->foreground},
|
||||||
{{0 * 8, 8 * 16}, "Humidity:", Color::light_grey()}};
|
{{0 * 8, 8 * 16}, "Humidity:", Theme::getInstance()->fg_light->foreground}};
|
||||||
|
|
||||||
RxFrequencyField field_frequency{
|
RxFrequencyField field_frequency{
|
||||||
{0 * 8, 0 * 8},
|
{0 * 8, 0 * 8},
|
||||||
@ -195,6 +195,14 @@ class SondeView : public View {
|
|||||||
const auto message = static_cast<const OrientationDataMessage*>(p);
|
const auto message = static_cast<const OrientationDataMessage*>(p);
|
||||||
this->on_orientation(message);
|
this->on_orientation(message);
|
||||||
}};
|
}};
|
||||||
|
MessageHandlerRegistration message_handler_freqchg{
|
||||||
|
Message::ID::FreqChangeCommand,
|
||||||
|
[this](Message* const p) {
|
||||||
|
const auto message = static_cast<const FreqChangeCommandMessage*>(p);
|
||||||
|
this->on_freqchg(message->freq);
|
||||||
|
}};
|
||||||
|
|
||||||
|
void on_freqchg(int64_t freq);
|
||||||
|
|
||||||
void on_gps(const GPSPosDataMessage* msg);
|
void on_gps(const GPSPosDataMessage* msg);
|
||||||
void on_orientation(const OrientationDataMessage* msg);
|
void on_orientation(const OrientationDataMessage* msg);
|
||||||
|
@ -48,12 +48,12 @@ void ScreenshotViewer::paint(Painter& painter) {
|
|||||||
painter.fill_rectangle({0, 0, screen_width, screen_height}, Color::black());
|
painter.fill_rectangle({0, 0, screen_width, screen_height}, Color::black());
|
||||||
|
|
||||||
auto show_invalid = [&]() {
|
auto show_invalid = [&]() {
|
||||||
painter.draw_string({10, 160}, Styles::white, "Not a valid screenshot.");
|
painter.draw_string({10, 160}, *Theme::getInstance()->bg_darkest, "Not a valid screenshot.");
|
||||||
};
|
};
|
||||||
|
|
||||||
auto error = file.open(path_);
|
auto error = file.open(path_);
|
||||||
if (error) {
|
if (error) {
|
||||||
painter.draw_string({10, 160}, Styles::white, error->what());
|
painter.draw_string({10, 160}, *Theme::getInstance()->bg_darkest, error->what());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -120,13 +120,13 @@ void SplashViewer::paint(Painter& painter) {
|
|||||||
painter.fill_rectangle({0, 0, screen_width, screen_height}, Color::black());
|
painter.fill_rectangle({0, 0, screen_width, screen_height}, Color::black());
|
||||||
|
|
||||||
if (!portapack::display.drawBMP2({0, 0}, path_)) {
|
if (!portapack::display.drawBMP2({0, 0}, path_)) {
|
||||||
painter.draw_string({10, 160}, Styles::white, "Not a valid splash image.");
|
painter.draw_string({10, 160}, *Theme::getInstance()->bg_darkest, "Not a valid splash image.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Show option to set splash screen if it's not already the splash screen
|
// Show option to set splash screen if it's not already the splash screen
|
||||||
if (!path_iequal(path_, splash_dot_bmp)) {
|
if (!path_iequal(path_, splash_dot_bmp)) {
|
||||||
painter.draw_string({0, 0}, Styles::white, "*RIGHT BUTTON UPDATES SPLASH*");
|
painter.draw_string({0, 0}, *Theme::getInstance()->bg_darkest, "*RIGHT BUTTON UPDATES SPLASH*");
|
||||||
valid_image = true;
|
valid_image = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -26,7 +26,6 @@
|
|||||||
#include "ui.hpp"
|
#include "ui.hpp"
|
||||||
#include "ui_navigation.hpp"
|
#include "ui_navigation.hpp"
|
||||||
#include "ui_painter.hpp"
|
#include "ui_painter.hpp"
|
||||||
#include "ui_styles.hpp"
|
|
||||||
#include "ui_widget.hpp"
|
#include "ui_widget.hpp"
|
||||||
#include "file.hpp"
|
#include "file.hpp"
|
||||||
|
|
||||||
|
82
firmware/application/apps/ui_standalone_view.cpp
Normal file
82
firmware/application/apps/ui_standalone_view.cpp
Normal file
@ -0,0 +1,82 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2024 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 "ui_standalone_view.hpp"
|
||||||
|
#include "irq_controls.hpp"
|
||||||
|
|
||||||
|
namespace ui {
|
||||||
|
|
||||||
|
void create_thread(int32_t (*fn)(void*), void* arg, size_t stack_size, int priority) {
|
||||||
|
// TODO: collect memory on terminate, once this is used
|
||||||
|
chThdCreateFromHeap(NULL, stack_size, priority, fn, arg);
|
||||||
|
}
|
||||||
|
|
||||||
|
void fill_rectangle(int x, int y, int width, int height, uint16_t color) {
|
||||||
|
ui::Painter painter;
|
||||||
|
painter.fill_rectangle({x, y, width, height}, ui::Color(color));
|
||||||
|
}
|
||||||
|
|
||||||
|
void* alloc(size_t size) {
|
||||||
|
void* p = chHeapAlloc(0x0, size);
|
||||||
|
if (p == nullptr)
|
||||||
|
chDbgPanic("Out of Memory");
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t get_switches_state_ulong() {
|
||||||
|
return get_switches_state().to_ulong();
|
||||||
|
}
|
||||||
|
|
||||||
|
standalone_application_api_t api = {
|
||||||
|
/* .malloc = */ &alloc,
|
||||||
|
/* .calloc = */ &calloc,
|
||||||
|
/* .realloc = */ &realloc,
|
||||||
|
/* .free = */ &chHeapFree,
|
||||||
|
/* .create_thread = */ &create_thread,
|
||||||
|
/* .fill_rectangle = */ &fill_rectangle,
|
||||||
|
/* .swizzled_switches = */ &swizzled_switches,
|
||||||
|
/* .get_switches_state = */ &get_switches_state_ulong,
|
||||||
|
};
|
||||||
|
|
||||||
|
StandaloneView::StandaloneView(NavigationView& nav, std::unique_ptr<uint8_t[]> app_image)
|
||||||
|
: nav_(nav), _app_image(std::move(app_image)) {
|
||||||
|
get_application_information()->initialize(api);
|
||||||
|
add_children({&dummy});
|
||||||
|
}
|
||||||
|
|
||||||
|
void StandaloneView::focus() {
|
||||||
|
dummy.focus();
|
||||||
|
}
|
||||||
|
|
||||||
|
void StandaloneView::paint(Painter& painter) {
|
||||||
|
(void)painter;
|
||||||
|
}
|
||||||
|
|
||||||
|
void StandaloneView::frame_sync() {
|
||||||
|
// skip first refresh
|
||||||
|
if (!initialized) {
|
||||||
|
initialized = true;
|
||||||
|
} else {
|
||||||
|
get_application_information()->on_event(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace ui
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2023 Bernd Herzog
|
* Copyright (C) 2024 Bernd Herzog
|
||||||
*
|
*
|
||||||
* This file is part of PortaPack.
|
* This file is part of PortaPack.
|
||||||
*
|
*
|
||||||
@ -19,22 +19,24 @@
|
|||||||
* Boston, MA 02110-1301, USA.
|
* Boston, MA 02110-1301, USA.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef __UI_PACMAN_H__
|
#ifndef __UI_STANDALONE_VIEW_H__
|
||||||
#define __UI_PACMAN_H__
|
#define __UI_STANDALONE_VIEW_H__
|
||||||
|
|
||||||
#include "ui_navigation.hpp"
|
#include "ui_navigation.hpp"
|
||||||
#include "event_m0.hpp"
|
#include "event_m0.hpp"
|
||||||
#include "message.hpp"
|
#include "message.hpp"
|
||||||
|
#include "standalone_app.hpp"
|
||||||
|
|
||||||
namespace ui::external_app::pacman {
|
namespace ui {
|
||||||
|
|
||||||
class PacmanView : public View {
|
class StandaloneView : public View {
|
||||||
public:
|
public:
|
||||||
PacmanView(NavigationView& nav);
|
StandaloneView(NavigationView& nav, std::unique_ptr<uint8_t[]> app_image);
|
||||||
|
virtual ~StandaloneView() override { get_application_information()->shutdown(); }
|
||||||
|
|
||||||
void focus() override;
|
void focus() override;
|
||||||
|
|
||||||
std::string title() const override { return "Pac-Man"; };
|
std::string title() const override { return (const char*)get_application_information()->app_name; };
|
||||||
|
|
||||||
void paint(Painter& painter) override;
|
void paint(Painter& painter) override;
|
||||||
void frame_sync();
|
void frame_sync();
|
||||||
@ -42,6 +44,10 @@ class PacmanView : public View {
|
|||||||
private:
|
private:
|
||||||
bool initialized = false;
|
bool initialized = false;
|
||||||
NavigationView& nav_;
|
NavigationView& nav_;
|
||||||
|
std::unique_ptr<uint8_t[]> _app_image;
|
||||||
|
standalone_application_information_t* get_application_information() const {
|
||||||
|
return reinterpret_cast<standalone_application_information_t*>(_app_image.get());
|
||||||
|
}
|
||||||
|
|
||||||
Button dummy{
|
Button dummy{
|
||||||
{240, 0, 0, 0},
|
{240, 0, 0, 0},
|
||||||
@ -54,6 +60,6 @@ class PacmanView : public View {
|
|||||||
}};
|
}};
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace ui::external_app::pacman
|
} // namespace ui
|
||||||
|
|
||||||
#endif /*__UI_PACMAN_H__*/
|
#endif /*__UI_STANDALONE_VIEW_H__*/
|
@ -32,12 +32,15 @@ using namespace ui;
|
|||||||
namespace ui {
|
namespace ui {
|
||||||
|
|
||||||
void SubGhzDRecentEntryDetailView::update_data() {
|
void SubGhzDRecentEntryDetailView::update_data() {
|
||||||
|
// process protocol data
|
||||||
|
parseProtocol();
|
||||||
// set text elements
|
// set text elements
|
||||||
text_type.set(SubGhzDView::getSensorTypeName((FPROTO_SUBGHZD_SENSOR)entry_.sensorType));
|
text_type.set(SubGhzDView::getSensorTypeName((FPROTO_SUBGHZD_SENSOR)entry_.sensorType));
|
||||||
text_id.set("0x" + to_string_hex(entry_.serial));
|
|
||||||
|
text_id.set("0x" + to_string_hex(serial));
|
||||||
if (entry_.bits > 0) console.writeln("Bits: " + to_string_dec_uint(entry_.bits));
|
if (entry_.bits > 0) console.writeln("Bits: " + to_string_dec_uint(entry_.bits));
|
||||||
if (entry_.btn != SD_NO_BTN) console.writeln("Btn: " + to_string_dec_uint(entry_.btn));
|
if (btn != SD_NO_BTN) console.writeln("Btn: " + to_string_dec_uint(btn));
|
||||||
if (entry_.cnt != SD_NO_CNT) console.writeln("Cnt: " + to_string_dec_uint(entry_.cnt));
|
if (cnt != SD_NO_CNT) console.writeln("Cnt: " + to_string_dec_uint(cnt));
|
||||||
|
|
||||||
if (entry_.data != 0) console.writeln("Data: " + to_string_hex(entry_.data));
|
if (entry_.data != 0) console.writeln("Data: " + to_string_hex(entry_.data));
|
||||||
}
|
}
|
||||||
@ -81,7 +84,7 @@ SubGhzDView::SubGhzDView(NavigationView& nav)
|
|||||||
recent.clear();
|
recent.clear();
|
||||||
recent_entries_view.set_dirty();
|
recent_entries_view.set_dirty();
|
||||||
};
|
};
|
||||||
field_frequency.set_step(100000);
|
field_frequency.set_step(10000);
|
||||||
|
|
||||||
const Rect content_rect{0, header_height, screen_width, screen_height - header_height};
|
const Rect content_rect{0, header_height, screen_width, screen_height - header_height};
|
||||||
recent_entries_view.set_parent_rect(content_rect);
|
recent_entries_view.set_parent_rect(content_rect);
|
||||||
@ -103,7 +106,7 @@ void SubGhzDView::on_tick_second() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void SubGhzDView::on_data(const SubGhzDDataMessage* data) {
|
void SubGhzDView::on_data(const SubGhzDDataMessage* data) {
|
||||||
SubGhzDRecentEntry key{data->sensorType, data->serial, data->bits, data->data, data->btn, data->cnt};
|
SubGhzDRecentEntry key{data->sensorType, data->data, data->bits};
|
||||||
auto matching_recent = find(recent, key.key());
|
auto matching_recent = find(recent, key.key());
|
||||||
if (matching_recent != std::end(recent)) {
|
if (matching_recent != std::end(recent)) {
|
||||||
// Found within. Move to front of list, increment counter.
|
// Found within. Move to front of list, increment counter.
|
||||||
@ -203,6 +206,16 @@ const char* SubGhzDView::getSensorTypeName(FPROTO_SUBGHZD_SENSOR type) {
|
|||||||
return "Star Line";
|
return "Star Line";
|
||||||
case FPS_X10:
|
case FPS_X10:
|
||||||
return "X10";
|
return "X10";
|
||||||
|
case FPS_LEGRAND:
|
||||||
|
return "Legrand";
|
||||||
|
case FPS_SOMIFY_KEYTIS:
|
||||||
|
return "Somify Keytis";
|
||||||
|
case FPS_SOMIFY_TELIS:
|
||||||
|
return "Somify Telis";
|
||||||
|
case FPS_GANGQI:
|
||||||
|
return "GangQi";
|
||||||
|
case FPS_MARANTEC24:
|
||||||
|
return "Marantec24";
|
||||||
case FPS_Invalid:
|
case FPS_Invalid:
|
||||||
default:
|
default:
|
||||||
return "Unknown";
|
return "Unknown";
|
||||||
@ -214,6 +227,10 @@ std::string SubGhzDView::pad_string_with_spaces(int snakes) {
|
|||||||
return paddedStr;
|
return paddedStr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SubGhzDView::on_freqchg(int64_t freq) {
|
||||||
|
field_frequency.set_value(freq);
|
||||||
|
}
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
void RecentEntriesTable<ui::SubGhzDRecentEntries>::draw(
|
void RecentEntriesTable<ui::SubGhzDRecentEntries>::draw(
|
||||||
const Entry& entry,
|
const Entry& entry,
|
||||||
@ -224,7 +241,7 @@ void RecentEntriesTable<ui::SubGhzDRecentEntries>::draw(
|
|||||||
line.reserve(30);
|
line.reserve(30);
|
||||||
|
|
||||||
line = SubGhzDView::getSensorTypeName((FPROTO_SUBGHZD_SENSOR)entry.sensorType);
|
line = SubGhzDView::getSensorTypeName((FPROTO_SUBGHZD_SENSOR)entry.sensorType);
|
||||||
line = line + " " + to_string_hex(entry.serial);
|
line = line + " " + to_string_hex(entry.data << 32);
|
||||||
if (line.length() < 19) {
|
if (line.length() < 19) {
|
||||||
line += SubGhzDView::pad_string_with_spaces(19 - line.length());
|
line += SubGhzDView::pad_string_with_spaces(19 - line.length());
|
||||||
} else {
|
} else {
|
||||||
@ -239,4 +256,482 @@ void RecentEntriesTable<ui::SubGhzDRecentEntries>::draw(
|
|||||||
painter.draw_string(target_rect.location(), style, line);
|
painter.draw_string(target_rect.location(), style, line);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// decoder helper functions
|
||||||
|
|
||||||
|
void atomo_decrypt(uint8_t* buff) {
|
||||||
|
buff[0] = (buff[0] ^ 5) & 0x7F;
|
||||||
|
uint8_t tmpB = (-buff[0]) & 0x7F;
|
||||||
|
|
||||||
|
uint8_t bitCnt = 8;
|
||||||
|
while (bitCnt < 59) {
|
||||||
|
if ((tmpB & 0x18) && (((tmpB / 8) & 3) != 3)) {
|
||||||
|
tmpB = ((tmpB << 1) & 0xFF) | 1;
|
||||||
|
} else {
|
||||||
|
tmpB = (tmpB << 1) & 0xFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tmpB & 0x80) {
|
||||||
|
buff[bitCnt / 8] ^= (0x80 >> (bitCnt & 7));
|
||||||
|
}
|
||||||
|
|
||||||
|
bitCnt++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const uint32_t came_twee_magic_numbers_xor[15] = {
|
||||||
|
0x0E0E0E00,
|
||||||
|
0x1D1D1D11,
|
||||||
|
0x2C2C2C22,
|
||||||
|
0x3B3B3B33,
|
||||||
|
0x4A4A4A44,
|
||||||
|
0x59595955,
|
||||||
|
0x68686866,
|
||||||
|
0x77777777,
|
||||||
|
0x86868688,
|
||||||
|
0x95959599,
|
||||||
|
0xA4A4A4AA,
|
||||||
|
0xB3B3B3BB,
|
||||||
|
0xC2C2C2CC,
|
||||||
|
0xD1D1D1DD,
|
||||||
|
0xE0E0E0EE,
|
||||||
|
};
|
||||||
|
|
||||||
|
// to save some byte of fw space, these will be inline. unreadeable? yes. needs a tons of free space? certanly. so sorry for this.
|
||||||
|
|
||||||
|
void SubGhzDRecentEntryDetailView::parseProtocol() {
|
||||||
|
btn = SD_NO_BTN;
|
||||||
|
cnt = SD_NO_CNT;
|
||||||
|
serial = 0;
|
||||||
|
|
||||||
|
if (entry_.sensorType == FPS_Invalid) return;
|
||||||
|
|
||||||
|
if (entry_.sensorType == FPS_BETT) {
|
||||||
|
return; // needs dip pattern output.
|
||||||
|
}
|
||||||
|
|
||||||
|
if (entry_.sensorType == FPS_AIRFORCE || entry_.sensorType == FPS_PRASTEL || entry_.sensorType == FPS_CAME) {
|
||||||
|
return; // nothing
|
||||||
|
}
|
||||||
|
|
||||||
|
if (entry_.sensorType == FPS_CAMEATOMO) {
|
||||||
|
entry_.data ^= 0xFFFFFFFFFFFFFFFF;
|
||||||
|
entry_.data <<= 4;
|
||||||
|
uint8_t pack[8] = {};
|
||||||
|
pack[0] = (entry_.data >> 56);
|
||||||
|
pack[1] = ((entry_.data >> 48) & 0xFF);
|
||||||
|
pack[2] = ((entry_.data >> 40) & 0xFF);
|
||||||
|
pack[3] = ((entry_.data >> 32) & 0xFF);
|
||||||
|
pack[4] = ((entry_.data >> 24) & 0xFF);
|
||||||
|
pack[5] = ((entry_.data >> 16) & 0xFF);
|
||||||
|
pack[6] = ((entry_.data >> 8) & 0xFF);
|
||||||
|
pack[7] = (entry_.data & 0xFF);
|
||||||
|
|
||||||
|
atomo_decrypt(pack);
|
||||||
|
|
||||||
|
// cnt_2 = pack[0];
|
||||||
|
cnt = (uint16_t)pack[1] << 8 | pack[2];
|
||||||
|
serial = (uint32_t)(pack[3]) << 24 | pack[4] << 16 | pack[5] << 8 | pack[6];
|
||||||
|
|
||||||
|
uint8_t btn_decode = (pack[7] >> 4);
|
||||||
|
if (btn_decode == 0x0) {
|
||||||
|
btn = 0x1;
|
||||||
|
} else if (btn_decode == 0x2) {
|
||||||
|
btn = 0x2;
|
||||||
|
} else if (btn_decode == 0x4) {
|
||||||
|
btn = 0x3;
|
||||||
|
} else if (btn_decode == 0x6) {
|
||||||
|
btn = 0x4;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (entry_.sensorType == FPS_CAMETWEE) {
|
||||||
|
uint8_t cnt_parcel = (uint8_t)(entry_.data & 0xF);
|
||||||
|
uint32_t data = (uint32_t)(entry_.data & 0x0FFFFFFFF);
|
||||||
|
|
||||||
|
data = (data ^ came_twee_magic_numbers_xor[cnt_parcel]);
|
||||||
|
serial = data;
|
||||||
|
data /= 4;
|
||||||
|
btn = (data >> 4) & 0x0F;
|
||||||
|
data >>= 16;
|
||||||
|
data = (uint16_t)FProtoGeneral::subghz_protocol_blocks_reverse_key(data, 16);
|
||||||
|
cnt = data >> 6;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (entry_.sensorType == FPS_CHAMBCODE) {
|
||||||
|
return; // nothing
|
||||||
|
}
|
||||||
|
|
||||||
|
if (entry_.sensorType == FPS_CLEMSA) {
|
||||||
|
serial = (entry_.data >> 2) & 0xFFFF;
|
||||||
|
btn = (entry_.data & 0x03);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (entry_.sensorType == FPS_DOITRAND) {
|
||||||
|
cnt = (entry_.data >> 24) | ((entry_.data >> 15) & 0x1);
|
||||||
|
btn = ((entry_.data >> 18) & 0x3);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (entry_.sensorType == FPS_DOOYA) {
|
||||||
|
serial = (entry_.data >> 16);
|
||||||
|
if ((entry_.data >> 12) & 0x0F) {
|
||||||
|
cnt = (entry_.data >> 8) & 0x0F;
|
||||||
|
} else {
|
||||||
|
cnt = 0xff;
|
||||||
|
}
|
||||||
|
btn = entry_.data & 0xFF;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (entry_.sensorType == FPS_FAAC) { // stripped down a lot.
|
||||||
|
uint32_t code_fix = entry_.data >> 32;
|
||||||
|
uint32_t code_hop = entry_.data & 0xFFFFFFFF;
|
||||||
|
// uint32_t decrypt = 0;
|
||||||
|
// uint64_t man;
|
||||||
|
|
||||||
|
uint8_t data_tmp = 0;
|
||||||
|
uint8_t data_prg[8];
|
||||||
|
data_prg[0] = (code_hop & 0xFF);
|
||||||
|
data_prg[1] = ((code_hop >> 8) & 0xFF);
|
||||||
|
data_prg[2] = ((code_hop >> 16) & 0xFF);
|
||||||
|
data_prg[3] = (code_hop >> 24);
|
||||||
|
data_prg[4] = (code_fix & 0xFF);
|
||||||
|
data_prg[5] = ((code_fix >> 8) & 0xFF);
|
||||||
|
data_prg[6] = ((code_fix >> 16) & 0xFF);
|
||||||
|
data_prg[7] = (code_fix >> 24);
|
||||||
|
|
||||||
|
if (((data_prg[7] == 0x52) && (data_prg[6] == 0x0F) && (data_prg[0] == 0x00))) {
|
||||||
|
// ProgMode ON
|
||||||
|
for (uint8_t i = data_prg[1] & 0xF; i != 0; i--) {
|
||||||
|
data_tmp = data_prg[2];
|
||||||
|
|
||||||
|
data_prg[2] = data_prg[2] >> 1 | (data_prg[3] & 1) << 7;
|
||||||
|
data_prg[3] = data_prg[3] >> 1 | (data_prg[4] & 1) << 7;
|
||||||
|
data_prg[4] = data_prg[4] >> 1 | (data_prg[5] & 1) << 7;
|
||||||
|
data_prg[5] = data_prg[5] >> 1 | (data_tmp & 1) << 7;
|
||||||
|
}
|
||||||
|
data_prg[2] ^= data_prg[1];
|
||||||
|
data_prg[3] ^= data_prg[1];
|
||||||
|
data_prg[4] ^= data_prg[1];
|
||||||
|
data_prg[5] ^= data_prg[1];
|
||||||
|
seed = data_prg[5] << 24 | data_prg[4] << 16 | data_prg[3] << 8 | data_prg[2];
|
||||||
|
// uint32_t dec_prg_1 = data_prg[7] << 24 | data_prg[6] << 16 | data_prg[5] << 8 | data_prg[4];
|
||||||
|
// uint32_t dec_prg_2 = data_prg[3] << 24 | data_prg[2] << 16 | data_prg[1] << 8 | data_prg[0];
|
||||||
|
// entry_.data_2 = (uint64_t)dec_prg_1 << 32 | dec_prg_2;
|
||||||
|
cnt = data_prg[1];
|
||||||
|
} else {
|
||||||
|
if (code_fix != 0x0) {
|
||||||
|
serial = code_fix >> 4;
|
||||||
|
btn = code_fix & 0xF;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (entry_.sensorType == FPS_GATETX) {
|
||||||
|
uint32_t code_found_reverse = FProtoGeneral::subghz_protocol_blocks_reverse_key(entry_.data, entry_.bits);
|
||||||
|
serial = (code_found_reverse & 0xFF) << 12 | ((code_found_reverse >> 8) & 0xFF) << 4 | ((code_found_reverse >> 20) & 0x0F);
|
||||||
|
btn = ((code_found_reverse >> 16) & 0x0F);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (entry_.sensorType == FPS_HOLTEK) {
|
||||||
|
if ((entry_.data & 0xF000000000) == 0x5000000000) {
|
||||||
|
serial = FProtoGeneral::subghz_protocol_blocks_reverse_key((entry_.data >> 16) & 0xFFFFF, 20);
|
||||||
|
uint16_t btn_ = entry_.data & 0xFFFF;
|
||||||
|
if ((btn_ & 0xf) != 0xA) {
|
||||||
|
btn = 0x1 << 4 | (btn_ & 0xF);
|
||||||
|
} else if (((btn_ >> 4) & 0xF) != 0xA) {
|
||||||
|
btn = 0x2 << 4 | ((btn_ >> 4) & 0xF);
|
||||||
|
} else if (((btn_ >> 8) & 0xF) != 0xA) {
|
||||||
|
btn = 0x3 << 4 | ((btn_ >> 8) & 0xF);
|
||||||
|
} else if (((btn_ >> 12) & 0xF) != 0xA) {
|
||||||
|
btn = 0x4 << 4 | ((btn_ >> 12) & 0xF);
|
||||||
|
} else {
|
||||||
|
btn = 0;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
serial = 0;
|
||||||
|
btn = 0;
|
||||||
|
cnt = 0;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (entry_.sensorType == FPS_HOLTEKHT12X) {
|
||||||
|
btn = entry_.data & 0x0F;
|
||||||
|
cnt = (entry_.data >> 4) & 0xFF;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (entry_.sensorType == FPS_HONEYWELL) {
|
||||||
|
serial = (entry_.data >> 24) & 0xFFFFF;
|
||||||
|
btn = (entry_.data >> 16) & 0xFF; // not exactly button, but can contain btn data too.
|
||||||
|
cnt = (entry_.data >> 44) & 0xF;
|
||||||
|
/*
|
||||||
|
uint8_t contact = (entry_.databtn & 0x80) >> 7;
|
||||||
|
uint8_t tamper = (entry_.databtn & 0x40) >> 6;
|
||||||
|
uint8_t reed = (entry_.databtn & 0x20) >> 5;
|
||||||
|
uint8_t alarm = (entry_.databtn & 0x10) >> 4;
|
||||||
|
uint8_t battery_low = (entry_.databtn & 0x08) >> 3;
|
||||||
|
uint8_t heartbeat = (entry_.databtn & 0x04) >> 2;
|
||||||
|
*/
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (entry_.sensorType == FPS_HONEYWELLWDB) {
|
||||||
|
serial = (entry_.data >> 28) & 0xFFFFF;
|
||||||
|
// enabled, when we'll have extra fields and free fw space
|
||||||
|
/* switch ((entry_.data >> 20) & 0x3) {
|
||||||
|
case 0x02:
|
||||||
|
device_type = "Doorbell";
|
||||||
|
break;
|
||||||
|
case 0x01:
|
||||||
|
device_type = "PIR-Motion";
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
device_type = "Unknown";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch ((entry_.data >> 16) & 0x3) {
|
||||||
|
case 0x00:
|
||||||
|
alert = "Normal";
|
||||||
|
break;
|
||||||
|
case 0x01:
|
||||||
|
case 0x02:
|
||||||
|
alert = "High";
|
||||||
|
break;
|
||||||
|
case 0x03:
|
||||||
|
alert = "Full";
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
alert = "Unknown";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
secret_knock = (uint8_t)((entry_.data >> 4) & 0x1);
|
||||||
|
relay = (uint8_t)((entry_.data >> 3) & 0x1);
|
||||||
|
lowbat = (uint8_t)((entry_.data >> 1) & 0x1);*/
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (entry_.sensorType == FPS_HORMANN) {
|
||||||
|
btn = (entry_.data >> 8) & 0xF;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* if (entry_.sensorType == FPS_HORMANNBISECURE) { //fm not implemented
|
||||||
|
serial = 0;
|
||||||
|
|
||||||
|
for (uint8_t i = 1; i < 5; i++) {
|
||||||
|
serial = serial << 8 | ((uint8_t*)(&entry_.data))[i];
|
||||||
|
}
|
||||||
|
} */
|
||||||
|
|
||||||
|
if (entry_.sensorType == FPS_IDO) {
|
||||||
|
uint64_t code_found_reverse = FProtoGeneral::subghz_protocol_blocks_reverse_key(entry_.data, entry_.bits);
|
||||||
|
uint32_t code_fix = code_found_reverse & 0xFFFFFF;
|
||||||
|
serial = code_fix & 0xFFFFF;
|
||||||
|
btn = (code_fix >> 20) & 0x0F;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (entry_.sensorType == FPS_INTERTECHNOV3) {
|
||||||
|
if (entry_.bits == 32) {
|
||||||
|
serial = (entry_.data >> 6) & 0x3FFFFFF;
|
||||||
|
if ((entry_.data >> 5) & 0x1) {
|
||||||
|
cnt = 1 << 5;
|
||||||
|
} else {
|
||||||
|
cnt = (~entry_.data & 0xF);
|
||||||
|
}
|
||||||
|
btn = (entry_.data >> 4) & 0x1;
|
||||||
|
} else if (entry_.bits == 36) {
|
||||||
|
serial = (entry_.data >> 10) & 0x3FFFFFF;
|
||||||
|
if ((entry_.data >> 9) & 0x1) {
|
||||||
|
cnt = 1 << 5;
|
||||||
|
} else {
|
||||||
|
cnt = (~(entry_.data >> 4) & 0xF);
|
||||||
|
}
|
||||||
|
btn = (entry_.data) & 0xF;
|
||||||
|
} else {
|
||||||
|
serial = 0;
|
||||||
|
cnt = 0;
|
||||||
|
btn = 0;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (entry_.sensorType == FPS_KEELOQ) {
|
||||||
|
// too many sub protocol versions, skipping. maybe in future when we'll have much more fw space
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* fm not implemented
|
||||||
|
if (entry_.sensorType == FPS_KIA) {
|
||||||
|
serial = (uint32_t)((entry_.data >> 12) & 0x0FFFFFFF);
|
||||||
|
btn = (entry_.data >> 8) & 0x0F;
|
||||||
|
cnt = (entry_.data >> 40) & 0xFFFF;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (entry_.sensorType == FPS_KINGGATESSTYLO4K) {
|
||||||
|
uint64_t fix = FProtoGeneral::subghz_protocol_blocks_reverse_key(entry_.data, 53);
|
||||||
|
btn = (fix >> 17) & 0x0F;
|
||||||
|
serial = ((fix >> 5) & 0xFFFF0000) | (fix & 0xFFFF);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (entry_.sensorType == FPS_LEGRAND) {
|
||||||
|
return; // nothing
|
||||||
|
}
|
||||||
|
|
||||||
|
if (entry_.sensorType == FPS_LINEAR || entry_.sensorType == FPS_LINEARDELTA3) {
|
||||||
|
return; // nothing
|
||||||
|
}
|
||||||
|
|
||||||
|
if (entry_.sensorType == FPS_MAGELLAN) {
|
||||||
|
uint64_t data_rev = FProtoGeneral::subghz_protocol_blocks_reverse_key(entry_.data >> 8, 24);
|
||||||
|
serial = data_rev & 0xFFFF;
|
||||||
|
btn = (data_rev >> 16) & 0xFF;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (entry_.sensorType == FPS_MARANTEC) {
|
||||||
|
btn = (entry_.data >> 16) & 0xF;
|
||||||
|
serial = ((entry_.data >> 12) & 0xFFFFFF00) | ((entry_.data >> 8) & 0xFF);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (entry_.sensorType == FPS_MASTERCODE) {
|
||||||
|
serial = (entry_.data >> 4) & 0xFFFF;
|
||||||
|
btn = (entry_.data >> 2 & 0x03);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (entry_.sensorType == FPS_MEGACODE) {
|
||||||
|
if ((entry_.data >> 23) == 1) {
|
||||||
|
serial = (entry_.data >> 3) & 0xFFFF;
|
||||||
|
btn = entry_.data & 0b111;
|
||||||
|
cnt = (entry_.data >> 19) & 0b1111;
|
||||||
|
} else {
|
||||||
|
serial = 0;
|
||||||
|
btn = 0;
|
||||||
|
cnt = 0;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (entry_.sensorType == FPS_NERORADIO) {
|
||||||
|
return; // nothing
|
||||||
|
}
|
||||||
|
|
||||||
|
if (entry_.sensorType == FPS_NERO_SKETCH) {
|
||||||
|
return; // nothing
|
||||||
|
}
|
||||||
|
|
||||||
|
if (entry_.sensorType == FPS_NICEFLO || entry_.sensorType == FPS_NICEFLORS) {
|
||||||
|
return; // nothing, and can't
|
||||||
|
}
|
||||||
|
|
||||||
|
if (entry_.sensorType == FPS_PHOENIXV2) {
|
||||||
|
uint64_t data_rev = FProtoGeneral::subghz_protocol_blocks_reverse_key(entry_.data, entry_.bits + 4);
|
||||||
|
serial = data_rev & 0xFFFFFFFF;
|
||||||
|
cnt = (data_rev >> 40) & 0xFFFF;
|
||||||
|
btn = (data_rev >> 32) & 0xF;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (entry_.sensorType == FPS_POWERSMART) {
|
||||||
|
btn = ((entry_.data >> 54) & 0x02) | ((entry_.data >> 40) & 0x1);
|
||||||
|
serial = ((entry_.data >> 33) & 0x3FFF00) | ((entry_.data >> 32) & 0xFF);
|
||||||
|
cnt = ((entry_.data >> 49) & 0x3F);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (entry_.sensorType == FPS_PRINCETON) {
|
||||||
|
serial = entry_.data >> 4;
|
||||||
|
btn = entry_.data & 0xF;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (entry_.sensorType == FPS_SECPLUSV1) {
|
||||||
|
uint32_t fixed = (entry_.data >> 32) & 0xFFFFFFFF;
|
||||||
|
cnt = entry_.data & 0xFFFFFFFF;
|
||||||
|
btn = fixed % 3;
|
||||||
|
// uint8_t id0 = (fixed / 3) % 3;
|
||||||
|
uint8_t id1 = (fixed / 9) % 3;
|
||||||
|
// uint16_t pin = 0;
|
||||||
|
if (id1 == 0) {
|
||||||
|
// (fixed // 3**3) % (3**7) 3^3=27 3^73=72187
|
||||||
|
|
||||||
|
serial = (fixed / 27) % 2187;
|
||||||
|
// pin = (fixed // 3**10) % (3**9) 3^10=59049 3^9=19683
|
||||||
|
// pin = (fixed / 59049) % 19683;
|
||||||
|
|
||||||
|
/* if (pin <= 9999) {
|
||||||
|
furi_string_cat_printf(output, " pin:%d", pin);
|
||||||
|
} else if (pin <= 11029) {
|
||||||
|
furi_string_cat_printf(output, " pin:enter");
|
||||||
|
} */
|
||||||
|
} else {
|
||||||
|
// id = fixed / 27;
|
||||||
|
serial = fixed / 27;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (entry_.sensorType == FPS_SECPLUSV2) {
|
||||||
|
return; // fw space saver
|
||||||
|
}
|
||||||
|
|
||||||
|
if (entry_.sensorType == FPS_SMC5326) {
|
||||||
|
return; // dip pattern output needed. skipping
|
||||||
|
}
|
||||||
|
|
||||||
|
if (entry_.sensorType == FPS_STARLINE) {
|
||||||
|
uint64_t key = FProtoGeneral::subghz_protocol_blocks_reverse_key(entry_.data, entry_.bits);
|
||||||
|
uint32_t key_fix = key >> 32;
|
||||||
|
serial = key_fix & 0x00FFFFFF;
|
||||||
|
btn = key_fix >> 24;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (entry_.sensorType == FPS_X10) {
|
||||||
|
serial = (entry_.data & 0xF0000000) >> (24 + 4);
|
||||||
|
btn = (((entry_.data & 0x07000000) >> 24) | ((entry_.data & 0xF800) >> 8));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (entry_.sensorType == FPS_SOMIFY_KEYTIS) {
|
||||||
|
uint64_t dataa = entry_.data ^ (entry_.data >> 8);
|
||||||
|
btn = (dataa >> 48) & 0xF;
|
||||||
|
cnt = (dataa >> 24) & 0xFFFF;
|
||||||
|
serial = dataa & 0xFFFFFF;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (entry_.sensorType == FPS_SOMIFY_TELIS) {
|
||||||
|
uint64_t dataa = entry_.data ^ (entry_.data >> 8);
|
||||||
|
btn = (dataa >> 44) & 0xF; // ctrl
|
||||||
|
cnt = (dataa >> 24) & 0xFFFF; // rolling code
|
||||||
|
serial = dataa & 0xFFFFFF; // address}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (entry_.sensorType == FPS_GANGQI) {
|
||||||
|
btn = 0; // parser needs some time i think in flipper side.
|
||||||
|
cnt = (uint8_t)(entry_.data >> 32);
|
||||||
|
serial = (entry_.data & 0xFFFFFFFF);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (entry_.sensorType == FPS_MARANTEC24) {
|
||||||
|
serial = (entry_.data >> 4);
|
||||||
|
btn = entry_.data & 0xf;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
} // namespace ui
|
} // namespace ui
|
@ -23,6 +23,10 @@
|
|||||||
#ifndef __UI_SUBGHZD_H__
|
#ifndef __UI_SUBGHZD_H__
|
||||||
#define __UI_SUBGHZD_H__
|
#define __UI_SUBGHZD_H__
|
||||||
|
|
||||||
|
#define SD_NO_SERIAL 0xFFFFFFFF
|
||||||
|
#define SD_NO_BTN 0xFF
|
||||||
|
#define SD_NO_CNT 0xFF
|
||||||
|
|
||||||
#include "ui.hpp"
|
#include "ui.hpp"
|
||||||
#include "ui_navigation.hpp"
|
#include "ui_navigation.hpp"
|
||||||
#include "ui_receiver.hpp"
|
#include "ui_receiver.hpp"
|
||||||
@ -33,6 +37,7 @@
|
|||||||
#include "recent_entries.hpp"
|
#include "recent_entries.hpp"
|
||||||
|
|
||||||
#include "../baseband/fprotos/subghztypes.hpp"
|
#include "../baseband/fprotos/subghztypes.hpp"
|
||||||
|
#include "../baseband/fprotos/fprotogeneral.hpp"
|
||||||
|
|
||||||
using namespace ui;
|
using namespace ui;
|
||||||
|
|
||||||
@ -42,29 +47,20 @@ struct SubGhzDRecentEntry {
|
|||||||
using Key = uint64_t;
|
using Key = uint64_t;
|
||||||
static constexpr Key invalid_key = 0x0fffffff;
|
static constexpr Key invalid_key = 0x0fffffff;
|
||||||
uint8_t sensorType = FPS_Invalid;
|
uint8_t sensorType = FPS_Invalid;
|
||||||
uint8_t btn = SD_NO_BTN;
|
|
||||||
uint32_t serial = SD_NO_SERIAL;
|
|
||||||
uint16_t bits = 0;
|
uint16_t bits = 0;
|
||||||
uint16_t age = 0; // updated on each seconds, show how long the signal was last seen
|
uint16_t age = 0; // updated on each seconds, show how long the signal was last seen
|
||||||
uint32_t cnt = SD_NO_CNT;
|
|
||||||
uint64_t data = 0;
|
uint64_t data = 0;
|
||||||
SubGhzDRecentEntry() {}
|
SubGhzDRecentEntry() {}
|
||||||
SubGhzDRecentEntry(
|
SubGhzDRecentEntry(
|
||||||
uint8_t sensorType,
|
uint8_t sensorType,
|
||||||
uint32_t serial,
|
|
||||||
uint16_t bits = 0,
|
|
||||||
uint64_t data = 0,
|
uint64_t data = 0,
|
||||||
uint8_t btn = SD_NO_BTN,
|
uint16_t bits = 0)
|
||||||
uint32_t cnt = SD_NO_CNT)
|
|
||||||
: sensorType{sensorType},
|
: sensorType{sensorType},
|
||||||
btn{btn},
|
|
||||||
serial{serial},
|
|
||||||
bits{bits},
|
bits{bits},
|
||||||
cnt{cnt},
|
|
||||||
data{data} {
|
data{data} {
|
||||||
}
|
}
|
||||||
Key key() const {
|
Key key() const {
|
||||||
return (data ^ ((static_cast<uint64_t>(serial) << 32) | (static_cast<uint64_t>(sensorType) & 0xFF) << 0));
|
return (data ^ ((static_cast<uint64_t>(sensorType) & 0xFF) << 0));
|
||||||
}
|
}
|
||||||
void inc_age(int delta) {
|
void inc_age(int delta) {
|
||||||
if (UINT16_MAX - delta > age) age += delta;
|
if (UINT16_MAX - delta > age) age += delta;
|
||||||
@ -131,6 +127,14 @@ class SubGhzDView : public View {
|
|||||||
}};
|
}};
|
||||||
SubGhzDRecentEntriesView recent_entries_view{columns, recent};
|
SubGhzDRecentEntriesView recent_entries_view{columns, recent};
|
||||||
|
|
||||||
|
void on_freqchg(int64_t freq);
|
||||||
|
MessageHandlerRegistration message_handler_freqchg{
|
||||||
|
Message::ID::FreqChangeCommand,
|
||||||
|
[this](Message* const p) {
|
||||||
|
const auto message = static_cast<const FreqChangeCommandMessage*>(p);
|
||||||
|
this->on_freqchg(message->freq);
|
||||||
|
}};
|
||||||
|
|
||||||
MessageHandlerRegistration message_handler_packet{
|
MessageHandlerRegistration message_handler_packet{
|
||||||
Message::ID::SubGhzDData,
|
Message::ID::SubGhzDData,
|
||||||
[this](Message* const p) {
|
[this](Message* const p) {
|
||||||
@ -149,6 +153,12 @@ class SubGhzDRecentEntryDetailView : public View {
|
|||||||
private:
|
private:
|
||||||
NavigationView& nav_;
|
NavigationView& nav_;
|
||||||
SubGhzDRecentEntry entry_{};
|
SubGhzDRecentEntry entry_{};
|
||||||
|
|
||||||
|
uint32_t serial = 0;
|
||||||
|
uint8_t btn = SD_NO_BTN;
|
||||||
|
uint32_t cnt = SD_NO_CNT;
|
||||||
|
uint32_t seed = 0;
|
||||||
|
|
||||||
Text text_type{{0 * 8, 1 * 16, 15 * 8, 16}, "?"};
|
Text text_type{{0 * 8, 1 * 16, 15 * 8, 16}, "?"};
|
||||||
Text text_id{{6 * 8, 2 * 16, 10 * 8, 16}, "?"};
|
Text text_id{{6 * 8, 2 * 16, 10 * 8, 16}, "?"};
|
||||||
|
|
||||||
@ -156,14 +166,16 @@ class SubGhzDRecentEntryDetailView : public View {
|
|||||||
{0, 4 * 16, 240, screen_height - (4 * 16) - 36}};
|
{0, 4 * 16, 240, screen_height - (4 * 16) - 36}};
|
||||||
|
|
||||||
Labels labels{
|
Labels labels{
|
||||||
{{0 * 8, 0 * 16}, "Type:", Color::light_grey()},
|
{{0 * 8, 0 * 16}, "Type:", Theme::getInstance()->fg_light->foreground},
|
||||||
{{0 * 8, 2 * 16}, "Serial: ", Color::light_grey()},
|
{{0 * 8, 2 * 16}, "Serial: ", Theme::getInstance()->fg_light->foreground},
|
||||||
{{0 * 8, 3 * 16}, "Data:", Color::light_grey()},
|
{{0 * 8, 3 * 16}, "Data:", Theme::getInstance()->fg_light->foreground},
|
||||||
};
|
};
|
||||||
|
|
||||||
Button button_done{
|
Button button_done{
|
||||||
{screen_width - 96 - 4, screen_height - 32 - 12, 96, 32},
|
{screen_width - 96 - 4, screen_height - 32 - 12, 96, 32},
|
||||||
"Done"};
|
"Done"};
|
||||||
|
|
||||||
|
void parseProtocol();
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace ui
|
} // namespace ui
|
||||||
|
@ -76,7 +76,7 @@ class TestView : public View {
|
|||||||
bool logging{false};
|
bool logging{false};
|
||||||
|
|
||||||
Labels labels{
|
Labels labels{
|
||||||
{{0 * 8, 1 * 16}, "Data:", Color::light_grey()}};
|
{{0 * 8, 1 * 16}, "Data:", Theme::getInstance()->fg_light->foreground}};
|
||||||
|
|
||||||
RxFrequencyField field_frequency{
|
RxFrequencyField field_frequency{
|
||||||
{0 * 8, 0 * 8},
|
{0 * 8, 0 * 8},
|
||||||
|
@ -339,7 +339,7 @@ void TextViewer::reset_file(FileWrapper* file) {
|
|||||||
|
|
||||||
void TextViewer::set_font_zoom(bool zoom) {
|
void TextViewer::set_font_zoom(bool zoom) {
|
||||||
font_zoom = zoom;
|
font_zoom = zoom;
|
||||||
font_style = font_zoom ? &Styles::white : &Styles::white_small;
|
font_style = font_zoom ? Theme::getInstance()->bg_darkest : Theme::getInstance()->bg_darkest_small;
|
||||||
char_height = style().font.line_height();
|
char_height = style().font.line_height();
|
||||||
char_width = style().font.char_width();
|
char_width = style().font.char_width();
|
||||||
max_line = (uint8_t)(parent_rect().height() / char_height);
|
max_line = (uint8_t)(parent_rect().height() / char_height);
|
||||||
@ -425,8 +425,8 @@ TextEditorView::TextEditorView(NavigationView& nav)
|
|||||||
&text_size,
|
&text_size,
|
||||||
});
|
});
|
||||||
|
|
||||||
text_position.set_style(&Styles::bg_dark_blue);
|
text_position.set_style(Theme::getInstance()->option_active);
|
||||||
text_size.set_style(&Styles::bg_dark_blue);
|
text_size.set_style(Theme::getInstance()->option_active);
|
||||||
|
|
||||||
viewer.set_font_zoom(enable_zoom);
|
viewer.set_font_zoom(enable_zoom);
|
||||||
|
|
||||||
@ -542,7 +542,7 @@ void TextEditorView::open_file(const fs::path& path) {
|
|||||||
Painter p;
|
Painter p;
|
||||||
auto percent = (value * 100) / total;
|
auto percent = (value * 100) / total;
|
||||||
auto width = (percent * screen_width) / 100;
|
auto width = (percent * screen_width) / 100;
|
||||||
p.draw_hline({0, 16}, width, Color::yellow());
|
p.draw_hline({0, 16}, width, Theme::getInstance()->fg_yellow->foreground);
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!result) {
|
if (!result) {
|
||||||
@ -653,7 +653,7 @@ void TextEditorView::prepare_for_write() {
|
|||||||
|
|
||||||
// TODO: This would be nice to have but it causes a stack overflow in an ISR?
|
// TODO: This would be nice to have but it causes a stack overflow in an ISR?
|
||||||
// Painter p;
|
// Painter p;
|
||||||
// p.draw_string({2, 48}, Styles::yellow, "Creating temporary file...");
|
// p.draw_string({2, 48}, *Theme::getInstance()->fg_yellow, "Creating temporary file...");
|
||||||
|
|
||||||
// Copy to temp file on write.
|
// Copy to temp file on write.
|
||||||
has_temp_file_ = true;
|
has_temp_file_ = true;
|
||||||
|
@ -26,7 +26,6 @@
|
|||||||
#include "ui.hpp"
|
#include "ui.hpp"
|
||||||
#include "ui_navigation.hpp"
|
#include "ui_navigation.hpp"
|
||||||
#include "ui_painter.hpp"
|
#include "ui_painter.hpp"
|
||||||
#include "ui_styles.hpp"
|
|
||||||
#include "ui_widget.hpp"
|
#include "ui_widget.hpp"
|
||||||
|
|
||||||
#include "app_settings.hpp"
|
#include "app_settings.hpp"
|
||||||
@ -159,61 +158,61 @@ class TextEditorMenu : public View {
|
|||||||
|
|
||||||
Rectangle rect_frame{
|
Rectangle rect_frame{
|
||||||
{0 * 8, 0 * 8, 23 * 8, 23 * 8},
|
{0 * 8, 0 * 8, 23 * 8, 23 * 8},
|
||||||
Color::dark_grey()};
|
Theme::getInstance()->fg_dark->foreground};
|
||||||
|
|
||||||
NewButton button_home{
|
NewButton button_home{
|
||||||
{1 * 8, 1 * 8, 7 * 8, 7 * 8},
|
{1 * 8, 1 * 8, 7 * 8, 7 * 8},
|
||||||
"Home",
|
"Home",
|
||||||
&bitmap_arrow_left,
|
&bitmap_arrow_left,
|
||||||
Color::dark_grey()};
|
Theme::getInstance()->fg_dark->foreground};
|
||||||
|
|
||||||
NewButton button_end{
|
NewButton button_end{
|
||||||
{8 * 8, 1 * 8, 7 * 8, 7 * 8},
|
{8 * 8, 1 * 8, 7 * 8, 7 * 8},
|
||||||
"End",
|
"End",
|
||||||
&bitmap_arrow_right,
|
&bitmap_arrow_right,
|
||||||
Color::dark_grey()};
|
Theme::getInstance()->fg_dark->foreground};
|
||||||
|
|
||||||
NewButton button_zoom{
|
NewButton button_zoom{
|
||||||
{15 * 8, 1 * 8, 7 * 8, 7 * 8},
|
{15 * 8, 1 * 8, 7 * 8, 7 * 8},
|
||||||
"Zoom",
|
"Zoom",
|
||||||
&bitmap_icon_search,
|
&bitmap_icon_search,
|
||||||
Color::orange()};
|
Theme::getInstance()->fg_orange->foreground};
|
||||||
|
|
||||||
NewButton button_delline{
|
NewButton button_delline{
|
||||||
{1 * 8, 8 * 8, 7 * 8, 7 * 8},
|
{1 * 8, 8 * 8, 7 * 8, 7 * 8},
|
||||||
"-Line",
|
"-Line",
|
||||||
&bitmap_icon_delete,
|
&bitmap_icon_delete,
|
||||||
Color::dark_red()};
|
Theme::getInstance()->fg_red->foreground};
|
||||||
|
|
||||||
NewButton button_edit{
|
NewButton button_edit{
|
||||||
{8 * 8, 8 * 8, 7 * 8, 7 * 8},
|
{8 * 8, 8 * 8, 7 * 8, 7 * 8},
|
||||||
"Edit",
|
"Edit",
|
||||||
&bitmap_icon_rename,
|
&bitmap_icon_rename,
|
||||||
Color::dark_blue()};
|
Theme::getInstance()->fg_blue->foreground};
|
||||||
|
|
||||||
NewButton button_addline{
|
NewButton button_addline{
|
||||||
{15 * 8, 8 * 8, 7 * 8, 7 * 8},
|
{15 * 8, 8 * 8, 7 * 8, 7 * 8},
|
||||||
"+Line",
|
"+Line",
|
||||||
&bitmap_icon_scanner,
|
&bitmap_icon_scanner,
|
||||||
Color::dark_blue()};
|
Theme::getInstance()->fg_blue->foreground};
|
||||||
|
|
||||||
NewButton button_open{
|
NewButton button_open{
|
||||||
{1 * 8, 15 * 8, 7 * 8, 7 * 8},
|
{1 * 8, 15 * 8, 7 * 8, 7 * 8},
|
||||||
"Open",
|
"Open",
|
||||||
&bitmap_icon_load,
|
&bitmap_icon_load,
|
||||||
Color::green()};
|
Theme::getInstance()->fg_green->foreground};
|
||||||
|
|
||||||
NewButton button_save{
|
NewButton button_save{
|
||||||
{8 * 8, 15 * 8, 7 * 8, 7 * 8},
|
{8 * 8, 15 * 8, 7 * 8, 7 * 8},
|
||||||
"Save",
|
"Save",
|
||||||
&bitmap_icon_save,
|
&bitmap_icon_save,
|
||||||
Color::green()};
|
Theme::getInstance()->fg_green->foreground};
|
||||||
|
|
||||||
NewButton button_exit{
|
NewButton button_exit{
|
||||||
{15 * 8, 15 * 8, 7 * 8, 7 * 8},
|
{15 * 8, 15 * 8, 7 * 8, 7 * 8},
|
||||||
"Exit",
|
"Exit",
|
||||||
&bitmap_icon_previous,
|
&bitmap_icon_previous,
|
||||||
Color::dark_red()};
|
Theme::getInstance()->fg_red->foreground};
|
||||||
};
|
};
|
||||||
|
|
||||||
/* View viewing and minor edits on a text file. */
|
/* View viewing and minor edits on a text file. */
|
||||||
@ -269,7 +268,7 @@ class TextEditorView : public View {
|
|||||||
{26 * 8, 34 * 8, 4 * 8, 4 * 8},
|
{26 * 8, 34 * 8, 4 * 8, 4 * 8},
|
||||||
{},
|
{},
|
||||||
&bitmap_icon_controls,
|
&bitmap_icon_controls,
|
||||||
Color::dark_grey(),
|
Theme::getInstance()->bg_dark->background,
|
||||||
/*vcenter*/ true};
|
/*vcenter*/ true};
|
||||||
|
|
||||||
Text text_position{
|
Text text_position{
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user