Compare commits

..

159 Commits

Author SHA1 Message Date
jLynx 9f54f4b5eb Added stable release pipeline (#573) 2022-04-13 18:02:43 +12:00
jLynx 178528ef96 Fixed no audio issue v2 (#567)
* Fixed no audio issue v2 (#567)
2022-04-12 09:28:36 +12:00
jLynx 5d9a2e560b SD card backup storage (#565)
* Got SD card mounting during boot

* Cleaned up comments

* Now loads settings from SD as backup

* Now loads settings from SD as backup

* linting

* refactoring
2022-04-11 21:42:56 +12:00
ArjanOnwezen b02329019c Merge pull request #556 from ArjanOnwezen/settings-cancel-button
Added cancel button in UI settings.
2022-04-08 23:57:03 +02:00
Arjan Onwezen 8c1593fab9 Added cancel button in UI settings. 2022-04-08 17:50:21 -04:00
ArjanOnwezen 1f27af660d Merge pull request #482 from zigad/feature/disableTouch
Enable / Disable Touchscreen
2022-04-08 22:59:18 +02:00
ArjanOnwezen a9d2b2ff8a Merge branch 'next' into feature/disableTouch 2022-04-08 16:10:55 +02:00
ArjanOnwezen a81d630d93 Merge pull request #555 from ArjanOnwezen/fix-scanner-only-audio-output-the-first-tim
Quick fix (as figures out by @bluegizmo83) to make sure WM8731S chips…
2022-04-08 15:59:18 +02:00
Arjan Onwezen efdefa85be Quick fix (as figures out by @bluegizmo83) to make sure WM8731S chips don't stay silent after pause in scanner app. 2022-04-08 09:51:41 -04:00
ArjanOnwezen f25ce9ed45 Merge pull request #554 from ArjanOnwezen/bigger-qr-code
Option to set bigger qr code (used in RadioSonde app)
2022-04-08 14:59:03 +02:00
Arjan Onwezen 6697d2533c Added support for LARGE qr code. 2022-04-08 08:38:32 -04:00
ArjanOnwezen 6cf5990b0e Merge pull request #38 from eried/next
[pull] next from eried:next
2022-04-08 12:35:42 +02:00
jLynx c97e1042b1 Merge pull request #550 from jLynx/QFP_fix
QFP100 Fix pt. 2
2022-04-08 12:45:49 +12:00
jLynx 9d5ed65f6b Added the most random fix 2022-04-08 12:42:12 +12:00
jLynx 2ba74d0413 What did I change? 2022-04-08 12:31:06 +12:00
jLynx a824e30420 Merge pull request #547 from jLynx/FM_fix
Fixed broken radio offset
2022-04-08 08:21:11 +12:00
jLynx 59d08a4203 Enabled auto detection again 2022-04-07 21:30:37 +12:00
jLynx 51bc0f0100 Fixed broken radio offset 2022-04-07 21:22:47 +12:00
jLynx d2e185a1fb 2021/12 QFP100 Fix
2021/12 QFP100 fix
2022-04-07 09:20:37 +12:00
jLynx 2d3cb426ba Stores in memory 2022-04-07 09:11:10 +12:00
jLynx dd2fdecb21 removed commented lines 2022-04-07 08:48:00 +12:00
jLynx a37ba1ee2b 2021/12 QFP100 fix 2022-04-07 08:41:46 +12:00
ArjanOnwezen 9fbcab4224 Update README.md 2022-04-06 17:59:32 +02:00
Jimi Sanchez 505f26c98a Merge pull request #540 from jLynx/next
Nightlys now include flashing software
2022-04-06 05:45:20 -04:00
jLynx dc18e340ab Update create_nightly_release.yml 2022-04-06 21:34:35 +12:00
jLynx 3e86f83099 Merge pull request #539 from jLynx/flashing
Added exe's to flashing folder
2022-04-06 20:52:23 +12:00
jLynx d98f2b40df Added exe's 2022-04-06 20:52:01 +12:00
jLynx e26d026216 Merge pull request #536 from jLynx/gen1
Fixed R1_20150901 vs R2_20170522 boot & detection issues. Read up about it here https://github.com/eried/portapack-mayhem/wiki/Won't-boot
2022-04-06 13:52:00 +12:00
jLynx 0c0d47b0d2 Added persistent memory of save state 2022-04-06 13:28:10 +12:00
jLynx 50821bab55 Added button on boot detection 2022-04-06 08:16:57 +12:00
jLynx 796d9ca854 Updated comments 2022-04-05 14:44:32 +12:00
jLynx fd8bc177ad Added support for H2+ 2022-04-05 14:41:12 +12:00
jLynx eab832396b Merge pull request #537 from jLynx/flashing
Added flashing tools
2022-04-05 11:14:16 +12:00
jLynx 3bb7ba59ae Added flashing tools 2022-04-05 11:13:12 +12:00
jLynx f6c496d1d3 removed comments 2022-04-05 10:56:09 +12:00
jLynx b4a6b958e5 Fixed R1_20150901 vs R2_20170522 boot & detection issues 2022-04-05 10:53:52 +12:00
jLynx 43e9ce4704 Fixed R1_20150901 vs R2_20170522 boot & detection issues 2022-04-05 10:52:42 +12:00
Erwin Ried b4e5fb7483 Merge pull request #534 from jLynx/changelog
Added changelog to release notes v2
2022-04-04 12:03:14 +02:00
jLynx 29d3a0f1dd Added python script to parse changelog 2022-04-04 09:00:41 +12:00
jLynx 1e413d034f WIP python 2022-04-04 08:54:43 +12:00
jLynx 5627634da1 Removed usernames for the moment 2022-04-04 07:33:14 +12:00
jLynx 719e7d42fd Removed usernames for the moment 2022-04-04 07:32:55 +12:00
jLynx 71d9fd1c87 Update with next 2022-04-04 07:15:24 +12:00
Erwin Ried 58bdd358c6 Merge pull request #529 from jLynx/version_automation
Version automation/injection
2022-04-03 12:28:14 +02:00
Erwin Ried 27c93e144b Merge pull request #530 from jLynx/stop_duplicate_nightly
Stops duplicate nightly builds
2022-04-03 12:27:36 +02:00
Erwin Ried 04f781ff52 Merge pull request #532 from eried/revert-531-changelog
Revert "Added changelog to release notes"
2022-04-03 12:27:14 +02:00
Erwin Ried 7a8637fb96 Revert "Added changelog to release notes" 2022-04-03 12:26:57 +02:00
Erwin Ried 054a931967 Merge pull request #531 from jLynx/changelog
Added changelog to release notes
2022-04-03 12:23:46 +02:00
jLynx 0a660aa5c0 Synced up SD card file name 2022-04-03 21:22:32 +12:00
jLynx 9c5bf8dcc0 Added changelog to release notes 2022-04-03 21:07:20 +12:00
jLynx 57df9dd2b7 Wont run if no changes in the last 24 hours 2022-04-03 15:36:37 +12:00
jLynx b33ef608ee Updated nightly release script 2022-04-03 09:15:06 +12:00
jLynx a17eb47657 Fixed typo in cmake 2022-04-03 08:50:08 +12:00
jLynx 250553e4ba Updated format 2022-04-02 22:40:00 +13:00
jLynx 9200db24be WIP 2022-04-02 22:02:05 +13:00
jLynx 03057546e1 WIP 2022-04-02 22:00:46 +13:00
Erwin Ried 486b064e08 Merge pull request #528 from jLynx/actions
Added nightly release pipeline
2022-04-02 03:34:45 +02:00
jLynx e4836a5e5c Removed comments 2022-04-02 12:46:51 +13:00
jLynx ad742a84e3 Added nightly pipeline 2022-04-02 12:38:19 +13:00
ArjanOnwezen eec4cd8778 Delete icao24.db
delete duplicated  icao24.db, since it should only be placed in /sdcard/ASDB folder
2022-04-01 14:02:03 +02:00
ArjanOnwezen d7a795b8f2 Delete mids.db
delete duplicate mids.db, since it should only be placed in /sdcard/AIS folder
2022-04-01 14:00:57 +02:00
ArjanOnwezen 579caa93b2 Merge pull request #527 from jLynx/TPMS_433
Updated TPMS 433 label
2022-04-01 11:39:37 +02:00
jLynx 3601545712 Updated to say 433 as it's not 434 2022-04-01 22:22:25 +13:00
ArjanOnwezen f7b219fc2b README.md added 2022-04-01 10:48:51 +02:00
eried 85cfdd75cc Rename the sample files 2022-04-01 10:05:06 +02:00
Erwin Ried deef2ebdc2 Merge pull request #526 from jLynx/Tesla_Charger
Added Tesla charge door open samples
2022-03-31 10:54:08 +02:00
jLynx 79a2c3a372 Added Tesla charge door open samples 2022-03-31 08:57:15 +13:00
eried 759c4d9d51 Contributors update 2022-03-29 08:28:31 +02:00
eried 77a0d255dd Version bump 2022-03-29 08:15:44 +02:00
eried 671fc12cf7 Tesla charge port open example
Thanks to @jLynx
2022-03-29 08:14:39 +02:00
Erwin Ried e1446598a8 Merge pull request #521 from notpike/audio_datetime_freq
Added Datetime + Freq Filename to Audio App
2022-03-29 08:10:09 +02:00
NotPike 7066f931a8 Update ui_record_view.cpp
cleanup
2022-03-29 01:16:16 -04:00
NotPike aa2c5a4c84 Update analog_audio_app.hpp
Forgot to take that include out. >_<
2022-03-29 00:34:52 -04:00
notpike d70e1a6fac Added Datetime + Freq Filename to Audio App 2022-03-28 20:53:09 -07:00
Erwin Ried 477e6d65df Merge pull request #488 from ArjanOnwezen/improve-screen-navigation
Improvements to screen navigation
2022-03-28 10:10:46 +02:00
Erwin Ried a55e5d4fc0 Merge pull request #497 from Brumi-2021/Solving_mic_saturation_and_spectrum_armonics_Mic_App
Solving_mic_saturation_and_spectrum_harmonics_Mic_App
2022-03-28 10:10:08 +02:00
Erwin Ried 8da0dbe36b Merge pull request #519 from notpike/replay_antenna_bias
Replay App Enable Bias-tee
2022-03-28 10:09:51 +02:00
Erwin Ried 8688ac0e05 Merge pull request #520 from ArjanOnwezen/add-country-info-to-ais-app
Added country to AIS app, so you know from which country a vessel is.
2022-03-28 10:08:39 +02:00
Erwin Ried 82732a3f73 Merge pull request #512 from jLynx/PSI
TPMS toggle between PSI and kPa (v1)
2022-03-28 10:07:41 +02:00
Arjan Onwezen be0427889f Added country to AIS app, so you know from which country a vessel is.
It's using the MID database, which is also part of the PR.
mids.db should be placed in /AIS folder on SD card.
2022-03-27 12:34:26 -04:00
NotPike 37a40cbeda Delete ui_newapp.hpp 2022-03-27 00:40:45 -04:00
notpike 4ef98e2928 Added Bias Tee support for Replay and fixed file error logic bug 2022-03-26 21:20:55 -07:00
notpike 434c559861 Added Bias Tee support for Replay and fixed file error logic bug 2022-03-26 21:20:49 -07:00
Erwin Ried 3cb3c95349 Merge pull request #516 from ArjanOnwezen/updated-airlines.db
updated airlines.db
2022-03-25 15:44:32 +01:00
Erwin Ried 979b5126a6 Merge pull request #517 from ArjanOnwezen/updated-icao24.db
updated icao24.db
2022-03-25 15:43:56 +01:00
Arjan Onwezen 8e3fa0b9ea updated icao24.db 2022-03-25 10:18:22 -04:00
Arjan Onwezen 00b43299ad updated airlines.db 2022-03-25 08:47:47 -04:00
Erwin Ried 1f31e9b983 Merge pull request #514 from jLynx/NZ_APRS
Added NZ to APRS app
2022-03-24 08:44:24 +01:00
jLynx 5c97c24b48 Added NZ to APRS 2022-03-24 20:36:39 +13:00
jLynx 4a8458d812 refactoring 2022-03-24 19:51:08 +13:00
jLynx 165efd7355 refactoring 2022-03-24 19:44:26 +13:00
jLynx d1d1198b1b refactoring 2022-03-24 19:43:26 +13:00
jLynx 0025ad2507 refactoring 2022-03-24 19:19:02 +13:00
jLynx 32f957cead WIP updating header 2022-03-24 19:08:07 +13:00
jLynx 2030118d9f WIP can now switch between kPa and PSI 2022-03-24 17:05:38 +13:00
jLynx 0523aabe91 WIP PSI selector 2022-03-24 16:10:55 +13:00
jLynx 1c81c7a8ba Revert "Added NZ to APRS"
This reverts commit 9df1cfa670.
2022-03-23 21:32:32 +13:00
jLynx 9df1cfa670 Added NZ to APRS 2022-03-23 20:51:10 +13:00
eried 68d40ebce8 Revert "Open the Tesla charge port"
This reverts commit c2856ce089.
2022-03-21 11:47:05 +01:00
Erwin Ried 901af22de5 Merge pull request #506 from ArjanOnwezen/#484-add-consecutive-ids-in-message.hpp
Added consecutive id's in message.hpp, as mentioned in #484.
2022-03-21 11:45:46 +01:00
Arjan Onwezen d9c1b6b61f Added consecutive id's in message.hpp, as mentioned in #484. 2022-03-20 13:38:53 -04:00
Erwin Ried 8774ee0acd Merge pull request #485 from ArjanOnwezen/centralize-database-functions
centralize-db-retrieval-functions
2022-03-18 22:05:09 +01:00
eried c2856ce089 Open the Tesla charge port
files from https://github.com/HackingIntoYourHeart/Tesla-Charging-Port-Opener
2022-03-14 08:52:36 +01:00
Brumi-2021 d5a1733c1c Solving_mic_saturation_and_spectrum_armonics_Mic_App 2022-03-05 21:39:53 +01:00
Erwin Ried 98c0ff1e47 Merge pull request #490 from notpike/file
Added return codes for delete_file() and rename_file() in file.hpp
2022-02-03 01:51:34 +01:00
notpike e00d91e1d2 Added return codes for delete_file() and rename_file() for file.hpp 2022-02-01 10:37:38 -08:00
Erwin Ried 459b8efc52 Merge pull request #487 from Brumi-2021/Add_Gain_TX_control_to_GPS_Simulator_issue#480
Add_Gain_TX_to_GPS_sim_App_issue_480
2022-01-31 09:43:20 +01:00
Erwin Ried db3f645131 Merge pull request #489 from Brumi-2021/“Antenna_DC_Bias_missing_in_AIS_and_RADIOSONDE”
“antenna dc bias missing in ais and radiosonde”
2022-01-31 09:41:11 +01:00
Brumi-2021 b84820963b Revert "Revert "“Antenna_DC_Bias_missing_in_AIS_and_RADIOSONDE”""
This reverts commit 4de25a2039.
2022-01-30 11:37:46 +01:00
Arjan Onwezen ec23dd8edf some improvements to screen navigation 2022-01-30 05:12:46 -05:00
Brumi-2021 4de25a2039 Revert "“Antenna_DC_Bias_missing_in_AIS_and_RADIOSONDE”"
This reverts commit 4a57af64ce.
2022-01-30 10:58:43 +01:00
Brumi-2021 a11b9c492f Add_Gain_TX_to_GPS_sim_App_issue_480
Add Gain control to the GPS Sim App .
(we are clonning the two previous PR's n #395 and #446 of the Replay App, correcting TX Gain control to this GPS Sim App )
2022-01-29 23:29:17 +01:00
Arjan Onwezen 867539ce9c centralize-db-retrieval-functions 2022-01-28 10:24:49 -05:00
Erwin Ried 799a701fc3 Merge pull request #479 from MichalLeonBorsuk/next
Some frequencies were shitfed by a few kHz
2022-01-27 20:02:12 +01:00
Žiga Deisinger cebbc12084 Enable / Disable Touchscreen #481
This commit will reverse the logic of touch screen as suggested by @ArjanOnwezen
2022-01-27 14:23:22 +01:00
Žiga Deisinger 4a0d42ed34 Add code for feature "Disable Touch" 2022-01-26 21:52:08 +01:00
Michał Borsuk 0d5af740a5 correction of spelling of units 2022-01-26 18:08:56 +01:00
Michał Borsuk 0da0431e5e Some frequencies were shitfed by a few kHz
I worked with DAB and noticed that some frequencies were not correct. I've imported data from http://www.wohnort.org/dab/freqs.html, which is a reliable source that I've used in the past.
2022-01-26 17:51:38 +01:00
Žiga Deisinger 96879d3664 Add code for feature "Disable Touch" 2022-01-26 14:53:31 +01:00
Erwin Ried ea251a87c0 Merge pull request #477 from zigad/bugfix-#473
Fix ADS-B not updating Altitude in Map #473
2022-01-24 09:26:05 +01:00
Erwin Ried 7fa64a3f76 Merge pull request #475 from zigad/ZARE
Added Slovenian Emergency Frequencies (ZARE)
2022-01-24 01:07:21 +01:00
Žiga Deisinger 7af7279ea4 Fix ADS-B not updating Altitude in Map #473
This commit will fix altitude not automatically updating when in Map mode. Also set default altitude for AIS to 0.
2022-01-23 22:34:01 +01:00
Žiga Deisinger 9726a50533 Added Slovenian Emergency Frequencies (ZARE) 2022-01-23 01:13:50 +01:00
Erwin Ried f42479c190 Merge pull request #470 from ArjanOnwezen/prepadding-MMSI-in-AIS
Prepadded MMSI in AIS app with zeros, so it's always 9 chars long
2022-01-17 10:35:07 +01:00
Arjan Onwezen dcb67049af Prepadded MMSI in AIS app with zeros, so it's always 9 chars long as in the specs. 2022-01-16 05:06:53 -05:00
Brumi-2021 4a57af64ce “Antenna_DC_Bias_missing_in_AIS_and_RADIOSONDE” 2022-01-15 23:09:42 +01:00
Erwin Ried 30449e0adf Merge pull request #467 from ArjanOnwezen/gui-glitch-in-adsb-rx
Small GUI glitch in ADSB RX
2022-01-12 19:06:14 +01:00
Arjan Onwezen c9a813fbd6 GUI glitch in ADSB RX 2022-01-12 10:31:59 -05:00
eried 0da7d2d0ac Version bump 2022-01-12 15:35:35 +01:00
eried 7c8f02d05a Update credits 2022-01-12 15:35:30 +01:00
Erwin Ried e5015cc67b Merge pull request #446 from Brumi-2021/“Indep_persistent_memory_14dBs_RF_tx-rx_amp”
Minor improvements to the previous PR #395 Add Gain_TX to Replay App
2022-01-12 15:19:54 +01:00
Erwin Ried 03c9812487 Merge pull request #457 from Brumi-2021/Solving_14dBs_lower_TX_AM_than_FM_TX_in_MIC_App
Minor improvements, to the previous excellent PR #329 AM-SSB-DSB Mic Functional from  aldude999
2022-01-10 11:05:23 +01:00
Erwin Ried fc08d0ba2d Merge pull request #452 from ArjanOnwezen/add-operator-to-icao-24
Added operator to ICAO24 file
2022-01-10 11:04:15 +01:00
Erwin Ried dfa7dfb024 Merge pull request #461 from notpike/touchtunes
Touchtunes EW Mode Feature
2022-01-04 10:55:22 +01:00
notpike c713d996ad TouchTunes TouchTunes New Feature QA 2022-01-03 20:15:54 -08:00
notpike c2ff37a1c7 TouchTunes TouchTunes New Feature QA 2022-01-03 19:57:51 -08:00
notpike 8ee650503c TouchTunes TouchTunes New Feature QA 2022-01-03 19:49:50 -08:00
notpike 47014b35ad TouchTunes new functions 2022-01-03 19:14:05 -08:00
Erwin Ried 0648e0d9bd Merge pull request #460 from ArjanOnwezen/qr-for-radiosonde
Added QR code generator with geo URI for radiosonde
2022-01-03 10:19:38 +01:00
Erwin Ried 094fa4c905 Update README.md
Link to a cheaper item with more accesory options
2022-01-03 10:14:54 +01:00
Arjan Onwezen 0a05c63c47 added qr code for radiosonde 2022-01-02 17:09:45 -05:00
Brumi-2021 f4403121a1 Minor improvementes to the previous PR #329 AM-SSB-DSB Mic Functionality App 2022-01-01 12:26:35 +01:00
Arjan Onwezen 9792e13cbf fixes and cleanup 2021-12-17 14:27:00 -05:00
Erwin Ried 6c4dec59bb Merge pull request #451 from ArjanOnwezen/adsb-metadata-improvemens
ADS-B metadata improvements
2021-12-14 10:47:14 +01:00
Arjan Onwezen 455389f1d1 fixes and cleanup 2021-12-12 05:09:06 -05:00
Arjan Onwezen 4a0a243530 added binary search tree lookup to airlines.db 2021-12-12 04:48:11 -05:00
Arjan Onwezen 3cb9e1849b added ICAO special designators, to aircraft types 2021-12-12 04:38:05 -05:00
Brumi-2021 d0f9073b67 Minor improvementes to the previous PR #395 Add Gain_TX to Replay App 2021-12-05 16:18:52 +01:00
Erwin Ried e2a2f7a448 Merge pull request #441 from ArjanOnwezen/make-icao24-db
Show aircraft info based on ICAO 24 bit transponder code in ADS-B app
2021-12-03 10:22:58 +01:00
Arjan Onwezen 708111066e removed duplicate file, README changes 2021-12-01 17:32:13 -05:00
Arjan Onwezen 2a2abac244 added aircraft info to ADS-B app 2021-12-01 17:23:40 -05:00
Erwin Ried c3da2863d5 Merge pull request #438 from Brumi-2021/Change_REC_icon_colour
Minor GUI change Capture App : Change "REC" icon background colour from black -> yellow , BW Options >600Khz
2021-11-29 03:19:12 +01:00
Arjan Onwezen 96db26e884 added icao24.db database and tool generator 2021-11-28 11:08:34 -05:00
Brumi-2021 9f48199a96 Changing background icon to yellow in the decimated files recording 2021-11-27 23:36:44 +01:00
Erwin Ried 834b65d833 Merge pull request #437 from ckuethe/next
Add some details about pagers in the US
2021-11-25 08:27:55 +01:00
Chris Kuethe 662eb0a7f9 limit of 99 frequencies per file 2021-11-24 16:59:35 -08:00
Chris Kuethe f60aab68a1 Add some details about pagers in the US 2021-11-24 15:45:04 -08:00
Brumi-2021 05a09bc988 Merge branch 'eried:next' into next 2021-11-24 21:10:00 +01:00
Brumi-2021 55fac01ab5 Merge branch 'eried:next' into next 2021-11-21 19:33:02 +01:00
108 changed files with 465230 additions and 784 deletions
+28
View File
@@ -0,0 +1,28 @@
import os
import re
import sys
raw_git = os.popen('git log next --since="24 hours" --pretty=format:"- %h - {USERNAME}*+%al-%an*: %s"').read()
def compute_username(line):
stripped = re.search(r'(?<=\*)(.*?)(?=\*)', line).group(0)
pattern = re.compile("[$@+&?].*[$@+&?]")
if pattern.match(stripped):
stripped = re.sub("[$@+&?].*[$@+&?]", "", stripped)
stripped = re.match(r'.+?(?=-)', stripped).group(0)
else:
stripped = re.sub(r'^.*?-', "", stripped)
return "@" + stripped
def compile_line(line):
username = compute_username(line)
line = re.sub(r'[*].*[*]', "", line)
line = line.replace("{USERNAME}", username)
return line
for row in raw_git.splitlines():
print(compile_line(row))
@@ -0,0 +1,99 @@
name: Nightly Release
on:
schedule:
- cron: "0 0 * * *"
workflow_dispatch:
jobs:
check_date:
runs-on: ubuntu-latest
name: Check latest commit
outputs:
should_run: ${{ steps.should_run.outputs.should_run }}
steps:
- uses: actions/checkout@v2
- name: print latest_commit
run: echo ${{ github.sha }}
- name: check latest commit is less than a day
id: should_run
continue-on-error: true
run: test -z $(git rev-list --after="24 hours" ${{ github.sha }}) && echo "::set-output name=should_run::false"
build:
needs: check_date
if: ${{ needs.check_date.outputs.should_run != 'false' }}
runs-on: ubuntu-latest
steps:
- name: Get current date
id: date
run: echo "::set-output name=date::$(date +'%Y-%m-%d')"
- name: Get version date
id: version_date
run: echo "::set-output name=date::n_$(date +'%y%m%d')"
- name: Checkout
uses: actions/checkout@master
with:
fetch-depth: 0
ref: next
submodules: true
- name: Git Sumbodule Update
run: |
git submodule update --init --recursive
- name: Build the Docker image
run: docker build -t portapack-dev -f dockerfile-nogit . --tag my-image-name:$(date +%s)
- name: Make build folder
run: mkdir ${{ github.workspace }}/build
- name: Run the Docker image
run: docker run -e VERSION_STRING=${{ steps.version_date.outputs.date }} -i -v ${{ github.workspace }}:/havoc portapack-dev
- name: Create Firmware ZIP
run: |
zip -j firmware.zip build/firmware/portapack-h1_h2-mayhem.bin && cd flashing && zip -r ../firmware.zip *
- name: Create SD Card ZIP
run: |
zip -r sdcard.zip sdcard
- name: Create changelog
run: |
CHANGELOG=$(python3 .github/workflows/changelog.py)
CHANGELOG="${CHANGELOG//'%'/'%25'}"
CHANGELOG="${CHANGELOG//$'\n'/'%0A'}"
CHANGELOG="${CHANGELOG//$'\r'/'%0D'}"
echo "::set-output name=content::$CHANGELOG"
id: changelog
- name: Create Release
id: create_release
uses: actions/create-release@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
tag_name: nightly-tag-${{ steps.date.outputs.date }}
release_name: Nightly Release - ${{ steps.date.outputs.date }}
body: |
**Nightly release - ${{ steps.date.outputs.date }}**
This build is the latest and greatest, although may not be the most stable as this is a nightly release.
## Release notes
### Revision (${{ steps.version_date.outputs.date }}):
${{ steps.changelog.outputs.content }}
draft: false
prerelease: true
- name: Upload Firmware Asset
id: upload-firmware-asset
uses: actions/upload-release-asset@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
upload_url: ${{ steps.create_release.outputs.upload_url }}
asset_path: ./firmware.zip
asset_name: mayhem_nightly_${{ steps.version_date.outputs.date }}_FIRMWARE.zip
asset_content_type: application/zip
- name: Upload SD Card Assets
id: upload-sd-card-asset
uses: actions/upload-release-asset@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
upload_url: ${{ steps.create_release.outputs.upload_url }}
asset_path: ./sdcard.zip
asset_name: mayhem_nightly_${{ steps.version_date.outputs.date }}_COPY_TO_SDCARD.zip
asset_content_type: application/zip
@@ -0,0 +1,93 @@
name: Stable Release
on:
workflow_dispatch:
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Get current date
id: date
run: echo "::set-output name=date::$(date +'%Y-%m-%d')"
- name: Checkout
uses: actions/checkout@master
with:
fetch-depth: 0
ref: next
submodules: true
- name: Git Sumbodule Update
run: |
git submodule update --init --recursive
- name: Get version
id: version
run: echo "::set-output name=version::$(cat .github/workflows/version.txt)"
- name: Get past version
id: past_version
run: echo "::set-output name=past_version::$(cat .github/workflows/past_version.txt)"
- name: Build the Docker image
run: docker build -t portapack-dev -f dockerfile-nogit . --tag my-image-name:$(date +%s)
- name: Make build folder
run: mkdir ${{ github.workspace }}/build
- name: Run the Docker image
run: docker run -e VERSION_STRING=${{ steps.version.outputs.version }} -i -v ${{ github.workspace }}:/havoc portapack-dev
- name: Create Firmware ZIP
run: |
zip -j firmware.zip build/firmware/portapack-h1_h2-mayhem.bin && cd flashing && zip -r ../firmware.zip *
- name: Create SD Card ZIP
run: |
zip -r sdcard.zip sdcard
- name: Create changelog
run: |
CHANGELOG=$(python3 .github/workflows/stable_changelog.py ${{ steps.past_version.outputs.past_version }})
CHANGELOG="${CHANGELOG//'%'/'%25'}"
CHANGELOG="${CHANGELOG//$'\n'/'%0A'}"
CHANGELOG="${CHANGELOG//$'\r'/'%0D'}"
echo "::set-output name=content::$CHANGELOG"
id: changelog
- name: Create Release
id: create_release
uses: actions/create-release@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
tag_name: v1.5.1
release_name: Mayhem firmware ${{ steps.version.outputs.version }}
body: |
**Stable release - ${{ steps.version.outputs.version }}**
This is a fork of the [Havoc](https://github.com/furrtek/portapack-havoc/) firmware, which itself was a fork of the [PortaPack](https://github.com/sharebrained/portapack-hackrf) firmware, an add-on for the [HackRF](http://greatscottgadgets.com/hackrf/). Please check the [readme](https://github.com/eried/portapack-mayhem/blob/master/README.md) for details.
## Release notes
### Revision (${{ steps.version.outputs.version }}):
${{ steps.changelog.outputs.content }}
**Full Changelog**: https://github.com/eried/portapack-mayhem/compare/${{ steps.past_version.outputs.past_version }}...${{ steps.version.outputs.version }}
## Installation
Check the [wiki](https://github.com/eried/portapack-havoc/wiki/Update-firmware) for details how to upgrade.
### MicroSD card files
For certain functionality, like the world map, GPS simulator, and others you need to uncompress (using [7-zip](https://www.7-zip.org/download.html)) the files from `mayhem_vX.Y.Z_COPY_TO_SDCARD.zip` to a FAT32 formatted MicroSD card.
draft: true
prerelease: false
- name: Upload Firmware Asset
id: upload-firmware-asset
uses: actions/upload-release-asset@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
upload_url: ${{ steps.create_release.outputs.upload_url }}
asset_path: ./firmware.zip
asset_name: mayhem_${{ steps.version.outputs.version }}_FIRMWARE.zip
asset_content_type: application/zip
- name: Upload SD Card Assets
id: upload-sd-card-asset
uses: actions/upload-release-asset@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
upload_url: ${{ steps.create_release.outputs.upload_url }}
asset_path: ./sdcard.zip
asset_name: mayhem_${{ steps.version.outputs.version }}_COPY_TO_SDCARD.zip
asset_content_type: application/zip
+1
View File
@@ -0,0 +1 @@
v1.5.0
+30
View File
@@ -0,0 +1,30 @@
import os
import re
import sys
past_version = sys.argv[1]
raw_git = os.popen('git log ' + past_version + '..next --pretty=format:"- %h - {USERNAME}*+%al-%an*: %s"').read()
def compute_username(line):
stripped = re.search(r'(?<=\*)(.*?)(?=\*)', line).group(0)
pattern = re.compile("[$@+&?].*[$@+&?]")
if pattern.match(stripped):
stripped = re.sub("[$@+&?].*[$@+&?]", "", stripped)
stripped = re.match(r'.+?(?=-)', stripped).group(0)
else:
stripped = re.sub(r'^.*?-', "", stripped)
return "@" + stripped
def compile_line(line):
username = compute_username(line)
line = re.sub(r'[*].*[*]', "", line)
line = line.replace("{USERNAME}", username)
return line
for row in raw_git.splitlines():
print(compile_line(row))
+1
View File
@@ -0,0 +1 @@
v1.5.1
-1
View File
@@ -39,7 +39,6 @@
*.lib
# Executables
*.exe
*.out
*.app
/firmware/baseband/*.bin
+3 -3
View File
@@ -25,8 +25,8 @@ set(CMAKE_TOOLCHAIN_FILE ${CMAKE_CURRENT_LIST_DIR}/firmware/toolchain-arm-cortex
project(portapack-h1)
#set(VERSION "")
if (NOT DEFINED VERSION)
set(VERSION "$ENV{VERSION_STRING}")
if ("$ENV{VERSION_STRING}" STREQUAL "")
execute_process(
COMMAND git log -n 1 --format=%h
WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR}
@@ -38,7 +38,7 @@ if (NOT DEFINED VERSION)
if (GIT_VERSION_FOUND)
set(VERSION "unknown")
else (GIT_VERSION_FOUND)
set(VERSION "local-${GIT_VERSION}")
set(VERSION "${GIT_VERSION}")
endif (GIT_VERSION_FOUND)
endif()
+1 -1
View File
@@ -1,5 +1,5 @@
# License
Portapack Mayhem is distributed under GPL v3.0, however some sub projects might have different (GPL v3.0 compatible) licenses.
Portapack Mayhem is distributed under [GPL v3.0](LICENSE), however some sub projects might have different (GPL v3.0 compatible) licenses.
## Other Licenses (compatible with GPL v3.0)
- Most of Portapack Mayhem is distributed under GPL-2.0-or-later. [license](LICENSE.GPL-2.0-or-later)
+5 -3
View File
@@ -6,7 +6,7 @@ This is a fork of the [Havoc](https://github.com/furrtek/portapack-havoc/) firmw
[<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/_dZ7lA96) (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/_9zbXMk) (clone) with a custom [3d printed case](https://github.com/eried/portapack-mayhem/wiki/H2-Enclosure)*
# Quick overview
@@ -20,13 +20,15 @@ This repository expands upon the previous work by many people and aims to consta
## Does it work on H1/H2 PortaPack?
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/_dZ7lA96), 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.
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.
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).
## Where is the latest firmware?
The current stable release is on the [![GitHub release (latest by date)](https://img.shields.io/github/v/release/eried/portapack-mayhem?label=Releases&style=social)](https://github.com/eried/portapack-mayhem/releases/latest) page. Follow the instructions you can find in the release description.
The **latest (nightly) release** can be found [here](https://github.com/eried/portapack-mayhem/releases/).
The current **stable release** is on the [![GitHub release (latest by date)](https://img.shields.io/github/v/release/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.
## 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*.
+3
View File
@@ -159,6 +159,7 @@ set(CPPSRC
capture_thread.cpp
clock_manager.cpp
core_control.cpp
database.cpp
de_bruijn.cpp
#emu_cc1101.cpp
rfm69.cpp
@@ -172,6 +173,7 @@ set(CPPSRC
irq_rtc.cpp
log_file.cpp
portapack.cpp
qrcodegen.cpp
radio.cpp
receiver_model.cpp
recent_entries.cpp
@@ -206,6 +208,7 @@ set(CPPSRC
ui/ui_channel.cpp
ui/ui_font_fixed_8x16.cpp
ui/ui_geomap.cpp
ui/ui_qrcode.cpp
ui/ui_menu.cpp
ui/ui_btngrid.cpp
ui/ui_receiver.cpp
+33 -6
View File
@@ -22,6 +22,7 @@
#include "ais_app.hpp"
#include "string_format.hpp"
#include "database.hpp"
#include "baseband_api.hpp"
@@ -59,7 +60,26 @@ static float latlon_float(const int32_t normalized) {
static std::string mmsi(
const ais::MMSI& mmsi
) {
return to_string_dec_uint(mmsi, 9);
return to_string_dec_uint(mmsi, 9, '0'); // MMSI is always is always 9 characters pre-padded with zeros
}
static std::string mid(
const ais::MMSI& mmsi
) {
std::database db;
std::string mid_code = "";
std::database::MidDBRecord mid_record = {};
int return_code = 0;
// Try getting the country name from mids.db using MID code for given MMSI
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_NOT_FOUND: return "No mids.db file";
default: return "";
}
}
static std::string navigational_status(const unsigned int value) {
@@ -240,7 +260,7 @@ AISRecentEntryDetailView::AISRecentEntryDetailView(NavigationView& nav) {
void AISRecentEntryDetailView::update_position() {
if (send_updates)
geomap_view->update_position(ais::format::latlon_float(entry_.last_position.latitude.normalized()), ais::format::latlon_float(entry_.last_position.longitude.normalized()), (float)entry_.last_position.true_heading);
geomap_view->update_position(ais::format::latlon_float(entry_.last_position.latitude.normalized()), ais::format::latlon_float(entry_.last_position.longitude.normalized()), (float)entry_.last_position.true_heading, 0);
}
void AISRecentEntryDetailView::focus() {
@@ -271,6 +291,7 @@ void AISRecentEntryDetailView::paint(Painter& painter) {
auto field_rect = Rect { rect.left(), rect.top() + 16, rect.width(), 16 };
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);
@@ -307,8 +328,13 @@ AISAppView::AISAppView(NavigationView& nav) : nav_ { nav } {
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.
radio::enable({
/* radio::enable({ // this can be removed, previous version,no DC-bias control.
tuning_frequency(),
sampling_rate,
baseband_bandwidth,
@@ -316,8 +342,8 @@ AISAppView::AISAppView(NavigationView& nav) : nav_ { nav } {
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);
};
@@ -337,7 +363,8 @@ AISAppView::AISAppView(NavigationView& nav) : nav_ { nav } {
}
AISAppView::~AISAppView() {
radio::disable();
/* radio::disable(); */
receiver_model.disable(); // to switch off all, including DC bias.
baseband::shutdown();
}
+3 -2
View File
@@ -131,11 +131,11 @@ private:
AISRecentEntry entry_ { };
Button button_done {
{ 125, 216, 96, 24 },
{ 125, 224, 96, 24 },
"Done"
};
Button button_see_map {
{ 19, 216, 96, 24 },
{ 19, 224, 96, 24 },
"See on map"
};
GeoMapView* geomap_view { nullptr };
@@ -169,6 +169,7 @@ private:
static constexpr uint32_t initial_target_frequency = 162025000;
static constexpr uint32_t sampling_rate = 2457600;
static constexpr uint32_t baseband_bandwidth = 1750000;
NavigationView& nav_;
AISRecentEntries recent { };
@@ -129,6 +129,9 @@ 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());
field_frequency.on_change = [this](rf::Frequency f) {
@@ -28,11 +28,11 @@
#include "ui_receiver.hpp"
#include "ui_spectrum.hpp"
#include "ui_record_view.hpp"
#include "ui_font_fixed_8x16.hpp"
#include "tone_key.hpp"
namespace ui {
constexpr Style style_options_group {
@@ -216,7 +216,10 @@ private:
RecordView record_view {
{ 0 * 8, 2 * 16, 30 * 8, 1 * 16 },
u"AUD_????", RecordView::FileType::WAV, 4096, 4
u"AUD",
RecordView::FileType::WAV,
4096,
4
};
spectrum::WaterfallWidget waterfall { true };
+6 -6
View File
@@ -75,8 +75,8 @@ CaptureAppView::CaptureAppView(NavigationView& nav) {
option_bandwidth.on_change = [this](size_t, uint32_t base_rate) {
sampling_rate = 8 * base_rate; // Decimation by 8 done on baseband side
/* base_rate is used for FFT calculation and display LCD, and also in recording writing SD Card rate. */
/* ex. sampling_rate values, 4Mhz, when recording 500 khz (BW) and fs 8 Mhz , when selected 1 Mhz BW ...*/
/* ex. recording 500khz BW to .C16 file, base_rate clock 500khz x2(I,Q) x 2 bytes (int signed) =2MB/sec rate SD Card */
/* ex. sampling_rate values, 4Mhz, when recording 500 kHz (BW) and fs 8 Mhz , when selected 1 Mhz BW ...*/
/* ex. recording 500kHz BW to .C16 file, base_rate clock 500kHz x2(I,Q) x 2 bytes (int signed) =2MB/sec rate SD Card */
waterfall.on_hide();
record_view.set_sampling_rate(sampling_rate);
@@ -85,12 +85,12 @@ CaptureAppView::CaptureAppView(NavigationView& nav) {
switch(sampling_rate) { // we use the var fs (sampling_rate) , to set up BPF aprox < fs_max/2 by Nyquist theorem.
case 0 ... 2000000: // BW Captured range (0 <= 250Khz max ) fs = 8 x 250 Khz
case 0 ... 2000000: // BW Captured range (0 <= 250kHz max ) fs = 8 x 250 kHz
anti_alias_baseband_bandwidth_filter = 1750000; // Minimum BPF MAX2837 for all those lower BW options.
break;
case 4000000 ... 6000000: // BW capture range (500k ... 750Khz max ) fs_max = 8 x 750Khz = 6Mhz
// BW 500k ... 750khz , ex. 500khz (fs = 8*BW = 4Mhz) , BW 600Khz (fs = 4,8Mhz) , BW 750 Khz (fs = 6Mhz)
case 4000000 ... 6000000: // BW capture range (500k ... 750kHz max ) fs_max = 8 x 750kHz = 6Mhz
// BW 500k ... 750kHz , ex. 500kHz (fs = 8*BW = 4Mhz) , BW 600kHz (fs = 4,8Mhz) , BW 750 kHz (fs = 6Mhz)
anti_alias_baseband_bandwidth_filter = 2500000; // in some IC MAX2837 appear 2250000 , but both works similar.
break;
@@ -123,7 +123,7 @@ CaptureAppView::CaptureAppView(NavigationView& nav) {
waterfall.on_show();
};
option_bandwidth.set_selected_index(7); // 500k, Preselected starting default option 500khz
option_bandwidth.set_selected_index(7); // 500k, Preselected starting default option 500kHz
receiver_model.set_modulation(ReceiverModel::Mode::Capture);
receiver_model.enable();
+17 -3
View File
@@ -140,13 +140,24 @@ void GpsSimAppView::start() {
}
);
}
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);
radio::enable({
receiver_model.tuning_frequency(),
sample_rate ,
baseband_bandwidth,
rf::Direction::Transmit,
receiver_model.rf_amp(),
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())
});
@@ -181,6 +192,9 @@ GpsSimAppView::GpsSimAppView(
NavigationView& nav
) : nav_ (nav)
{
tx_gain = 35;field_rfgain.set_value(tx_gain); // Initial default value (-12 dB's max 47dBs ).
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_gps);
add_children({
@@ -191,8 +205,8 @@ GpsSimAppView::GpsSimAppView(
&text_duration,
&progressbar,
&field_frequency,
&field_lna,
&field_rf_amp,
&field_rfgain,
&field_rfamp, // let's not use common persistent rf_amp , local rfamp is enough
&check_loop,
&button_play,
&waterfall,
+15 -5
View File
@@ -52,6 +52,8 @@ private:
static constexpr ui::Dim header_height = 3 * 16;
uint32_t sample_rate = 0;
int32_t tx_gain { 47 };
bool rf_amp { true }; // aux private var to store temporal, same as Replay App rf_amp user selection.
static constexpr uint32_t baseband_bandwidth = 3000000; //filter bandwidth
const size_t read_size { 16384 };
const size_t buffer_count { 3 };
@@ -76,7 +78,7 @@ private:
bool ready_signal { false };
Labels labels {
{ { 10 * 8, 2 * 16 }, "LNA: A:", Color::light_grey() }
{ { 10 * 8, 2 * 16 }, "GAIN A:", Color::light_grey() }
};
Button button_open {
@@ -104,11 +106,19 @@ private:
FrequencyField field_frequency {
{ 0 * 8, 2 * 16 },
};
LNAGainField field_lna {
{ 14 * 8, 2 * 16 }
NumberField field_rfgain {
{ 14 * 8, 2 * 16 },
2,
{ 0, 47 },
1,
' '
};
RFAmpField field_rf_amp {
{ 19 * 8, 2 * 16 }
NumberField field_rfamp { // previously we were 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 and Replay App
14,
' '
};
Checkbox check_loop {
{ 21 * 8, 2 * 16 },
+20 -6
View File
@@ -1,6 +1,7 @@
/*
* Copyright (C) 2016 Jared Boone, ShareBrained Technology, Inc.
* Copyright (C) 2016 Furrtek
* Copyleft (ↄ) 2022 NotPike
*
* This file is part of PortaPack.
*
@@ -121,6 +122,7 @@ void ReplayAppView::start() {
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);
}
@@ -145,16 +147,25 @@ void ReplayAppView::start() {
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 ,
sample_rate * 8,
baseband_bandwidth,
rf::Direction::Transmit,
receiver_model.rf_amp(),
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 ReplayAppView::stop(const bool do_loop) {
if( is_active() )
@@ -163,6 +174,7 @@ void ReplayAppView::stop(const bool do_loop) {
if (do_loop && check_loop.value()) {
start();
} else {
radio::set_antenna_bias(false); //Turn off Bias Tee
radio::disable();
button_play.set_bitmap(&bitmap_play);
}
@@ -186,7 +198,9 @@ ReplayAppView::ReplayAppView(
) : nav_ (nav)
{
tx_gain = 35;field_rfgain.set_value(tx_gain);
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({
@@ -198,7 +212,7 @@ ReplayAppView::ReplayAppView(
&progressbar,
&field_frequency,
&field_rfgain,
&field_rf_amp,
&field_rfamp, // let's not use common rf_amp
&check_loop,
&button_play,
&waterfall,
+7 -2
View File
@@ -52,6 +52,7 @@ private:
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 };
@@ -112,8 +113,12 @@ private:
1,
' '
};
RFAmpField field_rf_amp {
{ 19 * 8, 2 * 16 }
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 },
+48 -6
View File
@@ -34,6 +34,8 @@ namespace tpms {
namespace format {
static bool use_kpa = true;
std::string type(Reading::Type type) {
return to_string_dec_uint(toUType(type), 2);
}
@@ -43,7 +45,11 @@ std::string id(TransponderID id) {
}
std::string pressure(Pressure pressure) {
return to_string_dec_int(pressure.kilopascal(), 3);
if(use_kpa){
return to_string_dec_int(pressure.kilopascal(), 3);
}
return to_string_dec_int(pressure.psi(), 3);
}
std::string temperature(Temperature temperature) {
@@ -142,7 +148,7 @@ TPMSAppView::TPMSAppView(NavigationView&) {
&field_rf_amp,
&field_lna,
&field_vga,
&recent_entries_view,
&options_type,
});
radio::enable({
@@ -160,6 +166,17 @@ TPMSAppView::TPMSAppView(NavigationView&) {
};
options_band.set_by_value(target_frequency());
options_type.on_change = [this](size_t, int32_t i) {
if (i == 0){
tpms::format::use_kpa = true;
} else if (i == 1){
tpms::format::use_kpa = false;
}
update_type();
};
options_type.set_selected_index(0, true);
logger = std::make_unique<TPMSLogger>();
if( logger ) {
logger->append(u"tpms.txt");
@@ -176,9 +193,24 @@ void TPMSAppView::focus() {
options_band.focus();
}
void TPMSAppView::update_type() {
if (tpms::format::use_kpa){
remove_child(&recent_entries_view_psi);
add_child(&recent_entries_view_kpa);
recent_entries_view_kpa.set_parent_rect(view_normal_rect);
} else {
remove_child(&recent_entries_view_kpa);
add_child(&recent_entries_view_psi);
recent_entries_view_psi.set_parent_rect(view_normal_rect);
}
}
void TPMSAppView::set_parent_rect(const Rect new_parent_rect) {
View::set_parent_rect(new_parent_rect);
recent_entries_view.set_parent_rect({ 0, header_height, new_parent_rect.width(), new_parent_rect.height() - header_height });
view_normal_rect = { 0, header_height, new_parent_rect.width(), new_parent_rect.height() - header_height };
update_type();
}
void TPMSAppView::on_packet(const tpms::Packet& packet) {
@@ -191,13 +223,23 @@ void TPMSAppView::on_packet(const tpms::Packet& packet) {
const auto reading = reading_opt.value();
auto& entry = ::on_packet(recent, TPMSRecentEntry::Key { reading.type(), reading.id() });
entry.update(reading);
recent_entries_view.set_dirty();
if(tpms::format::use_kpa){
recent_entries_view_kpa.set_dirty();
} else {
recent_entries_view_psi.set_dirty();
}
}
}
void TPMSAppView::on_show_list() {
recent_entries_view.hidden(false);
recent_entries_view.focus();
if(tpms::format::use_kpa){
recent_entries_view_kpa.hidden(false);
recent_entries_view_kpa.focus();
} else {
recent_entries_view_psi.hidden(false);
recent_entries_view_psi.focus();
}
}
void TPMSAppView::on_band_changed(const uint32_t new_band_frequency) {
+25 -3
View File
@@ -121,6 +121,8 @@ private:
static constexpr ui::Dim header_height = 1 * 16;
ui::Rect view_normal_rect { };
RSSI rssi {
{ 21 * 8, 0, 6 * 8, 4 },
};
@@ -134,7 +136,16 @@ private:
3,
{
{ "315", 315000000 },
{ "434", 433920000 },
{ "433", 433920000 },
}
};
OptionsField options_type {
{ 5 * 8, 0 * 16 },
3,
{
{ "kPa", 0 },
{ "PSI", 1 }
}
};
@@ -153,7 +164,7 @@ private:
TPMSRecentEntries recent { };
std::unique_ptr<TPMSLogger> logger { };
const RecentEntriesColumns columns { {
const RecentEntriesColumns columns_kpa { {
{ "Tp", 2 },
{ "ID", 8 },
{ "kPa", 3 },
@@ -161,12 +172,23 @@ private:
{ "Cnt", 3 },
{ "Fl", 2 },
} };
TPMSRecentEntriesView recent_entries_view { columns, recent };
TPMSRecentEntriesView recent_entries_view_kpa { columns_kpa, recent };
const RecentEntriesColumns columns_psi { {
{ "Tp", 2 },
{ "ID", 8 },
{ "PSI", 3 },
{ "C", 3 },
{ "Cnt", 3 },
{ "Fl", 2 },
} };
TPMSRecentEntriesView recent_entries_view_psi { columns_psi, recent };
uint32_t target_frequency_ = initial_target_frequency;
void on_packet(const tpms::Packet& packet);
void on_show_list();
void update_type();
void on_band_changed(const uint32_t new_band_frequency);
@@ -36,14 +36,16 @@ namespace ui
console.writeln("East2West,fossum,ArjanOnwezen");
console.writeln("vXxOinvizioNxX,teixeluis");
console.writeln("Brumi-2021,texasyojimbo");
console.writeln("heurist1,intoxsick");
console.writeln("heurist1,intoxsick,ckuethe");
console.writeln("notpike,jLynx,zigad");
console.writeln("MichalLeonBorsuk");
console.writeln("");
break;
case 2:
// https://github.com/eried/portapack-mayhem/graphs/contributors?to=2020-04-12&from=2015-07-31&type=c
console.writeln("\x1B\x06Havoc:\x1B\x10");
console.writeln("furrtek,mrmookie,notpike");
console.writeln("furrtek,mrmookie,NotPike");
console.writeln("mjwaxios,ImDroided,Giorgiofox");
console.writeln("F4GEV,z4ziggy,xmycroftx");
console.writeln("troussos,silascutler");
+142 -40
View File
@@ -72,7 +72,7 @@ void RecentEntriesTable<AircraftRecentEntries>::draw(
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, 3);
to_string_dec_uint(entry.age, 4);
#endif
painter.draw_string(
@@ -91,6 +91,117 @@ void ADSBLogger::log_str(std::string& logline) {
log_file.write_entry(datetime,logline);
}
// Aircraft Details
void ADSBRxAircraftDetailsView::focus() {
button_close.focus();
}
ADSBRxAircraftDetailsView::~ADSBRxAircraftDetailsView() {
on_close_();
}
ADSBRxAircraftDetailsView::ADSBRxAircraftDetailsView(
NavigationView& nav,
const AircraftRecentEntry& entry,
const std::function<void(void)> on_close
) : entry_copy(entry),
on_close_(on_close)
{
add_children({
&labels,
&text_icao_address,
&text_registration,
&text_manufacturer,
&text_model,
&text_type,
&text_number_of_engines,
&text_engine_type,
&text_owner,
&text_operator,
&button_close
});
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));
// Try getting the aircraft information from icao24.db
return_code = db.retrieve_aircraft_record(&aircraft_record, icao_code);
switch(return_code) {
case DATABASE_RECORD_FOUND:
text_registration.set(aircraft_record.aircraft_registration);
text_manufacturer.set(aircraft_record.aircraft_manufacturer);
text_model.set(aircraft_record.aircraft_model);
text_owner.set(aircraft_record.aircraft_owner);
text_operator.set(aircraft_record.aircraft_operator);
// Check for ICAO type, e.g. L2J
if(strlen(aircraft_record.icao_type) == 3) {
switch(aircraft_record.icao_type[0]) {
case 'L':
text_type.set("Landplane");
break;
case 'S':
text_type.set("Seaplane");
break;
case 'A':
text_type.set("Amphibian");
break;
case 'H':
text_type.set("Helicopter");
break;
case 'G':
text_type.set("Gyrocopter");
break;
case 'T':
text_type.set("Tilt-wing aircraft");
break;
}
text_number_of_engines.set(std::string(1, aircraft_record.icao_type[1]));
switch(aircraft_record.icao_type[2]) {
case 'P':
text_engine_type.set("Piston engine");
break;
case 'T':
text_engine_type.set("Turboprop/Turboshaft engine");
break;
case 'J':
text_engine_type.set("Jet engine");
break;
case 'E':
text_engine_type.set("Electric engine");
break;
}
}
// Check for ICAO type designator
else if(strlen(aircraft_record.icao_type) == 4) {
if(strcmp(aircraft_record.icao_type,"SHIP") == 0) text_type.set("Airship");
else if(strcmp(aircraft_record.icao_type,"BALL") == 0) text_type.set("Balloon");
else if(strcmp(aircraft_record.icao_type,"GLID") == 0) text_type.set("Glider / sailplane");
else if(strcmp(aircraft_record.icao_type,"ULAC") == 0) text_type.set("Micro/ultralight aircraft");
else if(strcmp(aircraft_record.icao_type,"GYRO") == 0) text_type.set("Micro/ultralight autogyro");
else if(strcmp(aircraft_record.icao_type,"UHEL") == 0) text_type.set("Micro/ultralight helicopter");
else if(strcmp(aircraft_record.icao_type,"SHIP") == 0) text_type.set("Airship");
else if(strcmp(aircraft_record.icao_type,"PARA") == 0) text_type.set("Powered parachute/paraplane");
}
break;
case DATABASE_NOT_FOUND:
text_manufacturer.set("No icao24.db file");
break;
}
button_close.on_select = [&nav](Button&){
nav.pop();
};
};
// End of Aicraft details
void ADSBRxDetailsView::focus() {
button_see_map.focus();
}
@@ -114,7 +225,7 @@ 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_position(entry_copy.pos.latitude, entry_copy.pos.longitude, entry_copy.velo.heading);
geomap_view->update_position(entry_copy.pos.latitude, entry_copy.pos.longitude, entry_copy.velo.heading, entry_copy.pos.altitude);
}
ADSBRxDetailsView::~ADSBRxDetailsView() {
@@ -128,14 +239,10 @@ ADSBRxDetailsView::ADSBRxDetailsView(
) : entry_copy(entry),
on_close_(on_close)
{
char file_buffer[32] { 0 };
bool found = false;
int number_of_airlines = 0;
std::string airline_code;
size_t c;
add_children({
&labels,
&text_icao_address,
&text_callsign,
&text_last_seen,
&text_airline,
@@ -144,6 +251,7 @@ ADSBRxDetailsView::ADSBRxDetailsView(
&text_info2,
&text_frame_pos_even,
&text_frame_pos_odd,
&button_aircraft_details,
&button_see_map
});
@@ -152,41 +260,34 @@ ADSBRxDetailsView::ADSBRxDetailsView(
// The following won't (shouldn't !) change for a given airborne aircraft
// Try getting the airline's name from airlines.db
auto result = db_file.open("ADSB/airlines.db");
if (!result.is_valid()) {
// Search for 3-letter code
number_of_airlines = (db_file.size() / 68); // determine number of airlines in file
airline_code = entry_copy.callsign.substr(0, 3);
c = 0;
do {
db_file.read(file_buffer, 4);
if (!file_buffer[0])
break;
if (!airline_code.compare(0, 4, file_buffer))
found = true;
else
c++;
} while (!found && (c < number_of_airlines));
if (found) {
db_file.seek((number_of_airlines * 4) + (c << 6)); // seek starting after index
db_file.read(file_buffer, 32);
text_airline.set(file_buffer);
db_file.read(file_buffer, 32);
text_country.set(file_buffer);
} else {
text_airline.set("Unknown");
text_country.set("Unknown");
}
} else {
text_airline.set("No airlines.db file");
text_country.set("No airlines.db file");
airline_code = entry_copy.callsign.substr(0, 3);
return_code = db.retrieve_airline_record(&airline_record, airline_code);
switch(return_code) {
case DATABASE_RECORD_FOUND:
text_airline.set(airline_record.airline);
text_country.set(airline_record.country);
break;
case DATABASE_NOT_FOUND:
text_airline.set("No airlines.db file");
break;
}
text_callsign.set(entry_copy.callsign);
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;
});
send_updates = false;
};
button_see_map.on_select = [this, &nav](Button&) {
if (!send_updates) { // Prevent recursivley launching the map
if (!send_updates) { // Prevent recursively launching the map
geomap_view = nav.push<GeoMapView>(
entry_copy.callsign,
entry_copy.pos.altitude,
@@ -202,6 +303,7 @@ ADSBRxDetailsView::ADSBRxDetailsView(
};
};
void ADSBRxView::focus() {
field_vga.focus();
}
+120 -9
View File
@@ -27,6 +27,7 @@
#include "ui_font_fixed_8x16.hpp"
#include "file.hpp"
#include "database.hpp"
#include "recent_entries.hpp"
#include "log_file.hpp"
#include "adsb.hpp"
@@ -159,6 +160,98 @@ private:
};
class ADSBRxAircraftDetailsView : public View {
public:
ADSBRxAircraftDetailsView(NavigationView&, const AircraftRecentEntry& entry, const std::function<void(void)> on_close);
~ADSBRxAircraftDetailsView();
ADSBRxAircraftDetailsView(const ADSBRxAircraftDetailsView&) = delete;
ADSBRxAircraftDetailsView(ADSBRxAircraftDetailsView&&) = delete;
ADSBRxAircraftDetailsView& operator=(const ADSBRxAircraftDetailsView&) = delete;
ADSBRxAircraftDetailsView& operator=(ADSBRxAircraftDetailsView&&) = delete;
void focus() override;
void update(const AircraftRecentEntry& entry);
std::string title() const override { return "AC Details"; };
AircraftRecentEntry get_current_entry() { return entry_copy; }
std::database::AircraftDBRecord aircraft_record = {};
private:
AircraftRecentEntry entry_copy { 0 };
std::function<void(void)> on_close_ { };
bool send_updates { false };
std::database db;
std::string icao_code = "";
int return_code = 0;
Labels labels {
{ { 0 * 8, 1 * 16 }, "ICAO:", Color::light_grey() },
{ { 0 * 8, 2 * 16 }, "Registration:", Color::light_grey() },
{ { 0 * 8, 3 * 16 }, "Manufacturer:", Color::light_grey() },
{ { 0 * 8, 5 * 16 }, "Model:", Color::light_grey() },
{ { 0 * 8, 7 * 16 }, "Type:", Color::light_grey() },
{ { 0 * 8, 8 * 16 }, "Number of engines:", Color::light_grey() },
{ { 0 * 8, 9 * 16 }, "Engine type:", Color::light_grey() },
{ { 0 * 8, 11 * 16 }, "Owner:", Color::light_grey() },
{ { 0 * 8, 13 * 16 }, "Operator:", Color::light_grey() }
};
Text text_icao_address {
{ 5 * 8, 1 * 16, 6 * 8, 16},
"-"
};
Text text_registration {
{ 13 * 8, 2 * 16, 8 * 8, 16 },
"-"
};
Text text_manufacturer {
{ 0 * 8, 4 * 16, 19 * 8, 16 },
"-"
};
Text text_model {
{ 0 * 8, 6 * 16, 30 * 8, 16 },
"-"
};
Text text_type {
{ 5 * 8, 7 * 16, 22 * 8, 16 },
"-"
};
Text text_number_of_engines {
{ 18 * 8, 8 * 16, 30 * 8, 16 },
"-"
};
Text text_engine_type {
{ 0 * 8, 10 * 16, 30 * 8, 16},
"-"
};
Text text_owner {
{ 0 * 8, 12 * 16, 30 * 8, 16 },
"-"
};
Text text_operator {
{ 0 * 8, 14 * 16, 30 * 8, 16 },
"-"
};
Button button_close {
{ 9 * 8, 16 * 16, 12 * 8, 3 * 16 },
"Back"
};
};
class ADSBRxDetailsView : public View {
public:
ADSBRxDetailsView(NavigationView&, const AircraftRecentEntry& entry, const std::function<void(void)> on_close);
@@ -176,16 +269,23 @@ public:
std::string title() const override { return "Details"; };
AircraftRecentEntry get_current_entry() { return entry_copy; }
std::database::AirlinesDBRecord airline_record = {};
private:
AircraftRecentEntry entry_copy { 0 };
std::function<void(void)> on_close_ { };
GeoMapView* geomap_view { nullptr };
bool send_updates { false };
File db_file { };
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::string airline_code = "";
int return_code = 0;
Labels labels {
{ { 0 * 8, 1 * 16 }, "Callsign:", Color::light_grey() },
{ { 0 * 8, 1 * 16 }, "ICAO:", Color::light_grey() },
{ { 13 * 8, 1 * 16 }, "Callsign:", Color::light_grey() },
{ { 0 * 8, 2 * 16 }, "Last seen:", Color::light_grey() },
{ { 0 * 8, 3 * 16 }, "Airline:", Color::light_grey() },
{ { 0 * 8, 5 * 16 }, "Country:", Color::light_grey() },
@@ -193,8 +293,13 @@ private:
{ { 0 * 8, 15 * 16 }, "Odd position frame:", Color::light_grey() }
};
Text text_icao_address {
{ 5 * 8, 1 * 16, 6 * 8, 16},
"-"
};
Text text_callsign {
{ 9 * 8, 1 * 16, 8 * 8, 16 },
{ 22 * 8, 1 * 16, 8 * 8, 16 },
"-"
};
@@ -232,11 +337,17 @@ private:
"-"
};
Button button_aircraft_details {
{ 2 * 8, 9 * 16, 12 * 8, 3 * 16 },
"A/C details"
};
Button button_see_map {
{ 8 * 8, 9 * 16, 14 * 8, 3 * 16 },
{ 16 * 8, 9 * 16, 12 * 8, 3 * 16 },
"See on map"
};
};
class ADSBRxView : public View {
public:
@@ -274,7 +385,7 @@ private:
{ "Spd", 3 },
{ "Amp", 3 },
{ "Hit", 3 },
{ "Age", 3 }
{ "Age", 4 }
#endif
} };
AircraftRecentEntries recent { };
+5 -5
View File
@@ -108,12 +108,12 @@ APRSRxView::APRSRxView(NavigationView& nav, Rect parent_rect) : View(parent_rect
options_region.on_change = [this](size_t, int32_t i) {
if (i == 0){
field_frequency.set_value(144390000);
}
if(i == 1){
} else if(i == 1){
field_frequency.set_value(144800000);
}
if(i == 2){
} else if(i == 2){
field_frequency.set_value(145175000);
} else if(i == 3){
field_frequency.set_value(144575000);
}
};
@@ -351,7 +351,7 @@ void APRSDetailsView::update() {
}
if (send_updates)
geomap_view->update_position(entry_copy.pos.latitude, entry_copy.pos.longitude, 0);
geomap_view->update_position(entry_copy.pos.latitude, entry_copy.pos.longitude, 0, 0);
}
APRSDetailsView::~APRSDetailsView() {
+2 -1
View File
@@ -217,7 +217,8 @@ private:
{
{ "NA ", 0 },
{ "EUR", 1 },
{ "AUS", 2 }
{ "AUS", 2 },
{ "NZ ", 3 }
}
};
+52 -5
View File
@@ -24,6 +24,10 @@
#include "baseband_api.hpp"
#include "audio.hpp"
#include "wm8731.hpp"
using wolfson::wm8731::WM8731;
#include "tonesets.hpp"
#include "portapack_hal.hpp"
#include "string_format.hpp"
@@ -34,6 +38,10 @@
using namespace tonekey;
using namespace portapack;
WM8731 audio_codec_wm8731 { i2c0, 0x1a };
namespace ui {
void MicTXView::focus() {
@@ -178,7 +186,7 @@ void MicTXView::rxaudio(bool is_on) {
baseband::run_image(portapack::spi_flash::image_tag_mic_tx);
audio::output::stop();
audio::input::start();
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)
portapack::pin_i2s0_rx_sda.mode(3);
configure_baseband();
}
@@ -203,10 +211,12 @@ MicTXView::MicTXView(
baseband::run_image(portapack::spi_flash::image_tag_mic_tx);
add_children({
&labels,
if ( audio_codec_wm8731.detected() ) {
add_children({
&labels_WM8731, // we have audio codec WM8731, same MIC menu as original.
&vumeter,
&options_gain,
&options_gain, // MIC GAIN float factor on the GUI.
// &check_va,
&field_va,
&field_va_level,
@@ -229,6 +239,37 @@ MicTXView::MicTXView(
&field_rxamp,
&tx_button
});
} else {
add_children({
&labels_AK4951, // we have audio codec AK4951, enable Automatic Level Control
&vumeter,
&options_gain,
&options_ak4951_alc_mode,
// &check_va,
&field_va,
&field_va_level,
&field_va_attack,
&field_va_decay,
&field_bw,
&field_rfgain,
&field_rfamp,
&options_mode,
&field_frequency,
&options_tone_key,
&check_rogerbeep,
&check_rxactive,
&field_volume,
&field_rxbw,
&field_squelch,
&field_rxfrequency,
&field_rxlna,
&field_rxvga,
&field_rxamp,
&tx_button
});
}
tone_keys_populate(options_tone_key);
options_tone_key.on_change = [this](size_t i, int32_t) {
@@ -242,6 +283,12 @@ MicTXView::MicTXView(
};
options_gain.set_selected_index(1); // x1.0
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);
tx_frequency = transmitter_model.tuning_frequency();
field_frequency.set_value(transmitter_model.tuning_frequency());
field_frequency.set_step(receiver_model.frequency_step());
@@ -478,7 +525,7 @@ MicTXView::MicTXView(
set_tx(false);
audio::set_rate(audio::Rate::Hz_24000);
audio::input::start();
audio::input::start(ak4951_alc_GUI_selected); // originally , audio::input::start(); (we added parameter)
}
MicTXView::~MicTXView() {
+49 -8
View File
@@ -83,6 +83,7 @@ private:
bool rx_enabled { false };
uint32_t tone_key_index { };
float mic_gain { 1.0 };
uint8_t ak4951_alc_GUI_selected { 0 };
uint32_t audio_level { 0 };
uint32_t va_level { };
uint32_t attack_ms { };
@@ -106,8 +107,8 @@ private:
bool enable_lsb { false };
Labels labels {
{ { 3 * 8, 1 * 8 }, "MIC. GAIN:", Color::light_grey() },
Labels labels_WM8731 {
{ { 3 * 8, 1 * 8 }, "MIC-GAIN:", Color::light_grey() },
{ { 3 * 8, 3 * 8 }, "F:", Color::light_grey() },
{ { 15 * 8, 3 * 8 }, "BW: FM kHz", Color::light_grey() },
{ { 3 * 8, 5 * 8 }, "GAIN:", Color::light_grey() },
@@ -118,15 +119,36 @@ 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() },
{ { 9 * 8, 23 * 8 }, "VOL:", Color::light_grey() },
{ {17 * 8, 23 * 8 }, "FM RXBW:", Color::light_grey() },
{ { 7 * 8, 23 * 8 }, "VOL:", Color::light_grey() },
{ {15 * 8, 23 * 8 }, "FM RXBW:", Color::light_grey() },
{ {17 * 8, 25 * 8 }, "SQ:", Color::light_grey() },
{ { 5 * 8, 25 * 8 }, "F:", Color::light_grey() },
{ { 5 * 8, 27 * 8 }, "LNA:", Color::light_grey()},
{ {12 * 8, 27 * 8 }, "VGA:", Color::light_grey()},
{ {19 * 8, 27 * 8 }, "AMP:", Color::light_grey()}
};
Labels labels_AK4951 {
{ { 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() },
{ { 3 * 8, 5 * 8 }, "GAIN:", Color::light_grey() },
{ {11 * 8, 5 * 8 }, "Amp:", Color::light_grey() },
{ { 18 * 8, (5 * 8) }, "Mode:", Color::light_grey() },
{ { 3 * 8, 8 * 8 }, "TX Activation:", Color::light_grey() },
{ { 4 * 8, 10 * 8 }, "LVL:", Color::light_grey() },
{ {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() },
{ {17 * 8, 25 * 8 }, "SQ:", Color::light_grey() },
{ { 5 * 8, 25 * 8 }, "F:", Color::light_grey() },
{ { 5 * 8, 27 * 8 }, "LNA:", Color::light_grey()},
{ {12 * 8, 27 * 8 }, "VGA:", Color::light_grey()},
{ {19 * 8, 27 * 8 }, "AMP:", Color::light_grey()}
};
VuMeter vumeter {
{ 0 * 8, 1 * 8, 2 * 8, 33 * 8 },
12,
@@ -135,7 +157,7 @@ private:
OptionsField options_gain {
{ 13 * 8, 1 * 8 },
{ 12 * 8, 1 * 8 },
4,
{
{ "x0.5", 5 },
@@ -145,6 +167,25 @@ private:
}
};
OptionsField options_ak4951_alc_mode {
{ 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)
{ "+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)
{ "+03dB-2kHz", 4 }, // ALC-> on, (+03dB's) Auto Vol max + Wind Noise cancel + LPF 3,5k + Pre-amp Mic (+21dB=original)+ EQ boosting ~<2kHz (f0~1k1,fb:1,7K, k=1,8)
{ "+03dB-4kHz", 5 }, // ALC-> on, (+03dB's) Auto Vol max + Wind Noise cancel + LPF 4kHz + Pre-amp Mic (+21dB=original)+ EQ boosting ~<3kHz (f0~1k4,fb~2,4k, k=1,8)
{ "+03dB-6kHz", 6 }, // ALC-> on, (+03dB's) Auto Vol max + Wind Noise cancel + LPF 6kHz + Pre-amp Mic (+21dB=original)
{ "+00dB-6kHz", 7 }, // ALC-> on, (+00dB's) Auto Vol max + Wind Noise cancel + LPF 6kHz + Pre-amp Mic (+21dB=original)
{ "-03dB-6kHz", 8 }, // ALC-> on, (-03dB's) Auto Vol max + Wind Noise cancel + LPF 6kHz + Pre-amp Mic (+21dB=original)
{ "-06dB-6kHz", 9 }, // ALC-> on, (-06dB's) Auto Vol max + Wind Noise cancel + LPF 6kHz + Pre-amp Mic (+21dB=original)
{ "-09dB-6kHz", 10 }, // ALC-> on, (-09dB's) Auto Vol max + Wind Noise cancel + LPF 6kHz - Pre-amp MIC -3dB (18dB's)
{ "-12dB-6kHz", 11 }, // ALC-> on, (-12dB's) Auto Vol max + Wind Noise cancel + LPF 6kHz - Pre-amp MIC -6dB (15dB's)
}
};
FrequencyField field_frequency {
{ 5 * 8, 3 * 8 },
};
@@ -244,7 +285,7 @@ private:
};
NumberField field_volume {
{ 13 * 8, 23 * 8 },
{ 11* 8, 23 * 8 },
2,
{ 0, 99 },
1,
@@ -252,7 +293,7 @@ private:
};
OptionsField field_rxbw {
{ 25 * 8, 23 * 8},
{ 23* 8, 23 * 8},
3,
{
{"8k5", 0},
+1
View File
@@ -484,6 +484,7 @@ void ScannerView::scan_pause() {
scan_thread->set_freq_lock(0); //Reset the scanner lock (because user paused, or MAX_FREQ_LOCK reached) for next freq scan
scan_thread->set_scanning(false); // WE STOP SCANNING
audio::output::start();
on_headphone_volume_changed(field_volume.value()); // quick fix to make sure WM8731S chips don't stay silent after pause
}
}
+11 -11
View File
@@ -242,16 +242,16 @@ private:
{ 17 * 8, (26 * 8) + 4 },
12,
{
{ "5Khz (SA AM)", 5000 },
{ "9Khz (EU AM)", 9000 },
{ "10Khz(US AM)", 10000 },
{ "50Khz (FM1)", 50000 },
{ "100Khz(FM2)", 100000 },
{ "6.25khz(NFM)", 6250 },
{ "12.5khz(NFM)", 12500 },
{ "25khz (N1)", 25000 },
{ "250khz (N2)", 250000 },
{ "8.33khz(AIR)", 8330 }
{ "5kHz (SA AM)", 5000 },
{ "9kHz (EU AM)", 9000 },
{ "10kHz(US AM)", 10000 },
{ "50kHz (FM1)", 50000 },
{ "100kHz(FM2)", 100000 },
{ "6.25kHz(NFM)", 6250 },
{ "12.5kHz(NFM)", 12500 },
{ "25kHz (N1)", 25000 },
{ "250kHz (N2)", 250000 },
{ "8.33kHz(AIR)", 8330 }
}
};
@@ -308,4 +308,4 @@ private:
};
};
} /* namespace ui */
} /* namespace ui */
+58 -254
View File
@@ -43,7 +43,7 @@ namespace ui {
SetDateTimeView::SetDateTimeView(
NavigationView& nav
) {
button_done.on_select = [&nav, this](Button&){
button_save.on_select = [&nav, this](Button&){
const auto model = this->form_collect();
const rtc::RTC new_datetime {
model.year, model.month, model.day,
@@ -65,7 +65,7 @@ SetDateTimeView::SetDateTimeView(
&field_hour,
&field_minute,
&field_second,
&button_done,
&button_save,
&button_cancel,
});
@@ -150,7 +150,7 @@ SetRadioView::SetRadioView(
&value_freq_step,
&labels_bias,
&check_bias,
&button_done,
&button_save,
&button_cancel
});
@@ -200,7 +200,7 @@ SetRadioView::SetRadioView(
EventDispatcher::send_message(message);
};
button_done.on_select = [this, &nav](Button&){
button_save.on_select = [this, &nav](Button&){
const auto model = this->form_collect();
portapack::persistent_memory::set_correction_ppb(model.ppm * 1000);
portapack::persistent_memory::set_clkout_freq(model.freq);
@@ -210,7 +210,7 @@ SetRadioView::SetRadioView(
}
void SetRadioView::focus() {
button_done.focus();
button_save.focus();
}
void SetRadioView::form_init(const SetFrequencyCorrectionModel& model) {
@@ -224,76 +224,24 @@ SetFrequencyCorrectionModel SetRadioView::form_collect() {
};
}
/*
SetPlayDeadView::SetPlayDeadView(NavigationView& nav) {
add_children({
&text_sequence,
&button_enter,
&button_cancel
});
button_enter.on_select = [this, &nav](Button&){
if (!entermode) {
sequence = 0;
keycount = 0;
memset(sequence_txt, '-', 10);
text_sequence.set(sequence_txt);
entermode = true;
button_cancel.hidden(true);
set_dirty();
} else {
if (sequence == 0x8D1) // U D L R
nav.display_modal("Warning", "Default sequence entered !", ABORT, nullptr);
else {
persistent_memory::set_playdead_sequence(sequence);
nav.pop();
}
}
};
button_enter.on_dir = [this](Button&, KeyEvent key){
if ((entermode == true) && (keycount < 10)) {
key_code = static_cast<std::underlying_type<KeyEvent>::type>(key);
if (key_code == 0)
sequence_txt[keycount] = 'R';
else if (key_code == 1)
sequence_txt[keycount] = 'L';
else if (key_code == 2)
sequence_txt[keycount] = 'D';
else if (key_code == 3)
sequence_txt[keycount] = 'U';
text_sequence.set(sequence_txt);
sequence = (sequence << 3) | (key_code + 1);
keycount++;
return true;
}
return false;
};
button_cancel.on_select = [&nav](Button&){ nav.pop(); };
}
void SetPlayDeadView::focus() {
button_cancel.focus();
}
*/
SetUIView::SetUIView(NavigationView& nav) {
add_children({
//&checkbox_login,
&checkbox_disable_touchscreen,
&checkbox_speaker,
&checkbox_bloff,
&options_bloff,
&checkbox_showsplash,
&checkbox_showclock,
&options_clockformat,
&button_ok
&options_clockformat,
&button_save,
&button_cancel
});
checkbox_disable_touchscreen.set_value(persistent_memory::disable_touchscreen());
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_login.set_value(persistent_memory::config_login());
uint32_t backlight_timer = persistent_memory::config_backlight_timer();
if (backlight_timer) {
@@ -309,16 +257,14 @@ 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
//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);
//};
persistent_memory::set_config_speaker(v); //Store Speaker status
StatusRefreshMessage message { }; //Refresh status bar with/out speaker
EventDispatcher::send_message(message);
};
button_ok.on_select = [&nav, this](Button&) {
button_save.on_select = [&nav, this](Button&) {
if (checkbox_bloff.value())
persistent_memory::set_config_backlight_timer(options_bloff.selected_index() + 1);
else
@@ -329,225 +275,83 @@ SetUIView::SetUIView(NavigationView& nav) {
persistent_memory::set_clock_with_date(true);
else
persistent_memory::set_clock_with_date(false);
}
}
if (checkbox_speaker.value()) audio::output::speaker_mute(); //Just mute audio if speaker is disabled
persistent_memory::set_config_speaker(checkbox_speaker.value()); //Store Speaker status
StatusRefreshMessage message { }; //Refresh status bar with/out speaker
EventDispatcher::send_message(message);
persistent_memory::set_config_splash(checkbox_showsplash.value());
persistent_memory::set_clock_hidden(!checkbox_showclock.value());
//persistent_memory::set_config_login(checkbox_login.value());
persistent_memory::set_disable_touchscreen(checkbox_disable_touchscreen.value());
nav.pop();
};
button_cancel.on_select = [&nav, this](Button&) {
nav.pop();
};
}
void SetUIView::focus() {
button_ok.focus();
button_save.focus();
}
SetAudioView::SetAudioView(NavigationView& nav) {
add_children({
&labels,
&field_tone_mix,
&button_ok
&button_save,
&button_cancel
});
field_tone_mix.set_value(persistent_memory::tone_mix());
button_ok.on_select = [&nav, this](Button&) {
button_save.on_select = [&nav, this](Button&) {
persistent_memory::set_tone_mix(field_tone_mix.value());
nav.pop();
};
button_cancel.on_select = [&nav, this](Button&) {
nav.pop();
};
}
void SetAudioView::focus() {
field_tone_mix.focus();
button_save.focus();
}
/*void ModInfoView::on_show() {
if (modules_nb) update_infos(0);
}
SetQRCodeView::SetQRCodeView(NavigationView& nav) {
add_children({
&checkbox_bigger_qr,
&button_save,
&button_cancel
});
void ModInfoView::update_infos(uint8_t modn) {
char info_str[27];
char ch;
uint8_t c;
Point pos = { 0, 0 };
Rect rect = { { 16, 144 }, { 208, 144 } };
checkbox_bigger_qr.set_value(persistent_memory::show_bigger_qr_code());
info_str[0] = 0;
strcat(info_str, module_list[modn].name);
text_namestr.set(info_str);
info_str[0] = 0;
strcat(info_str, to_string_dec_uint(module_list[modn].size).c_str());
strcat(info_str, " bytes");
text_sizestr.set(info_str);
info_str[0] = 0;
for (c = 0; c < 8; c++)
strcat(info_str, to_string_hex(module_list[modn].md5[c], 2).c_str());
text_md5_a.set(info_str);
info_str[0] = 0;
for (c = 8; c < 16; c++)
strcat(info_str, to_string_hex(module_list[modn].md5[c], 2).c_str());
text_md5_b.set(info_str);
// TODO: Use ui_console
display.fill_rectangle(rect, Color::black());
const Font& font = font::fixed_8x16;
const auto line_height = font.line_height();
c = 0;
while((ch = module_list[modn].description[c++])) {
const auto glyph = font.glyph(ch);
const auto advance = glyph.advance();
if((pos.x + advance.x) > rect.width()) {
pos.x = 0;
pos.y += line_height;
}
const Point pos_glyph {
static_cast<Coord>(rect.pos.x + pos.x),
static_cast<Coord>(rect.pos.y + pos.y)
};
display.draw_glyph(pos_glyph, glyph, Color::white(), Color::black());
pos.x += advance.x;
}
}
ModInfoView::ModInfoView(NavigationView& nav) {
const char magic[4] = {'P', 'P', 'M', ' '};
UINT bw;
uint8_t i;
char read_buf[16];
char info_str[25];
FILINFO modinfo;
FIL modfile;
DIR rootdir;
FRESULT res;
uint8_t c;
using option_t = std::pair<std::string, int32_t>;
using options_t = std::vector<option_t>;
option_t opt;
options_t opts;
static constexpr Style style_orange {
.font = font::fixed_8x16,
.background = Color::black(),
.foreground = Color::orange(),
};
add_children({{
&text_modcount,
&text_name,
&text_namestr,
&text_size,
&text_sizestr,
&text_md5,
&text_md5_a,
&text_md5_b,
&button_ok
}});
text_name.set_style(&style_orange);
text_size.set_style(&style_orange);
text_md5.set_style(&style_orange);
// TODO: Find a way to merge this with m4_load_image() in m4_startup.cpp
// Scan SD card root directory for files starting with the magic bytes
c = 0;
if (f_opendir(&rootdir, "/") == FR_OK) {
for (;;) {
res = f_readdir(&rootdir, &modinfo);
if (res != FR_OK || modinfo.fname[0] == 0) break; // Reached last file, abort
// Only care about files with .bin extension
if ((!(modinfo.fattrib & AM_DIR)) && (modinfo.fname[9] == 'B') && (modinfo.fname[10] == 'I') && (modinfo.fname[11] == 'N')) {
f_open(&modfile, modinfo.fname, FA_OPEN_EXISTING | FA_READ);
// Magic bytes check
f_read(&modfile, &read_buf, 4, &bw);
for (i = 0; i < 4; i++)
if (read_buf[i] != magic[i]) break;
if (i == 4) {
memcpy(&module_list[c].filename, modinfo.fname, 8);
module_list[c].filename[8] = 0;
f_lseek(&modfile, 4);
f_read(&modfile, &module_list[c].version, 2, &bw);
f_lseek(&modfile, 6);
f_read(&modfile, &module_list[c].size, 4, &bw);
f_lseek(&modfile, 10);
f_read(&modfile, &module_list[c].name, 16, &bw);
f_lseek(&modfile, 26);
f_read(&modfile, &module_list[c].md5, 16, &bw);
f_lseek(&modfile, 42);
f_read(&modfile, &module_list[c].description, 214, &bw);
f_lseek(&modfile, 256);
// Sanitize
module_list[c].name[15] = 0;
module_list[c].description[213] = 0;
memcpy(info_str, module_list[c].filename, 16);
strcat(info_str, "(V");
strcat(info_str, to_string_dec_uint(module_list[c].version, 4, '0').c_str());
strcat(info_str, ")");
while(strlen(info_str) < 24)
strcat(info_str, " ");
opt = std::make_pair(info_str, c);
opts.insert(opts.end(), opt);
c++;
}
f_close(&modfile);
}
if (c == 8) break;
}
}
f_closedir(&rootdir);
modules_nb = c;
if (modules_nb) {
strcpy(info_str, "Found ");
strcat(info_str, to_string_dec_uint(modules_nb, 1).c_str());
strcat(info_str, " module(s)");
text_modcount.set(info_str);
option_modules.set_options(opts);
add_child(&option_modules);
option_modules.on_change = [this](size_t n, OptionsField::value_t v) {
(void)n;
update_infos(v);
};
} else {
strcpy(info_str, "No modules found");
text_modcount.set(info_str);
}
button_ok.on_select = [&nav,this](Button&){
button_save.on_select = [&nav, this](Button&) {
persistent_memory::set_show_bigger_qr_code(checkbox_bigger_qr.value());
nav.pop();
};
button_cancel.on_select = [&nav, this](Button&) {
nav.pop();
};
}
void ModInfoView::focus() {
if (modules_nb)
option_modules.focus();
else
button_ok.focus();
}*/
void SetQRCodeView::focus() {
button_save.focus();
}
SettingsMenuView::SettingsMenuView(NavigationView& nav) {
add_items({
//{ "..", ui::Color::light_grey(), &bitmap_icon_previous, [&nav](){ nav.pop(); } },
{ "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>(); } },
{ "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>(); } },
//{ "SD card modules", ui::Color::dark_cyan(), [&nav](){ nav.push<ModInfoView>(); } },
{ "Date/Time", ui::Color::dark_cyan(), &bitmap_icon_options_datetime, [&nav](){ nav.push<SetDateTimeView>(); } },
{ "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>(); } },
//{ "Play dead", ui::Color::dark_cyan(), &bitmap_icon_playdead, [&nav](){ nav.push<SetPlayDeadView>(); } }
{ "QR code", ui::Color::dark_cyan(), &bitmap_icon_qr_code, [&nav](){ nav.push<SetQRCodeView>(); } }
});
set_max_rows(2); // allow wider buttons
}
+34 -96
View File
@@ -99,7 +99,7 @@ private:
'0',
};
Button button_done {
Button button_save {
{ 2 * 8, 16 * 16, 12 * 8, 32 },
"Save"
};
@@ -197,7 +197,7 @@ private:
"Turn on bias voltage"
};
Button button_done {
Button button_save {
{ 2 * 8, 16 * 16, 12 * 8, 32 },
"Save"
};
@@ -219,11 +219,12 @@ public:
std::string title() const override { return "UI settings"; };
private:
/*Checkbox checkbox_login {
Checkbox checkbox_disable_touchscreen {
{ 3 * 8, 2 * 16 },
20,
"Login with play dead"
};*/
"Disable touchscreen"
};
Checkbox checkbox_speaker {
{ 3 * 8, 4 * 16 },
@@ -271,10 +272,15 @@ private:
}
};
Button button_ok {
Button button_save {
{ 2 * 8, 16 * 16, 12 * 8, 32 },
"Save"
};
Button button_cancel {
{ 16 * 8, 16 * 16, 12 * 8, 32 },
"Cancel",
};
};
class SetAudioView : public View {
@@ -298,111 +304,43 @@ private:
'0'
};
Button button_ok {
Button button_save {
{ 2 * 8, 16 * 16, 12 * 8, 32 },
"Save"
};
Button button_cancel {
{ 16 * 8, 16 * 16, 12 * 8, 32 },
"Cancel",
};
};
/*
class SetPlayDeadView : public View {
public:
SetPlayDeadView(NavigationView& nav);
void focus() override;
std::string title() const override { return "Playdead settings"; };
private:
bool entermode = false;
uint32_t sequence { 0 };
uint8_t keycount { 0 }, key_code { };
char sequence_txt[11] = { 0 };
Text text_sequence {
{ 64, 32, 14 * 8, 16 },
"Enter sequence",
};
Button button_enter {
{ 16, 192, 96, 24 },
"Enter"
};
Button button_cancel {
{ 128, 192, 96, 24 },
"Cancel"
};
};*/
/*class ModInfoView : public View {
class SetQRCodeView : public View {
public:
ModInfoView(NavigationView& nav);
SetQRCodeView(NavigationView& nav);
void focus() override;
void on_show() override;
std::string title() const override { return "QR code"; };
private:
void update_infos(uint8_t modn);
typedef struct moduleinfo_t{
char filename[9];
uint16_t version;
uint32_t size;
char md5[16];
char name[16];
char description[214];
} moduleinfo_t;
moduleinfo_t module_list[8]; // 8 max for now
uint8_t modules_nb;
Text text_modcount {
{ 2 * 8, 1 * 16, 18 * 8, 16 },
"Searching..."
Checkbox checkbox_bigger_qr {
{ 3 * 8, 9 * 16 },
20,
"Show large QR code"
};
OptionsField option_modules {
{ 2 * 8, 2 * 16 },
24,
{
{ "-", 0 }
}
Button button_save {
{ 2 * 8, 16 * 16, 12 * 8, 32 },
"Save"
};
Text text_name {
{ 2 * 8, 4 * 16, 5 * 8, 16 },
"Name:"
Button button_cancel {
{ 16 * 8, 16 * 16, 12 * 8, 32 },
"Cancel",
};
Text text_namestr {
{ 8 * 8, 4 * 16, 16 * 8, 16 },
"..."
};
Text text_size {
{ 2 * 8, 5 * 16, 5 * 8, 16 },
"Size:"
};
Text text_sizestr {
{ 8 * 8, 5 * 16, 16 * 8, 16 },
"..."
};
Text text_md5 {
{ 2 * 8, 6 * 16, 4 * 8, 16 },
"MD5:"
};
Text text_md5_a {
{ 7 * 8, 6 * 16, 16 * 8, 16 },
"..."
};
Text text_md5_b {
{ 7 * 8, 7 * 16, 16 * 8, 16 },
"..."
};
Button button_ok {
{ 4 * 8, 272, 64, 24 },
"Ok"
};
};*/
};
class SettingsMenuView : public BtnGridView {
public:
+63 -3
View File
@@ -41,6 +41,7 @@ void SondeLogger::on_packet(const sonde::Packet& packet) {
namespace ui {
SondeView::SondeView(NavigationView& nav) {
baseband::run_image(portapack::spi_flash::image_tag_sonde);
@@ -63,6 +64,7 @@ SondeView::SondeView(NavigationView& nav) {
&text_temp,
&text_humid,
&geopos,
&button_see_qr,
&button_see_map
});
@@ -98,7 +100,12 @@ SondeView::SondeView(NavigationView& nav) {
use_crc = v;
};
radio::enable({
receiver_model.set_tuning_frequency(tuning_frequency());
receiver_model.set_sampling_rate(sampling_rate);
receiver_model.set_baseband_bandwidth(baseband_bandwidth);
receiver_model.enable(); // Before using radio::enable(), but not updating Ant.DC-Bias.
/* radio::enable({ // this can be removed, previous version, no DC-bias ant. control.
tuning_frequency(),
sampling_rate,
baseband_bandwidth,
@@ -106,7 +113,13 @@ SondeView::SondeView(NavigationView& nav) {
receiver_model.rf_amp(),
static_cast<int8_t>(receiver_model.lna()),
static_cast<int8_t>(receiver_model.vga()),
});
}); */
// QR code with geo URI
button_see_qr.on_select = [this, &nav](Button&) {
nav.push<QRCodeView>(geo_uri);
};
button_see_map.on_select = [this, &nav](Button&) {
nav.push<GeoMapView>(
@@ -145,7 +158,8 @@ SondeView::SondeView(NavigationView& nav) {
SondeView::~SondeView() {
baseband::set_pitch_rssi(0, false);
radio::disable();
/* radio::disable(); */
receiver_model.disable(); // to switch off all, including DC bias.
baseband::shutdown();
audio::output::stop();
}
@@ -154,10 +168,56 @@ void SondeView::focus() {
field_vga.focus();
}
// used to convert float to character pointer, since unfortunately function like
// sprintf and c_str aren't supported.
char * SondeView::float_to_char(float x, char *p)
{
char *s = p + 9; // go to end of buffer
uint16_t decimals; // variable to store the decimals
int units; // variable to store the units (part to left of decimal place)
if (x < 0) { // take care of negative numbers
decimals = (int)(x * -100000) % 100000; // make 1000 for 3 decimals etc.
units = (int)(-1 * x);
} else { // positive numbers
decimals = (int)(x * 100000) % 100000;
units = (int)x;
}
// TODO: more elegant solution (loop?)
*--s = (decimals % 10) + '0';
decimals /= 10;
*--s = (decimals % 10) + '0';
decimals /= 10;
*--s = (decimals % 10) + '0';
decimals /= 10;
*--s = (decimals % 10) + '0';
decimals /= 10;
*--s = (decimals % 10) + '0';
*--s = '.';
while (units > 0) {
*--s = (units % 10) + '0';
units /= 10;
}
if (x < 0) *--s = '-'; // unary minus sign for negative numbers
return s;
}
void SondeView::on_packet(const sonde::Packet &packet)
{
if (!use_crc || packet.crc_ok()) //euquiq: Reject bad packet if crc is on
{
char buffer_lat[10] = {};
char buffer_lon[10] = {};
strcpy(geo_uri, "geo:");
strcat(geo_uri, float_to_char(gps_info.lat, buffer_lat));
strcat(geo_uri, ",");
strcat(geo_uri, float_to_char(gps_info.lon, buffer_lon));
text_signature.set(packet.type_string());
sonde_id = packet.serial_number(); //used also as tag on the geomap
+14 -3
View File
@@ -26,6 +26,7 @@
#include "ui_navigation.hpp"
#include "ui_receiver.hpp"
#include "ui_rssi.hpp"
#include "ui_qrcode.hpp"
#include "ui_geomap.hpp"
#include "event_m0.hpp"
@@ -63,6 +64,8 @@ public:
std::string title() const override { return "Radiosonde RX"; };
private:
std::unique_ptr<SondeLogger> logger { };
uint32_t target_frequency_ { 402700000 };
@@ -70,6 +73,8 @@ private:
bool use_crc { false };
bool beep { false };
char geo_uri[32] = {};
sonde::GPS_data gps_info { };
sonde::temp_humid temp_humid_info { };
std::string sonde_id { };
@@ -173,9 +178,15 @@ private:
{ 0, 12 * 16 },
GeoPos::alt_unit::METERS
};
Button button_see_qr {
{ 2 * 8, 15 * 16, 12 * 8, 3 * 16 },
"See QR"
};
Button button_see_map {
{ 8 * 8, 16 * 16, 14 * 8, 3 * 16 },
{ 16 * 8, 15 * 16, 12 * 8, 3 * 16 },
"See on map"
};
@@ -190,7 +201,7 @@ private:
void on_packet(const sonde::Packet& packet);
void on_headphone_volume_changed(int32_t v);
char * float_to_char(float x, char *p);
void set_target_frequency(const uint32_t new_value);
uint32_t tuning_frequency() const;
+55 -2
View File
@@ -1,7 +1,7 @@
/*
* Copyright (C) 2015 Jared Boone, ShareBrained Technology, Inc.
* Copyright (C) 2017 Furrtek
* Copyright (C) 2017 NotPike
* Copyright (C) 2022 NotPike
*
* This file is part of PortaPack.
*
@@ -27,6 +27,7 @@
#include "baseband_api.hpp"
#include "string_format.hpp"
using namespace portapack;
using namespace encoders;
@@ -45,7 +46,13 @@ void TouchTunesView::stop_tx() {
transmitter_model.disable();
tx_mode = IDLE;
progressbar.set_value(0);
text_status.set("Ready");
// EW Mode Check
if(check_ew.value()) {
start_ew();
} else {
text_status.set("Ready");
}
}
void TouchTunesView::on_tx_progress(const uint32_t progress, const bool done) {
@@ -72,7 +79,43 @@ void TouchTunesView::on_tx_progress(const uint32_t progress, const bool done) {
}
}
// EW (Electronic Warfare) Mode will jam the receiving jukebox
// while still alowing you (the hacker) to send commands
// to the target jukebox.
// EW Mode works by transmitting a CW on 433.92MHz inbetween
// transmission events.
void TouchTunesView::start_ew() {
// Radio
transmitter_model.set_tuning_frequency(433920000);
transmitter_model.set_sampling_rate(3072000U);
transmitter_model.set_rf_amp(true);
transmitter_model.set_baseband_bandwidth(3500000U);
transmitter_model.set_tx_gain(47);
transmitter_model.enable();
//UI
text_status.set("Jamming...");
progressbar.set_max(1);
progressbar.set_value(1);
}
void TouchTunesView::stop_ew() {
// Radio
transmitter_model.disable();
// UI
text_status.set("Ready");
progressbar.set_value(0);
}
void TouchTunesView::start_tx(const uint32_t button_index) {
// Check EW Mode
if(check_ew.value()) {
stop_ew();
}
std::string fragments = { "" };
size_t bit;
uint64_t frame_data;
@@ -136,6 +179,7 @@ TouchTunesView::TouchTunesView(
&labels,
&field_pin,
&check_scan,
&check_ew,
&text_status,
&progressbar
});
@@ -145,6 +189,15 @@ TouchTunesView::TouchTunesView(
field_pin.on_change = [this](int32_t v) {
pin = v;
};
// EW Mode
check_ew.on_select = [this](Checkbox&, bool v) {
if(v){
start_ew();
} else {
stop_ew();
}
};
const auto button_fn = [this](Button& button) {
start_tx(button.id);
+10 -2
View File
@@ -1,7 +1,7 @@
/*
* Copyright (C) 2015 Jared Boone, ShareBrained Technology, Inc.
* Copyright (C) 2017 Furrtek
* Copyright (C) 2018 NotPike
* Copyright (C) 2022 NotPike
*
* This file is part of PortaPack.
*
@@ -127,6 +127,8 @@ private:
void start_tx(const uint32_t button_index);
void stop_tx();
void on_tx_progress(const uint32_t progress, const bool done);
void start_ew();
void stop_ew();
struct remote_layout_t {
Point position;
@@ -191,11 +193,17 @@ private:
};
Checkbox check_scan {
{ 2 * 8, 27 * 8 },
{ 2 * 8, 25 * 8 },
4,
"Scan"
};
Checkbox check_ew {
{ 2 * 8, 29 * 8 },
4,
"EW Mode"
};
Text text_status {
{ 2 * 8, 33 * 8, 128, 16 },
"Ready"
+2 -2
View File
@@ -168,8 +168,8 @@ void speaker_mute() {
namespace input {
void start() {
audio_codec->microphone_enable();
void start(int8_t alc_mode) {
audio_codec->microphone_enable(alc_mode); // added user-GUI selection for AK4951, ALC mode parameter.
i2s::i2s0::rx_start();
}
+3 -3
View File
@@ -49,7 +49,7 @@ public:
virtual volume_range_t headphone_gain_range() const = 0;
virtual void set_headphone_volume(const volume_t volume) = 0;
virtual void microphone_enable() = 0;
virtual void microphone_enable(int8_t alc_mode) = 0; // added user-GUI AK4951 ,selected ALC mode.
virtual void microphone_disable() = 0;
virtual size_t reg_count() const = 0;
@@ -59,7 +59,7 @@ public:
namespace output {
void start();
void start(); // this other start(),no changed. ,in namespace output , used to config audio playback mode,
void stop();
void mute();
@@ -72,7 +72,7 @@ void speaker_unmute();
namespace input {
void start();
void start(int8_t alc_mode); // added parameter user-GUI select AK4951-ALC mode for config mic path,(recording mode in datasheet),
void stop();
} /* namespace input */
+22
View File
@@ -1285,6 +1285,28 @@ static constexpr Bitmap bitmap_icon_previous {
{ 16, 16 }, bitmap_icon_previous_data
};
static constexpr uint8_t bitmap_icon_qr_code_data[] = {
0x00, 0x00,
0xFE, 0x7E,
0xC6, 0x62,
0xFA, 0x5A,
0xFA, 0x5A,
0xDA, 0x5A,
0xFE, 0x7E,
0x7E, 0x7E,
0x00, 0x00,
0xFE, 0x46,
0xC2, 0x06,
0xFA, 0x18,
0xFA, 0x18,
0xC6, 0x60,
0xFE, 0x62,
0x00, 0x00,
};
static constexpr Bitmap bitmap_icon_qr_code {
{ 16, 16 }, bitmap_icon_qr_code_data
};
static constexpr uint8_t bitmap_icon_rds_data[] = {
0x00, 0x00,
0x00, 0x00,
+107
View File
@@ -0,0 +1,107 @@
/*
* 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 "database.hpp"
#include "file.hpp"
#include <cstring>
namespace std {
int database::retrieve_mid_record(MidDBRecord* record, std::string search_term){
file_path = "AIS/mids.db";
index_item_length = 4;
record_length = 32;
result = std::database::retrieve_record(file_path, index_item_length, record_length, record, search_term);
return(result);
}
int database::retrieve_airline_record(AirlinesDBRecord* record, std::string search_term){
file_path = "ADSB/airlines.db";
index_item_length = 4;
record_length = 64;
result = std::database::retrieve_record(file_path, index_item_length, record_length, record, search_term);
return(result);
}
int database::retrieve_aircraft_record(AircraftDBRecord* record, std::string search_term){
file_path = "ADSB/icao24.db";
index_item_length = 7;
record_length = 146;
result = std::database::retrieve_record(file_path, index_item_length, record_length, record, search_term);
return(result);
}
int database::retrieve_record(std::string file_path, int index_item_length, int record_length, void* record, std::string search_term)
{
auto result = db_file.open(file_path);
if (!result.is_valid()) {
number_of_records = (db_file.size() / (index_item_length + record_length)); // determine number of records in file
// binary search tree
int first = 0, // First search element
last = number_of_records - 1, // Last search element
middle, // Mid point of search
position = -1; // Position of search value
while (!found && first <= last) {
middle = (first + last) / 2; // Calculate mid point
db_file.seek(middle * index_item_length);
db_file.read(file_buffer, search_term.length());
if (file_buffer == search_term) { // If value is found at mid
found = true;
position = middle;
}
else if (file_buffer > search_term) // If value is in lower half
last = middle - 1;
else
first = middle + 1; // If value is in upper half
}
if(found == true) {
db_file.seek((number_of_records * index_item_length) + (position * record_length)); // seek starting after index
db_file.read(record, record_length);
return(DATABASE_RECORD_FOUND);
}
else {
return(DATABASE_RECORD_NOT_FOUND);
}
}
else return(DATABASE_NOT_FOUND);
}
} /* namespace std */
+94
View File
@@ -0,0 +1,94 @@
/*
* 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 __DATABASE_H__
#define __DATABASE_H__
#include <cstddef>
#include <cstdint>
#include <string>
#include "file.hpp"
namespace std {
class database {
public:
#define DATABASE_RECORD_FOUND 0 // record found in database
#define DATABASE_NOT_FOUND -1 // database not found / could not be opened
#define DATABASE_RECORD_NOT_FOUND -2 // record could not be found in database
struct MidDBRecord {
char country[32]; // country name
};
int retrieve_mid_record(MidDBRecord* record, std::string search_term);
struct AirlinesDBRecord {
char airline[32]; // airline name
char country[32]; // country name
};
int retrieve_airline_record(AirlinesDBRecord* record, std::string search_term);
struct AircraftDBRecord {
char aircraft_registration[9]; // aircraft registration
char aircraft_manufacturer[33]; // aircraft manufacturer
char aircraft_model[33]; // aircraft model
char icao_type[5]; // ICAO type descripton or when unavailable ICAO type designator
char aircraft_owner[33]; // aircraft owner
char aircraft_operator[33]; // aircraft operator
};
int retrieve_aircraft_record(AircraftDBRecord* record, std::string search_term);
private:
string file_path = ""; // path inclusing filename
int index_item_length = 0; // length of index item
int record_length = 0; // length of record
File db_file { };
int number_of_records = 0;
int position = 0;
char file_buffer[32] { 0 };
bool found = false;
int result = 0;
int retrieve_record(std::string file_path, int index_item_length, int record_length, void* record, std::string search_term);
};
} // namespace std
#endif/*__DATABASE_H__*/
+4 -4
View File
@@ -197,12 +197,12 @@ std::vector<std::filesystem::path> scan_root_directories(const std::filesystem::
return directory_list;
}
void delete_file(const std::filesystem::path& file_path) {
f_unlink(reinterpret_cast<const TCHAR*>(file_path.c_str()));
uint32_t delete_file(const std::filesystem::path& file_path) {
return f_unlink(reinterpret_cast<const TCHAR*>(file_path.c_str()));
}
void rename_file(const std::filesystem::path& file_path, const std::filesystem::path& new_name) {
f_rename(reinterpret_cast<const TCHAR*>(file_path.c_str()), reinterpret_cast<const TCHAR*>(new_name.c_str()));
uint32_t rename_file(const std::filesystem::path& file_path, const std::filesystem::path& new_name) {
return f_rename(reinterpret_cast<const TCHAR*>(file_path.c_str()), reinterpret_cast<const TCHAR*>(new_name.c_str()));
}
FATTimestamp file_created_date(const std::filesystem::path& file_path) {
+2 -2
View File
@@ -238,8 +238,8 @@ struct FATTimestamp {
uint16_t FAT_time;
};
void delete_file(const std::filesystem::path& file_path);
void rename_file(const std::filesystem::path& file_path, const std::filesystem::path& new_name);
uint32_t delete_file(const std::filesystem::path& file_path);
uint32_t rename_file(const std::filesystem::path& file_path, const std::filesystem::path& new_name);
FATTimestamp file_created_date(const std::filesystem::path& file_path);
uint32_t make_new_directory(const std::filesystem::path& dir_path);
+9 -9
View File
@@ -51,15 +51,15 @@ enum freqman_entry_type {
//Entry step placed for AlainD freqman version (or any other enhanced version)
enum freqman_entry_step {
STEP_DEF = 0, // default
AM_US, // 10 Khz AM/CB
AM_EUR, // 9 Khz LW/MW
NFM_1, // 12,5 Khz (Analogic PMR 446)
NFM_2, // 6,25 Khz (Digital PMR 446)
FM_1, // 100 Khz
FM_2, // 50 Khz
N_1, // 25 Khz
N_2, // 250 Khz
AIRBAND, // AIRBAND 8,33 Khz
AM_US, // 10 kHz AM/CB
AM_EUR, // 9 kHz LW/MW
NFM_1, // 12,5 kHz (Analogic PMR 446)
NFM_2, // 6,25 kHz (Digital PMR 446)
FM_1, // 100 kHz
FM_2, // 50 kHz
N_1, // 25 kHz
N_2, // 250 kHz
AIRBAND, // AIRBAND 8,33 kHz
ERROR_STEP
};
+3 -2
View File
@@ -167,14 +167,15 @@ int main(void) {
if( portapack::init() ) {
portapack::display.init();
sdcStart(&SDCD1, nullptr);
// sdcStart(&SDCD1, nullptr); // Commented out as now happens in portapack.cpp
controls_init();
// controls_init(); // Commented out as now happens in portapack.cpp
lcd_frame_sync_configure();
rtc_interrupt_enable();
event_loop();
sdcDisconnect(&SDCD1);
sdcStop(&SDCD1);
+120 -23
View File
@@ -29,6 +29,7 @@
#include "hackrf_gpio.hpp"
using namespace hackrf::one;
#include "clock_manager.hpp"
#include "event_m0.hpp"
@@ -45,6 +46,11 @@ using asahi_kasei::ak4951::AK4951;
#include "cpld_update.hpp"
#include "optional.hpp"
#include "irq_controls.hpp"
#include "file.hpp"
#include "sd_card.hpp"
#include "string_format.hpp"
namespace portapack {
@@ -175,22 +181,93 @@ enum class PortaPackModel {
R2_20170522,
};
static bool save_config(int8_t value){
persistent_memory::set_config_cpld(value);
if(sd_card::status() == sd_card::Status::Mounted){
make_new_directory("/hardware");
File file;
auto sucess = file.create("/hardware/settings.txt");
if(!sucess.is_valid()) {
file.write_line(to_string_dec_uint(value));
}
}
return true;
}
int read_file(std::string name) {
std::string return_string = "";
File file;
auto success = file.open(name);
if(!success.is_valid()) {
char one_char[1];
for(size_t pointer = 0; pointer < file.size() ; pointer++) {
file.seek(pointer);
file.read(one_char, 1);
return_string += one_char[0];
}
return std::stoi(return_string);
}
return -1;
}
static int load_config(){
static Optional<int> config_value;
if(!config_value.is_valid()){
int8_t value = portapack::persistent_memory::config_cpld();
if((value <= 0 || value >= 4) && sd_card::status() == sd_card::Status::Mounted){
int data = read_file("/hardware/settings.txt");
if(data != -1) {
config_value = data;
}
} else {
config_value = value;
}
}
return config_value.value();
}
static PortaPackModel portapack_model() {
static Optional<PortaPackModel> model;
if( !model.is_valid() ) {
/*For the time being, it is impossible to distinguish the hardware of R1 and R2 from the software level*/
/*At this point, I2c is not ready.*/
//if( audio_codec_wm8731.detected() ) {
// model = PortaPackModel::R1_20150901;
//} else {
const auto switches_state = get_switches_state();
if (switches_state[(size_t)ui::KeyEvent::Up]){
save_config(1);
model = PortaPackModel::R2_20170522;
//}
}
else if (switches_state[(size_t)ui::KeyEvent::Down]){
save_config(2);
model = PortaPackModel::R1_20150901;
}
else if (switches_state[(size_t)ui::KeyEvent::Left]){
save_config(3);
}
else if (switches_state[(size_t)ui::KeyEvent::Select]){
save_config(0);
}
if (load_config() == 1) {
model = PortaPackModel::R2_20170522;
} else if (load_config() == 2) {
model = PortaPackModel::R1_20150901;
} else {
if( audio_codec_wm8731.detected() ) {
model = PortaPackModel::R1_20150901; // H1R1
} else {
model = PortaPackModel::R2_20170522; // H1R2, H2, H2+
}
}
}
return model.value();
}
//audio_codec_wm8731 = H1R1 & H2+
//audio_codec_ak4951 = H1R2
static audio::Codec* portapack_audio_codec() {
/* I2C ready OK, Automatic recognition of audio chip */
return (audio_codec_wm8731.detected())
@@ -201,15 +278,14 @@ static audio::Codec* portapack_audio_codec() {
static const portapack::cpld::Config& portapack_cpld_config() {
return (portapack_model() == PortaPackModel::R2_20170522)
? portapack::cpld::rev_20170522::config
: portapack::cpld::rev_20150901::config
;
? portapack::cpld::rev_20170522::config
: portapack::cpld::rev_20150901::config;
}
Backlight* backlight() {
return (portapack_model() == PortaPackModel::R2_20170522)
? static_cast<portapack::Backlight*>(&backlight_cat4004)
: static_cast<portapack::Backlight*>(&backlight_on_off);
? static_cast<portapack::Backlight*>(&backlight_cat4004) // R2_20170522
: static_cast<portapack::Backlight*>(&backlight_on_off); // R1_20150901
}
#define ARRAY_SIZE(a) (sizeof(a)/sizeof(a[0]))
@@ -318,14 +394,15 @@ bool init() {
i2c0.start(i2c_config_boot_clock);
if( !portapack::cpld::update_if_necessary(portapack_cpld_config()) ) {
shutdown_base();
return false;
}
// Keeping this here for now incase we need to revert
// if( !portapack::cpld::update_if_necessary(portapack_cpld_config()) ) {
// shutdown_base();
// return false;
// }
if( !hackrf::cpld::load_sram() ) {
chSysHalt();
}
// if( !hackrf::cpld::load_sram() ) {
// chSysHalt();
// }
configure_pins_portapack();
@@ -336,7 +413,6 @@ bool init() {
i2c0.stop();
set_clock_config(clock_config_irc);
cgu::pll1::disable();
/* Incantation from LPC43xx UM10503 section 12.2.1.1, to bring the M4
@@ -377,20 +453,41 @@ bool init() {
i2c0.start(i2c_config_fast_clock);
clock_manager.set_reference_ppb(persistent_memory::correction_ppb());
touch::adc::init();
controls_init();
audio::init(portapack_audio_codec());
clock_manager.set_reference_ppb(persistent_memory::correction_ppb());
clock_manager.enable_first_if_clock();
clock_manager.enable_second_if_clock();
clock_manager.enable_codec_clocks();
radio::init();
touch::adc::init();
sdcStart(&SDCD1, nullptr);
sd_card::poll_inserted();
chThdSleepMilliseconds(1);
if( !portapack::cpld::update_if_necessary(portapack_cpld_config()) ) {
chThdSleepMilliseconds(1);
// If using a "2021/12 QFP100", press and hold the left button while booting. Should only need to do once.
if (load_config() != 3){
shutdown_base();
return false;
}
}
if( !hackrf::cpld::load_sram() ) {
chSysHalt();
}
chThdSleepMilliseconds(1); // This delay seems to solve white noise audio issues
LPC_CREG->DMAMUX = portapack::gpdma_mux;
gpdma::controller.enable();
audio::init(portapack_audio_codec());
return true;
}
+876
View File
@@ -0,0 +1,876 @@
/**
* The MIT License (MIT)
*
* This library is written and maintained by Richard Moore.
* Major parts were derived from Project Nayuki's library.
*
* Copyright (c) 2017 Richard Moore (https://github.com/ricmoo/QRCode)
* Copyright (c) 2017 Project Nayuki (https://www.nayuki.io/page/qr-code-generator-library)
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
/**
* Special thanks to Nayuki (https://www.nayuki.io/) from which this library was
* heavily inspired and compared against.
*
* See: https://github.com/nayuki/QR-Code-generator/tree/master/cpp
*/
#include "qrcodegen.hpp"
#include <stdlib.h>
#include <string.h>
#pragma mark - Error Correction Lookup tables
#if LOCK_VERSION == 0
static const uint16_t NUM_ERROR_CORRECTION_CODEWORDS[4][40] = {
// 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40 Error correction level
{ 10, 16, 26, 36, 48, 64, 72, 88, 110, 130, 150, 176, 198, 216, 240, 280, 308, 338, 364, 416, 442, 476, 504, 560, 588, 644, 700, 728, 784, 812, 868, 924, 980, 1036, 1064, 1120, 1204, 1260, 1316, 1372}, // Medium
{ 7, 10, 15, 20, 26, 36, 40, 48, 60, 72, 80, 96, 104, 120, 132, 144, 168, 180, 196, 224, 224, 252, 270, 300, 312, 336, 360, 390, 420, 450, 480, 510, 540, 570, 570, 600, 630, 660, 720, 750}, // Low
{ 17, 28, 44, 64, 88, 112, 130, 156, 192, 224, 264, 308, 352, 384, 432, 480, 532, 588, 650, 700, 750, 816, 900, 960, 1050, 1110, 1200, 1260, 1350, 1440, 1530, 1620, 1710, 1800, 1890, 1980, 2100, 2220, 2310, 2430}, // High
{ 13, 22, 36, 52, 72, 96, 108, 132, 160, 192, 224, 260, 288, 320, 360, 408, 448, 504, 546, 600, 644, 690, 750, 810, 870, 952, 1020, 1050, 1140, 1200, 1290, 1350, 1440, 1530, 1590, 1680, 1770, 1860, 1950, 2040}, // Quartile
};
static const uint8_t NUM_ERROR_CORRECTION_BLOCKS[4][40] = {
// Version: (note that index 0 is for padding, and is set to an illegal value)
// 1, 2, 3, 4, 5, 6, 7, 8, 9,10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40 Error correction level
{ 1, 1, 1, 2, 2, 4, 4, 4, 5, 5, 5, 8, 9, 9, 10, 10, 11, 13, 14, 16, 17, 17, 18, 20, 21, 23, 25, 26, 28, 29, 31, 33, 35, 37, 38, 40, 43, 45, 47, 49}, // Medium
{ 1, 1, 1, 1, 1, 2, 2, 2, 2, 4, 4, 4, 4, 4, 6, 6, 6, 6, 7, 8, 8, 9, 9, 10, 12, 12, 12, 13, 14, 15, 16, 17, 18, 19, 19, 20, 21, 22, 24, 25}, // Low
{ 1, 1, 2, 4, 4, 4, 5, 6, 8, 8, 11, 11, 16, 16, 18, 16, 19, 21, 25, 25, 25, 34, 30, 32, 35, 37, 40, 42, 45, 48, 51, 54, 57, 60, 63, 66, 70, 74, 77, 81}, // High
{ 1, 1, 2, 2, 4, 4, 6, 6, 8, 8, 8, 10, 12, 16, 12, 17, 16, 18, 21, 20, 23, 23, 25, 27, 29, 34, 34, 35, 38, 40, 43, 45, 48, 51, 53, 56, 59, 62, 65, 68}, // Quartile
};
static const uint16_t NUM_RAW_DATA_MODULES[40] = {
// 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17,
208, 359, 567, 807, 1079, 1383, 1568, 1936, 2336, 2768, 3232, 3728, 4256, 4651, 5243, 5867, 6523,
// 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
7211, 7931, 8683, 9252, 10068, 10916, 11796, 12708, 13652, 14628, 15371, 16411, 17483, 18587,
// 32, 33, 34, 35, 36, 37, 38, 39, 40
19723, 20891, 22091, 23008, 24272, 25568, 26896, 28256, 29648
};
// @TODO: Put other LOCK_VERSIONS here
#elif LOCK_VERSION == 3
static const int16_t NUM_ERROR_CORRECTION_CODEWORDS[4] = {
26, 15, 44, 36
};
static const int8_t NUM_ERROR_CORRECTION_BLOCKS[4] = {
1, 1, 2, 2
};
static const uint16_t NUM_RAW_DATA_MODULES = 567;
#else
#error Unsupported LOCK_VERSION (add it...)
#endif
static int max(int a, int b) {
if (a > b) { return a; }
return b;
}
/*
static int abs(int value) {
if (value < 0) { return -value; }
return value;
}
*/
#pragma mark - Mode testing and conversion
static int8_t getAlphanumeric(char c) {
if (c >= '0' && c <= '9') { return (c - '0'); }
if (c >= 'A' && c <= 'Z') { return (c - 'A' + 10); }
switch (c) {
case ' ': return 36;
case '$': return 37;
case '%': return 38;
case '*': return 39;
case '+': return 40;
case '-': return 41;
case '.': return 42;
case '/': return 43;
case ':': return 44;
}
return -1;
}
static bool isAlphanumeric(const char *text, uint16_t length) {
while (length != 0) {
if (getAlphanumeric(text[--length]) == -1) { return false; }
}
return true;
}
static bool isNumeric(const char *text, uint16_t length) {
while (length != 0) {
char c = text[--length];
if (c < '0' || c > '9') { return false; }
}
return true;
}
#pragma mark - Counting
// We store the following tightly packed (less 8) in modeInfo
// <=9 <=26 <= 40
// NUMERIC ( 10, 12, 14);
// ALPHANUMERIC ( 9, 11, 13);
// BYTE ( 8, 16, 16);
static char getModeBits(uint8_t version, uint8_t mode) {
// Note: We use 15 instead of 16; since 15 doesn't exist and we cannot store 16 (8 + 8) in 3 bits
// hex(int("".join(reversed([('00' + bin(x - 8)[2:])[-3:] for x in [10, 9, 8, 12, 11, 15, 14, 13, 15]])), 2))
unsigned int modeInfo = 0x7bbb80a;
#if LOCK_VERSION == 0 || LOCK_VERSION > 9
if (version > 9) { modeInfo >>= 9; }
#endif
#if LOCK_VERSION == 0 || LOCK_VERSION > 26
if (version > 26) { modeInfo >>= 9; }
#endif
char result = 8 + ((modeInfo >> (3 * mode)) & 0x07);
if (result == 15) { result = 16; }
return result;
}
#pragma mark - BitBucket
typedef struct BitBucket {
uint32_t bitOffsetOrWidth;
uint16_t capacityBytes;
uint8_t *data;
} BitBucket;
/*
void bb_dump(BitBucket *bitBuffer) {
printf("Buffer: ");
for (uint32_t i = 0; i < bitBuffer->capacityBytes; i++) {
printf("%02x", bitBuffer->data[i]);
if ((i % 4) == 3) { printf(" "); }
}
printf("\n");
}
*/
static uint16_t bb_getGridSizeBytes(uint8_t size) {
return (((size * size) + 7) / 8);
}
static uint16_t bb_getBufferSizeBytes(uint32_t bits) {
return ((bits + 7) / 8);
}
static void bb_initBuffer(BitBucket *bitBuffer, uint8_t *data, int32_t capacityBytes) {
bitBuffer->bitOffsetOrWidth = 0;
bitBuffer->capacityBytes = capacityBytes;
bitBuffer->data = data;
memset(data, 0, bitBuffer->capacityBytes);
}
static void bb_initGrid(BitBucket *bitGrid, uint8_t *data, uint8_t size) {
bitGrid->bitOffsetOrWidth = size;
bitGrid->capacityBytes = bb_getGridSizeBytes(size);
bitGrid->data = data;
memset(data, 0, bitGrid->capacityBytes);
}
static void bb_appendBits(BitBucket *bitBuffer, uint32_t val, uint8_t length) {
uint32_t offset = bitBuffer->bitOffsetOrWidth;
for (int8_t i = length - 1; i >= 0; i--, offset++) {
bitBuffer->data[offset >> 3] |= ((val >> i) & 1) << (7 - (offset & 7));
}
bitBuffer->bitOffsetOrWidth = offset;
}
/*
void bb_setBits(BitBucket *bitBuffer, uint32_t val, int offset, uint8_t length) {
for (int8_t i = length - 1; i >= 0; i--, offset++) {
bitBuffer->data[offset >> 3] |= ((val >> i) & 1) << (7 - (offset & 7));
}
}
*/
static void bb_setBit(BitBucket *bitGrid, uint8_t x, uint8_t y, bool on) {
uint32_t offset = y * bitGrid->bitOffsetOrWidth + x;
uint8_t mask = 1 << (7 - (offset & 0x07));
if (on) {
bitGrid->data[offset >> 3] |= mask;
} else {
bitGrid->data[offset >> 3] &= ~mask;
}
}
static void bb_invertBit(BitBucket *bitGrid, uint8_t x, uint8_t y, bool invert) {
uint32_t offset = y * bitGrid->bitOffsetOrWidth + x;
uint8_t mask = 1 << (7 - (offset & 0x07));
bool on = ((bitGrid->data[offset >> 3] & (1 << (7 - (offset & 0x07)))) != 0);
if (on ^ invert) {
bitGrid->data[offset >> 3] |= mask;
} else {
bitGrid->data[offset >> 3] &= ~mask;
}
}
static bool bb_getBit(BitBucket *bitGrid, uint8_t x, uint8_t y) {
uint32_t offset = y * bitGrid->bitOffsetOrWidth + x;
return (bitGrid->data[offset >> 3] & (1 << (7 - (offset & 0x07)))) != 0;
}
#pragma mark - Drawing Patterns
// XORs the data modules in this QR Code with the given mask pattern. Due to XOR's mathematical
// properties, calling applyMask(m) twice with the same value is equivalent to no change at all.
// This means it is possible to apply a mask, undo it, and try another mask. Note that a final
// well-formed QR Code symbol needs exactly one mask applied (not zero, not two, etc.).
static void applyMask(BitBucket *modules, BitBucket *isFunction, uint8_t mask) {
uint8_t size = modules->bitOffsetOrWidth;
for (uint8_t y = 0; y < size; y++) {
for (uint8_t x = 0; x < size; x++) {
if (bb_getBit(isFunction, x, y)) { continue; }
bool invert = 0;
switch (mask) {
case 0: invert = (x + y) % 2 == 0; break;
case 1: invert = y % 2 == 0; break;
case 2: invert = x % 3 == 0; break;
case 3: invert = (x + y) % 3 == 0; break;
case 4: invert = (x / 3 + y / 2) % 2 == 0; break;
case 5: invert = x * y % 2 + x * y % 3 == 0; break;
case 6: invert = (x * y % 2 + x * y % 3) % 2 == 0; break;
case 7: invert = ((x + y) % 2 + x * y % 3) % 2 == 0; break;
}
bb_invertBit(modules, x, y, invert);
}
}
}
static void setFunctionModule(BitBucket *modules, BitBucket *isFunction, uint8_t x, uint8_t y, bool on) {
bb_setBit(modules, x, y, on);
bb_setBit(isFunction, x, y, true);
}
// Draws a 9*9 finder pattern including the border separator, with the center module at (x, y).
static void drawFinderPattern(BitBucket *modules, BitBucket *isFunction, uint8_t x, uint8_t y) {
uint8_t size = modules->bitOffsetOrWidth;
for (int8_t i = -4; i <= 4; i++) {
for (int8_t j = -4; j <= 4; j++) {
uint8_t dist = max(abs(i), abs(j)); // Chebyshev/infinity norm
int16_t xx = x + j, yy = y + i;
if (0 <= xx && xx < size && 0 <= yy && yy < size) {
setFunctionModule(modules, isFunction, xx, yy, dist != 2 && dist != 4);
}
}
}
}
// Draws a 5*5 alignment pattern, with the center module at (x, y).
static void drawAlignmentPattern(BitBucket *modules, BitBucket *isFunction, uint8_t x, uint8_t y) {
for (int8_t i = -2; i <= 2; i++) {
for (int8_t j = -2; j <= 2; j++) {
setFunctionModule(modules, isFunction, x + j, y + i, max(abs(i), abs(j)) != 1);
}
}
}
// Draws two copies of the format bits (with its own error correction code)
// based on the given mask and this object's error correction level field.
static void drawFormatBits(BitBucket *modules, BitBucket *isFunction, uint8_t ecc, uint8_t mask) {
uint8_t size = modules->bitOffsetOrWidth;
// Calculate error correction code and pack bits
uint32_t data = ecc << 3 | mask; // errCorrLvl is uint2, mask is uint3
uint32_t rem = data;
for (int i = 0; i < 10; i++) {
rem = (rem << 1) ^ ((rem >> 9) * 0x537);
}
data = data << 10 | rem;
data ^= 0x5412; // uint15
// Draw first copy
for (uint8_t i = 0; i <= 5; i++) {
setFunctionModule(modules, isFunction, 8, i, ((data >> i) & 1) != 0);
}
setFunctionModule(modules, isFunction, 8, 7, ((data >> 6) & 1) != 0);
setFunctionModule(modules, isFunction, 8, 8, ((data >> 7) & 1) != 0);
setFunctionModule(modules, isFunction, 7, 8, ((data >> 8) & 1) != 0);
for (int8_t i = 9; i < 15; i++) {
setFunctionModule(modules, isFunction, 14 - i, 8, ((data >> i) & 1) != 0);
}
// Draw second copy
for (int8_t i = 0; i <= 7; i++) {
setFunctionModule(modules, isFunction, size - 1 - i, 8, ((data >> i) & 1) != 0);
}
for (int8_t i = 8; i < 15; i++) {
setFunctionModule(modules, isFunction, 8, size - 15 + i, ((data >> i) & 1) != 0);
}
setFunctionModule(modules, isFunction, 8, size - 8, true);
}
// Draws two copies of the version bits (with its own error correction code),
// based on this object's version field (which only has an effect for 7 <= version <= 40).
static void drawVersion(BitBucket *modules, BitBucket *isFunction, uint8_t version) {
int8_t size = modules->bitOffsetOrWidth;
#if LOCK_VERSION != 0 && LOCK_VERSION < 7
return;
#else
if (version < 7) { return; }
// Calculate error correction code and pack bits
uint32_t rem = version; // version is uint6, in the range [7, 40]
for (uint8_t i = 0; i < 12; i++) {
rem = (rem << 1) ^ ((rem >> 11) * 0x1F25);
}
uint32_t data = version << 12 | rem; // uint18
// Draw two copies
for (uint8_t i = 0; i < 18; i++) {
bool bit = ((data >> i) & 1) != 0;
uint8_t a = size - 11 + i % 3, b = i / 3;
setFunctionModule(modules, isFunction, a, b, bit);
setFunctionModule(modules, isFunction, b, a, bit);
}
#endif
}
static void drawFunctionPatterns(BitBucket *modules, BitBucket *isFunction, uint8_t version, uint8_t ecc) {
uint8_t size = modules->bitOffsetOrWidth;
// Draw the horizontal and vertical timing patterns
for (uint8_t i = 0; i < size; i++) {
setFunctionModule(modules, isFunction, 6, i, i % 2 == 0);
setFunctionModule(modules, isFunction, i, 6, i % 2 == 0);
}
// Draw 3 finder patterns (all corners except bottom right; overwrites some timing modules)
drawFinderPattern(modules, isFunction, 3, 3);
drawFinderPattern(modules, isFunction, size - 4, 3);
drawFinderPattern(modules, isFunction, 3, size - 4);
#if LOCK_VERSION == 0 || LOCK_VERSION > 1
if (version > 1) {
// Draw the numerous alignment patterns
uint8_t alignCount = version / 7 + 2;
uint8_t step;
if (version != 32) {
step = (version * 4 + alignCount * 2 + 1) / (2 * alignCount - 2) * 2; // ceil((size - 13) / (2*numAlign - 2)) * 2
} else { // C-C-C-Combo breaker!
step = 26;
}
uint8_t alignPositionIndex = alignCount - 1;
uint8_t alignPosition[alignCount];
alignPosition[0] = 6;
uint8_t size = version * 4 + 17;
for (uint8_t i = 0, pos = size - 7; i < alignCount - 1; i++, pos -= step) {
alignPosition[alignPositionIndex--] = pos;
}
for (uint8_t i = 0; i < alignCount; i++) {
for (uint8_t j = 0; j < alignCount; j++) {
if ((i == 0 && j == 0) || (i == 0 && j == alignCount - 1) || (i == alignCount - 1 && j == 0)) {
continue; // Skip the three finder corners
} else {
drawAlignmentPattern(modules, isFunction, alignPosition[i], alignPosition[j]);
}
}
}
}
#endif
// Draw configuration data
drawFormatBits(modules, isFunction, ecc, 0); // Dummy mask value; overwritten later in the constructor
drawVersion(modules, isFunction, version);
}
// Draws the given sequence of 8-bit codewords (data and error correction) onto the entire
// data area of this QR Code symbol. Function modules need to be marked off before this is called.
static void drawCodewords(BitBucket *modules, BitBucket *isFunction, BitBucket *codewords) {
uint32_t bitLength = codewords->bitOffsetOrWidth;
uint8_t *data = codewords->data;
uint8_t size = modules->bitOffsetOrWidth;
// Bit index into the data
uint32_t i = 0;
// Do the funny zigzag scan
for (int16_t right = size - 1; right >= 1; right -= 2) { // Index of right column in each column pair
if (right == 6) { right = 5; }
for (uint8_t vert = 0; vert < size; vert++) { // Vertical counter
for (int j = 0; j < 2; j++) {
uint8_t x = right - j; // Actual x coordinate
bool upwards = ((right & 2) == 0) ^ (x < 6);
uint8_t y = upwards ? size - 1 - vert : vert; // Actual y coordinate
if (!bb_getBit(isFunction, x, y) && i < bitLength) {
bb_setBit(modules, x, y, ((data[i >> 3] >> (7 - (i & 7))) & 1) != 0);
i++;
}
// If there are any remainder bits (0 to 7), they are already
// set to 0/false/white when the grid of modules was initialized
}
}
}
}
#pragma mark - Penalty Calculation
#define PENALTY_N1 3
#define PENALTY_N2 3
#define PENALTY_N3 40
#define PENALTY_N4 10
// Calculates and returns the penalty score based on state of this QR Code's current modules.
// This is used by the automatic mask choice algorithm to find the mask pattern that yields the lowest score.
// @TODO: This can be optimized by working with the bytes instead of bits.
static uint32_t getPenaltyScore(BitBucket *modules) {
uint32_t result = 0;
uint8_t size = modules->bitOffsetOrWidth;
// Adjacent modules in row having same color
for (uint8_t y = 0; y < size; y++) {
bool colorX = bb_getBit(modules, 0, y);
for (uint8_t x = 1, runX = 1; x < size; x++) {
bool cx = bb_getBit(modules, x, y);
if (cx != colorX) {
colorX = cx;
runX = 1;
} else {
runX++;
if (runX == 5) {
result += PENALTY_N1;
} else if (runX > 5) {
result++;
}
}
}
}
// Adjacent modules in column having same color
for (uint8_t x = 0; x < size; x++) {
bool colorY = bb_getBit(modules, x, 0);
for (uint8_t y = 1, runY = 1; y < size; y++) {
bool cy = bb_getBit(modules, x, y);
if (cy != colorY) {
colorY = cy;
runY = 1;
} else {
runY++;
if (runY == 5) {
result += PENALTY_N1;
} else if (runY > 5) {
result++;
}
}
}
}
uint16_t black = 0;
for (uint8_t y = 0; y < size; y++) {
uint16_t bitsRow = 0, bitsCol = 0;
for (uint8_t x = 0; x < size; x++) {
bool color = bb_getBit(modules, x, y);
// 2*2 blocks of modules having same color
if (x > 0 && y > 0) {
bool colorUL = bb_getBit(modules, x - 1, y - 1);
bool colorUR = bb_getBit(modules, x, y - 1);
bool colorL = bb_getBit(modules, x - 1, y);
if (color == colorUL && color == colorUR && color == colorL) {
result += PENALTY_N2;
}
}
// Finder-like pattern in rows and columns
bitsRow = ((bitsRow << 1) & 0x7FF) | color;
bitsCol = ((bitsCol << 1) & 0x7FF) | bb_getBit(modules, y, x);
// Needs 11 bits accumulated
if (x >= 10) {
if (bitsRow == 0x05D || bitsRow == 0x5D0) {
result += PENALTY_N3;
}
if (bitsCol == 0x05D || bitsCol == 0x5D0) {
result += PENALTY_N3;
}
}
// Balance of black and white modules
if (color) { black++; }
}
}
// Find smallest k such that (45-5k)% <= dark/total <= (55+5k)%
uint16_t total = size * size;
for (uint16_t k = 0; black * 20 < (9 - k) * total || black * 20 > (11 + k) * total; k++) {
result += PENALTY_N4;
}
return result;
}
#pragma mark - Reed-Solomon Generator
static uint8_t rs_multiply(uint8_t x, uint8_t y) {
// Russian peasant multiplication
// See: https://en.wikipedia.org/wiki/Ancient_Egyptian_multiplication
uint16_t z = 0;
for (int8_t i = 7; i >= 0; i--) {
z = (z << 1) ^ ((z >> 7) * 0x11D);
z ^= ((y >> i) & 1) * x;
}
return z;
}
static void rs_init(uint8_t degree, uint8_t *coeff) {
memset(coeff, 0, degree);
coeff[degree - 1] = 1;
// Compute the product polynomial (x - r^0) * (x - r^1) * (x - r^2) * ... * (x - r^{degree-1}),
// drop the highest term, and store the rest of the coefficients in order of descending powers.
// Note that r = 0x02, which is a generator element of this field GF(2^8/0x11D).
uint16_t root = 1;
for (uint8_t i = 0; i < degree; i++) {
// Multiply the current product by (x - r^i)
for (uint8_t j = 0; j < degree; j++) {
coeff[j] = rs_multiply(coeff[j], root);
if (j + 1 < degree) {
coeff[j] ^= coeff[j + 1];
}
}
root = (root << 1) ^ ((root >> 7) * 0x11D); // Multiply by 0x02 mod GF(2^8/0x11D)
}
}
static void rs_getRemainder(uint8_t degree, uint8_t *coeff, uint8_t *data, uint8_t length, uint8_t *result, uint8_t stride) {
// Compute the remainder by performing polynomial division
//for (uint8_t i = 0; i < degree; i++) { result[] = 0; }
//memset(result, 0, degree);
for (uint8_t i = 0; i < length; i++) {
uint8_t factor = data[i] ^ result[0];
for (uint8_t j = 1; j < degree; j++) {
result[(j - 1) * stride] = result[j * stride];
}
result[(degree - 1) * stride] = 0;
for (uint8_t j = 0; j < degree; j++) {
result[j * stride] ^= rs_multiply(coeff[j], factor);
}
}
}
#pragma mark - QrCode
static int8_t encodeDataCodewords(BitBucket *dataCodewords, const uint8_t *text, uint16_t length, uint8_t version) {
int8_t mode = MODE_BYTE;
if (isNumeric((char*)text, length)) {
mode = MODE_NUMERIC;
bb_appendBits(dataCodewords, 1 << MODE_NUMERIC, 4);
bb_appendBits(dataCodewords, length, getModeBits(version, MODE_NUMERIC));
uint16_t accumData = 0;
uint8_t accumCount = 0;
for (uint16_t i = 0; i < length; i++) {
accumData = accumData * 10 + ((char)(text[i]) - '0');
accumCount++;
if (accumCount == 3) {
bb_appendBits(dataCodewords, accumData, 10);
accumData = 0;
accumCount = 0;
}
}
// 1 or 2 digits remaining
if (accumCount > 0) {
bb_appendBits(dataCodewords, accumData, accumCount * 3 + 1);
}
} else if (isAlphanumeric((char*)text, length)) {
mode = MODE_ALPHANUMERIC;
bb_appendBits(dataCodewords, 1 << MODE_ALPHANUMERIC, 4);
bb_appendBits(dataCodewords, length, getModeBits(version, MODE_ALPHANUMERIC));
uint16_t accumData = 0;
uint8_t accumCount = 0;
for (uint16_t i = 0; i < length; i++) {
accumData = accumData * 45 + getAlphanumeric((char)(text[i]));
accumCount++;
if (accumCount == 2) {
bb_appendBits(dataCodewords, accumData, 11);
accumData = 0;
accumCount = 0;
}
}
// 1 character remaining
if (accumCount > 0) {
bb_appendBits(dataCodewords, accumData, 6);
}
} else {
bb_appendBits(dataCodewords, 1 << MODE_BYTE, 4);
bb_appendBits(dataCodewords, length, getModeBits(version, MODE_BYTE));
for (uint16_t i = 0; i < length; i++) {
bb_appendBits(dataCodewords, (char)(text[i]), 8);
}
}
//bb_setBits(dataCodewords, length, 4, getModeBits(version, mode));
return mode;
}
static void performErrorCorrection(uint8_t version, uint8_t ecc, BitBucket *data) {
// See: http://www.thonky.com/qr-code-tutorial/structure-final-message
#if LOCK_VERSION == 0
uint8_t numBlocks = NUM_ERROR_CORRECTION_BLOCKS[ecc][version - 1];
uint16_t totalEcc = NUM_ERROR_CORRECTION_CODEWORDS[ecc][version - 1];
uint16_t moduleCount = NUM_RAW_DATA_MODULES[version - 1];
#else
uint8_t numBlocks = NUM_ERROR_CORRECTION_BLOCKS[ecc];
uint16_t totalEcc = NUM_ERROR_CORRECTION_CODEWORDS[ecc];
uint16_t moduleCount = NUM_RAW_DATA_MODULES;
#endif
uint8_t blockEccLen = totalEcc / numBlocks;
uint8_t numShortBlocks = numBlocks - moduleCount / 8 % numBlocks;
uint8_t shortBlockLen = moduleCount / 8 / numBlocks;
uint8_t shortDataBlockLen = shortBlockLen - blockEccLen;
uint8_t result[data->capacityBytes];
memset(result, 0, sizeof(result));
uint8_t coeff[blockEccLen];
rs_init(blockEccLen, coeff);
uint16_t offset = 0;
uint8_t *dataBytes = data->data;
// Interleave all short blocks
for (uint8_t i = 0; i < shortDataBlockLen; i++) {
uint16_t index = i;
uint8_t stride = shortDataBlockLen;
for (uint8_t blockNum = 0; blockNum < numBlocks; blockNum++) {
result[offset++] = dataBytes[index];
#if LOCK_VERSION == 0 || LOCK_VERSION >= 5
if (blockNum == numShortBlocks) { stride++; }
#endif
index += stride;
}
}
// Version less than 5 only have short blocks
#if LOCK_VERSION == 0 || LOCK_VERSION >= 5
{
// Interleave long blocks
uint16_t index = shortDataBlockLen * (numShortBlocks + 1);
uint8_t stride = shortDataBlockLen;
for (uint8_t blockNum = 0; blockNum < numBlocks - numShortBlocks; blockNum++) {
result[offset++] = dataBytes[index];
if (blockNum == 0) { stride++; }
index += stride;
}
}
#endif
// Add all ecc blocks, interleaved
uint8_t blockSize = shortDataBlockLen;
for (uint8_t blockNum = 0; blockNum < numBlocks; blockNum++) {
#if LOCK_VERSION == 0 || LOCK_VERSION >= 5
if (blockNum == numShortBlocks) { blockSize++; }
#endif
rs_getRemainder(blockEccLen, coeff, dataBytes, blockSize, &result[offset + blockNum], numBlocks);
dataBytes += blockSize;
}
memcpy(data->data, result, data->capacityBytes);
data->bitOffsetOrWidth = moduleCount;
}
// We store the Format bits tightly packed into a single byte (each of the 4 modes is 2 bits)
// The format bits can be determined by ECC_FORMAT_BITS >> (2 * ecc)
static const uint8_t ECC_FORMAT_BITS = (0x02 << 6) | (0x03 << 4) | (0x00 << 2) | (0x01 << 0);
#pragma mark - Public QRCode functions
uint16_t qrcode_getBufferSize(uint8_t version) {
return bb_getGridSizeBytes(4 * version + 17);
}
// @TODO: Return error if data is too big.
int8_t qrcode_initBytes(QRCode *qrcode, uint8_t *modules, uint8_t version, uint8_t ecc, uint8_t *data, uint16_t length) {
uint8_t size = version * 4 + 17;
qrcode->version = version;
qrcode->size = size;
qrcode->ecc = ecc;
qrcode->modules = modules;
uint8_t eccFormatBits = (ECC_FORMAT_BITS >> (2 * ecc)) & 0x03;
#if LOCK_VERSION == 0
uint16_t moduleCount = NUM_RAW_DATA_MODULES[version - 1];
uint16_t dataCapacity = moduleCount / 8 - NUM_ERROR_CORRECTION_CODEWORDS[eccFormatBits][version - 1];
#else
version = LOCK_VERSION;
uint16_t moduleCount = NUM_RAW_DATA_MODULES;
uint16_t dataCapacity = moduleCount / 8 - NUM_ERROR_CORRECTION_CODEWORDS[eccFormatBits];
#endif
struct BitBucket codewords;
uint8_t codewordBytes[bb_getBufferSizeBytes(moduleCount)];
bb_initBuffer(&codewords, codewordBytes, (int32_t)sizeof(codewordBytes));
// Place the data code words into the buffer
int8_t mode = encodeDataCodewords(&codewords, data, length, version);
if (mode < 0) { return -1; }
qrcode->mode = mode;
// Add terminator and pad up to a byte if applicable
uint32_t padding = (dataCapacity * 8) - codewords.bitOffsetOrWidth;
if (padding > 4) { padding = 4; }
bb_appendBits(&codewords, 0, padding);
bb_appendBits(&codewords, 0, (8 - codewords.bitOffsetOrWidth % 8) % 8);
// Pad with alternate bytes until data capacity is reached
for (uint8_t padByte = 0xEC; codewords.bitOffsetOrWidth < (dataCapacity * 8); padByte ^= 0xEC ^ 0x11) {
bb_appendBits(&codewords, padByte, 8);
}
BitBucket modulesGrid;
bb_initGrid(&modulesGrid, modules, size);
BitBucket isFunctionGrid;
uint8_t isFunctionGridBytes[bb_getGridSizeBytes(size)];
bb_initGrid(&isFunctionGrid, isFunctionGridBytes, size);
// Draw function patterns, draw all codewords, do masking
drawFunctionPatterns(&modulesGrid, &isFunctionGrid, version, eccFormatBits);
performErrorCorrection(version, eccFormatBits, &codewords);
drawCodewords(&modulesGrid, &isFunctionGrid, &codewords);
// Find the best (lowest penalty) mask
uint8_t mask = 0;
int32_t minPenalty = INT32_MAX;
for (uint8_t i = 0; i < 8; i++) {
drawFormatBits(&modulesGrid, &isFunctionGrid, eccFormatBits, i);
applyMask(&modulesGrid, &isFunctionGrid, i);
int penalty = getPenaltyScore(&modulesGrid);
if (penalty < minPenalty) {
mask = i;
minPenalty = penalty;
}
applyMask(&modulesGrid, &isFunctionGrid, i); // Undoes the mask due to XOR
}
qrcode->mask = mask;
// Overwrite old format bits
drawFormatBits(&modulesGrid, &isFunctionGrid, eccFormatBits, mask);
// Apply the final choice of mask
applyMask(&modulesGrid, &isFunctionGrid, mask);
return 0;
}
int8_t qrcode_initText(QRCode *qrcode, uint8_t *modules, uint8_t version, uint8_t ecc, const char *data) {
return qrcode_initBytes(qrcode, modules, version, ecc, (uint8_t*)data, strlen(data));
}
bool qrcode_getModule(QRCode *qrcode, uint8_t x, uint8_t y) {
if (x < 0 || x >= qrcode->size || y < 0 || y >= qrcode->size) {
return false;
}
uint32_t offset = y * qrcode->size + x;
return (qrcode->modules[offset >> 3] & (1 << (7 - (offset & 0x07)))) != 0;
}
/*
uint8_t qrcode_getHexLength(QRCode *qrcode) {
return ((qrcode->size * qrcode->size) + 7) / 4;
}
void qrcode_getHex(QRCode *qrcode, char *result) {
}
*/
+99
View File
@@ -0,0 +1,99 @@
/**
* The MIT License (MIT)
*
* This library is written and maintained by Richard Moore.
* Major parts were derived from Project Nayuki's library.
*
* Copyright (c) 2017 Richard Moore (https://github.com/ricmoo/QRCode)
* Copyright (c) 2017 Project Nayuki (https://www.nayuki.io/page/qr-code-generator-library)
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
/**
* Special thanks to Nayuki (https://www.nayuki.io/) from which this library was
* heavily inspired and compared against.
*
* See: https://github.com/nayuki/QR-Code-generator/tree/master/cpp
*/
#ifndef __QRCODEGEN_H_
#define __QRCODEGEN_H_
#ifndef __cplusplus
typedef unsigned char bool;
static const bool false = 0;
static const bool true = 1;
#endif
#include <stdint.h>
// QR Code Format Encoding
#define MODE_NUMERIC 0
#define MODE_ALPHANUMERIC 1
#define MODE_BYTE 2
// Error Correction Code Levels
#define ECC_LOW 0
#define ECC_MEDIUM 1
#define ECC_QUARTILE 2
#define ECC_HIGH 3
// If set to non-zero, this library can ONLY produce QR codes at that version
// This saves a lot of dynamic memory, as the codeword tables are skipped
#ifndef LOCK_VERSION
#define LOCK_VERSION 0
#endif
typedef struct QRCode {
uint8_t version;
uint8_t size;
uint8_t ecc;
uint8_t mode;
uint8_t mask;
uint8_t *modules;
} QRCode;
#ifdef __cplusplus
extern "C"{
#endif /* __cplusplus */
uint16_t qrcode_getBufferSize(uint8_t version);
int8_t qrcode_initText(QRCode *qrcode, uint8_t *modules, uint8_t version, uint8_t ecc, const char *data);
int8_t qrcode_initBytes(QRCode *qrcode, uint8_t *modules, uint8_t version, uint8_t ecc, uint8_t *data, uint16_t length);
bool qrcode_getModule(QRCode *qrcode, uint8_t x, uint8_t y);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* __QRCODEGEN_H_ */
+5
View File
@@ -129,6 +129,11 @@ std::string to_string_decimal(float decimal, int8_t precision) {
return result;
}
std::string to_string_freq(const uint64_t f) {
auto final_str = to_string_dec_int(f / 1000000,4) + to_string_dec_int(f % 1000000, 6, '0');
return final_str;
}
std::string to_string_short_freq(const uint64_t f) {
auto final_str = to_string_dec_int(f / 1000000,4) + "." + to_string_dec_int((f / 100) % 10000, 4, '0');
return final_str;
+1
View File
@@ -48,6 +48,7 @@ std::string to_string_decimal(float decimal, int8_t precision);
std::string to_string_hex(const uint64_t n, const int32_t l = 0);
std::string to_string_hex_array(uint8_t * const array, const int32_t l = 0);
std::string to_string_freq(const uint64_t f);
std::string to_string_short_freq(const uint64_t f);
std::string to_string_time_ms(const uint32_t ms);
+1 -1
View File
@@ -109,7 +109,7 @@ void Manager::feed(const Frame& frame) {
switch(state) {
case State::NoTouch:
if( touch_stable && touch_pressure ) {
if( touch_stable && touch_pressure && !persistent_memory::disable_touchscreen()) {
if( point_stable() ) {
state = State::TouchDetected;
touch_started();
+3 -1
View File
@@ -253,14 +253,16 @@ void GeoMapView::focus() {
nav_.display_modal("No map", "No world_map.bin file in\n/ADSB/ directory", ABORT, nullptr);
}
void GeoMapView::update_position(float lat, float lon, uint16_t angle) {
void GeoMapView::update_position(float lat, float lon, uint16_t angle, int32_t altitude) {
lat_ = lat;
lon_ = lon;
altitude_ = altitude;
// Stupid hack to avoid an event loop
geopos.set_report_change(false);
geopos.set_lat(lat_);
geopos.set_lon(lon_);
geopos.set_altitude(altitude_);
geopos.set_report_change(true);
geomap.set_angle(angle);
+1 -1
View File
@@ -177,7 +177,7 @@ public:
void focus() override;
void update_position(float lat, float lon, uint16_t angle);
void update_position(float lat, float lon, uint16_t angle, int32_t altitude);
std::string title() const override { return "Map view"; };
+131
View File
@@ -0,0 +1,131 @@
/*
* Copyright (C) 2015 Jared Boone, ShareBrained Technology, Inc.
* Copyright (C) 2017 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_qrcode.hpp"
#include "qrcodegen.hpp"
#include "portapack.hpp"
#include "portapack_persistent_memory.hpp"
#include <cstring>
#include <stdio.h>
using namespace portapack;
#include "string_format.hpp"
#include "complex.hpp"
namespace ui {
QRCodeImage::QRCodeImage(
Rect parent_rect
) : Widget { parent_rect }
{
}
void QRCodeImage::paint(Painter& painter) {
// The structure to manage the QR code
QRCode qrcode;
//Either small or large QR code can be shown..
if(portapack::persistent_memory::show_bigger_qr_code()) { // show large QR code
int qr_version = 2;
// Allocate a chunk of memory to store the QR code
uint8_t qrcodeBytes[qrcode_getBufferSize(qr_version)];
qrcode_initText(&qrcode, qrcodeBytes, qr_version, ECC_HIGH, qr_text_);
display.fill_rectangle(Rect(10, 30, 220, 220), Color::white());
for (uint8_t y = 0; y < qrcode.size; y++) {
for (uint8_t x = 0; x < qrcode.size; x++) {
if (qrcode_getModule(&qrcode, x, y)) {
display.fill_rectangle(Rect(20+(x*8), 40+(y*8), 8, 8), Color::black());
}
}
}
}
else { // show small QR code
int qr_version = 10;
// Allocate a chunk of memory to store the QR code
uint8_t qrcodeBytes[qrcode_getBufferSize(qr_version)];
qrcode_initText(&qrcode, qrcodeBytes, qr_version, ECC_HIGH, qr_text_);
display.fill_rectangle(Rect(92, 97, 63, 63), Color::white());
for (uint8_t y = 0; y < qrcode.size; y++) {
for (uint8_t x = 0; x < qrcode.size; x++) {
if (qrcode_getModule(&qrcode, x, y)) {
display.draw_pixel(Point(95+x,100+y), Color::black());
}
}
}
}
}
void QRCodeView::focus() {
button_close.focus();
}
QRCodeView::~QRCodeView() {
if (on_close_)
on_close_();
}
QRCodeView::QRCodeView(
NavigationView& nav,
const char * qr_text,
const std::function<void(void)> on_close
) : nav_ (nav),
on_close_(on_close)
{
add_children({
&qr_code,
&button_close});
//text_qr.set(qr_text);
qr_code.set_text(qr_text);
button_close.on_select = [&nav](Button&){
nav.pop();
};
}
} /* namespace ui */
+90
View File
@@ -0,0 +1,90 @@
/*
* Copyright (C) 2015 Jared Boone, ShareBrained Technology, Inc.
* Copyright (C) 2017 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 __QRCODE_H__
#define __QRCODE_H__
#include "ui.hpp"
#include "ui_navigation.hpp"
#include "ui_font_fixed_8x16.hpp"
#include "qrcodegen.hpp"
#include "portapack.hpp"
namespace ui {
class QRCodeImage : public Widget {
public:
QRCodeImage(Rect parent_rect);
void set_text(const char * qr_text) {
qr_text_ = qr_text;
}
void paint(Painter& painter) override;
private:
const char * qr_text_ ;
};
class QRCodeView : public View {
public:
QRCodeView(
NavigationView& nav,
const char * qr_text,
const std::function<void(void)> on_close = nullptr
);
~QRCodeView();
QRCodeView(const QRCodeView&) = delete;
QRCodeView(QRCodeView&&) = delete;
QRCodeView& operator=(const QRCodeView&) = delete;
QRCodeView& operator=(QRCodeView&&) = delete;
std::string title() const override { return "QR code"; };
void focus() override;
private:
NavigationView& nav_;
std::function<void(void)> on_close_ { nullptr };
QRCodeImage qr_code {
{ 50, 100, 100, 100 }
};
//Text text_qr {
// { 0 * 8, 10 * 16, 32 * 8, 1 * 8 },
// "-"
//};
Button button_close {
{ 9 * 8, 31 * 8, 12 * 8, 3 * 16 },
"Back"
};
};
} /* namespace ui */
#endif
+3 -3
View File
@@ -190,7 +190,7 @@ namespace ui
void on_speaker();
void on_stealth();
void on_bias_tee();
//void on_textentry();
// void on_textentry();
void on_camera();
void on_title();
void refresh();
@@ -212,7 +212,7 @@ namespace ui
void refresh();
private:
static constexpr auto version_string = "v1.4.2";
// static constexpr auto version_string = "v1.4.4"; // This is commented out as we are now setting the version via ENV (VERSION_STRING=v1.0.0)
NavigationView &nav_;
Rectangle backdrop{
@@ -221,7 +221,7 @@ namespace ui
Text version{
{2, 0, 11 * 8, 16},
version_string};
VERSION_STRING};
LiveDateTime ltime{
{86, 0, 19 * 8, 16}};
+36 -1
View File
@@ -98,6 +98,19 @@ void RecordView::focus() {
}
void RecordView::set_sampling_rate(const size_t new_sampling_rate) {
/* We are changing "REC" icon background to yellow in BW rec Options >600kHz
where we are NOT recording full IQ .C16 files (recorded files are decimated ones).
Those decimated recorded files,has not the full IQ samples .
are ok as recorded spectrum indication, but they should not be used by Replay app.
We keep original black background in all the correct IQ .C16 files BW's Options */
if (new_sampling_rate > 4800000) { // > BW >600kHz (fs=8*BW), (750kHz ...2750kHz)
button_record.set_background(ui::Color::yellow());
} else {
button_record.set_background(ui::Color::black());
}
if( new_sampling_rate != sampling_rate ) {
stop();
@@ -114,6 +127,11 @@ void RecordView::set_sampling_rate(const size_t new_sampling_rate) {
}
}
// Setter for datetime and frequency filename
void RecordView::set_filename_date_frequency(bool set) {
filename_date_frequency = set;
}
bool RecordView::is_active() const {
return (bool)capture_thread;
}
@@ -136,7 +154,24 @@ void RecordView::start() {
return;
}
auto base_path = next_filename_stem_matching_pattern(filename_stem_pattern);
std::filesystem::path base_path;
if(filename_date_frequency) {
rtcGetTime(&RTCD1, &datetime);
//ISO 8601
std::string date_time = to_string_dec_uint(datetime.year(), 4, '0') +
to_string_dec_uint(datetime.month(), 2, '0') +
to_string_dec_uint(datetime.day(), 2, '0') + "T" +
to_string_dec_uint(datetime.hour()) +
to_string_dec_uint(datetime.minute()) +
to_string_dec_uint(datetime.second());
base_path = filename_stem_pattern.string() + "_" + date_time + "_" + to_string_freq(receiver_model.tuning_frequency()) + "Hz";
} else {
base_path = next_filename_stem_matching_pattern(filename_stem_pattern);
}
if( base_path.empty() ) {
return;
}
+7
View File
@@ -63,6 +63,8 @@ public:
bool is_active() const;
void set_filename_date_frequency(bool set);
private:
void toggle();
//void toggle_pitch_rssi();
@@ -75,6 +77,11 @@ private:
void handle_error(const File::Error error);
//bool pitch_rssi_enabled = false;
// Time Stamp
bool filename_date_frequency = false;
rtc::RTC datetime { };
const std::filesystem::path filename_stem_pattern;
const FileType file_type;
const size_t write_size;
+4 -4
View File
@@ -62,8 +62,8 @@ void SSB::execute(const buffer_s16_t& audio, const buffer_c8_t& buffer) {
//default: break;
//}
i *= 64.0f;
q *= 64.0f;
i *= 256.0f; // Original 64.0f, now x 4 (+12 dB's SSB BB modulation)
q *= 256.0f; // Original 64.0f, now x 4 (+12 dB's SSB BB modulation)
switch (mode) {
case Mode::LSB: re = q; im = i; break;
case Mode::USB: re = i; im = q; break;
@@ -123,9 +123,9 @@ void AM::execute(const buffer_s16_t& audio, const buffer_c8_t& buffer) {
}
q = sample / 32768.0f;
q *= 64.0f;
q *= 256.0f; // Original 64.0f,now x4 (+12 dB's BB_modulation in AM & DSB)
switch (mode) {
case Mode::AM: re = q + 20; im = q + 20; break;
case Mode::AM: re = q + 80; im = q + 80; break; // Original DC add +20_DC_level=carrier,now x4 (+12dB's AM carrier)
case Mode::DSB: re = q; im = q; break;
default: break;
}
+327 -66
View File
@@ -115,6 +115,10 @@ void AK4951::init() {
// update(Register::DigitalFilterMode);
}
bool AK4951::detected() {
return reset();
}
bool AK4951::reset() {
io.audio_reset_state(true);
@@ -212,90 +216,347 @@ void AK4951::speaker_disable() {
set_speaker_power(false);
}
void AK4951::microphone_enable() {
// map.r.digital_mic.DMIC = 0;
// update(Register::DigitalMic);
void AK4951::microphone_enable(int8_t alc_mode) {
// alc_mode =0 = (OFF =same as original code = NOT using AK4951 Programmable digital filter block),
// alc_mode >1 (with DIGITAL FILTER BLOCK , example : 1:(+12dB) , 2:(+9dB)", 3:(+6dB), ...)
// map.r.digital_mic.DMIC = 0; // originally commented code
// update(Register::DigitalMic); // originally commented code
uint_fast8_t mgain =0b0111; // Pre-amp mic (Original code, =0b0111 (+21dB's=7x3dBs),(Max is NOT 0b1111!, it is 0b1010=+30dBs=10x3dBs)
map.r.signal_select_2.INL = 0b01; // Lch input signal = LIN2 , our ext. MONO MIC is connected here LIN2 in Portapack.
map.r.signal_select_2.INR = 0b01; // Rch input signal = RIN2 , Not used ,not connected ,but no problem.
map.r.signal_select_2.MICL = 0; // MPWR = 2.4V (it has two possible settings , 2.4V or 2.0V) , (majority smarthphones around 2V , range 1V-5V)
update(Register::SignalSelect2);
// ------Common code part, = original setting conditions, it is fine for all user-GUI alc_modes: OFF , and ALC modes .*/
map.r.digital_filter_select_1.HPFAD = 1; // HPF1 ON (after ADC);page 40 datasheet, HPFAD bit controls the ON/OFF of the HPF1 (HPF ON is recommended).
map.r.digital_filter_select_1.HPFC = 0b11; // HPF Cut off frequency of high pass filter from 236.8 Hz @fs=48k ("00":3.7Hz, "01":14,8Hz, "10":118,4Hz)
update(Register::DigitalFilterSelect1);
// map.r.r_ch_mic_gain_setting.MGR = 0x80; // Microphone sensitivity correction = 0dB., (not used by now , original code cond.)
// update(Register::RchMicGainSetting); // (those two lines , not activated, same as original)
// pre-load 4 byes LPF coefficicients (.lpf_coefficient_0,1,2,3), FSA 14..0, FSB 14..0 , (fcut initial 6kHz, fs 48Khz).
// it will be default pre-loading coeff. for al ALC modes, LPF bit is activated down, for all ALC digital modes.
map.r.lpf_coefficient_0.l = 0x5F; // Pre-loading here LPF 6kHz, 1st Order from digital Block , Fc=6000 Hz, fs = 48khz
map.r.lpf_coefficient_1.h = 0x09; // LPF bit is activated down, for all ALC digital modes.
map.r.lpf_coefficient_2.l = 0xBF; // Writting reg to AK4951, with "update", following instructions.
map.r.lpf_coefficient_3.h = 0x32;
update(Register::LPFCoefficient0); // Writing pre-loaded 4 bytes LPF CoefFiecients 14 bits (FSA13..0, FSB13..0
update(Register::LPFCoefficient1); // In this case , LPF 6KHz , when we activate the LPF block.
update(Register::LPFCoefficient2);
update(Register::LPFCoefficient3);
// Reset , setting OFF all 5 x Digital Equalizer filters
map.r.digital_filter_select_3.EQ1 = 0; // EQ1 Coeffic Setting , (0: Disable-default, audio data passes EQ1 block by 0dB gain). When EQ1="1”, the settings of E1A15-0, E1B15-0 and E1C15-0 bits are enabled
map.r.digital_filter_select_3.EQ2 = 0; // EQ2 Coeffic Setting , (0: Disable-default, audio data passes EQ2 block by 0dB gain). When EQ2="1”, the settings of E2A15-0, E2B15-0 and E2C15-0 bits are enabled
map.r.digital_filter_select_3.EQ3 = 0; // EQ3 Coeffic Setting , (0: Disable-default, audio data passes EQ3 block by 0dB gain). When EQ3="1”, the settings of E3A15-0, E3B15-0 and E3C15-0 bits are enabled
map.r.digital_filter_select_3.EQ4 = 0; // EQ4 Coeffic Setting , (0: Disable-default, audio data passes EQ4 block by 0dB gain). When EQ4="1”, the settings of E4A15-0, E4B15-0 and E4C15-0 bits are enabled
map.r.digital_filter_select_3.EQ5 = 0; // EQ5 Coeffic Setting , (0: Disable-default, audio data passes EQ5 block by 0dB gain). When EQ5="1”, the settings of E5A15-0, E5B15-0 and E5C15-0 bits are enabled
update(Register::DigitalFilterSelect3); // A,B,C EQ1 Coefficients are already pre-loaded in ak4951.hpp
if (alc_mode==0) { // Programmable Digital Filter OFF, same as original condition., no Digital ALC, nor Wind Noise Filter, LPF , EQ
map.r.digital_filter_select_2.LPF = 0; // LPF-Block, Coeffic Setting Enable (OFF-Default), When LPF bit is “0”, audio data passes the LPF block by 0dB gain.
update(Register::DigitalFilterSelect2);
// Pre-loading AUDIO PATH with all DIGITAL BLOCK by pased, see, audio path block diagramm AK4951 datasheet + Table Playback mode -Recording mode.
// Digital filter block PATH is BY PASSED (we can swith off DIG. BLOCK power , PMPFIL=0) .The Path in Recording Mode 2 & Playback Mode 2 (NO DIG FILTER BLOCK AT ALL, not for MIC recording, nor for Playback)
map.r.digital_filter_mode.ADCPF = 1; // ADCPF bit swith ("0" Mic after ADC Output connected (recording mode) to the DIGITAL FILTER BLOCK. ("1" Playback mode)
map.r.digital_filter_mode.PFSDO = 0; // ADC bit switch ("0" : 1st order HPF) connectedto the Output. By bass DIGITAL block .
map.r.digital_filter_mode.PFDAC = 0b00; // (Input selector for DAC (not used in MIC), SDTI= Audio Serial Data Input Pin)
update(Register::DigitalFilterMode); // Writing the Audio Path : NO DIGITAL BLOCK or DIG BLOCK FOR MIC , Audio mode path : Playback mode /-Recording mode.
map.r.power_management_1.PMADL = 1; // ADC Lch = Lch input signal. Mic Amp Lch and ADC Lch Power Management
map.r.power_management_1.PMADR = 1; // ADC Rch = Rch input signal. Mic Amp Rch and ADC Rch Power Management
map.r.power_management_1.PMPFIL = 0; // Pre-loading , Programmable Dig. filter OFF ,filter unused, routed around.(original value = 0 )
update(Register::PowerManagement1); // Activating the Power management of the used blocks . (Mic ADC always + Dig Block filter , when used )
// 1059/fs, 22ms @ 48kHz
chThdSleepMilliseconds(22);
} else { // ( alc_mode !=0)
switch(alc_mode) { // Pre-loading register values depending on user-GUI selection (they will be sended below, with "update(Register_name::xxx )".
case 1: // ALC-> on, (+12dB's) Auto Vol max + Wind Noise cancel + LPF 6kHz + Pre-amp Mic (+21dB=original)
map.r.alc_mode_control_2.REF = 0xC0; // REF7-0 bits,max gain at ALC recovery operation,(FFH +36dBs , D0H +18dBs, A0H 0dBs, C0H=+12dBs)
map.r.l_ch_input_volume_control.IV = 0xC0; // Left, Input Digital Volume Setting, (FFH +36dBs , D0H +18dBs, A0H 0dBs, 70H=-18dBs)
map.r.r_ch_input_volume_control.IV = 0xC0; // Right Input Dig Vol Setting, same comment as above , The value of IVOL should be <= than REFs
// Already Pre-loaded, "map.r.lpf_coefficient", 6Khz - LPF 1st Order from digital Block,Fc=6000Hz,fs = 48khz
// LPF bit is activated down, for all ALC digital modes.
break;
case 2: // ALC-> on, (+09dB's) Auto Vol max + Wind Noise cancel + LPF 6kHz + Pre-amp Mic (+21dB=original)
map.r.alc_mode_control_2.REF = 0xB8; // REF7-0 bits,max gain at ALC recoveryoperation,(FFH +36dBs , D0H +18dBs, A0H 0dBs, B8H= +9dBs)
map.r.l_ch_input_volume_control.IV = 0xB8; // Left, Input Digital Volume Setting, (FFH +36dBs , D0H +18dBs, A0H 0dBs, 70H=-18dBs)
map.r.r_ch_input_volume_control.IV = 0xB8; // Right Input Dig Vol Setting, same comment as above , The value of IVOL should be <= than REFs
// Already Pre-loaded, "map.r.lpf_coefficient", 6Khz - LPF 1st Order from digital Block,Fc=6000Hz,fs = 48khz
// LPF bit is activated down, for all ALC digital modes.
break;
case 3: // ALC-> on, (+06dB's) Auto Vol max + Wind Noise cancel + LPF 6kHz + Pre-amp Mic (+21dB=original)
map.r.alc_mode_control_2.REF = 0xB0; // 0xB8 , REF7-0 bits,max gain at ALC recoveryoperation,(FFH +36dBs , D0H +18dBs, A0H 0dBs, B0H= +6dBs)
map.r.l_ch_input_volume_control.IV = 0xB0; // Left, Input Digital Volume Setting, (FFH +36dBs , D0H +18dBs, A0H 0dBs, 70H=-18dBs)
map.r.r_ch_input_volume_control.IV = 0xB0; // Right Input Dig Vol Setting, same comment as above , Then value of IVOL should be <= than REFs
// Already Pre-loaded, "map.r.lpf_coefficient", 6Khz - LPF 1st Order from digital Block,Fc=6000Hz,fs = 48khz
// LPF bit is activated down, for all ALC digital modes.
break;
case 4: // ALC-> on, (+03dB's) Auto Vol max + Wind Noise cancel + Pre-amp Mic (+21dB=original)
// + EQ boosting ~<2kHz (f0:1,1k, fb:1,7K, k=1,8) && + LPF 3,5k
map.r.alc_mode_control_2.REF = 0xA8; // 0xA8 , REF7-0 bits,max gain at ALC recoveryoperation,(FFH +36dBs , D0H +18dBs, A0H 0dBs, A8H= +3dBs)
map.r.l_ch_input_volume_control.IV = 0xA8; // Left, Input Digital Volume Setting, (FFH +36dBs , D0H +18dBs, A0H 0dBs, 70H=-18dBs)
map.r.r_ch_input_volume_control.IV = 0xA8; // Right Input Dig Vol Setting, same comment as above , Then value of IVOL should be <= than REFs
//The EQn (n=1, 2, 3, 4 or 5) coefficient must be set when EQn bit = “0” or PMPFIL bit = “0”.
map.r.digital_filter_select_3.EQ1 = 1; // EQ1 Coeffic Setting , (0: Disable-default, audio data passes EQ1 block by 0dB gain). When EQ1="1”, the settings of E1A15-0, E1B15-0 and E1C15-0 bits are enabled
update(Register::DigitalFilterSelect3); // A,B,C EQ1 Coefficients are already pre-loaded in ak4951.hpp
map.r.lpf_coefficient_0.l = 0x0D; // Pre-loading here LPF 3,5k , 1st Order from digital Block , Fc=3.500 Hz, fs = 48khz
map.r.lpf_coefficient_1.h = 0x06; // LPF bit is activated down, for all ALC digital modes.
map.r.lpf_coefficient_2.l = 0x1A; // Writting reg to AK4951 , down with update....
map.r.lpf_coefficient_3.h = 0x2C;
// LPF bit is activated down, for all ALC digital modes.
break;
case 5: // ALC-> on, (+03dB's) Auto Vol max + Wind Noise cancel + Pre-amp Mic (+21dB=original)
// + EQ boosting ~<3kHz (f0~1k4,fb~2,4k,k=1,8) && LPF 4kHz
map.r.alc_mode_control_2.REF = 0xA8; // 0xA0 , REF7-0 bits,max gain at ALC recoveryoperation,(FFH +36dBs , D0H +18dBs, A0H 0dBs, A8H= +3dBs)
map.r.l_ch_input_volume_control.IV = 0xA8; // Left, Input Digital Volume Setting, (FFH +36dBs , D0H +18dBs, A0H 0dBs, 70H=-18dBs)
map.r.r_ch_input_volume_control.IV = 0xA8; // Right Input Dig Vol Setting, same comment as above , Then value of IVOL should be <= than REFs
map.r.digital_filter_select_3.EQ2 = 1; // EQ2 Coeffic Setting , (0: Disable-default, audio data passes EQ2 block by 0dB gain). When EQ2="1”, the settings of E2A15-0, E2B15-0 and E2C15-0 bits are enabled
update(Register::DigitalFilterSelect3);
map.r.lpf_coefficient_0.l = 0xC3; // Pre-loading here LPF 4k , 1st Order from digital Block , Fc=4000 Hz, fs = 48khz
map.r.lpf_coefficient_1.h = 0x06; // LPF bit is activated down, for all ALC digital modes.
map.r.lpf_coefficient_2.l = 0x86; // Writting reg to AK4951 , down with update....
map.r.lpf_coefficient_3.h = 0x2D;
// LPF bit is activated down, for all ALC digital modes.
break;
case 6: // ALC-> on, (+03dB's) Auto Vol max + Wind Noise cancel + LPF 6kHz + Pre-amp Mic (+21dB=original)
map.r.alc_mode_control_2.REF = 0xA8; // REF7-0 bits,max gain at ALC recoveryoperation,(FFH +36dBs , D0H +18dBs, A0H 0dBs, A0H= 0dBs)
map.r.l_ch_input_volume_control.IV = 0xA8; // Left, Input Digital Volume Setting, (FFH +36dBs , D0H +18dBs, A0H 0dBs, 70H=-18dBs)
map.r.r_ch_input_volume_control.IV = 0xA8; // Right Input Dig Vol Setting, same comment as above , Then value of IVOL should be <= than REFs
// Already Pre-loaded, "map.r.lpf_coefficient", 6Khz - LPF 1st Order from digital Block,Fc=6000Hz,fs = 48khz
// LPF bit is activated down, for all ALC digital modes.
break;
case 7: // ALC-> on, (+00dB's) Auto Vol max + Wind Noise cancel + LPF 6kHz + Pre-amp Mic (+21dB=original)
map.r.alc_mode_control_2.REF = 0xA0; // REF7-0 bits,max gain at ALC recoveryoperation,(FFH +36dBs , D0H +18dBs, A0H 0dBs, A0H= 0dBs)
map.r.l_ch_input_volume_control.IV = 0xA0; // Left, Input Digital Volume Setting, (FFH +36dBs , D0H +18dBs, A0H 0dBs, 70H=-18dBs)
map.r.r_ch_input_volume_control.IV = 0xA0; // Right Input Dig Vol Setting, same comment as above , Then value of IVOL should be <= than REFs
// Already Pre-loaded, "map.r.lpf_coefficient", 6Khz - LPF 1st Order from digital Block,Fc=6000Hz,fs = 48khz
// LPF bit is activated down, for all ALC digital modes.
break;
case 8: // ALC-> on, (-03dB's) Auto Vol max + Wind Noise cancel + LPF 6kHz + Pre-amp Mic (+21dB=original)
map.r.alc_mode_control_2.REF = 0x98; //REF7-0 bits,max gain at ALC recovery operation,(FFH +36dBs , D0H +18dBs, A0H 0dBs, 98H=-03dBs)
map.r.l_ch_input_volume_control.IV = 0x98; // Left, Input Digital Volume Setting, (FFH +36dBs , D0H +18dBs, A0H 0dBs, 70H=-18dBs)
map.r.r_ch_input_volume_control.IV = 0x98; // Right Input Dig Vol Setting, same comment as above , Then value of IVOL should be <= than REFs
const uint_fast8_t mgain = 0b0111;
map.r.signal_select_1.MGAIN20 = mgain & 7;
map.r.signal_select_1.PMMP = 1;
map.r.signal_select_1.MPSEL = 1; // MPWR2 pin
map.r.signal_select_1.MGAIN3 = (mgain >> 3) & 1;
update(Register::SignalSelect1);
// Already Pre-loaded, "map.r.lpf_coefficient", 6Khz - LPF 1st Order from digital Block,Fc=6000Hz,fs = 48khz
// LPF bit is activated down, for all ALC digital modes.
break;
map.r.signal_select_2.INL = 0b01; // Lch input signal = LIN2
map.r.signal_select_2.INR = 0b01; // Rch input signal = RIN2
map.r.signal_select_2.MICL = 0; // MPWR = 2.4V
update(Register::SignalSelect2);
case 9: // ALC-> on, (-06dB's) Auto Vol max + Wind Noise cancel + LPF 6kHz + Pre-amp Mic (+21dB=original)
map.r.alc_mode_control_2.REF = 0x90; // REF7-0 bits,max gain at ALC recovery operation,(FFH +36dBs , D0H +18dBs, A0H 0dBs, 90H=-06dBs)
map.r.l_ch_input_volume_control.IV = 0x90; // Left, Input Digital Volume Setting, (FFH +36dBs , D0H +18dBs, A0H 0dBs, 70H=-18dBs)
map.r.r_ch_input_volume_control.IV = 0x90; // Right Input Dig Vol Setting, same comment as above , Then value of IVOL should be <= than REFs
// map.r.r_ch_mic_gain_setting.MGR = 0x80; // Microphone sensitivity correction = 0dB.
// update(Register::RchMicGainSetting);
/*
map.r.timer_select.FRN = ?;
map.r.timer_select.FRATT = ?;
map.r.timer_select.ADRST = 0b??;
update(Register::TimerSelect);
// Already Pre-loaded, "map.r.lpf_coefficient", 6Khz - LPF 1st Order from digital Block,Fc=6000Hz,fs = 48khz
// LPF bit is activated down, for all ALC digital modes.
break;
map.r.alc_timer_select. = ?;
update(Register::ALCTimerSelect);
map.r.alc_mode_control_1. = ?;
map.r.alc_mode_control_1.ALC = 1;
case 10: // ALC-> on, (-09dB's) Auto Vol max + Wind Noise cancel + LPF 6kHz - Pre-amp MIC -3dB (18dB's)
// Reduce also Pre-amp Mic -3dB's (+18dB's)
mgain = 0b0110; // Pre-amp mic Mic Gain Pre-amp (+18dB), Original=0b0111 (+21dB's =7x3dBs),
map.r.alc_mode_control_2.REF = 0x88; // REF7-0 bits,max gain at ALC recovery operation,(FFH +36dBs , D0H +18dBs, A0H 0dBs, 88H=-09dBs)
map.r.l_ch_input_volume_control.IV = 0x88; // Left, Input Digital Volume Setting, (FFH +36dBs , D0H +18dBs, A0H 0dBs, 70H=-18dBs)
map.r.r_ch_input_volume_control.IV = 0x88; // Right Input Dig Vol Setting, same comment as above , Then value of IVOL should be <= than REFs
// Already Pre-loaded, "map.r.lpf_coefficient", 6Khz - LPF 1st Order from digital Block,Fc=6000Hz,fs = 48khz
// LPF bit is activated down, for all ALC digital modes.
break;
case 11: // ALC-> on, (-12dB's) Auto Vol max + Wind Noise cancel + LPF 6kHz - Pre-amp MIC -6dB (15dB's)
// Reduce also Pre-amp Mic -6dB's (+15dB's)
mgain = 0b0101; // Pre-amp mic Mic Gain Pre-amp (+15dB), (Original=0b0111 (+21dB's= 7x3dBs),
map.r.alc_mode_control_2.REF = 0x80; // REF7-0 bits,max gain at ALC recovery operation,(FFH +36dBs , D0H +18dBs, A0H 0dBs, 80H=-12dBs)
map.r.l_ch_input_volume_control.IV = 0x80; // Left, Input Digital Volume Setting, (FFH +36dBs , D0H +18dBs, A0H 0dBs, 70H=-18dBs)
map.r.r_ch_input_volume_control.IV = 0x80; // Right Input Dig Vol Setting, same comment as above , Then value of IVOL should be <= than REFs
// Already Pre-loaded, "map.r.lpf_coefficient", 6Khz - LPF 1st Order from digital Block,Fc=6000Hz,fs = 48khz
// LPF bit is activated down, for all ALC digital modes.
break;
}
//-------------------------------DIGITAL ALC (Automatic Level Control ) --- --------
map.r.alc_mode_control_1.ALC = 0; // LMTH2-0, WTM1-0, RGAIN2-0, REF7-0, RFST1-0, EQFC1-0, FRATT, FRN and ALCEQN bits (needs to be set up with ALC disable = 0)
update(Register::ALCModeControl1);
map.r.alc_mode_control_2.REF = ?;
map.r.timer_select.FRN = 0; // (FRN= 0 Fast Recovery mode , enable )
map.r.timer_select.FRATT = 0; // Fast Recovery Ref. Volume Atten. Amount -0,00106dB's, timing 4/fs (default)
map.r.timer_select.ADRST = 0b00; // initial offset ADC cycles , 22ms @fs=48Khz.
update(Register::TimerSelect);
map.r.alc_timer_select.RFST = 0b00; // RFST1-0: ALC Fast Recovery Speed Default: “00” (0.0032dB)
map.r.alc_timer_select.WTM = 0b00; // ALC Recovery Operation Waiting Period 128/fs = 2,7 mseg (min=default)
map.r.alc_timer_select.EQFC = 0b10; // Selecting default, fs 48Khz , ALCEQ: First order zero pole high pass filter fc2=100Hz, fc1=150Hz
map.r.alc_timer_select.IVTM = 0; // IVTM bit set the vol transition time ,236/fs = 4,9msecs (min) (default was 19,7msegs.)
update(Register::ALCTimerSelect);
map.r.alc_mode_control_1.LMTH10 = 0b11; // ALC Limiter Detec Level/ Recovery Counter Reset; lower 2 bits (Ob111=-8,4dbs), (default 0b000=-2,5dBs)
map.r.alc_mode_control_1.RGAIN = 0b000; // ALC Recovery Gain Step, max step , max speed. Default: “000” (0.00424dB)
map.r.alc_mode_control_1.ALC = 1; // ALC Enable . (we are now, NOT in MANUAL volume mode, only becomes manual when (ALC=“0” while ADCPF=“1”. )
map.r.alc_mode_control_1.LMTH2 = 1; // ALC Limiter Detection Level/ Recovery Counter Reset Level,Upper bit,default 0b000
map.r.alc_mode_control_1.ALCEQN = 1; // ALC EQ Off =1 not used by now, 0: ALC EQ On (default)
update(Register::ALCModeControl1);
// map.r.alc_mode_control_2.REF = 0x??; // Pre-loaded in top part. Maximum gain at ALC recovery operation,.(FFH +36dBs , D0H +18dBs, A0H 0dBs, 70H=-18dBs)
update(Register::ALCModeControl2);
*/
// map.r.l_ch_input_volume_control.IV = 0xe1;
// update(Register::LchInputVolumeControl);
// map.r.r_ch_input_volume_control.IV = 0xe1;
// update(Register::RchInputVolumeControl);
/*
map.r.auto_hpf_control.STG = 0b00;
map.r.auto_hpf_control.SENC = 0b011;
map.r.auto_hpf_control.AHPF = 0;
update(Register::AutoHPFControl);
*/
map.r.digital_filter_select_1.HPFAD = 1; // HPF1 (after ADC) = on
map.r.digital_filter_select_1.HPFC = 0b11; // 2336.8 Hz @ fs=48k
update(Register::DigitalFilterSelect1);
/*
map.r.digital_filter_select_2.HPF = 0;
map.r.digital_filter_select_2.LPF = 0;
map.r.digital_filter_select_2.FIL3 = 0;
map.r.digital_filter_select_2.EQ0 = 0;
map.r.digital_filter_select_2.GN = 0b00;
// map.r.l_ch_input_volume_control.IV = 0x??; // Pre-loaded in top part. Left, Input Digital Volume Setting, (FFH +36dBs , D0H +18dBs, A0H 0dBs, 70H=-18dBs)
update(Register::LchInputVolumeControl);
// map.r.r_ch_input_volume_control.IV = 0x??; // Pre-loaded in top part. Right,Input Digital Volume Setting, (FFH +36dBs , D0H +18dBs, A0H 0dBs, 70H=-18dBs)
update(Register::RchInputVolumeControl);
//---------------Switch ON, Digital Automatic Wind Noise Filter reduction -------------------
// Difficult to realise that Dynamic HPF Wind noise filter benefit, maybe because we have another fixed HPF 236.8 Hz .
// Anyway , we propose to activate it , with default setting conditions.
map.r.power_management_1.PMPFIL = 0; // (*1) To programm SENC, STG , we need PMPFIL = 0 . (but this disconnect Digital block power supply.
update(Register::PowerManagement1); // Updated PMPFIL to 0 . (*1)
map.r.auto_hpf_control.STG = 0b00; // (00=LOW ATTENUATION Level), lets put 11 (HIGH ATTENUATION Level) (default 00)
map.r.auto_hpf_control.SENC = 0b011; // (000=LOW sensitivity detection)… 111((MAX sensitivity detection) (default 011)
map.r.auto_hpf_control.AHPF = 1; // Autom. Wind noise filter ON (AHPF bit=“1”).It atten. wind noise when detecting ,and adjusts the atten. level dynamically.
update(Register::AutoHPFControl);
// We are in Digital Block ON , (Wind Noise Filter+ALC+LPF+EQ),==> needs at the end , PMPFIL=1 , Program. Dig.filter ON
// map.r.power_management_1.PMPFIL = 1; // that instruction is at the end , we can skp pre-loading Programmable Dig. filter ON (*1)
//---------------------------------------------------------------------
// Writing AUDIO PATH diagramm, Changing Audio mode path : Playback mode1 /-Recording mode2. (Figure 37 AK4951 datasheet, Table 27. Recording Playback Mode)
// When changing those modes, PMPFIL bit must be “0”, it is OK (*1)
map.r.digital_filter_mode.ADCPF = 1; // ADCPF bit swith ("0" Mic after ADC Output connected (recording mode) to the DIGITAL FILTER BLOCK. ("1" Playback mode)
map.r.digital_filter_mode.PFSDO = 1; // ADC (+ 1st order HPF) Output
map.r.digital_filter_mode.PFDAC = 0b00; // (Input selector for DAC (not used in MIC), SDTI= Audio Serial Data Input Pin)
update(Register::DigitalFilterMode); // Writing the Audio Path : NO DIGITAL BLOCK or DIG BLOCK FOR MIC , Audio mode path : Playback mode /-Recording mode.
// The EQn (n=1, 2, 3, 4 or 5) coefficient must be set when EQn bit = “0” or PMPFIL bit = “0”., but we are already (*1)
// map.r.power_management_1.PMPFIL = 0; // In the previous Wind Noise Filter , we already set up PPFIL = 0
// update(Register::PowerManagement1); // Activating the Power management of the used blocks . (Mic ADC always + Dig Block filter , when used )
// ... Set EQ & LPF coefficients ---------------------------------
// writting to the IC ak4951 reg. settings defined in Ak4951.hpp , the 30 bytes , EQ coefficient = 5 (EQ1,2,3,4,5) x 3 (A,B,C coefficients) x 2 bytes (16 bits)
update(Register::E1Coefficient0); // we could pre-load here,ex ,"map.r.e1_coefficient_0.l = 0x50;" , EQ1 Coefficient A : A7...A0, but already done in ak4951.hpp
update(Register::E1Coefficient1); // we could pre-load here,ex ,"map.r.e1_coefficient_1.h = 0xFE;" , EQ1 Coefficient A : A15..A8, " "
update(Register::E1Coefficient2); // we could pre-load here,ex ,"map.r.e1_coefficient_2.l = 0x29;" , EQ1 Coefficient B : B7...B0, " "
update(Register::E1Coefficient3); // we could pre-load here,ex ,"map.r.e1_coefficient_3.h = 0xC5;" , EQ1 Coefficient B : B15..B8, " "
update(Register::E1Coefficient4); // we could pre-load here,ex ,"map.r.e1_coefficient_4.l = 0xA0;" , EQ1 Coefficient C : C7...C0, " "
update(Register::E1Coefficient5); // we could pre-load here,ex ,"map.r.e1_coefficient_5.h = 0x1C;" , EQ1 Coefficient C : C15..C8, " "
update(Register::E2Coefficient0); // writing pre-loaded EQ2 coefficcients
update(Register::E2Coefficient1);
update(Register::E2Coefficient2);
update(Register::E2Coefficient3);
update(Register::E2Coefficient4);
update(Register::E2Coefficient5);
// Already pre-loaded LPF coefficients to 6k, 3,5k or 4k ,(LPF 6Khz all digital alc modes top , except when 3k5 , 4k)
update(Register::LPFCoefficient0); // Writing pre-loaded 4 bytes LPF CoefFiecients 14 bits (FSA13..0, FSB13..0
update(Register::LPFCoefficient1);
update(Register::LPFCoefficient2);
update(Register::LPFCoefficient3);
// Activating LPF block , (and re-configuring the rest of bits of the same register)
map.r.digital_filter_select_2.HPF = 0; // HPF2-Block, Coeffic Setting Enable (OFF-Default), When HPF bit is “0”, audio data passes the HPF2 block by is 0dB gain.
map.r.digital_filter_select_2.LPF = 1; // LPF-Block, Coeffic Setting Enable (OFF-Default), When LPF bit is “0”, audio data passes the LPF block by 0dB gain.
map.r.digital_filter_select_2.FIL3 = 0; // Stereo_Emphasis_Filter-Block,(OFF-Default) Coefficient Setting Enable , OFF , Disable.
map.r.digital_filter_select_2.EQ0 = 0; // Gain Compensation-Block, (OFF-Default) Coeffic Setting Enable, When EQ0 bit = “0” audio data passes the EQ0 block by 0dB gain.
map.r.digital_filter_select_2.GN = 0b00; // Gain Setting of the Gain Compensation Block Default: “00”-Default (0dB)
update(Register::DigitalFilterSelect2);
map.r.digital_filter_select_3.EQ1 = 0;
map.r.digital_filter_select_3.EQ2 = 0;
map.r.digital_filter_select_3.EQ3 = 0;
map.r.digital_filter_select_3.EQ4 = 0;
map.r.digital_filter_select_3.EQ5 = 0;
update(Register::DigitalFilterSelect3);
*/
map.r.digital_filter_mode.PFSDO = 0; // ADC (+ 1st order HPF) Output
map.r.digital_filter_mode.ADCPF = 1; // ADC Output (default)
update(Register::DigitalFilterMode);
// ... Set coefficients ...
map.r.power_management_1.PMADL = 1; // ADC Lch = Lch input signal
map.r.power_management_1.PMADR = 1; // ADC Rch = Rch input signal
map.r.power_management_1.PMPFIL = 0; // Programmable filter unused, routed around.
update(Register::PowerManagement1);
// Acitivating digital block , power supply
map.r.power_management_1.PMADL = 1; // ADC Lch = Lch input signal. Mic Amp Lch and ADC Lch Power Management
map.r.power_management_1.PMADR = 1; // ADC Rch = Rch input signal. Mic Amp Rch and ADC Rch Power Management
map.r.power_management_1.PMPFIL = 1; // Pre-loaded in top part. Orig value=0, Programmable Digital filter unused (not power up), routed around.
update(Register::PowerManagement1); // Activating the Power management of the used blocks . (Mic ADC always + Dig Block filter , when used )
// 1059/fs, 22ms @ 48kHz
chThdSleepMilliseconds(22);
}
// Common part for all alc_mode , --------------------------
// const uint_fast8_t mgain = 0b0111; // Already pre-loaded , in above switch case .
map.r.signal_select_1.MGAIN20 = mgain & 7; // writing 3 lower bits of mgain , (pre-amp mic gain).
map.r.signal_select_1.PMMP = 1; // Activating DC Mic Power supply through 2kohms res., similar majority smartphones headphone+mic jack, "plug-in-power"
map.r.signal_select_1.MPSEL = 1; // MPWR2 pin ,selecting output voltage to MPWR2 pin, that we are using in portapack ext. MIC)
map.r.signal_select_1.MGAIN3 = (mgain >> 3) & 1; // writing 4th upper bit of mgain (pre-amp mic gain).
update(Register::SignalSelect1);
}
void AK4951::microphone_disable() {
map.r.power_management_1.PMADL = 0;
map.r.power_management_1.PMADR = 0;
map.r.power_management_1.PMPFIL = 0;
map.r.power_management_1.PMADL = 0; // original code , disable Power managem.Mic ADC L
map.r.power_management_1.PMADR = 0; // original code , disable Power managem.Mic ADC R
map.r.power_management_1.PMPFIL = 0; // original code , disable Power managem. all Programmable Dig. block
update(Register::PowerManagement1);
map.r.alc_mode_control_1.ALC = 0;
map.r.alc_mode_control_1.ALC = 0; // original code , Restore , disable ALC block.
update(Register::ALCModeControl1);
map.r.auto_hpf_control.AHPF = 0; //----------- new code addition , Restore disable Wind noise filter OFF (AHPF bit=“0”).
update(Register::AutoHPFControl);
//Restore original AUDIO PATH , condition, (Digital filter block PATH is BY PASSED) (we can also swith off DIG. BLOCK power , PMPFIL=0)
// The Path in Recording Mode 2 & Playback Mode 2 , (NO DIG FILTER BLOCK AT ALL, not for MIC recording, nor for Playback)
map.r.digital_filter_mode.ADCPF = 1; // new code addition , ADCPF bit swith ("0" Mic after ADC Output connected (recording mode) to the DIGITAL FILTER BLOCK. ("1" Playback mode)
map.r.digital_filter_mode.PFSDO = 0; // new code addition , ADC bit switch ("0" : 1st order HPF) connectedto the Output. By bass DIGITAL block .
map.r.digital_filter_mode.PFDAC = 0b00; // new code addition , (Input selector for DAC (not used in MIC), SDTI= Audio Serial Data Input Pin)
update(Register::DigitalFilterMode); // Writing the Audio Path : NO DIGITAL BLOCK or DIG BLOCK FOR MIC , Audio mode path : Playback mode /-Recording mode.
// Restore original condition , LPF , OFF . same as when not using DIGITAL Programmable block
map.r.digital_filter_select_2.LPF = 0; // LPF-Block, Coeffic Setting Enable (OFF-Default), When LPF bit is “0”, audio data passes the LPF block by 0dB gain.
update(Register::DigitalFilterSelect2);
map.r.lpf_coefficient_0.l = 0x00; // Pre-loading here LPF 6k , 1st Order from digital Block , Fc=6000 Hz, fs = 48khz
map.r.lpf_coefficient_1.h = 0x00; // LPF bit is activated down, for all ALC digital modes.
map.r.lpf_coefficient_2.l = 0x00; // Writting reg to AK4951 , down with update....
map.r.lpf_coefficient_3.h = 0x00;
update(Register::LPFCoefficient0); // Writing pre-loaded 4 bytes LPF CoefFiecients 14 bits (FSA13..0, FSB13..0
update(Register::LPFCoefficient1);
update(Register::LPFCoefficient2);
update(Register::LPFCoefficient3);
// Switch off all EQ 1,2,3,4,5
map.r.digital_filter_select_3.EQ1 = 0; // EQ1 Coeffic Setting , (0: Disable-default, audio data passes EQ1 block by 0dB gain). When EQ1="1”, the settings of E1A15-0, E1B15-0 and E1C15-0 bits are enabled
map.r.digital_filter_select_3.EQ2 = 0; // EQ2 Coeffic Setting , (0: Disable-default, audio data passes EQ2 block by 0dB gain). When EQ2="1”, the settings of E2A15-0, E2B15-0 and E2C15-0 bits are enabled
map.r.digital_filter_select_3.EQ3 = 0; // EQ3 Coeffic Setting , (0: Disable-default, audio data passes EQ3 block by 0dB gain). When EQ3="1”, the settings of E3A15-0, E3B15-0 and E3C15-0 bits are enabled
map.r.digital_filter_select_3.EQ4 = 0; // EQ4 Coeffic Setting , (0: Disable-default, audio data passes EQ4 block by 0dB gain). When EQ4="1”, the settings of E4A15-0, E4B15-0 and E4C15-0 bits are enabled
map.r.digital_filter_select_3.EQ5 = 0; // EQ5 Coeffic Setting , (0: Disable-default, audio data passes EQ5 block by 0dB gain). When EQ5="1”, the settings of E5A15-0, E5B15-0 and E5C15-0 bits are enabled
update(Register::DigitalFilterSelect3);
}
reg_t AK4951::read(const address_t reg_address) {
+34 -31
View File
@@ -773,40 +773,41 @@ constexpr RegisterMap default_after_reset { Register_Type {
.REV = 0b1100,
},
.e1_coefficient_0 = { .l = 0x00 },
.e1_coefficient_1 = { .h = 0x00 },
.e1_coefficient_2 = { .l = 0x00 },
.e1_coefficient_3 = { .h = 0x00 },
.e1_coefficient_4 = { .l = 0x00 },
.e1_coefficient_5 = { .h = 0x00 },
// just pre-loading into memory, 30 bytes = EQ 1,2,3,4,5 x A,B,C (2 x bytes) coefficients, but it will be written from ak4951.cpp
.e1_coefficient_0 = { .l = 0xCA }, //EQ1 Coefficient A : A7...A0, BW : 300Hz - 1700Hz (fo = 1150Hz , fb= 1700Hz) , k=1,8 peaking
.e1_coefficient_1 = { .h = 0x05 }, //EQ1 Coefficient A : A15..A8
.e1_coefficient_2 = { .l = 0xEB }, //EQ1 Coefficient B : B7...B0
.e1_coefficient_3 = { .h = 0x38 }, //EQ1 Coefficient B : B15...B8
.e1_coefficient_4 = { .l = 0x6F }, //EQ1 Coefficient C : C7...C0
.e1_coefficient_5 = { .h = 0xE6 }, //EQ1 Coefficient C : C15..C8
.e2_coefficient_0 = { .l = 0x00 },
.e2_coefficient_1 = { .h = 0x00 },
.e2_coefficient_2 = { .l = 0x00 },
.e2_coefficient_3 = { .h = 0x00 },
.e2_coefficient_4 = { .l = 0x00 },
.e2_coefficient_5 = { .h = 0x00 },
.e2_coefficient_0 = { .l = 0x05 }, //EQ2 Coefficient A : A7...A0, BW : 250Hz - 2700Hz (fo = 1475Hz , fb= 2450Hz) , k=1,8 peaking
.e2_coefficient_1 = { .h = 0x08 }, //EQ2 Coefficient A : A15..A8
.e2_coefficient_2 = { .l = 0x11 }, //EQ2 Coefficient B : B7...B0
.e2_coefficient_3 = { .h = 0x36 }, //EQ2 Coefficient B : B15...B8
.e2_coefficient_4 = { .l = 0xE9 }, //EQ2 Coefficient C : C7...C0
.e2_coefficient_5 = { .h = 0xE8 }, //EQ2 Coefficient C : C15..C8
.e3_coefficient_0 = { .l = 0x00 },
.e3_coefficient_1 = { .h = 0x00 },
.e3_coefficient_2 = { .l = 0x00 },
.e3_coefficient_3 = { .h = 0x00 },
.e3_coefficient_4 = { .l = 0x00 },
.e3_coefficient_5 = { .h = 0x00 },
.e3_coefficient_0 = { .l = 0x00 }, //EQ3 Coefficient A : A7...A0, not used currently
.e3_coefficient_1 = { .h = 0x00 }, //EQ3 Coefficient A : A15..A8
.e3_coefficient_2 = { .l = 0x00 }, //EQ3 Coefficient B : B7...B0
.e3_coefficient_3 = { .h = 0x00 }, //EQ3 Coefficient B : B15...B8
.e3_coefficient_4 = { .l = 0x00 }, //EQ3 Coefficient C : C7...C0
.e3_coefficient_5 = { .h = 0x00 }, //EQ3 Coefficient C : C15..C8
.e4_coefficient_0 = { .l = 0x00 },
.e4_coefficient_1 = { .h = 0x00 },
.e4_coefficient_2 = { .l = 0x00 },
.e4_coefficient_3 = { .h = 0x00 },
.e4_coefficient_4 = { .l = 0x00 },
.e4_coefficient_5 = { .h = 0x00 },
.e4_coefficient_0 = { .l = 0x00 }, //EQ4 Coefficient A : A7...A0, not used currently
.e4_coefficient_1 = { .h = 0x00 }, //EQ4 Coefficient A : A15..A8
.e4_coefficient_2 = { .l = 0x00 }, //EQ4 Coefficient B : B7...B0
.e4_coefficient_3 = { .h = 0x00 }, //EQ4 Coefficient B : B15...B8
.e4_coefficient_4 = { .l = 0x00 }, //EQ4 Coefficient C : C7...C0
.e4_coefficient_5 = { .h = 0x00 }, //EQ4 Coefficient C : C15..C8
.e5_coefficient_0 = { .l = 0x00 },
.e5_coefficient_1 = { .h = 0x00 },
.e5_coefficient_2 = { .l = 0x00 },
.e5_coefficient_3 = { .h = 0x00 },
.e5_coefficient_4 = { .l = 0x00 },
.e5_coefficient_5 = { .h = 0x00 },
.e5_coefficient_0 = { .l = 0x00 }, //EQ5 Coefficient A : A7...A0, not used currently
.e5_coefficient_1 = { .h = 0x00 }, //EQ5 Coefficient A : A15..A8
.e5_coefficient_2 = { .l = 0x00 }, //EQ5 Coefficient B : B7...B0
.e5_coefficient_3 = { .h = 0x00 }, //EQ5 Coefficient B : B15...B8
.e5_coefficient_4 = { .l = 0x00 }, //EQ5 Coefficient C : C7...C0
.e5_coefficient_5 = { .h = 0x00 }, //EQ5 Coefficient C : C15..C8
} };
class AK4951 : public audio::Codec {
@@ -822,6 +823,8 @@ public:
std::string name() const override {
return "AK4951";
}
bool detected();
void init() override;
bool reset() override;
@@ -839,7 +842,7 @@ public:
void set_headphone_volume(const volume_t volume) override;
void headphone_mute();
void microphone_enable();
void microphone_enable(int8_t alc_mode); // added user GUI parameter , to set up AK4951 ALC mode.
void microphone_disable();
size_t reg_count() const override {
+28 -33
View File
@@ -81,39 +81,34 @@ public:
SamplerateConfig = 24,
BTLERxConfigure = 25,
NRFRxConfigure = 26,
TXProgress = 30,
Retune = 31,
TonesConfigure = 32,
AFSKTxConfigure = 33,
PitchRSSIConfigure = 34,
OOKConfigure = 35,
RDSConfigure = 36,
AudioTXConfig = 37,
POCSAGConfigure = 38,
DTMFTXConfig = 39,
ADSBConfigure = 40,
JammerConfigure = 41,
WidebandSpectrumConfig = 42,
FSKConfigure = 43,
SSTVConfigure = 44,
SigGenConfig = 43,
SigGenTone = 44,
POCSAGPacket = 45,
ADSBFrame = 46,
AFSKData = 47,
TestAppPacket = 48,
RequestSignal = 49,
FIFOData = 50,
AudioLevelReport = 51,
CodedSquelch = 52,
AudioSpectrum = 53,
APRSPacket = 54,
APRSRxConfigure = 55,
TXProgress = 27,
Retune = 28,
TonesConfigure = 29,
AFSKTxConfigure = 30,
PitchRSSIConfigure = 31,
OOKConfigure = 32,
RDSConfigure = 33,
AudioTXConfig = 34,
POCSAGConfigure = 35,
DTMFTXConfig = 36,
ADSBConfigure = 37,
JammerConfigure = 38,
WidebandSpectrumConfig = 39,
FSKConfigure = 40,
SSTVConfigure = 41,
SigGenConfig = 42,
SigGenTone = 43,
POCSAGPacket = 44,
ADSBFrame = 45,
AFSKData = 46,
TestAppPacket = 47,
RequestSignal = 48,
FIFOData = 49,
AudioLevelReport = 50,
CodedSquelch = 51,
AudioSpectrum = 52,
APRSPacket = 53,
APRSRxConfigure = 54,
MAX
};
@@ -82,7 +82,7 @@ struct data_t {
int32_t afsk_space_freq;
int32_t modem_baudrate;
int32_t modem_repeat;
// Play dead unlock
uint32_t playdead_magic;
uint32_t playing_dead;
@@ -95,6 +95,9 @@ struct data_t {
uint32_t pocsag_ignore_address;
int32_t tone_mix;
// Hardware
uint32_t hardware_config;
};
static_assert(sizeof(data_t) <= backup_ram.size(), "Persistent memory structure too large for VBAT-maintained region");
@@ -224,9 +227,17 @@ void set_playdead_sequence(const uint32_t new_value) {
// ui_config is an uint32_t var storing information bitwise
// bits 0,1,2 store the backlight timer
// bits 31, 30,29,28,27, 26, 25 stores the different single bit configs depicted below
// bits 31, 30,29,28,27, 26, 25, 24 stores the different single bit configs depicted below
// bits on position 4 to 19 (16 bits) store the clkout frequency
bool disable_touchscreen() { // Option to disable touch screen
return data->ui_config & (1 << 24);
}
bool show_bigger_qr_code() { // show bigger QR code
return data->ui_config & (1 << 23);
}
bool hide_clock() { // clock hidden from main menu
return data->ui_config & (1 << 25);
}
@@ -254,11 +265,23 @@ bool config_splash() {
return data->ui_config & (1 << 31);
}
uint8_t config_cpld() {
return data->hardware_config;
}
uint32_t config_backlight_timer() {
const uint32_t timer_seconds[8] = { 0, 5, 15, 30, 60, 180, 300, 600 };
return timer_seconds[data->ui_config & 7]; //first three bits, 8 possible values
}
void set_disable_touchscreen(bool v) {
data->ui_config = (data->ui_config & ~(1 << 24)) | (v << 24);
}
void set_show_bigger_qr_code(bool v) {
data->ui_config = (data->ui_config & ~(1 << 23)) | (v << 23);
}
void set_clock_hidden(bool v) {
data->ui_config = (data->ui_config & ~(1 << 25)) | (v << 25);
}
@@ -287,6 +310,10 @@ void set_config_splash(bool v) {
data->ui_config = (data->ui_config & ~(1 << 31)) | (v << 31);
}
void set_config_cpld(uint8_t i) {
data->hardware_config = i;
}
void set_config_backlight_timer(uint32_t i) {
data->ui_config = (data->ui_config & ~7) | (i & 7);
}
@@ -74,19 +74,26 @@ void set_playdead_sequence(const uint32_t new_value);
bool stealth_mode();
void set_stealth_mode(const bool v);
uint8_t config_cpld();
void set_config_cpld(uint8_t i);
bool config_splash();
bool show_bigger_qr_code();
bool hide_clock();
bool clock_with_date();
bool config_login();
bool config_speaker();
uint32_t config_backlight_timer();
bool disable_touchscreen();
void set_config_splash(bool v);
void set_show_bigger_qr_code(bool v);
void set_clock_hidden(bool v);
void set_clock_with_date(bool v);
void set_config_login(bool v);
void set_config_speaker(bool v);
void set_config_backlight_timer(uint32_t i);
void set_disable_touchscreen(bool v);
//uint8_t ui_config_textentry();
//void set_config_textentry(uint8_t new_value);
+17 -1
View File
@@ -142,7 +142,23 @@ static int32_t rect_distances(
return -1;
}
return (std::abs(perpendicular_axis_end - perpendicular_axis_start) + 1) * (on_axis_distance + 1);
switch(direction) {
case KeyEvent::Right:
case KeyEvent::Left:
return ((std::abs(perpendicular_axis_end - perpendicular_axis_start) + 1) ^ 3) * sqrt((on_axis_distance + 1));
break;
case KeyEvent::Up:
case KeyEvent::Down:
return (sqrt(std::abs(perpendicular_axis_end - perpendicular_axis_start) + 1)) * ((on_axis_distance + 1) ^ 3);
break;
default:
return 0;
}
}
void FocusManager::update(
+3 -2
View File
@@ -345,8 +345,9 @@ public:
void speaker_disable() {};
void microphone_enable() override {
// TODO: Implement
void microphone_enable(int8_t alc_mode) override {
(void)alc_mode; // to avoid "unused warning" when compiling. (@WM8731 we do not use that parameter)
// TODO: Implement,
}
void microphone_disable() override {
BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 427 B

+1 -1
View File
@@ -1,4 +1,4 @@
#!/usr/bin/env python
#!/usr/bin/env python3
# Copyright (C) 2017 Furrtek
#
+2 -1
View File
@@ -1,7 +1,8 @@
# Make airlines.db
Licensed under GNU GPL v3 (license)[../../../LICENSE]
Licensed under [GNU GPL v3](../../../LICENSE)
USAGE:
- Copy file from: https://raw.githubusercontent.com/kx1t/planefence-airlinecodes/main/airlinecodes.txt
- Run Python 3 script: `./make_airlines_db.py`
- Copy file to /ADSB folder on SDCARD
+1231 -71
View File
File diff suppressed because it is too large Load Diff
+8
View File
@@ -0,0 +1,8 @@
# Make icao24.db
Licensed under [GNU GPL v3](../../../LICENSE)
USAGE:
- Copy file from: https://opensky-network.org/datasets/metadata/aircraftDatabase.csv
- Run Python 3 script: `./make_icao24_db.py`
- Copy file to /ADSB folder on SDCARD
File diff suppressed because it is too large Load Diff
+63
View File
@@ -0,0 +1,63 @@
#!/usr/bin/env python3
# Copyright (C) 2021 ArjanOnwezen
#
# 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.
#
# -------------------------------------------------------------------------------------
# Create icao24.db, used for ADS-B receiver application, using
# https://opensky-network.org/datasets/metadata/aircraftDatabase.csv
# as a source.
# -------------------------------------------------------------------------------------
import csv
import unicodedata
icao24_codes=bytearray()
data=bytearray()
row_count=0
database=open("icao24.db", "wb")
with open('aircraftDatabase.csv', 'rt') as csv_file:
sorted_lines=sorted(csv_file.readlines()[1:])
for row in csv.reader(sorted_lines, quotechar='"', delimiter=',', quoting=csv.QUOTE_ALL, skipinitialspace=True):
# only store in case enough info is available
if len(row) == 27 and len(row[0]) == 6 and len(row[1]) > 0:
icao24_code=row[0][:6].upper()
registration=row[1][:8].encode('ascii', 'ignore')
manufacturer=row[3][:32].encode('ascii', 'ignore')
model=row[4][:32].encode('ascii', 'ignore')
# in case icao aircraft type isn't, use ac type like BALL for balloon
if len(row[8]) == 3:
actype=row[8][:3].encode('ascii', 'ignore')
else:
actype=row[5][:4].encode('ascii', 'ignore')
owner=row[13][:32].encode('ascii', 'ignore')
operator=row[9][:32].encode('ascii', 'ignore')
#padding
icao24_codes=icao24_codes+bytearray(icao24_code+'\0', encoding='ascii')
registration_padding=bytearray('\0' * (9 - len(registration)), encoding='ascii')
manufacturer_padding=bytearray('\0' * (33 - len(manufacturer)), encoding='ascii')
model_padding=bytearray('\0' * (33 - len(model)), encoding='ascii')
actype_padding=bytearray('\0' * (5 - len(actype)), encoding='ascii')
owner_padding=bytearray('\0' * (33 - len(owner)), encoding='ascii')
operator_padding=bytearray('\0' * (33 - len(operator)), encoding='ascii')
data=data+bytearray(registration+registration_padding+manufacturer+manufacturer_padding+model+model_padding+actype+actype_padding+owner+owner_padding+operator+operator_padding)
row_count+=1
database.write(icao24_codes+data)
print("Total of", row_count, "ICAO codes stored in database")
@@ -0,0 +1,295 @@
Digit,Allocated to
201,Albania (Republic of)
202,Andorra (Principality of)
203,Austria
204,Portugal - Azores
205,Belgium
206,Belarus (Republic of)
207,Bulgaria (Republic of)
208,Vatican City State
209,Cyprus (Republic of)
210,Cyprus (Republic of)
211,Germany (Federal Republic of)
212,Cyprus (Republic of)
213,Georgia
214,Moldova (Republic of)
215,Malta
216,Armenia (Republic of)
218,Germany (Federal Republic of)
219,Denmark
220,Denmark
224,Spain
225,Spain
226,France
227,France
228,France
229,Malta
230,Finland
231,Denmark - Faroe Islands
232,United Kingdom of Great Britain and Northern Ireland
233,United Kingdom of Great Britain and Northern Ireland
234,United Kingdom of Great Britain and Northern Ireland
235,United Kingdom of Great Britain and Northern Ireland
236,United Kingdom of Great Britain and Northern Ireland - Gibraltar
237,Greece
238,Croatia (Republic of)
239,Greece
240,Greece
241,Greece
242,Morocco (Kingdom of)
243,Hungary
244,Netherlands (Kingdom of the)
245,Netherlands (Kingdom of the)
246,Netherlands (Kingdom of the)
247,Italy
248,Malta
249,Malta
250,Ireland
251,Iceland
252,Liechtenstein (Principality of)
253,Luxembourg
254,Monaco (Principality of)
255,Portugal - Madeira
256,Malta
257,Norway
258,Norway
259,Norway
261,Poland (Republic of)
262,Montenegro
263,Portugal
264,Romania
265,Sweden
266,Sweden
267,Slovak Republic
268,San Marino (Republic of)
269,Switzerland (Confederation of)
270,Czech Republic
271,Turkey
272,Ukraine
273,Russian Federation
274,North Macedonia (Republic of)
275,Latvia (Republic of)
276,Estonia (Republic of)
277,Lithuania (Republic of)
278,Slovenia (Republic of)
279,Serbia (Republic of)
301,United Kingdom of Great Britain and Northern Ireland - Anguilla
303,United States of America - Alaska (State of)
304,Antigua and Barbuda
305,Antigua and Barbuda
306,"Netherlands (Kingdom of the) - Bonaire, Sint Eustatius and Saba"
306,Netherlands (Kingdom of the) - Curaçao
306,Netherlands (Kingdom of the) - Sint Maarten (Dutch part)
307,Netherlands (Kingdom of the) - Aruba
308,Bahamas (Commonwealth of the)
309,Bahamas (Commonwealth of the)
310,United Kingdom of Great Britain and Northern Ireland - Bermuda
311,Bahamas (Commonwealth of the)
312,Belize
314,Barbados
316,Canada
319,United Kingdom of Great Britain and Northern Ireland - Cayman Islands
321,Costa Rica
323,Cuba
325,Dominica (Commonwealth of)
327,Dominican Republic
329,France - Guadeloupe (French Department of)
330,Grenada
331,Denmark - Greenland
332,Guatemala (Republic of)
334,Honduras (Republic of)
336,Haiti (Republic of)
338,United States of America
339,Jamaica
341,Saint Kitts and Nevis (Federation of)
343,Saint Lucia
345,Mexico
347,France - Martinique (French Department of)
348,United Kingdom of Great Britain and Northern Ireland - Montserrat
350,Nicaragua
351,Panama (Republic of)
352,Panama (Republic of)
353,Panama (Republic of)
354,Panama (Republic of)
355,Panama (Republic of)
356,Panama (Republic of)
357,Panama (Republic of)
358,United States of America - Puerto Rico
359,El Salvador (Republic of)
361,France - Saint Pierre and Miquelon (Territorial Collectivity of)
362,Trinidad and Tobago
364,United Kingdom of Great Britain and Northern Ireland - Turks and Caicos Islands
366,United States of America
367,United States of America
368,United States of America
369,United States of America
370,Panama (Republic of)
371,Panama (Republic of)
372,Panama (Republic of)
373,Panama (Republic of)
374,Panama (Republic of)
375,Saint Vincent and the Grenadines
376,Saint Vincent and the Grenadines
377,Saint Vincent and the Grenadines
378,United Kingdom of Great Britain and Northern Ireland - British Virgin Islands
379,United States of America - United States Virgin Islands
401,Afghanistan
403,Saudi Arabia (Kingdom of)
405,Bangladesh (People's Republic of)
408,Bahrain (Kingdom of)
410,Bhutan (Kingdom of)
412,China (People's Republic of)
413,China (People's Republic of)
414,China (People's Republic of)
416,China (People's Republic of) - Taiwan (Province of China)
417,Sri Lanka (Democratic Socialist Republic of)
419,India (Republic of)
422,Iran (Islamic Republic of)
423,Azerbaijan (Republic of)
425,Iraq (Republic of)
428,Israel (State of)
431,Japan
432,Japan
434,Turkmenistan
436,Kazakhstan (Republic of)
437,Uzbekistan (Republic of)
438,Jordan (Hashemite Kingdom of)
440,Korea (Republic of)
441,Korea (Republic of)
443,"State of Palestine (In accordance with Resolution 99 Rev. Dubai, 2018)"
445,Democratic People's Republic of Korea
447,Kuwait (State of)
450,Lebanon
451,Kyrgyz Republic
453,China (People's Republic of) - Macao (Special Administrative Region of China)
455,Maldives (Republic of)
457,Mongolia
459,Nepal (Federal Democratic Republic of)
461,Oman (Sultanate of)
463,Pakistan (Islamic Republic of)
466,Qatar (State of)
468,Syrian Arab Republic
470,United Arab Emirates
471,United Arab Emirates
472,Tajikistan (Republic of)
473,Yemen (Republic of)
475,Yemen (Republic of)
477,China (People's Republic of) - Hong Kong (Special Administrative Region of China)
478,Bosnia and Herzegovina
501,France - Adelie Land
503,Australia
506,Myanmar (Union of)
508,Brunei Darussalam
510,Micronesia (Federated States of)
511,Palau (Republic of)
512,New Zealand
514,Cambodia (Kingdom of)
515,Cambodia (Kingdom of)
516,Australia - Christmas Island (Indian Ocean)
518,New Zealand - Cook Islands
520,Fiji (Republic of)
523,Australia - Cocos (Keeling) Islands
525,Indonesia (Republic of)
529,Kiribati (Republic of)
531,Lao People's Democratic Republic
533,Malaysia
536,United States of America - Northern Mariana Islands (Commonwealth of the)
538,Marshall Islands (Republic of the)
540,France - New Caledonia
542,New Zealand - Niue
544,Nauru (Republic of)
546,France - French Polynesia
548,Philippines (Republic of the)
550,Timor-Leste (Democratic Republic of)
553,Papua New Guinea
555,United Kingdom of Great Britain and Northern Ireland - Pitcairn Island
557,Solomon Islands
559,United States of America - American Samoa
561,Samoa (Independent State of)
563,Singapore (Republic of)
564,Singapore (Republic of)
565,Singapore (Republic of)
566,Singapore (Republic of)
567,Thailand
570,Tonga (Kingdom of)
572,Tuvalu
574,Viet Nam (Socialist Republic of)
576,Vanuatu (Republic of)
577,Vanuatu (Republic of)
578,France - Wallis and Futuna Islands
601,South Africa (Republic of)
603,Angola (Republic of)
605,Algeria (People's Democratic Republic of)
607,France - Saint Paul and Amsterdam Islands
608,United Kingdom of Great Britain and Northern Ireland - Ascension Island
609,Burundi (Republic of)
610,Benin (Republic of)
611,Botswana (Republic of)
612,Central African Republic
613,Cameroon (Republic of)
615,Congo (Republic of the)
616,Comoros (Union of the)
617,Cabo Verde (Republic of)
618,France - Crozet Archipelago
619,Côte d'Ivoire (Republic of)
620,Comoros (Union of the)
621,Djibouti (Republic of)
622,Egypt (Arab Republic of)
624,Ethiopia (Federal Democratic Republic of)
625,Eritrea
626,Gabonese Republic
627,Ghana
629,Gambia (Republic of the)
630,Guinea-Bissau (Republic of)
631,Equatorial Guinea (Republic of)
632,Guinea (Republic of)
633,Burkina Faso
634,Kenya (Republic of)
635,France - Kerguelen Islands
636,Liberia (Republic of)
637,Liberia (Republic of)
638,South Sudan (Republic of)
642,Libya (State of)
644,Lesotho (Kingdom of)
645,Mauritius (Republic of)
647,Madagascar (Republic of)
649,Mali (Republic of)
650,Mozambique (Republic of)
654,Mauritania (Islamic Republic of)
655,Malawi
656,Niger (Republic of the)
657,Nigeria (Federal Republic of)
659,Namibia (Republic of)
660,France - Reunion (French Department of)
661,Rwanda (Republic of)
662,Sudan (Republic of the)
663,Senegal (Republic of)
664,Seychelles (Republic of)
665,United Kingdom of Great Britain and Northern Ireland - Saint Helena
666,Somalia (Federal Republic of)
667,Sierra Leone
668,Sao Tome and Principe (Democratic Republic of)
669,Eswatini (Kingdom of)
670,Chad (Republic of)
671,Togolese Republic
672,Tunisia
674,Tanzania (United Republic of)
675,Uganda (Republic of)
676,Democratic Republic of the Congo
677,Tanzania (United Republic of)
678,Zambia (Republic of)
679,Zimbabwe (Republic of)
701,Argentine Republic
710,Brazil (Federative Republic of)
720,Bolivia (Plurinational State of)
725,Chile
730,Colombia (Republic of)
735,Ecuador
740,United Kingdom of Great Britain and Northern Ireland - Falkland Islands (Malvinas)
745,France - Guiana (French Department of)
750,Guyana
755,Paraguay (Republic of)
760,Peru
765,Suriname (Republic of)
770,Uruguay (Eastern Republic of)
775,Venezuela (Bolivarian Republic of)
1 Digit Allocated to
2 201 Albania (Republic of)
3 202 Andorra (Principality of)
4 203 Austria
5 204 Portugal - Azores
6 205 Belgium
7 206 Belarus (Republic of)
8 207 Bulgaria (Republic of)
9 208 Vatican City State
10 209 Cyprus (Republic of)
11 210 Cyprus (Republic of)
12 211 Germany (Federal Republic of)
13 212 Cyprus (Republic of)
14 213 Georgia
15 214 Moldova (Republic of)
16 215 Malta
17 216 Armenia (Republic of)
18 218 Germany (Federal Republic of)
19 219 Denmark
20 220 Denmark
21 224 Spain
22 225 Spain
23 226 France
24 227 France
25 228 France
26 229 Malta
27 230 Finland
28 231 Denmark - Faroe Islands
29 232 United Kingdom of Great Britain and Northern Ireland
30 233 United Kingdom of Great Britain and Northern Ireland
31 234 United Kingdom of Great Britain and Northern Ireland
32 235 United Kingdom of Great Britain and Northern Ireland
33 236 United Kingdom of Great Britain and Northern Ireland - Gibraltar
34 237 Greece
35 238 Croatia (Republic of)
36 239 Greece
37 240 Greece
38 241 Greece
39 242 Morocco (Kingdom of)
40 243 Hungary
41 244 Netherlands (Kingdom of the)
42 245 Netherlands (Kingdom of the)
43 246 Netherlands (Kingdom of the)
44 247 Italy
45 248 Malta
46 249 Malta
47 250 Ireland
48 251 Iceland
49 252 Liechtenstein (Principality of)
50 253 Luxembourg
51 254 Monaco (Principality of)
52 255 Portugal - Madeira
53 256 Malta
54 257 Norway
55 258 Norway
56 259 Norway
57 261 Poland (Republic of)
58 262 Montenegro
59 263 Portugal
60 264 Romania
61 265 Sweden
62 266 Sweden
63 267 Slovak Republic
64 268 San Marino (Republic of)
65 269 Switzerland (Confederation of)
66 270 Czech Republic
67 271 Turkey
68 272 Ukraine
69 273 Russian Federation
70 274 North Macedonia (Republic of)
71 275 Latvia (Republic of)
72 276 Estonia (Republic of)
73 277 Lithuania (Republic of)
74 278 Slovenia (Republic of)
75 279 Serbia (Republic of)
76 301 United Kingdom of Great Britain and Northern Ireland - Anguilla
77 303 United States of America - Alaska (State of)
78 304 Antigua and Barbuda
79 305 Antigua and Barbuda
80 306 Netherlands (Kingdom of the) - Bonaire, Sint Eustatius and Saba
81 306 Netherlands (Kingdom of the) - Curaçao
82 306 Netherlands (Kingdom of the) - Sint Maarten (Dutch part)
83 307 Netherlands (Kingdom of the) - Aruba
84 308 Bahamas (Commonwealth of the)
85 309 Bahamas (Commonwealth of the)
86 310 United Kingdom of Great Britain and Northern Ireland - Bermuda
87 311 Bahamas (Commonwealth of the)
88 312 Belize
89 314 Barbados
90 316 Canada
91 319 United Kingdom of Great Britain and Northern Ireland - Cayman Islands
92 321 Costa Rica
93 323 Cuba
94 325 Dominica (Commonwealth of)
95 327 Dominican Republic
96 329 France - Guadeloupe (French Department of)
97 330 Grenada
98 331 Denmark - Greenland
99 332 Guatemala (Republic of)
100 334 Honduras (Republic of)
101 336 Haiti (Republic of)
102 338 United States of America
103 339 Jamaica
104 341 Saint Kitts and Nevis (Federation of)
105 343 Saint Lucia
106 345 Mexico
107 347 France - Martinique (French Department of)
108 348 United Kingdom of Great Britain and Northern Ireland - Montserrat
109 350 Nicaragua
110 351 Panama (Republic of)
111 352 Panama (Republic of)
112 353 Panama (Republic of)
113 354 Panama (Republic of)
114 355 Panama (Republic of)
115 356 Panama (Republic of)
116 357 Panama (Republic of)
117 358 United States of America - Puerto Rico
118 359 El Salvador (Republic of)
119 361 France - Saint Pierre and Miquelon (Territorial Collectivity of)
120 362 Trinidad and Tobago
121 364 United Kingdom of Great Britain and Northern Ireland - Turks and Caicos Islands
122 366 United States of America
123 367 United States of America
124 368 United States of America
125 369 United States of America
126 370 Panama (Republic of)
127 371 Panama (Republic of)
128 372 Panama (Republic of)
129 373 Panama (Republic of)
130 374 Panama (Republic of)
131 375 Saint Vincent and the Grenadines
132 376 Saint Vincent and the Grenadines
133 377 Saint Vincent and the Grenadines
134 378 United Kingdom of Great Britain and Northern Ireland - British Virgin Islands
135 379 United States of America - United States Virgin Islands
136 401 Afghanistan
137 403 Saudi Arabia (Kingdom of)
138 405 Bangladesh (People's Republic of)
139 408 Bahrain (Kingdom of)
140 410 Bhutan (Kingdom of)
141 412 China (People's Republic of)
142 413 China (People's Republic of)
143 414 China (People's Republic of)
144 416 China (People's Republic of) - Taiwan (Province of China)
145 417 Sri Lanka (Democratic Socialist Republic of)
146 419 India (Republic of)
147 422 Iran (Islamic Republic of)
148 423 Azerbaijan (Republic of)
149 425 Iraq (Republic of)
150 428 Israel (State of)
151 431 Japan
152 432 Japan
153 434 Turkmenistan
154 436 Kazakhstan (Republic of)
155 437 Uzbekistan (Republic of)
156 438 Jordan (Hashemite Kingdom of)
157 440 Korea (Republic of)
158 441 Korea (Republic of)
159 443 State of Palestine (In accordance with Resolution 99 Rev. Dubai, 2018)
160 445 Democratic People's Republic of Korea
161 447 Kuwait (State of)
162 450 Lebanon
163 451 Kyrgyz Republic
164 453 China (People's Republic of) - Macao (Special Administrative Region of China)
165 455 Maldives (Republic of)
166 457 Mongolia
167 459 Nepal (Federal Democratic Republic of)
168 461 Oman (Sultanate of)
169 463 Pakistan (Islamic Republic of)
170 466 Qatar (State of)
171 468 Syrian Arab Republic
172 470 United Arab Emirates
173 471 United Arab Emirates
174 472 Tajikistan (Republic of)
175 473 Yemen (Republic of)
176 475 Yemen (Republic of)
177 477 China (People's Republic of) - Hong Kong (Special Administrative Region of China)
178 478 Bosnia and Herzegovina
179 501 France - Adelie Land
180 503 Australia
181 506 Myanmar (Union of)
182 508 Brunei Darussalam
183 510 Micronesia (Federated States of)
184 511 Palau (Republic of)
185 512 New Zealand
186 514 Cambodia (Kingdom of)
187 515 Cambodia (Kingdom of)
188 516 Australia - Christmas Island (Indian Ocean)
189 518 New Zealand - Cook Islands
190 520 Fiji (Republic of)
191 523 Australia - Cocos (Keeling) Islands
192 525 Indonesia (Republic of)
193 529 Kiribati (Republic of)
194 531 Lao People's Democratic Republic
195 533 Malaysia
196 536 United States of America - Northern Mariana Islands (Commonwealth of the)
197 538 Marshall Islands (Republic of the)
198 540 France - New Caledonia
199 542 New Zealand - Niue
200 544 Nauru (Republic of)
201 546 France - French Polynesia
202 548 Philippines (Republic of the)
203 550 Timor-Leste (Democratic Republic of)
204 553 Papua New Guinea
205 555 United Kingdom of Great Britain and Northern Ireland - Pitcairn Island
206 557 Solomon Islands
207 559 United States of America - American Samoa
208 561 Samoa (Independent State of)
209 563 Singapore (Republic of)
210 564 Singapore (Republic of)
211 565 Singapore (Republic of)
212 566 Singapore (Republic of)
213 567 Thailand
214 570 Tonga (Kingdom of)
215 572 Tuvalu
216 574 Viet Nam (Socialist Republic of)
217 576 Vanuatu (Republic of)
218 577 Vanuatu (Republic of)
219 578 France - Wallis and Futuna Islands
220 601 South Africa (Republic of)
221 603 Angola (Republic of)
222 605 Algeria (People's Democratic Republic of)
223 607 France - Saint Paul and Amsterdam Islands
224 608 United Kingdom of Great Britain and Northern Ireland - Ascension Island
225 609 Burundi (Republic of)
226 610 Benin (Republic of)
227 611 Botswana (Republic of)
228 612 Central African Republic
229 613 Cameroon (Republic of)
230 615 Congo (Republic of the)
231 616 Comoros (Union of the)
232 617 Cabo Verde (Republic of)
233 618 France - Crozet Archipelago
234 619 Côte d'Ivoire (Republic of)
235 620 Comoros (Union of the)
236 621 Djibouti (Republic of)
237 622 Egypt (Arab Republic of)
238 624 Ethiopia (Federal Democratic Republic of)
239 625 Eritrea
240 626 Gabonese Republic
241 627 Ghana
242 629 Gambia (Republic of the)
243 630 Guinea-Bissau (Republic of)
244 631 Equatorial Guinea (Republic of)
245 632 Guinea (Republic of)
246 633 Burkina Faso
247 634 Kenya (Republic of)
248 635 France - Kerguelen Islands
249 636 Liberia (Republic of)
250 637 Liberia (Republic of)
251 638 South Sudan (Republic of)
252 642 Libya (State of)
253 644 Lesotho (Kingdom of)
254 645 Mauritius (Republic of)
255 647 Madagascar (Republic of)
256 649 Mali (Republic of)
257 650 Mozambique (Republic of)
258 654 Mauritania (Islamic Republic of)
259 655 Malawi
260 656 Niger (Republic of the)
261 657 Nigeria (Federal Republic of)
262 659 Namibia (Republic of)
263 660 France - Reunion (French Department of)
264 661 Rwanda (Republic of)
265 662 Sudan (Republic of the)
266 663 Senegal (Republic of)
267 664 Seychelles (Republic of)
268 665 United Kingdom of Great Britain and Northern Ireland - Saint Helena
269 666 Somalia (Federal Republic of)
270 667 Sierra Leone
271 668 Sao Tome and Principe (Democratic Republic of)
272 669 Eswatini (Kingdom of)
273 670 Chad (Republic of)
274 671 Togolese Republic
275 672 Tunisia
276 674 Tanzania (United Republic of)
277 675 Uganda (Republic of)
278 676 Democratic Republic of the Congo
279 677 Tanzania (United Republic of)
280 678 Zambia (Republic of)
281 679 Zimbabwe (Republic of)
282 701 Argentine Republic
283 710 Brazil (Federative Republic of)
284 720 Bolivia (Plurinational State of)
285 725 Chile
286 730 Colombia (Republic of)
287 735 Ecuador
288 740 United Kingdom of Great Britain and Northern Ireland - Falkland Islands (Malvinas)
289 745 France - Guiana (French Department of)
290 750 Guyana
291 755 Paraguay (Republic of)
292 760 Peru
293 765 Suriname (Republic of)
294 770 Uruguay (Eastern Republic of)
295 775 Venezuela (Bolivarian Republic of)
+13
View File
@@ -0,0 +1,13 @@
# Make mids.db
Licensed under [GNU GPL v3](../../../LICENSE)
Python3 script creates a MID (Marine Identification Digit) database.
MID is part of MMSI and determines (among other things) the conutry.
USAGE:
- Copy Excel file from https://www.itu.int/en/ITU-R/terrestrial/fmd/Pages/mid.aspx
- Convert it to a csv document
- Run Python 3 script: `./make_mids_db.py`
- Copy file to /AIS folder on SDCARD
+55
View File
@@ -0,0 +1,55 @@
#!/usr/bin/env python3
# Copyright (C) 2022 ArjanOnwezen
#
# 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.
#
# -------------------------------------------------------------------------------------
# Create mids.db, used for AIS receiver application, using converted Excel file on page:
# https://www.itu.int/en/ITU-R/terrestrial/fmd/Pages/mid.aspx
# as a source.
# MID stands for Marine Identification Digits and can be used to determine conutry of
# vessel or coastal station.
# -------------------------------------------------------------------------------------
import csv
import re
import unicodedata
mid_codes=bytearray()
countries=bytearray()
row_count=0
database=open("mids.db", "wb")
with open('MaritimeIdentificationDigits.csv', 'rt') as csv_file:
sorted_lines=sorted(csv_file.readlines())
for row in csv.reader(sorted_lines, quotechar='"', delimiter=',', quoting=csv.QUOTE_ALL, skipinitialspace=True):
mid_code=row[0]
# Normalize some unicode characters
#unicodedata.normalize('NFKD', row[3][:32]).encode('ascii', 'ignore')
country=unicodedata.normalize('NFKD', "".join(re.split("\(|\)|\[|\]", row[1].split('-')[-1].replace(" of Great Britain and Northern Ireland" , ""))[::2])).replace("Democratic People's Republic of Korea", "North-Korea").strip().encode('ascii', 'ignore')[:32]
if len(mid_code) == 3 :
country_padding=bytearray()
print(mid_code,' - ', country)
mid_codes=mid_codes+bytearray(mid_code+'\0', encoding='ascii')
country_padding=bytearray('\0' * (32 - len(country)), encoding='ascii')
countries=countries+country+country_padding
row_count+=1
database.write(mid_codes+countries)
print("Total of", row_count, "MID codes stored in database")
+2
View File
@@ -0,0 +1,2 @@
[InternetShortcut]
URL=https://github.com/eried/portapack-mayhem/releases
+2
View File
@@ -0,0 +1,2 @@
[InternetShortcut]
URL=https://github.com/eried/portapack-mayhem/wiki/Update-firmware
+1
View File
@@ -0,0 +1 @@
Plug HackRF+Portapack, set it in HackRF mode, launch flash_portapack_mayhem.bat
Binary file not shown.
+19
View File
@@ -0,0 +1,19 @@
@echo off
echo *** Run HackRF firmware in RAM via LPC DFU ***
echo.
echo This is used to "unbrick" your HackRF, if you are no longer able to use
echo HackRF tools to flash or operate your HackRF.
echo.
echo Connect your HackRF One to a USB port on your computer.
echo.
echo Hold down both the DFU and RESET buttons on the HackRF.
echo Then release the RESET button (closest to the edge).
echo Then release the DFU button.
echo.
pause
echo.
dfu-util-static.exe --device 1fc9:000c --download hackrf_one_usb.dfu --reset
echo.
pause
Binary file not shown.
+7
View File
@@ -0,0 +1,7 @@
<?xml version="1.0" ?>
<dpinst>
<deleteBinaries/>
<installAllOrNone/>
<suppressAddRemovePrograms/>
<suppressWizard/>
</dpinst>
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+15
View File
@@ -0,0 +1,15 @@
@echo off
echo *** Re-flash the HackRF with HackRF firmware ***
echo.
echo Connect your HackRF One to a USB port on your computer.
echo.
echo If using a PortaPack, put the PortaPack in HackRF mode by selecting
echo the "HackRF" option from the main menu.
echo.
pause
echo.
hackrf_update.exe hackrf_one_usb.bin
echo.
pause
+15
View File
@@ -0,0 +1,15 @@
@echo off
echo *** Re-flash the HackRF with PortaPack firmware ***
echo.
echo Connect your HackRF One to a USB port on your computer.
echo.
echo If using a PortaPack, put the PortaPack in HackRF mode by selecting
echo the "HackRF" option from the main menu.
echo.
pause
echo.
hackrf_update.exe portapack-h1_h2-mayhem.bin
echo.
pause
Binary file not shown.
Binary file not shown.
Binary file not shown.
Executable → Regular
BIN
View File
Binary file not shown.
Binary file not shown.
Binary file not shown.
+29 -29
View File
@@ -1,41 +1,41 @@
f=174928000,d=Channel 5A
f=176648000,d=Channel 5B
f=178358000,d=Channel 5C
f=180068000,d=Channel 5D
f=181938000,d=Channel 6A
f=176640000,d=Channel 5B
f=178352000,d=Channel 5C
f=180064000,d=Channel 5D
f=181936000,d=Channel 6A
f=183648000,d=Channel 6B
f=185368000,d=Channel 6C
f=187078000,d=Channel 6D
f=185360000,d=Channel 6C
f=187072000,d=Channel 6D
f=188928000,d=Channel 7A
f=190648000,d=Channel 7B
f=192358000,d=Channel 7C
f=194068000,d=Channel 7D
f=195938000,d=Channel 8A
f=190640000,d=Channel 7B
f=192352000,d=Channel 7C
f=194064000,d=Channel 7D
f=195936000,d=Channel 8A
f=197648000,d=Channel 8B
f=199368000,d=Channel 8C
f=201078000,d=Channel 8D
f=199360000,d=Channel 8C
f=201072000,d=Channel 8D
f=202928000,d=Channel 9A
f=204648000,d=Channel 9B
f=206358000,d=Channel 9C
f=208068000,d=Channel 9D
f=209938000,d=Channel 10A
f=204640000,d=Channel 9B
f=206352000,d=Channel 9C
f=208064000,d=Channel 9D
f=209936000,d=Channel 10A
f=210096000,d=Channel 10N
f=211648000,d=Channel 10B
f=213368000,d=Channel 10C
f=215078000,d=Channel 10D
f=213360000,d=Channel 10C
f=215072000,d=Channel 10D
f=216928000,d=Channel 11A
f=217088000,d=Channel 11N
f=218648000,d=Channel 11B
f=220358000,d=Channel 11C
f=222068000,d=Channel 11D
f=223938000,d=Channel 12A
f=218640000,d=Channel 11B
f=220352000,d=Channel 11C
f=222064000,d=Channel 11D
f=223936000,d=Channel 12A
f=224096000,d=Channel 12N
f=225648000,d=Channel 12B
f=227368000,d=Channel 12C
f=229078000,d=Channel 12D
f=230788000,d=Channel 13A
f=232498000,d=Channel 13B
f=227360000,d=Channel 12C
f=229072000,d=Channel 12D
f=230784000,d=Channel 13A
f=232496000,d=Channel 13B
f=234208000,d=Channel 13C
f=235778000,d=Channel 13D
f=237448000,d=Channel 13E
f=239208000,d=Channel 13F
f=235776000,d=Channel 13D
f=237488000,d=Channel 13E
f=239200000,d=Channel 13F
+1
View File
@@ -36,3 +36,4 @@ f=147325000,d=CH Swissphone 2
f=147375000,d=CH Swissphone 3
f=147400000,d=CH Swissphone 4
f=169700000,d=CH Swissphone 5
f=173250000,d=SLO Fire
+88
View File
@@ -0,0 +1,88 @@
# https://www.fcc.gov/wireless/bureau-divisions/mobility-division/paging
# Lower Paging Bands - Paired
f=152030000,d=USA LPBP-FA1
f=152060000,d=USA LPBP-FB1
f=152090000,d=USA LPBP-FC1
f=152120000,d=USA LPBP-FD1
f=152150000,d=USA LPBP-FE1
f=152180000,d=USA LPBP-FF1
f=152210000,d=USA LPBP-FG1
f=152510000,d=USA LPBP-FH1
f=152540000,d=USA LPBP-FI1
f=152570000,d=USA LPBP-FJ1
f=152600000,d=USA LPBP-FK1
f=152630000,d=USA LPBP-FL1
f=152660000,d=USA LPBP-FM1
f=152690000,d=USA LPBP-FN1
f=152720000,d=USA LPBP-FO1
f=152750000,d=USA LPBP-FP1
f=152780000,d=USA LPBP-FQ1
f=152810000,d=USA LPBP-FR1
f=158490000,d=USA LPBP-FA2
f=158520000,d=USA LPBP-FB2
f=158550000,d=USA LPBP-FC2
f=158580000,d=USA LPBP-FD2
f=158610000,d=USA LPBP-FE2
f=158640000,d=USA LPBP-FF2
f=158670000,d=USA LPBP-FG2
f=157770000,d=USA LPBP-FH2
f=157800000,d=USA LPBP-FI2
f=157830000,d=USA LPBP-FJ2
f=157860000,d=USA LPBP-FK2
f=157890000,d=USA LPBP-FL2
f=157920000,d=USA LPBP-FM2
f=157950000,d=USA LPBP-FN2
f=157980000,d=USA LPBP-FO2
f=158010000,d=USA LPBP-FP2
f=158040000,d=USA LPBP-FQ2
f=158070000,d=USA LPBP-FR2
f=454025000,d=USA LPBP-GA1
f=454050000,d=USA LPBP-GB1
f=454075000,d=USA LPBP-GC1
f=454100000,d=USA LPBP-GD1
f=454125000,d=USA LPBP-GE1
f=454150000,d=USA LPBP-GF1
f=454175000,d=USA LPBP-GG1
f=454200000,d=USA LPBP-GH1
f=454225000,d=USA LPBP-GI1
f=454250000,d=USA LPBP-GJ1
f=454275000,d=USA LPBP-GK1
f=454300000,d=USA LPBP-GL1
f=454325000,d=USA LPBP-GM1
f=152570000,d=USA LPBP-GN1
f=152600000,d=USA LPBP-GO1
f=152630000,d=USA LPBP-GP1
f=152660000,d=USA LPBP-GQ1
f=152690000,d=USA LPBP-GR1
f=152720000,d=USA LPBP-GS1
f=152750000,d=USA LPBP-GT1
f=152780000,d=USA LPBP-GU1
f=152810000,d=USA LPBP-GV1
f=152720000,d=USA LPBP-GX1
f=152750000,d=USA LPBP-GY1
f=152810000,d=USA LPBP-GZ1
f=459025000,d=USA LPBP-GA2
f=459050000,d=USA LPBP-GB2
f=459075000,d=USA LPBP-GC2
f=459100000,d=USA LPBP-GD2
f=459125000,d=USA LPBP-GE2
f=459150000,d=USA LPBP-GF2
f=459175000,d=USA LPBP-GG2
f=459200000,d=USA LPBP-GH2
f=459225000,d=USA LPBP-GI2
f=459250000,d=USA LPBP-GJ2
f=459275000,d=USA LPBP-GK2
f=459300000,d=USA LPBP-GL2
f=459325000,d=USA LPBP-GM2
f=157830000,d=USA LPBP-GN2
f=157860000,d=USA LPBP-GO2
f=157890000,d=USA LPBP-GP2
f=157920000,d=USA LPBP-GQ2
f=157950000,d=USA LPBP-GR2
f=157980000,d=USA LPBP-GS2
f=158010000,d=USA LPBP-GT2
f=158040000,d=USA LPBP-GU2
f=158070000,d=USA LPBP-GV2
f=157980000,d=USA LPBP-GX2
f=158010000,d=USA LPBP-GY2
f=158070000,d=USA LPBP-GZ2
+38
View File
@@ -0,0 +1,38 @@
# https://www.fcc.gov/wireless/bureau-divisions/mobility-division/paging
# Lower Paging Bands - Unpaired
f=35200000,d=USA LPBU-CA
f=35220000,d=USA LPBU-CB
f=35240000,d=USA LPBU-CC
f=35260000,d=USA LPBU-CD
f=35300000,d=USA LPBU-CE
f=35340000,d=USA LPBU-CF
f=35380000,d=USA LPBU-CG
f=35420000,d=USA LPBU-CH
f=35460000,d=USA LPBU-CI
f=35500000,d=USA LPBU-CJ
f=35540000,d=USA LPBU-CK
f=35560000,d=USA LPBU-CL
f=35580000,d=USA LPBU-CM
f=35600000,d=USA LPBU-CN
f=35620000,d=USA LPBU-CO
f=35660000,d=USA LPBU-CP
f=43200000,d=USA LPBU-DA
f=43220000,d=USA LPBU-DB
f=43240000,d=USA LPBU-DC
f=43260000,d=USA LPBU-DD
f=43300000,d=USA LPBU-DE
f=43340000,d=USA LPBU-DF
f=43380000,d=USA LPBU-DG
f=43420000,d=USA LPBU-DH
f=43460000,d=USA LPBU-DI
f=43500000,d=USA LPBU-DJ
f=43540000,d=USA LPBU-DK
f=43560000,d=USA LPBU-DL
f=43580000,d=USA LPBU-DM
f=43600000,d=USA LPBU-DN
f=43620000,d=USA LPBU-DO
f=43660000,d=USA LPBU-DP
f=152240000,d=USA LPBU-EA
f=152800000,d=USA LPBU-EB
f=158100000,d=USA LPBU-EC
f=158700000,d=USA LPBU-ED

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