Compare commits

..
195 Commits
Author SHA1 Message Date
Jonathan Naylor 0ea732780d Implement Kerchunk TX option. 2020-06-20 21:03:11 +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 7169836621 Merge branch 'master' into FM 2020-05-13 12:01:19 +01:00
Jonathan Naylor c84d227242 Merge branch 'master' into TXHang 2020-05-13 12:00:23 +01:00
Jonathan Naylor 4f93c6022c Merge pull request #273 from F4FXL/FM_Ext
Send unsigned data and simplify downdampling code
2020-05-13 11:44:37 +01:00
Geoffrey Merck 81f6b6be53 Send usigned data and simplify downdamplign code 2020-05-13 12:42:14 +02:00
Jonathan Naylor fa9f89700f Merge pull request #272 from F4FXL/FM_Ext
Fix compiler warnings
2020-05-13 11:10:04 +01:00
Geoffrey Merck 9023b6ae13 Correct indentation 2020-05-13 12:03:52 +02:00
Geoffrey Merck df23e15c91 Fix compilation warnings 2020-05-13 11:52:59 +02:00
Jonathan Naylor 51e5e7b851 Merge branch 'FM' into FM_Ext 2020-05-13 10:31:17 +01:00
Jonathan Naylor 8e52bdcc5c Merge branch 'master' into FM 2020-05-13 10:30:46 +01:00
Jonathan Naylor 1332c6544b Merge pull request #271 from shawnchain/fix_led_alternate_macro_names
Fix led alternate macro names
2020-05-13 09:36:05 +01:00
Shawn Chain 703ed2628d Init FM led/mode GPIO pin 2020-05-13 16:28:05 +08:00
Shawn Chain f3943a7888 fix wrong macro name for LED/MODE pin 2020-05-13 16:27:12 +08:00
Jonathan Naylor 737454281a Merge pull request #270 from shawnchain/add_nqf_board_pin_defs_header
pin header file for nqf board
2020-05-13 08:43:19 +01:00
Shawn Chain 1aef42bb21 add missing header files for nqf board 2020-05-13 15:28:08 +08:00
Jonathan Naylor 9550299e4d Merge pull request #268 from shawnchain/drcc_dvm_nqf_board_support
Supports drcc_dvm_nqf board
2020-05-13 07:46:58 +01:00
Jonathan Naylor 056dd908b3 Merge pull request #269 from F4FXL/FM_Ext
Fix crash when writing to serial, Tighten handling of incomign data
2020-05-13 07:41:39 +01:00
Geoffrey Merck 62f239ccc9 Fix modem crash while writing to serial, Split IO write and serial write to 2 separate loops. 2020-05-13 08:31:59 +02:00
Shawn Chain f8879e1f25 Supports drcc_dvm_nqf board 2020-05-13 13:51:02 +08:00
Geoffrey Merck 994226e4b1 Tighten incoming data, Add FM UpSampler 2020-05-12 22:06:26 +02:00
Jonathan Naylor 2cc6c1f68f Merge pull request #267 from F4FXL/FM_Ext
Write Audio to serial
2020-05-12 19:00:09 +01:00
Geoffrey Merck 8e8cf35b19 Merge remote-tracking branch 'upstream/FM_Ext' into FM_Ext 2020-05-12 17:55:41 +02:00
Geoffrey Merck 66de35b6d8 Move downsamplig call back to samples 2020-05-12 17:55:24 +02:00
Jonathan Naylor 43e00bbe1d Merge pull request #266 from shawnchain/io_pins_def_for_each_board_type
Extract the IO pins defs from IOSTM.cpp to separate files
2020-05-12 16:28:04 +01:00
Shawn Chain f31b682625 Extract the IO pins defs from IOSTM.cpp to separate files 2020-05-12 23:21:05 +08:00
Jonathan Naylor 7dc420c8ff Add the FM controller status to the FM Status message. 2020-05-12 15:58:54 +01:00
Jonathan Naylor df0a9ebe72 Merge branch 'FM' into FM_Ext 2020-05-12 15:51:41 +01:00
Jonathan Naylor 66feb9d50b Merge branch 'master' into FM 2020-05-12 15:48:44 +01:00
Jonathan Naylor 0b14b0b73f Merge pull request #265 from shawnchain/mode_led_fm_fix
fix compile error if no MODE_LEDS defined
2020-05-12 15:48:22 +01:00
Shawn Chain 50706c6f09 fix compile error if no MODE_LEDS defined 2020-05-12 22:44:15 +08:00
Jonathan Naylor e957f0154e Merge pull request #264 from F4FXL/FM_Ext
Fix Silence
2020-05-12 15:25:27 +01:00
Geoffrey Merck b10c72fd78 Merge branch 'FM_Ext' of https://github.com/F4FXL/MMDVM into FM_Ext 2020-05-12 16:22:54 +02:00
Geoffrey Merck 496afcb40e Fix silence 2020-05-12 16:21:24 +02:00
Geoffrey Merck 9467b10e5c Fix silence 2020-05-12 16:19:19 +02:00
Jonathan Naylor 13c5f7b0b4 Merge pull request #263 from F4FXL/FM_Ext
Fix FM not transmitting, remove silence for testing
2020-05-12 15:07:17 +01:00
Jonathan Naylor 435544f7a1 Add CTCSS hysteresis. 2020-05-12 13:55:30 +01:00
Geoffrey Merck b64712f657 Restore silence 2020-05-12 14:45:03 +02:00
Geoffrey Merck d23c0900c1 Fix compilation 2020-05-12 14:18:27 +02:00
Geoffrey Merck a0a3080da2 Make sure downsampler always buffers 22 samples at a time 2020-05-12 14:15:04 +02:00
Geoffrey Merck 0fad84b46d Remove silence 2020-05-12 09:29:01 +02:00
Geoffrey Merck 1b40044a23 Re-enable write audio to serial 2020-05-12 09:28:24 +02:00
Geoffrey Merck a671263398 Merge remote-tracking branch 'upstream/FM_Ext' into FM_Ext 2020-05-12 08:37:10 +02:00
Geoffrey Merck ca1cc7096a Fix modem not goign on transmit, still some cleansing to be done 2020-05-12 08:36:38 +02:00
Geoffrey Merck a5aabd8fac Update TX ON/OFF debug info 2020-05-12 08:35:48 +02:00
Jonathan Naylor 6d0e57ea88 Merge pull request #262 from F4FXL/FM_Ext
Still some work in progress to fix no TX
2020-05-11 23:39:05 +01:00
Geoffrey Merck 1d04c1e903 Typo 2020-05-11 22:35:46 +02:00
Geoffrey Merck 042c26b3bb Trying to fix no tx, WIP 2020-05-11 22:32:24 +02:00
Geoffrey Merck b4a125a759 Add debug info TX switching 2020-05-11 22:31:50 +02:00
Geoffrey Merck 8ecf80ff8f Merge branch 'FM_Ext' of https://github.com/F4FXL/MMDVM into FM_Ext 2020-05-11 19:02:24 +02:00
Geoffrey Merck 6786b9b6b1 Temporary revert to previous code 2020-05-11 19:02:08 +02:00
Geoffrey Merck 86ffc69b30 Add getData 2020-05-11 19:02:08 +02:00
Geoffrey Merck 5d4df6ffd9 Write larger chunks of data to IO 2020-05-11 19:02:08 +02:00
Geoffrey Merck eac2aa4ac1 Write larger chunks of FM audio to the serial port 2020-05-11 19:02:08 +02:00
Geoffrey Merck 8cbd52aa72 Update to SAM 1.6.12 2020-05-11 19:02:08 +02:00
Jonathan Naylor 99b853a976 Stop the status timer when leaving TX. 2020-05-11 15:00:53 +01:00
Jonathan Naylor 15bc1a4027 Merge branch 'FM' into FM_Ext 2020-05-11 13:42:14 +01:00
Jonathan Naylor 75e32e1b71 Merge branch 'master' into FM 2020-05-11 13:41:37 +01:00
Jonathan Naylor 7ebc4044f9 Remove Coocox file. 2020-05-11 13:41:10 +01:00
Jonathan Naylor 1836ba928e Merge branch 'FM' into FM_Ext 2020-05-11 13:36:38 +01:00
Jonathan Naylor c54c13c146 Merge branch 'master' into FM 2020-05-11 13:33:49 +01:00
phl0 17a3743cd8 Add GPIO and LEDs for FM mode 2020-05-11 14:27:23 +02:00
Jonathan Naylor 4a5a260c28 Perform FM mode changing in a more conventional manner. 2020-05-11 13:15:13 +01:00
Geoffrey Merck 4bcc1e88c4 Update to SAM 1.6.12 2020-05-11 07:53:21 +02:00
Jonathan Naylor 4cba5931f4 Loosen the conditions for returning to STATE_IDLE 2020-05-10 21:29:01 +01:00
Jonathan Naylor 89458a2c93 Release to STATE_IDLE under simpler conditions. 2020-05-10 21:25:10 +01:00
Jonathan Naylor c91a42f53d Merge pull request #260 from F4FXL/FM_Ext
Write audio to serial port, blank too ext high audio, really ignore ext audio when ext is disabled
2020-05-10 21:04:22 +01:00
Geoffrey Merck 470a070d96 Merge remote-tracking branch 'upstream/FM_Ext' into FM_Ext 2020-05-10 21:59:57 +02:00
Geoffrey Merck 36537c981c Write audio to serial port, blank to high audio, really ignore ext aduio when ext is disabled 2020-05-10 21:59:14 +02:00
Jonathan Naylor c85978a4e3 Rescale the FM calibration level. 2020-05-10 17:33:50 +01:00
Jonathan Naylor d0062a55f8 Rescale the FM calibration output. 2020-05-10 17:31:21 +01:00
Jonathan Naylor 66ea3ad0d1 Only use the CTCSS delay when not using COS. 2020-05-10 17:15:54 +01:00
Jonathan Naylor 3ad443dc2a Remove the delay when using COS. 2020-05-10 17:13:10 +01:00
Jonathan Naylor da16ee277c Merge pull request #258 from F4FXL/FM_Ext
Fix repeater stuck on transmit
2020-05-10 17:06:57 +01:00
Jonathan Naylor 85acdc7121 Merge pull request #259 from F4FXL/FM
Fix stuck on TX
2020-05-10 17:06:26 +01:00
Geoffrey Merck a2518e99f2 Fix stuck on TX 2020-05-10 17:29:17 +02:00
Geoffrey Merck 0f51ddd0bd Fix repeater stuck on transmit 2020-05-10 17:18:59 +02:00
Jonathan Naylor aaa72e769f Merge pull request #257 from F4FXL/FM_Ext
Only use one RingBuffer plus some bug fixes
2020-05-10 08:14:08 +01:00
Geoffrey Merck 0e8fdb381a Fix State machine not changing state 2020-05-10 09:07:21 +02:00
Geoffrey Merck 0b31c40c2b Made Get volatile 2020-05-10 08:01:10 +02:00
Geoffrey Merck 2b3df4e901 Merge remote-tracking branch 'upstream/FM_Ext' into FM_Ext 2020-05-10 07:01:21 +02:00
Geoffrey Merck 807f01ba72 Get rid of annoying PI warning 2020-05-10 07:00:58 +02:00
Geoffrey Merck 03f18451f7 Remove CSerialBuffer, use CRingBuffer 2020-05-10 06:50:35 +02:00
Geoffrey Merck 16c3d418eb Buffer no longer volatile, not needed 2020-05-10 00:03:32 +02:00
Geoffrey Merck 55df5fe04c Remove useless stuff 2020-05-10 00:03:05 +02:00
Geoffrey Merck b0ba3b5dd8 SerialRB now inherits from RingBuffer 2020-05-09 19:57:40 +02:00
Geoffrey Merck 05d21c0a14 TX Buffer now using Templae RB 2020-05-09 17:44:44 +02:00
Geoffrey Merck 26a703c68c IO RXbuffer now uses template RingBuffer 2020-05-09 17:35:38 +02:00
Geoffrey Merck 6c3dd265ab No more need to specify each types for ringBuffer 2020-05-09 14:14:53 +02:00
Jonathan Naylor c04e207821 Insert the missing silence. 2020-05-09 13:10:02 +01:00
Jonathan Naylor 67e0bf02e2 Merge branch 'FM' into FM_Ext 2020-05-09 13:06:32 +01:00
Jonathan Naylor 3bb7cde322 Add input audio delay to match the CTCSS decoder results. 2020-05-09 13:01:02 +01:00
Jonathan Naylor fa29a27695 Ensure all output audio is flushed before leaving FM state. 2020-05-09 12:53:50 +01:00
Geoffrey Merck 7302dc8bd7 Replace RSSI RB with template RB 2020-05-09 11:08:18 +02:00
Jonathan Naylor bb7383a301 Merge pull request #256 from F4FXL/FM_Ext
Add missing files
2020-05-09 10:03:04 +01:00
Geoffrey Merck 61a69d8536 Add missing file 2020-05-09 11:01:28 +02:00
Jonathan Naylor 5a11fcea5b Merge pull request #255 from F4FXL/FM_Ext
Add RingBuffer Template
2020-05-09 09:59:57 +01:00
Geoffrey Merck 05775f0bfa Add RingBuffer Template 2020-05-09 10:57:16 +02:00
Jonathan Naylor 973a1391d7 Merge pull request #254 from F4FXL/FM_Ext
Handle Incoming external audio
2020-05-09 07:36:32 +01:00
Geoffrey Merck 5d45649096 Simplify code 2020-05-09 08:29:31 +02:00
Geoffrey Merck e91c4417cb Handle incoming audio 2020-05-09 08:23:02 +02:00
Geoffrey Merck ff3e6feeb6 Use more explicit names 2020-05-09 08:00:24 +02:00
Geoffrey Merck 0e2a83bc7b Add incoming network data buffer 2020-05-09 07:57:45 +02:00
Jonathan Naylor c84dbd02e5 Merge pull request #253 from F4FXL/FM_Ext
FM into FM_Ext
2020-05-08 21:07:46 +01:00
Geoffrey Merck c0aad5effa Add mising initilizer 2020-05-08 21:47:03 +02:00
Geoffrey Merck e0234dfc00 Merge remote-tracking branch 'upstream/FM' into FM_Ext 2020-05-08 21:39:18 +02:00
Jonathan Naylor e30eb3adaf Reduce the output buffer loading. 2020-05-08 17:18:26 +01:00
Jonathan Naylor 7c9385beab Merge pull request #252 from F4FXL/FM_Ext
Use pointer/shift/masking for sample unpacking
2020-05-08 16:53:32 +01:00
Geoffrey Merck 4c6601d778 Merge branch 'FM_Ext' of https://github.com/F4FXL/MMDVM into FM_Ext 2020-05-08 17:43:43 +02:00
Geoffrey Merck e3a951b33b Use pointer/masking/shifting for sample unpacking 2020-05-08 17:43:05 +02:00
Geoffrey Merck 97192602d8 Use pointer/masking/shifting for sample unpacking 2020-05-08 17:41:12 +02:00
Jonathan Naylor 604957b3e2 Merge pull request #251 from F4FXL/FM_Ext
Remove Union for sample packing
2020-05-08 16:30:06 +01:00
Geoffrey Merck bb731e7890 Init pointer with null 2020-05-08 17:15:23 +02:00
Geoffrey Merck c81d13395b Use correct types 2020-05-08 17:13:29 +02:00
Jonathan Naylor 9b0fed975c Buffer output after adding some initial silence. 2020-05-08 15:48:03 +01:00
Geoffrey Merck 18bc0a75b8 Merge branch 'FM_Ext' of https://github.com/F4FXL/MMDVM into FM_Ext 2020-05-08 16:45:22 +02:00
Geoffrey Merck f1a43ee520 Remove union, use pointer tricks instead 2020-05-08 16:44:53 +02:00
Geoffrey Merck b73bca237d Remove union, use pointer tricks instead 2020-05-08 15:06:08 +02:00
Jonathan Naylor e7ff0d1898 Use const uint8_t instead of non-const. 2020-05-08 13:29:50 +01:00
Jonathan Naylor 880df2536d Add audio packing code. 2020-05-08 12:30:15 +01:00
Jonathan Naylor 09b6929100 Merge pull request #250 from F4FXL/FM_Ext
Merge FM into FM_Ext
2020-05-08 11:04:14 +01:00
Geoffrey Merck 9afcf3acc9 Merge remote-tracking branch 'upstream/FM' into FM_Ext 2020-05-08 12:00:36 +02:00
Jonathan Naylor 5ca9313db8 Merge pull request #248 from F4FXL/FM
Make the FM chain RX Level independant
2020-05-08 09:18:58 +01:00
Geoffrey Merck feff1ee2c7 remove emphasis 2020-05-08 09:04:28 +02:00
Geoffrey Merck 77e0deee76 Make whole FM chain RX level independant 2020-05-08 09:01:00 +02:00
Jonathan Naylor d7cd7096d0 Add the external audio state machine and the beginnings of the audio
processing.
2020-05-07 22:39:17 +01:00
Jonathan Naylor 5d1b66dde3 Add the missing functions. 2020-05-07 22:07:58 +01:00
Jonathan Naylor 96364dc189 Add the external audio parameters. 2020-05-07 22:01:48 +01:00
Jonathan Naylor a816818e3f Beginnings of external audio for the FM controller. 2020-05-07 16:17:00 +01:00
Jonathan Naylor 61ae1fc83a Add transmit hangs to NXDN and P25. 2020-05-06 17:42:46 +01:00
Jonathan Naylor eb9c0dfd93 Allow for the inversion of COS levels. 2020-05-06 11:34:04 +01:00
Jonathan Naylor 79a09e61fa Add the dot to the FM keyer. 2020-05-05 21:02:56 +01:00
Jonathan Naylor 9978a75651 Merge branch 'master' into FM 2020-05-05 21:01:15 +01:00
Jonathan Naylor bd16d13531 Add the dot to the CW Id. 2020-05-05 21:00:36 +01:00
Jonathan Naylor f00d729264 Merge pull request #246 from F4FXL/bugfix/STM32F1_POG
Bug Fixes for the STM32F1_POG and derivatives
2020-05-05 10:17:03 +01:00
Geoffrey Merck a4ddc2a060 Merge remote-tracking branch 'upstream/FM' into bugfix/STM32F1_POG 2020-05-05 11:02:27 +02:00
Geoffrey Merck a938c8b708 Reduce buffer size 2020-05-05 10:48:44 +02:00
Jonathan Naylor aa7a484c7a Allow the start callsign to occur when the kerchunk timer has latched. 2020-05-04 22:18:51 +01:00
Jonathan Naylor 915be8c279 Calculate the AckMinTime accurately. 2020-05-04 22:06:57 +01:00
Geoffrey Merck 87feadd451 Better LED management 2020-05-04 19:12:45 +02:00
Geoffrey Merck 419ab89ee9 Merge branch 'bugfix/STM32F1_POG' of https://github.com/F4FXL/MMDVM into bugfix/STM32F1_POG 2020-05-04 16:44:25 +02:00
Geoffrey Merck fcdb582893 Change FM LED Pin 2020-05-04 16:43:08 +02:00
Geoffrey Merck 5e85565208 Fix compile isue 2020-05-04 15:26:17 +02:00
Geoffrey Merck 2d876b8d8e Fix Fancy LED effect accessing unused ports 2020-05-03 15:36:10 +02:00
Jonathan Naylor 4feca3c5b7 Clock the timers seperately. 2020-05-03 13:08:33 +01:00
Jonathan Naylor f8e119c26b Set the modem state in SET_CONFIG. 2020-05-02 17:37:47 +01:00
Jonathan Naylor edddbedd4b Fix compilation issues. 2020-05-02 15:46:36 +01:00
Jonathan Naylor baa4f7aa4c Last minute tidy-ups. 2020-05-02 14:47:43 +01:00
Jonathan Naylor de3c257f79 Bump the version date. 2020-05-01 18:47:15 +01:00
Jonathan Naylor b027e1d1bf Merge pull request #243 from F4FXL/FM
Fix CTCSS value is different when using RXLevel 50 to 99
2020-05-01 17:04:05 +01:00
Geoffrey Merck 0a5c496a3a Fix CTCSS value is different when using RXLevel 50 to 99 2020-05-01 17:56:45 +02:00
Jonathan Naylor 5b32fecc0a Remove the pre- and de-emphasis and the downsampler. 2020-04-30 11:39:04 +01:00
Jonathan Naylor 92a4db9886 Merge pull request #242 from g4klx/revert-241-FM
Revert "Change emphasis time constant to 750µS"
2020-04-30 11:23:42 +01:00
66 changed files with 3027 additions and 2844 deletions
+1 -1
View File
@@ -77,6 +77,7 @@ const struct {
{',', 0xEEAEE000U, 22U}, {',', 0xEEAEE000U, 22U},
{'-', 0xEAAE0000U, 18U}, {'-', 0xEAAE0000U, 18U},
{'=', 0xEAB80000U, 16U}, {'=', 0xEAB80000U, 16U},
{'.', 0xBAEB8000U, 20U},
{' ', 0x00000000U, 4U}, {' ', 0x00000000U, 4U},
{0U, 0x00000000U, 0U} {0U, 0x00000000U, 0U}
}; };
@@ -170,4 +171,3 @@ void CCWIdTX::reset()
m_poPtr = 0U; m_poPtr = 0U;
m_n = 0U; m_n = 0U;
} }
+12 -12
View File
@@ -38,13 +38,13 @@ const struct TONE_TABLE {
const uint8_t TONE_TABLE_DATA_LEN = 6U; const uint8_t TONE_TABLE_DATA_LEN = 6U;
CCalFM::CCalFM() : CCalFM::CCalFM() :
m_tone(NULL),
m_frequency(0), m_frequency(0),
m_length(0), m_length(0),
m_level(128*32), m_tone(NULL),
m_level(128 * 12),
m_transmit(false), m_transmit(false),
m_lastState(STATE_IDLE), m_audioSeq(0),
m_audioSeq(0) m_lastState(STATE_IDLE)
{ {
} }
@@ -52,29 +52,29 @@ void CCalFM::process()
{ {
const TONE_TABLE* entry = NULL; const TONE_TABLE* entry = NULL;
if (m_modemState!=m_lastState) if (m_modemState != m_lastState)
{ {
switch (m_modemState) { switch (m_modemState) {
case STATE_FMCAL10K: case STATE_FMCAL10K:
m_frequency=956U; m_frequency = 956U;
break; break;
case STATE_FMCAL12K: case STATE_FMCAL12K:
m_frequency=1039U; m_frequency = 1039U;
break; break;
case STATE_FMCAL15K: case STATE_FMCAL15K:
m_frequency=1247U; m_frequency = 1247U;
break; break;
case STATE_FMCAL20K: case STATE_FMCAL20K:
m_frequency=1633U; m_frequency = 1633U;
break; break;
case STATE_FMCAL25K: case STATE_FMCAL25K:
m_frequency=2079U; m_frequency = 2079U;
break; break;
case STATE_FMCAL30K: case STATE_FMCAL30K:
m_frequency=2495U; m_frequency = 2495U;
break; break;
default: default:
m_frequency=0; m_frequency = 0U;
break; break;
} }
+6 -1
View File
@@ -35,6 +35,11 @@
// For 19.2 MHz // For 19.2 MHz
// #define EXTERNAL_OSC 19200000 // #define EXTERNAL_OSC 19200000
// Use a higher baudrate for host communication. Required for FM network !
#define SERIAL_SPEED 115200 //suitable for most older boards (Arduino, Due STM32F1_POG etc). External FM will NOT work with this !
// #define SERIAL_SPEED 230400 // Only works on newer board M4, M7, Teensy. External FM might work with this
// #define SERIAL_SPEED 460800 // Only works on newer board M4, M7, Teensy. External FM should work with this
// Allow the use of the COS line to lockout the modem // Allow the use of the COS line to lockout the modem
// #define USE_COS_AS_LOCKOUT // #define USE_COS_AS_LOCKOUT
@@ -85,6 +90,6 @@
// #define USE_ALTERNATE_POCSAG_LEDS // #define USE_ALTERNATE_POCSAG_LEDS
// Use the D-Star and YSF LEDs for FM // Use the D-Star and YSF LEDs for FM
// #define USE_ALTERNATE_FM_LEDS #define USE_ALTERNATE_FM_LEDS
#endif #endif
+1 -1
View File
@@ -74,7 +74,7 @@ void CDMRDMOTX::process()
m_poLen = m_txDelay; m_poLen = m_txDelay;
} else { } else {
for (unsigned int i = 0U; i < DMR_FRAME_LENGTH_BYTES; i++) 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++) for (unsigned int i = 0U; i < 39U; i++)
m_poBuffer[i + DMR_FRAME_LENGTH_BYTES] = PR_FILL[i]; m_poBuffer[i + DMR_FRAME_LENGTH_BYTES] = PR_FILL[i];
+2 -2
View File
@@ -23,7 +23,7 @@
#include "Config.h" #include "Config.h"
#include "DMRDefines.h" #include "DMRDefines.h"
#include "SerialRB.h" #include "RingBuffer.h"
class CDMRDMOTX { class CDMRDMOTX {
public: public:
@@ -38,7 +38,7 @@ public:
uint8_t getSpace() const; uint8_t getSpace() const;
private: private:
CSerialRB m_fifo; CRingBuffer<uint8_t> m_fifo;
arm_fir_interpolate_instance_q15 m_modFilter; arm_fir_interpolate_instance_q15 m_modFilter;
q15_t m_modState[16U]; // blockSize + phaseLength - 1, 4 + 9 - 1 plus some spare q15_t m_modState[16U]; // blockSize + phaseLength - 1, 4 + 9 - 1 plus some spare
uint8_t m_poBuffer[1200U]; uint8_t m_poBuffer[1200U];
+1 -1
View File
@@ -293,7 +293,7 @@ void CDMRTX::createData(uint8_t slotIndex)
{ {
if (m_fifo[slotIndex].getData() >= DMR_FRAME_LENGTH_BYTES && m_frameCount >= STARTUP_COUNT && m_abortCount[slotIndex] >= ABORT_COUNT) { 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++) { 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; m_markBuffer[i] = MARK_NONE;
} }
} else { } else {
+2 -2
View File
@@ -23,7 +23,7 @@
#include "Config.h" #include "Config.h"
#include "DMRDefines.h" #include "DMRDefines.h"
#include "SerialRB.h" #include "RingBuffer.h"
enum DMRTXSTATE { enum DMRTXSTATE {
DMRTXSTATE_IDLE, DMRTXSTATE_IDLE,
@@ -59,7 +59,7 @@ public:
void setColorCode(uint8_t colorCode); void setColorCode(uint8_t colorCode);
private: private:
CSerialRB m_fifo[2U]; CRingBuffer<uint8_t> m_fifo[2U];
arm_fir_interpolate_instance_q15 m_modFilter; arm_fir_interpolate_instance_q15 m_modFilter;
q15_t m_modState[16U]; // blockSize + phaseLength - 1, 4 + 9 - 1 plus some spare q15_t m_modState[16U]; // blockSize + phaseLength - 1, 4 + 9 - 1 plus some spare
DMRTXSTATE m_state; DMRTXSTATE m_state;
+8 -5
View File
@@ -216,12 +216,13 @@ void CDStarTX::process()
for (uint16_t i = 0U; i < m_txDelay; i++) for (uint16_t i = 0U; i < m_txDelay; i++)
m_poBuffer[m_poLen++] = BIT_SYNC; m_poBuffer[m_poLen++] = BIT_SYNC;
} else { } else {
uint8_t dummy;
// Pop the type byte off // Pop the type byte off
m_buffer.get(); m_buffer.get(dummy);
uint8_t header[DSTAR_HEADER_LENGTH_BYTES]; uint8_t header[DSTAR_HEADER_LENGTH_BYTES];
for (uint8_t i = 0U; i < DSTAR_HEADER_LENGTH_BYTES; i++) 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]; uint8_t buffer[86U];
txHeader(header, buffer + 2U); txHeader(header, buffer + 2U);
@@ -239,17 +240,19 @@ void CDStarTX::process()
if (type == DSTAR_DATA && m_poLen == 0U) { if (type == DSTAR_DATA && m_poLen == 0U) {
// Pop the type byte off // 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++) 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; m_poPtr = 0U;
} }
if (type == DSTAR_EOT && m_poLen == 0U) { if (type == DSTAR_EOT && m_poLen == 0U) {
// Pop the type byte off // 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 j = 0U; j < 3U; j++) {
for (uint8_t i = 0U; i < DSTAR_EOT_LENGTH_BYTES; i++) for (uint8_t i = 0U; i < DSTAR_EOT_LENGTH_BYTES; i++)
+2 -2
View File
@@ -21,7 +21,7 @@
#include "Config.h" #include "Config.h"
#include "SerialRB.h" #include "RingBuffer.h"
class CDStarTX { class CDStarTX {
public: public:
@@ -38,7 +38,7 @@ public:
uint8_t getSpace() const; uint8_t getSpace() const;
private: private:
CSerialRB m_buffer; CRingBuffer<uint8_t> m_buffer;
arm_fir_interpolate_instance_q15 m_modFilter; arm_fir_interpolate_instance_q15 m_modFilter;
q15_t m_modState[20U]; // blockSize + phaseLength - 1, 8 + 9 - 1 plus some spare q15_t m_modState[20U]; // blockSize + phaseLength - 1, 8 + 9 - 1 plus some spare
uint8_t m_poBuffer[600U]; uint8_t m_poBuffer[600U];
+502 -126
View File
@@ -20,116 +20,208 @@
#include "Globals.h" #include "Globals.h"
#include "FM.h" #include "FM.h"
const uint16_t FM_TX_BLOCK_SIZE = 100U;
const uint16_t FM_SERIAL_BLOCK_SIZE = 84U;//this is the number of sample pairs to send over serial. One sample pair is 3bytes.
//three times this value shall never exceed 252
const uint16_t FM_SERIAL_BLOCK_SIZE_BYTES = FM_SERIAL_BLOCK_SIZE * 3U;
CFM::CFM() : CFM::CFM() :
m_callsign(), m_callsign(),
m_rfAck(), m_rfAck(),
m_extAck(),
m_ctcssRX(), m_ctcssRX(),
m_ctcssTX(), m_ctcssTX(),
m_timeoutTone(), m_timeoutTone(),
m_state(FS_LISTENING), m_state(FS_LISTENING),
m_callsignAtStart(false), m_callsignAtStart(false),
m_callsignAtEnd(false), m_callsignAtEnd(false),
m_callsignAtLatch(false),
m_callsignTimer(), m_callsignTimer(),
m_timeoutTimer(), m_timeoutTimer(),
m_holdoffTimer(), m_holdoffTimer(),
m_kerchunkTimer(), m_kerchunkTimer(),
m_kerchunkTX(true),
m_ackMinTimer(), m_ackMinTimer(),
m_ackDelayTimer(), m_ackDelayTimer(),
m_hangTimer(), m_hangTimer(),
m_statusTimer(),
m_filterStage1( 724, 1448, 724, 32768, -37895, 21352),//3rd order Cheby Filter 300 to 2700Hz, 0.2dB passband ripple, sampling rate 24kHz m_filterStage1( 724, 1448, 724, 32768, -37895, 21352),//3rd order Cheby Filter 300 to 2700Hz, 0.2dB passband ripple, sampling rate 24kHz
m_filterStage2(32768, 0,-32768, 32768, -50339, 19052), m_filterStage2(32768, 0,-32768, 32768, -50339, 19052),
m_filterStage3(32768, -65536, 32768, 32768, -64075, 31460), m_filterStage3(32768, -65536, 32768, 32768, -64075, 31460),
m_preemphasis(32768, 13967, 0, 32768, -18801, 0),//75µS 24kHz sampling rate
m_deemphasis (32768, -18801, 0, 32768, 13967, 0),//75µS 24kHz sampling rate
m_blanking(), m_blanking(),
m_useCOS(true), m_useCOS(true),
m_cosInvert(false),
m_rfAudioBoost(1U), m_rfAudioBoost(1U),
m_downsampler(1024)//Size might need adjustement m_extAudioBoost(1U),
m_downsampler(400U),// 100 ms of audio
m_extEnabled(false),
m_rxLevel(1),
m_inputRFRB(2401U), // 100ms of audio + 1 sample
m_outputRFRB(2400U), // 100ms of audio
m_inputExtRB()
{ {
m_statusTimer.setTimeout(1U, 0U);
insertDelay(100U);
} }
void CFM::samples(bool cos, q15_t* samples, uint8_t length) void CFM::samples(bool cos, q15_t* samples, uint8_t length)
{ {
if (!m_useCOS) if (m_useCOS) {
if (m_cosInvert)
cos = !cos;
} else {
cos = true; cos = true;
}
clock(length);
uint8_t i = 0U; uint8_t i = 0U;
for (; i < length; i++) { for (; i < length; i++) {
q15_t currentSample = samples[i];//save to a local variable to avoid indirection on every access // ARMv7-M has hardware integer division
q15_t currentRFSample = q15_t((q31_t(samples[i]) << 8) / m_rxLevel);
uint8_t ctcssState = m_ctcssRX.process(currentRFSample);
CTCSSState ctcssState = m_ctcssRX.process(currentSample); if (!m_useCOS) {
// Delay the audio by 100ms to better match the CTCSS detector output
m_inputRFRB.put(currentRFSample);
m_inputRFRB.get(currentRFSample);
}
if (CTCSS_NOT_READY(ctcssState) && m_modemState != STATE_FM) { q15_t currentExtSample;
//Not enough samples to determine if you have CTCSS, just carry on bool inputExt = m_inputExtRB.getSample(currentExtSample);//always consume the external input data so it does not overflow
inputExt = inputExt && m_extEnabled;
if (!inputExt && (CTCSS_NOT_READY(ctcssState)) && m_modemState != STATE_FM) {
//Not enough samples to determine if you have CTCSS, just carry on. But only if we haven't any external data in the queue
continue; continue;
} else if (CTCSS_READY(ctcssState) && m_modemState != STATE_FM) { } else if ((inputExt || CTCSS_READY(ctcssState)) && m_modemState != STATE_FM) {
//we had enough samples for CTCSS and we are in some other mode than FM //we had enough samples for CTCSS and we are in some other mode than FM
bool validCTCSS = CTCSS_VALID(ctcssState); bool validCTCSS = CTCSS_VALID(ctcssState);
stateMachine(validCTCSS && cos, i + 1U); stateMachine(validCTCSS && cos, inputExt);
if (m_modemState != STATE_FM) if (m_modemState != STATE_FM)
continue; continue;
} else if (CTCSS_READY(ctcssState) && m_modemState == STATE_FM) { } else if ((inputExt || CTCSS_NOT_READY(ctcssState)) && m_modemState == STATE_FM && i == length - 1) {
//We had enough samples for CTCSS and we are in FM mode, trigger the state machine
bool validCTCSS = CTCSS_VALID(ctcssState);
stateMachine(validCTCSS && cos, i + 1U);
if (m_modemState != STATE_FM)
break;
} else if (CTCSS_NOT_READY(ctcssState) && m_modemState == STATE_FM && i == length - 1) {
//Not enough samples for CTCSS but we already are in FM, trigger the state machine //Not enough samples for CTCSS but we already are in FM, trigger the state machine
//but do not trigger the state machine on every single sample, save CPU! //but do not trigger the state machine on every single sample, save CPU!
bool validCTCSS = CTCSS_VALID(ctcssState); bool validCTCSS = CTCSS_VALID(ctcssState);
stateMachine(validCTCSS && cos, i + 1U); stateMachine(validCTCSS && cos, inputExt);
} }
// Only let audio through when relaying audio q15_t currentSample = currentRFSample;
if (m_state == FS_RELAYING || m_state == FS_KERCHUNK) { q15_t currentBoost = m_rfAudioBoost;
currentSample = m_deemphasis.filter(currentSample); if (m_state == FS_RELAYING_EXT || m_state == FS_KERCHUNK_EXT) {
m_downsampler.addSample(currentSample); currentSample = currentExtSample;
currentBoost = m_extAudioBoost;
}
// Only let RF audio through when relaying RF audio
if (m_state == FS_RELAYING_RF || m_state == FS_KERCHUNK_RF || m_state == FS_RELAYING_EXT || m_state == FS_KERCHUNK_EXT) {
currentSample = m_blanking.process(currentSample); currentSample = m_blanking.process(currentSample);
currentSample *= m_rfAudioBoost; if (m_extEnabled && (m_state == FS_RELAYING_RF || m_state == FS_KERCHUNK_RF))
m_downsampler.addSample(currentSample);
currentSample *= currentBoost;
} else { } else {
currentSample = 0; currentSample = 0;
} }
if (!m_callsign.isRunning()) if (!m_callsign.isRunning() && !m_extAck.isRunning())
currentSample += m_rfAck.getHighAudio(); currentSample += m_rfAck.getHighAudio();
if (!m_rfAck.isRunning()) { if (!m_callsign.isRunning() && !m_rfAck.isRunning())
currentSample += m_extAck.getHighAudio();
if (!m_rfAck.isRunning() && !m_extAck.isRunning()) {
if (m_state == FS_LISTENING) if (m_state == FS_LISTENING)
currentSample += m_callsign.getHighAudio(); currentSample += m_callsign.getHighAudio();
else else
currentSample += m_callsign.getLowAudio(); currentSample += m_callsign.getLowAudio();
} }
if (!m_callsign.isRunning() && !m_rfAck.isRunning()) if (!m_callsign.isRunning() && !m_rfAck.isRunning() && !m_extAck.isRunning())
currentSample += m_timeoutTone.getAudio(); currentSample += m_timeoutTone.getAudio();
currentSample = m_filterStage3.filter(m_filterStage2.filter(m_filterStage1.filter(currentSample))); currentSample = m_filterStage3.filter(m_filterStage2.filter(m_filterStage1.filter(currentSample)));
currentSample = m_preemphasis.filter(currentSample);
currentSample += m_ctcssTX.getAudio(); currentSample += m_ctcssTX.getAudio();
samples[i] = currentSample; m_outputRFRB.put(currentSample);
} }
if (m_modemState == STATE_FM)
io.write(STATE_FM, samples, i);//only write the actual number of processed samples to IO
} }
void CFM::process() void CFM::process()
{ {
uint16_t space = io.getSpace();
uint16_t length = m_outputRFRB.getData();
if (space > 10U && length >= FM_TX_BLOCK_SIZE ) {
space -= 2U;
if (length > FM_TX_BLOCK_SIZE)
length = FM_TX_BLOCK_SIZE;
if (space > FM_TX_BLOCK_SIZE)
space = FM_TX_BLOCK_SIZE;
if (length > space)
length = space;
q15_t samples[FM_TX_BLOCK_SIZE];
for (uint16_t i = 0U; i < length; i++) {
q15_t sample = 0;
m_outputRFRB.get(sample);
samples[i] = sample;
}
io.write(STATE_FM, samples, length);
}
if (m_extEnabled) {
uint16_t length = m_downsampler.getData();
if (length >= FM_SERIAL_BLOCK_SIZE) {
if (length > FM_SERIAL_BLOCK_SIZE)
length = FM_SERIAL_BLOCK_SIZE;
TSamplePairPack serialSamples[FM_SERIAL_BLOCK_SIZE];
for (uint16_t j = 0U; j < length; j++)
m_downsampler.getPackedData(serialSamples[j]);
serial.writeFMData((uint8_t*)serialSamples, length * sizeof(TSamplePairPack));
}
}
} }
void CFM::reset() void CFM::reset()
{ {
m_state = FS_LISTENING;
m_callsignTimer.stop();
m_timeoutTimer.stop();
m_kerchunkTimer.stop();
m_ackMinTimer.stop();
m_ackDelayTimer.stop();
m_hangTimer.stop();
m_statusTimer.stop();
m_ctcssRX.reset(); m_ctcssRX.reset();
m_rfAck.stop();
m_extAck.stop();
m_callsign.stop();
m_timeoutTone.stop();
m_outputRFRB.reset();
m_inputExtRB.reset();
m_downsampler.reset();
} }
uint8_t CFM::setCallsign(const char* callsign, uint8_t speed, uint16_t frequency, uint8_t time, uint8_t holdoff, uint8_t highLevel, uint8_t lowLevel, bool callsignAtStart, bool callsignAtEnd) uint8_t CFM::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)
{ {
m_callsignAtStart = callsignAtStart; m_callsignAtStart = callsignAtStart;
m_callsignAtEnd = callsignAtEnd; m_callsignAtEnd = callsignAtEnd;
m_callsignAtLatch = callsignAtLatch;
uint16_t holdoffTime = holdoff * 60U; uint16_t holdoffTime = holdoff * 60U;
uint16_t callsignTime = time * 60U; uint16_t callsignTime = time * 60U;
@@ -146,31 +238,98 @@ uint8_t CFM::setCallsign(const char* callsign, uint8_t speed, uint16_t frequency
uint8_t CFM::setAck(const char* rfAck, uint8_t speed, uint16_t frequency, uint8_t minTime, uint16_t delay, uint8_t level) uint8_t CFM::setAck(const char* rfAck, uint8_t speed, uint16_t frequency, uint8_t minTime, uint16_t delay, uint8_t level)
{ {
m_ackDelayTimer.setTimeout(0U, delay); m_ackDelayTimer.setTimeout(0U, delay);
m_ackMinTimer.setTimeout(minTime, 0U);
if (minTime > 0U)
m_ackMinTimer.setTimeout(minTime, delay);
return m_rfAck.setParams(rfAck, speed, frequency, level, level); return m_rfAck.setParams(rfAck, speed, frequency, level, level);
} }
uint8_t CFM::setMisc(uint16_t timeout, uint8_t timeoutLevel, uint8_t ctcssFrequency, uint8_t ctcssThreshold, uint8_t ctcssLevel, uint8_t kerchunkTime, uint8_t hangTime, bool useCOS, uint8_t rfAudioBoost, uint8_t maxDev, uint8_t rxLevel) uint8_t CFM::setMisc(uint16_t timeout, uint8_t timeoutLevel, uint8_t ctcssFrequency, uint8_t ctcssHighThreshold, uint8_t ctcssLowThreshold, uint8_t ctcssLevel, uint8_t kerchunkTime, bool kerchunkTX, uint8_t hangTime, bool useCOS, bool cosInvert, uint8_t rfAudioBoost, uint8_t maxDev, uint8_t rxLevel)
{ {
m_useCOS = useCOS; m_useCOS = useCOS;
m_cosInvert = cosInvert;
m_rfAudioBoost = q15_t(rfAudioBoost); m_rfAudioBoost = q15_t(rfAudioBoost);
m_timeoutTimer.setTimeout(timeout, 0U); m_timeoutTimer.setTimeout(timeout, 0U);
m_kerchunkTimer.setTimeout(kerchunkTime, 0U); m_kerchunkTimer.setTimeout(kerchunkTime, 0U);
m_kerchunkTX = kerchunkTX;
m_hangTimer.setTimeout(hangTime, 0U); m_hangTimer.setTimeout(hangTime, 0U);
m_timeoutTone.setParams(timeoutLevel); m_timeoutTone.setParams(timeoutLevel);
m_blanking.setParams(maxDev, timeoutLevel); m_blanking.setParams(maxDev, timeoutLevel);
uint8_t ret = m_ctcssRX.setParams(ctcssFrequency, ctcssThreshold, rxLevel); m_rxLevel = rxLevel; //q15_t(255)/q15_t(rxLevel >> 1);
uint8_t ret = m_ctcssRX.setParams(ctcssFrequency, ctcssHighThreshold, ctcssLowThreshold);
if (ret != 0U) if (ret != 0U)
return ret; return ret;
return m_ctcssTX.setParams(ctcssFrequency, ctcssLevel); return m_ctcssTX.setParams(ctcssFrequency, ctcssLevel);
} }
void CFM::stateMachine(bool validSignal, uint8_t length) uint8_t CFM::setExt(const char* ack, uint8_t audioBoost, uint8_t speed, uint16_t frequency, uint8_t level)
{
m_extEnabled = true;
m_extAudioBoost = q15_t(audioBoost);
return m_extAck.setParams(ack, speed, frequency, level, level);
}
void CFM::stateMachine(bool validRFSignal, bool validExtSignal)
{
switch (m_state) {
case FS_LISTENING:
listeningState(validRFSignal, validExtSignal);
break;
case FS_KERCHUNK_RF:
kerchunkRFState(validRFSignal);
break;
case FS_RELAYING_RF:
relayingRFState(validRFSignal);
break;
case FS_RELAYING_WAIT_RF:
relayingRFWaitState(validRFSignal);
break;
case FS_TIMEOUT_RF:
timeoutRFState(validRFSignal);
break;
case FS_TIMEOUT_WAIT_RF:
timeoutRFWaitState(validRFSignal);
break;
case FS_KERCHUNK_EXT:
kerchunkExtState(validExtSignal);
break;
case FS_RELAYING_EXT:
relayingExtState(validExtSignal);
break;
case FS_RELAYING_WAIT_EXT:
relayingExtWaitState(validExtSignal);
break;
case FS_TIMEOUT_EXT:
timeoutExtState(validExtSignal);
break;
case FS_TIMEOUT_WAIT_EXT:
timeoutExtWaitState(validExtSignal);
break;
case FS_HANG:
hangState(validRFSignal, validExtSignal);
break;
default:
break;
}
if (m_state == FS_LISTENING && !m_rfAck.isWanted() && !m_extAck.isWanted() && !m_callsign.isWanted()) {
m_outputRFRB.reset();
m_downsampler.reset();
}
}
void CFM::clock(uint8_t length)
{ {
m_callsignTimer.clock(length); m_callsignTimer.clock(length);
m_timeoutTimer.clock(length); m_timeoutTimer.clock(length);
@@ -179,102 +338,135 @@ void CFM::stateMachine(bool validSignal, uint8_t length)
m_ackMinTimer.clock(length); m_ackMinTimer.clock(length);
m_ackDelayTimer.clock(length); m_ackDelayTimer.clock(length);
m_hangTimer.clock(length); m_hangTimer.clock(length);
m_statusTimer.clock(length);
switch (m_state) { if (m_statusTimer.isRunning() && m_statusTimer.hasExpired()) {
case FS_LISTENING: serial.writeFMStatus(m_state);
listeningState(validSignal); m_statusTimer.start();
break;
case FS_KERCHUNK:
kerchunkState(validSignal);
break;
case FS_RELAYING:
relayingState(validSignal);
break;
case FS_RELAYING_WAIT:
relayingWaitState(validSignal);
break;
case FS_TIMEOUT:
timeoutState(validSignal);
break;
case FS_TIMEOUT_WAIT:
timeoutWaitState(validSignal);
break;
case FS_HANG:
hangState(validSignal);
break;
default:
break;
}
if (m_state == FS_LISTENING && m_modemState == STATE_FM) {
if (!m_callsign.isRunning() && !m_rfAck.isRunning()) {
DEBUG1("Change to STATE_IDLE");
m_modemState = STATE_IDLE;
m_callsignTimer.stop();
m_timeoutTimer.stop();
m_kerchunkTimer.stop();
m_ackMinTimer.stop();
m_ackDelayTimer.stop();
m_hangTimer.stop();
}
} }
} }
void CFM::listeningState(bool validSignal) void CFM::listeningState(bool validRFSignal, bool validExtSignal)
{ {
if (validSignal) { if (validRFSignal) {
if (m_kerchunkTimer.getTimeout() > 0U) { if (m_kerchunkTimer.getTimeout() > 0U) {
DEBUG1("State to KERCHUNK"); DEBUG1("State to KERCHUNK_RF");
m_state = FS_KERCHUNK; m_state = FS_KERCHUNK_RF;
m_kerchunkTimer.start(); m_kerchunkTimer.start();
if (m_callsignAtStart && !m_callsignAtLatch)
sendCallsign();
} else { } else {
DEBUG1("State to RELAYING"); DEBUG1("State to RELAYING_RF");
m_state = FS_RELAYING; m_state = FS_RELAYING_RF;
if (m_callsignAtStart) if (m_callsignAtStart)
sendCallsign(); sendCallsign();
} }
beginRelaying(); if (m_state == FS_RELAYING_RF || (m_state == FS_KERCHUNK_RF && m_kerchunkTX)) {
insertSilence(50U);
m_callsignTimer.start(); beginRelaying();
DEBUG1("Change to STATE_FM"); m_callsignTimer.start();
m_modemState = STATE_FM;
io.setDecode(true);
io.setADCDetection(true);
m_statusTimer.start();
serial.writeFMStatus(m_state);
}
} else if (validExtSignal) {
if (m_kerchunkTimer.getTimeout() > 0U) {
DEBUG1("State to KERCHUNK_EXT");
m_state = FS_KERCHUNK_EXT;
m_kerchunkTimer.start();
if (m_callsignAtStart && !m_callsignAtLatch)
sendCallsign();
} else {
DEBUG1("State to RELAYING_EXT");
m_state = FS_RELAYING_EXT;
if (m_callsignAtStart)
sendCallsign();
}
if (m_state == FS_RELAYING_EXT || (m_state == FS_KERCHUNK_EXT && m_kerchunkTX)) {
insertSilence(50U);
beginRelaying();
m_callsignTimer.start();
m_statusTimer.start();
serial.writeFMStatus(m_state);
}
} }
} }
void CFM::kerchunkState(bool validSignal) void CFM::kerchunkRFState(bool validSignal)
{ {
if (validSignal) { if (validSignal) {
if (m_kerchunkTimer.hasExpired()) { if (m_kerchunkTimer.hasExpired()) {
DEBUG1("State to RELAYING"); DEBUG1("State to RELAYING_RF");
m_state = FS_RELAYING; m_state = FS_RELAYING_RF;
m_kerchunkTimer.stop(); m_kerchunkTimer.stop();
if (!m_kerchunkTX) {
insertSilence(50U);
beginRelaying();
m_callsignTimer.start();
io.setDecode(true);
io.setADCDetection(true);
m_statusTimer.start();
serial.writeFMStatus(m_state);
}
if (m_callsignAtStart && m_callsignAtLatch) {
sendCallsign();
m_callsignTimer.start();
}
} }
} else { } else {
io.setDecode(false);
io.setADCDetection(false);
DEBUG1("State to LISTENING"); DEBUG1("State to LISTENING");
m_state = FS_LISTENING; m_state = FS_LISTENING;
m_kerchunkTimer.stop(); m_kerchunkTimer.stop();
m_timeoutTimer.stop(); m_timeoutTimer.stop();
m_ackMinTimer.stop(); m_ackMinTimer.stop();
m_callsignTimer.stop(); m_callsignTimer.stop();
m_statusTimer.stop();
if (m_extEnabled)
serial.writeFMEOT();
} }
} }
void CFM::relayingState(bool validSignal) void CFM::relayingRFState(bool validSignal)
{ {
if (validSignal) { if (validSignal) {
if (m_timeoutTimer.isRunning() && m_timeoutTimer.hasExpired()) { if (m_timeoutTimer.isRunning() && m_timeoutTimer.hasExpired()) {
DEBUG1("State to TIMEOUT"); DEBUG1("State to TIMEOUT_RF");
m_state = FS_TIMEOUT; m_state = FS_TIMEOUT_RF;
m_ackMinTimer.stop(); m_ackMinTimer.stop();
m_timeoutTimer.stop(); m_timeoutTimer.stop();
m_timeoutTone.start(); m_timeoutTone.start();
if (m_extEnabled)
serial.writeFMEOT();
} }
} else { } else {
DEBUG1("State to RELAYING_WAIT"); io.setDecode(false);
m_state = FS_RELAYING_WAIT; io.setADCDetection(false);
DEBUG1("State to RELAYING_WAIT_RF");
m_state = FS_RELAYING_WAIT_RF;
m_ackDelayTimer.start(); m_ackDelayTimer.start();
if (m_extEnabled)
serial.writeFMEOT();
} }
if (m_callsignTimer.isRunning() && m_callsignTimer.hasExpired()) { if (m_callsignTimer.isRunning() && m_callsignTimer.hasExpired()) {
@@ -283,11 +475,14 @@ void CFM::relayingState(bool validSignal)
} }
} }
void CFM::relayingWaitState(bool validSignal) void CFM::relayingRFWaitState(bool validSignal)
{ {
if (validSignal) { if (validSignal) {
DEBUG1("State to RELAYING"); io.setDecode(true);
m_state = FS_RELAYING; io.setADCDetection(true);
DEBUG1("State to RELAYING_RF");
m_state = FS_RELAYING_RF;
m_ackDelayTimer.stop(); m_ackDelayTimer.stop();
} else { } else {
if (m_ackDelayTimer.isRunning() && m_ackDelayTimer.hasExpired()) { if (m_ackDelayTimer.isRunning() && m_ackDelayTimer.hasExpired()) {
@@ -296,12 +491,12 @@ void CFM::relayingWaitState(bool validSignal)
if (m_ackMinTimer.isRunning()) { if (m_ackMinTimer.isRunning()) {
if (m_ackMinTimer.hasExpired()) { if (m_ackMinTimer.hasExpired()) {
DEBUG1("Send ack"); DEBUG1("Send RF ack");
m_rfAck.start(); m_rfAck.start();
m_ackMinTimer.stop(); m_ackMinTimer.stop();
} }
} else { } else {
DEBUG1("Send ack"); DEBUG1("Send RF ack");
m_rfAck.start(); m_rfAck.start();
m_ackMinTimer.stop(); m_ackMinTimer.stop();
} }
@@ -318,38 +513,52 @@ void CFM::relayingWaitState(bool validSignal)
} }
} }
void CFM::hangState(bool validSignal) void CFM::kerchunkExtState(bool validSignal)
{ {
if (validSignal) { if (validSignal) {
DEBUG1("State to RELAYING"); if (m_kerchunkTimer.hasExpired()) {
m_state = FS_RELAYING; DEBUG1("State to RELAYING_EXT");
DEBUG1("Stop ack"); m_state = FS_RELAYING_EXT;
m_rfAck.stop(); m_kerchunkTimer.stop();
beginRelaying(); if (!m_kerchunkTX) {
} else { insertSilence(50U);
if (m_hangTimer.isRunning() && m_hangTimer.hasExpired()) {
DEBUG1("State to LISTENING");
m_state = FS_LISTENING;
m_hangTimer.stop();
if (m_callsignAtEnd) beginRelaying();
m_callsignTimer.start();
m_statusTimer.start();
serial.writeFMStatus(m_state);
}
if (m_callsignAtStart && m_callsignAtLatch) {
sendCallsign(); sendCallsign();
m_callsignTimer.start();
m_callsignTimer.stop(); }
} }
} } else {
DEBUG1("State to LISTENING");
if (m_callsignTimer.isRunning() && m_callsignTimer.hasExpired()) { m_state = FS_LISTENING;
sendCallsign(); m_kerchunkTimer.stop();
m_callsignTimer.start(); m_timeoutTimer.stop();
m_ackMinTimer.stop();
m_callsignTimer.stop();
m_statusTimer.stop();
} }
} }
void CFM::timeoutState(bool validSignal) void CFM::relayingExtState(bool validSignal)
{ {
if (!validSignal) { if (validSignal) {
DEBUG1("State to TIMEOUT_WAIT"); if (m_timeoutTimer.isRunning() && m_timeoutTimer.hasExpired()) {
m_state = FS_TIMEOUT_WAIT; DEBUG1("State to TIMEOUT_EXT");
m_state = FS_TIMEOUT_EXT;
m_ackMinTimer.stop();
m_timeoutTimer.stop();
m_timeoutTone.start();
}
} else {
DEBUG1("State to RELAYING_WAIT_EXT");
m_state = FS_RELAYING_WAIT_EXT;
m_ackDelayTimer.start(); m_ackDelayTimer.start();
} }
@@ -359,18 +568,117 @@ void CFM::timeoutState(bool validSignal)
} }
} }
void CFM::timeoutWaitState(bool validSignal) void CFM::relayingExtWaitState(bool validSignal)
{ {
if (validSignal) { if (validSignal) {
DEBUG1("State to TIMEOUT"); DEBUG1("State to RELAYING_EXT");
m_state = FS_TIMEOUT; m_state = FS_RELAYING_EXT;
m_ackDelayTimer.stop();
} else {
if (m_ackDelayTimer.isRunning() && m_ackDelayTimer.hasExpired()) {
DEBUG1("State to HANG");
m_state = FS_HANG;
if (m_ackMinTimer.isRunning()) {
if (m_ackMinTimer.hasExpired()) {
DEBUG1("Send Ext ack");
m_extAck.start();
m_ackMinTimer.stop();
}
} else {
DEBUG1("Send Ext ack");
m_extAck.start();
m_ackMinTimer.stop();
}
m_ackDelayTimer.stop();
m_timeoutTimer.stop();
m_hangTimer.start();
}
}
if (m_callsignTimer.isRunning() && m_callsignTimer.hasExpired()) {
sendCallsign();
m_callsignTimer.start();
}
}
void CFM::hangState(bool validRFSignal, bool validExtSignal)
{
if (validRFSignal) {
io.setDecode(true);
io.setADCDetection(true);
DEBUG1("State to RELAYING_RF");
m_state = FS_RELAYING_RF;
DEBUG1("Stop ack");
m_rfAck.stop();
m_extAck.stop();
beginRelaying();
} else if (validExtSignal) {
DEBUG1("State to RELAYING_EXT");
m_state = FS_RELAYING_EXT;
DEBUG1("Stop ack");
m_rfAck.stop();
m_extAck.stop();
beginRelaying();
} else {
if (m_hangTimer.isRunning() && m_hangTimer.hasExpired()) {
DEBUG1("State to LISTENING");
m_state = FS_LISTENING;
m_hangTimer.stop();
m_statusTimer.stop();
if (m_callsignAtEnd)
sendCallsign();
m_callsignTimer.stop();
}
}
if (m_callsignTimer.isRunning() && m_callsignTimer.hasExpired()) {
sendCallsign();
m_callsignTimer.start();
}
}
void CFM::timeoutRFState(bool validSignal)
{
if (!validSignal) {
io.setDecode(false);
io.setADCDetection(false);
DEBUG1("State to TIMEOUT_WAIT_RF");
m_state = FS_TIMEOUT_WAIT_RF;
if (m_callsignAtEnd)
sendCallsign();
m_ackDelayTimer.start();
}
if (m_callsignTimer.isRunning() && m_callsignTimer.hasExpired()) {
sendCallsign();
m_callsignTimer.start();
}
}
void CFM::timeoutRFWaitState(bool validSignal)
{
if (validSignal) {
io.setDecode(true);
io.setADCDetection(true);
DEBUG1("State to TIMEOUT_RF");
m_state = FS_TIMEOUT_RF;
m_ackDelayTimer.stop(); m_ackDelayTimer.stop();
} else { } else {
if (m_ackDelayTimer.isRunning() && m_ackDelayTimer.hasExpired()) { if (m_ackDelayTimer.isRunning() && m_ackDelayTimer.hasExpired()) {
DEBUG1("State to HANG"); DEBUG1("State to HANG");
m_state = FS_HANG; m_state = FS_HANG;
m_timeoutTone.stop(); m_timeoutTone.stop();
DEBUG1("Send ack"); DEBUG1("Send RF ack");
m_rfAck.start(); m_rfAck.start();
m_ackDelayTimer.stop(); m_ackDelayTimer.stop();
m_ackMinTimer.stop(); m_ackMinTimer.stop();
@@ -385,6 +693,45 @@ void CFM::timeoutWaitState(bool validSignal)
} }
} }
void CFM::timeoutExtState(bool validSignal)
{
if (!validSignal) {
DEBUG1("State to TIMEOUT_WAIT_EXT");
m_state = FS_TIMEOUT_WAIT_EXT;
m_ackDelayTimer.start();
}
if (m_callsignTimer.isRunning() && m_callsignTimer.hasExpired()) {
sendCallsign();
m_callsignTimer.start();
}
}
void CFM::timeoutExtWaitState(bool validSignal)
{
if (validSignal) {
DEBUG1("State to TIMEOUT_EXT");
m_state = FS_TIMEOUT_EXT;
m_ackDelayTimer.stop();
} else {
if (m_ackDelayTimer.isRunning() && m_ackDelayTimer.hasExpired()) {
DEBUG1("State to HANG");
m_state = FS_HANG;
m_timeoutTone.stop();
DEBUG1("Send Ext ack");
m_extAck.start();
m_ackDelayTimer.stop();
m_ackMinTimer.stop();
m_timeoutTimer.stop();
m_hangTimer.start();
}
}
if (m_callsignTimer.isRunning() && m_callsignTimer.hasExpired()) {
sendCallsign();
m_callsignTimer.start();
}
}
void CFM::sendCallsign() void CFM::sendCallsign()
{ {
if (m_holdoffTimer.isRunning()) { if (m_holdoffTimer.isRunning()) {
@@ -404,3 +751,32 @@ void CFM::beginRelaying()
m_timeoutTimer.start(); m_timeoutTimer.start();
m_ackMinTimer.start(); m_ackMinTimer.start();
} }
uint8_t CFM::getSpace() const
{
// The amount of free space for receiving external audio, in frames.
return m_inputExtRB.getSpace() / FM_SERIAL_BLOCK_SIZE_BYTES;
}
uint8_t CFM::writeData(const uint8_t* data, uint8_t length)
{
//todo check if length is a multiple of 3
m_inputExtRB.addData(data, length);
return 0U;
}
void CFM::insertDelay(uint16_t ms)
{
uint32_t nSamples = ms * 24U;
for (uint32_t i = 0U; i < nSamples; i++)
m_inputRFRB.put(0);
}
void CFM::insertSilence(uint16_t ms)
{
uint32_t nSamples = ms * 24U;
for (uint32_t i = 0U; i < nSamples; i++)
m_outputRFRB.put(0);
}
+48 -19
View File
@@ -27,22 +27,27 @@
#include "FMTimeout.h" #include "FMTimeout.h"
#include "FMKeyer.h" #include "FMKeyer.h"
#include "FMTimer.h" #include "FMTimer.h"
#include "RingBuffer.h"
#include "FMDirectForm1.h" #include "FMDirectForm1.h"
#include "FMDownsampler.h" #include "FMDownsampler.h"
#include "FMUpSampler.h"
enum FM_STATE { enum FM_STATE {
FS_LISTENING, FS_LISTENING,
FS_KERCHUNK, FS_KERCHUNK_RF,
FS_RELAYING, FS_RELAYING_RF,
FS_RELAYING_WAIT, FS_RELAYING_WAIT_RF,
FS_TIMEOUT, FS_TIMEOUT_RF,
FS_TIMEOUT_WAIT, FS_TIMEOUT_WAIT_RF,
FS_KERCHUNK_EXT,
FS_RELAYING_EXT,
FS_RELAYING_WAIT_EXT,
FS_TIMEOUT_EXT,
FS_TIMEOUT_WAIT_EXT,
FS_HANG FS_HANG
}; };
class CFM { class CFM {
public: public:
CFM(); CFM();
@@ -53,47 +58,71 @@ public:
void reset(); void reset();
uint8_t setCallsign(const char* callsign, uint8_t speed, uint16_t frequency, uint8_t time, uint8_t holdoff, uint8_t highLevel, uint8_t lowLevel, bool callsignAtStart, bool callsignAtEnd); uint8_t setCallsign(const char* callsign, uint8_t speed, uint16_t frequency, uint8_t time, uint8_t holdoff, uint8_t highLevel, uint8_t lowLevel, bool callsignAtStart, bool callsignAtEnd, bool callsignAtLatch);
uint8_t setAck(const char* rfAck, uint8_t speed, uint16_t frequency, uint8_t minTime, uint16_t delay, uint8_t level); uint8_t setAck(const char* rfAck, uint8_t speed, uint16_t frequency, uint8_t minTime, uint16_t delay, uint8_t level);
uint8_t setMisc(uint16_t timeout, uint8_t timeoutLevel, uint8_t ctcssFrequency, uint8_t ctcssThreshold, uint8_t ctcssLevel, uint8_t kerchunkTime, uint8_t hangTime, bool useCOS, uint8_t 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, bool kerchunkTX, uint8_t hangTime, bool useCOS, bool cosInvert, uint8_t rfAudioBoost, uint8_t maxDev, uint8_t rxLevel);
uint8_t setExt(const char* ack, uint8_t audioBoost, uint8_t speed, uint16_t frequency, uint8_t level);
uint8_t getSpace() const;
uint8_t writeData(const uint8_t* data, uint8_t length);
private: private:
CFMKeyer m_callsign; CFMKeyer m_callsign;
CFMKeyer m_rfAck; CFMKeyer m_rfAck;
CFMKeyer m_extAck;
CFMCTCSSRX m_ctcssRX; CFMCTCSSRX m_ctcssRX;
CFMCTCSSTX m_ctcssTX; CFMCTCSSTX m_ctcssTX;
CFMTimeout m_timeoutTone; CFMTimeout m_timeoutTone;
FM_STATE m_state; FM_STATE m_state;
bool m_callsignAtStart; bool m_callsignAtStart;
bool m_callsignAtEnd; bool m_callsignAtEnd;
bool m_callsignAtLatch;
CFMTimer m_callsignTimer; CFMTimer m_callsignTimer;
CFMTimer m_timeoutTimer; CFMTimer m_timeoutTimer;
CFMTimer m_holdoffTimer; CFMTimer m_holdoffTimer;
CFMTimer m_kerchunkTimer; CFMTimer m_kerchunkTimer;
bool m_kerchunkTX;
CFMTimer m_ackMinTimer; CFMTimer m_ackMinTimer;
CFMTimer m_ackDelayTimer; CFMTimer m_ackDelayTimer;
CFMTimer m_hangTimer; CFMTimer m_hangTimer;
CFMTimer m_statusTimer;
CFMDirectFormI m_filterStage1; CFMDirectFormI m_filterStage1;
CFMDirectFormI m_filterStage2; CFMDirectFormI m_filterStage2;
CFMDirectFormI m_filterStage3; CFMDirectFormI m_filterStage3;
CFMDirectFormI m_preemphasis;
CFMDirectFormI m_deemphasis;
CFMBlanking m_blanking; CFMBlanking m_blanking;
bool m_useCOS; bool m_useCOS;
bool m_cosInvert;
q15_t m_rfAudioBoost; q15_t m_rfAudioBoost;
q15_t m_extAudioBoost;
CFMDownsampler m_downsampler; CFMDownsampler m_downsampler;
bool m_extEnabled;
q15_t m_rxLevel;
CRingBuffer<q15_t> m_inputRFRB;
CRingBuffer<q15_t> m_outputRFRB;
CFMUpSampler m_inputExtRB;
void stateMachine(bool validSignal, uint8_t length); void stateMachine(bool validRFSignal, bool validExtSignal);
void listeningState(bool validSignal); void listeningState(bool validRFSignal, bool validExtSignal);
void kerchunkState(bool validSignal); void kerchunkRFState(bool validSignal);
void relayingState(bool validSignal); void relayingRFState(bool validSignal);
void relayingWaitState(bool validSignal); void relayingRFWaitState(bool validSignal);
void timeoutState(bool validSignal); void timeoutRFState(bool validSignal);
void timeoutWaitState(bool validSignal); void timeoutRFWaitState(bool validSignal);
void hangState(bool validSignal); void kerchunkExtState(bool validSignal);
void relayingExtState(bool validSignal);
void relayingExtWaitState(bool validSignal);
void timeoutExtState(bool validSignal);
void timeoutExtWaitState(bool validSignal);
void hangState(bool validRFSignal, bool validExtSignal);
void clock(uint8_t length);
void sendCallsign(); void sendCallsign();
void beginRelaying(); void beginRelaying();
void insertDelay(uint16_t ms);
void insertSilence(uint16_t ms);
}; };
#endif #endif
+22 -22
View File
@@ -82,19 +82,17 @@ const uint16_t N = 24000U / 4U;
CFMCTCSSRX::CFMCTCSSRX() : CFMCTCSSRX::CFMCTCSSRX() :
m_coeffDivTwo(0), m_coeffDivTwo(0),
m_threshold(0), m_highThreshold(0),
m_lowThreshold(0),
m_count(0U), m_count(0U),
m_q0(0), m_q0(0),
m_q1(0), m_q1(0),
m_result(CTS_NONE), m_result(CTS_NONE)
m_rxLevelInverse(1)
{ {
} }
uint8_t CFMCTCSSRX::setParams(uint8_t frequency, uint8_t threshold, uint8_t level) uint8_t CFMCTCSSRX::setParams(uint8_t frequency, uint8_t highThreshold, uint8_t lowThreshold)
{ {
m_rxLevelInverse = 511 / q15_t(level);
m_coeffDivTwo = 0; m_coeffDivTwo = 0;
for (uint8_t i = 0U; i < CTCSS_TABLE_DATA_LEN; i++) { for (uint8_t i = 0U; i < CTCSS_TABLE_DATA_LEN; i++) {
@@ -107,16 +105,18 @@ uint8_t CFMCTCSSRX::setParams(uint8_t frequency, uint8_t threshold, uint8_t leve
if (m_coeffDivTwo == 0) if (m_coeffDivTwo == 0)
return 4U; return 4U;
m_threshold = q31_t(threshold); m_highThreshold = q31_t(highThreshold);
m_lowThreshold = q31_t(lowThreshold);
return 0U; return 0U;
} }
CTCSSState CFMCTCSSRX::process(q15_t sample) uint8_t CFMCTCSSRX::process(q15_t sample)
{ {
q31_t sample31 = q31_t(sample) * m_rxLevelInverse; //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 = m_result & (~CTS_READY); m_result &= ~CTS_READY;
q31_t q2 = m_q1; q31_t q2 = m_q1;
m_q1 = m_q0; m_q1 = m_q0;
@@ -150,14 +150,19 @@ CTCSSState CFMCTCSSRX::process(q15_t sample)
q31_t value = t2 + t4 - t9; q31_t value = t2 + t4 - t9;
bool previousCTCSSValid = CTCSS_VALID(m_result); bool previousCTCSSValid = CTCSS_VALID(m_result);
m_result = m_result | CTS_READY;
if (value >= m_threshold)
m_result = m_result | CTS_VALID;
else
m_result = m_result & ~CTS_VALID;
if(previousCTCSSValid != CTCSS_VALID(m_result)) q31_t threshold = m_highThreshold;
DEBUG4("CTCSS Value / Threshold / Valid", value, m_threshold, CTCSS_VALID(m_result)); if (previousCTCSSValid)
threshold = m_lowThreshold;
m_result |= CTS_READY;
if (value >= threshold)
m_result |= CTS_VALID;
else
m_result &= ~CTS_VALID;
if (previousCTCSSValid != CTCSS_VALID(m_result))
DEBUG4("CTCSS Value / Threshold / Valid", value, threshold, CTCSS_VALID(m_result));
m_count = 0U; m_count = 0U;
m_q0 = 0; m_q0 = 0;
@@ -167,11 +172,6 @@ CTCSSState CFMCTCSSRX::process(q15_t sample)
return m_result; return m_result;
} }
CTCSSState CFMCTCSSRX::getState()
{
return m_result;
}
void CFMCTCSSRX::reset() void CFMCTCSSRX::reset()
{ {
m_q0 = 0; m_q0 = 0;
+12 -33
View File
@@ -21,28 +21,9 @@
#include "Config.h" #include "Config.h"
enum CTCSSState const uint8_t CTS_NONE = 0U;
{ const uint8_t CTS_READY = 1U;
CTS_NONE = 0, const uint8_t CTS_VALID = 2U;
CTS_READY = 1,
CTS_VALID = 2,
CTS_READY_VALID = CTS_READY | CTS_VALID
};
inline CTCSSState operator|(CTCSSState a, CTCSSState b)
{
return static_cast<CTCSSState>(static_cast<uint8_t>(a) | static_cast<uint8_t>(b));
}
inline CTCSSState operator&(CTCSSState a, CTCSSState b)
{
return static_cast<CTCSSState>(static_cast<uint8_t>(a) & static_cast<uint8_t>(b));
}
inline CTCSSState operator~(CTCSSState a)
{
return static_cast<CTCSSState>(~(static_cast<uint8_t>(a)));
}
#define CTCSS_READY(a) ((a & CTS_READY) != 0) #define CTCSS_READY(a) ((a & CTS_READY) != 0)
#define CTCSS_NOT_READY(a) ((a & CTS_READY) == 0) #define CTCSS_NOT_READY(a) ((a & CTS_READY) == 0)
@@ -53,22 +34,20 @@ class CFMCTCSSRX {
public: public:
CFMCTCSSRX(); CFMCTCSSRX();
uint8_t setParams(uint8_t frequency, uint8_t threshold, uint8_t level); uint8_t setParams(uint8_t frequency, uint8_t highThreshold, uint8_t lowThreshold);
CTCSSState process(q15_t sample); uint8_t process(q15_t sample);
CTCSSState getState();
void reset(); void reset();
private: private:
q63_t m_coeffDivTwo; q63_t m_coeffDivTwo;
q31_t m_threshold; q31_t m_highThreshold;
uint16_t m_count; q31_t m_lowThreshold;
q31_t m_q0; uint16_t m_count;
q31_t m_q1; q31_t m_q0;
CTCSSState m_result; q31_t m_q1;
q15_t m_rxLevelInverse; uint8_t m_result;
}; };
#endif #endif
+1 -1
View File
@@ -29,7 +29,7 @@ THE SOFTWARE.
// based on https://raw.githubusercontent.com/berndporr/iir_fixed_point/master/DirectFormI.h // based on https://raw.githubusercontent.com/berndporr/iir_fixed_point/master/DirectFormI.h
#include "Globals.h" #include <cstdint>
#ifndef DIRECTFORMI_H_ #ifndef DIRECTFORMI_H_
#define DIRECTFORMI_H_ #define DIRECTFORMI_H_
+42 -31
View File
@@ -20,44 +20,55 @@
#include "Config.h" #include "Config.h"
#include "FMDownsampler.h" #include "FMDownsampler.h"
CFMDownsampler::CFMDownsampler(uint16_t length) : CFMDownsampler::CFMDownsampler(uint16_t length) :
m_ringBuffer(length),//length might need tweaking m_ringBuffer(length),
m_packIndex(0), m_samplePack(0U),
m_downSampleIndex(0) m_samplePackPointer(NULL),
m_sampleIndex(0U)
{ {
m_samplePack = 0; m_samplePackPointer = (uint8_t*)&m_samplePack;
} }
void CFMDownsampler::addSample(q15_t sample) void CFMDownsampler::addSample(q15_t sample)
{ {
//only take one of three samples uint32_t usample = uint32_t(int32_t(sample) + 2048);
if(m_downSampleIndex == 0) { //only take one of three samples
switch(m_packIndex){ switch(m_sampleIndex){
case 0: case 0:
m_samplePack = int32_t(sample) << 12; m_samplePack = usample << 12;
break; break;
case 1:{ case 3:{
m_samplePack |= int32_t(sample); m_samplePack |= usample;
//we did not use MSB; skip it //we did not use MSB; skip it
m_ringBuffer.put(m_samplePackBytes[1]); TSamplePairPack pair{m_samplePackPointer[0U], m_samplePackPointer[1U], m_samplePackPointer[2U]};
m_ringBuffer.put(m_samplePackBytes[2]);
m_ringBuffer.put(m_samplePackBytes[3]);
m_samplePack = 0; m_ringBuffer.put(pair);
}
break; m_samplePack = 0U;//reset the sample pack
default:
//should never happen
break;
}
m_packIndex++;
if(m_packIndex >= 2)
m_packIndex = 0;
} }
break;
default:
//Just skip this sample
break;
}
m_downSampleIndex++; m_sampleIndex++;
if(m_downSampleIndex >= 3) if(m_sampleIndex >= 6U)//did we pack two samples ?
m_downSampleIndex = 0; 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;
} }
+10 -11
View File
@@ -21,23 +21,22 @@
#define FMDOWNSAMPLER_H #define FMDOWNSAMPLER_H
#include "Config.h" #include "Config.h"
#include "FMDownsampleRB.h" #include "RingBuffer.h"
#include "FMSamplePairPack.h"
class CFMDownsampler { class CFMDownsampler {
public: public:
CFMDownsampler(uint16_t length); CFMDownsampler(uint16_t length);
void addSample(q15_t sample); void addSample(q15_t sample);
inline bool getPackedData(uint8_t& data){ return m_ringBuffer.get(data); }; bool getPackedData(TSamplePairPack& data);
inline bool hasOverflowed() { return m_ringBuffer.hasOverflowed(); }; uint16_t getData();
void reset();
private: private:
CFMDownsampleRB m_ringBuffer; CRingBuffer<TSamplePairPack> m_ringBuffer;
union { uint32_t m_samplePack;
int32_t m_samplePack; uint8_t* m_samplePackPointer;
int8_t m_samplePackBytes[4]; uint8_t m_sampleIndex;
};
uint8_t m_packIndex;
uint8_t m_downSampleIndex;
}; };
#endif #endif
+6
View File
@@ -66,6 +66,7 @@ const struct {
{',', 0xEEAEE000U, 22U}, {',', 0xEEAEE000U, 22U},
{'-', 0xEAAE0000U, 18U}, {'-', 0xEAAE0000U, 18U},
{'=', 0xEAB80000U, 16U}, {'=', 0xEAB80000U, 16U},
{'.', 0xBAEB8000U, 20U},
{' ', 0x00000000U, 4U}, {' ', 0x00000000U, 4U},
{0U, 0x00000000U, 0U} {0U, 0x00000000U, 0U}
}; };
@@ -204,6 +205,11 @@ void CFMKeyer::stop()
m_audioPos = 0U; m_audioPos = 0U;
} }
bool CFMKeyer::isWanted() const
{
return m_wanted;
}
bool CFMKeyer::isRunning() const bool CFMKeyer::isRunning() const
{ {
return m_poPos > 0U || m_dotPos > 0U || m_audioPos > 0U; return m_poPos > 0U || m_dotPos > 0U || m_audioPos > 0U;
+2
View File
@@ -35,6 +35,8 @@ public:
bool isRunning() const; bool isRunning() const;
bool isWanted() const;
private: private:
bool m_wanted; bool m_wanted;
uint8_t m_poBuffer[1000U]; uint8_t m_poBuffer[1000U];
+29
View File
@@ -0,0 +1,29 @@
/*
* 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(TSAMPLEPACK_H)
#define TSAMPLEPACK_H
struct TSamplePairPack {
uint8_t byte0;
uint8_t byte1;
uint8_t byte2;
};
#endif
+97
View File
@@ -0,0 +1,97 @@
/*
* 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 "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);
}
+48
View File
@@ -0,0 +1,48 @@
/*
* 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(FMUPSAMPLER_H)
#define FMUPSAMPLER_H
#include "Config.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
+1
View File
@@ -28,6 +28,7 @@
#include "STM32Utils.h" #include "STM32Utils.h"
#else #else
#include <Arduino.h> #include <Arduino.h>
#undef PI //Undefine PI to get rid of annoying warning as it is also defined in arm_math.h.
#endif #endif
#if defined(__SAM3X8E__) || defined(STM32F105xC) #if defined(__SAM3X8E__) || defined(STM32F105xC)
+9 -6
View File
@@ -264,6 +264,7 @@ void CIO::process()
if (m_txBuffer.getData() == 0U && m_tx) { if (m_txBuffer.getData() == 0U && m_tx) {
m_tx = false; m_tx = false;
setPTTInt(m_pttInvert ? true : false); setPTTInt(m_pttInvert ? true : false);
DEBUG1("TX OFF");
} }
if (m_rxBuffer.getData() >= RX_BLOCK_SIZE) { if (m_rxBuffer.getData() >= RX_BLOCK_SIZE) {
@@ -272,15 +273,16 @@ void CIO::process()
uint16_t rssi[RX_BLOCK_SIZE]; uint16_t rssi[RX_BLOCK_SIZE];
for (uint16_t i = 0U; i < RX_BLOCK_SIZE; i++) { for (uint16_t i = 0U; i < RX_BLOCK_SIZE; i++) {
uint16_t sample; TSample sample;
m_rxBuffer.get(sample, control[i]); m_rxBuffer.get(sample);
control[i] = sample.control;
m_rssiBuffer.get(rssi[i]); m_rssiBuffer.get(rssi[i]);
// Detect ADC overflow // Detect ADC overflow
if (m_detect && (sample == 0U || sample == 4095U)) if (m_detect && (sample.sample == 0U || sample.sample == 4095U))
m_adcOverflow++; 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; q31_t res2 = res1 * m_rxLevel;
samples[i] = q15_t(__SSAT((res2 >> 15), 16)); samples[i] = q15_t(__SSAT((res2 >> 15), 16));
} }
@@ -452,6 +454,7 @@ void CIO::write(MMDVM_STATE mode, q15_t* samples, uint16_t length, const uint8_t
if (!m_tx) { if (!m_tx) {
m_tx = true; m_tx = true;
setPTTInt(m_pttInvert ? false : true); setPTTInt(m_pttInvert ? false : true);
DEBUG1("TX ON");
} }
q15_t txLevel = 0; q15_t txLevel = 0;
@@ -492,9 +495,9 @@ void CIO::write(MMDVM_STATE mode, q15_t* samples, uint16_t length, const uint8_t
m_dacOverflow++; m_dacOverflow++;
if (control == NULL) if (control == NULL)
m_txBuffer.put(res3, MARK_NONE); m_txBuffer.put({res3, MARK_NONE});
else else
m_txBuffer.put(res3, control[i]); m_txBuffer.put({res3, control[i]});
} }
} }
+10 -6
View File
@@ -21,8 +21,12 @@
#include "Globals.h" #include "Globals.h"
#include "SampleRB.h" #include "RingBuffer.h"
#include "RSSIRB.h"
struct TSample {
volatile uint16_t sample;
volatile uint8_t control;
};
class CIO { class CIO {
public: public:
@@ -57,11 +61,11 @@ public:
void selfTest(); void selfTest();
private: private:
bool m_started; bool m_started;
CSampleRB m_rxBuffer; CRingBuffer<TSample> m_rxBuffer;
CSampleRB m_txBuffer; CRingBuffer<TSample> m_txBuffer;
CRSSIRB m_rssiBuffer; CRingBuffer<uint16_t> m_rssiBuffer;
arm_biquad_casd_df1_inst_q31 m_dcFilter; arm_biquad_casd_df1_inst_q31 m_dcFilter;
q31_t m_dcState[4]; q31_t m_dcState[4];
+5 -6
View File
@@ -185,14 +185,13 @@ void CIO::startInt()
void CIO::interrupt() 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 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; TSample sample = {DC_OFFSET, MARK_NONE};
uint16_t sample = DC_OFFSET;
m_txBuffer.get(sample, control); m_txBuffer.get(sample);
DACC->DACC_CDR = sample; DACC->DACC_CDR = sample.sample;
sample = ADC->ADC_CDR[ADC_CDR_Chan]; sample.sample = ADC->ADC_CDR[ADC_CDR_Chan];
m_rxBuffer.put(sample, control); m_rxBuffer.put(sample);
#if defined(SEND_RSSI_DATA) #if defined(SEND_RSSI_DATA)
m_rssiBuffer.put(ADC->ADC_CDR[RSSI_CDR_Chan]); m_rssiBuffer.put(ADC->ADC_CDR[RSSI_CDR_Chan]);
+70
View File
@@ -0,0 +1,70 @@
/*
* Copyright (C) 2019,2020 by BG5HHP
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifndef _IO_PINS_H
#define _IO_PINS_H
#if !defined(CONFIG_H)
#error "Requires Config.h to be included first!"
#endif
#if defined(STM32F4_RPT_HAT_TGO)
#include "pins/pins_f4_rpt_tgo.h"
#elif defined(STM32F4_DISCOVERY)
#include "pins/pins_f4_discovery.h"
#elif defined(STM32F4_PI)
#include "pins/pins_f4_pi.h"
#elif defined(STM32F722_PI)
#include "pins/pins_f7_pi.h"
#elif defined(STM32F4_F4M)
#include "pins/pins_f4_f4m.h"
#elif defined(STM32F722_F7M)
#include "pins/pins_f7_f7m.h"
#elif defined(STM32F722_RPT_HAT)
#include "pins/pins_f7_rpt_hat.h"
#elif defined(STM32F4_NUCLEO)
#if defined(STM32F4_NUCLEO_MORPHO_HEADER)
#include "pins/pins_f4_nucleo_morpho.h"
#elif defined(STM32F4_NUCLEO_ARDUINO_HEADER)
#include "pins/pins_f4_nucleo_arduino.h"
#else
#error "Either STM32F4_NUCLEO_MORPHO_HEADER or STM32F4_NUCLEO_ARDUINO_HEADER need to be defined"
#endif
#elif defined(STM32F7_NUCLEO)
#include "pins/pins_f7_nucleo.h"
#elif defined(STM32F4_DVM)
#include "pins/pins_f4_stm32dvm_v3.h"
#elif defined(DRCC_DVM_NQF)
#include "pins/pins_f4_drcc_nqf.h"
#else
#error "A valid board type macro need to be defined."
#endif
#endif //#ifndef _IO_PINS_H
+59 -1032
View File
File diff suppressed because it is too large Load Diff
+42 -20
View File
@@ -85,7 +85,7 @@ USART1_RXD PA10 input (AF)
#define PIN_POCSAG 11 #define PIN_POCSAG 11
#define PORT_POCSAG GPIOB #define PORT_POCSAG GPIOB
#define BB_POCSAG *((bitband_t)BITBAND_PERIPH(&PORT_POCSAG->ODR, PIN_POCSAG)) #define BB_POCSAG *((bitband_t)BITBAND_PERIPH(&PORT_POCSAG->ODR, PIN_POCSAG))
#define PIN_FM 12 #define PIN_FM 14
#define PORT_FM GPIOB #define PORT_FM GPIOB
#define BB_FM *((bitband_t)BITBAND_PERIPH(&PORT_FM->ODR, PIN_FM)) #define BB_FM *((bitband_t)BITBAND_PERIPH(&PORT_FM->ODR, PIN_FM))
@@ -158,16 +158,35 @@ void GPIOConfigPin(GPIO_TypeDef *port_ptr, uint32_t pin, uint32_t mode_cnf_value
#if defined(STM32F1_POG) #if defined(STM32F1_POG)
void FancyLEDEffect() void FancyLEDEffect()
{ {
bitband_t foo[] = {&BB_LED, &BB_COSLED, &BB_PTT, &BB_DMR, &BB_DSTAR, &BB_YSF, &BB_P25, &BB_NXDN, &BB_POCSAG, &BB_FM}; int ledCount = 10;
for(int i=0; i<10; i++){ bitband_t foo[] = {&BB_LED, &BB_COSLED, &BB_PTT, &BB_DMR, &BB_DSTAR, &BB_YSF, &BB_P25,
*foo[i] = 0x01; #if defined(USE_ALTERNATE_NXDN_LEDS)
NULL,
#else
&BB_NXDN,
#endif
#if defined(USE_ALTERNATE_POCSAG_LEDS)
NULL,
#else
&BB_POCSAG,
#endif
#if defined(USE_ALTERNATE_FM_LEDS)
NULL};
#else
&BB_FM};
#endif
for(int i=0; i<ledCount; i++){
if(foo[i] != NULL)
*foo[i] = 0x01;
} }
GPIOConfigPin(PORT_USART1_TXD, PIN_USART1_TXD, GPIO_CRL_MODE0_1); GPIOConfigPin(PORT_USART1_TXD, PIN_USART1_TXD, GPIO_CRL_MODE0_1);
*((bitband_t)BITBAND_PERIPH(&PORT_USART1_TXD->ODR, PIN_USART1_TXD)) = 0x00; *((bitband_t)BITBAND_PERIPH(&PORT_USART1_TXD->ODR, PIN_USART1_TXD)) = 0x00;
delay(SystemCoreClock/1000*100); delay(SystemCoreClock/1000*100);
for(int i=0; i<7; i++){ for(int i=0; i<ledCount; i++){
*foo[i] = 0x00; if(foo[i] != NULL)
*foo[i] = 0x00;
} }
*((bitband_t)BITBAND_PERIPH(&PORT_USART1_TXD->ODR, PIN_USART1_TXD)) = 0x01; *((bitband_t)BITBAND_PERIPH(&PORT_USART1_TXD->ODR, PIN_USART1_TXD)) = 0x01;
delay(SystemCoreClock/1000*20); delay(SystemCoreClock/1000*20);
@@ -176,18 +195,22 @@ void FancyLEDEffect()
*((bitband_t)BITBAND_PERIPH(&PORT_USART1_TXD->ODR, PIN_USART1_TXD)) = 0x01; *((bitband_t)BITBAND_PERIPH(&PORT_USART1_TXD->ODR, PIN_USART1_TXD)) = 0x01;
*foo[0] = 0x01; *foo[0] = 0x01;
for(int i=1; i<10; i++){ for(int i=1; i<ledCount; i++){
delay(SystemCoreClock/1000*10); delay(SystemCoreClock/1000*10);
*foo[i-1] = 0x00; if (foo[i-1] != NULL)
*foo[i] = 0x01; *foo[i-1] = 0x00;
if (foo[i] != NULL)
*foo[i] = 0x01;
} }
for(int i=10; i>=0; i--){ for(int i=ledCount - 2; i>=0; i--) {
delay(SystemCoreClock/1000*10); delay(SystemCoreClock/1000*10);
*foo[i+1] = 0x00; if (foo[i+1] != NULL)
*foo[i] = 0x01; *foo[i+1] = 0x00;
if (foo[i] != NULL)
*foo[i] = 0x01;
} }
delay(SystemCoreClock/1000*10); delay(SystemCoreClock/1000*10);
*foo[5+1-6] = 0x00; *foo[0] = 0x00;
*((bitband_t)BITBAND_PERIPH(&PORT_USART1_TXD->ODR, PIN_USART1_TXD)) = 0x00; *((bitband_t)BITBAND_PERIPH(&PORT_USART1_TXD->ODR, PIN_USART1_TXD)) = 0x00;
delay(SystemCoreClock/1000*10); delay(SystemCoreClock/1000*10);
*((bitband_t)BITBAND_PERIPH(&PORT_USART1_TXD->ODR, PIN_USART1_TXD)) = 0x01; *((bitband_t)BITBAND_PERIPH(&PORT_USART1_TXD->ODR, PIN_USART1_TXD)) = 0x01;
@@ -374,8 +397,7 @@ void CIO::startInt()
void CIO::interrupt() void CIO::interrupt()
{ {
uint8_t control = MARK_NONE; TSample sample = {DC_OFFSET, MARK_NONE};
uint16_t sample = DC_OFFSET;
#if defined(SEND_RSSI_DATA) #if defined(SEND_RSSI_DATA)
uint16_t rawRSSI = 0U; uint16_t rawRSSI = 0U;
#endif #endif
@@ -392,12 +414,12 @@ void CIO::interrupt()
*rssi_adon = 1; *rssi_adon = 1;
#endif #endif
m_txBuffer.get(sample, control); m_txBuffer.get(sample);
DAC->DHR12R1 = sample; // Send the value to the DAC DAC->DHR12R1 = sample.sample; // Send the value to the DAC
// Read value from ADC1 and ADC2 // Read value from ADC1 and ADC2
sample = ADC1->DR; // read conversion result; EOC is cleared by this read sample.sample = ADC1->DR; // read conversion result; EOC is cleared by this read
m_rxBuffer.put(sample, control); m_rxBuffer.put(sample);
#if defined(SEND_RSSI_DATA) #if defined(SEND_RSSI_DATA)
rawRSSI = ADC2->DR; rawRSSI = ADC2->DR;
m_rssiBuffer.put(rawRSSI); m_rssiBuffer.put(rawRSSI);
+5 -6
View File
@@ -161,15 +161,14 @@ void CIO::startInt()
void CIO::interrupt() void CIO::interrupt()
{ {
uint8_t control = MARK_NONE; TSample sample = {DC_OFFSET, MARK_NONE};
uint16_t sample = DC_OFFSET;
m_txBuffer.get(sample, control); m_txBuffer.get(sample);
*(int16_t *)&(DAC0_DAT0L) = sample; *(int16_t *)&(DAC0_DAT0L) = sample.sample;
if ((ADC0_SC1A & ADC_SC1_COCO) == ADC_SC1_COCO) { if ((ADC0_SC1A & ADC_SC1_COCO) == ADC_SC1_COCO) {
sample = ADC0_RA; sample.sample = ADC0_RA;
m_rxBuffer.put(sample, control); m_rxBuffer.put(sample);
} }
#if defined(SEND_RSSI_DATA) #if defined(SEND_RSSI_DATA)
-340
View File
@@ -1,340 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<Project version="2G - 1.7.8" name="MMDVM_STM32F4xx">
<Target name="MMDVM_Discovery_407" isCurrent="1">
<Device manufacturerId="9" manufacturerName="ST" chipId="344" chipName="STM32F407VG" boardId="" boardName=""/>
<BuildOption>
<Compile>
<Option name="OptimizationLevel" value="4"/>
<Option name="UseFPU" value="0"/>
<Option name="UserEditCompiler" value=""/>
<Option name="SupportCPlusplus" value="1"/>
<Option name="FPU" value="2"/>
<Includepaths>
<Includepath path="."/>
</Includepaths>
<DefinedSymbols>
<Define name="STM32F4XX"/>
<Define name="USE_STDPERIPH_DRIVER"/>
<Define name="__ASSEMBLY__"/>
<Define name="SUPPORT_CPLUSPLUS"/>
<Define name="STM32F40_41xxx"/>
<Define name="HSE_VALUE=8000000"/>
<Define name="STM32F4_DISCOVERY"/>
<Define name="__FPU_USED"/>
</DefinedSymbols>
</Compile>
<Link useDefault="0">
<Option name="DiscardUnusedSection" value="0"/>
<Option name="UserEditLinkder" value=""/>
<Option name="UseMemoryLayout" value="0"/>
<Option name="nostartfiles" value="1"/>
<Option name="LTO" value="0"/>
<Option name="IsNewStartupCode" value="1"/>
<Option name="Library" value="Semihosting"/>
<Option name="UserEditLinker" value="-lstdc++; --specs=nano.specs;"/>
<LinkedLibraries>
<Libset dir="stm32f4xx_lib\cmsis\lib\gcc\" libs="arm_cortexm4lf_math"/>
</LinkedLibraries>
<MemoryAreas debugInFlashNotRAM="1">
<Memory name="IROM1" type="ReadOnly" size="0x00100000" startValue="0x08000000"/>
<Memory name="IRAM1" type="ReadWrite" size="0x00020000" startValue="0x20000000"/>
<Memory name="IROM2" type="ReadOnly" size="" startValue=""/>
<Memory name="IRAM2" type="ReadWrite" size="0x00010000" startValue="0x10000000"/>
</MemoryAreas>
<LocateLinkFile path="./stm32f4xx_link.ld" type="0"/>
</Link>
<Output>
<Option name="OutputFileType" value="0"/>
<Option name="Path" value="./"/>
<Option name="Name" value="MMDVM_DIS"/>
<Option name="HEX" value="1"/>
<Option name="BIN" value="1"/>
</Output>
<User>
<UserRun name="Run#1" type="Before" checked="0" value=""/>
<UserRun name="Run#1" type="After" checked="0" value=""/>
</User>
</BuildOption>
<DebugOption>
<Option name="org.coocox.codebugger.gdbjtag.core.adapter" value="ST-Link"/>
<Option name="org.coocox.codebugger.gdbjtag.core.debugMode" value="SWD"/>
<Option name="org.coocox.codebugger.gdbjtag.core.clockDiv" value="1M"/>
<Option name="org.coocox.codebugger.gdbjtag.corerunToMain" value="1"/>
<Option name="org.coocox.codebugger.gdbjtag.core.jlinkgdbserver" value=""/>
<Option name="org.coocox.codebugger.gdbjtag.core.userDefineGDBScript" value=""/>
<Option name="org.coocox.codebugger.gdbjtag.core.targetEndianess" value="0"/>
<Option name="org.coocox.codebugger.gdbjtag.core.jlinkResetMode" value="Type 0: Normal"/>
<Option name="org.coocox.codebugger.gdbjtag.core.resetMode" value="SYSRESETREQ"/>
<Option name="org.coocox.codebugger.gdbjtag.core.ifSemihost" value="0"/>
<Option name="org.coocox.codebugger.gdbjtag.core.ifCacheRom" value="1"/>
<Option name="org.coocox.codebugger.gdbjtag.core.ipAddress" value="127.0.0.1"/>
<Option name="org.coocox.codebugger.gdbjtag.core.portNumber" value="2009"/>
<Option name="org.coocox.codebugger.gdbjtag.core.autoDownload" value="1"/>
<Option name="org.coocox.codebugger.gdbjtag.core.verify" value="1"/>
<Option name="org.coocox.codebugger.gdbjtag.core.downloadFuction" value="Erase Effected"/>
<Option name="org.coocox.codebugger.gdbjtag.core.defaultAlgorithm" value="STM32F4xx_1024.elf"/>
</DebugOption>
<ExcludeFile/>
</Target>
<Target name="MMDVM_Pi_446" isCurrent="0">
<Device manufacturerId="9" manufacturerName="ST" chipId="344" chipName="STM32F407VG" boardId="" boardName=""/>
<BuildOption>
<Compile>
<Option name="OptimizationLevel" value="4"/>
<Option name="UseFPU" value="0"/>
<Option name="UserEditCompiler" value=""/>
<Option name="SupportCPlusplus" value="1"/>
<Option name="FPU" value="2"/>
<Includepaths>
<Includepath path="."/>
</Includepaths>
<DefinedSymbols>
<Define name="STM32F4XX"/>
<Define name="USE_STDPERIPH_DRIVER"/>
<Define name="__ASSEMBLY__"/>
<Define name="SUPPORT_CPLUSPLUS"/>
<Define name="__FPU_USED"/>
<Define name="STM32F446xx"/>
<Define name="HSE_VALUE=12000000"/>
<Define name="STM32F4_PI"/>
<Define name="MODE_LEDS"/>
</DefinedSymbols>
</Compile>
<Link useDefault="0">
<Option name="DiscardUnusedSection" value="0"/>
<Option name="UserEditLinkder" value=""/>
<Option name="UseMemoryLayout" value="0"/>
<Option name="nostartfiles" value="1"/>
<Option name="LTO" value="0"/>
<Option name="IsNewStartupCode" value="1"/>
<Option name="Library" value="Semihosting"/>
<Option name="UserEditLinker" value="-lstdc++; --specs=nano.specs;"/>
<LinkedLibraries>
<Libset dir="stm32f4xx_lib\cmsis\lib\gcc\" libs="arm_cortexm4lf_math"/>
</LinkedLibraries>
<MemoryAreas debugInFlashNotRAM="1">
<Memory name="IROM1" type="ReadOnly" size="0x00100000" startValue="0x08000000"/>
<Memory name="IRAM1" type="ReadWrite" size="0x00020000" startValue="0x20000000"/>
<Memory name="IROM2" type="ReadOnly" size="" startValue=""/>
<Memory name="IRAM2" type="ReadWrite" size="0x00010000" startValue="0x10000000"/>
</MemoryAreas>
<LocateLinkFile path="./stm32f4xx_link.ld" type="0"/>
</Link>
<Output>
<Option name="OutputFileType" value="0"/>
<Option name="Path" value="./"/>
<Option name="Name" value="MMDVM_PI"/>
<Option name="HEX" value="1"/>
<Option name="BIN" value="1"/>
</Output>
<User>
<UserRun name="Run#1" type="Before" checked="0" value=""/>
<UserRun name="Run#1" type="After" checked="0" value=""/>
</User>
</BuildOption>
<DebugOption>
<Option name="org.coocox.codebugger.gdbjtag.core.adapter" value="ST-Link"/>
<Option name="org.coocox.codebugger.gdbjtag.core.debugMode" value="SWD"/>
<Option name="org.coocox.codebugger.gdbjtag.core.clockDiv" value="1M"/>
<Option name="org.coocox.codebugger.gdbjtag.corerunToMain" value="1"/>
<Option name="org.coocox.codebugger.gdbjtag.core.jlinkgdbserver" value=""/>
<Option name="org.coocox.codebugger.gdbjtag.core.userDefineGDBScript" value=""/>
<Option name="org.coocox.codebugger.gdbjtag.core.targetEndianess" value="0"/>
<Option name="org.coocox.codebugger.gdbjtag.core.jlinkResetMode" value="Type 0: Normal"/>
<Option name="org.coocox.codebugger.gdbjtag.core.resetMode" value="SYSRESETREQ"/>
<Option name="org.coocox.codebugger.gdbjtag.core.ifSemihost" value="0"/>
<Option name="org.coocox.codebugger.gdbjtag.core.ifCacheRom" value="1"/>
<Option name="org.coocox.codebugger.gdbjtag.core.ipAddress" value="127.0.0.1"/>
<Option name="org.coocox.codebugger.gdbjtag.core.portNumber" value="2009"/>
<Option name="org.coocox.codebugger.gdbjtag.core.autoDownload" value="1"/>
<Option name="org.coocox.codebugger.gdbjtag.core.verify" value="1"/>
<Option name="org.coocox.codebugger.gdbjtag.core.downloadFuction" value="Erase Effected"/>
<Option name="org.coocox.codebugger.gdbjtag.core.defaultAlgorithm" value="STM32F4xx_1024.elf"/>
</DebugOption>
<ExcludeFile/>
</Target>
<Target name="MMDVM_Nucleo_446" isCurrent="0">
<Device manufacturerId="9" manufacturerName="ST" chipId="344" chipName="STM32F407VG" boardId="" boardName=""/>
<BuildOption>
<Compile>
<Option name="OptimizationLevel" value="4"/>
<Option name="UseFPU" value="0"/>
<Option name="UserEditCompiler" value=""/>
<Option name="SupportCPlusplus" value="1"/>
<Option name="FPU" value="2"/>
<Includepaths>
<Includepath path="."/>
</Includepaths>
<DefinedSymbols>
<Define name="STM32F4XX"/>
<Define name="USE_STDPERIPH_DRIVER"/>
<Define name="__ASSEMBLY__"/>
<Define name="SUPPORT_CPLUSPLUS"/>
<Define name="HSE_VALUE=8000000"/>
<Define name="__FPU_USED"/>
<Define name="STM32F4_NUCLEO"/>
<Define name="STM32F446xx"/>
</DefinedSymbols>
</Compile>
<Link useDefault="0">
<Option name="DiscardUnusedSection" value="0"/>
<Option name="UserEditLinkder" value=""/>
<Option name="UseMemoryLayout" value="0"/>
<Option name="nostartfiles" value="1"/>
<Option name="LTO" value="0"/>
<Option name="IsNewStartupCode" value="1"/>
<Option name="Library" value="Semihosting"/>
<Option name="UserEditLinker" value="-lstdc++; --specs=nano.specs;"/>
<LinkedLibraries>
<Libset dir="stm32f4xx_lib\cmsis\lib\gcc\" libs="arm_cortexm4lf_math"/>
</LinkedLibraries>
<MemoryAreas debugInFlashNotRAM="1">
<Memory name="IROM1" type="ReadOnly" size="0x00100000" startValue="0x08000000"/>
<Memory name="IRAM1" type="ReadWrite" size="0x00020000" startValue="0x20000000"/>
<Memory name="IROM2" type="ReadOnly" size="" startValue=""/>
<Memory name="IRAM2" type="ReadWrite" size="0x00010000" startValue="0x10000000"/>
</MemoryAreas>
<LocateLinkFile path="./stm32f4xx_link.ld" type="0"/>
</Link>
<Output>
<Option name="OutputFileType" value="0"/>
<Option name="Path" value="./"/>
<Option name="Name" value="MMDVM_NUCLEO"/>
<Option name="HEX" value="1"/>
<Option name="BIN" value="1"/>
</Output>
<User>
<UserRun name="Run#1" type="Before" checked="0" value=""/>
<UserRun name="Run#1" type="After" checked="0" value=""/>
</User>
</BuildOption>
<DebugOption>
<Option name="org.coocox.codebugger.gdbjtag.core.adapter" value="ST-Link"/>
<Option name="org.coocox.codebugger.gdbjtag.core.debugMode" value="SWD"/>
<Option name="org.coocox.codebugger.gdbjtag.core.clockDiv" value="1M"/>
<Option name="org.coocox.codebugger.gdbjtag.corerunToMain" value="1"/>
<Option name="org.coocox.codebugger.gdbjtag.core.jlinkgdbserver" value=""/>
<Option name="org.coocox.codebugger.gdbjtag.core.userDefineGDBScript" value=""/>
<Option name="org.coocox.codebugger.gdbjtag.core.targetEndianess" value="0"/>
<Option name="org.coocox.codebugger.gdbjtag.core.jlinkResetMode" value="Type 0: Normal"/>
<Option name="org.coocox.codebugger.gdbjtag.core.resetMode" value="SYSRESETREQ"/>
<Option name="org.coocox.codebugger.gdbjtag.core.ifSemihost" value="0"/>
<Option name="org.coocox.codebugger.gdbjtag.core.ifCacheRom" value="1"/>
<Option name="org.coocox.codebugger.gdbjtag.core.ipAddress" value="127.0.0.1"/>
<Option name="org.coocox.codebugger.gdbjtag.core.portNumber" value="2009"/>
<Option name="org.coocox.codebugger.gdbjtag.core.autoDownload" value="1"/>
<Option name="org.coocox.codebugger.gdbjtag.core.verify" value="1"/>
<Option name="org.coocox.codebugger.gdbjtag.core.downloadFuction" value="Erase Effected"/>
<Option name="org.coocox.codebugger.gdbjtag.core.defaultAlgorithm" value="STM32F4xx_1024.elf"/>
</DebugOption>
<ExcludeFile/>
</Target>
<Components path="./">
</Components>
<Files>
<File name="DMRIdleRX.h" path="DMRIdleRX.h" type="1"/>
<File name="STM32F4XX_Lib/STM32F4xx_StdPeriph_Driver/source/stm32f4xx_dac.c" path="STM32F4XX_Lib/STM32F4xx_StdPeriph_Driver/source/stm32f4xx_dac.c" type="1"/>
<File name="DMRDMOTX.cpp" path="DMRDMOTX.cpp" type="1"/>
<File name="DMRRX.cpp" path="DMRRX.cpp" type="1"/>
<File name="YSFRX.cpp" path="YSFRX.cpp" type="1"/>
<File name="CalRSSI.cpp" path="CalRSSI.cpp" type="1"/>
<File name="STM32F4XX_Lib/Device/stm32f4xx.h" path="STM32F4XX_Lib/Device/stm32f4xx.h" type="1"/>
<File name="SampleRB.cpp" path="SampleRB.cpp" type="1"/>
<File name="CalDStarTX.h" path="CalDStarTX.h" type="1"/>
<File name="STM32F4XX_Lib/CMSIS/Include/core_cm4.h" path="STM32F4XX_Lib/CMSIS/Include/core_cm4.h" type="1"/>
<File name="DMRSlotRX.h" path="DMRSlotRX.h" type="1"/>
<File name="STM32F4XX_Lib/STM32F4xx_StdPeriph_Driver/source/stm32f4xx_tim.c" path="STM32F4XX_Lib/STM32F4xx_StdPeriph_Driver/source/stm32f4xx_tim.c" type="1"/>
<File name="YSFRX.h" path="YSFRX.h" type="1"/>
<File name="STM32F4XX_Lib/CMSIS/Include" path="" type="2"/>
<File name="IO.cpp" path="IO.cpp" type="1"/>
<File name="DMRDMORX.cpp" path="DMRDMORX.cpp" type="1"/>
<File name="P25RX.h" path="P25RX.h" type="1"/>
<File name="STM32F4XX_Lib/STM32F4xx_StdPeriph_Driver/source/misc.c" path="STM32F4XX_Lib/STM32F4xx_StdPeriph_Driver/source/misc.c" type="1"/>
<File name="STM32F4XX_Lib/CMSIS" path="" type="2"/>
<File name="SerialArduino.cpp" path="SerialArduino.cpp" type="1"/>
<File name="SerialPort.cpp" path="SerialPort.cpp" type="1"/>
<File name="STM32F4XX_Lib/Device/stm32f4xx_conf.h" path="STM32F4XX_Lib/Device/stm32f4xx_conf.h" type="1"/>
<File name="STM32F4XX_Lib/STM32F4xx_StdPeriph_Driver/source/stm32f4xx_adc.c" path="STM32F4XX_Lib/STM32F4xx_StdPeriph_Driver/source/stm32f4xx_adc.c" type="1"/>
<File name="DStarTX.cpp" path="DStarTX.cpp" type="1"/>
<File name="STM32F4XX_Lib/STM32F4xx_StdPeriph_Driver/source/stm32f4xx_usart.c" path="STM32F4XX_Lib/STM32F4xx_StdPeriph_Driver/source/stm32f4xx_usart.c" type="1"/>
<File name="SampleRB.h" path="SampleRB.h" type="1"/>
<File name="YSFTX.h" path="YSFTX.h" type="1"/>
<File name="DMRRX.h" path="DMRRX.h" type="1"/>
<File name="CalRSSI.h" path="CalRSSI.h" type="1"/>
<File name="IOTeensy.cpp" path="IOTeensy.cpp" type="1"/>
<File name="MMDVM.cpp" path="MMDVM.cpp" type="1"/>
<File name="STM32F4XX_Lib/CMSIS/Include/core_cmSimd.h" path="STM32F4XX_Lib/CMSIS/Include/core_cmSimd.h" type="1"/>
<File name="DMRDMORX.h" path="DMRDMORX.h" type="1"/>
<File name="SerialPort.h" path="SerialPort.h" type="1"/>
<File name="STM32F4XX_Lib/STM32F4xx_StdPeriph_Driver/include/stm32f4xx_dac.h" path="STM32F4XX_Lib/STM32F4xx_StdPeriph_Driver/include/stm32f4xx_dac.h" type="1"/>
<File name="CWIdTX.h" path="CWIdTX.h" type="1"/>
<File name="STM32F4XX_Lib/Device/system_stm32f4xx.h" path="STM32F4XX_Lib/Device/system_stm32f4xx.h" type="1"/>
<File name="STM32F4XX_Lib/CMSIS/Include/core_cmFunc.h" path="STM32F4XX_Lib/CMSIS/Include/core_cmFunc.h" type="1"/>
<File name="CalDStarTX.cpp" path="CalDStarTX.cpp" type="1"/>
<File name="STM32F4XX_Lib/STM32F4xx_StdPeriph_Driver/source" path="" type="2"/>
<File name="CalDMR.h" path="CalDMR.h" type="1"/>
<File name="CalFM.h" path="CalFM.h" type="1"/>
<File name="DMRDMOTX.h" path="DMRDMOTX.h" type="1"/>
<File name="IODue.cpp" path="IODue.cpp" type="1"/>
<File name="DMRTX.cpp" path="DMRTX.cpp" type="1"/>
<File name="P25RX.cpp" path="P25RX.cpp" type="1"/>
<File name="STM32F4XX_Lib/CMSIS/Lib/GCC" path="" type="2"/>
<File name="STM32F4XX_Lib" path="" type="2"/>
<File name="STM32F4XX_Lib/CMSIS/Include/core_cmInstr.h" path="STM32F4XX_Lib/CMSIS/Include/core_cmInstr.h" type="1"/>
<File name="DMRTX.h" path="DMRTX.h" type="1"/>
<File name="STM32F4XX_Lib/Device/system_stm32f4xx.c" path="STM32F4XX_Lib/Device/system_stm32f4xx.c" type="1"/>
<File name="RSSIRB.h" path="RSSIRB.h" type="1"/>
<File name="STM32F4XX_Lib/Device/startup/startup_stm32f4xx.c" path="STM32F4XX_Lib/Device/startup/startup_stm32f4xx.c" type="1"/>
<File name="STM32F4XX_Lib/Device/startup" path="" type="2"/>
<File name="SerialRB.h" path="SerialRB.h" type="1"/>
<File name="STM32F4XX_Lib/STM32F4xx_StdPeriph_Driver/include/stm32f4xx_gpio.h" path="STM32F4XX_Lib/STM32F4xx_StdPeriph_Driver/include/stm32f4xx_gpio.h" type="1"/>
<File name="STM32F4XX_Lib/STM32F4xx_StdPeriph_Driver" path="" type="2"/>
<File name="DMRDefines.h" path="DMRDefines.h" type="1"/>
<File name="CalDMR.cpp" path="CalDMR.cpp" type="1"/>
<File name="CalFM.cpp" path="CalFM.cpp" type="1"/>
<File name="STM32F4XX_Lib/STM32F4xx_StdPeriph_Driver/include/stm32f4xx_adc.h" path="STM32F4XX_Lib/STM32F4xx_StdPeriph_Driver/include/stm32f4xx_adc.h" type="1"/>
<File name="SerialSTM.cpp" path="SerialSTM.cpp" type="1"/>
<File name="STM32F4XX_Lib/CMSIS/Lib/GCC/libarm_cortexM4lf_math.a" path="STM32F4XX_Lib/CMSIS/Lib/GCC/libarm_cortexM4lf_math.a" type="1"/>
<File name="DStarDefines.h" path="DStarDefines.h" type="1"/>
<File name="DStarRX.h" path="DStarRX.h" type="1"/>
<File name="Config.h" path="Config.h" type="1"/>
<File name="DMRSlotType.cpp" path="DMRSlotType.cpp" type="1"/>
<File name="Globals.h" path="Globals.h" type="1"/>
<File name="STM32F4XX_Lib/Device" path="" type="2"/>
<File name="CalDStarRX.cpp" path="CalDStarRX.cpp" type="1"/>
<File name="STM32F4XX_Lib/STM32F4xx_StdPeriph_Driver/include/stm32f4xx_tim.h" path="STM32F4XX_Lib/STM32F4xx_StdPeriph_Driver/include/stm32f4xx_tim.h" type="1"/>
<File name="CalDStarRX.h" path="CalDStarRX.h" type="1"/>
<File name="STM32F4XX_Lib/STM32F4xx_StdPeriph_Driver/include" path="" type="2"/>
<File name="IO.h" path="IO.h" type="1"/>
<File name="Utils.cpp" path="Utils.cpp" type="1"/>
<File name="STM32F4XX_Lib/CMSIS/.DS_Store" path="STM32F4XX_Lib/CMSIS/.DS_Store" type="1"/>
<File name="STM32F4XX_Lib/CMSIS/Lib/.DS_Store" path="STM32F4XX_Lib/CMSIS/Lib/.DS_Store" type="1"/>
<File name="Utils.h" path="Utils.h" type="1"/>
<File name="STM32F4XX_Lib/CMSIS/Lib" path="" type="2"/>
<File name="STM32F4XX_Lib/STM32F4xx_StdPeriph_Driver/.DS_Store" path="STM32F4XX_Lib/STM32F4xx_StdPeriph_Driver/.DS_Store" type="1"/>
<File name="STM32F4XX_Lib/CMSIS/Include/.DS_Store" path="STM32F4XX_Lib/CMSIS/Include/.DS_Store" type="1"/>
<File name="STM32F4XX_Lib/CMSIS/Include/arm_math.h" path="STM32F4XX_Lib/CMSIS/Include/arm_math.h" type="1"/>
<File name="YSFDefines.h" path="YSFDefines.h" type="1"/>
<File name="DStarTX.h" path="DStarTX.h" type="1"/>
<File name="STM32F4XX_Lib/STM32F4xx_StdPeriph_Driver/source/stm32f4xx_rcc.c" path="STM32F4XX_Lib/STM32F4xx_StdPeriph_Driver/source/stm32f4xx_rcc.c" type="1"/>
<File name="STM32F4XX_Lib/Device/.DS_Store" path="STM32F4XX_Lib/Device/.DS_Store" type="1"/>
<File name="STM32F4XX_Lib/STM32F4xx_StdPeriph_Driver/include/stm32f4xx_rcc.h" path="STM32F4XX_Lib/STM32F4xx_StdPeriph_Driver/include/stm32f4xx_rcc.h" type="1"/>
<File name="P25Defines.h" path="P25Defines.h" type="1"/>
<File name="DMRSlotType.h" path="DMRSlotType.h" type="1"/>
<File name="Debug.h" path="Debug.h" type="1"/>
<File name="STM32F4XX_Lib/STM32F4xx_StdPeriph_Driver/include/misc.h" path="STM32F4XX_Lib/STM32F4xx_StdPeriph_Driver/include/misc.h" type="1"/>
<File name="P25TX.h" path="P25TX.h" type="1"/>
<File name="RSSIRB.cpp" path="RSSIRB.cpp" type="1"/>
<File name="DStarRX.cpp" path="DStarRX.cpp" type="1"/>
<File name="DMRSlotRX.cpp" path="DMRSlotRX.cpp" type="1"/>
<File name="IOSTM.cpp" path="IOSTM.cpp" type="1"/>
<File name="P25TX.cpp" path="P25TX.cpp" type="1"/>
<File name="SerialRB.cpp" path="SerialRB.cpp" type="1"/>
<File name="CWIdTX.cpp" path="CWIdTX.cpp" type="1"/>
<File name="DMRIdleRX.cpp" path="DMRIdleRX.cpp" type="1"/>
<File name="STM32F4XX_Lib/STM32F4xx_StdPeriph_Driver/include/stm32f4xx_usart.h" path="STM32F4XX_Lib/STM32F4xx_StdPeriph_Driver/include/stm32f4xx_usart.h" type="1"/>
<File name="STM32F4XX_Lib/.DS_Store" path="STM32F4XX_Lib/.DS_Store" type="1"/>
<File name="YSFTX.cpp" path="YSFTX.cpp" type="1"/>
<File name="STM32F4XX_Lib/STM32F4xx_StdPeriph_Driver/source/stm32f4xx_gpio.c" path="STM32F4XX_Lib/STM32F4xx_StdPeriph_Driver/source/stm32f4xx_gpio.c" type="1"/>
</Files>
</Project>
+17 -1
View File
@@ -25,6 +25,7 @@ F7_LIB_PATH=./STM32F7XX_Lib
# MCU external clock frequency (Hz) # MCU external clock frequency (Hz)
CLK_MMDVM_PI=12000000 CLK_MMDVM_PI=12000000
CLK_NUCLEO=8000000 CLK_NUCLEO=8000000
CLK_12MHZ=12000000
# Directory Structure # Directory Structure
BINDIR=bin BINDIR=bin
@@ -93,6 +94,8 @@ ifndef $(OSC)
OSC=$(CLK_MMDVM_PI) OSC=$(CLK_MMDVM_PI)
else ifeq ($(MAKECMDGOALS),pi-f722) else ifeq ($(MAKECMDGOALS),pi-f722)
OSC=$(CLK_MMDVM_PI) OSC=$(CLK_MMDVM_PI)
else ifeq ($(MAKECMDGOALS),drcc_nqf)
OSC=$(CLK_12MHZ)
else else
OSC=$(CLK_NUCLEO) OSC=$(CLK_NUCLEO)
endif endif
@@ -134,6 +137,9 @@ DEFS_RPT_HAT=-DUSE_HAL_DRIVER -DSTM32F722xx -DSTM32F7XX -DSTM32F722_RPT_HAT -DHS
DEFS_DVM=-DUSE_STDPERIPH_DRIVER -DSTM32F4XX -DSTM32F446xx -DSTM32F4_DVM -DHSE_VALUE=$(OSC) -DMADEBYMAKEFILE DEFS_DVM=-DUSE_STDPERIPH_DRIVER -DSTM32F4XX -DSTM32F446xx -DSTM32F4_DVM -DHSE_VALUE=$(OSC) -DMADEBYMAKEFILE
# MMDVM_RPT_Hat BG4TGO, BG5HHP board: # MMDVM_RPT_Hat BG4TGO, BG5HHP board:
DEFS_RPT_HAT_TGO=-DUSE_STDPERIPH_DRIVER -DSTM32F4XX -DSTM32F40_41xxx -DSTM32F4_RPT_HAT_TGO -DHSE_VALUE=$(OSC) -DMADEBYMAKEFILE 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
# Build compiler flags # Build compiler flags
CFLAGS_F4=-c $(MCFLAGS_F4) $(INCLUDES_F4) CFLAGS_F4=-c $(MCFLAGS_F4) $(INCLUDES_F4)
@@ -152,7 +158,7 @@ CXXFLAGS=-Os -fno-exceptions -ffunction-sections -fdata-sections -fno-builtin -f
LDFLAGS=-Os --specs=nano.specs LDFLAGS=-Os --specs=nano.specs
# Build Rules # Build Rules
.PHONY: all release dis pi pi-f722 f4m nucleo f767 dvm clean .PHONY: all release dis pi pi-f722 f4m nucleo f767 dvm drcc_nqf clean
# Default target: Nucleo-64 F446RE board # Default target: Nucleo-64 F446RE board
all: nucleo all: nucleo
@@ -217,6 +223,12 @@ dvm: CXXFLAGS+=$(CXXFLAGS_F4) $(DEFS_DVM)
dvm: LDFLAGS+=$(LDFLAGS_F4) dvm: LDFLAGS+=$(LDFLAGS_F4)
dvm: release_f4 dvm: release_f4
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
release_f4: $(BINDIR) release_f4: $(BINDIR)
release_f4: $(OBJDIR_F4) release_f4: $(OBJDIR_F4)
release_f4: $(BINDIR)/$(BINHEX_F4) release_f4: $(BINDIR)/$(BINHEX_F4)
@@ -365,3 +377,7 @@ else
echo "#define GITVERSION \"0000000\"" > $@ echo "#define GITVERSION \"0000000\"" > $@
endif endif
endif endif
flash_f4:
@echo "flashing firmware..."
st-flash write bin/$(BINBIN_F4) 0x8000000
+2 -2
View File
@@ -1,5 +1,5 @@
#!/usr/bin/make #!/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 # 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) C:=$(CC)
#SAM:=arduino/sam/ #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/ #CMSIS:=arduino/sam/system/CMSIS/
#LIBSAM:=arduino/sam/system/libsam #LIBSAM:=arduino/sam/system/libsam
TMPDIR:=$(PWD)/build TMPDIR:=$(PWD)/build
+39 -7
View File
@@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2009-2018 by Jonathan Naylor G4KLX * Copyright (C) 2009-2018,2020 by Jonathan Naylor G4KLX
* Copyright (C) 2017 by Andy Uribe CA6JAU * Copyright (C) 2017 by Andy Uribe CA6JAU
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
@@ -53,7 +53,9 @@ m_sincState(),
m_poBuffer(), m_poBuffer(),
m_poLen(0U), m_poLen(0U),
m_poPtr(0U), m_poPtr(0U),
m_txDelay(240U) // 200ms m_txDelay(240U), // 200ms
m_txHang(3000U), // 5s
m_txCount(0U)
{ {
::memset(m_modState, 0x00U, 16U * sizeof(q15_t)); ::memset(m_modState, 0x00U, 16U * sizeof(q15_t));
::memset(m_sincState, 0x00U, 70U * sizeof(q15_t)); ::memset(m_sincState, 0x00U, 70U * sizeof(q15_t));
@@ -70,10 +72,7 @@ m_txDelay(240U) // 200ms
void CNXDNTX::process() void CNXDNTX::process()
{ {
if (m_buffer.getData() == 0U && m_poLen == 0U) if (m_poLen == 0U && m_buffer.getData() > 0U) {
return;
if (m_poLen == 0U) {
if (!m_tx) { if (!m_tx) {
for (uint16_t i = 0U; i < m_txDelay; i++) for (uint16_t i = 0U; i < m_txDelay; i++)
m_poBuffer[m_poLen++] = NXDN_SYNC; m_poBuffer[m_poLen++] = NXDN_SYNC;
@@ -82,7 +81,8 @@ void CNXDNTX::process()
m_poBuffer[m_poLen++] = NXDN_PREAMBLE[2U]; m_poBuffer[m_poLen++] = NXDN_PREAMBLE[2U];
} else { } else {
for (uint8_t i = 0U; i < NXDN_FRAME_LENGTH_BYTES; i++) { 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; m_poBuffer[m_poLen++] = c;
} }
} }
@@ -98,6 +98,8 @@ void CNXDNTX::process()
writeByte(c); writeByte(c);
space -= 4U * NXDN_RADIO_SYMBOL_LENGTH; space -= 4U * NXDN_RADIO_SYMBOL_LENGTH;
if (m_duplex)
m_txCount = m_txHang;
if (m_poPtr >= m_poLen) { if (m_poPtr >= m_poLen) {
m_poPtr = 0U; m_poPtr = 0U;
@@ -105,6 +107,19 @@ void CNXDNTX::process()
return; return;
} }
} }
} else if (m_txCount > 0U) {
// Transmit silence until the hang timer has expired.
uint16_t space = io.getSpace();
while (space > (4U * NXDN_RADIO_SYMBOL_LENGTH)) {
writeSilence();
space -= 4U * NXDN_RADIO_SYMBOL_LENGTH;
m_txCount--;
if (m_txCount == 0U)
return;
}
} }
} }
@@ -155,6 +170,19 @@ void CNXDNTX::writeByte(uint8_t c)
io.write(STATE_NXDN, outBuffer, NXDN_RADIO_SYMBOL_LENGTH * 4U); io.write(STATE_NXDN, outBuffer, NXDN_RADIO_SYMBOL_LENGTH * 4U);
} }
void CNXDNTX::writeSilence()
{
q15_t inBuffer[4U] = {0x00U, 0x00U, 0x00U, 0x00U};
q15_t intBuffer[NXDN_RADIO_SYMBOL_LENGTH * 4U];
q15_t outBuffer[NXDN_RADIO_SYMBOL_LENGTH * 4U];
::arm_fir_interpolate_q15(&m_modFilter, inBuffer, intBuffer, 4U);
::arm_fir_fast_q15(&m_sincFilter, intBuffer, outBuffer, NXDN_RADIO_SYMBOL_LENGTH * 4U);
io.write(STATE_NXDN, outBuffer, NXDN_RADIO_SYMBOL_LENGTH * 4U);
}
void CNXDNTX::setTXDelay(uint8_t delay) void CNXDNTX::setTXDelay(uint8_t delay)
{ {
m_txDelay = 300U + uint16_t(delay) * 6U; // 500ms + tx delay m_txDelay = 300U + uint16_t(delay) * 6U; // 500ms + tx delay
@@ -168,3 +196,7 @@ uint8_t CNXDNTX::getSpace() const
return m_buffer.getSpace() / NXDN_FRAME_LENGTH_BYTES; return m_buffer.getSpace() / NXDN_FRAME_LENGTH_BYTES;
} }
void CNXDNTX::setParams(uint8_t txHang)
{
m_txHang = txHang * 600U;
}
+8 -4
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 * 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 * it under the terms of the GNU General Public License as published by
@@ -21,7 +21,7 @@
#include "Config.h" #include "Config.h"
#include "SerialRB.h" #include "RingBuffer.h"
class CNXDNTX { class CNXDNTX {
public: public:
@@ -35,8 +35,10 @@ public:
uint8_t getSpace() const; uint8_t getSpace() const;
void setParams(uint8_t txHang);
private: private:
CSerialRB m_buffer; CRingBuffer<uint8_t> m_buffer;
arm_fir_interpolate_instance_q15 m_modFilter; arm_fir_interpolate_instance_q15 m_modFilter;
arm_fir_instance_q15 m_sincFilter; arm_fir_instance_q15 m_sincFilter;
q15_t m_modState[16U]; // blockSize + phaseLength - 1, 4 + 9 - 1 plus some spare q15_t m_modState[16U]; // blockSize + phaseLength - 1, 4 + 9 - 1 plus some spare
@@ -45,9 +47,11 @@ private:
uint16_t m_poLen; uint16_t m_poLen;
uint16_t m_poPtr; uint16_t m_poPtr;
uint16_t m_txDelay; uint16_t m_txDelay;
uint32_t m_txHang;
uint32_t m_txCount;
void writeByte(uint8_t c); void writeByte(uint8_t c);
void writeSilence();
}; };
#endif #endif
+43 -9
View File
@@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2016,2017 by Jonathan Naylor G4KLX * Copyright (C) 2016,2017,2020 by Jonathan Naylor G4KLX
* Copyright (C) 2017 by Andy Uribe CA6JAU * Copyright (C) 2017 by Andy Uribe CA6JAU
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
@@ -51,7 +51,9 @@ m_lpState(),
m_poBuffer(), m_poBuffer(),
m_poLen(0U), m_poLen(0U),
m_poPtr(0U), m_poPtr(0U),
m_txDelay(240U) // 200ms m_txDelay(240U), // 200ms
m_txHang(6000U), // 5s
m_txCount(0U)
{ {
::memset(m_modState, 0x00U, 16U * sizeof(q15_t)); ::memset(m_modState, 0x00U, 16U * sizeof(q15_t));
::memset(m_lpState, 0x00U, 60U * sizeof(q15_t)); ::memset(m_lpState, 0x00U, 60U * sizeof(q15_t));
@@ -68,17 +70,16 @@ m_txDelay(240U) // 200ms
void CP25TX::process() void CP25TX::process()
{ {
if (m_buffer.getData() == 0U && m_poLen == 0U) if (m_poLen == 0U && m_buffer.getData() > 0U) {
return;
if (m_poLen == 0U) {
if (!m_tx) { if (!m_tx) {
for (uint16_t i = 0U; i < m_txDelay; i++) for (uint16_t i = 0U; i < m_txDelay; i++)
m_poBuffer[m_poLen++] = P25_START_SYNC; m_poBuffer[m_poLen++] = P25_START_SYNC;
} else { } else {
uint8_t length = m_buffer.get(); uint8_t length;
m_buffer.get(length);
for (uint8_t i = 0U; i < length; i++) { 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; m_poBuffer[m_poLen++] = c;
} }
} }
@@ -94,13 +95,28 @@ void CP25TX::process()
writeByte(c); writeByte(c);
space -= 4U * P25_RADIO_SYMBOL_LENGTH; space -= 4U * P25_RADIO_SYMBOL_LENGTH;
if (m_duplex)
m_txCount = m_txHang;
if (m_poPtr >= m_poLen) { if (m_poPtr >= m_poLen) {
m_poPtr = 0U; m_poPtr = 0U;
m_poLen = 0U; m_poLen = 0U;
return; return;
} }
} }
} else if (m_txCount > 0U) {
// Transmit silence until the hang timer has expired.
uint16_t space = io.getSpace();
while (space > (4U * P25_RADIO_SYMBOL_LENGTH)) {
writeSilence();
space -= 4U * P25_RADIO_SYMBOL_LENGTH;
m_txCount--;
if (m_txCount == 0U)
return;
}
} }
} }
@@ -152,6 +168,19 @@ void CP25TX::writeByte(uint8_t c)
io.write(STATE_P25, outBuffer, P25_RADIO_SYMBOL_LENGTH * 4U); io.write(STATE_P25, outBuffer, P25_RADIO_SYMBOL_LENGTH * 4U);
} }
void CP25TX::writeSilence()
{
q15_t inBuffer[4U] = {0x00U, 0x00U, 0x00U, 0x00U};
q15_t intBuffer[P25_RADIO_SYMBOL_LENGTH * 4U];
q15_t outBuffer[P25_RADIO_SYMBOL_LENGTH * 4U];
::arm_fir_interpolate_q15(&m_modFilter, inBuffer, intBuffer, 4U);
::arm_fir_fast_q15(&m_lpFilter, intBuffer, outBuffer, P25_RADIO_SYMBOL_LENGTH * 4U);
io.write(STATE_P25, outBuffer, P25_RADIO_SYMBOL_LENGTH * 4U);
}
void CP25TX::setTXDelay(uint8_t delay) void CP25TX::setTXDelay(uint8_t delay)
{ {
m_txDelay = 600U + uint16_t(delay) * 12U; // 500ms + tx delay m_txDelay = 600U + uint16_t(delay) * 12U; // 500ms + tx delay
@@ -164,3 +193,8 @@ uint8_t CP25TX::getSpace() const
{ {
return m_buffer.getSpace() / P25_LDU_FRAME_LENGTH_BYTES; return m_buffer.getSpace() / P25_LDU_FRAME_LENGTH_BYTES;
} }
void CP25TX::setParams(uint8_t txHang)
{
m_txHang = txHang * 1200U;
}
+8 -4
View File
@@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2016,2017 by Jonathan Naylor G4KLX * Copyright (C) 2016,2017,2020 by Jonathan Naylor G4KLX
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@@ -21,7 +21,7 @@
#include "Config.h" #include "Config.h"
#include "SerialRB.h" #include "RingBuffer.h"
class CP25TX { class CP25TX {
public: public:
@@ -35,8 +35,10 @@ public:
uint8_t getSpace() const; uint8_t getSpace() const;
void setParams(uint8_t txHang);
private: private:
CSerialRB m_buffer; CRingBuffer<uint8_t> m_buffer;
arm_fir_interpolate_instance_q15 m_modFilter; arm_fir_interpolate_instance_q15 m_modFilter;
arm_fir_instance_q15 m_lpFilter; arm_fir_instance_q15 m_lpFilter;
q15_t m_modState[16U]; // blockSize + phaseLength - 1, 4 + 9 - 1 plus some spare q15_t m_modState[16U]; // blockSize + phaseLength - 1, 4 + 9 - 1 plus some spare
@@ -45,9 +47,11 @@ private:
uint16_t m_poLen; uint16_t m_poLen;
uint16_t m_poPtr; uint16_t m_poPtr;
uint16_t m_txDelay; uint16_t m_txDelay;
uint32_t m_txHang;
uint32_t m_txCount;
void writeByte(uint8_t c); void writeByte(uint8_t c);
void writeSilence();
}; };
#endif #endif
+3 -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 * 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 * it under the terms of the GNU General Public License as published by
@@ -61,7 +61,8 @@ void CPOCSAGTX::process()
m_poBuffer[m_poLen++] = POCSAG_SYNC; m_poBuffer[m_poLen++] = POCSAG_SYNC;
} else { } else {
for (uint8_t i = 0U; i < POCSAG_FRAME_LENGTH_BYTES; i++) { 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; m_poBuffer[m_poLen++] = c;
} }
} }
@@ -146,4 +147,3 @@ uint8_t CPOCSAGTX::getSpace() const
{ {
return m_buffer.getSpace() / POCSAG_FRAME_LENGTH_BYTES; return m_buffer.getSpace() / POCSAG_FRAME_LENGTH_BYTES;
} }
+2 -2
View File
@@ -21,7 +21,7 @@
#include "Config.h" #include "Config.h"
#include "SerialRB.h" #include "RingBuffer.h"
class CPOCSAGTX { class CPOCSAGTX {
public: public:
@@ -40,7 +40,7 @@ public:
bool busy(); bool busy();
private: private:
CSerialRB m_buffer; CRingBuffer<uint8_t> m_buffer;
arm_fir_instance_q15 m_modFilter; arm_fir_instance_q15 m_modFilter;
q15_t m_modState[170U]; // NoTaps + BlockSize - 1, 6 + 160 - 1 plus some spare q15_t m_modState[170U]; // NoTaps + BlockSize - 1, 6 + 160 - 1 plus some spare
uint8_t m_poBuffer[200U]; uint8_t m_poBuffer[200U];
-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
+22 -13
View File
@@ -1,5 +1,6 @@
/* /*
* Copyright (C) 2020 by Jonathan Naylor G4KLX * 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 * 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 * it under the terms of the GNU General Public License as published by
@@ -16,8 +17,8 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/ */
#if !defined(FMRB_H) #if !defined(RINGBUFFER_H)
#define FMRB_H #define RINGBUFFER_H
#if defined(STM32F4XX) #if defined(STM32F4XX)
#include "stm32f4xx.h" #include "stm32f4xx.h"
@@ -28,6 +29,7 @@
#include <cstddef> #include <cstddef>
#else #else
#include <Arduino.h> #include <Arduino.h>
#undef PI
#endif #endif
#if defined(__SAM3X8E__) || defined(STM32F105xC) #if defined(__SAM3X8E__) || defined(STM32F105xC)
@@ -42,27 +44,34 @@
#include <arm_math.h> #include <arm_math.h>
class CFMDownsampleRB { template <typename TDATATYPE>
class CRingBuffer {
public: public:
CFMDownsampleRB(uint16_t length); CRingBuffer(uint16_t length = 370U);
uint16_t getSpace() const; uint16_t getSpace() const;
uint16_t getData() const; uint16_t getData() const;
bool put(uint8_t sample); bool put(TDATATYPE item) volatile;
bool get(uint8_t& sample); bool get(TDATATYPE& item) volatile;
TDATATYPE peek() const;
bool hasOverflowed(); bool hasOverflowed();
void reset();
private: private:
uint16_t m_length; uint16_t m_length;
volatile uint8_t* m_samples; TDATATYPE* m_buffer;
volatile uint16_t m_head; volatile uint16_t m_head;
volatile uint16_t m_tail; volatile uint16_t m_tail;
volatile bool m_full; volatile bool m_full;
bool m_overflow; bool m_overflow;
}; };
#endif #include "RingBuffer.impl.h"
#endif
+24 -11
View File
@@ -1,5 +1,6 @@
/* /*
* Copyright (C) 2020 by Jonathan Naylor G4KLX * 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 * 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 * 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. * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/ */
#include "RingBuffer.h"
#include "FMDownsampleRB.h" template <typename TDATATYPE> CRingBuffer<TDATATYPE>::CRingBuffer(uint16_t length) :
CFMDownsampleRB::CFMDownsampleRB(uint16_t length) :
m_length(length), m_length(length),
m_head(0U), m_head(0U),
m_tail(0U), m_tail(0U),
m_full(false), m_full(false),
m_overflow(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; uint16_t n = 0U;
@@ -46,7 +46,7 @@ uint16_t CFMDownsampleRB::getSpace() const
return n; return n;
} }
uint16_t CFMDownsampleRB::getData() const template <typename TDATATYPE> uint16_t CRingBuffer<TDATATYPE>::getData() const
{ {
if (m_tail == m_head) if (m_tail == m_head)
return m_full ? m_length : 0U; return m_full ? m_length : 0U;
@@ -56,14 +56,14 @@ uint16_t CFMDownsampleRB::getData() const
return m_length - m_tail + m_head; return m_length - m_tail + m_head;
} }
bool CFMDownsampleRB::put(uint8_t sample) template <typename TDATATYPE> bool CRingBuffer<TDATATYPE>::put(TDATATYPE item) volatile
{ {
if (m_full) { if (m_full) {
m_overflow = true; m_overflow = true;
return false; return false;
} }
m_samples[m_head] = sample; m_buffer[m_head] = item;
m_head++; m_head++;
if (m_head >= m_length) if (m_head >= m_length)
@@ -75,12 +75,17 @@ bool CFMDownsampleRB::put(uint8_t sample)
return true; 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) if (m_head == m_tail && !m_full)
return false; return false;
sample = m_samples[m_tail]; item = m_buffer[m_tail];
m_full = false; m_full = false;
@@ -91,7 +96,7 @@ bool CFMDownsampleRB::get(uint8_t& sample)
return true; return true;
} }
bool CFMDownsampleRB::hasOverflowed() template <typename TDATATYPE> bool CRingBuffer<TDATATYPE>::hasOverflowed()
{ {
bool overflow = m_overflow; bool overflow = m_overflow;
@@ -99,3 +104,11 @@ bool CFMDownsampleRB::hasOverflowed()
return overflow; return overflow;
} }
template <typename TDATATYPE> void CRingBuffer<TDATATYPE>::reset()
{
m_head = 0U;
m_tail = 0U;
m_full = false;
m_overflow = false;
}
+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
-106
View File
@@ -1,106 +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 "SampleRB.h"
CSampleRB::CSampleRB(uint16_t length) :
m_length(length),
m_head(0U),
m_tail(0U),
m_full(false),
m_overflow(false)
{
m_samples = new uint16_t[length];
m_control = new uint8_t[length];
}
uint16_t CSampleRB::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 CSampleRB::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 CSampleRB::put(uint16_t sample, uint8_t control)
{
if (m_full) {
m_overflow = true;
return false;
}
m_samples[m_head] = sample;
m_control[m_head] = control;
m_head++;
if (m_head >= m_length)
m_head = 0U;
if (m_head == m_tail)
m_full = true;
return true;
}
bool CSampleRB::get(uint16_t& sample, uint8_t& control)
{
if (m_head == m_tail && !m_full)
return false;
sample = m_samples[m_tail];
control = m_control[m_tail];
m_full = false;
m_tail++;
if (m_tail >= m_length)
m_tail = 0U;
return true;
}
bool CSampleRB::hasOverflowed()
{
bool overflow = m_overflow;
m_overflow = false;
return overflow;
}
-60
View File
@@ -1,60 +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(SAMPLERB_H)
#define SAMPLERB_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 CSampleRB {
public:
CSampleRB(uint16_t length);
uint16_t getSpace() const;
uint16_t getData() const;
bool put(uint16_t sample, uint8_t control);
bool get(uint16_t& sample, uint8_t& control);
bool hasOverflowed();
private:
uint16_t m_length;
volatile uint16_t* m_samples;
volatile uint8_t* m_control;
volatile uint16_t m_head;
volatile uint16_t m_tail;
volatile bool m_full;
bool m_overflow;
};
#endif
+141 -19
View File
@@ -68,6 +68,10 @@ const uint8_t MMDVM_POCSAG_DATA = 0x50U;
const uint8_t MMDVM_FM_PARAMS1 = 0x60U; const uint8_t MMDVM_FM_PARAMS1 = 0x60U;
const uint8_t MMDVM_FM_PARAMS2 = 0x61U; const uint8_t MMDVM_FM_PARAMS2 = 0x61U;
const uint8_t MMDVM_FM_PARAMS3 = 0x62U; const uint8_t MMDVM_FM_PARAMS3 = 0x62U;
const uint8_t MMDVM_FM_PARAMS4 = 0x63U;
const uint8_t MMDVM_FM_DATA = 0x65U;
const uint8_t MMDVM_FM_STATUS = 0x66U;
const uint8_t MMDVM_FM_EOT = 0x67U;
const uint8_t MMDVM_ACK = 0x70U; const uint8_t MMDVM_ACK = 0x70U;
const uint8_t MMDVM_NAK = 0x7FU; const uint8_t MMDVM_NAK = 0x7FU;
@@ -95,13 +99,15 @@ const uint8_t MMDVM_DEBUG5 = 0xF5U;
#define TCXO "NO TCXO" #define TCXO "NO TCXO"
#endif #endif
#if defined(STM32F4_RPT_HAT_TGO) #if defined(DRCC_DVM_NQF)
#define HW_TYPE "MMDVM DRCC_DVM_NQF"
#elif defined(STM32F4_RPT_HAT_TGO)
#define HW_TYPE "MMDVM RPT_HAT_TGO" #define HW_TYPE "MMDVM RPT_HAT_TGO"
#else #else
#define HW_TYPE "MMDVM" #define HW_TYPE "MMDVM"
#endif #endif
#define DESCRIPTION "20200429 (D-Star/DMR/System Fusion/P25/NXDN/POCSAG/FM)" #define DESCRIPTION "20200620 (D-Star/DMR/System Fusion/P25/NXDN/POCSAG/FM)"
#if defined(GITVERSION) #if defined(GITVERSION)
#define concat(h, a, b, c) h " " a " " b " GitID #" c "" #define concat(h, a, b, c) h " " a " " b " GitID #" c ""
@@ -156,7 +162,7 @@ void CSerialPort::getStatus()
// Send all sorts of interesting internal values // Send all sorts of interesting internal values
reply[0U] = MMDVM_FRAME_START; reply[0U] = MMDVM_FRAME_START;
reply[1U] = 13U; reply[1U] = 14U;
reply[2U] = MMDVM_GET_STATUS; reply[2U] = MMDVM_GET_STATUS;
reply[3U] = 0x00U; reply[3U] = 0x00U;
@@ -238,7 +244,12 @@ void CSerialPort::getStatus()
else else
reply[12U] = 0U; reply[12U] = 0U;
writeInt(1U, reply, 13); if (m_fmEnable)
reply[13U] = fm.getSpace();
else
reply[13U] = 0U;
writeInt(1U, reply, 14);
} }
void CSerialPort::getVersion() void CSerialPort::getVersion()
@@ -262,7 +273,7 @@ void CSerialPort::getVersion()
uint8_t CSerialPort::setConfig(const uint8_t* data, uint8_t length) uint8_t CSerialPort::setConfig(const uint8_t* data, uint8_t length)
{ {
if (length < 19U) if (length < 21U)
return 4U; return 4U;
bool rxInvert = (data[0U] & 0x01U) == 0x01U; bool rxInvert = (data[0U] & 0x01U) == 0x01U;
@@ -329,7 +340,11 @@ uint8_t CSerialPort::setConfig(const uint8_t* data, uint8_t length)
uint8_t fmTXLevel = data[18U]; uint8_t fmTXLevel = data[18U];
m_modemState = modemState; uint8_t p25TXHang = data[19U];
uint8_t nxdnTXHang = data[20U];
setMode(modemState);
m_dstarEnable = dstarEnable; m_dstarEnable = dstarEnable;
m_dmrEnable = dmrEnable; m_dmrEnable = dmrEnable;
@@ -354,6 +369,8 @@ uint8_t CSerialPort::setConfig(const uint8_t* data, uint8_t length)
dmrIdleRX.setColorCode(colorCode); dmrIdleRX.setColorCode(colorCode);
ysfTX.setParams(ysfLoDev, ysfTXHang); ysfTX.setParams(ysfLoDev, ysfTXHang);
p25TX.setParams(p25TXHang);
nxdnTX.setParams(nxdnTXHang);
io.setParameters(rxInvert, txInvert, pttInvert, rxLevel, cwIdTXLevel, dstarTXLevel, dmrTXLevel, ysfTXLevel, p25TXLevel, nxdnTXLevel, pocsagTXLevel, fmTXLevel, txDCOffset, rxDCOffset); io.setParameters(rxInvert, txInvert, pttInvert, rxLevel, cwIdTXLevel, dstarTXLevel, dmrTXLevel, ysfTXLevel, p25TXLevel, nxdnTXLevel, pocsagTXLevel, fmTXLevel, txDCOffset, rxDCOffset);
@@ -376,6 +393,7 @@ uint8_t CSerialPort::setFMParams1(const uint8_t* data, uint8_t length)
bool callAtStart = (data[6U] & 0x01U) == 0x01U; bool callAtStart = (data[6U] & 0x01U) == 0x01U;
bool callAtEnd = (data[6U] & 0x02U) == 0x02U; bool callAtEnd = (data[6U] & 0x02U) == 0x02U;
bool callAtLatch = (data[6U] & 0x04U) == 0x04U;
char callsign[50U]; char callsign[50U];
uint8_t n = 0U; uint8_t n = 0U;
@@ -383,7 +401,7 @@ uint8_t CSerialPort::setFMParams1(const uint8_t* data, uint8_t length)
callsign[n] = data[i]; callsign[n] = data[i];
callsign[n] = '\0'; callsign[n] = '\0';
return fm.setCallsign(callsign, speed, frequency, time, holdoff, highLevel, lowLevel, callAtStart, callAtEnd); return fm.setCallsign(callsign, speed, frequency, time, holdoff, highLevel, lowLevel, callAtStart, callAtEnd, callAtLatch);
} }
uint8_t CSerialPort::setFMParams2(const uint8_t* data, uint8_t length) uint8_t CSerialPort::setFMParams2(const uint8_t* data, uint8_t length)
@@ -408,26 +426,48 @@ uint8_t CSerialPort::setFMParams2(const uint8_t* data, uint8_t length)
uint8_t CSerialPort::setFMParams3(const uint8_t* data, uint8_t length) uint8_t CSerialPort::setFMParams3(const uint8_t* data, uint8_t length)
{ {
if (length < 11U) if (length < 12U)
return 4U; return 4U;
uint16_t timeout = data[0U] * 5U; uint16_t timeout = data[0U] * 5U;
uint8_t timeoutLevel = data[1U]; uint8_t timeoutLevel = data[1U];
uint8_t ctcssFrequency = data[2U]; uint8_t ctcssFrequency = data[2U];
uint8_t ctcssThreshold = data[3U]; uint8_t ctcssHighThreshold = data[3U];
uint8_t ctcssLevel = data[4U]; uint8_t ctcssLowThreshold = data[4U];
uint8_t ctcssLevel = data[5U];
uint8_t kerchunkTime = data[5U]; uint8_t kerchunkTime = data[6U];
uint8_t hangTime = data[6U]; uint8_t hangTime = data[7U];
bool useCOS = (data[7U] & 0x01U) == 0x01U; bool useCOS = (data[8U] & 0x01U) == 0x01U;
bool cosInvert = (data[8U] & 0x02U) == 0x02U;
bool kerchunkTX = (data[8U] & 0x04U) == 0x04U;
uint8_t rfAudioBoost = data[8U]; uint8_t rfAudioBoost = data[9U];
uint8_t maxDev = data[9U]; uint8_t maxDev = data[10U];
uint8_t rxLevel = data[10U]; uint8_t rxLevel = data[11U];
return fm.setMisc(timeout, timeoutLevel, ctcssFrequency, ctcssThreshold, ctcssLevel, kerchunkTime, hangTime, useCOS, rfAudioBoost, maxDev, rxLevel); return fm.setMisc(timeout, timeoutLevel, ctcssFrequency, ctcssHighThreshold, ctcssLowThreshold, ctcssLevel, kerchunkTime, kerchunkTX, hangTime, useCOS, cosInvert, rfAudioBoost, maxDev, rxLevel);
}
uint8_t CSerialPort::setFMParams4(const uint8_t* data, uint8_t length)
{
if (length < 4U)
return 4U;
uint8_t audioBoost = data[0U];
uint8_t speed = data[1U];
uint16_t frequency = data[2U] * 10U;
uint8_t level = data[3U];
char ack[50U];
uint8_t n = 0U;
for (uint8_t i = 4U; i < length; i++, n++)
ack[n] = data[i];
ack[n] = '\0';
return fm.setExt(ack, audioBoost, speed, frequency, level);
} }
uint8_t CSerialPort::setMode(const uint8_t* data, uint8_t length) uint8_t CSerialPort::setMode(const uint8_t* data, uint8_t length)
@@ -563,7 +603,7 @@ void CSerialPort::setMode(MMDVM_STATE modemState)
void CSerialPort::start() void CSerialPort::start()
{ {
beginInt(1U, 115200); beginInt(1U, SERIAL_SPEED);
#if defined(SERIAL_REPEATER) #if defined(SERIAL_REPEATER)
beginInt(3U, 9600); beginInt(3U, 9600);
@@ -658,6 +698,16 @@ void CSerialPort::process()
} }
break; break;
case MMDVM_FM_PARAMS4:
err = setFMParams4(m_buffer + 3U, m_len - 3U);
if (err == 0U) {
sendACK();
} else {
DEBUG2("Received invalid FM params 4", err);
sendNAK(err);
}
break;
case MMDVM_CAL_DATA: case MMDVM_CAL_DATA:
if (m_modemState == STATE_DSTARCAL) if (m_modemState == STATE_DSTARCAL)
err = calDStarTX.write(m_buffer + 3U, m_len - 3U); err = calDStarTX.write(m_buffer + 3U, m_len - 3U);
@@ -874,6 +924,20 @@ void CSerialPort::process()
} }
break; break;
case MMDVM_FM_DATA:
if (m_fmEnable) {
if (m_modemState == STATE_IDLE || m_modemState == STATE_FM)
err = fm.writeData(m_buffer + 3U, m_len - 3U);
}
if (err == 0U) {
if (m_modemState == STATE_IDLE)
setMode(STATE_FM);
} else {
DEBUG2("Received invalid FM data", err);
sendNAK(err);
}
break;
case MMDVM_TRANSPARENT: case MMDVM_TRANSPARENT:
case MMDVM_QSO_INFO: case MMDVM_QSO_INFO:
// Do nothing on the MMDVM. // Do nothing on the MMDVM.
@@ -1186,6 +1250,64 @@ void CSerialPort::writeNXDNLost()
writeInt(1U, reply, 3); writeInt(1U, reply, 3);
} }
void CSerialPort::writeFMData(const uint8_t* data, uint8_t length)
{
if (m_modemState != STATE_FM && m_modemState != STATE_IDLE)
return;
if (!m_fmEnable)
return;
uint8_t reply[255U];
reply[0U] = MMDVM_FRAME_START;
reply[1U] = 0U;
reply[2U] = MMDVM_FM_DATA;
uint8_t count = 3U;
for (uint8_t i = 0U; i < length; i++, count++)
reply[count] = data[i];
reply[1U] = count;
writeInt(1U, reply, count);
}
void CSerialPort::writeFMStatus(uint8_t status)
{
if (m_modemState != STATE_FM && m_modemState != STATE_IDLE)
return;
if (!m_fmEnable)
return;
uint8_t reply[10U];
reply[0U] = MMDVM_FRAME_START;
reply[1U] = 4U;
reply[2U] = MMDVM_FM_STATUS;
reply[3U] = status;
writeInt(1U, reply, 4U);
}
void CSerialPort::writeFMEOT()
{
if (m_modemState != STATE_FM && m_modemState != STATE_IDLE)
return;
if (!m_fmEnable)
return;
uint8_t reply[10U];
reply[0U] = MMDVM_FRAME_START;
reply[1U] = 3U;
reply[2U] = MMDVM_FM_EOT;
writeInt(1U, reply, 3U);
}
void CSerialPort::writeCalData(const uint8_t* data, uint8_t length) void CSerialPort::writeCalData(const uint8_t* data, uint8_t length)
{ {
if (m_modemState != STATE_DSTARCAL) if (m_modemState != STATE_DSTARCAL)
+12 -3
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 * 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 * it under the terms of the GNU General Public License as published by
@@ -21,7 +21,11 @@
#include "Config.h" #include "Config.h"
#include "Globals.h" #include "Globals.h"
#include "SerialRB.h" #include "RingBuffer.h"
#if !defined(SERIAL_SPEED)
#define SERIAL_SPEED 115200
#endif
class CSerialPort { class CSerialPort {
@@ -50,6 +54,10 @@ public:
void writeNXDNData(const uint8_t* data, uint8_t length); void writeNXDNData(const uint8_t* data, uint8_t length);
void writeNXDNLost(); void writeNXDNLost();
void writeFMData(const uint8_t* data, uint8_t length);
void writeFMStatus(uint8_t status);
void writeFMEOT();
void writeCalData(const uint8_t* data, uint8_t length); void writeCalData(const uint8_t* data, uint8_t length);
void writeRSSIData(const uint8_t* data, uint8_t length); void writeRSSIData(const uint8_t* data, uint8_t length);
@@ -64,7 +72,7 @@ private:
uint8_t m_ptr; uint8_t m_ptr;
uint8_t m_len; uint8_t m_len;
bool m_debug; bool m_debug;
CSerialRB m_repeat; CRingBuffer<uint8_t> m_repeat;
void sendACK(); void sendACK();
void sendNAK(uint8_t err); void sendNAK(uint8_t err);
@@ -76,6 +84,7 @@ private:
uint8_t setFMParams1(const uint8_t* data, uint8_t length); uint8_t setFMParams1(const uint8_t* data, uint8_t length);
uint8_t setFMParams2(const uint8_t* data, uint8_t length); uint8_t setFMParams2(const uint8_t* data, uint8_t length);
uint8_t setFMParams3(const uint8_t* data, uint8_t length); uint8_t setFMParams3(const uint8_t* data, uint8_t length);
uint8_t setFMParams4(const uint8_t* data, uint8_t length);
// Hardware versions // Hardware versions
void beginInt(uint8_t n, int speed); void beginInt(uint8_t n, int speed);
-100
View File
@@ -1,100 +0,0 @@
/*
Serial RB 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 "SerialRB.h"
CSerialRB::CSerialRB(uint16_t length) :
m_length(length),
m_head(0U),
m_tail(0U),
m_full(false)
{
m_buffer = new uint8_t[length];
}
void CSerialRB::reset()
{
m_head = 0U;
m_tail = 0U;
m_full = false;
}
uint16_t CSerialRB::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 CSerialRB::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 CSerialRB::put(uint8_t c)
{
if (m_full)
return false;
m_buffer[m_head] = c;
m_head++;
if (m_head >= m_length)
m_head = 0U;
if (m_head == m_tail)
m_full = true;
return true;
}
uint8_t CSerialRB::peek() const
{
return m_buffer[m_tail];
}
uint8_t CSerialRB::get()
{
uint8_t value = m_buffer[m_tail];
m_full = false;
m_tail++;
if (m_tail >= m_length)
m_tail = 0U;
return value;
}
-62
View File
@@ -1,62 +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(SERIALRB_H)
#define SERIALRB_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
const uint16_t SERIAL_RINGBUFFER_SIZE = 370U;
class CSerialRB {
public:
CSerialRB(uint16_t length = SERIAL_RINGBUFFER_SIZE);
uint16_t getSpace() const;
uint16_t getData() const;
void reset();
bool put(uint8_t c);
uint8_t peek() const;
uint8_t get();
private:
uint16_t m_length;
volatile uint8_t* m_buffer;
volatile uint16_t m_head;
volatile uint16_t m_tail;
volatile bool m_full;
};
#endif
+64 -576
View File
@@ -39,9 +39,7 @@ UART5 - TXD PC12 - RXD PD2 (Discovery, MMDVM-Pi, MMDVM-Pi F722 board, MMDVM-F4M
#if defined(STM32F4XX) || defined(STM32F7XX) #if defined(STM32F4XX) || defined(STM32F7XX)
#define TX_SERIAL_FIFO_SIZE 512U #include "STMUART.h"
#define RX_SERIAL_FIFO_SIZE 512U
extern "C" { extern "C" {
void USART1_IRQHandler(); void USART1_IRQHandler();
void USART2_IRQHandler(); void USART2_IRQHandler();
@@ -50,113 +48,14 @@ extern "C" {
} }
/* ************* USART1 ***************** */ /* ************* USART1 ***************** */
#if defined(STM32F4_PI) || defined(STM32F4_F4M) || defined(STM32F722_F7M) || defined(STM32F722_PI) || defined(STM32F722_RPT_HAT) || defined(STM32F4_DVM) || (defined(STM32F4_NUCLEO) && defined(STM32F4_NUCLEO_ARDUINO_HEADER)) #if defined(STM32F4_PI) || defined(STM32F4_F4M) || defined(STM32F722_F7M) || defined(STM32F722_PI) || defined(STM32F722_RPT_HAT) || defined(STM32F4_DVM) || (defined(STM32F4_NUCLEO) && defined(STM32F4_NUCLEO_ARDUINO_HEADER)) || defined(DRCC_DVM)
volatile uint8_t TXSerialfifo1[TX_SERIAL_FIFO_SIZE];
volatile uint8_t RXSerialfifo1[RX_SERIAL_FIFO_SIZE];
volatile uint16_t TXSerialfifohead1, TXSerialfifotail1;
volatile uint16_t RXSerialfifohead1, RXSerialfifotail1;
// Init queues static CSTMUART m_USART1;
void TXSerialfifoinit1()
{
TXSerialfifohead1 = 0U;
TXSerialfifotail1 = 0U;
}
void RXSerialfifoinit1()
{
RXSerialfifohead1 = 0U;
RXSerialfifotail1 = 0U;
}
// How full is queue
// TODO decide if how full or how empty is preferred info to return
uint16_t TXSerialfifolevel1()
{
uint32_t tail = TXSerialfifotail1;
uint32_t head = TXSerialfifohead1;
if (tail > head)
return TX_SERIAL_FIFO_SIZE + head - tail;
else
return head - tail;
}
uint16_t RXSerialfifolevel1()
{
uint32_t tail = RXSerialfifotail1;
uint32_t head = RXSerialfifohead1;
if (tail > head)
return RX_SERIAL_FIFO_SIZE + head - tail;
else
return head - tail;
}
// Flushes the transmit shift register
// warning: this call is blocking
void TXSerialFlush1()
{
// wait until the TXE shows the shift register is empty
while (USART_GetITStatus(USART1, USART_FLAG_TXE))
;
}
uint8_t TXSerialfifoput1(uint8_t next)
{
if (TXSerialfifolevel1() < TX_SERIAL_FIFO_SIZE) {
TXSerialfifo1[TXSerialfifohead1] = next;
TXSerialfifohead1++;
if (TXSerialfifohead1 >= TX_SERIAL_FIFO_SIZE)
TXSerialfifohead1 = 0U;
// make sure transmit interrupts are enabled as long as there is data to send
USART_ITConfig(USART1, USART_IT_TXE, ENABLE);
return 1U;
} else {
return 0U; // signal an overflow occurred by returning a zero count
}
}
void USART1_IRQHandler() void USART1_IRQHandler()
{ {
uint8_t c; m_USART1.handleIRQ();
if (USART_GetITStatus(USART1, USART_IT_RXNE)) {
c = (uint8_t) USART_ReceiveData(USART1);
if (RXSerialfifolevel1() < RX_SERIAL_FIFO_SIZE) {
RXSerialfifo1[RXSerialfifohead1] = c;
RXSerialfifohead1++;
if (RXSerialfifohead1 >= RX_SERIAL_FIFO_SIZE)
RXSerialfifohead1 = 0U;
} else {
// TODO - do something if rx fifo is full?
}
USART_ClearITPendingBit(USART1, USART_IT_RXNE);
}
if (USART_GetITStatus(USART1, USART_IT_TXE)) {
c = 0U;
if (TXSerialfifohead1 != TXSerialfifotail1) { // if the fifo is not empty
c = TXSerialfifo1[TXSerialfifotail1];
TXSerialfifotail1++;
if (TXSerialfifotail1 >= TX_SERIAL_FIFO_SIZE)
TXSerialfifotail1 = 0U;
USART_SendData(USART1, c);
} else { // if there's no more data to transmit then turn off TX interrupts
USART_ITConfig(USART1, USART_IT_TXE, DISABLE);
}
USART_ClearITPendingBit(USART1, USART_IT_TXE);
}
} }
void InitUSART1(int speed) void InitUSART1(int speed)
@@ -201,153 +100,20 @@ void InitUSART1(int speed)
USART_ITConfig(USART1, USART_IT_RXNE, ENABLE); USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);
// initialize the fifos m_USART1.init(USART1);
TXSerialfifoinit1();
RXSerialfifoinit1();
}
uint8_t AvailUSART1()
{
if (RXSerialfifolevel1() > 0U)
return 1U;
else
return 0U;
}
int AvailForWriteUSART1()
{
return TX_SERIAL_FIFO_SIZE - TXSerialfifolevel1();
}
uint8_t ReadUSART1()
{
uint8_t data_c = RXSerialfifo1[RXSerialfifotail1];
RXSerialfifotail1++;
if (RXSerialfifotail1 >= RX_SERIAL_FIFO_SIZE)
RXSerialfifotail1 = 0U;
return data_c;
}
void WriteUSART1(const uint8_t* data, uint16_t length)
{
for (uint16_t i = 0U; i < length; i++)
TXSerialfifoput1(data[i]);
USART_ITConfig(USART1, USART_IT_TXE, ENABLE);
} }
#endif #endif
/* ************* USART2 ***************** */ /* ************* USART2 ***************** */
#if defined(STM32F4_NUCLEO) || defined(STM32F4_RPT_HAT_TGO) #if defined(STM32F4_NUCLEO) || defined(STM32F4_RPT_HAT_TGO) || defined(DRCC_DVM)
volatile uint8_t TXSerialfifo2[TX_SERIAL_FIFO_SIZE]; static CSTMUART m_USART2;
volatile uint8_t RXSerialfifo2[RX_SERIAL_FIFO_SIZE];
volatile uint16_t TXSerialfifohead2, TXSerialfifotail2;
volatile uint16_t RXSerialfifohead2, RXSerialfifotail2;
// Init queues
void TXSerialfifoinit2()
{
TXSerialfifohead2 = 0U;
TXSerialfifotail2 = 0U;
}
void RXSerialfifoinit2()
{
RXSerialfifohead2 = 0U;
RXSerialfifotail2 = 0U;
}
// How full is queue
// TODO decide if how full or how empty is preferred info to return
uint16_t TXSerialfifolevel2()
{
uint32_t tail = TXSerialfifotail2;
uint32_t head = TXSerialfifohead2;
if (tail > head)
return TX_SERIAL_FIFO_SIZE + head - tail;
else
return head - tail;
}
uint16_t RXSerialfifolevel2()
{
uint32_t tail = RXSerialfifotail2;
uint32_t head = RXSerialfifohead2;
if (tail > head)
return RX_SERIAL_FIFO_SIZE + head - tail;
else
return head - tail;
}
// Flushes the transmit shift register
// warning: this call is blocking
void TXSerialFlush2()
{
// wait until the TXE shows the shift register is empty
while (USART_GetITStatus(USART2, USART_FLAG_TXE))
;
}
uint8_t TXSerialfifoput2(uint8_t next)
{
if (TXSerialfifolevel2() < TX_SERIAL_FIFO_SIZE) {
TXSerialfifo2[TXSerialfifohead2] = next;
TXSerialfifohead2++;
if (TXSerialfifohead2 >= TX_SERIAL_FIFO_SIZE)
TXSerialfifohead2 = 0U;
// make sure transmit interrupts are enabled as long as there is data to send
USART_ITConfig(USART2, USART_IT_TXE, ENABLE);
return 1U;
} else {
return 0U; // signal an overflow occurred by returning a zero count
}
}
void USART2_IRQHandler() void USART2_IRQHandler()
{ {
uint8_t c; m_USART2.handleIRQ();
if (USART_GetITStatus(USART2, USART_IT_RXNE)) {
c = (uint8_t) USART_ReceiveData(USART2);
if (RXSerialfifolevel2() < RX_SERIAL_FIFO_SIZE) {
RXSerialfifo2[RXSerialfifohead2] = c;
RXSerialfifohead2++;
if (RXSerialfifohead2 >= RX_SERIAL_FIFO_SIZE)
RXSerialfifohead2 = 0U;
} else {
// TODO - do something if rx fifo is full?
}
USART_ClearITPendingBit(USART2, USART_IT_RXNE);
}
if (USART_GetITStatus(USART2, USART_IT_TXE)) {
c = 0U;
if (TXSerialfifohead2 != TXSerialfifotail2) { // if the fifo is not empty
c = TXSerialfifo2[TXSerialfifotail2];
TXSerialfifotail2++;
if (TXSerialfifotail2 >= TX_SERIAL_FIFO_SIZE)
TXSerialfifotail2 = 0U;
USART_SendData(USART2, c);
} else { // if there's no more data to transmit then turn off TX interrupts
USART_ITConfig(USART2, USART_IT_TXE, DISABLE);
}
USART_ClearITPendingBit(USART2, USART_IT_TXE);
}
} }
void InitUSART2(int speed) void InitUSART2(int speed)
@@ -392,41 +158,7 @@ void InitUSART2(int speed)
USART_ITConfig(USART2, USART_IT_RXNE, ENABLE); USART_ITConfig(USART2, USART_IT_RXNE, ENABLE);
// initialize the fifos m_USART2.init(USART2);
TXSerialfifoinit2();
RXSerialfifoinit2();
}
uint8_t AvailUSART2()
{
if (RXSerialfifolevel2() > 0U)
return 1U;
else
return 0U;
}
int AvailForWriteUSART2()
{
return TX_SERIAL_FIFO_SIZE - TXSerialfifolevel2();
}
uint8_t ReadUSART2()
{
uint8_t data_c = RXSerialfifo2[RXSerialfifotail2];
RXSerialfifotail2++;
if (RXSerialfifotail2 >= RX_SERIAL_FIFO_SIZE)
RXSerialfifotail2 = 0U;
return data_c;
}
void WriteUSART2(const uint8_t* data, uint16_t length)
{
for (uint16_t i = 0U; i < length; i++)
TXSerialfifoput2(data[i]);
USART_ITConfig(USART2, USART_IT_TXE, ENABLE);
} }
#endif #endif
@@ -434,111 +166,11 @@ void WriteUSART2(const uint8_t* data, uint16_t length)
/* ************* USART3 ***************** */ /* ************* USART3 ***************** */
#if defined(STM32F4_DISCOVERY) || defined(STM32F7_NUCLEO) #if defined(STM32F4_DISCOVERY) || defined(STM32F7_NUCLEO)
volatile uint8_t TXSerialfifo3[TX_SERIAL_FIFO_SIZE]; static CSTMUART m_USART3;
volatile uint8_t RXSerialfifo3[RX_SERIAL_FIFO_SIZE];
volatile uint16_t TXSerialfifohead3, TXSerialfifotail3;
volatile uint16_t RXSerialfifohead3, RXSerialfifotail3;
// Init queues
void TXSerialfifoinit3()
{
TXSerialfifohead3 = 0U;
TXSerialfifotail3 = 0U;
}
void RXSerialfifoinit3()
{
RXSerialfifohead3 = 0U;
RXSerialfifotail3 = 0U;
}
// How full is queue
// TODO decide if how full or how empty is preferred info to return
uint16_t TXSerialfifolevel3()
{
uint32_t tail = TXSerialfifotail3;
uint32_t head = TXSerialfifohead3;
if (tail > head)
return TX_SERIAL_FIFO_SIZE + head - tail;
else
return head - tail;
}
uint16_t RXSerialfifolevel3()
{
uint32_t tail = RXSerialfifotail3;
uint32_t head = RXSerialfifohead3;
if (tail > head)
return RX_SERIAL_FIFO_SIZE + head - tail;
else
return head - tail;
}
// Flushes the transmit shift register
// warning: this call is blocking
void TXSerialFlush3()
{
// wait until the TXE shows the shift register is empty
while (USART_GetITStatus(USART3, USART_FLAG_TXE))
;
}
uint8_t TXSerialfifoput3(uint8_t next)
{
if (TXSerialfifolevel3() < TX_SERIAL_FIFO_SIZE) {
TXSerialfifo3[TXSerialfifohead3] = next;
TXSerialfifohead3++;
if (TXSerialfifohead3 >= TX_SERIAL_FIFO_SIZE)
TXSerialfifohead3 = 0U;
// make sure transmit interrupts are enabled as long as there is data to send
USART_ITConfig(USART3, USART_IT_TXE, ENABLE);
return 1U;
} else {
return 0U; // signal an overflow occurred by returning a zero count
}
}
void USART3_IRQHandler() void USART3_IRQHandler()
{ {
uint8_t c; m_USART3.handleIRQ();
if (USART_GetITStatus(USART3, USART_IT_RXNE)) {
c = (uint8_t) USART_ReceiveData(USART3);
if (RXSerialfifolevel3() < RX_SERIAL_FIFO_SIZE) {
RXSerialfifo3[RXSerialfifohead3] = c;
RXSerialfifohead3++;
if (RXSerialfifohead3 >= RX_SERIAL_FIFO_SIZE)
RXSerialfifohead3 = 0U;
} else {
// TODO - do something if rx fifo is full?
}
USART_ClearITPendingBit(USART3, USART_IT_RXNE);
}
if (USART_GetITStatus(USART3, USART_IT_TXE)) {
c = 0U;
if (TXSerialfifohead3 != TXSerialfifotail3) { // if the fifo is not empty
c = TXSerialfifo3[TXSerialfifotail3];
TXSerialfifotail3++;
if (TXSerialfifotail3 >= TX_SERIAL_FIFO_SIZE)
TXSerialfifotail3 = 0U;
USART_SendData(USART3, c);
} else { // if there's no more data to transmit then turn off TX interrupts
USART_ITConfig(USART3, USART_IT_TXE, DISABLE);
}
USART_ClearITPendingBit(USART3, USART_IT_TXE);
}
} }
#if defined(STM32F7_NUCLEO) #if defined(STM32F7_NUCLEO)
@@ -600,41 +232,7 @@ void InitUSART3(int speed)
USART_ITConfig(USART3, USART_IT_RXNE, ENABLE); USART_ITConfig(USART3, USART_IT_RXNE, ENABLE);
// initialize the fifos m_USART3.init(USART3);
TXSerialfifoinit3();
RXSerialfifoinit3();
}
uint8_t AvailUSART3()
{
if (RXSerialfifolevel3() > 0U)
return 1U;
else
return 0U;
}
int AvailForWriteUSART3()
{
return TX_SERIAL_FIFO_SIZE - TXSerialfifolevel3();
}
uint8_t ReadUSART3()
{
uint8_t data_c = RXSerialfifo3[RXSerialfifotail3];
RXSerialfifotail3++;
if (RXSerialfifotail3 >= RX_SERIAL_FIFO_SIZE)
RXSerialfifotail3 = 0U;
return data_c;
}
void WriteUSART3(const uint8_t* data, uint16_t length)
{
for (uint16_t i = 0U; i < length; i++)
TXSerialfifoput3(data[i]);
USART_ITConfig(USART3, USART_IT_TXE, ENABLE);
} }
#endif #endif
@@ -642,111 +240,11 @@ void WriteUSART3(const uint8_t* data, uint16_t length)
/* ************* UART5 ***************** */ /* ************* UART5 ***************** */
#if !(defined(STM32F4_NUCLEO) && defined(STM32F4_NUCLEO_ARDUINO_HEADER)) #if !(defined(STM32F4_NUCLEO) && defined(STM32F4_NUCLEO_ARDUINO_HEADER))
volatile uint8_t TXSerialfifo5[TX_SERIAL_FIFO_SIZE]; static CSTMUART m_UART5;
volatile uint8_t RXSerialfifo5[RX_SERIAL_FIFO_SIZE];
volatile uint16_t TXSerialfifohead5, TXSerialfifotail5;
volatile uint16_t RXSerialfifohead5, RXSerialfifotail5;
// Init queues
void TXSerialfifoinit5()
{
TXSerialfifohead5 = 0U;
TXSerialfifotail5 = 0U;
}
void RXSerialfifoinit5()
{
RXSerialfifohead5 = 0U;
RXSerialfifotail5 = 0U;
}
// How full is queue
// TODO decide if how full or how empty is preferred info to return
uint16_t TXSerialfifolevel5()
{
uint32_t tail = TXSerialfifotail5;
uint32_t head = TXSerialfifohead5;
if (tail > head)
return TX_SERIAL_FIFO_SIZE + head - tail;
else
return head - tail;
}
uint16_t RXSerialfifolevel5()
{
uint32_t tail = RXSerialfifotail5;
uint32_t head = RXSerialfifohead5;
if (tail > head)
return RX_SERIAL_FIFO_SIZE + head - tail;
else
return head - tail;
}
// Flushes the transmit shift register
// warning: this call is blocking
void TXSerialFlush5()
{
// wait until the TXE shows the shift register is empty
while (USART_GetITStatus(UART5, USART_FLAG_TXE))
;
}
uint8_t TXSerialfifoput5(uint8_t next)
{
if (TXSerialfifolevel5() < TX_SERIAL_FIFO_SIZE) {
TXSerialfifo5[TXSerialfifohead5] = next;
TXSerialfifohead5++;
if (TXSerialfifohead5 >= TX_SERIAL_FIFO_SIZE)
TXSerialfifohead5 = 0U;
// make sure transmit interrupts are enabled as long as there is data to send
USART_ITConfig(UART5, USART_IT_TXE, ENABLE);
return 1U;
} else {
return 0U; // signal an overflow occurred by returning a zero count
}
}
void UART5_IRQHandler() void UART5_IRQHandler()
{ {
uint8_t c; m_UART5.handleIRQ();
if (USART_GetITStatus(UART5, USART_IT_RXNE)) {
c = (uint8_t) USART_ReceiveData(UART5);
if (RXSerialfifolevel5() < RX_SERIAL_FIFO_SIZE) {
RXSerialfifo5[RXSerialfifohead5] = c;
RXSerialfifohead5++;
if (RXSerialfifohead5 >= RX_SERIAL_FIFO_SIZE)
RXSerialfifohead5 = 0U;
} else {
// TODO - do something if rx fifo is full?
}
USART_ClearITPendingBit(UART5, USART_IT_RXNE);
}
if (USART_GetITStatus(UART5, USART_IT_TXE)) {
c = 0U;
if (TXSerialfifohead5 != TXSerialfifotail5) { // if the fifo is not empty
c = TXSerialfifo5[TXSerialfifotail5];
TXSerialfifotail5++;
if (TXSerialfifotail5 >= TX_SERIAL_FIFO_SIZE)
TXSerialfifotail5 = 0U;
USART_SendData(UART5, c);
} else { // if there's no more data to transmit then turn off TX interrupts
USART_ITConfig(UART5, USART_IT_TXE, DISABLE);
}
USART_ClearITPendingBit(UART5, USART_IT_TXE);
}
} }
void InitUART5(int speed) void InitUART5(int speed)
@@ -795,41 +293,7 @@ void InitUART5(int speed)
USART_ITConfig(UART5, USART_IT_RXNE, ENABLE); USART_ITConfig(UART5, USART_IT_RXNE, ENABLE);
// initialize the fifos m_UART5.init(UART5);
TXSerialfifoinit5();
RXSerialfifoinit5();
}
uint8_t AvailUART5()
{
if (RXSerialfifolevel5() > 0U)
return 1U;
else
return 0U;
}
int AvailForWriteUART5()
{
return TX_SERIAL_FIFO_SIZE - TXSerialfifolevel5();
}
uint8_t ReadUART5()
{
uint8_t data_c = RXSerialfifo5[RXSerialfifotail5];
RXSerialfifotail5++;
if (RXSerialfifotail5 >= RX_SERIAL_FIFO_SIZE)
RXSerialfifotail5 = 0U;
return data_c;
}
void WriteUART5(const uint8_t* data, uint16_t length)
{
for (uint16_t i = 0U; i < length; i++)
TXSerialfifoput5(data[i]);
USART_ITConfig(UART5, USART_IT_TXE, ENABLE);
} }
#endif #endif
@@ -845,11 +309,15 @@ void CSerialPort::beginInt(uint8_t n, int speed)
InitUSART1(speed); InitUSART1(speed);
#elif defined(STM32F4_NUCLEO) || defined(STM32F4_RPT_HAT_TGO) #elif defined(STM32F4_NUCLEO) || defined(STM32F4_RPT_HAT_TGO)
InitUSART2(speed); InitUSART2(speed);
#elif defined(DRCC_DVM)
InitUSART1(speed);
#endif #endif
break; break;
case 3U: case 3U:
#if defined(STM32F4_NUCLEO) && defined(STM32F4_NUCLEO_ARDUINO_HEADER) #if defined(STM32F4_NUCLEO) && defined(STM32F4_NUCLEO_ARDUINO_HEADER)
InitUSART1(speed); InitUSART1(speed);
#elif defined(DRCC_DVM)
InitUSART2(speed);
#else #else
InitUART5(speed); InitUART5(speed);
#endif #endif
@@ -864,17 +332,21 @@ int CSerialPort::availableInt(uint8_t n)
switch (n) { switch (n) {
case 1U: case 1U:
#if defined(STM32F4_DISCOVERY) || defined(STM32F7_NUCLEO) #if defined(STM32F4_DISCOVERY) || defined(STM32F7_NUCLEO)
return AvailUSART3(); return m_USART3.availble();//AvailUSART3();
#elif defined(STM32F4_PI) || defined(STM32F4_F4M) || defined(STM32F722_PI) || defined(STM32F722_F7M) || defined(STM32F722_RPT_HAT) || defined(STM32F4_DVM) #elif defined(STM32F4_PI) || defined(STM32F4_F4M) || defined(STM32F722_PI) || defined(STM32F722_F7M) || defined(STM32F722_RPT_HAT) || defined(STM32F4_DVM)
return AvailUSART1(); return m_USART1.available();//AvailUSART1();
#elif defined(STM32F4_NUCLEO) || defined(STM32F4_RPT_HAT_TGO) #elif defined(STM32F4_NUCLEO) || defined(STM32F4_RPT_HAT_TGO)
return AvailUSART2(); return m_USART2.available();//AvailUSART2();
#elif defined(DRCC_DVM)
return m_USART1.available();//AvailUSART1();
#endif #endif
case 3U: case 3U:
#if defined(STM32F4_NUCLEO) && defined(STM32F4_NUCLEO_ARDUINO_HEADER) #if defined(STM32F4_NUCLEO) && defined(STM32F4_NUCLEO_ARDUINO_HEADER)
return AvailUSART1(); return m_USART1.available(); //AvailUSART1();
#elif defined(DRCC_DVM)
return m_USART2.available(); //AvailUSART2();
#else #else
return AvailUART5(); return m_UART5.available();//AvailUART5();
#endif #endif
default: default:
return 0; return 0;
@@ -886,17 +358,21 @@ int CSerialPort::availableForWriteInt(uint8_t n)
switch (n) { switch (n) {
case 1U: case 1U:
#if defined(STM32F4_DISCOVERY) || defined(STM32F7_NUCLEO) #if defined(STM32F4_DISCOVERY) || defined(STM32F7_NUCLEO)
return AvailForWriteUSART3(); return m_USART3.availableForWrite(); //AvailForWriteUSART3();
#elif defined(STM32F4_PI) || defined(STM32F4_F4M) || defined(STM32F722_PI) || defined(STM32F722_F7M) || defined(STM32F722_RPT_HAT) || defined(STM32F4_DVM) #elif defined(STM32F4_PI) || defined(STM32F4_F4M) || defined(STM32F722_PI) || defined(STM32F722_F7M) || defined(STM32F722_RPT_HAT) || defined(STM32F4_DVM)
return AvailForWriteUSART1(); return m_USART1.availableForWrite(); //AvailForWriteUSART1();
#elif defined(STM32F4_NUCLEO) || defined(STM32F4_RPT_HAT_TGO) #elif defined(STM32F4_NUCLEO) || defined(STM32F4_RPT_HAT_TGO)
return AvailForWriteUSART2(); return m_USART2.availableForWrite();//AvailForWriteUSART2();
#elif defined(DRCC_DVM)
return m_USART1.availableForWrite();//AvailForWriteUSART1();
#endif #endif
case 3U: case 3U:
#if defined(STM32F4_NUCLEO) && defined(STM32F4_NUCLEO_ARDUINO_HEADER) #if defined(STM32F4_NUCLEO) && defined(STM32F4_NUCLEO_ARDUINO_HEADER)
return AvailForWriteUSART1(); return m_USART1.availableForWrite(); //AvailForWriteUSART1();
#elif defined(DRCC_DVM)
return m_USART2.availableForWrite();//AvailForWriteUSART2();
#else #else
return AvailForWriteUART5(); return m_UART5.availableForWrite();//AvailForWriteUART5();
#endif #endif
default: default:
return 0; return 0;
@@ -908,17 +384,21 @@ uint8_t CSerialPort::readInt(uint8_t n)
switch (n) { switch (n) {
case 1U: case 1U:
#if defined(STM32F4_DISCOVERY) || defined(STM32F7_NUCLEO) #if defined(STM32F4_DISCOVERY) || defined(STM32F7_NUCLEO)
return ReadUSART3(); return m_USART3.read();//ReadUSART3();
#elif defined(STM32F4_PI) || defined(STM32F4_F4M) || defined(STM32F722_PI) || defined(STM32F722_F7M) || defined(STM32F722_RPT_HAT) || defined(STM32F4_DVM) #elif defined(STM32F4_PI) || defined(STM32F4_F4M) || defined(STM32F722_PI) || defined(STM32F722_F7M) || defined(STM32F722_RPT_HAT) || defined(STM32F4_DVM)
return ReadUSART1(); return m_USART1.read();//ReadUSART1();
#elif defined(STM32F4_NUCLEO) || defined(STM32F4_RPT_HAT_TGO) #elif defined(STM32F4_NUCLEO) || defined(STM32F4_RPT_HAT_TGO)
return ReadUSART2(); return m_USART2.read();//ReadUSART2();
#elif defined(DRCC_DVM)
return m_USART1.read();//ReadUSART1();
#endif #endif
case 3U: case 3U:
#if defined(STM32F4_NUCLEO) && defined(STM32F4_NUCLEO_ARDUINO_HEADER) #if defined(STM32F4_NUCLEO) && defined(STM32F4_NUCLEO_ARDUINO_HEADER)
return ReadUSART1(); return m_USART1.read();//ReadUSART1();
#elif defined(DRCC_DVM)
return m_USART2.read();//ReadUSART2();
#else #else
return ReadUART5(); return m_UART5.read();//ReadUART5();
#endif #endif
default: default:
return 0U; return 0U;
@@ -930,28 +410,36 @@ void CSerialPort::writeInt(uint8_t n, const uint8_t* data, uint16_t length, bool
switch (n) { switch (n) {
case 1U: case 1U:
#if defined(STM32F4_DISCOVERY) || defined(STM32F7_NUCLEO) #if defined(STM32F4_DISCOVERY) || defined(STM32F7_NUCLEO)
WriteUSART3(data, length); m_USART3.write(data, length); //WriteUSART3(data, length);
if (flush) if (flush)
TXSerialFlush3(); m_USART3.flush();//TXSerialFlush3();
#elif defined(STM32F4_PI) || defined(STM32F4_F4M) || defined(STM32F722_PI) || defined(STM32F722_F7M) || defined(STM32F722_RPT_HAT) || defined(STM32F4_DVM) #elif defined(STM32F4_PI) || defined(STM32F4_F4M) || defined(STM32F722_PI) || defined(STM32F722_F7M) || defined(STM32F722_RPT_HAT) || defined(STM32F4_DVM)
WriteUSART1(data, length); m_USART1.write(data, length);//WriteUSART1(data, length);
if (flush) if (flush)
TXSerialFlush1(); m_USART1.flush();//TXSerialFlush1();
#elif defined(STM32F4_NUCLEO) || defined(STM32F4_RPT_HAT_TGO) #elif defined(STM32F4_NUCLEO) || defined(STM32F4_RPT_HAT_TGO)
WriteUSART2(data, length); m_USART2.write(data, length);//WriteUSART2(data, length);
if (flush) if (flush)
TXSerialFlush2(); m_USART2.flush();//TXSerialFlush2();
#elif defined(DRCC_DVM)
m_USART1.write(data, length);//WriteUSART1(data, length);
if (flush)
m_USART1.flush();//TXSerialFlush1();
#endif #endif
break; break;
case 3U: case 3U:
#if defined(STM32F4_NUCLEO) && defined(STM32F4_NUCLEO_ARDUINO_HEADER) #if defined(STM32F4_NUCLEO) && defined(STM32F4_NUCLEO_ARDUINO_HEADER)
WriteUSART1(data, length); m_USART1.write(data, length); //WriteUSART1(data, length);
if (flush) if (flush)
TXSerialFlush1(); m_USART1.flush();
#elif defined(DRCC_DVM)
m_USART2.write(data, length);//WriteUSART2(data, length);
if (flush)
m_USART2.flush();//TXSerialFlush2();
#else #else
WriteUART5(data, length); m_UART5.write(data, length);//WriteUART5(data, length);
if (flush) if (flush)
TXSerialFlush5(); m_UART5.flush();//TXSerialFlush5();
#endif #endif
break; break;
default: default:
+8 -8
View File
@@ -17,30 +17,30 @@ f2 = 2700
rp = 0.2 rp = 0.2
# scaling factor in bits, do not change ! # scaling factor in bits, do not change !
q = 0 q = 15
# scaling factor as facor... # scaling factor as facor...
scaling_factor = 2**q scaling_factor = 2**q
# let's generate a sequence of 2nd order IIR filters # let's generate a sequence of 2nd order IIR filters
sos = signal.cheby1(3,rp,[f1, f2],'bandpass', output='sos', fs=fs) sos = signal.cheby1(3,rp,[f1, f2],'bandpass', output='sos', fs=fs)
#sos = signal.cheby1(1, rp, 2122, 'lowpass', output='sos', fs=fs) #deemphasis filter #os = signal.cheby1(4, rp, f2, 'lowpass', output='sos', fs=fs) #deemphasis filter
#sos = signal.cheby1(1, rp, 2122, 'highpass', output='sos', fs=fs) #deemphasis filter #sos = signal.cheby1(1, rp, 2122, 'highpass', output='sos', fs=fs) #deemphasis filter
#sos = np.round((sos) * scaling_factor) sosrounded = np.round((sos) * scaling_factor)
# print coefficients # print coefficients
for biquad in sos: for biquad in sosrounded:
for coeff in biquad: for coeff in biquad:
#print(int(coeff),",",sep="",end="") print(int(coeff),",",sep="",end="")
print((coeff),",",sep="",end="") #print((coeff),",",sep="",end="")
print("") print("")
# plot the frequency response # plot the frequency response
b,a = signal.sos2tf(sos) b,a = signal.sos2tf(sos)
w,h = signal.freqz(b,a) w,h = signal.freqz(b,a, worN=2048)
pl.plot(w/np.pi/2*fs,20*np.log(np.abs(h))) pl.plot(w/np.pi/2*fs,20*np.log(np.abs(h)))
pl.xlabel('frequency/Hz'); pl.xlabel('frequency/Hz');
pl.ylabel('gain/dB'); pl.ylabel('gain/dB');
pl.ylim(top=1,bottom=-20); pl.ylim(top=1,bottom=-30);
pl.xlim(left=250, right=12000); pl.xlim(left=250, right=12000);
pl.show() pl.show()
+2 -5
View File
@@ -66,9 +66,6 @@ m_txCount(0U)
void CYSFTX::process() void CYSFTX::process()
{ {
if (m_buffer.getData() == 0U && m_poLen == 0U && m_txCount == 0U)
return;
// If we have YSF data to transmit, do so. // If we have YSF data to transmit, do so.
if (m_poLen == 0U && m_buffer.getData() > 0U) { if (m_poLen == 0U && m_buffer.getData() > 0U) {
if (!m_tx) { if (!m_tx) {
@@ -76,7 +73,8 @@ void CYSFTX::process()
m_poBuffer[m_poLen++] = YSF_START_SYNC; m_poBuffer[m_poLen++] = YSF_START_SYNC;
} else { } else {
for (uint8_t i = 0U; i < YSF_FRAME_LENGTH_BYTES; i++) { for (uint8_t i = 0U; i < YSF_FRAME_LENGTH_BYTES; i++) {
uint8_t c = m_buffer.get(); uint8_t c = 0U;
m_buffer.get(c);
m_poBuffer[m_poLen++] = c; m_poBuffer[m_poLen++] = c;
} }
} }
@@ -191,4 +189,3 @@ void CYSFTX::setParams(bool on, uint8_t txHang)
m_loDev = on; m_loDev = on;
m_txHang = txHang * 1200U; m_txHang = txHang * 1200U;
} }
+2 -2
View File
@@ -21,7 +21,7 @@
#include "Config.h" #include "Config.h"
#include "SerialRB.h" #include "RingBuffer.h"
class CYSFTX { class CYSFTX {
public: public:
@@ -38,7 +38,7 @@ public:
void setParams(bool on, uint8_t txHang); void setParams(bool on, uint8_t txHang);
private: private:
CSerialRB m_buffer; CRingBuffer<uint8_t> m_buffer;
arm_fir_interpolate_instance_q15 m_modFilter; arm_fir_interpolate_instance_q15 m_modFilter;
q15_t m_modState[16U]; // blockSize + phaseLength - 1, 4 + 9 - 1 plus some spare q15_t m_modState[16U]; // blockSize + phaseLength - 1, 4 + 9 - 1 plus some spare
uint8_t m_poBuffer[1200U]; uint8_t m_poBuffer[1200U];
+96
View File
@@ -0,0 +1,96 @@
/*
* Copyright (C) 2019,2020 by BG5HHP
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifndef _PINS_F4_DISCOVERY_H
#define _PINS_F4_DISCOVERY_H
/*
Pin definitions for STM32F4 Discovery Board:
PTT PB13 output P1 Pin37
COSLED PA7 output P1 Pin17
LED PD15 output P1 Pin47
COS PA5 input P1 Pin15
DSTAR PD12 output P1 Pin44
DMR PD13 output P1 Pin45
YSF PD14 output P1 Pin46
P25 PD11 output P1 Pin43
NXDN PD10 output P1 Pin42
RX PA0 analog input P1 Pin12
RSSI PA1 analog input P1 Pin11
TX PA4 analog output P1 Pin16
EXT_CLK PA15 input P2 Pin40
*/
#define PIN_COS GPIO_Pin_5
#define PORT_COS GPIOA
#define RCC_Per_COS RCC_AHB1Periph_GPIOA
#define PIN_PTT GPIO_Pin_13
#define PORT_PTT GPIOB
#define RCC_Per_PTT RCC_AHB1Periph_GPIOB
#define PIN_COSLED GPIO_Pin_7
#define PORT_COSLED GPIOA
#define RCC_Per_COSLED RCC_AHB1Periph_GPIOA
#define PIN_LED GPIO_Pin_15
#define PORT_LED GPIOD
#define RCC_Per_LED RCC_AHB1Periph_GPIOD
#define PIN_P25 GPIO_Pin_11
#define PORT_P25 GPIOD
#define RCC_Per_P25 RCC_AHB1Periph_GPIOD
#define PIN_NXDN GPIO_Pin_10
#define PORT_NXDN GPIOD
#define RCC_Per_NXDN RCC_AHB1Periph_GPIOD
#define PIN_DSTAR GPIO_Pin_12
#define PORT_DSTAR GPIOD
#define RCC_Per_DSTAR RCC_AHB1Periph_GPIOD
#define PIN_DMR GPIO_Pin_13
#define PORT_DMR GPIOD
#define RCC_Per_DMR RCC_AHB1Periph_GPIOD
#define PIN_YSF GPIO_Pin_14
#define PORT_YSF GPIOD
#define RCC_Per_YSF RCC_AHB1Periph_GPIOD
#define PIN_EXT_CLK GPIO_Pin_15
#define SRC_EXT_CLK GPIO_PinSource15
#define PORT_EXT_CLK GPIOA
#define PIN_RX GPIO_Pin_0
#define PIN_RX_CH ADC_Channel_0
#define PORT_RX GPIOA
#define RCC_Per_RX RCC_AHB1Periph_GPIOA
#define PIN_RSSI GPIO_Pin_1
#define PIN_RSSI_CH ADC_Channel_1
#define PORT_RSSI GPIOA
#define RCC_Per_RSSI RCC_AHB1Periph_GPIOA
#define PIN_TX GPIO_Pin_4
#define PIN_TX_CH DAC_Channel_1
#endif
+140
View File
@@ -0,0 +1,140 @@
/*
* Copyright (C) 2019,2020 by BG5HHP
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifndef _PINS_F4_DRCC_NQF_H
#define _PINS_F4_DRCC_NQF_H
/*
Pin definitions for DRCC_DVM BG7NQF board rev1
PTT PB12 output
LED_PTT PB4 output
LED_COS PB5 output
LED_SRV PB10 output
COS PB13 input
DSTAR N/A
DMR N/A
YSF N/A
P25 N/A
NXDN N/A
POCSAG N/A
MDSTAR PB14 output
MDMR PB8 output
MYSF PB9 output
MP25 PB15 output
MNXDN N/A
MPOCSAG N/A
RX PB0 analog input
RSSI PB1 analog input
TX PA4 analog output
EXT_CLK PA15 input
UART1_TX PA9 output
UART1_RX PA10 output
UART2_TX PA2 output
UART2_RX PA3 output
*/
#define PIN_COS GPIO_Pin_13
#define PORT_COS GPIOB
#define RCC_Per_COS RCC_AHB1Periph_GPIOB
#define PIN_PTT GPIO_Pin_12
#define PORT_PTT GPIOB
#define RCC_Per_PTT RCC_AHB1Periph_GPIOB
#define PIN_COSLED GPIO_Pin_5
#define PORT_COSLED GPIOB
#define RCC_Per_COSLED RCC_AHB1Periph_GPIOB
#define PIN_LED GPIO_Pin_10
#define PORT_LED GPIOB
#define RCC_Per_LED RCC_AHB1Periph_GPIOB
#define PIN_TXLED GPIO_Pin_4
#define PORT_TXLED GPIOB
#define RCC_Per_TXLED RCC_AHB1Periph_GPIOB
// #define PIN_P25 GPIO_Pin_3
// #define PORT_P25 GPIOB
// #define RCC_Per_P25 RCC_AHB1Periph_GPIOB
// #define PIN_NXDN GPIO_Pin_10
// #define PORT_NXDN GPIOA
// #define RCC_Per_NXDN RCC_AHB1Periph_GPIOA
// #define PIN_POCSAG GPIO_Pin_12
// #define PORT_POCSAG GPIOB
// #define RCC_Per_POCSAG RCC_AHB1Periph_GPIOB
// #define PIN_DSTAR GPIO_Pin_10
// #define PORT_DSTAR GPIOB
// #define RCC_Per_DSTAR RCC_AHB1Periph_GPIOB
// #define PIN_DMR GPIO_Pin_4
// #define PORT_DMR GPIOB
// #define RCC_Per_DMR RCC_AHB1Periph_GPIOB
// #define PIN_YSF GPIO_Pin_5
// #define PORT_YSF GPIOB
// #define RCC_Per_YSF RCC_AHB1Periph_GPIOB
#if defined(MODE_PINS)
#define PIN_MP25 GPIO_Pin_15
#define PORT_MP25 GPIOB
#define RCC_Per_MP25 RCC_AHB1Periph_GPIOB
#define PIN_MDSTAR GPIO_Pin_9
#define PORT_MDSTAR GPIOB
#define RCC_Per_MDSTAR RCC_AHB1Periph_GPIOB
#define PIN_MDMR GPIO_Pin_8
#define PORT_MDMR GPIOB
#define RCC_Per_MDMR RCC_AHB1Periph_GPIOB
#define PIN_MYSF GPIO_Pin_14
#define PORT_MYSF GPIOB
#define RCC_Per_MYSF RCC_AHB1Periph_GPIOB
#endif
#define PIN_EXT_CLK GPIO_Pin_15
#define SRC_EXT_CLK GPIO_PinSource15
#define PORT_EXT_CLK GPIOA
#define PIN_RX GPIO_Pin_0
#define PIN_RX_CH ADC_Channel_0
#define PORT_RX GPIOB
#define RCC_Per_RX RCC_AHB1Periph_GPIOB
#define PIN_RSSI GPIO_Pin_1
#define PIN_RSSI_CH ADC_Channel_1
#define PORT_RSSI GPIOB
#define RCC_Per_RSSI RCC_AHB1Periph_GPIOB
#define PIN_TX GPIO_Pin_4
#define PIN_TX_CH DAC_Channel_1
#define PORT_TX GPIOA
#define RCC_Per_TX RCC_AHB1Periph_GPIOA
#endif
+101
View File
@@ -0,0 +1,101 @@
/*
* Copyright (C) 2019,2020 by BG5HHP
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifndef _PINS_F4_F4M_H
#define _PINS_F4_F4M_H
/*
Pin definitions for MMDVM-F4M Pi-Hat F0DEI board:
PTT PB13 output
COSLED PB14 output
LED PB15 output
COS PC0 input
DSTAR PC7 output
DMR PC8 output
YSF PA8 output
P25 PC9 output
NXDN PB1 output
POCSAG PB12 output
RX PA0 analog input
RSSI PA7 analog input
TX PA4 analog output
EXT_CLK PA15 input
*/
#define PIN_COS GPIO_Pin_0
#define PORT_COS GPIOC
#define RCC_Per_COS RCC_AHB1Periph_GPIOC
#define PIN_PTT GPIO_Pin_13
#define PORT_PTT GPIOB
#define RCC_Per_PTT RCC_AHB1Periph_GPIOB
#define PIN_COSLED GPIO_Pin_14
#define PORT_COSLED GPIOB
#define RCC_Per_COSLED RCC_AHB1Periph_GPIOB
#define PIN_LED GPIO_Pin_15
#define PORT_LED GPIOB
#define RCC_Per_LED RCC_AHB1Periph_GPIOB
#define PIN_P25 GPIO_Pin_9
#define PORT_P25 GPIOC
#define RCC_Per_P25 RCC_AHB1Periph_GPIOC
#define PIN_NXDN GPIO_Pin_1
#define PORT_NXDN GPIOB
#define RCC_Per_NXDN RCC_AHB1Periph_GPIOB
#define PIN_POCSAG GPIO_Pin_12
#define PORT_POCSAG GPIOB
#define RCC_Per_POCSAG RCC_AHB1Periph_GPIOB
#define PIN_DSTAR GPIO_Pin_7
#define PORT_DSTAR GPIOC
#define RCC_Per_DSTAR RCC_AHB1Periph_GPIOC
#define PIN_DMR GPIO_Pin_8
#define PORT_DMR GPIOC
#define RCC_Per_DMR RCC_AHB1Periph_GPIOC
#define PIN_YSF GPIO_Pin_8
#define PORT_YSF GPIOA
#define RCC_Per_YSF RCC_AHB1Periph_GPIOA
#define PIN_EXT_CLK GPIO_Pin_15
#define SRC_EXT_CLK GPIO_PinSource15
#define PORT_EXT_CLK GPIOA
#define PIN_RX GPIO_Pin_0
#define PIN_RX_CH ADC_Channel_0
#define PORT_RX GPIOA
#define RCC_Per_RX RCC_AHB1Periph_GPIOA
#define PIN_RSSI GPIO_Pin_7
#define PIN_RSSI_CH ADC_Channel_7
#define PORT_RSSI GPIOA
#define RCC_Per_RSSI RCC_AHB1Periph_GPIOA
#define PIN_TX GPIO_Pin_4
#define PIN_TX_CH DAC_Channel_1
#endif
+101
View File
@@ -0,0 +1,101 @@
/*
* Copyright (C) 2019,2020 by BG5HHP
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifndef _PINS_F4_NUCLEO_ARDUINO_H
#define _PINS_F4_NUCLEO_ARDUINO_H
/*
Pin definitions for STM32F4 Nucleo boards (Arduino header):
PTT PB10 output CN9 Pin7
COSLED PB3 output CN9 Pin4
LED PB5 output CN9 Pin5
COS PB4 input CN9 Pin6
DSTAR PA1 output CN8 Pin2
DMR PA4 output CN8 Pin3
YSF PB0 output CN8 Pin4
P25 PC1 output CN8 Pin5
NXDN PA3 output CN9 Pin1
POCSAG PB12 output
RX PA0 analog input CN8 Pin1
RSSI PC0 analog input CN8 Pin6
TX PA5 analog output CN5 Pin6
EXT_CLK PB8 input CN5 Pin10
*/
#define PIN_COS GPIO_Pin_4
#define PORT_COS GPIOB
#define RCC_Per_COS RCC_AHB1Periph_GPIOB
#define PIN_PTT GPIO_Pin_10
#define PORT_PTT GPIOB
#define RCC_Per_PTT RCC_AHB1Periph_GPIOB
#define PIN_COSLED GPIO_Pin_3
#define PORT_COSLED GPIOB
#define RCC_Per_COSLED RCC_AHB1Periph_GPIOB
#define PIN_LED GPIO_Pin_5
#define PORT_LED GPIOB
#define RCC_Per_LED RCC_AHB1Periph_GPIOB
#define PIN_P25 GPIO_Pin_1
#define PORT_P25 GPIOC
#define RCC_Per_P25 RCC_AHB1Periph_GPIOC
#define PIN_NXDN GPIO_Pin_3
#define PORT_NXDN GPIOA
#define RCC_Per_NXDN RCC_AHB1Periph_GPIOA
#define PIN_POCSAG GPIO_Pin_12
#define PORT_POCSAG GPIOB
#define RCC_Per_POCSAG RCC_AHB1Periph_GPIOB
#define PIN_DSTAR GPIO_Pin_1
#define PORT_DSTAR GPIOA
#define RCC_Per_DSTAR RCC_AHB1Periph_GPIOA
#define PIN_DMR GPIO_Pin_4
#define PORT_DMR GPIOA
#define RCC_Per_DMR RCC_AHB1Periph_GPIOA
#define PIN_YSF GPIO_Pin_0
#define PORT_YSF GPIOB
#define RCC_Per_YSF RCC_AHB1Periph_GPIOB
#define PIN_EXT_CLK GPIO_Pin_8
#define SRC_EXT_CLK GPIO_PinSource8
#define PORT_EXT_CLK GPIOB
#define PIN_RX GPIO_Pin_0
#define PIN_RX_CH ADC_Channel_0
#define PORT_RX GPIOA
#define RCC_Per_RX RCC_AHB1Periph_GPIOA
#define PIN_RSSI GPIO_Pin_0
#define PIN_RSSI_CH ADC_Channel_10
#define PORT_RSSI GPIOC
#define RCC_Per_RSSI RCC_AHB1Periph_GPIOC
#define PIN_TX GPIO_Pin_5
#define PIN_TX_CH DAC_Channel_2
#endif
+134
View File
@@ -0,0 +1,134 @@
/*
* Copyright (C) 2019,2020 by BG5HHP
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifndef _PINS_F4_NUCLEO_MORPHO_H
#define _PINS_F4_NUCLEO_MORPHO_H
/*
Pin definitions for STM32F4 Nucleo boards (ST Morpho header):
PTT PB13 output CN10 Pin30
COSLED PB14 output CN10 Pin28
LED PA5 output CN10 Pin11
COS PB15 input CN10 Pin26
DSTAR PB10 output CN10 Pin25
DMR PB4 output CN10 Pin27
YSF PB5 output CN10 Pin29
P25 PB3 output CN10 Pin31
NXDN PA10 output CN10 Pin33
POCSAG PB12 output CN10 Pin16
MDSTAR PC4 output CN10 Pin34
MDMR PC5 output CN10 Pin6
MYSF PC2 output CN7 Pin35
MP25 PC3 output CN7 Pin37
MNXDN PC6 output CN10 Pin4
MPOCSAG PC8 output CN10 Pin2
RX PA0 analog input CN7 Pin28
RSSI PA1 analog input CN7 Pin30
TX PA4 analog output CN7 Pin32
EXT_CLK PA15 input CN7 Pin17
*/
#define PIN_COS GPIO_Pin_15
#define PORT_COS GPIOB
#define RCC_Per_COS RCC_AHB1Periph_GPIOB
#define PIN_PTT GPIO_Pin_13
#define PORT_PTT GPIOB
#define RCC_Per_PTT RCC_AHB1Periph_GPIOB
#define PIN_COSLED GPIO_Pin_14
#define PORT_COSLED GPIOB
#define RCC_Per_COSLED RCC_AHB1Periph_GPIOB
#define PIN_LED GPIO_Pin_5
#define PORT_LED GPIOA
#define RCC_Per_LED RCC_AHB1Periph_GPIOA
#define PIN_P25 GPIO_Pin_3
#define PORT_P25 GPIOB
#define RCC_Per_P25 RCC_AHB1Periph_GPIOB
#define PIN_NXDN GPIO_Pin_10
#define PORT_NXDN GPIOA
#define RCC_Per_NXDN RCC_AHB1Periph_GPIOA
#define PIN_POCSAG GPIO_Pin_12
#define PORT_POCSAG GPIOB
#define RCC_Per_POCSAG RCC_AHB1Periph_GPIOB
#define PIN_DSTAR GPIO_Pin_10
#define PORT_DSTAR GPIOB
#define RCC_Per_DSTAR RCC_AHB1Periph_GPIOB
#define PIN_DMR GPIO_Pin_4
#define PORT_DMR GPIOB
#define RCC_Per_DMR RCC_AHB1Periph_GPIOB
#define PIN_YSF GPIO_Pin_5
#define PORT_YSF GPIOB
#define RCC_Per_YSF RCC_AHB1Periph_GPIOB
#if defined(MODE_PINS)
#define PIN_MP25 GPIO_Pin_3
#define PORT_MP25 GPIOC
#define RCC_Per_MP25 RCC_AHB1Periph_GPIOC
#define PIN_MNXDN GPIO_Pin_6
#define PORT_MNXDN GPIOC
#define RCC_Per_MNXDN RCC_AHB1Periph_GPIOC
#define PIN_MDSTAR GPIO_Pin_4
#define PORT_MDSTAR GPIOC
#define RCC_Per_MDSTAR RCC_AHB1Periph_GPIOC
#define PIN_MDMR GPIO_Pin_5
#define PORT_MDMR GPIOC
#define RCC_Per_MDMR RCC_AHB1Periph_GPIOC
#define PIN_MYSF GPIO_Pin_2
#define PORT_MYSF GPIOC
#define RCC_Per_MYSF RCC_AHB1Periph_GPIOC
#define PIN_MPOCSAG GPIO_Pin_8
#define PORT_MPOCSAG GPIOC
#define RCC_Per_MPOCSAG RCC_AHB1Periph_GPIOC
#endif
#define PIN_EXT_CLK GPIO_Pin_15
#define SRC_EXT_CLK GPIO_PinSource15
#define PORT_EXT_CLK GPIOA
#define PIN_RX GPIO_Pin_0
#define PIN_RX_CH ADC_Channel_0
#define PORT_RX GPIOA
#define RCC_Per_RX RCC_AHB1Periph_GPIOA
#define PIN_RSSI GPIO_Pin_1
#define PIN_RSSI_CH ADC_Channel_1
#define PORT_RSSI GPIOA
#define RCC_Per_RSSI RCC_AHB1Periph_GPIOA
#define PIN_TX GPIO_Pin_4
#define PIN_TX_CH DAC_Channel_1
#endif
+101
View File
@@ -0,0 +1,101 @@
/*
* Copyright (C) 2019,2020 by BG5HHP
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifndef _PINS_F4_PI_H
#define _PINS_F4_PI_H
/*
Pin definitions for STM32F4 Pi Board:
PTT PB13 output
COSLED PB14 output
LED PB15 output
COS PC0 input
DSTAR PC7 output
DMR PC8 output
YSF PA8 output
P25 PC9 output
NXDN PB1 output
POCSAG PB12 output
RX PA0 analog input
RSSI PA7 analog input
TX PA4 analog output
EXT_CLK PA15 input
*/
#define PIN_COS GPIO_Pin_0
#define PORT_COS GPIOC
#define RCC_Per_COS RCC_AHB1Periph_GPIOC
#define PIN_PTT GPIO_Pin_13
#define PORT_PTT GPIOB
#define RCC_Per_PTT RCC_AHB1Periph_GPIOB
#define PIN_COSLED GPIO_Pin_14
#define PORT_COSLED GPIOB
#define RCC_Per_COSLED RCC_AHB1Periph_GPIOB
#define PIN_LED GPIO_Pin_15
#define PORT_LED GPIOB
#define RCC_Per_LED RCC_AHB1Periph_GPIOB
#define PIN_P25 GPIO_Pin_9
#define PORT_P25 GPIOC
#define RCC_Per_P25 RCC_AHB1Periph_GPIOC
#define PIN_NXDN GPIO_Pin_1
#define PORT_NXDN GPIOB
#define RCC_Per_NXDN RCC_AHB1Periph_GPIOB
#define PIN_POCSAG GPIO_Pin_12
#define PORT_POCSAG GPIOB
#define RCC_Per_POCSAG RCC_AHB1Periph_GPIOB
#define PIN_DSTAR GPIO_Pin_7
#define PORT_DSTAR GPIOC
#define RCC_Per_DSTAR RCC_AHB1Periph_GPIOC
#define PIN_DMR GPIO_Pin_8
#define PORT_DMR GPIOC
#define RCC_Per_DMR RCC_AHB1Periph_GPIOC
#define PIN_YSF GPIO_Pin_8
#define PORT_YSF GPIOA
#define RCC_Per_YSF RCC_AHB1Periph_GPIOA
#define PIN_EXT_CLK GPIO_Pin_15
#define SRC_EXT_CLK GPIO_PinSource15
#define PORT_EXT_CLK GPIOA
#define PIN_RX GPIO_Pin_0
#define PIN_RX_CH ADC_Channel_0
#define PORT_RX GPIOA
#define RCC_Per_RX RCC_AHB1Periph_GPIOA
#define PIN_RSSI GPIO_Pin_7
#define PIN_RSSI_CH ADC_Channel_7
#define PORT_RSSI GPIOA
#define RCC_Per_RSSI RCC_AHB1Periph_GPIOA
#define PIN_TX GPIO_Pin_4
#define PIN_TX_CH DAC_Channel_1
#endif
+134
View File
@@ -0,0 +1,134 @@
/*
* Copyright (C) 2019,2020 by BG5HHP
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifndef _PINS_F4_RPT_TGO_H
#define _PINS_F4_RPT_TGO_H
/*
Pin definitions for MMDVM_RPT_Hat Pi-Hat BG4TGO board::
PTT PB13 output CN10 Pin30
COSLED PB14 output CN10 Pin28
LED PA5 output CN10 Pin11
COS PB15 input CN10 Pin26
DSTAR PB10 output CN10 Pin25
DMR PB4 output CN10 Pin27
YSF PB5 output CN10 Pin29
P25 PB3 output CN10 Pin31
NXDN PA10 output CN10 Pin33
POCSAG PB12 output CN10 Pin16
MDSTAR PC4 output CN10 Pin34
MDMR PC5 output CN10 Pin6
MYSF PC2 output CN7 Pin35
MP25 PC3 output CN7 Pin37
MNXDN PC6 output CN10 Pin4
MPOCSAG PC8 output CN10 Pin2
RX PA0 analog input CN7 Pin28
RSSI PA1 analog input CN7 Pin30
TX PA4 analog output CN7 Pin32
EXT_CLK PA15 input CN7 Pin17
*/
#define PIN_COS GPIO_Pin_15
#define PORT_COS GPIOB
#define RCC_Per_COS RCC_AHB1Periph_GPIOB
#define PIN_PTT GPIO_Pin_13
#define PORT_PTT GPIOB
#define RCC_Per_PTT RCC_AHB1Periph_GPIOB
#define PIN_COSLED GPIO_Pin_14
#define PORT_COSLED GPIOB
#define RCC_Per_COSLED RCC_AHB1Periph_GPIOB
#define PIN_LED GPIO_Pin_5
#define PORT_LED GPIOA
#define RCC_Per_LED RCC_AHB1Periph_GPIOA
#define PIN_P25 GPIO_Pin_3
#define PORT_P25 GPIOB
#define RCC_Per_P25 RCC_AHB1Periph_GPIOB
#define PIN_NXDN GPIO_Pin_10
#define PORT_NXDN GPIOA
#define RCC_Per_NXDN RCC_AHB1Periph_GPIOA
#define PIN_POCSAG GPIO_Pin_12
#define PORT_POCSAG GPIOB
#define RCC_Per_POCSAG RCC_AHB1Periph_GPIOB
#define PIN_DSTAR GPIO_Pin_10
#define PORT_DSTAR GPIOB
#define RCC_Per_DSTAR RCC_AHB1Periph_GPIOB
#define PIN_DMR GPIO_Pin_4
#define PORT_DMR GPIOB
#define RCC_Per_DMR RCC_AHB1Periph_GPIOB
#define PIN_YSF GPIO_Pin_5
#define PORT_YSF GPIOB
#define RCC_Per_YSF RCC_AHB1Periph_GPIOB
#if defined(MODE_PINS)
#define PIN_MP25 GPIO_Pin_3
#define PORT_MP25 GPIOC
#define RCC_Per_MP25 RCC_AHB1Periph_GPIOC
#define PIN_MNXDN GPIO_Pin_6
#define PORT_MNXDN GPIOC
#define RCC_Per_MNXDN RCC_AHB1Periph_GPIOC
#define PIN_MDSTAR GPIO_Pin_4
#define PORT_MDSTAR GPIOC
#define RCC_Per_MDSTAR RCC_AHB1Periph_GPIOC
#define PIN_MDMR GPIO_Pin_5
#define PORT_MDMR GPIOC
#define RCC_Per_MDMR RCC_AHB1Periph_GPIOC
#define PIN_MYSF GPIO_Pin_2
#define PORT_MYSF GPIOC
#define RCC_Per_MYSF RCC_AHB1Periph_GPIOC
#define PIN_MPOCSAG GPIO_Pin_8
#define PORT_MPOCSAG GPIOC
#define RCC_Per_MPOCSAG RCC_AHB1Periph_GPIOC
#endif
#define PIN_EXT_CLK GPIO_Pin_15
#define SRC_EXT_CLK GPIO_PinSource15
#define PORT_EXT_CLK GPIOA
#define PIN_RX GPIO_Pin_0
#define PIN_RX_CH ADC_Channel_0
#define PORT_RX GPIOA
#define RCC_Per_RX RCC_AHB1Periph_GPIOA
#define PIN_RSSI GPIO_Pin_1
#define PIN_RSSI_CH ADC_Channel_1
#define PORT_RSSI GPIOA
#define RCC_Per_RSSI RCC_AHB1Periph_GPIOA
#define PIN_TX GPIO_Pin_4
#define PIN_TX_CH DAC_Channel_1
#endif
+102
View File
@@ -0,0 +1,102 @@
/*
* Copyright (C) 2019,2020 by BG5HHP
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifndef _PINS_F4_STM32DVM_V3_H
#define _PINS_F4_STM32DVM_V3_H
/*
Pin definitions for STM32F4 STM32-DVM rev 3 Board:
COS PB13 input
PTT PB12 output
COSLED PB4 output
LED PB3 output
P25 PB8 output
NXDN PB9 output
DSTAR PB6 output
DMR PB5 output
YSF PB7 output
POCSAG PC10 output
RX PB0 analog input
RSSI PB1 analog input
TX PA4 analog output
EXT_CLK PA15 input
*/
#define PIN_COS GPIO_Pin_13
#define PORT_COS GPIOB
#define RCC_Per_COS RCC_AHB1Periph_GPIOB
#define PIN_PTT GPIO_Pin_12
#define PORT_PTT GPIOB
#define RCC_Per_PTT RCC_AHB1Periph_GPIOB
#define PIN_COSLED GPIO_Pin_4
#define PORT_COSLED GPIOB
#define RCC_Per_COSLED RCC_AHB1Periph_GPIOB
#define PIN_LED GPIO_Pin_3
#define PORT_LED GPIOB
#define RCC_Per_LED RCC_AHB1Periph_GPIOB
#define PIN_P25 GPIO_Pin_8
#define PORT_P25 GPIOB
#define RCC_Per_P25 RCC_AHB1Periph_GPIOB
#define PIN_NXDN GPIO_Pin_9
#define PORT_NXDN GPIOB
#define RCC_Per_NXDN RCC_AHB1Periph_GPIOB
#define PIN_DSTAR GPIO_Pin_6
#define PORT_DSTAR GPIOB
#define RCC_Per_DSTAR RCC_AHB1Periph_GPIOB
#define PIN_DMR GPIO_Pin_5
#define PORT_DMR GPIOB
#define RCC_Per_DMR RCC_AHB1Periph_GPIOB
#define PIN_YSF GPIO_Pin_7
#define PORT_YSF GPIOB
#define RCC_Per_YSF RCC_AHB1Periph_GPIOB
#define PIN_POCSAG GPIO_Pin_10
#define PORT_POCSAG GPIOC
#define RCC_Per_POCSAG RCC_AHB1Periph_GPIOC
#define PIN_EXT_CLK GPIO_Pin_15
#define SRC_EXT_CLK GPIO_PinSource15
#define PORT_EXT_CLK GPIOA
#define PIN_RX GPIO_Pin_0
#define PIN_RX_CH ADC_Channel_8
#define PORT_RX GPIOB
#define RCC_Per_RX RCC_AHB1Periph_GPIOB
#define PIN_RSSI GPIO_Pin_1
#define PIN_RSSI_CH ADC_Channel_9
#define PORT_RSSI GPIOB
#define RCC_Per_RSSI RCC_AHB1Periph_GPIOB
#define PIN_TX GPIO_Pin_4
#define PIN_TX_CH DAC_Channel_1
#endif
+101
View File
@@ -0,0 +1,101 @@
/*
* Copyright (C) 2019,2020 by BG5HHP
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifndef _PINS_F7_F7M_H
#define _PINS_F7_F7M_H
/*
Pin definitions for MMDVM-F7M Pi-Hat F0DEI board:
PTT PB13 output
COSLED PB14 output
LED PB15 output
COS PC0 input
DSTAR PC7 output
DMR PC8 output
YSF PA8 output
P25 PC9 output
NXDN PB1 output
POCSAG PB12 output
RX PA0 analog input
RSSI PA7 analog input
TX PA4 analog output
EXT_CLK PA15 input
*/
#define PIN_COS GPIO_Pin_0
#define PORT_COS GPIOC
#define RCC_Per_COS RCC_AHB1Periph_GPIOC
#define PIN_PTT GPIO_Pin_13
#define PORT_PTT GPIOB
#define RCC_Per_PTT RCC_AHB1Periph_GPIOB
#define PIN_COSLED GPIO_Pin_14
#define PORT_COSLED GPIOB
#define RCC_Per_COSLED RCC_AHB1Periph_GPIOB
#define PIN_LED GPIO_Pin_15
#define PORT_LED GPIOB
#define RCC_Per_LED RCC_AHB1Periph_GPIOB
#define PIN_P25 GPIO_Pin_9
#define PORT_P25 GPIOC
#define RCC_Per_P25 RCC_AHB1Periph_GPIOC
#define PIN_NXDN GPIO_Pin_1
#define PORT_NXDN GPIOB
#define RCC_Per_NXDN RCC_AHB1Periph_GPIOB
#define PIN_POCSAG GPIO_Pin_12
#define PORT_POCSAG GPIOB
#define RCC_Per_POCSAG RCC_AHB1Periph_GPIOB
#define PIN_DSTAR GPIO_Pin_7
#define PORT_DSTAR GPIOC
#define RCC_Per_DSTAR RCC_AHB1Periph_GPIOC
#define PIN_DMR GPIO_Pin_8
#define PORT_DMR GPIOC
#define RCC_Per_DMR RCC_AHB1Periph_GPIOC
#define PIN_YSF GPIO_Pin_8
#define PORT_YSF GPIOA
#define RCC_Per_YSF RCC_AHB1Periph_GPIOA
#define PIN_EXT_CLK GPIO_Pin_15
#define SRC_EXT_CLK GPIO_PinSource15
#define PORT_EXT_CLK GPIOA
#define PIN_RX GPIO_Pin_0
#define PIN_RX_CH ADC_Channel_0
#define PORT_RX GPIOA
#define RCC_Per_RX RCC_AHB1Periph_GPIOA
#define PIN_RSSI GPIO_Pin_7
#define PIN_RSSI_CH ADC_Channel_7
#define PORT_RSSI GPIOA
#define RCC_Per_RSSI RCC_AHB1Periph_GPIOA
#define PIN_TX GPIO_Pin_4
#define PIN_TX_CH DAC_Channel_1
#endif
+129
View File
@@ -0,0 +1,129 @@
/*
* Copyright (C) 2019,2020 by BG5HHP
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifndef _PINS_F7_NUCLEO_H
#define _PINS_F7_NUCLEO_H
/*
Pin definitions for STM32F7 Nucleo boards (ST Morpho header):
PTT PB13 output CN12 Pin30
COSLED PB14 output CN12 Pin28
LED PA5 output CN12 Pin11
COS PB15 input CN12 Pin26
DSTAR PB10 output CN12 Pin25
DMR PB4 output CN12 Pin27
YSF PB5 output CN12 Pin29
P25 PB3 output CN12 Pin31
NXDN PA10 output CN12 Pin33
POCSAG PB12 output CN12 Pin16
MDSTAR PC4 output CN12 Pin34
MDMR PC5 output CN12 Pin6
MYSF PC2 output CN11 Pin35
MP25 PC3 output CN11 Pin37
MNXDN PC6 output CN12 Pin4
RX PA0 analog input CN11 Pin28
RSSI PA1 analog input CN11 Pin30
TX PA4 analog output CN11 Pin32
EXT_CLK PA15 input CN11 Pin17
*/
#define PIN_COS GPIO_Pin_15
#define PORT_COS GPIOB
#define RCC_Per_COS RCC_AHB1Periph_GPIOB
#define PIN_PTT GPIO_Pin_13
#define PORT_PTT GPIOB
#define RCC_Per_PTT RCC_AHB1Periph_GPIOB
#define PIN_COSLED GPIO_Pin_14
#define PORT_COSLED GPIOB
#define RCC_Per_COSLED RCC_AHB1Periph_GPIOB
#define PIN_LED GPIO_Pin_5
#define PORT_LED GPIOA
#define RCC_Per_LED RCC_AHB1Periph_GPIOA
#define PIN_P25 GPIO_Pin_3
#define PORT_P25 GPIOB
#define RCC_Per_P25 RCC_AHB1Periph_GPIOB
#define PIN_NXDN GPIO_Pin_10
#define PORT_NXDN GPIOA
#define RCC_Per_NXDN RCC_AHB1Periph_GPIOA
#define PIN_POCSAG GPIO_Pin_12
#define PORT_POCSAG GPIOB
#define RCC_Per_POCSAG RCC_AHB1Periph_GPIOB
#define PIN_DSTAR GPIO_Pin_10
#define PORT_DSTAR GPIOB
#define RCC_Per_DSTAR RCC_AHB1Periph_GPIOB
#define PIN_DMR GPIO_Pin_4
#define PORT_DMR GPIOB
#define RCC_Per_DMR RCC_AHB1Periph_GPIOB
#define PIN_YSF GPIO_Pin_5
#define PORT_YSF GPIOB
#define RCC_Per_YSF RCC_AHB1Periph_GPIOB
#if defined(MODE_PINS)
#define PIN_MP25 GPIO_Pin_3
#define PORT_MP25 GPIOC
#define RCC_Per_MP25 RCC_AHB1Periph_GPIOC
#define PIN_MNXDN GPIO_Pin_6
#define PORT_MNXDN GPIOC
#define RCC_Per_MNXDN RCC_AHB1Periph_GPIOC
#define PIN_MDSTAR GPIO_Pin_4
#define PORT_MDSTAR GPIOC
#define RCC_Per_MDSTAR RCC_AHB1Periph_GPIOC
#define PIN_MDMR GPIO_Pin_5
#define PORT_MDMR GPIOC
#define RCC_Per_MDMR RCC_AHB1Periph_GPIOC
#define PIN_MYSF GPIO_Pin_2
#define PORT_MYSF GPIOC
#define RCC_Per_MYSF RCC_AHB1Periph_GPIOC
#endif
#define PIN_EXT_CLK GPIO_Pin_15
#define SRC_EXT_CLK GPIO_PinSource15
#define PORT_EXT_CLK GPIOA
#define PIN_RX GPIO_Pin_0
#define PIN_RX_CH ADC_Channel_0
#define PORT_RX GPIOA
#define RCC_Per_RX RCC_AHB1Periph_GPIOA
#define PIN_RSSI GPIO_Pin_1
#define PIN_RSSI_CH ADC_Channel_1
#define PORT_RSSI GPIOA
#define RCC_Per_RSSI RCC_AHB1Periph_GPIOA
#define PIN_TX GPIO_Pin_4
#define PIN_TX_CH DAC_Channel_1
#endif
+101
View File
@@ -0,0 +1,101 @@
/*
* Copyright (C) 2019,2020 by BG5HHP
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifndef _PINS_F7_PI_H
#define _PINS_F7_PI_H
/*
Pin definitions for STM32F722 Pi Board:
PTT PB13 output
COSLED PB14 output
LED PB15 output
COS PC0 input
DSTAR PC7 output
DMR PC8 output
YSF PA8 output
P25 PC9 output
NXDN PB1 output
POCSAG PB12 output
RX PA0 analog input
RSSI PA7 analog input
TX PA4 analog output
EXT_CLK PA15 input
*/
#define PIN_COS GPIO_Pin_0
#define PORT_COS GPIOC
#define RCC_Per_COS RCC_AHB1Periph_GPIOC
#define PIN_PTT GPIO_Pin_13
#define PORT_PTT GPIOB
#define RCC_Per_PTT RCC_AHB1Periph_GPIOB
#define PIN_COSLED GPIO_Pin_14
#define PORT_COSLED GPIOB
#define RCC_Per_COSLED RCC_AHB1Periph_GPIOB
#define PIN_LED GPIO_Pin_15
#define PORT_LED GPIOB
#define RCC_Per_LED RCC_AHB1Periph_GPIOB
#define PIN_P25 GPIO_Pin_9
#define PORT_P25 GPIOC
#define RCC_Per_P25 RCC_AHB1Periph_GPIOC
#define PIN_NXDN GPIO_Pin_1
#define PORT_NXDN GPIOB
#define RCC_Per_NXDN RCC_AHB1Periph_GPIOB
#define PIN_POCSAG GPIO_Pin_12
#define PORT_POCSAG GPIOB
#define RCC_Per_POCSAG RCC_AHB1Periph_GPIOB
#define PIN_DSTAR GPIO_Pin_7
#define PORT_DSTAR GPIOC
#define RCC_Per_DSTAR RCC_AHB1Periph_GPIOC
#define PIN_DMR GPIO_Pin_8
#define PORT_DMR GPIOC
#define RCC_Per_DMR RCC_AHB1Periph_GPIOC
#define PIN_YSF GPIO_Pin_8
#define PORT_YSF GPIOA
#define RCC_Per_YSF RCC_AHB1Periph_GPIOA
#define PIN_EXT_CLK GPIO_Pin_15
#define SRC_EXT_CLK GPIO_PinSource15
#define PORT_EXT_CLK GPIOA
#define PIN_RX GPIO_Pin_0
#define PIN_RX_CH ADC_Channel_0
#define PORT_RX GPIOA
#define RCC_Per_RX RCC_AHB1Periph_GPIOA
#define PIN_RSSI GPIO_Pin_7
#define PIN_RSSI_CH ADC_Channel_7
#define PORT_RSSI GPIOA
#define RCC_Per_RSSI RCC_AHB1Periph_GPIOA
#define PIN_TX GPIO_Pin_4
#define PIN_TX_CH DAC_Channel_1
#endif
+144
View File
@@ -0,0 +1,144 @@
/*
* Copyright (C) 2019,2020 by BG5HHP
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifndef _PINS_F7_RPT_HAT_H
#define _PINS_F7_RPT_HAT_H
/*
Pin definitions for MMDVM_RPT_Hat Pi-Hat F0DEI DB9MAT DF2ET board:
PTT PB14 output
COSLED PB13 output
LED PB12 output
COS PC0 input
DSTAR PB15 output
DMR PC6 output
YSF PC7 output
P25 PC8 output
NXDN PC9 output
POCSAG PA8 output
FM PA11 output
MDSTAR PC1 output
MDMR PC2 output
MYSF PC3 output
MP25 PC4 output
MNXDN PC10 output
MPOCSAG PC11 output
MFM PC13 output
RX PA0 analog input
RSSI PA7 analog input
TX PA4 analog output
EXT_CLK PA15 input
*/
#define PIN_COS GPIO_Pin_0
#define PORT_COS GPIOC
#define RCC_Per_COS RCC_AHB1Periph_GPIOC
#define PIN_PTT GPIO_Pin_14
#define PORT_PTT GPIOB
#define RCC_Per_PTT RCC_AHB1Periph_GPIOB
#define PIN_COSLED GPIO_Pin_13
#define PORT_COSLED GPIOB
#define RCC_Per_COSLED RCC_AHB1Periph_GPIOB
#define PIN_LED GPIO_Pin_12
#define PORT_LED GPIOB
#define RCC_Per_LED RCC_AHB1Periph_GPIOB
#define PIN_P25 GPIO_Pin_8
#define PORT_P25 GPIOC
#define RCC_Per_P25 RCC_AHB1Periph_GPIOC
#define PIN_NXDN GPIO_Pin_9
#define PORT_NXDN GPIOC
#define RCC_Per_NXDN RCC_AHB1Periph_GPIOC
#define PIN_POCSAG GPIO_Pin_8
#define PORT_POCSAG GPIOA
#define RCC_Per_POCSAG RCC_AHB1Periph_GPIOA
#define PIN_FM GPIO_Pin_11
#define PORT_FM GPIOA
#define RCC_Per_FM RCC_AHB1Periph_GPIOA
#define PIN_DSTAR GPIO_Pin_15
#define PORT_DSTAR GPIOB
#define RCC_Per_DSTAR RCC_AHB1Periph_GPIOB
#define PIN_DMR GPIO_Pin_6
#define PORT_DMR GPIOC
#define RCC_Per_DMR RCC_AHB1Periph_GPIOC
#define PIN_YSF GPIO_Pin_7
#define PORT_YSF GPIOC
#define RCC_Per_YSF RCC_AHB1Periph_GPIOC
#if defined(MODE_PINS)
#define PIN_MP25 GPIO_Pin_4
#define PORT_MP25 GPIOC
#define RCC_Per_MP25 RCC_AHB1Periph_GPIOC
#define PIN_MNXDN GPIO_Pin_10
#define PORT_MNXDN GPIOC
#define RCC_Per_MNXDN RCC_AHB1Periph_GPIOC
#define PIN_MDSTAR GPIO_Pin_1
#define PORT_MDSTAR GPIOC
#define RCC_Per_MDSTAR RCC_AHB1Periph_GPIOC
#define PIN_MDMR GPIO_Pin_2
#define PORT_MDMR GPIOC
#define RCC_Per_MDMR RCC_AHB1Periph_GPIOC
#define PIN_MYSF GPIO_Pin_3
#define PORT_MYSF GPIOC
#define RCC_Per_MYSF RCC_AHB1Periph_GPIOC
#define PIN_MPOCSAG GPIO_Pin_11
#define PORT_MPOCSAG GPIOC
#define RCC_Per_MPOCSAG RCC_AHB1Periph_GPIOC
#define PIN_MFM GPIO_Pin_13
#define PORT_MFM GPIOC
#define RCC_Per_MFM RCC_AHB1Periph_GPIOC
#endif
#define PIN_EXT_CLK GPIO_Pin_15
#define SRC_EXT_CLK GPIO_PinSource15
#define PORT_EXT_CLK GPIOA
#define PIN_RX GPIO_Pin_0
#define PIN_RX_CH ADC_Channel_0
#define PORT_RX GPIOA
#define RCC_Per_RX RCC_AHB1Periph_GPIOA
#define PIN_RSSI GPIO_Pin_7
#define PIN_RSSI_CH ADC_Channel_7
#define PORT_RSSI GPIOA
#define RCC_Per_RSSI RCC_AHB1Periph_GPIOA
#define PIN_TX GPIO_Pin_4
#define PIN_TX_CH DAC_Channel_1
#endif