Compare commits

...
341 Commits
Author SHA1 Message Date
Jonathan Naylor 57e692ad8c Small cleanups of the DMR trunking code. 2026-04-24 16:54:23 +01:00
Jonathan Naylor 841d7505c2 Merge pull request #358 from qradiolink/trunking_patches
Add support for DMR tier III trunking
2026-04-24 14:50:28 +01:00
adrian 549dfd7258 Change DMR ALOHA header to 0x17 2026-04-19 11:32:07 +03:00
adrian 30ba4c4c55 Fix merge gone wrong in DMRTX.cpp 2026-04-19 11:12:37 +03:00
adrian a696fd454c DMR trunking patches to DMRTX and SerialPort 2026-04-18 11:29:48 +03:00
Jonathan Naylor 3fd84d5ed4 Fix merge compilation issue. 2026-02-19 15:59:46 +00:00
Jonathan Naylor 78216afbb7 Clean up the ring buffer. 2026-02-18 13:40:05 +00:00
Jonathan Naylor 0308bfc6c7 Merge branch 'master' into mqtt 2026-02-18 13:36:22 +00:00
Jonathan Naylor 278c69152a Merge pull request #356 from F4FXL/C++11-Flags 2026-01-20 20:31:18 +00:00
Geoffrey Merck 8e144e81d0 Add C++11 standard flag to compiler flags
Debian Trixie ships with arm-none-eabi-g++ v14.2.1 which defaults to c++17, this forces compilation with c++11
2026-01-20 20:29:04 +01:00
Jonathan Naylor 5dd59fc473 Merge branch 'master' into mqtt 2025-08-28 17:00:21 +01:00
Jonathan Naylor 5fb5986d50 Remove M17 and AX.25 2025-08-27 18:35:30 +01:00
Jonathan Naylor 824c9b9852 Widened the size of serial data going into M17 and FM. 2025-01-13 15:05:28 +00:00
Jonathan Naylor f324f96db7 Increase the number of frames before YSF declares a signal to be lost. 2024-11-21 17:50:15 +00:00
Jonathan Naylor 15227d9cec Merge branch 'master' into mqtt 2024-10-02 16:10:09 +01:00
Jonathan Naylor c3246dbcb7 Merge branch 'master' of https://github.com/g4klx/MMDVM 2024-10-02 16:05:48 +01:00
Jonathan Naylor 65c51bf849 Merge branch 'master' into mqtt 2024-08-01 12:55:06 +01:00
Jonathan Naylor edd60caad3 Remove the deprecated register keyword. 2024-07-31 19:25:59 +01:00
Jonathan Naylor b8a0f7b1cf Merge pull request #343 from mytechguyri/master
Added option to configure Serial Repeater baud rate
2024-03-10 18:28:44 +00:00
John Tetreault 28e564738e Added option to configure Serial Repeater baud rate so end user can set to 115,200 for high speed Nextion display 2024-03-10 14:19:21 -04:00
Jonathan Naylor a7fddc37e1 Don't send a status when the FM repeater is reset, it causes a loop. 2023-11-18 16:45:36 +00:00
Jonathan Naylor a8bf99037e Merge branch 'master' into mqtt 2023-11-09 19:13:12 +00:00
Jonathan Naylor 029e6df4b9 Remove support for STM32F1* boards, they're just too slow. 2023-11-09 19:08:15 +00: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 508018c89c Add the MMDVM serial protocol document from December 2015. 2023-09-22 16:51:03 +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 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 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 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 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
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 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 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
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 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 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
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 1836ba928e Merge branch 'FM' into FM_Ext 2020-05-11 13:36:38 +01: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 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 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
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
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 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
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 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
126 changed files with 4753 additions and 4414 deletions
+2
View File
@@ -1,3 +1,5 @@
.pio
.vscode
*.o
obj/
bin/
-3
View File
@@ -4,6 +4,3 @@
[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
+2 -2
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
@@ -125,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));
+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
+9 -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
* Copyright (C) 2020 by Phil Taylor M0VSE
*
@@ -19,6 +19,9 @@
*/
#include "Config.h"
#if defined(MODE_FM)
#include "Globals.h"
#include "CalFM.h"
@@ -52,7 +55,7 @@ void CCalFM::process()
{
const TONE_TABLE* entry = NULL;
if (m_modemState!=m_lastState)
if (m_modemState != m_lastState)
{
switch (m_modemState) {
case STATE_FMCAL10K:
@@ -116,7 +119,7 @@ void CCalFM::process()
}
uint8_t CCalFM::write(const uint8_t* data, uint8_t length)
uint8_t CCalFM::write(const uint8_t* data, uint16_t length)
{
if (length != 1U)
return 4U;
@@ -125,3 +128,6 @@ uint8_t CCalFM::write(const uint8_t* data, uint8_t length)
return 0U;
}
#endif
+8 -4
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
* Copyright (C) 2020 by Phil Taylor M0VSE
*
@@ -18,11 +18,13 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "Config.h"
#if defined(MODE_FM)
#if !defined(CALFM_H)
#define CALFM_H
#include "Config.h"
class CCalFM {
public:
CCalFM();
@@ -35,7 +37,7 @@ public:
void fm25kcal();
void fm30kcal();
uint8_t write(const uint8_t* data, uint8_t length);
uint8_t write(const uint8_t* data, uint16_t length);
private:
uint16_t m_frequency;
@@ -49,3 +51,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_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
+43 -13
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2015,2016,2017,2018,2020 by Jonathan Naylor G4KLX
* Copyright (C) 2015,2016,2017,2018,2020,2025 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,31 @@
#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.
// 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 POCSAG support.
#define MODE_POCSAG
// Enable FM support.
#define MODE_FM
// Allow for the use of high quality external clock oscillators
// The number is the frequency of the oscillator in Hertz.
//
@@ -35,22 +60,20 @@
// 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, 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
#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
// #define ARDUINO_DUE_ZUM_V10
// For the SP8NTH board
// #define ARDUINO_DUE_NTH
@@ -66,10 +89,16 @@
// #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
// Set the baud rate of the modem serial repeater for Nextion displays
#define SERIAL_REPEATER_BAUD_RATE 9600
// 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
@@ -82,9 +111,10 @@
// #define USE_ALTERNATE_NXDN_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
#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
+63 -16
View File
@@ -1,7 +1,8 @@
/*
* 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
* Copyright (C) 2022,2023,2026 by Adrian Musceac YO8RZZ
*
* 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 +20,9 @@
*/
#include "Config.h"
#if defined(MODE_DMR)
#include "Globals.h"
#include "DMRSlotType.h"
@@ -39,6 +43,12 @@ const uint8_t IDLE_DATA[] =
0x36U, 0x00U, 0x0DU, 0xFFU, 0x57U, 0xD7U, 0x5DU, 0xF5U, 0xD0U, 0x03U, 0xF6U,
0xE4U, 0x65U, 0x17U, 0x1BU, 0x48U, 0xCAU, 0x6DU, 0x4FU, 0xC6U, 0x10U, 0xB4U};
// DT Terminator with LC, empty
const uint8_t TERMINATOR_DATA[] =
{0x00U, 0xCCU, 0x01U, 0x80U, 0x01U, 0x94U, 0x01U, 0x48U, 0x08U, 0xB0U, 0x08U,
0x80U, 0x04U, 0xADU, 0xFFU, 0x57U, 0xD7U, 0x5DU, 0xF5U, 0xD9U, 0x65U, 0x90U,
0x01U, 0x78U, 0x00U, 0xD0U, 0x08U, 0x40U, 0x14U, 0x00U, 0x0DU, 0x80U, 0x15U};
const uint8_t CACH_INTERLEAVE[] =
{ 1U, 2U, 3U, 5U, 6U, 7U, 9U, 10U, 11U, 13U, 15U, 16U, 17U, 19U, 20U, 21U, 23U,
25U, 26U, 27U, 29U, 30U, 31U, 33U, 34U, 35U, 37U, 39U, 40U, 41U, 43U, 44U, 45U, 47U,
@@ -62,6 +72,7 @@ m_modFilter(),
m_modState(),
m_state(DMRTXSTATE_IDLE),
m_idle(),
m_aloha(),
m_cachPtr(0U),
m_shortLC(),
m_newShortLC(),
@@ -71,7 +82,9 @@ m_poLen(0U),
m_poPtr(0U),
m_frameCount(0U),
m_abortCount(),
m_abort()
m_abort(),
m_controlChannel(false),
m_trunking(false)
{
::memset(m_modState, 0x00U, 16U * sizeof(q15_t));
@@ -144,7 +157,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 +181,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 +205,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 +221,18 @@ 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::writeAloha(const uint8_t* data, uint16_t length)
{
if (length != DMR_FRAME_LENGTH_BYTES)
return 4U;
::memcpy(m_aloha, data, length);
m_controlChannel = true;
return 0U;
}
uint8_t CDMRTX::writeAbort(const uint8_t* data, uint16_t length)
{
if (length != 1U)
return 4U;
@@ -291,16 +315,20 @@ uint8_t CDMRTX::getSpace2() const
void CDMRTX::createData(uint8_t slotIndex)
{
if (m_fifo[slotIndex].getData() >= DMR_FRAME_LENGTH_BYTES && m_frameCount >= STARTUP_COUNT && m_abortCount[slotIndex] >= ABORT_COUNT) {
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 {
m_abort[slotIndex] = false;
// Transmit an idle message
for (unsigned int i = 0U; i < DMR_FRAME_LENGTH_BYTES; i++) {
m_poBuffer[i] = m_idle[i];
if ((slotIndex == 0U) && m_controlChannel && m_trunking)
m_poBuffer[i] = m_aloha[i];
else
m_poBuffer[i] = m_idle[i];
m_markBuffer[i] = MARK_NONE;
}
}
@@ -351,10 +379,14 @@ void CDMRTX::createCACH(uint8_t txSlotIndex, uint8_t rxSlotIndex)
m_cachPtr = 0U;
if (m_cachPtr == 0U) {
if (m_fifo[0U].getData() == 0U && m_fifo[1U].getData() == 0U)
::memcpy(m_shortLC, EMPTY_SHORT_LC, 12U);
else
if ((m_fifo[0U].getData() == 0U) && (m_fifo[1U].getData() == 0U)) {
if (m_trunking)
::memcpy(m_shortLC, m_newShortLC, 12U);
else
::memcpy(m_shortLC, EMPTY_SHORT_LC, 12U);
} else {
::memcpy(m_shortLC, m_newShortLC, 12U);
}
}
::memcpy(m_poBuffer, m_shortLC + m_cachPtr, 3U);
@@ -364,8 +396,8 @@ void CDMRTX::createCACH(uint8_t txSlotIndex, uint8_t rxSlotIndex)
bool at = false;
if (m_frameCount >= STARTUP_COUNT)
at = m_fifo[rxSlotIndex].getData() > 0U;
bool tc = txSlotIndex == 1U;
at = (m_fifo[rxSlotIndex].getData() > 0U);
bool tc = (txSlotIndex == 1U);
bool ls0 = true; // For 1 and 2
bool ls1 = true;
@@ -394,10 +426,18 @@ void CDMRTX::createCACH(uint8_t txSlotIndex, uint8_t rxSlotIndex)
void CDMRTX::setColorCode(uint8_t colorCode)
{
::memcpy(m_idle, IDLE_DATA, DMR_FRAME_LENGTH_BYTES);
if (m_trunking)
::memcpy(m_idle, TERMINATOR_DATA, DMR_FRAME_LENGTH_BYTES);
else
::memcpy(m_idle, IDLE_DATA, DMR_FRAME_LENGTH_BYTES);
CDMRSlotType slotType;
slotType.encode(colorCode, DT_IDLE, m_idle);
if (m_trunking) {
slotType.encode(colorCode, DT_TERMINATOR_WITH_LC, m_idle);
slotType.encode(colorCode, DT_CSBK, m_aloha);
} else {
slotType.encode(colorCode, DT_IDLE, m_idle);
}
}
void CDMRTX::resetFifo1()
@@ -414,3 +454,10 @@ uint32_t CDMRTX::getFrameCount()
{
return m_frameCount;
}
void CDMRTX::setTrunking(bool trunking)
{
m_trunking = trunking;
}
#endif
+18 -8
View File
@@ -1,6 +1,7 @@
/*
* 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
* Copyright (C) 2026 by Adrian Musceac YO8RZZ
*
* 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,13 +18,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,14 +42,16 @@ 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 writeAloha(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);
void setTrunking(bool trunking);
void process();
@@ -59,11 +65,12 @@ 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;
uint8_t m_idle[DMR_FRAME_LENGTH_BYTES];
uint8_t m_aloha[DMR_FRAME_LENGTH_BYTES];
uint8_t m_cachPtr;
uint8_t m_shortLC[12U];
uint8_t m_newShortLC[12U];
@@ -74,6 +81,8 @@ private:
uint32_t m_frameCount;
uint32_t m_abortCount[2U];
bool m_abort[2U];
bool m_controlChannel;
bool m_trunking;
void createData(uint8_t slotIndex);
void createCACH(uint8_t txSlotIndex, uint8_t rxSlotIndex);
@@ -83,3 +92,4 @@ 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
+959 -137
View File
File diff suppressed because it is too large Load Diff
+68 -32
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2020 by Jonathan Naylor G4KLX
* Copyright (C) 2020,2021,2023,2025 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,39 +16,31 @@
* 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 "FMRB.h"
#include "RingBuffer.h"
#include "FMDirectForm1.h"
#include "FMDownsampler.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, const q15_t* samples, uint8_t length);
void samples(bool cos, q15_t* samples, const uint16_t* rssi, uint8_t length);
void process();
@@ -56,15 +48,22 @@ public:
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 ctcssHighThreshold, uint8_t ctcssLowThreshold, uint8_t ctcssLevel, uint8_t kerchunkTime, uint8_t hangTime, bool useCOS, bool cosInvert, uint8_t rfAudioBoost, uint8_t maxDev, uint8_t rxLevel);
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, uint16_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;
@@ -75,26 +74,60 @@ 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;
uint8_t m_accessMode;
bool m_linkMode;
bool m_cosInvert;
bool m_noiseSquelch;
q15_t m_rfAudioBoost;
CFMDownsampler m_downsampler;
q15_t m_extAudioBoost;
CFMDownSampler m_downSampler;
bool m_extEnabled;
q15_t m_rxLevel;
CFMRB m_inputRB;
CFMRB m_outputRB;
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);
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);
@@ -106,3 +139,6 @@ private:
};
#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
+16 -16
View File
@@ -17,6 +17,9 @@
*/
#include "Config.h"
#if defined(MODE_FM)
#include "Globals.h"
#include "FMCTCSSRX.h"
@@ -87,7 +90,7 @@ m_lowThreshold(0),
m_count(0U),
m_q0(0),
m_q1(0),
m_result(CTS_NONE)
m_state(false)
{
}
@@ -111,13 +114,11 @@ uint8_t CFMCTCSSRX::setParams(uint8_t frequency, uint8_t highThreshold, uint8_t
return 0U;
}
uint8_t CFMCTCSSRX::process(q15_t sample)
bool CFMCTCSSRX::process(q15_t sample)
{
//get more dynamic into the decoder by multiplying the sample by 1.5
q31_t sample31 = q31_t(sample) + (q31_t(sample) >> 1);
m_result &= ~CTS_READY;
q31_t q2 = m_q1;
m_q1 = m_q0;
@@ -149,33 +150,32 @@ uint8_t 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;
bool previousCTCSSValid = CTCSS_VALID(m_result);
bool previousState = m_state;
q31_t threshold = m_highThreshold;
if (previousCTCSSValid)
if (previousState)
threshold = m_lowThreshold;
m_result |= CTS_READY;
if (value >= threshold)
m_result |= CTS_VALID;
else
m_result &= ~CTS_VALID;
m_state = value >= threshold;
if (previousCTCSSValid != CTCSS_VALID(m_result))
DEBUG4("CTCSS Value / Threshold / Valid", value, threshold, CTCSS_VALID(m_result));
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;
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
+8 -12
View File
@@ -16,19 +16,12 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#if !defined(FMCTCSSRX_H)
#define FMCTCSSRX_H
#include "Config.h"
const uint8_t CTS_NONE = 0U;
const uint8_t CTS_READY = 1U;
const uint8_t CTS_VALID = 2U;
#if defined(MODE_FM)
#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:
@@ -36,7 +29,7 @@ public:
uint8_t setParams(uint8_t frequency, uint8_t highThreshold, uint8_t lowThreshold);
uint8_t process(q15_t sample);
bool process(q15_t sample);
void reset();
@@ -47,7 +40,10 @@ private:
uint16_t m_count;
q31_t m_q0;
q31_t m_q1;
uint8_t m_result;
bool m_state;
};
#endif
#endif
+12 -3
View File
@@ -17,6 +17,9 @@
*/
#include "Config.h"
#if defined(MODE_FM)
#include "Globals.h"
#include "FMCTCSSTX.h"
@@ -115,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
+15 -13
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_
@@ -38,8 +42,7 @@ class CFMDirectFormI
public:
// convenience function which takes the a0 argument but ignores it!
CFMDirectFormI(const q31_t b0, const q31_t b1, const q31_t b2,
const q31_t, const q31_t a1, const q31_t a2)
CFMDirectFormI(const q31_t b0, const q31_t b1, const q31_t b2, const q31_t, const q31_t a1, const q31_t a2)
{
// FIR coefficients
c_b0 = b0;
@@ -53,21 +56,21 @@ public:
CFMDirectFormI(const CFMDirectFormI &my)
{
// delay line
// delay line
m_x2 = my.m_x2; // x[n-2]
m_y2 = my.m_y2; // y[n-2]
m_x1 = my.m_x1; // x[n-1]
m_y1 = my.m_y1; // y[n-1]
// coefficients
// coefficients
c_b0 = my.c_b0;
c_b1 = my.c_b1;
c_b2 = my.c_b2; // FIR
c_a1 = my.c_a1;
c_a2 = my.c_a2; // IIR
}
}
void reset ()
void reset()
{
m_x1 = 0;
m_x2 = 0;
@@ -79,11 +82,7 @@ public:
inline q15_t filter(const q15_t in)
{
// calculate the output
register q31_t out_upscaled = c_b0 * in
+ c_b1 * m_x1
+ c_b2 * m_x2
- c_a1 * m_y1
- c_a2 * m_y2;
q31_t out_upscaled = c_b0 * in + c_b1 * m_x1 + c_b2 * m_x2 - c_a1 * m_y1 - c_a2 * m_y2;
q15_t out = __SSAT(out_upscaled >> 15, 15);
@@ -108,4 +107,7 @@ private:
q31_t c_a1,c_a2; // IIR
};
#endif /* DIRECTFORMI_H */
#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
+22 -13
View File
@@ -17,27 +17,36 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "Config.h"
#if defined(MODE_FM)
#if !defined(FMDOWNSAMPLER_H)
#define FMDOWNSAMPLER_H
#include "Config.h"
#include "FMDownsampleRB.h"
#include "RingBuffer.h"
#include "FMSamplePairPack.h"
class CFMDownsampler {
class CFMDownSampler {
public:
CFMDownsampler(uint16_t length);
CFMDownSampler(uint16_t length);
void addSample(q15_t sample);
inline bool getPackedData(uint8_t& data){ return m_ringBuffer.get(data); };
inline bool hasOverflowed() { return m_ringBuffer.hasOverflowed(); };
bool getPackedData(TSamplePairPack& data);
uint16_t getData();
void reset();
private:
CFMDownsampleRB m_ringBuffer;
union {
int32_t m_samplePack;
int8_t m_samplePackBytes[4];
};
uint8_t m_packIndex;
uint8_t m_downSampleIndex;
CRingBuffer<TSamplePairPack> m_ringBuffer;
uint32_t m_samplePack;
uint8_t* m_samplePackPointer;
uint8_t m_sampleIndex;
};
#endif
#endif
-63
View File
@@ -1,63 +0,0 @@
/*
* 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"
#include "FMDownsampler.h"
CFMDownsampler::CFMDownsampler(uint16_t length) :
m_ringBuffer(length),//length might need tweaking
m_packIndex(0),
m_downSampleIndex(0)
{
m_samplePack = 0;
}
void CFMDownsampler::addSample(q15_t sample)
{
//only take one of three samples
if(m_downSampleIndex == 0) {
switch(m_packIndex){
case 0:
m_samplePack = int32_t(sample) << 12;
break;
case 1:{
m_samplePack |= int32_t(sample);
//we did not use MSB; skip it
m_ringBuffer.put(m_samplePackBytes[1]);
m_ringBuffer.put(m_samplePackBytes[2]);
m_ringBuffer.put(m_samplePackBytes[3]);
m_samplePack = 0;
}
break;
default:
//should never happen
break;
}
m_packIndex++;
if(m_packIndex >= 2)
m_packIndex = 0;
}
m_downSampleIndex++;
if(m_downSampleIndex >= 3)
m_downSampleIndex = 0;
}
+6
View File
@@ -17,6 +17,9 @@
*/
#include "Config.h"
#if defined(MODE_FM)
#include "Globals.h"
#include "FMKeyer.h"
@@ -214,3 +217,6 @@ bool CFMKeyer::isRunning() const
{
return m_poPos > 0U || m_dotPos > 0U || m_audioPos > 0U;
}
#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(FMKeyer_H)
#define FMKeyer_H
#include "Config.h"
class CFMKeyer {
public:
CFMKeyer();
@@ -52,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
-110
View File
@@ -1,110 +0,0 @@
/*
TX fifo control - Copyright (C) KI6ZUM 2015
Copyright (C) 2015,2016,2020 by Jonathan Naylor G4KLX
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library 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
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with this library; if not, write to the
Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
Boston, MA 02110-1301, USA.
*/
#include "FMRB.h"
CFMRB::CFMRB(uint16_t length) :
m_length(length),
m_head(0U),
m_tail(0U),
m_full(false),
m_overflow(false)
{
m_samples = new q15_t[length];
}
uint16_t CFMRB::getSpace() const
{
uint16_t n = 0U;
if (m_tail == m_head)
n = m_full ? 0U : m_length;
else if (m_tail < m_head)
n = m_length - m_head + m_tail;
else
n = m_tail - m_head;
if (n > m_length)
n = 0U;
return n;
}
uint16_t CFMRB::getData() const
{
if (m_tail == m_head)
return m_full ? m_length : 0U;
else if (m_tail < m_head)
return m_head - m_tail;
else
return m_length - m_tail + m_head;
}
bool CFMRB::put(q15_t sample)
{
if (m_full) {
m_overflow = true;
return false;
}
m_samples[m_head] = sample;
m_head++;
if (m_head >= m_length)
m_head = 0U;
if (m_head == m_tail)
m_full = true;
return true;
}
bool CFMRB::get(q15_t& sample)
{
if (m_head == m_tail && !m_full)
return false;
sample = m_samples[m_tail];
m_full = false;
m_tail++;
if (m_tail >= m_length)
m_tail = 0U;
return true;
}
bool CFMRB::hasOverflowed()
{
bool overflow = m_overflow;
m_overflow = false;
return overflow;
}
void CFMRB::reset()
{
m_head = 0U;
m_tail = 0U;
m_full = false;
m_overflow = false;
}
-72
View File
@@ -1,72 +0,0 @@
/*
Serial fifo control - Copyright (C) KI6ZUM 2015
Copyright (C) 2015,2016,2020 by Jonathan Naylor G4KLX
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library 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
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with this library; if not, write to the
Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
Boston, MA 02110-1301, USA.
*/
#if !defined(FMRB_H)
#define FMRB_H
#if defined(STM32F4XX)
#include "stm32f4xx.h"
#elif defined(STM32F7XX)
#include "stm32f7xx.h"
#elif defined(STM32F105xC)
#include "stm32f1xx.h"
#include <cstddef>
#else
#include <Arduino.h>
#endif
#if defined(__SAM3X8E__) || defined(STM32F105xC)
#define ARM_MATH_CM3
#elif defined(STM32F7XX)
#define ARM_MATH_CM7
#elif defined(STM32F4XX) || defined(__MK20DX256__) || defined(__MK64FX512__) || defined(__MK66FX1M0__)
#define ARM_MATH_CM4
#else
#error "Unknown processor type"
#endif
#include <arm_math.h>
class CFMRB {
public:
CFMRB(uint16_t length);
uint16_t getSpace() const;
uint16_t getData() const;
bool put(q15_t sample);
bool get(q15_t& sample);
bool hasOverflowed();
void reset();
private:
uint16_t m_length;
volatile q15_t* m_samples;
volatile uint16_t m_head;
volatile uint16_t m_tail;
volatile bool m_full;
bool m_overflow;
};
#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
+33 -16
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,2025 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,14 +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)
#if defined(__SAM3X8E__)
#define ARM_MATH_CM3
#elif defined(STM32F7XX)
#define ARM_MATH_CM7
@@ -109,7 +107,7 @@ const uint16_t RX_BLOCK_SIZE = 2U;
const uint16_t TX_RINGBUFFER_SIZE = 500U;
const uint16_t RX_RINGBUFFER_SIZE = 600U;
#if defined(STM32F105xC) || defined(__MK20DX256__)
#if defined(__MK20DX256__)
const uint16_t TX_BUFFER_LEN = 2000U;
#else
const uint16_t TX_BUFFER_LEN = 4000U;
@@ -133,9 +131,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;
@@ -143,28 +147,41 @@ 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 CCalFM calFM;
extern CCalP25 calP25;
extern CCalNXDN calNXDN;
extern CCalPOCSAG calPOCSAG;
extern CCalRSSI calRSSI;
#if defined(MODE_FM)
extern CFM fm;
extern CCalFM calFM;
#endif
extern CCalRSSI calRSSI;
extern CCWIdTX cwIdTX;
#endif
+239 -81
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,2025,2026 by Jonathan Naylor G4KLX
* Copyright (C) 2015 by Jim Mclaughlin KI6ZUM
* Copyright (C) 2016 by Colin Durbridge G4EML
*
@@ -22,16 +22,26 @@
#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_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 +53,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 +75,37 @@ 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
m_pttInvert(false),
m_rxLevel(128 * 128),
m_cwIdTXLevel(128 * 128),
@@ -83,6 +118,7 @@ m_pocsagTXLevel(128 * 128),
m_fmTXLevel(128 * 128),
m_rxDCOffset(DC_OFFSET),
m_txDCOffset(DC_OFFSET),
m_useCOSAsLockout(false),
m_ledCount(0U),
m_ledValue(true),
m_detect(false),
@@ -91,30 +127,52 @@ 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
#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_boxcarFilter.numTaps = BOXCAR_FILTER_LEN;
m_boxcarFilter.pState = m_boxcarState;
m_boxcarFilter.pCoeffs = BOXCAR_FILTER;
m_nxdnFilter.numTaps = NXDN_0_2_FILTER_LEN;
m_nxdnFilter.pState = m_nxdnState;
m_nxdnFilter.pCoeffs = NXDN_0_2_FILTER;
@@ -122,6 +180,8 @@ m_lockout(false)
m_nxdnISincFilter.numTaps = NXDN_ISINC_FILTER_LEN;
m_nxdnISincFilter.pState = m_nxdnISincState;
m_nxdnISincFilter.pCoeffs = NXDN_ISINC_FILTER;
#endif
#endif
initInt();
@@ -132,7 +192,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 +203,34 @@ void CIO::selfTest()
setDMRInt(ledValue);
setYSFInt(ledValue);
setP25Int(ledValue);
#if !defined(USE_ALTERNATE_NXDN_LEDS)
setNXDNInt(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_POCSAG_LEDS)
setPOCSAGInt(false);
#endif
#if !defined(USE_ALTERNATE_FM_LEDS)
setFMInt(false);
#endif
setDStarInt(true);
delayInt(250);
setDMRInt(true);
@@ -219,7 +292,7 @@ void CIO::start()
m_started = true;
setMode();
setMode(STATE_IDLE);
}
void CIO::process()
@@ -229,10 +302,11 @@ void CIO::process()
// 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 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 +330,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 +346,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 +383,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 +393,80 @@ 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_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_DSTAR)
else if (m_modemState == STATE_DSTAR) {
if (m_dstarEnable) {
q15_t GMSKVals[RX_BLOCK_SIZE];
#if defined(USE_DCBLOCKER)
@@ -374,10 +476,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 +495,82 @@ 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_FM)
else if (m_modemState == STATE_FM) {
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_DSTARCAL) {
}
#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 +588,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;
@@ -492,9 +629,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 +653,39 @@ 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_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_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 pocsagTXLevel, uint8_t fmTXLevel, int16_t txDCOffset, int16_t rxDCOffset, bool useCOSAsLockout)
{
m_pttInvert = pttInvert;
@@ -545,6 +701,8 @@ void CIO::setParameters(bool rxInvert, bool txInvert, bool pttInvert, uint8_t rx
m_rxDCOffset = DC_OFFSET + rxDCOffset;
m_txDCOffset = DC_OFFSET + txDCOffset;
m_useCOSAsLockout = useCOSAsLockout;
if (rxInvert)
m_rxLevel = -m_rxLevel;
+48 -14
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,2025 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 pocsagTXLevel, uint8_t fmTXLevel, int16_t txDCOffset, int16_t rxDCOffset, bool useCOSAsLockout);
void getOverflow(bool& adcOverflow, bool& dacOverflow);
@@ -54,28 +58,55 @@ 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
bool m_pttInvert;
q15_t m_rxLevel;
@@ -91,6 +122,8 @@ private:
uint16_t m_rxDCOffset;
uint16_t m_txDCOffset;
bool m_useCOSAsLockout;
uint32_t m_ledCount;
bool m_ledValue;
@@ -125,3 +158,4 @@ private:
};
#endif
+35 -7
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2015,2016,2017,2018,2020 by Jonathan Naylor G4KLX
* Copyright (C) 2015,2016,2017,2018,2020,2025 by Jonathan Naylor G4KLX
* Copyright (C) 2015 by Jim Mclaughlin KI6ZUM
* Copyright (C) 2016 by Colin Durbridge G4EML
*
@@ -185,14 +185,13 @@ void CIO::startInt()
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;
TSample sample = {DC_OFFSET, MARK_NONE};
m_txBuffer.get(sample, control);
DACC->DACC_CDR = sample;
m_txBuffer.get(sample);
DACC->DACC_CDR = sample.sample;
sample = ADC->ADC_CDR[ADC_CDR_Chan];
m_rxBuffer.put(sample, control);
sample.sample = ADC->ADC_CDR[ADC_CDR_Chan];
m_rxBuffer.put(sample);
#if defined(SEND_RSSI_DATA)
m_rssiBuffer.put(ADC->ADC_CDR[RSSI_CDR_Chan]);
@@ -279,4 +278,33 @@ void CIO::delayInt(unsigned int dly)
delay(dly);
}
uint8_t CIO::getCPU() const
{
return 0U;
}
// Code taken from https://github.com/emagii/at91sam3s/blob/master/examples/eefc_uniqueid/main.c
void CIO::getUDID(uint8_t* buffer)
{
uint32_t status;
EFC1->EEFC_FCR = (0x5A << 24) | EFC_FCMD_STUI;
do {
status = EFC1->EEFC_FSR;
} while ( (status & EEFC_FSR_FRDY) == EEFC_FSR_FRDY );
for (uint8_t i = 0; i < 16; i+=4) {
buffer[i + 0] = *(uint32_t *)(IFLASH1_ADDR + i) >> 24;
buffer[i + 1] = *(uint32_t *)(IFLASH1_ADDR + i) >> 16;
buffer[i + 2] = *(uint32_t *)(IFLASH1_ADDR + i) >> 8;
buffer[i + 3] = *(uint32_t *)(IFLASH1_ADDR + i) >> 0;
}
EFC1->EEFC_FCR = (0x5A << 24) | EFC_FCMD_SPUI;
do {
status = EFC1->EEFC_FSR;
} while ( (status & EEFC_FSR_FRDY) != EEFC_FSR_FRDY );
}
#endif
+10 -1
View File
@@ -59,12 +59,21 @@
#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
#endif //#ifndef _IO_PINS_H
+32 -10
View File
@@ -1,7 +1,7 @@
/*
* Copyright (C) 2016 by Jim McLaughlin KI6ZUM
* Copyright (C) 2016,2017,2018 by Andy Uribe CA6JAU
* Copyright (C) 2017,2018,2020 by Jonathan Naylor G4KLX
* Copyright (C) 2017,2018,2020,2023,2025 by Jonathan Naylor G4KLX
* Copyright (C) 2019,2020 by BG5HHP
*
* This program is free software; you can redistribute it and/or modify
@@ -326,35 +326,40 @@ void CIO::startInt()
void CIO::interrupt()
{
uint8_t control = MARK_NONE;
uint16_t sample = DC_OFFSET;
TSample sample = {DC_OFFSET, MARK_NONE};
uint16_t rawRSSI = 0U;
m_txBuffer.get(sample, control);
m_txBuffer.get(sample);
// Send the value to the DAC
#if defined(STM32F4_NUCLEO) && defined(STM32F4_NUCLEO_ARDUINO_HEADER)
DAC_SetChannel2Data(DAC_Align_12b_R, sample);
DAC_SetChannel2Data(DAC_Align_12b_R, sample.sample);
#else
DAC_SetChannel1Data(DAC_Align_12b_R, sample);
DAC_SetChannel1Data(DAC_Align_12b_R, sample.sample);
#endif
// Read value from ADC1 and ADC2
if ((ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC) == RESET)) {
// shouldn't be still in reset at this point so null the sample value?
sample = 0U;
sample.sample = 0U;
} else {
sample = ADC_GetConversionValue(ADC1);
sample.sample = ADC_GetConversionValue(ADC1);
#if defined(SEND_RSSI_DATA)
rawRSSI = ADC_GetConversionValue(ADC2);
#endif
}
// trigger next ADC1
// Trigger next ADC1
ADC_ClearFlag(ADC1, ADC_FLAG_EOC);
ADC_SoftwareStartConv(ADC1);
m_rxBuffer.put(sample, control);
#if defined(SEND_RSSI_DATA)
// Trigger next ADC2
ADC_ClearFlag(ADC2, ADC_FLAG_EOC);
ADC_SoftwareStartConv(ADC2);
#endif
m_rxBuffer.put(sample);
m_rssiBuffer.put(rawRSSI);
m_watchdog++;
@@ -509,4 +514,21 @@ void CIO::delayInt(unsigned int dly)
}
}
uint8_t CIO::getCPU() const
{
return 2U;
}
void CIO::getUDID(uint8_t* buffer)
{
#if defined(STM32F4XX)
::memcpy(buffer, (void *)0x1FFF7A10, 12U);
#elif defined(STM32F722xx)
::memcpy(buffer, (void *)0x1FF07A10, 12U);
#elif defined(STM32F767xx)
::memcpy(buffer, (void *)0x1FF0F420, 12U);
#endif
}
#endif
-476
View File
@@ -1,476 +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
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_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};
for(int i=0; i<7; 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<7; i++){
delay(SystemCoreClock/1000*10);
*foo[i-1] = 0x00;
*foo[i] = 0x01;
}
for(int i=5; 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
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;
#endif
}
void CIO::delayInt(unsigned int dly)
{
delay(dly);
}
#endif
+17 -7
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2016,2017,2018,2020 by Jonathan Naylor G4KLX
* Copyright (C) 2016,2017,2018,2020,2025 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
@@ -161,15 +161,14 @@ void CIO::startInt()
void CIO::interrupt()
{
uint8_t control = MARK_NONE;
uint16_t sample = DC_OFFSET;
TSample sample = {DC_OFFSET, MARK_NONE};
m_txBuffer.get(sample, control);
*(int16_t *)&(DAC0_DAT0L) = sample;
m_txBuffer.get(sample);
*(int16_t *)&(DAC0_DAT0L) = sample.sample;
if ((ADC0_SC1A & ADC_SC1_COCO) == ADC_SC1_COCO) {
sample = ADC0_RA;
m_rxBuffer.put(sample, control);
sample.sample = ADC0_RA;
m_rxBuffer.put(sample);
}
#if defined(SEND_RSSI_DATA)
@@ -263,4 +262,15 @@ void CIO::delayInt(unsigned int dly)
delay(dly);
}
uint8_t CIO::getCPU() const
{
return 1U;
}
void CIO::getUDID(uint8_t* buffer)
{
::memcpy(buffer, (void *)0x4058, 16U);
}
#endif
+78 -33
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,2025 by Jonathan Naylor G4KLX
* Copyright (C) 2016 by Mathis Schmieder DB9MAT
* Copyright (C) 2016 by Colin Durbridge G4EML
*
@@ -18,7 +18,7 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#if defined(STM32F4XX) || defined(STM32F7XX) || defined(STM32F105xC)
#if defined(STM32F4XX) || defined(STM32F7XX)
#include "Config.h"
#include "Globals.h"
@@ -39,37 +39,55 @@ 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;
CCalFM calFM;
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_POCSAG)
CPOCSAGTX pocsagTX;
CCalPOCSAG calPOCSAG;
#endif
#if defined(MODE_FM)
CFM fm;
CCalFM calFM;
#endif
CCalRSSI calRSSI;
CCWIdTX cwIdTX;
@@ -88,48 +106,74 @@ 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_POCSAG)
if (m_pocsagEnable && (m_modemState == STATE_POCSAG || pocsagTX.busy()))
pocsagTX.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_POCSAG)
if (m_modemState == STATE_POCSAGCAL)
calPOCSAG.process();
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 (m_modemState == STATE_IDLE)
cwIdTX.process();
@@ -144,3 +188,4 @@ int main()
}
#endif
+74 -29
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,2025 by Jonathan Naylor G4KLX
* Copyright (C) 2016 by Colin Durbridge G4EML
*
* This program is free software; you can redistribute it and/or modify
@@ -36,37 +36,55 @@ 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;
CCalFM calFM;
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_POCSAG)
CPOCSAGTX pocsagTX;
CCalPOCSAG calPOCSAG;
#endif
#if defined(MODE_FM)
CFM fm;
CCalFM calFM;
#endif
CCalRSSI calRSSI;
CCWIdTX cwIdTX;
@@ -85,49 +103,76 @@ 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_POCSAG)
if (m_pocsagEnable && (m_modemState == STATE_POCSAG || pocsagTX.busy()))
pocsagTX.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_POCSAG)
if (m_modemState == STATE_POCSAGCAL)
calPOCSAG.process();
#endif
if (m_modemState == STATE_IDLE)
cwIdTX.process();
}
Binary file not shown.
+41 -11
View File
@@ -133,19 +133,25 @@ 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)
CXXFLAGS_F4=-c $(MCFLAGS_F4) $(INCLUDES_F4)
CXXFLAGS_F4=-c $(MCFLAGS_F4) $(INCLUDES_F4) -std=c++11
CFLAGS_F7=-c $(MCFLAGS_F7) $(INCLUDES_F7)
CXXFLAGS_F7=-c $(MCFLAGS_F7) $(INCLUDES_F7)
CXXFLAGS_F7=-c $(MCFLAGS_F7) $(INCLUDES_F7) -std=c++11
# Linker flags
LDFLAGS_F4 =-T stm32f4xx_link.ld $(MCFLAGS_F4) --specs=nosys.specs $(INCLUDES_LIBS_F4)
@@ -218,17 +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)
@@ -338,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
+2 -2
View File
@@ -1,5 +1,5 @@
#!/usr/bin/make
# makefile for the arduino due (works with arduino IDE 1.6.11)
# makefile for the arduino due (works with arduino IDE 1.6.12)
#
# The original file can be found at https://github.com/pauldreik/arduino-due-makefile
#
@@ -34,7 +34,7 @@ OBJCOPY:=$(ADIR)/packages/arduino/tools/arm-none-eabi-gcc/4.8.3-2014q1/bin/arm-n
C:=$(CC)
#SAM:=arduino/sam/
SAM:=$(ADIR)/packages/arduino/hardware/sam/1.6.11
SAM:=$(ADIR)/packages/arduino/hardware/sam/1.6.12
#CMSIS:=arduino/sam/system/CMSIS/
#LIBSAM:=arduino/sam/system/libsam
TMPDIR:=$(PWD)/build
-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
+10 -3
View File
@@ -18,6 +18,9 @@
*/
#include "Config.h"
#if defined(MODE_NXDN)
#include "Globals.h"
#include "NXDNTX.h"
@@ -81,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;
}
}
@@ -122,7 +126,7 @@ void CNXDNTX::process()
}
}
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;
@@ -171,7 +175,7 @@ void CNXDNTX::writeByte(uint8_t c)
void CNXDNTX::writeSilence()
{
q15_t inBuffer[4U] = {0x00U, 0x00U, 0x00U, 0x00U};
q15_t inBuffer[4U] = {0, 0, 0, 0};
q15_t intBuffer[NXDN_RADIO_SYMBOL_LENGTH * 4U];
q15_t outBuffer[NXDN_RADIO_SYMBOL_LENGTH * 4U];
@@ -199,3 +203,6 @@ void CNXDNTX::setParams(uint8_t txHang)
{
m_txHang = txHang * 600U;
}
#endif
+10 -5
View File
@@ -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();
@@ -38,7 +40,7 @@ public:
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
@@ -55,3 +57,6 @@ 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
* Copyright (C) 2018 by Bryan Biedenkapp <gatekeep@gmail.com>
*
* 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 <gatekeep@gmail.com>
*
* 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
+12 -4
View File
@@ -18,6 +18,9 @@
*/
#include "Config.h"
#if defined(MODE_P25)
#include "Globals.h"
#include "P25TX.h"
@@ -75,9 +78,11 @@ void CP25TX::process()
for (uint16_t i = 0U; i < m_txDelay; i++)
m_poBuffer[m_poLen++] = P25_START_SYNC;
} else {
uint8_t length = m_buffer.get();
uint8_t length;
m_buffer.get(length);
for (uint8_t i = 0U; i < length; i++) {
uint8_t c = m_buffer.get();
uint8_t c = 0U;
m_buffer.get(c);
m_poBuffer[m_poLen++] = c;
}
}
@@ -118,7 +123,7 @@ void CP25TX::process()
}
}
uint8_t CP25TX::writeData(const uint8_t* data, uint8_t length)
uint8_t CP25TX::writeData(const uint8_t* data, uint16_t length)
{
if (length < (P25_TERM_FRAME_LENGTH_BYTES + 1U))
return 4U;
@@ -168,7 +173,7 @@ void CP25TX::writeByte(uint8_t c)
void CP25TX::writeSilence()
{
q15_t inBuffer[4U] = {0x00U, 0x00U, 0x00U, 0x00U};
q15_t inBuffer[4U] = {0, 0, 0, 0};
q15_t intBuffer[P25_RADIO_SYMBOL_LENGTH * 4U];
q15_t outBuffer[P25_RADIO_SYMBOL_LENGTH * 4U];
@@ -196,3 +201,6 @@ void CP25TX::setParams(uint8_t txHang)
{
m_txHang = txHang * 1200U;
}
#endif
+10 -5
View File
@@ -16,18 +16,20 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "Config.h"
#if defined(MODE_P25)
#if !defined(P25TX_H)
#define P25TX_H
#include "Config.h"
#include "SerialRB.h"
#include "RingBuffer.h"
class CP25TX {
public:
CP25TX();
uint8_t writeData(const uint8_t* data, uint8_t length);
uint8_t writeData(const uint8_t* data, uint16_t length);
void process();
@@ -38,7 +40,7 @@ public:
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_lpFilter;
q15_t m_modState[16U]; // blockSize + phaseLength - 1, 4 + 9 - 1 plus some spare
@@ -55,3 +57,6 @@ private:
};
#endif
#endif
+9 -3
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_POCSAG)
#include "Globals.h"
#include "POCSAGTX.h"
@@ -61,7 +64,8 @@ void CPOCSAGTX::process()
m_poBuffer[m_poLen++] = POCSAG_SYNC;
} else {
for (uint8_t i = 0U; i < POCSAG_FRAME_LENGTH_BYTES; i++) {
uint8_t c = m_buffer.get();
uint8_t c = 0U;
m_buffer.get(c);
m_poBuffer[m_poLen++] = c;
}
}
@@ -95,7 +99,7 @@ bool CPOCSAGTX::busy()
return false;
}
uint8_t CPOCSAGTX::writeData(const uint8_t* data, uint8_t length)
uint8_t CPOCSAGTX::writeData(const uint8_t* data, uint16_t length)
{
if (length != POCSAG_FRAME_LENGTH_BYTES)
return 4U;
@@ -147,3 +151,5 @@ uint8_t CPOCSAGTX::getSpace() const
return m_buffer.getSpace() / POCSAG_FRAME_LENGTH_BYTES;
}
#endif
+10 -6
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2015-2019 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,18 +16,20 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "Config.h"
#if defined(MODE_POCSAG)
#if !defined(POCSAGTX_H)
#define POCSAGTX_H
#include "Config.h"
#include "SerialRB.h"
#include "RingBuffer.h"
class CPOCSAGTX {
public:
CPOCSAGTX();
uint8_t writeData(const uint8_t* data, uint8_t length);
uint8_t writeData(const uint8_t* data, uint16_t length);
void writeByte(uint8_t c);
@@ -40,7 +42,7 @@ public:
bool busy();
private:
CSerialRB m_buffer;
CRingBuffer<uint8_t> m_buffer;
arm_fir_instance_q15 m_modFilter;
q15_t m_modState[170U]; // NoTaps + BlockSize - 1, 6 + 160 - 1 plus some spare
uint8_t m_poBuffer[200U];
@@ -51,3 +53,5 @@ private:
#endif
#endif
+32 -14
View File
@@ -1,17 +1,35 @@
This is the source code of the MMDVM firmware that supports D-Star, DMR,
System Fusion, P25, NXDN, POCSAG, and FM modes.
This is the source code of the MMDVM firmware that supports D-Star, DMR, System Fusion, P25, NXDN, POCSAG, and FM modes.
It runs on the Arduino Due, the ST-Micro STM32F1xxx, STM32F4xxx and STM32F7xxx
processors, as well as the Teensy 3.1/3.2/3.5/3.6. What these platforms have in
common is the use of an ARM Cortex-M3, M4, or M7 processors with a clock speed
greater than 70 MHz, and access to at least one analogue to digital converter
and one digital to analogue converter.
It runs on the Arduino Due, the ST-Micro STM32F4xxx and STM32F7xxx processors, as well as the Teensy 3.5/3.6. What these platforms have in common is the use of an ARM Cortex-M3, M4, or M7 processors with a minimum clock speed greater of 80 MHz, and access to at least one analogue to digital converter, one digital to analogue converter, as well as a number of GPIO pins.
In order to build this software for the Arduino Due, you will need to edit a
file within the Arduino GUI and that is detailed in the BUILD.txt file. The
STM32 support is being supplied via the ARM GCC compiler. The Teensy support
uses Teensyduino.
In order to build this software for the Arduino Due, you will need to edit a file within the Arduino GUI and that is detailed in the BUILD.txt file. The STM32 support is supplied via the ARM GCC compiler. The Teensy support uses Teensyduino.
This software is licenced under the GPL v2 and is intended for amateur and
educational use only. Use of this software for commercial purposes is strictly
forbidden.
This software is licenced under the GPL v2 and is primarily intended for amateur and educational use.
Portions of the ARM support code include the following copyright:
Copyright (c) 2011 - 2013 ARM LIMITED
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
- Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
- Neither the name of ARM nor the names of its contributors may be used
to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDERS AND CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
-102
View File
@@ -1,102 +0,0 @@
/*
TX fifo control - Copyright (C) KI6ZUM 2015
Copyright (C) 2015,2016 by Jonathan Naylor G4KLX
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library 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
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with this library; if not, write to the
Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
Boston, MA 02110-1301, USA.
*/
#include "RSSIRB.h"
CRSSIRB::CRSSIRB(uint16_t length) :
m_length(length),
m_head(0U),
m_tail(0U),
m_full(false),
m_overflow(false)
{
m_rssi = new uint16_t[length];
}
uint16_t CRSSIRB::getSpace() const
{
uint16_t n = 0U;
if (m_tail == m_head)
n = m_full ? 0U : m_length;
else if (m_tail < m_head)
n = m_length - m_head + m_tail;
else
n = m_tail - m_head;
if (n > m_length)
n = 0U;
return n;
}
uint16_t CRSSIRB::getData() const
{
if (m_tail == m_head)
return m_full ? m_length : 0U;
else if (m_tail < m_head)
return m_head - m_tail;
else
return m_length - m_tail + m_head;
}
bool CRSSIRB::put(uint16_t rssi)
{
if (m_full) {
m_overflow = true;
return false;
}
m_rssi[m_head] = rssi;
m_head++;
if (m_head >= m_length)
m_head = 0U;
if (m_head == m_tail)
m_full = true;
return true;
}
bool CRSSIRB::get(uint16_t& rssi)
{
if (m_head == m_tail && !m_full)
return false;
rssi = m_rssi[m_tail];
m_full = false;
m_tail++;
if (m_tail >= m_length)
m_tail = 0U;
return true;
}
bool CRSSIRB::hasOverflowed()
{
bool overflow = m_overflow;
m_overflow = false;
return overflow;
}
-59
View File
@@ -1,59 +0,0 @@
/*
Serial fifo control - Copyright (C) KI6ZUM 2015
Copyright (C) 2015,2016 by Jonathan Naylor G4KLX
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library 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
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with this library; if not, write to the
Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
Boston, MA 02110-1301, USA.
*/
#if !defined(RSSIRB_H)
#define RSSIRB_H
#if defined(STM32F4XX)
#include "stm32f4xx.h"
#elif defined(STM32F7XX)
#include "stm32f7xx.h"
#elif defined(STM32F105xC)
#include "stm32f1xx.h"
#include <cstddef>
#else
#include <Arduino.h>
#endif
class CRSSIRB {
public:
CRSSIRB(uint16_t length);
uint16_t getSpace() const;
uint16_t getData() const;
bool put(uint16_t rssi);
bool get(uint16_t& rssi);
bool hasOverflowed();
private:
uint16_t m_length;
volatile uint16_t* m_rssi;
volatile uint16_t m_head;
volatile uint16_t m_tail;
volatile bool m_full;
bool m_overflow;
};
#endif
-47
View File
@@ -1,47 +0,0 @@
/*
* Copyright (C) 2017 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 3 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, see <http://www.gnu.org/licenses/>.
*
* FIFO ring buffer
* source:
* http://stackoverflow.com/questions/6822548/correct-way-of-implementing-a-uart-receive-buffer-in-a-small-arm-microcontroller
* (modified)
*
*/
#if !defined(RINGBUFF_H)
#define RINGBUFF_H
#define RINGBUFF_SIZE(ringBuff) (ringBuff.size) /* serial buffer in bytes (power 2) */
#define RINGBUFF_MASK(ringBuff) (ringBuff.size-1U) /* buffer size mask */
/* Buffer read / write macros */
#define RINGBUFF_RESET(ringBuff) (ringBuff).rdIdx = ringBuff.wrIdx = 0
#define RINGBUFF_WRITE(ringBuff, dataIn) (ringBuff).data[RINGBUFF_MASK(ringBuff) & ringBuff.wrIdx++] = (dataIn)
#define RINGBUFF_READ(ringBuff) ((ringBuff).data[RINGBUFF_MASK(ringBuff) & ((ringBuff).rdIdx++)])
#define RINGBUFF_EMPTY(ringBuff) ((ringBuff).rdIdx == (ringBuff).wrIdx)
#define RINGBUFF_FULL(ringBuff) ((RINGBUFF_MASK(ringBuff) & ringFifo.rdIdx) == (RINGBUFF_MASK(ringBuff) & ringFifo.wrIdx))
#define RINGBUFF_COUNT(ringBuff) (RINGBUFF_MASK(ringBuff) & ((ringBuff).wrIdx - (ringBuff).rdIdx))
/* Buffer type */
#define DECLARE_RINGBUFFER_TYPE(name, _size) \
typedef struct{ \
uint32_t size; \
uint32_t wrIdx; \
uint32_t rdIdx; \
uint8_t data[_size]; \
}name##_t
#endif
+23 -17
View File
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2020 by Jonathan Naylor G4KLX
* Copyright (C) 2020,2026 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
@@ -16,21 +17,19 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#if !defined(FMDOWNSAMPLERB_H)
#define FMDOWNSAMPLERB_H
#if !defined(RINGBUFFER_H)
#define RINGBUFFER_H
#if defined(STM32F4XX)
#include "stm32f4xx.h"
#elif defined(STM32F7XX)
#include "stm32f7xx.h"
#elif defined(STM32F105xC)
#include "stm32f1xx.h"
#include <cstddef>
#else
#include <Arduino.h>
#undef PI
#endif
#if defined(__SAM3X8E__) || defined(STM32F105xC)
#if defined(__SAM3X8E__)
#define ARM_MATH_CM3
#elif defined(STM32F7XX)
#define ARM_MATH_CM7
@@ -42,27 +41,34 @@
#include <arm_math.h>
class CFMDownsampleRB {
template <typename TDATATYPE>
class CRingBuffer {
public:
CFMDownsampleRB(uint16_t length);
CRingBuffer(uint16_t length = 370U);
uint16_t getSpace() const;
uint16_t getData() const;
bool put(uint8_t sample);
bool put(const TDATATYPE& item) volatile;
bool get(uint8_t& sample);
bool get(TDATATYPE& item) volatile;
TDATATYPE peek() const;
bool hasOverflowed();
void reset();
private:
uint16_t m_length;
volatile uint8_t* m_samples;
volatile uint16_t m_head;
volatile uint16_t m_tail;
volatile bool m_full;
bool m_overflow;
uint16_t m_length;
TDATATYPE* m_buffer;
volatile uint16_t m_head;
volatile uint16_t m_tail;
volatile bool m_full;
bool m_overflow;
};
#include "RingBuffer.impl.h"
#endif
+25 -12
View File
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2020 by Jonathan Naylor G4KLX
* Copyright (C) 2020,2026 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
@@ -16,20 +17,19 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "RingBuffer.h"
#include "FMDownsampleRB.h"
CFMDownsampleRB::CFMDownsampleRB(uint16_t length) :
template <typename TDATATYPE> CRingBuffer<TDATATYPE>::CRingBuffer(uint16_t length) :
m_length(length),
m_head(0U),
m_tail(0U),
m_full(false),
m_overflow(false)
{
m_samples = new uint8_t[length];
m_buffer = new TDATATYPE[length];
}
uint16_t CFMDownsampleRB::getSpace() const
template <typename TDATATYPE> uint16_t CRingBuffer<TDATATYPE>::getSpace() const
{
uint16_t n = 0U;
@@ -46,7 +46,7 @@ uint16_t CFMDownsampleRB::getSpace() const
return n;
}
uint16_t CFMDownsampleRB::getData() const
template <typename TDATATYPE> uint16_t CRingBuffer<TDATATYPE>::getData() const
{
if (m_tail == m_head)
return m_full ? m_length : 0U;
@@ -56,14 +56,14 @@ uint16_t CFMDownsampleRB::getData() const
return m_length - m_tail + m_head;
}
bool CFMDownsampleRB::put(uint8_t sample)
template <typename TDATATYPE> bool CRingBuffer<TDATATYPE>::put(const TDATATYPE& item) volatile
{
if (m_full) {
m_overflow = true;
return false;
}
m_samples[m_head] = sample;
m_buffer[m_head] = item;
m_head++;
if (m_head >= m_length)
@@ -75,12 +75,17 @@ bool CFMDownsampleRB::put(uint8_t sample)
return true;
}
bool CFMDownsampleRB::get(uint8_t& sample)
template <typename TDATATYPE> TDATATYPE CRingBuffer<TDATATYPE>::peek() const
{
return m_buffer[m_tail];
}
template <typename TDATATYPE> bool CRingBuffer<TDATATYPE>::get(TDATATYPE& item) volatile
{
if (m_head == m_tail && !m_full)
return false;
sample = m_samples[m_tail];
item = m_buffer[m_tail];
m_full = false;
@@ -91,7 +96,7 @@ bool CFMDownsampleRB::get(uint8_t& sample)
return true;
}
bool CFMDownsampleRB::hasOverflowed()
template <typename TDATATYPE> bool CRingBuffer<TDATATYPE>::hasOverflowed()
{
bool overflow = m_overflow;
@@ -99,3 +104,11 @@ bool CFMDownsampleRB::hasOverflowed()
return overflow;
}
template <typename TDATATYPE> void CRingBuffer<TDATATYPE>::reset()
{
m_head = 0U;
m_tail = 0U;
m_full = false;
m_overflow = false;
}
Submodule STM32F10X_Lib deleted from 417e0c2f4a
+3 -1
View File
@@ -1,5 +1,7 @@
/*
* source: http://mightydevices.com/?p=144
* Copyright (C) 2017 by Wojciech Krutnik N0CALL
*
* Source: http://mightydevices.com/?p=144
*
* 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
+100
View File
@@ -0,0 +1,100 @@
/*
* 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.
*/
#if defined(STM32F4XX) || defined(STM32F7XX)
#include "STMUART.h"
CSTMUART::CSTMUART() :
m_usart(NULL)
{
}
void CSTMUART::init(USART_TypeDef* usart)
{
m_usart = usart;
}
void CSTMUART::write(const uint8_t * data, uint16_t length)
{
if(length == 0U || m_usart == NULL)
return;
m_txFifo.put(data[0]);
USART_ITConfig(m_usart, USART_IT_TXE, ENABLE);//switch TX IRQ is on
for(uint16_t i = 1U; i < length; i++) {
m_txFifo.put(data[i]);
}
USART_ITConfig(m_usart, USART_IT_TXE, ENABLE);//make sure TX IRQ is on
}
uint8_t CSTMUART::read()
{
return m_rxFifo.get();
}
void CSTMUART::handleIRQ()
{
if(m_usart == NULL)
return;
if (USART_GetITStatus(m_usart, USART_IT_RXNE)) {
if(!m_rxFifo.isFull())
m_rxFifo.put((uint8_t) USART_ReceiveData(m_usart));
USART_ClearITPendingBit(USART1, USART_IT_RXNE);
}
if (USART_GetITStatus(m_usart, USART_IT_TXE)) {
if(!m_txFifo.isEmpty())
USART_SendData(m_usart, m_txFifo.get());
USART_ClearITPendingBit(m_usart, USART_IT_TXE);
if (m_txFifo.isEmpty()) // if there's no more data to transmit then turn off TX interrupts
USART_ITConfig(m_usart, USART_IT_TXE, DISABLE);
}
}
// Flushes the transmit shift register
// warning: this call is blocking
void CSTMUART::flush()
{
if(m_usart == NULL)
return;
// wait until the TXE shows the shift register is empty
while (USART_GetITStatus(m_usart, USART_FLAG_TXE))
;
}
uint16_t CSTMUART::available()
{
return m_rxFifo.isEmpty() ? 0U : 1U;
}
uint16_t CSTMUART::availableForWrite()
{
return m_txFifo.isFull() ? 0U : 1U;
}
#endif
+91
View File
@@ -0,0 +1,91 @@
/*
* 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.
*/
#if defined(STM32F4XX) || defined(STM32F7XX)
#if !defined(STMUART_H)
#define STMUART_H
#if defined(STM32F4XX)
#include "stm32f4xx.h"
#elif defined(STM32F7XX)
#include "stm32f7xx.h"
#endif
const uint16_t BUFFER_SIZE = 2048U; //needs to be a power of 2 !
const uint16_t BUFFER_MASK = BUFFER_SIZE - 1;
class CSTMUARTFIFO {
public:
CSTMUARTFIFO() :
m_head(0U),
m_tail(0U)
{
}
void put(uint8_t data)
{
m_buffer[BUFFER_MASK & (m_head++)] = data;
}
uint8_t get()
{
return m_buffer[BUFFER_MASK & (m_tail++)];
}
void reset()
{
m_tail = 0U;
m_head = 0U;
}
bool isEmpty()
{
return m_tail == m_head;
}
bool isFull()
{
return ((m_head + 1U) & BUFFER_MASK) == (m_tail & BUFFER_MASK);
}
private:
volatile uint8_t m_buffer[BUFFER_SIZE];
volatile uint16_t m_head;
volatile uint16_t m_tail;
};
class CSTMUART {
public:
CSTMUART();
void init(USART_TypeDef* usart);
void write(const uint8_t * data, uint16_t length);
uint8_t read();
void handleIRQ();
void flush();
uint16_t available();
uint16_t availableForWrite();
private:
USART_TypeDef * m_usart;
CSTMUARTFIFO m_rxFifo;
CSTMUARTFIFO m_txFifo;
};
#endif
#endif

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