Compare commits

...
429 Commits
Author SHA1 Message Date
Jonathan Naylor 7f339556f4 Add the ST-Micro licences. 2023-10-29 20:32:18 +00:00
Jonathan Naylor 0189520ab2 Add the LL library files and clean up some indentation. 2023-10-28 20:30:36 +01:00
Jonathan Naylor 5d2d37f44b Remove the submodules. 2023-10-28 16:32:48 +01:00
Jonathan Naylor 5ede02212a Remove Due, Teensy, and STM32F1xx support. 2023-10-27 16:23:49 +01:00
Jonathan Naylor 85d3086d4c Restart the RSSI ADC conversion in the STM32 interrupt to match the signal ADC. 2023-10-10 20:06:50 +01:00
Jonathan Naylor ccf3b7301e Make the type correct for silence frames. 2023-10-10 20:03:01 +01:00
Jonathan Naylor 6b3a811ae7 Simplify the serial repeater code. 2023-10-05 19:49:17 +01:00
Jonathan Naylor 3e079f58ad Add RSSI reporting to FM and AX.25 2023-08-02 17:34:52 +01:00
Jonathan Naylor 7ef0d992d9 Improve the status reporting for FM mode. 2023-01-18 14:30:02 +00:00
Jonathan Naylor bf23a94038 Merge pull request #334 from n0mjs710/master 2023-01-09 15:17:17 +00:00
Cort Buffington b2755864ef Adding support for WA0EDA STM32-DVM-MTR2K v2.0d with FM LED, and a (commented) line to compile for 500000 serial port speed to support the WA0EDA MODEMs and others that use Armbian + AllWinner H2/H3 SOC that does not support 4600800. 2023-01-09 07:06:42 -06:00
Jonathan Naylor 7276ca3929 Update Version.h 2022-11-21 19:14:24 +00:00
Jonathan Naylor d14b9dede3 Update Version.h 2022-11-21 19:14:14 +00:00
Jonathan Naylor de87d77ad6 Merge pull request #330 from spongegovo/pocsagax25_fix
Fixed Serial protocol issue where MMDVMHost could not send POCSAG or AX25 to the MMDVM
2022-11-21 19:13:21 +00:00
spongegovo 2626ad5580 Update SerialPort.cpp 2022-11-20 09:15:59 +11:00
Jonathan Naylor 031b078e76 Merge pull request #327 from shawnchain/fix_ax25_dac_overflow_error 2022-09-13 14:09:12 +01:00
Shawn Chain 5d987969a9 The AX25 sine value ranges from 0-4095, and inside io.write() will perform the calculation (value * q15_t(txLevel) >> 15) which may exceed 4096 and cause the DAC Overflow error 2022-09-13 20:18:03 +08:00
Jonathan Naylor f898390956 Bump the version date. 2021-12-20 23:00:13 +00:00
Jonathan Naylor f8d1cc7aed Fix crash on long data frames. 2021-12-20 22:57:40 +00:00
Jonathan Naylor cf9fa93cb9 Include the ARM copyright in the README file. 2021-12-18 22:38:26 +00:00
Jonathan Naylor 69adaf2ebb Update SerialTeensy.cpp 2021-12-18 22:34:24 +00:00
Jonathan Naylor 7f4ae790ba Update STM32Utils.h 2021-12-18 22:31:48 +00:00
Jonathan Naylor 416fc8fc8b Update the README. 2021-12-13 10:31:10 +00:00
Jonathan Naylor 5b79356ddb Merge pull request #324 from 1tilen/master
Added PB15 to comment with pins, changed STM32F4 to STM32F7 in line 23
2021-11-14 19:51:29 +00:00
Tilen 26fc87aca6 Added PB15 to comment with pins, changed STM32F4 to STM32F7 in line 23 2021-11-14 19:21:35 +01:00
Jonathan Naylor 54745130c2 Add the transmit function. 2021-10-27 21:28:43 +01:00
Jonathan Naylor f65d52bf2f Add M17 calibration mode. 2021-10-27 19:37:58 +01:00
Jonathan Naylor 5800b33f21 Split the DMR and YSF filtering 2021-10-26 20:51:21 +01:00
Jonathan Naylor 105dba2c27 Merge branch 'master' of github.com:g4klx/MMDVM 2021-10-26 17:43:51 +01:00
Jonathan Naylor 777cc9f2ea Fix typo 2021-10-26 17:43:34 +01:00
Jonathan Naylor e879b4615a Merge branch 'master' of https://github.com/g4klx/MMDVM 2021-10-25 20:03:36 +01:00
Jonathan Naylor 8d69fc59be Update the README file 2021-10-25 20:03:17 +01:00
Jonathan Naylor 2f4e9cc269 Remove unused configuration option 2021-10-25 19:47:31 +01:00
Jonathan Naylor ee07f76bd5 Split the repeater and link mode audio paths. 2021-09-30 18:16:51 +01:00
Jonathan Naylor d063a1da1e Change the EOT handling on TX. 2021-09-19 14:25:12 +01:00
Jonathan Naylor 6a4dad4c44 Change the LinkMode state machine. 2021-09-06 22:50:40 +01:00
Jonathan Naylor ed6bd66fab Rename SimpleMode to LinkMode. 2021-09-06 21:53:01 +01:00
Jonathan Naylor 1a07a6f0d1 Add more details to the simple FM state machine. 2021-09-05 19:46:01 +01:00
Jonathan Naylor 70bf47f93e Add a bery simple FM mode for internet gatewaying. 2021-09-05 19:06:56 +01:00
Jonathan Naylor a5eaafc7e0 Change a method name. 2021-08-26 17:39:52 +01:00
Jonathan Naylor 2200945857 Change the EOF sync pattern for simplicity. 2021-08-26 16:50:18 +01:00
Jonathan Naylor 63a8e61a45 Update to send and receive the new EOF marker. 2021-08-25 21:11:09 +01:00
Jonathan Naylor 7275f65e44 Reset the transmit levels to be correct. 2021-08-23 21:07:17 +01:00
Jonathan Naylor 2aabdb61ab Remove the last traces of M17 packet mode and fix a buffer overrun bug. 2021-08-08 18:55:09 +01:00
Jonathan Naylor 96c0e5b141 Fix compiler warnings when building for POG style boards. 2021-07-19 21:20:57 +01:00
Jonathan Naylor 9c883cfafd Revert "Restore SerialRB for POG builds."
This reverts commit 8a1ab88c3a.
2021-07-01 22:58:59 +01:00
Jonathan Naylor 8a1ab88c3a Restore SerialRB for POG builds. 2021-07-01 22:28:59 +01:00
Jonathan Naylor f4e1c0b401 Fix a potential issue with reporting the wrong command type in ACK and NAK messages. 2021-06-17 16:55:59 +01:00
Jonathan Naylor 43b53fe2fc Add a dummy return for the setting of the FM parameters when FM is not enabled. 2021-05-08 23:48:52 +01:00
Jonathan Naylor 6517229f87 Bump the version date. 2021-05-08 23:24:36 +01:00
Jonathan Naylor d0557ab723 Fix merge mistake which disabled serial access to the RB V5 board. 2021-05-08 23:22:25 +01:00
Jonathan Naylor b5d106dcb6 Merge branch 'master' into M17_AX25_FM 2021-05-05 21:01:19 +01:00
Jonathan Naylor 34cbff41c9 Merge pull request #317 from N4IRS/master 2021-05-02 15:00:12 +01:00
Steve N4IRS 752e13821f Add STM32F7-DVM board 2021-05-02 07:19:24 -04:00
Jonathan Naylor 86b45c15eb Merge branch 'master' into M17_AX25_FM 2021-04-20 20:38:14 +01:00
Jonathan Naylor 4fa0e052f8 Merge pull request #316 from N4IRS/master
RB STM32_DVM_F7 support
2021-04-20 12:51:10 +01:00
Steve N4IRS 0736a5cbe8 RB STM32_DVM_F7 support 2021-04-18 09:50:46 -04:00
Jonathan Naylor 6ffb68450c Allow for hex dumps of modem data by the host. 2021-04-11 18:15:19 +01:00
Jonathan Naylor 1ad20fd4a0 Disable packet mode in M17. 2021-04-07 19:02:04 +01:00
Jonathan Naylor 34f6dfc5bb Simplification of the M17 receiver. 2021-03-14 18:24:30 +00:00
Jonathan Naylor 1e065ba17f Fix and simplify the M17 receiver. 2021-03-14 17:53:28 +00:00
Jonathan Naylor 1df7d7a7fc Change the FM serial block size to 80. 2021-03-07 19:01:46 +00:00
Jonathan Naylor 7e919b12f7 Clean up the M17 synchronisation logic. 2021-01-02 12:24:11 +00:00
Jonathan Naylor bada4d9285 Add M17 packet mode support. 2021-01-01 13:17:02 +00:00
Jonathan Naylor 9ae4a5376d Merge branch 'master' into M17_AX25_FM 2021-01-01 13:01:56 +00:00
Jonathan Naylor 8038ce9c9c Merge pull request #308 from shawnchain/drcc_dvm_hhp_board_support
Add DRCC_DVM_HHP446 board support
2021-01-01 12:32:01 +00:00
Shawn Chain 842dcdb5c5 Add DRCC_DVM_HHP446 board support 2021-01-01 19:48:07 +08:00
Jonathan Naylor f7ead5cc0e Update the M17 sync vectors. 2020-12-26 12:42:16 +00:00
Jonathan Naylor b155597693 Merge branch 'master' into M17_AX25_FM 2020-12-14 09:53:38 +00:00
Jonathan Naylor 7148cf9f7d Add I2C support. 2020-12-14 09:46:53 +00:00
Jonathan Naylor 9440b43114 Simplify the D-Star fast data support. 2020-12-14 09:45:53 +00:00
Jonathan Naylor c06a83660f Merge pull request #306 from timclassic/dstar-match-full-last-data-frame
Detect full 48 bits of last data frame in a D-Star transmission
2020-12-14 09:37:05 +00:00
Tim Stewart 657e71238d Detect full 48 bits of last data frame in a transmission
While testing new support for DV Fast Data, I ran across a particular
image that reliably generated a bit sequence that the MDMVM firmware
interpreted as an end-of-transmission.  I dug a bit and discovered
that MMDVM only matches on 32 bits of the last data frame instead of
the full 48 bits.

See http://www.arrl.org/files/file/D-STAR.pdf section 2.1.2, item (6)
for details.
2020-12-05 13:37:06 -05:00
Jonathan Naylor 510d433906 Merge pull request #305 from dg0tm/M17_AX25_FM
Fixing Arduino Unique Identifier byte order
2020-11-28 15:27:16 +00:00
Christoph Kottke ff39a9031b Fixing Arduino Unique Identifier byte order 2020-11-28 16:25:08 +01:00
Jonathan Naylor 4f3aa8b7e1 Merge pull request #304 from dg0tm/M17_AX25_FM
Fixing Arduino UUID support
2020-11-28 12:13:35 +00:00
Christoph Kottke a35b8f929a Fixing Arduino UUID support 2020-11-28 08:51:58 +01:00
Jonathan Naylor 6d0335b357 Update for latest M17 specification. 2020-11-26 10:03:54 +00:00
Jonathan Naylor 54f4dcabf0 Increase serial speed to 460800. 2020-11-24 16:22:14 +00:00
Jonathan Naylor 19e2ccf150 Bump the version date. 2020-11-20 10:36:45 +00:00
Jonathan Naylor 0c4f49fa68 Add FM LED pin definition for the Repeater Builder V4 board. 2020-11-20 10:35:19 +00:00
Jonathan Naylor 98ebefe84b Update module pointers. 2020-11-20 10:31:11 +00:00
Jonathan Naylor 029e7eef4a Fix bugs. 2020-11-18 20:35:07 +00:00
Jonathan Naylor ca4fff2ba6 Remove unused I2C code and fix buffer handling bugs. 2020-11-17 10:36:00 +00:00
Jonathan Naylor 23ba73cabd Disable I2C in M17_AX25_FM. 2020-11-13 15:22:35 +00:00
Jonathan Naylor 519af80ac4 Add the beginnings of I2C support. 2020-11-13 15:20:54 +00:00
Jonathan Naylor c5b542f438 Allow serial data to be sent back to the host. 2020-11-13 12:09:10 +00:00
Jonathan Naylor 3503e0cc2a Merge branch 'master' into M17_AX25_FM 2020-11-12 09:15:40 +00:00
Jonathan Naylor 955578789d Make the M17 receiver less sensitive to noise. 2020-11-11 18:30:49 +00:00
Andy CA6JAU 061e10e395 Fixing deploy-pi and deploy-pi-f7 (M0VSE advice) 2020-11-11 15:23:14 -03:00
Jonathan Naylor fa9040fdf0 Fix compile issue for the serial repeater. 2020-11-11 17:14:05 +00:00
Jonathan Naylor 8240225371 Set the Config.h defaults correctly for the ZUM v0.9 board. 2020-11-11 17:11:22 +00:00
Jonathan Naylor f2c7c19444 Strip the version out of SerialPort.cpp 2020-11-09 17:29:55 +00:00
Jonathan Naylor 2e5f174cdd Add the modem capabilities data to the version message. 2020-11-09 16:22:44 +00:00
Jonathan Naylor d144ce6f1c Small changes to the serial protocol. 2020-11-09 14:23:43 +00:00
Jonathan Naylor 31744a237a Use the D-Star correlator receiver. 2020-11-09 11:50:02 +00:00
Jonathan Naylor 46c0958704 Add the boxcar filter as an option for NXDN. 2020-11-09 11:25:03 +00:00
Jonathan Naylor 99d2a0d822 Add UDID support. 2020-11-09 10:23:57 +00:00
Jonathan Naylor 81518bf74c Make AX.25, DMR, P25, NXDN and FM selectable at compile time. 2020-11-08 22:23:27 +00:00
Jonathan Naylor dd5a465a39 Make D-Star, System Fusion, M17, and POCSAG optional. 2020-11-08 21:28:26 +00:00
Jonathan Naylor a345586ee9 Update the protocol version. 2020-11-06 15:14:02 +00:00
Jonathan Naylor 55c89a4413 Merge branch 'AX25_FM' into M17_AX25_FM 2020-11-06 15:06:00 +00:00
Jonathan Naylor 60f87072ba Rescale the TX filter for M17. 2020-10-15 09:40:35 +01:00
Jonathan Naylor f2d2033733 Add the sync and RRC 0.5 data and code. 2020-10-14 13:29:23 +01:00
Jonathan Naylor 0334b5a791 Handle the M17 mode LED pins(-ish) 2020-10-14 11:55:31 +01:00
Jonathan Naylor a62fd814ae Begin M17 support. 2020-10-14 10:52:30 +01:00
Jonathan Naylor 02000c8049 Merge branch 'master' into AX25_FM 2020-09-01 13:27:57 +01:00
Jonathan Naylor 2509ab5ba1 Fix the self-test LEDs. 2020-09-01 13:27:29 +01:00
Jonathan Naylor 2de9e4d533 Merge branch 'master' into AX25_FM 2020-09-01 09:59:31 +01:00
Jonathan Naylor fda1e3dcf4 More LED fixes. 2020-09-01 09:57:49 +01:00
Jonathan Naylor cb3ed795d0 Merge branch 'master' into AX25_FM 2020-08-31 16:09:44 +01:00
Jonathan Naylor 632ddda68b Change the handling of the mode LEDs. 2020-08-31 16:06:59 +01:00
Jonathan Naylor b6093406ad Fix missing AX25 class definition. 2020-08-11 16:39:19 +01:00
Jonathan Naylor 8d9b49bdb0 Merge pull request #297 from F4FXL/AX25_FM
Add some delay to squelch
2020-08-05 22:16:37 +01:00
Geoffrey Merck 625ec93af8 Remove unused variable 2020-08-05 21:17:05 +02:00
Geoffrey Merck b2111553c6 Correct comment 2020-08-05 21:15:03 +02:00
Geoffrey Merck 252d54a484 Add some delay to squelch 2020-08-05 21:11:32 +02:00
Jonathan Naylor 1ad9799123 Merge branch 'AX25' into AX25_FM 2020-08-03 13:09:15 +01:00
Jonathan Naylor 6d67b9f104 Merge branch 'master' into AX25 2020-08-03 13:08:48 +01:00
Jonathan Naylor fb85505433 Merge pull request #296 from msraya/patch-1
YSF pictures can go through modem
2020-08-03 08:43:11 +01:00
Manuel Sánchez Raya 823b91c97d Update YSFRX.cpp
Lower MAX_SYNC_FRAMES to 2, so decoder can recover and Yaesu pictures can pass through the modem without problem.
2020-08-03 09:17:07 +02:00
Jonathan Naylor 2a001f491d Simplify the CTCSS and Noise Squelch decoders and logic. 2020-07-31 09:20:55 +01:00
Jonathan Naylor b5ba384495 Fix a couple of minor bugs. 2020-07-28 14:24:51 +01:00
Jonathan Naylor d8f138066e Add an experimental noise squelch. 2020-07-28 13:55:50 +01:00
Jonathan Naylor 6964251122 Merge branch 'AX25' into AX25_FM 2020-07-28 12:40:42 +01:00
Jonathan Naylor 0fca178bd7 Merge branch 'master' into AX25 2020-07-28 12:37:07 +01:00
Jonathan Naylor a60ecb3e57 Merge pull request #295 from n0mjs710/master
Added pin definition for FM mode LED (WA0EDA Boards)
2020-07-21 16:21:08 +01:00
Cort Buffington a2978d9e91 Removed a local change to not contaminate the repo 2020-07-21 08:27:02 -05:00
Cort Buffington e304f5cce2 Added pin assignment for FM mode LED (WA0EDA) 2020-07-21 08:19:18 -05:00
Jonathan Naylor 99a7df7c13 Merge pull request #294 from n0mjs710/master
Add support for WA0EDA MTR2000 & MASTR III boards
2020-07-21 06:08:08 +01:00
Cort Buffington 6dfe1a9271 Add support for WA0EDA MTR2000 & MASTR3 boards 2020-07-20 17:11:29 -05:00
Jonathan Naylor 9ff59570c7 Merge branch 'AX25' into AX25_FM 2020-07-15 10:42:43 +01:00
Jonathan Naylor d5e9b5a315 Merge branch 'master' into AX25 2020-07-15 08:49:40 +01:00
Jonathan Naylor 1ac0628c1c Improve the code efficiency slightly. 2020-07-14 14:54:47 +01:00
Jonathan Naylor dc41fd83d2 Test the use of a reverse burst at the end of a transmission. 2020-07-14 12:20:42 +01:00
Jonathan Naylor 20013e3adc Make Use COS As Lockout a run-time parameter and allow for different access modes. 2020-07-13 17:13:01 +01:00
Jonathan Naylor 5960fb97f3 Merge branch 'AX25' into AX25_FM 2020-07-12 15:28:00 +01:00
Jonathan Naylor 8f8dc92a14 Merge branch 'master' into AX25 2020-07-12 15:24:50 +01:00
Jonathan Naylor ccdbe126e0 Fix the timeout tones. 2020-07-12 15:22:35 +01:00
Jonathan Naylor d29a0bc3a6 Merge branch 'AX25' into AX25_FM 2020-07-12 10:48:43 +01:00
Jonathan Naylor 4ff057069b Merge branch 'master' into AX25 2020-07-12 10:48:20 +01:00
Jonathan Naylor f8d8f85841 Small simplification of the timeout tones. 2020-07-12 10:47:43 +01:00
Jonathan Naylor ad77fd60fd Remove KerchunkTX. 2020-07-07 17:57:31 +01:00
Jonathan Naylor aab8f5469f Add timeouts to the FM simplex state machine. 2020-07-06 10:56:35 +01:00
Jonathan Naylor f1d6a8b36e Add DCD LED control. 2020-07-06 10:03:48 +01:00
Jonathan Naylor 843997ccad Merge pull request #293 from F4FXL/AX25_FM
Fix wrong frame type
2020-07-06 06:52:50 +01:00
Geoffrey Merck d5f2d1c382 Fix wrong frame type 2020-07-04 12:15:33 +02:00
Jonathan Naylor c99f50575d Add a simpe simplex FM controller state machine. 2020-07-01 13:02:14 +01:00
Jonathan Naylor 29c8cf9414 Add AX.25 Slot Time and P-Persist processing for simplex work. 2020-07-01 12:33:08 +01:00
Jonathan Naylor 2c6e2c2a11 Remove unneeded zeroes from the band pass FIR filter. 2020-06-30 17:09:09 +01:00
Jonathan Naylor 8d10555dc9 Reduce the low pass filter a little. 2020-06-30 15:35:58 +01:00
Jonathan Naylor 14d5098018 Rename FMDownsampler to FMDownSampler. 2020-06-30 12:44:02 +01:00
Jonathan Naylor 52a351d0f1 Slight tweak to the mark and space. 2020-06-29 16:11:56 +01:00
Jonathan Naylor 43f84ae968 Simplify the pre-emphasis code for AX.25. 2020-06-29 15:59:46 +01:00
Jonathan Naylor a73376671c Fix preamble and NRZI. 2020-06-28 15:27:58 +01:00
Jonathan Naylor 759efd1da4 Merge pull request #292 from F4FXL/AX25_FM
correct preamble and NRZI
2020-06-28 15:25:45 +01:00
Geoffrey Merck ea0c1953cc correct preamble and NRZI 2020-06-28 11:22:10 +02:00
Jonathan Naylor a29cb23a75 Remove TX Twist. 2020-06-27 22:55:16 +01:00
Jonathan Naylor bb66c72ef3 Merge branch 'FM_Ext' into AX25_FM 2020-06-25 10:41:48 +01:00
Jonathan Naylor 2da28ede64 Increase the maximum AX25 frame size. 2020-06-24 13:14:10 +01:00
Jonathan Naylor a7ac55795d Fix obvious AX25 TX data bug. 2020-06-24 12:46:27 +01:00
Jonathan Naylor 835ef46aef Bump the version date. 2020-06-24 11:16:02 +01:00
Jonathan Naylor 3de10fe98b First version of the AX25 TX functionality. 2020-06-24 11:14:02 +01:00
Jonathan Naylor 7ad70d04a4 Add a dummy AX25 transmit function and make AX25 RX changes. 2020-06-23 10:34:19 +01:00
Jonathan Naylor e210062365 Add the twist processing to the AX25 RX. 2020-06-21 21:40:40 +01:00
Jonathan Naylor f9fcdc5292 Begin adding AX25 TX. 2020-06-21 19:16:02 +01:00
Jonathan Naylor 0ea732780d Implement Kerchunk TX option. 2020-06-20 21:03:11 +01:00
Jonathan Naylor 33d922b8c2 Handle the incoming data offset correctly. 2020-06-19 13:27:45 +01:00
Jonathan Naylor 114c2bcb15 Handle extended packet lengths. 2020-06-19 13:16:47 +01:00
Jonathan Naylor 6dbda2795a Miscalculated the address length. 2020-06-17 22:40:09 +01:00
Jonathan Naylor 6a80d0ec09 Fix minimum packet size. 2020-06-17 22:33:13 +01:00
Jonathan Naylor 0e8f20e1cc Bump the version date. 2020-06-17 16:02:15 +01:00
Jonathan Naylor af11be16dc First woring AX.25 decoder (in simulation). 2020-06-17 15:28:41 +01:00
Jonathan Naylor e332dbba8e Add the correct CCITT checksum table. 2020-06-11 12:59:30 +01:00
Jonathan Naylor 746d915bf9 Rescale one of the filters for the MMDVM sample rate. 2020-06-11 12:14:36 +01:00
Jonathan Naylor c896cf823e Add mobilinkd copyright. 2020-06-11 10:04:09 +01:00
Jonathan Naylor c2959466fd Code complete, but untested. 2020-06-11 10:02:11 +01:00
Jonathan Naylor 121c76f3d8 More filtering added. 2020-06-10 16:38:10 +01:00
Jonathan Naylor 22cb16f831 Add more frame processing. 2020-06-10 16:09:45 +01:00
Jonathan Naylor 57e18e337f Add the seperate AX25Frame class. 2020-06-10 13:53:18 +01:00
Jonathan Naylor e1d1ac4a4d More work on adding AX.25 decoding. 2020-06-10 12:07:04 +01:00
Jonathan Naylor 64fe59382f Start on the actual AX.25 demodulator. 2020-06-09 14:57:06 +01:00
Jonathan Naylor a2e2853241 Begin AX.25 development. 2020-06-08 15:02:12 +01:00
Jonathan Naylor 598d32287d Add alternate FM LEDs for the POG board. 2020-06-01 16:55:13 +01:00
Jonathan Naylor 53d8cfa360 Revert IOSTM_CMSIS.cpp to 5c9abf2 2020-06-01 16:51:59 +01:00
Jonathan Naylor 1309ad9326 Merge pull request #286 from F4FXL/FM_Ext
Add forgotten file for large frame handling
2020-06-01 09:55:25 +01:00
Geoffrey Merck 411d439d78 Add forgotten file for large frame handling 2020-06-01 10:29:05 +02:00
Jonathan Naylor ec9428d63e Merge pull request #285 from F4FXL/FM_Ext
Habdle full frame length
2020-05-31 21:14:35 +01:00
Geoffrey Merck 2a4b28c35e return space as number of bytes 2020-05-31 22:11:28 +02:00
Geoffrey Merck 4f060c0047 Esnure frame size is 84 samples, correctly report space as number of frames 2020-05-31 21:50:06 +02:00
Jonathan Naylor 1ed3a4c9d5 Merge pull request #284 from F4FXL/FM_Ext
Avoid Buffer underruns
2020-05-31 11:26:27 +01:00
Geoffrey Merck f414288c9b Update speed comments 2020-05-31 11:45:17 +02:00
Geoffrey Merck 72cd2ce03e Ensure we have at least 75ms of audio before transmitting 2020-05-30 20:05:34 +02:00
Jonathan Naylor 9137af8e3f Merge pull request #281 from F4FXL/FM_Ext
Speed improvements and fixes for FM Ext
2020-05-24 07:56:45 +01:00
Geoffrey Merck cdfe3d0ec9 Clean up includes 2020-05-24 08:20:03 +02:00
Geoffrey Merck 4dfab06a50 Revert to GPIO_Fast_Speed 2020-05-24 08:11:32 +02:00
Geoffrey Merck 47649171fc Fix sample unpacking 2020-05-24 08:01:59 +02:00
Geoffrey Merck 0bd79fa440 Fix sample packing 2020-05-24 07:45:50 +02:00
Geoffrey Merck 26d055a67b Update filter generation script 2020-05-24 07:44:38 +02:00
Geoffrey Merck 5db1adb5ea #defines for serial speeds 2020-05-23 21:01:21 +02:00
Geoffrey Merck f86b5435bb Remove unneeded include 2020-05-23 15:30:00 +02:00
Geoffrey Merck 31f0e24588 Make serial speed a compile option 2020-05-23 08:57:30 +02:00
Geoffrey Merck 04d0b15545 Remove UART habndling Copy/Paste code 2020-05-23 08:28:23 +02:00
Geoffrey Merck f14222e77d Make sure buffer is continuously filled 2020-05-23 08:25:51 +02:00
Jonathan Naylor 7fabddd7f1 Update the README file. 2020-05-21 11:11:19 +01:00
Jonathan Naylor 5039dfbe68 Merge pull request #280 from F4FXL/FM_Ext
Fix Callsign at end and simplify Samples
2020-05-20 22:19:36 +01:00
Jonathan Naylor f9f81b9b8e Try and make the closing callsign appear.
(cherry picked from commit 063b21f999)
2020-05-20 23:11:22 +02:00
Geoffrey Merck 3cc5d67696 check acks 2020-05-20 22:51:22 +02:00
Geoffrey Merck 3f960f9fc5 Fix Callsignatend and simplify Samples 2020-05-20 22:30:55 +02:00
Jonathan Naylor 489853f200 Fix the TX Hang. 2020-05-20 15:27:16 +01:00
Jonathan Naylor 2cf2ce4dfa Fix the TX Hang handling. 2020-05-20 15:16:12 +01:00
Jonathan Naylor 96e1a765f9 Merge pull request #279 from F4FXL/FM_Ext
Remove SerialUSB for Arduino and remove uneeded class
2020-05-20 10:17:33 +01:00
Geoffrey Merck 04982c25c0 Remove SerialUSB for Arduino 2020-05-20 11:06:02 +02:00
Geoffrey Merck a3ffa9ed36 Remove no longer needed SerialRB class 2020-05-20 08:08:22 +02:00
Jonathan Naylor e7a22482db Set the COS LED on incoming RF transmissions. 2020-05-19 13:45:17 +01:00
Jonathan Naylor 5f29808b80 Set the COS LED correctly. 2020-05-19 12:09:44 +01:00
Jonathan Naylor 063b21f999 Try and make the closing callsign appear. 2020-05-18 11:09:56 +01:00
Jonathan Naylor 89b8641955 Merge pull request #278 from shawnchain/drcc_serial_bugfix
Drcc serial bugfix
2020-05-18 06:34:09 +01:00
Shawn Chain 6397c720e8 Generate bin map file for analysis 2020-05-18 12:19:22 +08:00
Shawn Chain 50c1e5aa3f update pin defs for drcc/nqf board 2020-05-18 12:18:44 +08:00
Shawn Chain 970d02773f Fix serial no write bug on DRCC board 2020-05-18 12:18:17 +08:00
Jonathan Naylor 625749a546 Fixed up the use of the writeFMEOT method. 2020-05-16 13:15:21 +01:00
Jonathan Naylor d75042dc4c Merge pull request #276 from F4FXL/FM_Ext
Add FM EOT
2020-05-16 12:57:33 +01:00
Geoffrey Merck 296ac88842 Correct length 2020-05-16 12:08:26 +02:00
Geoffrey Merck 48e863d1d0 Sent EOT on rf timeout 2020-05-15 21:19:26 +02:00
Geoffrey Merck 7b915f9cac Only send EOT when EXT is enabled 2020-05-15 21:06:16 +02:00
Geoffrey Merck e330c9f52a Fix typo 2020-05-15 21:05:57 +02:00
Geoffrey Merck 9470b1d6d3 Merge remote-tracking branch 'upstream/FM_Ext' into FM_Ext 2020-05-15 20:21:12 +02:00
Geoffrey Merck 388620b182 Add FM EOT 2020-05-15 18:53:34 +02:00
Jonathan Naylor 72e45177f3 Merge pull request #275 from F4FXL/FM_Ext
Minor fix, reduce memory usage
2020-05-14 22:19:27 +01:00
Geoffrey Merck 90b82621f2 Merge remote-tracking branch 'upstream/FM_Ext' into FM_Ext 2020-05-14 22:02:47 +02:00
Jonathan Naylor ff375abb0e Hold off the mode change until the ack and callsign have been
transmitted.
2020-05-14 12:10:37 +01:00
Geoffrey Merck cfcb7ed852 Really fix TX Buffer ovrflows,, reduce delay buffer memory footprint 2020-05-14 09:10:11 +02:00
Geoffrey Merck b245be464f Fix txbuffer overflows and bring back elegant while loop 2020-05-13 22:57:42 +02:00
Jonathan Naylor 139003d4c7 Merge pull request #274 from F4FXL/FM_Ext
Add define to use native USB port on Arduino
2020-05-13 20:19:41 +01:00
Geoffrey Merck c47eacd010 Add define to use native port on Arduino 2020-05-13 21:02:19 +02:00
Jonathan Naylor 6b01f12602 Merge branch 'FM' into FM_Ext 2020-05-13 12:03:12 +01:00
Jonathan Naylor 7169836621 Merge branch 'master' into FM 2020-05-13 12:01:19 +01:00
Jonathan Naylor c84d227242 Merge branch 'master' into TXHang 2020-05-13 12:00:23 +01:00
Jonathan Naylor 4f93c6022c Merge pull request #273 from F4FXL/FM_Ext
Send unsigned data and simplify downdampling code
2020-05-13 11:44:37 +01:00
Geoffrey Merck 81f6b6be53 Send usigned data and simplify downdamplign code 2020-05-13 12:42:14 +02:00
Jonathan Naylor fa9f89700f Merge pull request #272 from F4FXL/FM_Ext
Fix compiler warnings
2020-05-13 11:10:04 +01:00
Geoffrey Merck 9023b6ae13 Correct indentation 2020-05-13 12:03:52 +02:00
Geoffrey Merck df23e15c91 Fix compilation warnings 2020-05-13 11:52:59 +02:00
Jonathan Naylor 51e5e7b851 Merge branch 'FM' into FM_Ext 2020-05-13 10:31:17 +01:00
Jonathan Naylor 8e52bdcc5c Merge branch 'master' into FM 2020-05-13 10:30:46 +01:00
Jonathan Naylor 1332c6544b Merge pull request #271 from shawnchain/fix_led_alternate_macro_names
Fix led alternate macro names
2020-05-13 09:36:05 +01:00
Shawn Chain 703ed2628d Init FM led/mode GPIO pin 2020-05-13 16:28:05 +08:00
Shawn Chain f3943a7888 fix wrong macro name for LED/MODE pin 2020-05-13 16:27:12 +08:00
Jonathan Naylor 737454281a Merge pull request #270 from shawnchain/add_nqf_board_pin_defs_header
pin header file for nqf board
2020-05-13 08:43:19 +01:00
Shawn Chain 1aef42bb21 add missing header files for nqf board 2020-05-13 15:28:08 +08:00
Jonathan Naylor 9550299e4d Merge pull request #268 from shawnchain/drcc_dvm_nqf_board_support
Supports drcc_dvm_nqf board
2020-05-13 07:46:58 +01:00
Jonathan Naylor 056dd908b3 Merge pull request #269 from F4FXL/FM_Ext
Fix crash when writing to serial, Tighten handling of incomign data
2020-05-13 07:41:39 +01:00
Geoffrey Merck 62f239ccc9 Fix modem crash while writing to serial, Split IO write and serial write to 2 separate loops. 2020-05-13 08:31:59 +02:00
Shawn Chain f8879e1f25 Supports drcc_dvm_nqf board 2020-05-13 13:51:02 +08:00
Geoffrey Merck 994226e4b1 Tighten incoming data, Add FM UpSampler 2020-05-12 22:06:26 +02:00
Jonathan Naylor 2cc6c1f68f Merge pull request #267 from F4FXL/FM_Ext
Write Audio to serial
2020-05-12 19:00:09 +01:00
Geoffrey Merck 8e8cf35b19 Merge remote-tracking branch 'upstream/FM_Ext' into FM_Ext 2020-05-12 17:55:41 +02:00
Geoffrey Merck 66de35b6d8 Move downsamplig call back to samples 2020-05-12 17:55:24 +02:00
Jonathan Naylor 43e00bbe1d Merge pull request #266 from shawnchain/io_pins_def_for_each_board_type
Extract the IO pins defs from IOSTM.cpp to separate files
2020-05-12 16:28:04 +01:00
Shawn Chain f31b682625 Extract the IO pins defs from IOSTM.cpp to separate files 2020-05-12 23:21:05 +08:00
Jonathan Naylor 7dc420c8ff Add the FM controller status to the FM Status message. 2020-05-12 15:58:54 +01:00
Jonathan Naylor df0a9ebe72 Merge branch 'FM' into FM_Ext 2020-05-12 15:51:41 +01:00
Jonathan Naylor 66feb9d50b Merge branch 'master' into FM 2020-05-12 15:48:44 +01:00
Jonathan Naylor 0b14b0b73f Merge pull request #265 from shawnchain/mode_led_fm_fix
fix compile error if no MODE_LEDS defined
2020-05-12 15:48:22 +01:00
Shawn Chain 50706c6f09 fix compile error if no MODE_LEDS defined 2020-05-12 22:44:15 +08:00
Jonathan Naylor e957f0154e Merge pull request #264 from F4FXL/FM_Ext
Fix Silence
2020-05-12 15:25:27 +01:00
Geoffrey Merck b10c72fd78 Merge branch 'FM_Ext' of https://github.com/F4FXL/MMDVM into FM_Ext 2020-05-12 16:22:54 +02:00
Geoffrey Merck 496afcb40e Fix silence 2020-05-12 16:21:24 +02:00
Geoffrey Merck 9467b10e5c Fix silence 2020-05-12 16:19:19 +02:00
Jonathan Naylor 13c5f7b0b4 Merge pull request #263 from F4FXL/FM_Ext
Fix FM not transmitting, remove silence for testing
2020-05-12 15:07:17 +01:00
Jonathan Naylor 435544f7a1 Add CTCSS hysteresis. 2020-05-12 13:55:30 +01:00
Geoffrey Merck b64712f657 Restore silence 2020-05-12 14:45:03 +02:00
Geoffrey Merck d23c0900c1 Fix compilation 2020-05-12 14:18:27 +02:00
Geoffrey Merck a0a3080da2 Make sure downsampler always buffers 22 samples at a time 2020-05-12 14:15:04 +02:00
Geoffrey Merck 0fad84b46d Remove silence 2020-05-12 09:29:01 +02:00
Geoffrey Merck 1b40044a23 Re-enable write audio to serial 2020-05-12 09:28:24 +02:00
Geoffrey Merck a671263398 Merge remote-tracking branch 'upstream/FM_Ext' into FM_Ext 2020-05-12 08:37:10 +02:00
Geoffrey Merck ca1cc7096a Fix modem not goign on transmit, still some cleansing to be done 2020-05-12 08:36:38 +02:00
Geoffrey Merck a5aabd8fac Update TX ON/OFF debug info 2020-05-12 08:35:48 +02:00
Jonathan Naylor 6d0e57ea88 Merge pull request #262 from F4FXL/FM_Ext
Still some work in progress to fix no TX
2020-05-11 23:39:05 +01:00
Geoffrey Merck 1d04c1e903 Typo 2020-05-11 22:35:46 +02:00
Geoffrey Merck 042c26b3bb Trying to fix no tx, WIP 2020-05-11 22:32:24 +02:00
Geoffrey Merck b4a125a759 Add debug info TX switching 2020-05-11 22:31:50 +02:00
Geoffrey Merck 8ecf80ff8f Merge branch 'FM_Ext' of https://github.com/F4FXL/MMDVM into FM_Ext 2020-05-11 19:02:24 +02:00
Geoffrey Merck 6786b9b6b1 Temporary revert to previous code 2020-05-11 19:02:08 +02:00
Geoffrey Merck 86ffc69b30 Add getData 2020-05-11 19:02:08 +02:00
Geoffrey Merck 5d4df6ffd9 Write larger chunks of data to IO 2020-05-11 19:02:08 +02:00
Geoffrey Merck eac2aa4ac1 Write larger chunks of FM audio to the serial port 2020-05-11 19:02:08 +02:00
Geoffrey Merck 8cbd52aa72 Update to SAM 1.6.12 2020-05-11 19:02:08 +02:00
Jonathan Naylor 99b853a976 Stop the status timer when leaving TX. 2020-05-11 15:00:53 +01:00
Jonathan Naylor 15bc1a4027 Merge branch 'FM' into FM_Ext 2020-05-11 13:42:14 +01:00
Jonathan Naylor 75e32e1b71 Merge branch 'master' into FM 2020-05-11 13:41:37 +01:00
Jonathan Naylor 7ebc4044f9 Remove Coocox file. 2020-05-11 13:41:10 +01:00
Jonathan Naylor 1836ba928e Merge branch 'FM' into FM_Ext 2020-05-11 13:36:38 +01:00
Jonathan Naylor c54c13c146 Merge branch 'master' into FM 2020-05-11 13:33:49 +01:00
phl0 17a3743cd8 Add GPIO and LEDs for FM mode 2020-05-11 14:27:23 +02:00
Jonathan Naylor 4a5a260c28 Perform FM mode changing in a more conventional manner. 2020-05-11 13:15:13 +01:00
Geoffrey Merck 4bcc1e88c4 Update to SAM 1.6.12 2020-05-11 07:53:21 +02:00
Jonathan Naylor 4cba5931f4 Loosen the conditions for returning to STATE_IDLE 2020-05-10 21:29:01 +01:00
Jonathan Naylor 89458a2c93 Release to STATE_IDLE under simpler conditions. 2020-05-10 21:25:10 +01:00
Jonathan Naylor c91a42f53d Merge pull request #260 from F4FXL/FM_Ext
Write audio to serial port, blank too ext high audio, really ignore ext audio when ext is disabled
2020-05-10 21:04:22 +01:00
Geoffrey Merck 470a070d96 Merge remote-tracking branch 'upstream/FM_Ext' into FM_Ext 2020-05-10 21:59:57 +02:00
Geoffrey Merck 36537c981c Write audio to serial port, blank to high audio, really ignore ext aduio when ext is disabled 2020-05-10 21:59:14 +02:00
Jonathan Naylor c85978a4e3 Rescale the FM calibration level. 2020-05-10 17:33:50 +01:00
Jonathan Naylor d0062a55f8 Rescale the FM calibration output. 2020-05-10 17:31:21 +01:00
Jonathan Naylor 66ea3ad0d1 Only use the CTCSS delay when not using COS. 2020-05-10 17:15:54 +01:00
Jonathan Naylor 3ad443dc2a Remove the delay when using COS. 2020-05-10 17:13:10 +01:00
Jonathan Naylor da16ee277c Merge pull request #258 from F4FXL/FM_Ext
Fix repeater stuck on transmit
2020-05-10 17:06:57 +01:00
Jonathan Naylor 85acdc7121 Merge pull request #259 from F4FXL/FM
Fix stuck on TX
2020-05-10 17:06:26 +01:00
Geoffrey Merck a2518e99f2 Fix stuck on TX 2020-05-10 17:29:17 +02:00
Geoffrey Merck 0f51ddd0bd Fix repeater stuck on transmit 2020-05-10 17:18:59 +02:00
Jonathan Naylor aaa72e769f Merge pull request #257 from F4FXL/FM_Ext
Only use one RingBuffer plus some bug fixes
2020-05-10 08:14:08 +01:00
Geoffrey Merck 0e8fdb381a Fix State machine not changing state 2020-05-10 09:07:21 +02:00
Geoffrey Merck 0b31c40c2b Made Get volatile 2020-05-10 08:01:10 +02:00
Geoffrey Merck 2b3df4e901 Merge remote-tracking branch 'upstream/FM_Ext' into FM_Ext 2020-05-10 07:01:21 +02:00
Geoffrey Merck 807f01ba72 Get rid of annoying PI warning 2020-05-10 07:00:58 +02:00
Geoffrey Merck 03f18451f7 Remove CSerialBuffer, use CRingBuffer 2020-05-10 06:50:35 +02:00
Geoffrey Merck 16c3d418eb Buffer no longer volatile, not needed 2020-05-10 00:03:32 +02:00
Geoffrey Merck 55df5fe04c Remove useless stuff 2020-05-10 00:03:05 +02:00
Geoffrey Merck b0ba3b5dd8 SerialRB now inherits from RingBuffer 2020-05-09 19:57:40 +02:00
Geoffrey Merck 05d21c0a14 TX Buffer now using Templae RB 2020-05-09 17:44:44 +02:00
Geoffrey Merck 26a703c68c IO RXbuffer now uses template RingBuffer 2020-05-09 17:35:38 +02:00
Geoffrey Merck 6c3dd265ab No more need to specify each types for ringBuffer 2020-05-09 14:14:53 +02:00
Jonathan Naylor c04e207821 Insert the missing silence. 2020-05-09 13:10:02 +01:00
Jonathan Naylor 67e0bf02e2 Merge branch 'FM' into FM_Ext 2020-05-09 13:06:32 +01:00
Jonathan Naylor 3bb7cde322 Add input audio delay to match the CTCSS decoder results. 2020-05-09 13:01:02 +01:00
Jonathan Naylor fa29a27695 Ensure all output audio is flushed before leaving FM state. 2020-05-09 12:53:50 +01:00
Geoffrey Merck 7302dc8bd7 Replace RSSI RB with template RB 2020-05-09 11:08:18 +02:00
Jonathan Naylor bb7383a301 Merge pull request #256 from F4FXL/FM_Ext
Add missing files
2020-05-09 10:03:04 +01:00
Geoffrey Merck 61a69d8536 Add missing file 2020-05-09 11:01:28 +02:00
Jonathan Naylor 5a11fcea5b Merge pull request #255 from F4FXL/FM_Ext
Add RingBuffer Template
2020-05-09 09:59:57 +01:00
Geoffrey Merck 05775f0bfa Add RingBuffer Template 2020-05-09 10:57:16 +02:00
Jonathan Naylor 973a1391d7 Merge pull request #254 from F4FXL/FM_Ext
Handle Incoming external audio
2020-05-09 07:36:32 +01:00
Geoffrey Merck 5d45649096 Simplify code 2020-05-09 08:29:31 +02:00
Geoffrey Merck e91c4417cb Handle incoming audio 2020-05-09 08:23:02 +02:00
Geoffrey Merck ff3e6feeb6 Use more explicit names 2020-05-09 08:00:24 +02:00
Geoffrey Merck 0e2a83bc7b Add incoming network data buffer 2020-05-09 07:57:45 +02:00
Jonathan Naylor c84dbd02e5 Merge pull request #253 from F4FXL/FM_Ext
FM into FM_Ext
2020-05-08 21:07:46 +01:00
Geoffrey Merck c0aad5effa Add mising initilizer 2020-05-08 21:47:03 +02:00
Geoffrey Merck e0234dfc00 Merge remote-tracking branch 'upstream/FM' into FM_Ext 2020-05-08 21:39:18 +02:00
Jonathan Naylor e30eb3adaf Reduce the output buffer loading. 2020-05-08 17:18:26 +01:00
Jonathan Naylor 7c9385beab Merge pull request #252 from F4FXL/FM_Ext
Use pointer/shift/masking for sample unpacking
2020-05-08 16:53:32 +01:00
Geoffrey Merck 4c6601d778 Merge branch 'FM_Ext' of https://github.com/F4FXL/MMDVM into FM_Ext 2020-05-08 17:43:43 +02:00
Geoffrey Merck e3a951b33b Use pointer/masking/shifting for sample unpacking 2020-05-08 17:43:05 +02:00
Geoffrey Merck 97192602d8 Use pointer/masking/shifting for sample unpacking 2020-05-08 17:41:12 +02:00
Jonathan Naylor 604957b3e2 Merge pull request #251 from F4FXL/FM_Ext
Remove Union for sample packing
2020-05-08 16:30:06 +01:00
Geoffrey Merck bb731e7890 Init pointer with null 2020-05-08 17:15:23 +02:00
Geoffrey Merck c81d13395b Use correct types 2020-05-08 17:13:29 +02:00
Jonathan Naylor 9b0fed975c Buffer output after adding some initial silence. 2020-05-08 15:48:03 +01:00
Geoffrey Merck 18bc0a75b8 Merge branch 'FM_Ext' of https://github.com/F4FXL/MMDVM into FM_Ext 2020-05-08 16:45:22 +02:00
Geoffrey Merck f1a43ee520 Remove union, use pointer tricks instead 2020-05-08 16:44:53 +02:00
Geoffrey Merck b73bca237d Remove union, use pointer tricks instead 2020-05-08 15:06:08 +02:00
Jonathan Naylor e7ff0d1898 Use const uint8_t instead of non-const. 2020-05-08 13:29:50 +01:00
Jonathan Naylor 880df2536d Add audio packing code. 2020-05-08 12:30:15 +01:00
Jonathan Naylor 09b6929100 Merge pull request #250 from F4FXL/FM_Ext
Merge FM into FM_Ext
2020-05-08 11:04:14 +01:00
Geoffrey Merck 9afcf3acc9 Merge remote-tracking branch 'upstream/FM' into FM_Ext 2020-05-08 12:00:36 +02:00
Jonathan Naylor 5ca9313db8 Merge pull request #248 from F4FXL/FM
Make the FM chain RX Level independant
2020-05-08 09:18:58 +01:00
Geoffrey Merck feff1ee2c7 remove emphasis 2020-05-08 09:04:28 +02:00
Geoffrey Merck 77e0deee76 Make whole FM chain RX level independant 2020-05-08 09:01:00 +02:00
Jonathan Naylor d7cd7096d0 Add the external audio state machine and the beginnings of the audio
processing.
2020-05-07 22:39:17 +01:00
Jonathan Naylor 5d1b66dde3 Add the missing functions. 2020-05-07 22:07:58 +01:00
Jonathan Naylor 96364dc189 Add the external audio parameters. 2020-05-07 22:01:48 +01:00
Jonathan Naylor a816818e3f Beginnings of external audio for the FM controller. 2020-05-07 16:17:00 +01:00
Jonathan Naylor 61ae1fc83a Add transmit hangs to NXDN and P25. 2020-05-06 17:42:46 +01:00
Jonathan Naylor eb9c0dfd93 Allow for the inversion of COS levels. 2020-05-06 11:34:04 +01:00
Jonathan Naylor 79a09e61fa Add the dot to the FM keyer. 2020-05-05 21:02:56 +01:00
Jonathan Naylor 9978a75651 Merge branch 'master' into FM 2020-05-05 21:01:15 +01:00
Jonathan Naylor bd16d13531 Add the dot to the CW Id. 2020-05-05 21:00:36 +01:00
Jonathan Naylor f00d729264 Merge pull request #246 from F4FXL/bugfix/STM32F1_POG
Bug Fixes for the STM32F1_POG and derivatives
2020-05-05 10:17:03 +01:00
Geoffrey Merck a4ddc2a060 Merge remote-tracking branch 'upstream/FM' into bugfix/STM32F1_POG 2020-05-05 11:02:27 +02:00
Geoffrey Merck a938c8b708 Reduce buffer size 2020-05-05 10:48:44 +02:00
Jonathan Naylor aa7a484c7a Allow the start callsign to occur when the kerchunk timer has latched. 2020-05-04 22:18:51 +01:00
Jonathan Naylor 915be8c279 Calculate the AckMinTime accurately. 2020-05-04 22:06:57 +01:00
Geoffrey Merck 87feadd451 Better LED management 2020-05-04 19:12:45 +02:00
Geoffrey Merck 419ab89ee9 Merge branch 'bugfix/STM32F1_POG' of https://github.com/F4FXL/MMDVM into bugfix/STM32F1_POG 2020-05-04 16:44:25 +02:00
Geoffrey Merck fcdb582893 Change FM LED Pin 2020-05-04 16:43:08 +02:00
Geoffrey Merck 5e85565208 Fix compile isue 2020-05-04 15:26:17 +02:00
Geoffrey Merck 2d876b8d8e Fix Fancy LED effect accessing unused ports 2020-05-03 15:36:10 +02:00
Jonathan Naylor 4feca3c5b7 Clock the timers seperately. 2020-05-03 13:08:33 +01:00
Jonathan Naylor f8e119c26b Set the modem state in SET_CONFIG. 2020-05-02 17:37:47 +01:00
Jonathan Naylor edddbedd4b Fix compilation issues. 2020-05-02 15:46:36 +01:00
Jonathan Naylor baa4f7aa4c Last minute tidy-ups. 2020-05-02 14:47:43 +01:00
Jonathan Naylor de3c257f79 Bump the version date. 2020-05-01 18:47:15 +01:00
Jonathan Naylor b027e1d1bf Merge pull request #243 from F4FXL/FM
Fix CTCSS value is different when using RXLevel 50 to 99
2020-05-01 17:04:05 +01:00
Geoffrey Merck 0a5c496a3a Fix CTCSS value is different when using RXLevel 50 to 99 2020-05-01 17:56:45 +02:00
Jonathan Naylor 5b32fecc0a Remove the pre- and de-emphasis and the downsampler. 2020-04-30 11:39:04 +01:00
Jonathan Naylor 92a4db9886 Merge pull request #242 from g4klx/revert-241-FM
Revert "Change emphasis time constant to 750µS"
2020-04-30 11:23:42 +01:00
Jonathan Naylor cc785e3225 Revert "Change emphasis time constant to 750µS" 2020-04-30 11:23:19 +01:00
Jonathan Naylor be0690e587 Merge pull request #241 from F4FXL/FM
Change emphasis time constant to 750µS
2020-04-30 09:38:24 +01:00
Geoffrey Merck 69e39e36b0 Change emphasis time constant to 750µS 2020-04-30 10:26:04 +02:00
Jonathan Naylor b2f33fd4d2 Bump the version date. 2020-04-29 21:51:12 +01:00
Jonathan Naylor 200199c5d4 Reduce the CPU load slightly. 2020-04-29 20:59:48 +01:00
Jonathan Naylor 1465d6f91d Merge pull request #240 from F4FXL/FM
Add resmaplign/packing and Pre and De emphasis
2020-04-29 20:45:02 +01:00
Geoffrey Merck 373aed13c8 Restore Passband 2020-04-29 20:43:01 +02:00
Geoffrey Merck b23620ede3 Add de and pre emphasis 2020-04-29 20:42:20 +02:00
Geoffrey Merck da87afc8d4 Move helper script to separate folder 2020-04-29 20:41:41 +02:00
Geoffrey Merck 626a280d27 Add filter chrachertitics comment 2020-04-29 18:24:15 +02:00
Geoffrey Merck 4b267c2e1e Move downsampling tap point 2020-04-28 22:35:06 +02:00
Geoffrey Merck cf18f95a92 Add Downsampling 2020-04-28 21:37:06 +02:00
Jonathan Naylor dac0f26e5d Rename RXBoost to RFAudioBoost. 2020-04-28 14:43:40 +01:00
Jonathan Naylor 13993891ec Merge pull request #239 from m0vse/FM
Change FM cal levels
2020-04-28 09:55:31 +01:00
m0vse 849c2a0f50 Change FM cal levels 2020-04-28 09:51:11 +01:00
Jonathan Naylor 172ac615a8 Rescale the output. 2020-04-27 14:59:33 +01:00
Jonathan Naylor 30031d8e95 Increase the output level. 2020-04-27 14:53:41 +01:00
Jonathan Naylor b2de5defa4 Tweak the values slightly. 2020-04-27 14:47:17 +01:00
Jonathan Naylor 177c7548ae Merge pull request #237 from m0vse/FM
Add FM Cal modes
2020-04-27 14:35:53 +01:00
m0vse b9bfc36e6f Remove commented code 2020-04-27 14:32:16 +01:00
m0vse 980c529107 Merge remote-tracking branch 'upstream/FM' into FM 2020-04-27 14:19:12 +01:00
m0vse 5156ca13b7 Add FM Cal modes 2020-04-27 14:18:42 +01:00
Jonathan Naylor d08a3690b0 Double the signal level to the CTCSS decoder. 2020-04-27 13:07:03 +01:00
Jonathan Naylor e8ed77241c Simplify the calculations. 2020-04-27 12:05:55 +01:00
Jonathan Naylor 82dcc44a2d Merge pull request #235 from F4FXL/FM
Move division to CTCSSRX, change sample unscaling to 1/rxLevel
2020-04-27 10:27:51 +01:00
Geoffrey Merck 93a8e63233 Remove m_rxLevel 2020-04-27 11:26:19 +02:00
Geoffrey Merck 4ffaa62855 Move division to CTCSSRX, change sample unscaling to 1/rxLevel 2020-04-27 11:16:06 +02:00
Jonathan Naylor f9530ee82a Pass the RX level to the FM controller. 2020-04-26 22:01:11 +01:00
Jonathan Naylor d66c6d7f9c Fix the multiplication. 2020-04-26 15:24:51 +01:00
Jonathan Naylor 458a3d2d24 Bump the version date. 2020-04-26 13:22:16 +01:00
Jonathan Naylor 6f4c19c006 Convert to Q47 arithmetic. 2020-04-26 13:02:43 +01:00
Jonathan Naylor a31cf3d6f8 Convert the CTCSS TX tones to Q31 from Q15. 2020-04-26 12:07:10 +01:00
Jonathan Naylor 3fb0631953 Merge pull request #233 from F4FXL/FM
Remove IO from CTCSSRX
2020-04-26 11:45:44 +01:00
Geoffrey Merck 028d0cf609 Add q31_t cast 2020-04-26 12:38:23 +02:00
Geoffrey Merck 6824d5662a Remove dependency to IO in CTCSSRX 2020-04-26 12:24:05 +02:00
Jonathan Naylor 1bc8726046 Merge pull request #232 from F4FXL/bugfix/FM_CTCSS_TX
Fix invalid values passed to arm_sin_q15
2020-04-26 08:16:20 +01:00
Jonathan Naylor 05c8c130b6 Merge pull request #231 from F4FXL/feature/FM_Normalized_CTCSS_Threshold
CTCSS threshold is level agnostic
2020-04-26 08:15:15 +01:00
Geoffrey Merck 5051a13711 Fix invalid values passed to arm_sin_q15 2020-04-26 08:16:08 +02:00
Geoffrey Merck 103116e410 Add debug essage when CTCSS status changes 2020-04-26 07:26:35 +02:00
Geoffrey Merck d973238596 CTCSS threshold is level agnostic, experimental
(cherry picked from commit d2d50e21e1)
2020-04-26 06:58:27 +02:00
Jonathan Naylor 4d664c4aa4 Merge pull request #230 from g4klx/revert-229-FM
Revert "Make CTCSS threshold RXLevel and RXBoost agnostic"
2020-04-25 23:48:25 +01:00
272 changed files with 164651 additions and 7109 deletions
-9
View File
@@ -1,9 +0,0 @@
[submodule "STM32F4XX_Lib"]
path = STM32F4XX_Lib
url = https://github.com/juribeparada/STM32F4XX_Lib.git
[submodule "STM32F7XX_Lib"]
path = STM32F7XX_Lib
url = https://github.com/juribeparada/STM32F7XX_Lib.git
[submodule "STM32F10X_Lib"]
path = STM32F10X_Lib
url = https://github.com/shawnchain/STM32F10X_Lib.git
+36
View File
@@ -0,0 +1,36 @@
/*
* Copyright (C) 2020 by Jonathan Naylor G4KLX
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#if !defined(AX25DEFINES_H)
#define AX25DEFINES_H
const uint8_t AX25_RADIO_SYMBOL_LENGTH = 20U; // At 24 kHz sample rate
const uint8_t AX25_FRAME_START = 0x7EU;
const uint8_t AX25_FRAME_END = 0x7EU;
const uint8_t AX25_FRAME_ABORT = 0xFEU;
const uint8_t AX25_MAX_ONES = 5U;
const uint16_t AX25_MIN_FRAME_LENGTH = 17U; // Callsign (7) + Callsign (7) + Control (1) + Checksum (2)
const uint16_t AX25_MAX_FRAME_LENGTH = 330U; // Callsign (7) + Callsign (7) + 8 Digipeaters (56) +
// Control (1) + PID (1) + Data (256) + Checksum (2)
#endif
+340
View File
@@ -0,0 +1,340 @@
/*
* Copyright (C) 2020,2023 by Jonathan Naylor G4KLX
* Copyright 2015-2019 Mobilinkd LLC <[email protected]>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "Config.h"
#if defined(MODE_AX25)
#include "Globals.h"
#include "AX25Demodulator.h"
#include "AX25Defines.h"
const float32_t SAMPLE_RATE = 24000.0F;
const float32_t SYMBOL_RATE = 1200.0F;
const uint16_t DELAY_LEN = 11U;
const float32_t SAMPLES_PER_SYMBOL = SAMPLE_RATE / SYMBOL_RATE;
const float32_t PLL_LIMIT = SAMPLES_PER_SYMBOL / 2.0F;
const uint32_t LPF_FILTER_LEN = 48U;
q15_t LPF_FILTER_COEFFS[] = {
-2, -8, -17, -28, -40, -47, -47, -34,
-5, 46, 122, 224, 354, 510, 689, 885,
1092, 1302, 1506, 1693, 1856, 1987, 2077, 2124,
2124, 2077, 1987, 1856, 1693, 1506, 1302, 1092,
885, 689, 510, 354, 224, 122, 46, -5,
-34, -47, -47, -40, -28, -17, -8, -2
};
// Lock low-pass filter taps (80Hz Bessel)
// scipy.signal:
// b, a = bessel(4, [80.0/(1200/2)], 'lowpass')
//
const uint8_t PLL_IIR_SIZE = 5U;
const float32_t PLL_LOCK_B[] = {
1.077063e-03,4.308253e-03,6.462379e-03,4.308253e-03,1.077063e-03};
const float32_t PLL_LOCK_A[] = {
1.000000e+00,-2.774567e+00,2.962960e+00,-1.437990e+00,2.668296e-01};
// 64 Hz loop filter.
// scipy.signal:
// loop_coeffs = firwin(9, [64.0/(1200/2)], width = None,
// pass_zero = True, scale = True, window='hann')
//
const uint32_t PLL_FILTER_LEN = 7U;
float32_t PLL_FILTER_COEFFS[] = {3.196252e-02F, 1.204223e-01F, 2.176819e-01F, 2.598666e-01F, 2.176819e-01F, 1.204223e-01F, 3.196252e-02F};
CAX25Demodulator::CAX25Demodulator(int8_t n) :
m_frame(),
m_twist(n),
m_lpfFilter(),
m_lpfState(),
m_delayLine(NULL),
m_delayPos(0U),
m_nrziState(false),
m_pllFilter(),
m_pllState(),
m_pllLast(false),
m_pllBits(1U),
m_pllCount(0.0F),
m_pllJitter(0.0F),
m_pllDCD(false),
m_iirHistory(),
m_hdlcOnes(0U),
m_hdlcFlag(false),
m_hdlcBuffer(0U),
m_hdlcBits(0U),
m_hdlcState(AX25_IDLE),
m_rssiAccum(0U),
m_rssiCount(0U)
{
m_delayLine = new bool[DELAY_LEN];
m_lpfFilter.numTaps = LPF_FILTER_LEN;
m_lpfFilter.pState = m_lpfState;
m_lpfFilter.pCoeffs = LPF_FILTER_COEFFS;
m_pllFilter.numTaps = PLL_FILTER_LEN;
m_pllFilter.pState = m_pllState;
m_pllFilter.pCoeffs = PLL_FILTER_COEFFS;
for (uint8_t i = 0U; i < PLL_IIR_SIZE; i++)
m_iirHistory[i] = 0.0F;
}
bool CAX25Demodulator::process(q15_t* samples, const uint16_t* rssi, uint8_t length, CAX25Frame& frame)
{
bool result = false;
q15_t fa[RX_BLOCK_SIZE];
m_twist.process(samples, fa, RX_BLOCK_SIZE);
int16_t buffer[RX_BLOCK_SIZE];
for (uint8_t i = 0; i < length; i++) {
bool level = (fa[i] >= 0);
bool delayed = delay(level);
buffer[i] = (int16_t(level ^ delayed) << 1) - 1;
}
q15_t fc[RX_BLOCK_SIZE];
::arm_fir_fast_q15(&m_lpfFilter, buffer, fc, RX_BLOCK_SIZE);
for (uint8_t i = 0; i < length; i++) {
m_rssiAccum += rssi[i];
m_rssiCount++;
bool bit = fc[i] >= 0;
bool sample = PLL(bit);
if (sample) {
// We will only ever get one frame because there are
// not enough bits in a block for more than one.
if (result) {
HDLC(NRZI(bit));
} else {
result = HDLC(NRZI(bit));
if (result) {
// Copy the frame data.
::memcpy(frame.m_data, m_frame.m_data, AX25_MAX_PACKET_LEN);
frame.m_length = m_frame.m_length;
frame.m_fcs = m_frame.m_fcs;
m_frame.m_length = 0U;
}
}
}
}
return result;
}
bool CAX25Demodulator::delay(bool b)
{
bool r = m_delayLine[m_delayPos];
m_delayLine[m_delayPos++] = b;
if (m_delayPos >= DELAY_LEN)
m_delayPos = 0U;
return r;
}
bool CAX25Demodulator::NRZI(bool b)
{
bool result = (b == m_nrziState);
m_nrziState = b;
return result;
}
bool CAX25Demodulator::PLL(bool input)
{
bool sample = false;
if (input != m_pllLast || m_pllBits > 16U) {
// Record transition.
m_pllLast = input;
if (m_pllCount > PLL_LIMIT)
m_pllCount -= SAMPLES_PER_SYMBOL;
float32_t adjust = m_pllBits > 16U ? 5.0F : 0.0F;
float32_t offset = m_pllCount / float32_t(m_pllBits);
float32_t jitter;
::arm_fir_f32(&m_pllFilter, &offset, &jitter, 1U);
float32_t absOffset = adjust;
if (offset < 0.0F)
absOffset -= offset;
else
absOffset += offset;
m_pllJitter = iir(absOffset);
m_pllCount -= jitter / 2.0F;
m_pllBits = 1U;
} else {
if (m_pllCount > PLL_LIMIT) {
sample = true;
m_pllCount -= SAMPLES_PER_SYMBOL;
m_pllBits++;
}
}
m_pllCount += 1.0F;
return sample;
}
bool CAX25Demodulator::HDLC(bool b)
{
if (m_hdlcOnes == AX25_MAX_ONES) {
if (b) {
// flag byte
m_hdlcFlag = true;
} else {
// bit stuffing...
m_hdlcFlag = false;
m_hdlcOnes = 0U;
return false;
}
}
m_hdlcBuffer >>= 1;
m_hdlcBuffer |= b ? 128U : 0U;
m_hdlcBits++; // Free-running until Sync byte.
if (b)
m_hdlcOnes++;
else
m_hdlcOnes = 0U;
if (m_hdlcFlag) {
bool result = false;
switch (m_hdlcBuffer) {
case AX25_FRAME_END:
if (m_frame.m_length >= AX25_MIN_FRAME_LENGTH) {
result = m_frame.checkCRC();
if (!result)
m_frame.m_length = 0U;
} else {
m_frame.m_length = 0U;
}
m_hdlcState = AX25_SYNC;
m_hdlcFlag = false;
m_hdlcBits = 0U;
break;
case AX25_FRAME_ABORT:
// Frame aborted
m_frame.m_length = 0U;
m_hdlcState = AX25_IDLE;
m_hdlcFlag = false;
m_hdlcBits = 0U;
break;
default:
break;
}
return result;
}
switch (m_hdlcState) {
case AX25_IDLE:
break;
case AX25_SYNC:
if (m_hdlcBits == 8U) { // 8th bit.
// Start of frame data.
m_hdlcState = AX25_RECEIVE;
m_frame.append(m_hdlcBuffer);
m_rssiAccum = 0U;
m_rssiCount = 0U;
m_hdlcBits = 0U;
}
break;
case AX25_RECEIVE:
if (m_hdlcBits == 8U) { // 8th bit.
m_frame.append(m_hdlcBuffer);
m_hdlcBits = 0U;
}
break;
default:
break;
}
return false;
}
void CAX25Demodulator::setTwist(int8_t n)
{
m_twist.setTwist(n);
}
bool CAX25Demodulator::isDCD()
{
if (m_pllJitter <= (SAMPLES_PER_SYMBOL * 0.03F))
m_pllDCD = true;
else if (m_pllJitter >= (SAMPLES_PER_SYMBOL * 0.15F))
m_pllDCD = false;
return m_pllDCD;
}
float32_t CAX25Demodulator::iir(float32_t input)
{
for (int8_t i = int8_t(PLL_IIR_SIZE) - 1; i != 0; i--)
m_iirHistory[i] = m_iirHistory[i - 1];
m_iirHistory[0] = input;
for (uint8_t i = 1U; i < PLL_IIR_SIZE; i++)
m_iirHistory[0] -= PLL_LOCK_A[i] * m_iirHistory[i];
float32_t result = 0.0F;
for (uint8_t i = 0U; i < PLL_IIR_SIZE; i++)
result += PLL_LOCK_B[i] * m_iirHistory[i];
return result;
}
uint16_t CAX25Demodulator::getRSSI()
{
if (m_rssiCount > 0U) {
uint16_t rssi = m_rssiAccum / m_rssiCount;
m_rssiAccum = 0U;
m_rssiCount = 0U;
return rssi;
}
return 0U;
}
#endif
+81
View File
@@ -0,0 +1,81 @@
/*
* Copyright (C) 2020,2023 by Jonathan Naylor G4KLX
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "Config.h"
#if defined(MODE_AX25)
#if !defined(AX25Demodulator_H)
#define AX25Demodulator_H
#include "AX25Frame.h"
#include "AX25Twist.h"
enum AX25_STATE {
AX25_IDLE,
AX25_SYNC,
AX25_RECEIVE
};
class CAX25Demodulator {
public:
CAX25Demodulator(int8_t n);
bool process(q15_t* samples, const uint16_t* rssi, uint8_t length, CAX25Frame& frame);
void setTwist(int8_t n);
bool isDCD();
uint16_t getRSSI();
private:
CAX25Frame m_frame;
CAX25Twist m_twist;
arm_fir_instance_q15 m_lpfFilter;
q15_t m_lpfState[70U]; // NoTaps + BlockSize - 1, 48 + 20 - 1 plus some spare
bool* m_delayLine;
uint16_t m_delayPos;
bool m_nrziState;
arm_fir_instance_f32 m_pllFilter;
float32_t m_pllState[20U]; // NoTaps + BlockSize - 1, 7 + 1 - 1 plus some spare
bool m_pllLast;
uint8_t m_pllBits;
float32_t m_pllCount;
float32_t m_pllJitter;
bool m_pllDCD;
float32_t m_iirHistory[5U];
uint16_t m_hdlcOnes;
bool m_hdlcFlag;
uint16_t m_hdlcBuffer;
uint16_t m_hdlcBits;
AX25_STATE m_hdlcState;
uint32_t m_rssiAccum;
uint16_t m_rssiCount;
bool delay(bool b);
bool NRZI(bool b);
bool PLL(bool b);
bool HDLC(bool b);
float32_t iir(float32_t input);
};
#endif
#endif
+127
View File
@@ -0,0 +1,127 @@
/*
* Copyright (C) 2020 by Jonathan Naylor G4KLX
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "Config.h"
#if defined(MODE_AX25)
#include "Globals.h"
#include "AX25Frame.h"
const uint16_t CCITT_TABLE[] = {
0x0000,0x1189,0x2312,0x329b,0x4624,0x57ad,0x6536,0x74bf,
0x8c48,0x9dc1,0xaf5a,0xbed3,0xca6c,0xdbe5,0xe97e,0xf8f7,
0x1081,0x0108,0x3393,0x221a,0x56a5,0x472c,0x75b7,0x643e,
0x9cc9,0x8d40,0xbfdb,0xae52,0xdaed,0xcb64,0xf9ff,0xe876,
0x2102,0x308b,0x0210,0x1399,0x6726,0x76af,0x4434,0x55bd,
0xad4a,0xbcc3,0x8e58,0x9fd1,0xeb6e,0xfae7,0xc87c,0xd9f5,
0x3183,0x200a,0x1291,0x0318,0x77a7,0x662e,0x54b5,0x453c,
0xbdcb,0xac42,0x9ed9,0x8f50,0xfbef,0xea66,0xd8fd,0xc974,
0x4204,0x538d,0x6116,0x709f,0x0420,0x15a9,0x2732,0x36bb,
0xce4c,0xdfc5,0xed5e,0xfcd7,0x8868,0x99e1,0xab7a,0xbaf3,
0x5285,0x430c,0x7197,0x601e,0x14a1,0x0528,0x37b3,0x263a,
0xdecd,0xcf44,0xfddf,0xec56,0x98e9,0x8960,0xbbfb,0xaa72,
0x6306,0x728f,0x4014,0x519d,0x2522,0x34ab,0x0630,0x17b9,
0xef4e,0xfec7,0xcc5c,0xddd5,0xa96a,0xb8e3,0x8a78,0x9bf1,
0x7387,0x620e,0x5095,0x411c,0x35a3,0x242a,0x16b1,0x0738,
0xffcf,0xee46,0xdcdd,0xcd54,0xb9eb,0xa862,0x9af9,0x8b70,
0x8408,0x9581,0xa71a,0xb693,0xc22c,0xd3a5,0xe13e,0xf0b7,
0x0840,0x19c9,0x2b52,0x3adb,0x4e64,0x5fed,0x6d76,0x7cff,
0x9489,0x8500,0xb79b,0xa612,0xd2ad,0xc324,0xf1bf,0xe036,
0x18c1,0x0948,0x3bd3,0x2a5a,0x5ee5,0x4f6c,0x7df7,0x6c7e,
0xa50a,0xb483,0x8618,0x9791,0xe32e,0xf2a7,0xc03c,0xd1b5,
0x2942,0x38cb,0x0a50,0x1bd9,0x6f66,0x7eef,0x4c74,0x5dfd,
0xb58b,0xa402,0x9699,0x8710,0xf3af,0xe226,0xd0bd,0xc134,
0x39c3,0x284a,0x1ad1,0x0b58,0x7fe7,0x6e6e,0x5cf5,0x4d7c,
0xc60c,0xd785,0xe51e,0xf497,0x8028,0x91a1,0xa33a,0xb2b3,
0x4a44,0x5bcd,0x6956,0x78df,0x0c60,0x1de9,0x2f72,0x3efb,
0xd68d,0xc704,0xf59f,0xe416,0x90a9,0x8120,0xb3bb,0xa232,
0x5ac5,0x4b4c,0x79d7,0x685e,0x1ce1,0x0d68,0x3ff3,0x2e7a,
0xe70e,0xf687,0xc41c,0xd595,0xa12a,0xb0a3,0x8238,0x93b1,
0x6b46,0x7acf,0x4854,0x59dd,0x2d62,0x3ceb,0x0e70,0x1ff9,
0xf78f,0xe606,0xd49d,0xc514,0xb1ab,0xa022,0x92b9,0x8330,
0x7bc7,0x6a4e,0x58d5,0x495c,0x3de3,0x2c6a,0x1ef1,0x0f78 };
CAX25Frame::CAX25Frame(const uint8_t* data, uint16_t length) :
m_data(),
m_length(0U),
m_fcs(0U)
{
for (uint16_t i = 0U; i < length && i < (AX25_MAX_PACKET_LEN - 2U); i++)
m_data[m_length++] = data[i];
}
CAX25Frame::CAX25Frame() :
m_data(),
m_length(0U),
m_fcs(0U)
{
}
bool CAX25Frame::append(uint16_t c)
{
if (m_length == AX25_MAX_PACKET_LEN)
return false;
m_data[m_length++] = uint8_t(c);
return true;
}
bool CAX25Frame::checkCRC()
{
union {
uint16_t crc16;
uint8_t crc8[2U];
};
crc16 = 0xFFFFU;
for (uint16_t i = 0U; i < (m_length - 2U); i++)
crc16 = uint16_t(crc8[1U]) ^ CCITT_TABLE[crc8[0U] ^ m_data[i]];
crc16 = ~crc16;
if (crc8[0U] == m_data[m_length - 2U] && crc8[1U] == m_data[m_length - 1U]) {
m_fcs = crc16;
return true;
} else {
return false;
}
}
void CAX25Frame::addCRC()
{
union {
uint16_t crc16;
uint8_t crc8[2U];
};
crc16 = 0xFFFFU;
for (uint16_t i = 0U; i < m_length; i++)
crc16 = uint16_t(crc8[1U]) ^ CCITT_TABLE[crc8[0U] ^ m_data[i]];
crc16 = ~crc16;
m_fcs = crc16;
m_data[m_length++] = crc8[0U];
m_data[m_length++] = crc8[1U];
}
#endif
+47
View File
@@ -0,0 +1,47 @@
/*
* Copyright (C) 2020 by Jonathan Naylor G4KLX
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "Config.h"
#if defined(MODE_AX25)
#if !defined(AX25Frame_H)
#define AX25Frame_H
const uint16_t AX25_MAX_PACKET_LEN = 300U;
class CAX25Frame {
public:
CAX25Frame(const uint8_t* data, uint16_t length);
CAX25Frame();
bool append(uint16_t c);
bool checkCRC();
void addCRC();
uint8_t m_data[AX25_MAX_PACKET_LEN];
uint16_t m_length;
uint16_t m_fcs;
};
#endif
#endif
+235
View File
@@ -0,0 +1,235 @@
/*
* Copyright (C) 2020,2023 by Jonathan Naylor G4KLX
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "Config.h"
#if defined(MODE_AX25)
#include "Globals.h"
#include "AX25RX.h"
/*
* Generated with Scipy Filter, 152 coefficients, 1100-2300Hz bandpass,
* Hann window, starting and ending 0 value coefficients removed.
*
* np.array(
* firwin2(152,
* [
* 0.0,
* 1000.0/(sample_rate/2),
* 1100.0/(sample_rate/2),
* 2350.0/(sample_rate/2),
* 2500.0/(sample_rate/2),
* 1.0
* ],
* [0,0,1,1,0,0],
* antisymmetric = False,
* window='hann') * 32768,
* dtype=int)[10:-10]
*/
const uint32_t FILTER_LEN = 130U;
q15_t FILTER_COEFFS[] = {
5, 12, 18, 21, 19, 11, -2, -15, -25, -27,
-21, -11, -3, -5, -19, -43, -69, -83, -73, -35,
27, 98, 155, 180, 163, 109, 39, -20, -45, -26,
23, 74, 89, 39, -81, -247, -407, -501, -480, -334,
-92, 175, 388, 479, 429, 275, 99, 5, 68, 298,
626, 913, 994, 740, 115, -791, -1770, -2544, -2847, -2509,
-1527, -76, 1518, 2875, 3653, 3653, 2875, 1518, -76, -1527,
-2509, -2847, -2544, -1770, -791, 115, 740, 994, 913, 626,
298, 68, 5, 99, 275, 429, 479, 388, 175, -92,
-334, -480, -501, -407, -247, -81, 39, 89, 74, 23,
-26, -45, -20, 39, 109, 163, 180, 155, 98, 27,
-35, -73, -83, -69, -43, -19, -5, -3, -11, -21,
-27, -25, -15, -2, 11, 19, 21, 18, 12, 5
};
CAX25RX::CAX25RX() :
m_filter(),
m_state(),
m_demod1(3),
m_demod2(6),
m_demod3(9),
m_lastFCS(0U),
m_count(0U),
m_slotTime(30U),
m_slotCount(0U),
m_pPersist(128U),
m_dcd(false),
m_canTX(false),
m_x(1U),
m_a(0xB7U),
m_b(0x73U),
m_c(0xF6U)
{
m_filter.numTaps = FILTER_LEN;
m_filter.pState = m_state;
m_filter.pCoeffs = FILTER_COEFFS;
initRand();
}
void CAX25RX::samples(q15_t* samples, const uint16_t* rssi, uint8_t length)
{
q15_t output[RX_BLOCK_SIZE];
::arm_fir_fast_q15(&m_filter, samples, output, RX_BLOCK_SIZE);
m_count++;
CAX25Frame frame;
bool ret = m_demod1.process(output, rssi, length, frame);
if (ret) {
if (frame.m_fcs != m_lastFCS || m_count > 2U) {
m_lastFCS = frame.m_fcs;
m_count = 0U;
#if defined(SEND_RSSI_DATA)
uint16_t rssi = m_demod1.getRSSI();
if (rssi > 0U)
serial.writeAX25DataEx(rssi, frame.m_data, frame.m_length - 2U);
else
serial.writeAX25Data(frame.m_data, frame.m_length - 2U);
#else
serial.writeAX25Data(frame.m_data, frame.m_length - 2U);
#endif
}
DEBUG1("Decoder 1 reported");
}
ret = m_demod2.process(output, rssi, length, frame);
if (ret) {
if (frame.m_fcs != m_lastFCS || m_count > 2U) {
m_lastFCS = frame.m_fcs;
m_count = 0U;
#if defined(SEND_RSSI_DATA)
uint16_t rssi = m_demod2.getRSSI();
if (rssi > 0U)
serial.writeAX25DataEx(rssi, frame.m_data, frame.m_length - 2U);
else
serial.writeAX25Data(frame.m_data, frame.m_length - 2U);
#else
serial.writeAX25Data(frame.m_data, frame.m_length - 2U);
#endif
}
DEBUG1("Decoder 2 reported");
}
ret = m_demod3.process(output, rssi, length, frame);
if (ret) {
if (frame.m_fcs != m_lastFCS || m_count > 2U) {
m_lastFCS = frame.m_fcs;
m_count = 0U;
#if defined(SEND_RSSI_DATA)
uint16_t rssi = m_demod3.getRSSI();
if (rssi > 0U)
serial.writeAX25DataEx(rssi, frame.m_data, frame.m_length - 2U);
else
serial.writeAX25Data(frame.m_data, frame.m_length - 2U);
#else
serial.writeAX25Data(frame.m_data, frame.m_length - 2U);
#endif
}
DEBUG1("Decoder 3 reported");
}
m_slotCount += RX_BLOCK_SIZE;
if (m_slotCount >= m_slotTime) {
m_slotCount = 0U;
bool dcd1 = m_demod1.isDCD();
bool dcd2 = m_demod2.isDCD();
bool dcd3 = m_demod3.isDCD();
if (dcd1 || dcd2 || dcd3) {
if (!m_dcd) {
io.setDecode(true);
io.setADCDetection(true);
m_dcd = true;
}
m_canTX = false;
} else {
if (m_dcd) {
io.setDecode(false);
io.setADCDetection(false);
m_dcd = false;
}
m_canTX = m_pPersist >= rand();
}
}
}
bool CAX25RX::canTX() const
{
return m_canTX;
}
void CAX25RX::setParams(int8_t twist, uint8_t slotTime, uint8_t pPersist)
{
m_demod1.setTwist(twist - 3);
m_demod2.setTwist(twist);
m_demod3.setTwist(twist + 3);
m_slotTime = slotTime * 240U; // Slot time in samples
m_pPersist = pPersist;
}
// Taken from https://www.electro-tech-online.com/threads/ultra-fast-pseudorandom-number-generator-for-8-bit.124249/
//X ABC Algorithm Random Number Generator for 8-Bit Devices:
//This is a small PRNG, experimentally verified to have at least a 50 million byte period
//by generating 50 million bytes and observing that there were no overapping sequences and repeats.
//This generator passes serial correlation, entropy , Monte Carlo Pi value, arithmetic mean,
//And many other statistical tests. This generator may have a period of up to 2^32, but this has
//not been verified.
//
// By XORing 3 bytes into the a,b, and c registers, you can add in entropy from
//an external source easily.
//
//This generator is free to use, but is not suitable for cryptography due to its short period(by //cryptographic standards) and simple construction. No attempt was made to make this generator
// suitable for cryptographic use.
//
//Due to the use of a constant counter, the generator should be resistant to latching up.
//A significant performance gain is had in that the x variable is only ever incremented.
//
//Only 4 bytes of ram are needed for the internal state, and generating a byte requires 3 XORs , //2 ADDs, one bit shift right , and one increment. Difficult or slow operations like multiply, etc
//were avoided for maximum speed on ultra low power devices.
void CAX25RX::initRand() //Can also be used to seed the rng with more entropy during use.
{
m_a = (m_a ^ m_c ^ m_x);
m_b = (m_b + m_a);
m_c = (m_c + (m_b >> 1) ^ m_a);
}
uint8_t CAX25RX::rand()
{
m_x++; //x is incremented every round and is not affected by any other variable
m_a = (m_a ^ m_c ^ m_x); //note the mix of addition and XOR
m_b = (m_b + m_a); //And the use of very few instructions
m_c = (m_c + (m_b >> 1) ^ m_a); //the right shift is to ensure that high-order bits from b can affect
return uint8_t(m_c); //low order bits of other variables
}
#endif
+63
View File
@@ -0,0 +1,63 @@
/*
* Copyright (C) 2020,2023 by Jonathan Naylor G4KLX
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "Config.h"
#if defined(MODE_AX25)
#if !defined(AX25RX_H)
#define AX25RX_H
#include "AX25Demodulator.h"
class CAX25RX {
public:
CAX25RX();
void samples(q15_t* samples, const uint16_t* rssi, uint8_t length);
void setParams(int8_t twist, uint8_t slotTime, uint8_t pPersist);
bool canTX() const;
private:
arm_fir_instance_q15 m_filter;
q15_t m_state[160U]; // NoTaps + BlockSize - 1, 130 + 20 - 1 plus some spare
CAX25Demodulator m_demod1;
CAX25Demodulator m_demod2;
CAX25Demodulator m_demod3;
uint16_t m_lastFCS;
uint32_t m_count;
uint32_t m_slotTime;
uint32_t m_slotCount;
uint8_t m_pPersist;
bool m_dcd;
bool m_canTX;
uint8_t m_x;
uint8_t m_a;
uint8_t m_b;
uint8_t m_c;
void initRand();
uint8_t rand();
};
#endif
#endif
+191
View File
@@ -0,0 +1,191 @@
/*
* Copyright (C) 2020 by Jonathan Naylor G4KLX
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "Config.h"
#if defined(MODE_AX25)
#include "Globals.h"
#include "AX25TX.h"
#include "AX25Defines.h"
#include "AX25Frame.h"
const uint8_t START_FLAG[] = { AX25_FRAME_START };
const uint8_t END_FLAG[] = { AX25_FRAME_END };
const uint8_t BIT_MASK_TABLE1[] = { 0x80U, 0x40U, 0x20U, 0x10U, 0x08U, 0x04U, 0x02U, 0x01U };
#define WRITE_BIT1(p,i,b) p[(i)>>3] = (b) ? (p[(i)>>3] | BIT_MASK_TABLE1[(i)&7]) : (p[(i)>>3] & ~BIT_MASK_TABLE1[(i)&7])
#define READ_BIT1(p,i) (p[(i)>>3] & BIT_MASK_TABLE1[(i)&7])
const uint8_t BIT_MASK_TABLE2[] = { 0x01U, 0x02U, 0x04U, 0x08U, 0x10U, 0x20U, 0x40U, 0x80U };
#define WRITE_BIT2(p,i,b) p[(i)>>3] = (b) ? (p[(i)>>3] | BIT_MASK_TABLE2[(i)&7]) : (p[(i)>>3] & ~BIT_MASK_TABLE2[(i)&7])
#define READ_BIT2(p,i) (p[(i)>>3] & BIT_MASK_TABLE2[(i)&7])
const uint16_t AUDIO_TABLE_LEN = 120U;
const q15_t AUDIO_TABLE_DATA[] = {
0, 214, 428, 641, 851, 1060, 1265, 1468, 1666, 1859, 2048, 2230, 2407, 2577, 2740, 2896, 3043, 3182, 3313, 3434, 3546, 3649,
3741, 3823, 3895, 3955, 4006, 4045, 4073, 4089, 4095, 4089, 4073, 4045, 4006, 3955, 3895, 3823, 3741, 3649, 3546, 3434, 3313,
3182, 3043, 2896, 2740, 2577, 2407, 2230, 2048, 1859, 1666, 1468, 1265, 1060, 851, 641, 428, 214, 0, -214, -428, -641, -851,
-1060, -1265, -1468, -1666, -1859, -2047, -2230, -2407, -2577, -2740, -2896, -3043, -3182, -3313, -3434, -3546, -3649, -3741,
-3823, -3895, -3955, -4006, -4045, -4073, -4089, -4095, -4089, -4073, -4045, -4006, -3955, -3895, -3823, -3741, -3649, -3546,
-3434, -3313, -3182, -3043, -2896, -2740, -2577, -2407, -2230, -2047, -1859, -1666, -1468, -1265, -1060, -851, -641, -428, -214
};
CAX25TX::CAX25TX() :
m_poBuffer(),
m_poLen(0U),
m_poPtr(0U),
m_txDelay(360U),
m_tablePtr(0U),
m_nrzi(false)
{
}
void CAX25TX::process()
{
if (m_poLen == 0U)
return;
if (!m_duplex) {
if (m_poPtr == 0U) {
bool tx = ax25RX.canTX();
if (!tx)
return;
}
}
uint16_t space = io.getSpace();
while (space > AX25_RADIO_SYMBOL_LENGTH) {
bool b = READ_BIT1(m_poBuffer, m_poPtr) != 0U;
m_poPtr++;
writeBit(b);
space -= AX25_RADIO_SYMBOL_LENGTH;
if (m_poPtr >= m_poLen) {
m_poPtr = 0U;
m_poLen = 0U;
return;
}
}
}
uint8_t CAX25TX::writeData(const uint8_t* data, uint16_t length)
{
CAX25Frame frame(data, length);
frame.addCRC();
m_poLen = 0U;
m_poPtr = 0U;
m_nrzi = false;
m_tablePtr = 0U;
// Add TX delay
for (uint16_t i = 0U; i < m_txDelay; i++, m_poLen++) {
bool preamble = NRZI(false);
WRITE_BIT1(m_poBuffer, m_poLen, preamble);
}
// Add the Start Flag
for (uint16_t i = 0U; i < 8U; i++, m_poLen++) {
bool b1 = READ_BIT1(START_FLAG, i) != 0U;
bool b2 = NRZI(b1);
WRITE_BIT1(m_poBuffer, m_poLen, b2);
}
uint8_t ones = 0U;
for (uint16_t i = 0U; i < (frame.m_length * 8U); i++) {
bool b1 = READ_BIT2(frame.m_data, i) != 0U;
bool b2 = NRZI(b1);
WRITE_BIT1(m_poBuffer, m_poLen, b2);
m_poLen++;
if (b1) {
ones++;
if (ones == AX25_MAX_ONES) {
// Bit stuffing
bool b = NRZI(false);
WRITE_BIT1(m_poBuffer, m_poLen, b);
m_poLen++;
ones = 0U;
}
} else {
ones = 0U;
}
}
// Add the End Flag
for (uint16_t i = 0U; i < 8U; i++, m_poLen++) {
bool b1 = READ_BIT1(END_FLAG, i) != 0U;
bool b2 = NRZI(b1);
WRITE_BIT1(m_poBuffer, m_poLen, b2);
}
return 0U;
}
void CAX25TX::writeBit(bool b)
{
q15_t buffer[AX25_RADIO_SYMBOL_LENGTH];
for (uint8_t i = 0U; i < AX25_RADIO_SYMBOL_LENGTH; i++) {
q15_t value = AUDIO_TABLE_DATA[m_tablePtr];
if (b) {
// De-emphasise the lower frequency by 6dB
value >>= 2;
m_tablePtr += 6U;
} else {
m_tablePtr += 11U;
}
buffer[i] = value >> 1;
if (m_tablePtr >= AUDIO_TABLE_LEN)
m_tablePtr -= AUDIO_TABLE_LEN;
}
io.write(STATE_AX25, buffer, AX25_RADIO_SYMBOL_LENGTH);
}
void CAX25TX::setTXDelay(uint8_t delay)
{
m_txDelay = delay * 12U;
}
uint8_t CAX25TX::getSpace() const
{
return m_poLen == 0U ? 255U : 0U;
}
bool CAX25TX::NRZI(bool b)
{
if (!b)
m_nrzi = !m_nrzi;
return m_nrzi;
}
#endif
+53
View File
@@ -0,0 +1,53 @@
/*
* Copyright (C) 2020 by Jonathan Naylor G4KLX
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "Config.h"
#if defined(MODE_AX25)
#if !defined(AX25TX_H)
#define AX25TX_H
class CAX25TX {
public:
CAX25TX();
uint8_t writeData(const uint8_t* data, uint16_t length);
void process();
void setTXDelay(uint8_t delay);
uint8_t getSpace() const;
private:
uint8_t m_poBuffer[600U];
uint16_t m_poLen;
uint16_t m_poPtr;
uint16_t m_txDelay;
uint16_t m_tablePtr;
bool m_nrzi;
void writeBit(bool b);
bool NRZI(bool b);
};
#endif
#endif
+316
View File
@@ -0,0 +1,316 @@
/*
* Copyright (C) 2020 by Jonathan Naylor G4KLX
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "Config.h"
#if defined(MODE_AX25)
#include "Globals.h"
#include "AX25Twist.h"
// 1200Hz = -12dB, 2200Hz = 0dB; 3381Hz cutoff; cosine.
q15_t dB12[] = {
176,
-812,
-3916,
-7586,
23536,
-7586,
-3916,
-812,
176
};
// 1200Hz = -11dB, 2200Hz = 0dB; 3258Hz cutoff; cosine.
q15_t dB11[] = {
121,
-957,
-3959,
-7383,
23871,
-7383,
-3959,
-957,
121
};
// 1200Hz = -10dB, 2200Hz = 0dB; 3118Hz cutoff; cosine.
q15_t dB10[] = {
56,
-1110,
-3987,
-7141,
24254,
-7141,
-3987,
-1110,
56
};
// 1200Hz = -9dB, 2200Hz = 0dB; 2959Hz cutoff; cosine.
q15_t dB9[] = {
-19,
-1268,
-3994,
-6856,
24688,
-6856,
-3994,
-1268,
-19
};
// 1200Hz = -8dB, 2200Hz = 0dB; 2778Hz cutoff; cosine.
q15_t dB8[] = {
-104,
-1424,
-3968,
-6516,
25182,
-6516,
-3968,
-1424,
-104
};
// 1200Hz = -7dB, 2200Hz = 0dB; 2573Hz cutoff; cosine.
q15_t dB7[] = {
-196,
-1565,
-3896,
-6114,
25742,
-6114,
-3896,
-1565,
-196
};
// 1200Hz = -6dB, 2200Hz = 0dB; 2343Hz cutoff; cosine.
q15_t dB6[] = {
-288,
-1676,
-3761,
-5642,
26370,
-5642,
-3761,
-1676,
-288
};
// 1200Hz = -5dB, 2200Hz = 0dB; 2085Hz cutoff; cosine.
q15_t dB5[] = {
-370,
-1735,
-3545,
-5088,
27075,
-5088,
-3545,
-1735,
-370
};
// 1200Hz = -4dB, 2200Hz = 0dB; 1790Hz cutoff; cosine.
q15_t dB4[] = {
-432,
-1715,
-3220,
-4427,
27880,
-4427,
-3220,
-1715,
-432
};
// 1200Hz = -3dB, 2200Hz = 0dB; 1456Hz cutoff; cosine.
q15_t dB3[] = {
-452,
-1582,
-2759,
-3646,
28792,
-3646,
-2759,
-1582,
-452
};
// 1200Hz = -2dB, 2200Hz = 0dB; 1070Hz cutoff; cosine.
q15_t dB2[] = {
-408,
-1295,
-2123,
-2710,
29846,
-2710,
-2123,
-1295,
-408
};
// 1200Hz = -1dB, 2200Hz = 0dB; 605Hz cutoff; cosine.
q15_t dB1[] = {
-268,
-795,
-1244,
-1546,
31116,
-1546,
-1244,
-795,
-268
};
q15_t dB0[] = {
0,
0,
0,
0,
32767,
0,
0,
0,
0,
};
// 1200Hz = 0dB, 2200Hz = -1dB; 4130Hz cutoff; cosine.
q15_t dB_1[] = {
-419,
-177,
3316,
8650,
11278,
8650,
3316,
-177,
-419
};
// 1200Hz = 0dB, 2200Hz = -2dB; 3190Hz cutoff; cosine.
q15_t dB_2[] = {
-90,
1033,
3975,
7267,
8711,
7267,
3975,
1033,
-90
};
// 1200Hz = 0dB, 2200Hz = -3dB; 2330Hz cutoff; cosine.
q15_t dB_3[] = {
292,
1680,
3752,
5615,
6362,
5615,
3752,
1680,
292
};
// 1200Hz = 0dB, 2200Hz = -4dB; 2657Hz cutoff; boxcar.
q15_t dB_4[] = {
917,
3024,
5131,
6684,
7255,
6684,
5131,
3024,
917
};
// 1200Hz = 0dB, 2200Hz = -5dB; 2360Hz cutoff; boxcar.
q15_t dB_5[] = {
1620,
3339,
4925,
6042,
6444,
6042,
4925,
3339,
1620
};
// 1200Hz = 0dB, 2200Hz = -6dB; 2067Hz cutoff; boxcar.
q15_t dB_6[] = {
2161,
3472,
4605,
5373,
5644,
5373,
4605,
3472,
2161
};
q15_t* coeffs[] = {
dB12,
dB11,
dB10,
dB9,
dB8,
dB7,
dB6,
dB5,
dB4,
dB3,
dB2,
dB1,
dB0,
dB_1,
dB_2,
dB_3,
dB_4,
dB_5,
dB_6
};
CAX25Twist::CAX25Twist(int8_t n) :
m_filter(),
m_state()
{
setTwist(n);
}
void CAX25Twist::process(q15_t* in, q15_t* out, uint8_t length)
{
::arm_fir_fast_q15(&m_filter, in, out, length);
}
void CAX25Twist::setTwist(int8_t n)
{
uint8_t twist = uint8_t(n + 6);
m_filter.numTaps = 9;
m_filter.pState = m_state;
m_filter.pCoeffs = coeffs[twist];
}
#endif
+42
View File
@@ -0,0 +1,42 @@
/*
* Copyright (C) 2020 by Jonathan Naylor G4KLX
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "Config.h"
#if defined(MODE_AX25)
#if !defined(AX25Twist_H)
#define AX25Twist_H
class CAX25Twist {
public:
CAX25Twist(int8_t n);
void process(q15_t* in, q15_t* out, uint8_t length);
void setTwist(int8_t n);
private:
arm_fir_instance_q15 m_filter;
q15_t m_state[40U]; // NoTaps + BlockSize - 1, 9 + 20 - 1 plus some spare
};
#endif
#endif
-125
View File
@@ -1,125 +0,0 @@
In order to build MMDVM, you need to tell the Arduino GUI to link with the
CMSIS DSP library, which is doesn't do by default.
My development is on Windows and so I can vouch for the following instructions.
For Arduino 1.6.3 with SAM 1.6.4
--------------------------------
1. Go to the where the platform.txt file is located. On my Windows machine it's
in:
C:\Users\Jonathan\AppData\Roaming\Arduino15\packages\arduino\hardware\sam\1.6.4
On Mac OS X it's located in:
/Applications/Arduino.app/Contents/Resources/Java/hardware/arduino/sam
Or
~/Library/Arduino15/packages/arduino/hardware/sam/1.6.6
2. You'll need to open the file in a text editor and find the line:
## Combine gc-sections, archives, and objects
recipe.c.combine.pattern="{compiler.path}{compiler.c.elf.cmd}" {compiler.c.elf.flags} -mcpu={build.mcu} "-T{build.variant.path}/{build.ldscript}" "-Wl,-Map,{build.path}/{build.project_name}.map" {compiler.c.elf.extra_flags} -o "{build.path}/{build.project_name}.elf" "-L{build.path}" -mthumb -Wl,--cref -Wl,--check-sections -Wl,--gc-sections -Wl,--entry=Reset_Handler -Wl,--unresolved-symbols=report-all -Wl,--warn-common -Wl,--warn-section-align -Wl,--warn-unresolved-symbols -Wl,--start-group "{build.path}/syscalls_sam3.c.o" {object_files} "{build.variant.path}/{build.variant_system_lib}" "{build.path}/{archive_file}" -Wl,--end-group -lm -gcc
In my version it's line 73.
3. Modify it to read as follows:
## Combine gc-sections, archives, and objects
recipe.c.combine.pattern="{compiler.path}{compiler.c.elf.cmd}" {compiler.c.elf.flags} -mcpu={build.mcu} "-T{build.variant.path}/{build.ldscript}" "-Wl,-Map,{build.path}/{build.project_name}.map" {compiler.c.elf.extra_flags} -o "{build.path}/{build.project_name}.elf" "-L{build.path}" -mthumb -Wl,--cref -Wl,--check-sections -Wl,--gc-sections -Wl,--entry=Reset_Handler -Wl,--unresolved-symbols=report-all -Wl,--warn-common -Wl,--warn-section-align -Wl,--warn-unresolved-symbols -Wl,--start-group "{build.path}/syscalls_sam3.c.o" {object_files} "{build.variant.path}/{build.variant_system_lib}" "{build.system.path}/CMSIS/CMSIS/Lib/ARM/arm_cortexM3l_math.lib" "{build.path}/{archive_file}" -Wl,--end-group -lm -gcc
The change is near the end, and is the addition of:
"{build.system.path}/CMSIS/CMSIS/Lib/ARM/arm_cortexM3l_math.lib"
Which is the CMSIS AMR3 DSP library for little-endian operation.
4. Save the file and start up the Arduino GUI and build MMDVM.
I would like to get instructions for doing the same on a Linux platform. As a
starter find the relevent platform.txt and try adding:
"{build.system.path}/CMSIS/CMSIS/Lib/ARM/libarm_cortexM3l_math.a"
or maybe:
"{build.variant.path}/libarm_cortexM3l_math.a"
Likely on Linux
"{build.system.path}/CMSIS/CMSIS/Lib/GCC/libarm_cortexM3l_math.a"
As with Arduino 1.6.7 with SAM 1.6.6, see below.
For Arduino 1.6.7 with SAM 1.6.6
--------------------------------
(checked OK on Arduino 1.6.11 and SAM 1.6.9)
1. Go to the where the platform.txt file is located. On my Windows machine it's
in:
C:\Users\Jonathan\AppData\Local\Arduino15\packages\arduino\hardware\sam\1.6.6
On Mac OS X it's located in:
/Applications/Arduino.app/Contents/Resources/Java/hardware/arduino/sam
On Linux, it's located in my home directory, downloaded and extracted from Arduino website, but must be installed.
/home/m1geo/arduino-1.6.7/hardware/arduino/sam
or
/home/m1geo/.arduino15/packages/arduino/hardware/sam/1.6.9 (if you let the board/library manager install SAM)
I (M1GEO) found it was necessary to download SAM-1.6.6 outside of the Arduino IDE, and manually extract the files.
The Board Manager didn't seem to install the SAM files correctly. Here's how I did it:
a) wget http://downloads.arduino.cc/cores/sam-1.6.6.tar.bz2 -O /tmp/sam-1.6.6.tar.bz2 (download and save in /tmp)
b) cd arduino-1.6.7/hardware/arduino/ (Arduino root, here, in my home directory)
c) tar xvfj /tmp/sam-1.6.6.tar.bz2
2. You'll need to open the file (platform.txt) in a text editor and find the line:
## Combine gc-sections, archives, and objects
recipe.c.combine.pattern="{compiler.path}{compiler.c.elf.cmd}" -mcpu={build.mcu} -mthumb {compiler.c.elf.flags} "-T{build.variant.path}/{build.ldscript}" "-Wl,-Map,{build.path}/{build.project_name}.map" {compiler.c.elf.extra_flags} -o "{build.path}/{build.project_name}.elf" "-L{build.path}" -Wl,--cref -Wl,--check-sections -Wl,--gc-sections -Wl,--entry=Reset_Handler -Wl,--unresolved-symbols=report-all -Wl,--warn-common -Wl,--warn-section-align -Wl,--start-group "{build.path}/core/syscalls_sam3.c.o" {object_files} "{build.variant.path}/{build.variant_system_lib}" "{build.path}/{archive_file}" -Wl,--end-group -lm -gcc
In my version it's line 73.
3. Modify it to read as follows:
## Combine gc-sections, archives, and objects
recipe.c.combine.pattern="{compiler.path}{compiler.c.elf.cmd}" -mcpu={build.mcu} -mthumb {compiler.c.elf.flags} "-T{build.variant.path}/{build.ldscript}" "-Wl,-Map,{build.path}/{build.project_name}.map" {compiler.c.elf.extra_flags} -o "{build.path}/{build.project_name}.elf" "-L{build.path}" -Wl,--cref -Wl,--check-sections -Wl,--gc-sections -Wl,--entry=Reset_Handler -Wl,--unresolved-symbols=report-all -Wl,--warn-common -Wl,--warn-section-align -Wl,--start-group "{build.path}/core/syscalls_sam3.c.o" {object_files} "{build.variant.path}/{build.variant_system_lib}" "{build.system.path}/CMSIS/CMSIS/Lib/ARM/arm_cortexM3l_math.lib" "{build.path}/{archive_file}" -Wl,--end-group -lm -gcc
The change is near the end, and is the addition of:
"{build.system.path}/CMSIS/CMSIS/Lib/ARM/arm_cortexM3l_math.lib"
On Linux, the path was found to differ slightly (GCC instead of ARM):
"{build.system.path}/CMSIS/CMSIS/Lib/GCC/libarm_cortexM3l_math.a"
Which is the CMSIS AMR3 DSP library for little-endian operation.
4. Save the file and start up the Arduino GUI and build MMDVM.
For Arduino 1.6.9 with SAM 1.6.8
--------------------------------
1. Locate platform.txt. On Ubuntu 14.04 LTS x86_64 OS it is in:
/home/$user/.arduino15/packages/arduino/hardware/sam/1.6.8/
2. Open the file in a text editor and change the line:
## Combine gc-sections, archives, and objects
recipe.c.combine.pattern="{compiler.path}{compiler.c.elf.cmd}" -mcpu={build.mcu} -mthumb {compiler.c.elf.flags} "-T{build.variant.path}/{build.ldscript}" "-Wl,-Map,{build.path}/{build.project_name}.map" {compiler.c.elf.extra_flags} -o "{build.path}/{build.project_name}.elf" "-L{build.path}" -Wl,--cref -Wl,--check-sections -Wl,--gc-sections -Wl,--entry=Reset_Handler -Wl,--unresolved-symbols=report-all -Wl,--warn-common -Wl,--warn-section-align -Wl,--start-group {compiler.combine.flags} {object_files} "{build.variant.path}/{build.variant_system_lib}" "{build.path}/{archive_file}" -Wl,--end-group -lm -gcc
to
recipe.c.combine.pattern="{compiler.path}{compiler.c.elf.cmd}" -mcpu={build.mcu} -mthumb {compiler.c.elf.flags} "-T{build.variant.path}/{build.ldscript}" "-Wl,-Map,{build.path}/{build.project_name}.map" {compiler.c.elf.extra_flags} -o "{build.path}/{build.project_name}.elf" "-L{build.path}" -Wl,--cref -Wl,--check-sections -Wl,--gc-sections -Wl,--entry=Reset_Handler -Wl,--unresolved-symbols=report-all -Wl,--warn-common -Wl,--warn-section-align -Wl,--start-group {compiler.combine.flags} {object_files} "{build.variant.path}/{build.variant_system_lib}" "{build.system.path}/CMSIS/CMSIS/Lib/GCC/libarm_cortexM3l_math.a" "{build.path}/{archive_file}" -Wl,--end-group -lm -gcc
3. Save the file, open the Arduino IDE and build MMDVM
+3 -3
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2009-2017 by Jonathan Naylor G4KLX
* Copyright (C) 2009-2017,2020 by Jonathan Naylor G4KLX
* Copyright (C) 2016 by Colin Durbridge G4EML
*
* This program is free software; you can redistribute it and/or modify
@@ -77,6 +77,7 @@ const struct {
{',', 0xEEAEE000U, 22U},
{'-', 0xEAAE0000U, 18U},
{'=', 0xEAB80000U, 16U},
{'.', 0xBAEB8000U, 20U},
{' ', 0x00000000U, 4U},
{0U, 0x00000000U, 0U}
};
@@ -124,7 +125,7 @@ void CCWIdTX::process()
}
}
uint8_t CCWIdTX::write(const uint8_t* data, uint8_t length)
uint8_t CCWIdTX::write(const uint8_t* data, uint16_t length)
{
::memset(m_poBuffer, 0x00U, 1000U * sizeof(uint8_t));
@@ -170,4 +171,3 @@ void CCWIdTX::reset()
m_poPtr = 0U;
m_n = 0U;
}
+2 -2
View File
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2009-2015 by Jonathan Naylor G4KLX
* Copyright (C) 2016 by Colin Durbridge G4EML
* Copyright (C) 2016,2020 by Colin Durbridge G4EML
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -28,7 +28,7 @@ public:
void process();
uint8_t write(const uint8_t* data, uint8_t length);
uint8_t write(const uint8_t* data, uint16_t length);
void reset();
+7 -2
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2009-2015 by Jonathan Naylor G4KLX
* Copyright (C) 2009-2015,2020 by Jonathan Naylor G4KLX
* Copyright (C) 2016 by Colin Durbridge G4EML
*
* This program is free software; you can redistribute it and/or modify
@@ -18,6 +18,9 @@
*/
#include "Config.h"
#if defined(MODE_DMR)
#include "Globals.h"
#include "CalDMR.h"
@@ -208,7 +211,7 @@ void CCalDMR::dmrdmo1k()
}
}
uint8_t CCalDMR::write(const uint8_t* data, uint8_t length)
uint8_t CCalDMR::write(const uint8_t* data, uint16_t length)
{
if (length != 1U)
return 4U;
@@ -221,3 +224,5 @@ uint8_t CCalDMR::write(const uint8_t* data, uint8_t length)
return 0U;
}
#endif
+8 -3
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2009-2015 by Jonathan Naylor G4KLX
* Copyright (C) 2009-2015,2020 by Jonathan Naylor G4KLX
* Copyright (C) 2016 by Colin Durbridge G4EML
*
* This program is free software; you can redistribute it and/or modify
@@ -17,10 +17,13 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "Config.h"
#if defined(MODE_DMR)
#if !defined(CALDMR_H)
#define CALDMR_H
#include "Config.h"
#include "DMRDefines.h"
enum DMRCAL1K {
@@ -41,7 +44,7 @@ public:
void createData1k(uint8_t n);
void createDataDMO1k(uint8_t n);
uint8_t write(const uint8_t* data, uint8_t length);
uint8_t write(const uint8_t* data, uint16_t length);
private:
bool m_transmit;
@@ -53,3 +56,5 @@ private:
#endif
#endif
+7 -2
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2009-2016 by Jonathan Naylor G4KLX
* Copyright (C) 2009-2016,2020 by Jonathan Naylor G4KLX
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -17,6 +17,9 @@
*/
#include "Config.h"
#if defined(MODE_DSTAR)
#include "Globals.h"
#include "CalDStarRX.h"
#include "Utils.h"
@@ -24,7 +27,7 @@
const unsigned int BUFFER_LENGTH = 200U;
const uint32_t PLLMAX = 0x10000U;
const uint32_t PLLINC = PLLMAX / DSTAR_RADIO_BIT_LENGTH;
const uint32_t PLLINC = PLLMAX / DSTAR_RADIO_SYMBOL_LENGTH;
const uint32_t INC = PLLINC / 32U;
// D-Star bit order version of 0x55 0x2D 0x16
@@ -126,3 +129,5 @@ void CCalDStarRX::process(q15_t value)
}
}
#endif
+7 -2
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2015,2016 by Jonathan Naylor G4KLX
* Copyright (C) 2015,2016,2020 by Jonathan Naylor G4KLX
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -16,10 +16,13 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "Config.h"
#if defined(MODE_DSTAR)
#if !defined(CALDSTARRX_H)
#define CALDSTARRX_H
#include "Config.h"
#include "DStarDefines.h"
class CCalDStarRX {
@@ -40,3 +43,5 @@ private:
#endif
#endif
+7 -2
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2009-2016 by Jonathan Naylor G4KLX
* Copyright (C) 2009-2016,2020 by Jonathan Naylor G4KLX
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -17,6 +17,9 @@
*/
#include "Config.h"
#if defined(MODE_DSTAR)
#include "Globals.h"
#include "CalDStarTX.h"
@@ -162,7 +165,7 @@ void CCalDStarTX::process()
m_count = (m_count + 1U) % (30U * 21U);
}
uint8_t CCalDStarTX::write(const uint8_t* data, uint8_t length)
uint8_t CCalDStarTX::write(const uint8_t* data, uint16_t length)
{
if (length != 1U)
return 4U;
@@ -181,3 +184,5 @@ uint8_t CCalDStarTX::write(const uint8_t* data, uint8_t length)
return 0U;
}
#endif
+8 -3
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2015,2016 by Jonathan Naylor G4KLX
* Copyright (C) 2015,2016,2020 by Jonathan Naylor G4KLX
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -16,17 +16,20 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "Config.h"
#if defined(MODE_DSTAR)
#if !defined(CALDSTARTX_H)
#define CALDSTARTX_H
#include "Config.h"
#include "DStarDefines.h"
class CCalDStarTX {
public:
CCalDStarTX();
uint8_t write(const uint8_t* data, uint8_t length);
uint8_t write(const uint8_t* data, uint16_t length);
void process();
@@ -37,3 +40,5 @@ private:
#endif
#endif
+133
View File
@@ -0,0 +1,133 @@
/*
* Copyright (C) 2009-2015,2020 by Jonathan Naylor G4KLX
* Copyright (C) 2016 by Colin Durbridge G4EML
* Copyright (C) 2020 by Phil Taylor M0VSE
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "Config.h"
#if defined(MODE_FM)
#include "Globals.h"
#include "CalFM.h"
const struct TONE_TABLE {
uint16_t frequency;
uint16_t length;
q31_t increment;
} TONE_TABLE_DATA[] = {
{2495U, 10U, 223248821},
{2079U, 12U, 186025772},
{1633U, 15U, 146118367},
{1247U, 19U, 111579672},
{1039U, 23U, 93012886},
{956U, 25U, 85541432}};
const uint8_t TONE_TABLE_DATA_LEN = 6U;
CCalFM::CCalFM() :
m_frequency(0),
m_length(0),
m_tone(NULL),
m_level(128 * 12),
m_transmit(false),
m_audioSeq(0),
m_lastState(STATE_IDLE)
{
}
void CCalFM::process()
{
const TONE_TABLE* entry = NULL;
if (m_modemState != m_lastState)
{
switch (m_modemState) {
case STATE_FMCAL10K:
m_frequency = 956U;
break;
case STATE_FMCAL12K:
m_frequency = 1039U;
break;
case STATE_FMCAL15K:
m_frequency = 1247U;
break;
case STATE_FMCAL20K:
m_frequency = 1633U;
break;
case STATE_FMCAL25K:
m_frequency = 2079U;
break;
case STATE_FMCAL30K:
m_frequency = 2495U;
break;
default:
m_frequency = 0U;
break;
}
for (uint8_t i = 0U; i < TONE_TABLE_DATA_LEN; i++) {
if (TONE_TABLE_DATA[i].frequency == m_frequency) {
entry = TONE_TABLE_DATA + i;
break;
}
}
if (entry == NULL)
return;
m_length = entry->length;
delete[] m_tone;
m_tone = new q15_t[m_length];
q31_t arg = 0;
for (uint16_t i = 0U; i < m_length; i++) {
q63_t value = ::arm_sin_q31(arg) * q63_t(m_level);
m_tone[i] = q15_t(__SSAT((value >> 31), 16));
arg += entry->increment;
}
m_lastState=m_modemState;
}
if (m_transmit)
{
uint16_t space = io.getSpace();
while (space > m_length)
{
io.write(m_modemState,m_tone,m_length);
space -= m_length;
}
}
}
uint8_t CCalFM::write(const uint8_t* data, uint16_t length)
{
if (length != 1U)
return 4U;
m_transmit = data[0U] == 1U;
return 0U;
}
#endif
+55
View File
@@ -0,0 +1,55 @@
/*
* Copyright (C) 2009-2015,2020 by Jonathan Naylor G4KLX
* Copyright (C) 2016 by Colin Durbridge G4EML
* Copyright (C) 2020 by Phil Taylor M0VSE
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "Config.h"
#if defined(MODE_FM)
#if !defined(CALFM_H)
#define CALFM_H
class CCalFM {
public:
CCalFM();
void process();
void fm10kcal();
void fm12k5cal();
void fm15kcal();
void fm20kcal();
void fm25kcal();
void fm30kcal();
uint8_t write(const uint8_t* data, uint16_t length);
private:
uint16_t m_frequency;
uint16_t m_length;
q15_t* m_tone;
q15_t m_level;
bool m_transmit;
uint8_t m_audioSeq;
uint8_t m_lastState;
};
#endif
#endif
+66
View File
@@ -0,0 +1,66 @@
/*
* Copyright (C) 2009-2015,2020,2021 by Jonathan Naylor G4KLX
* Copyright (C) 2016 by Colin Durbridge G4EML
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "Config.h"
#if defined(MODE_M17)
#include "Globals.h"
#include "CalM17.h"
#include "M17Defines.h"
const uint8_t PREAMBLE[] = {0x00U,
0x77U, 0x77U, 0x77U, 0x77U, 0x77U, 0x77U, 0x77U, 0x77U,
0x77U, 0x77U, 0x77U, 0x77U, 0x77U, 0x77U, 0x77U, 0x77U,
0x77U, 0x77U, 0x77U, 0x77U, 0x77U, 0x77U, 0x77U, 0x77U,
0x77U, 0x77U, 0x77U, 0x77U, 0x77U, 0x77U, 0x77U, 0x77U,
0x77U, 0x77U, 0x77U, 0x77U, 0x77U, 0x77U, 0x77U, 0x77U,
0x77U, 0x77U, 0x77U, 0x77U, 0x77U, 0x77U, 0x77U, 0x77U};
CCalM17::CCalM17() :
m_transmit(false)
{
}
void CCalM17::process()
{
m17TX.process();
if (!m_transmit)
return;
uint16_t space = m17TX.getSpace();
if (space < 2U)
return;
m17TX.writeData(PREAMBLE, M17_FRAME_LENGTH_BYTES + 1U);
}
uint8_t CCalM17::write(const uint8_t* data, uint16_t length)
{
if (length != 1U)
return 4U;
m_transmit = data[0U] == 1U;
return 0U;
}
#endif
+43
View File
@@ -0,0 +1,43 @@
/*
* Copyright (C) 2009-2015,2020,2021 by Jonathan Naylor G4KLX
* Copyright (C) 2016 by Colin Durbridge G4EML
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "Config.h"
#if defined(MODE_M17)
#if !defined(CALM17_H)
#define CALM17_H
class CCalM17 {
public:
CCalM17();
void process();
uint8_t write(const uint8_t* data, uint16_t length);
private:
bool m_transmit;
};
#endif
#endif
+7 -1
View File
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2018 by Andy Uribe CA6JAU
* Copyright (C) 2020 by Jonathan Naylor G4KLX
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -17,6 +18,9 @@
*/
#include "Config.h"
#if defined(MODE_NXDN)
#include "Globals.h"
#include "CalNXDN.h"
@@ -79,7 +83,7 @@ void CCalNXDN::process()
}
}
uint8_t CCalNXDN::write(const uint8_t* data, uint8_t length)
uint8_t CCalNXDN::write(const uint8_t* data, uint16_t length)
{
if (length != 1U)
return 4U;
@@ -92,3 +96,5 @@ uint8_t CCalNXDN::write(const uint8_t* data, uint8_t length)
return 0U;
}
#endif
+8 -3
View File
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2018 by Andy Uribe CA6JAU
* Copyright (C) 2020 by Jonathan Naylor G4KLX
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -16,11 +17,13 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "Config.h"
#if defined(MODE_NXDN)
#if !defined(CALNXDN_H)
#define CALNXDN_H
#include "Config.h"
enum NXDNCAL1K {
NXDNCAL1K_IDLE,
NXDNCAL1K_TX
@@ -32,7 +35,7 @@ public:
void process();
uint8_t write(const uint8_t* data, uint8_t length);
uint8_t write(const uint8_t* data, uint16_t length);
private:
bool m_transmit;
@@ -42,3 +45,5 @@ private:
#endif
#endif
+7 -1
View File
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2018 by Andy Uribe CA6JAU
* Copyright (C) 2020 by Jonathan Naylor G4KLX
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -17,6 +18,9 @@
*/
#include "Config.h"
#if defined(MODE_P25)
#include "Globals.h"
#include "CalP25.h"
@@ -82,7 +86,7 @@ void CCalP25::process()
}
}
uint8_t CCalP25::write(const uint8_t* data, uint8_t length)
uint8_t CCalP25::write(const uint8_t* data, uint16_t length)
{
if (length != 1U)
return 4U;
@@ -95,3 +99,5 @@ uint8_t CCalP25::write(const uint8_t* data, uint8_t length)
return 0U;
}
#endif
+8 -2
View File
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2018 by Andy Uribe CA6JAU
* Copyright (C) 2020 by Jonathan Naylor G4KLX
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -16,10 +17,13 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "Config.h"
#if defined(MODE_P25)
#if !defined(CALP25_H)
#define CALP25_H
#include "Config.h"
#include "P25Defines.h"
enum P25CAL1K {
@@ -34,7 +38,7 @@ public:
void process();
uint8_t write(const uint8_t* data, uint8_t length);
uint8_t write(const uint8_t* data, uint16_t length);
private:
bool m_transmit;
@@ -43,3 +47,5 @@ private:
#endif
#endif
+8 -2
View File
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2019 by Florian Wolters DF2ET
* Copyright (C) 2020 by Jonathan Naylor G4KLX
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -17,10 +18,12 @@
*/
#include "Config.h"
#if defined(MODE_POCSAG)
#include "Globals.h"
#include "CalPOCSAG.h"
CCalPOCSAG::CCalPOCSAG() :
m_state(POCSAGCAL_IDLE)
{
@@ -38,7 +41,7 @@ void CCalPOCSAG::process()
pocsagTX.writeByte(0xAAU);
}
uint8_t CCalPOCSAG::write(const uint8_t* data, uint8_t length)
uint8_t CCalPOCSAG::write(const uint8_t* data, uint16_t length)
{
if (length != 1U)
return 4U;
@@ -47,3 +50,6 @@ uint8_t CCalPOCSAG::write(const uint8_t* data, uint8_t length)
return 0U;
}
#endif
+9 -3
View File
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2019 by Florian Wolters DF2ET
* Copyright (C) 2020 by Jonathan Naylor G4KLX
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -16,11 +17,13 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "Config.h"
#if defined(MODE_POCSAG)
#if !defined(CALPOCSAG_H)
#define CALPOCSAG_H
#include "Config.h"
enum POCSAGCAL {
POCSAGCAL_IDLE,
POCSAGCAL_TX
@@ -32,10 +35,13 @@ public:
void process();
uint8_t write(const uint8_t* data, uint8_t length);
uint8_t write(const uint8_t* data, uint16_t length);
private:
POCSAGCAL m_state;
};
#endif
#endif
+49 -22
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2015,2016,2017,2018,2020 by Jonathan Naylor G4KLX
* Copyright (C) 2015,2016,2017,2018,2020,2023 by Jonathan Naylor G4KLX
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -19,6 +19,37 @@
#if !defined(CONFIG_H)
#define CONFIG_H
// Allow for the selection of which modes to compile into the firmware. This is particularly useful for processors
// which have limited code space and processing power like the STM32F103, which is found on older/cheaper boards.
// Enable D-Star support.
#define MODE_DSTAR
// Enable DMR support.
#define MODE_DMR
// Enable System Fusion support.
#define MODE_YSF
// Enable P25 phase 1 support.
#define MODE_P25
// Enable NXDN support, the boxcar filter sometimes improves the performance of NXDN receive on some systems.
#define MODE_NXDN
#define USE_NXDN_BOXCAR
// Enable M17 support.
#define MODE_M17
// Enable POCSAG support.
#define MODE_POCSAG
// Enable FM support.
#define MODE_FM
// Enable AX.25 support, this is only enabled if FM is also enabled.
#define MODE_AX25
// Allow for the use of high quality external clock oscillators
// The number is the frequency of the oscillator in Hertz.
//
@@ -35,25 +66,14 @@
// For 19.2 MHz
// #define EXTERNAL_OSC 19200000
// Allow the use of the COS line to lockout the modem
// #define USE_COS_AS_LOCKOUT
// Select a baud rate for host communication. The faster speeds are needed for external FM to work.
// #define SERIAL_SPEED 115200 // Suitable for most older boards (Arduino Due, STM32F1_POG, etc). External FM will NOT work with this!
// #define SERIAL_SPEED 230400 // Only works on newer boards like fast M4, M7, Teensy 3.x. External FM might work with this
#define SERIAL_SPEED 460800 // Only works on newer boards like fast M4, M7, Teensy 3.x. External FM should work with this
//#define SERIAL_SPEED 500000 // Used with newer boards and Armbian on AllWinner SOCs (H2, H3) that do not support 460800
// Use pins to output the current mode via LEDs
// #define MODE_LEDS
// For the original Arduino Due pin layout
// #define ARDUINO_DUE_PAPA
#if defined(STM32F1)
// For the SQ6POG board
#define STM32F1_POG
#else
// For the ZUM V1.0 and V1.0.1 boards pin layout
#define ARDUINO_DUE_ZUM_V10
#endif
// For the SP8NTH board
// #define ARDUINO_DUE_NTH
#define MODE_LEDS
// For ST Nucleo-64 STM32F446RE board
// #define STM32F4_NUCLEO_MORPHO_HEADER
@@ -66,10 +86,13 @@
// #define VK6MST_TEENSY_PI3_SHIELD_I2C
// Pass RSSI information to the host
// #define SEND_RSSI_DATA
#define SEND_RSSI_DATA
// Use the modem as a serial repeater for Nextion displays
// #define SERIAL_REPEATER
#define SERIAL_REPEATER
// Use the modem as an I2C repeater for OLED displays
// #define I2C_REPEATER
// To reduce CPU load, you can remove the DC blocker by commenting out the next line
#define USE_DCBLOCKER
@@ -81,10 +104,14 @@
// Use the YSF and P25 LEDs for NXDN
// #define USE_ALTERNATE_NXDN_LEDS
// Use the D-Star and P25 LEDs for M17
#define USE_ALTERNATE_M17_LEDS
// Use the D-Star and DMR LEDs for POCSAG
// #define USE_ALTERNATE_POCSAG_LEDS
#define USE_ALTERNATE_POCSAG_LEDS
// Use the D-Star and YSF LEDs for FM
// #define USE_ALTERNATE_FM_LEDS
#define USE_ALTERNATE_FM_LEDS
#endif
+7 -1
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2009-2017 by Jonathan Naylor G4KLX
* Copyright (C) 2009-2017,2020 by Jonathan Naylor G4KLX
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -17,6 +17,9 @@
*/
#include "Config.h"
#if defined(MODE_DMR)
#include "Globals.h"
#include "DMRDMORX.h"
#include "DMRSlotType.h"
@@ -423,3 +426,6 @@ void CDMRDMORX::writeRSSIData(uint8_t* frame)
serial.writeDMRData(true, frame, DMR_FRAME_LENGTH_BYTES + 1U);
#endif
}
#endif
+8 -2
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2015,2016,2017 by Jonathan Naylor G4KLX
* Copyright (C) 2015,2016,2017,2020 by Jonathan Naylor G4KLX
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -16,10 +16,13 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "Config.h"
#if defined(MODE_DMR)
#if !defined(DMRDMORX_H)
#define DMRDMORX_H
#include "Config.h"
#include "DMRDefines.h"
const uint16_t DMO_BUFFER_LENGTH_SAMPLES = 1440U; // 60ms at 24 kHz
@@ -67,3 +70,6 @@ private:
};
#endif
#endif
+8 -3
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2009-2017 by Jonathan Naylor G4KLX
* Copyright (C) 2009-2017,2020 by Jonathan Naylor G4KLX
* Copyright (C) 2016 by Colin Durbridge G4EML
* Copyright (C) 2017 by Andy Uribe CA6JAU
*
@@ -19,6 +19,9 @@
*/
#include "Config.h"
#if defined(MODE_DMR)
#include "Globals.h"
#include "DMRSlotType.h"
@@ -74,7 +77,7 @@ void CDMRDMOTX::process()
m_poLen = m_txDelay;
} else {
for (unsigned int i = 0U; i < DMR_FRAME_LENGTH_BYTES; i++)
m_poBuffer[i] = m_fifo.get();
m_fifo.get(m_poBuffer[i]);
for (unsigned int i = 0U; i < 39U; i++)
m_poBuffer[i + DMR_FRAME_LENGTH_BYTES] = PR_FILL[i];
@@ -104,7 +107,7 @@ void CDMRDMOTX::process()
}
}
uint8_t CDMRDMOTX::writeData(const uint8_t* data, uint8_t length)
uint8_t CDMRDMOTX::writeData(const uint8_t* data, uint16_t length)
{
if (length != (DMR_FRAME_LENGTH_BYTES + 1U))
return 4U;
@@ -161,3 +164,5 @@ void CDMRDMOTX::setTXDelay(uint8_t delay)
m_txDelay = 1200U;
}
#endif
+10 -5
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2015,2016,2017 by Jonathan Naylor G4KLX
* Copyright (C) 2015,2016,2017,2020 by Jonathan Naylor G4KLX
* Copyright (C) 2016 by Colin Durbridge G4EML
*
* This program is free software; you can redistribute it and/or modify
@@ -17,19 +17,22 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "Config.h"
#if defined(MODE_DMR)
#if !defined(DMRDMOTX_H)
#define DMRDMOTX_H
#include "Config.h"
#include "DMRDefines.h"
#include "SerialRB.h"
#include "RingBuffer.h"
class CDMRDMOTX {
public:
CDMRDMOTX();
uint8_t writeData(const uint8_t* data, uint8_t length);
uint8_t writeData(const uint8_t* data, uint16_t length);
void process();
@@ -38,7 +41,7 @@ public:
uint8_t getSpace() const;
private:
CSerialRB m_fifo;
CRingBuffer<uint8_t> m_fifo;
arm_fir_interpolate_instance_q15 m_modFilter;
q15_t m_modState[16U]; // blockSize + phaseLength - 1, 4 + 9 - 1 plus some spare
uint8_t m_poBuffer[1200U];
@@ -51,3 +54,5 @@ private:
#endif
#endif
+7 -1
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2009-2017 by Jonathan Naylor G4KLX
* Copyright (C) 2009-2017,2020 by Jonathan Naylor G4KLX
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -17,6 +17,9 @@
*/
#include "Config.h"
#if defined(MODE_DMR)
#include "Globals.h"
#include "DMRIdleRX.h"
#include "DMRSlotType.h"
@@ -209,3 +212,6 @@ void CDMRIdleRX::setColorCode(uint8_t colorCode)
{
m_colorCode = colorCode;
}
#endif
+7 -2
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2015 by Jonathan Naylor G4KLX
* Copyright (C) 2015,2020 by Jonathan Naylor G4KLX
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -16,10 +16,13 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "Config.h"
#if defined(MODE_DMR)
#if !defined(DMRIDLERX_H)
#define DMRIDLERX_H
#include "Config.h"
#include "DMRDefines.h"
class CDMRIdleRX {
@@ -49,3 +52,5 @@ private:
#endif
#endif
+6 -1
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2015,2016 by Jonathan Naylor G4KLX
* Copyright (C) 2015,2016,2020 by Jonathan Naylor G4KLX
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -17,6 +17,9 @@
*/
#include "Config.h"
#if defined(MODE_DMR)
#include "Globals.h"
#include "DMRRX.h"
@@ -68,3 +71,5 @@ void CDMRRX::reset()
m_slot2RX.reset();
}
#endif
+7 -2
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2015,2016 by Jonathan Naylor G4KLX
* Copyright (C) 2015,2016,2020 by Jonathan Naylor G4KLX
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -16,10 +16,13 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "Config.h"
#if defined(MODE_DMR)
#if !defined(DMRRX_H)
#define DMRRX_H
#include "Config.h"
#include "DMRSlotRX.h"
class CDMRRX {
@@ -40,3 +43,5 @@ private:
#endif
#endif
+7 -1
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2009-2017 by Jonathan Naylor G4KLX
* Copyright (C) 2009-2017,2020 by Jonathan Naylor G4KLX
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -17,6 +17,9 @@
*/
#include "Config.h"
#if defined(MODE_DMR)
#include "Globals.h"
#include "DMRSlotRX.h"
#include "DMRSlotType.h"
@@ -400,3 +403,6 @@ void CDMRSlotRX::writeRSSIData(uint8_t* frame)
serial.writeDMRData(m_slot, frame, DMR_FRAME_LENGTH_BYTES + 1U);
#endif
}
#endif
+8 -2
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2015,2016,2017 by Jonathan Naylor G4KLX
* Copyright (C) 2015,2016,2017,2020 by Jonathan Naylor G4KLX
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -16,10 +16,13 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "Config.h"
#if defined(MODE_DMR)
#if !defined(DMRSLOTRX_H)
#define DMRSLOTRX_H
#include "Config.h"
#include "DMRDefines.h"
enum DMRRX_STATE {
@@ -70,3 +73,6 @@ private:
};
#endif
#endif
+6 -1
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2015 by Jonathan Naylor G4KLX
* Copyright (C) 2015,2020 by Jonathan Naylor G4KLX
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -17,6 +17,9 @@
*/
#include "Config.h"
#if defined(MODE_DMR)
#include "Globals.h"
#include "DMRSlotType.h"
@@ -285,3 +288,5 @@ void CDMRSlotType::encode(uint8_t colorCode, uint8_t dataType, uint8_t* frame) c
frame[20U] = (frame[20U] & 0x03U) | ((slotType[1U] << 6) & 0xC0U) | ((slotType[2U] >> 2) & 0x3CU);
}
#endif
+7 -1
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2015 by Jonathan Naylor G4KLX
* Copyright (C) 2015,2020 by Jonathan Naylor G4KLX
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -16,6 +16,10 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "Config.h"
#if defined(MODE_DMR)
#if !defined(DMRSLOTTYPE_H)
#define DMRSLOTTYPE_H
@@ -35,3 +39,5 @@ private:
#endif
#endif
+12 -6
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2009-2017 by Jonathan Naylor G4KLX
* Copyright (C) 2009-2017,2020 by Jonathan Naylor G4KLX
* Copyright (C) 2016 by Colin Durbridge G4EML
* Copyright (C) 2017 by Andy Uribe CA6JAU
*
@@ -19,6 +19,9 @@
*/
#include "Config.h"
#if defined(MODE_DMR)
#include "Globals.h"
#include "DMRSlotType.h"
@@ -144,7 +147,7 @@ void CDMRTX::process()
}
}
uint8_t CDMRTX::writeData1(const uint8_t* data, uint8_t length)
uint8_t CDMRTX::writeData1(const uint8_t* data, uint16_t length)
{
if (length != (DMR_FRAME_LENGTH_BYTES + 1U))
return 4U;
@@ -168,7 +171,7 @@ uint8_t CDMRTX::writeData1(const uint8_t* data, uint8_t length)
return 0U;
}
uint8_t CDMRTX::writeData2(const uint8_t* data, uint8_t length)
uint8_t CDMRTX::writeData2(const uint8_t* data, uint16_t length)
{
if (length != (DMR_FRAME_LENGTH_BYTES + 1U))
return 4U;
@@ -192,7 +195,7 @@ uint8_t CDMRTX::writeData2(const uint8_t* data, uint8_t length)
return 0U;
}
uint8_t CDMRTX::writeShortLC(const uint8_t* data, uint8_t length)
uint8_t CDMRTX::writeShortLC(const uint8_t* data, uint16_t length)
{
if (length != 9U)
return 4U;
@@ -208,7 +211,7 @@ uint8_t CDMRTX::writeShortLC(const uint8_t* data, uint8_t length)
return 0U;
}
uint8_t CDMRTX::writeAbort(const uint8_t* data, uint8_t length)
uint8_t CDMRTX::writeAbort(const uint8_t* data, uint16_t length)
{
if (length != 1U)
return 4U;
@@ -293,7 +296,7 @@ void CDMRTX::createData(uint8_t slotIndex)
{
if (m_fifo[slotIndex].getData() >= DMR_FRAME_LENGTH_BYTES && m_frameCount >= STARTUP_COUNT && m_abortCount[slotIndex] >= ABORT_COUNT) {
for (unsigned int i = 0U; i < DMR_FRAME_LENGTH_BYTES; i++) {
m_poBuffer[i] = m_fifo[slotIndex].get();
m_fifo[slotIndex].get(m_poBuffer[i]);
m_markBuffer[i] = MARK_NONE;
}
} else {
@@ -414,3 +417,6 @@ uint32_t CDMRTX::getFrameCount()
{
return m_frameCount;
}
#endif
+13 -8
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2015,2016,2017 by Jonathan Naylor G4KLX
* Copyright (C) 2015,2016,2017,2020 by Jonathan Naylor G4KLX
* Copyright (C) 2016 by Colin Durbridge G4EML
*
* This program is free software; you can redistribute it and/or modify
@@ -17,13 +17,16 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "Config.h"
#if defined(MODE_DMR)
#if !defined(DMRTX_H)
#define DMRTX_H
#include "Config.h"
#include "DMRDefines.h"
#include "SerialRB.h"
#include "RingBuffer.h"
enum DMRTXSTATE {
DMRTXSTATE_IDLE,
@@ -38,11 +41,11 @@ class CDMRTX {
public:
CDMRTX();
uint8_t writeData1(const uint8_t* data, uint8_t length);
uint8_t writeData2(const uint8_t* data, uint8_t length);
uint8_t writeData1(const uint8_t* data, uint16_t length);
uint8_t writeData2(const uint8_t* data, uint16_t length);
uint8_t writeShortLC(const uint8_t* data, uint8_t length);
uint8_t writeAbort(const uint8_t* data, uint8_t length);
uint8_t writeShortLC(const uint8_t* data, uint16_t length);
uint8_t writeAbort(const uint8_t* data, uint16_t length);
void setStart(bool start);
void setCal(bool start);
@@ -59,7 +62,7 @@ public:
void setColorCode(uint8_t colorCode);
private:
CSerialRB m_fifo[2U];
CRingBuffer<uint8_t> m_fifo[2U];
arm_fir_interpolate_instance_q15 m_modFilter;
q15_t m_modState[16U]; // blockSize + phaseLength - 1, 4 + 9 - 1 plus some spare
DMRTXSTATE m_state;
@@ -83,3 +86,5 @@ private:
#endif
#endif
+37 -17
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2009-2015 by Jonathan Naylor G4KLX
* Copyright (C) 2009-2015,2017,2020 by Jonathan Naylor G4KLX
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -19,30 +19,50 @@
#if !defined(DSTARDEFINES_H)
#define DSTARDEFINES_H
const unsigned int DSTAR_RADIO_BIT_LENGTH = 5U; // At 24 kHz sample rate
const unsigned int DSTAR_RADIO_SYMBOL_LENGTH = 5U; // At 24 kHz sample rate
const unsigned int DSTAR_HEADER_LENGTH_BYTES = 41U;
const unsigned int DSTAR_HEADER_LENGTH_BITS = DSTAR_HEADER_LENGTH_BYTES * 8U;
const unsigned int DSTAR_HEADER_LENGTH_BYTES = 41U;
const unsigned int DSTAR_FEC_SECTION_LENGTH_BYTES = 83U;
const unsigned int DSTAR_FEC_SECTION_LENGTH_BITS = 660U;
const unsigned int DSTAR_FEC_SECTION_LENGTH_BYTES = 83U;
const unsigned int DSTAR_FEC_SECTION_LENGTH_SYMBOLS = 660U;
const unsigned int DSTAR_FEC_SECTION_LENGTH_SAMPLES = DSTAR_FEC_SECTION_LENGTH_SYMBOLS * DSTAR_RADIO_SYMBOL_LENGTH;
const unsigned int DSTAR_DATA_LENGTH_BYTES = 12U;
const unsigned int DSTAR_DATA_LENGTH_BITS = DSTAR_DATA_LENGTH_BYTES * 8U;
const unsigned int DSTAR_DATA_LENGTH_BYTES = 12U;
const unsigned int DSTAR_DATA_LENGTH_SYMBOLS = DSTAR_DATA_LENGTH_BYTES * 8U;
const unsigned int DSTAR_DATA_LENGTH_SAMPLES = DSTAR_DATA_LENGTH_SYMBOLS * DSTAR_RADIO_SYMBOL_LENGTH;
const uint8_t DSTAR_EOT_BYTES[] = {0x55, 0x55, 0x55, 0x55, 0xC8, 0x7A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
const unsigned int DSTAR_EOT_LENGTH_BYTES = 6U;
const unsigned int DSTAR_EOT_LENGTH_BITS = DSTAR_EOT_LENGTH_BYTES * 8U;
const unsigned int DSTAR_END_SYNC_LENGTH_BYTES = 6U;
const unsigned int DSTAR_END_SYNC_LENGTH_BITS = DSTAR_END_SYNC_LENGTH_BYTES * 8U;
const uint8_t DSTAR_DATA_SYNC_LENGTH_BYTES = 3U;
const uint8_t DSTAR_DATA_SYNC_LENGTH_BITS = DSTAR_DATA_SYNC_LENGTH_BYTES * 8U;
const unsigned int DSTAR_FRAME_SYNC_LENGTH_BYTES = 3U;
const unsigned int DSTAR_FRAME_SYNC_LENGTH_SYMBOLS = DSTAR_FRAME_SYNC_LENGTH_BYTES * 8U;
const unsigned int DSTAR_FRAME_SYNC_LENGTH_SAMPLES = DSTAR_FRAME_SYNC_LENGTH_SYMBOLS * DSTAR_RADIO_SYMBOL_LENGTH;
const uint8_t DSTAR_DATA_SYNC_BYTES[] = {0x9E, 0x8D, 0x32, 0x88, 0x26, 0x1A, 0x3F, 0x61, 0xE8, 0x55, 0x2D, 0x16};
const unsigned int DSTAR_DATA_SYNC_LENGTH_BYTES = 3U;
const unsigned int DSTAR_DATA_SYNC_LENGTH_SYMBOLS = DSTAR_DATA_SYNC_LENGTH_BYTES * 8U;
const unsigned int DSTAR_DATA_SYNC_LENGTH_SAMPLES = DSTAR_DATA_SYNC_LENGTH_SYMBOLS * DSTAR_RADIO_SYMBOL_LENGTH;
const uint8_t DSTAR_SLOW_DATA_TYPE_TEXT = 0x40U;
const uint8_t DSTAR_SLOW_DATA_TYPE_HEADER = 0x50U;
const uint8_t DSTAR_DATA_SYNC_BYTES[] = {0x9E, 0x8D, 0x32, 0x88, 0x26, 0x1A, 0x3F, 0x61, 0xE8, 0x55, 0x2D, 0x16};
const uint8_t DSTAR_SCRAMBLER_BYTES[] = {0x70U, 0x4FU, 0x93U};
// D-Star bit order version of 0x55 0x6E 0x0A
const uint32_t DSTAR_FRAME_SYNC_DATA = 0x00557650U;
const uint32_t DSTAR_FRAME_SYNC_MASK = 0x00FFFFFFU;
const bool DSTAR_FRAME_SYNC_SYMBOLS[] = {false, true, false, true, false, true, false, true, false, true, true, true, false, true, true, false, false, true, false, true, false, false, false, false};
// D-Star bit order version of 0x55 0x2D 0x16
const uint32_t DSTAR_DATA_SYNC_DATA = 0x00AAB468U;
const uint32_t DSTAR_DATA_SYNC_MASK = 0x00FFFFFFU;
const bool DSTAR_DATA_SYNC_SYMBOLS[] = {true, false, true, false, true, false, true, false, true, false, true, true, false, true, false, false, false, true, true, false, true, false, false, false};
// D-Star bit order version of 0x55 0x55 0xC8 0x7A
const uint32_t DSTAR_END_SYNC_DATA = 0xAAAA135EU;
const uint32_t DSTAR_END_SYNC_MASK = 0xFFFFFFFFU;
const uint8_t DSTAR_END_SYNC_BYTES[] = {0x55, 0x55, 0x55, 0x55, 0xC8, 0x7A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
const uint8_t DSTAR_SLOW_DATA_TYPE_TEXT = 0x40U;
const uint8_t DSTAR_SLOW_DATA_TYPE_HEADER = 0x50U;
const uint8_t DSTAR_SCRAMBLER_BYTES[] = {0x70U, 0x4FU, 0x93U};
#endif
+249 -142
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2009-2017 by Jonathan Naylor G4KLX
* Copyright (C) 2009-2017,2020 by Jonathan Naylor G4KLX
* Copyright (C) 2017 by Andy Uribe CA6JAU
*
* This program is free software; you can redistribute it and/or modify
@@ -18,31 +18,28 @@
*/
#include "Config.h"
#if defined(MODE_DSTAR)
#include "Globals.h"
#include "DStarRX.h"
#include "Utils.h"
const unsigned int BUFFER_LENGTH = 200U;
const uint32_t PLLMAX = 0x10000U;
const uint32_t PLLINC = PLLMAX / DSTAR_RADIO_BIT_LENGTH;
const uint32_t INC = PLLINC / 32U;
const unsigned int MAX_SYNC_BITS = 100U * DSTAR_DATA_LENGTH_BITS;
const unsigned int MAX_FRAMES = 150U;
// D-Star bit order version of 0x55 0x55 0x6E 0x0A
const uint32_t FRAME_SYNC_DATA = 0x00557650U;
const uint32_t FRAME_SYNC_MASK = 0x00FFFFFFU;
const uint64_t FRAME_SYNC_DATA = 0x0000000000557650U;
const uint64_t FRAME_SYNC_MASK = 0x0000000000FFFFFFU;
const uint8_t FRAME_SYNC_ERRS = 2U;
// D-Star bit order version of 0x55 0x2D 0x16
const uint32_t DATA_SYNC_DATA = 0x00AAB468U;
const uint32_t DATA_SYNC_MASK = 0x00FFFFFFU;
const uint64_t DATA_SYNC_DATA = 0x0000000000AAB468U;
const uint64_t DATA_SYNC_MASK = 0x0000000000FFFFFFU;
const uint8_t DATA_SYNC_ERRS = 2U;
// D-Star bit order version of 0x55 0x55 0xC8 0x7A
const uint32_t END_SYNC_DATA = 0xAAAA135EU;
const uint32_t END_SYNC_MASK = 0xFFFFFFFFU;
const uint64_t END_SYNC_DATA = 0x0000AAAAAAAA135EU;
const uint64_t END_SYNC_MASK = 0x0000FFFFFFFFFFFFU;
const uint8_t END_SYNC_ERRS = 1U;
const uint8_t BIT_MASK_TABLE0[] = {0x7FU, 0xBFU, 0xDFU, 0xEFU, 0xF7U, 0xFBU, 0xFDU, 0xFEU};
@@ -237,14 +234,24 @@ const uint16_t CCITT_TABLE[] = {
0xf78fU, 0xe606U, 0xd49dU, 0xc514U, 0xb1abU, 0xa022U, 0x92b9U, 0x8330U,
0x7bc7U, 0x6a4eU, 0x58d5U, 0x495cU, 0x3de3U, 0x2c6aU, 0x1ef1U, 0x0f78U};
const uint16_t NOENDPTR = 9999U;
CDStarRX::CDStarRX() :
m_pll(0U),
m_prev(false),
m_rxState(DSRXS_NONE),
m_patternBuffer(0x00U),
m_rxBuffer(),
m_rxBufferBits(0U),
m_dataBits(0U),
m_bitBuffer(),
m_headerBuffer(),
m_dataBuffer(),
m_bitPtr(0U),
m_headerPtr(0U),
m_dataPtr(0U),
m_startPtr(NOENDPTR),
m_syncPtr(NOENDPTR),
m_minSyncPtr(NOENDPTR),
m_maxSyncPtr(NOENDPTR),
m_maxFrameCorr(0),
m_maxDataCorr(0),
m_frameCount(0U),
m_countdown(0U),
m_mar(0U),
m_pathMetric(),
m_pathMemory0(),
@@ -259,14 +266,20 @@ m_rssiCount(0U)
void CDStarRX::reset()
{
m_pll = 0U;
m_prev = false;
m_rxState = DSRXS_NONE;
m_patternBuffer = 0x00U;
m_rxBufferBits = 0U;
m_dataBits = 0U;
m_rssiAccum = 0U;
m_rssiCount = 0U;
m_rxState = DSRXS_NONE;
m_headerPtr = 0U;
m_dataPtr = 0U;
m_bitPtr = 0U;
m_maxFrameCorr = 0;
m_maxDataCorr = 0;
m_startPtr = NOENDPTR;
m_syncPtr = NOENDPTR;
m_minSyncPtr = NOENDPTR;
m_maxSyncPtr = NOENDPTR;
m_frameCount = 0U;
m_countdown = 0U;
m_rssiAccum = 0U;
m_rssiCount = 0U;
}
void CDStarRX::samples(const q15_t* samples, const uint16_t* rssi, uint8_t length)
@@ -275,125 +288,117 @@ void CDStarRX::samples(const q15_t* samples, const uint16_t* rssi, uint8_t lengt
m_rssiAccum += rssi[i];
m_rssiCount++;
bool bit = samples[i] < 0;
q15_t sample = samples[i];
if (bit != m_prev) {
if (m_pll < (PLLMAX / 2U))
m_pll += INC;
else
m_pll -= INC;
m_bitBuffer[m_bitPtr] <<= 1;
if (sample < 0)
m_bitBuffer[m_bitPtr] |= 0x01U;
m_dataBuffer[m_dataPtr] = sample;
switch (m_rxState) {
case DSRXS_HEADER:
processHeader(sample);
break;
case DSRXS_DATA:
processData();
break;
default:
processNone(sample);
break;
}
m_prev = bit;
m_dataPtr++;
if (m_dataPtr >= DSTAR_DATA_LENGTH_SAMPLES)
m_dataPtr = 0U;
m_pll += PLLINC;
if (m_pll >= PLLMAX) {
m_pll -= PLLMAX;
switch (m_rxState) {
case DSRXS_NONE:
processNone(bit);
break;
case DSRXS_HEADER:
processHeader(bit);
break;
case DSRXS_DATA:
processData(bit);
break;
default:
break;
}
}
m_bitPtr++;
if (m_bitPtr >= DSTAR_RADIO_SYMBOL_LENGTH)
m_bitPtr = 0U;
}
}
void CDStarRX::processNone(bool bit)
void CDStarRX::processNone(q15_t sample)
{
m_patternBuffer <<= 1;
if (bit)
m_patternBuffer |= 0x01U;
// Fuzzy matching of the frame sync sequence
if (countBits32((m_patternBuffer & FRAME_SYNC_MASK) ^ FRAME_SYNC_DATA) <= FRAME_SYNC_ERRS) {
DEBUG1("DStarRX: found frame sync in None");
bool ret = correlateFrameSync();
if (ret) {
m_countdown = 5U;
::memset(m_rxBuffer, 0x00U, DSTAR_FEC_SECTION_LENGTH_BYTES);
m_rxBufferBits = 0U;
m_headerBuffer[m_headerPtr] = sample;
m_headerPtr++;
m_rssiAccum = 0U;
m_rssiCount = 0U;
m_rxState = DSRXS_HEADER;
return;
}
// Exact matching of the data sync bit sequence
if (countBits32((m_patternBuffer & DATA_SYNC_MASK) ^ DATA_SYNC_DATA) == 0U) {
// Fuzzy matching of the data sync bit sequence
ret = correlateDataSync();
if (ret) {
DEBUG1("DStarRX: found data sync in None");
io.setDecode(true);
io.setADCDetection(true);
// Suppress RSSI on the dummy sync message
m_rssiAccum = 0U;
m_rssiCount = 0U;
::memcpy(m_rxBuffer, DSTAR_DATA_SYNC_BYTES, DSTAR_DATA_LENGTH_BYTES);
writeRSSIData(m_rxBuffer);
::memset(m_rxBuffer, 0x00U, DSTAR_DATA_LENGTH_BYTES + 2U);
m_rxBufferBits = 0U;
m_dataBits = MAX_SYNC_BITS;
m_rxState = DSRXS_DATA;
return;
m_rxState = DSRXS_DATA;
}
}
void CDStarRX::processHeader(bool bit)
void CDStarRX::processHeader(q15_t sample)
{
m_patternBuffer <<= 1;
if (bit)
m_patternBuffer |= 0x01U;
if (m_countdown > 0U) {
correlateFrameSync();
m_countdown--;
}
WRITE_BIT2(m_rxBuffer, m_rxBufferBits, bit);
m_rxBufferBits++;
m_headerBuffer[m_headerPtr] = sample;
m_headerPtr++;
// A full FEC header
if (m_rxBufferBits == DSTAR_FEC_SECTION_LENGTH_BITS) {
// Process the scrambling, interleaving and FEC, then return if the chcksum was correct
unsigned char header[DSTAR_HEADER_LENGTH_BYTES];
bool ok = rxHeader(m_rxBuffer, header);
if (ok) {
if (m_headerPtr == (DSTAR_FEC_SECTION_LENGTH_SAMPLES + DSTAR_RADIO_SYMBOL_LENGTH)) {
uint8_t buffer[DSTAR_FEC_SECTION_LENGTH_BYTES];
samplesToBits(m_headerBuffer, DSTAR_RADIO_SYMBOL_LENGTH, DSTAR_FEC_SECTION_LENGTH_SYMBOLS, buffer, DSTAR_FEC_SECTION_LENGTH_SAMPLES);
// Process the scrambling, interleaving and FEC, then return true if the chcksum was correct
uint8_t header[DSTAR_HEADER_LENGTH_BYTES];
bool ok = rxHeader(buffer, header);
if (!ok) {
// The checksum failed, return to looking for syncs
m_rxState = DSRXS_NONE;
m_maxFrameCorr = 0;
m_maxDataCorr = 0;
} else {
io.setDecode(true);
io.setADCDetection(true);
writeRSSIHeader(header);
::memset(m_rxBuffer, 0x00U, DSTAR_DATA_LENGTH_BYTES + 2U);
m_rxBufferBits = 0U;
m_rxState = DSRXS_DATA;
m_dataBits = MAX_SYNC_BITS;
} else {
// The checksum failed, return to looking for syncs
m_rxState = DSRXS_NONE;
}
}
// Ready to start the first data section
if (m_headerPtr == (DSTAR_FEC_SECTION_LENGTH_SAMPLES + 2U * DSTAR_RADIO_SYMBOL_LENGTH)) {
m_frameCount = 0U;
m_dataPtr = 0U;
m_startPtr = 476U;
m_syncPtr = 471U;
m_maxSyncPtr = 472U;
m_minSyncPtr = 470U;
DEBUG5("DStarRX: calc start/sync/max/min", m_startPtr, m_syncPtr, m_maxSyncPtr, m_minSyncPtr);
m_rxState = DSRXS_DATA;
}
}
void CDStarRX::processData(bool bit)
void CDStarRX::processData()
{
m_patternBuffer <<= 1;
if (bit)
m_patternBuffer |= 0x01U;
WRITE_BIT2(m_rxBuffer, m_rxBufferBits, bit);
m_rxBufferBits++;
// Fuzzy matching of the end frame sequences
if (countBits32((m_patternBuffer & END_SYNC_MASK) ^ END_SYNC_DATA) <= END_SYNC_ERRS) {
if (countBits64((m_bitBuffer[m_bitPtr] & DSTAR_END_SYNC_MASK) ^ DSTAR_END_SYNC_DATA) <= END_SYNC_ERRS) {
DEBUG1("DStarRX: Found end sync in Data");
io.setDecode(false);
@@ -401,35 +406,24 @@ void CDStarRX::processData(bool bit)
serial.writeDStarEOT();
m_maxFrameCorr = 0;
m_maxDataCorr = 0;
m_rxState = DSRXS_NONE;
return;
}
// Fuzzy matching of the data sync bit sequence
bool syncSeen = false;
if (m_rxBufferBits >= (DSTAR_DATA_LENGTH_BITS - 3U)) {
if (countBits32((m_patternBuffer & DATA_SYNC_MASK) ^ DATA_SYNC_DATA) <= DATA_SYNC_ERRS) {
m_rxBufferBits = DSTAR_DATA_LENGTH_BITS;
m_dataBits = MAX_SYNC_BITS;
syncSeen = true;
}
if (m_minSyncPtr < m_maxSyncPtr) {
if (m_dataPtr >= m_minSyncPtr && m_dataPtr <= m_maxSyncPtr)
correlateDataSync();
} else {
if (m_dataPtr >= m_minSyncPtr || m_dataPtr <= m_maxSyncPtr)
correlateDataSync();
}
// Check to see if the sync is arriving late
if (m_rxBufferBits == DSTAR_DATA_LENGTH_BITS && !syncSeen) {
for (uint8_t i = 1U; i <= 3U; i++) {
uint32_t syncMask = DATA_SYNC_MASK >> i;
uint32_t syncData = DATA_SYNC_DATA >> i;
if (countBits32((m_patternBuffer & syncMask) ^ syncData) <= DATA_SYNC_ERRS) {
m_rxBufferBits -= i;
break;
}
}
}
m_dataBits--;
if (m_dataBits == 0U) {
// We've not seen a data sync for too long, signal RXLOST and change to RX_NONE
if (m_frameCount >= MAX_FRAMES) {
DEBUG1("DStarRX: data sync timed out, lost lock");
io.setDecode(false);
@@ -437,24 +431,35 @@ void CDStarRX::processData(bool bit)
serial.writeDStarLost();
m_maxFrameCorr = 0;
m_maxDataCorr = 0;
m_rxState = DSRXS_NONE;
return;
}
// Send a data frame to the host if the required number of bits have been received, or if a data sync has been seen
if (m_rxBufferBits == DSTAR_DATA_LENGTH_BITS) {
if (syncSeen) {
m_rxBuffer[9U] = DSTAR_DATA_SYNC_BYTES[9U];
m_rxBuffer[10U] = DSTAR_DATA_SYNC_BYTES[10U];
m_rxBuffer[11U] = DSTAR_DATA_SYNC_BYTES[11U];
writeRSSIData(m_rxBuffer);
} else {
serial.writeDStarData(m_rxBuffer, DSTAR_DATA_LENGTH_BYTES);
}
// Send a data frame to the host if the required number of bits have been received
if (m_dataPtr == m_maxSyncPtr) {
uint8_t buffer[DSTAR_DATA_LENGTH_BYTES + 2U];
samplesToBits(m_dataBuffer, m_startPtr, DSTAR_DATA_LENGTH_SYMBOLS, buffer, DSTAR_DATA_LENGTH_SAMPLES);
// Start the next frame
::memset(m_rxBuffer, 0x00U, DSTAR_DATA_LENGTH_BYTES + 2U);
m_rxBufferBits = 0U;
if ((m_frameCount % 21U) == 0U) {
if (m_frameCount == 0U) {
buffer[9U] = DSTAR_DATA_SYNC_BYTES[9U];
buffer[10U] = DSTAR_DATA_SYNC_BYTES[10U];
buffer[11U] = DSTAR_DATA_SYNC_BYTES[11U];
DEBUG5("DStarRX: found start/sync/max/min", m_startPtr, m_syncPtr, m_maxSyncPtr, m_minSyncPtr);
}
writeRSSIData(buffer);
} else {
serial.writeDStarData(buffer, DSTAR_DATA_LENGTH_BYTES);
}
m_frameCount++;
m_maxFrameCorr = 0;
m_maxDataCorr = 0;
}
}
@@ -500,6 +505,105 @@ void CDStarRX::writeRSSIData(unsigned char* data)
m_rssiCount = 0U;
}
bool CDStarRX::correlateFrameSync()
{
if (countBits64((m_bitBuffer[m_bitPtr] & DSTAR_FRAME_SYNC_MASK) ^ DSTAR_FRAME_SYNC_DATA) <= FRAME_SYNC_ERRS) {
uint16_t ptr = m_dataPtr + DSTAR_DATA_LENGTH_SAMPLES - DSTAR_FRAME_SYNC_LENGTH_SAMPLES + DSTAR_RADIO_SYMBOL_LENGTH;
if (ptr >= DSTAR_DATA_LENGTH_SAMPLES)
ptr -= DSTAR_DATA_LENGTH_SAMPLES;
q31_t corr = 0;
for (uint8_t i = 0U; i < DSTAR_FRAME_SYNC_LENGTH_SYMBOLS; i++) {
q15_t val = m_dataBuffer[ptr];
if (DSTAR_FRAME_SYNC_SYMBOLS[i])
corr -= val;
else
corr += val;
ptr += DSTAR_RADIO_SYMBOL_LENGTH;
if (ptr >= DSTAR_DATA_LENGTH_SAMPLES)
ptr -= DSTAR_DATA_LENGTH_SAMPLES;
}
if (corr > m_maxFrameCorr) {
m_maxFrameCorr = corr;
m_headerPtr = 0U;
return true;
}
}
return false;
}
bool CDStarRX::correlateDataSync()
{
uint8_t maxErrs = 0U;
if (m_rxState == DSRXS_DATA)
maxErrs = DATA_SYNC_ERRS;
if (countBits64((m_bitBuffer[m_bitPtr] & DSTAR_DATA_SYNC_MASK) ^ DSTAR_DATA_SYNC_DATA) <= maxErrs) {
uint16_t ptr = m_dataPtr + DSTAR_DATA_LENGTH_SAMPLES - DSTAR_DATA_SYNC_LENGTH_SAMPLES + DSTAR_RADIO_SYMBOL_LENGTH;
if (ptr >= DSTAR_DATA_LENGTH_SAMPLES)
ptr -= DSTAR_DATA_LENGTH_SAMPLES;
q31_t corr = 0;
for (uint8_t i = 0U; i < DSTAR_DATA_SYNC_LENGTH_SYMBOLS; i++) {
q15_t val = m_dataBuffer[ptr];
if (DSTAR_DATA_SYNC_SYMBOLS[i])
corr -= val;
else
corr += val;
ptr += DSTAR_RADIO_SYMBOL_LENGTH;
if (ptr >= DSTAR_DATA_LENGTH_SAMPLES)
ptr -= DSTAR_DATA_LENGTH_SAMPLES;
}
if (corr > m_maxDataCorr) {
m_maxDataCorr = corr;
m_frameCount = 0U;
m_syncPtr = m_dataPtr;
m_startPtr = m_dataPtr + DSTAR_RADIO_SYMBOL_LENGTH;
if (m_startPtr >= DSTAR_DATA_LENGTH_SAMPLES)
m_startPtr -= DSTAR_DATA_LENGTH_SAMPLES;
m_maxSyncPtr = m_syncPtr + 1U;
if (m_maxSyncPtr >= DSTAR_DATA_LENGTH_SAMPLES)
m_maxSyncPtr -= DSTAR_DATA_LENGTH_SAMPLES;
m_minSyncPtr = m_syncPtr + DSTAR_DATA_LENGTH_SAMPLES - 1U;
if (m_minSyncPtr >= DSTAR_DATA_LENGTH_SAMPLES)
m_minSyncPtr -= DSTAR_DATA_LENGTH_SAMPLES;
return true;
}
}
return false;
}
void CDStarRX::samplesToBits(const q15_t* inBuffer, uint16_t start, uint16_t count, uint8_t* outBuffer, uint16_t limit)
{
for (uint16_t i = 0U; i < count; i++) {
q15_t sample = inBuffer[start];
if (sample < 0)
WRITE_BIT2(outBuffer, i, true);
else
WRITE_BIT2(outBuffer, i, false);
start += DSTAR_RADIO_SYMBOL_LENGTH;
if (start >= limit)
start -= limit;
}
}
bool CDStarRX::rxHeader(uint8_t* in, uint8_t* out)
{
int i;
@@ -715,3 +819,6 @@ bool CDStarRX::checksum(const uint8_t* header) const
return crc8[0U] == header[DSTAR_HEADER_LENGTH_BYTES - 2U] && crc8[1U] == header[DSTAR_HEADER_LENGTH_BYTES - 1U];
}
#endif
+27 -11
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2015,2016,2017 by Jonathan Naylor G4KLX
* Copyright (C) 2015,2016,2017,2020 by Jonathan Naylor G4KLX
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -16,10 +16,13 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "Config.h"
#if defined(MODE_DSTAR)
#if !defined(DSTARRX_H)
#define DSTARRX_H
#include "Config.h"
#include "DStarDefines.h"
enum DSRX_STATE {
@@ -37,13 +40,21 @@ public:
void reset();
private:
uint32_t m_pll;
bool m_prev;
DSRX_STATE m_rxState;
uint32_t m_patternBuffer;
uint8_t m_rxBuffer[100U];
unsigned int m_rxBufferBits;
unsigned int m_dataBits;
uint64_t m_bitBuffer[DSTAR_RADIO_SYMBOL_LENGTH];
q15_t m_headerBuffer[DSTAR_FEC_SECTION_LENGTH_SAMPLES + 2U * DSTAR_RADIO_SYMBOL_LENGTH];
q15_t m_dataBuffer[DSTAR_DATA_LENGTH_SAMPLES];
uint16_t m_bitPtr;
uint16_t m_headerPtr;
uint16_t m_dataPtr;
uint16_t m_startPtr;
uint16_t m_syncPtr;
uint16_t m_minSyncPtr;
uint16_t m_maxSyncPtr;
q31_t m_maxFrameCorr;
q31_t m_maxDataCorr;
uint16_t m_frameCount;
uint8_t m_countdown;
unsigned int m_mar;
int m_pathMetric[4U];
unsigned int m_pathMemory0[42U];
@@ -54,9 +65,12 @@ private:
uint32_t m_rssiAccum;
uint16_t m_rssiCount;
void processNone(bool bit);
void processHeader(bool bit);
void processData(bool bit);
void processNone(q15_t sample);
void processHeader(q15_t sample);
void processData();
bool correlateFrameSync();
bool correlateDataSync();
void samplesToBits(const q15_t* inBuffer, uint16_t start, uint16_t count, uint8_t* outBuffer, uint16_t limit);
void writeRSSIHeader(unsigned char* header);
void writeRSSIData(unsigned char* data);
bool rxHeader(uint8_t* in, uint8_t* out);
@@ -68,3 +82,5 @@ private:
#endif
#endif
+23 -15
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2009-2017 by Jonathan Naylor G4KLX
* Copyright (C) 2009-2017,2020 by Jonathan Naylor G4KLX
* Copyright (C) 2017 by Andy Uribe CA6JAU
*
* This program is free software; you can redistribute it and/or modify
@@ -18,6 +18,9 @@
*/
#include "Config.h"
#if defined(MODE_DSTAR)
#include "Globals.h"
#include "DStarTX.h"
@@ -198,7 +201,7 @@ m_txDelay(60U) // 100ms
{
::memset(m_modState, 0x00U, 20U * sizeof(q15_t));
m_modFilter.L = DSTAR_RADIO_BIT_LENGTH;
m_modFilter.L = DSTAR_RADIO_SYMBOL_LENGTH;
m_modFilter.phaseLength = GAUSSIAN_0_35_FILTER_PHASE_LEN;
m_modFilter.pCoeffs = GAUSSIAN_0_35_FILTER;
m_modFilter.pState = m_modState;
@@ -217,11 +220,12 @@ void CDStarTX::process()
m_poBuffer[m_poLen++] = BIT_SYNC;
} else {
// Pop the type byte off
m_buffer.get();
uint8_t dummy;
m_buffer.get(dummy);
uint8_t header[DSTAR_HEADER_LENGTH_BYTES];
for (uint8_t i = 0U; i < DSTAR_HEADER_LENGTH_BYTES; i++)
header[i] = m_buffer.get();
m_buffer.get(header[i]);
uint8_t buffer[86U];
txHeader(header, buffer + 2U);
@@ -239,21 +243,23 @@ void CDStarTX::process()
if (type == DSTAR_DATA && m_poLen == 0U) {
// Pop the type byte off
m_buffer.get();
uint8_t dummy;
m_buffer.get(dummy);
for (uint8_t i = 0U; i < DSTAR_DATA_LENGTH_BYTES; i++)
m_poBuffer[m_poLen++] = m_buffer.get();
m_buffer.get(m_poBuffer[m_poLen++]);
m_poPtr = 0U;
}
if (type == DSTAR_EOT && m_poLen == 0U) {
// Pop the type byte off
m_buffer.get();
uint8_t dummy;
m_buffer.get(dummy);
for (uint8_t j = 0U; j < 3U; j++) {
for (uint8_t i = 0U; i < DSTAR_EOT_LENGTH_BYTES; i++)
m_poBuffer[m_poLen++] = DSTAR_EOT_BYTES[i];
for (uint8_t i = 0U; i < DSTAR_END_SYNC_LENGTH_BYTES; i++)
m_poBuffer[m_poLen++] = DSTAR_END_SYNC_BYTES[i];
}
m_poPtr = 0U;
@@ -262,11 +268,11 @@ void CDStarTX::process()
if (m_poLen > 0U) {
uint16_t space = io.getSpace();
while (space > (8U * DSTAR_RADIO_BIT_LENGTH)) {
while (space > (8U * DSTAR_RADIO_SYMBOL_LENGTH)) {
uint8_t c = m_poBuffer[m_poPtr++];
writeByte(c);
space -= 8U * DSTAR_RADIO_BIT_LENGTH;
space -= 8U * DSTAR_RADIO_SYMBOL_LENGTH;
if (m_poPtr >= m_poLen) {
m_poPtr = 0U;
@@ -277,7 +283,7 @@ void CDStarTX::process()
}
}
uint8_t CDStarTX::writeHeader(const uint8_t* header, uint8_t length)
uint8_t CDStarTX::writeHeader(const uint8_t* header, uint16_t length)
{
if (length != DSTAR_HEADER_LENGTH_BYTES)
return 4U;
@@ -296,7 +302,7 @@ uint8_t CDStarTX::writeHeader(const uint8_t* header, uint8_t length)
return 0U;
}
uint8_t CDStarTX::writeData(const uint8_t* data, uint8_t length)
uint8_t CDStarTX::writeData(const uint8_t* data, uint16_t length)
{
if (length != DSTAR_DATA_LENGTH_BYTES)
return 4U;
@@ -412,7 +418,7 @@ void CDStarTX::txHeader(const uint8_t* in, uint8_t* out) const
void CDStarTX::writeByte(uint8_t c)
{
q15_t inBuffer[8U];
q15_t outBuffer[DSTAR_RADIO_BIT_LENGTH * 8U];
q15_t outBuffer[DSTAR_RADIO_SYMBOL_LENGTH * 8U];
uint8_t mask = 0x01U;
@@ -427,7 +433,7 @@ void CDStarTX::writeByte(uint8_t c)
::arm_fir_interpolate_q15(&m_modFilter, inBuffer, outBuffer, 8U);
io.write(STATE_DSTAR, outBuffer, DSTAR_RADIO_BIT_LENGTH * 8U);
io.write(STATE_DSTAR, outBuffer, DSTAR_RADIO_SYMBOL_LENGTH * 8U);
}
void CDStarTX::setTXDelay(uint8_t delay)
@@ -443,3 +449,5 @@ uint8_t CDStarTX::getSpace() const
return m_buffer.getSpace() / (DSTAR_DATA_LENGTH_BYTES + 1U);
}
#endif
+11 -7
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2015,2016,2017 by Jonathan Naylor G4KLX
* Copyright (C) 2015,2016,2017,2020 by Jonathan Naylor G4KLX
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -16,19 +16,21 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "Config.h"
#if defined(MODE_DSTAR)
#if !defined(DSTARTX_H)
#define DSTARTX_H
#include "Config.h"
#include "SerialRB.h"
#include "RingBuffer.h"
class CDStarTX {
public:
CDStarTX();
uint8_t writeHeader(const uint8_t* header, uint8_t length);
uint8_t writeData(const uint8_t* data, uint8_t length);
uint8_t writeHeader(const uint8_t* header, uint16_t length);
uint8_t writeData(const uint8_t* data, uint16_t length);
uint8_t writeEOT();
void process();
@@ -38,7 +40,7 @@ public:
uint8_t getSpace() const;
private:
CSerialRB m_buffer;
CRingBuffer<uint8_t> m_buffer;
arm_fir_interpolate_instance_q15 m_modFilter;
q15_t m_modState[20U]; // blockSize + phaseLength - 1, 8 + 9 - 1 plus some spare
uint8_t m_poBuffer[600U];
@@ -52,3 +54,5 @@ private:
#endif
#endif
+2 -1
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2015,2016,2017 by Jonathan Naylor G4KLX
* Copyright (C) 2015,2016,2017,2021 by Jonathan Naylor G4KLX
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -27,6 +27,7 @@
#define DEBUG3(a,b,c) serial.writeDebug((a),(b),(c))
#define DEBUG4(a,b,c,d) serial.writeDebug((a),(b),(c),(d))
#define DEBUG5(a,b,c,d,e) serial.writeDebug((a),(b),(c),(d),(e))
#define DEBUG_DUMP(a,b) serial.writeDebugDump((a),(b))
#endif
+1054 -140
View File
File diff suppressed because it is too large Load Diff
+78 -29
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2020 by Jonathan Naylor G4KLX
* Copyright (C) 2020,2021,2023 by Jonathan Naylor G4KLX
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -16,55 +16,57 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "Config.h"
#if defined(MODE_FM)
#if !defined(FM_H)
#define FM_H
#include "Config.h"
#include "FMBlanking.h"
#include "FMCTCSSRX.h"
#include "FMCTCSSTX.h"
#include "FMTimeout.h"
#include "FMKeyer.h"
#include "FMTimer.h"
#include "RingBuffer.h"
#include "FMDirectForm1.h"
enum FM_STATE {
FS_LISTENING,
FS_KERCHUNK,
FS_RELAYING,
FS_RELAYING_WAIT,
FS_TIMEOUT,
FS_TIMEOUT_WAIT,
FS_HANG
};
#include "FMDownSampler.h"
#include "FMUpSampler.h"
#include "FMNoiseSquelch.h"
class CFM {
public:
CFM();
void samples(bool cos, q15_t* samples, uint8_t length);
void samples(bool cos, q15_t* samples, const uint16_t* rssi, uint8_t length);
void process();
void reset();
uint8_t setCallsign(const char* callsign, uint8_t speed, uint16_t frequency, uint8_t time, uint8_t holdoff, uint8_t highLevel, uint8_t lowLevel, bool callsignAtStart, bool callsignAtEnd);
uint8_t setCallsign(const char* callsign, uint8_t speed, uint16_t frequency, uint8_t time, uint8_t holdoff, uint8_t highLevel, uint8_t lowLevel, bool callsignAtStart, bool callsignAtEnd, bool callsignAtLatch);
uint8_t setAck(const char* rfAck, uint8_t speed, uint16_t frequency, uint8_t minTime, uint16_t delay, uint8_t level);
uint8_t setMisc(uint16_t timeout, uint8_t timeoutLevel, uint8_t ctcssFrequency, uint8_t ctcssThreshold, uint8_t ctcssLevel, uint8_t kerchunkTime, uint8_t hangTime, bool useCOS, uint8_t rxBoost, uint8_t maxDev);
uint8_t setMisc(uint16_t timeout, uint8_t timeoutLevel, uint8_t ctcssFrequency, uint8_t ctcssHighThreshold, uint8_t ctcssLowThreshold, uint8_t ctcssLevel, uint8_t kerchunkTime, uint8_t hangTime, uint8_t accessMode, bool linkMode, bool cosInvert, bool noiseSquelch, uint8_t squelchHighThreshold, uint8_t squelchLowThreshold, uint8_t rfAudioBoost, uint8_t maxDev, uint8_t rxLevel);
uint8_t setExt(const char* ack, uint8_t audioBoost, uint8_t speed, uint16_t frequency, uint8_t level);
uint8_t getSpace() const;
uint8_t writeData(const uint8_t* data, uint8_t length);
private:
CFMKeyer m_callsign;
CFMKeyer m_rfAck;
CFMKeyer m_extAck;
CFMCTCSSRX m_ctcssRX;
CFMCTCSSTX m_ctcssTX;
CFMNoiseSquelch m_squelch;
CFMTimeout m_timeoutTone;
FM_STATE m_state;
uint8_t m_state;
bool m_callsignAtStart;
bool m_callsignAtEnd;
bool m_callsignAtLatch;
CFMTimer m_callsignTimer;
CFMTimer m_timeoutTimer;
CFMTimer m_holdoffTimer;
@@ -72,24 +74,71 @@ private:
CFMTimer m_ackMinTimer;
CFMTimer m_ackDelayTimer;
CFMTimer m_hangTimer;
CFMTimer m_reverseTimer;
bool m_needReverse;
CFMDirectFormI m_filterStage1;
CFMDirectFormI m_filterStage2;
CFMDirectFormI m_filterStage3;
CFMBlanking m_blanking;
bool m_useCOS;
q15_t m_rxBoost;
uint8_t m_accessMode;
bool m_linkMode;
bool m_cosInvert;
bool m_noiseSquelch;
q15_t m_rfAudioBoost;
q15_t m_extAudioBoost;
CFMDownSampler m_downSampler;
bool m_extEnabled;
q15_t m_rxLevel;
CRingBuffer<q15_t> m_inputRFRB;
CRingBuffer<q15_t> m_outputRFRB;
CFMUpSampler m_inputExtRB;
bool m_rfSignal;
bool m_extSignal;
uint32_t m_rssiAccum;
uint16_t m_rssiCount;
void stateMachine(bool validSignal, uint8_t length);
void listeningState(bool validSignal);
void kerchunkState(bool validSignal);
void relayingState(bool validSignal);
void relayingWaitState(bool validSignal);
void timeoutState(bool validSignal);
void timeoutWaitState(bool validSignal);
void hangState(bool validSignal);
void stateMachine(bool validRFSignal, bool validExtSignal);
void repeaterSamples(bool cos, q15_t* samples, const uint16_t* rssi, uint8_t length);
void linkSamples(bool cos, q15_t* samples, uint8_t length);
void duplexStateMachine(bool validRFSignal, bool validExtSignal);
void listeningStateDuplex(bool validRFSignal, bool validExtSignal);
void kerchunkRFStateDuplex(bool validSignal);
void relayingRFStateDuplex(bool validSignal);
void relayingRFWaitStateDuplex(bool validSignal);
void timeoutRFStateDuplex(bool validSignal);
void timeoutRFWaitStateDuplex(bool validSignal);
void kerchunkExtStateDuplex(bool validSignal);
void relayingExtStateDuplex(bool validSignal);
void relayingExtWaitStateDuplex(bool validSignal);
void timeoutExtStateDuplex(bool validSignal);
void timeoutExtWaitStateDuplex(bool validSignal);
void hangStateDuplex(bool validRFSignal, bool validExtSignal);
void simplexStateMachine(bool validRFSignal, bool validExtSignal);
void listeningStateSimplex(bool validRFSignal, bool validExtSignal);
void relayingRFStateSimplex(bool validSignal);
void relayingRFWaitStateSimplex(bool validSignal);
void timeoutRFStateSimplex(bool validSignal);
void timeoutRFWaitStateSimplex(bool validSignal);
void relayingExtStateSimplex(bool validSignal);
void relayingExtWaitStateSimplex(bool validSignal);
void timeoutExtStateSimplex(bool validSignal);
void timeoutExtWaitStateSimplex(bool validSignal);
void linkStateMachine(bool validRFSignal, bool validExtSignal);
void clock(uint8_t length);
void sendCallsign();
void beginRelaying();
void insertDelay(uint16_t ms);
void insertSilence(uint16_t ms);
};
#endif
#endif
+6
View File
@@ -17,6 +17,9 @@
*/
#include "Config.h"
#if defined(MODE_FM)
#include "Globals.h"
#include "FMBlanking.h"
@@ -80,3 +83,6 @@ q15_t CFMBlanking::process(q15_t sample)
return sample;
}
#endif
+7 -2
View File
@@ -16,11 +16,13 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "Config.h"
#if defined(MODE_FM)
#if !defined(FMBlanking_H)
#define FMBlanking_H
#include "Config.h"
class CFMBlanking {
public:
CFMBlanking();
@@ -39,3 +41,6 @@ private:
};
#endif
#endif
+29 -20
View File
@@ -17,6 +17,9 @@
*/
#include "Config.h"
#if defined(MODE_FM)
#include "Globals.h"
#include "FMCTCSSRX.h"
@@ -82,15 +85,16 @@ const uint16_t N = 24000U / 4U;
CFMCTCSSRX::CFMCTCSSRX() :
m_coeffDivTwo(0),
m_threshold(0),
m_highThreshold(0),
m_lowThreshold(0),
m_count(0U),
m_q0(0),
m_q1(0),
m_result(CTS_NONE)
m_state(false)
{
}
uint8_t CFMCTCSSRX::setParams(uint8_t frequency, uint8_t threshold)
uint8_t CFMCTCSSRX::setParams(uint8_t frequency, uint8_t highThreshold, uint8_t lowThreshold)
{
m_coeffDivTwo = 0;
@@ -104,14 +108,16 @@ uint8_t CFMCTCSSRX::setParams(uint8_t frequency, uint8_t threshold)
if (m_coeffDivTwo == 0)
return 4U;
m_threshold = q31_t(threshold);
m_highThreshold = q31_t(highThreshold);
m_lowThreshold = q31_t(lowThreshold);
return 0U;
}
CTCSSState CFMCTCSSRX::process(q15_t sample)
bool CFMCTCSSRX::process(q15_t sample)
{
m_result = m_result & (~CTS_READY);
//get more dynamic into the decoder by multiplying the sample by 1.5
q31_t sample31 = q31_t(sample) + (q31_t(sample) >> 1);
q31_t q2 = m_q1;
m_q1 = m_q0;
@@ -122,7 +128,7 @@ CTCSSState CFMCTCSSRX::process(q15_t sample)
q31_t t3 = t2 * 2;
// m_q0 = m_coeffDivTwo * m_q1 * 2 - q2 + sample
m_q0 = t3 - q2 + q31_t(sample);
m_q0 = t3 - q2 + sample31;
m_count++;
if (m_count == N) {
@@ -144,29 +150,32 @@ CTCSSState CFMCTCSSRX::process(q15_t sample)
// value = m_q0 * m_q0 + m_q1 * m_q1 - m_q0 * m_q1 * m_coeffDivTwo * 2
q31_t value = t2 + t4 - t9;
m_result = m_result | CTS_READY;
if (value >= m_threshold)
m_result = m_result | CTS_VALID;
else
m_result = m_result & ~CTS_VALID;
bool previousState = m_state;
q31_t threshold = m_highThreshold;
if (previousState)
threshold = m_lowThreshold;
m_state = value >= threshold;
if (previousState != m_state)
DEBUG4("CTCSS Value / Threshold / Valid", value, threshold, m_state);
m_count = 0U;
m_q0 = 0;
m_q1 = 0;
}
return m_result;
}
CTCSSState CFMCTCSSRX::getState()
{
return m_result;
return m_state;
}
void CFMCTCSSRX::reset()
{
m_q0 = 0;
m_q1 = 0;
m_result = CTS_NONE;
m_count = 0U;
m_state = false;
m_count = 0U;
}
#endif
+15 -39
View File
@@ -16,58 +16,34 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#if !defined(FMCTCSSRX_H)
#define FMCTCSSRX_H
#include "Config.h"
enum CTCSSState
{
CTS_NONE = 0,
CTS_READY = 1,
CTS_VALID = 2,
CTS_READY_VALID = CTS_READY | CTS_VALID
};
#if defined(MODE_FM)
inline CTCSSState operator|(CTCSSState a, CTCSSState b)
{
return static_cast<CTCSSState>(static_cast<uint8_t>(a) | static_cast<uint8_t>(b));
}
inline CTCSSState operator&(CTCSSState a, CTCSSState b)
{
return static_cast<CTCSSState>(static_cast<uint8_t>(a) & static_cast<uint8_t>(b));
}
inline CTCSSState operator~(CTCSSState a)
{
return static_cast<CTCSSState>(~(static_cast<uint8_t>(a)));
}
#define CTCSS_READY(a) ((a & CTS_READY) != 0)
#define CTCSS_NOT_READY(a) ((a & CTS_READY) == 0)
#define CTCSS_VALID(a) ((a & CTS_VALID) != 0)
#define CTCSS_NOT_VALID(a) ((a & CTS_VALID) == 0)
#if !defined(FMCTCSSRX_H)
#define FMCTCSSRX_H
class CFMCTCSSRX {
public:
CFMCTCSSRX();
uint8_t setParams(uint8_t frequency, uint8_t threshold);
uint8_t setParams(uint8_t frequency, uint8_t highThreshold, uint8_t lowThreshold);
CTCSSState process(q15_t samples);
CTCSSState getState();
bool process(q15_t sample);
void reset();
private:
q63_t m_coeffDivTwo;
q31_t m_threshold;
uint16_t m_count;
q31_t m_q0;
q31_t m_q1;
CTCSSState m_result;
q63_t m_coeffDivTwo;
q31_t m_highThreshold;
q31_t m_lowThreshold;
uint16_t m_count;
q31_t m_q0;
q31_t m_q1;
bool m_state;
};
#endif
#endif
+66 -58
View File
@@ -17,65 +17,67 @@
*/
#include "Config.h"
#if defined(MODE_FM)
#include "Globals.h"
#include "FMCTCSSTX.h"
const struct TX_CTCSS_TABLE {
uint8_t frequency;
uint16_t length;
q15_t increment;
q31_t increment;
} TX_CTCSS_TABLE_DATA[] = {
{ 67U, 358U, 92},
{ 69U, 346U, 95},
{ 71U, 334U, 99},
{ 74U, 323U, 102},
{ 77U, 312U, 106},
{ 79U, 301U, 109},
{ 82U, 291U, 113},
{ 85U, 281U, 117},
{ 88U, 271U, 121},
{ 91U, 262U, 125},
{ 94U, 253U, 130},
{ 97U, 246U, 133},
{100U, 240U, 137},
{103U, 232U, 142},
{107U, 224U, 147},
{110U, 216U, 152},
{114U, 209U, 157},
{118U, 202U, 163},
{123U, 195U, 168},
{127U, 189U, 174},
{131U, 182U, 180},
{136U, 176U, 187},
{141U, 170U, 193},
{146U, 164U, 200},
{151U, 159U, 207},
{156U, 153U, 214},
{159U, 150U, 219},
{162U, 148U, 222},
{165U, 145U, 226},
{167U, 143U, 230},
{171U, 140U, 234},
{173U, 138U, 238},
{177U, 135U, 243},
{179U, 133U, 246},
{183U, 131U, 251},
{186U, 129U, 255},
{189U, 126U, 260},
{192U, 124U, 264},
{196U, 122U, 269},
{199U, 120U, 273},
{203U, 118U, 278},
{206U, 116U, 282},
{210U, 114U, 288},
{218U, 110U, 298},
{225U, 106U, 309},
{229U, 105U, 313},
{233U, 103U, 319},
{241U, 99U, 331},
{250U, 96U, 342},
{254U, 94U, 347}
};
{ 67U, 358U, 5995059},
{ 69U, 346U, 6200860},
{ 71U, 334U, 6433504},
{ 74U, 323U, 6657200},
{ 77U, 312U, 6889844},
{ 79U, 301U, 7131436},
{ 82U, 291U, 7381976},
{ 85U, 281U, 7641463},
{ 88U, 271U, 7918846},
{ 91U, 262U, 8187282},
{ 94U, 253U, 8482561},
{ 97U, 246U, 8715205},
{100U, 240U, 8947849},
{103U, 232U, 9261024},
{107U, 224U, 9592094},
{110U, 216U, 9923165},
{114U, 209U, 10272131},
{118U, 202U, 10630045},
{123U, 195U, 11005854},
{127U, 189U, 11390612},
{131U, 182U, 11793265},
{136U, 176U, 12213814},
{141U, 170U, 12643310},
{146U, 164U, 13081755},
{151U, 159U, 13547043},
{156U, 153U, 14021279},
{159U, 150U, 14298662},
{162U, 148U, 14513411},
{165U, 145U, 14808690},
{167U, 143U, 15023438},
{171U, 140U, 15327665},
{173U, 138U, 15551361},
{177U, 135U, 15864536},
{179U, 133U, 16097180},
{183U, 131U, 16419303},
{186U, 129U, 16660894},
{189U, 126U, 16991965},
{192U, 124U, 17251452},
{196U, 122U, 17591471},
{199U, 120U, 17850958},
{203U, 118U, 18208872},
{206U, 116U, 18477308},
{210U, 114U, 18853117},
{218U, 110U, 19515258},
{225U, 106U, 20195295},
{229U, 105U, 20499521},
{233U, 103U, 20902175},
{241U, 99U, 21635898},
{250U, 96U, 22396465},
{254U, 94U, 22736484}};
const uint8_t CTCSS_TABLE_DATA_LEN = 50U;
@@ -105,10 +107,10 @@ uint8_t CFMCTCSSTX::setParams(uint8_t frequency, uint8_t level)
delete[] m_values;
m_values = new q15_t[m_length];
q15_t arg = 0;
q31_t arg = 0;
for (uint16_t i = 0U; i < m_length; i++) {
q31_t value = ::arm_sin_q15(arg) * q15_t(level * 13);
m_values[i] = q15_t(__SSAT((value >> 15), 16));
q63_t value = ::arm_sin_q31(arg) * q63_t(level * 13);
m_values[i] = q15_t(__SSAT((value >> 31), 16));
arg += entry->increment;
}
@@ -116,11 +118,17 @@ uint8_t CFMCTCSSTX::setParams(uint8_t frequency, uint8_t level)
return 0U;
}
q15_t CFMCTCSSTX::getAudio()
q15_t CFMCTCSSTX::getAudio(bool reverse)
{
q15_t sample = m_values[m_n++];
if(m_n >= m_length)
if (m_n >= m_length)
m_n = 0U;
return sample;
if (reverse)
return -sample;
else
return sample;
}
#endif
+8 -3
View File
@@ -16,18 +16,20 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "Config.h"
#if defined(MODE_FM)
#if !defined(FMCTCSSTX_H)
#define FMCTCSSTX_H
#include "Config.h"
class CFMCTCSSTX {
public:
CFMCTCSSTX();
uint8_t setParams(uint8_t frequency, uint8_t level);
q15_t getAudio();
q15_t getAudio(bool reverse);
private:
q15_t* m_values;
@@ -36,3 +38,6 @@ private:
};
#endif
#endif
+9 -2
View File
@@ -29,7 +29,11 @@ THE SOFTWARE.
// based on https://raw.githubusercontent.com/berndporr/iir_fixed_point/master/DirectFormI.h
#include "Globals.h"
#include "Config.h"
#if defined(MODE_FM)
#include <cstdint>
#ifndef DIRECTFORMI_H_
#define DIRECTFORMI_H_
@@ -79,7 +83,7 @@ public:
inline q15_t filter(const q15_t in)
{
// calculate the output
register q31_t out_upscaled = c_b0 * in //F4FXL puting stauration here made everything quiet, not sure why
register q31_t out_upscaled = c_b0 * in
+ c_b1 * m_x1
+ c_b2 * m_x2
- c_a1 * m_y1
@@ -109,3 +113,6 @@ private:
};
#endif /* DIRECTFORMI_H */
#endif
+80
View File
@@ -0,0 +1,80 @@
/*
* Copyright (C) 2020 by Jonathan Naylor G4KLX
* Copyright (C) 2020 by Geoffrey Merck F4FXL - KC3FRA
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "Config.h"
#if defined(MODE_FM)
#include "FMDownSampler.h"
CFMDownSampler::CFMDownSampler(uint16_t length) :
m_ringBuffer(length),
m_samplePack(0U),
m_samplePackPointer(NULL),
m_sampleIndex(0U)
{
m_samplePackPointer = (uint8_t*)&m_samplePack;
}
void CFMDownSampler::addSample(q15_t sample)
{
uint32_t usample = uint32_t(int32_t(sample) + 2048);
//only take one of three samples
switch(m_sampleIndex){
case 0:
m_samplePack = usample << 12;
break;
case 3:{
m_samplePack |= usample;
//we did not use MSB; skip it
TSamplePairPack pair{m_samplePackPointer[0U], m_samplePackPointer[1U], m_samplePackPointer[2U]};
m_ringBuffer.put(pair);
m_samplePack = 0U;//reset the sample pack
}
break;
default:
//Just skip this sample
break;
}
m_sampleIndex++;
if (m_sampleIndex >= 6U)//did we pack two samples ?
m_sampleIndex = 0U;
}
bool CFMDownSampler::getPackedData(TSamplePairPack& data)
{
return m_ringBuffer.get(data);
}
uint16_t CFMDownSampler::getData()
{
return m_ringBuffer.getData();
}
void CFMDownSampler::reset()
{
m_sampleIndex = 0U;
}
#endif
+52
View File
@@ -0,0 +1,52 @@
/*
* Copyright (C) 2020 by Jonathan Naylor G4KLX
* Copyright (C) 2020 by Geoffrey Merck F4FXL - KC3FRA
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "Config.h"
#if defined(MODE_FM)
#if !defined(FMDOWNSAMPLER_H)
#define FMDOWNSAMPLER_H
#include "RingBuffer.h"
#include "FMSamplePairPack.h"
class CFMDownSampler {
public:
CFMDownSampler(uint16_t length);
void addSample(q15_t sample);
bool getPackedData(TSamplePairPack& data);
uint16_t getData();
void reset();
private:
CRingBuffer<TSamplePairPack> m_ringBuffer;
uint32_t m_samplePack;
uint8_t* m_samplePackPointer;
uint8_t m_sampleIndex;
};
#endif
#endif
+12
View File
@@ -17,6 +17,9 @@
*/
#include "Config.h"
#if defined(MODE_FM)
#include "Globals.h"
#include "FMKeyer.h"
@@ -66,6 +69,7 @@ const struct {
{',', 0xEEAEE000U, 22U},
{'-', 0xEAAE0000U, 18U},
{'=', 0xEAB80000U, 16U},
{'.', 0xBAEB8000U, 20U},
{' ', 0x00000000U, 4U},
{0U, 0x00000000U, 0U}
};
@@ -204,7 +208,15 @@ void CFMKeyer::stop()
m_audioPos = 0U;
}
bool CFMKeyer::isWanted() const
{
return m_wanted;
}
bool CFMKeyer::isRunning() const
{
return m_poPos > 0U || m_dotPos > 0U || m_audioPos > 0U;
}
#endif
+9 -2
View File
@@ -16,11 +16,13 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "Config.h"
#if defined(MODE_FM)
#if !defined(FMKeyer_H)
#define FMKeyer_H
#include "Config.h"
class CFMKeyer {
public:
CFMKeyer();
@@ -35,6 +37,8 @@ public:
bool isRunning() const;
bool isWanted() const;
private:
bool m_wanted;
uint8_t m_poBuffer[1000U];
@@ -50,3 +54,6 @@ private:
};
#endif
#endif
+133
View File
@@ -0,0 +1,133 @@
/*
* Copyright (C) 2020 by Jonathan Naylor G4KLX
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "Config.h"
#if defined(MODE_FM)
#include "Globals.h"
#include "FMNoiseSquelch.h"
// 4500Hz centre frequency
const q31_t COEFF_DIV_TWO = 821806413;
// 400Hz bandwidth
const uint16_t N = 24000U / 400U;
CFMNoiseSquelch::CFMNoiseSquelch() :
m_highThreshold(0),
m_lowThreshold(0),
m_count(0U),
m_q0(0),
m_q1(0),
m_state(false),
m_validCount(0U)
{
}
void CFMNoiseSquelch::setParams(uint8_t highThreshold, uint8_t lowThreshold)
{
m_highThreshold = q31_t(highThreshold);
m_lowThreshold = q31_t(lowThreshold);
}
bool CFMNoiseSquelch::process(q15_t sample)
{
//get more dynamic into the decoder by multiplying the sample by 64
q31_t sample31 = q31_t(sample) << 6; //+ (q31_t(sample) >> 1);
q31_t q2 = m_q1;
m_q1 = m_q0;
// Q31 multiplication, t3 = m_coeffDivTwo * 2 * m_q1
q63_t t1 = COEFF_DIV_TWO * m_q1;
q31_t t2 = __SSAT((t1 >> 31), 31);
q31_t t3 = t2 * 2;
// m_q0 = m_coeffDivTwo * m_q1 * 2 - q2 + sample
m_q0 = t3 - q2 + sample31;
m_count++;
if (m_count == N) {
// Q31 multiplication, t2 = m_q0 * m_q0
q63_t t1 = q63_t(m_q0) * q63_t(m_q0);
q31_t t2 = __SSAT((t1 >> 31), 31);
// Q31 multiplication, t4 = m_q0 * m_q0
q63_t t3 = q63_t(m_q1) * q63_t(m_q1);
q31_t t4 = __SSAT((t3 >> 31), 31);
// Q31 multiplication, t9 = m_q0 * m_q1 * m_coeffDivTwo * 2
q63_t t5 = q63_t(m_q0) * q63_t(m_q1);
q31_t t6 = __SSAT((t5 >> 31), 31);
q63_t t7 = t6 * COEFF_DIV_TWO;
q31_t t8 = __SSAT((t7 >> 31), 31);
q31_t t9 = t8 * 2;
// value = m_q0 * m_q0 + m_q1 * m_q1 - m_q0 * m_q1 * m_coeffDivTwo * 2
q31_t value = t2 + t4 - t9;
bool previousState = m_state;
q31_t threshold = m_highThreshold;
if (previousState)
threshold = m_lowThreshold;
if (!m_state) {
if (value < threshold)
m_validCount++;
else
m_validCount = 0U;
}
if (m_state) {
if (value >= threshold)
m_invalidCount++;
else
m_invalidCount = 0U;
}
m_state = m_validCount >= 10U && m_invalidCount < 10U;
if(previousState && !m_state)
m_invalidCount = 0U;
if (previousState != m_state) {
DEBUG4("Noise Squelch Value / Threshold / Valid", value, threshold, m_state);
DEBUG3("Valid Count / Invalid Count", m_validCount, m_invalidCount);
}
m_count = 0U;
m_q0 = 0;
m_q1 = 0;
}
return m_state;
}
void CFMNoiseSquelch::reset()
{
m_q0 = 0;
m_q1 = 0;
m_state = false;
m_count = 0U;
}
#endif
+50
View File
@@ -0,0 +1,50 @@
/*
* Copyright (C) 2020 by Jonathan Naylor G4KLX
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "Config.h"
#if defined(MODE_FM)
#if !defined(FMNOISESQUELCH_H)
#define FMNOISESQUELCH_H
class CFMNoiseSquelch {
public:
CFMNoiseSquelch();
void setParams(uint8_t highThreshold, uint8_t lowThreshold);
bool process(q15_t sample);
void reset();
private:
q31_t m_highThreshold;
q31_t m_lowThreshold;
uint16_t m_count;
q31_t m_q0;
q31_t m_q1;
bool m_state;
uint8_t m_validCount;
uint8_t m_invalidCount;
};
#endif
#endif
+36
View File
@@ -0,0 +1,36 @@
/*
* Copyright (C) 2020 by Jonathan Naylor G4KLX
* Copyright (C) 2020 by Geoffrey Merck F4FXL - KC3FRA
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "Config.h"
#if defined(MODE_FM)
#if !defined(TSAMPLEPACK_H)
#define TSAMPLEPACK_H
struct TSamplePairPack {
uint8_t byte0;
uint8_t byte1;
uint8_t byte2;
};
#endif
#endif
+11 -7
View File
@@ -17,6 +17,9 @@
*/
#include "Config.h"
#if defined(MODE_FM)
#include "Globals.h"
#include "FMTimeout.h"
@@ -36,24 +39,22 @@ m_n(0U)
void CFMTimeout::setParams(uint8_t level)
{
m_level = q15_t(level * 128);
m_level = q15_t(level * 5);
}
q15_t CFMTimeout::getAudio()
{
q15_t sample = 0U;
q15_t sample = 0;
if (!m_running)
return sample;
if (m_pos > 12000U) {
q31_t sample = BUSY_AUDIO[m_n] * m_level;
sample = q15_t(__SSAT((sample >> 15), 16));
if (m_pos >= 12000U) {
q31_t sample31 = BUSY_AUDIO[m_n] * m_level;
sample = q15_t(__SSAT((sample31 >> 15), 16));
m_n++;
if (m_n >= BUSY_AUDIO_LEN)
m_n = 0U;
} else {
sample = 0U;
}
m_pos++;
@@ -74,3 +75,6 @@ void CFMTimeout::stop()
{
m_running = false;
}
#endif
+7 -2
View File
@@ -16,11 +16,13 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "Config.h"
#if defined(MODE_FM)
#if !defined(FMTimeout_H)
#define FMTimeout_H
#include "Config.h"
class CFMTimeout {
public:
CFMTimeout();
@@ -40,3 +42,6 @@ private:
};
#endif
#endif
+6
View File
@@ -17,6 +17,9 @@
*/
#include "Config.h"
#if defined(MODE_FM)
#include "Globals.h"
#include "FMTimer.h"
@@ -68,3 +71,6 @@ bool CFMTimer::hasExpired() const
return false;
}
#endif
+7 -2
View File
@@ -16,11 +16,13 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "Config.h"
#if defined(MODE_FM)
#if !defined(FMTimer_H)
#define FMTimer_H
#include "Config.h"
class CFMTimer {
public:
CFMTimer();
@@ -45,3 +47,6 @@ private:
};
#endif
#endif
+104
View File
@@ -0,0 +1,104 @@
/*
* Copyright (C) 2020 by Jonathan Naylor G4KLX
* Copyright (C) 2020 by Geoffrey Merck F4FXL - KC3FRA
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "Config.h"
#if defined(MODE_FM)
#include "FMUpSampler.h"
const uint32_t FM_UPSAMPLE_MASK = 0x00000FFFU;
CFMUpSampler::CFMUpSampler() :
m_upSampleIndex(0),
m_pack(0U),
m_packPointer(NULL),
m_samples(3600U), //300ms of 12 bit 8kHz audio
m_running(false)
{
m_packPointer = (uint8_t*)&m_pack;
}
void CFMUpSampler::reset()
{
m_upSampleIndex = 0U;
m_pack = 0U;
m_samples.reset();
m_running = false;
}
void CFMUpSampler::addData(const uint8_t* data, uint16_t length)
{
TSamplePairPack* packPointer = (TSamplePairPack*)data;
TSamplePairPack* packPointerEnd = packPointer + (length / 3U);
while(packPointer != packPointerEnd) {
m_samples.put(*packPointer);
packPointer++;
}
if(!m_running)
m_running = m_samples.getData() > 300U;//75ms of audio
}
bool CFMUpSampler::getSample(q15_t& sample)
{
if(!m_running)
return false;
switch (m_upSampleIndex)
{
case 0: {
TSamplePairPack pairPack;
if(!m_samples.get(pairPack)) {
m_running = false;
return false;
}
m_pack = 0U;
m_packPointer = (uint8_t*)&m_pack;
m_packPointer[0U] = pairPack.byte0;
m_packPointer[1U] = pairPack.byte1;
m_packPointer[2U] = pairPack.byte2;
sample = q15_t(m_pack >> 12) - 2048;
break;
}
case 3:
sample = q15_t(m_pack & FM_UPSAMPLE_MASK) - 2048;
break;
default:
sample = 0;
break;
}
m_upSampleIndex++;
if(m_upSampleIndex >= 6U)
m_upSampleIndex = 0U;
return true;
}
uint16_t CFMUpSampler::getSpace() const
{
//return available space in bytes
return m_samples.getSpace() * sizeof(TSamplePairPack);
}
#endif
+54
View File
@@ -0,0 +1,54 @@
/*
* Copyright (C) 2020 by Jonathan Naylor G4KLX
* Copyright (C) 2020 by Geoffrey Merck F4FXL - KC3FRA
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "Config.h"
#if defined(MODE_FM)
#if !defined(FMUPSAMPLER_H)
#define FMUPSAMPLER_H
#include "RingBuffer.h"
#include "FMSamplePairPack.h"
class CFMUpSampler {
public:
CFMUpSampler();
void reset();
void addData(const uint8_t* data, uint16_t length);
bool getSample(q15_t& sample);
uint16_t getSpace() const;
private:
uint8_t m_upSampleIndex;
uint32_t m_pack;
uint8_t * m_packPointer;
CRingBuffer<TSamplePairPack> m_samples;
bool m_running;
};
#endif
#endif
+62 -17
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2015,2016,2017,2018,2020 by Jonathan Naylor G4KLX
* Copyright (C) 2015,2016,2017,2018,2020,2021,2023 by Jonathan Naylor G4KLX
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -23,16 +23,12 @@
#include "stm32f4xx.h"
#elif defined(STM32F7XX)
#include "stm32f7xx.h"
#elif defined(STM32F105xC)
#include "stm32f1xx.h"
#include "STM32Utils.h"
#else
#include <Arduino.h>
#undef PI //Undefine PI to get rid of annoying warning as it is also defined in arm_math.h.
#endif
#if defined(__SAM3X8E__) || defined(STM32F105xC)
#define ARM_MATH_CM3
#elif defined(STM32F7XX)
#if defined(STM32F7XX)
#define ARM_MATH_CM7
#elif defined(STM32F4XX) || defined(__MK20DX256__) || defined(__MK64FX512__) || defined(__MK66FX1M0__)
#define ARM_MATH_CM4
@@ -50,7 +46,9 @@ enum MMDVM_STATE {
STATE_P25 = 4,
STATE_NXDN = 5,
STATE_POCSAG = 6,
STATE_M17 = 7,
STATE_FM = 10,
STATE_AX25 = 11,
// Dummy states start at 90
STATE_NXDNCAL1K = 91,
@@ -63,7 +61,14 @@ enum MMDVM_STATE {
STATE_DMRCAL = 98,
STATE_DSTARCAL = 99,
STATE_INTCAL = 100,
STATE_POCSAGCAL = 101
STATE_POCSAGCAL = 101,
STATE_FMCAL10K = 102,
STATE_FMCAL12K = 103,
STATE_FMCAL15K = 104,
STATE_FMCAL20K = 105,
STATE_FMCAL25K = 106,
STATE_FMCAL30K = 107,
STATE_M17CAL = 108
};
#include "SerialPort.h"
@@ -78,17 +83,23 @@ enum MMDVM_STATE {
#include "YSFTX.h"
#include "P25RX.h"
#include "P25TX.h"
#include "M17RX.h"
#include "M17TX.h"
#include "NXDNRX.h"
#include "NXDNTX.h"
#include "POCSAGTX.h"
#include "CalDStarRX.h"
#include "CalDStarTX.h"
#include "CalFM.h"
#include "CalDMR.h"
#include "CalP25.h"
#include "CalNXDN.h"
#include "CalPOCSAG.h"
#include "CalRSSI.h"
#include "CWIdTX.h"
#include "AX25RX.h"
#include "AX25TX.h"
#include "CalM17.h"
#include "Debug.h"
#include "IO.h"
#include "FM.h"
@@ -116,7 +127,9 @@ extern bool m_ysfEnable;
extern bool m_p25Enable;
extern bool m_nxdnEnable;
extern bool m_pocsagEnable;
extern bool m_m17Enable;
extern bool m_fmEnable;
extern bool m_ax25Enable;
extern bool m_duplex;
@@ -126,9 +139,15 @@ extern bool m_dcd;
extern CSerialPort serial;
extern CIO io;
#if defined(MODE_DSTAR)
extern CDStarRX dstarRX;
extern CDStarTX dstarTX;
extern CCalDStarRX calDStarRX;
extern CCalDStarTX calDStarTX;
#endif
#if defined(MODE_DMR)
extern CDMRIdleRX dmrIdleRX;
extern CDMRRX dmrRX;
extern CDMRTX dmrTX;
@@ -136,27 +155,53 @@ extern CDMRTX dmrTX;
extern CDMRDMORX dmrDMORX;
extern CDMRDMOTX dmrDMOTX;
extern CCalDMR calDMR;
#endif
#if defined(MODE_YSF)
extern CYSFRX ysfRX;
extern CYSFTX ysfTX;
#endif
#if defined(MODE_P25)
extern CP25RX p25RX;
extern CP25TX p25TX;
extern CCalP25 calP25;
#endif
#if defined(MODE_NXDN)
extern CNXDNRX nxdnRX;
extern CNXDNTX nxdnTX;
extern CPOCSAGTX pocsagTX;
extern CCalNXDN calNXDN;
#endif
extern CFM fm;
#if defined(MODE_POCSAG)
extern CPOCSAGTX pocsagTX;
extern CCalPOCSAG calPOCSAG;
#endif
extern CCalDStarRX calDStarRX;
extern CCalDStarTX calDStarTX;
extern CCalDMR calDMR;
extern CCalP25 calP25;
extern CCalNXDN calNXDN;
extern CCalPOCSAG calPOCSAG;
extern CCalRSSI calRSSI;
#if defined(MODE_M17)
extern CM17RX m17RX;
extern CM17TX m17TX;
extern CCalM17 calM17;
#endif
#if defined(MODE_FM)
extern CFM fm;
extern CCalFM calFM;
#endif
#if defined(MODE_AX25)
extern CAX25RX ax25RX;
extern CAX25TX ax25TX;
#endif
extern CCalRSSI calRSSI;
extern CCWIdTX cwIdTX;
#endif
-235
View File
@@ -1,235 +0,0 @@
/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* 28-4-2017 Created for MMDVM Pi shield for Teensy by Chris Huitema
*/
#include "Config.h"
#include "Globals.h"
#if defined(VK6MST_TEENSY_PI3_SHIELD_I2C)
#include <i2c_t3.h> //available here https://github.com/nox771/i2c_t3 or maybe the normal wire will work #include <wire.h> justs need to test i guess
#define I2C_ADDRESS 0x22
#define I2C_SPEED 100000
// Function prototypes
void receiveEvent(size_t count);
void requestEvent(void);
#define TX_FIFO_SIZE 512U
#define RX_FIFO_SIZE 512U
volatile uint8_t TXfifo[TX_FIFO_SIZE];
volatile uint8_t RXfifo[RX_FIFO_SIZE];
volatile uint16_t TXfifohead, TXfifotail;
volatile uint16_t RXfifohead, RXfifotail;
// Init queues
void TXfifoinit(void)
{
TXfifohead = 0U;
TXfifotail = 0U;
}
void RXfifoinit()
{
RXfifohead = 0U;
RXfifotail = 0U;
}
// How full is queue
uint16_t TXfifolevel(void)
{
uint32_t tail = TXfifotail;
uint32_t head = TXfifohead;
if (tail > head)
return TX_FIFO_SIZE + head - tail;
else
return head - tail;
}
uint16_t RXfifolevel(void)
{
uint32_t tail = RXfifotail;
uint32_t head = RXfifohead;
if (tail > head)
return RX_FIFO_SIZE + head - tail;
else
return head - tail;
}
uint8_t TXfifoput(uint8_t next)
{
if (TXfifolevel() < TX_FIFO_SIZE) {
TXfifo[TXfifohead] = next;
TXfifohead++;
if (TXfifohead >= TX_FIFO_SIZE)
TXfifohead = 0U;
return 1U;
} else {
return 0U; // signal an overflow occurred by returning a zero count
}
}
void I2Cbegin(void)
{
// Setup for Slave mode, address 0x22, pins 18/19, external pullups, speed in hz
Wire.begin(I2C_SLAVE, I2C_ADDRESS, I2C_PINS_18_19, I2C_PULLUP_EXT, I2C_SPEED);
// register events
Wire.onReceive(receiveEvent);
Wire.onRequest(requestEvent);
// initialize the fifos
TXfifoinit();
RXfifoinit();
}
int I2Cavailable(void)
{
if (RXfifolevel() > 0U)
return 1U;
else
return 0U;
}
uint8_t I2Cread(void)
{
uint8_t data_c = RXfifo[RXfifotail];
RXfifotail++;
if (RXfifotail >= RX_FIFO_SIZE)
RXfifotail = 0U;
return data_c;
}
void I2Cwrite(const uint8_t* data, uint16_t length)
{
for (uint16_t i = 0U; i < length; i++)
TXfifoput(data[i]); //puts it in the fifo
}
//
// handle Rx Event (incoming I2C data)
//
void receiveEvent(size_t count)
{
for (uint16_t i = 0U; i < count; i++)
{
if (RXfifolevel() < RX_FIFO_SIZE) {
RXfifo[RXfifohead] = Wire.readByte();
if (RXfifo[RXfifohead] != -1){
RXfifohead++;
if (RXfifohead >= RX_FIFO_SIZE) RXfifohead = 0U;
}
} else {
Wire.readByte(); // drop data if mem full.
}
}
}
//
// handle Tx Event (outgoing I2C data)
//
void requestEvent(void)
{
if (TXfifolevel() > 0) {
if (Wire.write(TXfifo[TXfifotail])){ //write to i2c
TXfifotail++;
if (TXfifotail >= TX_FIFO_SIZE) TXfifotail = 0U;
}
}
}
/************************************/
void CSerialPort::beginInt(uint8_t n, int speed)
{
switch (n) {
case 1U:
return I2Cbegin();
case 3U:
Serial3.begin(speed);
break;
default:
break;
}
}
int CSerialPort::availableInt(uint8_t n)
{
switch (n) {
case 1U:
return I2Cavailable();
case 3U:
return Serial3.available();
default:
return false;
}
}
int CSerialPort::availableForWriteInt(uint8_t n)
{
switch (n) {
case 3U:
return Serial3.availableForWrite();
default:
return false;
}
}
uint8_t CSerialPort::readInt(uint8_t n)
{
switch (n) {
case 1U:
return I2Cread();
case 3U:
return Serial3.read();
default:
return 0U;
}
}
void CSerialPort::writeInt(uint8_t n, const uint8_t* data, uint16_t length, bool flush)
{
switch (n) {
case 1U:
I2Cwrite(data, length);
break;
case 3U:
Serial3.write(data, length);
if (flush)
Serial3.flush();
break;
default:
break;
}
}
#endif
+334 -82
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2015,2016,2017,2018,2020 by Jonathan Naylor G4KLX
* Copyright (C) 2015,2016,2017,2018,2020,2021,2023 by Jonathan Naylor G4KLX
* Copyright (C) 2015 by Jim Mclaughlin KI6ZUM
* Copyright (C) 2016 by Colin Durbridge G4EML
*
@@ -22,16 +22,34 @@
#include "Globals.h"
#include "IO.h"
#if defined(USE_DCBLOCKER)
// Generated using [b, a] = butter(1, 0.001) in MATLAB
static q31_t DC_FILTER[] = {3367972, 0, 3367972, 0, 2140747704, 0}; // {b0, 0, b1, b2, -a1, -a2}
const uint32_t DC_FILTER_STAGES = 1U; // One Biquad stage
#endif
#if defined(MODE_DMR) || defined(MODE_YSF)
// Generated using rcosdesign(0.2, 8, 5, 'sqrt') in MATLAB
static q15_t RRC_0_2_FILTER[] = {401, 104, -340, -731, -847, -553, 112, 909, 1472, 1450, 683, -675, -2144, -3040, -2706, -770, 2667, 6995,
11237, 14331, 15464, 14331, 11237, 6995, 2667, -770, -2706, -3040, -2144, -675, 683, 1450, 1472, 909, 112,
-553, -847, -731, -340, 104, 401, 0};
const uint16_t RRC_0_2_FILTER_LEN = 42U;
#endif
#if defined(MODE_M17)
// Generated using rcosdesign(0.5, 8, 5, 'sqrt') in MATLAB
static q15_t RRC_0_5_FILTER[] = {-147, -88, 72, 220, 223, 46, -197, -285, -79, 334, 623, 390, -498, -1691, -2363, -1556, 1284, 5872, 11033,
15109, 16656, 15109, 11033, 5872, 1284, -1556, -2363, -1691, -498, 390, 623, 334, -79, -285, -197, 46, 223,
220, 72, -88, -147, 0};
const uint16_t RRC_0_5_FILTER_LEN = 42U;
#endif
#if defined(MODE_NXDN)
#if defined(USE_NXDN_BOXCAR)
// One symbol boxcar filter
static q15_t BOXCAR10_FILTER[] = {6000, 6000, 6000, 6000, 6000, 6000, 6000, 6000, 6000, 6000};
const uint16_t BOXCAR10_FILTER_LEN = 10U;
#else
// Generated using rcosdesign(0.2, 8, 10, 'sqrt') in MATLAB
static q15_t NXDN_0_2_FILTER[] = {284, 198, 73, -78, -240, -393, -517, -590, -599, -533, -391, -181, 79, 364, 643, 880, 1041, 1097, 1026, 819,
483, 39, -477, -1016, -1516, -1915, -2150, -2164, -1914, -1375, -545, 557, 1886, 3376, 4946, 6502, 7946, 9184,
@@ -43,14 +61,20 @@ const uint16_t NXDN_0_2_FILTER_LEN = 82U;
static q15_t NXDN_ISINC_FILTER[] = {790, -1085, -1073, -553, 747, 2341, 3156, 2152, -893, -4915, -7834, -7536, -3102, 4441, 12354, 17394, 17394,
12354, 4441, -3102, -7536, -7834, -4915, -893, 2152, 3156, 2341, 747, -553, -1073, -1085, 790};
const uint16_t NXDN_ISINC_FILTER_LEN = 32U;
#endif
#endif
#if defined(MODE_DSTAR)
// Generated using gaussfir(0.5, 4, 5) in MATLAB
static q15_t GAUSSIAN_0_5_FILTER[] = {8, 104, 760, 3158, 7421, 9866, 7421, 3158, 760, 104, 8, 0};
const uint16_t GAUSSIAN_0_5_FILTER_LEN = 12U;
#endif
#if defined(MODE_P25)
// One symbol boxcar filter
static q15_t BOXCAR_FILTER[] = {12000, 12000, 12000, 12000, 12000, 0};
const uint16_t BOXCAR_FILTER_LEN = 6U;
static q15_t BOXCAR5_FILTER[] = {12000, 12000, 12000, 12000, 12000, 0};
const uint16_t BOXCAR5_FILTER_LEN = 6U;
#endif
const uint16_t DC_OFFSET = 2048U;
@@ -59,18 +83,41 @@ m_started(false),
m_rxBuffer(RX_RINGBUFFER_SIZE),
m_txBuffer(TX_RINGBUFFER_SIZE),
m_rssiBuffer(RX_RINGBUFFER_SIZE),
#if defined(USE_DCBLOCKER)
m_dcFilter(),
m_dcState(),
m_rrcFilter(),
#endif
#if defined(MODE_DSTAR)
m_gaussianFilter(),
m_boxcarFilter(),
m_gaussianState(),
#endif
#if defined(MODE_DMR)
m_rrc02Filter1(),
m_rrc02State1(),
#endif
#if defined(MODE_YSF)
m_rrc02Filter2(),
m_rrc02State2(),
#endif
#if defined(MODE_P25)
m_boxcar5Filter(),
m_boxcar5State(),
#endif
#if defined(MODE_NXDN)
#if defined(USE_NXDN_BOXCAR)
m_boxcar10Filter(),
m_boxcar10State(),
#else
m_nxdnFilter(),
m_nxdnISincFilter(),
m_rrcState(),
m_gaussianState(),
m_boxcarState(),
m_nxdnState(),
m_nxdnISincState(),
#endif
#endif
#if defined(MODE_M17)
m_rrc05Filter(),
m_rrc05State(),
#endif
m_pttInvert(false),
m_rxLevel(128 * 128),
m_cwIdTXLevel(128 * 128),
@@ -79,10 +126,13 @@ m_dmrTXLevel(128 * 128),
m_ysfTXLevel(128 * 128),
m_p25TXLevel(128 * 128),
m_nxdnTXLevel(128 * 128),
m_m17TXLevel(128 * 128),
m_pocsagTXLevel(128 * 128),
m_fmTXLevel(128 * 128),
m_ax25TXLevel(128 * 128),
m_rxDCOffset(DC_OFFSET),
m_txDCOffset(DC_OFFSET),
m_useCOSAsLockout(false),
m_ledCount(0U),
m_ledValue(true),
m_detect(false),
@@ -91,29 +141,51 @@ m_dacOverflow(0U),
m_watchdog(0U),
m_lockout(false)
{
::memset(m_rrcState, 0x00U, 70U * sizeof(q15_t));
::memset(m_gaussianState, 0x00U, 40U * sizeof(q15_t));
::memset(m_boxcarState, 0x00U, 30U * sizeof(q15_t));
::memset(m_nxdnState, 0x00U, 110U * sizeof(q15_t));
::memset(m_nxdnISincState, 0x00U, 60U * sizeof(q15_t));
::memset(m_dcState, 0x00U, 4U * sizeof(q31_t));
#if defined(USE_DCBLOCKER)
::memset(m_dcState, 0x00U, 4U * sizeof(q31_t));
m_dcFilter.numStages = DC_FILTER_STAGES;
m_dcFilter.pState = m_dcState;
m_dcFilter.pCoeffs = DC_FILTER;
m_dcFilter.postShift = 0;
#endif
m_rrcFilter.numTaps = RRC_0_2_FILTER_LEN;
m_rrcFilter.pState = m_rrcState;
m_rrcFilter.pCoeffs = RRC_0_2_FILTER;
#if defined(MODE_DSTAR)
::memset(m_gaussianState, 0x00U, 40U * sizeof(q15_t));
m_gaussianFilter.numTaps = GAUSSIAN_0_5_FILTER_LEN;
m_gaussianFilter.pState = m_gaussianState;
m_gaussianFilter.pCoeffs = GAUSSIAN_0_5_FILTER;
#endif
m_boxcarFilter.numTaps = BOXCAR_FILTER_LEN;
m_boxcarFilter.pState = m_boxcarState;
m_boxcarFilter.pCoeffs = BOXCAR_FILTER;
#if defined(MODE_DMR)
::memset(m_rrc02State1, 0x00U, 70U * sizeof(q15_t));
m_rrc02Filter1.numTaps = RRC_0_2_FILTER_LEN;
m_rrc02Filter1.pState = m_rrc02State1;
m_rrc02Filter1.pCoeffs = RRC_0_2_FILTER;
#endif
#if defined(MODE_YSF)
::memset(m_rrc02State2, 0x00U, 70U * sizeof(q15_t));
m_rrc02Filter2.numTaps = RRC_0_2_FILTER_LEN;
m_rrc02Filter2.pState = m_rrc02State2;
m_rrc02Filter2.pCoeffs = RRC_0_2_FILTER;
#endif
#if defined(MODE_P25)
::memset(m_boxcar5State, 0x00U, 30U * sizeof(q15_t));
m_boxcar5Filter.numTaps = BOXCAR5_FILTER_LEN;
m_boxcar5Filter.pState = m_boxcar5State;
m_boxcar5Filter.pCoeffs = BOXCAR5_FILTER;
#endif
#if defined(MODE_NXDN)
#if defined(USE_NXDN_BOXCAR)
::memset(m_boxcar10State, 0x00U, 40U * sizeof(q15_t));
m_boxcar10Filter.numTaps = BOXCAR10_FILTER_LEN;
m_boxcar10Filter.pState = m_boxcar10State;
m_boxcar10Filter.pCoeffs = BOXCAR10_FILTER;
#else
::memset(m_nxdnState, 0x00U, 110U * sizeof(q15_t));
::memset(m_nxdnISincState, 0x00U, 60U * sizeof(q15_t));
m_nxdnFilter.numTaps = NXDN_0_2_FILTER_LEN;
m_nxdnFilter.pState = m_nxdnState;
@@ -122,6 +194,15 @@ m_lockout(false)
m_nxdnISincFilter.numTaps = NXDN_ISINC_FILTER_LEN;
m_nxdnISincFilter.pState = m_nxdnISincState;
m_nxdnISincFilter.pCoeffs = NXDN_ISINC_FILTER;
#endif
#endif
#if defined(MODE_M17)
::memset(m_rrc05State, 0x00U, 70U * sizeof(q15_t));
m_rrc05Filter.numTaps = RRC_0_5_FILTER_LEN;
m_rrc05Filter.pState = m_rrc05State;
m_rrc05Filter.pCoeffs = RRC_0_5_FILTER;
#endif
initInt();
@@ -132,7 +213,7 @@ void CIO::selfTest()
{
bool ledValue = false;
for (uint8_t i = 0; i < 6; i++) {
for (uint8_t i = 0U; i < 6U; i++) {
ledValue = !ledValue;
// We exclude PTT to avoid trigger the transmitter
@@ -143,21 +224,40 @@ void CIO::selfTest()
setDMRInt(ledValue);
setYSFInt(ledValue);
setP25Int(ledValue);
#if !defined(USE_ALTERNATE_NXDN_LEDS)
setNXDNInt(ledValue);
#endif
#if !defined(USE_ALTERNATE_M17_LEDS)
setM17Int(ledValue);
#endif
#if !defined(USE_ALTERNATE_POCSAG_LEDS)
setPOCSAGInt(ledValue);
#endif
#if !defined(USE_ALTERNATE_FM_LEDS)
setFMInt(ledValue);
#endif
#endif
delayInt(250);
}
#if defined(MODE_LEDS)
setDStarInt(true);
setDStarInt(false);
setDMRInt(false);
setYSFInt(false);
setP25Int(false);
#if !defined(USE_ALTERNATE_NXDN_LEDS)
setNXDNInt(false);
#endif
#if !defined(USE_ALTERNATE_M17_LEDS)
setM17Int(false);
#endif
#if !defined(USE_ALTERNATE_POCSAG_LEDS)
setPOCSAGInt(false);
#endif
#if !defined(USE_ALTERNATE_FM_LEDS)
setFMInt(false);
#endif
setDStarInt(true);
delayInt(250);
setDMRInt(true);
@@ -173,6 +273,11 @@ void CIO::selfTest()
setNXDNInt(true);
#endif
#if !defined(USE_ALTERNATE_M17_LEDS)
delayInt(250);
setM17Int(true);
#endif
#if !defined(USE_ALTERNATE_POCSAG_LEDS)
delayInt(250);
setPOCSAGInt(true);
@@ -191,6 +296,11 @@ void CIO::selfTest()
setPOCSAGInt(false);
#endif
#if !defined(USE_ALTERNATE_M17_LEDS)
delayInt(250);
setM17Int(false);
#endif
#if !defined(USE_ALTERNATE_NXDN_LEDS)
delayInt(250);
setNXDNInt(false);
@@ -219,7 +329,7 @@ void CIO::start()
m_started = true;
setMode();
setMode(STATE_IDLE);
}
void CIO::process()
@@ -228,11 +338,12 @@ void CIO::process()
if (m_started) {
// Two seconds timeout
if (m_watchdog >= 48000U) {
if (m_modemState == STATE_DSTAR || m_modemState == STATE_DMR || m_modemState == STATE_YSF || m_modemState == STATE_P25 || m_modemState == STATE_NXDN || m_modemState == STATE_POCSAG) {
if (m_modemState == STATE_DSTAR || m_modemState == STATE_DMR || m_modemState == STATE_YSF || m_modemState == STATE_P25 || m_modemState == STATE_NXDN || m_modemState == STATE_M17 || m_modemState == STATE_POCSAG) {
#if defined(MODE_DMR)
if (m_modemState == STATE_DMR && m_tx)
dmrTX.setStart(false);
m_modemState = STATE_IDLE;
setMode();
#endif
setMode(STATE_IDLE);
}
m_watchdog = 0U;
@@ -256,14 +367,14 @@ void CIO::process()
return;
}
#if defined(USE_COS_AS_LOCKOUT)
m_lockout = getCOSInt();
#endif
if (m_useCOSAsLockout)
m_lockout = getCOSInt();
// Switch off the transmitter if needed
if (m_txBuffer.getData() == 0U && m_tx) {
m_tx = false;
setPTTInt(m_pttInvert ? true : false);
DEBUG1("TX OFF");
}
if (m_rxBuffer.getData() >= RX_BLOCK_SIZE) {
@@ -272,15 +383,16 @@ void CIO::process()
uint16_t rssi[RX_BLOCK_SIZE];
for (uint16_t i = 0U; i < RX_BLOCK_SIZE; i++) {
uint16_t sample;
m_rxBuffer.get(sample, control[i]);
TSample sample;
m_rxBuffer.get(sample);
control[i] = sample.control;
m_rssiBuffer.get(rssi[i]);
// Detect ADC overflow
if (m_detect && (sample == 0U || sample == 4095U))
if (m_detect && (sample.sample == 0U || sample.sample == 4095U))
m_adcOverflow++;
q15_t res1 = q15_t(sample) - m_rxDCOffset;
q15_t res1 = q15_t(sample.sample) - m_rxDCOffset;
q31_t res2 = res1 * m_rxLevel;
samples[i] = q15_t(__SSAT((res2 >> 15), 16));
}
@@ -308,6 +420,7 @@ void CIO::process()
#endif
if (m_modemState == STATE_IDLE) {
#if defined(MODE_DSTAR)
if (m_dstarEnable) {
q15_t GMSKVals[RX_BLOCK_SIZE];
#if defined(USE_DCBLOCKER)
@@ -317,54 +430,102 @@ void CIO::process()
#endif
dstarRX.samples(GMSKVals, rssi, RX_BLOCK_SIZE);
}
#endif
#if defined(MODE_P25)
if (m_p25Enable) {
q15_t P25Vals[RX_BLOCK_SIZE];
#if defined(USE_DCBLOCKER)
::arm_fir_fast_q15(&m_boxcarFilter, dcSamples, P25Vals, RX_BLOCK_SIZE);
::arm_fir_fast_q15(&m_boxcar5Filter, dcSamples, P25Vals, RX_BLOCK_SIZE);
#else
::arm_fir_fast_q15(&m_boxcarFilter, samples, P25Vals, RX_BLOCK_SIZE);
::arm_fir_fast_q15(&m_boxcar5Filter, samples, P25Vals, RX_BLOCK_SIZE);
#endif
p25RX.samples(P25Vals, rssi, RX_BLOCK_SIZE);
}
#endif
#if defined(MODE_NXDN)
if (m_nxdnEnable) {
q15_t NXDNVals[RX_BLOCK_SIZE];
#if defined(USE_NXDN_BOXCAR)
#if defined(USE_DCBLOCKER)
::arm_fir_fast_q15(&m_boxcar10Filter, dcSamples, NXDNVals, RX_BLOCK_SIZE);
#else
::arm_fir_fast_q15(&m_boxcar10Filter, samples, NXDNVals, RX_BLOCK_SIZE);
#endif
#else
q15_t NXDNValsTmp[RX_BLOCK_SIZE];
#if defined(USE_DCBLOCKER)
::arm_fir_fast_q15(&m_nxdnFilter, dcSamples, NXDNValsTmp, RX_BLOCK_SIZE);
#else
::arm_fir_fast_q15(&m_nxdnFilter, samples, NXDNValsTmp, RX_BLOCK_SIZE);
#endif
q15_t NXDNVals[RX_BLOCK_SIZE];
::arm_fir_fast_q15(&m_nxdnISincFilter, NXDNValsTmp, NXDNVals, RX_BLOCK_SIZE);
#endif
nxdnRX.samples(NXDNVals, rssi, RX_BLOCK_SIZE);
}
#endif
if (m_dmrEnable || m_ysfEnable) {
q15_t RRCVals[RX_BLOCK_SIZE];
::arm_fir_fast_q15(&m_rrcFilter, samples, RRCVals, RX_BLOCK_SIZE);
#if defined(MODE_DMR)
if (m_dmrEnable) {
q15_t DMRVals[RX_BLOCK_SIZE];
::arm_fir_fast_q15(&m_rrc02Filter1, samples, DMRVals, RX_BLOCK_SIZE);
if (m_ysfEnable)
ysfRX.samples(RRCVals, rssi, RX_BLOCK_SIZE);
if (m_dmrEnable) {
if (m_duplex)
dmrIdleRX.samples(RRCVals, RX_BLOCK_SIZE);
else
dmrDMORX.samples(RRCVals, rssi, RX_BLOCK_SIZE);
}
if (m_duplex)
dmrIdleRX.samples(DMRVals, RX_BLOCK_SIZE);
else
dmrDMORX.samples(DMRVals, rssi, RX_BLOCK_SIZE);
}
#endif
#if defined(MODE_YSF)
if (m_ysfEnable) {
q15_t YSFVals[RX_BLOCK_SIZE];
#if defined(USE_DCBLOCKER)
::arm_fir_fast_q15(&m_rrc02Filter2, dcSamples, YSFVals, RX_BLOCK_SIZE);
#else
::arm_fir_fast_q15(&m_rrc02Filter2, samples, YSFVals, RX_BLOCK_SIZE);
#endif
ysfRX.samples(YSFVals, rssi, RX_BLOCK_SIZE);
}
#endif
#if defined(MODE_M17)
if (m_m17Enable) {
q15_t RRCVals[RX_BLOCK_SIZE];
#if defined(USE_DCBLOCKER)
::arm_fir_fast_q15(&m_rrc05Filter, dcSamples, RRCVals, RX_BLOCK_SIZE);
#else
::arm_fir_fast_q15(&m_rrc05Filter, samples, RRCVals, RX_BLOCK_SIZE);
#endif
m17RX.samples(RRCVals, rssi, RX_BLOCK_SIZE);
}
#endif
#if defined(MODE_FM)
if (m_fmEnable) {
bool cos = getCOSInt();
#if defined(USE_DCBLOCKER)
fm.samples(cos, dcSamples, RX_BLOCK_SIZE);
fm.samples(cos, dcSamples, rssi, RX_BLOCK_SIZE);
#else
fm.samples(cos, samples, RX_BLOCK_SIZE);
fm.samples(cos, samples, rssi, RX_BLOCK_SIZE);
#endif
}
} else if (m_modemState == STATE_DSTAR) {
#endif
#if defined(MODE_FM) && defined(MODE_AX25)
if (m_ax25Enable) {
#if defined(USE_DCBLOCKER)
ax25RX.samples(dcSamples, rssi, RX_BLOCK_SIZE);
#else
ax25RX.samples(samples, rssi, RX_BLOCK_SIZE);
#endif
}
#endif
}
#if defined(MODE_DSTAR)
else if (m_modemState == STATE_DSTAR) {
if (m_dstarEnable) {
q15_t GMSKVals[RX_BLOCK_SIZE];
#if defined(USE_DCBLOCKER)
@@ -374,10 +535,14 @@ void CIO::process()
#endif
dstarRX.samples(GMSKVals, rssi, RX_BLOCK_SIZE);
}
} else if (m_modemState == STATE_DMR) {
}
#endif
#if defined(MODE_DMR)
else if (m_modemState == STATE_DMR) {
if (m_dmrEnable) {
q15_t DMRVals[RX_BLOCK_SIZE];
::arm_fir_fast_q15(&m_rrcFilter, samples, DMRVals, RX_BLOCK_SIZE);
::arm_fir_fast_q15(&m_rrc02Filter1, samples, DMRVals, RX_BLOCK_SIZE);
if (m_duplex) {
// If the transmitter isn't on, use the DMR idle RX to detect the wakeup CSBKs
@@ -389,52 +554,106 @@ void CIO::process()
dmrDMORX.samples(DMRVals, rssi, RX_BLOCK_SIZE);
}
}
} else if (m_modemState == STATE_YSF) {
}
#endif
#if defined(MODE_YSF)
else if (m_modemState == STATE_YSF) {
if (m_ysfEnable) {
q15_t YSFVals[RX_BLOCK_SIZE];
#if defined(USE_DCBLOCKER)
::arm_fir_fast_q15(&m_rrcFilter, dcSamples, YSFVals, RX_BLOCK_SIZE);
::arm_fir_fast_q15(&m_rrc02Filter2, dcSamples, YSFVals, RX_BLOCK_SIZE);
#else
::arm_fir_fast_q15(&m_rrcFilter, samples, YSFVals, RX_BLOCK_SIZE);
::arm_fir_fast_q15(&m_rrc02Filter2, samples, YSFVals, RX_BLOCK_SIZE);
#endif
ysfRX.samples(YSFVals, rssi, RX_BLOCK_SIZE);
}
} else if (m_modemState == STATE_P25) {
}
#endif
#if defined(MODE_P25)
else if (m_modemState == STATE_P25) {
if (m_p25Enable) {
q15_t P25Vals[RX_BLOCK_SIZE];
#if defined(USE_DCBLOCKER)
::arm_fir_fast_q15(&m_boxcarFilter, dcSamples, P25Vals, RX_BLOCK_SIZE);
::arm_fir_fast_q15(&m_boxcar5Filter, dcSamples, P25Vals, RX_BLOCK_SIZE);
#else
::arm_fir_fast_q15(&m_boxcarFilter, samples, P25Vals, RX_BLOCK_SIZE);
::arm_fir_fast_q15(&m_boxcar5Filter, samples, P25Vals, RX_BLOCK_SIZE);
#endif
p25RX.samples(P25Vals, rssi, RX_BLOCK_SIZE);
}
} else if (m_modemState == STATE_NXDN) {
}
#endif
#if defined(MODE_NXDN)
else if (m_modemState == STATE_NXDN) {
if (m_nxdnEnable) {
q15_t NXDNVals[RX_BLOCK_SIZE];
#if defined(USE_NXDN_BOXCAR)
#if defined(USE_DCBLOCKER)
::arm_fir_fast_q15(&m_boxcar10Filter, dcSamples, NXDNVals, RX_BLOCK_SIZE);
#else
::arm_fir_fast_q15(&m_boxcar10Filter, samples, NXDNVals, RX_BLOCK_SIZE);
#endif
#else
q15_t NXDNValsTmp[RX_BLOCK_SIZE];
#if defined(USE_DCBLOCKER)
::arm_fir_fast_q15(&m_nxdnFilter, dcSamples, NXDNValsTmp, RX_BLOCK_SIZE);
#else
::arm_fir_fast_q15(&m_nxdnFilter, samples, NXDNValsTmp, RX_BLOCK_SIZE);
#endif
q15_t NXDNVals[RX_BLOCK_SIZE];
::arm_fir_fast_q15(&m_nxdnISincFilter, NXDNValsTmp, NXDNVals, RX_BLOCK_SIZE);
#endif
nxdnRX.samples(NXDNVals, rssi, RX_BLOCK_SIZE);
}
} else if (m_modemState == STATE_FM) {
}
#endif
#if defined(MODE_M17)
else if (m_modemState == STATE_M17) {
if (m_m17Enable) {
q15_t M17Vals[RX_BLOCK_SIZE];
#if defined(USE_DCBLOCKER)
::arm_fir_fast_q15(&m_rrc05Filter, dcSamples, M17Vals, RX_BLOCK_SIZE);
#else
::arm_fir_fast_q15(&m_rrc05Filter, samples, M17Vals, RX_BLOCK_SIZE);
#endif
m17RX.samples(M17Vals, rssi, RX_BLOCK_SIZE);
}
}
#endif
#if defined(MODE_FM)
else if (m_modemState == STATE_FM) {
bool cos = getCOSInt();
#if defined(USE_DCBLOCKER)
fm.samples(cos, dcSamples, RX_BLOCK_SIZE);
#else
fm.samples(cos, samples, RX_BLOCK_SIZE);
fm.samples(cos, dcSamples, rssi, RX_BLOCK_SIZE);
#if defined(MODE_AX25)
if (m_ax25Enable)
ax25RX.samples(dcSamples, rssi, RX_BLOCK_SIZE);
#endif
} else if (m_modemState == STATE_DSTARCAL) {
#else
fm.samples(cos, samples, rssi, RX_BLOCK_SIZE);
#if defined(MODE_AX25)
if (m_ax25Enable)
ax25RX.samples(samples, rssi, RX_BLOCK_SIZE);
#endif
#endif
}
#endif
#if defined(MODE_DSTAR)
else if (m_modemState == STATE_DSTARCAL) {
q15_t GMSKVals[RX_BLOCK_SIZE];
::arm_fir_fast_q15(&m_gaussianFilter, samples, GMSKVals, RX_BLOCK_SIZE);
calDStarRX.samples(GMSKVals, RX_BLOCK_SIZE);
} else if (m_modemState == STATE_RSSICAL) {
}
#endif
else if (m_modemState == STATE_RSSICAL) {
calRSSI.samples(rssi, RX_BLOCK_SIZE);
}
}
@@ -452,6 +671,7 @@ void CIO::write(MMDVM_STATE mode, q15_t* samples, uint16_t length, const uint8_t
if (!m_tx) {
m_tx = true;
setPTTInt(m_pttInvert ? false : true);
DEBUG1("TX ON");
}
q15_t txLevel = 0;
@@ -471,12 +691,18 @@ void CIO::write(MMDVM_STATE mode, q15_t* samples, uint16_t length, const uint8_t
case STATE_NXDN:
txLevel = m_nxdnTXLevel;
break;
case STATE_M17:
txLevel = m_m17TXLevel;
break;
case STATE_POCSAG:
txLevel = m_pocsagTXLevel;
break;
case STATE_FM:
txLevel = m_fmTXLevel;
break;
case STATE_AX25:
txLevel = m_ax25TXLevel;
break;
default:
txLevel = m_cwIdTXLevel;
break;
@@ -492,9 +718,9 @@ void CIO::write(MMDVM_STATE mode, q15_t* samples, uint16_t length, const uint8_t
m_dacOverflow++;
if (control == NULL)
m_txBuffer.put(res3, MARK_NONE);
m_txBuffer.put({res3, MARK_NONE});
else
m_txBuffer.put(res3, control[i]);
m_txBuffer.put({res3, control[i]});
}
}
@@ -516,20 +742,41 @@ void CIO::setADCDetection(bool detect)
m_detect = detect;
}
void CIO::setMode()
void CIO::setMode(MMDVM_STATE state)
{
if (state == m_modemState)
return;
#if defined(MODE_LEDS)
setDStarInt(m_modemState == STATE_DSTAR);
setDMRInt(m_modemState == STATE_DMR);
setYSFInt(m_modemState == STATE_YSF);
setP25Int(m_modemState == STATE_P25);
setNXDNInt(m_modemState == STATE_NXDN);
setPOCSAGInt(m_modemState == STATE_POCSAG);
setFMInt(m_modemState == STATE_FM);
switch (m_modemState) {
case STATE_DSTAR: setDStarInt(false); break;
case STATE_DMR: setDMRInt(false); break;
case STATE_YSF: setYSFInt(false); break;
case STATE_P25: setP25Int(false); break;
case STATE_NXDN: setNXDNInt(false); break;
case STATE_M17: setM17Int(false); break;
case STATE_POCSAG: setPOCSAGInt(false); break;
case STATE_FM: setFMInt(false); break;
default: break;
}
switch (state) {
case STATE_DSTAR: setDStarInt(true); break;
case STATE_DMR: setDMRInt(true); break;
case STATE_YSF: setYSFInt(true); break;
case STATE_P25: setP25Int(true); break;
case STATE_NXDN: setNXDNInt(true); break;
case STATE_M17: setM17Int(true); break;
case STATE_POCSAG: setPOCSAGInt(true); break;
case STATE_FM: setFMInt(true); break;
default: break;
}
#endif
m_modemState = state;
}
void CIO::setParameters(bool rxInvert, bool txInvert, bool pttInvert, uint8_t rxLevel, uint8_t cwIdTXLevel, uint8_t dstarTXLevel, uint8_t dmrTXLevel, uint8_t ysfTXLevel, uint8_t p25TXLevel, uint8_t nxdnTXLevel, uint8_t pocsagTXLevel, uint8_t fmTXLevel, int16_t txDCOffset, int16_t rxDCOffset)
void CIO::setParameters(bool rxInvert, bool txInvert, bool pttInvert, uint8_t rxLevel, uint8_t cwIdTXLevel, uint8_t dstarTXLevel, uint8_t dmrTXLevel, uint8_t ysfTXLevel, uint8_t p25TXLevel, uint8_t nxdnTXLevel, uint8_t m17TXLevel, uint8_t pocsagTXLevel, uint8_t fmTXLevel, uint8_t ax25TXLevel, int16_t txDCOffset, int16_t rxDCOffset, bool useCOSAsLockout)
{
m_pttInvert = pttInvert;
@@ -540,12 +787,16 @@ void CIO::setParameters(bool rxInvert, bool txInvert, bool pttInvert, uint8_t rx
m_ysfTXLevel = q15_t(ysfTXLevel * 128);
m_p25TXLevel = q15_t(p25TXLevel * 128);
m_nxdnTXLevel = q15_t(nxdnTXLevel * 128);
m_m17TXLevel = q15_t(m17TXLevel * 128);
m_pocsagTXLevel = q15_t(pocsagTXLevel * 128);
m_fmTXLevel = q15_t(fmTXLevel * 128);
m_ax25TXLevel = q15_t(ax25TXLevel * 128);
m_rxDCOffset = DC_OFFSET + rxDCOffset;
m_txDCOffset = DC_OFFSET + txDCOffset;
m_useCOSAsLockout = useCOSAsLockout;
if (rxInvert)
m_rxLevel = -m_rxLevel;
@@ -555,6 +806,7 @@ void CIO::setParameters(bool rxInvert, bool txInvert, bool pttInvert, uint8_t rx
m_ysfTXLevel = -m_ysfTXLevel;
m_p25TXLevel = -m_p25TXLevel;
m_nxdnTXLevel = -m_nxdnTXLevel;
m_m17TXLevel = -m_m17TXLevel;
m_pocsagTXLevel = -m_pocsagTXLevel;
}
}
+55 -14
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2015,2016,2017,2018 by Jonathan Naylor G4KLX
* Copyright (C) 2015,2016,2017,2018,2020,2021 by Jonathan Naylor G4KLX
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -21,8 +21,12 @@
#include "Globals.h"
#include "SampleRB.h"
#include "RSSIRB.h"
#include "RingBuffer.h"
struct TSample {
volatile uint16_t sample;
volatile uint8_t control;
};
class CIO {
public:
@@ -38,11 +42,11 @@ public:
void setDecode(bool dcd);
void setADCDetection(bool detect);
void setMode();
void setMode(MMDVM_STATE state);
void interrupt();
void setParameters(bool rxInvert, bool txInvert, bool pttInvert, uint8_t rxLevel, uint8_t cwIdTXLevel, uint8_t dstarTXLevel, uint8_t dmrTXLevel, uint8_t ysfTXLevel, uint8_t p25TXLevel, uint8_t nxdnTXLevel, uint8_t pocsagTXLevel, uint8_t fmTXLevel, int16_t txDCOffset, int16_t rxDCOffset);
void setParameters(bool rxInvert, bool txInvert, bool pttInvert, uint8_t rxLevel, uint8_t cwIdTXLevel, uint8_t dstarTXLevel, uint8_t dmrTXLevel, uint8_t ysfTXLevel, uint8_t p25TXLevel, uint8_t nxdnTXLevel, uint8_t m17TXLevel, uint8_t pocsagTXLevel, uint8_t fmTXLevel, uint8_t ax25TXLevel, int16_t txDCOffset, int16_t rxDCOffset, bool useCOSAsLockout);
void getOverflow(bool& adcOverflow, bool& dacOverflow);
@@ -54,28 +58,60 @@ public:
void resetWatchdog();
uint32_t getWatchdog();
uint8_t getCPU() const;
void getUDID(uint8_t* buffer);
void selfTest();
private:
bool m_started;
bool m_started;
CSampleRB m_rxBuffer;
CSampleRB m_txBuffer;
CRSSIRB m_rssiBuffer;
CRingBuffer<TSample> m_rxBuffer;
CRingBuffer<TSample> m_txBuffer;
CRingBuffer<uint16_t> m_rssiBuffer;
#if defined(USE_DCBLOCKER)
arm_biquad_casd_df1_inst_q31 m_dcFilter;
q31_t m_dcState[4];
#endif
arm_fir_instance_q15 m_rrcFilter;
#if defined(MODE_DSTAR)
arm_fir_instance_q15 m_gaussianFilter;
arm_fir_instance_q15 m_boxcarFilter;
q15_t m_gaussianState[40U]; // NoTaps + BlockSize - 1, 12 + 20 - 1 plus some spare
#endif
#if defined(MODE_DMR)
arm_fir_instance_q15 m_rrc02Filter1;
q15_t m_rrc02State1[70U]; // NoTaps + BlockSize - 1, 42 + 20 - 1 plus some spare
#endif
#if defined(MODE_YSF)
arm_fir_instance_q15 m_rrc02Filter2;
q15_t m_rrc02State2[70U]; // NoTaps + BlockSize - 1, 42 + 20 - 1 plus some spare
#endif
#if defined(MODE_P25)
arm_fir_instance_q15 m_boxcar5Filter;
q15_t m_boxcar5State[30U]; // NoTaps + BlockSize - 1, 6 + 20 - 1 plus some spare
#endif
#if defined(MODE_NXDN)
#if defined(USE_NXDN_BOXCAR)
arm_fir_instance_q15 m_boxcar10Filter;
q15_t m_boxcar10State[40U]; // NoTaps + BlockSize - 1, 10 + 20 - 1 plus some spare
#else
arm_fir_instance_q15 m_nxdnFilter;
arm_fir_instance_q15 m_nxdnISincFilter;
q15_t m_rrcState[70U]; // NoTaps + BlockSize - 1, 42 + 20 - 1 plus some spare
q15_t m_gaussianState[40U]; // NoTaps + BlockSize - 1, 12 + 20 - 1 plus some spare
q15_t m_boxcarState[30U]; // NoTaps + BlockSize - 1, 6 + 20 - 1 plus some spare
q15_t m_nxdnState[110U]; // NoTaps + BlockSize - 1, 82 + 20 - 1 plus some spare
q15_t m_nxdnISincState[60U]; // NoTaps + BlockSize - 1, 32 + 20 - 1 plus some spare
#endif
#endif
#if defined(MODE_M17)
arm_fir_instance_q15 m_rrc05Filter;
q15_t m_rrc05State[70U]; // NoTaps + BlockSize - 1, 42 + 20 - 1 plus some spare
#endif
bool m_pttInvert;
q15_t m_rxLevel;
@@ -85,12 +121,16 @@ private:
q15_t m_ysfTXLevel;
q15_t m_p25TXLevel;
q15_t m_nxdnTXLevel;
q15_t m_m17TXLevel;
q15_t m_pocsagTXLevel;
q15_t m_fmTXLevel;
q15_t m_ax25TXLevel;
uint16_t m_rxDCOffset;
uint16_t m_txDCOffset;
bool m_useCOSAsLockout;
uint32_t m_ledCount;
bool m_ledValue;
@@ -119,6 +159,7 @@ private:
void setP25Int(bool on);
void setNXDNInt(bool on);
void setPOCSAGInt(bool on);
void setM17Int(bool on);
void setFMInt(bool on);
void delayInt(unsigned int dly);
-282
View File
@@ -1,282 +0,0 @@
/*
* Copyright (C) 2015,2016,2017,2018,2020 by Jonathan Naylor G4KLX
* Copyright (C) 2015 by Jim Mclaughlin KI6ZUM
* Copyright (C) 2016 by Colin Durbridge G4EML
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "Config.h"
#include "Globals.h"
#include "IO.h"
#if defined(__SAM3X8E__)
// An Arduino Due
#if defined(ARDUINO_DUE_PAPA)
#define PIN_COS 7
#define PIN_PTT 8
#define PIN_COSLED 11
#define PIN_DSTAR 16
#define PIN_DMR 17
#define PIN_YSF 18
#define PIN_P25 19
#define PIN_NXDN 20
#define PIN_POCSAG 4
#define PIN_FM 5
#define ADC_CHER_Chan (1<<7) // ADC on Due pin A0 - Due AD7 - (1 << 7)
#define ADC_ISR_EOC_Chan ADC_ISR_EOC7
#define ADC_CDR_Chan 7
#define DACC_MR_USER_SEL_Chan DACC_MR_USER_SEL_CHANNEL0 // DAC on Due DAC0
#define DACC_CHER_Chan DACC_CHER_CH0
#elif defined(ARDUINO_DUE_ZUM_V10)
#define PIN_COS 52
#define PIN_PTT 23
#define PIN_COSLED 22
#define PIN_DSTAR 9
#define PIN_DMR 8
#define PIN_YSF 7
#define PIN_P25 6
#define PIN_NXDN 5
#define PIN_POCSAG 4
#define PIN_FM 3
#define ADC_CHER_Chan (1<<13) // ADC on Due pin A11 - Due AD13 - (1 << 13)
#define ADC_ISR_EOC_Chan ADC_ISR_EOC13
#define ADC_CDR_Chan 13
#define DACC_MR_USER_SEL_Chan DACC_MR_USER_SEL_CHANNEL1 // DAC on Due DAC1
#define DACC_CHER_Chan DACC_CHER_CH1
#define RSSI_CHER_Chan (1<<1) // ADC on Due pin A6 - Due AD1 - (1 << 1)
#define RSSI_CDR_Chan 1
#elif defined(ARDUINO_DUE_NTH)
#define PIN_COS A7
#define PIN_PTT A8
#define PIN_COSLED A11
#define PIN_DSTAR 9
#define PIN_DMR 8
#define PIN_YSF 7
#define PIN_P25 6
#define PIN_NXDN 5
#define PIN_POCSAG 4
#define PIN_FM 3
#define ADC_CHER_Chan (1<<7) // ADC on Due pin A0 - Due AD7 - (1 << 7)
#define ADC_ISR_EOC_Chan ADC_ISR_EOC7
#define ADC_CDR_Chan 7
#define DACC_MR_USER_SEL_Chan DACC_MR_USER_SEL_CHANNEL0 // DAC on Due DAC0
#define DACC_CHER_Chan DACC_CHER_CH0
#define RSSI_CHER_Chan (1<<1) // ADC on Due pin A6 - Due AD1 - (1 << 1)
#define RSSI_CDR_Chan 1
#else
#error "Either ARDUINO_DUE_PAPA, ARDUINO_DUE_ZUM_V10, or ARDUINO_DUE_NTH need to be defined"
#endif
const uint16_t DC_OFFSET = 2048U;
extern "C" {
void ADC_Handler()
{
io.interrupt();
}
}
void CIO::initInt()
{
// Set up the TX, COS and LED pins
pinMode(PIN_PTT, OUTPUT);
pinMode(PIN_COSLED, OUTPUT);
pinMode(PIN_LED, OUTPUT);
pinMode(PIN_COS, INPUT);
#if defined(MODE_LEDS)
// Set up the mode output pins
pinMode(PIN_DSTAR, OUTPUT);
pinMode(PIN_DMR, OUTPUT);
pinMode(PIN_YSF, OUTPUT);
pinMode(PIN_P25, OUTPUT);
#if !defined(USE_ALTERNATE_NXDN_LEDS)
pinMode(PIN_NXDN, OUTPUT);
#endif
#if !defined(USE_ALTERNATE_POCSAG_LEDS)
pinMode(PIN_POCSAG, OUTPUT);
#endif
#if !defined(USE_ALTERNATE_POCSAG_LEDS)
pinMode(PIN_FM, OUTPUT);
#endif
#endif
}
void CIO::startInt()
{
if (ADC->ADC_ISR & ADC_ISR_EOC_Chan) // Ensure there was an End-of-Conversion and we read the ISR reg
io.interrupt();
// Set up the ADC
NVIC_EnableIRQ(ADC_IRQn); // Enable ADC interrupt vector
ADC->ADC_IDR = 0xFFFFFFFF; // Disable interrupts
ADC->ADC_IER = ADC_CHER_Chan; // Enable End-Of-Conv interrupt
ADC->ADC_CHDR = 0xFFFF; // Disable all channels
ADC->ADC_CHER = ADC_CHER_Chan; // Enable rx input channel
#if defined(SEND_RSSI_DATA)
ADC->ADC_CHER |= RSSI_CHER_Chan; // and RSSI input
#endif
ADC->ADC_CGR = 0x15555555; // All gains set to x1
ADC->ADC_COR = 0x00000000; // All offsets off
ADC->ADC_MR = (ADC->ADC_MR & 0xFFFFFFF0) | (1 << 1) | ADC_MR_TRGEN; // 1 = trig source TIO from TC0
#if defined(EXTERNAL_OSC)
// Set up the external clock input on PA4 = AI5
REG_PIOA_ODR = 0x10; // Set pin as input
REG_PIOA_PDR = 0x10; // Disable PIO A bit 4
REG_PIOA_ABSR &= ~0x10; // Select A peripheral = TCLK1 Input
#endif
// Set up the timer
pmc_enable_periph_clk(TC_INTERFACE_ID + 0*3+0) ; // Clock the TC0 channel 0
TcChannel* t = &(TC0->TC_CHANNEL)[0]; // Pointer to TC0 registers for its channel 0
t->TC_CCR = TC_CCR_CLKDIS; // Disable internal clocking while setup regs
t->TC_IDR = 0xFFFFFFFF; // Disable interrupts
t->TC_SR; // Read int status reg to clear pending
#if defined(EXTERNAL_OSC)
t->TC_CMR = TC_CMR_TCCLKS_XC1 | // Use XC1 = TCLK1 external clock
#else
t->TC_CMR = TC_CMR_TCCLKS_TIMER_CLOCK1 | // Use TCLK1 (prescale by 2, = 42MHz)
#endif
TC_CMR_WAVE | // Waveform mode
TC_CMR_WAVSEL_UP_RC | // Count-up PWM using RC as threshold
TC_CMR_EEVT_XC0 | // Set external events from XC0 (this setup TIOB as output)
TC_CMR_ACPA_CLEAR | TC_CMR_ACPC_CLEAR |
TC_CMR_BCPB_CLEAR | TC_CMR_BCPC_CLEAR;
#if defined(EXTERNAL_OSC)
t->TC_RC = EXTERNAL_OSC / 24000; // Counter resets on RC, so sets period in terms of the external clock
t->TC_RA = EXTERNAL_OSC / 48000; // Roughly square wave
#else
t->TC_RC = 1750; // Counter resets on RC, so sets period in terms of 42MHz internal clock
t->TC_RA = 880; // Roughly square wave
#endif
t->TC_CMR = (t->TC_CMR & 0xFFF0FFFF) | TC_CMR_ACPA_CLEAR | TC_CMR_ACPC_SET; // Set clear and set from RA and RC compares
t->TC_CCR = TC_CCR_CLKEN | TC_CCR_SWTRG; // re-enable local clocking and switch to hardware trigger source.
// Set up the DAC
pmc_enable_periph_clk(DACC_INTERFACE_ID); // Start clocking DAC
DACC->DACC_CR = DACC_CR_SWRST; // Reset DAC
DACC->DACC_MR =
DACC_MR_TRGEN_EN | DACC_MR_TRGSEL(1) | // Trigger 1 = TIO output of TC0
DACC_MR_USER_SEL_Chan | // Select channel
(24 << DACC_MR_STARTUP_Pos); // 24 = 1536 cycles which I think is in range 23..45us since DAC clock = 42MHz
DACC->DACC_IDR = 0xFFFFFFFF; // No interrupts
DACC->DACC_CHER = DACC_CHER_Chan; // Enable channel
digitalWrite(PIN_PTT, m_pttInvert ? HIGH : LOW);
digitalWrite(PIN_COSLED, LOW);
digitalWrite(PIN_LED, HIGH);
}
void CIO::interrupt()
{
if ((ADC->ADC_ISR & ADC_ISR_EOC_Chan) == ADC_ISR_EOC_Chan) { // Ensure there was an End-of-Conversion and we read the ISR reg
uint8_t control = MARK_NONE;
uint16_t sample = DC_OFFSET;
m_txBuffer.get(sample, control);
DACC->DACC_CDR = sample;
sample = ADC->ADC_CDR[ADC_CDR_Chan];
m_rxBuffer.put(sample, control);
#if defined(SEND_RSSI_DATA)
m_rssiBuffer.put(ADC->ADC_CDR[RSSI_CDR_Chan]);
#else
m_rssiBuffer.put(0U);
#endif
m_watchdog++;
}
}
bool CIO::getCOSInt()
{
return digitalRead(PIN_COS) == HIGH;
}
void CIO::setLEDInt(bool on)
{
digitalWrite(PIN_LED, on ? HIGH : LOW);
}
void CIO::setPTTInt(bool on)
{
digitalWrite(PIN_PTT, on ? HIGH : LOW);
}
void CIO::setCOSInt(bool on)
{
digitalWrite(PIN_COSLED, on ? HIGH : LOW);
}
void CIO::setDStarInt(bool on)
{
digitalWrite(PIN_DSTAR, on ? HIGH : LOW);
}
void CIO::setDMRInt(bool on)
{
digitalWrite(PIN_DMR, on ? HIGH : LOW);
}
void CIO::setYSFInt(bool on)
{
digitalWrite(PIN_YSF, on ? HIGH : LOW);
}
void CIO::setP25Int(bool on)
{
digitalWrite(PIN_P25, on ? HIGH : LOW);
}
void CIO::setNXDNInt(bool on)
{
#if defined(USE_ALTERNATE_NXDN_LEDS)
digitalWrite(PIN_YSF, on ? HIGH : LOW);
digitalWrite(PIN_P25, on ? HIGH : LOW);
#else
digitalWrite(PIN_NXDN, on ? HIGH : LOW);
#endif
}
void CIO::setPOCSAGInt(bool on)
{
#if defined(USE_ALTERNATE_POCSAG_LEDS)
digitalWrite(PIN_DSTAR, on ? HIGH : LOW);
digitalWrite(PIN_DMR, on ? HIGH : LOW);
#else
digitalWrite(PIN_POCSAG, on ? HIGH : LOW);
#endif
}
void CIO::setFMInt(bool on)
{
#if defined(USE_ALTERNATE_FM_LEDS)
digitalWrite(PIN_DSTAR, on ? HIGH : LOW);
digitalWrite(PIN_YSF, on ? HIGH : LOW);
#else
digitalWrite(PIN_FM, on ? HIGH : LOW);
#endif
}
void CIO::delayInt(unsigned int dly)
{
delay(dly);
}
#endif
+79
View File
@@ -0,0 +1,79 @@
/*
* Copyright (C) 2019,2020 by BG5HHP
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifndef _IO_PINS_H
#define _IO_PINS_H
#if !defined(CONFIG_H)
#error "Requires Config.h to be included first!"
#endif
#if defined(STM32F4_RPT_HAT_TGO)
#include "pins/pins_f4_rpt_tgo.h"
#elif defined(STM32F4_DISCOVERY)
#include "pins/pins_f4_discovery.h"
#elif defined(STM32F4_PI)
#include "pins/pins_f4_pi.h"
#elif defined(STM32F722_PI)
#include "pins/pins_f7_pi.h"
#elif defined(STM32F4_F4M)
#include "pins/pins_f4_f4m.h"
#elif defined(STM32F722_F7M)
#include "pins/pins_f7_f7m.h"
#elif defined(STM32F722_RPT_HAT)
#include "pins/pins_f7_rpt_hat.h"
#elif defined(STM32F4_NUCLEO)
#if defined(STM32F4_NUCLEO_MORPHO_HEADER)
#include "pins/pins_f4_nucleo_morpho.h"
#elif defined(STM32F4_NUCLEO_ARDUINO_HEADER)
#include "pins/pins_f4_nucleo_arduino.h"
#else
#error "Either STM32F4_NUCLEO_MORPHO_HEADER or STM32F4_NUCLEO_ARDUINO_HEADER need to be defined"
#endif
#elif defined(STM32F7_NUCLEO)
#include "pins/pins_f7_nucleo.h"
#elif defined(STM32F4_DVM)
#include "pins/pins_f4_stm32dvm_v3.h"
#elif defined(STM32F7_DVM)
#include "pins/pins_f7_stm32dvm_v5.h"
#elif defined(DRCC_DVM_NQF)
#include "pins/pins_f4_drcc_nqf.h"
#elif defined(DRCC_DVM_HHP446)
#include "pins/pins_f4_drcc_hhp446.h"
#elif defined(STM32F4_EDA_405) || defined(STM32F4_EDA_446)
#include "pins/pins_f4_stm32eda.h"
#else
#error "A valid board type macro need to be defined."
#endif
#endif //#ifndef _IO_PINS_H
+121 -1034
View File
File diff suppressed because it is too large Load Diff
-485
View File
@@ -1,485 +0,0 @@
/*
* Copyright (C) 2016 by Jim McLaughlin KI6ZUM
* Copyright (C) 2016, 2017 by Andy Uribe CA6JAU
* Copyright (C) 2017,2018,2020 by Jonathan Naylor G4KLX
* Copyright (C) 2017 by Wojciech Krutnik N0CALL
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "Config.h"
#include "Globals.h"
#include "IO.h"
#if defined(STM32F1)
#if defined(STM32F1_POG)
/*
Pin definitions for STM32F1 POG Board:
PTT PB12 output
COSLED PB5 output
LED PB4 output
COS PB13 input/PD
DSTAR PB7 output
DMR PB6 output
YSF PB8 output
P25 PB9 output
NXDN PB10 output
POCSAG PB11 output
FM PB12 output
RX PB0 analog input (ADC1_8)
RSSI PB1 analog input (ADC2_9)
TX PA4 analog output (DAC_OUT1)
EXT_CLK PA15 input (AF: TIM2_CH1_ETR)
USART1_TXD PA9 output (AF)
USART1_RXD PA10 input (AF)
*/
#define PIN_PTT 12
#define PORT_PTT GPIOB
#define BB_PTT *((bitband_t)BITBAND_PERIPH(&PORT_PTT->ODR, PIN_PTT))
#define PIN_COSLED 5
#define PORT_COSLED GPIOB
#define BB_COSLED *((bitband_t)BITBAND_PERIPH(&PORT_COSLED->ODR, PIN_COSLED))
#define PIN_LED 4
#define PORT_LED GPIOB
#define BB_LED *((bitband_t)BITBAND_PERIPH(&PORT_LED->ODR, PIN_LED))
#define PIN_COS 13
#define PORT_COS GPIOB
#define BB_COS *((bitband_t)BITBAND_PERIPH(&PORT_COS->IDR, PIN_COS))
#define PIN_DSTAR 7
#define PORT_DSTAR GPIOB
#define BB_DSTAR *((bitband_t)BITBAND_PERIPH(&PORT_DSTAR->ODR, PIN_DSTAR))
#define PIN_DMR 6
#define PORT_DMR GPIOB
#define BB_DMR *((bitband_t)BITBAND_PERIPH(&PORT_DMR->ODR, PIN_DMR))
#define PIN_YSF 8
#define PORT_YSF GPIOB
#define BB_YSF *((bitband_t)BITBAND_PERIPH(&PORT_YSF->ODR, PIN_YSF))
#define PIN_P25 9
#define PORT_P25 GPIOB
#define BB_P25 *((bitband_t)BITBAND_PERIPH(&PORT_P25->ODR, PIN_P25))
#define PIN_NXDN 10
#define PORT_NXDN GPIOB
#define BB_NXDN *((bitband_t)BITBAND_PERIPH(&PORT_NXDN->ODR, PIN_NXDN))
#define PIN_POCSAG 11
#define PORT_POCSAG GPIOB
#define BB_POCSAG *((bitband_t)BITBAND_PERIPH(&PORT_POCSAG->ODR, PIN_POCSAG))
#define PIN_FM 12
#define PORT_FM GPIOB
#define BB_FM *((bitband_t)BITBAND_PERIPH(&PORT_FM->ODR, PIN_FM))
#define PIN_RX 0
#define PIN_RX_ADC_CH 8
#define PORT_RX GPIOB
#define PIN_RSSI 1
#define PIN_RSSI_ADC_CH 9
#define PORT_RSSI GPIOB
#define PIN_TX 4
#define PIN_TX_DAC_CH 1
#define PORT_TX GPIOA
#define PIN_EXT_CLK 15
#define SRC_EXT_CLK 15
#define PORT_EXT_CLK GPIOA
#define PIN_USART1_TXD 9
#define PORT_USART1_TXD GPIOA
#define PIN_USART1_RXD 10
#define PORT_USART1_RXD GPIOA
#else // defined(STM32F1_POG)
#error "Either STM32F1_POG, or sth need to be defined"
#endif // defined(STM32F1_POG)
const uint16_t DC_OFFSET = 2048U;
// Sampling frequency
#define SAMP_FREQ 24000
extern "C" {
void TIM2_IRQHandler() {
if ((TIM2->SR & TIM_SR_UIF) == TIM_SR_UIF) {
TIM2->SR = ~TIM_SR_UIF; // clear UI flag
io.interrupt();
}
}
}
void delay(uint32_t cnt)
{
while(cnt--)
asm("nop");
}
// source: http://www.freddiechopin.info/
void GPIOConfigPin(GPIO_TypeDef *port_ptr, uint32_t pin, uint32_t mode_cnf_value)
{
volatile uint32_t *cr_ptr;
uint32_t cr_value;
cr_ptr = &port_ptr->CRL; // configuration of pins [0,7] is in CRL
if (pin >= 8) // is pin in [8; 15]?
{ // configuration of pins [8,15] is in CRH
cr_ptr++; // advance to next struct element CRL -> CRH
pin -= 8; // crop the pin number
}
cr_value = *cr_ptr; // localize the CRL / CRH value
cr_value &= ~(0xF << (pin * 4)); // clear the MODE and CNF fields (now that pin is an analog input)
cr_value |= (mode_cnf_value << (pin * 4)); // save new MODE and CNF value for desired pin
*cr_ptr = cr_value; // save localized value to CRL / CRL
}
#if defined(STM32F1_POG)
void FancyLEDEffect()
{
bitband_t foo[] = {&BB_LED, &BB_COSLED, &BB_PTT, &BB_DMR, &BB_DSTAR, &BB_YSF, &BB_P25, &BB_NXDN, &BB_POCSAG, &BB_FM};
for(int i=0; i<10; i++){
*foo[i] = 0x01;
}
GPIOConfigPin(PORT_USART1_TXD, PIN_USART1_TXD, GPIO_CRL_MODE0_1);
*((bitband_t)BITBAND_PERIPH(&PORT_USART1_TXD->ODR, PIN_USART1_TXD)) = 0x00;
delay(SystemCoreClock/1000*100);
for(int i=0; i<7; i++){
*foo[i] = 0x00;
}
*((bitband_t)BITBAND_PERIPH(&PORT_USART1_TXD->ODR, PIN_USART1_TXD)) = 0x01;
delay(SystemCoreClock/1000*20);
*((bitband_t)BITBAND_PERIPH(&PORT_USART1_TXD->ODR, PIN_USART1_TXD)) = 0x00;
delay(SystemCoreClock/1000*10);
*((bitband_t)BITBAND_PERIPH(&PORT_USART1_TXD->ODR, PIN_USART1_TXD)) = 0x01;
*foo[0] = 0x01;
for(int i=1; i<10; i++){
delay(SystemCoreClock/1000*10);
*foo[i-1] = 0x00;
*foo[i] = 0x01;
}
for(int i=10; i>=0; i--){
delay(SystemCoreClock/1000*10);
*foo[i+1] = 0x00;
*foo[i] = 0x01;
}
delay(SystemCoreClock/1000*10);
*foo[5+1-6] = 0x00;
*((bitband_t)BITBAND_PERIPH(&PORT_USART1_TXD->ODR, PIN_USART1_TXD)) = 0x00;
delay(SystemCoreClock/1000*10);
*((bitband_t)BITBAND_PERIPH(&PORT_USART1_TXD->ODR, PIN_USART1_TXD)) = 0x01;
GPIOConfigPin(PORT_USART1_TXD, PIN_USART1_TXD, GPIO_CRL_MODE0_1|GPIO_CRL_CNF0_1);
delay(SystemCoreClock/1000*50);
}
#endif
static inline void GPIOInit()
{
RCC->APB2ENR |= RCC_APB2ENR_IOPAEN | RCC_APB2ENR_IOPBEN
| RCC_APB2ENR_IOPCEN | RCC_APB2ENR_IOPDEN
| RCC_APB2ENR_AFIOEN; // enable all GPIOs
// set all ports to input with pull-down
GPIOA->CRL = 0x88888888;
GPIOA->CRH = 0x88888888;
GPIOA->ODR = 0;
GPIOB->CRL = 0x88888888;
GPIOB->CRH = 0x88888888;
GPIOB->ODR = 0;
GPIOC->CRL = 0x88888888;
GPIOC->CRH = 0x88888888;
GPIOC->ODR = 0;
GPIOD->CRL = 0x88888888;
GPIOD->CRH = 0x88888888;
GPIOD->ODR = 0;
// configure ports
GPIOConfigPin(PORT_PTT, PIN_PTT, GPIO_CRL_MODE0_1);
GPIOConfigPin(PORT_COSLED, PIN_COSLED, GPIO_CRL_MODE0_1);
GPIOConfigPin(PORT_LED, PIN_LED, GPIO_CRL_MODE0_1);
GPIOConfigPin(PORT_COS, PIN_COS, GPIO_CRL_CNF0_1);
GPIOConfigPin(PORT_DSTAR, PIN_DSTAR, GPIO_CRL_MODE0_1);
GPIOConfigPin(PORT_DMR, PIN_DMR, GPIO_CRL_MODE0_1);
GPIOConfigPin(PORT_YSF, PIN_YSF, GPIO_CRL_MODE0_1);
GPIOConfigPin(PORT_P25, PIN_P25, GPIO_CRL_MODE0_1);
#if !defined(USE_ALTERNATE_NXDN_LEDS)
GPIOConfigPin(PORT_NXDN, PIN_NXDN, GPIO_CRL_MODE0_1);
#endif
#if !defined(USE_ALTERNATE_POCSAG_LEDS)
GPIOConfigPin(PORT_POCSAG, PIN_POCSAG, GPIO_CRL_MODE0_1);
#endif
#if !defined(USE_ALTERNATE_FM_LEDS)
GPIOConfigPin(PORT_FM, PIN_FM, GPIO_CRL_MODE0_1);
#endif
GPIOConfigPin(PORT_RX, PIN_RX, 0);
#if defined(SEND_RSSI_DATA)
GPIOConfigPin(PORT_RSSI, PIN_RSSI, 0);
#endif
GPIOConfigPin(PORT_TX, PIN_TX, 0);
#if defined(EXTERNAL_OSC)
#if defined(STM32F1_POG)
GPIOConfigPin(PORT_EXT_CLK, PIN_EXT_CLK, GPIO_CRL_CNF0_0);
AFIO->MAPR = (AFIO->MAPR & ~AFIO_MAPR_TIM2_REMAP) | AFIO_MAPR_TIM2_REMAP_0;
#endif
#endif
GPIOConfigPin(PORT_USART1_TXD, PIN_USART1_TXD, GPIO_CRL_MODE0_1|GPIO_CRL_CNF0_1);
GPIOConfigPin(PORT_USART1_RXD, PIN_USART1_RXD, GPIO_CRL_CNF0_0);
AFIO->MAPR = (AFIO->MAPR & ~AFIO_MAPR_SWJ_CFG) | AFIO_MAPR_SWJ_CFG_1;
}
static inline void ADCInit()
{
RCC->CFGR = (RCC->CFGR & ~RCC_CFGR_ADCPRE_Msk)
| RCC_CFGR_ADCPRE_DIV6; // ADC clock divided by 6 (72MHz/6 = 12MHz)
RCC->APB2ENR |= RCC_APB2ENR_ADC1EN;
#if defined(SEND_RSSI_DATA)
RCC->APB2ENR |= RCC_APB2ENR_ADC2EN;
#endif
// Init ADCs in dual mode (RSSI)
#if defined(SEND_RSSI_DATA)
ADC1->CR1 = ADC_CR1_DUALMOD_1|ADC_CR1_DUALMOD_2; // Regular simultaneous mode
#endif
// Set sampling time to 7.5 cycles
if (PIN_RX_ADC_CH < 10) {
ADC1->SMPR2 = ADC_SMPR2_SMP0_0 << (3*PIN_RX_ADC_CH);
} else {
ADC1->SMPR1 = ADC_SMPR1_SMP10_0 << (3*PIN_RX_ADC_CH);
}
#if defined(SEND_RSSI_DATA)
if (PIN_RSSI_ADC_CH < 10) {
ADC2->SMPR2 = ADC_SMPR2_SMP0_0 << (3*PIN_RSSI_ADC_CH);
} else {
ADC2->SMPR1 = ADC_SMPR1_SMP10_0 << (3*PIN_RSSI_ADC_CH);
}
#endif
// Set conversion channel (single conversion)
ADC1->SQR3 = PIN_RX_ADC_CH;
#if defined(SEND_RSSI_DATA)
ADC2->SQR3 = PIN_RSSI_ADC_CH;
#endif
// Enable ADC
ADC1->CR2 |= ADC_CR2_ADON;
#if defined(SEND_RSSI_DATA)
// Enable ADC2
ADC2->CR2 |= ADC_CR2_ADON;
#endif
// Start calibration
delay(6*2);
ADC1->CR2 |= ADC_CR2_CAL;
while((ADC1->CR2 & ADC_CR2_CAL) == ADC_CR2_CAL)
;
#if defined(SEND_RSSI_DATA)
ADC2->CR2 |= ADC_CR2_CAL;
while((ADC2->CR2 & ADC_CR2_CAL) == ADC_CR2_CAL)
;
#endif
// Trigger first conversion
ADC1->CR2 |= ADC_CR2_ADON;
#if defined(SEND_RSSI_DATA)
ADC2->CR2 |= ADC_CR2_ADON;
#endif
}
static inline void DACInit()
{
RCC->APB1ENR |= RCC_APB1ENR_DACEN;
DAC->CR = DAC_CR_EN1;
}
static inline void TimerInit()
{
RCC->APB1ENR |= RCC_APB1ENR_TIM2EN;
#if defined(EXTERNAL_OSC)
// Enable external clock, prescaler /4
TIM2->SMCR = TIM_SMCR_ECE | TIM_SMCR_ETPS_1;
#endif
// TIM2 output frequency
TIM2->PSC = 0;
#if defined(EXTERNAL_OSC)
// TimerCount = ExternalOsc
// /4 (external clock prescaler)
// /SAMP_FREQ
TIM2->ARR = (uint16_t) ((EXTERNAL_OSC/(4*SAMP_FREQ)) - 1);
#else
TIM2->ARR = (uint16_t) ((SystemCoreClock/(SAMP_FREQ)) - 1);
#endif
// Enable TIse 1%-tolerance comM2 interrupt
TIM2->DIER = TIM_DIER_UIE;
NVIC_EnableIRQ(TIM2_IRQn);
// Enable TIM2
TIM2->CR1 |= TIM_CR1_CEN;
}
void CIO::initInt()
{
GPIOInit();
ADCInit();
DACInit();
#if defined(STM32F1_POG)
FancyLEDEffect();
#endif
}
void CIO::startInt()
{
TimerInit();
BB_COSLED = 0;
BB_LED = 1;
}
void CIO::interrupt()
{
uint8_t control = MARK_NONE;
uint16_t sample = DC_OFFSET;
#if defined(SEND_RSSI_DATA)
uint16_t rawRSSI = 0U;
#endif
bitband_t eoc = (bitband_t)BITBAND_PERIPH(&ADC1->SR, ADC_SR_EOS_Pos);
bitband_t adon = (bitband_t)BITBAND_PERIPH(&ADC1->CR2, ADC_CR2_ADON_Pos);
#if defined(SEND_RSSI_DATA)
bitband_t rssi_adon = (bitband_t)BITBAND_PERIPH(&ADC2->CR2, ADC_CR2_ADON_Pos);
#endif
if (*eoc) {
// trigger next conversion
*adon = 1;
#if defined(SEND_RSSI_DATA)
*rssi_adon = 1;
#endif
m_txBuffer.get(sample, control);
DAC->DHR12R1 = sample; // Send the value to the DAC
// Read value from ADC1 and ADC2
sample = ADC1->DR; // read conversion result; EOC is cleared by this read
m_rxBuffer.put(sample, control);
#if defined(SEND_RSSI_DATA)
rawRSSI = ADC2->DR;
m_rssiBuffer.put(rawRSSI);
#endif
m_watchdog++;
}
}
bool CIO::getCOSInt()
{
return BB_COS;
}
void CIO::setLEDInt(bool on)
{
BB_LED = !!on;
}
void CIO::setPTTInt(bool on)
{
BB_PTT = !!on;
}
void CIO::setCOSInt(bool on)
{
BB_COSLED = !!on;
}
void CIO::setDStarInt(bool on)
{
BB_DSTAR = !!on;
}
void CIO::setDMRInt(bool on)
{
BB_DMR = !!on;
}
void CIO::setYSFInt(bool on)
{
BB_YSF = !!on;
}
void CIO::setP25Int(bool on)
{
BB_P25 = !!on;
}
void CIO::setNXDNInt(bool on)
{
#if defined(USE_ALTERNATE_NXDN_LEDS)
BB_YSF = !!on;
BB_P25 = !!on;
#else
BB_NXDN = !!on;
#endif
}
void CIO::setPOCSAGInt(bool on)
{
#if defined(USE_ALTERNATE_POCSAG_LEDS)
BB_DSTAR = !!on;
BB_DMR = !!on;
#else
BB_POCSAG = !!on;
#endif
}
void CIO::setFMInt(bool on)
{
#if defined(USE_ALTERNATE_FM_LEDS)
BB_DSTAR = !!on;
BB_YSF = !!on;
#else
BB_FM = !!on;
#endif
}
void CIO::delayInt(unsigned int dly)
{
delay(dly);
}
#endif
-266
View File
@@ -1,266 +0,0 @@
/*
* Copyright (C) 2016,2017,2018,2020 by Jonathan Naylor G4KLX
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "Config.h"
#include "Globals.h"
#include "IO.h"
#if defined(__MK20DX256__) || defined(__MK64FX512__) || defined(__MK66FX1M0__)
#if defined(EXTERNAL_OSC)
#define PIN_LED 3
#else
#define PIN_LED 13
#endif
#define PIN_COS 4
#define PIN_PTT 5
#define PIN_COSLED 6
#define PIN_DSTAR 9
#define PIN_DMR 10
#define PIN_YSF 11
#define PIN_P25 12
#if defined(__MK20DX256__)
#define PIN_NXDN 2
#define PIN_POCSAG 3
#define PIN_FM 4
#else
#define PIN_NXDN 24
#define PIN_POCSAG 25
#define PIN_FM 26
#endif
#define PIN_ADC 5 // A0, Pin 14
#define PIN_RSSI 4 // Teensy 3.5/3.6, A16, Pin 35. Teensy 3.1/3.2, A17, Pin 28
#define PDB_CHnC1_TOS 0x0100
#define PDB_CHnC1_EN 0x0001
const uint16_t DC_OFFSET = 2048U;
extern "C" {
void adc0_isr()
{
io.interrupt();
}
}
void CIO::initInt()
{
// Set up the TX, COS and LED pins
pinMode(PIN_PTT, OUTPUT);
pinMode(PIN_COSLED, OUTPUT);
pinMode(PIN_LED, OUTPUT);
pinMode(PIN_COS, INPUT);
#if defined(MODE_LEDS)
// Set up the mode output pins
pinMode(PIN_DSTAR, OUTPUT);
pinMode(PIN_DMR, OUTPUT);
pinMode(PIN_YSF, OUTPUT);
pinMode(PIN_P25, OUTPUT);
#if !defined(USE_ALTERNATE_NXDN_LEDS)
pinMode(PIN_NXDN, OUTPUT);
#endif
#if !defined(USE_ALTERNATE_POCSAG_LEDS)
pinMode(PIN_POCSAG, OUTPUT);
#endif
#if !defined(USE_ALTERNATE_FM_LEDS)
pinMode(PIN_FM, OUTPUT);
#endif
#endif
}
void CIO::startInt()
{
// Initialise the DAC
SIM_SCGC2 |= SIM_SCGC2_DAC0;
DAC0_C0 = DAC_C0_DACEN | DAC_C0_DACRFS; // 3.3V VDDA is DACREF_2
// Initialise ADC0
SIM_SCGC6 |= SIM_SCGC6_ADC0;
ADC0_CFG1 = ADC_CFG1_ADIV(1) | ADC_CFG1_ADICLK(1) | // Single-ended 12 bits, long sample time
ADC_CFG1_MODE(1) | ADC_CFG1_ADLSMP;
ADC0_CFG2 = ADC_CFG2_MUXSEL | ADC_CFG2_ADLSTS(2); // Select channels ADxxxb
ADC0_SC2 = ADC_SC2_REFSEL(0) | ADC_SC2_ADTRG; // Voltage ref external, hardware trigger
ADC0_SC3 = ADC_SC3_AVGE | ADC_SC3_AVGS(0); // Enable averaging, 4 samples
ADC0_SC3 |= ADC_SC3_CAL;
while (ADC0_SC3 & ADC_SC3_CAL) // Wait for calibration
;
uint16_t sum0 = ADC0_CLPS + ADC0_CLP4 + ADC0_CLP3 + // Plus side gain
ADC0_CLP2 + ADC0_CLP1 + ADC0_CLP0;
sum0 = (sum0 / 2U) | 0x8000U;
ADC0_PG = sum0;
ADC0_SC1A = ADC_SC1_AIEN | PIN_ADC; // Enable ADC interrupt, use A0
NVIC_ENABLE_IRQ(IRQ_ADC0);
#if defined(SEND_RSSI_DATA)
// Initialise ADC1
SIM_SCGC3 |= SIM_SCGC3_ADC1;
ADC1_CFG1 = ADC_CFG1_ADIV(1) | ADC_CFG1_ADICLK(1) | // Single-ended 12 bits, long sample time
ADC_CFG1_MODE(1) | ADC_CFG1_ADLSMP;
ADC1_CFG2 = ADC_CFG2_MUXSEL | ADC_CFG2_ADLSTS(2); // Select channels ADxxxb
ADC1_SC2 = ADC_SC2_REFSEL(0); // Voltage ref external, software trigger
ADC1_SC3 = ADC_SC3_AVGE | ADC_SC3_AVGS(0); // Enable averaging, 4 samples
ADC1_SC3 |= ADC_SC3_CAL;
while (ADC1_SC3 & ADC_SC3_CAL) // Wait for calibration
;
uint16_t sum1 = ADC1_CLPS + ADC1_CLP4 + ADC1_CLP3 + // Plus side gain
ADC1_CLP2 + ADC1_CLP1 + ADC1_CLP0;
sum1 = (sum1 / 2U) | 0x8000U;
ADC1_PG = sum1;
#endif
#if defined(EXTERNAL_OSC)
// Set ADC0 to trigger from the LPTMR at 24 kHz
SIM_SOPT7 = SIM_SOPT7_ADC0ALTTRGEN | // Enable ADC0 alternate trigger
SIM_SOPT7_ADC0TRGSEL(14); // Trigger ADC0 by LPTMR0
CORE_PIN13_CONFIG = PORT_PCR_MUX(3);
SIM_SCGC5 |= SIM_SCGC5_LPTIMER; // Enable Low Power Timer Access
LPTMR0_CSR = 0; // Disable
LPTMR0_PSR = LPTMR_PSR_PBYP; // Bypass prescaler/filter
LPTMR0_CMR = (EXTERNAL_OSC / 24000) - 1; // Frequency divided by CMR + 1
LPTMR0_CSR = LPTMR_CSR_TPS(2) | // Pin: 0=CMP0, 1=xtal, 2=pin13
LPTMR_CSR_TMS; // Mode Select, 0=timer, 1=counter
LPTMR0_CSR |= LPTMR_CSR_TEN; // Enable
#else
// Setup PDB for ADC0 at 24 kHz
SIM_SCGC6 |= SIM_SCGC6_PDB; // Enable PDB clock
PDB0_MOD = (F_BUS / 24000) - 1; // Timer period - 1
PDB0_IDLY = 0; // Interrupt delay
PDB0_CH0C1 = PDB_CHnC1_TOS | PDB_CHnC1_EN; // Enable pre-trigger for ADC0
PDB0_SC = PDB_SC_TRGSEL(15) | PDB_SC_PDBEN | // SW trigger, enable interrupts, continuous mode
PDB_SC_PDBIE | PDB_SC_CONT | PDB_SC_LDOK; // No prescaling
PDB0_SC |= PDB_SC_SWTRIG; // Software trigger (reset and restart counter)
#endif
digitalWrite(PIN_PTT, m_pttInvert ? HIGH : LOW);
digitalWrite(PIN_COSLED, LOW);
digitalWrite(PIN_LED, HIGH);
}
void CIO::interrupt()
{
uint8_t control = MARK_NONE;
uint16_t sample = DC_OFFSET;
m_txBuffer.get(sample, control);
*(int16_t *)&(DAC0_DAT0L) = sample;
if ((ADC0_SC1A & ADC_SC1_COCO) == ADC_SC1_COCO) {
sample = ADC0_RA;
m_rxBuffer.put(sample, control);
}
#if defined(SEND_RSSI_DATA)
if ((ADC1_SC1A & ADC_SC1_COCO) == ADC_SC1_COCO) {
uint16_t rssi = ADC1_RA;
m_rssiBuffer.put(rssi);
} else {
m_rssiBuffer.put(0U);
}
ADC1_SC1A = PIN_RSSI; // Start the next RSSI conversion
#else
m_rssiBuffer.put(0U);
#endif
m_watchdog++;
}
bool CIO::getCOSInt()
{
return digitalRead(PIN_COS) == HIGH;
}
void CIO::setLEDInt(bool on)
{
digitalWrite(PIN_LED, on ? HIGH : LOW);
}
void CIO::setPTTInt(bool on)
{
digitalWrite(PIN_PTT, on ? HIGH : LOW);
}
void CIO::setCOSInt(bool on)
{
digitalWrite(PIN_COSLED, on ? HIGH : LOW);
}
void CIO::setDStarInt(bool on)
{
digitalWrite(PIN_DSTAR, on ? HIGH : LOW);
}
void CIO::setDMRInt(bool on)
{
digitalWrite(PIN_DMR, on ? HIGH : LOW);
}
void CIO::setYSFInt(bool on)
{
digitalWrite(PIN_YSF, on ? HIGH : LOW);
}
void CIO::setP25Int(bool on)
{
digitalWrite(PIN_P25, on ? HIGH : LOW);
}
void CIO::setNXDNInt(bool on)
{
#if defined(USE_ALTERNATE_NXDN_LEDS)
digitalWrite(PIN_YSF, on ? HIGH : LOW);
digitalWrite(PIN_P25, on ? HIGH : LOW);
#else
digitalWrite(PIN_NXDN, on ? HIGH : LOW);
#endif
}
void CIO::setPOCSAGInt(bool on)
{
#if defined(USE_ALTERNATE_POCSAG_LEDS)
digitalWrite(PIN_DSTAR, on ? HIGH : LOW);
digitalWrite(PIN_DMR, on ? HIGH : LOW);
#else
digitalWrite(PIN_POCSAG, on ? HIGH : LOW);
#endif
}
void CIO::setFMInt(bool on)
{
#if defined(USE_ALTERNATE_FM_LEDS)
digitalWrite(PIN_DSTAR, on ? HIGH : LOW);
digitalWrite(PIN_YSF, on ? HIGH : LOW);
#else
digitalWrite(PIN_FM, on ? HIGH : LOW);
#endif
}
void CIO::delayInt(unsigned int dly)
{
delay(dly);
}
#endif
+67
View File
@@ -0,0 +1,67 @@
/*
* Copyright (C) 2016,2017,2018,2020,2021 by Jonathan Naylor G4KLX
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#if !defined(M17DEFINES_H)
#define M17DEFINES_H
const unsigned int M17_RADIO_SYMBOL_LENGTH = 5U; // At 24 kHz sample rate
const unsigned int M17_FRAME_LENGTH_BITS = 384U;
const unsigned int M17_FRAME_LENGTH_BYTES = M17_FRAME_LENGTH_BITS / 8U;
const unsigned int M17_FRAME_LENGTH_SYMBOLS = M17_FRAME_LENGTH_BITS / 2U;
const unsigned int M17_FRAME_LENGTH_SAMPLES = M17_FRAME_LENGTH_SYMBOLS * M17_RADIO_SYMBOL_LENGTH;
const unsigned int M17_SYNC_LENGTH_BITS = 16U;
const unsigned int M17_SYNC_LENGTH_BYTES = M17_SYNC_LENGTH_BITS / 8U;
const unsigned int M17_SYNC_LENGTH_SYMBOLS = M17_SYNC_LENGTH_BITS / 2U;
const unsigned int M17_SYNC_LENGTH_SAMPLES = M17_SYNC_LENGTH_SYMBOLS * M17_RADIO_SYMBOL_LENGTH;
const uint8_t M17_LINK_SETUP_SYNC_BYTES[] = {0x55U, 0xF7U};
const uint8_t M17_STREAM_SYNC_BYTES[] = {0xFFU, 0x5DU};
const uint8_t M17_EOF_SYNC_BYTES[] = {0x55U, 0x5DU};
const uint16_t M17_LINK_SETUP_SYNC_BITS = 0x55F7U;
const uint16_t M17_STREAM_SYNC_BITS = 0xFF5DU;
const uint16_t M17_EOF_SYNC_BITS = 0x555DU;
// 5 5 F 7
// 01 01 01 01 11 11 01 11
// +3 +3 +3 +3 -3 -3 +3 -3
const int8_t M17_LINK_SETUP_SYNC_SYMBOLS_VALUES[] = {+3, +3, +3, +3, -3, -3, +3, -3};
const uint8_t M17_LINK_SETUP_SYNC_SYMBOLS = 0xF2U;
// F F 5 D
// 11 11 11 11 01 01 11 01
// -3 -3 -3 -3 +3 +3 -3 +3
const int8_t M17_STREAM_SYNC_SYMBOLS_VALUES[] = {-3, -3, -3, -3, +3, +3, -3, +3};
const uint8_t M17_STREAM_SYNC_SYMBOLS = 0x0DU;
// 5 5 5 D
// 01 01 01 01 01 01 11 01
// +3 +3 +3 +3 +3 +3 -3 +3
const int8_t M17_EOF_SYNC_SYMBOLS_VALUES[] = {+3, +3, +3, +3, +3, +3, -3, +3};
const uint8_t M17_EOF_SYNC_SYMBOLS = 0xFDU;
#endif
+485
View File
@@ -0,0 +1,485 @@
/*
* Copyright (C) 2009-2017,2020,2021 by Jonathan Naylor G4KLX
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "Config.h"
#if defined(MODE_M17)
#include "Globals.h"
#include "M17RX.h"
#include "Utils.h"
const q15_t SCALING_FACTOR = 18750; // Q15(0.55)
const uint8_t MAX_SYNC_BIT_START_ERRS = 0U;
const uint8_t MAX_SYNC_BIT_RUN_ERRS = 2U;
const uint8_t MAX_SYNC_SYMBOL_START_ERRS = 0U;
const uint8_t MAX_SYNC_SYMBOL_RUN_ERRS = 1U;
const uint8_t BIT_MASK_TABLE[] = {0x80U, 0x40U, 0x20U, 0x10U, 0x08U, 0x04U, 0x02U, 0x01U};
#define WRITE_BIT1(p,i,b) p[(i)>>3] = (b) ? (p[(i)>>3] | BIT_MASK_TABLE[(i)&7]) : (p[(i)>>3] & ~BIT_MASK_TABLE[(i)&7])
const uint8_t NOAVEPTR = 99U;
const uint16_t NOENDPTR = 9999U;
const unsigned int MAX_SYNC_FRAMES = 3U + 1U;
CM17RX::CM17RX() :
m_state(M17RXS_NONE),
m_bitBuffer(),
m_buffer(),
m_bitPtr(0U),
m_dataPtr(0U),
m_startPtr(NOENDPTR),
m_endPtr(NOENDPTR),
m_syncPtr(NOENDPTR),
m_minSyncPtr(NOENDPTR),
m_maxSyncPtr(NOENDPTR),
m_maxCorr(0),
m_lostCount(0U),
m_countdown(0U),
m_nextState(M17RXS_NONE),
m_centre(),
m_centreVal(0),
m_threshold(),
m_thresholdVal(0),
m_averagePtr(NOAVEPTR),
m_rssiAccum(0U),
m_rssiCount(0U)
{
}
void CM17RX::reset()
{
m_state = M17RXS_NONE;
m_dataPtr = 0U;
m_bitPtr = 0U;
m_maxCorr = 0;
m_averagePtr = NOAVEPTR;
m_startPtr = NOENDPTR;
m_endPtr = NOENDPTR;
m_syncPtr = NOENDPTR;
m_minSyncPtr = NOENDPTR;
m_maxSyncPtr = NOENDPTR;
m_centreVal = 0;
m_thresholdVal = 0;
m_lostCount = 0U;
m_countdown = 0U;
m_nextState = M17RXS_NONE;
m_rssiAccum = 0U;
m_rssiCount = 0U;
}
void CM17RX::samples(const q15_t* samples, uint16_t* rssi, uint8_t length)
{
for (uint8_t i = 0U; i < length; i++) {
q15_t sample = samples[i];
m_rssiAccum += rssi[i];
m_rssiCount++;
m_bitBuffer[m_bitPtr] <<= 1;
if (sample < 0)
m_bitBuffer[m_bitPtr] |= 0x01U;
m_buffer[m_dataPtr] = sample;
switch (m_state) {
case M17RXS_LINK_SETUP:
case M17RXS_STREAM:
processData(sample);
break;
default:
processNone(sample);
break;
}
m_dataPtr++;
if (m_dataPtr >= M17_FRAME_LENGTH_SAMPLES)
m_dataPtr = 0U;
m_bitPtr++;
if (m_bitPtr >= M17_RADIO_SYMBOL_LENGTH)
m_bitPtr = 0U;
}
}
void CM17RX::processNone(q15_t sample)
{
bool ret1 = correlateSync(M17_LINK_SETUP_SYNC_SYMBOLS, M17_LINK_SETUP_SYNC_SYMBOLS_VALUES, M17_LINK_SETUP_SYNC_BYTES, MAX_SYNC_SYMBOL_START_ERRS, MAX_SYNC_BIT_START_ERRS);
bool ret2 = correlateSync(M17_STREAM_SYNC_SYMBOLS, M17_STREAM_SYNC_SYMBOLS_VALUES, M17_STREAM_SYNC_BYTES, MAX_SYNC_SYMBOL_START_ERRS, MAX_SYNC_BIT_START_ERRS);
if (ret1 || ret2) {
// On the first sync, start the countdown to the state change
if (m_countdown == 0U) {
m_rssiAccum = 0U;
m_rssiCount = 0U;
io.setDecode(true);
io.setADCDetection(true);
m_averagePtr = NOAVEPTR;
m_countdown = 5U;
if (ret1) m_nextState = M17RXS_LINK_SETUP;
if (ret2) m_nextState = M17RXS_STREAM;
}
}
if (m_countdown > 0U)
m_countdown--;
if (m_countdown == 1U) {
m_minSyncPtr = m_syncPtr + M17_FRAME_LENGTH_SAMPLES - 1U;
if (m_minSyncPtr >= M17_FRAME_LENGTH_SAMPLES)
m_minSyncPtr -= M17_FRAME_LENGTH_SAMPLES;
m_maxSyncPtr = m_syncPtr + 1U;
if (m_maxSyncPtr >= M17_FRAME_LENGTH_SAMPLES)
m_maxSyncPtr -= M17_FRAME_LENGTH_SAMPLES;
m_state = m_nextState;
m_countdown = 0U;
m_nextState = M17RXS_NONE;
}
}
void CM17RX::processData(q15_t sample)
{
bool eof = false;
if (m_minSyncPtr < m_maxSyncPtr) {
if (m_dataPtr >= m_minSyncPtr && m_dataPtr <= m_maxSyncPtr) {
bool ret = correlateSync(M17_STREAM_SYNC_SYMBOLS, M17_STREAM_SYNC_SYMBOLS_VALUES, M17_STREAM_SYNC_BYTES, MAX_SYNC_SYMBOL_RUN_ERRS, MAX_SYNC_BIT_RUN_ERRS);
eof = correlateSync(M17_EOF_SYNC_SYMBOLS, M17_EOF_SYNC_SYMBOLS_VALUES, M17_EOF_SYNC_BYTES, MAX_SYNC_SYMBOL_RUN_ERRS, MAX_SYNC_BIT_RUN_ERRS);
if (ret) m_state = M17RXS_STREAM;
}
} else {
if (m_dataPtr >= m_minSyncPtr || m_dataPtr <= m_maxSyncPtr) {
bool ret = correlateSync(M17_STREAM_SYNC_SYMBOLS, M17_STREAM_SYNC_SYMBOLS_VALUES, M17_STREAM_SYNC_BYTES, MAX_SYNC_SYMBOL_RUN_ERRS, MAX_SYNC_BIT_RUN_ERRS);
eof = correlateSync(M17_EOF_SYNC_SYMBOLS, M17_EOF_SYNC_SYMBOLS_VALUES, M17_EOF_SYNC_BYTES, MAX_SYNC_SYMBOL_RUN_ERRS, MAX_SYNC_BIT_RUN_ERRS);
if (ret) m_state = M17RXS_STREAM;
}
}
if (eof) {
DEBUG4("M17RX: eof sync found pos/centre/threshold", m_syncPtr, m_centreVal, m_thresholdVal);
io.setDecode(false);
io.setADCDetection(false);
serial.writeM17EOT();
m_state = M17RXS_NONE;
m_endPtr = NOENDPTR;
m_averagePtr = NOAVEPTR;
m_countdown = 0U;
m_nextState = M17RXS_NONE;
m_maxCorr = 0;
}
if (m_dataPtr == m_endPtr) {
// Only update the centre and threshold if they are from a good sync
if (m_lostCount == MAX_SYNC_FRAMES) {
m_minSyncPtr = m_syncPtr + M17_FRAME_LENGTH_SAMPLES - 1U;
if (m_minSyncPtr >= M17_FRAME_LENGTH_SAMPLES)
m_minSyncPtr -= M17_FRAME_LENGTH_SAMPLES;
m_maxSyncPtr = m_syncPtr + 1U;
if (m_maxSyncPtr >= M17_FRAME_LENGTH_SAMPLES)
m_maxSyncPtr -= M17_FRAME_LENGTH_SAMPLES;
}
calculateLevels(m_startPtr, M17_FRAME_LENGTH_SYMBOLS);
switch (m_state) {
case M17RXS_LINK_SETUP:
DEBUG4("M17RX: link setup sync found pos/centre/threshold", m_syncPtr, m_centreVal, m_thresholdVal);
break;
case M17RXS_STREAM:
DEBUG4("M17RX: stream sync found pos/centre/threshold", m_syncPtr, m_centreVal, m_thresholdVal);
break;
default:
break;
}
uint8_t frame[M17_FRAME_LENGTH_BYTES + 3U];
samplesToBits(m_startPtr, M17_FRAME_LENGTH_SYMBOLS, frame, 8U, m_centreVal, m_thresholdVal);
// We've not seen a stream sync for too long, signal RXLOST and change to RX_NONE
m_lostCount--;
if (m_lostCount == 0U) {
DEBUG1("M17RX: sync timed out, lost lock");
io.setDecode(false);
io.setADCDetection(false);
serial.writeM17Lost();
m_state = M17RXS_NONE;
m_endPtr = NOENDPTR;
m_averagePtr = NOAVEPTR;
m_countdown = 0U;
m_nextState = M17RXS_NONE;
m_maxCorr = 0;
} else {
frame[0U] = m_lostCount == (MAX_SYNC_FRAMES - 1U) ? 0x01U : 0x00U;
switch (m_state) {
case M17RXS_LINK_SETUP:
writeRSSILinkSetup(frame);
break;
case M17RXS_STREAM:
writeRSSIStream(frame);
break;
default:
break;
}
m_maxCorr = 0;
m_nextState = M17RXS_NONE;
}
}
}
bool CM17RX::correlateSync(uint8_t syncSymbols, const int8_t* syncSymbolValues, const uint8_t* syncBytes, uint8_t maxSymbolErrs, uint8_t maxBitErrs)
{
if (countBits8(m_bitBuffer[m_bitPtr] ^ syncSymbols) <= maxSymbolErrs) {
uint16_t ptr = m_dataPtr + M17_FRAME_LENGTH_SAMPLES - M17_SYNC_LENGTH_SAMPLES + M17_RADIO_SYMBOL_LENGTH;
if (ptr >= M17_FRAME_LENGTH_SAMPLES)
ptr -= M17_FRAME_LENGTH_SAMPLES;
q31_t corr = 0;
q15_t min = 16000;
q15_t max = -16000;
for (uint8_t i = 0U; i < M17_SYNC_LENGTH_SYMBOLS; i++) {
q15_t val = m_buffer[ptr];
if (val > max)
max = val;
if (val < min)
min = val;
switch (syncSymbolValues[i]) {
case +3:
corr -= (val + val + val);
break;
case +1:
corr -= val;
break;
case -1:
corr += val;
break;
default: // -3
corr += (val + val + val);
break;
}
ptr += M17_RADIO_SYMBOL_LENGTH;
if (ptr >= M17_FRAME_LENGTH_SAMPLES)
ptr -= M17_FRAME_LENGTH_SAMPLES;
}
if (corr > m_maxCorr) {
if (m_averagePtr == NOAVEPTR) {
m_centreVal = (max + min) >> 1;
q31_t v1 = (max - m_centreVal) * SCALING_FACTOR;
m_thresholdVal = q15_t(v1 >> 15);
}
uint16_t startPtr = m_dataPtr + M17_FRAME_LENGTH_SAMPLES - M17_SYNC_LENGTH_SAMPLES + M17_RADIO_SYMBOL_LENGTH;
if (startPtr >= M17_FRAME_LENGTH_SAMPLES)
startPtr -= M17_FRAME_LENGTH_SAMPLES;
uint8_t sync[M17_SYNC_LENGTH_BYTES];
samplesToBits(startPtr, M17_SYNC_LENGTH_SYMBOLS, sync, 0U, m_centreVal, m_thresholdVal);
uint8_t errs = 0U;
for (uint8_t i = 0U; i < M17_SYNC_LENGTH_BYTES; i++)
errs += countBits8(sync[i] ^ syncBytes[i]);
if (errs <= maxBitErrs) {
m_maxCorr = corr;
m_lostCount = MAX_SYNC_FRAMES;
m_syncPtr = m_dataPtr;
m_startPtr = startPtr;
m_endPtr = m_dataPtr + M17_FRAME_LENGTH_SAMPLES - M17_SYNC_LENGTH_SAMPLES - 1U;
if (m_endPtr >= M17_FRAME_LENGTH_SAMPLES)
m_endPtr -= M17_FRAME_LENGTH_SAMPLES;
return true;
}
}
}
return false;
}
void CM17RX::calculateLevels(uint16_t start, uint16_t count)
{
q15_t maxPos = -16000;
q15_t minPos = 16000;
q15_t maxNeg = 16000;
q15_t minNeg = -16000;
for (uint16_t i = 0U; i < count; i++) {
q15_t sample = m_buffer[start];
if (sample > 0) {
if (sample > maxPos)
maxPos = sample;
if (sample < minPos)
minPos = sample;
} else {
if (sample < maxNeg)
maxNeg = sample;
if (sample > minNeg)
minNeg = sample;
}
start += M17_RADIO_SYMBOL_LENGTH;
if (start >= M17_FRAME_LENGTH_SAMPLES)
start -= M17_FRAME_LENGTH_SAMPLES;
}
q15_t posThresh = (maxPos + minPos) >> 1;
q15_t negThresh = (maxNeg + minNeg) >> 1;
q15_t centre = (posThresh + negThresh) >> 1;
q15_t threshold = posThresh - centre;
DEBUG5("M17RX: pos/neg/centre/threshold", posThresh, negThresh, centre, threshold);
if (m_averagePtr == NOAVEPTR) {
for (uint8_t i = 0U; i < 16U; i++) {
m_centre[i] = centre;
m_threshold[i] = threshold;
}
m_averagePtr = 0U;
} else {
m_centre[m_averagePtr] = centre;
m_threshold[m_averagePtr] = threshold;
m_averagePtr++;
if (m_averagePtr >= 16U)
m_averagePtr = 0U;
}
m_centreVal = 0;
m_thresholdVal = 0;
for (uint8_t i = 0U; i < 16U; i++) {
m_centreVal += m_centre[i];
m_thresholdVal += m_threshold[i];
}
m_centreVal >>= 4;
m_thresholdVal >>= 4;
}
void CM17RX::samplesToBits(uint16_t start, uint16_t count, uint8_t* buffer, uint16_t offset, q15_t centre, q15_t threshold)
{
for (uint16_t i = 0U; i < count; i++) {
q15_t sample = m_buffer[start] - centre;
if (sample < -threshold) {
WRITE_BIT1(buffer, offset, false);
offset++;
WRITE_BIT1(buffer, offset, true);
offset++;
} else if (sample < 0) {
WRITE_BIT1(buffer, offset, false);
offset++;
WRITE_BIT1(buffer, offset, false);
offset++;
} else if (sample < threshold) {
WRITE_BIT1(buffer, offset, true);
offset++;
WRITE_BIT1(buffer, offset, false);
offset++;
} else {
WRITE_BIT1(buffer, offset, true);
offset++;
WRITE_BIT1(buffer, offset, true);
offset++;
}
start += M17_RADIO_SYMBOL_LENGTH;
if (start >= M17_FRAME_LENGTH_SAMPLES)
start -= M17_FRAME_LENGTH_SAMPLES;
}
}
void CM17RX::writeRSSILinkSetup(uint8_t* data)
{
#if defined(SEND_RSSI_DATA)
if (m_rssiCount > 0U) {
uint16_t rssi = m_rssiAccum / m_rssiCount;
data[49U] = (rssi >> 8) & 0xFFU;
data[50U] = (rssi >> 0) & 0xFFU;
serial.writeM17LinkSetup(data, M17_FRAME_LENGTH_BYTES + 3U);
} else {
serial.writeM17LinkSetup(data, M17_FRAME_LENGTH_BYTES + 1U);
}
#else
serial.writeM17LinkSetup(data, M17_FRAME_LENGTH_BYTES + 1U);
#endif
m_rssiAccum = 0U;
m_rssiCount = 0U;
}
void CM17RX::writeRSSIStream(uint8_t* data)
{
#if defined(SEND_RSSI_DATA)
if (m_rssiCount > 0U) {
uint16_t rssi = m_rssiAccum / m_rssiCount;
data[49U] = (rssi >> 8) & 0xFFU;
data[50U] = (rssi >> 0) & 0xFFU;
serial.writeM17Stream(data, M17_FRAME_LENGTH_BYTES + 3U);
} else {
serial.writeM17Stream(data, M17_FRAME_LENGTH_BYTES + 1U);
}
#else
serial.writeM17Stream(data, M17_FRAME_LENGTH_BYTES + 1U);
#endif
m_rssiAccum = 0U;
m_rssiCount = 0U;
}
#endif
+77
View File
@@ -0,0 +1,77 @@
/*
* Copyright (C) 2015,2016,2017,2020,2021 by Jonathan Naylor G4KLX
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "Config.h"
#if defined(MODE_M17)
#if !defined(M17RX_H)
#define M17RX_H
#include "M17Defines.h"
enum M17RX_STATE {
M17RXS_NONE,
M17RXS_LINK_SETUP,
M17RXS_STREAM
};
class CM17RX {
public:
CM17RX();
void samples(const q15_t* samples, uint16_t* rssi, uint8_t length);
void reset();
private:
M17RX_STATE m_state;
uint8_t m_bitBuffer[M17_RADIO_SYMBOL_LENGTH];
q15_t m_buffer[M17_FRAME_LENGTH_SAMPLES];
uint16_t m_bitPtr;
uint16_t m_dataPtr;
uint16_t m_startPtr;
uint16_t m_endPtr;
uint16_t m_syncPtr;
uint16_t m_minSyncPtr;
uint16_t m_maxSyncPtr;
q31_t m_maxCorr;
uint16_t m_lostCount;
uint8_t m_countdown;
M17RX_STATE m_nextState;
q15_t m_centre[16U];
q15_t m_centreVal;
q15_t m_threshold[16U];
q15_t m_thresholdVal;
uint8_t m_averagePtr;
uint32_t m_rssiAccum;
uint16_t m_rssiCount;
void processNone(q15_t sample);
void processData(q15_t sample);
bool correlateSync(uint8_t syncSymbols, const int8_t* syncSymbolValues, const uint8_t* syncBytes, uint8_t maxSymbolErrs, uint8_t maxBitErrs);
void calculateLevels(uint16_t start, uint16_t count);
void samplesToBits(uint16_t start, uint16_t count, uint8_t* buffer, uint16_t offset, q15_t centre, q15_t threshold);
void writeRSSILinkSetup(uint8_t* data);
void writeRSSIStream(uint8_t* data);
};
#endif
#endif
+190
View File
@@ -0,0 +1,190 @@
/*
* Copyright (C) 2009-2018,2020,2021 by Jonathan Naylor G4KLX
* Copyright (C) 2017 by Andy Uribe CA6JAU
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "Config.h"
#if defined(MODE_M17)
#include "Globals.h"
#include "M17TX.h"
#include "M17Defines.h"
// Generated using rcosdesign(0.5, 8, 5, 'sqrt') in MATLAB
static q15_t RRC_0_5_FILTER[] = {0, 0, 0, 0, -290, -174, 142, 432, 438, 90, -387, -561, -155, 658, 1225, 767,
-980, -3326, -4648, -3062, 2527, 11552, 21705, 29724, 32767, 29724, 21705,
11552, 2527, -3062, -4648, -3326, -980, 767, 1225, 658, -155, -561, -387, 90,
438, 432, 142, -174, -290}; // numTaps = 45, L = 5
const uint16_t RRC_0_5_FILTER_PHASE_LEN = 9U; // phaseLength = numTaps/L
const q15_t M17_LEVELA = 1481;
const q15_t M17_LEVELB = 494;
const q15_t M17_LEVELC = -494;
const q15_t M17_LEVELD = -1481;
const uint8_t M17_START_SYNC = 0x77U;
const uint8_t M17_END_SYNC = 0xFFU;
const uint8_t M17_HANG = 0x00U;
CM17TX::CM17TX() :
m_buffer(TX_BUFFER_LEN),
m_modFilter(),
m_modState(),
m_poBuffer(),
m_poLen(0U),
m_poPtr(0U),
m_txDelay(240U), // 200ms
m_txHang(4800U), // 4s
m_txCount(0U)
{
::memset(m_modState, 0x00U, 16U * sizeof(q15_t));
m_modFilter.L = M17_RADIO_SYMBOL_LENGTH;
m_modFilter.phaseLength = RRC_0_5_FILTER_PHASE_LEN;
m_modFilter.pCoeffs = RRC_0_5_FILTER;
m_modFilter.pState = m_modState;
}
void CM17TX::process()
{
// If we have M17 data to transmit, do so.
if (m_poLen == 0U && m_buffer.getData() > 0U) {
if (!m_tx) {
for (uint16_t i = 0U; i < m_txDelay; i++)
m_poBuffer[m_poLen++] = M17_START_SYNC;
} else {
for (uint8_t i = 0U; i < M17_FRAME_LENGTH_BYTES; i++) {
uint8_t c = 0U;
m_buffer.get(c);
m_poBuffer[m_poLen++] = c;
}
}
m_poPtr = 0U;
}
if (m_poLen > 0U) {
// Transmit M17 data.
uint16_t space = io.getSpace();
while (space > (4U * M17_RADIO_SYMBOL_LENGTH)) {
uint8_t c = m_poBuffer[m_poPtr++];
writeByte(c);
// Reduce space and reset the hang timer.
space -= 4U * M17_RADIO_SYMBOL_LENGTH;
if (m_duplex)
m_txCount = m_txHang;
if (m_poPtr >= m_poLen) {
m_poPtr = 0U;
m_poLen = 0U;
return;
}
}
} else if (m_txCount > 0U) {
// Transmit silence until the hang timer has expired.
uint16_t space = io.getSpace();
while (space > (4U * M17_RADIO_SYMBOL_LENGTH)) {
writeSilence();
space -= 4U * M17_RADIO_SYMBOL_LENGTH;
m_txCount--;
if (m_txCount == 0U)
return;
}
}
}
uint8_t CM17TX::writeData(const uint8_t* data, uint8_t length)
{
if (length != (M17_FRAME_LENGTH_BYTES + 1U))
return 4U;
uint16_t space = m_buffer.getSpace();
if (space < M17_FRAME_LENGTH_BYTES)
return 5U;
for (uint8_t i = 0U; i < M17_FRAME_LENGTH_BYTES; i++)
m_buffer.put(data[i + 1U]);
return 0U;
}
void CM17TX::writeByte(uint8_t c)
{
q15_t inBuffer[4U];
q15_t outBuffer[M17_RADIO_SYMBOL_LENGTH * 4U];
const uint8_t MASK = 0xC0U;
for (uint8_t i = 0U; i < 4U; i++, c <<= 2) {
switch (c & MASK) {
case 0xC0U:
inBuffer[i] = M17_LEVELA;
break;
case 0x80U:
inBuffer[i] = M17_LEVELB;
break;
case 0x00U:
inBuffer[i] = M17_LEVELC;
break;
default:
inBuffer[i] = M17_LEVELD;
break;
}
}
::arm_fir_interpolate_q15(&m_modFilter, inBuffer, outBuffer, 4U);
io.write(STATE_M17, outBuffer, M17_RADIO_SYMBOL_LENGTH * 4U);
}
void CM17TX::writeSilence()
{
q15_t inBuffer[4U] = {0, 0, 0, 0};
q15_t outBuffer[M17_RADIO_SYMBOL_LENGTH * 4U];
::arm_fir_interpolate_q15(&m_modFilter, inBuffer, outBuffer, 4U);
io.write(STATE_M17, outBuffer, M17_RADIO_SYMBOL_LENGTH * 4U);
}
void CM17TX::setTXDelay(uint8_t delay)
{
m_txDelay = 600U + uint16_t(delay) * 12U; // 500ms + tx delay
if (m_txDelay > 1200U)
m_txDelay = 1200U;
}
uint8_t CM17TX::getSpace() const
{
return m_buffer.getSpace() / M17_FRAME_LENGTH_BYTES;
}
void CM17TX::setParams(uint8_t txHang)
{
m_txHang = txHang * 1200U;
}
#endif
+60
View File
@@ -0,0 +1,60 @@
/*
* Copyright (C) 2015,2016,2017,2020 by Jonathan Naylor G4KLX
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "Config.h"
#if defined(MODE_M17)
#if !defined(M17TX_H)
#define M17TX_H
#include "RingBuffer.h"
class CM17TX {
public:
CM17TX();
uint8_t writeData(const uint8_t* data, uint8_t length);
void process();
void setTXDelay(uint8_t delay);
uint8_t getSpace() const;
void setParams(uint8_t txHang);
private:
CRingBuffer<uint8_t> m_buffer;
arm_fir_interpolate_instance_q15 m_modFilter;
q15_t m_modState[16U]; // blockSize + phaseLength - 1, 4 + 9 - 1 plus some spare
uint8_t m_poBuffer[1200U];
uint16_t m_poLen;
uint16_t m_poPtr;
uint16_t m_txDelay;
uint32_t m_txHang;
uint32_t m_txCount;
void writeByte(uint8_t c);
void writeSilence();
};
#endif
#endif
+105 -28
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2015,2016,2017,2018,2020 by Jonathan Naylor G4KLX
* Copyright (C) 2015,2016,2017,2018,2020,2021 by Jonathan Naylor G4KLX
* Copyright (C) 2016 by Mathis Schmieder DB9MAT
* Copyright (C) 2016 by Colin Durbridge G4EML
*
@@ -31,44 +31,77 @@ bool m_dmrEnable = true;
bool m_ysfEnable = true;
bool m_p25Enable = true;
bool m_nxdnEnable = true;
bool m_m17Enable = true;
bool m_pocsagEnable = true;
bool m_fmEnable = true;
bool m_ax25Enable = true;
bool m_duplex = true;
bool m_tx = false;
bool m_dcd = false;
CDStarRX dstarRX;
CDStarTX dstarTX;
CDMRIdleRX dmrIdleRX;
CDMRRX dmrRX;
CDMRTX dmrTX;
CDMRDMORX dmrDMORX;
CDMRDMOTX dmrDMOTX;
CYSFRX ysfRX;
CYSFTX ysfTX;
CP25RX p25RX;
CP25TX p25TX;
CNXDNRX nxdnRX;
CNXDNTX nxdnTX;
CPOCSAGTX pocsagTX;
CFM fm;
#if defined(MODE_DSTAR)
CDStarRX dstarRX;
CDStarTX dstarTX;
CCalDStarRX calDStarRX;
CCalDStarTX calDStarTX;
CCalDMR calDMR;
CCalP25 calP25;
CCalNXDN calNXDN;
CCalPOCSAG calPOCSAG;
CCalRSSI calRSSI;
#endif
#if defined(MODE_DMR)
CDMRIdleRX dmrIdleRX;
CDMRRX dmrRX;
CDMRTX dmrTX;
CDMRDMORX dmrDMORX;
CDMRDMOTX dmrDMOTX;
CCalDMR calDMR;
#endif
#if defined(MODE_YSF)
CYSFRX ysfRX;
CYSFTX ysfTX;
#endif
#if defined(MODE_P25)
CP25RX p25RX;
CP25TX p25TX;
CCalP25 calP25;
#endif
#if defined(MODE_NXDN)
CNXDNRX nxdnRX;
CNXDNTX nxdnTX;
CCalNXDN calNXDN;
#endif
#if defined(MODE_M17)
CM17RX m17RX;
CM17TX m17TX;
CCalM17 calM17;
#endif
#if defined(MODE_POCSAG)
CPOCSAGTX pocsagTX;
CCalPOCSAG calPOCSAG;
#endif
#if defined(MODE_FM)
CFM fm;
CCalFM calFM;
#endif
#if defined(MODE_AX25)
CAX25RX ax25RX;
CAX25TX ax25TX;
#endif
CCalRSSI calRSSI;
CCWIdTX cwIdTX;
@@ -87,45 +120,89 @@ void loop()
io.process();
// The following is for transmitting
#if defined(MODE_DSTAR)
if (m_dstarEnable && m_modemState == STATE_DSTAR)
dstarTX.process();
#endif
#if defined(MODE_DMR)
if (m_dmrEnable && m_modemState == STATE_DMR) {
if (m_duplex)
dmrTX.process();
else
dmrDMOTX.process();
}
#endif
#if defined(MODE_YSF)
if (m_ysfEnable && m_modemState == STATE_YSF)
ysfTX.process();
#endif
#if defined(MODE_P25)
if (m_p25Enable && m_modemState == STATE_P25)
p25TX.process();
#endif
#if defined(MODE_NXDN)
if (m_nxdnEnable && m_modemState == STATE_NXDN)
nxdnTX.process();
#endif
#if defined(MODE_M17)
if (m_m17Enable && m_modemState == STATE_M17)
m17TX.process();
#endif
#if defined(MODE_POCSAG)
if (m_pocsagEnable && (m_modemState == STATE_POCSAG || pocsagTX.busy()))
pocsagTX.process();
#endif
#if defined(MODE_AX25)
if (m_ax25Enable && (m_modemState == STATE_IDLE || m_modemState == STATE_FM))
ax25TX.process();
#endif
#if defined(MODE_FM)
if (m_fmEnable && m_modemState == STATE_FM)
fm.process();
#endif
#if defined(MODE_DSTAR)
if (m_modemState == STATE_DSTARCAL)
calDStarTX.process();
#endif
#if defined(MODE_DMR)
if (m_modemState == STATE_DMRCAL || m_modemState == STATE_LFCAL || m_modemState == STATE_DMRCAL1K || m_modemState == STATE_DMRDMO1K)
calDMR.process();
#endif
#if defined(MODE_FM)
if (m_modemState == STATE_FMCAL10K || m_modemState == STATE_FMCAL12K || m_modemState == STATE_FMCAL15K || m_modemState == STATE_FMCAL20K || m_modemState == STATE_FMCAL25K || m_modemState == STATE_FMCAL30K)
calFM.process();
#endif
#if defined(MODE_P25)
if (m_modemState == STATE_P25CAL1K)
calP25.process();
#endif
#if defined(MODE_NXDN)
if (m_modemState == STATE_NXDNCAL1K)
calNXDN.process();
#endif
#if defined(MODE_M17)
if (m_modemState == STATE_M17CAL)
calM17.process();
#endif
#if defined(MODE_POCSAG)
if (m_modemState == STATE_POCSAGCAL)
calPOCSAG.process();
#endif
if (m_modemState == STATE_IDLE)
cwIdTX.process();
-129
View File
@@ -1,129 +0,0 @@
/*
* Copyright (C) 2015,2016,2017,2018,2020 by Jonathan Naylor G4KLX
* Copyright (C) 2016 by Colin Durbridge G4EML
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "Config.h"
#include "Globals.h"
// Global variables
MMDVM_STATE m_modemState = STATE_IDLE;
bool m_dstarEnable = true;
bool m_dmrEnable = true;
bool m_ysfEnable = true;
bool m_p25Enable = true;
bool m_nxdnEnable = true;
bool m_pocsagEnable = true;
bool m_fmEnable = true;
bool m_duplex = true;
bool m_tx = false;
bool m_dcd = false;
CDStarRX dstarRX;
CDStarTX dstarTX;
CDMRIdleRX dmrIdleRX;
CDMRRX dmrRX;
CDMRTX dmrTX;
CDMRDMORX dmrDMORX;
CDMRDMOTX dmrDMOTX;
CYSFRX ysfRX;
CYSFTX ysfTX;
CP25RX p25RX;
CP25TX p25TX;
CNXDNRX nxdnRX;
CNXDNTX nxdnTX;
CPOCSAGTX pocsagTX;
CFM fm;
CCalDStarRX calDStarRX;
CCalDStarTX calDStarTX;
CCalDMR calDMR;
CCalP25 calP25;
CCalNXDN calNXDN;
CCalPOCSAG calPOCSAG;
CCalRSSI calRSSI;
CCWIdTX cwIdTX;
CSerialPort serial;
CIO io;
void setup()
{
serial.start();
}
void loop()
{
serial.process();
io.process();
// The following is for transmitting
if (m_dstarEnable && m_modemState == STATE_DSTAR)
dstarTX.process();
if (m_dmrEnable && m_modemState == STATE_DMR) {
if (m_duplex)
dmrTX.process();
else
dmrDMOTX.process();
}
if (m_ysfEnable && m_modemState == STATE_YSF)
ysfTX.process();
if (m_p25Enable && m_modemState == STATE_P25)
p25TX.process();
if (m_nxdnEnable && m_modemState == STATE_NXDN)
nxdnTX.process();
if (m_pocsagEnable && (m_modemState == STATE_POCSAG || pocsagTX.busy()))
pocsagTX.process();
if (m_fmEnable && m_modemState == STATE_FM)
fm.process();
if (m_modemState == STATE_DSTARCAL)
calDStarTX.process();
if (m_modemState == STATE_DMRCAL || m_modemState == STATE_LFCAL || m_modemState == STATE_DMRCAL1K || m_modemState == STATE_DMRDMO1K)
calDMR.process();
if (m_modemState == STATE_P25CAL1K)
calP25.process();
if (m_modemState == STATE_NXDNCAL1K)
calNXDN.process();
if (m_modemState == STATE_POCSAGCAL)
calPOCSAG.process();
if (m_modemState == STATE_IDLE)
cwIdTX.process();
}
-338
View File
@@ -1,338 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<Project version="2G - 1.7.8" name="MMDVM_STM32F4xx">
<Target name="MMDVM_Discovery_407" isCurrent="1">
<Device manufacturerId="9" manufacturerName="ST" chipId="344" chipName="STM32F407VG" boardId="" boardName=""/>
<BuildOption>
<Compile>
<Option name="OptimizationLevel" value="4"/>
<Option name="UseFPU" value="0"/>
<Option name="UserEditCompiler" value=""/>
<Option name="SupportCPlusplus" value="1"/>
<Option name="FPU" value="2"/>
<Includepaths>
<Includepath path="."/>
</Includepaths>
<DefinedSymbols>
<Define name="STM32F4XX"/>
<Define name="USE_STDPERIPH_DRIVER"/>
<Define name="__ASSEMBLY__"/>
<Define name="SUPPORT_CPLUSPLUS"/>
<Define name="STM32F40_41xxx"/>
<Define name="HSE_VALUE=8000000"/>
<Define name="STM32F4_DISCOVERY"/>
<Define name="__FPU_USED"/>
</DefinedSymbols>
</Compile>
<Link useDefault="0">
<Option name="DiscardUnusedSection" value="0"/>
<Option name="UserEditLinkder" value=""/>
<Option name="UseMemoryLayout" value="0"/>
<Option name="nostartfiles" value="1"/>
<Option name="LTO" value="0"/>
<Option name="IsNewStartupCode" value="1"/>
<Option name="Library" value="Semihosting"/>
<Option name="UserEditLinker" value="-lstdc++; --specs=nano.specs;"/>
<LinkedLibraries>
<Libset dir="stm32f4xx_lib\cmsis\lib\gcc\" libs="arm_cortexm4lf_math"/>
</LinkedLibraries>
<MemoryAreas debugInFlashNotRAM="1">
<Memory name="IROM1" type="ReadOnly" size="0x00100000" startValue="0x08000000"/>
<Memory name="IRAM1" type="ReadWrite" size="0x00020000" startValue="0x20000000"/>
<Memory name="IROM2" type="ReadOnly" size="" startValue=""/>
<Memory name="IRAM2" type="ReadWrite" size="0x00010000" startValue="0x10000000"/>
</MemoryAreas>
<LocateLinkFile path="./stm32f4xx_link.ld" type="0"/>
</Link>
<Output>
<Option name="OutputFileType" value="0"/>
<Option name="Path" value="./"/>
<Option name="Name" value="MMDVM_DIS"/>
<Option name="HEX" value="1"/>
<Option name="BIN" value="1"/>
</Output>
<User>
<UserRun name="Run#1" type="Before" checked="0" value=""/>
<UserRun name="Run#1" type="After" checked="0" value=""/>
</User>
</BuildOption>
<DebugOption>
<Option name="org.coocox.codebugger.gdbjtag.core.adapter" value="ST-Link"/>
<Option name="org.coocox.codebugger.gdbjtag.core.debugMode" value="SWD"/>
<Option name="org.coocox.codebugger.gdbjtag.core.clockDiv" value="1M"/>
<Option name="org.coocox.codebugger.gdbjtag.corerunToMain" value="1"/>
<Option name="org.coocox.codebugger.gdbjtag.core.jlinkgdbserver" value=""/>
<Option name="org.coocox.codebugger.gdbjtag.core.userDefineGDBScript" value=""/>
<Option name="org.coocox.codebugger.gdbjtag.core.targetEndianess" value="0"/>
<Option name="org.coocox.codebugger.gdbjtag.core.jlinkResetMode" value="Type 0: Normal"/>
<Option name="org.coocox.codebugger.gdbjtag.core.resetMode" value="SYSRESETREQ"/>
<Option name="org.coocox.codebugger.gdbjtag.core.ifSemihost" value="0"/>
<Option name="org.coocox.codebugger.gdbjtag.core.ifCacheRom" value="1"/>
<Option name="org.coocox.codebugger.gdbjtag.core.ipAddress" value="127.0.0.1"/>
<Option name="org.coocox.codebugger.gdbjtag.core.portNumber" value="2009"/>
<Option name="org.coocox.codebugger.gdbjtag.core.autoDownload" value="1"/>
<Option name="org.coocox.codebugger.gdbjtag.core.verify" value="1"/>
<Option name="org.coocox.codebugger.gdbjtag.core.downloadFuction" value="Erase Effected"/>
<Option name="org.coocox.codebugger.gdbjtag.core.defaultAlgorithm" value="STM32F4xx_1024.elf"/>
</DebugOption>
<ExcludeFile/>
</Target>
<Target name="MMDVM_Pi_446" isCurrent="0">
<Device manufacturerId="9" manufacturerName="ST" chipId="344" chipName="STM32F407VG" boardId="" boardName=""/>
<BuildOption>
<Compile>
<Option name="OptimizationLevel" value="4"/>
<Option name="UseFPU" value="0"/>
<Option name="UserEditCompiler" value=""/>
<Option name="SupportCPlusplus" value="1"/>
<Option name="FPU" value="2"/>
<Includepaths>
<Includepath path="."/>
</Includepaths>
<DefinedSymbols>
<Define name="STM32F4XX"/>
<Define name="USE_STDPERIPH_DRIVER"/>
<Define name="__ASSEMBLY__"/>
<Define name="SUPPORT_CPLUSPLUS"/>
<Define name="__FPU_USED"/>
<Define name="STM32F446xx"/>
<Define name="HSE_VALUE=12000000"/>
<Define name="STM32F4_PI"/>
<Define name="MODE_LEDS"/>
</DefinedSymbols>
</Compile>
<Link useDefault="0">
<Option name="DiscardUnusedSection" value="0"/>
<Option name="UserEditLinkder" value=""/>
<Option name="UseMemoryLayout" value="0"/>
<Option name="nostartfiles" value="1"/>
<Option name="LTO" value="0"/>
<Option name="IsNewStartupCode" value="1"/>
<Option name="Library" value="Semihosting"/>
<Option name="UserEditLinker" value="-lstdc++; --specs=nano.specs;"/>
<LinkedLibraries>
<Libset dir="stm32f4xx_lib\cmsis\lib\gcc\" libs="arm_cortexm4lf_math"/>
</LinkedLibraries>
<MemoryAreas debugInFlashNotRAM="1">
<Memory name="IROM1" type="ReadOnly" size="0x00100000" startValue="0x08000000"/>
<Memory name="IRAM1" type="ReadWrite" size="0x00020000" startValue="0x20000000"/>
<Memory name="IROM2" type="ReadOnly" size="" startValue=""/>
<Memory name="IRAM2" type="ReadWrite" size="0x00010000" startValue="0x10000000"/>
</MemoryAreas>
<LocateLinkFile path="./stm32f4xx_link.ld" type="0"/>
</Link>
<Output>
<Option name="OutputFileType" value="0"/>
<Option name="Path" value="./"/>
<Option name="Name" value="MMDVM_PI"/>
<Option name="HEX" value="1"/>
<Option name="BIN" value="1"/>
</Output>
<User>
<UserRun name="Run#1" type="Before" checked="0" value=""/>
<UserRun name="Run#1" type="After" checked="0" value=""/>
</User>
</BuildOption>
<DebugOption>
<Option name="org.coocox.codebugger.gdbjtag.core.adapter" value="ST-Link"/>
<Option name="org.coocox.codebugger.gdbjtag.core.debugMode" value="SWD"/>
<Option name="org.coocox.codebugger.gdbjtag.core.clockDiv" value="1M"/>
<Option name="org.coocox.codebugger.gdbjtag.corerunToMain" value="1"/>
<Option name="org.coocox.codebugger.gdbjtag.core.jlinkgdbserver" value=""/>
<Option name="org.coocox.codebugger.gdbjtag.core.userDefineGDBScript" value=""/>
<Option name="org.coocox.codebugger.gdbjtag.core.targetEndianess" value="0"/>
<Option name="org.coocox.codebugger.gdbjtag.core.jlinkResetMode" value="Type 0: Normal"/>
<Option name="org.coocox.codebugger.gdbjtag.core.resetMode" value="SYSRESETREQ"/>
<Option name="org.coocox.codebugger.gdbjtag.core.ifSemihost" value="0"/>
<Option name="org.coocox.codebugger.gdbjtag.core.ifCacheRom" value="1"/>
<Option name="org.coocox.codebugger.gdbjtag.core.ipAddress" value="127.0.0.1"/>
<Option name="org.coocox.codebugger.gdbjtag.core.portNumber" value="2009"/>
<Option name="org.coocox.codebugger.gdbjtag.core.autoDownload" value="1"/>
<Option name="org.coocox.codebugger.gdbjtag.core.verify" value="1"/>
<Option name="org.coocox.codebugger.gdbjtag.core.downloadFuction" value="Erase Effected"/>
<Option name="org.coocox.codebugger.gdbjtag.core.defaultAlgorithm" value="STM32F4xx_1024.elf"/>
</DebugOption>
<ExcludeFile/>
</Target>
<Target name="MMDVM_Nucleo_446" isCurrent="0">
<Device manufacturerId="9" manufacturerName="ST" chipId="344" chipName="STM32F407VG" boardId="" boardName=""/>
<BuildOption>
<Compile>
<Option name="OptimizationLevel" value="4"/>
<Option name="UseFPU" value="0"/>
<Option name="UserEditCompiler" value=""/>
<Option name="SupportCPlusplus" value="1"/>
<Option name="FPU" value="2"/>
<Includepaths>
<Includepath path="."/>
</Includepaths>
<DefinedSymbols>
<Define name="STM32F4XX"/>
<Define name="USE_STDPERIPH_DRIVER"/>
<Define name="__ASSEMBLY__"/>
<Define name="SUPPORT_CPLUSPLUS"/>
<Define name="HSE_VALUE=8000000"/>
<Define name="__FPU_USED"/>
<Define name="STM32F4_NUCLEO"/>
<Define name="STM32F446xx"/>
</DefinedSymbols>
</Compile>
<Link useDefault="0">
<Option name="DiscardUnusedSection" value="0"/>
<Option name="UserEditLinkder" value=""/>
<Option name="UseMemoryLayout" value="0"/>
<Option name="nostartfiles" value="1"/>
<Option name="LTO" value="0"/>
<Option name="IsNewStartupCode" value="1"/>
<Option name="Library" value="Semihosting"/>
<Option name="UserEditLinker" value="-lstdc++; --specs=nano.specs;"/>
<LinkedLibraries>
<Libset dir="stm32f4xx_lib\cmsis\lib\gcc\" libs="arm_cortexm4lf_math"/>
</LinkedLibraries>
<MemoryAreas debugInFlashNotRAM="1">
<Memory name="IROM1" type="ReadOnly" size="0x00100000" startValue="0x08000000"/>
<Memory name="IRAM1" type="ReadWrite" size="0x00020000" startValue="0x20000000"/>
<Memory name="IROM2" type="ReadOnly" size="" startValue=""/>
<Memory name="IRAM2" type="ReadWrite" size="0x00010000" startValue="0x10000000"/>
</MemoryAreas>
<LocateLinkFile path="./stm32f4xx_link.ld" type="0"/>
</Link>
<Output>
<Option name="OutputFileType" value="0"/>
<Option name="Path" value="./"/>
<Option name="Name" value="MMDVM_NUCLEO"/>
<Option name="HEX" value="1"/>
<Option name="BIN" value="1"/>
</Output>
<User>
<UserRun name="Run#1" type="Before" checked="0" value=""/>
<UserRun name="Run#1" type="After" checked="0" value=""/>
</User>
</BuildOption>
<DebugOption>
<Option name="org.coocox.codebugger.gdbjtag.core.adapter" value="ST-Link"/>
<Option name="org.coocox.codebugger.gdbjtag.core.debugMode" value="SWD"/>
<Option name="org.coocox.codebugger.gdbjtag.core.clockDiv" value="1M"/>
<Option name="org.coocox.codebugger.gdbjtag.corerunToMain" value="1"/>
<Option name="org.coocox.codebugger.gdbjtag.core.jlinkgdbserver" value=""/>
<Option name="org.coocox.codebugger.gdbjtag.core.userDefineGDBScript" value=""/>
<Option name="org.coocox.codebugger.gdbjtag.core.targetEndianess" value="0"/>
<Option name="org.coocox.codebugger.gdbjtag.core.jlinkResetMode" value="Type 0: Normal"/>
<Option name="org.coocox.codebugger.gdbjtag.core.resetMode" value="SYSRESETREQ"/>
<Option name="org.coocox.codebugger.gdbjtag.core.ifSemihost" value="0"/>
<Option name="org.coocox.codebugger.gdbjtag.core.ifCacheRom" value="1"/>
<Option name="org.coocox.codebugger.gdbjtag.core.ipAddress" value="127.0.0.1"/>
<Option name="org.coocox.codebugger.gdbjtag.core.portNumber" value="2009"/>
<Option name="org.coocox.codebugger.gdbjtag.core.autoDownload" value="1"/>
<Option name="org.coocox.codebugger.gdbjtag.core.verify" value="1"/>
<Option name="org.coocox.codebugger.gdbjtag.core.downloadFuction" value="Erase Effected"/>
<Option name="org.coocox.codebugger.gdbjtag.core.defaultAlgorithm" value="STM32F4xx_1024.elf"/>
</DebugOption>
<ExcludeFile/>
</Target>
<Components path="./">
</Components>
<Files>
<File name="DMRIdleRX.h" path="DMRIdleRX.h" type="1"/>
<File name="STM32F4XX_Lib/STM32F4xx_StdPeriph_Driver/source/stm32f4xx_dac.c" path="STM32F4XX_Lib/STM32F4xx_StdPeriph_Driver/source/stm32f4xx_dac.c" type="1"/>
<File name="DMRDMOTX.cpp" path="DMRDMOTX.cpp" type="1"/>
<File name="DMRRX.cpp" path="DMRRX.cpp" type="1"/>
<File name="YSFRX.cpp" path="YSFRX.cpp" type="1"/>
<File name="CalRSSI.cpp" path="CalRSSI.cpp" type="1"/>
<File name="STM32F4XX_Lib/Device/stm32f4xx.h" path="STM32F4XX_Lib/Device/stm32f4xx.h" type="1"/>
<File name="SampleRB.cpp" path="SampleRB.cpp" type="1"/>
<File name="CalDStarTX.h" path="CalDStarTX.h" type="1"/>
<File name="STM32F4XX_Lib/CMSIS/Include/core_cm4.h" path="STM32F4XX_Lib/CMSIS/Include/core_cm4.h" type="1"/>
<File name="DMRSlotRX.h" path="DMRSlotRX.h" type="1"/>
<File name="STM32F4XX_Lib/STM32F4xx_StdPeriph_Driver/source/stm32f4xx_tim.c" path="STM32F4XX_Lib/STM32F4xx_StdPeriph_Driver/source/stm32f4xx_tim.c" type="1"/>
<File name="YSFRX.h" path="YSFRX.h" type="1"/>
<File name="STM32F4XX_Lib/CMSIS/Include" path="" type="2"/>
<File name="IO.cpp" path="IO.cpp" type="1"/>
<File name="DMRDMORX.cpp" path="DMRDMORX.cpp" type="1"/>
<File name="P25RX.h" path="P25RX.h" type="1"/>
<File name="STM32F4XX_Lib/STM32F4xx_StdPeriph_Driver/source/misc.c" path="STM32F4XX_Lib/STM32F4xx_StdPeriph_Driver/source/misc.c" type="1"/>
<File name="STM32F4XX_Lib/CMSIS" path="" type="2"/>
<File name="SerialArduino.cpp" path="SerialArduino.cpp" type="1"/>
<File name="SerialPort.cpp" path="SerialPort.cpp" type="1"/>
<File name="STM32F4XX_Lib/Device/stm32f4xx_conf.h" path="STM32F4XX_Lib/Device/stm32f4xx_conf.h" type="1"/>
<File name="STM32F4XX_Lib/STM32F4xx_StdPeriph_Driver/source/stm32f4xx_adc.c" path="STM32F4XX_Lib/STM32F4xx_StdPeriph_Driver/source/stm32f4xx_adc.c" type="1"/>
<File name="DStarTX.cpp" path="DStarTX.cpp" type="1"/>
<File name="STM32F4XX_Lib/STM32F4xx_StdPeriph_Driver/source/stm32f4xx_usart.c" path="STM32F4XX_Lib/STM32F4xx_StdPeriph_Driver/source/stm32f4xx_usart.c" type="1"/>
<File name="SampleRB.h" path="SampleRB.h" type="1"/>
<File name="YSFTX.h" path="YSFTX.h" type="1"/>
<File name="DMRRX.h" path="DMRRX.h" type="1"/>
<File name="CalRSSI.h" path="CalRSSI.h" type="1"/>
<File name="IOTeensy.cpp" path="IOTeensy.cpp" type="1"/>
<File name="MMDVM.cpp" path="MMDVM.cpp" type="1"/>
<File name="STM32F4XX_Lib/CMSIS/Include/core_cmSimd.h" path="STM32F4XX_Lib/CMSIS/Include/core_cmSimd.h" type="1"/>
<File name="DMRDMORX.h" path="DMRDMORX.h" type="1"/>
<File name="SerialPort.h" path="SerialPort.h" type="1"/>
<File name="STM32F4XX_Lib/STM32F4xx_StdPeriph_Driver/include/stm32f4xx_dac.h" path="STM32F4XX_Lib/STM32F4xx_StdPeriph_Driver/include/stm32f4xx_dac.h" type="1"/>
<File name="CWIdTX.h" path="CWIdTX.h" type="1"/>
<File name="STM32F4XX_Lib/Device/system_stm32f4xx.h" path="STM32F4XX_Lib/Device/system_stm32f4xx.h" type="1"/>
<File name="STM32F4XX_Lib/CMSIS/Include/core_cmFunc.h" path="STM32F4XX_Lib/CMSIS/Include/core_cmFunc.h" type="1"/>
<File name="CalDStarTX.cpp" path="CalDStarTX.cpp" type="1"/>
<File name="STM32F4XX_Lib/STM32F4xx_StdPeriph_Driver/source" path="" type="2"/>
<File name="CalDMR.h" path="CalDMR.h" type="1"/>
<File name="DMRDMOTX.h" path="DMRDMOTX.h" type="1"/>
<File name="IODue.cpp" path="IODue.cpp" type="1"/>
<File name="DMRTX.cpp" path="DMRTX.cpp" type="1"/>
<File name="P25RX.cpp" path="P25RX.cpp" type="1"/>
<File name="STM32F4XX_Lib/CMSIS/Lib/GCC" path="" type="2"/>
<File name="STM32F4XX_Lib" path="" type="2"/>
<File name="STM32F4XX_Lib/CMSIS/Include/core_cmInstr.h" path="STM32F4XX_Lib/CMSIS/Include/core_cmInstr.h" type="1"/>
<File name="DMRTX.h" path="DMRTX.h" type="1"/>
<File name="STM32F4XX_Lib/Device/system_stm32f4xx.c" path="STM32F4XX_Lib/Device/system_stm32f4xx.c" type="1"/>
<File name="RSSIRB.h" path="RSSIRB.h" type="1"/>
<File name="STM32F4XX_Lib/Device/startup/startup_stm32f4xx.c" path="STM32F4XX_Lib/Device/startup/startup_stm32f4xx.c" type="1"/>
<File name="STM32F4XX_Lib/Device/startup" path="" type="2"/>
<File name="SerialRB.h" path="SerialRB.h" type="1"/>
<File name="STM32F4XX_Lib/STM32F4xx_StdPeriph_Driver/include/stm32f4xx_gpio.h" path="STM32F4XX_Lib/STM32F4xx_StdPeriph_Driver/include/stm32f4xx_gpio.h" type="1"/>
<File name="STM32F4XX_Lib/STM32F4xx_StdPeriph_Driver" path="" type="2"/>
<File name="DMRDefines.h" path="DMRDefines.h" type="1"/>
<File name="CalDMR.cpp" path="CalDMR.cpp" type="1"/>
<File name="STM32F4XX_Lib/STM32F4xx_StdPeriph_Driver/include/stm32f4xx_adc.h" path="STM32F4XX_Lib/STM32F4xx_StdPeriph_Driver/include/stm32f4xx_adc.h" type="1"/>
<File name="SerialSTM.cpp" path="SerialSTM.cpp" type="1"/>
<File name="STM32F4XX_Lib/CMSIS/Lib/GCC/libarm_cortexM4lf_math.a" path="STM32F4XX_Lib/CMSIS/Lib/GCC/libarm_cortexM4lf_math.a" type="1"/>
<File name="DStarDefines.h" path="DStarDefines.h" type="1"/>
<File name="DStarRX.h" path="DStarRX.h" type="1"/>
<File name="Config.h" path="Config.h" type="1"/>
<File name="DMRSlotType.cpp" path="DMRSlotType.cpp" type="1"/>
<File name="Globals.h" path="Globals.h" type="1"/>
<File name="STM32F4XX_Lib/Device" path="" type="2"/>
<File name="CalDStarRX.cpp" path="CalDStarRX.cpp" type="1"/>
<File name="STM32F4XX_Lib/STM32F4xx_StdPeriph_Driver/include/stm32f4xx_tim.h" path="STM32F4XX_Lib/STM32F4xx_StdPeriph_Driver/include/stm32f4xx_tim.h" type="1"/>
<File name="CalDStarRX.h" path="CalDStarRX.h" type="1"/>
<File name="STM32F4XX_Lib/STM32F4xx_StdPeriph_Driver/include" path="" type="2"/>
<File name="IO.h" path="IO.h" type="1"/>
<File name="Utils.cpp" path="Utils.cpp" type="1"/>
<File name="STM32F4XX_Lib/CMSIS/.DS_Store" path="STM32F4XX_Lib/CMSIS/.DS_Store" type="1"/>
<File name="STM32F4XX_Lib/CMSIS/Lib/.DS_Store" path="STM32F4XX_Lib/CMSIS/Lib/.DS_Store" type="1"/>
<File name="Utils.h" path="Utils.h" type="1"/>
<File name="STM32F4XX_Lib/CMSIS/Lib" path="" type="2"/>
<File name="STM32F4XX_Lib/STM32F4xx_StdPeriph_Driver/.DS_Store" path="STM32F4XX_Lib/STM32F4xx_StdPeriph_Driver/.DS_Store" type="1"/>
<File name="STM32F4XX_Lib/CMSIS/Include/.DS_Store" path="STM32F4XX_Lib/CMSIS/Include/.DS_Store" type="1"/>
<File name="STM32F4XX_Lib/CMSIS/Include/arm_math.h" path="STM32F4XX_Lib/CMSIS/Include/arm_math.h" type="1"/>
<File name="YSFDefines.h" path="YSFDefines.h" type="1"/>
<File name="DStarTX.h" path="DStarTX.h" type="1"/>
<File name="STM32F4XX_Lib/STM32F4xx_StdPeriph_Driver/source/stm32f4xx_rcc.c" path="STM32F4XX_Lib/STM32F4xx_StdPeriph_Driver/source/stm32f4xx_rcc.c" type="1"/>
<File name="STM32F4XX_Lib/Device/.DS_Store" path="STM32F4XX_Lib/Device/.DS_Store" type="1"/>
<File name="STM32F4XX_Lib/STM32F4xx_StdPeriph_Driver/include/stm32f4xx_rcc.h" path="STM32F4XX_Lib/STM32F4xx_StdPeriph_Driver/include/stm32f4xx_rcc.h" type="1"/>
<File name="P25Defines.h" path="P25Defines.h" type="1"/>
<File name="DMRSlotType.h" path="DMRSlotType.h" type="1"/>
<File name="Debug.h" path="Debug.h" type="1"/>
<File name="STM32F4XX_Lib/STM32F4xx_StdPeriph_Driver/include/misc.h" path="STM32F4XX_Lib/STM32F4xx_StdPeriph_Driver/include/misc.h" type="1"/>
<File name="P25TX.h" path="P25TX.h" type="1"/>
<File name="RSSIRB.cpp" path="RSSIRB.cpp" type="1"/>
<File name="DStarRX.cpp" path="DStarRX.cpp" type="1"/>
<File name="DMRSlotRX.cpp" path="DMRSlotRX.cpp" type="1"/>
<File name="IOSTM.cpp" path="IOSTM.cpp" type="1"/>
<File name="P25TX.cpp" path="P25TX.cpp" type="1"/>
<File name="SerialRB.cpp" path="SerialRB.cpp" type="1"/>
<File name="CWIdTX.cpp" path="CWIdTX.cpp" type="1"/>
<File name="DMRIdleRX.cpp" path="DMRIdleRX.cpp" type="1"/>
<File name="STM32F4XX_Lib/STM32F4xx_StdPeriph_Driver/include/stm32f4xx_usart.h" path="STM32F4XX_Lib/STM32F4xx_StdPeriph_Driver/include/stm32f4xx_usart.h" type="1"/>
<File name="STM32F4XX_Lib/.DS_Store" path="STM32F4XX_Lib/.DS_Store" type="1"/>
<File name="YSFTX.cpp" path="YSFTX.cpp" type="1"/>
<File name="STM32F4XX_Lib/STM32F4xx_StdPeriph_Driver/source/stm32f4xx_gpio.c" path="STM32F4XX_Lib/STM32F4xx_StdPeriph_Driver/source/stm32f4xx_gpio.c" type="1"/>
</Files>
</Project>
+57 -11
View File
@@ -25,6 +25,7 @@ F7_LIB_PATH=./STM32F7XX_Lib
# MCU external clock frequency (Hz)
CLK_MMDVM_PI=12000000
CLK_NUCLEO=8000000
CLK_12MHZ=12000000
# Directory Structure
BINDIR=bin
@@ -93,6 +94,8 @@ ifndef $(OSC)
OSC=$(CLK_MMDVM_PI)
else ifeq ($(MAKECMDGOALS),pi-f722)
OSC=$(CLK_MMDVM_PI)
else ifeq ($(MAKECMDGOALS),drcc_nqf)
OSC=$(CLK_12MHZ)
else
OSC=$(CLK_NUCLEO)
endif
@@ -130,10 +133,19 @@ DEFS_PI_F722=-DUSE_HAL_DRIVER -DSTM32F722xx -DSTM32F7XX -DSTM32F722_PI -DHSE_VAL
DEFS_F7M=-DUSE_HAL_DRIVER -DSTM32F722xx -DSTM32F7XX -DSTM32F722_F7M -DHSE_VALUE=$(OSC) -DMADEBYMAKEFILE
# MMDVM_RPT_Hat F0DEI, DB9MAT, DF2ET board:
DEFS_RPT_HAT=-DUSE_HAL_DRIVER -DSTM32F722xx -DSTM32F7XX -DSTM32F722_RPT_HAT -DHSE_VALUE=$(OSC) -DMADEBYMAKEFILE
# STM32F4 DVM board:
# RB STM32F4_DVM board:
DEFS_DVM=-DUSE_STDPERIPH_DRIVER -DSTM32F4XX -DSTM32F446xx -DSTM32F4_DVM -DHSE_VALUE=$(OSC) -DMADEBYMAKEFILE
# RB STM32F7 DVM board:
DEFS_DVM722=-DUSE_HAL_DRIVER -DSTM32F722xx -DSTM32F7XX -DSTM32F7_DVM -DHSE_VALUE=$(OSC) -DMADEBYMAKEFILE
# MMDVM_RPT_Hat BG4TGO, BG5HHP board:
DEFS_RPT_HAT_TGO=-DUSE_STDPERIPH_DRIVER -DSTM32F4XX -DSTM32F40_41xxx -DSTM32F4_RPT_HAT_TGO -DHSE_VALUE=$(OSC) -DMADEBYMAKEFILE
# DRCC_DVM BG7NQF board:
DEFS_DRCC_DVM=-DUSE_STDPERIPH_DRIVER -DSTM32F4XX -DSTM32F446xx -DDRCC_DVM -DHSE_VALUE=$(OSC) -DMADEBYMAKEFILE
# WA0EDA F405 MTR2K, MASTR3 board:
DEFS_EDA_405=-DUSE_STDPERIPH_DRIVER -DSTM32F4XX -DSTM32F40_41xxx -DSTM32F4_EDA_405 -DHSE_VALUE=$(OSC) -DMADEBYMAKEFILE
# WA0EDA F446 MTR2K, MASTR3 board:
DEFS_EDA_446=-DUSE_STDPERIPH_DRIVER -DSTM32F4XX -DSTM32F446xx -DSTM32F4_EDA_446 -DHSE_VALUE=$(OSC) -DMADEBYMAKEFILE
# Build compiler flags
CFLAGS_F4=-c $(MCFLAGS_F4) $(INCLUDES_F4)
@@ -149,10 +161,10 @@ LDFLAGS_F722 =-T stm32f722_link.ld $(MCFLAGS_F7) --specs=nosys.specs $(INCLUDES_
# Common flags
CFLAGS=-Os -ffunction-sections -fdata-sections -fno-builtin -Wno-implicit -DCUSTOM_NEW -DNO_EXCEPTIONS
CXXFLAGS=-Os -fno-exceptions -ffunction-sections -fdata-sections -fno-builtin -fno-rtti -DCUSTOM_NEW -DNO_EXCEPTIONS
LDFLAGS=-Os --specs=nano.specs
LDFLAGS=-Os --specs=nano.specs -Wl,-Map=bin/mmdvm.map
# Build Rules
.PHONY: all release dis pi pi-f722 f4m nucleo f767 dvm clean
.PHONY: all release dis pi pi-f722 f4m nucleo f767 dvm drcc_nqf clean
# Default target: Nucleo-64 F446RE board
all: nucleo
@@ -212,11 +224,41 @@ f767: LDFLAGS+=$(LDFLAGS_F767)
f767: release_f7
dvm: GitVersion.h
dvm: CFLAGS+=$(CFLAGS_F4) $(DEFS_DVM)
dvm: CXXFLAGS+=$(CXXFLAGS_F4) $(DEFS_DVM)
dvm: CFLAGS+=$(CFLAGS_F4) $(DEFS_DVM) -DDRCC_DVM_446
dvm: CXXFLAGS+=$(CXXFLAGS_F4) $(DEFS_DVM) -DDRCC_DVM_446
dvm: LDFLAGS+=$(LDFLAGS_F4)
dvm: release_f4
dvm722: GitVersion.h
dvm722: CFLAGS+=$(CFLAGS_F7) $(DEFS_DVM722) -DDRCC_DVM_722
dvm722: CXXFLAGS+=$(CXXFLAGS_F7) $(DEFS_DVM722) -DDRCC_DVM_722
dvm722: LDFLAGS+=$(LDFLAGS_F722)
dvm722: release_f7
drcc_nqf: GitVersion.h
drcc_nqf: CFLAGS+=$(CFLAGS_F4) $(DEFS_DRCC_DVM) -DDRCC_DVM_NQF
drcc_nqf: CXXFLAGS+=$(CXXFLAGS_F4) $(DEFS_DRCC_DVM) -DDRCC_DVM_NQF
drcc_nqf: LDFLAGS+=$(LDFLAGS_F4)
drcc_nqf: release_f4
hhp446: GitVersion.h
hhp446: CFLAGS+=$(CFLAGS_F4) $(DEFS_DRCC_DVM) -DDRCC_DVM_HHP446
hhp446: CXXFLAGS+=$(CXXFLAGS_F4) $(DEFS_DRCC_DVM) -DDRCC_DVM_HHP446
hhp446: LDFLAGS+=$(LDFLAGS_F4)
hhp446: release_f4
eda405: GitVersion.h
eda405: CFLAGS+=$(CFLAGS_F4) $(DEFS_EDA_405)
eda405: CXXFLAGS+=$(CXXFLAGS_F4) $(DEFS_EDA_405)
eda405: LDFLAGS+=$(LDFLAGS_F4)
eda405: release_f4
eda446: GitVersion.h
eda446: CFLAGS+=$(CFLAGS_F4) $(DEFS_EDA_446)
eda446: CXXFLAGS+=$(CXXFLAGS_F4) $(DEFS_EDA_446)
eda446: LDFLAGS+=$(LDFLAGS_F4)
eda446: release_f4
release_f4: $(BINDIR)
release_f4: $(OBJDIR_F4)
release_f4: $(BINDIR)/$(BINHEX_F4)
@@ -326,27 +368,27 @@ endif
deploy-pi:
ifneq ($(wildcard /usr/local/bin/stm32flash),)
-/usr/local/bin/stm32flash -i 20,-21,21:-20,21 /dev/ttyAMA0
-/usr/local/bin/stm32ld /dev/ttyAMA0 57600 bin/$(BINBIN_F4)
/usr/local/bin/stm32flash -v -w bin/$(BINBIN_F4) -g 0x0 -R -c /dev/ttyAMA0
/usr/local/bin/stm32flash -v -w bin/$(BINBIN_F4) -g 0x0 -R /dev/ttyAMA0
endif
ifneq ($(wildcard /usr/bin/stm32flash),)
-/usr/bin/stm32flash -i 20,-21,21:-20,21 /dev/ttyAMA0
-/usr/bin/stm32ld /dev/ttyAMA0 57600 bin/$(BINBIN_F4)
/usr/bin/stm32flash -v -w bin/$(BINBIN_F4) -g 0x0 -R -c /dev/ttyAMA0
/usr/bin/stm32flash -v -w bin/$(BINBIN_F4) -g 0x0 -R /dev/ttyAMA0
endif
deploy-f4m: deploy-pi
deploy-dvm: deploy-pi
deploy-eda405: deploy-pi
deploy-eda446: deploy-pi
deploy-pi-f7:
ifneq ($(wildcard /usr/local/bin/stm32flash),)
-/usr/local/bin/stm32flash -i 20,-21,21:-20,21 /dev/ttyAMA0
/usr/local/bin/stm32flash -v -w bin/$(BINBIN_F7) -g 0x0 -R -c /dev/ttyAMA0
/usr/local/bin/stm32flash -v -w bin/$(BINBIN_F7) -g 0x0 -R /dev/ttyAMA0
else ifneq ($(wildcard /usr/bin/stm32flash),)
-/usr/bin/stm32flash -i 20,-21,21:-20,21 /dev/ttyAMA0
/usr/bin/stm32flash -v -w bin/$(BINBIN_F7) -g 0x0 -R -c /dev/ttyAMA0
/usr/bin/stm32flash -v -w bin/$(BINBIN_F7) -g 0x0 -R /dev/ttyAMA0
endif
deploy-f7m: deploy-pi-f7
@@ -365,3 +407,7 @@ else
echo "#define GITVERSION \"0000000\"" > $@
endif
endif
flash_f4:
@echo "flashing firmware..."
st-flash write bin/$(BINBIN_F4) 0x8000000
-189
View File
@@ -1,189 +0,0 @@
#!/usr/bin/make
# makefile for the arduino due (works with arduino IDE 1.6.11)
#
# The original file can be found at https://github.com/pauldreik/arduino-due-makefile
#
# USAGE: put this file in the same dir as your .ino file is.
# configure the PORT variable and ADIR at the top of the file
# to match your local configuration.
# Type make upload to compile and upload.
#
#user specific settings:
#where to find the IDE
ADIR:=$(HOME)/.arduino15
#which serial port to use (add a file with SUBSYSTEMS=="usb",
#ATTRS{product}=="Arduino Due Prog. Port", ATTRS{idProduct}=="003d",
#ATTRS{idVendor}=="2341", SYMLINK+="arduino_due" in /etc/udev/rules.d/
#to get this working). Do not prefix the port with /dev/, just take
#the basename.
PORT:=ttyACM0
#if you want to verify the bossac upload, define this to -v
VERIFY:=-v
#end of user configuration.
#then some general settings. They should not be necessary to modify.
#CXX:=$(ADIR)/tools/g++_arm_none_eabi/bin/arm-none-eabi-g++
CXX:=$(ADIR)/packages/arduino/tools/arm-none-eabi-gcc/4.8.3-2014q1/bin/arm-none-eabi-g++
#CC:=$(ADIR)/tools/g++_arm_none_eabi/bin/arm-none-eabi-gcc
CC:=$(ADIR)/packages/arduino/tools/arm-none-eabi-gcc/4.8.3-2014q1/bin/arm-none-eabi-gcc
OBJCOPY:=$(ADIR)/packages/arduino/tools/arm-none-eabi-gcc/4.8.3-2014q1/bin/arm-none-eabi-objcopy
C:=$(CC)
#SAM:=arduino/sam/
SAM:=$(ADIR)/packages/arduino/hardware/sam/1.6.11
#CMSIS:=arduino/sam/system/CMSIS/
#LIBSAM:=arduino/sam/system/libsam
TMPDIR:=$(PWD)/build
AR:=$(ADIR)/tools/g++_arm_none_eabi/bin/arm-none-eabi-ar
AR:=$(ADIR)/packages/arduino/tools/arm-none-eabi-gcc/4.8.3-2014q1/bin/arm-none-eabi-ar
#all these values are hard coded and should maybe be configured somehow else,
#like olikraus does in his makefile.
DEFINES:=-Dprintf=iprintf -DF_CPU=84000000 -DARDUINO=10611 -D__SAM3X8E__ -DUSB_PID=0x003e -DUSB_VID=0x2341 -DUSBCON \
-DARDUINO_SAM_DUE -DARDUINO_ARCH_SAM '-DUSB_MANUFACTURER="Arduino LLC"' '-DUSB_PRODUCT="Arduino Due"' \
-DMADEBYMAKEFILE
INCLUDES:=-I$(SAM)/system/libsam -I$(SAM)/system/CMSIS/CMSIS/Include/ \
-I$(SAM)/system/CMSIS/Device/ATMEL/ -I$(SAM)/cores/arduino \
-I$(SAM)/variants/arduino_due_x
#also include the current dir for convenience
INCLUDES += -I.
#compilation flags common to both c and c++
COMMON_FLAGS:=-g -Os -w -ffunction-sections -fdata-sections -nostdlib \
--param max-inline-insns-single=500 -mcpu=cortex-m3 -mthumb \
-fno-threadsafe-statics
#for compiling c (do not warn, this is not our code)
CFLAGS:=$(COMMON_FLAGS) -std=gnu11
#for compiling c++
CXXFLAGS:=$(COMMON_FLAGS) -fno-rtti -fno-exceptions -std=gnu++11 -Wall -Wextra
#let the results be named after the project
PROJNAME:=$(shell basename *.ino .ino)
#we will make a new mainfile from the ino file.
NEWMAINFILE:=$(TMPDIR)/$(PROJNAME).ino.cpp
#our own sourcefiles is the (converted) ino file and any local cpp files
MYSRCFILES:=$(NEWMAINFILE) $(shell ls *.cpp 2>/dev/null)
MYOBJFILES:=$(addsuffix .o,$(addprefix $(TMPDIR)/,$(notdir $(MYSRCFILES))))
#These source files are the ones forming core.a
CORESRCXX:=$(shell ls ${SAM}/cores/arduino/*.cpp ${SAM}/cores/arduino/USB/*.cpp ${SAM}/variants/arduino_due_x/variant.cpp)
CORESRC:=$(shell ls ${SAM}/cores/arduino/*.c)
#hey this one is needed too: $(SAM)/cores/arduino/wiring_pulse_asm.S" add -x assembler-with-cpp
#and this one: /1.6.11/cores/arduino/avr/dtostrf.c but it seems to work
#anyway, probably because I do not use that functionality.
#convert the core source files to object files. assume no clashes.
COREOBJSXX:=$(addprefix $(TMPDIR)/core/,$(notdir $(CORESRCXX)) )
COREOBJSXX:=$(addsuffix .o,$(COREOBJSXX))
COREOBJS:=$(addprefix $(TMPDIR)/core/,$(notdir $(CORESRC)) )
COREOBJS:=$(addsuffix .o,$(COREOBJS))
default:
@echo default rule, does nothing. Try make compile or make upload.
#This rule is good to just make sure stuff compiles, without having to wait
#for bossac.
compile: GitVersion.h $(TMPDIR)/$(PROJNAME).elf $(TMPDIR)/$(PROJNAME).bin
#This is a make rule template to create object files from the source files.
# arg 1=src file
# arg 2=object file
# arg 3= XX if c++, empty if c
define OBJ_template
$(2): $(1)
$(C$(3)) -MD -c $(C$(3)FLAGS) $(DEFINES) $(INCLUDES) $(1) -o $(2)
endef
#now invoke the template both for c++ sources
$(foreach src,$(CORESRCXX), $(eval $(call OBJ_template,$(src),$(addsuffix .o,$(addprefix $(TMPDIR)/core/,$(notdir $(src)))),XX) ) )
#...and for c sources:
$(foreach src,$(CORESRC), $(eval $(call OBJ_template,$(src),$(addsuffix .o,$(addprefix $(TMPDIR)/core/,$(notdir $(src)))),) ) )
#and our own c++ sources
$(foreach src,$(MYSRCFILES), $(eval $(call OBJ_template,$(src),$(addsuffix .o,$(addprefix $(TMPDIR)/,$(notdir $(src)))),XX) ) )
clean:
test ! -d $(TMPDIR) || rm -rf $(TMPDIR)
$(RM) GitVersion.h
.PHONY: .FORCE upload default
$(TMPDIR):
mkdir -p $(TMPDIR)
$(TMPDIR)/core:
mkdir -p $(TMPDIR)/core
#creates the cpp file from the .ino file
$(NEWMAINFILE): $(PROJNAME).ino
cat $(SAM)/cores/arduino/main.cpp > $(NEWMAINFILE)
cat $(PROJNAME).ino >> $(NEWMAINFILE)
echo 'extern "C" void __cxa_pure_virtual() {while (true);}' >> $(NEWMAINFILE)
#include the dependencies for our own files
-include $(MYOBJFILES:.o=.d)
#create the core library from the core objects. Do this EXACTLY as the
#arduino IDE does it, seems *really* picky about this.
#Sorry for the hard coding.
$(TMPDIR)/core.a: $(TMPDIR)/core $(COREOBJS) $(COREOBJSXX)
$(AR) rcs $(TMPDIR)/core.a $(TMPDIR)/core/wiring_shift.c.o
$(AR) rcs $(TMPDIR)/core.a $(TMPDIR)/core/wiring_analog.c.o
$(AR) rcs $(TMPDIR)/core.a $(TMPDIR)/core/itoa.c.o
$(AR) rcs $(TMPDIR)/core.a $(TMPDIR)/core/cortex_handlers.c.o
$(AR) rcs $(TMPDIR)/core.a $(TMPDIR)/core/hooks.c.o
$(AR) rcs $(TMPDIR)/core.a $(TMPDIR)/core/wiring.c.o
$(AR) rcs $(TMPDIR)/core.a $(TMPDIR)/core/WInterrupts.c.o
$(AR) rcs $(TMPDIR)/core.a $(TMPDIR)/core/syscalls_sam3.c.o
$(AR) rcs $(TMPDIR)/core.a $(TMPDIR)/core/iar_calls_sam3.c.o
$(AR) rcs $(TMPDIR)/core.a $(TMPDIR)/core/wiring_digital.c.o
$(AR) rcs $(TMPDIR)/core.a $(TMPDIR)/core/Print.cpp.o
$(AR) rcs $(TMPDIR)/core.a $(TMPDIR)/core/USARTClass.cpp.o
$(AR) rcs $(TMPDIR)/core.a $(TMPDIR)/core/WString.cpp.o
$(AR) rcs $(TMPDIR)/core.a $(TMPDIR)/core/PluggableUSB.cpp.o
$(AR) rcs $(TMPDIR)/core.a $(TMPDIR)/core/USBCore.cpp.o
$(AR) rcs $(TMPDIR)/core.a $(TMPDIR)/core/CDC.cpp.o
$(AR) rcs $(TMPDIR)/core.a $(TMPDIR)/core/wiring_pulse.cpp.o
$(AR) rcs $(TMPDIR)/core.a $(TMPDIR)/core/UARTClass.cpp.o
$(AR) rcs $(TMPDIR)/core.a $(TMPDIR)/core/main.cpp.o
$(AR) rcs $(TMPDIR)/core.a $(TMPDIR)/core/new.cpp.o
$(AR) rcs $(TMPDIR)/core.a $(TMPDIR)/core/watchdog.cpp.o
$(AR) rcs $(TMPDIR)/core.a $(TMPDIR)/core/Stream.cpp.o
$(AR) rcs $(TMPDIR)/core.a $(TMPDIR)/core/RingBuffer.cpp.o
$(AR) rcs $(TMPDIR)/core.a $(TMPDIR)/core/IPAddress.cpp.o
$(AR) rcs $(TMPDIR)/core.a $(TMPDIR)/core/Reset.cpp.o
$(AR) rcs $(TMPDIR)/core.a $(TMPDIR)/core/WMath.cpp.o
$(AR) rcs $(TMPDIR)/core.a $(TMPDIR)/core/variant.cpp.o
#link our own object files with core to form the elf file
$(TMPDIR)/$(PROJNAME).elf: $(TMPDIR)/core.a $(TMPDIR)/core/syscalls_sam3.c.o $(MYOBJFILES)
$(CC) -mcpu=cortex-m3 -mthumb -Os -Wl,--gc-sections -T$(SAM)/variants/arduino_due_x/linker_scripts/gcc/flash.ld -Wl,-Map,$(NEWMAINFILE).map -o $@ -L$(TMPDIR) -Wl,--cref -Wl,--check-sections -Wl,--gc-sections -Wl,--entry=Reset_Handler -Wl,--unresolved-symbols=report-all -Wl,--warn-common -Wl,--warn-section-align -Wl,--start-group -u _sbrk -u link -u _close -u _fstat -u _isatty -u _lseek -u _read -u _write -u _exit -u kill -u _getpid $(MYOBJFILES) $(TMPDIR)/core/variant.cpp.o $(SAM)/variants/arduino_due_x/libsam_sam3x8e_gcc_rel.a $(SAM)/system/CMSIS/CMSIS/Lib/GCC/libarm_cortexM3l_math.a $(TMPDIR)/core.a -Wl,--end-group -lm -gcc
#copy from the hex to our bin file (why?)
$(TMPDIR)/$(PROJNAME).bin: $(TMPDIR)/$(PROJNAME).elf
$(OBJCOPY) -O binary $< $@
#upload to the arduino by first resetting it (stty) and the running bossac
upload: compile
stty -F /dev/$(PORT) cs8 1200 hupcl
$(ADIR)/packages/arduino/tools/bossac/1.6.1-arduino/bossac -i --port=$(PORT) -U false -e -w $(VERIFY) -b $(TMPDIR)/$(PROJNAME).bin -R
# Export the current git version if the index file exists, else 000...
GitVersion.h: .FORCE
ifneq ("$(wildcard .git/index)","")
echo "#define GITVERSION \"$(shell git rev-parse --short HEAD)\"" > $@
else
echo "#define GITVERSION \"0000000\"" > $@
endif
.FORCE:
-165
View File
@@ -1,165 +0,0 @@
# The name for the project
TARGET:=mmdvm
# The CPU architecture (will be used for -mcpu)
MCPU:=cortex-m3
MCU:=STM32F105xC
# The source files of the project
CSRC:=
CXXSRC:=$(wildcard *.cpp)
# Include directory for the system include files and system source file
SYSDIR:=system_stm32f1xx
SYSSRC:=$(SYSDIR)/system_stm32f1xx.c
# Other include directories
INCDIR:=
# Definitions
CDEFS:=
CXXDEFS:=
# The name of the startup file which matches to the architecture (MCPU)
STARTUP:=$(SYSDIR)/startup_stm32f105xc.S
STARTUP_DEFS=
# Include directory for CMSIS
CMSISDIR:=STM32F10X_Lib/CMSIS
# Libraries
LIBDIR:=
LIBS:=-larm_cortexM3l_math
# Name of the linker script
LDSCRIPT:=$(SYSDIR)/gcc.ld
# Target objects and binaries directory
OBJDIR:=obj
BINDIR:=bin
# Port definition for programming via bootloader (using stm32flash)
BL_PORT:=ttyUSB0
# Internal Variables
ELF:=$(BINDIR)/$(TARGET).elf
HEX:=$(BINDIR)/$(TARGET).hex
DIS:=$(BINDIR)/$(TARGET).dis
MAP:=$(BINDIR)/$(TARGET).map
OBJ:=$(CSRC:%.c=$(OBJDIR)/%.o) $(CXXSRC:%.cpp=$(OBJDIR)/%.o)
OBJ+=$(SYSSRC:$(SYSDIR)/%.c=$(OBJDIR)/%.o) $(STARTUP:$(SYSDIR)/%.S=$(OBJDIR)/%.o)
# Replace standard build tools by arm tools
CC:=arm-none-eabi-gcc
CXX:=arm-none-eabi-g++
AS:=arm-none-eabi-gcc
LD:=arm-none-eabi-g++
OBJCOPY:=arm-none-eabi-objcopy
OBJDUMP:=arm-none-eabi-objdump
SIZE:=arm-none-eabi-size
# Common flags
COMMON_FLAGS =-mthumb -mlittle-endian -mcpu=$(MCPU)
COMMON_FLAGS+= -Wall
COMMON_FLAGS+= -I. -I$(CMSISDIR)/Include -I$(CMSISDIR)/Device/ST/STM32F1xx/Include -I$(SYSDIR)
COMMON_FLAGS+= $(addprefix -I,$(INCDIR))
COMMON_FLAGS+= -D$(MCU) -DMADEBYMAKEFILE -DSTM32F1
COMMON_FLAGS+= -Os -flto -ffunction-sections -fdata-sections
COMMON_FLAGS+= -g
# Assembler flags
ASFLAGS:=$(COMMON_FLAGS)
# C flags
CFLAGS:=$(COMMON_FLAGS) $(addprefix -D,$(CDEFS))
CFLAGS+= -std=gnu11 -nostdlib
# CXX flags
CXXFLAGS:=$(COMMON_FLAGS) $(addprefix -D,$(CXXDEFS))
CXXFLAGS+= -nostdlib -fno-exceptions -fno-rtti
# LD flags
LDFLAGS:=$(COMMON_FLAGS) -Wl,--gc-sections -Wl,-Map=$(MAP) -Wl,--no-wchar-size-warning
LDFLAGS+= --specs=nosys.specs --specs=nano.specs
LDFLAGS+= -L$(CMSISDIR)/Lib/GCC/ $(addprefix -L,$(LIBDIR))
LDLIBS:=-T$(LDSCRIPT) $(LIBS)
# Dependecies
DEPENDS:=$(CSRC:%.c=$(OBJDIR)/%.d) $(CXXSRC:%.cpp=$(OBJDIR)/%.d)
# Additional Suffixes
.SUFFIXES: .elf .hex
# Targets
.PHONY: all
all: GitVersion.h $(DIS) $(HEX)
$(SIZE) $(ELF)
.PHONY: program
program: $(HEX) $(ELF)
openocd -f openocd.cfg \
-c "program $(HEX) verify reset exit"
$(SIZE) $(ELF)
.PHONY: program_bl
program_bl: $(HEX) $(ELF)
stm32flash -w $(HEX) -v /dev/$(BL_PORT)
$(SIZE) $(ELF)
.PHONY: run
run: $(HEX) $(ELF)
openocd -f openocd.cfg \
-c "init" -c "reset" -c "exit"
.PHONY: debug
debug: $(ELF)
./debug.sh $(ELF)
.PHONY: clean
clean:
$(RM) $(OBJ) $(HEX) $(ELF) $(DIS) $(MAP) $(DEPENDS) GitVersion.h
# implicit rules
.elf.hex:
$(OBJCOPY) -O ihex $< $@
$(OBJDIR)/%.o: %.c
$(CC) -MMD $(CFLAGS) -c $< -o $@
$(OBJDIR)/%.o: %.cpp
$(CXX) -MMD $(CXXFLAGS) -c $< -o $@
$(OBJDIR)/%.o: $(SYSDIR)/%.c
$(CC) $(CFLAGS) -c $< -o $@
$(OBJDIR)/%.o: $(SYSDIR)/%.S
$(AS) $(ASFLAGS) -c $< -o $@
# explicit rules
$(OBJDIR):
mkdir -p $(OBJDIR)
$(BINDIR):
mkdir -p $(BINDIR)
$(ELF): $(OBJDIR) $(BINDIR) $(OBJ)
$(LD) $(OBJ) $(LDFLAGS) $(LDLIBS) -o $@
$(DIS): $(ELF)
$(OBJDUMP) -S $< > $@
# include dependecies
-include $(DEPENDS)
# Export the current git version if the index file exists, else 000...
GitVersion.h:
ifdef SYSTEMROOT
echo #define GITVERSION "0000000" > $@
else ifdef SystemRoot
echo #define GITVERSION "0000000" > $@
else
ifneq ("$(wildcard .git/index)","")
echo "#define GITVERSION \"$(shell git rev-parse --short HEAD)\"" > $@
else
echo "#define GITVERSION \"0000000\"" > $@
endif
endif
+6 -1
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2009-2018 by Jonathan Naylor G4KLX
* Copyright (C) 2009-2018,2020 by Jonathan Naylor G4KLX
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -17,6 +17,9 @@
*/
#include "Config.h"
#if defined(MODE_NXDN)
#include "Globals.h"
#include "NXDNRX.h"
#include "Utils.h"
@@ -403,3 +406,5 @@ void CNXDNRX::writeRSSIData(uint8_t* data)
m_rssiCount = 0U;
}
#endif
+7 -2
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2015,2016,2017,2018 by Jonathan Naylor G4KLX
* Copyright (C) 2015,2016,2017,2018,2020 by Jonathan Naylor G4KLX
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -16,10 +16,13 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "Config.h"
#if defined(MODE_NXDN)
#if !defined(NXDNRX_H)
#define NXDNRX_H
#include "Config.h"
#include "NXDNDefines.h"
enum NXDNRX_STATE {
@@ -67,3 +70,5 @@ private:
#endif
#endif
+46 -8
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2009-2018 by Jonathan Naylor G4KLX
* Copyright (C) 2009-2018,2020 by Jonathan Naylor G4KLX
* Copyright (C) 2017 by Andy Uribe CA6JAU
*
* This program is free software; you can redistribute it and/or modify
@@ -18,6 +18,9 @@
*/
#include "Config.h"
#if defined(MODE_NXDN)
#include "Globals.h"
#include "NXDNTX.h"
@@ -53,7 +56,9 @@ m_sincState(),
m_poBuffer(),
m_poLen(0U),
m_poPtr(0U),
m_txDelay(240U) // 200ms
m_txDelay(240U), // 200ms
m_txHang(3000U), // 5s
m_txCount(0U)
{
::memset(m_modState, 0x00U, 16U * sizeof(q15_t));
::memset(m_sincState, 0x00U, 70U * sizeof(q15_t));
@@ -70,10 +75,7 @@ m_txDelay(240U) // 200ms
void CNXDNTX::process()
{
if (m_buffer.getData() == 0U && m_poLen == 0U)
return;
if (m_poLen == 0U) {
if (m_poLen == 0U && m_buffer.getData() > 0U) {
if (!m_tx) {
for (uint16_t i = 0U; i < m_txDelay; i++)
m_poBuffer[m_poLen++] = NXDN_SYNC;
@@ -82,7 +84,8 @@ void CNXDNTX::process()
m_poBuffer[m_poLen++] = NXDN_PREAMBLE[2U];
} else {
for (uint8_t i = 0U; i < NXDN_FRAME_LENGTH_BYTES; i++) {
uint8_t c = m_buffer.get();
uint8_t c = 0U;
m_buffer.get(c);
m_poBuffer[m_poLen++] = c;
}
}
@@ -98,6 +101,8 @@ void CNXDNTX::process()
writeByte(c);
space -= 4U * NXDN_RADIO_SYMBOL_LENGTH;
if (m_duplex)
m_txCount = m_txHang;
if (m_poPtr >= m_poLen) {
m_poPtr = 0U;
@@ -105,10 +110,23 @@ void CNXDNTX::process()
return;
}
}
} else if (m_txCount > 0U) {
// Transmit silence until the hang timer has expired.
uint16_t space = io.getSpace();
while (space > (4U * NXDN_RADIO_SYMBOL_LENGTH)) {
writeSilence();
space -= 4U * NXDN_RADIO_SYMBOL_LENGTH;
m_txCount--;
if (m_txCount == 0U)
return;
}
}
}
uint8_t CNXDNTX::writeData(const uint8_t* data, uint8_t length)
uint8_t CNXDNTX::writeData(const uint8_t* data, uint16_t length)
{
if (length != (NXDN_FRAME_LENGTH_BYTES + 1U))
return 4U;
@@ -155,6 +173,19 @@ void CNXDNTX::writeByte(uint8_t c)
io.write(STATE_NXDN, outBuffer, NXDN_RADIO_SYMBOL_LENGTH * 4U);
}
void CNXDNTX::writeSilence()
{
q15_t inBuffer[4U] = {0, 0, 0, 0};
q15_t intBuffer[NXDN_RADIO_SYMBOL_LENGTH * 4U];
q15_t outBuffer[NXDN_RADIO_SYMBOL_LENGTH * 4U];
::arm_fir_interpolate_q15(&m_modFilter, inBuffer, intBuffer, 4U);
::arm_fir_fast_q15(&m_sincFilter, intBuffer, outBuffer, NXDN_RADIO_SYMBOL_LENGTH * 4U);
io.write(STATE_NXDN, outBuffer, NXDN_RADIO_SYMBOL_LENGTH * 4U);
}
void CNXDNTX::setTXDelay(uint8_t delay)
{
m_txDelay = 300U + uint16_t(delay) * 6U; // 500ms + tx delay
@@ -168,3 +199,10 @@ uint8_t CNXDNTX::getSpace() const
return m_buffer.getSpace() / NXDN_FRAME_LENGTH_BYTES;
}
void CNXDNTX::setParams(uint8_t txHang)
{
m_txHang = txHang * 600U;
}
#endif
+15 -6
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2015,2016,2017,2018 by Jonathan Naylor G4KLX
* Copyright (C) 2015,2016,2017,2018,2020 by Jonathan Naylor G4KLX
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -16,18 +16,20 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "Config.h"
#if defined(MODE_NXDN)
#if !defined(NXDNTX_H)
#define NXDNTX_H
#include "Config.h"
#include "SerialRB.h"
#include "RingBuffer.h"
class CNXDNTX {
public:
CNXDNTX();
uint8_t writeData(const uint8_t* data, uint8_t length);
uint8_t writeData(const uint8_t* data, uint16_t length);
void process();
@@ -35,8 +37,10 @@ public:
uint8_t getSpace() const;
void setParams(uint8_t txHang);
private:
CSerialRB m_buffer;
CRingBuffer<uint8_t> m_buffer;
arm_fir_interpolate_instance_q15 m_modFilter;
arm_fir_instance_q15 m_sincFilter;
q15_t m_modState[16U]; // blockSize + phaseLength - 1, 4 + 9 - 1 plus some spare
@@ -45,9 +49,14 @@ private:
uint16_t m_poLen;
uint16_t m_poPtr;
uint16_t m_txDelay;
uint32_t m_txHang;
uint32_t m_txCount;
void writeByte(uint8_t c);
void writeSilence();
};
#endif
#endif
+7 -1
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2009-2017 by Jonathan Naylor G4KLX
* Copyright (C) 2009-2017,2020 by Jonathan Naylor G4KLX
* Copyright (C) 2018 by Bryan Biedenkapp <[email protected]>
*
* This program is free software; you can redistribute it and/or modify
@@ -18,6 +18,9 @@
*/
#include "Config.h"
#if defined(MODE_P25)
#include "Globals.h"
#include "P25RX.h"
#include "Utils.h"
@@ -535,3 +538,6 @@ void CP25RX::writeRSSILdu(uint8_t* ldu)
m_rssiAccum = 0U;
m_rssiCount = 0U;
}
#endif
+8 -2
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2015,2016,2017 by Jonathan Naylor G4KLX
* Copyright (C) 2015,2016,2017,2020 by Jonathan Naylor G4KLX
* Copyright (C) 2018 by Bryan Biedenkapp <[email protected]>
*
* This program is free software; you can redistribute it and/or modify
@@ -17,10 +17,13 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "Config.h"
#if defined(MODE_P25)
#if !defined(P25RX_H)
#define P25RX_H
#include "Config.h"
#include "P25Defines.h"
enum P25RX_STATE {
@@ -72,3 +75,6 @@ private:
};
#endif
#endif

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