Compare commits

...

248 Commits

Author SHA1 Message Date
gullradriel e2620f1a33 Merge pull request #822 from heurist1/fix-tuning-radio-when-opening-app-with-settings
Fix  the initialisation of frquency when apps are launched
2023-03-05 20:57:54 +01:00
heurist1 f6a4cc26ee Move where on_change for the frequency field is setup, so that the frequency is correctly initialised when the app is launched and settings are being used 2023-03-05 19:50:56 +00:00
gullradriel 3d248647c9 Set usable persistent memory defaults for Recon (#820)
* Set usable defaults for Recon when PortaPack is not having a valid button battery installed

* fixed indentation

* fixed indentation

---------

Co-authored-by: GullCode <gullradriel@hotmail.com>
2023-03-04 22:04:53 +01:00
gullradriel 3c13161273 Merge pull request #818 from Brumi-2021/ADSB_squawk_investigation
Correct squawk id in ADSB TX
2023-03-04 08:10:43 +01:00
gullradriel f0b4914186 Merge pull request #819 from Brumi-2021/revert_new_spectrum_colour_scheme
Revert "New spectrum color scheme"
2023-03-04 08:09:44 +01:00
Brumi-2021 037fc098ef Revert "New spectrum color scheme"
This reverts commit f59437cf71.
2023-03-04 00:47:40 +01:00
Brumi-2021 988404df9c Correct squawk id in ADSB TX 2023-03-03 23:10:58 +01:00
jLynx f5deae56cf Merge pull request #806 from nnesetto/next
New Docker and sounds
2023-03-02 08:12:13 +13:00
gullradriel e526061d13 Merge pull request #815 from heurist1/adsb-multiple-aircraft-on-map2
ADSB RX multiple aircraft on map - 2
2023-03-01 18:41:25 +01:00
heurist1 daf63de55f Final corrections to make merged code compile, and reduce the adding and removing of other markers 2023-02-28 23:00:51 +00:00
heurist1 778111d466 Updates to put the multiple aircraft on the map
Also manage the CPU in on the one second tick to keep GUI responsive
Some other small edits that fix minor problems from my previous checkins
2023-02-28 20:19:23 +00:00
heurist1 00b75eacda Update map to allow multiple markers 2023-02-28 20:14:15 +00:00
heurist1 ef151e243b Imprment string trimr to remove spaces at the end of aircraft name.
(cherry picked from commit 70fd4039938cdd45f03d541e0aff1238de85fb3e)
2023-02-28 20:00:56 +00:00
heurist1 567fee1d98 Create optimised integer functions to reduce CPU usage
(cherry picked from commit a47bfe1da7bffe9f752e4c522e11593cce6dffd0)
2023-02-28 20:00:39 +00:00
heurist1 b549d3a4f1 Add ability to draw text with a transparent background
(cherry picked from commit a15da2e136147b31ab53058871815c8eb759576a)
2023-02-28 20:00:05 +00:00
gullradriel 86203f090f Merge pull request #812 from euquiq/mayhem-version
Looking Glass optimizations
2023-02-28 08:03:06 +01:00
euquiq 19fed78b7f Looking Glass optimizations 2023-02-27 23:29:13 -03:00
ittercho c0532aeafa Merge branch 'eried:next' into next 2023-02-22 23:24:38 +00:00
Erwin Ried c8774e82d9 Merge pull request #808 from zxkmm/next
Add config files for FREQMAN
2023-02-22 14:07:27 +01:00
zxkmm 62ee23a314 Add config files for FREQMAN 2023-02-22 21:00:15 +08:00
ittercho 70551ef155 Format 2023-02-19 08:35:25 +01:00
ittercho 91074e5b4e Add file 2023-02-19 08:35:19 +01:00
gullradriel 5f95cec5f4 Merge pull request #805 from phil-stumpy/next
Adding support for HackRF One R9
2023-02-16 13:48:01 +01:00
phil-stumpy 66ba6442b1 Adding support for HackRF One R9, as per https://github.com/sharebrained/portapack-hackrf/pull/187 2023-02-16 12:10:26 +00:00
gullradriel 7e20cea6d7 Merge pull request #800 from gullradriel/next
Updated hackRF submodule
2023-02-07 14:00:54 +01:00
GullCode 65217856c0 Updated hackRF submodule 2023-02-07 13:59:00 +01:00
gullradriel 5117538b49 Merge pull request #799 from lujji/fix-ook-app
Fix OOK app
2023-02-04 16:41:06 +01:00
lujji 362c208078 fix ook app and 1527 encoder; add scan encoding 2023-02-02 17:54:36 +02:00
Erwin Ried 4f9e8e9642 Update README.md 2023-01-25 15:34:09 +01:00
Erwin Ried de53626a46 Update README.md 2023-01-25 15:33:00 +01:00
Erwin Ried 2cf6849985 Update README.md 2023-01-25 15:16:03 +01:00
Erwin Ried 1cde3ab189 Update README.md 2023-01-25 15:12:21 +01:00
Erwin Ried bdb70a3231 Update README.md 2023-01-25 15:04:43 +01:00
Erwin Ried 49e63e2728 Update README.md 2023-01-25 14:36:18 +01:00
Erwin Ried 1beca57e56 Update README.md 2023-01-25 14:33:27 +01:00
Erwin Ried 27632825a3 Update contributors list 2023-01-25 14:14:12 +01:00
gullradriel e02e58b366 Merge pull request #789 from formtapez/settings
Save and recall all receiver settings of the Audio RX app
2023-01-21 13:04:52 +01:00
formtapez 37912df085 tabs vs spaces 2023-01-21 11:46:43 +01:00
formtapez a20a08c630 save/recall all receiver settings 2023-01-21 11:36:06 +01:00
formtapez a8885282cd save and recall stepsize 2023-01-20 22:21:59 +01:00
gullradriel 2d9090862b Merge pull request #782 from Brumi-2021/adding_Vertical_rate_field_ADSB_TX
Added Vertical rate field ADSB-TX
2023-01-05 09:59:00 +01:00
Brumi-2021 6e5bb7911c Added Vertical rate field ADSB-TX 2023-01-05 00:14:11 +01:00
Brumi-2021 46f98ddc8b Merge pull request #780 from Brumi-2021/Correcting_complementary_Bearing_Compas_Hdg_angle_ADSB-TX_App_final
Solving correct  Bearing Angle in ADSB TX app
2023-01-01 23:15:52 +01:00
Brumi-2021 2902365b80 Solving correct Bearing Angle in ADSB TX app 2023-01-01 23:23:06 +01:00
Brumi-2021 c0f368c978 Merge pull request #775 from Brumi-2021/Small_BW_Label_error_correction_Scanner_App
Scanner BW label corrections
2022-12-29 23:23:41 +01:00
Brumi-2021 75c2b69f19 Scanner BW label corrections 2022-12-30 00:38:54 +01:00
Brumi-2021 3291c7e2a0 Merge pull request #774 from Brumi-2021/Minor_ADSB_Compas_sinf32_array_value_correction_and_comments
Minor sin_f32_table correction and comments
2022-12-29 22:24:28 +01:00
Brumi-2021 64ca9f6a68 Minor sin_f32_table correction and comments 2022-12-29 23:27:15 +01:00
gullradriel 297063873f Merge pull request #767 from rusty-labs/scanner-manual-mode-unlimited-range
#765 Scanner app, unlimited range for manual mode
2022-12-29 17:41:00 +01:00
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
rusty.labs 1f7b800c2a #765 unlimited range for manual mode
* fix for #765, manual mode has unlimited range now
* speedup for button_add.on_select (roughly x70 times faster)
* fix for random freezes while switching to Audio
2022-12-26 17:18:30 -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
jLynx 2f10fe2fe4 v1.5.3 (#649)
* Update create_stable_release.yml

* Update version.txt
2022-05-21 08:03:17 +12:00
jLynx 5a7b12f920 Update version.txt 2022-05-20 11:00:41 +12:00
jLynx f8a4134973 Update past_version.txt 2022-05-20 11:00:34 +12:00
ArjanOnwezen a3ee160e27 Merge pull request #643 from ArjanOnwezen/save-more-app-settings
Save most common settings for TX apps
2022-05-13 21:42:51 +02:00
Arjan Onwezen ade0d6c68f French translations. 2022-05-13 09:31:58 -04:00
ArjanOnwezen 8e9355b57a Merge pull request #644 from ArjanOnwezen/set-fixed-modulation-for-pocsag
Set fixed modulation (NFM) for Pocsag app. (#569)
2022-05-13 15:11:43 +02:00
Arjan Onwezen e97ffd42ef Set fixed modulation (WFM) for Pocsag app. 2022-05-13 09:04:53 -04:00
Arjan Onwezen cccc92cc34 Save most common settings for TX apps. And translated some French apps along the way. 2022-05-13 08:38:04 -04:00
ArjanOnwezen 3387b59eab Add AMD64 folder #632
Added AMD64 folder #632
2022-05-11 17:33:33 +02:00
MattLodge 6c5f8a38e0 Update generate_world_map.bin.py (#640)
Use bytes instead of strings to write ADSB map binary for python3
2022-05-09 07:27:15 +12:00
Brumi-2021 dda543f7f3 Merge branch 'eried:next' into next 2022-05-08 12:39:27 +02:00
Brumi-2021 de1570d8af Allow change initial gain amp values just opened file (#634)
* Update spectrum_collector.cpp

lower case correction

* Update spectrum_collector.cpp

Description changed , better explanation.

* Revert "Update spectrum_collector.cpp"

This reverts commit 4a6fc35384.

* Revert "Update spectrum_collector.cpp"

This reverts commit 35cece1cb0.

* 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.

* Allow initial GAIN ,AMP changes after opened  file
2022-05-07 11:43:55 +12:00
Brumi-2021 1027e80d53 Recovered lost ctcss/roger beep/correct mic gain in mic app from 1.5.1 without ALC (Auto mic Limit Control-AK) (#633)
* Update spectrum_collector.cpp

lower case correction

* Update spectrum_collector.cpp

Description changed , better explanation.

* Revert "Update spectrum_collector.cpp"

This reverts commit 4a6fc35384.

* Revert "Update spectrum_collector.cpp"

This reverts commit 35cece1cb0.

* 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.

* Recovered CTCSS-Roger_beep-MIC-GAIN from 1.5.1

* Temporary removing ALC-( for AK4951 platorm)
2022-05-07 11:43:14 +12:00
Brumi-2021 92844a7528 Merge branch 'eried:next' into next 2022-05-06 21:55:27 +02:00
Erwin Ried c9db1aab30 Merge pull request #630 from TQMatvey/next
Fix KeyFob (beta) being off-screen
2022-05-05 14:57:35 +02:00
TqMatvey 367cb318cd Fix KeyFob (beta) being off-screen 2022-05-05 18:06:15 +07:00
jLynx fe33c12111 Sound/white noise Clock fix (#625) 2022-05-05 08:31:54 +12:00
ArjanOnwezen 8957d692ea Merge pull request #623 from GullCode/touch_return_option
Added a ui_config flag to manage gui return icon status
2022-05-04 13:47:34 +02:00
GullCode 5551c6a676 Fixing branch, moving block, adding quote 2022-05-04 10:29:12 +02:00
GullCode 2b7b0d028a Merge branch 'touch_return_option' of github.com:GullCode/portapack-mayhem into touch_return_option 2022-05-03 14:42:40 +02:00
GullCode 7b42d9ec94 changed label to fit the screen 2022-05-03 14:34:55 +02:00
GullCode 0580a528e4 Merge branch 'next' into touch_return_option 2022-05-03 14:31:03 +02:00
GullCode c75c4685cd Added a ui_config flag to manage gui return icon status 2022-05-03 14:23:58 +02:00
Brumi-2021 ef52339b1d Merge branch 'eried:next' into next 2022-05-02 20:05:42 +02:00
ArjanOnwezen da49743cc4 Merge pull request #619 from ArjanOnwezen/save-app-settings
Save individual app settings.
2022-05-01 21:19:09 +02:00
Arjan Onwezen 799a473b36 Save individual app settings. Currently only for apps in Receive section and basic settings like, LNA, VGA, Rx Amp and Frequency. 2022-05-01 06:09:02 -04: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
ArjanOnwezen dccc68a4e0 Merge pull request #610 from zigad/fix-title-inconsistancy
Fix #494 - Change App Titles
2022-04-27 12:49:03 +02:00
Arne Luehrs d2dbad73c7 Merge branch 'eried:next' into next 2022-04-27 10:16:26 +02:00
Žiga Deisinger ee9b4c89bd Fix #494 - Change App Titles
I choose what I think are the best Titles based on existing titles/class names and so on. There were also inconsistencies between TX and Transmit and RX and receive. I renamed them to shorter version TX and RX also added it as suffix where possible to make it clearer in what mode you are in. If you have any other title suggestions or changes please use Add comment on Files Changed Screen so I can change it.
2022-04-26 23:09:24 +02:00
Erwin Ried a91bbe6a2e Merge pull request #596 from GullCode/proc-adsbrx-warning-fix
Fix for warning: comparison of integer expressions of different signedness
2022-04-22 10:00:05 +02:00
Erwin Ried a5a9bc85f8 Merge pull request #597 from GullCode/proc-aprsrx-warning-fix
Fix for proc_aprsrx and aprs_packet warnings, they are related
2022-04-22 09:59:31 +02:00
Erwin Ried b23addd452 Merge pull request #598 from GullCode/tpms-warning-fix
Fix for warning: narrowing conversion
2022-04-22 09:59:21 +02:00
Erwin Ried 6467e5e7e6 Merge pull request #599 from GullCode/proc_mictx-warning-fix
Fix for warning: 'MicTXProcessor::modulator' should be initialized
2022-04-22 09:59:08 +02:00
Erwin Ried 35ed394b37 Merge pull request #601 from GullCode/ais_app-warning-fix
Added missing contructors/operators/etc in ais_app
2022-04-22 09:59:01 +02:00
Erwin Ried 4c98cf16a1 Merge pull request #600 from GullCode/ui_qrcode-warning-fix
Fix for weffc++
2022-04-22 08:19:43 +02:00
Erwin Ried 18be6750e5 Merge pull request #602 from GullCode/ui_adsb_rx-warning-fix
Added missing initializer
2022-04-22 08:19:03 +02:00
Erwin Ried 4f58be737a Merge pull request #603 from GullCode/proc_pocsag-warning-fix
Fix warning for proc_pocsag
2022-04-22 01:04:22 +02:00
GullCode 3fa190324b Fix warning for proc_pocsag 2022-04-21 23:25:58 +02:00
GullCode de042df7eb Added missing initializer 2022-04-21 23:12:37 +02:00
GullCode 2fbf96425a Added missing contructors/operators/etc in ais_app 2022-04-21 22:52:17 +02:00
GullCode 85d5a8fdba Fix for weffc++ 2022-04-21 22:27:20 +02:00
GullCode f13d1f8b9c Fix for warning: 'MicTXProcessor::modulator' should be initialized 2022-04-21 21:46:55 +02:00
GullCode f804d7997c Fix for warning: narrowing conversion 2022-04-21 21:41:02 +02:00
GullCode 2108ea53fa Fix for proc_aprsrx and aprs_packet warnings, they are related 2022-04-21 17:38:49 +02:00
GullCode 90d38af705 Fix for warning: comparison of integer expressions of different signedness 2022-04-21 17:29:42 +02:00
Erwin Ried d617618dcd Merge pull request #592 from GullCode/ui-aprs-rx-warning-fix
Fix for warning XXX should be initialized
2022-04-21 09:15:53 +02:00
GullCode c37df0c6fd Fix for warning XXX should be initialized in the member initialization list 2022-04-19 17:23:30 +02:00
Erwin Ried cdba4fa5bf Merge pull request #590 from GullCode/a-packet-warning-fix
Fixed warning: comparison of integer expressions of different signedness
2022-04-18 23:29:41 +02:00
Erwin Ried 1537b1eccb Merge pull request #589 from GullCode/qrcode-warning-fix
Qrcode warning fix
2022-04-18 23:29:08 +02:00
GullCode 048b254354 Fixed uninitialized class members 2022-04-18 22:45:16 +02:00
GullCode 4b87a8a7dd Fixed warning: comparison of integer expressions of different signedness 2022-04-18 22:38:29 +02:00
GullCode 5cdaac6b82 Fix uneeded negative test because type is uint ( warning: comparison is always false due to limited range of data type) 2022-04-18 22:33:10 +02:00
GullCode 17aa58bbf8 Changed pramga to comments to fix warning: ignoring #pragma mark [-Wunknown-pragmas] 2022-04-18 22:32:43 +02:00
Erwin Ried e93a5820a2 Merge pull request #587 from notpike/grc
Added GRC C16 to complex script
2022-04-17 20:45:54 +02:00
notpike 0e9c7448c0 Added GRC C16 to complex script 2022-04-17 11:05:20 -07: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
206 changed files with 10039 additions and 2076 deletions
+1
View File
@@ -0,0 +1 @@
build
+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
@@ -51,7 +51,7 @@ jobs:
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
tag_name: v1.5.1
tag_name: ${{ steps.version.outputs.version }}
release_name: Mayhem firmware ${{ steps.version.outputs.version }}
body: |
**Stable release - ${{ steps.version.outputs.version }}**
+1 -1
View File
@@ -1 +1 @@
v1.5.0
v1.5.4
+1 -1
View File
@@ -1 +1 @@
v1.5.1
v1.6.0
-1
View File
@@ -27,7 +27,6 @@
# Compiled Dynamic libraries
*.so
*.dylib
*.dll
# Fortran module files
*.mod
-1
View File
@@ -53,4 +53,3 @@ addons:
- sed
- cmake
- dfu-util
+18 -23
View File
@@ -1,12 +1,12 @@
# 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.
[<img src="https://raw.githubusercontent.com/wiki/eried/portapack-mayhem/img/hw_overview_h2_front.png" height="400">](https://github.com/eried/portapack-mayhem/wiki/Hardware-overview) [<img src="https://raw.githubusercontent.com/wiki/eried/portapack-mayhem/img/hw_overview_h2_inside.png" height="400">](https://github.com/eried/portapack-mayhem/wiki/Hardware-overview#portapack-internals)
*[PortaPack H2+HackRF+battery](https://s.click.aliexpress.com/e/_9zbXMk) (clone) with a custom [3d printed case](https://github.com/eried/portapack-mayhem/wiki/H2-Enclosure)*
*[PortaPack H2+HackRF+battery](https://s.click.aliexpress.com/e/_DmU7GQX) (clone) with a custom [3d printed case](https://github.com/eried/portapack-mayhem/wiki/H2-Enclosure)*
# Quick overview
@@ -18,42 +18,40 @@ If you are new to *HackRF+PortaPack+Mayhem*, there is an awesome introductory vi
This repository expands upon the previous work by many people and aims to constantly add new features, bugfixes and generate documentation to make further development easier. [Collaboration](https://github.com/eried/portapack-mayhem/wiki/How-to-collaborate) is always welcomed and appreciated.
## Does it work on H1/H2 PortaPack?
## What to buy?
Yes, both devices are the [same](https://github.com/eried/portapack-mayhem/wiki/First-steps). The one I am using to test all changes is this [PortaPack H2+HackRF+battery](https://s.click.aliexpress.com/e/_9zbXMk), which is a kit that includes everything you need. Sadly, the people making the H2 never made the updated schematics available, which is not ideal (and goes against the terms of the license). Most members of the community are using a clone of the [PortaPack H1+HackRF+metal case](https://s.click.aliexpress.com/e/_dS6liw4), which does not include any battery functionality, but it is a cheaper alternative.
:heavy_check_mark: A recommended one is this [PortaPack H2](https://s.click.aliexpress.com/e/_DmU7GQX) pack, that includes everything you need. Sadly, the people making the H2 never made the updated schematics available (against the terms of the license).
To support the people behind the hardware, please buy a genuine [HackRF](https://greatscottgadgets.com/hackrf/) and [PortaPack](https://store.sharebrained.com/products/portapack-for-hackrf-one-kit).
:heavy_check_mark: Another popular option is the clone of the [PortaPack H1](https://s.click.aliexpress.com/e/_Dkbqs2X).
## Where is the latest firmware?
:warning: Be cautious , *ask* the seller about compatibility with the latest releases. Look out for the description of the item, if they provide the firmware files for an older version or they have custom setup instructions, this means it might be **NOT compatible**, for example:
The **latest (nightly) release** can be found [here](https://github.com/eried/portapack-mayhem/releases/).
![image](https://user-images.githubusercontent.com/1091420/214579017-9ad970b9-0917-48f6-a550-588226d3f89b.png)
The current **stable release** is on the [![GitHub release (latest by date)](https://img.shields.io/github/v/release/eried/portapack-mayhem?label=Releases&style=social)](https://github.com/eried/portapack-mayhem/releases/latest) page. Follow the instructions you can find in the release description.
:warning: If it looks **too different**, this might mean that they are using their own recipe, check the [different models](https://github.com/eried/portapack-mayhem/wiki/PortaPack-Versions) in our wiki. For example all the H3 and clones of that version use their own version of the firmware. They do not contribute the changes back and eventually you will be left with a device that nobody maintains:
## Is this the newest firmware for my PortaPack?
Most probably: **YES**. *If you find new features somewhere else, please [suggest](https://github.com/eried/portapack-mayhem/issues/new/choose) them*.
![image](https://user-images.githubusercontent.com/1091420/214581333-424900ee-26f8-4e96-be2f-69d8dc995ba9.png)
## Which one is actually the newest?
There is a lot of confusion of which is the latest version because no old version used any actual "version number". Additionally, since the files were distributed on facebook groups, github issue links and similar temporal sources, then there was no central location for them.
## Where is the latest version?
This fork (**Mayhem**) uses *major.minor.release* [semantic versioning](https://en.wikipedia.org/wiki/Software_versioning), so you can always compare your current version with the latest from [Releases](https://github.com/eried/portapack-mayhem/releases/latest).
## What about Havoc/GridRF/jamesshao8/jboone's?
* jboone's PortaPack: the [vanilla](https://en.wikipedia.org/wiki/Vanilla_software) experience
* Havoc: It was the most popular fork of jboone's PortaPack, currrently, it is not being maintained nor updated
* jamesshao8: He keeps his own version of the fork, while not attached as a fork to anything. Latest functions do not follow the license and are not being published with source code, so keep this in mind
* GridRF: They sell PortaPack clones with their own firmware based on a old version, which has no sourcecode available
The current **stable release** is on the [![GitHub release (latest by date)](https://img.shields.io/github/v/release/eried/portapack-mayhem?label=Releases&style=social)](https://github.com/eried/portapack-mayhem/releases/latest) page. Follow the instructions you can find in the release description. The **latest (nightly) release** can be found [here](https://github.com/eried/portapack-mayhem/releases/).
## How can I collaborate
You can write [documentation](https://github.com/eried/portapack-mayhem/wiki), fix bugs and [answer issues](https://github.com/eried/portapack-mayhem/issues) or add new functionality. Please check the following [guide](https://github.com/eried/portapack-mayhem/wiki/How-to-collaborate) with details.
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)
To support the people behind the hardware, please buy a genuine [HackRF](https://greatscottgadgets.com/hackrf/) and [PortaPack](https://store.sharebrained.com/products/portapack-for-hackrf-one-kit).
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)
## What if I really want to pay for something?
## What if I really want something specific?
If what you need can be relevant in general, you can [request a feature](https://github.com/eried/portapack-mayhem/issues/new?labels=enhancement&template=feature_request.md).
You can create a bounty and invite people to your own bounty. This will incentivize coders to work on a new feature, solving a bug or even writting documentation. Start a bounty by [creating](https://github.com/eried/portapack-mayhem/issues/new/choose) or [choosing](https://github.com/eried/portapack-mayhem/issues/) an existing issue. Then, go to [Bountysource](https://www.bountysource.com/) and post a bounty using the link to that specific [issue](https://www.bountysource.com/teams/portapack-mayhem/issues).
Promote your bounty over our Discord by clicking the chat badge on [top](#portapack-mayhem).
@@ -62,6 +60,3 @@ Promote your bounty over our Discord by clicking the chat badge on [top](#portap
First, check the [documentation](https://github.com/eried/portapack-mayhem/wiki). If you find a bug or you think the problem is related to the current repository, please open an [issue](https://github.com/eried/portapack-mayhem/issues/new/choose).
You can reach the [official community](https://www.facebook.com/groups/177623356165819) in Facebook, and our Discord by clicking the chat badge on [top](#portapack-mayhem).
## What if I find incongruencies, or grammatical errors in the text?
If is on the [Wiki](https://github.com/eried/portapack-mayhem/wiki), you can modify it directly. If is on files of the repository, you can send corrections as [pull requests](https://github.com/eried/portapack-mayhem/wiki/How-to-collaborate#coding-new-stuff-or-fixing-bugs). As a last resource, open an [issue](https://github.com/eried/portapack-mayhem/issues/new/choose).
+9
View File
@@ -0,0 +1,9 @@
version: '3.9'
services:
portapack-mayhem-dev:
build:
context: .
dockerfile: dockerfile-nogit-alpine
volumes:
- ".:/havoc"
+9
View File
@@ -0,0 +1,9 @@
version: '3.9'
services:
portapack-mayhem-dev:
build:
context: .
dockerfile: dockerfile-alpine
volumes:
- "./bin:/havocbin"
+17 -14
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,17 +14,19 @@ 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 && \
ln -s /usr/bin/pip3 /usr/bin/pip
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
ENV LC_ALL C.UTF-8
@@ -32,14 +34,15 @@ 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
CMD cd /havocsrc && \
mkdir build && cd build && \
cmake .. && make firmware && \
cp /portapack-havoc/firmware/portapack-h1-havoc.bin /havocbin
mkdir build && cd build && \
cmake .. && make firmware && \
cp /portapack-havoc/firmware/portapack-h1-havoc.bin /havocbin
+29
View File
@@ -0,0 +1,29 @@
# Download base image.
FROM alpine:edge
# Download ARM toolkit.
RUN apk add --no-cache gcc-arm-none-eabi gcc
# Create volume /havocbin for compiled firmware binaries
VOLUME /havocbin
# Copy build context (repository root) to /havocsrc
COPY ./ /havocsrc
# Fetch dependencies from APK
RUN echo "http://dl-cdn.alpinelinux.org/alpine/edge/testing" >> /etc/apk/repositories
RUN apk update -U
RUN apk add --no-cache git tar wget cmake curl bzip2 make
RUN apk add --no-cache dfu-util ccache icu-data-full
RUN apk add --no-cache python3 py3-pip py3-yaml
RUN apk add --no-cache py3-pyyaml-env-tag
RUN apk add --no-cache g++ gcc clang clang-static clang-dev llvm-dev llvm-static
ENV LANG C.UTF-8
ENV LC_ALL C.UTF-8
CMD cd /havocsrc && \
mkdir build && cd build && \
cmake .. && make firmware && \
cp /portapack-havoc/firmware/portapack-h1-havoc.bin /havocbin
+2 -2
View File
@@ -21,7 +21,7 @@ RUN curl https://bootstrap.pypa.io/pip/3.4/get-pip.py -o get-pip.py && \
#Fetch additional dependencies from Python 3.x pip
RUN pip install pyyaml
RUN ln -s /usr/bin/python3 /usr/bin/python && \
ln -s /usr/bin/pip3 /usr/bin/pip
ln -s /usr/bin/pip3 /usr/bin/pip
ENV LANG C.UTF-8
ENV LC_ALL C.UTF-8
@@ -38,4 +38,4 @@ RUN mkdir ~/bin && cd ~/bin && \
for tool in gcc g++ cpp c++;do ln -s $(which ccache) arm-none-eabi-$tool;done
CMD cd .. && cd build && \
cmake .. && make firmware
cmake .. && make firmware
+27
View File
@@ -0,0 +1,27 @@
FROM alpine:edge
# Download ARM toolkit.
RUN apk add --no-cache gcc-arm-none-eabi gcc
# Create volume /havoc/bin for compiled firmware binaries
VOLUME /havoc
WORKDIR /havoc/firmware
# Fetch dependencies from APK
RUN echo "http://dl-cdn.alpinelinux.org/alpine/edge/testing" >> /etc/apk/repositories
RUN apk update -U
RUN apk add --no-cache git tar wget cmake curl bzip2 make
RUN apk add --no-cache dfu-util ccache icu-data-full
RUN apk add --no-cache python3 py3-pip py3-yaml
RUN apk add --no-cache py3-pyyaml-env-tag
RUN apk add --no-cache g++ gcc clang clang-static clang-dev llvm-dev llvm-static
ENV LANG C.UTF-8
ENV LC_ALL C.UTF-8
# Configure CCACHE
RUN mkdir ~/bin && cd ~/bin && \
for tool in gcc g++ cpp c++;do ln -s $(which ccache) arm-none-eabi-$tool;done
CMD cd .. && cd build && \
cmake .. && make firmware
+7
View File
@@ -103,6 +103,7 @@ set(CSRC
${PLATFORMSRC}
${BOARDSRC}
${FATFSSRC}
firmware_info.c
)
# C++ sources that can be compiled in ARM or THUMB mode depending on the global
@@ -154,6 +155,7 @@ set(CPPSRC
${COMMON}/ui_widget.cpp
${COMMON}/utility.cpp
${COMMON}/wm8731.cpp
app_settings.cpp
audio.cpp
baseband_api.cpp
capture_thread.cpp
@@ -192,6 +194,7 @@ set(CPPSRC
hw/debounce.cpp
hw/encoder.cpp
hw/max2837.cpp
hw/max2839.cpp
hw/max5864.cpp
hw/rffc507x.cpp
hw/rffc507x_spi.cpp
@@ -266,8 +269,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
+115
View File
@@ -0,0 +1,115 @@
/*
* Copyright (C) 2015 Jared Boone, ShareBrained Technology, Inc.
* Copyright (C) 2016 Furrtek
* Copyright (C) 2022 Arjan Onwezen
*
* This file is part of PortaPack.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street,
* Boston, MA 02110-1301, USA.
*/
#include "app_settings.hpp"
#include "file.hpp"
#include "portapack.hpp"
#include "portapack_persistent_memory.hpp"
#include <cstring>
#include <algorithm>
namespace std {
int app_settings::load(std::string application, AppSettings* settings) {
if (portapack::persistent_memory::load_app_settings()) {
file_path = folder+"/"+application+".ini";
auto error = settings_file.open(file_path);
if (!error.is_valid()) {
auto error = settings_file.read(file_content, std::min((int)settings_file.size(), MAX_FILE_CONTENT_SIZE));
settings->baseband_bandwidth=std::app_settings::read_long_long(file_content, "baseband_bandwidth=");
settings->channel_bandwidth=std::app_settings::read_long_long(file_content, "channel_bandwidth=");
settings->lna=std::app_settings::read_long_long(file_content, "lna=");
settings->modulation=std::app_settings::read_long_long(file_content, "modulation=");
settings->rx_amp=std::app_settings::read_long_long(file_content, "rx_amp=");
settings->rx_frequency=std::app_settings::read_long_long(file_content, "rx_frequency=");
settings->sampling_rate=std::app_settings::read_long_long(file_content, "sampling_rate=");
settings->vga=std::app_settings::read_long_long(file_content, "vga=");
settings->tx_amp=std::app_settings::read_long_long(file_content, "tx_amp=");
settings->tx_frequency=std::app_settings::read_long_long(file_content, "tx_frequency=");
settings->tx_gain=std::app_settings::read_long_long(file_content, "tx_gain=");
settings->step=std::app_settings::read_long_long(file_content, "step=");
settings->modulation=std::app_settings::read_long_long(file_content, "modulation=");
settings->am_config_index=std::app_settings::read_long_long(file_content, "am_config_index=");
settings->nbfm_config_index=std::app_settings::read_long_long(file_content, "nbfm_config_index=");
settings->wfm_config_index=std::app_settings::read_long_long(file_content, "wfm_config_index=");
settings->squelch=std::app_settings::read_long_long(file_content, "squelch=");
rc = SETTINGS_OK;
}
else rc = SETTINGS_UNABLE_TO_LOAD;
}
else rc = SETTINGS_DISABLED;
return(rc);
}
int app_settings::save(std::string application, AppSettings* settings) {
if (portapack::persistent_memory::save_app_settings()) {
file_path = folder+"/"+application+".ini";
make_new_directory(folder);
auto error = settings_file.create(file_path);
if (!error.is_valid()) {
// Save common setting
settings_file.write_line("baseband_bandwidth="+to_string_dec_uint(portapack::receiver_model.baseband_bandwidth()));
settings_file.write_line("channel_bandwidth="+to_string_dec_uint(portapack::transmitter_model.channel_bandwidth()));
settings_file.write_line("lna="+to_string_dec_uint(portapack::receiver_model.lna()));
settings_file.write_line("rx_amp="+to_string_dec_uint(portapack::receiver_model.rf_amp()));
settings_file.write_line("sampling_rate="+to_string_dec_uint(portapack::receiver_model.sampling_rate()));
settings_file.write_line("tx_amp="+to_string_dec_uint(portapack::transmitter_model.rf_amp()));
settings_file.write_line("tx_gain="+to_string_dec_uint(portapack::transmitter_model.tx_gain()));
settings_file.write_line("vga="+to_string_dec_uint(portapack::receiver_model.vga()));
// Save other settings from struct
settings_file.write_line("rx_frequency="+to_string_dec_uint(settings->rx_frequency));
settings_file.write_line("tx_frequency="+to_string_dec_uint(settings->tx_frequency));
settings_file.write_line("step="+to_string_dec_uint(settings->step));
settings_file.write_line("modulation="+to_string_dec_uint(settings->modulation));
settings_file.write_line("am_config_index="+to_string_dec_uint(settings->am_config_index));
settings_file.write_line("nbfm_config_index="+to_string_dec_uint(settings->nbfm_config_index));
settings_file.write_line("wfm_config_index="+to_string_dec_uint(settings->wfm_config_index));
settings_file.write_line("squelch="+to_string_dec_uint(settings->squelch));
rc = SETTINGS_OK;
}
else rc = SETTINGS_UNABLE_TO_SAVE;
}
else rc = SETTINGS_DISABLED;
return(rc);
}
long long int app_settings::read_long_long(char* file_content, const char* setting_text) {
auto position = strstr(file_content, (char *)setting_text);
if (position) {
position += strlen((char *)setting_text);
setting_value = strtoll(position, nullptr, 10);
}
return(setting_value);
}
} /* namespace std */
+92
View File
@@ -0,0 +1,92 @@
/*
* Copyright (C) 2015 Jared Boone, ShareBrained Technology, Inc.
* Copyright (C) 2016 Furrtek
* Copyright (C) 2022 Arjan Onwezen
*
* This file is part of PortaPack.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street,
* Boston, MA 02110-1301, USA.
*/
#ifndef __APP_SETTINGS_H__
#define __APP_SETTINGS_H__
#include <cstddef>
#include <cstdint>
#include <string>
#include "file.hpp"
#include "string_format.hpp"
namespace std {
class app_settings {
public:
#define SETTINGS_OK 0 // settings found
#define SETTINGS_UNABLE_TO_LOAD -1 // settings (file) not found
#define SETTINGS_UNABLE_TO_SAVE -2 // unable to save settings
#define SETTINGS_DISABLED -3 // load/save settings disabled in settings
struct AppSettings {
uint32_t baseband_bandwidth;
uint32_t channel_bandwidth;
uint8_t lna;
uint8_t modulation;
uint8_t rx_amp;
uint32_t rx_frequency;
uint32_t sampling_rate;
uint8_t tx_amp;
uint32_t tx_frequency;
uint8_t tx_gain;
uint8_t vga;
uint32_t step;
uint8_t am_config_index;
uint8_t nbfm_config_index;
uint8_t wfm_config_index;
uint8_t squelch;
};
int load(std::string application, AppSettings* settings);
int save(std::string application, AppSettings* settings);
private:
#define MAX_FILE_CONTENT_SIZE 1000
char file_content[MAX_FILE_CONTENT_SIZE] = {};
std::string file_path = "";
std::string folder = "SETTINGS";
int rc = SETTINGS_OK;
File settings_file { };
long long int setting_value {} ;
long long int read_long_long(char* file_content, const char* setting_text);
}; // class app_settings
} // namespace std
#endif/*__APP_SETTINGS_H__*/
+73 -28
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,10 +284,20 @@ AISRecentEntryDetailView::AISRecentEntryDetailView(NavigationView& nav) {
});
send_updates = true;
};
}
AISRecentEntryDetailView::AISRecentEntryDetailView(const AISRecentEntryDetailView&Entry) : View()
{
(void)Entry;
}
AISRecentEntryDetailView & AISRecentEntryDetailView::operator=(const AISRecentEntryDetailView&Entry)
{
(void)Entry;
return *this;
}
void AISRecentEntryDetailView::update_position() {
@@ -292,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));
@@ -325,25 +367,24 @@ AISAppView::AISAppView(NavigationView& nav) : nav_ { nav } {
&recent_entry_detail_view,
});
// load app settings
auto rc = settings.load("rx_ais", &app_settings);
if(rc == SETTINGS_OK) {
field_lna.set_value(app_settings.lna);
field_vga.set_value(app_settings.vga);
field_rf_amp.set_value(app_settings.rx_amp);
target_frequency_ = app_settings.rx_frequency;
}
else target_frequency_ = initial_target_frequency;
recent_entry_detail_view.hidden(true);
target_frequency_ = initial_target_frequency;
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.
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({ // this can be removed, previous version,no DC-bias control.
tuning_frequency(),
sampling_rate,
baseband_bandwidth,
rf::Direction::Receive,
receiver_model.rf_amp(),
static_cast<int8_t>(receiver_model.lna()),
static_cast<int8_t>(receiver_model.vga()),
}); */
options_channel.on_change = [this](size_t, OptionsField::value_t v) {
this->on_frequency_changed(v);
};
@@ -363,7 +404,11 @@ AISAppView::AISAppView(NavigationView& nav) : nav_ { nav } {
}
AISAppView::~AISAppView() {
/* radio::disable(); */
// save app settings
app_settings.rx_frequency = target_frequency_;
settings.save("rx_ais", &app_settings);
receiver_model.disable(); // to switch off all, including DC bias.
baseband::shutdown();
+10 -2
View File
@@ -33,7 +33,7 @@
#include "event_m0.hpp"
#include "log_file.hpp"
#include "app_settings.hpp"
#include "ais_packet.hpp"
#include "lpc43xx_cpp.hpp"
@@ -127,6 +127,9 @@ public:
void focus() override;
void paint(Painter&) override;
AISRecentEntryDetailView(const AISRecentEntryDetailView&Entry);
AISRecentEntryDetailView &operator=(const AISRecentEntryDetailView&Entry);
private:
AISRecentEntry entry_ { };
@@ -163,13 +166,18 @@ public:
void focus() override;
std::string title() const override { return "AIS"; };
std::string title() const override { return "AIS Boats RX"; };
private:
static constexpr uint32_t initial_target_frequency = 162025000;
static constexpr uint32_t sampling_rate = 2457600;
static constexpr uint32_t baseband_bandwidth = 1750000;
// app save settings
std::app_settings settings { };
std::app_settings::AppSettings app_settings { };
NavigationView& nav_;
AISRecentEntries recent { };
+42 -18
View File
@@ -129,14 +129,26 @@ AnalogAudioView::AnalogAudioView(
&waterfall
});
//Filename Datetime and Frequency
record_view.set_filename_date_frequency(true);
field_frequency.set_value(receiver_model.tuning_frequency());
field_frequency.set_step(receiver_model.frequency_step());
// Set on_change before initialising the field
field_frequency.on_change = [this](rf::Frequency f) {
this->on_tuning_frequency_changed(f);
};
// load app settings
auto rc = settings.load("rx_audio", &app_settings);
if(rc == SETTINGS_OK) {
field_lna.set_value(app_settings.lna);
field_vga.set_value(app_settings.vga);
receiver_model.set_rf_amp(app_settings.rx_amp);
field_frequency.set_value(app_settings.rx_frequency);
receiver_model.set_configuration_without_init(static_cast<ReceiverModel::Mode>(app_settings.modulation), app_settings.step, app_settings.am_config_index, app_settings.nbfm_config_index, app_settings.wfm_config_index, app_settings.squelch);
}
else field_frequency.set_value(receiver_model.tuning_frequency());
//Filename Datetime and Frequency
record_view.set_filename_date_frequency(true);
field_frequency.set_step(receiver_model.frequency_step());
field_frequency.on_edit = [this, &nav]() {
// TODO: Provide separate modal method/scheme?
auto new_view = nav.push<FrequencyKeypadView>(receiver_model.tuning_frequency());
@@ -160,6 +172,7 @@ AnalogAudioView::AnalogAudioView(
const auto modulation = receiver_model.modulation();
options_modulation.set_by_value(toUType(modulation));
options_modulation.on_change = [this](size_t, OptionsField::value_t v) {
this->on_modulation_changed(static_cast<ReceiverModel::Mode>(v));
};
@@ -183,33 +196,47 @@ AnalogAudioView::AnalogAudioView(
audio::output::start();
update_modulation(static_cast<ReceiverModel::Mode>(modulation));
on_modulation_changed(static_cast<ReceiverModel::Mode>(modulation));
on_modulation_changed(static_cast<ReceiverModel::Mode>(modulation));
}
size_t AnalogAudioView::get_spec_bw_index() {
return spec_bw_index;
return spec_bw_index;
}
void AnalogAudioView::set_spec_bw(size_t index, uint32_t bw) {
spec_bw_index = index;
spec_bw = bw;
spec_bw_index = index;
spec_bw = bw;
baseband::set_spectrum(bw, spec_trigger);
receiver_model.set_sampling_rate(bw);
receiver_model.set_baseband_bandwidth(bw/2);
baseband::set_spectrum(bw, spec_trigger);
receiver_model.set_sampling_rate(bw);
receiver_model.set_baseband_bandwidth(bw/2);
}
uint16_t AnalogAudioView::get_spec_trigger() {
return spec_trigger;
return spec_trigger;
}
void AnalogAudioView::set_spec_trigger(uint16_t trigger) {
spec_trigger = trigger;
spec_trigger = trigger;
baseband::set_spectrum(spec_bw, spec_trigger);
baseband::set_spectrum(spec_bw, spec_trigger);
}
AnalogAudioView::~AnalogAudioView() {
// save app settings
app_settings.rx_frequency = field_frequency.value();
app_settings.lna = receiver_model.lna();
app_settings.vga = receiver_model.vga();
app_settings.rx_amp = receiver_model.rf_amp();
app_settings.step = receiver_model.frequency_step();
app_settings.modulation = (uint8_t)receiver_model.modulation();
app_settings.am_config_index = receiver_model.am_configuration();
app_settings.nbfm_config_index = receiver_model.nbfm_configuration();
app_settings.wfm_config_index = receiver_model.wfm_configuration();
app_settings.squelch = receiver_model.squelch_level();
settings.save("rx_audio", &app_settings);
// TODO: Manipulating audio codec here, and in ui_receiver.cpp. Good to do
// both?
audio::output::stop();
@@ -397,9 +424,6 @@ void AnalogAudioView::update_modulation(const ReceiverModel::Mode modulation) {
}
}
/*void AnalogAudioView::squelched() {
if (exit_on_squelch) nav_.pop();
}*/
void AnalogAudioView::handle_coded_squelch(const uint32_t value) {
float diff, min_diff = value;
+12 -7
View File
@@ -29,7 +29,7 @@
#include "ui_spectrum.hpp"
#include "ui_record_view.hpp"
#include "ui_font_fixed_8x16.hpp"
#include "app_settings.hpp"
#include "tone_key.hpp"
@@ -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 },
}
};
};
@@ -143,7 +144,7 @@ public:
void focus() override;
std::string title() const override { return "Analog audio"; };
std::string title() const override { return "Audio RX"; };
size_t get_spec_bw_index();
void set_spec_bw(size_t index, uint32_t bw);
@@ -154,6 +155,10 @@ public:
private:
static constexpr ui::Dim header_height = 3 * 16;
// app save settings
std::app_settings settings { };
std::app_settings::AppSettings app_settings { };
const Rect options_view_rect { 0 * 8, 1 * 16, 30 * 8, 1 * 16 };
const Rect nbfm_view_rect { 0 * 8, 1 * 16, 18 * 8, 1 * 16 };
+19 -4
View File
@@ -57,11 +57,23 @@ AnalogTvView::AnalogTvView(
&tv
});
field_frequency.set_value(receiver_model.tuning_frequency());
field_frequency.set_step(receiver_model.frequency_step());
// Set on_change before initialising the field
field_frequency.on_change = [this](rf::Frequency f) {
this->on_tuning_frequency_changed(f);
};
// load app settings
auto rc = settings.load("rx_tv", &app_settings);
if(rc == SETTINGS_OK) {
field_lna.set_value(app_settings.lna);
field_vga.set_value(app_settings.vga);
receiver_model.set_rf_amp(app_settings.rx_amp);
field_frequency.set_value(app_settings.rx_frequency);
}
else field_frequency.set_value(receiver_model.tuning_frequency());
field_frequency.set_step(receiver_model.frequency_step());
field_frequency.on_edit = [this, &nav]() {
// TODO: Provide separate modal method/scheme?
auto new_view = nav.push<FrequencyKeypadView>(receiver_model.tuning_frequency());
@@ -106,12 +118,15 @@ AnalogTvView::AnalogTvView(
}
AnalogTvView::~AnalogTvView() {
// save app settings
app_settings.rx_frequency = field_frequency.value();
settings.save("rx_tv", &app_settings);
// TODO: Manipulating audio codec here, and in ui_receiver.cpp. Good to do
// both?
audio::output::stop();
receiver_model.disable();
baseband::shutdown();
}
+6 -2
View File
@@ -29,7 +29,7 @@
#include "ui_receiver.hpp"
#include "ui_tv.hpp"
#include "ui_record_view.hpp"
#include "app_settings.hpp"
#include "ui_font_fixed_8x16.hpp"
#include "tone_key.hpp"
@@ -53,11 +53,15 @@ public:
void focus() override;
std::string title() const override { return "Analog TV"; };
std::string title() const override { return "Analog TV RX"; };
private:
static constexpr ui::Dim header_height = 3 * 16;
// app save settings
std::app_settings settings { };
std::app_settings::AppSettings app_settings { };
const Rect options_view_rect { 0 * 8, 1 * 16, 30 * 8, 1 * 16 };
const Rect nbfm_view_rect { 0 * 8, 1 * 16, 18 * 8, 1 * 16 };
+20 -3
View File
@@ -105,7 +105,20 @@ ERTAppView::ERTAppView(NavigationView&) {
&recent_entries_view,
});
radio::enable({
// load app settings
auto rc = settings.load("rx_ert", &app_settings);
if(rc == SETTINGS_OK) {
field_lna.set_value(app_settings.lna);
field_vga.set_value(app_settings.vga);
field_rf_amp.set_value(app_settings.rx_amp);
}
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({
initial_target_frequency,
sampling_rate,
baseband_bandwidth,
@@ -113,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 ) {
@@ -122,7 +135,11 @@ ERTAppView::ERTAppView(NavigationView&) {
}
ERTAppView::~ERTAppView() {
radio::disable();
// save app settings
settings.save("rx_ert", &app_settings);
receiver_model.disable(); // to switch off all, including DC bias and change flag enabled_
baseband::shutdown();
}
+7 -2
View File
@@ -28,7 +28,7 @@
#include "ui_channel.hpp"
#include "event_m0.hpp"
#include "app_settings.hpp"
#include "log_file.hpp"
#include "ert_packet.hpp"
@@ -125,12 +125,17 @@ public:
void focus() override;
std::string title() const override { return "ERT"; };
std::string title() const override { return "ERT Meter RX"; };
private:
ERTRecentEntries recent { };
std::unique_ptr<ERTLogger> logger { };
// app save settings
std::app_settings settings { };
std::app_settings::AppSettings app_settings { };
const RecentEntriesColumns columns { {
{ "ID", 10 },
{ "Tp", 2 },
+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() {
+1 -1
View File
@@ -44,7 +44,7 @@ public:
void set_parent_rect(const Rect new_parent_rect) override;
void focus() override;
std::string title() const override { return "GPS Simulator"; };
std::string title() const override { return "GPS Sim TX"; };
private:
NavigationView& nav_;
+56 -41
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"
@@ -39,12 +40,17 @@ using namespace portapack;
namespace ui {
void LGEView::focus() {
options_trame.focus();
options_frame.focus();
}
LGEView::~LGEView() {
// save app settings
app_settings.tx_frequency = transmitter_model.tuning_frequency();
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) {
@@ -70,10 +76,10 @@ void LGEView::generate_frame_touche() {
std::vector<uint8_t> data { 0x46, 0x28, 0x01, 0x45, 0x27, 0x01, 0x44, 0x23 };
console.write("\n\x1B\x07Touche:\x1B\x10");
generate_lge_frame(0x96, (field_joueur.value() << 8) | field_salle.value(), 0x0001, data);
generate_lge_frame(0x96, (field_player.value() << 8) | field_room.value(), 0x0001, data);
}
void LGEView::generate_frame_pseudo() {
void LGEView::generate_frame_nickname() {
// 0040.48s:
// 30 02 1A 00 19 00 FF 00 02 19 42 52 45 42 49 53 20 00 00 00 00 00 00 00 00 00
// 04 01 B0 04 7F 1F 11 33 40 1F 22 01 07 00 00 01 07 00 00 63 05 00 00 99 A2
@@ -90,15 +96,15 @@ void LGEView::generate_frame_pseudo() {
};
uint32_t c;
//data_header[2] = field_salle.value(); // ?
//data_footer[0] = field_salle.value(); // ?
//data_header[2] = field_room.value(); // ?
//data_footer[0] = field_room.value(); // ?
data.insert(data.begin(), data_header.begin(), data_header.end());
data.push_back(field_joueur.value());
data.push_back(field_player.value());
c = 0;
for (auto &ch : pseudo) {
for (auto &ch : nickname) {
data.push_back(ch);
c++;
}
@@ -108,16 +114,16 @@ void LGEView::generate_frame_pseudo() {
while (++c < 16)
data.push_back(0x00);
data.push_back(field_equipe.value());
data.push_back(field_team.value());
data.insert(data.end(), data_footer.begin(), data_footer.end());
console.write("\n\x1B\x0ESet pseudo:\x1B\x10");
console.write("\n\x1B\x0ESet nickname:\x1B\x10");
generate_lge_frame(0x02, 0x001A, field_joueur.value(), data);
generate_lge_frame(0x02, 0x001A, field_player.value(), data);
}
void LGEView::generate_frame_equipe() {
void LGEView::generate_frame_team() {
// 0041.83s:
// 3D 03 FF FF FF FF 02 03 01 52 4F 55 47 45 00 00 00 00 00 00 00 00 00 00 00 00
// 02 56 45 52 54 45 00 00 00 00 00 00 00 00 00 00 00 01 03 42 4C 45 55 45 00 00
@@ -129,10 +135,10 @@ void LGEView::generate_frame_equipe() {
data.insert(data.begin(), data_header.begin(), data_header.end());
data.push_back(field_equipe.value());
data.push_back(field_team.value());
c = 0;
for (auto &ch : pseudo) {
for (auto &ch : nickname) {
data.push_back(ch);
c++;
}
@@ -140,14 +146,14 @@ void LGEView::generate_frame_equipe() {
while (c++ < 16)
data.push_back(0x00);
data.push_back(field_equipe.value() - 1); // Color ?
data.push_back(field_team.value() - 1); // Color ?
console.write("\n\x1B\x0ASet equipe:\x1B\x10");
console.write("\n\x1B\x0ASet team:\x1B\x10");
generate_lge_frame(0x03, data);
}
void LGEView::generate_frame_broadcast_pseudo() {
void LGEView::generate_frame_broadcast_nickname() {
// 0043.86s:
// 3D 04 FF FF FF FF 02 03 19 42 52 45 42 49 53 20 00 00 00 00 00 00 00 00 00 04
// 07 50 4F 4E 45 59 20 00 00 00 00 00 00 00 00 00 00 05 1B 41 42 42 59 20 00 00
@@ -159,10 +165,10 @@ void LGEView::generate_frame_broadcast_pseudo() {
data.insert(data.begin(), data_header.begin(), data_header.end());
data.push_back(field_joueur.value());
data.push_back(field_player.value());
c = 0;
for (auto &ch : pseudo) {
for (auto &ch : nickname) {
data.push_back(ch);
c++;
}
@@ -172,9 +178,9 @@ void LGEView::generate_frame_broadcast_pseudo() {
while (++c < 16)
data.push_back(0x00);
data.push_back(field_equipe.value());
data.push_back(field_team.value());
console.write("\n\x1B\x09" "Broadcast pseudo:\x1B\x10");
console.write("\n\x1B\x09" "Broadcast nickname:\x1B\x10");
generate_lge_frame(0x04, data);
}
@@ -184,14 +190,14 @@ void LGEView::generate_frame_start() {
// 0A 05 FF FF FF FF 02 EC FF FF FF A3 35
std::vector<uint8_t> data { 0x02, 0xEC, 0xFF, 0xFF, 0xFF };
//data[0] = field_salle.value(); // ?
//data[0] = field_room.value(); // ?
console.write("\n\x1B\x0DStart:\x1B\x10");
generate_lge_frame(0x05, data);
}
void LGEView::generate_frame_gameover() {
std::vector<uint8_t> data { (uint8_t)field_salle.value() };
std::vector<uint8_t> data { (uint8_t)field_room.value() };
console.write("\n\x1B\x0CGameover:\x1B\x10");
generate_lge_frame(0x0D, data);
@@ -203,7 +209,7 @@ void LGEView::generate_frame_collier() {
// Custom
// 0C 00 13 37 13 37 id flags channel playerid zapduty zaptime checksum CRC CRC
// channel: field_channel
// playerid: field_joueur
// playerid: field_player
// zapduty: field_power
// zaptime: field_duration
@@ -218,8 +224,8 @@ void LGEView::generate_frame_collier() {
std::vector<uint8_t> data {
id,
flags,
(uint8_t)field_salle.value(),
(uint8_t)field_joueur.value(),
(uint8_t)field_room.value(),
(uint8_t)field_player.value(),
(uint8_t)field_power.value(),
(uint8_t)(field_duration.value() * 10)
};
@@ -285,11 +291,11 @@ LGEView::LGEView(NavigationView& nav) {
add_children({
&labels,
&options_trame,
&field_salle,
&button_texte,
&field_equipe,
&field_joueur,
&options_frame,
&field_room,
&button_text,
&field_team,
&field_player,
&field_id,
&field_power,
&field_duration,
@@ -300,20 +306,29 @@ LGEView::LGEView(NavigationView& nav) {
&tx_view
});
field_salle.set_value(1);
field_equipe.set_value(1);
field_joueur.set_value(1);
// load app settings
auto rc = settings.load("tx_lge", &app_settings);
if(rc == SETTINGS_OK) {
transmitter_model.set_rf_amp(app_settings.tx_amp);
transmitter_model.set_channel_bandwidth(app_settings.channel_bandwidth);
transmitter_model.set_tuning_frequency(app_settings.tx_frequency);
transmitter_model.set_tx_gain(app_settings.tx_gain);
}
field_room.set_value(1);
field_team.set_value(1);
field_player.set_value(1);
field_id.set_value(1);
field_power.set_value(1);
field_duration.set_value(2);
button_texte.on_select = [this, &nav](Button&) {
button_text.on_select = [this, &nav](Button&) {
text_prompt(
nav,
pseudo,
nickname,
15,
[this](std::string& buffer) {
button_texte.set_text(buffer);
button_text.set_text(buffer);
});
};
@@ -326,15 +341,15 @@ LGEView::LGEView(NavigationView& nav) {
tx_view.on_start = [this]() {
if (tx_mode == IDLE) {
auto i = options_trame.selected_index_value();
auto i = options_frame.selected_index_value();
if (i == 0)
generate_frame_touche();
else if (i == 1)
generate_frame_pseudo();
generate_frame_nickname();
else if (i == 2)
generate_frame_equipe();
generate_frame_team();
else if (i == 3)
generate_frame_broadcast_pseudo();
generate_frame_broadcast_nickname();
else if (i == 4)
generate_frame_start();
else if (i == 5)
+28 -23
View File
@@ -30,6 +30,7 @@
#include "message.hpp"
#include "transmitter_model.hpp"
#include "portapack.hpp"
#include "app_settings.hpp"
namespace ui {
@@ -40,7 +41,7 @@ public:
void focus() override;
std::string title() const override { return "LGE tool"; };
std::string title() const override { return "LGE tool TX"; };
private:
enum tx_modes {
@@ -48,15 +49,19 @@ private:
SINGLE,
ALL
};
// app save settings
std::app_settings settings { };
std::app_settings::AppSettings app_settings { };
tx_modes tx_mode = IDLE;
RFM69 rfm69 { 5, 0x2DD4, true, true };
RFM69 rfm69 { 5, 0x2DD4, true, true };
uint32_t frame_size { 0 };
uint32_t repeats { 0 };
uint32_t channel_index { 0 };
std::string pseudo { "ABCDEF" };
std::string nickname { "ABCDEF" };
rf::Frequency channels[3] = { 868067000, 868183000, 868295000 };
@@ -68,9 +73,9 @@ private:
}
void generate_lge_frame(const uint8_t command, const uint16_t address_a, const uint16_t address_b, std::vector<uint8_t>& data);
void generate_frame_touche();
void generate_frame_pseudo();
void generate_frame_equipe();
void generate_frame_broadcast_pseudo();
void generate_frame_nickname();
void generate_frame_team();
void generate_frame_broadcast_nickname();
void generate_frame_start();
void generate_frame_gameover();
void generate_frame_collier();
@@ -79,28 +84,28 @@ private:
Labels labels {
//{ { 7 * 8, 1 * 8 }, "NO FUN ALLOWED !", Color::red() },
{ { 1 * 8, 1 * 8 }, "Trame:", Color::light_grey() },
{ { 1 * 8, 3 * 8 }, "Salle:", Color::light_grey() },
{ { 14 * 8, 3 * 8 }, "Texte:", Color::light_grey() },
{ { 0 * 8, 5 * 8 }, "Equipe:", Color::light_grey() },
{ { 0 * 8, 7 * 8 }, "Joueur:", Color::light_grey() },
{ { 0 * 8, 10 * 8 }, "Collier:", Color::light_grey() },
{ { 1 * 8, 1 * 8 }, "Frame:", Color::light_grey() },
{ { 2 * 8, 3 * 8 }, "Room:", Color::light_grey() },
{ { 14 * 8, 3 * 8 }, "Text:", Color::light_grey() },
{ { 2 * 8, 5 * 8 }, "Team:", Color::light_grey() },
{ { 0 * 8, 7 * 8 }, "Player:", Color::light_grey() },
{ { 0 * 8, 10 * 8 }, "Vest:", Color::light_grey() },
{ { 4 * 8, 12 * 8 }, "ID:", Color::light_grey() },
{ { 3 * 8, 14 * 8 }, "Pow: /10", Color::light_grey() },
{ { 1 * 8, 16 * 8 }, "Duree: x100ms", Color::light_grey() }
{ { 2 * 8, 16 * 8 }, "Time: x100ms", Color::light_grey() }
};
OptionsField options_trame {
OptionsField options_frame {
{ 7 * 8, 1 * 8 },
13,
{
{ "Touche", 0 },
{ "Set pseudo", 1 },
{ "Set equipe", 2 },
{ "Brdcst pseudo", 3 },
{ "Key", 0 },
{ "Set nickname", 1 },
{ "Set team", 2 },
{ "Brdcst nick", 3 },
{ "Start", 4 },
{ "Game over", 5 },
{ "Set collier", 6 }
{ "Set vest", 6 }
}
};
@@ -111,7 +116,7 @@ private:
true
};
NumberField field_salle {
NumberField field_room {
{ 7 * 8, 3 * 8 },
1,
{ 1, 2 },
@@ -119,12 +124,12 @@ private:
'0'
};
Button button_texte {
Button button_text {
{ 14 * 8, 5 * 8, 16 * 8, 3 * 8 },
"ABCDEF"
};
NumberField field_equipe {
NumberField field_team {
{ 7 * 8, 5 * 8 },
1,
{ 1, 6 },
@@ -132,7 +137,7 @@ private:
'0'
};
NumberField field_joueur {
NumberField field_player {
{ 7 * 8, 7 * 8 },
2,
{ 1, 50 },
+22 -4
View File
@@ -77,15 +77,28 @@ POCSAGAppView::POCSAGAppView(NavigationView& nav) {
&console
});
// Set on_change before initialising the field
field_frequency.on_change = [this](rf::Frequency f) {
update_freq(f);
};
// load app settings
auto rc = settings.load("rx_pocsag", &app_settings);
if(rc == SETTINGS_OK) {
field_lna.set_value(app_settings.lna);
field_vga.set_value(app_settings.vga);
field_rf_amp.set_value(app_settings.rx_amp);
field_frequency.set_value(app_settings.rx_frequency);
}
else field_frequency.set_value(receiver_model.tuning_frequency());
receiver_model.set_modulation(ReceiverModel::Mode::NarrowbandFMAudio);
receiver_model.set_sampling_rate(3072000);
receiver_model.set_baseband_bandwidth(1750000);
receiver_model.enable();
field_frequency.set_value(receiver_model.tuning_frequency());
field_frequency.set_step(receiver_model.frequency_step());
field_frequency.on_change = [this](rf::Frequency f) {
update_freq(f);
};
field_frequency.on_edit = [this, &nav]() {
// TODO: Provide separate modal method/scheme?
auto new_view = nav.push<FrequencyKeypadView>(receiver_model.tuning_frequency());
@@ -127,6 +140,11 @@ POCSAGAppView::POCSAGAppView(NavigationView& nav) {
}
POCSAGAppView::~POCSAGAppView() {
// save app settings
app_settings.rx_frequency = field_frequency.value();
settings.save("rx_pocsag", &app_settings);
audio::output::stop();
// Save ignored address
+5 -1
View File
@@ -28,7 +28,7 @@
#include "ui_rssi.hpp"
#include "log_file.hpp"
#include "app_settings.hpp"
#include "pocsag.hpp"
#include "pocsag_packet.hpp"
@@ -60,6 +60,10 @@ public:
private:
static constexpr uint32_t initial_target_frequency = 466175000;
// app save settings
std::app_settings settings { };
std::app_settings::AppSettings app_settings { };
bool logging { true };
bool ignore { true };
uint32_t last_address = 0xFFFFFFFF;
+17 -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"
@@ -201,6 +201,16 @@ ReplayAppView::ReplayAppView(
tx_gain = 35;field_rfgain.set_value(tx_gain); // Initial default value (-12 dB's max ).
field_rfamp.set_value(rf_amp ? 14 : 0); // Initial default value True. (TX RF amp on , +14dB's)
field_rfamp.on_change = [this](int32_t v) { // allow initial value change just after opened file.
rf_amp = (bool)v;
};
field_rfamp.set_value(rf_amp ? 14 : 0);
field_rfgain.on_change = [this](int32_t v) { // allow initial value change just after opened file.
tx_gain = v;
};
field_rfgain.set_value(tx_gain);
baseband::run_image(portapack::spi_flash::image_tag_replay);
add_children({
@@ -248,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() {
+17 -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
@@ -240,6 +242,15 @@ SoundBoardView::SoundBoardView(
&button_next_page,
&tx_view
});
// load app settings
auto rc = settings.load("tx_soundboard", &app_settings);
if(rc == SETTINGS_OK) {
transmitter_model.set_rf_amp(app_settings.tx_amp);
transmitter_model.set_channel_bandwidth(app_settings.channel_bandwidth);
transmitter_model.set_tuning_frequency(app_settings.tx_frequency);
transmitter_model.set_tx_gain(app_settings.tx_gain);
}
refresh_list();
@@ -280,9 +291,14 @@ SoundBoardView::SoundBoardView(
}
SoundBoardView::~SoundBoardView() {
// save app settings
app_settings.tx_frequency = transmitter_model.tuning_frequency();
settings.save("tx_soundboard", &app_settings);
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.
}
}
+6 -1
View File
@@ -30,6 +30,7 @@
#include "lfsr_random.hpp"
#include "io_wave.hpp"
#include "tone_key.hpp"
#include "app_settings.hpp"
namespace ui {
@@ -45,10 +46,14 @@ public:
void focus() override;
std::string title() const override { return "Soundboard"; };
std::string title() const override { return "Soundboard TX"; };
private:
NavigationView& nav_;
// app save settings
std::app_settings settings { };
std::app_settings::AppSettings app_settings { };
enum tx_modes {
NORMAL = 0,
+24 -3
View File
@@ -151,7 +151,22 @@ TPMSAppView::TPMSAppView(NavigationView&) {
&options_type,
});
radio::enable({
// load app settings
auto rc = settings.load("rx_tpms", &app_settings);
if(rc == SETTINGS_OK) {
field_lna.set_value(app_settings.lna);
field_vga.set_value(app_settings.vga);
field_rf_amp.set_value(app_settings.rx_amp);
options_band.set_by_value(app_settings.rx_frequency);
}
else options_band.set_by_value(receiver_model.tuning_frequency());
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,
@@ -159,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);
@@ -184,7 +199,13 @@ TPMSAppView::TPMSAppView(NavigationView&) {
}
TPMSAppView::~TPMSAppView() {
radio::disable();
// save app settings
app_settings.rx_frequency = target_frequency_;
settings.save("rx_tpms", &app_settings);
receiver_model.disable(); // to switch off all, including DC bias and change flag enabled_
baseband::shutdown();
}
+6 -2
View File
@@ -27,7 +27,7 @@
#include "ui_receiver.hpp"
#include "ui_rssi.hpp"
#include "ui_channel.hpp"
#include "app_settings.hpp"
#include "event_m0.hpp"
#include "log_file.hpp"
@@ -103,13 +103,17 @@ public:
void focus() override;
std::string title() const override { return "TPMS"; };
std::string title() const override { return "TPMS Cars RX"; };
private:
static constexpr uint32_t initial_target_frequency = 315000000;
static constexpr uint32_t sampling_rate = 2457600;
static constexpr uint32_t baseband_bandwidth = 1750000;
// app save settings
std::app_settings settings { };
std::app_settings::AppSettings app_settings { };
MessageHandlerRegistration message_handler_packet {
Message::ID::TPMSPacket,
[this](Message* const p) {
@@ -38,7 +38,7 @@ namespace ui
console.writeln("Brumi-2021,texasyojimbo");
console.writeln("heurist1,intoxsick,ckuethe");
console.writeln("notpike,jLynx,zigad");
console.writeln("MichalLeonBorsuk");
console.writeln("MichalLeonBorsuk,jimilinuxguy");
console.writeln("");
break;
+134 -61
View File
@@ -46,10 +46,10 @@ void RecentEntriesTable<AircraftRecentEntries>::draw(
auto entry_age = entry.age;
// Color decay for flights not being updated anymore
if (entry_age < ADSB_DECAY_A) {
if (entry_age < ADSB_CURRENT) {
aged_color = 0x10;
target_color = Color::green();
} else if (entry_age < ADSB_DECAY_B) {
} else if (entry_age < ADSB_RECENT) {
aged_color = 0x07;
target_color = Color::light_grey();
} else {
@@ -59,21 +59,13 @@ void RecentEntriesTable<AircraftRecentEntries>::draw(
std::string entry_string = "\x1B";
entry_string += aged_color;
#if false
entry_string += to_string_hex(entry.ICAO_address, 6) + " " +
entry.callsign + " " +
(entry.hits <= 999 ? to_string_dec_uint(entry.hits, 4) : "999+") + " " +
entry.time_string;
#else
// SBT
entry_string +=
(entry.callsign[0]!=' ' ? entry.callsign + " " : to_string_hex(entry.ICAO_address, 6) + " ") +
to_string_dec_uint((unsigned int)((entry.pos.altitude+50)/100),4) +
(entry.callsign[0]!=' ' ? entry.callsign + " " : entry.icaoStr + " ") +
to_string_dec_uint((unsigned int)(entry.pos.altitude/100),4) +
to_string_dec_uint((unsigned int)entry.velo.speed,4) +
to_string_dec_uint((unsigned int)(entry.amp>>9),4) + " " +
(entry.hits <= 999 ? to_string_dec_uint(entry.hits, 3) + " " : "1k+ ") +
to_string_dec_uint(entry.age, 4);
#endif
painter.draw_string(
target_rect.location(),
@@ -124,8 +116,6 @@ ADSBRxAircraftDetailsView::ADSBRxAircraftDetailsView(
});
std::unique_ptr<ADSBLogger> logger { };
//update(entry_copy);
icao_code = to_string_hex(entry_copy.ICAO_address, 6);
text_icao_address.set(to_string_hex(entry_copy.ICAO_address, 6));
@@ -225,7 +215,10 @@ void ADSBRxDetailsView::update(const AircraftRecentEntry& entry) {
text_frame_pos_odd.set(to_string_hex_array(entry_copy.frame_pos_odd.get_raw_data(), 14));
if (send_updates)
{
geomap_view->update_tag(trimr(entry.callsign[0]!=' ' ? entry.callsign : to_string_hex(entry.ICAO_address, 6)));
geomap_view->update_position(entry_copy.pos.latitude, entry_copy.pos.longitude, entry_copy.velo.heading, entry_copy.pos.altitude);
}
}
ADSBRxDetailsView::~ADSBRxDetailsView() {
@@ -277,19 +270,14 @@ ADSBRxDetailsView::ADSBRxDetailsView(
text_icao_address.set(to_string_hex(entry_copy.ICAO_address, 6));
button_aircraft_details.on_select = [this, &nav](Button&) {
//detailed_entry_key = entry.key();
aircraft_details_view = nav.push<ADSBRxAircraftDetailsView>(
entry_copy,
[this]() {
send_updates = false;
});
aircraft_details_view = nav.push<ADSBRxAircraftDetailsView>(entry_copy, [this]() { send_updates = false;});
send_updates = false;
};
button_see_map.on_select = [this, &nav](Button&) {
if (!send_updates) { // Prevent recursively launching the map
geomap_view = nav.push<GeoMapView>(
entry_copy.callsign,
trimr(entry_copy.callsign[0]!=' ' ? entry_copy.callsign : entry_copy.icaoStr),
entry_copy.pos.altitude,
GeoPos::alt_unit::FEET,
entry_copy.pos.latitude,
@@ -309,8 +297,13 @@ void ADSBRxView::focus() {
}
ADSBRxView::~ADSBRxView() {
receiver_model.set_tuning_frequency(prevFreq);
receiver_model.set_tuning_frequency(prevFreq); // Restore previous frequency on exit
// save app settings
settings.save("rx_adsb", &app_settings);
//TODO: once all apps keep there own settin previous frequency logic can be removed
receiver_model.set_tuning_frequency(prevFreq);
rtc_time::signal_tick_second -= signal_token_tick_second;
receiver_model.disable();
baseband::shutdown();
@@ -322,8 +315,6 @@ AircraftRecentEntry ADSBRxView::find_or_create_entry(uint32_t ICAO_address) {
// If not found
if (it == std::end(recent)){
recent.emplace_front(ICAO_address); // Add it
truncate_entries(recent); // Truncate the list
sort_entries_by_state();
it = find(recent, ICAO_address); // Find it again
}
return *it;
@@ -338,6 +329,21 @@ void ADSBRxView::replace_entry(AircraftRecentEntry & entry)
entry);
}
void ADSBRxView::remove_old_entries()
{
auto it = recent.rbegin();
auto end = recent.rend();
while (it != end)
{
if (it->age_state>=4) {
std::advance(it, 1);
recent.erase( it.base() );
} else {
break; // stop looking because the list is sorted
}
}
}
void ADSBRxView::sort_entries_by_state()
{
// Sorting List pn age_state using lambda function as comparator
@@ -345,8 +351,8 @@ void ADSBRxView::sort_entries_by_state()
}
void ADSBRxView::on_frame(const ADSBFrameMessage * message) {
logger = std::make_unique<ADSBLogger>();
rtc::RTC datetime;
std::string str_timestamp;
std::string callsign;
std::string str_info;
std::string logentry;
@@ -361,16 +367,16 @@ void ADSBRxView::on_frame(const ADSBFrameMessage * message) {
entry.reset_age();
if (entry.hits==0)
{
entry.amp = message->amp;
entry.amp = message->amp; // Store amplitude on first hit
} else {
entry.amp = ((entry.amp*15)+message->amp)>>4;
entry.amp = ((entry.amp*15)+message->amp)>>4; // Update smoothed amplitude on updates
}
str_timestamp = to_string_datetime(datetime, HMS);
entry.set_time_string(str_timestamp);
entry.inc_hit();
logentry += to_string_hex_array(frame.get_raw_data(), 14) + " ";
logentry += "ICAO:" + to_string_hex(ICAO_address, 6) + " ";
if (logger) {
logentry += to_string_hex_array(frame.get_raw_data(), 14) + " ";
logentry += "ICAO:" + entry.icaoStr + " ";
}
if (frame.get_DF() == DF_ADSB) {
uint8_t msg_type = frame.get_msg_type();
@@ -381,7 +387,9 @@ void ADSBRxView::on_frame(const ADSBFrameMessage * message) {
if ((msg_type >= AIRCRAFT_ID_L) && (msg_type <= AIRCRAFT_ID_H)) {
callsign = decode_frame_id(frame);
entry.set_callsign(callsign);
logentry+=callsign+" ";
if (logger) {
logentry+=callsign+" ";
}
}
// 9:
// 18: { // Extended squitter/non-transponder
@@ -396,30 +404,33 @@ void ADSBRxView::on_frame(const ADSBFrameMessage * message) {
" Lat:" + to_string_decimal(entry.pos.latitude, 2) +
" Lon:" + to_string_decimal(entry.pos.longitude, 2);
// printing the coordinates in the log file with more
// resolution, as we are not constrained by screen
// real estate there:
std::string log_info = "Alt:" + to_string_dec_int(entry.pos.altitude) +
" Lat:" + to_string_decimal(entry.pos.latitude, 7) +
" Lon:" + to_string_decimal(entry.pos.longitude, 7);
entry.set_info_string(str_info);
logentry+=log_info + " ";
if (logger) {
// printing the coordinates in the log file with more
// resolution, as we are not constrained by screen
// real estate there:
std::string log_info = "Alt:" + to_string_dec_int(entry.pos.altitude) +
" Lat:" + to_string_decimal(entry.pos.latitude, 7) +
" Lon:" + to_string_decimal(entry.pos.longitude, 7);
logentry+=log_info + " ";
}
}
} else if(msg_type == AIRBORNE_VEL && msg_sub >= VEL_GND_SUBSONIC && msg_sub <= VEL_AIR_SUPERSONIC){
entry.set_frame_velo(frame);
logentry += "Type:" + to_string_dec_uint(msg_sub) +
" Hdg:" + to_string_dec_uint(entry.velo.heading) +
" Spd: "+ to_string_dec_int(entry.velo.speed);
if (logger) {
logentry += "Type:" + to_string_dec_uint(msg_sub) +
" Hdg:" + to_string_dec_uint(entry.velo.heading) +
" Spd: "+ to_string_dec_int(entry.velo.speed);
}
}
}
replace_entry(entry);
} // frame.get_DF() == DF_ADSB
replace_entry(entry);
logger = std::make_unique<ADSBLogger>();
if (logger) {
logger->append(u"adsb.txt");
// will log each frame in format:
@@ -429,20 +440,69 @@ void ADSBRxView::on_frame(const ADSBFrameMessage * message) {
}
}
void ADSBRxView::on_tick_second() {
// Decay and refresh if needed
for (auto& entry : recent) {
entry.inc_age();
if (details_view) {
if (send_updates && (entry.key() == detailed_entry_key)) // Check if the ICAO address match
details_view->update(entry);
void ADSBRxView::on_tick_second() {
if (recent.size() <= 16){ // Not many entries update everything (16 is one screen full)
updateDetailsAndMap(1);
updateRecentEntries();
} else if (updateState==0) { // Even second
updateState = 1;
updateDetailsAndMap(2);
} else { // Odd second only performed when there are many entries
updateState = 0;
updateRecentEntries();
}
}
void ADSBRxView::updateDetailsAndMap(int ageStep) {
ui::GeoMarker marker;
bool storeNewMarkers = false;
// Sort and truncate the entries, grouped, newest group first
sort_entries_by_state();
truncate_entries(recent);
remove_old_entries();
// Calculate if it is time to update markers
if (send_updates && details_view && details_view->geomap_view) {
ticksSinceMarkerRefresh += ageStep;
if (ticksSinceMarkerRefresh >= MARKER_UPDATE_SECONDS) { // Update other aircraft every few seconds
storeNewMarkers = true;
ticksSinceMarkerRefresh=0;
}
} else {
ticksSinceMarkerRefresh = MARKER_UPDATE_SECONDS; // Send the markers as soon as the geoview exists
}
// Sort the list if it is being displayed
if (!send_updates) {
sort_entries_by_state();
// Increment age, and pass updates to the details and map
const bool otherMarkersCanBeSent = send_updates && storeNewMarkers && details_view && details_view->geomap_view; // Save retesting all of this
MapMarkerStored markerStored = MARKER_NOT_STORED;
if (otherMarkersCanBeSent) {details_view->geomap_view->clear_markers();}
// Loop through all entries
for (auto& entry : recent) {
entry.inc_age(ageStep);
// Only if there is a details view
if (send_updates && details_view) {
if (entry.key() == detailed_entry_key) // Check if the ICAO address match
{
details_view->update(entry);
}
// Store if the view is present and the list isn't full
else if (otherMarkersCanBeSent && (markerStored != MARKER_LIST_FULL) && entry.pos.valid && (entry.age_state<=2))
{
marker.lon = entry.pos.longitude;
marker.lat = entry.pos.latitude;
marker.angle = entry.velo.heading;
marker.tag = trimr(entry.callsign[0]!=' ' ? entry.callsign : entry.icaoStr);
markerStored = details_view->geomap_view->store_marker(marker);
}
}
} // Loop through all entries, if only to update the age
}
void ADSBRxView::updateRecentEntries() {
// Redraw the list of aircraft
if (!send_updates){
recent_entries_view.set_dirty();
}
}
@@ -458,6 +518,21 @@ ADSBRxView::ADSBRxView(NavigationView& nav) {
&recent_entries_view
});
// load app settings
auto rc = settings.load("rx_adsb", &app_settings);
if(rc == SETTINGS_OK) {
field_lna.set_value(app_settings.lna);
field_vga.set_value(app_settings.vga);
field_rf_amp.set_value(app_settings.rx_amp);
}
else
{
field_lna.set_value(40);
field_vga.set_value(40);
}
recent_entries_view.set_parent_rect({ 0, 16, 240, 272 });
recent_entries_view.on_select = [this, &nav](const AircraftRecentEntry& entry) {
detailed_entry_key = entry.key();
@@ -473,13 +548,11 @@ ADSBRxView::ADSBRxView(NavigationView& nav) {
on_tick_second();
};
prevFreq = receiver_model.tuning_frequency();
prevFreq = receiver_model.tuning_frequency(); // Store previous frequency on creation
baseband::set_adsb();
receiver_model.set_tuning_frequency(1090000000);
field_lna.set_value(40);
field_vga.set_value(40);
receiver_model.set_modulation(ReceiverModel::Mode::SpectrumAnalysis);
receiver_model.set_sampling_rate(2000000);
receiver_model.set_baseband_bandwidth(2500000);
+31 -29
View File
@@ -25,6 +25,7 @@
#include "ui_receiver.hpp"
#include "ui_geomap.hpp"
#include "ui_font_fixed_8x16.hpp"
#include "string_format.hpp"
#include "file.hpp"
#include "database.hpp"
@@ -32,16 +33,16 @@
#include "log_file.hpp"
#include "adsb.hpp"
#include "message.hpp"
#include "app_settings.hpp"
#include "crc.hpp"
using namespace adsb;
namespace ui {
#define ADSB_DECAY_A 10 // In seconds
#define ADSB_DECAY_B 30
#define ADSB_DECAY_C 60 // Can be used for removing old entries, RecentEntries already caps to 64
#define ADSB_CURRENT 10 // Seconds
#define ADSB_RECENT 30 // Seconds
#define ADSB_REMOVE 300 // Used for removing old entries
#define AIRCRAFT_ID_L 1 // aircraft ID message type (lowest type id)
#define AIRCRAFT_ID_H 4 // aircraft ID message type (highest type id)
@@ -83,14 +84,15 @@ struct AircraftRecentEntry {
ADSBFrame frame_pos_even { };
ADSBFrame frame_pos_odd { };
std::string icaoStr {" "};
std::string callsign { " " };
std::string time_string { "" };
std::string info_string { "" };
AircraftRecentEntry(
const uint32_t ICAO_address
) : ICAO_address { ICAO_address }
{
this->icaoStr = to_string_hex(ICAO_address, 6);
}
Key key() const {
@@ -125,23 +127,20 @@ struct AircraftRecentEntry {
info_string = new_info_string;
}
void set_time_string(std::string& new_time_string) {
time_string = new_time_string;
}
void reset_age() {
age = 0;
}
void inc_age() {
age++;
if (age < ADSB_DECAY_A)
{
void inc_age(int delta) {
age+=delta;
if (age < ADSB_CURRENT){
age_state = pos.valid ? 0 : 1;
}
else
{
age_state = (age < ADSB_DECAY_B) ? 2 : 3;
} else if(age < ADSB_RECENT){
age_state = 2;
} else if(age < ADSB_REMOVE){
age_state = 3;
} else{
age_state = 4;
}
}
};
@@ -184,7 +183,7 @@ private:
AircraftRecentEntry entry_copy { 0 };
std::function<void(void)> on_close_ { };
bool send_updates { false };
std::database db;
std::database db = { };
std::string icao_code = "";
int return_code = 0;
@@ -273,13 +272,13 @@ public:
std::database::AirlinesDBRecord airline_record = {};
GeoMapView* geomap_view { nullptr };
private:
AircraftRecentEntry entry_copy { 0 };
std::function<void(void)> on_close_ { };
GeoMapView* geomap_view { nullptr };
ADSBRxAircraftDetailsView* aircraft_details_view { nullptr };
bool send_updates { false };
std::database db;
std::database db = { };
std::string airline_code = "";
int return_code = 0;
@@ -361,32 +360,35 @@ public:
void focus() override;
std::string title() const override { return "ADS-B receive"; };
std::string title() const override { return "ADS-B RX"; };
void replace_entry(AircraftRecentEntry & entry);
void remove_old_entries();
AircraftRecentEntry find_or_create_entry(uint32_t ICAO_address);
void sort_entries_by_state();
private:
rf::Frequency prevFreq;
rf::Frequency prevFreq = { 0 };
std::unique_ptr<ADSBLogger> logger { };
void on_frame(const ADSBFrameMessage * message);
void on_tick_second();
int updateState = { 0 };
void updateRecentEntries();
void updateDetailsAndMap(int ageStep);
#define MARKER_UPDATE_SECONDS (5)
int ticksSinceMarkerRefresh { MARKER_UPDATE_SECONDS-1 };
// app save settings
std::app_settings settings { };
std::app_settings::AppSettings app_settings { };
const RecentEntriesColumns columns { {
#if false
{ "ICAO", 6 },
{ "Callsign", 9 },
{ "Hits", 4 },
{ "Time", 8 }
#else
{ "ICAO/Call", 9 },
{ "Lvl", 3 },
{ "Spd", 3 },
{ "Amp", 3 },
{ "Hit", 3 },
{ "Age", 4 }
#endif
} };
AircraftRecentEntries recent { };
RecentEntriesView<RecentEntries<AircraftRecentEntry>> recent_entries_view { columns, recent };
+25 -7
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>
@@ -161,13 +162,16 @@ ADSBSpeedView::ADSBSpeedView(
add_children({
&labels_speed,
&labels_vert_rate,
&compass,
&field_angle,
&field_speed
&field_speed,
&field_vert_rate
});
field_angle.set_value(0);
field_speed.set_value(400);
field_vert_rate.set_value(0);
field_angle.on_change = [this](int32_t v) {
compass.set_value(v);
@@ -180,7 +184,7 @@ void ADSBSpeedView::collect_frames(const uint32_t ICAO_address, std::vector<ADSB
ADSBFrame temp_frame;
encode_frame_velo(temp_frame, ICAO_address, field_speed.value(),
field_angle.value(), 0); // TODO: v_rate
field_angle.value(), field_vert_rate.value()); // Added v_rate , ft/min , (+) climb , (-) descend .
frame_list.emplace_back(temp_frame);
}
@@ -203,7 +207,7 @@ void ADSBSquawkView::collect_frames(const uint32_t ICAO_address, std::vector<ADS
ADSBFrame temp_frame;
(void)ICAO_address;
encode_frame_squawk(temp_frame, field_squawk.value_dec_u32());
encode_frame_squawk(temp_frame, field_squawk.concatenate_4_octal_u16());
frame_list.emplace_back(temp_frame);
}
@@ -284,9 +288,15 @@ void ADSBTxView::focus() {
}
ADSBTxView::~ADSBTxView() {
// save app settings
app_settings.tx_frequency = transmitter_model.tuning_frequency();
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();
@@ -334,8 +344,16 @@ ADSBTxView::ADSBTxView(
&view_squawk,
&text_frame,
&tx_view
});
});
// load app settings
auto rc = settings.load("tx_adsb", &app_settings);
if(rc == SETTINGS_OK) {
transmitter_model.set_tuning_frequency(app_settings.tx_frequency);
transmitter_model.set_rf_amp(app_settings.tx_amp);
transmitter_model.set_tx_gain(app_settings.tx_gain);
}
tx_view.on_edit_frequency = [this, &nav]() {
auto new_view = nav.push<FrequencyKeypadView>(receiver_model.tuning_frequency());
new_view->on_changed = [this](rf::Frequency f) {
+14 -1
View File
@@ -28,6 +28,7 @@
#include "ui_transmitter.hpp"
#include "message.hpp"
#include "transmitter_model.hpp"
#include "app_settings.hpp"
#include "portapack.hpp"
using namespace adsb;
@@ -95,6 +96,10 @@ private:
{ { 1 * 8, 6 * 16 }, "Speed: kn Bearing: *", Color::light_grey() }
};
Labels labels_vert_rate {
{ { 1 * 8, 8 * 16 }, "Vert. rate: ft/min, (+/-)", Color::light_grey() }
};
Compass compass {
{ 21 * 8, 2 * 16 }
};
@@ -106,6 +111,10 @@ private:
NumberField field_speed {
{ 8 * 8, 6 * 16 }, 3, { 0, 999 }, 5, ' '
};
NumberField field_vert_rate {
{ 11 * 8, 8 * 16 }, 5, { -4096, 4096 }, 64, ' ' // Let's limit to +/-5k aprox , Ex. max safe descent vertical rate aprox -1000 ft/min on an instrument approach. , std step is 64
};
};
class ADSBSquawkView : public OptionTabView {
@@ -152,7 +161,7 @@ public:
void focus() override;
std::string title() const override { return "ADS-B transmit"; };
std::string title() const override { return "ADS-B TX"; };
private:
/*enum tx_modes {
@@ -189,6 +198,10 @@ private:
-1,
-1
};*/
// app save settings
std::app_settings settings { };
std::app_settings::AppSettings app_settings { };
//tx_modes tx_mode = IDLE;
NavigationView& nav_;
+14
View File
@@ -66,6 +66,15 @@ AFSKRxView::AFSKRxView(NavigationView& nav) {
&console
});
// load app settings
auto rc = settings.load("rx_afsk", &app_settings);
if(rc == SETTINGS_OK) {
field_lna.set_value(app_settings.lna);
field_vga.set_value(app_settings.vga);
field_rf_amp.set_value(app_settings.rx_amp);
}
// DEBUG
record_view.on_error = [&nav](std::string message) {
nav.display_modal("Error", message);
@@ -164,6 +173,11 @@ void AFSKRxView::on_data(uint32_t value, bool is_data) {
}
AFSKRxView::~AFSKRxView() {
// save app settings
app_settings.rx_frequency = field_frequency.value();
settings.save("rx_afsk", &app_settings);
audio::output::stop();
receiver_model.disable();
baseband::shutdown();
+5 -1
View File
@@ -27,7 +27,7 @@
#include "ui_navigation.hpp"
#include "ui_receiver.hpp"
#include "ui_record_view.hpp" // DEBUG
#include "app_settings.hpp"
#include "log_file.hpp"
#include "utility.hpp"
@@ -57,6 +57,10 @@ public:
private:
void on_data(uint32_t value, bool is_data);
// app save settings
std::app_settings settings { };
std::app_settings::AppSettings app_settings { };
uint8_t console_color { 0 };
uint32_t prev_value { 0 };
std::string str_log { "" };
+13
View File
@@ -98,6 +98,15 @@ APRSRxView::APRSRxView(NavigationView& nav, Rect parent_rect) : View(parent_rect
&console
});
// load app settings
auto rc = settings.load("rx_aprs", &app_settings);
if(rc == SETTINGS_OK) {
field_lna.set_value(app_settings.lna);
field_vga.set_value(app_settings.vga);
field_rf_amp.set_value(app_settings.rx_amp);
}
// DEBUG
record_view.on_error = [&nav](std::string message) {
nav.display_modal("Error", message);
@@ -211,6 +220,10 @@ void APRSRxView::on_show(){
}
APRSRxView::~APRSRxView() {
// save app settings
settings.save("rx_aprs", &app_settings);
audio::output::stop();
receiver_model.disable();
baseband::shutdown();
+9 -3
View File
@@ -28,7 +28,7 @@
#include "ui_receiver.hpp"
#include "ui_record_view.hpp" // DEBUG
#include "ui_geomap.hpp"
#include "app_settings.hpp"
#include "recent_entries.hpp"
#include "ui_tabview.hpp"
@@ -57,12 +57,12 @@ struct APRSRecentEntry {
uint16_t hits { 0 };
uint32_t age { 0 };
uint64_t source;
uint64_t source { 0 };
std::string source_formatted { " " };
std::string time_string { "" };
std::string info_string { "" };
aprs::aprs_pos pos;
aprs::aprs_pos pos { 0 , 0 , 0 , 0 };
bool has_position = false;
APRSRecentEntry(uint64_t src)
{
@@ -131,6 +131,7 @@ private:
GeoMapView* geomap_view { nullptr };
bool send_updates { false };
Console console {
{ 0, 0 * 16, 240, 224 }
};
@@ -192,6 +193,11 @@ private:
void on_data(uint32_t value, bool is_data);
bool reset_console = false;
// app save settings
std::app_settings settings { };
std::app_settings::AppSettings app_settings { };
uint8_t console_color { 0 };
std::string str_log { "" };
+17 -2
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"
@@ -43,8 +44,13 @@ void APRSTXView::focus() {
}
APRSTXView::~APRSTXView() {
// save app settings
app_settings.tx_frequency = transmitter_model.tuning_frequency();
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() {
@@ -66,7 +72,7 @@ void APRSTXView::start_tx() {
1200,
2200,
1,
10000, //transmitter_model.channel_bandwidth(),
10000, //APRS uses fixed 10k bandwidth
8
);
}
@@ -95,6 +101,15 @@ APRSTXView::APRSTXView(NavigationView& nav) {
&tx_view
});
// load app settings
auto rc = settings.load("tx_aprs", &app_settings);
if(rc == SETTINGS_OK) {
transmitter_model.set_rf_amp(app_settings.tx_amp);
transmitter_model.set_tuning_frequency(app_settings.tx_frequency);
transmitter_model.set_tx_gain(app_settings.tx_gain);
}
button_set.on_select = [this, &nav](Button&) {
text_prompt(
nav,
+7 -9
View File
@@ -29,6 +29,7 @@
#include "message.hpp"
#include "transmitter_model.hpp"
#include "app_settings.hpp"
#include "portapack.hpp"
namespace ui {
@@ -40,17 +41,14 @@ public:
void focus() override;
std::string title() const override { return "APRS TX (beta)"; };
std::string title() const override { return "APRS TX"; };
private:
/*enum tx_modes {
IDLE = 0,
SINGLE,
SEQUENCE
};
tx_modes tx_mode = IDLE;*/
// app save settings
std::app_settings settings { };
std::app_settings::AppSettings app_settings { };
std::string payload { "" };
void start_tx();
@@ -103,7 +101,7 @@ private:
TransmitterView tx_view {
16 * 16,
5000,
10
0 // disable setting bandwith, since APRS used fixed 10k bandwidth
};
MessageHandlerRegistration message_handler_tx_progress {
+23 -7
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;
@@ -96,9 +97,9 @@ void BHTView::on_tx_progress(const uint32_t progress, const bool done) {
if (target_system == XYLOS) {
if (done) {
if (tx_mode == SINGLE) {
if (checkbox_cligno.value()) {
if (checkbox_flashing.value()) {
// TODO: Thread !
chThdSleepMilliseconds(field_tempo.value() * 1000); // Dirty :(
chThdSleepMilliseconds(field_speed.value() * 1000); // Dirty :(
view_xylos.flip_relays();
start_tx();
} else
@@ -120,9 +121,9 @@ void BHTView::on_tx_progress(const uint32_t progress, const bool done) {
} else {
view_EPAR.half = false;
if (tx_mode == SINGLE) {
if (checkbox_cligno.value()) {
if (checkbox_flashing.value()) {
// TODO: Thread !
chThdSleepMilliseconds(field_tempo.value() * 1000); // Dirty :(
chThdSleepMilliseconds(field_speed.value() * 1000); // Dirty :(
view_EPAR.flip_relays();
start_tx();
} else
@@ -140,7 +141,13 @@ void BHTView::on_tx_progress(const uint32_t progress, const bool done) {
}
BHTView::~BHTView() {
// save app settings
app_settings.tx_frequency = transmitter_model.tuning_frequency();
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) {
@@ -150,13 +157,22 @@ BHTView::BHTView(NavigationView& nav) {
&view_xylos,
&view_EPAR,
&checkbox_scan,
&checkbox_cligno,
&field_tempo,
&checkbox_flashing,
&field_speed,
&progressbar,
&tx_view
});
field_tempo.set_value(1);
// load app settings
auto rc = settings.load("tx_bht", &app_settings);
if(rc == SETTINGS_OK) {
transmitter_model.set_rf_amp(app_settings.tx_amp);
transmitter_model.set_channel_bandwidth(app_settings.channel_bandwidth);
transmitter_model.set_tuning_frequency(app_settings.tx_frequency);
transmitter_model.set_tx_gain(app_settings.tx_gain);
}
field_speed.set_value(1);
tx_view.on_edit_frequency = [this, &nav]() {
auto new_view = nav.push<FrequencyKeypadView>(receiver_model.tuning_frequency());
+22 -17
View File
@@ -32,6 +32,7 @@
#include "message.hpp"
#include "transmitter_model.hpp"
#include "encoders.hpp"
#include "app_settings.hpp"
#include "portapack.hpp"
namespace ui {
@@ -50,11 +51,11 @@ public:
private:
Labels labels {
{ { 8 * 8, 1 * 8 }, "Header:", Color::light_grey() },
{ { 4 * 8, 3 * 8 }, "Code ville:", Color::light_grey() },
{ { 7 * 8, 5 * 8 }, "Famille:", Color::light_grey() },
{ { 2 * 8, 7 * 8 + 2 }, "Sous-famille:", Color::light_grey() },
{ { 2 * 8, 11 * 8 }, "ID recepteur:", Color::light_grey() },
{ { 2 * 8, 14 * 8 }, "Relais:", Color::light_grey() }
{ { 4 * 8, 3 * 8 }, "City code:", Color::light_grey() },
{ { 7 * 8, 5 * 8 }, "Family:", Color::light_grey() },
{ { 2 * 8, 7 * 8 + 2 }, "Subfamily:", Color::light_grey() },
{ { 2 * 8, 11 * 8 }, "Receiver ID:", Color::light_grey() },
{ { 2 * 8, 14 * 8 }, "Relay:", Color::light_grey() }
};
NumberField field_header_a {
@@ -98,8 +99,8 @@ private:
Checkbox checkbox_wcsubfamily {
{ 20 * 8, 6 * 8 + 6 },
6,
"Toutes"
3,
"All"
};
NumberField field_receiver {
@@ -111,8 +112,8 @@ private:
};
Checkbox checkbox_wcid {
{ 20 * 8, 10 * 8 + 4 },
4,
"Tous"
3,
"All"
};
std::array<ImageOptionsField, 4> relay_states { };
@@ -139,9 +140,9 @@ public:
private:
Labels labels {
{ { 4 * 8, 1 * 8 }, "Code ville:", Color::light_grey() },
{ { 8 * 8, 3 * 8 }, "Groupe:", Color::light_grey() },
{ { 8 * 8, 7 * 8 }, "Relais:", Color::light_grey() }
{ { 4 * 8, 1 * 8 }, "City code:", Color::light_grey() },
{ { 8 * 8, 3 * 8 }, "Group:", Color::light_grey() },
{ { 8 * 8, 7 * 8 }, "Relay:", Color::light_grey() }
};
NumberField field_city {
@@ -178,9 +179,13 @@ public:
void focus() override;
std::string title() const override { return "BHT transmit"; };
std::string title() const override { return "BHT Xy/EP TX"; };
private:
// app save settings
std::app_settings settings { };
std::app_settings::AppSettings app_settings { };
void on_tx_progress(const uint32_t progress, const bool done);
void start_tx();
void stop_tx();
@@ -220,12 +225,12 @@ private:
"Scan"
};
Checkbox checkbox_cligno {
Checkbox checkbox_flashing {
{ 16 * 8, 25 * 8 },
6,
"Cligno"
8,
"Flashing"
};
NumberField field_tempo {
NumberField field_speed {
{ 26 * 8, 25 * 8 + 4 },
2,
{ 1, 99 },
+14
View File
@@ -60,6 +60,15 @@ BTLERxView::BTLERxView(NavigationView& nav) {
&console
});
// load app settings
auto rc = settings.load("rx_btle", &app_settings);
if(rc == SETTINGS_OK) {
field_lna.set_value(app_settings.lna);
field_vga.set_value(app_settings.vga);
field_rf_amp.set_value(app_settings.rx_amp);
}
// DEBUG
record_view.on_error = [&nav](std::string message) {
nav.display_modal("Error", message);
@@ -152,6 +161,11 @@ void BTLERxView::on_data(uint32_t value, bool is_data) {
}
BTLERxView::~BTLERxView() {
// save app settings
app_settings.rx_frequency = field_frequency.value();
settings.save("rx_btle", &app_settings);
audio::output::stop();
receiver_model.disable();
baseband::shutdown();
+6
View File
@@ -27,6 +27,7 @@
#include "ui.hpp"
#include "ui_navigation.hpp"
#include "ui_receiver.hpp"
#include "app_settings.hpp"
#include "ui_record_view.hpp" // DEBUG
#include "utility.hpp"
@@ -45,6 +46,11 @@ public:
private:
void on_data(uint32_t value, bool is_data);
// app save settings
std::app_settings settings { };
std::app_settings::AppSettings app_settings { };
uint8_t console_color { 0 };
uint32_t prev_value { 0 };
std::string str_log { "" };
+16 -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>
@@ -37,8 +38,13 @@ void CoasterPagerView::focus() {
}
CoasterPagerView::~CoasterPagerView() {
// save app settings
app_settings.tx_frequency = transmitter_model.tuning_frequency();
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() {
@@ -119,6 +125,15 @@ CoasterPagerView::CoasterPagerView(NavigationView& nav) {
&tx_view
});
// load app settings
auto rc = settings.load("tx_coaster", &app_settings);
if(rc == SETTINGS_OK) {
transmitter_model.set_rf_amp(app_settings.tx_amp);
transmitter_model.set_channel_bandwidth(app_settings.channel_bandwidth);
transmitter_model.set_tuning_frequency(app_settings.tx_frequency);
transmitter_model.set_tx_gain(app_settings.tx_gain);
}
// Bytes to nibbles
for (c = 0; c < 16; c++)
sym_data.set_sym(c, (data_init[c >> 1] >> ((c & 1) ? 0 : 4)) & 0x0F);
+6 -1
View File
@@ -28,6 +28,7 @@
#include "message.hpp"
#include "transmitter_model.hpp"
#include "app_settings.hpp"
#include "portapack.hpp"
namespace ui {
@@ -39,7 +40,7 @@ public:
void focus() override;
std::string title() const override { return "Si44xx TX"; };
std::string title() const override { return "BurgerPgr TX"; };
private:
enum tx_modes {
@@ -50,6 +51,10 @@ private:
tx_modes tx_mode = IDLE;
// app save settings
std::app_settings settings { };
std::app_settings::AppSettings app_settings { };
void start_tx();
void generate_frame();
void on_tx_progress(const uint32_t progress, const bool done);
+12 -6
View File
@@ -31,6 +31,7 @@
#include "ui_sd_card_debug.hpp"
#include "portapack.hpp"
#include "portapack_persistent_memory.hpp"
using namespace portapack;
#include "irq_controls.hpp"
@@ -321,17 +322,19 @@ void DebugControlsView::focus() {
/* DebugPeripheralsMenuView **********************************************/
DebugPeripheralsMenuView::DebugPeripheralsMenuView(NavigationView& nav) {
const char * max283x = hackrf_r9 ? "MAX2839" : "MAX2837";
const char * si5351x = hackrf_r9 ? "Si5351A" : "Si5351C";
add_items({
{ "RFFC5072", ui::Color::dark_cyan(), &bitmap_icon_peripherals_details, [&nav](){ nav.push<RegistersView>(
"RFFC5072", RegistersWidgetConfig { 31, 16 },
[](const size_t register_number) { return radio::debug::first_if::register_read(register_number); }
); } },
{ "MAX2837", ui::Color::dark_cyan(), &bitmap_icon_peripherals_details, [&nav](){ nav.push<RegistersView>(
"MAX2837", RegistersWidgetConfig { 32, 10 },
{ max283x, ui::Color::dark_cyan(), &bitmap_icon_peripherals_details, [&nav, max283x](){ nav.push<RegistersView>(
max283x, RegistersWidgetConfig { 32, 10 },
[](const size_t register_number) { return radio::debug::second_if::register_read(register_number); }
); } },
{ "Si5351C", ui::Color::dark_cyan(), &bitmap_icon_peripherals_details, [&nav](){ nav.push<RegistersView>(
"Si5351C", RegistersWidgetConfig { 96, 8 },
{ si5351x, ui::Color::dark_cyan(), &bitmap_icon_peripherals_details, [&nav, si5351x](){ nav.push<RegistersView>(
si5351x, RegistersWidgetConfig { 96, 8 },
[](const size_t register_number) { return portapack::clock_generator.read_register(register_number); }
); } },
{ audio::debug::codec_name(), ui::Color::dark_cyan(), &bitmap_icon_peripherals_details, [&nav](){ nav.push<RegistersView>(
@@ -345,14 +348,17 @@ DebugPeripheralsMenuView::DebugPeripheralsMenuView(NavigationView& nav) {
/* DebugMenuView *********************************************************/
DebugMenuView::DebugMenuView(NavigationView& nav) {
if( portapack::persistent_memory::show_gui_return_icon() )
{
add_items( { { "..", ui::Color::light_grey(),&bitmap_icon_previous, [&nav](){ nav.pop(); } } } );
}
add_items({
//{ "..", ui::Color::light_grey(),&bitmap_icon_previous, [&nav](){ nav.pop(); } },
{ "Memory", ui::Color::dark_cyan(), &bitmap_icon_memory, [&nav](){ nav.push<DebugMemoryView>(); } },
//{ "Radio State", ui::Color::white(), nullptr, [&nav](){ nav.push<NotImplementedView>(); } },
{ "SD Card", ui::Color::dark_cyan(), &bitmap_icon_sdcard, [&nav](){ nav.push<SDCardDebugView>(); } },
{ "Peripherals", ui::Color::dark_cyan(), &bitmap_icon_peripherals, [&nav](){ nav.push<DebugPeripheralsMenuView>(); } },
{ "Temperature", ui::Color::dark_cyan(), &bitmap_icon_temperature, [&nav](){ nav.push<TemperatureView>(); } },
{ "Buttons test", ui::Color::dark_cyan(), &bitmap_icon_controls, [&nav](){ nav.push<DebugControlsView>(); } },
{ "Buttons Test", ui::Color::dark_cyan(), &bitmap_icon_controls, [&nav](){ nav.push<DebugControlsView>(); } },
});
set_max_rows(2); // allow wider buttons
}
+6 -1
View File
@@ -29,7 +29,6 @@
#include "ui_navigation.hpp"
#include "rffc507x.hpp"
#include "max2837.hpp"
#include "portapack.hpp"
#include <functional>
@@ -43,6 +42,8 @@ public:
void focus() override;
std::string title() const override { return "Memory"; };
private:
Text text_title {
{ 96, 96, 48, 16 },
@@ -113,6 +114,8 @@ public:
void focus() override;
std::string title() const override { return "Temperature"; };
private:
Text text_title {
{ 76, 16, 240, 16 },
@@ -252,6 +255,8 @@ public:
void focus() override;
std::string title() const override { return "Buttons Test"; };
private:
Text text_title {
{ 64, 16, 184, 16 },
+97 -123
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,30 @@ 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 if (!c)
break;
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 +178,7 @@ uint32_t EncodersConfigView::pause_symbols() {
}
void EncodersScanView::focus() {
field_debug.focus();
field_length.focus();
}
EncodersScanView::EncodersScanView(
@@ -171,31 +186,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() {
@@ -203,30 +204,22 @@ void EncodersView::focus() {
}
EncodersView::~EncodersView() {
// save app settings
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);
@@ -234,89 +227,59 @@ 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;
constexpr auto sym_len = 4;
const uint32_t seq_len = ((1 << (scan_width - 1)) * 2) * ((uint64_t) samples_per_bit) * sym_len / 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
);
}
@@ -334,21 +297,32 @@ EncodersView::EncodersView(
&progressbar,
&tx_view
});
// load app settings
auto rc = settings.load("tx_ook", &app_settings);
if (rc == SETTINGS_OK) {
transmitter_model.set_rf_amp(app_settings.tx_amp);
transmitter_model.set_channel_bandwidth(app_settings.channel_bandwidth);
transmitter_model.set_tuning_frequency(app_settings.tx_frequency);
transmitter_model.set_tx_gain(app_settings.tx_gain);
}
tx_view.on_edit_frequency = [this, &nav]() {
auto new_view = nav.push<FrequencyKeypadView>(transmitter_model.tuning_frequency());
new_view->on_changed = [this](rf::Frequency f) {
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();
};
}
+101 -64
View File
@@ -26,6 +26,7 @@
#include "transmitter_model.hpp"
#include "encoders.hpp"
#include "de_bruijn.hpp"
#include "app_settings.hpp"
using namespace encoders;
@@ -34,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
@@ -81,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,
@@ -121,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() },
};
};
@@ -155,10 +188,10 @@ class EncodersView : public View {
public:
EncodersView(NavigationView& nav);
~EncodersView();
void focus() override;
std::string title() const override { return "OOK transmit"; };
std::string title() const override { return "OOK TX"; };
private:
NavigationView& nav_;
@@ -168,15 +201,19 @@ private:
SINGLE,
SCAN
};
// app save 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(),
@@ -187,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)
+21 -3
View File
@@ -106,7 +106,7 @@ public:
void focus() override;
std::string title() const override { return "Jammer"; };
std::string title() const override { return "Jammer TX"; };
private:
NavigationView& nav_;
@@ -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"
};
+13 -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;
@@ -136,8 +137,12 @@ void KeyfobView::focus() {
}
KeyfobView::~KeyfobView() {
// save app settings
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) {
@@ -214,6 +219,13 @@ KeyfobView::KeyfobView(
&tx_view
});
// load app settings
auto rc = settings.load("tx_keyfob", &app_settings);
if(rc == SETTINGS_OK) {
transmitter_model.set_rf_amp(app_settings.tx_amp);
transmitter_model.set_tx_gain(app_settings.tx_gain);
}
frame[0] = 0x55;
update_symfields();
+6 -1
View File
@@ -23,6 +23,7 @@
#include "ui.hpp"
#include "ui_transmitter.hpp"
#include "transmitter_model.hpp"
#include "app_settings.hpp"
#include "encoders.hpp"
using namespace encoders;
@@ -36,11 +37,15 @@ public:
void focus() override;
std::string title() const override { return "Keyfob (BETA)"; };
std::string title() const override { return "Key fob TX"; };
private:
NavigationView& nav_;
// app save settings
std::app_settings settings { };
std::app_settings::AppSettings app_settings { };
// 1013210ns / bit
static constexpr uint32_t subaru_samples_per_bit = (OOK_SAMPLERATE * 0.00101321);
static constexpr uint32_t repeats = 4;
+16 -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"
@@ -39,8 +40,13 @@ void LCRView::focus() {
}
LCRView::~LCRView() {
// save app settings
app_settings.tx_frequency = transmitter_model.tuning_frequency();
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.
}
/*
@@ -173,6 +179,15 @@ LCRView::LCRView(NavigationView& nav) {
&tx_view
});
// load app settings
auto rc = settings.load("tx_lcr", &app_settings);
if(rc == SETTINGS_OK) {
transmitter_model.set_rf_amp(app_settings.tx_amp);
transmitter_model.set_channel_bandwidth(app_settings.channel_bandwidth);
transmitter_model.set_tuning_frequency(app_settings.tx_frequency);
transmitter_model.set_tx_gain(app_settings.tx_gain);
}
options_scanlist.set_selected_index(0);
const auto button_set_am_fn = [this, &nav](Button& button) {
+6 -1
View File
@@ -27,6 +27,7 @@
#include "message.hpp"
#include "transmitter_model.hpp"
#include "app_settings.hpp"
namespace ui {
@@ -39,7 +40,7 @@ public:
void focus() override;
std::string title() const override { return "LCR transmit"; };
std::string title() const override { return "TEDI/LCR TX"; };
private:
struct scan_list_t {
@@ -81,6 +82,10 @@ private:
SCAN
};
// app save settings
std::app_settings settings { };
std::app_settings::AppSettings app_settings { };
tx_modes tx_mode = IDLE;
uint8_t scan_count { 0 }, scan_index { 0 };
uint32_t scan_progress { 0 };
+305 -280
View File
@@ -22,315 +22,340 @@
#include "ui_looking_glass_app.hpp"
using namespace portapack;
namespace ui
{
void GlassView::focus() {
field_marker.focus();
}
GlassView::~GlassView() {
receiver_model.set_sampling_rate(3072000); // Just a hack to avoid hanging other apps
receiver_model.disable();
baseband::shutdown();
}
void GlassView::on_lna_changed(int32_t v_db) {
receiver_model.set_lna(v_db);
}
void GlassView::on_vga_changed(int32_t v_db) {
receiver_model.set_vga(v_db);
}
void GlassView::add_spectrum_pixel(Color color)
{
spectrum_row[pixel_index++] = color;
if (pixel_index == 240) //got an entire waterfall line
{
const auto draw_y = display.scroll(1); //Scroll 1 pixel down
display.draw_pixels( {{0, draw_y}, {240, 1}}, spectrum_row); //new line at top
pixel_index = 0; //Start New cascade line
}
}
//Apparently, the spectrum object returns an array of 256 bins
//Each having the radio signal power for it's corresponding frequency slot
void GlassView::on_channel_spectrum(const ChannelSpectrum &spectrum)
{
baseband::spectrum_streaming_stop();
// Convert bins of this spectrum slice into a representative max_power and when enough, into pixels
// Spectrum.db has 256 bins. Center 12 bins are ignored (DC spike is blanked) Leftmost and rightmost 2 bins are ignored
// All things said and done, we actually need 240 of those bins:
for(uint8_t bin = 0; bin < 240; bin++)
void GlassView::focus()
{
if (bin < 120) {
if (spectrum.db[134 + bin] > max_power)
max_power = spectrum.db[134 + bin];
}
else
field_marker.focus();
}
GlassView::~GlassView()
{
receiver_model.set_sampling_rate(3072000); // Just a hack to avoid hanging other apps
receiver_model.disable();
baseband::shutdown();
}
void GlassView::on_lna_changed(int32_t v_db)
{
receiver_model.set_lna(v_db);
}
void GlassView::on_vga_changed(int32_t v_db)
{
receiver_model.set_vga(v_db);
}
void GlassView::add_spectrum_pixel(Color color)
{
spectrum_row[pixel_index++] = color;
if (pixel_index == 240) // got an entire waterfall line
{
if (spectrum.db[bin - 118] > max_power)
max_power = spectrum.db[bin - 118];
display.draw_pixels({{0, display.scroll(1)}, {240, 1}}, spectrum_row); // new line at top, one less var, speedier
pixel_index = 0; // Start New cascade line
}
}
bins_Hz_size += each_bin_size; //add this bin Hz count into the "pixel fulfilled bag of Hz"
// Apparently, the spectrum object returns an array of 256 bins
// Each having the radio signal power for it's corresponding frequency slot
void GlassView::on_channel_spectrum(const ChannelSpectrum &spectrum)
{
baseband::spectrum_streaming_stop();
if (bins_Hz_size >= marker_pixel_step) //new pixel fullfilled
// Convert bins of this spectrum slice into a representative max_power and when enough, into pixels
// Spectrum.db has 256 bins. Center 12 bins are ignored (DC spike is blanked) Leftmost and rightmost 2 bins are ignored
// All things said and done, we actually need 240 of those bins:
for (uint8_t bin = 0; bin < 240; bin++)
{
if (min_color_power < max_power)
add_spectrum_pixel(spectrum_rgb3_lut[max_power]); //Pixel will represent max_power
else
add_spectrum_pixel(0); //Filtered out, show black
max_power = 0;
if (!pixel_index) //Received indication that a waterfall line has been completed
if (bin < 120)
{
bins_Hz_size = 0; //Since this is an entire pixel line, we don't carry "Pixels into next bin"
break;
} else {
bins_Hz_size -= marker_pixel_step; //reset bins size, but carrying the eventual excess Hz into next pixel
if (spectrum.db[134 + bin] > max_power) // 134
max_power = spectrum.db[134 + bin];
}
else
{
if (spectrum.db[bin - 118] > max_power) // 118
max_power = spectrum.db[bin - 118];
}
bins_Hz_size += each_bin_size; // add this bin Hz count into the "pixel fulfilled bag of Hz"
if (bins_Hz_size >= marker_pixel_step) // new pixel fullfilled
{
if (min_color_power < max_power)
add_spectrum_pixel(spectrum_rgb3_lut[max_power]); // Pixel will represent max_power
else
add_spectrum_pixel(0); // Filtered out, show black
max_power = 0;
if (!pixel_index) // Received indication that a waterfall line has been completed
{
bins_Hz_size = 0; // Since this is an entire pixel line, we don't carry "Pixels into next bin"
f_center = f_center_ini; // Start a new sweep
radio::set_tuning_frequency(f_center); // tune rx for this new slice directly, faster than using persistent memory saving
chThdSleepMilliseconds(10);
baseband::spectrum_streaming_start(); // Do the RX
return;
}
bins_Hz_size -= marker_pixel_step; // reset bins size, but carrying the eventual excess Hz into next pixel
}
}
f_center += LOOKING_GLASS_SLICE_WIDTH; // Move into the next bandwidth slice NOTE: spectrum.sampling_rate = LOOKING_GLASS_SLICE_WIDTH
radio::set_tuning_frequency(f_center); // tune rx for this new slice directly, faster than using persistent memory saving
chThdSleepMilliseconds(5);
// receiver_model.set_tuning_frequency(f_center); //tune rx for this slice
baseband::spectrum_streaming_start(); // Do the RX
}
if (pixel_index)
f_center += LOOKING_GLASS_SLICE_WIDTH; //Move into the next bandwidth slice NOTE: spectrum.sampling_rate = LOOKING_GLASS_SLICE_WIDTH
else
f_center = f_center_ini; //Start a new sweep
receiver_model.set_tuning_frequency(f_center); //tune rx for this slice
baseband::spectrum_streaming_start(); //Do the RX
}
void GlassView::on_hide()
{
baseband::spectrum_streaming_stop();
display.scroll_disable();
}
void GlassView::on_show()
{
display.scroll_set_area( 109, 319); //Restart scroll on the correct coordinates
baseband::spectrum_streaming_start();
}
void GlassView::on_range_changed()
{
f_min = field_frequency_min.value();
f_max = field_frequency_max.value();
search_span = f_max - f_min;
field_marker.set_range(f_min, f_max); //Move the marker between range
field_marker.set_value(f_min + (search_span / 2)); //Put MARKER AT MIDDLE RANGE
text_range.set(to_string_dec_uint(search_span));
f_min = (f_min)*MHZ_DIV; //Transpose into full frequency realm
f_max = (f_max)*MHZ_DIV;
search_span = search_span * MHZ_DIV;
marker_pixel_step = search_span / 240; //Each pixel value in Hz
text_marker_pm.set(to_string_dec_uint((marker_pixel_step / X2_MHZ_DIV) + 1)); // Give idea of +/- marker precision
int32_t marker_step = marker_pixel_step / MHZ_DIV;
if (!marker_step)
field_marker.set_step(1); //in case selected range is less than 240 (pixels)
else
field_marker.set_step(marker_step); //step needs to be a pixel wide.
f_center_ini = f_min + (LOOKING_GLASS_SLICE_WIDTH / 2); //Initial center frequency for sweep
f_center_ini += LOOKING_GLASS_SLICE_WIDTH; //euquiq: Why do I need to move the center ???!!! (shift needed for marker accuracy)
PlotMarker(field_marker.value()); //Refresh marker on screen
f_center = f_center_ini; //Reset sweep into first slice
pixel_index = 0; //reset pixel counter
max_power = 0;
bins_Hz_size = 0; //reset amount of Hz filled up by pixels
baseband::set_spectrum(LOOKING_GLASS_SLICE_WIDTH, field_trigger.value());
receiver_model.set_tuning_frequency(f_center_ini); //tune rx for this slice
}
void GlassView::PlotMarker(rf::Frequency fpos)
{
int64_t pos = fpos * MHZ_DIV;
pos -= f_min;
pos = pos / marker_pixel_step; //Real pixel
portapack::display.fill_rectangle({0, 100, 240, 8}, Color::black()); //Clear old marker and whole marker rectangle btw
portapack::display.fill_rectangle({(int16_t)pos - 2, 100, 5, 3}, Color::red()); //Red marker middle
portapack::display.fill_rectangle({(int16_t)pos - 1, 103, 3, 3}, Color::red()); //Red marker middle
portapack::display.fill_rectangle({(int16_t)pos, 106, 1, 2}, Color::red()); //Red marker middle
}
GlassView::GlassView(
NavigationView &nav) : nav_(nav)
{
baseband::run_image(portapack::spi_flash::image_tag_wideband_spectrum);
add_children({&labels,
&field_frequency_min,
&field_frequency_max,
&field_lna,
&field_vga,
&text_range,
&filter_config,
&field_rf_amp,
&range_presets,
&field_marker,
&text_marker_pm,
&field_trigger
});
load_Presets(); //Load available presets from TXT files (or default)
field_frequency_min.set_value(presets_db[0].min); //Defaults to first preset
field_frequency_min.on_change = [this](int32_t v) {
if (v >= field_frequency_max.value())
field_frequency_max.set_value(v + 240);
this->on_range_changed();
};
field_frequency_max.set_value(presets_db[0].max); //Defaults to first preset
field_frequency_max.on_change = [this](int32_t v) {
if (v <= field_frequency_min.value())
field_frequency_min.set_value(v - 240);
this->on_range_changed();
};
field_lna.set_value(receiver_model.lna());
field_lna.on_change = [this](int32_t v) {
this->on_lna_changed(v);
};
field_vga.set_value(receiver_model.vga());
field_vga.on_change = [this](int32_t v_db) {
this->on_vga_changed(v_db);
};
filter_config.set_selected_index(0);
filter_config.on_change = [this](size_t n, OptionsField::value_t v) {
(void)n;
min_color_power = v;
};
range_presets.on_change = [this](size_t n, OptionsField::value_t v) {
(void)n;
field_frequency_min.set_value(presets_db[v].min,false);
field_frequency_max.set_value(presets_db[v].max,false);
this->on_range_changed();
};
field_marker.on_change = [this](int32_t v) {
PlotMarker(v); //Refresh marker on screen
};
field_marker.on_select = [this](NumberField&) {
f_center = field_marker.value();
f_center = f_center * MHZ_DIV;
receiver_model.set_tuning_frequency(f_center); //Center tune rx in marker freq.
receiver_model.set_frequency_step(MHZ_DIV); // Preset a 1 MHz frequency step into RX -> AUDIO
nav_.pop();
nav_.push<AnalogAudioView>(); //Jump into audio view
};
field_trigger.set_value(32); //Defaults to 32, as normal triggering resolution
field_trigger.on_change = [this](int32_t v) {
baseband::set_spectrum(LOOKING_GLASS_SLICE_WIDTH, v);
};
display.scroll_set_area( 109, 319);
baseband::set_spectrum(LOOKING_GLASS_SLICE_WIDTH, field_trigger.value()); //trigger:
// Discord User jteich: WidebandSpectrum::on_message to set the trigger value. In WidebandSpectrum::execute ,
// it keeps adding the output of the fft to the buffer until "trigger" number of calls are made,
//at which time it pushes the buffer up with channel_spectrum.feed
on_range_changed();
receiver_model.set_modulation(ReceiverModel::Mode::SpectrumAnalysis);
receiver_model.set_sampling_rate(LOOKING_GLASS_SLICE_WIDTH); //20mhz
receiver_model.set_baseband_bandwidth(LOOKING_GLASS_SLICE_WIDTH); // possible values: 1.75/2.5/3.5/5/5.5/6/7/8/9/10/12/14/15/20/24/28MHz
receiver_model.set_squelch_level(0);
receiver_model.enable();
}
void GlassView::load_Presets() {
File presets_file; //LOAD /WHIPCALC/ANTENNAS.TXT from microSD
auto result = presets_file.open("LOOKINGGLASS/PRESETS.TXT");
presets_db.clear(); //Start with fresh db
if (result.is_valid()) {
presets_Default(); //There is no txt, store a default range
} else {
std::string line; //There is a txt file
char one_char[1]; //Read it char by char
for (size_t pointer=0; pointer < presets_file.size();pointer++) {
presets_file.seek(pointer);
presets_file.read(one_char, 1);
if ((int)one_char[0] > 31) { //ascii space upwards
line += one_char[0]; //Add it to the textline
}
else if (one_char[0] == '\n') { //New Line
txtline_process(line); //make sense of this textline
line.clear(); //Ready for next textline
}
}
if (line.length() > 0) txtline_process(line); //Last line had no newline at end ?
if (!presets_db.size()) presets_Default(); //no antenna on txt, use default
void GlassView::on_hide()
{
baseband::spectrum_streaming_stop();
display.scroll_disable();
}
populate_Presets();
}
void GlassView::on_show()
{
display.scroll_set_area(109, 319); // Restart scroll on the correct coordinates
baseband::spectrum_streaming_start();
}
void GlassView::txtline_process(std::string& line)
{
if (line.find("#") != std::string::npos) return; //Line is just a comment
void GlassView::on_range_changed()
{
f_min = field_frequency_min.value();
f_max = field_frequency_max.value();
search_span = f_max - f_min;
size_t comma = line.find(","); //Get first comma position
if (comma == std::string::npos) return; //No comma at all
field_marker.set_range(f_min, f_max); // Move the marker between range
field_marker.set_value(f_min + (search_span / 2)); // Put MARKER AT MIDDLE RANGE
text_range.set(to_string_dec_uint(search_span));
size_t previous = 0;
preset_entry new_preset;
f_min = (f_min)*MHZ_DIV; // Transpose into full frequency realm
f_max = (f_max)*MHZ_DIV;
search_span = search_span * MHZ_DIV;
new_preset.min = std::stoi(line.substr(0,comma));
if (!new_preset.min) return; //No frequency!
previous = comma + 1;
comma = line.find(",",previous); //Search for next delimiter
if (comma == std::string::npos) return; //No comma at all
marker_pixel_step = search_span / 240; // Each pixel value in Hz
text_marker_pm.set(to_string_dec_uint((marker_pixel_step / X2_MHZ_DIV) + 1)); // Give idea of +/- marker precision
new_preset.max = std::stoi(line.substr(previous,comma - previous));
if (!new_preset.max) return; //No frequency!
int32_t marker_step = marker_pixel_step / MHZ_DIV;
if (!marker_step)
field_marker.set_step(1); // in case selected range is less than 240 (pixels)
else
field_marker.set_step(marker_step); // step needs to be a pixel wide.
new_preset.label = line.substr(comma + 1);
if (new_preset.label.size() == 0) return; //No label ?
presets_db.push_back(new_preset); //Add this preset.
}
f_center_ini = f_min + (LOOKING_GLASS_SLICE_WIDTH / 2); // Initial center frequency for sweep
void GlassView::populate_Presets()
{
using option_t = std::pair<std::string, int32_t>;
using options_t = std::vector<option_t>;
options_t entries;
PlotMarker(field_marker.value()); // Refresh marker on screen
for (preset_entry preset : presets_db)
{ //go thru all available presets
entries.emplace_back(preset.label,entries.size());
f_center = f_center_ini; // Reset sweep into first slice
pixel_index = 0; // reset pixel counter
max_power = 0;
bins_Hz_size = 0; // reset amount of Hz filled up by pixels
baseband::set_spectrum(LOOKING_GLASS_SLICE_WIDTH, field_trigger.value());
receiver_model.set_tuning_frequency(f_center_ini); // tune rx for this slice
}
void GlassView::PlotMarker(rf::Frequency pos)
{
pos = pos * MHZ_DIV;
pos -= f_min;
pos = pos / marker_pixel_step; // Real pixel
portapack::display.fill_rectangle({0, 100, 240, 8}, Color::black()); // Clear old marker and whole marker rectangle btw
portapack::display.fill_rectangle({(int)pos - 2, 100, 5, 3}, Color::red()); // Red marker top
portapack::display.fill_rectangle({(int)pos - 1, 103, 3, 3}, Color::red()); // Red marker middle
portapack::display.fill_rectangle({(int)pos, 106, 1, 2}, Color::red()); // Red marker bottom
}
GlassView::GlassView(
NavigationView &nav) : nav_(nav)
{
baseband::run_image(portapack::spi_flash::image_tag_wideband_spectrum);
add_children({&labels,
&field_frequency_min,
&field_frequency_max,
&field_lna,
&field_vga,
&text_range,
&filter_config,
&field_rf_amp,
&range_presets,
&field_marker,
&text_marker_pm,
&field_trigger});
load_Presets(); // Load available presets from TXT files (or default)
field_frequency_min.set_value(presets_db[0].min); // Defaults to first preset
field_frequency_min.on_change = [this](int32_t v)
{
if (v >= field_frequency_max.value())
field_frequency_max.set_value(v + 240);
this->on_range_changed();
};
field_frequency_max.set_value(presets_db[0].max); // Defaults to first preset
field_frequency_max.on_change = [this](int32_t v)
{
if (v <= field_frequency_min.value())
field_frequency_min.set_value(v - 240);
this->on_range_changed();
};
field_lna.set_value(receiver_model.lna());
field_lna.on_change = [this](int32_t v)
{
this->on_lna_changed(v);
};
field_vga.set_value(receiver_model.vga());
field_vga.on_change = [this](int32_t v_db)
{
this->on_vga_changed(v_db);
};
filter_config.set_selected_index(0);
filter_config.on_change = [this](size_t n, OptionsField::value_t v)
{
(void)n;
min_color_power = v;
};
range_presets.on_change = [this](size_t n, OptionsField::value_t v)
{
(void)n;
field_frequency_min.set_value(presets_db[v].min, false);
field_frequency_max.set_value(presets_db[v].max, false);
this->on_range_changed();
};
field_marker.on_change = [this](int32_t v)
{
PlotMarker(v); // Refresh marker on screen
};
field_marker.on_select = [this](NumberField &)
{
f_center = field_marker.value();
f_center = f_center * MHZ_DIV;
receiver_model.set_tuning_frequency(f_center); // Center tune rx in marker freq.
receiver_model.set_frequency_step(MHZ_DIV); // Preset a 1 MHz frequency step into RX -> AUDIO
nav_.pop();
nav_.push<AnalogAudioView>(); // Jump into audio view
};
field_trigger.set_value(32); // Defaults to 32, as normal triggering resolution
field_trigger.on_change = [this](int32_t v)
{
baseband::set_spectrum(LOOKING_GLASS_SLICE_WIDTH, v);
};
display.scroll_set_area(109, 319);
baseband::set_spectrum(LOOKING_GLASS_SLICE_WIDTH, field_trigger.value()); // trigger:
// Discord User jteich: WidebandSpectrum::on_message to set the trigger value. In WidebandSpectrum::execute ,
// it keeps adding the output of the fft to the buffer until "trigger" number of calls are made,
// at which time it pushes the buffer up with channel_spectrum.feed
on_range_changed();
receiver_model.set_modulation(ReceiverModel::Mode::SpectrumAnalysis);
receiver_model.set_sampling_rate(LOOKING_GLASS_SLICE_WIDTH); // 20mhz
receiver_model.set_baseband_bandwidth(LOOKING_GLASS_SLICE_WIDTH); // possible values: 1.75/2.5/3.5/5/5.5/6/7/8/9/10/12/14/15/20/24/28MHz
receiver_model.set_squelch_level(0);
receiver_model.enable();
}
void GlassView::load_Presets()
{
File presets_file; // LOAD /WHIPCALC/ANTENNAS.TXT from microSD
auto result = presets_file.open("LOOKINGGLASS/PRESETS.TXT");
presets_db.clear(); // Start with fresh db
if (result.is_valid())
{
presets_Default(); // There is no txt, store a default range
}
range_presets.set_options(entries);
}
else
{
std::string line; // There is a txt file
char one_char[1]; // Read it char by char
for (size_t pointer = 0; pointer < presets_file.size(); pointer++)
{
presets_file.seek(pointer);
presets_file.read(one_char, 1);
if ((int)one_char[0] > 31)
{ // ascii space upwards
line += one_char[0]; // Add it to the textline
}
else if (one_char[0] == '\n')
{ // New Line
txtline_process(line); // make sense of this textline
line.clear(); // Ready for next textline
}
}
if (line.length() > 0)
txtline_process(line); // Last line had no newline at end ?
if (!presets_db.size())
presets_Default(); // no antenna on txt, use default
}
populate_Presets();
}
void GlassView::presets_Default()
{
void GlassView::txtline_process(std::string &line)
{
if (line.find("#") != std::string::npos)
return; // Line is just a comment
size_t comma = line.find(","); // Get first comma position
if (comma == std::string::npos)
return; // No comma at all
size_t previous = 0;
preset_entry new_preset;
new_preset.min = std::stoi(line.substr(0, comma));
if (!new_preset.min)
return; // No frequency!
previous = comma + 1;
comma = line.find(",", previous); // Search for next delimiter
if (comma == std::string::npos)
return; // No comma at all
new_preset.max = std::stoi(line.substr(previous, comma - previous));
if (!new_preset.max)
return; // No frequency!
new_preset.label = line.substr(comma + 1);
if (new_preset.label.size() == 0)
return; // No label ?
presets_db.push_back(new_preset); // Add this preset.
}
void GlassView::populate_Presets()
{
using option_t = std::pair<std::string, int32_t>;
using options_t = std::vector<option_t>;
options_t entries;
for (preset_entry preset : presets_db)
{ // go thru all available presets
entries.emplace_back(preset.label, entries.size());
}
range_presets.set_options(entries);
}
void GlassView::presets_Default()
{
presets_db.clear();
presets_db.push_back({2320, 2560, "DEFAULT WIFI 2.4GHz"});
}
}
}
+156 -49
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(ak4951_alc_GUI_selected); // set up audio input = mic config of any audio coded AK4951/WM8731, (in WM8731 parameter will be ignored)
audio::input::start(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 ( 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(ak4951_alc_GUI_selected);
};
// 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,36 +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
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
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).
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
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
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
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();
@@ -434,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);
@@ -523,9 +629,9 @@ MicTXView::MicTXView(
transmitter_model.set_baseband_bandwidth(1750000);
set_tx(false);
audio::set_rate(audio::Rate::Hz_24000);
audio::input::start(ak4951_alc_GUI_selected); // 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() {
@@ -534,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.
}
}
+36 -20
View File
@@ -58,7 +58,7 @@ public:
};
*/
std::string title() const override { return "Mic TX RX"; };
std::string title() const override { return "Microphone"; };
private:
static constexpr uint32_t sampling_rate = 1536000U;
@@ -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 {
+18 -3
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"
@@ -56,13 +57,13 @@ static msg_t ookthread_fn(void * arg) {
v = (symbol < 2) ? 1 : 0; // TX on for dot or dash, off for pause
delay = morse_symbols[symbol];
gpio_tx.write(v);
gpio_og_tx.write(v);
arg_c->on_tx_progress(i, false);
chThdSleepMilliseconds(delay * arg_c->time_unit_ms);
}
gpio_tx.write(0); // Ensure TX is off
gpio_og_tx.write(0); // Ensure TX is off
arg_c->on_tx_progress(0, true);
chThdExit(0);
@@ -97,8 +98,13 @@ void MorseView::focus() {
}
MorseView::~MorseView() {
// save app settings
app_settings.tx_frequency = transmitter_model.tuning_frequency();
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&) {
@@ -203,6 +209,15 @@ MorseView::MorseView(
&tx_view
});
// load app settings
auto rc = settings.load("tx_morse", &app_settings);
if(rc == SETTINGS_OK) {
transmitter_model.set_rf_amp(app_settings.tx_amp);
transmitter_model.set_channel_bandwidth(app_settings.channel_bandwidth);
transmitter_model.set_tuning_frequency(app_settings.tx_frequency);
transmitter_model.set_tx_gain(app_settings.tx_gain);
}
// Default settings
field_speed.set_value(15); // 15wps
field_tone.set_value(700); // 700Hz FM tone
+5 -1
View File
@@ -27,7 +27,7 @@
#include "ui_widget.hpp"
#include "ui_navigation.hpp"
#include "ui_transmitter.hpp"
#include "app_settings.hpp"
#include "portapack.hpp"
#include "message.hpp"
#include "volume.hpp"
@@ -67,6 +67,10 @@ private:
std::string message { };
uint32_t time_units { 0 };
// app save settings
std::app_settings settings { };
std::app_settings::AppSettings app_settings { };
enum modulation_t {
CW = 0,
FM = 1
+13
View File
@@ -60,6 +60,14 @@ NRFRxView::NRFRxView(NavigationView& nav) {
&console
});
// load app settings
auto rc = settings.load("rx_nrf", &app_settings);
if(rc == SETTINGS_OK) {
field_lna.set_value(app_settings.lna);
field_vga.set_value(app_settings.vga);
field_rf_amp.set_value(app_settings.rx_amp);
}
// DEBUG
record_view.on_error = [&nav](std::string message) {
nav.display_modal("Error", message);
@@ -157,6 +165,11 @@ void NRFRxView::on_data(uint32_t value, bool is_data) {
}
NRFRxView::~NRFRxView() {
// save app settings
app_settings.rx_frequency = field_frequency.value();
settings.save("rx_nrf", &app_settings);
audio::output::stop();
receiver_model.disable();
baseband::shutdown();
+5
View File
@@ -27,6 +27,7 @@
#include "ui.hpp"
#include "ui_navigation.hpp"
#include "ui_receiver.hpp"
#include "app_settings.hpp"
#include "ui_record_view.hpp" // DEBUG
#include "utility.hpp"
@@ -45,6 +46,10 @@ public:
private:
void on_data(uint32_t value, bool is_data);
// app save settings
std::app_settings settings { };
std::app_settings::AppSettings app_settings { };
uint8_t console_color { 0 };
uint32_t prev_value { 0 };
std::string str_log { "" };
+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 */
+16 -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"
@@ -38,8 +39,13 @@ void POCSAGTXView::focus() {
}
POCSAGTXView::~POCSAGTXView() {
// save app settings
app_settings.tx_frequency = transmitter_model.tuning_frequency();
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) {
@@ -141,6 +147,15 @@ POCSAGTXView::POCSAGTXView(
&tx_view
});
// load app settings
auto rc = settings.load("tx_pocsag", &app_settings);
if(rc == SETTINGS_OK) {
transmitter_model.set_rf_amp(app_settings.tx_amp);
transmitter_model.set_channel_bandwidth(app_settings.channel_bandwidth);
transmitter_model.set_tuning_frequency(app_settings.tx_frequency);
transmitter_model.set_tx_gain(app_settings.tx_gain);
}
options_bitrate.set_selected_index(1); // 1200bps
options_type.set_selected_index(0); // Address only
@@ -31,6 +31,7 @@
#include "bch_code.hpp"
#include "message.hpp"
#include "transmitter_model.hpp"
#include "app_settings.hpp"
#include "pocsag.hpp"
using namespace pocsag;
@@ -62,6 +63,10 @@ private:
5, 31, 21, 2
};
// app save settings
std::app_settings settings { };
std::app_settings::AppSettings app_settings { };
void on_set_text(NavigationView& nav);
void on_tx_progress(const uint32_t progress, const bool done);
bool start_tx();
+16 -6
View File
@@ -24,6 +24,7 @@
#include "portapack.hpp"
#include "baseband_api.hpp"
#include "cpld_update.hpp"
#include "portapack_shared_memory.hpp"
#include <cstring>
@@ -175,8 +176,13 @@ void RDSView::focus() {
}
RDSView::~RDSView() {
// save app settings
app_settings.tx_frequency = transmitter_model.tuning_frequency();
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() {
@@ -226,11 +232,17 @@ RDSView::RDSView(
&view_radiotext,
&view_datetime,
&view_audio,
//&options_countrycode,
//&options_coverage,
&tx_view,
});
// load app settings
auto rc = settings.load("tx_rds", &app_settings);
if(rc == SETTINGS_OK) {
transmitter_model.set_rf_amp(app_settings.tx_amp);
transmitter_model.set_channel_bandwidth(app_settings.channel_bandwidth);
transmitter_model.set_tuning_frequency(app_settings.tx_frequency);
transmitter_model.set_tx_gain(app_settings.tx_gain);
}
check_TP.set_value(true);
sym_pi_code.set_sym(0, 0xF);
@@ -242,8 +254,6 @@ RDSView::RDSView(
};
options_pty.set_selected_index(0); // None
//options_countrycode.set_selected_index(18); // Baguette du fromage
//options_coverage.set_selected_index(0); // Local
tx_view.on_edit_frequency = [this, &nav]() {
auto new_view = nav.push<FrequencyKeypadView>(receiver_model.tuning_frequency());
+7 -2
View File
@@ -24,7 +24,7 @@
#include "ui_transmitter.hpp"
#include "ui_textentry.hpp"
#include "ui_tabview.hpp"
#include "app_settings.hpp"
#include "rds.hpp"
using namespace rds;
@@ -144,12 +144,17 @@ public:
void focus() override;
std::string title() const override { return "RDS transmit"; };
std::string title() const override { return "RDS TX"; };
private:
NavigationView& nav_;
RDS_flags rds_flags { };
// app save settings
std::app_settings settings { };
std::app_settings::AppSettings app_settings { };
std::vector<RDSGroup> frame_psn { };
std::vector<RDSGroup> frame_radiotext { };
std::vector<RDSGroup> frame_datetime { };
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 */
+129 -53
View File
@@ -31,13 +31,23 @@ ScannerThread::ScannerThread(
std::vector<rf::Frequency> frequency_list
) : frequency_list_ { std::move(frequency_list) }
{
thread = chThdCreateFromHeap(NULL, 1024, NORMALPRIO + 10, ScannerThread::static_fn, this);
create_thread();
}
ScannerThread::ScannerThread(const jammer::jammer_range_t& frequency_range, size_t def_step) : frequency_range_(frequency_range), def_step_(def_step)
{
create_thread();
}
ScannerThread::~ScannerThread() {
stop();
}
void ScannerThread::create_thread()
{
thread = chThdCreateFromHeap(NULL, 1024, NORMALPRIO + 10, ScannerThread::static_fn, this);
}
void ScannerThread::stop() {
if( thread ) {
chThdTerminate(thread);
@@ -102,12 +112,13 @@ void ScannerThread::run() {
else
restart_scan=false; //Effectively skipping first retuning, giving system time
}
message.freq = frequency_list_[frequency_index];
message.range = frequency_index; //Inform freq (for coloring purposes also!)
EventDispatcher::send_message(message);
}
else { //NOT scanning
if (_freq_del != 0) { //There is a frequency to delete
for (uint16_t i = 0; i < frequency_list_.size(); i++) { //Search for the freq to delete
for (uint32_t i = 0; i < frequency_list_.size(); i++) { //Search for the freq to delete
if (frequency_list_[i] == _freq_del)
{ //found: Erase it
frequency_list_.erase(frequency_list_.begin() + i);
@@ -126,16 +137,58 @@ void ScannerThread::run() {
}
chThdSleepMilliseconds(50); //Needed to (eventually) stabilize the receiver into new freq
}
}else if(def_step_ > 0) // manual mode
{
RetuneMessage message { };
int64_t frequency_index = 0;
int64_t size = (frequency_range_.max - frequency_range_.min) / def_step_;
bool restart_scan = false; //Flag whenever scanning is restarting after a pause
while( !chThdShouldTerminate() ) {
if (_scanning) { //Scanning
if (_freq_lock == 0) { //normal scanning (not performing freq_lock)
if (!restart_scan) { //looping at full speed
if (_fwd) { //forward
frequency_index++;
if (frequency_index >= size)
frequency_index = 0;
} else { //reverse
if (frequency_index < 1)
frequency_index = size;
frequency_index--;
}
receiver_model.set_tuning_frequency(frequency_range_.min + frequency_index * def_step_); // Retune
}
else
restart_scan=false; //Effectively skipping first retuning, giving system time
}
message.freq = frequency_range_.min + frequency_index * def_step_;
message.range = 0; //Inform freq (for coloring purposes also!)
EventDispatcher::send_message(message);
}
else { //NOT scanning
restart_scan=true; //Flag the need for skipping a cycle when restarting scan
}
chThdSleepMilliseconds(50); //Needed to (eventually) stabilize the receiver into new freq
}
}
}
void ScannerView::handle_retune(uint32_t i) {
void ScannerView::handle_retune(int64_t freq, uint32_t freq_idx) {
current_index = freq_idx; //since it is an ongoing scan, this is a new index
current_frequency = freq;
switch (scan_thread->is_freq_lock())
{
case 0: //NO FREQ LOCK, ONGOING STANDARD SCANNING
text_cycle.set( to_string_dec_uint(i + 1,3) );
current_index = i; //since it is an ongoing scan, this is a new index
if (description_list[current_index].size() > 0) desc_cycle.set( description_list[current_index] ); //Show new description
if (frequency_list.size() > 0) {
text_cycle.set( to_string_dec_uint(freq_idx + 1,3) );
}
if (freq_idx < description_list.size() && description_list[freq_idx].size() > 0) {
desc_cycle.set( description_list[freq_idx] ); //Show new description
}
break;
case 1: //STARTING LOCK FREQ
big_display.set_style(&style_yellow);
@@ -146,7 +199,7 @@ void ScannerView::handle_retune(uint32_t i) {
default: //freq lock is checking the signal, do not update display
return;
}
big_display.set(frequency_list[current_index]); //UPDATE the big Freq after 0, 1 or MAX_FREQ_LOCK (at least, for color synching)
big_display.set(freq); //UPDATE the big Freq after 0, 1 or MAX_FREQ_LOCK (at least, for color synching)
}
void ScannerView::focus() {
@@ -154,15 +207,17 @@ void ScannerView::focus() {
}
ScannerView::~ScannerView() {
// make sure to stop the thread before shutting down the receiver
scan_thread.reset();
audio::output::stop();
receiver_model.disable();
baseband::shutdown();
}
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);
@@ -297,23 +352,15 @@ ScannerView::ScannerView(
description_list.clear();
def_step = step_mode.selected_index_value(); //Use def_step from manual selector
description_list.push_back(
"M" + to_string_short_freq(frequency_range.min) + ">"
+ to_string_short_freq(frequency_range.max) + "S"
+ to_string_short_freq(def_step).erase(0,1) //euquiq: lame kludge to reduce spacing in step freq
);
rf::Frequency frequency = frequency_range.min;
while (frequency_list.size() < MAX_DB_ENTRY && 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;
}
show_max();
desc_cycle.set("");
text_max.set("");
text_cycle.set("");
if ( userpause ) //If user-paused, resume
user_resume();
big_display.set_style(&style_grey); //Back to grey color
start_scan_thread(); //RESTART SCANNER THREAD
start_scan_thread(frequency_range, def_step); //RESTART SCANNER THREAD
}
};
@@ -333,35 +380,56 @@ ScannerView::ScannerView(
big_display.set_style(&style_grey); //Back to grey color
};
button_add.on_select = [this](Button&) { //frequency_list[current_index]
button_add.on_select = [this](Button&) { // current_frequency
File scanner_file;
std::string freq_file_path = "FREQMAN/" + loaded_file_name + ".TXT";
const std::string freq_file_path = "FREQMAN/" + loaded_file_name + ".TXT";
auto result = scanner_file.open(freq_file_path); //First search if freq is already in txt
if (!result.is_valid()) {
std::string frequency_to_add = "f="
+ to_string_dec_uint(frequency_list[current_index] / 1000)
+ to_string_dec_uint(frequency_list[current_index] % 1000UL, 3, '0');
char one_char[1]; //Read it char by char
std::string line; //and put read line in here
const std::string frequency_to_add = "f="
+ to_string_dec_uint(current_frequency / 1000)
+ to_string_dec_uint(current_frequency % 1000UL, 3, '0');
bool found=false;
for (size_t pointer=0; pointer < scanner_file.size();pointer++) {
constexpr size_t buffer_size = 1024;
char buffer[buffer_size];
for (size_t pointer = 0, freq_str_idx = 0; pointer < scanner_file.size(); pointer += buffer_size) {
size_t adjusted_buffer_size;
if (pointer + buffer_size >= scanner_file.size()) {
memset(buffer, 0, sizeof(buffer));
adjusted_buffer_size = scanner_file.size() - pointer;
}
else {
adjusted_buffer_size = buffer_size;
}
scanner_file.seek(pointer);
scanner_file.read(one_char, 1);
if ((int)one_char[0] > 31) { //ascii space upwards
line += one_char[0]; //Add it to the textline
}
else if (one_char[0] == '\n') { //New Line
if (line.compare(0, frequency_to_add.size(),frequency_to_add) == 0) {
found=true;
break;
scanner_file.read(buffer, adjusted_buffer_size);
for (size_t i = 0; i < adjusted_buffer_size; ++i) {
if (buffer[i] == frequency_to_add.data()[freq_str_idx]) {
++freq_str_idx;
if (freq_str_idx >= frequency_to_add.size()) {
found = true;
break;
}
}
else {
freq_str_idx = 0;
}
line.clear(); //Ready for next textline
}
}
if (found) {
break;
}
}
if (found) {
nav_.display_modal("Error", "Frequency already exists");
big_display.set(frequency_list[current_index]); //After showing an error
big_display.set(current_frequency); //After showing an error
}
else {
scanner_file.append(freq_file_path); //Second: append if it is not there
@@ -370,7 +438,7 @@ ScannerView::ScannerView(
} else
{
nav_.display_modal("Error", "Cannot open " + loaded_file_name + ".TXT\nfor appending freq.");
big_display.set(frequency_list[current_index]); //After showing an error
big_display.set(current_frequency); //After showing an error
}
};
@@ -398,7 +466,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 +489,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)
@@ -516,9 +584,9 @@ size_t ScannerView::change_mode(uint8_t new_mod) { //Before this, do a scan_thre
switch (new_mod) {
case NFM: //bw 16k (2) default
bw.emplace_back("8k5", 0);
bw.emplace_back("11k", 0);
bw.emplace_back("16k", 0);
bw.emplace_back("8k5 ", 0);
bw.emplace_back("11k ", 0);
bw.emplace_back("16k ", 0);
field_bw.set_options(bw);
baseband::run_image(portapack::spi_flash::image_tag_nfm_audio);
@@ -529,10 +597,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 +610,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);
@@ -564,4 +634,10 @@ void ScannerView::start_scan_thread() {
scan_thread = std::make_unique<ScannerThread>(frequency_list);
}
void ScannerView::start_scan_thread(const jammer::jammer_range_t& frequency_range, size_t def_step) {
receiver_model.enable();
receiver_model.set_squelch_level(0);
scan_thread = std::make_unique<ScannerThread>(frequency_range, def_step);
}
} /* namespace ui */
+12 -7
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 {
@@ -47,6 +46,7 @@ size_t const mod_step[3] = {9000, 100000, 12500 };
class ScannerThread {
public:
ScannerThread(std::vector<rf::Frequency> frequency_list);
ScannerThread(const jammer::jammer_range_t& frequency_range, size_t def_step);
~ScannerThread();
void set_scanning(const bool v);
@@ -68,6 +68,8 @@ public:
private:
std::vector<rf::Frequency> frequency_list_ { };
jammer::jammer_range_t frequency_range_ {false, 0, 0};
size_t def_step_ { 0 };
Thread* thread { nullptr };
bool _scanning { true };
@@ -76,6 +78,7 @@ private:
uint32_t _freq_del { 0 };
static msg_t static_fn(void* arg);
void run();
void create_thread();
};
class ScannerView : public View {
@@ -111,7 +114,7 @@ public:
.foreground = Color::red(),
};
std::string title() const override { return "SCANNER"; };
std::string title() const override { return "Scanner"; };
std::vector<rf::Frequency> frequency_list{ };
std::vector<string> description_list { };
@@ -121,6 +124,7 @@ private:
NavigationView& nav_;
void start_scan_thread();
void start_scan_thread(const jammer::jammer_range_t& frequency_range, size_t def_step);
size_t change_mode(uint8_t mod_type);
void show_max();
void scan_pause();
@@ -130,7 +134,7 @@ private:
void on_statistics_update(const ChannelStatistics& statistics);
void on_headphone_volume_changed(int32_t v);
void handle_retune(uint32_t i);
void handle_retune(int64_t freq, uint32_t freq_idx);
jammer::jammer_range_t frequency_range { false, 0, 0 }; //perfect for manual scan task too...
int32_t squelch { 0 };
@@ -140,11 +144,12 @@ private:
freqman_db database { };
std::string loaded_file_name;
uint32_t current_index { 0 };
rf::Frequency current_frequency { 0 };
bool userpause { false };
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 +182,7 @@ private:
};
NumberField field_squelch {
{ 15 * 8, 1 * 16 },
{ 18 * 8, 1 * 16 },
3,
{ -90, 20 },
1,
@@ -185,7 +190,7 @@ private:
};
NumberField field_wait {
{ 26 * 8, 1 * 16 },
{ 27 * 8, 1 * 16 },
2,
{ 0, 99 },
1,
@@ -296,7 +301,7 @@ private:
Message::ID::Retune,
[this](const Message* const p) {
const auto message = *reinterpret_cast<const RetuneMessage*>(p);
this->handle_retune(message.range);
this->handle_retune(message.freq, message.range);
}
};
+1 -1
View File
@@ -38,7 +38,7 @@ public:
~WipeSDView();
void focus() override;
std::string title() const override { return "Wipe FAT"; };
std::string title() const override { return "Wipe SD Card"; };
private:
NavigationView& nav_;
+52 -21
View File
@@ -234,6 +234,7 @@ SetUIView::SetUIView(NavigationView& nav) {
&checkbox_showsplash,
&checkbox_showclock,
&options_clockformat,
&checkbox_guireturnflag,
&button_save,
&button_cancel
});
@@ -242,14 +243,11 @@ SetUIView::SetUIView(NavigationView& nav) {
checkbox_speaker.set_value(persistent_memory::config_speaker());
checkbox_showsplash.set_value(persistent_memory::config_splash());
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);
@@ -257,19 +255,13 @@ SetUIView::SetUIView(NavigationView& nav) {
options_clockformat.set_selected_index(0);
}
//checkbox_speaker.on_select = [this](Checkbox&, bool v) {
// if (v) audio::output::speaker_mute(); //Just mute audio if speaker is disabled
// persistent_memory::set_config_speaker(v); //Store Speaker status
// StatusRefreshMessage message { }; //Refresh status bar with/out speaker
// EventDispatcher::send_message(message);
//};
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);
@@ -284,6 +276,7 @@ SetUIView::SetUIView(NavigationView& nav) {
persistent_memory::set_config_splash(checkbox_showsplash.value());
persistent_memory::set_clock_hidden(!checkbox_showclock.value());
persistent_memory::set_gui_return_icon(checkbox_guireturnflag.value());
persistent_memory::set_disable_touchscreen(checkbox_disable_touchscreen.value());
nav.pop();
};
@@ -296,6 +289,36 @@ void SetUIView::focus() {
button_save.focus();
}
// ---------------------------------------------------------
// Appl. Settings
// ---------------------------------------------------------
SetAppSettingsView::SetAppSettingsView(NavigationView& nav) {
add_children({
&checkbox_load_app_settings,
&checkbox_save_app_settings,
&button_save,
&button_cancel
});
checkbox_load_app_settings.set_value(persistent_memory::load_app_settings());
checkbox_save_app_settings.set_value(persistent_memory::save_app_settings());
button_save.on_select = [&nav, this](Button&) {
persistent_memory::set_load_app_settings(checkbox_load_app_settings.value());
persistent_memory::set_save_app_settings(checkbox_save_app_settings.value());
nav.pop();
};
button_cancel.on_select = [&nav, this](Button&) {
nav.pop();
};
}
void SetAppSettingsView::focus() {
button_save.focus();
}
SetAudioView::SetAudioView(NavigationView& nav) {
add_children({
&labels,
@@ -344,14 +367,22 @@ void SetQRCodeView::focus() {
button_save.focus();
}
// ---------------------------------------------------------
// Settings main menu
// ---------------------------------------------------------
SettingsMenuView::SettingsMenuView(NavigationView& nav) {
if( portapack::persistent_memory::show_gui_return_icon() )
{
add_items( { { "..", ui::Color::light_grey(),&bitmap_icon_previous, [&nav](){ nav.pop(); } } } );
}
add_items({
{ "Audio", ui::Color::dark_cyan(), &bitmap_icon_speaker, [&nav](){ nav.push<SetAudioView>(); } },
{ "Radio", ui::Color::dark_cyan(), &bitmap_icon_options_radio, [&nav](){ nav.push<SetRadioView>(); } },
{ "Interface", ui::Color::dark_cyan(), &bitmap_icon_options_ui, [&nav](){ nav.push<SetUIView>(); } },
{ "User Interface", ui::Color::dark_cyan(), &bitmap_icon_options_ui, [&nav](){ nav.push<SetUIView>(); } },
{ "Date/Time", ui::Color::dark_cyan(), &bitmap_icon_options_datetime, [&nav](){ nav.push<SetDateTimeView>(); } },
{ "Touchscreen", ui::Color::dark_cyan(), &bitmap_icon_options_touch, [&nav](){ nav.push<TouchCalibrationView>(); } },
{ "QR code", ui::Color::dark_cyan(), &bitmap_icon_qr_code, [&nav](){ nav.push<SetQRCodeView>(); } }
{ "Calibration", ui::Color::dark_cyan(), &bitmap_icon_options_touch, [&nav](){ nav.push<TouchCalibrationView>(); } },
{ "App Settings", ui::Color::dark_cyan(), &bitmap_icon_setup, [&nav](){ nav.push<SetAppSettingsView>(); } },
{ "QR Code", ui::Color::dark_cyan(), &bitmap_icon_qr_code, [&nav](){ nav.push<SetQRCodeView>(); } }
});
set_max_rows(2); // allow wider buttons
}
+52 -9
View File
@@ -27,6 +27,7 @@
#include "ui_menu.hpp"
#include "ui_navigation.hpp"
#include "ff.h"
#include "portapack_persistent_memory.hpp"
#include <cstdint>
@@ -47,7 +48,7 @@ public:
void focus() override;
std::string title() const override { return "Set Date/Time"; };
std::string title() const override { return "Date/Time"; };
private:
Labels labels {
@@ -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 },
}
};
@@ -271,6 +275,45 @@ private:
{ "time and date", 1 }
}
};
Checkbox checkbox_guireturnflag {
{ 3 * 8, 14 * 16 },
25,
"add return icon in GUI"
};
Button button_save {
{ 2 * 8, 16 * 16, 12 * 8, 32 },
"Save"
};
Button button_cancel {
{ 16 * 8, 16 * 16, 12 * 8, 32 },
"Cancel",
};
};
class SetAppSettingsView : public View {
public:
SetAppSettingsView(NavigationView& nav);
void focus() override;
std::string title() const override { return "App Settings"; };
private:
Checkbox checkbox_load_app_settings {
{ 3 * 8, 2 * 16 },
25,
"Load app settings"
};
Checkbox checkbox_save_app_settings {
{ 3 * 8, 4 * 16 },
25,
"Save app settings"
};
Button button_save {
{ 2 * 8, 16 * 16, 12 * 8, 32 },
@@ -322,7 +365,7 @@ public:
void focus() override;
std::string title() const override { return "QR code"; };
std::string title() const override { return "QR Code"; };
private:
Checkbox checkbox_bigger_qr {
+1 -1
View File
@@ -40,7 +40,7 @@ public:
void focus() override;
std::string title() const override { return "Generator"; };
std::string title() const override { return "Signal gen"; };
private:
void start_tx();
+20 -14
View File
@@ -23,6 +23,7 @@
#include "ui_sonde.hpp"
#include "baseband_api.hpp"
#include "audio.hpp"
#include "app_settings.hpp"
#include "portapack.hpp"
#include <cstring>
@@ -43,6 +44,8 @@ namespace ui {
SondeView::SondeView(NavigationView& nav) {
baseband::run_image(portapack::spi_flash::image_tag_sonde);
add_children({
@@ -68,8 +71,17 @@ SondeView::SondeView(NavigationView& nav) {
&button_see_map
});
// start from the frequency currently stored in the receiver_model:
target_frequency_ = receiver_model.tuning_frequency();
// load app settings
auto rc = settings.load("rx_sonde", &app_settings);
if(rc == SETTINGS_OK) {
field_lna.set_value(app_settings.lna);
field_vga.set_value(app_settings.vga);
field_rf_amp.set_value(app_settings.rx_amp);
target_frequency_ = app_settings.rx_frequency;
}
else target_frequency_ = receiver_model.tuning_frequency();
field_frequency.set_value(target_frequency_);
field_frequency.set_step(500); //euquiq: was 10000, but we are using this for fine-tunning
@@ -104,16 +116,6 @@ SondeView::SondeView(NavigationView& nav) {
receiver_model.set_sampling_rate(sampling_rate);
receiver_model.set_baseband_bandwidth(baseband_bandwidth);
receiver_model.enable(); // Before using radio::enable(), but not updating Ant.DC-Bias.
/* radio::enable({ // this can be removed, previous version, no DC-bias ant. control.
tuning_frequency(),
sampling_rate,
baseband_bandwidth,
rf::Direction::Receive,
receiver_model.rf_amp(),
static_cast<int8_t>(receiver_model.lna()),
static_cast<int8_t>(receiver_model.vga()),
}); */
// QR code with geo URI
@@ -157,9 +159,13 @@ SondeView::SondeView(NavigationView& nav) {
}
SondeView::~SondeView() {
// save app settings
app_settings.rx_frequency = target_frequency_;
settings.save("rx_sonde", &app_settings);
baseband::set_pitch_rssi(0, false);
/* radio::disable(); */
receiver_model.disable(); // to switch off all, including DC bias.
receiver_model.disable(); // to switch off all, including DC bias.
baseband::shutdown();
audio::output::stop();
}
+4 -1
View File
@@ -34,7 +34,7 @@
#include "log_file.hpp"
#include "sonde_packet.hpp"
#include "app_settings.hpp"
#include <cstddef>
#include <string>
@@ -74,6 +74,9 @@ private:
bool beep { false };
char geo_uri[32] = {};
// app save settings
std::app_settings settings { };
std::app_settings::AppSettings app_settings { };
sonde::GPS_data gps_info { };
sonde::temp_humid temp_humid_info { };
+16 -1
View File
@@ -25,6 +25,7 @@
#include "portapack.hpp"
#include "hackrf_hal.hpp"
#include "cpld_update.hpp"
#include <cstring>
#include <stdio.h>
@@ -88,8 +89,13 @@ void SSTVTXView::paint(Painter&) {
}
SSTVTXView::~SSTVTXView() {
// save app settings
app_settings.tx_frequency = transmitter_model.tuning_frequency();
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) {
@@ -215,6 +221,15 @@ SSTVTXView::SSTVTXView(
options_t mode_options;
uint32_t c;
// load app settings
auto rc = settings.load("tx_sstv", &app_settings);
if(rc == SETTINGS_OK) {
transmitter_model.set_rf_amp(app_settings.tx_amp);
transmitter_model.set_channel_bandwidth(app_settings.channel_bandwidth);
transmitter_model.set_tuning_frequency(app_settings.tx_frequency);
transmitter_model.set_tx_gain(app_settings.tx_gain);
}
// Search for valid bitmaps
file_list = scan_root_files(u"/sstv", u"*.bmp");
if (!file_list.size()) {
+5 -1
View File
@@ -34,6 +34,7 @@
#include "sstv.hpp"
#include "file.hpp"
#include "bmp.hpp"
#include "app_settings.hpp"
using namespace sstv;
@@ -58,7 +59,10 @@ private:
NavigationView& nav_;
sstv_scanline scanline_buffer { };
// app save settings
std::app_settings settings { };
std::app_settings::AppSettings app_settings { };
bool file_error { false };
File bmp_file { };
bmp_header_t bmp_header { };
@@ -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() {
+28 -15
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
};
@@ -294,7 +307,7 @@ void run_image(const portapack::spi_flash::image_tag_t image_tag) {
creg::m4txevent::clear();
m4_init(image_tag, portapack::memory::map::m4_code);
m4_init(image_tag, portapack::memory::map::m4_code, false);
baseband_image_running = true;
creg::m4txevent::enable();
@@ -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();
+204 -91
View File
@@ -41,12 +41,18 @@ constexpr si5351::Inputs si5351_inputs {
static_assert(si5351_inputs.f_xtal == si5351_xtal_f, "XTAL output frequency wrong");
static_assert(si5351_inputs.f_clkin_out() == si5351_clkin_f, "CLKIN output frequency wrong");
constexpr si5351::PLLInputSource::Type si5351_pll_input_sources {
constexpr si5351::PLLInputSource::Type si5351c_pll_input_sources {
si5351::PLLInputSource::PLLA_Source_XTAL
| si5351::PLLInputSource::PLLB_Source_CLKIN
| si5351::PLLInputSource::CLKIN_Div1
};
constexpr si5351::PLLInputSource::Type si5351a_pll_input_sources {
si5351::PLLInputSource::PLLA_Source_XTAL
| si5351::PLLInputSource::PLLB_Source_XTAL
| si5351::PLLInputSource::CLKIN_Div1
};
constexpr si5351::PLL si5351_pll_xtal_25m {
.f_in = si5351_inputs.f_xtal,
.a = 32,
@@ -61,7 +67,8 @@ constexpr si5351::PLL si5351_pll_clkin_10m {
.b = 0,
.c = 1,
};
constexpr auto si5351_pll_b_clkin_reg = si5351_pll_clkin_10m.reg(1);
constexpr auto si5351c_pll_b_clkin_reg = si5351_pll_clkin_10m.reg(1);
constexpr auto si5351a_pll_a_clkin_reg = si5351_pll_clkin_10m.reg(0);
static_assert(si5351_pll_xtal_25m.f_vco() == si5351_vco_f, "PLL XTAL frequency wrong");
static_assert(si5351_pll_xtal_25m.p1() == 3584, "PLL XTAL P1 wrong");
@@ -98,7 +105,7 @@ constexpr si5351::MultisynthFractional si5351_ms_0_8m {
.c = 1,
.r_div = 1,
};
constexpr auto si5351_ms_0_8m_reg = si5351_ms_0_8m.reg(clock_generator_output_codec);
constexpr auto si5351c_ms_0_8m_reg = si5351_ms_0_8m.reg(clock_generator_output_og_codec);
constexpr si5351::MultisynthFractional si5351_ms_group {
.f_src = si5351_vco_f,
@@ -107,8 +114,17 @@ constexpr si5351::MultisynthFractional si5351_ms_group {
.c = 1,
.r_div = 0,
};
constexpr auto si5351_ms_1_group_reg = si5351_ms_group.reg(clock_generator_output_cpld);
constexpr auto si5351_ms_2_group_reg = si5351_ms_group.reg(clock_generator_output_sgpio);
constexpr auto si5351c_ms_1_group_reg = si5351_ms_group.reg(clock_generator_output_og_cpld);
constexpr auto si5351c_ms_2_group_reg = si5351_ms_group.reg(clock_generator_output_og_sgpio);
constexpr si5351::MultisynthFractional si5351_ms_16m {
.f_src = si5351_vco_f,
.a = 50,
.b = 0,
.c = 1,
.r_div = 0,
};
constexpr auto si5351a_ms_1_sgpio_16m_reg = si5351_ms_16m.reg(clock_generator_output_r9_sgpio);
constexpr si5351::MultisynthFractional si5351_ms_10m {
.f_src = si5351_vco_f,
@@ -117,7 +133,8 @@ constexpr si5351::MultisynthFractional si5351_ms_10m {
.c = 1,
.r_div = 0,
};
constexpr auto si5351_ms_3_10m_reg = si5351_ms_10m.reg(3);
constexpr auto si5351c_ms_3_10m_reg = si5351_ms_10m.reg(3);
constexpr auto si5351a_ms_2_mcu_10m_reg = si5351_ms_10m.reg(clock_generator_output_r9_mcu_clkin);
constexpr si5351::MultisynthFractional si5351_ms_40m {
.f_src = si5351_vco_f,
@@ -128,10 +145,11 @@ constexpr si5351::MultisynthFractional si5351_ms_40m {
};
constexpr auto si5351_ms_rffc5072 = si5351_ms_40m;
constexpr auto si5351_ms_max2837 = si5351_ms_40m;
constexpr auto si5351_ms_max283x = si5351_ms_40m;
constexpr auto si5351_ms_4_reg = si5351_ms_rffc5072.reg(clock_generator_output_first_if);
constexpr auto si5351_ms_5_reg = si5351_ms_max2837.reg(clock_generator_output_second_if);
constexpr auto si5351c_ms_4_reg = si5351_ms_rffc5072.reg(clock_generator_output_og_first_if);
constexpr auto si5351c_ms_5_reg = si5351_ms_max283x.reg(clock_generator_output_og_second_if);
constexpr auto si5351a_ms_0_if_40m_reg = si5351_ms_40m.reg(clock_generator_output_r9_if);
static_assert(si5351_ms_10m.f_out() == 10000000, "MS 10MHz f_out wrong");
static_assert(si5351_ms_10m.p1() == 9728, "MS 10MHz p1 wrong");
@@ -139,14 +157,8 @@ static_assert(si5351_ms_10m.p2() == 0, "MS 10MHz p2 wrong");
static_assert(si5351_ms_10m.p3() == 1, "MS 10MHz p3 wrong");
static_assert(si5351_ms_rffc5072.f_out() == rffc5072_reference_f, "RFFC5072 reference f_out wrong");
// static_assert(si5351_ms_50m.p1() == 2048, "MS 50MHz P1 wrong");
// static_assert(si5351_ms_50m.p2() == 0, "MS 50MHz P2 wrong");
// static_assert(si5351_ms_50m.p3() == 1, "MS 50MHz P3 wrong");
static_assert(si5351_ms_max2837.f_out() == max2837_reference_f, "MAX2837 reference f_out wrong");
// static_assert(si5351_ms_50m.p1() == 2048, "MS 40MHz P1 wrong");
// static_assert(si5351_ms_50m.p2() == 0, "MS 40MHz P2 wrong");
// static_assert(si5351_ms_50m.p3() == 1, "MS 40MHz P3 wrong");
static_assert(si5351_ms_max283x.f_out() == max283x_reference_f, "MAX283x reference f_out wrong");
constexpr si5351::MultisynthInteger si5351_ms_int_off {
.f_src = si5351_vco_f,
@@ -154,40 +166,60 @@ constexpr si5351::MultisynthInteger si5351_ms_int_off {
.r_div = 0,
};
constexpr si5351::MultisynthInteger si5351_ms_int_mcu_clkin {
constexpr si5351::MultisynthInteger si5351_ms_int_40m {
.f_src = si5351_vco_f,
.a = 20,
.r_div = 0,
};
constexpr auto si5351_ms6_7_off_mcu_clkin_reg = si5351::ms6_7_reg(si5351_ms_int_off, si5351_ms_int_mcu_clkin);
constexpr si5351::MultisynthInteger si5351_ms_int_10m {
.f_src = si5351_vco_f,
.a = 80,
.r_div = 0,
};
constexpr auto si5351c_ms_int_mcu_clkin = si5351_ms_int_40m;
constexpr auto si5351a_ms_int_mcu_clkin = si5351_ms_int_10m;
constexpr auto si5351c_ms6_7_off_mcu_clkin_reg = si5351::ms6_7_reg(si5351_ms_int_off, si5351c_ms_int_mcu_clkin);
constexpr auto si5351a_ms6_7_off_reg = si5351::ms6_7_reg(si5351_ms_int_off, si5351_ms_int_off);
static_assert(si5351_ms_int_off.f_out() == 3137254, "MS int off f_out wrong");
static_assert(si5351_ms_int_off.p1() == 255, "MS int off P1 wrong");
static_assert(si5351_ms_int_mcu_clkin.f_out() == mcu_clkin_f, "MS int MCU CLKIN f_out wrong");
// static_assert(si5351_ms_int_mcu_clkin.p1() == 20, "MS int MCU CLKIN P1 wrong");
static_assert(si5351c_ms_int_mcu_clkin.f_out() == mcu_clkin_og_f, "MS int MCU CLKIN OG f_out wrong");
static_assert(si5351a_ms_int_mcu_clkin.f_out() == mcu_clkin_r9_f, "MS int MCU CLKIN r9 f_out wrong");
using namespace si5351;
static constexpr ClockControl::MultiSynthSource get_reference_clock_generator_pll(const ClockManager::ReferenceSource reference_source) {
static constexpr ClockControl::MultiSynthSource get_si5351c_reference_clock_generator_pll(const ClockManager::ReferenceSource reference_source) {
return (reference_source == ClockManager::ReferenceSource::Xtal)
? ClockControl::MultiSynthSource::PLLA
: ClockControl::MultiSynthSource::PLLB
;
}
constexpr ClockControls si5351_clock_control_common { {
{ ClockControl::ClockCurrentDrive::_8mA, ClockControl::ClockSource::MS_Self, ClockControl::ClockInvert::Normal, get_reference_clock_generator_pll(ClockManager::ReferenceSource::Xtal), ClockControl::MultiSynthMode::Fractional, ClockControl::ClockPowerDown::Power_Off },
{ ClockControl::ClockCurrentDrive::_2mA, ClockControl::ClockSource::MS_Group, ClockControl::ClockInvert::Invert, get_reference_clock_generator_pll(ClockManager::ReferenceSource::Xtal), ClockControl::MultiSynthMode::Integer, ClockControl::ClockPowerDown::Power_Off },
{ ClockControl::ClockCurrentDrive::_2mA, ClockControl::ClockSource::MS_Group, ClockControl::ClockInvert::Normal, get_reference_clock_generator_pll(ClockManager::ReferenceSource::Xtal), ClockControl::MultiSynthMode::Integer, ClockControl::ClockPowerDown::Power_Off },
{ ClockControl::ClockCurrentDrive::_8mA, ClockControl::ClockSource::MS_Self, ClockControl::ClockInvert::Normal, get_reference_clock_generator_pll(ClockManager::ReferenceSource::Xtal), ClockControl::MultiSynthMode::Integer, ClockControl::ClockPowerDown::Power_Off },
{ ClockControl::ClockCurrentDrive::_6mA, ClockControl::ClockSource::MS_Self, ClockControl::ClockInvert::Invert, get_reference_clock_generator_pll(ClockManager::ReferenceSource::Xtal), ClockControl::MultiSynthMode::Integer, ClockControl::ClockPowerDown::Power_Off },
{ ClockControl::ClockCurrentDrive::_4mA, ClockControl::ClockSource::MS_Self, ClockControl::ClockInvert::Normal, get_reference_clock_generator_pll(ClockManager::ReferenceSource::Xtal), ClockControl::MultiSynthMode::Integer, ClockControl::ClockPowerDown::Power_Off },
{ ClockControl::ClockCurrentDrive::_2mA, ClockControl::ClockSource::MS_Self, ClockControl::ClockInvert::Normal, get_reference_clock_generator_pll(ClockManager::ReferenceSource::Xtal), ClockControl::MultiSynthMode::Fractional, ClockControl::ClockPowerDown::Power_Off },
{ ClockControl::ClockCurrentDrive::_2mA, ClockControl::ClockSource::MS_Self, ClockControl::ClockInvert::Normal, get_reference_clock_generator_pll(ClockManager::ReferenceSource::Xtal), ClockControl::MultiSynthMode::Integer, ClockControl::ClockPowerDown::Power_Off },
constexpr ClockControls si5351c_clock_control_common { {
{ ClockControl::ClockCurrentDrive::_8mA, ClockControl::ClockSource::MS_Self, ClockControl::ClockInvert::Normal, get_si5351c_reference_clock_generator_pll(ClockManager::ReferenceSource::Xtal), ClockControl::MultiSynthMode::Fractional, ClockControl::ClockPowerDown::Power_Off },
{ ClockControl::ClockCurrentDrive::_2mA, ClockControl::ClockSource::MS_Group, ClockControl::ClockInvert::Invert, get_si5351c_reference_clock_generator_pll(ClockManager::ReferenceSource::Xtal), ClockControl::MultiSynthMode::Integer, ClockControl::ClockPowerDown::Power_Off },
{ ClockControl::ClockCurrentDrive::_2mA, ClockControl::ClockSource::MS_Group, ClockControl::ClockInvert::Normal, get_si5351c_reference_clock_generator_pll(ClockManager::ReferenceSource::Xtal), ClockControl::MultiSynthMode::Integer, ClockControl::ClockPowerDown::Power_Off },
{ ClockControl::ClockCurrentDrive::_8mA, ClockControl::ClockSource::MS_Self, ClockControl::ClockInvert::Normal, get_si5351c_reference_clock_generator_pll(ClockManager::ReferenceSource::Xtal), ClockControl::MultiSynthMode::Integer, ClockControl::ClockPowerDown::Power_Off },
{ ClockControl::ClockCurrentDrive::_6mA, ClockControl::ClockSource::MS_Self, ClockControl::ClockInvert::Invert, get_si5351c_reference_clock_generator_pll(ClockManager::ReferenceSource::Xtal), ClockControl::MultiSynthMode::Integer, ClockControl::ClockPowerDown::Power_Off },
{ ClockControl::ClockCurrentDrive::_4mA, ClockControl::ClockSource::MS_Self, ClockControl::ClockInvert::Normal, get_si5351c_reference_clock_generator_pll(ClockManager::ReferenceSource::Xtal), ClockControl::MultiSynthMode::Integer, ClockControl::ClockPowerDown::Power_Off },
{ ClockControl::ClockCurrentDrive::_2mA, ClockControl::ClockSource::MS_Self, ClockControl::ClockInvert::Normal, get_si5351c_reference_clock_generator_pll(ClockManager::ReferenceSource::Xtal), ClockControl::MultiSynthMode::Fractional, ClockControl::ClockPowerDown::Power_Off },
{ ClockControl::ClockCurrentDrive::_2mA, ClockControl::ClockSource::MS_Self, ClockControl::ClockInvert::Normal, get_si5351c_reference_clock_generator_pll(ClockManager::ReferenceSource::Xtal), ClockControl::MultiSynthMode::Integer, ClockControl::ClockPowerDown::Power_Off },
} };
constexpr ClockControls si5351a_clock_control_common { {
{ ClockControl::ClockCurrentDrive::_6mA, ClockControl::ClockSource::MS_Self, ClockControl::ClockInvert::Normal, ClockControl::MultiSynthSource::PLLA, ClockControl::MultiSynthMode::Integer, ClockControl::ClockPowerDown::Power_Off },
{ ClockControl::ClockCurrentDrive::_4mA, ClockControl::ClockSource::MS_Self, ClockControl::ClockInvert::Normal, ClockControl::MultiSynthSource::PLLA, ClockControl::MultiSynthMode::Fractional, ClockControl::ClockPowerDown::Power_Off },
{ ClockControl::ClockCurrentDrive::_8mA, ClockControl::ClockSource::MS_Self, ClockControl::ClockInvert::Normal, ClockControl::MultiSynthSource::PLLA, ClockControl::MultiSynthMode::Integer, ClockControl::ClockPowerDown::Power_Off },
{ ClockControl::ClockCurrentDrive::_2mA, ClockControl::ClockSource::MS_Self, ClockControl::ClockInvert::Normal, ClockControl::MultiSynthSource::PLLA, ClockControl::MultiSynthMode::Integer, ClockControl::ClockPowerDown::Power_Off },
{ ClockControl::ClockCurrentDrive::_2mA, ClockControl::ClockSource::MS_Self, ClockControl::ClockInvert::Normal, ClockControl::MultiSynthSource::PLLA, ClockControl::MultiSynthMode::Integer, ClockControl::ClockPowerDown::Power_Off },
{ ClockControl::ClockCurrentDrive::_2mA, ClockControl::ClockSource::MS_Self, ClockControl::ClockInvert::Normal, ClockControl::MultiSynthSource::PLLA, ClockControl::MultiSynthMode::Integer, ClockControl::ClockPowerDown::Power_Off },
{ ClockControl::ClockCurrentDrive::_2mA, ClockControl::ClockSource::MS_Self, ClockControl::ClockInvert::Normal, ClockControl::MultiSynthSource::PLLA, ClockControl::MultiSynthMode::Integer, ClockControl::ClockPowerDown::Power_Off },
{ ClockControl::ClockCurrentDrive::_2mA, ClockControl::ClockSource::MS_Self, ClockControl::ClockInvert::Normal, ClockControl::MultiSynthSource::PLLA, ClockControl::MultiSynthMode::Integer, ClockControl::ClockPowerDown::Power_Off },
} };
ClockManager::Reference ClockManager::get_reference() const {
return reference;
}
@@ -212,11 +244,25 @@ void ClockManager::init_clock_generator() {
clock_generator.reset();
clock_generator.set_crystal_internal_load_capacitance(CrystalInternalLoadCapacitance::XTAL_CL_8pF);
clock_generator.enable_fanout();
clock_generator.set_pll_input_sources(si5351_pll_input_sources);
clock_generator.set_pll_input_sources(hackrf_r9
? si5351a_pll_input_sources
: si5351c_pll_input_sources);
auto si5351_clock_control_common = hackrf_r9
? si5351a_clock_control_common
: si5351c_clock_control_common;
auto clock_generator_output_mcu_clkin = hackrf_r9
? clock_generator_output_r9_mcu_clkin
: clock_generator_output_og_mcu_clkin;
clock_generator.set_clock_control(
clock_generator_output_mcu_clkin,
si5351_clock_control_common[clock_generator_output_mcu_clkin].clk_src(ClockControl::ClockSource::CLKIN).clk_pdn(ClockControl::ClockPowerDown::Power_On)
si5351_clock_control_common[clock_generator_output_mcu_clkin]
.clk_src(hackrf_r9
? ClockControl::ClockSource::Xtal
: ClockControl::ClockSource::CLKIN)
.clk_pdn(ClockControl::ClockPowerDown::Power_On)
);
clock_generator.enable_output(clock_generator_output_mcu_clkin);
@@ -224,7 +270,10 @@ void ClockManager::init_clock_generator() {
clock_generator.disable_output(clock_generator_output_mcu_clkin);
const auto ref_pll = get_reference_clock_generator_pll(reference.source);
const auto ref_pll = hackrf_r9
? ClockControl::MultiSynthSource::PLLA
: get_si5351c_reference_clock_generator_pll(reference.source);
const ClockControls si5351_clock_control = ClockControls { {
si5351_clock_control_common[0].ms_src(ref_pll),
si5351_clock_control_common[1].ms_src(ref_pll),
@@ -237,21 +286,35 @@ void ClockManager::init_clock_generator() {
} };
clock_generator.set_clock_control(si5351_clock_control);
clock_generator.write(si5351_pll_a_xtal_reg);
clock_generator.write(si5351_pll_b_clkin_reg);
clock_generator.write(si5351_ms_0_8m_reg);
clock_generator.write(si5351_ms_1_group_reg);
clock_generator.write(si5351_ms_2_group_reg);
clock_generator.write(si5351_ms_3_10m_reg);
clock_generator.write(si5351_ms_4_reg);
clock_generator.write(si5351_ms_5_reg);
clock_generator.write(si5351_ms6_7_off_mcu_clkin_reg);
if (hackrf_r9) {
const PLLReg pll_reg = (reference.source == ReferenceSource::Xtal)
? si5351_pll_a_xtal_reg
: si5351a_pll_a_clkin_reg;
clock_generator.write(pll_reg);
clock_generator.write(si5351a_ms_0_if_40m_reg);
clock_generator.write(si5351a_ms_1_sgpio_16m_reg);
clock_generator.write(si5351a_ms_2_mcu_10m_reg);
clock_generator.write(si5351a_ms6_7_off_reg);
} else {
clock_generator.write(si5351_pll_a_xtal_reg);
clock_generator.write(si5351c_pll_b_clkin_reg);
clock_generator.write(si5351c_ms_0_8m_reg);
clock_generator.write(si5351c_ms_1_group_reg);
clock_generator.write(si5351c_ms_2_group_reg);
clock_generator.write(si5351c_ms_3_10m_reg);
clock_generator.write(si5351c_ms_4_reg);
clock_generator.write(si5351c_ms_5_reg);
clock_generator.write(si5351c_ms6_7_off_mcu_clkin_reg);
}
clock_generator.reset_plls();
// Wait for both PLLs to lock.
// TODO: Disable the unused PLL?
const uint8_t device_status_mask = (ref_pll == ClockControl::MultiSynthSource::PLLB) ? 0x40 : 0x20;
// Wait for PLL(s) to lock.
uint8_t device_status_mask = hackrf_r9
? 0x20
: (ref_pll == ClockControl::MultiSynthSource::PLLB)
? 0x40
: 0x20;
while((clock_generator.device_status() & device_status_mask) != 0);
clock_generator.set_clock_control(
@@ -268,12 +331,18 @@ uint32_t ClockManager::measure_gp_clkin_frequency() {
return get_frequency_monitor_measurement_in_hertz();
}
bool ClockManager::loss_of_signal() {
return hackrf_r9
? clock_generator.plla_loss_of_signal()
: clock_generator.clkin_loss_of_signal();
}
ClockManager::ReferenceSource ClockManager::detect_reference_source() {
if( clock_generator.clkin_loss_of_signal() ) {
if(loss_of_signal()) {
// No external reference. Turn on PortaPack reference (if present).
portapack_tcxo_enable();
if( clock_generator.clkin_loss_of_signal() ) {
if(loss_of_signal()) {
// No PortaPack reference was detected. Choose the HackRF crystal as the reference.
return ReferenceSource::Xtal;
} else {
@@ -285,6 +354,11 @@ ClockManager::ReferenceSource ClockManager::detect_reference_source() {
}
ClockManager::Reference ClockManager::choose_reference() {
if (hackrf_r9) {
gpio_r9_clkin_en.write(1);
volatile uint32_t delay = 240000 + 24000;
while(delay--);
}
const auto detected_reference = detect_reference_source();
if( (detected_reference == ReferenceSource::External) ||
@@ -296,8 +370,12 @@ ClockManager::Reference ClockManager::choose_reference() {
}
}
if (hackrf_r9) {
gpio_r9_clkin_en.write(0);
}
portapack_tcxo_disable();
return { ReferenceSource::Xtal, 10000000 };
return { ReferenceSource::Xtal, 25000000 };
}
void ClockManager::shutdown() {
@@ -305,18 +383,26 @@ void ClockManager::shutdown() {
}
void ClockManager::enable_codec_clocks() {
clock_generator.enable_clock(clock_generator_output_codec);
clock_generator.enable_clock(clock_generator_output_cpld);
clock_generator.enable_clock(clock_generator_output_sgpio);
if (hackrf_r9) {
clock_generator.enable_clock(clock_generator_output_r9_sgpio);
} else {
clock_generator.enable_clock(clock_generator_output_og_codec);
clock_generator.enable_clock(clock_generator_output_og_cpld);
clock_generator.enable_clock(clock_generator_output_og_sgpio);
}
/* Turn on all outputs at the same time. This probably doesn't ensure
* their phase relationships. For example, clocks that output frequencies
* in a 2:1 relationship may start with the slower clock high or low?
*/
clock_generator.enable_output_mask(
(1U << clock_generator_output_codec)
| (1U << clock_generator_output_cpld)
| (1U << clock_generator_output_sgpio)
);
if (hackrf_r9) {
clock_generator.enable_output_mask(1U << clock_generator_output_r9_sgpio);
} else {
clock_generator.enable_output_mask(
(1U << clock_generator_output_og_codec)
| (1U << clock_generator_output_og_cpld)
| (1U << clock_generator_output_og_sgpio)
);
}
}
void ClockManager::disable_codec_clocks() {
@@ -324,34 +410,45 @@ void ClockManager::disable_codec_clocks() {
* be enabled for the output to come to rest at the state specified by
* CLKx_DISABLE_STATE.
*/
clock_generator.disable_output_mask(
(1U << clock_generator_output_codec)
| (1U << clock_generator_output_cpld)
| (1U << clock_generator_output_sgpio)
);
clock_generator.disable_clock(clock_generator_output_codec);
clock_generator.disable_clock(clock_generator_output_cpld);
clock_generator.disable_clock(clock_generator_output_sgpio);
if (hackrf_r9) {
clock_generator.disable_output_mask(1U << clock_generator_output_r9_sgpio);
clock_generator.disable_clock(clock_generator_output_r9_sgpio);
} else {
clock_generator.disable_output_mask(
(1U << clock_generator_output_og_codec)
| (1U << clock_generator_output_og_cpld)
| (1U << clock_generator_output_og_sgpio)
);
clock_generator.disable_clock(clock_generator_output_og_codec);
clock_generator.disable_clock(clock_generator_output_og_cpld);
clock_generator.disable_clock(clock_generator_output_og_sgpio);
}
}
void ClockManager::enable_first_if_clock() {
clock_generator.enable_clock(clock_generator_output_first_if);
clock_generator.enable_output_mask(1U << clock_generator_output_first_if);
void ClockManager::enable_if_clocks() {
if (hackrf_r9) {
clock_generator.enable_clock(clock_generator_output_r9_if);
clock_generator.enable_output_mask(1U << clock_generator_output_r9_if);
} else {
clock_generator.enable_clock(clock_generator_output_og_first_if);
clock_generator.enable_output_mask(1U << clock_generator_output_og_first_if);
clock_generator.enable_clock(clock_generator_output_og_second_if);
clock_generator.enable_output_mask(1U << clock_generator_output_og_second_if);
}
}
void ClockManager::disable_first_if_clock() {
clock_generator.disable_output_mask(1U << clock_generator_output_first_if);
clock_generator.disable_clock(clock_generator_output_first_if);
}
void ClockManager::enable_second_if_clock() {
clock_generator.enable_clock(clock_generator_output_second_if);
clock_generator.enable_output_mask(1U << clock_generator_output_second_if);
}
void ClockManager::disable_second_if_clock() {
clock_generator.disable_output_mask(1U << clock_generator_output_second_if);
clock_generator.disable_clock(clock_generator_output_second_if);
void ClockManager::disable_if_clocks() {
if (hackrf_r9) {
clock_generator.disable_output_mask(1U << clock_generator_output_r9_if);
clock_generator.disable_clock(clock_generator_output_r9_if);
} else {
clock_generator.disable_output_mask(1U << clock_generator_output_og_first_if);
clock_generator.disable_clock(clock_generator_output_og_first_if);
clock_generator.disable_output_mask(1U << clock_generator_output_og_second_if);
clock_generator.disable_clock(clock_generator_output_og_second_if);
}
}
void ClockManager::set_sampling_frequency(const uint32_t frequency) {
@@ -360,14 +457,21 @@ void ClockManager::set_sampling_frequency(const uint32_t frequency) {
* necessary to change the MS0 synth frequency, and ensure the output
* is divided by two.
*/
clock_generator.set_ms_frequency(clock_generator_output_codec, frequency * 2, si5351_vco_f, 1);
if (hackrf_r9) {
clock_generator.set_ms_frequency(clock_generator_output_r9_sgpio, frequency * 2, si5351_vco_f, 0);
} else {
clock_generator.set_ms_frequency(clock_generator_output_og_codec, frequency * 2, si5351_vco_f, 1);
}
}
void ClockManager::set_reference_ppb(const int32_t ppb) {
/* NOTE: This adjustment only affects PLLA, which is derived from the 25MHz crystal.
* It is assumed an external clock coming in to PLLB is sufficiently accurate as to not need adjustment.
/* NOTE: This adjustment only affects PLLA when it is derived from the 25MHz crystal.
* It is assumed an external clock coming in to CLKIN/PLLB is sufficiently accurate as to not need adjustment.
* TODO: Revisit the above policy. It may be good to allow adjustment of the external reference too.
*/
if (hackrf_r9 && reference.source != ReferenceSource::Xtal) {
return;
}
constexpr uint32_t pll_multiplier = si5351_pll_xtal_25m.a;
constexpr uint32_t denominator = 1000000 / pll_multiplier;
const uint32_t new_a = (ppb >= 0) ? pll_multiplier : (pll_multiplier - 1);
@@ -425,11 +529,13 @@ void ClockManager::start_audio_pll() {
/* For 40MHz clock source, 48kHz audio rate, 256Fs MCLK:
* Fout=12.288MHz, Fcco=491.52MHz
* PSEL=20, NSEL=125, MSEL=768
* OG: PSEL=20, NSEL=125, MSEL=768
* PDEC=31, NDEC=45, MDEC=30542
* r9: PSEL=20, NSEL=125, MSEL=3072
* PDEC=31, NDEC=45, MDEC=8308
*/
cgu::pll0audio::mdiv({
.mdec = 30542,
.mdec = hackrf_r9 ? 8308UL : 30542UL,
});
cgu::pll0audio::np_div({
.pdec = 31,
@@ -467,18 +573,25 @@ void ClockManager::stop_audio_pll() {
void ClockManager::enable_clock_output(bool enable) {
if(enable) {
clock_generator.enable_output(clock_generator_output_clkout);
clock_generator.enable_output(clock_generator_output_og_clkout);
if(portapack::persistent_memory::clkout_freq() < 1000) {
clock_generator.set_ms_frequency(clock_generator_output_clkout, portapack::persistent_memory::clkout_freq() * 128000, si5351_vco_f, 7);
clock_generator.set_ms_frequency(clock_generator_output_og_clkout, portapack::persistent_memory::clkout_freq() * 128000, si5351_vco_f, 7);
} else {
clock_generator.set_ms_frequency(clock_generator_output_clkout, portapack::persistent_memory::clkout_freq() * 1000, si5351_vco_f, 0);
clock_generator.set_ms_frequency(clock_generator_output_og_clkout, portapack::persistent_memory::clkout_freq() * 1000, si5351_vco_f, 0);
}
} else {
clock_generator.disable_output(clock_generator_output_clkout);
clock_generator.disable_output(clock_generator_output_og_clkout);
}
auto si5351_clock_control_common = hackrf_r9
? si5351a_clock_control_common
: si5351c_clock_control_common;
const auto ref_pll = hackrf_r9
? ClockControl::MultiSynthSource::PLLA
: get_si5351c_reference_clock_generator_pll(reference.source);
if(enable)
clock_generator.set_clock_control(clock_generator_output_clkout, si5351_clock_control_common[clock_generator_output_clkout].ms_src(get_reference_clock_generator_pll(reference.source)).clk_pdn(ClockControl::ClockPowerDown::Power_On));
clock_generator.set_clock_control(clock_generator_output_og_clkout, si5351_clock_control_common[clock_generator_output_og_clkout].ms_src(ref_pll).clk_pdn(ClockControl::ClockPowerDown::Power_On));
else
clock_generator.set_clock_control(clock_generator_output_clkout, ClockControl::power_off());
clock_generator.set_clock_control(clock_generator_output_og_clkout, ClockControl::power_off());
}
+3 -5
View File
@@ -65,11 +65,8 @@ public:
void enable_codec_clocks();
void disable_codec_clocks();
void enable_first_if_clock();
void disable_first_if_clock();
void enable_second_if_clock();
void disable_second_if_clock();
void enable_if_clocks();
void disable_if_clocks();
void set_sampling_frequency(const uint32_t frequency);
@@ -99,6 +96,7 @@ private:
ReferenceSource detect_reference_source();
Reference choose_reference();
bool loss_of_signal();
};
#endif/*__CLOCK_MANAGER_H__*/
+6 -3
View File
@@ -38,7 +38,7 @@ using namespace lpc43xx;
* I suppose I could force M4MEMMAP to an invalid memory reason which would
* cause an exception and effectively halt the M4. But that feels gross.
*/
void m4_init(const portapack::spi_flash::image_tag_t image_tag, const portapack::memory::region_t to) {
void m4_init(const portapack::spi_flash::image_tag_t image_tag, const portapack::memory::region_t to, const bool full_reset) {
const portapack::spi_flash::chunk_t* chunk = reinterpret_cast<const portapack::spi_flash::chunk_t*>(portapack::spi_flash::images.base());
while(chunk->tag) {
if( chunk->tag == image_tag ) {
@@ -50,8 +50,11 @@ void m4_init(const portapack::spi_flash::image_tag_t image_tag, const portapack:
*/
LPC_CREG->M4MEMMAP = to.base();
/* Reset M4 core */
LPC_RGU->RESET_CTRL[0] = (1 << 13);
/* Reset M4 core and optionally all peripherals */
LPC_RGU->RESET_CTRL[0] = (full_reset) ?
(1 << 1) // PERIPH_RST
: (1 << 13) // M4_RST
;
return;
}
+1 -1
View File
@@ -27,7 +27,7 @@
#include "memory_map.hpp"
#include "spi_image.hpp"
void m4_init(const portapack::spi_flash::image_tag_t image_tag, const portapack::memory::region_t to);
void m4_init(const portapack::spi_flash::image_tag_t image_tag, const portapack::memory::region_t to, const bool full_reset);
void m4_request_shutdown();
void m0_halt();
+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) {

Some files were not shown because too many files have changed in this diff Show More