mirror of
https://github.com/portapack-mayhem/mayhem-firmware.git
synced 2025-08-21 10:58:06 +00:00
28
.github/workflows/changelog.py
vendored
Normal file
28
.github/workflows/changelog.py
vendored
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
import os
|
||||||
|
import re
|
||||||
|
import sys
|
||||||
|
|
||||||
|
raw_git = os.popen('git log next --since="24 hours" --pretty=format:"- %h - {USERNAME}*+%al-%an*: %s"').read()
|
||||||
|
|
||||||
|
|
||||||
|
def compute_username(line):
|
||||||
|
stripped = re.search(r'(?<=\*)(.*?)(?=\*)', line).group(0)
|
||||||
|
|
||||||
|
pattern = re.compile("[$@+&?].*[$@+&?]")
|
||||||
|
if pattern.match(stripped):
|
||||||
|
stripped = re.sub("[$@+&?].*[$@+&?]", "", stripped)
|
||||||
|
stripped = re.match(r'.+?(?=-)', stripped).group(0)
|
||||||
|
else:
|
||||||
|
stripped = re.sub(r'^.*?-', "", stripped)
|
||||||
|
return "@" + stripped
|
||||||
|
|
||||||
|
|
||||||
|
def compile_line(line):
|
||||||
|
username = compute_username(line)
|
||||||
|
line = re.sub(r'[*].*[*]', "", line)
|
||||||
|
line = line.replace("{USERNAME}", username)
|
||||||
|
return line
|
||||||
|
|
||||||
|
|
||||||
|
for row in raw_git.splitlines():
|
||||||
|
print(compile_line(row))
|
44
.github/workflows/create_nightly_release.yml
vendored
44
.github/workflows/create_nightly_release.yml
vendored
@@ -1,5 +1,3 @@
|
|||||||
# ToDo: only trigger after 24 hours if there are actually changes: https://github.community/t/trigger-action-on-schedule-only-if-there-are-changes-to-the-branch/17887/4
|
|
||||||
|
|
||||||
name: Nightly Release
|
name: Nightly Release
|
||||||
|
|
||||||
on:
|
on:
|
||||||
@@ -9,15 +7,35 @@ on:
|
|||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
|
check_date:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
name: Check latest commit
|
||||||
|
outputs:
|
||||||
|
should_run: ${{ steps.should_run.outputs.should_run }}
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
- name: print latest_commit
|
||||||
|
run: echo ${{ github.sha }}
|
||||||
|
|
||||||
|
- name: check latest commit is less than a day
|
||||||
|
id: should_run
|
||||||
|
continue-on-error: true
|
||||||
|
run: test -z $(git rev-list --after="24 hours" ${{ github.sha }}) && echo "::set-output name=should_run::false"
|
||||||
build:
|
build:
|
||||||
|
needs: check_date
|
||||||
|
if: ${{ needs.check_date.outputs.should_run != 'false' }}
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Get current date
|
- name: Get current date
|
||||||
id: date
|
id: date
|
||||||
run: echo "::set-output name=date::$(date +'%Y-%m-%d')"
|
run: echo "::set-output name=date::$(date +'%Y-%m-%d')"
|
||||||
|
- name: Get version date
|
||||||
|
id: version_date
|
||||||
|
run: echo "::set-output name=date::n_$(date +'%y%m%d')"
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@master
|
uses: actions/checkout@master
|
||||||
with:
|
with:
|
||||||
|
fetch-depth: 0
|
||||||
ref: next
|
ref: next
|
||||||
submodules: true
|
submodules: true
|
||||||
- name: Git Sumbodule Update
|
- name: Git Sumbodule Update
|
||||||
@@ -28,13 +46,21 @@ jobs:
|
|||||||
- name: Make build folder
|
- name: Make build folder
|
||||||
run: mkdir ${{ github.workspace }}/build
|
run: mkdir ${{ github.workspace }}/build
|
||||||
- name: Run the Docker image
|
- name: Run the Docker image
|
||||||
run: docker run -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 Firmware ZIP
|
- name: Create Firmware ZIP
|
||||||
run: |
|
run: |
|
||||||
zip --junk-paths firmware build/firmware/portapack-h1_h2-mayhem.bin
|
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: |
|
||||||
zip -r sdcard.zip sdcard
|
zip -r sdcard.zip sdcard
|
||||||
|
- name: Create changelog
|
||||||
|
run: |
|
||||||
|
CHANGELOG=$(python3 .github/workflows/changelog.py)
|
||||||
|
CHANGELOG="${CHANGELOG//'%'/'%25'}"
|
||||||
|
CHANGELOG="${CHANGELOG//$'\n'/'%0A'}"
|
||||||
|
CHANGELOG="${CHANGELOG//$'\r'/'%0D'}"
|
||||||
|
echo "::set-output name=content::$CHANGELOG"
|
||||||
|
id: changelog
|
||||||
- name: Create Release
|
- name: Create Release
|
||||||
id: create_release
|
id: create_release
|
||||||
uses: actions/create-release@v1
|
uses: actions/create-release@v1
|
||||||
@@ -42,11 +68,13 @@ jobs:
|
|||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
with:
|
with:
|
||||||
tag_name: nightly-tag-${{ steps.date.outputs.date }}
|
tag_name: nightly-tag-${{ steps.date.outputs.date }}
|
||||||
release_name: Nightly-release - ${{ steps.date.outputs.date }}
|
release_name: Nightly Release - ${{ steps.date.outputs.date }}
|
||||||
body: |
|
body: |
|
||||||
**Nightly release - ${{ steps.date.outputs.date }}**
|
**Nightly release - ${{ steps.date.outputs.date }}**
|
||||||
This build is the latest and greatest, although may not be the most stable as this is a nightly release.
|
This build is the latest and greatest, although may not be the most stable as this is a nightly release.
|
||||||
You can find the changes in this commit ${{ github.sha }}
|
## Release notes
|
||||||
|
### Revision (${{ steps.version_date.outputs.date }}):
|
||||||
|
${{ steps.changelog.outputs.content }}
|
||||||
draft: false
|
draft: false
|
||||||
prerelease: true
|
prerelease: true
|
||||||
- name: Upload Firmware Asset
|
- name: Upload Firmware Asset
|
||||||
@@ -57,7 +85,7 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
upload_url: ${{ steps.create_release.outputs.upload_url }}
|
upload_url: ${{ steps.create_release.outputs.upload_url }}
|
||||||
asset_path: ./firmware.zip
|
asset_path: ./firmware.zip
|
||||||
asset_name: mayhem_nightly_${{ steps.date.outputs.date }}_FIRMWARE.zip
|
asset_name: mayhem_nightly_${{ steps.version_date.outputs.date }}_FIRMWARE.zip
|
||||||
asset_content_type: application/zip
|
asset_content_type: application/zip
|
||||||
- name: Upload SD Card Assets
|
- name: Upload SD Card Assets
|
||||||
id: upload-sd-card-asset
|
id: upload-sd-card-asset
|
||||||
@@ -67,5 +95,5 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
upload_url: ${{ steps.create_release.outputs.upload_url }}
|
upload_url: ${{ steps.create_release.outputs.upload_url }}
|
||||||
asset_path: ./sdcard.zip
|
asset_path: ./sdcard.zip
|
||||||
asset_name: mayhem_nightly_${{ steps.date.outputs.date }}_COPY_TO_SDCARD.zip
|
asset_name: mayhem_nightly_${{ steps.version_date.outputs.date }}_COPY_TO_SDCARD.zip
|
||||||
asset_content_type: application/zip
|
asset_content_type: application/zip
|
||||||
|
93
.github/workflows/create_stable_release.yml
vendored
Normal file
93
.github/workflows/create_stable_release.yml
vendored
Normal file
@@ -0,0 +1,93 @@
|
|||||||
|
name: Stable Release
|
||||||
|
|
||||||
|
on:
|
||||||
|
workflow_dispatch:
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Get current date
|
||||||
|
id: date
|
||||||
|
run: echo "::set-output name=date::$(date +'%Y-%m-%d')"
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@master
|
||||||
|
with:
|
||||||
|
fetch-depth: 0
|
||||||
|
ref: next
|
||||||
|
submodules: true
|
||||||
|
- name: Git Sumbodule Update
|
||||||
|
run: |
|
||||||
|
git submodule update --init --recursive
|
||||||
|
- name: Get version
|
||||||
|
id: version
|
||||||
|
run: echo "::set-output name=version::$(cat .github/workflows/version.txt)"
|
||||||
|
- name: Get past version
|
||||||
|
id: past_version
|
||||||
|
run: echo "::set-output name=past_version::$(cat .github/workflows/past_version.txt)"
|
||||||
|
- name: Build the Docker image
|
||||||
|
run: docker build -t portapack-dev -f dockerfile-nogit . --tag my-image-name:$(date +%s)
|
||||||
|
- name: Make build folder
|
||||||
|
run: mkdir ${{ github.workspace }}/build
|
||||||
|
- name: Run the Docker image
|
||||||
|
run: docker run -e VERSION_STRING=${{ steps.version.outputs.version }} -i -v ${{ github.workspace }}:/havoc portapack-dev
|
||||||
|
- name: Create Firmware ZIP
|
||||||
|
run: |
|
||||||
|
zip -j firmware.zip build/firmware/portapack-h1_h2-mayhem.bin && cd flashing && zip -r ../firmware.zip *
|
||||||
|
- name: Create SD Card ZIP
|
||||||
|
run: |
|
||||||
|
zip -r sdcard.zip sdcard
|
||||||
|
- name: Create changelog
|
||||||
|
run: |
|
||||||
|
CHANGELOG=$(python3 .github/workflows/stable_changelog.py ${{ steps.past_version.outputs.past_version }})
|
||||||
|
CHANGELOG="${CHANGELOG//'%'/'%25'}"
|
||||||
|
CHANGELOG="${CHANGELOG//$'\n'/'%0A'}"
|
||||||
|
CHANGELOG="${CHANGELOG//$'\r'/'%0D'}"
|
||||||
|
echo "::set-output name=content::$CHANGELOG"
|
||||||
|
id: changelog
|
||||||
|
- name: Create Release
|
||||||
|
id: create_release
|
||||||
|
uses: actions/create-release@v1
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
with:
|
||||||
|
tag_name: ${{ steps.version.outputs.version }}
|
||||||
|
release_name: Mayhem firmware ${{ steps.version.outputs.version }}
|
||||||
|
body: |
|
||||||
|
**Stable release - ${{ steps.version.outputs.version }}**
|
||||||
|
This is a fork of the [Havoc](https://github.com/furrtek/portapack-havoc/) firmware, which itself was a fork of the [PortaPack](https://github.com/sharebrained/portapack-hackrf) firmware, an add-on for the [HackRF](http://greatscottgadgets.com/hackrf/). Please check the [readme](https://github.com/eried/portapack-mayhem/blob/master/README.md) for details.
|
||||||
|
## Release notes
|
||||||
|
### Revision (${{ steps.version.outputs.version }}):
|
||||||
|
${{ steps.changelog.outputs.content }}
|
||||||
|
|
||||||
|
**Full Changelog**: https://github.com/eried/portapack-mayhem/compare/${{ steps.past_version.outputs.past_version }}...${{ steps.version.outputs.version }}
|
||||||
|
|
||||||
|
## Installation
|
||||||
|
Check the [wiki](https://github.com/eried/portapack-havoc/wiki/Update-firmware) for details how to upgrade.
|
||||||
|
|
||||||
|
### MicroSD card files
|
||||||
|
|
||||||
|
For certain functionality, like the world map, GPS simulator, and others you need to uncompress (using [7-zip](https://www.7-zip.org/download.html)) the files from `mayhem_vX.Y.Z_COPY_TO_SDCARD.zip` to a FAT32 formatted MicroSD card.
|
||||||
|
draft: true
|
||||||
|
prerelease: false
|
||||||
|
- name: Upload Firmware Asset
|
||||||
|
id: upload-firmware-asset
|
||||||
|
uses: actions/upload-release-asset@v1
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
with:
|
||||||
|
upload_url: ${{ steps.create_release.outputs.upload_url }}
|
||||||
|
asset_path: ./firmware.zip
|
||||||
|
asset_name: mayhem_${{ steps.version.outputs.version }}_FIRMWARE.zip
|
||||||
|
asset_content_type: application/zip
|
||||||
|
- name: Upload SD Card Assets
|
||||||
|
id: upload-sd-card-asset
|
||||||
|
uses: actions/upload-release-asset@v1
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
with:
|
||||||
|
upload_url: ${{ steps.create_release.outputs.upload_url }}
|
||||||
|
asset_path: ./sdcard.zip
|
||||||
|
asset_name: mayhem_${{ steps.version.outputs.version }}_COPY_TO_SDCARD.zip
|
||||||
|
asset_content_type: application/zip
|
||||||
|
|
1
.github/workflows/past_version.txt
vendored
Normal file
1
.github/workflows/past_version.txt
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
v1.5.1
|
30
.github/workflows/stable_changelog.py
vendored
Normal file
30
.github/workflows/stable_changelog.py
vendored
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
import os
|
||||||
|
import re
|
||||||
|
import sys
|
||||||
|
|
||||||
|
past_version = sys.argv[1]
|
||||||
|
|
||||||
|
raw_git = os.popen('git log ' + past_version + '..next --pretty=format:"- %h - {USERNAME}*+%al-%an*: %s"').read()
|
||||||
|
|
||||||
|
|
||||||
|
def compute_username(line):
|
||||||
|
stripped = re.search(r'(?<=\*)(.*?)(?=\*)', line).group(0)
|
||||||
|
|
||||||
|
pattern = re.compile("[$@+&?].*[$@+&?]")
|
||||||
|
if pattern.match(stripped):
|
||||||
|
stripped = re.sub("[$@+&?].*[$@+&?]", "", stripped)
|
||||||
|
stripped = re.match(r'.+?(?=-)', stripped).group(0)
|
||||||
|
else:
|
||||||
|
stripped = re.sub(r'^.*?-', "", stripped)
|
||||||
|
return "@" + stripped
|
||||||
|
|
||||||
|
|
||||||
|
def compile_line(line):
|
||||||
|
username = compute_username(line)
|
||||||
|
line = re.sub(r'[*].*[*]', "", line)
|
||||||
|
line = line.replace("{USERNAME}", username)
|
||||||
|
return line
|
||||||
|
|
||||||
|
|
||||||
|
for row in raw_git.splitlines():
|
||||||
|
print(compile_line(row))
|
1
.github/workflows/version.txt
vendored
Normal file
1
.github/workflows/version.txt
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
v1.5.3
|
1
.gitignore
vendored
1
.gitignore
vendored
@@ -39,7 +39,6 @@
|
|||||||
*.lib
|
*.lib
|
||||||
|
|
||||||
# Executables
|
# Executables
|
||||||
*.exe
|
|
||||||
*.out
|
*.out
|
||||||
*.app
|
*.app
|
||||||
/firmware/baseband/*.bin
|
/firmware/baseband/*.bin
|
||||||
|
@@ -25,8 +25,8 @@ set(CMAKE_TOOLCHAIN_FILE ${CMAKE_CURRENT_LIST_DIR}/firmware/toolchain-arm-cortex
|
|||||||
|
|
||||||
project(portapack-h1)
|
project(portapack-h1)
|
||||||
|
|
||||||
#set(VERSION "")
|
set(VERSION "$ENV{VERSION_STRING}")
|
||||||
if (NOT DEFINED VERSION)
|
if ("$ENV{VERSION_STRING}" STREQUAL "")
|
||||||
execute_process(
|
execute_process(
|
||||||
COMMAND git log -n 1 --format=%h
|
COMMAND git log -n 1 --format=%h
|
||||||
WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR}
|
WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR}
|
||||||
@@ -38,7 +38,7 @@ if (NOT DEFINED VERSION)
|
|||||||
if (GIT_VERSION_FOUND)
|
if (GIT_VERSION_FOUND)
|
||||||
set(VERSION "unknown")
|
set(VERSION "unknown")
|
||||||
else (GIT_VERSION_FOUND)
|
else (GIT_VERSION_FOUND)
|
||||||
set(VERSION "local-${GIT_VERSION}")
|
set(VERSION "${GIT_VERSION}")
|
||||||
endif (GIT_VERSION_FOUND)
|
endif (GIT_VERSION_FOUND)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
@@ -26,7 +26,9 @@ To support the people behind the hardware, please buy a genuine [HackRF](https:/
|
|||||||
|
|
||||||
## Where is the latest firmware?
|
## Where is the latest firmware?
|
||||||
|
|
||||||
The current stable release is on the [](https://github.com/eried/portapack-mayhem/releases/latest) page. Follow the instructions you can find in the release description.
|
The **latest (nightly) release** can be found [here](https://github.com/eried/portapack-mayhem/releases/).
|
||||||
|
|
||||||
|
The current **stable release** is on the [](https://github.com/eried/portapack-mayhem/releases/latest) page. Follow the instructions you can find in the release description.
|
||||||
|
|
||||||
## Is this the newest firmware for my PortaPack?
|
## Is this the newest firmware for my PortaPack?
|
||||||
Most probably: **YES**. *If you find new features somewhere else, please [suggest](https://github.com/eried/portapack-mayhem/issues/new/choose) them*.
|
Most probably: **YES**. *If you find new features somewhere else, please [suggest](https://github.com/eried/portapack-mayhem/issues/new/choose) them*.
|
||||||
|
@@ -154,6 +154,7 @@ set(CPPSRC
|
|||||||
${COMMON}/ui_widget.cpp
|
${COMMON}/ui_widget.cpp
|
||||||
${COMMON}/utility.cpp
|
${COMMON}/utility.cpp
|
||||||
${COMMON}/wm8731.cpp
|
${COMMON}/wm8731.cpp
|
||||||
|
app_settings.cpp
|
||||||
audio.cpp
|
audio.cpp
|
||||||
baseband_api.cpp
|
baseband_api.cpp
|
||||||
capture_thread.cpp
|
capture_thread.cpp
|
||||||
|
102
firmware/application/app_settings.cpp
Normal file
102
firmware/application/app_settings.cpp
Normal file
@@ -0,0 +1,102 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2015 Jared Boone, ShareBrained Technology, Inc.
|
||||||
|
* Copyright (C) 2016 Furrtek
|
||||||
|
* Copyright (C) 2022 Arjan Onwezen
|
||||||
|
*
|
||||||
|
* 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 "app_settings.hpp"
|
||||||
|
|
||||||
|
#include "file.hpp"
|
||||||
|
#include "portapack.hpp"
|
||||||
|
#include "portapack_persistent_memory.hpp"
|
||||||
|
#include <cstring>
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
|
namespace std {
|
||||||
|
|
||||||
|
int app_settings::load(std::string application, AppSettings* settings) {
|
||||||
|
|
||||||
|
if (portapack::persistent_memory::load_app_settings()) {
|
||||||
|
file_path = folder+"/"+application+".ini";
|
||||||
|
|
||||||
|
auto error = settings_file.open(file_path);
|
||||||
|
if (!error.is_valid()) {
|
||||||
|
auto error = settings_file.read(file_content, std::min((int)settings_file.size(), MAX_FILE_CONTENT_SIZE));
|
||||||
|
|
||||||
|
settings->baseband_bandwidth=std::app_settings::read_long_long(file_content, "baseband_bandwidth=");
|
||||||
|
settings->channel_bandwidth=std::app_settings::read_long_long(file_content, "channel_bandwidth=");
|
||||||
|
settings->lna=std::app_settings::read_long_long(file_content, "lna=");
|
||||||
|
settings->modulation=std::app_settings::read_long_long(file_content, "modulation=");
|
||||||
|
settings->rx_amp=std::app_settings::read_long_long(file_content, "rx_amp=");
|
||||||
|
settings->rx_frequency=std::app_settings::read_long_long(file_content, "rx_frequency=");
|
||||||
|
settings->sampling_rate=std::app_settings::read_long_long(file_content, "sampling_rate=");
|
||||||
|
settings->vga=std::app_settings::read_long_long(file_content, "vga=");
|
||||||
|
settings->tx_amp=std::app_settings::read_long_long(file_content, "tx_amp=");
|
||||||
|
settings->tx_frequency=std::app_settings::read_long_long(file_content, "tx_frequency=");
|
||||||
|
settings->tx_gain=std::app_settings::read_long_long(file_content, "tx_gain=");
|
||||||
|
rc = SETTINGS_OK;
|
||||||
|
}
|
||||||
|
else rc = SETTINGS_UNABLE_TO_LOAD;
|
||||||
|
}
|
||||||
|
else rc = SETTINGS_DISABLED;
|
||||||
|
return(rc);
|
||||||
|
}
|
||||||
|
|
||||||
|
int app_settings::save(std::string application, AppSettings* settings) {
|
||||||
|
|
||||||
|
if (portapack::persistent_memory::save_app_settings()) {
|
||||||
|
file_path = folder+"/"+application+".ini";
|
||||||
|
make_new_directory(folder);
|
||||||
|
|
||||||
|
auto error = settings_file.create(file_path);
|
||||||
|
if (!error.is_valid()) {
|
||||||
|
// Save common setting
|
||||||
|
settings_file.write_line("baseband_bandwidth="+to_string_dec_uint(portapack::receiver_model.baseband_bandwidth()));
|
||||||
|
settings_file.write_line("channel_bandwidth="+to_string_dec_uint(portapack::transmitter_model.channel_bandwidth()));
|
||||||
|
settings_file.write_line("lna="+to_string_dec_uint(portapack::receiver_model.lna()));
|
||||||
|
settings_file.write_line("rx_amp="+to_string_dec_uint(portapack::receiver_model.rf_amp()));
|
||||||
|
settings_file.write_line("sampling_rate="+to_string_dec_uint(portapack::receiver_model.sampling_rate()));
|
||||||
|
settings_file.write_line("tx_amp="+to_string_dec_uint(portapack::transmitter_model.rf_amp()));
|
||||||
|
settings_file.write_line("tx_gain="+to_string_dec_uint(portapack::transmitter_model.tx_gain()));
|
||||||
|
settings_file.write_line("vga="+to_string_dec_uint(portapack::receiver_model.vga()));
|
||||||
|
// Save other settings from struct
|
||||||
|
settings_file.write_line("rx_frequency="+to_string_dec_uint(settings->rx_frequency));
|
||||||
|
settings_file.write_line("tx_frequency="+to_string_dec_uint(settings->tx_frequency));
|
||||||
|
|
||||||
|
rc = SETTINGS_OK;
|
||||||
|
}
|
||||||
|
else rc = SETTINGS_UNABLE_TO_SAVE;
|
||||||
|
}
|
||||||
|
else rc = SETTINGS_DISABLED;
|
||||||
|
return(rc);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
long long int app_settings::read_long_long(char* file_content, const char* setting_text) {
|
||||||
|
auto position = strstr(file_content, (char *)setting_text);
|
||||||
|
if (position) {
|
||||||
|
position += strlen((char *)setting_text);
|
||||||
|
setting_value = strtoll(position, nullptr, 10);
|
||||||
|
}
|
||||||
|
return(setting_value);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
} /* namespace std */
|
87
firmware/application/app_settings.hpp
Normal file
87
firmware/application/app_settings.hpp
Normal file
@@ -0,0 +1,87 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2015 Jared Boone, ShareBrained Technology, Inc.
|
||||||
|
* Copyright (C) 2016 Furrtek
|
||||||
|
* Copyright (C) 2022 Arjan Onwezen
|
||||||
|
*
|
||||||
|
* 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 __APP_SETTINGS_H__
|
||||||
|
#define __APP_SETTINGS_H__
|
||||||
|
|
||||||
|
|
||||||
|
#include <cstddef>
|
||||||
|
#include <cstdint>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#include "file.hpp"
|
||||||
|
#include "string_format.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
namespace std {
|
||||||
|
class app_settings {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
#define SETTINGS_OK 0 // settings found
|
||||||
|
#define SETTINGS_UNABLE_TO_LOAD -1 // settings (file) not found
|
||||||
|
#define SETTINGS_UNABLE_TO_SAVE -2 // unable to save settings
|
||||||
|
#define SETTINGS_DISABLED -3 // load/save settings disabled in settings
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
struct AppSettings {
|
||||||
|
uint32_t baseband_bandwidth;
|
||||||
|
uint32_t channel_bandwidth;
|
||||||
|
uint8_t lna;
|
||||||
|
uint8_t modulation;
|
||||||
|
uint8_t rx_amp;
|
||||||
|
uint32_t rx_frequency;
|
||||||
|
uint32_t sampling_rate;
|
||||||
|
uint8_t tx_amp;
|
||||||
|
uint32_t tx_frequency;
|
||||||
|
uint8_t tx_gain;
|
||||||
|
uint8_t vga;
|
||||||
|
};
|
||||||
|
|
||||||
|
int load(std::string application, AppSettings* settings);
|
||||||
|
int save(std::string application, AppSettings* settings);
|
||||||
|
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
#define MAX_FILE_CONTENT_SIZE 1000
|
||||||
|
|
||||||
|
char file_content[MAX_FILE_CONTENT_SIZE] = {};
|
||||||
|
std::string file_path = "";
|
||||||
|
std::string folder = "SETTINGS";
|
||||||
|
int rc = SETTINGS_OK;
|
||||||
|
File settings_file { };
|
||||||
|
long long int setting_value {} ;
|
||||||
|
|
||||||
|
long long int read_long_long(char* file_content, const char* setting_text);
|
||||||
|
|
||||||
|
|
||||||
|
}; // class app_settings
|
||||||
|
} // namespace std
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#endif/*__APP_SETTINGS_H__*/
|
@@ -254,8 +254,18 @@ AISRecentEntryDetailView::AISRecentEntryDetailView(NavigationView& nav) {
|
|||||||
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
AISRecentEntryDetailView::AISRecentEntryDetailView(const AISRecentEntryDetailView&Entry) : View()
|
||||||
|
{
|
||||||
|
(void)Entry;
|
||||||
|
}
|
||||||
|
|
||||||
|
AISRecentEntryDetailView & AISRecentEntryDetailView::operator=(const AISRecentEntryDetailView&Entry)
|
||||||
|
{
|
||||||
|
(void)Entry;
|
||||||
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
void AISRecentEntryDetailView::update_position() {
|
void AISRecentEntryDetailView::update_position() {
|
||||||
@@ -325,24 +335,23 @@ AISAppView::AISAppView(NavigationView& nav) : nav_ { nav } {
|
|||||||
&recent_entry_detail_view,
|
&recent_entry_detail_view,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
// load app settings
|
||||||
|
auto rc = settings.load("rx_ais", &app_settings);
|
||||||
|
if(rc == SETTINGS_OK) {
|
||||||
|
field_lna.set_value(app_settings.lna);
|
||||||
|
field_vga.set_value(app_settings.vga);
|
||||||
|
field_rf_amp.set_value(app_settings.rx_amp);
|
||||||
|
target_frequency_ = app_settings.rx_frequency;
|
||||||
|
}
|
||||||
|
else target_frequency_ = initial_target_frequency;
|
||||||
|
|
||||||
recent_entry_detail_view.hidden(true);
|
recent_entry_detail_view.hidden(true);
|
||||||
|
|
||||||
target_frequency_ = initial_target_frequency;
|
receiver_model.set_tuning_frequency(tuning_frequency());
|
||||||
|
receiver_model.set_sampling_rate(sampling_rate);
|
||||||
receiver_model.set_tuning_frequency(tuning_frequency());
|
receiver_model.set_baseband_bandwidth(baseband_bandwidth);
|
||||||
receiver_model.set_sampling_rate(sampling_rate);
|
receiver_model.enable(); // Before using radio::enable(), but not updating Ant.DC-Bias.
|
||||||
receiver_model.set_baseband_bandwidth(baseband_bandwidth);
|
|
||||||
receiver_model.enable(); // Before using radio::enable(), but not updating Ant.DC-Bias.
|
|
||||||
|
|
||||||
/* radio::enable({ // this can be removed, previous version,no DC-bias control.
|
|
||||||
tuning_frequency(),
|
|
||||||
sampling_rate,
|
|
||||||
baseband_bandwidth,
|
|
||||||
rf::Direction::Receive,
|
|
||||||
receiver_model.rf_amp(),
|
|
||||||
static_cast<int8_t>(receiver_model.lna()),
|
|
||||||
static_cast<int8_t>(receiver_model.vga()),
|
|
||||||
}); */
|
|
||||||
|
|
||||||
options_channel.on_change = [this](size_t, OptionsField::value_t v) {
|
options_channel.on_change = [this](size_t, OptionsField::value_t v) {
|
||||||
this->on_frequency_changed(v);
|
this->on_frequency_changed(v);
|
||||||
@@ -363,7 +372,11 @@ AISAppView::AISAppView(NavigationView& nav) : nav_ { nav } {
|
|||||||
}
|
}
|
||||||
|
|
||||||
AISAppView::~AISAppView() {
|
AISAppView::~AISAppView() {
|
||||||
/* radio::disable(); */
|
|
||||||
|
// save app settings
|
||||||
|
app_settings.rx_frequency = target_frequency_;
|
||||||
|
settings.save("rx_ais", &app_settings);
|
||||||
|
|
||||||
receiver_model.disable(); // to switch off all, including DC bias.
|
receiver_model.disable(); // to switch off all, including DC bias.
|
||||||
|
|
||||||
baseband::shutdown();
|
baseband::shutdown();
|
||||||
|
@@ -33,7 +33,7 @@
|
|||||||
#include "event_m0.hpp"
|
#include "event_m0.hpp"
|
||||||
|
|
||||||
#include "log_file.hpp"
|
#include "log_file.hpp"
|
||||||
|
#include "app_settings.hpp"
|
||||||
#include "ais_packet.hpp"
|
#include "ais_packet.hpp"
|
||||||
|
|
||||||
#include "lpc43xx_cpp.hpp"
|
#include "lpc43xx_cpp.hpp"
|
||||||
@@ -127,6 +127,9 @@ public:
|
|||||||
void focus() override;
|
void focus() override;
|
||||||
void paint(Painter&) override;
|
void paint(Painter&) override;
|
||||||
|
|
||||||
|
AISRecentEntryDetailView(const AISRecentEntryDetailView&Entry);
|
||||||
|
AISRecentEntryDetailView &operator=(const AISRecentEntryDetailView&Entry);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
AISRecentEntry entry_ { };
|
AISRecentEntry entry_ { };
|
||||||
|
|
||||||
@@ -163,13 +166,18 @@ public:
|
|||||||
|
|
||||||
void focus() override;
|
void focus() override;
|
||||||
|
|
||||||
std::string title() const override { return "AIS"; };
|
std::string title() const override { return "AIS Boats RX"; };
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static constexpr uint32_t initial_target_frequency = 162025000;
|
static constexpr uint32_t initial_target_frequency = 162025000;
|
||||||
static constexpr uint32_t sampling_rate = 2457600;
|
static constexpr uint32_t sampling_rate = 2457600;
|
||||||
static constexpr uint32_t baseband_bandwidth = 1750000;
|
static constexpr uint32_t baseband_bandwidth = 1750000;
|
||||||
|
|
||||||
|
|
||||||
|
// app save settings
|
||||||
|
std::app_settings settings { };
|
||||||
|
std::app_settings::AppSettings app_settings { };
|
||||||
|
|
||||||
NavigationView& nav_;
|
NavigationView& nav_;
|
||||||
|
|
||||||
AISRecentEntries recent { };
|
AISRecentEntries recent { };
|
||||||
|
@@ -129,10 +129,19 @@ AnalogAudioView::AnalogAudioView(
|
|||||||
&waterfall
|
&waterfall
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// load app settings
|
||||||
|
auto rc = settings.load("rx_audio", &app_settings);
|
||||||
|
if(rc == SETTINGS_OK) {
|
||||||
|
field_lna.set_value(app_settings.lna);
|
||||||
|
field_vga.set_value(app_settings.vga);
|
||||||
|
receiver_model.set_rf_amp(app_settings.rx_amp);
|
||||||
|
field_frequency.set_value(app_settings.rx_frequency);
|
||||||
|
}
|
||||||
|
else field_frequency.set_value(receiver_model.tuning_frequency());
|
||||||
|
|
||||||
//Filename Datetime and Frequency
|
//Filename Datetime and Frequency
|
||||||
record_view.set_filename_date_frequency(true);
|
record_view.set_filename_date_frequency(true);
|
||||||
|
|
||||||
field_frequency.set_value(receiver_model.tuning_frequency());
|
|
||||||
field_frequency.set_step(receiver_model.frequency_step());
|
field_frequency.set_step(receiver_model.frequency_step());
|
||||||
field_frequency.on_change = [this](rf::Frequency f) {
|
field_frequency.on_change = [this](rf::Frequency f) {
|
||||||
this->on_tuning_frequency_changed(f);
|
this->on_tuning_frequency_changed(f);
|
||||||
@@ -160,6 +169,7 @@ AnalogAudioView::AnalogAudioView(
|
|||||||
|
|
||||||
const auto modulation = receiver_model.modulation();
|
const auto modulation = receiver_model.modulation();
|
||||||
options_modulation.set_by_value(toUType(modulation));
|
options_modulation.set_by_value(toUType(modulation));
|
||||||
|
|
||||||
options_modulation.on_change = [this](size_t, OptionsField::value_t v) {
|
options_modulation.on_change = [this](size_t, OptionsField::value_t v) {
|
||||||
this->on_modulation_changed(static_cast<ReceiverModel::Mode>(v));
|
this->on_modulation_changed(static_cast<ReceiverModel::Mode>(v));
|
||||||
};
|
};
|
||||||
@@ -183,7 +193,7 @@ AnalogAudioView::AnalogAudioView(
|
|||||||
audio::output::start();
|
audio::output::start();
|
||||||
|
|
||||||
update_modulation(static_cast<ReceiverModel::Mode>(modulation));
|
update_modulation(static_cast<ReceiverModel::Mode>(modulation));
|
||||||
on_modulation_changed(static_cast<ReceiverModel::Mode>(modulation));
|
on_modulation_changed(static_cast<ReceiverModel::Mode>(modulation));
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t AnalogAudioView::get_spec_bw_index() {
|
size_t AnalogAudioView::get_spec_bw_index() {
|
||||||
@@ -210,6 +220,11 @@ void AnalogAudioView::set_spec_trigger(uint16_t trigger) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
AnalogAudioView::~AnalogAudioView() {
|
AnalogAudioView::~AnalogAudioView() {
|
||||||
|
|
||||||
|
// save app settings
|
||||||
|
app_settings.rx_frequency = field_frequency.value();
|
||||||
|
settings.save("rx_audio", &app_settings);
|
||||||
|
|
||||||
// TODO: Manipulating audio codec here, and in ui_receiver.cpp. Good to do
|
// TODO: Manipulating audio codec here, and in ui_receiver.cpp. Good to do
|
||||||
// both?
|
// both?
|
||||||
audio::output::stop();
|
audio::output::stop();
|
||||||
@@ -397,9 +412,6 @@ void AnalogAudioView::update_modulation(const ReceiverModel::Mode modulation) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*void AnalogAudioView::squelched() {
|
|
||||||
if (exit_on_squelch) nav_.pop();
|
|
||||||
}*/
|
|
||||||
|
|
||||||
void AnalogAudioView::handle_coded_squelch(const uint32_t value) {
|
void AnalogAudioView::handle_coded_squelch(const uint32_t value) {
|
||||||
float diff, min_diff = value;
|
float diff, min_diff = value;
|
||||||
|
@@ -29,7 +29,7 @@
|
|||||||
#include "ui_spectrum.hpp"
|
#include "ui_spectrum.hpp"
|
||||||
#include "ui_record_view.hpp"
|
#include "ui_record_view.hpp"
|
||||||
#include "ui_font_fixed_8x16.hpp"
|
#include "ui_font_fixed_8x16.hpp"
|
||||||
|
#include "app_settings.hpp"
|
||||||
#include "tone_key.hpp"
|
#include "tone_key.hpp"
|
||||||
|
|
||||||
|
|
||||||
@@ -143,7 +143,7 @@ public:
|
|||||||
|
|
||||||
void focus() override;
|
void focus() override;
|
||||||
|
|
||||||
std::string title() const override { return "Analog audio"; };
|
std::string title() const override { return "Audio RX"; };
|
||||||
|
|
||||||
size_t get_spec_bw_index();
|
size_t get_spec_bw_index();
|
||||||
void set_spec_bw(size_t index, uint32_t bw);
|
void set_spec_bw(size_t index, uint32_t bw);
|
||||||
@@ -154,6 +154,10 @@ public:
|
|||||||
private:
|
private:
|
||||||
static constexpr ui::Dim header_height = 3 * 16;
|
static constexpr ui::Dim header_height = 3 * 16;
|
||||||
|
|
||||||
|
// app save settings
|
||||||
|
std::app_settings settings { };
|
||||||
|
std::app_settings::AppSettings app_settings { };
|
||||||
|
|
||||||
const Rect options_view_rect { 0 * 8, 1 * 16, 30 * 8, 1 * 16 };
|
const Rect options_view_rect { 0 * 8, 1 * 16, 30 * 8, 1 * 16 };
|
||||||
const Rect nbfm_view_rect { 0 * 8, 1 * 16, 18 * 8, 1 * 16 };
|
const Rect nbfm_view_rect { 0 * 8, 1 * 16, 18 * 8, 1 * 16 };
|
||||||
|
|
||||||
|
@@ -57,7 +57,18 @@ AnalogTvView::AnalogTvView(
|
|||||||
&tv
|
&tv
|
||||||
});
|
});
|
||||||
|
|
||||||
field_frequency.set_value(receiver_model.tuning_frequency());
|
|
||||||
|
// load app settings
|
||||||
|
auto rc = settings.load("rx_tv", &app_settings);
|
||||||
|
if(rc == SETTINGS_OK) {
|
||||||
|
field_lna.set_value(app_settings.lna);
|
||||||
|
field_vga.set_value(app_settings.vga);
|
||||||
|
receiver_model.set_rf_amp(app_settings.rx_amp);
|
||||||
|
field_frequency.set_value(app_settings.rx_frequency);
|
||||||
|
}
|
||||||
|
else field_frequency.set_value(receiver_model.tuning_frequency());
|
||||||
|
|
||||||
|
|
||||||
field_frequency.set_step(receiver_model.frequency_step());
|
field_frequency.set_step(receiver_model.frequency_step());
|
||||||
field_frequency.on_change = [this](rf::Frequency f) {
|
field_frequency.on_change = [this](rf::Frequency f) {
|
||||||
this->on_tuning_frequency_changed(f);
|
this->on_tuning_frequency_changed(f);
|
||||||
@@ -106,12 +117,15 @@ AnalogTvView::AnalogTvView(
|
|||||||
}
|
}
|
||||||
|
|
||||||
AnalogTvView::~AnalogTvView() {
|
AnalogTvView::~AnalogTvView() {
|
||||||
|
|
||||||
|
// save app settings
|
||||||
|
app_settings.rx_frequency = field_frequency.value();
|
||||||
|
settings.save("rx_tv", &app_settings);
|
||||||
|
|
||||||
// TODO: Manipulating audio codec here, and in ui_receiver.cpp. Good to do
|
// TODO: Manipulating audio codec here, and in ui_receiver.cpp. Good to do
|
||||||
// both?
|
// both?
|
||||||
audio::output::stop();
|
audio::output::stop();
|
||||||
|
|
||||||
receiver_model.disable();
|
receiver_model.disable();
|
||||||
|
|
||||||
baseband::shutdown();
|
baseband::shutdown();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -29,7 +29,7 @@
|
|||||||
#include "ui_receiver.hpp"
|
#include "ui_receiver.hpp"
|
||||||
#include "ui_tv.hpp"
|
#include "ui_tv.hpp"
|
||||||
#include "ui_record_view.hpp"
|
#include "ui_record_view.hpp"
|
||||||
|
#include "app_settings.hpp"
|
||||||
#include "ui_font_fixed_8x16.hpp"
|
#include "ui_font_fixed_8x16.hpp"
|
||||||
|
|
||||||
#include "tone_key.hpp"
|
#include "tone_key.hpp"
|
||||||
@@ -53,11 +53,15 @@ public:
|
|||||||
|
|
||||||
void focus() override;
|
void focus() override;
|
||||||
|
|
||||||
std::string title() const override { return "Analog TV"; };
|
std::string title() const override { return "Analog TV RX"; };
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static constexpr ui::Dim header_height = 3 * 16;
|
static constexpr ui::Dim header_height = 3 * 16;
|
||||||
|
|
||||||
|
// app save settings
|
||||||
|
std::app_settings settings { };
|
||||||
|
std::app_settings::AppSettings app_settings { };
|
||||||
|
|
||||||
const Rect options_view_rect { 0 * 8, 1 * 16, 30 * 8, 1 * 16 };
|
const Rect options_view_rect { 0 * 8, 1 * 16, 30 * 8, 1 * 16 };
|
||||||
const Rect nbfm_view_rect { 0 * 8, 1 * 16, 18 * 8, 1 * 16 };
|
const Rect nbfm_view_rect { 0 * 8, 1 * 16, 18 * 8, 1 * 16 };
|
||||||
|
|
||||||
|
@@ -105,6 +105,15 @@ ERTAppView::ERTAppView(NavigationView&) {
|
|||||||
&recent_entries_view,
|
&recent_entries_view,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// load app settings
|
||||||
|
auto rc = settings.load("rx_ert", &app_settings);
|
||||||
|
if(rc == SETTINGS_OK) {
|
||||||
|
field_lna.set_value(app_settings.lna);
|
||||||
|
field_vga.set_value(app_settings.vga);
|
||||||
|
field_rf_amp.set_value(app_settings.rx_amp);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
radio::enable({
|
radio::enable({
|
||||||
initial_target_frequency,
|
initial_target_frequency,
|
||||||
sampling_rate,
|
sampling_rate,
|
||||||
@@ -122,6 +131,10 @@ ERTAppView::ERTAppView(NavigationView&) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ERTAppView::~ERTAppView() {
|
ERTAppView::~ERTAppView() {
|
||||||
|
|
||||||
|
// save app settings
|
||||||
|
settings.save("rx_ert", &app_settings);
|
||||||
|
|
||||||
radio::disable();
|
radio::disable();
|
||||||
|
|
||||||
baseband::shutdown();
|
baseband::shutdown();
|
||||||
|
@@ -28,7 +28,7 @@
|
|||||||
#include "ui_channel.hpp"
|
#include "ui_channel.hpp"
|
||||||
|
|
||||||
#include "event_m0.hpp"
|
#include "event_m0.hpp"
|
||||||
|
#include "app_settings.hpp"
|
||||||
#include "log_file.hpp"
|
#include "log_file.hpp"
|
||||||
|
|
||||||
#include "ert_packet.hpp"
|
#include "ert_packet.hpp"
|
||||||
@@ -125,12 +125,17 @@ public:
|
|||||||
|
|
||||||
void focus() override;
|
void focus() override;
|
||||||
|
|
||||||
std::string title() const override { return "ERT"; };
|
std::string title() const override { return "ERT Meter RX"; };
|
||||||
|
|
||||||
private:
|
private:
|
||||||
ERTRecentEntries recent { };
|
ERTRecentEntries recent { };
|
||||||
std::unique_ptr<ERTLogger> logger { };
|
std::unique_ptr<ERTLogger> logger { };
|
||||||
|
|
||||||
|
// app save settings
|
||||||
|
std::app_settings settings { };
|
||||||
|
std::app_settings::AppSettings app_settings { };
|
||||||
|
|
||||||
|
|
||||||
const RecentEntriesColumns columns { {
|
const RecentEntriesColumns columns { {
|
||||||
{ "ID", 10 },
|
{ "ID", 10 },
|
||||||
{ "Tp", 2 },
|
{ "Tp", 2 },
|
||||||
|
@@ -44,7 +44,7 @@ public:
|
|||||||
void set_parent_rect(const Rect new_parent_rect) override;
|
void set_parent_rect(const Rect new_parent_rect) override;
|
||||||
void focus() override;
|
void focus() override;
|
||||||
|
|
||||||
std::string title() const override { return "GPS Simulator"; };
|
std::string title() const override { return "GPS Sim TX"; };
|
||||||
|
|
||||||
private:
|
private:
|
||||||
NavigationView& nav_;
|
NavigationView& nav_;
|
||||||
|
@@ -39,10 +39,14 @@ using namespace portapack;
|
|||||||
namespace ui {
|
namespace ui {
|
||||||
|
|
||||||
void LGEView::focus() {
|
void LGEView::focus() {
|
||||||
options_trame.focus();
|
options_frame.focus();
|
||||||
}
|
}
|
||||||
|
|
||||||
LGEView::~LGEView() {
|
LGEView::~LGEView() {
|
||||||
|
// save app settings
|
||||||
|
app_settings.tx_frequency = transmitter_model.tuning_frequency();
|
||||||
|
settings.save("tx_lge", &app_settings);
|
||||||
|
|
||||||
transmitter_model.disable();
|
transmitter_model.disable();
|
||||||
baseband::shutdown();
|
baseband::shutdown();
|
||||||
}
|
}
|
||||||
@@ -70,10 +74,10 @@ void LGEView::generate_frame_touche() {
|
|||||||
std::vector<uint8_t> data { 0x46, 0x28, 0x01, 0x45, 0x27, 0x01, 0x44, 0x23 };
|
std::vector<uint8_t> data { 0x46, 0x28, 0x01, 0x45, 0x27, 0x01, 0x44, 0x23 };
|
||||||
|
|
||||||
console.write("\n\x1B\x07Touche:\x1B\x10");
|
console.write("\n\x1B\x07Touche:\x1B\x10");
|
||||||
generate_lge_frame(0x96, (field_joueur.value() << 8) | field_salle.value(), 0x0001, data);
|
generate_lge_frame(0x96, (field_player.value() << 8) | field_room.value(), 0x0001, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
void LGEView::generate_frame_pseudo() {
|
void LGEView::generate_frame_nickname() {
|
||||||
// 0040.48s:
|
// 0040.48s:
|
||||||
// 30 02 1A 00 19 00 FF 00 02 19 42 52 45 42 49 53 20 00 00 00 00 00 00 00 00 00
|
// 30 02 1A 00 19 00 FF 00 02 19 42 52 45 42 49 53 20 00 00 00 00 00 00 00 00 00
|
||||||
// 04 01 B0 04 7F 1F 11 33 40 1F 22 01 07 00 00 01 07 00 00 63 05 00 00 99 A2
|
// 04 01 B0 04 7F 1F 11 33 40 1F 22 01 07 00 00 01 07 00 00 63 05 00 00 99 A2
|
||||||
@@ -90,15 +94,15 @@ void LGEView::generate_frame_pseudo() {
|
|||||||
};
|
};
|
||||||
uint32_t c;
|
uint32_t c;
|
||||||
|
|
||||||
//data_header[2] = field_salle.value(); // ?
|
//data_header[2] = field_room.value(); // ?
|
||||||
//data_footer[0] = field_salle.value(); // ?
|
//data_footer[0] = field_room.value(); // ?
|
||||||
|
|
||||||
data.insert(data.begin(), data_header.begin(), data_header.end());
|
data.insert(data.begin(), data_header.begin(), data_header.end());
|
||||||
|
|
||||||
data.push_back(field_joueur.value());
|
data.push_back(field_player.value());
|
||||||
|
|
||||||
c = 0;
|
c = 0;
|
||||||
for (auto &ch : pseudo) {
|
for (auto &ch : nickname) {
|
||||||
data.push_back(ch);
|
data.push_back(ch);
|
||||||
c++;
|
c++;
|
||||||
}
|
}
|
||||||
@@ -108,16 +112,16 @@ void LGEView::generate_frame_pseudo() {
|
|||||||
while (++c < 16)
|
while (++c < 16)
|
||||||
data.push_back(0x00);
|
data.push_back(0x00);
|
||||||
|
|
||||||
data.push_back(field_equipe.value());
|
data.push_back(field_team.value());
|
||||||
|
|
||||||
data.insert(data.end(), data_footer.begin(), data_footer.end());
|
data.insert(data.end(), data_footer.begin(), data_footer.end());
|
||||||
|
|
||||||
console.write("\n\x1B\x0ESet pseudo:\x1B\x10");
|
console.write("\n\x1B\x0ESet nickname:\x1B\x10");
|
||||||
|
|
||||||
generate_lge_frame(0x02, 0x001A, field_joueur.value(), data);
|
generate_lge_frame(0x02, 0x001A, field_player.value(), data);
|
||||||
}
|
}
|
||||||
|
|
||||||
void LGEView::generate_frame_equipe() {
|
void LGEView::generate_frame_team() {
|
||||||
// 0041.83s:
|
// 0041.83s:
|
||||||
// 3D 03 FF FF FF FF 02 03 01 52 4F 55 47 45 00 00 00 00 00 00 00 00 00 00 00 00
|
// 3D 03 FF FF FF FF 02 03 01 52 4F 55 47 45 00 00 00 00 00 00 00 00 00 00 00 00
|
||||||
// 02 56 45 52 54 45 00 00 00 00 00 00 00 00 00 00 00 01 03 42 4C 45 55 45 00 00
|
// 02 56 45 52 54 45 00 00 00 00 00 00 00 00 00 00 00 01 03 42 4C 45 55 45 00 00
|
||||||
@@ -129,10 +133,10 @@ void LGEView::generate_frame_equipe() {
|
|||||||
|
|
||||||
data.insert(data.begin(), data_header.begin(), data_header.end());
|
data.insert(data.begin(), data_header.begin(), data_header.end());
|
||||||
|
|
||||||
data.push_back(field_equipe.value());
|
data.push_back(field_team.value());
|
||||||
|
|
||||||
c = 0;
|
c = 0;
|
||||||
for (auto &ch : pseudo) {
|
for (auto &ch : nickname) {
|
||||||
data.push_back(ch);
|
data.push_back(ch);
|
||||||
c++;
|
c++;
|
||||||
}
|
}
|
||||||
@@ -140,14 +144,14 @@ void LGEView::generate_frame_equipe() {
|
|||||||
while (c++ < 16)
|
while (c++ < 16)
|
||||||
data.push_back(0x00);
|
data.push_back(0x00);
|
||||||
|
|
||||||
data.push_back(field_equipe.value() - 1); // Color ?
|
data.push_back(field_team.value() - 1); // Color ?
|
||||||
|
|
||||||
console.write("\n\x1B\x0ASet equipe:\x1B\x10");
|
console.write("\n\x1B\x0ASet team:\x1B\x10");
|
||||||
|
|
||||||
generate_lge_frame(0x03, data);
|
generate_lge_frame(0x03, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
void LGEView::generate_frame_broadcast_pseudo() {
|
void LGEView::generate_frame_broadcast_nickname() {
|
||||||
// 0043.86s:
|
// 0043.86s:
|
||||||
// 3D 04 FF FF FF FF 02 03 19 42 52 45 42 49 53 20 00 00 00 00 00 00 00 00 00 04
|
// 3D 04 FF FF FF FF 02 03 19 42 52 45 42 49 53 20 00 00 00 00 00 00 00 00 00 04
|
||||||
// 07 50 4F 4E 45 59 20 00 00 00 00 00 00 00 00 00 00 05 1B 41 42 42 59 20 00 00
|
// 07 50 4F 4E 45 59 20 00 00 00 00 00 00 00 00 00 00 05 1B 41 42 42 59 20 00 00
|
||||||
@@ -159,10 +163,10 @@ void LGEView::generate_frame_broadcast_pseudo() {
|
|||||||
|
|
||||||
data.insert(data.begin(), data_header.begin(), data_header.end());
|
data.insert(data.begin(), data_header.begin(), data_header.end());
|
||||||
|
|
||||||
data.push_back(field_joueur.value());
|
data.push_back(field_player.value());
|
||||||
|
|
||||||
c = 0;
|
c = 0;
|
||||||
for (auto &ch : pseudo) {
|
for (auto &ch : nickname) {
|
||||||
data.push_back(ch);
|
data.push_back(ch);
|
||||||
c++;
|
c++;
|
||||||
}
|
}
|
||||||
@@ -172,9 +176,9 @@ void LGEView::generate_frame_broadcast_pseudo() {
|
|||||||
while (++c < 16)
|
while (++c < 16)
|
||||||
data.push_back(0x00);
|
data.push_back(0x00);
|
||||||
|
|
||||||
data.push_back(field_equipe.value());
|
data.push_back(field_team.value());
|
||||||
|
|
||||||
console.write("\n\x1B\x09" "Broadcast pseudo:\x1B\x10");
|
console.write("\n\x1B\x09" "Broadcast nickname:\x1B\x10");
|
||||||
|
|
||||||
generate_lge_frame(0x04, data);
|
generate_lge_frame(0x04, data);
|
||||||
}
|
}
|
||||||
@@ -184,14 +188,14 @@ void LGEView::generate_frame_start() {
|
|||||||
// 0A 05 FF FF FF FF 02 EC FF FF FF A3 35
|
// 0A 05 FF FF FF FF 02 EC FF FF FF A3 35
|
||||||
std::vector<uint8_t> data { 0x02, 0xEC, 0xFF, 0xFF, 0xFF };
|
std::vector<uint8_t> data { 0x02, 0xEC, 0xFF, 0xFF, 0xFF };
|
||||||
|
|
||||||
//data[0] = field_salle.value(); // ?
|
//data[0] = field_room.value(); // ?
|
||||||
|
|
||||||
console.write("\n\x1B\x0DStart:\x1B\x10");
|
console.write("\n\x1B\x0DStart:\x1B\x10");
|
||||||
generate_lge_frame(0x05, data);
|
generate_lge_frame(0x05, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
void LGEView::generate_frame_gameover() {
|
void LGEView::generate_frame_gameover() {
|
||||||
std::vector<uint8_t> data { (uint8_t)field_salle.value() };
|
std::vector<uint8_t> data { (uint8_t)field_room.value() };
|
||||||
|
|
||||||
console.write("\n\x1B\x0CGameover:\x1B\x10");
|
console.write("\n\x1B\x0CGameover:\x1B\x10");
|
||||||
generate_lge_frame(0x0D, data);
|
generate_lge_frame(0x0D, data);
|
||||||
@@ -203,7 +207,7 @@ void LGEView::generate_frame_collier() {
|
|||||||
// Custom
|
// Custom
|
||||||
// 0C 00 13 37 13 37 id flags channel playerid zapduty zaptime checksum CRC CRC
|
// 0C 00 13 37 13 37 id flags channel playerid zapduty zaptime checksum CRC CRC
|
||||||
// channel: field_channel
|
// channel: field_channel
|
||||||
// playerid: field_joueur
|
// playerid: field_player
|
||||||
// zapduty: field_power
|
// zapduty: field_power
|
||||||
// zaptime: field_duration
|
// zaptime: field_duration
|
||||||
|
|
||||||
@@ -218,8 +222,8 @@ void LGEView::generate_frame_collier() {
|
|||||||
std::vector<uint8_t> data {
|
std::vector<uint8_t> data {
|
||||||
id,
|
id,
|
||||||
flags,
|
flags,
|
||||||
(uint8_t)field_salle.value(),
|
(uint8_t)field_room.value(),
|
||||||
(uint8_t)field_joueur.value(),
|
(uint8_t)field_player.value(),
|
||||||
(uint8_t)field_power.value(),
|
(uint8_t)field_power.value(),
|
||||||
(uint8_t)(field_duration.value() * 10)
|
(uint8_t)(field_duration.value() * 10)
|
||||||
};
|
};
|
||||||
@@ -285,11 +289,11 @@ LGEView::LGEView(NavigationView& nav) {
|
|||||||
|
|
||||||
add_children({
|
add_children({
|
||||||
&labels,
|
&labels,
|
||||||
&options_trame,
|
&options_frame,
|
||||||
&field_salle,
|
&field_room,
|
||||||
&button_texte,
|
&button_text,
|
||||||
&field_equipe,
|
&field_team,
|
||||||
&field_joueur,
|
&field_player,
|
||||||
&field_id,
|
&field_id,
|
||||||
&field_power,
|
&field_power,
|
||||||
&field_duration,
|
&field_duration,
|
||||||
@@ -300,20 +304,29 @@ LGEView::LGEView(NavigationView& nav) {
|
|||||||
&tx_view
|
&tx_view
|
||||||
});
|
});
|
||||||
|
|
||||||
field_salle.set_value(1);
|
// load app settings
|
||||||
field_equipe.set_value(1);
|
auto rc = settings.load("tx_lge", &app_settings);
|
||||||
field_joueur.set_value(1);
|
if(rc == SETTINGS_OK) {
|
||||||
|
transmitter_model.set_rf_amp(app_settings.tx_amp);
|
||||||
|
transmitter_model.set_channel_bandwidth(app_settings.channel_bandwidth);
|
||||||
|
transmitter_model.set_tuning_frequency(app_settings.tx_frequency);
|
||||||
|
transmitter_model.set_tx_gain(app_settings.tx_gain);
|
||||||
|
}
|
||||||
|
|
||||||
|
field_room.set_value(1);
|
||||||
|
field_team.set_value(1);
|
||||||
|
field_player.set_value(1);
|
||||||
field_id.set_value(1);
|
field_id.set_value(1);
|
||||||
field_power.set_value(1);
|
field_power.set_value(1);
|
||||||
field_duration.set_value(2);
|
field_duration.set_value(2);
|
||||||
|
|
||||||
button_texte.on_select = [this, &nav](Button&) {
|
button_text.on_select = [this, &nav](Button&) {
|
||||||
text_prompt(
|
text_prompt(
|
||||||
nav,
|
nav,
|
||||||
pseudo,
|
nickname,
|
||||||
15,
|
15,
|
||||||
[this](std::string& buffer) {
|
[this](std::string& buffer) {
|
||||||
button_texte.set_text(buffer);
|
button_text.set_text(buffer);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -326,15 +339,15 @@ LGEView::LGEView(NavigationView& nav) {
|
|||||||
|
|
||||||
tx_view.on_start = [this]() {
|
tx_view.on_start = [this]() {
|
||||||
if (tx_mode == IDLE) {
|
if (tx_mode == IDLE) {
|
||||||
auto i = options_trame.selected_index_value();
|
auto i = options_frame.selected_index_value();
|
||||||
if (i == 0)
|
if (i == 0)
|
||||||
generate_frame_touche();
|
generate_frame_touche();
|
||||||
else if (i == 1)
|
else if (i == 1)
|
||||||
generate_frame_pseudo();
|
generate_frame_nickname();
|
||||||
else if (i == 2)
|
else if (i == 2)
|
||||||
generate_frame_equipe();
|
generate_frame_team();
|
||||||
else if (i == 3)
|
else if (i == 3)
|
||||||
generate_frame_broadcast_pseudo();
|
generate_frame_broadcast_nickname();
|
||||||
else if (i == 4)
|
else if (i == 4)
|
||||||
generate_frame_start();
|
generate_frame_start();
|
||||||
else if (i == 5)
|
else if (i == 5)
|
||||||
|
@@ -30,6 +30,7 @@
|
|||||||
#include "message.hpp"
|
#include "message.hpp"
|
||||||
#include "transmitter_model.hpp"
|
#include "transmitter_model.hpp"
|
||||||
#include "portapack.hpp"
|
#include "portapack.hpp"
|
||||||
|
#include "app_settings.hpp"
|
||||||
|
|
||||||
namespace ui {
|
namespace ui {
|
||||||
|
|
||||||
@@ -40,7 +41,7 @@ public:
|
|||||||
|
|
||||||
void focus() override;
|
void focus() override;
|
||||||
|
|
||||||
std::string title() const override { return "LGE tool"; };
|
std::string title() const override { return "LGE tool TX"; };
|
||||||
|
|
||||||
private:
|
private:
|
||||||
enum tx_modes {
|
enum tx_modes {
|
||||||
@@ -48,15 +49,19 @@ private:
|
|||||||
SINGLE,
|
SINGLE,
|
||||||
ALL
|
ALL
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// app save settings
|
||||||
|
std::app_settings settings { };
|
||||||
|
std::app_settings::AppSettings app_settings { };
|
||||||
|
|
||||||
tx_modes tx_mode = IDLE;
|
tx_modes tx_mode = IDLE;
|
||||||
|
|
||||||
RFM69 rfm69 { 5, 0x2DD4, true, true };
|
RFM69 rfm69 { 5, 0x2DD4, true, true };
|
||||||
|
|
||||||
uint32_t frame_size { 0 };
|
uint32_t frame_size { 0 };
|
||||||
uint32_t repeats { 0 };
|
uint32_t repeats { 0 };
|
||||||
uint32_t channel_index { 0 };
|
uint32_t channel_index { 0 };
|
||||||
std::string pseudo { "ABCDEF" };
|
std::string nickname { "ABCDEF" };
|
||||||
|
|
||||||
rf::Frequency channels[3] = { 868067000, 868183000, 868295000 };
|
rf::Frequency channels[3] = { 868067000, 868183000, 868295000 };
|
||||||
|
|
||||||
@@ -68,9 +73,9 @@ private:
|
|||||||
}
|
}
|
||||||
void generate_lge_frame(const uint8_t command, const uint16_t address_a, const uint16_t address_b, std::vector<uint8_t>& data);
|
void generate_lge_frame(const uint8_t command, const uint16_t address_a, const uint16_t address_b, std::vector<uint8_t>& data);
|
||||||
void generate_frame_touche();
|
void generate_frame_touche();
|
||||||
void generate_frame_pseudo();
|
void generate_frame_nickname();
|
||||||
void generate_frame_equipe();
|
void generate_frame_team();
|
||||||
void generate_frame_broadcast_pseudo();
|
void generate_frame_broadcast_nickname();
|
||||||
void generate_frame_start();
|
void generate_frame_start();
|
||||||
void generate_frame_gameover();
|
void generate_frame_gameover();
|
||||||
void generate_frame_collier();
|
void generate_frame_collier();
|
||||||
@@ -79,28 +84,28 @@ private:
|
|||||||
|
|
||||||
Labels labels {
|
Labels labels {
|
||||||
//{ { 7 * 8, 1 * 8 }, "NO FUN ALLOWED !", Color::red() },
|
//{ { 7 * 8, 1 * 8 }, "NO FUN ALLOWED !", Color::red() },
|
||||||
{ { 1 * 8, 1 * 8 }, "Trame:", Color::light_grey() },
|
{ { 1 * 8, 1 * 8 }, "Frame:", Color::light_grey() },
|
||||||
{ { 1 * 8, 3 * 8 }, "Salle:", Color::light_grey() },
|
{ { 2 * 8, 3 * 8 }, "Room:", Color::light_grey() },
|
||||||
{ { 14 * 8, 3 * 8 }, "Texte:", Color::light_grey() },
|
{ { 14 * 8, 3 * 8 }, "Text:", Color::light_grey() },
|
||||||
{ { 0 * 8, 5 * 8 }, "Equipe:", Color::light_grey() },
|
{ { 2 * 8, 5 * 8 }, "Team:", Color::light_grey() },
|
||||||
{ { 0 * 8, 7 * 8 }, "Joueur:", Color::light_grey() },
|
{ { 0 * 8, 7 * 8 }, "Player:", Color::light_grey() },
|
||||||
{ { 0 * 8, 10 * 8 }, "Collier:", Color::light_grey() },
|
{ { 0 * 8, 10 * 8 }, "Vest:", Color::light_grey() },
|
||||||
{ { 4 * 8, 12 * 8 }, "ID:", Color::light_grey() },
|
{ { 4 * 8, 12 * 8 }, "ID:", Color::light_grey() },
|
||||||
{ { 3 * 8, 14 * 8 }, "Pow: /10", Color::light_grey() },
|
{ { 3 * 8, 14 * 8 }, "Pow: /10", Color::light_grey() },
|
||||||
{ { 1 * 8, 16 * 8 }, "Duree: x100ms", Color::light_grey() }
|
{ { 2 * 8, 16 * 8 }, "Time: x100ms", Color::light_grey() }
|
||||||
};
|
};
|
||||||
|
|
||||||
OptionsField options_trame {
|
OptionsField options_frame {
|
||||||
{ 7 * 8, 1 * 8 },
|
{ 7 * 8, 1 * 8 },
|
||||||
13,
|
13,
|
||||||
{
|
{
|
||||||
{ "Touche", 0 },
|
{ "Key", 0 },
|
||||||
{ "Set pseudo", 1 },
|
{ "Set nickname", 1 },
|
||||||
{ "Set equipe", 2 },
|
{ "Set team", 2 },
|
||||||
{ "Brdcst pseudo", 3 },
|
{ "Brdcst nick", 3 },
|
||||||
{ "Start", 4 },
|
{ "Start", 4 },
|
||||||
{ "Game over", 5 },
|
{ "Game over", 5 },
|
||||||
{ "Set collier", 6 }
|
{ "Set vest", 6 }
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -111,7 +116,7 @@ private:
|
|||||||
true
|
true
|
||||||
};
|
};
|
||||||
|
|
||||||
NumberField field_salle {
|
NumberField field_room {
|
||||||
{ 7 * 8, 3 * 8 },
|
{ 7 * 8, 3 * 8 },
|
||||||
1,
|
1,
|
||||||
{ 1, 2 },
|
{ 1, 2 },
|
||||||
@@ -119,12 +124,12 @@ private:
|
|||||||
'0'
|
'0'
|
||||||
};
|
};
|
||||||
|
|
||||||
Button button_texte {
|
Button button_text {
|
||||||
{ 14 * 8, 5 * 8, 16 * 8, 3 * 8 },
|
{ 14 * 8, 5 * 8, 16 * 8, 3 * 8 },
|
||||||
"ABCDEF"
|
"ABCDEF"
|
||||||
};
|
};
|
||||||
|
|
||||||
NumberField field_equipe {
|
NumberField field_team {
|
||||||
{ 7 * 8, 5 * 8 },
|
{ 7 * 8, 5 * 8 },
|
||||||
1,
|
1,
|
||||||
{ 1, 6 },
|
{ 1, 6 },
|
||||||
@@ -132,7 +137,7 @@ private:
|
|||||||
'0'
|
'0'
|
||||||
};
|
};
|
||||||
|
|
||||||
NumberField field_joueur {
|
NumberField field_player {
|
||||||
{ 7 * 8, 7 * 8 },
|
{ 7 * 8, 7 * 8 },
|
||||||
2,
|
2,
|
||||||
{ 1, 50 },
|
{ 1, 50 },
|
||||||
|
@@ -77,11 +77,22 @@ POCSAGAppView::POCSAGAppView(NavigationView& nav) {
|
|||||||
&console
|
&console
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// load app settings
|
||||||
|
auto rc = settings.load("rx_pocsag", &app_settings);
|
||||||
|
if(rc == SETTINGS_OK) {
|
||||||
|
field_lna.set_value(app_settings.lna);
|
||||||
|
field_vga.set_value(app_settings.vga);
|
||||||
|
field_rf_amp.set_value(app_settings.rx_amp);
|
||||||
|
field_frequency.set_value(app_settings.rx_frequency);
|
||||||
|
}
|
||||||
|
else field_frequency.set_value(receiver_model.tuning_frequency());
|
||||||
|
|
||||||
|
receiver_model.set_modulation(ReceiverModel::Mode::NarrowbandFMAudio);
|
||||||
|
|
||||||
receiver_model.set_sampling_rate(3072000);
|
receiver_model.set_sampling_rate(3072000);
|
||||||
receiver_model.set_baseband_bandwidth(1750000);
|
receiver_model.set_baseband_bandwidth(1750000);
|
||||||
receiver_model.enable();
|
receiver_model.enable();
|
||||||
|
|
||||||
field_frequency.set_value(receiver_model.tuning_frequency());
|
|
||||||
field_frequency.set_step(receiver_model.frequency_step());
|
field_frequency.set_step(receiver_model.frequency_step());
|
||||||
field_frequency.on_change = [this](rf::Frequency f) {
|
field_frequency.on_change = [this](rf::Frequency f) {
|
||||||
update_freq(f);
|
update_freq(f);
|
||||||
@@ -127,6 +138,11 @@ POCSAGAppView::POCSAGAppView(NavigationView& nav) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
POCSAGAppView::~POCSAGAppView() {
|
POCSAGAppView::~POCSAGAppView() {
|
||||||
|
|
||||||
|
// save app settings
|
||||||
|
app_settings.rx_frequency = field_frequency.value();
|
||||||
|
settings.save("rx_pocsag", &app_settings);
|
||||||
|
|
||||||
audio::output::stop();
|
audio::output::stop();
|
||||||
|
|
||||||
// Save ignored address
|
// Save ignored address
|
||||||
|
@@ -28,7 +28,7 @@
|
|||||||
#include "ui_rssi.hpp"
|
#include "ui_rssi.hpp"
|
||||||
|
|
||||||
#include "log_file.hpp"
|
#include "log_file.hpp"
|
||||||
|
#include "app_settings.hpp"
|
||||||
#include "pocsag.hpp"
|
#include "pocsag.hpp"
|
||||||
#include "pocsag_packet.hpp"
|
#include "pocsag_packet.hpp"
|
||||||
|
|
||||||
@@ -60,6 +60,10 @@ public:
|
|||||||
private:
|
private:
|
||||||
static constexpr uint32_t initial_target_frequency = 466175000;
|
static constexpr uint32_t initial_target_frequency = 466175000;
|
||||||
|
|
||||||
|
// app save settings
|
||||||
|
std::app_settings settings { };
|
||||||
|
std::app_settings::AppSettings app_settings { };
|
||||||
|
|
||||||
bool logging { true };
|
bool logging { true };
|
||||||
bool ignore { true };
|
bool ignore { true };
|
||||||
uint32_t last_address = 0xFFFFFFFF;
|
uint32_t last_address = 0xFFFFFFFF;
|
||||||
|
@@ -201,6 +201,16 @@ ReplayAppView::ReplayAppView(
|
|||||||
tx_gain = 35;field_rfgain.set_value(tx_gain); // Initial default value (-12 dB's max ).
|
tx_gain = 35;field_rfgain.set_value(tx_gain); // Initial default value (-12 dB's max ).
|
||||||
field_rfamp.set_value(rf_amp ? 14 : 0); // Initial default value True. (TX RF amp on , +14dB's)
|
field_rfamp.set_value(rf_amp ? 14 : 0); // Initial default value True. (TX RF amp on , +14dB's)
|
||||||
|
|
||||||
|
field_rfamp.on_change = [this](int32_t v) { // allow initial value change just after opened file.
|
||||||
|
rf_amp = (bool)v;
|
||||||
|
};
|
||||||
|
field_rfamp.set_value(rf_amp ? 14 : 0);
|
||||||
|
|
||||||
|
field_rfgain.on_change = [this](int32_t v) { // allow initial value change just after opened file.
|
||||||
|
tx_gain = v;
|
||||||
|
};
|
||||||
|
field_rfgain.set_value(tx_gain);
|
||||||
|
|
||||||
baseband::run_image(portapack::spi_flash::image_tag_replay);
|
baseband::run_image(portapack::spi_flash::image_tag_replay);
|
||||||
|
|
||||||
add_children({
|
add_children({
|
||||||
|
@@ -240,6 +240,15 @@ SoundBoardView::SoundBoardView(
|
|||||||
&button_next_page,
|
&button_next_page,
|
||||||
&tx_view
|
&tx_view
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// load app settings
|
||||||
|
auto rc = settings.load("tx_soundboard", &app_settings);
|
||||||
|
if(rc == SETTINGS_OK) {
|
||||||
|
transmitter_model.set_rf_amp(app_settings.tx_amp);
|
||||||
|
transmitter_model.set_channel_bandwidth(app_settings.channel_bandwidth);
|
||||||
|
transmitter_model.set_tuning_frequency(app_settings.tx_frequency);
|
||||||
|
transmitter_model.set_tx_gain(app_settings.tx_gain);
|
||||||
|
}
|
||||||
|
|
||||||
refresh_list();
|
refresh_list();
|
||||||
|
|
||||||
@@ -280,6 +289,10 @@ SoundBoardView::SoundBoardView(
|
|||||||
}
|
}
|
||||||
|
|
||||||
SoundBoardView::~SoundBoardView() {
|
SoundBoardView::~SoundBoardView() {
|
||||||
|
// save app settings
|
||||||
|
app_settings.tx_frequency = transmitter_model.tuning_frequency();
|
||||||
|
settings.save("tx_soundboard", &app_settings);
|
||||||
|
|
||||||
stop();
|
stop();
|
||||||
transmitter_model.disable();
|
transmitter_model.disable();
|
||||||
baseband::shutdown();
|
baseband::shutdown();
|
||||||
|
@@ -30,6 +30,7 @@
|
|||||||
#include "lfsr_random.hpp"
|
#include "lfsr_random.hpp"
|
||||||
#include "io_wave.hpp"
|
#include "io_wave.hpp"
|
||||||
#include "tone_key.hpp"
|
#include "tone_key.hpp"
|
||||||
|
#include "app_settings.hpp"
|
||||||
|
|
||||||
namespace ui {
|
namespace ui {
|
||||||
|
|
||||||
@@ -45,10 +46,14 @@ public:
|
|||||||
|
|
||||||
void focus() override;
|
void focus() override;
|
||||||
|
|
||||||
std::string title() const override { return "Soundboard"; };
|
std::string title() const override { return "Soundboard TX"; };
|
||||||
|
|
||||||
private:
|
private:
|
||||||
NavigationView& nav_;
|
NavigationView& nav_;
|
||||||
|
|
||||||
|
// app save settings
|
||||||
|
std::app_settings settings { };
|
||||||
|
std::app_settings::AppSettings app_settings { };
|
||||||
|
|
||||||
enum tx_modes {
|
enum tx_modes {
|
||||||
NORMAL = 0,
|
NORMAL = 0,
|
||||||
|
@@ -151,6 +151,16 @@ TPMSAppView::TPMSAppView(NavigationView&) {
|
|||||||
&options_type,
|
&options_type,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// load app settings
|
||||||
|
auto rc = settings.load("rx_tpms", &app_settings);
|
||||||
|
if(rc == SETTINGS_OK) {
|
||||||
|
field_lna.set_value(app_settings.lna);
|
||||||
|
field_vga.set_value(app_settings.vga);
|
||||||
|
field_rf_amp.set_value(app_settings.rx_amp);
|
||||||
|
options_band.set_by_value(app_settings.rx_frequency);
|
||||||
|
}
|
||||||
|
else options_band.set_by_value(receiver_model.tuning_frequency());
|
||||||
|
|
||||||
radio::enable({
|
radio::enable({
|
||||||
tuning_frequency(),
|
tuning_frequency(),
|
||||||
sampling_rate,
|
sampling_rate,
|
||||||
@@ -184,6 +194,12 @@ TPMSAppView::TPMSAppView(NavigationView&) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
TPMSAppView::~TPMSAppView() {
|
TPMSAppView::~TPMSAppView() {
|
||||||
|
|
||||||
|
|
||||||
|
// save app settings
|
||||||
|
app_settings.rx_frequency = target_frequency_;
|
||||||
|
settings.save("rx_tpms", &app_settings);
|
||||||
|
|
||||||
radio::disable();
|
radio::disable();
|
||||||
|
|
||||||
baseband::shutdown();
|
baseband::shutdown();
|
||||||
|
@@ -27,7 +27,7 @@
|
|||||||
#include "ui_receiver.hpp"
|
#include "ui_receiver.hpp"
|
||||||
#include "ui_rssi.hpp"
|
#include "ui_rssi.hpp"
|
||||||
#include "ui_channel.hpp"
|
#include "ui_channel.hpp"
|
||||||
|
#include "app_settings.hpp"
|
||||||
#include "event_m0.hpp"
|
#include "event_m0.hpp"
|
||||||
|
|
||||||
#include "log_file.hpp"
|
#include "log_file.hpp"
|
||||||
@@ -103,13 +103,17 @@ public:
|
|||||||
|
|
||||||
void focus() override;
|
void focus() override;
|
||||||
|
|
||||||
std::string title() const override { return "TPMS"; };
|
std::string title() const override { return "TPMS Cars RX"; };
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static constexpr uint32_t initial_target_frequency = 315000000;
|
static constexpr uint32_t initial_target_frequency = 315000000;
|
||||||
static constexpr uint32_t sampling_rate = 2457600;
|
static constexpr uint32_t sampling_rate = 2457600;
|
||||||
static constexpr uint32_t baseband_bandwidth = 1750000;
|
static constexpr uint32_t baseband_bandwidth = 1750000;
|
||||||
|
|
||||||
|
// app save settings
|
||||||
|
std::app_settings settings { };
|
||||||
|
std::app_settings::AppSettings app_settings { };
|
||||||
|
|
||||||
MessageHandlerRegistration message_handler_packet {
|
MessageHandlerRegistration message_handler_packet {
|
||||||
Message::ID::TPMSPacket,
|
Message::ID::TPMSPacket,
|
||||||
[this](Message* const p) {
|
[this](Message* const p) {
|
||||||
|
@@ -309,8 +309,12 @@ void ADSBRxView::focus() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ADSBRxView::~ADSBRxView() {
|
ADSBRxView::~ADSBRxView() {
|
||||||
receiver_model.set_tuning_frequency(prevFreq);
|
|
||||||
|
|
||||||
|
// save app settings
|
||||||
|
settings.save("rx_adsb", &app_settings);
|
||||||
|
|
||||||
|
//TODO: once all apps keep there own settin previous frequency logic can be removed
|
||||||
|
receiver_model.set_tuning_frequency(prevFreq);
|
||||||
rtc_time::signal_tick_second -= signal_token_tick_second;
|
rtc_time::signal_tick_second -= signal_token_tick_second;
|
||||||
receiver_model.disable();
|
receiver_model.disable();
|
||||||
baseband::shutdown();
|
baseband::shutdown();
|
||||||
@@ -458,6 +462,21 @@ ADSBRxView::ADSBRxView(NavigationView& nav) {
|
|||||||
&recent_entries_view
|
&recent_entries_view
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
// load app settings
|
||||||
|
auto rc = settings.load("rx_adsb", &app_settings);
|
||||||
|
if(rc == SETTINGS_OK) {
|
||||||
|
field_lna.set_value(app_settings.lna);
|
||||||
|
field_vga.set_value(app_settings.vga);
|
||||||
|
field_rf_amp.set_value(app_settings.rx_amp);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
field_lna.set_value(40);
|
||||||
|
field_vga.set_value(40);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
recent_entries_view.set_parent_rect({ 0, 16, 240, 272 });
|
recent_entries_view.set_parent_rect({ 0, 16, 240, 272 });
|
||||||
recent_entries_view.on_select = [this, &nav](const AircraftRecentEntry& entry) {
|
recent_entries_view.on_select = [this, &nav](const AircraftRecentEntry& entry) {
|
||||||
detailed_entry_key = entry.key();
|
detailed_entry_key = entry.key();
|
||||||
@@ -478,8 +497,6 @@ ADSBRxView::ADSBRxView(NavigationView& nav) {
|
|||||||
baseband::set_adsb();
|
baseband::set_adsb();
|
||||||
|
|
||||||
receiver_model.set_tuning_frequency(1090000000);
|
receiver_model.set_tuning_frequency(1090000000);
|
||||||
field_lna.set_value(40);
|
|
||||||
field_vga.set_value(40);
|
|
||||||
receiver_model.set_modulation(ReceiverModel::Mode::SpectrumAnalysis);
|
receiver_model.set_modulation(ReceiverModel::Mode::SpectrumAnalysis);
|
||||||
receiver_model.set_sampling_rate(2000000);
|
receiver_model.set_sampling_rate(2000000);
|
||||||
receiver_model.set_baseband_bandwidth(2500000);
|
receiver_model.set_baseband_bandwidth(2500000);
|
||||||
|
@@ -32,7 +32,7 @@
|
|||||||
#include "log_file.hpp"
|
#include "log_file.hpp"
|
||||||
#include "adsb.hpp"
|
#include "adsb.hpp"
|
||||||
#include "message.hpp"
|
#include "message.hpp"
|
||||||
|
#include "app_settings.hpp"
|
||||||
#include "crc.hpp"
|
#include "crc.hpp"
|
||||||
|
|
||||||
using namespace adsb;
|
using namespace adsb;
|
||||||
@@ -184,7 +184,7 @@ private:
|
|||||||
AircraftRecentEntry entry_copy { 0 };
|
AircraftRecentEntry entry_copy { 0 };
|
||||||
std::function<void(void)> on_close_ { };
|
std::function<void(void)> on_close_ { };
|
||||||
bool send_updates { false };
|
bool send_updates { false };
|
||||||
std::database db;
|
std::database db = { };
|
||||||
std::string icao_code = "";
|
std::string icao_code = "";
|
||||||
int return_code = 0;
|
int return_code = 0;
|
||||||
|
|
||||||
@@ -279,7 +279,7 @@ private:
|
|||||||
GeoMapView* geomap_view { nullptr };
|
GeoMapView* geomap_view { nullptr };
|
||||||
ADSBRxAircraftDetailsView* aircraft_details_view { nullptr };
|
ADSBRxAircraftDetailsView* aircraft_details_view { nullptr };
|
||||||
bool send_updates { false };
|
bool send_updates { false };
|
||||||
std::database db;
|
std::database db = { };
|
||||||
std::string airline_code = "";
|
std::string airline_code = "";
|
||||||
int return_code = 0;
|
int return_code = 0;
|
||||||
|
|
||||||
@@ -361,17 +361,20 @@ public:
|
|||||||
|
|
||||||
void focus() override;
|
void focus() override;
|
||||||
|
|
||||||
std::string title() const override { return "ADS-B receive"; };
|
std::string title() const override { return "ADS-B RX"; };
|
||||||
|
|
||||||
void replace_entry(AircraftRecentEntry & entry);
|
void replace_entry(AircraftRecentEntry & entry);
|
||||||
AircraftRecentEntry find_or_create_entry(uint32_t ICAO_address);
|
AircraftRecentEntry find_or_create_entry(uint32_t ICAO_address);
|
||||||
void sort_entries_by_state();
|
void sort_entries_by_state();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
rf::Frequency prevFreq;
|
rf::Frequency prevFreq = { 0 };
|
||||||
std::unique_ptr<ADSBLogger> logger { };
|
std::unique_ptr<ADSBLogger> logger { };
|
||||||
void on_frame(const ADSBFrameMessage * message);
|
void on_frame(const ADSBFrameMessage * message);
|
||||||
void on_tick_second();
|
void on_tick_second();
|
||||||
|
// app save settings
|
||||||
|
std::app_settings settings { };
|
||||||
|
std::app_settings::AppSettings app_settings { };
|
||||||
|
|
||||||
const RecentEntriesColumns columns { {
|
const RecentEntriesColumns columns { {
|
||||||
#if false
|
#if false
|
||||||
|
@@ -284,6 +284,11 @@ void ADSBTxView::focus() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ADSBTxView::~ADSBTxView() {
|
ADSBTxView::~ADSBTxView() {
|
||||||
|
|
||||||
|
// save app settings
|
||||||
|
app_settings.tx_frequency = transmitter_model.tuning_frequency();
|
||||||
|
settings.save("tx_adsb", &app_settings);
|
||||||
|
|
||||||
transmitter_model.disable();
|
transmitter_model.disable();
|
||||||
baseband::shutdown();
|
baseband::shutdown();
|
||||||
}
|
}
|
||||||
@@ -334,8 +339,16 @@ ADSBTxView::ADSBTxView(
|
|||||||
&view_squawk,
|
&view_squawk,
|
||||||
&text_frame,
|
&text_frame,
|
||||||
&tx_view
|
&tx_view
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// load app settings
|
||||||
|
auto rc = settings.load("tx_adsb", &app_settings);
|
||||||
|
if(rc == SETTINGS_OK) {
|
||||||
|
transmitter_model.set_tuning_frequency(app_settings.tx_frequency);
|
||||||
|
transmitter_model.set_rf_amp(app_settings.tx_amp);
|
||||||
|
transmitter_model.set_tx_gain(app_settings.tx_gain);
|
||||||
|
}
|
||||||
|
|
||||||
tx_view.on_edit_frequency = [this, &nav]() {
|
tx_view.on_edit_frequency = [this, &nav]() {
|
||||||
auto new_view = nav.push<FrequencyKeypadView>(receiver_model.tuning_frequency());
|
auto new_view = nav.push<FrequencyKeypadView>(receiver_model.tuning_frequency());
|
||||||
new_view->on_changed = [this](rf::Frequency f) {
|
new_view->on_changed = [this](rf::Frequency f) {
|
||||||
|
@@ -28,6 +28,7 @@
|
|||||||
#include "ui_transmitter.hpp"
|
#include "ui_transmitter.hpp"
|
||||||
#include "message.hpp"
|
#include "message.hpp"
|
||||||
#include "transmitter_model.hpp"
|
#include "transmitter_model.hpp"
|
||||||
|
#include "app_settings.hpp"
|
||||||
#include "portapack.hpp"
|
#include "portapack.hpp"
|
||||||
|
|
||||||
using namespace adsb;
|
using namespace adsb;
|
||||||
@@ -152,7 +153,7 @@ public:
|
|||||||
|
|
||||||
void focus() override;
|
void focus() override;
|
||||||
|
|
||||||
std::string title() const override { return "ADS-B transmit"; };
|
std::string title() const override { return "ADS-B TX"; };
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/*enum tx_modes {
|
/*enum tx_modes {
|
||||||
@@ -189,6 +190,10 @@ private:
|
|||||||
-1,
|
-1,
|
||||||
-1
|
-1
|
||||||
};*/
|
};*/
|
||||||
|
|
||||||
|
// app save settings
|
||||||
|
std::app_settings settings { };
|
||||||
|
std::app_settings::AppSettings app_settings { };
|
||||||
|
|
||||||
//tx_modes tx_mode = IDLE;
|
//tx_modes tx_mode = IDLE;
|
||||||
NavigationView& nav_;
|
NavigationView& nav_;
|
||||||
|
@@ -66,6 +66,15 @@ AFSKRxView::AFSKRxView(NavigationView& nav) {
|
|||||||
&console
|
&console
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// load app settings
|
||||||
|
auto rc = settings.load("rx_afsk", &app_settings);
|
||||||
|
if(rc == SETTINGS_OK) {
|
||||||
|
field_lna.set_value(app_settings.lna);
|
||||||
|
field_vga.set_value(app_settings.vga);
|
||||||
|
field_rf_amp.set_value(app_settings.rx_amp);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// DEBUG
|
// DEBUG
|
||||||
record_view.on_error = [&nav](std::string message) {
|
record_view.on_error = [&nav](std::string message) {
|
||||||
nav.display_modal("Error", message);
|
nav.display_modal("Error", message);
|
||||||
@@ -164,6 +173,11 @@ void AFSKRxView::on_data(uint32_t value, bool is_data) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
AFSKRxView::~AFSKRxView() {
|
AFSKRxView::~AFSKRxView() {
|
||||||
|
|
||||||
|
// save app settings
|
||||||
|
app_settings.rx_frequency = field_frequency.value();
|
||||||
|
settings.save("rx_afsk", &app_settings);
|
||||||
|
|
||||||
audio::output::stop();
|
audio::output::stop();
|
||||||
receiver_model.disable();
|
receiver_model.disable();
|
||||||
baseband::shutdown();
|
baseband::shutdown();
|
||||||
|
@@ -27,7 +27,7 @@
|
|||||||
#include "ui_navigation.hpp"
|
#include "ui_navigation.hpp"
|
||||||
#include "ui_receiver.hpp"
|
#include "ui_receiver.hpp"
|
||||||
#include "ui_record_view.hpp" // DEBUG
|
#include "ui_record_view.hpp" // DEBUG
|
||||||
|
#include "app_settings.hpp"
|
||||||
#include "log_file.hpp"
|
#include "log_file.hpp"
|
||||||
#include "utility.hpp"
|
#include "utility.hpp"
|
||||||
|
|
||||||
@@ -57,6 +57,10 @@ public:
|
|||||||
private:
|
private:
|
||||||
void on_data(uint32_t value, bool is_data);
|
void on_data(uint32_t value, bool is_data);
|
||||||
|
|
||||||
|
// app save settings
|
||||||
|
std::app_settings settings { };
|
||||||
|
std::app_settings::AppSettings app_settings { };
|
||||||
|
|
||||||
uint8_t console_color { 0 };
|
uint8_t console_color { 0 };
|
||||||
uint32_t prev_value { 0 };
|
uint32_t prev_value { 0 };
|
||||||
std::string str_log { "" };
|
std::string str_log { "" };
|
||||||
|
@@ -98,6 +98,15 @@ APRSRxView::APRSRxView(NavigationView& nav, Rect parent_rect) : View(parent_rect
|
|||||||
&console
|
&console
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// load app settings
|
||||||
|
auto rc = settings.load("rx_aprs", &app_settings);
|
||||||
|
if(rc == SETTINGS_OK) {
|
||||||
|
field_lna.set_value(app_settings.lna);
|
||||||
|
field_vga.set_value(app_settings.vga);
|
||||||
|
field_rf_amp.set_value(app_settings.rx_amp);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// DEBUG
|
// DEBUG
|
||||||
record_view.on_error = [&nav](std::string message) {
|
record_view.on_error = [&nav](std::string message) {
|
||||||
nav.display_modal("Error", message);
|
nav.display_modal("Error", message);
|
||||||
@@ -211,6 +220,10 @@ void APRSRxView::on_show(){
|
|||||||
}
|
}
|
||||||
|
|
||||||
APRSRxView::~APRSRxView() {
|
APRSRxView::~APRSRxView() {
|
||||||
|
|
||||||
|
// save app settings
|
||||||
|
settings.save("rx_aprs", &app_settings);
|
||||||
|
|
||||||
audio::output::stop();
|
audio::output::stop();
|
||||||
receiver_model.disable();
|
receiver_model.disable();
|
||||||
baseband::shutdown();
|
baseband::shutdown();
|
||||||
|
@@ -28,7 +28,7 @@
|
|||||||
#include "ui_receiver.hpp"
|
#include "ui_receiver.hpp"
|
||||||
#include "ui_record_view.hpp" // DEBUG
|
#include "ui_record_view.hpp" // DEBUG
|
||||||
#include "ui_geomap.hpp"
|
#include "ui_geomap.hpp"
|
||||||
|
#include "app_settings.hpp"
|
||||||
#include "recent_entries.hpp"
|
#include "recent_entries.hpp"
|
||||||
#include "ui_tabview.hpp"
|
#include "ui_tabview.hpp"
|
||||||
|
|
||||||
@@ -57,12 +57,12 @@ struct APRSRecentEntry {
|
|||||||
uint16_t hits { 0 };
|
uint16_t hits { 0 };
|
||||||
uint32_t age { 0 };
|
uint32_t age { 0 };
|
||||||
|
|
||||||
uint64_t source;
|
uint64_t source { 0 };
|
||||||
std::string source_formatted { " " };
|
std::string source_formatted { " " };
|
||||||
std::string time_string { "" };
|
std::string time_string { "" };
|
||||||
std::string info_string { "" };
|
std::string info_string { "" };
|
||||||
|
|
||||||
aprs::aprs_pos pos;
|
aprs::aprs_pos pos { 0 , 0 , 0 , 0 };
|
||||||
bool has_position = false;
|
bool has_position = false;
|
||||||
APRSRecentEntry(uint64_t src)
|
APRSRecentEntry(uint64_t src)
|
||||||
{
|
{
|
||||||
@@ -131,6 +131,7 @@ private:
|
|||||||
GeoMapView* geomap_view { nullptr };
|
GeoMapView* geomap_view { nullptr };
|
||||||
bool send_updates { false };
|
bool send_updates { false };
|
||||||
|
|
||||||
|
|
||||||
Console console {
|
Console console {
|
||||||
{ 0, 0 * 16, 240, 224 }
|
{ 0, 0 * 16, 240, 224 }
|
||||||
};
|
};
|
||||||
@@ -192,6 +193,11 @@ private:
|
|||||||
void on_data(uint32_t value, bool is_data);
|
void on_data(uint32_t value, bool is_data);
|
||||||
bool reset_console = false;
|
bool reset_console = false;
|
||||||
|
|
||||||
|
// app save settings
|
||||||
|
std::app_settings settings { };
|
||||||
|
std::app_settings::AppSettings app_settings { };
|
||||||
|
|
||||||
|
|
||||||
uint8_t console_color { 0 };
|
uint8_t console_color { 0 };
|
||||||
std::string str_log { "" };
|
std::string str_log { "" };
|
||||||
|
|
||||||
|
@@ -43,6 +43,10 @@ void APRSTXView::focus() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
APRSTXView::~APRSTXView() {
|
APRSTXView::~APRSTXView() {
|
||||||
|
// save app settings
|
||||||
|
app_settings.tx_frequency = transmitter_model.tuning_frequency();
|
||||||
|
settings.save("tx_aprs", &app_settings);
|
||||||
|
|
||||||
transmitter_model.disable();
|
transmitter_model.disable();
|
||||||
baseband::shutdown();
|
baseband::shutdown();
|
||||||
}
|
}
|
||||||
@@ -66,7 +70,7 @@ void APRSTXView::start_tx() {
|
|||||||
1200,
|
1200,
|
||||||
2200,
|
2200,
|
||||||
1,
|
1,
|
||||||
10000, //transmitter_model.channel_bandwidth(),
|
10000, //APRS uses fixed 10k bandwidth
|
||||||
8
|
8
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -95,6 +99,15 @@ APRSTXView::APRSTXView(NavigationView& nav) {
|
|||||||
&tx_view
|
&tx_view
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
// load app settings
|
||||||
|
auto rc = settings.load("tx_aprs", &app_settings);
|
||||||
|
if(rc == SETTINGS_OK) {
|
||||||
|
transmitter_model.set_rf_amp(app_settings.tx_amp);
|
||||||
|
transmitter_model.set_tuning_frequency(app_settings.tx_frequency);
|
||||||
|
transmitter_model.set_tx_gain(app_settings.tx_gain);
|
||||||
|
}
|
||||||
|
|
||||||
button_set.on_select = [this, &nav](Button&) {
|
button_set.on_select = [this, &nav](Button&) {
|
||||||
text_prompt(
|
text_prompt(
|
||||||
nav,
|
nav,
|
||||||
|
@@ -29,6 +29,7 @@
|
|||||||
|
|
||||||
#include "message.hpp"
|
#include "message.hpp"
|
||||||
#include "transmitter_model.hpp"
|
#include "transmitter_model.hpp"
|
||||||
|
#include "app_settings.hpp"
|
||||||
#include "portapack.hpp"
|
#include "portapack.hpp"
|
||||||
|
|
||||||
namespace ui {
|
namespace ui {
|
||||||
@@ -40,17 +41,14 @@ public:
|
|||||||
|
|
||||||
void focus() override;
|
void focus() override;
|
||||||
|
|
||||||
std::string title() const override { return "APRS TX (beta)"; };
|
std::string title() const override { return "APRS TX"; };
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/*enum tx_modes {
|
|
||||||
IDLE = 0,
|
|
||||||
SINGLE,
|
|
||||||
SEQUENCE
|
|
||||||
};
|
|
||||||
|
|
||||||
tx_modes tx_mode = IDLE;*/
|
|
||||||
|
|
||||||
|
// app save settings
|
||||||
|
std::app_settings settings { };
|
||||||
|
std::app_settings::AppSettings app_settings { };
|
||||||
|
|
||||||
std::string payload { "" };
|
std::string payload { "" };
|
||||||
|
|
||||||
void start_tx();
|
void start_tx();
|
||||||
@@ -103,7 +101,7 @@ private:
|
|||||||
TransmitterView tx_view {
|
TransmitterView tx_view {
|
||||||
16 * 16,
|
16 * 16,
|
||||||
5000,
|
5000,
|
||||||
10
|
0 // disable setting bandwith, since APRS used fixed 10k bandwidth
|
||||||
};
|
};
|
||||||
|
|
||||||
MessageHandlerRegistration message_handler_tx_progress {
|
MessageHandlerRegistration message_handler_tx_progress {
|
||||||
|
@@ -96,9 +96,9 @@ void BHTView::on_tx_progress(const uint32_t progress, const bool done) {
|
|||||||
if (target_system == XYLOS) {
|
if (target_system == XYLOS) {
|
||||||
if (done) {
|
if (done) {
|
||||||
if (tx_mode == SINGLE) {
|
if (tx_mode == SINGLE) {
|
||||||
if (checkbox_cligno.value()) {
|
if (checkbox_flashing.value()) {
|
||||||
// TODO: Thread !
|
// TODO: Thread !
|
||||||
chThdSleepMilliseconds(field_tempo.value() * 1000); // Dirty :(
|
chThdSleepMilliseconds(field_speed.value() * 1000); // Dirty :(
|
||||||
view_xylos.flip_relays();
|
view_xylos.flip_relays();
|
||||||
start_tx();
|
start_tx();
|
||||||
} else
|
} else
|
||||||
@@ -120,9 +120,9 @@ void BHTView::on_tx_progress(const uint32_t progress, const bool done) {
|
|||||||
} else {
|
} else {
|
||||||
view_EPAR.half = false;
|
view_EPAR.half = false;
|
||||||
if (tx_mode == SINGLE) {
|
if (tx_mode == SINGLE) {
|
||||||
if (checkbox_cligno.value()) {
|
if (checkbox_flashing.value()) {
|
||||||
// TODO: Thread !
|
// TODO: Thread !
|
||||||
chThdSleepMilliseconds(field_tempo.value() * 1000); // Dirty :(
|
chThdSleepMilliseconds(field_speed.value() * 1000); // Dirty :(
|
||||||
view_EPAR.flip_relays();
|
view_EPAR.flip_relays();
|
||||||
start_tx();
|
start_tx();
|
||||||
} else
|
} else
|
||||||
@@ -140,6 +140,10 @@ void BHTView::on_tx_progress(const uint32_t progress, const bool done) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
BHTView::~BHTView() {
|
BHTView::~BHTView() {
|
||||||
|
// save app settings
|
||||||
|
app_settings.tx_frequency = transmitter_model.tuning_frequency();
|
||||||
|
settings.save("tx_bht", &app_settings);
|
||||||
|
|
||||||
transmitter_model.disable();
|
transmitter_model.disable();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -150,13 +154,22 @@ BHTView::BHTView(NavigationView& nav) {
|
|||||||
&view_xylos,
|
&view_xylos,
|
||||||
&view_EPAR,
|
&view_EPAR,
|
||||||
&checkbox_scan,
|
&checkbox_scan,
|
||||||
&checkbox_cligno,
|
&checkbox_flashing,
|
||||||
&field_tempo,
|
&field_speed,
|
||||||
&progressbar,
|
&progressbar,
|
||||||
&tx_view
|
&tx_view
|
||||||
});
|
});
|
||||||
|
|
||||||
field_tempo.set_value(1);
|
// load app settings
|
||||||
|
auto rc = settings.load("tx_bht", &app_settings);
|
||||||
|
if(rc == SETTINGS_OK) {
|
||||||
|
transmitter_model.set_rf_amp(app_settings.tx_amp);
|
||||||
|
transmitter_model.set_channel_bandwidth(app_settings.channel_bandwidth);
|
||||||
|
transmitter_model.set_tuning_frequency(app_settings.tx_frequency);
|
||||||
|
transmitter_model.set_tx_gain(app_settings.tx_gain);
|
||||||
|
}
|
||||||
|
|
||||||
|
field_speed.set_value(1);
|
||||||
|
|
||||||
tx_view.on_edit_frequency = [this, &nav]() {
|
tx_view.on_edit_frequency = [this, &nav]() {
|
||||||
auto new_view = nav.push<FrequencyKeypadView>(receiver_model.tuning_frequency());
|
auto new_view = nav.push<FrequencyKeypadView>(receiver_model.tuning_frequency());
|
||||||
|
@@ -32,6 +32,7 @@
|
|||||||
#include "message.hpp"
|
#include "message.hpp"
|
||||||
#include "transmitter_model.hpp"
|
#include "transmitter_model.hpp"
|
||||||
#include "encoders.hpp"
|
#include "encoders.hpp"
|
||||||
|
#include "app_settings.hpp"
|
||||||
#include "portapack.hpp"
|
#include "portapack.hpp"
|
||||||
|
|
||||||
namespace ui {
|
namespace ui {
|
||||||
@@ -50,11 +51,11 @@ public:
|
|||||||
private:
|
private:
|
||||||
Labels labels {
|
Labels labels {
|
||||||
{ { 8 * 8, 1 * 8 }, "Header:", Color::light_grey() },
|
{ { 8 * 8, 1 * 8 }, "Header:", Color::light_grey() },
|
||||||
{ { 4 * 8, 3 * 8 }, "Code ville:", Color::light_grey() },
|
{ { 4 * 8, 3 * 8 }, "City code:", Color::light_grey() },
|
||||||
{ { 7 * 8, 5 * 8 }, "Famille:", Color::light_grey() },
|
{ { 7 * 8, 5 * 8 }, "Family:", Color::light_grey() },
|
||||||
{ { 2 * 8, 7 * 8 + 2 }, "Sous-famille:", Color::light_grey() },
|
{ { 2 * 8, 7 * 8 + 2 }, "Subfamily:", Color::light_grey() },
|
||||||
{ { 2 * 8, 11 * 8 }, "ID recepteur:", Color::light_grey() },
|
{ { 2 * 8, 11 * 8 }, "Receiver ID:", Color::light_grey() },
|
||||||
{ { 2 * 8, 14 * 8 }, "Relais:", Color::light_grey() }
|
{ { 2 * 8, 14 * 8 }, "Relay:", Color::light_grey() }
|
||||||
};
|
};
|
||||||
|
|
||||||
NumberField field_header_a {
|
NumberField field_header_a {
|
||||||
@@ -98,8 +99,8 @@ private:
|
|||||||
|
|
||||||
Checkbox checkbox_wcsubfamily {
|
Checkbox checkbox_wcsubfamily {
|
||||||
{ 20 * 8, 6 * 8 + 6 },
|
{ 20 * 8, 6 * 8 + 6 },
|
||||||
6,
|
3,
|
||||||
"Toutes"
|
"All"
|
||||||
};
|
};
|
||||||
|
|
||||||
NumberField field_receiver {
|
NumberField field_receiver {
|
||||||
@@ -111,8 +112,8 @@ private:
|
|||||||
};
|
};
|
||||||
Checkbox checkbox_wcid {
|
Checkbox checkbox_wcid {
|
||||||
{ 20 * 8, 10 * 8 + 4 },
|
{ 20 * 8, 10 * 8 + 4 },
|
||||||
4,
|
3,
|
||||||
"Tous"
|
"All"
|
||||||
};
|
};
|
||||||
|
|
||||||
std::array<ImageOptionsField, 4> relay_states { };
|
std::array<ImageOptionsField, 4> relay_states { };
|
||||||
@@ -139,9 +140,9 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
Labels labels {
|
Labels labels {
|
||||||
{ { 4 * 8, 1 * 8 }, "Code ville:", Color::light_grey() },
|
{ { 4 * 8, 1 * 8 }, "City code:", Color::light_grey() },
|
||||||
{ { 8 * 8, 3 * 8 }, "Groupe:", Color::light_grey() },
|
{ { 8 * 8, 3 * 8 }, "Group:", Color::light_grey() },
|
||||||
{ { 8 * 8, 7 * 8 }, "Relais:", Color::light_grey() }
|
{ { 8 * 8, 7 * 8 }, "Relay:", Color::light_grey() }
|
||||||
};
|
};
|
||||||
|
|
||||||
NumberField field_city {
|
NumberField field_city {
|
||||||
@@ -178,9 +179,13 @@ public:
|
|||||||
|
|
||||||
void focus() override;
|
void focus() override;
|
||||||
|
|
||||||
std::string title() const override { return "BHT transmit"; };
|
std::string title() const override { return "BHT Xy/EP TX"; };
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
// app save settings
|
||||||
|
std::app_settings settings { };
|
||||||
|
std::app_settings::AppSettings app_settings { };
|
||||||
|
|
||||||
void on_tx_progress(const uint32_t progress, const bool done);
|
void on_tx_progress(const uint32_t progress, const bool done);
|
||||||
void start_tx();
|
void start_tx();
|
||||||
void stop_tx();
|
void stop_tx();
|
||||||
@@ -220,12 +225,12 @@ private:
|
|||||||
"Scan"
|
"Scan"
|
||||||
};
|
};
|
||||||
|
|
||||||
Checkbox checkbox_cligno {
|
Checkbox checkbox_flashing {
|
||||||
{ 16 * 8, 25 * 8 },
|
{ 16 * 8, 25 * 8 },
|
||||||
6,
|
8,
|
||||||
"Cligno"
|
"Flashing"
|
||||||
};
|
};
|
||||||
NumberField field_tempo {
|
NumberField field_speed {
|
||||||
{ 26 * 8, 25 * 8 + 4 },
|
{ 26 * 8, 25 * 8 + 4 },
|
||||||
2,
|
2,
|
||||||
{ 1, 99 },
|
{ 1, 99 },
|
||||||
|
@@ -60,6 +60,15 @@ BTLERxView::BTLERxView(NavigationView& nav) {
|
|||||||
&console
|
&console
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// load app settings
|
||||||
|
auto rc = settings.load("rx_btle", &app_settings);
|
||||||
|
if(rc == SETTINGS_OK) {
|
||||||
|
field_lna.set_value(app_settings.lna);
|
||||||
|
field_vga.set_value(app_settings.vga);
|
||||||
|
field_rf_amp.set_value(app_settings.rx_amp);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// DEBUG
|
// DEBUG
|
||||||
record_view.on_error = [&nav](std::string message) {
|
record_view.on_error = [&nav](std::string message) {
|
||||||
nav.display_modal("Error", message);
|
nav.display_modal("Error", message);
|
||||||
@@ -152,6 +161,11 @@ void BTLERxView::on_data(uint32_t value, bool is_data) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
BTLERxView::~BTLERxView() {
|
BTLERxView::~BTLERxView() {
|
||||||
|
|
||||||
|
// save app settings
|
||||||
|
app_settings.rx_frequency = field_frequency.value();
|
||||||
|
settings.save("rx_btle", &app_settings);
|
||||||
|
|
||||||
audio::output::stop();
|
audio::output::stop();
|
||||||
receiver_model.disable();
|
receiver_model.disable();
|
||||||
baseband::shutdown();
|
baseband::shutdown();
|
||||||
|
@@ -27,6 +27,7 @@
|
|||||||
#include "ui.hpp"
|
#include "ui.hpp"
|
||||||
#include "ui_navigation.hpp"
|
#include "ui_navigation.hpp"
|
||||||
#include "ui_receiver.hpp"
|
#include "ui_receiver.hpp"
|
||||||
|
#include "app_settings.hpp"
|
||||||
#include "ui_record_view.hpp" // DEBUG
|
#include "ui_record_view.hpp" // DEBUG
|
||||||
|
|
||||||
#include "utility.hpp"
|
#include "utility.hpp"
|
||||||
@@ -45,6 +46,11 @@ public:
|
|||||||
private:
|
private:
|
||||||
void on_data(uint32_t value, bool is_data);
|
void on_data(uint32_t value, bool is_data);
|
||||||
|
|
||||||
|
|
||||||
|
// app save settings
|
||||||
|
std::app_settings settings { };
|
||||||
|
std::app_settings::AppSettings app_settings { };
|
||||||
|
|
||||||
uint8_t console_color { 0 };
|
uint8_t console_color { 0 };
|
||||||
uint32_t prev_value { 0 };
|
uint32_t prev_value { 0 };
|
||||||
std::string str_log { "" };
|
std::string str_log { "" };
|
||||||
|
@@ -37,6 +37,10 @@ void CoasterPagerView::focus() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
CoasterPagerView::~CoasterPagerView() {
|
CoasterPagerView::~CoasterPagerView() {
|
||||||
|
// save app settings
|
||||||
|
app_settings.tx_frequency = transmitter_model.tuning_frequency();
|
||||||
|
settings.save("tx_coaster", &app_settings);
|
||||||
|
|
||||||
transmitter_model.disable();
|
transmitter_model.disable();
|
||||||
baseband::shutdown();
|
baseband::shutdown();
|
||||||
}
|
}
|
||||||
@@ -119,6 +123,15 @@ CoasterPagerView::CoasterPagerView(NavigationView& nav) {
|
|||||||
&tx_view
|
&tx_view
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// load app settings
|
||||||
|
auto rc = settings.load("tx_coaster", &app_settings);
|
||||||
|
if(rc == SETTINGS_OK) {
|
||||||
|
transmitter_model.set_rf_amp(app_settings.tx_amp);
|
||||||
|
transmitter_model.set_channel_bandwidth(app_settings.channel_bandwidth);
|
||||||
|
transmitter_model.set_tuning_frequency(app_settings.tx_frequency);
|
||||||
|
transmitter_model.set_tx_gain(app_settings.tx_gain);
|
||||||
|
}
|
||||||
|
|
||||||
// Bytes to nibbles
|
// Bytes to nibbles
|
||||||
for (c = 0; c < 16; c++)
|
for (c = 0; c < 16; c++)
|
||||||
sym_data.set_sym(c, (data_init[c >> 1] >> ((c & 1) ? 0 : 4)) & 0x0F);
|
sym_data.set_sym(c, (data_init[c >> 1] >> ((c & 1) ? 0 : 4)) & 0x0F);
|
||||||
|
@@ -28,6 +28,7 @@
|
|||||||
|
|
||||||
#include "message.hpp"
|
#include "message.hpp"
|
||||||
#include "transmitter_model.hpp"
|
#include "transmitter_model.hpp"
|
||||||
|
#include "app_settings.hpp"
|
||||||
#include "portapack.hpp"
|
#include "portapack.hpp"
|
||||||
|
|
||||||
namespace ui {
|
namespace ui {
|
||||||
@@ -39,7 +40,7 @@ public:
|
|||||||
|
|
||||||
void focus() override;
|
void focus() override;
|
||||||
|
|
||||||
std::string title() const override { return "Si44xx TX"; };
|
std::string title() const override { return "BurgerPgr TX"; };
|
||||||
|
|
||||||
private:
|
private:
|
||||||
enum tx_modes {
|
enum tx_modes {
|
||||||
@@ -50,6 +51,10 @@ private:
|
|||||||
|
|
||||||
tx_modes tx_mode = IDLE;
|
tx_modes tx_mode = IDLE;
|
||||||
|
|
||||||
|
// app save settings
|
||||||
|
std::app_settings settings { };
|
||||||
|
std::app_settings::AppSettings app_settings { };
|
||||||
|
|
||||||
void start_tx();
|
void start_tx();
|
||||||
void generate_frame();
|
void generate_frame();
|
||||||
void on_tx_progress(const uint32_t progress, const bool done);
|
void on_tx_progress(const uint32_t progress, const bool done);
|
||||||
|
@@ -31,6 +31,7 @@
|
|||||||
#include "ui_sd_card_debug.hpp"
|
#include "ui_sd_card_debug.hpp"
|
||||||
|
|
||||||
#include "portapack.hpp"
|
#include "portapack.hpp"
|
||||||
|
#include "portapack_persistent_memory.hpp"
|
||||||
using namespace portapack;
|
using namespace portapack;
|
||||||
|
|
||||||
#include "irq_controls.hpp"
|
#include "irq_controls.hpp"
|
||||||
@@ -345,14 +346,17 @@ DebugPeripheralsMenuView::DebugPeripheralsMenuView(NavigationView& nav) {
|
|||||||
/* DebugMenuView *********************************************************/
|
/* DebugMenuView *********************************************************/
|
||||||
|
|
||||||
DebugMenuView::DebugMenuView(NavigationView& nav) {
|
DebugMenuView::DebugMenuView(NavigationView& nav) {
|
||||||
|
if( portapack::persistent_memory::show_gui_return_icon() )
|
||||||
|
{
|
||||||
|
add_items( { { "..", ui::Color::light_grey(),&bitmap_icon_previous, [&nav](){ nav.pop(); } } } );
|
||||||
|
}
|
||||||
add_items({
|
add_items({
|
||||||
//{ "..", ui::Color::light_grey(),&bitmap_icon_previous, [&nav](){ nav.pop(); } },
|
|
||||||
{ "Memory", ui::Color::dark_cyan(), &bitmap_icon_memory, [&nav](){ nav.push<DebugMemoryView>(); } },
|
{ "Memory", ui::Color::dark_cyan(), &bitmap_icon_memory, [&nav](){ nav.push<DebugMemoryView>(); } },
|
||||||
//{ "Radio State", ui::Color::white(), nullptr, [&nav](){ nav.push<NotImplementedView>(); } },
|
//{ "Radio State", ui::Color::white(), nullptr, [&nav](){ nav.push<NotImplementedView>(); } },
|
||||||
{ "SD Card", ui::Color::dark_cyan(), &bitmap_icon_sdcard, [&nav](){ nav.push<SDCardDebugView>(); } },
|
{ "SD Card", ui::Color::dark_cyan(), &bitmap_icon_sdcard, [&nav](){ nav.push<SDCardDebugView>(); } },
|
||||||
{ "Peripherals", ui::Color::dark_cyan(), &bitmap_icon_peripherals, [&nav](){ nav.push<DebugPeripheralsMenuView>(); } },
|
{ "Peripherals", ui::Color::dark_cyan(), &bitmap_icon_peripherals, [&nav](){ nav.push<DebugPeripheralsMenuView>(); } },
|
||||||
{ "Temperature", ui::Color::dark_cyan(), &bitmap_icon_temperature, [&nav](){ nav.push<TemperatureView>(); } },
|
{ "Temperature", ui::Color::dark_cyan(), &bitmap_icon_temperature, [&nav](){ nav.push<TemperatureView>(); } },
|
||||||
{ "Buttons test", ui::Color::dark_cyan(), &bitmap_icon_controls, [&nav](){ nav.push<DebugControlsView>(); } },
|
{ "Buttons Test", ui::Color::dark_cyan(), &bitmap_icon_controls, [&nav](){ nav.push<DebugControlsView>(); } },
|
||||||
});
|
});
|
||||||
set_max_rows(2); // allow wider buttons
|
set_max_rows(2); // allow wider buttons
|
||||||
}
|
}
|
||||||
|
@@ -43,6 +43,8 @@ public:
|
|||||||
|
|
||||||
void focus() override;
|
void focus() override;
|
||||||
|
|
||||||
|
std::string title() const override { return "Memory"; };
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Text text_title {
|
Text text_title {
|
||||||
{ 96, 96, 48, 16 },
|
{ 96, 96, 48, 16 },
|
||||||
@@ -113,6 +115,8 @@ public:
|
|||||||
|
|
||||||
void focus() override;
|
void focus() override;
|
||||||
|
|
||||||
|
std::string title() const override { return "Temperature"; };
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Text text_title {
|
Text text_title {
|
||||||
{ 76, 16, 240, 16 },
|
{ 76, 16, 240, 16 },
|
||||||
@@ -252,6 +256,8 @@ public:
|
|||||||
|
|
||||||
void focus() override;
|
void focus() override;
|
||||||
|
|
||||||
|
std::string title() const override { return "Buttons Test"; };
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Text text_title {
|
Text text_title {
|
||||||
{ 64, 16, 184, 16 },
|
{ 64, 16, 184, 16 },
|
||||||
|
@@ -203,6 +203,10 @@ void EncodersView::focus() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
EncodersView::~EncodersView() {
|
EncodersView::~EncodersView() {
|
||||||
|
// save app settings
|
||||||
|
app_settings.tx_frequency = transmitter_model.tuning_frequency();
|
||||||
|
settings.save("tx_ook", &app_settings);
|
||||||
|
|
||||||
transmitter_model.disable();
|
transmitter_model.disable();
|
||||||
baseband::shutdown();
|
baseband::shutdown();
|
||||||
}
|
}
|
||||||
@@ -335,6 +339,15 @@ EncodersView::EncodersView(
|
|||||||
&tx_view
|
&tx_view
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// load app settings
|
||||||
|
auto rc = settings.load("tx_ook", &app_settings);
|
||||||
|
if(rc == SETTINGS_OK) {
|
||||||
|
transmitter_model.set_rf_amp(app_settings.tx_amp);
|
||||||
|
transmitter_model.set_channel_bandwidth(app_settings.channel_bandwidth);
|
||||||
|
transmitter_model.set_tuning_frequency(app_settings.tx_frequency);
|
||||||
|
transmitter_model.set_tx_gain(app_settings.tx_gain);
|
||||||
|
}
|
||||||
|
|
||||||
tx_view.on_edit_frequency = [this, &nav]() {
|
tx_view.on_edit_frequency = [this, &nav]() {
|
||||||
auto new_view = nav.push<FrequencyKeypadView>(transmitter_model.tuning_frequency());
|
auto new_view = nav.push<FrequencyKeypadView>(transmitter_model.tuning_frequency());
|
||||||
new_view->on_changed = [this](rf::Frequency f) {
|
new_view->on_changed = [this](rf::Frequency f) {
|
||||||
|
@@ -26,6 +26,7 @@
|
|||||||
#include "transmitter_model.hpp"
|
#include "transmitter_model.hpp"
|
||||||
#include "encoders.hpp"
|
#include "encoders.hpp"
|
||||||
#include "de_bruijn.hpp"
|
#include "de_bruijn.hpp"
|
||||||
|
#include "app_settings.hpp"
|
||||||
|
|
||||||
using namespace encoders;
|
using namespace encoders;
|
||||||
|
|
||||||
@@ -158,7 +159,7 @@ public:
|
|||||||
|
|
||||||
void focus() override;
|
void focus() override;
|
||||||
|
|
||||||
std::string title() const override { return "OOK transmit"; };
|
std::string title() const override { return "OOK TX"; };
|
||||||
|
|
||||||
private:
|
private:
|
||||||
NavigationView& nav_;
|
NavigationView& nav_;
|
||||||
@@ -169,6 +170,10 @@ private:
|
|||||||
SCAN
|
SCAN
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// app save settings
|
||||||
|
std::app_settings settings { };
|
||||||
|
std::app_settings::AppSettings app_settings { };
|
||||||
|
|
||||||
tx_modes tx_mode = IDLE;
|
tx_modes tx_mode = IDLE;
|
||||||
uint8_t repeat_index { 0 };
|
uint8_t repeat_index { 0 };
|
||||||
uint8_t repeat_min { 0 };
|
uint8_t repeat_min { 0 };
|
||||||
|
@@ -106,7 +106,7 @@ public:
|
|||||||
|
|
||||||
void focus() override;
|
void focus() override;
|
||||||
|
|
||||||
std::string title() const override { return "Jammer"; };
|
std::string title() const override { return "Jammer TX"; };
|
||||||
|
|
||||||
private:
|
private:
|
||||||
NavigationView& nav_;
|
NavigationView& nav_;
|
||||||
|
@@ -136,6 +136,9 @@ void KeyfobView::focus() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
KeyfobView::~KeyfobView() {
|
KeyfobView::~KeyfobView() {
|
||||||
|
// save app settings
|
||||||
|
settings.save("tx_keyfob", &app_settings);
|
||||||
|
|
||||||
transmitter_model.disable();
|
transmitter_model.disable();
|
||||||
baseband::shutdown();
|
baseband::shutdown();
|
||||||
}
|
}
|
||||||
@@ -214,6 +217,13 @@ KeyfobView::KeyfobView(
|
|||||||
&tx_view
|
&tx_view
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// load app settings
|
||||||
|
auto rc = settings.load("tx_keyfob", &app_settings);
|
||||||
|
if(rc == SETTINGS_OK) {
|
||||||
|
transmitter_model.set_rf_amp(app_settings.tx_amp);
|
||||||
|
transmitter_model.set_tx_gain(app_settings.tx_gain);
|
||||||
|
}
|
||||||
|
|
||||||
frame[0] = 0x55;
|
frame[0] = 0x55;
|
||||||
update_symfields();
|
update_symfields();
|
||||||
|
|
||||||
|
@@ -23,6 +23,7 @@
|
|||||||
#include "ui.hpp"
|
#include "ui.hpp"
|
||||||
#include "ui_transmitter.hpp"
|
#include "ui_transmitter.hpp"
|
||||||
#include "transmitter_model.hpp"
|
#include "transmitter_model.hpp"
|
||||||
|
#include "app_settings.hpp"
|
||||||
#include "encoders.hpp"
|
#include "encoders.hpp"
|
||||||
|
|
||||||
using namespace encoders;
|
using namespace encoders;
|
||||||
@@ -36,11 +37,15 @@ public:
|
|||||||
|
|
||||||
void focus() override;
|
void focus() override;
|
||||||
|
|
||||||
std::string title() const override { return "Keyfob (BETA)"; };
|
std::string title() const override { return "Key fob TX"; };
|
||||||
|
|
||||||
private:
|
private:
|
||||||
NavigationView& nav_;
|
NavigationView& nav_;
|
||||||
|
|
||||||
|
// app save settings
|
||||||
|
std::app_settings settings { };
|
||||||
|
std::app_settings::AppSettings app_settings { };
|
||||||
|
|
||||||
// 1013210ns / bit
|
// 1013210ns / bit
|
||||||
static constexpr uint32_t subaru_samples_per_bit = (OOK_SAMPLERATE * 0.00101321);
|
static constexpr uint32_t subaru_samples_per_bit = (OOK_SAMPLERATE * 0.00101321);
|
||||||
static constexpr uint32_t repeats = 4;
|
static constexpr uint32_t repeats = 4;
|
||||||
|
@@ -39,6 +39,10 @@ void LCRView::focus() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
LCRView::~LCRView() {
|
LCRView::~LCRView() {
|
||||||
|
// save app settings
|
||||||
|
app_settings.tx_frequency = transmitter_model.tuning_frequency();
|
||||||
|
settings.save("tx_lcr", &app_settings);
|
||||||
|
|
||||||
transmitter_model.disable();
|
transmitter_model.disable();
|
||||||
baseband::shutdown();
|
baseband::shutdown();
|
||||||
}
|
}
|
||||||
@@ -173,6 +177,15 @@ LCRView::LCRView(NavigationView& nav) {
|
|||||||
&tx_view
|
&tx_view
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// load app settings
|
||||||
|
auto rc = settings.load("tx_lcr", &app_settings);
|
||||||
|
if(rc == SETTINGS_OK) {
|
||||||
|
transmitter_model.set_rf_amp(app_settings.tx_amp);
|
||||||
|
transmitter_model.set_channel_bandwidth(app_settings.channel_bandwidth);
|
||||||
|
transmitter_model.set_tuning_frequency(app_settings.tx_frequency);
|
||||||
|
transmitter_model.set_tx_gain(app_settings.tx_gain);
|
||||||
|
}
|
||||||
|
|
||||||
options_scanlist.set_selected_index(0);
|
options_scanlist.set_selected_index(0);
|
||||||
|
|
||||||
const auto button_set_am_fn = [this, &nav](Button& button) {
|
const auto button_set_am_fn = [this, &nav](Button& button) {
|
||||||
|
@@ -27,6 +27,7 @@
|
|||||||
|
|
||||||
#include "message.hpp"
|
#include "message.hpp"
|
||||||
#include "transmitter_model.hpp"
|
#include "transmitter_model.hpp"
|
||||||
|
#include "app_settings.hpp"
|
||||||
|
|
||||||
namespace ui {
|
namespace ui {
|
||||||
|
|
||||||
@@ -39,7 +40,7 @@ public:
|
|||||||
|
|
||||||
void focus() override;
|
void focus() override;
|
||||||
|
|
||||||
std::string title() const override { return "LCR transmit"; };
|
std::string title() const override { return "TEDI/LCR TX"; };
|
||||||
|
|
||||||
private:
|
private:
|
||||||
struct scan_list_t {
|
struct scan_list_t {
|
||||||
@@ -81,6 +82,10 @@ private:
|
|||||||
SCAN
|
SCAN
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// app save settings
|
||||||
|
std::app_settings settings { };
|
||||||
|
std::app_settings::AppSettings app_settings { };
|
||||||
|
|
||||||
tx_modes tx_mode = IDLE;
|
tx_modes tx_mode = IDLE;
|
||||||
uint8_t scan_count { 0 }, scan_index { 0 };
|
uint8_t scan_count { 0 }, scan_index { 0 };
|
||||||
uint32_t scan_progress { 0 };
|
uint32_t scan_progress { 0 };
|
||||||
|
@@ -186,7 +186,7 @@ void MicTXView::rxaudio(bool is_on) {
|
|||||||
|
|
||||||
baseband::run_image(portapack::spi_flash::image_tag_mic_tx);
|
baseband::run_image(portapack::spi_flash::image_tag_mic_tx);
|
||||||
audio::output::stop();
|
audio::output::stop();
|
||||||
audio::input::start(ak4951_alc_GUI_selected); // set up audio input = mic config of any audio coded AK4951/WM8731, (in WM8731 parameter will be ignored)
|
audio::input::start(); // set up audio input = mic config of any audio coded AK4951/WM8731, (in WM8731 parameter will be ignored)
|
||||||
portapack::pin_i2s0_rx_sda.mode(3);
|
portapack::pin_i2s0_rx_sda.mode(3);
|
||||||
configure_baseband();
|
configure_baseband();
|
||||||
}
|
}
|
||||||
@@ -212,7 +212,7 @@ MicTXView::MicTXView(
|
|||||||
baseband::run_image(portapack::spi_flash::image_tag_mic_tx);
|
baseband::run_image(portapack::spi_flash::image_tag_mic_tx);
|
||||||
|
|
||||||
|
|
||||||
if ( audio_codec_wm8731.detected() ) {
|
if (true ) { // Temporary , disabling ALC feature , (pending to solve -No Audio in Mic app ,in some H2/H2+ WM /QFP100 CPLS users- if ( audio_codec_wm8731.detected() ) {
|
||||||
add_children({
|
add_children({
|
||||||
&labels_WM8731, // we have audio codec WM8731, same MIC menu as original.
|
&labels_WM8731, // we have audio codec WM8731, same MIC menu as original.
|
||||||
&vumeter,
|
&vumeter,
|
||||||
@@ -285,7 +285,7 @@ MicTXView::MicTXView(
|
|||||||
|
|
||||||
options_ak4951_alc_mode.on_change = [this](size_t, int8_t v) {
|
options_ak4951_alc_mode.on_change = [this](size_t, int8_t v) {
|
||||||
ak4951_alc_GUI_selected = v;
|
ak4951_alc_GUI_selected = v;
|
||||||
audio::input::start(ak4951_alc_GUI_selected);
|
audio::input::start();
|
||||||
};
|
};
|
||||||
// options_ak4951_alc_mode.set_selected_index(0);
|
// options_ak4951_alc_mode.set_selected_index(0);
|
||||||
|
|
||||||
@@ -341,23 +341,37 @@ MicTXView::MicTXView(
|
|||||||
enable_dsb = false;
|
enable_dsb = false;
|
||||||
field_bw.set_value(transmitter_model.channel_bandwidth() / 1000);
|
field_bw.set_value(transmitter_model.channel_bandwidth() / 1000);
|
||||||
//if (rx_enabled)
|
//if (rx_enabled)
|
||||||
rxaudio(rx_enabled); //Update now if we have RX audio on
|
rxaudio(rx_enabled); //Update now if we have RX audio on
|
||||||
|
options_tone_key.hidden(0); // we are in FM mode , we should have active the Key-tones & CTCSS option.
|
||||||
|
field_rxbw.hidden(0); // we are in FM mode, we need to allow the user set up of the RX NFM BW selection (8K5, 11K, 16K)
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
enable_am = true;
|
enable_am = true;
|
||||||
rxaudio(rx_enabled); //Update now if we have RX audio on
|
rxaudio(rx_enabled); //Update now if we have RX audio on
|
||||||
|
options_tone_key.set_selected_index(0); // we are NOT in FM mode , we reset the possible previous key-tones &CTCSS selection.
|
||||||
|
set_dirty(); // Refresh display
|
||||||
|
options_tone_key.hidden(1); // we hide that Key-tones & CTCSS input selecction, (no meaning in AM/DSB/SSB).
|
||||||
|
field_rxbw.hidden(1); // we hide the NFM BW selection in other modes non_FM (no meaning in AM/DSB/SSB)
|
||||||
|
check_rogerbeep.hidden(0); // make visible again the "rogerbeep" selection.
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
enable_usb = true;
|
enable_usb = true;
|
||||||
rxaudio(rx_enabled); //Update now if we have RX audio on
|
rxaudio(rx_enabled); //Update now if we have RX audio on
|
||||||
|
check_rogerbeep.set_value(false); // reset the possible activation of roger beep, because it is not compatible with SSB , by now.
|
||||||
|
check_rogerbeep.hidden(1); // hide that roger beep selection.
|
||||||
|
set_dirty(); // Refresh display
|
||||||
break;
|
break;
|
||||||
case 3:
|
case 3:
|
||||||
enable_lsb = true;
|
enable_lsb = true;
|
||||||
rxaudio(rx_enabled); //Update now if we have RX audio on
|
rxaudio(rx_enabled); //Update now if we have RX audio on
|
||||||
|
check_rogerbeep.set_value(false); // reset the possible activation of roger beep, because it is not compatible with SSB , by now.
|
||||||
|
check_rogerbeep.hidden(1); // hide that roger beep selection.
|
||||||
|
set_dirty(); // Refresh display
|
||||||
break;
|
break;
|
||||||
case 4:
|
case 4:
|
||||||
enable_dsb = true;
|
enable_dsb = true;
|
||||||
rxaudio(rx_enabled); //Update now if we have RX audio on
|
rxaudio(rx_enabled); //Update now if we have RX audio on
|
||||||
|
check_rogerbeep.hidden(0); // make visible again the "rogerbeep" selection.
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
//configure_baseband();
|
//configure_baseband();
|
||||||
@@ -525,7 +539,7 @@ MicTXView::MicTXView(
|
|||||||
set_tx(false);
|
set_tx(false);
|
||||||
|
|
||||||
audio::set_rate(audio::Rate::Hz_24000);
|
audio::set_rate(audio::Rate::Hz_24000);
|
||||||
audio::input::start(ak4951_alc_GUI_selected); // originally , audio::input::start(); (we added parameter)
|
audio::input::start(); // originally , audio::input::start(); (we added parameter)
|
||||||
}
|
}
|
||||||
|
|
||||||
MicTXView::~MicTXView() {
|
MicTXView::~MicTXView() {
|
||||||
|
@@ -58,7 +58,7 @@ public:
|
|||||||
};
|
};
|
||||||
*/
|
*/
|
||||||
|
|
||||||
std::string title() const override { return "Mic TX RX"; };
|
std::string title() const override { return "Microphone"; };
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static constexpr uint32_t sampling_rate = 1536000U;
|
static constexpr uint32_t sampling_rate = 1536000U;
|
||||||
|
@@ -97,6 +97,10 @@ void MorseView::focus() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
MorseView::~MorseView() {
|
MorseView::~MorseView() {
|
||||||
|
// save app settings
|
||||||
|
app_settings.tx_frequency = transmitter_model.tuning_frequency();
|
||||||
|
settings.save("tx_morse", &app_settings);
|
||||||
|
|
||||||
transmitter_model.disable();
|
transmitter_model.disable();
|
||||||
baseband::shutdown();
|
baseband::shutdown();
|
||||||
}
|
}
|
||||||
@@ -203,6 +207,15 @@ MorseView::MorseView(
|
|||||||
&tx_view
|
&tx_view
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// load app settings
|
||||||
|
auto rc = settings.load("tx_morse", &app_settings);
|
||||||
|
if(rc == SETTINGS_OK) {
|
||||||
|
transmitter_model.set_rf_amp(app_settings.tx_amp);
|
||||||
|
transmitter_model.set_channel_bandwidth(app_settings.channel_bandwidth);
|
||||||
|
transmitter_model.set_tuning_frequency(app_settings.tx_frequency);
|
||||||
|
transmitter_model.set_tx_gain(app_settings.tx_gain);
|
||||||
|
}
|
||||||
|
|
||||||
// Default settings
|
// Default settings
|
||||||
field_speed.set_value(15); // 15wps
|
field_speed.set_value(15); // 15wps
|
||||||
field_tone.set_value(700); // 700Hz FM tone
|
field_tone.set_value(700); // 700Hz FM tone
|
||||||
|
@@ -27,7 +27,7 @@
|
|||||||
#include "ui_widget.hpp"
|
#include "ui_widget.hpp"
|
||||||
#include "ui_navigation.hpp"
|
#include "ui_navigation.hpp"
|
||||||
#include "ui_transmitter.hpp"
|
#include "ui_transmitter.hpp"
|
||||||
|
#include "app_settings.hpp"
|
||||||
#include "portapack.hpp"
|
#include "portapack.hpp"
|
||||||
#include "message.hpp"
|
#include "message.hpp"
|
||||||
#include "volume.hpp"
|
#include "volume.hpp"
|
||||||
@@ -67,6 +67,10 @@ private:
|
|||||||
std::string message { };
|
std::string message { };
|
||||||
uint32_t time_units { 0 };
|
uint32_t time_units { 0 };
|
||||||
|
|
||||||
|
// app save settings
|
||||||
|
std::app_settings settings { };
|
||||||
|
std::app_settings::AppSettings app_settings { };
|
||||||
|
|
||||||
enum modulation_t {
|
enum modulation_t {
|
||||||
CW = 0,
|
CW = 0,
|
||||||
FM = 1
|
FM = 1
|
||||||
|
@@ -60,6 +60,14 @@ NRFRxView::NRFRxView(NavigationView& nav) {
|
|||||||
&console
|
&console
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// load app settings
|
||||||
|
auto rc = settings.load("rx_nrf", &app_settings);
|
||||||
|
if(rc == SETTINGS_OK) {
|
||||||
|
field_lna.set_value(app_settings.lna);
|
||||||
|
field_vga.set_value(app_settings.vga);
|
||||||
|
field_rf_amp.set_value(app_settings.rx_amp);
|
||||||
|
}
|
||||||
|
|
||||||
// DEBUG
|
// DEBUG
|
||||||
record_view.on_error = [&nav](std::string message) {
|
record_view.on_error = [&nav](std::string message) {
|
||||||
nav.display_modal("Error", message);
|
nav.display_modal("Error", message);
|
||||||
@@ -157,6 +165,11 @@ void NRFRxView::on_data(uint32_t value, bool is_data) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
NRFRxView::~NRFRxView() {
|
NRFRxView::~NRFRxView() {
|
||||||
|
|
||||||
|
// save app settings
|
||||||
|
app_settings.rx_frequency = field_frequency.value();
|
||||||
|
settings.save("rx_nrf", &app_settings);
|
||||||
|
|
||||||
audio::output::stop();
|
audio::output::stop();
|
||||||
receiver_model.disable();
|
receiver_model.disable();
|
||||||
baseband::shutdown();
|
baseband::shutdown();
|
||||||
|
@@ -27,6 +27,7 @@
|
|||||||
#include "ui.hpp"
|
#include "ui.hpp"
|
||||||
#include "ui_navigation.hpp"
|
#include "ui_navigation.hpp"
|
||||||
#include "ui_receiver.hpp"
|
#include "ui_receiver.hpp"
|
||||||
|
#include "app_settings.hpp"
|
||||||
#include "ui_record_view.hpp" // DEBUG
|
#include "ui_record_view.hpp" // DEBUG
|
||||||
|
|
||||||
#include "utility.hpp"
|
#include "utility.hpp"
|
||||||
@@ -45,6 +46,10 @@ public:
|
|||||||
private:
|
private:
|
||||||
void on_data(uint32_t value, bool is_data);
|
void on_data(uint32_t value, bool is_data);
|
||||||
|
|
||||||
|
// app save settings
|
||||||
|
std::app_settings settings { };
|
||||||
|
std::app_settings::AppSettings app_settings { };
|
||||||
|
|
||||||
uint8_t console_color { 0 };
|
uint8_t console_color { 0 };
|
||||||
uint32_t prev_value { 0 };
|
uint32_t prev_value { 0 };
|
||||||
std::string str_log { "" };
|
std::string str_log { "" };
|
||||||
|
@@ -38,6 +38,10 @@ void POCSAGTXView::focus() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
POCSAGTXView::~POCSAGTXView() {
|
POCSAGTXView::~POCSAGTXView() {
|
||||||
|
// save app settings
|
||||||
|
app_settings.tx_frequency = transmitter_model.tuning_frequency();
|
||||||
|
settings.save("tx_pocsag", &app_settings);
|
||||||
|
|
||||||
transmitter_model.disable();
|
transmitter_model.disable();
|
||||||
baseband::shutdown();
|
baseband::shutdown();
|
||||||
}
|
}
|
||||||
@@ -141,6 +145,15 @@ POCSAGTXView::POCSAGTXView(
|
|||||||
&tx_view
|
&tx_view
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// load app settings
|
||||||
|
auto rc = settings.load("tx_pocsag", &app_settings);
|
||||||
|
if(rc == SETTINGS_OK) {
|
||||||
|
transmitter_model.set_rf_amp(app_settings.tx_amp);
|
||||||
|
transmitter_model.set_channel_bandwidth(app_settings.channel_bandwidth);
|
||||||
|
transmitter_model.set_tuning_frequency(app_settings.tx_frequency);
|
||||||
|
transmitter_model.set_tx_gain(app_settings.tx_gain);
|
||||||
|
}
|
||||||
|
|
||||||
options_bitrate.set_selected_index(1); // 1200bps
|
options_bitrate.set_selected_index(1); // 1200bps
|
||||||
options_type.set_selected_index(0); // Address only
|
options_type.set_selected_index(0); // Address only
|
||||||
|
|
||||||
|
@@ -31,6 +31,7 @@
|
|||||||
#include "bch_code.hpp"
|
#include "bch_code.hpp"
|
||||||
#include "message.hpp"
|
#include "message.hpp"
|
||||||
#include "transmitter_model.hpp"
|
#include "transmitter_model.hpp"
|
||||||
|
#include "app_settings.hpp"
|
||||||
#include "pocsag.hpp"
|
#include "pocsag.hpp"
|
||||||
|
|
||||||
using namespace pocsag;
|
using namespace pocsag;
|
||||||
@@ -62,6 +63,10 @@ private:
|
|||||||
5, 31, 21, 2
|
5, 31, 21, 2
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// app save settings
|
||||||
|
std::app_settings settings { };
|
||||||
|
std::app_settings::AppSettings app_settings { };
|
||||||
|
|
||||||
void on_set_text(NavigationView& nav);
|
void on_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);
|
||||||
bool start_tx();
|
bool start_tx();
|
||||||
|
@@ -175,6 +175,10 @@ void RDSView::focus() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
RDSView::~RDSView() {
|
RDSView::~RDSView() {
|
||||||
|
// save app settings
|
||||||
|
app_settings.tx_frequency = transmitter_model.tuning_frequency();
|
||||||
|
settings.save("tx_rds", &app_settings);
|
||||||
|
|
||||||
transmitter_model.disable();
|
transmitter_model.disable();
|
||||||
baseband::shutdown();
|
baseband::shutdown();
|
||||||
}
|
}
|
||||||
@@ -226,11 +230,17 @@ RDSView::RDSView(
|
|||||||
&view_radiotext,
|
&view_radiotext,
|
||||||
&view_datetime,
|
&view_datetime,
|
||||||
&view_audio,
|
&view_audio,
|
||||||
//&options_countrycode,
|
|
||||||
//&options_coverage,
|
|
||||||
&tx_view,
|
&tx_view,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// load app settings
|
||||||
|
auto rc = settings.load("tx_rds", &app_settings);
|
||||||
|
if(rc == SETTINGS_OK) {
|
||||||
|
transmitter_model.set_rf_amp(app_settings.tx_amp);
|
||||||
|
transmitter_model.set_channel_bandwidth(app_settings.channel_bandwidth);
|
||||||
|
transmitter_model.set_tuning_frequency(app_settings.tx_frequency);
|
||||||
|
transmitter_model.set_tx_gain(app_settings.tx_gain);
|
||||||
|
}
|
||||||
check_TP.set_value(true);
|
check_TP.set_value(true);
|
||||||
|
|
||||||
sym_pi_code.set_sym(0, 0xF);
|
sym_pi_code.set_sym(0, 0xF);
|
||||||
@@ -242,8 +252,6 @@ RDSView::RDSView(
|
|||||||
};
|
};
|
||||||
|
|
||||||
options_pty.set_selected_index(0); // None
|
options_pty.set_selected_index(0); // None
|
||||||
//options_countrycode.set_selected_index(18); // Baguette du fromage
|
|
||||||
//options_coverage.set_selected_index(0); // Local
|
|
||||||
|
|
||||||
tx_view.on_edit_frequency = [this, &nav]() {
|
tx_view.on_edit_frequency = [this, &nav]() {
|
||||||
auto new_view = nav.push<FrequencyKeypadView>(receiver_model.tuning_frequency());
|
auto new_view = nav.push<FrequencyKeypadView>(receiver_model.tuning_frequency());
|
||||||
|
@@ -24,7 +24,7 @@
|
|||||||
#include "ui_transmitter.hpp"
|
#include "ui_transmitter.hpp"
|
||||||
#include "ui_textentry.hpp"
|
#include "ui_textentry.hpp"
|
||||||
#include "ui_tabview.hpp"
|
#include "ui_tabview.hpp"
|
||||||
|
#include "app_settings.hpp"
|
||||||
#include "rds.hpp"
|
#include "rds.hpp"
|
||||||
|
|
||||||
using namespace rds;
|
using namespace rds;
|
||||||
@@ -144,12 +144,17 @@ public:
|
|||||||
|
|
||||||
void focus() override;
|
void focus() override;
|
||||||
|
|
||||||
std::string title() const override { return "RDS transmit"; };
|
std::string title() const override { return "RDS TX"; };
|
||||||
|
|
||||||
private:
|
private:
|
||||||
NavigationView& nav_;
|
NavigationView& nav_;
|
||||||
RDS_flags rds_flags { };
|
RDS_flags rds_flags { };
|
||||||
|
|
||||||
|
// app save settings
|
||||||
|
std::app_settings settings { };
|
||||||
|
std::app_settings::AppSettings app_settings { };
|
||||||
|
|
||||||
|
|
||||||
std::vector<RDSGroup> frame_psn { };
|
std::vector<RDSGroup> frame_psn { };
|
||||||
std::vector<RDSGroup> frame_radiotext { };
|
std::vector<RDSGroup> frame_radiotext { };
|
||||||
std::vector<RDSGroup> frame_datetime { };
|
std::vector<RDSGroup> frame_datetime { };
|
||||||
|
@@ -484,6 +484,7 @@ void ScannerView::scan_pause() {
|
|||||||
scan_thread->set_freq_lock(0); //Reset the scanner lock (because user paused, or MAX_FREQ_LOCK reached) for next freq scan
|
scan_thread->set_freq_lock(0); //Reset the scanner lock (because user paused, or MAX_FREQ_LOCK reached) for next freq scan
|
||||||
scan_thread->set_scanning(false); // WE STOP SCANNING
|
scan_thread->set_scanning(false); // WE STOP SCANNING
|
||||||
audio::output::start();
|
audio::output::start();
|
||||||
|
on_headphone_volume_changed(field_volume.value()); // quick fix to make sure WM8731S chips don't stay silent after pause
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -111,7 +111,7 @@ public:
|
|||||||
.foreground = Color::red(),
|
.foreground = Color::red(),
|
||||||
};
|
};
|
||||||
|
|
||||||
std::string title() const override { return "SCANNER"; };
|
std::string title() const override { return "Scanner"; };
|
||||||
std::vector<rf::Frequency> frequency_list{ };
|
std::vector<rf::Frequency> frequency_list{ };
|
||||||
std::vector<string> description_list { };
|
std::vector<string> description_list { };
|
||||||
|
|
||||||
|
@@ -38,7 +38,7 @@ public:
|
|||||||
~WipeSDView();
|
~WipeSDView();
|
||||||
void focus() override;
|
void focus() override;
|
||||||
|
|
||||||
std::string title() const override { return "Wipe FAT"; };
|
std::string title() const override { return "Wipe SD Card"; };
|
||||||
|
|
||||||
private:
|
private:
|
||||||
NavigationView& nav_;
|
NavigationView& nav_;
|
||||||
|
@@ -43,7 +43,7 @@ namespace ui {
|
|||||||
SetDateTimeView::SetDateTimeView(
|
SetDateTimeView::SetDateTimeView(
|
||||||
NavigationView& nav
|
NavigationView& nav
|
||||||
) {
|
) {
|
||||||
button_done.on_select = [&nav, this](Button&){
|
button_save.on_select = [&nav, this](Button&){
|
||||||
const auto model = this->form_collect();
|
const auto model = this->form_collect();
|
||||||
const rtc::RTC new_datetime {
|
const rtc::RTC new_datetime {
|
||||||
model.year, model.month, model.day,
|
model.year, model.month, model.day,
|
||||||
@@ -65,7 +65,7 @@ SetDateTimeView::SetDateTimeView(
|
|||||||
&field_hour,
|
&field_hour,
|
||||||
&field_minute,
|
&field_minute,
|
||||||
&field_second,
|
&field_second,
|
||||||
&button_done,
|
&button_save,
|
||||||
&button_cancel,
|
&button_cancel,
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -150,7 +150,7 @@ SetRadioView::SetRadioView(
|
|||||||
&value_freq_step,
|
&value_freq_step,
|
||||||
&labels_bias,
|
&labels_bias,
|
||||||
&check_bias,
|
&check_bias,
|
||||||
&button_done,
|
&button_save,
|
||||||
&button_cancel
|
&button_cancel
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -200,7 +200,7 @@ SetRadioView::SetRadioView(
|
|||||||
EventDispatcher::send_message(message);
|
EventDispatcher::send_message(message);
|
||||||
};
|
};
|
||||||
|
|
||||||
button_done.on_select = [this, &nav](Button&){
|
button_save.on_select = [this, &nav](Button&){
|
||||||
const auto model = this->form_collect();
|
const auto model = this->form_collect();
|
||||||
portapack::persistent_memory::set_correction_ppb(model.ppm * 1000);
|
portapack::persistent_memory::set_correction_ppb(model.ppm * 1000);
|
||||||
portapack::persistent_memory::set_clkout_freq(model.freq);
|
portapack::persistent_memory::set_clkout_freq(model.freq);
|
||||||
@@ -210,7 +210,7 @@ SetRadioView::SetRadioView(
|
|||||||
}
|
}
|
||||||
|
|
||||||
void SetRadioView::focus() {
|
void SetRadioView::focus() {
|
||||||
button_done.focus();
|
button_save.focus();
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetRadioView::form_init(const SetFrequencyCorrectionModel& model) {
|
void SetRadioView::form_init(const SetFrequencyCorrectionModel& model) {
|
||||||
@@ -224,76 +224,26 @@ SetFrequencyCorrectionModel SetRadioView::form_collect() {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
SetPlayDeadView::SetPlayDeadView(NavigationView& nav) {
|
|
||||||
add_children({
|
|
||||||
&text_sequence,
|
|
||||||
&button_enter,
|
|
||||||
&button_cancel
|
|
||||||
});
|
|
||||||
|
|
||||||
button_enter.on_select = [this, &nav](Button&){
|
|
||||||
if (!entermode) {
|
|
||||||
sequence = 0;
|
|
||||||
keycount = 0;
|
|
||||||
memset(sequence_txt, '-', 10);
|
|
||||||
text_sequence.set(sequence_txt);
|
|
||||||
entermode = true;
|
|
||||||
button_cancel.hidden(true);
|
|
||||||
set_dirty();
|
|
||||||
} else {
|
|
||||||
if (sequence == 0x8D1) // U D L R
|
|
||||||
nav.display_modal("Warning", "Default sequence entered !", ABORT, nullptr);
|
|
||||||
else {
|
|
||||||
persistent_memory::set_playdead_sequence(sequence);
|
|
||||||
nav.pop();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
button_enter.on_dir = [this](Button&, KeyEvent key){
|
|
||||||
if ((entermode == true) && (keycount < 10)) {
|
|
||||||
key_code = static_cast<std::underlying_type<KeyEvent>::type>(key);
|
|
||||||
if (key_code == 0)
|
|
||||||
sequence_txt[keycount] = 'R';
|
|
||||||
else if (key_code == 1)
|
|
||||||
sequence_txt[keycount] = 'L';
|
|
||||||
else if (key_code == 2)
|
|
||||||
sequence_txt[keycount] = 'D';
|
|
||||||
else if (key_code == 3)
|
|
||||||
sequence_txt[keycount] = 'U';
|
|
||||||
text_sequence.set(sequence_txt);
|
|
||||||
sequence = (sequence << 3) | (key_code + 1);
|
|
||||||
keycount++;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
};
|
|
||||||
|
|
||||||
button_cancel.on_select = [&nav](Button&){ nav.pop(); };
|
|
||||||
}
|
|
||||||
|
|
||||||
void SetPlayDeadView::focus() {
|
|
||||||
button_cancel.focus();
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
SetUIView::SetUIView(NavigationView& nav) {
|
SetUIView::SetUIView(NavigationView& nav) {
|
||||||
add_children({
|
add_children({
|
||||||
//&checkbox_login,
|
&checkbox_disable_touchscreen,
|
||||||
&checkbox_speaker,
|
&checkbox_speaker,
|
||||||
&checkbox_bloff,
|
&checkbox_bloff,
|
||||||
&options_bloff,
|
&options_bloff,
|
||||||
&checkbox_showsplash,
|
&checkbox_showsplash,
|
||||||
&checkbox_showclock,
|
&checkbox_showclock,
|
||||||
&options_clockformat,
|
&options_clockformat,
|
||||||
&button_ok
|
&checkbox_guireturnflag,
|
||||||
|
&button_save,
|
||||||
|
&button_cancel
|
||||||
});
|
});
|
||||||
|
|
||||||
|
checkbox_disable_touchscreen.set_value(persistent_memory::disable_touchscreen());
|
||||||
checkbox_speaker.set_value(persistent_memory::config_speaker());
|
checkbox_speaker.set_value(persistent_memory::config_speaker());
|
||||||
checkbox_showsplash.set_value(persistent_memory::config_splash());
|
checkbox_showsplash.set_value(persistent_memory::config_splash());
|
||||||
checkbox_showclock.set_value(!persistent_memory::hide_clock());
|
checkbox_showclock.set_value(!persistent_memory::hide_clock());
|
||||||
//checkbox_login.set_value(persistent_memory::config_login());
|
checkbox_guireturnflag.set_value(persistent_memory::show_gui_return_icon());
|
||||||
|
|
||||||
uint32_t backlight_timer = persistent_memory::config_backlight_timer();
|
uint32_t backlight_timer = persistent_memory::config_backlight_timer();
|
||||||
if (backlight_timer) {
|
if (backlight_timer) {
|
||||||
@@ -309,16 +259,8 @@ SetUIView::SetUIView(NavigationView& nav) {
|
|||||||
options_clockformat.set_selected_index(0);
|
options_clockformat.set_selected_index(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
checkbox_speaker.on_select = [this](Checkbox&, bool v) {
|
|
||||||
if (v) audio::output::speaker_mute(); //Just mute audio if speaker is disabled
|
|
||||||
|
|
||||||
persistent_memory::set_config_speaker(v); //Store Speaker status
|
button_save.on_select = [&nav, this](Button&) {
|
||||||
|
|
||||||
StatusRefreshMessage message { }; //Refresh status bar with/out speaker
|
|
||||||
EventDispatcher::send_message(message);
|
|
||||||
};
|
|
||||||
|
|
||||||
button_ok.on_select = [&nav, this](Button&) {
|
|
||||||
if (checkbox_bloff.value())
|
if (checkbox_bloff.value())
|
||||||
persistent_memory::set_config_backlight_timer(options_bloff.selected_index() + 1);
|
persistent_memory::set_config_backlight_timer(options_bloff.selected_index() + 1);
|
||||||
else
|
else
|
||||||
@@ -329,225 +271,122 @@ SetUIView::SetUIView(NavigationView& nav) {
|
|||||||
persistent_memory::set_clock_with_date(true);
|
persistent_memory::set_clock_with_date(true);
|
||||||
else
|
else
|
||||||
persistent_memory::set_clock_with_date(false);
|
persistent_memory::set_clock_with_date(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (checkbox_speaker.value()) audio::output::speaker_mute(); //Just mute audio if speaker is disabled
|
||||||
|
persistent_memory::set_config_speaker(checkbox_speaker.value()); //Store Speaker status
|
||||||
|
StatusRefreshMessage message { }; //Refresh status bar with/out speaker
|
||||||
|
EventDispatcher::send_message(message);
|
||||||
|
|
||||||
persistent_memory::set_config_splash(checkbox_showsplash.value());
|
persistent_memory::set_config_splash(checkbox_showsplash.value());
|
||||||
persistent_memory::set_clock_hidden(!checkbox_showclock.value());
|
persistent_memory::set_clock_hidden(!checkbox_showclock.value());
|
||||||
//persistent_memory::set_config_login(checkbox_login.value());
|
persistent_memory::set_gui_return_icon(checkbox_guireturnflag.value());
|
||||||
|
persistent_memory::set_disable_touchscreen(checkbox_disable_touchscreen.value());
|
||||||
|
nav.pop();
|
||||||
|
};
|
||||||
|
button_cancel.on_select = [&nav, this](Button&) {
|
||||||
nav.pop();
|
nav.pop();
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetUIView::focus() {
|
void SetUIView::focus() {
|
||||||
button_ok.focus();
|
button_save.focus();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ---------------------------------------------------------
|
||||||
|
// Appl. Settings
|
||||||
|
// ---------------------------------------------------------
|
||||||
|
SetAppSettingsView::SetAppSettingsView(NavigationView& nav) {
|
||||||
|
add_children({
|
||||||
|
&checkbox_load_app_settings,
|
||||||
|
&checkbox_save_app_settings,
|
||||||
|
&button_save,
|
||||||
|
&button_cancel
|
||||||
|
});
|
||||||
|
|
||||||
|
checkbox_load_app_settings.set_value(persistent_memory::load_app_settings());
|
||||||
|
checkbox_save_app_settings.set_value(persistent_memory::save_app_settings());
|
||||||
|
|
||||||
|
|
||||||
|
button_save.on_select = [&nav, this](Button&) {
|
||||||
|
persistent_memory::set_load_app_settings(checkbox_load_app_settings.value());
|
||||||
|
persistent_memory::set_save_app_settings(checkbox_save_app_settings.value());
|
||||||
|
nav.pop();
|
||||||
|
};
|
||||||
|
button_cancel.on_select = [&nav, this](Button&) {
|
||||||
|
nav.pop();
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetAppSettingsView::focus() {
|
||||||
|
button_save.focus();
|
||||||
}
|
}
|
||||||
|
|
||||||
SetAudioView::SetAudioView(NavigationView& nav) {
|
SetAudioView::SetAudioView(NavigationView& nav) {
|
||||||
add_children({
|
add_children({
|
||||||
&labels,
|
&labels,
|
||||||
&field_tone_mix,
|
&field_tone_mix,
|
||||||
&button_ok
|
&button_save,
|
||||||
|
&button_cancel
|
||||||
});
|
});
|
||||||
|
|
||||||
field_tone_mix.set_value(persistent_memory::tone_mix());
|
field_tone_mix.set_value(persistent_memory::tone_mix());
|
||||||
|
|
||||||
button_ok.on_select = [&nav, this](Button&) {
|
button_save.on_select = [&nav, this](Button&) {
|
||||||
persistent_memory::set_tone_mix(field_tone_mix.value());
|
persistent_memory::set_tone_mix(field_tone_mix.value());
|
||||||
nav.pop();
|
nav.pop();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
button_cancel.on_select = [&nav, this](Button&) {
|
||||||
|
nav.pop();
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetAudioView::focus() {
|
void SetAudioView::focus() {
|
||||||
field_tone_mix.focus();
|
button_save.focus();
|
||||||
}
|
}
|
||||||
|
|
||||||
/*void ModInfoView::on_show() {
|
SetQRCodeView::SetQRCodeView(NavigationView& nav) {
|
||||||
if (modules_nb) update_infos(0);
|
add_children({
|
||||||
}
|
&checkbox_bigger_qr,
|
||||||
|
&button_save,
|
||||||
|
&button_cancel
|
||||||
|
});
|
||||||
|
|
||||||
void ModInfoView::update_infos(uint8_t modn) {
|
checkbox_bigger_qr.set_value(persistent_memory::show_bigger_qr_code());
|
||||||
char info_str[27];
|
|
||||||
char ch;
|
|
||||||
uint8_t c;
|
|
||||||
Point pos = { 0, 0 };
|
|
||||||
Rect rect = { { 16, 144 }, { 208, 144 } };
|
|
||||||
|
|
||||||
info_str[0] = 0;
|
button_save.on_select = [&nav, this](Button&) {
|
||||||
strcat(info_str, module_list[modn].name);
|
persistent_memory::set_show_bigger_qr_code(checkbox_bigger_qr.value());
|
||||||
text_namestr.set(info_str);
|
|
||||||
|
|
||||||
info_str[0] = 0;
|
|
||||||
strcat(info_str, to_string_dec_uint(module_list[modn].size).c_str());
|
|
||||||
strcat(info_str, " bytes");
|
|
||||||
text_sizestr.set(info_str);
|
|
||||||
|
|
||||||
info_str[0] = 0;
|
|
||||||
for (c = 0; c < 8; c++)
|
|
||||||
strcat(info_str, to_string_hex(module_list[modn].md5[c], 2).c_str());
|
|
||||||
text_md5_a.set(info_str);
|
|
||||||
|
|
||||||
info_str[0] = 0;
|
|
||||||
for (c = 8; c < 16; c++)
|
|
||||||
strcat(info_str, to_string_hex(module_list[modn].md5[c], 2).c_str());
|
|
||||||
text_md5_b.set(info_str);
|
|
||||||
|
|
||||||
// TODO: Use ui_console
|
|
||||||
display.fill_rectangle(rect, Color::black());
|
|
||||||
|
|
||||||
const Font& font = font::fixed_8x16;
|
|
||||||
const auto line_height = font.line_height();
|
|
||||||
c = 0;
|
|
||||||
while((ch = module_list[modn].description[c++])) {
|
|
||||||
const auto glyph = font.glyph(ch);
|
|
||||||
const auto advance = glyph.advance();
|
|
||||||
if((pos.x + advance.x) > rect.width()) {
|
|
||||||
pos.x = 0;
|
|
||||||
pos.y += line_height;
|
|
||||||
}
|
|
||||||
const Point pos_glyph {
|
|
||||||
static_cast<Coord>(rect.pos.x + pos.x),
|
|
||||||
static_cast<Coord>(rect.pos.y + pos.y)
|
|
||||||
};
|
|
||||||
display.draw_glyph(pos_glyph, glyph, Color::white(), Color::black());
|
|
||||||
pos.x += advance.x;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ModInfoView::ModInfoView(NavigationView& nav) {
|
|
||||||
const char magic[4] = {'P', 'P', 'M', ' '};
|
|
||||||
UINT bw;
|
|
||||||
uint8_t i;
|
|
||||||
char read_buf[16];
|
|
||||||
char info_str[25];
|
|
||||||
FILINFO modinfo;
|
|
||||||
FIL modfile;
|
|
||||||
DIR rootdir;
|
|
||||||
FRESULT res;
|
|
||||||
uint8_t c;
|
|
||||||
|
|
||||||
using option_t = std::pair<std::string, int32_t>;
|
|
||||||
using options_t = std::vector<option_t>;
|
|
||||||
option_t opt;
|
|
||||||
options_t opts;
|
|
||||||
|
|
||||||
static constexpr Style style_orange {
|
|
||||||
.font = font::fixed_8x16,
|
|
||||||
.background = Color::black(),
|
|
||||||
.foreground = Color::orange(),
|
|
||||||
};
|
|
||||||
|
|
||||||
add_children({{
|
|
||||||
&text_modcount,
|
|
||||||
&text_name,
|
|
||||||
&text_namestr,
|
|
||||||
&text_size,
|
|
||||||
&text_sizestr,
|
|
||||||
&text_md5,
|
|
||||||
&text_md5_a,
|
|
||||||
&text_md5_b,
|
|
||||||
&button_ok
|
|
||||||
}});
|
|
||||||
|
|
||||||
text_name.set_style(&style_orange);
|
|
||||||
text_size.set_style(&style_orange);
|
|
||||||
text_md5.set_style(&style_orange);
|
|
||||||
|
|
||||||
// TODO: Find a way to merge this with m4_load_image() in m4_startup.cpp
|
|
||||||
|
|
||||||
// Scan SD card root directory for files starting with the magic bytes
|
|
||||||
c = 0;
|
|
||||||
if (f_opendir(&rootdir, "/") == FR_OK) {
|
|
||||||
for (;;) {
|
|
||||||
res = f_readdir(&rootdir, &modinfo);
|
|
||||||
if (res != FR_OK || modinfo.fname[0] == 0) break; // Reached last file, abort
|
|
||||||
// Only care about files with .bin extension
|
|
||||||
if ((!(modinfo.fattrib & AM_DIR)) && (modinfo.fname[9] == 'B') && (modinfo.fname[10] == 'I') && (modinfo.fname[11] == 'N')) {
|
|
||||||
f_open(&modfile, modinfo.fname, FA_OPEN_EXISTING | FA_READ);
|
|
||||||
// Magic bytes check
|
|
||||||
f_read(&modfile, &read_buf, 4, &bw);
|
|
||||||
for (i = 0; i < 4; i++)
|
|
||||||
if (read_buf[i] != magic[i]) break;
|
|
||||||
if (i == 4) {
|
|
||||||
memcpy(&module_list[c].filename, modinfo.fname, 8);
|
|
||||||
module_list[c].filename[8] = 0;
|
|
||||||
|
|
||||||
f_lseek(&modfile, 4);
|
|
||||||
f_read(&modfile, &module_list[c].version, 2, &bw);
|
|
||||||
f_lseek(&modfile, 6);
|
|
||||||
f_read(&modfile, &module_list[c].size, 4, &bw);
|
|
||||||
f_lseek(&modfile, 10);
|
|
||||||
f_read(&modfile, &module_list[c].name, 16, &bw);
|
|
||||||
f_lseek(&modfile, 26);
|
|
||||||
f_read(&modfile, &module_list[c].md5, 16, &bw);
|
|
||||||
f_lseek(&modfile, 42);
|
|
||||||
f_read(&modfile, &module_list[c].description, 214, &bw);
|
|
||||||
f_lseek(&modfile, 256);
|
|
||||||
|
|
||||||
// Sanitize
|
|
||||||
module_list[c].name[15] = 0;
|
|
||||||
module_list[c].description[213] = 0;
|
|
||||||
|
|
||||||
memcpy(info_str, module_list[c].filename, 16);
|
|
||||||
strcat(info_str, "(V");
|
|
||||||
strcat(info_str, to_string_dec_uint(module_list[c].version, 4, '0').c_str());
|
|
||||||
strcat(info_str, ")");
|
|
||||||
while(strlen(info_str) < 24)
|
|
||||||
strcat(info_str, " ");
|
|
||||||
|
|
||||||
opt = std::make_pair(info_str, c);
|
|
||||||
opts.insert(opts.end(), opt);
|
|
||||||
|
|
||||||
c++;
|
|
||||||
}
|
|
||||||
f_close(&modfile);
|
|
||||||
}
|
|
||||||
if (c == 8) break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
f_closedir(&rootdir);
|
|
||||||
|
|
||||||
modules_nb = c;
|
|
||||||
|
|
||||||
if (modules_nb) {
|
|
||||||
strcpy(info_str, "Found ");
|
|
||||||
strcat(info_str, to_string_dec_uint(modules_nb, 1).c_str());
|
|
||||||
strcat(info_str, " module(s)");
|
|
||||||
|
|
||||||
text_modcount.set(info_str);
|
|
||||||
option_modules.set_options(opts);
|
|
||||||
|
|
||||||
add_child(&option_modules);
|
|
||||||
|
|
||||||
option_modules.on_change = [this](size_t n, OptionsField::value_t v) {
|
|
||||||
(void)n;
|
|
||||||
update_infos(v);
|
|
||||||
};
|
|
||||||
} else {
|
|
||||||
strcpy(info_str, "No modules found");
|
|
||||||
text_modcount.set(info_str);
|
|
||||||
}
|
|
||||||
|
|
||||||
button_ok.on_select = [&nav,this](Button&){
|
|
||||||
nav.pop();
|
nav.pop();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
button_cancel.on_select = [&nav, this](Button&) {
|
||||||
|
nav.pop();
|
||||||
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ModInfoView::focus() {
|
void SetQRCodeView::focus() {
|
||||||
if (modules_nb)
|
button_save.focus();
|
||||||
option_modules.focus();
|
}
|
||||||
else
|
|
||||||
button_ok.focus();
|
|
||||||
}*/
|
|
||||||
|
|
||||||
|
// ---------------------------------------------------------
|
||||||
|
// Settings main menu
|
||||||
|
// ---------------------------------------------------------
|
||||||
SettingsMenuView::SettingsMenuView(NavigationView& nav) {
|
SettingsMenuView::SettingsMenuView(NavigationView& nav) {
|
||||||
|
if( portapack::persistent_memory::show_gui_return_icon() )
|
||||||
|
{
|
||||||
|
add_items( { { "..", ui::Color::light_grey(),&bitmap_icon_previous, [&nav](){ nav.pop(); } } } );
|
||||||
|
}
|
||||||
add_items({
|
add_items({
|
||||||
//{ "..", ui::Color::light_grey(), &bitmap_icon_previous, [&nav](){ nav.pop(); } },
|
{ "Audio", ui::Color::dark_cyan(), &bitmap_icon_speaker, [&nav](){ nav.push<SetAudioView>(); } },
|
||||||
{ "Audio", ui::Color::dark_cyan(), &bitmap_icon_speaker, [&nav](){ nav.push<SetAudioView>(); } },
|
{ "Radio", ui::Color::dark_cyan(), &bitmap_icon_options_radio, [&nav](){ nav.push<SetRadioView>(); } },
|
||||||
{ "Radio", ui::Color::dark_cyan(), &bitmap_icon_options_radio, [&nav](){ nav.push<SetRadioView>(); } },
|
{ "User Interface", ui::Color::dark_cyan(), &bitmap_icon_options_ui, [&nav](){ nav.push<SetUIView>(); } },
|
||||||
{ "Interface", ui::Color::dark_cyan(), &bitmap_icon_options_ui, [&nav](){ nav.push<SetUIView>(); } },
|
{ "Date/Time", ui::Color::dark_cyan(), &bitmap_icon_options_datetime, [&nav](){ nav.push<SetDateTimeView>(); } },
|
||||||
//{ "SD card modules", ui::Color::dark_cyan(), [&nav](){ nav.push<ModInfoView>(); } },
|
{ "Calibration", ui::Color::dark_cyan(), &bitmap_icon_options_touch, [&nav](){ nav.push<TouchCalibrationView>(); } },
|
||||||
{ "Date/Time", ui::Color::dark_cyan(), &bitmap_icon_options_datetime, [&nav](){ nav.push<SetDateTimeView>(); } },
|
{ "App Settings", ui::Color::dark_cyan(), &bitmap_icon_setup, [&nav](){ nav.push<SetAppSettingsView>(); } },
|
||||||
{ "Touchscreen", ui::Color::dark_cyan(), &bitmap_icon_options_touch, [&nav](){ nav.push<TouchCalibrationView>(); } },
|
{ "QR Code", ui::Color::dark_cyan(), &bitmap_icon_qr_code, [&nav](){ nav.push<SetQRCodeView>(); } }
|
||||||
//{ "Play dead", ui::Color::dark_cyan(), &bitmap_icon_playdead, [&nav](){ nav.push<SetPlayDeadView>(); } }
|
|
||||||
});
|
});
|
||||||
set_max_rows(2); // allow wider buttons
|
set_max_rows(2); // allow wider buttons
|
||||||
}
|
}
|
||||||
|
@@ -47,7 +47,7 @@ public:
|
|||||||
|
|
||||||
void focus() override;
|
void focus() override;
|
||||||
|
|
||||||
std::string title() const override { return "Set Date/Time"; };
|
std::string title() const override { return "Date/Time"; };
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Labels labels {
|
Labels labels {
|
||||||
@@ -99,7 +99,7 @@ private:
|
|||||||
'0',
|
'0',
|
||||||
};
|
};
|
||||||
|
|
||||||
Button button_done {
|
Button button_save {
|
||||||
{ 2 * 8, 16 * 16, 12 * 8, 32 },
|
{ 2 * 8, 16 * 16, 12 * 8, 32 },
|
||||||
"Save"
|
"Save"
|
||||||
};
|
};
|
||||||
@@ -197,7 +197,7 @@ private:
|
|||||||
"Turn on bias voltage"
|
"Turn on bias voltage"
|
||||||
};
|
};
|
||||||
|
|
||||||
Button button_done {
|
Button button_save {
|
||||||
{ 2 * 8, 16 * 16, 12 * 8, 32 },
|
{ 2 * 8, 16 * 16, 12 * 8, 32 },
|
||||||
"Save"
|
"Save"
|
||||||
};
|
};
|
||||||
@@ -219,11 +219,12 @@ public:
|
|||||||
std::string title() const override { return "UI settings"; };
|
std::string title() const override { return "UI settings"; };
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/*Checkbox checkbox_login {
|
|
||||||
|
Checkbox checkbox_disable_touchscreen {
|
||||||
{ 3 * 8, 2 * 16 },
|
{ 3 * 8, 2 * 16 },
|
||||||
20,
|
20,
|
||||||
"Login with play dead"
|
"Disable touchscreen"
|
||||||
};*/
|
};
|
||||||
|
|
||||||
Checkbox checkbox_speaker {
|
Checkbox checkbox_speaker {
|
||||||
{ 3 * 8, 4 * 16 },
|
{ 3 * 8, 4 * 16 },
|
||||||
@@ -270,11 +271,55 @@ private:
|
|||||||
{ "time and date", 1 }
|
{ "time and date", 1 }
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Checkbox checkbox_guireturnflag {
|
||||||
|
{ 3 * 8, 14 * 16 },
|
||||||
|
25,
|
||||||
|
"add return icon in GUI"
|
||||||
|
};
|
||||||
|
|
||||||
Button button_ok {
|
Button button_save {
|
||||||
{ 2 * 8, 16 * 16, 12 * 8, 32 },
|
{ 2 * 8, 16 * 16, 12 * 8, 32 },
|
||||||
"Save"
|
"Save"
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Button button_cancel {
|
||||||
|
{ 16 * 8, 16 * 16, 12 * 8, 32 },
|
||||||
|
"Cancel",
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
class SetAppSettingsView : public View {
|
||||||
|
public:
|
||||||
|
SetAppSettingsView(NavigationView& nav);
|
||||||
|
|
||||||
|
void focus() override;
|
||||||
|
|
||||||
|
std::string title() const override { return "App Settings"; };
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
Checkbox checkbox_load_app_settings {
|
||||||
|
{ 3 * 8, 2 * 16 },
|
||||||
|
25,
|
||||||
|
"Load app settings"
|
||||||
|
};
|
||||||
|
|
||||||
|
Checkbox checkbox_save_app_settings {
|
||||||
|
{ 3 * 8, 4 * 16 },
|
||||||
|
25,
|
||||||
|
"Save app settings"
|
||||||
|
};
|
||||||
|
|
||||||
|
Button button_save {
|
||||||
|
{ 2 * 8, 16 * 16, 12 * 8, 32 },
|
||||||
|
"Save"
|
||||||
|
};
|
||||||
|
|
||||||
|
Button button_cancel {
|
||||||
|
{ 16 * 8, 16 * 16, 12 * 8, 32 },
|
||||||
|
"Cancel",
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
class SetAudioView : public View {
|
class SetAudioView : public View {
|
||||||
@@ -298,111 +343,43 @@ private:
|
|||||||
'0'
|
'0'
|
||||||
};
|
};
|
||||||
|
|
||||||
Button button_ok {
|
Button button_save {
|
||||||
{ 2 * 8, 16 * 16, 12 * 8, 32 },
|
{ 2 * 8, 16 * 16, 12 * 8, 32 },
|
||||||
"Save"
|
"Save"
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Button button_cancel {
|
||||||
|
{ 16 * 8, 16 * 16, 12 * 8, 32 },
|
||||||
|
"Cancel",
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
|
||||||
class SetPlayDeadView : public View {
|
|
||||||
public:
|
|
||||||
SetPlayDeadView(NavigationView& nav);
|
|
||||||
|
|
||||||
void focus() override;
|
|
||||||
|
|
||||||
std::string title() const override { return "Playdead settings"; };
|
|
||||||
|
|
||||||
private:
|
|
||||||
bool entermode = false;
|
|
||||||
uint32_t sequence { 0 };
|
|
||||||
uint8_t keycount { 0 }, key_code { };
|
|
||||||
char sequence_txt[11] = { 0 };
|
|
||||||
|
|
||||||
Text text_sequence {
|
|
||||||
{ 64, 32, 14 * 8, 16 },
|
|
||||||
"Enter sequence",
|
|
||||||
};
|
|
||||||
|
|
||||||
Button button_enter {
|
|
||||||
{ 16, 192, 96, 24 },
|
|
||||||
"Enter"
|
|
||||||
};
|
|
||||||
Button button_cancel {
|
|
||||||
{ 128, 192, 96, 24 },
|
|
||||||
"Cancel"
|
|
||||||
};
|
|
||||||
};*/
|
|
||||||
|
|
||||||
/*class ModInfoView : public View {
|
class SetQRCodeView : public View {
|
||||||
public:
|
public:
|
||||||
ModInfoView(NavigationView& nav);
|
SetQRCodeView(NavigationView& nav);
|
||||||
|
|
||||||
void focus() override;
|
void focus() override;
|
||||||
void on_show() override;
|
|
||||||
|
std::string title() const override { return "QR Code"; };
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void update_infos(uint8_t modn);
|
Checkbox checkbox_bigger_qr {
|
||||||
|
{ 3 * 8, 9 * 16 },
|
||||||
typedef struct moduleinfo_t{
|
20,
|
||||||
char filename[9];
|
"Show large QR code"
|
||||||
uint16_t version;
|
|
||||||
uint32_t size;
|
|
||||||
char md5[16];
|
|
||||||
char name[16];
|
|
||||||
char description[214];
|
|
||||||
} moduleinfo_t;
|
|
||||||
|
|
||||||
moduleinfo_t module_list[8]; // 8 max for now
|
|
||||||
|
|
||||||
uint8_t modules_nb;
|
|
||||||
|
|
||||||
Text text_modcount {
|
|
||||||
{ 2 * 8, 1 * 16, 18 * 8, 16 },
|
|
||||||
"Searching..."
|
|
||||||
};
|
};
|
||||||
|
|
||||||
OptionsField option_modules {
|
Button button_save {
|
||||||
{ 2 * 8, 2 * 16 },
|
{ 2 * 8, 16 * 16, 12 * 8, 32 },
|
||||||
24,
|
"Save"
|
||||||
{
|
|
||||||
{ "-", 0 }
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
Text text_name {
|
Button button_cancel {
|
||||||
{ 2 * 8, 4 * 16, 5 * 8, 16 },
|
{ 16 * 8, 16 * 16, 12 * 8, 32 },
|
||||||
"Name:"
|
"Cancel",
|
||||||
};
|
};
|
||||||
Text text_namestr {
|
};
|
||||||
{ 8 * 8, 4 * 16, 16 * 8, 16 },
|
|
||||||
"..."
|
|
||||||
};
|
|
||||||
Text text_size {
|
|
||||||
{ 2 * 8, 5 * 16, 5 * 8, 16 },
|
|
||||||
"Size:"
|
|
||||||
};
|
|
||||||
Text text_sizestr {
|
|
||||||
{ 8 * 8, 5 * 16, 16 * 8, 16 },
|
|
||||||
"..."
|
|
||||||
};
|
|
||||||
Text text_md5 {
|
|
||||||
{ 2 * 8, 6 * 16, 4 * 8, 16 },
|
|
||||||
"MD5:"
|
|
||||||
};
|
|
||||||
Text text_md5_a {
|
|
||||||
{ 7 * 8, 6 * 16, 16 * 8, 16 },
|
|
||||||
"..."
|
|
||||||
};
|
|
||||||
Text text_md5_b {
|
|
||||||
{ 7 * 8, 7 * 16, 16 * 8, 16 },
|
|
||||||
"..."
|
|
||||||
};
|
|
||||||
|
|
||||||
Button button_ok {
|
|
||||||
{ 4 * 8, 272, 64, 24 },
|
|
||||||
"Ok"
|
|
||||||
};
|
|
||||||
};*/
|
|
||||||
|
|
||||||
class SettingsMenuView : public BtnGridView {
|
class SettingsMenuView : public BtnGridView {
|
||||||
public:
|
public:
|
||||||
|
@@ -40,7 +40,7 @@ public:
|
|||||||
|
|
||||||
void focus() override;
|
void focus() override;
|
||||||
|
|
||||||
std::string title() const override { return "Generator"; };
|
std::string title() const override { return "Signal gen"; };
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void start_tx();
|
void start_tx();
|
||||||
|
@@ -23,6 +23,7 @@
|
|||||||
#include "ui_sonde.hpp"
|
#include "ui_sonde.hpp"
|
||||||
#include "baseband_api.hpp"
|
#include "baseband_api.hpp"
|
||||||
#include "audio.hpp"
|
#include "audio.hpp"
|
||||||
|
#include "app_settings.hpp"
|
||||||
|
|
||||||
#include "portapack.hpp"
|
#include "portapack.hpp"
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
@@ -43,6 +44,8 @@ namespace ui {
|
|||||||
|
|
||||||
|
|
||||||
SondeView::SondeView(NavigationView& nav) {
|
SondeView::SondeView(NavigationView& nav) {
|
||||||
|
|
||||||
|
|
||||||
baseband::run_image(portapack::spi_flash::image_tag_sonde);
|
baseband::run_image(portapack::spi_flash::image_tag_sonde);
|
||||||
|
|
||||||
add_children({
|
add_children({
|
||||||
@@ -68,8 +71,17 @@ SondeView::SondeView(NavigationView& nav) {
|
|||||||
&button_see_map
|
&button_see_map
|
||||||
});
|
});
|
||||||
|
|
||||||
// start from the frequency currently stored in the receiver_model:
|
|
||||||
target_frequency_ = receiver_model.tuning_frequency();
|
// load app settings
|
||||||
|
auto rc = settings.load("rx_sonde", &app_settings);
|
||||||
|
if(rc == SETTINGS_OK) {
|
||||||
|
field_lna.set_value(app_settings.lna);
|
||||||
|
field_vga.set_value(app_settings.vga);
|
||||||
|
field_rf_amp.set_value(app_settings.rx_amp);
|
||||||
|
target_frequency_ = app_settings.rx_frequency;
|
||||||
|
}
|
||||||
|
else target_frequency_ = receiver_model.tuning_frequency();
|
||||||
|
|
||||||
|
|
||||||
field_frequency.set_value(target_frequency_);
|
field_frequency.set_value(target_frequency_);
|
||||||
field_frequency.set_step(500); //euquiq: was 10000, but we are using this for fine-tunning
|
field_frequency.set_step(500); //euquiq: was 10000, but we are using this for fine-tunning
|
||||||
@@ -104,16 +116,6 @@ SondeView::SondeView(NavigationView& nav) {
|
|||||||
receiver_model.set_sampling_rate(sampling_rate);
|
receiver_model.set_sampling_rate(sampling_rate);
|
||||||
receiver_model.set_baseband_bandwidth(baseband_bandwidth);
|
receiver_model.set_baseband_bandwidth(baseband_bandwidth);
|
||||||
receiver_model.enable(); // Before using radio::enable(), but not updating Ant.DC-Bias.
|
receiver_model.enable(); // Before using radio::enable(), but not updating Ant.DC-Bias.
|
||||||
|
|
||||||
/* radio::enable({ // this can be removed, previous version, no DC-bias ant. control.
|
|
||||||
tuning_frequency(),
|
|
||||||
sampling_rate,
|
|
||||||
baseband_bandwidth,
|
|
||||||
rf::Direction::Receive,
|
|
||||||
receiver_model.rf_amp(),
|
|
||||||
static_cast<int8_t>(receiver_model.lna()),
|
|
||||||
static_cast<int8_t>(receiver_model.vga()),
|
|
||||||
}); */
|
|
||||||
|
|
||||||
|
|
||||||
// QR code with geo URI
|
// QR code with geo URI
|
||||||
@@ -157,9 +159,13 @@ SondeView::SondeView(NavigationView& nav) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
SondeView::~SondeView() {
|
SondeView::~SondeView() {
|
||||||
|
// save app settings
|
||||||
|
app_settings.rx_frequency = target_frequency_;
|
||||||
|
settings.save("rx_sonde", &app_settings);
|
||||||
|
|
||||||
baseband::set_pitch_rssi(0, false);
|
baseband::set_pitch_rssi(0, false);
|
||||||
/* radio::disable(); */
|
|
||||||
receiver_model.disable(); // to switch off all, including DC bias.
|
receiver_model.disable(); // to switch off all, including DC bias.
|
||||||
baseband::shutdown();
|
baseband::shutdown();
|
||||||
audio::output::stop();
|
audio::output::stop();
|
||||||
}
|
}
|
||||||
|
@@ -34,7 +34,7 @@
|
|||||||
#include "log_file.hpp"
|
#include "log_file.hpp"
|
||||||
|
|
||||||
#include "sonde_packet.hpp"
|
#include "sonde_packet.hpp"
|
||||||
|
#include "app_settings.hpp"
|
||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
@@ -74,6 +74,9 @@ private:
|
|||||||
bool beep { false };
|
bool beep { false };
|
||||||
|
|
||||||
char geo_uri[32] = {};
|
char geo_uri[32] = {};
|
||||||
|
// app save settings
|
||||||
|
std::app_settings settings { };
|
||||||
|
std::app_settings::AppSettings app_settings { };
|
||||||
|
|
||||||
sonde::GPS_data gps_info { };
|
sonde::GPS_data gps_info { };
|
||||||
sonde::temp_humid temp_humid_info { };
|
sonde::temp_humid temp_humid_info { };
|
||||||
|
@@ -88,6 +88,10 @@ void SSTVTXView::paint(Painter&) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
SSTVTXView::~SSTVTXView() {
|
SSTVTXView::~SSTVTXView() {
|
||||||
|
// save app settings
|
||||||
|
app_settings.tx_frequency = transmitter_model.tuning_frequency();
|
||||||
|
settings.save("tx_sstv", &app_settings);
|
||||||
|
|
||||||
transmitter_model.disable();
|
transmitter_model.disable();
|
||||||
baseband::shutdown();
|
baseband::shutdown();
|
||||||
}
|
}
|
||||||
@@ -215,6 +219,15 @@ SSTVTXView::SSTVTXView(
|
|||||||
options_t mode_options;
|
options_t mode_options;
|
||||||
uint32_t c;
|
uint32_t c;
|
||||||
|
|
||||||
|
// load app settings
|
||||||
|
auto rc = settings.load("tx_sstv", &app_settings);
|
||||||
|
if(rc == SETTINGS_OK) {
|
||||||
|
transmitter_model.set_rf_amp(app_settings.tx_amp);
|
||||||
|
transmitter_model.set_channel_bandwidth(app_settings.channel_bandwidth);
|
||||||
|
transmitter_model.set_tuning_frequency(app_settings.tx_frequency);
|
||||||
|
transmitter_model.set_tx_gain(app_settings.tx_gain);
|
||||||
|
}
|
||||||
|
|
||||||
// Search for valid bitmaps
|
// Search for valid bitmaps
|
||||||
file_list = scan_root_files(u"/sstv", u"*.bmp");
|
file_list = scan_root_files(u"/sstv", u"*.bmp");
|
||||||
if (!file_list.size()) {
|
if (!file_list.size()) {
|
||||||
|
@@ -34,6 +34,7 @@
|
|||||||
#include "sstv.hpp"
|
#include "sstv.hpp"
|
||||||
#include "file.hpp"
|
#include "file.hpp"
|
||||||
#include "bmp.hpp"
|
#include "bmp.hpp"
|
||||||
|
#include "app_settings.hpp"
|
||||||
|
|
||||||
using namespace sstv;
|
using namespace sstv;
|
||||||
|
|
||||||
@@ -58,7 +59,10 @@ private:
|
|||||||
NavigationView& nav_;
|
NavigationView& nav_;
|
||||||
|
|
||||||
sstv_scanline scanline_buffer { };
|
sstv_scanline scanline_buffer { };
|
||||||
|
// app save settings
|
||||||
|
std::app_settings settings { };
|
||||||
|
std::app_settings::AppSettings app_settings { };
|
||||||
|
|
||||||
bool file_error { false };
|
bool file_error { false };
|
||||||
File bmp_file { };
|
File bmp_file { };
|
||||||
bmp_header_t bmp_header { };
|
bmp_header_t bmp_header { };
|
||||||
|
@@ -168,8 +168,8 @@ void speaker_mute() {
|
|||||||
|
|
||||||
namespace input {
|
namespace input {
|
||||||
|
|
||||||
void start(int8_t alc_mode) {
|
void start() {
|
||||||
audio_codec->microphone_enable(alc_mode); // added user-GUI selection for AK4951, ALC mode parameter.
|
audio_codec->microphone_enable();
|
||||||
i2s::i2s0::rx_start();
|
i2s::i2s0::rx_start();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -49,7 +49,7 @@ public:
|
|||||||
virtual volume_range_t headphone_gain_range() const = 0;
|
virtual volume_range_t headphone_gain_range() const = 0;
|
||||||
virtual void set_headphone_volume(const volume_t volume) = 0;
|
virtual void set_headphone_volume(const volume_t volume) = 0;
|
||||||
|
|
||||||
virtual void microphone_enable(int8_t alc_mode) = 0; // added user-GUI AK4951 ,selected ALC mode.
|
virtual void microphone_enable() = 0;
|
||||||
virtual void microphone_disable() = 0;
|
virtual void microphone_disable() = 0;
|
||||||
|
|
||||||
virtual size_t reg_count() const = 0;
|
virtual size_t reg_count() const = 0;
|
||||||
@@ -59,7 +59,7 @@ public:
|
|||||||
|
|
||||||
namespace output {
|
namespace output {
|
||||||
|
|
||||||
void start(); // this other start(),no changed. ,in namespace output , used to config audio playback mode,
|
void start();
|
||||||
void stop();
|
void stop();
|
||||||
|
|
||||||
void mute();
|
void mute();
|
||||||
@@ -72,7 +72,7 @@ void speaker_unmute();
|
|||||||
|
|
||||||
namespace input {
|
namespace input {
|
||||||
|
|
||||||
void start(int8_t alc_mode); // added parameter user-GUI select AK4951-ALC mode for config mic path,(recording mode in datasheet),
|
void start();
|
||||||
void stop();
|
void stop();
|
||||||
|
|
||||||
} /* namespace input */
|
} /* namespace input */
|
||||||
|
@@ -1285,6 +1285,28 @@ static constexpr Bitmap bitmap_icon_previous {
|
|||||||
{ 16, 16 }, bitmap_icon_previous_data
|
{ 16, 16 }, bitmap_icon_previous_data
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static constexpr uint8_t bitmap_icon_qr_code_data[] = {
|
||||||
|
0x00, 0x00,
|
||||||
|
0xFE, 0x7E,
|
||||||
|
0xC6, 0x62,
|
||||||
|
0xFA, 0x5A,
|
||||||
|
0xFA, 0x5A,
|
||||||
|
0xDA, 0x5A,
|
||||||
|
0xFE, 0x7E,
|
||||||
|
0x7E, 0x7E,
|
||||||
|
0x00, 0x00,
|
||||||
|
0xFE, 0x46,
|
||||||
|
0xC2, 0x06,
|
||||||
|
0xFA, 0x18,
|
||||||
|
0xFA, 0x18,
|
||||||
|
0xC6, 0x60,
|
||||||
|
0xFE, 0x62,
|
||||||
|
0x00, 0x00,
|
||||||
|
};
|
||||||
|
static constexpr Bitmap bitmap_icon_qr_code {
|
||||||
|
{ 16, 16 }, bitmap_icon_qr_code_data
|
||||||
|
};
|
||||||
|
|
||||||
static constexpr uint8_t bitmap_icon_rds_data[] = {
|
static constexpr uint8_t bitmap_icon_rds_data[] = {
|
||||||
0x00, 0x00,
|
0x00, 0x00,
|
||||||
0x00, 0x00,
|
0x00, 0x00,
|
||||||
|
@@ -167,14 +167,15 @@ int main(void) {
|
|||||||
if( portapack::init() ) {
|
if( portapack::init() ) {
|
||||||
portapack::display.init();
|
portapack::display.init();
|
||||||
|
|
||||||
sdcStart(&SDCD1, nullptr);
|
// sdcStart(&SDCD1, nullptr); // Commented out as now happens in portapack.cpp
|
||||||
|
|
||||||
controls_init();
|
// controls_init(); // Commented out as now happens in portapack.cpp
|
||||||
lcd_frame_sync_configure();
|
lcd_frame_sync_configure();
|
||||||
rtc_interrupt_enable();
|
rtc_interrupt_enable();
|
||||||
|
|
||||||
event_loop();
|
event_loop();
|
||||||
|
|
||||||
|
|
||||||
sdcDisconnect(&SDCD1);
|
sdcDisconnect(&SDCD1);
|
||||||
sdcStop(&SDCD1);
|
sdcStop(&SDCD1);
|
||||||
|
|
||||||
|
@@ -29,6 +29,7 @@
|
|||||||
#include "hackrf_gpio.hpp"
|
#include "hackrf_gpio.hpp"
|
||||||
using namespace hackrf::one;
|
using namespace hackrf::one;
|
||||||
|
|
||||||
|
|
||||||
#include "clock_manager.hpp"
|
#include "clock_manager.hpp"
|
||||||
#include "event_m0.hpp"
|
#include "event_m0.hpp"
|
||||||
|
|
||||||
@@ -45,6 +46,11 @@ using asahi_kasei::ak4951::AK4951;
|
|||||||
#include "cpld_update.hpp"
|
#include "cpld_update.hpp"
|
||||||
|
|
||||||
#include "optional.hpp"
|
#include "optional.hpp"
|
||||||
|
#include "irq_controls.hpp"
|
||||||
|
|
||||||
|
#include "file.hpp"
|
||||||
|
#include "sd_card.hpp"
|
||||||
|
#include "string_format.hpp"
|
||||||
|
|
||||||
namespace portapack {
|
namespace portapack {
|
||||||
|
|
||||||
@@ -175,22 +181,93 @@ enum class PortaPackModel {
|
|||||||
R2_20170522,
|
R2_20170522,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static bool save_config(int8_t value){
|
||||||
|
persistent_memory::set_config_cpld(value);
|
||||||
|
if(sd_card::status() == sd_card::Status::Mounted){
|
||||||
|
make_new_directory("/hardware");
|
||||||
|
File file;
|
||||||
|
auto sucess = file.create("/hardware/settings.txt");
|
||||||
|
if(!sucess.is_valid()) {
|
||||||
|
file.write_line(to_string_dec_uint(value));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
int read_file(std::string name) {
|
||||||
|
std::string return_string = "";
|
||||||
|
File file;
|
||||||
|
auto success = file.open(name);
|
||||||
|
|
||||||
|
if(!success.is_valid()) {
|
||||||
|
char one_char[1];
|
||||||
|
for(size_t pointer = 0; pointer < file.size() ; pointer++) {
|
||||||
|
file.seek(pointer);
|
||||||
|
file.read(one_char, 1);
|
||||||
|
return_string += one_char[0];
|
||||||
|
}
|
||||||
|
return std::stoi(return_string);
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int load_config(){
|
||||||
|
static Optional<int> config_value;
|
||||||
|
if(!config_value.is_valid()){
|
||||||
|
int8_t value = portapack::persistent_memory::config_cpld();
|
||||||
|
if((value <= 0 || value >= 4) && sd_card::status() == sd_card::Status::Mounted){
|
||||||
|
int data = read_file("/hardware/settings.txt");
|
||||||
|
if(data != -1) {
|
||||||
|
config_value = data;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
config_value = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return config_value.value();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static PortaPackModel portapack_model() {
|
static PortaPackModel portapack_model() {
|
||||||
static Optional<PortaPackModel> model;
|
static Optional<PortaPackModel> model;
|
||||||
|
|
||||||
if( !model.is_valid() ) {
|
if( !model.is_valid() ) {
|
||||||
/*For the time being, it is impossible to distinguish the hardware of R1 and R2 from the software level*/
|
const auto switches_state = get_switches_state();
|
||||||
/*At this point, I2c is not ready.*/
|
if (switches_state[(size_t)ui::KeyEvent::Up]){
|
||||||
//if( audio_codec_wm8731.detected() ) {
|
save_config(1);
|
||||||
// model = PortaPackModel::R1_20150901;
|
|
||||||
//} else {
|
|
||||||
model = PortaPackModel::R2_20170522;
|
model = PortaPackModel::R2_20170522;
|
||||||
//}
|
}
|
||||||
|
else if (switches_state[(size_t)ui::KeyEvent::Down]){
|
||||||
|
save_config(2);
|
||||||
|
model = PortaPackModel::R1_20150901;
|
||||||
|
}
|
||||||
|
else if (switches_state[(size_t)ui::KeyEvent::Left]){
|
||||||
|
save_config(3);
|
||||||
|
}
|
||||||
|
else if (switches_state[(size_t)ui::KeyEvent::Select]){
|
||||||
|
save_config(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (load_config() == 1) {
|
||||||
|
model = PortaPackModel::R2_20170522;
|
||||||
|
} else if (load_config() == 2) {
|
||||||
|
model = PortaPackModel::R1_20150901;
|
||||||
|
} else {
|
||||||
|
if( audio_codec_wm8731.detected() ) {
|
||||||
|
model = PortaPackModel::R1_20150901; // H1R1
|
||||||
|
} else {
|
||||||
|
model = PortaPackModel::R2_20170522; // H1R2, H2, H2+
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return model.value();
|
return model.value();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//audio_codec_wm8731 = H1R1 & H2+
|
||||||
|
//audio_codec_ak4951 = H1R2
|
||||||
|
|
||||||
static audio::Codec* portapack_audio_codec() {
|
static audio::Codec* portapack_audio_codec() {
|
||||||
/* I2C ready OK, Automatic recognition of audio chip */
|
/* I2C ready OK, Automatic recognition of audio chip */
|
||||||
return (audio_codec_wm8731.detected())
|
return (audio_codec_wm8731.detected())
|
||||||
@@ -201,15 +278,14 @@ static audio::Codec* portapack_audio_codec() {
|
|||||||
|
|
||||||
static const portapack::cpld::Config& portapack_cpld_config() {
|
static const portapack::cpld::Config& portapack_cpld_config() {
|
||||||
return (portapack_model() == PortaPackModel::R2_20170522)
|
return (portapack_model() == PortaPackModel::R2_20170522)
|
||||||
? portapack::cpld::rev_20170522::config
|
? portapack::cpld::rev_20170522::config
|
||||||
: portapack::cpld::rev_20150901::config
|
: portapack::cpld::rev_20150901::config;
|
||||||
;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Backlight* backlight() {
|
Backlight* backlight() {
|
||||||
return (portapack_model() == PortaPackModel::R2_20170522)
|
return (portapack_model() == PortaPackModel::R2_20170522)
|
||||||
? static_cast<portapack::Backlight*>(&backlight_cat4004)
|
? static_cast<portapack::Backlight*>(&backlight_cat4004) // R2_20170522
|
||||||
: static_cast<portapack::Backlight*>(&backlight_on_off);
|
: static_cast<portapack::Backlight*>(&backlight_on_off); // R1_20150901
|
||||||
}
|
}
|
||||||
|
|
||||||
#define ARRAY_SIZE(a) (sizeof(a)/sizeof(a[0]))
|
#define ARRAY_SIZE(a) (sizeof(a)/sizeof(a[0]))
|
||||||
@@ -318,14 +394,16 @@ bool init() {
|
|||||||
|
|
||||||
i2c0.start(i2c_config_boot_clock);
|
i2c0.start(i2c_config_boot_clock);
|
||||||
|
|
||||||
if( !portapack::cpld::update_if_necessary(portapack_cpld_config()) ) {
|
// Keeping this here for now incase we need to revert
|
||||||
shutdown_base();
|
// if( !portapack::cpld::update_if_necessary(portapack_cpld_config()) ) {
|
||||||
return false;
|
// shutdown_base();
|
||||||
}
|
// return false;
|
||||||
|
// }
|
||||||
|
|
||||||
if( !hackrf::cpld::load_sram() ) {
|
// if( !hackrf::cpld::load_sram() ) {
|
||||||
chSysHalt();
|
// chSysHalt();
|
||||||
}
|
// }
|
||||||
|
chThdSleepMilliseconds(100);
|
||||||
|
|
||||||
configure_pins_portapack();
|
configure_pins_portapack();
|
||||||
|
|
||||||
@@ -335,8 +413,9 @@ bool init() {
|
|||||||
|
|
||||||
i2c0.stop();
|
i2c0.stop();
|
||||||
|
|
||||||
set_clock_config(clock_config_irc);
|
chThdSleepMilliseconds(10);
|
||||||
|
|
||||||
|
set_clock_config(clock_config_irc);
|
||||||
cgu::pll1::disable();
|
cgu::pll1::disable();
|
||||||
|
|
||||||
/* Incantation from LPC43xx UM10503 section 12.2.1.1, to bring the M4
|
/* Incantation from LPC43xx UM10503 section 12.2.1.1, to bring the M4
|
||||||
@@ -376,21 +455,46 @@ bool init() {
|
|||||||
cgu::pll1::direct();
|
cgu::pll1::direct();
|
||||||
|
|
||||||
i2c0.start(i2c_config_fast_clock);
|
i2c0.start(i2c_config_fast_clock);
|
||||||
|
chThdSleepMilliseconds(10);
|
||||||
|
|
||||||
|
touch::adc::init();
|
||||||
|
controls_init();
|
||||||
|
chThdSleepMilliseconds(10);
|
||||||
|
|
||||||
clock_manager.set_reference_ppb(persistent_memory::correction_ppb());
|
clock_manager.set_reference_ppb(persistent_memory::correction_ppb());
|
||||||
|
|
||||||
audio::init(portapack_audio_codec());
|
|
||||||
|
|
||||||
clock_manager.enable_first_if_clock();
|
clock_manager.enable_first_if_clock();
|
||||||
clock_manager.enable_second_if_clock();
|
clock_manager.enable_second_if_clock();
|
||||||
clock_manager.enable_codec_clocks();
|
clock_manager.enable_codec_clocks();
|
||||||
radio::init();
|
radio::init();
|
||||||
|
|
||||||
touch::adc::init();
|
sdcStart(&SDCD1, nullptr);
|
||||||
|
sd_card::poll_inserted();
|
||||||
|
|
||||||
|
chThdSleepMilliseconds(10);
|
||||||
|
|
||||||
|
if( !portapack::cpld::update_if_necessary(portapack_cpld_config()) ) {
|
||||||
|
chThdSleepMilliseconds(10);
|
||||||
|
// If using a "2021/12 QFP100", press and hold the left button while booting. Should only need to do once.
|
||||||
|
if (load_config() != 3){
|
||||||
|
shutdown_base();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if( !hackrf::cpld::load_sram() ) {
|
||||||
|
chSysHalt();
|
||||||
|
}
|
||||||
|
|
||||||
|
chThdSleepMilliseconds(10); // This delay seems to solve white noise audio issues
|
||||||
|
|
||||||
LPC_CREG->DMAMUX = portapack::gpdma_mux;
|
LPC_CREG->DMAMUX = portapack::gpdma_mux;
|
||||||
gpdma::controller.enable();
|
gpdma::controller.enable();
|
||||||
|
|
||||||
|
chThdSleepMilliseconds(10);
|
||||||
|
|
||||||
|
audio::init(portapack_audio_codec());
|
||||||
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -38,7 +38,7 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#pragma mark - Error Correction Lookup tables
|
/* #pragma mark - Error Correction Lookup tables */
|
||||||
|
|
||||||
#if LOCK_VERSION == 0
|
#if LOCK_VERSION == 0
|
||||||
|
|
||||||
@@ -101,7 +101,7 @@ static int abs(int value) {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
#pragma mark - Mode testing and conversion
|
/* #pragma mark - Mode testing and conversion */
|
||||||
|
|
||||||
static int8_t getAlphanumeric(char c) {
|
static int8_t getAlphanumeric(char c) {
|
||||||
|
|
||||||
@@ -140,7 +140,7 @@ static bool isNumeric(const char *text, uint16_t length) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#pragma mark - Counting
|
/* #pragma mark - Counting */
|
||||||
|
|
||||||
// We store the following tightly packed (less 8) in modeInfo
|
// We store the following tightly packed (less 8) in modeInfo
|
||||||
// <=9 <=26 <= 40
|
// <=9 <=26 <= 40
|
||||||
@@ -167,7 +167,7 @@ static char getModeBits(uint8_t version, uint8_t mode) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#pragma mark - BitBucket
|
/* #pragma mark - BitBucket */
|
||||||
|
|
||||||
typedef struct BitBucket {
|
typedef struct BitBucket {
|
||||||
uint32_t bitOffsetOrWidth;
|
uint32_t bitOffsetOrWidth;
|
||||||
@@ -251,7 +251,7 @@ static bool bb_getBit(BitBucket *bitGrid, uint8_t x, uint8_t y) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#pragma mark - Drawing Patterns
|
/* #pragma mark - Drawing Patterns */
|
||||||
|
|
||||||
// XORs the data modules in this QR Code with the given mask pattern. Due to XOR's mathematical
|
// XORs the data modules in this QR Code with the given mask pattern. Due to XOR's mathematical
|
||||||
// properties, calling applyMask(m) twice with the same value is equivalent to no change at all.
|
// properties, calling applyMask(m) twice with the same value is equivalent to no change at all.
|
||||||
@@ -474,7 +474,7 @@ static void drawCodewords(BitBucket *modules, BitBucket *isFunction, BitBucket *
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
#pragma mark - Penalty Calculation
|
/* #pragma mark - Penalty Calculation */
|
||||||
|
|
||||||
#define PENALTY_N1 3
|
#define PENALTY_N1 3
|
||||||
#define PENALTY_N2 3
|
#define PENALTY_N2 3
|
||||||
@@ -574,7 +574,7 @@ static uint32_t getPenaltyScore(BitBucket *modules) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#pragma mark - Reed-Solomon Generator
|
/* #pragma mark - Reed-Solomon Generator */
|
||||||
|
|
||||||
static uint8_t rs_multiply(uint8_t x, uint8_t y) {
|
static uint8_t rs_multiply(uint8_t x, uint8_t y) {
|
||||||
// Russian peasant multiplication
|
// Russian peasant multiplication
|
||||||
@@ -628,7 +628,7 @@ static void rs_getRemainder(uint8_t degree, uint8_t *coeff, uint8_t *data, uint8
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
#pragma mark - QrCode
|
/* #pragma mark - QrCode */
|
||||||
|
|
||||||
static int8_t encodeDataCodewords(BitBucket *dataCodewords, const uint8_t *text, uint16_t length, uint8_t version) {
|
static int8_t encodeDataCodewords(BitBucket *dataCodewords, const uint8_t *text, uint16_t length, uint8_t version) {
|
||||||
int8_t mode = MODE_BYTE;
|
int8_t mode = MODE_BYTE;
|
||||||
@@ -769,7 +769,7 @@ static void performErrorCorrection(uint8_t version, uint8_t ecc, BitBucket *data
|
|||||||
static const uint8_t ECC_FORMAT_BITS = (0x02 << 6) | (0x03 << 4) | (0x00 << 2) | (0x01 << 0);
|
static const uint8_t ECC_FORMAT_BITS = (0x02 << 6) | (0x03 << 4) | (0x00 << 2) | (0x01 << 0);
|
||||||
|
|
||||||
|
|
||||||
#pragma mark - Public QRCode functions
|
/* #pragma mark - Public QRCode functions */
|
||||||
|
|
||||||
uint16_t qrcode_getBufferSize(uint8_t version) {
|
uint16_t qrcode_getBufferSize(uint8_t version) {
|
||||||
return bb_getGridSizeBytes(4 * version + 17);
|
return bb_getGridSizeBytes(4 * version + 17);
|
||||||
@@ -857,7 +857,7 @@ int8_t qrcode_initText(QRCode *qrcode, uint8_t *modules, uint8_t version, uint8_
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool qrcode_getModule(QRCode *qrcode, uint8_t x, uint8_t y) {
|
bool qrcode_getModule(QRCode *qrcode, uint8_t x, uint8_t y) {
|
||||||
if (x < 0 || x >= qrcode->size || y < 0 || y >= qrcode->size) {
|
if ( x >= qrcode->size || y >= qrcode->size) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -873,4 +873,4 @@ uint8_t qrcode_getHexLength(QRCode *qrcode) {
|
|||||||
void qrcode_getHex(QRCode *qrcode, char *result) {
|
void qrcode_getHex(QRCode *qrcode, char *result) {
|
||||||
|
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
@@ -109,7 +109,7 @@ void Manager::feed(const Frame& frame) {
|
|||||||
|
|
||||||
switch(state) {
|
switch(state) {
|
||||||
case State::NoTouch:
|
case State::NoTouch:
|
||||||
if( touch_stable && touch_pressure ) {
|
if( touch_stable && touch_pressure && !persistent_memory::disable_touchscreen()) {
|
||||||
if( point_stable() ) {
|
if( point_stable() ) {
|
||||||
state = State::TouchDetected;
|
state = State::TouchDetected;
|
||||||
touch_started();
|
touch_started();
|
||||||
|
@@ -23,6 +23,7 @@
|
|||||||
#include "ui_qrcode.hpp"
|
#include "ui_qrcode.hpp"
|
||||||
#include "qrcodegen.hpp"
|
#include "qrcodegen.hpp"
|
||||||
#include "portapack.hpp"
|
#include "portapack.hpp"
|
||||||
|
#include "portapack_persistent_memory.hpp"
|
||||||
|
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
@@ -42,26 +43,74 @@ QRCodeImage::QRCodeImage(
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QRCodeImage::~QRCodeImage( )
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
QRCodeImage::QRCodeImage(const QRCodeImage&Image) : Widget { }
|
||||||
|
{
|
||||||
|
(void)Image;
|
||||||
|
}
|
||||||
|
|
||||||
|
QRCodeImage & QRCodeImage::operator=(const QRCodeImage&Image)
|
||||||
|
{
|
||||||
|
(void)Image;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
void QRCodeImage::paint(Painter& painter) {
|
void QRCodeImage::paint(Painter& painter) {
|
||||||
|
|
||||||
|
(void)painter ;
|
||||||
|
|
||||||
// The structure to manage the QR code
|
// The structure to manage the QR code
|
||||||
QRCode qrcode;
|
QRCode qrcode;
|
||||||
int qr_version = 10; // bigger versions aren't handled very well
|
|
||||||
|
|
||||||
// Allocate a chunk of memory to store the QR code
|
|
||||||
uint8_t qrcodeBytes[qrcode_getBufferSize(qr_version)];
|
|
||||||
|
|
||||||
qrcode_initText(&qrcode, qrcodeBytes, qr_version, ECC_HIGH, qr_text_);
|
|
||||||
|
|
||||||
|
|
||||||
display.fill_rectangle(Rect(92, 97, 63, 63), Color::white());
|
//Either small or large QR code can be shown..
|
||||||
|
|
||||||
for (uint8_t y = 0; y < qrcode.size; y++) {
|
if(portapack::persistent_memory::show_bigger_qr_code()) { // show large QR code
|
||||||
for (uint8_t x = 0; x < qrcode.size; x++) {
|
int qr_version = 2;
|
||||||
if (qrcode_getModule(&qrcode, x, y)) {
|
|
||||||
display.draw_pixel(Point(95+x,100+y), Color::black());
|
// Allocate a chunk of memory to store the QR code
|
||||||
|
uint8_t qrcodeBytes[qrcode_getBufferSize(qr_version)];
|
||||||
|
|
||||||
|
qrcode_initText(&qrcode, qrcodeBytes, qr_version, ECC_HIGH, qr_text_);
|
||||||
|
|
||||||
|
|
||||||
|
display.fill_rectangle(Rect(10, 30, 220, 220), Color::white());
|
||||||
|
|
||||||
|
for (uint8_t y = 0; y < qrcode.size; y++) {
|
||||||
|
for (uint8_t x = 0; x < qrcode.size; x++) {
|
||||||
|
if (qrcode_getModule(&qrcode, x, y)) {
|
||||||
|
display.fill_rectangle(Rect(20+(x*8), 40+(y*8), 8, 8), Color::black());
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
else { // show small QR code
|
||||||
|
int qr_version = 10;
|
||||||
|
|
||||||
|
// Allocate a chunk of memory to store the QR code
|
||||||
|
uint8_t qrcodeBytes[qrcode_getBufferSize(qr_version)];
|
||||||
|
|
||||||
|
qrcode_initText(&qrcode, qrcodeBytes, qr_version, ECC_HIGH, qr_text_);
|
||||||
|
|
||||||
|
|
||||||
|
display.fill_rectangle(Rect(92, 97, 63, 63), Color::white());
|
||||||
|
|
||||||
|
for (uint8_t y = 0; y < qrcode.size; y++) {
|
||||||
|
for (uint8_t x = 0; x < qrcode.size; x++) {
|
||||||
|
if (qrcode_getModule(&qrcode, x, y)) {
|
||||||
|
display.draw_pixel(Point(95+x,100+y), Color::black());
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -84,10 +133,9 @@ QRCodeView::QRCodeView(
|
|||||||
|
|
||||||
|
|
||||||
add_children({
|
add_children({
|
||||||
&text_qr,
|
|
||||||
&qr_code,
|
&qr_code,
|
||||||
&button_close});
|
&button_close});
|
||||||
text_qr.set(qr_text);
|
//text_qr.set(qr_text);
|
||||||
qr_code.set_text(qr_text);
|
qr_code.set_text(qr_text);
|
||||||
|
|
||||||
button_close.on_select = [&nav](Button&){
|
button_close.on_select = [&nav](Button&){
|
||||||
|
@@ -40,10 +40,13 @@ public:
|
|||||||
qr_text_ = qr_text;
|
qr_text_ = qr_text;
|
||||||
}
|
}
|
||||||
void paint(Painter& painter) override;
|
void paint(Painter& painter) override;
|
||||||
|
// for -weffc++ to be killed
|
||||||
|
~QRCodeImage(); // destructor
|
||||||
|
QRCodeImage(const QRCodeImage&Image);
|
||||||
|
QRCodeImage & operator=(const QRCodeImage &Image); // assignment
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const char * qr_text_ ;
|
const char * qr_text_ = NULL ;
|
||||||
};
|
};
|
||||||
|
|
||||||
class QRCodeView : public View {
|
class QRCodeView : public View {
|
||||||
@@ -74,13 +77,13 @@ private:
|
|||||||
{ 50, 100, 100, 100 }
|
{ 50, 100, 100, 100 }
|
||||||
};
|
};
|
||||||
|
|
||||||
Text text_qr {
|
//Text text_qr {
|
||||||
{ 0 * 8, 10 * 16, 32 * 8, 1 * 8 },
|
// { 0 * 8, 10 * 16, 32 * 8, 1 * 8 },
|
||||||
"-"
|
// "-"
|
||||||
};
|
//};
|
||||||
|
|
||||||
Button button_close {
|
Button button_close {
|
||||||
{ 9 * 8, 15 * 16, 12 * 8, 3 * 16 },
|
{ 9 * 8, 31 * 8, 12 * 8, 3 * 16 },
|
||||||
"Back"
|
"Back"
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
@@ -465,8 +465,11 @@ void NavigationView::focus() {
|
|||||||
/* ReceiversMenuView *****************************************************/
|
/* ReceiversMenuView *****************************************************/
|
||||||
|
|
||||||
ReceiversMenuView::ReceiversMenuView(NavigationView& nav) {
|
ReceiversMenuView::ReceiversMenuView(NavigationView& nav) {
|
||||||
add_items({
|
if( portapack::persistent_memory::show_gui_return_icon() )
|
||||||
//{ "..", ui::Color::light_grey(),&bitmap_icon_previous, [&nav](){ nav.pop(); } },
|
{
|
||||||
|
add_items( { { "..", ui::Color::light_grey(),&bitmap_icon_previous , [&nav](){ nav.pop(); } } } );
|
||||||
|
}
|
||||||
|
add_items( {
|
||||||
{ "ADS-B", ui::Color::green(), &bitmap_icon_adsb, [&nav](){ nav.push<ADSBRxView>(); }, },
|
{ "ADS-B", ui::Color::green(), &bitmap_icon_adsb, [&nav](){ nav.push<ADSBRxView>(); }, },
|
||||||
//{ "ACARS", ui::Color::yellow(), &bitmap_icon_adsb, [&nav](){ nav.push<ACARSAppView>(); }, },
|
//{ "ACARS", ui::Color::yellow(), &bitmap_icon_adsb, [&nav](){ nav.push<ACARSAppView>(); }, },
|
||||||
{ "AIS Boats", ui::Color::green(), &bitmap_icon_ais, [&nav](){ nav.push<AISAppView>(); } },
|
{ "AIS Boats", ui::Color::green(), &bitmap_icon_ais, [&nav](){ nav.push<AISAppView>(); } },
|
||||||
@@ -486,16 +489,19 @@ ReceiversMenuView::ReceiversMenuView(NavigationView& nav) {
|
|||||||
{ "LoRa", ui::Color::dark_grey(), &bitmap_icon_lora, [&nav](){ nav.push<NotImplementedView>(); } },
|
{ "LoRa", ui::Color::dark_grey(), &bitmap_icon_lora, [&nav](){ nav.push<NotImplementedView>(); } },
|
||||||
{ "SSTV", ui::Color::dark_grey(), &bitmap_icon_sstv, [&nav](){ nav.push<NotImplementedView>(); } },
|
{ "SSTV", ui::Color::dark_grey(), &bitmap_icon_sstv, [&nav](){ nav.push<NotImplementedView>(); } },
|
||||||
{ "TETRA", ui::Color::dark_grey(), &bitmap_icon_tetra, [&nav](){ nav.push<NotImplementedView>(); } },*/
|
{ "TETRA", ui::Color::dark_grey(), &bitmap_icon_tetra, [&nav](){ nav.push<NotImplementedView>(); } },*/
|
||||||
});
|
} );
|
||||||
|
|
||||||
//set_highlighted(4); // Default selection is "Audio"
|
//set_highlighted(0); // Default selection is "Audio"
|
||||||
}
|
}
|
||||||
|
|
||||||
/* TransmittersMenuView **************************************************/
|
/* TransmittersMenuView **************************************************/
|
||||||
|
|
||||||
TransmittersMenuView::TransmittersMenuView(NavigationView& nav) {
|
TransmittersMenuView::TransmittersMenuView(NavigationView& nav) {
|
||||||
add_items({
|
if( portapack::persistent_memory::show_gui_return_icon() )
|
||||||
//{ "..", ui::Color::light_grey(),&bitmap_icon_previous, [&nav](){ nav.pop(); } },
|
{
|
||||||
|
add_items( { { "..", ui::Color::light_grey(),&bitmap_icon_previous , [&nav](){ nav.pop(); } } } );
|
||||||
|
}
|
||||||
|
add_items({
|
||||||
{ "ADS-B [S]", ui::Color::yellow(), &bitmap_icon_adsb, [&nav](){ nav.push<ADSBTxView>(); } },
|
{ "ADS-B [S]", ui::Color::yellow(), &bitmap_icon_adsb, [&nav](){ nav.push<ADSBTxView>(); } },
|
||||||
{ "APRS", ui::Color::green(), &bitmap_icon_aprs, [&nav](){ nav.push<APRSTXView>(); } },
|
{ "APRS", ui::Color::green(), &bitmap_icon_aprs, [&nav](){ nav.push<APRSTXView>(); } },
|
||||||
{ "BHT Xy/EP", ui::Color::green(), &bitmap_icon_bht, [&nav](){ nav.push<BHTView>(); } },
|
{ "BHT Xy/EP", ui::Color::green(), &bitmap_icon_bht, [&nav](){ nav.push<BHTView>(); } },
|
||||||
@@ -522,18 +528,21 @@ TransmittersMenuView::TransmittersMenuView(NavigationView& nav) {
|
|||||||
/* UtilitiesMenuView *****************************************************/
|
/* UtilitiesMenuView *****************************************************/
|
||||||
|
|
||||||
UtilitiesMenuView::UtilitiesMenuView(NavigationView& nav) {
|
UtilitiesMenuView::UtilitiesMenuView(NavigationView& nav) {
|
||||||
|
if( portapack::persistent_memory::show_gui_return_icon() )
|
||||||
|
{
|
||||||
|
add_items( { { "..", ui::Color::light_grey(),&bitmap_icon_previous , [&nav](){ nav.pop(); } } } );
|
||||||
|
}
|
||||||
add_items({
|
add_items({
|
||||||
//{ "Test app", ui::Color::dark_grey(), nullptr, [&nav](){ nav.push<TestView>(); } },
|
//{ "Test app", ui::Color::dark_grey(), nullptr, [&nav](){ nav.push<TestView>(); } },
|
||||||
//{ "..", ui::Color::light_grey(),&bitmap_icon_previous, [&nav](){ nav.pop(); } },
|
{ "Freq. manager", ui::Color::green(), &bitmap_icon_freqman, [&nav](){ nav.push<FrequencyManagerView>(); } },
|
||||||
{ "Freq manager", ui::Color::green(), &bitmap_icon_freqman, [&nav](){ nav.push<FrequencyManagerView>(); } },
|
|
||||||
{ "File manager", ui::Color::yellow(), &bitmap_icon_dir, [&nav](){ nav.push<FileManagerView>(); } },
|
{ "File manager", ui::Color::yellow(), &bitmap_icon_dir, [&nav](){ nav.push<FileManagerView>(); } },
|
||||||
//{ "Notepad", ui::Color::dark_grey(), &bitmap_icon_notepad, [&nav](){ nav.push<NotImplementedView>(); } },
|
//{ "Notepad", ui::Color::dark_grey(), &bitmap_icon_notepad, [&nav](){ nav.push<NotImplementedView>(); } },
|
||||||
{ "Signal gen", ui::Color::green(), &bitmap_icon_cwgen, [&nav](){ nav.push<SigGenView>(); } },
|
{ "Signal gen", ui::Color::green(), &bitmap_icon_cwgen, [&nav](){ nav.push<SigGenView>(); } },
|
||||||
//{ "Tone search", ui::Color::dark_grey(), nullptr, [&nav](){ nav.push<ToneSearchView>(); } },
|
//{ "Tone search", ui::Color::dark_grey(), nullptr, [&nav](){ nav.push<ToneSearchView>(); } },
|
||||||
{ "Wave viewer", ui::Color::yellow(), &bitmap_icon_soundboard, [&nav](){ nav.push<ViewWavView>(); } },
|
{ "WAV viewer", ui::Color::yellow(), &bitmap_icon_soundboard, [&nav](){ nav.push<ViewWavView>(); } },
|
||||||
{ "Antenna length", ui::Color::green(), &bitmap_icon_tools_antenna, [&nav](){ nav.push<WhipCalcView>(); } },
|
{ "Antenna length", ui::Color::green(), &bitmap_icon_tools_antenna, [&nav](){ nav.push<WhipCalcView>(); } },
|
||||||
{ "Wipe SD card", ui::Color::red(), &bitmap_icon_tools_wipesd, [&nav](){ nav.push<WipeSDView>(); } },
|
|
||||||
|
|
||||||
|
{ "Wipe SD card", ui::Color::red(), &bitmap_icon_tools_wipesd, [&nav](){ nav.push<WipeSDView>(); } },
|
||||||
});
|
});
|
||||||
set_max_rows(2); // allow wider buttons
|
set_max_rows(2); // allow wider buttons
|
||||||
}
|
}
|
||||||
@@ -557,12 +566,12 @@ SystemMenuView::SystemMenuView(NavigationView& nav) {
|
|||||||
{ "Transmit", ui::Color::cyan(), &bitmap_icon_transmit, [&nav](){ nav.push<TransmittersMenuView>(); } },
|
{ "Transmit", ui::Color::cyan(), &bitmap_icon_transmit, [&nav](){ nav.push<TransmittersMenuView>(); } },
|
||||||
{ "Capture", ui::Color::red(), &bitmap_icon_capture, [&nav](){ nav.push<CaptureAppView>(); } },
|
{ "Capture", ui::Color::red(), &bitmap_icon_capture, [&nav](){ nav.push<CaptureAppView>(); } },
|
||||||
{ "Replay", ui::Color::green(), &bitmap_icon_replay, [&nav](){ nav.push<ReplayAppView>(); } },
|
{ "Replay", ui::Color::green(), &bitmap_icon_replay, [&nav](){ nav.push<ReplayAppView>(); } },
|
||||||
{ "Calls", ui::Color::yellow(), &bitmap_icon_search, [&nav](){ nav.push<SearchView>(); } },
|
{ "Search", ui::Color::yellow(), &bitmap_icon_search, [&nav](){ nav.push<SearchView>(); } },
|
||||||
{ "Scanner", ui::Color::yellow(), &bitmap_icon_scanner, [&nav](){ nav.push<ScannerView>(); } },
|
{ "Scanner", ui::Color::yellow(), &bitmap_icon_scanner, [&nav](){ nav.push<ScannerView>(); } },
|
||||||
{ "Microphone", ui::Color::yellow(), &bitmap_icon_microphone,[&nav](){ nav.push<MicTXView>(); } },
|
{ "Microphone", ui::Color::yellow(), &bitmap_icon_microphone,[&nav](){ nav.push<MicTXView>(); } },
|
||||||
{ "Looking Glass", ui::Color::yellow(), &bitmap_icon_looking, [&nav](){ nav.push<GlassView>(); } },
|
{ "Looking Glass", ui::Color::yellow(), &bitmap_icon_looking, [&nav](){ nav.push<GlassView>(); } },
|
||||||
{ "Tools", ui::Color::cyan(), &bitmap_icon_utilities, [&nav](){ nav.push<UtilitiesMenuView>(); } },
|
{ "Utilities", ui::Color::cyan(), &bitmap_icon_utilities, [&nav](){ nav.push<UtilitiesMenuView>(); } },
|
||||||
{ "Options", ui::Color::cyan(), &bitmap_icon_setup, [&nav](){ nav.push<SettingsMenuView>(); } },
|
{ "Settings", ui::Color::cyan(), &bitmap_icon_setup, [&nav](){ nav.push<SettingsMenuView>(); } },
|
||||||
{ "Debug", ui::Color::light_grey(), &bitmap_icon_debug, [&nav](){ nav.push<DebugMenuView>(); } },
|
{ "Debug", ui::Color::light_grey(), &bitmap_icon_debug, [&nav](){ nav.push<DebugMenuView>(); } },
|
||||||
{ "HackRF", ui::Color::cyan(), &bitmap_icon_hackrf, [this, &nav](){ hackrf_mode(nav); } },
|
{ "HackRF", ui::Color::cyan(), &bitmap_icon_hackrf, [this, &nav](){ hackrf_mode(nav); } },
|
||||||
//{ "About", ui::Color::cyan(), nullptr, [&nav](){ nav.push<AboutView>(); } }
|
//{ "About", ui::Color::cyan(), nullptr, [&nav](){ nav.push<AboutView>(); } }
|
||||||
|
@@ -190,7 +190,7 @@ namespace ui
|
|||||||
void on_speaker();
|
void on_speaker();
|
||||||
void on_stealth();
|
void on_stealth();
|
||||||
void on_bias_tee();
|
void on_bias_tee();
|
||||||
//void on_textentry();
|
// void on_textentry();
|
||||||
void on_camera();
|
void on_camera();
|
||||||
void on_title();
|
void on_title();
|
||||||
void refresh();
|
void refresh();
|
||||||
@@ -212,7 +212,7 @@ namespace ui
|
|||||||
void refresh();
|
void refresh();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static constexpr auto version_string = "v1.4.4";
|
// static constexpr auto version_string = "v1.4.4"; // This is commented out as we are now setting the version via ENV (VERSION_STRING=v1.0.0)
|
||||||
NavigationView &nav_;
|
NavigationView &nav_;
|
||||||
|
|
||||||
Rectangle backdrop{
|
Rectangle backdrop{
|
||||||
@@ -221,7 +221,7 @@ namespace ui
|
|||||||
|
|
||||||
Text version{
|
Text version{
|
||||||
{2, 0, 11 * 8, 16},
|
{2, 0, 11 * 8, 16},
|
||||||
version_string};
|
VERSION_STRING};
|
||||||
|
|
||||||
LiveDateTime ltime{
|
LiveDateTime ltime{
|
||||||
{86, 0, 19 * 8, 16}};
|
{86, 0, 19 * 8, 16}};
|
||||||
@@ -248,14 +248,14 @@ namespace ui
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
ReceiversMenuView(NavigationView &nav);
|
ReceiversMenuView(NavigationView &nav);
|
||||||
std::string title() const override { return "Receivers"; };
|
std::string title() const override { return "Receive"; };
|
||||||
};
|
};
|
||||||
|
|
||||||
class TransmittersMenuView : public BtnGridView
|
class TransmittersMenuView : public BtnGridView
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
TransmittersMenuView(NavigationView &nav);
|
TransmittersMenuView(NavigationView &nav);
|
||||||
std::string title() const override { return "Transmitters"; };
|
std::string title() const override { return "Transmit"; };
|
||||||
};
|
};
|
||||||
|
|
||||||
class UtilitiesMenuView : public BtnGridView
|
class UtilitiesMenuView : public BtnGridView
|
||||||
|
@@ -38,6 +38,8 @@ public:
|
|||||||
|
|
||||||
void focus() override;
|
void focus() override;
|
||||||
|
|
||||||
|
std::string title() const override { return "SD Card"; };
|
||||||
|
|
||||||
private:
|
private:
|
||||||
SignalToken sd_card_status_signal_token { };
|
SignalToken sd_card_status_signal_token { };
|
||||||
|
|
||||||
|
@@ -35,8 +35,8 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
uint8_t n = 0;
|
uint8_t n = 0;
|
||||||
SOSFilter<5> sos_i;
|
SOSFilter<5> sos_i = {};
|
||||||
SOSFilter<5> sos_q;
|
SOSFilter<5> sos_q = {};
|
||||||
};
|
};
|
||||||
|
|
||||||
} /* namespace dsp */
|
} /* namespace dsp */
|
||||||
|
@@ -21,6 +21,8 @@
|
|||||||
|
|
||||||
#include "dsp_modulate.hpp"
|
#include "dsp_modulate.hpp"
|
||||||
#include "sine_table_int8.hpp"
|
#include "sine_table_int8.hpp"
|
||||||
|
#include "portapack_shared_memory.hpp"
|
||||||
|
#include "tonesets.hpp"
|
||||||
|
|
||||||
namespace dsp {
|
namespace dsp {
|
||||||
namespace modulate {
|
namespace modulate {
|
||||||
@@ -40,13 +42,42 @@ void Modulator::set_over(uint32_t new_over) {
|
|||||||
over = new_over;
|
over = new_over;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Modulator::set_gain_vumeter_beep(float new_audio_gain , bool new_play_beep ) {
|
||||||
|
audio_gain = new_audio_gain ;
|
||||||
|
play_beep = new_play_beep;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t Modulator::apply_beep(int32_t sample_in, bool& configured_in, uint32_t& new_beep_index, uint32_t& new_beep_timer, TXProgressMessage& new_txprogress_message ) {
|
||||||
|
|
||||||
|
if (play_beep) { // We need to add audio beep sample.
|
||||||
|
if (new_beep_timer) {
|
||||||
|
new_beep_timer--;
|
||||||
|
} else {
|
||||||
|
new_beep_timer = baseband_fs * 0.05; // 50ms
|
||||||
|
|
||||||
|
if (new_beep_index == BEEP_TONES_NB) {
|
||||||
|
configured_in = false;
|
||||||
|
shared_memory.application_queue.push(new_txprogress_message);
|
||||||
|
} else {
|
||||||
|
beep_gen.configure(beep_deltas[new_beep_index], 1.0); // config sequentially the audio beep tone.
|
||||||
|
new_beep_index++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sample_in = beep_gen.process(0); // Get sample of the selected sequence of 6 beep tones , and overwrite audio sample. Mix 0%.
|
||||||
|
}
|
||||||
|
return sample_in; // Return audio mic scaled with gain , 8 bit sample or audio beep sample.
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
///
|
///
|
||||||
|
|
||||||
SSB::SSB() : hilbert() {
|
SSB::SSB() : hilbert() {
|
||||||
mode = Mode::LSB;
|
mode = Mode::LSB;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SSB::execute(const buffer_s16_t& audio, const buffer_c8_t& buffer) {
|
void SSB::execute(const buffer_s16_t& audio, const buffer_c8_t& buffer, bool& configured_in, uint32_t& new_beep_index, uint32_t& new_beep_timer,TXProgressMessage& new_txprogress_message, AudioLevelReportMessage& new_level_message, uint32_t& new_power_acc_count, uint32_t& new_divider ) {
|
||||||
|
// No way to activate correctly the roger beep in this option, Maybe not enough M4 CPU power , Let's block roger beep in SSB selection by now .
|
||||||
int32_t sample = 0;
|
int32_t sample = 0;
|
||||||
int8_t re = 0, im = 0;
|
int8_t re = 0, im = 0;
|
||||||
|
|
||||||
@@ -55,7 +86,9 @@ void SSB::execute(const buffer_s16_t& audio, const buffer_c8_t& buffer) {
|
|||||||
float i = 0.0, q = 0.0;
|
float i = 0.0, q = 0.0;
|
||||||
|
|
||||||
sample = audio.p[counter / over] >> 2;
|
sample = audio.p[counter / over] >> 2;
|
||||||
//switch (mode) {
|
sample *= audio_gain; // Apply GAIN Scale factor to the audio TX modulation.
|
||||||
|
|
||||||
|
//switch (mode) {
|
||||||
//case Mode::LSB:
|
//case Mode::LSB:
|
||||||
hilbert.execute(sample / 32768.0f, i, q);
|
hilbert.execute(sample / 32768.0f, i, q);
|
||||||
//case Mode::USB: hilbert.execute(sample / 32768.0f, q, i);
|
//case Mode::USB: hilbert.execute(sample / 32768.0f, q, i);
|
||||||
@@ -72,9 +105,23 @@ void SSB::execute(const buffer_s16_t& audio, const buffer_c8_t& buffer) {
|
|||||||
//re = q;
|
//re = q;
|
||||||
//im = i;
|
//im = i;
|
||||||
//break;
|
//break;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
buffer.p[counter] = { re, im };
|
buffer.p[counter] = { re, im };
|
||||||
|
|
||||||
|
// Update vu-meter bar in the LCD screen.
|
||||||
|
power_acc += (sample < 0) ? -sample : sample; // Power average for UI vu-meter
|
||||||
|
|
||||||
|
if (new_power_acc_count) {
|
||||||
|
new_power_acc_count--;
|
||||||
|
} else { // power_acc_count = 0
|
||||||
|
new_power_acc_count = new_divider;
|
||||||
|
new_level_message.value = power_acc / (new_divider *8); // Why ? . This division is to adj vu-meter sentitivity, to match saturation point to red-muter .
|
||||||
|
shared_memory.application_queue.push(new_level_message);
|
||||||
|
power_acc = 0;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -88,15 +135,39 @@ void FM::set_fm_delta(uint32_t new_delta) {
|
|||||||
fm_delta = new_delta;
|
fm_delta = new_delta;
|
||||||
}
|
}
|
||||||
|
|
||||||
void FM::execute(const buffer_s16_t& audio, const buffer_c8_t& buffer) {
|
void FM::set_tone_gen_configure(const uint32_t set_delta, const float set_tone_mix_weight) {
|
||||||
|
tone_gen.configure(set_delta, set_tone_mix_weight);
|
||||||
|
}
|
||||||
|
|
||||||
|
void FM::execute(const buffer_s16_t& audio, const buffer_c8_t& buffer, bool& configured_in, uint32_t& new_beep_index, uint32_t& new_beep_timer, TXProgressMessage& new_txprogress_message, AudioLevelReportMessage& new_level_message, uint32_t& new_power_acc_count, uint32_t& new_divider ) {
|
||||||
int32_t sample = 0;
|
int32_t sample = 0;
|
||||||
int8_t re, im;
|
int8_t re, im;
|
||||||
|
|
||||||
for (size_t counter = 0; counter < buffer.count; counter++) {
|
for (size_t counter = 0; counter < buffer.count; counter++) {
|
||||||
if (counter % over == 0) {
|
|
||||||
sample = audio.p[counter / over] >> 8;
|
sample = audio.p[counter>>6] >> 8; // sample = audio.p[counter / over] >> 8; (not enough efficient running code, over = 1536000/240000= 64 )
|
||||||
delta = sample * fm_delta;
|
sample *= audio_gain; // Apply GAIN Scale factor to the audio TX modulation.
|
||||||
}
|
|
||||||
|
if (play_beep) {
|
||||||
|
sample = apply_beep(sample, configured_in, new_beep_index, new_beep_timer, new_txprogress_message ); // Apply beep -if selected - atom ,sample by sample.
|
||||||
|
} else {
|
||||||
|
// Update vu-meter bar in the LCD screen.
|
||||||
|
power_acc += (sample < 0) ? -sample : sample; // Power average for UI vu-meter
|
||||||
|
|
||||||
|
if (new_power_acc_count) {
|
||||||
|
new_power_acc_count--;
|
||||||
|
} else { // power_acc_count = 0
|
||||||
|
new_power_acc_count = new_divider;
|
||||||
|
new_level_message.value = power_acc / (new_divider / 4); // Why ? . This division is to adj vu-meter sentitivity, to match saturation point to red-muter .
|
||||||
|
shared_memory.application_queue.push(new_level_message);
|
||||||
|
power_acc = 0;
|
||||||
|
}
|
||||||
|
// TODO: pending to optimize CPU running code.
|
||||||
|
// So far , we can not handle all 3 issues at the same time (vu-meter , CTCSS, beep).
|
||||||
|
sample = tone_gen.process(sample); // Add selected Key_Tone or CTCSS subtone , atom function() , sample by sample.
|
||||||
|
}
|
||||||
|
|
||||||
|
delta = sample * fm_delta; // Modulate FM
|
||||||
|
|
||||||
phase += delta;
|
phase += delta;
|
||||||
sphase = phase >> 24;
|
sphase = phase >> 24;
|
||||||
@@ -112,16 +183,33 @@ AM::AM() {
|
|||||||
mode = Mode::AM;
|
mode = Mode::AM;
|
||||||
}
|
}
|
||||||
|
|
||||||
void AM::execute(const buffer_s16_t& audio, const buffer_c8_t& buffer) {
|
void AM::execute(const buffer_s16_t& audio, const buffer_c8_t& buffer, bool& configured_in, uint32_t& new_beep_index, uint32_t& new_beep_timer, TXProgressMessage& new_txprogress_message, AudioLevelReportMessage& new_level_message, uint32_t& new_power_acc_count, uint32_t& new_divider ) {
|
||||||
int32_t sample = 0;
|
int32_t sample = 0;
|
||||||
int8_t re = 0, im = 0;
|
int8_t re = 0, im = 0;
|
||||||
float q = 0.0;
|
float q = 0.0;
|
||||||
|
|
||||||
for (size_t counter = 0; counter < buffer.count; counter++) {
|
for (size_t counter = 0; counter < buffer.count; counter++) {
|
||||||
if (counter % 128 == 0) {
|
if (counter % 128 == 0) {
|
||||||
sample = audio.p[counter / over] >> 2;
|
sample = audio.p[counter / over] >> 2;
|
||||||
|
sample *= audio_gain; // Apply GAIN Scale factor to the audio TX modulation.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (play_beep) {
|
||||||
|
sample = apply_beep(sample, configured_in, new_beep_index, new_beep_timer, new_txprogress_message )<<5; // Apply beep -if selected - atom sample by sample.
|
||||||
|
} else {
|
||||||
|
// Update vu-meter bar in the LCD screen.
|
||||||
|
power_acc += (sample < 0) ? -sample : sample; // Power average for UI vu-meter
|
||||||
|
|
||||||
|
if (new_power_acc_count) {
|
||||||
|
new_power_acc_count--;
|
||||||
|
} else { // power_acc_count = 0
|
||||||
|
new_power_acc_count = new_divider;
|
||||||
|
new_level_message.value = power_acc / (new_divider *8); // Why ?orig / (new_divider / 4); // Why ?
|
||||||
|
shared_memory.application_queue.push(new_level_message);
|
||||||
|
power_acc = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
q = sample / 32768.0f;
|
q = sample / 32768.0f;
|
||||||
q *= 256.0f; // Original 64.0f,now x4 (+12 dB's BB_modulation in AM & DSB)
|
q *= 256.0f; // Original 64.0f,now x4 (+12 dB's BB_modulation in AM & DSB)
|
||||||
switch (mode) {
|
switch (mode) {
|
||||||
|
@@ -24,6 +24,8 @@
|
|||||||
|
|
||||||
#include "dsp_types.hpp"
|
#include "dsp_types.hpp"
|
||||||
#include "dsp_hilbert.hpp"
|
#include "dsp_hilbert.hpp"
|
||||||
|
#include "tone_gen.hpp"
|
||||||
|
#include "baseband_processor.hpp"
|
||||||
|
|
||||||
namespace dsp {
|
namespace dsp {
|
||||||
namespace modulate {
|
namespace modulate {
|
||||||
@@ -41,13 +43,28 @@ enum class Mode {
|
|||||||
|
|
||||||
class Modulator {
|
class Modulator {
|
||||||
public:
|
public:
|
||||||
virtual void execute(const buffer_s16_t& audio, const buffer_c8_t& buffer) = 0;
|
virtual void execute(const buffer_s16_t& audio, const buffer_c8_t& buffer,bool& configured_in, uint32_t& new_beep_index, uint32_t& new_beep_timer, TXProgressMessage& new_txprogress_message, AudioLevelReportMessage& new_level_message, uint32_t& new_power_acc_count, uint32_t& new_divider ) = 0;
|
||||||
virtual ~Modulator();
|
virtual ~Modulator();
|
||||||
|
|
||||||
Mode get_mode();
|
Mode get_mode();
|
||||||
void set_mode(Mode new_mode);
|
void set_mode(Mode new_mode);
|
||||||
|
|
||||||
void set_over(uint32_t new_over);
|
void set_over(uint32_t new_over);
|
||||||
|
void set_gain_vumeter_beep(float new_audio_gain , bool new_play_beep );
|
||||||
|
int32_t apply_beep(int32_t sample_in, bool& configured_in, uint32_t& new_beep_index, uint32_t& new_beep_timer, TXProgressMessage& new_txprogress_message );
|
||||||
|
float audio_gain { };
|
||||||
|
bool play_beep { false };
|
||||||
|
uint32_t power_acc_count { 0 }; // this var it is initialized from Proc_mictx.cpp
|
||||||
|
uint32_t divider { }; // this var it is initialized from Proc_mictx.cpp
|
||||||
|
uint64_t power_acc { 0 }; // it is aux Accumulated sum (Absolute sample signal) , initialitzed to zero.
|
||||||
|
AudioLevelReportMessage level_message { };
|
||||||
|
|
||||||
|
private:
|
||||||
|
static constexpr size_t baseband_fs = 1536000U;
|
||||||
|
TXProgressMessage txprogress_message { };
|
||||||
|
ToneGen beep_gen { };
|
||||||
|
uint32_t beep_index { }, beep_timer { };
|
||||||
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
uint32_t over = 1;
|
uint32_t over = 1;
|
||||||
@@ -60,7 +77,7 @@ class SSB : public Modulator {
|
|||||||
public:
|
public:
|
||||||
SSB();
|
SSB();
|
||||||
|
|
||||||
virtual void execute(const buffer_s16_t& audio, const buffer_c8_t& buffer);
|
virtual void execute(const buffer_s16_t& audio, const buffer_c8_t& buffer, bool& configured_in, uint32_t& new_beep_index, uint32_t& new_beep_timer, TXProgressMessage& new_txprogress_message, AudioLevelReportMessage& new_level_message, uint32_t& new_power_acc_count, uint32_t& new_divider );
|
||||||
|
|
||||||
private:
|
private:
|
||||||
dsp::HilbertTransform hilbert;
|
dsp::HilbertTransform hilbert;
|
||||||
@@ -72,8 +89,9 @@ class FM : public Modulator {
|
|||||||
public:
|
public:
|
||||||
FM();
|
FM();
|
||||||
|
|
||||||
virtual void execute(const buffer_s16_t& audio, const buffer_c8_t& buffer);
|
virtual void execute(const buffer_s16_t& audio, const buffer_c8_t& buffer, bool& configured_in, uint32_t& new_beep_index, uint32_t& new_beep_timer, TXProgressMessage& new_txprogress_message, AudioLevelReportMessage& new_level_message, uint32_t& new_power_acc_count, uint32_t& new_divider ) ;
|
||||||
void set_fm_delta(uint32_t new_delta);
|
void set_fm_delta(uint32_t new_delta);
|
||||||
|
void set_tone_gen_configure(const uint32_t delta, const float tone_mix_weight);
|
||||||
|
|
||||||
///
|
///
|
||||||
|
|
||||||
@@ -81,13 +99,16 @@ private:
|
|||||||
uint32_t fm_delta { 0 };
|
uint32_t fm_delta { 0 };
|
||||||
uint32_t phase { 0 }, sphase { 0 };
|
uint32_t phase { 0 }, sphase { 0 };
|
||||||
int32_t sample { 0 }, delta { };
|
int32_t sample { 0 }, delta { };
|
||||||
|
ToneGen tone_gen { };
|
||||||
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class AM : public Modulator {
|
class AM : public Modulator {
|
||||||
public:
|
public:
|
||||||
AM();
|
AM();
|
||||||
|
|
||||||
virtual void execute(const buffer_s16_t& audio, const buffer_c8_t& buffer);
|
virtual void execute(const buffer_s16_t& audio, const buffer_c8_t& buffer, bool& configured_in, uint32_t& new_beep_index, uint32_t& new_beep_timer, TXProgressMessage& new_txprogress_message, AudioLevelReportMessage& new_level_message, uint32_t& new_power_acc_count, uint32_t& new_divider );
|
||||||
};
|
};
|
||||||
|
|
||||||
} /* namespace modulate */
|
} /* namespace modulate */
|
||||||
|
@@ -120,7 +120,7 @@ void ADSBRXProcessor::execute(const buffer_c8_t& buffer) {
|
|||||||
// the high levels as signals can be out of phase so part of the
|
// the high levels as signals can be out of phase so part of the
|
||||||
// energy can be in the near samples
|
// energy can be in the near samples
|
||||||
int32_t thisAmp = (shifter[1] + shifter[3] + shifter[8] + shifter[10]);
|
int32_t thisAmp = (shifter[1] + shifter[3] + shifter[8] + shifter[10]);
|
||||||
int32_t high = thisAmp / 9;
|
uint32_t high = thisAmp / 9;
|
||||||
if (
|
if (
|
||||||
shifter[5] < high &&
|
shifter[5] < high &&
|
||||||
shifter[6] < high &&
|
shifter[6] < high &&
|
||||||
|
@@ -125,18 +125,18 @@ private:
|
|||||||
uint32_t sample_bits { 0 };
|
uint32_t sample_bits { 0 };
|
||||||
uint32_t phase { }, phase_inc { };
|
uint32_t phase { }, phase_inc { };
|
||||||
int32_t sample_mixed { }, prev_mixed { }, sample_filtered { }, prev_filtered { };
|
int32_t sample_mixed { }, prev_mixed { }, sample_filtered { }, prev_filtered { };
|
||||||
uint8_t last_bit;
|
uint8_t last_bit = 0;
|
||||||
uint8_t ones_count = 0;
|
uint8_t ones_count = 0 ;
|
||||||
uint8_t current_byte = 0;
|
uint8_t current_byte = 0;
|
||||||
uint8_t byte_index = 0;
|
uint8_t byte_index = 0;
|
||||||
uint8_t packet_buffer[256];
|
uint8_t packet_buffer[256];
|
||||||
size_t packet_buffer_size = 0;
|
size_t packet_buffer_size = 0;
|
||||||
|
|
||||||
bool configured { false };
|
bool configured { false };
|
||||||
bool wait_start { };
|
bool wait_start { 0 };
|
||||||
bool bit_value { };
|
bool bit_value { 0 };
|
||||||
|
|
||||||
aprs::APRSPacket aprs_packet;
|
aprs::APRSPacket aprs_packet { };
|
||||||
|
|
||||||
void configure(const APRSRxConfigureMessage& message);
|
void configure(const APRSRxConfigureMessage& message);
|
||||||
void capture_config(const CaptureConfigMessage& message);
|
void capture_config(const CaptureConfigMessage& message);
|
||||||
|
@@ -35,8 +35,10 @@ void MicTXProcessor::execute(const buffer_c8_t& buffer){
|
|||||||
if (!configured) return;
|
if (!configured) return;
|
||||||
|
|
||||||
audio_input.read_audio_buffer(audio_buffer);
|
audio_input.read_audio_buffer(audio_buffer);
|
||||||
modulator->execute(audio_buffer, buffer);
|
modulator->set_gain_vumeter_beep(audio_gain, play_beep ) ;
|
||||||
|
modulator->execute(audio_buffer, buffer, configured, beep_index, beep_timer, txprogress_message, level_message, power_acc_count, divider ); // Now "Key Tones & CTCSS" baseband additon inside FM mod. dsp_modulate.cpp"
|
||||||
|
|
||||||
|
/* Original fw 1.3.1 good reference, beep and vu-meter
|
||||||
for (size_t i = 0; i < buffer.count; i++) {
|
for (size_t i = 0; i < buffer.count; i++) {
|
||||||
|
|
||||||
if (!play_beep) {
|
if (!play_beep) {
|
||||||
@@ -67,13 +69,13 @@ void MicTXProcessor::execute(const buffer_c8_t& buffer){
|
|||||||
beep_index++;
|
beep_index++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
sample = beep_gen.process(0); // TODO : Pending how to move inside modulate.cpp
|
||||||
sample = beep_gen.process(0);
|
}
|
||||||
}
|
*/
|
||||||
|
|
||||||
/*
|
/* Original fw 1.3.1 good reference FM moulation version, including "key tones CTCSS" fw 1.3.1
|
||||||
sample = tone_gen.process(sample);
|
sample = tone_gen.process(sample);
|
||||||
|
|
||||||
// FM
|
// FM
|
||||||
if (configured) {
|
if (configured) {
|
||||||
delta = sample * fm_delta;
|
delta = sample * fm_delta;
|
||||||
@@ -89,8 +91,8 @@ void MicTXProcessor::execute(const buffer_c8_t& buffer){
|
|||||||
}
|
}
|
||||||
|
|
||||||
buffer.p[i] = { re, im };
|
buffer.p[i] = { re, im };
|
||||||
*/
|
|
||||||
}
|
} */
|
||||||
}
|
}
|
||||||
|
|
||||||
void MicTXProcessor::on_message(const Message* const msg) {
|
void MicTXProcessor::on_message(const Message* const msg) {
|
||||||
@@ -100,12 +102,16 @@ void MicTXProcessor::on_message(const Message* const msg) {
|
|||||||
switch(msg->id) {
|
switch(msg->id) {
|
||||||
case Message::ID::AudioTXConfig:
|
case Message::ID::AudioTXConfig:
|
||||||
if (fm_enabled) {
|
if (fm_enabled) {
|
||||||
dsp::modulate::FM *fm = new dsp::modulate::FM();
|
dsp::modulate::FM *fm = new dsp::modulate::FM();
|
||||||
|
|
||||||
fm->set_fm_delta(config_message.deviation_hz * (0xFFFFFFUL / baseband_fs));
|
// Config fm_delta private var inside DSP modulate.cpp
|
||||||
|
fm->set_fm_delta(config_message.deviation_hz * (0xFFFFFFUL / baseband_fs));
|
||||||
|
|
||||||
|
// Config properly the private tone_gen function parameters inside DSP modulate.cpp
|
||||||
|
fm->set_tone_gen_configure(config_message.tone_key_delta, config_message.tone_key_mix_weight);
|
||||||
modulator = fm;
|
modulator = fm;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (usb_enabled) {
|
if (usb_enabled) {
|
||||||
modulator = new dsp::modulate::SSB();
|
modulator = new dsp::modulate::SSB();
|
||||||
modulator->set_mode(dsp::modulate::Mode::USB);
|
modulator->set_mode(dsp::modulate::Mode::USB);
|
||||||
@@ -124,7 +130,7 @@ void MicTXProcessor::on_message(const Message* const msg) {
|
|||||||
modulator->set_mode(dsp::modulate::Mode::DSB);
|
modulator->set_mode(dsp::modulate::Mode::DSB);
|
||||||
}
|
}
|
||||||
|
|
||||||
modulator->set_over(baseband_fs / 24000);
|
modulator->set_over(baseband_fs / 24000); // Keep no change.
|
||||||
|
|
||||||
am_enabled = config_message.am_enabled;
|
am_enabled = config_message.am_enabled;
|
||||||
usb_enabled = config_message.usb_enabled;
|
usb_enabled = config_message.usb_enabled;
|
||||||
@@ -137,8 +143,9 @@ void MicTXProcessor::on_message(const Message* const msg) {
|
|||||||
audio_gain = config_message.audio_gain;
|
audio_gain = config_message.audio_gain;
|
||||||
divider = config_message.divider;
|
divider = config_message.divider;
|
||||||
power_acc_count = 0;
|
power_acc_count = 0;
|
||||||
|
|
||||||
tone_gen.configure(config_message.tone_key_delta, config_message.tone_key_mix_weight);
|
// now this config moved, in the case Message::ID::AudioTXConfig , only FM case.
|
||||||
|
// tone_gen.configure(config_message.tone_key_delta, config_message.tone_key_mix_weight);
|
||||||
|
|
||||||
txprogress_message.done = true;
|
txprogress_message.done = true;
|
||||||
|
|
||||||
|
@@ -49,9 +49,9 @@ private:
|
|||||||
};
|
};
|
||||||
|
|
||||||
AudioInput audio_input { };
|
AudioInput audio_input { };
|
||||||
ToneGen tone_gen { };
|
// ToneGen tone_gen { }; moved to dsp_modulate.cpp
|
||||||
ToneGen beep_gen { };
|
// ToneGen beep_gen { }; moved to dsp_modulate.cpp
|
||||||
dsp::modulate::Modulator *modulator;
|
dsp::modulate::Modulator *modulator = NULL ;
|
||||||
|
|
||||||
bool am_enabled { false };
|
bool am_enabled { false };
|
||||||
bool fm_enabled { true };
|
bool fm_enabled { true };
|
||||||
|
@@ -68,6 +68,16 @@ public:
|
|||||||
delete[] m_lastVals;
|
delete[] m_lastVals;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SmoothVals(const SmoothVals<float, float>&)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
SmoothVals & operator=(const SmoothVals<float, float>&)
|
||||||
|
{
|
||||||
|
return *this ;
|
||||||
|
}
|
||||||
|
|
||||||
// --------------------------------------------------
|
// --------------------------------------------------
|
||||||
// Set size of smoothing
|
// Set size of smoothing
|
||||||
// --------------------------------------------------
|
// --------------------------------------------------
|
||||||
@@ -154,7 +164,7 @@ private:
|
|||||||
dsp::decimate::FIRC16xR16x32Decim8 decim_1 { };
|
dsp::decimate::FIRC16xR16x32Decim8 decim_1 { };
|
||||||
dsp::decimate::FIRAndDecimateComplex channel_filter { };
|
dsp::decimate::FIRAndDecimateComplex channel_filter { };
|
||||||
dsp::demodulate::FM demod { };
|
dsp::demodulate::FM demod { };
|
||||||
SmoothVals<float, float> smooth;
|
SmoothVals<float, float> smooth = { };
|
||||||
|
|
||||||
AudioOutput audio_output { };
|
AudioOutput audio_output { };
|
||||||
|
|
||||||
|
@@ -103,27 +103,13 @@ void SpectrumCollector::post_message(const buffer_c16_t& data) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 3 types of Windowing time domain shapes declaration , but only used Hamming , shapes for FFT
|
template<typename T>
|
||||||
GCC10 compile sintax error c/m (1/2),
|
|
||||||
The primary diff. between const and constexpr variables is that
|
|
||||||
the initialization of a const var can be deferred until run time.
|
|
||||||
A constexpr var. must be initialized at compile time. ...
|
|
||||||
A var. can be declared with constexpr , when it has a literal type and is initialized.
|
|
||||||
GCC compile sintax error c/m (2/2)
|
|
||||||
Static assert --> Tests a software assertion at compile time for debugging.
|
|
||||||
we keep the same safety compile protection , just changing slightly the sintax checking that the size of the called array is power of 2.
|
|
||||||
if the bool "constant expression" is TRUE (normal case) , the declaration has no effect.
|
|
||||||
if the bool "constant expression" is FALSE (abnormal array size) , it is aborted the compile with a msg error.
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
template<typename T> // Although currently we are not using that Windowing shape, we apply the same GCC10 compile error c/m
|
|
||||||
static typename T::value_type spectrum_window_none(const T& s, const size_t i) {
|
static typename T::value_type spectrum_window_none(const T& s, const size_t i) {
|
||||||
static_assert(power_of_two(ARRAY_ELEMENTS(s)), "Array number of elements must be power of 2"); // c/m compile error GCC10 , OK for all GCC versions.
|
static_assert(power_of_two(ARRAY_ELEMENTS(s)), "Array number of elements must be power of 2"); // c/m compile error GCC10 , OK for all GCC versions.
|
||||||
return s[i];
|
return s[i];
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename T> // Currently we are calling and using that Window shape.
|
template<typename T>
|
||||||
static typename T::value_type spectrum_window_hamming_3(const T& s, const size_t i) {
|
static typename T::value_type spectrum_window_hamming_3(const T& s, const size_t i) {
|
||||||
static_assert(power_of_two(ARRAY_ELEMENTS(s)), "Array number of elements must be power of 2"); // c/m compile error GCC10 , OK for all GCC versions.
|
static_assert(power_of_two(ARRAY_ELEMENTS(s)), "Array number of elements must be power of 2"); // c/m compile error GCC10 , OK for all GCC versions.
|
||||||
const size_t mask = s.size() - 1; // c/m compile error GCC10 , constexpr->const
|
const size_t mask = s.size() - 1; // c/m compile error GCC10 , constexpr->const
|
||||||
@@ -131,7 +117,7 @@ static typename T::value_type spectrum_window_hamming_3(const T& s, const size_t
|
|||||||
return s[i] * 0.54f + (s[(i-1) & mask] + s[(i+1) & mask]) * -0.23f;
|
return s[i] * 0.54f + (s[(i-1) & mask] + s[(i+1) & mask]) * -0.23f;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename T> // Although currently we are not using that Windowing shape, we apply the same GCC10 compile error c/m
|
template<typename T>
|
||||||
static typename T::value_type spectrum_window_blackman_3(const T& s, const size_t i) {
|
static typename T::value_type spectrum_window_blackman_3(const T& s, const size_t i) {
|
||||||
static_assert(power_of_two(ARRAY_ELEMENTS(s)), "Array number of elements must be power of 2"); // c/m compile error GCC10 , OK for all GCC versions.
|
static_assert(power_of_two(ARRAY_ELEMENTS(s)), "Array number of elements must be power of 2"); // c/m compile error GCC10 , OK for all GCC versions.
|
||||||
const size_t mask = s.size() - 1; // c/m compile error GCC10 , constexpr->const
|
const size_t mask = s.size() - 1; // c/m compile error GCC10 , constexpr->const
|
||||||
|
@@ -24,14 +24,20 @@
|
|||||||
#include "sine_table_int8.hpp"
|
#include "sine_table_int8.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
int32_t ToneGen::tone_sine() {
|
int32_t ToneGen::tone_sine() {
|
||||||
|
// TODO : Added for Sonde App. We keep it by now , but it needs to be reviewed in Sonde
|
||||||
|
// Hoepfully we can manage without it , same as previous fw 1.3.1
|
||||||
int32_t tone_sample = sine_table_i8[tone_phase_] * 0x1000000;
|
int32_t tone_sample = sine_table_i8[tone_phase_] * 0x1000000;
|
||||||
tone_phase_ += delta_;
|
tone_phase_ += delta_;
|
||||||
|
|
||||||
return tone_sample;
|
return tone_sample;
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
int32_t ToneGen::tone_square() {
|
int32_t ToneGen::tone_square() {
|
||||||
|
// TODO : Added for Sonde App. We keep it by now , but it needs to be reviewed in Sonde
|
||||||
int32_t tone_sample = 0;
|
int32_t tone_sample = 0;
|
||||||
|
|
||||||
if(tone_phase_ < (UINT32_MAX / 2)) {
|
if(tone_phase_ < (UINT32_MAX / 2)) {
|
||||||
@@ -46,33 +52,66 @@ int32_t ToneGen::tone_square() {
|
|||||||
return tone_sample;
|
return tone_sample;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
void ToneGen::configure(const uint32_t delta, const float tone_mix_weight) {
|
void ToneGen::configure(const uint32_t delta, const float tone_mix_weight) {
|
||||||
|
// Confirmed ! It is not working well in the fw 1.4.4 Mic App , CTCSS generation, (but added for Sonde App)
|
||||||
|
// I Think it should be deleted or modified but not use it as it is in Mic App .
|
||||||
|
|
||||||
delta_ = (uint8_t) ((delta & 0xFF000000U) >> 24);
|
delta_ = (uint8_t) ((delta & 0xFF000000U) >> 24);
|
||||||
|
delta_ = delta;
|
||||||
tone_mix_weight_ = tone_mix_weight;
|
tone_mix_weight_ = tone_mix_weight;
|
||||||
input_mix_weight_ = 1.0 - tone_mix_weight;
|
input_mix_weight_ = 1.0 - tone_mix_weight;
|
||||||
|
|
||||||
current_tone_type_ = sine;
|
current_tone_type_ = sine;
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void ToneGen::configure(const uint32_t freq, const float tone_mix_weight, const tone_type tone_type, const uint32_t sample_rate) {
|
void ToneGen::configure(const uint32_t freq, const float tone_mix_weight, const tone_type tone_type, const uint32_t sample_rate) {
|
||||||
|
// TODO : Added for Sonde App. We keep it by now to avoid compile errors, but it needs to be reviewed in Sonde
|
||||||
delta_ = (uint8_t) ((freq * sizeof(sine_table_i8)) / sample_rate);
|
delta_ = (uint8_t) ((freq * sizeof(sine_table_i8)) / sample_rate);
|
||||||
tone_mix_weight_ = tone_mix_weight;
|
tone_mix_weight_ = tone_mix_weight;
|
||||||
input_mix_weight_ = 1.0 - tone_mix_weight;
|
input_mix_weight_ = 1.0 - tone_mix_weight;
|
||||||
current_tone_type_ = tone_type;
|
current_tone_type_ = tone_type;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// ----Original available core SW code from fw 1.3.1 , Working also well in Mic App CTCSS Gen from fw 1.4.0 onwards
|
||||||
|
|
||||||
|
// Original direct-look-up synthesis algorithm with Fractional delta phase. It is OK
|
||||||
|
// Delta and Accumulator fase are stored in 32 bits (4 bytes), 1st top byte used as Modulo-256 Sine look-up table [index]
|
||||||
|
// the lower 3 bytes (24 bits) are used as a Fractional Detla and Accumulator phase, to have very finer Fstep control.
|
||||||
|
|
||||||
|
void ToneGen::configure(const uint32_t delta, const float tone_mix_weight) {
|
||||||
|
delta_ = delta;
|
||||||
|
tone_mix_weight_ = tone_mix_weight;
|
||||||
|
input_mix_weight_ = 1.0 - tone_mix_weight;
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t ToneGen::process(const int32_t sample_in) {
|
int32_t ToneGen::process(const int32_t sample_in) {
|
||||||
if (!delta_)
|
if (!delta_)
|
||||||
return sample_in;
|
return sample_in;
|
||||||
|
|
||||||
int32_t tone_sample = 0;
|
int32_t tone_sample = sine_table_i8[(tone_phase_ & 0xFF000000U) >> 24];
|
||||||
|
tone_phase_ += delta_;
|
||||||
if(current_tone_type_ == sine) {
|
|
||||||
tone_sample = tone_sine();
|
return (sample_in * input_mix_weight_) + (tone_sample * tone_mix_weight_);
|
||||||
}
|
}
|
||||||
else if(current_tone_type_ == square) {
|
// -------------------------------------------------------------
|
||||||
tone_sample = tone_square();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
int32_t ToneGen::process_square(const int32_t sample_in) {
|
||||||
|
// TODO : Added for Sonde App. We keep it by now , but it needs to be reviewed in Sonde
|
||||||
|
if (!delta_)
|
||||||
|
return sample_in;
|
||||||
|
|
||||||
|
int32_t tone_sample = 0;
|
||||||
|
|
||||||
|
tone_sample = tone_square();
|
||||||
|
|
||||||
|
|
||||||
return (sample_in * input_mix_weight_) + (tone_sample * tone_mix_weight_);
|
return (sample_in * input_mix_weight_) + (tone_sample * tone_mix_weight_);
|
||||||
}
|
}
|
||||||
|
@@ -28,7 +28,7 @@
|
|||||||
|
|
||||||
class ToneGen {
|
class ToneGen {
|
||||||
public:
|
public:
|
||||||
enum tone_type { sine, square };
|
enum tone_type { sine, square }; // TODO: Added for Radio Sonde.cpp PR 376, 381 , we need to check if keep or not.
|
||||||
|
|
||||||
/*ToneGen(const size_t sample_rate
|
/*ToneGen(const size_t sample_rate
|
||||||
) : sample_rate_ { sample_rate }
|
) : sample_rate_ { sample_rate }
|
||||||
@@ -38,6 +38,7 @@ public:
|
|||||||
void configure(const uint32_t freq, const float tone_mix_weight, const tone_type tone_type, const uint32_t sample_rate);
|
void configure(const uint32_t freq, const float tone_mix_weight, const tone_type tone_type, const uint32_t sample_rate);
|
||||||
|
|
||||||
int32_t process(const int32_t sample_in);
|
int32_t process(const int32_t sample_in);
|
||||||
|
int32_t process_square(const int32_t sample_in);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
tone_type current_tone_type_ { sine };
|
tone_type current_tone_type_ { sine };
|
||||||
@@ -45,19 +46,23 @@ private:
|
|||||||
float input_mix_weight_ { 1 };
|
float input_mix_weight_ { 1 };
|
||||||
float tone_mix_weight_ { 0 };
|
float tone_mix_weight_ { 0 };
|
||||||
|
|
||||||
uint8_t delta_ { 0 };
|
uint32_t delta_ { 0 };
|
||||||
uint8_t tone_phase_ { 0 };
|
uint32_t tone_phase_ { 0 };
|
||||||
|
|
||||||
|
// uint8_t delta_ { 0 }; // TODO: Added for Radio Sonde.cpp PR 376, 381 , we need to check if keep or not.
|
||||||
|
// uint8_t tone_phase_ { 0 }; // TODO: Added for Radio Sonde.cpp PR 376, 381 , we need to check if keep or not.
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generator function which selects every other sample from the reference sine waveform to the output sample:
|
* Generator function which selects every other sample from the reference sine waveform to the output sample:
|
||||||
*/
|
*/
|
||||||
int32_t tone_sine();
|
int32_t tone_sine();// TODO: Added for Radio Sonde.cpp PR 376, 381 , we need to check if keep or not.
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generator function for square waves:
|
* Generator function for square waves:
|
||||||
*/
|
*/
|
||||||
int32_t tone_square();
|
int32_t tone_square(); // TODO: Added for Radio Sonde.cpp PR 376, 381 , we need to check if keep or not.
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* __TONE_GEN_H__ */
|
#endif /* __TONE_GEN_H__ */
|
||||||
|
@@ -84,7 +84,7 @@ bool Packet::crc_ok() const {
|
|||||||
acars_fcs.process_byte(field_crc.read(i, 8));
|
acars_fcs.process_byte(field_crc.read(i, 8));
|
||||||
}
|
}
|
||||||
|
|
||||||
return (acars_fcs.checksum() == field_crc.read(data_length(), fcs_length));
|
return (acars_fcs.checksum() == (unsigned)field_crc.read(data_length(), fcs_length));
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t Packet::data_and_fcs_length() const {
|
size_t Packet::data_and_fcs_length() const {
|
||||||
|
@@ -191,7 +191,7 @@ bool Packet::crc_ok() const {
|
|||||||
ais_fcs.process_byte(field_crc.read(i, 8));
|
ais_fcs.process_byte(field_crc.read(i, 8));
|
||||||
}
|
}
|
||||||
|
|
||||||
return (ais_fcs.checksum() == field_crc.read(data_length(), fcs_length));
|
return (ais_fcs.checksum() == (unsigned)field_crc.read(data_length(), fcs_length));
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t Packet::data_and_fcs_length() const {
|
size_t Packet::data_and_fcs_length() const {
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user