1664 Commits

Author SHA1 Message Date
c266a37a6b fix sdrplay configuration bug
Some checks failed
Build Binaries / build_debian_buster (push) Failing after 4s
Build Binaries / build_debian_bullseye (push) Failing after 4s
Build Binaries / build_debian_bookworm (push) Failing after 4s
Build Binaries / build_debian_sid (push) Failing after 6s
Build Binaries / build_ubuntu_focal (push) Failing after 4s
Build Binaries / build_ubuntu_jammy (push) Failing after 4s
Build Binaries / build_ubuntu_mantic (push) Failing after 4s
Build Binaries / build_ubuntu_noble (push) Failing after 3s
Build Binaries / build_android (push) Failing after 4s
Build Binaries / check_spelling (push) Failing after 4s
Build Binaries / check_formatting (push) Successful in 4s
Build Binaries / create_full_archive (push) Has been cancelled
Build Binaries / update_nightly_release (push) Has been cancelled
Build Binaries / build_windows (push) Has been cancelled
Build Binaries / build_macos_intel (push) Has been cancelled
Build Binaries / build_macos_arm (push) Has been cancelled
Build Binaries / build_raspios_bullseye_armhf (push) Has been cancelled
2024-12-18 23:19:40 +01:00
895199ae94 fix RSPdx bug
Some checks failed
Build Binaries / build_windows (push) Waiting to run
Build Binaries / build_macos_intel (push) Waiting to run
Build Binaries / build_macos_arm (push) Waiting to run
Build Binaries / build_raspios_bullseye_armhf (push) Waiting to run
Build Binaries / create_full_archive (push) Blocked by required conditions
Build Binaries / update_nightly_release (push) Blocked by required conditions
Build Binaries / build_debian_buster (push) Failing after 4s
Build Binaries / build_debian_bullseye (push) Failing after 5s
Build Binaries / build_debian_bookworm (push) Failing after 4s
Build Binaries / build_debian_sid (push) Failing after 4s
Build Binaries / build_ubuntu_focal (push) Failing after 4s
Build Binaries / build_ubuntu_jammy (push) Failing after 4s
Build Binaries / build_ubuntu_mantic (push) Failing after 4s
Build Binaries / build_ubuntu_noble (push) Failing after 4s
Build Binaries / build_android (push) Failing after 4s
Build Binaries / check_spelling (push) Failing after 4s
Build Binaries / check_formatting (push) Successful in 4s
2024-12-18 23:02:49 +01:00
d62426364a finish implementing support for RSP1B and RSPdx R2 + Improve samplerate and bandwidth code 2024-12-18 22:59:57 +01:00
304d5c42cc some fucking changes too lazy to name this shit 2024-11-27 21:49:46 +01:00
11f87e0fe2 fix menu order bug
Some checks failed
Build Binaries / build_debian_buster (push) Failing after 5s
Build Binaries / build_debian_bullseye (push) Failing after 5s
Build Binaries / build_debian_bookworm (push) Failing after 4s
Build Binaries / build_debian_sid (push) Failing after 4s
Build Binaries / build_ubuntu_focal (push) Failing after 5s
Build Binaries / build_ubuntu_jammy (push) Failing after 4s
Build Binaries / build_ubuntu_mantic (push) Failing after 5s
Build Binaries / build_ubuntu_noble (push) Failing after 5s
Build Binaries / build_android (push) Failing after 5s
Build Binaries / check_spelling (push) Failing after 4s
Build Binaries / check_formatting (push) Successful in 4s
Build Binaries / build_windows (push) Has been cancelled
Build Binaries / build_macos_intel (push) Has been cancelled
Build Binaries / build_macos_arm (push) Has been cancelled
Build Binaries / build_raspios_bullseye_armhf (push) Has been cancelled
Build Binaries / create_full_archive (push) Has been cancelled
Build Binaries / update_nightly_release (push) Has been cancelled
2024-11-09 19:28:34 +01:00
e192cb963b fix MacOS ARM CI
Some checks failed
Build Binaries / build_debian_buster (push) Failing after 5s
Build Binaries / build_debian_bullseye (push) Failing after 4s
Build Binaries / build_debian_sid (push) Failing after 5s
Build Binaries / build_debian_bookworm (push) Failing after 5s
Build Binaries / build_ubuntu_focal (push) Failing after 5s
Build Binaries / build_ubuntu_jammy (push) Failing after 5s
Build Binaries / build_ubuntu_mantic (push) Failing after 4s
Build Binaries / build_ubuntu_noble (push) Failing after 4s
Build Binaries / build_android (push) Failing after 5s
Build Binaries / check_spelling (push) Failing after 4s
Build Binaries / check_formatting (push) Successful in 5s
Build Binaries / build_windows (push) Has been cancelled
Build Binaries / build_macos_intel (push) Has been cancelled
Build Binaries / build_macos_arm (push) Has been cancelled
Build Binaries / build_raspios_bullseye_armhf (push) Has been cancelled
Build Binaries / create_full_archive (push) Has been cancelled
Build Binaries / update_nightly_release (push) Has been cancelled
2024-11-08 00:29:46 +01:00
fe407a2f27 Merge pull request #1521 from AlexandreRouma/new_source_menu
New source menu
2024-11-08 00:20:26 +01:00
6891d0bb0f final bugfixes to the new source menu
Some checks failed
Build Binaries / build_debian_buster (push) Failing after 4s
Build Binaries / build_debian_bullseye (push) Failing after 3s
Build Binaries / build_debian_bookworm (push) Failing after 6s
Build Binaries / build_debian_sid (push) Failing after 5s
Build Binaries / build_ubuntu_focal (push) Failing after 5s
Build Binaries / build_ubuntu_jammy (push) Failing after 4s
Build Binaries / build_ubuntu_mantic (push) Failing after 5s
Build Binaries / build_ubuntu_noble (push) Failing after 5s
Build Binaries / build_android (push) Failing after 5s
Build Binaries / check_spelling (push) Failing after 4s
Build Binaries / check_formatting (push) Successful in 4s
Build Binaries / build_windows (push) Has been cancelled
Build Binaries / build_macos_intel (push) Has been cancelled
Build Binaries / build_macos_arm (push) Has been cancelled
Build Binaries / build_raspios_bullseye_armhf (push) Has been cancelled
Build Binaries / create_full_archive (push) Has been cancelled
Build Binaries / update_nightly_release (push) Has been cancelled
2024-11-07 23:49:15 +01:00
b835d07573 finish custom offset definitions and fix bug in source selection 2024-11-07 17:39:52 +01:00
f205d97b52 Merge pull request #1518 from Oskar-Dudek/patch-3
Some checks failed
Build Binaries / build_windows (push) Waiting to run
Build Binaries / build_macos_intel (push) Waiting to run
Build Binaries / build_macos_arm (push) Waiting to run
Build Binaries / build_raspios_bullseye_armhf (push) Waiting to run
Build Binaries / create_full_archive (push) Blocked by required conditions
Build Binaries / update_nightly_release (push) Blocked by required conditions
Build Binaries / build_debian_buster (push) Failing after 4s
Build Binaries / build_debian_bullseye (push) Failing after 4s
Build Binaries / build_debian_bookworm (push) Failing after 5s
Build Binaries / build_debian_sid (push) Failing after 4s
Build Binaries / build_ubuntu_focal (push) Failing after 4s
Build Binaries / build_ubuntu_jammy (push) Failing after 8s
Build Binaries / build_ubuntu_mantic (push) Failing after 4s
Build Binaries / build_ubuntu_noble (push) Failing after 5s
Build Binaries / build_android (push) Failing after 5s
Build Binaries / check_spelling (push) Failing after 4s
Build Binaries / check_formatting (push) Successful in 4s
Fix ireland.json
2024-11-07 17:36:13 +01:00
628dcfcce0 Fix ireland.json
I used jsonlint.com and i edited it in some places and it says json valid, please can you try this version
2024-11-07 16:26:37 +00:00
d1e7cc56b4 re-disable the M17 decoder module in MacOS ARM nightly builds due to codec2 package bug 2024-11-07 15:02:16 +01:00
334860c963 attempt to enable M17 Decoder on MacOS ARM 2024-11-07 14:53:27 +01:00
69161253e8 source menu upgrade 2024-11-07 14:03:32 +01:00
5ab3428b90 update readme
Some checks failed
Build Binaries / build_windows (push) Waiting to run
Build Binaries / build_macos_intel (push) Waiting to run
Build Binaries / build_macos_arm (push) Waiting to run
Build Binaries / create_full_archive (push) Blocked by required conditions
Build Binaries / build_raspios_bullseye_armhf (push) Waiting to run
Build Binaries / update_nightly_release (push) Blocked by required conditions
Build Binaries / build_debian_buster (push) Failing after 5s
Build Binaries / build_debian_bullseye (push) Failing after 5s
Build Binaries / build_debian_bookworm (push) Failing after 5s
Build Binaries / build_debian_sid (push) Failing after 5s
Build Binaries / build_ubuntu_focal (push) Failing after 4s
Build Binaries / build_ubuntu_jammy (push) Failing after 4s
Build Binaries / build_ubuntu_mantic (push) Failing after 6s
Build Binaries / build_ubuntu_noble (push) Failing after 5s
Build Binaries / build_android (push) Failing after 5s
Build Binaries / check_spelling (push) Failing after 3s
Build Binaries / check_formatting (push) Successful in 4s
2024-11-06 21:27:45 +01:00
7f002f6276 add lower limit to network source samplerate 2024-11-06 20:54:01 +01:00
a728403a3f Merge branch 'master' of https://github.com/AlexandreRouma/SDRPlusPlus 2024-11-06 20:29:58 +01:00
0f1d2da3b7 finish and enable the network source 2024-11-06 20:29:50 +01:00
6d0b65c27f Merge pull request #1515 from Oskar-Dudek/patch-1
Some checks failed
Build Binaries / create_full_archive (push) Blocked by required conditions
Build Binaries / update_nightly_release (push) Blocked by required conditions
Build Binaries / build_windows (push) Waiting to run
Build Binaries / build_macos_intel (push) Waiting to run
Build Binaries / build_macos_arm (push) Waiting to run
Build Binaries / build_raspios_bullseye_armhf (push) Waiting to run
Build Binaries / build_debian_buster (push) Failing after 6s
Build Binaries / build_debian_bullseye (push) Failing after 5s
Build Binaries / build_debian_bookworm (push) Failing after 5s
Build Binaries / build_debian_sid (push) Failing after 5s
Build Binaries / build_ubuntu_focal (push) Failing after 5s
Build Binaries / build_ubuntu_jammy (push) Failing after 5s
Build Binaries / build_ubuntu_mantic (push) Failing after 5s
Build Binaries / build_ubuntu_noble (push) Failing after 5s
Build Binaries / build_android (push) Failing after 5s
Build Binaries / check_spelling (push) Failing after 3s
Build Binaries / check_formatting (push) Successful in 4s
Create ireland.json
2024-11-06 17:51:31 +01:00
f640cdcb6a fix formatting 2024-11-06 17:47:14 +01:00
80a90e13d9 Create ireland.json 2024-11-06 16:37:49 +00:00
3982db73d3 Merge pull request #1501 from bsy0317/master
Some checks failed
Build Binaries / build_debian_buster (push) Failing after 5s
Build Binaries / build_debian_bullseye (push) Failing after 4s
Build Binaries / build_debian_bookworm (push) Failing after 3s
Build Binaries / build_debian_sid (push) Failing after 4s
Build Binaries / build_ubuntu_focal (push) Failing after 4s
Build Binaries / build_ubuntu_jammy (push) Failing after 6s
Build Binaries / build_ubuntu_mantic (push) Failing after 8s
Build Binaries / build_ubuntu_noble (push) Failing after 5s
Build Binaries / build_android (push) Failing after 5s
Build Binaries / check_spelling (push) Failing after 9s
Build Binaries / check_formatting (push) Successful in 5s
Build Binaries / build_windows (push) Has been cancelled
Build Binaries / build_macos_intel (push) Has been cancelled
Build Binaries / build_macos_arm (push) Has been cancelled
Build Binaries / build_raspios_bullseye_armhf (push) Has been cancelled
Build Binaries / create_full_archive (push) Has been cancelled
Build Binaries / update_nightly_release (push) Has been cancelled
Add Republic of Korea BandPlan
2024-10-22 11:03:52 +02:00
bd64f07a20 Update republic-of-korea.json 2024-10-22 17:57:18 +09:00
c9950d9331 fix band plan name 2024-10-22 10:48:39 +02:00
9bc609f4e4 Update republic-of-korea.json
Modify indentation
2024-10-22 17:39:15 +09:00
bcc8e20e66 Update republic-of-korea.json
Corrected typos
2024-10-22 17:34:02 +09:00
b07e828fed Update republic-of-korea.json
Correcting typos
2024-10-22 12:55:10 +09:00
bd24a4a5eb Add Republic of Korea.json
Add Republic of Korea BandPlan.
It's not the Democratic People's Republic of Korea!
2024-10-22 12:39:06 +09:00
fe4a7b32a7 Merge pull request #1496 from AlexandreRouma/bladerf_clock_sel
Some checks failed
Build Binaries / build_debian_buster (push) Failing after 5s
Build Binaries / build_debian_bullseye (push) Failing after 4s
Build Binaries / build_debian_bookworm (push) Failing after 4s
Build Binaries / build_debian_sid (push) Failing after 3s
Build Binaries / build_ubuntu_focal (push) Failing after 4s
Build Binaries / build_ubuntu_jammy (push) Failing after 4s
Build Binaries / build_android (push) Failing after 5s
Build Binaries / check_formatting (push) Successful in 4s
Build Binaries / build_ubuntu_mantic (push) Failing after 4s
Build Binaries / build_ubuntu_noble (push) Failing after 4s
Build Binaries / check_spelling (push) Failing after 4s
Build Binaries / build_windows (push) Has been cancelled
Build Binaries / build_macos_intel (push) Has been cancelled
Build Binaries / build_macos_arm (push) Has been cancelled
Build Binaries / build_raspios_bullseye_armhf (push) Has been cancelled
Build Binaries / create_full_archive (push) Has been cancelled
Build Binaries / update_nightly_release (push) Has been cancelled
add clock selection got bladerf devices
2024-10-17 20:35:52 +02:00
0e1ab29b5d ingore commas in pasted frequencies
Some checks failed
Build Binaries / build_debian_buster (push) Failing after 4s
Build Binaries / build_debian_bullseye (push) Failing after 5s
Build Binaries / build_debian_bookworm (push) Failing after 5s
Build Binaries / build_debian_sid (push) Failing after 4s
Build Binaries / build_ubuntu_focal (push) Failing after 4s
Build Binaries / build_ubuntu_jammy (push) Failing after 4s
Build Binaries / build_ubuntu_mantic (push) Failing after 4s
Build Binaries / build_android (push) Failing after 5s
Build Binaries / check_spelling (push) Failing after 4s
Build Binaries / build_ubuntu_noble (push) Failing after 4s
Build Binaries / check_formatting (push) Successful in 4s
Build Binaries / build_windows (push) Has been cancelled
Build Binaries / build_macos_intel (push) Has been cancelled
Build Binaries / build_macos_arm (push) Has been cancelled
Build Binaries / build_raspios_bullseye_armhf (push) Has been cancelled
Build Binaries / create_full_archive (push) Has been cancelled
Build Binaries / update_nightly_release (push) Has been cancelled
2024-10-16 22:14:12 +02:00
fbbafddd3d fix frequency formatting when copying from frequency selector 2024-10-16 20:48:35 +02:00
1cbc8ec6f5 add copy/paste support to the frequency selector 2024-10-16 18:31:14 +02:00
9f65e3ec71 add clock selection got bladerf devices 2024-10-12 01:48:39 +02:00
08f3a7d201 make the modulation field of a baseband recording 'IQ' instead of 'Unknown'
Some checks failed
Build Binaries / build_debian_buster (push) Failing after 6s
Build Binaries / build_debian_bullseye (push) Failing after 4s
Build Binaries / build_debian_bookworm (push) Failing after 4s
Build Binaries / build_debian_sid (push) Failing after 4s
Build Binaries / build_ubuntu_focal (push) Failing after 4s
Build Binaries / build_ubuntu_jammy (push) Failing after 4s
Build Binaries / build_ubuntu_mantic (push) Failing after 4s
Build Binaries / build_ubuntu_noble (push) Failing after 4s
Build Binaries / build_android (push) Failing after 5s
Build Binaries / check_spelling (push) Failing after 3s
Build Binaries / check_formatting (push) Successful in 4s
Build Binaries / build_raspios_bullseye_armhf (push) Has been cancelled
Build Binaries / create_full_archive (push) Has been cancelled
Build Binaries / update_nightly_release (push) Has been cancelled
Build Binaries / build_windows (push) Has been cancelled
Build Binaries / build_macos_intel (push) Has been cancelled
Build Binaries / build_macos_arm (push) Has been cancelled
2024-10-07 14:39:45 +02:00
9ce62f8885 add whitelist for plutosdr-like devices 2024-10-07 14:10:23 +02:00
caeaa2d46c add kcsdr_source to the readme
Some checks failed
Build Binaries / build_debian_buster (push) Failing after 8s
Build Binaries / build_debian_bullseye (push) Failing after 4s
Build Binaries / build_debian_bookworm (push) Failing after 4s
Build Binaries / build_debian_sid (push) Failing after 4s
Build Binaries / build_ubuntu_focal (push) Failing after 4s
Build Binaries / build_ubuntu_jammy (push) Failing after 4s
Build Binaries / build_ubuntu_mantic (push) Failing after 4s
Build Binaries / build_ubuntu_noble (push) Failing after 6s
Build Binaries / build_android (push) Failing after 7s
Build Binaries / check_spelling (push) Failing after 4s
Build Binaries / check_formatting (push) Successful in 4s
Build Binaries / build_windows (push) Has been cancelled
Build Binaries / build_macos_intel (push) Has been cancelled
Build Binaries / build_macos_arm (push) Has been cancelled
Build Binaries / build_raspios_bullseye_armhf (push) Has been cancelled
Build Binaries / create_full_archive (push) Has been cancelled
Build Binaries / update_nightly_release (push) Has been cancelled
2024-10-02 19:15:13 +02:00
7ae030a3a6 fix fobossdr_source module missing on MacOS as described in #1485 2024-10-02 18:58:48 +02:00
1b27379a3d add beginning of kcsdr source 2024-10-02 18:57:05 +02:00
e52123038e Merge branch 'master' of https://github.com/AlexandreRouma/SDRPlusPlus
Some checks failed
Build Binaries / build_debian_buster (push) Failing after 5s
Build Binaries / build_debian_bullseye (push) Failing after 4s
Build Binaries / build_debian_bookworm (push) Failing after 4s
Build Binaries / build_debian_sid (push) Failing after 4s
Build Binaries / build_ubuntu_focal (push) Failing after 4s
Build Binaries / build_ubuntu_jammy (push) Failing after 4s
Build Binaries / build_ubuntu_mantic (push) Failing after 4s
Build Binaries / build_ubuntu_noble (push) Failing after 4s
Build Binaries / build_android (push) Failing after 5s
Build Binaries / check_spelling (push) Failing after 4s
Build Binaries / check_formatting (push) Successful in 5s
Build Binaries / build_windows (push) Has been cancelled
Build Binaries / build_macos_intel (push) Has been cancelled
Build Binaries / build_macos_arm (push) Has been cancelled
Build Binaries / build_raspios_bullseye_armhf (push) Has been cancelled
Build Binaries / create_full_archive (push) Has been cancelled
Build Binaries / update_nightly_release (push) Has been cancelled
2024-09-28 03:32:14 +02:00
ec8c60111d uncomment lines that copy the fobossdr source module for windows packaging 2024-09-28 03:32:07 +02:00
f61799cf5f Merge pull request #1482 from AlexandreRouma/fobos_test
Enable the FobosSDR source on windows and linux
2024-09-28 02:44:04 +02:00
17eccf5156 enabled fobos source on windows 2024-09-14 15:05:12 +02:00
e835c8dd9a disable fobos source on windows 2024-09-14 15:04:07 +02:00
acb1be121c enable fobossdr source 2024-09-14 14:48:37 +02:00
0fa89614bb disabled problematic fobossdr source 2024-09-14 14:47:10 +02:00
256affd918 fixed fobossdr CI 2024-09-14 02:06:34 +02:00
e80cdbf248 fix CI + fix fobossdr_source cmakelist + prepare for fobos source on windows 2024-09-14 00:18:31 +02:00
75e66226c3 finish fobossdr source + add rigexpert to hardware donor list + fix source module default instantiation 2024-09-13 23:02:30 +02:00
c2f0e756a5 add fobossdr_source module and fix network sink crash when the given hostname is invalid 2024-09-11 21:57:12 +02:00
79dd5bdcbb add beginning of DAB decoder and add missing hardware donors to the credits 2024-09-10 15:33:22 +02:00
6dce28345c add missing stddef includes 2024-08-26 22:37:18 +02:00
fe9ac6c9a1 implemented all user options for harogic devices 2024-08-22 04:36:36 +02:00
bfdfa2b30b add debug logging to the harogic source enumeration function 2024-08-22 02:20:51 +02:00
46e98b9b03 add harogic_source module 2024-08-22 01:52:27 +02:00
e674a73771 removed useless include 2024-08-20 00:32:16 +02:00
118e1fbff0 Add badgesdr source and add logging to spectran source 2024-08-05 22:32:39 +02:00
bcadb36232 fix include issues in dsp library 2024-07-26 23:55:26 +02:00
554ba2f596 add ryfi decoder module 2024-07-24 16:31:29 +02:00
949fde022d fix recorder options not disabled during recording, increase rfnm source dsp frame size and fix long pause when stopping rfnm 2024-07-18 18:10:33 +02:00
123e34d250 fix appliesCh of preferred path in rfnm_source 2024-07-18 16:53:02 +02:00
f1c7010437 add rfnm_source path logging 2024-07-18 16:40:21 +02:00
33a7795de1 fix RFNM source on MacOS 2024-07-18 03:12:38 +02:00
fe7299c18a lots of work on the RFNM source 2024-07-18 02:15:20 +02:00
8a9e0abcc2 fix RFNM source not enabled 2024-07-16 21:01:44 +02:00
13abe4860b fix missing permissions 2024-07-16 20:59:32 +02:00
981592fa19 how many times can someone fuck up a build script 2024-07-16 20:58:25 +02:00
582750f79b fix CI script typo 2024-07-16 20:55:19 +02:00
36f2a083ce More work towards working RFNM CI 2024-07-16 20:53:32 +02:00
d753135a61 fix ARM macos CI build not having RFNM source 2024-07-16 20:45:27 +02:00
07744e5bae add rfnm_source module to linux and MacOS CI 2024-07-16 20:43:53 +02:00
9ec78da7ac rfnm source cleanup 2024-07-16 00:23:06 +02:00
0066994899 add missing files for rfnm source and add it to the default instantiation config 2024-07-15 22:48:27 +02:00
93ab51bf2f fix ci 2024-07-15 20:36:08 +02:00
f9d7d20073 add rfnm_source to windows nightlies 2024-07-15 20:25:53 +02:00
e81db5d85c make text bold so people won't miss it 2024-07-07 00:00:23 +02:00
5c3a66642b Added an idiot-proof warning that the drivers for the SDR you want to use must be installed. I know... shocker... 2024-07-06 23:59:33 +02:00
36492e799a Merge pull request #1418 from Armand31/patch-1
Update france.json
2024-06-26 17:41:53 +02:00
0110dfbef6 Another attempt 2024-06-26 17:19:06 +02:00
0b5a2ff786 Update librtlsdr for windows CI 2024-06-26 17:11:23 +02:00
ce0f1f05ae Attempt to fix the Windows CI builds (fuck you Microsoft) 2024-06-26 16:49:05 +02:00
46a5ff8ac5 Update france.json
Correcting typos
2024-06-10 00:57:42 +02:00
03559b928b Update france.json
Adding the 2 DAB bands and Police band (tetrapol protocol)
2024-06-10 00:26:48 +02:00
206ce6e8c3 fix formatting mistake in pull request... for fucks sake... 2024-06-08 05:33:57 +02:00
d7a1f46af0 Merge pull request #1416 from Armand31/patch-1
Update france.json
2024-06-07 22:37:40 +02:00
89e6e4f7ad Update france.json 2024-06-07 22:13:55 +02:00
6ced9b15c3 Update france.json
Add DVB-T (TNT) band, from 470 to 694 MHz
2024-06-07 21:30:13 +02:00
0de189a7b7 Merge pull request #1413 from ycanerol/master
Add Turkish Bandplan
2024-06-06 19:35:30 +02:00
bb9024fadd disable badgesdr_source module 2024-06-04 22:04:25 +02:00
d1dc20f4e2 fix rfnm device selection 2024-06-04 22:03:39 +02:00
309717b5f8 Add Turkish Bandplan 2024-05-31 01:59:31 +03:00
762444d340 fix version number on Linux, MacOS and Android 2024-05-29 00:56:56 +02:00
18300e8916 switch to SDRplay API v3.15 2024-05-26 22:57:47 +02:00
a93bb9d468 fix source/samplerate selection bugs 2024-05-26 22:27:47 +02:00
ea0362b927 add microtelecom to hardware donor list 2024-05-24 17:06:30 +02:00
ffc642f270 set stage of rfnm source to beta 2024-05-24 01:58:17 +02:00
1b5975f563 Add RFNM to hardware donor list 2024-05-24 01:42:36 +02:00
733dc55723 added missing files 2024-05-24 01:38:24 +02:00
b841180f84 add ubuntu noble build 2024-05-24 01:38:15 +02:00
e99e84e809 add gain slider and FM notch controls to RFNM source$ 2024-05-15 13:01:57 +02:00
7a4281dd76 add rfnm_source module 2024-05-14 22:22:03 +02:00
c89763a989 Merge branch 'master' of https://github.com/AlexandreRouma/SDRPlusPlus 2024-05-04 16:38:52 +02:00
27edc260c9 fix some fft sizes not being saved as described in #1396 2024-05-04 16:38:47 +02:00
2ea7ac496f Merge pull request #1391 from rberaldo/master
Add a bandplan for Brazilian ham bands
2024-05-01 21:13:15 +02:00
314d78d9d2 Add another missing include to the spectran source 2024-04-27 07:00:27 +02:00
4e455e6661 Add missing include in spectran source 2024-04-27 06:53:15 +02:00
58b86fcee5 add brazil.json
Add a bandplan for the Brazilian ham bands inspired in netherlands.json.
I intend to improve and extend on this band plan, including by adding non-ham
bands.
2024-04-26 16:36:06 -03:00
27072e9fe7 version bump to indicate ABI change. modules just need to be recompiled. 2024-04-23 22:46:43 +02:00
da1417b5ab made recorder crash fix more robust 2024-04-22 21:54:01 +02:00
e60eca5d6d fix crash when attempting to record from disabled radio 2024-04-22 21:51:49 +02:00
ccb10bfb9a fix missing virtual destructors as reported in #1386 2024-04-22 18:54:12 +02:00
2813aa7c93 fix some tables not scaled along with the rest of the UI as described in #1382 2024-04-17 01:31:49 +02:00
c61fc400a6 Merge branch 'master' of https://github.com/AlexandreRouma/SDRPlusPlus 2024-04-17 01:20:25 +02:00
779ef7ecf1 fix memcpy erroneously used on overlapping buffer regions as described in #1379 2024-04-17 01:20:17 +02:00
6fdab5e0c2 undo problematic commit 2024-04-15 06:23:39 +02:00
ea08fac32e handle deprecation of rotator in volk 3.1.0 2024-04-14 03:41:00 +02:00
632a4eebab Deprecated SoapySDR support 2024-04-10 22:09:07 +02:00
e118598f57 Fix waterfall size related crash described in #1230 2024-04-10 18:28:59 +02:00
a2d49b2f87 update development status of various modules in the readme 2024-04-08 17:17:16 +02:00
38abfc715e potential fix for #677 2024-04-08 17:01:27 +02:00
07eebd7018 potential fix for #677 2024-04-08 16:59:05 +02:00
d12021fc2f potential fix for #1361 2024-04-08 16:37:03 +02:00
db1682a2ac fix #1034 2024-04-08 16:21:33 +02:00
fdfb1dbf5e remove useless menu item in pager decoder 2024-04-05 20:15:21 +02:00
17f698577f disable FLEX protocol from pager module since it's not implemented and add setBaudrate function 2024-04-05 19:50:14 +02:00
8eaa987d90 fix spectran http source samplerate detection 2024-04-04 19:42:58 +02:00
12f7efed32 Switch spectran http source module to use the remoteconfig endpoint as per #1354 2024-04-04 19:25:02 +02:00
065a5b4c40 add audio source to readme 2024-04-01 19:56:36 +02:00
70f90fd570 MacOS CI workaround (I hate you microsoft) 2024-03-31 23:27:07 +02:00
a2054ad780 fix #1367 2024-03-31 23:00:50 +02:00
e1c48e9a1f try to fix macos CI again (fix your shit microsoft...) 2024-03-26 00:30:31 +01:00
867a8680e1 another MacOS CI fix attempt (this is getting ridiculous, fix your shit github) 2024-03-22 19:14:17 +01:00
bf831e3a50 attempt to fix the MacOS CI yet again 2024-03-22 18:48:27 +01:00
eb8b852ea6 fix macos build 2024-03-22 02:06:11 +01:00
67520ea45e fix linux CI 2024-03-20 01:58:16 +01:00
a3f0ad238a Merge branch 'master' of https://github.com/AlexandreRouma/SDRPlusPlus 2024-03-20 01:38:44 +01:00
feb9789896 Update sdrplay api version for nightlies to 3.14.0 2024-03-20 01:38:36 +01:00
3a5096092d Merge pull request #1338 from LEDFlighter/master
Update germany.json
2024-02-24 22:33:57 +01:00
9dc0196a16 Update germany.json
Added the Name after a ","
recovered the "author_url" from the original author (I don't have an URL to refer to)
2024-02-24 12:56:33 +01:00
b1603f0e72 Update germany.json
Updated and extended the German bandplan
2024-02-23 23:26:36 +01:00
09467439e3 Update germany.json
Updated and extended the German bandplan
2024-02-23 23:21:42 +01:00
021928bbda fix show/hide waterfall keybind not working with the Display menu hidden 2024-02-21 21:59:55 +01:00
7c933d5103 fix typo mentioned in #174 2024-02-21 18:47:50 +01:00
a987c112a3 fix crash when USRP has two frontends named the same 2024-02-17 17:37:37 +01:00
f1339f08cf add workaround for uhd bug reporting same device twice 2024-02-17 06:30:06 +01:00
650a61930c fix SDR++ server crash at high samplerates #1326 2024-02-13 18:39:11 +01:00
61ffb3e6bf revert pager decoder to traditional clock recovery 2024-02-13 16:27:54 +01:00
9ab3c97c44 don't include rc file on platforms other than windows 2024-02-13 16:18:25 +01:00
edc08ddc08 more progress on the network source 2024-02-13 16:17:17 +01:00
95052c34ff more work on network source and syntax cleanup in iq exporter 2024-02-13 03:11:37 +01:00
34171d4edc fix windows CI 2024-02-12 23:24:00 +01:00
726e1069bf fix wrong mode name in rigctl server as described in #1327 2024-02-12 22:46:03 +01:00
61c14bab48 fix iq_exporter module crashing when removed in the case it's disabled and in baseband mode 2024-02-12 22:43:16 +01:00
01ab1831e8 more progress on the network source 2024-02-12 22:07:17 +01:00
2b752bb267 disable M17 decoder on M1 CI 2024-02-11 19:57:13 +01:00
5204cfec56 disable perseus source on macos M1 2024-02-11 19:41:49 +01:00
c616892eda attempt to add MacOS M1 CI 2024-02-11 19:36:26 +01:00
5f23c1f312 added new patrons and hardware donors 2024-02-10 20:59:37 +01:00
5e0c4449f8 switched back ATV demod to black and white 2024-02-09 22:13:25 +01:00
cd3e2b6c05 fix network source build on windows 2024-02-08 21:45:58 +01:00
ba5380f9bb started work on the network source 2024-02-08 15:01:11 +01:00
daf0f8c159 more work on new clock recovery 2024-02-08 14:17:35 +01:00
63aa45de9e beginning of new pager clock recovery 2024-02-08 09:03:46 +01:00
c0a84f8703 pocsag menu cleanup 2024-02-06 22:16:21 +01:00
f66f2c25e1 improve pocsag alpha decoding 2024-02-05 16:46:08 +01:00
bddfe5396f fix iq exporter config name 2024-02-03 01:43:16 +01:00
d5fa76df06 removed archived decoder from readme 2024-02-02 23:15:58 +01:00
8029cef4da promote iq_exporter module to Beta status 2024-02-02 23:12:44 +01:00
d84bb9bdec fix module not enabled 2024-02-02 23:07:13 +01:00
a0ff745b63 fix windows CI missing module 2024-02-02 23:06:03 +01:00
a08d2a0f85 more work on debugging the pager decoder 2024-02-02 22:52:19 +01:00
7ab743d05b finish iq exporter and fix network lib send not closing socket on error 2024-02-02 04:11:29 +01:00
122e67ef65 finished VFO mode of the iq exporter 2024-02-01 21:38:13 +01:00
fbeb2195da fix make_windows_package.ps1 issue 2024-02-01 18:54:18 +01:00
1f2b50c9bb add beginning of IQ exporter module 2024-02-01 18:36:25 +01:00
f486c657c1 fix cmake to prevent always enabling the pager decoder 2024-02-01 01:12:51 +01:00
f1f04d59fe add missing files 2024-02-01 00:55:36 +01:00
ef42ea01d8 add flex decoder menu entry and fix pocsag decoding 2024-02-01 00:55:17 +01:00
3fc893568a beginning of pager decoder 2024-01-31 23:34:40 +01:00
4b6835141e fix low PI RDS callsign decoding 2024-01-30 22:18:18 +01:00
a9e59bdf3c removed useless logging again 2024-01-30 00:01:10 +01:00
f0bd17f9f4 fix north americal RDS callsign decoding 2024-01-29 23:57:23 +01:00
a8ed213ed3 remove useless debug logging 2024-01-29 21:49:13 +01:00
f8183739f7 add rds region selection 2024-01-29 21:28:43 +01:00
120745de19 add rds program type name decoding 2024-01-29 21:00:23 +01:00
05ab17add3 Merge pull request #1307 from AlexandreRouma/new_rds
New rds demod and decode
2024-01-29 19:43:06 +01:00
2ef8ee3629 disable rds symbol diagram data stream when not visible 2024-01-29 19:15:45 +01:00
14cb839863 clean up rds code and fix use before init 2024-01-29 18:43:46 +01:00
9501371c6c Merge pull request #1302 from AlexandreRouma/master
keep new_rds branch updated
2024-01-29 01:45:32 +01:00
ff23d7e43f fix warnings 2024-01-29 01:40:20 +01:00
f541328e5c Merge pull request #1301 from AlexandreRouma/new_plutosdr_enum
New plutosdr enum
2024-01-28 23:39:33 +01:00
be8edbfa9e revamp sdr++ server source networking code 2024-01-28 21:46:54 +01:00
11a7c382e8 update more github action versions 2024-01-28 17:28:07 +01:00
54276177ae update github action version 2024-01-28 17:25:27 +01:00
bc77bab45f improved plutosdr device naming 2024-01-28 17:23:18 +01:00
97d0a07ec7 fix plutosdr commit persistence 2024-01-28 15:26:34 +01:00
6b5de78e80 fix plutosdr source not updating samplerate on select 2024-01-28 14:39:01 +01:00
1cd8c2510a fix plutosdr source error checking 2024-01-28 14:38:36 +01:00
32cbd726fd implement enumeration and settings for plutosdr source 2024-01-28 02:16:20 +01:00
175992b081 add android workaround 2024-01-28 00:25:46 +01:00
31c9e5767e beginning of PlutoSDR context enumeration 2024-01-28 00:03:04 +01:00
e6a02a3944 fix bad plutosdr bandwidth selection at very high samplerates 2024-01-27 22:52:11 +01:00
00e6832055 add plutosdr bandwidth selection for #563 2024-01-27 22:49:39 +01:00
bc8baca190 clean up plutosdr source code 2024-01-27 21:35:13 +01:00
08e75b6d14 fix gain mode selection not always applying 2024-01-27 21:30:06 +01:00
e9ec79f6ef modernise gain mode selection for plutosdr 2024-01-27 21:29:44 +01:00
cd996292bc revamp plutosdr samplerate selection code 2024-01-27 21:12:26 +01:00
06b7ad5c98 remove old useless debug code from audio sink 2024-01-27 16:34:54 +01:00
38a95b4011 update SDRplay API in MacOS CI 2024-01-26 19:31:32 +01:00
f6052d913a bump version of updated modules 2024-01-26 19:00:36 +01:00
2b00370cf3 Merge branch 'master' of https://github.com/AlexandreRouma/SDRPlusPlus 2024-01-26 18:47:18 +01:00
09f4071803 Switch SDRplay API in Linux nightly builds to version 3.12 2024-01-26 18:47:13 +01:00
e61ef29e0f Merge pull request #1292 from daviderud/aligned_master
additions and corrections to NL band plan
2024-01-26 17:56:54 +01:00
eb36f86d41 added missing include 2024-01-26 17:21:51 +01:00
29889a289f Merge branch 'master' of https://github.com/AlexandreRouma/SDRPlusPlus 2024-01-26 16:57:19 +01:00
859af77bd3 revamp RFspace source to use new networking library and fix buffering 2024-01-26 16:57:11 +01:00
0a3d1de02f removed tabs and unnecessary pipes 2024-01-26 07:43:01 +01:00
db3fbd2975 update issue template to reflect that fact that filling it out is not optional 2024-01-26 01:40:17 +01:00
f5adc7c587 fix hermes lite buffering 2024-01-25 23:28:03 +01:00
255988ee46 fix hermes lite enumeration issues and fix copy paste fail in network library 2024-01-25 22:27:59 +01:00
68bf2fc16f fix bad network lib broadcast implementation 2024-01-25 21:34:13 +01:00
3aa167701e fix networking library to allow multicast 2024-01-25 20:27:04 +01:00
97c1a132a5 move zoom waterfall's zoom function in the cpp file to avoid annoying recomps 2024-01-25 19:48:04 +01:00
118e56897c Add ubuntu mantic CI build 2024-01-25 15:41:23 +01:00
af8c085d43 switch osx to macos 2024-01-24 18:14:29 +01:00
708f74e179 additions and corrections 2024-01-24 06:14:00 +01:00
eab4264604 Merge pull request #1291 from AlexandreRouma/citest
Allow MacOS build to run on Catalina and newer
2024-01-22 11:32:25 -08:00
4b77d8c395 prepare for merge back part 2, electric boogaloo 2024-01-22 20:31:18 +01:00
854ed89b82 prepare for merge back 2024-01-22 20:30:53 +01:00
27ab5bf3c1 Fix exceptions referenced in #1287 2024-01-22 19:46:01 +01:00
159f59b858 fix return warning for #1234 2024-01-22 19:34:56 +01:00
93cafe7109 fix typo referenced in #1083 2024-01-22 19:22:26 +01:00
74ae8a45d9 fix incorrect formatting again for #1288 2024-01-22 18:17:23 +01:00
691216a298 fix incorrect formatting #1288 this time in the right branch... 2024-01-22 17:31:09 +01:00
3e58d4ba31 fix missing return statement 2024-01-22 02:10:48 +01:00
86dcec7495 Merge pull request #1284 from hzeller/20240121-adapt-rtaudio
Make compatible with rtaudio API 5 and 6.
2024-01-21 16:31:31 -08:00
5a003e99d2 Address review comments. 2024-01-21 15:36:41 -08:00
f197cf6bd9 Fix styling in the other file 2024-01-21 23:49:23 +01:00
8cefeadbd4 Fix styling, modern computers can display more than 40 columns 2024-01-21 23:48:04 +01:00
23ae66151b Make compatible with rtaudio API 5 and 6.
Recent rtaudio changed the API to not throw exceptions anymore and
also have DeviceIDs not queried by index but IDs that are provided
separately ( https://github.com/thestk/rtaudio/releases ).

Adapt the code-base to be compatible with the old and the new API
as we have to exepect that in a transition period both APIs are
common on various build platforms.
2024-01-21 14:37:30 -08:00
fa76b4e865 Made the contributing policy more clear 2024-01-21 20:19:46 +01:00
5e195a0d43 testing something for macos (do not use this CI build) 2024-01-19 20:53:25 +01:00
5e299d9d23 testing something silly 2 2024-01-19 20:01:05 +01:00
fd5813df6d testing something silly 2024-01-19 19:43:31 +01:00
eabb842b6b switched MacOS CI to debug mode 2024-01-19 19:11:01 +01:00
5a1945f779 allow running code on older macos version (test) 2024-01-17 07:07:24 +01:00
052167962d fix the rtlsdr source on android again 2024-01-17 06:52:08 +01:00
6fc41a81a7 fix build on android due to new librtlsdr function name 2024-01-17 06:41:25 +01:00
e710b6c6dc Merge branch 'master' of https://github.com/AlexandreRouma/SDRPlusPlus 2024-01-17 06:29:41 +01:00
a91434c5fe fix windows CI (hopefully) and rebuild with Android BlogV4 support 2024-01-17 06:28:16 +01:00
193580caf3 Merge pull request #1270 from AlexandreRouma/master
merge
2024-01-08 06:18:00 +01:00
ead2ac6128 Merge pull request #1267 from clouserw/readme-fix
add additional library to debian install instructions
2024-01-05 00:20:29 +01:00
505cbb0ba2 add additional library to debian install instructions 2024-01-04 14:01:00 -08:00
b1030cbdfb Implement #1260 2023-12-27 03:53:43 +01:00
f3c5b2c31f Fixed #1259 2023-12-26 23:10:44 +01:00
2432390600 Completely redid the RDS demod 2023-12-13 23:25:46 +01:00
794d6ff5ac clean up 2023-10-29 02:40:34 +01:00
4803271115 fix #1212 2023-10-29 02:27:19 +01:00
78daed7879 Implemented #1205 2023-10-11 21:50:23 +02:00
5f297b1a69 undid the oopsie 2023-10-10 15:21:55 +02:00
7c5d4226eb removed MacOS CI since it required payment (ew...) 2023-10-09 22:43:39 +02:00
ec086ebbdf attempt at fixing M1 ci 2023-10-09 22:42:07 +02:00
d10d420467 added MacOS M1 CI 2023-10-02 23:57:06 +02:00
5bf989f49d fixed android build 2023-09-29 15:35:48 +02:00
4b3b6976d6 removed rpi install script since it is not to be used 2023-09-29 14:52:30 +02:00
55ddd383d2 Fix #1199 2023-09-29 14:42:45 +02:00
a043ab2dd3 Merge pull request #1185 from daviderud/master
Netherlands bandplan and readme correction
2023-09-14 09:58:58 +02:00
d270e1c5e8 Merge branch 'master' of https://github.com/daviderud/SDRPlusPlus 2023-09-14 05:53:25 +02:00
e41f24a95e first version 2023-09-14 05:50:53 +02:00
766b3db363 added clarification and correction 2023-09-14 05:43:00 +02:00
0632342bb7 fixed MacOS packaging 2023-09-13 05:14:07 +02:00
27b07ed0e8 Merge pull request #1163 from theverygaming/master
fixed buffer overflow in file source
2023-09-13 03:43:45 +02:00
a824c83848 Update main.cpp 2023-09-13 03:16:12 +02:00
0e50ee0e67 Update main.cpp 2023-09-13 02:51:44 +02:00
a55d1d9c06 Merge pull request #1179 from isorochan/master
Fix typo in fastAmplitude()
2023-09-07 20:05:24 +02:00
97187b790f Fix typo in fastAmplitude() 2023-09-07 17:27:34 +03:00
9c1361a8a9 Added radio mode info in the recorder and fixed horrible code in the rigctl_server module 2023-09-06 05:38:00 +02:00
4d0d14856b added support for RTL-SDR v4 on MacOS 2023-09-06 04:12:04 +02:00
365ab2325e MacOS CI fix 2023-09-06 03:39:12 +02:00
4da7e686f3 Merge branch 'master' of https://github.com/AlexandreRouma/SDRPlusPlus 2023-09-04 22:19:59 +02:00
c1d9ab64f8 fixed CI 2023-09-04 22:19:51 +02:00
ea33135bf1 Merge pull request #1174 from Bastiti/master
Add 8m - Amateur to the Belgian Bandplan
2023-09-04 15:20:54 +02:00
2081384905 Update belgium.json
https://www.ibpt.be/consommateurs/publication/decision-du-29-aout-2023-concernant-l-attribution-du-spectre-40.660-mhz---40.690-mhz-a-des-stations-de-radiocommunications-privees-dinstruction-individuelle-dintercommunication-technique-et-detudes-utilisees-par-des-radioamateurs
2023-09-04 14:47:13 +02:00
6b31134af2 do not play file when samplerate == 0 2023-08-27 13:28:21 +02:00
99d2786c25 Merge pull request #1169 from nmaster2042/master
Update france.json
2023-08-26 16:07:07 +02:00
320f4459ed Update france.json
Change France Band plan 11m band high limit to 27,410 Mhz, see https://www.legifrance.gouv.fr/loda/article_lc/LEGIARTI000006430657/2020-10-31
2023-08-26 13:21:30 +02:00
de5816f79f Merge pull request #1160 from themeadery/usa-bandplan
Update usa.json bandplan with MURS frequencies
2023-08-07 07:40:49 +02:00
7b9c01ec73 fixed buffer overflow in file source 2023-08-06 04:02:51 +02:00
f06eccd97c Merge pull request #1161 from Manawyrm/manawyrm-bandplan
Update name in bandplan and contributors list
2023-08-05 00:03:25 +02:00
88baa8a48e Update name in bandplan and contributors list 2023-08-04 22:50:12 +02:00
b436fd0745 Update usa.json
Added MURS frequencies
2023-08-03 10:01:48 -07:00
6fa4299136 fixed bookworm build 2023-07-24 00:54:17 +02:00
220dcbcc76 added debian bookworm nightly 2023-07-24 00:05:25 +02:00
15ad065feb Merge pull request #1131 from rmdlv/patch-1
Fixed russia.json
2023-07-11 01:14:04 +02:00
dddf84510e Fixed russia.json
Source - https://digital.gov.ru/ru/documents/3634/
2023-07-10 21:18:33 +08:00
acd9ad9781 Merge branch 'master' of https://github.com/AlexandreRouma/SDRPlusPlus 2023-07-10 04:41:41 +02:00
168e28cc44 added SNR meter smoothing 2023-07-10 04:41:34 +02:00
3b9867c1d7 Merge pull request #1104 from jj1bdx/jj1bdx-rigctl-get_powerstat-fix
rigctl_server: Add answering code for rigctl \get_powerstat
2023-07-09 18:53:40 +02:00
ff7ef78b8f Merge pull request #1114 from bvernoux/master
Workaround for RtAudio Exception when no Input are connected on Input MIC on some PC
2023-07-02 18:00:46 +02:00
87add9ad83 Fix formatting 2023-07-02 17:03:52 +02:00
6cd09f9b60 Workaround for RtAudio Exception when no Input are connected on MIC IN on some computer
Issue reproduced with Windows11 Pro + ROG CROSSHAIR X670E HERO
Workaround for RtAudio just add try/catch and log the error but allow to start SDR++
2023-07-02 16:44:47 +02:00
8d05c1e181 bugfix 2023-06-30 01:36:28 +02:00
1c081cad78 added OQPSK mode to the meteor demodulator 2023-06-29 01:19:15 +02:00
aa929a1e79 Add answering code for rigctl \get_powerstat
* Answer "1" (Power is ON) to \get_powerstat inquiry
2023-06-25 13:51:51 +09:00
5acdab0d22 Instantiated the perseus source by default and perseus on raspberrypi 2023-06-10 21:48:02 +02:00
3e3846daa1 another fix 2023-06-10 21:17:17 +02:00
47617e1acd trying again, powershell belongs in the trash 2023-06-10 20:37:38 +02:00
1df51020aa hopefully last windows CI fix 2023-06-10 20:22:32 +02:00
aa1fd9e573 enabled perseus-sdr build on windows 2023-06-10 19:24:40 +02:00
21816fb438 maybe CI fix 2023-06-10 03:56:46 +02:00
3a06612ff5 fixed missing autoconf on macos 2023-05-24 03:09:35 +02:00
a53bf05ed3 and another one... 2023-05-24 02:55:37 +02:00
78c57db116 I hate autotools so much 2023-05-24 02:52:57 +02:00
c16281f68a hopefully last fix... 2023-05-24 02:49:22 +02:00
32c580ba57 another fix 2023-05-24 02:47:04 +02:00
664b5d85e2 fixed again 2023-05-24 02:43:37 +02:00
6bcb62bfb2 fixed ci 2023-05-24 02:40:23 +02:00
0e7c754b8b Enabled perseus build on all unix 2023-05-24 02:32:27 +02:00
71327cd695 fixed driver download link 2023-05-17 18:37:21 +02:00
f296730302 fixed recorder frequency bug with multivfo 2023-05-17 03:58:49 +02:00
b89fdba433 Update united-kingdom.json 2023-05-02 21:15:02 +02:00
2c3b522787 Update contributing.md 2023-04-24 03:49:30 +02:00
528763d10e disabled spectran http sampleFreq autodetection 2023-04-22 00:27:31 +02:00
582aeed640 Added samplerate and center frequency tracking to http spectran source 2023-04-20 08:32:31 +02:00
9c0b57a036 Work on the spectran HTTP source 2023-04-19 02:25:44 +02:00
604f95fd96 Added perseus source (still a bit buggy) 2023-04-14 22:12:13 +02:00
c892e51000 Added Archlinux disclaimer 2023-04-10 22:53:41 +02:00
3336ae4aa5 added rigctl client to the macos bundle 2023-04-03 20:50:11 +02:00
190cea8e4e added missing include 2023-04-03 19:44:47 +02:00
13a268a3e1 Update module.cpp 2023-04-01 19:10:47 +02:00
800a8b22c7 fixed fft smoothing not set on startup when enabled 2023-03-31 01:38:14 +02:00
2eb030dd83 Added stdexcept 2023-03-30 19:55:54 +02:00
365fe1930c Update smgui.h 2023-03-30 19:17:15 +02:00
342a677c3f Merge pull request #1001 from konung-yaropolk/master
Added new colormaps: Vivid, Smoke and Temper
2023-03-30 08:41:58 +02:00
b5c41bcb3a added missing argument to macos instructions 2023-03-29 22:04:51 +02:00
f578adceef more work 2023-03-27 17:26:37 +02:00
a9f882e5b1 Fixed halfed volume with HPF on 2023-03-25 21:22:40 +01:00
3420808f3a added high-pass filter in NFM mode 2023-03-25 19:09:27 +01:00
d3d245992d Merge pull request #1021 from sergeyvfx/fix_start_crash
Fix crash in LimeSDR start when the device is disconnected
2023-03-23 23:20:49 +01:00
9a3414b847 Made the code more useful to the user
maybe just yeeting out of the start function with no indication to the user is a bad idea?
2023-03-23 23:19:05 +01:00
90c26f8c1b Fix crash in LimeSDR start when the device is disconnected
This fixes crash when a device which was enumerated on the
application startup gets disconnected prior to the attempt
to start the radio.

The check is done after the existing work around for the
LimeSuite bug. The idea is to give it the best possible
chance for the radio to start.

Possibly, the check needs needs to happen in the second
LMS_Open() but ideally this needs to be verified against
the original workaround scenario.
2023-03-23 22:36:44 +01:00
ec4dc6cc9e fix 2023-03-22 20:47:05 +01:00
93b28d1495 M17 decoder fix 2023-03-22 18:38:15 +01:00
84291deaf6 Merge branch 'master' of https://github.com/AlexandreRouma/SDRPlusPlus 2023-03-22 18:20:38 +01:00
21e0696917 readme update 2023-03-22 18:20:34 +01:00
19247ef4f2 Merge pull request #1013 from sergeyvfx/fix_empty_limesdr_crash
Fix crash starting LimeSDR source without device
2023-03-14 23:00:13 +01:00
1e5601e773 Better check
Need to check if a device is actually selected, not just if there is one to select
2023-03-14 22:17:47 +01:00
ae1fd87f02 Fix crash starting LimeSDR source without device
This change fixes crash when a LimeSDR source is started without
an actual device selected.
2023-03-14 21:37:22 +01:00
ab2aee316c Merge pull request #1012 from Bastiti/patch-1
Belgian bandplan
2023-03-14 11:33:44 +01:00
109374277e Belgian bandplan
Added the amateur radio band as specified in the 2019
https://www.ibpt.be/file/cc73d96153bbd5448a56f19d925d05b1379c7f21/821514ac30e14d85dfdbe6747d1b82af9fd4da4c/2019-05-24_ram-decision.pdf

Broadcast band added from BIPT/IBPT Bandplanning.

According to Belgian laws, you're not allowed to receive anything execpt Ham Radio, CB, PMR446 or Broadcasting.
2023-03-14 09:08:43 +01:00
692436f6e4 Merge pull request #1010 from hb9fxq/patch-3
Update readme.md
2023-03-13 18:13:17 +01:00
eccb715d0c Update readme.md 2023-03-13 17:55:44 +01:00
f6f074e0c7 added missing patrons 2023-03-13 17:29:37 +01:00
50a77a7e60 Added a PR template 2023-03-11 13:52:37 +01:00
a4f3c92a03 added missing include to legacy network lib 2023-03-10 17:59:13 +01:00
37920b6476 adjustments 2023-03-10 00:45:56 +01:00
314b8bf72d Const correctness fix for optionlist 2023-03-09 15:14:33 +01:00
5f0858bab2 Removed logging from the DSP lib 2023-03-09 08:56:48 +01:00
007761a027 made it a bit cleaner 2023-03-08 19:49:23 +01:00
801f1be6b2 Hopefully a fix for the rfspace SDR-IP 2023-03-08 19:46:14 +01:00
9cc793e328 bugfix 2023-03-08 19:39:15 +01:00
1e01313612 Update vivid.json 2023-03-08 00:26:26 -06:00
4283cacae6 fixed build for volk 1.x 2023-03-02 15:19:16 +01:00
6f9dacdd53 Added back 'ignore silence' option in the recorder 2023-03-02 14:47:02 +01:00
e64c343645 Update vivid.json 2023-03-01 02:24:08 -06:00
kek
b9effce7d6 Added new colormap: Temper Colors 2023-02-26 05:19:34 -06:00
kek
45a13227de new file: root/res/colormaps/smoke.json
new file:   root/res/colormaps/vivid.json
2023-02-26 04:35:55 -06:00
5b47f900a6 more android bullshit 2023-02-25 20:59:12 +01:00
82fd3732a9 hopefully the last fix for android, this is getting annoying 2023-02-25 20:33:03 +01:00
8d6ed17e01 more android fixes 2023-02-25 20:19:34 +01:00
aa2071e2df more android fixes, I hate this OS so much 2023-02-25 20:00:04 +01:00
b32618708f fixed android one more time 2023-02-25 19:45:13 +01:00
ac875aee3b bugfix macos and android 2023-02-25 19:30:58 +01:00
df83d65271 changes 2023-02-25 18:14:35 +01:00
7723d15e8f Switched to a custom logging lib instead of that spdlog junk 2023-02-25 18:12:34 +01:00
a8cbc37e0d removed unecessary include 2023-02-23 10:05:04 +01:00
0d149f997f CMake install prefix bugfix when generating several times 2023-02-23 09:31:27 +01:00
7e80bbd02c added missing rigctl client 2023-02-22 21:45:19 +01:00
edb4ac45b2 more work on the rigctl module but removed tracking for now 2023-02-22 20:55:23 +01:00
63416fe93a added missing files 2023-02-21 20:46:28 +01:00
0fedcf8745 Added audio source 2023-02-21 19:38:31 +01:00
fe821fb830 Removed debugging junk 2023-02-19 18:58:39 +01:00
ea882cb285 Changed M17 modulation parameters 2023-02-19 18:54:33 +01:00
13e81c9f6b attempt at enabling the plutosdr in android build 2023-02-18 20:22:29 +01:00
290c989451 attempt at re-enabling M17 on android 2023-02-18 18:22:53 +01:00
b7ca19583a the macos CI is wasting more of my time again 2023-02-18 16:56:41 +01:00
1f97e9e10b Improved detection of M17 frames to avoid spurious decodes 2023-02-18 16:08:57 +01:00
93e985ab54 bugfix 2023-02-16 07:59:01 +01:00
8f972ee0b2 Added proper cmake debug support 2023-02-15 20:37:13 +01:00
570b8dbd7c Merge pull request #991 from AlexandreRouma/better_cmake
Better cmake
2023-02-15 19:34:41 +01:00
c0c5b1186c Fixed bug with audio sink 2023-02-15 17:28:02 +01:00
d5a9538d0c bugfix 2023-02-15 15:39:34 +01:00
7cfc30ee6e new cmake stuff 2023-02-14 16:25:05 +01:00
a1b6cbb38a Addded label to bandwidth selection of SDRplay Source 2023-02-13 09:38:26 +01:00
a3b13e572b Merge pull request #946 from CircuitChaos/fix-kg-sstv-name
Fixed KG SSTV (KG-STV) decoder name
2023-02-12 16:32:18 +01:00
16eaa0cf59 Fixed network library which also fixes RTL-TCP source 2023-02-09 16:55:37 +01:00
fd65984762 fixed build again 2023-02-08 01:40:44 +01:00
7094368113 fixed build 2023-02-08 01:19:11 +01:00
208851ebc5 cleanup 2023-02-07 12:04:29 +01:00
0a6fbdb393 Merge branch 'master' of https://github.com/AlexandreRouma/SDRPlusPlus 2023-02-07 08:33:54 +01:00
3451edb131 refactoring 2023-02-07 08:33:47 +01:00
bbf0c17cb8 Fixed missing include 2023-02-03 04:23:43 +01:00
7758c40bd7 Added missing files 2023-02-03 02:38:19 +01:00
8a2d0fe56b Recorder bugfix + rewrote RTL-TCP source to use new network lib 2023-02-03 02:38:08 +01:00
31ff7f3224 fixed build 2023-01-26 03:05:32 +01:00
e59d804b31 more work 2023-01-26 02:55:11 +01:00
66bbc93535 cleanup 2023-01-26 02:54:29 +01:00
ab5d7a73c1 USRP samplerate selection fix attempt 2023-01-21 00:16:31 +01:00
7a1a37fbf6 Fixed broken bandwidth options 2023-01-20 23:43:46 +01:00
a58683f748 Merge branch 'master' of https://github.com/AlexandreRouma/SDRPlusPlus 2023-01-20 17:52:42 +01:00
d020dcc4a3 Added bandwidth and clock selection to USRP source 2023-01-20 17:52:35 +01:00
691ab585e2 Merge pull request #964 from KentuckyFriedData/patch-3
Fix wrong target name
2023-01-13 22:44:28 +01:00
bad8ecba49 Fixed needless config saves 2023-01-13 22:43:42 +01:00
d21a6af5a9 Fix wrong target name 2023-01-13 13:05:01 -08:00
a53dc1a6ae Merge branch 'master' of https://github.com/AlexandreRouma/SDRPlusPlus 2023-01-13 17:11:23 +01:00
b3222003b1 bugfixes 2023-01-13 17:11:16 +01:00
e3914ebdc6 more macos CI fixes 2023-01-09 16:32:23 +01:00
1ae1cc0e77 Fixed missing samplerate update in new recorder 2023-01-09 05:51:58 +01:00
55db98d1df Update readme.md 2023-01-06 00:30:32 +01:00
90ce82190b updated readme 2023-01-06 00:29:33 +01:00
a1cbc69a65 temporarily removed the ignore silence option since it doesn't work properly 2023-01-02 23:01:45 +01:00
ffefd9cce8 fixed stereo option not persistent and added todos for ignore silence 2023-01-02 21:00:15 +01:00
4d890e78ed MacOS is wasting so much of my time omfg 2023-01-02 18:23:55 +01:00
4eabc829fa even more fixes 2023-01-02 18:06:49 +01:00
ee79bf9f81 more macos ci fix 2023-01-02 17:54:05 +01:00
447d0e969e MacOS CI fix 2023-01-02 17:16:12 +01:00
637d683c0a Merge pull request #920 from AlexandreRouma/new_recorder
New recorder
2023-01-02 02:37:15 +01:00
5773419257 added missing include 2023-01-02 02:09:41 +01:00
385b34a0a1 bugfix 2023-01-02 01:24:30 +01:00
8771e4bf09 final fixes 2023-01-01 03:20:49 +01:00
0ba0a3ab97 Fixed KG SSTV (KG-STV) decoder name 2022-12-26 02:57:57 +01:00
9b33d8d63b Merge branch 'master' of https://github.com/AlexandreRouma/SDRPlusPlus 2022-12-12 00:10:56 +01:00
bd99210fd3 more work on the spectran 2022-12-12 00:10:39 +01:00
a426f7b3ab Merge pull request #934 from RAD750/mmds_converter
Added MMDS converter offset preset
2022-12-10 20:15:44 +01:00
3d4c7550be fixed 2022-12-10 20:11:49 +01:00
d14fc3805c Added MMDS converter offset preset 2022-12-10 13:43:14 +01:00
ea23c44266 More work on the spectran source 2022-12-06 22:28:58 +01:00
fa2e13f3ea more work on the spectran 2022-12-06 20:54:23 +01:00
643d47fe47 stream fixes 2022-12-06 16:10:11 +01:00
5eba556605 Merge pull request #931 from hb9fxq/patch-2
Update spectran_source CMakeLists.txt
2022-12-06 14:53:09 +01:00
5c690c9753 more work 2022-12-06 14:52:42 +01:00
643cad3581 Update spectran_source CMakeLists.txt 2022-12-06 14:33:18 +01:00
bd854b590e Work on spectran sources 2022-12-06 08:23:58 +01:00
f163e926c7 spectran http source + hermes source cleanup 2022-12-04 02:10:34 +01:00
d069fb3af8 more fixes 2022-11-25 20:32:12 +01:00
f97ca9ac05 almost done with the new recorder 2022-11-23 10:22:29 +01:00
b104e82874 Merge pull request #915 from jeffrizzo/riz-usa-bandplan
Correct USA amateur allocations below 2GHz
2022-11-23 10:03:27 +01:00
3520424208 Update usa.json 2022-11-23 08:57:50 +01:00
9ae6a74408 fixed CI again 2022-11-22 13:27:56 +01:00
5eb42b61e9 disabled automatic CI for pull requests 2022-11-22 13:16:40 +01:00
a1259d7d32 undid it, it was stupid 2022-11-22 12:41:16 +01:00
31ac8f7b70 disabled CI for certain releases 2022-11-22 12:40:49 +01:00
9f472330f8 fixed CI 2022-11-22 11:56:57 +01:00
df91f56283 maybe better way to save release 2022-11-22 11:14:31 +01:00
f022c21f11 fix nightly release 2022-11-22 09:16:14 +01:00
5aac9d66e0 fixed typo 2022-11-22 08:39:46 +01:00
a9a0798d7d update nightly release automagically 2022-11-22 08:34:59 +01:00
bd947c2669 Merge branch 'master' of https://github.com/AlexandreRouma/SDRPlusPlus 2022-11-21 22:37:31 +01:00
6adf0baaa7 fixed CI warnings 2022-11-21 22:37:25 +01:00
fb10d0f917 Merge pull request #708 from hb9fxq/patch-1
Allow user defined CMAKE_INSTALL_PREFIX
2022-11-21 17:23:04 +01:00
61f19f44a2 Correct USA amateur allocations below 2GHz
- add 2200m band
 - add 630m band
 - fix 80m band - in US, it's 3.5-4.0 MHz
 - 60m band is 5 discrete "channels"
 - 40m band in US is 7.0-7.3 MHz
 - 10m band in US is 28.0-29.7 MHz
 - 1.25m band is in two parts; 219-220MHz and 222-225 MHz

Source: ARRL, FCC
2022-11-15 10:24:10 -08:00
638306e2da added hermes module to android build and cleanup 2022-11-12 18:00:25 +01:00
2ac1a38ea4 bugfix to hermes band filters 2022-11-12 17:17:19 +01:00
1c373e9cdb bunch of bugfix and new features 2022-11-12 02:19:53 +01:00
c4bac3b298 twinrx fix 2022-10-23 21:11:04 +02:00
0a4c191054 windows CI fix 2022-10-23 20:13:14 +02:00
c72c8d056d fixed USRP channel name bug 2022-10-23 20:11:35 +02:00
d74ea13878 fixed missing USRP source build 2022-10-23 18:05:10 +02:00
d16c08c8b2 random fixes 2022-10-23 17:41:10 +02:00
ebc9911f18 fixes 2022-10-23 16:52:33 +02:00
aa06db4d7a Merge branch 'master' of https://github.com/AlexandreRouma/SDRPlusPlus 2022-10-23 16:41:56 +02:00
9ccc14848b USRP source 2022-10-23 16:41:45 +02:00
09d814e845 Fixed typo in readme 2022-10-19 11:02:23 +02:00
d4a6ada56e added missing include 2022-10-18 11:43:44 +02:00
c4fd285f7b fixed MacOS instructions 2022-10-18 11:36:35 +02:00
cc6b239d22 added MacOS instructions 2022-10-18 11:34:11 +02:00
a9e8db2a24 cleanup + beginning of hermes source 2022-10-18 11:09:22 +02:00
8eed0fcc9c fixed not init variable 2022-10-11 17:49:51 +02:00
68ba6d7d19 Merge pull request #886 from AlexandreRouma/rigctl_client
Beginning of rigctl client (not yet usable)
2022-10-11 17:43:41 +02:00
a85bae9527 Update CMakeLists.txt 2022-10-11 17:43:20 +02:00
34b0577f3b more work on the new recorder 2022-10-11 17:40:38 +02:00
52a4143cf5 code cleanup and fixes 2022-09-28 17:15:38 +02:00
b65da2fd49 work 2022-09-28 15:55:50 +02:00
c95c7b18af added invert iq option 2022-09-27 15:43:33 +02:00
f4bd483410 more work 2022-09-26 17:04:24 +02:00
869b3e0abd thread safety + stop recorder on audio stream deselect 2022-09-26 15:08:01 +02:00
3421aae9a2 more work on recorder 2022-09-26 14:57:06 +02:00
f49fbd2a73 fixed RSP1A DAB notch 2022-09-25 01:03:06 +02:00
5b8b344142 added missing files 2022-09-25 01:01:43 +02:00
0c8f6ab836 new recorder stuff 2022-09-25 01:01:07 +02:00
4047d3bcc2 Removed outdated MacOS instructions 2022-09-05 15:22:07 +02:00
dcb6321531 Fixed android text bug and updated readme 2022-09-04 18:00:39 +02:00
bd9df6ecf9 Merge branch 'master' of https://github.com/AlexandreRouma/SDRPlusPlus 2022-09-04 01:17:29 +02:00
81ac817639 added dummy debug keystore 2022-09-04 01:17:20 +02:00
fccd08a6e0 Merge pull request #860 from rs1729/fix_fprintf_percent
core/src/dsp/multirate/rational_resampler.h
2022-09-03 20:58:52 +02:00
e97dcecc6e Disabled bionic CI 2022-09-03 20:13:14 +02:00
54db4b41a4 still not working.. 2022-09-03 20:08:54 +02:00
70ff76e553 more fixes to the bionic ci (update your distros ffs) 2022-09-03 19:53:05 +02:00
0f7c17f007 fix again 2022-09-03 19:49:50 +02:00
6cf474144b ubuntu bionic CI fix 2022-09-03 19:48:55 +02:00
7ae59681d5 save APK 2022-09-03 19:41:39 +02:00
c7a1bda364 fixed android CI 2022-09-03 19:05:01 +02:00
1c02f4edca fix 2022-09-03 18:54:08 +02:00
4479170cc2 attempt at adding android CI 2022-09-03 18:53:14 +02:00
cd71becd8a android fix 2022-09-03 00:38:18 +02:00
72b895fc67 android fixes 2022-09-02 20:08:16 +02:00
6c93d9b2fa fix fprintf % error 2022-09-02 19:59:29 +02:00
ce3fea3747 fixed lowpass setting not presistent for NFM 2022-09-01 18:12:59 +02:00
9f0daf7d45 added scanner status indicator and enabled the scanner on android 2022-08-31 14:59:22 +02:00
6d784dfe27 enabled scanner 2022-08-30 16:07:49 +02:00
efcf26f0ac Merge pull request #850 from EmstallZ/master
Fix typos
2022-08-29 19:36:48 +02:00
14e37b41d4 Now showing the serial number on the RTL-SDR 2022-08-27 00:31:05 +02:00
ad36ede26b hackrf code cleanup 2022-08-27 00:03:46 +02:00
18a924d3a9 Fix typos 2022-08-22 14:41:39 +02:00
fb85177987 Fixed recording bug when decimation is enabled (issue #828) 2022-08-03 00:59:44 +02:00
90a8f617e9 Removed deprecated distros and fixed macos CI (hopefully) 2022-07-28 17:33:55 +02:00
575a941e24 More DSP cleanup + Remove FastFFT option because it should never be used 2022-07-27 21:35:36 +02:00
8efd5cd01a Update issue templates 2022-07-24 04:00:20 +02:00
50d7e5f86d Update issue templates 2022-07-24 03:45:02 +02:00
dcda49aea8 Update issue templates 2022-07-24 03:39:46 +02:00
3262f54100 Update issue templates 2022-07-24 03:35:27 +02:00
63bb9ad9af Fixed SDRplay FM/MW notch control 2022-07-16 22:42:10 +02:00
277d399e48 fixed limesdr antenna not set on startup and worked around limesuite bug 2022-07-16 02:36:03 +02:00
25f09a355e Added meteor recovery option 2022-07-16 00:08:25 +02:00
5bf5a10a12 bugfix + work on scanner 2022-07-15 17:17:53 +02:00
8b7afd88f9 fixed PCL bug 2022-07-11 16:18:07 +02:00
c57482771b Merge branch 'master' of https://github.com/AlexandreRouma/SDRPlusPlus 2022-07-10 18:27:36 +02:00
e03e95cc54 Fixed autostart for networked sources 2022-07-10 18:03:17 +02:00
76b41cb9ab Merge pull request #802 from dforsi/fix/typos
Fix spelling errors
2022-07-10 00:05:40 +02:00
55b468a02e Fix spelling errors
Fixed with
codespell --ignore-words-list=hist,parm,sur --skip=./core/src/imgui,./core/src/json.hpp,./core/libcorrect,./core/src/spdlog,./misc_modules/discord_integration/discord-rpc,./misc_modules/discord_integration/discord-rpc/include/rapidjson,./source_modules/sddc_source/src/libsddc --write-changes
2022-07-09 22:16:05 +02:00
039ef5eae3 removed SDDC option 2022-07-09 15:55:32 +02:00
d3e9ebef72 removed broken SDDC source 2022-07-09 15:54:39 +02:00
dbedc0d352 fixed package version not matching 2022-07-08 20:31:53 +02:00
d422230ae9 Merge pull request #713 from Ozies/master
Update Australia Band Plan
2022-07-08 19:15:12 +02:00
db5914a4d1 Merge pull request #722 from CamK06/master
Update Canada bandplan ...again
2022-07-08 19:15:00 +02:00
164970abf3 Merge pull request #736 from Pytlicek/master
Add Slovakia Band Plan
2022-07-08 19:14:20 +02:00
76c744a1bb Merge pull request #779 from cropinghigh/patch-3
Fix PMR frequencies + remove broken t.c. band
2022-07-08 19:13:52 +02:00
e5f73e36d9 Merge pull request #798 from RAD750/italy-bandplan
Added Italian bandplan
2022-07-08 19:13:36 +02:00
381c9d0e4b Merge pull request #801 from AlexandreRouma/new_dsp
New dsp + code cleanups
2022-07-08 19:13:03 +02:00
30b6c2b1da Code cleanup and optimisation$ 2022-07-08 17:30:43 +02:00
3ab8badb6a Fixed waterfall being cleared for no reason 2022-07-08 16:02:50 +02:00
96f5b37f76 Added RDS error correction (still needs better clock recovery) 2022-07-08 01:02:36 +02:00
bdd4998b1b fixed blury icon and recorder level meter 2022-07-07 22:14:40 +02:00
ae149b256b Fixed recorder bug 2022-07-07 20:07:13 +02:00
06210ae825 Fixed RDS not enabled when in mono even if RDS checkbox checked 2022-07-07 00:45:15 +02:00
b5857e2078 bugfix because std::chrono is stupid 2022-07-06 22:32:27 +02:00
edf22ccfe8 Added basic RDS support, no error correction yet 2022-07-06 22:11:49 +02:00
1af234e379 Added Italian bandplan based on Piano Nazionale della Ripartizione delle Frequenze (PNRF) updated October 5th, 2018 2022-07-03 17:15:02 +02:00
46f17019a7 cleanup + bugfix 2022-07-02 18:30:13 +02:00
74fd30f08c Added back the digital demodulators 2022-07-02 16:53:09 +02:00
ff6754099f More cleanup 2022-06-26 23:36:31 +02:00
3f6687659e Prototype noise blanker 2022-06-26 03:42:22 +02:00
c3ddffb3a9 UI fix 2022-06-23 23:37:12 +02:00
7d64d78d67 rollback 2022-06-23 22:25:39 +02:00
fb0e0d732b Attempted cmake cleanup 2022-06-23 22:21:25 +02:00
db034527e9 cleanup and better defaultzs 2022-06-23 21:30:38 +02:00
97643edf2f Fixed crash on radio disable/enable 2022-06-23 01:10:24 +02:00
01e1430847 final attempt at a fix 2022-06-22 05:28:03 +02:00
218fd6ccf4 another attempt at a fix 2022-06-22 05:20:40 +02:00
f2b8418a25 hopefully a fix for the linux crash 2022-06-22 04:58:03 +02:00
b943e6e869 Code cleanup, bugfix and optimisation 2022-06-21 19:54:03 +02:00
f7c566f652 More work 2022-06-21 17:24:48 +02:00
834890b69a maybe macOS fixes and other 2022-06-20 19:55:13 +02:00
53afaeda9e Fixes 2022-06-20 18:15:35 +02:00
ce1b0d0170 MacOS do be wasting my time 2022-06-19 23:50:34 +02:00
927bbab330 another dumb macos fix 2022-06-19 23:30:02 +02:00
fd5970b35a maybe a macos compilation fix idk 2022-06-19 23:03:55 +02:00
1dddbadd04 More work 2022-06-18 00:33:08 +02:00
ccc57cddc7 hopefully the final bugfix 2022-06-17 19:43:16 +02:00
9b1ec79d61 more stuff idk at this point$ 2022-06-17 19:14:55 +02:00
e06646367b another synthax error 2022-06-17 18:47:09 +02:00
b9e269f9dc roses are red, violets are blue, missing ';' on line 32 2022-06-17 18:37:02 +02:00
ed3f87da29 If one more build fails because of a missing namespace imma mc-fucking lose it... 2022-06-17 18:12:58 +02:00
4f601405a1 More dumb linux bugfix 2022-06-17 18:01:27 +02:00
cb59b04b17 more linux bugfix 2022-06-17 17:53:07 +02:00
c5f30f6d6a bugfix 2022-06-17 17:40:52 +02:00
36adc102ee attemt at a CI build with new DSP 2022-06-17 17:34:23 +02:00
d1318d3a0f even more stuff 2022-06-15 16:08:54 +02:00
343ec6ca1c lots o shit 2022-06-15 16:08:28 +02:00
e4926c236f Fix PMR frequencies + remove broken t.c. band 2022-06-05 14:12:37 +03:00
61614da910 Update some frequencies 2022-04-25 07:30:22 +02:00
5712db9bf8 #1 Add Slovakia Band Plan 2022-04-23 20:25:34 +02:00
79a15ed186 New DSP filters 2022-04-21 20:25:44 +02:00
527d40c95e Update Canada bandplan 2022-04-09 19:37:50 -04:00
6f747dad0d Merge branch 'master' of https://github.com/AlexandreRouma/SDRPlusPlus 2022-04-07 15:55:42 +02:00
663dd8d887 added autostart feature 2022-04-07 15:55:22 +02:00
2836292d58 marked irc channel as no longer active 2022-04-05 21:54:58 +02:00
09c8346d4b Update Australia Band Plan
Added in Shortwave bands
2022-04-02 17:51:11 +11:00
8dbae4e307 Merge pull request #707 from Ozies/master
Add Australia Band Plan
2022-04-01 16:23:08 +02:00
4c004d16a2 Update CMakeLists.txt 2022-04-01 16:03:43 +02:00
747b6bfbc6 Added FFT hold feature 2022-03-31 20:16:21 +02:00
83da29e80b Beginning of FFT Hold feature 2022-03-31 15:13:42 +02:00
28dccee34b Add Australia Band Plan 2022-03-31 21:19:20 +11:00
54dd3a77db Added menu order locked tooltip for distracted people 2022-03-31 01:13:12 +02:00
8d78eb301c Added option to lock the menu order 2022-03-31 01:03:31 +02:00
03f173a3ac Fixed M17 module on android 2022-03-30 20:15:27 +02:00
b8bc942b84 cmake bugfix 2022-03-30 17:33:47 +02:00
80d244003a Merge pull request #649 from AlexandreRouma/backend_abstraction
Backend abstraction and android support
2022-03-28 22:27:38 +02:00
50416b3319 Added the new patrons 2022-03-28 22:25:26 +02:00
ea59bc5cc0 UI issue fixed 2022-03-27 19:49:31 +02:00
47b54743bd more android fixes 2022-03-24 20:23:07 +01:00
58fcbbc5d2 A few fixes 2022-03-24 16:03:02 +01:00
842b23b2f4 More UI fixes 2022-03-21 21:35:05 +01:00
f58c7dd62f Merge pull request #691 from CamK06/master
Improve Canada bandplan
2022-03-16 21:46:47 +01:00
6958e46875 Improve Canada bandplan 2022-03-15 20:45:14 -04:00
e82e89a87c Fixed minor UI glitch 2022-03-04 09:59:36 +01:00
763807565c More DPI fixes 2022-02-25 17:32:03 +01:00
8a603c5420 bugfix 2022-02-24 22:44:37 +01:00
9999693c0d Added missing includes 2022-02-24 21:24:46 +01:00
81692fa910 More fixes 2022-02-24 21:11:02 +01:00
9bbc50ff3c Fixed issues hopefully 2022-02-24 21:01:51 +01:00
2779516378 Switched to new cleaner argument system 2022-02-24 20:49:53 +01:00
5c138aa4a5 More work on the new param system 2022-02-21 18:10:01 +01:00
7de9f3f497 Merge pull request #661 from dforsi/fix/typos
Fix spelling errors
2022-02-20 16:25:25 +01:00
98f4f560ad Fix spelling errors
Fixed with:
codespell --ignore-words-list=hist,parm,sur --skip=./core/src/imgui,./core/src/json.hpp,./core/libcorrect,./core/src/spdlog,./misc_modules/discord_integration/discord-rpc,./misc_modules/discord_integration/discord-rpc/include/rapidjson,./source_modules/sddc_source/src/libsddc
2022-02-20 16:19:05 +01:00
a87aedabb8 bugfix + part of the new command arg system 2022-02-18 19:21:02 +01:00
f46fa2157b Hopefully fixed MacOS cursor not calling ImGui when moved through software 2022-02-17 23:27:40 +01:00
b5cbafb01d Android cleanup 2022-02-16 17:06:46 +01:00
51c940acd4 Updated to ImGui 1.87 to cleanup UI code 2022-02-14 23:33:52 +01:00
04e54a2d57 Partial unicode support (the proper way), only cyrillic at the moment 2022-02-14 20:35:39 +01:00
6eb8bfc29a Fixed close not working 2022-02-14 19:36:49 +01:00
96da404149 Fixed text 2022-02-13 17:41:29 +01:00
e9cb7fda42 Backend abstraction + added android support + partial high DPI scaling + added missing files 2022-02-13 17:25:43 +01:00
e5f3d1672c Backend abstraction + added android support + partial high DPI scaling 2022-02-13 17:25:23 +01:00
71c95af711 Merge pull request #631 from orryverducci/macos-icon
Add macOS specific icon
2022-02-03 15:04:46 +01:00
94cf720cfd Add macOS specific icon 2022-02-03 12:57:38 +00:00
9969ce018b Backend abstraction 2022-01-29 20:35:08 +01:00
3c19081561 Bugfix in sdr++ server source 2022-01-29 17:42:53 +01:00
3ab669ecda Radio CW demod bugfix + more cleanup 2022-01-29 17:27:38 +01:00
860121dad2 Added CW tone option plus clean up 2022-01-29 16:55:31 +01:00
5e5c575e93 Added SDRplay source to the Raspberry Pi CI 2022-01-29 16:31:59 +01:00
8dcf17bef7 Fixed ever-expanding apply button in sdrplay source 2022-01-29 16:20:45 +01:00
4fcd06eff6 Added missing CI files 2022-01-29 14:51:53 +01:00
dcc0fef235 Added ubuntu jammy CI 2022-01-29 14:47:28 +01:00
260651fb5c Updated prebuilt debs 2022-01-27 19:21:30 +01:00
97346e6621 Merge pull request #616 from AlexandreRouma/zstd_compression
Optional ZSTD compression in SDR++ server
2022-01-27 17:29:32 +01:00
80dcf2d968 Fixed support for older distro (update ffs) 2022-01-26 20:51:59 +01:00
963c5c6581 Added missing deps to CI 2022-01-26 20:27:55 +01:00
a7b0b52da9 Fixed depencies 2022-01-26 20:20:04 +01:00
03f0704dff Switched to ImGui::TextUnfort 2022-01-26 14:50:16 +01:00
e158eabbf4 Merge pull request #615 from hewittc/format-security
Satisfy GCC -Wformat-security with string literals
2022-01-26 13:29:32 +01:00
4c0220a228 compression 2022-01-26 13:23:55 +01:00
aa265ea312 Satisfy GCC -Wformat-security with TextUnformatted 2022-01-25 14:41:09 -07:00
2c3b603b88 Satisfy GCC -Wformat-security with string literals 2022-01-25 14:05:12 -07:00
75da59833a Fixed server bug 2022-01-24 01:02:27 +01:00
fa0967313f Merge pull request #609 from AlexandreRouma/drop_glew
Drop glew
2022-01-23 18:22:27 +01:00
6fba9d7904 removed all trace of glew from the codebase 2022-01-22 20:16:48 +01:00
c1685a441c Fixed typo 2022-01-22 19:22:58 +01:00
9d7c1369ca Fix bad OpenGL bu 2022-01-22 18:13:46 +01:00
6dc97de57b Dropping glew and using ImGui's loader instead 2022-01-22 18:03:14 +01:00
0dc2f5f7c9 Fixed rigctl server 2022-01-22 16:36:48 +01:00
983c4c0f87 Fix for me being stupid (again...) 2022-01-22 16:15:48 +01:00
0ac85e0daf Linux Bugfix 2022-01-22 05:37:19 +01:00
da06fc39db Merge pull request #591 from kistlin/fix/unused_variables_warnings
fix warnings about unused/maybe uninitialized variables
2022-01-22 04:29:00 +01:00
4c1b50a3ac Major bugfix in server 2022-01-22 02:30:08 +01:00
34fc32dcf7 fixed fault config issues 2022-01-21 20:41:39 +01:00
070e27505b Fixed new networking typo 2022-01-21 20:28:31 +01:00
74b9d13360 SDR++ server beta :) 2022-01-21 20:22:13 +01:00
81d23967b6 revert some changes after the review 2022-01-17 06:53:14 +01:00
174158233b fix a lot of warnings about unused variables, or maybe uninitialized variables 2022-01-16 08:28:57 +01:00
1185e4e114 Added persistent config for the rfspace source's hostname and port 2022-01-02 19:56:27 +01:00
290bf5e32a Fixed invalid default config 2022-01-02 19:02:12 +01:00
4db485e209 Enabled the RFspace source by default 2022-01-02 18:34:06 +01:00
a58ae2bd98 Added persistent config for RFspace source 2022-01-02 15:34:55 +01:00
aab9d9e6ad Fixed RFspace source missing from windows build 2022-01-01 21:38:15 +01:00
7cc06b7a7b Fixed RFspace client on MacOS 2022-01-01 05:54:23 +01:00
efecd14281 Merge branch 'master' of https://github.com/AlexandreRouma/SDRPlusPlus 2022-01-01 05:27:19 +01:00
33914a7316 More work on RFSpace source 2022-01-01 05:27:10 +01:00
608979a0b7 Merge pull request #567 from visat1/master
Bandplan for austria
2021-12-30 19:46:20 +01:00
3a815d94b9 Merge pull request #1 from visat1/visat1-bandplan-at
Share bandplan for austria
2021-12-30 15:28:38 +01:00
7b77bb3d45 Share bandplan for austria 2021-12-30 15:27:53 +01:00
201a612c19 Only showing filename of modules in loading screen 2021-12-26 17:26:45 +01:00
5a0c1ab5d0 Added new patron 2021-12-26 16:49:50 +01:00
470e748e4a Fixed weird bug where config files spointainously appear everywhere (wtf...) 2021-12-26 02:09:37 +01:00
66269659c5 Lowered the number of threads for the rpi CI 2021-12-26 01:38:58 +01:00
6ded678048 Made sure to clean build 2021-12-26 01:01:15 +01:00
f34614e169 Saving build artifacts from raspberry pi CI 2021-12-26 00:59:25 +01:00
9d3f0f4f7e hopefully the final fix, i'm loosing my patience 2021-12-26 00:32:05 +01:00
25d585a35a Fixing raspberrypi ci 3 2021-12-26 00:30:06 +01:00
34bd09a92e Fixed raspberripi CI again 2021-12-26 00:26:37 +01:00
e5bbd0fdb3 Fixed raspberry pi ci 2021-12-26 00:23:38 +01:00
b141c4b2a5 Start of notch control + added raspberry pi CI 2021-12-26 00:22:16 +01:00
5a19829068 Removed ubuntu groovy from the CI 2021-12-25 16:51:39 +01:00
51f84566c4 Radio Bugfix 2021-12-25 02:17:21 +01:00
db8f736d58 fixes 2021-12-24 21:51:18 +01:00
07294034f6 Added preset system for FM IF NR 2021-12-24 21:42:04 +01:00
ad2ddc6ad3 Rolled back PFD 2021-12-19 22:18:35 +01:00
b736f83993 Fixed CI 2021-12-19 22:13:58 +01:00
d893eaae32 Formatted the entire codebase and added a CI check for formatting 2021-12-19 22:11:53 +01:00
ea587db0cb Formatted the entire codebase and added a CI check for formatting 2021-12-19 22:11:44 +01:00
8644957881 Fixed clang format file 2021-12-19 21:52:21 +01:00
cc2d73202e Added clang format files for future linting 2021-12-19 05:37:23 +01:00
fe0b63a275 Removed option 2021-12-19 02:35:40 +01:00
ef01205fb6 Fixed missing argument 2021-12-19 02:33:55 +01:00
c1cb3d5a1c bugfix 2021-12-18 21:48:03 +01:00
f1a231b791 Added new deemphasis mode + new image widget 2021-12-18 21:23:23 +01:00
5483268f8f Added error dialog to module manager and fixed typo 2021-12-16 16:49:19 +01:00
6c7e952be3 Further APT tuning 2021-12-13 18:12:17 +01:00
20b44403b2 Added missing file 2021-12-13 03:27:26 +01:00
964fd467f8 Added new dialog helpers and added Are You Sure dialogs in a few places 2021-12-13 03:01:06 +01:00
b4924a8fae CPU performance improvements for IF noise reduction 2021-12-12 21:55:00 +01:00
cee0f75870 bugfix + improved NFM IF noise reduction (less distortion) 2021-12-12 20:06:21 +01:00
15010cff01 Added a noise blanker for SSB and DSB 2021-12-10 22:25:22 +01:00
241632288e Fixed IF reduction not working with multivfo + Added beginning of IF notch code 2021-12-09 19:43:57 +01:00
f8ff67c5b0 beginning of notch filter implementation 2021-12-08 11:59:04 +01:00
c1942ac51d Fixed wrong default deemphasis mode on WFM 2021-12-08 04:15:05 +01:00
91370993a2 Further NR tuning 2021-12-08 03:07:52 +01:00
2a5671878f new FM IF noise reduction + bugfix 2021-12-08 02:10:41 +01:00
1594051a5d Switch old radio module to new radio module 2021-12-07 23:56:11 +01:00
355a6352da New radio logic system 2021-12-07 02:13:23 +01:00
7208028c01 Fixed VFO bandwidth not adjustable after disabling new radio module 2021-12-05 19:28:41 +01:00
cdc060aa2a Fixes to the new radio module 2021-12-04 19:59:30 +01:00
31b2cdd284 fixed macos missing new radio module 2021-12-04 19:10:31 +01:00
636bb214e8 Fixed windows CI 2021-12-04 18:09:43 +01:00
8accb531b0 New radio module 2 2021-12-04 17:46:55 +01:00
fe285c71ff New radio module 2021-12-04 17:46:48 +01:00
62d2dfafd7 More work on the new radio 2021-12-04 04:49:51 +01:00
2748c13142 new radio code + fixes 2021-12-03 19:46:09 +01:00
2daaf00cb3 Disabled raspios CI + added start of noise reduction code 2021-11-28 03:17:08 +01:00
b148fc8a28 Testing fixes for raspberry pi CI 2 2021-11-24 20:49:34 +01:00
407efef935 Testing fixes for raspberry pi CI 2021-11-24 20:46:45 +01:00
8c35639767 fixed raspberry pi CI 2 2021-11-24 20:09:54 +01:00
5e89c52007 fixed raspberry pi CI 2021-11-24 20:07:02 +01:00
2261b0fc2b Added raspberry pi CI 2021-11-24 20:02:16 +01:00
e394b64ad3 Added persistent recorder volume 2021-11-23 22:35:09 +01:00
fc7d902c1d Merge pull request #521 from aosync/master
readme.md: add IRC channel
2021-11-23 20:52:55 +01:00
2f5a8c38a1 Update readme.md 2021-11-23 20:52:49 +01:00
f3e987fb7e Fixed SDRplay AGC and added hardware donators to the credits 2021-11-23 17:05:40 +01:00
abd718b024 readme.md: add IRC channel
readme.md: add link to libera.chat
2021-11-22 22:17:23 +01:00
28d056b776 Update CMakeLists.txt 2021-11-18 22:26:25 +01:00
8c631f40c7 minor cleanup 2021-11-18 14:40:59 +01:00
a84d525252 another fix 2021-11-18 13:52:06 +01:00
4ee677154f Fixed bad libraries being included 2021-11-18 12:06:43 +01:00
098b78dcd1 Fixed libiio and libad9361 missing from MacOS bundle 2021-11-18 11:46:53 +01:00
46a9ecee72 Refactored bundle script 2021-11-18 11:27:47 +01:00
c320a486b3 MacOS CI fix again 2021-11-18 10:58:48 +01:00
21b405d2bb Added LimeSDR support on MacOS 2021-11-18 10:03:45 +01:00
9c2cb26376 Final plutosdr macos fix 2021-11-18 09:38:56 +01:00
3ca7dc87e7 MacOS CI fix 2021-11-18 08:56:06 +01:00
916c95a75e Enabled plutosdr source in MacOS CI 2021-11-18 08:37:55 +01:00
dde95019ea CI bugfix and refactoring 2021-11-17 15:37:21 -06:00
170a48f83f Cleaned up the MacOS tools and enabled the plutosdr_source in the MacOS CI 2021-11-17 15:04:20 -06:00
a08f5c35af Enabled SDRplay source in MacOS CI 2021-11-17 12:27:11 -06:00
1fe799b445 Fixed signing on MacOS 2021-11-17 11:16:20 -06:00
7474241e01 Added missing file 2021-11-17 10:22:27 -06:00
7faaa21ac1 Switched tonew dotapp buildscript 2021-11-17 10:03:59 -06:00
a6e6c93a50 Final MacOS .app fix 2021-11-16 14:18:33 -06:00
10733f7a5d Added pip command and fixed waterfall bug 2021-11-16 13:23:52 -06:00
7f6c555310 More fixes 2021-11-16 13:08:20 -06:00
c659c4b007 FSwitched to self built volk for Mac CI 2021-11-16 12:55:03 -06:00
66dcb5eb79 Added check for rpath in MacOS dotapp script 2021-11-16 12:19:50 -06:00
6f8fc86236 Disabled option wrongly enabled by default 2021-11-16 05:29:05 +01:00
1bbb1eea0e CI Fix 2021-11-16 03:55:49 +01:00
b81d0c47cf Final work on MacOS compatibility 2021-11-15 20:33:09 -06:00
49cf6944f0 Added missing file 2021-11-15 18:26:33 +01:00
ca657c8ca8 More MacOS work 2021-11-15 18:25:32 +01:00
2620d688ec More MacOS work 6 2021-11-15 18:04:57 +01:00
799e8c7e02 More MacOS work 5 2021-11-15 18:01:08 +01:00
f5b07f6a60 More MacOS work 4 2021-11-15 17:59:52 +01:00
599a53b49b More MacOS work 3 2021-11-15 17:56:18 +01:00
0e5384b8ad More MacOS work 2 2021-11-15 17:55:33 +01:00
715129566d More MacOS work 2021-11-15 17:53:32 +01:00
106e0ada80 Added more MacOS tools 2021-11-15 17:28:12 +01:00
7ad616d62b finished set_library_path for MacOS .app build 2021-11-15 17:20:06 +01:00
40e2564ef9 More work on MacOS and the scheduler 2021-11-15 17:15:59 +01:00
0ab4d16f9d Beginning of scheduler code 2021-11-14 18:30:58 +01:00
d20b41401f Merge branch 'master' of https://github.com/AlexandreRouma/SDRPlusPlus 2021-11-11 17:11:48 +01:00
cca18f3a70 More work on scanner 2021-11-11 17:09:37 +01:00
07a4ff3e9f Incremented version 2021-11-09 17:38:27 +01:00
a414b75ef4 Fixed windows CI 2021-11-09 13:55:52 +01:00
12d16fe9ee Work on RFspace support 2 2021-11-09 00:00:43 +01:00
07419275ff Work on RFspace support 2021-11-09 00:00:13 +01:00
927115b50b Added start/stop commands to the rigctl server 2021-11-05 19:42:49 +01:00
a938324886 Saved fullscreen state in the config 2021-11-05 18:57:50 +01:00
894700cbab Fixed Impish CI 2 2021-11-05 16:15:08 +01:00
6ea4f5fd68 Fixed Impish CI 2021-11-05 15:51:46 +01:00
ca185bb416 Added Ubuntu Impish CI 2021-11-05 13:55:00 +01:00
a3dc20b384 Merge pull request #506 from cropinghigh/patch-2
Update Russian Bandplan
2021-11-05 12:19:22 +01:00
fd643c37f5 Update Russian Bandplan
fix overlaps, bring OIRT back, add LTE-450, add train communications frequencies, add L to X satellite bands
2021-11-05 04:36:27 +03:00
c784630345 Fixed the default fft size 2021-11-03 18:12:43 +01:00
e6377d4f3d Fixed waterfall recursive lock bug 2021-11-03 16:30:32 +01:00
d5becc5fc2 Merge pull request #487 from DJRaov/master
Finish the Russian bandplan
2021-10-31 17:51:36 +01:00
9d44f91f45 Finish the Russian bandplan
took me long enough i know
2021-10-31 19:02:19 +05:00
c7db2d2b6a Merge pull request #479 from sikmir/cmake
Fixed sdrpp.desktop installation path
2021-10-31 01:39:34 +02:00
c8bdd2e52b Removed install target from included libcorrect 2021-10-29 17:58:15 +02:00
2c7c93b64c Fixed sdrpp.desktop installation path 2021-10-29 03:17:53 +03:00
312c80b355 Fixes for Archlinux 2021-10-28 10:05:31 +02:00
a11b74a595 Added new patron 2021-10-26 16:44:59 +02:00
0f5398b064 Added new bandplan 2021-10-25 18:24:33 +02:00
f539cfad32 Fixed alrge FFT size bug 2021-10-18 00:38:02 +02:00
ab1a482352 Increased max FFT size 2021-10-18 00:06:03 +02:00
35fc973a65 new 2021-10-17 21:01:47 +02:00
db8eb47422 Merge pull request #444 from KentuckyFriedData/patch-2
Typo
2021-10-16 19:33:28 +02:00
d4795cb369 Typo 2021-10-16 09:53:08 -07:00
75249fe849 Fixed draw list size in code 2021-10-16 16:12:51 +02:00
d1aab6f25d fixed typo 2021-10-13 00:22:10 +02:00
afe13969a7 Added support for Bias-T in the bladerf_source module & added bladerf type detection 2021-10-12 19:45:42 +02:00
47e5c589bc Merge branch 'master' of https://github.com/AlexandreRouma/SDRPlusPlus 2021-10-10 18:26:31 +02:00
3795e7cf23 Fixed RSP1A FM notch bug 2021-10-10 18:26:17 +02:00
d18a019abf Merge pull request #402 from corvus-ch/mac_build
Document how to build on MacOS
2021-10-10 14:13:07 +02:00
4d7b46b1a8 Sync build example with github action workflow 2021-10-09 22:22:01 +02:00
cf3e024fb9 Use Port Audio instead of RtAudio 2021-10-09 21:26:35 +02:00
8deb018684 Added RTLD_LOCAL to the dynamic linker flags FIX 2021-10-09 18:34:44 +02:00
33b9b53328 Added RTLD_LOCAL to the dynamic linker flags 2021-10-09 18:34:20 +02:00
011e7ca409 Added new theme 2021-10-08 23:24:58 +02:00
a27a46350e Merge pull request #419 from thomasgi1/memoryCorruption
renamed SpyServer source module class
2021-10-08 23:15:35 +02:00
3fd4294afa renamed SpyServer source module class AirspyHFSourceModule -> SpyServerSourceModule, so that it does not collide with the original Airspy HF source module causing massive memory corruption 2021-10-08 22:24:09 +02:00
4b2f3e4f60 Added new patrons to the credits + fixed patreon order list to be alphabetical 2021-10-05 20:57:15 +02:00
82cacf14bb Fixed text in M17 decoder 2021-10-04 05:07:11 +02:00
0fffa7d45a More cmake fixes 2021-10-04 04:00:06 +02:00
9555dda8a4 More cmake cleanup 2021-10-04 03:31:13 +02:00
44ad0a1a7e CMakeLists cleanup 2021-10-04 02:34:17 +02:00
c515ddb811 MacOS fix final (final)???? 2021-10-04 01:13:02 +02:00
ea0d905177 MacOS fix final???? 2021-10-04 00:58:16 +02:00
1be3092c7d MacOS fix 8 2021-10-03 23:58:11 +02:00
f29f77bbdc MacOS fix 7 2021-10-03 22:44:15 +02:00
91d960da3c MacOS fix 6 2021-10-03 22:11:03 +02:00
dd083b6634 MacOS fix 5 2021-10-03 21:40:39 +02:00
b4e2875acd MacOS fix 4 2021-10-03 21:07:12 +02:00
4ea9b96397 MacOS fix 3 2021-10-03 20:56:24 +02:00
8c15e78315 CI fix 2 2021-10-03 19:00:50 +02:00
94b7676ca5 CI fix 2021-10-03 18:49:56 +02:00
83fc20cacc Another potential fix for the MacOS issues 2021-10-03 17:48:32 +02:00
fcd759654c Potential fix for MacOS ci 2021-10-03 17:41:07 +02:00
73393e36c6 Changed project structure 2021-10-03 16:50:36 +02:00
c36034dbb8 Potential MacOS CI fix 2021-10-03 03:40:16 +02:00
a9d92d3a8e More fixes + debugging macos ci 2021-10-03 02:04:02 +02:00
8666aa07e7 Fixed missing const 2021-10-03 01:48:44 +02:00
a37a2d3b36 fixed warning + verbose cmake test 2021-10-03 01:41:18 +02:00
dc31539f6e Fixed compile arguments for the discord module 2021-10-03 01:29:32 +02:00
4564475821 Reworked cmake compiler arguments 2021-10-03 01:13:15 +02:00
163e35727c Fixed M17 not being enabled in the CI 2021-10-02 20:51:59 +02:00
40d21b3321 Final tweaks to windows CI for M17 decoder 2021-10-02 20:33:22 +02:00
fb9bbcb158 Fixed windows CI 2021-10-02 20:04:14 +02:00
c0801a8aed Added codec2 to the windows CI 2021-10-02 19:58:30 +02:00
dc43e76405 Document how to build on MacOS 2021-10-02 19:40:27 +02:00
8b2f019ce4 Enabled the M17 Decoder in the macos build 2021-10-02 18:06:30 +02:00
13bafa002a Changed back to pkg-config for codec2 2021-10-02 17:45:52 +02:00
90ebe373df Fixed missing .pc file in ubuntu bionic CI 2021-10-02 17:43:44 +02:00
5b7fc417ff fixed typo + switched off pkg-config for codec2 2021-10-02 17:24:23 +02:00
b4213ea049 Bugfix + added M17 decoder to the linux CI 2021-10-02 17:01:23 +02:00
26fa23c8f5 Improved feature lsit 2021-10-02 00:16:16 +02:00
c2da150d43 Added new patron to the credits 2021-09-29 08:53:15 +02:00
48f6642c70 M17 decoder bugfix 2021-09-29 08:44:03 +02:00
efd3c47a6c more progress on M17 support 2021-09-28 20:46:19 +02:00
187fc2cb9e Added M17 decoder module (unfinished) 2021-09-27 03:42:26 +02:00
c9a78d5dc6 Merge pull request #327 from arkhnchul/sdrplay-lowif
IF Mode selection for SDRPlay devices
2021-09-24 19:24:37 +02:00
b7c95de8cc Fixed network sink not being present by default 2021-09-23 20:37:34 +02:00
bc0de50ba6 Fixed missing renamed filed 2021-09-20 20:08:53 +02:00
049fc77ff6 Fixed typos 2021-09-20 19:59:35 +02:00
9ee0951874 Fixed CI typo 2021-09-20 19:03:48 +02:00
841c31daf4 Added spell check to CI 2021-09-20 19:02:53 +02:00
d9b061ef89 Fixed typo in french bandplan 2021-09-20 17:14:32 +02:00
ce48257706 Update rpi_install.sh 2021-09-19 15:10:08 +02:00
fe09a30279 Update rpi_install.sh 2021-09-19 12:18:39 +02:00
daa26e8e97 Merge branch 'AlexandreRouma:master' into sdrplay-lowif 2021-09-14 14:56:14 +03:00
318e57dc3d Fixed wonky fft resize behavior 2021-09-13 23:31:01 +02:00
b74e2d37a5 fixed dependencies in deb files 2021-09-13 20:42:13 +02:00
9d34c6a8c1 Fixed wonky center tuning behavior 2021-09-13 20:07:40 +02:00
2184e15e44 Added rtaudio to the base dependencies 2021-09-13 19:37:38 +02:00
bd427d23b3 Fixed typo in the readme + Fixed bandwidth and NFM and AM demodulators 2021-09-13 19:22:32 +02:00
5a2b0c9d79 Added new patron to the readme and fixed radio remove/disable bug 2021-09-12 19:12:23 +02:00
a208d4078e IF titles consistent with sdrplay doc 2021-09-02 03:25:09 +03:00
f56113aae4 IFBW 5000 samplerate fix 2021-08-31 21:37:44 +03:00
11c6377c7f Merge branch 'AlexandreRouma:master' into sdrplay-lowif 2021-08-31 20:48:46 +03:00
22acf33c01 UI Cleanup + Fixed waterfall zoom bug 2021-08-31 18:39:48 +02:00
ec6a258958 Removed logging when zooming 2021-08-30 19:54:43 +02:00
012903fbf4 Fixed wrong bandwidth when zooming 2021-08-30 19:22:00 +02:00
e48b5c6035 Added missing refresh button when in low IF mode 2021-08-30 16:37:29 +02:00
0a54b92c58 Merge branch 'AlexandreRouma:master' into sdrplay-lowif 2021-08-30 17:37:00 +03:00
7c1d1cad22 Switched the place of the Sample rate and IF mode combos 2021-08-30 15:53:41 +02:00
e101c1ebd7 Fixed the way the IF mode combo is displayed 2021-08-30 15:50:47 +02:00
68b3eb9b21 Merge pull request #329 from ericek111/soapy_fix
soapy_source: refresh devices on start if none in devList
2021-08-30 15:47:08 +02:00
c579aca1db Merge pull request #330 from ericek111/exp_zoom
Make the zoom slider exponential
2021-08-30 15:24:38 +02:00
c31e260425 Added error message 2021-08-30 03:07:36 +02:00
fa75a3a176 Update main.cpp 2021-08-30 03:06:40 +02:00
af59144f5b Merge pull request #328 from ericek111/master
soapy_source: always show the Refresh button
2021-08-30 03:01:42 +02:00
04ce4c3583 Make the zoom slider increase exponentially 2021-08-30 02:27:48 +02:00
ba6d9f7202 minor style change 2021-08-30 01:23:42 +02:00
49fd49b4d6 soapy_source: refresh devices on start if none in devList 2021-08-30 01:07:40 +02:00
99441ea2eb soapy_source: always show the Refresh button 2021-08-30 00:56:46 +02:00
dbd734a0b5 IF Mode selection for SDRPlay devices 2021-08-30 01:02:45 +03:00
f572d12936 Fixed macos build 2021-08-27 14:07:01 +02:00
37bf9c46c5 Enabled airspy hf+ for all MacOS automated builds 2021-08-27 13:44:45 +02:00
aa9a2a8b46 Merge pull request #309 from drfruct/macos_sdrplay
fix: CMakeList to build SDRPlay on MacOS
2021-08-26 02:26:13 +02:00
124f3368d4 MacOS SDRPlay 2021-08-25 22:50:19 +03:00
51d084c20e Fixed ubuntu 18.04 support issues 2021-08-24 19:36:13 +02:00
101674379d Added support for ubuntu 18.04 2021-08-24 19:23:08 +02:00
61bbb4a374 work towards ubuntu 18.04 compatibility 2021-08-24 18:59:45 +02:00
2d8bbef12a Merge pull request #300 from NickEngmann/master
Fix Wrong Source Branch within BladeRF build
2021-08-23 14:59:55 +02:00
4109ea73b3 Merge pull request #1 from NickEngmann/fix-bladeRF-build-patch
fix:wrong source branch mentioned
2021-08-23 08:52:06 -04:00
a7d8ec8a2d fix:wrong source branch mentioned 2021-08-23 08:51:07 -04:00
6036300ecb Added missing people to the credits 2021-08-22 17:18:15 +02:00
9cf3ba79f3 Merge pull request #297 from shuyuan-liu/master
Add bandplan for (mainland) China
2021-08-22 17:11:18 +02:00
dcda74c0cf Merge branch 'AlexandreRouma:master' into master 2021-08-22 22:38:09 +08:00
4f16c6bf90 Correct freqs of 2200m ham band 2021-08-22 20:04:05 +08:00
73daca9116 Add the rest of china.json
Amateur bands above 100GHz are omitted.
2021-08-22 19:59:51 +08:00
2fd91459fd Fixed bug 2021-08-21 23:13:38 +02:00
8502bae236 Added basic dependencies to the debian/ubuntu packages 2021-08-21 18:03:34 +02:00
f01cb4af9f Added support for OpenGL 2.1 and OpenGL ES 3.0 with no modifications to the code necessary by the user 2021-08-21 17:47:55 +02:00
53cb328c2c Merge pull request #289 from 3cky/set-reuseaddr-listen-sock
Set SO_REUSEADDR option to listen sockets on non-Windows systems
2021-08-21 13:42:54 +02:00
9a2794a0dd Set SO_REUSEADDR option to listen sockets on non-Windows systems 2021-08-21 09:45:46 +03:00
c84371ba52 Merge pull request #288 from 3cky/fix-rigctl-wsjtx
Fix rigctl server to work with WSJT-X
2021-08-20 23:51:57 +02:00
dbf1fb790f Changed back to PR 2021-08-20 21:45:07 +02:00
271d1f9240 Update main.cpp 2021-08-20 20:41:54 +02:00
b2ce47d975 Fixed radio bandwidth not adjusted when the menu is closed or hidden 2021-08-20 20:40:14 +02:00
6ab59ad3c5 Fix rigctl server to work with WSJT-X 2021-08-20 20:38:05 +03:00
3516baa042 Create partial bandplan for (mainland) China 2021-08-20 23:10:26 +08:00
1465fb784f Merge pull request #276 from ge0metrix/master
Updated US Bandplan to add FRS/GMRS
2021-08-20 14:48:46 +02:00
42918908a0 Updated US Bandplan to add FRS/GMRS 2021-08-19 13:15:35 -04:00
9f0e050d1b Started work for older system support 2021-08-16 18:49:00 +02:00
dcc17cdee7 Fixed LimeSDR + Fixed FFTSize bug + added ppm option to RTL-SDR & RTL-TCP + Fixed RTL-TCP not saving settings 2021-08-10 00:54:00 +02:00
9eb3ef0500 Fixed rigctl server not starting on AOS 2021-08-08 21:38:15 +02:00
ffc20f5fee Added new patron 2021-08-08 21:38:15 +02:00
6144f3a3f9 Update readme.md 2021-08-04 16:46:32 +02:00
a3bda1b8fd Bugfix 2 2021-08-04 00:16:14 +02:00
2a6c742a51 Bugfix 2021-08-04 00:15:05 +02:00
604a559b54 Update readme.md 2021-08-03 21:37:35 +02:00
d9a0243905 Slight fixes on the hrpt decoder and new version 2021-08-01 14:48:47 +02:00
99096885f5 Changed to a better way of selecting sample rate on the plutosdr 2021-07-31 21:50:46 +02:00
f16c296f38 Potential fix for windows 7 not detecting the home key and the radio not saving the bandwidth when set through the frequency manager 2021-07-31 21:00:47 +02:00
85eb08e422 Fixed issues with unselectable VFOs when too small 2021-07-31 20:17:36 +02:00
ee5b89c4aa Fixed waterfall at very low samplerates 2021-07-31 16:36:04 +02:00
c13eb950b2 better defaults for rtl-sdr and rtl-tcp sources 2021-07-31 05:12:26 +02:00
011fdce237 Fixed weird VFO behavior 2021-07-31 01:38:01 +02:00
79e79e78ac Fixed network sink missing from windows CI builds 2021-07-31 00:03:28 +02:00
6114cf0f58 Fixed crash on disconnect 2021-07-30 23:39:28 +02:00
3350697875 Fixed broken code on linux 2021-07-30 22:06:06 +02:00
7f4557527e Added network sink and fixes to the networking lib 2021-07-30 21:56:56 +02:00
1aa2c064f7 Merge pull request #190 from thedocruby/patch-1
Further progress the rigctl server towards full feature parity
2021-07-29 22:27:31 +02:00
1f3dcc1beb removed broken scripting interface 2021-07-29 22:08:42 +02:00
e9cdf162fa More fixes 2021-07-29 21:20:40 +02:00
a487c0aaea more bugfix 2021-07-29 20:22:16 +02:00
d84273a0db Merge branch 'master' into patch-1 2021-07-29 12:38:23 -04:00
5d08f1018d Partial fix for the SNR meter not being the right size 2021-07-29 17:58:23 +02:00
b7a0f849cf potential fix for Windows 7 freeze on exit 2021-07-29 15:07:22 +02:00
7079ddb74e Fixes to the UI 2021-07-29 02:50:51 +02:00
e744520d50 Fixed setFFTSize visual bug 2021-07-28 22:53:38 +02:00
0741f265d7 Fixed bugs with the frequency manager 2021-07-28 20:16:31 +02:00
2f61b190ca Fixed RTL-TCP bug 2021-07-28 19:35:25 +02:00
fc30287bed Fixed wrong response for get_mode rigctl command 2021-07-28 04:34:44 +02:00
003ff37ab8 Added support for compound commands and long commands to the rigctl server 2021-07-28 04:21:51 +02:00
8290284586 Improved performance of DC correction 2021-07-28 02:18:54 +02:00
b9e35e6558 Added IQ correction 2021-07-27 23:51:06 +02:00
679fb49743 Added IQ correction 2021-07-27 23:50:48 +02:00
5974839515 Merge branch 'AlexandreRouma:master' into patch-1 2021-07-27 13:06:17 -04:00
666b89c4c7 Copy down last edit 2021-07-27 13:02:31 -04:00
d21a61aefd Switches only take ints
dumb mistake. I squashed the if-else chain just a bit so that it wasn't any longer than the switch. it's already really, long, I didn't want it to be any longer. Thought it might be more readable this way.
2021-07-27 13:01:15 -04:00
5f29350dd1 Potential fix for AM squelch issue 2021-07-27 18:47:58 +02:00
8f43110c72 Fix dependency issue 2021-07-27 12:46:25 -04:00
a4240ab8a1 Merge branch 'AlexandreRouma:master' into patch-1 2021-07-27 12:20:12 -04:00
d73a18ddcc Touch-ups and commentary 2021-07-27 12:18:50 -04:00
6dc24a7fc7 Updated version number 2021-07-27 18:09:47 +02:00
cd74313bc8 Added mode and vfo commands
vfo command is currently a dummy implementation, but as some rigs officially supported by rigctl do not support vfo besides a dummy response, such an implementation is acceptable for now.
2021-07-27 11:57:51 -04:00
14fae89a0b Added error message on SDRplay source when API isn't working 2021-07-27 16:32:25 +02:00
0498a48b93 Fixed bug in source selection 2021-07-27 15:47:11 +02:00
22e9d25bed Added longform frequency commands for consistency
Also:
 - fixed control error at line 366 
 - fixed control errors related to returning in compound command loop
 - added commentary
2021-07-26 20:30:03 -04:00
4092874f5c Add support for compound commands 2021-07-26 20:06:33 -04:00
e27702c166 Rearrange commands, add slash commands. 2021-07-26 20:00:32 -04:00
21f4c40e7f Added a FFT framerate setting 2021-07-27 01:57:12 +02:00
bd744d07ba Final fix for the linux crash 2021-07-26 22:16:31 +02:00
8a4055920d More fixes 2021-07-26 21:44:15 +02:00
6c05c11a62 potential fix for stall 2021-07-26 21:30:49 +02:00
e62351c206 Added decimation 2021-07-26 21:18:06 +02:00
ffed602246 Fixed stereo checkbox in radio module 2021-07-26 18:21:06 +02:00
03a2f41c04 Fixed category on .desktop 2021-07-26 18:16:30 +02:00
df51dc7104 Fixed module manager title not locked 2021-07-26 17:49:16 +02:00
8bea72beb5 Fixed module manager not saving module list 2021-07-26 17:45:09 +02:00
14813aa962 Fixed module manager not saving 2021-07-26 17:33:41 +02:00
ce448d6852 Fixed weird source deselect bug 2021-07-26 17:17:10 +02:00
7506e45d3b Fixed bug when removing certain modules 2021-07-26 16:56:48 +02:00
034ada1ed7 Fixed freeze when removing the recorder 2021-07-26 16:40:05 +02:00
646fe4fd02 more bugfix on the module manager and audio streams 2021-07-26 15:54:33 +02:00
fa9347f2ee More bugfix 2021-07-26 04:16:00 +02:00
85de72a859 Fixed support in the module manager 2021-07-26 03:11:51 +02:00
b327bfbe5d Slight fix to the audio sink 2021-07-24 19:53:57 +02:00
da8614438c Added elements for the wiki 2021-07-23 20:32:43 +02:00
5248688241 Fixed username 2021-07-23 19:43:59 +02:00
26dedec561 Merge pull request #180 from Starman0620/master
Change all references to me to use my real name
2021-07-23 19:39:53 +02:00
d8d45ec7af more bugfix on the file source 2021-07-23 19:39:17 +02:00
a888065624 more fixes to stereo FM 2021-07-23 16:18:47 +02:00
8454b40d54 FM stereo prototype 2021-07-23 06:29:16 +02:00
175e361ccd bugfix + preparations for stereo FM 2021-07-22 23:30:41 +02:00
2baf607b8c Fixed RTL-TCP bug 2021-07-21 16:23:03 +02:00
a974658c98 Fixed checkbox with no name 2021-07-21 15:44:50 +02:00
465dc9e5dc fixed typo 2021-07-21 15:43:30 +02:00
8d3f646aec Added bias-t support to rtl_tcp source 2021-07-21 15:42:01 +02:00
4418baba3f Changed Starman0620 to Cam K. in Discord integration credits 2021-07-20 23:08:41 -04:00
3d5047338c Renamed Starman0620 to Cam K. in contributors 2021-07-20 23:07:47 -04:00
fb32b4d55a Made the file source set the frequency of the waterfall 2021-07-21 04:08:28 +02:00
5f1a94c267 more bugfix 2021-07-20 21:39:16 +02:00
0d7f1265da Fixed CW demodulator 2021-07-20 03:38:58 +02:00
09e332a8d1 more fixes 2021-07-20 03:03:22 +02:00
e877844768 More spyserver bugfix 2021-07-19 22:23:03 +02:00
c9f1ec0a8a Fixed more bugs 2021-07-19 20:51:17 +02:00
4b43da095e SpyServer fixes 2021-07-19 20:09:37 +02:00
3103d2d168 spyserver source bugfix 2021-07-19 16:20:01 +02:00
027297933b Fixed hanging bug 2021-07-19 15:57:37 +02:00
1adcdea6d1 Fixed missing modules 2021-07-19 14:25:28 +02:00
ebd74d1d1a Another fix for the spyserver source 2021-07-19 05:18:58 +02:00
0d993937b3 Fixed linux issue 2021-07-19 05:07:24 +02:00
79e2747aed New spyserver source 2021-07-19 04:52:13 +02:00
8d3557268f bugfix 2021-07-18 04:39:21 +02:00
336d69c043 Finished RigCTL server 2021-07-18 04:30:55 +02:00
2ddb1b93c4 Fixed typo in CI 2021-07-17 20:07:26 +02:00
63ae56cb9b Added a new optional audio sink as a test 2021-07-17 19:43:44 +02:00
45e4c21870 Fixed network lib bug on linux 2021-07-16 18:13:18 +02:00
ead7ee153a Merge pull request #170 from Starman0620/master
Add CB to Canadian bandplan
2021-07-16 14:39:46 +02:00
9cb6d96f8f Added new patron 2021-07-16 03:21:53 +02:00
0b7a7ca193 slight bugfix 2021-07-16 03:11:49 +02:00
f6e0e2f39d New custom network lib + half finished rigctl server 2021-07-16 01:49:41 +02:00
def6036b30 New custom network lib + half finished rigctl server 2021-07-16 01:49:33 +02:00
943d23a7ce Added CB to Canadian bandplan 2021-07-15 15:54:05 -04:00
218844ed47 Fixed sample rate not updating 2021-07-14 01:58:59 +02:00
794c486352 Another fix attempt 2021-07-13 22:16:20 +02:00
e6293b6435 fixed error 2021-07-13 22:07:01 +02:00
6ef58f2e7c Merge pull request #167 from mbiette/hackrf_close_workaround
Added error log to the HackRF start and stop calls
2021-07-13 21:12:32 +02:00
c0f3babc49 Fixed code style 2021-07-13 21:12:07 +02:00
0ff287cbfb Merge pull request #169 from KentuckyFriedData/patch-1
Fixed small typos
2021-07-13 21:05:51 +02:00
0c40a2954d Fixed small typos 2021-07-13 11:59:38 -07:00
4735fd238a Bugfix 2021-07-13 20:34:31 +02:00
ace0f4a316 Performance improvements 2021-07-13 20:15:42 +02:00
6583104a96 Add error details on libhackrf open/close 2021-07-13 13:21:02 -04:00
4a5a29a59a Fixed the audio glitches!!! 2021-07-13 18:47:34 +02:00
ff38cefe11 Merge pull request #168 from mbiette/fix_typo
Fix typo untyped_steam -> untyped_stream
2021-07-13 00:17:10 +02:00
168226c634 Fix typo untyped_steam -> untyped_stream 2021-07-12 17:49:06 -04:00
3d7cfffe13 potential fix for the RTL-SDR not tuning (mayhaps?) 2021-07-12 16:53:59 +02:00
6f409b59c8 Fixed credit screen not centered 2021-07-12 16:20:59 +02:00
ff030397a4 DSP code cleanup 2021-07-12 05:03:51 +02:00
1f1b0cd45e Merge pull request #164 from mbiette/fix_delete
Fix destructor crash due to wild pointer
2021-07-12 01:22:02 +02:00
4aaf71f5cc Fixed code style 2021-07-12 00:58:39 +02:00
5971d3d3b3 Fix destructor crash due to wild pointer
Otherwise when RingBuffer is deleted before its init() being called it would crash in the destructor due to its _buffer pointer not being initialized.
2021-07-11 18:33:41 -04:00
2151d1e6cc Merge pull request #163 from cropinghigh/patch-1
Add gqrx colormap
2021-07-11 20:13:42 +02:00
b2d8e19504 fixed case 2021-07-11 20:13:30 +02:00
939197df6b Add gqrx colormap 2021-07-11 13:27:15 +03:00
eb48dd70fb More UI bugfix 2021-07-10 21:15:20 +02:00
6cca4c654f Optimized the menu + bugfix 2021-07-10 18:33:11 +02:00
f86df07c36 bugfix 2021-07-10 01:07:26 +02:00
73bbd69e3f The enabled state of all modules is now preserved 2021-07-10 00:28:56 +02:00
fd9f4ebdc3 Merge pull request #162 from mbiette/fix_typo
Fix typo aquire -> acquire
2021-07-09 21:50:15 +02:00
ac04432453 Fix typo aquire -> acquire
https://en.wiktionary.org/wiki/aquire
2021-07-09 14:57:58 -04:00
91c6823e0c Bugfix 2021-07-09 17:55:17 +02:00
cf3c976651 Added a way to move menus around 2021-07-09 04:29:16 +02:00
29ec14d3f0 Added a better offset config for up/down converters 2021-07-09 00:58:05 +02:00
ba208bf8b3 Added new contributor 2021-07-08 22:41:36 +02:00
7ebfddc03c Merge pull request #160 from mbiette/fix_doc
Improve documentation for windows build
2021-07-08 22:39:57 +02:00
61f56b6e56 Updated ImGui + Fixed bugs in the frequency manager + new features 2021-07-08 22:39:26 +02:00
132f591288 removed outdated folders from the gitignore left there by accident 2021-07-08 22:36:28 +02:00
7e6b9d8487 Changed a few things 2021-07-08 22:35:14 +02:00
4c8b810bd6 Improving Windows build instructions 2021-07-08 10:33:58 -04:00
f9ad86e312 Update .gitignore for Visual Studio, ReSharper and CLion 2021-07-08 10:29:28 -04:00
7219e3a4de Switched back to portaudio for macos 2021-07-06 23:53:11 +02:00
1bc49426e2 Update readme.md 2021-07-05 20:45:04 +02:00
41a307fd35 Update readme.md 2021-07-05 20:44:30 +02:00
d4849af171 Fixed windowing not being enabled by default 2021-07-05 05:26:49 +02:00
ab376ea1aa Performance improvement to the FFT + code cleanup + Added an option to select the FFT window 2021-07-05 01:09:48 +02:00
6db8251e46 Fixed bugs + added option to show bookmarks on FFT 2021-07-04 16:41:46 +02:00
4dc0df74cf Added option to show current list on FFT 2021-07-04 02:25:36 +02:00
5b9bd56cf2 Fixed missing frequency manager from windows CI 2021-07-03 20:39:35 +02:00
ecbb451763 Added zimm to contrib list 2021-07-03 20:31:54 +02:00
78f079ca84 Finished the frequency manager module 2021-07-03 19:46:21 +02:00
a408084237 changed name 2021-07-03 16:29:26 +02:00
9c0602f406 more changes 2021-07-03 16:15:27 +02:00
3f6b8dbe6c Merge pull request #157 from marvin-sinister/feature-improve-build
Improve docker builds
2021-07-03 15:09:51 +02:00
5a21b07269 revert package installation changes 2021-07-03 14:46:55 +02:00
b96206765a Path fix 2021-07-03 13:44:56 +02:00
f0b2d80ba7 docker build improvements 2021-07-03 13:35:42 +02:00
a19e47bd54 more work on the frequency manager and adder 2.4MS/s to rtl tcp 2021-07-03 00:08:01 +02:00
4a2774367f Fixed UI and frequency manager bug 2021-07-02 18:12:56 +02:00
7d720e4d6f Fixed more LimeSDR bugs 2021-07-01 22:23:08 +02:00
b87ec8f2cc Merge pull request #154 from marvin-sinister/feature-debian-version
append build number to debian package version
2021-06-30 17:34:13 +02:00
2c4e221d1c append build number to debian package version 2021-06-30 14:03:30 +02:00
0dbd89db19 Fixed BladeRF and LimeSDR bugs 2021-06-30 03:13:14 +02:00
8f4942bbe9 Mooooore performance 2021-06-30 02:48:36 +02:00
24892c854e Fixed SDRplay source of OSX 2021-06-29 19:37:03 +02:00
5f84ecc4de Added audio fix for MacOS 2021-06-29 18:14:26 +02:00
659b9b1e8c Potential fix for SDR++ not stopping on Linux 2021-06-29 15:52:35 +02:00
8a1df1d712 Fixed SNR not updating when waterfall is hidden 2021-06-29 03:32:40 +02:00
aaa15315ce Fixed file source and cleaned up buffering code 2021-06-29 02:43:04 +02:00
70cf463881 new buffer thingy 2 2021-06-28 22:11:20 +02:00
dff9ec2d37 new buffer thingy 2021-06-28 22:06:42 +02:00
192e86064c Fixed windows CI 2021-06-28 16:28:10 +02:00
bfdeb77f7d Fixed ubuntu hirsute CI 2021-06-28 04:16:37 +02:00
da96ecaaba A lot of new stuff 2021-06-28 02:22:51 +02:00
72a794df6f Disabled bladerf source build for debian buster 2021-06-27 02:36:55 +02:00
c39b9609be Added bladerf source 2021-06-27 02:20:11 +02:00
d31ed762c1 IMPORTANT BUGFIX 2021-06-26 18:26:58 +02:00
dad41e1574 Better light theme 2021-06-24 18:21:07 +02:00
a6aee1d9a4 Fixed themes not being installed 2021-06-24 03:23:30 +02:00
64ed5058bf Fixed wrong disabled color sheme 2021-06-23 22:24:58 +02:00
26079dba0a Added theme system 2021-06-23 21:45:38 +02:00
94fae2135d Cleaned up UI code 2021-06-20 21:17:11 +02:00
1e71a52727 Removed temporary missing code 2021-06-17 20:18:49 +02:00
da2f4fcf3a Changed the default NFM snap interval 2021-06-17 20:14:23 +02:00
b5d38c71ce Added french band plan 2021-05-31 18:39:15 +02:00
8a18bec55c switched pothos version 2021-05-18 20:05:24 +02:00
45ff5dd0cc testing 2021-05-18 02:38:06 +02:00
55017f876d Fixed vfo selection issue 2021-05-18 02:26:55 +02:00
c59b83e564 Merge pull request #141 from invader-zimm/master
Frequency manager by Zimm
2021-05-13 17:32:47 +02:00
c0244e819e Push before merge 2021-05-13 17:31:40 +02:00
3467031bf4 disable Freq Mngr build by default 2021-05-12 18:54:08 -04:00
51ef8b1891 change indentation and brackets style 2021-05-12 18:52:31 -04:00
bbff0036dc maybe fix crash with bookmarks table 2021-05-12 10:49:46 -04:00
e6ab6f3cc9 fix CMakeLists.txt file 2021-05-12 10:38:16 -04:00
99d14f7abb Update CMakeLists.txt 2021-05-12 00:04:12 -04:00
215c17ae20 add frequency manager 2021-05-12 00:03:31 -04:00
b4e1eef8c9 frequency manager initial commit 2021-05-12 00:01:10 -04:00
0b276bed1d Fixed weird audio glitch on some AM station 2021-05-09 03:06:57 +02:00
1b27916c24 Added module management system 2021-05-05 04:31:37 +02:00
85b9649a9a Added BladeRF source to CI 2021-05-04 21:37:57 +02:00
aa9ab8e1e8 Fixed VFO color menu position 2021-05-04 21:05:45 +02:00
1eca58605c Added VFO coloring option 2021-05-04 20:41:23 +02:00
9a1850bd61 Fixed delayed VFO update bug 2021-05-04 02:52:59 +02:00
c23b2bdc55 reduced buffer size 2021-05-03 22:42:10 +02:00
754a9ac406 Acutally moved the mode and freq variables to the stack because why not 2021-05-03 22:40:53 +02:00
3225f15419 Fixed bug in discord integration 2021-05-03 22:38:38 +02:00
b1bb863a7e Added new patron + more bladerf upgrades 2021-05-03 20:21:30 +02:00
b030c22c56 More work on the bladerf 2021-05-03 18:11:46 +02:00
e1086e2d41 Merge pull request #130 from Starman0620/master
Add GitHub info to Rich Presence
2021-05-03 04:23:46 +02:00
4634c8187f More fixes idk 2021-05-03 04:20:48 +02:00
9913124a5c Added GitHub info to Rich Presence 2021-05-02 22:17:56 -04:00
0bc1bd8549 Fixed color interpolation bug 2021-05-03 02:18:26 +02:00
c6c15a446b Fixed OS EventHandler compilation issue 2021-05-03 02:08:49 +02:00
6e4f502454 More work on the BladeRF support 2021-05-02 02:23:10 +02:00
66150922c7 Fixed OSX CI not in group 2021-05-01 14:44:33 +02:00
d1acfeb496 Added MacOS package build 2021-04-30 20:33:51 +02:00
233d5ed838 Fixed mac stuff 2021-04-30 20:10:29 +02:00
860afb2fbd More MacOS related stuff 2021-04-30 19:23:43 +02:00
d8c0c8649c Patched pothos libusb versions in automated builds 2021-04-30 16:34:42 +02:00
55b2b050c8 Fixed crash when changing RSP settings before starting 2021-04-30 15:16:07 +02:00
96f83ee55c Added SNR meter 2021-04-30 04:28:08 +02:00
3e79d4dfad Added tooltip to show VFO name 2021-04-29 23:29:40 +02:00
d3276a1546 Added missing line smh 2021-04-29 22:09:06 +02:00
ce8b4ceb44 Added persistant config for file source 2021-04-29 22:04:20 +02:00
bed0712be1 Recorder should now save dialog path 2021-04-29 21:41:47 +02:00
f483de1f7e Fixed missing vector again 2021-04-29 20:51:26 +02:00
a6df90785a Fixed missing vector 2021-04-29 20:48:37 +02:00
ab4cde9bb8 Added cross platform support for file and folder select widgets 2021-04-29 20:43:17 +02:00
1738706c59 Fixed libusb not found for rtlsdr on OSX 2021-04-29 19:12:54 +02:00
c801b6547f Added workaround for pkgconfig not adding the right directories for libairspy 2021-04-29 16:32:06 +02:00
490243e346 Fixed bad directory for MacOS CI 2021-04-29 15:51:32 +02:00
17db61c302 Fixed target name for airspy source 2021-04-29 15:44:32 +02:00
bef4a6efc1 Fixed soapy source name macos 2021-04-29 15:37:04 +02:00
26605b8d90 Added MacOS CI 2 2021-04-29 15:34:08 +02:00
8b25d74dde Added MacOS CI$ 2021-04-29 15:32:59 +02:00
8c8acf6955 Fixed missing library dir argument for OSX 2021-04-29 14:30:11 +02:00
6aade531a2 Merge pull request #122 from Starman0620/master
Fix Canada bandplan
2021-04-28 21:26:41 +02:00
53f2caa9cc Fixed Canada bandplan
Weatheradio/Environment Canada weather was mistyped as an amateur band
2021-04-28 15:04:30 -04:00
ac474902a4 Bugfix for SDRplay source crashes 2021-04-28 15:34:24 +02:00
20c47ae8f2 Added new contributors to credits and added file name standards to contributing.md 2021-04-28 13:42:05 +02:00
7d4fdad6f6 More additions to contributing.md 2021-04-27 20:16:01 +02:00
de3ee34fce Fixed audio sink not deleting instance 2021-04-27 16:48:54 +02:00
7481f0432b Merge pull request #116 from Starman0620/master
Add Canadian Bandplan
2021-04-27 13:02:53 +02:00
41709ef916 Merge branch 'master' of https://github.com/AlexandreRouma/SDRPlusPlus 2021-04-26 21:50:48 -04:00
935534905f Added Canada bandplan 2021-04-26 21:50:10 -04:00
b9a41c83bf Added sdrplay source to CI 2021-04-26 23:34:24 +02:00
54165c64ec Fixed CI again... 2021-04-26 20:17:57 +02:00
0300be1c4b Fixed contributing.md 2021-04-26 19:59:41 +02:00
48932a5230 Added automatic build for full archive 3 2021-04-26 19:43:55 +02:00
624817618c Added automatic build for full archive 2 2021-04-26 19:28:19 +02:00
48399d341f Added automatic build for full archive 2021-04-26 19:27:05 +02:00
48ae57ad2d Added CI for debian sid 2021-04-26 17:41:03 +02:00
128e52e33a Dropping support for old volk and ubuntu versions, please update..; 2021-04-26 17:03:52 +02:00
27697bb638 More bionic compatibility 2021-04-26 16:55:55 +02:00
ed29f9dcc5 Added work around for old volk versions 2021-04-26 16:02:03 +02:00
78c7ef0242 Fixed more bionic stuff 2 2021-04-26 15:34:32 +02:00
95f7171256 Fixed more bionic stuff 2021-04-26 15:30:52 +02:00
f968725469 Fixed cmake 3.10 compatibility for ubuntu bionic based distros 2021-04-26 15:25:28 +02:00
3d65e515ad Fixed bad cmake command 2021-04-26 15:17:24 +02:00
1ba3756be0 Fixed cmake bug and added ubuntu bionic 2021-04-26 15:12:52 +02:00
061cb91c48 Fixed CI Stall 2021-04-26 14:38:14 +02:00
5feba74b9b Fixed stalling issue 2021-04-26 14:21:45 +02:00
6117635a8d Merge pull request #114 from JoshuaKimsey/band-plan-organising
Standardized sorting of bands array for band allocation plans
2021-04-26 13:29:55 +02:00
8c70d816a0 Added JSON styling guides to the Contribution file
* Added guides to the Contribution file for how to properly style and organise the JSON files for Band allocation identifiers and colour maps.
2021-04-26 03:03:38 -04:00
c862882499 Added other ubuntu versions to CI 3 2021-04-26 05:48:52 +02:00
b9642f1e62 Added other ubuntu versions to CI 2 2021-04-26 05:44:55 +02:00
481d5a6b14 Added other ubuntu versions to CI 2021-04-26 05:43:40 +02:00
6deae14870 Standardised sorting of bands array for band plans
* Standardised organisation of the bands array in the band allocation JSON files. They are now organised by the starting frequency.

* Added 'Polar Orbiting Satellites' to the general JSON file, as that affects all general users.
2021-04-25 23:34:02 -04:00
102eea134c Fixed CI for debian 10 and 11 4 2021-04-26 05:23:41 +02:00
1894e191d5 Fixed CI for debian 10 and 11 3 2021-04-26 05:13:32 +02:00
36f2b157e5 Fixed CI for debian 10 and 11 2 2021-04-26 05:07:09 +02:00
e4b4787cbb Merge pull request #113 from JoshuaKimsey/usa-band-plan
Added band allocation plan for the USA
2021-04-26 05:05:54 +02:00
78e40f1f76 Fixed CI for debian 10 and 11 2021-04-26 05:04:31 +02:00
8596c26f7e Fixed CI for debian 10 and 11 2021-04-26 05:04:20 +02:00
a4ce0c8868 Added CI for debian 10 and 11 2021-04-26 04:59:37 +02:00
86702040a4 Added band allocation plan for the USA
* Added band allocation markers for NOAA Weather Radio, Polar Orbiting Satellites, and TV Channel Broadcasting frequencies. Will add more as time moves along.

* Changed some frequencies to better fit with FCC declared frequency ranges.

* Fixed issue with bands array not being organised. Will now be organised by start frequency.

(All relevant information was pulled from the FCC to ensure accuracy)
2021-04-25 22:47:58 -04:00
5322a4632c quick test for volk 2021-04-26 01:59:26 +02:00
670b5aefce Added new patron to credits 2021-04-25 22:54:09 +02:00
f316856682 fixed contributing.md 2021-04-25 19:50:07 +02:00
1c18310f37 adde contributing.md 2021-04-25 19:44:41 +02:00
8c428be885 Fixed ubuntu version in CI 2021-04-25 03:53:31 +02:00
c9a247b64d Added pothos to windows CI 12 2021-04-25 01:21:48 +02:00
95d2d2d7c8 Added pothos to windows CI 11 2021-04-25 00:44:30 +02:00
8eb1067da5 Added pothos to windows CI 10 2021-04-25 00:25:02 +02:00
d08611ee91 Added pothos to windows CI 9 2021-04-25 00:05:47 +02:00
289eba7855 Added pothos to windows CI 8 2021-04-24 23:47:35 +02:00
31e7867915 Added pothos to windows CI 7 2021-04-24 23:46:59 +02:00
5fd1509c96 Added pothos to windows CI 6 2021-04-24 23:25:44 +02:00
e2b897f1f2 Added pothos to windows CI 5 2021-04-24 22:58:19 +02:00
2628700ea8 Added pothos to windows CI 4 2021-04-24 22:50:38 +02:00
10d368444b Added pothos to windows CI 3 2021-04-24 22:20:33 +02:00
75b54fb9b4 Added pothos to windows CI 2 2021-04-24 22:05:02 +02:00
f0250f0cd1 Added pothos to windows CI 2021-04-24 22:01:28 +02:00
db1ab774f0 More windows CI stuff 2021-04-24 21:32:55 +02:00
28d189e35a Windows CI 3 2021-04-24 21:21:10 +02:00
5c487b73ab Fix CI 2 2021-04-24 21:17:49 +02:00
71eb2735f6 Fix CI 2021-04-24 21:17:00 +02:00
53ba9eddf7 Windows CI 2 2021-04-24 21:16:06 +02:00
3efdd51fa6 Windows CI 2021-04-24 21:12:04 +02:00
e115161da8 Merge pull request #108 from KentuckyFriedData/patch-1
Fixed typos and some grammar
2021-04-24 20:58:56 +02:00
dec16eeb87 push before merge 2021-04-24 20:58:33 +02:00
2a22a125bb Fixed bug 2021-04-24 19:41:02 +02:00
8305750016 Fixed frequency select not updating when disabling VFO 2021-04-24 19:26:22 +02:00
77ac94ff99 Fixed typos and some grammar 2021-04-24 09:59:57 -07:00
35122708be Fixed wrong env var name again 2021-04-24 16:44:41 +02:00
6152403faf Fixed wrong env var name 2021-04-24 16:25:07 +02:00
cd4f64bc80 saving github actions artifact 2 2021-04-24 16:11:56 +02:00
7a95229cc2 saving github actions artifact 2021-04-24 16:09:42 +02:00
df42830d38 testing github actions 2021-04-24 15:52:22 +02:00
2df1869824 Fixed typo 2021-04-24 04:30:30 +02:00
05440ed2fc Fixed missing .json 2021-04-24 04:27:32 +02:00
7a9371c062 Merge pull request #106 from Starman0620/master
Revised readme.md
2021-04-24 04:26:08 +02:00
fc350871e4 Update readme 2021-04-23 22:18:17 -04:00
88fe31fead Fixed code block in readme 2021-04-23 22:17:09 -04:00
fc7ecab5f2 Update readme 2021-04-23 22:14:39 -04:00
0382b8aed8 Update readme 2021-04-23 22:13:54 -04:00
a35d0252e7 Fixed scroll bug and added keybinds 2021-04-24 04:06:04 +02:00
dd5490cac6 Added scroll controls 2021-04-24 01:24:27 +02:00
75568a7bf7 added keyboard input to frequency select 2021-04-23 21:35:54 +02:00
b8347fd254 More keyboard controls 2021-04-23 19:12:24 +02:00
d43f501819 Added more keyboard controls 2021-04-23 17:53:25 +02:00
b8e4a79188 Fixed inexplicable ImGui bug 2021-04-23 03:58:10 +02:00
1dbdf48e9a Added persistant menu open/close 2021-04-22 23:49:35 +02:00
ed83abaeef meteor demodulator now saves the recording path 2021-04-22 19:18:19 +02:00
89e805b1a0 more stuff 2021-04-22 05:58:20 +02:00
a4c25280b3 bunch of stuff idk i'm tired 2021-04-22 05:38:25 +02:00
72cbf741b3 Code clean up + added inter module communication 2021-04-22 04:15:23 +02:00
2c83d79836 Fixed hackrf performance issues 2021-04-22 02:18:43 +02:00
9efdb6b150 Merge pull request #102 from Starman0620/master
Add Discord Rich Presence module
2021-04-22 02:17:29 +02:00
20ce4efebb Removed Discords dumb crap from discord-rpc 2021-04-21 20:11:47 -04:00
d3ad4a5035 Added persistent config for VFO offsets 2021-04-22 02:00:33 +02:00
5edb838f31 Renamed discord-integration to discord_integration 2021-04-21 19:58:07 -04:00
89dfeeb247 Renamed discord-integration to discord_integration 2021-04-21 19:52:16 -04:00
956969f679 Removed discord-integration GUI element
This was done because there's no point in having an enable/disable checkbox when the module itself isn't even loaded on default.
2021-04-21 19:25:15 -04:00
7ee86a5d40 Merge branch 'master' of https://github.com/Starman0620/SDRPlusPlus; branch 'master' of https://github.com/AlexandreRouma/SDRPlusPlus 2021-04-21 19:20:00 -04:00
f8be28dcee Enabled discord-integration on default 2021-04-21 19:19:36 -04:00
bc11ef7e9c Added rapidjson to discord-integration 2021-04-21 19:15:10 -04:00
eb8cd09e65 Another fix for the weird no exit thing 2021-04-21 20:06:30 +02:00
77dada07da Fixed sdrpp not exiting 2021-04-21 19:24:58 +02:00
e236c42068 Fixed missing include 2021-04-21 18:39:47 +02:00
38c9e2c894 Fixed delay before exiting 2021-04-21 18:36:45 +02:00
a4fa7d2ff6 Merge branch 'master' of https://github.com/AlexandreRouma/SDRPlusPlus 2021-04-21 12:00:00 -04:00
61ebff209b Fixed enable/disable bug in discord-integration 2021-04-21 11:59:03 -04:00
4849d9cf09 Fix for threads not terminating 2021-04-21 17:23:09 +02:00
a0316e57c5 Fixed gain bug for RSPduo 2021-04-21 14:53:09 +02:00
6332b33f3e Fixed RSP fft lag 2021-04-21 03:03:40 +02:00
7d6ecf923b Disabled discord-integration on default in CMakeLists 2021-04-20 18:31:59 -04:00
8e194ba5a9 Switched the 10s timer in discord-integration to be thread based 2021-04-20 18:31:28 -04:00
99ec2a12f1 Cleaned up discord-integration 2021-04-20 18:19:58 -04:00
dd0ec72fb7 Merge remote-tracking branch 'origin/master' 2021-04-20 18:15:13 -04:00
271e4a6f46 Changed frequency fetching for discord-integration 2021-04-20 18:15:08 -04:00
a9d1d9b9e7 Changed frequency fetching 2021-04-20 18:14:58 -04:00
9776191e83 Added discord-rpc files 2021-04-20 17:33:11 -04:00
a0f955e907 Full support for the RSPduo 2021-04-20 22:53:23 +02:00
18eb29fabd Renamed rich presence module 2021-04-20 14:34:54 -04:00
f23faa72ec Removed submodule discord/discord-rpc 2021-04-20 14:26:55 -04:00
70c7060eaf Added frequency display to presence 2021-04-20 14:26:48 -04:00
6420553ae9 Added basic rich presence 2021-04-19 21:47:11 -04:00
dc65ff3a05 Added discord-rpc to build process 2021-04-19 21:19:16 -04:00
c9a44d1ecf Added discord-rpc submodule 2021-04-19 21:06:58 -04:00
13949e0dde Merge branch 'master' of https://github.com/Starman0620/SDRPlusPlus; branch 'master' of https://github.com/AlexandreRouma/SDRPlusPlus
Merge updated files
2021-04-19 21:02:45 -04:00
35d50c91c7 Adjusted Discord UI 2021-04-19 20:59:39 -04:00
3a142b0d85 Added boilerplate code for Discord module 2021-04-19 20:58:47 -04:00
f119af5e6f Fix AGC for SDRplay 2021-04-20 01:38:32 +02:00
a91ed266d5 Fixed other potential bug on OSX 2021-04-19 19:46:03 +02:00
bdce551a50 Fixed module extension on OSX 2021-04-18 21:36:15 +02:00
89599d0bf8 More OSX fixes (this is becoming annoying...) 2021-04-18 20:30:21 +02:00
685a14a21e removed unused bug 2021-04-18 20:08:28 +02:00
24e6ac8013 Bugfix for OSX 8 2021-04-18 20:04:59 +02:00
2b4cc46a53 Bugfix for OSX 7 2021-04-18 20:00:47 +02:00
30e8b3b60e Bugfix for OSX 6 2021-04-18 19:32:18 +02:00
026e5f9bcb Bugfix for OSX 5 2021-04-18 19:29:03 +02:00
3c9b8db090 Bugfix for OSX 4 2021-04-18 19:24:56 +02:00
234e1618c8 Bugfix for OSX 3 2021-04-18 19:20:51 +02:00
bc605f1351 Bugfix for OSX 2 2021-04-18 19:17:20 +02:00
06b524213f Bugfix for OSX 2021-04-18 19:12:07 +02:00
21cea65fbe Fixed board not selected after refresh bug for hackrf 2021-04-18 17:59:42 +02:00
000429c3b5 removed debug log 2021-04-18 15:59:37 +02:00
85d79f25d9 new fixes 3 2021-04-18 04:16:17 +02:00
31b7d97097 new fixes 2 2021-04-18 04:15:31 +02:00
16098ba717 new fixesµ 2021-04-18 04:13:46 +02:00
dfd29bfa04 Added fixes for clang 2021-04-18 03:52:13 +02:00
ba25eee09a Rollback of changes to resampler 2021-04-18 01:15:57 +02:00
cf4cfb50fc Even more fixes 2021-04-18 01:04:50 +02:00
91176c9291 More fixes to wfù 2021-04-18 00:47:23 +02:00
5aa9359236 Fixed FM bug 2021-04-18 00:13:32 +02:00
f760aba7dd Fixed waterfall bug 2021-04-17 23:05:53 +02:00
b0409ad033 Fix linux bug 2021-04-17 22:41:46 +02:00
d91934955b New features + waterfall code cleanup 2021-04-17 22:37:50 +02:00
d1e553f05a Fixes to filtering 2021-04-17 03:38:48 +02:00
3bf4f0ce01 typo fix 2021-04-16 20:21:42 +02:00
892f957729 Merge pull request #96 from bvernoux/master
Fix build with Windows SDK 8.1 or more, fix typos in airspy_source
2021-04-16 19:55:05 +02:00
d903daa046 added missing files 2021-04-16 19:54:08 +02:00
b16ab3f0c0 Push before merge 2021-04-16 19:53:47 +02:00
c2bccc9b04 Fixed some typos in spdlog::error() for airspy_source (removed HF+) 2021-04-16 19:48:25 +02:00
0b9d5c2b69 Fix build with SDK 8.1 or more (replace #include <ShlObj_core.h> supported only with Windows SDK10 by #include <ShlObj.h> support by Windows SDK 8.1 or more) 2021-04-16 19:40:12 +02:00
098f09844b Fixed deemphasis bug 2021-04-14 02:03:03 +02:00
2c334c08ac Added position option for the bandplan 2021-04-14 01:45:21 +02:00
11766a2c41 added saved config to recorder 2021-04-14 01:07:54 +02:00
ce389dfd79 Added HackRF source built by default 2021-04-13 18:35:31 +02:00
48bba00cb3 Added FFTSize setting 2021-04-13 18:31:38 +02:00
b74043e2ee Changed defaults 2021-04-13 04:57:42 +02:00
64436f1034 New changes 2021-04-13 04:54:47 +02:00
58864b79e4 Slight performance improvement on detailed fft 2021-04-13 03:52:30 +02:00
cb8bbd7ccc New optional detailed FFT system 2021-04-12 23:02:45 +02:00
37ad6365e3 Another fix 2 2021-04-10 15:05:45 +02:00
6c4af86b29 Another fix 2021-04-10 15:02:36 +02:00
f492c6fc61 Fixed pluto sample rate bug 2021-04-10 14:55:35 +02:00
d41ae73e0d Beginning of code for the RSPduo + bugfix for the hackrf 2021-04-10 03:06:59 +02:00
26e623bec4 Beginning of code for the RSPduo + bugfix for the hackrf 2021-04-10 03:06:51 +02:00
aeab33127d more audio BS 2021-04-02 18:40:57 +02:00
7b6d0c1acd Fixed deemphasis unit 2021-04-02 14:19:33 +02:00
b16c6f50a6 Fixed bad class name 2021-04-02 03:33:48 +02:00
edf3743f49 Fixed meteor bandwidth 2021-04-02 03:29:48 +02:00
1675ee99a4 added throttle block 2021-04-02 00:35:05 +02:00
f88e2312b8 more bugfix on the meteor demod 2021-04-01 20:57:03 +02:00
28aaeef2b6 Fixed other issues 2 2021-04-01 17:42:30 +02:00
669288385e Fixed other issues 2021-04-01 17:42:04 +02:00
4b0516966d Fixed missing semicolon 2021-04-01 17:33:59 +02:00
a9cb6bfe79 Bugfix + added meteor demodulator 2021-04-01 16:54:16 +02:00
bcc1744a76 More bugfix 2021-03-30 03:37:40 +02:00
ce56d03c3e Another fix 2021-03-29 22:41:17 +02:00
38c1949538 Fixed bug with operators 2021-03-29 22:28:26 +02:00
27394a091f DSP performance upgrades + bugfix 2021-03-29 21:53:43 +02:00
b72246d769 Merge pull request #85 from nonoo/master
Fix file source rewind and read after it is finished
2021-03-23 00:45:18 +01:00
a6e58e7b1d Fix compile error caused by inline instructions
Issue: https://github.com/AlexandreRouma/SDRPlusPlus/issues/82
Fix: https://stackoverflow.com/questions/54654290/error-inlining-failed-to-call-always-inline
2021-03-22 22:35:28 +01:00
ad579d514b Fix file source rewind and read after it is finished 2021-03-22 22:12:55 +01:00
3b657484b2 explicitly logging if the recording started 2021-03-21 23:54:41 +01:00
eff9cd4b71 fixed bug introduced in recorder by the last commit 2021-03-21 23:53:45 +01:00
5e9486ef4c Fixed broken code 2021-03-21 19:51:38 +01:00
f29d683918 new stuff 2021-03-20 21:53:44 +01:00
f55d591cba added frequency in recording + fixed SDRplay typo 2021-03-12 22:22:14 +01:00
20ee982e3d Added persistent config for sdrplay + bugfix 2021-03-09 02:21:30 +01:00
c21db4b6d1 added new patron 2021-03-08 16:38:48 +01:00
f0ef239e22 Fixed patron name 2021-03-07 20:11:35 +01:00
a714370eb2 Preparations for RSPduo support + Added new patrons! 2021-03-07 20:10:10 +01:00
abf5ad2eec fixed swapped b and hi-z ports 2021-03-07 16:14:08 +01:00
68fdd7e3f0 Fixed gains 2021-03-07 00:57:08 +01:00
49e671802a Fixed Dab notch 2021-03-07 00:47:12 +01:00
da8fa813c5 Fix for RSP2 2021-03-07 00:22:35 +01:00
c823f0759d Added support for rsp2 and rspdx 2021-03-06 22:56:35 +01:00
c71f7898ed fixes 2021-03-06 19:23:03 +01:00
a24972843e Fixed bad argument in compile args 2021-03-01 17:39:39 +01:00
9f0262fc05 bugfix + added missing contributors 2021-02-28 17:32:22 +01:00
4fc55f75a8 Added stream name 2021-02-28 16:32:57 +01:00
fcb1d94946 Added bias-T support plus fixed bugs for sdrplay module 2021-02-26 21:33:48 +01:00
38acf81a76 Fixed wrong sdprlay lib name for linux 4 2021-02-26 18:25:52 +01:00
eaae856a37 Fixed wrong sdprlay lib name for linux 3 2021-02-26 18:13:54 +01:00
79df475c9d Fixed wrong sdprlay lib name for linux 2 2021-02-26 18:11:54 +01:00
a6ce43ba71 Fixed wrong sdprlay lib name for linxu 2021-02-26 18:04:54 +01:00
9e0fee27ab added more options to sdrplay module 2021-02-26 16:52:54 +01:00
d3a6ee6a94 Hide antenna select when SDR only has one antenna 2021-02-23 15:15:29 +01:00
a4ec53c90a Merge pull request #75 from aosync/master
Added conditionals to build on FreeBSD
2021-02-23 14:55:08 +01:00
0e7a8301f7 Merge pull request #76 from thotypous/soapy-select-antenna
Support selecting antenna for SoapySDR source
2021-02-23 14:54:18 +01:00
5b4c5bd5c1 Support selecting antenna for SoapySDR source 2021-02-23 00:36:24 -03:00
b4ee6420c5 Fixed weird value idk 2021-02-23 03:35:40 +01:00
e4c062c9c2 yeeted portaudio 2021-02-23 00:26:35 +01:00
72bd3e9cc1 Finished RtAudio sink 2021-02-22 04:04:49 +01:00
49cf3af769 Tuned rtaudio sink 2021-02-21 00:06:41 +01:00
127d6bf0a7 added rtaudio sink 2021-02-20 22:05:13 +01:00
044f8cbffd Fixed some stuff 2 2021-02-20 15:35:39 +01:00
89d0f6b761 Fixed some stuff 2021-02-20 15:27:43 +01:00
d0bea51cd4 Fixed CW demod + fixed bug in sinks 2021-02-18 02:47:19 +01:00
d325dab035 added conditionals to build on FreeBSD 2021-02-17 16:59:30 +01:00
4174554260 Added offset tuning option to rtl-sdr 2021-02-17 16:00:22 +01:00
3a81bb9725 Fixed recorder not creating default recording folder 2021-02-17 02:35:00 +01:00
f96c31deab Fixed bug in radio 2021-02-16 23:56:53 +01:00
aae6f535f5 Fixed bug with radio 2021-02-15 20:16:40 +01:00
23dcc16829 Fixed RTL-SDR module bug 2021-02-15 16:35:54 +01:00
8f9fdd8b70 Added sample rates for RTL-SDR 2021-02-15 14:55:48 +01:00
b4d06697b4 Fixed bug tuning with sdrplay and rtlsdr 2021-02-15 13:18:21 +01:00
cc9da905a6 fixed install prefix 2021-02-14 23:14:42 +01:00
e79fa4145b text in rtlsdr 2021-02-14 22:23:30 +01:00
0769b61dd2 added persistant config and bias t support to rtlsdr module 2021-02-14 15:08:54 +01:00
3a8a29402d Added RTL-SDR module by default 2021-02-13 22:48:42 +01:00
e21b876104 Added librtlsdr to CI 2021-02-13 20:46:08 +01:00
36b5af45c6 Added RTL-SDR source module 2021-02-13 20:43:29 +01:00
d0c14efbd1 Changed the FFT scaling 2021-02-12 23:11:57 +01:00
3e9e6de16d added lazy db thing 2 2021-02-12 22:47:10 +01:00
a754becb46 added lazy db thing 2021-02-12 22:44:29 +01:00
fe9af9ced6 Fixed cmakelists 2021-02-12 00:18:20 +01:00
5c9c8c2670 New debian deb build file 2021-02-12 00:15:35 +01:00
0a4c72c571 fixed cmakelists.txt 2021-02-12 00:05:25 +01:00
f765a07c3b Merge pull request #68 from Aang23/master
Generate a Linux desktop icon
2021-02-12 00:04:09 +01:00
3e81a07563 Generate a Linux desktop icon 2021-02-12 00:03:30 +01:00
c2e376879c Merge pull request #67 from Aang23/master
Properly set CMAKE_INSTALL_PREFIX to /usr by default
2021-02-11 23:35:29 +01:00
548b56cf16 Properly set CMAKE_INSTALL_PREFIX to /usr by default 2021-02-11 23:32:56 +01:00
8333912b24 cleanup up string concat 2021-02-11 23:10:01 +01:00
f879a775f8 Merge pull request #66 from Aang23/master
Support installation via CMake
2021-02-11 22:53:15 +01:00
51573146f0 Changes to sdrplay source 2021-02-11 22:53:00 +01:00
835ec716a0 Support installation via CMake 2021-02-11 22:49:33 +01:00
b86cf9681c temporarily disabled sdrplay_source build for CI 2 2021-02-11 15:39:41 +01:00
3b4cc26210 temporarily disabled sdrplay_source build for CI 2021-02-11 15:37:23 +01:00
3422998bd1 fixed file select and folder select widget bug 2021-02-11 15:29:51 +01:00
c90772666e changed limites on demodulators 2021-02-10 23:15:19 +01:00
096c5edbd4 Fixed file select length 2021-02-10 22:47:13 +01:00
3541b8a0dd new stuff idk 2021-02-10 21:35:56 +01:00
9e410e3856 VFOs are now visible in waterfall 2021-02-09 02:11:40 +01:00
35d079beb1 Maybe fixed airspy and airspyhf crash 2021-02-08 20:27:05 +01:00
c846e0f400 Added spdlog test button 2021-02-08 20:08:59 +01:00
7ff8f3f7b9 Fixed airspy_source bug 2021-02-08 19:50:16 +01:00
27eb2571a4 Fixed power slider 2021-02-08 11:13:26 +01:00
ff2ab3b27e Fixed windows code left outside ifdef 2021-02-08 01:55:57 +01:00
9df90e5e75 removed scrolling due to bug + Fixed file source 2021-02-07 23:47:17 +01:00
49ec3d68d2 Added scroll control to sliders in radio 2021-02-07 14:20:10 +01:00
9def1843b2 Added scroll to sliders 2021-02-07 12:30:25 +01:00
c26855d07e Fixed UI bug 2021-02-06 21:52:58 +01:00
a3f147a827 New recorder plugin + bugfix 2021-02-06 21:28:27 +01:00
a2d93915e8 Added airspy_source to defaults 2021-02-04 14:53:12 +01:00
29e9db184f Fixed small bug in SSB tuning 2021-02-02 21:49:35 +01:00
2f93c7ae58 Fixed wrong sample rate at startup 2021-01-30 02:21:30 +01:00
4abfe407da Removed bad files 2021-01-29 18:29:02 +01:00
9b27e81091 Fixed autobuild 3 2021-01-29 18:26:18 +01:00
39787743fd Fixed autobuild 2 2021-01-29 17:44:56 +01:00
22e47807b8 Fixed autobuild 2021-01-29 17:42:02 +01:00
898525a6d8 Added automatic build to actions 2021-01-29 17:24:10 +01:00
1ebcfe7d80 UI improvements 2021-01-29 16:50:57 +01:00
1dbc39b970 Added persistant config to airspyhf_source 2021-01-29 16:15:13 +01:00
80f5f6c288 Added persistant config to airspy_source + bugfix 2021-01-29 15:07:45 +01:00
b18acd469f Fixed missing dependency in CI 2021-01-28 21:13:09 +01:00
cefcd18269 Added airspy module + changes to the UI for scaling 2021-01-28 21:10:53 +01:00
4de3ac176d Update cmake.yml 2021-01-11 21:47:35 +01:00
afd5699ff1 Added new contributors + fixed waterfall bug 2021-01-11 03:19:09 +01:00
b79461e3ce Merge pull request #60 from mnhauke/master
Add bandplan for German mobile networks
2021-01-03 02:49:20 +01:00
de6ab8ecdf Add bandplan for LTE bands used in Germany 2021-01-02 23:43:49 +01:00
d0180d42a8 Add bandplan for German mobile networks 2021-01-02 21:59:13 +01:00
2e504b40f6 Fixed invalid colormap 2021-01-02 15:18:57 +01:00
9b00304c29 Fixed resampling bug + added waterfall colormap selection + general bugfix 2020-12-31 14:42:09 +01:00
979928ded8 Fixed resampling bug + added waterfall colormap selection + general bugfix 2020-12-31 14:26:12 +01:00
7c4e442432 Fixed gain not updated on RTL-SDR 2020-12-28 14:47:34 +01:00
0dd445f101 Merge pull request #55 from cropinghigh/master
Stepped sliders+bandwidth
2020-12-28 14:40:30 +01:00
f217804838 push before merge 2020-12-28 14:39:30 +01:00
9a630fff06 Merge branch 'master' of https://github.com/cropinghigh/SDRPlusPlus 2020-12-28 16:06:34 +03:00
db508214d7 Merge branch 'master' of https://github.com/AlexandreRouma/SDRPlusPlus 2020-12-28 16:05:57 +03:00
8e764f48ae Fix unusable bw 2020-12-28 16:05:35 +03:00
2583063f5f Update
Update
2020-12-27 15:30:51 +03:00
dd4ec22b39 + contributors list 2020-12-26 23:12:09 +01:00
42dbcec93f Update
Update
2020-12-27 01:11:05 +03:00
9bbf634f5d Merge pull request #52 from zakrent/master
Added SIMD to polyphase resampler
2020-12-26 23:08:45 +01:00
d6b09759de Merge pull request #51 from cropinghigh/patch-1
Addition to linux guide
2020-12-26 23:08:00 +01:00
5bb8a943ad push before merge 2020-12-26 23:02:07 +01:00
b370eda0d5 Fix bugs+move widget 2020-12-27 00:56:39 +03:00
69bcbf6f27 :Added SIMD to polyphase resampler 2020-12-26 22:18:34 +01:00
04823abb83 Fix bugs 2020-12-26 21:36:16 +03:00
7269a0ea12 Merge branch 'patch-1' of https://github.com/cropinghigh/SDRPlusPlus 2020-12-26 21:02:43 +03:00
153b58fbbd Stepped sliders 2020-12-26 21:00:09 +03:00
149af55e61 Addition to linux guide 2020-12-26 11:47:37 +03:00
9cac95fd82 push before merge 2020-12-26 00:48:12 +01:00
09498f3b18 Merge pull request #50 from AlexandreRouma/revert-49-master
Revert " Added recorder volume meter "
2020-12-26 00:47:22 +01:00
bb919d0f32 Revert " Added recorder volume meter " 2020-12-26 00:46:52 +01:00
6d0abd73a5 Merge pull request #49 from zakrent/master
Added recorder volume meter
2020-12-26 00:42:32 +01:00
717f2a822b Merge branch 'master' of https://github.com/zakrent/SDRPlusPlus 2020-12-26 01:17:37 +01:00
8946b4b4b6 Added recorder volume meter 2020-12-26 01:07:07 +01:00
db279d2b36 Fixed audio freeze on linux 2020-12-25 19:58:52 +01:00
bb7965b3c4 Fixed luckup bug 2020-12-25 18:17:43 +01:00
a33fe5a4cc Added cropinghigh to contributor's list 2020-12-25 17:22:24 +01:00
4a03f0870c Merge pull request #47 from cropinghigh/patch-3
Update russian bandplan
2020-12-25 17:10:33 +01:00
bfe15aff19 Merge pull request #48 from AlexandreRouma/double_bufferd_streams
switched all streams to double buffering
2020-12-25 17:10:13 +01:00
42bc2d01f7 switched all streams to double buffering 2020-12-25 16:58:07 +01:00
0cb9fc0df8 Update russian bandplan 2020-12-25 16:39:24 +03:00
450896b122 OpenGL version fix for shitty SoCs 2020-12-24 23:38:45 +01:00
cc0b89dbe2 fixed wrong dependency in readme 2020-12-24 19:44:17 +01:00
c887b96a77 fixed wrong dependency in readme 2020-12-24 19:44:07 +01:00
22541ae0f4 updated readme 2020-12-24 16:27:12 +01:00
d83da38d79 Added windows build script 2020-12-24 14:43:14 +01:00
b21f8abbd6 fixed missing module 2020-12-24 00:11:33 +01:00
e9aade4d0d fixed debian build again again 2020-12-23 23:39:34 +01:00
2bf2fff3d6 fixed debian build again 2020-12-23 23:34:56 +01:00
463a22fdfb fixed debian build 2 2020-12-23 23:20:28 +01:00
3175022b31 fixed debian build 2020-12-23 23:18:44 +01:00
504d910226 removed automated debian package build 2020-12-23 22:21:46 +01:00
c2769e1a72 fixed CI 2 2020-12-23 21:59:05 +01:00
7577253dbf fixed CI 2020-12-23 21:19:02 +01:00
e4c5b2dbd1 fixed directories 2020-12-23 21:10:24 +01:00
fafd76ff94 Added debian package build 2020-12-23 20:58:02 +01:00
e354d11820 Added debian package build 2020-12-23 20:57:41 +01:00
a3374c7eca fixed airspyhf module missing function 2020-12-23 20:22:20 +01:00
552b886cea fixed volk version in CI 2020-12-23 20:10:55 +01:00
ff9a19381b switch to more recent ubuntu version for CI 2020-12-23 20:09:08 +01:00
77aacc2e5d Fixed compiler version 2020-12-23 19:50:54 +01:00
6a1fa2c13b added more recent GCC version to CI 2020-12-23 19:44:34 +01:00
c3bb64bf6e Update cmake.yml 2020-12-23 19:39:14 +01:00
da68ab4ed0 Create cmake.yml 2020-12-23 19:36:12 +01:00
1aedf92bcd fixes to the rtl-tcp source 2020-12-23 19:23:47 +01:00
abcf484506 removed un-necessary directory 2020-12-23 00:12:52 +01:00
a93681a980 New system for band plans 2020-12-23 00:11:12 +01:00
a08758ea54 fixed directory bug on linux 2 2020-12-22 23:10:49 +01:00
0a0f5b8e8c fixed directory bug on linux 2020-12-22 23:04:46 +01:00
84f67a3ac1 updated readme about new directory system 2020-12-22 22:45:27 +01:00
22d18a9e58 new directory system on linux 2020-12-22 22:39:24 +01:00
d1a8425d43 Create FUNDING.yml 2020-12-22 21:42:16 +01:00
65d94f03e4 Fixed compile bugs 2020-12-22 21:23:49 +01:00
3a49041f27 other fix 2020-12-22 21:09:49 +01:00
eec2f7c4a0 fixed bug in spyserevr source 2020-12-22 20:44:49 +01:00
720df5ce89 Fixed build issues 2 2020-12-22 20:37:10 +01:00
d7cea16d4a Fixed build issues 2020-12-22 20:35:31 +01:00
d5c0fdd525 fixed linux build bug 2020-12-22 20:00:51 +01:00
4a86d6073c added better credit system 2020-12-22 18:42:30 +01:00
98b6e580b4 updated readme 2020-12-22 18:23:26 +01:00
c96c69c112 changes to the build system 2020-12-22 14:56:57 +01:00
bd545feb2c changes to the build system 2020-12-22 14:50:26 +01:00
e90b6656c3 Fixed airspy hf+ module bug 2020-12-16 01:45:17 +01:00
5099c16a12 Added airpyhf_source 2020-12-15 23:05:11 +01:00
d9dcfa4a88 Fixed waterfall non-threadsafe behavior 2020-12-14 19:33:30 +01:00
1fcd783dd9 fixed zoom bug 2020-12-14 18:14:04 +01:00
2c84123158 modified soapy menu 2020-12-14 17:18:43 +01:00
c3d39029b8 Merge pull request #42 from wingrime/sample-rate
Soapysdr: Improve sample rate information
2020-12-14 17:01:50 +01:00
20b703f8bf push before merge 2020-12-14 16:37:56 +01:00
89c579880c Soapy: Refresh button 2020-12-14 19:46:05 +05:00
db389372ad Soapysdr: Improve sample rate information 2020-12-14 19:34:44 +05:00
3a6eaf6526 Removed second radio from the default config 2020-12-14 01:15:52 +01:00
3e27af472b added more info to the readme 2020-12-14 01:07:30 +01:00
7bea6058fe modified readme 2020-12-14 00:47:11 +01:00
b02b6c30b5 Merge pull request #40 from AlexandreRouma/better_dsp
Better dsp
2020-12-14 00:23:35 +01:00
46e9266752 fixed soapy bug 2020-12-13 14:52:54 +01:00
e3db19b16a Bugfixed + performance improvements to the waterfall 2020-12-12 05:34:58 +01:00
774663d70d Added squelch to radio 2020-12-10 05:18:40 +01:00
2c729bf646 Added persistant settings to recorder module 2020-12-09 19:45:32 +01:00
9b1c9e9e29 Added persistant config for the selected demodulator 2020-12-09 15:28:31 +01:00
80badebb37 Added persistant setting sto demodulator of radio module 2020-12-09 15:16:38 +01:00
fc9e155481 random bug fixes 2020-12-09 04:47:30 +01:00
16d8a31c12 center tuning and more 2020-12-08 16:27:52 +01:00
7ba6081cb3 tweaks 2020-12-08 04:44:19 +01:00
c3a8865dd3 Fixed a tone of stuff + new features 2020-12-08 04:36:37 +01:00
929ca50b06 Added AGC + Started working on channel selection 2020-12-07 04:13:16 +01:00
e5123dd8bf Fixed UI bug in radio 2020-12-06 20:02:22 +01:00
fe1de4bed9 Fixed SSB demod bug 2020-12-06 19:51:56 +01:00
c612620ca5 testing 2020-12-06 17:57:44 +01:00
ca9d2c01af other potential fix 2020-12-06 17:26:42 +01:00
51d90c1898 fixed missing include 2020-12-06 17:02:47 +01:00
a6a4193fbb potential fix to audio issues 2020-12-06 16:46:50 +01:00
f4f8c77ffa Fixed bugs + new radio 2020-12-06 16:13:47 +01:00
9b8c1a3072 More bugfix + folder selection in recorder 2020-12-05 22:42:12 +01:00
92b77904f6 more fixes 2020-12-04 20:12:36 +01:00
9805e4a395 Fixed loading screen 2020-11-30 21:17:36 +01:00
6a01c9d426 trying to fix underrun when switching sdr 2020-11-30 17:43:53 +01:00
48df92c8a5 Fixed bug in GUI 2020-11-30 16:45:02 +01:00
5bb2f9bf05 Fixed compile bug on linux 2020-11-30 16:30:45 +01:00
e5dbac4345 Finished sink module system + new icons 2020-11-30 16:05:51 +01:00
618d4ac4cc fix 2020-11-30 05:51:33 +01:00
19e516f206 Push before potential f*ck up 2020-11-29 20:55:00 +01:00
afadb71d64 Fixed sample rate bug 2020-11-28 23:25:14 +01:00
b3d1eabbad Fixed sample rate bug 2020-11-28 23:24:45 +01:00
eac0a7a13f Fixed FIR bug with the pluto module 2020-11-26 19:25:58 +01:00
e06ed84330 fixed wrong ip string 2020-11-25 21:54:30 +01:00
4eae7c3ba5 plutosdr support 2020-11-25 21:52:37 +01:00
61a612cf30 More work on the sink interface 2020-11-22 18:26:48 +01:00
f1084157a3 fixed issues at 64MS/s 2020-11-13 02:04:37 +01:00
de3b056133 Partial RX888 source module 2020-11-12 21:23:18 +01:00
02ae50905d added rx888 2020-11-12 00:53:38 +01:00
0a5fd5c271 Fixed small bug in waterfall 2020-11-04 05:08:42 +01:00
ef968ac1fb finally fixed the waterfall7 2020-11-04 04:11:51 +01:00
3156236745 Fixed DSP 2020-11-04 00:42:39 +01:00
5d320fdd53 Fixes 2020-11-03 19:22:53 +01:00
cee6af1e14 fixing audio bug 2020-11-02 21:13:28 +01:00
35c7f0e3cf Fixed stall 2020-11-02 17:48:17 +01:00
fc9bc496cb fixed 2020-11-02 16:16:21 +01:00
75f8a45119 new dsp 2020-11-02 03:57:44 +01:00
50a73a380d more fixes 2020-10-31 15:07:49 +01:00
e62042d26a Update readme.md 2020-10-24 18:56:32 +02:00
c109de3949 Merge pull request #31 from aosync/openbsd
Build on OpenBSD
2020-10-24 18:54:47 +02:00
39c87782db Merge branch 'experimental' into openbsd 2020-10-24 18:54:34 +02:00
b6566dde14 Merge pull request #32 from howard0su/experimental
Add instruction for Linux
2020-10-24 17:50:32 +02:00
ef36283370 Add instruction for Linux 2020-10-24 23:41:40 +08:00
922a226028 fixed OpenBSD build 4 2020-10-24 17:34:18 +02:00
ba81f25933 Added OpenBSD build instructions 2020-10-24 17:18:54 +02:00
da9528576a fixed openbsd build 3 2020-10-24 17:09:25 +02:00
3fdd2477e5 Fixed typo in root CMakeLists.txt 2020-10-24 15:33:00 +02:00
62368e35a7 Merge pull request #29 from aosync/experimental
make prepare_root.sh an executable and take advantage of globbing
2020-10-24 14:56:10 +02:00
82d3431f1d Merge pull request #28 from howard0su/experimental
Build system fix and cleanup
2020-10-24 14:55:41 +02:00
edbc0c149d fixed linux bugs 2020-10-24 14:51:55 +02:00
b8987e6d2d make prepare_root.sh a proper program and take advantage of globbing 2020-10-24 09:44:15 +02:00
6296b8865b fftw lib is not used but fftw3f only 2020-10-23 17:07:02 +08:00
2df185e340 Copy volk.dll when building on Windows 2020-10-23 17:06:10 +08:00
6262c64daa Consolidate Linux and OSX build
Use pkg-config to find the right include path and lib names.
2020-10-23 10:53:48 +08:00
0fe5af9816 Fix volk.h include path. It should be volk/volk.h 2020-10-23 10:39:20 +08:00
e94888d533 Use pkg for every module, and link them static 2020-10-23 10:37:10 +08:00
6130428989 glfwSetWindowMaximizeCallback is added in 3.3 2020-10-23 10:36:14 +08:00
5400a4e18a Fix build on Debian 10 2020-10-22 23:55:49 +08:00
0d45217dfd Added baseband recording 2020-10-22 12:53:46 +02:00
fa1e647235 Merge pull request #26 from AlexandreRouma/better_modules
Better modules
2020-10-22 11:03:32 +02:00
d637cb9e75 Merge pull request #24 from howard0su/osx
another warning
2020-10-22 11:01:24 +02:00
406f18bf11 another warning 2020-10-22 09:18:58 +08:00
72611b5fa7 Fixed OpenGL memory leak 2020-10-22 03:16:11 +02:00
313b786d88 Merge pull request #23 from howard0su/warnings
Fix warnings
2020-10-22 02:54:01 +02:00
801a56787f Merge pull request #22 from howard0su/osx
Fix OSX build
2020-10-22 02:53:50 +02:00
62868b2533 Fix warnings 2020-10-22 08:48:31 +08:00
4bf88739b5 Fix OSX build 2020-10-22 08:33:55 +08:00
087380c966 Push before merge 2020-10-22 02:33:50 +02:00
fbd7321b48 Fixed typo 2020-10-20 19:55:14 +02:00
f6cfe83d45 Fixed typo 2020-10-20 19:15:43 +02:00
71f6be8d08 Fixed VFO alignment 2020-10-20 14:59:42 +02:00
6e5450ed24 new fixes 2020-10-20 00:32:17 +02:00
027054b57e Fixed waterfall inaccuracies + started adding stepped VFO 2020-10-15 16:09:01 +02:00
3b6a3ff94d Fixed scripting + cleaner code + fixed RTLTCP 2020-10-07 22:44:54 +02:00
46d5b8a750 new scripting system 2020-10-07 14:44:39 +02:00
ac068036b8 Finished soapy module + added file source + added RTL_TCP source (windows only rn) 2020-10-06 15:50:46 +02:00
ace1fe1e5e added linux support for rtl_tcp 2020-10-06 10:54:00 +02:00
14a8e81662 Fixed missing label bug of soapysdr 2020-10-05 18:20:27 +02:00
eff7bbdd5a added new patrons 2020-10-04 15:23:40 +02:00
60342de9c0 Finished soapy module + added file source + added RTL_TCP source (windows only rn) 2020-10-04 02:56:02 +02:00
47b04ffef4 More work on the source module system 2020-10-02 01:44:18 +02:00
1507e6ec31 New module system 2020-10-01 13:46:12 +02:00
524f20bc2f Save before changes 2020-10-01 01:21:15 +02:00
2c4d7cbf09 Moved menus to their own respective files 2020-09-25 14:25:36 +02:00
5fedda08d7 More fixes 3 2020-09-24 19:50:22 +02:00
2056eae139 More fixes 2 2020-09-24 19:38:05 +02:00
48a8b04eaa More fixes 2020-09-24 19:36:57 +02:00
51ee02f9da Fixed windows bugs 2020-09-20 02:18:01 +02:00
ab8ce4c53f Fixed warnings on linux 2020-09-20 01:36:25 +02:00
2aaf254565 Fixed issues with new module system 6 2020-09-20 00:56:00 +02:00
109696c65a Fixed issues with new module system 5 2020-09-20 00:44:45 +02:00
35ef99c6e9 Fixed issues with new module system 4 2020-09-20 00:41:35 +02:00
91d382ca0c Fixed issues with new module system 3 2020-09-20 00:33:38 +02:00
ec234e99a1 Fixed issues with new module system 2 2020-09-20 00:26:45 +02:00
9de585190f Fixed issues with new module system 2020-09-20 00:19:39 +02:00
d6b9e1d86a new modole system 2020-09-19 12:48:34 +02:00
1ef31f0f8b new stuff 2020-09-18 00:23:03 +02:00
c1052b1b28 easier build 2020-09-06 16:31:50 +02:00
e497122c06 Merge pull request #17 from howard0su/fix_warn
Add a missing else to shutdown a warning message
2020-09-06 16:43:16 +03:00
407fcaadc6 Merge pull request #18 from howard0su/fil
cleanup DecimatingFIRFilter code
2020-09-06 16:43:05 +03:00
7e6f24d203 Merge pull request #16 from howard0su/fix_vfo
Freq can be zero
2020-09-06 16:42:41 +03:00
c0825dbeeb Push before merge 2020-09-06 15:39:09 +02:00
39a65b51fb optimize DecimatingFIRFilter 2020-09-06 08:42:05 +08:00
acf3fe0297 Add a missing else to shutdown a warning message 2020-09-06 08:40:42 +08:00
70c2ef36f5 Freq can be zero
In Zero-IF scenerio, freq can be zero.
2020-09-06 08:38:50 +08:00
7190acfe9e Fixed band plan name not appearing correctly 2020-08-21 17:12:48 +02:00
bf6210721d Fixed config not saved properly 2020-08-21 17:11:12 +02:00
27731f376a fixed default config file 2020-08-21 15:47:19 +02:00
d82260d4d4 New stuff ++++ 2020-08-21 15:38:27 +02:00
78086a79f4 New stuff +++ 2020-08-21 15:37:34 +02:00
aa2caa67ad New stuff ++ 2020-08-21 15:34:50 +02:00
709627a738 New stuff lmao 2020-08-20 18:29:23 +02:00
649be86cb6 added a recorder module 2020-08-18 00:56:51 +02:00
b56aab8f74 new styles 2020-08-17 02:39:56 +02:00
53ec38766a bruh 2020-08-16 19:34:53 +02:00
dbe811b47a bruh 2020-08-16 19:28:14 +02:00
f08515420e bruh 2020-08-16 19:07:17 +02:00
11913ab683 bruh 2020-08-16 19:01:59 +02:00
1cecc78c0c bruh 2020-08-16 18:57:50 +02:00
6717c43fc2 bruh 2020-08-16 18:51:20 +02:00
e44d20bdbc bruh 2020-08-16 18:46:30 +02:00
e50ed1b960 bruh 2020-08-16 18:30:40 +02:00
cff5987329 Fixed delete[] in soapy.h 2020-08-16 18:22:22 +02:00
b2191c5d2c Fixed delete[] in soapy.h 2020-08-16 18:18:10 +02:00
03dc5d2042 Fixed SoapySDR trying to set gain on no device 2020-08-16 18:06:21 +02:00
19e07eb767 Fixed gain memory error 2020-08-16 17:56:12 +02:00
c4f49203a1 testing on linux 2020-08-16 17:36:48 +02:00
9830337103 small fixes 2020-08-16 14:26:22 +02:00
eadaf3ce6b a LOT of new stuff 2020-08-16 03:39:05 +02:00
31a95031e4 Full module system 2020-08-12 16:43:44 +02:00
cdea80f8c5 modules 2020-08-11 18:33:42 +02:00
b65bddc1b3 multi-vfo 2020-08-10 02:30:25 +02:00
7759de96da added module system 2020-08-07 14:29:06 +02:00
9d2b60b88e Updated screenshot 2020-08-05 23:27:39 +02:00
793 changed files with 132040 additions and 31546 deletions

131
.clang-format Normal file
View File

@ -0,0 +1,131 @@
---
Language: Cpp
# BasedOnStyle: LLVM
AccessModifierOffset: -4
AlignAfterOpenBracket: Align
AlignConsecutiveMacros: true
AlignConsecutiveAssignments: false
AlignConsecutiveDeclarations: false
AlignEscapedNewlines: Right
AlignOperands: true
AlignTrailingComments: true
AllowAllArgumentsOnNextLine: true
AllowAllConstructorInitializersOnNextLine: true
AllowAllParametersOfDeclarationOnNextLine: true
AllowShortBlocksOnASingleLine: Always
AllowShortCaseLabelsOnASingleLine: false
AllowShortFunctionsOnASingleLine: All
AllowShortLambdasOnASingleLine: All
AllowShortIfStatementsOnASingleLine: WithoutElse
AllowShortLoopsOnASingleLine: true
AlwaysBreakAfterDefinitionReturnType: None
AlwaysBreakAfterReturnType: None
AlwaysBreakBeforeMultilineStrings: false
AlwaysBreakTemplateDeclarations: MultiLine
BinPackArguments: true
BinPackParameters: true
BraceWrapping:
AfterCaseLabel: false
AfterClass: false
AfterControlStatement: false
AfterEnum: false
AfterFunction: false
AfterNamespace: false
AfterObjCDeclaration: false
AfterStruct: false
AfterUnion: false
AfterExternBlock: false
BeforeCatch: true
BeforeElse: true
IndentBraces: false
SplitEmptyFunction: false
SplitEmptyRecord: true
SplitEmptyNamespace: true
BreakBeforeBinaryOperators: None
BreakBeforeBraces: Custom
BreakBeforeInheritanceComma: false
BreakInheritanceList: BeforeColon
BreakBeforeTernaryOperators: true
BreakConstructorInitializersBeforeComma: false
BreakConstructorInitializers: BeforeColon
BreakAfterJavaFieldAnnotations: false
BreakStringLiterals: true
ColumnLimit: 0
CommentPragmas: '^ IWYU pragma:'
CompactNamespaces: false
ConstructorInitializerAllOnOneLineOrOnePerLine: false
ConstructorInitializerIndentWidth: 4
ContinuationIndentWidth: 4
Cpp11BracedListStyle: false
DeriveLineEnding: true
DerivePointerAlignment: false
DisableFormat: false
ExperimentalAutoDetectBinPacking: false
FixNamespaceComments: false
ForEachMacros:
- foreach
- Q_FOREACH
- BOOST_FOREACH
IncludeBlocks: Preserve
IncludeCategories:
- Regex: '.'
Priority: 2
SortPriority: 2
IncludeIsMainRegex: '(Test)?$'
IncludeIsMainSourceRegex: ''
IndentCaseLabels: false
IndentGotoLabels: true
IndentPPDirectives: None
IndentWidth: 4
IndentWrappedFunctionNames: false
JavaScriptQuotes: Leave
JavaScriptWrapImports: true
KeepEmptyLinesAtTheStartOfBlocks: true
MacroBlockBegin: ''
MacroBlockEnd: ''
MaxEmptyLinesToKeep: 2
NamespaceIndentation: All
ObjCBinPackProtocolList: Auto
ObjCBlockIndentWidth: 4
ObjCSpaceAfterProperty: false
ObjCSpaceBeforeProtocolList: true
PenaltyBreakAssignment: 2
PenaltyBreakBeforeFirstCallParameter: 19
PenaltyBreakComment: 300
PenaltyBreakFirstLessLess: 120
PenaltyBreakString: 1000
PenaltyBreakTemplateDeclaration: 10
PenaltyExcessCharacter: 1000000
PenaltyReturnTypeOnItsOwnLine: 60
PointerAlignment: Left
ReflowComments: true
SortIncludes: false
SortUsingDeclarations: true
SpaceAfterCStyleCast: false
SpaceAfterLogicalNot: false
SpaceAfterTemplateKeyword: true
SpaceBeforeAssignmentOperators: true
SpaceBeforeCpp11BracedList: false
SpaceBeforeCtorInitializerColon: true
SpaceBeforeInheritanceColon: true
SpaceBeforeParens: ControlStatements
SpaceBeforeRangeBasedForLoopColon: true
SpaceInEmptyBlock: false
SpaceInEmptyParentheses: false
SpacesBeforeTrailingComments: 1
SpacesInAngles: false
SpacesInConditionalStatement: false
SpacesInContainerLiterals: true
SpacesInCStyleCastParentheses: false
SpacesInParentheses: false
SpacesInSquareBrackets: false
SpaceBeforeSquareBrackets: false
Standard: Latest
StatementMacros:
- Q_UNUSED
- QT_REQUIRE_VERSION
TabWidth: 4
UseCRLF: false
UseTab: Never
...

3
.github/FUNDING.yml vendored Normal file
View File

@ -0,0 +1,3 @@
# These are supported funding model platforms
patreon: ryzerth

43
.github/ISSUE_TEMPLATE/bug_report.md vendored Normal file
View File

@ -0,0 +1,43 @@
---
name: Bug report
about: Report crashes or unexpected behavior
title: ''
labels: bug
assignees: ''
---
# WARNING: Filling out the template below is NOT optional. Issues not filling out this template will be closed without review.
FIRST: Before reporting any bug, make sure that the bug you are reporting has not been reported before. Also, try to use the [nightly version](https://www.sdrpp.org/nightly) if possible in case I've already fixed the bug.
**Hardware**
- CPU:
- RAM:
- GPU:
- SDR: (Remote or local? If remote, what protocol?)
**Software**
- Operating System: Name + Exact version (eg. Windows 10 x64, Ubuntu 22.04, MacOS 10.15)
- SDR++: Version + Build date (available either in the window title or in the credits menu which you can access by clicking on the SDR++ icon in the top right corner of the software).
**Bug Description**
A clear description of the bug.
**Steps To Reproduce**
1. ...
2. ...
3. ...
**Only If SDR++ fails to lauch or the SDR fails to start:**
Run SDR++ from a command line window with special parameters:
* On Windows, open a terminal and `cd` to SDR++'s directory and run `.\sdrpp.exe -c` (if running SDR++ version 1.0.4 or older, use `-s` instead, though you should probably update SDR++ instead...)
* On Linux: Open a terminal and run `sdrpp -c`
* On MacOS: Open a terminal and run `/path/to/the/SDR++.app/Contents/MacOS/sdrpp -c`
Then, post the **entire** logs from start to after the issue. **DOT NOT truncate to where you *think* the error is...**
**Screenshots**
Add any screenshot that is relevant to the bug (GUI error messages, strange behavior, graphics glitch, etc...).
**Additional info**
Add any other relevant information.

View File

@ -0,0 +1,10 @@
---
name: Feature request
about: Suggest an idea for this project
title: ''
labels: enhancement
assignees: ''
---
**Feature description**

4
.github/pull_request_template.md vendored Normal file
View File

@ -0,0 +1,4 @@
# Important
Only bandplan, colormaps and themes are accepted. Code pull requests are **NOT welcome**.
Open an issue requesting a feature or discussing a possible bugfix instead.

505
.github/workflows/build_all.yml vendored Normal file
View File

@ -0,0 +1,505 @@
name: Build Binaries
on:
push:
branches-ignore:
- nightly
pull_request:
branches-ignore:
- nightly
env:
# Customize the CMake build type here (Release, Debug, RelWithDebInfo, etc.)
BUILD_TYPE: Release
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
jobs:
build_windows:
runs-on: windows-latest
steps:
- uses: actions/checkout@v4
- name: Create Build Environment
run: cmake -E make_directory ${{runner.workspace}}/build
- name: Download PothosSDR
run: Invoke-WebRequest -Uri "https://downloads.myriadrf.org/builds/PothosSDR/PothosSDR-2020.01.26-vc14-x64.exe" -OutFile ${{runner.workspace}}/pothos.exe
- name: Install PothosSDR
run: mkdir "C:/Program Files/PothosSDR" ; 7z x ${{runner.workspace}}/pothos.exe -o"C:/Program Files/PothosSDR/"
- name: Download libusb
run: Invoke-WebRequest -Uri "https://github.com/libusb/libusb/releases/download/v1.0.23/libusb-1.0.23.7z" -OutFile ${{runner.workspace}}/libusb.7z
- name: Patch Pothos with earlier libusb version
working-directory: ${{runner.workspace}}
run: 7z x libusb.7z -olibusb_old ; rm "C:/Program Files/PothosSDR/bin/libusb-1.0.dll" ; cp "libusb_old/MS64/dll/libusb-1.0.dll" "C:/Program Files/PothosSDR/bin/" ; rm "C:/Program Files/PothosSDR/lib/libusb-1.0.lib" ; cp "libusb_old/MS64/dll/libusb-1.0.lib" "C:/Program Files/PothosSDR/lib/"
- name: Download librtlsdr
run: Invoke-WebRequest -Uri "https://ftp.osmocom.org/binaries/windows/rtl-sdr/rtl-sdr-64bit-20240623.zip" -OutFile ${{runner.workspace}}/rtl-sdr.zip
- name: Patch Pothos with newer librtlsdr version
working-directory: ${{runner.workspace}}
run: 7z x rtl-sdr.zip ; rm "C:/Program Files/PothosSDR/bin/rtlsdr.dll" ; cp "rtl-sdr-64bit-20240623/librtlsdr.dll" "C:/Program Files/PothosSDR/bin/rtlsdr.dll"
- name: Download SDRPlay API
run: Invoke-WebRequest -Uri "https://www.sdrpp.org/SDRplay.zip" -OutFile ${{runner.workspace}}/SDRplay.zip
- name: Install SDRPlay API
run: 7z x ${{runner.workspace}}/SDRplay.zip -o"C:/Program Files/"
- name: Download codec2
run: git clone https://github.com/AlexandreRouma/codec2
- name: Prepare MinGW
run: C:/msys64/msys2_shell.cmd -defterm -here -no-start -mingw64 -c "pacman --noconfirm -S --needed base-devel mingw-w64-x86_64-toolchain mingw-w64-x86_64-cmake mingw-w64-x86_64-ninja"
- name: Prepare build for codec2
run: cd codec2 ; mkdir build ; cd build ; C:/msys64/msys2_shell.cmd -defterm -here -no-start -mingw64 -c "cmake .. -DCMAKE_GNUtoMS=ON -DCMAKE_BUILD_TYPE=Release -DCMAKE_C_FLAGS=-static-libgcc"
- name: Build codec2
run: cd codec2/build ; C:/msys64/msys2_shell.cmd -defterm -here -no-start -mingw64 -c "ninja"
- name: Install codec2
run: mkdir "C:/Program Files/codec2" ; mkdir "C:/Program Files/codec2/include" ; mkdir "C:/Program Files/codec2/include/codec2" ; mkdir "C:/Program Files/codec2/lib" ; cd "codec2" ; xcopy "src" "C:/Program Files/codec2/include" ; cd "build" ; xcopy "src" "C:/Program Files/codec2/lib" ; xcopy "codec2" "C:/Program Files/codec2/include/codec2"
- name: Install vcpkg dependencies
run: vcpkg install fftw3:x64-windows glfw3:x64-windows portaudio:x64-windows zstd:x64-windows libusb:x64-windows spdlog:x64-windows
- name: Install rtaudio
run: git clone https://github.com/thestk/rtaudio ; cd rtaudio ; git checkout 2f2fca4502d506abc50f6d4473b2836d24cfb1e3 ; mkdir build ; cd build ; cmake .. ; cmake --build . --config Release ; cmake --install .
- name: Install libperseus-sdr
run: git clone https://github.com/AlexandreRouma/libperseus-sdr ; cd libperseus-sdr ; mkdir build ; cd build ; cmake -DCMAKE_BUILD_TYPE=Release "-DLIBUSB_LIBRARIES=C:/Program Files/PothosSDR/lib/libusb-1.0.lib" "-DLIBUSB_INCLUDE_DIRS=C:/Program Files/PothosSDR/include/libusb-1.0" .. "-DCMAKE_TOOLCHAIN_FILE=C:/vcpkg/scripts/buildsystems/vcpkg.cmake" ; cmake --build . --config Release ; mkdir "C:/Program Files/PothosSDR/include/perseus-sdr" ; cp Release/perseus-sdr.dll "C:/Program Files/PothosSDR/bin" ; cp Release/perseus-sdr.lib "C:/Program Files/PothosSDR/bin" ; cd .. ; xcopy "src" "C:/Program Files/PothosSDR/include/perseus-sdr"
- name: Install librfnm
run: git clone https://github.com/AlexandreRouma/librfnm ; cd librfnm ; mkdir build ; cd build ; cmake .. -DCMAKE_BUILD_TYPE=Release "-DCMAKE_TOOLCHAIN_FILE=C:/vcpkg/scripts/buildsystems/vcpkg.cmake" ; cmake --build . --config Release ; cmake --install .
- name: Install libfobos
run: git clone https://github.com/AlexandreRouma/libfobos ; cd libfobos ; mkdir build ; cd build ; cmake .. -DCMAKE_BUILD_TYPE=Release "-DCMAKE_TOOLCHAIN_FILE=C:/vcpkg/scripts/buildsystems/vcpkg.cmake" ; cmake --build . --config Release ; cmake --install .
- name: Prepare CMake
working-directory: ${{runner.workspace}}/build
run: cmake -DCOPY_MSVC_REDISTRIBUTABLES=ON "$Env:GITHUB_WORKSPACE" "-DCMAKE_TOOLCHAIN_FILE=C:/vcpkg/scripts/buildsystems/vcpkg.cmake" -DOPT_BUILD_BLADERF_SOURCE=ON -DOPT_BUILD_LIMESDR_SOURCE=ON -DOPT_BUILD_PERSEUS_SOURCE=ON -DOPT_BUILD_SDRPLAY_SOURCE=ON -DOPT_BUILD_NEW_PORTAUDIO_SINK=ON -DOPT_BUILD_M17_DECODER=ON -DOPT_BUILD_RFNM_SOURCE=ON -DOPT_BUILD_FOBOSSDR_SOURCE=ON
- name: Build
working-directory: ${{runner.workspace}}/build
run: cmake --build . --config Release --verbose
- name: Create Archive
working-directory: ${{runner.workspace}}
run: '&($Env:GITHUB_WORKSPACE + "/make_windows_package.ps1") ./build ($Env:GITHUB_WORKSPACE + "/root")'
- name: Save Archive
uses: actions/upload-artifact@v4
with:
name: sdrpp_windows_x64
path: ${{runner.workspace}}/sdrpp_windows_x64.zip
build_macos_intel:
runs-on: macos-12
steps:
- uses: actions/checkout@v4
- name: Create Build Environment
run: cmake -E make_directory ${{runner.workspace}}/build
- name: Install dependencies
run: brew install pkg-config libusb fftw glfw airspy airspyhf portaudio hackrf libbladerf codec2 zstd autoconf automake libtool spdlog && pip3 install mako
- name: Install volk
run: git clone --recursive https://github.com/gnuradio/volk && cd volk && mkdir build && cd build && cmake -DCMAKE_OSX_DEPLOYMENT_TARGET=10.15 -DCMAKE_BUILD_TYPE=Release .. && make -j3 && sudo make install && cd ../../
- name: Install SDRplay API
run: wget https://www.sdrplay.com/software/SDRplayAPI-macos-installer-universal-3.15.0.pkg && sudo installer -pkg SDRplayAPI-macos-installer-universal-3.15.0.pkg -target /
- name: Install libiio
run: wget https://github.com/analogdevicesinc/libiio/archive/refs/tags/v0.25.zip && 7z x v0.25.zip && cd libiio-0.25 && mkdir build && cd build && cmake -DCMAKE_OSX_DEPLOYMENT_TARGET=10.15 -DCMAKE_BUILD_TYPE=Release .. && make -j3 && sudo make install && cd ../../
- name: Install libad9361
run: git clone https://github.com/analogdevicesinc/libad9361-iio && cd libad9361-iio && mkdir build && cd build && cmake -DCMAKE_OSX_DEPLOYMENT_TARGET=10.15 -DCMAKE_BUILD_TYPE=Release .. && make -j3 && sudo make install && cd ../../
- name: Install LimeSuite
run: git clone https://github.com/myriadrf/LimeSuite && cd LimeSuite && mkdir builddir && cd builddir && cmake -DCMAKE_OSX_DEPLOYMENT_TARGET=10.15 -DCMAKE_BUILD_TYPE=Release .. && make -j3 && sudo make install && cd ../../
- name: Install libperseus
run: git clone https://github.com/Microtelecom/libperseus-sdr && cd libperseus-sdr && autoreconf -i && ./configure --prefix=/usr/local && make && sudo make install && cd ..
- name: Install librfnm
run: git clone https://github.com/AlexandreRouma/librfnm && cd librfnm && mkdir build && cd build && cmake .. -DCMAKE_BUILD_TYPE=Release && make && sudo make install && cd ..
- name: Install libfobos
run: git clone https://github.com/AlexandreRouma/libfobos && cd libfobos && mkdir build && cd build && cmake .. -DCMAKE_BUILD_TYPE=Release && make && sudo make install && cd ..
- name: Install more recent librtlsdr
run: git clone https://github.com/osmocom/rtl-sdr && cd rtl-sdr && mkdir build && cd build && cmake -DCMAKE_OSX_DEPLOYMENT_TARGET=10.15 -DCMAKE_BUILD_TYPE=Release .. && make -j3 LIBRARY_PATH=$(pkg-config --libs-only-L libusb-1.0 | sed 's/\-L//') && sudo make install && cd ../../
- name: Prepare CMake
working-directory: ${{runner.workspace}}/build
run: cmake -DCMAKE_OSX_DEPLOYMENT_TARGET=10.15 $GITHUB_WORKSPACE -DOPT_BUILD_PLUTOSDR_SOURCE=ON -DOPT_BUILD_BLADERF_SOURCE=ON -DOPT_BUILD_SDRPLAY_SOURCE=ON -DOPT_BUILD_LIMESDR_SOURCE=ON -DOPT_BUILD_AUDIO_SINK=OFF -DOPT_BUILD_PORTAUDIO_SINK=ON -DOPT_BUILD_NEW_PORTAUDIO_SINK=ON -DOPT_BUILD_M17_DECODER=ON -DOPT_BUILD_PERSEUS_SOURCE=ON -DOPT_BUILD_AUDIO_SOURCE=OFF -DOPT_BUILD_RFNM_SOURCE=ON -DOPT_BUILD_FOBOSSDR_SOURCE=ON -DUSE_BUNDLE_DEFAULTS=ON -DCMAKE_BUILD_TYPE=Release
- name: Build
working-directory: ${{runner.workspace}}/build
run: make VERBOSE=1 -j3
- name: Create Archive
working-directory: ${{runner.workspace}}
run: cd $GITHUB_WORKSPACE && sh make_macos_bundle.sh ${{runner.workspace}}/build ./SDR++.app && zip -r ${{runner.workspace}}/sdrpp_macos_intel.zip SDR++.app
- name: Save Archive
uses: actions/upload-artifact@v4
with:
name: sdrpp_macos_intel
path: ${{runner.workspace}}/sdrpp_macos_intel.zip
build_macos_arm:
runs-on: macos-14
steps:
- uses: actions/checkout@v4
- name: Create Build Environment
run: cmake -E make_directory ${{runner.workspace}}/build
- name: Install dependencies
run: brew install pkg-config libusb fftw glfw airspy airspyhf portaudio hackrf libbladerf codec2 zstd autoconf automake libtool spdlog && pip3 install mako --break-system-packages
- name: Install volk
run: git clone --recursive https://github.com/gnuradio/volk && cd volk && mkdir build && cd build && cmake -DCMAKE_OSX_DEPLOYMENT_TARGET=10.15 -DCMAKE_BUILD_TYPE=Release .. && make -j3 && sudo make install && cd ../../
- name: Install SDRplay API
run: wget https://www.sdrplay.com/software/SDRplayAPI-macos-installer-universal-3.15.0.pkg && sudo installer -pkg SDRplayAPI-macos-installer-universal-3.15.0.pkg -target /
- name: Install libiio
run: wget https://github.com/analogdevicesinc/libiio/archive/refs/tags/v0.25.zip && 7z x v0.25.zip && cd libiio-0.25 && mkdir build && cd build && cmake -DCMAKE_OSX_DEPLOYMENT_TARGET=10.15 -DCMAKE_BUILD_TYPE=Release .. && make -j3 && sudo make install && cd ../../
- name: Install libad9361
run: git clone https://github.com/analogdevicesinc/libad9361-iio && cd libad9361-iio && mkdir build && cd build && cmake -DCMAKE_OSX_DEPLOYMENT_TARGET=10.15 -DCMAKE_BUILD_TYPE=Release .. && make -j3 && sudo make install && cd ../../
- name: Install LimeSuite
run: git clone https://github.com/myriadrf/LimeSuite && cd LimeSuite && mkdir builddir && cd builddir && cmake -DCMAKE_OSX_DEPLOYMENT_TARGET=10.15 -DCMAKE_BUILD_TYPE=Release .. && make -j3 && sudo make install && cd ../../
# - name: Install libperseus
# run: git clone https://github.com/Microtelecom/libperseus-sdr && cd libperseus-sdr && autoreconf -i && ./configure --prefix=/usr/local && make && make install && cd ..
- name: Install librfnm
run: git clone https://github.com/AlexandreRouma/librfnm && cd librfnm && mkdir build && cd build && cmake .. -DCMAKE_BUILD_TYPE=Release && make && sudo make install && cd ..
- name: Install libfobos
run: git clone https://github.com/AlexandreRouma/libfobos && cd libfobos && mkdir build && cd build && cmake .. -DCMAKE_BUILD_TYPE=Release && make && sudo make install && cd ..
- name: Install more recent librtlsdr
run: git clone https://github.com/osmocom/rtl-sdr && cd rtl-sdr && mkdir build && cd build && cmake -DCMAKE_OSX_DEPLOYMENT_TARGET=10.15 -DCMAKE_BUILD_TYPE=Release .. && make -j3 LIBRARY_PATH=$(pkg-config --libs-only-L libusb-1.0 | sed 's/\-L//') && sudo make install && cd ../../
- name: Prepare CMake
working-directory: ${{runner.workspace}}/build
run: cmake -DCMAKE_OSX_DEPLOYMENT_TARGET=10.15 $GITHUB_WORKSPACE -DOPT_BUILD_PLUTOSDR_SOURCE=ON -DOPT_BUILD_BLADERF_SOURCE=ON -DOPT_BUILD_SDRPLAY_SOURCE=ON -DOPT_BUILD_LIMESDR_SOURCE=ON -DOPT_BUILD_AUDIO_SINK=OFF -DOPT_BUILD_PORTAUDIO_SINK=ON -DOPT_BUILD_NEW_PORTAUDIO_SINK=ON -DOPT_BUILD_M17_DECODER=OFF -DOPT_BUILD_PERSEUS_SOURCE=OFF -DOPT_BUILD_AUDIO_SOURCE=OFF -DOPT_BUILD_RFNM_SOURCE=ON -DOPT_BUILD_FOBOSSDR_SOURCE=ON -DUSE_BUNDLE_DEFAULTS=ON -DCMAKE_BUILD_TYPE=Release
- name: Build
working-directory: ${{runner.workspace}}/build
run: make VERBOSE=1 -j3
- name: Create Archive
working-directory: ${{runner.workspace}}
run: cd $GITHUB_WORKSPACE && sh make_macos_bundle.sh ${{runner.workspace}}/build ./SDR++.app && zip -r ${{runner.workspace}}/sdrpp_macos_arm.zip SDR++.app
- name: Save Archive
uses: actions/upload-artifact@v4
with:
name: sdrpp_macos_arm
path: ${{runner.workspace}}/sdrpp_macos_arm.zip
build_debian_buster:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Create Docker Image
run: cd $GITHUB_WORKSPACE/docker_builds/debian_buster && docker build . --tag sdrpp_build
- name: Run Container
run: docker run --name build -v $GITHUB_WORKSPACE:/root/SDRPlusPlus --env BUILD_NO="-$GITHUB_RUN_NUMBER" sdrpp_build /root/do_build.sh
- name: Recover Deb Archive
working-directory: ${{runner.workspace}}
run: docker cp build:/root/SDRPlusPlus/sdrpp_debian_amd64.deb ./
- name: Save Deb Archive
uses: actions/upload-artifact@v4
with:
name: sdrpp_debian_buster_amd64
path: ${{runner.workspace}}/sdrpp_debian_amd64.deb
build_debian_bullseye:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Create Docker Image
run: cd $GITHUB_WORKSPACE/docker_builds/debian_bullseye && docker build . --tag sdrpp_build
- name: Run Container
run: docker run --name build -v $GITHUB_WORKSPACE:/root/SDRPlusPlus --env BUILD_NO="-$GITHUB_RUN_NUMBER" sdrpp_build /root/do_build.sh
- name: Recover Deb Archive
working-directory: ${{runner.workspace}}
run: docker cp build:/root/SDRPlusPlus/sdrpp_debian_amd64.deb ./
- name: Save Deb Archive
uses: actions/upload-artifact@v4
with:
name: sdrpp_debian_bullseye_amd64
path: ${{runner.workspace}}/sdrpp_debian_amd64.deb
build_debian_bookworm:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Create Docker Image
run: cd $GITHUB_WORKSPACE/docker_builds/debian_bookworm && docker build . --tag sdrpp_build
- name: Run Container
run: docker run --name build -v $GITHUB_WORKSPACE:/root/SDRPlusPlus --env BUILD_NO="-$GITHUB_RUN_NUMBER" sdrpp_build /root/do_build.sh
- name: Recover Deb Archive
working-directory: ${{runner.workspace}}
run: docker cp build:/root/SDRPlusPlus/sdrpp_debian_amd64.deb ./
- name: Save Deb Archive
uses: actions/upload-artifact@v4
with:
name: sdrpp_debian_bookworm_amd64
path: ${{runner.workspace}}/sdrpp_debian_amd64.deb
build_debian_sid:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Create Docker Image
run: cd $GITHUB_WORKSPACE/docker_builds/debian_sid && docker build . --tag sdrpp_build
- name: Run Container
run: docker run --name build -v $GITHUB_WORKSPACE:/root/SDRPlusPlus --env BUILD_NO="-$GITHUB_RUN_NUMBER" sdrpp_build /root/do_build.sh
- name: Recover Deb Archive
working-directory: ${{runner.workspace}}
run: docker cp build:/root/SDRPlusPlus/sdrpp_debian_amd64.deb ./
- name: Save Deb Archive
uses: actions/upload-artifact@v4
with:
name: sdrpp_debian_sid_amd64
path: ${{runner.workspace}}/sdrpp_debian_amd64.deb
build_ubuntu_focal:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Create Docker Image
run: cd $GITHUB_WORKSPACE/docker_builds/ubuntu_focal && docker build . --tag sdrpp_build
- name: Run Container
run: docker run --name build -v $GITHUB_WORKSPACE:/root/SDRPlusPlus --env BUILD_NO="-$GITHUB_RUN_NUMBER" sdrpp_build /root/do_build.sh
- name: Recover Deb Archive
working-directory: ${{runner.workspace}}
run: docker cp build:/root/SDRPlusPlus/sdrpp_debian_amd64.deb ./
- name: Save Deb Archive
uses: actions/upload-artifact@v4
with:
name: sdrpp_ubuntu_focal_amd64
path: ${{runner.workspace}}/sdrpp_debian_amd64.deb
build_ubuntu_jammy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Create Docker Image
run: cd $GITHUB_WORKSPACE/docker_builds/ubuntu_jammy && docker build . --tag sdrpp_build
- name: Run Container
run: docker run --name build -v $GITHUB_WORKSPACE:/root/SDRPlusPlus --env BUILD_NO="-$GITHUB_RUN_NUMBER" sdrpp_build /root/do_build.sh
- name: Recover Deb Archive
working-directory: ${{runner.workspace}}
run: docker cp build:/root/SDRPlusPlus/sdrpp_debian_amd64.deb ./
- name: Save Deb Archive
uses: actions/upload-artifact@v4
with:
name: sdrpp_ubuntu_jammy_amd64
path: ${{runner.workspace}}/sdrpp_debian_amd64.deb
build_ubuntu_mantic:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Create Docker Image
run: cd $GITHUB_WORKSPACE/docker_builds/ubuntu_mantic && docker build . --tag sdrpp_build
- name: Run Container
run: docker run --name build -v $GITHUB_WORKSPACE:/root/SDRPlusPlus --env BUILD_NO="-$GITHUB_RUN_NUMBER" sdrpp_build /root/do_build.sh
- name: Recover Deb Archive
working-directory: ${{runner.workspace}}
run: docker cp build:/root/SDRPlusPlus/sdrpp_debian_amd64.deb ./
- name: Save Deb Archive
uses: actions/upload-artifact@v4
with:
name: sdrpp_ubuntu_mantic_amd64
path: ${{runner.workspace}}/sdrpp_debian_amd64.deb
build_ubuntu_noble:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Create Docker Image
run: cd $GITHUB_WORKSPACE/docker_builds/ubuntu_noble && docker build . --tag sdrpp_build
- name: Run Container
run: docker run --name build -v $GITHUB_WORKSPACE:/root/SDRPlusPlus --env BUILD_NO="-$GITHUB_RUN_NUMBER" sdrpp_build /root/do_build.sh
- name: Recover Deb Archive
working-directory: ${{runner.workspace}}
run: docker cp build:/root/SDRPlusPlus/sdrpp_debian_amd64.deb ./
- name: Save Deb Archive
uses: actions/upload-artifact@v4
with:
name: sdrpp_ubuntu_noble_amd64
path: ${{runner.workspace}}/sdrpp_debian_amd64.deb
build_raspios_bullseye_armhf:
runs-on: ARM
steps:
- uses: actions/checkout@v4
- name: Create Build Environment
run: rm -rf ${{runner.workspace}}/build && cmake -E make_directory ${{runner.workspace}}/build
- name: Prepare CMake
working-directory: ${{runner.workspace}}/build
run: cmake $GITHUB_WORKSPACE -DOPT_BUILD_BLADERF_SOURCE=ON -DOPT_BUILD_LIMESDR_SOURCE=ON -DOPT_BUILD_SDRPLAY_SOURCE=ON -DOPT_BUILD_NEW_PORTAUDIO_SINK=ON -DOPT_BUILD_M17_DECODER=ON -DOPT_BUILD_USRP_SOURCE=ON -DOPT_BUILD_PERSEUS_SOURCE=ON
- name: Build
working-directory: ${{runner.workspace}}/build
run: make VERBOSE=1 -j3
- name: Create Dev Archive
working-directory: ${{runner.workspace}}
run: sh $GITHUB_WORKSPACE/make_debian_package.sh ./build 'libfftw3-dev, libglfw3-dev, libvolk2-dev, librtaudio-dev' && mv sdrpp_debian_amd64.deb sdrpp_debian_armhf.deb
- name: Save Deb Archive
uses: actions/upload-artifact@v4
with:
name: sdrpp_raspios_bullseye_armhf
path: ${{runner.workspace}}/sdrpp_debian_armhf.deb
build_android:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Fetch container
working-directory: ${{runner.workspace}}
run: git clone https://github.com/AlexandreRouma/android-sdr-kit
- name: Build container
working-directory: ${{runner.workspace}}/android-sdr-kit
run: docker build --progress=plain -t android-sdr-kit .
- name: Build
run: docker run --name build -v $GITHUB_WORKSPACE:/root/SDRPlusPlus android-sdr-kit /bin/bash -l -c "cd /root/SDRPlusPlus/android && gradle --info assembleDebug"
- name: Recover APK
working-directory: ${{runner.workspace}}
run: docker cp build:/root/SDRPlusPlus/android/app/build/outputs/apk/debug/app-debug.apk ./ && mv app-debug.apk sdrpp.apk
- name: Save APK
uses: actions/upload-artifact@v4
with:
name: sdrpp_android
path: ${{runner.workspace}}/sdrpp.apk
create_full_archive:
needs: ['build_windows', 'build_macos_intel', 'build_macos_arm', 'build_debian_buster', 'build_debian_bullseye', 'build_debian_bookworm', 'build_debian_sid', 'build_ubuntu_focal', 'build_ubuntu_jammy', 'build_ubuntu_mantic', 'build_ubuntu_noble', 'build_raspios_bullseye_armhf', 'build_android']
runs-on: ubuntu-latest
steps:
- name: Download All Builds
uses: actions/download-artifact@v4
- name: Create Archive
run: >
mkdir sdrpp_all &&
mv sdrpp_windows_x64/sdrpp_windows_x64.zip sdrpp_all/ &&
mv sdrpp_macos_intel/sdrpp_macos_intel.zip sdrpp_all/ &&
mv sdrpp_macos_arm/sdrpp_macos_arm.zip sdrpp_all/ &&
mv sdrpp_debian_buster_amd64/sdrpp_debian_amd64.deb sdrpp_all/sdrpp_debian_buster_amd64.deb &&
mv sdrpp_debian_bullseye_amd64/sdrpp_debian_amd64.deb sdrpp_all/sdrpp_debian_bullseye_amd64.deb &&
mv sdrpp_debian_bookworm_amd64/sdrpp_debian_amd64.deb sdrpp_all/sdrpp_debian_bookworm_amd64.deb &&
mv sdrpp_debian_sid_amd64/sdrpp_debian_amd64.deb sdrpp_all/sdrpp_debian_sid_amd64.deb &&
mv sdrpp_ubuntu_focal_amd64/sdrpp_debian_amd64.deb sdrpp_all/sdrpp_ubuntu_focal_amd64.deb &&
mv sdrpp_ubuntu_jammy_amd64/sdrpp_debian_amd64.deb sdrpp_all/sdrpp_ubuntu_jammy_amd64.deb &&
mv sdrpp_ubuntu_mantic_amd64/sdrpp_debian_amd64.deb sdrpp_all/sdrpp_ubuntu_mantic_amd64.deb &&
mv sdrpp_ubuntu_noble_amd64/sdrpp_debian_amd64.deb sdrpp_all/sdrpp_ubuntu_noble_amd64.deb &&
mv sdrpp_raspios_bullseye_armhf/sdrpp_debian_armhf.deb sdrpp_all/sdrpp_raspios_bullseye_armhf.deb &&
mv sdrpp_android/sdrpp.apk sdrpp_all/sdrpp.apk
- uses: actions/upload-artifact@v4
with:
name: sdrpp_all
path: sdrpp_all/
update_nightly_release:
needs: [create_full_archive]
runs-on: ubuntu-latest
if: ${{ github.event_name == 'push' && github.ref == 'refs/heads/master' }}
steps:
- name: Download All Builds
uses: actions/download-artifact@v4
- name: Update Nightly
run: gh release upload nightly sdrpp_all/* -R ${{github.repository}} --clobber
check_spelling:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install codespell
run: sudo apt update -y && sudo apt install -y codespell
- name: Running codespell
run: cd $GITHUB_WORKSPACE && codespell -q 2 || true
check_formatting:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Run check_clang_format
run: cd $GITHUB_WORKSPACE && chmod +x ./check_clang_format.sh && ./check_clang_format.sh || true

18
.gitignore vendored
View File

@ -1,3 +1,19 @@
build/
.vscode/
*.old
.vs/
.idea/
*.old
*.dll
*.exe
*.zip
*.wav
.DS_Store
root_dev/
root_dev_srv/
Folder.DotSettings.user
CMakeSettings.json
poggers_decoder
m17_decoder/libcorrect
SDR++.app
android/deps
android/app/assets

View File

@ -1,59 +1,398 @@
cmake_minimum_required(VERSION 3.9)
cmake_minimum_required(VERSION 3.13)
project(sdrpp)
if (MSVC)
set(CMAKE_CXX_FLAGS "-O2 /std:c++17")
link_directories(sdrpp "C:/Program Files/PothosSDR/lib/")
include_directories(sdrpp "C:/Program Files/PothosSDR/include/volk/")
include_directories(sdrpp "C:/Program Files/PothosSDR/include/")
# Backends
option(OPT_BACKEND_GLFW "Use the GLFW backend" ON)
option(OPT_BACKEND_ANDROID "Use the Android backend" OFF)
# Compatibility Options
option(OPT_OVERRIDE_STD_FILESYSTEM "Use a local version of std::filesystem on systems that don't have it yet" OFF)
# Sources
option(OPT_BUILD_AIRSPY_SOURCE "Build Airspy Source Module (Dependencies: libairspy)" ON)
option(OPT_BUILD_AIRSPYHF_SOURCE "Build Airspy HF+ Source Module (Dependencies: libairspyhf)" ON)
option(OPT_BUILD_AUDIO_SOURCE "Build Audio Source Module (Dependencies: rtaudio)" ON)
option(OPT_BUILD_BADGESDR_SOURCE "Build BadgeSDR Source Module (Dependencies: libusb)" OFF)
option(OPT_BUILD_BLADERF_SOURCE "Build BladeRF Source Module (Dependencies: libbladeRF)" OFF)
option(OPT_BUILD_FILE_SOURCE "Wav file source" ON)
option(OPT_BUILD_FOBOSSDR_SOURCE "Build FobosSDR Source Module (Dependencies: libfobos)" OFF)
option(OPT_BUILD_HACKRF_SOURCE "Build HackRF Source Module (Dependencies: libhackrf)" ON)
option(OPT_BUILD_HAROGIC_SOURCE "Build Harogic Source Module (Dependencies: htra_api)" OFF)
option(OPT_BUILD_HERMES_SOURCE "Build Hermes Source Module (no dependencies required)" ON)
option(OPT_BUILD_KCSDR_SOURCE "Build KCSDR Source Module (Dependencies: libkcsdr)" OFF)
option(OPT_BUILD_LIMESDR_SOURCE "Build LimeSDR Source Module (Dependencies: liblimesuite)" OFF)
option(OPT_BUILD_NETWORK_SOURCE "Build Network Source Module (no dependencies required)" ON)
option(OPT_BUILD_PERSEUS_SOURCE "Build Perseus Source Module (Dependencies: libperseus-sdr)" OFF)
option(OPT_BUILD_PLUTOSDR_SOURCE "Build PlutoSDR Source Module (Dependencies: libiio, libad9361)" ON)
option(OPT_BUILD_RFNM_SOURCE "Build RFNM Source Module (Dependencies: librfnm)" OFF)
option(OPT_BUILD_RFSPACE_SOURCE "Build RFspace Source Module (no dependencies required)" ON)
option(OPT_BUILD_RTL_SDR_SOURCE "Build RTL-SDR Source Module (Dependencies: librtlsdr)" ON)
option(OPT_BUILD_RTL_TCP_SOURCE "Build RTL-TCP Source Module (no dependencies required)" ON)
option(OPT_BUILD_SDRPP_SERVER_SOURCE "Build SDR++ Server Source Module (no dependencies required)" ON)
option(OPT_BUILD_SDRPLAY_SOURCE "Build SDRplay Source Module (Dependencies: libsdrplay)" OFF)
option(OPT_BUILD_SOAPY_SOURCE "Build SoapySDR Source Module (Dependencies: soapysdr)" OFF)
option(OPT_BUILD_SPECTRAN_SOURCE "Build Spectran Source Module (Dependencies: Aaronia RTSA Suite)" OFF)
option(OPT_BUILD_SPECTRAN_HTTP_SOURCE "Build Spectran HTTP Source Module (no dependencies required)" ON)
option(OPT_BUILD_SPYSERVER_SOURCE "Build SpyServer Source Module (no dependencies required)" ON)
option(OPT_BUILD_USRP_SOURCE "Build USRP Source Module (libuhd)" OFF)
# Sinks
option(OPT_BUILD_ANDROID_AUDIO_SINK "Build Android Audio Sink Module (Dependencies: AAudio, only for android)" OFF)
option(OPT_BUILD_AUDIO_SINK "Build Audio Sink Module (Dependencies: rtaudio)" ON)
option(OPT_BUILD_NETWORK_SINK "Build Audio Sink Module (no dependencies required)" ON)
option(OPT_BUILD_NEW_PORTAUDIO_SINK "Build the new PortAudio Sink Module (Dependencies: portaudio)" OFF)
option(OPT_BUILD_PORTAUDIO_SINK "Build PortAudio Sink Module (Dependencies: portaudio)" OFF)
# Decoders
option(OPT_BUILD_ATV_DECODER "Build ATV decoder (no dependencies required)" OFF)
option(OPT_BUILD_DAB_DECODER "Build the DAB/DAB+ decoder (no dependencies required)" OFF)
option(OPT_BUILD_FALCON9_DECODER "Build the falcon9 live decoder (Dependencies: ffplay)" OFF)
option(OPT_BUILD_KG_SSTV_DECODER "Build the KG SSTV (KG-STV) decoder module (no dependencies required)" OFF)
option(OPT_BUILD_M17_DECODER "Build the M17 decoder module (Dependencies: codec2)" OFF)
option(OPT_BUILD_METEOR_DEMODULATOR "Build the meteor demodulator module (no dependencies required)" ON)
option(OPT_BUILD_PAGER_DECODER "Build the pager decoder module (no dependencies required)" ON)
option(OPT_BUILD_RADIO "Main audio modulation decoder (AM, FM, SSB, etc...)" ON)
option(OPT_BUILD_RYFI_DECODER "RyFi data link decoder" OFF)
option(OPT_BUILD_WEATHER_SAT_DECODER "Build the HRPT decoder module (no dependencies required)" OFF)
# Misc
option(OPT_BUILD_DISCORD_PRESENCE "Build the Discord Rich Presence module" ON)
option(OPT_BUILD_FREQUENCY_MANAGER "Build the Frequency Manager module" ON)
option(OPT_BUILD_IQ_EXPORTER "Build the IQ Exporter module" ON)
option(OPT_BUILD_RECORDER "Audio and baseband recorder" ON)
option(OPT_BUILD_RIGCTL_CLIENT "Rigctl client to make SDR++ act as a panadapter" ON)
option(OPT_BUILD_RIGCTL_SERVER "Rigctl backend for controlling SDR++ with software like gpredict" ON)
option(OPT_BUILD_SCANNER "Frequency scanner" ON)
option(OPT_BUILD_SCHEDULER "Build the scheduler" OFF)
# Other options
option(USE_INTERNAL_LIBCORRECT "Use an internal version of libcorrect" ON)
option(USE_BUNDLE_DEFAULTS "Set the default resource and module directories to the right ones for a MacOS .app" OFF)
option(COPY_MSVC_REDISTRIBUTABLES "Copy over the Visual C++ Redistributable" OFF)
# Module cmake path
set(SDRPP_MODULE_CMAKE "${CMAKE_SOURCE_DIR}/sdrpp_module.cmake")
# Root source folder
set(SDRPP_CORE_ROOT "${CMAKE_SOURCE_DIR}/core/src/")
# Compiler flags
if (${CMAKE_BUILD_TYPE} MATCHES "Debug")
# Debug Flags
if (MSVC)
set(SDRPP_COMPILER_FLAGS /std:c++17 /EHsc)
elseif (CMAKE_CXX_COMPILER_ID MATCHES "Clang")
set(SDRPP_COMPILER_FLAGS -g -Og -std=c++17 -Wno-unused-command-line-argument -undefined dynamic_lookup)
else ()
set(SDRPP_COMPILER_FLAGS -g -Og -std=c++17)
endif ()
else()
set(CMAKE_CXX_FLAGS "-O3 -std=c++17 -fsanitize=address -g")
include_directories(sdrpp "/usr/include/volk")
link_libraries(pthread)
link_libraries(GL)
link_libraries(GLEW)
link_libraries(glfw)
link_libraries(fftw3)
link_libraries(fftw3f)
link_libraries(portaudio)
link_libraries(X11)
link_libraries(Xxf86vm)
endif (MSVC)
# Normal Flags
if (MSVC)
set(SDRPP_COMPILER_FLAGS /O2 /Ob2 /std:c++17 /EHsc)
elseif (CMAKE_CXX_COMPILER_ID MATCHES "Clang")
set(SDRPP_COMPILER_FLAGS -O3 -std=c++17 -Wno-unused-command-line-argument -undefined dynamic_lookup)
else ()
set(SDRPP_COMPILER_FLAGS -O3 -std=c++17)
endif ()
endif()
set(SDRPP_MODULE_COMPILER_FLAGS ${SDRPP_COMPILER_FLAGS})
link_libraries(volk)
link_libraries(SoapySDR)
# Set a default install prefix
if (CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT)
if (${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
set(CMAKE_INSTALL_PREFIX "/usr/local" CACHE PATH "..." FORCE)
else()
set(CMAKE_INSTALL_PREFIX "/usr" CACHE PATH "..." FORCE)
endif()
endif()
# Main code
include_directories(sdrpp "src/")
include_directories(sdrpp "src/imgui")
file(GLOB SRC "src/*.cpp")
file(GLOB IMGUI "src/imgui/*.cpp")
add_executable(sdrpp ${SRC} ${IMGUI})
# Configure toolchain for android
if (ANDROID)
set(CMAKE_SHARED_LINKER_FLAGS
"${CMAKE_SHARED_LINKER_FLAGS} -u ANativeActivity_onCreate"
)
set(CMAKE_C_STANDARD 11)
set(CMAKE_CXX_STANDARD 14)
set(CMAKE_CXX14_EXTENSION_COMPILE_OPTION "-std=c++17")
endif (ANDROID)
# Core of SDR++
add_subdirectory("core")
# Source modules
if (OPT_BUILD_AIRSPY_SOURCE)
add_subdirectory("source_modules/airspy_source")
endif (OPT_BUILD_AIRSPY_SOURCE)
if (OPT_BUILD_AIRSPYHF_SOURCE)
add_subdirectory("source_modules/airspyhf_source")
endif (OPT_BUILD_AIRSPYHF_SOURCE)
if (OPT_BUILD_AUDIO_SOURCE)
add_subdirectory("source_modules/audio_source")
endif (OPT_BUILD_AUDIO_SOURCE)
if (OPT_BUILD_BADGESDR_SOURCE)
add_subdirectory("source_modules/badgesdr_source")
endif (OPT_BUILD_BADGESDR_SOURCE)
if (OPT_BUILD_BLADERF_SOURCE)
add_subdirectory("source_modules/bladerf_source")
endif (OPT_BUILD_BLADERF_SOURCE)
if (OPT_BUILD_FILE_SOURCE)
add_subdirectory("source_modules/file_source")
endif (OPT_BUILD_FILE_SOURCE)
if (OPT_BUILD_FOBOSSDR_SOURCE)
add_subdirectory("source_modules/fobossdr_source")
endif (OPT_BUILD_FOBOSSDR_SOURCE)
if (OPT_BUILD_HACKRF_SOURCE)
add_subdirectory("source_modules/hackrf_source")
endif (OPT_BUILD_HACKRF_SOURCE)
if (OPT_BUILD_HAROGIC_SOURCE)
add_subdirectory("source_modules/harogic_source")
endif (OPT_BUILD_HAROGIC_SOURCE)
if (OPT_BUILD_HERMES_SOURCE)
add_subdirectory("source_modules/hermes_source")
endif (OPT_BUILD_HERMES_SOURCE)
if (OPT_BUILD_KCSDR_SOURCE)
add_subdirectory("source_modules/kcsdr_source")
endif (OPT_BUILD_KCSDR_SOURCE)
if (OPT_BUILD_LIMESDR_SOURCE)
add_subdirectory("source_modules/limesdr_source")
endif (OPT_BUILD_LIMESDR_SOURCE)
if (OPT_BUILD_NETWORK_SOURCE)
add_subdirectory("source_modules/network_source")
endif (OPT_BUILD_NETWORK_SOURCE)
if (OPT_BUILD_PERSEUS_SOURCE)
add_subdirectory("source_modules/perseus_source")
endif (OPT_BUILD_PERSEUS_SOURCE)
if (OPT_BUILD_PLUTOSDR_SOURCE)
add_subdirectory("source_modules/plutosdr_source")
endif (OPT_BUILD_PLUTOSDR_SOURCE)
if (OPT_BUILD_RFNM_SOURCE)
add_subdirectory("source_modules/rfnm_source")
endif (OPT_BUILD_RFNM_SOURCE)
if (OPT_BUILD_RFSPACE_SOURCE)
add_subdirectory("source_modules/rfspace_source")
endif (OPT_BUILD_RFSPACE_SOURCE)
if (OPT_BUILD_RTL_SDR_SOURCE)
add_subdirectory("source_modules/rtl_sdr_source")
endif (OPT_BUILD_RTL_SDR_SOURCE)
if (OPT_BUILD_RTL_TCP_SOURCE)
add_subdirectory("source_modules/rtl_tcp_source")
endif (OPT_BUILD_RTL_TCP_SOURCE)
if (OPT_BUILD_SDRPP_SERVER_SOURCE)
add_subdirectory("source_modules/sdrpp_server_source")
endif (OPT_BUILD_SDRPP_SERVER_SOURCE)
if (OPT_BUILD_SDRPLAY_SOURCE)
add_subdirectory("source_modules/sdrplay_source")
endif (OPT_BUILD_SDRPLAY_SOURCE)
if (OPT_BUILD_SOAPY_SOURCE)
add_subdirectory("source_modules/soapy_source")
endif (OPT_BUILD_SOAPY_SOURCE)
if (OPT_BUILD_SPECTRAN_SOURCE)
add_subdirectory("source_modules/spectran_source")
endif (OPT_BUILD_SPECTRAN_SOURCE)
if (OPT_BUILD_SPECTRAN_HTTP_SOURCE)
add_subdirectory("source_modules/spectran_http_source")
endif (OPT_BUILD_SPECTRAN_HTTP_SOURCE)
if (OPT_BUILD_SPYSERVER_SOURCE)
add_subdirectory("source_modules/spyserver_source")
endif (OPT_BUILD_SPYSERVER_SOURCE)
if (OPT_BUILD_USRP_SOURCE)
add_subdirectory("source_modules/usrp_source")
endif (OPT_BUILD_USRP_SOURCE)
# Sink modules
if (OPT_BUILD_ANDROID_AUDIO_SINK)
add_subdirectory("sink_modules/android_audio_sink")
endif (OPT_BUILD_ANDROID_AUDIO_SINK)
if (OPT_BUILD_AUDIO_SINK)
add_subdirectory("sink_modules/audio_sink")
endif (OPT_BUILD_AUDIO_SINK)
if (OPT_BUILD_PORTAUDIO_SINK)
add_subdirectory("sink_modules/portaudio_sink")
endif (OPT_BUILD_PORTAUDIO_SINK)
if (OPT_BUILD_NETWORK_SINK)
add_subdirectory("sink_modules/network_sink")
endif (OPT_BUILD_NETWORK_SINK)
if (OPT_BUILD_NEW_PORTAUDIO_SINK)
add_subdirectory("sink_modules/new_portaudio_sink")
endif (OPT_BUILD_NEW_PORTAUDIO_SINK)
# Decoders
if (OPT_BUILD_ATV_DECODER)
add_subdirectory("decoder_modules/atv_decoder")
endif (OPT_BUILD_ATV_DECODER)
if (OPT_BUILD_DAB_DECODER)
add_subdirectory("decoder_modules/dab_decoder")
endif (OPT_BUILD_DAB_DECODER)
if (OPT_BUILD_FALCON9_DECODER)
add_subdirectory("decoder_modules/falcon9_decoder")
endif (OPT_BUILD_FALCON9_DECODER)
if (OPT_BUILD_KG_SSTV_DECODER)
add_subdirectory("decoder_modules/kg_sstv_decoder")
endif (OPT_BUILD_KG_SSTV_DECODER)
if (OPT_BUILD_M17_DECODER)
add_subdirectory("decoder_modules/m17_decoder")
endif (OPT_BUILD_M17_DECODER)
if (OPT_BUILD_METEOR_DEMODULATOR)
add_subdirectory("decoder_modules/meteor_demodulator")
endif (OPT_BUILD_METEOR_DEMODULATOR)
if (OPT_BUILD_PAGER_DECODER)
add_subdirectory("decoder_modules/pager_decoder")
endif (OPT_BUILD_PAGER_DECODER)
if (OPT_BUILD_RADIO)
add_subdirectory("decoder_modules/radio")
endif (OPT_BUILD_RADIO)
if (OPT_BUILD_RYFI_DECODER)
add_subdirectory("decoder_modules/ryfi_decoder")
endif (OPT_BUILD_RYFI_DECODER)
if (OPT_BUILD_WEATHER_SAT_DECODER)
add_subdirectory("decoder_modules/weather_sat_decoder")
endif (OPT_BUILD_WEATHER_SAT_DECODER)
# Misc
if (OPT_BUILD_DISCORD_PRESENCE)
add_subdirectory("misc_modules/discord_integration")
endif (OPT_BUILD_DISCORD_PRESENCE)
if (OPT_BUILD_FREQUENCY_MANAGER)
add_subdirectory("misc_modules/frequency_manager")
endif (OPT_BUILD_FREQUENCY_MANAGER)
if (OPT_BUILD_IQ_EXPORTER)
add_subdirectory("misc_modules/iq_exporter")
endif (OPT_BUILD_IQ_EXPORTER)
if (OPT_BUILD_RECORDER)
add_subdirectory("misc_modules/recorder")
endif (OPT_BUILD_RECORDER)
if (OPT_BUILD_RIGCTL_CLIENT)
add_subdirectory("misc_modules/rigctl_client")
endif (OPT_BUILD_RIGCTL_CLIENT)
if (OPT_BUILD_RIGCTL_SERVER)
add_subdirectory("misc_modules/rigctl_server")
endif (OPT_BUILD_RIGCTL_SERVER)
if (OPT_BUILD_SCANNER)
add_subdirectory("misc_modules/scanner")
endif (OPT_BUILD_SCANNER)
if (OPT_BUILD_SCHEDULER)
add_subdirectory("misc_modules/scheduler")
endif (OPT_BUILD_SCHEDULER)
if (MSVC)
# Glew
find_package(GLEW REQUIRED)
target_link_libraries(sdrpp PRIVATE GLEW::GLEW)
add_executable(sdrpp "src/main.cpp" "win32/resources.rc")
else ()
add_executable(sdrpp "src/main.cpp")
endif ()
# GLFW3
find_package(glfw3 CONFIG REQUIRED)
target_link_libraries(sdrpp PRIVATE glfw)
target_link_libraries(sdrpp PRIVATE sdrpp_core)
# FFTW3
find_package(FFTW3 CONFIG REQUIRED)
target_link_libraries(sdrpp PRIVATE FFTW3::fftw3)
find_package(FFTW3f CONFIG REQUIRED)
target_link_libraries(sdrpp PRIVATE FFTW3::fftw3f)
# Compiler arguments
target_compile_options(sdrpp PRIVATE ${SDRPP_COMPILER_FLAGS})
# PortAudio
find_package(portaudio CONFIG REQUIRED)
target_link_libraries(sdrpp PRIVATE portaudio portaudio_static)
endif (MSVC)
# Copy dynamic libs over
if (MSVC)
add_custom_target(do_always ALL xcopy /s \"$<TARGET_FILE_DIR:sdrpp_core>\\*.dll\" \"$<TARGET_FILE_DIR:sdrpp>\" /Y)
add_custom_target(do_always_volk ALL xcopy /s \"C:/Program Files/PothosSDR/bin\\volk.dll\" \"$<TARGET_FILE_DIR:sdrpp>\" /Y)
# # Copy resource directories
# if (!MSVC)
# add_custom_command(TARGET sdrpp POST_BUILD COMMAND cmake -E copy_directory ${CMAKE_SOURCE_DIR}/res ${CMAKE_BINARY_DIR}/res)
# add_custom_command(TARGET sdrpp POST_BUILD COMMAND cmake -E copy_directory ${CMAKE_SOURCE_DIR}/bandplans ${CMAKE_BINARY_DIR}/bandplans)
# endif (MSVC)
if (COPY_MSVC_REDISTRIBUTABLES)
# Get the list of Visual C++ runtime DLLs
set(CMAKE_INSTALL_SYSTEM_RUNTIME_LIBS_SKIP True)
include(InstallRequiredSystemLibraries)
# cmake .. "-DCMAKE_TOOLCHAIN_FILE=C:/Users/Alex/vcpkg/scripts/buildsystems/vcpkg.cmake" -G "Visual Studio 15 2017 Win64"
# Create a space sperated list
set(REDIST_DLLS_STR "")
foreach(DLL IN LISTS CMAKE_INSTALL_SYSTEM_RUNTIME_LIBS)
set(REDIST_DLLS_STR COMMAND xcopy /F \"${DLL}\" \"$<TARGET_FILE_DIR:sdrpp>\" /Y ${REDIST_DLLS_STR})
endforeach()
# Create target
add_custom_target(do_always_msvc ALL ${REDIST_DLLS_STR})
endif ()
endif ()
if (${CMAKE_SYSTEM_NAME} MATCHES "OpenBSD")
add_custom_target(do_always ALL cp \"$<TARGET_FILE_DIR:sdrpp_core>/libsdrpp_core.so\" \"$<TARGET_FILE_DIR:sdrpp>\")
endif ()
if (${CMAKE_SYSTEM_NAME} MATCHES "FreeBSD")
target_link_libraries(sdrpp PUBLIC pthread)
add_custom_target(do_always ALL cp \"$<TARGET_FILE_DIR:sdrpp_core>/libsdrpp_core.so\" \"$<TARGET_FILE_DIR:sdrpp>\")
endif ()
if (${CMAKE_SYSTEM_NAME} MATCHES "Linux")
add_custom_target(do_always ALL cp \"$<TARGET_FILE_DIR:sdrpp_core>/libsdrpp_core.so\" \"$<TARGET_FILE_DIR:sdrpp>\")
endif ()
if (${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
add_custom_target(do_always ALL cp \"$<TARGET_FILE_DIR:sdrpp_core>/libsdrpp_core.dylib\" \"$<TARGET_FILE_DIR:sdrpp>\")
endif ()
# cmake .. "-DCMAKE_TOOLCHAIN_FILE=C:/dev/vcpkg/scripts/buildsystems/vcpkg.cmake" -DOPT_BUILD_BLADERF_SOURCE=ON -DOPT_BUILD_LIMESDR_SOURCE=ON -DOPT_BUILD_SDRPLAY_SOURCE=ON -DOPT_BUILD_M17_DECODER=ON -DOPT_BUILD_SCANNER=ON -DOPT_BUILD_SCHEDULER=ON -DOPT_BUILD_USRP_SOURCE=ON -DOPT_BUILD_PAGER_DECODER=ON
# Create module cmake file
configure_file(${CMAKE_SOURCE_DIR}/sdrpp_module.cmake ${CMAKE_CURRENT_BINARY_DIR}/sdrpp_module.cmake @ONLY)
# Install directives
install(TARGETS sdrpp DESTINATION bin)
install(DIRECTORY ${CMAKE_SOURCE_DIR}/root/res/bandplans DESTINATION share/sdrpp)
install(DIRECTORY ${CMAKE_SOURCE_DIR}/root/res/colormaps DESTINATION share/sdrpp)
install(DIRECTORY ${CMAKE_SOURCE_DIR}/root/res/fonts DESTINATION share/sdrpp)
install(DIRECTORY ${CMAKE_SOURCE_DIR}/root/res/icons DESTINATION share/sdrpp)
install(DIRECTORY ${CMAKE_SOURCE_DIR}/root/res/themes DESTINATION share/sdrpp)
configure_file(${CMAKE_SOURCE_DIR}/sdrpp.desktop ${CMAKE_CURRENT_BINARY_DIR}/sdrpp.desktop @ONLY)
if (${CMAKE_SYSTEM_NAME} MATCHES "Linux")
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/sdrpp.desktop DESTINATION share/applications)
endif ()
# Create uninstall target
configure_file(${CMAKE_SOURCE_DIR}/cmake_uninstall.cmake ${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake @ONLY)
add_custom_target(uninstall ${CMAKE_COMMAND} -P ${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake)
# Create headers target

12
android/.gitignore vendored Normal file
View File

@ -0,0 +1,12 @@
.cxx
.externalNativeBuild
build/
*.iml
.idea
.gradle
local.properties
# Android Studio puts a Gradle wrapper here, that we don't want:
gradle/
gradlew*

76
android/app/build.gradle Normal file
View File

@ -0,0 +1,76 @@
apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
android {
compileSdkVersion 28
buildToolsVersion "30.0.3"
ndkVersion "25.1.8937393"
defaultConfig {
applicationId "org.sdrpp.sdrpp"
minSdkVersion 28
targetSdkVersion 28
versionCode 1
versionName "1.2.0"
externalNativeBuild {
cmake {
arguments "-DOPT_BACKEND_GLFW=OFF", "-DOPT_BACKEND_ANDROID=ON", "-DOPT_BUILD_SOAPY_SOURCE=OFF", "-DOPT_BUILD_ANDROID_AUDIO_SINK=ON", "-DOPT_BUILD_AUDIO_SINK=OFF", "-DOPT_BUILD_DISCORD_PRESENCE=OFF", "-DOPT_BUILD_M17_DECODER=ON", "-DOPT_BUILD_PLUTOSDR_SOURCE=ON", "-DOPT_BUILD_AUDIO_SOURCE=OFF"
}
}
}
signingConfigs {
debug {
storeFile file("debug.keystore")
storePassword "android"
keyAlias "androiddebugkey"
keyPassword "android"
}
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt')
}
debug {
signingConfig signingConfigs.debug
}
}
externalNativeBuild {
cmake {
version "3.18.1"
path "../../CMakeLists.txt"
}
}
sourceSets {
main {
assets.srcDirs += ['assets']
}
}
}
task deleteTempAssets (type: Delete) {
delete 'assets'
}
task copyResources(type: Copy) {
description = 'Copy resources...'
from '../../root/'
into 'assets/'
include('**/*')
}
repositories {
mavenCentral()
}
dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
implementation 'androidx.appcompat:appcompat:1.0.2'
}
copyResources.dependsOn deleteTempAssets
preBuild.dependsOn copyResources

BIN
android/app/debug.keystore Normal file

Binary file not shown.

View File

@ -0,0 +1,28 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="org.sdrpp.sdrpp">
<application
android:label="SDR++"
android:allowBackup="false"
android:fullBackupContent="false"
android:hasCode="true">
<activity
android:name="org.sdrpp.sdrpp.MainActivity"
android:icon="@mipmap/ic_launcher"
android:theme="@android:style/Theme.NoTitleBar.Fullscreen"
android:configChanges="orientation|keyboardHidden|screenSize">
<meta-data android:name="android.app.lib_name" android:value="sdrpp_core" />
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.INTERNET"/>
</manifest>

View File

@ -0,0 +1,32 @@
package org.sdrpp.sdrpp;
import android.app.NativeActivity;
import android.app.AlertDialog;
import android.app.PendingIntent;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.DialogInterface;
import android.content.pm.PackageManager;
import android.hardware.usb.*;
import android.Manifest;
import android.os.Bundle;
import android.view.View;
import android.view.KeyEvent;
import android.view.inputmethod.InputMethodManager;
import android.util.Log;
import android.content.res.AssetManager;
import androidx.core.app.ActivityCompat;
import androidx.core.content.PermissionChecker;
import java.util.concurrent.LinkedBlockingQueue;
import java.io.*;
class DeviceManager {
public fun init() {
}
}

View File

@ -0,0 +1,192 @@
package org.sdrpp.sdrpp;
import android.app.NativeActivity;
import android.app.AlertDialog;
import android.app.PendingIntent;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.DialogInterface;
import android.content.pm.PackageManager;
import android.hardware.usb.*;
import android.Manifest;
import android.os.Bundle;
import android.view.View;
import android.view.KeyEvent;
import android.view.inputmethod.InputMethodManager;
import android.util.Log;
import android.content.res.AssetManager;
import androidx.core.app.ActivityCompat;
import androidx.core.content.PermissionChecker;
import java.util.concurrent.LinkedBlockingQueue;
import java.io.*;
private const val ACTION_USB_PERMISSION = "org.sdrpp.sdrpp.USB_PERMISSION";
private val usbReceiver = object : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
if (ACTION_USB_PERMISSION == intent.action) {
synchronized(this) {
var _this = context as MainActivity;
_this.SDR_device = intent.getParcelableExtra(UsbManager.EXTRA_DEVICE)
if (intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false)) {
_this.SDR_conn = _this.usbManager!!.openDevice(_this.SDR_device);
// Save SDR info
_this.SDR_VID = _this.SDR_device!!.getVendorId();
_this.SDR_PID = _this.SDR_device!!.getProductId()
_this.SDR_FD = _this.SDR_conn!!.getFileDescriptor();
}
// Whatever the hell this does
context.unregisterReceiver(this);
// Hide again the system bars
_this.hideSystemBars();
}
}
}
}
class MainActivity : NativeActivity() {
private val TAG : String = "SDR++";
public var usbManager : UsbManager? = null;
public var SDR_device : UsbDevice? = null;
public var SDR_conn : UsbDeviceConnection? = null;
public var SDR_VID : Int = -1;
public var SDR_PID : Int = -1;
public var SDR_FD : Int = -1;
fun checkAndAsk(permission: String) {
if (PermissionChecker.checkSelfPermission(this, permission) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this, arrayOf(permission), 1);
}
}
public fun hideSystemBars() {
val decorView = getWindow().getDecorView();
val uiOptions = View.SYSTEM_UI_FLAG_HIDE_NAVIGATION or View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY;
decorView.setSystemUiVisibility(uiOptions);
}
public override fun onCreate(savedInstanceState: Bundle?) {
// Hide bars
hideSystemBars();
// Ask for required permissions, without these the app cannot run.
checkAndAsk(Manifest.permission.WRITE_EXTERNAL_STORAGE);
checkAndAsk(Manifest.permission.READ_EXTERNAL_STORAGE);
// TODO: Have the main code wait until these two permissions are available
// Register events
usbManager = getSystemService(Context.USB_SERVICE) as UsbManager;
val permissionIntent = PendingIntent.getBroadcast(this, 0, Intent(ACTION_USB_PERMISSION), 0)
val filter = IntentFilter(ACTION_USB_PERMISSION)
registerReceiver(usbReceiver, filter)
// Get permission for all USB devices
val devList = usbManager!!.getDeviceList();
for ((name, dev) in devList) {
usbManager!!.requestPermission(dev, permissionIntent);
}
// Ask for internet permission
checkAndAsk(Manifest.permission.INTERNET);
super.onCreate(savedInstanceState)
}
public override fun onResume() {
// Hide bars again
hideSystemBars();
super.onResume();
}
fun showSoftInput() {
val inputMethodManager = getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager;
inputMethodManager.showSoftInput(window.decorView, 0);
}
fun hideSoftInput() {
val inputMethodManager = getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager;
inputMethodManager.hideSoftInputFromWindow(window.decorView.windowToken, 0);
hideSystemBars();
}
// Queue for the Unicode characters to be polled from native code (via pollUnicodeChar())
private var unicodeCharacterQueue: LinkedBlockingQueue<Int> = LinkedBlockingQueue()
// We assume dispatchKeyEvent() of the NativeActivity is actually called for every
// KeyEvent and not consumed by any View before it reaches here
override fun dispatchKeyEvent(event: KeyEvent): Boolean {
if (event.action == KeyEvent.ACTION_DOWN) {
unicodeCharacterQueue.offer(event.getUnicodeChar(event.metaState))
}
return super.dispatchKeyEvent(event)
}
fun pollUnicodeChar(): Int {
return unicodeCharacterQueue.poll() ?: 0
}
public fun createIfDoesntExist(path: String) {
// This is a directory, create it in the filesystem
var folder = File(path);
var success = true;
if (!folder.exists()) {
success = folder.mkdirs();
}
if (!success) {
Log.e(TAG, "Could not create folder with path " + path);
}
}
public fun extractDir(aman: AssetManager, local: String, rsrc: String): Int {
val flist = aman.list(rsrc);
var ecount = 0;
for (fp in flist) {
val lpath = local + "/" + fp;
val rpath = rsrc + "/" + fp;
Log.w(TAG, "Extracting '" + rpath + "' to '" + lpath + "'");
// Create local path if non-existent
createIfDoesntExist(local);
// Create if directory
val ext = extractDir(aman, lpath, rpath);
// Extract if file
if (ext == 0) {
// This is a file, extract it
val _os = FileOutputStream(lpath);
val _is = aman.open(rpath);
val ilen = _is.available();
var fbuf = ByteArray(ilen);
_is.read(fbuf, 0, ilen);
_os.write(fbuf);
_os.close();
_is.close();
}
ecount++;
}
return ecount;
}
public fun getAppDir(): String {
val fdir = getFilesDir().getAbsolutePath();
// Extract all resources to the app directory
val aman = getAssets();
extractDir(aman, fdir + "/res", "res");
createIfDoesntExist(fdir + "/modules");
return fdir;
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

22
android/build.gradle Normal file
View File

@ -0,0 +1,22 @@
buildscript {
ext.kotlin_version = '1.4.31'
repositories {
google()
mavenCentral()
}
dependencies {
classpath 'com.android.tools.build:gradle:4.1.0'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
}
}
allprojects {
repositories {
google()
mavenCentral()
}
}
task clean(type: Delete) {
delete rootProject.buildDir
}

View File

@ -0,0 +1 @@
android.useAndroidX=true

1
android/settings.gradle Normal file
View File

@ -0,0 +1 @@
include ':app'

View File

@ -1,7 +0,0 @@
{
"broadcast": "#0000FFFF",
"amateur": "#FF0000FF",
"aviation": "#00FF00FF",
"marine": "#00FFFFFF",
"military": "#FFFF00FF"
}

View File

@ -1,135 +0,0 @@
{
"name": "Russia",
"country_name": "Russia",
"country_code": "RU",
"author_name": "Raov",
"author_url": "https://twitter.com/raov_birbtog",
"bands": [
{
"name": "160m CW",
"type": "amateur",
"start": 1810000,
"end": 1838000
},
{
"name": "160m NB",
"type": "amateur",
"start": 1838000,
"end": 1840000
},
{
"name": "160m + Digi",
"type": "amateur",
"start": 1840000,
"end": 1843000
},
{
"name": "160m",
"type": "amateur",
"start": 1843000,
"end": 2000000
},
{
"name": "80m CW",
"type": "amateur",
"start": 3500000,
"end": 3510000
},
{
"name": "80m CW Contest",
"type": "amateur",
"start": 3510000,
"end": 3560000
},
{
"name": "80m CW",
"type": "amateur",
"start": 3560000,
"end": 3570000
},
{
"name": "80m NB, Digi 200Hz",
"type": "amateur",
"start": 3570000,
"end": 3580000
},
{
"name": "80m NB, Digi 500Hz",
"type": "amateur",
"start": 3580000,
"end": 3600000
},
{
"name": "80m SSB Contest",
"type": "amateur",
"start": 3600000,
"end": 3650000
},
{
"name": "80m",
"type": "amateur",
"start": 3650000,
"end": 3700000
},
{
"name": "80m SSB Contest",
"type": "amateur",
"start": 3700000,
"end": 3800000
},
{
"name": "60m CW 200Hz",
"type": "amateur",
"start": 5351500,
"end": 5354000
},
{
"name": "60m USB",
"type": "amateur",
"start": 5354000,
"end": 5366000
},
{
"name": "60m CW 20Hz",
"type": "amateur",
"start": 5356000,
"end": 5366500
},
{
"name": "40m CW",
"type": "amateur",
"start": 7000000,
"end": 7040000
},
{
"name": "40m NB, Digi 500Hz",
"type": "amateur",
"start": 7040000,
"end": 7050000
},
{
"name": "40m",
"type": "amateur",
"start": 7050000,
"end": 7060000
},
{
"name": "40m SSB Contest",
"type": "amateur",
"start": 7060000,
"end": 7100000
},
{
"name": "40m",
"type": "amateur",
"start": 7100000,
"end": 7130000
},
{
"name": "40m SSB Contest",
"type": "amateur",
"start": 7130000,
"end": 7200000
}
]
}

20
check_clang_format.sh Normal file
View File

@ -0,0 +1,20 @@
#!/bin/bash
echo Searching directories...
CODE_FILES=$(find . -iregex '.*\.\(h\|hpp\|c\|cpp\)$')
while read -r CPP_FILE_PATH; do
# Skip unwanted files
if [[ "$CPP_FILE_PATH" == "./.old"* ]]; then continue; fi
if [[ "$CPP_FILE_PATH" == "./build"* ]]; then continue; fi
if [[ "$CPP_FILE_PATH" == "./core/libcorrect"* ]]; then continue; fi
if [[ "$CPP_FILE_PATH" == "./core/std_replacement"* ]]; then continue; fi
if [[ "$CPP_FILE_PATH" == "./core/src/imgui"* ]]; then continue; fi
if [[ "$CPP_FILE_PATH" == "./misc_modules/discord_integration/discord-rpc"* ]]; then continue; fi
if [[ "$CPP_FILE_PATH" == "./source_modules/sddc_source/src/libsddc"* ]]; then continue; fi
if [ "$CPP_FILE_PATH" = ./core/src/json.hpp ]; then continue; fi
if [ "$CPP_FILE_PATH" = ./core/src/gui/file_dialogs.h ]; then continue; fi
echo Checking $CPP_FILE_PATH
clang-format --style=file -i -n -Werror $CPP_FILE_PATH
done <<< "$CODE_FILES"

32
cmake_uninstall.cmake Normal file
View File

@ -0,0 +1,32 @@
# http://www.vtk.org/Wiki/CMake_FAQ#Can_I_do_.22make_uninstall.22_with_CMake.3F
IF(NOT EXISTS "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt")
MESSAGE(FATAL_ERROR "Cannot find install manifest: \"@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt\"")
ENDIF(NOT EXISTS "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt")
FILE(READ "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt" files)
STRING(REGEX REPLACE "\n" ";" files "${files}")
FOREACH(file ${files})
MESSAGE(STATUS "Uninstalling \"$ENV{DESTDIR}${file}\"")
IF(EXISTS "$ENV{DESTDIR}${file}")
EXEC_PROGRAM(
"@CMAKE_COMMAND@" ARGS "-E remove \"$ENV{DESTDIR}${file}\""
OUTPUT_VARIABLE rm_out
RETURN_VALUE rm_retval
)
IF(NOT "${rm_retval}" STREQUAL 0)
MESSAGE(FATAL_ERROR "Problem when removing \"$ENV{DESTDIR}${file}\"")
ENDIF(NOT "${rm_retval}" STREQUAL 0)
ELSEIF(IS_SYMLINK "$ENV{DESTDIR}${file}")
EXEC_PROGRAM(
"@CMAKE_COMMAND@" ARGS "-E remove \"$ENV{DESTDIR}${file}\""
OUTPUT_VARIABLE rm_out
RETURN_VALUE rm_retval
)
IF(NOT "${rm_retval}" STREQUAL 0)
MESSAGE(FATAL_ERROR "Problem when removing \"$ENV{DESTDIR}${file}\"")
ENDIF(NOT "${rm_retval}" STREQUAL 0)
ELSE(EXISTS "$ENV{DESTDIR}${file}")
MESSAGE(STATUS "File \"$ENV{DESTDIR}${file}\" does not exist.")
ENDIF(EXISTS "$ENV{DESTDIR}${file}")
ENDFOREACH(file)

67
contributing.md Normal file
View File

@ -0,0 +1,67 @@
# Pull Requests
Code pull requests are **NOT welcome**. Please open an issue discussing potential bugfixes or feature requests instead.
## Band Frequency Allocation
Please follow this guide to properly format the JSON files for custom radio band allocation identifiers.
```json
{
"name": "Short name (has to fit in the menu)",
"country_name": "Name of country or area, if applicable (Use '--' otherwise)",
"country_code": "Two letter country code, if applicable (Use '--' otherwise)",
"author_name": "Name of the original/main creator of the JSON file",
"author_url": "URL the author wishes to be associated with the file (personal website, GitHub, Twitter, etc)",
"bands": [
// Bands in this array must be sorted by their starting frequency
{
"name": "Name of the band",
"type": "Type name ('amateur', 'broadcast', 'marine', 'military', or any type declared in config.json)",
"start": 148500, //In Hz, must be an integer
"end": 283500 //In Hz, must be an integer
},
{
"name": "Name of the band",
"type": "Type name ('amateur', 'broadcast', 'marine', 'military', or any type declared in config.json)",
"start": 526500, //In Hz, must be an integer
"end": 1606500 //In Hz, must be an integer
}
]
}
```
## Color Maps
Please follow this guide to properly format the JSON files for custom color maps.
```json
{
"name": "Short name (has to fit in the menu)",
"author": "Name of the original/main creator of the color map",
"map": [
// These are the color codes, in hexadecimal (#RRGGBB) format, for the custom color scales for the waterfall. They must be entered as strings, not integers, with the hashtag/pound-symbol proceeding the 6 digit number.
"#000020",
"#000030",
"#000050",
"#000091",
"#1E90FF",
"#FFFFFF",
"#FFFF00",
"#FE6D16",
"#FE6D16",
"#FF0000",
"#FF0000",
"#C60000",
"#9F0000",
"#750000",
"#4A0000"
]
}
```
# JSON Formatting
The ability to add new radio band allocation identifiers and color maps relies on JSON files. Proper formatting of these JSON files is important for reference and readability. The following guides will show you how to properly format the JSON files for their respective uses.
**IMPORTANT: JSON File cannot contain comments, there are only in this example for clarity**

170
core/CMakeLists.txt Normal file
View File

@ -0,0 +1,170 @@
cmake_minimum_required(VERSION 3.13)
project(sdrpp_core)
if (USE_INTERNAL_LIBCORRECT)
add_subdirectory("libcorrect/")
endif (USE_INTERNAL_LIBCORRECT)
if (USE_BUNDLE_DEFAULTS)
add_definitions(-DIS_MACOS_BUNDLE)
endif (USE_BUNDLE_DEFAULTS)
# Main code
file(GLOB_RECURSE SRC "src/*.cpp" "src/*.c")
add_definitions(-DSDRPP_IS_CORE)
add_definitions(-DFLOG_ANDROID_TAG="SDR++")
if (MSVC)
set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON)
endif ()
# Configure backend sources
if (OPT_BACKEND_GLFW)
file(GLOB_RECURSE BACKEND_SRC "backends/glfw/*.cpp" "backends/glfw/*.c")
endif (OPT_BACKEND_GLFW)
if (OPT_BACKEND_ANDROID)
file(GLOB_RECURSE BACKEND_SRC "backends/android/*.cpp" "backends/android/*.c")
set(BACKEND_SRC ${BACKEND_SRC} ${ANDROID_NDK}/sources/android/native_app_glue/android_native_app_glue.c)
endif (OPT_BACKEND_ANDROID)
# Add code to dyn lib
add_library(sdrpp_core SHARED ${SRC} ${BACKEND_SRC})
# Set compiler options
target_compile_options(sdrpp_core PRIVATE ${SDRPP_COMPILER_FLAGS})
# Set the install prefix
target_compile_definitions(sdrpp_core PUBLIC INSTALL_PREFIX="${CMAKE_INSTALL_PREFIX}")
# Include core headers
target_include_directories(sdrpp_core PUBLIC "src/")
target_include_directories(sdrpp_core PUBLIC "src/imgui")
# Configure backend includes and libraries
if (OPT_BACKEND_GLFW)
target_include_directories(sdrpp_core PUBLIC "backends/glfw")
target_include_directories(sdrpp_core PUBLIC "backends/glfw/imgui")
if (MSVC)
# GLFW3
find_package(glfw3 CONFIG REQUIRED)
target_link_libraries(sdrpp_core PUBLIC glfw)
else()
find_package(PkgConfig)
pkg_check_modules(GLFW3 REQUIRED glfw3)
target_include_directories(sdrpp_core PUBLIC ${GLFW3_INCLUDE_DIRS})
target_link_directories(sdrpp_core PUBLIC ${GLFW3_LIBRARY_DIRS})
target_link_libraries(sdrpp_core PUBLIC ${GLFW3_LIBRARIES})
endif()
endif (OPT_BACKEND_GLFW)
if (OPT_BACKEND_ANDROID)
target_include_directories(sdrpp_core PUBLIC "backends/android")
target_include_directories(sdrpp_core PUBLIC "backends/android/imgui")
endif (OPT_BACKEND_ANDROID)
# Link to libcorrect
if (USE_INTERNAL_LIBCORRECT)
target_include_directories(sdrpp_core PUBLIC "libcorrect/include")
target_link_libraries(sdrpp_core PUBLIC correct_static)
endif (USE_INTERNAL_LIBCORRECT)
if (OPT_OVERRIDE_STD_FILESYSTEM)
target_include_directories(sdrpp_core PUBLIC "std_replacement")
endif (OPT_OVERRIDE_STD_FILESYSTEM)
if (MSVC)
# Lib path
target_link_directories(sdrpp_core PUBLIC "C:/Program Files/PothosSDR/lib/")
# Misc headers
target_include_directories(sdrpp_core PUBLIC "C:/Program Files/PothosSDR/include/")
# Volk
target_link_libraries(sdrpp_core PUBLIC volk)
# OpenGL
find_package(OpenGL REQUIRED)
target_link_libraries(sdrpp_core PUBLIC OpenGL::GL)
# GLFW3
find_package(glfw3 CONFIG REQUIRED)
target_link_libraries(sdrpp_core PUBLIC glfw)
# FFTW3
find_package(FFTW3f CONFIG REQUIRED)
target_link_libraries(sdrpp_core PUBLIC FFTW3::fftw3f)
# WinSock2
target_link_libraries(sdrpp_core PUBLIC wsock32 ws2_32 iphlpapi)
# ZSTD
find_package(zstd CONFIG REQUIRED)
target_link_libraries(sdrpp_core PUBLIC zstd::libzstd_shared)
elseif (ANDROID)
target_include_directories(sdrpp_core PUBLIC
/sdr-kit/${ANDROID_ABI}/include
${ANDROID_NDK}/sources/android/native_app_glue
)
target_link_libraries(sdrpp_core PUBLIC
/sdr-kit/${ANDROID_ABI}/lib/libvolk.so
/sdr-kit/${ANDROID_ABI}/lib/libfftw3f.so
/sdr-kit/${ANDROID_ABI}/lib/libzstd.so
android
EGL
GLESv3
log
)
else()
find_package(PkgConfig)
find_package(OpenGL REQUIRED)
pkg_check_modules(FFTW3 REQUIRED fftw3f)
pkg_check_modules(VOLK REQUIRED volk)
pkg_check_modules(GLFW3 REQUIRED glfw3)
pkg_check_modules(LIBZSTD REQUIRED libzstd)
target_include_directories(sdrpp_core PUBLIC
${OPENGL_INCLUDE_DIRS}
${FFTW3_INCLUDE_DIRS}
${GLFW3_INCLUDE_DIRS}
${VOLK_INCLUDE_DIRS}
${LIBZSTD_INCLUDE_DIRS}
)
target_link_directories(sdrpp_core PUBLIC
${OPENGL_LIBRARY_DIRS}
${FFTW3_LIBRARY_DIRS}
${GLFW3_LIBRARY_DIRS}
${VOLK_LIBRARY_DIRS}
${LIBZSTD_LIBRARY_DIRS}
)
target_link_libraries(sdrpp_core PUBLIC
${OPENGL_LIBRARIES}
${FFTW3_LIBRARIES}
${GLFW3_LIBRARIES}
${VOLK_LIBRARIES}
${LIBZSTD_LIBRARIES}
)
if (NOT USE_INTERNAL_LIBCORRECT)
pkg_check_modules(CORRECT REQUIRED libcorrect)
target_include_directories(sdrpp_core PUBLIC ${CORRECT_INCLUDE_DIRS})
target_link_directories(sdrpp_core PUBLIC ${CORRECT_LIBRARY_DIRS})
target_link_libraries(sdrpp_core PUBLIC ${CORRECT_LIBRARIES})
endif (NOT USE_INTERNAL_LIBCORRECT)
if (${CMAKE_SYSTEM_NAME} MATCHES "Linux")
target_link_libraries(sdrpp_core PUBLIC stdc++fs)
endif ()
endif ()
set(CORE_FILES ${RUNTIME_OUTPUT_DIRECTORY} PARENT_SCOPE)
# cmake .. "-DCMAKE_TOOLCHAIN_FILE=C:/dev/vcpkg/scripts/buildsystems/vcpkg.cmake"
# Install directives
install(TARGETS sdrpp_core DESTINATION lib)

View File

@ -0,0 +1,17 @@
#pragma once
#include <vector>
#include <stdint.h>
namespace backend {
struct DevVIDPID {
uint16_t vid;
uint16_t pid;
};
extern const std::vector<DevVIDPID> AIRSPY_VIDPIDS;
extern const std::vector<DevVIDPID> AIRSPYHF_VIDPIDS;
extern const std::vector<DevVIDPID> HACKRF_VIDPIDS;
extern const std::vector<DevVIDPID> RTL_SDR_VIDPIDS;
int getDeviceFD(int& vid, int& pid, const std::vector<DevVIDPID>& allowedVidPids);
}

View File

@ -0,0 +1,483 @@
#include <backend.h>log
#include "android_backend.h"
#include <core.h>
#include <gui/gui.h>
#include "imgui.h"
#include "imgui_impl_android.h"
#include "imgui_impl_opengl3.h"
#include <android/log.h>
#include <android_native_app_glue.h>
#include <android/asset_manager.h>
#include <EGL/egl.h>
#include <GLES3/gl3.h>
#include <stdint.h>
#include <gui/icons.h>
#include <gui/style.h>
#include <gui/menus/theme.h>
#include <filesystem>
// Credit to the ImGui android OpenGL3 example for a lot of this code!
namespace backend {
struct android_app* app = NULL;
EGLDisplay _EglDisplay = EGL_NO_DISPLAY;
EGLSurface _EglSurface = EGL_NO_SURFACE;
EGLContext _EglContext = EGL_NO_CONTEXT;
bool _Initialized = false;
char _LogTag[] = "SDR++";
bool initialized = false;
bool pauseRendering = false;
bool exited = false;
// Forward declaration
int ShowSoftKeyboardInput();
int PollUnicodeChars();
void doPartialInit() {
std::string root = (std::string)core::args["root"];
backend::init();
style::loadFonts(root + "/res"); // TODO: Don't hardcode, use config
icons::load(root + "/res");
thememenu::applyTheme();
ImGui::GetStyle().ScaleAllSizes(style::uiScale);
gui::mainWindow.setFirstMenuRender();
}
void handleAppCmd(struct android_app* app, int32_t appCmd) {
switch (appCmd) {
case APP_CMD_SAVE_STATE:
flog::warn("APP_CMD_SAVE_STATE");
break;
case APP_CMD_INIT_WINDOW:
flog::warn("APP_CMD_INIT_WINDOW");
if (pauseRendering && !exited) {
doPartialInit();
pauseRendering = false;
}
exited = false;
break;
case APP_CMD_TERM_WINDOW:
flog::warn("APP_CMD_TERM_WINDOW");
pauseRendering = true;
backend::end();
break;
case APP_CMD_GAINED_FOCUS:
flog::warn("APP_CMD_GAINED_FOCUS");
break;
case APP_CMD_LOST_FOCUS:
flog::warn("APP_CMD_LOST_FOCUS");
break;
}
}
int32_t handleInputEvent(struct android_app* app, AInputEvent* inputEvent) {
return ImGui_ImplAndroid_HandleInputEvent(inputEvent);
}
int aquireWindow() {
while (!app->window) {
flog::warn("Waiting on the shitty window thing"); std::this_thread::sleep_for(std::chrono::milliseconds(30));
int out_events;
struct android_poll_source* out_data;
while (ALooper_pollAll(0, NULL, &out_events, (void**)&out_data) >= 0) {
// Process one event
if (out_data != NULL) { out_data->process(app, out_data); }
// Exit the app by returning from within the infinite loop
if (app->destroyRequested != 0) {
return -1;
}
}
}
ANativeWindow_acquire(app->window);
return 0;
}
int init(std::string resDir) {
flog::warn("Backend init");
// Get window
aquireWindow();
// EGL Init
{
_EglDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
if (_EglDisplay == EGL_NO_DISPLAY)
__android_log_print(ANDROID_LOG_ERROR, _LogTag, "%s", "eglGetDisplay(EGL_DEFAULT_DISPLAY) returned EGL_NO_DISPLAY");
if (eglInitialize(_EglDisplay, 0, 0) != EGL_TRUE)
__android_log_print(ANDROID_LOG_ERROR, _LogTag, "%s", "eglInitialize() returned with an error");
const EGLint egl_attributes[] = { EGL_BLUE_SIZE, 8, EGL_GREEN_SIZE, 8, EGL_RED_SIZE, 8, EGL_DEPTH_SIZE, 24, EGL_SURFACE_TYPE, EGL_WINDOW_BIT, EGL_NONE };
EGLint num_configs = 0;
if (eglChooseConfig(_EglDisplay, egl_attributes, nullptr, 0, &num_configs) != EGL_TRUE)
__android_log_print(ANDROID_LOG_ERROR, _LogTag, "%s", "eglChooseConfig() returned with an error");
if (num_configs == 0)
__android_log_print(ANDROID_LOG_ERROR, _LogTag, "%s", "eglChooseConfig() returned 0 matching config");
// Get the first matching config
EGLConfig egl_config;
eglChooseConfig(_EglDisplay, egl_attributes, &egl_config, 1, &num_configs);
EGLint egl_format;
eglGetConfigAttrib(_EglDisplay, egl_config, EGL_NATIVE_VISUAL_ID, &egl_format);
ANativeWindow_setBuffersGeometry(app->window, 0, 0, egl_format);
const EGLint egl_context_attributes[] = { EGL_CONTEXT_CLIENT_VERSION, 3, EGL_NONE };
_EglContext = eglCreateContext(_EglDisplay, egl_config, EGL_NO_CONTEXT, egl_context_attributes);
if (_EglContext == EGL_NO_CONTEXT)
__android_log_print(ANDROID_LOG_ERROR, _LogTag, "%s", "eglCreateContext() returned EGL_NO_CONTEXT");
_EglSurface = eglCreateWindowSurface(_EglDisplay, egl_config, app->window, NULL);
eglMakeCurrent(_EglDisplay, _EglSurface, _EglSurface, _EglContext);
}
// Setup Dear ImGui context
IMGUI_CHECKVERSION();
ImGui::CreateContext();
ImGuiIO& io = ImGui::GetIO();
(void)io;
// Disable loading/saving of .ini file from disk.
// FIXME: Consider using LoadIniSettingsFromMemory() / SaveIniSettingsToMemory() to save in appropriate location for Android.
io.IniFilename = NULL;
// Setup Platform/Renderer backends
ImGui_ImplAndroid_Init(app->window);
ImGui_ImplOpenGL3_Init("#version 300 es");
return 0;
}
void beginFrame() {
// Start the Dear ImGui frame
ImGui_ImplOpenGL3_NewFrame();
ImGui_ImplAndroid_NewFrame();
ImGui::NewFrame();
}
void render(bool vsync) {
// Rendering
ImGui::Render();
auto dSize = ImGui::GetIO().DisplaySize;
glViewport(0, 0, dSize.x, dSize.y);
glClearColor(gui::themeManager.clearColor.x, gui::themeManager.clearColor.y, gui::themeManager.clearColor.z, gui::themeManager.clearColor.w);
glClear(GL_COLOR_BUFFER_BIT);
ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());
eglSwapBuffers(_EglDisplay, _EglSurface);
}
// No screen pos to detect
void getMouseScreenPos(double& x, double& y) { x = 0; y = 0; }
void setMouseScreenPos(double x, double y) {}
int renderLoop() {
while (true) {
int out_events;
struct android_poll_source* out_data;
while (ALooper_pollAll(0, NULL, &out_events, (void**)&out_data) >= 0) {
// Process one event
if (out_data != NULL) { out_data->process(app, out_data); }
// Exit the app by returning from within the infinite loop
if (app->destroyRequested != 0) {
flog::warn("ASKED TO EXIT");
exited = true;
// Stop SDR
gui::mainWindow.setPlayState(false);
return 0;
}
}
if (_EglDisplay == EGL_NO_DISPLAY) { continue; }
if (!pauseRendering) {
// Initiate a new frame
ImGuiIO& io = ImGui::GetIO();
auto dsize = io.DisplaySize;
// Poll Unicode characters via JNI
// FIXME: do not call this every frame because of JNI overhead
PollUnicodeChars();
// Open on-screen (soft) input if requested by Dear ImGui
static bool WantTextInputLast = false;
if (io.WantTextInput && !WantTextInputLast)
ShowSoftKeyboardInput();
WantTextInputLast = io.WantTextInput;
// Render
beginFrame();
if (dsize.x > 0 && dsize.y > 0) {
ImGui::SetNextWindowPos(ImVec2(0, 0));
ImGui::SetNextWindowSize(ImVec2(dsize.x, dsize.y));
gui::mainWindow.draw();
}
render();
}
else {
std::this_thread::sleep_for(std::chrono::milliseconds(30));
}
}
return 0;
}
int end() {
// Cleanup
ImGui_ImplOpenGL3_Shutdown();
ImGui_ImplAndroid_Shutdown();
ImGui::DestroyContext();
// Destroy all
if (_EglDisplay != EGL_NO_DISPLAY) {
eglMakeCurrent(_EglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
if (_EglContext != EGL_NO_CONTEXT) { eglDestroyContext(_EglDisplay, _EglContext); }
if (_EglSurface != EGL_NO_SURFACE) { eglDestroySurface(_EglDisplay, _EglSurface); }
eglTerminate(_EglDisplay);
}
_EglDisplay = EGL_NO_DISPLAY;
_EglContext = EGL_NO_CONTEXT;
_EglSurface = EGL_NO_SURFACE;
if (app->window) { ANativeWindow_release(app->window); }
return 0;
}
int ShowSoftKeyboardInput() {
JavaVM* java_vm = app->activity->vm;
JNIEnv* java_env = NULL;
jint jni_return = java_vm->GetEnv((void**)&java_env, JNI_VERSION_1_6);
if (jni_return == JNI_ERR)
return -1;
jni_return = java_vm->AttachCurrentThread(&java_env, NULL);
if (jni_return != JNI_OK)
return -2;
jclass native_activity_clazz = java_env->GetObjectClass(app->activity->clazz);
if (native_activity_clazz == NULL)
return -3;
jmethodID method_id = java_env->GetMethodID(native_activity_clazz, "showSoftInput", "()V");
if (method_id == NULL)
return -4;
java_env->CallVoidMethod(app->activity->clazz, method_id);
jni_return = java_vm->DetachCurrentThread();
if (jni_return != JNI_OK)
return -5;
return 0;
}
int getDeviceFD(int& vid, int& pid, const std::vector<DevVIDPID>& allowedVidPids) {
JavaVM* java_vm = app->activity->vm;
JNIEnv* java_env = NULL;
jint jni_return = java_vm->GetEnv((void**)&java_env, JNI_VERSION_1_6);
if (jni_return == JNI_ERR)
return -1;
jni_return = java_vm->AttachCurrentThread(&java_env, NULL);
if (jni_return != JNI_OK)
return -1;
jclass native_activity_clazz = java_env->GetObjectClass(app->activity->clazz);
if (native_activity_clazz == NULL)
return -1;
jfieldID fd_field_id = java_env->GetFieldID(native_activity_clazz, "SDR_FD", "I");
jfieldID vid_field_id = java_env->GetFieldID(native_activity_clazz, "SDR_VID", "I");
jfieldID pid_field_id = java_env->GetFieldID(native_activity_clazz, "SDR_PID", "I");
if (!vid_field_id || !vid_field_id || !pid_field_id)
return -1;
int fd = java_env->GetIntField(app->activity->clazz, fd_field_id);
vid = java_env->GetIntField(app->activity->clazz, vid_field_id);
pid = java_env->GetIntField(app->activity->clazz, pid_field_id);
jni_return = java_vm->DetachCurrentThread();
if (jni_return != JNI_OK)
return -1;
// If no vid/pid was given, just return successfully
if (allowedVidPids.empty()) {
return fd;
}
// Otherwise, check that the vid/pid combo is allowed
for (auto const& vp : allowedVidPids) {
if (vp.vid != vid || vp.pid != pid) { continue; }
return fd;
}
return -1;
}
// Unfortunately, the native KeyEvent implementation has no getUnicodeChar() function.
// Therefore, we implement the processing of KeyEvents in MainActivity.kt and poll
// the resulting Unicode characters here via JNI and send them to Dear ImGui.
int PollUnicodeChars() {
JavaVM* java_vm = app->activity->vm;
JNIEnv* java_env = NULL;
jint jni_return = java_vm->GetEnv((void**)&java_env, JNI_VERSION_1_6);
if (jni_return == JNI_ERR)
return -1;
jni_return = java_vm->AttachCurrentThread(&java_env, NULL);
if (jni_return != JNI_OK)
return -2;
jclass native_activity_clazz = java_env->GetObjectClass(app->activity->clazz);
if (native_activity_clazz == NULL)
return -3;
jmethodID method_id = java_env->GetMethodID(native_activity_clazz, "pollUnicodeChar", "()I");
if (method_id == NULL)
return -4;
// Send the actual characters to Dear ImGui
ImGuiIO& io = ImGui::GetIO();
jint unicode_character;
while ((unicode_character = java_env->CallIntMethod(app->activity->clazz, method_id)) != 0)
io.AddInputCharacter(unicode_character);
jni_return = java_vm->DetachCurrentThread();
if (jni_return != JNI_OK)
return -5;
return 0;
}
std::string getAppFilesDir() {
JavaVM* java_vm = app->activity->vm;
JNIEnv* java_env = NULL;
jint jni_return = java_vm->GetEnv((void**)&java_env, JNI_VERSION_1_6);
if (jni_return == JNI_ERR)
throw std::runtime_error("Could not get JNI environment");
jni_return = java_vm->AttachCurrentThread(&java_env, NULL);
if (jni_return != JNI_OK)
throw std::runtime_error("Could not attach to thread");
jclass native_activity_clazz = java_env->GetObjectClass(app->activity->clazz);
if (native_activity_clazz == NULL)
throw std::runtime_error("Could not get MainActivity class");
jmethodID method_id = java_env->GetMethodID(native_activity_clazz, "getAppDir", "()Ljava/lang/String;");
if (method_id == NULL)
throw std::runtime_error("Could not get method ID");
jstring jstr = (jstring)java_env->CallObjectMethod(app->activity->clazz, method_id);
const char* _str = java_env->GetStringUTFChars(jstr, NULL);
std::string str(_str);
java_env->ReleaseStringUTFChars(jstr, _str);
jni_return = java_vm->DetachCurrentThread();
if (jni_return != JNI_OK)
throw std::runtime_error("Could not detach from thread");
return str;
}
const std::vector<DevVIDPID> AIRSPY_VIDPIDS = {
{ 0x1d50, 0x60a1 }
};
const std::vector<DevVIDPID> AIRSPYHF_VIDPIDS = {
{ 0x03EB, 0x800C }
};
const std::vector<DevVIDPID> HACKRF_VIDPIDS = {
{ 0x1d50, 0x604b },
{ 0x1d50, 0x6089 },
{ 0x1d50, 0xcc15 }
};
const std::vector<DevVIDPID> RTL_SDR_VIDPIDS = {
{ 0x0bda, 0x2832 },
{ 0x0bda, 0x2838 },
{ 0x0413, 0x6680 },
{ 0x0413, 0x6f0f },
{ 0x0458, 0x707f },
{ 0x0ccd, 0x00a9 },
{ 0x0ccd, 0x00b3 },
{ 0x0ccd, 0x00b4 },
{ 0x0ccd, 0x00b5 },
{ 0x0ccd, 0x00b7 },
{ 0x0ccd, 0x00b8 },
{ 0x0ccd, 0x00b9 },
{ 0x0ccd, 0x00c0 },
{ 0x0ccd, 0x00c6 },
{ 0x0ccd, 0x00d3 },
{ 0x0ccd, 0x00d7 },
{ 0x0ccd, 0x00e0 },
{ 0x1554, 0x5020 },
{ 0x15f4, 0x0131 },
{ 0x15f4, 0x0133 },
{ 0x185b, 0x0620 },
{ 0x185b, 0x0650 },
{ 0x185b, 0x0680 },
{ 0x1b80, 0xd393 },
{ 0x1b80, 0xd394 },
{ 0x1b80, 0xd395 },
{ 0x1b80, 0xd397 },
{ 0x1b80, 0xd398 },
{ 0x1b80, 0xd39d },
{ 0x1b80, 0xd3a4 },
{ 0x1b80, 0xd3a8 },
{ 0x1b80, 0xd3af },
{ 0x1b80, 0xd3b0 },
{ 0x1d19, 0x1101 },
{ 0x1d19, 0x1102 },
{ 0x1d19, 0x1103 },
{ 0x1d19, 0x1104 },
{ 0x1f4d, 0xa803 },
{ 0x1f4d, 0xb803 },
{ 0x1f4d, 0xc803 },
{ 0x1f4d, 0xd286 },
{ 0x1f4d, 0xd803 }
};
}
extern "C" {
void android_main(struct android_app* app) {
// Save app instance
app->onAppCmd = backend::handleAppCmd;
app->onInputEvent = backend::handleInputEvent;
backend::app = app;
// Check if this is the first time we run or not
if (backend::initialized) {
flog::warn("android_main called again");
backend::doPartialInit();
backend::pauseRendering = false;
backend::renderLoop();
return;
}
backend::initialized = true;
// Grab files dir
std::string appdir = backend::getAppFilesDir();
// Call main
char* rootpath = new char[appdir.size() + 1];
strcpy(rootpath, appdir.c_str());
char* dummy[] = { "", "-r", rootpath };
sdrpp_main(3, dummy);
}
}

View File

@ -0,0 +1,278 @@
// dear imgui: Platform Binding for Android native app
// This needs to be used along with the OpenGL 3 Renderer (imgui_impl_opengl3)
// Implemented features:
// [X] Platform: Keyboard support. Since 1.87 we are using the io.AddKeyEvent() function. Pass ImGuiKey values to all key functions e.g. ImGui::IsKeyPressed(ImGuiKey_Space). [Legacy AKEYCODE_* values will also be supported unless IMGUI_DISABLE_OBSOLETE_KEYIO is set]
// Missing features:
// [ ] Platform: Clipboard support.
// [ ] Platform: Gamepad support. Enable with 'io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad'.
// [ ] Platform: Mouse cursor shape and visibility. Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange'. FIXME: Check if this is even possible with Android.
// Important:
// - Consider using SDL or GLFW backend on Android, which will be more full-featured than this.
// - FIXME: On-screen keyboard currently needs to be enabled by the application (see examples/ and issue #3446)
// - FIXME: Unicode character inputs needs to be passed by Dear ImGui by the application (see examples/ and issue #3446)
// You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
// Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need.
// If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp.
// Read online: https://github.com/ocornut/imgui/tree/master/docs
// CHANGELOG
// (minor and older changes stripped away, please see git history for details)
// 2022-01-26: Inputs: replaced short-lived io.AddKeyModsEvent() (added two weeks ago)with io.AddKeyEvent() using ImGuiKey_ModXXX flags. Sorry for the confusion.
// 2022-01-17: Inputs: calling new io.AddMousePosEvent(), io.AddMouseButtonEvent(), io.AddMouseWheelEvent() API (1.87+).
// 2022-01-10: Inputs: calling new io.AddKeyEvent(), io.AddKeyModsEvent() + io.SetKeyEventNativeData() API (1.87+). Support for full ImGuiKey range.
// 2021-03-04: Initial version.
#include "imgui.h"
#include "imgui_impl_android.h"
#include <time.h>
#include <android/native_window.h>
#include <android/input.h>
#include <android/keycodes.h>
#include <android/log.h>
// Android data
static double g_Time = 0.0;
static ANativeWindow* g_Window;
static char g_LogTag[] = "ImGuiExample";
static ImGuiKey ImGui_ImplAndroid_KeyCodeToImGuiKey(int32_t key_code)
{
switch (key_code)
{
case AKEYCODE_TAB: return ImGuiKey_Tab;
case AKEYCODE_DPAD_LEFT: return ImGuiKey_LeftArrow;
case AKEYCODE_DPAD_RIGHT: return ImGuiKey_RightArrow;
case AKEYCODE_DPAD_UP: return ImGuiKey_UpArrow;
case AKEYCODE_DPAD_DOWN: return ImGuiKey_DownArrow;
case AKEYCODE_PAGE_UP: return ImGuiKey_PageUp;
case AKEYCODE_PAGE_DOWN: return ImGuiKey_PageDown;
case AKEYCODE_MOVE_HOME: return ImGuiKey_Home;
case AKEYCODE_MOVE_END: return ImGuiKey_End;
case AKEYCODE_INSERT: return ImGuiKey_Insert;
case AKEYCODE_FORWARD_DEL: return ImGuiKey_Delete;
case AKEYCODE_DEL: return ImGuiKey_Backspace;
case AKEYCODE_SPACE: return ImGuiKey_Space;
case AKEYCODE_ENTER: return ImGuiKey_Enter;
case AKEYCODE_ESCAPE: return ImGuiKey_Escape;
case AKEYCODE_APOSTROPHE: return ImGuiKey_Apostrophe;
case AKEYCODE_COMMA: return ImGuiKey_Comma;
case AKEYCODE_MINUS: return ImGuiKey_Minus;
case AKEYCODE_PERIOD: return ImGuiKey_Period;
case AKEYCODE_SLASH: return ImGuiKey_Slash;
case AKEYCODE_SEMICOLON: return ImGuiKey_Semicolon;
case AKEYCODE_EQUALS: return ImGuiKey_Equal;
case AKEYCODE_LEFT_BRACKET: return ImGuiKey_LeftBracket;
case AKEYCODE_BACKSLASH: return ImGuiKey_Backslash;
case AKEYCODE_RIGHT_BRACKET: return ImGuiKey_RightBracket;
case AKEYCODE_GRAVE: return ImGuiKey_GraveAccent;
case AKEYCODE_CAPS_LOCK: return ImGuiKey_CapsLock;
case AKEYCODE_SCROLL_LOCK: return ImGuiKey_ScrollLock;
case AKEYCODE_NUM_LOCK: return ImGuiKey_NumLock;
case AKEYCODE_SYSRQ: return ImGuiKey_PrintScreen;
case AKEYCODE_BREAK: return ImGuiKey_Pause;
case AKEYCODE_NUMPAD_0: return ImGuiKey_Keypad0;
case AKEYCODE_NUMPAD_1: return ImGuiKey_Keypad1;
case AKEYCODE_NUMPAD_2: return ImGuiKey_Keypad2;
case AKEYCODE_NUMPAD_3: return ImGuiKey_Keypad3;
case AKEYCODE_NUMPAD_4: return ImGuiKey_Keypad4;
case AKEYCODE_NUMPAD_5: return ImGuiKey_Keypad5;
case AKEYCODE_NUMPAD_6: return ImGuiKey_Keypad6;
case AKEYCODE_NUMPAD_7: return ImGuiKey_Keypad7;
case AKEYCODE_NUMPAD_8: return ImGuiKey_Keypad8;
case AKEYCODE_NUMPAD_9: return ImGuiKey_Keypad9;
case AKEYCODE_NUMPAD_DOT: return ImGuiKey_KeypadDecimal;
case AKEYCODE_NUMPAD_DIVIDE: return ImGuiKey_KeypadDivide;
case AKEYCODE_NUMPAD_MULTIPLY: return ImGuiKey_KeypadMultiply;
case AKEYCODE_NUMPAD_SUBTRACT: return ImGuiKey_KeypadSubtract;
case AKEYCODE_NUMPAD_ADD: return ImGuiKey_KeypadAdd;
case AKEYCODE_NUMPAD_ENTER: return ImGuiKey_KeypadEnter;
case AKEYCODE_NUMPAD_EQUALS: return ImGuiKey_KeypadEqual;
case AKEYCODE_CTRL_LEFT: return ImGuiKey_LeftCtrl;
case AKEYCODE_SHIFT_LEFT: return ImGuiKey_LeftShift;
case AKEYCODE_ALT_LEFT: return ImGuiKey_LeftAlt;
case AKEYCODE_META_LEFT: return ImGuiKey_LeftSuper;
case AKEYCODE_CTRL_RIGHT: return ImGuiKey_RightCtrl;
case AKEYCODE_SHIFT_RIGHT: return ImGuiKey_RightShift;
case AKEYCODE_ALT_RIGHT: return ImGuiKey_RightAlt;
case AKEYCODE_META_RIGHT: return ImGuiKey_RightSuper;
case AKEYCODE_MENU: return ImGuiKey_Menu;
case AKEYCODE_0: return ImGuiKey_0;
case AKEYCODE_1: return ImGuiKey_1;
case AKEYCODE_2: return ImGuiKey_2;
case AKEYCODE_3: return ImGuiKey_3;
case AKEYCODE_4: return ImGuiKey_4;
case AKEYCODE_5: return ImGuiKey_5;
case AKEYCODE_6: return ImGuiKey_6;
case AKEYCODE_7: return ImGuiKey_7;
case AKEYCODE_8: return ImGuiKey_8;
case AKEYCODE_9: return ImGuiKey_9;
case AKEYCODE_A: return ImGuiKey_A;
case AKEYCODE_B: return ImGuiKey_B;
case AKEYCODE_C: return ImGuiKey_C;
case AKEYCODE_D: return ImGuiKey_D;
case AKEYCODE_E: return ImGuiKey_E;
case AKEYCODE_F: return ImGuiKey_F;
case AKEYCODE_G: return ImGuiKey_G;
case AKEYCODE_H: return ImGuiKey_H;
case AKEYCODE_I: return ImGuiKey_I;
case AKEYCODE_J: return ImGuiKey_J;
case AKEYCODE_K: return ImGuiKey_K;
case AKEYCODE_L: return ImGuiKey_L;
case AKEYCODE_M: return ImGuiKey_M;
case AKEYCODE_N: return ImGuiKey_N;
case AKEYCODE_O: return ImGuiKey_O;
case AKEYCODE_P: return ImGuiKey_P;
case AKEYCODE_Q: return ImGuiKey_Q;
case AKEYCODE_R: return ImGuiKey_R;
case AKEYCODE_S: return ImGuiKey_S;
case AKEYCODE_T: return ImGuiKey_T;
case AKEYCODE_U: return ImGuiKey_U;
case AKEYCODE_V: return ImGuiKey_V;
case AKEYCODE_W: return ImGuiKey_W;
case AKEYCODE_X: return ImGuiKey_X;
case AKEYCODE_Y: return ImGuiKey_Y;
case AKEYCODE_Z: return ImGuiKey_Z;
case AKEYCODE_F1: return ImGuiKey_F1;
case AKEYCODE_F2: return ImGuiKey_F2;
case AKEYCODE_F3: return ImGuiKey_F3;
case AKEYCODE_F4: return ImGuiKey_F4;
case AKEYCODE_F5: return ImGuiKey_F5;
case AKEYCODE_F6: return ImGuiKey_F6;
case AKEYCODE_F7: return ImGuiKey_F7;
case AKEYCODE_F8: return ImGuiKey_F8;
case AKEYCODE_F9: return ImGuiKey_F9;
case AKEYCODE_F10: return ImGuiKey_F10;
case AKEYCODE_F11: return ImGuiKey_F11;
case AKEYCODE_F12: return ImGuiKey_F12;
default: return ImGuiKey_None;
}
}
int32_t ImGui_ImplAndroid_HandleInputEvent(AInputEvent* input_event)
{
ImGuiIO& io = ImGui::GetIO();
int32_t event_type = AInputEvent_getType(input_event);
switch (event_type)
{
case AINPUT_EVENT_TYPE_KEY:
{
int32_t event_key_code = AKeyEvent_getKeyCode(input_event);
int32_t event_scan_code = AKeyEvent_getScanCode(input_event);
int32_t event_action = AKeyEvent_getAction(input_event);
int32_t event_meta_state = AKeyEvent_getMetaState(input_event);
io.AddKeyEvent(ImGuiKey_ModCtrl, (event_meta_state & AMETA_CTRL_ON) != 0);
io.AddKeyEvent(ImGuiKey_ModShift, (event_meta_state & AMETA_SHIFT_ON) != 0);
io.AddKeyEvent(ImGuiKey_ModAlt, (event_meta_state & AMETA_ALT_ON) != 0);
io.AddKeyEvent(ImGuiKey_ModSuper, (event_meta_state & AMETA_META_ON) != 0);
switch (event_action)
{
// FIXME: AKEY_EVENT_ACTION_DOWN and AKEY_EVENT_ACTION_UP occur at once as soon as a touch pointer
// goes up from a key. We use a simple key event queue/ and process one event per key per frame in
// ImGui_ImplAndroid_NewFrame()...or consider using IO queue, if suitable: https://github.com/ocornut/imgui/issues/2787
case AKEY_EVENT_ACTION_DOWN:
case AKEY_EVENT_ACTION_UP:
{
ImGuiKey key = ImGui_ImplAndroid_KeyCodeToImGuiKey(event_key_code);
if (key != ImGuiKey_None && (event_action == AKEY_EVENT_ACTION_DOWN || event_action == AKEY_EVENT_ACTION_UP))
{
io.AddKeyEvent(key, event_action == AKEY_EVENT_ACTION_DOWN);
io.SetKeyEventNativeData(key, event_key_code, event_scan_code);
}
break;
}
default:
break;
}
break;
}
case AINPUT_EVENT_TYPE_MOTION:
{
int32_t event_action = AMotionEvent_getAction(input_event);
int32_t event_pointer_index = (event_action & AMOTION_EVENT_ACTION_POINTER_INDEX_MASK) >> AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT;
event_action &= AMOTION_EVENT_ACTION_MASK;
switch (event_action)
{
case AMOTION_EVENT_ACTION_DOWN:
case AMOTION_EVENT_ACTION_UP:
// Physical mouse buttons (and probably other physical devices) also invoke the actions AMOTION_EVENT_ACTION_DOWN/_UP,
// but we have to process them separately to identify the actual button pressed. This is done below via
// AMOTION_EVENT_ACTION_BUTTON_PRESS/_RELEASE. Here, we only process "FINGER" input (and "UNKNOWN", as a fallback).
if((AMotionEvent_getToolType(input_event, event_pointer_index) == AMOTION_EVENT_TOOL_TYPE_FINGER)
|| (AMotionEvent_getToolType(input_event, event_pointer_index) == AMOTION_EVENT_TOOL_TYPE_STYLUS)
|| (AMotionEvent_getToolType(input_event, event_pointer_index) == AMOTION_EVENT_TOOL_TYPE_MOUSE)
|| (AMotionEvent_getToolType(input_event, event_pointer_index) == AMOTION_EVENT_TOOL_TYPE_UNKNOWN))
{
io.AddMousePosEvent(AMotionEvent_getX(input_event, event_pointer_index), AMotionEvent_getY(input_event, event_pointer_index));
io.AddMouseButtonEvent(0, event_action == AMOTION_EVENT_ACTION_DOWN);
}
break;
case AMOTION_EVENT_ACTION_BUTTON_PRESS:
case AMOTION_EVENT_ACTION_BUTTON_RELEASE:
{
int32_t button_state = AMotionEvent_getButtonState(input_event);
io.AddMouseButtonEvent(0, (button_state & AMOTION_EVENT_BUTTON_PRIMARY) != 0);
io.AddMouseButtonEvent(1, (button_state & AMOTION_EVENT_BUTTON_SECONDARY) != 0);
io.AddMouseButtonEvent(2, (button_state & AMOTION_EVENT_BUTTON_TERTIARY) != 0);
}
break;
case AMOTION_EVENT_ACTION_HOVER_MOVE: // Hovering: Tool moves while NOT pressed (such as a physical mouse)
case AMOTION_EVENT_ACTION_MOVE: // Touch pointer moves while DOWN
io.AddMousePosEvent(AMotionEvent_getX(input_event, event_pointer_index), AMotionEvent_getY(input_event, event_pointer_index));
break;
case AMOTION_EVENT_ACTION_SCROLL:
io.AddMouseWheelEvent(AMotionEvent_getAxisValue(input_event, AMOTION_EVENT_AXIS_HSCROLL, event_pointer_index), AMotionEvent_getAxisValue(input_event, AMOTION_EVENT_AXIS_VSCROLL, event_pointer_index));
break;
default:
break;
}
}
return 1;
default:
break;
}
return 0;
}
bool ImGui_ImplAndroid_Init(ANativeWindow* window)
{
g_Window = window;
g_Time = 0.0;
// Setup backend capabilities flags
ImGuiIO& io = ImGui::GetIO();
io.BackendPlatformName = "imgui_impl_android";
return true;
}
void ImGui_ImplAndroid_Shutdown()
{
}
void ImGui_ImplAndroid_NewFrame()
{
ImGuiIO& io = ImGui::GetIO();
// Setup display size (every frame to accommodate for window resizing)
int32_t window_width = ANativeWindow_getWidth(g_Window);
int32_t window_height = ANativeWindow_getHeight(g_Window);
int display_width = window_width;
int display_height = window_height;
io.DisplaySize = ImVec2((float)window_width, (float)window_height);
if (window_width > 0 && window_height > 0)
io.DisplayFramebufferScale = ImVec2((float)display_width / window_width, (float)display_height / window_height);
// Setup time step
struct timespec current_timespec;
clock_gettime(CLOCK_MONOTONIC, &current_timespec);
double current_time = (double)(current_timespec.tv_sec) + (current_timespec.tv_nsec / 1000000000.0);
io.DeltaTime = g_Time > 0.0 ? (float)(current_time - g_Time) : (float)(1.0f / 60.0f);
g_Time = current_time;
}

View File

@ -0,0 +1,28 @@
// dear imgui: Platform Binding for Android native app
// This needs to be used along with the OpenGL 3 Renderer (imgui_impl_opengl3)
// Implemented features:
// [X] Platform: Keyboard support. Since 1.87 we are using the io.AddKeyEvent() function. Pass ImGuiKey values to all key functions e.g. ImGui::IsKeyPressed(ImGuiKey_Space). [Legacy AKEYCODE_* values will also be supported unless IMGUI_DISABLE_OBSOLETE_KEYIO is set]
// Missing features:
// [ ] Platform: Clipboard support.
// [ ] Platform: Gamepad support. Enable with 'io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad'.
// [ ] Platform: Mouse cursor shape and visibility. Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange'. FIXME: Check if this is even possible with Android.
// Important:
// - Consider using SDL or GLFW backend on Android, which will be more full-featured than this.
// - FIXME: On-screen keyboard currently needs to be enabled by the application (see examples/ and issue #3446)
// - FIXME: Unicode character inputs needs to be passed by Dear ImGui by the application (see examples/ and issue #3446)
// You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
// Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need.
// If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp.
// Read online: https://github.com/ocornut/imgui/tree/master/docs
#pragma once
struct ANativeWindow;
struct AInputEvent;
IMGUI_IMPL_API bool ImGui_ImplAndroid_Init(ANativeWindow* window);
IMGUI_IMPL_API int32_t ImGui_ImplAndroid_HandleInputEvent(AInputEvent* input_event);
IMGUI_IMPL_API void ImGui_ImplAndroid_Shutdown();
IMGUI_IMPL_API void ImGui_ImplAndroid_NewFrame();

View File

@ -0,0 +1,305 @@
#include <backend.h>
#include "imgui.h"
#include "imgui_impl_glfw.h"
#include "imgui_impl_opengl3.h"
#include <GLFW/glfw3.h>
#include <utils/flog.h>
#include <utils/opengl_include_code.h>
#include <version.h>
#include <core.h>
#include <filesystem>
#include <stb_image.h>
#include <stb_image_resize.h>
#include <gui/gui.h>
namespace backend {
const char* OPENGL_VERSIONS_GLSL[] = {
"#version 120",
"#version 300 es",
"#version 120"
};
const int OPENGL_VERSIONS_MAJOR[] = {
3,
3,
2
};
const int OPENGL_VERSIONS_MINOR[] = {
0,
1,
1
};
const bool OPENGL_VERSIONS_IS_ES[] = {
false,
true,
false
};
#define OPENGL_VERSION_COUNT (sizeof(OPENGL_VERSIONS_GLSL) / sizeof(char*))
bool maximized = false;
bool fullScreen = false;
int winHeight;
int winWidth;
bool _maximized = maximized;
int fsWidth, fsHeight, fsPosX, fsPosY;
int _winWidth, _winHeight;
GLFWwindow* window;
GLFWmonitor* monitor;
static void glfw_error_callback(int error, const char* description) {
flog::error("Glfw Error {0}: {1}", error, description);
}
static void maximized_callback(GLFWwindow* window, int n) {
if (n == GLFW_TRUE) {
maximized = true;
}
else {
maximized = false;
}
}
int init(std::string resDir) {
// Load config
core::configManager.acquire();
winWidth = core::configManager.conf["windowSize"]["w"];
winHeight = core::configManager.conf["windowSize"]["h"];
maximized = core::configManager.conf["maximized"];
fullScreen = core::configManager.conf["fullscreen"];
core::configManager.release();
// Setup window
glfwSetErrorCallback(glfw_error_callback);
if (!glfwInit()) {
return 1;
}
#ifdef __APPLE__
// GL 3.2 + GLSL 150
const char* glsl_version = "#version 150";
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 2);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); // 3.2+ only
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); // Required on Mac
// Create window with graphics context
monitor = glfwGetPrimaryMonitor();
window = glfwCreateWindow(winWidth, winHeight, "SDR++ v" VERSION_STR " (Built at " __TIME__ ", " __DATE__ ")", NULL, NULL);
if (window == NULL)
return 1;
glfwMakeContextCurrent(window);
#else
const char* glsl_version = "#version 120";
monitor = NULL;
for (int i = 0; i < OPENGL_VERSION_COUNT; i++) {
glsl_version = OPENGL_VERSIONS_GLSL[i];
glfwWindowHint(GLFW_CLIENT_API, OPENGL_VERSIONS_IS_ES[i] ? GLFW_OPENGL_ES_API : GLFW_OPENGL_API);
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, OPENGL_VERSIONS_MAJOR[i]);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, OPENGL_VERSIONS_MINOR[i]);
// Create window with graphics context
monitor = glfwGetPrimaryMonitor();
window = glfwCreateWindow(winWidth, winHeight, "SDR++ v" VERSION_STR " (Built at " __TIME__ ", " __DATE__ ")", NULL, NULL);
if (window == NULL) {
flog::info("OpenGL {0}.{1} {2}was not supported", OPENGL_VERSIONS_MAJOR[i], OPENGL_VERSIONS_MINOR[i], OPENGL_VERSIONS_IS_ES[i] ? "ES " : "");
continue;
}
flog::info("Using OpenGL {0}.{1}{2}", OPENGL_VERSIONS_MAJOR[i], OPENGL_VERSIONS_MINOR[i], OPENGL_VERSIONS_IS_ES[i] ? " ES" : "");
glfwMakeContextCurrent(window);
break;
}
#endif
// Load app icon
if (!std::filesystem::is_regular_file(resDir + "/icons/sdrpp.png")) {
flog::error("Icon file '{0}' doesn't exist!", resDir + "/icons/sdrpp.png");
return 1;
}
GLFWimage icons[10];
icons[0].pixels = stbi_load(((std::string)(resDir + "/icons/sdrpp.png")).c_str(), &icons[0].width, &icons[0].height, 0, 4);
icons[1].pixels = (unsigned char*)malloc(16 * 16 * 4);
icons[1].width = icons[1].height = 16;
icons[2].pixels = (unsigned char*)malloc(24 * 24 * 4);
icons[2].width = icons[2].height = 24;
icons[3].pixels = (unsigned char*)malloc(32 * 32 * 4);
icons[3].width = icons[3].height = 32;
icons[4].pixels = (unsigned char*)malloc(48 * 48 * 4);
icons[4].width = icons[4].height = 48;
icons[5].pixels = (unsigned char*)malloc(64 * 64 * 4);
icons[5].width = icons[5].height = 64;
icons[6].pixels = (unsigned char*)malloc(96 * 96 * 4);
icons[6].width = icons[6].height = 96;
icons[7].pixels = (unsigned char*)malloc(128 * 128 * 4);
icons[7].width = icons[7].height = 128;
icons[8].pixels = (unsigned char*)malloc(196 * 196 * 4);
icons[8].width = icons[8].height = 196;
icons[9].pixels = (unsigned char*)malloc(256 * 256 * 4);
icons[9].width = icons[9].height = 256;
stbir_resize_uint8(icons[0].pixels, icons[0].width, icons[0].height, icons[0].width * 4, icons[1].pixels, 16, 16, 16 * 4, 4);
stbir_resize_uint8(icons[0].pixels, icons[0].width, icons[0].height, icons[0].width * 4, icons[2].pixels, 24, 24, 24 * 4, 4);
stbir_resize_uint8(icons[0].pixels, icons[0].width, icons[0].height, icons[0].width * 4, icons[3].pixels, 32, 32, 32 * 4, 4);
stbir_resize_uint8(icons[0].pixels, icons[0].width, icons[0].height, icons[0].width * 4, icons[4].pixels, 48, 48, 48 * 4, 4);
stbir_resize_uint8(icons[0].pixels, icons[0].width, icons[0].height, icons[0].width * 4, icons[5].pixels, 64, 64, 64 * 4, 4);
stbir_resize_uint8(icons[0].pixels, icons[0].width, icons[0].height, icons[0].width * 4, icons[6].pixels, 96, 96, 96 * 4, 4);
stbir_resize_uint8(icons[0].pixels, icons[0].width, icons[0].height, icons[0].width * 4, icons[7].pixels, 128, 128, 128 * 4, 4);
stbir_resize_uint8(icons[0].pixels, icons[0].width, icons[0].height, icons[0].width * 4, icons[8].pixels, 196, 196, 196 * 4, 4);
stbir_resize_uint8(icons[0].pixels, icons[0].width, icons[0].height, icons[0].width * 4, icons[9].pixels, 256, 256, 256 * 4, 4);
glfwSetWindowIcon(window, 10, icons);
stbi_image_free(icons[0].pixels);
for (int i = 1; i < 10; i++) {
free(icons[i].pixels);
}
// Add callback for max/min if GLFW supports it
#if (GLFW_VERSION_MAJOR == 3) && (GLFW_VERSION_MINOR >= 3)
if (maximized) {
glfwMaximizeWindow(window);
}
glfwSetWindowMaximizeCallback(window, maximized_callback);
#endif
// Setup Dear ImGui context
IMGUI_CHECKVERSION();
ImGui::CreateContext();
ImGuiIO& io = ImGui::GetIO();
(void)io;
io.IniFilename = NULL;
// Setup Platform/Renderer bindings
ImGui_ImplGlfw_InitForOpenGL(window, true);
if (!ImGui_ImplOpenGL3_Init(glsl_version)) {
// If init fail, try to fall back on GLSL 1.2
flog::warn("Could not init using OpenGL with normal GLSL version, falling back to GLSL 1.2");
if (!ImGui_ImplOpenGL3_Init("#version 120")) {
flog::error("Failed to initialize OpenGL with GLSL 1.2");
return -1;
}
}
// Set window size and fullscreen state
glfwGetWindowSize(window, &_winWidth, &_winHeight);
if (fullScreen) {
flog::info("Fullscreen: ON");
fsWidth = _winWidth;
fsHeight = _winHeight;
glfwGetWindowPos(window, &fsPosX, &fsPosY);
const GLFWvidmode* mode = glfwGetVideoMode(glfwGetPrimaryMonitor());
glfwSetWindowMonitor(window, monitor, 0, 0, mode->width, mode->height, 0);
}
// Everything went according to plan
return 0;
}
void beginFrame() {
// Start the Dear ImGui frame
ImGui_ImplOpenGL3_NewFrame();
ImGui_ImplGlfw_NewFrame();
ImGui::NewFrame();
}
void render(bool vsync) {
// Rendering
ImGui::Render();
int display_w, display_h;
glfwGetFramebufferSize(window, &display_w, &display_h);
glViewport(0, 0, display_w, display_h);
glClearColor(gui::themeManager.clearColor.x, gui::themeManager.clearColor.y, gui::themeManager.clearColor.z, gui::themeManager.clearColor.w);
glClear(GL_COLOR_BUFFER_BIT);
ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());
glfwSwapInterval(vsync);
glfwSwapBuffers(window);
}
void getMouseScreenPos(double& x, double& y) {
glfwGetCursorPos(window, &x, &y);
}
void setMouseScreenPos(double x, double y) {
// Tell GLFW to move the cursor and then manually fire the event
glfwSetCursorPos(window, x, y);
ImGui_ImplGlfw_CursorPosCallback(window, x, y);
}
int renderLoop() {
// Main loop
while (!glfwWindowShouldClose(window)) {
glfwPollEvents();
beginFrame();
if (_maximized != maximized) {
_maximized = maximized;
core::configManager.acquire();
core::configManager.conf["maximized"] = _maximized;
if (!maximized) {
glfwSetWindowSize(window, core::configManager.conf["windowSize"]["w"], core::configManager.conf["windowSize"]["h"]);
}
core::configManager.release(true);
}
glfwGetWindowSize(window, &_winWidth, &_winHeight);
if (ImGui::IsKeyPressed(GLFW_KEY_F11)) {
fullScreen = !fullScreen;
if (fullScreen) {
flog::info("Fullscreen: ON");
fsWidth = _winWidth;
fsHeight = _winHeight;
glfwGetWindowPos(window, &fsPosX, &fsPosY);
const GLFWvidmode* mode = glfwGetVideoMode(glfwGetPrimaryMonitor());
glfwSetWindowMonitor(window, monitor, 0, 0, mode->width, mode->height, 0);
core::configManager.acquire();
core::configManager.conf["fullscreen"] = true;
core::configManager.release();
}
else {
flog::info("Fullscreen: OFF");
glfwSetWindowMonitor(window, nullptr, fsPosX, fsPosY, fsWidth, fsHeight, 0);
core::configManager.acquire();
core::configManager.conf["fullscreen"] = false;
core::configManager.release();
}
}
if ((_winWidth != winWidth || _winHeight != winHeight) && !maximized && _winWidth > 0 && _winHeight > 0) {
winWidth = _winWidth;
winHeight = _winHeight;
core::configManager.acquire();
core::configManager.conf["windowSize"]["w"] = winWidth;
core::configManager.conf["windowSize"]["h"] = winHeight;
core::configManager.release(true);
}
if (winWidth > 0 && winHeight > 0) {
ImGui::SetNextWindowPos(ImVec2(0, 0));
ImGui::SetNextWindowSize(ImVec2(_winWidth, _winHeight));
gui::mainWindow.draw();
}
render();
}
return 0;
}
int end() {
// Cleanup
ImGui_ImplOpenGL3_Shutdown();
ImGui_ImplGlfw_Shutdown();
ImGui::DestroyContext();
glfwDestroyWindow(window);
glfwTerminate();
return 0; // TODO: Int really needed?
}
}

View File

@ -0,0 +1,643 @@
// dear imgui: Platform Backend for GLFW
// This needs to be used along with a Renderer (e.g. OpenGL3, Vulkan, WebGPU..)
// (Info: GLFW is a cross-platform general purpose library for handling windows, inputs, OpenGL/Vulkan graphics context creation, etc.)
// (Requires: GLFW 3.1+)
// Implemented features:
// [X] Platform: Clipboard support.
// [X] Platform: Keyboard support. Since 1.87 we are using the io.AddKeyEvent() function. Pass ImGuiKey values to all key functions e.g. ImGui::IsKeyPressed(ImGuiKey_Space). [Legacy GLFW_KEY_* values will also be supported unless IMGUI_DISABLE_OBSOLETE_KEYIO is set]
// [X] Platform: Gamepad support. Enable with 'io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad'.
// [X] Platform: Mouse cursor shape and visibility. Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange' (note: the resizing cursors requires GLFW 3.4+).
// You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
// Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need.
// If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp.
// Read online: https://github.com/ocornut/imgui/tree/master/docs
// CHANGELOG
// (minor and older changes stripped away, please see git history for details)
// 2022-02-07: Added ImGui_ImplGlfw_InstallCallbacks()/ImGui_ImplGlfw_RestoreCallbacks() helpers to facilitate user installing callbacks after iniitializing backend.
// 2022-01-26: Inputs: replaced short-lived io.AddKeyModsEvent() (added two weeks ago)with io.AddKeyEvent() using ImGuiKey_ModXXX flags. Sorry for the confusion.
// 2021-01-20: Inputs: calling new io.AddKeyAnalogEvent() for gamepad support, instead of writing directly to io.NavInputs[].
// 2022-01-17: Inputs: calling new io.AddMousePosEvent(), io.AddMouseButtonEvent(), io.AddMouseWheelEvent() API (1.87+).
// 2022-01-17: Inputs: always update key mods next and before key event (not in NewFrame) to fix input queue with very low framerates.
// 2022-01-12: *BREAKING CHANGE*: Now using glfwSetCursorPosCallback(). If you called ImGui_ImplGlfw_InitXXX() with install_callbacks = false, you MUST install glfwSetCursorPosCallback() and forward it to the backend via ImGui_ImplGlfw_CursorPosCallback().
// 2022-01-10: Inputs: calling new io.AddKeyEvent(), io.AddKeyModsEvent() + io.SetKeyEventNativeData() API (1.87+). Support for full ImGuiKey range.
// 2022-01-05: Inputs: Converting GLFW untranslated keycodes back to translated keycodes (in the ImGui_ImplGlfw_KeyCallback() function) in order to match the behavior of every other backend, and facilitate the use of GLFW with lettered-shortcuts API.
// 2021-08-17: *BREAKING CHANGE*: Now using glfwSetWindowFocusCallback() to calling io.AddFocusEvent(). If you called ImGui_ImplGlfw_InitXXX() with install_callbacks = false, you MUST install glfwSetWindowFocusCallback() and forward it to the backend via ImGui_ImplGlfw_WindowFocusCallback().
// 2021-07-29: *BREAKING CHANGE*: Now using glfwSetCursorEnterCallback(). MousePos is correctly reported when the host platform window is hovered but not focused. If you called ImGui_ImplGlfw_InitXXX() with install_callbacks = false, you MUST install glfwSetWindowFocusCallback() callback and forward it to the backend via ImGui_ImplGlfw_CursorEnterCallback().
// 2021-06-29: Reorganized backend to pull data from a single structure to facilitate usage with multiple-contexts (all g_XXXX access changed to bd->XXXX).
// 2020-01-17: Inputs: Disable error callback while assigning mouse cursors because some X11 setup don't have them and it generates errors.
// 2019-12-05: Inputs: Added support for new mouse cursors added in GLFW 3.4+ (resizing cursors, not allowed cursor).
// 2019-10-18: Misc: Previously installed user callbacks are now restored on shutdown.
// 2019-07-21: Inputs: Added mapping for ImGuiKey_KeyPadEnter.
// 2019-05-11: Inputs: Don't filter value from character callback before calling AddInputCharacter().
// 2019-03-12: Misc: Preserve DisplayFramebufferScale when main window is minimized.
// 2018-11-30: Misc: Setting up io.BackendPlatformName so it can be displayed in the About Window.
// 2018-11-07: Inputs: When installing our GLFW callbacks, we save user's previously installed ones - if any - and chain call them.
// 2018-08-01: Inputs: Workaround for Emscripten which doesn't seem to handle focus related calls.
// 2018-06-29: Inputs: Added support for the ImGuiMouseCursor_Hand cursor.
// 2018-06-08: Misc: Extracted imgui_impl_glfw.cpp/.h away from the old combined GLFW+OpenGL/Vulkan examples.
// 2018-03-20: Misc: Setup io.BackendFlags ImGuiBackendFlags_HasMouseCursors flag + honor ImGuiConfigFlags_NoMouseCursorChange flag.
// 2018-02-20: Inputs: Added support for mouse cursors (ImGui::GetMouseCursor() value, passed to glfwSetCursor()).
// 2018-02-06: Misc: Removed call to ImGui::Shutdown() which is not available from 1.60 WIP, user needs to call CreateContext/DestroyContext themselves.
// 2018-02-06: Inputs: Added mapping for ImGuiKey_Space.
// 2018-01-25: Inputs: Added gamepad support if ImGuiConfigFlags_NavEnableGamepad is set.
// 2018-01-25: Inputs: Honoring the io.WantSetMousePos by repositioning the mouse (when using navigation and ImGuiConfigFlags_NavMoveMouse is set).
// 2018-01-20: Inputs: Added Horizontal Mouse Wheel support.
// 2018-01-18: Inputs: Added mapping for ImGuiKey_Insert.
// 2017-08-25: Inputs: MousePos set to -FLT_MAX,-FLT_MAX when mouse is unavailable/missing (instead of -1,-1).
// 2016-10-15: Misc: Added a void* user_data parameter to Clipboard function handlers.
#include "imgui.h"
#include "imgui_impl_glfw.h"
// Clang warnings with -Weverything
#if defined(__clang__)
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wold-style-cast" // warning: use of old-style cast
#pragma clang diagnostic ignored "-Wsign-conversion" // warning: implicit conversion changes signedness
#if __has_warning("-Wzero-as-null-pointer-constant")
#pragma clang diagnostic ignored "-Wzero-as-null-pointer-constant"
#endif
#endif
// GLFW
#include <GLFW/glfw3.h>
#ifdef _WIN32
#undef APIENTRY
#define GLFW_EXPOSE_NATIVE_WIN32
#include <GLFW/glfw3native.h> // for glfwGetWin32Window
#endif
#ifdef GLFW_RESIZE_NESW_CURSOR // Let's be nice to people who pulled GLFW between 2019-04-16 (3.4 define) and 2019-11-29 (cursors defines) // FIXME: Remove when GLFW 3.4 is released?
#define GLFW_HAS_NEW_CURSORS (GLFW_VERSION_MAJOR * 1000 + GLFW_VERSION_MINOR * 100 >= 3400) // 3.4+ GLFW_RESIZE_ALL_CURSOR, GLFW_RESIZE_NESW_CURSOR, GLFW_RESIZE_NWSE_CURSOR, GLFW_NOT_ALLOWED_CURSOR
#else
#define GLFW_HAS_NEW_CURSORS (0)
#endif
#define GLFW_HAS_GAMEPAD_API (GLFW_VERSION_MAJOR * 1000 + GLFW_VERSION_MINOR * 100 >= 3300) // 3.3+ glfwGetGamepadState() new api
#define GLFW_HAS_GET_KEY_NAME (GLFW_VERSION_MAJOR * 1000 + GLFW_VERSION_MINOR * 100 >= 3200) // 3.2+ glfwGetKeyName()
// GLFW data
enum GlfwClientApi
{
GlfwClientApi_Unknown,
GlfwClientApi_OpenGL,
GlfwClientApi_Vulkan
};
struct ImGui_ImplGlfw_Data
{
GLFWwindow* Window;
GlfwClientApi ClientApi;
double Time;
GLFWwindow* MouseWindow;
GLFWcursor* MouseCursors[ImGuiMouseCursor_COUNT];
ImVec2 LastValidMousePos;
bool InstalledCallbacks;
// Chain GLFW callbacks: our callbacks will call the user's previously installed callbacks, if any.
GLFWwindowfocusfun PrevUserCallbackWindowFocus;
GLFWcursorposfun PrevUserCallbackCursorPos;
GLFWcursorenterfun PrevUserCallbackCursorEnter;
GLFWmousebuttonfun PrevUserCallbackMousebutton;
GLFWscrollfun PrevUserCallbackScroll;
GLFWkeyfun PrevUserCallbackKey;
GLFWcharfun PrevUserCallbackChar;
GLFWmonitorfun PrevUserCallbackMonitor;
ImGui_ImplGlfw_Data() { memset(this, 0, sizeof(*this)); }
};
// Backend data stored in io.BackendPlatformUserData to allow support for multiple Dear ImGui contexts
// It is STRONGLY preferred that you use docking branch with multi-viewports (== single Dear ImGui context + multiple windows) instead of multiple Dear ImGui contexts.
// FIXME: multi-context support is not well tested and probably dysfunctional in this backend.
// - Because glfwPollEvents() process all windows and some events may be called outside of it, you will need to register your own callbacks
// (passing install_callbacks=false in ImGui_ImplGlfw_InitXXX functions), set the current dear imgui context and then call our callbacks.
// - Otherwise we may need to store a GLFWWindow* -> ImGuiContext* map and handle this in the backend, adding a little bit of extra complexity to it.
// FIXME: some shared resources (mouse cursor shape, gamepad) are mishandled when using multi-context.
static ImGui_ImplGlfw_Data* ImGui_ImplGlfw_GetBackendData()
{
return ImGui::GetCurrentContext() ? (ImGui_ImplGlfw_Data*)ImGui::GetIO().BackendPlatformUserData : NULL;
}
// Functions
static const char* ImGui_ImplGlfw_GetClipboardText(void* user_data)
{
return glfwGetClipboardString((GLFWwindow*)user_data);
}
static void ImGui_ImplGlfw_SetClipboardText(void* user_data, const char* text)
{
glfwSetClipboardString((GLFWwindow*)user_data, text);
}
static ImGuiKey ImGui_ImplGlfw_KeyToImGuiKey(int key)
{
switch (key)
{
case GLFW_KEY_TAB: return ImGuiKey_Tab;
case GLFW_KEY_LEFT: return ImGuiKey_LeftArrow;
case GLFW_KEY_RIGHT: return ImGuiKey_RightArrow;
case GLFW_KEY_UP: return ImGuiKey_UpArrow;
case GLFW_KEY_DOWN: return ImGuiKey_DownArrow;
case GLFW_KEY_PAGE_UP: return ImGuiKey_PageUp;
case GLFW_KEY_PAGE_DOWN: return ImGuiKey_PageDown;
case GLFW_KEY_HOME: return ImGuiKey_Home;
case GLFW_KEY_END: return ImGuiKey_End;
case GLFW_KEY_INSERT: return ImGuiKey_Insert;
case GLFW_KEY_DELETE: return ImGuiKey_Delete;
case GLFW_KEY_BACKSPACE: return ImGuiKey_Backspace;
case GLFW_KEY_SPACE: return ImGuiKey_Space;
case GLFW_KEY_ENTER: return ImGuiKey_Enter;
case GLFW_KEY_ESCAPE: return ImGuiKey_Escape;
case GLFW_KEY_APOSTROPHE: return ImGuiKey_Apostrophe;
case GLFW_KEY_COMMA: return ImGuiKey_Comma;
case GLFW_KEY_MINUS: return ImGuiKey_Minus;
case GLFW_KEY_PERIOD: return ImGuiKey_Period;
case GLFW_KEY_SLASH: return ImGuiKey_Slash;
case GLFW_KEY_SEMICOLON: return ImGuiKey_Semicolon;
case GLFW_KEY_EQUAL: return ImGuiKey_Equal;
case GLFW_KEY_LEFT_BRACKET: return ImGuiKey_LeftBracket;
case GLFW_KEY_BACKSLASH: return ImGuiKey_Backslash;
case GLFW_KEY_RIGHT_BRACKET: return ImGuiKey_RightBracket;
case GLFW_KEY_GRAVE_ACCENT: return ImGuiKey_GraveAccent;
case GLFW_KEY_CAPS_LOCK: return ImGuiKey_CapsLock;
case GLFW_KEY_SCROLL_LOCK: return ImGuiKey_ScrollLock;
case GLFW_KEY_NUM_LOCK: return ImGuiKey_NumLock;
case GLFW_KEY_PRINT_SCREEN: return ImGuiKey_PrintScreen;
case GLFW_KEY_PAUSE: return ImGuiKey_Pause;
case GLFW_KEY_KP_0: return ImGuiKey_Keypad0;
case GLFW_KEY_KP_1: return ImGuiKey_Keypad1;
case GLFW_KEY_KP_2: return ImGuiKey_Keypad2;
case GLFW_KEY_KP_3: return ImGuiKey_Keypad3;
case GLFW_KEY_KP_4: return ImGuiKey_Keypad4;
case GLFW_KEY_KP_5: return ImGuiKey_Keypad5;
case GLFW_KEY_KP_6: return ImGuiKey_Keypad6;
case GLFW_KEY_KP_7: return ImGuiKey_Keypad7;
case GLFW_KEY_KP_8: return ImGuiKey_Keypad8;
case GLFW_KEY_KP_9: return ImGuiKey_Keypad9;
case GLFW_KEY_KP_DECIMAL: return ImGuiKey_KeypadDecimal;
case GLFW_KEY_KP_DIVIDE: return ImGuiKey_KeypadDivide;
case GLFW_KEY_KP_MULTIPLY: return ImGuiKey_KeypadMultiply;
case GLFW_KEY_KP_SUBTRACT: return ImGuiKey_KeypadSubtract;
case GLFW_KEY_KP_ADD: return ImGuiKey_KeypadAdd;
case GLFW_KEY_KP_ENTER: return ImGuiKey_KeypadEnter;
case GLFW_KEY_KP_EQUAL: return ImGuiKey_KeypadEqual;
case GLFW_KEY_LEFT_SHIFT: return ImGuiKey_LeftShift;
case GLFW_KEY_LEFT_CONTROL: return ImGuiKey_LeftCtrl;
case GLFW_KEY_LEFT_ALT: return ImGuiKey_LeftAlt;
case GLFW_KEY_LEFT_SUPER: return ImGuiKey_LeftSuper;
case GLFW_KEY_RIGHT_SHIFT: return ImGuiKey_RightShift;
case GLFW_KEY_RIGHT_CONTROL: return ImGuiKey_RightCtrl;
case GLFW_KEY_RIGHT_ALT: return ImGuiKey_RightAlt;
case GLFW_KEY_RIGHT_SUPER: return ImGuiKey_RightSuper;
case GLFW_KEY_MENU: return ImGuiKey_Menu;
case GLFW_KEY_0: return ImGuiKey_0;
case GLFW_KEY_1: return ImGuiKey_1;
case GLFW_KEY_2: return ImGuiKey_2;
case GLFW_KEY_3: return ImGuiKey_3;
case GLFW_KEY_4: return ImGuiKey_4;
case GLFW_KEY_5: return ImGuiKey_5;
case GLFW_KEY_6: return ImGuiKey_6;
case GLFW_KEY_7: return ImGuiKey_7;
case GLFW_KEY_8: return ImGuiKey_8;
case GLFW_KEY_9: return ImGuiKey_9;
case GLFW_KEY_A: return ImGuiKey_A;
case GLFW_KEY_B: return ImGuiKey_B;
case GLFW_KEY_C: return ImGuiKey_C;
case GLFW_KEY_D: return ImGuiKey_D;
case GLFW_KEY_E: return ImGuiKey_E;
case GLFW_KEY_F: return ImGuiKey_F;
case GLFW_KEY_G: return ImGuiKey_G;
case GLFW_KEY_H: return ImGuiKey_H;
case GLFW_KEY_I: return ImGuiKey_I;
case GLFW_KEY_J: return ImGuiKey_J;
case GLFW_KEY_K: return ImGuiKey_K;
case GLFW_KEY_L: return ImGuiKey_L;
case GLFW_KEY_M: return ImGuiKey_M;
case GLFW_KEY_N: return ImGuiKey_N;
case GLFW_KEY_O: return ImGuiKey_O;
case GLFW_KEY_P: return ImGuiKey_P;
case GLFW_KEY_Q: return ImGuiKey_Q;
case GLFW_KEY_R: return ImGuiKey_R;
case GLFW_KEY_S: return ImGuiKey_S;
case GLFW_KEY_T: return ImGuiKey_T;
case GLFW_KEY_U: return ImGuiKey_U;
case GLFW_KEY_V: return ImGuiKey_V;
case GLFW_KEY_W: return ImGuiKey_W;
case GLFW_KEY_X: return ImGuiKey_X;
case GLFW_KEY_Y: return ImGuiKey_Y;
case GLFW_KEY_Z: return ImGuiKey_Z;
case GLFW_KEY_F1: return ImGuiKey_F1;
case GLFW_KEY_F2: return ImGuiKey_F2;
case GLFW_KEY_F3: return ImGuiKey_F3;
case GLFW_KEY_F4: return ImGuiKey_F4;
case GLFW_KEY_F5: return ImGuiKey_F5;
case GLFW_KEY_F6: return ImGuiKey_F6;
case GLFW_KEY_F7: return ImGuiKey_F7;
case GLFW_KEY_F8: return ImGuiKey_F8;
case GLFW_KEY_F9: return ImGuiKey_F9;
case GLFW_KEY_F10: return ImGuiKey_F10;
case GLFW_KEY_F11: return ImGuiKey_F11;
case GLFW_KEY_F12: return ImGuiKey_F12;
default: return ImGuiKey_None;
}
}
static void ImGui_ImplGlfw_UpdateKeyModifiers(int mods)
{
ImGuiIO& io = ImGui::GetIO();
io.AddKeyEvent(ImGuiKey_ModCtrl, (mods & GLFW_MOD_CONTROL) != 0);
io.AddKeyEvent(ImGuiKey_ModShift, (mods & GLFW_MOD_SHIFT) != 0);
io.AddKeyEvent(ImGuiKey_ModAlt, (mods & GLFW_MOD_ALT) != 0);
io.AddKeyEvent(ImGuiKey_ModSuper, (mods & GLFW_MOD_SUPER) != 0);
}
void ImGui_ImplGlfw_MouseButtonCallback(GLFWwindow* window, int button, int action, int mods)
{
ImGui_ImplGlfw_Data* bd = ImGui_ImplGlfw_GetBackendData();
if (bd->PrevUserCallbackMousebutton != NULL && window == bd->Window)
bd->PrevUserCallbackMousebutton(window, button, action, mods);
ImGui_ImplGlfw_UpdateKeyModifiers(mods);
ImGuiIO& io = ImGui::GetIO();
if (button >= 0 && button < ImGuiMouseButton_COUNT)
io.AddMouseButtonEvent(button, action == GLFW_PRESS);
}
void ImGui_ImplGlfw_ScrollCallback(GLFWwindow* window, double xoffset, double yoffset)
{
ImGui_ImplGlfw_Data* bd = ImGui_ImplGlfw_GetBackendData();
if (bd->PrevUserCallbackScroll != NULL && window == bd->Window)
bd->PrevUserCallbackScroll(window, xoffset, yoffset);
ImGuiIO& io = ImGui::GetIO();
io.AddMouseWheelEvent((float)xoffset, (float)yoffset);
}
static int ImGui_ImplGlfw_TranslateUntranslatedKey(int key, int scancode)
{
#if GLFW_HAS_GET_KEY_NAME && !defined(__EMSCRIPTEN__)
// GLFW 3.1+ attempts to "untranslate" keys, which goes the opposite of what every other framework does, making using lettered shortcuts difficult.
// (It had reasons to do so: namely GLFW is/was more likely to be used for WASD-type game controls rather than lettered shortcuts, but IHMO the 3.1 change could have been done differently)
// See https://github.com/glfw/glfw/issues/1502 for details.
// Adding a workaround to undo this (so our keys are translated->untranslated->translated, likely a lossy process).
// This won't cover edge cases but this is at least going to cover common cases.
if (key >= GLFW_KEY_KP_0 && key <= GLFW_KEY_KP_EQUAL)
return key;
const char* key_name = glfwGetKeyName(key, scancode);
if (key_name && key_name[0] != 0 && key_name[1] == 0)
{
const char char_names[] = "`-=[]\\,;\'./";
const int char_keys[] = { GLFW_KEY_GRAVE_ACCENT, GLFW_KEY_MINUS, GLFW_KEY_EQUAL, GLFW_KEY_LEFT_BRACKET, GLFW_KEY_RIGHT_BRACKET, GLFW_KEY_BACKSLASH, GLFW_KEY_COMMA, GLFW_KEY_SEMICOLON, GLFW_KEY_APOSTROPHE, GLFW_KEY_PERIOD, GLFW_KEY_SLASH, 0 };
IM_ASSERT(IM_ARRAYSIZE(char_names) == IM_ARRAYSIZE(char_keys));
if (key_name[0] >= '0' && key_name[0] <= '9') { key = GLFW_KEY_0 + (key_name[0] - '0'); }
else if (key_name[0] >= 'A' && key_name[0] <= 'Z') { key = GLFW_KEY_A + (key_name[0] - 'A'); }
else if (const char* p = strchr(char_names, key_name[0])) { key = char_keys[p - char_names]; }
}
// if (action == GLFW_PRESS) printf("key %d scancode %d name '%s'\n", key, scancode, key_name);
#else
IM_UNUSED(scancode);
#endif
return key;
}
void ImGui_ImplGlfw_KeyCallback(GLFWwindow* window, int keycode, int scancode, int action, int mods)
{
ImGui_ImplGlfw_Data* bd = ImGui_ImplGlfw_GetBackendData();
if (bd->PrevUserCallbackKey != NULL && window == bd->Window)
bd->PrevUserCallbackKey(window, keycode, scancode, action, mods);
if (action != GLFW_PRESS && action != GLFW_RELEASE)
return;
ImGui_ImplGlfw_UpdateKeyModifiers(mods);
keycode = ImGui_ImplGlfw_TranslateUntranslatedKey(keycode, scancode);
ImGuiIO& io = ImGui::GetIO();
ImGuiKey imgui_key = ImGui_ImplGlfw_KeyToImGuiKey(keycode);
io.AddKeyEvent(imgui_key, (action == GLFW_PRESS));
io.SetKeyEventNativeData(imgui_key, keycode, scancode); // To support legacy indexing (<1.87 user code)
}
void ImGui_ImplGlfw_WindowFocusCallback(GLFWwindow* window, int focused)
{
ImGui_ImplGlfw_Data* bd = ImGui_ImplGlfw_GetBackendData();
if (bd->PrevUserCallbackWindowFocus != NULL && window == bd->Window)
bd->PrevUserCallbackWindowFocus(window, focused);
ImGuiIO& io = ImGui::GetIO();
io.AddFocusEvent(focused != 0);
}
void ImGui_ImplGlfw_CursorPosCallback(GLFWwindow* window, double x, double y)
{
ImGui_ImplGlfw_Data* bd = ImGui_ImplGlfw_GetBackendData();
if (bd->PrevUserCallbackCursorPos != NULL && window == bd->Window)
bd->PrevUserCallbackCursorPos(window, x, y);
ImGuiIO& io = ImGui::GetIO();
io.AddMousePosEvent((float)x, (float)y);
bd->LastValidMousePos = ImVec2((float)x, (float)y);
}
// Workaround: X11 seems to send spurious Leave/Enter events which would make us lose our position,
// so we back it up and restore on Leave/Enter (see https://github.com/ocornut/imgui/issues/4984)
void ImGui_ImplGlfw_CursorEnterCallback(GLFWwindow* window, int entered)
{
ImGui_ImplGlfw_Data* bd = ImGui_ImplGlfw_GetBackendData();
if (bd->PrevUserCallbackCursorEnter != NULL && window == bd->Window)
bd->PrevUserCallbackCursorEnter(window, entered);
ImGuiIO& io = ImGui::GetIO();
if (entered)
{
bd->MouseWindow = window;
io.AddMousePosEvent(bd->LastValidMousePos.x, bd->LastValidMousePos.y);
}
else if (!entered && bd->MouseWindow == window)
{
bd->LastValidMousePos = io.MousePos;
bd->MouseWindow = NULL;
io.AddMousePosEvent(-FLT_MAX, -FLT_MAX);
}
}
void ImGui_ImplGlfw_CharCallback(GLFWwindow* window, unsigned int c)
{
ImGui_ImplGlfw_Data* bd = ImGui_ImplGlfw_GetBackendData();
if (bd->PrevUserCallbackChar != NULL && window == bd->Window)
bd->PrevUserCallbackChar(window, c);
ImGuiIO& io = ImGui::GetIO();
io.AddInputCharacter(c);
}
void ImGui_ImplGlfw_MonitorCallback(GLFWmonitor*, int)
{
// Unused in 'master' branch but 'docking' branch will use this, so we declare it ahead of it so if you have to install callbacks you can install this one too.
}
void ImGui_ImplGlfw_InstallCallbacks(GLFWwindow* window)
{
ImGui_ImplGlfw_Data* bd = ImGui_ImplGlfw_GetBackendData();
IM_ASSERT(bd->InstalledCallbacks == false && "Callbacks already installed!");
IM_ASSERT(bd->Window == window);
bd->PrevUserCallbackWindowFocus = glfwSetWindowFocusCallback(window, ImGui_ImplGlfw_WindowFocusCallback);
bd->PrevUserCallbackCursorEnter = glfwSetCursorEnterCallback(window, ImGui_ImplGlfw_CursorEnterCallback);
bd->PrevUserCallbackCursorPos = glfwSetCursorPosCallback(window, ImGui_ImplGlfw_CursorPosCallback);
bd->PrevUserCallbackMousebutton = glfwSetMouseButtonCallback(window, ImGui_ImplGlfw_MouseButtonCallback);
bd->PrevUserCallbackScroll = glfwSetScrollCallback(window, ImGui_ImplGlfw_ScrollCallback);
bd->PrevUserCallbackKey = glfwSetKeyCallback(window, ImGui_ImplGlfw_KeyCallback);
bd->PrevUserCallbackChar = glfwSetCharCallback(window, ImGui_ImplGlfw_CharCallback);
bd->PrevUserCallbackMonitor = glfwSetMonitorCallback(ImGui_ImplGlfw_MonitorCallback);
bd->InstalledCallbacks = true;
}
void ImGui_ImplGlfw_RestoreCallbacks(GLFWwindow* window)
{
ImGui_ImplGlfw_Data* bd = ImGui_ImplGlfw_GetBackendData();
IM_ASSERT(bd->InstalledCallbacks == true && "Callbacks not installed!");
IM_ASSERT(bd->Window == window);
glfwSetWindowFocusCallback(window, bd->PrevUserCallbackWindowFocus);
glfwSetCursorEnterCallback(window, bd->PrevUserCallbackCursorEnter);
glfwSetCursorPosCallback(window, bd->PrevUserCallbackCursorPos);
glfwSetMouseButtonCallback(window, bd->PrevUserCallbackMousebutton);
glfwSetScrollCallback(window, bd->PrevUserCallbackScroll);
glfwSetKeyCallback(window, bd->PrevUserCallbackKey);
glfwSetCharCallback(window, bd->PrevUserCallbackChar);
glfwSetMonitorCallback(bd->PrevUserCallbackMonitor);
bd->InstalledCallbacks = false;
bd->PrevUserCallbackWindowFocus = NULL;
bd->PrevUserCallbackCursorEnter = NULL;
bd->PrevUserCallbackCursorPos = NULL;
bd->PrevUserCallbackMousebutton = NULL;
bd->PrevUserCallbackScroll = NULL;
bd->PrevUserCallbackKey = NULL;
bd->PrevUserCallbackChar = NULL;
bd->PrevUserCallbackMonitor = NULL;
}
static bool ImGui_ImplGlfw_Init(GLFWwindow* window, bool install_callbacks, GlfwClientApi client_api)
{
ImGuiIO& io = ImGui::GetIO();
IM_ASSERT(io.BackendPlatformUserData == NULL && "Already initialized a platform backend!");
// Setup backend capabilities flags
ImGui_ImplGlfw_Data* bd = IM_NEW(ImGui_ImplGlfw_Data)();
io.BackendPlatformUserData = (void*)bd;
io.BackendPlatformName = "imgui_impl_glfw";
io.BackendFlags |= ImGuiBackendFlags_HasMouseCursors; // We can honor GetMouseCursor() values (optional)
io.BackendFlags |= ImGuiBackendFlags_HasSetMousePos; // We can honor io.WantSetMousePos requests (optional, rarely used)
bd->Window = window;
bd->Time = 0.0;
io.SetClipboardTextFn = ImGui_ImplGlfw_SetClipboardText;
io.GetClipboardTextFn = ImGui_ImplGlfw_GetClipboardText;
io.ClipboardUserData = bd->Window;
// Set platform dependent data in viewport
#if defined(_WIN32)
ImGui::GetMainViewport()->PlatformHandleRaw = (void*)glfwGetWin32Window(bd->Window);
#endif
// Create mouse cursors
// (By design, on X11 cursors are user configurable and some cursors may be missing. When a cursor doesn't exist,
// GLFW will emit an error which will often be printed by the app, so we temporarily disable error reporting.
// Missing cursors will return NULL and our _UpdateMouseCursor() function will use the Arrow cursor instead.)
GLFWerrorfun prev_error_callback = glfwSetErrorCallback(NULL);
bd->MouseCursors[ImGuiMouseCursor_Arrow] = glfwCreateStandardCursor(GLFW_ARROW_CURSOR);
bd->MouseCursors[ImGuiMouseCursor_TextInput] = glfwCreateStandardCursor(GLFW_IBEAM_CURSOR);
bd->MouseCursors[ImGuiMouseCursor_ResizeNS] = glfwCreateStandardCursor(GLFW_VRESIZE_CURSOR);
bd->MouseCursors[ImGuiMouseCursor_ResizeEW] = glfwCreateStandardCursor(GLFW_HRESIZE_CURSOR);
bd->MouseCursors[ImGuiMouseCursor_Hand] = glfwCreateStandardCursor(GLFW_HAND_CURSOR);
#if GLFW_HAS_NEW_CURSORS
bd->MouseCursors[ImGuiMouseCursor_ResizeAll] = glfwCreateStandardCursor(GLFW_RESIZE_ALL_CURSOR);
bd->MouseCursors[ImGuiMouseCursor_ResizeNESW] = glfwCreateStandardCursor(GLFW_RESIZE_NESW_CURSOR);
bd->MouseCursors[ImGuiMouseCursor_ResizeNWSE] = glfwCreateStandardCursor(GLFW_RESIZE_NWSE_CURSOR);
bd->MouseCursors[ImGuiMouseCursor_NotAllowed] = glfwCreateStandardCursor(GLFW_NOT_ALLOWED_CURSOR);
#else
bd->MouseCursors[ImGuiMouseCursor_ResizeAll] = glfwCreateStandardCursor(GLFW_ARROW_CURSOR);
bd->MouseCursors[ImGuiMouseCursor_ResizeNESW] = glfwCreateStandardCursor(GLFW_ARROW_CURSOR);
bd->MouseCursors[ImGuiMouseCursor_ResizeNWSE] = glfwCreateStandardCursor(GLFW_ARROW_CURSOR);
bd->MouseCursors[ImGuiMouseCursor_NotAllowed] = glfwCreateStandardCursor(GLFW_ARROW_CURSOR);
#endif
glfwSetErrorCallback(prev_error_callback);
// Chain GLFW callbacks: our callbacks will call the user's previously installed callbacks, if any.
if (install_callbacks)
ImGui_ImplGlfw_InstallCallbacks(window);
bd->ClientApi = client_api;
return true;
}
bool ImGui_ImplGlfw_InitForOpenGL(GLFWwindow* window, bool install_callbacks)
{
return ImGui_ImplGlfw_Init(window, install_callbacks, GlfwClientApi_OpenGL);
}
bool ImGui_ImplGlfw_InitForVulkan(GLFWwindow* window, bool install_callbacks)
{
return ImGui_ImplGlfw_Init(window, install_callbacks, GlfwClientApi_Vulkan);
}
bool ImGui_ImplGlfw_InitForOther(GLFWwindow* window, bool install_callbacks)
{
return ImGui_ImplGlfw_Init(window, install_callbacks, GlfwClientApi_Unknown);
}
void ImGui_ImplGlfw_Shutdown()
{
ImGui_ImplGlfw_Data* bd = ImGui_ImplGlfw_GetBackendData();
IM_ASSERT(bd != NULL && "No platform backend to shutdown, or already shutdown?");
ImGuiIO& io = ImGui::GetIO();
if (bd->InstalledCallbacks)
ImGui_ImplGlfw_RestoreCallbacks(bd->Window);
for (ImGuiMouseCursor cursor_n = 0; cursor_n < ImGuiMouseCursor_COUNT; cursor_n++)
glfwDestroyCursor(bd->MouseCursors[cursor_n]);
io.BackendPlatformName = NULL;
io.BackendPlatformUserData = NULL;
IM_DELETE(bd);
}
static void ImGui_ImplGlfw_UpdateMouseData()
{
ImGui_ImplGlfw_Data* bd = ImGui_ImplGlfw_GetBackendData();
ImGuiIO& io = ImGui::GetIO();
#ifdef __EMSCRIPTEN__
const bool is_app_focused = true;
#else
const bool is_app_focused = glfwGetWindowAttrib(bd->Window, GLFW_FOCUSED) != 0;
#endif
if (is_app_focused)
{
// (Optional) Set OS mouse position from Dear ImGui if requested (rarely used, only when ImGuiConfigFlags_NavEnableSetMousePos is enabled by user)
if (io.WantSetMousePos)
glfwSetCursorPos(bd->Window, (double)io.MousePos.x, (double)io.MousePos.y);
// (Optional) Fallback to provide mouse position when focused (ImGui_ImplGlfw_CursorPosCallback already provides this when hovered or captured)
if (is_app_focused && bd->MouseWindow == NULL)
{
double mouse_x, mouse_y;
glfwGetCursorPos(bd->Window, &mouse_x, &mouse_y);
io.AddMousePosEvent((float)mouse_x, (float)mouse_y);
bd->LastValidMousePos = ImVec2((float)mouse_x, (float)mouse_y);
}
}
}
static void ImGui_ImplGlfw_UpdateMouseCursor()
{
ImGuiIO& io = ImGui::GetIO();
ImGui_ImplGlfw_Data* bd = ImGui_ImplGlfw_GetBackendData();
if ((io.ConfigFlags & ImGuiConfigFlags_NoMouseCursorChange) || glfwGetInputMode(bd->Window, GLFW_CURSOR) == GLFW_CURSOR_DISABLED)
return;
ImGuiMouseCursor imgui_cursor = ImGui::GetMouseCursor();
if (imgui_cursor == ImGuiMouseCursor_None || io.MouseDrawCursor)
{
// Hide OS mouse cursor if imgui is drawing it or if it wants no cursor
glfwSetInputMode(bd->Window, GLFW_CURSOR, GLFW_CURSOR_HIDDEN);
}
else
{
// Show OS mouse cursor
// FIXME-PLATFORM: Unfocused windows seems to fail changing the mouse cursor with GLFW 3.2, but 3.3 works here.
glfwSetCursor(bd->Window, bd->MouseCursors[imgui_cursor] ? bd->MouseCursors[imgui_cursor] : bd->MouseCursors[ImGuiMouseCursor_Arrow]);
glfwSetInputMode(bd->Window, GLFW_CURSOR, GLFW_CURSOR_NORMAL);
}
}
// Update gamepad inputs
static inline float Saturate(float v) { return v < 0.0f ? 0.0f : v > 1.0f ? 1.0f : v; }
static void ImGui_ImplGlfw_UpdateGamepads()
{
ImGuiIO& io = ImGui::GetIO();
if ((io.ConfigFlags & ImGuiConfigFlags_NavEnableGamepad) == 0)
return;
io.BackendFlags &= ~ImGuiBackendFlags_HasGamepad;
#if GLFW_HAS_GAMEPAD_API
GLFWgamepadstate gamepad;
if (!glfwGetGamepadState(GLFW_JOYSTICK_1, &gamepad))
return;
#define MAP_BUTTON(KEY_NO, BUTTON_NO, _UNUSED) do { io.AddKeyEvent(KEY_NO, gamepad.buttons[BUTTON_NO] != 0); } while (0)
#define MAP_ANALOG(KEY_NO, AXIS_NO, _UNUSED, V0, V1) do { float v = gamepad.axes[AXIS_NO]; v = (v - V0) / (V1 - V0); io.AddKeyAnalogEvent(KEY_NO, v > 0.10f, Saturate(v)); } while (0)
#else
int axes_count = 0, buttons_count = 0;
const float* axes = glfwGetJoystickAxes(GLFW_JOYSTICK_1, &axes_count);
const unsigned char* buttons = glfwGetJoystickButtons(GLFW_JOYSTICK_1, &buttons_count);
if (axes_count == 0 || buttons_count == 0)
return;
#define MAP_BUTTON(KEY_NO, _UNUSED, BUTTON_NO) do { io.AddKeyEvent(KEY_NO, (buttons_count > BUTTON_NO && buttons[BUTTON_NO] == GLFW_PRESS)); } while (0)
#define MAP_ANALOG(KEY_NO, _UNUSED, AXIS_NO, V0, V1) do { float v = (axes_count > AXIS_NO) ? axes[AXIS_NO] : V0; v = (v - V0) / (V1 - V0); io.AddKeyAnalogEvent(KEY_NO, v > 0.10f, Saturate(v)); } while (0)
#endif
io.BackendFlags |= ImGuiBackendFlags_HasGamepad;
MAP_BUTTON(ImGuiKey_GamepadStart, GLFW_GAMEPAD_BUTTON_START, 7);
MAP_BUTTON(ImGuiKey_GamepadBack, GLFW_GAMEPAD_BUTTON_BACK, 6);
MAP_BUTTON(ImGuiKey_GamepadFaceDown, GLFW_GAMEPAD_BUTTON_A, 0); // Xbox A, PS Cross
MAP_BUTTON(ImGuiKey_GamepadFaceRight, GLFW_GAMEPAD_BUTTON_B, 1); // Xbox B, PS Circle
MAP_BUTTON(ImGuiKey_GamepadFaceLeft, GLFW_GAMEPAD_BUTTON_X, 2); // Xbox X, PS Square
MAP_BUTTON(ImGuiKey_GamepadFaceUp, GLFW_GAMEPAD_BUTTON_Y, 3); // Xbox Y, PS Triangle
MAP_BUTTON(ImGuiKey_GamepadDpadLeft, GLFW_GAMEPAD_BUTTON_DPAD_LEFT, 13);
MAP_BUTTON(ImGuiKey_GamepadDpadRight, GLFW_GAMEPAD_BUTTON_DPAD_RIGHT, 11);
MAP_BUTTON(ImGuiKey_GamepadDpadUp, GLFW_GAMEPAD_BUTTON_DPAD_UP, 10);
MAP_BUTTON(ImGuiKey_GamepadDpadDown, GLFW_GAMEPAD_BUTTON_DPAD_DOWN, 12);
MAP_BUTTON(ImGuiKey_GamepadL1, GLFW_GAMEPAD_BUTTON_LEFT_BUMPER, 4);
MAP_BUTTON(ImGuiKey_GamepadR1, GLFW_GAMEPAD_BUTTON_RIGHT_BUMPER, 5);
MAP_ANALOG(ImGuiKey_GamepadL2, GLFW_GAMEPAD_AXIS_LEFT_TRIGGER, 4, -0.75f, +1.0f);
MAP_ANALOG(ImGuiKey_GamepadR2, GLFW_GAMEPAD_AXIS_RIGHT_TRIGGER, 5, -0.75f, +1.0f);
MAP_BUTTON(ImGuiKey_GamepadL3, GLFW_GAMEPAD_BUTTON_LEFT_THUMB, 8);
MAP_BUTTON(ImGuiKey_GamepadR3, GLFW_GAMEPAD_BUTTON_RIGHT_THUMB, 9);
MAP_ANALOG(ImGuiKey_GamepadLStickLeft, GLFW_GAMEPAD_AXIS_LEFT_X, 0, -0.25f, -1.0f);
MAP_ANALOG(ImGuiKey_GamepadLStickRight, GLFW_GAMEPAD_AXIS_LEFT_X, 0, +0.25f, +1.0f);
MAP_ANALOG(ImGuiKey_GamepadLStickUp, GLFW_GAMEPAD_AXIS_LEFT_Y, 1, -0.25f, -1.0f);
MAP_ANALOG(ImGuiKey_GamepadLStickDown, GLFW_GAMEPAD_AXIS_LEFT_Y, 1, +0.25f, +1.0f);
MAP_ANALOG(ImGuiKey_GamepadRStickLeft, GLFW_GAMEPAD_AXIS_RIGHT_X, 2, -0.25f, -1.0f);
MAP_ANALOG(ImGuiKey_GamepadRStickRight, GLFW_GAMEPAD_AXIS_RIGHT_X, 2, +0.25f, +1.0f);
MAP_ANALOG(ImGuiKey_GamepadRStickUp, GLFW_GAMEPAD_AXIS_RIGHT_Y, 3, -0.25f, -1.0f);
MAP_ANALOG(ImGuiKey_GamepadRStickDown, GLFW_GAMEPAD_AXIS_RIGHT_Y, 3, +0.25f, +1.0f);
#undef MAP_BUTTON
#undef MAP_ANALOG
}
void ImGui_ImplGlfw_NewFrame()
{
ImGuiIO& io = ImGui::GetIO();
ImGui_ImplGlfw_Data* bd = ImGui_ImplGlfw_GetBackendData();
IM_ASSERT(bd != NULL && "Did you call ImGui_ImplGlfw_InitForXXX()?");
// Setup display size (every frame to accommodate for window resizing)
int w, h;
int display_w, display_h;
glfwGetWindowSize(bd->Window, &w, &h);
glfwGetFramebufferSize(bd->Window, &display_w, &display_h);
io.DisplaySize = ImVec2((float)w, (float)h);
if (w > 0 && h > 0)
io.DisplayFramebufferScale = ImVec2((float)display_w / (float)w, (float)display_h / (float)h);
// Setup time step
double current_time = glfwGetTime();
io.DeltaTime = bd->Time > 0.0 ? (float)(current_time - bd->Time) : (float)(1.0f / 60.0f);
bd->Time = current_time;
ImGui_ImplGlfw_UpdateMouseData();
ImGui_ImplGlfw_UpdateMouseCursor();
// Update game controllers (if enabled and available)
ImGui_ImplGlfw_UpdateGamepads();
}
#if defined(__clang__)
#pragma clang diagnostic pop
#endif

View File

@ -0,0 +1,46 @@
// dear imgui: Platform Backend for GLFW
// This needs to be used along with a Renderer (e.g. OpenGL3, Vulkan, WebGPU..)
// (Info: GLFW is a cross-platform general purpose library for handling windows, inputs, OpenGL/Vulkan graphics context creation, etc.)
// Implemented features:
// [X] Platform: Clipboard support.
// [X] Platform: Keyboard support. Since 1.87 we are using the io.AddKeyEvent() function. Pass ImGuiKey values to all key functions e.g. ImGui::IsKeyPressed(ImGuiKey_Space). [Legacy GLFW_KEY_* values will also be supported unless IMGUI_DISABLE_OBSOLETE_KEYIO is set]
// [X] Platform: Gamepad support. Enable with 'io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad'.
// [X] Platform: Mouse cursor shape and visibility. Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange' (note: the resizing cursors requires GLFW 3.4+).
// You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
// Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need.
// If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp.
// Read online: https://github.com/ocornut/imgui/tree/master/docs
// About GLSL version:
// The 'glsl_version' initialization parameter defaults to "#version 150" if NULL.
// Only override if your GL version doesn't handle this GLSL version. Keep NULL if unsure!
#pragma once
#include "imgui.h" // IMGUI_IMPL_API
struct GLFWwindow;
struct GLFWmonitor;
IMGUI_IMPL_API bool ImGui_ImplGlfw_InitForOpenGL(GLFWwindow* window, bool install_callbacks);
IMGUI_IMPL_API bool ImGui_ImplGlfw_InitForVulkan(GLFWwindow* window, bool install_callbacks);
IMGUI_IMPL_API bool ImGui_ImplGlfw_InitForOther(GLFWwindow* window, bool install_callbacks);
IMGUI_IMPL_API void ImGui_ImplGlfw_Shutdown();
IMGUI_IMPL_API void ImGui_ImplGlfw_NewFrame();
// GLFW callbacks (installer)
// - When calling Init with 'install_callbacks=true': ImGui_ImplGlfw_InstallCallbacks() is called. GLFW callbacks will be installed for you. They will chain-call user's previously installed callbacks, if any.
// - When calling Init with 'install_callbacks=false': GLFW callbacks won't be installed. You will need to call individual function yourself from your own GLFW callbacks.
IMGUI_IMPL_API void ImGui_ImplGlfw_InstallCallbacks(GLFWwindow* window);
IMGUI_IMPL_API void ImGui_ImplGlfw_RestoreCallbacks(GLFWwindow* window);
// GLFW callbacks (individual callbacks to call if you didn't install callbacks)
IMGUI_IMPL_API void ImGui_ImplGlfw_WindowFocusCallback(GLFWwindow* window, int focused); // Since 1.84
IMGUI_IMPL_API void ImGui_ImplGlfw_CursorEnterCallback(GLFWwindow* window, int entered); // Since 1.84
IMGUI_IMPL_API void ImGui_ImplGlfw_CursorPosCallback(GLFWwindow* window, double x, double y); // Since 1.87
IMGUI_IMPL_API void ImGui_ImplGlfw_MouseButtonCallback(GLFWwindow* window, int button, int action, int mods);
IMGUI_IMPL_API void ImGui_ImplGlfw_ScrollCallback(GLFWwindow* window, double xoffset, double yoffset);
IMGUI_IMPL_API void ImGui_ImplGlfw_KeyCallback(GLFWwindow* window, int key, int scancode, int action, int mods);
IMGUI_IMPL_API void ImGui_ImplGlfw_CharCallback(GLFWwindow* window, unsigned int c);
IMGUI_IMPL_API void ImGui_ImplGlfw_MonitorCallback(GLFWmonitor* monitor, int event);

View File

@ -0,0 +1,47 @@
@echo on
if NOT EXIST C:\projects\tools (
mkdir C:\projects\tools
)
cd C:\projects\tools
::###########################################################################
:: Setup Compiler
::###########################################################################
if NOT EXIST llvm-installer.exe (
appveyor DownloadFile http://prereleases.llvm.org/win-snapshots/LLVM-5.0.0-r306282-win32.exe -FileName llvm-installer.exe
)
START /WAIT llvm-installer.exe /S /D=C:\"projects\tools\LLVM-install"
@set PATH="C:\projects\tools\LLVM-install\bin";%PATH%
clang-cl -v
if DEFINED MINGW_PATH rename "C:\Program Files\Git\usr\bin\sh.exe" "sh-ignored.exe"
if DEFINED MINGW_PATH @set "PATH=%PATH:C:\Program Files (x86)\Git\bin=%"
if DEFINED MINGW_PATH @set "PATH=%PATH%;%MINGW_PATH%"
if DEFINED MINGW_PATH g++ -v
::###########################################################################
:: Install a recent CMake
::###########################################################################
if NOT EXIST cmake (
appveyor DownloadFile https://cmake.org/files/v3.7/cmake-3.7.2-win64-x64.zip -FileName cmake.zip
7z x cmake.zip -oC:\projects\tools > nul
move C:\projects\tools\cmake-* C:\projects\tools\cmake
rm cmake.zip
)
@set PATH=C:\projects\tools\cmake\bin;%PATH%
cmake --version
::###########################################################################
:: Install Ninja
::###########################################################################
if NOT EXIST ninja (
appveyor DownloadFile https://github.com/ninja-build/ninja/releases/download/v1.6.0/ninja-win.zip -FileName ninja.zip
7z x ninja.zip -oC:\projects\tools\ninja > nul
rm ninja.zip
)
@set PATH=C:\projects\tools\ninja;%PATH%
ninja --version
@echo off

1
core/libcorrect/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
build

View File

@ -0,0 +1,12 @@
language: c
matrix:
include:
- os: linux
dist: trusty
- os: osx
script:
- mkdir build
- cd build
- cmake ..
- make shim
- make check CTEST_OUTPUT_ON_FAILURE=TRUE

View File

@ -0,0 +1,108 @@
cmake_minimum_required(VERSION 2.8)
project(Correct C)
include(CheckLibraryExists)
include(CheckIncludeFiles)
include(CheckCSourceCompiles)
include(CMakePushCheckState)
include(CheckCCompilerFlag)
if(MSVC)
set(LIBM "")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /W4")
else(MSVC)
set(LIBM "m")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fPIC -std=c99 -Wall")
check_c_compiler_flag(-Wpedantic COMPILER_SUPPORTS_WPEDANTIC)
if(COMPILER_SUPPORTS_WPEDANTIC)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wpedantic")
endif()
if(CMAKE_BUILD_TYPE STREQUAL "Debug")
# On android, keep optimisations and don't use asan
if (ANDROID)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -g3 -O3")
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,")
else()
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -g3 -O0 -fsanitize=address")
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,-no_pie,")
endif()
else()
if("${CMAKE_C_COMPILER_ID}" STREQUAL "Clang")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -O2")
else()
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -O2")
endif()
if(CMAKE_BUILD_TYPE STREQUAL "Profiling")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -O2 -g3")
endif()
endif()
endif(MSVC)
find_library(FEC fec)
CHECK_LIBRARY_EXISTS(FEC dotprod "" HAVE_LIBFEC)
if(NOT CMAKE_CROSSCOMPILING)
# Check if host machine can compile with SSE 4.1 intrinsic
cmake_push_check_state(RESET)
set(CMAKE_REQUIRED_DEFINITIONS -march=native)
check_c_source_compiles("
#include <x86intrin.h>
int main() {
__m128i a;
__m128i b;
__m128i c = _mm_min_epu16(a, b);
return 0;
}" HAVE_SSE)
cmake_pop_check_state()
endif()
if(HAVE_SSE)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -msse4.1")
endif()
set(CMAKE_CXX_VISIBILITY_PRESET hidden)
set(CMAKE_VISIBILITY_INLINES_HIDDEN 1)
set(LIBRARY_OUTPUT_PATH ${PROJECT_BINARY_DIR}/lib)
set(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin)
include_directories(${PROJECT_SOURCE_DIR}/include)
add_subdirectory(src)
set(INSTALL_HEADERS "${PROJECT_BINARY_DIR}/include/correct.h")
add_custom_target(correct-h ALL COMMAND ${CMAKE_COMMAND} -E copy ${PROJECT_SOURCE_DIR}/include/correct.h ${PROJECT_BINARY_DIR}/include/correct.h)
if(HAVE_SSE)
set(correct_obj_files $<TARGET_OBJECTS:correct-reed-solomon> $<TARGET_OBJECTS:correct-convolutional> $<TARGET_OBJECTS:correct-convolutional-sse>)
set(INSTALL_HEADERS ${INSTALL_HEADERS} ${PROJECT_BINARY_DIR}/include/correct-sse.h)
add_custom_target(correct-sse-h ALL COMMAND ${CMAKE_COMMAND} -E copy ${PROJECT_SOURCE_DIR}/include/correct-sse.h ${PROJECT_BINARY_DIR}/include/correct-sse.h)
else()
set(correct_obj_files $<TARGET_OBJECTS:correct-reed-solomon> $<TARGET_OBJECTS:correct-convolutional>)
endif()
add_library(correct SHARED ${correct_obj_files})
add_library(correct_static STATIC ${correct_obj_files})
set_target_properties(correct_static PROPERTIES OUTPUT_NAME "correct")
if(HAVE_SSE)
target_compile_definitions(correct PUBLIC HAVE_SSE=1)
target_compile_definitions(correct_static PUBLIC HAVE_SSE=1)
endif()
add_subdirectory(util)
add_subdirectory(tests)
add_subdirectory(tools)
# add_subdirectory(benchmarks)
# install(TARGETS correct correct_static
# DESTINATION lib)
# install(FILES ${INSTALL_HEADERS} DESTINATION "${CMAKE_INSTALL_PREFIX}/include")
add_library(fec_shim_static EXCLUDE_FROM_ALL src/fec_shim.c ${correct_obj_files})
set_target_properties(fec_shim_static PROPERTIES OUTPUT_NAME "fec")
add_library(fec_shim_shared SHARED EXCLUDE_FROM_ALL src/fec_shim.c ${correct_obj_files})
set_target_properties(fec_shim_shared PROPERTIES OUTPUT_NAME "fec")
add_custom_target(fec-shim-h COMMAND ${CMAKE_COMMAND} -E copy ${PROJECT_SOURCE_DIR}/include/fec_shim.h ${PROJECT_BINARY_DIR}/include/fec.h)
add_custom_target(shim DEPENDS fec_shim_static fec_shim_shared fec-shim-h)
# install(TARGETS fec_shim_static fec_shim_shared
# DESTINATION lib
# OPTIONAL)
# install(FILES ${PROJECT_BINARY_DIR}/include/fec.h DESTINATION "${CMAKE_INSTALL_PREFIX}/include" OPTIONAL)

12
core/libcorrect/LICENSE Normal file
View File

@ -0,0 +1,12 @@
Copyright (c) 2016, Brian Armstrong
All rights reserved.
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

38
core/libcorrect/README.md Normal file
View File

@ -0,0 +1,38 @@
[libcorrect](https://github.com/quiet/libcorrect)
===========
[![OSX/Linux Build Status](https://travis-ci.org/quiet/libcorrect.svg?branch=master)](https://travis-ci.org/quiet/libcorrect)
[![Windows Build status](https://ci.appveyor.com/api/projects/status/i3e84jmj00fa5my8/branch/master?svg=true)](https://ci.appveyor.com/project/brian-armstrong/libcorrect/branch/master)
libcorrect is a library for Forward Error Correction. By using libcorrect, you can encode extra redundancy into a packet of data and then send it across a lossy channel. When the packet is received, it can be decoded to recover the original, pre-encoded data.
libcorrect accomplishes this task with two algorithms, [Convolutional codes](https://en.wikipedia.org/wiki/Convolutional_code) and [Reed-Solomon](https://en.wikipedia.org/wiki/Reed%E2%80%93Solomon_error_correction). Convolutional codes are robust to a constant background noise, while Reed-Solomon error correction is effective at dealing with noise that occurs in bursts. These algorithms have played an important role in [telecommunications](https://en.wikipedia.org/wiki/Error_detection_and_correction#Deep-space_telecommunications). libcorrect uses a [Viterbi algorithm](https://en.wikipedia.org/wiki/Viterbi_algorithm) decoder to decode convolutional codes.
libcorrect is a performant, BSD-licensed library. It is also the author's hope that this library's contents could help others learn how its algorithms work.
Design goals
-----------
1. libcorrect should be a drop-in, BSD-licensed substitute for [libfec](http://www.ka9q.net/code/fec/), which offers similar functionality under the LGPL-license. Although libfec is a fantastic library, the state of LGPL-licensed libraries on mobile devices is somewhat uncertain. For this reason, libcorrect is a completely new approach under the BSD license which supports the same algorithms as libfec. Additionally, libcorrect can be built with a compatibility layer so that libcorrect can be linked in place of libfec.
Achieving this goal gives [libquiet](https://github.com/quiet/quiet) a fully BSD-/MIT-licensed set of dependencies, which gives libquiet more flexibility in mobile applications.
2. libcorrect should make it easier to investigate how forward error correction works. To accomplish this, libcorrect provides tools to test the fitness of convolutional codes and their polynomials. Additionally, libcorrect should be written in a way that leads to easy understanding of these powerful algorithms. This library's roadmap includes more documentation on how these algorithms work and how to increase their computational performance.
3. libcorrect should explore further into error correction. This goal would help libquiet operate in noisier situations. One approach might be to use parts of libcorrect's Viterbi Algorithm decoder to create a [Turbo code](https://en.wikipedia.org/wiki/Turbo_code) decoder, although this is just an idea and may turn out to be prohibitively difficult.
Build
-----------
libcorrect uses CMake, which allows for out-of-source builds. To get started, make sure that you have CMake installed, and then, from libcorrect's source directory, run `mkdir build && cd build && cmake .. && make && make install`. Additionally, if you would like the libfec compatibility layer, you can run `make shim && make install`, though do be cautioned that this can overwrite an existing installation of libfec.
If you are on a host which has `<x86intrin.h>` available, then libcorrect will automatically build its SSE version as well. The SSE headers are provided under `<correct-sse.h>`. For now, it is on the caller of this code to ensure that SSE is available and can be used. libcorrect requires SSE functions up to and including SSE4.
If you have any questions or problems with libcorrect, do not hesitate to open an issue.
-----------
I'd like to thank Ryan Hitchman and Josh Gao for all of their help and rubber ducking.
A huge thank you goes to [Lucas Teske](https://github.com/racerxdl) for finding all the ways that libcorrect was broken on Windows and to [Denis Golovan](https://github.com/MageSlayer) for finding an error in the returned length of the convolutional code decoder.

View File

@ -0,0 +1,43 @@
version: '{build}'
build:
verbosity: detailed
branches:
only:
- master
environment:
matrix:
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
COMPILER: cl.exe
MSVC_BAT: C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat
MSVC_BAT_ARCH: x86
GENERATOR: "Visual Studio 14 2015 Win64"
APPVEYOR_SAVE_CACHE_ON_ERROR: true
DLL_PATH: lib\Release\fec.dll
install:
- call "%APPVEYOR_BUILD_FOLDER%\\.appveyor-install-tools.cmd"
before_build:
- if DEFINED MSVC_BAT call "%MSVC_BAT%" %MSVC_BAT_ARCH%
- cd %APPVEYOR_BUILD_FOLDER%
build_script:
- mkdir build
- cd build
- cmake -G "%GENERATOR%" -DCMAKE_C_COMPILER=%COMPILER% -DCMAKE_CXX_COMPILER=%COMPILER% -DCMAKE_BUILD_TYPE=Release ..
- cmake --build . --config Release --target shim
- cmake --build . --config Release --target test_runners
- dumpbin /EXPORTS %DLL_PATH%
test_script:
- cd tests
- set CTEST_OUTPUT_ON_FAILURE=1
- ctest -C Release
cache:
- C:\projects\tools\ninja
- C:\projects\tools\cmake
- C:\projects\tools\llvm-installer.exe

View File

@ -0,0 +1,30 @@
#ifndef CORRECT_SSE_H
#define CORRECT_SSE_H
#include <correct.h>
struct correct_convolutional_sse;
typedef struct correct_convolutional_sse correct_convolutional_sse;
/* SSE versions of libcorrect's convolutional encoder/decoder.
* These instances should not be used with the non-sse functions,
* and non-sse instances should not be used with the sse functions.
*/
correct_convolutional_sse *correct_convolutional_sse_create(
size_t rate, size_t order, const correct_convolutional_polynomial_t *poly);
void correct_convolutional_sse_destroy(correct_convolutional_sse *conv);
size_t correct_convolutional_sse_encode_len(correct_convolutional_sse *conv, size_t msg_len);
size_t correct_convolutional_sse_encode(correct_convolutional_sse *conv, const uint8_t *msg,
size_t msg_len, uint8_t *encoded);
ssize_t correct_convolutional_sse_decode(correct_convolutional_sse *conv, const uint8_t *encoded,
size_t num_encoded_bits, uint8_t *msg);
ssize_t correct_convolutional_sse_decode_soft(correct_convolutional_sse *conv,
const correct_convolutional_soft_t *encoded,
size_t num_encoded_bits, uint8_t *msg);
#endif

View File

@ -0,0 +1,277 @@
#ifndef CORRECT_H
#define CORRECT_H
#include <stdint.h>
#ifndef _MSC_VER
#include <unistd.h>
#else
#include <stddef.h>
typedef ptrdiff_t ssize_t;
#endif
// Convolutional Codes
// Convolutional polynomials are 16 bits wide
typedef uint16_t correct_convolutional_polynomial_t;
static const correct_convolutional_polynomial_t correct_conv_r12_6_polynomial[] = {073, 061};
static const correct_convolutional_polynomial_t correct_conv_r12_7_polynomial[] = {0161, 0127};
static const correct_convolutional_polynomial_t correct_conv_r12_8_polynomial[] = {0225, 0373};
static const correct_convolutional_polynomial_t correct_conv_r12_9_polynomial[] = {0767, 0545};
static const correct_convolutional_polynomial_t correct_conv_r13_6_polynomial[] = {053, 075, 047};
static const correct_convolutional_polynomial_t correct_conv_r13_7_polynomial[] = {0137, 0153,
0121};
static const correct_convolutional_polynomial_t correct_conv_r13_8_polynomial[] = {0333, 0257,
0351};
static const correct_convolutional_polynomial_t correct_conv_r13_9_polynomial[] = {0417, 0627,
0675};
typedef uint8_t correct_convolutional_soft_t;
struct correct_convolutional;
typedef struct correct_convolutional correct_convolutional;
/* correct_convolutional_create allocates and initializes an encoder/decoder for
* a convolutional code with the given parameters. This function expects that
* poly will contain inv_rate elements. E.g., to create a conv. code instance
* with rate 1/2, order 7 and polynomials 0161, 0127, call
* correct_convolutional_create(2, 7, []correct_convolutional_polynomial_t{0161, 0127});
*
* If this call is successful, it returns a non-NULL pointer.
*/
correct_convolutional *correct_convolutional_create(size_t inv_rate, size_t order,
const correct_convolutional_polynomial_t *poly);
/* correct_convolutional_destroy releases all resources associated
* with conv. This pointer should not be used for further calls
* after calling destroy.
*/
void correct_convolutional_destroy(correct_convolutional *conv);
/* correct_convolutional_encode_len returns the number of *bits*
* in a msg_len of given size, in *bytes*. In order to convert
* this returned length to bytes, save the result of the length
* modulo 8. If it's nonzero, then the length in bytes is
* length/8 + 1. If it is zero, then the length is just
* length/8.
*/
size_t correct_convolutional_encode_len(correct_convolutional *conv, size_t msg_len);
/* correct_convolutional_encode uses the given conv instance to
* encode a block of data and write it to encoded. The length of
* encoded must be long enough to hold the resulting encoded length,
* which can be calculated by calling correct_convolutional_encode_len.
* However, this length should first be converted to bytes, as that
* function returns the length in bits.
*
* This function returns the number of bits written to encoded. If
* this is not an exact multiple of 8, then it occupies an additional
* byte.
*/
size_t correct_convolutional_encode(correct_convolutional *conv, const uint8_t *msg, size_t msg_len,
uint8_t *encoded);
/* correct_convolutional_decode uses the given conv instance to
* decode a block encoded by correct_convolutional_encode. This
* call can cope with some bits being corrupted. This function
* cannot detect if there are too many bits corrupted, however,
* and will still write a message even if it is not recovered
* correctly. It is up to the user to perform checksums or CRC
* in order to guarantee that the decoded message is intact.
*
* num_encoded_bits should contain the length of encoded in *bits*.
* This value need not be an exact multiple of 8. However,
* it must be a multiple of the inv_rate used to create
* the conv instance.
*
* This function writes the result to msg, which must be large
* enough to hold the decoded message. A good conservative size
* for this buffer is the number of encoded bits multiplied by the
* rate of the code, e.g. for a rate 1/2 code, divide by 2. This
* value should then be converted to bytes to find the correct
* length for msg.
*
* This function returns the number of bytes written to msg. If
* it fails, it returns -1.
*/
ssize_t correct_convolutional_decode(correct_convolutional *conv, const uint8_t *encoded,
size_t num_encoded_bits, uint8_t *msg);
/* correct_convolutional_decode_soft uses the given conv instance
* to decode a block encoded by correct_convolutional_encode and
* then modulated/demodulated to 8-bit symbols. This function expects
* that 1 is mapped to 255 and 0 to 0. An erased symbol should be
* set to 128. The decoded message may contain errors.
*
* num_encoded_bits should contain the length of encoded in *bits*.
* This value need not be an exact multiple of 8. However,
* it must be a multiple of the inv_rate used to create
* the conv instance.
*
* This function writes the result to msg, which must be large
* enough to hold the decoded message. A good conservative size
* for this buffer is the number of encoded bits multiplied by the
* rate of the code, e.g. for a rate 1/2 code, divide by 2. This
* value should then be converted to bytes to find the correct
* length for msg.
*
* This function returns the number of bytes written to msg. If
* it fails, it returns -1.
*/
ssize_t correct_convolutional_decode_soft(correct_convolutional *conv,
const correct_convolutional_soft_t *encoded,
size_t num_encoded_bits, uint8_t *msg);
// Reed-Solomon
struct correct_reed_solomon;
typedef struct correct_reed_solomon correct_reed_solomon;
static const uint16_t correct_rs_primitive_polynomial_8_4_3_2_0 =
0x11d; // x^8 + x^4 + x^3 + x^2 + 1
static const uint16_t correct_rs_primitive_polynomial_8_5_3_1_0 =
0x12b; // x^8 + x^5 + x^3 + x + 1
static const uint16_t correct_rs_primitive_polynomial_8_5_3_2_0 =
0x12d; // x^8 + x^5 + x^3 + x^2 + 1
static const uint16_t correct_rs_primitive_polynomial_8_6_3_2_0 =
0x14d; // x^8 + x^6 + x^3 + x^2 + 1
static const uint16_t correct_rs_primitive_polynomial_8_6_4_3_2_1_0 =
0x15f; // x^8 + x^6 + x^4 + x^3 + x^2 + x + 1;
static const uint16_t correct_rs_primitive_polynomial_8_6_5_1_0 =
0x163; // x^8 + x^6 + x^5 + x + 1
static const uint16_t correct_rs_primitive_polynomial_8_6_5_2_0 =
0x165; // x^8 + x^6 + x^5 + x^2 + 1
static const uint16_t correct_rs_primitive_polynomial_8_6_5_3_0 =
0x169; // x^8 + x^6 + x^5 + x^3 + 1
static const uint16_t correct_rs_primitive_polynomial_8_6_5_4_0 =
0x171; // x^8 + x^6 + x^5 + x^4 + 1
static const uint16_t correct_rs_primitive_polynomial_8_7_2_1_0 =
0x187; // x^8 + x^7 + x^2 + x + 1
static const uint16_t correct_rs_primitive_polynomial_8_7_3_2_0 =
0x18d; // x^8 + x^7 + x^3 + x^2 + 1
static const uint16_t correct_rs_primitive_polynomial_8_7_5_3_0 =
0x1a9; // x^8 + x^7 + x^5 + x^3 + 1
static const uint16_t correct_rs_primitive_polynomial_8_7_6_1_0 =
0x1c3; // x^8 + x^7 + x^6 + x + 1
static const uint16_t correct_rs_primitive_polynomial_8_7_6_3_2_1_0 =
0x1cf; // x^8 + x^7 + x^6 + x^3 + x^2 + x + 1
static const uint16_t correct_rs_primitive_polynomial_8_7_6_5_2_1_0 =
0x1e7; // x^8 + x^7 + x^6 + x^5 + x^2 + x + 1
static const uint16_t correct_rs_primitive_polynomial_8_7_6_5_4_2_0 =
0x1f5; // x^8 + x^7 + x^6 + x^5 + x^4 + x^2 + 1
static const uint16_t correct_rs_primitive_polynomial_ccsds =
0x187; // x^8 + x^7 + x^2 + x + 1
/* correct_reed_solomon_create allocates and initializes an
* encoder/decoder for a given reed solomon error correction
* code. The block size must be 255 bytes with 8-bit symbols.
*
* This block can repair corrupted bytes. It can handle as
* many as num_roots/2 bytes having corruption and still recover
* the encoded payload. However, using more num_roots
* adds more parity overhead and substantially increases
* the computational time for decoding.
*
* primitive_polynomial should be one of the given values in this
* file. Sane values for first_consecutive_root and
* generator_root_gap are 1 and 1. Not all combinations of
* values produce valid codes.
*/
correct_reed_solomon *correct_reed_solomon_create(uint16_t primitive_polynomial,
uint8_t first_consecutive_root,
uint8_t generator_root_gap,
size_t num_roots);
/* correct_reed_solomon_encode uses the rs instance to encode
* parity information onto a block of data. msg_length should be
* no more than the payload size for one block e.g. no more
* than 223 for a (255, 223) code. Shorter blocks will be encoded
* with virtual padding where the padding is not emitted.
*
* encoded should be at least msg_length + parity length bytes long
*
* It is allowable for msg and encoded to be the same pointer. In
* that case, the parity bytes will be written after the msg bytes
* end.
*
* This function returns the number of bytes written to encoded.
*/
ssize_t correct_reed_solomon_encode(correct_reed_solomon *rs, const uint8_t *msg, size_t msg_length,
uint8_t *encoded);
/* correct_reed_solomon_decode uses the rs instance to decode
* a payload from a block containing payload and parity bytes.
* This function can recover in spite of some bytes being corrupted.
*
* In most cases, if the block is too corrupted, this function
* will return -1 and not perform decoding. It is possible but
* unlikely that the payload written to msg will contain
* errors when this function returns a positive value.
*
* msg should be long enough to contain a decoded payload for
* this encoded block.
*
* This function returns a positive number of bytes written to msg
* if it has decoded or -1 if it has encountered an error.
*/
ssize_t correct_reed_solomon_decode(correct_reed_solomon *rs, const uint8_t *encoded,
size_t encoded_length, uint8_t *msg);
/* correct_reed_solomon_decode_with_erasures uses the rs
* instance to decode a payload from a block containing payload
* and parity bytes. Additionally, the user can provide the
* indices of bytes which have been suspected to be corrupted.
* This erasure information is typically provided by a demodulating
* or receiving device. This function can recover with
* some additional errors on top of the erasures.
*
* In order to successfully decode, the quantity
* (num_erasures + 2*num_errors) must be less than
* num_roots.
*
* erasure_locations shold contain erasure_length items.
* erasure_length should not exceed the number of parity
* bytes encoded into this block.
*
* In most cases, if the block is too corrupted, this function
* will return -1 and not perform decoding. It is possible but
* unlikely that the payload written to msg will contain
* errors when this function returns a positive value.
*
* msg should be long enough to contain a decoded payload for
* this encoded block.
*
* This function returns a positive number of bytes written to msg
* if it has decoded or -1 if it has encountered an error.
*/
ssize_t correct_reed_solomon_decode_with_erasures(correct_reed_solomon *rs, const uint8_t *encoded,
size_t encoded_length,
const uint8_t *erasure_locations,
size_t erasure_length, uint8_t *msg);
/* correct_reed_solomon_destroy releases the resources
* associated with rs. This pointer should not be
* used for any functions after this call.
*/
void correct_reed_solomon_destroy(correct_reed_solomon *rs);
#endif

View File

@ -0,0 +1,28 @@
#ifndef CORRECT_CONVOLUTIONAL
#define CORRECT_CONVOLUTIONAL
#include <stdint.h>
#include <stdbool.h>
#include <stdlib.h>
#include <stdio.h>
#include <stddef.h>
#include <string.h>
#include <limits.h>
#include <assert.h>
#include "correct.h"
#include "correct/portable.h"
typedef unsigned int shift_register_t;
typedef uint16_t polynomial_t;
typedef uint64_t path_t;
typedef uint8_t soft_t;
static const soft_t soft_max = UINT8_MAX;
typedef uint16_t distance_t;
static const distance_t distance_max = UINT16_MAX;
typedef enum {
CORRECT_SOFT_LINEAR,
CORRECT_SOFT_QUADRATIC,
} soft_measurement_t;
#endif

View File

@ -0,0 +1,44 @@
#ifndef CORRECT_CONVOLUTIONAL_BIT
#define CORRECT_CONVOLUTIONAL_BIT
#include "correct/convolutional.h"
typedef struct {
uint8_t current_byte;
unsigned int current_byte_len;
uint8_t *bytes;
size_t byte_index;
size_t len;
} bit_writer_t;
bit_writer_t *bit_writer_create(uint8_t *bytes, size_t len);
void bit_writer_reconfigure(bit_writer_t *w, uint8_t *bytes, size_t len);
void bit_writer_destroy(bit_writer_t *w);
void bit_writer_write(bit_writer_t *w, uint8_t val, unsigned int n);
void bit_writer_write_1(bit_writer_t *w, uint8_t val);
void bit_writer_write_bitlist_reversed(bit_writer_t *w, uint8_t *l, size_t len);
void bit_writer_flush_byte(bit_writer_t *w);
size_t bit_writer_length(bit_writer_t *w);
typedef struct {
uint8_t current_byte;
size_t byte_index;
size_t len;
size_t current_byte_len;
const uint8_t *bytes;
} bit_reader_t;
bit_reader_t *bit_reader_create(const uint8_t *bytes, size_t len);
void bit_reader_reconfigure(bit_reader_t *r, const uint8_t *bytes, size_t len);
void bit_reader_destroy(bit_reader_t *r);
uint8_t bit_reader_read(bit_reader_t *r, unsigned int n);
#endif

View File

@ -0,0 +1,40 @@
#ifndef CORRECT_CONVOLUTIONAL_H
#define CORRECT_CONVOLUTIONAL_H
#include "correct/convolutional.h"
#include "correct/convolutional/bit.h"
#include "correct/convolutional/metric.h"
#include "correct/convolutional/lookup.h"
#include "correct/convolutional/history_buffer.h"
#include "correct/convolutional/error_buffer.h"
struct correct_convolutional {
const unsigned int *table; // size 2**order
size_t rate; // e.g. 2, 3...
size_t order; // e.g. 7, 9...
unsigned int numstates; // 2**order
bit_writer_t *bit_writer;
bit_reader_t *bit_reader;
bool has_init_decode;
distance_t *distances;
pair_lookup_t pair_lookup;
soft_measurement_t soft_measurement;
history_buffer *history_buffer;
error_buffer_t *errors;
};
correct_convolutional *_correct_convolutional_init(correct_convolutional *conv,
size_t rate, size_t order,
const polynomial_t *poly);
void _correct_convolutional_teardown(correct_convolutional *conv);
// portable versions
void _convolutional_decode_init(correct_convolutional *conv, unsigned int min_traceback, unsigned int traceback_length, unsigned int renormalize_interval);
void convolutional_decode_warmup(correct_convolutional *conv, unsigned int sets,
const uint8_t *soft);
void convolutional_decode_inner(correct_convolutional *conv, unsigned int sets,
const uint8_t *soft);
void convolutional_decode_tail(correct_convolutional *conv, unsigned int sets,
const uint8_t *soft);
#endif

View File

@ -0,0 +1,15 @@
#include "correct/convolutional.h"
typedef struct {
unsigned int index;
distance_t *errors[2];
unsigned int num_states;
const distance_t *read_errors;
distance_t *write_errors;
} error_buffer_t;
error_buffer_t *error_buffer_create(unsigned int num_states);
void error_buffer_destroy(error_buffer_t *buf);
void error_buffer_reset(error_buffer_t *buf);
void error_buffer_swap(error_buffer_t *buf);

View File

@ -0,0 +1,59 @@
#include "correct/convolutional.h"
#include "correct/convolutional/bit.h"
// ring buffer of path histories
// generates output bits after accumulating sufficient history
typedef struct {
// history entries must be at least this old to be decoded
const unsigned int min_traceback_length;
// we'll decode entries in bursts. this tells us the length of the burst
const unsigned int traceback_group_length;
// we will store a total of cap entries. equal to min_traceback_length +
// traceback_group_length
const unsigned int cap;
// how many states in the shift register? this is one of the dimensions of
// history table
const unsigned int num_states;
// what's the high order bit of the shift register?
const shift_register_t highbit;
// history is a compact history representation for every shift register
// state,
// one bit per time slice
uint8_t **history;
// which slice are we writing next?
unsigned int index;
// how many valid entries are there?
unsigned int len;
// temporary store of fetched bits
uint8_t *fetched;
// how often should we renormalize?
unsigned int renormalize_interval;
unsigned int renormalize_counter;
} history_buffer;
history_buffer *history_buffer_create(unsigned int min_traceback_length,
unsigned int traceback_group_length,
unsigned int renormalize_interval,
unsigned int num_states,
shift_register_t highbit);
void history_buffer_destroy(history_buffer *buf);
void history_buffer_reset(history_buffer *buf);
void history_buffer_step(history_buffer *buf);
uint8_t *history_buffer_get_slice(history_buffer *buf);
shift_register_t history_buffer_search(history_buffer *buf,
const distance_t *distances,
unsigned int search_every);
void history_buffer_traceback(history_buffer *buf, shift_register_t bestpath,
unsigned int min_traceback_length,
bit_writer_t *output);
void history_buffer_process_skip(history_buffer *buf, distance_t *distances,
bit_writer_t *output, unsigned int skip);
void history_buffer_process(history_buffer *buf, distance_t *distances,
bit_writer_t *output);
void history_buffer_flush(history_buffer *buf, bit_writer_t *output);

View File

@ -0,0 +1,27 @@
#ifndef CORRECT_CONVOLUTIONAL_LOOKUP
#define CORRECT_CONVOLUTIONAL_LOOKUP
#include "correct/convolutional.h"
typedef unsigned int distance_pair_key_t;
typedef uint32_t output_pair_t;
typedef uint32_t distance_pair_t;
typedef struct {
distance_pair_key_t *keys;
output_pair_t *outputs;
output_pair_t output_mask;
unsigned int output_width;
size_t outputs_len;
distance_pair_t *distances;
} pair_lookup_t;
void fill_table(unsigned int order,
unsigned int rate,
const polynomial_t *poly,
unsigned int *table);
pair_lookup_t pair_lookup_create(unsigned int rate,
unsigned int order,
const unsigned int *table);
void pair_lookup_destroy(pair_lookup_t pairs);
void pair_lookup_fill_distance(pair_lookup_t pairs, distance_t *distances);
#endif

View File

@ -0,0 +1,20 @@
#include "correct/convolutional.h"
// measure the hamming distance of two bit strings
// implemented as population count of x XOR y
static inline distance_t metric_distance(unsigned int x, unsigned int y) {
return popcount(x ^ y);
}
static inline distance_t metric_soft_distance_linear(unsigned int hard_x, const uint8_t *soft_y, size_t len) {
distance_t dist = 0;
for (unsigned int i = 0; i < len; i++) {
unsigned int soft_x = ((int8_t)(0) - (hard_x & 1)) & 0xff;
hard_x >>= 1;
int d = soft_y[i] - soft_x;
dist += (d < 0) ? -d : d;
}
return dist;
}
distance_t metric_soft_distance_quadratic(unsigned int hard_x, const uint8_t *soft_y, size_t len);

View File

@ -0,0 +1,15 @@
#include "correct/convolutional/convolutional.h"
#include "correct/convolutional/sse/lookup.h"
// BIG HEAPING TODO sort out the include mess
#include "correct-sse.h"
#ifdef _MSC_VER
#include <intrin.h>
#else
#include <x86intrin.h>
#endif
struct correct_convolutional_sse {
correct_convolutional base_conv;
oct_lookup_t oct_lookup;
};

View File

@ -0,0 +1,65 @@
#include "correct/convolutional/lookup.h"
#ifdef _MSC_VER
#include <intrin.h>
#else
#include <x86intrin.h>
#endif
typedef unsigned int distance_quad_key_t;
typedef unsigned int output_quad_t;
typedef uint64_t distance_quad_t;
typedef struct {
distance_quad_key_t *keys;
output_quad_t *outputs;
output_quad_t output_mask;
unsigned int output_width;
size_t outputs_len;
distance_quad_t *distances;
} quad_lookup_t;
typedef uint16_t distance_oct_key_t;
typedef uint64_t output_oct_t;
typedef uint64_t distance_oct_t;
typedef struct {
distance_oct_key_t *keys;
output_oct_t *outputs;
output_oct_t output_mask;
unsigned int output_width;
size_t outputs_len;
distance_oct_t *distances;
} oct_lookup_t;
quad_lookup_t quad_lookup_create(unsigned int rate,
unsigned int order,
const unsigned int *table);
void quad_lookup_destroy(quad_lookup_t quads);
void quad_lookup_fill_distance(quad_lookup_t quads, distance_t *distances);
distance_oct_key_t oct_lookup_find_key(output_oct_t *outputs, output_oct_t out, size_t num_keys);
oct_lookup_t oct_lookup_create(unsigned int rate,
unsigned int order,
const unsigned int *table);
void oct_lookup_destroy(oct_lookup_t octs);
static inline void oct_lookup_fill_distance(oct_lookup_t octs, distance_t *distances) {
distance_pair_t *pairs = (distance_pair_t*)octs.distances;
for (unsigned int i = 1; i < octs.outputs_len; i += 1) {
output_oct_t concat_out = octs.outputs[i];
unsigned int i_0 = concat_out & 0xff;
unsigned int i_1 = (concat_out >> 8) & 0xff;
unsigned int i_2 = (concat_out >> 16) & 0xff;
unsigned int i_3 = (concat_out >> 24) & 0xff;
pairs[i*4 + 1] = distances[i_3] << 16 | distances[i_2];
pairs[i*4 + 0] = distances[i_1] << 16 | distances[i_0];
concat_out >>= 32;
unsigned int i_4 = concat_out & 0xff;
unsigned int i_5 = (concat_out >> 8) & 0xff;
unsigned int i_6 = (concat_out >> 16) & 0xff;
unsigned int i_7 = (concat_out >> 24) & 0xff;
pairs[i*4 + 3] = distances[i_7] << 16 | distances[i_6];
pairs[i*4 + 2] = distances[i_5] << 16 | distances[i_4];
}
}

View File

@ -0,0 +1,20 @@
#ifdef __GNUC__
#define HAVE_BUILTINS
#endif
#ifdef HAVE_BUILTINS
#define popcount __builtin_popcount
#define prefetch __builtin_prefetch
#else
static inline int popcount(int x) {
/* taken from the helpful http://graphics.stanford.edu/~seander/bithacks.html#CountBitsSetParallel */
x = x - ((x >> 1) & 0x55555555);
x = (x & 0x33333333) + ((x >> 2) & 0x33333333);
return ((x + (x >> 4) & 0x0f0f0f0f) * 0x01010101) >> 24;
}
static inline void prefetch(void *x) {}
#endif

View File

@ -0,0 +1,76 @@
#ifndef CORRECT_REED_SOLOMON
#define CORRECT_REED_SOLOMON
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <stdbool.h>
#include <time.h>
#include <stdint.h>
#include "correct.h"
#include "correct/portable.h"
// an element in GF(2^8)
typedef uint8_t field_element_t;
// a power of the primitive element alpha
typedef uint8_t field_logarithm_t;
// give us some bits of headroom to do arithmetic
// variables of this type aren't really in any proper space
typedef uint16_t field_operation_t;
// generated by find_poly
typedef struct {
const field_element_t *exp;
const field_logarithm_t *log;
} field_t;
typedef struct {
field_element_t *coeff;
unsigned int order;
} polynomial_t;
struct correct_reed_solomon {
size_t block_length;
size_t message_length;
size_t min_distance;
field_logarithm_t first_consecutive_root;
field_logarithm_t generator_root_gap;
field_t field;
polynomial_t generator;
field_element_t *generator_roots;
field_logarithm_t **generator_root_exp;
polynomial_t encoded_polynomial;
polynomial_t encoded_remainder;
field_element_t *syndromes;
field_element_t *modified_syndromes;
polynomial_t received_polynomial;
polynomial_t error_locator;
polynomial_t error_locator_log;
polynomial_t erasure_locator;
field_element_t *error_roots;
field_element_t *error_vals;
field_logarithm_t *error_locations;
field_logarithm_t **element_exp;
// scratch
// (do no allocations at steady state)
// used during find_error_locator
polynomial_t last_error_locator;
// used during error value search
polynomial_t error_evaluator;
polynomial_t error_locator_derivative;
polynomial_t init_from_roots_scratch[2];
bool has_init_decode;
};
#endif

View File

@ -0,0 +1,3 @@
#include "correct/reed-solomon.h"
#include "correct/reed-solomon/field.h"
#include "correct/reed-solomon/polynomial.h"

View File

@ -0,0 +1,3 @@
#include "correct/reed-solomon.h"
#include "correct/reed-solomon/field.h"
#include "correct/reed-solomon/polynomial.h"

View File

@ -0,0 +1,167 @@
#ifndef CORRECT_REED_SOLOMON_FIELD
#define CORRECT_REED_SOLOMON_FIELD
#include "correct/reed-solomon.h"
/*
field_t field_create(field_operation_t primitive_poly);
void field_destroy(field_t field);
field_element_t field_add(field_t field, field_element_t l, field_element_t r);
field_element_t field_sub(field_t field, field_element_t l, field_element_t r);
field_element_t field_sum(field_t field, field_element_t elem, unsigned int n);
field_element_t field_mul(field_t field, field_element_t l, field_element_t r);
field_element_t field_div(field_t field, field_element_t l, field_element_t r);
field_logarithm_t field_mul_log(field_t field, field_logarithm_t l, field_logarithm_t r);
field_logarithm_t field_div_log(field_t field, field_logarithm_t l, field_logarithm_t r);
field_element_t field_mul_log_element(field_t field, field_logarithm_t l, field_logarithm_t r);
field_element_t field_pow(field_t field, field_element_t elem, int pow);
*/
static inline field_element_t field_mul_log_element(field_t field, field_logarithm_t l, field_logarithm_t r) {
// like field_mul_log, but returns a field_element_t
// because we are doing lookup here, we can safely skip the wrapover check
field_operation_t res = (field_operation_t)l + (field_operation_t)r;
return field.exp[res];
}
static inline field_t field_create(field_operation_t primitive_poly) {
// in GF(2^8)
// log and exp
// bits are in GF(2), compute alpha^val in GF(2^8)
// exp should be of size 512 so that it can hold a "wraparound" which prevents some modulo ops
// log should be of size 256. no wraparound here, the indices into this table are field elements
field_element_t *exp = malloc(512 * sizeof(field_element_t));
field_logarithm_t *log = malloc(256 * sizeof(field_logarithm_t));
// assume alpha is a primitive element, p(x) (primitive_poly) irreducible in GF(2^8)
// addition is xor
// subtraction is addition (also xor)
// e.g. x^5 + x^4 + x^4 + x^2 + 1 = x^5 + x^2 + 1
// each row of exp contains the field element found by exponentiating
// alpha by the row index
// each row of log contains the coefficients of
// alpha^7 + alpha^6 + alpha^5 + alpha^4 + alpha^3 + alpha^2 + alpha + 1
// as 8 bits packed into one byte
field_operation_t element = 1;
exp[0] = (field_element_t)element;
log[0] = (field_logarithm_t)0; // really, it's undefined. we shouldn't ever access this
for (field_operation_t i = 1; i < 512; i++) {
element = element * 2;
element = (element > 255) ? (element ^ primitive_poly) : element;
exp[i] = (field_element_t)element;
if (i < 256) {
log[element] = (field_logarithm_t)i;
}
}
field_t field;
*(field_element_t **)&field.exp = exp;
*(field_logarithm_t **)&field.log = log;
return field;
}
static inline void field_destroy(field_t field) {
free(*(field_element_t **)&field.exp);
free(*(field_element_t **)&field.log);
}
static inline field_element_t field_add(field_t field, field_element_t l, field_element_t r) {
return l ^ r;
}
static inline field_element_t field_sub(field_t field, field_element_t l, field_element_t r) {
return l ^ r;
}
static inline field_element_t field_sum(field_t field, field_element_t elem, unsigned int n) {
// we'll do a closed-form expression of the sum, although we could also
// choose to call field_add n times
// since the sum is actually the bytewise XOR operator, this suggests two
// kinds of values: n odd, and n even
// if you sum once, you have coeff
// if you sum twice, you have coeff XOR coeff = 0
// if you sum thrice, you are back at coeff
// an even number of XORs puts you at 0
// an odd number of XORs puts you back at your value
// so, just throw away all the even n
return (n % 2) ? elem : 0;
}
static inline field_element_t field_mul(field_t field, field_element_t l, field_element_t r) {
if (l == 0 || r == 0) {
return 0;
}
// multiply two field elements by adding their logarithms.
// yep, get your slide rules out
field_operation_t res = (field_operation_t)field.log[l] + (field_operation_t)field.log[r];
// if coeff exceeds 255, we would normally have to wrap it back around
// alpha^255 = 1; alpha^256 = alpha^255 * alpha^1 = alpha^1
// however, we've constructed exponentiation table so that
// we can just directly lookup this result
// the result must be clamped to [0, 511]
// the greatest we can see at this step is alpha^255 * alpha^255
// = alpha^510
return field.exp[res];
}
static inline field_element_t field_div(field_t field, field_element_t l, field_element_t r) {
if (l == 0) {
return 0;
}
if (r == 0) {
// XXX ???
return 0;
}
// division as subtraction of logarithms
// if rcoeff is larger, then log[l] - log[r] wraps under
// so, instead, always add 255. in some cases, we'll wrap over, but
// that's ok because the exp table runs up to 511.
field_operation_t res = (field_operation_t)255 + (field_operation_t)field.log[l] - (field_operation_t)field.log[r];
return field.exp[res];
}
static inline field_logarithm_t field_mul_log(field_t field, field_logarithm_t l, field_logarithm_t r) {
// this function performs the equivalent of field_mul on two logarithms
// we save a little time by skipping the lookup step at the beginning
field_operation_t res = (field_operation_t)l + (field_operation_t)r;
// because we arent using the table, the value we return must be a valid logarithm
// which we have decided must live in [0, 255] (they are 8-bit values)
// ensuring this makes it so that multiple muls will not reach past the end of the
// exp table whenever we finally convert back to an element
if (res > 255) {
return (field_logarithm_t)(res - 255);
}
return (field_logarithm_t)res;
}
static inline field_logarithm_t field_div_log(field_t field, field_logarithm_t l, field_logarithm_t r) {
// like field_mul_log, this performs field_div without going through a field_element_t
field_operation_t res = (field_operation_t)255 + (field_operation_t)l - (field_operation_t)r;
if (res > 255) {
return (field_logarithm_t)(res - 255);
}
return (field_logarithm_t)res;
}
static inline field_element_t field_pow(field_t field, field_element_t elem, int pow) {
// take the logarithm, multiply, and then "exponentiate"
// n.b. the exp table only considers powers of alpha, the primitive element
// but here we have an arbitrary coeff
field_logarithm_t log = field.log[elem];
int res_log = log * pow;
int mod = res_log % 255;
if (mod < 0) {
mod += 255;
}
return field.exp[mod];
}
#endif

View File

@ -0,0 +1,14 @@
#include "correct/reed-solomon.h"
#include "correct/reed-solomon/field.h"
polynomial_t polynomial_create(unsigned int order);
void polynomial_destroy(polynomial_t polynomial);
void polynomial_mul(field_t field, polynomial_t l, polynomial_t r, polynomial_t res);
void polynomial_mod(field_t field, polynomial_t dividend, polynomial_t divisor, polynomial_t mod);
void polynomial_formal_derivative(field_t field, polynomial_t poly, polynomial_t der);
field_element_t polynomial_eval(field_t field, polynomial_t poly, field_element_t val);
field_element_t polynomial_eval_lut(field_t field, polynomial_t poly, const field_logarithm_t *val_exp);
field_element_t polynomial_eval_log_lut(field_t field, polynomial_t poly_log, const field_logarithm_t *val_exp);
void polynomial_build_exp_lut(field_t field, field_element_t val, unsigned int order, field_logarithm_t *val_exp);
polynomial_t polynomial_init_from_roots(field_t field, unsigned int nroots, field_element_t *roots, polynomial_t poly, polynomial_t *scratch);
polynomial_t polynomial_create_from_roots(field_t field, unsigned int nroots, field_element_t *roots);

View File

@ -0,0 +1,3 @@
#include "correct/reed-solomon.h"
#include "correct/reed-solomon/field.h"
#include "correct/reed-solomon/polynomial.h"

View File

@ -0,0 +1,8 @@
#include "correct/util/error-sim.h"
#include <fec.h>
void conv_fec27_decode(void *conv_v, uint8_t *soft, size_t soft_len, uint8_t *msg);
void conv_fec29_decode(void *conv_v, uint8_t *soft, size_t soft_len, uint8_t *msg);
void conv_fec39_decode(void *conv_v, uint8_t *soft, size_t soft_len, uint8_t *msg);
void conv_fec615_decode(void *conv_v, uint8_t *soft, size_t soft_len, uint8_t *msg);

View File

@ -0,0 +1,7 @@
#include "correct/util/error-sim.h"
#include "fec_shim.h"
ssize_t conv_shim27_decode(void *conv_v, uint8_t *soft, size_t soft_len, uint8_t *msg);
ssize_t conv_shim29_decode(void *conv_v, uint8_t *soft, size_t soft_len, uint8_t *msg);
ssize_t conv_shim39_decode(void *conv_v, uint8_t *soft, size_t soft_len, uint8_t *msg);
ssize_t conv_shim615_decode(void *conv_v, uint8_t *soft, size_t soft_len, uint8_t *msg);

View File

@ -0,0 +1,7 @@
#include "correct/util/error-sim.h"
#include "correct-sse.h"
size_t conv_correct_sse_enclen(void *conv_v, size_t msg_len);
void conv_correct_sse_encode(void *conv_v, uint8_t *msg, size_t msg_len, uint8_t *encoded);
ssize_t conv_correct_sse_decode(void *conv_v, uint8_t *soft, size_t soft_len, uint8_t *msg);

View File

@ -0,0 +1,47 @@
#include <stdbool.h>
#include <math.h>
#include <string.h>
#include <stdlib.h>
#include <float.h>
#include <stdio.h>
#include "correct.h"
#include "correct/portable.h"
size_t distance(uint8_t *a, uint8_t *b, size_t len);
void gaussian(double *res, size_t n_res, double sigma);
void encode_bpsk(uint8_t *msg, double *voltages, size_t n_syms, double bpsk_voltage);
void byte2bit(uint8_t *bytes, uint8_t *bits, size_t n_bits);
void decode_bpsk(uint8_t *soft, uint8_t *msg, size_t n_syms);
void decode_bpsk_soft(double *voltages, uint8_t *soft, size_t n_syms, double bpsk_voltage);
double log2amp(double l);
double amp2log(double a);
double sigma_for_eb_n0(double eb_n0, double bpsk_bit_energy);
void build_white_noise(double *noise, size_t n_syms, double eb_n0, double bpsk_bit_energy);
void add_white_noise(double *signal, double *noise, size_t n_syms);
typedef struct {
uint8_t *msg_out;
size_t msg_len;
uint8_t *encoded;
double *v;
double *corrupted;
uint8_t *soft;
double *noise;
size_t enclen;
size_t enclen_bytes;
void (*encode)(void *, uint8_t *msg, size_t msg_len, uint8_t *encoded);
void *encoder;
ssize_t (*decode)(void *, uint8_t *soft, size_t soft_len, uint8_t *msg);
void *decoder;
} conv_testbench;
conv_testbench *resize_conv_testbench(conv_testbench *scratch, size_t (*enclen)(void *, size_t), void *enc, size_t msg_len);
void free_scratch(conv_testbench *scratch);
int test_conv_noise(conv_testbench *scratch, uint8_t *msg, size_t n_bytes,
double bpsk_voltage);
size_t conv_correct_enclen(void *conv_v, size_t msg_len);
void conv_correct_encode(void *conv_v, uint8_t *msg, size_t msg_len, uint8_t *encoded);
ssize_t conv_correct_decode(void *conv_v, uint8_t *soft, size_t soft_len, uint8_t *msg);

View File

@ -0,0 +1,74 @@
#ifndef CORRECT_FEC_H
#define CORRECT_FEC_H
// libcorrect's libfec shim header
// this is a partial implementation of libfec
// header signatures derived from found usages of libfec -- some things may be different
#include <correct.h>
// Reed-Solomon
void *init_rs_char(int symbol_size, int primitive_polynomial, int first_consecutive_root,
int root_gap, int number_roots, unsigned int pad);
void free_rs_char(void *rs);
void encode_rs_char(void *rs, const unsigned char *msg, unsigned char *parity);
void decode_rs_char(void *rs, unsigned char *block, int *erasure_locations, int num_erasures);
// Convolutional Codes
// Polynomials
// These have been determined via find_conv_libfec_poly.c
// We could just make up new ones, but we use libfec's here so that
// codes encoded by this library can be decoded by the original libfec
// and vice-versa
#define V27POLYA 0155
#define V27POLYB 0117
#define V29POLYA 0657
#define V29POLYB 0435
#define V39POLYA 0755
#define V39POLYB 0633
#define V39POLYC 0447
#define V615POLYA 042631
#define V615POLYB 047245
#define V615POLYC 056507
#define V615POLYD 073363
#define V615POLYE 077267
#define V615POLYF 064537
// Convolutional Methods
void *create_viterbi27(int num_decoded_bits);
int init_viterbi27(void *vit, int _mystery);
int update_viterbi27_blk(void *vit, unsigned char *encoded_soft, int n_encoded_groups);
int chainback_viterbi27(void *vit, unsigned char *decoded, unsigned int n_decoded_bits, unsigned int _mystery);
void delete_viterbi27(void *vit);
void *create_viterbi29(int num_decoded_bits);
int init_viterbi29(void *vit, int _mystery);
int update_viterbi29_blk(void *vit, unsigned char *encoded_soft, int n_encoded_groups);
int chainback_viterbi29(void *vit, unsigned char *decoded, unsigned int n_decoded_bits, unsigned int _mystery);
void delete_viterbi29(void *vit);
void *create_viterbi39(int num_decoded_bits);
int init_viterbi39(void *vit, int _mystery);
int update_viterbi39_blk(void *vit, unsigned char *encoded_soft, int n_encoded_groups);
int chainback_viterbi39(void *vit, unsigned char *decoded, unsigned int n_decoded_bits, unsigned int _mystery);
void delete_viterbi39(void *vit);
void *create_viterbi615(int num_decoded_bits);
int init_viterbi615(void *vit, int _mystery);
int update_viterbi615_blk(void *vit, unsigned char *encoded_soft, int n_encoded_groups);
int chainback_viterbi615(void *vit, unsigned char *decoded, unsigned int n_decoded_bits, unsigned int _mystery);
void delete_viterbi615(void *vit);
// Misc other
static inline int parity(unsigned int x) {
/* http://graphics.stanford.edu/~seander/bithacks.html#ParityParallel */
x ^= x >> 16;
x ^= x >> 8;
x ^= x >> 4;
x &= 0xf;
return (0x6996 >> x) & 1;
}
#endif

View File

@ -0,0 +1,2 @@
add_subdirectory(convolutional)
add_subdirectory(reed-solomon)

View File

@ -0,0 +1,5 @@
set(SRCFILES bit.c metric.c history_buffer.c error_buffer.c lookup.c convolutional.c encode.c decode.c)
add_library(correct-convolutional OBJECT ${SRCFILES})
if(HAVE_SSE)
add_subdirectory(sse)
endif()

View File

@ -0,0 +1,232 @@
#include "correct/convolutional/bit.h"
bit_writer_t *bit_writer_create(uint8_t *bytes, size_t len) {
bit_writer_t *w = calloc(1, sizeof(bit_writer_t));
if (bytes) {
bit_writer_reconfigure(w, bytes, len);
}
return w;
}
void bit_writer_reconfigure(bit_writer_t *w, uint8_t *bytes, size_t len) {
w->bytes = bytes;
w->len = len;
w->current_byte = 0;
w->current_byte_len = 0;
w->byte_index = 0;
}
void bit_writer_destroy(bit_writer_t *w) {
free(w);
}
void bit_writer_write(bit_writer_t *w, uint8_t val, unsigned int n) {
for (size_t j = 0; j < n; j++) {
bit_writer_write_1(w, val);
val >>= 1;
}
}
void bit_writer_write_1(bit_writer_t *w, uint8_t val) {
w->current_byte |= val & 1;
w->current_byte_len++;
if (w->current_byte_len == 8) {
// 8 bits in a byte -- move to the next byte
w->bytes[w->byte_index] = w->current_byte;
w->byte_index++;
w->current_byte_len = 0;
w->current_byte = 0;
} else {
w->current_byte <<= 1;
}
}
void bit_writer_write_bitlist(bit_writer_t *w, uint8_t *l, size_t len) {
// first close the current byte
// we might have been given too few elements to do that. be careful.
size_t close_len = 8 - w->current_byte_len;
close_len = (close_len < len) ? close_len : len;
uint16_t b = w->current_byte;
for (ptrdiff_t i = 0; i < close_len; i++) {
b |= l[i];
b <<= 1;
}
l += close_len;
len -= close_len;
uint8_t *bytes = w->bytes;
size_t byte_index = w->byte_index;
if (w->current_byte_len + close_len == 8) {
b >>= 1;
bytes[byte_index] = b;
byte_index++;
} else {
w->current_byte = b;
w->current_byte_len += close_len;
return;
}
size_t full_bytes = len/8;
for (size_t i = 0; i < full_bytes; i++) {
bytes[byte_index] = l[0] << 7 | l[1] << 6 | l[2] << 5 |
l[3] << 4 | l[4] << 3 | l[5] << 2 |
l[6] << 1 | l[7];
byte_index += 1;
l += 8;
}
len -= 8*full_bytes;
b = 0;
for (ptrdiff_t i = 0; i < len; i++) {
b |= l[i];
b <<= 1;
}
w->current_byte = b;
w->byte_index = byte_index;
w->current_byte_len = len;
}
void bit_writer_write_bitlist_reversed(bit_writer_t *w, uint8_t *l, size_t len) {
l = l + len - 1;
uint8_t *bytes = w->bytes;
size_t byte_index = w->byte_index;
uint16_t b;
if (w->current_byte_len != 0) {
size_t close_len = 8 - w->current_byte_len;
close_len = (close_len < len) ? close_len : len;
b = w->current_byte;
for (ptrdiff_t i = 0; i < close_len; i++) {
b |= *l;
b <<= 1;
l--;
}
len -= close_len;
if (w->current_byte_len + close_len == 8) {
b >>= 1;
bytes[byte_index] = b;
byte_index++;
} else {
w->current_byte = b;
w->current_byte_len += close_len;
return;
}
}
size_t full_bytes = len/8;
for (size_t i = 0; i < full_bytes; i++) {
bytes[byte_index] = l[0] << 7 | l[-1] << 6 | l[-2] << 5 |
l[-3] << 4 | l[-4] << 3 | l[-5] << 2 |
l[-6] << 1 | l[-7];
byte_index += 1;
l -= 8;
}
len -= 8*full_bytes;
b = 0;
for (ptrdiff_t i = 0; i < len; i++) {
b |= *l;
b <<= 1;
l--;
}
w->current_byte = (uint8_t)b;
w->byte_index = byte_index;
w->current_byte_len = len;
}
void bit_writer_flush_byte(bit_writer_t *w) {
if (w->current_byte_len != 0) {
w->current_byte <<= (8 - w->current_byte_len);
w->bytes[w->byte_index] = w->current_byte;
w->byte_index++;
w->current_byte_len = 0;
}
}
size_t bit_writer_length(bit_writer_t *w) {
return w->byte_index;
}
uint8_t reverse_byte(uint8_t b) {
return (b & 0x80) >> 7 | (b & 0x40) >> 5 | (b & 0x20) >> 3 |
(b & 0x10) >> 1 | (b & 0x08) << 1 | (b & 0x04) << 3 |
(b & 0x02) << 5 | (b & 0x01) << 7;
}
static uint8_t reverse_table[256];
void create_reverse_table() {
for (uint16_t i = 0; i < 256; i++) {
reverse_table[i] = reverse_byte(i);
}
}
bit_reader_t *bit_reader_create(const uint8_t *bytes, size_t len) {
bit_reader_t *r = calloc(1, sizeof(bit_reader_t));
static bool reverse_table_created = false;
if (!reverse_table_created) {
create_reverse_table();
reverse_table_created = true;
}
if (bytes) {
bit_reader_reconfigure(r, bytes, len);
}
return r;
}
void bit_reader_reconfigure(bit_reader_t *r, const uint8_t *bytes, size_t len) {
r->bytes = bytes;
r->len = len;
r->current_byte_len = 8;
r->current_byte = bytes[0];
r->byte_index = 0;
}
void bit_reader_destroy(bit_reader_t *r) {
free(r);
}
uint8_t bit_reader_read(bit_reader_t *r, unsigned int n) {
unsigned int read = 0;
unsigned int n_copy = n;
if (r->current_byte_len < n) {
read = r->current_byte & ((1 << r->current_byte_len) - 1);
r->byte_index++;
r->current_byte = r->bytes[r->byte_index];
n -= r->current_byte_len;
r->current_byte_len = 8;
read <<= n;
}
uint8_t copy_mask = (1 << n) - 1;
copy_mask <<= (r->current_byte_len - n);
read |= (r->current_byte & copy_mask) >> (r->current_byte_len - n);
r->current_byte_len -= n;
return reverse_table[read] >> (8 - n_copy);
}

View File

@ -0,0 +1,59 @@
#include "correct/convolutional/convolutional.h"
// https://www.youtube.com/watch?v=b3_lVSrPB6w
correct_convolutional *_correct_convolutional_init(correct_convolutional *conv,
size_t rate, size_t order,
const polynomial_t *poly) {
if (order > 8 * sizeof(shift_register_t)) {
// XXX turn this into an error code
// printf("order must be smaller than 8 * sizeof(shift_register_t)\n");
return NULL;
}
if (rate < 2) {
// XXX turn this into an error code
// printf("rate must be 2 or greater\n");
return NULL;
}
conv->order = order;
conv->rate = rate;
conv->numstates = 1 << order;
unsigned int *table = malloc(sizeof(unsigned int) * (1 << order));
fill_table(conv->rate, conv->order, poly, table);
*(unsigned int **)&conv->table = table;
conv->bit_writer = bit_writer_create(NULL, 0);
conv->bit_reader = bit_reader_create(NULL, 0);
conv->has_init_decode = false;
return conv;
}
correct_convolutional *correct_convolutional_create(size_t rate, size_t order,
const polynomial_t *poly) {
correct_convolutional *conv = malloc(sizeof(correct_convolutional));
correct_convolutional *init_conv = _correct_convolutional_init(conv, rate, order, poly);
if (!init_conv) {
free(conv);
}
return init_conv;
}
void _correct_convolutional_teardown(correct_convolutional *conv) {
free(*(unsigned int **)&conv->table);
bit_writer_destroy(conv->bit_writer);
bit_reader_destroy(conv->bit_reader);
if (conv->has_init_decode) {
pair_lookup_destroy(conv->pair_lookup);
history_buffer_destroy(conv->history_buffer);
error_buffer_destroy(conv->errors);
free(conv->distances);
}
}
void correct_convolutional_destroy(correct_convolutional *conv) {
_correct_convolutional_teardown(conv);
free(conv);
}

View File

@ -0,0 +1,321 @@
#include "correct/convolutional/convolutional.h"
void conv_decode_print_iter(correct_convolutional *conv, unsigned int iter,
unsigned int winner_index) {
if (iter < 2220) {
return;
}
printf("iteration: %d\n", iter);
distance_t *errors = conv->errors->write_errors;
printf("errors:\n");
for (shift_register_t i = 0; i < conv->numstates / 2; i++) {
printf("%2d: %d\n", i, errors[i]);
}
printf("\n");
printf("history:\n");
for (shift_register_t i = 0; i < conv->numstates / 2; i++) {
printf("%2d: ", i);
for (unsigned int j = 0; j <= winner_index; j++) {
printf("%d", conv->history_buffer->history[j][i] ? 1 : 0);
}
printf("\n");
}
printf("\n");
}
void convolutional_decode_warmup(correct_convolutional *conv, unsigned int sets,
const uint8_t *soft) {
// first phase: load shiftregister up from 0 (order goes from 1 to conv->order)
// we are building up error metrics for the first order bits
for (unsigned int i = 0; i < conv->order - 1 && i < sets; i++) {
// peel off rate bits from encoded to recover the same `out` as in the encoding process
// the difference being that this `out` will have the channel noise/errors applied
unsigned int out;
if (!soft) {
out = bit_reader_read(conv->bit_reader, conv->rate);
}
const distance_t *read_errors = conv->errors->read_errors;
distance_t *write_errors = conv->errors->write_errors;
// walk all of the state we have so far
for (size_t j = 0; j < (1 << (i + 1)); j += 1) {
unsigned int last = j >> 1;
distance_t dist;
if (soft) {
if (conv->soft_measurement == CORRECT_SOFT_LINEAR) {
dist = metric_soft_distance_linear(conv->table[j], soft + i * conv->rate,
conv->rate);
} else {
dist = metric_soft_distance_quadratic(conv->table[j], soft + i * conv->rate,
conv->rate);
}
} else {
dist = metric_distance(conv->table[j], out);
}
write_errors[j] = dist + read_errors[last];
}
error_buffer_swap(conv->errors);
}
}
void convolutional_decode_inner(correct_convolutional *conv, unsigned int sets,
const uint8_t *soft) {
shift_register_t highbit = 1 << (conv->order - 1);
for (unsigned int i = conv->order - 1; i < (sets - conv->order + 1); i++) {
distance_t *distances = conv->distances;
// lasterrors are the aggregate bit errors for the states of shiftregister for the previous
// time slice
if (soft) {
if (conv->soft_measurement == CORRECT_SOFT_LINEAR) {
for (unsigned int j = 0; j < 1 << (conv->rate); j++) {
distances[j] =
metric_soft_distance_linear(j, soft + i * conv->rate, conv->rate);
}
} else {
for (unsigned int j = 0; j < 1 << (conv->rate); j++) {
distances[j] =
metric_soft_distance_quadratic(j, soft + i * conv->rate, conv->rate);
}
}
} else {
unsigned int out = bit_reader_read(conv->bit_reader, conv->rate);
for (unsigned int i = 0; i < 1 << (conv->rate); i++) {
distances[i] = metric_distance(i, out);
}
}
pair_lookup_t pair_lookup = conv->pair_lookup;
pair_lookup_fill_distance(pair_lookup, distances);
// a mask to get the high order bit from the shift register
unsigned int num_iter = highbit << 1;
const distance_t *read_errors = conv->errors->read_errors;
// aggregate bit errors for this time slice
distance_t *write_errors = conv->errors->write_errors;
uint8_t *history = history_buffer_get_slice(conv->history_buffer);
// walk through all states, ignoring oldest bit
// we will track a best register state (path) and the number of bit errors at that path at
// this time slice
// this loop considers two paths per iteration (high order bit set, clear)
// so, it only runs numstates/2 iterations
// we'll update the history for every state and find the path with the least aggregated bit
// errors
// now run the main loop
// we calculate 2 sets of 2 register states here (4 states per iter)
// this creates 2 sets which share a predecessor, and 2 sets which share a successor
//
// the first set definition is the two states that are the same except for the least order
// bit
// these two share a predecessor because their high n - 1 bits are the same (differ only by
// newest bit)
//
// the second set definition is the two states that are the same except for the high order
// bit
// these two share a successor because the oldest high order bit will be shifted out, and
// the other bits will be present in the successor
//
shift_register_t highbase = highbit >> 1;
for (shift_register_t low = 0, high = highbit, base = 0; high < num_iter;
low += 8, high += 8, base += 4) {
// shifted-right ancestors
// low and low_plus_one share low_past_error
// note that they are the same when shifted right by 1
// same goes for high and high_plus_one
for (shift_register_t offset = 0, base_offset = 0; base_offset < 4;
offset += 2, base_offset += 1) {
distance_pair_key_t low_key = pair_lookup.keys[base + base_offset];
distance_pair_key_t high_key = pair_lookup.keys[highbase + base + base_offset];
distance_pair_t low_concat_dist = pair_lookup.distances[low_key];
distance_pair_t high_concat_dist = pair_lookup.distances[high_key];
distance_t low_past_error = read_errors[base + base_offset];
distance_t high_past_error = read_errors[highbase + base + base_offset];
distance_t low_error = (low_concat_dist & 0xffff) + low_past_error;
distance_t high_error = (high_concat_dist & 0xffff) + high_past_error;
shift_register_t successor = low + offset;
distance_t error;
uint8_t history_mask;
if (low_error <= high_error) {
error = low_error;
history_mask = 0;
} else {
error = high_error;
history_mask = 1;
}
write_errors[successor] = error;
history[successor] = history_mask;
shift_register_t low_plus_one = low + offset + 1;
distance_t low_plus_one_error = (low_concat_dist >> 16) + low_past_error;
distance_t high_plus_one_error = (high_concat_dist >> 16) + high_past_error;
shift_register_t plus_one_successor = low_plus_one;
distance_t plus_one_error;
uint8_t plus_one_history_mask;
if (low_plus_one_error <= high_plus_one_error) {
plus_one_error = low_plus_one_error;
plus_one_history_mask = 0;
} else {
plus_one_error = high_plus_one_error;
plus_one_history_mask = 1;
}
write_errors[plus_one_successor] = plus_one_error;
history[plus_one_successor] = plus_one_history_mask;
}
}
history_buffer_process(conv->history_buffer, write_errors, conv->bit_writer);
error_buffer_swap(conv->errors);
}
}
void convolutional_decode_tail(correct_convolutional *conv, unsigned int sets,
const uint8_t *soft) {
// flush state registers
// now we only shift in 0s, skipping 1-successors
shift_register_t highbit = 1 << (conv->order - 1);
for (unsigned int i = sets - conv->order + 1; i < sets; i++) {
// lasterrors are the aggregate bit errors for the states of shiftregister for the previous
// time slice
const distance_t *read_errors = conv->errors->read_errors;
// aggregate bit errors for this time slice
distance_t *write_errors = conv->errors->write_errors;
uint8_t *history = history_buffer_get_slice(conv->history_buffer);
// calculate the distance from all output states to our sliced bits
distance_t *distances = conv->distances;
if (soft) {
if (conv->soft_measurement == CORRECT_SOFT_LINEAR) {
for (unsigned int j = 0; j < 1 << (conv->rate); j++) {
distances[j] =
metric_soft_distance_linear(j, soft + i * conv->rate, conv->rate);
}
} else {
for (unsigned int j = 0; j < 1 << (conv->rate); j++) {
distances[j] =
metric_soft_distance_quadratic(j, soft + i * conv->rate, conv->rate);
}
}
} else {
unsigned int out = bit_reader_read(conv->bit_reader, conv->rate);
for (unsigned int i = 0; i < 1 << (conv->rate); i++) {
distances[i] = metric_distance(i, out);
}
}
const unsigned int *table = conv->table;
// a mask to get the high order bit from the shift register
unsigned int num_iter = highbit << 1;
unsigned int skip = 1 << (conv->order - (sets - i));
unsigned int base_skip = skip >> 1;
shift_register_t highbase = highbit >> 1;
for (shift_register_t low = 0, high = highbit, base = 0; high < num_iter;
low += skip, high += skip, base += base_skip) {
unsigned int low_output = table[low];
unsigned int high_output = table[high];
distance_t low_dist = distances[low_output];
distance_t high_dist = distances[high_output];
distance_t low_past_error = read_errors[base];
distance_t high_past_error = read_errors[highbase + base];
distance_t low_error = low_dist + low_past_error;
distance_t high_error = high_dist + high_past_error;
shift_register_t successor = low;
distance_t error;
uint8_t history_mask;
if (low_error < high_error) {
error = low_error;
history_mask = 0;
} else {
error = high_error;
history_mask = 1;
}
write_errors[successor] = error;
history[successor] = history_mask;
}
history_buffer_process_skip(conv->history_buffer, write_errors, conv->bit_writer, skip);
error_buffer_swap(conv->errors);
}
}
void _convolutional_decode_init(correct_convolutional *conv, unsigned int min_traceback,
unsigned int traceback_length, unsigned int renormalize_interval) {
conv->has_init_decode = true;
conv->distances = calloc(1 << (conv->rate), sizeof(distance_t));
conv->pair_lookup = pair_lookup_create(conv->rate, conv->order, conv->table);
conv->soft_measurement = CORRECT_SOFT_LINEAR;
// we limit history to go back as far as 5 * the order of our polynomial
conv->history_buffer = history_buffer_create(min_traceback, traceback_length, renormalize_interval,
conv->numstates / 2, 1 << (conv->order - 1));
conv->errors = error_buffer_create(conv->numstates);
}
static ssize_t _convolutional_decode(correct_convolutional *conv, size_t num_encoded_bits,
size_t num_encoded_bytes, uint8_t *msg,
const soft_t *soft_encoded) {
if (!conv->has_init_decode) {
uint64_t max_error_per_input = conv->rate * soft_max;
unsigned int renormalize_interval = distance_max / max_error_per_input;
_convolutional_decode_init(conv, 5 * conv->order, 15 * conv->order, renormalize_interval);
}
size_t sets = num_encoded_bits / conv->rate;
// XXX fix this vvvvvv
size_t decoded_len_bytes = num_encoded_bytes;
bit_writer_reconfigure(conv->bit_writer, msg, decoded_len_bytes);
error_buffer_reset(conv->errors);
history_buffer_reset(conv->history_buffer);
// no outputs are generated during warmup
convolutional_decode_warmup(conv, sets, soft_encoded);
convolutional_decode_inner(conv, sets, soft_encoded);
convolutional_decode_tail(conv, sets, soft_encoded);
history_buffer_flush(conv->history_buffer, conv->bit_writer);
return bit_writer_length(conv->bit_writer);
}
// perform viterbi decoding
// hard decoder
ssize_t correct_convolutional_decode(correct_convolutional *conv, const uint8_t *encoded,
size_t num_encoded_bits, uint8_t *msg) {
if (num_encoded_bits % conv->rate) {
// XXX turn this into an error code
// printf("encoded length of message must be a multiple of rate\n");
return -1;
}
size_t num_encoded_bytes =
(num_encoded_bits % 8) ? (num_encoded_bits / 8 + 1) : (num_encoded_bits / 8);
bit_reader_reconfigure(conv->bit_reader, encoded, num_encoded_bytes);
return _convolutional_decode(conv, num_encoded_bits, num_encoded_bytes, msg, NULL);
}
ssize_t correct_convolutional_decode_soft(correct_convolutional *conv, const soft_t *encoded,
size_t num_encoded_bits, uint8_t *msg) {
if (num_encoded_bits % conv->rate) {
// XXX turn this into an error code
// printf("encoded length of message must be a multiple of rate\n");
return -1;
}
size_t num_encoded_bytes =
(num_encoded_bits % 8) ? (num_encoded_bits / 8 + 1) : (num_encoded_bits / 8);
return _convolutional_decode(conv, num_encoded_bits, num_encoded_bytes, msg, encoded);
}

View File

@ -0,0 +1,61 @@
#include "correct/convolutional/convolutional.h"
size_t correct_convolutional_encode_len(correct_convolutional *conv, size_t msg_len) {
size_t msgbits = 8 * msg_len;
size_t encodedbits = conv->rate * (msgbits + conv->order + 1);
return encodedbits;
}
// shift in most significant bit every time, one byte at a time
// shift register takes most recent bit on right, shifts left
// poly is written in same order, just & mask message w/ poly
// assume that encoded length is long enough?
size_t correct_convolutional_encode(correct_convolutional *conv,
const uint8_t *msg,
size_t msg_len,
uint8_t *encoded) {
// convolutional code convolves filter coefficients, given by
// the polynomial, with some history from our message.
// the history is stored as single subsequent bits in shiftregister
shift_register_t shiftregister = 0;
// shiftmask is the shiftregister bit mask that removes bits
// that extend beyond order
// e.g. if order is 7, then remove the 8th bit and beyond
unsigned int shiftmask = (1 << conv->order) - 1;
size_t encoded_len_bits = correct_convolutional_encode_len(conv, msg_len);
size_t encoded_len = (encoded_len_bits % 8) ? (encoded_len_bits / 8 + 1) : (encoded_len_bits / 8);
bit_writer_reconfigure(conv->bit_writer, encoded, encoded_len);
bit_reader_reconfigure(conv->bit_reader, msg, msg_len);
for (size_t i = 0; i < 8 * msg_len; i++) {
// shiftregister has oldest bits on left, newest on right
shiftregister <<= 1;
shiftregister |= bit_reader_read(conv->bit_reader, 1);
shiftregister &= shiftmask;
// shift most significant bit from byte and move down one bit at a time
// we do direct lookup of our convolutional output here
// all of the bits from this convolution are stored in this row
unsigned int out = conv->table[shiftregister];
bit_writer_write(conv->bit_writer, out, conv->rate);
}
// now flush the shiftregister
// this is simply running the loop as above but without any new inputs
// or rather, the new input string is all 0s
for (size_t i = 0; i < conv->order + 1; i++) {
shiftregister <<= 1;
shiftregister &= shiftmask;
unsigned int out = conv->table[shiftregister];
bit_writer_write(conv->bit_writer, out, conv->rate);
}
// 0-fill any remaining bits on our final byte
bit_writer_flush_byte(conv->bit_writer);
return encoded_len_bits;
}

View File

@ -0,0 +1,43 @@
#include "correct/convolutional/error_buffer.h"
error_buffer_t *error_buffer_create(unsigned int num_states) {
error_buffer_t *buf = calloc(1, sizeof(error_buffer_t));
// how large are the error buffers?
buf->num_states = num_states;
// save two error metrics, one for last round and one for this
// (double buffer)
// the error metric is the aggregated number of bit errors found
// at a given path which terminates at a particular shift register state
buf->errors[0] = calloc(sizeof(distance_t), num_states);
buf->errors[1] = calloc(sizeof(distance_t), num_states);
// which buffer are we using, 0 or 1?
buf->index = 0;
buf->read_errors = buf->errors[0];
buf->write_errors = buf->errors[1];
return buf;
}
void error_buffer_destroy(error_buffer_t *buf) {
free(buf->errors[0]);
free(buf->errors[1]);
free(buf);
}
void error_buffer_reset(error_buffer_t *buf) {
memset(buf->errors[0], 0, buf->num_states * sizeof(distance_t));
memset(buf->errors[1], 0, buf->num_states * sizeof(distance_t));
buf->index = 0;
buf->read_errors = buf->errors[0];
buf->write_errors = buf->errors[1];
}
void error_buffer_swap(error_buffer_t *buf) {
buf->read_errors = buf->errors[buf->index];
buf->index = (buf->index + 1) % 2;
buf->write_errors = buf->errors[buf->index];
}

View File

@ -0,0 +1,158 @@
#include "correct/convolutional/history_buffer.h"
history_buffer *history_buffer_create(unsigned int min_traceback_length,
unsigned int traceback_group_length,
unsigned int renormalize_interval, unsigned int num_states,
shift_register_t highbit) {
history_buffer *buf = calloc(1, sizeof(history_buffer));
*(unsigned int *)&buf->min_traceback_length = min_traceback_length;
*(unsigned int *)&buf->traceback_group_length = traceback_group_length;
*(unsigned int *)&buf->cap = min_traceback_length + traceback_group_length;
*(unsigned int *)&buf->num_states = num_states;
*(shift_register_t *)&buf->highbit = highbit;
buf->history = malloc(buf->cap * sizeof(uint8_t *));
for (unsigned int i = 0; i < buf->cap; i++) {
buf->history[i] = calloc(num_states, sizeof(uint8_t));
}
buf->fetched = malloc(buf->cap * sizeof(uint8_t));
buf->index = 0;
buf->len = 0;
buf->renormalize_counter = 0;
buf->renormalize_interval = renormalize_interval;
return buf;
}
void history_buffer_destroy(history_buffer *buf) {
for (unsigned int i = 0; i < buf->cap; i++) {
free(buf->history[i]);
}
free(buf->history);
free(buf->fetched);
free(buf);
}
void history_buffer_reset(history_buffer *buf) {
buf->len = 0;
buf->index = 0;
}
uint8_t *history_buffer_get_slice(history_buffer *buf) { return buf->history[buf->index]; }
shift_register_t history_buffer_search(history_buffer *buf, const distance_t *distances,
unsigned int search_every) {
shift_register_t bestpath = 0;
distance_t leasterror = USHRT_MAX;
// search for a state with the least error
for (shift_register_t state = 0; state < buf->num_states; state += search_every) {
if (distances[state] < leasterror) {
leasterror = distances[state];
bestpath = state;
}
}
return bestpath;
}
void history_buffer_renormalize(history_buffer *buf, distance_t *distances,
shift_register_t min_register) {
distance_t min_distance = distances[min_register];
for (shift_register_t i = 0; i < buf->num_states; i++) {
distances[i] -= min_distance;
}
}
void history_buffer_traceback(history_buffer *buf, shift_register_t bestpath,
unsigned int min_traceback_length, bit_writer_t *output) {
unsigned int fetched_index = 0;
shift_register_t highbit = buf->highbit;
unsigned int index = buf->index;
unsigned int cap = buf->cap;
for (unsigned int j = 0; j < min_traceback_length; j++) {
if (index == 0) {
index = cap - 1;
} else {
index--;
}
// we're walking backwards from what the work we did before
// so, we'll shift high order bits in
// the path will cross multiple different shift register states, and we determine
// which state by going backwards one time slice at a time
uint8_t history = buf->history[index][bestpath];
shift_register_t pathbit = history ? highbit : 0;
bestpath |= pathbit;
bestpath >>= 1;
}
unsigned int prefetch_index = index;
if (prefetch_index == 0) {
prefetch_index = cap - 1;
} else {
prefetch_index--;
}
unsigned int len = buf->len;
for (unsigned int j = min_traceback_length; j < len; j++) {
index = prefetch_index;
if (prefetch_index == 0) {
prefetch_index = cap - 1;
} else {
prefetch_index--;
}
prefetch(buf->history[prefetch_index]);
// we're walking backwards from what the work we did before
// so, we'll shift high order bits in
// the path will cross multiple different shift register states, and we determine
// which state by going backwards one time slice at a time
uint8_t history = buf->history[index][bestpath];
shift_register_t pathbit = history ? highbit : 0;
bestpath |= pathbit;
bestpath >>= 1;
buf->fetched[fetched_index] = (pathbit ? 1 : 0);
fetched_index++;
}
bit_writer_write_bitlist_reversed(output, buf->fetched, fetched_index);
buf->len -= fetched_index;
}
void history_buffer_process_skip(history_buffer *buf, distance_t *distances, bit_writer_t *output,
unsigned int skip) {
buf->index++;
if (buf->index == buf->cap) {
buf->index = 0;
}
buf->renormalize_counter++;
buf->len++;
// there are four ways these branches can resolve
// a) we are neither renormalizing nor doing a traceback
// b) we are renormalizing but not doing a traceback
// c) we are renormalizing and doing a traceback
// d) we are not renormalizing but we are doing a traceback
// in case c, we want to save the effort of finding the bestpath
// since that's expensive
// so we have to check for that case after we renormalize
if (buf->renormalize_counter == buf->renormalize_interval) {
buf->renormalize_counter = 0;
shift_register_t bestpath = history_buffer_search(buf, distances, skip);
history_buffer_renormalize(buf, distances, bestpath);
if (buf->len == buf->cap) {
// reuse the bestpath found for renormalizing
history_buffer_traceback(buf, bestpath, buf->min_traceback_length, output);
}
} else if (buf->len == buf->cap) {
// not renormalizing, find the bestpath here
shift_register_t bestpath = history_buffer_search(buf, distances, skip);
history_buffer_traceback(buf, bestpath, buf->min_traceback_length, output);
}
}
void history_buffer_process(history_buffer *buf, distance_t *distances, bit_writer_t *output) {
history_buffer_process_skip(buf, distances, output, 1);
}
void history_buffer_flush(history_buffer *buf, bit_writer_t *output) {
history_buffer_traceback(buf, 0, 0, output);
}

View File

@ -0,0 +1,74 @@
#include "correct/convolutional/lookup.h"
// table has numstates rows
// each row contains all of the polynomial output bits concatenated together
// e.g. for rate 2, we have 2 bits in each row
// the first poly gets the LEAST significant bit, last poly gets most significant
void fill_table(unsigned int rate,
unsigned int order,
const polynomial_t *poly,
unsigned int *table) {
for (shift_register_t i = 0; i < 1 << order; i++) {
unsigned int out = 0;
unsigned int mask = 1;
for (size_t j = 0; j < rate; j++) {
out |= (popcount(i & poly[j]) % 2) ? mask : 0;
mask <<= 1;
}
table[i] = out;
}
}
pair_lookup_t pair_lookup_create(unsigned int rate,
unsigned int order,
const unsigned int *table) {
pair_lookup_t pairs;
pairs.keys = malloc(sizeof(unsigned int) * (1 << (order - 1)));
pairs.outputs = calloc((1 << (rate * 2)), sizeof(unsigned int));
unsigned int *inv_outputs = calloc((1 << (rate * 2)), sizeof(unsigned int));
unsigned int output_counter = 1;
// for every (even-numbered) shift register state, find the concatenated output of the state
// and the subsequent state that follows it (low bit set). then, check to see if this
// concatenated output has a unique key assigned to it already. if not, give it a key.
// if it does, retrieve the key. assign this key to the shift register state.
for (unsigned int i = 0; i < (1 << (order - 1)); i++) {
// first get the concatenated pair of outputs
unsigned int out = table[i * 2 + 1];
out <<= rate;
out |= table[i * 2];
// does this concatenated output exist in the outputs table yet?
if (!inv_outputs[out]) {
// doesn't exist, allocate a new key
inv_outputs[out] = output_counter;
pairs.outputs[output_counter] = out;
output_counter++;
}
// set the opaque key for the ith shift register state to the concatenated output entry
pairs.keys[i] = inv_outputs[out];
}
pairs.outputs_len = output_counter;
pairs.output_mask = (1 << (rate)) - 1;
pairs.output_width = rate;
pairs.distances = calloc(pairs.outputs_len, sizeof(distance_pair_t));
free(inv_outputs);
return pairs;
}
void pair_lookup_destroy(pair_lookup_t pairs) {
free(pairs.keys);
free(pairs.outputs);
free(pairs.distances);
}
void pair_lookup_fill_distance(pair_lookup_t pairs, distance_t *distances) {
for (unsigned int i = 1; i < pairs.outputs_len; i += 1) {
output_pair_t concat_out = pairs.outputs[i];
unsigned int i_0 = concat_out & pairs.output_mask;
concat_out >>= pairs.output_width;
unsigned int i_1 = concat_out;
pairs.distances[i] = (distances[i_1] << 16) | distances[i_0];
}
}

View File

@ -0,0 +1,17 @@
#include "correct/convolutional/metric.h"
// measure the square of the euclidean distance between x and y
// since euclidean dist is sqrt(a^2 + b^2 + ... + n^2), the square is just
// a^2 + b^2 + ... + n^2
distance_t metric_soft_distance_quadratic(unsigned int hard_x, const uint8_t *soft_y, size_t len) {
distance_t dist = 0;
for (unsigned int i = 0; i < len; i++) {
// first, convert hard_x to a soft measurement (0 -> 0, 1 - > 255)
unsigned int soft_x = (hard_x & 1) ? 255 : 0;
hard_x >>= 1;
int d = soft_y[i] - soft_x;
dist += d*d;
}
return dist >> 3;
}

View File

@ -0,0 +1,2 @@
set(SRCFILES lookup.c convolutional.c encode.c decode.c)
add_library(correct-convolutional-sse OBJECT ${SRCFILES})

View File

@ -0,0 +1,21 @@
#include "correct/convolutional/sse/convolutional.h"
correct_convolutional_sse *correct_convolutional_sse_create(size_t rate,
size_t order,
const polynomial_t *poly) {
correct_convolutional_sse *conv = malloc(sizeof(correct_convolutional_sse));
correct_convolutional *init_conv = _correct_convolutional_init(&conv->base_conv, rate, order, poly);
if (!init_conv) {
free(conv);
conv = NULL;
}
return conv;
}
void correct_convolutional_sse_destroy(correct_convolutional_sse *conv) {
if (conv->base_conv.has_init_decode) {
oct_lookup_destroy(conv->oct_lookup);
}
_correct_convolutional_teardown(&conv->base_conv);
free(conv);
}

View File

@ -0,0 +1,319 @@
#include "correct/convolutional/sse/convolutional.h"
static void convolutional_sse_decode_inner(correct_convolutional_sse *sse_conv, unsigned int sets,
const uint8_t *soft) {
correct_convolutional *conv = &sse_conv->base_conv;
shift_register_t highbit = 1 << (conv->order - 1);
unsigned int hist_buf_index = conv->history_buffer->index;
unsigned int hist_buf_cap = conv->history_buffer->cap;
unsigned int hist_buf_len = conv->history_buffer->len;
unsigned int hist_buf_rn_int = conv->history_buffer->renormalize_interval;
unsigned int hist_buf_rn_cnt = conv->history_buffer->renormalize_counter;
for (unsigned int i = conv->order - 1; i < (sets - conv->order + 1); i++) {
distance_t *distances = conv->distances;
// lasterrors are the aggregate bit errors for the states of
// shiftregister for the previous time slice
if (soft) {
if (conv->soft_measurement == CORRECT_SOFT_LINEAR) {
for (unsigned int j = 0; j < 1 << (conv->rate); j++) {
distances[j] =
metric_soft_distance_linear(j, soft + i * conv->rate, conv->rate);
}
} else {
for (unsigned int j = 0; j < 1 << (conv->rate); j++) {
distances[j] =
metric_soft_distance_quadratic(j, soft + i * conv->rate, conv->rate);
}
}
} else {
unsigned int out = bit_reader_read(conv->bit_reader, conv->rate);
for (unsigned int i = 0; i < 1 << (conv->rate); i++) {
distances[i] = metric_distance(i, out);
}
}
oct_lookup_t oct_lookup = sse_conv->oct_lookup;
oct_lookup_fill_distance(oct_lookup, distances);
// a mask to get the high order bit from the shift register
unsigned int num_iter = highbit << 1;
const distance_t *read_errors = conv->errors->read_errors;
// aggregate bit errors for this time slice
distance_t *write_errors = conv->errors->write_errors;
uint8_t *history = conv->history_buffer->history[hist_buf_index];
;
// walk through all states, ignoring oldest bit
// we will track a best register state (path) and the number of bit
// errors at that path at this time slice
// this loop considers two paths per iteration (high order bit set,
// clear)
// so, it only runs numstates/2 iterations
// we'll update the history for every state and find the path with the
// least aggregated bit errors
// now run the main loop
// we calculate 2 sets of 2 register states here (4 states per iter)
// this creates 2 sets which share a predecessor, and 2 sets which share
// a successor
//
// the first set definition is the two states that are the same except
// for the least order bit
// these two share a predecessor because their high n - 1 bits are the
// same (differ only by newest bit)
//
// the second set definition is the two states that are the same except
// for the high order bit
// these two share a successor because the oldest high order bit will be
// shifted out, and the other bits will be present in the successor
//
shift_register_t highbase = highbit >> 1;
shift_register_t oct_highbase = highbase >> 2;
for (shift_register_t low = 0, high = highbit, base = 0, oct = 0; high < num_iter;
low += 32, high += 32, base += 16, oct += 4) {
// shifted-right ancestors
// low and low_plus_one share low_past_error
// note that they are the same when shifted right by 1
// same goes for high and high_plus_one
__m128i past_shuffle_mask =
_mm_set_epi32(0x07060706, 0x05040504, 0x03020302, 0x01000100);
__m128i hist_mask =
_mm_set_epi32(0x80808080, 0x80808080, 0x0e0c0a09, 0x07050301);
// the loop below calculates 64 register states per loop iteration
// it does this by packing the 128-bit xmm registers with 8, 16-bit
// distances
// 4 of these registers hold distances for convolutional shift
// register states with the high bit cleared
// and 4 hold distances for the corresponding shift register
// states with the high bit set
// since each xmm register holds 8 distances, this adds up to a
// total of 8 * 8 = 64 shift register states
for (shift_register_t offset = 0, base_offset = 0; base_offset < 16;
offset += 32, base_offset += 16) {
// load the past error for the register states with the high
// order bit cleared
__m128i low_past_error =
_mm_loadl_epi64((const __m128i *)(read_errors + base + base_offset));
__m128i low_past_error0 =
_mm_loadl_epi64((const __m128i *)(read_errors + base + base_offset + 4));
__m128i low_past_error1 =
_mm_loadl_epi64((const __m128i *)(read_errors + base + base_offset + 8));
__m128i low_past_error2 =
_mm_loadl_epi64((const __m128i *)(read_errors + base + base_offset + 12));
// shuffle the low past error
// register states that differ only by their low order bit share
// a past error
low_past_error = _mm_shuffle_epi8(low_past_error, past_shuffle_mask);
low_past_error0 = _mm_shuffle_epi8(low_past_error0, past_shuffle_mask);
low_past_error1 = _mm_shuffle_epi8(low_past_error1, past_shuffle_mask);
low_past_error2 = _mm_shuffle_epi8(low_past_error2, past_shuffle_mask);
// repeat past error lookup for register states with high order
// bit set
__m128i high_past_error =
_mm_loadl_epi64((const __m128i *)(read_errors + highbase + base + base_offset));
__m128i high_past_error0 = _mm_loadl_epi64(
(const __m128i *)(read_errors + highbase + base + base_offset + 4));
__m128i high_past_error1 = _mm_loadl_epi64(
(const __m128i *)(read_errors + highbase + base + base_offset + 8));
__m128i high_past_error2 = _mm_loadl_epi64(
(const __m128i *)(read_errors + highbase + base + base_offset + 12));
high_past_error = _mm_shuffle_epi8(high_past_error, past_shuffle_mask);
high_past_error0 = _mm_shuffle_epi8(high_past_error0, past_shuffle_mask);
high_past_error1 = _mm_shuffle_epi8(high_past_error1, past_shuffle_mask);
high_past_error2 = _mm_shuffle_epi8(high_past_error2, past_shuffle_mask);
// __m128i this_shuffle_mask = (__m128i){0x80800100, 0x80800302,
// 0x80800504, 0x80800706};
// load the opaque oct distance table keys from out loop index
distance_oct_key_t low_key = oct_lookup.keys[oct + (base_offset / 4)];
distance_oct_key_t low_key0 = oct_lookup.keys[oct + (base_offset / 4) + 1];
distance_oct_key_t low_key1 = oct_lookup.keys[oct + (base_offset / 4) + 2];
distance_oct_key_t low_key2 = oct_lookup.keys[oct + (base_offset / 4) + 3];
// load the distances for the register states with high order
// bit cleared
__m128i low_this_error =
_mm_load_si128((const __m128i *)(oct_lookup.distances + low_key));
__m128i low_this_error0 =
_mm_load_si128((const __m128i *)(oct_lookup.distances + low_key0));
__m128i low_this_error1 =
_mm_load_si128((const __m128i *)(oct_lookup.distances + low_key1));
__m128i low_this_error2 =
_mm_load_si128((const __m128i *)(oct_lookup.distances + low_key2));
// add the distance for this time slice to the past distances
__m128i low_error = _mm_add_epi16(low_past_error, low_this_error);
__m128i low_error0 = _mm_add_epi16(low_past_error0, low_this_error0);
__m128i low_error1 = _mm_add_epi16(low_past_error1, low_this_error1);
__m128i low_error2 = _mm_add_epi16(low_past_error2, low_this_error2);
// repeat oct distance table lookup for registers with high
// order bit set
distance_oct_key_t high_key =
oct_lookup.keys[oct_highbase + oct + (base_offset / 4)];
distance_oct_key_t high_key0 =
oct_lookup.keys[oct_highbase + oct + (base_offset / 4) + 1];
distance_oct_key_t high_key1 =
oct_lookup.keys[oct_highbase + oct + (base_offset / 4) + 2];
distance_oct_key_t high_key2 =
oct_lookup.keys[oct_highbase + oct + (base_offset / 4) + 3];
__m128i high_this_error =
_mm_load_si128((const __m128i *)(oct_lookup.distances + high_key));
__m128i high_this_error0 =
_mm_load_si128((const __m128i *)(oct_lookup.distances + high_key0));
__m128i high_this_error1 =
_mm_load_si128((const __m128i *)(oct_lookup.distances + high_key1));
__m128i high_this_error2 =
_mm_load_si128((const __m128i *)(oct_lookup.distances + high_key2));
__m128i high_error = _mm_add_epi16(high_past_error, high_this_error);
__m128i high_error0 = _mm_add_epi16(high_past_error0, high_this_error0);
__m128i high_error1 = _mm_add_epi16(high_past_error1, high_this_error1);
__m128i high_error2 = _mm_add_epi16(high_past_error2, high_this_error2);
// distances for this time slice calculated
// find the least error between registers who differ only in
// their high order bit
__m128i min_error = _mm_min_epu16(low_error, high_error);
__m128i min_error0 = _mm_min_epu16(low_error0, high_error0);
__m128i min_error1 = _mm_min_epu16(low_error1, high_error1);
__m128i min_error2 = _mm_min_epu16(low_error2, high_error2);
_mm_store_si128((__m128i *)(write_errors + low + offset), min_error);
_mm_store_si128((__m128i *)(write_errors + low + offset + 8), min_error0);
_mm_store_si128((__m128i *)(write_errors + low + offset + 16), min_error1);
_mm_store_si128((__m128i *)(write_errors + low + offset + 24), min_error2);
// generate history bits as (low_error > least_error)
// this operation fills each element with all 1s if true and 0s
// if false
// in other words, we set the history bit to 1 if
// the register state with high order bit set was the least
// error
__m128i hist = _mm_cmpgt_epi16(low_error, min_error);
// pack the bits down from 16-bit wide to 8-bit wide to
// accomodate history table
hist = _mm_shuffle_epi8(hist, hist_mask);
__m128i hist0 = _mm_cmpgt_epi16(low_error0, min_error0);
hist0 = _mm_shuffle_epi8(hist0, hist_mask);
__m128i hist1 = _mm_cmpgt_epi16(low_error1, min_error1);
hist1 = _mm_shuffle_epi8(hist1, hist_mask);
__m128i hist2 = _mm_cmpgt_epi16(low_error2, min_error2);
hist2 = _mm_shuffle_epi8(hist2, hist_mask);
// write the least error so that the next time slice sees it as
// the past error
// store the history bits set by cmp and shuffle operations
_mm_storel_epi64((__m128i *)(history + low + offset), hist);
_mm_storel_epi64((__m128i *)(history + low + offset + 8), hist0);
_mm_storel_epi64((__m128i *)(history + low + offset + 16), hist1);
_mm_storel_epi64((__m128i *)(history + low + offset + 24), hist2);
}
}
// bypass the call to history buffer
// we should really make that function inline and remove this below
if (hist_buf_len == hist_buf_cap - 1 || hist_buf_rn_cnt == hist_buf_rn_int - 1) {
// restore hist buffer state and invoke it
conv->history_buffer->len = hist_buf_len;
conv->history_buffer->index = hist_buf_index;
conv->history_buffer->renormalize_counter = hist_buf_rn_cnt;
history_buffer_process(conv->history_buffer, write_errors, conv->bit_writer);
// restore our local values
hist_buf_len = conv->history_buffer->len;
hist_buf_index = conv->history_buffer->index;
hist_buf_cap = conv->history_buffer->cap;
hist_buf_rn_cnt = conv->history_buffer->renormalize_counter;
} else {
hist_buf_len++;
hist_buf_index++;
if (hist_buf_index == hist_buf_cap) {
hist_buf_index = 0;
}
hist_buf_rn_cnt++;
}
error_buffer_swap(conv->errors);
}
conv->history_buffer->len = hist_buf_len;
conv->history_buffer->index = hist_buf_index;
conv->history_buffer->renormalize_counter = hist_buf_rn_cnt;
}
static void _convolutional_sse_decode_init(correct_convolutional_sse *conv,
unsigned int min_traceback,
unsigned int traceback_length,
unsigned int renormalize_interval) {
_convolutional_decode_init(&conv->base_conv, min_traceback, traceback_length,
renormalize_interval);
conv->oct_lookup =
oct_lookup_create(conv->base_conv.rate, conv->base_conv.order, conv->base_conv.table);
}
static ssize_t _convolutional_sse_decode(correct_convolutional_sse *sse_conv,
size_t num_encoded_bits, size_t num_encoded_bytes,
uint8_t *msg, const soft_t *soft_encoded) {
correct_convolutional *conv = &sse_conv->base_conv;
if (!conv->has_init_decode) {
uint64_t max_error_per_input = conv->rate * soft_max;
// sse implementation unfortunately uses signed math on our unsigned values
// reduces usable distance by /2
unsigned int renormalize_interval = (distance_max / 2) / max_error_per_input;
_convolutional_sse_decode_init(sse_conv, 5 * conv->order, 100 * conv->order,
renormalize_interval);
}
size_t sets = num_encoded_bits / conv->rate;
// XXX fix this vvvvvv
size_t decoded_len_bytes = num_encoded_bytes;
bit_writer_reconfigure(conv->bit_writer, msg, decoded_len_bytes);
error_buffer_reset(conv->errors);
history_buffer_reset(conv->history_buffer);
// no outputs are generated during warmup
convolutional_decode_warmup(conv, sets, soft_encoded);
convolutional_sse_decode_inner(sse_conv, sets, soft_encoded);
convolutional_decode_tail(conv, sets, soft_encoded);
history_buffer_flush(conv->history_buffer, conv->bit_writer);
return bit_writer_length(conv->bit_writer);
}
ssize_t correct_convolutional_sse_decode(correct_convolutional_sse *conv, const uint8_t *encoded,
size_t num_encoded_bits, uint8_t *msg) {
if (num_encoded_bits % conv->base_conv.rate) {
// XXX turn this into an error code
// printf("encoded length of message must be a multiple of rate\n");
return -1;
}
size_t num_encoded_bytes =
(num_encoded_bits % 8) ? (num_encoded_bits / 8 + 1) : (num_encoded_bits / 8);
bit_reader_reconfigure(conv->base_conv.bit_reader, encoded, num_encoded_bytes);
return _convolutional_sse_decode(conv, num_encoded_bits, num_encoded_bytes, msg, NULL);
}
ssize_t correct_convolutional_sse_decode_soft(correct_convolutional_sse *conv, const soft_t *encoded,
size_t num_encoded_bits, uint8_t *msg) {
if (num_encoded_bits % conv->base_conv.rate) {
// XXX turn this into an error code
// printf("encoded length of message must be a multiple of rate\n");
return -1;
}
size_t num_encoded_bytes =
(num_encoded_bits % 8) ? (num_encoded_bits / 8 + 1) : (num_encoded_bits / 8);
return _convolutional_sse_decode(conv, num_encoded_bits, num_encoded_bytes, msg, encoded);
}

View File

@ -0,0 +1,9 @@
#include "correct/convolutional/sse/convolutional.h"
size_t correct_convolutional_sse_encode_len(correct_convolutional_sse *conv, size_t msg_len) {
return correct_convolutional_encode_len(&conv->base_conv, msg_len);
}
size_t correct_convolutional_sse_encode(correct_convolutional_sse *conv, const uint8_t *msg, size_t msg_len, uint8_t *encoded) {
return correct_convolutional_encode(&conv->base_conv, msg, msg_len, encoded);
}

View File

@ -0,0 +1,183 @@
#include "correct/convolutional/sse/lookup.h"
quad_lookup_t quad_lookup_create(unsigned int rate,
unsigned int order,
const unsigned int *table) {
quad_lookup_t quads;
quads.keys = malloc(sizeof(unsigned int) * (1 << (order - 2)));
quads.outputs = calloc((1 << (rate * 4)), sizeof(unsigned int));
unsigned int *inv_outputs = calloc((1 << (rate * 4)), sizeof(unsigned int));
unsigned int output_counter = 1;
// for every (even-numbered) shift register state, find the concatenated output of the state
// and the subsequent state that follows it (low bit set). then, check to see if this
// concatenated output has a unique key assigned to it already. if not, give it a key.
// if it does, retrieve the key. assign this key to the shift register state.
for (unsigned int i = 0; i < (1 << (order - 2)); i++) {
// first get the concatenated quad of outputs
unsigned int out = table[i * 4 + 3];
out <<= rate;
out |= table[i * 4 + 2];
out <<= rate;
out |= table[i * 4 + 1];
out <<= rate;
out |= table[i * 4];
// does this concatenated output exist in the outputs table yet?
if (!inv_outputs[out]) {
// doesn't exist, allocate a new key
inv_outputs[out] = output_counter;
quads.outputs[output_counter] = out;
output_counter++;
}
// set the opaque key for the ith shift register state to the concatenated output entry
quads.keys[i] = inv_outputs[out];
}
quads.outputs_len = output_counter;
quads.output_mask = (1 << (rate)) - 1;
quads.output_width = rate;
quads.distances = calloc(quads.outputs_len, sizeof(distance_quad_t));
free(inv_outputs);
return quads;
}
void quad_lookup_destroy(quad_lookup_t quads) {
free(quads.keys);
free(quads.outputs);
free(quads.distances);
}
void quad_lookup_fill_distance(quad_lookup_t quads, distance_t *distances) {
for (unsigned int i = 1; i < quads.outputs_len; i += 1) {
output_quad_t concat_out = quads.outputs[i];
unsigned int i_0 = concat_out & quads.output_mask;
concat_out >>= quads.output_width;
unsigned int i_1 = concat_out & quads.output_mask;
concat_out >>= quads.output_width;
unsigned int i_2 = concat_out & quads.output_mask;
concat_out >>= quads.output_width;
unsigned int i_3 = concat_out;
quads.distances[i] = ((uint64_t)distances[i_3] << 48) | ((uint64_t)distances[i_2] << 32) | (distances[i_1] << 16) | distances[i_0];
}
}
distance_oct_key_t oct_lookup_find_key(output_oct_t *outputs, output_oct_t out, size_t num_keys) {
for (size_t i = 1; i < num_keys; i++) {
if (outputs[i] == out) {
return i;
}
}
return 0;
}
oct_lookup_t oct_lookup_create(unsigned int rate,
unsigned int order,
const unsigned int *table) {
oct_lookup_t octs;
octs.keys = malloc((1 << (order - 3)) * sizeof(distance_oct_key_t));
octs.outputs = malloc(((output_oct_t)2 << rate) * sizeof(uint64_t));
output_oct_t *short_outs = calloc(((output_oct_t)2 << rate), sizeof(output_oct_t));
size_t outputs_len = 2 << rate;
unsigned int output_counter = 1;
// for every (even-numbered) shift register state, find the concatenated output of the state
// and the subsequent state that follows it (low bit set). then, check to see if this
// concatenated output has a unique key assigned to it already. if not, give it a key.
// if it does, retrieve the key. assign this key to the shift register state.
for (shift_register_t i = 0; i < (1 << (order - 3)); i++) {
// first get the concatenated oct of outputs
output_oct_t out = table[i * 8 + 7];
out <<= rate;
out |= table[i * 8 + 6];
out <<= rate;
out |= table[i * 8 + 5];
out <<= rate;
out |= table[i * 8 + 4];
out <<= rate;
out |= table[i * 8 + 3];
out <<= rate;
out |= table[i * 8 + 2];
out <<= rate;
out |= table[i * 8 + 1];
out <<= rate;
out |= table[i * 8];
distance_oct_key_t key = oct_lookup_find_key(short_outs, out, output_counter);
// does this concatenated output exist in the outputs table yet?
if (!key) {
// doesn't exist, allocate a new key
// now build it in expanded form
output_oct_t expanded_out = table[i * 8 + 7];
expanded_out <<= 8;
expanded_out |= table[i * 8 + 6];
expanded_out <<= 8;
expanded_out |= table[i * 8 + 5];
expanded_out <<= 8;
expanded_out |= table[i * 8 + 4];
expanded_out <<= 8;
expanded_out |= table[i * 8 + 3];
expanded_out <<= 8;
expanded_out |= table[i * 8 + 2];
expanded_out <<= 8;
expanded_out |= table[i * 8 + 1];
expanded_out <<= 8;
expanded_out |= table[i * 8];
if (output_counter == outputs_len) {
octs.outputs = realloc(octs.outputs, outputs_len * 2 * sizeof(output_oct_t));
short_outs = realloc(short_outs, outputs_len * 2 * sizeof(output_oct_t));
outputs_len *= 2;
}
short_outs[output_counter] = out;
octs.outputs[output_counter] = expanded_out;
key = output_counter;
output_counter++;
}
// set the opaque key for the ith shift register state to the concatenated output entry
// we multiply the key by 2 since the distances are strided by 2
octs.keys[i] = key * 2;
}
free(short_outs);
octs.outputs_len = output_counter;
octs.output_mask = (1 << (rate)) - 1;
octs.output_width = rate;
octs.distances = malloc(octs.outputs_len * 2 * sizeof(uint64_t));
return octs;
}
void oct_lookup_destroy(oct_lookup_t octs) {
free(octs.keys);
free(octs.outputs);
free(octs.distances);
}
// WIP: sse approach to filling the distance table
/*
void oct_lookup_fill_distance_sse(oct_lookup_t octs, distance_t *distances) {
distance_pair_t *distance_pair = (distance_pair_t*)octs.distances;
__v4si index_shuffle_mask = (__v4si){0xffffff00, 0xffffff01, 0xffffff02, 0xffffff03};
__m256i dist_shuffle_mask = (__m256i){0x01000504, 0x09080d0c, 0xffffffff, 0xffffffff,
0x01000504, 0x09080d0c, 0xffffffff, 0xffffffff};
const int dist_permute_mask = 0x0c;
for (unsigned int i = 1; i < octs.outputs_len; i += 2) {
// big heaping todo vvv
// a) we want 16 bit distances GATHERed, not 32 bit
// b) we need to load 8 of those distances, not 4
__v4si short_concat_index = _mm_loadl_epi64(octs.outputs + 2*i);
__v4si short_concat_index0 = _mm_loadl_epi64(octs.outputs + 2*i + 1);
__m256i concat_index = _mm256_cvtepu8_epi32(short_concat_index);
__m256i concat_index0 = _mm256_cvtepu8_epi32(short_concat_index0);
__m256i dist = _mm256_i32gather_epi32(distances, concat_index, sizeof(distance_t));
__m256i dist0 = _mm256_i32gather_epi32(distances, concat_index0, sizeof(distance_t));
dist = _mm256_shuffle_epi8(dist, dist_shuffle_mask);
dist0 = _mm256_shuffle_epi8(dist0, dist_shuffle_mask);
dist = __builtin_shufflevector(dist, dist, 0, 5, 0, 0);
dist0 = __builtin_shufflevector(dist0, dist0, 0, 5, 0, 0);
__v4si packed_dist = _mm256_castsi256_si128(dist);
_mm_store_si128(distance_pair + 8 * i, packed_dist);
__v4si packed_dist0 = _mm256_castsi256_si128(dist0);
_mm_store_si128(distance_pair + 8 * i + 4, packed_dist0);
}
}
*/

View File

@ -0,0 +1,255 @@
#include <stdlib.h>
#include <string.h>
#include "fec_shim.h"
typedef struct {
correct_reed_solomon *rs;
unsigned int msg_length;
unsigned int block_length;
unsigned int num_roots;
uint8_t *msg_out;
unsigned int pad;
uint8_t *erasures;
} reed_solomon_shim;
void *init_rs_char(int symbol_size, int primitive_polynomial,
int first_consecutive_root, int root_gap, int number_roots,
unsigned int pad) {
if (symbol_size != 8) {
return NULL;
}
reed_solomon_shim *shim = malloc(sizeof(reed_solomon_shim));
shim->pad = pad;
shim->block_length = 255 - pad;
shim->num_roots = number_roots;
shim->msg_length = shim->block_length - number_roots;
shim->rs = correct_reed_solomon_create(primitive_polynomial,
first_consecutive_root, root_gap, number_roots);
shim->msg_out = malloc(shim->block_length);
shim->erasures = malloc(number_roots);
return shim;
}
void free_rs_char(void *rs) {
reed_solomon_shim *shim = (reed_solomon_shim *)rs;
correct_reed_solomon_destroy(shim->rs);
free(shim->msg_out);
free(shim->erasures);
free(shim);
}
void encode_rs_char(void *rs, const unsigned char *msg, unsigned char *parity) {
reed_solomon_shim *shim = (reed_solomon_shim *)rs;
correct_reed_solomon_encode(shim->rs, msg, shim->msg_length, shim->msg_out);
memcpy(parity, shim->msg_out + shim->msg_length, shim->num_roots);
}
void decode_rs_char(void *rs, unsigned char *block, int *erasure_locations,
int num_erasures) {
reed_solomon_shim *shim = (reed_solomon_shim *)rs;
for (int i = 0; i < num_erasures; i++) {
shim->erasures[i] = (uint8_t)(erasure_locations[i]) - shim->pad;
}
correct_reed_solomon_decode_with_erasures(shim->rs, block, shim->block_length,
shim->erasures, num_erasures,
block);
}
typedef struct {
correct_convolutional *conv;
unsigned int rate;
unsigned int order;
uint8_t *buf;
size_t buf_len;
uint8_t *read_iter;
uint8_t *write_iter;
} convolutional_shim;
static correct_convolutional_polynomial_t r12k7[] = {V27POLYA, V27POLYB};
static correct_convolutional_polynomial_t r12k9[] = {V29POLYA, V29POLYB};
static correct_convolutional_polynomial_t r13k9[] = {V39POLYA, V39POLYB,
V39POLYC};
static correct_convolutional_polynomial_t r16k15[] = {
V615POLYA, V615POLYB, V615POLYC, V615POLYD, V615POLYE, V615POLYF};
/* Common methods */
static void *create_viterbi(unsigned int num_decoded_bits, unsigned int rate,
unsigned int order,
correct_convolutional_polynomial_t *poly) {
convolutional_shim *shim = malloc(sizeof(convolutional_shim));
size_t num_decoded_bytes = (num_decoded_bits % 8)
? (num_decoded_bits / 8 + 1)
: num_decoded_bits / 8;
shim->rate = rate;
shim->order = order;
shim->buf = malloc(num_decoded_bytes);
shim->buf_len = num_decoded_bytes;
shim->conv = correct_convolutional_create(rate, order, poly);
shim->read_iter = shim->buf;
shim->write_iter = shim->buf;
return shim;
}
static void delete_viterbi(void *vit) {
convolutional_shim *shim = (convolutional_shim *)vit;
free(shim->buf);
correct_convolutional_destroy(shim->conv);
free(shim);
}
static void init_viterbi(void *vit) {
convolutional_shim *shim = (convolutional_shim *)vit;
shim->read_iter = shim->buf;
shim->write_iter = shim->buf;
}
static void update_viterbi_blk(void *vit, const unsigned char *encoded_soft,
unsigned int num_encoded_groups) {
convolutional_shim *shim = (convolutional_shim *)vit;
// don't overwrite our buffer
size_t rem = (shim->buf + shim->buf_len) - shim->write_iter;
size_t rem_bits = 8 * rem;
// this math isn't very clear
// here we sort of do the opposite of what liquid-dsp does
size_t n_write_bits = num_encoded_groups - (shim->order - 1);
if (n_write_bits > rem_bits) {
size_t reduction = n_write_bits - rem_bits;
num_encoded_groups -= reduction;
n_write_bits -= reduction;
}
// what if n_write_bits isn't a multiple of 8?
// libcorrect can't start and stop at arbitrary indices...
correct_convolutional_decode_soft(
shim->conv, encoded_soft, num_encoded_groups * shim->rate, shim->write_iter);
shim->write_iter += n_write_bits / 8;
}
static void chainback_viterbi(void *vit, unsigned char *decoded,
unsigned int num_decoded_bits) {
convolutional_shim *shim = (convolutional_shim *)vit;
// num_decoded_bits not a multiple of 8?
// this is a similar problem to update_viterbi_blk
// although here we could actually resolve a non-multiple of 8
size_t rem = shim->write_iter - shim->read_iter;
size_t rem_bits = 8 * rem;
if (num_decoded_bits > rem_bits) {
num_decoded_bits = rem_bits;
}
size_t num_decoded_bytes = (num_decoded_bits % 8)
? (num_decoded_bits / 8 + 1)
: num_decoded_bits / 8;
memcpy(decoded, shim->read_iter, num_decoded_bytes);
shim->read_iter += num_decoded_bytes;
}
/* Rate 1/2, k = 7 */
void *create_viterbi27(int num_decoded_bits) {
return create_viterbi(num_decoded_bits, 2, 7, r12k7);
}
void delete_viterbi27(void *vit) { delete_viterbi(vit); }
int init_viterbi27(void *vit, int _) {
init_viterbi(vit);
return 0;
}
int update_viterbi27_blk(void *vit, unsigned char *encoded_soft,
int num_encoded_groups) {
update_viterbi_blk(vit, encoded_soft, num_encoded_groups);
return 0;
}
int chainback_viterbi27(void *vit, unsigned char *decoded,
unsigned int num_decoded_bits, unsigned int _) {
chainback_viterbi(vit, decoded, num_decoded_bits);
return 0;
}
/* Rate 1/2, k = 9 */
void *create_viterbi29(int num_decoded_bits) {
return create_viterbi(num_decoded_bits, 2, 9, r12k9);
}
void delete_viterbi29(void *vit) { delete_viterbi(vit); }
int init_viterbi29(void *vit, int _) {
init_viterbi(vit);
return 0;
}
int update_viterbi29_blk(void *vit, unsigned char *encoded_soft,
int num_encoded_groups) {
update_viterbi_blk(vit, encoded_soft, num_encoded_groups);
return 0;
}
int chainback_viterbi29(void *vit, unsigned char *decoded,
unsigned int num_decoded_bits, unsigned int _) {
chainback_viterbi(vit, decoded, num_decoded_bits);
return 0;
}
/* Rate 1/3, k = 9 */
void *create_viterbi39(int num_decoded_bits) {
return create_viterbi(num_decoded_bits, 3, 9, r13k9);
}
void delete_viterbi39(void *vit) { delete_viterbi(vit); }
int init_viterbi39(void *vit, int _) {
init_viterbi(vit);
return 0;
}
int update_viterbi39_blk(void *vit, unsigned char *encoded_soft,
int num_encoded_groups) {
update_viterbi_blk(vit, encoded_soft, num_encoded_groups);
return 0;
}
int chainback_viterbi39(void *vit, unsigned char *decoded,
unsigned int num_decoded_bits, unsigned int _) {
chainback_viterbi(vit, decoded, num_decoded_bits);
return 0;
}
/* Rate 1/6, k = 15 */
void *create_viterbi615(int num_decoded_bits) {
return create_viterbi(num_decoded_bits, 6, 15, r16k15);
}
void delete_viterbi615(void *vit) { delete_viterbi(vit); }
int init_viterbi615(void *vit, int _) {
init_viterbi(vit);
return 0;
}
int update_viterbi615_blk(void *vit, unsigned char *encoded_soft,
int num_encoded_groups) {
update_viterbi_blk(vit, encoded_soft, num_encoded_groups);
return 0;
}
int chainback_viterbi615(void *vit, unsigned char *decoded,
unsigned int num_decoded_bits, unsigned int _) {
chainback_viterbi(vit, decoded, num_decoded_bits);
return 0;
}

View File

@ -0,0 +1,2 @@
set(SRCFILES polynomial.c reed-solomon.c encode.c decode.c)
add_library(correct-reed-solomon OBJECT ${SRCFILES})

View File

@ -0,0 +1,508 @@
#include "correct/reed-solomon/encode.h"
// calculate all syndromes of the received polynomial at the roots of the generator
// because we're evaluating at the roots of the generator, and because the transmitted
// polynomial was made to be a product of the generator, we know that the transmitted
// polynomial is 0 at these roots
// any nonzero syndromes we find here are the values of the error polynomial evaluated
// at these roots, so these values give us a window into the error polynomial. if
// these syndromes are all zero, then we can conclude the error polynomial is also
// zero. if they're nonzero, then we know our message received an error in transit.
// returns true if syndromes are all zero
static bool reed_solomon_find_syndromes(field_t field, polynomial_t msgpoly, field_logarithm_t **generator_root_exp,
field_element_t *syndromes, size_t min_distance) {
bool all_zero = true;
memset(syndromes, 0, min_distance * sizeof(field_element_t));
for (unsigned int i = 0; i < min_distance; i++) {
// profiling reveals that this function takes about 50% of the cpu time of
// decoding. so, in order to speed it up a little, we precompute and save
// the successive powers of the roots of the generator, which are
// located in generator_root_exp
field_element_t eval = polynomial_eval_lut(field, msgpoly, generator_root_exp[i]);
if (eval) {
all_zero = false;
}
syndromes[i] = eval;
}
return all_zero;
}
// Berlekamp-Massey algorithm to find LFSR that describes syndromes
// returns number of errors and writes the error locator polynomial to rs->error_locator
static unsigned int reed_solomon_find_error_locator(correct_reed_solomon *rs, size_t num_erasures) {
unsigned int numerrors = 0;
memset(rs->error_locator.coeff, 0, (rs->min_distance + 1) * sizeof(field_element_t));
// initialize to f(x) = 1
rs->error_locator.coeff[0] = 1;
rs->error_locator.order = 0;
memcpy(rs->last_error_locator.coeff, rs->error_locator.coeff, (rs->min_distance + 1) * sizeof(field_element_t));
rs->last_error_locator.order = rs->error_locator.order;
field_element_t discrepancy;
field_element_t last_discrepancy = 1;
unsigned int delay_length = 1;
for (unsigned int i = rs->error_locator.order; i < rs->min_distance - num_erasures; i++) {
discrepancy = rs->syndromes[i];
for (unsigned int j = 1; j <= numerrors; j++) {
discrepancy = field_add(rs->field, discrepancy,
field_mul(rs->field, rs->error_locator.coeff[j], rs->syndromes[i - j]));
}
if (!discrepancy) {
// our existing LFSR describes the new syndrome as well
// leave it as-is but update the number of delay elements
// so that if a discrepancy occurs later we can eliminate it
delay_length++;
continue;
}
if (2 * numerrors <= i) {
// there's a discrepancy, but we still have room for more taps
// lengthen LFSR by one tap and set weight to eliminate discrepancy
// shift the last locator by the delay length, multiply by discrepancy,
// and divide by the last discrepancy
// we move down because we're shifting up, and this prevents overwriting
for (int j = rs->last_error_locator.order; j >= 0; j--) {
// the bounds here will be ok since we have a headroom of numerrors
rs->last_error_locator.coeff[j + delay_length] = field_div(
rs->field, field_mul(rs->field, rs->last_error_locator.coeff[j], discrepancy), last_discrepancy);
}
for (int j = delay_length - 1; j >= 0; j--) {
rs->last_error_locator.coeff[j] = 0;
}
// locator = locator - last_locator
// we will also update last_locator to be locator before this loop takes place
field_element_t temp;
for (int j = 0; j <= (rs->last_error_locator.order + delay_length); j++) {
temp = rs->error_locator.coeff[j];
rs->error_locator.coeff[j] =
field_add(rs->field, rs->error_locator.coeff[j], rs->last_error_locator.coeff[j]);
rs->last_error_locator.coeff[j] = temp;
}
unsigned int temp_order = rs->error_locator.order;
rs->error_locator.order = rs->last_error_locator.order + delay_length;
rs->last_error_locator.order = temp_order;
// now last_locator is locator before we started,
// and locator is (locator - (discrepancy/last_discrepancy) * x^(delay_length) * last_locator)
numerrors = i + 1 - numerrors;
last_discrepancy = discrepancy;
delay_length = 1;
continue;
}
// no more taps
// unlike the previous case, we are preserving last locator,
// but we'll update locator as before
// we're basically flattening the two loops from the previous case because
// we no longer need to update last_locator
for (int j = rs->last_error_locator.order; j >= 0; j--) {
rs->error_locator.coeff[j + delay_length] =
field_add(rs->field, rs->error_locator.coeff[j + delay_length],
field_div(rs->field, field_mul(rs->field, rs->last_error_locator.coeff[j], discrepancy),
last_discrepancy));
}
rs->error_locator.order = (rs->last_error_locator.order + delay_length > rs->error_locator.order)
? rs->last_error_locator.order + delay_length
: rs->error_locator.order;
delay_length++;
}
return rs->error_locator.order;
}
// find the roots of the error locator polynomial
// Chien search
bool reed_solomon_factorize_error_locator(field_t field, unsigned int num_skip, polynomial_t locator_log, field_element_t *roots,
field_logarithm_t **element_exp) {
// normally it'd be tricky to find all the roots
// but, the finite field is awfully finite...
// just brute force search across every field element
unsigned int root = num_skip;
memset(roots + num_skip, 0, (locator_log.order) * sizeof(field_element_t));
for (field_operation_t i = 0; i < 256; i++) {
// we make two optimizations here to help this search go faster
// a) we have precomputed the first successive powers of every single element
// in the field. we need at most n powers, where n is the largest possible
// degree of the error locator
// b) we have precomputed the error locator polynomial in log form, which
// helps reduce some lookups that would be done here
if (!polynomial_eval_log_lut(field, locator_log, element_exp[i])) {
roots[root] = (field_element_t)i;
root++;
}
}
// this is where we find out if we are have too many errors to recover from
// berlekamp-massey may have built an error locator that has 0 discrepancy
// on the syndromes but doesn't have enough roots
return root == locator_log.order + num_skip;
}
// use error locator and syndromes to find the error evaluator polynomial
void reed_solomon_find_error_evaluator(field_t field, polynomial_t locator, polynomial_t syndromes,
polynomial_t error_evaluator) {
// the error evaluator, omega(x), is S(x)*Lamba(x) mod x^(2t)
// where S(x) is a polynomial constructed from the syndromes
// S(1) + S(2)*x + ... + S(2t)*x(2t - 1)
// and Lambda(x) is the error locator
// the modulo is implicit here -- we have limited the max length of error_evaluator,
// which polynomial_mul will interpret to mean that it should not compute
// powers larger than that, which is the same as performing mod x^(2t)
polynomial_mul(field, locator, syndromes, error_evaluator);
}
// use error locator, error roots and syndromes to find the error values
// that is, the elements in the finite field which can be added to the received
// polynomial at the locations of the error roots in order to produce the
// transmitted polynomial
// forney algorithm
void reed_solomon_find_error_values(correct_reed_solomon *rs) {
// error value e(j) = -(X(j)^(1-c) * omega(X(j)^-1))/(lambda'(X(j)^-1))
// where X(j)^-1 is a root of the error locator, omega(X) is the error evaluator,
// lambda'(X) is the first formal derivative of the error locator,
// and c is the first consecutive root of the generator used in encoding
// first find omega(X), the error evaluator
// we generate S(x), the polynomial constructed from the roots of the syndromes
// this is *not* the polynomial constructed by expanding the products of roots
// S(x) = S(1) + S(2)*x + ... + S(2t)*x(2t - 1)
polynomial_t syndrome_poly;
syndrome_poly.order = rs->min_distance - 1;
syndrome_poly.coeff = rs->syndromes;
memset(rs->error_evaluator.coeff, 0, (rs->error_evaluator.order + 1) * sizeof(field_element_t));
reed_solomon_find_error_evaluator(rs->field, rs->error_locator, syndrome_poly, rs->error_evaluator);
// now find lambda'(X)
rs->error_locator_derivative.order = rs->error_locator.order - 1;
polynomial_formal_derivative(rs->field, rs->error_locator, rs->error_locator_derivative);
// calculate each e(j)
for (unsigned int i = 0; i < rs->error_locator.order; i++) {
if (rs->error_roots[i] == 0) {
continue;
}
rs->error_vals[i] = field_mul(
rs->field, field_pow(rs->field, rs->error_roots[i], rs->first_consecutive_root - 1),
field_div(
rs->field, polynomial_eval_lut(rs->field, rs->error_evaluator, rs->element_exp[rs->error_roots[i]]),
polynomial_eval_lut(rs->field, rs->error_locator_derivative, rs->element_exp[rs->error_roots[i]])));
}
}
void reed_solomon_find_error_locations(field_t field, field_logarithm_t generator_root_gap,
field_element_t *error_roots, field_logarithm_t *error_locations,
unsigned int num_errors, unsigned int num_skip) {
for (unsigned int i = 0; i < num_errors; i++) {
// the error roots are the reciprocals of the error locations, so div 1 by them
// we do mod 255 here because the log table aliases at index 1
// the log of 1 is both 0 and 255 (alpha^255 = alpha^0 = 1)
// for most uses it makes sense to have log(1) = 255, but in this case
// we're interested in a byte index, and the 255th index is not even valid
// just wrap it back to 0
if (error_roots[i] == 0) {
continue;
}
field_operation_t loc = field_div(field, 1, error_roots[i]);
for (field_operation_t j = 0; j < 256; j++) {
if (field_pow(field, j, generator_root_gap) == loc) {
error_locations[i] = field.log[j];
break;
}
}
}
}
// erasure method -- take given locations and convert to roots
// this is the inverse of reed_solomon_find_error_locations
static void reed_solomon_find_error_roots_from_locations(field_t field, field_logarithm_t generator_root_gap,
const field_logarithm_t *error_locations,
field_element_t *error_roots, unsigned int num_errors) {
for (unsigned int i = 0; i < num_errors; i++) {
field_element_t loc = field_pow(field, field.exp[error_locations[i]], generator_root_gap);
// field_element_t loc = field.exp[error_locations[i]];
error_roots[i] = field_div(field, 1, loc);
// error_roots[i] = loc;
}
}
// erasure method -- given the roots of the error locator, create the polynomial
static polynomial_t reed_solomon_find_error_locator_from_roots(field_t field, unsigned int num_errors,
field_element_t *error_roots,
polynomial_t error_locator,
polynomial_t *scratch) {
// multiply out roots to build the error locator polynomial
return polynomial_init_from_roots(field, num_errors, error_roots, error_locator, scratch);
}
// erasure method
static void reed_solomon_find_modified_syndromes(correct_reed_solomon *rs, field_element_t *syndromes, polynomial_t error_locator, field_element_t *modified_syndromes) {
polynomial_t syndrome_poly;
syndrome_poly.order = rs->min_distance - 1;
syndrome_poly.coeff = syndromes;
polynomial_t modified_syndrome_poly;
modified_syndrome_poly.order = rs->min_distance - 1;
modified_syndrome_poly.coeff = modified_syndromes;
polynomial_mul(rs->field, error_locator, syndrome_poly, modified_syndrome_poly);
}
void correct_reed_solomon_decoder_create(correct_reed_solomon *rs) {
rs->has_init_decode = true;
rs->syndromes = calloc(rs->min_distance, sizeof(field_element_t));
rs->modified_syndromes = calloc(2 * rs->min_distance, sizeof(field_element_t));
rs->received_polynomial = polynomial_create(rs->block_length - 1);
rs->error_locator = polynomial_create(rs->min_distance);
rs->error_locator_log = polynomial_create(rs->min_distance);
rs->erasure_locator = polynomial_create(rs->min_distance);
rs->error_roots = calloc(2 * rs->min_distance, sizeof(field_element_t));
rs->error_vals = malloc(rs->min_distance * sizeof(field_element_t));
rs->error_locations = malloc(rs->min_distance * sizeof(field_logarithm_t));
rs->last_error_locator = polynomial_create(rs->min_distance);
rs->error_evaluator = polynomial_create(rs->min_distance - 1);
rs->error_locator_derivative = polynomial_create(rs->min_distance - 1);
// calculate and store the first block_length powers of every generator root
// we would have to do this work in order to calculate the syndromes
// if we save it, we can prevent the need to recalculate it on subsequent calls
// total memory usage is min_distance * block_length bytes e.g. 32 * 255 ~= 8k
rs->generator_root_exp = malloc(rs->min_distance * sizeof(field_logarithm_t *));
for (unsigned int i = 0; i < rs->min_distance; i++) {
rs->generator_root_exp[i] = malloc(rs->block_length * sizeof(field_logarithm_t));
polynomial_build_exp_lut(rs->field, rs->generator_roots[i], rs->block_length - 1, rs->generator_root_exp[i]);
}
// calculate and store the first min_distance powers of every element in the field
// we would have to do this for chien search anyway, and its size is only 256 * min_distance bytes
// for min_distance = 32 this is 8k of memory, a pittance for the speedup we receive in exchange
// we also get to reuse this work during error value calculation
rs->element_exp = malloc(256 * sizeof(field_logarithm_t *));
for (field_operation_t i = 0; i < 256; i++) {
rs->element_exp[i] = malloc(rs->min_distance * sizeof(field_logarithm_t));
polynomial_build_exp_lut(rs->field, i, rs->min_distance - 1, rs->element_exp[i]);
}
rs->init_from_roots_scratch[0] = polynomial_create(rs->min_distance);
rs->init_from_roots_scratch[1] = polynomial_create(rs->min_distance);
}
ssize_t correct_reed_solomon_decode(correct_reed_solomon *rs, const uint8_t *encoded, size_t encoded_length,
uint8_t *msg) {
if (encoded_length > rs->block_length) {
return -1;
}
// the message is the non-remainder part
size_t msg_length = encoded_length - rs->min_distance;
// if they handed us a nonfull block, we'll write in 0s
size_t pad_length = rs->block_length - encoded_length;
if (!rs->has_init_decode) {
// initialize rs for decoding
correct_reed_solomon_decoder_create(rs);
}
// we need to copy to our local buffer
// the buffer we're given has the coordinates in the wrong direction
// e.g. byte 0 corresponds to the 254th order coefficient
// so we're going to flip and then write padding
// the final copied buffer will look like
// | rem (rs->min_distance) | msg (msg_length) | pad (pad_length) |
for (unsigned int i = 0; i < encoded_length; i++) {
rs->received_polynomial.coeff[i] = encoded[encoded_length - (i + 1)];
}
// fill the pad_length with 0s
for (unsigned int i = 0; i < pad_length; i++) {
rs->received_polynomial.coeff[i + encoded_length] = 0;
}
bool all_zero = reed_solomon_find_syndromes(rs->field, rs->received_polynomial, rs->generator_root_exp,
rs->syndromes, rs->min_distance);
if (all_zero) {
// syndromes were all zero, so there was no error in the message
// copy to msg and we are done
for (unsigned int i = 0; i < msg_length; i++) {
msg[i] = rs->received_polynomial.coeff[encoded_length - (i + 1)];
}
return msg_length;
}
unsigned int order = reed_solomon_find_error_locator(rs, 0);
// XXX fix this vvvv
rs->error_locator.order = order;
for (unsigned int i = 0; i <= rs->error_locator.order; i++) {
// this is a little strange since the coeffs are logs, not elements
// also, we'll be storing log(0) = 0 for any 0 coeffs in the error locator
// that would seem bad but we'll just be using this in chien search, and we'll skip all 0 coeffs
// (you might point out that log(1) also = 0, which would seem to alias. however, that's ok,
// because log(1) = 255 as well, and in fact that's how it's represented in our log table)
rs->error_locator_log.coeff[i] = rs->field.log[rs->error_locator.coeff[i]];
}
rs->error_locator_log.order = rs->error_locator.order;
if (!reed_solomon_factorize_error_locator(rs->field, 0, rs->error_locator_log, rs->error_roots, rs->element_exp)) {
// roots couldn't be found, so there were too many errors to deal with
// RS has failed for this message
return -1;
}
reed_solomon_find_error_locations(rs->field, rs->generator_root_gap, rs->error_roots, rs->error_locations,
rs->error_locator.order, 0);
reed_solomon_find_error_values(rs);
for (unsigned int i = 0; i < rs->error_locator.order; i++) {
rs->received_polynomial.coeff[rs->error_locations[i]] =
field_sub(rs->field, rs->received_polynomial.coeff[rs->error_locations[i]], rs->error_vals[i]);
}
for (unsigned int i = 0; i < msg_length; i++) {
msg[i] = rs->received_polynomial.coeff[encoded_length - (i + 1)];
}
return msg_length;
}
ssize_t correct_reed_solomon_decode_with_erasures(correct_reed_solomon *rs, const uint8_t *encoded,
size_t encoded_length, const uint8_t *erasure_locations,
size_t erasure_length, uint8_t *msg) {
if (!erasure_length) {
return correct_reed_solomon_decode(rs, encoded, encoded_length, msg);
}
if (encoded_length > rs->block_length) {
return -1;
}
if (erasure_length > rs->min_distance) {
return -1;
}
// the message is the non-remainder part
size_t msg_length = encoded_length - rs->min_distance;
// if they handed us a nonfull block, we'll write in 0s
size_t pad_length = rs->block_length - encoded_length;
if (!rs->has_init_decode) {
// initialize rs for decoding
correct_reed_solomon_decoder_create(rs);
}
// we need to copy to our local buffer
// the buffer we're given has the coordinates in the wrong direction
// e.g. byte 0 corresponds to the 254th order coefficient
// so we're going to flip and then write padding
// the final copied buffer will look like
// | rem (rs->min_distance) | msg (msg_length) | pad (pad_length) |
for (unsigned int i = 0; i < encoded_length; i++) {
rs->received_polynomial.coeff[i] = encoded[encoded_length - (i + 1)];
}
// fill the pad_length with 0s
for (unsigned int i = 0; i < pad_length; i++) {
rs->received_polynomial.coeff[i + encoded_length] = 0;
}
for (unsigned int i = 0; i < erasure_length; i++) {
// remap the coordinates of the erasures
rs->error_locations[i] = rs->block_length - (erasure_locations[i] + pad_length + 1);
}
reed_solomon_find_error_roots_from_locations(rs->field, rs->generator_root_gap, rs->error_locations,
rs->error_roots, erasure_length);
rs->erasure_locator =
reed_solomon_find_error_locator_from_roots(rs->field, erasure_length, rs->error_roots, rs->erasure_locator, rs->init_from_roots_scratch);
bool all_zero = reed_solomon_find_syndromes(rs->field, rs->received_polynomial, rs->generator_root_exp,
rs->syndromes, rs->min_distance);
if (all_zero) {
// syndromes were all zero, so there was no error in the message
// copy to msg and we are done
for (unsigned int i = 0; i < msg_length; i++) {
msg[i] = rs->received_polynomial.coeff[encoded_length - (i + 1)];
}
return msg_length;
}
reed_solomon_find_modified_syndromes(rs, rs->syndromes, rs->erasure_locator, rs->modified_syndromes);
field_element_t *syndrome_copy = malloc(rs->min_distance * sizeof(field_element_t));
memcpy(syndrome_copy, rs->syndromes, rs->min_distance * sizeof(field_element_t));
for (unsigned int i = erasure_length; i < rs->min_distance; i++) {
rs->syndromes[i - erasure_length] = rs->modified_syndromes[i];
}
unsigned int order = reed_solomon_find_error_locator(rs, erasure_length);
// XXX fix this vvvv
rs->error_locator.order = order;
for (unsigned int i = 0; i <= rs->error_locator.order; i++) {
// this is a little strange since the coeffs are logs, not elements
// also, we'll be storing log(0) = 0 for any 0 coeffs in the error locator
// that would seem bad but we'll just be using this in chien search, and we'll skip all 0 coeffs
// (you might point out that log(1) also = 0, which would seem to alias. however, that's ok,
// because log(1) = 255 as well, and in fact that's how it's represented in our log table)
rs->error_locator_log.coeff[i] = rs->field.log[rs->error_locator.coeff[i]];
}
rs->error_locator_log.order = rs->error_locator.order;
/*
for (unsigned int i = 0; i < erasure_length; i++) {
rs->error_roots[i] = field_div(rs->field, 1, rs->error_roots[i]);
}
*/
if (!reed_solomon_factorize_error_locator(rs->field, erasure_length, rs->error_locator_log, rs->error_roots, rs->element_exp)) {
// roots couldn't be found, so there were too many errors to deal with
// RS has failed for this message
free(syndrome_copy);
return -1;
}
polynomial_t temp_poly = polynomial_create(rs->error_locator.order + erasure_length);
polynomial_mul(rs->field, rs->erasure_locator, rs->error_locator, temp_poly);
polynomial_t placeholder_poly = rs->error_locator;
rs->error_locator = temp_poly;
reed_solomon_find_error_locations(rs->field, rs->generator_root_gap, rs->error_roots, rs->error_locations,
rs->error_locator.order, erasure_length);
memcpy(rs->syndromes, syndrome_copy, rs->min_distance * sizeof(field_element_t));
reed_solomon_find_error_values(rs);
for (unsigned int i = 0; i < rs->error_locator.order; i++) {
rs->received_polynomial.coeff[rs->error_locations[i]] =
field_sub(rs->field, rs->received_polynomial.coeff[rs->error_locations[i]], rs->error_vals[i]);
}
rs->error_locator = placeholder_poly;
for (unsigned int i = 0; i < msg_length; i++) {
msg[i] = rs->received_polynomial.coeff[encoded_length - (i + 1)];
}
polynomial_destroy(temp_poly);
free(syndrome_copy);
return msg_length;
}

View File

@ -0,0 +1,34 @@
#include "correct/reed-solomon/encode.h"
ssize_t correct_reed_solomon_encode(correct_reed_solomon *rs, const uint8_t *msg, size_t msg_length, uint8_t *encoded) {
if (msg_length > rs->message_length) {
return -1;
}
size_t pad_length = rs->message_length - msg_length;
for (unsigned int i = 0; i < msg_length; i++) {
// message goes from high order to low order but libcorrect polynomials go low to high
// so we reverse on the way in and on the way out
// we'd have to do a copy anyway so this reversal should be free
rs->encoded_polynomial.coeff[rs->encoded_polynomial.order - (i + pad_length)] = msg[i];
}
// 0-fill the rest of the coefficients -- this length will always be > 0
// because the order of this poly is block_length and the msg_length <= message_length
// e.g. 255 and 223
memset(rs->encoded_polynomial.coeff + (rs->encoded_polynomial.order + 1 - pad_length), 0, pad_length);
memset(rs->encoded_polynomial.coeff, 0, (rs->encoded_polynomial.order + 1 - rs->message_length));
polynomial_mod(rs->field, rs->encoded_polynomial, rs->generator, rs->encoded_remainder);
// now return byte order to highest order to lowest order
for (unsigned int i = 0; i < msg_length; i++) {
encoded[i] = rs->encoded_polynomial.coeff[rs->encoded_polynomial.order - (i + pad_length)];
}
for (unsigned int i = 0; i < rs->min_distance; i++) {
encoded[msg_length + i] = rs->encoded_remainder.coeff[rs->min_distance - (i + 1)];
}
return rs->block_length;
}

View File

@ -0,0 +1,255 @@
#include "correct/reed-solomon/polynomial.h"
polynomial_t polynomial_create(unsigned int order) {
polynomial_t polynomial;
polynomial.coeff = malloc(sizeof(field_element_t) * (order + 1));
polynomial.order = order;
return polynomial;
}
void polynomial_destroy(polynomial_t polynomial) {
free(polynomial.coeff);
}
// if you want a full multiplication, then make res.order = l.order + r.order
// but if you just care about a lower order, e.g. mul mod x^i, then you can select
// fewer coefficients
void polynomial_mul(field_t field, polynomial_t l, polynomial_t r, polynomial_t res) {
// perform an element-wise multiplication of two polynomials
memset(res.coeff, 0, sizeof(field_element_t) * (res.order + 1));
for (unsigned int i = 0; i <= l.order; i++) {
if (i > res.order) {
continue;
}
unsigned int j_limit = (r.order > res.order - i) ? res.order - i : r.order;
for (unsigned int j = 0; j <= j_limit; j++) {
// e.g. alpha^5*x * alpha^37*x^2 --> alpha^42*x^3
res.coeff[i + j] = field_add(field, res.coeff[i + j], field_mul(field, l.coeff[i], r.coeff[j]));
}
}
}
void polynomial_mod(field_t field, polynomial_t dividend, polynomial_t divisor, polynomial_t mod) {
// find the polynomial remainder of dividend mod divisor
// do long division and return just the remainder (written to mod)
if (mod.order < dividend.order) {
// mod.order must be >= dividend.order (scratch space needed)
// this is an error -- catch it in debug?
return;
}
// initialize remainder as dividend
memcpy(mod.coeff, dividend.coeff, sizeof(field_element_t) * (dividend.order + 1));
// XXX make sure divisor[divisor_order] is nonzero
field_logarithm_t divisor_leading = field.log[divisor.coeff[divisor.order]];
// long division steps along one order at a time, starting at the highest order
for (unsigned int i = dividend.order; i > 0; i--) {
// look at the leading coefficient of dividend and divisor
// if leading coefficient of dividend / leading coefficient of divisor is q
// then the next row of subtraction will be q * divisor
// if order of q < 0 then what we have is the remainder and we are done
if (i < divisor.order) {
break;
}
if (mod.coeff[i] == 0) {
continue;
}
unsigned int q_order = i - divisor.order;
field_logarithm_t q_coeff = field_div_log(field, field.log[mod.coeff[i]], divisor_leading);
// now that we've chosen q, multiply the divisor by q and subtract from
// our remainder. subtracting in GF(2^8) is XOR, just like addition
for (unsigned int j = 0; j <= divisor.order; j++) {
if (divisor.coeff[j] == 0) {
continue;
}
// all of the multiplication is shifted up by q_order places
mod.coeff[j + q_order] = field_add(field, mod.coeff[j + q_order],
field_mul_log_element(field, field.log[divisor.coeff[j]], q_coeff));
}
}
}
void polynomial_formal_derivative(field_t field, polynomial_t poly, polynomial_t der) {
// if f(x) = a(n)*x^n + ... + a(1)*x + a(0)
// then f'(x) = n*a(n)*x^(n-1) + ... + 2*a(2)*x + a(1)
// where n*a(n) = sum(k=1, n, a(n)) e.g. the nth sum of a(n) in GF(2^8)
// assumes der.order = poly.order - 1
memset(der.coeff, 0, sizeof(field_element_t) * (der.order + 1));
for (unsigned int i = 0; i <= der.order; i++) {
// we're filling in the ith power of der, so we look ahead one power in poly
// f(x) = a(i + 1)*x^(i + 1) -> f'(x) = (i + 1)*a(i + 1)*x^i
// where (i + 1)*a(i + 1) is the sum of a(i + 1) (i + 1) times, not the product
der.coeff[i] = field_sum(field, poly.coeff[i + 1], i + 1);
}
}
field_element_t polynomial_eval(field_t field, polynomial_t poly, field_element_t val) {
// evaluate the polynomial poly at a particular element val
if (val == 0) {
return poly.coeff[0];
}
field_element_t res = 0;
// we're going to start at 0th order and multiply by val each time
field_logarithm_t val_exponentiated = field.log[1];
field_logarithm_t val_log = field.log[val];
for (unsigned int i = 0; i <= poly.order; i++) {
if (poly.coeff[i] != 0) {
// multiply-accumulate by the next coeff times the next power of val
res = field_add(field, res,
field_mul_log_element(field, field.log[poly.coeff[i]], val_exponentiated));
}
// now advance to the next power
val_exponentiated = field_mul_log(field, val_exponentiated, val_log);
}
return res;
}
field_element_t polynomial_eval_lut(field_t field, polynomial_t poly, const field_logarithm_t *val_exp) {
// evaluate the polynomial poly at a particular element val
// in this case, all of the logarithms of the successive powers of val have been precalculated
// this removes the extra work we'd have to do to calculate val_exponentiated each time
// if this function is to be called on the same val multiple times
if (val_exp[0] == 0) {
return poly.coeff[0];
}
field_element_t res = 0;
for (unsigned int i = 0; i <= poly.order; i++) {
if (poly.coeff[i] != 0) {
// multiply-accumulate by the next coeff times the next power of val
res = field_add(field, res,
field_mul_log_element(field, field.log[poly.coeff[i]], val_exp[i]));
}
}
return res;
}
field_element_t polynomial_eval_log_lut(field_t field, polynomial_t poly_log, const field_logarithm_t *val_exp) {
// evaluate the log_polynomial poly at a particular element val
// like polynomial_eval_lut, the logarithms of the successive powers of val have been
// precomputed
if (val_exp[0] == 0) {
if (poly_log.coeff[0] == 0) {
// special case for the non-existant log case
return 0;
}
return field.exp[poly_log.coeff[0]];
}
field_element_t res = 0;
for (unsigned int i = 0; i <= poly_log.order; i++) {
// using 0 as a sentinel value in log -- log(0) is really -inf
if (poly_log.coeff[i] != 0) {
// multiply-accumulate by the next coeff times the next power of val
res = field_add(field, res,
field_mul_log_element(field, poly_log.coeff[i], val_exp[i]));
}
}
return res;
}
void polynomial_build_exp_lut(field_t field, field_element_t val, unsigned int order, field_logarithm_t *val_exp) {
// create the lookup table of successive powers of val used by polynomial_eval_lut
field_logarithm_t val_exponentiated = field.log[1];
field_logarithm_t val_log = field.log[val];
for (unsigned int i = 0; i <= order; i++) {
if (val == 0) {
val_exp[i] = 0;
} else {
val_exp[i] = val_exponentiated;
val_exponentiated = field_mul_log(field, val_exponentiated, val_log);
}
}
}
polynomial_t polynomial_init_from_roots(field_t field, unsigned int nroots, field_element_t *roots, polynomial_t poly, polynomial_t *scratch) {
unsigned int order = nroots;
polynomial_t l;
field_element_t l_coeff[2];
l.order = 1;
l.coeff = l_coeff;
// we'll keep two temporary stores of rightside polynomial
// each time through the loop, we take the previous result and use it as new rightside
// swap back and forth (prevents the need for a copy)
polynomial_t r[2];
r[0] = scratch[0];
r[1] = scratch[1];
unsigned int rcoeffres = 0;
// initialize the result with x + roots[0]
r[rcoeffres].coeff[1] = 1;
r[rcoeffres].coeff[0] = roots[0];
r[rcoeffres].order = 1;
// initialize lcoeff[1] with x
// we'll fill in the 0th order term in each loop iter
l.coeff[1] = 1;
// loop through, using previous run's result as the new right hand side
// this allows us to multiply one group at a time
for (unsigned int i = 1; i < nroots; i++) {
l.coeff[0] = roots[i];
unsigned int nextrcoeff = rcoeffres;
rcoeffres = (rcoeffres + 1) % 2;
r[rcoeffres].order = i + 1;
polynomial_mul(field, l, r[nextrcoeff], r[rcoeffres]);
}
memcpy(poly.coeff, r[rcoeffres].coeff, (order + 1) * sizeof(field_element_t));
poly.order = order;
return poly;
}
polynomial_t polynomial_create_from_roots(field_t field, unsigned int nroots, field_element_t *roots) {
polynomial_t poly = polynomial_create(nroots);
unsigned int order = nroots;
polynomial_t l;
l.order = 1;
l.coeff = calloc(2, sizeof(field_element_t));
polynomial_t r[2];
// we'll keep two temporary stores of rightside polynomial
// each time through the loop, we take the previous result and use it as new rightside
// swap back and forth (prevents the need for a copy)
r[0].coeff = calloc(order + 1, sizeof(field_element_t));
r[1].coeff = calloc(order + 1, sizeof(field_element_t));
unsigned int rcoeffres = 0;
// initialize the result with x + roots[0]
r[rcoeffres].coeff[0] = roots[0];
r[rcoeffres].coeff[1] = 1;
r[rcoeffres].order = 1;
// initialize lcoeff[1] with x
// we'll fill in the 0th order term in each loop iter
l.coeff[1] = 1;
// loop through, using previous run's result as the new right hand side
// this allows us to multiply one group at a time
for (unsigned int i = 1; i < nroots; i++) {
l.coeff[0] = roots[i];
unsigned int nextrcoeff = rcoeffres;
rcoeffres = (rcoeffres + 1) % 2;
r[rcoeffres].order = i + 1;
polynomial_mul(field, l, r[nextrcoeff], r[rcoeffres]);
}
memcpy(poly.coeff, r[rcoeffres].coeff, (order + 1) * sizeof(field_element_t));
poly.order = order;
free(l.coeff);
free(r[0].coeff);
free(r[1].coeff);
return poly;
}

View File

@ -0,0 +1,187 @@
#include "correct/reed-solomon/reed-solomon.h"
// coeff must be of size nroots + 1
// e.g. 2 roots (x + alpha)(x + alpha^2) yields a poly with 3 terms x^2 + g0*x + g1
static polynomial_t reed_solomon_build_generator(field_t field, unsigned int nroots, field_element_t first_consecutive_root, unsigned int root_gap, polynomial_t generator, field_element_t *roots) {
// generator has order 2*t
// of form (x + alpha^1)(x + alpha^2)...(x - alpha^2*t)
for (unsigned int i = 0; i < nroots; i++) {
roots[i] = field.exp[(root_gap * (i + first_consecutive_root)) % 255];
}
return polynomial_create_from_roots(field, nroots, roots);
}
correct_reed_solomon *correct_reed_solomon_create(field_operation_t primitive_polynomial, field_logarithm_t first_consecutive_root, field_logarithm_t generator_root_gap, size_t num_roots) {
correct_reed_solomon *rs = calloc(1, sizeof(correct_reed_solomon));
rs->field = field_create(primitive_polynomial);
rs->block_length = 255;
rs->min_distance = num_roots;
rs->message_length = rs->block_length - rs->min_distance;
rs->first_consecutive_root = first_consecutive_root;
rs->generator_root_gap = generator_root_gap;
rs->generator_roots = malloc(rs->min_distance * sizeof(field_element_t));
rs->generator = reed_solomon_build_generator(rs->field, rs->min_distance, rs->first_consecutive_root, rs->generator_root_gap, rs->generator, rs->generator_roots);
rs->encoded_polynomial = polynomial_create(rs->block_length - 1);
rs->encoded_remainder = polynomial_create(rs->block_length - 1);
rs->has_init_decode = false;
return rs;
}
void correct_reed_solomon_destroy(correct_reed_solomon *rs) {
field_destroy(rs->field);
polynomial_destroy(rs->generator);
free(rs->generator_roots);
polynomial_destroy(rs->encoded_polynomial);
polynomial_destroy(rs->encoded_remainder);
if (rs->has_init_decode) {
free(rs->syndromes);
free(rs->modified_syndromes);
polynomial_destroy(rs->received_polynomial);
polynomial_destroy(rs->error_locator);
polynomial_destroy(rs->error_locator_log);
polynomial_destroy(rs->erasure_locator);
free(rs->error_roots);
free(rs->error_vals);
free(rs->error_locations);
polynomial_destroy(rs->last_error_locator);
polynomial_destroy(rs->error_evaluator);
polynomial_destroy(rs->error_locator_derivative);
for (unsigned int i = 0; i < rs->min_distance; i++) {
free(rs->generator_root_exp[i]);
}
free(rs->generator_root_exp);
for (field_operation_t i = 0; i < 256; i++) {
free(rs->element_exp[i]);
}
free(rs->element_exp);
polynomial_destroy(rs->init_from_roots_scratch[0]);
polynomial_destroy(rs->init_from_roots_scratch[1]);
}
free(rs);
}
void correct_reed_solomon_debug_print(correct_reed_solomon *rs) {
for (unsigned int i = 0; i < 256; i++) {
printf("%3d %3d %3d %3d\n", i, rs->field.exp[i], i, rs->field.log[i]);
}
printf("\n");
printf("roots: ");
for (unsigned int i = 0; i < rs->min_distance; i++) {
printf("%d", rs->generator_roots[i]);
if (i < rs->min_distance - 1) {
printf(", ");
}
}
printf("\n\n");
printf("generator: ");
for (unsigned int i = 0; i < rs->generator.order + 1; i++) {
printf("%d*x^%d", rs->generator.coeff[i], i);
if (i < rs->generator.order) {
printf(" + ");
}
}
printf("\n\n");
printf("generator (alpha format): ");
for (unsigned int i = rs->generator.order + 1; i > 0; i--) {
printf("alpha^%d*x^%d", rs->field.log[rs->generator.coeff[i - 1]], i - 1);
if (i > 1) {
printf(" + ");
}
}
printf("\n\n");
printf("remainder: ");
bool has_printed = false;
for (unsigned int i = 0; i < rs->encoded_remainder.order + 1; i++) {
if (!rs->encoded_remainder.coeff[i]) {
continue;
}
if (has_printed) {
printf(" + ");
}
has_printed = true;
printf("%d*x^%d", rs->encoded_remainder.coeff[i], i);
}
printf("\n\n");
printf("syndromes: ");
for (unsigned int i = 0; i < rs->min_distance; i++) {
printf("%d", rs->syndromes[i]);
if (i < rs->min_distance - 1) {
printf(", ");
}
}
printf("\n\n");
printf("numerrors: %d\n\n", rs->error_locator.order);
printf("error locator: ");
has_printed = false;
for (unsigned int i = 0; i < rs->error_locator.order + 1; i++) {
if (!rs->error_locator.coeff[i]) {
continue;
}
if (has_printed) {
printf(" + ");
}
has_printed = true;
printf("%d*x^%d", rs->error_locator.coeff[i], i);
}
printf("\n\n");
printf("error roots: ");
for (unsigned int i = 0; i < rs->error_locator.order; i++) {
printf("%d@%d", polynomial_eval(rs->field, rs->error_locator, rs->error_roots[i]), rs->error_roots[i]);
if (i < rs->error_locator.order - 1) {
printf(", ");
}
}
printf("\n\n");
printf("error evaluator: ");
has_printed = false;
for (unsigned int i = 0; i < rs->error_evaluator.order; i++) {
if (!rs->error_evaluator.coeff[i]) {
continue;
}
if (has_printed) {
printf(" + ");
}
has_printed = true;
printf("%d*x^%d", rs->error_evaluator.coeff[i], i);
}
printf("\n\n");
printf("error locator derivative: ");
has_printed = false;
for (unsigned int i = 0; i < rs->error_locator_derivative.order; i++) {
if (!rs->error_locator_derivative.coeff[i]) {
continue;
}
if (has_printed) {
printf(" + ");
}
has_printed = true;
printf("%d*x^%d", rs->error_locator_derivative.coeff[i], i);
}
printf("\n\n");
printf("error locator: ");
for (unsigned int i = 0; i < rs->error_locator.order; i++) {
printf("%d@%d", rs->error_vals[i], rs->error_locations[i]);
if (i < rs->error_locator.order - 1) {
printf(", ");
}
}
printf("\n\n");
}

View File

@ -0,0 +1,54 @@
include_directories("include")
add_executable(convolutional_test_runner EXCLUDE_FROM_ALL convolutional.c $<TARGET_OBJECTS:error_sim>)
target_link_libraries(convolutional_test_runner correct_static "${LIBM}")
set_target_properties(convolutional_test_runner PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/tests")
add_test(NAME convolutional_test WORKING_DIRECTORY "${CMAKE_BINARY_DIR}/tests" COMMAND convolutional_test_runner)
set(all_test_runners ${all_test_runners} convolutional_test_runner)
if(HAVE_SSE)
add_executable(convolutional_sse_test_runner EXCLUDE_FROM_ALL convolutional-sse.c $<TARGET_OBJECTS:error_sim_sse>)
target_link_libraries(convolutional_sse_test_runner correct_static "${LIBM}")
set_target_properties(convolutional_sse_test_runner PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/tests")
add_test(NAME convolutional_sse_test WORKING_DIRECTORY "${CMAKE_BINARY_DIR}/tests" COMMAND convolutional_sse_test_runner)
set(all_test_runners ${all_test_runners} convolutional_sse_test_runner)
endif()
if(HAVE_LIBFEC)
add_executable(convolutional_fec_test_runner EXCLUDE_FROM_ALL convolutional-fec.c $<TARGET_OBJECTS:error_sim_fec>)
target_link_libraries(convolutional_fec_test_runner correct_static FEC "${LIBM}")
set_target_properties(convolutional_fec_test_runner PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/tests")
add_test(NAME convolutional_fec_test WORKING_DIRECTORY "${CMAKE_BINARY_DIR}/tests" COMMAND convolutional_fec_test_runner)
set(all_test_runners ${all_test_runners} convolutional_fec_test_runner)
endif()
add_executable(convolutional_shim_test_runner EXCLUDE_FROM_ALL convolutional-shim.c $<TARGET_OBJECTS:error_sim_shim>)
target_link_libraries(convolutional_shim_test_runner correct_static fec_shim_static "${LIBM}")
set_target_properties(convolutional_shim_test_runner PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/tests")
add_test(NAME convolutional_shim_test WORKING_DIRECTORY "${CMAKE_BINARY_DIR}/tests" COMMAND convolutional_shim_test_runner)
set(all_test_runners ${all_test_runners} convolutional_shim_test_runner)
add_executable(reed_solomon_test_runner EXCLUDE_FROM_ALL reed-solomon.c rs_tester.c)
target_link_libraries(reed_solomon_test_runner correct_static "${LIBM}")
set_target_properties(reed_solomon_test_runner PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/tests")
add_test(NAME reed_solomon_test WORKING_DIRECTORY "${CMAKE_BINARY_DIR}/tests" COMMAND reed_solomon_test_runner)
set(all_test_runners ${all_test_runners} reed_solomon_test_runner)
if(HAVE_LIBFEC)
add_executable(reed_solomon_interop_test_runner EXCLUDE_FROM_ALL reed-solomon-fec-interop.c rs_tester.c rs_tester_fec.c)
target_link_libraries(reed_solomon_interop_test_runner correct_static FEC "${LIBM}")
set_target_properties(reed_solomon_interop_test_runner PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/tests")
add_test(NAME reed_solomon_interop_test WORKING_DIRECTORY "${CMAKE_BINARY_DIR}/tests" COMMAND reed_solomon_interop_test_runner)
set(all_test_runners ${all_test_runners} reed_solomon_interop_test_runner)
endif()
add_executable(reed_solomon_shim_interop_test_runner EXCLUDE_FROM_ALL reed-solomon-shim-interop.c rs_tester.c rs_tester_fec_shim.c)
target_link_libraries(reed_solomon_shim_interop_test_runner correct_static fec_shim_static "${LIBM}")
set_target_properties(reed_solomon_shim_interop_test_runner PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/tests")
add_test(NAME reed_solomon_shim_interop_test WORKING_DIRECTORY "${CMAKE_BINARY_DIR}/tests" COMMAND reed_solomon_shim_interop_test_runner)
set(all_test_runners ${all_test_runners} reed_solomon_shim_interop_test_runner)
add_custom_target(test_runners DEPENDS ${all_test_runners})
add_custom_target(check COMMAND ${CMAKE_CTEST_COMMAND} DEPENDS test_runners)
enable_testing()

View File

@ -0,0 +1,123 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <fec.h>
#include "correct.h"
#include "correct/util/error-sim-fec.h"
size_t max_block_len = 4096;
size_t test_conv(correct_convolutional *conv, void *fec,
void (*decode)(void *, uint8_t *, size_t, uint8_t *),
conv_testbench **testbench_ptr, size_t msg_len, double eb_n0,
double bpsk_bit_energy, double bpsk_voltage) {
uint8_t *msg = malloc(max_block_len);
size_t num_errors = 0;
while (msg_len) {
size_t block_len = (max_block_len < msg_len) ? max_block_len : msg_len;
msg_len -= block_len;
for (unsigned int j = 0; j < block_len; j++) {
msg[j] = rand() % 256;
}
*testbench_ptr =
resize_conv_testbench(*testbench_ptr, conv_correct_enclen, conv, block_len);
conv_testbench *testbench = *testbench_ptr;
testbench->encoder = conv;
testbench->encode = conv_correct_encode;
testbench->decoder = fec;
testbench->decode = decode;
build_white_noise(testbench->noise, testbench->enclen, eb_n0, bpsk_bit_energy);
num_errors += test_conv_noise(testbench, msg, block_len, bpsk_voltage);
}
free(msg);
return num_errors;
}
void assert_test_result(correct_convolutional *conv, void *fec,
void (*decode)(void *, uint8_t *, size_t, uint8_t *),
conv_testbench **testbench, size_t test_length, size_t rate, size_t order,
double eb_n0, double error_rate) {
double bpsk_voltage = 1.0 / sqrt(2.0);
double bpsk_sym_energy = 2 * pow(bpsk_voltage, 2.0);
double bpsk_bit_energy = bpsk_sym_energy * rate;
size_t error_count =
test_conv(conv, fec, decode, testbench, test_length, eb_n0, bpsk_bit_energy, bpsk_voltage);
double observed_error_rate = error_count / ((double)test_length * 8);
if (observed_error_rate > error_rate) {
printf(
"test failed, expected error rate=%.2e, observed error rate=%.2e @%.1fdB for rate %zu "
"order %zu\n",
error_rate, observed_error_rate, eb_n0, rate, order);
exit(1);
} else {
printf(
"test passed, expected error rate=%.2e, observed error rate=%.2e @%.1fdB for rate %zu "
"order %zu\n",
error_rate, observed_error_rate, eb_n0, rate, order);
}
}
int main() {
srand(time(NULL));
conv_testbench *testbench = NULL;
correct_convolutional *conv;
void *fec;
uint16_t *poly;
poly = (uint16_t[]){V27POLYA, V27POLYB};
conv = correct_convolutional_create(2, 7, poly);
fec = create_viterbi27(8 * max_block_len);
assert_test_result(conv, fec, conv_fec27_decode, &testbench, 1000000, 2, 6, INFINITY, 0);
assert_test_result(conv, fec, conv_fec27_decode, &testbench, 1000000, 2, 6, 4.5, 8e-06);
assert_test_result(conv, fec, conv_fec27_decode, &testbench, 1000000, 2, 6, 4.0, 5e-05);
delete_viterbi27(fec);
correct_convolutional_destroy(conv);
printf("\n");
poly = (uint16_t[]){V29POLYA, V29POLYB};
conv = correct_convolutional_create(2, 9, poly);
fec = create_viterbi29(8 * max_block_len);
assert_test_result(conv, fec, conv_fec29_decode, &testbench, 1000000, 2, 9, INFINITY, 0);
assert_test_result(conv, fec, conv_fec29_decode, &testbench, 1000000, 2, 9, 4.5, 3e-06);
assert_test_result(conv, fec, conv_fec29_decode, &testbench, 1000000, 2, 9, 4.0, 8e-06);
delete_viterbi29(fec);
correct_convolutional_destroy(conv);
printf("\n");
poly = (uint16_t[]){V39POLYA, V39POLYB, V39POLYC};
conv = correct_convolutional_create(3, 9, poly);
fec = create_viterbi39(8 * max_block_len);
assert_test_result(conv, fec, conv_fec39_decode, &testbench, 1000000, 3, 9, INFINITY, 0);
assert_test_result(conv, fec, conv_fec39_decode, &testbench, 1000000, 3, 9, 4.5, 3e-06);
assert_test_result(conv, fec, conv_fec39_decode, &testbench, 1000000, 3, 9, 4.0, 5e-06);
delete_viterbi39(fec);
correct_convolutional_destroy(conv);
printf("\n");
poly = (uint16_t[]){V615POLYA, V615POLYB, V615POLYC, V615POLYD, V615POLYE, V615POLYF};
conv = correct_convolutional_create(6, 15, poly);
fec = create_viterbi615(8 * max_block_len);
assert_test_result(conv, fec, conv_fec615_decode, &testbench, 100000, 6, 15, INFINITY, 0);
assert_test_result(conv, fec, conv_fec615_decode, &testbench, 100000, 6, 15, 3.0, 3e-06);
assert_test_result(conv, fec, conv_fec615_decode, &testbench, 100000, 6, 15, 2.5, 1e-05);
delete_viterbi615(fec);
correct_convolutional_destroy(conv);
printf("\n");
free_scratch(testbench);
return 0;
}

View File

@ -0,0 +1,122 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include "correct.h"
#include "fec_shim.h"
#include "correct/util/error-sim-shim.h"
size_t max_block_len = 4096;
size_t test_conv(correct_convolutional *conv, void *fec,
ssize_t (*decode)(void *, uint8_t *, size_t, uint8_t *),
conv_testbench **testbench_ptr, size_t msg_len, double eb_n0,
double bpsk_bit_energy, double bpsk_voltage) {
uint8_t *msg = malloc(max_block_len);
size_t num_errors = 0;
while (msg_len) {
size_t block_len = (max_block_len < msg_len) ? max_block_len : msg_len;
msg_len -= block_len;
for (unsigned int j = 0; j < block_len; j++) {
msg[j] = rand() % 256;
}
*testbench_ptr =
resize_conv_testbench(*testbench_ptr, conv_correct_enclen, conv, block_len);
conv_testbench *testbench = *testbench_ptr;
testbench->encoder = conv;
testbench->encode = conv_correct_encode;
testbench->decoder = fec;
testbench->decode = decode;
build_white_noise(testbench->noise, testbench->enclen, eb_n0, bpsk_bit_energy);
num_errors += test_conv_noise(testbench, msg, block_len, bpsk_voltage);
}
free(msg);
return num_errors;
}
void assert_test_result(correct_convolutional *conv, void *fec,
ssize_t (*decode)(void *, uint8_t *, size_t, uint8_t *),
conv_testbench **testbench, size_t test_length, size_t rate, size_t order,
double eb_n0, double error_rate) {
double bpsk_voltage = 1.0 / sqrt(2.0);
double bpsk_sym_energy = 2 * pow(bpsk_voltage, 2.0);
double bpsk_bit_energy = bpsk_sym_energy * rate;
size_t error_count =
test_conv(conv, fec, decode, testbench, test_length, eb_n0, bpsk_bit_energy, bpsk_voltage);
double observed_error_rate = error_count / ((double)test_length * 8);
if (observed_error_rate > error_rate) {
printf(
"test failed, expected error rate=%.2e, observed error rate=%.2e @%.1fdB for rate %zu "
"order %zu\n",
error_rate, observed_error_rate, eb_n0, rate, order);
exit(1);
} else {
printf(
"test passed, expected error rate=%.2e, observed error rate=%.2e @%.1fdB for rate %zu "
"order %zu\n",
error_rate, observed_error_rate, eb_n0, rate, order);
}
}
int main() {
srand(time(NULL));
conv_testbench *testbench = NULL;
correct_convolutional *conv;
void *fec;
uint16_t *poly;
poly = (uint16_t[]){V27POLYA, V27POLYB};
conv = correct_convolutional_create(2, 7, poly);
fec = create_viterbi27(8 * max_block_len);
assert_test_result(conv, fec, conv_shim27_decode, &testbench, 1000000, 2, 6, INFINITY, 0);
assert_test_result(conv, fec, conv_shim27_decode, &testbench, 1000000, 2, 6, 4.5, 8e-06);
assert_test_result(conv, fec, conv_shim27_decode, &testbench, 1000000, 2, 6, 4.0, 5e-05);
delete_viterbi27(fec);
correct_convolutional_destroy(conv);
printf("\n");
poly = (uint16_t[]){V29POLYA, V29POLYB};
conv = correct_convolutional_create(2, 9, poly);
fec = create_viterbi29(8 * max_block_len);
assert_test_result(conv, fec, conv_shim29_decode, &testbench, 1000000, 2, 9, INFINITY, 0);
assert_test_result(conv, fec, conv_shim29_decode, &testbench, 1000000, 2, 9, 4.5, 3e-06);
assert_test_result(conv, fec, conv_shim29_decode, &testbench, 1000000, 2, 9, 4.0, 8e-06);
delete_viterbi29(fec);
correct_convolutional_destroy(conv);
printf("\n");
poly = (uint16_t[]){V39POLYA, V39POLYB, V39POLYC};
conv = correct_convolutional_create(3, 9, poly);
fec = create_viterbi39(8 * max_block_len);
assert_test_result(conv, fec, conv_shim39_decode, &testbench, 1000000, 3, 9, INFINITY, 0);
assert_test_result(conv, fec, conv_shim39_decode, &testbench, 1000000, 3, 9, 4.5, 3e-06);
assert_test_result(conv, fec, conv_shim39_decode, &testbench, 1000000, 3, 9, 4.0, 9e-06);
delete_viterbi39(fec);
correct_convolutional_destroy(conv);
printf("\n");
poly = (uint16_t[]){V615POLYA, V615POLYB, V615POLYC, V615POLYD, V615POLYE, V615POLYF};
conv = correct_convolutional_create(6, 15, poly);
fec = create_viterbi615(8 * max_block_len);
assert_test_result(conv, fec, conv_shim615_decode, &testbench, 100000, 6, 15, INFINITY, 0);
assert_test_result(conv, fec, conv_shim615_decode, &testbench, 100000, 6, 15, 3.0, 2e-05);
assert_test_result(conv, fec, conv_shim615_decode, &testbench, 100000, 6, 15, 2.5, 4e-05);
delete_viterbi615(fec);
correct_convolutional_destroy(conv);
printf("\n");
free_scratch(testbench);
return 0;
}

View File

@ -0,0 +1,132 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include "correct/util/error-sim-sse.h"
size_t max_block_len = 4096;
size_t test_conv(correct_convolutional_sse *conv, conv_testbench **testbench_ptr,
size_t msg_len, double eb_n0, double bpsk_bit_energy,
double bpsk_voltage) {
uint8_t *msg = malloc(max_block_len);
size_t num_errors = 0;
while (msg_len) {
size_t block_len = (max_block_len < msg_len) ? max_block_len : msg_len;
msg_len -= block_len;
for (unsigned int j = 0; j < block_len; j++) {
msg[j] = rand() % 256;
}
*testbench_ptr = resize_conv_testbench(*testbench_ptr, conv_correct_sse_enclen, conv, block_len);
conv_testbench *testbench = *testbench_ptr;
testbench->encoder = conv;
testbench->encode = conv_correct_sse_encode;
testbench->decoder = conv;
testbench->decode = conv_correct_sse_decode;
build_white_noise(testbench->noise, testbench->enclen, eb_n0, bpsk_bit_energy);
num_errors += test_conv_noise(testbench, msg, block_len, bpsk_voltage);
}
free(msg);
return num_errors;
}
void assert_test_result(correct_convolutional_sse *conv, conv_testbench **testbench,
size_t test_length, size_t rate, size_t order, double eb_n0, double error_rate) {
double bpsk_voltage = 1.0/sqrt(2.0);
double bpsk_sym_energy = 2*pow(bpsk_voltage, 2.0);
double bpsk_bit_energy = bpsk_sym_energy * rate;
size_t error_count = test_conv(conv, testbench, test_length, eb_n0, bpsk_bit_energy, bpsk_voltage);
double observed_error_rate = error_count/((double)test_length * 8);
if (observed_error_rate > error_rate) {
printf("test failed, expected error rate=%.2e, observed error rate=%.2e @%.1fdB for rate %zu order %zu\n",
error_rate, observed_error_rate, eb_n0, rate, order);
exit(1);
} else {
printf("test passed, expected error rate=%.2e, observed error rate=%.2e @%.1fdB for rate %zu order %zu\n",
error_rate, observed_error_rate, eb_n0, rate, order);
}
}
int main() {
srand(time(NULL));
conv_testbench *testbench = NULL;
correct_convolutional_sse *conv;
// n.b. the error rates below are at 5.0dB/4.5dB for order 6 polys
// and 4.5dB/4.0dB for order 7-9 polys. this can be easy to miss.
conv = correct_convolutional_sse_create(2, 6, correct_conv_r12_6_polynomial);
assert_test_result(conv, &testbench, 1000000, 2, 6, INFINITY, 0);
assert_test_result(conv, &testbench, 1000000, 2, 6, 5.0, 8e-06);
assert_test_result(conv, &testbench, 1000000, 2, 6, 4.5, 3e-05);
correct_convolutional_sse_destroy(conv);
printf("\n");
conv = correct_convolutional_sse_create(2, 7, correct_conv_r12_7_polynomial);
assert_test_result(conv, &testbench, 1000000, 2, 7, INFINITY, 0);
assert_test_result(conv, &testbench, 1000000, 2, 7, 4.5, 1e-05);
assert_test_result(conv, &testbench, 1000000, 2, 7, 4.0, 5e-05);
correct_convolutional_sse_destroy(conv);
printf("\n");
conv = correct_convolutional_sse_create(2, 8, correct_conv_r12_8_polynomial);
assert_test_result(conv, &testbench, 1000000, 2, 8, INFINITY, 0);
assert_test_result(conv, &testbench, 1000000, 2, 8, 4.5, 5e-06);
assert_test_result(conv, &testbench, 1000000, 2, 8, 4.0, 3e-05);
correct_convolutional_sse_destroy(conv);
printf("\n");
conv = correct_convolutional_sse_create(2, 9, correct_conv_r12_9_polynomial);
assert_test_result(conv, &testbench, 1000000, 2, 9, INFINITY, 0);
assert_test_result(conv, &testbench, 1000000, 2, 9, 4.5, 3e-06);
assert_test_result(conv, &testbench, 1000000, 2, 9, 4.0, 8e-06);
correct_convolutional_sse_destroy(conv);
printf("\n");
conv = correct_convolutional_sse_create(3, 6, correct_conv_r13_6_polynomial);
assert_test_result(conv, &testbench, 1000000, 3, 6, INFINITY, 0);
assert_test_result(conv, &testbench, 1000000, 3, 6, 5.0, 5e-06);
assert_test_result(conv, &testbench, 1000000, 3, 6, 4.5, 2e-05);
correct_convolutional_sse_destroy(conv);
printf("\n");
conv = correct_convolutional_sse_create(3, 7, correct_conv_r13_7_polynomial);
assert_test_result(conv, &testbench, 1000000, 3, 7, INFINITY, 0);
assert_test_result(conv, &testbench, 1000000, 3, 7, 4.5, 5e-06);
assert_test_result(conv, &testbench, 1000000, 3, 7, 4.0, 3e-05);
correct_convolutional_sse_destroy(conv);
printf("\n");
conv = correct_convolutional_sse_create(3, 8, correct_conv_r13_8_polynomial);
assert_test_result(conv, &testbench, 1000000, 3, 8, INFINITY, 0);
assert_test_result(conv, &testbench, 1000000, 3, 8, 4.5, 4e-06);
assert_test_result(conv, &testbench, 1000000, 3, 8, 4.0, 1e-05);
correct_convolutional_sse_destroy(conv);
printf("\n");
conv = correct_convolutional_sse_create(3, 9, correct_conv_r13_9_polynomial);
assert_test_result(conv, &testbench, 1000000, 3, 9, INFINITY, 0);
assert_test_result(conv, &testbench, 1000000, 3, 9, 4.5, 3e-06);
assert_test_result(conv, &testbench, 1000000, 3, 9, 4.0, 5e-06);
correct_convolutional_sse_destroy(conv);
printf("\n");
free_scratch(testbench);
return 0;
}

View File

@ -0,0 +1,133 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include "correct.h"
#include "correct/util/error-sim.h"
size_t max_block_len = 4096;
size_t test_conv(correct_convolutional *conv, conv_testbench **testbench_ptr,
size_t msg_len, double eb_n0, double bpsk_bit_energy,
double bpsk_voltage) {
uint8_t *msg = malloc(max_block_len);
size_t num_errors = 0;
while (msg_len) {
size_t block_len = (max_block_len < msg_len) ? max_block_len : msg_len;
msg_len -= block_len;
for (unsigned int j = 0; j < block_len; j++) {
msg[j] = rand() % 256;
}
*testbench_ptr = resize_conv_testbench(*testbench_ptr, conv_correct_enclen, conv, block_len);
conv_testbench *testbench = *testbench_ptr;
testbench->encoder = conv;
testbench->encode = conv_correct_encode;
testbench->decoder = conv;
testbench->decode = conv_correct_decode;
build_white_noise(testbench->noise, testbench->enclen, eb_n0, bpsk_bit_energy);
num_errors += test_conv_noise(testbench, msg, block_len, bpsk_voltage);
}
free(msg);
return num_errors;
}
void assert_test_result(correct_convolutional *conv, conv_testbench **testbench,
size_t test_length, size_t rate, size_t order, double eb_n0, double error_rate) {
double bpsk_voltage = 1.0/sqrt(2.0);
double bpsk_sym_energy = 2*pow(bpsk_voltage, 2.0);
double bpsk_bit_energy = bpsk_sym_energy * rate;
size_t error_count = test_conv(conv, testbench, test_length, eb_n0, bpsk_bit_energy, bpsk_voltage);
double observed_error_rate = error_count/((double)test_length * 8);
if (observed_error_rate > error_rate) {
printf("test failed, expected error rate=%.2e, observed error rate=%.2e @%.1fdB for rate %zu order %zu\n",
error_rate, observed_error_rate, eb_n0, rate, order);
exit(1);
} else {
printf("test passed, expected error rate=%.2e, observed error rate=%.2e @%.1fdB for rate %zu order %zu\n",
error_rate, observed_error_rate, eb_n0, rate, order);
}
}
int main() {
srand(time(NULL));
conv_testbench *testbench = NULL;
correct_convolutional *conv;
// n.b. the error rates below are at 5.0dB/4.5dB for order 6 polys
// and 4.5dB/4.0dB for order 7-9 polys. this can be easy to miss.
conv = correct_convolutional_create(2, 6, correct_conv_r12_6_polynomial);
assert_test_result(conv, &testbench, 1000000, 2, 6, INFINITY, 0);
assert_test_result(conv, &testbench, 1000000, 2, 6, 5.0, 5e-06);
assert_test_result(conv, &testbench, 1000000, 2, 6, 4.5, 3e-05);
correct_convolutional_destroy(conv);
printf("\n");
conv = correct_convolutional_create(2, 7, correct_conv_r12_7_polynomial);
assert_test_result(conv, &testbench, 1000000, 2, 7, INFINITY, 0);
assert_test_result(conv, &testbench, 1000000, 2, 7, 4.5, 1e-05);
assert_test_result(conv, &testbench, 1000000, 2, 7, 4.0, 5e-05);
correct_convolutional_destroy(conv);
printf("\n");
conv = correct_convolutional_create(2, 8, correct_conv_r12_8_polynomial);
assert_test_result(conv, &testbench, 1000000, 2, 8, INFINITY, 0);
assert_test_result(conv, &testbench, 1000000, 2, 8, 4.5, 5e-06);
assert_test_result(conv, &testbench, 1000000, 2, 8, 4.0, 3e-05);
correct_convolutional_destroy(conv);
printf("\n");
conv = correct_convolutional_create(2, 9, correct_conv_r12_9_polynomial);
assert_test_result(conv, &testbench, 1000000, 2, 9, INFINITY, 0);
assert_test_result(conv, &testbench, 1000000, 2, 9, 4.5, 3e-06);
assert_test_result(conv, &testbench, 1000000, 2, 9, 4.0, 1e-05);
correct_convolutional_destroy(conv);
printf("\n");
conv = correct_convolutional_create(3, 6, correct_conv_r13_6_polynomial);
assert_test_result(conv, &testbench, 1000000, 3, 6, INFINITY, 0);
assert_test_result(conv, &testbench, 1000000, 3, 6, 5.0, 5e-06);
assert_test_result(conv, &testbench, 1000000, 3, 6, 4.5, 2e-05);
correct_convolutional_destroy(conv);
printf("\n");
conv = correct_convolutional_create(3, 7, correct_conv_r13_7_polynomial);
assert_test_result(conv, &testbench, 1000000, 3, 7, INFINITY, 0);
assert_test_result(conv, &testbench, 1000000, 3, 7, 4.5, 5e-06);
assert_test_result(conv, &testbench, 1000000, 3, 7, 4.0, 3e-05);
correct_convolutional_destroy(conv);
printf("\n");
conv = correct_convolutional_create(3, 8, correct_conv_r13_8_polynomial);
assert_test_result(conv, &testbench, 1000000, 3, 8, INFINITY, 0);
assert_test_result(conv, &testbench, 1000000, 3, 8, 4.5, 4e-06);
assert_test_result(conv, &testbench, 1000000, 3, 8, 4.0, 1e-05);
correct_convolutional_destroy(conv);
printf("\n");
conv = correct_convolutional_create(3, 9, correct_conv_r13_9_polynomial);
assert_test_result(conv, &testbench, 1000000, 3, 9, INFINITY, 0);
assert_test_result(conv, &testbench, 1000000, 3, 9, 4.5, 3e-06);
assert_test_result(conv, &testbench, 1000000, 3, 9, 4.0, 5e-06);
correct_convolutional_destroy(conv);
printf("\n");
free_scratch(testbench);
return 0;
}

View File

@ -0,0 +1,41 @@
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
#include <time.h>
#include "correct.h"
void rs_correct_encode(void *encoder, uint8_t *msg, size_t msg_length,
uint8_t *msg_out);
void rs_correct_decode(void *decoder, uint8_t *encoded, size_t encoded_length,
uint8_t *erasure_locations, size_t erasure_length,
uint8_t *msg, size_t pad_length, size_t num_roots);
typedef struct {
size_t block_length;
size_t message_length;
size_t min_distance;
unsigned char *msg;
uint8_t *encoded;
int *indices;
uint8_t *corrupted_encoded;
uint8_t *erasure_locations;
unsigned char *recvmsg;
} rs_testbench;
typedef struct {
void (*encode)(void *, uint8_t *, size_t, uint8_t *);
void *encoder;
void (*decode)(void *, uint8_t *, size_t, uint8_t *, size_t, uint8_t *, size_t, size_t);
void *decoder;
} rs_test;
rs_testbench *rs_testbench_create(size_t block_length, size_t min_distance);
void rs_testbench_destroy(rs_testbench *testbench);
typedef struct {
bool output_matches;
} rs_test_run;
rs_test_run test_rs_errors(rs_test *test, rs_testbench *testbench, size_t msg_length,
size_t num_errors, size_t num_erasures);

View File

@ -0,0 +1,10 @@
#include <stdint.h>
#include <stddef.h>
#include <stdlib.h>
#include <string.h>
#include <fec.h>
void rs_fec_encode(void *encoder, uint8_t *msg, size_t msg_length,
uint8_t *msg_out);
void rs_fec_decode(void *decoder, uint8_t *encoded, size_t encoded_length,
uint8_t *erasure_locations, size_t erasure_length,
uint8_t *msg, size_t pad_length, size_t num_roots);

View File

@ -0,0 +1,10 @@
#include <stdint.h>
#include <stddef.h>
#include <stdlib.h>
#include <string.h>
#include "fec_shim.h"
void rs_fec_encode(void *encoder, uint8_t *msg, size_t msg_length,
uint8_t *msg_out);
void rs_fec_decode(void *decoder, uint8_t *encoded, size_t encoded_length,
uint8_t *erasure_locations, size_t erasure_length,
uint8_t *msg, size_t pad_length, size_t num_roots);

View File

@ -0,0 +1,138 @@
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <stdbool.h>
#include <time.h>
#include "rs_tester.h"
#include "rs_tester_fec.h"
void print_test_type(size_t block_length, size_t message_length,
size_t num_errors, size_t num_erasures) {
printf(
"testing reed solomon block length=%zu, message length=%zu, "
"errors=%zu, erasures=%zu...",
block_length, message_length, num_errors, num_erasures);
}
void fail_test() {
printf("FAILED\n");
exit(1);
}
void pass_test() { printf("PASSED\n"); }
void run_tests(correct_reed_solomon *rs, void *fec_rs, rs_testbench *testbench,
size_t block_length, size_t test_msg_length, size_t num_errors,
size_t num_erasures, size_t num_iterations) {
// run both ways, correct->fec and fec->correct
rs_test test;
test.encode = rs_correct_encode;
test.encoder = rs;
test.decode = rs_fec_decode;
test.decoder = fec_rs;
print_test_type(block_length, test_msg_length, num_errors, num_erasures);
for (size_t i = 0; i < num_iterations; i++) {
rs_test_run run = test_rs_errors(&test, testbench, test_msg_length,
num_errors, num_erasures);
if (!run.output_matches) {
fail_test();
}
}
test.encode = rs_fec_encode;
test.encoder = fec_rs;
test.decode = rs_correct_decode;
test.decoder = rs;
for (size_t i = 0; i < num_iterations; i++) {
rs_test_run run = test_rs_errors(&test, testbench, test_msg_length,
num_errors, num_erasures);
if (!run.output_matches) {
fail_test();
}
}
pass_test();
}
int main() {
srand(time(NULL));
size_t block_length = 255;
size_t min_distance = 32;
size_t message_length = block_length - min_distance;
size_t pad_length;
void *fec_rs;
correct_reed_solomon *rs = correct_reed_solomon_create(
correct_rs_primitive_polynomial_ccsds, 1, 1, min_distance);
rs_testbench *testbench = rs_testbench_create(block_length, min_distance);
pad_length = message_length / 2;
fec_rs = init_rs_char(8, correct_rs_primitive_polynomial_ccsds, 1, 1, min_distance,
pad_length);
run_tests(rs, fec_rs, testbench, block_length, message_length - pad_length,
0, 0, 20000);
run_tests(rs, fec_rs, testbench, block_length, message_length - pad_length,
min_distance / 2, 0, 20000);
run_tests(rs, fec_rs, testbench, block_length, message_length - pad_length,
0, min_distance, 20000);
run_tests(rs, fec_rs, testbench, block_length, message_length - pad_length,
min_distance / 4, min_distance / 2, 20000);
free_rs_char(fec_rs);
pad_length = 0;
fec_rs = init_rs_char(8, correct_rs_primitive_polynomial_ccsds, 1, 1, min_distance,
pad_length);
run_tests(rs, fec_rs, testbench, block_length, message_length - pad_length,
0, 0, 20000);
run_tests(rs, fec_rs, testbench, block_length, message_length - pad_length,
min_distance / 2, 0, 20000);
run_tests(rs, fec_rs, testbench, block_length, message_length - pad_length,
0, min_distance, 20000);
run_tests(rs, fec_rs, testbench, block_length, message_length - pad_length,
min_distance / 4, min_distance / 2, 20000);
free_rs_char(fec_rs);
rs_testbench_destroy(testbench);
correct_reed_solomon_destroy(rs);
min_distance = 16;
message_length = block_length - min_distance;
rs = correct_reed_solomon_create(
correct_rs_primitive_polynomial_ccsds, 1, 1, min_distance);
testbench = rs_testbench_create(block_length, min_distance);
pad_length = message_length / 2;
fec_rs = init_rs_char(8, correct_rs_primitive_polynomial_ccsds, 1, 1, min_distance,
pad_length);
run_tests(rs, fec_rs, testbench, block_length, message_length - pad_length,
0, 0, 20000);
run_tests(rs, fec_rs, testbench, block_length, message_length - pad_length,
min_distance / 2, 0, 20000);
run_tests(rs, fec_rs, testbench, block_length, message_length - pad_length,
0, min_distance, 20000);
run_tests(rs, fec_rs, testbench, block_length, message_length - pad_length,
min_distance / 4, min_distance / 2, 20000);
free_rs_char(fec_rs);
pad_length = 0;
fec_rs = init_rs_char(8, correct_rs_primitive_polynomial_ccsds, 1, 1, min_distance,
pad_length);
run_tests(rs, fec_rs, testbench, block_length, message_length - pad_length,
0, 0, 20000);
run_tests(rs, fec_rs, testbench, block_length, message_length - pad_length,
min_distance / 2, 0, 20000);
run_tests(rs, fec_rs, testbench, block_length, message_length - pad_length,
0, min_distance, 20000);
run_tests(rs, fec_rs, testbench, block_length, message_length - pad_length,
min_distance / 4, min_distance / 2, 20000);
free_rs_char(fec_rs);
rs_testbench_destroy(testbench);
correct_reed_solomon_destroy(rs);
printf("test passed\n");
return 0;
}

View File

@ -0,0 +1,138 @@
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <stdbool.h>
#include <time.h>
#include "rs_tester.h"
#include "rs_tester_fec_shim.h"
void print_test_type(size_t block_length, size_t message_length,
size_t num_errors, size_t num_erasures) {
printf(
"testing reed solomon block length=%zu, message length=%zu, "
"errors=%zu, erasures=%zu...",
block_length, message_length, num_errors, num_erasures);
}
void fail_test() {
printf("FAILED\n");
exit(1);
}
void pass_test() { printf("PASSED\n"); }
void run_tests(correct_reed_solomon *rs, void *fec_rs, rs_testbench *testbench,
size_t block_length, size_t test_msg_length, size_t num_errors,
size_t num_erasures, size_t num_iterations) {
// run both ways, correct->fec and fec->correct
rs_test test;
test.encode = rs_correct_encode;
test.encoder = rs;
test.decode = rs_fec_decode;
test.decoder = fec_rs;
print_test_type(block_length, test_msg_length, num_errors, num_erasures);
for (size_t i = 0; i < num_iterations; i++) {
rs_test_run run = test_rs_errors(&test, testbench, test_msg_length, num_errors,
num_erasures);
if (!run.output_matches) {
fail_test();
}
}
test.encode = rs_fec_encode;
test.encoder = fec_rs;
test.decode = rs_correct_decode;
test.decoder = rs;
for (size_t i = 0; i < num_iterations; i++) {
rs_test_run run = test_rs_errors(&test, testbench, test_msg_length, num_errors,
num_erasures);
if (!run.output_matches) {
fail_test();
}
}
pass_test();
}
int main() {
srand(time(NULL));
size_t block_length = 255;
size_t min_distance = 32;
size_t message_length = block_length - min_distance;
size_t pad_length;
void *fec_rs;
correct_reed_solomon *rs = correct_reed_solomon_create(
correct_rs_primitive_polynomial_ccsds, 1, 1, min_distance);
rs_testbench *testbench = rs_testbench_create(block_length, min_distance);
pad_length = message_length / 2;
fec_rs = init_rs_char(8, correct_rs_primitive_polynomial_ccsds, 1, 1, min_distance,
pad_length);
run_tests(rs, fec_rs, testbench, block_length, message_length - pad_length,
0, 0, 20000);
run_tests(rs, fec_rs, testbench, block_length, message_length - pad_length,
min_distance / 2, 0, 20000);
run_tests(rs, fec_rs, testbench, block_length, message_length - pad_length,
0, min_distance, 20000);
run_tests(rs, fec_rs, testbench, block_length, message_length - pad_length,
min_distance / 4, min_distance / 2, 20000);
free_rs_char(fec_rs);
pad_length = 0;
fec_rs = init_rs_char(8, correct_rs_primitive_polynomial_ccsds, 1, 1, min_distance,
pad_length);
run_tests(rs, fec_rs, testbench, block_length, message_length - pad_length,
0, 0, 20000);
run_tests(rs, fec_rs, testbench, block_length, message_length - pad_length,
min_distance / 2, 0, 20000);
run_tests(rs, fec_rs, testbench, block_length, message_length - pad_length,
0, min_distance, 20000);
run_tests(rs, fec_rs, testbench, block_length, message_length - pad_length,
min_distance / 4, min_distance / 2, 20000);
free_rs_char(fec_rs);
rs_testbench_destroy(testbench);
correct_reed_solomon_destroy(rs);
min_distance = 16;
message_length = block_length - min_distance;
rs = correct_reed_solomon_create(
correct_rs_primitive_polynomial_ccsds, 1, 1, min_distance);
testbench = rs_testbench_create(block_length, min_distance);
pad_length = message_length / 2;
fec_rs = init_rs_char(8, correct_rs_primitive_polynomial_ccsds, 1, 1, min_distance,
pad_length);
run_tests(rs, fec_rs, testbench, block_length, message_length - pad_length,
0, 0, 20000);
run_tests(rs, fec_rs, testbench, block_length, message_length - pad_length,
min_distance / 2, 0, 20000);
run_tests(rs, fec_rs, testbench, block_length, message_length - pad_length,
0, min_distance, 20000);
run_tests(rs, fec_rs, testbench, block_length, message_length - pad_length,
min_distance / 4, min_distance / 2, 20000);
free_rs_char(fec_rs);
pad_length = 0;
fec_rs = init_rs_char(8, correct_rs_primitive_polynomial_ccsds, 1, 1, min_distance,
pad_length);
run_tests(rs, fec_rs, testbench, block_length, message_length - pad_length,
0, 0, 20000);
run_tests(rs, fec_rs, testbench, block_length, message_length - pad_length,
min_distance / 2, 0, 20000);
run_tests(rs, fec_rs, testbench, block_length, message_length - pad_length,
0, min_distance, 20000);
run_tests(rs, fec_rs, testbench, block_length, message_length - pad_length,
min_distance / 4, min_distance / 2, 20000);
free_rs_char(fec_rs);
rs_testbench_destroy(testbench);
correct_reed_solomon_destroy(rs);
printf("test passed\n");
return 0;
}

View File

@ -0,0 +1,146 @@
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <stdbool.h>
#include <time.h>
#include "rs_tester.h"
void print_test_type(size_t block_length, size_t message_length,
size_t num_errors, size_t num_erasures) {
printf(
"testing reed solomon block length=%zu, message length=%zu, "
"errors=%zu, erasures=%zu...",
block_length, message_length, num_errors, num_erasures);
}
void fail_test() {
printf("FAILED\n");
exit(1);
}
void pass_test() { printf("PASSED\n"); }
void run_tests(correct_reed_solomon *rs, rs_testbench *testbench,
size_t block_length, size_t test_msg_length, size_t num_errors,
size_t num_erasures, size_t num_iterations) {
rs_test test;
test.encode = rs_correct_encode;
test.decode = rs_correct_decode;
test.encoder = rs;
test.decoder = rs;
print_test_type(block_length, test_msg_length, num_errors, num_erasures);
for (size_t i = 0; i < num_iterations; i++) {
rs_test_run run = test_rs_errors(&test, testbench, test_msg_length, num_errors,
num_erasures);
if (!run.output_matches) {
fail_test();
}
}
pass_test();
}
int main() {
srand(time(NULL));
size_t block_length = 255;
size_t min_distance = 32;
size_t message_length = block_length - min_distance;
correct_reed_solomon *rs = correct_reed_solomon_create(
correct_rs_primitive_polynomial_ccsds, 1, 1, min_distance);
rs_testbench *testbench = rs_testbench_create(block_length, min_distance);
run_tests(rs, testbench, block_length, message_length / 2, 0, 0, 20000);
run_tests(rs, testbench, block_length, message_length, 0, 0, 20000);
run_tests(rs, testbench, block_length, message_length / 2, min_distance / 2,
0, 20000);
run_tests(rs, testbench, block_length, message_length, min_distance / 2, 0,
20000);
run_tests(rs, testbench, block_length, message_length / 2, 0, min_distance,
20000);
run_tests(rs, testbench, block_length, message_length, 0, min_distance,
20000);
run_tests(rs, testbench, block_length, message_length / 2, min_distance / 4,
min_distance / 2, 20000);
run_tests(rs, testbench, block_length, message_length, min_distance / 4,
min_distance / 2, 20000);
rs_testbench_destroy(testbench);
correct_reed_solomon_destroy(rs);
min_distance = 16;
message_length = block_length - min_distance;
rs = correct_reed_solomon_create(
correct_rs_primitive_polynomial_ccsds, 1, 1, min_distance);
testbench = rs_testbench_create(block_length, min_distance);
run_tests(rs, testbench, block_length, message_length / 2, 0, 0, 20000);
run_tests(rs, testbench, block_length, message_length, 0, 0, 20000);
run_tests(rs, testbench, block_length, message_length / 2, min_distance / 2,
0, 20000);
run_tests(rs, testbench, block_length, message_length, min_distance / 2, 0,
20000);
run_tests(rs, testbench, block_length, message_length / 2, 0, min_distance,
20000);
run_tests(rs, testbench, block_length, message_length, 0, min_distance,
20000);
run_tests(rs, testbench, block_length, message_length / 2, min_distance / 4,
min_distance / 2, 20000);
run_tests(rs, testbench, block_length, message_length, min_distance / 4,
min_distance / 2, 20000);
rs_testbench_destroy(testbench);
correct_reed_solomon_destroy(rs);
min_distance = 8;
message_length = block_length - min_distance;
rs = correct_reed_solomon_create(
correct_rs_primitive_polynomial_ccsds, 1, 1, min_distance);
testbench = rs_testbench_create(block_length, min_distance);
run_tests(rs, testbench, block_length, message_length / 2, 0, 0, 20000);
run_tests(rs, testbench, block_length, message_length, 0, 0, 20000);
run_tests(rs, testbench, block_length, message_length / 2, min_distance / 2,
0, 20000);
run_tests(rs, testbench, block_length, message_length, min_distance / 2, 0,
20000);
run_tests(rs, testbench, block_length, message_length / 2, 0, min_distance,
20000);
run_tests(rs, testbench, block_length, message_length, 0, min_distance,
20000);
run_tests(rs, testbench, block_length, message_length / 2, min_distance / 4,
min_distance / 2, 20000);
run_tests(rs, testbench, block_length, message_length, min_distance / 4,
min_distance / 2, 20000);
rs_testbench_destroy(testbench);
correct_reed_solomon_destroy(rs);
min_distance = 4;
message_length = block_length - min_distance;
rs = correct_reed_solomon_create(
correct_rs_primitive_polynomial_ccsds, 1, 1, min_distance);
testbench = rs_testbench_create(block_length, min_distance);
run_tests(rs, testbench, block_length, message_length / 2, 0, 0, 20000);
run_tests(rs, testbench, block_length, message_length, 0, 0, 20000);
run_tests(rs, testbench, block_length, message_length / 2, min_distance / 2,
0, 20000);
run_tests(rs, testbench, block_length, message_length, min_distance / 2, 0,
20000);
run_tests(rs, testbench, block_length, message_length / 2, 0, min_distance,
20000);
run_tests(rs, testbench, block_length, message_length, 0, min_distance,
20000);
run_tests(rs, testbench, block_length, message_length / 2, min_distance / 4,
min_distance / 2, 20000);
run_tests(rs, testbench, block_length, message_length, min_distance / 4,
min_distance / 2, 20000);
rs_testbench_destroy(testbench);
correct_reed_solomon_destroy(rs);
printf("test passed\n");
return 0;
}

View File

@ -0,0 +1,102 @@
#include "rs_tester.h"
void shuffle(int *a, size_t len) {
for (size_t i = 0; i < len - 2; i++) {
size_t j = rand() % (len - i) + i;
int temp = a[i];
a[i] = a[j];
a[j] = temp;
}
}
void rs_correct_encode(void *encoder, uint8_t *msg, size_t msg_length,
uint8_t *msg_out) {
correct_reed_solomon_encode((correct_reed_solomon *)encoder, msg,
msg_length, msg_out);
}
void rs_correct_decode(void *decoder, uint8_t *encoded, size_t encoded_length,
uint8_t *erasure_locations, size_t erasure_length,
uint8_t *msg, size_t pad_length, size_t num_roots) {
correct_reed_solomon_decode_with_erasures(
(correct_reed_solomon *)decoder, encoded, encoded_length,
erasure_locations, erasure_length, msg);
}
rs_testbench *rs_testbench_create(size_t block_length, size_t min_distance) {
rs_testbench *testbench = calloc(1, sizeof(rs_testbench));
size_t message_length = block_length - min_distance;
testbench->message_length = message_length;
testbench->block_length = block_length;
testbench->min_distance = min_distance;
testbench->msg = calloc(message_length, sizeof(unsigned char));
testbench->encoded = malloc(block_length * sizeof(uint8_t));
testbench->indices = malloc(block_length * sizeof(int));
testbench->corrupted_encoded = malloc(block_length * sizeof(uint8_t));
testbench->erasure_locations = malloc(min_distance * sizeof(uint8_t));
testbench->recvmsg = malloc(sizeof(unsigned char) * message_length);
return testbench;
}
void rs_testbench_destroy(rs_testbench *testbench) {
free(testbench->msg);
free(testbench->encoded);
free(testbench->indices);
free(testbench->corrupted_encoded);
free(testbench->erasure_locations);
free(testbench->recvmsg);
free(testbench);
}
rs_test_run test_rs_errors(rs_test *test, rs_testbench *testbench, size_t msg_length,
size_t num_errors, size_t num_erasures) {
rs_test_run run;
run.output_matches = false;
if (msg_length > testbench->message_length) {
return run;
}
for (size_t i = 0; i < msg_length; i++) {
testbench->msg[i] = rand() % 256;
}
size_t block_length = msg_length + testbench->min_distance;
size_t pad_length = testbench->message_length - msg_length;
test->encode(test->encoder, testbench->msg, msg_length, testbench->encoded);
memcpy(testbench->corrupted_encoded, testbench->encoded, block_length);
for (int i = 0; i < block_length; i++) {
testbench->indices[i] = i;
}
shuffle(testbench->indices, block_length);
for (unsigned int i = 0; i < num_erasures; i++) {
int index = testbench->indices[i];
uint8_t corruption_mask = (rand() % 255) + 1;
testbench->corrupted_encoded[index] ^= corruption_mask;
testbench->erasure_locations[i] = index;
}
for (unsigned int i = 0; i < num_errors; i++) {
int index = testbench->indices[i + num_erasures];
uint8_t corruption_mask = (rand() % 255) + 1;
testbench->corrupted_encoded[index] ^= corruption_mask;
}
test->decode(test->decoder, testbench->corrupted_encoded, block_length,
testbench->erasure_locations, num_erasures,
testbench->recvmsg, pad_length, testbench->min_distance);
run.output_matches = (bool)(memcmp(testbench->msg, testbench->recvmsg, msg_length) == 0);
return run;
}

View File

@ -0,0 +1,30 @@
#include "rs_tester_fec.h"
void rs_fec_encode(void *encoder, uint8_t *msg, size_t msg_length,
uint8_t *msg_out) {
// XXX make sure that pad length used to build encoder corresponds to this
// msg_length
memcpy(msg_out, msg, msg_length);
encode_rs_char(encoder, msg_out, msg_out + msg_length);
}
void rs_fec_decode(void *decoder, uint8_t *encoded, size_t encoded_length,
uint8_t *erasure_locations, size_t erasure_length,
uint8_t *msg, size_t pad_length, size_t num_roots) {
// XXX make sure that pad length used to build decoder corresponds to this
// encoded_length
if (erasure_length) {
static size_t locations_len = 0;
static int *locations = NULL;
if (locations_len < erasure_length) {
locations = realloc(locations, erasure_length * sizeof(int));
locations_len = erasure_length;
}
for (size_t i = 0; i < erasure_length; i++) {
locations[i] = (unsigned int)(erasure_locations[i]) + pad_length;
}
decode_rs_char(decoder, encoded, locations, erasure_length);
} else {
decode_rs_char(decoder, encoded, NULL, 0);
}
memcpy(msg, encoded, encoded_length - num_roots);
}

View File

@ -0,0 +1,26 @@
#include "rs_tester_fec_shim.h"
void rs_fec_encode(void *encoder, uint8_t *msg, size_t msg_length,
uint8_t *msg_out) {
// XXX make sure that pad length used to build encoder corresponds to this
// msg_length
memcpy(msg_out, msg, msg_length);
encode_rs_char(encoder, msg_out, msg_out + msg_length);
}
void rs_fec_decode(void *decoder, uint8_t *encoded, size_t encoded_length,
uint8_t *erasure_locations, size_t erasure_length,
uint8_t *msg, size_t pad_length, size_t num_roots) {
// XXX make sure that pad length used to build decoder corresponds to this
// encoded_length
if (erasure_length) {
int *locations = malloc(erasure_length * sizeof(int));
for (size_t i = 0; i < erasure_length; i++) {
locations[i] = (unsigned int)(erasure_locations[i]) + pad_length;
}
decode_rs_char(decoder, encoded, locations, erasure_length);
free(locations);
} else {
decode_rs_char(decoder, encoded, NULL, 0);
}
memcpy(msg, encoded, encoded_length - num_roots);
}

View File

@ -0,0 +1,29 @@
add_executable(rs_find_primitive_poly EXCLUDE_FROM_ALL find_rs_primitive_poly.c)
target_link_libraries(rs_find_primitive_poly correct_static)
set(all_tools ${all_tools} rs_find_primitive_poly)
if(HAVE_LIBFEC)
add_executable(conv_find_libfec_poly EXCLUDE_FROM_ALL find_conv_libfec_poly.c)
target_link_libraries(conv_find_libfec_poly correct_static fec)
set(all_tools ${all_tools} conv_find_libfec_poly)
endif()
if(HAVE_SSE)
add_executable(conv_find_optim_poly EXCLUDE_FROM_ALL find_conv_optim_poly.c $<TARGET_OBJECTS:error_sim_sse>)
target_link_libraries(conv_find_optim_poly correct_static)
set(all_tools ${all_tools} conv_find_optim_poly)
add_executable(conv_find_optim_poly_annealing EXCLUDE_FROM_ALL find_conv_optim_poly_annealing.c $<TARGET_OBJECTS:error_sim_sse>)
target_link_libraries(conv_find_optim_poly_annealing correct_static)
set(all_tools ${all_tools} conv_find_optim_poly_annealing)
else()
add_executable(conv_find_optim_poly EXCLUDE_FROM_ALL find_conv_optim_poly.c $<TARGET_OBJECTS:error_sim>)
target_link_libraries(conv_find_optim_poly correct_static)
set(all_tools ${all_tools} conv_find_optim_poly)
add_executable(conv_find_optim_poly_annealing EXCLUDE_FROM_ALL find_conv_optim_poly_annealing.c $<TARGET_OBJECTS:error_sim>)
target_link_libraries(conv_find_optim_poly_annealing correct_static)
set(all_tools ${all_tools} conv_find_optim_poly_annealing)
endif()
add_custom_target(tools DEPENDS ${all_tools})

View File

@ -0,0 +1,279 @@
#include <stdlib.h>
#include <stdio.h>
#include <stdbool.h>
#include <string.h>
#include <time.h>
#include <stddef.h>
#include <assert.h>
#include <correct.h>
#include <fec.h>
// this program allows us to find all of the polynomials that come with libfec
// this way, we can provide compatibility with libfec-encoded streams and vice versa
// we can do this without directly copy-pasting from libfec's source, thanks
// to this finder
typedef struct {
void *vit;
int update_len;
int (*init)(void *, int);
int (*update)(void *, unsigned char *, int);
int (*chainback)(void *, unsigned char *, unsigned int, unsigned int);
} libfec_decoder_t;
void byte2bit(uint8_t *bytes, uint8_t *bits, size_t n_bits) {
unsigned char cmask = 0x80;
for (size_t i = 0; i < n_bits; i++) {
bits[i] = (bytes[i/8] & cmask) ? 255 : 0;
cmask >>= 1;
if (!cmask) {
cmask = 0x80;
}
}
}
correct_convolutional_polynomial_t *resize_poly_list(correct_convolutional_polynomial_t *polys, size_t cap) {
polys = realloc(polys, cap * sizeof(correct_convolutional_polynomial_t));
return polys;
}
void find_poly_coeff(size_t rate, size_t order, uint8_t *msg, size_t msg_len, libfec_decoder_t libfec, correct_convolutional_polynomial_t **polys_dest, size_t *polys_len, size_t search_coeff) {
// find a single coefficient of an unknown convolutional polynomial
// we are given a payload to encode, and we'll test all possible coefficients
// to see which ones yield correct decodings by libfec, which has some
// unknown polynomial "baked in"
// temp poly (this will be the one we search with)
correct_convolutional_polynomial_t *poly = malloc(rate * sizeof(correct_convolutional_polynomial_t));
// what's the largest coefficient value we'll test?
correct_convolutional_polynomial_t maxcoeff = (1 << order) - 1;
// note that we start about half way in
// this sum asks that we have the
// a) highest order bit set
// b) lowest order bit set
// we're only interested in coefficient values for which this is
// true because if it weren't, the coefficient would actually be
// of a smaller order than its supposed given order
correct_convolutional_polynomial_t startcoeff = (1 << (order - 1)) + 1;
// the values of this don't really matter except for the coeff we're searching for
// but just to be safe, we set them all
for (size_t i = 0; i < rate; i++) {
poly[i] = startcoeff;
}
// create a dummy encoder so that we can find how long the resulting encoded value is
correct_convolutional *conv_dummy = correct_convolutional_create(rate, order, poly);
size_t enclen_bits = correct_convolutional_encode_len(conv_dummy, msg_len);
size_t enclen = (enclen_bits % 8) ? (enclen_bits / 8 + 1) : enclen_bits / 8;
correct_convolutional_destroy(conv_dummy);
// compact encoded format (this comes from libcorrect)
uint8_t *encoded = malloc(enclen * sizeof(uint8_t));
// soft encoded format (this goes to libfec, one byte per bit)
uint8_t *encoded_bits = malloc(enclen * 8 * sizeof(uint8_t));
// resulting decoded message which we'll compare to our given payload
uint8_t *msg_cmp = malloc(msg_len * sizeof(uint8_t));
// we keep a list of coefficients which yielded correct decodings
// there could be 0, 1, or more than 1, and we'll return all of them
// we'll dynamically resize this as we go
size_t polys_cap = 1;
*polys_len = 0;
correct_convolutional_polynomial_t *polys = NULL;
polys = resize_poly_list(polys, polys_cap);
// iteration constants -- we go by 2 because we want the lowest order bit to
// stay set
for (correct_convolutional_polynomial_t i = startcoeff; i <= maxcoeff; i += 2) {
poly[search_coeff] = i;
correct_convolutional *conv = correct_convolutional_create(rate, order, poly);
correct_convolutional_encode(conv, (uint8_t*)msg, msg_len, encoded);
byte2bit(encoded, encoded_bits, enclen);
// now erase all the bits we're not searching for
for (size_t i = 0; i < msg_len * 8; i++) {
for (size_t j = 0; j < rate; j++) {
if (j != search_coeff) {
// 128 is a soft erasure
encoded_bits[i * rate + j] = 128;
}
}
}
libfec.init(libfec.vit, 0);
libfec.update(libfec.vit, encoded_bits, libfec.update_len);
libfec.chainback(libfec.vit, msg_cmp, 8 * msg_len, 0);
correct_convolutional_destroy(conv);
if (memcmp(msg_cmp, msg, msg_len) == 0) {
// match found
// resize list to make room
if (*polys_len == polys_cap) {
polys = resize_poly_list(polys, polys_cap * 2);
polys_cap *= 2;
}
polys[*polys_len] = i;
*polys_len = *polys_len + 1;
}
}
polys = resize_poly_list(polys, *polys_len);
*polys_dest = polys;
free(poly);
free(msg_cmp);
free(encoded);
free(encoded_bits);
}
// we choose 2 bytes because we need a payload that's longer than
// the shift register under test. since that includes an order 15
// s.r., we need at least 15 bits.
size_t msg_len = 2;
void find_poly(size_t rate, size_t order, libfec_decoder_t libfec, correct_convolutional_polynomial_t *poly) {
// find the complete set of coefficients that are "baked in" to
// one particular method of libfec
// most of this method is described by find_poly_coeff
// for each coeff we want to find, we'll generate random 2-byte payloads and give
// them to find_poly_coeff. If find_poly_coeff returns an empty list, we
// try again. If it returns a nonempty list, then we find the intersection of
// all the coefficient values find_poly_coeff has given us so far (we start
// with the complete set). we are finished when only one coeff value remains
// we perform this process for each coeff e.g. 6 times for a rate 1/6 polynomial
uint8_t msg[msg_len];
// this is the list returned to us by find_poly_coeff
correct_convolutional_polynomial_t *polys;
// the list's length is written here
size_t polys_len;
printf("rate 1/%zu order %zu poly:", rate, order);
for (size_t search_coeff = 0; search_coeff < rate; search_coeff++) {
correct_convolutional_polynomial_t *fit = NULL;
size_t fit_len = 0;
size_t fit_cap = 0;
bool done = false;
while (!done) {
for (size_t i = 0; i < msg_len; i++) {
msg[i] = rand() % 256;
}
find_poly_coeff(rate, order, msg, msg_len, libfec, &polys, &polys_len, search_coeff);
if (polys_len == 0) {
// skip if none fit (this is a special case)
continue;
}
if (fit_len == 0) {
// the very first intersection
// we'll just copy the list handed to us
fit_cap = polys_len;
fit_len = polys_len;
fit = resize_poly_list(fit, fit_cap);
for (size_t i = 0; i < polys_len; i++) {
fit[i] = polys[i];
}
} else {
// find intersection
ptrdiff_t polys_iter = 0;
ptrdiff_t fit_iter = 0;
ptrdiff_t new_fit_iter = 0;
// the lists generated by find_poly_coeff are sorted
// so we just retain the sorted property and walk both
while (polys_iter < polys_len && fit_iter < fit_len) {
if (polys[polys_iter] < fit[fit_iter]) {
polys_iter++;
} else if (polys[polys_iter] > fit[fit_iter]) {
fit_iter++;
} else {
fit[new_fit_iter] = fit[fit_iter];
polys_iter++;
fit_iter++;
new_fit_iter++;
}
}
// if new_fit_iter is 0 here then we don't intersect at all
// in this case we have to restart the search for this coeff
if (new_fit_iter != 0) {
fit_len = new_fit_iter;
} else {
free(fit);
fit = NULL;
fit_cap = 0;
fit_len = 0;
}
}
free(polys);
if (fit_len == 1) {
poly[search_coeff] = fit[0];
if (order <= 9) {
printf(" %04o", fit[0]);
} else {
printf(" %06o", fit[0]);
}
done = true;
}
}
free(fit);
}
printf("\n");
}
int main() {
libfec_decoder_t libfec;
srand(time(NULL));
setbuf(stdout, NULL);
correct_convolutional_polynomial_t poly[6];
libfec.vit = create_viterbi27(8 * msg_len);
libfec.update_len = 8 * msg_len + 6;
libfec.init = init_viterbi27;
libfec.update = update_viterbi27_blk;
libfec.chainback = chainback_viterbi27;
find_poly(2, 7, libfec, poly);
delete_viterbi27(libfec.vit);
libfec.vit = create_viterbi29(8 * msg_len);
libfec.update_len = 8 * msg_len + 8;
libfec.init = init_viterbi29;
libfec.update = update_viterbi29_blk;
libfec.chainback = chainback_viterbi29;
find_poly(2, 9, libfec, poly);
delete_viterbi29(libfec.vit);
libfec.vit = create_viterbi39(8 * msg_len);
libfec.update_len = 8 * msg_len + 8;
libfec.init = init_viterbi39;
libfec.update = update_viterbi39_blk;
libfec.chainback = chainback_viterbi39;
find_poly(3, 9, libfec, poly);
delete_viterbi39(libfec.vit);
libfec.vit = create_viterbi615(8 * msg_len);
libfec.update_len = 8 * msg_len + 14;
libfec.init = init_viterbi615;
libfec.update = update_viterbi615_blk;
libfec.chainback = chainback_viterbi615;
find_poly(6, 15, libfec, poly);
delete_viterbi615(libfec.vit);
return 0;
}

View File

@ -0,0 +1,330 @@
#include <stdbool.h>
#include <float.h>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <stddef.h>
#include <limits.h>
#include <pthread.h>
#if HAVE_SSE
#include "correct/util/error-sim-sse.h"
typedef correct_convolutional_sse conv_t;
static conv_t*(*conv_create)(size_t, size_t, const uint16_t *) = correct_convolutional_sse_create;
static void(*conv_destroy)(conv_t *) = correct_convolutional_sse_destroy;
static size_t(*conv_enclen)(void *, size_t) = conv_correct_sse_enclen;
static void(*conv_encode)(void *, uint8_t *, size_t, uint8_t *) = conv_correct_sse_encode;
static void(*conv_decode)(void *, uint8_t *, size_t, uint8_t *) = conv_correct_sse_decode;
#else
#include "correct/util/error-sim.h"
typedef correct_convolutional conv_t;
static conv_t*(*conv_create)(size_t, size_t, const uint16_t *) = correct_convolutional_create;
static void(*conv_destroy)(conv_t *) = correct_convolutional_destroy;
static size_t(*conv_enclen)(void *, size_t) = conv_correct_enclen;
static void(*conv_encode)(void *, uint8_t *, size_t, uint8_t *) = conv_correct_encode;
static void(*conv_decode)(void *, uint8_t *, size_t, uint8_t *) = conv_correct_decode;
#endif
typedef struct {
conv_t *conv;
correct_convolutional_polynomial_t *poly;
} conv_tester_t;
typedef struct {
int *distances;
float cost;
correct_convolutional_polynomial_t *poly;
} conv_result_t;
int compare_conv_results(const void *avoid, const void *bvoid) {
const conv_result_t *a = (const conv_result_t *)avoid;
const conv_result_t *b = (const conv_result_t *)bvoid;
if (a->cost > b->cost) {
return 1;
}
return -1;
}
typedef struct {
size_t rate;
size_t order;
conv_result_t *items;
size_t items_len;
conv_testbench *scratch;
uint8_t *msg;
size_t msg_len;
size_t test_offset;
double bpsk_voltage;
} exhaustive_thread_args;
void *search_exhaustive_thread(void *vargs) {
exhaustive_thread_args *args = (exhaustive_thread_args *)vargs;
conv_t *conv;
for (size_t i = 0; i < args->items_len; i++) {
conv = conv_create(args->rate, args->order, args->items[i].poly);
args->scratch->encode = conv_encode;
args->scratch->encoder = conv;
args->scratch->decode = conv_decode;
args->scratch->decoder = conv;
args->items[i].distances[args->test_offset] += test_conv_noise(args->scratch, args->msg, args->msg_len, args->bpsk_voltage);
conv_destroy(conv);
}
pthread_exit(NULL);
}
void search_exhaustive(size_t rate, size_t order,
size_t n_bytes, uint8_t *msg,
conv_testbench **scratches, size_t num_scratches,
float *weights,
conv_result_t *items,
size_t items_len, double bpsk_voltage) {
exhaustive_thread_args *args = malloc(num_scratches * sizeof(exhaustive_thread_args));
pthread_t *threads = malloc(num_scratches * sizeof(pthread_t));
for (size_t i = 0; i < num_scratches; i++) {
args[i].rate = rate;
args[i].order = order;
args[i].items = items;
args[i].items_len = items_len;
args[i].scratch = scratches[i];
args[i].msg = msg;
args[i].msg_len = n_bytes;
args[i].test_offset = i;
args[i].bpsk_voltage = bpsk_voltage;
pthread_attr_t attr;
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
pthread_create(&threads[i], &attr, search_exhaustive_thread, &args[i]);
}
for (size_t i = 0; i < num_scratches; i++) {
pthread_join(threads[i], NULL);
}
free(args);
free(threads);
}
void search_exhaustive_init(conv_result_t *items, size_t items_len,
size_t num_scratches) {
for (size_t i = 0; i < items_len; i++) {
for (size_t j = 0; j < num_scratches; j++) {
items[i].distances[j] = 0;
}
}
}
void search_exhaustive_fin(conv_result_t *items, size_t items_len,
float *weights, size_t weights_len) {
for (size_t i = 0; i < items_len; i++) {
items[i].cost = 0;
for (size_t j = 0; j < weights_len; j++) {
items[i].cost += weights[j] * items[i].distances[j];
}
}
qsort(items, items_len, sizeof(conv_result_t), compare_conv_results);
}
const size_t max_block_len = 16384;
const size_t max_msg_len = 50000000;
void test(size_t rate, size_t order,
conv_tester_t start, conv_testbench **scratches,
size_t num_scratches, float *weights,
size_t n_bytes, double *eb_n0,
double bpsk_bit_energy, size_t n_iter,
double bpsk_voltage) {
uint8_t *msg = malloc(max_block_len * sizeof(uint8_t));
correct_convolutional_polynomial_t maxcoeff = (1 << order) - 1;
correct_convolutional_polynomial_t startcoeff = (1 << (order - 1)) + 1;
size_t num_polys = (maxcoeff - startcoeff) / 2 + 1;
size_t convs_len = 1;
for (size_t i = 0; i < rate; i++) {
convs_len *= num_polys;
}
conv_result_t *exhaustive = malloc(convs_len * sizeof(conv_result_t));
correct_convolutional_polynomial_t *iter_poly = malloc(rate * sizeof(correct_convolutional_polynomial_t));
for (size_t i = 0; i < rate; i++) {
iter_poly[i] = startcoeff;
}
// init exhaustive with all polys
for (size_t i = 0; i < convs_len; i++) {
exhaustive[i].poly = malloc(rate * sizeof(correct_convolutional_polynomial_t));
exhaustive[i].distances = calloc(num_scratches, sizeof(int));
exhaustive[i].cost = 0;
memcpy(exhaustive[i].poly, iter_poly, rate * sizeof(correct_convolutional_polynomial_t));
// this next loop adds 2 with "carry"
for (size_t j = 0; j < rate; j++) {
if (iter_poly[j] < maxcoeff) {
iter_poly[j] += 2;
// no more carries to propagate
break;
} else {
iter_poly[j] = startcoeff;
}
}
}
free(iter_poly);
while (convs_len > 20) {
size_t bytes_remaining = n_bytes;
// call init(), which sets all the error metrics to 0 for our new run
search_exhaustive_init(exhaustive, convs_len, num_scratches);
while (bytes_remaining) {
// in order to keep memory usage constant, we separate the msg into
// blocks and send each one through
// each time we do this, we have to calculate a new noise for each
// testbench
size_t block_len = (max_block_len < bytes_remaining) ? max_block_len : bytes_remaining;
bytes_remaining -= block_len;
for (unsigned int j = 0; j < block_len; j++) {
msg[j] = rand() % 256;
}
for (size_t i = 0; i < num_scratches; i++) {
scratches[i] = resize_conv_testbench(scratches[i], conv_enclen, start.conv, block_len);
build_white_noise(scratches[i]->noise, scratches[i]->enclen, eb_n0[i], bpsk_bit_energy);
}
search_exhaustive(rate, order,
block_len, msg, scratches, num_scratches, weights,
exhaustive, convs_len, bpsk_voltage);
}
// call fin(), which calculates a cost metric for all of the distances
// added by our msg block iterations and then sorts by this metric
search_exhaustive_fin(exhaustive, convs_len, weights, num_scratches);
// decide parameters for next loop iter
// if we've reduced to 20 or fewer items, we're going to just select
// those and declare the test done
size_t new_convs_len = (convs_len / 2) < 20 ? 20 : convs_len / 2;
// normally we'll double the message length each time we halve
// the number of entries so that each iter takes roughly the
// same time but has twice the resolution of the previous run.
//
// however, if we've reached max_msg_len, then we assume that
// the error stats collected are likely converged to whatever
// final value they'll take, and adding more length will not
// help us get better metrics. if we're at that point, then
// we just select the top 20 items and declare them winners
if (n_bytes >= max_msg_len) {
// converged case
new_convs_len = 20;
} else {
// increase our error metric resolution next run
n_bytes *= 2;
n_bytes = (n_bytes < max_msg_len) ? n_bytes : max_msg_len;
}
for (size_t i = new_convs_len; i < convs_len; i++) {
// these entries lost, free their memory here
free(exhaustive[i].poly);
free(exhaustive[i].distances);
}
convs_len = new_convs_len;
printf("exhaustive run: %zu items remain\n", convs_len);
}
for (size_t i = 0; i < convs_len; i++) {
for (size_t j = 0; j < rate; j++) {
printf(" %06o", exhaustive[i].poly[j]);
}
printf(":");
for (size_t j = 0; j < num_scratches; j++) {
printf(" %.2e@%.1fdB", exhaustive[i].distances[j]/((float)n_bytes * 8), eb_n0[j]);
}
printf("\n");
}
for (size_t i = 0; i < convs_len; i++) {
free(exhaustive[i].poly);
free(exhaustive[i].distances);
}
free(exhaustive);
free(msg);
}
int main(int argc, char **argv) {
srand(time(NULL));
size_t rate, order, n_bytes, n_iter;
sscanf(argv[1], "%zu", &rate);
sscanf(argv[2], "%zu", &order);
sscanf(argv[3], "%zu", &n_bytes);
sscanf(argv[4], "%zu", &n_iter);
double bpsk_voltage = 1.0/sqrt(2.0);
double bpsk_sym_energy = 2*pow(bpsk_voltage, 2.0);
double bpsk_bit_energy = bpsk_sym_energy/1.0;
bpsk_bit_energy = bpsk_sym_energy * rate; // rate bits transmitted for every input bit
correct_convolutional_polynomial_t maxcoeff = (1 << order) - 1;
correct_convolutional_polynomial_t startcoeff = (1 << (order - 1)) + 1;
conv_tester_t start;
start.poly = malloc(rate * sizeof(correct_convolutional_polynomial_t));
for (size_t i = 0; i < rate; i++) {
start.poly[i] = ((maxcoeff - startcoeff) / 2) + startcoeff + 1;
}
start.conv = conv_create(rate, order, start.poly);
size_t num_scratches = 4;
float *weights;
conv_testbench **scratches = malloc(num_scratches * sizeof(conv_testbench *));
double *eb_n0;
for (size_t i = 0; i < num_scratches; i++) {
scratches[i] = resize_conv_testbench(NULL, conv_enclen, start.conv, max_block_len);
}
switch (order) {
case 6:
eb_n0 = (double[]){6.0, 5.5, 5.0, 4.5};
weights = (float[]){8000, 400, 20, 1};
break;
case 7:
eb_n0 = (double[]){5.5, 5.0, 4.5, 4.0};
weights = (float[]){8000, 400, 20, 1};
break;
case 8:
case 9:
eb_n0 = (double[]){5.0, 4.5, 4.0, 3.5};
weights = (float[]){8000, 400, 20, 1};
break;
default:
eb_n0 = (double[]){4.5, 4.0, 3.5, 3.0};
weights = (float[]){8000, 400, 20, 1};
}
test(rate, order, start, scratches, num_scratches, weights, n_bytes, eb_n0, bpsk_bit_energy, n_iter, bpsk_voltage);
free(start.poly);
conv_destroy(start.conv);
for (size_t i = 0; i < num_scratches; i++) {
free_scratch(scratches[i]);
}
free(scratches);
return 0;
}

View File

@ -0,0 +1,350 @@
#include <stdbool.h>
#include <float.h>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <stddef.h>
#include <limits.h>
#include <pthread.h>
#include <signal.h>
#if HAVE_SSE
#include "correct/util/error-sim-sse.h"
typedef correct_convolutional_sse conv_t;
static conv_t*(*conv_create)(size_t, size_t, const uint16_t *) = correct_convolutional_sse_create;
static void(*conv_destroy)(conv_t *) = correct_convolutional_sse_destroy;
static size_t(*conv_enclen)(void *, size_t) = conv_correct_sse_enclen;
static void(*conv_encode)(void *, uint8_t *, size_t, uint8_t *) = conv_correct_sse_encode;
static void(*conv_decode)(void *, uint8_t *, size_t, uint8_t *) = conv_correct_sse_decode;
#else
#include "correct/util/error-sim.h"
typedef correct_convolutional conv_t;
static conv_t*(*conv_create)(size_t, size_t, const uint16_t *) = correct_convolutional_create;
static void(*conv_destroy)(conv_t *) = correct_convolutional_destroy;
static size_t(*conv_enclen)(void *, size_t) = conv_correct_enclen;
static void(*conv_encode)(void *, uint8_t *, size_t, uint8_t *) = conv_correct_encode;
static void(*conv_decode)(void *, uint8_t *, size_t, uint8_t *) = conv_correct_decode;
#endif
typedef struct {
conv_t *conv;
correct_convolutional_polynomial_t *poly;
} conv_tester_t;
void shuffle(int *a, size_t len) {
for (size_t i = 0; i < len - 2; i++) {
size_t j = rand() % (len - i) + i;
int temp = a[i];
a[i] = a[j];
a[j] = temp;
}
}
int rand_geo(float p, int max) {
int geo = 1;
while (geo < max) {
if (rand() / (float)RAND_MAX > p) {
geo++;
} else {
break;
}
}
return geo;
}
void next_neighbor(correct_convolutional_polynomial_t *start,
correct_convolutional_polynomial_t *neighbor, size_t rate, size_t order) {
int coeffs[rate * (order - 2)];
for (int i = 0; i < rate * (order - 2); i++) {
coeffs[i] = i;
}
shuffle(coeffs, rate * (order - 2));
memcpy(neighbor, start, rate * sizeof(correct_convolutional_polynomial_t));
size_t nflips = rand_geo(0.4, rate * (order - 2));
for (int i = 0; i < nflips; i++) {
ptrdiff_t index = coeffs[i] / (order - 2);
// decide which bit to flip
// we avoid the edge bits to prevent creating a degenerate poly
neighbor[index] ^= 1 << (coeffs[i] % (order - 2) + 1);
}
}
bool accept(float cost_a, float cost_b, double temperature) {
if (cost_b < cost_a) {
return true;
}
float p = (float)(rand()) / (float)(RAND_MAX);
return exp((cost_a - cost_b) / (cost_a * temperature)) > p;
}
typedef struct {
size_t rate;
size_t order;
correct_convolutional_polynomial_t *poly;
unsigned int distance;
conv_testbench *scratch;
size_t msg_len;
double eb_n0;
double bpsk_voltage;
double bpsk_bit_energy;
} thread_args;
const size_t max_block_len = 16384;
void *find_cost_thread(void *vargs) {
thread_args *args = (thread_args *)vargs;
conv_t *conv;
uint8_t *msg = malloc(max_block_len);
conv = conv_create(args->rate, args->order, args->poly);
args->distance = 0;
conv_testbench *scratch = args->scratch;
size_t bytes_remaining = args->msg_len;
while (bytes_remaining) {
// in order to keep memory usage constant, we separate the msg into
// blocks and send each one through
// each time we do this, we have to calculate a new noise for each
// testbench
size_t block_len = (max_block_len < bytes_remaining) ? max_block_len : bytes_remaining;
bytes_remaining -= block_len;
for (unsigned int j = 0; j < block_len; j++) {
msg[j] = rand() % 256;
}
scratch = resize_conv_testbench(scratch, conv_enclen, conv, block_len);
scratch->encode = conv_encode;
scratch->encoder = conv;
scratch->decode = conv_decode;
scratch->decoder = conv;
build_white_noise(scratch->noise, scratch->enclen, args->eb_n0, args->bpsk_bit_energy);
args->distance += test_conv_noise(scratch, msg, block_len, args->bpsk_voltage);
}
conv_destroy(conv);
free(msg);
pthread_exit(NULL);
}
float find_cost(size_t rate, size_t order, correct_convolutional_polynomial_t *poly, size_t msg_len,
conv_testbench **scratches, size_t num_scratches, float *weights, double *eb_n0,
double bpsk_voltage, double bpsk_bit_energy) {
thread_args *args = malloc(num_scratches * sizeof(thread_args));
pthread_t *threads = malloc(num_scratches * sizeof(pthread_t));
for (size_t i = 0; i < num_scratches; i++) {
args[i].rate = rate;
args[i].order = order;
args[i].poly = poly;
args[i].scratch = scratches[i];
args[i].msg_len = msg_len;
args[i].eb_n0 = eb_n0[i];
args[i].bpsk_voltage = bpsk_voltage;
args[i].bpsk_bit_energy = bpsk_bit_energy;
pthread_attr_t attr;
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
pthread_create(&threads[i], &attr, find_cost_thread, &args[i]);
}
for (size_t i = 0; i < num_scratches; i++) {
pthread_join(threads[i], NULL);
}
float cost = 0;
printf("poly:");
for (size_t i = 0; i < rate; i++) {
printf(" %06o", poly[i]);
}
printf(" error:");
for (size_t i = 0; i < num_scratches; i++) {
cost += weights[i] * args[i].distance;
printf(" %.2e@%.1fdB", (args[i].distance / (float)(msg_len * 8)), eb_n0[i]);
}
printf("\n");
free(args);
free(threads);
return cost;
}
static bool terminated = false;
void sig_handler(int sig) {
if (sig == SIGINT || sig == SIGTERM || sig == SIGHUP) {
if (!terminated) {
terminated = true;
printf("terminating after current poly\n");
}
}
}
void search_simulated_annealing(size_t rate, size_t order, size_t n_steps, conv_tester_t *start,
size_t n_bytes, conv_testbench **scratches, size_t num_scratches,
float *weights, double start_temperature, double cooling_factor,
double *eb_n0, double bpsk_voltage, double bpsk_bit_energy) {
// perform simulated annealing to find the optimal polynomial
float cost = find_cost(rate, order, start->poly, n_bytes, scratches, num_scratches, weights,
eb_n0, bpsk_voltage, bpsk_bit_energy);
correct_convolutional_polynomial_t *neighbor_poly =
malloc(rate * sizeof(correct_convolutional_polynomial_t));
correct_convolutional_polynomial_t *state =
malloc(rate * sizeof(correct_convolutional_polynomial_t));
correct_convolutional_polynomial_t *best =
malloc(rate * sizeof(correct_convolutional_polynomial_t));
float best_cost = cost;
memcpy(state, start->poly, rate * sizeof(correct_convolutional_polynomial_t));
memcpy(best, start->poly, rate * sizeof(correct_convolutional_polynomial_t));
double temperature = start_temperature;
for (size_t i = 0; i < n_steps; i++) {
next_neighbor(state, neighbor_poly, rate, order);
float neighbor_cost =
find_cost(rate, order, neighbor_poly, n_bytes, scratches, num_scratches, weights, eb_n0,
bpsk_voltage, bpsk_bit_energy);
if (accept(cost, neighbor_cost, temperature)) {
// we're moving to our neighbor's house
memcpy(state, neighbor_poly, rate * sizeof(correct_convolutional_polynomial_t));
cost = neighbor_cost;
} else {
// actually where we live now is nice
}
if (cost < best_cost) {
best_cost = cost;
memcpy(best, state, rate * sizeof(correct_convolutional_polynomial_t));
}
temperature *= cooling_factor;
if (terminated) {
break;
}
}
printf("last state:");
for (size_t i = 0; i < rate; i++) {
printf(" %06o", state[i]);
}
printf("\n");
printf("best state:");
for (size_t i = 0; i < rate; i++) {
printf(" %06o", best[i]);
}
memcpy(start->poly, best, rate * sizeof(correct_convolutional_polynomial_t));
free(state);
free(best);
free(neighbor_poly);
}
void test_sa(size_t rate, size_t order, conv_tester_t start, conv_testbench **scratches,
size_t num_scratches, float *weights, size_t n_bytes, double *eb_n0,
double bpsk_bit_energy, size_t n_iter, double bpsk_voltage) {
for (size_t i = 0; i < n_iter; i++) {
double temperature = (i == 0) ? 0.5 : 250;
double cooling_factor = (i == 0) ? 0.985 : 0.95;
size_t n_steps = (i == 0) ? 500 : 100;
search_simulated_annealing(rate, order, n_steps, &start, n_bytes, scratches, num_scratches,
weights, temperature, cooling_factor, eb_n0, bpsk_voltage,
bpsk_bit_energy);
}
}
int main(int argc, char **argv) {
srand(time(NULL));
signal(SIGINT, sig_handler);
signal(SIGTERM, sig_handler);
signal(SIGHUP, sig_handler);
size_t rate, order, n_bytes, n_iter;
sscanf(argv[1], "%zu", &rate);
sscanf(argv[2], "%zu", &order);
sscanf(argv[3], "%zu", &n_bytes);
sscanf(argv[4], "%zu", &n_iter);
double bpsk_voltage = 1.0 / sqrt(2.0);
double bpsk_sym_energy = 2 * pow(bpsk_voltage, 2.0);
double bpsk_bit_energy = bpsk_sym_energy / 1.0;
bpsk_bit_energy = bpsk_sym_energy * rate; // rate bits transmitted for every input bit
// correct_convolutional_polynomial_t maxcoeff = (1 << order) - 1;
correct_convolutional_polynomial_t startcoeff = (1 << (order - 1)) + 1;
conv_tester_t start;
start.poly = malloc(rate * sizeof(correct_convolutional_polynomial_t));
for (size_t i = 0; i < rate; i++) {
start.poly[i] = ((rand() % (1 << (order - 2))) << 1) + startcoeff;
}
start.conv = conv_create(rate, order, start.poly);
size_t num_scratches = 4;
float *weights;
conv_testbench **scratches = malloc(num_scratches * sizeof(conv_testbench *));
double *eb_n0;
for (size_t i = 0; i < num_scratches; i++) {
scratches[i] = resize_conv_testbench(NULL, conv_enclen, start.conv, max_block_len);
}
switch (order) {
case 6:
eb_n0 = (double[]){6.0, 5.5, 5.0, 4.5};
weights = (float[]){8000, 400, 20, 1};
break;
case 7:
case 8:
eb_n0 = (double[]){5.5, 5.0, 4.5, 4.0};
weights = (float[]){8000, 400, 20, 1};
break;
case 9:
case 10:
eb_n0 = (double[]){5.0, 4.5, 4.0, 3.5};
weights = (float[]){8000, 400, 20, 1};
break;
case 11:
case 12:
case 13:
eb_n0 = (double[]){4.5, 4.0, 3.5, 3.0};
weights = (float[]){8000, 400, 20, 1};
break;
default:
eb_n0 = (double[]){3.5, 3.0, 2.5, 2.0};
weights = (float[]){8000, 400, 20, 1};
}
test_sa(rate, order, start, scratches, num_scratches, weights, n_bytes, eb_n0, bpsk_bit_energy,
n_iter, bpsk_voltage);
free(start.poly);
conv_destroy(start.conv);
for (size_t i = 0; i < num_scratches; i++) {
free_scratch(scratches[i]);
}
free(scratches);
return 0;
}

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