Compare commits

..

147 Commits

Author SHA1 Message Date
jLynx 2a38f386ab Update version.txt 2022-12-29 15:35:54 +13:00
jLynx 079a0506a4 Update past_version.txt 2022-12-29 15:35:45 +13:00
Brumi-2021 e8ad86cc94 Merge pull request #768 from rusty-labs/sin_function_180_fix
#755 fix, sin_f32 fails at 180
2022-12-28 16:34:38 +01:00
rusty.labs e69c9bbc7b #755 fix, sin_f32 fails at 180
#755 fix, sin_f32 returns incorrect result at 180 degrees, clean up
2022-12-28 01:13:42 -05:00
Brumi-2021 25c267a3d9 Merge pull request #744 from strijar/spectrum_color
New spectrum color scheme Look at table (LUT) for the Waterfall FFT .
2022-12-17 16:02:54 +01:00
gullradriel efbcd2aa9b Merge pull request #752 from lujji/fix-ook-bug
Fix OOK repeat bug
2022-12-17 12:44:19 +01:00
gullradriel f32b55f66f Merge pull request #754 from lujji/ook-scan
Implement OOK scan
2022-12-17 12:43:34 +01:00
gullradriel e9adc32421 Merge pull request #757 from gullradriel/next
Updated submodules
2022-12-14 22:18:43 +01:00
GullCode a120a6344d Updated submodules 2022-12-14 22:17:25 +01:00
lujji e3cea4c68b minor ui fix 2022-12-05 22:12:46 +02:00
lujji 0631f5d5ab implement ook scan 2022-12-05 16:51:23 +02:00
lujji 8986b65f94 fix ook repeat bug 2022-11-30 10:59:24 +02:00
gullradriel 7f64606fb2 Merge pull request #750 from gullradriel/recon-delete-retune-fix
Retune after delete fix
2022-11-20 20:14:47 +01:00
GullCode 7bfb54eee9 better order of events 2022-11-20 19:53:03 +01:00
GullCode e0c1f7b45e Retune after delete fix 2022-11-20 19:46:01 +01:00
gullradriel 734f315266 Merge pull request #749 from gullradriel/updating-am-mode
Added/Renamed AM bandwidth modes
2022-11-20 18:36:43 +01:00
GullCode 7f6aebbe53 Fixed typos 2022-11-20 18:29:20 +01:00
GullCode 5f62926af3 Fixed typo 2022-11-20 18:02:54 +01:00
GullCode 17f6475506 Added/Renamed AM bandwidth modes 2022-11-20 17:44:11 +01:00
Jimi Sanchez 17d3cb387e Merge pull request #747 from Brumi-2021/“Additional_AM_BW_type_9Khz_on_top_current_6Khz”
“additional am bw type 9 khz on top current 6 khz”
2022-11-19 17:04:19 -05:00
Brumi-2021 1e4c93b979 Final opt. AM-9K, applied to Audio_RX and Mic App. 2022-11-19 18:17:54 +01:00
Brumi-2021 25dfa96257 Adding FIR_taps for EU AM broadcasting 9K00A3E 2022-11-14 00:32:29 +01:00
Erwin Ried 400cccdcc1 Contributors gridview 2022-11-10 09:41:20 +01:00
Belousov Oleg f59437cf71 New spectrum color scheme 2022-11-10 02:17:04 +03:00
GullCode 5577ec82ed Merge pull request #729 from BehleZebub/patch-1
Update generate_world_map.bin.py
2022-11-02 17:54:42 +01:00
GullCode da98e7739e Update generate_world_map.bin.py
Formatting text
2022-11-02 17:21:56 +01:00
GullCode b5b5bf42af Merge pull request #737 from BehleZebub/next
update for python scripts so no python2.7 is needed
2022-11-02 17:14:53 +01:00
BehleZebub 587fbfbbb1 added shebang line for pyhton3 on unix 2022-11-02 00:36:04 +01:00
GullCode c54e382db2 Merge pull request #739 from lujji/next
Add gain and amplifier controls in Jammer
2022-11-01 12:00:55 +01:00
lujji 22de89c879 added gain and amp controls 2022-11-01 06:42:55 +02:00
GullCode aa778e5797 Merge pull request #738 from Brumi-2021/Extending_previous_ghost_signal_interference_c/m_in_all_RX_after_using_Replay_App
(MINOR IMPROV Replay App) - Extending previous  "ghost interf. signal" c/m to Replay App
2022-10-30 20:15:24 +01:00
Brumi-2021 e8e98475e2 Extending "ghost interf. signal" c/m to Replay App 2022-10-30 19:23:52 +01:00
BehleZebub 95d1bca9fd changed from python2 to python3 2022-10-30 00:04:31 +02:00
BehleZebub 1a5c360efe changed from python2 to python3 2022-10-30 00:04:07 +02:00
BehleZebub 560c7143bf Update make_dcs.py 2022-10-30 00:03:07 +02:00
BehleZebub 6fc03a2651 changed from python2 to python3 2022-10-30 00:02:01 +02:00
BehleZebub f31ee1172d changed from python2 to python3 2022-10-30 00:00:55 +02:00
BehleZebub 996e648a64 changed from python2 to python3 2022-10-30 00:00:26 +02:00
BehleZebub ca4f68d24a changed from python2 to python3 2022-10-29 23:58:26 +02:00
GullCode 2c3f8e9b3d Merge pull request #734 from Brumi-2021/“Solving_correctg_RX_DSB-SC_Suppressed_Carrier”
Mic App: DSB RX distortion c/m + minor improv.
2022-10-29 21:31:50 +02:00
Brumi-2021 a591ba572f Mic App: DSB RX distortion c/m + minor improv. 2022-10-29 16:02:08 +02:00
BehleZebub c9657bc92b Update generate_world_map.bin.py
corrected typo in print();
2022-10-28 17:38:00 +02:00
BehleZebub b8d98e4f45 Update generate_world_map.bin.py
forced endianess on outfile.write() to little endian and closed outfile at the end
2022-10-22 23:42:40 +02:00
GullCode e0309b13e5 Merge pull request #728 from GullCode/fix-wfm-bw-label
Fix wfm bw label
2022-10-18 21:38:21 +02:00
GullCode c2117b2c5b cosmetic fix for bw display 2022-10-18 21:37:28 +02:00
GullCode 2b78f9e907 Correct WFM bw label to 200k 2022-10-18 21:36:22 +02:00
GullCode 6cd4eb0358 Correct WFM bandwidth and step 2022-10-18 21:26:14 +02:00
GullCode 8ec69d7c95 Merge pull request #727 from Brumi-2021/adding_in_RX_WFM_to_Mic_App
Add WFM mode in Mic App (in tx and rx)
2022-10-16 20:47:50 +02:00
Brumi-2021 efe8d82fae Add WFM mode in Mic App (in tx and rx) 2022-10-16 19:01:05 +02:00
GullCode 32697d1c73 Merge pull request #723 from GullCode/recon-freqman-steps-band-update
Recon freqman steps band update
2022-10-11 12:52:23 +02:00
GullCode 11558b9843 Merge pull request #722 from GullCode/scanner-freqman-update-max_files-steps
Scanner freqman update max files steps
2022-10-11 12:52:10 +02:00
GullCode e5d1308560 Added FM bands files 2022-10-11 12:49:32 +02:00
GullCode 62968e6009 Added default RECON.TXT file 2022-10-11 12:49:15 +02:00
GullCode a9b4abc07e Indenting some comments 2022-10-11 12:48:42 +02:00
GullCode 05f3793213 Added 30Khz steps and removed quoted code 2022-10-11 12:46:12 +02:00
GullCode ae8633c569 Use FREQMAN_MAX_PER_FILE instead of MAX_DB_ENTRY 2022-10-11 12:40:49 +02:00
GullCode 480f492740 Removed MAX_DB_ENTRY definition 2022-10-11 12:40:31 +02:00
GullCode dd2e23f901 Updated FREQMAN_MAX_PER_FILE value 2022-10-11 12:40:08 +02:00
GullCode 3ca57f634c Merge pull request #721 from eried/hackrf_update
Update hackrf
2022-10-11 12:10:26 +02:00
GullCode 29ac3192cb Update hackrf 2022-10-11 12:03:25 +02:00
GullCode e76faf6edd Merge pull request #717 from Brumi-2021/Recovered_ALC_AK4953_Mic_App_feature_solving_WM8731_side_effects
Adding Mic Control gain in both platforms : mic Auto volume Level Control  (AK4951) and mic Boost control (WM8731)
2022-10-09 21:50:43 +02:00
GullCode 5474487751 Merge pull request #696 from andrej-mk/ook
Increase max OOK clock
2022-10-09 18:23:33 +02:00
GullCode e6cf04e511 Update ui_encoders.hpp
Proper indentation
2022-10-09 18:22:23 +02:00
GullCode 1d521819ff Merge pull request #711 from GullCode/recon-app
Recon app
2022-10-08 13:46:50 +02:00
GullCode 83f7c9ae63 Merge pull request #707 from Brumi-2021/try_to_solve_RX_ghost_signal_issue_#637
Solve previous regression fw 1.3.1 -->fw 1.4.0 onwards , about RX ghost signal issue #637
2022-10-07 22:17:10 +02:00
igolyudov 310fbd53ec Update docker file (#719)
Pin base image ubuntu LTS version. add installation python3 with python3-yaml package. create python link in PATH for build hackrf dependency,
2022-10-04 08:56:04 +13:00
Brumi-2021 6b75249b0a Finalised all Mic Boost(WM) and Mic ALC(AK) 2022-10-02 00:51:12 +02:00
Brumi-2021 745574d3c4 Ak4951-ALC_base adding WM8731-boost OFF options 2022-09-28 22:42:33 +02:00
Jimi Sanchez c80595db7e Merge pull request #535 from jimilinuxguy/jimi-merging-conflicts
Playlist replay application
2022-09-19 17:48:11 -04:00
Jimi Sanchez 040dded2a6 Merges latest firmware into feature branch 2022-09-19 17:35:28 -04:00
Jimi Sanchez 958c9a1bfa Merge pull request #4 from jimilinuxguy/replayapp
Replayapp
2022-09-19 13:13:21 -04:00
Jimi Sanchez 76a137924c Merge pull request #3 from eried/master
Master
2022-09-19 13:12:31 -04:00
Jimi Sanchez 861db600e8 Merge branch 'replayapp' into master 2022-09-19 13:12:15 -04:00
Erwin Ried 4993a6abcb Update README.md 2022-09-16 09:28:32 +02:00
GullCode 9086f32a63 Added Recon app persistent settings 2022-09-13 23:58:03 +02:00
GullCode 9d59c07855 Added Recon app under 'Receive' menu 2022-09-13 23:58:03 +02:00
GullCode 0d18aa47f3 Added Recon files to CMake list 2022-09-13 23:58:03 +02:00
GullCode cf40f5eb14 Added ButtonWithEncoder 2022-09-13 23:58:03 +02:00
GullCode fe4bc7902f Added access to min/med/max values 2022-09-13 23:58:03 +02:00
GullCode 5d5865eefb Added tone to string and string to tone 2022-09-13 23:58:03 +02:00
GullCode a7370ee95d Added new file format funcs 2022-09-13 23:58:03 +02:00
GullCode 223cd7c20d added Recon files 2022-09-13 23:58:03 +02:00
Erwin Ried 1be3167748 Merge pull request #710 from Brumi-2021/Increase_freq_step_resolution
Very minor change , add 10 & 50Hz freq. steps , SSB  in HF and Qo-100_sat_#669
2022-09-12 09:24:25 +02:00
Brumi-2021 1bbd889005 Very minor change , add 10/50Hz freq. step #669 2022-09-06 21:01:09 +02:00
Erwin Ried d87e9853a1 Merge pull request #705 from Brumi-2021/Bias_DC_Voltage_not_working_in_TPMS_&_ERT_#700
Adding Bias dc voltage not working in tpms & ert (previous issue #700)
2022-09-05 10:14:47 +02:00
Erwin Ried 36109964a7 Merge pull request #701 from arneluehrs/ais-fix
AIS Class B decoding and display
2022-09-05 10:13:54 +02:00
Brumi-2021 6087c658e9 Applied ghost-signal c/m to all remaining TX Apps 2022-08-27 17:47:24 +02:00
Brumi-2021 08a108d3e4 First test, ghost-singal c/m to only Mic_App 2022-08-26 18:34:30 +02:00
GullCode c78659db38 RECON sdcard dir and empty config 2022-08-24 17:36:58 +02:00
Brumi-2021 5021a03572 Minor change radio,disable-->receiver.disable 2022-08-23 00:04:48 +02:00
Brumi-2021 961a4c4588 Addition_bias_DC_ERP_TPMS 2022-08-21 19:59:15 +02:00
Arne Luehrs a89d418202 AIS Decoding, destination text display fix
Remove trailing null characters '@' from display of destination field
2022-08-15 14:41:07 +08:00
Arne Luehrs 1dcc80ba59 Merge remote-tracking branch 'refs/remotes/origin/ais-fix' into ais-fix 2022-08-15 14:04:40 +08:00
Arne Luehrs 1e14ca4df1 Enable AIS-B decoding and display
Implement decoding for AIS messages 18 and 24A 24B
clean up display of text messages by removing the trailing null
character '@'
2022-08-15 13:56:40 +08:00
Arne Luehrs 5096f91986 Add AIS Class B Decoding 2022-08-15 00:12:24 +08:00
Arne Luehrs 65be02c5b1 Add AIS Class B Decoding 2022-08-14 23:48:04 +08:00
Arne Luehrs f5a604a0a5 Merge pull request #3 from eried/next
Sync with upstream
2022-08-12 15:17:29 +08:00
andrej 87418703e0 Make clk and frame duration steps in OOK configurable 2022-08-01 08:40:26 +02:00
andrej e33c98cbc7 Increase maximum OOK clock to 1000 kHz 2022-08-01 08:40:16 +02:00
Brumi-2021 823c69eb42 Merge branch 'eried:next' into next 2022-06-14 21:55:36 +02:00
jLynx 15f3d81798 Update version.txt 2022-06-08 19:21:01 +12:00
jLynx fa2791004f Update past_version.txt 2022-06-08 19:20:52 +12:00
Timo Taskinen 50bd08d9ff Fix AM bandwidth and sampling rate in scanner (#671)
In scanner app, the bandwidth and sampling rate for AM modulation was incorrect. This resulted in high pitched and distorted sound. I have now copied the settings from the Audio receiver app, and now the sound in Scanner sounds good also in AM mode.
2022-06-07 11:05:17 +12:00
Brumi-2021 a26ee84ff8 Merge branch 'eried:next' into next 2022-06-06 15:33:20 +02:00
jLynx 39134b62c3 Fix for new H2+ devices (#666)
* WIP Fix for new h2+ devices

* reset

* Updated sub module
2022-06-05 14:15:44 +12:00
Jared Boone e5a30b4309 Persistent memory check value verification, defaulting when fails. (#662)
* Make default constructor for touch calibration

* Add persistent memory check value and access abstraction.

* Add persistent data_t default constructor with reasonable defaults.

* serial_format_t default constructor.

* Tidy up backlight timeout type.

* Add persistent data struct version/checking.

* Make range_t functions constexpr.

* Move ui_config and functions into class.

* Add backlight_config_t struct, separate enable and time settings.
2022-05-29 08:55:18 +12:00
Brumi-2021 379ad6dbf0 Recovered_ALC_Mic_Feature_AK4953_OK_WM8731 2022-05-28 22:29:10 +02:00
Brumi-2021 840da4c685 Merge branch 'eried:next' into next 2022-05-22 16:41:48 +02:00
ArjanOnwezen 2031a79b34 Update problem-upgrading-the-firmware.md
Typo
2022-05-21 10:12:52 +02:00
ArjanOnwezen deff646e36 Update problem-upgrading-the-firmware.md
Typo
2022-05-21 10:11:36 +02:00
jLynx 4aa3314906 Updated templates (#655)
* Update problem-upgrading-the-firmware.md

* Update problem-upgrading-the-firmware.md

* Update bug_report.md
2022-05-21 13:41:44 +12:00
jLynx e3da9d4cb2 Included DLL files (#654) 2022-05-21 12:11:03 +12:00
jLynx c389ce7c0e Merge pull request #653 from eried/next
v1.5.3
2022-05-21 12:06:39 +12:00
Brumi-2021 dda543f7f3 Merge branch 'eried:next' into next 2022-05-08 12:39:27 +02:00
Brumi-2021 92844a7528 Merge branch 'eried:next' into next 2022-05-06 21:55:27 +02:00
Brumi-2021 ef52339b1d Merge branch 'eried:next' into next 2022-05-02 20:05:42 +02:00
Brumi-2021 5e0780839c Merge branch 'eried:next' into next 2022-04-30 16:22:45 +02:00
Jimi Sanchez 85602d145a Update create_nightly_release.yml 2022-04-28 17:15:03 -04:00
Jimi Sanchez 2efab19bf6 Merge branch 'next' of https://github.com/jimilinuxguy/portapack-mayhem into next 2022-04-28 17:06:50 -04:00
Jimi Sanchez 4562228b55 Fixing spelling of Wav Viewer 2022-04-28 17:06:45 -04:00
Jimi Sanchez b56acb0c9d Merge pull request #2 from jimilinuxguy/jimi-merging-conflicts
Jimi merging conflicts
2022-04-28 17:03:37 -04:00
Jimi Sanchez 6af0d4e751 Merge branch 'next' into jimi-merging-conflicts 2022-04-28 17:03:24 -04:00
Jimi Sanchez 0fed174a80 Adding back wipe sd 2022-04-28 16:58:44 -04:00
Jimi Sanchez d71c759480 Merge branch 'next' into jimi-merging-conflicts 2022-04-28 13:55:44 -04:00
Jimi Sanchez c1e568f62c Removing wipe sd 2022-04-28 13:54:17 -04:00
Jimi Sanchez db1b7ffddf Merge branch 'next' of https://github.com/jimilinuxguy/portapack-mayhem into next 2022-04-28 13:52:55 -04:00
Jimi Sanchez f48980e381 Adding playlist to CMakeLists 2022-04-28 13:52:47 -04:00
Jimi Sanchez cdaa6683ae Adding playlist to CMakeLists 2022-04-28 13:49:36 -04:00
Arne Luehrs d2dbad73c7 Merge branch 'eried:next' into next 2022-04-27 10:16:26 +02:00
jLynx 9412dd8bec Merge pull request #546 from eried/next
V1.5.0
2022-04-07 20:42:05 +12:00
Jimi Sanchez d624b92e85 Adding helper header for playlist file 2022-04-03 19:42:48 -04:00
Jimi Sanchez 584c46af64 Initial commit of playlist app for replaying capture files sequentially 2022-04-03 19:38:06 -04:00
Brumi-2021 1976c3648b Merge branch 'eried:next' into next 2022-04-02 13:23:43 +02:00
Jimi Sanchez c4eb02422b Merge pull request #1 from eried/next
Merging changes
2022-04-02 05:10:41 -04:00
Brumi-2021 95ac4a2d1e Merge branch 'eried:next' into next 2022-03-28 18:13:24 +02:00
Brumi-2021 a7c7495428 Merge branch 'eried:next' into next 2022-03-26 21:56:38 +01:00
Arne Luehrs 8f311ea1f2 Merge pull request #1 from eried/next
Sync with upstream
2022-02-25 15:00:45 +01:00
Brumi-2021 d0643421a8 Merge branch 'eried:next' into next 2022-02-04 20:13:04 +01:00
Brumi-2021 adb0cdf8fb Merge branch 'eried:next' into next 2022-02-01 23:20:00 +01:00
Brumi-2021 1b93a042a3 Merge branch 'next' of https://github.com/Brumi-2021/portapack-mayhem into next 2022-01-29 12:19:06 +01:00
Brumi-2021 52c6d0e4ed Merge branch 'next' of https://github.com/Brumi-2021/portapack-mayhem into next 2021-11-24 21:10:08 +01:00
Brumi-2021 22a5ca7df7 Merge branch 'next' of https://github.com/Brumi-2021/portapack-mayhem into next 2021-10-25 20:47:33 +02:00
Brumi-2021 d0b356a7ef Revert "Solving Compile error on gcc10 . Keeping same safety protection about the size of the array ,but with slightly different sintax."
This reverts commit f4db4e2b53.
2021-10-24 01:59:25 +02:00
Brumi-2021 28ee69baae Revert "Update spectrum_collector.cpp"
This reverts commit 35cece1cb0.
2021-10-24 01:58:58 +02:00
Brumi-2021 bfd614b51f Revert "Update spectrum_collector.cpp"
This reverts commit 4a6fc35384.
2021-10-24 01:58:06 +02:00
Brumi-2021 4a6fc35384 Update spectrum_collector.cpp
Description changed , better explanation.
2021-10-24 01:47:42 +02:00
Brumi-2021 35cece1cb0 Update spectrum_collector.cpp
lower case correction
2021-10-24 01:40:08 +02:00
100 changed files with 6034 additions and 1083 deletions
+10 -4
View File
@@ -1,12 +1,18 @@
---
name: Bug report
about: Create a report to help us improve
about: Create a report to help us improve the software
title: ''
labels: bug
assignees: ''
---
----
(Please try the latest nightly release before submitting this. You can find the latest nightly verison here: https://github.com/eried/portapack-mayhem/releases)
----
**Describe the bug**
A clear and concise description of what the bug is.
@@ -21,9 +27,9 @@ A clear and concise description of what you expected to happen.
**Affected versions**
Please write any difference related with the Expected behavior, on the following versions:
* Latest Stable Release
* Previous one (if any) that did not presented the issue
* Old versions available here: https://github.com/eried/Research/tree/master/HackRF/PortaPack/old_legacy_firmware
* Latest Stable release:
* Latest Nightly release:
* Previous working release:
**Additional**
If the bug is difficult to explain, additionally to the text please include images and videos.
@@ -1,18 +1,39 @@
---
name: Problem upgrading the firmware
about: Deal with the firmware upgrade problems
title: Problem upgrading the firmware
labels: ''
name: Problem upgrading the firmware or booting
about: If you are having firmware upgrade or booting problems
title: ''
labels: 'firmware'
assignees: ''
---
**What is happening?**
Describe here why you are unable to upgrade the firmware. Before describing your problems, **do the following**:
----
Before creating this issue, **do the following**:
* Read the Wiki on booting: https://github.com/eried/portapack-mayhem/wiki/Won't-boot
* Read: https://github.com/eried/portapack-havoc/wiki/Update-firmware
* Watch carefully: https://www.youtube.com/watch?v=_zx4ZvurgOs
* (if you are not in Windows) also check: https://www.youtube.com/watch?v=kjFB58Y1TAo
----
**Describe the issue**
A clear and concise description of what the issue you are facing is.
**To Reproduce**
Steps to reproduce the behavior:
1. Go to '...'
2. Tap on '....'
**My Hardware**
Please specify what PortaPack hardware version you are using.
You can find the list of versions here: https://github.com/eried/portapack-mayhem/wiki/PortaPack-Versions
**Affected versions**
Please tell us what version you are running.
Also please try the latest nightly release before submitting this.
You can find the latest nightly version here https://github.com/eried/portapack-mayhem/releases
**Were you able to update the firmware before?**
Things might be confusing the first time, please check the video available on the link above.
@@ -20,4 +41,4 @@ Things might be confusing the first time, please check the video available on th
If is possible, swap hardware and try again. Also, try different USB cables, even if the one you are using works fine for other purposes.
**Additional**
Add photos and videos of your procedure.
If the issue is difficult to explain, additionally to the text please include images and videos.
+1 -1
View File
@@ -1 +1 @@
v1.5.1
v1.5.4
+1 -1
View File
@@ -1 +1 @@
v1.5.3
v1.6.0
-1
View File
@@ -27,7 +27,6 @@
# Compiled Dynamic libraries
*.so
*.dylib
*.dll
# Fortran module files
*.mod
+3 -1
View File
@@ -1,6 +1,6 @@
# PortaPack Mayhem
[![Build Status](https://travis-ci.com/eried/portapack-mayhem.svg?branch=master)](https://travis-ci.com/eried/portapack-mayhem) [![CodeScene Code Health](https://codescene.io/projects/8381/status-badges/code-health)](https://codescene.io/projects/8381) [![GitHub All Releases](https://img.shields.io/github/downloads/eried/portapack-mayhem/total)](https://github.com/eried/portapack-mayhem/releases) [![GitHub Releases](https://img.shields.io/github/downloads/eried/portapack-mayhem/latest/total)](https://github.com/eried/portapack-mayhem/releases/latest) [![Docker Hub Pulls](https://img.shields.io/docker/pulls/eried/portapack.svg)](https://hub.docker.com/r/eried/portapack) [![Discord Chat](https://img.shields.io/discord/719669764804444213.svg)](https://discord.gg/tuwVMv3) [![Check bounties!](https://img.shields.io/bountysource/team/portapack-mayhem/activity?color=%2333ccff&label=bountysource%20%28USD%29&style=plastic)](https://www.bountysource.com/teams/portapack-mayhem/issues)
[![Build Status](https://travis-ci.com/eried/portapack-mayhem.svg?branch=master)](https://travis-ci.com/eried/portapack-mayhem) [![Nightly Release](https://github.com/eried/portapack-mayhem/actions/workflows/create_nightly_release.yml/badge.svg?branch=next)](https://github.com/eried/portapack-mayhem/actions/workflows/create_nightly_release.yml) [![CodeScene Code Health](https://codescene.io/projects/8381/status-badges/code-health)](https://codescene.io/projects/8381) [![GitHub All Releases](https://img.shields.io/github/downloads/eried/portapack-mayhem/total)](https://github.com/eried/portapack-mayhem/releases) [![GitHub Releases](https://img.shields.io/github/downloads/eried/portapack-mayhem/latest/total)](https://github.com/eried/portapack-mayhem/releases/latest) [![Docker Hub Pulls](https://img.shields.io/docker/pulls/eried/portapack.svg)](https://hub.docker.com/r/eried/portapack) [![Discord Chat](https://img.shields.io/discord/719669764804444213.svg)](https://discord.gg/tuwVMv3) [![Check bounties!](https://img.shields.io/bountysource/team/portapack-mayhem/activity?color=%2333ccff&label=bountysource%20%28USD%29&style=plastic)](https://www.bountysource.com/teams/portapack-mayhem/issues)
This is a fork of the [Havoc](https://github.com/furrtek/portapack-havoc/) firmware, which itself was a fork of the [PortaPack](https://github.com/sharebrained/portapack-hackrf) firmware, an add-on for the [HackRF](http://greatscottgadgets.com/hackrf/). A fork is a derivate, in this case one that has extra features and fixes when compared to the older versions.
@@ -49,6 +49,8 @@ You can write [documentation](https://github.com/eried/portapack-mayhem/wiki), f
Consider that the hardware and firmware has been created and maintain by a [lot](https://github.com/mossmann/hackrf/graphs/contributors) of [people](https://github.com/eried/portapack-mayhem/graphs/contributors), so always try colaborating your time and effort first. For coding related questions, if something does not fit as an issue, please join our Discord by clicking the chat badge on [top](#portapack-mayhem).
[![Contributors](https://contrib.rocks/image?repo=eried/portapack-mayhem)](https://github.com/eried/portapack-mayhem/graphs/contributors)
As a last option, if you want to send money directly to me for getting more boards, antennas and such:
[![paypal](https://www.paypalobjects.com/en_US/i/btn/btn_donate_LG.gif)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=CBPQA4HRRPJQ6&source=url)
+12 -9
View File
@@ -1,6 +1,6 @@
#Download base image.
#The ubuntu:latest tag points to the "latest LTS"
FROM ubuntu:latest
#The ubuntu:20.04 tag points to the "20.04 LTS"
FROM ubuntu:20.04
#Set location to download ARM toolkit from.
# This will need to be changed over time or replaced with a static link to the latest release.
@@ -14,16 +14,18 @@ COPY ./ /havocsrc
#Fetch dependencies from APT
RUN apt-get update && \
apt-get install -y tar wget dfu-util cmake python bzip2 curl && \
apt-get -qy autoremove
apt-get install -y tar wget dfu-util cmake python bzip2 curl python3 python3-yaml && \
apt-get -qy autoremove
#Install current pip from PyPa
RUN curl https://bootstrap.pypa.io/pip/3.4/get-pip.py -o get-pip.py && \
python get-pip.py
python get-pip.py
#Fetch additional dependencies from Python 2.x pip
RUN pip install pyyaml
RUN ln -s /usr/bin/python3 /usr/bin/python && \
RUN rm -rf /usr/bin/python && \
rm -rf /usr/bin/pip && \
ln -s /usr/bin/python3 /usr/bin/python && \
ln -s /usr/bin/pip3 /usr/bin/pip
ENV LANG C.UTF-8
@@ -32,9 +34,9 @@ ENV LC_ALL C.UTF-8
#Grab the GNU ARM toolchain from arm.com
#Then extract contents to /opt/build/armbin/
RUN mkdir /opt/build && cd /opt/build && \
wget -O gcc-arm-none-eabi $ARMBINURL && \
mkdir armbin && \
tar --strip=1 -xjvf gcc-arm-none-eabi -C armbin
wget -O gcc-arm-none-eabi $ARMBINURL && \
mkdir armbin && \
tar --strip=1 -xjvf gcc-arm-none-eabi -C armbin
#Set environment variable so compiler knows where the toolchain lives
ENV PATH=$PATH:/opt/build/armbin/bin
@@ -43,3 +45,4 @@ CMD cd /havocsrc && \
mkdir build && cd build && \
cmake .. && make firmware && \
cp /portapack-havoc/firmware/portapack-h1-havoc.bin /havocbin
+4
View File
@@ -267,8 +267,12 @@ set(CPPSRC
apps/lge_app.cpp
apps/pocsag_app.cpp
apps/replay_app.cpp
apps/ui_playlist.cpp
apps/gps_sim_app.cpp
apps/soundboard_app.cpp
apps/ui_recon.cpp
apps/ui_recon_settings.cpp
apps/tpms_app.cpp
apps/tpms_app.cpp
protocols/aprs.cpp
protocols/ax25.cpp
+43 -11
View File
@@ -76,12 +76,18 @@ static std::string mid(
mid_code = to_string_dec_uint(mmsi, 9, ' ').substr(0, 3);
return_code = db.retrieve_mid_record(&mid_record, mid_code);
switch(return_code) {
case DATABASE_RECORD_FOUND: return mid_record.country;
case DATABASE_RECORD_FOUND: return mid_record.country;
case DATABASE_NOT_FOUND: return "No mids.db file";
default: return "";
}
}
static std::string text(const std::string &text) {
size_t end = text.find_last_not_of("@");
return (end == std::string::npos) ? "" : text.substr(0, end + 1);
}
static std::string navigational_status(const unsigned int value) {
switch(value) {
case 0: return "under way w/engine";
@@ -164,7 +170,7 @@ void AISLogger::on_packet(const ais::Packet& packet) {
}
log_file.write_entry(packet.received_at(), entry);
}
}
void AISRecentEntry::update(const ais::Packet& packet) {
received_count++;
@@ -195,6 +201,15 @@ void AISRecentEntry::update(const ais::Packet& packet) {
destination = packet.text(302, 20);
break;
case 18:
last_position.timestamp = packet.received_at();
last_position.speed_over_ground = packet.read(46, 10);
last_position.latitude = packet.latitude(85);
last_position.longitude = packet.longitude(57);
last_position.course_over_ground = packet.read(112, 12);
last_position.true_heading = packet.read(124, 9);
break;
case 21:
name = packet.text(43, 20);
last_position.timestamp = packet.received_at();
@@ -202,6 +217,23 @@ void AISRecentEntry::update(const ais::Packet& packet) {
last_position.longitude = packet.longitude(164);
break;
case 24:
switch (packet.read(38, 2))
{
case 0:
name = packet.text(40, 20);
break;
case 1:
call_sign = packet.text(90, 7);
break;
default:
break;
}
break;
default:
break;
}
@@ -218,9 +250,9 @@ void RecentEntriesTable<AISRecentEntries>::draw(
) {
std::string line = ais::format::mmsi(entry.mmsi) + " ";
if( !entry.name.empty() ) {
line += entry.name;
line += ais::format::text(entry.name);
} else {
line += entry.call_sign;
line += ais::format::text(entry.call_sign);
}
line.resize(target_rect.width() / 8, ' ');
@@ -241,7 +273,7 @@ AISRecentEntryDetailView::AISRecentEntryDetailView(NavigationView& nav) {
button_see_map.on_select = [this, &nav](Button&) {
geomap_view = nav.push<GeoMapView>(
entry_.name,
ais::format::text(entry_.name),
0,
GeoPos::alt_unit::METERS,
ais::format::latlon_float(entry_.last_position.latitude.normalized()),
@@ -252,7 +284,7 @@ AISRecentEntryDetailView::AISRecentEntryDetailView(NavigationView& nav) {
});
send_updates = true;
};
}
@@ -262,7 +294,7 @@ AISRecentEntryDetailView::AISRecentEntryDetailView(const AISRecentEntryDetailVie
(void)Entry;
}
AISRecentEntryDetailView & AISRecentEntryDetailView::operator=(const AISRecentEntryDetailView&Entry)
AISRecentEntryDetailView & AISRecentEntryDetailView::operator=(const AISRecentEntryDetailView&Entry)
{
(void)Entry;
return *this;
@@ -302,9 +334,9 @@ void AISRecentEntryDetailView::paint(Painter& painter) {
field_rect = draw_field(painter, field_rect, s, "MMSI", ais::format::mmsi(entry_.mmsi));
field_rect = draw_field(painter, field_rect, s, "Ctry", ais::format::mid(entry_.mmsi));
field_rect = draw_field(painter, field_rect, s, "Name", entry_.name);
field_rect = draw_field(painter, field_rect, s, "Call", entry_.call_sign);
field_rect = draw_field(painter, field_rect, s, "Dest", entry_.destination);
field_rect = draw_field(painter, field_rect, s, "Name", ais::format::text(entry_.name));
field_rect = draw_field(painter, field_rect, s, "Call", ais::format::text(entry_.call_sign));
field_rect = draw_field(painter, field_rect, s, "Dest", ais::format::text(entry_.destination));
field_rect = draw_field(painter, field_rect, s, "Last", to_string_datetime(entry_.last_position.timestamp));
field_rect = draw_field(painter, field_rect, s, "Pos ", ais::format::latlon(entry_.last_position.latitude, entry_.last_position.longitude));
field_rect = draw_field(painter, field_rect, s, "Stat", ais::format::navigational_status(entry_.navigational_status));
@@ -352,7 +384,7 @@ AISAppView::AISAppView(NavigationView& nav) : nav_ { nav } {
receiver_model.set_sampling_rate(sampling_rate);
receiver_model.set_baseband_bandwidth(baseband_bandwidth);
receiver_model.enable(); // Before using radio::enable(), but not updating Ant.DC-Bias.
options_channel.on_change = [this](size_t, OptionsField::value_t v) {
this->on_frequency_changed(v);
};
@@ -53,12 +53,13 @@ private:
OptionsField options_config {
{ 3 * 8, 0 * 16 },
4,
5,
{
{ "DSB ", 0 },
{ "USB ", 0 },
{ "LSB ", 0 },
{ "CW ", 0 },
{ "DSB 9k ", 0 },
{ "DSB 6k ", 0 },
{ "USB+3k ", 0 },
{ "LSB-3k ", 0 },
{ "CW ", 0 },
}
};
};
+7 -3
View File
@@ -113,8 +113,12 @@ ERTAppView::ERTAppView(NavigationView&) {
field_rf_amp.set_value(app_settings.rx_amp);
}
receiver_model.set_tuning_frequency(initial_target_frequency);
receiver_model.set_sampling_rate(sampling_rate);
receiver_model.set_baseband_bandwidth(baseband_bandwidth);
receiver_model.enable(); // Before using radio::enable(), but not updating Ant.DC-Bias.
radio::enable({
/* radio::enable({
initial_target_frequency,
sampling_rate,
baseband_bandwidth,
@@ -122,7 +126,7 @@ ERTAppView::ERTAppView(NavigationView&) {
receiver_model.rf_amp(),
static_cast<int8_t>(receiver_model.lna()),
static_cast<int8_t>(receiver_model.vga()),
});
}); */
logger = std::make_unique<ERTLogger>();
if( logger ) {
@@ -135,7 +139,7 @@ ERTAppView::~ERTAppView() {
// save app settings
settings.save("rx_ert", &app_settings);
radio::disable();
receiver_model.disable(); // to switch off all, including DC bias and change flag enabled_
baseband::shutdown();
}
+3 -1
View File
@@ -29,6 +29,7 @@
#include "baseband_api.hpp"
#include "portapack.hpp"
#include "cpld_update.hpp"
#include "portapack_persistent_memory.hpp"
using namespace portapack;
@@ -242,7 +243,8 @@ GpsSimAppView::GpsSimAppView(
GpsSimAppView::~GpsSimAppView() {
radio::disable();
baseband::shutdown();
hackrf::cpld::load_sram_no_verify(); // to leave all RX ok, without ghost signal problem at the exit .
baseband::shutdown(); // better this function at the end, not load_sram() that sometimes produces hang up.
}
void GpsSimAppView::on_hide() {
+3 -1
View File
@@ -27,6 +27,7 @@
#include "lge_app.hpp"
#include "baseband_api.hpp"
#include "cpld_update.hpp"
#include "ui_textentry.hpp"
#include "string_format.hpp"
@@ -48,7 +49,8 @@ LGEView::~LGEView() {
settings.save("tx_lge", &app_settings);
transmitter_model.disable();
baseband::shutdown();
hackrf::cpld::load_sram_no_verify(); // to leave all RX ok, without ghost signal problem at the exit .
baseband::shutdown();// better this function at the end, not load_sram() that sometimes produces hang up.
}
void LGEView::generate_lge_frame(const uint8_t command, const uint16_t address_a, const uint16_t address_b, std::vector<uint8_t>& data) {
+7 -2
View File
@@ -26,7 +26,7 @@
#include "ui_fileman.hpp"
#include "io_file.hpp"
#include "cpld_update.hpp"
#include "baseband_api.hpp"
#include "portapack.hpp"
#include "portapack_persistent_memory.hpp"
@@ -258,7 +258,12 @@ ReplayAppView::ReplayAppView(
ReplayAppView::~ReplayAppView() {
radio::disable();
baseband::shutdown();
display.fill_rectangle({ 0,0,240, 320 },Color::black()); //Solving sometimes visible bottom waterfall artifacts, clearing all LCD pixels.
chThdSleepMilliseconds(40); // (that happened sometimes if we interrupt the waterfall play at the beggining of the play around 25% and exit )
hackrf::cpld::load_sram_no_verify(); // to leave all RX reception ok, without "ghost interference signal problem" at the exit .
baseband::shutdown(); // better this function at the end, after load_sram(). If not , sometimes produced hang up (now not , it is ok).
}
void ReplayAppView::on_hide() {
+4 -1
View File
@@ -25,6 +25,7 @@
#include "soundboard_app.hpp"
#include "string_format.hpp"
#include "tonesets.hpp"
#include "cpld_update.hpp"
using namespace tonekey;
using namespace portapack;
@@ -110,6 +111,7 @@ void SoundBoardView::start_tx(const uint32_t id) {
1536000 / 20, // Update vu-meter at 20Hz
transmitter_model.channel_bandwidth(),
0, // Gain is unused
8, // shift_bits_s16, default 8 bits, but also unused
TONES_F2D(tone_key_frequency(tone_key_index), 1536000),
0, //AM
0, //DSB
@@ -295,7 +297,8 @@ SoundBoardView::~SoundBoardView() {
stop();
transmitter_model.disable();
baseband::shutdown();
hackrf::cpld::load_sram_no_verify(); // to leave all RX ok, without ghost signal problem at the exit.
baseband::shutdown(); // better this function at the end, not load_sram() that sometimes produces hang up.
}
}
+8 -3
View File
@@ -161,7 +161,12 @@ TPMSAppView::TPMSAppView(NavigationView&) {
}
else options_band.set_by_value(receiver_model.tuning_frequency());
radio::enable({
receiver_model.set_tuning_frequency(tuning_frequency());
receiver_model.set_sampling_rate(sampling_rate);
receiver_model.set_baseband_bandwidth(baseband_bandwidth);
receiver_model.enable(); // Before using radio::enable(), but not updating Ant.DC-Bias.
/* radio::enable({
tuning_frequency(),
sampling_rate,
baseband_bandwidth,
@@ -169,7 +174,7 @@ TPMSAppView::TPMSAppView(NavigationView&) {
receiver_model.rf_amp(),
static_cast<int8_t>(receiver_model.lna()),
static_cast<int8_t>(receiver_model.vga()),
});
}); */
options_band.on_change = [this](size_t, OptionsField::value_t v) {
this->on_band_changed(v);
@@ -200,7 +205,7 @@ TPMSAppView::~TPMSAppView() {
app_settings.rx_frequency = target_frequency_;
settings.save("rx_tpms", &app_settings);
radio::disable();
receiver_model.disable(); // to switch off all, including DC bias and change flag enabled_
baseband::shutdown();
}
+4 -2
View File
@@ -26,6 +26,7 @@
#include "manchester.hpp"
#include "string_format.hpp"
#include "portapack.hpp"
#include "cpld_update.hpp"
#include "baseband_api.hpp"
#include <cstring>
@@ -290,8 +291,9 @@ ADSBTxView::~ADSBTxView() {
settings.save("tx_adsb", &app_settings);
transmitter_model.disable();
baseband::shutdown();
}
hackrf::cpld::load_sram_no_verify(); // to leave all RX ok, withouth ghost signal problem at the exit .
baseband::shutdown(); // better this function at the end, not load_sram() that sometimes produces hang up.
}
void ADSBTxView::generate_frames() {
const uint32_t ICAO_address = sym_icao.value_hex_u64();
+3 -1
View File
@@ -26,6 +26,7 @@
#include "aprs.hpp"
#include "string_format.hpp"
#include "portapack.hpp"
#include "cpld_update.hpp"
#include "baseband_api.hpp"
#include "portapack_shared_memory.hpp"
#include "portapack_persistent_memory.hpp"
@@ -48,7 +49,8 @@ APRSTXView::~APRSTXView() {
settings.save("tx_aprs", &app_settings);
transmitter_model.disable();
baseband::shutdown();
hackrf::cpld::load_sram_no_verify(); // to leave all RX ok, without ghost signal problem at the exit.
baseband::shutdown(); // better this function at the end, not load_sram() that sometimes produces hang up.
}
void APRSTXView::start_tx() {
+3
View File
@@ -24,6 +24,7 @@
#include "string_format.hpp"
#include "baseband_api.hpp"
#include "cpld_update.hpp"
#include "portapack_persistent_memory.hpp"
using namespace portapack;
@@ -145,6 +146,8 @@ BHTView::~BHTView() {
settings.save("tx_bht", &app_settings);
transmitter_model.disable();
hackrf::cpld::load_sram_no_verify(); // to leave all RX ok, without ghost signal problem at the exit .
baseband::shutdown(); // better this function at the end, not load_sram() that sometimes produces hang up.
}
BHTView::BHTView(NavigationView& nav) {
+3 -1
View File
@@ -23,6 +23,7 @@
#include "ui_coasterp.hpp"
#include "baseband_api.hpp"
#include "cpld_update.hpp"
#include "portapack_persistent_memory.hpp"
#include <cstring>
@@ -42,7 +43,8 @@ CoasterPagerView::~CoasterPagerView() {
settings.save("tx_coaster", &app_settings);
transmitter_model.disable();
baseband::shutdown();
hackrf::cpld::load_sram_no_verify(); // to leave all RX ok, without ghost signal problem at the exit .
baseband::shutdown(); // better this function at the end, not load_sram() that sometimes produces hang up.
}
void CoasterPagerView::generate_frame() {
+84 -126
View File
@@ -24,6 +24,7 @@
#include "baseband_api.hpp"
#include "string_format.hpp"
#include "cpld_update.hpp"
using namespace portapack;
@@ -35,18 +36,21 @@ EncodersConfigView::EncodersConfigView(
using option_t = std::pair<std::string, int32_t>;
std::vector<option_t> enc_options;
size_t i;
set_parent_rect(parent_rect);
hidden(true);
// Default encoder def
encoder_def = &encoder_defs[0];
add_children({
&labels,
&options_enctype,
&field_repeat_min,
&field_clk,
&field_clk_step,
&field_frameduration,
&field_frameduration_step,
&symfield_word,
&text_format,
&waveform
@@ -55,18 +59,18 @@ EncodersConfigView::EncodersConfigView(
// Load encoder types in option field
for (i = 0; i < ENC_TYPES_COUNT; i++)
enc_options.emplace_back(std::make_pair(encoder_defs[i].name, i));
options_enctype.on_change = [this](size_t index, int32_t) {
on_type_change(index);
};
options_enctype.set_options(enc_options);
options_enctype.set_selected_index(0);
symfield_word.on_change = [this]() {
generate_frame();
};
// Selecting input clock changes symbol and word duration
field_clk.on_change = [this](int32_t value) {
// value is in kHz, new_value is in us
@@ -74,7 +78,11 @@ EncodersConfigView::EncodersConfigView(
if (new_value != field_frameduration.value())
field_frameduration.set_value(new_value * encoder_def->word_length, false);
};
field_clk_step.on_change = [this](size_t, int32_t value) {
field_clk.set_step(value);
};
// Selecting word duration changes input clock and symbol duration
field_frameduration.on_change = [this](int32_t value) {
// value is in us, new_value is in kHz
@@ -82,6 +90,10 @@ EncodersConfigView::EncodersConfigView(
if (new_value != field_clk.value())
field_clk.set_value(1000000 / new_value, false);
};
field_frameduration_step.on_change = [this](size_t, int32_t value) {
field_frameduration.set_step(value);
};
}
void EncodersConfigView::focus() {
@@ -96,7 +108,8 @@ void EncodersConfigView::on_type_change(size_t index) {
encoder_def = &encoder_defs[index];
field_clk.set_value(encoder_def->default_speed / 1000);
field_repeat_min.set_value(encoder_def->repeat_min);
// SymField setup
word_length = encoder_def->word_length;
symfield_word.set_length(word_length);
@@ -111,10 +124,10 @@ void EncodersConfigView::on_type_change(size_t index) {
format_string += 'D';
}
}
// Ugly :( Pad to erase
format_string.append(24 - format_string.size(), ' ');
text_format.set(format_string);
generate_frame();
@@ -130,28 +143,28 @@ void EncodersConfigView::draw_waveform() {
for (size_t n = 0; n < length; n++)
waveform_buffer[n] = (frame_fragments[n] == '0') ? 0 : 1;
waveform.set_length(length);
waveform.set_dirty();
}
void EncodersConfigView::generate_frame() {
size_t i = 0;
frame_fragments.clear();
for (auto c : encoder_def->word_format) {
if (c == 'S')
frame_fragments += encoder_def->sync;
else
frame_fragments += encoder_def->bit_format[symfield_word.get_sym(i++)];
}
draw_waveform();
}
uint8_t EncodersConfigView::repeat_min() {
return encoder_def->repeat_min;
return field_repeat_min.value();
}
uint32_t EncodersConfigView::samples_per_bit() {
@@ -163,7 +176,7 @@ uint32_t EncodersConfigView::pause_symbols() {
}
void EncodersScanView::focus() {
field_debug.focus();
field_length.focus();
}
EncodersScanView::EncodersScanView(
@@ -171,31 +184,17 @@ EncodersScanView::EncodersScanView(
) {
set_parent_rect(parent_rect);
hidden(true);
add_children({
&labels,
&field_debug,
&text_debug,
&text_length
&field_length,
&bit_length_10,
&bit_length
});
// DEBUG
field_debug.on_change = [this](int32_t value) {
uint32_t l;
size_t length;
de_bruijn debruijn_seq;
length = debruijn_seq.init(value);
l = 1;
l <<= value;
l--;
if (l > 25)
l = 25;
text_debug.set(to_string_bin(debruijn_seq.compute(l), 25));
text_length.set(to_string_dec_uint(length));
};
field_length.set_value(8);
bit_length_10.set_value(40);
bit_length.set_value(0);
}
void EncodersView::focus() {
@@ -204,33 +203,21 @@ void EncodersView::focus() {
EncodersView::~EncodersView() {
// save app settings
app_settings.tx_frequency = transmitter_model.tuning_frequency();
app_settings.tx_frequency = transmitter_model.tuning_frequency();
settings.save("tx_ook", &app_settings);
transmitter_model.disable();
baseband::shutdown();
hackrf::cpld::load_sram_no_verify(); // ghost signal c/m to the problem at the exit .
baseband::shutdown(); // better this function after load_sram()
}
void EncodersView::update_progress() {
std::string str_buffer;
// text_status.set(" ");
if (tx_mode == SINGLE) {
if (tx_mode == SINGLE || tx_mode == SCAN) {
str_buffer = to_string_dec_uint(repeat_index) + "/" + to_string_dec_uint(repeat_min);
text_status.set(str_buffer);
progressbar.set_value(repeat_index);
/*} else if (tx_mode == SCAN) {
strcpy(str, to_string_dec_uint(repeat_index).c_str());
strcat(str, "/");
strcat(str, to_string_dec_uint(portapack::persistent_memory::afsk_repeats()).c_str());
strcat(str, " ");
strcat(str, to_string_dec_uint(scan_index + 1).c_str());
strcat(str, "/");
strcat(str, to_string_dec_uint(scan_count).c_str());
text_status.set(str);
progress.set_value(scan_progress);*/
} else {
text_status.set("Ready");
progressbar.set_value(0);
@@ -238,89 +225,58 @@ void EncodersView::update_progress() {
}
void EncodersView::on_tx_progress(const uint32_t progress, const bool done) {
//char str[16];
if (!done) {
// Repeating...
repeat_index = progress + 1;
/*if (tx_mode == SCAN) {
scan_progress++;
update_progress();
} else {*/
update_progress();
//}
update_progress();
} else {
// make sure all samples are transmitted before disabling radio
chThdSleepMilliseconds(10);
// Done transmitting
/*if ((tx_mode == SCAN) && (scan_index < (scan_count - 1))) {
transmitter_model.disable();
if (abort_scan) {
// Kill scan process
strcpy(str, "Abort @");
strcat(str, rgsb);
text_status.set(str);
progress.set_value(0);
tx_mode = IDLE;
abort_scan = false;
button_scan.set_style(&style_val);
button_scan.set_text("SCAN");
} else {
// Next address
scan_index++;
strcpy(rgsb, &scan_list[options_scanlist.selected_index()].addresses[scan_index * 5]);
scan_progress++;
repeat_index = 1;
update_progress();
start_tx(true);
}
} else {*/
transmitter_model.disable();
tx_mode = IDLE;
text_status.set("Done");
progressbar.set_value(0);
tx_view.set_transmitting(false);
//}
transmitter_model.disable();
tx_mode = IDLE;
text_status.set("Done");
progressbar.set_value(0);
tx_view.set_transmitting(false);
}
}
void EncodersView::start_tx(const bool scan) {
(void)scan;
size_t bitstream_length = 0;
repeat_min = view_config.repeat_min();
/*if (scan) {
if (tx_mode != SCAN) {
scan_index = 0;
scan_count = scan_list[options_scanlist.selected_index()].count;
scan_progress = 1;
repeat_index = 1;
tx_mode = SCAN;
strcpy(rgsb, &scan_list[options_scanlist.selected_index()].addresses[0]);
progress.set_max(scan_count * afsk_repeats);
update_progress();
}
} else {*/
int scan_width = 0;
uint32_t samples_per_bit;
if (scan) {
tx_mode = SCAN;
scan_width = view_scan.field_length.value();
samples_per_bit =
((view_scan.bit_length_10.value() * 10 + view_scan.bit_length.value()) * OOK_SAMPLERATE) / 1000000UL;
const uint32_t seq_len = ((1 << (scan_width - 1)) * 2) * ((uint64_t) samples_per_bit) / 2048UL;
progressbar.set_max(seq_len);
repeat_min = seq_len;
} else {
tx_mode = SINGLE;
repeat_index = 1;
samples_per_bit = view_config.samples_per_bit();
view_config.generate_frame();
bitstream_length = make_bitstream(view_config.frame_fragments);
progressbar.set_max(repeat_min);
update_progress();
//}
view_config.generate_frame();
bitstream_length = make_bitstream(view_config.frame_fragments);
repeat_min = view_config.repeat_min();
}
repeat_index = 1;
update_progress();
transmitter_model.set_sampling_rate(OOK_SAMPLERATE);
transmitter_model.set_rf_amp(true);
transmitter_model.set_baseband_bandwidth(1750000);
transmitter_model.enable();
baseband::set_ook_data(
bitstream_length,
view_config.samples_per_bit(),
samples_per_bit,
repeat_min,
view_config.pause_symbols()
view_config.pause_symbols(),
scan_width
);
}
@@ -338,14 +294,14 @@ EncodersView::EncodersView(
&progressbar,
&tx_view
});
// load app settings
auto rc = settings.load("tx_ook", &app_settings);
if(rc == SETTINGS_OK) {
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);
transmitter_model.set_tx_gain(app_settings.tx_gain);
}
tx_view.on_edit_frequency = [this, &nav]() {
@@ -354,14 +310,16 @@ EncodersView::EncodersView(
transmitter_model.set_tuning_frequency(f);
};
};
tx_view.on_start = [this]() {
tx_view.set_transmitting(true);
start_tx(false);
start_tx(tab_view.selected());
};
tx_view.on_stop = [this]() {
tx_view.set_transmitting(false);
baseband::kill_ook();
transmitter_model.disable();
};
}
+96 -64
View File
@@ -35,43 +35,41 @@ namespace ui {
class EncodersConfigView : public View {
public:
EncodersConfigView(NavigationView& nav, Rect parent_rect);
EncodersConfigView(const EncodersConfigView&) = delete;
EncodersConfigView(EncodersConfigView&&) = delete;
EncodersConfigView& operator=(const EncodersConfigView&) = delete;
EncodersConfigView& operator=(EncodersConfigView&&) = delete;
void focus() override;
void on_show() override;
uint8_t repeat_min();
uint32_t samples_per_bit();
uint32_t pause_symbols();
void generate_frame();
std::string frame_fragments = "0";
private:
//bool abort_scan = false;
//uint8_t scan_count;
//double scan_progress;
//unsigned int scan_index;
int16_t waveform_buffer[550];
const encoder_def_t * encoder_def { };
//uint8_t enc_type = 0;
void draw_waveform();
void on_bitfield();
void on_type_change(size_t index);
Labels labels {
{ { 1 * 8, 0 }, "Type:", Color::light_grey() },
{ { 16 * 8, 0 }, "Clk:", Color::light_grey() },
{ { 24 * 8, 0 }, "kHz", Color::light_grey() },
{ { 14 * 8, 2 * 8 }, "Frame:", Color::light_grey() },
{ { 26 * 8, 2 * 8 }, "us", Color::light_grey() },
{ { 2 * 8, 4 * 8 }, "Symbols:", Color::light_grey() },
{ { 1 * 8, 11 * 8 }, "Waveform:", Color::light_grey() }
{ { 17 * 8, 0 }, "Repeat:", Color::light_grey() },
{ { 1 * 8, 2 * 8 }, "Clk:", Color::light_grey() },
{ { 10 * 8, 2 * 8 }, "kHz", Color::light_grey() },
{ { 17 * 8, 2 * 8 }, "Step:", Color::light_grey() },
{ { 1 * 8, 4 * 8 }, "Frame:", Color::light_grey() },
{ { 13 * 8, 4 * 8 }, "us", Color::light_grey() },
{ { 17 * 8, 4 * 8 }, "Step:", Color::light_grey() },
{ { 2 * 8, 7 * 8 }, "Symbols:", Color::light_grey() },
{ { 1 * 8, 14 * 8 }, "Waveform:", Color::light_grey() }
};
OptionsField options_enctype { // Options are loaded at runtime
@@ -82,34 +80,63 @@ private:
};
NumberField field_clk {
{ 21 * 8, 0 },
3,
{ 1, 500 },
{ 5 * 8, 2 * 8 },
4,
{ 1, 1000 },
1,
' '
};
NumberField field_repeat_min {
{ 24 * 8, 0 },
2,
{ 1, 99 },
1,
' '
};
OptionsField field_clk_step {
{ 22 * 8, 2 * 8 },
7,
{
{ "1", 1 },
{ "10", 10 },
{ "100", 100 }
}
};
NumberField field_frameduration {
{ 21 * 8, 2 * 8 },
{ 7 * 8, 4 * 8 },
5,
{ 300, 99999 },
100,
' '
};
OptionsField field_frameduration_step {
{ 22 * 8, 4 * 8 },
7,
{
{ "1", 1 },
{ "10", 10 },
{ "100", 100 },
{ "1000", 1000 }
}
};
SymField symfield_word {
{ 2 * 8, 6 * 8 },
{ 2 * 8, 9 * 8 },
20,
SymField::SYMFIELD_DEF
};
Text text_format {
{ 2 * 8, 8 * 8, 24 * 8, 16 },
{ 2 * 8, 11 * 8, 24 * 8, 16 },
""
};
Waveform waveform {
{ 0, 14 * 8, 240, 32 },
{ 0, 17 * 8, 240, 32 },
waveform_buffer,
0,
0,
@@ -122,33 +149,38 @@ private:
class EncodersScanView : public View {
public:
EncodersScanView(NavigationView& nav, Rect parent_rect);
NumberField field_length {
{ 8 * 8, 0 },
2,
{ 3, 24 },
1,
' '
};
NumberField bit_length_10 {
{ 12 * 8, 2 * 8 },
2,
{ 1, 88 },
1,
' '
};
NumberField bit_length {
{ 14 * 8, 2 * 8 },
1,
{ 0, 9 },
1,
' '
};
void focus() override;
private:
Labels labels {
{ { 1 * 8, 1 * 8 }, "Coming soon...", Color::light_grey() }
};
// DEBUG
NumberField field_debug {
{ 1 * 8, 6 * 8 },
2,
{ 3, 16 },
1,
' '
};
// DEBUG
Text text_debug {
{ 1 * 8, 8 * 8, 24 * 8, 16 },
""
};
// DEBUG
Text text_length {
{ 1 * 8, 10 * 8, 24 * 8, 16 },
""
{ { 1 * 8, 0 * 8 }, "Length:", Color::light_grey() },
{ { 1 * 8, 2 * 8 }, "Bit length:", Color::light_grey() },
{ { 16 * 8, 2 * 8 }, "us", Color::light_grey() },
};
};
@@ -156,9 +188,9 @@ class EncodersView : public View {
public:
EncodersView(NavigationView& nav);
~EncodersView();
void focus() override;
std::string title() const override { return "OOK TX"; };
private:
@@ -169,19 +201,19 @@ private:
SINGLE,
SCAN
};
// app save settings
std::app_settings settings { };
std::app_settings settings { };
std::app_settings::AppSettings app_settings { };
tx_modes tx_mode = IDLE;
uint8_t repeat_index { 0 };
uint8_t repeat_min { 0 };
uint32_t repeat_index { 0 };
uint32_t repeat_min { 0 };
void update_progress();
void start_tx(const bool scan);
void on_tx_progress(const uint32_t progress, const bool done);
/*const Style style_address {
.font = font::fixed_8x16,
.background = Color::black(),
@@ -192,32 +224,32 @@ private:
.background = Color::black(),
.foreground = Color::blue(),
};*/
Rect view_rect = { 0, 4 * 8, 240, 168 };
EncodersConfigView view_config { nav_, view_rect };
EncodersScanView view_scan { nav_, view_rect };
TabView tab_view {
{ "Config", Color::cyan(), &view_config },
{ "Scan", Color::green(), &view_scan },
{ "de Bruijn", Color::green(), &view_scan },
};
Text text_status {
{ 2 * 8, 13 * 16, 128, 16 },
"Ready"
};
ProgressBar progressbar {
{ 2 * 8, 13 * 16 + 20, 208, 16 }
};
TransmitterView tx_view {
16 * 16,
50000,
9
};
MessageHandlerRegistration message_handler_tx_progress {
Message::ID::TXProgress,
[this](const Message* const p) {
+9 -3
View File
@@ -25,6 +25,7 @@
#include "ui_freqman.hpp"
#include "baseband_api.hpp"
#include "cpld_update.hpp"
#include "string_format.hpp"
using namespace portapack;
@@ -183,7 +184,8 @@ void JammerView::focus() {
JammerView::~JammerView() {
transmitter_model.disable();
baseband::shutdown();
hackrf::cpld::load_sram_no_verify(); // to leave all RX ok, without ghost signal problem at the exit .
baseband::shutdown(); // better this function at the end, not load_sram() that sometimes produces hang up.
}
void JammerView::on_retune(const rf::Frequency freq, const uint32_t range) {
@@ -268,9 +270,9 @@ void JammerView::start_tx() {
button_transmit.set_text("STOP");
transmitter_model.set_sampling_rate(3072000U);
transmitter_model.set_rf_amp(true);
transmitter_model.set_rf_amp(field_amp.value());
transmitter_model.set_baseband_bandwidth(3500000U);
transmitter_model.set_tx_gain(47);
transmitter_model.set_tx_gain(field_gain.value());
transmitter_model.enable();
baseband::set_jammer(true, (JammerType)options_type.selected_index(), options_speed.selected_index_value());
@@ -366,6 +368,8 @@ JammerView::JammerView(
&field_timetx,
&field_timepause,
&field_jitter,
&field_gain,
&field_amp,
&button_transmit
});
@@ -380,6 +384,8 @@ JammerView::JammerView(
field_timetx.set_value(30);
field_timepause.set_value(1);
field_gain.set_value(transmitter_model.tx_gain());
field_amp.set_value(transmitter_model.rf_amp());
button_transmit.on_select = [this](Button&) {
if (jamming || cooling)
+20 -2
View File
@@ -156,7 +156,9 @@ private:
{ { 0 * 8, 33 * 8 }, "Jitter:", Color::light_grey() }, //Maybe the repository curator can keep the "mystype" for some versions.
{ { 11 * 8, 29 * 8 }, "Secs.", Color::light_grey() },
{ { 11 * 8, 31 * 8 }, "Secs.", Color::light_grey() },
{ { 11 * 8, 33 * 8 }, "/60", Color::light_grey() }
{ { 11 * 8, 33 * 8 }, "/60", Color::light_grey() },
{ { 2 * 8, 35 * 8 }, "Gain:", Color::light_grey() },
{ { 11 * 8, 35 * 8 }, "A:", Color::light_grey() }
};
OptionsField options_type {
@@ -229,8 +231,24 @@ private:
' ',
};
NumberField field_gain {
{ 8 * 8, 35 * 8 },
2,
{ 0, 47 },
1,
' ',
};
NumberField field_amp {
{ 13 * 8, 35 * 8 },
1,
{ 0, 1 },
1,
' ',
};
Button button_transmit {
{ 148, 212, 80, 80},
{ 148, 216, 80, 80},
"START"
};
+3 -1
View File
@@ -23,6 +23,7 @@
#include "ui_keyfob.hpp"
#include "baseband_api.hpp"
#include "cpld_update.hpp"
#include "string_format.hpp"
using namespace portapack;
@@ -140,7 +141,8 @@ KeyfobView::~KeyfobView() {
settings.save("tx_keyfob", &app_settings);
transmitter_model.disable();
baseband::shutdown();
hackrf::cpld::load_sram_no_verify(); // to leave all RX ok, without ghost signal problem at the exit .
baseband::shutdown(); // better this function at the end, not load_sram() that sometimes produces hang up.
}
void KeyfobView::update_progress(const uint32_t progress) {
+3 -1
View File
@@ -27,6 +27,7 @@
#include "modems.hpp"
#include "baseband_api.hpp"
#include "string_format.hpp"
#include "cpld_update.hpp"
#include "serializer.hpp"
@@ -44,7 +45,8 @@ LCRView::~LCRView() {
settings.save("tx_lcr", &app_settings);
transmitter_model.disable();
baseband::shutdown();
hackrf::cpld::load_sram_no_verify(); // to leave all RX ok, without ghost signal problem at the exit.
baseband::shutdown(); // better this function at the end, not load_sram() that sometimes produces hang up.
}
/*
+139 -46
View File
@@ -30,6 +30,7 @@ using wolfson::wm8731::WM8731;
#include "tonesets.hpp"
#include "portapack_hal.hpp"
#include "cpld_update.hpp"
#include "string_format.hpp"
#include "irq_controls.hpp"
@@ -73,6 +74,7 @@ void MicTXView::configure_baseband() {
sampling_rate / 20, // Update vu-meter at 20Hz
transmitting ? transmitter_model.channel_bandwidth() : 0,
mic_gain,
shift_bits_s16, // to be used in dsp_modulate
TONES_F2D(tone_key_frequency(tone_key_index), sampling_rate),
enable_am,
enable_dsb,
@@ -157,19 +159,24 @@ void MicTXView::rxaudio(bool is_on) {
audio::input::stop();
baseband::shutdown();
if (enable_am || enable_usb || enable_lsb || enable_dsb) {
if (enable_am || enable_usb || enable_lsb || enable_dsb) { // "NFM/FM",0 ," WFM ",1 , " AM ",2, " USB ", 3, " LSB ",4, " DSB-SC", 5
baseband::run_image(portapack::spi_flash::image_tag_am_audio);
receiver_model.set_modulation(ReceiverModel::Mode::AMAudio);
if (options_mode.selected_index() < 4)
receiver_model.set_am_configuration(options_mode.selected_index() - 1);
else
receiver_model.set_am_configuration(0);
receiver_model.set_modulation(ReceiverModel::Mode::AMAudio); // that AM demodulation engine is common to all Amplitude mod : AM/USB/LSB/DSB (2,3,4,5)
if (options_mode.selected_index() < 5) // We will be called here with 2,3,4,5 . We treat here demod. filter 2,3,4; (excluding DSB-C case (5) it is treated more down).
receiver_model.set_am_configuration(options_mode.selected_index() - 1); // selecting proper filter(2,3,4). 2-1=1=>6k-AM(1) , 3-1=2=>+3k-USB(2), 4-1=3=>-3K-LSB(3),
}
else {
baseband::run_image(portapack::spi_flash::image_tag_nfm_audio);
receiver_model.set_modulation(ReceiverModel::Mode::NarrowbandFMAudio);
else { // We are in NFM/FM or WFM (NFM BW:8k5 or 11k / FM BW 16k / WFM BW:200k)
}
if (enable_wfm) { // WFM , BW 200Khz aprox ,
baseband::run_image(portapack::spi_flash::image_tag_wfm_audio);
receiver_model.set_modulation(ReceiverModel::Mode::WidebandFMAudio);
receiver_model.set_wfm_configuration(0); // there are only 1 x config filters 200k WFM . (not like 8k5/11k/16k)
} else { // NFM BW:8k5 or 11k / FM BW 16k
baseband::run_image(portapack::spi_flash::image_tag_nfm_audio);
receiver_model.set_modulation(ReceiverModel::Mode::NarrowbandFMAudio); //
// receiver_model.set_nbfm_configuration(n); is called above , depending 8k5, 11k, 16k
}
}
receiver_model.set_sampling_rate(3072000);
receiver_model.set_baseband_bandwidth(1750000);
// receiver_model.set_tuning_frequency(field_frequency.value()); //probably this too can be commented out.
@@ -178,6 +185,7 @@ void MicTXView::rxaudio(bool is_on) {
receiver_model.set_vga(rx_vga);
receiver_model.set_rf_amp(rx_amp);
receiver_model.enable();
hackrf::cpld::load_sram_no_verify(); // to have a good RX without any ghost inside Mic App
audio::output::start();
} else { //These incredibly convoluted steps are required for the vumeter to reappear when stopping RX.
receiver_model.set_modulation(ReceiverModel::Mode::NarrowbandFMAudio); //This fixes something with AM RX...
@@ -186,7 +194,7 @@ void MicTXView::rxaudio(bool is_on) {
baseband::run_image(portapack::spi_flash::image_tag_mic_tx);
audio::output::stop();
audio::input::start(); // set up audio input = mic config of any audio coded AK4951/WM8731, (in WM8731 parameter will be ignored)
audio::input::start(ak4951_alc_and_wm8731_boost_GUI); // When detected AK4951 => set up ALC mode; when detected WM8731 => set up mic_boost ON/OFF.
portapack::pin_i2s0_rx_sda.mode(3);
configure_baseband();
}
@@ -211,12 +219,12 @@ MicTXView::MicTXView(
baseband::run_image(portapack::spi_flash::image_tag_mic_tx);
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() ) {
if (audio::debug::codec_name() =="WM8731" ) {
add_children({
&labels_WM8731, // we have audio codec WM8731, same MIC menu as original.
&vumeter,
&options_gain, // MIC GAIN float factor on the GUI.
&options_wm8731_boost_mode,
// &check_va,
&field_va,
&field_va_level,
@@ -281,13 +289,43 @@ MicTXView::MicTXView(
mic_gain = v / 10.0;
configure_baseband();
};
options_gain.set_selected_index(1); // x1.0
options_gain.set_selected_index(1); // x1.0 preselected default.
if (audio::debug::codec_name() =="WM8731") {
options_wm8731_boost_mode.on_change = [this](size_t, int8_t v) {
switch(v) {
case 0: // +12 dBs respect reference level orig fw 1.5.x fw FM : when +20dB's boost ON) and shift bits (>>8),
shift_bits_s16 = 6; // now mic-boost on (+20dBs) and shift bits (>>6), +20+12=32 dBs (orig fw +20 dBs+ 0dBs)=> +12dB's respect ref.
break;
case 1: // +06 dBs reference level , (when +20dB's boost ON)
shift_bits_s16 = 7; // now mic-boost on (+20dBs) and shift bits (>>7), +20+06=26 dBs (orig fw +20 dBs+ 0dBs) => +06dB's respect ref.
break;
case 2:
shift_bits_s16 = 4; // +04 dBs respect ref level , (when +20dB's boost OFF)
break; // now mic-boost off (+00dBs) shift bits (4) (+0+24dB's)=24 dBs => +04dB's respect ref.
case 3:
shift_bits_s16 = 5; // -02 dBs respect ref level , (when +20dB's boost OFF)
break; // now mic-boost off (+00dBs) shift bits (5) (+0+18dB's)=18 dBs => -02dB's respect ref.
case 4:
shift_bits_s16 = 6; // -08 dBs respect ref level , (when +20dB's boost OFF)
break; // now mic-boost off (+00dBs) shift bits (6) (+0+12dB's)=12 dBs => -08dB's respect ref.
}
ak4951_alc_and_wm8731_boost_GUI = v; // 0,..4 WM8731_boost dB's options, (combination boost on/off , and effective gain in captured data >>x)
audio::input::start(ak4951_alc_and_wm8731_boost_GUI); // Detected (WM8731) , set up the proper wm_boost on/off , 0..4 (0,1) boost_on , (2,3,4) boost_0ff
configure_baseband(); // to update in real timme,sending msg , var-parameters >>shift_bits FM msg ,to audio_tx from M0 to M4 Proc -
};
options_wm8731_boost_mode.set_selected_index(3); // preset GUI index 3 as default WM -> -02 dB's .
} else {
shift_bits_s16 = 8; // Initialized default fixed >>8_FM for FM tx mod , shift audio data for AK4951 ,using top 8 bits s16 data (>>8)
options_ak4951_alc_mode.on_change = [this](size_t, int8_t v) {
ak4951_alc_and_wm8731_boost_GUI = v; // 0,..11, AK4951 Mic -Automatic volume Level Control options,
audio::input::start(ak4951_alc_and_wm8731_boost_GUI); // Detected (AK4951) ==> Set up proper ALC mode from 0..11 options
configure_baseband(); // sending fixed >>8_FM , var-parameters msg , to audiotx from this M0 to M4 process.
};
}
options_ak4951_alc_mode.on_change = [this](size_t, int8_t v) {
ak4951_alc_GUI_selected = v;
audio::input::start();
};
// options_ak4951_alc_mode.set_selected_index(0);
// options_ak4951_alc_mode.set_selected_index(0);
tx_frequency = transmitter_model.tuning_frequency();
field_frequency.set_value(transmitter_model.tuning_frequency());
@@ -313,7 +351,8 @@ MicTXView::MicTXView(
field_bw.on_change = [this](uint32_t v) {
transmitter_model.set_channel_bandwidth(v * 1000);
};
field_bw.set_value(10);
field_bw.set_value(10); // pre-default first time, TX deviation FM for NFM / FM
tx_gain = transmitter_model.tx_gain();
field_rfgain.on_change = [this](int32_t v) {
@@ -328,50 +367,102 @@ MicTXView::MicTXView(
};
field_rfamp.set_value(rf_amp ? 14 : 0);
options_mode.on_change = [this](size_t, int32_t v) {
enable_am = false;
options_mode.on_change = [this](size_t, int32_t v) { //{ "NFM/FM", 0 }, { " WFM ", 1 },{ "AM", 2 },{ "USB", 3 },{ "LSB", 4 },{ "DSB", 5 }
enable_am = false;
enable_usb = false;
enable_lsb = false;
enable_dsb = false;
enable_wfm = false;
using option_t = std::pair<std::string, int32_t>;
using options_t = std::vector<option_t>;
options_t rxbw; // Aux structure to change dynamically field_rxbw contents,
switch(v) {
case 0:
enable_am = false;
case 0: //{ "FM", 0 }
enable_am = false;
enable_usb = false;
enable_lsb = false;
enable_dsb = false;
field_bw.set_value(transmitter_model.channel_bandwidth() / 1000);
field_bw.set_value(10); // pre-default deviation FM for WFM
// field_bw.set_value(transmitter_model.channel_bandwidth() / 1000);
//if (rx_enabled)
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.
rxbw.emplace_back(" NFM1:8k5 ", 0); // restore the original dynamic field_rxbw value.
rxbw.emplace_back(" NFM2:11k ", 1);
rxbw.emplace_back(" FM :16k ", 2);
field_rxbw.set_options(rxbw); // store that aux GUI option to the field_rxbw.
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)
field_bw.hidden(0); // we are in FM mode, we need to allow FM deviation parameter , in non FM mode.
break;
case 1:
case 1: //{ "WFM", 1 }
enable_am = false;
enable_usb = false;
enable_lsb = false;
enable_dsb = false;
enable_wfm = true;
field_bw.set_value(75); // pre-default deviation FM for WFM
// field_bw.set_value(transmitter_model.channel_bandwidth() / 1000);
//if (rx_enabled)
rxaudio(rx_enabled); //Update now if we have RX audio on
options_tone_key.hidden(0); // we are in WFM mode , we should have active the Key-tones & CTCSS option.
rxbw.emplace_back(" 200k-WFM ", 0); // locked a fixed option , to display it .
field_rxbw.set_options(rxbw); // store that aux GUI option to the field_rxbw.
field_rxbw.hidden(0); // we are in WFM mode, we need to show to the user the selected BW WFM filer .
field_bw.hidden(0); // we are in WFM mode, we need to allow WFM deviation parameter , in non FM mode.
break;
case 2: //{ "AM", 2 }
enable_am = true;
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.
rxbw.emplace_back(" DSB1-9k ", 0); // we offer in AM DSB two audio BW 9k / 6k .
rxbw.emplace_back(" DSB2-6k ", 1);
field_rxbw.set_options(rxbw); // store that aux GUI option to the field_rxbw.
field_rxbw.hidden(0); // we show fixed RX AM BW 6Khz
field_bw.hidden(1); // we hide the FM TX deviation parameter , in non FM mode.
check_rogerbeep.hidden(0); // make visible again the "rogerbeep" selection.
break;
case 2:
case 3: //{ "USB", 3 }
enable_usb = true;
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.
rxbw.emplace_back(" USB+3k ", 0); // locked a fixed option , to display it .
field_rxbw.set_options(rxbw); // store that aux GUI option to the field_rxbw.
set_dirty(); // Refresh display
break;
case 3:
case 4: //{ "LSB", 4 }
enable_lsb = true;
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.
rxbw.emplace_back(" LSB-3k ", 0); // locked a fixed option , to display it .
field_rxbw.set_options(rxbw); // store that aux GUI option to the field_rxbw.
set_dirty(); // Refresh display
break;
case 4:
case 5: //{ "DSB-SC", 5 }
enable_dsb = true;
rxaudio(rx_enabled); //Update now if we have RX audio on
check_rogerbeep.hidden(0); // make visible again the "rogerbeep" selection.
rxbw.emplace_back("SSB1:USB+3k", 0); // added dynamically two options (index 0,1) to that DSB-C case to the field_rxbw value.
rxbw.emplace_back("SSB2:LSB-3k", 1);
field_rxbw.set_options(rxbw); // store that aux GUI option to the field_rxbw.
break;
}
//configure_baseband();
@@ -448,19 +539,20 @@ MicTXView::MicTXView(
field_volume.on_change = [this](int32_t v) { this->on_headphone_volume_changed(v); };
field_rxbw.on_change = [this](size_t, int32_t v) {
switch(v) {
case 0:
receiver_model.set_nbfm_configuration(0);
break;
case 1:
receiver_model.set_nbfm_configuration(1);
break;
case 2:
receiver_model.set_nbfm_configuration(2);
break;
if (!(enable_am || enable_usb || enable_lsb || enable_dsb || enable_wfm )) {
// In Previous fw versions, that nbfm_configuration(n) was done in any mode (FM/AM/SSB/DSB)...strictly speaking only need it in (NFM/FM)
receiver_model.set_nbfm_configuration(v ); // we are in NFM/FM case, we need to select proper NFM/FM RX channel filter , NFM BW 8K5(0), NFM BW 11K(1) , FM BW 16K (2)
}
else { // we are not in NFM/FM mode .(we could be in any of the rest : AM /USB/LSB/DSB-SC)
if (enable_am) { // we are in AM TX mode , we will allow both independent RX audio BW : AM 9K (9K00AE3 / AM 6K (6K00AE3). (In AM option v can be 0 (9k) , 1 (6k)
receiver_model.set_am_configuration(v ); // we are in AM TX mode , we need to select proper AM full path config AM-9K filter. 0+0 =>AM-9K(0), 0+1=1 =>AM-6K(1),
}
if (enable_dsb) { // we are in DSB-SC in TX mode , we will allow both independent RX SSB demodulation (USB / LSB side band). in that submenu, v is 0 (SSB1 USB) or 1 (SSB2 LSB)
receiver_model.set_am_configuration(v +2 ); // we are in DSB-SC TX mode , we need to select proper SSB filter. 0+2 =>usb(2), 1+2=3 =>lsb(3),
}
}
};
field_rxbw.set_selected_index(2);
field_squelch.on_change = [this](int32_t v) {
receiver_model.set_squelch_level(100 - v);
@@ -537,9 +629,9 @@ MicTXView::MicTXView(
transmitter_model.set_baseband_bandwidth(1750000);
set_tx(false);
audio::set_rate(audio::Rate::Hz_24000);
audio::input::start(); // originally , audio::input::start(); (we added parameter)
audio::set_rate(audio::Rate::Hz_24000);
audio::input::start(ak4951_alc_and_wm8731_boost_GUI); // When detected AK4951 => set up ALC mode; when detected WM8731 => set up mic_boost ON/OFF.
}
MicTXView::~MicTXView() {
@@ -548,7 +640,8 @@ MicTXView::~MicTXView() {
transmitter_model.disable();
if (rx_enabled) //Also turn off audio rx if enabled
rxaudio(false);
baseband::shutdown();
hackrf::cpld::load_sram_no_verify(); // to leave all RX ok, without ghost signal problem at the exit .
baseband::shutdown(); // better this function at the end, not load_sram() that sometimes produces hang up.
}
}
+35 -19
View File
@@ -83,7 +83,7 @@ private:
bool rx_enabled { false };
uint32_t tone_key_index { };
float mic_gain { 1.0 };
uint8_t ak4951_alc_GUI_selected { 0 };
uint8_t ak4951_alc_and_wm8731_boost_GUI { 0 };
uint32_t audio_level { 0 };
uint32_t va_level { };
uint32_t attack_ms { };
@@ -99,18 +99,21 @@ private:
rf::Frequency rx_frequency { 0 };
int32_t focused_ui { 2 };
bool button_touch { false };
uint8_t shift_bits_s16 {4} ; // shift bits factor to the captured ADC S16 audio sample.
//AM TX Stuff
bool enable_am { false };
bool enable_dsb { false };
bool enable_usb { false };
bool enable_lsb { false };
bool enable_wfm { false }; // added to distinguish in the FM mode , RX BW : NFM (8K5, 11K), FM (16K), WFM(200K)
Labels labels_WM8731 {
{ { 3 * 8, 1 * 8 }, "MIC-GAIN:", Color::light_grey() },
{ { 17 * 8, 1 * 8 }, "Boost", Color::light_grey() },
{ { 3 * 8, 3 * 8 }, "F:", Color::light_grey() },
{ { 15 * 8, 3 * 8 }, "BW: FM kHz", Color::light_grey() },
{ { 15 * 8, 3 * 8 }, "FM TXBW: kHz", Color::light_grey() }, // to be more symetric and consistent to the below FM RXBW
{ { 3 * 8, 5 * 8 }, "GAIN:", Color::light_grey() },
{ {11 * 8, 5 * 8 }, "Amp:", Color::light_grey() },
{ { 18 * 8, (5 * 8) }, "Mode:", Color::light_grey() },
@@ -120,7 +123,7 @@ private:
{ {20 * 8, 10 * 8 }, "DEC:", Color::light_grey() },
{ { 4 * 8, ( 13 * 8 ) - 2 }, "TONE KEY:", Color::light_grey() },
{ { 7 * 8, 23 * 8 }, "VOL:", Color::light_grey() },
{ {15 * 8, 23 * 8 }, "FM RXBW:", Color::light_grey() },
{ {14 * 8, 23 * 8 }, "RXBW:", Color::light_grey() }, //we remove the label "FM" because we will display all MOD types RX_BW.
{ {17 * 8, 25 * 8 }, "SQ:", Color::light_grey() },
{ { 5 * 8, 25 * 8 }, "F:", Color::light_grey() },
{ { 5 * 8, 27 * 8 }, "LNA:", Color::light_grey()},
@@ -131,7 +134,7 @@ private:
{ { 3 * 8, 1 * 8 }, "MIC-GAIN:", Color::light_grey() },
{ { 17 * 8, 1 * 8 }, "ALC", Color::light_grey() },
{ { 3 * 8, 3 * 8 }, "F:", Color::light_grey() },
{ { 15 * 8, 3 * 8 }, "BW: FM kHz", Color::light_grey() },
{ { 15 * 8, 3 * 8 }, "FM TXBW: kHz", Color::light_grey() },
{ { 3 * 8, 5 * 8 }, "GAIN:", Color::light_grey() },
{ {11 * 8, 5 * 8 }, "Amp:", Color::light_grey() },
{ { 18 * 8, (5 * 8) }, "Mode:", Color::light_grey() },
@@ -140,8 +143,8 @@ private:
{ {12 * 8, 10 * 8 }, "ATT:", Color::light_grey() },
{ {20 * 8, 10 * 8 }, "DEC:", Color::light_grey() },
{ { 4 * 8, ( 13 * 8 ) - 2 }, "TONE KEY:", Color::light_grey() },
{ { 7 * 8, 23 * 8 }, "VOL:", Color::light_grey() },
{ {15 * 8, 23 * 8 }, "FM RXBW:", Color::light_grey() },
{ { (6 * 8)+4, 23 * 8 }, "VOL:", Color::light_grey() },
{ {14 * 8, 23 * 8 }, "RXBW:", Color::light_grey() }, //we remove the label "FM" because we will display all MOD types RX_BW.
{ {17 * 8, 25 * 8 }, "SQ:", Color::light_grey() },
{ { 5 * 8, 25 * 8 }, "F:", Color::light_grey() },
{ { 5 * 8, 27 * 8 }, "LNA:", Color::light_grey()},
@@ -171,7 +174,7 @@ private:
{ 20 * 8, 1 * 8 }, // Coordinates are: int:x (px), int:y (px)
11,
{
{ " OFF-20kHz", 0 }, // Nothing changed from ORIGINAL,keeping ALL programm. AK4951 Dig. block->OFF)
{ " OFF-12kHz", 0 }, // Nothing changed from ORIGINAL,keeping ALL programmable AK4951 Digital Block->OFF, sampling 24Khz)
{ "+12dB-6kHz", 1 }, // ALC-> on, (+12dB's) Auto Vol max + Wind Noise cancel + LPF 6kHz + Pre-amp Mic (+21dB=original)
{ "+09dB-6kHz", 2 }, // ALC-> on, (+09dB's) Auto Vol max + Wind Noise cancel + LPF 6kHz + Pre-amp Mic (+21dB=original)
{ "+06dB-6kHz", 3 }, // ALC-> on, (+06dB's) Auto Vol max + Wind Noise cancel + LPF 6kHz + Pre-amp Mic (+21dB=original)
@@ -186,11 +189,23 @@ private:
}
};
OptionsField options_wm8731_boost_mode {
{ 22 * 8, 1 * 8 }, // Coordinates are: int:x (px), int:y (px)
5,
{
{ "ON +12dB", 0 }, // WM8731 Mic Boost ON ,original+12dBs condition, easy to saturate ADC sat in high voice ,relative G = +12 dB's respect ref level
{ "ON +06dB", 1 }, // WM8731 Mic Boost ON ,original+6 dBs condition, easy to saturate ADC sat in high voice ,relative G = +06 dB's respect ref level
{ "OFF+04dB", 2 }, // WM8731 Mic Boost OFF to avoid ADC sat in high voice ,relative G = +04 dB's (respect ref level) , always effective sampling 24khz
{ "OFF-02dB", 3 }, // WM8731 Mic Boost OFF to avoid ADC sat in high voice ,relative G = -02 dB's (respect ref level)
{ "OFF-08dB", 4 }, // WM8731 Mic Boost OFF to avoid ADC sat in high voice ,relative G = -12 dB's (respect ref level)
}
};
FrequencyField field_frequency {
{ 5 * 8, 3 * 8 },
};
NumberField field_bw {
{ 18 * 8, 3 * 8 },
{ 23 * 8, 3 * 8 },
3,
{ 0, 150 },
1,
@@ -214,13 +229,14 @@ private:
OptionsField options_mode {
{ 24 * 8, 5 * 8 },
3,
4,
{
{ "FM", 0 },
{ "AM", 1 },
{ "USB", 2 },
{ "LSB", 3 },
{ "DSB", 4 }
{ "NFM/FM", 0 },
{ " WFM ", 1 },
{ " AM ", 2 }, // in fact that TX mode = AM -DSB with carrier .
{ " USB ", 3 },
{ " LSB ", 4 },
{ "DSB-SC", 5 } // We are TX Double Side AM Band with suppressed carrier, and allowing in RX both indep SSB lateral band (USB/LSB).
}
};
/*
@@ -293,13 +309,13 @@ private:
};
OptionsField field_rxbw {
{ 23* 8, 23 * 8},
{ 19* 8, 23 * 8},
3,
{
{"8k5", 0},
{"11k", 1},
{"16k", 2}
}
{" NFM1:8k5 ", 0},
{" NFM2:11k ", 1},
{" FM :16k ", 2},
}
};
NumberField field_squelch {
+3 -1
View File
@@ -26,6 +26,7 @@
#include "baseband_api.hpp"
#include "hackrf_gpio.hpp"
#include "portapack_shared_memory.hpp"
#include "cpld_update.hpp"
#include "ui_textentry.hpp"
#include "string_format.hpp"
@@ -102,7 +103,8 @@ MorseView::~MorseView() {
settings.save("tx_morse", &app_settings);
transmitter_model.disable();
baseband::shutdown();
hackrf::cpld::load_sram_no_verify(); // to leave all RX ok, without ghost signal problem at the exit .
baseband::shutdown(); // better this function at the end, not load_sram() that sometimes produces hang up.
}
void MorseView::paint(Painter&) {
+328
View File
@@ -0,0 +1,328 @@
/*
* Copyright (C) 2016 Jared Boone, ShareBrained Technology, Inc.
* Copyright (C) 2016 Furrtek
* Copyleft () 2022 NotPike
*
* This file is part of PortaPack.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street,
* Boston, MA 02110-1301, USA.
*/
#include "ui_playlist.hpp"
#include "string_format.hpp"
#include "ui_fileman.hpp"
#include "io_file.hpp"
#include "baseband_api.hpp"
#include "portapack.hpp"
#include "portapack_persistent_memory.hpp"
#include <unistd.h>
using namespace portapack;
namespace ui {
void PlaylistView::set_ready() {
ready_signal = true;
}
void PlaylistView::load_file(std::filesystem::path playlist_path) {
File playlist_file;
auto error = playlist_file.open(playlist_path.string());
if (!error.is_valid()) {
std::string line;
char one_char[1];
for (size_t pointer =0 ; pointer < playlist_file.size(); pointer++) {
playlist_file.seek(pointer);
playlist_file.read(one_char, 1);
if ((int) one_char[0] >= ' ') {
line += one_char[0];
} else if (one_char[0] == '\n') {
txtline_process(line);
line.clear();
}
}
if (line.length() > 0) {
txtline_process(line);
}
}
playlist_masterdb = playlist_db;
return ;
}
void PlaylistView::txtline_process(std::string &line) {
playlist_entry new_item;
rf::Frequency f;
size_t previous = 0;
size_t current = line.find(',');
std::string freqs = line.substr(0, current);
previous = current +1;
current = line.find(',', previous);
std::string file = line.substr(previous, current - previous);
previous = current +1;
current = line.find(',', previous);
uint32_t sample_rate = strtoll(line.substr(previous).c_str(), nullptr, 10);
f = strtoll(freqs.c_str(), nullptr, 0);
new_item.replay_frequency = f;
new_item.replay_file = "/" + file;
new_item.sample_rate = sample_rate;
new_item.next_delay = 0;
playlist_db.push_back(std::move(new_item));
}
void PlaylistView::on_file_changed(std::filesystem::path new_file_path, rf::Frequency replay_frequency, uint32_t replay_sample_rate) {
File data_file;
// Get file size
auto data_open_error = data_file.open("/" + new_file_path.string());
if (data_open_error.is_valid()) {
file_error();
return;
}
file_path = new_file_path;
field_frequency.set_value(replay_frequency);
sample_rate = replay_sample_rate;
text_sample_rate.set(unit_auto_scale(sample_rate, 3, 0) + "Hz");
auto file_size = data_file.size();
auto duration = (file_size * 1000) / (2 * 2 * sample_rate);
progressbar.set_max(file_size);
text_filename.set(file_path.filename().string().substr(0, 12));
text_duration.set(to_string_time_ms(duration));
button_play.focus();
}
void PlaylistView::on_tx_progress(const uint32_t progress) {
progressbar.set_value(progress);
}
void PlaylistView::focus() {
button_open.focus();
}
void PlaylistView::file_error() {
nav_.display_modal("Error", "File "+file_path.string() +" read error. " +file_path.string());
}
bool PlaylistView::is_active() const {
return (bool)replay_thread;
}
bool PlaylistView::loop() const {
return (bool) playlist_db.size();
}
void PlaylistView::toggle() {
if( is_active() ) {
stop(false);
} else {
start();
}
}
void PlaylistView::start() {
stop(false);
playlist_entry item = playlist_db.front();
playlist_db.pop_front();
// playlist_entry item = playlist_db[0];
// for (playlist_entry item : playlist_db) {
// file_path = item.replay_file;
// rf::Frequency replay_frequency = strtoll(item.replay_frequency.c_str(),nullptr,10);
on_file_changed(item.replay_file, item.replay_frequency, item.sample_rate);
on_target_frequency_changed(item.replay_frequency);
std::unique_ptr<stream::Reader> reader;
auto p = std::make_unique<FileReader>();
auto open_error = p->open(file_path);
if( open_error.is_valid() ) {
file_error();
return; // Fixes TX bug if there's a file error
} else {
reader = std::move(p);
}
if( reader ) {
button_play.set_bitmap(&bitmap_stop);
baseband::set_sample_rate(sample_rate * 8);
replay_thread = std::make_unique<ReplayThread>(
std::move(reader),
read_size, buffer_count,
&ready_signal,
[](uint32_t return_code) {
ReplayThreadDoneMessage message { return_code };
EventDispatcher::send_message(message);
}
);
}
field_rfgain.on_change = [this](int32_t v) {
tx_gain = v;
};
field_rfgain.set_value(tx_gain);
receiver_model.set_tx_gain(tx_gain);
field_rfamp.on_change = [this](int32_t v) {
rf_amp = (bool)v;
};
field_rfamp.set_value(rf_amp ? 14 : 0);
//Enable Bias Tee if selected
radio::set_antenna_bias(portapack::get_antenna_bias());
radio::enable({
receiver_model.tuning_frequency(),
sample_rate * 8,
baseband_bandwidth,
rf::Direction::Transmit,
rf_amp, // previous code line : "receiver_model.rf_amp()," was passing the same rf_amp of all Receiver Apps
static_cast<int8_t>(receiver_model.lna()),
static_cast<int8_t>(receiver_model.vga())
});
// }
}
void PlaylistView::stop(const bool do_loop) {
if( is_active() ) {
replay_thread.reset();
}
if (do_loop) {
if (playlist_db.size() > 0 ) {
start();
} else {
playlist_db = playlist_masterdb;
start();
}
} else {
radio::set_antenna_bias(false); //Turn off Bias Tee
radio::disable();
button_play.set_bitmap(&bitmap_play);
}
ready_signal = false;
}
void PlaylistView::handle_replay_thread_done(const uint32_t return_code) {
if (return_code == ReplayThread::END_OF_FILE) {
stop(true);
} else if (return_code == ReplayThread::READ_ERROR) {
stop(false);
file_error();
}
progressbar.set_value(0);
}
PlaylistView::PlaylistView(
NavigationView& nav
) : nav_ (nav)
{
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)
baseband::run_image(portapack::spi_flash::image_tag_replay);
add_children({
&labels,
&button_open,
&text_filename,
&text_sample_rate,
&text_duration,
&progressbar,
&field_frequency,
&field_rfgain,
&field_rfamp, // let's not use common rf_amp
&check_loop,
&button_play,
&waterfall,
});
field_frequency.set_value(target_frequency());
field_frequency.set_step(receiver_model.frequency_step());
field_frequency.on_change = [this](rf::Frequency f) {
this->on_target_frequency_changed(f);
};
field_frequency.on_edit = [this, &nav]() {
// TODO: Provide separate modal method/scheme?
auto new_view = nav.push<FrequencyKeypadView>(this->target_frequency());
new_view->on_changed = [this](rf::Frequency f) {
this->on_target_frequency_changed(f);
this->field_frequency.set_value(f);
};
};
field_frequency.set_step(5000);
button_play.on_select = [this](ImageButton&) {
this->toggle();
};
button_open.on_select = [this, &nav](Button&) {
auto open_view = nav.push<FileLoadView>(".TXT");
open_view->on_changed = [this](std::filesystem::path new_file_path) {
load_file(new_file_path);
};
};
}
PlaylistView::~PlaylistView() {
radio::disable();
baseband::shutdown();
}
void PlaylistView::on_hide() {
stop(false);
// TODO: Terrible kludge because widget system doesn't notify Waterfall that
// it's being shown or hidden.
waterfall.on_hide();
View::on_hide();
}
void PlaylistView::set_parent_rect(const Rect new_parent_rect) {
View::set_parent_rect(new_parent_rect);
const ui::Rect waterfall_rect { 0, header_height, new_parent_rect.width(), new_parent_rect.height() - header_height };
waterfall.set_parent_rect(waterfall_rect);
}
void PlaylistView::on_target_frequency_changed(rf::Frequency f) {
set_target_frequency(f);
}
void PlaylistView::set_target_frequency(const rf::Frequency new_value) {
persistent_memory::set_tuned_frequency(new_value);;
}
rf::Frequency PlaylistView::target_frequency() const {
return persistent_memory::tuned_frequency();
}
} /* namespace ui */
+176
View File
@@ -0,0 +1,176 @@
/*
* Copyright (C) 2016 Jared Boone, ShareBrained Technology, Inc.
* Copyright (C) 2016 Furrtek
*
* This file is part of PortaPack.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street,
* Boston, MA 02110-1301, USA.
*/
#include "ui_widget.hpp"
#include "ui_navigation.hpp"
#include "ui_receiver.hpp"
#include "replay_thread.hpp"
#include "ui_spectrum.hpp"
#include <string>
#include <memory>
#include <deque>
namespace ui {
class PlaylistView : public View {
public:
PlaylistView(NavigationView& nav);
~PlaylistView();
void on_hide() override;
void set_parent_rect(const Rect new_parent_rect) override;
void focus() override;
std::string title() const override { return "Playlist"; };
private:
NavigationView& nav_;
static constexpr ui::Dim header_height = 3 * 16;
struct playlist_entry {
rf::Frequency replay_frequency { 0 };
std::string replay_file{};
uint32_t sample_rate{};
uint32_t next_delay{};
};
std::deque<playlist_entry> playlist_db{};
std::deque<playlist_entry> playlist_masterdb{};
uint32_t sample_rate = 0;
int32_t tx_gain { 47 };
bool rf_amp { true }; // aux private var to store temporal, Replay App rf_amp user selection.
static constexpr uint32_t baseband_bandwidth = 2500000;
const size_t read_size { 16384 };
const size_t buffer_count { 3 };
void load_file(std::filesystem::path playlist_path);
void txtline_process(std::string &);
void on_file_changed(std::filesystem::path new_file_path, rf::Frequency replay_frequency, uint32_t replay_sample_rate);
void on_target_frequency_changed(rf::Frequency f);
void on_tx_progress(const uint32_t progress);
void set_target_frequency(const rf::Frequency new_value);
rf::Frequency target_frequency() const;
void toggle();
void start();
void stop(const bool do_loop);
bool is_active() const;
bool loop() const;
void set_ready();
void handle_replay_thread_done(const uint32_t return_code);
void file_error();
std::filesystem::path file_path { };
std::unique_ptr<ReplayThread> replay_thread { };
bool ready_signal { false };
Labels labels {
{ { 10 * 8, 2 * 16 }, "GAIN A:", Color::light_grey() }
};
Button button_open {
{ 0 * 8, 0 * 16, 10 * 8, 2 * 16 },
"Open file"
};
Text text_filename {
{ 11 * 8, 0 * 16, 12 * 8, 16 },
"-"
};
Text text_sample_rate {
{ 24 * 8, 0 * 16, 6 * 8, 16 },
"-"
};
Text text_duration {
{ 11 * 8, 1 * 16, 6 * 8, 16 },
"-"
};
ProgressBar progressbar {
{ 18 * 8, 1 * 16, 12 * 8, 16 }
};
FrequencyField field_frequency {
{ 0 * 8, 2 * 16 },
};
NumberField field_rfgain {
{ 14 * 8, 2 * 16 },
2,
{ 0, 47 },
1,
' '
};
NumberField field_rfamp { // previously I was using "RFAmpField field_rf_amp" but that is general Receiver amp setting.
{ 19 * 8, 2 * 16 },
2,
{ 0, 14 }, // this time we will display GUI , 0 or 14 dBs same as Mic App
14,
' '
};
Checkbox check_loop {
{ 21 * 8, 2 * 16 },
4,
"Loop",
true
};
ImageButton button_play {
{ 28 * 8, 2 * 16, 2 * 8, 1 * 16 },
&bitmap_play,
Color::green(),
Color::black()
};
spectrum::WaterfallWidget waterfall { };
MessageHandlerRegistration message_handler_replay_thread_error {
Message::ID::ReplayThreadDone,
[this](const Message* const p) {
const auto message = *reinterpret_cast<const ReplayThreadDoneMessage*>(p);
this->handle_replay_thread_done(message.return_code);
}
};
MessageHandlerRegistration message_handler_fifo_signal {
Message::ID::RequestSignal,
[this](const Message* const p) {
const auto message = static_cast<const RequestSignalMessage*>(p);
if (message->signal == RequestSignalMessage::Signal::FillRequest) {
this->set_ready();
}
}
};
MessageHandlerRegistration message_handler_tx_progress {
Message::ID::TXProgress,
[this](const Message* const p) {
const auto message = *reinterpret_cast<const TXProgressMessage*>(p);
this->on_tx_progress(message.progress);
}
};
};
} /* namespace ui */
+3 -1
View File
@@ -23,6 +23,7 @@
#include "ui_pocsag_tx.hpp"
#include "baseband_api.hpp"
#include "cpld_update.hpp"
#include "string_format.hpp"
#include "ui_textentry.hpp"
@@ -43,7 +44,8 @@ POCSAGTXView::~POCSAGTXView() {
settings.save("tx_pocsag", &app_settings);
transmitter_model.disable();
baseband::shutdown();
hackrf::cpld::load_sram_no_verify(); // to leave all RX ok, without ghost signal problem at the exit
baseband::shutdown(); // better this function at the end, not load_sram() that sometimes produces hang up.
}
void POCSAGTXView::on_tx_progress(const uint32_t progress, const bool done) {
+3 -1
View File
@@ -24,6 +24,7 @@
#include "portapack.hpp"
#include "baseband_api.hpp"
#include "cpld_update.hpp"
#include "portapack_shared_memory.hpp"
#include <cstring>
@@ -180,7 +181,8 @@ RDSView::~RDSView() {
settings.save("tx_rds", &app_settings);
transmitter_model.disable();
baseband::shutdown();
hackrf::cpld::load_sram_no_verify(); // to leave all RX ok, without ghost signal problem at the exit.
baseband::shutdown(); // better this function at the end, not load_sram() that sometimes produces hang up.
}
void RDSView::start_tx() {
File diff suppressed because it is too large Load Diff
+403
View File
@@ -0,0 +1,403 @@
/*
* Copyright (C) 2015 Jared Boone, ShareBrained Technology, Inc.
* Copyright (C) 2018 Furrtek
*
* This file is part of PortaPack.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street,
* Boston, MA 02110-1301, USA.
*/
#ifndef _UI_RECON
#define _UI_RECON
#include "ui.hpp"
#include "receiver_model.hpp"
#include "ui_receiver.hpp"
#include "ui_font_fixed_8x16.hpp"
#include "freqman.hpp"
#include "analog_audio_app.hpp"
#include "audio.hpp"
#include "ui_mictx.hpp"
#include "portapack_persistent_memory.hpp"
#include "baseband_api.hpp"
#include "string_format.hpp"
#include "file.hpp"
#include "app_settings.hpp"
namespace ui {
class ReconThread {
public:
ReconThread(freqman_db *database );
~ReconThread();
void set_recon(const bool v);
void set_freq_delete(const bool v);
bool is_recon();
void set_lock_duration( const uint32_t v );
uint32_t get_lock_duration();
void set_lock_nb_match( const uint32_t v );
void set_match_mode( const uint32_t v );
uint32_t get_lock_nb_match();
void set_freq_lock(const uint32_t v);
uint32_t is_freq_lock();
int64_t get_current_freq();
void set_stepper(const int64_t v);
void change_recon_direction();
bool get_recon_direction();
void set_recon_direction( const bool v);
void set_continuous(const bool v);
void set_default_modulation( freqman_index_t index );
freqman_index_t get_current_modulation();
void set_default_bandwidth( freqman_index_t index );
freqman_index_t get_current_bandwidth();
void set_default_step( freqman_index_t index );
void set_freq_index( int16_t index );
int16_t get_freq_index();
void run();
void stop();
ReconThread(const ReconThread&) = delete;
ReconThread(ReconThread&&) = delete;
ReconThread& operator=(const ReconThread&) = delete;
ReconThread& operator=(ReconThread&&) = delete;
private:
freqman_db &frequency_list_ ;
Thread* thread { nullptr };
int64_t freq = 0 ;
uint32_t step = 0 ;
freqman_index_t def_modulation = 0 ;
freqman_index_t def_bandwidth = 0 ;
freqman_index_t def_step = 0 ;
tone_index tone = 0 ;
freqman_entry last_entry = { } ;
int16_t frequency_index = 0 ;
bool _recon { true };
bool _freq_delete { false };
bool _fwd { true };
bool _continuous { true };
int64_t _stepper { 0 };
int32_t _freq_lock { 0 };
uint32_t _lock_duration { 50 };
uint32_t _lock_nb_match { 10 };
static msg_t static_fn(void* arg);
};
class ReconView : public View {
public:
ReconView(NavigationView& nav);
~ReconView();
void focus() override;
void big_display_freq( int64_t f );
const Style style_grey { // recon
.font = font::fixed_8x16,
.background = Color::black(),
.foreground = Color::grey(),
};
const Style style_white { // recon
.font = font::fixed_8x16,
.background = Color::black(),
.foreground = Color::white(),
};
const Style style_yellow { //Found signal
.font = font::fixed_8x16,
.background = Color::black(),
.foreground = Color::yellow(),
};
const Style style_green { //Found signal
.font = font::fixed_8x16,
.background = Color::black(),
.foreground = Color::green(),
};
const Style style_red { //erasing freq
.font = font::fixed_8x16,
.background = Color::black(),
.foreground = Color::red(),
};
const Style style_blue { // quick recon, wait == 0
.font = font::fixed_8x16,
.background = Color::black(),
.foreground = Color::blue(),
};
std::string title() const override { return "Recon"; };
//void set_parent_rect(const Rect new_parent_rect) override;
private:
NavigationView& nav_;
void start_recon_thread();
size_t change_mode( freqman_index_t mod_type);
void show_max( bool refresh_display = false );
void recon_pause();
void recon_resume();
void user_pause();
void user_resume();
void frequency_file_load( bool stop_all_before = false);
void on_statistics_update(const ChannelStatistics& statistics);
void on_headphone_volume_changed(int32_t v);
void set_display_freq( int64_t freq );
void handle_retune( int64_t freq , uint32_t index );
bool check_sd_card();
jammer::jammer_range_t frequency_range { false, 0, 0 }; //perfect for manual recon task too...
int32_t squelch { 0 };
int32_t db { 0 };
int32_t timer { 0 };
int32_t wait { 5000 }; // in msec. if > 0 wait duration after a lock, if < 0 duration is set to 'wait' unless there is no more activity
uint32_t lock_wait { 500 }; // in msec. Represent the maximum amount of time we will wait for a lock to complete before switching to next
int32_t def_step { 0 };
freqman_db frequency_list = { };
uint32_t current_index { 0 };
bool userpause { false };
bool continuous_lock { false };
std::string input_file = { "RECON" };
std::string output_file = { "RECON_RESULTS" };
bool autosave = { true };
bool autostart = { true };
bool continuous = { true };
bool filedelete = { true };
bool load_freqs = { true };
bool load_ranges = { true };
bool load_hamradios = { true };
bool update_ranges = { true };
bool fwd = { true };
// maximum usable freq
long long int MAX_UFREQ = { 7200000000 };
uint32_t recon_lock_nb_match = { 10 };
uint32_t recon_lock_duration = { 50 };
uint32_t recon_match_mode = { 0 };
bool scanner_mode { false };
bool manual_mode { false };
bool sd_card_mounted = false ;
int32_t volume = 40 ;
Labels labels
{
{ { 0 * 8 , 0 * 16 }, "LNA: VGA: AMP: VOL: ", Color::light_grey() },
{ { 0 * 8 , 1 * 16 }, "BW: SQ: W,L: , ", Color::light_grey() },
{ { 3 * 8 , 10 * 16 }, "START END MANUAL", Color::light_grey() },
{ { 0 * 8 , (26 * 8) + 4 }, "MODE:", Color::light_grey() },
{ { 11 * 8 , (26 * 8) + 4 }, "STEP:", Color::light_grey() },
};
LNAGainField field_lna {
{ 4 * 8, 0 * 16 }
};
VGAGainField field_vga {
{ 11 * 8, 0 * 16 }
};
RFAmpField field_rf_amp {
{ 18 * 8, 0 * 16 }
};
NumberField field_volume {
{ 24 * 8, 0 * 16 },
2,
{ 0, 99 },
1,
' ',
};
OptionsField field_bw {
{ 3 * 8, 1 * 16 },
6,
{ }
};
NumberField field_squelch {
{ 12 * 8, 1 * 16 },
3,
{ -90, 20 },
1,
' ',
};
NumberField field_wait {
{ 20 * 8, 1 * 16 },
5,
{ -9000, 9000 },
100,
' ',
};
NumberField field_lock_wait {
{ 26 * 8, 1 * 16 },
4,
{ 100 , 9000 },
100,
' ',
};
RSSI rssi {
{ 0 * 16, 2 * 16, 15 * 16, 8 },
};
Text text_cycle {
{ 0, 3 * 16, 3 * 8, 16 },
};
Text text_max {
{ 3 * 8, 3 * 16, 20 * 8 , 16 },
};
Text desc_cycle {
{0, 4 * 16, 240, 16 },
};
/* BigFrequency big_display { //Show frequency in glamour
{ 4, 7 * 16 - 8 , 28 * 8, 52 },
0
}; */
Text big_display { //Show frequency in text mode
{ 0, 5 * 16 , 28 * 8, 16 },
};
Text freq_stats { //Show frequency stats in text mode
{ 0, 6 * 16 , 28 * 8, 16 },
};
Text text_timer { //Show frequency stats in text mode
{ 0, 7 * 16 , 28 * 8, 16 },
};
Button button_recon_setup {
{ 25 * 8 , 2 * 16 + 8 , 4 * 8, 28 },
"OPT"
};
Button button_scanner_mode {
{ 21 * 8 , 8 * 16 , 9 * 8, 28 },
"RECON"
};
Text file_name { //Show file used
{ 0 , 8 * 16 + 4 , 20 * 8, 16 },
};
ButtonWithEncoder button_manual_start {
{ 0 * 8, 11 * 16, 11 * 8, 28 },
""
};
ButtonWithEncoder button_manual_end {
{ 12 * 8 - 6, 11 * 16, 11 * 8, 28 },
""
};
Button button_manual_recon {
{ 23 * 8 - 3, 11 * 16, 7 * 8 , 28 },
"SEARCH"
};
OptionsField field_mode {
{ 5 * 8, (26 * 8) + 4 },
6,
{
}
};
OptionsField step_mode {
{ 17 * 8, (26 * 8) + 4 },
12,
{
}
};
ButtonWithEncoder button_pause {
{ 0, (15 * 16) - 4, 72, 28 },
"PAUSE"
};
Button button_audio_app {
{ 84, (15 * 16) - 4, 72, 28 },
"AUDIO"
};
ButtonWithEncoder button_add {
{ 168, (15 * 16) - 4, 72, 28 },
"<STORE>"
};
Button button_dir {
{ 0, (35 * 8) - 4, 34, 28 },
"FW>"
};
Button button_restart {
{ 38, (35 * 8) - 4, 34, 28 },
"RST"
};
Button button_mic_app {
{ 84, (35 * 8) - 4, 72, 28 },
"MIC TX"
};
ButtonWithEncoder button_remove {
{ 168, (35 * 8) - 4, 72, 28 },
"<REMOVE>"
};
std::unique_ptr<ReconThread> recon_thread { };
MessageHandlerRegistration message_handler_retune {
Message::ID::Retune,
[this](const Message* const p) {
const auto message = *reinterpret_cast<const RetuneMessage*>(p);
this->handle_retune(message.freq,message.range);
}
};
MessageHandlerRegistration message_handler_stats {
Message::ID::ChannelStatistics,
[this](const Message* const p) {
this->on_statistics_update(static_cast<const ChannelStatisticsMessage*>(p)->statistics);
}
};
// app save settings
std::app_settings settings { };
std::app_settings::AppSettings app_settings { };
};
} /* namespace ui */
#endif
@@ -0,0 +1,301 @@
/*
* Copyright (C) 2015 Jared Boone, ShareBrained Technology, Inc.
* Copyright (C) 2016 Furrtek
*
* This file is part of PortaPack.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street,
* Boston, MA 02110-1301, USA.
*/
#include "ui_recon_settings.hpp"
#include "ui_navigation.hpp"
#include "ui_fileman.hpp"
#include "ui_textentry.hpp"
#include "file.hpp"
#include "portapack.hpp"
#include "portapack_persistent_memory.hpp"
using namespace std;
using namespace portapack;
namespace ui {
bool ReconSetupLoadStrings( std::string source, std::string &input_file , std::string &output_file , uint32_t &recon_lock_duration , uint32_t &recon_lock_nb_match , int32_t &recon_squelch_level , uint32_t &recon_match_mode , int32_t &wait , uint32_t &lock_wait , int32_t &volume )
{
File settings_file;
size_t length, file_position = 0;
char * pos;
char * line_start;
char * line_end;
char file_data[257];
uint32_t it = 0 ;
uint32_t nb_params = 9 ;
std::string params[ 9 ];
bool check_sd_card = (sd_card::status() == sd_card::Status::Mounted) ? true : false ;
if( check_sd_card )
{
auto result = settings_file.open( source );
if( !result.is_valid() )
{
while( it < nb_params )
{
// Read a 256 bytes block from file
settings_file.seek(file_position);
memset(file_data, 0, 257);
auto read_size = settings_file.read(file_data, 256);
if (read_size.is_error())
break ;
file_position += 256;
// Reset line_start to beginning of buffer
line_start = file_data;
pos=line_start;
while ((line_end = strstr(line_start, "\x0A"))) {
length = line_end - line_start - 1 ;
params[ it ] = string( pos , length );
it ++ ;
line_start = line_end + 1;
pos=line_start ;
if (line_start - file_data >= 256)
break;
if( it >= nb_params )
break ;
}
if (read_size.value() != 256)
break; // End of file
// Restart at beginning of last incomplete line
file_position -= (file_data + 256 - line_start);
}
}
}
if( it > 0 )
input_file = params[ 0 ];
else
input_file = "RECON" ;
if( it > 1 )
output_file= params[ 1 ];
else
output_file = "RECON_RESULTS" ;
if( it > 2 )
recon_lock_duration = strtoll( params[ 2 ].c_str() , nullptr , 10 );
else
recon_lock_duration = 50 ;
if( it > 3 )
recon_lock_nb_match = strtoll( params[ 3 ].c_str() , nullptr , 10 );
else
recon_lock_nb_match = 10 ;
if( it > 4 )
recon_squelch_level = strtoll( params[ 4 ].c_str() , nullptr , 10 );
else
recon_squelch_level = -14 ;
if( it > 5 )
recon_match_mode = strtoll( params[ 5 ].c_str() , nullptr , 10 );
else
recon_match_mode = 0 ;
if( it > 6 )
wait = strtoll( params[ 6 ].c_str() , nullptr , 10 );
else
wait = 5000 ;
if( it > 7 )
lock_wait = strtoll( params[ 7 ].c_str() , nullptr , 10 );
else
lock_wait = 1000 ;
if( it > 8 )
volume = strtoll( params[ 8 ].c_str() , nullptr , 10 );
else
volume = 40 ;
if( it < nb_params )
{
/* bad number of params, signal defaults */
return false ;
}
return true ;
}
bool ReconSetupSaveStrings( std::string dest, std::string input_file , std::string output_file , uint32_t recon_lock_duration , uint32_t recon_lock_nb_match , int32_t recon_squelch_level , uint32_t recon_match_mode , int32_t wait , uint32_t lock_wait , int32_t volume )
{
File settings_file;
auto result = settings_file.create( dest );
if( result.is_valid() )
return false ;
settings_file.write_line( input_file );
settings_file.write_line( output_file );
settings_file.write_line( to_string_dec_uint( recon_lock_duration ) );
settings_file.write_line( to_string_dec_uint( recon_lock_nb_match ) );
settings_file.write_line( to_string_dec_int( recon_squelch_level ) );
settings_file.write_line( to_string_dec_uint( recon_match_mode ) );
settings_file.write_line( to_string_dec_int( wait ) );
settings_file.write_line( to_string_dec_uint( lock_wait ) );
settings_file.write_line( to_string_dec_int( volume ) );
return true ;
}
ReconSetupViewMain::ReconSetupViewMain( NavigationView &nav , Rect parent_rect , std::string input_file , std::string output_file ) : View( parent_rect ) , _input_file { input_file } , _output_file { output_file }
{
hidden(true);
add_children({
&button_load_freqs,
&text_input_file,
&button_save_freqs,
&button_output_file,
&checkbox_autosave_freqs,
&checkbox_autostart_recon,
&checkbox_continuous,
&checkbox_clear_output
});
checkbox_autosave_freqs.set_value( persistent_memory::recon_autosave_freqs() );
checkbox_autostart_recon.set_value( persistent_memory::recon_autostart_recon() );
checkbox_continuous.set_value( persistent_memory::recon_continuous() );
checkbox_clear_output.set_value( persistent_memory::recon_clear_output() );
text_input_file.set( _input_file );
button_output_file.set_text( _output_file );
button_load_freqs.on_select = [this, &nav](Button&) {
auto open_view = nav.push<FileLoadView>(".TXT");
open_view->on_changed = [this,&nav](std::filesystem::path new_file_path) {
std::string dir_filter = "FREQMAN/";
std::string str_file_path = new_file_path.string();
if (str_file_path.find(dir_filter) != string::npos) { // assert file from the FREQMAN folder
// get the filename without txt extension so we can use load_freqman_file fcn
_input_file = new_file_path.stem().string();
text_input_file.set( _input_file );
} else {
nav.display_modal("LOAD ERROR", "A valid file from\nFREQMAN directory is\nrequired.");
}
};
};
button_save_freqs.on_select = [this, &nav](Button&) {
auto open_view = nav.push<FileLoadView>(".TXT");
open_view->on_changed = [this,&nav](std::filesystem::path new_file_path) {
std::string dir_filter = "FREQMAN/";
std::string str_file_path = new_file_path.string();
if (str_file_path.find(dir_filter) != string::npos) { // assert file from the FREQMAN folder
_output_file = new_file_path.stem().string();
button_output_file.set_text( _output_file );
} else {
nav.display_modal("LOAD ERROR", "A valid file from\nFREQMAN directory is\nrequired.");
}
};
};
button_output_file.on_select =[this, &nav](Button&) {
text_prompt( nav, _output_file , 28 ,
[this](std::string& buffer) {
_output_file = buffer ;
button_output_file.set_text( _output_file );
} );
};
};
void ReconSetupViewMain::Save( std::string &input_file , std::string &output_file ) {
persistent_memory::set_recon_autosave_freqs(checkbox_autosave_freqs.value());
persistent_memory::set_recon_autostart_recon(checkbox_autostart_recon.value());
persistent_memory::set_recon_continuous(checkbox_continuous.value());
persistent_memory::set_recon_clear_output(checkbox_clear_output.value());
input_file=_input_file ;
output_file=_output_file ;
};
void ReconSetupViewMore::Save( uint32_t &recon_lock_duration , uint32_t &recon_lock_nb_match , uint32_t &recon_match_mode ) {
persistent_memory::set_recon_load_freqs(checkbox_load_freqs.value());
persistent_memory::set_recon_load_ranges(checkbox_load_ranges.value());
persistent_memory::set_recon_load_hamradios(checkbox_load_hamradios.value());
persistent_memory::set_recon_update_ranges_when_recon(checkbox_update_ranges_when_recon.value());
recon_lock_duration = field_recon_lock_duration.value();
recon_lock_nb_match = field_recon_lock_nb_match.value();
recon_match_mode = field_recon_match_mode . selected_index_value() ;
};
void ReconSetupViewMain::focus() {
button_load_freqs.focus();
}
ReconSetupViewMore::ReconSetupViewMore( NavigationView &nav , Rect parent_rect , uint32_t recon_lock_duration , uint32_t recon_lock_nb_match , uint32_t recon_match_mode ) : View( parent_rect ), _recon_lock_duration { recon_lock_duration } , _recon_lock_nb_match { recon_lock_nb_match } , _recon_match_mode { recon_match_mode }
{
(void)nav;
hidden(true);
add_children({
&checkbox_load_freqs,
&checkbox_load_ranges,
&checkbox_load_hamradios,
&checkbox_update_ranges_when_recon,
&text_recon_lock_duration,
&field_recon_lock_duration,
&text_recon_lock_nb,
&field_recon_lock_nb_match,
&field_recon_match_mode,
});
checkbox_load_freqs.set_value( persistent_memory::recon_load_freqs() );
checkbox_load_ranges.set_value( persistent_memory::recon_load_ranges() );
checkbox_load_hamradios.set_value( persistent_memory::recon_load_hamradios() );
checkbox_update_ranges_when_recon.set_value( persistent_memory::recon_update_ranges_when_recon() );
field_recon_lock_duration.set_value( _recon_lock_duration );
field_recon_lock_nb_match.set_value( _recon_lock_nb_match );
field_recon_match_mode.set_by_value( _recon_match_mode );
};
void ReconSetupViewMore::focus() {
checkbox_load_freqs.focus();
}
void ReconSetupView::focus() {
viewMain.focus();
}
ReconSetupView::ReconSetupView(
NavigationView& nav , std::string _input_file , std::string _output_file , uint32_t _recon_lock_duration , uint32_t _recon_lock_nb_match , uint32_t _recon_match_mode ) : nav_ { nav } , input_file { _input_file } , output_file { _output_file } , recon_lock_duration { _recon_lock_duration } , recon_lock_nb_match { _recon_lock_nb_match } , recon_match_mode { _recon_match_mode }
{
add_children({
&tab_view,
&viewMain,
&viewMore,
&button_save
});
button_save.on_select = [this,&nav](Button&) {
viewMain.Save( input_file , output_file );
viewMore.Save( recon_lock_duration , recon_lock_nb_match , recon_match_mode );
std::vector<std::string> messages ;
messages.push_back( input_file );
messages.push_back( output_file );
messages.push_back( to_string_dec_uint( recon_lock_duration ) );
messages.push_back( to_string_dec_uint( recon_lock_nb_match ) );
messages.push_back( to_string_dec_uint( recon_match_mode ) );
on_changed( messages );
nav.pop();
};
}
} /* namespace ui */
@@ -0,0 +1,194 @@
/*
* Copyright (C) 2014 Jared Boone, ShareBrained Technology, Inc.
* Copyright (C) 2016 Furrtek
*
* This file is part of PortaPack.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street,
* Boston, MA 02110-1301, USA.
*/
#include "serializer.hpp"
#include "ui.hpp"
#include "ui_widget.hpp"
#include "ui_tabview.hpp"
#include "ui_navigation.hpp"
#include "string_format.hpp"
namespace ui {
bool ReconSetupLoadStrings( std::string source, std::string &input_file , std::string &output_file , uint32_t &recon_lock_duration , uint32_t &recon_lock_nb_match , int32_t &recon_squelch_level , uint32_t &recon_match_mode , int32_t &wait , uint32_t &lock_wait , int32_t &volume );
bool ReconSetupSaveStrings( std::string dest, const std::string input_file , const std::string output_file , const uint32_t recon_lock_duration , const uint32_t recon_lock_nb_match , int32_t recon_squelch_level , uint32_t recon_match_mode , int32_t wait , uint32_t lock_wait , int32_t volume );
class ReconSetupViewMain : public View {
public:
ReconSetupViewMain( NavigationView& nav, Rect parent_rect , std::string input_file , std::string output_file );
void Save( std::string &input_file , std::string &output_file );
void focus() override;
private:
std::string _input_file = { "RECON" };
std::string _output_file = { "RECON_RESULTS" };
Button button_load_freqs {
{ 1 * 8 , 12 , 18 * 8 , 22 },
"select input file"
};
Text text_input_file {
{ 1 * 8 , 4 + 2 * 16, 18 * 8, 22 },
"RECON"
};
Button button_save_freqs {
{ 1 * 8 , 4 * 16 - 8 , 18 * 8 , 22 },
"select output file"
};
Button button_output_file {
{ 1 * 8 , 5 * 16 - 2, 18 * 8, 22 },
"RECON_RESULTS"
};
Checkbox checkbox_autosave_freqs {
{ 1 * 8, 7 * 16 - 4 },
3,
"autosave freqs"
};
Checkbox checkbox_autostart_recon {
{ 1 * 8, 9 * 16 - 4 },
3,
"autostart recon"
};
Checkbox checkbox_continuous {
{ 1 * 8, 11 * 16 - 4 },
3,
"continuous"
};
Checkbox checkbox_clear_output {
{ 1 * 8, 13 * 16 - 4 },
3,
"clear output at start"
};
};
class ReconSetupViewMore : public View {
public:
ReconSetupViewMore( NavigationView& nav, Rect parent_rect , const uint32_t _recon_lock_duration , const uint32_t _recon_lock_nb_match , const uint32_t _recon_match_mode );
void Save( uint32_t &recon_lock_duration , uint32_t &recon_lock_nb_match , uint32_t &recon_match_mode );
void focus() override;
private:
const uint32_t _recon_lock_duration = 50 ;
const uint32_t _recon_lock_nb_match = 10 ;
const uint32_t _recon_match_mode = 0 ;
Checkbox checkbox_load_freqs {
{ 1 * 8, 12 },
3,
"input: load freqs"
};
Checkbox checkbox_load_ranges {
{ 1 * 8, 42 },
3,
"input: load ranges"
};
Checkbox checkbox_load_hamradios {
{ 1 * 8, 72 },
3,
"input: load hamradios"
};
Checkbox checkbox_update_ranges_when_recon {
{ 1 * 8, 102 },
3,
"auto update m-ranges"
};
Text text_recon_lock_duration {
{ 1 * 8 , 132 , 22 * 8 , 22 },
" ms (lock duration)"
};
NumberField field_recon_lock_duration {
{ 1 * 8, 132 }, // position X , Y
4, // number of displayed digits (even empty)
{ 50 , 990 }, // range of number
10, // rotary encoder increment
' ', // filling character
false // can loop
};
Text text_recon_lock_nb {
{ 1 * 8 , 162 , 25 * 8 , 22 },
" x (nb lock to match freq)"
};
NumberField field_recon_lock_nb_match {
{ 1 * 8, 162 },
4,
{ 1, 99 },
1,
' ',
false
};
OptionsField field_recon_match_mode {
{ 1 * 8, 192 },
20, // CONTINUOUS MATCH MODE / SPARSE TIMED MATCH MODE
{
{ "SQL MATCH: CONTINOUS" , 0 },
{ "SQL MATCH: SPARSE" , 1 }
}
};
};
class ReconSetupView : public View {
public:
ReconSetupView( NavigationView& nav , std::string _input_file , std::string _output_file , const uint32_t _recon_lock_duration , const uint32_t _recon_lock_nb_match , const uint32_t _recon_match_mode );
std::function<void( std::vector<std::string> messages )> on_changed { };
void focus() override;
std::string title() const override { return "Recon setup"; };
private:
NavigationView& nav_ ;
std::string input_file = { "RECON" };
std::string output_file = { "RECON_RESULTS" };
uint32_t recon_lock_duration = 50 ;
uint32_t recon_lock_nb_match = 10 ;
uint32_t recon_match_mode = 0 ;
Rect view_rect = { 0, 3 * 8, 240, 230 };
ReconSetupViewMain viewMain{ nav_ , view_rect , input_file , output_file };
ReconSetupViewMore viewMore{ nav_ , view_rect , recon_lock_duration , recon_lock_nb_match , recon_match_mode };
TabView tab_view {
{ "Main", Color::cyan() , &viewMain },
{ "More", Color::green(), &viewMore }
};
Button button_save {
{ 9 * 8, 255, 14 * 8 , 40 },
"SAVE"
};
};
} /* namespace ui */
+13 -11
View File
@@ -160,9 +160,9 @@ ScannerView::~ScannerView() {
}
void ScannerView::show_max() { //show total number of freqs to scan
if (frequency_list.size() == MAX_DB_ENTRY) {
if (frequency_list.size() == FREQMAN_MAX_PER_FILE ) {
text_max.set_style(&style_red);
text_max.set( "/ " + to_string_dec_uint(MAX_DB_ENTRY) + " (DB MAX!)");
text_max.set( "/ " + to_string_dec_uint(FREQMAN_MAX_PER_FILE ) + " (DB MAX!)");
}
else {
text_max.set_style(&style_grey);
@@ -304,7 +304,7 @@ ScannerView::ScannerView(
);
rf::Frequency frequency = frequency_range.min;
while (frequency_list.size() < MAX_DB_ENTRY && frequency <= frequency_range.max) { //add manual range
while (frequency_list.size() < FREQMAN_MAX_PER_FILE && frequency <= frequency_range.max) { //add manual range
frequency_list.push_back(frequency);
description_list.push_back(""); //If empty, will keep showing the last description
frequency+=def_step;
@@ -398,7 +398,7 @@ void ScannerView::frequency_file_load(std::string file_name, bool stop_all_befor
if ( load_freqman_file(file_name, database) ) {
loaded_file_name = file_name; // keep loaded filename in memory
for(auto& entry : database) { // READ LINE PER LINE
if (frequency_list.size() < MAX_DB_ENTRY) { //We got space!
if (frequency_list.size() < FREQMAN_MAX_PER_FILE ) { //We got space!
if (entry.type == RANGE) { //RANGE
switch (entry.step) {
case AM_US: def_step = 10000; break ;
@@ -421,7 +421,7 @@ void ScannerView::frequency_file_load(std::string file_name, bool stop_all_befor
+ ">" + to_string_short_freq(entry.frequency_b)
+ " S" + to_string_short_freq(def_step).erase(0,1) //euquiq: lame kludge to reduce spacing in step freq
);
while (frequency_list.size() < MAX_DB_ENTRY && entry.frequency_a <= entry.frequency_b) { //add the rest of the range
while (frequency_list.size() < FREQMAN_MAX_PER_FILE && entry.frequency_a <= entry.frequency_b) { //add the rest of the range
entry.frequency_a+=def_step;
frequency_list.push_back(entry.frequency_a);
description_list.push_back(""); //Token (keep showing the last description)
@@ -529,10 +529,12 @@ size_t ScannerView::change_mode(uint8_t new_mod) { //Before this, do a scan_thre
receiver_model.set_sampling_rate(3072000); receiver_model.set_baseband_bandwidth(1750000);
break;
case AM:
bw.emplace_back("DSB", 0);
bw.emplace_back("USB", 0);
bw.emplace_back("LSB", 0);
bw.emplace_back("CW ", 0);
bw.emplace_back("DSB 9k" , 0 );
bw.emplace_back("DSB 6k" , 1 );
bw.emplace_back("USB+3k" , 2 );
bw.emplace_back("LSB-3k" , 3 );
bw.emplace_back("CW " , 4 );
field_bw.set_options(bw);
baseband::run_image(portapack::spi_flash::image_tag_am_audio);
@@ -540,10 +542,10 @@ size_t ScannerView::change_mode(uint8_t new_mod) { //Before this, do a scan_thre
field_bw.set_selected_index(0);
receiver_model.set_am_configuration(field_bw.selected_index());
field_bw.on_change = [this](size_t n, OptionsField::value_t) { receiver_model.set_am_configuration(n); };
receiver_model.set_sampling_rate(2000000);receiver_model.set_baseband_bandwidth(2000000);
receiver_model.set_sampling_rate(3072000); receiver_model.set_baseband_bandwidth(1750000);
break;
case WFM:
bw.emplace_back("16k", 0);
bw.emplace_back("200k", 0);
field_bw.set_options(bw);
baseband::run_image(portapack::spi_flash::image_tag_wfm_audio);
+3 -4
View File
@@ -34,7 +34,6 @@
#include "file.hpp"
#define MAX_DB_ENTRY 500
#define MAX_FREQ_LOCK 10 //50ms cycles scanner locks into freq when signal detected, to verify signal is not spureous
namespace ui {
@@ -144,7 +143,7 @@ private:
Labels labels {
{ { 0 * 8, 0 * 16 }, "LNA: VGA: AMP: VOL:", Color::light_grey() },
{ { 0 * 8, 1* 16 }, "BW: SQUELCH: db WAIT:", Color::light_grey() },
{ { 0 * 8, 1* 16 }, "BW: SQLCH: db WAIT:", Color::light_grey() },
{ { 3 * 8, 10 * 16 }, "START END MANUAL", Color::light_grey() },
{ { 0 * 8, (26 * 8) + 4 }, "MODE:", Color::light_grey() },
{ { 11 * 8, (26 * 8) + 4 }, "STEP:", Color::light_grey() },
@@ -177,7 +176,7 @@ private:
};
NumberField field_squelch {
{ 15 * 8, 1 * 16 },
{ 18 * 8, 1 * 16 },
3,
{ -90, 20 },
1,
@@ -185,7 +184,7 @@ private:
};
NumberField field_wait {
{ 26 * 8, 1 * 16 },
{ 27 * 8, 1 * 16 },
2,
{ 0, 99 },
1,
+8 -12
View File
@@ -245,13 +245,9 @@ SetUIView::SetUIView(NavigationView& nav) {
checkbox_showclock.set_value(!persistent_memory::hide_clock());
checkbox_guireturnflag.set_value(persistent_memory::show_gui_return_icon());
uint32_t backlight_timer = persistent_memory::config_backlight_timer();
if (backlight_timer) {
checkbox_bloff.set_value(true);
options_bloff.set_by_value(backlight_timer);
} else {
options_bloff.set_selected_index(0);
}
const auto backlight_config = persistent_memory::config_backlight_timer();
checkbox_bloff.set_value(backlight_config.timeout_enabled());
options_bloff.set_by_value(backlight_config.timeout_enum());
if (persistent_memory::clock_with_date()) {
options_clockformat.set_selected_index(1);
@@ -261,11 +257,11 @@ SetUIView::SetUIView(NavigationView& nav) {
button_save.on_select = [&nav, this](Button&) {
if (checkbox_bloff.value())
persistent_memory::set_config_backlight_timer(options_bloff.selected_index() + 1);
else
persistent_memory::set_config_backlight_timer(0);
persistent_memory::set_config_backlight_timer({
(persistent_memory::backlight_timeout_t)options_bloff.selected_index_value(),
checkbox_bloff.value()
});
if (checkbox_showclock.value()){
if (options_clockformat.selected_index() == 1)
persistent_memory::set_clock_with_date(true);
+11 -7
View File
@@ -27,6 +27,7 @@
#include "ui_menu.hpp"
#include "ui_navigation.hpp"
#include "ff.h"
#include "portapack_persistent_memory.hpp"
#include <cstdint>
@@ -210,6 +211,8 @@ private:
SetFrequencyCorrectionModel form_collect();
};
using portapack::persistent_memory::backlight_timeout_t;
class SetUIView : public View {
public:
SetUIView(NavigationView& nav);
@@ -241,13 +244,14 @@ private:
{ 52, 7 * 16 + 8 },
20,
{
{ "5 seconds", 5 },
{ "15 seconds", 15 },
{ "30 seconds", 30 },
{ "1 minute", 60 },
{ "3 minutes", 180 },
{ "5 minutes", 300 },
{ "10 minutes", 600 }
{ "5 seconds", backlight_timeout_t::Timeout5Sec },
{ "15 seconds", backlight_timeout_t::Timeout15Sec },
{ "30 seconds", backlight_timeout_t::Timeout30Sec },
{ "1 minute", backlight_timeout_t::Timeout60Sec },
{ "3 minutes", backlight_timeout_t::Timeout180Sec },
{ "5 minutes", backlight_timeout_t::Timeout300Sec },
{ "10 minutes", backlight_timeout_t::Timeout600Sec },
{ "1 hour", backlight_timeout_t::Timeout3600Sec },
}
};
+3 -1
View File
@@ -25,6 +25,7 @@
#include "portapack.hpp"
#include "hackrf_hal.hpp"
#include "cpld_update.hpp"
#include <cstring>
#include <stdio.h>
@@ -93,7 +94,8 @@ SSTVTXView::~SSTVTXView() {
settings.save("tx_sstv", &app_settings);
transmitter_model.disable();
baseband::shutdown();
hackrf::cpld::load_sram_no_verify(); // to leave all RX ok, without ghost signal problem at the exit.
baseband::shutdown(); // better this function at the end, not load_sram() that sometimes produces hang up.
}
void SSTVTXView::on_tuning_frequency_changed(rf::Frequency f) {
@@ -31,7 +31,7 @@ namespace ui {
TouchCalibrationView::TouchCalibrationView(
NavigationView& nav
) : nav { nav },
calibration { touch::default_calibration() }
calibration { touch::Calibration() }
{
add_children({
&image_calibrate_0,
+3 -1
View File
@@ -26,6 +26,7 @@
#include "baseband_api.hpp"
#include "string_format.hpp"
#include "cpld_update.hpp"
using namespace portapack;
@@ -39,7 +40,8 @@ void TouchTunesView::focus() {
TouchTunesView::~TouchTunesView() {
transmitter_model.disable();
baseband::shutdown();
hackrf::cpld::load_sram_no_verify(); // to leave all RX ok, without ghost signal problem at the exit.
baseband::shutdown(); // better this function at the end, not load_sram() that sometimes produces hang up.
}
void TouchTunesView::stop_tx() {
+2 -2
View File
@@ -168,8 +168,8 @@ void speaker_mute() {
namespace input {
void start() {
audio_codec->microphone_enable();
void start(int8_t alc_mode) {
audio_codec->microphone_enable(alc_mode); // added user-GUI selection for AK4951, ALC mode parameter.
i2s::i2s0::rx_start();
}
+3 -3
View File
@@ -49,7 +49,7 @@ public:
virtual volume_range_t headphone_gain_range() const = 0;
virtual void set_headphone_volume(const volume_t volume) = 0;
virtual void microphone_enable() = 0;
virtual void microphone_enable(int8_t alc_mode) = 0; // added user-GUI AK4951 ,selected ALC mode.
virtual void microphone_disable() = 0;
virtual size_t reg_count() const = 0;
@@ -59,7 +59,7 @@ public:
namespace output {
void start();
void start(); // this other start(),no changed. ,in namespace output , used to config audio playback mode,
void stop();
void mute();
@@ -72,7 +72,7 @@ void speaker_unmute();
namespace input {
void start();
void start(int8_t alc_mode); // added parameter user-GUI select AK4951-ALC mode for config mic path,(recording mode in datasheet),
void stop();
} /* namespace input */
+27 -14
View File
@@ -45,11 +45,11 @@ static void send_message(const Message* const message) {
void AMConfig::apply() const {
const AMConfigureMessage message {
taps_6k0_decim_0,
taps_6k0_decim_1,
taps_6k0_decim_2,
channel,
modulation,
taps_6k0_decim_0, // common FIR filter taps pre-decim_0 to all 5 x AM mod types.(AM-9K, AM-6K, USB, LSB, CW)
taps_6k0_decim_1, // common FIR filter taps pre-decim_1 to all 5 x AM mod. types.
decim_2, // var decim_2 FIR taps filter , variable values, depending selected AM mod(AM 9k / 6k all rest AM modes)
channel, // var channel FIR taps filter , variable values, depending selected AM mode, each one different (DSB-9K, DSB-6K, USB-3K, LSB-3K,CW)
modulation, // var parameter .
audio_12k_hpf_300hz_config
};
send_message(&message);
@@ -146,7 +146,7 @@ void set_btle(const uint32_t baudrate, const uint32_t word_length, const uint32_
};
send_message(&message);
}
void set_nrf(const uint32_t baudrate, const uint32_t word_length, const uint32_t trigger_value, const bool trigger_word) {
const NRFRxConfigureMessage message {
baudrate,
@@ -156,7 +156,7 @@ void set_nrf(const uint32_t baudrate, const uint32_t word_length, const uint32_t
};
send_message(&message);
}
void set_afsk_data(const uint32_t afsk_samples_per_bit, const uint32_t afsk_phase_inc_mark, const uint32_t afsk_phase_inc_space,
const uint8_t afsk_repeat, const uint32_t afsk_bw, const uint8_t symbol_count) {
const AFSKTxConfigureMessage message {
@@ -183,12 +183,13 @@ void kill_afsk() {
}
void set_audiotx_config(const uint32_t divider, const float deviation_hz, const float audio_gain,
const uint32_t tone_key_delta, const bool am_enabled, const bool dsb_enabled,
const bool usb_enabled, const bool lsb_enabled) {
uint8_t audio_shift_bits_s16, const uint32_t tone_key_delta, const bool am_enabled,
const bool dsb_enabled, const bool usb_enabled, const bool lsb_enabled) {
const AudioTXConfigMessage message {
divider,
deviation_hz,
audio_gain,
audio_shift_bits_s16,
tone_key_delta,
(float)persistent_memory::tone_mix() / 100.0f,
am_enabled,
@@ -211,16 +212,28 @@ void set_pitch_rssi(int32_t avg, bool enabled) {
enabled,
avg
};
send_message(&message);
send_message(&message);
}
void set_ook_data(const uint32_t stream_length, const uint32_t samples_per_bit, const uint8_t repeat,
const uint32_t pause_symbols) {
const uint32_t pause_symbols, const uint8_t de_bruijn_length) {
const OOKConfigureMessage message {
stream_length,
samples_per_bit,
repeat,
pause_symbols
pause_symbols,
de_bruijn_length
};
send_message(&message);
}
void kill_ook() {
const OOKConfigureMessage message {
0,
0,
0,
0,
0
};
send_message(&message);
}
@@ -250,7 +263,7 @@ void set_adsb() {
void set_jammer(const bool run, const jammer::JammerType type, const uint32_t speed) {
const JammerConfigureMessage message {
run,
run,
type,
speed
};
@@ -311,7 +324,7 @@ void shutdown() {
send_message(&message);
shared_memory.application_queue.reset();
baseband_image_running = false;
}
+5 -3
View File
@@ -36,6 +36,7 @@
namespace baseband {
struct AMConfig {
const fir_taps_real<32> decim_2; // added to handle two types decim_2 9k, 6k
const fir_taps_complex<64> channel;
const AMConfigureMessage::Modulation modulation;
@@ -61,8 +62,8 @@ void set_tones_config(const uint32_t bw, const uint32_t pre_silence, const uint1
void kill_tone();
void set_sstv_data(const uint8_t vis_code, const uint32_t pixel_duration);
void set_audiotx_config(const uint32_t divider, const float deviation_hz, const float audio_gain,
const uint32_t tone_key_delta, const bool am_enabled, const bool dsb_enabled,
const bool usb_enabled, const bool lsb_enabled);
uint8_t audio_shift_bits_s16, const uint32_t tone_key_delta, const bool am_enabled,
const bool dsb_enabled, const bool usb_enabled, const bool lsb_enabled);
void set_fifo_data(const int8_t * data);
void set_pitch_rssi(int32_t avg, bool enabled);
void set_afsk_data(const uint32_t afsk_samples_per_bit, const uint32_t afsk_phase_inc_mark, const uint32_t afsk_phase_inc_space,
@@ -76,7 +77,8 @@ void set_btle(const uint32_t baudrate, const uint32_t word_length, const uint32_
void set_nrf(const uint32_t baudrate, const uint32_t word_length, const uint32_t trigger_value, const bool trigger_word);
void set_ook_data(const uint32_t stream_length, const uint32_t samples_per_bit, const uint8_t repeat,
const uint32_t pause_symbols);
const uint32_t pause_symbols, const uint8_t de_bruijn_length = 0);
void kill_ook();
void set_fsk_data(const uint32_t stream_length, const uint32_t samples_per_bit, const uint32_t shift,
const uint32_t progress_notice);
void set_pocsag();
+5 -3
View File
@@ -226,15 +226,17 @@ void EventDispatcher::handle_rtc_tick() {
portapack::temperature_logger.second_tick();
uint32_t backlight_timer = portapack::persistent_memory::config_backlight_timer();
if (backlight_timer) {
if (portapack::bl_tick_counter == backlight_timer)
const auto backlight_timer = portapack::persistent_memory::config_backlight_timer();
if (backlight_timer.timeout_enabled()) {
if (portapack::bl_tick_counter == backlight_timer.timeout_seconds())
set_display_sleep(true);
else
portapack::bl_tick_counter++;
}
rtc_time::on_tick_second();
portapack::persistent_memory::cache::persist();
}
ui::Widget* EventDispatcher::touch_widget(ui::Widget* const w, ui::TouchEvent event) {
+474 -148
View File
@@ -23,166 +23,492 @@
#include "freqman.hpp"
#include <algorithm>
using option_t = std::pair<std::string, int32_t>;
using options_t = std::vector<option_t>;
options_t freqman_entry_modulations = {
{ "AM", 0 },
{ "NFM", 1 },
{ "WFM", 2 }
};
options_t freqman_entry_bandwidths[ 4 ] = {
{ //AM
{ "DSB 9k" , 0 },
{ "DSB 6k" , 1 },
{ "USB+3k" , 2 },
{ "LSB-3k" , 3 },
{ "CW" , 4 }
},
{ //NFM
{ "8k5" , 0 },
{ "11k" , 1 },
{ "16k" , 2 }
},
{ //WFM
{ "200k" , 0 },
}
};
options_t freqman_entry_steps = {
{ "5KHz (SA AM)" , 5000 },
{ "6.25KHz(NFM)" , 6250 },
{ "8.33KHz(AIR)" , 8330 },
{ "9KHz (EU AM)" , 9000 },
{ "10KHz(US AM)" , 10000 },
{ "12.5KHz(NFM)" , 12500 },
{ "15KHz (HFM)" , 15000 },
{ "25KHz (N1)" , 25000 },
{ "30KHz (OIRT)" , 30000 },
{ "50KHz (FM1)" , 50000 },
{ "100KHz (FM2)" , 100000 },
{ "250KHz (N2)" , 250000 },
{ "500KHz (WFM)" , 500000 },
{ "1MHz " , 1000000 }
};
options_t freqman_entry_steps_short = {
{ "5KHz" , 5000 },
{ "6.25KHz" , 6250 },
{ "8.33KHz" , 8330 },
{ "9KHz" , 9000 },
{ "10KHz" , 10000 },
{ "12.5KHz" , 12500 },
{ "15KHz" , 15000 },
{ "25KHz" , 25000 },
{ "30KHz" , 30000 },
{ "50KHz" , 50000 },
{ "100KHz" , 100000 },
{ "250KHz" , 250000 },
{ "500KHz" , 500000 },
{ "1MHz" , 1000000 }
};
std::vector<std::string> get_freqman_files() {
std::vector<std::string> file_list;
auto files = scan_root_files(u"FREQMAN", u"*.TXT");
for (auto file : files) {
std::string file_name = file.stem().string();
// don't propose tmp / hidden files in freqman's list
if (file_name.length() && file_name[0] != '.') {
file_list.emplace_back(file_name);
}
}
return file_list;
std::vector<std::string> file_list;
auto files = scan_root_files(u"FREQMAN", u"*.TXT");
for (auto file : files) {
std::string file_name = file.stem().string();
// don't propose tmp / hidden files in freqman's list
if (file_name.length() && file_name[0] != '.') {
file_list.emplace_back(file_name);
}
}
return file_list;
};
bool load_freqman_file(std::string& file_stem, freqman_db &db) {
File freqman_file;
size_t length, n = 0, file_position = 0;
char * pos;
char * line_start;
char * line_end;
std::string description;
rf::Frequency frequency_a, frequency_b;
char file_data[257];
freqman_entry_type type;
db.clear();
auto result = freqman_file.open("FREQMAN/" + file_stem + ".TXT");
if (result.is_valid())
return false;
while (1) {
// Read a 256 bytes block from file
freqman_file.seek(file_position);
memset(file_data, 0, 257);
auto read_size = freqman_file.read(file_data, 256);
if (read_size.is_error())
return false; // Read error
file_position += 256;
// Reset line_start to beginning of buffer
line_start = file_data;
if (!strstr(file_data, "f=") && !strstr(file_data, "a="))
break;
// Look for complete lines in buffer
while ((line_end = strstr(line_start, "\x0A"))) {
// Read frequency
pos = strstr(line_start, "f=");
frequency_b = 0;
type = SINGLE;
if (pos) {
pos += 2;
frequency_a = strtoll(pos, nullptr, 10);
} else {
// ...or range
pos = strstr(line_start, "a=");
if (pos) {
pos += 2;
frequency_a = strtoll(pos, nullptr, 10);
type = RANGE;
pos = strstr(line_start, "b=");
if (pos) {
pos += 2;
frequency_b = strtoll(pos, nullptr, 10);
} else
frequency_b = 0;
} else
frequency_a = 0;
}
// Read description until , or LF
pos = strstr(line_start, "d=");
if (pos) {
pos += 2;
length = std::min(strcspn(pos, ",\x0A"), (size_t)FREQMAN_DESC_MAX_LEN);
description = string(pos, length);
} else
description = "-";
db.push_back({ frequency_a, frequency_b, description, type });
n++;
if (n >= FREQMAN_MAX_PER_FILE) return true;
line_start = line_end + 1;
if (line_start - file_data >= 256) break;
}
if (read_size.value() != 256)
break; // End of file
// Restart at beginning of last incomplete line
file_position -= (file_data + 256 - line_start);
}
return true;
return load_freqman_file_ex( file_stem , db , true , true , true );
}
bool save_freqman_file(std::string& file_stem, freqman_db &db) {
File freqman_file;
std::string item_string;
rf::Frequency frequency_a, frequency_b;
if (!create_freqman_file(file_stem, freqman_file))
return false;
for (size_t n = 0; n < db.size(); n++) {
auto& entry = db[n];
bool load_freqman_file_ex(std::string& file_stem, freqman_db& db, bool load_freqs , bool load_ranges , bool load_hamradios ) {
File freqman_file;
size_t length, n = 0, file_position = 0;
char * pos;
char * line_start;
char * line_end;
std::string description;
rf::Frequency frequency_a, frequency_b;
char file_data[257];
freqman_entry_type type;
freqman_index_t modulation = 0 ;
freqman_index_t bandwidth = 0 ;
freqman_index_t step = 0 ;
freqman_index_t tone = 0 ;
frequency_a = entry.frequency_a;
if (entry.type == SINGLE) {
// Single
// TODO: Make to_string_dec_uint be able to return uint64_t's
// Please forgive me...
item_string = "f=" + to_string_dec_uint(frequency_a / 1000) + to_string_dec_uint(frequency_a % 1000UL, 3, '0');
} else {
// Range
frequency_b = entry.frequency_b;
item_string = "a=" + to_string_dec_uint(frequency_a / 1000) + to_string_dec_uint(frequency_a % 1000UL, 3, '0');
item_string += ",b=" + to_string_dec_uint(frequency_b / 1000) + to_string_dec_uint(frequency_b % 1000UL, 3, '0');
}
if (entry.description.size())
item_string += ",d=" + entry.description;
freqman_file.write_line(item_string);
}
return true;
db.clear();
auto result = freqman_file.open("FREQMAN/" + file_stem + ".TXT");
if (result.is_valid())
return false;
while (1) {
// Read a 256 bytes block from file
freqman_file.seek(file_position);
memset(file_data, 0, 257);
auto read_size = freqman_file.read(file_data, 256);
if (read_size.is_error())
return false; // Read error
file_position += 256;
// Reset line_start to beginning of buffer
line_start = file_data;
if (!strstr(file_data, "f=") && !strstr(file_data, "a=") && !strstr(file_data, "r=") )
break;
// Look for complete lines in buffer
while ((line_end = strstr(line_start, "\x0A"))) {
modulation = -1 ;
bandwidth = -1 ;
step = -1 ;
tone = -1 ;
type=SINGLE ;
frequency_a = frequency_b = 0;
// Read frequency
pos = strstr(line_start, "f=");
if(pos) {
pos += 2;
frequency_a = strtoll(pos, nullptr, 10);
} else {
// ...or range
pos = strstr(line_start, "a=");
if (pos) {
pos += 2;
frequency_a = strtoll(pos, nullptr, 10);
type = RANGE;
pos = strstr(line_start, "b=");
if (pos) {
pos += 2;
frequency_b = strtoll(pos, nullptr, 10);
} else
frequency_b = 0;
}else {
// ... or hamradio
pos = strstr(line_start, "r=");
if (pos) {
pos += 2;
frequency_a = strtoll(pos, nullptr, 10);
type = HAMRADIO;
pos = strstr(line_start, "t=");
if (pos) {
pos += 2;
frequency_b = strtoll(pos, nullptr, 10);
} else
frequency_b = frequency_a ;
} else
frequency_a = 0;
}
}
// modulation if any
pos = strstr(line_start, "m=");
if (pos) {
pos += 2;
modulation = freqman_entry_get_modulation_from_str( pos );
}
// bandwidth if any
pos = strstr(line_start, "bw=");
if (pos) {
pos += 3;
bandwidth = freqman_entry_get_bandwidth_from_str( modulation , pos );
}
// step if any
pos = strstr(line_start, "s=");
if (pos) {
pos += 2;
step = freqman_entry_get_step_from_str_short( pos );
}
// ctcss tone if any
/* disabled until better form
pos = strstr(line_start, "c=");
if (pos) {
pos += 2;
tone = tone_key_index_by_value( strtoll( pos , nullptr , 10 ) );
} */
// Read description until , or LF
pos = strstr(line_start, "d=");
if (pos) {
pos += 2;
length = std::min(strcspn(pos, ",\x0A"), (size_t)FREQMAN_DESC_MAX_LEN);
description = string(pos, length);
} else
description = "-";
if( (type == SINGLE && load_freqs) || (type == RANGE && load_ranges) || (type == HAMRADIO && load_hamradios) )
{
db.push_back({ frequency_a, frequency_b, description, type , modulation , bandwidth , step , tone });
n++;
if (n >= FREQMAN_MAX_PER_FILE) return true;
}
line_start = line_end + 1;
if (line_start - file_data >= 256) break;
}
if (read_size.value() != 256)
break; // End of file
// Restart at beginning of last incomplete line
file_position -= (file_data + 256 - line_start);
}
/* populate implicitly specified modulation / bandwidth */
if( db.size() > 2 )
{
modulation = db[ 0 ] . modulation;
bandwidth = db[ 0 ] . bandwidth;
for( unsigned int it = 1 ; it < db.size() ; it ++ )
{
if( db[ it ] . modulation < 0 )
{
db[ it ] . modulation = modulation ;
}
else
{
modulation = db[ it ] . modulation ;
}
if( db[ it ] . bandwidth < 0 )
{
db[ it ] . bandwidth = bandwidth ;
}
else
{
modulation = db[ it ] . bandwidth ;
}
}
}
return true;
}
bool get_freq_string( freqman_entry &entry , std::string &item_string )
{
rf::Frequency frequency_a, frequency_b;
frequency_a = entry.frequency_a;
if (entry.type == SINGLE) {
// Single
item_string = "f=" + to_string_dec_uint(frequency_a / 1000) + to_string_dec_uint(frequency_a % 1000UL, 3, '0');
} else if( entry.type == RANGE ) {
// Range
frequency_b = entry.frequency_b;
item_string = "a=" + to_string_dec_uint(frequency_a / 1000) + to_string_dec_uint(frequency_a % 1000UL, 3, '0');
item_string += ",b=" + to_string_dec_uint(frequency_b / 1000) + to_string_dec_uint(frequency_b % 1000UL, 3, '0');
if( entry.step >= 0 )
{
item_string += ",s=" + freqman_entry_get_step_string_short( entry.step );
}
} else if( entry.type == HAMRADIO ) {
frequency_b = entry.frequency_b;
item_string = "r=" + to_string_dec_uint(frequency_a / 1000) + to_string_dec_uint(frequency_a % 1000UL, 3, '0');
item_string += ",t=" + to_string_dec_uint(frequency_b / 1000) + to_string_dec_uint(frequency_b % 1000UL, 3, '0');
if( entry.tone >= 0 )
{
item_string += ",c=" + tone_key_string( entry.tone );
}
}
if( entry.modulation >= 0 && (unsigned)entry.modulation < freqman_entry_modulations . size() )
{
item_string += ",m=" + freqman_entry_get_modulation_string( entry.modulation );
if( entry.bandwidth >= 0 && (unsigned)entry.bandwidth < freqman_entry_bandwidths[ entry.modulation ] . size() )
{
item_string += ",bw=" + freqman_entry_get_bandwidth_string( entry.modulation , entry.bandwidth );
}
}
if (entry.description.size())
item_string += ",d=" + entry.description;
return true ;
}
bool save_freqman_file(std::string &file_stem, freqman_db &db) {
File freqman_file;
std::string freq_file_path = "FREQMAN/" + file_stem + ".TXT";
std::string tmp_freq_file_path = "FREQMAN/" + file_stem + ".TXT.TMP";
if( !db.size() )
{
delete_file( "FREQMAN/"+file_stem+".TXT" );
return true ;
}
delete_file( tmp_freq_file_path );
auto result = freqman_file.open( tmp_freq_file_path );
if ( !result.is_valid() ) {
for (size_t n = 0; n < db.size(); n++) {
std::string item_string;
auto& entry = db[n];
get_freq_string( entry , item_string );
freqman_file.write_line( item_string );
delete &item_string;
}
delete_file( freq_file_path );
rename_file( tmp_freq_file_path , freq_file_path );
return true;
}
return false ;
}
bool create_freqman_file(std::string& file_stem, File& freqman_file) {
auto result = freqman_file.create("FREQMAN/" + file_stem + ".TXT");
if (result.is_valid())
return false;
return true;
auto result = freqman_file.create( "FREQMAN/" + file_stem + ".TXT" );
if (result.is_valid())
return false;
return true;
}
std::string freqman_item_string(freqman_entry &entry, size_t max_length) {
std::string item_string;
std::string item_string;
if (entry.type == SINGLE) {
item_string = to_string_short_freq(entry.frequency_a) + "M: " + entry.description;
} else {
item_string = "Range: " + entry.description;
}
if (item_string.size() > max_length)
return item_string.substr(0, max_length - 3) + "...";
return item_string;
switch( entry.type ){
case SINGLE:
item_string = to_string_short_freq(entry.frequency_a) + "M: " + entry.description;
break;
case RANGE:
item_string = "R: " + entry.description;
break;
case HAMRADIO:
item_string = "H: " + entry.description;
break;
default:
item_string = "!UNKNOW TYPE " + entry.description;
break;
}
if (item_string.size() > max_length)
return item_string.substr(0, max_length - 3) + "...";
return item_string;
}
void freqman_set_modulation_option( OptionsField &option )
{
option.set_options( freqman_entry_modulations );
}
void freqman_set_bandwidth_option( freqman_index_t modulation , OptionsField &option )
{
option.set_options( freqman_entry_bandwidths[ modulation ] );
}
void freqman_set_step_option( OptionsField &option )
{
option.set_options( freqman_entry_steps );
}
void freqman_set_step_option_short( OptionsField &option )
{
option.set_options( freqman_entry_steps_short );
}
std::string freqman_entry_get_modulation_string( freqman_index_t modulation )
{
if( modulation < 0 || (unsigned)modulation >= freqman_entry_modulations . size() )
{
return std::string( "" ); // unknown modulation
}
return freqman_entry_modulations[ modulation ] . first ;
}
std::string freqman_entry_get_bandwidth_string( freqman_index_t modulation , freqman_index_t bandwidth )
{
if( modulation < 0 || (unsigned)modulation >= freqman_entry_modulations . size() )
{
return std::string( "" ); // unknown modulation
}
if( bandwidth < 0 || (unsigned)bandwidth > freqman_entry_bandwidths[ modulation ] . size() )
{
return std::string( "" ); // unknown modulation
}
return freqman_entry_bandwidths[ modulation ][ bandwidth ] . first ;
}
std::string freqman_entry_get_step_string( freqman_index_t step )
{
if( step < 0 || (unsigned)step >= freqman_entry_steps . size() )
{
return std::string( "" ); // unknown modulation
}
return freqman_entry_steps[ step ] . first ;
}
std::string freqman_entry_get_step_string_short( freqman_index_t step )
{
if( step < 0 || (unsigned)step >= freqman_entry_steps_short . size() )
{
return std::string( "" ); // unknown modulation
}
return freqman_entry_steps_short[ step ] . first ;
}
int32_t freqman_entry_get_modulation_value( freqman_index_t modulation )
{
if( modulation < 0 || (unsigned)modulation >= freqman_entry_modulations . size() )
{
return -1 ; // unknown modulation
}
return freqman_entry_modulations[ modulation ] . second ;
}
int32_t freqman_entry_get_bandwidth_value( freqman_index_t modulation , freqman_index_t bandwidth )
{
if( modulation < 0 || (unsigned)modulation >= freqman_entry_modulations . size() )
{
return -1 ; // unknown modulation
}
if( bandwidth < 0 || (unsigned)bandwidth > freqman_entry_bandwidths[ modulation ] . size() )
{
return -1 ; // unknown bandwidth for modulation
}
return freqman_entry_bandwidths[ modulation ][ bandwidth ] . second ;
}
int32_t freqman_entry_get_step_value( freqman_index_t step )
{
if( step < 0 || (unsigned)step >= freqman_entry_steps . size() )
{
return -1 ; // unknown modulation
}
return freqman_entry_steps[ step ] . second ;
}
freqman_index_t freqman_entry_get_modulation_from_str( char *str )
{
if( !str )
return -1 ;
for( freqman_index_t index = 0 ; (unsigned)index < freqman_entry_modulations . size() ; index ++ )
{
if( strncmp( freqman_entry_modulations[ index ] . first . c_str() , str , freqman_entry_modulations[ index ] . first . size() ) == 0 )
return index ;
}
return -1 ;
}
freqman_index_t freqman_entry_get_bandwidth_from_str( freqman_index_t modulation , char *str )
{
if( !str )
return -1 ;
if( modulation < 0 || (unsigned)modulation >= freqman_entry_modulations . size() )
return -1 ;
for( freqman_index_t index = 0 ; (unsigned)index < freqman_entry_bandwidths[ modulation ] . size() ; index ++ )
{
if( strncmp( freqman_entry_bandwidths[ modulation ][ index ] . first . c_str() , str , freqman_entry_bandwidths[ modulation ][ index ] . first . size() ) == 0 )
return index ;
}
return -1 ;
}
freqman_index_t freqman_entry_get_step_from_str( char *str )
{
if( !str )
return -1 ;
for( freqman_index_t index = 0 ; (unsigned)index < freqman_entry_steps . size() ; index ++ )
{
if( strncmp( freqman_entry_steps[ index ] . first . c_str() , str , freqman_entry_steps[ index ] . first . size() ) == 0 )
return index ;
}
return -1 ;
}
freqman_index_t freqman_entry_get_step_from_str_short( char *str )
{
if( !str )
return -1 ;
for( freqman_index_t index = 0 ; (unsigned)index < freqman_entry_steps_short . size() ; index ++ )
{
if( strncmp( freqman_entry_steps_short[ index ] . first . c_str() , str , freqman_entry_steps_short[ index ] . first . size() ) == 0 )
return index ;
}
return -1 ;
}
+55 -14
View File
@@ -20,21 +20,27 @@
* Boston, MA 02110-1301, USA.
*/
#ifndef __FREQMAN_H__
#define __FREQMAN_H__
#include <cstring>
#include <string>
#include "file.hpp"
#include "ui_receiver.hpp"
#include "tone_key.hpp"
#include "string_format.hpp"
#ifndef __FREQMAN_H__
#define __FREQMAN_H__
#include "ui_widget.hpp"
#define FREQMAN_DESC_MAX_LEN 30
#define FREQMAN_MAX_PER_FILE 99
#define FREQMAN_MAX_PER_FILE_STR "99"
#define FREQMAN_MAX_PER_FILE 500 /* MAX PER FILES */
#define FREQMAN_MAX_PER_FILE_STR "500" /*STRING OF FREQMAN_MAX_PER_FILE */
using namespace ui;
using namespace std;
using namespace tonekey;
// needs to be signed as -1 means not set
typedef int8_t freqman_index_t ;
enum freqman_error {
NO_ERROR = 0,
@@ -44,13 +50,23 @@ enum freqman_error {
};
enum freqman_entry_type {
SINGLE = 0,
RANGE
SINGLE = 0, //f=
RANGE, //a=,b=
HAMRADIO, //r=,t=
ERROR_TYPE
};
enum freqman_entry_modulation {
AM_MODULATION = 0 ,
NFM_MODULATION ,
WFM_MODULATION ,
MODULATION_DEF ,
ERROR_MODULATION
};
//Entry step placed for AlainD freqman version (or any other enhanced version)
enum freqman_entry_step {
STEP_DEF = 0, // default
STEP_DEF = -1, // default
AM_US, // 10 kHz AM/CB
AM_EUR, // 9 kHz LW/MW
NFM_1, // 12,5 kHz (Analogic PMR 446)
@@ -63,21 +79,46 @@ enum freqman_entry_step {
ERROR_STEP
};
// freqman_entry_step step added, as above, to provide compatibility / future enhancement.
struct freqman_entry {
rf::Frequency frequency_a { 0 };
rf::Frequency frequency_b { 0 };
std::string description { };
freqman_entry_type type { };
freqman_entry_step step { };
rf::Frequency frequency_a { 0 }; // 'f=freq' or 'a=freq_start' or 'r=recv_freq'
rf::Frequency frequency_b { 0 }; // 'b=freq_end' or 't=tx_freq'
std::string description { }; // 'd=desc'
freqman_entry_type type { }; // SINGLE,RANGE,HAMRADIO
freqman_index_t modulation { }; // AM,NFM,WFM
freqman_index_t bandwidth { }; // AM_DSB, ...
freqman_index_t step { }; // 5Khz (SA AM,...
tone_index tone { }; // 0XZ, 11 1ZB,...
};
using freqman_db = std::vector<freqman_entry>;
std::vector<std::string> get_freqman_files();
bool load_freqman_file(std::string& file_stem, freqman_db& db);
bool load_freqman_file_ex(std::string& file_stem, freqman_db& db, bool load_freqs , bool load_ranges , bool load_hamradios );
bool get_freq_string( freqman_entry &entry , std::string &item_string );
bool save_freqman_file(std::string& file_stem, freqman_db& db);
bool create_freqman_file(std::string& file_stem, File& freqman_file);
std::string freqman_item_string(freqman_entry &item, size_t max_length);
void freqman_set_bandwidth_option( freqman_index_t modulation , OptionsField &option );
void freqman_set_modulation_option( OptionsField &option );
void freqman_set_step_option( OptionsField &option );
void freqman_set_step_option_short( OptionsField &option );
void freqman_set_tone_option( OptionsField &option );
std::string freqman_entry_get_modulation_string( freqman_index_t modulation );
std::string freqman_entry_get_bandwidth_string( freqman_index_t modulation , freqman_index_t bandwidth );
std::string freqman_entry_get_step_string( freqman_index_t step );
std::string freqman_entry_get_step_string_short( freqman_index_t step );
int32_t freqman_entry_get_modulation_value( freqman_index_t modulation );
int32_t freqman_entry_get_bandwidth_value( freqman_index_t modulation , freqman_index_t bandwidth );
int32_t freqman_entry_get_step_value( freqman_index_t step );
freqman_index_t freqman_entry_get_modulation_from_str( char *str );
freqman_index_t freqman_entry_get_bandwidth_from_str( freqman_index_t modulation , char *str );
freqman_index_t freqman_entry_get_step_from_str( char *str );
freqman_index_t freqman_entry_get_step_from_str_short( char *str );
#endif/*__FREQMAN_H__*/
+16 -4
View File
@@ -215,7 +215,7 @@ 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){
if((value <= 0 || value >= 5) && sd_card::status() == sd_card::Status::Mounted){
int data = read_file("/hardware/settings.txt");
if(data != -1) {
config_value = data;
@@ -235,14 +235,19 @@ static PortaPackModel portapack_model() {
const auto switches_state = get_switches_state();
if (switches_state[(size_t)ui::KeyEvent::Up]){
save_config(1);
model = PortaPackModel::R2_20170522;
// model = PortaPackModel::R2_20170522; // Commented these out as they should be set down below anyway
}
else if (switches_state[(size_t)ui::KeyEvent::Down]){
save_config(2);
model = PortaPackModel::R1_20150901;
// model = PortaPackModel::R1_20150901;
}
else if (switches_state[(size_t)ui::KeyEvent::Left]){
save_config(3);
// model = PortaPackModel::R1_20150901;
}
else if (switches_state[(size_t)ui::KeyEvent::Right]){
save_config(4);
// model = PortaPackModel::R2_20170522;
}
else if (switches_state[(size_t)ui::KeyEvent::Select]){
save_config(0);
@@ -253,6 +258,10 @@ static PortaPackModel portapack_model() {
model = PortaPackModel::R2_20170522;
} else if (load_config() == 2) {
model = PortaPackModel::R1_20150901;
} else if (load_config() == 3) {
model = PortaPackModel::R1_20150901;
} else if (load_config() == 4) {
model = PortaPackModel::R2_20170522;
} else {
if( audio_codec_wm8731.detected() ) {
model = PortaPackModel::R1_20150901; // H1R1
@@ -457,6 +466,9 @@ bool init() {
i2c0.start(i2c_config_fast_clock);
chThdSleepMilliseconds(10);
/* Cache some configuration data from persistent memory. */
persistent_memory::cache::init();
touch::adc::init();
controls_init();
chThdSleepMilliseconds(10);
@@ -475,7 +487,7 @@ bool init() {
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){
if (load_config() != 3 && load_config() != 4){
shutdown_base();
return false;
}
+6 -5
View File
@@ -38,11 +38,12 @@ using namespace portapack;
namespace {
static constexpr std::array<baseband::AMConfig, 4> am_configs { {
{ taps_6k0_dsb_channel, AMConfigureMessage::Modulation::DSB },
{ taps_2k8_usb_channel, AMConfigureMessage::Modulation::SSB },
{ taps_2k8_lsb_channel, AMConfigureMessage::Modulation::SSB },
{ taps_0k7_usb_channel, AMConfigureMessage::Modulation::SSB },
static constexpr std::array<baseband::AMConfig, 5> am_configs { { // we config here all the non COMMON parameters to each AM modulation type in RX.
{ taps_9k0_decim_2, taps_9k0_dsb_channel, AMConfigureMessage::Modulation::DSB }, // AM DSB-C BW 9khz (+-4k5) commercial EU bandwidth .
{ taps_6k0_decim_2, taps_6k0_dsb_channel, AMConfigureMessage::Modulation::DSB }, // AM DSB-C BW 6khz (+-3k0) narrow AM , ham equipments.
{ taps_6k0_decim_2, taps_2k8_usb_channel, AMConfigureMessage::Modulation::SSB }, // SSB USB BW 2K8 (+ 2K8)
{ taps_6k0_decim_2, taps_2k8_lsb_channel, AMConfigureMessage::Modulation::SSB }, // SSB LSB BW 2K8 (- 2K8)
{ taps_6k0_decim_2, taps_0k7_usb_channel, AMConfigureMessage::Modulation::SSB }, // SSB USB BW 0K7 (+ 0K7) used to get audio tone from CW Morse, assuming tx shifted +700hz aprox
} };
static constexpr std::array<baseband::NBFMConfig, 3> nbfm_configs { {
+8
View File
@@ -45,6 +45,14 @@ struct serial_format_t {
parity_enum parity;
uint8_t stop_bits;
order_enum bit_order;
constexpr serial_format_t() :
data_bits(7),
parity(parity_enum::EVEN),
stop_bits(1),
bit_order(order_enum::LSB_FIRST)
{
}
};
size_t symbol_count(const serial_format_t& serial_format);
+256 -256
View File
@@ -281,262 +281,262 @@ const std::array<ui::Color, 256> spectrum_rgb2_lut { {
} };
const std::array<ui::Color, 256> spectrum_rgb3_lut { {
{ 0, 0, 0 },
{ 0, 0, 3 },
{ 0, 0, 6 },
{ 0, 0, 9 },
{ 0, 0, 12 },
{ 0, 0, 15 },
{ 0, 0, 18 },
{ 0, 0, 21 },
{ 0, 0, 24 },
{ 0, 0, 27 },
{ 0, 0, 30 },
{ 0, 0, 33 },
{ 0, 0, 36 },
{ 0, 0, 39 },
{ 0, 0, 42 },
{ 0, 0, 45 },
{ 0, 0, 48 },
{ 0, 0, 51 },
{ 0, 0, 54 },
{ 0, 0, 57 },
{ 0, 0, 60 },
{ 0, 0, 63 },
{ 0, 0, 66 },
{ 0, 0, 69 },
{ 0, 0, 72 },
{ 0, 0, 75 },
{ 0, 0, 78 },
{ 0, 0, 81 },
{ 0, 0, 84 },
{ 0, 0, 87 },
{ 0, 0, 90 },
{ 0, 0, 93 },
{ 0, 0, 96 },
{ 0, 0, 99 },
{ 0, 0, 102 },
{ 0, 0, 105 },
{ 0, 0, 108 },
{ 0, 0, 111 },
{ 0, 0, 114 },
{ 0, 0, 117 },
{ 0, 0, 120 },
{ 0, 0, 123 },
{ 0, 0, 126 },
{ 0, 0, 129 },
{ 0, 0, 132 },
{ 0, 0, 135 },
{ 0, 0, 138 },
{ 0, 0, 141 },
{ 0, 0, 144 },
{ 0, 0, 147 },
{ 0, 0, 150 },
{ 0, 0, 153 },
{ 0, 0, 156 },
{ 0, 0, 159 },
{ 0, 0, 162 },
{ 0, 0, 165 },
{ 0, 0, 168 },
{ 0, 0, 171 },
{ 0, 0, 174 },
{ 0, 0, 177 },
{ 0, 0, 180 },
{ 0, 0, 183 },
{ 0, 0, 186 },
{ 0, 0, 189 },
{ 0, 0, 192 },
{ 0, 0, 195 },
{ 0, 0, 198 },
{ 0, 0, 201 },
{ 0, 0, 204 },
{ 0, 0, 207 },
{ 0, 0, 210 },
{ 0, 0, 213 },
{ 0, 0, 216 },
{ 0, 0, 219 },
{ 0, 0, 222 },
{ 0, 0, 225 },
{ 0, 0, 228 },
{ 0, 0, 231 },
{ 0, 0, 234 },
{ 0, 0, 237 },
{ 0, 0, 240 },
{ 0, 0, 243 },
{ 0, 0, 246 },
{ 0, 0, 249 },
{ 0, 0, 252 },
{ 0, 0, 255 },
{ 0, 3, 252 },
{ 0, 6, 249 },
{ 0, 9, 246 },
{ 0, 12, 243 },
{ 0, 15, 240 },
{ 0, 18, 237 },
{ 0, 21, 234 },
{ 0, 24, 231 },
{ 0, 27, 228 },
{ 0, 30, 225 },
{ 0, 33, 222 },
{ 0, 36, 219 },
{ 0, 39, 216 },
{ 0, 42, 213 },
{ 0, 45, 210 },
{ 0, 48, 207 },
{ 0, 51, 204 },
{ 0, 54, 201 },
{ 0, 57, 198 },
{ 0, 60, 195 },
{ 0, 63, 192 },
{ 0, 66, 189 },
{ 0, 69, 186 },
{ 0, 72, 183 },
{ 0, 75, 180 },
{ 0, 78, 177 },
{ 0, 81, 174 },
{ 0, 84, 171 },
{ 0, 87, 168 },
{ 0, 90, 165 },
{ 0, 93, 162 },
{ 0, 96, 159 },
{ 0, 99, 156 },
{ 0, 102, 153 },
{ 0, 105, 150 },
{ 0, 108, 147 },
{ 0, 111, 144 },
{ 0, 114, 141 },
{ 0, 117, 138 },
{ 0, 120, 135 },
{ 0, 123, 132 },
{ 0, 126, 129 },
{ 0, 129, 126 },
{ 0, 132, 123 },
{ 0, 135, 120 },
{ 0, 138, 117 },
{ 0, 141, 114 },
{ 0, 144, 111 },
{ 0, 147, 108 },
{ 0, 150, 105 },
{ 0, 153, 102 },
{ 0, 156, 99 },
{ 0, 159, 96 },
{ 0, 162, 93 },
{ 0, 165, 90 },
{ 0, 168, 87 },
{ 0, 171, 84 },
{ 0, 174, 81 },
{ 0, 177, 78 },
{ 0, 180, 75 },
{ 0, 183, 72 },
{ 0, 186, 69 },
{ 0, 189, 66 },
{ 0, 192, 63 },
{ 0, 195, 60 },
{ 0, 198, 57 },
{ 0, 201, 54 },
{ 0, 204, 51 },
{ 0, 207, 48 },
{ 0, 210, 45 },
{ 0, 213, 42 },
{ 0, 216, 39 },
{ 0, 219, 36 },
{ 0, 222, 33 },
{ 0, 225, 30 },
{ 0, 228, 27 },
{ 0, 231, 24 },
{ 0, 234, 21 },
{ 0, 237, 18 },
{ 0, 240, 15 },
{ 0, 243, 12 },
{ 0, 246, 9 },
{ 0, 249, 6 },
{ 0, 252, 3 },
{ 0, 255, 0 },
{ 3, 252, 0 },
{ 6, 249, 0 },
{ 9, 246, 0 },
{ 12, 243, 0 },
{ 15, 240, 0 },
{ 18, 237, 0 },
{ 21, 234, 0 },
{ 24, 231, 0 },
{ 27, 228, 0 },
{ 30, 225, 0 },
{ 33, 222, 0 },
{ 36, 219, 0 },
{ 39, 216, 0 },
{ 42, 213, 0 },
{ 45, 210, 0 },
{ 48, 207, 0 },
{ 51, 204, 0 },
{ 54, 201, 0 },
{ 57, 198, 0 },
{ 60, 195, 0 },
{ 63, 192, 0 },
{ 66, 189, 0 },
{ 69, 186, 0 },
{ 72, 183, 0 },
{ 75, 180, 0 },
{ 78, 177, 0 },
{ 81, 174, 0 },
{ 84, 171, 0 },
{ 87, 168, 0 },
{ 90, 165, 0 },
{ 93, 162, 0 },
{ 96, 159, 0 },
{ 99, 156, 0 },
{ 102, 153, 0 },
{ 105, 150, 0 },
{ 108, 147, 0 },
{ 111, 144, 0 },
{ 114, 141, 0 },
{ 117, 138, 0 },
{ 120, 135, 0 },
{ 123, 132, 0 },
{ 126, 129, 0 },
{ 129, 126, 0 },
{ 132, 123, 0 },
{ 135, 120, 0 },
{ 138, 117, 0 },
{ 141, 114, 0 },
{ 144, 111, 0 },
{ 147, 108, 0 },
{ 150, 105, 0 },
{ 153, 102, 0 },
{ 156, 99, 0 },
{ 159, 96, 0 },
{ 162, 93, 0 },
{ 165, 90, 0 },
{ 168, 87, 0 },
{ 171, 84, 0 },
{ 174, 81, 0 },
{ 177, 78, 0 },
{ 180, 75, 0 },
{ 183, 72, 0 },
{ 186, 69, 0 },
{ 189, 66, 0 },
{ 192, 63, 0 },
{ 195, 60, 0 },
{ 198, 57, 0 },
{ 201, 54, 0 },
{ 204, 51, 0 },
{ 207, 48, 0 },
{ 210, 45, 0 },
{ 213, 42, 0 },
{ 216, 39, 0 },
{ 219, 36, 0 },
{ 222, 33, 0 },
{ 225, 30, 0 },
{ 228, 27, 0 },
{ 231, 24, 0 },
{ 234, 21, 0 },
{ 237, 18, 0 },
{ 240, 15, 0 },
{ 243, 12, 0 },
{ 246, 9, 0 },
{ 249, 6, 0 },
{ 252, 3, 0 },
{ 255, 0, 0 },
{ 0x00, 0x00, 0x02 },
{ 0x00, 0x00, 0x04 },
{ 0x00, 0x00, 0x05 },
{ 0x00, 0x00, 0x07 },
{ 0x00, 0x00, 0x0a },
{ 0x00, 0x00, 0x0c },
{ 0x00, 0x00, 0x0e },
{ 0x00, 0x00, 0x10 },
{ 0x00, 0x00, 0x13 },
{ 0x00, 0x00, 0x15 },
{ 0x00, 0x00, 0x17 },
{ 0x00, 0x00, 0x19 },
{ 0x00, 0x00, 0x1b },
{ 0x00, 0x00, 0x1d },
{ 0x00, 0x00, 0x1f },
{ 0x00, 0x00, 0x21 },
{ 0x00, 0x00, 0x24 },
{ 0x00, 0x00, 0x25 },
{ 0x00, 0x00, 0x28 },
{ 0x00, 0x00, 0x29 },
{ 0x00, 0x00, 0x2c },
{ 0x00, 0x00, 0x2e },
{ 0x00, 0x00, 0x30 },
{ 0x00, 0x00, 0x33 },
{ 0x00, 0x00, 0x35 },
{ 0x00, 0x00, 0x37 },
{ 0x00, 0x00, 0x39 },
{ 0x00, 0x00, 0x3b },
{ 0x00, 0x00, 0x3d },
{ 0x00, 0x00, 0x3f },
{ 0x00, 0x00, 0x41 },
{ 0x00, 0x00, 0x43 },
{ 0x00, 0x00, 0x46 },
{ 0x00, 0x00, 0x48 },
{ 0x00, 0x00, 0x4a },
{ 0x00, 0x00, 0x4c },
{ 0x00, 0x00, 0x4e },
{ 0x00, 0x00, 0x50 },
{ 0x00, 0x00, 0x53 },
{ 0x00, 0x00, 0x55 },
{ 0x00, 0x00, 0x56 },
{ 0x00, 0x00, 0x59 },
{ 0x00, 0x00, 0x5b },
{ 0x00, 0x00, 0x5d },
{ 0x00, 0x00, 0x5f },
{ 0x00, 0x00, 0x62 },
{ 0x00, 0x00, 0x63 },
{ 0x00, 0x00, 0x66 },
{ 0x00, 0x00, 0x68 },
{ 0x00, 0x00, 0x6a },
{ 0x00, 0x00, 0x6c },
{ 0x00, 0x00, 0x6e },
{ 0x00, 0x00, 0x70 },
{ 0x00, 0x00, 0x73 },
{ 0x00, 0x00, 0x75 },
{ 0x00, 0x00, 0x77 },
{ 0x00, 0x00, 0x79 },
{ 0x00, 0x00, 0x7b },
{ 0x00, 0x00, 0x7d },
{ 0x00, 0x00, 0x7f },
{ 0x00, 0x00, 0x82 },
{ 0x00, 0x00, 0x84 },
{ 0x00, 0x00, 0x86 },
{ 0x00, 0x00, 0x88 },
{ 0x00, 0x00, 0x8a },
{ 0x00, 0x00, 0x8c },
{ 0x00, 0x00, 0x8e },
{ 0x00, 0x00, 0x91 },
{ 0x00, 0x00, 0x93 },
{ 0x00, 0x00, 0x95 },
{ 0x00, 0x00, 0x97 },
{ 0x00, 0x00, 0x99 },
{ 0x00, 0x00, 0x9b },
{ 0x00, 0x00, 0x9d },
{ 0x00, 0x00, 0x9f },
{ 0x00, 0x00, 0xa2 },
{ 0x00, 0x00, 0xa4 },
{ 0x00, 0x00, 0xa6 },
{ 0x00, 0x00, 0xa8 },
{ 0x00, 0x00, 0xaa },
{ 0x00, 0x00, 0xac },
{ 0x00, 0x00, 0xae },
{ 0x00, 0x00, 0xb1 },
{ 0x00, 0x00, 0xb3 },
{ 0x00, 0x00, 0xb5 },
{ 0x00, 0x00, 0xb7 },
{ 0x00, 0x00, 0xb9 },
{ 0x00, 0x00, 0xbb },
{ 0x00, 0x00, 0xbd },
{ 0x00, 0x00, 0xbf },
{ 0x00, 0x00, 0xc2 },
{ 0x00, 0x00, 0xc4 },
{ 0x00, 0x00, 0xc6 },
{ 0x00, 0x00, 0xc8 },
{ 0x00, 0x00, 0xca },
{ 0x00, 0x00, 0xcc },
{ 0x00, 0x00, 0xce },
{ 0x00, 0x00, 0xd1 },
{ 0x00, 0x00, 0xd3 },
{ 0x00, 0x00, 0xd5 },
{ 0x00, 0x00, 0xd7 },
{ 0x00, 0x00, 0xd9 },
{ 0x00, 0x00, 0xdb },
{ 0x00, 0x00, 0xdd },
{ 0x00, 0x00, 0xdf },
{ 0x00, 0x00, 0xe2 },
{ 0x00, 0x00, 0xe4 },
{ 0x00, 0x00, 0xe6 },
{ 0x00, 0x00, 0xe8 },
{ 0x00, 0x00, 0xea },
{ 0x00, 0x00, 0xec },
{ 0x00, 0x00, 0xee },
{ 0x00, 0x00, 0xf1 },
{ 0x00, 0x00, 0xf3 },
{ 0x00, 0x00, 0xf5 },
{ 0x00, 0x00, 0xf7 },
{ 0x00, 0x00, 0xf9 },
{ 0x00, 0x00, 0xfb },
{ 0x00, 0x00, 0xfd },
{ 0x01, 0x00, 0xfe },
{ 0x05, 0x00, 0xfa },
{ 0x09, 0x00, 0xf6 },
{ 0x0e, 0x00, 0xf2 },
{ 0x12, 0x00, 0xed },
{ 0x16, 0x00, 0xe9 },
{ 0x1b, 0x00, 0xe4 },
{ 0x1f, 0x00, 0xe0 },
{ 0x24, 0x00, 0xdc },
{ 0x27, 0x00, 0xd8 },
{ 0x2c, 0x00, 0xd3 },
{ 0x30, 0x00, 0xcf },
{ 0x35, 0x00, 0xcb },
{ 0x39, 0x00, 0xc6 },
{ 0x3d, 0x00, 0xc2 },
{ 0x42, 0x00, 0xbd },
{ 0x46, 0x00, 0xb9 },
{ 0x4b, 0x00, 0xb5 },
{ 0x4f, 0x00, 0xb0 },
{ 0x53, 0x00, 0xac },
{ 0x58, 0x00, 0xa7 },
{ 0x5c, 0x00, 0xa3 },
{ 0x61, 0x00, 0x9f },
{ 0x65, 0x00, 0x9a },
{ 0x69, 0x00, 0x96 },
{ 0x6e, 0x00, 0x91 },
{ 0x72, 0x00, 0x8d },
{ 0x77, 0x00, 0x89 },
{ 0x7b, 0x00, 0x84 },
{ 0x7f, 0x00, 0x80 },
{ 0x84, 0x00, 0x7b },
{ 0x88, 0x00, 0x77 },
{ 0x8d, 0x00, 0x73 },
{ 0x91, 0x00, 0x6e },
{ 0x95, 0x00, 0x6a },
{ 0x9a, 0x00, 0x65 },
{ 0x9e, 0x00, 0x61 },
{ 0xa3, 0x00, 0x5d },
{ 0xa7, 0x00, 0x58 },
{ 0xab, 0x00, 0x54 },
{ 0xb0, 0x00, 0x4f },
{ 0xb4, 0x00, 0x4b },
{ 0xb9, 0x00, 0x47 },
{ 0xbd, 0x00, 0x42 },
{ 0xc1, 0x00, 0x3e },
{ 0xc6, 0x00, 0x39 },
{ 0xca, 0x00, 0x35 },
{ 0xcf, 0x00, 0x31 },
{ 0xd3, 0x00, 0x2c },
{ 0xd7, 0x00, 0x28 },
{ 0xdc, 0x00, 0x23 },
{ 0xe0, 0x00, 0x1f },
{ 0xe5, 0x00, 0x1b },
{ 0xe9, 0x00, 0x16 },
{ 0xed, 0x00, 0x12 },
{ 0xf2, 0x00, 0x0d },
{ 0xf6, 0x00, 0x09 },
{ 0xfb, 0x00, 0x05 },
{ 0xfe, 0x01, 0x01 },
{ 0xff, 0x06, 0x00 },
{ 0xff, 0x0d, 0x00 },
{ 0xff, 0x13, 0x00 },
{ 0xff, 0x1a, 0x00 },
{ 0xff, 0x20, 0x00 },
{ 0xff, 0x26, 0x00 },
{ 0xff, 0x2d, 0x00 },
{ 0xff, 0x33, 0x00 },
{ 0xff, 0x3a, 0x00 },
{ 0xff, 0x40, 0x00 },
{ 0xff, 0x46, 0x00 },
{ 0xff, 0x4d, 0x00 },
{ 0xff, 0x53, 0x00 },
{ 0xff, 0x59, 0x00 },
{ 0xff, 0x60, 0x00 },
{ 0xff, 0x66, 0x00 },
{ 0xff, 0x6c, 0x00 },
{ 0xff, 0x73, 0x00 },
{ 0xff, 0x79, 0x00 },
{ 0xff, 0x80, 0x00 },
{ 0xff, 0x86, 0x00 },
{ 0xff, 0x8c, 0x00 },
{ 0xff, 0x93, 0x00 },
{ 0xff, 0x99, 0x00 },
{ 0xff, 0x9f, 0x00 },
{ 0xff, 0xa6, 0x00 },
{ 0xff, 0xac, 0x00 },
{ 0xff, 0xb3, 0x00 },
{ 0xff, 0xb9, 0x00 },
{ 0xff, 0xbf, 0x00 },
{ 0xff, 0xc6, 0x00 },
{ 0xff, 0xcc, 0x00 },
{ 0xff, 0xd2, 0x00 },
{ 0xff, 0xd9, 0x00 },
{ 0xff, 0xdf, 0x00 },
{ 0xff, 0xe6, 0x00 },
{ 0xff, 0xec, 0x00 },
{ 0xff, 0xf2, 0x00 },
{ 0xff, 0xf9, 0x00 },
{ 0xff, 0xfe, 0x01 },
{ 0xff, 0xff, 0x06 },
{ 0xff, 0xff, 0x0d },
{ 0xff, 0xff, 0x14 },
{ 0xff, 0xff, 0x1b },
{ 0xff, 0xff, 0x21 },
{ 0xff, 0xff, 0x28 },
{ 0xff, 0xff, 0x2f },
{ 0xff, 0xff, 0x35 },
{ 0xff, 0xff, 0x3c },
{ 0xff, 0xff, 0x42 },
{ 0xff, 0xff, 0x49 },
{ 0xff, 0xff, 0x4f },
{ 0xff, 0xff, 0x56 },
{ 0xff, 0xff, 0x5d },
{ 0xff, 0xff, 0x63 },
{ 0xff, 0xff, 0x6a },
{ 0xff, 0xff, 0x71 },
{ 0xff, 0xff, 0x77 },
{ 0xff, 0xff, 0x7e },
{ 0xff, 0xff, 0x84 },
{ 0xff, 0xff, 0x8b },
{ 0xff, 0xff, 0x92 },
{ 0xff, 0xff, 0x98 },
{ 0xff, 0xff, 0x9f },
{ 0xff, 0xff, 0xa6 },
{ 0xff, 0xff, 0xac },
{ 0xff, 0xff, 0xb3 },
{ 0xff, 0xff, 0xb9 },
{ 0xff, 0xff, 0xc0 },
{ 0xff, 0xff, 0xc7 },
{ 0xff, 0xff, 0xcd },
{ 0xff, 0xff, 0xd4 },
{ 0xff, 0xff, 0xdb },
{ 0xff, 0xff, 0xe1 },
{ 0xff, 0xff, 0xe8 },
{ 0xff, 0xff, 0xee },
{ 0xff, 0xff, 0xf5 },
{ 0xff, 0xff, 0xfb }
} };
const std::array<ui::Color, 256> spectrum_rgb4_lut { {
+23 -1
View File
@@ -104,8 +104,30 @@ void tone_keys_populate(OptionsField& field) {
field.set_options(tone_key_options);
}
float tone_key_frequency(const uint32_t index) {
float tone_key_frequency(const tone_index index) {
return tone_keys[index].second;
}
std::string tone_key_string( tone_index index ) {
if( index < 0 || (unsigned)index >= tone_keys . size() )
return std::string( "" );
return tone_keys[ index ] .first ;
}
tone_index tone_key_index_by_string( char *str ) {
if( !str )
return -1 ;
for( tone_index index = 0 ; (unsigned)index < tone_keys . size() ; index ++ )
{
if( tone_keys[ index ] . first . compare( str ) >= 0 )
return index ;
}
return -1 ;
}
/* tone_index tone_key_index_by_value( int32_t freq )
{
return -1 ;
} */
}
+7 -1
View File
@@ -30,12 +30,18 @@ using namespace ui;
namespace tonekey {
typedef int16_t tone_index ;
using tone_key_t = std::vector<std::pair<std::string, float>>;
extern const tone_key_t tone_keys;
void tone_keys_populate(OptionsField& field);
float tone_key_frequency(const uint32_t index);
float tone_key_frequency(const tone_index index);
std::string tone_key_string( const tone_index index );
tone_index tone_key_index_by_string( char *str );
// tone_index tone_key_index_by_value( int32_t freq );
}
-8
View File
@@ -76,14 +76,6 @@ ui::Point Calibration::translate(const DigitizerPoint& p) const {
return { x_clipped, y_clipped };
}
const Calibration default_calibration() {
/* Values derived from one PortaPack H1 unit. */
return {
{ { { 256, 731 }, { 880, 432 }, { 568, 146 } } },
{ { { 32, 48 }, { 208, 168 }, { 120, 288 } } }
};
};
void Manager::feed(const Frame& frame) {
// touch_debounce.feed(touch_raw);
const auto touch_raw = frame.touch;
+9 -2
View File
@@ -137,6 +137,15 @@ struct Calibration {
{
}
constexpr Calibration() :
Calibration(
/* Values derived from one PortaPack H1 unit. */
{ { { 256, 731 }, { 880, 432 }, { 568, 146 } } },
{ { { 32, 48 }, { 208, 168 }, { 120, 288 } } }
)
{
}
ui::Point translate(const DigitizerPoint& p) const;
private:
@@ -149,8 +158,6 @@ private:
int32_t f;
};
const Calibration default_calibration();
template<size_t N>
class Filter {
public:
+2
View File
@@ -247,6 +247,8 @@ public:
parent_pos,
5,
{
{ " 10", 10 }, /* Fine tuning SSB voice pitch,in HF and QO-100 sat #669 */
{ " 50", 50 }, /* added 50Hz/10Hz,but we do not increase GUI digit decimal */
{ " 100", 100 },
{ " 1k ", 1000 },
{ " 3k ", 3000 }, /* Approximate SSB bandwidth */
+15
View File
@@ -80,6 +80,21 @@ void RSSI::paint(Painter& painter) {
}
}
int32_t RSSI::get_min()
{
return min_ ;
}
int32_t RSSI::get_avg()
{
return avg_ ;
}
int32_t RSSI::get_max()
{
return max_ ;
}
void RSSI::set_pitch_rssi(bool enabled) {
pitch_rssi_enabled = enabled;
if (!enabled) baseband::set_pitch_rssi(0, false);
+3
View File
@@ -46,6 +46,9 @@ public:
}
void paint(Painter& painter) override;
int32_t get_min();
int32_t get_avg();
int32_t get_max();
private:
int32_t min_;
+8 -2
View File
@@ -57,6 +57,7 @@
#include "ui_remote.hpp"
#include "ui_scanner.hpp"
#include "ui_search.hpp"
#include "ui_recon.hpp"
#include "ui_sd_wipe.hpp"
#include "ui_settings.hpp"
#include "ui_siggen.hpp"
@@ -65,6 +66,7 @@
//#include "ui_test.hpp"
#include "ui_tone_search.hpp"
#include "ui_touchtunes.hpp"
#include "ui_playlist.hpp"
#include "ui_view_wav.hpp"
#include "ui_whipcalc.hpp"
@@ -481,6 +483,7 @@ ReceiversMenuView::ReceiversMenuView(NavigationView& nav) {
{ "POCSAG", ui::Color::green(), &bitmap_icon_pocsag, [&nav](){ nav.push<POCSAGAppView>(); } },
{ "Radiosnde", ui::Color::green(), &bitmap_icon_sonde, [&nav](){ nav.push<SondeView>(); } },
{ "TPMS Cars", ui::Color::green(), &bitmap_icon_tpms, [&nav](){ nav.push<TPMSAppView>(); } },
{ "Recon", ui::Color::green(), &bitmap_icon_scanner, [&nav](){ nav.push<ReconView>(); } },
{ "APRS", ui::Color::green(), &bitmap_icon_aprs, [&nav](){ nav.push<APRSRXView>(); } }
/*
{ "DMR", ui::Color::dark_grey(), &bitmap_icon_dmr, [&nav](){ nav.push<NotImplementedView>(); } },
@@ -518,6 +521,8 @@ TransmittersMenuView::TransmittersMenuView(NavigationView& nav) {
{ "SSTV", ui::Color::green(), &bitmap_icon_sstv, [&nav](){ nav.push<SSTVTXView>(); } },
{ "TEDI/LCR", ui::Color::yellow(), &bitmap_icon_lcr, [&nav](){ nav.push<LCRView>(); } },
{ "TouchTune", ui::Color::yellow(), &bitmap_icon_remote, [&nav](){ nav.push<TouchTunesView>(); } },
{ "Playlist", ui::Color::yellow(), &bitmap_icon_remote, [&nav](){ nav.push<PlaylistView>(); } },
//{ "Remote", ui::Color::dark_grey(), &bitmap_icon_remote, [&nav](){ nav.push<RemoteView>(); } },
});
}
@@ -536,9 +541,10 @@ UtilitiesMenuView::UtilitiesMenuView(NavigationView& nav) {
//{ "Notepad", ui::Color::dark_grey(), &bitmap_icon_notepad, [&nav](){ nav.push<NotImplementedView>(); } },
{ "Signal gen", ui::Color::green(), &bitmap_icon_cwgen, [&nav](){ nav.push<SigGenView>(); } },
//{ "Tone search", ui::Color::dark_grey(), nullptr, [&nav](){ nav.push<ToneSearchView>(); } },
{ "WAV 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>(); } },
{ "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
}
+12 -6
View File
@@ -42,10 +42,16 @@ void Modulator::set_over(uint32_t new_over) {
over = new_over;
}
void Modulator::set_gain_vumeter_beep(float new_audio_gain , bool new_play_beep ) {
audio_gain = new_audio_gain ;
void Modulator::set_gain_shiftbits_vumeter_beep(float new_audio_gain ,uint8_t new_audio_shift_bits_s16, bool new_play_beep ) {
//new_audio_shift_bits_s16 are the direct shift bits (FM mod >>x) , and it is fixed to >>8_FM (AK) or 4,5,6, (WM boost OFF) or 6,7 (WM boost ON)
audio_gain = new_audio_gain ;
audio_shift_bits_s16_FM = new_audio_shift_bits_s16; //FM : >>8(AK) fixed , >>4,5,6 (WM boost OFF)
if (new_audio_shift_bits_s16==8) { //FM : we are in AK codec IC => for AM-SSB-DSB we were using >>2 fixed (wm boost ON) .
audio_shift_bits_s16_AM_DSB_SSB = 2; //AM-DSB-SSB: >>2(AK) fixed , >>0,1,2 (WM boost OFF)
} else {
audio_shift_bits_s16_AM_DSB_SSB = (new_audio_shift_bits_s16-4) ; //AM-DSB-SSB: >>0,1,2 (WM boost OFF), >>2,3 (WM boost ON)
}
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 ) {
@@ -85,7 +91,7 @@ void SSB::execute(const buffer_s16_t& audio, const buffer_c8_t& buffer, bool& co
if (counter % 128 == 0) {
float i = 0.0, q = 0.0;
sample = audio.p[counter / over] >> 2;
sample = audio.p[counter / over] >> audio_shift_bits_s16_AM_DSB_SSB; // originally fixed >> 2, now >>2 for AK, 0,1,2,3 for WM (boost off)
sample *= audio_gain; // Apply GAIN Scale factor to the audio TX modulation.
//switch (mode) {
@@ -145,7 +151,7 @@ void FM::execute(const buffer_s16_t& audio, const buffer_c8_t& buffer, bool& con
for (size_t counter = 0; counter < buffer.count; counter++) {
sample = audio.p[counter>>6] >> 8; // sample = audio.p[counter / over] >> 8; (not enough efficient running code, over = 1536000/240000= 64 )
sample = audio.p[counter>>6] >> audio_shift_bits_s16_FM ; // Orig. >>8 , sample = audio.p[counter / over] >> 8; (not enough efficient running code, over = 1536000/240000= 64 )
sample *= audio_gain; // Apply GAIN Scale factor to the audio TX modulation.
if (play_beep) {
@@ -190,7 +196,7 @@ void AM::execute(const buffer_s16_t& audio, const buffer_c8_t& buffer, bool& con
for (size_t counter = 0; counter < buffer.count; counter++) {
if (counter % 128 == 0) {
sample = audio.p[counter / over] >> 2;
sample = audio.p[counter / over] >> audio_shift_bits_s16_AM_DSB_SSB; // originally fixed >> 2, now >>2 for AK, 0,1,2,3 for WM (boost off)
sample *= audio_gain; // Apply GAIN Scale factor to the audio TX modulation.
}
+3 -1
View File
@@ -50,9 +50,11 @@ public:
void set_mode(Mode new_mode);
void set_over(uint32_t new_over);
void set_gain_vumeter_beep(float new_audio_gain , bool new_play_beep );
void set_gain_shiftbits_vumeter_beep(float new_audio_gain ,uint8_t new_audio_shift_bits_s16, 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 { };
uint8_t audio_shift_bits_s16_FM { }; // shift bits factor to the captured ADC S16 audio sample.
uint8_t audio_shift_bits_s16_AM_DSB_SSB { };
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
+2 -1
View File
@@ -35,7 +35,7 @@ void MicTXProcessor::execute(const buffer_c8_t& buffer){
if (!configured) return;
audio_input.read_audio_buffer(audio_buffer);
modulator->set_gain_vumeter_beep(audio_gain, play_beep ) ;
modulator->set_gain_shiftbits_vumeter_beep(audio_gain, audio_shift_bits_s16, 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
@@ -141,6 +141,7 @@ void MicTXProcessor::on_message(const Message* const msg) {
}
audio_gain = config_message.audio_gain;
audio_shift_bits_s16 = config_message.audio_shift_bits_s16;
divider = config_message.divider;
power_acc_count = 0;
+2
View File
@@ -61,6 +61,8 @@ private:
uint32_t divider { };
float audio_gain { };
uint8_t audio_shift_bits_s16 { } ; // shift bits factor to the captured ADC S16 audio sample.
uint64_t power_acc { 0 };
uint32_t power_acc_count { 0 };
bool play_beep { false };
+113 -22
View File
@@ -27,15 +27,88 @@
#include <cstdint>
void OOKProcessor::execute(const buffer_c8_t& buffer) {
inline void OOKProcessor::write_sample(const buffer_c8_t& buffer, uint8_t bit_value, size_t i) {
int8_t re, im;
if (bit_value) {
phase = (phase + 200); // What ?
sphase = phase + (64 << 18);
re = (sine_table_i8[(sphase & 0x03FC0000) >> 18]);
im = (sine_table_i8[(phase & 0x03FC0000) >> 18]);
} else {
re = 0;
im = 0;
}
buffer.p[i] = {re, im};
}
inline void OOKProcessor::duval_algo(const buffer_c8_t& buffer) {
size_t buf_ptr = 0;
const unsigned int w = de_bruijn_length;
// Duval's algorithm for generating de Bruijn sequence
while (idx) {
if (w % idx == 0) {
for (; k < idx; k++) {
size_t available_size = buffer.count - buf_ptr;
size_t len = (samples_per_bit > available_size) ? available_size : samples_per_bit;
for (; bit_ptr < len; bit_ptr++) {
write_sample(buffer, v[k], buf_ptr);
buf_ptr++;
}
if (buf_ptr == buffer.count) {
txprogress_message.done = false;
txprogress_message.progress = scan_progress++;
shared_memory.application_queue.push(txprogress_message);
return;
}
bit_ptr = 0;
}
k = 0;
}
for (unsigned int j = 0; j < w - idx; j++)
v[idx + j] = v[j];
for (idx = w; idx > 0 && v[idx - 1]; idx--) ;
if (idx)
v[idx - 1] = 1;
}
// clear the buffer in case we have any bytes left
if (buf_ptr < buffer.count) {
for (size_t i = buf_ptr; i < buffer.count; i++) {
buffer.p[i] = {0, 0};
}
}
if (!scan_done) {
txprogress_message.done = true;
shared_memory.application_queue.push(txprogress_message);
}
scan_done = 1;
}
void OOKProcessor::execute(const buffer_c8_t& buffer) {
// This is called at 2.28M/2048 = 1113Hz
if (!configured) return;
if (de_bruijn_length) {
duval_algo(buffer);
return;
}
for (size_t i = 0; i < buffer.count; i++) {
// Synthesis at 2.28M/10 = 228kHz
if (!s) {
s = 10 - 1;
@@ -49,11 +122,11 @@ void OOKProcessor::execute(const buffer_c8_t& buffer) {
} else if (pause_counter == 1) {
if (repeat_counter < repeat) {
// Repeat
bit_pos = 0;
cur_bit = shared_memory.bb_data.data[0] & 0x80;
txprogress_message.progress = repeat_counter + 1;
txprogress_message.done = false;
shared_memory.application_queue.push(txprogress_message);
bit_pos = 1;
repeat_counter++;
} else {
// Stop
@@ -71,7 +144,7 @@ void OOKProcessor::execute(const buffer_c8_t& buffer) {
bit_pos++;
}
}
sample_count = 0;
} else {
sample_count++;
@@ -79,31 +152,49 @@ void OOKProcessor::execute(const buffer_c8_t& buffer) {
} else {
s--;
}
if (cur_bit) {
phase = (phase + 200); // What ?
sphase = phase + (64 << 18);
re = (sine_table_i8[(sphase & 0x03FC0000) >> 18]);
im = (sine_table_i8[(phase & 0x03FC0000) >> 18]);
} else {
re = 0;
im = 0;
}
buffer.p[i] = {re, im};
write_sample(buffer, cur_bit, i);
}
}
void OOKProcessor::on_message(const Message* const p) {
const auto message = *reinterpret_cast<const OOKConfigureMessage*>(p);
if (message.id == Message::ID::OOKConfigure) {
samples_per_bit = message.samples_per_bit / 10;
configured = false;
repeat = message.repeat - 1;
length = message.stream_length;
pause = message.pause_symbols + 1;
de_bruijn_length = message.de_bruijn_length;
samples_per_bit = message.samples_per_bit;
if (!length && !samples_per_bit) {
// shutdown
return;
}
if (de_bruijn_length) {
if (de_bruijn_length > sizeof(v)) {
return;
}
if (samples_per_bit > 2048) {
// can't handle more than dma::transfer_samples
return;
}
k = 0;
bit_ptr = 0;
idx = 1;
scan_done = false;
scan_progress = 0;
memset(v, 0, sizeof(v));
} else {
samples_per_bit /= 10;
}
pause_counter = 0;
s = 0;
sample_count = samples_per_bit;
+17 -5
View File
@@ -29,19 +29,20 @@
class OOKProcessor : public BasebandProcessor {
public:
void execute(const buffer_c8_t& buffer) override;
void on_message(const Message* const p) override;
private:
bool configured = false;
BasebandThread baseband_thread { 2280000, this, NORMALPRIO + 20, baseband::Direction::Transmit };
uint32_t samples_per_bit { 0 };
uint8_t repeat { 0 };
uint32_t length { 0 };
uint32_t pause { 0 };
uint8_t de_bruijn_length { 0 };
uint32_t pause_counter { 0 };
uint8_t repeat_counter { 0 };
uint8_t s { 0 };
@@ -50,8 +51,19 @@ private:
uint32_t sample_count { 0 };
uint32_t tone_phase { 0 }, phase { 0 }, sphase { 0 };
int32_t tone_sample { 0 }, sig { 0 }, frq { 0 };
TXProgressMessage txprogress_message { };
static constexpr auto MAX_DE_BRUIJN_ORDER = 24;
uint8_t v[MAX_DE_BRUIJN_ORDER];
unsigned int idx { 0 };
unsigned int k { 0 };
size_t bit_ptr{ 0 };
size_t scan_progress{ 0 };
uint8_t scan_done { true };
void write_sample(const buffer_c8_t& buffer, uint8_t bit_value, size_t i);
void duval_algo(const buffer_c8_t& buffer);
};
#endif
+323 -66
View File
@@ -216,90 +216,347 @@ void AK4951::speaker_disable() {
set_speaker_power(false);
}
void AK4951::microphone_enable() {
// map.r.digital_mic.DMIC = 0;
// update(Register::DigitalMic);
void AK4951::microphone_enable(int8_t alc_mode) {
// alc_mode =0 = (OFF =same as original code = NOT using AK4951 Programmable digital filter block),
// alc_mode >1 (with DIGITAL FILTER BLOCK , example : 1:(+12dB) , 2:(+9dB)", 3:(+6dB), ...)
// map.r.digital_mic.DMIC = 0; // originally commented code
// update(Register::DigitalMic); // originally commented code
uint_fast8_t mgain =0b0111; // Pre-amp mic (Original code, =0b0111 (+21dB's=7x3dBs),(Max is NOT 0b1111!, it is 0b1010=+30dBs=10x3dBs)
map.r.signal_select_2.INL = 0b01; // Lch input signal = LIN2 , our ext. MONO MIC is connected here LIN2 in Portapack.
map.r.signal_select_2.INR = 0b01; // Rch input signal = RIN2 , Not used ,not connected ,but no problem.
map.r.signal_select_2.MICL = 0; // MPWR = 2.4V (it has two possible settings , 2.4V or 2.0V) , (majority smarthphones around 2V , range 1V-5V)
update(Register::SignalSelect2);
// ------Common code part, = original setting conditions, it is fine for all user-GUI alc_modes: OFF , and ALC modes .*/
map.r.digital_filter_select_1.HPFAD = 1; // HPF1 ON (after ADC);page 40 datasheet, HPFAD bit controls the ON/OFF of the HPF1 (HPF ON is recommended).
map.r.digital_filter_select_1.HPFC = 0b11; // HPF Cut off frequency of high pass filter from 236.8 Hz @fs=48k ("00":3.7Hz, "01":14,8Hz, "10":118,4Hz)
update(Register::DigitalFilterSelect1);
// map.r.r_ch_mic_gain_setting.MGR = 0x80; // Microphone sensitivity correction = 0dB., (not used by now , original code cond.)
// update(Register::RchMicGainSetting); // (those two lines , not activated, same as original)
// pre-load 4 byes LPF coefficicients (.lpf_coefficient_0,1,2,3), FSA 14..0, FSB 14..0 , (fcut initial 6kHz, fs 48Khz).
// it will be default pre-loading coeff. for al ALC modes, LPF bit is activated down, for all ALC digital modes.
map.r.lpf_coefficient_0.l = 0x5F; // Pre-loading here LPF 6kHz, 1st Order from digital Block , Fc=6000 Hz, fs = 48khz
map.r.lpf_coefficient_1.h = 0x09; // LPF bit is activated down, for all ALC digital modes.
map.r.lpf_coefficient_2.l = 0xBF; // Writting reg to AK4951, with "update", following instructions.
map.r.lpf_coefficient_3.h = 0x32;
update(Register::LPFCoefficient0); // Writing pre-loaded 4 bytes LPF CoefFiecients 14 bits (FSA13..0, FSB13..0
update(Register::LPFCoefficient1); // In this case , LPF 6KHz , when we activate the LPF block.
update(Register::LPFCoefficient2);
update(Register::LPFCoefficient3);
// Reset , setting OFF all 5 x Digital Equalizer filters
map.r.digital_filter_select_3.EQ1 = 0; // EQ1 Coeffic Setting , (0: Disable-default, audio data passes EQ1 block by 0dB gain). When EQ1="1”, the settings of E1A15-0, E1B15-0 and E1C15-0 bits are enabled
map.r.digital_filter_select_3.EQ2 = 0; // EQ2 Coeffic Setting , (0: Disable-default, audio data passes EQ2 block by 0dB gain). When EQ2="1”, the settings of E2A15-0, E2B15-0 and E2C15-0 bits are enabled
map.r.digital_filter_select_3.EQ3 = 0; // EQ3 Coeffic Setting , (0: Disable-default, audio data passes EQ3 block by 0dB gain). When EQ3="1”, the settings of E3A15-0, E3B15-0 and E3C15-0 bits are enabled
map.r.digital_filter_select_3.EQ4 = 0; // EQ4 Coeffic Setting , (0: Disable-default, audio data passes EQ4 block by 0dB gain). When EQ4="1”, the settings of E4A15-0, E4B15-0 and E4C15-0 bits are enabled
map.r.digital_filter_select_3.EQ5 = 0; // EQ5 Coeffic Setting , (0: Disable-default, audio data passes EQ5 block by 0dB gain). When EQ5="1”, the settings of E5A15-0, E5B15-0 and E5C15-0 bits are enabled
update(Register::DigitalFilterSelect3); // A,B,C EQ1 Coefficients are already pre-loaded in ak4951.hpp
if (alc_mode==0) { // Programmable Digital Filter OFF, same as original condition., no Digital ALC, nor Wind Noise Filter, LPF , EQ
map.r.digital_filter_select_2.LPF = 0; // LPF-Block, Coeffic Setting Enable (OFF-Default), When LPF bit is “0”, audio data passes the LPF block by 0dB gain.
update(Register::DigitalFilterSelect2);
// Pre-loading AUDIO PATH with all DIGITAL BLOCK by pased, see, audio path block diagramm AK4951 datasheet + Table Playback mode -Recording mode.
// Digital filter block PATH is BY PASSED (we can swith off DIG. BLOCK power , PMPFIL=0) .The Path in Recording Mode 2 & Playback Mode 2 (NO DIG FILTER BLOCK AT ALL, not for MIC recording, nor for Playback)
map.r.digital_filter_mode.ADCPF = 1; // ADCPF bit swith ("0" Mic after ADC Output connected (recording mode) to the DIGITAL FILTER BLOCK. ("1" Playback mode)
map.r.digital_filter_mode.PFSDO = 0; // ADC bit switch ("0" : 1st order HPF) connectedto the Output. By bass DIGITAL block .
map.r.digital_filter_mode.PFDAC = 0b00; // (Input selector for DAC (not used in MIC), SDTI= Audio Serial Data Input Pin)
update(Register::DigitalFilterMode); // Writing the Audio Path : NO DIGITAL BLOCK or DIG BLOCK FOR MIC , Audio mode path : Playback mode /-Recording mode.
map.r.power_management_1.PMADL = 1; // ADC Lch = Lch input signal. Mic Amp Lch and ADC Lch Power Management
map.r.power_management_1.PMADR = 1; // ADC Rch = Rch input signal. Mic Amp Rch and ADC Rch Power Management
map.r.power_management_1.PMPFIL = 0; // Pre-loading , Programmable Dig. filter OFF ,filter unused, routed around.(original value = 0 )
update(Register::PowerManagement1); // Activating the Power management of the used blocks . (Mic ADC always + Dig Block filter , when used )
// 1059/fs, 22ms @ 48kHz
chThdSleepMilliseconds(22);
} else { // ( alc_mode !=0)
switch(alc_mode) { // Pre-loading register values depending on user-GUI selection (they will be sended below, with "update(Register_name::xxx )".
case 1: // ALC-> on, (+12dB's) Auto Vol max + Wind Noise cancel + LPF 6kHz + Pre-amp Mic (+21dB=original)
map.r.alc_mode_control_2.REF = 0xC0; // REF7-0 bits,max gain at ALC recovery operation,(FFH +36dBs , D0H +18dBs, A0H 0dBs, C0H=+12dBs)
map.r.l_ch_input_volume_control.IV = 0xC0; // Left, Input Digital Volume Setting, (FFH +36dBs , D0H +18dBs, A0H 0dBs, 70H=-18dBs)
map.r.r_ch_input_volume_control.IV = 0xC0; // Right Input Dig Vol Setting, same comment as above , The value of IVOL should be <= than REFs
// Already Pre-loaded, "map.r.lpf_coefficient", 6Khz - LPF 1st Order from digital Block,Fc=6000Hz,fs = 48khz
// LPF bit is activated down, for all ALC digital modes.
break;
case 2: // ALC-> on, (+09dB's) Auto Vol max + Wind Noise cancel + LPF 6kHz + Pre-amp Mic (+21dB=original)
map.r.alc_mode_control_2.REF = 0xB8; // REF7-0 bits,max gain at ALC recoveryoperation,(FFH +36dBs , D0H +18dBs, A0H 0dBs, B8H= +9dBs)
map.r.l_ch_input_volume_control.IV = 0xB8; // Left, Input Digital Volume Setting, (FFH +36dBs , D0H +18dBs, A0H 0dBs, 70H=-18dBs)
map.r.r_ch_input_volume_control.IV = 0xB8; // Right Input Dig Vol Setting, same comment as above , The value of IVOL should be <= than REFs
// Already Pre-loaded, "map.r.lpf_coefficient", 6Khz - LPF 1st Order from digital Block,Fc=6000Hz,fs = 48khz
// LPF bit is activated down, for all ALC digital modes.
break;
case 3: // ALC-> on, (+06dB's) Auto Vol max + Wind Noise cancel + LPF 6kHz + Pre-amp Mic (+21dB=original)
map.r.alc_mode_control_2.REF = 0xB0; // 0xB8 , REF7-0 bits,max gain at ALC recoveryoperation,(FFH +36dBs , D0H +18dBs, A0H 0dBs, B0H= +6dBs)
map.r.l_ch_input_volume_control.IV = 0xB0; // Left, Input Digital Volume Setting, (FFH +36dBs , D0H +18dBs, A0H 0dBs, 70H=-18dBs)
map.r.r_ch_input_volume_control.IV = 0xB0; // Right Input Dig Vol Setting, same comment as above , Then value of IVOL should be <= than REFs
// Already Pre-loaded, "map.r.lpf_coefficient", 6Khz - LPF 1st Order from digital Block,Fc=6000Hz,fs = 48khz
// LPF bit is activated down, for all ALC digital modes.
break;
case 4: // ALC-> on, (+03dB's) Auto Vol max + Wind Noise cancel + Pre-amp Mic (+21dB=original)
// + EQ boosting ~<2kHz (f0:1,1k, fb:1,7K, k=1,8) && + LPF 3,5k
map.r.alc_mode_control_2.REF = 0xA8; // 0xA8 , REF7-0 bits,max gain at ALC recoveryoperation,(FFH +36dBs , D0H +18dBs, A0H 0dBs, A8H= +3dBs)
map.r.l_ch_input_volume_control.IV = 0xA8; // Left, Input Digital Volume Setting, (FFH +36dBs , D0H +18dBs, A0H 0dBs, 70H=-18dBs)
map.r.r_ch_input_volume_control.IV = 0xA8; // Right Input Dig Vol Setting, same comment as above , Then value of IVOL should be <= than REFs
//The EQn (n=1, 2, 3, 4 or 5) coefficient must be set when EQn bit = “0” or PMPFIL bit = “0”.
map.r.digital_filter_select_3.EQ1 = 1; // EQ1 Coeffic Setting , (0: Disable-default, audio data passes EQ1 block by 0dB gain). When EQ1="1”, the settings of E1A15-0, E1B15-0 and E1C15-0 bits are enabled
update(Register::DigitalFilterSelect3); // A,B,C EQ1 Coefficients are already pre-loaded in ak4951.hpp
map.r.lpf_coefficient_0.l = 0x0D; // Pre-loading here LPF 3,5k , 1st Order from digital Block , Fc=3.500 Hz, fs = 48khz
map.r.lpf_coefficient_1.h = 0x06; // LPF bit is activated down, for all ALC digital modes.
map.r.lpf_coefficient_2.l = 0x1A; // Writting reg to AK4951 , down with update....
map.r.lpf_coefficient_3.h = 0x2C;
// LPF bit is activated down, for all ALC digital modes.
break;
case 5: // ALC-> on, (+03dB's) Auto Vol max + Wind Noise cancel + Pre-amp Mic (+21dB=original)
// + EQ boosting ~<3kHz (f0~1k4,fb~2,4k,k=1,8) && LPF 4kHz
map.r.alc_mode_control_2.REF = 0xA8; // 0xA0 , REF7-0 bits,max gain at ALC recoveryoperation,(FFH +36dBs , D0H +18dBs, A0H 0dBs, A8H= +3dBs)
map.r.l_ch_input_volume_control.IV = 0xA8; // Left, Input Digital Volume Setting, (FFH +36dBs , D0H +18dBs, A0H 0dBs, 70H=-18dBs)
map.r.r_ch_input_volume_control.IV = 0xA8; // Right Input Dig Vol Setting, same comment as above , Then value of IVOL should be <= than REFs
map.r.digital_filter_select_3.EQ2 = 1; // EQ2 Coeffic Setting , (0: Disable-default, audio data passes EQ2 block by 0dB gain). When EQ2="1”, the settings of E2A15-0, E2B15-0 and E2C15-0 bits are enabled
update(Register::DigitalFilterSelect3);
map.r.lpf_coefficient_0.l = 0xC3; // Pre-loading here LPF 4k , 1st Order from digital Block , Fc=4000 Hz, fs = 48khz
map.r.lpf_coefficient_1.h = 0x06; // LPF bit is activated down, for all ALC digital modes.
map.r.lpf_coefficient_2.l = 0x86; // Writting reg to AK4951 , down with update....
map.r.lpf_coefficient_3.h = 0x2D;
// LPF bit is activated down, for all ALC digital modes.
break;
case 6: // ALC-> on, (+03dB's) Auto Vol max + Wind Noise cancel + LPF 6kHz + Pre-amp Mic (+21dB=original)
map.r.alc_mode_control_2.REF = 0xA8; // REF7-0 bits,max gain at ALC recoveryoperation,(FFH +36dBs , D0H +18dBs, A0H 0dBs, A0H= 0dBs)
map.r.l_ch_input_volume_control.IV = 0xA8; // Left, Input Digital Volume Setting, (FFH +36dBs , D0H +18dBs, A0H 0dBs, 70H=-18dBs)
map.r.r_ch_input_volume_control.IV = 0xA8; // Right Input Dig Vol Setting, same comment as above , Then value of IVOL should be <= than REFs
// Already Pre-loaded, "map.r.lpf_coefficient", 6Khz - LPF 1st Order from digital Block,Fc=6000Hz,fs = 48khz
// LPF bit is activated down, for all ALC digital modes.
break;
case 7: // ALC-> on, (+00dB's) Auto Vol max + Wind Noise cancel + LPF 6kHz + Pre-amp Mic (+21dB=original)
map.r.alc_mode_control_2.REF = 0xA0; // REF7-0 bits,max gain at ALC recoveryoperation,(FFH +36dBs , D0H +18dBs, A0H 0dBs, A0H= 0dBs)
map.r.l_ch_input_volume_control.IV = 0xA0; // Left, Input Digital Volume Setting, (FFH +36dBs , D0H +18dBs, A0H 0dBs, 70H=-18dBs)
map.r.r_ch_input_volume_control.IV = 0xA0; // Right Input Dig Vol Setting, same comment as above , Then value of IVOL should be <= than REFs
// Already Pre-loaded, "map.r.lpf_coefficient", 6Khz - LPF 1st Order from digital Block,Fc=6000Hz,fs = 48khz
// LPF bit is activated down, for all ALC digital modes.
break;
case 8: // ALC-> on, (-03dB's) Auto Vol max + Wind Noise cancel + LPF 6kHz + Pre-amp Mic (+21dB=original)
map.r.alc_mode_control_2.REF = 0x98; //REF7-0 bits,max gain at ALC recovery operation,(FFH +36dBs , D0H +18dBs, A0H 0dBs, 98H=-03dBs)
map.r.l_ch_input_volume_control.IV = 0x98; // Left, Input Digital Volume Setting, (FFH +36dBs , D0H +18dBs, A0H 0dBs, 70H=-18dBs)
map.r.r_ch_input_volume_control.IV = 0x98; // Right Input Dig Vol Setting, same comment as above , Then value of IVOL should be <= than REFs
const uint_fast8_t mgain = 0b0111;
map.r.signal_select_1.MGAIN20 = mgain & 7;
map.r.signal_select_1.PMMP = 1;
map.r.signal_select_1.MPSEL = 1; // MPWR2 pin
map.r.signal_select_1.MGAIN3 = (mgain >> 3) & 1;
update(Register::SignalSelect1);
// Already Pre-loaded, "map.r.lpf_coefficient", 6Khz - LPF 1st Order from digital Block,Fc=6000Hz,fs = 48khz
// LPF bit is activated down, for all ALC digital modes.
break;
map.r.signal_select_2.INL = 0b01; // Lch input signal = LIN2
map.r.signal_select_2.INR = 0b01; // Rch input signal = RIN2
map.r.signal_select_2.MICL = 0; // MPWR = 2.4V
update(Register::SignalSelect2);
case 9: // ALC-> on, (-06dB's) Auto Vol max + Wind Noise cancel + LPF 6kHz + Pre-amp Mic (+21dB=original)
map.r.alc_mode_control_2.REF = 0x90; // REF7-0 bits,max gain at ALC recovery operation,(FFH +36dBs , D0H +18dBs, A0H 0dBs, 90H=-06dBs)
map.r.l_ch_input_volume_control.IV = 0x90; // Left, Input Digital Volume Setting, (FFH +36dBs , D0H +18dBs, A0H 0dBs, 70H=-18dBs)
map.r.r_ch_input_volume_control.IV = 0x90; // Right Input Dig Vol Setting, same comment as above , Then value of IVOL should be <= than REFs
// map.r.r_ch_mic_gain_setting.MGR = 0x80; // Microphone sensitivity correction = 0dB.
// update(Register::RchMicGainSetting);
/*
map.r.timer_select.FRN = ?;
map.r.timer_select.FRATT = ?;
map.r.timer_select.ADRST = 0b??;
update(Register::TimerSelect);
// Already Pre-loaded, "map.r.lpf_coefficient", 6Khz - LPF 1st Order from digital Block,Fc=6000Hz,fs = 48khz
// LPF bit is activated down, for all ALC digital modes.
break;
map.r.alc_timer_select. = ?;
update(Register::ALCTimerSelect);
map.r.alc_mode_control_1. = ?;
map.r.alc_mode_control_1.ALC = 1;
case 10: // ALC-> on, (-09dB's) Auto Vol max + Wind Noise cancel + LPF 6kHz - Pre-amp MIC -3dB (18dB's)
// Reduce also Pre-amp Mic -3dB's (+18dB's)
mgain = 0b0110; // Pre-amp mic Mic Gain Pre-amp (+18dB), Original=0b0111 (+21dB's =7x3dBs),
map.r.alc_mode_control_2.REF = 0x88; // REF7-0 bits,max gain at ALC recovery operation,(FFH +36dBs , D0H +18dBs, A0H 0dBs, 88H=-09dBs)
map.r.l_ch_input_volume_control.IV = 0x88; // Left, Input Digital Volume Setting, (FFH +36dBs , D0H +18dBs, A0H 0dBs, 70H=-18dBs)
map.r.r_ch_input_volume_control.IV = 0x88; // Right Input Dig Vol Setting, same comment as above , Then value of IVOL should be <= than REFs
// Already Pre-loaded, "map.r.lpf_coefficient", 6Khz - LPF 1st Order from digital Block,Fc=6000Hz,fs = 48khz
// LPF bit is activated down, for all ALC digital modes.
break;
case 11: // ALC-> on, (-12dB's) Auto Vol max + Wind Noise cancel + LPF 6kHz - Pre-amp MIC -6dB (15dB's)
// Reduce also Pre-amp Mic -6dB's (+15dB's)
mgain = 0b0101; // Pre-amp mic Mic Gain Pre-amp (+15dB), (Original=0b0111 (+21dB's= 7x3dBs),
map.r.alc_mode_control_2.REF = 0x80; // REF7-0 bits,max gain at ALC recovery operation,(FFH +36dBs , D0H +18dBs, A0H 0dBs, 80H=-12dBs)
map.r.l_ch_input_volume_control.IV = 0x80; // Left, Input Digital Volume Setting, (FFH +36dBs , D0H +18dBs, A0H 0dBs, 70H=-18dBs)
map.r.r_ch_input_volume_control.IV = 0x80; // Right Input Dig Vol Setting, same comment as above , Then value of IVOL should be <= than REFs
// Already Pre-loaded, "map.r.lpf_coefficient", 6Khz - LPF 1st Order from digital Block,Fc=6000Hz,fs = 48khz
// LPF bit is activated down, for all ALC digital modes.
break;
}
//-------------------------------DIGITAL ALC (Automatic Level Control ) --- --------
map.r.alc_mode_control_1.ALC = 0; // LMTH2-0, WTM1-0, RGAIN2-0, REF7-0, RFST1-0, EQFC1-0, FRATT, FRN and ALCEQN bits (needs to be set up with ALC disable = 0)
update(Register::ALCModeControl1);
map.r.alc_mode_control_2.REF = ?;
map.r.timer_select.FRN = 0; // (FRN= 0 Fast Recovery mode , enable )
map.r.timer_select.FRATT = 0; // Fast Recovery Ref. Volume Atten. Amount -0,00106dB's, timing 4/fs (default)
map.r.timer_select.ADRST = 0b00; // initial offset ADC cycles , 22ms @fs=48Khz.
update(Register::TimerSelect);
map.r.alc_timer_select.RFST = 0b00; // RFST1-0: ALC Fast Recovery Speed Default: “00” (0.0032dB)
map.r.alc_timer_select.WTM = 0b00; // ALC Recovery Operation Waiting Period 128/fs = 2,7 mseg (min=default)
map.r.alc_timer_select.EQFC = 0b10; // Selecting default, fs 48Khz , ALCEQ: First order zero pole high pass filter fc2=100Hz, fc1=150Hz
map.r.alc_timer_select.IVTM = 0; // IVTM bit set the vol transition time ,236/fs = 4,9msecs (min) (default was 19,7msegs.)
update(Register::ALCTimerSelect);
map.r.alc_mode_control_1.LMTH10 = 0b11; // ALC Limiter Detec Level/ Recovery Counter Reset; lower 2 bits (Ob111=-8,4dbs), (default 0b000=-2,5dBs)
map.r.alc_mode_control_1.RGAIN = 0b000; // ALC Recovery Gain Step, max step , max speed. Default: “000” (0.00424dB)
map.r.alc_mode_control_1.ALC = 1; // ALC Enable . (we are now, NOT in MANUAL volume mode, only becomes manual when (ALC=“0” while ADCPF=“1”. )
map.r.alc_mode_control_1.LMTH2 = 1; // ALC Limiter Detection Level/ Recovery Counter Reset Level,Upper bit,default 0b000
map.r.alc_mode_control_1.ALCEQN = 1; // ALC EQ Off =1 not used by now, 0: ALC EQ On (default)
update(Register::ALCModeControl1);
// map.r.alc_mode_control_2.REF = 0x??; // Pre-loaded in top part. Maximum gain at ALC recovery operation,.(FFH +36dBs , D0H +18dBs, A0H 0dBs, 70H=-18dBs)
update(Register::ALCModeControl2);
*/
// map.r.l_ch_input_volume_control.IV = 0xe1;
// update(Register::LchInputVolumeControl);
// map.r.r_ch_input_volume_control.IV = 0xe1;
// update(Register::RchInputVolumeControl);
/*
map.r.auto_hpf_control.STG = 0b00;
map.r.auto_hpf_control.SENC = 0b011;
map.r.auto_hpf_control.AHPF = 0;
update(Register::AutoHPFControl);
*/
map.r.digital_filter_select_1.HPFAD = 1; // HPF1 (after ADC) = on
map.r.digital_filter_select_1.HPFC = 0b11; // 2336.8 Hz @ fs=48k
update(Register::DigitalFilterSelect1);
/*
map.r.digital_filter_select_2.HPF = 0;
map.r.digital_filter_select_2.LPF = 0;
map.r.digital_filter_select_2.FIL3 = 0;
map.r.digital_filter_select_2.EQ0 = 0;
map.r.digital_filter_select_2.GN = 0b00;
// map.r.l_ch_input_volume_control.IV = 0x??; // Pre-loaded in top part. Left, Input Digital Volume Setting, (FFH +36dBs , D0H +18dBs, A0H 0dBs, 70H=-18dBs)
update(Register::LchInputVolumeControl);
// map.r.r_ch_input_volume_control.IV = 0x??; // Pre-loaded in top part. Right,Input Digital Volume Setting, (FFH +36dBs , D0H +18dBs, A0H 0dBs, 70H=-18dBs)
update(Register::RchInputVolumeControl);
//---------------Switch ON, Digital Automatic Wind Noise Filter reduction -------------------
// Difficult to realise that Dynamic HPF Wind noise filter benefit, maybe because we have another fixed HPF 236.8 Hz .
// Anyway , we propose to activate it , with default setting conditions.
map.r.power_management_1.PMPFIL = 0; // (*1) To programm SENC, STG , we need PMPFIL = 0 . (but this disconnect Digital block power supply.
update(Register::PowerManagement1); // Updated PMPFIL to 0 . (*1)
map.r.auto_hpf_control.STG = 0b00; // (00=LOW ATTENUATION Level), lets put 11 (HIGH ATTENUATION Level) (default 00)
map.r.auto_hpf_control.SENC = 0b011; // (000=LOW sensitivity detection)… 111((MAX sensitivity detection) (default 011)
map.r.auto_hpf_control.AHPF = 1; // Autom. Wind noise filter ON (AHPF bit=“1”).It atten. wind noise when detecting ,and adjusts the atten. level dynamically.
update(Register::AutoHPFControl);
// We are in Digital Block ON , (Wind Noise Filter+ALC+LPF+EQ),==> needs at the end , PMPFIL=1 , Program. Dig.filter ON
// map.r.power_management_1.PMPFIL = 1; // that instruction is at the end , we can skp pre-loading Programmable Dig. filter ON (*1)
//---------------------------------------------------------------------
// Writing AUDIO PATH diagramm, Changing Audio mode path : Playback mode1 /-Recording mode2. (Figure 37 AK4951 datasheet, Table 27. Recording Playback Mode)
// When changing those modes, PMPFIL bit must be “0”, it is OK (*1)
map.r.digital_filter_mode.ADCPF = 1; // ADCPF bit swith ("0" Mic after ADC Output connected (recording mode) to the DIGITAL FILTER BLOCK. ("1" Playback mode)
map.r.digital_filter_mode.PFSDO = 1; // ADC (+ 1st order HPF) Output
map.r.digital_filter_mode.PFDAC = 0b00; // (Input selector for DAC (not used in MIC), SDTI= Audio Serial Data Input Pin)
update(Register::DigitalFilterMode); // Writing the Audio Path : NO DIGITAL BLOCK or DIG BLOCK FOR MIC , Audio mode path : Playback mode /-Recording mode.
// The EQn (n=1, 2, 3, 4 or 5) coefficient must be set when EQn bit = “0” or PMPFIL bit = “0”., but we are already (*1)
// map.r.power_management_1.PMPFIL = 0; // In the previous Wind Noise Filter , we already set up PPFIL = 0
// update(Register::PowerManagement1); // Activating the Power management of the used blocks . (Mic ADC always + Dig Block filter , when used )
// ... Set EQ & LPF coefficients ---------------------------------
// writting to the IC ak4951 reg. settings defined in Ak4951.hpp , the 30 bytes , EQ coefficient = 5 (EQ1,2,3,4,5) x 3 (A,B,C coefficients) x 2 bytes (16 bits)
update(Register::E1Coefficient0); // we could pre-load here,ex ,"map.r.e1_coefficient_0.l = 0x50;" , EQ1 Coefficient A : A7...A0, but already done in ak4951.hpp
update(Register::E1Coefficient1); // we could pre-load here,ex ,"map.r.e1_coefficient_1.h = 0xFE;" , EQ1 Coefficient A : A15..A8, " "
update(Register::E1Coefficient2); // we could pre-load here,ex ,"map.r.e1_coefficient_2.l = 0x29;" , EQ1 Coefficient B : B7...B0, " "
update(Register::E1Coefficient3); // we could pre-load here,ex ,"map.r.e1_coefficient_3.h = 0xC5;" , EQ1 Coefficient B : B15..B8, " "
update(Register::E1Coefficient4); // we could pre-load here,ex ,"map.r.e1_coefficient_4.l = 0xA0;" , EQ1 Coefficient C : C7...C0, " "
update(Register::E1Coefficient5); // we could pre-load here,ex ,"map.r.e1_coefficient_5.h = 0x1C;" , EQ1 Coefficient C : C15..C8, " "
update(Register::E2Coefficient0); // writing pre-loaded EQ2 coefficcients
update(Register::E2Coefficient1);
update(Register::E2Coefficient2);
update(Register::E2Coefficient3);
update(Register::E2Coefficient4);
update(Register::E2Coefficient5);
// Already pre-loaded LPF coefficients to 6k, 3,5k or 4k ,(LPF 6Khz all digital alc modes top , except when 3k5 , 4k)
update(Register::LPFCoefficient0); // Writing pre-loaded 4 bytes LPF CoefFiecients 14 bits (FSA13..0, FSB13..0
update(Register::LPFCoefficient1);
update(Register::LPFCoefficient2);
update(Register::LPFCoefficient3);
// Activating LPF block , (and re-configuring the rest of bits of the same register)
map.r.digital_filter_select_2.HPF = 0; // HPF2-Block, Coeffic Setting Enable (OFF-Default), When HPF bit is “0”, audio data passes the HPF2 block by is 0dB gain.
map.r.digital_filter_select_2.LPF = 1; // LPF-Block, Coeffic Setting Enable (OFF-Default), When LPF bit is “0”, audio data passes the LPF block by 0dB gain.
map.r.digital_filter_select_2.FIL3 = 0; // Stereo_Emphasis_Filter-Block,(OFF-Default) Coefficient Setting Enable , OFF , Disable.
map.r.digital_filter_select_2.EQ0 = 0; // Gain Compensation-Block, (OFF-Default) Coeffic Setting Enable, When EQ0 bit = “0” audio data passes the EQ0 block by 0dB gain.
map.r.digital_filter_select_2.GN = 0b00; // Gain Setting of the Gain Compensation Block Default: “00”-Default (0dB)
update(Register::DigitalFilterSelect2);
map.r.digital_filter_select_3.EQ1 = 0;
map.r.digital_filter_select_3.EQ2 = 0;
map.r.digital_filter_select_3.EQ3 = 0;
map.r.digital_filter_select_3.EQ4 = 0;
map.r.digital_filter_select_3.EQ5 = 0;
update(Register::DigitalFilterSelect3);
*/
map.r.digital_filter_mode.PFSDO = 0; // ADC (+ 1st order HPF) Output
map.r.digital_filter_mode.ADCPF = 1; // ADC Output (default)
update(Register::DigitalFilterMode);
// ... Set coefficients ...
map.r.power_management_1.PMADL = 1; // ADC Lch = Lch input signal
map.r.power_management_1.PMADR = 1; // ADC Rch = Rch input signal
map.r.power_management_1.PMPFIL = 0; // Programmable filter unused, routed around.
update(Register::PowerManagement1);
// Acitivating digital block , power supply
map.r.power_management_1.PMADL = 1; // ADC Lch = Lch input signal. Mic Amp Lch and ADC Lch Power Management
map.r.power_management_1.PMADR = 1; // ADC Rch = Rch input signal. Mic Amp Rch and ADC Rch Power Management
map.r.power_management_1.PMPFIL = 1; // Pre-loaded in top part. Orig value=0, Programmable Digital filter unused (not power up), routed around.
update(Register::PowerManagement1); // Activating the Power management of the used blocks . (Mic ADC always + Dig Block filter , when used )
// 1059/fs, 22ms @ 48kHz
chThdSleepMilliseconds(22);
}
// Common part for all alc_mode , --------------------------
// const uint_fast8_t mgain = 0b0111; // Already pre-loaded , in above switch case .
map.r.signal_select_1.MGAIN20 = mgain & 7; // writing 3 lower bits of mgain , (pre-amp mic gain).
map.r.signal_select_1.PMMP = 1; // Activating DC Mic Power supply through 2kohms res., similar majority smartphones headphone+mic jack, "plug-in-power"
map.r.signal_select_1.MPSEL = 1; // MPWR2 pin ,selecting output voltage to MPWR2 pin, that we are using in portapack ext. MIC)
map.r.signal_select_1.MGAIN3 = (mgain >> 3) & 1; // writing 4th upper bit of mgain (pre-amp mic gain).
update(Register::SignalSelect1);
}
void AK4951::microphone_disable() {
map.r.power_management_1.PMADL = 0;
map.r.power_management_1.PMADR = 0;
map.r.power_management_1.PMPFIL = 0;
map.r.power_management_1.PMADL = 0; // original code , disable Power managem.Mic ADC L
map.r.power_management_1.PMADR = 0; // original code , disable Power managem.Mic ADC R
map.r.power_management_1.PMPFIL = 0; // original code , disable Power managem. all Programmable Dig. block
update(Register::PowerManagement1);
map.r.alc_mode_control_1.ALC = 0;
map.r.alc_mode_control_1.ALC = 0; // original code , Restore , disable ALC block.
update(Register::ALCModeControl1);
map.r.auto_hpf_control.AHPF = 0; //----------- new code addition , Restore disable Wind noise filter OFF (AHPF bit=“0”).
update(Register::AutoHPFControl);
//Restore original AUDIO PATH , condition, (Digital filter block PATH is BY PASSED) (we can also swith off DIG. BLOCK power , PMPFIL=0)
// The Path in Recording Mode 2 & Playback Mode 2 , (NO DIG FILTER BLOCK AT ALL, not for MIC recording, nor for Playback)
map.r.digital_filter_mode.ADCPF = 1; // new code addition , ADCPF bit swith ("0" Mic after ADC Output connected (recording mode) to the DIGITAL FILTER BLOCK. ("1" Playback mode)
map.r.digital_filter_mode.PFSDO = 0; // new code addition , ADC bit switch ("0" : 1st order HPF) connectedto the Output. By bass DIGITAL block .
map.r.digital_filter_mode.PFDAC = 0b00; // new code addition , (Input selector for DAC (not used in MIC), SDTI= Audio Serial Data Input Pin)
update(Register::DigitalFilterMode); // Writing the Audio Path : NO DIGITAL BLOCK or DIG BLOCK FOR MIC , Audio mode path : Playback mode /-Recording mode.
// Restore original condition , LPF , OFF . same as when not using DIGITAL Programmable block
map.r.digital_filter_select_2.LPF = 0; // LPF-Block, Coeffic Setting Enable (OFF-Default), When LPF bit is “0”, audio data passes the LPF block by 0dB gain.
update(Register::DigitalFilterSelect2);
map.r.lpf_coefficient_0.l = 0x00; // Pre-loading here LPF 6k , 1st Order from digital Block , Fc=6000 Hz, fs = 48khz
map.r.lpf_coefficient_1.h = 0x00; // LPF bit is activated down, for all ALC digital modes.
map.r.lpf_coefficient_2.l = 0x00; // Writting reg to AK4951 , down with update....
map.r.lpf_coefficient_3.h = 0x00;
update(Register::LPFCoefficient0); // Writing pre-loaded 4 bytes LPF CoefFiecients 14 bits (FSA13..0, FSB13..0
update(Register::LPFCoefficient1);
update(Register::LPFCoefficient2);
update(Register::LPFCoefficient3);
// Switch off all EQ 1,2,3,4,5
map.r.digital_filter_select_3.EQ1 = 0; // EQ1 Coeffic Setting , (0: Disable-default, audio data passes EQ1 block by 0dB gain). When EQ1="1”, the settings of E1A15-0, E1B15-0 and E1C15-0 bits are enabled
map.r.digital_filter_select_3.EQ2 = 0; // EQ2 Coeffic Setting , (0: Disable-default, audio data passes EQ2 block by 0dB gain). When EQ2="1”, the settings of E2A15-0, E2B15-0 and E2C15-0 bits are enabled
map.r.digital_filter_select_3.EQ3 = 0; // EQ3 Coeffic Setting , (0: Disable-default, audio data passes EQ3 block by 0dB gain). When EQ3="1”, the settings of E3A15-0, E3B15-0 and E3C15-0 bits are enabled
map.r.digital_filter_select_3.EQ4 = 0; // EQ4 Coeffic Setting , (0: Disable-default, audio data passes EQ4 block by 0dB gain). When EQ4="1”, the settings of E4A15-0, E4B15-0 and E4C15-0 bits are enabled
map.r.digital_filter_select_3.EQ5 = 0; // EQ5 Coeffic Setting , (0: Disable-default, audio data passes EQ5 block by 0dB gain). When EQ5="1”, the settings of E5A15-0, E5B15-0 and E5C15-0 bits are enabled
update(Register::DigitalFilterSelect3);
}
reg_t AK4951::read(const address_t reg_address) {
+32 -31
View File
@@ -773,40 +773,41 @@ constexpr RegisterMap default_after_reset { Register_Type {
.REV = 0b1100,
},
.e1_coefficient_0 = { .l = 0x00 },
.e1_coefficient_1 = { .h = 0x00 },
.e1_coefficient_2 = { .l = 0x00 },
.e1_coefficient_3 = { .h = 0x00 },
.e1_coefficient_4 = { .l = 0x00 },
.e1_coefficient_5 = { .h = 0x00 },
// just pre-loading into memory, 30 bytes = EQ 1,2,3,4,5 x A,B,C (2 x bytes) coefficients, but it will be written from ak4951.cpp
.e1_coefficient_0 = { .l = 0xCA }, //EQ1 Coefficient A : A7...A0, BW : 300Hz - 1700Hz (fo = 1150Hz , fb= 1700Hz) , k=1,8 peaking
.e1_coefficient_1 = { .h = 0x05 }, //EQ1 Coefficient A : A15..A8
.e1_coefficient_2 = { .l = 0xEB }, //EQ1 Coefficient B : B7...B0
.e1_coefficient_3 = { .h = 0x38 }, //EQ1 Coefficient B : B15...B8
.e1_coefficient_4 = { .l = 0x6F }, //EQ1 Coefficient C : C7...C0
.e1_coefficient_5 = { .h = 0xE6 }, //EQ1 Coefficient C : C15..C8
.e2_coefficient_0 = { .l = 0x00 },
.e2_coefficient_1 = { .h = 0x00 },
.e2_coefficient_2 = { .l = 0x00 },
.e2_coefficient_3 = { .h = 0x00 },
.e2_coefficient_4 = { .l = 0x00 },
.e2_coefficient_5 = { .h = 0x00 },
.e2_coefficient_0 = { .l = 0x05 }, //EQ2 Coefficient A : A7...A0, BW : 250Hz - 2700Hz (fo = 1475Hz , fb= 2450Hz) , k=1,8 peaking
.e2_coefficient_1 = { .h = 0x08 }, //EQ2 Coefficient A : A15..A8
.e2_coefficient_2 = { .l = 0x11 }, //EQ2 Coefficient B : B7...B0
.e2_coefficient_3 = { .h = 0x36 }, //EQ2 Coefficient B : B15...B8
.e2_coefficient_4 = { .l = 0xE9 }, //EQ2 Coefficient C : C7...C0
.e2_coefficient_5 = { .h = 0xE8 }, //EQ2 Coefficient C : C15..C8
.e3_coefficient_0 = { .l = 0x00 },
.e3_coefficient_1 = { .h = 0x00 },
.e3_coefficient_2 = { .l = 0x00 },
.e3_coefficient_3 = { .h = 0x00 },
.e3_coefficient_4 = { .l = 0x00 },
.e3_coefficient_5 = { .h = 0x00 },
.e3_coefficient_0 = { .l = 0x00 }, //EQ3 Coefficient A : A7...A0, not used currently
.e3_coefficient_1 = { .h = 0x00 }, //EQ3 Coefficient A : A15..A8
.e3_coefficient_2 = { .l = 0x00 }, //EQ3 Coefficient B : B7...B0
.e3_coefficient_3 = { .h = 0x00 }, //EQ3 Coefficient B : B15...B8
.e3_coefficient_4 = { .l = 0x00 }, //EQ3 Coefficient C : C7...C0
.e3_coefficient_5 = { .h = 0x00 }, //EQ3 Coefficient C : C15..C8
.e4_coefficient_0 = { .l = 0x00 },
.e4_coefficient_1 = { .h = 0x00 },
.e4_coefficient_2 = { .l = 0x00 },
.e4_coefficient_3 = { .h = 0x00 },
.e4_coefficient_4 = { .l = 0x00 },
.e4_coefficient_5 = { .h = 0x00 },
.e4_coefficient_0 = { .l = 0x00 }, //EQ4 Coefficient A : A7...A0, not used currently
.e4_coefficient_1 = { .h = 0x00 }, //EQ4 Coefficient A : A15..A8
.e4_coefficient_2 = { .l = 0x00 }, //EQ4 Coefficient B : B7...B0
.e4_coefficient_3 = { .h = 0x00 }, //EQ4 Coefficient B : B15...B8
.e4_coefficient_4 = { .l = 0x00 }, //EQ4 Coefficient C : C7...C0
.e4_coefficient_5 = { .h = 0x00 }, //EQ4 Coefficient C : C15..C8
.e5_coefficient_0 = { .l = 0x00 },
.e5_coefficient_1 = { .h = 0x00 },
.e5_coefficient_2 = { .l = 0x00 },
.e5_coefficient_3 = { .h = 0x00 },
.e5_coefficient_4 = { .l = 0x00 },
.e5_coefficient_5 = { .h = 0x00 },
.e5_coefficient_0 = { .l = 0x00 }, //EQ5 Coefficient A : A7...A0, not used currently
.e5_coefficient_1 = { .h = 0x00 }, //EQ5 Coefficient A : A15..A8
.e5_coefficient_2 = { .l = 0x00 }, //EQ5 Coefficient B : B7...B0
.e5_coefficient_3 = { .h = 0x00 }, //EQ5 Coefficient B : B15...B8
.e5_coefficient_4 = { .l = 0x00 }, //EQ5 Coefficient C : C7...C0
.e5_coefficient_5 = { .h = 0x00 }, //EQ5 Coefficient C : C15..C8
} };
class AK4951 : public audio::Codec {
@@ -841,7 +842,7 @@ public:
void set_headphone_volume(const volume_t volume) override;
void headphone_mute();
void microphone_enable();
void microphone_enable(int8_t alc_mode); // added user GUI parameter , to set up AK4951 ALC mode.
void microphone_disable();
size_t reg_count() const override {
+14
View File
@@ -114,6 +114,20 @@ bool load_sram() {
return ok;
}
void load_sram_no_verify() {
// CoolRunner II family has Hybrid memory CPLD arquitecture (SRAM+NVM)
// It seems that after using TX App somehow , I do not why , the CPLD_SRAM part needs to be re_loaded to solve #637 ghost beat
// load_sram() it is already called at each boot in portapack.cpp ,including verify CPLD part.
// Here we skipped CPLD verify part,just to be quicker (in case any CPLD problem it will be detected in the boot process).
auto jtag_target_hackrf_cpld = jtag_target_hackrf();
hackrf::one::cpld::CPLD hackrf_cpld { jtag_target_hackrf_cpld };
hackrf_cpld.write_sram(hackrf::one::cpld::verify_blocks);
return;
}
bool verify_eeprom() {
auto jtag_target_hackrf_cpld = jtag_target_hackrf();
hackrf::one::cpld::CPLD hackrf_cpld { jtag_target_hackrf_cpld };
+1
View File
@@ -38,6 +38,7 @@ namespace hackrf {
namespace cpld {
bool load_sram();
void load_sram_no_verify(); // added to solve issue #637 , "ghost" signal at RX , after using any TX App
bool verify_eeprom();
void init_from_eeprom();
+48 -1
View File
@@ -245,12 +245,29 @@ constexpr fir_taps_real<32> taps_6k0_decim_2 {
11815, 10413, 7946, 4978, 2134, -83, -1411, -1857,
-1640, -1080, -474, -21, 208, 247, 178, 95,
} },
};
// IFIR prototype filter fs=48000 ; pass=4500 (cutt off -3dBs) , stop=8000 (<-60dBs), decim=4, fout=12000
// For Europe AM commercial broadcasting stations in LF/MF/HF, Emissions Designator 9K00A3E Bandwidth: 9.00 kHz (derivated from taps_6k0_decim_2 )
// Pre-decimate LPF FIR filter design Created with SciPy Python with the "window method", num_taps = 32, cut_off = 5150. sample_rate = 48000 # Hz,
// Created with h = signal.firwin(num_taps, cut_off, nyq=sample_rate/2, window=('chebwin',50)) , achieving good STOP band plot < -60 dB's with some ripple.
// post-scaled h taps to avoid decimals , targeting <= similar int values as previous taps_6k0_dsb_channel peak < 32.767 (2 exp 15) and similar H(f)gain
constexpr fir_taps_real<32> taps_9k0_decim_2 {
.low_frequency_normalized = -4500.0f / 48000.0f, // Negative -cutt off freq -3dB (real achieved data ,in the plot and measurements)
.high_frequency_normalized = 4500.0f / 48000.0f, // Positive +cutt off freq -3dB (idem)
.transition_normalized = 3500.0f / 48000.0f, // 3500 Hz = (8000 Hz - 4500 Hz) (both from plot H(f) curve plot)
.taps = { {
-53, -30, 47, 198, 355, 372, 89, -535,
-1307, -1771, -1353, 370, 3384, 7109, 10535, 12591,
12591, 10535, 7109, 3384, 370, -1353, -1771, -1307,
-535, 89, 372, 355, 198, 47, -30, -53
} },
};
// Channel filter: fs=12000, pass=3000, stop=3300, decim=1, fout=12000
/* NOTE: Slightly less than 1.0 gain (normalized to 65536) due to max(taps) being
* slightly larger than 32767 (33312).
*/
*/
constexpr fir_taps_complex<64> taps_6k0_dsb_channel {
.low_frequency_normalized = -3000.0f / 12000.0f,
.high_frequency_normalized = 3000.0f / 12000.0f,
@@ -275,6 +292,36 @@ constexpr fir_taps_complex<64> taps_6k0_dsb_channel {
} },
};
// Channel filter: fs=12000, pass=4500 (cutt off -3dBs), stop=4940 (<-60dBs), decim=1, fout=12000 (*1) real frec pass / stop , based on plotted H(f) curve)
// For Europe AM commercial broadcasting stations in LF/MF/HF, Emissions Designator 9K00A3E Bandwidth: 9.00 kHz (derivative from taps_6k0_dsb_channel)
// FIR filter design created with SciPy Python using "window method"; selected design parameters: num_taps = 64, cut_off = 4575. sample_rate = 12000 # Hz,
// Created with : h = signal.firwin(num_taps, cut_off, nyq=sample_rate/2, window=('chebwin',50)) , achieving real plot curve (*1) with peak stop band ripple -60dBs.
// post-scaled h taps to avoid decimals , targeting <= similar int values as previous taps_6k0_dsb_channel peak < 32.767 (2 exp 15), (29625) and similar H(f)gain
constexpr fir_taps_complex<64> taps_9k0_dsb_channel {
.low_frequency_normalized = -4500.0f / 12000.0f, // Negative -cutt off freq -3dB (in the H(f) curve plot)
.high_frequency_normalized = 4500.0f / 12000.0f, // Positive +cutt off freq -3dB (in the H(f) curve plot)
.transition_normalized = 440.0f / 12000.0f, // 440Hz = (4940 Hz -4500 Hz) cut-3dB's (both data comes from H(f) curve plot and confirmed by measurements )
.taps = { {
{ 2, 0 }, { -18, 0 }, { 34, 0 }, { -33, 0 },
{ 6, 0 }, { 44, 0 }, { -91, 0 }, { 96, 0 },
{ -35, 0 }, { -80, 0 }, { 193, 0 }, { -223, 0 },
{ 116, 0 }, { 112, 0 }, { -353, 0 }, { 452, 0 },
{ -293, 0 }, { -111, 0 }, { 584, 0 }, { -844, 0 },
{ 653, 0 }, { 22, 0 }, { -921, 0 }, { 1554, 0 },
{ -1422, 0 }, { 301, 0 }, { 1533, 0 }, { -3282, 0 },
{ 3804, 0 }, { -1819, 0 }, { -4605, 0 }, { 29625, 0 },
{ 29625, 0 }, { -4605, 0 }, { -1819, 0 }, { 3804, 0 },
{ -3282, 0 }, { 1533, 0 }, { 301, 0 }, { -1422, 0 },
{ 1554, 0 }, { -921, 0 }, { 22, 0 }, { 653, 0 },
{ -844, 0 }, { 584, 0 }, { -111, 0 }, { -293, 0 },
{ 452, 0 }, { -353, 0 }, { 112, 0 }, { 116, 0 },
{ -223, 0 }, { 193, 0 }, { -80, 0 }, { -35, 0 },
{ 96, 0 }, { -91, 0 }, { 44, 0 }, { 6, 0 },
{ -33, 0 }, { 34, 0 }, { -18, 0 }, { 2, 0 },
} },
};
// USB AM 2K80J3E emission type ///////////////////////////////////////////
// IFIR prototype filter: fs=12000, pass=3000, stop=3300, decim=1, fout=12000
+26 -20
View File
@@ -306,7 +306,7 @@ using ChannelSpectrumFIFO = FIFO<ChannelSpectrum>;
class ChannelSpectrumConfigMessage : public Message {
public:
static constexpr size_t fifo_k = 2;
constexpr ChannelSpectrumConfigMessage(
ChannelSpectrumFIFO* fifo
) : Message { ID::ChannelSpectrumConfig },
@@ -352,7 +352,7 @@ public:
packet { packet }
{
}
pocsag::POCSAGPacket packet;
};
@@ -378,7 +378,7 @@ public:
amp(amp)
{
}
adsb::ADSBFrame frame;
uint32_t amp;
};
@@ -393,7 +393,7 @@ public:
value { value }
{
}
bool is_data;
uint32_t value;
};
@@ -406,7 +406,7 @@ public:
value { value }
{
}
uint32_t value;
};
@@ -584,7 +584,7 @@ public:
used_ += copy_size;
return copy_size;
}
size_t read(void* p, const size_t count) {
const auto copy_size = std::min(used_, count);
memcpy(p, &data_[capacity_ - used_], copy_size);
@@ -595,7 +595,7 @@ public:
bool is_full() const {
return used_ >= capacity_;
}
bool is_empty() const {
return used_ == 0;
}
@@ -607,7 +607,7 @@ public:
size_t size() const {
return used_;
}
size_t capacity() const {
return capacity_;
}
@@ -700,7 +700,7 @@ public:
) : Message { ID::TXProgress }
{
}
uint32_t progress = 0;
bool done = false;
};
@@ -719,7 +719,7 @@ public:
trigger_word(trigger_word)
{
}
const uint32_t baudrate;
const uint32_t word_length;
const uint32_t trigger_value;
@@ -734,7 +734,7 @@ public:
baudrate(baudrate)
{
}
const uint32_t baudrate;
};
@@ -788,7 +788,7 @@ public:
rssi(rssi)
{
}
const bool enabled;
const int32_t rssi;
};
@@ -825,7 +825,7 @@ public:
length(length)
{
}
const uint16_t length = 0;
};
@@ -835,7 +835,7 @@ public:
) : Message { ID::Retune }
{
}
int64_t freq = 0;
uint32_t range = 0;
};
@@ -848,7 +848,7 @@ public:
sample_rate(sample_rate)
{
}
const uint32_t sample_rate = 0;
};
@@ -858,7 +858,7 @@ public:
) : Message { ID::AudioLevelReport }
{
}
uint32_t value = 0;
};
@@ -868,6 +868,7 @@ public:
const uint32_t divider,
const float deviation_hz,
const float audio_gain,
const uint8_t audio_shift_bits_s16,
const uint32_t tone_key_delta,
const float tone_key_mix_weight,
const bool am_enabled,
@@ -878,6 +879,7 @@ public:
divider(divider),
deviation_hz(deviation_hz),
audio_gain(audio_gain),
audio_shift_bits_s16(audio_shift_bits_s16),
tone_key_delta(tone_key_delta),
tone_key_mix_weight(tone_key_mix_weight),
am_enabled(am_enabled),
@@ -890,6 +892,7 @@ public:
const uint32_t divider;
const float deviation_hz;
const float audio_gain;
const uint8_t audio_shift_bits_s16;
const uint32_t tone_key_delta;
const float tone_key_mix_weight;
const bool am_enabled;
@@ -961,12 +964,14 @@ public:
const uint32_t stream_length,
const uint32_t samples_per_bit,
const uint8_t repeat,
const uint32_t pause_symbols
const uint32_t pause_symbols,
const uint8_t de_bruijn_length
) : Message { ID::OOKConfigure },
stream_length(stream_length),
samples_per_bit(samples_per_bit),
repeat(repeat),
pause_symbols(pause_symbols)
pause_symbols(pause_symbols),
de_bruijn_length(de_bruijn_length)
{
}
@@ -974,6 +979,7 @@ public:
const uint32_t samples_per_bit;
const uint8_t repeat;
const uint32_t pause_symbols;
const uint8_t de_bruijn_length;
};
class SSTVConfigureMessage : public Message {
@@ -1014,7 +1020,7 @@ public:
class POCSAGConfigureMessage : public Message {
public:
constexpr POCSAGConfigureMessage()
constexpr POCSAGConfigureMessage()
: Message { ID::POCSAGConfigure }
{
}
@@ -1028,7 +1034,7 @@ public:
packet { packet }
{
}
aprs::APRSPacket packet;
};
+415 -54
View File
@@ -28,7 +28,8 @@
#include "utility.hpp"
#include "memory_map.hpp"
using portapack::memory::map::backup_ram;
#include "crc.hpp"
#include <algorithm>
#include <utility>
@@ -67,8 +68,193 @@ using clkout_freq_range_t = range_t<uint32_t>;
constexpr clkout_freq_range_t clkout_freq_range { 10, 60000 };
constexpr uint32_t clkout_freq_reset_value { 10000 };
enum data_structure_version_enum : uint32_t {
VERSION_CURRENT = 0x10000002,
};
static const uint32_t TOUCH_CALIBRATION_MAGIC = 0x074af82f;
struct ui_config_t {
private:
enum bits_t {
BacklightTimeoutLSB = 0,
BacklightTimeoutEnable = 3,
ClkoutFreqLSB = 4,
ShowGUIReturnIcon = 20,
LoadAppSettings = 21,
SaveAppSettings = 22,
ShowBiggerQRCode = 23,
DisableTouchscreen = 24,
HideClock = 25,
ClockWithDate = 26,
ClkOutEnabled = 27,
ConfigSpeaker = 28,
StealthMode = 29,
ConfigLogin = 30,
ConfigSplash = 31,
};
enum bits_mask_t : uint32_t {
BacklightTimeoutMask = ((1 << 3) - 1) << bits_t::BacklightTimeoutLSB,
ClkoutFreqMask = ((1 << 16) - 1) << bits_t::ClkoutFreqLSB,
};
uint32_t values;
constexpr bool bit_read(const bits_t n) const {
return ((values >> n) & 1) != 0;
}
constexpr void bit_write(const bits_t n, const bool v) {
if(bit_read(n) != v) {
values ^= 1 << n;
}
}
public:
backlight_config_t config_backlight_timer() {
const auto timeout_enum = (backlight_timeout_t)((values & bits_mask_t::BacklightTimeoutMask) >> bits_t::BacklightTimeoutLSB);
const bool timeout_enabled = bit_read(bits_t::BacklightTimeoutEnable);
return backlight_config_t(timeout_enum, timeout_enabled);
}
void set_config_backlight_timer(const backlight_config_t& new_value) {
values = (values & ~bits_mask_t::BacklightTimeoutMask)
| ((new_value.timeout_enum() << bits_t::BacklightTimeoutLSB) & bits_mask_t::BacklightTimeoutMask);
bit_write(bits_t::BacklightTimeoutEnable, new_value.timeout_enabled());
}
constexpr uint32_t clkout_freq() {
uint32_t freq = (values & bits_mask_t::ClkoutFreqMask) >> bits_t::ClkoutFreqLSB;
if(freq < clkout_freq_range.minimum || freq > clkout_freq_range.maximum) {
values = (values & ~bits_mask_t::ClkoutFreqMask) | (clkout_freq_reset_value << bits_t::ClkoutFreqLSB);
return clkout_freq_reset_value;
}
else {
return freq;
}
}
constexpr void set_clkout_freq(uint32_t freq) {
values = (values & ~bits_mask_t::ClkoutFreqMask) | (clkout_freq_range.clip(freq) << bits_t::ClkoutFreqLSB);
}
// ui_config is an uint32_t var storing information bitwise
// bits 0-2 store the backlight timer
// bits 4-19 (16 bits) store the clkout frequency
// bits 21-31 store the different single bit configs depicted below
// bit 20 store the display state of the gui return icon, hidden (0) or shown (1)
constexpr bool show_gui_return_icon() const { // add return icon in touchscreen menue
return bit_read(bits_t::ShowGUIReturnIcon);
}
constexpr void set_gui_return_icon(bool v) {
bit_write(bits_t::ShowGUIReturnIcon, v);
}
constexpr bool load_app_settings() const { // load (last saved) app settings on startup of app
return bit_read(bits_t::LoadAppSettings);
}
constexpr void set_load_app_settings(bool v) {
bit_write(bits_t::LoadAppSettings, v);
}
constexpr bool save_app_settings() const { // save app settings when closing app
return bit_read(bits_t::SaveAppSettings);
}
constexpr void set_save_app_settings(bool v) {
bit_write(bits_t::SaveAppSettings, v);
}
constexpr bool show_bigger_qr_code() const { // show bigger QR code
return bit_read(bits_t::ShowBiggerQRCode);
}
constexpr void set_show_bigger_qr_code(bool v) {
bit_write(bits_t::ShowBiggerQRCode, v);
}
constexpr bool disable_touchscreen() const { // Option to disable touch screen
return bit_read(bits_t::DisableTouchscreen);
}
constexpr void set_disable_touchscreen(bool v) {
bit_write(bits_t::DisableTouchscreen, v);
}
constexpr bool hide_clock() const { // clock hidden from main menu
return bit_read(bits_t::HideClock);
}
constexpr void set_clock_hidden(bool v) {
bit_write(bits_t::HideClock, v);
}
constexpr bool clock_with_date() const { // show clock with date, if not hidden
return bit_read(bits_t::ClockWithDate);
}
constexpr void set_clock_with_date(bool v) {
bit_write(bits_t::ClockWithDate, v);
}
constexpr bool clkout_enabled() const {
return bit_read(bits_t::ClkOutEnabled);
}
constexpr void set_clkout_enabled(bool v) {
bit_write(bits_t::ClkOutEnabled, v);
}
constexpr bool config_speaker() const {
return bit_read(bits_t::ConfigSpeaker);
}
constexpr void set_config_speaker(bool v) {
bit_write(bits_t::ConfigSpeaker, v);
}
constexpr bool stealth_mode() const {
return bit_read(bits_t::StealthMode);
}
constexpr void set_stealth_mode(bool v) {
bit_write(bits_t::StealthMode, v);
}
constexpr bool config_login() const {
return bit_read(bits_t::ConfigLogin);
}
constexpr void set_config_login(bool v) {
bit_write(bits_t::ConfigLogin, v);
}
constexpr bool config_splash() const {
return bit_read(bits_t::ConfigSplash);
}
constexpr void set_config_splash(bool v) {
bit_write(bits_t::ConfigSplash, v);
}
constexpr ui_config_t() :
values(
(1 << ConfigSplash)
| (1 << ConfigSpeaker)
| (clkout_freq_reset_value << ClkoutFreqLSB)
| (7 << BacklightTimeoutLSB)
)
{
}
};
/* struct must pack the same way on M4 and M0 cores. */
struct data_t {
data_structure_version_enum structure_version;
int64_t tuned_frequency;
int32_t correction_ppb;
uint32_t touch_calibration_magic;
@@ -89,7 +275,7 @@ struct data_t {
uint32_t playdead_sequence;
// UI
uint32_t ui_config;
ui_config_t ui_config;
uint32_t pocsag_last_address;
uint32_t pocsag_ignore_address;
@@ -98,11 +284,146 @@ struct data_t {
// Hardware
uint32_t hardware_config;
// Recon App
uint64_t recon_config;
constexpr data_t() :
structure_version(data_structure_version_enum::VERSION_CURRENT),
tuned_frequency(tuned_frequency_reset_value),
correction_ppb(ppb_reset_value),
touch_calibration_magic(TOUCH_CALIBRATION_MAGIC),
touch_calibration(touch::Calibration()),
modem_def_index(0), // TODO: Unused?
serial_format(),
modem_bw(15000), // TODO: Unused?
afsk_mark_freq(afsk_mark_reset_value),
afsk_space_freq(afsk_space_reset_value),
modem_baudrate(modem_baudrate_reset_value),
modem_repeat(modem_repeat_reset_value),
playdead_magic(), // TODO: Unused?
playing_dead(), // TODO: Unused?
playdead_sequence(), // TODO: Unused?
ui_config(),
pocsag_last_address(0), // TODO: A better default?
pocsag_ignore_address(0), // TODO: A better default?
tone_mix(tone_mix_reset_value),
hardware_config(0),
recon_config(0)
{
}
};
static_assert(sizeof(data_t) <= backup_ram.size(), "Persistent memory structure too large for VBAT-maintained region");
struct backup_ram_t {
private:
uint32_t regfile[63];
uint32_t check_value;
static data_t* const data = reinterpret_cast<data_t*>(backup_ram.base());
static void copy(const backup_ram_t& src, backup_ram_t& dst) {
for(size_t i=0; i<63; i++) {
dst.regfile[i] = src.regfile[i];
}
dst.check_value = src.check_value;
}
static void copy_from_data_t(const data_t& src, backup_ram_t& dst) {
const uint32_t* const src_words = (uint32_t*)&src;
const size_t word_count = (sizeof(data_t) + 3) / 4;
for(size_t i=0; i<63; i++) {
if(i<word_count) {
dst.regfile[i] = src_words[i];
} else {
dst.regfile[i] = 0;
}
}
}
uint32_t compute_check_value() {
CRC<32> crc { 0x04c11db7, 0xffffffff, 0xffffffff };
for(size_t i=0; i<63; i++) {
const auto word = regfile[i];
crc.process_byte((word >> 0) & 0xff);
crc.process_byte((word >> 8) & 0xff);
crc.process_byte((word >> 16) & 0xff);
crc.process_byte((word >> 24) & 0xff);
}
return crc.checksum();
}
public:
/* default constructor */
backup_ram_t() :
check_value(0)
{
const data_t defaults = data_t();
copy_from_data_t(defaults, *this);
}
/* copy-assignment operator */
backup_ram_t& operator=(const backup_ram_t& src) {
copy(src, *this);
return *this;
}
/* Calculate a check value from `this`, and check against
* the stored value.
*/
bool is_valid() {
return compute_check_value() == check_value;
}
/* Assuming `this` contains valid data, update the checksum
* and copy to the destination.
*/
void persist_to(backup_ram_t& dst) {
check_value = compute_check_value();
copy(*this, dst);
}
};
static_assert(sizeof(backup_ram_t) == memory::map::backup_ram.size());
static_assert(sizeof(data_t) <= sizeof(backup_ram_t) - sizeof(uint32_t));
static backup_ram_t* const backup_ram = reinterpret_cast<backup_ram_t*>(memory::map::backup_ram.base());
static backup_ram_t cached_backup_ram;
static data_t* const data = reinterpret_cast<data_t*>(&cached_backup_ram);
namespace cache {
void defaults() {
cached_backup_ram = backup_ram_t();
}
void init() {
if(backup_ram->is_valid()) {
// Copy valid persistent data into cache.
cached_backup_ram = *backup_ram;
// Check that structure data we copied into cache is the expected
// version. If not, initialize cache to defaults.
if(data->structure_version != data_structure_version_enum::VERSION_CURRENT) {
// TODO: Can provide version-to-version upgrade functions here,
// if we want to be fancy.
defaults();
}
} else {
// Copy defaults into cache.
defaults();
}
}
void persist() {
cached_backup_ram.persist_to(*backup_ram);
}
} /* namespace cache */
rf::Frequency tuned_frequency() {
rf::tuning_range.reset_if_outside(data->tuned_frequency, tuned_frequency_reset_value);
@@ -124,16 +445,14 @@ void set_correction_ppb(const ppb_t new_value) {
portapack::clock_manager.set_reference_ppb(clipped_value);
}
static constexpr uint32_t touch_calibration_magic = 0x074af82f;
void set_touch_calibration(const touch::Calibration& new_value) {
data->touch_calibration = new_value;
data->touch_calibration_magic = touch_calibration_magic;
data->touch_calibration_magic = TOUCH_CALIBRATION_MAGIC;
}
const touch::Calibration& touch_calibration() {
if( data->touch_calibration_magic != touch_calibration_magic ) {
set_touch_calibration(touch::default_calibration());
if( data->touch_calibration_magic != TOUCH_CALIBRATION_MAGIC ) {
set_touch_calibration(touch::Calibration());
}
return data->touch_calibration;
}
@@ -200,122 +519,116 @@ void set_serial_format(const serial_format_t new_value) {
data->serial_format = new_value;
}
// ui_config is an uint32_t var storing information bitwise
// bits 0-2 store the backlight timer
// bits 4-19 (16 bits) store the clkout frequency
// bits 21-31 store the different single bit configs depicted below
// bit 20 store the display state of the gui return icon, hidden (0) or shown (1)
bool show_gui_return_icon(){ // add return icon in touchscreen menue
return data->ui_config & (1 << 20);
bool show_gui_return_icon() { // add return icon in touchscreen menue
return data->ui_config.show_gui_return_icon();
}
bool load_app_settings() { // load (last saved) app settings on startup of app
return data->ui_config & (1 << 21);
return data->ui_config.load_app_settings();
}
bool save_app_settings() { // save app settings when closing app
return data->ui_config & (1 << 22);
return data->ui_config.save_app_settings();
}
bool show_bigger_qr_code() { // show bigger QR code
return data->ui_config & (1 << 23);
return data->ui_config.show_bigger_qr_code();
}
bool disable_touchscreen() { // Option to disable touch screen
return data->ui_config & (1 << 24);
return data->ui_config.disable_touchscreen();
}
bool hide_clock() { // clock hidden from main menu
return data->ui_config & (1 << 25);
return data->ui_config.hide_clock();
}
bool clock_with_date() { // show clock with date, if not hidden
return data->ui_config & (1 << 26);
return data->ui_config.clock_with_date();
}
bool clkout_enabled() {
return data->ui_config & (1 << 27);
return data->ui_config.clkout_enabled();
}
bool config_speaker() {
return data->ui_config & (1 << 28);
return data->ui_config.config_speaker();
}
bool stealth_mode() {
return data->ui_config & (1 << 29);
return data->ui_config.stealth_mode();
}
bool config_login() {
return data->ui_config & (1 << 30);
return data->ui_config.config_login();
}
bool config_splash() {
return data->ui_config & (1 << 31);
return data->ui_config.config_splash();
}
uint8_t config_cpld() {
return data->hardware_config;
}
uint32_t config_backlight_timer() {
const uint32_t timer_seconds[8] = { 0, 5, 15, 30, 60, 180, 300, 600 };
return timer_seconds[data->ui_config & 7]; //first three bits, 8 possible values
backlight_config_t config_backlight_timer() {
return data->ui_config.config_backlight_timer();
}
void set_gui_return_icon(bool v) {
data->ui_config = (data->ui_config & ~(1 << 20)) | (v << 20);
data->ui_config.set_gui_return_icon(v);
}
void set_load_app_settings(bool v) {
data->ui_config = (data->ui_config & ~(1 << 21)) | (v << 21);
data->ui_config.set_load_app_settings(v);
}
void set_save_app_settings(bool v) {
data->ui_config = (data->ui_config & ~(1 << 22)) | (v << 22);
data->ui_config.set_save_app_settings(v);
}
void set_show_bigger_qr_code(bool v) {
data->ui_config = (data->ui_config & ~(1 << 23)) | (v << 23);
data->ui_config.set_show_bigger_qr_code(v);
}
void set_disable_touchscreen(bool v) {
data->ui_config = (data->ui_config & ~(1 << 24)) | (v << 24);
data->ui_config.set_disable_touchscreen(v);
}
void set_clock_hidden(bool v) {
data->ui_config = (data->ui_config & ~(1 << 25)) | (v << 25);
data->ui_config.set_clock_hidden(v);
}
void set_clock_with_date(bool v) {
data->ui_config = (data->ui_config & ~(1 << 26)) | (v << 26);
data->ui_config.set_clock_with_date(v);
}
void set_clkout_enabled(bool v) {
data->ui_config = (data->ui_config & ~(1 << 27)) | (v << 27);
data->ui_config.set_clkout_enabled(v);
}
void set_config_speaker(bool v) {
data->ui_config = (data->ui_config & ~(1 << 28)) | (v << 28);
data->ui_config.set_config_speaker(v);
}
void set_stealth_mode(bool v) {
data->ui_config = (data->ui_config & ~(1 << 29)) | (v << 29);
data->ui_config.set_stealth_mode(v);
}
void set_config_login(bool v) {
data->ui_config = (data->ui_config & ~(1 << 30)) | (v << 30);
data->ui_config.set_config_login(v);
}
void set_config_splash(bool v) {
data->ui_config = (data->ui_config & ~(1 << 31)) | (v << 31);
data->ui_config.set_config_splash(v);
}
void set_config_cpld(uint8_t i) {
data->hardware_config = i;
}
void set_config_backlight_timer(uint32_t i) {
data->ui_config = (data->ui_config & ~7) | (i & 7);
void set_config_backlight_timer(const backlight_config_t& new_value) {
data->ui_config.set_config_backlight_timer(new_value);
}
/*void set_config_textentry(uint8_t new_value) {
@@ -347,20 +660,68 @@ void set_pocsag_ignore_address(uint32_t address) {
}
uint32_t clkout_freq() {
uint16_t freq = (data->ui_config & 0x000FFFF0) >> 4;
if(freq < clkout_freq_range.minimum || freq > clkout_freq_range.maximum) {
data->ui_config = (data->ui_config & ~0x000FFFF0) | clkout_freq_reset_value << 4;
return clkout_freq_reset_value;
}
else {
return freq;
}
return data->ui_config.clkout_freq();
}
void set_clkout_freq(uint32_t freq) {
data->ui_config = (data->ui_config & ~0x000FFFF0) | (clkout_freq_range.clip(freq) << 4);
data->ui_config.set_clkout_freq(freq);
}
bool recon_autosave_freqs() {
return (data->recon_config & 0x80000000UL) ? true : false;
}
bool recon_autostart_recon() {
return (data->recon_config & 0x40000000UL) ? true : false;
}
bool recon_continuous() {
return (data->recon_config & 0x20000000UL) ? true : false;
}
bool recon_clear_output() {
return (data->recon_config & 0x10000000UL) ? true : false;
}
bool recon_load_freqs() {
return (data->recon_config & 0x08000000UL) ? true : false;
}
bool recon_load_ranges() {
return (data->recon_config & 0x04000000UL) ? true : false;
}
bool recon_update_ranges_when_recon() {
return (data->recon_config & 0x02000000UL) ? true : false;
}
bool recon_load_hamradios() {
return (data->recon_config & 0x01000000UL) ? true : false;
}
bool recon_match_mode() {
return (data->recon_config & 0x00800000UL) ? true : false;
}
void set_recon_autosave_freqs(const bool v ){
data->recon_config = (data->recon_config & ~0x80000000UL) | (v << 31);
}
void set_recon_autostart_recon(const bool v ){
data->recon_config = (data->recon_config & ~0x40000000UL) | (v << 30);
}
void set_recon_continuous(const bool v ){
data->recon_config = (data->recon_config & ~0x20000000UL) | (v << 29);
}
void set_recon_clear_output(const bool v ){
data->recon_config = (data->recon_config & ~0x10000000UL) | (v << 28);
}
void set_recon_load_freqs(const bool v ){
data->recon_config = (data->recon_config & ~0x08000000UL) | (v << 27);
}
void set_recon_load_ranges(const bool v ){
data->recon_config = (data->recon_config & ~0x04000000UL) | (v << 26);
}
void set_recon_update_ranges_when_recon(const bool v ){
data->recon_config = (data->recon_config & ~0x02000000UL) | (v << 25);
}
void set_recon_load_hamradios(const bool v ){
data->recon_config = (data->recon_config & ~0x01000000UL) | (v << 24);
}
void set_recon_match_mode(const bool v ) {
data->recon_config = (data->recon_config & ~0x00800000UL) | (v << 23);
}
} /* namespace persistent_memory */
} /* namespace portapack */
@@ -25,6 +25,8 @@
#include <cstdint>
#include "optional.hpp"
#include "rf_path.hpp"
#include "touch.hpp"
#include "modems.hpp"
@@ -36,6 +38,77 @@ using namespace serializer;
namespace portapack {
namespace persistent_memory {
enum backlight_timeout_t {
Timeout5Sec = 0,
Timeout15Sec = 1,
Timeout30Sec = 2,
Timeout60Sec = 3,
Timeout180Sec = 4,
Timeout300Sec = 5,
Timeout600Sec = 6,
Timeout3600Sec = 7,
};
struct backlight_config_t {
public:
backlight_config_t() :
_timeout_enum(backlight_timeout_t::Timeout600Sec),
_timeout_enabled(false)
{
}
backlight_config_t(
backlight_timeout_t timeout_enum,
bool timeout_enabled
) :
_timeout_enum(timeout_enum),
_timeout_enabled(timeout_enabled)
{
}
bool timeout_enabled() const {
return _timeout_enabled;
}
backlight_timeout_t timeout_enum() const {
return _timeout_enum;
}
uint32_t timeout_seconds() const {
switch(timeout_enum()) {
case Timeout5Sec: return 5;
case Timeout15Sec: return 15;
case Timeout30Sec: return 30;
case Timeout60Sec: return 60;
case Timeout180Sec: return 180;
case Timeout300Sec: return 300;
default:
case Timeout600Sec: return 600;
case Timeout3600Sec: return 3600;
}
}
private:
backlight_timeout_t _timeout_enum;
bool _timeout_enabled;
};
namespace cache {
/* Set values in cache to sensible defaults. */
void defaults();
/* Load cached settings from values in persistent RAM, replacing with defaults
* if persistent RAM contents appear to be invalid. */
void init();
/* Calculate a check value for cached settings, and copy the check value and
* settings into persistent RAM. Intended to be called periodically to update
* persistent settings with current settings. */
void persist();
} /* namespace cache */
using ppb_t = int32_t;
rf::Frequency tuned_frequency();
@@ -86,7 +159,7 @@ bool hide_clock();
bool clock_with_date();
bool config_login();
bool config_speaker();
uint32_t config_backlight_timer();
backlight_config_t config_backlight_timer();
bool disable_touchscreen();
void set_gui_return_icon(bool v);
@@ -98,7 +171,7 @@ void set_clock_hidden(bool v);
void set_clock_with_date(bool v);
void set_config_login(bool v);
void set_config_speaker(bool v);
void set_config_backlight_timer(uint32_t i);
void set_config_backlight_timer(const backlight_config_t& new_value);
void set_disable_touchscreen(bool v);
//uint8_t ui_config_textentry();
@@ -115,6 +188,26 @@ void set_clkout_enabled(bool v);
uint32_t clkout_freq();
void set_clkout_freq(uint32_t freq);
/* Recon app */
bool recon_autosave_freqs();
bool recon_autostart_recon();
bool recon_continuous();
bool recon_clear_output();
bool recon_load_freqs();
bool recon_load_ranges();
bool recon_update_ranges_when_recon();
bool recon_load_hamradios();
bool recon_match_mode();
void set_recon_autosave_freqs(const bool v);
void set_recon_autostart_recon(const bool v);
void set_recon_continuous(const bool v);
void set_recon_clear_output(const bool v);
void set_recon_load_freqs(const bool v);
void set_recon_load_ranges(const bool v);
void set_recon_update_ranges_when_recon(const bool v);
void set_recon_load_hamradios(const bool v );
void set_recon_match_mode( const bool v );
} /* namespace persistent_memory */
} /* namespace portapack */
+10 -14
View File
@@ -35,11 +35,9 @@ w = numpy.arange(length, dtype=numpy.float64) * (2 * numpy.pi / length)
v = numpy.sin(w)
print(v)
*/
constexpr size_t sine_table_f32_period_log2 = 8;
constexpr size_t sine_table_f32_period = 1 << sine_table_f32_period_log2;
constexpr uint32_t sine_table_f32_index_mask = sine_table_f32_period - 1;
constexpr uint16_t sine_table_f32_period = 256;
static constexpr std::array<float, sine_table_f32_period + 1> sine_table_f32 { {
static constexpr std::array<float, sine_table_f32_period + 2> sine_table_f32{
0.00000000e+00, 2.45412285e-02, 4.90676743e-02,
7.35645636e-02, 9.80171403e-02, 1.22410675e-01,
1.46730474e-01, 1.70961889e-01, 1.95090322e-01,
@@ -125,24 +123,22 @@ static constexpr std::array<float, sine_table_f32_period + 1> sine_table_f32 { {
-2.42980180e-01, -2.19101240e-01, -1.95090322e-01,
-1.70961889e-01, -1.46730474e-01, -1.22410675e-01,
-9.80171403e-02, -7.35645636e-02, -4.90676743e-02,
-2.45412285e-02, 0.00000000e+00,
} };
-2.45412285e-02, 0.00000000e+00, 0.00000000e+00
};
inline float sin_f32(const float w) {
constexpr float normalize = 1.0 / (2 * pi);
const float x = w * normalize;
const int32_t x_int = std::floor(x);
const float x_frac = x - x_int;
const float x = w / (2 * pi); // normalization
const float x_frac = x - std::floor(x); // [0, 1]
const float n = x_frac * sine_table_f32_period;
const int32_t n_int = static_cast<uint32_t>(n) & sine_table_f32_index_mask;
const uint16_t n_int = static_cast<uint16_t>(n);
const float n_frac = n - n_int;
const float p0 = sine_table_f32[n_int + 0];
const float p0 = sine_table_f32[n_int];
const float p1 = sine_table_f32[n_int + 1];
const float diff = p1 - p0;
const float result = p0 + n_frac * diff;
const float result = p0 + n_frac * diff; // linear interpolation
return result;
}
+153
View File
@@ -984,6 +984,159 @@ bool Button::on_touch(const TouchEvent event) {
#endif
}
/* ButtonWithEncoder ****************************************************************/
ButtonWithEncoder::ButtonWithEncoder(
Rect parent_rect,
std::string text,
bool instant_exec
) : Widget { parent_rect },
text_ { text },
instant_exec_ { instant_exec }
{
set_focusable(true);
}
void ButtonWithEncoder::set_text(const std::string value) {
text_ = value;
set_dirty();
}
int32_t ButtonWithEncoder::get_encoder_delta() {
return encoder_delta ;
}
void ButtonWithEncoder::set_encoder_delta( const int32_t delta )
{
encoder_delta = delta ;
}
std::string ButtonWithEncoder::text() const {
return text_;
}
void ButtonWithEncoder::paint(Painter& painter) {
Color bg, fg;
const auto r = screen_rect();
if (has_focus() || highlighted()) {
bg = style().foreground;
fg = Color::black();
} else {
bg = Color::grey();
fg = style().foreground;
}
const Style paint_style = { style().font, bg, fg };
painter.draw_rectangle({r.location(), {r.size().width(), 1}}, Color::light_grey());
painter.draw_rectangle({r.location().x(), r.location().y() + r.size().height() - 1, r.size().width(), 1}, Color::dark_grey());
painter.draw_rectangle({r.location().x() + r.size().width() - 1, r.location().y(), 1, r.size().height()}, Color::dark_grey());
painter.fill_rectangle(
{ r.location().x(), r.location().y() + 1, r.size().width() - 1, r.size().height() - 2 },
paint_style.background
);
const auto label_r = paint_style.font.size_of(text_);
painter.draw_string(
{ r.location().x() + (r.size().width() - label_r.width()) / 2, r.location().y() + (r.size().height() - label_r.height()) / 2 },
paint_style,
text_
);
}
void ButtonWithEncoder::on_focus() {
if( on_highlight )
on_highlight(*this);
}
bool ButtonWithEncoder::on_key(const KeyEvent key) {
if( key == KeyEvent::Select ) {
if( on_select ) {
on_select(*this);
return true;
}
} else {
if( on_dir ) {
return on_dir(*this, key);
}
}
return false;
}
bool ButtonWithEncoder::on_touch(const TouchEvent event) {
switch(event.type) {
case TouchEvent::Type::Start:
set_highlighted(true);
set_dirty();
if( on_touch_press) {
on_touch_press(*this);
}
if( on_select && instant_exec_ ) {
on_select(*this);
}
return true;
case TouchEvent::Type::End:
set_highlighted(false);
set_dirty();
if( on_touch_release) {
on_touch_release(*this);
}
if( on_select && !instant_exec_ ) {
on_select(*this);
}
return true;
default:
return false;
}
#if 0
switch(event.type) {
case TouchEvent::Type::Start:
flags.highlighted = true;
set_dirty();
return true;
case TouchEvent::Type::Move:
{
const bool new_highlighted = screen_rect().contains(event.point);
if( flags.highlighted != new_highlighted ) {
flags.highlighted = new_highlighted;
set_dirty();
}
}
return true;
case TouchEvent::Type::End:
if( flags.highlighted ) {
flags.highlighted = false;
set_dirty();
if( on_select ) {
on_select(*this);
}
}
return true;
default:
return false;
}
#endif
}
bool ButtonWithEncoder::on_encoder(const EncoderEvent delta) {
if( delta != 0 )
{
encoder_delta += delta ;
delta_change = true ;
on_change();
}
else
delta_change = 0 ;
return true ;
}
/* NewButton ****************************************************************/
NewButton::NewButton(
+45
View File
@@ -414,6 +414,51 @@ private:
bool instant_exec_ { false };
};
class ButtonWithEncoder : public Widget {
public:
std::function<void(ButtonWithEncoder&)> on_select { };
std::function<void(ButtonWithEncoder&)> on_touch_release { }; // Executed when releasing touch, after on_select.
std::function<void(ButtonWithEncoder&)> on_touch_press { }; // Executed when touching, before on_select.
std::function<bool(ButtonWithEncoder&, KeyEvent)> on_dir { };
std::function<void(ButtonWithEncoder&)> on_highlight { };
ButtonWithEncoder(Rect parent_rect, std::string text, bool instant_exec); // instant_exec: Execute on_select when you touching instead of releasing
ButtonWithEncoder(
Rect parent_rect,
std::string text
) : ButtonWithEncoder { parent_rect, text, false }
{
}
ButtonWithEncoder(
) : ButtonWithEncoder { { }, { } }
{
}
std::function<void()> on_change { };
void set_text(const std::string value);
int32_t get_encoder_delta();
void set_encoder_delta( const int32_t delta );
std::string text() const;
void paint(Painter& painter) override;
void on_focus() override;
bool on_key(const KeyEvent key) override;
bool on_touch(const TouchEvent event) override;
bool on_encoder(const EncoderEvent delta) override;
private:
std::string text_;
int32_t encoder_delta = 0 ;
bool delta_change = 0 ;
bool instant_exec_ { false };
};
class NewButton : public Widget {
public:
std::function<void(void)> on_select { };
+5 -5
View File
@@ -95,27 +95,27 @@ struct range_t {
const T minimum;
const T maximum;
const T& clip(const T& value) const {
constexpr const T& clip(const T& value) const {
return std::max(std::min(value, maximum), minimum);
}
void reset_if_outside(T& value, const T& reset_value) const {
constexpr void reset_if_outside(T& value, const T& reset_value) const {
if( (value < minimum ) ||
(value > maximum ) ) {
value = reset_value;
}
}
bool below_range(const T& value) const {
constexpr bool below_range(const T& value) const {
return value < minimum;
}
bool contains(const T& value) const {
constexpr bool contains(const T& value) const {
// TODO: Subtle gotcha here! Range test doesn't include maximum!
return (value >= minimum) && (value < maximum);
}
bool out_of_range(const T& value) const {
constexpr bool out_of_range(const T& value) const {
// TODO: Subtle gotcha here! Range test in contains() doesn't include maximum!
return !contains(value);
}
+1 -1
View File
@@ -84,7 +84,7 @@ void WM8731::init() {
});
write(AnalogAudioPathControl {
.micboost = 1, // Enable 20dB boost
.micboost = 0, // Disable 20dB boost by default
.mutemic = 0, // Disable mute (unmute)
.insel = 1, // Microphone input to ADC
.bypass = 0,
+17 -7
View File
@@ -345,18 +345,28 @@ public:
void speaker_disable() {};
void microphone_enable() override {
// TODO: Implement
}
void microphone_enable(int8_t wm8731_boost_GUI) override {
microphone_mute(true); // c/m to reduce "plop noise" when changing wm8731_boost_GUI.
// chThdSleepMilliseconds(20); // does not help to reduce the "plop noise"
microphone_boost((wm8731_boost_GUI<2) ? 1 : 0 ); // 1 = Enable Boost (+20 dBs) . 0 = Disable Boost (0dBs).
chThdSleepMilliseconds(120); // >50 msegs, very effective , >100 msegs minor improvement ,120 msegs trade off speed .
microphone_mute(false);
// (void)alc_mode; In prev. fw version , when we did not use at all param., to avoid "unused warning" when compiling.)
}
void microphone_disable() override {
// TODO: Implement
}
// void microphone_mute(const bool mute) {
// map.r.analog_audio_path_control.mutemic = (mute ? 0 : 1);
// write(Register::AnalogAudioPathControl);
// }
void microphone_boost(const bool boost) {
map.r.analog_audio_path_control.micboost = (boost ? 1 : 0);
write(Register::AnalogAudioPathControl);
}
void microphone_mute(const bool mute) {
map.r.analog_audio_path_control.mutemic = (mute ? 1 : 0); //1 = Enable Mute , 0 = Disable Mute
write(Register::AnalogAudioPathControl);
}
// void set_adc_source(const ADCSource adc_source) {
// map.r.analog_audio_path_control.insel = toUType(adc_source);
+9 -9
View File
@@ -1,4 +1,4 @@
#!/usr/bin/env python
#!/usr/bin/env python3
#
# Copyright (C) 2014 Jared Boone, ShareBrained Technology, Inc.
@@ -80,7 +80,7 @@ def print_block(block):
for n in range(0, len(block), 8):
chunk = block[n:n+8]
line = ['0x%04x,' % v for v in chunk]
print('\t%s' % ' '.join(line))
print(('\t%s' % ' '.join(line)))
def crc32(blocks):
import zlib
@@ -92,7 +92,7 @@ def crc32(blocks):
crc_bytes.append((word >> 8) & 0xff)
return zlib.crc32(bytearray(crc_bytes)) & 0xffffffff
print("""#include "portapack_cpld_data.hpp"
print(("""#include "portapack_cpld_data.hpp"
#include <cstdint>
#include <array>
@@ -100,23 +100,23 @@ print("""#include "portapack_cpld_data.hpp"
namespace portapack {
namespace cpld {
namespace %s {
""" % revision_name)
""" % revision_name))
print('const std::array<uint16_t, %d> block_0 { {' % len(block_0))
print(('const std::array<uint16_t, %d> block_0 { {' % len(block_0)))
print_block(block_0)
print("""} };
""")
print('const std::array<uint16_t, %d> block_1 { {' % len(block_1))
print(('const std::array<uint16_t, %d> block_1 { {' % len(block_1)))
print_block(block_1)
print("""} };
print(("""} };
} /* namespace %s */
} /* namespace cpld */
} /* namespace portapack */
""" % revision_name)
""" % revision_name))
if calculate_crc:
# Apply post-programming modification to make post-programming CRC correct:
@@ -124,4 +124,4 @@ if calculate_crc:
programmed_block_0[0] &= 0xfbff
crc = crc32((programmed_block_0, block_1))
print('%08x' % crc)
print(('%08x' % crc))
+3 -1
View File
@@ -1,3 +1,5 @@
#!/usr/bin/env python3
import math
m = 64 - 1
@@ -6,7 +8,7 @@ ft = 300.0 / 24000.0
taps = []
window = []
print("Normalized ft = " + str(ft))
print(("Normalized ft = " + str(ft)))
for n in range(0, 64):
taps.append(math.sin(2 * math.pi * ft * (n - (m / 2.0))) / (math.pi * (n - (m / 2.0))))
+6 -5
View File
@@ -29,10 +29,10 @@ outfile = open('../../sdcard/ADSB/world_map.bin', 'wb')
Image.MAX_IMAGE_PIXELS = None
im = Image.open("../../sdcard/ADSB/world_map.jpg")
pix = im.load()
outfile.write(struct.pack('H', im.size[0]))
outfile.write(struct.pack('H', im.size[1]))
# Write as unsigned short (2 bytes) as little endian
outfile.write(struct.pack('<H', im.size[0]))
outfile.write(struct.pack('<H', im.size[1]))
print("image \t size[0]=" + str(im.size[0]) + "\tsize[1]=" + str(im.size[1]) + " pixels");
print("Generating: \t" + outfile.name + "\n from\t\t" + im.filename + "\n please wait...");
for y in range (0, im.size[1]):
@@ -47,8 +47,9 @@ for y in range (0, im.size[1]):
# pixel_lcd = (pix[x, y][0] >> 5) << 5
# pixel_lcd |= (pix[x, y][1] >> 5) << 2
# pixel_lcd |= (pix[x, y][2] >> 6)
line += struct.pack('H', pixel_lcd)
line += struct.pack('<H', pixel_lcd)
outfile.write(line)
print(str(y) + '/' + str(im.size[1]) + '\r', end="")
outfile.close();
print("Ready.");
+1 -1
View File
@@ -1,4 +1,4 @@
#!/usr/bin/env python
#!/usr/bin/env python3
# Copyright (C) 2016 Furrtek
#
+3 -3
View File
@@ -1,4 +1,4 @@
#!/usr/bin/env python
#!/usr/bin/env python3
# Copyright (C) 2016 Furrtek
#
@@ -42,7 +42,7 @@ def convert_png(file):
rgb_im = im.convert('RGBA')
if rgb_im.size[0] % 8 or rgb_im.size[1] % 8:
print(file + ": Size isn\'t a multiple of 8")
print((file + ": Size isn\'t a multiple of 8"))
sys.exit(-1)
name = path.basename(file).split(".")[0].lower();
@@ -112,4 +112,4 @@ f.write("\n")
f.write("} /* namespace ui */\n\n")
f.write("#endif/*__BITMAP_HPP__*/\n")
print("Converted " + str(count) + " files")
print(("Converted " + str(count) + " files"))
+2 -2
View File
@@ -1,4 +1,4 @@
#!/usr/bin/env python
#!/usr/bin/env python3
# Copyright (C) 2016 Furrtek
#
@@ -40,4 +40,4 @@ for c in range (0, 0x200): # DCS code is 9 bits
p10 = cb[3] ^ cb[5] ^ cb[6] ^ cb[8] ^ 1;
p11 = cb[0] ^ cb[1] ^ cb[2] ^ cb[3] ^ cb[6] ^ 1;
print ' 0b{0:011b}'.format((p11<<10) | (p10<<9) | (p9<<8) |(p8<<7) | (p7<<6) | (p6<<5) | (p5<<4) | (p4<<3) | (p3<<2) | (p2<<1) | (p1)) + ', // ' + str(c);
print(' 0b{0:011b}'.format((p11<<10) | (p10<<9) | (p9<<8) |(p8<<7) | (p7<<6) | (p6<<5) | (p5<<4) | (p4<<3) | (p3<<2) | (p2<<1) | (p1)) + ', // ' + str(c));
+1 -1
View File
@@ -1,4 +1,4 @@
#!/usr/bin/env python
#!/usr/bin/env python3
#
# Copyright (C) 2015 Jared Boone, ShareBrained Technology, Inc.
+1 -1
View File
@@ -1,4 +1,4 @@
#!/usr/bin/env python
#!/usr/bin/env python3
#
# Copyright (C) 2015 Jared Boone, ShareBrained Technology, Inc.
Binary file not shown.
Binary file not shown.
+1 -1
Submodule hackrf updated: e6eb4ba29b...eff4a20022
+1
View File
@@ -0,0 +1 @@
a=76000000,b=90000000,m=WFM,bw=16k,s=50KHz,d=WFM Japan
+1
View File
@@ -0,0 +1 @@
a=65800000,b=74000000,m=WFM,bw=16k,s=30KHz,d=WFM OIRT
+1
View File
@@ -0,0 +1 @@
a=87500000,b=108000000,m=WFM,bw=16k,s=50KHz,d=WFM Standard
+22
View File
@@ -0,0 +1,22 @@
a=150000,b=285000,m=AM,bw=DSB,s=5KHz,d=Longwave broadcast band|BCB (EU)
a=525000,b=1605000,m=AM,bw=DSB,s=5KHz,d=AM broadcast band|BCB (EU & J)
a=530000,b=1710000,m=AM,bw=DSB,s=5KHz,d=AM broadcast band|BCB (US)
a=1800000,b=29700000,m=WFM,bw=16k,d=Amateur_radio|Amateur
a=26900000,b=27400000,m=WFM,bw=16k,d=Citizens_band_radio|Citizens band
a=28000000,b=30000000,m=WFM,bw=16k,d=Amateur_radio|Amateur
a=29000000,b=54000000,m=WFM,bw=16k,d=Land mobile
a=50000000,b=54000000,m=WFM,bw=16k,d=Amateur_radio|Amateur
a=65000000,b=85000000,m=WFM,bw=16k,d=Land mobile (EU)
a=108000000,b=136000000,m=WFM,bw=16k,d=Aircraft
a=120000000,b=160000000,m=WFM,bw=16k,s=50KHz,d=Land mobile (EU)
a=132000000,b=174000000,m=WFM,bw=16k,s=50KHz,d=Land mobile
a=142000000,b=170000000,m=WFM,bw=16k,s=50KHz,d=Land mobile (J)
a=144000000,b=148000000,m=WFM,bw=16k,s=50KHz,d=Amateur_radio|Amateur
a=216000000,b=222000000,m=WFM,bw=16k,s=50KHz,d=Land mobile
a=222000000,b=225000000,m=WFM,bw=16k,s=50KHz,d=Amateur_radio|Amateur
a=335000000,b=384000000,m=WFM,bw=16k,s=50KHz,d=Land mobile (J)
a=406000000,b=512000000,m=WFM,bw=16k,s=50KHz,d=Land mobile
a=450000000,b=470000000,m=WFM,bw=16k,s=50KHz,d=Land mobile (J)
a=430000000,b=450000000,m=WFM,bw=16k,s=50KHz,d=Amateur_radio|Amateur
a=806000000,b=947000000,m=WFM,bw=16k,s=50KHz,d=Land mobile
a=1200000000,b=1600000000,m=WFM,bw=16k,s=50KHz,d=Amateur|Land mobile|GPS
+3
View File
@@ -0,0 +1,3 @@
##FREQ FILE SAMPLE RATE
315000000,SAMPLES/TeslaChargePort_US.C16,500000
433920000,SAMPLES/TeslaChargePort_EU_AU.C16,500000
View File