Compare commits

..

479 commits
M17 ... master

Author SHA1 Message Date
9a3cfe9fd9 Remove wiringPi depencies 2022-11-27 04:22:43 +01:00
de6f60ed5d Display ID 2022-07-30 00:30:52 +02:00
035dd944ab Set Mode to DMR at bootup 2022-07-30 00:10:10 +02:00
0082295493 Fix header 2022-07-30 00:01:42 +02:00
575a36e42c Log incoming radio id, verbose log of downlink 2022-07-29 23:59:37 +02:00
10fe14ab72 Fix whitelist output 2022-07-29 23:23:49 +02:00
7a551ddf04 Show whitelist on start 2022-07-29 23:08:25 +02:00
f8ad2e28ca Change prefix length 2022-07-29 22:37:10 +02:00
ca8571c276 Rename DMR access control 2022-07-29 22:33:32 +02:00
bbd72df6fc Add one byte to DMR ID lookup 2022-07-29 19:28:25 +02:00
a81c03b0ef Modify makefile for rpi 2022-07-29 19:25:03 +02:00
9e7186b9bd Set fixed mode 2022-07-29 19:24:39 +02:00
58f9b7388c Fix build 2022-07-29 19:08:46 +02:00
31cc01c811 Clean up files 2022-07-29 18:54:00 +02:00
f26ab797dc Clean up code 2022-07-29 18:49:08 +02:00
77a9501dc4 fix typo in Readme 2022-07-29 13:22:37 +02:00
842bb20fbf Changed readme 2022-07-29 13:22:14 +02:00
Jonathan Naylor
fe195c4e40 Rewrite the OVCM handling. 2022-05-23 22:35:14 +01:00
Jonathan Naylor
33939d8cf5
Merge pull request #746 from es2ast/patch-2 2022-04-16 09:15:23 +01:00
es2ast
60b5e425df
MMDVM protocol ver 2 hwType
Repeater Builder ver 4 board
2022-04-16 03:37:00 +03:00
Jonathan Naylor
3e8cda274d
Merge pull request #741 from cainbit/fix_uart_setnonblock 2022-03-07 07:59:57 +00:00
Jonathan Naylor
452be45b11
Merge pull request #742 from iddq/master
Add Radio Check CSBK
2022-03-06 20:01:37 +00:00
Jonathan Naylor
d94043e06d
Merge pull request #739 from AG4OJ/patch-6
sendCommandAction(15) used twice
2022-03-06 20:00:00 +00:00
iddq
82024fae5f Add Radio Check CSBK 2022-03-04 10:53:54 +01:00
cainbit
ace0d21975 fix UART setNonblock bug. 2022-02-18 10:06:49 +08:00
William R. Pelfrey
6290449266
sendCommandAction(15) used twice
sendCommand(15) used for LOCKOUT in line 235 and FM in line 277. Changing FM to unused 18 could be preferable.
2022-02-10 16:53:38 -05:00
Jonathan Naylor
efff4f0dc4 Add the missing UseCOSAsLockout configuration option. 2022-01-31 17:37:24 +00:00
Jonathan Naylor
2b34978be1
Merge pull request #737 from f1rmb/disable_remotecommand_logging
Add a way to disable the RemoteCommand logging (annoying when RemoteCommand is heavily used).
2022-01-24 07:12:54 +00:00
Jonathan Naylor
f81e8fbdf5
Merge pull request #736 from f1rmb/hosts_remote_command
Add new remote command:
2022-01-24 07:12:44 +00:00
Daniel Caujolle-Bert
4d294fda56 Add a way to disable the RemoteCommand logging (annoying when RemoteCommand is heavily used). 2022-01-24 02:55:18 +00:00
Jonathan Naylor
fed4400632
Merge pull request #734 from f1rmb/remotecommand_argument_usage
Display optional argument to RemoteCommand's usage output.
2022-01-23 19:49:30 +00:00
Daniel Caujolle-Bert
a30ae3af4d Add new remote command:
- hosts: display connected hosts, or NONE if disconnected (surrounded with double quotes).
Increase buffer size, for reply string, from 100 to 1024.
2022-01-21 10:51:41 +00:00
Daniel Caujolle-Bert
a6b05aab5b Display optional argument to RemoteCommand's usage output. 2022-01-20 14:25:53 +01:00
Jonathan Naylor
e0adf4328b
Merge pull request #731 from f1rmb/m17_remotecommand_status 2022-01-07 12:11:41 +00:00
Daniel Caujolle-Bert
20b1367848 Add M17 network status to Remote command "status" output.
YSFNetwork: fix ::IsConnected(), it should not take m_enabled in account.
2022-01-07 11:47:19 +00:00
Jonathan Naylor
4b864661a7 Update the README. 2021-12-13 10:32:28 +00:00
Jonathan Naylor
5d9acbae1b
Merge pull request #729 from nolith/m17-logo 2021-12-09 18:31:56 +00:00
Alessio Caiazza
572227a073 Add M17 logo for OLED display 2021-12-09 18:24:21 +01:00
Jonathan Naylor
a26f9af671
Merge pull request #728 from AG4OJ/patch-2
Changes To Agree With Code In Nextion.cpp
2021-11-25 21:54:18 +00:00
William R. Pelfrey
a919088f1f
Changes To Agree With Code In Nextion.cpp
Please apply these changes so they agree with the code in file Nextion.cpp.
2021-11-25 16:06:17 -05:00
Jonathan Naylor
18823b6c9c
Merge pull request #725 from AG4OJ/patch-1
These Are Conflict Changes - Proposed AG4OJ
2021-11-23 16:39:03 +00:00
Jonathan Naylor
94981664e0
Merge pull request #726 from on7lds/master
Add M17 to the ON7LDS layouts and documentation
2021-11-23 16:38:31 +00:00
on7lds
bcc73d87aa Add M17 to the ON7LDS layouts and documentation files.
Send unique status codes for M17 to the Nextion display.
2021-11-23 08:35:12 +01:00
ON7LDS
8ecc41b0bb Add M17 to the ON7LDS layouts and documentation files
Send unique status codes for M17 to the Nextion display
2021-11-23 08:10:48 +01:00
William R. Pelfrey
af8d1f45ed
These Are Conflict Changes - Proposed AG4OJ
Please over look these changes to help stabilize the new M17 Mode additions.
2021-11-21 15:21:59 -05:00
Jonathan Naylor
b1d5973bb0
Merge pull request #721 from jg1uaa/master 2021-10-30 17:27:36 +01:00
SASANO Takayoshi
483a886fa8 TFTSurenoo: initialize improvement
Sometimes the timing of transmitted data through Nextion UART port on
MMDVM board is not accurate. For example, 250ms delay of lcdReset() is
ignored.

(via MMDVM LCD-UART port)
[2021/10/29 23:04:57.481] RESET;
[2021/10/29 23:04:57.482] CLR(0);
[2021/10/29 23:04:58.100]
[2021/10/29 23:04:58.101] DIR(1);BL(50);SBC(0);
[2021/10/29 23:04:58.142] BOXF(0,0,159,127,0);DCV24(0,0,'MMDVM',4);DCV16(0,32,'JG1UAA / 440xxxx',5);DCV16(0,48,'IDLE',5);

(via native serial port)
[2021/10/30 08:11:21.587] RESET;
[2021/10/30 08:11:21.827] CLR(0);
[2021/10/30 08:11:37.478]
[2021/10/30 08:11:37.480] DIR(1);BL(50);SBC(0);
[2021/10/30 08:11:37.498] BOXF(0,0,159,127,0);DCV24(0,0,'MMDVM',4);DCV16(0,32,'JG1UAA / 440xxxx',5);DCV16(0,48,'IDLE',5);

Ignoring screen direction(DIR), background color(SBC) breaks screen layout.
To solve this, send some LCD configuration command at refreshDisplay().
This is not smart solution, but inevitable.
2021-10-30 08:48:15 +09:00
Jonathan Naylor
204b4140bb Fix compiler warning 2021-10-25 17:57:41 +01:00
Jonathan Naylor
8a5f79878e
Merge pull request #719 from jg1uaa/master 2021-10-25 16:19:15 +01:00
Jonathan Naylor
e960b052db
Merge pull request #720 from shawnchain/macos-uart460800-fix 2021-10-25 16:18:20 +01:00
Shawn Chain
2f9b4c120c macos fix for the baudrate 460800 2021-10-25 19:31:29 +08:00
SASANO Takayoshi
e6d4bfe61c permit inline comment 2021-10-25 20:17:07 +09:00
Jonathan Naylor
b57b781ab8
Merge pull request #717 from jg1uaa/master 2021-10-24 07:44:13 +01:00
SASANO Takayoshi
fc836f3812 revise UART speed setting in setRaw()
not only Apple but also *BSD uses raw baudrate for cfset[io]speed().
If cfset[io]speed can accept raw value, set m_speed directly.

Otherwise (Linux) use bitmask like B115200.
2021-10-24 13:37:19 +09:00
SASANO Takayoshi
a9fbbc1d2c <pty.h>: linux only
not only Apple but also other OSes except Linux uses <util.h>.
for details, see
https://www.gnu.org/software/gnulib/manual/html_node/pty_002eh.html
2021-10-24 13:17:47 +09:00
Jonathan Naylor
186c61a128 Fix method name. 2021-10-22 09:16:44 +01:00
Jonathan Naylor
116e257f90 Add M17 to the HD44780 display. 2021-10-21 20:53:00 +01:00
Jonathan Naylor
c469d31227 Merge branch 'master' into M17_AX25_FM 2021-10-17 18:41:43 +01:00
Jonathan Naylor
12282f709a
Merge pull request #716 from KE7FNS/master 2021-10-13 06:40:59 +01:00
Jason Kraemer
df12cf1052
Merge pull request #2 from KE7FNS/KE7FNS-patch-2
Update HD44780.cpp
2021-10-12 19:49:15 -07:00
Jason Kraemer
2f274d3746
Update HD44780.cpp
POCSAG string was 6 characters, it HAS to be 5 or else it wraps to another line.
2021-10-12 19:48:27 -07:00
Jonathan Naylor
c5c5db39a1 Merge branch 'master' into M17_AX25_FM 2021-10-05 23:34:33 +01:00
Jonathan Naylor
cd7527a3aa
Merge pull request #715 from KE7FNS/master
Reversing recent changes
2021-10-05 23:33:45 +01:00
KE7FNS
8b67d856f7
Merge pull request #1 from KE7FNS/KE7FNS-patch-1
Update HD44780.cpp
2021-10-05 15:07:32 -07:00
KE7FNS
991fd46cad
Update HD44780.cpp
Reversing recent changes to limit strings to the length of 5 to match previously implemented structure so alignment works on multiple displays without issues and position conflicts.
2021-10-05 15:06:26 -07:00
Jonathan Naylor
358adce2c9 Merge branch 'extended' into M17_AX25_FM 2021-10-04 21:44:25 +01:00
Jonathan Naylor
54c3584453 Fix newline issue in the OLED makefile. 2021-09-28 21:34:11 +01:00
Jonathan Naylor
d83e06a4ad Merge branch 'M17_AX25_FM' into extended 2021-09-27 22:57:22 +01:00
Jonathan Naylor
2b357f79c5 Fix a double declaration of M17 for the OLED. 2021-09-27 22:56:43 +01:00
Jonathan Naylor
9c297371e6 Merge branch 'M17_AX25_FM' into extended 2021-09-27 22:33:28 +01:00
Jonathan Naylor
40620f855c Merge branch 'master' into M17_AX25_FM 2021-09-27 22:33:05 +01:00
Jonathan Naylor
ed541885f6
Merge pull request #714 from pd9mwo/patch-1
Update HD44780.cpp with POCSAG
2021-09-27 22:32:27 +01:00
pd9mwo
4b0e016355
Update HD44780.cpp
POCSAG TX wont fit on a HD47780 16x2 screen
2021-09-26 17:56:09 +02:00
Jonathan Naylor
45e45da6e6 Substitute the source with the repeaters callsign and add the extended callsign information on RF. 2021-09-21 20:56:11 +01:00
Jonathan Naylor
cdfe3620d5 Merge branch 'M17_AX25_FM' into extended 2021-09-19 17:26:11 +01:00
Jonathan Naylor
50a3afd66f Change to the new method of M17 EOT transmission. 2021-09-19 15:15:37 +01:00
Jonathan Naylor
8ba7a78a77 Merge branch 'M17_AX25_FM' into extended 2021-09-12 20:32:19 +01:00
Jonathan Naylor
cb89b34a39 Rename SimpleMode to LinkMode. 2021-09-06 21:47:23 +01:00
Jonathan Naylor
ded46ebb60 Add a new simple FM mode for gatewaying. 2021-09-05 19:07:50 +01:00
Jonathan Naylor
14e682dec4 Merge branch 'M17_AX25_FM' into extended 2021-09-05 18:01:28 +01:00
Jonathan Naylor
efb3a24872 Merge branch 'M17_AX25_FM' of github.com:g4klx/MMDVMHost into M17_AX25_FM 2021-09-05 17:55:50 +01:00
Jonathan Naylor
6aac9d67b7 Document the AccessMode value for the FM repeater. 2021-09-05 17:55:23 +01:00
Jonathan Naylor
0071fce5c0 Fix the calculation of the Link Setup BER. 2021-09-05 16:19:05 +01:00
Jonathan Naylor
a173c884e4 Merge branch 'M17_AX25_FM' into EOF 2021-09-05 15:11:59 +01:00
Jonathan Naylor
11f14465e6 Fix the Link Setup puncturing matrix. 2021-09-05 14:59:15 +01:00
Jonathan Naylor
d1dc6bb7a0 Simplify the LSF processing to allow changed META field data changed
through.
2021-08-26 21:49:46 +01:00
Jonathan Naylor
b779ea5ae6 Convert to the new EOF marker. 2021-08-25 19:27:53 +01:00
Jonathan Naylor
37c889c2d9 Merge branch 'M17_AX25_FM' into EOF 2021-08-24 23:07:15 +01:00
Jonathan Naylor
836bc0dc9b Update to the latest Link Setup puncturing pattern. 2021-08-23 23:03:52 +01:00
Jonathan Naylor
ef6ce0ef88 Include the fragment LICH in the network data. 2021-08-22 21:56:46 +01:00
Jonathan Naylor
e966d355cd Change the internal network protocol. 2021-08-22 20:38:26 +01:00
Jonathan Naylor
8e36cd88aa Update the 1600 silence bytes. 2021-08-20 16:10:21 +01:00
Jonathan Naylor
8c31fe6f34 Fix a bug introduced in the new EOF processing. 2021-08-20 09:23:39 +01:00
Jonathan Naylor
fbb835812d Clean up the new EOF handling. 2021-08-20 07:08:18 +01:00
Jonathan Naylor
55f4c6ce1a Fix small queueing bug. 2021-08-19 21:39:29 +01:00
Jonathan Naylor
293962a7f7 Filter the EOF marker out of the FN for retransmission. 2021-08-19 20:50:31 +01:00
Jonathan Naylor
e1b164de70 Add the new EOF frame. 2021-08-19 20:44:15 +01:00
Jonathan Naylor
8e34cab68b Add validation for M17 end bit. 2021-08-18 19:36:00 +01:00
Jonathan Naylor
200986b698 Fix problem with incoming network audio being ignored. 2021-08-17 21:30:05 +01:00
Jonathan Naylor
4ec4b3dafe Update the copyright header. 2021-08-17 12:15:54 +01:00
Jonathan Naylor
2a63f83a9b Remove the unused packetTimer from the M17 controller. 2021-08-17 10:54:59 +01:00
Jonathan Naylor
9cea26ec62
Merge pull request #710 from nostar/M17_AX25_FM 2021-08-13 20:18:50 +01:00
Home
03a4837227 OSX build error fixes 2021-08-13 15:00:17 -04:00
Jonathan Naylor
14bf5007d5 Fix the M17 convolution. 2021-08-11 18:42:15 +01:00
Jonathan Naylor
e2e5ddf4c8 Add M17 Codec 1600 mode on RX and remove the remains of M17 packet mode
support.
2021-08-10 19:54:14 +01:00
Jonathan Naylor
bfacdee8e2 Merge branch 'master' into M17_AX25_FM 2021-08-09 22:14:15 +01:00
Jonathan Naylor
433cb441be
Merge pull request #709 from stefansaraev/rfstate-reset 2021-08-08 17:27:24 +01:00
Stefan Saraev
61e5623ad3 DMRSlot: reset m_rfState after rejecting rf activity 2021-08-08 00:29:34 +03:00
Jonathan Naylor
dd09c666bb Display the M17 FN numbers correctly. 2021-07-29 21:32:07 +01:00
Jonathan Naylor
bf3dbdb55d Clean up the FEC processing for M17. 2021-07-08 23:00:53 +01:00
Jonathan Naylor
b6ff701c05 Merge branch 'M17_AX25_FM' of https://github.com/g4klx/MMDVMHost into M17_AX25_FM 2021-07-01 07:11:08 +01:00
Jonathan Naylor
bc1b84caef Change the capabilties of version 1 protocol based systems. 2021-07-01 07:09:46 +01:00
Jonathan Naylor
42c53d3c39 Add LSF BER debug message. 2021-06-30 07:46:19 +01:00
Jonathan Naylor
926755171f Fix the M17 FN handling. 2021-06-30 07:42:48 +01:00
Jonathan Naylor
dae05ad58a Use the BER from the Viterbi decoder in M17 mode to determine if the
audio is usable or not.
2021-06-28 19:16:16 +01:00
Jonathan Naylor
f7b8448963 Add extra logging to the ID lookup processing. 2021-06-27 22:16:26 +01:00
Jonathan Naylor
8547a210bd Get the convolution BER directly from the decoder. 2021-06-27 17:29:55 +01:00
Jonathan Naylor
50337639b2 Accept rejected or invalid transmissions as being 'in' despite not being
relayed. Also give extra headroom on the convolution decoders.
2021-06-25 16:21:48 +01:00
Jonathan Naylor
a8fe55acc4 Merge branch 'master' into M17_AX25_FM 2021-06-25 15:34:30 +01:00
Jonathan Naylor
3f65200d7d
Merge pull request #704 from f1rmb/fix_adafruit_makefile
Adafruit Makefile: Add missing SMeter.
2021-06-25 15:31:07 +01:00
Jonathan Naylor
f9e953d687 D-Star rejected transmissions are still valid RF for the host. 2021-06-25 09:58:34 +01:00
Jonathan Naylor
e344fc5b56 Alter the mode timer reset behaviour when already in that mode. 2021-06-18 08:56:29 +01:00
Daniel Caujolle-Bert
43bfaef117
Add missing SMeter. 2021-06-17 07:33:01 +02:00
Jonathan Naylor
c7effe5e2d Merge branch 'master' into M17_AX25_FM 2021-06-03 19:08:17 +01:00
Jonathan Naylor
9106fd69d2
Merge pull request #700 from F4FXL/f4fxl/BERandRSSI
Fix Sprintf warnings
2021-06-03 19:07:20 +01:00
Geoffrey Merck
deff9910eb Fix Sprintf warnings (maybe should consider moving to std::string) 2021-05-31 21:02:35 +02:00
Jonathan Naylor
7226c6f1f3 Merge branch 'M17_AX25_FM' of https://github.com/g4klx/MMDVMHost into M17_AX25_FM 2021-05-25 20:34:41 +01:00
Jonathan Naylor
5727acceb8 Restore the FM lockout parameter. 2021-05-25 20:33:28 +01:00
Jonathan Naylor
a5639559ff Fix a typo in the example MMDVM.ini file. 2021-05-25 20:21:27 +01:00
Jonathan Naylor
0448a315e9 Merge branch 'M17_AX25_FM' of https://github.com/g4klx/MMDVMHost into M17_AX25_FM 2021-05-25 19:05:01 +01:00
Jonathan Naylor
347fc4bedb Add an FM lockout to add to the other modes. 2021-05-25 19:04:09 +01:00
Jonathan Naylor
bf3bf07747 Fix the return status for M17 RF data. 2021-05-25 06:56:01 +01:00
Jonathan Naylor
ccdf708bbd Add access to the M17 META data field in the LSF. 2021-05-18 20:59:17 +01:00
Jonathan Naylor
8d6da34b79 Fix M17 and FM mode switching. 2021-05-18 20:24:26 +01:00
Jonathan Naylor
8363a72f6a Merge branch 'master' into M17_AX25_FM 2021-05-18 20:05:40 +01:00
Jonathan Naylor
e2d61d1572 Clean up the D-Star Control class a little. 2021-05-18 19:44:41 +01:00
Jonathan Naylor
21b66d5113
Merge pull request #697 from F4FXL/f4fxl/BERandRSSI
Add SMeter reports to DStar Ack and Error
2021-05-18 19:19:17 +01:00
Geoffrey
d7c95f05f0 Add leading 0 to + 2021-05-17 07:14:26 +02:00
Geoffrey
87a447f601 fix reports between S9 and S9+10, always return "plus" 2021-05-15 12:34:59 +02:00
Geoffrey
0e39d81797 Remove leading - and trailing + where not needed 2021-05-15 12:22:39 +02:00
Geoffrey
efabc44189 Align with R1 VHF/UH recommendation and pi-star 2021-05-15 12:20:57 +02:00
Geoffrey
397e5ff14f Fix wrong smeter logic 2021-05-15 09:30:20 +02:00
Geoffrey
19d234a627 Make sure dBm is not truncated when RSSI < 99 2021-05-15 07:06:37 +02:00
Geoffrey
f5e3427cd8 Add SMeter to DStar ack and error 2021-05-15 06:51:12 +02:00
Jonathan Naylor
c0e3fd0a5b Remove unneeded warning message. 2021-05-08 19:57:28 +01:00
Jonathan Naylor
e6fc679502 Add modem capabilities to stop misconfiguration. 2021-05-08 19:34:44 +01:00
Jonathan Naylor
2d6f601feb Remove depenancy on libsamplerate in the makefile. 2021-05-08 15:12:47 +01:00
Geoffrey Merck
4c4ea18319 Forgot that slow data is limited to 20 chars -_- 2021-05-04 21:07:35 +02:00
Geoffrey Merck
39620c22bd Also send BER with RSSI in Ack 2021-05-04 21:02:41 +02:00
Geoffrey Merck
77741318a0 Always send BER and RSSI in Dstar ack 2021-05-04 20:46:14 +02:00
Jonathan Naylor
7008c624d9 Regularise the local address handling across all of the protocol. 2021-04-25 11:10:35 +01:00
Jonathan Naylor
8b45e04ea0 Merge branch 'master' into M17_AX25_FM 2021-04-25 10:26:57 +01:00
Jonathan Naylor
db1eef6b0e
Merge pull request #696 from f1rmb/f1rmb_network_port_datatype
Fix network ports datatype (unsigned int -> unsigned short). UDPSocket: fix old bug using m_port instead of m_port[x].
2021-04-25 09:36:41 +01:00
Daniel Caujolle-Bert
ec0bc51899
Fix network ports datatype (unsigned int -> unsigned short). UDPSocket: fix old bug using m_port instead of m_port[x]. 2021-04-25 07:47:06 +02:00
Jonathan Naylor
609f1e356a Add the USDP metadata header to the FM network output. 2021-04-24 08:43:48 +01:00
Jonathan Naylor
82b5b010eb Add an end of transmission marker to the USRP protocol. 2021-04-20 22:37:17 +01:00
Jonathan Naylor
cfe9e0fba4 Remove the FM networking sample rate conversion. 2021-04-11 19:15:23 +01:00
Jonathan Naylor
a5ee4284f2 Add new modem debug message type. 2021-04-11 17:45:23 +01:00
Jonathan Naylor
3a73a25c1e Update M17 to the latest secification, removal of the CRC from the
stream data.
2021-04-11 17:31:05 +01:00
Jonathan Naylor
e6d5ef9055 Merge branch 'master' into M17_AX25_FM 2021-04-08 18:44:51 +01:00
Jonathan Naylor
b30d5465f5 Merge branch 'master' of https://github.com/g4klx/MMDVMHost 2021-04-08 18:36:59 +01:00
Jonathan Naylor
dad34bea98 Don't send RPTCL on DMR under error conditions. 2021-04-08 18:36:27 +01:00
Jonathan Naylor
6ae01af364
Merge pull request #692 from f1rmb/f1rmb_fix_UDPSocket_close
Fix nasty bug in UDPSocket::close().
2021-04-08 18:14:27 +01:00
Jonathan Naylor
ffb4bdb042 Refactor the Golay 24,12,8 code and its uses. 2021-04-07 19:56:28 +01:00
Daniel Caujolle-Bert
c08b41a17a
Fix nasty bug in UDPSocket::close(). 2021-03-31 13:34:31 +02:00
Jonathan Naylor
8dc54ed21f Ignore M17 packet data, for now. 2021-03-29 19:36:55 +01:00
Jonathan Naylor
389bd3b928 Remove the CRC4 processing. 2021-03-28 15:29:26 +01:00
Jonathan Naylor
6ac672e106 Finally process the Golay(24,12,8) parity bit. 2021-03-27 20:00:53 +00:00
Jonathan Naylor
4422444179 Disable the LICH CRC and clean up the payload checksum handling. 2021-03-27 14:51:53 +00:00
Jonathan Naylor
8efd77132f Rename the CRC4 functions correctly. 2021-03-26 22:45:33 +00:00
Jonathan Naylor
0a94b0deb6 Add the LICH CRC. 2021-03-26 22:21:20 +00:00
Jonathan Naylor
242cf50240 Remove the CAN processing from the LICH. 2021-03-26 20:34:08 +00:00
Jonathan Naylor
dbf771d80c Fixed M17 to be compatible with the latest protocol speciication. 2021-03-25 21:07:44 +00:00
Jonathan Naylor
6b43bce561
Merge pull request #690 from f1rmb/f1rmb_fix_network_isConnected
Fix *Network::isConnected().
2021-03-23 22:54:43 +00:00
Daniel Caujolle-Bert
b5420fef15
Fix *Network::isConnected().
As m_enabled is changed accordingly to the modem current mode, it's not valid to use it for network connexion status.
2021-03-23 22:32:36 +01:00
Jonathan Naylor
69a4fdd23c Merge branch 'master' into M17_AX25_FM 2021-03-22 22:14:54 +00:00
Jonathan Naylor
d26f3ea567
Merge pull request #689 from f1rmb/f1rmb_remote_status
Add RemoteCommand 'status' command.
2021-03-22 22:07:05 +00:00
Daniel Caujolle-Bert
27b7d3fc41
Add RemoteCommand 'status' command.
As DMRGateway, it reports connection status.

Command sent: "status" to port: 7642
dstar:n/a dmr:conn ysf:n/a p25:n/a nxdn:n/a fm:n/a

RemoveCommand has been slighlty modified, as using Log on a read-only filesystem simply forbids the strings to be displayed.
Another solution would be to set LogInitialisse's filePath to "/tmp/" for *nix systems.
2021-03-22 20:32:43 +01:00
Jonathan Naylor
9373b15e58 Merge branch 'master' into M17_AX25_FM 2021-03-22 19:23:03 +00:00
Jonathan Naylor
0088b0b225
Merge pull request #688 from f1rmb/f1rmb_remote_command_unifying
Unitying RemoteCommand with latest DMRGateway's RemoteControl PR.
2021-03-22 19:16:37 +00:00
Daniel Caujolle-Bert
629cdcfb2a
Unitying RemoteCommand with latest DMRGateway's RemoteControl PR. 2021-03-20 18:12:25 +01:00
Jonathan Naylor
95cb575a2e Improve FM data tracing. 2021-03-14 22:54:33 +00:00
Jonathan Naylor
a3e4a250bd Make the Null Controller respond properly. 2021-03-14 21:00:47 +00:00
Jonathan Naylor
42570c905d Handle updated M17 modem serial data. 2021-03-14 19:04:54 +00:00
Jonathan Naylor
d0ccc0ee61 Try and fix a crash. 2021-03-14 16:24:48 +00:00
Jonathan Naylor
75e8e95aad Add FM network audio gain and optional pre- and de-emphasis. 2021-03-14 14:59:34 +00:00
Jonathan Naylor
fb0d1ef5e2 Allow the USRP audio format to be used natively by the FM networking. 2021-03-14 12:16:39 +00:00
Jonathan Naylor
7c14a6ec40 Merge branch 'master' into M17_AX25_FM 2021-03-13 12:03:22 +00:00
Jonathan Naylor
69c9500cb1
Merge pull request #687 from jg1uaa/oled
delete unused variable
2021-03-13 11:57:27 +00:00
SASANO Takayoshi
c2be5ab2f7 delete unused variable 2021-03-13 12:27:23 +09:00
Jonathan Naylor
f1de23e568 Merge branch 'master' into M17_AX25_FM 2021-03-12 19:56:57 +00:00
Jonathan Naylor
125f21735b Move the host lookup for the DMR Direct Network. 2021-03-12 19:56:05 +00:00
Jonathan Naylor
5111d16b99
Merge pull request #685 from jg1uaa/oled
revise UserDB display setting on OLED
2021-03-12 19:46:35 +00:00
SASANO Takayoshi
51e74c6182 revise UserDB display setting on OLED
To display UserDB on OLED, either Slot1=0/Slot2=1 or Slot1=1/Slot2=0
of [DMR Network] in MMDVM.ini was required.

Other displays such as LCDproc, HD44180 and TFTSurenoo uses duplex value of
[General], OLED also uses same entry from now.
2021-03-10 21:09:58 +09:00
Jonathan Naylor
6f2bd43c53 Merge branch 'master' into M17_AX25_FM 2021-03-09 20:59:38 +00:00
Jonathan Naylor
79fc7623dc DMR networking code cleanup. 2021-03-09 20:59:04 +00:00
Jonathan Naylor
39e89584e1 Akter the FM Network data standard. 2021-03-07 19:25:21 +00:00
Jonathan Naylor
46b8ea56d3 Merge branch 'master' into M17_AX25_FM 2021-03-07 17:51:06 +00:00
Jonathan Naylor
5d8d1a3fb9 Add mode 4 (force off) for the DMR OVCM flag. 2021-03-07 17:42:55 +00:00
Jonathan Naylor
5537ebbb65
Merge pull request #684 from randybuildsthings/patch-1
Ref #683: Fix misaligned talker alias pointer
2021-03-07 17:08:08 +00:00
Randy Hall
c6f5a21a27
Proposed fix for #683
Adding 2 byte offset to the data pointer passed to CDMRTA::add() in the "RF" section of CDMRSlot.cpp::writeModem(). Fixes the bug that incorrectly decodes talker alias coming in over RF.
2021-03-07 07:27:34 -08:00
Jonathan Naylor
5c292f77e5 Put example modem IP parameters into the MMDVM.ini file. 2021-02-19 17:42:58 +00:00
Jonathan Naylor
fe3be93a2e Small UDP modem update. 2021-02-18 22:56:20 +00:00
Jonathan Naylor
e291096d22 Final modem refactoring. 2021-02-17 21:36:47 +00:00
Jonathan Naylor
279afb75f3 Finish off the UDP Controller and more clean-ups. 2021-02-17 19:35:28 +00:00
Jonathan Naylor
8ace65b86d More sane modem port protocol handling. 2021-02-16 22:34:25 +00:00
Jonathan Naylor
ff9712b36a Refactored some class names. 2021-02-16 20:05:03 +00:00
Jonathan Naylor
6344f8b9ef Merge branch 'master' into M17_AX25_FM 2021-01-02 12:56:27 +00:00
Jonathan Naylor
b64359a157
Merge pull request #675 from timclassic/enhance-dstar-frame-logging
Add frame content details to D-Star debug logging
2021-01-02 12:55:44 +00:00
Tim Stewart
0e6208cc67 Add frame content details to D-Star debug logging
Commit bf5651b deleted all log entries related to D-Star frame
contents.  This change adds some detail to the existing D-Star frame
debugging log entries.  Rather than always printing "audio", frames
may be logged as one of "audio", "nullaudio", or "fastdata".

A minimum width has been set for some fields so that the log messages
form columns while watching a data stream.

By virtue of centralizing the frame log messages, this commit also
adds debugging entries for frames originating from the network.

Example log entries that contain all three types as generated by a
Kenwood TH-D74 using fast data:

  M: 2021-01-01 19:52:44.255 D-Star, received RF header from KG4BXH  /D74  to CQCQCQ
  D: 2021-01-01 19:52:44.282 D-Star, RF nullaudio sequence no.  0
  D: 2021-01-01 19:52:44.282 D-Star, RF nullaudio sequence no.  1
  D: 2021-01-01 19:52:44.309 D-Star, RF nullaudio sequence no.  2
  D: 2021-01-01 19:52:44.332 D-Star, RF nullaudio sequence no.  3
  D: 2021-01-01 19:52:44.354 D-Star, RF nullaudio sequence no.  4
  D: 2021-01-01 19:52:44.365 D-Star, RF nullaudio sequence no.  5
  D: 2021-01-01 19:52:44.388 D-Star, RF nullaudio sequence no.  6
  D: 2021-01-01 19:52:44.404 D-Star, RF nullaudio sequence no.  7
  D: 2021-01-01 19:52:44.426 D-Star, RF nullaudio sequence no.  8
  D: 2021-01-01 19:52:44.443 D-Star, RF nullaudio sequence no.  9
  D: 2021-01-01 19:52:44.465 D-Star, RF nullaudio sequence no. 10
  D: 2021-01-01 19:52:44.488 D-Star, RF nullaudio sequence no. 11
  D: 2021-01-01 19:52:44.510 D-Star, RF nullaudio sequence no. 12
  D: 2021-01-01 19:52:44.526 D-Star, RF nullaudio sequence no. 13
  D: 2021-01-01 19:52:44.543 D-Star, RF nullaudio sequence no. 14
  D: 2021-01-01 19:52:44.565 D-Star, RF nullaudio sequence no. 15
  D: 2021-01-01 19:52:44.588 D-Star, RF nullaudio sequence no. 16
  D: 2021-01-01 19:52:44.604 D-Star, RF nullaudio sequence no. 17
  D: 2021-01-01 19:52:44.627 D-Star, RF nullaudio sequence no. 18
  D: 2021-01-01 19:52:44.649 D-Star, RF nullaudio sequence no. 19
  D: 2021-01-01 19:52:44.665 D-Star, RF nullaudio sequence no. 20
  D: 2021-01-01 19:52:44.704 D-Star, RF fastdata  sequence no.  0
  D: 2021-01-01 19:52:44.704 D-Star, RF fastdata  sequence no.  1
  D: 2021-01-01 19:52:44.726 D-Star, RF fastdata  sequence no.  2
  D: 2021-01-01 19:52:44.748 D-Star, RF fastdata  sequence no.  3
  D: 2021-01-01 19:52:44.765 D-Star, RF fastdata  sequence no.  4
   ... many fastdata frames elided ...
  D: 2021-01-01 19:52:45.486 D-Star, RF fastdata  sequence no. 19
  D: 2021-01-01 19:52:45.508 D-Star, RF fastdata  sequence no. 20
  D: 2021-01-01 19:52:45.548 D-Star, RF fastdata  sequence no.  0
  D: 2021-01-01 19:52:45.548 D-Star, RF fastdata  sequence no.  1
  D: 2021-01-01 19:52:45.565 D-Star, RF fastdata  sequence no.  2
  D: 2021-01-01 19:52:45.587 D-Star, RF audio     sequence no.  3, errs:  0/48 (  0.0%)
  D: 2021-01-01 19:52:45.609 D-Star, RF audio     sequence no.  4, errs:  0/48 (  0.0%)
  D: 2021-01-01 19:52:45.631 D-Star, RF audio     sequence no.  5, errs:  0/48 (  0.0%)
  D: 2021-01-01 19:52:45.648 D-Star, RF audio     sequence no.  6, errs:  0/48 (  0.0%)
  D: 2021-01-01 19:52:45.670 D-Star, RF audio     sequence no.  7, errs:  0/48 (  0.0%)
  D: 2021-01-01 19:52:45.687 D-Star, RF audio     sequence no.  8, errs:  0/48 (  0.0%)
  D: 2021-01-01 19:52:45.709 D-Star, RF fastdata  sequence no.  9
  D: 2021-01-01 19:52:45.731 D-Star, RF fastdata  sequence no. 10
  D: 2021-01-01 19:52:45.753 D-Star, RF fastdata  sequence no. 11
  D: 2021-01-01 19:52:45.775 D-Star, RF fastdata  sequence no. 12
  D: 2021-01-01 19:52:45.786 D-Star, RF fastdata  sequence no. 13
   ... many more fastdata frames with periodic audio as above ...
2021-01-01 17:55:48 -05:00
Jonathan Naylor
e761e9c083 Merge branch 'master' into M17_AX25_FM 2021-01-01 14:45:08 +00:00
Jonathan Naylor
a209c00479 Allow DMR/P25 and NXDN Id reload with a SIGUSR1 or via a remote command. 2021-01-01 13:54:03 +00:00
Jonathan Naylor
d07782696c Merge branch 'master' into M17_AX25_FM 2021-01-01 13:20:25 +00:00
Jonathan Naylor
4ec33c86a7
Merge pull request #674 from s-s-s/patch-2
New format of DMRIds.dat file
2021-01-01 12:32:51 +00:00
Sergei
397b10131f
New format of DMRIds.dat file
Generate new format of DMRIds.dat file
2020-12-29 12:41:06 +03:00
Jonathan Naylor
9d85b6451c Update the M17 sync words. 2020-12-26 12:12:52 +00:00
Jonathan Naylor
1c3f6ae75e Merge branch 'master' into M17_AX25_FM 2020-12-26 12:01:32 +00:00
Jonathan Naylor
28f2203f5a
Merge pull request #673 from SA7BNT/master
Update DMRIDUpdate.sh
2020-12-26 12:00:30 +00:00
SA7BNT
75a6a67c17
Update DMRIDUpdate.sh
Change DB adress
2020-12-26 02:13:01 +01:00
Jonathan Naylor
37c298c885 Merge branch 'master' into M17_AX25_FM 2020-12-16 13:06:50 +00:00
Jonathan Naylor
02141f55ff
Merge pull request #669 from jg1uaa/master
revise POCSAG layout for decoded ROT1 message
2020-12-16 13:02:04 +00:00
SASANO Takayoshi
d76d4b063c revise POCSAG layout for decoded ROT1 message
POCSAGControl.cpp has ROT1 decoder now and it sends
(rublic index) "message" format.

To display whole message, parse text to fit OLED.

- rublic index is after RIC
- discard leading/trailing double quote character
2020-12-16 20:39:00 +09:00
Jonathan Naylor
e086b70526 Merge branch 'M17_AX25_FM' of https://github.com/g4klx/MMDVMHost into M17_AX25_FM 2020-12-15 16:30:39 +00:00
Jonathan Naylor
d77e2a00ce Restore the branch 2020-12-15 16:21:07 +00:00
Jonathan Naylor
ffc369c3a5 Revert "Merge branch 'M17_AX25_FM'"
This reverts commit e1427e3e37, reversing
changes made to bcdba292eb.
2020-12-15 16:02:59 +00:00
Jonathan Naylor
a95389242b Revert "Revert "Merge branch 'M17_AX25_FM'""
This reverts commit 135fd04e0d.
2020-12-15 16:02:11 +00:00
Jonathan Naylor
135fd04e0d Revert "Merge branch 'M17_AX25_FM'"
This reverts commit e1427e3e37, reversing
changes made to bcdba292eb.
2020-12-15 15:52:27 +00:00
Jonathan Naylor
e1427e3e37 Merge branch 'M17_AX25_FM' 2020-12-15 15:50:45 +00:00
Jonathan Naylor
bcdba292eb Display the rubric of the encrypted messages. 2020-12-15 14:27:47 +00:00
Jonathan Naylor
2ad4a2abfc Merge branch 'master' into M17_AX25_FM 2020-12-15 10:20:12 +00:00
Jonathan Naylor
b22d9084c8 Add more POCSAG display information. 2020-12-15 10:19:37 +00:00
Jonathan Naylor
9811bb7d4d Merge branch 'master' into M17_AX25_FM 2020-12-14 12:49:36 +00:00
Jonathan Naylor
a027b1f3bd Display the decrypted text on the external displays. 2020-12-14 12:48:56 +00:00
Jonathan Naylor
f5449ffc83 Merge branch 'master' into M17_AX25_FM 2020-12-14 12:23:42 +00:00
Jonathan Naylor
77daf86723 Decode encrypted POCSAG messages (thanks to JG1UAA for the code). 2020-12-14 12:22:43 +00:00
Jonathan Naylor
99a4d37082 Merge branch 'master' into M17_AX25_FM 2020-12-14 10:14:53 +00:00
Jonathan Naylor
56f361b3e4 Bump the version date. 2020-12-14 10:05:12 +00:00
Jonathan Naylor
4897313fc0
Merge pull request #667 from timclassic/dstar-fast-data-again
Detect D-Star DV Fast Data on a per-frame basis
2020-12-14 09:59:39 +00:00
Tim Stewart
bf5651b7a0 Remove DV Fast Data debugging statements 2020-12-13 19:27:38 -05:00
Tim Stewart
b2844bc0a6 Avoid FEC regeneration and DTMF blanking for null AMBE data
FEC recalculation always reports errors for null AMBE frames, and
there is no DTMF present by definition.

In practice, null AMBE data is often (always?) sent by the Kenwood
TH-D74 in the first 21 voice frames, and I've also seen it at the end
of a fast data transmission.
2020-12-13 19:25:09 -05:00
Jonathan Naylor
0a7df1758b Merge branch 'master' into M17_AX25_FM 2020-12-13 15:10:35 +00:00
Jonathan Naylor
787393e4c2
Merge pull request #666 from jg1uaa/oled-userdb
adjust message layout to display whole POCSAG message
2020-12-13 10:41:02 +00:00
SASANO Takayoshi
9dbe634f08 adjust message layout to display whole POCSAG message 2020-12-13 16:39:23 +09:00
Jonathan Naylor
fcf45d3e4b Merge branch 'master' into M17_AX25_FM 2020-12-09 09:47:49 +00:00
Jonathan Naylor
6e05225522 Reinstate the full RPTC command. 2020-12-09 09:41:11 +00:00
Jonathan Naylor
38f6292e71 Merge branch 'master' into M17_AX25_FM 2020-12-08 16:43:06 +00:00
Jonathan Naylor
99a4257d12 Fixed the configuration message prefix. 2020-12-08 16:42:15 +00:00
Jonathan Naylor
ef6056506c Merge branch 'master' into M17_AX25_FM 2020-12-06 16:46:10 +00:00
Jonathan Naylor
136deac61a Allow optional direct connections to masters again. 2020-12-06 16:12:54 +00:00
Tim Stewart
efe9b3d459 Process FEC and DTMF on Voice frames followed by Sync frame
Rather than skipping FEC recalculation and DTMF blanking on Voice
frames that do not have a corresponding mini-header (i.e. Voice frames
followed by a Sync frame), set aside the frame's data.  The data is
processed and submitted to the modem/network during the next
iteration, once the presence of DV Fast Data can be determined.
2020-11-29 16:26:32 -05:00
Tim Stewart
8874d1262b Detect DV Fast Data on a per-frame basis
This commit adds a maybeFixupVoiceFrame() function that is used by
both the RF and Net code to manage FEC regeneration and DTMF blanking
in voice frames.

The presence of Fast Data is discovered by reading the mini-header in
every second data frame.  If found, FEC regeneration and DTMF blanking
are disabled for the current and next voice frames.

An exception is voice frames that have a sync frame instead of a data
frame.  This commit always disables FEC regeneration and DTMF blanking
for these frames.  A later commit will add support for these frames by
setting aside the voice frame until the next data frame can be read.

This commit also includes a number of debugging statements that will
be removed in a later commit.
2020-11-29 16:12:58 -05:00
Tim Stewart
8656aaedaa Add back desired changes that were reverted 2020-11-27 18:36:39 -05:00
Tim Stewart
1fd1a4f6d1 Revert "First attempt at detecting D-Star data frames, Kenwood and Icom."
This reverts commit 3362e29b62.
2020-11-27 18:01:02 -05:00
Tim Stewart
7aabb96351 Revert "Fix a bug and add a second Icom D-Star fast data mode identifier."
This reverts commit 18398efe97.
2020-11-27 17:51:22 -05:00
Tim Stewart
821db7910a Revert "Regenerate the data mode markers."
This reverts commit 54fbacb487.
2020-11-27 17:51:06 -05:00
Tim Stewart
4f0f0fea66 Revert "Don't insert silence on lost D-Star fast data."
This reverts commit 1bd814a079.
2020-11-27 17:50:47 -05:00
Tim Stewart
b8ae0febb0 Revert "New way to detect D-Star fast data mode."
This reverts commit a9b7179d13.
2020-11-27 17:47:51 -05:00
Tim Stewart
2d2b736c54 Revert "Don't forget to descramble the byte first."
This reverts commit 16bf9d5745.
2020-11-27 17:47:24 -05:00
Tim Stewart
449ca905ee Revert "Place the scrambled null data regeneration into the right place."
This reverts commit 59cb07329d.
2020-11-27 17:47:04 -05:00
Tim Stewart
fcad5ee0d2 Revert "Only test the slow data type in the correct place."
This reverts commit ff0082b18b.
2020-11-27 17:46:19 -05:00
Tim Stewart
bbbfbbbfad Revert "Simplify the D-Star sequence number processing."
This reverts commit 99d4a9bc51.
2020-11-27 17:45:19 -05:00
Tim Stewart
7ea37fc5e9 Revert "Fix the silence insertion for D-Star."
This reverts commit 9cc2bfaaec.
2020-11-27 17:44:33 -05:00
Tim Stewart
c94f4f5d4a Revert "Check the guard byte on fast data as well as the mini header."
This reverts commit 317bda0177.
2020-11-27 17:14:31 -05:00
Tim Stewart
a87449bf51 Revert "Loosen fast data admission criteria."
This reverts commit 6d719353c6.
2020-11-27 17:14:10 -05:00
Tim Stewart
59b8b5d623 Revert "Remove redundant code."
This reverts commit f88c9826a7.
2020-11-27 17:13:57 -05:00
Tim Stewart
da92771afa Revert "Remove more redundant code."
This reverts commit c3c5fe1a5a.
2020-11-27 17:13:37 -05:00
Jonathan Naylor
ef9fedcc01 Fix the logging messages for late entry. 2020-11-26 14:25:45 +00:00
Jonathan Naylor
ec80e9553a Fully implement the latest M17 specification. 2020-11-26 13:47:47 +00:00
Jonathan Naylor
67b93d6310 Partial work supporting the latest M17 specification. 2020-11-26 11:30:16 +00:00
Jonathan Naylor
8d31808ae8 Increase serial port speed to 460800. 2020-11-24 16:24:32 +00:00
Jonathan Naylor
3968786044 Merge branch 'master' into M17_AX25_FM 2020-11-24 09:27:30 +00:00
Jonathan Naylor
1b0caaae23 Update README.md 2020-11-24 09:27:01 +00:00
Jonathan Naylor
8e857edda2 Merge branch 'M17_AX25_FM' of https://github.com/g4klx/MMDVMHost into M17_AX25_FM 2020-11-16 16:58:33 +00:00
Jonathan Naylor
43733df7a4 Add M17 to the OLED display, even though it does say NXDN! 2020-11-16 16:56:36 +00:00
Jonathan Naylor
302a23b6e6 Add M17 to the OLED display. 2020-11-13 16:01:46 +00:00
Jonathan Naylor
2618a14ae5 Handle returned modem serial data properly. 2020-11-13 14:56:39 +00:00
Jonathan Naylor
a98f65e3aa Rename the modem data type MMDVM_SERIAL to MMDVM_SERIAL_DATA to match
the modem.
2020-11-13 12:10:41 +00:00
Jonathan Naylor
021c0fea4d Fix M17 bug spotted by nostar. 2020-11-13 09:24:37 +00:00
Jonathan Naylor
bb5e20538d Change the M17 logging slightly. 2020-11-11 18:35:52 +00:00
Jonathan Naylor
c1bb4c825e Change M17 enable bit position. 2020-11-11 11:47:46 +00:00
Jonathan Naylor
644351db4f Merge branch 'master' into M17_AX25_FM 2020-11-11 11:43:59 +00:00
Jonathan Naylor
ffe0fd0cbb Change the M17 enable bit position for version 1 protocol. 2020-11-10 16:58:03 +00:00
Jonathan Naylor
067c1039d1 Merge branch 'M17_AX25_FM' of https://github.com/g4klx/MMDVMHost into M17_AX25_FM 2020-11-10 13:51:03 +00:00
Jonathan Naylor
8c65b1c1d9 Remove the out of date ISSUES.txt 2020-11-10 13:50:30 +00:00
Jonathan Naylor
a4ba00f567 Small cleanups. 2020-11-10 11:45:13 +00:00
Jonathan Naylor
eece693f05 Remove support for the Hobbytronics TFT display. 2020-11-10 10:08:59 +00:00
Jonathan Naylor
dbd779a6d3 Fix obvious crash issue. 2020-11-10 10:01:05 +00:00
Jonathan Naylor
f89145b772 Remove support for the UMP (sob). 2020-11-10 09:58:10 +00:00
Jonathan Naylor
f1dda251c3 Display the modes in the log more nicely. 2020-11-10 09:40:54 +00:00
Jonathan Naylor
3d489096cd Add the modem capabilities decoding. 2020-11-09 16:23:33 +00:00
Jonathan Naylor
304143d4a6 Handle protocol versions 1 and 2. 2020-11-09 14:22:43 +00:00
Jonathan Naylor
827a0cb72f Allow the FM Network code to build on Windows. 2020-11-09 12:17:06 +00:00
Jonathan Naylor
d1942fcb43 Merge branch 'master' into M17_AX25_FM 2020-11-09 12:05:18 +00:00
Jonathan Naylor
a57397e274 Merge branch 'AX25_FM' into M17_AX25_FM 2020-11-06 15:43:12 +00:00
Jonathan Naylor
d8677b4028 Merge branch 'M17' into M17_AX25_FM 2020-11-06 11:37:33 +00:00
Jonathan Naylor
06ba457da2 Merge branch 'SimpleDMR' into AX25_FM 2020-10-31 21:45:48 +00:00
Jonathan Naylor
ff8c9edb49 Merge branch 'SimpleDMR' into AX25_FM 2020-10-31 21:05:17 +00:00
Jonathan Naylor
098cc74c9e Merge branch 'SimpleDMR' into AX25_FM 2020-10-30 13:57:58 +00:00
Jonathan Naylor
e2a4ccfc05 Merge branch 'SimpleDMR' into AX25_FM 2020-10-13 10:12:58 +01:00
Jonathan Naylor
35e9a2a830 Merge branch 'SimpleDMR' into AX25_FM 2020-10-07 10:33:06 +01:00
Jonathan Naylor
2fc62e0e7a Merge branch 'SimpleDMR' into AX25_FM 2020-10-06 10:51:15 +01:00
Jonathan Naylor
7c81128d77 Merge branch 'SimpleDMR' into AX25_FM 2020-10-05 12:50:52 +01:00
Jonathan Naylor
20e8d4079d Merge branch 'SimpleDMR' into AX25_FM 2020-09-25 12:35:34 +01:00
Jonathan Naylor
3f125f055c Merge branch 'SimpleDMR' into AX25_FM 2020-09-24 14:05:18 +01:00
Jonathan Naylor
6d313fce51 Merge branch 'SimpleDMR' into AX25_FM 2020-09-20 21:32:11 +01:00
Jonathan Naylor
c2a1aeb581 Merge branch 'SimpleDMR' into AX25_FM 2020-09-08 10:11:38 +01:00
Jonathan Naylor
5a3c61644c Fix compilation. 2020-09-06 14:49:52 +01:00
Jonathan Naylor
90e7b58b92 Merge branch 'SimpleDMR' into AX25_FM 2020-09-06 14:30:26 +01:00
Jonathan Naylor
98b1e6478b Merge branch 'SimpleDMR' into AX25_FM 2020-09-06 14:27:55 +01:00
Jonathan Naylor
2502ee94d7 Merge branch 'SimpleDMR' into AX25_FM 2020-09-03 12:10:01 +01:00
Jonathan Naylor
d5bbd77304 Merge branch 'master' into AX25_FM 2020-08-14 09:34:30 +01:00
Jonathan Naylor
739550885b Merge branch 'master' into AX25_FM 2020-08-10 14:31:53 +01:00
Jonathan Naylor
97a10c7e30 Merge branch 'master' into AX25_FM 2020-08-09 19:40:37 +01:00
Jonathan Naylor
82ea772269 Merge branch 'master' into AX25_FM 2020-08-09 15:09:46 +01:00
Jonathan Naylor
8a6f14e6e6 Merge branch 'master' into AX25_FM 2020-08-05 15:00:23 +01:00
Jonathan Naylor
3776ed2b1b Merge branch 'master' into AX25_FM 2020-08-04 10:39:23 +01:00
Jonathan Naylor
11c8403829 Merge branch 'master' into AX25_FM 2020-08-04 10:04:47 +01:00
Jonathan Naylor
f35ab6230b
Merge pull request #619 from F4FXL/AX25_FM
systemd install
2020-08-02 13:30:03 +01:00
Geoffrey Merck
efcecd69d3 Merge remote-tracking branch 'upstream/AX25_FM' into AX25_FM 2020-07-30 19:53:43 +02:00
Jonathan Naylor
0579b4387a Add the noise squelch configuration items. 2020-07-28 14:22:26 +01:00
Geoffrey Merck
b4cf7a4ad4 Merge branch 'AX25_FM' of https://github.com/F4FXL/MMDVMHost into AX25_FM 2020-07-27 14:53:56 +02:00
Geoffrey Merck
c2c1266233 Correct typo 2020-07-27 14:53:36 +02:00
Geoffrey Merck
7aec7eefcb Add install service to othe rmakefiles 2020-07-27 14:53:36 +02:00
Geoffrey Merck
869edd33fd fix typo in executable path 2020-07-27 14:53:36 +02:00
Geoffrey Merck
f64371b4c8 delete unit file on uninstall 2020-07-27 14:53:36 +02:00
Geoffrey Merck
d4e6f2cb5e add install targets 2020-07-27 14:53:36 +02:00
Geoffrey Merck
354e808ccb Add systemd unit 2020-07-27 14:53:36 +02:00
Geoffrey Merck
8f59691738 Moved existing scripts to pi-star folder 2020-07-27 14:53:36 +02:00
Geoffrey Merck
5703758116 Merge remote-tracking branch 'upstream/AX25_FM' into AX25_FM 2020-07-27 11:58:54 +02:00
Jonathan Naylor
15c21de416 Fix complilation on Linux. 2020-07-27 10:58:32 +01:00
Jonathan Naylor
da077c73f8 Allow the FM network sample rate to be specified. 2020-07-27 10:38:07 +01:00
Geoffrey Merck
801ba04e0d Correct typo 2020-07-20 09:08:58 +02:00
Geoffrey Merck
fa7be67d9c Add install service to othe rmakefiles 2020-07-20 08:36:22 +02:00
Geoffrey Merck
49a4e2ad0d fix typo in executable path 2020-07-20 08:13:27 +02:00
Geoffrey Merck
bb1a542fe1 delete unit file on uninstall 2020-07-20 08:06:29 +02:00
Geoffrey Merck
ba9c97289f add install targets 2020-07-18 18:07:21 +02:00
Geoffrey Merck
76033dd301 Add systemd unit 2020-07-18 18:07:10 +02:00
Geoffrey Merck
87b7a7c48a Moved existing scripts to pi-star folder 2020-07-18 17:36:54 +02:00
Jonathan Naylor
c80894ddaa Fix the configuration source file. 2020-07-15 12:31:48 +01:00
Jonathan Naylor
9c4d2f46bb Merge branch 'master' into AX25_FM 2020-07-15 12:15:07 +01:00
Jonathan Naylor
1e833d78cf Remove KerchunkTX. 2020-07-07 17:54:46 +01:00
Jonathan Naylor
e9a128ebdc
Merge pull request #618 from F4FXL/AX25_FM
Fix FM buffer underrun
2020-07-06 19:01:58 +01:00
Geoffrey Merck
009f50a913 Write FM_EOT as uint 2020-07-06 19:52:16 +02:00
Geoffrey Merck
4d6f64a51e Write FM control length as integer, since we always read it as int 2020-07-06 19:44:55 +02:00
Geoffrey Merck
b8f0525dcb Merge branch 'AX25_FM' of https://github.com/F4FXL/MMDVMHost into AX25_FM 2020-07-06 19:15:55 +02:00
Geoffrey Merck
40a974d7cb Revert "Fix buffer underrun in FM"
This reverts commit 192e8e2435.
2020-07-06 19:14:12 +02:00
Geoffrey Merck
41dc96affe Fix buffer underrun in FM 2020-07-06 19:14:12 +02:00
Jonathan Naylor
954231ccbc Bump the version date. 2020-07-06 10:22:00 +01:00
Jonathan Naylor
3cc77c5c57 Fix bug in bug. 2020-07-06 10:20:40 +01:00
Jonathan Naylor
f42f6f07c4 Fix bug. 2020-07-06 10:16:06 +01:00
Geoffrey Merck
183430593f Revert "Fix buffer underrun in FM"
This reverts commit 192e8e2435.
2020-07-04 14:21:11 +02:00
Geoffrey Merck
192e8e2435 Fix buffer underrun in FM 2020-07-04 13:04:24 +02:00
Jonathan Naylor
ba1b6a8751 Merge branch 'AX25' into AX25_FM 2020-07-02 16:38:53 +01:00
Jonathan Naylor
8c52246be8 Merge branch 'master' into AX25 2020-07-02 13:21:18 +01:00
Jonathan Naylor
2bc6dd6ca9 Merge branch 'AX25' into AX25_FM 2020-07-01 13:40:35 +01:00
Jonathan Naylor
fb6fb70ffb Merge branch 'master' into AX25 2020-07-01 13:40:15 +01:00
Jonathan Naylor
4d3869172d Merge branch 'AX25' into AX25_FM 2020-07-01 13:17:44 +01:00
Jonathan Naylor
e106df3cdf Merge branch 'master' into AX25 2020-07-01 13:17:22 +01:00
Jonathan Naylor
d2be920254 Add AX25 SlotTime and P-Persist parameters. 2020-07-01 10:59:46 +01:00
Jonathan Naylor
d0fa27bfd1
Merge pull request #610 from F4FXL/AX25_FM
Fix KISS
2020-06-30 22:23:56 +01:00
Geoffrey Merck
5f0ee739e1 Use correct file 2020-06-30 23:19:26 +02:00
Geoffrey Merck
4ae141f594 Fix KISS 2020-06-30 23:11:00 +02:00
Geoffrey Merck
22427cd348 Merge remote-tracking branch 'upstream/AX25_FM' into AX25_FM 2020-06-30 20:57:50 +02:00
Jonathan Naylor
aa8b78a311 Refactor the Modem class hierarchy. 2020-06-30 12:35:03 +01:00
Jonathan Naylor
14413963d9 Merge branch 'AX25' into AX25_FM 2020-06-30 11:45:58 +01:00
Jonathan Naylor
e339de8fee Merge branch 'master' into AX25 2020-06-30 11:40:55 +01:00
Jonathan Naylor
8383c7d320 Clean up the Makefiles. 2020-06-29 12:11:01 +01:00
Jonathan Naylor
5dbf916db0 Fix Windows compilation. 2020-06-29 11:53:54 +01:00
Jonathan Naylor
4ee32a506f Fix the NullModem. 2020-06-29 11:46:30 +01:00
Jonathan Naylor
8291470698 Merge branch 'AX25' into AX25_FM 2020-06-29 11:44:14 +01:00
Jonathan Naylor
35a283d7b4 Merge branch 'master' into AX25 2020-06-29 11:26:17 +01:00
Jonathan Naylor
fab4dc227e Fix NullModem.h 2020-06-28 15:41:41 +01:00
Jonathan Naylor
30098a5d38 Fix SerialController being used by PseudoTTYController. 2020-06-28 15:23:56 +01:00
Geoffrey Merck
d4c7f20696 Fix assertion in PseudoTTY 2020-06-28 11:22:54 +02:00
Jonathan Naylor
93a0b9793b Update the other Makefiles. 2020-06-27 23:01:00 +01:00
Jonathan Naylor
648426f44c Allow Windows compilation. 2020-06-27 22:58:37 +01:00
Jonathan Naylor
97f1ebb25f Convert TXTwist to TXDelay. 2020-06-27 22:47:54 +01:00
Jonathan Naylor
d1a809808b Rationalise the pseudo tty handling. 2020-06-27 22:33:24 +01:00
Jonathan Naylor
bdb1c49bae
Merge pull request #608 from F4FXL/AX25_FM
Make pty work
2020-06-26 20:25:06 +01:00
Geoffrey Merck
f151ca6c1a Make pty work 2020-06-26 21:17:14 +02:00
Jonathan Naylor
e164538b09 Fix compilation bugs. 2020-06-25 21:23:43 +01:00
Jonathan Naylor
cb51a14575 Create a pseudo TTY for the AX25 Network. 2020-06-25 21:17:38 +01:00
Jonathan Naylor
371661bd11
Merge pull request #607 from F4FXL/AX25_FM
add missing files in makefiles
2020-06-25 20:49:43 +01:00
Geoffrey Merck
6321563496 add missing files in makefiles 2020-06-25 21:13:28 +02:00
Jonathan Naylor
ab3705e8e0
Merge pull request #606 from F4FXL/AX25_FM
add missing files in makefile
2020-06-25 19:42:55 +01:00
Geoffrey Merck
aec1ae74f7 add missing files in makefile 2020-06-25 20:40:13 +02:00
Jonathan Naylor
2953ce85a0 Merge branch 'FM_Ext' into AX25_FM 2020-06-25 13:41:19 +01:00
Jonathan Naylor
1c6a48a8e1 Merge branch 'master' into AX25 2020-06-25 09:56:31 +01:00
Jonathan Naylor
28d64e7c3d Merge branch 'master' into AX25 2020-06-25 09:44:55 +01:00
Jonathan Naylor
96a8ec0e35 Change the maximum packet length. 2020-06-24 13:22:55 +01:00
Jonathan Naylor
d8716adc43 Change the free space handling for AX25. 2020-06-24 11:18:12 +01:00
Jonathan Naylor
92ceba052a Add AX.25 transmit functionality to the modem handler. 2020-06-21 21:16:31 +01:00
Jonathan Naylor
c026471aec Start the AX.25 transmit path development. 2020-06-21 18:53:38 +01:00
Jonathan Naylor
27c9ad43ec Add KISS receive. 2020-06-21 17:22:27 +01:00
Jonathan Naylor
38f59236ae Add the KISS encoding. 2020-06-21 14:28:40 +01:00
Jonathan Naylor
692d6519db Add the AX.25 modem parameters and start reworking the AX,25 RX
processing.
2020-06-21 14:15:37 +01:00
Jonathan Naylor
fe77cbd68c Add the extra AX.25 parameters. 2020-06-20 21:28:39 +01:00
Jonathan Naylor
f936a6c5b6 Add the Kerchunk TX parameter. 2020-06-20 20:44:02 +01:00
Jonathan Naylor
d0878bbf7e Add new AX.25 parameters. 2020-06-20 20:06:48 +01:00
Jonathan Naylor
e0f800ba98 Handle the new larger frame type. 2020-06-19 15:09:21 +01:00
Jonathan Naylor
d9e2940f08 Add AX.25 packet tracking. 2020-06-18 12:51:13 +01:00
Jonathan Naylor
b3398710bc Merge branch 'master' into AX25 2020-06-17 15:48:20 +01:00
Jonathan Naylor
d409700a31 X25 cleanups. 2020-06-09 14:32:05 +01:00
Jonathan Naylor
dbe04c3c2f Initial code for AX.25 support. 2020-06-08 16:33:20 +01:00
Jonathan Naylor
85751e0c51
Merge pull request #596 from F4FXL/FM_Ext
Use full lenght for FM frames
2020-05-31 21:13:50 +01:00
Geoffrey Merck
f01fc3e9fc Ensure Modem FM frames are always 168 samples 2020-05-31 21:42:35 +02:00
Geoffrey Merck
82c6f717cf Remove 250 length check 2020-05-31 20:35:04 +02:00
Jonathan Naylor
f18e253eac
Merge pull request #595 from F4FXL/FM_Ext
Make FM Network work
2020-05-31 11:28:15 +01:00
Geoffrey Merck
17b49fde88 Typo 2020-05-31 12:19:20 +02:00
Geoffrey Merck
aa5eeb3554 Merge remote-tracking branch 'upstream/FM_Ext' into FM_Ext 2020-05-31 12:15:36 +02:00
Geoffrey Merck
97a35e69a4 clean up 2020-05-31 12:14:16 +02:00
Geoffrey Merck
af6b7d79da Adjust emphasis gains 2020-05-31 11:43:35 +02:00
Geoffrey Merck
bd1aa20803 Simplify writeModem, only 2 loops 2020-05-31 11:37:18 +02:00
Geoffrey Merck
015edf9b81 Simplify readmodem, only one loop 2020-05-31 11:01:53 +02:00
Geoffrey Merck
98cd2404f5 Use GNU Radio emphasis filters, add filters generation scripts 2020-05-31 09:17:45 +02:00
Geoffrey Merck
eef364b1a9 Enable Pre emphasis 2020-05-31 08:38:17 +02:00
Geoffrey Merck
8d4241d154 Reenable RTS 2020-05-31 08:20:39 +02:00
Geoffrey Merck
409e0de721 Send correct number of bytes 2020-05-31 07:03:01 +02:00
Geoffrey Merck
c2187fd624 Add 460800 serial speed 2020-05-30 20:19:46 +02:00
Geoffrey Merck
75d5083f8e fixe network byte ordering, change audio dump to dumep 16 bit samples 2020-05-30 19:59:15 +02:00
Geoffrey Merck
0b8a9a1a4c Increase FM TX Buffer size 2020-05-30 07:32:09 +02:00
Geoffrey Merck
a28aa77927 Add deemphasis and remove CTCSS, emphasis temp deactivated 2020-05-30 07:31:48 +02:00
Geoffrey Merck
02d1e2f0ef Add CTCSS removal 2020-05-24 19:07:59 +02:00
Jonathan Naylor
1caffc1dad Small cleanups. 2020-05-24 14:26:24 +01:00
Jonathan Naylor
12e58d5440
Merge pull request #593 from F4FXL/FM_Ext
FM Ext improvements
2020-05-24 10:10:25 +01:00
Geoffrey Merck
8b31cb34ff Use stdio instead of iostream, fix file not properly closed 2020-05-24 10:47:11 +02:00
Geoffrey Merck
c0a9bb81a3 Fix sample packing 2020-05-24 08:00:27 +02:00
Geoffrey Merck
3b7d4d486e Merge branch 'FM_Ext' of https://github.com/F4FXL/MMDVMHost into FM_Ext 2020-05-24 07:49:44 +02:00
Geoffrey Merck
ed3299a513 Fix unpack, add audio dump 2020-05-24 07:49:13 +02:00
Geoffrey Merck
ad843e7283 do not write EOT when network is not set 2020-05-24 07:49:12 +02:00
Jonathan Naylor
af34d9abc3 Linux compile fix. 2020-05-23 16:54:11 +01:00
Jonathan Naylor
0b185a0900 Clean up the I2C controller code. 2020-05-23 16:49:21 +01:00
Jonathan Naylor
303a0163d3 Make the modem speed dynamic with a default of 115200. 2020-05-23 13:03:55 +01:00
Geoffrey Merck
1290f9c49e do not write EOT when network is not set 2020-05-20 18:07:57 +02:00
Jonathan Naylor
9d08f1605c
Merge pull request #591 from F4FXL/FM_Ext
Add FM Poll network message
2020-05-16 17:08:09 +01:00
Geoffrey Merck
578ef5a3d4 Handle poll message 2020-05-16 17:45:24 +02:00
Geoffrey Merck
23e92af6fa Add Poll message 2020-05-16 17:40:42 +02:00
Geoffrey Merck
734af9453c Fix message for FM EOT 2020-05-16 17:16:05 +02:00
Jonathan Naylor
a66f4c6188 Add an FM EOT network message. 2020-05-16 13:09:28 +01:00
Jonathan Naylor
283b54c46a
Merge pull request #590 from F4FXL/FM_Ext
Add FM EOT
2020-05-16 12:56:21 +01:00
Geoffrey Merck
dc41acbd21 Merge remote-tracking branch 'upstream/FM_Ext' into FM_Ext 2020-05-15 20:21:39 +02:00
Geoffrey Merck
b5316907ad Handle FM EOT 2020-05-15 20:19:57 +02:00
Jonathan Naylor
56619166b6
Merge pull request #589 from F4FXL/FM_Ext
Tighten code, enable emphasis
2020-05-14 22:18:53 +01:00
Geoffrey Merck
d96e2204bf Initialize all members 2020-05-14 22:02:05 +02:00
Geoffrey Merck
2165b38379 Make sur we always return even length 2020-05-14 22:01:38 +02:00
Geoffrey Merck
c413c3a855 Tighten code, reactivate emphasis 2020-05-14 22:01:10 +02:00
Jonathan Naylor
9e52db3ef3 Merge branch 'FM' into FM_Ext 2020-05-13 12:06:35 +01:00
Jonathan Naylor
8ac6a1b208 Merge branch 'FM' into FM_Ext 2020-05-12 16:24:42 +01:00
Jonathan Naylor
143652b7f2
Merge pull request #586 from F4FXL/FM_Ext
Some network stuff, still WIP
2020-05-11 17:53:50 +01:00
Geoffrey Merck
cbcbe4c56a Used fixed length array 2020-05-11 18:38:07 +02:00
Geoffrey Merck
f9ccb7c876 Merge branch 'FM_Ext' of https://github.com/F4FXL/MMDVMHost into FM_Ext 2020-05-11 16:46:59 +02:00
Geoffrey Merck
bc6f832b7d Loop using correct length 2020-05-11 16:46:38 +02:00
Jonathan Naylor
039ef44a63 Fix the setMode(MODE_FM) command. 2020-05-11 15:32:39 +01:00
Geoffrey Merck
bc3f98f19c Merge branch 'FM_Ext' of https://github.com/F4FXL/MMDVMHost into FM_Ext 2020-05-11 14:40:14 +02:00
Geoffrey Merck
7bca857852 Loop using correct length 2020-05-11 14:39:24 +02:00
Jonathan Naylor
29b36a66f8 Use more conventional handling of FM mode timing. 2020-05-11 12:59:28 +01:00
Geoffrey Merck
6b4fe7dd33 Loop using correct length 2020-05-10 22:08:36 +02:00
Jonathan Naylor
7be89b91ea
Merge pull request #585 from F4FXL/FM_Ext
Handle modem FM audio
2020-05-10 21:07:14 +01:00
Geoffrey Merck
008bfee6b9 Merge remote-tracking branch 'upstream/FM_Ext' into FM_Ext 2020-05-10 22:03:25 +02:00
Geoffrey Merck
0178ba0aba Buffer incoming modem audio 2020-05-10 21:49:11 +02:00
Jonathan Naylor
3299913003
Merge pull request #584 from F4FXL/FM_Ext
Fix crash when network is disabled
2020-05-10 10:57:10 +01:00
Geoffrey Merck
33fedb781d Handle no network 2020-05-10 10:31:53 +02:00
Jonathan Naylor
ab437c0866 Merge branch 'FM' into FM_Ext 2020-05-09 12:48:08 +01:00
Jonathan Naylor
467140dbf8 VS2019 fixes. 2020-05-09 12:41:37 +01:00
Jonathan Naylor
2a8e1ce9f4 Merge branch 'FM' into FM_Ext 2020-05-09 12:36:44 +01:00
Jonathan Naylor
47862e0682
Merge pull request #581 from F4FXL/FM_Ext
Add Pre and De emphasis
2020-05-08 20:24:59 +01:00
Geoffrey Merck
e28dfe79dd Fix typo in file name 2020-05-08 21:23:32 +02:00
Geoffrey Merck
bc22709abb Add preemphasis and deemphasis 2020-05-08 21:16:02 +02:00
Geoffrey Merck
dc9e6ade23 Add filter 2020-05-08 20:41:57 +02:00
Jonathan Naylor
9a2dd6a5e6
Merge pull request #580 from F4FXL/FM_Ext
Pack and unpack using shifting and masking
2020-05-08 16:33:47 +01:00
Geoffrey Merck
c48f45d2da remove union 2020-05-08 17:30:22 +02:00
Geoffrey Merck
93652c764e Using correct types 2020-05-08 17:05:04 +02:00
Geoffrey Merck
8cdc1ffe7f Pack and unpack using shifting and masking 2020-05-08 16:41:06 +02:00
Jonathan Naylor
5e887a95c5 Merge branch 'FM_Ext' of https://github.com/g4klx/MMDVMHost into FM_Ext 2020-05-08 13:13:01 +01:00
Jonathan Naylor
7ae77a01a9 Add the data packing and unpacking code. 2020-05-08 13:12:37 +01:00
phl0
51a1e2bb9c
Fix FM network section detection in Conf.cpp 2020-05-08 13:17:29 +02:00
Jonathan Naylor
c2ca65f889 Add more parameters to the external ack data. 2020-05-07 22:03:57 +01:00
Jonathan Naylor
b3d287965f Create a dummy FM Control class. 2020-05-07 21:49:18 +01:00
Jonathan Naylor
bc791577e7 Beginnings of FM networking. 2020-05-07 16:08:58 +01:00
210 changed files with 4704 additions and 29866 deletions

1
.gitignore vendored
View file

@ -17,3 +17,4 @@ RemoteCommand
.vs .vs
*.ambe *.ambe
GitVersion.h GitVersion.h
.vscode

80
.vscode/settings.json vendored Normal file
View file

@ -0,0 +1,80 @@
{
"files.associations": {
"fstream": "cpp",
"cstring": "cpp",
"string": "cpp",
"cctype": "cpp",
"clocale": "cpp",
"cmath": "cpp",
"cstdarg": "cpp",
"cstddef": "cpp",
"cstdio": "cpp",
"cstdlib": "cpp",
"ctime": "cpp",
"cwchar": "cpp",
"cwctype": "cpp",
"any": "cpp",
"array": "cpp",
"atomic": "cpp",
"hash_map": "cpp",
"strstream": "cpp",
"bit": "cpp",
"*.tcc": "cpp",
"bitset": "cpp",
"cfenv": "cpp",
"chrono": "cpp",
"codecvt": "cpp",
"compare": "cpp",
"complex": "cpp",
"concepts": "cpp",
"condition_variable": "cpp",
"cstdint": "cpp",
"deque": "cpp",
"forward_list": "cpp",
"list": "cpp",
"map": "cpp",
"set": "cpp",
"unordered_map": "cpp",
"unordered_set": "cpp",
"vector": "cpp",
"exception": "cpp",
"algorithm": "cpp",
"functional": "cpp",
"iterator": "cpp",
"memory": "cpp",
"memory_resource": "cpp",
"numeric": "cpp",
"optional": "cpp",
"random": "cpp",
"ratio": "cpp",
"source_location": "cpp",
"string_view": "cpp",
"system_error": "cpp",
"tuple": "cpp",
"type_traits": "cpp",
"utility": "cpp",
"future": "cpp",
"initializer_list": "cpp",
"iomanip": "cpp",
"iosfwd": "cpp",
"iostream": "cpp",
"istream": "cpp",
"limits": "cpp",
"mutex": "cpp",
"new": "cpp",
"numbers": "cpp",
"ostream": "cpp",
"semaphore": "cpp",
"shared_mutex": "cpp",
"sstream": "cpp",
"stdexcept": "cpp",
"stop_token": "cpp",
"streambuf": "cpp",
"thread": "cpp",
"cinttypes": "cpp",
"typeindex": "cpp",
"typeinfo": "cpp",
"valarray": "cpp",
"variant": "cpp"
}
}

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2010,2014,2016,2018 by Jonathan Naylor G4KLX * Copyright (C) 2010,2014,2016,2018,2021 by Jonathan Naylor G4KLX
* Copyright (C) 2016 Mathias Weyland, HB9FRV * Copyright (C) 2016 Mathias Weyland, HB9FRV
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
@ -20,6 +20,7 @@
#include "Golay24128.h" #include "Golay24128.h"
#include "Hamming.h" #include "Hamming.h"
#include "AMBEFEC.h" #include "AMBEFEC.h"
#include "Utils.h"
#include <cstdio> #include <cstdio>
#include <cassert> #include <cassert>
@ -795,34 +796,31 @@ unsigned int CAMBEFEC::regenerateDStar(unsigned int& a, unsigned int& b) const
unsigned int orig_a = a; unsigned int orig_a = a;
unsigned int orig_b = b; unsigned int orig_b = b;
unsigned int data = CGolay24128::decode24128(a); unsigned int data;
bool valid1 = CGolay24128::decode24128(a, data);
a = CGolay24128::encode24128(data); if (!valid1)
return 10U;
// The PRNG // The PRNG
unsigned int p = PRNG_TABLE[data]; unsigned int p = PRNG_TABLE[data];
b ^= p; b ^= p;
unsigned int datb = CGolay24128::decode24128(b); unsigned int datb;
bool valid2 = CGolay24128::decode24128(b, datb);
if (!valid2)
return 10U;
a = CGolay24128::encode24128(data);
b = CGolay24128::encode24128(datb); b = CGolay24128::encode24128(datb);
b ^= p; b ^= p;
unsigned int errsA = 0U, errsB = 0U;
unsigned int v = a ^ orig_a; unsigned int v = a ^ orig_a;
while (v != 0U) { unsigned int errsA = CUtils::countBits(v);
v &= v - 1U;
errsA++;
}
v = b ^ orig_b; v = b ^ orig_b;
while (v != 0U) { unsigned int errsB = CUtils::countBits(v);
v &= v - 1U;
errsB++;
}
return errsA + errsB; return errsA + errsB;
} }
@ -832,7 +830,14 @@ unsigned int CAMBEFEC::regenerateDMR(unsigned int& a, unsigned int& b, unsigned
unsigned int orig_a = a; unsigned int orig_a = a;
unsigned int orig_b = b; unsigned int orig_b = b;
unsigned int data = CGolay24128::decode24128(a); unsigned int data;
bool valid = CGolay24128::decode24128(a, data);
if (!valid) {
a = 0xF00292U;
b = 0x0E0B20U;
c = 0x000000U;
return 10U; // An invalid A block gives an error count of 10
}
a = CGolay24128::encode24128(data); a = CGolay24128::encode24128(data);
@ -847,19 +852,11 @@ unsigned int CAMBEFEC::regenerateDMR(unsigned int& a, unsigned int& b, unsigned
b ^= p; b ^= p;
unsigned int errsA = 0U, errsB = 0U;
unsigned int v = a ^ orig_a; unsigned int v = a ^ orig_a;
while (v != 0U) { unsigned int errsA = CUtils::countBits(v);
v &= v - 1U;
errsA++;
}
v = b ^ orig_b; v = b ^ orig_b;
while (v != 0U) { unsigned int errsB = CUtils::countBits(v);
v &= v - 1U;
errsB++;
}
if (errsA >= 4U || ((errsA + errsB) >= 6U && errsA >= 2U)) { if (errsA >= 4U || ((errsA + errsB) >= 6U && errsA >= 2U)) {
a = 0xF00292U; a = 0xF00292U;

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2016,2018,2020 by Jonathan Naylor G4KLX * Copyright (C) 2016,2018,2020,2021 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
@ -76,20 +76,6 @@ void CCASTInfo::setQuitInt()
{ {
} }
void CCASTInfo::setFMInt()
{
}
void CCASTInfo::writeDStarInt(const char* my1, const char* my2, const char* your, const char* type, const char* reflector)
{
if (m_modem != NULL)
m_modem->writeDStarInfo(my1, my2, your, type, reflector);
}
void CCASTInfo::clearDStarInt()
{
}
void CCASTInfo::writeDMRInt(unsigned int slotNo, const std::string& src, bool group, const std::string& dst, const char* type) void CCASTInfo::writeDMRInt(unsigned int slotNo, const std::string& src, bool group, const std::string& dst, const char* type)
{ {
if (m_modem != NULL) if (m_modem != NULL)
@ -100,56 +86,6 @@ void CCASTInfo::clearDMRInt(unsigned int slotNo)
{ {
} }
void CCASTInfo::writeFusionInt(const char* source, const char* dest, unsigned char dgid, const char* type, const char* origin)
{
if (m_modem != NULL)
m_modem->writeYSFInfo(source, dest, dgid, type, origin);
}
void CCASTInfo::clearFusionInt()
{
}
void CCASTInfo::writeP25Int(const char* source, bool group, unsigned int dest, const char* type)
{
if (m_modem != NULL)
m_modem->writeP25Info(source, group, dest, type);
}
void CCASTInfo::clearP25Int()
{
}
void CCASTInfo::writeNXDNInt(const char* source, bool group, unsigned int dest, const char* type)
{
if (m_modem != NULL)
m_modem->writeNXDNInfo(source, group, dest, type);
}
void CCASTInfo::clearNXDNInt()
{
}
void CCASTInfo::writeM17Int(const char* source, const char* dest, const char* type)
{
if (m_modem != NULL)
m_modem->writeM17Info(source, dest, type);
}
void CCASTInfo::clearM17Int()
{
}
void CCASTInfo::writePOCSAGInt(uint32_t ric, const std::string& message)
{
if (m_modem != NULL)
m_modem->writePOCSAGInfo(ric, message);
}
void CCASTInfo::clearPOCSAGInt()
{
}
void CCASTInfo::writeCWInt() void CCASTInfo::writeCWInt()
{ {
} }

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2016,2018,2020 by Jonathan Naylor G4KLX * Copyright (C) 2016,2018,2020,2021 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
@ -25,6 +25,7 @@
#include "NetworkInfo.h" #include "NetworkInfo.h"
#include "Modem.h" #include "Modem.h"
class CCASTInfo : public CDisplay class CCASTInfo : public CDisplay
{ {
public: public:
@ -40,34 +41,15 @@ protected:
virtual void setErrorInt(const char* text); virtual void setErrorInt(const char* text);
virtual void setLockoutInt(); virtual void setLockoutInt();
virtual void setQuitInt(); virtual void setQuitInt();
virtual void setFMInt();
virtual void writeDStarInt(const char* my1, const char* my2, const char* your, const char* type, const char* reflector);
virtual void clearDStarInt();
virtual void writeDMRInt(unsigned int slotNo, const std::string& src, bool group, const std::string& dst, const char* type); virtual void writeDMRInt(unsigned int slotNo, const std::string& src, bool group, const std::string& dst, const char* type);
virtual void clearDMRInt(unsigned int slotNo); virtual void clearDMRInt(unsigned int slotNo);
virtual void writeFusionInt(const char* source, const char* dest, unsigned char dgid, const char* type, const char* origin);
virtual void clearFusionInt();
virtual void writeP25Int(const char* source, bool group, unsigned int dest, const char* type);
virtual void clearP25Int();
virtual void writeNXDNInt(const char* source, bool group, unsigned int dest, const char* type);
virtual void clearNXDNInt();
virtual void writeM17Int(const char* source, const char* dest, const char* type);
virtual void clearM17Int();
virtual void writePOCSAGInt(uint32_t ric, const std::string& message);
virtual void clearPOCSAGInt();
virtual void writeCWInt(); virtual void writeCWInt();
virtual void clearCWInt(); virtual void clearCWInt();
private: private:
CModem* m_modem; CModem* m_modem;
std::string m_ipaddress; std::string m_ipaddress;
}; };

1979
Conf.cpp

File diff suppressed because it is too large Load diff

356
Conf.h
View file

@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2015-2020 by Jonathan Naylor G4KLX * Copyright (C) 2015-2021 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
@ -42,6 +42,12 @@ public:
unsigned int getRXFrequency() const; unsigned int getRXFrequency() const;
unsigned int getTXFrequency() const; unsigned int getTXFrequency() const;
unsigned int getPower() const; unsigned int getPower() const;
float getLatitude() const;
float getLongitude() const;
int getHeight() const;
std::string getLocation() const;
std::string getDescription() const;
std::string getURL() const;
// The Log section // The Log section
unsigned int getLogDisplayLevel() const; unsigned int getLogDisplayLevel() const;
@ -59,14 +65,16 @@ public:
std::string getDMRIdLookupFile() const; std::string getDMRIdLookupFile() const;
unsigned int getDMRIdLookupTime() const; unsigned int getDMRIdLookupTime() const;
// The NXDN Id section
std::string getNXDNIdLookupFile() const;
unsigned int getNXDNIdLookupTime() const;
// The Modem section // The Modem section
std::string getModemPort() const;
std::string getModemProtocol() const; std::string getModemProtocol() const;
unsigned int getModemAddress() const; std::string getModemUARTPort() const;
unsigned int getModemUARTSpeed() const;
std::string getModemI2CPort() const;
unsigned int getModemI2CAddress() const;
std::string getModemModemAddress() const;
unsigned short getModemModemPort() const;
std::string getModemLocalAddress() const;
unsigned short getModemLocalPort() const;
bool getModemRXInvert() const; bool getModemRXInvert() const;
bool getModemTXInvert() const; bool getModemTXInvert() const;
bool getModemPTTInvert() const; bool getModemPTTInvert() const;
@ -87,6 +95,7 @@ public:
float getModemM17TXLevel() const; float getModemM17TXLevel() const;
float getModemPOCSAGTXLevel() const; float getModemPOCSAGTXLevel() const;
float getModemFMTXLevel() const; float getModemFMTXLevel() const;
float getModemAX25TXLevel() const;
std::string getModemRSSIMappingFile() const; std::string getModemRSSIMappingFile() const;
bool getModemUseCOSAsLockout() const; bool getModemUseCOSAsLockout() const;
bool getModemTrace() const; bool getModemTrace() const;
@ -95,28 +104,11 @@ public:
// The Transparent Data section // The Transparent Data section
bool getTransparentEnabled() const; bool getTransparentEnabled() const;
std::string getTransparentRemoteAddress() const; std::string getTransparentRemoteAddress() const;
unsigned int getTransparentRemotePort() const; unsigned short getTransparentRemotePort() const;
unsigned int getTransparentLocalPort() const; unsigned short getTransparentLocalPort() const;
unsigned int getTransparentSendFrameType() const; unsigned int getTransparentSendFrameType() const;
// The UMP section // The DMR section
bool getUMPEnabled() const;
std::string getUMPPort() const;
// The D-Star section
bool getDStarEnabled() const;
std::string getDStarModule() const;
bool getDStarSelfOnly() const;
std::vector<std::string> getDStarBlackList() const;
std::vector<std::string> getDStarWhiteList() const;
bool getDStarAckReply() const;
unsigned int getDStarAckTime() const;
bool getDStarAckMessage() const;
bool getDStarErrorReply() const;
bool getDStarRemoteGateway() const;
unsigned int getDStarModeHang() const;
// The DMR section
bool getDMREnabled() const; bool getDMREnabled() const;
DMR_BEACONS getDMRBeacons() const; DMR_BEACONS getDMRBeacons() const;
unsigned int getDMRBeaconInterval() const; unsigned int getDMRBeaconInterval() const;
@ -136,90 +128,13 @@ public:
unsigned int getDMRModeHang() const; unsigned int getDMRModeHang() const;
DMR_OVCM_TYPES getDMROVCM() const; DMR_OVCM_TYPES getDMROVCM() const;
// The System Fusion section // The DMR Network section
bool getFusionEnabled() const;
bool getFusionLowDeviation() const;
bool getFusionRemoteGateway() const;
bool getFusionSelfOnly() const;
unsigned int getFusionTXHang() const;
unsigned int getFusionModeHang() const;
// The P25 section
bool getP25Enabled() const;
unsigned int getP25Id() const;
unsigned int getP25NAC() const;
bool getP25SelfOnly() const;
bool getP25OverrideUID() const;
bool getP25RemoteGateway() const;
unsigned int getP25TXHang() const;
unsigned int getP25ModeHang() const;
// The NXDN section
bool getNXDNEnabled() const;
unsigned int getNXDNId() const;
unsigned int getNXDNRAN() const;
bool getNXDNSelfOnly() const;
bool getNXDNRemoteGateway() const;
unsigned int getNXDNTXHang() const;
unsigned int getNXDNModeHang() const;
// The M17 section
bool getM17Enabled() const;
bool getM17SelfOnly() const;
bool getM17AllowEncryption() const;
unsigned int getM17TXHang() const;
unsigned int getM17ModeHang() const;
// The POCSAG section
bool getPOCSAGEnabled() const;
unsigned int getPOCSAGFrequency() const;
// The FM Section
bool getFMEnabled() const;
std::string getFMCallsign() const;
unsigned int getFMCallsignSpeed() const;
unsigned int getFMCallsignFrequency() const;
unsigned int getFMCallsignTime() const;
unsigned int getFMCallsignHoldoff() const;
float getFMCallsignHighLevel() const;
float getFMCallsignLowLevel() const;
bool getFMCallsignAtStart() const;
bool getFMCallsignAtEnd() const;
bool getFMCallsignAtLatch() const;
std::string getFMRFAck() const;
std::string getFMExtAck() const;
unsigned int getFMAckSpeed() const;
unsigned int getFMAckFrequency() const;
unsigned int getFMAckMinTime() const;
unsigned int getFMAckDelay() const;
float getFMAckLevel() const;
unsigned int getFMTimeout() const;
float getFMTimeoutLevel() const;
float getFMCTCSSFrequency() const;
unsigned int getFMCTCSSHighThreshold() const;
unsigned int getFMCTCSSLowThreshold() const;
float getFMCTCSSLevel() const;
unsigned int getFMKerchunkTime() const;
unsigned int getFMHangTime() const;
unsigned int getFMAccessMode() const;
bool getFMCOSInvert() const;
unsigned int getFMRFAudioBoost() const;
float getFMMaxDevLevel() const;
unsigned int getFMExtAudioBoost() const;
// The D-Star Network section
bool getDStarNetworkEnabled() const;
std::string getDStarGatewayAddress() const;
unsigned int getDStarGatewayPort() const;
unsigned int getDStarLocalPort() const;
unsigned int getDStarNetworkModeHang() const;
bool getDStarNetworkDebug() const;
// The DMR Network section
bool getDMRNetworkEnabled() const; bool getDMRNetworkEnabled() const;
std::string getDMRNetworkAddress() const; std::string getDMRNetworkType() const;
unsigned int getDMRNetworkPort() const; std::string getDMRNetworkRemoteAddress() const;
unsigned int getDMRNetworkLocal() const; unsigned short getDMRNetworkRemotePort() const;
std::string getDMRNetworkLocalAddress() const;
unsigned short getDMRNetworkLocalPort() const;
std::string getDMRNetworkPassword() const; std::string getDMRNetworkPassword() const;
std::string getDMRNetworkOptions() const; std::string getDMRNetworkOptions() const;
bool getDMRNetworkDebug() const; bool getDMRNetworkDebug() const;
@ -228,51 +143,7 @@ public:
bool getDMRNetworkSlot2() const; bool getDMRNetworkSlot2() const;
unsigned int getDMRNetworkModeHang() const; unsigned int getDMRNetworkModeHang() const;
// The System Fusion Network section // The TFTSERIAL section
bool getFusionNetworkEnabled() const;
std::string getFusionNetworkMyAddress() const;
unsigned int getFusionNetworkMyPort() const;
std::string getFusionNetworkGatewayAddress() const;
unsigned int getFusionNetworkGatewayPort() const;
unsigned int getFusionNetworkModeHang() const;
bool getFusionNetworkDebug() const;
// The P25 Network section
bool getP25NetworkEnabled() const;
std::string getP25GatewayAddress() const;
unsigned int getP25GatewayPort() const;
unsigned int getP25LocalPort() const;
unsigned int getP25NetworkModeHang() const;
bool getP25NetworkDebug() const;
// The NXDN Network section
bool getNXDNNetworkEnabled() const;
std::string getNXDNNetworkProtocol() const;
std::string getNXDNGatewayAddress() const;
unsigned int getNXDNGatewayPort() const;
std::string getNXDNLocalAddress() const;
unsigned int getNXDNLocalPort() const;
unsigned int getNXDNNetworkModeHang() const;
bool getNXDNNetworkDebug() const;
// The M17 Network section
bool getM17NetworkEnabled() const;
std::string getM17GatewayAddress() const;
unsigned int getM17GatewayPort() const;
unsigned int getM17LocalPort() const;
unsigned int getM17NetworkModeHang() const;
bool getM17NetworkDebug() const;
// The POCSAG Network section
bool getPOCSAGNetworkEnabled() const;
std::string getPOCSAGGatewayAddress() const;
unsigned int getPOCSAGGatewayPort() const;
std::string getPOCSAGLocalAddress() const;
unsigned int getPOCSAGLocalPort() const;
unsigned int getPOCSAGNetworkModeHang() const;
bool getPOCSAGNetworkDebug() const;
// The TFTSERIAL section
std::string getTFTSerialPort() const; std::string getTFTSerialPort() const;
unsigned int getTFTSerialBrightness() const; unsigned int getTFTSerialBrightness() const;
@ -307,8 +178,8 @@ public:
// The LCDproc section // The LCDproc section
std::string getLCDprocAddress() const; std::string getLCDprocAddress() const;
unsigned int getLCDprocPort() const; unsigned short getLCDprocPort() const;
unsigned int getLCDprocLocalPort() const; unsigned short getLCDprocLocalPort() const;
bool getLCDprocDisplayClock() const; bool getLCDprocDisplayClock() const;
bool getLCDprocUTC() const; bool getLCDprocUTC() const;
bool getLCDprocDimOnIdle() const; bool getLCDprocDimOnIdle() const;
@ -320,7 +191,7 @@ public:
// The Remote Control section // The Remote Control section
bool getRemoteControlEnabled() const; bool getRemoteControlEnabled() const;
std::string getRemoteControlAddress() const; std::string getRemoteControlAddress() const;
unsigned int getRemoteControlPort() const; unsigned short getRemoteControlPort() const;
private: private:
std::string m_file; std::string m_file;
@ -334,6 +205,12 @@ private:
unsigned int m_rxFrequency; unsigned int m_rxFrequency;
unsigned int m_txFrequency; unsigned int m_txFrequency;
unsigned int m_power; unsigned int m_power;
float m_latitude;
float m_longitude;
int m_height;
std::string m_location;
std::string m_description;
std::string m_url;
unsigned int m_logDisplayLevel; unsigned int m_logDisplayLevel;
unsigned int m_logFileLevel; unsigned int m_logFileLevel;
@ -351,9 +228,15 @@ private:
std::string m_nxdnIdLookupFile; std::string m_nxdnIdLookupFile;
unsigned int m_nxdnIdLookupTime; unsigned int m_nxdnIdLookupTime;
std::string m_modemPort;
std::string m_modemProtocol; std::string m_modemProtocol;
unsigned int m_modemAddress; std::string m_modemUARTPort;
unsigned int m_modemUARTSpeed;
std::string m_modemI2CPort;
unsigned int m_modemI2CAddress;
std::string m_modemModemAddress;
unsigned short m_modemModemPort;
std::string m_modemLocalAddress;
unsigned short m_modemLocalPort;
bool m_modemRXInvert; bool m_modemRXInvert;
bool m_modemTXInvert; bool m_modemTXInvert;
bool m_modemPTTInvert; bool m_modemPTTInvert;
@ -366,14 +249,7 @@ private:
float m_modemRFLevel; float m_modemRFLevel;
float m_modemRXLevel; float m_modemRXLevel;
float m_modemCWIdTXLevel; float m_modemCWIdTXLevel;
float m_modemDStarTXLevel;
float m_modemDMRTXLevel; float m_modemDMRTXLevel;
float m_modemYSFTXLevel;
float m_modemP25TXLevel;
float m_modemNXDNTXLevel;
float m_modemM17TXLevel;
float m_modemPOCSAGTXLevel;
float m_modemFMTXLevel;
std::string m_modemRSSIMappingFile; std::string m_modemRSSIMappingFile;
bool m_modemUseCOSAsLockout; bool m_modemUseCOSAsLockout;
bool m_modemTrace; bool m_modemTrace;
@ -381,25 +257,10 @@ private:
bool m_transparentEnabled; bool m_transparentEnabled;
std::string m_transparentRemoteAddress; std::string m_transparentRemoteAddress;
unsigned int m_transparentRemotePort; unsigned short m_transparentRemotePort;
unsigned int m_transparentLocalPort; unsigned short m_transparentLocalPort;
unsigned int m_transparentSendFrameType; unsigned int m_transparentSendFrameType;
bool m_umpEnabled;
std::string m_umpPort;
bool m_dstarEnabled;
std::string m_dstarModule;
bool m_dstarSelfOnly;
std::vector<std::string> m_dstarBlackList;
std::vector<std::string> m_dstarWhiteList;
bool m_dstarAckReply;
unsigned int m_dstarAckTime;
bool m_dstarAckMessage;
bool m_dstarErrorReply;
bool m_dstarRemoteGateway;
unsigned int m_dstarModeHang;
bool m_dmrEnabled; bool m_dmrEnabled;
DMR_BEACONS m_dmrBeacons; DMR_BEACONS m_dmrBeacons;
unsigned int m_dmrBeaconInterval; unsigned int m_dmrBeaconInterval;
@ -419,82 +280,12 @@ private:
unsigned int m_dmrModeHang; unsigned int m_dmrModeHang;
DMR_OVCM_TYPES m_dmrOVCM; DMR_OVCM_TYPES m_dmrOVCM;
bool m_fusionEnabled;
bool m_fusionLowDeviation;
bool m_fusionRemoteGateway;
bool m_fusionSelfOnly;
unsigned int m_fusionTXHang;
unsigned int m_fusionModeHang;
bool m_p25Enabled;
unsigned int m_p25Id;
unsigned int m_p25NAC;
bool m_p25SelfOnly;
bool m_p25OverrideUID;
bool m_p25RemoteGateway;
unsigned int m_p25TXHang;
unsigned int m_p25ModeHang;
bool m_nxdnEnabled;
unsigned int m_nxdnId;
unsigned int m_nxdnRAN;
bool m_nxdnSelfOnly;
bool m_nxdnRemoteGateway;
unsigned int m_nxdnTXHang;
unsigned int m_nxdnModeHang;
bool m_m17Enabled;
bool m_m17SelfOnly;
bool m_m17AllowEncryption;
unsigned int m_m17TXHang;
unsigned int m_m17ModeHang;
bool m_pocsagEnabled;
unsigned int m_pocsagFrequency;
bool m_fmEnabled;
std::string m_fmCallsign;
unsigned int m_fmCallsignSpeed;
unsigned int m_fmCallsignFrequency;
unsigned int m_fmCallsignTime;
unsigned int m_fmCallsignHoldoff;
float m_fmCallsignHighLevel;
float m_fmCallsignLowLevel;
bool m_fmCallsignAtStart;
bool m_fmCallsignAtEnd;
bool m_fmCallsignAtLatch;
std::string m_fmRFAck;
std::string m_fmExtAck;
unsigned int m_fmAckSpeed;
unsigned int m_fmAckFrequency;
unsigned int m_fmAckMinTime;
unsigned int m_fmAckDelay;
float m_fmAckLevel;
unsigned int m_fmTimeout;
float m_fmTimeoutLevel;
float m_fmCTCSSFrequency;
unsigned int m_fmCTCSSHighThreshold;
unsigned int m_fmCTCSSLowThreshold;
float m_fmCTCSSLevel;
unsigned int m_fmKerchunkTime;
unsigned int m_fmHangTime;
unsigned int m_fmAccessMode;
bool m_fmCOSInvert;
unsigned int m_fmRFAudioBoost;
float m_fmMaxDevLevel;
unsigned int m_fmExtAudioBoost;
bool m_dstarNetworkEnabled;
std::string m_dstarGatewayAddress;
unsigned int m_dstarGatewayPort;
unsigned int m_dstarLocalPort;
unsigned int m_dstarNetworkModeHang;
bool m_dstarNetworkDebug;
bool m_dmrNetworkEnabled; bool m_dmrNetworkEnabled;
std::string m_dmrNetworkAddress; std::string m_dmrNetworkType;
unsigned int m_dmrNetworkPort; std::string m_dmrNetworkRemoteAddress;
unsigned int m_dmrNetworkLocal; unsigned short m_dmrNetworkRemotePort;
std::string m_dmrNetworkLocalAddress;
unsigned short m_dmrNetworkLocalPort;
std::string m_dmrNetworkPassword; std::string m_dmrNetworkPassword;
std::string m_dmrNetworkOptions; std::string m_dmrNetworkOptions;
bool m_dmrNetworkDebug; bool m_dmrNetworkDebug;
@ -503,46 +294,7 @@ private:
bool m_dmrNetworkSlot2; bool m_dmrNetworkSlot2;
unsigned int m_dmrNetworkModeHang; unsigned int m_dmrNetworkModeHang;
bool m_fusionNetworkEnabled; std::string m_tftSerialPort;
std::string m_fusionNetworkMyAddress;
unsigned int m_fusionNetworkMyPort;
std::string m_fusionNetworkGatewayAddress;
unsigned int m_fusionNetworkGatewayPort;
unsigned int m_fusionNetworkModeHang;
bool m_fusionNetworkDebug;
bool m_p25NetworkEnabled;
std::string m_p25GatewayAddress;
unsigned int m_p25GatewayPort;
unsigned int m_p25LocalPort;
unsigned int m_p25NetworkModeHang;
bool m_p25NetworkDebug;
bool m_nxdnNetworkEnabled;
std::string m_nxdnNetworkProtocol;
std::string m_nxdnGatewayAddress;
unsigned int m_nxdnGatewayPort;
std::string m_nxdnLocalAddress;
unsigned int m_nxdnLocalPort;
unsigned int m_nxdnNetworkModeHang;
bool m_nxdnNetworkDebug;
bool m_m17NetworkEnabled;
std::string m_m17GatewayAddress;
unsigned int m_m17GatewayPort;
unsigned int m_m17LocalPort;
unsigned int m_m17NetworkModeHang;
bool m_m17NetworkDebug;
bool m_pocsagNetworkEnabled;
std::string m_pocsagGatewayAddress;
unsigned int m_pocsagGatewayPort;
std::string m_pocsagLocalAddress;
unsigned int m_pocsagLocalPort;
unsigned int m_pocsagNetworkModeHang;
bool m_pocsagNetworkDebug;
std::string m_tftSerialPort;
unsigned int m_tftSerialBrightness; unsigned int m_tftSerialBrightness;
unsigned int m_hd44780Rows; unsigned int m_hd44780Rows;
@ -572,8 +324,8 @@ private:
bool m_oledLogoScreensaver; bool m_oledLogoScreensaver;
std::string m_lcdprocAddress; std::string m_lcdprocAddress;
unsigned int m_lcdprocPort; unsigned short m_lcdprocPort;
unsigned int m_lcdprocLocalPort; unsigned short m_lcdprocLocalPort;
bool m_lcdprocDisplayClock; bool m_lcdprocDisplayClock;
bool m_lcdprocUTC; bool m_lcdprocUTC;
bool m_lcdprocDimOnIdle; bool m_lcdprocDimOnIdle;
@ -583,7 +335,7 @@ private:
bool m_remoteControlEnabled; bool m_remoteControlEnabled;
std::string m_remoteControlAddress; std::string m_remoteControlAddress;
unsigned int m_remoteControlPort; unsigned short m_remoteControlPort;
}; };
#endif #endif

View file

@ -61,7 +61,7 @@ bool CDMRAccessControl::validateSrcId(unsigned int id)
return false; return false;
unsigned int prefix = id / 10000U; unsigned int prefix = id / 10000U;
if (prefix == 0U || prefix > 999U) if (prefix == 0U || prefix > 9999U)
return false; return false;
if (!m_prefixes.empty()) { if (!m_prefixes.empty()) {

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2015,2016,2020 by Jonathan Naylor G4KLX * Copyright (C) 2015,2016,2020,2021,2022 by Jonathan Naylor G4KLX
* Copyright (C) 2019 by Patrick Maier DK5MP * Copyright (C) 2019 by Patrick Maier DK5MP
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
@ -34,7 +34,8 @@ m_bsId(0U),
m_srcId(0U), m_srcId(0U),
m_dstId(0U), m_dstId(0U),
m_dataContent(false), m_dataContent(false),
m_CBF(0U) m_CBF(0U),
m_OVCM(false)
{ {
m_data = new unsigned char[12U]; m_data = new unsigned char[12U];
} }
@ -81,6 +82,7 @@ bool CDMRCSBK::put(const unsigned char* bytes)
m_srcId = m_data[7U] << 16 | m_data[8U] << 8 | m_data[9U]; m_srcId = m_data[7U] << 16 | m_data[8U] << 8 | m_data[9U];
m_dataContent = false; m_dataContent = false;
m_CBF = 0U; m_CBF = 0U;
m_OVCM = (m_data[2U] & 0x04U) == 0x04U;
CUtils::dump(1U, "Unit to Unit Service Request CSBK", m_data, 12U); CUtils::dump(1U, "Unit to Unit Service Request CSBK", m_data, 12U);
break; break;
@ -90,6 +92,7 @@ bool CDMRCSBK::put(const unsigned char* bytes)
m_srcId = m_data[7U] << 16 | m_data[8U] << 8 | m_data[9U]; m_srcId = m_data[7U] << 16 | m_data[8U] << 8 | m_data[9U];
m_dataContent = false; m_dataContent = false;
m_CBF = 0U; m_CBF = 0U;
m_OVCM = (m_data[2U] & 0x04U) == 0x04U;
CUtils::dump(1U, "Unit to Unit Service Answer Response CSBK", m_data, 12U); CUtils::dump(1U, "Unit to Unit Service Answer Response CSBK", m_data, 12U);
break; break;
@ -129,6 +132,21 @@ bool CDMRCSBK::put(const unsigned char* bytes)
CUtils::dump(1U, "Call Alert Ack CSBK", m_data, 12U); CUtils::dump(1U, "Call Alert Ack CSBK", m_data, 12U);
break; break;
case CSBKO_RADIO_CHECK:
m_GI = false;
if (m_data[3U] == 0x80) {
m_dstId = m_data[4U] << 16 | m_data[5U] << 8 | m_data[6U];
m_srcId = m_data[7U] << 16 | m_data[8U] << 8 | m_data[9U];
CUtils::dump(1U, "Radio Check Req CSBK", m_data, 12U);
} else {
m_srcId = m_data[4U] << 16 | m_data[5U] << 8 | m_data[6U];
m_dstId = m_data[7U] << 16 | m_data[8U] << 8 | m_data[9U];
CUtils::dump(1U, "Radio Check Ack CSBK", m_data, 12U);
}
m_dataContent = false;
m_CBF = 0U;
break;
default: default:
m_GI = false; m_GI = false;
m_srcId = 0U; m_srcId = 0U;
@ -170,22 +188,18 @@ unsigned char CDMRCSBK::getFID() const
bool CDMRCSBK::getOVCM() const bool CDMRCSBK::getOVCM() const
{ {
bool bOVCM = false; return m_OVCM;
// Service options informations are only available in
// "Unit to Unit Voice Service Request CSBK" and
// "Unit to Unit Voice Service Answer Response CSBK"
if ((m_CSBKO == CSBKO_UUVREQ) || (m_CSBKO == CSBKO_UUANSRSP))
bOVCM = (m_data[2U] & 0x04U) == 0x04U;
return bOVCM;
} }
void CDMRCSBK::setOVCM(bool ovcm) void CDMRCSBK::setOVCM(bool ovcm)
{ {
// Set OVCM only in CSBKs having the service options information if (m_CSBKO == CSBKO_UUVREQ || m_CSBKO == CSBKO_UUANSRSP) {
if ((m_CSBKO == CSBKO_UUVREQ) || (m_CSBKO == CSBKO_UUANSRSP)) { m_OVCM = ovcm;
if (ovcm) if (ovcm)
m_data[2U] |= 0x04U; m_data[2U] |= 0x04U;
else
m_data[2U] &= 0xFBU;
} }
} }

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2015,2016,2020 by Jonathan Naylor G4KLX * Copyright (C) 2015,2016,2020,2021,2022 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
@ -28,6 +28,7 @@ enum CSBKO {
CSBKO_CTCSBK = 0x07, CSBKO_CTCSBK = 0x07,
CSBKO_CALL_ALERT = 0x1F, CSBKO_CALL_ALERT = 0x1F,
CSBKO_CALL_ALERT_ACK = 0x20, CSBKO_CALL_ALERT_ACK = 0x20,
CSBKO_RADIO_CHECK = 0x24,
CSBKO_NACKRSP = 0x26, CSBKO_NACKRSP = 0x26,
CSBKO_BSDWNACT = 0x38, CSBKO_BSDWNACT = 0x38,
CSBKO_PRECCSBK = 0x3D CSBKO_PRECCSBK = 0x3D
@ -75,6 +76,7 @@ private:
unsigned int m_dstId; unsigned int m_dstId;
bool m_dataContent; bool m_dataContent;
unsigned char m_CBF; unsigned char m_CBF;
bool m_OVCM;
}; };
#endif #endif

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2015-2019 Jonathan Naylor, G4KLX * Copyright (C) 2015-2021 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 <cassert> #include <cassert>
#include <algorithm> #include <algorithm>
CDMRControl::CDMRControl(unsigned int id, unsigned int colorCode, unsigned int callHang, bool selfOnly, bool embeddedLCOnly, bool dumpTAData, const std::vector<unsigned int>& prefixes, const std::vector<unsigned int>& blacklist, const std::vector<unsigned int>& whitelist, const std::vector<unsigned int>& slot1TGWhitelist, const std::vector<unsigned int>& slot2TGWhitelist, unsigned int timeout, CModem* modem, CDMRNetwork* network, CDisplay* display, bool duplex, CDMRLookup* lookup, CRSSIInterpolator* rssi, unsigned int jitter, DMR_OVCM_TYPES ovcm) : CDMRControl::CDMRControl(unsigned int id, unsigned int colorCode, unsigned int callHang, bool selfOnly, bool embeddedLCOnly, bool dumpTAData, const std::vector<unsigned int>& prefixes, const std::vector<unsigned int>& blacklist, const std::vector<unsigned int>& whitelist, const std::vector<unsigned int>& slot1TGWhitelist, const std::vector<unsigned int>& slot2TGWhitelist, unsigned int timeout, CModem* modem, IDMRNetwork* network, CDisplay* display, bool duplex, CDMRLookup* lookup, CRSSIInterpolator* rssi, unsigned int jitter, DMR_OVCM_TYPES ovcm) :
m_colorCode(colorCode), m_colorCode(colorCode),
m_modem(modem), m_modem(modem),
m_network(network), m_network(network),
@ -38,6 +38,13 @@ m_lookup(lookup)
// Load black and white lists to DMRAccessControl // Load black and white lists to DMRAccessControl
CDMRAccessControl::init(blacklist, whitelist, slot1TGWhitelist, slot2TGWhitelist, selfOnly, prefixes, id); CDMRAccessControl::init(blacklist, whitelist, slot1TGWhitelist, slot2TGWhitelist, selfOnly, prefixes, id);
//Print whitelisted IDs
LogMessage("Allowed radio ids: ");
for (unsigned int i: whitelist) {
std::string id_name = std::to_string(i);
LogMessage(id_name.c_str());
}
CDMRSlot::init(colorCode, embeddedLCOnly, dumpTAData, callHang, modem, network, display, duplex, m_lookup, rssi, jitter, ovcm); CDMRSlot::init(colorCode, embeddedLCOnly, dumpTAData, callHang, modem, network, display, duplex, m_lookup, rssi, jitter, ovcm);
} }
@ -63,15 +70,17 @@ bool CDMRControl::processWakeup(const unsigned char* data)
return false; return false;
unsigned int srcId = csbk.getSrcId(); unsigned int srcId = csbk.getSrcId();
std::string srcId_name = std::to_string(srcId);
LogMessage("Incoming uplink from radio id: %s", srcId_name.c_str());
std::string src = m_lookup->find(srcId); std::string src = m_lookup->find(srcId);
bool ret = CDMRAccessControl::validateSrcId(srcId); bool ret = CDMRAccessControl::validateSrcId(srcId);
if (!ret) { if (!ret) {
LogMessage("Invalid Downlink Activate received from %s", src.c_str()); LogMessage("Blocked downlink activation from %s (%s)", src.c_str(), srcId_name.c_str());
return false; return false;
} }
LogMessage("Downlink Activate received from %s", src.c_str()); LogMessage("Downlink request received from %s (%s)", src.c_str(), srcId_name.c_str());
return true; return true;
} }

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2015-2019 by Jonathan Naylor G4KLX * Copyright (C) 2015-2021 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
@ -31,7 +31,7 @@
class CDMRControl { class CDMRControl {
public: public:
CDMRControl(unsigned int id, unsigned int colorCode, unsigned int callHang, bool selfOnly, bool embeddedLCOnly, bool dumpTAData, const std::vector<unsigned int>& prefixes, const std::vector<unsigned int>& blacklist, const std::vector<unsigned int>& whitelist, const std::vector<unsigned int>& slot1TGWhitelist, const std::vector<unsigned int>& slot2TGWhitelist, unsigned int timeout, CModem* modem, CDMRNetwork* network, CDisplay* display, bool duplex, CDMRLookup* lookup, CRSSIInterpolator* rssi, unsigned int jitter, DMR_OVCM_TYPES ovcm); CDMRControl(unsigned int id, unsigned int colorCode, unsigned int callHang, bool selfOnly, bool embeddedLCOnly, bool dumpTAData, const std::vector<unsigned int>& prefixes, const std::vector<unsigned int>& blacklist, const std::vector<unsigned int>& whitelist, const std::vector<unsigned int>& slot1TGWhitelist, const std::vector<unsigned int>& slot2TGWhitelist, unsigned int timeout, CModem* modem, IDMRNetwork* network, CDisplay* display, bool duplex, CDMRLookup* lookup, CRSSIInterpolator* rssi, unsigned int jitter, DMR_OVCM_TYPES ovcm);
~CDMRControl(); ~CDMRControl();
bool processWakeup(const unsigned char* data); bool processWakeup(const unsigned char* data);
@ -51,7 +51,7 @@ public:
private: private:
unsigned int m_colorCode; unsigned int m_colorCode;
CModem* m_modem; CModem* m_modem;
CDMRNetwork* m_network; IDMRNetwork* m_network;
CDMRSlot m_slot1; CDMRSlot m_slot1;
CDMRSlot m_slot2; CDMRSlot m_slot2;
CDMRLookup* m_lookup; CDMRLookup* m_lookup;

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2015,2016 by Jonathan Naylor G4KLX * Copyright (C) 2015,2016,2021 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

644
DMRDirectNetwork.cpp Normal file
View file

@ -0,0 +1,644 @@
/*
* Copyright (C) 2015,2016,2017,2018,2020,2021 by Jonathan Naylor G4KLX
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* 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 "DMRDirectNetwork.h"
#include "SHA256.h"
#include "Utils.h"
#include "Log.h"
#include <cstdio>
#include <cassert>
const unsigned int BUFFER_LENGTH = 500U;
const unsigned int HOMEBREW_DATA_PACKET_LENGTH = 55U;
CDMRDirectNetwork::CDMRDirectNetwork(const std::string& address, unsigned short port, const std::string& localAddress, unsigned short localPort, unsigned int id, const std::string& password, bool duplex, const char* version, bool slot1, bool slot2, HW_TYPE hwType, bool debug) :
m_address(address),
m_port(port),
m_addr(),
m_addrLen(0U),
m_id(NULL),
m_password(password),
m_duplex(duplex),
m_version(version),
m_debug(debug),
m_socket(localAddress, localPort),
m_enabled(false),
m_slot1(slot1),
m_slot2(slot2),
m_hwType(hwType),
m_status(WAITING_CONNECT),
m_retryTimer(1000U, 10U),
m_timeoutTimer(1000U, 60U),
m_buffer(NULL),
m_streamId(NULL),
m_salt(NULL),
m_rxData(1000U, "DMR Network"),
m_options(),
m_random(),
m_callsign(),
m_rxFrequency(0U),
m_txFrequency(0U),
m_power(0U),
m_colorCode(0U),
m_latitude(0.0F),
m_longitude(0.0F),
m_height(0),
m_location(),
m_description(),
m_url(),
m_beacon(false)
{
assert(!address.empty());
assert(port > 0U);
assert(id > 1000U);
assert(!password.empty());
m_buffer = new unsigned char[BUFFER_LENGTH];
m_salt = new unsigned char[sizeof(uint32_t)];
m_id = new uint8_t[4U];
m_streamId = new uint32_t[2U];
m_id[0U] = id >> 24;
m_id[1U] = id >> 16;
m_id[2U] = id >> 8;
m_id[3U] = id >> 0;
std::random_device rd;
std::mt19937 mt(rd());
m_random = mt;
std::uniform_int_distribution<uint32_t> dist(0x00000001, 0xfffffffe);
m_streamId[0U] = dist(m_random);
m_streamId[1U] = dist(m_random);
}
CDMRDirectNetwork::~CDMRDirectNetwork()
{
delete[] m_streamId;
delete[] m_buffer;
delete[] m_salt;
delete[] m_id;
}
void CDMRDirectNetwork::setOptions(const std::string& options)
{
m_options = options;
}
void CDMRDirectNetwork::setConfig(const std::string& callsign, unsigned int rxFrequency, unsigned int txFrequency, unsigned int power, unsigned int colorCode, float latitude, float longitude, int height, const std::string& location, const std::string& description, const std::string& url)
{
m_callsign = callsign;
m_rxFrequency = rxFrequency;
m_txFrequency = txFrequency;
m_power = power;
m_colorCode = colorCode;
m_latitude = latitude;
m_longitude = longitude;
m_height = height;
m_location = location;
m_description = description;
m_url = url;
}
bool CDMRDirectNetwork::open()
{
if (CUDPSocket::lookup(m_address, m_port, m_addr, m_addrLen) != 0) {
LogError("DMR, Could not lookup the address of the DMR Network");
return false;
}
LogMessage("Opening DMR Network");
m_status = WAITING_CONNECT;
m_timeoutTimer.stop();
m_retryTimer.start();
return true;
}
void CDMRDirectNetwork::enable(bool enabled)
{
if (!enabled && m_enabled)
m_rxData.clear();
m_enabled = enabled;
}
bool CDMRDirectNetwork::read(CDMRData& data)
{
if (m_status != RUNNING)
return false;
if (m_rxData.isEmpty())
return false;
unsigned char length = 0U;
m_rxData.getData(&length, 1U);
m_rxData.getData(m_buffer, length);
// Is this a data packet?
if (::memcmp(m_buffer, "DMRD", 4U) != 0)
return false;
unsigned char seqNo = m_buffer[4U];
unsigned int srcId = (m_buffer[5U] << 16) | (m_buffer[6U] << 8) | (m_buffer[7U] << 0);
unsigned int dstId = (m_buffer[8U] << 16) | (m_buffer[9U] << 8) | (m_buffer[10U] << 0);
unsigned int slotNo = (m_buffer[15U] & 0x80U) == 0x80U ? 2U : 1U;
// DMO mode slot disabling
if (slotNo == 1U && !m_duplex)
return false;
// Individual slot disabling
if (slotNo == 1U && !m_slot1)
return false;
if (slotNo == 2U && !m_slot2)
return false;
FLCO flco = (m_buffer[15U] & 0x40U) == 0x40U ? FLCO_USER_USER : FLCO_GROUP;
data.setSeqNo(seqNo);
data.setSlotNo(slotNo);
data.setSrcId(srcId);
data.setDstId(dstId);
data.setFLCO(flco);
bool dataSync = (m_buffer[15U] & 0x20U) == 0x20U;
bool voiceSync = (m_buffer[15U] & 0x10U) == 0x10U;
if (dataSync) {
unsigned char dataType = m_buffer[15U] & 0x0FU;
data.setData(m_buffer + 20U);
data.setDataType(dataType);
data.setN(0U);
} else if (voiceSync) {
data.setData(m_buffer + 20U);
data.setDataType(DT_VOICE_SYNC);
data.setN(0U);
} else {
unsigned char n = m_buffer[15U] & 0x0FU;
data.setData(m_buffer + 20U);
data.setDataType(DT_VOICE);
data.setN(n);
}
return true;
}
bool CDMRDirectNetwork::write(const CDMRData& data)
{
if (m_status != RUNNING)
return false;
unsigned char buffer[HOMEBREW_DATA_PACKET_LENGTH];
::memset(buffer, 0x00U, HOMEBREW_DATA_PACKET_LENGTH);
buffer[0U] = 'D';
buffer[1U] = 'M';
buffer[2U] = 'R';
buffer[3U] = 'D';
unsigned int srcId = data.getSrcId();
buffer[5U] = srcId >> 16;
buffer[6U] = srcId >> 8;
buffer[7U] = srcId >> 0;
unsigned int dstId = data.getDstId();
buffer[8U] = dstId >> 16;
buffer[9U] = dstId >> 8;
buffer[10U] = dstId >> 0;
::memcpy(buffer + 11U, m_id, 4U);
unsigned int slotNo = data.getSlotNo();
// Individual slot disabling
if (slotNo == 1U && !m_slot1)
return false;
if (slotNo == 2U && !m_slot2)
return false;
buffer[15U] = slotNo == 1U ? 0x00U : 0x80U;
FLCO flco = data.getFLCO();
buffer[15U] |= flco == FLCO_GROUP ? 0x00U : 0x40U;
unsigned int slotIndex = slotNo - 1U;
std::uniform_int_distribution<uint32_t> dist(0x00000001, 0xfffffffe);
unsigned char dataType = data.getDataType();
if (dataType == DT_VOICE_SYNC) {
buffer[15U] |= 0x10U;
} else if (dataType == DT_VOICE) {
buffer[15U] |= data.getN();
} else {
if (dataType == DT_VOICE_LC_HEADER)
m_streamId[slotIndex] = dist(m_random);
if (dataType == DT_CSBK || dataType == DT_DATA_HEADER)
m_streamId[slotIndex] = dist(m_random);
buffer[15U] |= (0x20U | dataType);
}
buffer[4U] = data.getSeqNo();
::memcpy(buffer + 16U, m_streamId + slotIndex, 4U);
data.getData(buffer + 20U);
buffer[53U] = data.getBER();
buffer[54U] = data.getRSSI();
write(buffer, HOMEBREW_DATA_PACKET_LENGTH);
return true;
}
bool CDMRDirectNetwork::writeRadioPosition(unsigned int id, const unsigned char* data)
{
if (m_status != RUNNING)
return false;
unsigned char buffer[20U];
::memcpy(buffer + 0U, "DMRG", 4U);
buffer[4U] = id >> 16;
buffer[5U] = id >> 8;
buffer[6U] = id >> 0;
::memcpy(buffer + 7U, data + 2U, 7U);
return write(buffer, 14U);
}
bool CDMRDirectNetwork::writeTalkerAlias(unsigned int id, unsigned char type, const unsigned char* data)
{
if (m_status != RUNNING)
return false;
unsigned char buffer[20U];
::memcpy(buffer + 0U, "DMRA", 4U);
buffer[4U] = id >> 16;
buffer[5U] = id >> 8;
buffer[6U] = id >> 0;
buffer[7U] = type;
::memcpy(buffer + 8U, data + 2U, 7U);
return write(buffer, 15U);
}
bool CDMRDirectNetwork::isConnected() const
{
return (m_status == RUNNING);
}
void CDMRDirectNetwork::close(bool sayGoodbye)
{
LogMessage("Closing DMR Network");
if (sayGoodbye && (m_status == RUNNING)) {
unsigned char buffer[9U];
::memcpy(buffer + 0U, "RPTCL", 5U);
::memcpy(buffer + 5U, m_id, 4U);
write(buffer, 9U);
}
m_socket.close();
m_retryTimer.stop();
m_timeoutTimer.stop();
}
void CDMRDirectNetwork::clock(unsigned int ms)
{
m_retryTimer.clock(ms);
if (m_retryTimer.isRunning() && m_retryTimer.hasExpired()) {
switch (m_status) {
case WAITING_CONNECT:
if (m_socket.open(m_addr.ss_family)) {
if (writeLogin()) {
m_status = WAITING_LOGIN;
}
}
break;
case WAITING_LOGIN:
writeLogin();
break;
case WAITING_AUTHORISATION:
writeAuthorisation();
break;
case WAITING_OPTIONS:
writeOptions();
break;
case WAITING_CONFIG:
writeConfig();
break;
case RUNNING:
writePing();
break;
default:
break;
}
m_retryTimer.start();
}
sockaddr_storage address;
unsigned int addrlen;
int length = m_socket.read(m_buffer, BUFFER_LENGTH, address, addrlen);
if (length < 0) {
LogError("DMR, Socket has failed, retrying connection to the master");
close(false);
open();
return;
}
if (length > 0) {
if (!CUDPSocket::match(m_addr, address)) {
LogMessage("DMR, packet received from an invalid source");
return;
}
if (m_debug)
CUtils::dump(1U, "DMR, Network Received", m_buffer, length);
if (::memcmp(m_buffer, "DMRD", 4U) == 0) {
if (m_enabled) {
unsigned char len = length;
m_rxData.addData(&len, 1U);
m_rxData.addData(m_buffer, len);
}
} else if (::memcmp(m_buffer, "MSTNAK", 6U) == 0) {
if (m_status == RUNNING) {
LogWarning("DMR, Login to the master has failed, retrying login ...");
m_status = WAITING_LOGIN;
m_timeoutTimer.start();
m_retryTimer.start();
} else {
/* Once the modem death spiral has been prevented in Modem.cpp
the Network sometimes times out and reaches here.
We want it to reconnect so... */
LogError("DMR, Login to the master has failed, retrying network ...");
close(false);
open();
return;
}
} else if (::memcmp(m_buffer, "RPTACK", 6U) == 0) {
switch (m_status) {
case WAITING_LOGIN:
LogDebug("DMR, Sending authorisation");
::memcpy(m_salt, m_buffer + 6U, sizeof(uint32_t));
writeAuthorisation();
m_status = WAITING_AUTHORISATION;
m_timeoutTimer.start();
m_retryTimer.start();
break;
case WAITING_AUTHORISATION:
LogDebug("DMR, Sending configuration");
writeConfig();
m_status = WAITING_CONFIG;
m_timeoutTimer.start();
m_retryTimer.start();
break;
case WAITING_CONFIG:
if (m_options.empty()) {
LogMessage("DMR, Logged into the master successfully");
m_status = RUNNING;
} else {
LogDebug("DMR, Sending options");
writeOptions();
m_status = WAITING_OPTIONS;
}
m_timeoutTimer.start();
m_retryTimer.start();
break;
case WAITING_OPTIONS:
LogMessage("DMR, Logged into the master successfully");
m_status = RUNNING;
m_timeoutTimer.start();
m_retryTimer.start();
break;
default:
break;
}
} else if (::memcmp(m_buffer, "MSTCL", 5U) == 0) {
LogError("DMR, Master is closing down");
close(false);
open();
} else if (::memcmp(m_buffer, "MSTPONG", 7U) == 0) {
m_timeoutTimer.start();
} else if (::memcmp(m_buffer, "RPTSBKN", 7U) == 0) {
m_beacon = true;
} else {
CUtils::dump("DMR, Unknown packet from the master", m_buffer, length);
}
}
m_timeoutTimer.clock(ms);
if (m_timeoutTimer.isRunning() && m_timeoutTimer.hasExpired()) {
LogError("DMR, Connection to the master has timed out, retrying connection");
close(false);
open();
}
}
bool CDMRDirectNetwork::writeLogin()
{
unsigned char buffer[8U];
::memcpy(buffer + 0U, "RPTL", 4U);
::memcpy(buffer + 4U, m_id, 4U);
return write(buffer, 8U);
}
bool CDMRDirectNetwork::writeAuthorisation()
{
size_t size = m_password.size();
unsigned char* in = new unsigned char[size + sizeof(uint32_t)];
::memcpy(in, m_salt, sizeof(uint32_t));
for (size_t i = 0U; i < size; i++)
in[i + sizeof(uint32_t)] = m_password.at(i);
unsigned char out[40U];
::memcpy(out + 0U, "RPTK", 4U);
::memcpy(out + 4U, m_id, 4U);
CSHA256 sha256;
sha256.buffer(in, (unsigned int)(size + sizeof(uint32_t)), out + 8U);
delete[] in;
return write(out, 40U);
}
bool CDMRDirectNetwork::writeOptions()
{
char buffer[300U];
::memcpy(buffer + 0U, "RPTO", 4U);
::memcpy(buffer + 4U, m_id, 4U);
::strcpy(buffer + 8U, m_options.c_str());
return write((unsigned char*)buffer, (unsigned int)m_options.length() + 8U);
}
bool CDMRDirectNetwork::writeConfig()
{
const char* software;
char slots = '0';
if (m_duplex) {
if (m_slot1 && m_slot2)
slots = '3';
else if (m_slot1 && !m_slot2)
slots = '1';
else if (!m_slot1 && m_slot2)
slots = '2';
switch (m_hwType) {
case HWT_MMDVM:
software = "MMDVM";
break;
case HWT_MMDVM_HS:
software = "MMDVM_MMDVM_HS";
break;
case HWT_MMDVM_HS_DUAL_HAT:
software = "MMDVM_MMDVM_HS_Dual_Hat";
break;
case HWT_NANO_HOTSPOT:
software = "MMDVM_Nano_hotSPOT";
break;
default:
software = "MMDVM_Unknown";
break;
}
} else {
slots = '4';
switch (m_hwType) {
case HWT_MMDVM:
software = "MMDVM_DMO";
break;
case HWT_DVMEGA:
software = "MMDVM_DVMega";
break;
case HWT_MMDVM_ZUMSPOT:
software = "MMDVM_ZUMspot";
break;
case HWT_MMDVM_HS_HAT:
software = "MMDVM_MMDVM_HS_Hat";
break;
case HWT_MMDVM_HS_DUAL_HAT:
software = "MMDVM_MMDVM_HS_Dual_Hat";
break;
case HWT_NANO_HOTSPOT:
software = "MMDVM_Nano_hotSPOT";
break;
case HWT_NANO_DV:
software = "MMDVM_Nano_DV";
break;
case HWT_D2RG_MMDVM_HS:
software = "MMDVM_D2RG_MMDVM_HS";
break;
case HWT_MMDVM_HS:
software = "MMDVM_MMDVM_HS";
break;
default:
software = "MMDVM_Unknown";
break;
}
}
char buffer[400U];
::memcpy(buffer + 0U, "RPTC", 4U);
::memcpy(buffer + 4U, m_id, 4U);
char latitude[20U];
::sprintf(latitude, "%08f", m_latitude);
char longitude[20U];
::sprintf(longitude, "%09f", m_longitude);
unsigned int power = m_power;
if (power > 99U)
power = 99U;
int height = m_height;
if (height > 999)
height = 999;
::sprintf(buffer + 8U, "%-8.8s%09u%09u%02u%02u%8.8s%9.9s%03d%-20.20s%-19.19s%c%-124.124s%-40.40s%-40.40s", m_callsign.c_str(),
m_rxFrequency, m_txFrequency, power, m_colorCode, latitude, longitude, height, m_location.c_str(),
m_description.c_str(), slots, m_url.c_str(), m_version, software);
return write((unsigned char*)buffer, 302U);
}
bool CDMRDirectNetwork::writePing()
{
unsigned char buffer[11U];
::memcpy(buffer + 0U, "RPTPING", 7U);
::memcpy(buffer + 7U, m_id, 4U);
return write(buffer, 11U);
}
bool CDMRDirectNetwork::wantsBeacon()
{
bool beacon = m_beacon;
m_beacon = false;
return beacon;
}
bool CDMRDirectNetwork::write(const unsigned char* data, unsigned int length)
{
assert(data != NULL);
assert(length > 0U);
if (m_debug)
CUtils::dump(1U, "DMR Network Transmitted", data, length);
bool ret = m_socket.write(data, length, m_addr, m_addrLen);
if (!ret) {
LogError("DMR, Socket has failed when writing data to the master, retrying connection");
close(false);
open();
return false;
}
return true;
}

121
DMRDirectNetwork.h Normal file
View file

@ -0,0 +1,121 @@
/*
* Copyright (C) 2015,2016,2017,2018,2020,2021 by Jonathan Naylor G4KLX
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* 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(DMRDirectNetwork_H)
#define DMRDirectNetwork_H
#include "DMRNetwork.h"
#include "UDPSocket.h"
#include "Timer.h"
#include "RingBuffer.h"
#include "DMRData.h"
#include <string>
#include <cstdint>
#include <random>
class CDMRDirectNetwork : public IDMRNetwork
{
public:
CDMRDirectNetwork(const std::string& remoteAddress, unsigned short remotePort, const std::string& localAddress, unsigned short localPort, unsigned int id, const std::string& password, bool duplex, const char* version, bool slot1, bool slot2, HW_TYPE hwType, bool debug);
virtual ~CDMRDirectNetwork();
virtual void setOptions(const std::string& options);
virtual void setConfig(const std::string& callsign, unsigned int rxFrequency, unsigned int txFrequency, unsigned int power, unsigned int colorCode, float latitude, float longitude, int height, const std::string& location, const std::string& description, const std::string& url);
virtual bool open();
virtual void enable(bool enabled);
virtual bool read(CDMRData& data);
virtual bool write(const CDMRData& data);
virtual bool writeRadioPosition(unsigned int id, const unsigned char* data);
virtual bool writeTalkerAlias(unsigned int id, unsigned char type, const unsigned char* data);
virtual bool wantsBeacon();
virtual void clock(unsigned int ms);
virtual bool isConnected() const;
virtual void close(bool sayGoodbye);
private:
std::string m_address;
unsigned short m_port;
sockaddr_storage m_addr;
unsigned int m_addrLen;
uint8_t* m_id;
std::string m_password;
bool m_duplex;
const char* m_version;
bool m_debug;
CUDPSocket m_socket;
bool m_enabled;
bool m_slot1;
bool m_slot2;
HW_TYPE m_hwType;
enum STATUS {
WAITING_CONNECT,
WAITING_LOGIN,
WAITING_AUTHORISATION,
WAITING_CONFIG,
WAITING_OPTIONS,
RUNNING
};
STATUS m_status;
CTimer m_retryTimer;
CTimer m_timeoutTimer;
unsigned char* m_buffer;
uint32_t* m_streamId;
unsigned char* m_salt;
CRingBuffer<unsigned char> m_rxData;
std::string m_options;
std::mt19937 m_random;
std::string m_callsign;
unsigned int m_rxFrequency;
unsigned int m_txFrequency;
unsigned int m_power;
unsigned int m_colorCode;
float m_latitude;
float m_longitude;
int m_height;
std::string m_location;
std::string m_description;
std::string m_url;
bool m_beacon;
bool writeLogin();
bool writeAuthorisation();
bool writeOptions();
bool writeConfig();
bool writePing();
bool write(const unsigned char* data, unsigned int length);
};
#endif

450
DMRGatewayNetwork.cpp Normal file
View file

@ -0,0 +1,450 @@
/*
* Copyright (C) 2015-2021 by Jonathan Naylor G4KLX
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "DMRGatewayNetwork.h"
#include "Utils.h"
#include "Log.h"
#include <cstdio>
#include <cassert>
#include <cstring>
#include <cstdlib>
const unsigned int BUFFER_LENGTH = 500U;
const unsigned int HOMEBREW_DATA_PACKET_LENGTH = 55U;
CDMRGatewayNetwork::CDMRGatewayNetwork(const std::string& address, unsigned short port, const std::string& localAddress, unsigned short localPort, unsigned int id, bool duplex, const char* version, bool slot1, bool slot2, HW_TYPE hwType, bool debug) :
m_addressStr(address),
m_addr(),
m_addrLen(0U),
m_port(port),
m_id(NULL),
m_duplex(duplex),
m_version(version),
m_debug(debug),
m_socket(localAddress, localPort),
m_enabled(false),
m_slot1(slot1),
m_slot2(slot2),
m_hwType(hwType),
m_buffer(NULL),
m_streamId(NULL),
m_rxData(1000U, "DMR Network"),
m_beacon(false),
m_random(),
m_callsign(),
m_rxFrequency(0U),
m_txFrequency(0U),
m_power(0U),
m_colorCode(0U),
m_pingTimer(1000U, 10U)
{
assert(!address.empty());
assert(port > 0U);
assert(id > 1000U);
if (CUDPSocket::lookup(m_addressStr, m_port, m_addr, m_addrLen) != 0)
m_addrLen = 0U;
m_buffer = new unsigned char[BUFFER_LENGTH];
m_id = new uint8_t[4U];
m_streamId = new uint32_t[2U];
m_id[0U] = id >> 24;
m_id[1U] = id >> 16;
m_id[2U] = id >> 8;
m_id[3U] = id >> 0;
std::random_device rd;
std::mt19937 mt(rd());
m_random = mt;
std::uniform_int_distribution<uint32_t> dist(0x00000001, 0xfffffffe);
m_streamId[0U] = dist(m_random);
m_streamId[1U] = dist(m_random);
}
CDMRGatewayNetwork::~CDMRGatewayNetwork()
{
delete[] m_buffer;
delete[] m_streamId;
delete[] m_id;
}
void CDMRGatewayNetwork::setConfig(const std::string & callsign, unsigned int rxFrequency, unsigned int txFrequency, unsigned int power, unsigned int colorCode, float latitude, float longitude, int height, const std::string& location, const std::string& description, const std::string& url)
{
m_callsign = callsign;
m_rxFrequency = rxFrequency;
m_txFrequency = txFrequency;
m_power = power;
m_colorCode = colorCode;
}
void CDMRGatewayNetwork::setOptions(const std::string& options)
{
}
bool CDMRGatewayNetwork::open()
{
if (m_addrLen == 0U) {
LogError("Unable to resolve the address of the DMR Network");
return false;
}
LogMessage("DMR, Opening DMR Network");
bool ret = m_socket.open(m_addr);
if (ret)
m_pingTimer.start();
return ret;
}
void CDMRGatewayNetwork::enable(bool enabled)
{
if (!enabled && m_enabled)
m_rxData.clear();
m_enabled = enabled;
}
bool CDMRGatewayNetwork::read(CDMRData& data)
{
if (m_rxData.isEmpty())
return false;
unsigned char length = 0U;
m_rxData.getData(&length, 1U);
m_rxData.getData(m_buffer, length);
// Is this a data packet?
if (::memcmp(m_buffer, "DMRD", 4U) != 0)
return false;
unsigned char seqNo = m_buffer[4U];
unsigned int srcId = (m_buffer[5U] << 16) | (m_buffer[6U] << 8) | (m_buffer[7U] << 0);
unsigned int dstId = (m_buffer[8U] << 16) | (m_buffer[9U] << 8) | (m_buffer[10U] << 0);
unsigned int slotNo = (m_buffer[15U] & 0x80U) == 0x80U ? 2U : 1U;
// DMO mode slot disabling
if (slotNo == 1U && !m_duplex)
return false;
// Individual slot disabling
if (slotNo == 1U && !m_slot1)
return false;
if (slotNo == 2U && !m_slot2)
return false;
FLCO flco = (m_buffer[15U] & 0x40U) == 0x40U ? FLCO_USER_USER : FLCO_GROUP;
data.setSeqNo(seqNo);
data.setSlotNo(slotNo);
data.setSrcId(srcId);
data.setDstId(dstId);
data.setFLCO(flco);
bool dataSync = (m_buffer[15U] & 0x20U) == 0x20U;
bool voiceSync = (m_buffer[15U] & 0x10U) == 0x10U;
if (dataSync) {
unsigned char dataType = m_buffer[15U] & 0x0FU;
data.setData(m_buffer + 20U);
data.setDataType(dataType);
data.setN(0U);
} else if (voiceSync) {
data.setData(m_buffer + 20U);
data.setDataType(DT_VOICE_SYNC);
data.setN(0U);
} else {
unsigned char n = m_buffer[15U] & 0x0FU;
data.setData(m_buffer + 20U);
data.setDataType(DT_VOICE);
data.setN(n);
}
return true;
}
bool CDMRGatewayNetwork::write(const CDMRData& data)
{
unsigned char buffer[HOMEBREW_DATA_PACKET_LENGTH];
::memset(buffer, 0x00U, HOMEBREW_DATA_PACKET_LENGTH);
buffer[0U] = 'D';
buffer[1U] = 'M';
buffer[2U] = 'R';
buffer[3U] = 'D';
unsigned int srcId = data.getSrcId();
buffer[5U] = srcId >> 16;
buffer[6U] = srcId >> 8;
buffer[7U] = srcId >> 0;
unsigned int dstId = data.getDstId();
buffer[8U] = dstId >> 16;
buffer[9U] = dstId >> 8;
buffer[10U] = dstId >> 0;
::memcpy(buffer + 11U, m_id, 4U);
unsigned int slotNo = data.getSlotNo();
// Individual slot disabling
if (slotNo == 1U && !m_slot1)
return false;
if (slotNo == 2U && !m_slot2)
return false;
buffer[15U] = slotNo == 1U ? 0x00U : 0x80U;
FLCO flco = data.getFLCO();
buffer[15U] |= flco == FLCO_GROUP ? 0x00U : 0x40U;
unsigned int slotIndex = slotNo - 1U;
std::uniform_int_distribution<uint32_t> dist(0x00000001, 0xfffffffe);
unsigned char dataType = data.getDataType();
if (dataType == DT_VOICE_SYNC) {
buffer[15U] |= 0x10U;
} else if (dataType == DT_VOICE) {
buffer[15U] |= data.getN();
} else {
if (dataType == DT_VOICE_LC_HEADER)
m_streamId[slotIndex] = dist(m_random);
if (dataType == DT_CSBK || dataType == DT_DATA_HEADER)
m_streamId[slotIndex] = dist(m_random);
buffer[15U] |= (0x20U | dataType);
}
buffer[4U] = data.getSeqNo();
::memcpy(buffer + 16U, m_streamId + slotIndex, 4U);
data.getData(buffer + 20U);
buffer[53U] = data.getBER();
buffer[54U] = data.getRSSI();
write(buffer, HOMEBREW_DATA_PACKET_LENGTH);
return true;
}
bool CDMRGatewayNetwork::writeRadioPosition(unsigned int id, const unsigned char* data)
{
unsigned char buffer[20U];
::memcpy(buffer + 0U, "DMRG", 4U);
buffer[4U] = id >> 16;
buffer[5U] = id >> 8;
buffer[6U] = id >> 0;
::memcpy(buffer + 7U, data + 2U, 7U);
return write(buffer, 14U);
}
bool CDMRGatewayNetwork::writeTalkerAlias(unsigned int id, unsigned char type, const unsigned char* data)
{
unsigned char buffer[20U];
::memcpy(buffer + 0U, "DMRA", 4U);
buffer[4U] = id >> 16;
buffer[5U] = id >> 8;
buffer[6U] = id >> 0;
buffer[7U] = type;
::memcpy(buffer + 8U, data + 2U, 7U);
return write(buffer, 15U);
}
bool CDMRGatewayNetwork::isConnected() const
{
return (m_addrLen != 0);
}
void CDMRGatewayNetwork::close(bool sayGoodbye)
{
LogMessage("DMR, Closing DMR Network");
m_socket.close();
}
void CDMRGatewayNetwork::clock(unsigned int ms)
{
m_pingTimer.clock(ms);
if (m_pingTimer.isRunning() && m_pingTimer.hasExpired()) {
writeConfig();
m_pingTimer.start();
}
sockaddr_storage address;
unsigned int addrLen;
int length = m_socket.read(m_buffer, BUFFER_LENGTH, address, addrLen);
if (length <= 0)
return;
if (!CUDPSocket::match(m_addr, address)) {
LogMessage("DMR, packet received from an invalid source");
return;
}
if (m_debug)
CUtils::dump(1U, "DMR Network Received", m_buffer, length);
if (::memcmp(m_buffer, "DMRD", 4U) == 0) {
if (m_enabled) {
unsigned char len = length;
m_rxData.addData(&len, 1U);
m_rxData.addData(m_buffer, len);
}
} else if (::memcmp(m_buffer, "DMRP", 4U) == 0) {
;
} else if (::memcmp(m_buffer, "DMRB", 4U) == 0) {
m_beacon = true;
} else {
CUtils::dump("DMR, unknown packet from the DMR Network", m_buffer, length);
}
}
bool CDMRGatewayNetwork::writeConfig()
{
const char* software;
char slots = '0';
if (m_duplex) {
if (m_slot1 && m_slot2)
slots = '3';
else if (m_slot1 && !m_slot2)
slots = '1';
else if (!m_slot1 && m_slot2)
slots = '2';
switch (m_hwType) {
case HWT_MMDVM:
software = "MMDVM";
break;
case HWT_MMDVM_HS:
software = "MMDVM_MMDVM_HS";
break;
case HWT_MMDVM_HS_DUAL_HAT:
software = "MMDVM_MMDVM_HS_Dual_Hat";
break;
case HWT_NANO_HOTSPOT:
software = "MMDVM_Nano_hotSPOT";
break;
default:
software = "MMDVM_Unknown";
break;
}
} else {
slots = '4';
switch (m_hwType) {
case HWT_MMDVM:
software = "MMDVM_DMO";
break;
case HWT_DVMEGA:
software = "MMDVM_DVMega";
break;
case HWT_MMDVM_ZUMSPOT:
software = "MMDVM_ZUMspot";
break;
case HWT_MMDVM_HS_HAT:
software = "MMDVM_MMDVM_HS_Hat";
break;
case HWT_MMDVM_HS_DUAL_HAT:
software = "MMDVM_MMDVM_HS_Dual_Hat";
break;
case HWT_NANO_HOTSPOT:
software = "MMDVM_Nano_hotSPOT";
break;
case HWT_NANO_DV:
software = "MMDVM_Nano_DV";
break;
case HWT_D2RG_MMDVM_HS:
software = "MMDVM_D2RG_MMDVM_HS";
break;
case HWT_MMDVM_HS:
software = "MMDVM_MMDVM_HS";
break;
case HWT_OPENGD77_HS:
software = "MMDVM_OpenGD77_HS";
break;
case HWT_SKYBRIDGE:
software = "MMDVM_SkyBridge";
break;
default:
software = "MMDVM_Unknown";
break;
}
}
unsigned int power = m_power;
if (power > 99U)
power = 99U;
char buffer[150U];
::memcpy(buffer + 0U, "DMRC", 4U);
::memcpy(buffer + 4U, m_id, 4U);
::sprintf(buffer + 8U, "%-8.8s%09u%09u%02u%02u%c%-40.40s%-40.40s",
m_callsign.c_str(), m_rxFrequency, m_txFrequency, power, m_colorCode, slots, m_version,
software);
return write((unsigned char*)buffer, 119U);
}
bool CDMRGatewayNetwork::wantsBeacon()
{
bool beacon = m_beacon;
m_beacon = false;
return beacon;
}
bool CDMRGatewayNetwork::write(const unsigned char* data, unsigned int length)
{
assert(data != NULL);
assert(length > 0U);
if (m_debug)
CUtils::dump(1U, "DMR Network Transmitted", data, length);
bool ret = m_socket.write(data, length, m_addr, m_addrLen);
if (!ret) {
LogError("DMR, socket error when writing to the DMR Network");
return false;
}
return true;
}

94
DMRGatewayNetwork.h Normal file
View file

@ -0,0 +1,94 @@
/*
* Copyright (C) 2015,2016,2017,2018,2020,2021 by Jonathan Naylor G4KLX
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* 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(DMRGatewayNetwork_H)
#define DMRGatewayNetwork_H
#include "DMRNetwork.h"
#include "UDPSocket.h"
#include "Timer.h"
#include "RingBuffer.h"
#include "DMRData.h"
#include "Defines.h"
#include <string>
#include <cstdint>
#include <random>
class CDMRGatewayNetwork : public IDMRNetwork
{
public:
CDMRGatewayNetwork(const std::string& remoteAddress, unsigned short remotePort, const std::string& localAddress, unsigned short localPort, unsigned int id, bool duplex, const char* version, bool slot1, bool slot2, HW_TYPE hwType, bool debug);
virtual ~CDMRGatewayNetwork();
virtual void setOptions(const std::string& options);
virtual void setConfig(const std::string& callsign, unsigned int rxFrequency, unsigned int txFrequency, unsigned int power, unsigned int colorCode, float latitude, float longitude, int height, const std::string& location, const std::string& description, const std::string& url);
virtual bool open();
virtual void enable(bool enabled);
virtual bool read(CDMRData& data);
virtual bool write(const CDMRData& data);
virtual bool writeRadioPosition(unsigned int id, const unsigned char* data);
virtual bool writeTalkerAlias(unsigned int id, unsigned char type, const unsigned char* data);
virtual bool wantsBeacon();
virtual void clock(unsigned int ms);
virtual bool isConnected() const;
virtual void close(bool sayGoodbye);
private:
std::string m_addressStr;
sockaddr_storage m_addr;
unsigned int m_addrLen;
unsigned short m_port;
uint8_t* m_id;
bool m_duplex;
const char* m_version;
bool m_debug;
CUDPSocket m_socket;
bool m_enabled;
bool m_slot1;
bool m_slot2;
HW_TYPE m_hwType;
unsigned char* m_buffer;
uint32_t* m_streamId;
CRingBuffer<unsigned char> m_rxData;
bool m_beacon;
std::mt19937 m_random;
std::string m_callsign;
unsigned int m_rxFrequency;
unsigned int m_txFrequency;
unsigned int m_power;
unsigned int m_colorCode;
CTimer m_pingTimer;
bool writeConfig();
bool write(const unsigned char* data, unsigned int length);
};
#endif

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2015,2016,2019 by Jonathan Naylor G4KLX * Copyright (C) 2015,2016,2019,2021,2022 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
@ -193,6 +193,8 @@ void CDMRLC::setOVCM(bool ovcm)
{ {
if (ovcm) if (ovcm)
m_options |= 0x04U; m_options |= 0x04U;
else
m_options &= 0xFBU;
} }
unsigned int CDMRLC::getSrcId() const unsigned int CDMRLC::getSrcId() const

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2015,2016,2019 by Jonathan Naylor G4KLX * Copyright (C) 2015,2016,2019,2021,2022 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

View file

@ -30,7 +30,8 @@ CThread(),
m_filename(filename), m_filename(filename),
m_reloadTime(reloadTime), m_reloadTime(reloadTime),
m_table(), m_table(),
m_stop(false) m_stop(false),
m_reload(false)
{ {
} }
@ -48,6 +49,14 @@ bool CDMRLookup::read()
return ret; return ret;
} }
void CDMRLookup::reload()
{
if (m_reloadTime == 0U)
m_table.load(m_filename);
else
m_reload = true;
}
void CDMRLookup::entry() void CDMRLookup::entry()
{ {
LogInfo("Started the DMR Id lookup reload thread"); LogInfo("Started the DMR Id lookup reload thread");
@ -59,9 +68,10 @@ void CDMRLookup::entry()
sleep(1000U); sleep(1000U);
timer.clock(); timer.clock();
if (timer.hasExpired()) { if (timer.hasExpired() || m_reload) {
m_table.load(m_filename); m_table.load(m_filename);
timer.start(); timer.start();
m_reload = false;
} }
} }
@ -82,7 +92,7 @@ void CDMRLookup::stop()
void CDMRLookup::findWithName(unsigned int id, class CUserDBentry *entry) void CDMRLookup::findWithName(unsigned int id, class CUserDBentry *entry)
{ {
if (id == 0xFFFFFFU) { if (id == 0xFFFFFFFU) {
entry->clear(); entry->clear();
entry->set(keyCALLSIGN, "ALL"); entry->set(keyCALLSIGN, "ALL");
return; return;
@ -105,7 +115,7 @@ std::string CDMRLookup::find(unsigned int id)
{ {
std::string callsign; std::string callsign;
if (id == 0xFFFFFFU) if (id == 0xFFFFFFFU)
return std::string("ALL"); return std::string("ALL");
class CUserDBentry entry; class CUserDBentry entry;

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2016,2017 by Jonathan Naylor G4KLX * Copyright (C) 2016,2017,2021 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
@ -31,6 +31,8 @@ public:
bool read(); bool read();
void reload();
virtual void entry(); virtual void entry();
std::string find(unsigned int id); std::string find(unsigned int id);
@ -45,6 +47,7 @@ private:
unsigned int m_reloadTime; unsigned int m_reloadTime;
class CUserDB m_table; class CUserDB m_table;
bool m_stop; bool m_stop;
bool m_reload;
}; };
#endif #endif

View file

@ -18,425 +18,6 @@
#include "DMRNetwork.h" #include "DMRNetwork.h"
#include "StopWatch.h" IDMRNetwork::~IDMRNetwork()
#include "Utils.h"
#include "Log.h"
#include <cstdio>
#include <cassert>
#include <cstring>
#include <cstdlib>
const unsigned int BUFFER_LENGTH = 500U;
const unsigned int HOMEBREW_DATA_PACKET_LENGTH = 55U;
CDMRNetwork::CDMRNetwork(const std::string& address, unsigned int port, unsigned int local, unsigned int id, bool duplex, const char* version, bool debug, bool slot1, bool slot2, HW_TYPE hwType) :
m_addressStr(address),
m_addr(),
m_addrLen(0U),
m_port(port),
m_id(NULL),
m_duplex(duplex),
m_version(version),
m_debug(debug),
m_socket(local),
m_enabled(false),
m_slot1(slot1),
m_slot2(slot2),
m_hwType(hwType),
m_buffer(NULL),
m_streamId(NULL),
m_rxData(1000U, "DMR Network"),
m_beacon(false),
m_random(),
m_callsign(),
m_rxFrequency(0U),
m_txFrequency(0U),
m_power(0U),
m_colorCode(0U),
m_pingTimer(1000U, 10U)
{ {
assert(!address.empty());
assert(port > 0U);
assert(id > 1000U);
if (CUDPSocket::lookup(m_addressStr, m_port, m_addr, m_addrLen) != 0)
m_addrLen = 0U;
m_buffer = new unsigned char[BUFFER_LENGTH];
m_id = new uint8_t[4U];
m_streamId = new uint32_t[2U];
m_id[0U] = id >> 24;
m_id[1U] = id >> 16;
m_id[2U] = id >> 8;
m_id[3U] = id >> 0;
std::random_device rd;
std::mt19937 mt(rd());
m_random = mt;
std::uniform_int_distribution<uint32_t> dist(0x00000001, 0xfffffffe);
m_streamId[0U] = dist(m_random);
m_streamId[1U] = dist(m_random);
}
CDMRNetwork::~CDMRNetwork()
{
delete[] m_buffer;
delete[] m_streamId;
delete[] m_id;
}
void CDMRNetwork::setConfig(const std::string & callsign, unsigned int rxFrequency, unsigned int txFrequency, unsigned int power, unsigned int colorCode)
{
m_callsign = callsign;
m_rxFrequency = rxFrequency;
m_txFrequency = txFrequency;
m_power = power;
m_colorCode = colorCode;
}
bool CDMRNetwork::open()
{
if (m_addrLen == 0U) {
LogError("Unable to resolve the address of the DMR Gateway");
return false;
}
LogMessage("DMR, Opening DMR Network");
bool ret = m_socket.open(m_addr);
if (ret)
m_pingTimer.start();
return ret;
}
void CDMRNetwork::enable(bool enabled)
{
if (!enabled && m_enabled)
m_rxData.clear();
m_enabled = enabled;
}
bool CDMRNetwork::read(CDMRData& data)
{
if (m_rxData.isEmpty())
return false;
unsigned char length = 0U;
m_rxData.getData(&length, 1U);
m_rxData.getData(m_buffer, length);
// Is this a data packet?
if (::memcmp(m_buffer, "DMRD", 4U) != 0)
return false;
unsigned char seqNo = m_buffer[4U];
unsigned int srcId = (m_buffer[5U] << 16) | (m_buffer[6U] << 8) | (m_buffer[7U] << 0);
unsigned int dstId = (m_buffer[8U] << 16) | (m_buffer[9U] << 8) | (m_buffer[10U] << 0);
unsigned int slotNo = (m_buffer[15U] & 0x80U) == 0x80U ? 2U : 1U;
// DMO mode slot disabling
if (slotNo == 1U && !m_duplex)
return false;
// Individual slot disabling
if (slotNo == 1U && !m_slot1)
return false;
if (slotNo == 2U && !m_slot2)
return false;
FLCO flco = (m_buffer[15U] & 0x40U) == 0x40U ? FLCO_USER_USER : FLCO_GROUP;
data.setSeqNo(seqNo);
data.setSlotNo(slotNo);
data.setSrcId(srcId);
data.setDstId(dstId);
data.setFLCO(flco);
bool dataSync = (m_buffer[15U] & 0x20U) == 0x20U;
bool voiceSync = (m_buffer[15U] & 0x10U) == 0x10U;
if (dataSync) {
unsigned char dataType = m_buffer[15U] & 0x0FU;
data.setData(m_buffer + 20U);
data.setDataType(dataType);
data.setN(0U);
} else if (voiceSync) {
data.setData(m_buffer + 20U);
data.setDataType(DT_VOICE_SYNC);
data.setN(0U);
} else {
unsigned char n = m_buffer[15U] & 0x0FU;
data.setData(m_buffer + 20U);
data.setDataType(DT_VOICE);
data.setN(n);
}
return true;
}
bool CDMRNetwork::write(const CDMRData& data)
{
unsigned char buffer[HOMEBREW_DATA_PACKET_LENGTH];
::memset(buffer, 0x00U, HOMEBREW_DATA_PACKET_LENGTH);
buffer[0U] = 'D';
buffer[1U] = 'M';
buffer[2U] = 'R';
buffer[3U] = 'D';
unsigned int srcId = data.getSrcId();
buffer[5U] = srcId >> 16;
buffer[6U] = srcId >> 8;
buffer[7U] = srcId >> 0;
unsigned int dstId = data.getDstId();
buffer[8U] = dstId >> 16;
buffer[9U] = dstId >> 8;
buffer[10U] = dstId >> 0;
::memcpy(buffer + 11U, m_id, 4U);
unsigned int slotNo = data.getSlotNo();
// Individual slot disabling
if (slotNo == 1U && !m_slot1)
return false;
if (slotNo == 2U && !m_slot2)
return false;
buffer[15U] = slotNo == 1U ? 0x00U : 0x80U;
FLCO flco = data.getFLCO();
buffer[15U] |= flco == FLCO_GROUP ? 0x00U : 0x40U;
unsigned int slotIndex = slotNo - 1U;
std::uniform_int_distribution<uint32_t> dist(0x00000001, 0xfffffffe);
unsigned char dataType = data.getDataType();
if (dataType == DT_VOICE_SYNC) {
buffer[15U] |= 0x10U;
} else if (dataType == DT_VOICE) {
buffer[15U] |= data.getN();
} else {
if (dataType == DT_VOICE_LC_HEADER)
m_streamId[slotIndex] = dist(m_random);
if (dataType == DT_CSBK || dataType == DT_DATA_HEADER)
m_streamId[slotIndex] = dist(m_random);
buffer[15U] |= (0x20U | dataType);
}
buffer[4U] = data.getSeqNo();
::memcpy(buffer + 16U, m_streamId + slotIndex, 4U);
data.getData(buffer + 20U);
buffer[53U] = data.getBER();
buffer[54U] = data.getRSSI();
write(buffer, HOMEBREW_DATA_PACKET_LENGTH);
return true;
}
bool CDMRNetwork::writeRadioPosition(unsigned int id, const unsigned char* data)
{
unsigned char buffer[20U];
::memcpy(buffer + 0U, "DMRG", 4U);
buffer[4U] = id >> 16;
buffer[5U] = id >> 8;
buffer[6U] = id >> 0;
::memcpy(buffer + 7U, data + 2U, 7U);
return write(buffer, 14U);
}
bool CDMRNetwork::writeTalkerAlias(unsigned int id, unsigned char type, const unsigned char* data)
{
unsigned char buffer[20U];
::memcpy(buffer + 0U, "DMRA", 4U);
buffer[4U] = id >> 16;
buffer[5U] = id >> 8;
buffer[6U] = id >> 0;
buffer[7U] = type;
::memcpy(buffer + 8U, data + 2U, 7U);
return write(buffer, 15U);
}
void CDMRNetwork::close()
{
LogMessage("DMR, Closing DMR Network");
m_socket.close();
}
void CDMRNetwork::clock(unsigned int ms)
{
m_pingTimer.clock(ms);
if (m_pingTimer.isRunning() && m_pingTimer.hasExpired()) {
writeConfig();
m_pingTimer.start();
}
sockaddr_storage address;
unsigned int addrLen;
int length = m_socket.read(m_buffer, BUFFER_LENGTH, address, addrLen);
if (length <= 0)
return;
if (!CUDPSocket::match(m_addr, address)) {
LogMessage("DMR, packet received from an invalid source");
return;
}
if (m_debug)
CUtils::dump(1U, "Network Received", m_buffer, length);
if (::memcmp(m_buffer, "DMRD", 4U) == 0) {
if (m_enabled) {
unsigned char len = length;
m_rxData.addData(&len, 1U);
m_rxData.addData(m_buffer, len);
}
} else if (::memcmp(m_buffer, "DMRP", 4U) == 0) {
;
} else if (::memcmp(m_buffer, "DMRB", 4U) == 0) {
m_beacon = true;
} else {
CUtils::dump("DMR, unknown packet from the DMR Gateway", m_buffer, length);
}
}
bool CDMRNetwork::writeConfig()
{
const char* software;
char slots = '0';
if (m_duplex) {
if (m_slot1 && m_slot2)
slots = '3';
else if (m_slot1 && !m_slot2)
slots = '1';
else if (!m_slot1 && m_slot2)
slots = '2';
switch (m_hwType) {
case HWT_MMDVM:
software = "MMDVM";
break;
case HWT_MMDVM_HS:
software = "MMDVM_MMDVM_HS";
break;
case HWT_MMDVM_HS_DUAL_HAT:
software = "MMDVM_MMDVM_HS_Dual_Hat";
break;
case HWT_NANO_HOTSPOT:
software = "MMDVM_Nano_hotSPOT";
break;
default:
software = "MMDVM_Unknown";
break;
}
} else {
slots = '4';
switch (m_hwType) {
case HWT_MMDVM:
software = "MMDVM_DMO";
break;
case HWT_DVMEGA:
software = "MMDVM_DVMega";
break;
case HWT_MMDVM_ZUMSPOT:
software = "MMDVM_ZUMspot";
break;
case HWT_MMDVM_HS_HAT:
software = "MMDVM_MMDVM_HS_Hat";
break;
case HWT_MMDVM_HS_DUAL_HAT:
software = "MMDVM_MMDVM_HS_Dual_Hat";
break;
case HWT_NANO_HOTSPOT:
software = "MMDVM_Nano_hotSPOT";
break;
case HWT_NANO_DV:
software = "MMDVM_Nano_DV";
break;
case HWT_D2RG_MMDVM_HS:
software = "MMDVM_D2RG_MMDVM_HS";
break;
case HWT_MMDVM_HS:
software = "MMDVM_MMDVM_HS";
break;
case HWT_OPENGD77_HS:
software = "MMDVM_OpenGD77_HS";
break;
case HWT_SKYBRIDGE:
software = "MMDVM_SkyBridge";
break;
default:
software = "MMDVM_Unknown";
break;
}
}
unsigned int power = m_power;
if (power > 99U)
power = 99U;
char buffer[150U];
::memcpy(buffer + 0U, "DMRC", 4U);
::memcpy(buffer + 4U, m_id, 4U);
::sprintf(buffer + 8U, "%-8.8s%09u%09u%02u%02u%c%-40.40s%-40.40s",
m_callsign.c_str(), m_rxFrequency, m_txFrequency, power, m_colorCode, slots, m_version,
software);
return write((unsigned char*)buffer, 119U);
}
bool CDMRNetwork::wantsBeacon()
{
bool beacon = m_beacon;
m_beacon = false;
return beacon;
}
bool CDMRNetwork::write(const unsigned char* data, unsigned int length)
{
assert(data != NULL);
assert(length > 0U);
if (m_debug)
CUtils::dump(1U, "Network Transmitted", data, length);
bool ret = m_socket.write(data, length, m_addr, m_addrLen);
if (!ret) {
LogError("DMR, socket error when writing to the DMR Gateway");
return false;
}
return true;
} }

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2015,2016,2017,2018,2020 by Jonathan Naylor G4KLX * Copyright (C) 2015,2016,2017,2018,2020,2021 by Jonathan Naylor G4KLX
* *
* 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
@ -19,71 +19,40 @@
#if !defined(DMRNetwork_H) #if !defined(DMRNetwork_H)
#define DMRNetwork_H #define DMRNetwork_H
#include "UDPSocket.h"
#include "Timer.h"
#include "RingBuffer.h"
#include "DMRData.h" #include "DMRData.h"
#include "Defines.h"
#include <string> #include <string>
#include <cstdint>
#include <random>
class CDMRNetwork class IDMRNetwork
{ {
public: public:
CDMRNetwork(const std::string& address, unsigned int port, unsigned int local, unsigned int id, bool duplex, const char* version, bool debug, bool slot1, bool slot2, HW_TYPE hwType); virtual ~IDMRNetwork() = 0;
~CDMRNetwork();
void setConfig(const std::string& callsign, unsigned int rxFrequency, unsigned int txFrequency, unsigned int power, unsigned int colorCode); virtual void setOptions(const std::string& options) = 0;
bool open(); virtual void setConfig(const std::string& callsign, unsigned int rxFrequency, unsigned int txFrequency, unsigned int power, unsigned int colorCode, float latitude, float longitude, int height, const std::string& location, const std::string& description, const std::string& url) = 0;
void enable(bool enabled); virtual bool open() = 0;
bool read(CDMRData& data); virtual void enable(bool enabled) = 0;
bool write(const CDMRData& data); virtual bool read(CDMRData& data) = 0;
bool writeRadioPosition(unsigned int id, const unsigned char* data); virtual bool write(const CDMRData& data) = 0;
bool writeTalkerAlias(unsigned int id, unsigned char type, const unsigned char* data); virtual bool writeRadioPosition(unsigned int id, const unsigned char* data) = 0;
bool wantsBeacon(); virtual bool writeTalkerAlias(unsigned int id, unsigned char type, const unsigned char* data) = 0;
void clock(unsigned int ms); virtual bool wantsBeacon() = 0;
void close(); virtual void clock(unsigned int ms) = 0;
virtual bool isConnected() const = 0;
virtual void close(bool sayGoodbye) = 0;
private: private:
std::string m_addressStr;
sockaddr_storage m_addr;
unsigned int m_addrLen;
unsigned int m_port;
uint8_t* m_id;
bool m_duplex;
const char* m_version;
bool m_debug;
CUDPSocket m_socket;
bool m_enabled;
bool m_slot1;
bool m_slot2;
HW_TYPE m_hwType;
unsigned char* m_buffer;
uint32_t* m_streamId;
CRingBuffer<unsigned char> m_rxData;
bool m_beacon;
std::mt19937 m_random;
std::string m_callsign;
unsigned int m_rxFrequency;
unsigned int m_txFrequency;
unsigned int m_power;
unsigned int m_colorCode;
CTimer m_pingTimer;
bool writeConfig();
bool write(const unsigned char* data, unsigned int length);
}; };
#endif #endif

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2015-2020 Jonathan Naylor, G4KLX * Copyright (C) 2015-2021 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
@ -38,7 +38,7 @@ bool CDMRSlot::m_embeddedLCOnly = false;
bool CDMRSlot::m_dumpTAData = true; bool CDMRSlot::m_dumpTAData = true;
CModem* CDMRSlot::m_modem = NULL; CModem* CDMRSlot::m_modem = NULL;
CDMRNetwork* CDMRSlot::m_network = NULL; IDMRNetwork* CDMRSlot::m_network = NULL;
CDisplay* CDMRSlot::m_display = NULL; CDisplay* CDMRSlot::m_display = NULL;
bool CDMRSlot::m_duplex = true; bool CDMRSlot::m_duplex = true;
CDMRLookup* CDMRSlot::m_lookup = NULL; CDMRLookup* CDMRSlot::m_lookup = NULL;
@ -224,16 +224,22 @@ bool CDMRSlot::writeModem(unsigned char *data, unsigned int len)
if (!CDMRAccessControl::validateSrcId(srcId)) { if (!CDMRAccessControl::validateSrcId(srcId)) {
LogMessage("DMR Slot %u, RF user %u rejected", m_slotNo, srcId); LogMessage("DMR Slot %u, RF user %u rejected", m_slotNo, srcId);
delete lc; delete lc;
m_rfState = RS_RF_LISTENING;
return false; return false;
} }
if (!CDMRAccessControl::validateTGId(m_slotNo, flco == FLCO_GROUP, dstId)) { if (!CDMRAccessControl::validateTGId(m_slotNo, flco == FLCO_GROUP, dstId)) {
LogMessage("DMR Slot %u, RF user %u rejected for using TG %u", m_slotNo, srcId, dstId); LogMessage("DMR Slot %u, RF user %u rejected for using TG %u", m_slotNo, srcId, dstId);
delete lc; delete lc;
m_rfState = RS_RF_LISTENING;
return false; return false;
} }
lc->setOVCM(m_ovcm == DMR_OVCM_TX_ON || m_ovcm == DMR_OVCM_ON); if (m_ovcm == DMR_OVCM_TX_ON || m_ovcm == DMR_OVCM_ON)
lc->setOVCM(true);
else if (m_ovcm == DMR_OVCM_FORCE_OFF)
lc->setOVCM(false);
m_rfLC = lc; m_rfLC = lc;
// The standby LC data // The standby LC data
@ -378,11 +384,13 @@ bool CDMRSlot::writeModem(unsigned char *data, unsigned int len)
if (!CDMRAccessControl::validateSrcId(srcId)) { if (!CDMRAccessControl::validateSrcId(srcId)) {
LogMessage("DMR Slot %u, RF user %u rejected", m_slotNo, srcId); LogMessage("DMR Slot %u, RF user %u rejected", m_slotNo, srcId);
m_rfState = RS_RF_LISTENING;
return false; return false;
} }
if (!CDMRAccessControl::validateTGId(m_slotNo, gi, dstId)) { if (!CDMRAccessControl::validateTGId(m_slotNo, gi, dstId)) {
LogMessage("DMR Slot %u, RF user %u rejected for using TG %u", m_slotNo, srcId, dstId); LogMessage("DMR Slot %u, RF user %u rejected for using TG %u", m_slotNo, srcId, dstId);
m_rfState = RS_RF_LISTENING;
return false; return false;
} }
@ -437,7 +445,10 @@ bool CDMRSlot::writeModem(unsigned char *data, unsigned int len)
return false; return false;
// set the OVCM bit for the supported csbk // set the OVCM bit for the supported csbk
csbk.setOVCM(m_ovcm == DMR_OVCM_TX_ON || m_ovcm == DMR_OVCM_ON); if (m_ovcm == DMR_OVCM_TX_ON || m_ovcm == DMR_OVCM_ON)
csbk.setOVCM(true);
else if (m_ovcm == DMR_OVCM_FORCE_OFF)
csbk.setOVCM(false);
bool gi = csbk.getGI(); bool gi = csbk.getGI();
unsigned int srcId = csbk.getSrcId(); unsigned int srcId = csbk.getSrcId();
@ -446,11 +457,13 @@ bool CDMRSlot::writeModem(unsigned char *data, unsigned int len)
if (srcId != 0U || dstId != 0U) { if (srcId != 0U || dstId != 0U) {
if (!CDMRAccessControl::validateSrcId(srcId)) { if (!CDMRAccessControl::validateSrcId(srcId)) {
LogMessage("DMR Slot %u, RF user %u rejected", m_slotNo, srcId); LogMessage("DMR Slot %u, RF user %u rejected", m_slotNo, srcId);
m_rfState = RS_RF_LISTENING;
return false; return false;
} }
if (!CDMRAccessControl::validateTGId(m_slotNo, gi, dstId)) { if (!CDMRAccessControl::validateTGId(m_slotNo, gi, dstId)) {
LogMessage("DMR Slot %u, RF user %u rejected for using TG %u", m_slotNo, srcId, dstId); LogMessage("DMR Slot %u, RF user %u rejected for using TG %u", m_slotNo, srcId, dstId);
m_rfState = RS_RF_LISTENING;
return false; return false;
} }
} }
@ -494,6 +507,9 @@ bool CDMRSlot::writeModem(unsigned char *data, unsigned int len)
case CSBKO_CALL_ALERT_ACK: case CSBKO_CALL_ALERT_ACK:
LogMessage("DMR Slot %u, received RF Call Alert Ack CSBK from %s to %s%s", m_slotNo, src.c_str(), gi ? "TG " : "", dst.c_str()); LogMessage("DMR Slot %u, received RF Call Alert Ack CSBK from %s to %s%s", m_slotNo, src.c_str(), gi ? "TG " : "", dst.c_str());
break; break;
case CSBKO_RADIO_CHECK:
LogMessage("DMR Slot %u, received RF Radio Check %s CSBK from %s to %s%s", m_slotNo, /* TBD */ 1 ? "Req" : "Ack", src.c_str(), gi ? "TG " : "", dst.c_str());
break;
default: default:
LogWarning("DMR Slot %u, unhandled RF CSBK type - 0x%02X", m_slotNo, csbko); LogWarning("DMR Slot %u, unhandled RF CSBK type - 0x%02X", m_slotNo, csbko);
break; break;
@ -656,7 +672,7 @@ bool CDMRSlot::writeModem(unsigned char *data, unsigned int len)
if (!(m_rfTalkerId & TALKER_ID_HEADER)) { if (!(m_rfTalkerId & TALKER_ID_HEADER)) {
if (m_rfTalkerId == TALKER_ID_NONE) if (m_rfTalkerId == TALKER_ID_NONE)
m_rfTalkerAlias.reset(); m_rfTalkerAlias.reset();
m_rfTalkerAlias.add(0, data, 7U); m_rfTalkerAlias.add(0, data + 2U, 7U);
m_display->writeDMRTA(m_slotNo, (unsigned char*)m_rfTalkerAlias.get(), "R"); m_display->writeDMRTA(m_slotNo, (unsigned char*)m_rfTalkerAlias.get(), "R");
if (m_dumpTAData) { if (m_dumpTAData) {
@ -675,7 +691,7 @@ bool CDMRSlot::writeModem(unsigned char *data, unsigned int len)
if (!(m_rfTalkerId & TALKER_ID_BLOCK1)) { if (!(m_rfTalkerId & TALKER_ID_BLOCK1)) {
if (m_rfTalkerId == TALKER_ID_NONE) if (m_rfTalkerId == TALKER_ID_NONE)
m_rfTalkerAlias.reset(); m_rfTalkerAlias.reset();
m_rfTalkerAlias.add(1, data, 7U); m_rfTalkerAlias.add(1, data + 2U, 7U);
m_display->writeDMRTA(m_slotNo, (unsigned char*)m_rfTalkerAlias.get(), "R"); m_display->writeDMRTA(m_slotNo, (unsigned char*)m_rfTalkerAlias.get(), "R");
if (m_dumpTAData) { if (m_dumpTAData) {
@ -694,7 +710,7 @@ bool CDMRSlot::writeModem(unsigned char *data, unsigned int len)
if (!(m_rfTalkerId & TALKER_ID_BLOCK2)) { if (!(m_rfTalkerId & TALKER_ID_BLOCK2)) {
if (m_rfTalkerId == TALKER_ID_NONE) if (m_rfTalkerId == TALKER_ID_NONE)
m_rfTalkerAlias.reset(); m_rfTalkerAlias.reset();
m_rfTalkerAlias.add(2, data, 7U); m_rfTalkerAlias.add(2, data + 2U, 7U);
m_display->writeDMRTA(m_slotNo, (unsigned char*)m_rfTalkerAlias.get(), "R"); m_display->writeDMRTA(m_slotNo, (unsigned char*)m_rfTalkerAlias.get(), "R");
if (m_dumpTAData) { if (m_dumpTAData) {
@ -713,7 +729,7 @@ bool CDMRSlot::writeModem(unsigned char *data, unsigned int len)
if (!(m_rfTalkerId & TALKER_ID_BLOCK3)) { if (!(m_rfTalkerId & TALKER_ID_BLOCK3)) {
if (m_rfTalkerId == TALKER_ID_NONE) if (m_rfTalkerId == TALKER_ID_NONE)
m_rfTalkerAlias.reset(); m_rfTalkerAlias.reset();
m_rfTalkerAlias.add(3, data, 7U); m_rfTalkerAlias.add(3, data + 2U, 7U);
m_display->writeDMRTA(m_slotNo, (unsigned char*)m_rfTalkerAlias.get(), "R"); m_display->writeDMRTA(m_slotNo, (unsigned char*)m_rfTalkerAlias.get(), "R");
if (m_dumpTAData) { if (m_dumpTAData) {
@ -785,16 +801,22 @@ bool CDMRSlot::writeModem(unsigned char *data, unsigned int len)
if (!CDMRAccessControl::validateSrcId(srcId)) { if (!CDMRAccessControl::validateSrcId(srcId)) {
LogMessage("DMR Slot %u, RF user %u rejected", m_slotNo, srcId); LogMessage("DMR Slot %u, RF user %u rejected", m_slotNo, srcId);
delete lc; delete lc;
m_rfState = RS_RF_LISTENING;
return false; return false;
} }
if (!CDMRAccessControl::validateTGId(m_slotNo, flco == FLCO_GROUP, dstId)) { if (!CDMRAccessControl::validateTGId(m_slotNo, flco == FLCO_GROUP, dstId)) {
LogMessage("DMR Slot %u, RF user %u rejected for using TG %u", m_slotNo, srcId, dstId); LogMessage("DMR Slot %u, RF user %u rejected for using TG %u", m_slotNo, srcId, dstId);
delete lc; delete lc;
m_rfState = RS_RF_LISTENING;
return false; return false;
} }
lc->setOVCM(m_ovcm == DMR_OVCM_TX_ON || m_ovcm == DMR_OVCM_ON); if (m_ovcm == DMR_OVCM_TX_ON || m_ovcm == DMR_OVCM_ON)
lc->setOVCM(true);
else if (m_ovcm == DMR_OVCM_FORCE_OFF)
lc->setOVCM(false);
m_rfLC = lc; m_rfLC = lc;
// The standby LC data // The standby LC data
@ -1050,7 +1072,11 @@ void CDMRSlot::writeNetwork(const CDMRData& dmrData)
dmrData.getSrcId(), dmrData.getFLCO() == FLCO_GROUP ? "TG" : "", dmrData.getDstId(), dmrData.getSrcId(), dmrData.getFLCO() == FLCO_GROUP ? "TG" : "", dmrData.getDstId(),
srcId, flco == FLCO_GROUP ? "TG" : "", dstId); srcId, flco == FLCO_GROUP ? "TG" : "", dstId);
lc->setOVCM(m_ovcm == DMR_OVCM_RX_ON || m_ovcm == DMR_OVCM_ON); if (m_ovcm == DMR_OVCM_RX_ON || m_ovcm == DMR_OVCM_ON)
lc->setOVCM(true);
else if (m_ovcm == DMR_OVCM_FORCE_OFF)
lc->setOVCM(false);
m_netLC = lc; m_netLC = lc;
// The standby LC data // The standby LC data
@ -1125,7 +1151,11 @@ void CDMRSlot::writeNetwork(const CDMRData& dmrData)
unsigned int dstId = lc->getDstId(); unsigned int dstId = lc->getDstId();
unsigned int srcId = lc->getSrcId(); unsigned int srcId = lc->getSrcId();
lc->setOVCM(m_ovcm == DMR_OVCM_RX_ON || m_ovcm == DMR_OVCM_ON); if (m_ovcm == DMR_OVCM_RX_ON || m_ovcm == DMR_OVCM_ON)
lc->setOVCM(true);
else if (m_ovcm == DMR_OVCM_FORCE_OFF)
lc->setOVCM(false);
m_netLC = lc; m_netLC = lc;
m_lastFrameValid = false; m_lastFrameValid = false;
@ -1312,7 +1342,11 @@ void CDMRSlot::writeNetwork(const CDMRData& dmrData)
unsigned int dstId = lc->getDstId(); unsigned int dstId = lc->getDstId();
unsigned int srcId = lc->getSrcId(); unsigned int srcId = lc->getSrcId();
lc->setOVCM(m_ovcm == DMR_OVCM_RX_ON || m_ovcm == DMR_OVCM_ON); if (m_ovcm == DMR_OVCM_RX_ON || m_ovcm == DMR_OVCM_ON)
lc->setOVCM(true);
else if (m_ovcm == DMR_OVCM_FORCE_OFF)
lc->setOVCM(false);
m_netLC = lc; m_netLC = lc;
// The standby LC data // The standby LC data
@ -1584,7 +1618,10 @@ void CDMRSlot::writeNetwork(const CDMRData& dmrData)
return; return;
// set the OVCM bit for the supported csbk // set the OVCM bit for the supported csbk
csbk.setOVCM(m_ovcm == DMR_OVCM_RX_ON || m_ovcm == DMR_OVCM_ON); if (m_ovcm == DMR_OVCM_RX_ON || m_ovcm == DMR_OVCM_ON)
csbk.setOVCM(true);
else if (m_ovcm == DMR_OVCM_FORCE_OFF)
csbk.setOVCM(false);
bool gi = csbk.getGI(); bool gi = csbk.getGI();
unsigned int srcId = csbk.getSrcId(); unsigned int srcId = csbk.getSrcId();
@ -1656,6 +1693,9 @@ void CDMRSlot::writeNetwork(const CDMRData& dmrData)
case CSBKO_CALL_ALERT_ACK: case CSBKO_CALL_ALERT_ACK:
LogMessage("DMR Slot %u, received network Call Alert Ack CSBK from %s to %s%s", m_slotNo, src.c_str(), gi ? "TG " : "", dst.c_str()); LogMessage("DMR Slot %u, received network Call Alert Ack CSBK from %s to %s%s", m_slotNo, src.c_str(), gi ? "TG " : "", dst.c_str());
break; break;
case CSBKO_RADIO_CHECK:
LogMessage("DMR Slot %u, received network Radio Check %s CSBK from %s to %s%s", m_slotNo, /* TBD */ 1 ? "Req" : "Ack", src.c_str(), gi ? "TG " : "", dst.c_str());
break;
default: default:
LogWarning("DMR Slot %u, unhandled network CSBK type - 0x%02X", m_slotNo, csbko); LogWarning("DMR Slot %u, unhandled network CSBK type - 0x%02X", m_slotNo, csbko);
break; break;
@ -1896,7 +1936,7 @@ void CDMRSlot::writeQueueNet(const unsigned char *data)
m_queue.addData(data, len); m_queue.addData(data, len);
} }
void CDMRSlot::init(unsigned int colorCode, bool embeddedLCOnly, bool dumpTAData, unsigned int callHang, CModem* modem, CDMRNetwork* network, CDisplay* display, bool duplex, CDMRLookup* lookup, CRSSIInterpolator* rssiMapper, unsigned int jitter, DMR_OVCM_TYPES ovcm) void CDMRSlot::init(unsigned int colorCode, bool embeddedLCOnly, bool dumpTAData, unsigned int callHang, CModem* modem, IDMRNetwork* network, CDisplay* display, bool duplex, CDMRLookup* lookup, CRSSIInterpolator* rssiMapper, unsigned int jitter, DMR_OVCM_TYPES ovcm)
{ {
assert(modem != NULL); assert(modem != NULL);
assert(display != NULL); assert(display != NULL);

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2015-2019 by Jonathan Naylor G4KLX * Copyright (C) 2015-2021 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
@ -62,7 +62,7 @@ public:
void enable(bool enabled); void enable(bool enabled);
static void init(unsigned int colorCode, bool embeddedLCOnly, bool dumpTAData, unsigned int callHang, CModem* modem, CDMRNetwork* network, CDisplay* display, bool duplex, CDMRLookup* lookup, CRSSIInterpolator* rssiMapper, unsigned int jitter, DMR_OVCM_TYPES ovcm); static void init(unsigned int colorCode, bool embeddedLCOnly, bool dumpTAData, unsigned int callHang, CModem* modem, IDMRNetwork* network, CDisplay* display, bool duplex, CDMRLookup* lookup, CRSSIInterpolator* rssiMapper, unsigned int jitter, DMR_OVCM_TYPES ovcm);
private: private:
unsigned int m_slotNo; unsigned int m_slotNo;
@ -118,7 +118,7 @@ private:
static bool m_dumpTAData; static bool m_dumpTAData;
static CModem* m_modem; static CModem* m_modem;
static CDMRNetwork* m_network; static IDMRNetwork* m_network;
static CDisplay* m_display; static CDisplay* m_display;
static bool m_duplex; static bool m_duplex;
static CDMRLookup* m_lookup; static CDMRLookup* m_lookup;

View file

@ -1,32 +0,0 @@
# DMRplus - Startup Options
## Introduction
This file is to give an overview over the Options-parameter in MMDVM.ini [DMR Network]-section.
## Example
You can pull some conection-info at startup to the DMRplus-Network to define the behavior of TS1 and TS2 in DMR-mode.
An example of such a line would be following:
Options=StartRef=4013;RelinkTime=15;UserLink=1;TS1_1=262;TS1_2=1;TS1_3=20;TS1_4=110;TS1_5=270;
If an option is set, it overwrites the setting preset at the master, if an option is empty, it unsets a predefined setting from
the master. If an option is not set, the default from the master would be taken over.
## What the parameters are about?
Here is a quick explaination about the options to be set:
* StartRef: This is the default reflector in TS2, in example: Refl. 4013
* RelinkTime: This is the time to fall back to the default-reflector if linked to another one and no local traffic is done,
not yet implemented, would come next
* UserLink: This defines, if users are allowed to link to another reflector (other than defined as startreflector)
* 1 = allow
* 0 = disallow
* TS1_1: This is the first of 5 talkgroups that could be set static, in example: TG262
* TS1_2: This is the second of 5 talkgroups that could be set static, in example: TG1
* TS1_3: This is the third of 5 talkgroups that could be set static, in example: TG20
* TS1_4: This is the fourth of 5 talkgroups that could be set static, in example: TG110
* TS1_5: This is the fifth of 5 talkgroups that could be set static, in example: TG270
---
Info created by DG9VH 2016-11-11

File diff suppressed because it is too large Load diff

View file

@ -1,129 +0,0 @@
/*
* Copyright (C) 2015-2019 by Jonathan Naylor G4KLX
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#if !defined(DStarControl_H)
#define DStarControl_H
#include "RSSIInterpolator.h"
#include "DStarNetwork.h"
#include "DStarSlowData.h"
#include "DStarDefines.h"
#include "DStarHeader.h"
#include "RingBuffer.h"
#include "StopWatch.h"
#include "AMBEFEC.h"
#include "Display.h"
#include "Defines.h"
#include "Timer.h"
#include "Modem.h"
#include <string>
#include <vector>
class CDStarControl {
public:
CDStarControl(const std::string& callsign, const std::string& module, bool selfOnly, bool ackReply, unsigned int ackTime, bool ackMessage, bool errorReply, const std::vector<std::string>& blackList, const std::vector<std::string>& whiteList, CDStarNetwork* network, CDisplay* display, unsigned int timeout, bool duplex, bool remoteGateway, CRSSIInterpolator* rssiMapper);
~CDStarControl();
bool writeModem(unsigned char* data, unsigned int len);
unsigned int readModem(unsigned char* data);
void clock();
bool isBusy() const;
void enable(bool enabled);
private:
unsigned char* m_callsign;
unsigned char* m_gateway;
bool m_selfOnly;
bool m_ackReply;
bool m_ackMessage;
bool m_errorReply;
bool m_remoteGateway;
std::vector<std::string> m_blackList;
std::vector<std::string> m_whiteList;
CDStarNetwork* m_network;
CDisplay* m_display;
bool m_duplex;
CRingBuffer<unsigned char> m_queue;
CDStarHeader m_rfHeader;
CDStarHeader m_netHeader;
RPT_RF_STATE m_rfState;
RPT_NET_STATE m_netState;
bool m_net;
CDStarSlowData m_slowData;
unsigned char m_rfN;
unsigned char m_netN;
CTimer m_networkWatchdog;
CTimer m_rfTimeoutTimer;
CTimer m_netTimeoutTimer;
CTimer m_packetTimer;
CTimer m_ackTimer;
CTimer m_errTimer;
CStopWatch m_interval;
CStopWatch m_elapsed;
unsigned int m_rfFrames;
unsigned int m_netFrames;
unsigned int m_netLost;
CAMBEFEC m_fec;
unsigned int m_rfBits;
unsigned int m_netBits;
unsigned int m_rfErrs;
unsigned int m_netErrs;
unsigned char* m_lastFrame;
bool m_lastFrameValid;
CRSSIInterpolator* m_rssiMapper;
unsigned char m_rssi;
unsigned char m_maxRSSI;
unsigned char m_minRSSI;
unsigned int m_aveRSSI;
unsigned int m_rssiCount;
bool m_enabled;
FILE* m_fp;
void writeNetwork();
void writeQueueHeaderRF(const unsigned char* data);
void writeQueueDataRF(const unsigned char* data);
void writeQueueEOTRF();
void writeQueueHeaderNet(const unsigned char* data);
void writeQueueDataNet(const unsigned char* data);
void writeQueueEOTNet();
void writeNetworkHeaderRF(const unsigned char* data);
void writeNetworkDataRF(const unsigned char* data, unsigned int errors, bool end);
void writeEndRF();
void writeEndNet();
bool openFile();
bool writeFile(const unsigned char* data, unsigned int length);
void closeFile();
bool insertSilence(const unsigned char* data, unsigned char seqNo);
void insertSilence(unsigned int count);
void blankDTMF(unsigned char* data) const;
void sendAck();
void sendError();
};
#endif

View file

@ -1,92 +0,0 @@
/*
* Copyright (C) 2015,2016,2018,2019 by Jonathan Naylor G4KLX
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#if !defined(DStarDefines_H)
#define DStarDefines_H
#include "Defines.h"
const unsigned int DSTAR_HEADER_LENGTH_BYTES = 41U;
const unsigned int DSTAR_FRAME_LENGTH_BYTES = 12U;
const unsigned char DSTAR_END_PATTERN_BYTES[] = { TAG_EOT, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0xC8, 0x7A };
const unsigned int DSTAR_END_PATTERN_LENGTH_BYTES = 6U;
const unsigned char DSTAR_NULL_AMBE_DATA_BYTES[] = { 0x9E, 0x8D, 0x32, 0x88, 0x26, 0x1A, 0x3F, 0x61, 0xE8 };
const unsigned char DSTAR_NULL_SLOW_SYNC_BYTES[] = { 0x55, 0x2D, 0x16 };
// Note that these are already scrambled, 0x66 0x66 0x66 otherwise
const unsigned char DSTAR_NULL_SLOW_DATA_BYTES[] = { 0x16, 0x29, 0xF5 };
const unsigned char DSTAR_NULL_FRAME_SYNC_BYTES[] = { TAG_DATA, 0x9E, 0x8D, 0x32, 0x88, 0x26, 0x1A, 0x3F, 0x61, 0xE8, 0x55, 0x2D, 0x16 };
const unsigned char DSTAR_NULL_FRAME_DATA_BYTES[] = { TAG_DATA, 0x9E, 0x8D, 0x32, 0x88, 0x26, 0x1A, 0x3F, 0x61, 0xE8, 0x16, 0x29, 0xF5 };
const unsigned char DSTAR_NULL_FRAME_DATA_SRAMBLED_BYTES[] = { 0xEEU, 0xC2U, 0xA1U, 0xC8U, 0x42U, 0x6EU, 0x52U, 0x51U, 0xC3U };
const unsigned int DSTAR_VOICE_FRAME_LENGTH_BYTES = 9U;
const unsigned int DSTAR_DATA_FRAME_LENGTH_BYTES = 3U;
const unsigned int DSTAR_LONG_CALLSIGN_LENGTH = 8U;
const unsigned int DSTAR_SHORT_CALLSIGN_LENGTH = 4U;
const unsigned char DSTAR_SLOW_DATA_TYPE_MASK = 0xF0U;
const unsigned char DSTAR_SLOW_DATA_TYPE_GPSDATA = 0x30U;
const unsigned char DSTAR_SLOW_DATA_TYPE_TEXT = 0x40U;
const unsigned char DSTAR_SLOW_DATA_TYPE_HEADER = 0x50U;
const unsigned char DSTAR_SLOW_DATA_TYPE_FAST_DATA1 = 0x80U;
const unsigned char DSTAR_SLOW_DATA_TYPE_FAST_DATA2 = 0x90U;
const unsigned char DSTAR_SLOW_DATA_TYPE_SQUELCH = 0xC0U;
const unsigned char DSTAR_SLOW_DATA_LENGTH_MASK = 0x0FU;
const unsigned char DSTAR_SCRAMBLER_BYTES[] = { 0x70U, 0x4FU, 0x93U, 0x40U, 0x64U, 0x74U, 0x6DU, 0x30U, 0x2BU };
const unsigned char DSTAR_DATA_MASK = 0x80U;
const unsigned char DSTAR_REPEATER_MASK = 0x40U;
const unsigned char DSTAR_INTERRUPTED_MASK = 0x20U;
const unsigned char DSTAR_CONTROL_SIGNAL_MASK = 0x10U;
const unsigned char DSTAR_URGENT_MASK = 0x08U;
const unsigned char DSTAR_REPEATER_CONTROL = 0x07U;
const unsigned char DSTAR_AUTO_REPLY = 0x06U;
const unsigned char DSTAR_RESEND_REQUESTED = 0x04U;
const unsigned char DSTAR_ACK_FLAG = 0x03U;
const unsigned char DSTAR_NO_RESPONSE = 0x02U;
const unsigned char DSTAR_RELAY_UNAVAILABLE = 0x01U;
const unsigned char DSTAR_SYNC_BYTES[] = {0x55U, 0x2DU, 0x16U};
const unsigned char DSTAR_DTMF_MASK[] = { 0x82U, 0x08U, 0x20U, 0x82U, 0x00U, 0x00U, 0x82U, 0x00U, 0x00U };
const unsigned char DSTAR_DTMF_SIG[] = { 0x82U, 0x08U, 0x20U, 0x82U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U };
const unsigned int DSTAR_FRAME_TIME = 20U;
enum LINK_STATUS {
LS_NONE,
LS_PENDING_IRCDDB,
LS_LINKING_LOOPBACK,
LS_LINKING_DEXTRA,
LS_LINKING_DPLUS,
LS_LINKING_DCS,
LS_LINKING_CCS,
LS_LINKED_LOOPBACK,
LS_LINKED_DEXTRA,
LS_LINKED_DPLUS,
LS_LINKED_DCS,
LS_LINKED_CCS
};
#endif

View file

@ -1,165 +0,0 @@
/*
* Copyright (C) 2016 by Jonathan Naylor G4KLX
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "DStarDefines.h"
#include "DStarHeader.h"
#include "CRC.h"
#include <cstdio>
#include <cassert>
#include <cstring>
CDStarHeader::CDStarHeader(const unsigned char* header) :
m_header(NULL)
{
assert(header != NULL);
m_header = new unsigned char[DSTAR_HEADER_LENGTH_BYTES];
::memcpy(m_header, header, DSTAR_HEADER_LENGTH_BYTES);
}
CDStarHeader::CDStarHeader() :
m_header(NULL)
{
m_header = new unsigned char[DSTAR_HEADER_LENGTH_BYTES];
::memset(m_header, ' ', DSTAR_HEADER_LENGTH_BYTES);
m_header[0U] = 0x00U;
m_header[1U] = 0x00U;
m_header[2U] = 0x00U;
}
CDStarHeader::~CDStarHeader()
{
delete[] m_header;
}
CDStarHeader& CDStarHeader::operator=(const CDStarHeader& header)
{
if (&header != this)
::memcpy(m_header, header.m_header, DSTAR_HEADER_LENGTH_BYTES);
return *this;
}
bool CDStarHeader::isRepeater() const
{
return (m_header[0U] & DSTAR_REPEATER_MASK) == DSTAR_REPEATER_MASK;
}
void CDStarHeader::setRepeater(bool on)
{
if (on)
m_header[0U] |= DSTAR_REPEATER_MASK;
else
m_header[0U] &= ~DSTAR_REPEATER_MASK;
}
bool CDStarHeader::isDataPacket() const
{
return (m_header[0U] & DSTAR_DATA_MASK) == DSTAR_DATA_MASK;
}
void CDStarHeader::setUnavailable(bool on)
{
if (on)
m_header[0U] |= DSTAR_RELAY_UNAVAILABLE;
else
m_header[0U] &= ~DSTAR_RELAY_UNAVAILABLE;
}
void CDStarHeader::getMyCall1(unsigned char* call1) const
{
assert(call1 != NULL);
::memcpy(call1, m_header + 27U, DSTAR_LONG_CALLSIGN_LENGTH);
}
void CDStarHeader::getMyCall2(unsigned char* call2) const
{
assert(call2 != NULL);
::memcpy(call2, m_header + 35U, DSTAR_SHORT_CALLSIGN_LENGTH);
}
void CDStarHeader::setMyCall1(const unsigned char* call1)
{
assert(call1 != NULL);
::memcpy(m_header + 27U, call1, DSTAR_LONG_CALLSIGN_LENGTH);
}
void CDStarHeader::setMyCall2(const unsigned char* call2)
{
assert(call2 != NULL);
::memcpy(m_header + 35U, call2, DSTAR_SHORT_CALLSIGN_LENGTH);
}
void CDStarHeader::getRPTCall1(unsigned char* call1) const
{
assert(call1 != NULL);
::memcpy(call1, m_header + 11U, DSTAR_LONG_CALLSIGN_LENGTH);
}
void CDStarHeader::getRPTCall2(unsigned char* call2) const
{
assert(call2 != NULL);
::memcpy(call2, m_header + 3U, DSTAR_LONG_CALLSIGN_LENGTH);
}
void CDStarHeader::setRPTCall1(const unsigned char* call1)
{
assert(call1 != NULL);
::memcpy(m_header + 11U, call1, DSTAR_LONG_CALLSIGN_LENGTH);
}
void CDStarHeader::setRPTCall2(const unsigned char* call2)
{
assert(call2 != NULL);
::memcpy(m_header + 3U, call2, DSTAR_LONG_CALLSIGN_LENGTH);
}
void CDStarHeader::getYourCall(unsigned char* call) const
{
assert(call != NULL);
::memcpy(call, m_header + 19U, DSTAR_LONG_CALLSIGN_LENGTH);
}
void CDStarHeader::setYourCall(const unsigned char* call)
{
assert(call != NULL);
::memcpy(m_header + 19U, call, DSTAR_LONG_CALLSIGN_LENGTH);
}
void CDStarHeader::get(unsigned char* header) const
{
assert(header != NULL);
::memcpy(header, m_header, DSTAR_HEADER_LENGTH_BYTES);
CCRC::addCCITT161(header, DSTAR_HEADER_LENGTH_BYTES);
}

View file

@ -1,58 +0,0 @@
/*
* Copyright (C) 2016 by Jonathan Naylor G4KLX
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifndef DStarHeader_H
#define DStarHeader_H
class CDStarHeader {
public:
CDStarHeader(const unsigned char* header);
CDStarHeader();
~CDStarHeader();
bool isRepeater() const;
void setRepeater(bool on);
bool isDataPacket() const;
void setUnavailable(bool on);
void getMyCall1(unsigned char* call1) const;
void getMyCall2(unsigned char* call2) const;
void setMyCall1(const unsigned char* call1);
void setMyCall2(const unsigned char* call2);
void getRPTCall1(unsigned char* call1) const;
void getRPTCall2(unsigned char* call2) const;
void setRPTCall1(const unsigned char* call1);
void setRPTCall2(const unsigned char* call2);
void getYourCall(unsigned char* call) const;
void setYourCall(const unsigned char* call);
void get(unsigned char* header) const;
CDStarHeader& operator=(const CDStarHeader& header);
private:
unsigned char* m_header;
};
#endif

View file

@ -1,341 +0,0 @@
/*
* Copyright (C) 2009-2014,2016,2019,2020 by Jonathan Naylor G4KLX
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "DStarDefines.h"
#include "DStarNetwork.h"
#include "StopWatch.h"
#include "Defines.h"
#include "Utils.h"
#include "Log.h"
#include <cstdio>
#include <cassert>
#include <cstring>
#include <cstdlib>
const unsigned int BUFFER_LENGTH = 100U;
CDStarNetwork::CDStarNetwork(const std::string& gatewayAddress, unsigned int gatewayPort, unsigned int localPort, bool duplex, const char* version, bool debug) :
m_socket(localPort),
m_addr(),
m_addrLen(0U),
m_duplex(duplex),
m_version(version),
m_debug(debug),
m_enabled(false),
m_outId(0U),
m_outSeq(0U),
m_inId(0U),
m_buffer(1000U, "D-Star Network"),
m_pollTimer(1000U, 60U),
m_linkStatus(LS_NONE),
m_linkReflector(NULL),
m_random()
{
if (CUDPSocket::lookup(gatewayAddress, gatewayPort, m_addr, m_addrLen) != 0)
m_addrLen = 0U;
m_linkReflector = new unsigned char[DSTAR_LONG_CALLSIGN_LENGTH];
std::random_device rd;
std::mt19937 mt(rd());
m_random = mt;
}
CDStarNetwork::~CDStarNetwork()
{
delete[] m_linkReflector;
}
bool CDStarNetwork::open()
{
if (m_addrLen == 0U) {
LogError("Unable to resolve the address of the ircDDB Gateway");
return false;
}
LogMessage("Opening D-Star network connection");
m_pollTimer.start();
return m_socket.open(m_addr);
}
bool CDStarNetwork::writeHeader(const unsigned char* header, unsigned int length, bool busy)
{
assert(header != NULL);
unsigned char buffer[50U];
buffer[0] = 'D';
buffer[1] = 'S';
buffer[2] = 'R';
buffer[3] = 'P';
buffer[4] = busy ? 0x22U : 0x20U;
// Create a random id for this transmission
std::uniform_int_distribution<uint16_t> dist(0x0001, 0xfffe);
m_outId = dist(m_random);
buffer[5] = m_outId / 256U; // Unique session id
buffer[6] = m_outId % 256U;
buffer[7] = 0U;
::memcpy(buffer + 8U, header, length);
m_outSeq = 0U;
if (m_debug)
CUtils::dump(1U, "D-Star Network Header Sent", buffer, 49U);
for (unsigned int i = 0U; i < 2U; i++) {
bool ret = m_socket.write(buffer, 49U, m_addr, m_addrLen);
if (!ret)
return false;
}
return true;
}
bool CDStarNetwork::writeData(const unsigned char* data, unsigned int length, unsigned int errors, bool end, bool busy)
{
assert(data != NULL);
unsigned char buffer[30U];
buffer[0] = 'D';
buffer[1] = 'S';
buffer[2] = 'R';
buffer[3] = 'P';
buffer[4] = busy ? 0x23U : 0x21U;
buffer[5] = m_outId / 256U; // Unique session id
buffer[6] = m_outId % 256U;
// If this is a data sync, reset the sequence to zero
if (data[9] == 0x55 && data[10] == 0x2D && data[11] == 0x16)
m_outSeq = 0U;
buffer[7] = m_outSeq;
if (end)
buffer[7] |= 0x40U; // End of data marker
buffer[8] = errors;
m_outSeq++;
if (m_outSeq > 0x14U)
m_outSeq = 0U;
::memcpy(buffer + 9U, data, length);
if (m_debug)
CUtils::dump(1U, "D-Star Network Data Sent", buffer, length + 9U);
return m_socket.write(buffer, length + 9U, m_addr, m_addrLen);
}
bool CDStarNetwork::writePoll(const char* text)
{
assert(text != NULL);
unsigned char buffer[40U];
buffer[0] = 'D';
buffer[1] = 'S';
buffer[2] = 'R';
buffer[3] = 'P';
buffer[4] = 0x0A; // Poll with text
unsigned int length = ::strlen(text);
// Include the nul at the end also
::memcpy(buffer + 5U, text, length + 1U);
// if (m_debug)
// CUtils::dump(1U, "D-Star Network Poll Sent", buffer, 6U + length);
return m_socket.write(buffer, 6U + length, m_addr, m_addrLen);
}
void CDStarNetwork::clock(unsigned int ms)
{
m_pollTimer.clock(ms);
if (m_pollTimer.hasExpired()) {
char text[60U];
#if defined(_WIN32) || defined(_WIN64)
if (m_duplex)
::sprintf(text, "win_mmdvm-%s", m_version);
else
::sprintf(text, "win_mmdvm-dvmega-%s", m_version);
#else
if (m_duplex)
::sprintf(text, "linux_mmdvm-%s", m_version);
else
::sprintf(text, "linux_mmdvm-dvmega-%s", m_version);
#endif
writePoll(text);
m_pollTimer.start();
}
unsigned char buffer[BUFFER_LENGTH];
sockaddr_storage address;
unsigned int addrLen;
int length = m_socket.read(buffer, BUFFER_LENGTH, address, addrLen);
if (length <= 0)
return;
if (!CUDPSocket::match(m_addr, address)) {
LogMessage("D-Star, packet received from an invalid source");
return;
}
// Invalid packet type?
if (::memcmp(buffer, "DSRP", 4U) != 0)
return;
switch (buffer[4]) {
case 0x00U: // NETWORK_TEXT;
if (m_debug)
CUtils::dump(1U, "D-Star Network Status Received", buffer, length);
m_linkStatus = LINK_STATUS(buffer[25U]);
::memcpy(m_linkReflector, buffer + 26U, DSTAR_LONG_CALLSIGN_LENGTH);
LogMessage("D-Star link status set to \"%20.20s\"", buffer + 5U);
return;
case 0x01U: // NETWORK_TEMPTEXT;
case 0x04U: // NETWORK_STATUS1..5
case 0x24U: // NETWORK_DD_DATA
return;
case 0x20U: // NETWORK_HEADER
if (m_inId == 0U && m_enabled) {
if (m_debug)
CUtils::dump(1U, "D-Star Network Header Received", buffer, length);
m_inId = buffer[5] * 256U + buffer[6];
unsigned char c = length - 7U;
m_buffer.addData(&c, 1U);
c = TAG_HEADER;
m_buffer.addData(&c, 1U);
m_buffer.addData(buffer + 8U, length - 8U);
}
break;
case 0x21U: // NETWORK_DATA
if (m_enabled) {
if (m_debug)
CUtils::dump(1U, "D-Star Network Data Received", buffer, length);
uint16_t id = buffer[5] * 256U + buffer[6];
// Check that the stream id matches the valid header, reject otherwise
if (id == m_inId && m_enabled) {
unsigned char ctrl[3U];
ctrl[0U] = length - 7U;
// Is this the last packet in the stream?
if ((buffer[7] & 0x40) == 0x40) {
m_inId = 0U;
ctrl[1U] = TAG_EOT;
} else {
ctrl[1U] = TAG_DATA;
}
ctrl[2U] = buffer[7] & 0x3FU;
m_buffer.addData(ctrl, 3U);
m_buffer.addData(buffer + 9U, length - 9U);
}
}
break;
default:
CUtils::dump("Unknown D-Star packet from the Gateway", buffer, length);
break;
}
}
unsigned int CDStarNetwork::read(unsigned char* data, unsigned int length)
{
assert(data != NULL);
if (m_buffer.isEmpty())
return 0U;
unsigned char c = 0U;
m_buffer.getData(&c, 1U);
assert(c <= 100U);
assert(c <= length);
unsigned char buffer[100U];
m_buffer.getData(buffer, c);
switch (buffer[0U]) {
case TAG_HEADER:
case TAG_DATA:
case TAG_EOT:
::memcpy(data, buffer, c);
return c;
default:
return 0U;
}
}
void CDStarNetwork::reset()
{
m_inId = 0U;
}
void CDStarNetwork::close()
{
m_socket.close();
LogMessage("Closing D-Star network connection");
}
void CDStarNetwork::enable(bool enabled)
{
if (enabled && !m_enabled)
reset();
else if (!enabled && m_enabled)
m_buffer.clear();
m_enabled = enabled;
}
void CDStarNetwork::getStatus(LINK_STATUS& status, unsigned char* reflector)
{
assert(reflector != NULL);
status = m_linkStatus;
::memcpy(reflector, m_linkReflector, DSTAR_LONG_CALLSIGN_LENGTH);
}

View file

@ -1,73 +0,0 @@
/*
* Copyright (C) 2009-2014,2016,2020 by Jonathan Naylor G4KLX
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* 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 DStarNetwork_H
#define DStarNetwork_H
#include "DStarDefines.h"
#include "RingBuffer.h"
#include "UDPSocket.h"
#include "Timer.h"
#include <cstdint>
#include <string>
#include <random>
class CDStarNetwork {
public:
CDStarNetwork(const std::string& gatewayAddress, unsigned int gatewayPort, unsigned int localPort, bool duplex, const char* version, bool debug);
~CDStarNetwork();
bool open();
void enable(bool enabled);
bool writeHeader(const unsigned char* header, unsigned int length, bool busy);
bool writeData(const unsigned char* data, unsigned int length, unsigned int errors, bool end, bool busy);
void getStatus(LINK_STATUS& status, unsigned char* reflector);
unsigned int read(unsigned char* data, unsigned int length);
void reset();
void close();
void clock(unsigned int ms);
private:
CUDPSocket m_socket;
sockaddr_storage m_addr;
unsigned int m_addrLen;
bool m_duplex;
const char* m_version;
bool m_debug;
bool m_enabled;
uint16_t m_outId;
uint8_t m_outSeq;
uint16_t m_inId;
CRingBuffer<unsigned char> m_buffer;
CTimer m_pollTimer;
LINK_STATUS m_linkStatus;
unsigned char* m_linkReflector;
std::mt19937 m_random;
bool writePoll(const char* text);
};
#endif

View file

@ -1,158 +0,0 @@
/*
* Copyright (C) 2016 by Jonathan Naylor G4KLX
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "DStarSlowData.h"
#include "DStarDefines.h"
#include "CRC.h"
#include "Log.h"
#include <cstdio>
#include <cassert>
#include <cstring>
CDStarSlowData::CDStarSlowData() :
m_header(NULL),
m_ptr(0U),
m_buffer(NULL),
m_text(NULL),
m_textPtr(0U),
m_state(SDD_FIRST)
{
m_header = new unsigned char[50U]; // DSTAR_HEADER_LENGTH_BYTES
m_buffer = new unsigned char[DSTAR_DATA_FRAME_LENGTH_BYTES * 2U];
m_text = new unsigned char[24U];
}
CDStarSlowData::~CDStarSlowData()
{
delete[] m_header;
delete[] m_buffer;
delete[] m_text;
}
CDStarHeader* CDStarSlowData::add(const unsigned char* data)
{
assert(data != NULL);
switch (m_state) {
case SDD_FIRST:
m_buffer[0U] = data[9U] ^ DSTAR_SCRAMBLER_BYTES[0U];
m_buffer[1U] = data[10U] ^ DSTAR_SCRAMBLER_BYTES[1U];
m_buffer[2U] = data[11U] ^ DSTAR_SCRAMBLER_BYTES[2U];
m_state = SDD_SECOND;
return NULL;
case SDD_SECOND:
m_buffer[3U] = data[9U] ^ DSTAR_SCRAMBLER_BYTES[0U];
m_buffer[4U] = data[10U] ^ DSTAR_SCRAMBLER_BYTES[1U];
m_buffer[5U] = data[11U] ^ DSTAR_SCRAMBLER_BYTES[2U];
m_state = SDD_FIRST;
break;
}
if ((m_buffer[0U] & DSTAR_SLOW_DATA_TYPE_MASK) != DSTAR_SLOW_DATA_TYPE_HEADER)
return NULL;
if (m_ptr >= 45U)
return NULL;
::memcpy(m_header + m_ptr, m_buffer + 1U, 5U);
m_ptr += 5U;
// Clean up the data
m_header[0U] &= (DSTAR_INTERRUPTED_MASK | DSTAR_URGENT_MASK | DSTAR_REPEATER_MASK);
m_header[1U] = 0x00U;
m_header[2U] = 0x00U;
for (unsigned int i = 3U; i < 39U; i++)
m_header[i] &= 0x7FU;
// Check the CRC
bool ret = CCRC::checkCCITT161(m_header, DSTAR_HEADER_LENGTH_BYTES);
if (!ret) {
if (m_ptr == 45U)
LogMessage("D-Star, invalid slow data header");
return NULL;
}
return new CDStarHeader(m_header);
}
void CDStarSlowData::start()
{
::memset(m_header, 0x00U, DSTAR_HEADER_LENGTH_BYTES);
m_ptr = 0U;
m_state = SDD_FIRST;
}
void CDStarSlowData::reset()
{
m_ptr = 0U;
m_state = SDD_FIRST;
}
void CDStarSlowData::setText(const char* text)
{
assert(text != NULL);
m_text[0U] = DSTAR_SLOW_DATA_TYPE_TEXT | 0U;
m_text[1U] = text[0U];
m_text[2U] = text[1U];
m_text[3U] = text[2U];
m_text[4U] = text[3U];
m_text[5U] = text[4U];
m_text[6U] = DSTAR_SLOW_DATA_TYPE_TEXT | 1U;
m_text[7U] = text[5U];
m_text[8U] = text[6U];
m_text[9U] = text[7U];
m_text[10U] = text[8U];
m_text[11U] = text[9U];
m_text[12U] = DSTAR_SLOW_DATA_TYPE_TEXT | 2U;
m_text[13U] = text[10U];
m_text[14U] = text[11U];
m_text[15U] = text[12U];
m_text[16U] = text[13U];
m_text[17U] = text[14U];
m_text[18U] = DSTAR_SLOW_DATA_TYPE_TEXT | 3U;
m_text[19U] = text[15U];
m_text[20U] = text[16U];
m_text[21U] = text[17U];
m_text[22U] = text[18U];
m_text[23U] = text[19U];
m_textPtr = 0U;
}
void CDStarSlowData::get(unsigned char* data)
{
assert(data != NULL);
if (m_textPtr < 24U) {
data[0U] = m_text[m_textPtr++] ^ DSTAR_SCRAMBLER_BYTES[0U];
data[1U] = m_text[m_textPtr++] ^ DSTAR_SCRAMBLER_BYTES[1U];
data[2U] = m_text[m_textPtr++] ^ DSTAR_SCRAMBLER_BYTES[2U];
} else {
data[0U] = 'f' ^ DSTAR_SCRAMBLER_BYTES[0U];
data[1U] = 'f' ^ DSTAR_SCRAMBLER_BYTES[1U];
data[2U] = 'f' ^ DSTAR_SCRAMBLER_BYTES[2U];
}
}

View file

@ -1,52 +0,0 @@
/*
* Copyright (C) 2016 by Jonathan Naylor G4KLX
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifndef DStarSlowData_H
#define DStarSlowData_H
#include "DStarHeader.h"
class CDStarSlowData {
public:
CDStarSlowData();
~CDStarSlowData();
CDStarHeader* add(const unsigned char* data);
void start();
void reset();
void setText(const char* text);
void get(unsigned char* data);
private:
unsigned char* m_header;
unsigned int m_ptr;
unsigned char* m_buffer;
unsigned char* m_text;
unsigned int m_textPtr;
enum SDD_STATE {
SDD_FIRST,
SDD_SECOND
};
SDD_STATE m_state;
};
#endif

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2015,2016,2017,2018,2020 by Jonathan Naylor G4KLX * Copyright (C) 2015,2016,2017,2018,2020,2021 by Jonathan Naylor G4KLX
* *
* 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
@ -20,15 +20,7 @@
#define Defines_H #define Defines_H
const unsigned char MODE_IDLE = 0U; const unsigned char MODE_IDLE = 0U;
const unsigned char MODE_DSTAR = 1U;
const unsigned char MODE_DMR = 2U; const unsigned char MODE_DMR = 2U;
const unsigned char MODE_YSF = 3U;
const unsigned char MODE_P25 = 4U;
const unsigned char MODE_NXDN = 5U;
const unsigned char MODE_POCSAG = 6U;
const unsigned char MODE_M17 = 7U;
const unsigned char MODE_FM = 10U;
const unsigned char MODE_CW = 98U; const unsigned char MODE_CW = 98U;
const unsigned char MODE_LOCKOUT = 99U; const unsigned char MODE_LOCKOUT = 99U;
@ -40,6 +32,8 @@ const unsigned char TAG_DATA = 0x01U;
const unsigned char TAG_LOST = 0x02U; const unsigned char TAG_LOST = 0x02U;
const unsigned char TAG_EOT = 0x03U; const unsigned char TAG_EOT = 0x03U;
const unsigned int DSTAR_MODEM_DATA_LEN = 220U;
enum HW_TYPE { enum HW_TYPE {
HWT_MMDVM, HWT_MMDVM,
HWT_DVMEGA, HWT_DVMEGA,
@ -59,6 +53,7 @@ enum RPT_RF_STATE {
RS_RF_LISTENING, RS_RF_LISTENING,
RS_RF_LATE_ENTRY, RS_RF_LATE_ENTRY,
RS_RF_AUDIO, RS_RF_AUDIO,
RS_RF_DATA_AUDIO,
RS_RF_DATA, RS_RF_DATA,
RS_RF_REJECTED, RS_RF_REJECTED,
RS_RF_INVALID RS_RF_INVALID
@ -67,6 +62,7 @@ enum RPT_RF_STATE {
enum RPT_NET_STATE { enum RPT_NET_STATE {
RS_NET_IDLE, RS_NET_IDLE,
RS_NET_AUDIO, RS_NET_AUDIO,
RS_NET_DATA_AUDIO,
RS_NET_DATA RS_NET_DATA
}; };
@ -80,7 +76,8 @@ enum DMR_OVCM_TYPES {
DMR_OVCM_OFF, DMR_OVCM_OFF,
DMR_OVCM_RX_ON, DMR_OVCM_RX_ON,
DMR_OVCM_TX_ON, DMR_OVCM_TX_ON,
DMR_OVCM_ON DMR_OVCM_ON,
DMR_OVCM_FORCE_OFF
}; };
#endif #endif

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2016,2017,2018,2020 by Jonathan Naylor G4KLX * Copyright (C) 2016,2017,2018,2020,2021 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
@ -18,17 +18,15 @@
#include "Display.h" #include "Display.h"
#include "Defines.h" #include "Defines.h"
#include "SerialController.h" #include "UARTController.h"
#include "ModemSerialPort.h" #include "ModemSerialPort.h"
#include "NullDisplay.h" #include "NullDisplay.h"
#include "TFTSerial.h"
#include "TFTSurenoo.h" #include "TFTSurenoo.h"
#include "LCDproc.h" #include "LCDproc.h"
#include "Nextion.h" #include "Nextion.h"
#include "CASTInfo.h" #include "CASTInfo.h"
#include "Conf.h" #include "Conf.h"
#include "Modem.h" #include "Modem.h"
#include "UMP.h"
#include "Log.h" #include "Log.h"
#if defined(HD44780) #if defined(HD44780)
@ -101,53 +99,6 @@ void CDisplay::setQuit()
setQuitInt(); setQuitInt();
} }
void CDisplay::setFM()
{
m_timer1.stop();
m_timer2.stop();
m_mode1 = MODE_FM;
m_mode2 = MODE_FM;
setFMInt();
}
void CDisplay::writeDStar(const char* my1, const char* my2, const char* your, const char* type, const char* reflector)
{
assert(my1 != NULL);
assert(my2 != NULL);
assert(your != NULL);
assert(type != NULL);
assert(reflector != NULL);
m_timer1.start();
m_mode1 = MODE_IDLE;
writeDStarInt(my1, my2, your, type, reflector);
}
void CDisplay::writeDStarRSSI(unsigned char rssi)
{
if (rssi != 0U)
writeDStarRSSIInt(rssi);
}
void CDisplay::writeDStarBER(float ber)
{
writeDStarBERInt(ber);
}
void CDisplay::clearDStar()
{
if (m_timer1.hasExpired()) {
clearDStarInt();
m_timer1.stop();
m_mode1 = MODE_IDLE;
} else {
m_mode1 = MODE_DSTAR;
}
}
void CDisplay::writeDMR(unsigned int slotNo, const std::string& src, bool group, const std::string& dst, const char* type) void CDisplay::writeDMR(unsigned int slotNo, const std::string& src, bool group, const std::string& dst, const char* type)
{ {
assert(type != NULL); assert(type != NULL);
@ -223,171 +174,6 @@ void CDisplay::clearDMR(unsigned int slotNo)
} }
} }
void CDisplay::writeFusion(const char* source, const char* dest, unsigned char dgid, const char* type, const char* origin)
{
assert(source != NULL);
assert(dest != NULL);
assert(type != NULL);
assert(origin != NULL);
m_timer1.start();
m_mode1 = MODE_IDLE;
writeFusionInt(source, dest, dgid, type, origin);
}
void CDisplay::writeFusionRSSI(unsigned char rssi)
{
if (rssi != 0U)
writeFusionRSSIInt(rssi);
}
void CDisplay::writeFusionBER(float ber)
{
writeFusionBERInt(ber);
}
void CDisplay::clearFusion()
{
if (m_timer1.hasExpired()) {
clearFusionInt();
m_timer1.stop();
m_mode1 = MODE_IDLE;
} else {
m_mode1 = MODE_YSF;
}
}
void CDisplay::writeP25(const char* source, bool group, unsigned int dest, const char* type)
{
assert(source != NULL);
assert(type != NULL);
m_timer1.start();
m_mode1 = MODE_IDLE;
writeP25Int(source, group, dest, type);
}
void CDisplay::writeP25RSSI(unsigned char rssi)
{
if (rssi != 0U)
writeP25RSSIInt(rssi);
}
void CDisplay::writeP25BER(float ber)
{
writeP25BERInt(ber);
}
void CDisplay::clearP25()
{
if (m_timer1.hasExpired()) {
clearP25Int();
m_timer1.stop();
m_mode1 = MODE_IDLE;
} else {
m_mode1 = MODE_P25;
}
}
void CDisplay::writeNXDN(const char* source, bool group, unsigned int dest, const char* type)
{
assert(source != NULL);
assert(type != NULL);
m_timer1.start();
m_mode1 = MODE_IDLE;
writeNXDNInt(source, group, dest, type);
}
void CDisplay::writeNXDN(const class CUserDBentry& source, bool group, unsigned int dest, const char* type)
{
assert(type != NULL);
m_timer1.start();
m_mode1 = MODE_IDLE;
if (writeNXDNIntEx(source, group, dest, type))
writeNXDNInt(source.get(keyCALLSIGN).c_str(), group, dest, type);
}
void CDisplay::writeNXDNRSSI(unsigned char rssi)
{
if (rssi != 0U)
writeNXDNRSSIInt(rssi);
}
void CDisplay::writeNXDNBER(float ber)
{
writeNXDNBERInt(ber);
}
void CDisplay::clearNXDN()
{
if (m_timer1.hasExpired()) {
clearNXDNInt();
m_timer1.stop();
m_mode1 = MODE_IDLE;
} else {
m_mode1 = MODE_NXDN;
}
}
void CDisplay::writeM17(const char* source, const char* dest, const char* type)
{
assert(source != NULL);
assert(dest != NULL);
assert(type != NULL);
m_timer1.start();
m_mode1 = MODE_IDLE;
writeM17Int(source, dest, type);
}
void CDisplay::writeM17RSSI(unsigned char rssi)
{
if (rssi != 0U)
writeM17RSSIInt(rssi);
}
void CDisplay::writeM17BER(float ber)
{
writeM17BERInt(ber);
}
void CDisplay::clearM17()
{
if (m_timer1.hasExpired()) {
clearM17Int();
m_timer1.stop();
m_mode1 = MODE_IDLE;
} else {
m_mode1 = MODE_M17;
}
}
void CDisplay::writePOCSAG(uint32_t ric, const std::string& message)
{
m_timer1.start();
m_mode1 = MODE_POCSAG;
writePOCSAGInt(ric, message);
}
void CDisplay::clearPOCSAG()
{
if (m_timer1.hasExpired()) {
clearPOCSAGInt();
m_timer1.stop();
m_mode1 = MODE_IDLE;
} else {
m_mode1 = MODE_POCSAG;
}
}
void CDisplay::writeCW() void CDisplay::writeCW()
{ {
m_timer1.start(); m_timer1.start();
@ -401,41 +187,11 @@ void CDisplay::clock(unsigned int ms)
m_timer1.clock(ms); m_timer1.clock(ms);
if (m_timer1.isRunning() && m_timer1.hasExpired()) { if (m_timer1.isRunning() && m_timer1.hasExpired()) {
switch (m_mode1) { switch (m_mode1) {
case MODE_DSTAR:
clearDStarInt();
m_mode1 = MODE_IDLE;
m_timer1.stop();
break;
case MODE_DMR: case MODE_DMR:
clearDMRInt(1U); clearDMRInt(1U);
m_mode1 = MODE_IDLE; m_mode1 = MODE_IDLE;
m_timer1.stop(); m_timer1.stop();
break; break;
case MODE_YSF:
clearFusionInt();
m_mode1 = MODE_IDLE;
m_timer1.stop();
break;
case MODE_P25:
clearP25Int();
m_mode1 = MODE_IDLE;
m_timer1.stop();
break;
case MODE_NXDN:
clearNXDNInt();
m_mode1 = MODE_IDLE;
m_timer1.stop();
break;
case MODE_M17:
clearM17Int();
m_mode1 = MODE_IDLE;
m_timer1.stop();
break;
case MODE_POCSAG:
clearPOCSAGInt();
m_mode1 = MODE_IDLE;
m_timer1.stop();
break;
case MODE_CW: case MODE_CW:
clearCWInt(); clearCWInt();
m_mode1 = MODE_IDLE; m_mode1 = MODE_IDLE;
@ -463,14 +219,6 @@ void CDisplay::clockInt(unsigned int ms)
{ {
} }
void CDisplay::writeDStarRSSIInt(unsigned char rssi)
{
}
void CDisplay::writeDStarBERInt(float ber)
{
}
int CDisplay::writeDMRIntEx(unsigned int slotNo, const class CUserDBentry& src, bool group, const std::string& dst, const char* type) int CDisplay::writeDMRIntEx(unsigned int slotNo, const class CUserDBentry& src, bool group, const std::string& dst, const char* type)
{ {
/* /*
@ -497,57 +245,19 @@ void CDisplay::writeDMRBERInt(unsigned int slotNo, float ber)
{ {
} }
void CDisplay::writeFusionRSSIInt(unsigned char rssi)
{
}
void CDisplay::writeFusionBERInt(float ber)
{
}
void CDisplay::writeP25RSSIInt(unsigned char rssi)
{
}
void CDisplay::writeP25BERInt(float ber)
{
}
void CDisplay::writeNXDNRSSIInt(unsigned char rssi)
{
}
void CDisplay::writeNXDNBERInt(float ber)
{
}
void CDisplay::writeM17RSSIInt(unsigned char rssi)
{
}
void CDisplay::writeM17BERInt(float ber)
{
}
int CDisplay::writeNXDNIntEx(const class CUserDBentry& source, bool group, unsigned int dest, const char* type)
{
/* return value definition is same as writeDMRIntEx() */
return -1; // not supported
}
/* Factory method extracted from MMDVMHost.cpp - BG5HHP */ /* Factory method extracted from MMDVMHost.cpp - BG5HHP */
CDisplay* CDisplay::createDisplay(const CConf& conf, CUMP* ump, CModem* modem) CDisplay* CDisplay::createDisplay(const CConf& conf, CModem* modem)
{ {
CDisplay *display = NULL; CDisplay *display = NULL;
std::string type = conf.getDisplay(); std::string type = conf.getDisplay();
unsigned int dmrid = conf.getDMRId(); unsigned int dmrid = conf.getDMRId();
LogInfo("Display Parameters"); LogInfo("Display Parameters");
LogInfo(" Type: %s", type.c_str()); LogInfo(" Type: %s", type.c_str());
if (type == "TFT Serial" || type == "TFT Surenoo") { if (type == "TFT Surenoo") {
std::string port = conf.getTFTSerialPort(); std::string port = conf.getTFTSerialPort();
unsigned int brightness = conf.getTFTSerialBrightness(); unsigned int brightness = conf.getTFTSerialBrightness();
@ -556,14 +266,11 @@ CDisplay* CDisplay::createDisplay(const CConf& conf, CUMP* ump, CModem* modem)
ISerialPort* serial = NULL; ISerialPort* serial = NULL;
if (port == "modem") if (port == "modem")
serial = new CModemSerialPort(modem); serial = new IModemSerialPort(modem);
else else
serial = new CSerialController(port, (type == "TFT Serial") ? SERIAL_9600 : SERIAL_115200); serial = new CUARTController(port, 115200U);
if (type == "TFT Surenoo") display = new CTFTSurenoo(conf.getCallsign(), dmrid, serial, brightness, conf.getDuplex());
display = new CTFTSurenoo(conf.getCallsign(), dmrid, serial, brightness, conf.getDuplex());
else
display = new CTFTSerial(conf.getCallsign(), dmrid, serial, brightness);
} else if (type == "Nextion") { } else if (type == "Nextion") {
std::string port = conf.getNextionPort(); std::string port = conf.getNextionPort();
unsigned int brightness = conf.getNextionBrightness(); unsigned int brightness = conf.getNextionBrightness();
@ -602,22 +309,15 @@ CDisplay* CDisplay::createDisplay(const CConf& conf, CUMP* ump, CModem* modem)
} }
if (port == "modem") { if (port == "modem") {
ISerialPort* serial = new CModemSerialPort(modem); ISerialPort* serial = new IModemSerialPort(modem);
display = new CNextion(conf.getCallsign(), dmrid, serial, brightness, displayClock, utc, idleBrightness, screenLayout, txFrequency, rxFrequency, displayTempInF); display = new CNextion(conf.getCallsign(), dmrid, serial, brightness, displayClock, utc, idleBrightness, screenLayout, txFrequency, rxFrequency, displayTempInF);
} else if (port == "ump") {
if (ump != NULL) {
display = new CNextion(conf.getCallsign(), dmrid, ump, brightness, displayClock, utc, idleBrightness, screenLayout, txFrequency, rxFrequency, displayTempInF);
} else {
LogInfo(" NullDisplay loaded");
display = new CNullDisplay;
}
} else { } else {
SERIAL_SPEED baudrate = SERIAL_9600; unsigned int baudrate = 9600U;
if (screenLayout&0x0cU) if (screenLayout == 4U)
baudrate = SERIAL_115200; baudrate = 115200U;
LogInfo(" Display baudrate: %u ",baudrate); LogInfo(" Display baudrate: %u ", baudrate);
ISerialPort* serial = new CSerialController(port, baudrate); ISerialPort* serial = new CUARTController(port, baudrate);
display = new CNextion(conf.getCallsign(), dmrid, serial, brightness, displayClock, utc, idleBrightness, screenLayout, txFrequency, rxFrequency, displayTempInF); display = new CNextion(conf.getCallsign(), dmrid, serial, brightness, displayClock, utc, idleBrightness, screenLayout, txFrequency, rxFrequency, displayTempInF);
} }
} else if (type == "LCDproc") { } else if (type == "LCDproc") {
@ -689,7 +389,7 @@ CDisplay* CDisplay::createDisplay(const CConf& conf, CUMP* ump, CModem* modem)
bool rotate = conf.getOLEDRotate(); bool rotate = conf.getOLEDRotate();
bool logosaver = conf.getOLEDLogoScreensaver(); bool logosaver = conf.getOLEDLogoScreensaver();
display = new COLED(type, brightness, invert, scroll, rotate, logosaver, conf.getDMRNetworkSlot1(), conf.getDMRNetworkSlot2()); display = new COLED(type, brightness, invert, scroll, rotate, logosaver, conf.getDuplex());
#endif #endif
} else if (type == "CAST") { } else if (type == "CAST") {
display = new CCASTInfo(modem); display = new CCASTInfo(modem);

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2016,2017,2018,2020 by Jonathan Naylor G4KLX * Copyright (C) 2016,2017,2018,2020,2021 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,6 +21,7 @@
#include "Timer.h" #include "Timer.h"
#include "UserDBentry.h" #include "UserDBentry.h"
#include "Modem.h"
#include <string> #include <string>
@ -28,7 +29,6 @@
class CConf; class CConf;
class CModem; class CModem;
class CUMP;
class CDisplay class CDisplay
{ {
@ -44,11 +44,6 @@ public:
void setQuit(); void setQuit();
void setFM(); void setFM();
void writeDStar(const char* my1, const char* my2, const char* your, const char* type, const char* reflector);
void writeDStarRSSI(unsigned char rssi);
void writeDStarBER(float ber);
void clearDStar();
void writeDMR(unsigned int slotNo, const std::string& src, bool group, const std::string& dst, const char* type); void writeDMR(unsigned int slotNo, const std::string& src, bool group, const std::string& dst, const char* type);
void writeDMR(unsigned int slotNo, const class CUserDBentry& src, bool group, const std::string& dst, const char* type); void writeDMR(unsigned int slotNo, const class CUserDBentry& src, bool group, const std::string& dst, const char* type);
void writeDMRRSSI(unsigned int slotNo, unsigned char rssi); void writeDMRRSSI(unsigned int slotNo, unsigned char rssi);
@ -56,49 +51,19 @@ public:
void writeDMRTA(unsigned int slotNo, unsigned char* talkerAlias, const char* type); void writeDMRTA(unsigned int slotNo, unsigned char* talkerAlias, const char* type);
void clearDMR(unsigned int slotNo); void clearDMR(unsigned int slotNo);
void writeFusion(const char* source, const char* dest, unsigned char dgid, const char* type, const char* origin);
void writeFusionRSSI(unsigned char rssi);
void writeFusionBER(float ber);
void clearFusion();
void writeP25(const char* source, bool group, unsigned int dest, const char* type);
void writeP25RSSI(unsigned char rssi);
void writeP25BER(float ber);
void clearP25();
void writeNXDN(const char* source, bool group, unsigned int dest, const char* type);
void writeNXDN(const class CUserDBentry& source, bool group, unsigned int dest, const char* type);
void writeNXDNRSSI(unsigned char rssi);
void writeNXDNBER(float ber);
void clearNXDN();
void writeM17(const char* source, const char* dest, const char* type);
void writeM17RSSI(unsigned char rssi);
void writeM17BER(float ber);
void clearM17();
void writePOCSAG(uint32_t ric, const std::string& message);
void clearPOCSAG();
void writeCW(); void writeCW();
virtual void close() = 0; virtual void close() = 0;
void clock(unsigned int ms); void clock(unsigned int ms);
static CDisplay* createDisplay(const CConf& conf, CUMP* ump, CModem* modem); static CDisplay* createDisplay(const CConf& conf, CModem* modem);
protected: protected:
virtual void setIdleInt() = 0; virtual void setIdleInt() = 0;
virtual void setLockoutInt() = 0; virtual void setLockoutInt() = 0;
virtual void setErrorInt(const char* text) = 0; virtual void setErrorInt(const char* text) = 0;
virtual void setQuitInt() = 0; virtual void setQuitInt() = 0;
virtual void setFMInt() = 0;
virtual void writeDStarInt(const char* my1, const char* my2, const char* your, const char* type, const char* reflector) = 0;
virtual void writeDStarRSSIInt(unsigned char rssi);
virtual void writeDStarBERInt(float ber);
virtual void clearDStarInt() = 0;
virtual void writeDMRInt(unsigned int slotNo, const std::string& src, bool group, const std::string& dst, const char* type) = 0; virtual void writeDMRInt(unsigned int slotNo, const std::string& src, bool group, const std::string& dst, const char* type) = 0;
virtual int writeDMRIntEx(unsigned int slotNo, const class CUserDBentry& src, bool group, const std::string& dst, const char* type); virtual int writeDMRIntEx(unsigned int slotNo, const class CUserDBentry& src, bool group, const std::string& dst, const char* type);
@ -107,30 +72,6 @@ protected:
virtual void writeDMRBERInt(unsigned int slotNo, float ber); virtual void writeDMRBERInt(unsigned int slotNo, float ber);
virtual void clearDMRInt(unsigned int slotNo) = 0; virtual void clearDMRInt(unsigned int slotNo) = 0;
virtual void writeFusionInt(const char* source, const char* dest, unsigned char dgid, const char* type, const char* origin) = 0;
virtual void writeFusionRSSIInt(unsigned char rssi);
virtual void writeFusionBERInt(float ber);
virtual void clearFusionInt() = 0;
virtual void writeP25Int(const char* source, bool group, unsigned int dest, const char* type) = 0;
virtual void writeP25RSSIInt(unsigned char rssi);
virtual void writeP25BERInt(float ber);
virtual void clearP25Int() = 0;
virtual void writeNXDNInt(const char* source, bool group, unsigned int dest, const char* type) = 0;
virtual int writeNXDNIntEx(const class CUserDBentry& source, bool group, unsigned int dest, const char* type);
virtual void writeNXDNRSSIInt(unsigned char rssi);
virtual void writeNXDNBERInt(float ber);
virtual void clearNXDNInt() = 0;
virtual void writeM17Int(const char* source, const char* dest, const char* type) = 0;
virtual void writeM17RSSIInt(unsigned char rssi);
virtual void writeM17BERInt(float ber);
virtual void clearM17Int() = 0;
virtual void writePOCSAGInt(uint32_t ric, const std::string& message) = 0;
virtual void clearPOCSAGInt() = 0;
virtual void writeCWInt() = 0; virtual void writeCWInt() = 0;
virtual void clearCWInt() = 0; virtual void clearCWInt() = 0;

View file

@ -1,19 +0,0 @@
FROM alpine
RUN apk add --update --no-cache \
cmake \
make \
g++ \
git \
&& rm -rf /var/cache/apk/*
ADD ./ /MMDVMHost
WORKDIR /MMDVMHost
RUN make \
&& cp MMDVMHost /usr/local/bin
VOLUME /MMDVMHost
WORKDIR /MMDVMHost
CMD ["MMDVMHost", "/MMDVMHost/MMDVM.ini"]

View file

@ -1,9 +1,10 @@
/* /*
* Copyright (C) 2010,2016 by Jonathan Naylor G4KLX * Copyright (C) 2010,2016,2021 by Jonathan Naylor G4KLX
* Copyright (C) 2002 by Robert H. Morelos-Zaragoza. All rights reserved. * Copyright (C) 2002 by Robert H. Morelos-Zaragoza. All rights reserved.
*/ */
#include "Golay24128.h" #include "Golay24128.h"
#include "Utils.h"
#include <cstdio> #include <cstdio>
#include <cassert> #include <cassert>
@ -1089,20 +1090,25 @@ unsigned int CGolay24128::decode23127(unsigned int code)
return code >> 11; return code >> 11;
} }
unsigned int CGolay24128::decode24128(unsigned int code) bool CGolay24128::decode24128(unsigned int in, unsigned int& out)
{ {
return decode23127(code >> 1); unsigned int syndrome = ::get_syndrome_23127(in >> 1);
unsigned int error_pattern = DECODING_TABLE_23127[syndrome] << 1;
out = in ^ error_pattern;
bool valid = (CUtils::countBits(syndrome) < 3U) || !(CUtils::countBits(out) & 1);
out >>= 12;
return valid;
} }
unsigned int CGolay24128::decode24128(unsigned char* bytes) bool CGolay24128::decode24128(unsigned char* in, unsigned int& out)
{ {
assert(bytes != NULL); assert(in != NULL);
unsigned int code = bytes[0U]; unsigned int code = (in[0U] << 16) | (in[1U] << 8) | (in[2U] << 0);
code <<= 8;
code |= bytes[1U];
code <<= 8;
code |= bytes[2U];
return decode23127(code >> 1); return decode24128(code, out);
} }

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2010,2016 by Jonathan Naylor G4KLX * Copyright (C) 2010,2016,2021 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
@ -25,8 +25,9 @@ public:
static unsigned int encode24128(unsigned int data); static unsigned int encode24128(unsigned int data);
static unsigned int decode23127(unsigned int code); static unsigned int decode23127(unsigned int code);
static unsigned int decode24128(unsigned int code);
static unsigned int decode24128(unsigned char* bytes); static bool decode24128(unsigned int in, unsigned int& out);
static bool decode24128(unsigned char* in, unsigned int& out);
}; };
#endif #endif

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2016,2017,2018,2020 by Jonathan Naylor G4KLX & Tony Corbett G0WFV * Copyright (C) 2016,2017,2018,2020,2021 by Jonathan Naylor G4KLX & Tony Corbett G0WFV
* *
* 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
@ -41,6 +41,7 @@ const unsigned int DMR_RSSI_COUNT = 4U; // 4 * 360ms = 1440ms
const unsigned int YSF_RSSI_COUNT = 13U; // 13 * 100ms = 1300ms const unsigned int YSF_RSSI_COUNT = 13U; // 13 * 100ms = 1300ms
const unsigned int P25_RSSI_COUNT = 7U; // 7 * 180ms = 1260ms const unsigned int P25_RSSI_COUNT = 7U; // 7 * 180ms = 1260ms
const unsigned int NXDN_RSSI_COUNT = 28U; // 28 * 40ms = 1120ms const unsigned int NXDN_RSSI_COUNT = 28U; // 28 * 40ms = 1120ms
const unsigned int M17_RSSI_COUNT = 28U; // 28 * 40ms = 1120ms
CHD44780::CHD44780(unsigned int rows, unsigned int cols, const std::string& callsign, unsigned int dmrid, const std::vector<unsigned int>& pins, unsigned int i2cAddress, bool pwm, unsigned int pwmPin, unsigned int pwmBright, unsigned int pwmDim, bool displayClock, bool utc, bool duplex) : CHD44780::CHD44780(unsigned int rows, unsigned int cols, const std::string& callsign, unsigned int dmrid, const std::vector<unsigned int>& pins, unsigned int i2cAddress, bool pwm, unsigned int pwmPin, unsigned int pwmBright, unsigned int pwmDim, bool displayClock, bool utc, bool duplex) :
CDisplay(), CDisplay(),
@ -211,12 +212,12 @@ void CHD44780::adafruitLCDSetup()
::pinMode(AF_RW, OUTPUT); ::pinMode(AF_RW, OUTPUT);
::digitalWrite(AF_RW, LOW); ::digitalWrite(AF_RW, LOW);
m_rb = AF_RS; m_rb = AF_RS;
m_strb = AF_E; m_strb = AF_E;
m_d0 = AF_D0; m_d0 = AF_D0;
m_d1 = AF_D1; m_d1 = AF_D1;
m_d2 = AF_D2; m_d2 = AF_D2;
m_d3 = AF_D3; m_d3 = AF_D3;
} }
void CHD44780::adafruitLCDColour(ADAFRUIT_COLOUR colour) void CHD44780::adafruitLCDColour(ADAFRUIT_COLOUR colour)
@ -275,12 +276,12 @@ void CHD44780::pcf8574LCDSetup()
::pcf8574Setup(AF_BASE, m_i2cAddress); ::pcf8574Setup(AF_BASE, m_i2cAddress);
// Turn on backlight // Turn on backlight
::pinMode (AF_BL, OUTPUT); ::pinMode(AF_BL, OUTPUT);
::digitalWrite (AF_BL, 1); ::digitalWrite(AF_BL, 1);
// Set LCD to write mode. // Set LCD to write mode.
::pinMode (AF_RW, OUTPUT); ::pinMode(AF_RW, OUTPUT);
::digitalWrite (AF_RW, 0); ::digitalWrite(AF_RW, 0);
m_rb = AF_RS; m_rb = AF_RS;
m_strb = AF_E; m_strb = AF_E;
@ -297,7 +298,7 @@ void CHD44780::setIdleInt()
::lcdClear(m_fd); ::lcdClear(m_fd);
#ifdef ADAFRUIT_DISPLAY #ifdef ADAFRUIT_DISPLAY
adafruitLCDColour(AC_WHITE); adafruitLCDColour(AC_WHITE);
#endif #endif
if (m_pwm) { if (m_pwm) {
@ -327,7 +328,7 @@ void CHD44780::setErrorInt(const char* text)
assert(text != NULL); assert(text != NULL);
#ifdef ADAFRUIT_DISPLAY #ifdef ADAFRUIT_DISPLAY
adafruitLCDColour(AC_RED); adafruitLCDColour(AC_RED);
#endif #endif
m_clockDisplayTimer.stop(); // Stop the clock display m_clockDisplayTimer.stop(); // Stop the clock display
@ -405,7 +406,7 @@ void CHD44780::setFMInt()
::lcdClear(m_fd); ::lcdClear(m_fd);
#ifdef ADAFRUIT_DISPLAY #ifdef ADAFRUIT_DISPLAY
adafruitLCDColour(AC_WHITE); adafruitLCDColour(AC_WHITE);
#endif #endif
if (m_pwm) { if (m_pwm) {
@ -439,7 +440,7 @@ void CHD44780::writeDStarInt(const char* my1, const char* my2, const char* your,
assert(reflector != NULL); assert(reflector != NULL);
#ifdef ADAFRUIT_DISPLAY #ifdef ADAFRUIT_DISPLAY
adafruitLCDColour(AC_RED); adafruitLCDColour(AC_RED);
#endif #endif
m_clockDisplayTimer.stop(); // Stop the clock display m_clockDisplayTimer.stop(); // Stop the clock display
@ -463,11 +464,10 @@ void CHD44780::writeDStarInt(const char* my1, const char* my2, const char* your,
::lcdPrintf(m_fd, " %.8s/%.4s", my1, my2); ::lcdPrintf(m_fd, " %.8s/%.4s", my1, my2);
::lcdPosition(m_fd, m_cols - 1, (m_rows / 2) - 1); ::lcdPosition(m_fd, m_cols - 1, (m_rows / 2) - 1);
if (strcmp(type, "R") == 0) { if (strcmp(type, "R") == 0)
::lcdPutchar(m_fd, 2); ::lcdPutchar(m_fd, 2);
} else { else
::lcdPutchar(m_fd, 3); ::lcdPutchar(m_fd, 3);
}
::sprintf(m_buffer1, "%.8s", your); ::sprintf(m_buffer1, "%.8s", your);
@ -493,19 +493,19 @@ void CHD44780::writeDStarInt(const char* my1, const char* my2, const char* your,
::lcdPrintf(m_fd, " %.*s", m_cols, m_buffer1); ::lcdPrintf(m_fd, " %.*s", m_cols, m_buffer1);
m_dmr = false; m_dmr = false;
m_rssiCount1 = 0U; m_rssiCount1 = 0U;
} }
void CHD44780::writeDStarRSSIInt(unsigned char rssi) void CHD44780::writeDStarRSSIInt(unsigned char rssi)
{ {
if (m_rssiCount1 == 0U && m_rows > 2) { if (m_rssiCount1 == 0U && m_rows > 2) {
::lcdPosition(m_fd, 0, 3); ::lcdPosition(m_fd, 0, 3);
::lcdPrintf(m_fd, "-%3udBm", rssi); ::lcdPrintf(m_fd, "-%3udBm", rssi);
} }
m_rssiCount1++; m_rssiCount1++;
if (m_rssiCount1 >= DSTAR_RSSI_COUNT) if (m_rssiCount1 >= DSTAR_RSSI_COUNT)
m_rssiCount1 = 0U; m_rssiCount1 = 0U;
} }
void CHD44780::clearDStarInt() void CHD44780::clearDStarInt()
@ -599,21 +599,20 @@ void CHD44780::writeDMRInt(unsigned int slotNo, const std::string& src, bool gro
::lcdPosition(m_fd, m_cols - 3U, (m_rows / 2) - 1); ::lcdPosition(m_fd, m_cols - 3U, (m_rows / 2) - 1);
::lcdPuts(m_fd, " "); ::lcdPuts(m_fd, " ");
if (group) { if (group)
::lcdPutchar(m_fd, 5); ::lcdPutchar(m_fd, 5);
} else { else
::lcdPutchar(m_fd, 4); ::lcdPutchar(m_fd, 4);
}
if (strcmp(type, "R") == 0) { if (strcmp(type, "R") == 0)
::lcdPutchar(m_fd, 2); ::lcdPutchar(m_fd, 2);
} else { else
::lcdPutchar(m_fd, 3); ::lcdPutchar(m_fd, 3);
}
} else { } else {
::lcdPosition(m_fd, 0, (m_rows / 2)); ::lcdPosition(m_fd, 0, (m_rows / 2));
::lcdPuts(m_fd, "2 "); ::lcdPuts(m_fd, "2 ");
if (m_cols > 16 )
if (m_cols > 16)
::sprintf(m_buffer2, "%s > %s%s%s", src.c_str(), group ? "TG" : "", dst.c_str(), DEADSPACE); ::sprintf(m_buffer2, "%s > %s%s%s", src.c_str(), group ? "TG" : "", dst.c_str(), DEADSPACE);
else else
::sprintf(m_buffer2, "%s>%s%s", src.c_str(), dst.c_str(), DEADSPACE); ::sprintf(m_buffer2, "%s>%s%s", src.c_str(), dst.c_str(), DEADSPACE);
@ -622,17 +621,15 @@ void CHD44780::writeDMRInt(unsigned int slotNo, const std::string& src, bool gro
::lcdPosition(m_fd, m_cols - 3U, (m_rows / 2)); ::lcdPosition(m_fd, m_cols - 3U, (m_rows / 2));
::lcdPuts(m_fd, " "); ::lcdPuts(m_fd, " ");
if (group) { if (group)
::lcdPutchar(m_fd, 5); ::lcdPutchar(m_fd, 5);
} else { else
::lcdPutchar(m_fd, 4); ::lcdPutchar(m_fd, 4);
}
if (strcmp(type, "R") == 0) { if (strcmp(type, "R") == 0)
::lcdPutchar(m_fd, 2); ::lcdPutchar(m_fd, 2);
} else { else
::lcdPutchar(m_fd, 3); ::lcdPutchar(m_fd, 3);
}
} }
} else { } else {
if (m_rows > 2U) { if (m_rows > 2U) {
@ -647,11 +644,10 @@ void CHD44780::writeDMRInt(unsigned int slotNo, const std::string& src, bool gro
::lcdPrintf(m_fd, "%.*s", m_cols - 4U, m_buffer2); ::lcdPrintf(m_fd, "%.*s", m_cols - 4U, m_buffer2);
::lcdPosition(m_fd, m_cols - 1U, (m_rows / 2) - 1); ::lcdPosition(m_fd, m_cols - 1U, (m_rows / 2) - 1);
if (strcmp(type, "R") == 0) { if (strcmp(type, "R") == 0)
::lcdPutchar(m_fd, 2); ::lcdPutchar(m_fd, 2);
} else { else
::lcdPutchar(m_fd, 3); ::lcdPutchar(m_fd, 3);
}
::lcdPosition(m_fd, 0, (m_rows / 2)); ::lcdPosition(m_fd, 0, (m_rows / 2));
::lcdPutchar(m_fd, 1); ::lcdPutchar(m_fd, 1);
@ -659,38 +655,38 @@ void CHD44780::writeDMRInt(unsigned int slotNo, const std::string& src, bool gro
::lcdPrintf(m_fd, "%.*s", m_cols - 4U, m_buffer2); ::lcdPrintf(m_fd, "%.*s", m_cols - 4U, m_buffer2);
::lcdPosition(m_fd, m_cols - 1U, (m_rows / 2)); ::lcdPosition(m_fd, m_cols - 1U, (m_rows / 2));
if (group) { if (group)
::lcdPutchar(m_fd, 5); ::lcdPutchar(m_fd, 5);
} else { else
::lcdPutchar(m_fd, 4); ::lcdPutchar(m_fd, 4);
}
} }
m_dmr = true; m_dmr = true;
m_rssiCount1 = 0U; m_rssiCount1 = 0U;
m_rssiCount2 = 0U; m_rssiCount2 = 0U;
} }
void CHD44780::writeDMRRSSIInt(unsigned int slotNo, unsigned char rssi) void CHD44780::writeDMRRSSIInt(unsigned int slotNo, unsigned char rssi)
{ {
if (m_rows > 2) { if (m_rows > 2) {
if (slotNo == 1U) { if (slotNo == 1U) {
if (m_rssiCount1 == 0U) { if (m_rssiCount1 == 0U) {
::lcdPosition(m_fd, 0, 3); ::lcdPosition(m_fd, 0, 3);
::lcdPrintf(m_fd, "-%3udBm", rssi); ::lcdPrintf(m_fd, "-%3udBm", rssi);
} }
m_rssiCount1++; m_rssiCount1++;
if (m_rssiCount1 >= DMR_RSSI_COUNT) if (m_rssiCount1 >= DMR_RSSI_COUNT)
m_rssiCount1 = 0U; m_rssiCount1 = 0U;
} else { } else {
if (m_rssiCount2 == 0U) { if (m_rssiCount2 == 0U) {
::lcdPosition(m_fd, (m_cols / 2), 3); ::lcdPosition(m_fd, (m_cols / 2), 3);
::lcdPrintf(m_fd, "-%3udBm", rssi); ::lcdPrintf(m_fd, "-%3udBm", rssi);
} }
m_rssiCount2++; m_rssiCount2++;
if (m_rssiCount2 >= DMR_RSSI_COUNT) if (m_rssiCount2 >= DMR_RSSI_COUNT)
m_rssiCount2 = 0U; m_rssiCount2 = 0U;
} }
} }
} }
@ -722,7 +718,6 @@ void CHD44780::clearDMRInt(unsigned int slotNo)
} }
} }
} else { } else {
if (m_rows > 2U) { if (m_rows > 2U) {
::lcdPosition(m_fd, 0, (m_rows / 2) - 2); ::lcdPosition(m_fd, 0, (m_rows / 2) - 2);
::sprintf(m_buffer1, "%s", DEADSPACE); ::sprintf(m_buffer1, "%s", DEADSPACE);
@ -745,7 +740,7 @@ void CHD44780::writeFusionInt(const char* source, const char* dest, unsigned cha
assert(origin != NULL); assert(origin != NULL);
#ifdef ADAFRUIT_DISPLAY #ifdef ADAFRUIT_DISPLAY
adafruitLCDColour(AC_RED); adafruitLCDColour(AC_RED);
#endif #endif
m_clockDisplayTimer.stop(); // Stop the clock display m_clockDisplayTimer.stop(); // Stop the clock display
@ -762,12 +757,10 @@ void CHD44780::writeFusionInt(const char* source, const char* dest, unsigned cha
::lcdPuts(m_fd, "System Fusion"); ::lcdPuts(m_fd, "System Fusion");
if (m_rows == 2U && m_cols == 16U) { if (m_rows == 2U && m_cols == 16U) {
char m_buffer1[16U];
::sprintf(m_buffer1, "%.10s >", source); ::sprintf(m_buffer1, "%.10s >", source);
::lcdPosition(m_fd, 0, 1); ::lcdPosition(m_fd, 0, 1);
::lcdPrintf(m_fd, "%.*s", m_cols, m_buffer1); ::lcdPrintf(m_fd, "%.*s", m_cols, m_buffer1);
} else if (m_rows == 4U && m_cols == 16U) { } else if (m_rows == 4U && m_cols == 16U) {
char m_buffer1[16U];
::sprintf(m_buffer1, "%.10s >", source); ::sprintf(m_buffer1, "%.10s >", source);
::lcdPosition(m_fd, 0, 1); ::lcdPosition(m_fd, 0, 1);
::lcdPrintf(m_fd, "%.*s", m_cols, m_buffer1); ::lcdPrintf(m_fd, "%.*s", m_cols, m_buffer1);
@ -776,7 +769,6 @@ void CHD44780::writeFusionInt(const char* source, const char* dest, unsigned cha
::lcdPosition(m_fd, 0, 2); ::lcdPosition(m_fd, 0, 2);
::lcdPrintf(m_fd, "%.*s", m_cols, m_buffer1); ::lcdPrintf(m_fd, "%.*s", m_cols, m_buffer1);
} else if (m_rows == 4U && m_cols == 20U) { } else if (m_rows == 4U && m_cols == 20U) {
char m_buffer1[20U];
::sprintf(m_buffer1, "%.10s >", source); ::sprintf(m_buffer1, "%.10s >", source);
::lcdPosition(m_fd, 0, 1); ::lcdPosition(m_fd, 0, 1);
::lcdPrintf(m_fd, "%.*s", m_cols, m_buffer1); ::lcdPrintf(m_fd, "%.*s", m_cols, m_buffer1);
@ -785,7 +777,6 @@ void CHD44780::writeFusionInt(const char* source, const char* dest, unsigned cha
::lcdPosition(m_fd, 0, 2); ::lcdPosition(m_fd, 0, 2);
::lcdPrintf(m_fd, "%.*s", m_cols, m_buffer1); ::lcdPrintf(m_fd, "%.*s", m_cols, m_buffer1);
} else if (m_rows == 2 && m_cols == 40U) { } else if (m_rows == 2 && m_cols == 40U) {
char m_buffer1[40U];
::sprintf(m_buffer1, "%.10s > DG-ID %u", source, dgid); ::sprintf(m_buffer1, "%.10s > DG-ID %u", source, dgid);
::lcdPosition(m_fd, 0, 1); ::lcdPosition(m_fd, 0, 1);
@ -796,16 +787,16 @@ void CHD44780::writeFusionInt(const char* source, const char* dest, unsigned cha
m_rssiCount1 = 0U; m_rssiCount1 = 0U;
} }
void CHD44780::writeFusionRSSIInt(unsigned char rssi) void CHD44780::writeFusionRSSIInt(unsigned char rssi)
{ {
if (m_rssiCount1 == 0U && m_rows > 2) { if (m_rssiCount1 == 0U && m_rows > 2) {
::lcdPosition(m_fd, 0, 3); ::lcdPosition(m_fd, 0, 3);
::lcdPrintf(m_fd, "-%3udBm", rssi); ::lcdPrintf(m_fd, "-%3udBm", rssi);
} }
m_rssiCount1++; m_rssiCount1++;
if (m_rssiCount1 >= YSF_RSSI_COUNT) if (m_rssiCount1 >= YSF_RSSI_COUNT)
m_rssiCount1 = 0U; m_rssiCount1 = 0U;
} }
void CHD44780::clearFusionInt() void CHD44780::clearFusionInt()
@ -848,7 +839,7 @@ void CHD44780::writeP25Int(const char* source, bool group, unsigned int dest, co
assert(type != NULL); assert(type != NULL);
#ifdef ADAFRUIT_DISPLAY #ifdef ADAFRUIT_DISPLAY
adafruitLCDColour(AC_RED); adafruitLCDColour(AC_RED);
#endif #endif
m_clockDisplayTimer.stop(); // Stop the clock display m_clockDisplayTimer.stop(); // Stop the clock display
@ -865,12 +856,10 @@ void CHD44780::writeP25Int(const char* source, bool group, unsigned int dest, co
::lcdPuts(m_fd, "P25"); ::lcdPuts(m_fd, "P25");
if (m_rows == 2U && m_cols == 16U) { if (m_rows == 2U && m_cols == 16U) {
char m_buffer1[16U];
::sprintf(m_buffer1, "%.10s >", source); ::sprintf(m_buffer1, "%.10s >", source);
::lcdPosition(m_fd, 0, 1); ::lcdPosition(m_fd, 0, 1);
::lcdPrintf(m_fd, "%.*s", m_cols, m_buffer1); ::lcdPrintf(m_fd, "%.*s", m_cols, m_buffer1);
} else if (m_rows == 4U && m_cols == 16U) { } else if (m_rows == 4U && m_cols == 16U) {
char m_buffer1[16U];
::sprintf(m_buffer1, "%.10s >", source); ::sprintf(m_buffer1, "%.10s >", source);
::lcdPosition(m_fd, 0, 1); ::lcdPosition(m_fd, 0, 1);
::lcdPrintf(m_fd, "%.*s", m_cols, m_buffer1); ::lcdPrintf(m_fd, "%.*s", m_cols, m_buffer1);
@ -879,7 +868,6 @@ void CHD44780::writeP25Int(const char* source, bool group, unsigned int dest, co
::lcdPosition(m_fd, 0, 2); ::lcdPosition(m_fd, 0, 2);
::lcdPrintf(m_fd, "%.*s", m_cols, m_buffer1); ::lcdPrintf(m_fd, "%.*s", m_cols, m_buffer1);
} else if (m_rows == 4U && m_cols == 20U) { } else if (m_rows == 4U && m_cols == 20U) {
char m_buffer1[20U];
::sprintf(m_buffer1, "%.10s >", source); ::sprintf(m_buffer1, "%.10s >", source);
::lcdPosition(m_fd, 0, 1); ::lcdPosition(m_fd, 0, 1);
::lcdPrintf(m_fd, "%.*s", m_cols, m_buffer1); ::lcdPrintf(m_fd, "%.*s", m_cols, m_buffer1);
@ -888,7 +876,6 @@ void CHD44780::writeP25Int(const char* source, bool group, unsigned int dest, co
::lcdPosition(m_fd, 0, 2); ::lcdPosition(m_fd, 0, 2);
::lcdPrintf(m_fd, "%.*s", m_cols, m_buffer1); ::lcdPrintf(m_fd, "%.*s", m_cols, m_buffer1);
} else if (m_rows == 2 && m_cols == 40U) { } else if (m_rows == 2 && m_cols == 40U) {
char m_buffer1[40U];
::sprintf(m_buffer1, "%.10s > %s%u", source, group ? "TG" : "", dest); ::sprintf(m_buffer1, "%.10s > %s%u", source, group ? "TG" : "", dest);
::lcdPosition(m_fd, 0, 1); ::lcdPosition(m_fd, 0, 1);
@ -896,19 +883,19 @@ void CHD44780::writeP25Int(const char* source, bool group, unsigned int dest, co
} }
m_dmr = false; m_dmr = false;
m_rssiCount1 = 0U; m_rssiCount1 = 0U;
} }
void CHD44780::writeP25RSSIInt(unsigned char rssi) void CHD44780::writeP25RSSIInt(unsigned char rssi)
{ {
if (m_rssiCount1 == 0U && m_rows > 2) { if (m_rssiCount1 == 0U && m_rows > 2) {
::lcdPosition(m_fd, 0, 3); ::lcdPosition(m_fd, 0, 3);
::lcdPrintf(m_fd, "-%3udBm", rssi); ::lcdPrintf(m_fd, "-%3udBm", rssi);
} }
m_rssiCount1++; m_rssiCount1++;
if (m_rssiCount1 >= P25_RSSI_COUNT) if (m_rssiCount1 >= P25_RSSI_COUNT)
m_rssiCount1 = 0U; m_rssiCount1 = 0U;
} }
void CHD44780::clearP25Int() void CHD44780::clearP25Int()
@ -952,7 +939,7 @@ void CHD44780::writeNXDNInt(const char* source, bool group, unsigned int dest, c
assert(type != NULL); assert(type != NULL);
#ifdef ADAFRUIT_DISPLAY #ifdef ADAFRUIT_DISPLAY
adafruitLCDColour(AC_RED); adafruitLCDColour(AC_RED);
#endif #endif
m_clockDisplayTimer.stop(); // Stop the clock display m_clockDisplayTimer.stop(); // Stop the clock display
@ -969,12 +956,10 @@ void CHD44780::writeNXDNInt(const char* source, bool group, unsigned int dest, c
::lcdPuts(m_fd, "NXDN"); ::lcdPuts(m_fd, "NXDN");
if (m_rows == 2U && m_cols == 16U) { if (m_rows == 2U && m_cols == 16U) {
char m_buffer1[16U];
::sprintf(m_buffer1, "%.10s >", source); ::sprintf(m_buffer1, "%.10s >", source);
::lcdPosition(m_fd, 0, 1); ::lcdPosition(m_fd, 0, 1);
::lcdPrintf(m_fd, "%.*s", m_cols, m_buffer1); ::lcdPrintf(m_fd, "%.*s", m_cols, m_buffer1);
} else if (m_rows == 4U && m_cols == 16U) { } else if (m_rows == 4U && m_cols == 16U) {
char m_buffer1[16U];
::sprintf(m_buffer1, "%.10s >", source); ::sprintf(m_buffer1, "%.10s >", source);
::lcdPosition(m_fd, 0, 1); ::lcdPosition(m_fd, 0, 1);
::lcdPrintf(m_fd, "%.*s", m_cols, m_buffer1); ::lcdPrintf(m_fd, "%.*s", m_cols, m_buffer1);
@ -983,7 +968,6 @@ void CHD44780::writeNXDNInt(const char* source, bool group, unsigned int dest, c
::lcdPosition(m_fd, 0, 2); ::lcdPosition(m_fd, 0, 2);
::lcdPrintf(m_fd, "%.*s", m_cols, m_buffer1); ::lcdPrintf(m_fd, "%.*s", m_cols, m_buffer1);
} else if (m_rows == 4U && m_cols == 20U) { } else if (m_rows == 4U && m_cols == 20U) {
char m_buffer1[20U];
::sprintf(m_buffer1, "%.10s >", source); ::sprintf(m_buffer1, "%.10s >", source);
::lcdPosition(m_fd, 0, 1); ::lcdPosition(m_fd, 0, 1);
::lcdPrintf(m_fd, "%.*s", m_cols, m_buffer1); ::lcdPrintf(m_fd, "%.*s", m_cols, m_buffer1);
@ -992,27 +976,25 @@ void CHD44780::writeNXDNInt(const char* source, bool group, unsigned int dest, c
::lcdPosition(m_fd, 0, 2); ::lcdPosition(m_fd, 0, 2);
::lcdPrintf(m_fd, "%.*s", m_cols, m_buffer1); ::lcdPrintf(m_fd, "%.*s", m_cols, m_buffer1);
} else if (m_rows == 2 && m_cols == 40U) { } else if (m_rows == 2 && m_cols == 40U) {
char m_buffer1[40U];
::sprintf(m_buffer1, "%.10s > %s%u", source, group ? "TG" : "", dest); ::sprintf(m_buffer1, "%.10s > %s%u", source, group ? "TG" : "", dest);
::lcdPosition(m_fd, 0, 1); ::lcdPosition(m_fd, 0, 1);
::lcdPrintf(m_fd, "%.*s", m_cols, m_buffer1); ::lcdPrintf(m_fd, "%.*s", m_cols, m_buffer1);
} }
m_dmr = false; m_dmr = false;
m_rssiCount1 = 0U; m_rssiCount1 = 0U;
} }
void CHD44780::writeNXDNRSSIInt(unsigned char rssi) void CHD44780::writeNXDNRSSIInt(unsigned char rssi)
{ {
if (m_rssiCount1 == 0U && m_rows > 2) { if (m_rssiCount1 == 0U && m_rows > 2) {
::lcdPosition(m_fd, 0, 3); ::lcdPosition(m_fd, 0, 3);
::lcdPrintf(m_fd, "-%3udBm", rssi); ::lcdPrintf(m_fd, "-%3udBm", rssi);
} }
m_rssiCount1++; m_rssiCount1++;
if (m_rssiCount1 >= NXDN_RSSI_COUNT) if (m_rssiCount1 >= NXDN_RSSI_COUNT)
m_rssiCount1 = 0U; m_rssiCount1 = 0U;
} }
void CHD44780::clearNXDNInt() void CHD44780::clearNXDNInt()
@ -1050,16 +1032,115 @@ void CHD44780::clearNXDNInt()
} }
} }
void CHD44780::writeM17Int(const char* source, const char* dest, const char* type)
{
assert(source != NULL);
assert(dest != NULL);
assert(type != NULL);
#ifdef ADAFRUIT_DISPLAY
adafruitLCDColour(AC_RED);
#endif
m_clockDisplayTimer.stop(); // Stop the clock display
::lcdClear(m_fd);
if (m_pwm) {
if (m_pwmPin != 1U)
::softPwmWrite(m_pwmPin, m_pwmBright);
else
::pwmWrite(m_pwmPin, (m_pwmBright / 100) * 1024);
}
::lcdPosition(m_fd, 0, 0);
::lcdPuts(m_fd, "M17");
::sprintf(m_buffer1, "%.9s", source);
::sprintf(m_buffer2, "%.9s", dest);
if (m_rows == 2U && m_cols == 16U) {
::lcdPosition(m_fd, 5, 0);
::lcdPrintf(m_fd, "%.*s", m_cols - 5, m_buffer1);
::lcdPosition(m_fd, 5, 1);
::lcdPrintf(m_fd, "%.*s", m_cols - 5, m_buffer2);
} else if (m_rows == 4U && m_cols == 16U) {
::lcdPosition(m_fd, 0, 1);
::lcdPrintf(m_fd, "%.*s", m_cols, m_buffer1);
::lcdPosition(m_fd, 0, 2);
::lcdPrintf(m_fd, "%.*s", m_cols, m_buffer2);
} else if (m_rows == 4U && m_cols == 20U) {
::lcdPosition(m_fd, 0, 1);
::lcdPrintf(m_fd, "%.*s", m_cols, m_buffer1);
::lcdPosition(m_fd, 0, 2);
::lcdPrintf(m_fd, "%.*s", m_cols, m_buffer1);
} else if (m_rows == 2 && m_cols == 40U) {
::sprintf(m_buffer1, "%.9s > %.9s", source, dest);
::lcdPosition(m_fd, 0, 1);
::lcdPrintf(m_fd, "%.*s", m_cols, m_buffer1);
}
m_dmr = false;
m_rssiCount1 = 0U;
}
void CHD44780::writeM17RSSIInt(unsigned char rssi)
{
if (m_rssiCount1 == 0U && m_rows > 2) {
::lcdPosition(m_fd, 0, 3);
::lcdPrintf(m_fd, "-%3udBm", rssi);
}
m_rssiCount1++;
if (m_rssiCount1 >= M17_RSSI_COUNT)
m_rssiCount1 = 0U;
}
void CHD44780::clearM17Int()
{
#ifdef ADAFRUIT_DISPLAY
adafruitLCDColour(AC_PURPLE);
#endif
m_clockDisplayTimer.stop(); // Stop the clock display
if (m_rows == 2U && m_cols == 16U) {
::lcdPosition(m_fd, 5, 0);
::lcdPrintf(m_fd, "%.*s", m_cols - 5, LISTENING);
::lcdPosition(m_fd, 5, 1);
::lcdPrintf(m_fd, "%.*s", m_cols - 5, " ");
} else if (m_rows == 4U && m_cols == 16U) {
::lcdPosition(m_fd, 0, 1);
::lcdPrintf(m_fd, "%.*s", m_cols, LISTENING);
::lcdPosition(m_fd, 0, 2);
::lcdPrintf(m_fd, "%.*s", m_cols, " ");
::lcdPosition(m_fd, 0, 3);
::lcdPrintf(m_fd, "%.*s", m_cols, " ");
} else if (m_rows == 4U && m_cols == 20U) {
::lcdPosition(m_fd, 0, 1);
::lcdPrintf(m_fd, "%.*s", m_cols, LISTENING);
::lcdPosition(m_fd, 0, 2);
::lcdPrintf(m_fd, "%.*s", m_cols, " ");
::lcdPosition(m_fd, 0, 3);
::lcdPrintf(m_fd, "%.*s", m_cols, " ");
} else if (m_rows == 2 && m_cols == 40U) {
::lcdPosition(m_fd, 0, 1);
::lcdPrintf(m_fd, "%.*s", m_cols, LISTENING);
}
}
void CHD44780::writePOCSAGInt(uint32_t ric, const std::string& message) void CHD44780::writePOCSAGInt(uint32_t ric, const std::string& message)
{ {
::lcdPosition(m_fd, m_cols - 5, m_rows - 1); ::lcdPosition(m_fd, m_cols - 5, m_rows - 1);
::lcdPuts(m_fd, "POCSAG TX"); ::lcdPuts(m_fd, "POCSG"); // Shortened "POCSAG TX" to 5 characters because it wraps around onto the next line (or on 16x2 displays the 1st line).
} }
void CHD44780::clearPOCSAGInt() void CHD44780::clearPOCSAGInt()
{ {
::lcdPosition(m_fd, m_cols - 5, m_rows - 1); ::lcdPosition(m_fd, m_cols - 5, m_rows - 1);
::lcdPuts(m_fd, " Idle"); ::lcdPuts(m_fd, " Idle"); // Reverted back to 5 character implementation.
} }
void CHD44780::writeCWInt() void CHD44780::writeCWInt()
@ -1080,31 +1161,30 @@ void CHD44780::clockInt(unsigned int ms)
// Idle clock display // Idle clock display
if (m_displayClock && m_clockDisplayTimer.isRunning() && m_clockDisplayTimer.hasExpired()) { if (m_displayClock && m_clockDisplayTimer.isRunning() && m_clockDisplayTimer.hasExpired()) {
time_t currentTime; time_t currentTime;
struct tm *Time; struct tm *Time;
time(&currentTime); ::time(&currentTime);
if (m_utc) { if (m_utc)
Time = gmtime(&currentTime); Time = ::gmtime(&currentTime);
} else { else
Time = localtime(&currentTime); Time = ::localtime(&currentTime);
}
setlocale(LC_TIME,""); setlocale(LC_TIME,"");
strftime(m_buffer1, 128, "%X", Time); // Time ::strftime(m_buffer1, 128, "%X", Time); // Time
strftime(m_buffer2, 128, "%x", Time); // Date ::strftime(m_buffer2, 128, "%x", Time); // Date
if (m_cols == 16U && m_rows == 2U) { if (m_cols == 16U && m_rows == 2U) {
::lcdPosition(m_fd, m_cols - 10, 1); ::lcdPosition(m_fd, m_cols - 10, 1);
::lcdPrintf(m_fd, "%s%.*s", strlen(m_buffer1) > 8 ? "" : " ", 10, m_buffer1); ::lcdPrintf(m_fd, "%s%.*s", strlen(m_buffer1) > 8 ? "" : " ", 10, m_buffer1);
} else { } else {
::lcdPosition(m_fd, (m_cols - (strlen(m_buffer1) == 8 ? 8 : 10)) / 2, m_rows == 2 ? 1 : 2); ::lcdPosition(m_fd, (m_cols - (strlen(m_buffer1) == 8 ? 8 : 10)) / 2, m_rows == 2 ? 1 : 2);
::lcdPrintf(m_fd, "%.*s", strlen(m_buffer1) == 8 ? 8 : 10, m_buffer1); ::lcdPrintf(m_fd, "%.*s", strlen(m_buffer1) == 8 ? 8 : 10, m_buffer1);
::lcdPosition(m_fd, (m_cols - strlen(m_buffer2)) / 2, m_rows == 2 ? 0 : 1); ::lcdPosition(m_fd, (m_cols - strlen(m_buffer2)) / 2, m_rows == 2 ? 0 : 1);
::lcdPrintf(m_fd, "%s", m_buffer2); ::lcdPrintf(m_fd, "%s", m_buffer2);
} }
m_clockDisplayTimer.start(); m_clockDisplayTimer.start();
} }
} }

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2016,2017,2018,2020 by Jonathan Naylor G4KLX & Tony Corbett G0WFV * Copyright (C) 2016,2017,2018,2020,2021 by Jonathan Naylor G4KLX & Tony Corbett G0WFV
* *
* 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
@ -89,47 +89,51 @@ enum ADAFRUIT_COLOUR {
class CHD44780 : public CDisplay class CHD44780 : public CDisplay
{ {
public: public:
CHD44780(unsigned int rows, unsigned int cols, const std::string& callsign, unsigned int dmrid, const std::vector<unsigned int>& pins, unsigned int i2cAddress, bool pwm, unsigned int pwmPin, unsigned int pwmBright, unsigned int pwmDim, bool displayClock, bool utc, bool duplex); CHD44780(unsigned int rows, unsigned int cols, const std::string& callsign, unsigned int dmrid, const std::vector<unsigned int>& pins, unsigned int i2cAddress, bool pwm, unsigned int pwmPin, unsigned int pwmBright, unsigned int pwmDim, bool displayClock, bool utc, bool duplex);
virtual ~CHD44780(); virtual ~CHD44780();
virtual bool open(); virtual bool open();
virtual void close(); virtual void close();
protected: protected:
virtual void setIdleInt(); virtual void setIdleInt();
virtual void setErrorInt(const char* text); virtual void setErrorInt(const char* text);
virtual void setLockoutInt(); virtual void setLockoutInt();
virtual void setQuitInt(); virtual void setQuitInt();
virtual void setFMInt(); virtual void setFMInt();
virtual void writeDStarInt(const char* my1, const char* my2, const char* your, const char* type, const char* reflector); virtual void writeDStarInt(const char* my1, const char* my2, const char* your, const char* type, const char* reflector);
virtual void writeDStarRSSIInt(unsigned char rssi); virtual void writeDStarRSSIInt(unsigned char rssi);
virtual void clearDStarInt(); virtual void clearDStarInt();
virtual void writeDMRInt(unsigned int slotNo, const std::string& src, bool group, const std::string& dst, const char* type); virtual void writeDMRInt(unsigned int slotNo, const std::string& src, bool group, const std::string& dst, const char* type);
virtual void writeDMRRSSIInt(unsigned int slotNo, unsigned char rssi); virtual void writeDMRRSSIInt(unsigned int slotNo, unsigned char rssi);
virtual void clearDMRInt(unsigned int slotNo); virtual void clearDMRInt(unsigned int slotNo);
virtual void writeFusionInt(const char* source, const char* dest, unsigned char dgid, const char* type, const char* origin); virtual void writeFusionInt(const char* source, const char* dest, unsigned char dgid, const char* type, const char* origin);
virtual void writeFusionRSSIInt(unsigned char rssi); virtual void writeFusionRSSIInt(unsigned char rssi);
virtual void clearFusionInt(); virtual void clearFusionInt();
virtual void writeP25Int(const char* source, bool group, unsigned int dest, const char* type); virtual void writeP25Int(const char* source, bool group, unsigned int dest, const char* type);
virtual void writeP25RSSIInt(unsigned char rssi); virtual void writeP25RSSIInt(unsigned char rssi);
virtual void clearP25Int(); virtual void clearP25Int();
virtual void writeNXDNInt(const char* source, bool group, unsigned int dest, const char* type); virtual void writeNXDNInt(const char* source, bool group, unsigned int dest, const char* type);
virtual void writeNXDNRSSIInt(unsigned char rssi); virtual void writeNXDNRSSIInt(unsigned char rssi);
virtual void clearNXDNInt(); virtual void clearNXDNInt();
virtual void writePOCSAGInt(uint32_t ric, const std::string& message); virtual void writeM17Int(const char* source, const char* dest, const char* type);
virtual void clearPOCSAGInt(); virtual void writeM17RSSIInt(unsigned char rssi);
virtual void clearM17Int();
virtual void writeCWInt(); virtual void writePOCSAGInt(uint32_t ric, const std::string& message);
virtual void clearCWInt(); virtual void clearPOCSAGInt();
virtual void clockInt(unsigned int ms); virtual void writeCWInt();
virtual void clearCWInt();
virtual void clockInt(unsigned int ms);
private: private:
unsigned int m_rows; unsigned int m_rows;
@ -162,12 +166,12 @@ private:
*/ */
#ifdef ADAFRUIT_DISPLAY #ifdef ADAFRUIT_DISPLAY
void adafruitLCDSetup(); void adafruitLCDSetup();
void adafruitLCDColour(ADAFRUIT_COLOUR colour); void adafruitLCDColour(ADAFRUIT_COLOUR colour);
#endif #endif
#ifdef PCF8574_DISPLAY #ifdef PCF8574_DISPLAY
void pcf8574LCDSetup(); void pcf8574LCDSetup();
#endif #endif
}; };

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2002-2004,2007-2011,2013,2014-2017 by Jonathan Naylor G4KLX * Copyright (C) 2002-2004,2007-2011,2013,2014-2017,2020 by Jonathan Naylor G4KLX
* Copyright (C) 1999-2001 by Thomas Sailor HB9JNX * Copyright (C) 1999-2001 by Thomas Sailor HB9JNX
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
@ -17,6 +17,8 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/ */
#if defined(__linux__)
#include "I2CController.h" #include "I2CController.h"
#include "Log.h" #include "Log.h"
@ -24,52 +26,18 @@
#include <cassert> #include <cassert>
#include <sys/types.h> #include <sys/types.h>
#if defined(_WIN32) || defined(_WIN64)
#include <setupapi.h>
#include <winioctl.h>
CI2CController::CI2CController(const std::string& device, SERIAL_SPEED speed, unsigned int address, bool assertRTS) :
CSerialController(device, speed, assertRTS),
m_address(address)
{
}
CI2CController::~CI2CController()
{
}
bool CI2CController::open()
{
return CSerialController::open();
}
int CI2CController::read(unsigned char* buffer, unsigned int length)
{
return CSerialController::read(buffer, length);
}
int CI2CController::write(const unsigned char* buffer, unsigned int length)
{
return CSerialController::write(buffer, length);
}
#else
#include <sys/ioctl.h> #include <sys/ioctl.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <cerrno> #include <cerrno>
#include <fcntl.h> #include <fcntl.h>
#include <unistd.h> #include <unistd.h>
#include <termios.h> #include <termios.h>
#if defined(__linux__)
#include <linux/i2c-dev.h> #include <linux/i2c-dev.h>
#endif
CI2CController::CI2CController(const std::string& device, SERIAL_SPEED speed, unsigned int address, bool assertRTS) : CI2CController::CI2CController(const std::string& device, unsigned int address) :
CSerialController(device, speed, assertRTS), m_device(device),
m_address(address) m_address(address),
m_fd(-1)
{ {
} }
@ -81,7 +49,6 @@ bool CI2CController::open()
{ {
assert(m_fd == -1); assert(m_fd == -1);
#if defined(__linux__)
m_fd = ::open(m_device.c_str(), O_RDWR); m_fd = ::open(m_device.c_str(), O_RDWR);
if (m_fd < 0) { if (m_fd < 0) {
LogError("Cannot open device - %s", m_device.c_str()); LogError("Cannot open device - %s", m_device.c_str());
@ -89,19 +56,16 @@ bool CI2CController::open()
} }
if (::ioctl(m_fd, I2C_TENBIT, 0) < 0) { if (::ioctl(m_fd, I2C_TENBIT, 0) < 0) {
LogError("CI2C: failed to set 7bitaddress"); LogError("I2C: failed to set 7bitaddress");
::close(m_fd); ::close(m_fd);
return false; return false;
} }
if (::ioctl(m_fd, I2C_SLAVE, m_address) < 0) { if (::ioctl(m_fd, I2C_SLAVE, m_address) < 0) {
LogError("CI2C: Failed to acquire bus access/talk to slave 0x%02X", m_address); LogError("I2C: Failed to acquire bus access/talk to slave 0x%02X", m_address);
::close(m_fd); ::close(m_fd);
return false; return false;
} }
#else
#warning "I2C controller supports Linux only"
#endif
return true; return true;
} }
@ -117,7 +81,6 @@ int CI2CController::read(unsigned char* buffer, unsigned int length)
unsigned int offset = 0U; unsigned int offset = 0U;
while (offset < length) { while (offset < length) {
#if defined(__linux__)
ssize_t n = ::read(m_fd, buffer + offset, 1U); ssize_t n = ::read(m_fd, buffer + offset, 1U);
if (n < 0) { if (n < 0) {
if (errno != EAGAIN) { if (errno != EAGAIN) {
@ -128,7 +91,6 @@ int CI2CController::read(unsigned char* buffer, unsigned int length)
if (n > 0) if (n > 0)
offset += n; offset += n;
#endif
} }
return length; return length;
@ -144,10 +106,7 @@ int CI2CController::write(const unsigned char* buffer, unsigned int length)
unsigned int ptr = 0U; unsigned int ptr = 0U;
while (ptr < length) { while (ptr < length) {
ssize_t n = 0U; ssize_t n = ::write(m_fd, buffer + ptr, 1U);
#if defined(__linux__)
n = ::write(m_fd, buffer + ptr, 1U);
#endif
if (n < 0) { if (n < 0) {
if (errno != EAGAIN) { if (errno != EAGAIN) {
LogError("Error returned from write(), errno=%d", errno); LogError("Error returned from write(), errno=%d", errno);
@ -162,4 +121,12 @@ int CI2CController::write(const unsigned char* buffer, unsigned int length)
return length; return length;
} }
void CI2CController::close()
{
assert(m_fd != -1);
::close(m_fd);
m_fd = -1;
}
#endif #endif

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2002-2004,2007-2009,2011-2013,2015-2017 by Jonathan Naylor G4KLX * Copyright (C) 2002-2004,2007-2009,2011-2013,2015-2017,2020,2021 by Jonathan Naylor G4KLX
* Copyright (C) 1999-2001 by Thomas Sailor HB9JNX * Copyright (C) 1999-2001 by Thomas Sailor HB9JNX
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
@ -20,11 +20,16 @@
#ifndef I2CController_H #ifndef I2CController_H
#define I2CController_H #define I2CController_H
#include "SerialController.h" #if defined(__linux__)
class CI2CController : public CSerialController { #include "ModemPort.h"
#include "SerialPort.h"
#include <string>
class CI2CController : public ISerialPort, public IModemPort {
public: public:
CI2CController(const std::string& device, SERIAL_SPEED speed, unsigned int address = 0x22U, bool assertRTS = false); CI2CController(const std::string& device, unsigned int address = 0x22U);
virtual ~CI2CController(); virtual ~CI2CController();
virtual bool open(); virtual bool open();
@ -33,8 +38,14 @@ public:
virtual int write(const unsigned char* buffer, unsigned int length); virtual int write(const unsigned char* buffer, unsigned int length);
virtual void close();
private: private:
std::string m_device;
unsigned int m_address; unsigned int m_address;
int m_fd;
}; };
#endif #endif
#endif

60
IIRDirectForm1Filter.cpp Normal file
View file

@ -0,0 +1,60 @@
/*
* Copyright (C) 2015-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 "IIRDirectForm1Filter.h"
#include "math.h"
CIIRDirectForm1Filter::CIIRDirectForm1Filter(float b0, float b1, float b2, float , float a1, float a2, float addtionalGaindB) :
m_x2(0.0F),
m_y2(0.0F),
m_x1(0.0F),
m_y1(0.0F),
m_b0(b0),
m_b1(b1),
m_b2(b2),
m_a1(a1),
m_a2(a2),
m_additionalGainLin(0.0F)
{
m_additionalGainLin = ::powf(10.0F, addtionalGaindB / 20.0F);
}
float CIIRDirectForm1Filter::filter(float sample)
{
float output = m_b0 * sample
+ m_b1 * m_x1
+ m_b2 * m_x2
- m_a1 * m_y1
- m_a2 * m_y2;
m_x2 = m_x1;
m_y2 = m_y1;
m_x1 = sample;
m_y1 = output;
return output * m_additionalGainLin;
}
void CIIRDirectForm1Filter::reset()
{
m_x1 = 0.0f;
m_x2 = 0.0f;
m_y1 = 0.0f;
m_y2 = 0.0f;
}

View file

@ -1,5 +1,6 @@
/* /*
* Copyright (C) 2020 by Jonathan Naylor G4KLX * Copyright (C) 2015-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,19 +17,34 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/ */
#if !defined(M17CRC_H) #if !defined(IIRDIRECTFORM1FILTER_H)
#define M17CRC_H #define IIRDIRECTFORM1FILTER_H
#include <cstdint> class CIIRDirectForm1Filter
class CM17CRC
{ {
public: public:
static bool checkCRC(const unsigned char* in, unsigned int nBytes); CIIRDirectForm1Filter(float b0, float b1, float b2, float, float a1, float a2, float additionalGaindB);
static void encodeCRC(unsigned char* in, unsigned int nBytes); float filter(float sample);
void reset();
private: private:
static uint16_t createCRC(const unsigned char* in, unsigned int nBytes); // delay line
float m_x2; // x[n-2]
float m_y2; // y[n-2]
float m_x1; // x[n-1]
float m_y1; // y[n-1]
// coefficients
// FIR
float m_b0;
float m_b1;
float m_b2;
// IIR
float m_a1;
float m_a2;
float m_additionalGainLin;
}; };
#endif
#endif

View file

@ -1,9 +0,0 @@
D-Star: On some radios, the header is not decoded correctly. It looks like frequency drift at the beginning of the transmission.
DMR: DMO mode doesn't wake up older radios like other radios do.
YSF: No known issues.
P25: Upgrade the filters, processing power in the Due permiting.
NXDN: No known issues.

View file

@ -97,7 +97,7 @@ const unsigned int P25_RSSI_COUNT = 7U; // 7 * 180ms = 1260ms
const unsigned int NXDN_RSSI_COUNT = 28U; // 28 * 40ms = 1120ms const unsigned int NXDN_RSSI_COUNT = 28U; // 28 * 40ms = 1120ms
const unsigned int M17_RSSI_COUNT = 28U; // 28 * 40ms = 1120ms const unsigned int M17_RSSI_COUNT = 28U; // 28 * 40ms = 1120ms
CLCDproc::CLCDproc(std::string address, unsigned int port, unsigned int localPort, const std::string& callsign, unsigned int dmrid, bool displayClock, bool utc, bool duplex, bool dimOnIdle) : CLCDproc::CLCDproc(std::string address, unsigned int port, unsigned short localPort, const std::string& callsign, unsigned int dmrid, bool displayClock, bool utc, bool duplex, bool dimOnIdle) :
CDisplay(), CDisplay(),
m_address(address), m_address(address),
m_port(port), m_port(port),

View file

@ -28,7 +28,7 @@
class CLCDproc : public CDisplay class CLCDproc : public CDisplay
{ {
public: public:
CLCDproc(std::string address, unsigned int port, unsigned int localPort, const std::string& callsign, unsigned int dmrid, bool displayClock, bool utc, bool duplex, bool dimOnIdle); CLCDproc(std::string address, unsigned int port, unsigned short localPort, const std::string& callsign, unsigned int dmrid, bool displayClock, bool utc, bool duplex, bool dimOnIdle);
virtual ~CLCDproc(); virtual ~CLCDproc();
virtual bool open(); virtual bool open();
@ -77,7 +77,7 @@ protected:
private: private:
std::string m_address; std::string m_address;
unsigned int m_port; unsigned int m_port;
unsigned int m_localPort; unsigned short m_localPort;
std::string m_callsign; std::string m_callsign;
unsigned int m_dmrid; unsigned int m_dmrid;
bool m_displayClock; bool m_displayClock;

View file

@ -161,7 +161,7 @@ void Log(unsigned int level, const char* fmt, ...)
struct tm* tm = ::gmtime(&now.tv_sec); struct tm* tm = ::gmtime(&now.tv_sec);
::sprintf(buffer, "%c: %04d-%02d-%02d %02d:%02d:%02d.%03ld ", LEVELS[level], tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec, now.tv_usec / 1000L); ::sprintf(buffer, "%c: %04d-%02d-%02d %02d:%02d:%02d.%03lld ", LEVELS[level], tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec, now.tv_usec / 1000LL);
#endif #endif
va_list vl; va_list vl;

View file

@ -1,85 +0,0 @@
/*
* Copyright (C) 2018,2020 by Jonathan Naylor G4KLX
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "M17CRC.h"
#include <cstdio>
#include <cassert>
const uint16_t CRC_TABLE[] = {0x0000U, 0x5935U, 0xB26AU, 0xEB5FU, 0x3DE1U, 0x64D4U, 0x8F8BU, 0xD6BEU, 0x7BC2U, 0x22F7U, 0xC9A8U,
0x909DU, 0x4623U, 0x1F16U, 0xF449U, 0xAD7CU, 0xF784U, 0xAEB1U, 0x45EEU, 0x1CDBU, 0xCA65U, 0x9350U,
0x780FU, 0x213AU, 0x8C46U, 0xD573U, 0x3E2CU, 0x6719U, 0xB1A7U, 0xE892U, 0x03CDU, 0x5AF8U, 0xB63DU,
0xEF08U, 0x0457U, 0x5D62U, 0x8BDCU, 0xD2E9U, 0x39B6U, 0x6083U, 0xCDFFU, 0x94CAU, 0x7F95U, 0x26A0U,
0xF01EU, 0xA92BU, 0x4274U, 0x1B41U, 0x41B9U, 0x188CU, 0xF3D3U, 0xAAE6U, 0x7C58U, 0x256DU, 0xCE32U,
0x9707U, 0x3A7BU, 0x634EU, 0x8811U, 0xD124U, 0x079AU, 0x5EAFU, 0xB5F0U, 0xECC5U, 0x354FU, 0x6C7AU,
0x8725U, 0xDE10U, 0x08AEU, 0x519BU, 0xBAC4U, 0xE3F1U, 0x4E8DU, 0x17B8U, 0xFCE7U, 0xA5D2U, 0x736CU,
0x2A59U, 0xC106U, 0x9833U, 0xC2CBU, 0x9BFEU, 0x70A1U, 0x2994U, 0xFF2AU, 0xA61FU, 0x4D40U, 0x1475U,
0xB909U, 0xE03CU, 0x0B63U, 0x5256U, 0x84E8U, 0xDDDDU, 0x3682U, 0x6FB7U, 0x8372U, 0xDA47U, 0x3118U,
0x682DU, 0xBE93U, 0xE7A6U, 0x0CF9U, 0x55CCU, 0xF8B0U, 0xA185U, 0x4ADAU, 0x13EFU, 0xC551U, 0x9C64U,
0x773BU, 0x2E0EU, 0x74F6U, 0x2DC3U, 0xC69CU, 0x9FA9U, 0x4917U, 0x1022U, 0xFB7DU, 0xA248U, 0x0F34U,
0x5601U, 0xBD5EU, 0xE46BU, 0x32D5U, 0x6BE0U, 0x80BFU, 0xD98AU, 0x6A9EU, 0x33ABU, 0xD8F4U, 0x81C1U,
0x577FU, 0x0E4AU, 0xE515U, 0xBC20U, 0x115CU, 0x4869U, 0xA336U, 0xFA03U, 0x2CBDU, 0x7588U, 0x9ED7U,
0xC7E2U, 0x9D1AU, 0xC42FU, 0x2F70U, 0x7645U, 0xA0FBU, 0xF9CEU, 0x1291U, 0x4BA4U, 0xE6D8U, 0xBFEDU,
0x54B2U, 0x0D87U, 0xDB39U, 0x820CU, 0x6953U, 0x3066U, 0xDCA3U, 0x8596U, 0x6EC9U, 0x37FCU, 0xE142U,
0xB877U, 0x5328U, 0x0A1DU, 0xA761U, 0xFE54U, 0x150BU, 0x4C3EU, 0x9A80U, 0xC3B5U, 0x28EAU, 0x71DFU,
0x2B27U, 0x7212U, 0x994DU, 0xC078U, 0x16C6U, 0x4FF3U, 0xA4ACU, 0xFD99U, 0x50E5U, 0x09D0U, 0xE28FU,
0xBBBAU, 0x6D04U, 0x3431U, 0xDF6EU, 0x865BU, 0x5FD1U, 0x06E4U, 0xEDBBU, 0xB48EU, 0x6230U, 0x3B05U,
0xD05AU, 0x896FU, 0x2413U, 0x7D26U, 0x9679U, 0xCF4CU, 0x19F2U, 0x40C7U, 0xAB98U, 0xF2ADU, 0xA855U,
0xF160U, 0x1A3FU, 0x430AU, 0x95B4U, 0xCC81U, 0x27DEU, 0x7EEBU, 0xD397U, 0x8AA2U, 0x61FDU, 0x38C8U,
0xEE76U, 0xB743U, 0x5C1CU, 0x0529U, 0xE9ECU, 0xB0D9U, 0x5B86U, 0x02B3U, 0xD40DU, 0x8D38U, 0x6667U,
0x3F52U, 0x922EU, 0xCB1BU, 0x2044U, 0x7971U, 0xAFCFU, 0xF6FAU, 0x1DA5U, 0x4490U, 0x1E68U, 0x475DU,
0xAC02U, 0xF537U, 0x2389U, 0x7ABCU, 0x91E3U, 0xC8D6U, 0x65AAU, 0x3C9FU, 0xD7C0U, 0x8EF5U, 0x584BU,
0x017EU, 0xEA21U, 0xB314U};
bool CM17CRC::checkCRC(const unsigned char* in, unsigned int nBytes)
{
assert(in != NULL);
assert(nBytes > 2U);
uint16_t crc = createCRC(in, nBytes - 2U);
uint8_t temp[2U];
temp[0U] = (crc >> 8) & 0xFFU;
temp[1U] = (crc >> 0) & 0xFFU;
return temp[0U] == in[nBytes - 2U] && temp[1U] == in[nBytes - 1U];
}
void CM17CRC::encodeCRC(unsigned char* in, unsigned int nBytes)
{
assert(in != NULL);
assert(nBytes > 2U);
uint16_t crc = createCRC(in, nBytes - 2U);
in[nBytes - 2U] = (crc >> 8) & 0xFFU;
in[nBytes - 1U] = (crc >> 0) & 0xFFU;
}
uint16_t CM17CRC::createCRC(const unsigned char* in, unsigned int nBytes)
{
assert(in != NULL);
uint16_t crc = 0xFFFFU;
for (unsigned int i = 0U; i < nBytes; i++)
crc = (crc << 8) ^ CRC_TABLE[((crc >> 8) ^ uint16_t(in[i])) & 0x00FFU];
return crc;
}

View file

@ -1,841 +0,0 @@
/*
* Copyright (C) 2015-2020 Jonathan Naylor, G4KLX
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* 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.
*/
#include "M17Control.h"
#include "M17Convolution.h"
#include "M17Utils.h"
#include "M17CRC.h"
#include "Golay24128.h"
#include "Utils.h"
#include "Sync.h"
#include "Log.h"
#include <cstdio>
#include <cassert>
#include <cstring>
#include <ctime>
const unsigned int INTERLEAVER[] = {
0U, 137U, 90U, 227U, 180U, 317U, 270U, 39U, 360U, 129U, 82U, 219U, 172U, 309U, 262U, 31U, 352U, 121U, 74U, 211U, 164U,
301U, 254U, 23U, 344U, 113U, 66U, 203U, 156U, 293U, 246U, 15U, 336U, 105U, 58U, 195U, 148U, 285U, 238U, 7U, 328U, 97U,
50U, 187U, 140U, 277U, 230U, 367U, 320U, 89U, 42U, 179U, 132U, 269U, 222U, 359U, 312U, 81U, 34U, 171U, 124U, 261U, 214U,
351U, 304U, 73U, 26U, 163U, 116U, 253U, 206U, 343U, 296U, 65U, 18U, 155U, 108U, 245U, 198U, 335U, 288U, 57U, 10U, 147U,
100U, 237U, 190U, 327U, 280U, 49U, 2U, 139U, 92U, 229U, 182U, 319U, 272U, 41U, 362U, 131U, 84U, 221U, 174U, 311U, 264U,
33U, 354U, 123U, 76U, 213U, 166U, 303U, 256U, 25U, 346U, 115U, 68U, 205U, 158U, 295U, 248U, 17U, 338U, 107U, 60U, 197U,
150U, 287U, 240U, 9U, 330U, 99U, 52U, 189U, 142U, 279U, 232U, 1U, 322U, 91U, 44U, 181U, 134U, 271U, 224U, 361U, 314U, 83U,
36U, 173U, 126U, 263U, 216U, 353U, 306U, 75U, 28U, 165U, 118U, 255U, 208U, 345U, 298U, 67U, 20U, 157U, 110U, 247U, 200U,
337U, 290U, 59U, 12U, 149U, 102U, 239U, 192U, 329U, 282U, 51U, 4U, 141U, 94U, 231U, 184U, 321U, 274U, 43U, 364U, 133U, 86U,
223U, 176U, 313U, 266U, 35U, 356U, 125U, 78U, 215U, 168U, 305U, 258U, 27U, 348U, 117U, 70U, 207U, 160U, 297U, 250U, 19U,
340U, 109U, 62U, 199U, 152U, 289U, 242U, 11U, 332U, 101U, 54U, 191U, 144U, 281U, 234U, 3U, 324U, 93U, 46U, 183U, 136U, 273U,
226U, 363U, 316U, 85U, 38U, 175U, 128U, 265U, 218U, 355U, 308U, 77U, 30U, 167U, 120U, 257U, 210U, 347U, 300U, 69U, 22U,
159U, 112U, 249U, 202U, 339U, 292U, 61U, 14U, 151U, 104U, 241U, 194U, 331U, 284U, 53U, 6U, 143U, 96U, 233U, 186U, 323U,
276U, 45U, 366U, 135U, 88U, 225U, 178U, 315U, 268U, 37U, 358U, 127U, 80U, 217U, 170U, 307U, 260U, 29U, 350U, 119U, 72U,
209U, 162U, 299U, 252U, 21U, 342U, 111U, 64U, 201U, 154U, 291U, 244U, 13U, 334U, 103U, 56U, 193U, 146U, 283U, 236U, 5U,
326U, 95U, 48U, 185U, 138U, 275U, 228U, 365U, 318U, 87U, 40U, 177U, 130U, 267U, 220U, 357U, 310U, 79U, 32U, 169U, 122U,
259U, 212U, 349U, 302U, 71U, 24U, 161U, 114U, 251U, 204U, 341U, 294U, 63U, 16U, 153U, 106U, 243U, 196U, 333U, 286U, 55U,
8U, 145U, 98U, 235U, 188U, 325U, 278U, 47U};
const unsigned char SCRAMBLER[] = {
0x00U, 0x00U, 0xD6U, 0xB5U, 0xE2U, 0x30U, 0x82U, 0xFFU, 0x84U, 0x62U, 0xBAU, 0x4EU, 0x96U, 0x90U, 0xD8U, 0x98U, 0xDDU,
0x5DU, 0x0CU, 0xC8U, 0x52U, 0x43U, 0x91U, 0x1DU, 0xF8U, 0x6EU, 0x68U, 0x2FU, 0x35U, 0xDAU, 0x14U, 0xEAU, 0xCDU, 0x76U,
0x19U, 0x8DU, 0xD5U, 0x80U, 0xD1U, 0x33U, 0x87U, 0x13U, 0x57U, 0x18U, 0x2DU, 0x29U, 0x78U, 0xC3U};
// #define DUMP_M17
const unsigned char BIT_MASK_TABLE[] = { 0x80U, 0x40U, 0x20U, 0x10U, 0x08U, 0x04U, 0x02U, 0x01U };
#define WRITE_BIT(p,i,b) p[(i)>>3] = (b) ? (p[(i)>>3] | BIT_MASK_TABLE[(i)&7]) : (p[(i)>>3] & ~BIT_MASK_TABLE[(i)&7])
#define READ_BIT(p,i) (p[(i)>>3] & BIT_MASK_TABLE[(i)&7])
CM17Control::CM17Control(const std::string& callsign, bool selfOnly, bool allowEncryption, CM17Network* network, CDisplay* display, unsigned int timeout, bool duplex, CRSSIInterpolator* rssiMapper) :
m_callsign(callsign),
m_selfOnly(selfOnly),
m_allowEncryption(allowEncryption),
m_network(network),
m_display(display),
m_duplex(duplex),
m_queue(5000U, "M17 Control"),
m_rfState(RS_RF_LISTENING),
m_netState(RS_NET_IDLE),
m_rfTimeoutTimer(1000U, timeout),
m_netTimeoutTimer(1000U, timeout),
m_packetTimer(1000U, 0U, 200U),
m_networkWatchdog(1000U, 0U, 1500U),
m_elapsed(),
m_rfFrames(0U),
m_netFrames(0U),
m_rfFN(0U),
m_rfErrs(0U),
m_rfBits(1U),
m_rfLICH(),
m_netLICH(),
m_rssiMapper(rssiMapper),
m_rssi(0U),
m_maxRSSI(0U),
m_minRSSI(0U),
m_aveRSSI(0U),
m_rssiCount(0U),
m_enabled(true),
m_fp(NULL)
{
assert(display != NULL);
assert(rssiMapper != NULL);
}
CM17Control::~CM17Control()
{
}
bool CM17Control::writeModem(unsigned char* data, unsigned int len)
{
assert(data != NULL);
if (!m_enabled)
return false;
unsigned char type = data[0U];
if (type == TAG_LOST && m_rfState == RS_RF_AUDIO) {
std::string source = m_rfLICH.getSource();
std::string dest = m_rfLICH.getDest();
if (m_rssi != 0U)
LogMessage("M17, transmission lost from %s to %s, %.1f seconds, BER: %.1f%%, RSSI: -%u/-%u/-%u dBm", source.c_str(), dest.c_str(), float(m_rfFrames) / 25.0F, float(m_rfErrs * 100U) / float(m_rfBits), m_minRSSI, m_maxRSSI, m_aveRSSI / m_rssiCount);
else
LogMessage("M17, transmission lost from %s to %s, %.1f seconds, BER: %.1f%%", source.c_str(), dest.c_str(), float(m_rfFrames) / 25.0F, float(m_rfErrs * 100U) / float(m_rfBits));
writeEndRF();
return false;
}
if (type == TAG_LOST && m_rfState == RS_RF_DATA) {
writeEndRF();
return false;
}
if (type == TAG_LOST) {
m_rfState = RS_RF_LISTENING;
return false;
}
// Have we got RSSI bytes on the end?
if (len == (M17_FRAME_LENGTH_BYTES + 4U)) {
uint16_t raw = 0U;
raw |= (data[50U] << 8) & 0xFF00U;
raw |= (data[51U] << 0) & 0x00FFU;
// Convert the raw RSSI to dBm
int rssi = m_rssiMapper->interpolate(raw);
if (rssi != 0)
LogDebug("M17, raw RSSI: %u, reported RSSI: %d dBm", raw, rssi);
// RSSI is always reported as positive
m_rssi = (rssi >= 0) ? rssi : -rssi;
if (m_rssi > m_minRSSI)
m_minRSSI = m_rssi;
if (m_rssi < m_maxRSSI)
m_maxRSSI = m_rssi;
m_aveRSSI += m_rssi;
m_rssiCount++;
}
unsigned char temp[M17_FRAME_LENGTH_BYTES];
decorrelator(data + 2U, temp);
interleaver(temp, data + 2U);
if (m_rfState == RS_RF_LISTENING) {
m_rfLICH.reset();
CM17Convolution conv;
unsigned char frame[M17_LICH_LENGTH_BYTES];
conv.decodeLinkSetup(data + 2U + M17_SYNC_LENGTH_BYTES, frame);
bool valid = CM17CRC::checkCRC(frame, M17_LICH_LENGTH_BYTES);
if (valid) {
m_rfFrames = 0U;
m_rfErrs = 0U;
m_rfBits = 1U;
m_rfTimeoutTimer.start();
m_minRSSI = m_rssi;
m_maxRSSI = m_rssi;
m_aveRSSI = m_rssi;
m_rssiCount = 1U;
m_rfFN = 0U;
#if defined(DUMP_M17)
openFile();
#endif
m_rfLICH.setLinkSetup(frame);
std::string source = m_rfLICH.getSource();
std::string dest = m_rfLICH.getDest();
if (m_selfOnly) {
bool ret = checkCallsign(source);
if (!ret) {
LogMessage("M17, invalid access attempt from %s to %s", source.c_str(), dest.c_str());
m_rfState = RS_RF_REJECTED;
return false;
}
}
if (!m_allowEncryption) {
bool ret = m_rfLICH.isNONCENull();
if (!ret) {
LogMessage("M17, invalid access attempt from %s to %s", source.c_str(), dest.c_str());
m_rfState = RS_RF_REJECTED;
return false;
}
}
unsigned char dataType = m_rfLICH.getDataType();
switch (dataType) {
case 1U:
LogMessage("M17, received RF data transmission from %s to %s", source.c_str(), dest.c_str());
m_rfState = RS_RF_DATA;
break;
case 2U:
LogMessage("M17, received RF voice transmission from %s to %s", source.c_str(), dest.c_str());
m_rfState = RS_RF_AUDIO;
break;
case 3U:
LogMessage("M17, received RF voice + data transmission from %s to %s", source.c_str(), dest.c_str());
m_rfState = RS_RF_AUDIO;
break;
default:
LogMessage("M17, received RF unknown transmission from %s to %s", source.c_str(), dest.c_str());
m_rfState = RS_RF_DATA;
break;
}
m_display->writeM17(source.c_str(), dest.c_str(), "R");
#if defined(DUMP_M17)
writeFile(data + 2U);
#endif
if (m_duplex) {
data[0U] = TAG_DATA;
data[1U] = 0x00U;
// Generate the sync
CSync::addM17Sync(data + 2U);
unsigned char setup[M17_LICH_LENGTH_BYTES];
m_rfLICH.getLinkSetup(setup);
// Add the convolution FEC
CM17Convolution conv;
conv.encodeLinkSetup(setup, data + 2U + M17_SYNC_LENGTH_BYTES);
unsigned char temp[M17_FRAME_LENGTH_BYTES];
interleaver(data + 2U, temp);
decorrelator(temp, data + 2U);
writeQueueRF(data);
}
return true;
} else {
m_rfState = RS_RF_LATE_ENTRY;
}
}
if (m_rfState == RS_RF_LATE_ENTRY) {
CM17Convolution conv;
unsigned char frame[M17_FN_LENGTH_BYTES + M17_PAYLOAD_LENGTH_BYTES + M17_CRC_LENGTH_BYTES];
conv.decodeData(data + 2U + M17_SYNC_LENGTH_BYTES + M17_LICH_FRAGMENT_FEC_LENGTH_BYTES, frame);
bool valid = CM17CRC::checkCRC(frame, M17_FN_LENGTH_BYTES + M17_PAYLOAD_LENGTH_BYTES + M17_CRC_LENGTH_BYTES);
if (valid) {
m_rfFN = (frame[0U] << 8) + (frame[1U] << 0);
unsigned int frag1, frag2, frag3, frag4;
CM17Utils::splitFragmentLICHFEC(data + 2U + M17_SYNC_LENGTH_BYTES, frag1, frag2, frag3, frag4);
unsigned int lich1 = CGolay24128::decode24128(frag1);
unsigned int lich2 = CGolay24128::decode24128(frag2);
unsigned int lich3 = CGolay24128::decode24128(frag3);
unsigned int lich4 = CGolay24128::decode24128(frag4);
unsigned char lich[M17_LICH_FRAGMENT_LENGTH_BYTES];
CM17Utils::combineFragmentLICH(lich1, lich2, lich3, lich4, lich);
m_rfLICH.setFragment(lich, m_rfFN);
valid = m_rfLICH.isValid();
if (valid) {
m_rfFrames = 0U;
m_rfErrs = 0U;
m_rfBits = 1U;
m_rfTimeoutTimer.start();
m_minRSSI = m_rssi;
m_maxRSSI = m_rssi;
m_aveRSSI = m_rssi;
m_rssiCount = 1U;
#if defined(DUMP_M17)
openFile();
#endif
std::string source = m_rfLICH.getSource();
std::string dest = m_rfLICH.getDest();
if (m_selfOnly) {
bool ret = checkCallsign(source);
if (!ret) {
LogMessage("M17, invalid access attempt from %s to %s", source.c_str(), dest.c_str());
m_rfState = RS_RF_REJECTED;
return false;
}
}
unsigned char dataType = m_rfLICH.getDataType();
switch (dataType) {
case 1U:
LogMessage("M17, received RF late entry data transmission from %s to %s", source.c_str(), dest.c_str());
m_rfState = RS_RF_DATA;
break;
case 2U:
LogMessage("M17, received RF late entry voice transmission from %s to %s", source.c_str(), dest.c_str());
m_rfState = RS_RF_AUDIO;
break;
case 3U:
LogMessage("M17, received RF late entry voice + data transmission from %s to %s", source.c_str(), dest.c_str());
m_rfState = RS_RF_AUDIO;
break;
default:
LogMessage("M17, received RF late entry unknown transmission from %s to %s", source.c_str(), dest.c_str());
m_rfState = RS_RF_DATA;
break;
}
m_display->writeM17(source.c_str(), dest.c_str(), "R");
if (m_duplex) {
// Create a Link Setup frame
data[0U] = TAG_DATA;
data[1U] = 0x00U;
// Generate the sync
CSync::addM17Sync(data + 2U);
unsigned char setup[M17_LICH_LENGTH_BYTES];
m_rfLICH.getLinkSetup(setup);
// Add the convolution FEC
CM17Convolution conv;
conv.encodeLinkSetup(setup, data + 2U + M17_SYNC_LENGTH_BYTES);
unsigned char temp[M17_FRAME_LENGTH_BYTES];
interleaver(data + 2U, temp);
decorrelator(temp, data + 2U);
writeQueueRF(data);
}
// Fall through to the next section
}
}
}
if (m_rfState == RS_RF_AUDIO || m_rfState == RS_RF_DATA) {
#if defined(DUMP_M17)
writeFile(data + 2U);
#endif
CM17Convolution conv;
unsigned char frame[M17_FN_LENGTH_BYTES + M17_PAYLOAD_LENGTH_BYTES + M17_CRC_LENGTH_BYTES];
conv.decodeData(data + 2U + M17_SYNC_LENGTH_BYTES + M17_LICH_FRAGMENT_FEC_LENGTH_BYTES, frame);
bool valid = CM17CRC::checkCRC(frame, M17_FN_LENGTH_BYTES + M17_PAYLOAD_LENGTH_BYTES + M17_CRC_LENGTH_BYTES);
if (valid) {
m_rfFN = (frame[0U] << 8) + (frame[1U] << 0);
} else {
// Create a silence frame
m_rfFN++;
// The new FN
frame[0U] = m_rfFN >> 8;
frame[1U] = m_rfFN >> 0;
// Add silent audio
unsigned char dataType = m_rfLICH.getDataType();
switch (dataType) {
case 2U:
::memcpy(frame + M17_FN_LENGTH_BYTES + 0U, M17_3200_SILENCE, 8U);
::memcpy(frame + M17_FN_LENGTH_BYTES + 8U, M17_3200_SILENCE, 8U);
break;
case 3U:
::memcpy(frame + M17_FN_LENGTH_BYTES + 0U, M17_1600_SILENCE, 8U);
break;
default:
break;
}
// Add the CRC
CM17CRC::encodeCRC(frame, M17_FN_LENGTH_BYTES + M17_PAYLOAD_LENGTH_BYTES + M17_CRC_LENGTH_BYTES);
}
unsigned char rfData[2U + M17_FRAME_LENGTH_BYTES];
rfData[0U] = TAG_DATA;
rfData[1U] = 0x00U;
// Generate the sync
CSync::addM17Sync(rfData + 2U);
unsigned char lich[M17_LICH_FRAGMENT_LENGTH_BYTES];
m_netLICH.getFragment(lich, m_rfFN);
unsigned int frag1, frag2, frag3, frag4;
CM17Utils::splitFragmentLICH(lich, frag1, frag2, frag3, frag4);
// Add Golay to the LICH fragment here
unsigned int lich1 = CGolay24128::encode24128(frag1);
unsigned int lich2 = CGolay24128::encode24128(frag2);
unsigned int lich3 = CGolay24128::encode24128(frag3);
unsigned int lich4 = CGolay24128::encode24128(frag4);
CM17Utils::combineFragmentLICHFEC(lich1, lich2, lich3, lich4, rfData + 2U + M17_SYNC_LENGTH_BYTES);
// Add the Convolution FEC
conv.encodeData(frame, rfData + 2U + M17_SYNC_LENGTH_BYTES + M17_LICH_FRAGMENT_FEC_LENGTH_BYTES);
// Calculate the BER
if (valid) {
unsigned int errors = 0U;
for (unsigned int i = 2U; i < (M17_FRAME_LENGTH_BYTES + 2U); i++)
errors += countBits(rfData[i] ^ data[i]);
LogDebug("M17, FN. %u, errs: %u/384 (%.1f%%)", m_rfFN, errors, float(errors) / 3.84F);
m_rfBits += M17_FRAME_LENGTH_BITS;
m_rfErrs += errors;
float ber = float(m_rfErrs) / float(m_rfBits);
m_display->writeM17BER(ber);
}
unsigned char temp[M17_FRAME_LENGTH_BYTES];
interleaver(rfData + 2U, temp);
decorrelator(rfData, data + 2U);
if (m_duplex)
writeQueueRF(rfData);
unsigned char netData[M17_LICH_LENGTH_BYTES + M17_FN_LENGTH_BYTES + M17_PAYLOAD_LENGTH_BYTES + M17_CRC_LENGTH_BYTES];
m_rfLICH.getNetwork(netData + 0U);
// Copy the FN and payload from the frame
::memcpy(netData + M17_LICH_LENGTH_BYTES - M17_CRC_LENGTH_BYTES, frame, M17_FN_LENGTH_BYTES + M17_PAYLOAD_LENGTH_BYTES);
// The CRC is added in the networking code
writeNetwork(netData);
m_rfFrames++;
// EOT?
if ((m_rfFN & 0x8000U) == 0x8000U) {
std::string source = m_rfLICH.getSource();
std::string dest = m_rfLICH.getDest();
if (m_rssi != 0U)
LogMessage("M17, received RF end of transmission from %s to %s, %.1f seconds, BER: %.1f%%, RSSI: -%u/-%u/-%u dBm", source.c_str(), dest.c_str(), float(m_rfFrames) / 25.0F, float(m_rfErrs * 100U) / float(m_rfBits), m_minRSSI, m_maxRSSI, m_aveRSSI / m_rssiCount);
else
LogMessage("M17, received RF end of transmission from %s to %s, %.1f seconds, BER: %.1f%%", source.c_str(), dest.c_str(), float(m_rfFrames) / 25.0F, float(m_rfErrs * 100U) / float(m_rfBits));
writeEndRF();
}
return true;
}
if (m_rfState == RS_RF_REJECTED) {
CM17Convolution conv;
unsigned char frame[M17_FN_LENGTH_BYTES + M17_PAYLOAD_LENGTH_BYTES + M17_CRC_LENGTH_BYTES];
conv.decodeData(data + 2U + M17_SYNC_LENGTH_BYTES + M17_LICH_FRAGMENT_FEC_LENGTH_BYTES, frame);
bool valid = CM17CRC::checkCRC(frame, M17_FN_LENGTH_BYTES + M17_PAYLOAD_LENGTH_BYTES + M17_CRC_LENGTH_BYTES);
if (valid) {
// Handle the EOT for rejected frames
unsigned int fn = (frame[0U] << 8) + (frame[1U] << 0);
if ((fn & 0x8000U) == 0x8000U)
writeEndRF();
}
return false;
}
return false;
}
unsigned int CM17Control::readModem(unsigned char* data)
{
assert(data != NULL);
if (m_queue.isEmpty())
return 0U;
unsigned char len = 0U;
m_queue.getData(&len, 1U);
m_queue.getData(data, len);
return len;
}
void CM17Control::writeEndRF()
{
m_rfState = RS_RF_LISTENING;
m_rfTimeoutTimer.stop();
if (m_netState == RS_NET_IDLE) {
m_display->clearM17();
if (m_network != NULL)
m_network->reset();
}
#if defined(DUMP_M17)
closeFile();
#endif
}
void CM17Control::writeEndNet()
{
m_netState = RS_NET_IDLE;
m_netTimeoutTimer.stop();
m_networkWatchdog.stop();
m_packetTimer.stop();
m_display->clearM17();
if (m_network != NULL)
m_network->reset();
}
void CM17Control::writeNetwork()
{
unsigned char netData[100U];
bool exists = m_network->read(netData);
if (!exists)
return;
if (!m_enabled)
return;
if (m_rfState != RS_RF_LISTENING && m_netState == RS_NET_IDLE)
return;
m_networkWatchdog.start();
m_netLICH.setNetwork(netData);
if (!m_allowEncryption) {
bool ret = m_rfLICH.isNONCENull();
if (!ret)
return;
}
if (m_netState == RS_NET_IDLE) {
std::string source = m_netLICH.getSource();
std::string dest = m_netLICH.getDest();
unsigned char dataType = m_netLICH.getDataType();
switch (dataType) {
case 1U:
LogMessage("M17, received network data transmission from %s to %s", source.c_str(), dest.c_str());
m_netState = RS_NET_DATA;
break;
case 2U:
LogMessage("M17, received network voice transmission from %s to %s", source.c_str(), dest.c_str());
m_netState = RS_NET_AUDIO;
break;
case 3U:
LogMessage("M17, received network voice + data transmission from %s to %s", source.c_str(), dest.c_str());
m_netState = RS_NET_AUDIO;
break;
default:
LogMessage("M17, received network unknown transmission from %s to %s", source.c_str(), dest.c_str());
m_netState = RS_NET_DATA;
break;
}
m_display->writeM17(source.c_str(), dest.c_str(), "N");
m_netTimeoutTimer.start();
m_packetTimer.start();
m_elapsed.start();
m_netFrames = 0U;
// Create a dummy start message
unsigned char start[M17_FRAME_LENGTH_BYTES + 2U];
start[0U] = TAG_DATA;
start[1U] = 0x00U;
// Generate the sync
CSync::addM17Sync(start + 2U);
unsigned char setup[M17_LICH_LENGTH_BYTES];
m_netLICH.getLinkSetup(setup);
// Add the convolution FEC
CM17Convolution conv;
conv.encodeLinkSetup(setup, start + 2U + M17_SYNC_LENGTH_BYTES);
unsigned char temp[M17_FRAME_LENGTH_BYTES];
interleaver(start + 2U, temp);
decorrelator(temp, start + 2U);
writeQueueNet(start);
}
unsigned char data[M17_FRAME_LENGTH_BYTES + 2U];
data[0U] = TAG_DATA;
data[1U] = 0x00U;
// Generate the sync
CSync::addM17Sync(data + 2U);
m_netFrames++;
// Add the fragment LICH
uint16_t fn = (netData[28U] << 8) + (netData[29U] << 0);
unsigned char lich[M17_LICH_FRAGMENT_LENGTH_BYTES];
m_netLICH.getFragment(lich, fn);
unsigned int frag1, frag2, frag3, frag4;
CM17Utils::splitFragmentLICH(lich, frag1, frag2, frag3, frag4);
// Add Golay to the LICH fragment here
unsigned int lich1 = CGolay24128::encode24128(frag1);
unsigned int lich2 = CGolay24128::encode24128(frag2);
unsigned int lich3 = CGolay24128::encode24128(frag3);
unsigned int lich4 = CGolay24128::encode24128(frag4);
CM17Utils::combineFragmentLICHFEC(lich1, lich2, lich3, lich4, data + 2U + M17_SYNC_LENGTH_BYTES);
// Add the FN and the data/audio
unsigned char payload[M17_FN_LENGTH_BYTES + M17_PAYLOAD_LENGTH_BYTES + M17_CRC_LENGTH_BYTES];
::memcpy(payload, netData + 28U, M17_FN_LENGTH_BYTES + M17_PAYLOAD_LENGTH_BYTES);
// Add the CRC
CM17CRC::encodeCRC(payload, M17_FN_LENGTH_BYTES + M17_PAYLOAD_LENGTH_BYTES + M17_CRC_LENGTH_BYTES);
// Add the Convolution FEC
CM17Convolution conv;
conv.encodeData(payload, data + 2U + M17_SYNC_LENGTH_BYTES + M17_LICH_FRAGMENT_FEC_LENGTH_BYTES);
unsigned char temp[M17_FRAME_LENGTH_BYTES];
interleaver(data + 2U, temp);
decorrelator(temp, data + 2U);
writeQueueNet(data);
// EOT handling
if ((fn & 0x8000U) == 0x8000U) {
std::string source = m_netLICH.getSource();
std::string dest = m_netLICH.getDest();
LogMessage("M17, received network end of transmission from %s to %s, %.1f seconds", source.c_str(), dest.c_str(), float(m_netFrames) / 25.0F);
writeEndNet();
}
}
void CM17Control::clock(unsigned int ms)
{
if (m_network != NULL)
writeNetwork();
m_rfTimeoutTimer.clock(ms);
m_netTimeoutTimer.clock(ms);
if (m_netState == RS_NET_AUDIO) {
m_networkWatchdog.clock(ms);
if (m_networkWatchdog.hasExpired()) {
LogMessage("M17, network watchdog has expired, %.1f seconds", float(m_netFrames) / 25.0F);
writeEndNet();
}
}
}
void CM17Control::writeQueueRF(const unsigned char *data)
{
assert(data != NULL);
if (m_netState != RS_NET_IDLE)
return;
if (m_rfTimeoutTimer.isRunning() && m_rfTimeoutTimer.hasExpired())
return;
unsigned char len = M17_FRAME_LENGTH_BYTES + 2U;
unsigned int space = m_queue.freeSpace();
if (space < (len + 1U)) {
LogError("M17, overflow in the M17 RF queue");
return;
}
m_queue.addData(&len, 1U);
m_queue.addData(data, len);
}
void CM17Control::writeQueueNet(const unsigned char *data)
{
assert(data != NULL);
if (m_netTimeoutTimer.isRunning() && m_netTimeoutTimer.hasExpired())
return;
unsigned char len = M17_FRAME_LENGTH_BYTES + 2U;
unsigned int space = m_queue.freeSpace();
if (space < (len + 1U)) {
LogError("M17, overflow in the M17 RF queue");
return;
}
m_queue.addData(&len, 1U);
m_queue.addData(data, len);
}
void CM17Control::writeNetwork(const unsigned char *data)
{
assert(data != NULL);
if (m_network == NULL)
return;
if (m_rfTimeoutTimer.isRunning() && m_rfTimeoutTimer.hasExpired())
return;
m_network->write(data);
}
void CM17Control::interleaver(const unsigned char* in, unsigned char* out) const
{
assert(in != NULL);
assert(out != NULL);
for (unsigned int i = 0U; i < (M17_FRAME_LENGTH_BITS - M17_SYNC_LENGTH_BITS); i++) {
unsigned int n1 = i + M17_SYNC_LENGTH_BITS;
bool b = READ_BIT(in, n1) != 0U;
unsigned int n2 = INTERLEAVER[i] + M17_SYNC_LENGTH_BITS;
WRITE_BIT(out, n2, b);
}
}
void CM17Control::decorrelator(const unsigned char* in, unsigned char* out) const
{
assert(in != NULL);
assert(out != NULL);
for (unsigned int i = M17_SYNC_LENGTH_BYTES; i < M17_FRAME_LENGTH_BYTES; i++) {
out[i] = in[i] ^ SCRAMBLER[i];
}
}
bool CM17Control::checkCallsign(const std::string& callsign) const
{
size_t len = m_callsign.size();
return m_callsign.compare(0U, len, callsign, 0U, len) == 0;
}
bool CM17Control::openFile()
{
if (m_fp != NULL)
return true;
time_t t;
::time(&t);
struct tm* tm = ::localtime(&t);
char name[100U];
::sprintf(name, "M17_%04d%02d%02d_%02d%02d%02d.ambe", tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec);
m_fp = ::fopen(name, "wb");
if (m_fp == NULL)
return false;
::fwrite("M17", 1U, 3U, m_fp);
return true;
}
bool CM17Control::writeFile(const unsigned char* data)
{
if (m_fp == NULL)
return false;
::fwrite(data, 1U, M17_FRAME_LENGTH_BYTES, m_fp);
return true;
}
void CM17Control::closeFile()
{
if (m_fp != NULL) {
::fclose(m_fp);
m_fp = NULL;
}
}
bool CM17Control::isBusy() const
{
return m_rfState != RS_RF_LISTENING || m_netState != RS_NET_IDLE;
}
void CM17Control::enable(bool enabled)
{
if (!enabled && m_enabled) {
m_queue.clear();
// Reset the RF section
m_rfState = RS_RF_LISTENING;
m_rfTimeoutTimer.stop();
// Reset the networking section
m_netState = RS_NET_IDLE;
m_netTimeoutTimer.stop();
m_networkWatchdog.stop();
m_packetTimer.stop();
}
m_enabled = enabled;
}
unsigned int CM17Control::countBits(unsigned char byte)
{
unsigned int count = 0U;
const unsigned char* p = &byte;
for (unsigned int i = 0U; i < 8U; i++) {
if (READ_BIT(p, i) != 0U)
count++;
}
return count;
}

View file

@ -1,101 +0,0 @@
/*
* Copyright (C) 2015-2020 by Jonathan Naylor G4KLX
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* 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(M17Control_H)
#define M17Control_H
#include "RSSIInterpolator.h"
#include "M17Network.h"
#include "M17Defines.h"
#include "RingBuffer.h"
#include "StopWatch.h"
#include "M17LICH.h"
#include "Display.h"
#include "Defines.h"
#include "Timer.h"
#include "Modem.h"
#include <string>
class CM17Control {
public:
CM17Control(const std::string& callsign, bool selfOnly, bool allowEncryption, CM17Network* network, CDisplay* display, unsigned int timeout, bool duplex, CRSSIInterpolator* rssiMapper);
~CM17Control();
bool writeModem(unsigned char* data, unsigned int len);
unsigned int readModem(unsigned char* data);
void clock(unsigned int ms);
bool isBusy() const;
void enable(bool enabled);
private:
std::string m_callsign;
bool m_selfOnly;
bool m_allowEncryption;
CM17Network* m_network;
CDisplay* m_display;
bool m_duplex;
CRingBuffer<unsigned char> m_queue;
RPT_RF_STATE m_rfState;
RPT_NET_STATE m_netState;
CTimer m_rfTimeoutTimer;
CTimer m_netTimeoutTimer;
CTimer m_packetTimer;
CTimer m_networkWatchdog;
CStopWatch m_elapsed;
unsigned int m_rfFrames;
unsigned int m_netFrames;
unsigned int m_rfFN;
unsigned int m_rfErrs;
unsigned int m_rfBits;
CM17LICH m_rfLICH;
CM17LICH m_netLICH;
CRSSIInterpolator* m_rssiMapper;
unsigned char m_rssi;
unsigned char m_maxRSSI;
unsigned char m_minRSSI;
unsigned int m_aveRSSI;
unsigned int m_rssiCount;
bool m_enabled;
FILE* m_fp;
void writeQueueRF(const unsigned char* data);
void writeQueueNet(const unsigned char* data);
void writeNetwork(const unsigned char* data);
void writeNetwork();
void interleaver(const unsigned char* in, unsigned char* out) const;
void decorrelator(const unsigned char* in, unsigned char* out) const;
bool checkCallsign(const std::string& source) const;
unsigned int countBits(unsigned char byte);
void writeEndRF();
void writeEndNet();
bool openFile();
bool writeFile(const unsigned char* data);
void closeFile();
};
#endif

View file

@ -1,275 +0,0 @@
/*
* Copyright (C) 2009-2016,2018,2020 by Jonathan Naylor G4KLX
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "M17Convolution.h"
#include <cstdio>
#include <cassert>
#include <cstring>
#include <cstdlib>
const unsigned int PUNCTURE_LIST_LINK_SETUP[] = {
3U, 6U, 9U, 12U, 19U, 22U, 25U, 28U, 35U, 38U, 41U, 44U, 51U, 54U, 57U, 64U, 67U, 70U, 73U, 80U, 83U, 86U, 89U, 96U, 99U, 102U,
105U, 112U, 115U, 118U, 125U, 128U, 131U, 134U, 141U, 144U, 147U, 150U, 157U, 160U, 163U, 166U, 173U, 176U, 179U, 186U, 189U,
192U, 195U, 202U, 205U, 208U, 211U, 218U, 221U, 224U, 227U, 234U, 237U, 240U, 247U, 250U, 253U, 256U, 263U, 266U, 269U, 272U,
279U, 282U, 285U, 288U, 295U, 298U, 301U, 308U, 311U, 314U, 317U, 324U, 327U, 330U, 333U, 340U, 343U, 346U, 349U, 356U, 359U,
362U, 369U, 372U, 375U, 378U, 385U, 388U, 391U, 394U, 401U, 404U, 407U, 410U, 417U, 420U, 423U, 430U, 433U, 436U, 439U, 446U,
449U, 452U, 455U, 462U, 465U, 468U, 471U, 478U, 481U, 484U};
const unsigned int PUNCTURE_LIST_DATA[] = {
5U, 11U, 17U, 20U, 23U, 29U, 35U, 46U, 52U, 58U, 61U, 64U, 70U, 76U, 87U, 93U, 99U, 102U, 105U, 111U, 117U, 128U, 134U, 140U,
143U, 146U, 152U, 158U, 169U, 175U, 181U, 184U, 187U, 193U, 199U, 210U, 216U, 222U, 225U, 228U, 234U, 240U, 251U, 257U, 263U,
266U, 269U, 275U, 281U, 292U, 298U, 304U, 307U, 310U, 316U, 322U};
const unsigned char BIT_MASK_TABLE[] = {0x80U, 0x40U, 0x20U, 0x10U, 0x08U, 0x04U, 0x02U, 0x01U};
#define WRITE_BIT1(p,i,b) p[(i)>>3] = (b) ? (p[(i)>>3] | BIT_MASK_TABLE[(i)&7]) : (p[(i)>>3] & ~BIT_MASK_TABLE[(i)&7])
#define READ_BIT1(p,i) (p[(i)>>3] & BIT_MASK_TABLE[(i)&7])
const uint8_t BRANCH_TABLE1[] = {0U, 0U, 0U, 0U, 2U, 2U, 2U, 2U};
const uint8_t BRANCH_TABLE2[] = {0U, 2U, 2U, 0U, 0U, 2U, 2U, 0U};
const unsigned int NUM_OF_STATES_D2 = 8U;
const unsigned int NUM_OF_STATES = 16U;
const uint32_t M = 4U;
const unsigned int K = 5U;
CM17Convolution::CM17Convolution() :
m_metrics1(NULL),
m_metrics2(NULL),
m_oldMetrics(NULL),
m_newMetrics(NULL),
m_decisions(NULL),
m_dp(NULL)
{
m_metrics1 = new uint16_t[16U];
m_metrics2 = new uint16_t[16U];
m_decisions = new uint64_t[300U];
}
CM17Convolution::~CM17Convolution()
{
delete[] m_metrics1;
delete[] m_metrics2;
delete[] m_decisions;
}
void CM17Convolution::encodeLinkSetup(const unsigned char* in, unsigned char* out) const
{
assert(in != NULL);
assert(out != NULL);
unsigned char temp1[31U];
::memset(temp1, 0x00U, 31U);
::memcpy(temp1, in, 30U);
unsigned char temp2[61U];
encode(temp1, temp2, 244U);
unsigned int n = 0U;
unsigned int index = 0U;
for (unsigned int i = 0U; i < 488U; i++) {
if (i != PUNCTURE_LIST_LINK_SETUP[index]) {
bool b = READ_BIT1(temp2, i);
WRITE_BIT1(out, n, b);
n++;
} else {
index++;
}
}
}
void CM17Convolution::encodeData(const unsigned char* in, unsigned char* out) const
{
assert(in != NULL);
assert(out != NULL);
unsigned char temp1[21U];
::memset(temp1, 0x00U, 21U);
::memcpy(temp1, in, 20U);
unsigned char temp2[41U];
encode(temp1, temp2, 164U);
unsigned int n = 0U;
unsigned int index = 0U;
for (unsigned int i = 0U; i < 328U; i++) {
if (i != PUNCTURE_LIST_DATA[index]) {
bool b = READ_BIT1(temp2, i);
WRITE_BIT1(out, n, b);
n++;
} else {
index++;
}
}
}
void CM17Convolution::decodeLinkSetup(const unsigned char* in, unsigned char* out)
{
assert(in != NULL);
assert(out != NULL);
uint8_t temp[500U];
unsigned int n = 0U;
unsigned int index = 0U;
for (unsigned int i = 0U; i < 368U; i++) {
if (n == PUNCTURE_LIST_LINK_SETUP[index]) {
temp[n++] = 1U;
index++;
}
bool b = READ_BIT1(in, i);
temp[n++] = b ? 2U : 0U;
}
for (unsigned int i = 0U; i < 8U; i++)
temp[n++] = 0U;
start();
n = 0U;
for (unsigned int i = 0U; i < 244U; i++) {
uint8_t s0 = temp[n++];
uint8_t s1 = temp[n++];
decode(s0, s1);
}
chainback(out, 240U);
}
void CM17Convolution::decodeData(const unsigned char* in, unsigned char* out)
{
assert(in != NULL);
assert(out != NULL);
uint8_t temp[350U];
unsigned int n = 0U;
unsigned int index = 0U;
for (unsigned int i = 0U; i < 272U; i++) {
if (n == PUNCTURE_LIST_DATA[index]) {
temp[n++] = 1U;
index++;
}
bool b = READ_BIT1(in, i);
temp[n++] = b ? 2U : 0U;
}
for (unsigned int i = 0U; i < 8U; i++)
temp[n++] = 0U;
start();
n = 0U;
for (unsigned int i = 0U; i < 164U; i++) {
uint8_t s0 = temp[n++];
uint8_t s1 = temp[n++];
decode(s0, s1);
}
chainback(out, 160U);
}
void CM17Convolution::start()
{
::memset(m_metrics1, 0x00U, NUM_OF_STATES * sizeof(uint16_t));
::memset(m_metrics2, 0x00U, NUM_OF_STATES * sizeof(uint16_t));
m_oldMetrics = m_metrics1;
m_newMetrics = m_metrics2;
m_dp = m_decisions;
}
void CM17Convolution::decode(uint8_t s0, uint8_t s1)
{
*m_dp = 0U;
for (uint8_t i = 0U; i < NUM_OF_STATES_D2; i++) {
uint8_t j = i * 2U;
uint16_t metric = std::abs(BRANCH_TABLE1[i] - s0) + std::abs(BRANCH_TABLE2[i] - s1);
uint16_t m0 = m_oldMetrics[i] + metric;
uint16_t m1 = m_oldMetrics[i + NUM_OF_STATES_D2] + (M - metric);
uint8_t decision0 = (m0 >= m1) ? 1U : 0U;
m_newMetrics[j + 0U] = decision0 != 0U ? m1 : m0;
m0 = m_oldMetrics[i] + (M - metric);
m1 = m_oldMetrics[i + NUM_OF_STATES_D2] + metric;
uint8_t decision1 = (m0 >= m1) ? 1U : 0U;
m_newMetrics[j + 1U] = decision1 != 0U ? m1 : m0;
*m_dp |= (uint64_t(decision1) << (j + 1U)) | (uint64_t(decision0) << (j + 0U));
}
++m_dp;
assert((m_dp - m_decisions) <= 300);
uint16_t* tmp = m_oldMetrics;
m_oldMetrics = m_newMetrics;
m_newMetrics = tmp;
}
void CM17Convolution::chainback(unsigned char* out, unsigned int nBits)
{
assert(out != NULL);
uint32_t state = 0U;
while (nBits-- > 0) {
--m_dp;
uint32_t i = state >> (9 - K);
uint8_t bit = uint8_t(*m_dp >> i) & 1;
state = (bit << 7) | (state >> 1);
WRITE_BIT1(out, nBits, bit != 0U);
}
}
void CM17Convolution::encode(const unsigned char* in, unsigned char* out, unsigned int nBits) const
{
assert(in != NULL);
assert(out != NULL);
assert(nBits > 0U);
uint8_t d1 = 0U, d2 = 0U, d3 = 0U, d4 = 0U;
uint32_t k = 0U;
for (unsigned int i = 0U; i < nBits; i++) {
uint8_t d = READ_BIT1(in, i) ? 1U : 0U;
uint8_t g1 = (d + d3 + d4) & 1;
uint8_t g2 = (d + d1 + d2 + d4) & 1;
d4 = d3;
d3 = d2;
d2 = d1;
d1 = d;
WRITE_BIT1(out, k, g1 != 0U);
k++;
WRITE_BIT1(out, k, g2 != 0U);
k++;
}
}

View file

@ -1,50 +0,0 @@
/*
* Copyright (C) 2015,2016,2018,2020 by Jonathan Naylor G4KLX
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#if !defined(M17Convolution_H)
#define M17Convolution_H
#include <cstdint>
class CM17Convolution {
public:
CM17Convolution();
~CM17Convolution();
void decodeLinkSetup(const unsigned char* in, unsigned char* out);
void decodeData(const unsigned char* in, unsigned char* out);
void encodeLinkSetup(const unsigned char* in, unsigned char* out) const;
void encodeData(const unsigned char* in, unsigned char* out) const;
private:
uint16_t* m_metrics1;
uint16_t* m_metrics2;
uint16_t* m_oldMetrics;
uint16_t* m_newMetrics;
uint64_t* m_decisions;
uint64_t* m_dp;
void start();
void decode(uint8_t s0, uint8_t s1);
void chainback(unsigned char* out, unsigned int nBits);
void encode(const unsigned char* in, unsigned char* out, unsigned int nBits) const;
};
#endif

View file

@ -1,56 +0,0 @@
/*
* Copyright (C) 2016,2017,2018,2020 by Jonathan Naylor G4KLX
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#if !defined(M17DEFINES_H)
#define M17DEFINES_H
const unsigned int M17_RADIO_SYMBOL_LENGTH = 5U; // At 24 kHz sample rate
const unsigned int M17_FRAME_LENGTH_BITS = 384U;
const unsigned int M17_FRAME_LENGTH_BYTES = M17_FRAME_LENGTH_BITS / 8U;
const unsigned char M17_SYNC_BYTES[] = {0x32U, 0x43U};
const unsigned int M17_SYNC_LENGTH_BITS = 16U;
const unsigned int M17_SYNC_LENGTH_BYTES = M17_SYNC_LENGTH_BITS / 8U;
const unsigned int M17_LICH_LENGTH_BITS = 240U;
const unsigned int M17_LICH_LENGTH_BYTES = M17_LICH_LENGTH_BITS / 8U;
const unsigned int M17_LICH_FRAGMENT_LENGTH_BITS = M17_LICH_LENGTH_BITS / 5U;
const unsigned int M17_LICH_FRAGMENT_LENGTH_BYTES = M17_LICH_FRAGMENT_LENGTH_BITS / 8U;
const unsigned int M17_LICH_FRAGMENT_FEC_LENGTH_BITS = M17_LICH_FRAGMENT_LENGTH_BITS * 2U;
const unsigned int M17_LICH_FRAGMENT_FEC_LENGTH_BYTES = M17_LICH_FRAGMENT_FEC_LENGTH_BITS / 8U;
const unsigned int M17_PAYLOAD_LENGTH_BITS = 128U;
const unsigned int M17_PAYLOAD_LENGTH_BYTES = M17_PAYLOAD_LENGTH_BITS / 8U;
const unsigned char M17_NULL_NONCE[] = {0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U};
const unsigned int M17_NONCE_LENGTH_BITS = 112U;
const unsigned int M17_NONCE_LENGTH_BYTES = M17_NONCE_LENGTH_BITS / 8U;
const unsigned int M17_FN_LENGTH_BITS = 16U;
const unsigned int M17_FN_LENGTH_BYTES = M17_FN_LENGTH_BITS / 8U;
const unsigned int M17_CRC_LENGTH_BITS = 16U;
const unsigned int M17_CRC_LENGTH_BYTES = M17_CRC_LENGTH_BITS / 8U;
const unsigned char M17_3200_SILENCE[] = {0x01U, 0x00U, 0x09U, 0x43U, 0x9CU, 0xE4U, 0x21U, 0x08U};
const unsigned char M17_1600_SILENCE[] = {0x01U, 0x00U, 0x04U, 0x00U, 0x25U, 0x75U, 0xDDU, 0xF2U};
#endif

View file

@ -1,147 +0,0 @@
/*
* Copyright (C) 2020 by Jonathan Naylor G4KLX
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "M17LICH.h"
#include "M17Utils.h"
#include "M17Defines.h"
#include "M17CRC.h"
#include <cassert>
#include <cstring>
CM17LICH::CM17LICH() :
m_lich(NULL),
m_valid(false)
{
m_lich = new unsigned char[M17_LICH_LENGTH_BYTES];
}
CM17LICH::~CM17LICH()
{
delete[] m_lich;
}
void CM17LICH::getNetwork(unsigned char* data) const
{
assert(data != NULL);
::memcpy(data, m_lich, M17_LICH_LENGTH_BYTES);
}
void CM17LICH::setNetwork(const unsigned char* data)
{
assert(data != NULL);
::memcpy(m_lich, data, M17_LICH_LENGTH_BYTES);
m_valid = true;
}
std::string CM17LICH::getSource() const
{
std::string callsign;
CM17Utils::decodeCallsign(m_lich + 6U, callsign);
return callsign;
}
void CM17LICH::setSource(const std::string& callsign)
{
CM17Utils::encodeCallsign(callsign, m_lich + 6U);
}
std::string CM17LICH::getDest() const
{
std::string callsign;
CM17Utils::decodeCallsign(m_lich + 0U, callsign);
return callsign;
}
void CM17LICH::setDest(const std::string& callsign)
{
CM17Utils::encodeCallsign(callsign, m_lich + 0U);
}
unsigned char CM17LICH::getDataType() const
{
return (m_lich[13U] >> 1) & 0x03U;
}
void CM17LICH::setDataType(unsigned char type)
{
m_lich[13U] &= 0xF9U;
m_lich[13U] |= (type << 1) & 0x06U;
}
bool CM17LICH::isNONCENull() const
{
return ::memcmp(m_lich + 14U, M17_NULL_NONCE, M17_NONCE_LENGTH_BYTES) == 0;
}
void CM17LICH::reset()
{
::memset(m_lich, 0x00U, 30U);
m_valid = false;
}
bool CM17LICH::isValid() const
{
return m_valid;
}
void CM17LICH::getLinkSetup(unsigned char* data) const
{
assert(data != NULL);
::memcpy(data, m_lich, M17_LICH_LENGTH_BYTES);
CM17CRC::encodeCRC(data, M17_LICH_LENGTH_BYTES);
}
void CM17LICH::setLinkSetup(const unsigned char* data)
{
assert(data != NULL);
::memcpy(m_lich, data, M17_LICH_LENGTH_BYTES);
m_valid = CM17CRC::checkCRC(m_lich, M17_LICH_LENGTH_BYTES);
}
void CM17LICH::getFragment(unsigned char* data, unsigned short fn) const
{
assert(data != NULL);
CM17CRC::encodeCRC(m_lich, M17_LICH_LENGTH_BYTES);
unsigned int n = (fn & 0x7FFFU) % 5U;
::memcpy(data, m_lich + (n * M17_LICH_FRAGMENT_LENGTH_BYTES), M17_LICH_FRAGMENT_LENGTH_BYTES);
}
void CM17LICH::setFragment(const unsigned char* data, unsigned short fn)
{
assert(data != NULL);
unsigned int n = (fn & 0x7FFFU) % 5U;
::memcpy(m_lich + (n * M17_LICH_FRAGMENT_LENGTH_BYTES), data, M17_LICH_FRAGMENT_LENGTH_BYTES);
m_valid = CM17CRC::checkCRC(m_lich, M17_LICH_LENGTH_BYTES);
}

View file

@ -1,57 +0,0 @@
/*
* Copyright (C) 2020 by Jonathan Naylor G4KLX
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#if !defined(M17LICH_H)
#define M17LICH_H
#include <string>
class CM17LICH {
public:
CM17LICH();
~CM17LICH();
void getNetwork(unsigned char* data) const;
void setNetwork(const unsigned char* data);
std::string getSource() const;
void setSource(const std::string& callsign);
std::string getDest() const;
void setDest(const std::string& callsign);
unsigned char getDataType() const;
void setDataType(unsigned char type);
bool isNONCENull() const;
void reset();
bool isValid() const;
void getLinkSetup(unsigned char* data) const;
void setLinkSetup(const unsigned char* data);
void getFragment(unsigned char* data, unsigned short fn) const;
void setFragment(const unsigned char* data, unsigned short fn);
private:
unsigned char* m_lich;
bool m_valid;
};
#endif

View file

@ -1,210 +0,0 @@
/*
* Copyright (C) 2009-2014,2016,2019,2020 by Jonathan Naylor G4KLX
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "M17Network.h"
#include "M17Defines.h"
#include "M17Utils.h"
#include "Defines.h"
#include "Utils.h"
#include "Log.h"
#include <cstdio>
#include <cassert>
#include <cstring>
const unsigned int BUFFER_LENGTH = 200U;
CM17Network::CM17Network(unsigned int localPort, const std::string& gwyAddress, unsigned int gwyPort, bool debug) :
m_socket(localPort),
m_addr(),
m_addrLen(0U),
m_debug(debug),
m_enabled(false),
m_outId(0U),
m_inId(0U),
m_buffer(1000U, "M17 Network"),
m_random(),
m_timer(1000U, 5U)
{
if (CUDPSocket::lookup(gwyAddress, gwyPort, m_addr, m_addrLen) != 0) {
m_addrLen = 0U;
return;
}
std::random_device rd;
std::mt19937 mt(rd());
m_random = mt;
}
CM17Network::~CM17Network()
{
}
bool CM17Network::open()
{
if (m_addrLen == 0U) {
LogError("M17, unable to resolve the gateway address");
return false;
}
LogMessage("Opening M17 network connection");
bool ret = m_socket.open(m_addr);
if (ret) {
m_timer.start();
return true;
} else {
return false;
}
}
bool CM17Network::write(const unsigned char* data)
{
if (m_addrLen != 0U)
return false;
assert(data != NULL);
unsigned char buffer[100U];
buffer[0U] = 'M';
buffer[1U] = '1';
buffer[2U] = '7';
buffer[3U] = ' ';
// Create a random id for this transmission if needed
if (m_outId == 0U) {
std::uniform_int_distribution<uint16_t> dist(0x0001, 0xFFFE);
m_outId = dist(m_random);
}
buffer[4U] = m_outId / 256U; // Unique session id
buffer[5U] = m_outId % 256U;
::memcpy(buffer + 6U, data, 46U);
// Dummy CRC
buffer[52U] = 0x00U;
buffer[53U] = 0x00U;
if (m_debug)
CUtils::dump(1U, "M17 data transmitted", buffer, 54U);
return m_socket.write(buffer, 54U, m_addr, m_addrLen);
}
void CM17Network::clock(unsigned int ms)
{
m_timer.clock(ms);
if (m_timer.isRunning() && m_timer.hasExpired()) {
sendPing();
m_timer.start();
}
unsigned char buffer[BUFFER_LENGTH];
sockaddr_storage address;
unsigned int addrLen;
int length = m_socket.read(buffer, BUFFER_LENGTH, address, addrLen);
if (length <= 0)
return;
if (!CUDPSocket::match(m_addr, address)) {
LogMessage("M17, packet received from an invalid source");
return;
}
if (m_debug)
CUtils::dump(1U, "M17 Network Data Received", buffer, length);
if (!m_enabled)
return;
if (::memcmp(buffer + 0U, "PING", 4U) == 0)
return;
if (::memcmp(buffer + 0U, "M17 ", 4U) != 0) {
CUtils::dump(2U, "M17, received unknown packet", buffer, length);
return;
}
uint16_t id = (buffer[4U] << 8) + (buffer[5U] << 0);
if (m_inId == 0U) {
m_inId = id;
} else {
if (id != m_inId)
return;
}
unsigned char c = length - 6U;
m_buffer.addData(&c, 1U);
m_buffer.addData(buffer + 6U, length - 6U);
}
bool CM17Network::read(unsigned char* data)
{
assert(data != NULL);
if (m_buffer.isEmpty())
return false;
unsigned char c = 0U;
m_buffer.getData(&c, 1U);
m_buffer.getData(data, c);
return true;
}
void CM17Network::close()
{
m_socket.close();
LogMessage("Closing M17 network connection");
}
void CM17Network::reset()
{
m_outId = 0U;
m_inId = 0U;
}
void CM17Network::enable(bool enabled)
{
if (!enabled && m_enabled)
m_buffer.clear();
m_enabled = enabled;
}
void CM17Network::sendPing()
{
unsigned char buffer[5U];
buffer[0U] = 'P';
buffer[1U] = 'I';
buffer[2U] = 'N';
buffer[3U] = 'G';
if (m_debug)
CUtils::dump(1U, "M17 data transmitted", buffer, 4U);
m_socket.write(buffer, 4U, m_addr, m_addrLen);
}

View file

@ -1,64 +0,0 @@
/*
* Copyright (C) 2009-2014,2016,2018,2020 by Jonathan Naylor G4KLX
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifndef M17Network_H
#define M17Network_H
#include "M17Defines.h"
#include "RingBuffer.h"
#include "UDPSocket.h"
#include "Timer.h"
#include <random>
#include <cstdint>
class CM17Network {
public:
CM17Network(unsigned int localPort, const std::string& gwyAddress, unsigned int gwyPort, bool debug);
~CM17Network();
bool open();
void enable(bool enabled);
bool write(const unsigned char* data);
bool read(unsigned char* data);
void reset();
void close();
void clock(unsigned int ms);
private:
CUDPSocket m_socket;
sockaddr_storage m_addr;
unsigned int m_addrLen;
bool m_debug;
bool m_enabled;
uint16_t m_outId;
uint16_t m_inId;
CRingBuffer<unsigned char> m_buffer;
std::mt19937 m_random;
CTimer m_timer;
void sendPing();
};
#endif

View file

@ -1,209 +0,0 @@
/*
* Copyright (C) 2020 by Jonathan Naylor G4KLX
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "M17Utils.h"
#include "M17Defines.h"
#include <cassert>
const std::string M17_CHARS = " ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-/.";
const unsigned char BIT_MASK_TABLE[] = { 0x80U, 0x40U, 0x20U, 0x10U, 0x08U, 0x04U, 0x02U, 0x01U };
#define WRITE_BIT1(p,i,b) p[(i)>>3] = (b) ? (p[(i)>>3] | BIT_MASK_TABLE[(i)&7]) : (p[(i)>>3] & ~BIT_MASK_TABLE[(i)&7])
#define READ_BIT1(p,i) (p[(i)>>3] & BIT_MASK_TABLE[(i)&7])
void CM17Utils::encodeCallsign(const std::string& callsign, unsigned char* encoded)
{
assert(encoded != NULL);
unsigned int len = callsign.size();
if (len > 9U)
len = 9U;
uint64_t enc = 0ULL;
for (int i = len - 1; i >= 0; i--) {
size_t pos = M17_CHARS.find(callsign[i]);
if (pos == std::string::npos)
pos = 0ULL;
enc *= 40ULL;
enc += pos;
}
encoded[0U] = (enc >> 40) & 0xFFU;
encoded[1U] = (enc >> 32) & 0xFFU;
encoded[2U] = (enc >> 24) & 0xFFU;
encoded[3U] = (enc >> 16) & 0xFFU;
encoded[4U] = (enc >> 8) & 0xFFU;
encoded[5U] = (enc >> 0) & 0xFFU;
}
void CM17Utils::decodeCallsign(const unsigned char* encoded, std::string& callsign)
{
assert(encoded != NULL);
callsign.clear();
uint64_t enc = (uint64_t(encoded[0U]) << 40) +
(uint64_t(encoded[1U]) << 32) +
(uint64_t(encoded[2U]) << 24) +
(uint64_t(encoded[3U]) << 16) +
(uint64_t(encoded[4U]) << 8) +
(uint64_t(encoded[5U]) << 0);
if (enc >= 262144000000000ULL) // 40^9
return;
while (enc > 0ULL) {
callsign += " ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-/."[enc % 40ULL];
enc /= 40ULL;
}
}
void CM17Utils::splitFragmentLICH(const unsigned char* data, unsigned int& frag1, unsigned int& frag2, unsigned int& frag3, unsigned int& frag4)
{
assert(data != NULL);
frag1 = frag2 = frag3 = frag4 = 0x00U;
unsigned int offset = 0U;
unsigned int MASK = 0x800U;
for (unsigned int i = 0U; i < (M17_LICH_FRAGMENT_LENGTH_BITS / 4U); i++, offset++, MASK >>= 1) {
bool b = READ_BIT1(data, offset) != 0x00U;
if (b)
frag1 |= MASK;
}
MASK = 0x800U;
for (unsigned int i = 0U; i < (M17_LICH_FRAGMENT_LENGTH_BITS / 4U); i++, offset++, MASK >>= 1) {
bool b = READ_BIT1(data, offset) != 0x00U;
if (b)
frag2 |= MASK;
}
MASK = 0x800U;
for (unsigned int i = 0U; i < (M17_LICH_FRAGMENT_LENGTH_BITS / 4U); i++, offset++, MASK >>= 1) {
bool b = READ_BIT1(data, offset) != 0x00U;
if (b)
frag3 |= MASK;
}
MASK = 0x800U;
for (unsigned int i = 0U; i < (M17_LICH_FRAGMENT_LENGTH_BITS / 4U); i++, offset++, MASK >>= 1) {
bool b = READ_BIT1(data, offset) != 0x00U;
if (b)
frag4 |= MASK;
}
}
void CM17Utils::splitFragmentLICHFEC(const unsigned char* data, unsigned int& frag1, unsigned int& frag2, unsigned int& frag3, unsigned int& frag4)
{
assert(data != NULL);
frag1 = frag2 = frag3 = frag4 = 0x00U;
unsigned int offset = 0U;
unsigned int MASK = 0x800000U;
for (unsigned int i = 0U; i < (M17_LICH_FRAGMENT_FEC_LENGTH_BITS / 4U); i++, offset++, MASK >>= 1) {
bool b = READ_BIT1(data, offset) != 0x00U;
if (b)
frag1 |= MASK;
}
MASK = 0x800000U;
for (unsigned int i = 0U; i < (M17_LICH_FRAGMENT_FEC_LENGTH_BITS / 4U); i++, offset++, MASK >>= 1) {
bool b = READ_BIT1(data, offset) != 0x00U;
if (b)
frag2 |= MASK;
}
MASK = 0x800000U;
for (unsigned int i = 0U; i < (M17_LICH_FRAGMENT_FEC_LENGTH_BITS / 4U); i++, offset++, MASK >>= 1) {
bool b = READ_BIT1(data, offset) != 0x00U;
if (b)
frag3 |= MASK;
}
MASK = 0x800000U;
for (unsigned int i = 0U; i < (M17_LICH_FRAGMENT_FEC_LENGTH_BITS / 4U); i++, offset++, MASK >>= 1) {
bool b = READ_BIT1(data, offset) != 0x00U;
if (b)
frag4 |= MASK;
}
}
void CM17Utils::combineFragmentLICH(unsigned int frag1, unsigned int frag2, unsigned int frag3, unsigned int frag4, unsigned char* data)
{
assert(data != NULL);
unsigned int offset = 0U;
unsigned int MASK = 0x800U;
for (unsigned int i = 0U; i < (M17_LICH_FRAGMENT_LENGTH_BITS / 4U); i++, offset++, MASK >>= 1) {
bool b = (frag1 & MASK) == MASK;
WRITE_BIT1(data, offset, b);
}
MASK = 0x800U;
for (unsigned int i = 0U; i < (M17_LICH_FRAGMENT_LENGTH_BITS / 4U); i++, offset++, MASK >>= 1) {
bool b = (frag2 & MASK) == MASK;
WRITE_BIT1(data, offset, b);
}
MASK = 0x800U;
for (unsigned int i = 0U; i < (M17_LICH_FRAGMENT_LENGTH_BITS / 4U); i++, offset++, MASK >>= 1) {
bool b = (frag3 & MASK) == MASK;
WRITE_BIT1(data, offset, b);
}
MASK = 0x800U;
for (unsigned int i = 0U; i < (M17_LICH_FRAGMENT_LENGTH_BITS / 4U); i++, offset++, MASK >>= 1) {
bool b = (frag4 & MASK) == MASK;
WRITE_BIT1(data, offset, b);
}
}
void CM17Utils::combineFragmentLICHFEC(unsigned int frag1, unsigned int frag2, unsigned int frag3, unsigned int frag4, unsigned char* data)
{
assert(data != NULL);
unsigned int offset = 0U;
unsigned int MASK = 0x800000U;
for (unsigned int i = 0U; i < (M17_LICH_FRAGMENT_FEC_LENGTH_BITS / 4U); i++, offset++, MASK >>= 1) {
bool b = (frag1 & MASK) == MASK;
WRITE_BIT1(data, offset, b);
}
MASK = 0x800000U;
for (unsigned int i = 0U; i < (M17_LICH_FRAGMENT_FEC_LENGTH_BITS / 4U); i++, offset++, MASK >>= 1) {
bool b = (frag2 & MASK) == MASK;
WRITE_BIT1(data, offset, b);
}
MASK = 0x800000U;
for (unsigned int i = 0U; i < (M17_LICH_FRAGMENT_FEC_LENGTH_BITS / 4U); i++, offset++, MASK >>= 1) {
bool b = (frag3 & MASK) == MASK;
WRITE_BIT1(data, offset, b);
}
MASK = 0x800000U;
for (unsigned int i = 0U; i < (M17_LICH_FRAGMENT_FEC_LENGTH_BITS / 4U); i++, offset++, MASK >>= 1) {
bool b = (frag4 & MASK) == MASK;
WRITE_BIT1(data, offset, b);
}
}

View file

@ -1,41 +0,0 @@
/*
* Copyright (C) 2020 by Jonathan Naylor G4KLX
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#if !defined(M17Utils_H)
#define M17Utils_H
#include <string>
class CM17Utils {
public:
CM17Utils();
~CM17Utils();
static void encodeCallsign(const std::string& callsign, unsigned char* encoded);
static void decodeCallsign(const unsigned char* encoded, std::string& callsign);
static void splitFragmentLICH(const unsigned char* data, unsigned int& frag1, unsigned int& frag2, unsigned int& frag3, unsigned int& frag4);
static void splitFragmentLICHFEC(const unsigned char* data, unsigned int& frag1, unsigned int& frag2, unsigned int& frag3, unsigned int& frag4);
static void combineFragmentLICH(unsigned int frag1, unsigned int frag2, unsigned int frag3, unsigned int frag4, unsigned char* data);
static void combineFragmentLICHFEC(unsigned int frag1, unsigned int frag2, unsigned int frag3, unsigned int frag4, unsigned char* data);
private:
};
#endif

191
MMDVM.ini
View file

@ -1,6 +1,6 @@
[General] [General]
Callsign=G9BF Callsign=MUTRPT
Id=123456 Id=1337
Timeout=180 Timeout=180
Duplex=1 Duplex=1
# ModeHang=10 # ModeHang=10
@ -31,16 +31,23 @@ Time=10
File=DMRIds.dat File=DMRIds.dat
Time=24 Time=24
[NXDN Id Lookup]
File=NXDN.csv
Time=24
[Modem] [Modem]
# Port=/dev/ttyACM0 # Valid values are "null", "uart", "udp", and (on Linux) "i2c"
# Port=/dev/ttyAMA0
Port=\\.\COM4
Protocol=uart Protocol=uart
# Address=0x22 # The port and speed used for a UART connection
# UARTPort=\\.\COM4
# UARTPort=/dev/ttyACM0
UARTPort=/dev/ttyAMA0
UARTSpeed=460800
# The port and address for an I2C connection
I2CPort=/dev/i2c
I2CAddress=0x22
# IP parameters for UDP connection
ModemAddress=192.168.2.100
ModemPort=3334
LocalAddress=192.168.2.1
LocalPort=3335
TXInvert=1 TXInvert=1
RXInvert=0 RXInvert=0
PTTInvert=0 PTTInvert=0
@ -53,15 +60,7 @@ TXLevel=50
RXDCOffset=0 RXDCOffset=0
TXDCOffset=0 TXDCOffset=0
RFLevel=100 RFLevel=100
# CWIdTXLevel=50 DMRTXLevel=50
# D-StarTXLevel=50
# DMRTXLevel=50
# YSFTXLevel=50
# P25TXLevel=50
# NXDNTXLevel=50
# M17TXLevel-50
# POCSAGTXLevel=50
# FMTXLevel=50
RSSIMappingFile=RSSI.dat RSSIMappingFile=RSSI.dat
UseCOSAsLockout=0 UseCOSAsLockout=0
Trace=0 Trace=0
@ -74,29 +73,12 @@ RemotePort=40094
LocalPort=40095 LocalPort=40095
# SendFrameType=0 # SendFrameType=0
[UMP]
Enable=0
# Port=\\.\COM4
Port=/dev/ttyACM1
[D-Star]
Enable=1
Module=C
SelfOnly=0
AckReply=1
AckTime=750
AckMessage=0
ErrorReply=1
RemoteGateway=0
# ModeHang=10
WhiteList=
[DMR] [DMR]
Enable=1 Enable=1
Beacons=0 Beacons=0
BeaconInterval=60 BeaconInterval=60
BeaconDuration=3 BeaconDuration=3
ColorCode=1 ColorCode=7
SelfOnly=0 SelfOnly=0
EmbeddedLCOnly=0 EmbeddedLCOnly=0
DumpTAData=1 DumpTAData=1
@ -106,138 +88,23 @@ DumpTAData=1
CallHang=3 CallHang=3
TXHang=4 TXHang=4
# ModeHang=10 # ModeHang=10
# OVCM Values, 0=off, 1=rx_on, 2=tx_on, 3=both_on # OVCM Values, 0=off, 1=rx_on, 2=tx_on, 3=both_on, 4=force off
# OVCM=0 # OVCM=0
[System Fusion]
Enable=1
LowDeviation=0
SelfOnly=0
TXHang=4
RemoteGateway=0
# ModeHang=10
[P25]
Enable=1
NAC=293
SelfOnly=0
OverrideUIDCheck=0
RemoteGateway=0
TXHang=5
# ModeHang=10
[NXDN]
Enable=1
RAN=1
SelfOnly=0
RemoteGateway=0
TXHang=5
# ModeHang=10
[M17]
Enable=1
SelfOnly=0
TXHang=5
# ModeHang=10
[POCSAG]
Enable=1
Frequency=439987500
[FM]
Enable=1
# Callsign=G4KLX
CallsignSpeed=20
CallsignFrequency=1000
CallsignTime=10
CallsignHoldoff=0
CallsignHighLevel=50
CallsignLowLevel=20
CallsignAtStart=1
CallsignAtEnd=1
CallsignAtLatch=0
RFAck=K
ExtAck=N
AckSpeed=20
AckFrequency=1750
AckMinTime=4
AckDelay=1000
AckLevel=50
# Timeout=180
TimeoutLevel=80
CTCSSFrequency=88.4
CTCSSThreshold=30
# CTCSSHighThreshold=30
# CTCSSLowThreshold=20
CTCSSLevel=20
KerchunkTime=0
HangTime=7
AccessMode=1
COSInvert=0
RFAudioBoost=1
MaxDevLevel=90
ExtAudioBoost=1
[D-Star Network]
Enable=1
GatewayAddress=127.0.0.1
GatewayPort=20010
LocalPort=20011
# ModeHang=3
Debug=0
[DMR Network] [DMR Network]
Enable=1 Enable=1
Address=127.0.0.1 # Type may be either 'Direct' or 'Gateway'. When Direct you must provide the Master's
Port=62031 # address as well as the Password, and for DMR+, Options also.
Local=62032 Type=Direct
LocalAddress=127.0.0.1
LocalPort=62032
RemoteAddress=127.0.0.1
RemotePort=62031
# Password=P@ssw0rd1234
Jitter=360 Jitter=360
Slot1=1 Slot1=1
Slot2=1 Slot2=1
# ModeHang=3 # Options=
Debug=0
[System Fusion Network]
Enable=1
LocalAddress=127.0.0.1
LocalPort=3200
GatewayAddress=127.0.0.1
GatewayPort=4200
# ModeHang=3
Debug=0
[P25 Network]
Enable=1
GatewayAddress=127.0.0.1
GatewayPort=42020
LocalPort=32010
# ModeHang=3
Debug=0
[NXDN Network]
Enable=1
Protocol=Icom
LocalAddress=127.0.0.1
LocalPort=14021
GatewayAddress=127.0.0.1
GatewayPort=14020
# ModeHang=3
Debug=0
[M17 Network]
Enable=1
GatewayAddress=127.0.0.1
GatewayPort=17010
LocalPort=17011
# ModeHang=3
Debug=0
[POCSAG Network]
Enable=1
LocalAddress=127.0.0.1
LocalPort=3800
GatewayAddress=127.0.0.1
GatewayPort=4800
# ModeHang=3 # ModeHang=3
Debug=0 Debug=0

File diff suppressed because it is too large Load diff

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2015-2020 by Jonathan Naylor G4KLX * Copyright (C) 2015-2021 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
@ -20,27 +20,30 @@
#define MMDVMHOST_H #define MMDVMHOST_H
#include "RemoteControl.h" #include "RemoteControl.h"
#include "POCSAGNetwork.h" //#include "POCSAGNetwork.h"
#include "POCSAGControl.h" //#include "POCSAGControl.h"
#include "DStarNetwork.h" //#include "DStarNetwork.h"
#include "NXDNNetwork.h" //#include "AX25Network.h"
#include "DStarControl.h" //#include "NXDNNetwork.h"
//#include "DStarControl.h"
//#include "AX25Control.h"
#include "DMRControl.h" #include "DMRControl.h"
#include "YSFControl.h" //#include "YSFControl.h"
#include "P25Control.h" //#include "P25Control.h"
#include "NXDNControl.h" //#include "NXDNControl.h"
#include "M17Control.h" //#include "M17Control.h"
#include "NXDNLookup.h" //#include "NXDNLookup.h"
#include "YSFNetwork.h" //#include "YSFNetwork.h"
#include "P25Network.h" //#include "P25Network.h"
#include "DMRNetwork.h" #include "DMRNetwork.h"
#include "M17Network.h" //#include "M17Network.h"
//#include "FMNetwork.h"
#include "DMRLookup.h" #include "DMRLookup.h"
#include "Display.h" //#include "FMControl.h"
//#include "Display.h"
#include "Timer.h" #include "Timer.h"
#include "Modem.h" #include "Modem.h"
#include "Conf.h" #include "Conf.h"
#include "UMP.h"
#include <string> #include <string>
@ -53,25 +56,17 @@ public:
int run(); int run();
void buildNetworkStatusString(std::string &str);
void buildNetworkHostsString(std::string &str);
private: private:
CConf m_conf; CConf m_conf;
CModem* m_modem; CModem* m_modem;
CDStarControl* m_dstar;
CDMRControl* m_dmr; CDMRControl* m_dmr;
CYSFControl* m_ysf;
CP25Control* m_p25; IDMRNetwork* m_dmrNetwork;
CNXDNControl* m_nxdn;
CM17Control* m_m17;
CPOCSAGControl* m_pocsag;
CDStarNetwork* m_dstarNetwork;
CDMRNetwork* m_dmrNetwork;
CYSFNetwork* m_ysfNetwork;
CP25Network* m_p25Network;
INXDNNetwork* m_nxdnNetwork;
CM17Network* m_m17Network;
CPOCSAGNetwork* m_pocsagNetwork;
CDisplay* m_display; CDisplay* m_display;
CUMP* m_ump;
unsigned char m_mode; unsigned char m_mode;
unsigned int m_dstarRFModeHang; unsigned int m_dstarRFModeHang;
unsigned int m_dmrRFModeHang; unsigned int m_dmrRFModeHang;
@ -79,6 +74,7 @@ private:
unsigned int m_p25RFModeHang; unsigned int m_p25RFModeHang;
unsigned int m_nxdnRFModeHang; unsigned int m_nxdnRFModeHang;
unsigned int m_m17RFModeHang; unsigned int m_m17RFModeHang;
unsigned int m_fmRFModeHang;
unsigned int m_dstarNetModeHang; unsigned int m_dstarNetModeHang;
unsigned int m_dmrNetModeHang; unsigned int m_dmrNetModeHang;
unsigned int m_ysfNetModeHang; unsigned int m_ysfNetModeHang;
@ -86,6 +82,7 @@ private:
unsigned int m_nxdnNetModeHang; unsigned int m_nxdnNetModeHang;
unsigned int m_m17NetModeHang; unsigned int m_m17NetModeHang;
unsigned int m_pocsagNetModeHang; unsigned int m_pocsagNetModeHang;
unsigned int m_fmNetModeHang;
CTimer m_modeTimer; CTimer m_modeTimer;
CTimer m_dmrTXTimer; CTimer m_dmrTXTimer;
CTimer m_cwIdTimer; CTimer m_cwIdTimer;
@ -99,9 +96,9 @@ private:
bool m_m17Enabled; bool m_m17Enabled;
bool m_pocsagEnabled; bool m_pocsagEnabled;
bool m_fmEnabled; bool m_fmEnabled;
bool m_ax25Enabled;
unsigned int m_cwIdTime; unsigned int m_cwIdTime;
CDMRLookup* m_dmrLookup; CDMRLookup* m_dmrLookup;
CNXDNLookup* m_nxdnLookup;
std::string m_callsign; std::string m_callsign;
unsigned int m_id; unsigned int m_id;
std::string m_cwCallsign; std::string m_cwCallsign;
@ -119,6 +116,8 @@ private:
bool createNXDNNetwork(); bool createNXDNNetwork();
bool createM17Network(); bool createM17Network();
bool createPOCSAGNetwork(); bool createPOCSAGNetwork();
bool createFMNetwork();
bool createAX25Network();
void remoteControl(); void remoteControl();
void processModeCommand(unsigned char mode, unsigned int timeout); void processModeCommand(unsigned char mode, unsigned int timeout);

View file

@ -1,41 +0,0 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15
VisualStudioVersion = 15.0.28307.271
MinimumVisualStudioVersion = 10.0.40219.1
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "MMDVMHost", "MMDVMHost.vcxproj", "{1D34E8C1-CFA5-4D60-B509-9DB58DC4AE92}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "RemoteCommand", "RemoteCommand.vcxproj", "{5A61AB93-58BB-413A-BBD9-A26284CB37AE}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|x64 = Debug|x64
Debug|x86 = Debug|x86
Release|x64 = Release|x64
Release|x86 = Release|x86
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{1D34E8C1-CFA5-4D60-B509-9DB58DC4AE92}.Debug|x64.ActiveCfg = Debug|x64
{1D34E8C1-CFA5-4D60-B509-9DB58DC4AE92}.Debug|x64.Build.0 = Debug|x64
{1D34E8C1-CFA5-4D60-B509-9DB58DC4AE92}.Debug|x86.ActiveCfg = Debug|Win32
{1D34E8C1-CFA5-4D60-B509-9DB58DC4AE92}.Debug|x86.Build.0 = Debug|Win32
{1D34E8C1-CFA5-4D60-B509-9DB58DC4AE92}.Release|x64.ActiveCfg = Release|x64
{1D34E8C1-CFA5-4D60-B509-9DB58DC4AE92}.Release|x64.Build.0 = Release|x64
{1D34E8C1-CFA5-4D60-B509-9DB58DC4AE92}.Release|x86.ActiveCfg = Release|Win32
{1D34E8C1-CFA5-4D60-B509-9DB58DC4AE92}.Release|x86.Build.0 = Release|Win32
{5A61AB93-58BB-413A-BBD9-A26284CB37AE}.Debug|x64.ActiveCfg = Debug|x64
{5A61AB93-58BB-413A-BBD9-A26284CB37AE}.Debug|x64.Build.0 = Debug|x64
{5A61AB93-58BB-413A-BBD9-A26284CB37AE}.Debug|x86.ActiveCfg = Debug|Win32
{5A61AB93-58BB-413A-BBD9-A26284CB37AE}.Debug|x86.Build.0 = Debug|Win32
{5A61AB93-58BB-413A-BBD9-A26284CB37AE}.Release|x64.ActiveCfg = Release|x64
{5A61AB93-58BB-413A-BBD9-A26284CB37AE}.Release|x64.Build.0 = Release|x64
{5A61AB93-58BB-413A-BBD9-A26284CB37AE}.Release|x86.ActiveCfg = Release|Win32
{5A61AB93-58BB-413A-BBD9-A26284CB37AE}.Release|x86.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {4FE84D69-7345-440E-8E0A-0CC1C84477F8}
EndGlobalSection
EndGlobal

View file

@ -1,357 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{1D34E8C1-CFA5-4D60-B509-9DB58DC4AE92}</ProjectGuid>
<Keyword>Win32Proj</Keyword>
<RootNamespace>MMDVMHost</RootNamespace>
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="Shared">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<LinkIncremental>true</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<LinkIncremental>true</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LinkIncremental>false</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<LinkIncremental>false</LinkIncremental>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>HAVE_LOG_H;WIN32;_DEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>HAVE_LOG_H;_DEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
<PreBuildEvent>
<Command>"$(ProjectDir)prebuild.cmd" $(ProjectDir)</Command>
</PreBuildEvent>
<PreBuildEvent>
<Message>prebuild.cmd generates GitVersion.h from git refs heads master</Message>
</PreBuildEvent>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<PrecompiledHeader>
</PrecompiledHeader>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>HAVE_LOG_H;WIN32;NDEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<PrecompiledHeader>
</PrecompiledHeader>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>HAVE_LOG_H;NDEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClInclude Include="AMBEFEC.h" />
<ClInclude Include="BCH.h" />
<ClInclude Include="BPTC19696.h" />
<ClInclude Include="CASTInfo.h" />
<ClInclude Include="Conf.h" />
<ClInclude Include="CRC.h" />
<ClInclude Include="Defines.h" />
<ClInclude Include="Display.h" />
<ClInclude Include="DMRAccessControl.h" />
<ClInclude Include="DMRControl.h" />
<ClInclude Include="DMRCSBK.h" />
<ClInclude Include="DMRData.h" />
<ClInclude Include="DMRDataHeader.h" />
<ClInclude Include="DMRDefines.h" />
<ClInclude Include="DMREMB.h" />
<ClInclude Include="DMREmbeddedData.h" />
<ClInclude Include="DMRFullLC.h" />
<ClInclude Include="DMRLC.h" />
<ClInclude Include="DMRNetwork.h" />
<ClInclude Include="DMRShortLC.h" />
<ClInclude Include="DMRSlot.h" />
<ClInclude Include="DMRSlotType.h" />
<ClInclude Include="DMRTA.h" />
<ClInclude Include="DMRTrellis.h" />
<ClInclude Include="DStarControl.h" />
<ClInclude Include="DStarDefines.h" />
<ClInclude Include="DStarHeader.h" />
<ClInclude Include="DStarNetwork.h" />
<ClInclude Include="DStarSlowData.h" />
<ClInclude Include="Golay2087.h" />
<ClInclude Include="Golay24128.h" />
<ClInclude Include="Hamming.h" />
<ClInclude Include="DMRLookup.h" />
<ClInclude Include="I2CController.h" />
<ClInclude Include="LCDproc.h" />
<ClInclude Include="Log.h" />
<ClInclude Include="M17Control.h" />
<ClInclude Include="M17Convolution.h" />
<ClInclude Include="M17CRC.h" />
<ClInclude Include="M17Defines.h" />
<ClInclude Include="M17LICH.h" />
<ClInclude Include="M17Network.h" />
<ClInclude Include="M17Utils.h" />
<ClInclude Include="MMDVMHost.h" />
<ClInclude Include="Modem.h" />
<ClInclude Include="ModemSerialPort.h" />
<ClInclude Include="Mutex.h" />
<ClInclude Include="NetworkInfo.h" />
<ClInclude Include="Nextion.h" />
<ClInclude Include="NullDisplay.h" />
<ClInclude Include="NullModem.h" />
<ClInclude Include="NXDNAudio.h" />
<ClInclude Include="NXDNControl.h" />
<ClInclude Include="NXDNConvolution.h" />
<ClInclude Include="NXDNCRC.h" />
<ClInclude Include="NXDNDefines.h" />
<ClInclude Include="NXDNFACCH1.h" />
<ClInclude Include="NXDNIcomNetwork.h" />
<ClInclude Include="NXDNKenwoodNetwork.h" />
<ClInclude Include="NXDNLayer3.h" />
<ClInclude Include="NXDNLICH.h" />
<ClInclude Include="NXDNLookup.h" />
<ClInclude Include="NXDNNetwork.h" />
<ClInclude Include="NXDNUDCH.h" />
<ClInclude Include="P25Audio.h" />
<ClInclude Include="P25Control.h" />
<ClInclude Include="P25Defines.h" />
<ClInclude Include="P25Data.h" />
<ClInclude Include="P25LowSpeedData.h" />
<ClInclude Include="P25Network.h" />
<ClInclude Include="P25NID.h" />
<ClInclude Include="P25Trellis.h" />
<ClInclude Include="P25Utils.h" />
<ClInclude Include="POCSAGControl.h" />
<ClInclude Include="POCSAGDefines.h" />
<ClInclude Include="POCSAGNetwork.h" />
<ClInclude Include="QR1676.h" />
<ClInclude Include="RemoteControl.h" />
<ClInclude Include="RingBuffer.h" />
<ClInclude Include="RS129.h" />
<ClInclude Include="RS241213.h" />
<ClInclude Include="RSSIInterpolator.h" />
<ClInclude Include="NXDNSACCH.h" />
<ClInclude Include="SerialController.h" />
<ClInclude Include="SerialPort.h" />
<ClInclude Include="StopWatch.h" />
<ClInclude Include="Sync.h" />
<ClInclude Include="TFTSerial.h" />
<ClInclude Include="TFTSurenoo.h" />
<ClInclude Include="Thread.h" />
<ClInclude Include="Timer.h" />
<ClInclude Include="UDPSocket.h" />
<ClInclude Include="UMP.h" />
<ClInclude Include="UserDB.h" />
<ClInclude Include="UserDBentry.h" />
<ClInclude Include="Utils.h" />
<ClInclude Include="Version.h" />
<ClInclude Include="YSFControl.h" />
<ClInclude Include="YSFConvolution.h" />
<ClInclude Include="YSFDefines.h" />
<ClInclude Include="YSFFICH.h" />
<ClInclude Include="YSFNetwork.h" />
<ClInclude Include="YSFPayload.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="AMBEFEC.cpp" />
<ClCompile Include="BCH.cpp" />
<ClCompile Include="BPTC19696.cpp" />
<ClCompile Include="CASTInfo.cpp" />
<ClCompile Include="Conf.cpp" />
<ClCompile Include="CRC.cpp" />
<ClCompile Include="Display.cpp" />
<ClCompile Include="DMRAccessControl.cpp" />
<ClCompile Include="DMRControl.cpp" />
<ClCompile Include="DMRCSBK.cpp" />
<ClCompile Include="DMRData.cpp" />
<ClCompile Include="DMRDataHeader.cpp" />
<ClCompile Include="DMREMB.cpp" />
<ClCompile Include="DMREmbeddedData.cpp" />
<ClCompile Include="DMRFullLC.cpp" />
<ClCompile Include="DMRLC.cpp" />
<ClCompile Include="DMRLookup.cpp" />
<ClCompile Include="DMRNetwork.cpp" />
<ClCompile Include="DMRShortLC.cpp" />
<ClCompile Include="DMRSlot.cpp" />
<ClCompile Include="DMRSlotType.cpp" />
<ClCompile Include="DMRTA.cpp" />
<ClCompile Include="DMRTrellis.cpp" />
<ClCompile Include="DStarControl.cpp" />
<ClCompile Include="DStarHeader.cpp" />
<ClCompile Include="DStarNetwork.cpp" />
<ClCompile Include="DStarSlowData.cpp" />
<ClCompile Include="Golay2087.cpp" />
<ClCompile Include="Golay24128.cpp" />
<ClCompile Include="Hamming.cpp" />
<ClCompile Include="I2CController.cpp" />
<ClCompile Include="LCDproc.cpp" />
<ClCompile Include="Log.cpp" />
<ClCompile Include="M17Control.cpp" />
<ClCompile Include="M17Convolution.cpp" />
<ClCompile Include="M17CRC.cpp" />
<ClCompile Include="M17LICH.cpp" />
<ClCompile Include="M17Network.cpp" />
<ClCompile Include="MMDVMHost.cpp" />
<ClCompile Include="Modem.cpp" />
<ClCompile Include="ModemSerialPort.cpp" />
<ClCompile Include="Mutex.cpp" />
<ClCompile Include="NetworkInfo.cpp" />
<ClCompile Include="Nextion.cpp" />
<ClCompile Include="NullDisplay.cpp" />
<ClCompile Include="NullModem.cpp" />
<ClCompile Include="NXDNAudio.cpp" />
<ClCompile Include="NXDNControl.cpp" />
<ClCompile Include="NXDNConvolution.cpp" />
<ClCompile Include="NXDNCRC.cpp" />
<ClCompile Include="NXDNFACCH1.cpp" />
<ClCompile Include="NXDNIcomNetwork.cpp" />
<ClCompile Include="NXDNKenwoodNetwork.cpp" />
<ClCompile Include="NXDNLayer3.cpp" />
<ClCompile Include="NXDNLICH.cpp" />
<ClCompile Include="NXDNLookup.cpp" />
<ClCompile Include="NXDNNetwork.cpp" />
<ClCompile Include="NXDNSACCH.cpp" />
<ClCompile Include="NXDNUDCH.cpp" />
<ClCompile Include="P25Audio.cpp" />
<ClCompile Include="P25Control.cpp" />
<ClCompile Include="P25Data.cpp" />
<ClCompile Include="P25LowSpeedData.cpp" />
<ClCompile Include="P25Network.cpp" />
<ClCompile Include="P25NID.cpp" />
<ClCompile Include="P25Trellis.cpp" />
<ClCompile Include="P25Utils.cpp" />
<ClCompile Include="POCSAGControl.cpp" />
<ClCompile Include="POCSAGNetwork.cpp" />
<ClCompile Include="QR1676.cpp" />
<ClCompile Include="RemoteControl.cpp" />
<ClCompile Include="RS129.cpp" />
<ClCompile Include="RS241213.cpp" />
<ClCompile Include="RSSIInterpolator.cpp" />
<ClCompile Include="SerialController.cpp" />
<ClCompile Include="SerialPort.cpp" />
<ClCompile Include="M17Utils.cpp" />
<ClCompile Include="StopWatch.cpp" />
<ClCompile Include="Sync.cpp" />
<ClCompile Include="TFTSerial.cpp" />
<ClCompile Include="TFTSurenoo.cpp" />
<ClCompile Include="Thread.cpp" />
<ClCompile Include="Timer.cpp" />
<ClCompile Include="UDPSocket.cpp" />
<ClCompile Include="UMP.cpp" />
<ClCompile Include="UserDB.cpp" />
<ClCompile Include="UserDBentry.cpp" />
<ClCompile Include="Utils.cpp" />
<ClCompile Include="YSFNetwork.cpp" />
<ClCompile Include="YSFPayload.cpp" />
<ClCompile Include="YSFControl.cpp" />
<ClCompile Include="YSFConvolution.cpp" />
<ClCompile Include="YSFFICH.cpp" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View file

@ -1,605 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="Source Files">
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
</Filter>
<Filter Include="Header Files">
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
<Extensions>h;hh;hpp;hxx;hm;inl;inc;xsd</Extensions>
</Filter>
</ItemGroup>
<ItemGroup>
<ClInclude Include="BPTC19696.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Conf.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="CRC.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Defines.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Display.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="DMRControl.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="DMRData.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="DMRDefines.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="DMRSlot.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="DStarDefines.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Golay2087.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Golay24128.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Hamming.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Log.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="MMDVMHost.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Modem.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="NullDisplay.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="QR1676.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="RemoteControl.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="RingBuffer.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="RS129.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="SerialController.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="StopWatch.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="TFTSerial.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Timer.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="UDPSocket.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Utils.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="YSFDefines.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Version.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="AMBEFEC.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="DStarNetwork.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="DMRDataHeader.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="DStarHeader.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="DStarSlowData.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="DStarControl.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="YSFConvolution.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="YSFFICH.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="DMRCSBK.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Sync.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="DMREMB.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="DMREmbeddedData.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="DMRFullLC.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="DMRLC.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="DMRShortLC.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="DMRSlotType.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="YSFControl.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="YSFPayload.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Nextion.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="DMRLookup.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="YSFNetwork.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Thread.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="DMRTrellis.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="DMRAccessControl.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="P25Defines.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="P25Control.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="P25NID.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="P25Audio.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="P25Data.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="P25Utils.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="P25LowSpeedData.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="P25Network.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="DMRNetwork.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="BCH.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="RS241213.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="SerialPort.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="ModemSerialPort.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Mutex.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="LCDproc.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="UMP.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="RSSIInterpolator.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="NetworkInfo.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="P25Trellis.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="NXDNDefines.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="NXDNControl.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="NXDNNetwork.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="NXDNLICH.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="NXDNConvolution.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="NXDNCRC.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="NXDNLookup.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="NXDNSACCH.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="NXDNFACCH1.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="NXDNUDCH.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="NXDNLayer3.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="NXDNAudio.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="POCSAGNetwork.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="POCSAGControl.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="POCSAGDefines.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="I2CController.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="NullModem.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="DMRTA.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="CASTInfo.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="TFTSurenoo.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="UserDB.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="UserDBentry.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="NXDNIcomNetwork.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="NXDNKenwoodNetwork.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="M17Defines.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="M17Control.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="M17Network.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="M17LICH.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="M17CRC.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="M17Convolution.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="M17Utils.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="BPTC19696.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Conf.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="CRC.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Display.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="DMRControl.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="DMRData.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="DMRSlot.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Golay2087.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Golay24128.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Hamming.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Log.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="MMDVMHost.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Modem.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="NullDisplay.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="QR1676.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="RemoteControl.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="RS129.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="SerialController.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="StopWatch.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="TFTSerial.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Timer.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="UDPSocket.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Utils.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="AMBEFEC.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="DStarNetwork.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="DMRDataHeader.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="DStarHeader.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="DStarSlowData.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="DStarControl.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="YSFConvolution.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="YSFFICH.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="DMRCSBK.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Sync.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="DMREMB.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="DMREmbeddedData.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="DMRFullLC.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="DMRLC.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="DMRShortLC.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="DMRSlotType.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="YSFControl.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="YSFPayload.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Nextion.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="DMRLookup.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="YSFNetwork.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Thread.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="DMRTrellis.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="DMRAccessControl.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="P25Control.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="P25NID.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="P25Audio.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="P25Data.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="P25Utils.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="P25LowSpeedData.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="P25Network.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="DMRNetwork.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="BCH.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="RS241213.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="SerialPort.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="ModemSerialPort.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Mutex.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="LCDproc.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="UMP.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="RSSIInterpolator.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="NetworkInfo.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="P25Trellis.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="NXDNControl.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="NXDNNetwork.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="NXDNLICH.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="NXDNConvolution.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="NXDNCRC.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="NXDNLookup.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="NXDNSACCH.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="NXDNFACCH1.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="NXDNUDCH.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="NXDNLayer3.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="NXDNAudio.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="POCSAGNetwork.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="POCSAGControl.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="I2CController.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="NullModem.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="DMRTA.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="CASTInfo.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="TFTSurenoo.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="UserDB.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="UserDBentry.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="NXDNIcomNetwork.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="NXDNKenwoodNetwork.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="M17Control.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="M17Network.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="M17CRC.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="M17Utils.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="M17LICH.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="M17Convolution.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
</Project>

View file

@ -2,19 +2,18 @@
CC = cc CC = cc
CXX = c++ CXX = c++
CFLAGS = -g -O3 -Wall -std=c++0x -pthread -DHAVE_LOG_H CFLAGS = -g -O3 -Wall -std=c++0x -pthread -DHAVE_LOG_H -I/usr/local/include
LIBS = -lpthread LIBS = -lpthread -lutil
LDFLAGS = -g LDFLAGS = -g -L/usr/local/lib
OBJECTS = \ OBJECTS = \
AMBEFEC.o BCH.o BPTC19696.o CASTInfo.o Conf.o CRC.o Display.o DMRControl.o DMRCSBK.o DMRData.o DMRDataHeader.o DMREMB.o DMREmbeddedData.o DMRFullLC.o \ AMBEFEC.o BCH.o BPTC19696.o CASTInfo.o Conf.o CRC.o Display.o DMRControl.o DMRCSBK.o DMRData.o DMRDataHeader.o \
DMRLookup.o DMRLC.o DMRNetwork.o DMRShortLC.o DMRSlot.o DMRSlotType.o DMRAccessControl.o DMRTA.o DMRTrellis.o DStarControl.o DStarHeader.o \ DMRDirectNetwork.o DMREMB.o DMREmbeddedData.o DMRFullLC.o DMRGatewayNetwork.o DMRLookup.o DMRLC.o DMRNetwork.o DMRShortLC.o DMRSlot.o DMRSlotType.o \
DStarNetwork.o DStarSlowData.o Golay2087.o Golay24128.o Hamming.o I2CController.o LCDproc.o Log.o M17Control.o M17Convolution.o M17CRC.o M17LICH.o \ DMRAccessControl.o DMRTA.o DMRTrellis.o Golay2087.o Golay24128.o\
M17Network.o M17Utils.o MMDVMHost.o Modem.o ModemSerialPort.o Mutex.o NetworkInfo.o Nextion.o NullDisplay.o NullModem.o NXDNAudio.o NXDNControl.o \ Hamming.o I2CController.o IIRDirectForm1Filter.o LCDproc.o Log.o MMDVMHost.o \
NXDNConvolution.o NXDNCRC.o NXDNFACCH1.o NXDNIcomNetwork.o NXDNKenwoodNetwork.o NXDNLayer3.o NXDNLICH.o NXDNLookup.o NXDNNetwork.o NXDNSACCH.o \ Modem.o ModemPort.o ModemSerialPort.o Mutex.o NetworkInfo.o Nextion.o NullController.o NullDisplay.o \
NXDNUDCH.o P25Audio.o P25Control.o P25Data.o P25LowSpeedData.o P25Network.o P25NID.o P25Trellis.o P25Utils.o POCSAGControl.o POCSAGNetwork.o QR1676.o \ RemoteControl.o QR1676.o RS129.o RS241213.o RSSIInterpolator.o SerialPort.o SMeter.o StopWatch.o Sync.o SHA256.o TFTSurenoo.o Thread.o \
RemoteControl.o RS129.o RS241213.o RSSIInterpolator.o SerialController.o SerialPort.o StopWatch.o Sync.o TFTSerial.o TFTSurenoo.o Thread.o Timer.o \ Timer.o UARTController.o UDPController.o UDPSocket.o UserDB.o UserDBentry.o Utils.o
UDPSocket.o UMP.o UserDB.o UserDBentry.o Utils.o YSFControl.o YSFConvolution.o YSFFICH.o YSFNetwork.o YSFPayload.o
all: MMDVMHost RemoteCommand all: MMDVMHost RemoteCommand
@ -27,10 +26,33 @@ RemoteCommand: Log.o RemoteCommand.o UDPSocket.o
%.o: %.cpp %.o: %.cpp
$(CXX) $(CFLAGS) -c -o $@ $< $(CXX) $(CFLAGS) -c -o $@ $<
install: .PHONY install:
install: all
install -m 755 MMDVMHost /usr/local/bin/ install -m 755 MMDVMHost /usr/local/bin/
install -m 755 RemoteCommand /usr/local/bin/ install -m 755 RemoteCommand /usr/local/bin/
.PHONY install-service:
install-service: install /etc/MMDVM.ini
@useradd --user-group -M --system mmdvm --shell /bin/false || true
@usermod --groups dialout --append mmdvm || true
@mkdir /var/log/mmdvm || true
@chown mmdvm:mmdvm /var/log/mmdvm
@cp ./linux/systemd/mmdvmhost.service /lib/systemd/system/
@systemctl enable mmdvmhost.service
/etc/MMDVM.ini:
@cp -n MMDVM.ini /etc/MMDVM.ini
@sed -i 's/FilePath=./FilePath=\/var\/log\/mmdvm\//' /etc/MMDVM.ini
@sed -i 's/Daemon=0/Daemon=1/' /etc/MMDVM.ini
@chown mmdvm:mmdvm /etc/MMDVM.ini
.PHONY uninstall-service:
uninstall-service:
@systemctl stop mmdvmhost.service || true
@systemctl disable mmdvmhost.service || true
@rm -f /usr/local/bin/MMDVMHost || true
@rm -f /lib/systemd/system/mmdvmhost.service || true
clean: clean:
$(RM) MMDVMHost RemoteCommand *.o *.d *.bak *~ GitVersion.h $(RM) MMDVMHost RemoteCommand *.o *.d *.bak *~ GitVersion.h

View file

@ -3,18 +3,17 @@
CC = cc CC = cc
CXX = c++ CXX = c++
CFLAGS = -g -O3 -Wall -std=c++0x -pthread -DHAVE_LOG_H -DRASPBERRY_PI -I/usr/local/include CFLAGS = -g -O3 -Wall -std=c++0x -pthread -DHAVE_LOG_H -DRASPBERRY_PI -I/usr/local/include
LIBS = -lwiringPi -lwiringPiDev -lpthread LIBS = -lwiringPi -lwiringPiDev -lpthread -lutil
LDFLAGS = -g -L/usr/local/lib LDFLAGS = -g -L/usr/local/lib
OBJECTS = \ OBJECTS = \
AMBEFEC.o BCH.o BPTC19696.o CASTInfo.o Conf.o CRC.o Display.o DMRControl.o DMRCSBK.o DMRData.o DMRDataHeader.o DMREMB.o DMREmbeddedData.o DMRFullLC.o \ AMBEFEC.o BCH.o BPTC19696.o CASTInfo.o Conf.o CRC.o Display.o DMRControl.o DMRCSBK.o DMRData.o DMRDataHeader.o \
DMRLookup.o DMRLC.o DMRNetwork.o DMRShortLC.o DMRSlot.o DMRSlotType.o DMRAccessControl.o DMRTA.o DMRTrellis.o DStarControl.o DStarHeader.o \ DMRDirectNetwork.o DMREMB.o DMREmbeddedData.o DMRFullLC.o DMRGatewayNetwork.o DMRLookup.o DMRLC.o DMRNetwork.o DMRShortLC.o DMRSlot.o DMRSlotType.o \
DStarNetwork.o DStarSlowData.o Golay2087.o Golay24128.o Hamming.o I2CController.o LCDproc.o Log.o M17Control.o M17Convolution.o M17CRC.o M17LICH.o \ DMRAccessControl.o DMRTA.o DMRTrellis.o Golay2087.o Golay24128.o\
M17Network.o M17Utils.o MMDVMHost.o Modem.o ModemSerialPort.o Mutex.o NetworkInfo.o Nextion.o NullDisplay.o NullModem.o NXDNAudio.o NXDNControl.o \ Hamming.o I2CController.o IIRDirectForm1Filter.o LCDproc.o Log.o MMDVMHost.o \
NXDNConvolution.o NXDNCRC.o NXDNFACCH1.o NXDNIcomNetwork.o NXDNKenwoodNetwork.o NXDNLayer3.o NXDNLICH.o NXDNLookup.o NXDNNetwork.o NXDNSACCH.o \ Modem.o ModemPort.o ModemSerialPort.o Mutex.o NetworkInfo.o Nextion.o NullController.o NullDisplay.o \
NXDNUDCH.o P25Audio.o P25Control.o P25Data.o P25LowSpeedData.o P25Network.o P25NID.o P25Trellis.o P25Utils.o POCSAGControl.o POCSAGNetwork.o QR1676.o \ RemoteControl.o QR1676.o RS129.o RS241213.o RSSIInterpolator.o SerialPort.o SMeter.o StopWatch.o Sync.o SHA256.o TFTSurenoo.o Thread.o \
RemoteControl.o RS129.o RS241213.o RSSIInterpolator.o SerialController.o SerialPort.o StopWatch.o Sync.o TFTSerial.o TFTSurenoo.o Thread.o Timer.o \ Timer.o UARTController.o UDPController.o UDPSocket.o UserDB.o UserDBentry.o Utils.o
UDPSocket.o UMP.o UserDB.o UserDBentry.o Utils.o YSFControl.o YSFConvolution.o YSFFICH.o YSFNetwork.o YSFPayload.o
all: MMDVMHost RemoteCommand all: MMDVMHost RemoteCommand
@ -27,10 +26,33 @@ RemoteCommand: Log.o RemoteCommand.o UDPSocket.o
%.o: %.cpp %.o: %.cpp
$(CXX) $(CFLAGS) -c -o $@ $< $(CXX) $(CFLAGS) -c -o $@ $<
install: .PHONY install:
install: all
install -m 755 MMDVMHost /usr/local/bin/ install -m 755 MMDVMHost /usr/local/bin/
install -m 755 RemoteCommand /usr/local/bin/ install -m 755 RemoteCommand /usr/local/bin/
.PHONY install-service:
install-service: install /etc/MMDVM.ini
@useradd --user-group -M --system mmdvm --shell /bin/false || true
@usermod --groups dialout --append mmdvm || true
@mkdir /var/log/mmdvm || true
@chown mmdvm:mmdvm /var/log/mmdvm
@cp ./linux/systemd/mmdvmhost.service /lib/systemd/system/
@systemctl enable mmdvmhost.service
/etc/MMDVM.ini:
@cp -n MMDVM.ini /etc/MMDVM.ini
@sed -i 's/FilePath=./FilePath=\/var\/log\/mmdvm\//' /etc/MMDVM.ini
@sed -i 's/Daemon=0/Daemon=1/' /etc/MMDVM.ini
@chown mmdvm:mmdvm /etc/MMDVM.ini
.PHONY uninstall-service:
uninstall-service:
@systemctl stop mmdvmhost.service || true
@systemctl disable mmdvmhost.service || true
@rm -f /usr/local/bin/MMDVMHost || true
@rm -f /lib/systemd/system/mmdvmhost.service || true
clean: clean:
$(RM) MMDVMHost RemoteCommand *.o *.d *.bak *~ GitVersion.h $(RM) MMDVMHost RemoteCommand *.o *.d *.bak *~ GitVersion.h

View file

@ -1,44 +0,0 @@
# This makefile is for use with the Raspberry Pi when using an HD44780 compatible display. The wiringpi library is needed.
# Support for the Adafruit i2c 16 x 2 RGB LCD Pi Plate
CC = cc
CXX = c++
CFLAGS = -g -O3 -Wall -std=c++0x -pthread -DHAVE_LOG_H -DHD44780 -DADAFRUIT_DISPLAY -I/usr/local/include
LIBS = -lwiringPi -lwiringPiDev -lpthread
LDFLAGS = -g -L/usr/local/lib
OBJECTS = \
AMBEFEC.o BCH.o BPTC19696.o CASTInfo.o Conf.o CRC.o Display.o DMRControl.o DMRCSBK.o DMRData.o DMRDataHeader.o DMREMB.o DMREmbeddedData.o DMRFullLC.o \
DMRLookup.o DMRLC.o DMRNetwork.o DMRShortLC.o DMRSlot.o DMRSlotType.o DMRAccessControl.o DMRTA.o DMRTrellis.o DStarControl.o DStarHeader.o \
DStarNetwork.o DStarSlowData.o Golay2087.o Golay24128.o Hamming.o HD44780.o I2CController.o LCDproc.o Log.o M17Control.o M17Convolution.o M17CRC.o \
M17LICH.o M17Network.o M17Utils.o MMDVMHost.o Modem.o ModemSerialPort.o Mutex.o NetworkInfo.o Nextion.o NullDisplay.o NullModem.o NXDNAudio.o \
NXDNControl.o NXDNConvolution.o NXDNCRC.o NXDNFACCH1.o NXDNIcomNetwork.o NXDNKenwoodNetwork.o NXDNLayer3.o NXDNLICH.o NXDNLookup.o NXDNNetwork.o \
NXDNSACCH.o NXDNUDCH.o P25Audio.o P25Control.o P25Data.o P25LowSpeedData.o P25Network.o P25NID.o P25Trellis.o P25Utils.o POCSAGControl.o \
POCSAGNetwork.o QR1676.o RemoteControl.o RS129.o RS241213.o RSSIInterpolator.o SerialController.o SerialPort.o StopWatch.o Sync.o TFTSerial.o \
TFTSurenoo.o Thread.o Timer.o UDPSocket.o UMP.o UserDB.o UserDBentry.o Utils.o YSFControl.o YSFConvolution.o YSFFICH.o YSFNetwork.o YSFPayload.o
all: MMDVMHost RemoteCommand
MMDVMHost: GitVersion.h $(OBJECTS)
$(CXX) $(OBJECTS) $(CFLAGS) $(LIBS) -o MMDVMHost
RemoteCommand: Log.o RemoteCommand.o UDPSocket.o
$(CXX) Log.o RemoteCommand.o UDPSocket.o $(CFLAGS) $(LIBS) -o RemoteCommand
%.o: %.cpp
$(CXX) $(CFLAGS) -c -o $@ $<
install:
install -m 755 MMDVMHost /usr/local/bin/
install -m 755 RemoteCommand /usr/local/bin/
clean:
$(RM) MMDVMHost RemoteCommand *.o *.d *.bak *~ GitVersion.h
# Export the current git version if the index file exists, else 000...
GitVersion.h:
ifneq ("$(wildcard .git/index)","")
echo "const char *gitversion = \"$(shell git rev-parse HEAD)\";" > $@
else
echo "const char *gitversion = \"0000000000000000000000000000000000000000\";" > $@
endif

View file

@ -1,43 +0,0 @@
# This makefile is for use with the Raspberry Pi when using an HD44780 compatible display. The wiringpi library is needed.
CC = cc
CXX = c++
CFLAGS = -g -O3 -Wall -std=c++0x -pthread -DHAVE_LOG_H -DHD44780 -I/usr/local/include
LIBS = -lwiringPi -lwiringPiDev -lpthread
LDFLAGS = -g -L/usr/local/lib
OBJECTS = \
AMBEFEC.o BCH.o BPTC19696.o CASTInfo.o Conf.o CRC.o Display.o DMRControl.o DMRCSBK.o DMRData.o DMRDataHeader.o DMREMB.o DMREmbeddedData.o DMRFullLC.o \
DMRLookup.o DMRLC.o DMRNetwork.o DMRShortLC.o DMRSlot.o DMRSlotType.o DMRAccessControl.o DMRTA.o DMRTrellis.o DStarControl.o DStarHeader.o \
DStarNetwork.o DStarSlowData.o Golay2087.o Golay24128.o Hamming.o HD44780.o I2CController.o LCDproc.o Log.o M17Control.o M17Convolution.o M17CRC.o \
M17LICH.o M17Network.o M17Utils.o MMDVMHost.o Modem.o ModemSerialPort.o Mutex.o NetworkInfo.o Nextion.o NullDisplay.o NullModem.o NXDNAudio.o \
NXDNControl.o NXDNConvolution.o NXDNCRC.o NXDNFACCH1.o NXDNIcomNetwork.o NXDNKenwoodNetwork.o NXDNLayer3.o NXDNLICH.o NXDNLookup.o NXDNNetwork.o \
NXDNSACCH.o NXDNUDCH.o P25Audio.o P25Control.o P25Data.o P25LowSpeedData.o P25Network.o P25NID.o P25Trellis.o P25Utils.o POCSAGControl.o \
POCSAGNetwork.o QR1676.o RemoteControl.o RS129.o RS241213.o RSSIInterpolator.o SerialController.o SerialPort.o StopWatch.o Sync.o TFTSerial.o \
TFTSurenoo.o Thread.o Timer.o UDPSocket.o UMP.o UserDB.o UserDBentry.o Utils.o YSFControl.o YSFConvolution.o YSFFICH.o YSFNetwork.o YSFPayload.o
all: MMDVMHost RemoteCommand
MMDVMHost: GitVersion.h $(OBJECTS)
$(CXX) $(OBJECTS) $(CFLAGS) $(LIBS) -o MMDVMHost
RemoteCommand: Log.o RemoteCommand.o UDPSocket.o
$(CXX) Log.o RemoteCommand.o UDPSocket.o $(CFLAGS) $(LIBS) -o RemoteCommand
%.o: %.cpp
$(CXX) $(CFLAGS) -c -o $@ $<
install:
install -m 755 MMDVMHost /usr/local/bin/
install -m 755 RemoteCommand /usr/local/bin/
clean:
$(RM) MMDVMHost RemoteCommand *.o *.d *.bak *~ GitVersion.h
# Export the current git version if the index file exists, else 000...
GitVersion.h:
ifneq ("$(wildcard .git/index)","")
echo "const char *gitversion = \"$(shell git rev-parse HEAD)\";" > $@
else
echo "const char *gitversion = \"0000000000000000000000000000000000000000\";" > $@
endif

View file

@ -1,48 +0,0 @@
# This makefile is for use with the Raspberry Pi when using an OLED display. The wiringpi library is not needed.
CC = cc
CXX = c++
CFLAGS = -g -O3 -Wall -std=c++0x -pthread -DHAVE_LOG_H -DOLED -I/usr/local/include
LIBS = -lArduiPi_OLED -lpthread
# If you use NetBSD, add following CFLAGS
#CFLAGS += -L/usr/local/lib -Wl,-rpath=/usr/local/lib
LDFLAGS = -g -L/usr/local/lib
OBJECTS = \
AMBEFEC.o BCH.o BPTC19696.o CASTInfo.o Conf.o CRC.o Display.o DMRControl.o DMRCSBK.o DMRData.o DMRDataHeader.o DMREMB.o DMREmbeddedData.o DMRFullLC.o \
DMRLookup.o DMRLC.o DMRNetwork.o DMRShortLC.o DMRSlot.o DMRSlotType.o DMRAccessControl.o DMRTA.o DMRTrellis.o DStarControl.o DStarHeader.o \
DStarNetwork.o DStarSlowData.o Golay2087.o Golay24128.o Hamming.o I2CController.o OLED.o LCDproc.o Log.o M17Control.o M17Convolution.o M17CRC.o \
M17LICH.o M17Network.o M17Utils.o MMDVMHost.o Modem.o ModemSerialPort.o Mutex.o NetworkInfo.o Nextion.o NullDisplay.o NullModem.o NXDNAudio.o \
NXDNControl.o NXDNConvolution.o NXDNCRC.o NXDNFACCH1.o NXDNIcomNetwork.o NXDNKenwoodNetwork.o NXDNLayer3.o NXDNLICH.o NXDNLookup.o NXDNNetwork.o \
NXDNSACCH.o NXDNUDCH.o P25Audio.o P25Control.o P25Data.o P25LowSpeedData.o P25Network.o P25NID.o P25Trellis.o P25Utils.o POCSAGControl.o \
POCSAGNetwork.o QR1676.o RemoteControl.o RS129.o RS241213.o RSSIInterpolator.o SerialController.o SerialPort.o StopWatch.o Sync.o TFTSerial.o \
TFTSurenoo.o Thread.o Timer.o UDPSocket.o UMP.o UserDB.o UserDBentry.o Utils.o YSFControl.o YSFConvolution.o YSFFICH.o YSFNetwork.o YSFPayload.o
all: MMDVMHost RemoteCommand
MMDVMHost: GitVersion.h $(OBJECTS)
$(CXX) $(OBJECTS) $(CFLAGS) $(LIBS) -o MMDVMHost
RemoteCommand: Log.o RemoteCommand.o UDPSocket.o
$(CXX) Log.o RemoteCommand.o UDPSocket.o $(CFLAGS) $(LIBS) -o RemoteCommand
%.o: %.cpp
$(CXX) $(CFLAGS) -c -o $@ $<
install:
install -m 755 MMDVMHost /usr/local/bin/
install -m 755 RemoteCommand /usr/local/bin/
clean:
$(RM) MMDVMHost RemoteCommand *.o *.d *.bak *~ GitVersion.h
# Export the current git version if the index file exists, else 000...
GitVersion.h:
ifneq ("$(wildcard .git/index)","")
echo "const char *gitversion = \"$(shell git rev-parse HEAD)\";" > $@
else
echo "const char *gitversion = \"0000000000000000000000000000000000000000\";" > $@
endif

View file

@ -1,44 +0,0 @@
# This makefile is for use with the Raspberry Pi when using an HD44780 compatible display. The wiringpi library is needed.
# Support for the HD44780 connected via a PCF8574 8-bit GPIO expander IC
CC = cc
CXX = c++
CFLAGS = -g -O3 -Wall -std=c++0x -pthread -DHAVE_LOG_H -DHD44780 -DPCF8574_DISPLAY -I/usr/local/include
LIBS = -lwiringPi -lwiringPiDev -lpthread
LDFLAGS = -g -L/usr/local/lib
OBJECTS = \
AMBEFEC.o BCH.o BPTC19696.o CASTInfo.o Conf.o CRC.o Display.o DMRControl.o DMRCSBK.o DMRData.o DMRDataHeader.o DMREMB.o DMREmbeddedData.o DMRFullLC.o \
DMRLookup.o DMRLC.o DMRNetwork.o DMRShortLC.o DMRSlot.o DMRSlotType.o DMRAccessControl.o DMRTA.o DMRTrellis.o DStarControl.o DStarHeader.o \
DStarNetwork.o DStarSlowData.o Golay2087.o Golay24128.o Hamming.o HD44780.o I2CController.o LCDproc.o Log.o M17Control.o M17Convolution.o M17CRC.o \
M17LICH.o M17Network.o M17Utils.o MMDVMHost.o Modem.o ModemSerialPort.o Mutex.o NetworkInfo.o Nextion.o NullDisplay.o NullModem.o NXDNAudio.o \
NXDNControl.o NXDNConvolution.o NXDNCRC.o NXDNFACCH1.o NXDNIcomNetwork.o NXDNKenwoodNetwork.o NXDNLayer3.o NXDNLICH.o NXDNLookup.o NXDNNetwork.o \
NXDNSACCH.o NXDNUDCH.o P25Audio.o P25Control.o P25Data.o P25LowSpeedData.o P25Network.o P25NID.o P25Trellis.o P25Utils.o POCSAGControl.o \
POCSAGNetwork.o QR1676.o RemoteControl.o RS129.o RS241213.o RSSIInterpolator.o SerialController.o SerialPort.o StopWatch.o Sync.o TFTSerial.o \
TFTSurenoo.o Thread.o Timer.o UDPSocket.o UMP.o UserDB.o UserDBentry.o Utils.o YSFControl.o YSFConvolution.o YSFFICH.o YSFNetwork.o YSFPayload.o
all: MMDVMHost RemoteCommand
MMDVMHost: GitVersion.h $(OBJECTS)
$(CXX) $(OBJECTS) $(CFLAGS) $(LIBS) -o MMDVMHost
RemoteCommand: Log.o RemoteCommand.o UDPSocket.o
$(CXX) Log.o RemoteCommand.o UDPSocket.o $(CFLAGS) $(LIBS) -o RemoteCommand
%.o: %.cpp
$(CXX) $(CFLAGS) -c -o $@ $<
install:
install -m 755 MMDVMHost /usr/local/bin/
install -m 755 RemoteCommand /usr/local/bin/
clean:
$(RM) MMDVMHost RemoteCommand *.o *.d *.bak *~ GitVersion.h
# Export the current git version if the index file exists, else 000...
GitVersion.h:
ifneq ("$(wildcard .git/index)","")
echo "const char *gitversion = \"$(shell git rev-parse HEAD)\";" > $@
else
echo "const char *gitversion = \"0000000000000000000000000000000000000000\";" > $@
endif

1684
Modem.cpp

File diff suppressed because it is too large Load diff

231
Modem.h
View file

@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2011-2018,2020 by Jonathan Naylor G4KLX * Copyright (C) 2011-2018,2020,2021 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
@ -16,10 +16,10 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/ */
#ifndef MODEM_H #ifndef Modem_H
#define MODEM_H #define Modem_H
#include "SerialController.h" #include "ModemPort.h"
#include "RingBuffer.h" #include "RingBuffer.h"
#include "Defines.h" #include "Defines.h"
#include "Timer.h" #include "Timer.h"
@ -32,102 +32,107 @@ enum RESP_TYPE_MMDVM {
RTM_ERROR RTM_ERROR
}; };
enum SERIAL_STATE {
SS_START,
SS_LENGTH1,
SS_LENGTH2,
SS_TYPE,
SS_DATA
};
class CModem { class CModem {
public: public:
CModem(const std::string& port, bool duplex, bool rxInvert, bool txInvert, bool pttInvert, unsigned int txDelay, unsigned int dmrDelay, bool useCOSAsLockout, bool trace, bool debug); CModem(bool duplex, bool rxInvert, bool txInvert, bool pttInvert, unsigned int txDelay, unsigned int dmrDelay, bool useCOSAsLockout, bool trace, bool debug);
virtual ~CModem(); ~CModem();
virtual void setSerialParams(const std::string& protocol, unsigned int address); void setPort(IModemPort* port);
virtual void setRFParams(unsigned int rxFrequency, int rxOffset, unsigned int txFrequency, int txOffset, int txDCOffset, int rxDCOffset, float rfLevel, unsigned int pocsagFrequency); void setRFParams(unsigned int rxFrequency, int rxOffset, unsigned int txFrequency, int txOffset, int txDCOffset, int rxDCOffset, float rfLevel);
virtual void setModeParams(bool dstarEnabled, bool dmrEnabled, bool ysfEnabled, bool p25Enabled, bool nxdnEnabled, bool m17Enabled, bool pocsagEnabled, bool fmEnabled); void setModeParams(bool dstarEnabled, bool dmrEnabled, bool ysfEnabled, bool p25Enabled, bool nxdnEnabled, bool m17Enabled, bool pocsagEnabled, bool fmEnabled, bool ax25Enabled);
virtual void setLevels(float rxLevel, float cwIdTXLevel, float dstarTXLevel, float dmrTXLevel, float ysfTXLevel, float p25TXLevel, float nxdnTXLevel, float m17TXLevel, float pocsagLevel, float fmTXLevel); void setLevels(float rxLevel, float cwIdTXLevel, float dmrTXLevel);
virtual void setDMRParams(unsigned int colorCode); void setDMRParams(unsigned int colorCode);
virtual void setYSFParams(bool loDev, unsigned int txHang); void setYSFParams(bool loDev, unsigned int txHang);
virtual void setP25Params(unsigned int txHang); void setP25Params(unsigned int txHang);
virtual void setNXDNParams(unsigned int txHang); void setNXDNParams(unsigned int txHang);
virtual void setM17Params(unsigned int txHang); void setM17Params(unsigned int txHang);
virtual void setTransparentDataParams(unsigned int sendFrameType); void setAX25Params(int rxTwist, unsigned int txDelay, unsigned int slotTime, unsigned int pPersist);
void setTransparentDataParams(unsigned int sendFrameType);
virtual void setFMCallsignParams(const std::string& callsign, unsigned int callsignSpeed, unsigned int callsignFrequency, unsigned int callsignTime, unsigned int callsignHoldoff, float callsignHighLevel, float callsignLowLevel, bool callsignAtStart, bool callsignAtEnd, bool callsignAtLatch); void setFMCallsignParams(const std::string& callsign, unsigned int callsignSpeed, unsigned int callsignFrequency, unsigned int callsignTime, unsigned int callsignHoldoff, float callsignHighLevel, float callsignLowLevel, bool callsignAtStart, bool callsignAtEnd, bool callsignAtLatch);
virtual void setFMAckParams(const std::string& rfAck, unsigned int ackSpeed, unsigned int ackFrequency, unsigned int ackMinTime, unsigned int ackDelay, float ackLevel); void setFMAckParams(const std::string& rfAck, unsigned int ackSpeed, unsigned int ackFrequency, unsigned int ackMinTime, unsigned int ackDelay, float ackLevel);
virtual void setFMMiscParams(unsigned int timeout, float timeoutLevel, float ctcssFrequency, unsigned int ctcssHighThreshold, unsigned int ctcssLowThreshold, float ctcssLevel, unsigned int kerchunkTime, unsigned int hangTime, unsigned int accessMode, bool cosInvert, unsigned int rfAudioBoost, float maxDevLevel); void setFMMiscParams(unsigned int timeout, float timeoutLevel, float ctcssFrequency, unsigned int ctcssHighThreshold, unsigned int ctcssLowThreshold, float ctcssLevel, unsigned int kerchunkTime, unsigned int hangTime, unsigned int accessMode, bool linkMode, bool cosInvert, bool noiseSquelch, unsigned int squelchHighThreshold, unsigned int squelchLowThreshold, unsigned int rfAudioBoost, float maxDevLevel);
void setFMExtParams(const std::string& ack, unsigned int audioBoost);
virtual bool open(); bool open();
virtual unsigned int readDStarData(unsigned char* data); bool hasDStar() const;
virtual unsigned int readDMRData1(unsigned char* data); bool hasDMR() const;
virtual unsigned int readDMRData2(unsigned char* data); bool hasYSF() const;
virtual unsigned int readYSFData(unsigned char* data); bool hasP25() const;
virtual unsigned int readP25Data(unsigned char* data); bool hasNXDN() const;
virtual unsigned int readNXDNData(unsigned char* data); bool hasM17() const;
virtual unsigned int readM17Data(unsigned char* data); bool hasPOCSAG() const;
virtual unsigned int readTransparentData(unsigned char* data); bool hasFM() const;
bool hasAX25() const;
virtual unsigned int readSerial(unsigned char* data, unsigned int length); unsigned int getVersion() const;
virtual bool hasDStarSpace() const; unsigned int readDStarData(unsigned char* data);
virtual bool hasDMRSpace1() const; unsigned int readDMRData1(unsigned char* data);
virtual bool hasDMRSpace2() const; unsigned int readDMRData2(unsigned char* data);
virtual bool hasYSFSpace() const; unsigned int readYSFData(unsigned char* data);
virtual bool hasP25Space() const; unsigned int readP25Data(unsigned char* data);
virtual bool hasNXDNSpace() const; unsigned int readNXDNData(unsigned char* data);
virtual bool hasM17Space() const; unsigned int readM17Data(unsigned char* data);
virtual bool hasPOCSAGSpace() const; unsigned int readFMData(unsigned char* data);
unsigned int readAX25Data(unsigned char* data);
virtual bool hasTX() const; bool hasDStarSpace() const;
virtual bool hasCD() const; bool hasDMRSpace1() const;
bool hasDMRSpace2() const;
bool hasYSFSpace() const;
bool hasP25Space() const;
bool hasNXDNSpace() const;
bool hasM17Space() const;
bool hasPOCSAGSpace() const;
unsigned int getFMSpace() const;
bool hasAX25Space() const;
virtual bool hasLockout() const; bool hasTX() const;
virtual bool hasError() const; bool hasCD() const;
virtual bool writeConfig(); bool hasLockout() const;
virtual bool writeDStarData(const unsigned char* data, unsigned int length); bool hasError() const;
virtual bool writeDMRData1(const unsigned char* data, unsigned int length);
virtual bool writeDMRData2(const unsigned char* data, unsigned int length);
virtual bool writeYSFData(const unsigned char* data, unsigned int length);
virtual bool writeP25Data(const unsigned char* data, unsigned int length);
virtual bool writeNXDNData(const unsigned char* data, unsigned int length);
virtual bool writeM17Data(const unsigned char* data, unsigned int length);
virtual bool writePOCSAGData(const unsigned char* data, unsigned int length);
virtual bool writeTransparentData(const unsigned char* data, unsigned int length); bool writeConfig();
bool writeDMRData1(const unsigned char* data, unsigned int length);
bool writeDMRData2(const unsigned char* data, unsigned int length);
bool writeDMRInfo(unsigned int slotNo, const std::string& src, bool group, const std::string& dst, const char* type);
bool writeIPInfo(const std::string& address);
virtual bool writeDStarInfo(const char* my1, const char* my2, const char* your, const char* type, const char* reflector); bool writeDMRStart(bool tx);
virtual bool writeDMRInfo(unsigned int slotNo, const std::string& src, bool group, const std::string& dst, const char* type); bool writeDMRShortLC(const unsigned char* lc);
virtual bool writeYSFInfo(const char* source, const char* dest, unsigned char dgid, const char* type, const char* origin); bool writeDMRAbort(unsigned int slotNo);
virtual bool writeP25Info(const char* source, bool group, unsigned int dest, const char* type);
virtual bool writeNXDNInfo(const char* source, bool group, unsigned int dest, const char* type);
virtual bool writeM17Info(const char* source, const char* dest, const char* type);
virtual bool writePOCSAGInfo(unsigned int ric, const std::string& message);
virtual bool writeIPInfo(const std::string& address);
virtual bool writeDMRStart(bool tx); bool writeTransparentData(const unsigned char* data, unsigned int length);
virtual bool writeDMRShortLC(const unsigned char* lc); unsigned int readTransparentData(unsigned char* data);
virtual bool writeDMRAbort(unsigned int slotNo);
virtual bool writeSerial(const unsigned char* data, unsigned int length); bool writeSerial(const unsigned char* data, unsigned int length);
unsigned int readSerial(unsigned char* data, unsigned int length);
virtual unsigned char getMode() const; unsigned char getMode() const;
virtual bool setMode(unsigned char mode); bool setMode(unsigned char mode);
virtual bool sendCWId(const std::string& callsign); bool sendCWId(const std::string& callsign);
virtual HW_TYPE getHWType() const; HW_TYPE getHWType() const;
virtual void clock(unsigned int ms); void clock(unsigned int ms);
virtual void close(); void close();
static CModem* createModem(const std::string& port, bool duplex, bool rxInvert, bool txInvert, bool pttInvert, unsigned int txDelay, unsigned int dmrDelay, bool useCOSAsLockout, bool trace, bool debug);
private: private:
std::string m_port; unsigned int m_protocolVersion;
unsigned int m_dmrColorCode; unsigned int m_dmrColorCode;
bool m_ysfLoDev;
unsigned int m_ysfTXHang;
unsigned int m_p25TXHang;
unsigned int m_nxdnTXHang;
unsigned int m_m17TXHang;
bool m_duplex; bool m_duplex;
bool m_rxInvert; bool m_rxInvert;
bool m_txInvert; bool m_txInvert;
@ -136,107 +141,55 @@ private:
unsigned int m_dmrDelay; unsigned int m_dmrDelay;
float m_rxLevel; float m_rxLevel;
float m_cwIdTXLevel; float m_cwIdTXLevel;
float m_dstarTXLevel;
float m_dmrTXLevel; float m_dmrTXLevel;
float m_ysfTXLevel;
float m_p25TXLevel;
float m_nxdnTXLevel;
float m_m17TXLevel;
float m_pocsagTXLevel;
float m_fmTXLevel;
float m_rfLevel; float m_rfLevel;
bool m_useCOSAsLockout; bool m_useCOSAsLockout;
bool m_trace; bool m_trace;
bool m_debug; bool m_debug;
unsigned int m_rxFrequency; unsigned int m_rxFrequency;
unsigned int m_txFrequency; unsigned int m_txFrequency;
unsigned int m_pocsagFrequency;
bool m_dstarEnabled; bool m_dstarEnabled;
bool m_dmrEnabled; bool m_dmrEnabled;
bool m_ysfEnabled;
bool m_p25Enabled;
bool m_nxdnEnabled;
bool m_m17Enabled;
bool m_pocsagEnabled;
bool m_fmEnabled;
int m_rxDCOffset; int m_rxDCOffset;
int m_txDCOffset; int m_txDCOffset;
CSerialController* m_serial; IModemPort* m_port;
unsigned char* m_buffer; unsigned char* m_buffer;
unsigned int m_length; unsigned int m_length;
unsigned int m_offset; unsigned int m_offset;
CRingBuffer<unsigned char> m_rxDStarData; SERIAL_STATE m_state;
CRingBuffer<unsigned char> m_txDStarData; unsigned char m_type;
CRingBuffer<unsigned char> m_rxDMRData1; CRingBuffer<unsigned char> m_rxDMRData1;
CRingBuffer<unsigned char> m_rxDMRData2; CRingBuffer<unsigned char> m_rxDMRData2;
CRingBuffer<unsigned char> m_txDMRData1; CRingBuffer<unsigned char> m_txDMRData1;
CRingBuffer<unsigned char> m_txDMRData2; CRingBuffer<unsigned char> m_txDMRData2;
CRingBuffer<unsigned char> m_rxYSFData; CRingBuffer<unsigned char> m_rxSerialData;
CRingBuffer<unsigned char> m_txYSFData; CRingBuffer<unsigned char> m_txSerialData;
CRingBuffer<unsigned char> m_rxP25Data;
CRingBuffer<unsigned char> m_txP25Data;
CRingBuffer<unsigned char> m_rxNXDNData;
CRingBuffer<unsigned char> m_txNXDNData;
CRingBuffer<unsigned char> m_rxM17Data;
CRingBuffer<unsigned char> m_txM17Data;
CRingBuffer<unsigned char> m_txPOCSAGData;
CRingBuffer<unsigned char> m_rxTransparentData; CRingBuffer<unsigned char> m_rxTransparentData;
CRingBuffer<unsigned char> m_txTransparentData; CRingBuffer<unsigned char> m_txTransparentData;
unsigned int m_sendTransparentDataFrameType; unsigned int m_sendTransparentDataFrameType;
CTimer m_statusTimer; CTimer m_statusTimer;
CTimer m_inactivityTimer; CTimer m_inactivityTimer;
CTimer m_playoutTimer; CTimer m_playoutTimer;
unsigned int m_dstarSpace;
unsigned int m_dmrSpace1; unsigned int m_dmrSpace1;
unsigned int m_dmrSpace2; unsigned int m_dmrSpace2;
unsigned int m_ysfSpace;
unsigned int m_p25Space;
unsigned int m_nxdnSpace;
unsigned int m_m17Space;
unsigned int m_pocsagSpace;
bool m_tx; bool m_tx;
bool m_cd; bool m_cd;
bool m_lockout; bool m_lockout;
bool m_error; bool m_error;
unsigned char m_mode; unsigned char m_mode;
HW_TYPE m_hwType; HW_TYPE m_hwType;
unsigned char m_capabilities1;
std::string m_fmCallsign; unsigned char m_capabilities2;
unsigned int m_fmCallsignSpeed;
unsigned int m_fmCallsignFrequency;
unsigned int m_fmCallsignTime;
unsigned int m_fmCallsignHoldoff;
float m_fmCallsignHighLevel;
float m_fmCallsignLowLevel;
bool m_fmCallsignAtStart;
bool m_fmCallsignAtEnd;
bool m_fmCallsignAtLatch;
std::string m_fmRfAck;
unsigned int m_fmAckSpeed;
unsigned int m_fmAckFrequency;
unsigned int m_fmAckMinTime;
unsigned int m_fmAckDelay;
float m_fmAckLevel;
unsigned int m_fmTimeout;
float m_fmTimeoutLevel;
float m_fmCtcssFrequency;
unsigned int m_fmCtcssHighThreshold;
unsigned int m_fmCtcssLowThreshold;
float m_fmCtcssLevel;
unsigned int m_fmKerchunkTime;
unsigned int m_fmHangTime;
unsigned int m_fmAccessMode;
bool m_fmCOSInvert;
unsigned int m_fmRFAudioBoost;
float m_fmMaxDevLevel;
bool readVersion(); bool readVersion();
bool readStatus(); bool readStatus();
bool setConfig(); bool setConfig1();
bool setConfig2();
bool setFrequency(); bool setFrequency();
bool setFMCallsignParams(); bool setFMCallsignParams();
bool setFMAckParams(); bool setFMAckParams();
bool setFMMiscParams(); bool setFMMiscParams();
bool setFMExtParams();
void printDebug(); void printDebug();

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2018 by Jonathan Naylor G4KLX * Copyright (C) 2016,2021 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
@ -16,22 +16,8 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/ */
#if !defined(NXDNAudio_H) #include "ModemPort.h"
#define NXDNAudio_H
class CNXDNAudio { IModemPort::~IModemPort()
public: {
CNXDNAudio(); }
~CNXDNAudio();
void encode(const unsigned char* in, unsigned char* out) const;
void decode(const unsigned char* in, unsigned char* out) const;
private:
void encode(const unsigned char* in, unsigned char* out, unsigned int offset) const;
void decode(const unsigned char* in, unsigned char* out, unsigned int offset) const;
};
#endif

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2016 by Jonathan Naylor G4KLX * Copyright (C) 2016,2021 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
@ -16,24 +16,25 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/ */
#if !defined(P25Audio_H) #ifndef ModemPort_H
#define P25Audio_H #define ModemPort_H
#include "AMBEFEC.h" class IModemPort {
class CP25Audio {
public: public:
CP25Audio(); virtual ~IModemPort() = 0;
~CP25Audio();
unsigned int process(unsigned char* data); virtual bool open() = 0;
void encode(unsigned char* data, const unsigned char* imbe, unsigned int n); virtual int read(unsigned char* buffer, unsigned int length) = 0;
void decode(const unsigned char* data, unsigned char* imbe, unsigned int n); virtual int write(const unsigned char* buffer, unsigned int length) = 0;
virtual void close() = 0;
#if defined(__APPLE__)
virtual int setNonblock(bool nonblock) = 0;
#endif
private: private:
CAMBEFEC m_fec;
}; };
#endif #endif

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2016 by Jonathan Naylor G4KLX * Copyright (C) 2016,2020,2021 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,22 +21,22 @@
#include <cstdio> #include <cstdio>
#include <cassert> #include <cassert>
CModemSerialPort::CModemSerialPort(CModem* modem) : IModemSerialPort::IModemSerialPort(CModem* modem) :
m_modem(modem) m_modem(modem)
{ {
assert(modem != NULL); assert(modem != NULL);
} }
CModemSerialPort::~CModemSerialPort() IModemSerialPort::~IModemSerialPort()
{ {
} }
bool CModemSerialPort::open() bool IModemSerialPort::open()
{ {
return true; return true;
} }
int CModemSerialPort::write(const unsigned char* data, unsigned int length) int IModemSerialPort::write(const unsigned char* data, unsigned int length)
{ {
assert(data != NULL); assert(data != NULL);
assert(length > 0U); assert(length > 0U);
@ -46,7 +46,7 @@ int CModemSerialPort::write(const unsigned char* data, unsigned int length)
return ret ? int(length) : -1; return ret ? int(length) : -1;
} }
int CModemSerialPort::read(unsigned char* data, unsigned int length) int IModemSerialPort::read(unsigned char* data, unsigned int length)
{ {
assert(data != NULL); assert(data != NULL);
assert(length > 0U); assert(length > 0U);
@ -54,6 +54,6 @@ int CModemSerialPort::read(unsigned char* data, unsigned int length)
return m_modem->readSerial(data, length); return m_modem->readSerial(data, length);
} }
void CModemSerialPort::close() void IModemSerialPort::close()
{ {
} }

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2016 by Jonathan Naylor G4KLX * Copyright (C) 2016,2020,2021 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
@ -22,10 +22,10 @@
#include "SerialPort.h" #include "SerialPort.h"
#include "Modem.h" #include "Modem.h"
class CModemSerialPort : public ISerialPort { class IModemSerialPort : public ISerialPort {
public: public:
CModemSerialPort(CModem* modem); IModemSerialPort(CModem* modem);
virtual ~CModemSerialPort(); virtual ~IModemSerialPort();
virtual bool open(); virtual bool open();

2339
NXDN.csv

File diff suppressed because it is too large Load diff

View file

@ -1,577 +0,0 @@
/*
* Copyright (C) 2018 by Jonathan Naylor G4KLX
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "NXDNAudio.h"
#include "Golay24128.h"
#include <cstdio>
#include <cassert>
#include <cstring>
const unsigned char BIT_MASK_TABLE[] = { 0x80U, 0x40U, 0x20U, 0x10U, 0x08U, 0x04U, 0x02U, 0x01U };
#define WRITE_BIT(p,i,b) p[(i)>>3] = (b) ? (p[(i)>>3] | BIT_MASK_TABLE[(i)&7]) : (p[(i)>>3] & ~BIT_MASK_TABLE[(i)&7])
#define READ_BIT(p,i) (p[(i)>>3] & BIT_MASK_TABLE[(i)&7])
const unsigned int PRNG_TABLE[] = {
0x42CC47U, 0x19D6FEU, 0x304729U, 0x6B2CD0U, 0x60BF47U, 0x39650EU, 0x7354F1U, 0xEACF60U, 0x819C9FU, 0xDE25CEU,
0xD7B745U, 0x8CC8B8U, 0x8D592BU, 0xF71257U, 0xBCA084U, 0xA5B329U, 0xEE6AFAU, 0xF7D9A7U, 0xBCC21CU, 0x4712D9U,
0x4F2922U, 0x14FA37U, 0x5D43ECU, 0x564115U, 0x299A92U, 0x20A9EBU, 0x7B707DU, 0x3BE3A4U, 0x20D95BU, 0x6B085AU,
0x5233A5U, 0x99A474U, 0xC0EDCBU, 0xCB5F12U, 0x918455U, 0xF897ECU, 0xE32E3BU, 0xAA7CC2U, 0xB1E7C9U, 0xFC561DU,
0xA70DE6U, 0x8DBE73U, 0xD4F608U, 0x57658DU, 0x0E5E56U, 0x458DABU, 0x7E15B8U, 0x376645U, 0x2DFD86U, 0x64EC3BU,
0x3F1F60U, 0x3481B4U, 0x4DA00FU, 0x067BCEU, 0x1B68B1U, 0xD19328U, 0xCA03FFU, 0xA31856U, 0xF8EB81U, 0xF9F2F8U,
0xA26067U, 0xA91BB6U, 0xF19A59U, 0x9A6148U, 0x8372B6U, 0xC8E86FU, 0x9399DCU, 0x1A0291U, 0x619142U, 0x6DE9FFU,
0x367A2CU, 0x7D2511U, 0x6484DAU, 0x2F1F0FU, 0x1E6DB4U, 0x55F6E1U, 0x0EA70AU, 0x061C96U, 0xDD0E45U, 0xB4D738U,
0xAF64ABU, 0xE47F42U, 0xFDBE9DU, 0xB684ACU, 0xFE5773U, 0xC1E4A2U, 0x8AFD0DU, 0x932ED4U, 0xD814E3U, 0x81853AU,
0x225EECU, 0x7A6945U, 0x31A112U, 0x2AB2EBU, 0x630974U, 0x785AB5U, 0x11E3CEU, 0x4A715BU, 0x402AA0U, 0x199B7DU,
0x16C05EU, 0x6F5283U, 0xA4FB10U, 0xBFA8ECU, 0xF633B7U, 0xEC4012U, 0xADD8C9U, 0xD6EB1CU, 0xDD3027U, 0x84A1FAU,
0xCF9E19U, 0xD64C80U, 0xBC4557U, 0xA7B62EU, 0x6E2DA1U, 0x311F50U, 0x38C68EU, 0x63D5BFU, 0x486E60U, 0x10BFE1U,
0x5BAD1EU, 0x4A4647U, 0x0157F0U, 0x7ACC29U, 0x73BEEAU, 0x2825D7U, 0xA0940CU, 0xFBCFF9U, 0xB05C62U, 0x892426U,
0xC6B3DDU, 0xDF3840U, 0x9449B3U, 0xCED3BEU, 0xE7804DU, 0xBC3B90U, 0xF5AA0BU, 0xE6D17EU, 0x2D43B5U, 0x345A04U,
0x5EA9DBU, 0x07A202U, 0x0C7134U, 0x45C9FDU, 0x5EDA0AU, 0x310193U, 0x6830C4U, 0x62AA3DU, 0x3B59B2U, 0xB04043U,
0xEB975CU, 0x82BCADU, 0x912E62U, 0xD8F7FBU, 0x82C489U, 0x895F54U, 0xF00FE7U, 0xFBBC2AU, 0xA2E771U, 0xE956C4U,
0xF6CD1FU, 0x3F8FEAU, 0x0534E1U, 0x4C653CU, 0x17FE8FU, 0x1C4C52U, 0x4515A1U, 0x2E86A9U, 0x3FBD56U, 0x756C87U,
0x6ED218U, 0x279179U, 0x7C0AA6U, 0xD53B17U, 0x8EE0C8U, 0x85F291U, 0xD94B36U, 0x9298EFU, 0xAB8318U, 0xE07301U,
0xBB68DFU, 0xB2CB7CU, 0xE910A5U, 0xE101D2U, 0x92BB4BU, 0x59E8B4U, 0x407175U, 0x0B026AU, 0x12989BU, 0x792944U,
0x2376EDU, 0x2EF5BAU, 0x758663U, 0x7C1ED5U, 0x078D0CU, 0x4EF6ABU, 0x5567F2U, 0x9F7C29U, 0xC68E9CU, 0xC51747U,
0xBC6422U, 0xB7EFB9U, 0xECFD44U, 0xA50497U, 0xAF178AU, 0xD68C69U, 0xD97DB5U, 0x82670EU, 0xCBB45BU, 0x508D90U,
0x190A25U, 0x63F0FEU, 0x68E3C7U, 0x317A10U, 0x3A09D9U, 0x6B926EU, 0x004237U, 0x1B79C8U, 0x53EA59U, 0x48B3B7U,
0x811166U, 0xDE4A79U, 0xF5F988U, 0xAC6057U, 0xE733FEU, 0xFF89ADU, 0xB49830U, 0x8F4BC3U, 0xC6F00EU, 0x9DA135U,
0x942FE0U, 0xC71C3BU, 0x4DC78FU, 0x3476C4U, 0x7F6C39U, 0x66BFAAU, 0x298657U, 0x725504U, 0x5B4E89U, 0x01FE72U,
0x0835A3U, 0x53269CU, 0x189D4DU, 0x01CDC2U, 0xEA763BU, 0xF3A56DU, 0xB0BCD4U, 0xE80F13U, 0xE355CAU, 0x98C47DU,
0x91AB24U, 0xCE38DBU, 0x87A35AU, 0x9CD3A5U, 0xD648F4U, 0xAF7B6FU, 0x24A292U, 0x7D3011U, 0x764B6DU, 0x2DDABEU,
0x44D123U, 0x5E22D8U, 0x1FB09DU, 0x04A926U, 0x4F5AF3U, 0x064128U, 0x3DB105U, 0x70AAD6U, 0xAA392FU, 0xA1C4B8U,
0xF8C7C0U, 0xD35D0FU, 0x8A2E9EU, 0xC1B761U, 0xDA44F0U, 0x925E8FU, 0x89CF4EU, 0xE8B4D1U, 0xB32728U, 0xB8FE7FU,
0x61DCC6U, 0x2A4701U, 0x1614D8U, 0x5DADE2U, 0x46BE37U, 0x0F44DCU, 0x54D549U, 0x5D8E32U, 0x263DAFU, 0x2C237CU,
0x75E291U, 0xBE5982U, 0xA74A7FU, 0xC493A4U, 0xDFA131U, 0x967A5AU, 0xCCCB8EU, 0xC1D835U, 0x9A02ECU, 0xF331BBU,
0xE8B812U, 0xA3EBC5U, 0xBA507CU, 0x7080ABU, 0x099BC2U, 0x02285DU, 0x59718CU, 0x50C273U, 0x0B1862U, 0x4A1F8CU,
0x70A655U, 0x3BF5C2U, 0x666FBBU, 0x6DDE68U, 0x3485C5U, 0x9F161EU, 0xC46F4BU, 0x8CFDF0U, 0x97C625U, 0xDE058EU,
0xC59CD3U, 0xAEAE20U, 0xF775BCU, 0xFC647FU, 0xBD9F02U, 0xE70C91U, 0xCC1468U, 0x11E7B7U, 0x1AFC36U, 0x435B49U,
0x080398U, 0x139027U, 0x7B63FEU, 0x607AF9U, 0x29E900U, 0x7293D6U, 0x79026FU, 0x00D930U, 0x0BEAF1U, 0xD3614EU,
0x90119FU, 0x8B8AE4U, 0xC61969U, 0xBD609AU, 0xB4F247U, 0xEFA954U, 0xE518A9U, 0xBC0362U, 0xD7D0D6U, 0xCE7E8DU,
0x856F18U, 0x1C94E3U, 0x578726U, 0x0D5F1DU, 0x24ECC0U, 0x7FF713U, 0x3E26AAU, 0x251D6DU, 0x6A8F14U, 0x53648BU,
0x19757AU, 0x40AEB4U, 0xCB9CA5U, 0x90055AU, 0x9956C3U, 0xE2ED34U, 0xAB3C7DU, 0xB126EAU, 0xFA9513U, 0xA3D2C8U,
0x886BFDU, 0xD9F836U, 0xD2A2E3U, 0x8D1359U, 0x454804U, 0x5EDBF7U, 0x37637AU, 0x2C3089U, 0x67ABD4U, 0x3E8847U,
0x3551BAU, 0x4D6331U, 0x46B8C4U, 0x1D299FU, 0x54120EU, 0x5FC0E1U, 0x86D93BU, 0xE56A0EU, 0xFBB1D5U, 0xB2B600U,
0xA94EABU, 0xE05DF6U, 0x9BE605U, 0x90B798U, 0xC92C6BU, 0xC3DE66U, 0x9AC7BDU, 0xD15448U, 0x6A3FD3U, 0x23ADA3U,
0x78346CU, 0x7147F5U, 0x2BDC02U, 0x0EAD5BU, 0x553FFCU, 0x1EA425U, 0x07D5F2U, 0x4C4ECBU, 0x554C14U, 0x3EB3F5U,
0xE4A26AU, 0xED799BU, 0xB6CA85U, 0xFFD25CU, 0xC421BFU, 0x8F3A22U, 0x96AB51U, 0xDC518CU, 0x895217U, 0x8289F2U,
0xF9B8A9U, 0xF0231CU, 0x2BF1C7U, 0x62C80AU, 0x781B39U, 0x1320E5U, 0x4AB156U, 0x41EB8FU, 0x1848E0U, 0x13D771U,
0x4886AEU, 0x203C5FU, 0x3B6F40U, 0x76F6A1U, 0xE5457EU, 0xAE1EE7U, 0xD7AC10U, 0xDCB549U, 0x8476EFU, 0x8FC536U,
0xD49DE9U, 0x9D0ED8U, 0xA63513U, 0xEFE4A6U, 0xB4DF7DU, 0x3E0D00U, 0x779693U, 0x4CA75EU, 0x0568ADU, 0x527BB0U,
0x59C34BU, 0x00109FU, 0x0A0B14U, 0x73FA61U, 0x38E0BAU, 0x23530FU, 0x6A88D4U, 0xB199DDU, 0x98322AU, 0xC260F3U,
0xCBF944U, 0x908A0DU, 0xDB11F2U, 0xC28163U, 0xADFABDU, 0xBC694CU, 0xF65243U, 0xAD83BAU, 0xA40D6DU, 0x5F7EF4U,
0x16E787U, 0x0DF44AU, 0x460EF1U, 0x5E1F24U, 0x15CC3FU, 0x6C77CAU, 0x676401U, 0x3C9CBDU, 0x359FEEU, 0x6A0413U,
0x02F590U, 0x91EE4DU, 0xDA3C3EU, 0xC305A3U, 0x889658U, 0xF14D99U, 0xFA7F86U, 0xA1E677U, 0xE981E8U, 0xF21A10U,
0xBB4BD7U, 0x80F1CEU, 0xCB6239U, 0x123BE0U, 0x1D885FU, 0x45921EU, 0x6641E1U, 0x3DE870U, 0x74BBAFU, 0x6F00C6U,
0x261055U, 0x7DCBA8U, 0x57787AU, 0x0E2167U, 0x05B28CU, 0xCC8819U, 0x975BE2U, 0xBC52B7U, 0xE5E52CU, 0xEB37C9U,
0xB20E12U, 0xF9DD2FU, 0xE8C6FCU, 0x837701U, 0xD8AD82U, 0xD1BE5AU, 0x0B0525U, 0x0244B4U, 0x79FE5BU, 0x322DCAU,
0x2B3495U, 0x60876CU, 0x79DCFBU, 0x334C12U, 0x4C7745U, 0x45A4DCU, 0x1E3F23U, 0x175FF2U, 0xC4C0D8U, 0xAFF30DU,
0xB72AF6U, 0xFCB96BU, 0xA5C338U, 0xAE5295U, 0xF54946U, 0xDCBABBU, 0x87A1A8U, 0xCF2165U, 0xD4DA9EU, 0x9FC90BU,
0x223070U, 0x6922A4U, 0x30B92FU, 0x3348D6U, 0x695B01U, 0x20C038U, 0x1BB2EFU, 0x523B06U, 0x49EC99U, 0x02D7C8U,
0x5B4777U, 0x713CA6U, 0xA8AF49U, 0xA3B650U, 0xF84586U, 0xB5DF7FU, 0xAE8CF8U, 0xC72581U, 0x9D3652U, 0x9EEDCFU,
0xC75D34U, 0xCC0671U, 0xB5B5CAU, 0xFEAC1FU, 0x677EA4U, 0x2DC5F9U, 0x26D63AU, 0x7F1F86U, 0x142855U, 0x0DF2A8U,
0x42E3B3U, 0x195872U, 0x108B8DU, 0x6AB31CU, 0x632063U, 0x307BAAU, 0xFBC83DU, 0xE201C4U, 0xA91393U, 0x90A82AU,
0xDAF9E4U, 0x816A55U, 0x88D00AU, 0xD383DBU, 0xFA3A64U, 0xA569A5U, 0xEEE2DEU, 0x76D243U, 0x3D0D90U, 0x649E6DU,
0x47E76EU, 0x1C7491U, 0x156E49U, 0x4E9DDEU, 0x0604B7U, 0x3D3720U, 0x76FDD9U, 0x6FEC06U, 0x2417B7U, 0xFD04F8U,
0xF29D29U, 0x886F92U, 0xC1744FU, 0xDAC73CU, 0x939EB1U, 0x880C63U, 0xEBE79EU, 0xB2F285U, 0xB86970U, 0xE11ABBU,
0xEA822EU, 0x311155U, 0x586AC0U, 0x43F92BU, 0x0A81F6U, 0x5412C5U, 0x5D111CU, 0x26E8CBU, 0x2D7B63U, 0x74213CU,
0x3F90CDU, 0x2E8B52U, 0x645883U, 0xDFE36CU, 0x96F375U, 0xDD0882U, 0xC40B1BU, 0x8FD6CCU, 0xB464A5U, 0xFC7F3EU,
0xA7AECBU, 0xAA9511U, 0xF10634U, 0xBA5CEFU, 0x83ED32U, 0x483681U, 0x5015DCU, 0x138D3FU, 0x48DEA2U, 0x616571U,
0x3AF40CU, 0x33AF97U, 0x681D72U, 0x2246E9U, 0x3BD7B9U, 0x506C46U, 0x0D2FDFU, 0x869338U, 0xDDC061U, 0xD45BD6U,
0xAF6A0FU, 0xE7B8C0U, 0xFC2371U, 0xBF102EU, 0xA6C9DFU, 0xEDDA40U, 0x943089U, 0x9FA1BFU, 0x459A66U, 0x0C4995U,
0x175108U, 0x7AE243U, 0x6139B6U, 0x2A2A2DU, 0x73D3D8U, 0x79C183U, 0x204A26U, 0x0B3FFDU, 0x5AA420U, 0x111613U,
0x8A4FDFU, 0xC3DC2CU, 0xF9A7B5U, 0xB034EAU, 0xEBAC5BU, 0xE0CF94U, 0xBD5465U, 0xF605FAU, 0xCFBEA3U, 0x85AC54U,
0x9E55DDU, 0xD7C62AU, 0x0CDD73U, 0x252FCDU, 0x76361CU, 0x7DF5D3U, 0x3546E2U, 0x6E5B39U, 0x67A98CU, 0x1CB247U,
0x57231AU, 0x4AD8A9U, 0x01CA74U, 0x191187U, 0xF2208AU, 0xA9AB50U, 0xA0F8A5U, 0xFB403EU, 0xF2D34BU, 0xA9A880U,
0xCB393DU, 0xD262EEU, 0x99D0B7U, 0xC04B00U, 0xCB1AC9U, 0xB0B176U, 0x39E3A7U, 0x677EF8U, 0x2ECD58U, 0x359687U,
0x7E277EU, 0x473D69U, 0x0CEEB0U, 0x55D557U, 0x5F04CEU, 0x0C8EBDU, 0x25BD60U, 0x7E64DBU, 0xB7771EU, 0xACCC05U,
0xE51CF0U, 0xBF2F2AU, 0x90F497U, 0xC9E7D4U, 0xC25F09U, 0x9B9CBAU, 0xD08767U, 0xEB320CU, 0xA36999U, 0x38FB42U,
0x7180B3U, 0x22112CU, 0x29AA45U, 0x50F9D2U, 0x1B610AU, 0x0202FDU, 0x4899E4U, 0x57080BU, 0x3E72DAU, 0x65E165U,
0x6CFA34U, 0xB70BEBU, 0xBC104AU, 0xE4E295U, 0x8F7BECU, 0x96787FU, 0xD583B2U, 0x9E9740U, 0x870C5DU, 0xECFFA6U,
0xF4E433U, 0xBF35F8U, 0xE00F8DU, 0x699C16U, 0x3265EBU, 0x1B6638U, 0x40F515U, 0x0A8DC6U, 0x131E1BU, 0x5845A0U,
0x21F670U, 0x2A6E1FU, 0x791D8EU, 0x708651U, 0x2AD7E8U, 0xE37CAFU, 0xD8EE56U, 0x97B3C1U, 0x8E0018U, 0xC51B6FU,
0x9CC9E6U, 0xB67019U, 0xEF23C8U, 0xE498F2U, 0xBF9927U, 0xF643ECU, 0xCD7051U, 0x04E902U, 0x563AFFU, 0x5D006CU,
0x04D3A1U, 0x0FCA9AU, 0x72794FU, 0x39A2B4U, 0x228231U, 0x6A19EAU, 0x714E96U, 0x18F705U, 0x4324FCU, 0xC83E3BU,
0x918D02U, 0xDADCD5U, 0xC2470CU, 0xA135B3U, 0xBABCF2U, 0xF30F4DU, 0xA8549EU, 0xA1C543U, 0xDEFF78U, 0xD42CBCU,
0x0DB747U, 0x46C6D2U, 0x5F5C89U, 0x144F60U, 0x6FA6F7U, 0x66350EU, 0x2C0A59U, 0x35DAE0U, 0x7EC12FU, 0x0D32FEU,
0x0429C1U, 0x5FB911U, 0xD642AEU, 0x895167U, 0xC3D8B0U, 0xFAAB89U, 0xB1315AU, 0xA8C0A7U, 0xE3DB24U, 0xB84879U,
0x913382U, 0xCBA317U, 0x82F8FCU, 0x994BA9U, 0x50C213U, 0x4390CEU, 0x282F5DU, 0x713E30U, 0x7FCDE3U, 0x26565EU,
0x2D0485U, 0x56BDD4U, 0x1FAE7BU, 0x0475AAU, 0x4DD555U, 0x17CE4CU, 0x9C1D9BU, 0xE52473U, 0xEEF7E4U, 0xB7CD1DU,
0xF45E42U, 0xEF87E3U, 0x87B43CU, 0x986FADU, 0xD16FD2U, 0x8AD403U, 0x8103A8U, 0xD83A75U, 0x33A826U, 0x2BF39BU,
0x604049U, 0x7B99A4U, 0x328ABFU, 0x49306AU, 0x407191U, 0x1BEA04U, 0x19D96FU, 0x4001F2U, 0x0FB201U, 0x36E9DCU,
0xFD7ADFU, 0xE64326U, 0xAF91F9U, 0xF51249U, 0xDC2B16U, 0x87F8D7U, 0xCCE668U, 0xC517B1U, 0x9E8C46U, 0x97BF5FU,
0xED6498U, 0xA67461U, 0x378FF6U, 0x788C8FU, 0x611514U, 0x0AE6F1U, 0x53FC2BU, 0x596F3EU, 0x0216C5U, 0x4B8508U,
0x507FBBU, 0x396EE6U, 0x22F535U, 0xE99688U, 0xB10F43U, 0xBA1D36U, 0xC3E2ADU, 0xC07178U, 0x9B28C3U, 0xD69A8BU,
0xCD817CU, 0x8570E5U, 0xFEEB12U, 0xF5E8CBU, 0xAC10C4U, 0x270335U, 0x7ED8EAU, 0x156B5BU, 0x0E7A14U, 0x46A0C5U,
0x5D937AU, 0x144AA3U, 0x4F79D5U, 0x6CF35CU, 0x31228FU, 0x7A1932U, 0x628E69U, 0xA9D59CU, 0x926517U, 0xDBBEE2U,
0x80ADB9U, 0x891424U, 0xD246D7U, 0xD8ED1AU, 0xA17C28U, 0xEA27F5U, 0xF3942EU, 0xB8CE8FU, 0xAB5FD0U, 0x466461U,
0x1CB7BEU, 0x152F6FU, 0x4E1CC0U, 0x05D799U, 0x1CE66EU, 0x773DF7U, 0x7EAB00U, 0x249048U, 0x6D41D7U, 0x765A26U,
0x1DA9F9U, 0x8431C8U, 0xCF0203U, 0x96C1DEU, 0x90D86DU, 0xCB6A30U, 0xA23193U, 0xB9A24EU, 0xF05B95U, 0xEB48A0U,
0xA0D27AU, 0xD8A39FU, 0xD33804U, 0x0A9B79U, 0x01C3AAU, 0x5A5437U, 0x132FD4U, 0x28BC0DU, 0x60253AU, 0x3F57E3U,
0x3CCC7CU, 0x65DD9DU, 0x4E26C2U, 0x172572U, 0xDCDDADU, 0xC64E64U, 0x8F5553U, 0x94A68AU, 0xFDBE7DU, 0xA66DE4U,
0xADD68BU, 0xF4C75AU, 0xFE0CC1U, 0x873E34U, 0xC8A72FU, 0xDBD0C2U, 0x124B10U, 0x49998DU, 0x40A8FEU, 0x3A3323U,
0x316088U, 0x68D95DU, 0x235B06U, 0x3A00B3U, 0x51B178U, 0x4AEA89U, 0x025816U, 0x59C36FU, 0xD092B8U, 0x8B2930U,
0xE43AC7U, 0xF5E2DEU, 0xBEC121U, 0xA71AF0U, 0xED8B7FU, 0x94B40EU, 0x9F66D1U, 0xD45D68U, 0xCD8CBFU, 0x8617F6U,
0x5F2545U, 0x75FC98U, 0x2EFF62U, 0x674467U, 0x7C959CU, 0x318F09U, 0x0A7CD2U, 0x4967AFU, 0x11D62CU, 0x1A8CD1U,
0x431F02U, 0x48A69DU, 0xB3E5ECU, 0xFA7623U, 0xE10E9AU, 0xA99948U, 0xB20215U, 0xD971A6U, 0x80E86BU, 0x8BDA90U,
0xD60185U, 0x9D907EU, 0x8FFBFBU, 0xE66920U, 0x7D705DU, 0x3483CEU, 0x6F9833U, 0x646BF1U, 0x1DF3E8U, 0x17E017U,
0x4E1BC6U, 0x050A79U, 0x1E8038U, 0x5773E7U, 0x2C685EU, 0xA1BD89U, 0xFB86B0U, 0xF01477U, 0xA16D8EU, 0xCAFE19U,
0xD365C1U, 0x9815AEU, 0x839E3FU, 0xCBCDC4U, 0x907611U, 0xB9E70AU, 0xE2BDE7U, 0x2B0E34U, 0x301789U, 0x7BE4DAU,
0x477707U, 0x0C2FACU, 0x558C79U, 0x5E9743U, 0x0D4496U, 0x04786DU, 0x7FABE0U, 0x3730B3U, 0x3C014AU, 0xE7DADDU,
0xEEE834U, 0x956163U, 0xDCB2FAU, 0xC78905U, 0x8D5BD4U, 0xD0427BU, 0xDBF12BU, 0xA22AB4U, 0xA93B4DU, 0xFA819AU,
0xB3D2B3U, 0x287B64U, 0x40289DU, 0x5BB206U, 0x100153U, 0x495CB8U, 0x42CF2DU, 0x3BF4D6U, 0x70248BU, 0x6ABF19U,
0x23CCF4U, 0x3C4527U, 0x75761AU, 0x8EACC1U, 0x853F44U, 0xD44EBFU, 0xDED5EEU, 0x87C751U, 0xEC3E80U, 0xF72D6FU,
0xBEB676U, 0xE557A1U, 0xEC4D59U, 0xB6BECEU, 0x9DA527U, 0x443078U, 0x0BCAE9U, 0x12D916U, 0x594087U, 0x6033E8U,
0x22A831U, 0x7948A2U, 0x70535FU, 0x2BC01CU, 0x62BBA1U, 0x592A7BU, 0x92308EU, 0x8AC395U, 0xC15A50U, 0x9809ABU,
0xB3B336U, 0xECB245U, 0xE54998U, 0xBEDA1BU, 0xF681E6U, 0xED35F5U, 0x8E2E0CU, 0x87FDD3U, 0x5CC453U, 0x1556ACU,
0x0E85FDU, 0x64AC42U, 0x3D7F8BU, 0x36447CU, 0x6FD665U, 0x640FB2U, 0x3B3C4BU, 0x52A7C4U, 0x48F7B5U, 0x014C2EU,
0x9A9FFBU, 0xD19601U, 0xA0250CU, 0xAB7FFFU, 0xF2C822U, 0xB8D1B1U, 0xA302CCU, 0xEAB907U, 0xD1E9B2U, 0x987269U,
0xC3411CU, 0xCC8897U, 0x141A42U, 0x3F61B8U, 0x66F2A1U, 0x2DCB56U, 0x3618DFU, 0x778208U, 0x2CB3F1U, 0x0468EEU,
0x5F7B1FU, 0x5693D0U, 0x0D8041U, 0x461B3EU, 0xFFECE7U, 0xB4FD50U, 0xA94798U, 0xE314CFU, 0xB88D76U, 0xB17EADU,
0xCA7508U, 0xC3E553U, 0x989EA6U, 0xDB0D3DU, 0xC396E8U, 0xA8E683U, 0x717D1EU, 0x7A0EEDU, 0x219730U, 0x288422U,
0x736ECFU, 0x1BFF14U, 0x04A4A1U, 0x4F177AU, 0x56092BU, 0x1DD884U, 0x64635DU, 0xEF70EAU, 0xA589B3U, 0xF49B54U,
0xFF50CDU, 0xA66312U, 0x8DFA62U, 0xD628FDU, 0x9F131CU, 0x8582C3U, 0xCCF9DAU, 0xF36A29U, 0xB8B2F4U, 0x618157U,
0x6A020AU, 0x335999U, 0x79E864U, 0x4272BFU, 0x03259AU, 0x189C40U, 0x51CFB5U, 0x0A752EU, 0x216463U, 0x79BF90U,
0x721C0DU, 0xAB47FEU, 0xE4D727U, 0xFDEC28U, 0x963FD9U, 0x8DA646U, 0xC594B7U, 0x9E4FE8U, 0x977E60U, 0xECA597U,
0xAF264EU, 0xB61C79U, 0xFDCDA0U, 0x65D64FU, 0x2E61DCU, 0x553881U, 0x5CAA72U, 0x0351FBU, 0x0A400CU, 0x51FB55U,
0x3BB9CAU, 0x22223AU, 0x6993B5U, 0x30C8C4U, 0x3B5B1BU, 0xE02B82U, 0xC1B075U, 0x9B23BCU, 0xD25A8BU, 0xC9C852U,
0x82A3A9U, 0xBB303CU, 0xF42977U, 0xADDA82U, 0xA64418U, 0xFC55E5U, 0xB5AEE6U, 0x0EBD3BU, 0x4765C8U, 0x4CD655U,
0x17DD2EU, 0x562EEBU, 0x6C3770U, 0x25A585U, 0x3E5EDEU, 0x754F6FU, 0x2C94A1U, 0x23A758U, 0x5A3F4FU, 0xD07C96U,
0x8BC761U, 0xC254E8U, 0xD92C97U, 0xB0BF06U, 0xEBE0D9U, 0xE25138U, 0xB8CAA7U, 0xBB98DEU, 0xE22109U, 0x896291U,
0x10F172U, 0x5BCB2FU, 0x401A94U, 0x0CA141U, 0x77B2BAU, 0x7E6BBFU, 0x255964U, 0x6E82D9U, 0x77130AU, 0x3C3877U,
0x04EAF4U, 0x4FD129U, 0x9C40DBU, 0x959BC6U, 0xCEAC2DU, 0xE774FCU, 0xBC6763U, 0xF6DC12U, 0xEB8DCDU, 0xA00664U,
0xF9F4B3U, 0xD2EF4AU, 0x895E5DU, 0x800584U, 0x5A972BU, 0x132EFBU, 0x287D84U, 0x63E615U, 0x7297CEU, 0x391D23U,
0x608E30U, 0x6AF5CDU, 0x11641EU, 0x5C5E93U, 0x4789E0U, 0x0E903DU, 0x956386U, 0xFEF053U, 0xB6E879U, 0xAD0BACU,
0xE41077U, 0xFF83CAU, 0xB47A99U, 0xCD6870U, 0xCE93E7U, 0x96823EU, 0x9D1941U, 0xC4EBD0U, 0x2BF23FU, 0x3031EEU,
0x790A71U, 0x229909U, 0x2AC1CEU, 0x717677U, 0x5AEDA0U, 0x039C99U, 0x480646U, 0x515587U, 0x1AEC3CU, 0x296F69U,
0xE13492U, 0xBA8607U, 0xB39FCCU, 0xEC4CB1U, 0xA77723U, 0x9EA7DEU, 0xD51C0DU, 0xCD0F00U, 0x86D4FBU, 0xDDF56EU,
0xF46F95U, 0x2FBCD4U, 0x268D6BU, 0x7D52B2U, 0x374165U, 0x26F9DCU, 0x4D2A9BU, 0x141163U, 0x1FD2FCU, 0x40CA2DU,
0x497952U, 0x3322D3U, 0x7AB32CU, 0xE108F5U, 0xAA5AE2U, 0xB3E31BU, 0xF8B098U, 0x812B65U, 0x8B8936U, 0xD0D08AU,
0xD94341U, 0x8A7894U, 0xE3A9AFU, 0xF8377AU, 0xB74481U, 0x6FDD0CU, 0x64EE5FU, 0x3D35A2U, 0x163731U, 0x5F8ECCU,
0x045DC7U, 0x0F4616U, 0x57B6E8U, 0x7CAD79U, 0x253E86U, 0x6EC7CFU, 0x7DD478U, 0xB426A1U, 0xCF2D76U, 0xC3BC5FU,
0x984780U, 0x935571U, 0xCACCEEU, 0x81BBBFU, 0xB82054U, 0xF371C0U, 0xE9CB3BU, 0xA05826U, 0xFB33F5U, 0x52A218U,
0x09B88BU, 0x424BF6U, 0x53D22DU, 0x198198U, 0x043A53U, 0x6F2A06U, 0x34F1BDU, 0x3DC260U, 0x664982U, 0x6FB81BU,
0x15A24CU, 0xDE71F5U, 0xC7482AU, 0x8CDFCBU, 0x9505D4U, 0xDE3405U, 0xA5EFFAU, 0xA4FC63U, 0xFE5704U, 0xB387DDU,
0xA8BC6AU, 0xC32FB2U, 0x5A7EE5U, 0x11C44CU, 0x489797U, 0x420E62U, 0x19BD79U, 0x30E6BCU, 0x6B6407U, 0x225DDAU,
0x398EA9U, 0x703534U, 0x0A64F7U, 0x09FA0AU, 0xD4C910U, 0xDF10E5U, 0x86833EU, 0xCDB99BU, 0xE67A40U, 0xBE631BU,
0xB590AEU, 0xEC8B75U, 0xA73BD0U, 0x9CE08BU, 0xD5F35EU, 0x8E0AE5U, 0x061828U, 0x5D835AU, 0x5660C7U, 0x277914U,
0x68CAE9U, 0x7190E2U, 0x3A0113U, 0x20FECCU, 0x49ED7DU, 0x127522U, 0x1B06ABU, 0x40855CU, 0x8B9E85U, 0x926FB2U,
0xF8F56AU, 0xE186A5U, 0xAA1F14U, 0xF10CCBU, 0xF0F7BAU, 0x8F6735U, 0x867CECU, 0xDC9F1FU, 0x978402U, 0x8E54F1U,
0x45EF3CU, 0x7CFC8FU, 0x3705D2U, 0x6C1248U, 0x64C8BDU, 0x3FF976U, 0x566243U, 0x4DA198U, 0x069B45U, 0x1F0AF6U,
0x5851BBU, 0x00E248U, 0xAB3BD1U, 0xF2090EU, 0xF9926FU, 0xA2C3F1U, 0xEB7800U, 0xD07B9FU, 0x98A1E6U, 0xC31021U,
0xC84BB8U, 0x91D84FU, 0x9AEC96U, 0x6337A9U, 0x288468U, 0x369FB3U, 0x774E06U, 0x6C645DU, 0x05B7A9U, 0x4E2E22U,
0x551DFFU, 0x1CC78CU, 0x47D611U, 0x4F2DF2U, 0x343E6FU, 0xBF8514U, 0xE655C1U, 0xAD5E5AU, 0xB4EDBFU, 0xDFB4E4U,
0xC1265DU, 0x80DD8BU, 0xDBC852U, 0xD25375U, 0x8920ACU, 0xA2BA53U, 0xFB0BC2U, 0x31401DU, 0x28D33CU, 0x63AAE3U,
0x18381AU, 0x11238DU, 0x4AD2E4U, 0x434933U, 0x195BABU, 0x56A058U, 0x6FB105U, 0x2C5AAEU, 0x35C97BU, 0xFED9A0U,
0xA52295U, 0x8D314EU, 0xD6ECA3U, 0x9F5E30U, 0x84456DU, 0xCFB6DEU, 0xD6AF03U, 0xBD2CE9U, 0xE556FCU, 0xEEC707U,
0xB71CD6U, 0x382F59U, 0x43B720U, 0x02E4F7U, 0x195F4EU, 0x51CC99U, 0x0AA550U, 0x013767U, 0x786CBEU, 0x73DD01U,
0x2AC6D1U, 0x61159EU, 0x7BA92FU, 0x92BAF4U, 0x896109U, 0xC0521AU, 0x9F9AF7U, 0x942924U, 0xC532B9U, 0xEFE3C2U,
0xA6D807U, 0xFD0ABCU, 0xF69369U, 0xAFA033U, 0x44738EU, 0x5D694DU, 0x17C8F0U, 0x0C93A3U, 0x45207AU, 0x1EF9C5U,
0x37EB04U, 0x6850FBU, 0x6305EAU, 0x3B9E15U, 0x782DC4U, 0x41774BU, 0x8AF633U, 0xD18DE4U, 0xD81E5DU, 0x83A69AU,
0x8AF583U, 0xF06E7CU, 0xBB5FADU, 0xA28416U, 0xE99653U, 0xF06D88U, 0x9FEC35U, 0xC4F7E6U, 0x4C059AU, 0x1F1C19U,
0x56EFC4U, 0x4D743FU, 0x24612AU, 0x3F9BD1U, 0x748814U, 0x2C13AFU, 0x27F276U, 0x5EE861U, 0x553B88U, 0x0E0A5FU,
0xC791E6U, 0xD8E2B0U, 0x907A69U, 0xABE9C6U, 0xE09217U, 0xB10168U, 0xBA48F9U, 0xE3FA26U, 0x8861CFU, 0x9230D8U,
0xDB8B21U, 0xC099B2U, 0x09644FU, 0x52F704U, 0x79AC90U, 0x201F6BU, 0x2E17BEU, 0x77C495U, 0x3CFF48U, 0x172E9BU,
0x4E9426U, 0x0D8775U, 0x145E98U, 0x5E6D03U, 0xC5F6D6U, 0xAC242DU, 0xF70D3CU, 0xFEDED2U, 0xA5C543U, 0xAE74BCU,
0xD62EE5U, 0x9D9D72U, 0x80029BU, 0xCB534CU, 0x90E175U, 0x19BAAAU, 0x6A3B6BU, 0x6280D4U, 0x39D385U, 0x724B7AU,
0x6B78E2U, 0x00A321U, 0x19101CU, 0x5248CFU, 0x0ADB30U, 0x01F0A9U, 0x5A21CEU, 0xB73A17U, 0xACC880U, 0xE55179U,
0xFE42A6U, 0xB4B987U, 0xC5AF58U, 0xCE1688U, 0x97C533U, 0x9CCE76U, 0xC73F8DU, 0x8E2510U, 0xB4B6C3U, 0x7D4FFEU,
0x665C3DU, 0x2DC7C0U, 0x70B55BU, 0x5B2C2EU, 0x025FF5U, 0x49D470U, 0x53448AU, 0x1A3FD7U, 0x09AC64U, 0x60BDBDU,
0x3B467AU, 0xB0D043U, 0xE98B9CU, 0xE33A2DU, 0x9A21E2U, 0xD1C3B3U, 0xCA5A0CU, 0x8709DDU, 0xDCB222U, 0xF5A3AAU,
0xBF79DDU, 0xA44A04U, 0xEDD193U, 0x3E006AU, 0x373B21U, 0x4CF994U, 0x47C04FU, 0x1F53DAU, 0x5488A1U, 0x4DB86CU,
0x2623DFU, 0x7D7402U, 0x70CF50U, 0x2B9EFDU, 0x232426U, 0xF8A7D3U, 0x91FEC8U, 0x8A4D39U, 0xC117F6U, 0xD0866FU,
0x9B3D18U, 0xE36EC1U, 0xE8F576U, 0xB3C5BFU, 0xBA1629U, 0xE1BD50U, 0xA8EC8FU, 0x17763EU, 0x5D45F1U, 0x049CA0U,
0x0F8F1FU, 0x5630C6U, 0x7DE225U, 0x26FB38U, 0x6F08CBU, 0x7D0316U, 0x34B28DU, 0x2F68E9U, 0xC47B72U, 0x9DC287U,
0x96915CU, 0xCF0B41U, 0x85F8A2U, 0xBAE17FU, 0xF372CCU, 0xE81991U, 0xA1894AU, 0xFAF2EBU, 0xF16134U, 0x89F845U,
0x0A8ADBU, 0x53153AU, 0x1806E5U, 0x03FF7CU, 0x6A7C0BU, 0x312692U, 0x399775U, 0x628CACU, 0x6D7FB3U, 0x34EE42U,
0x5FF49DU, 0x56073CU, 0x8D1C67U, 0x87CDBBU, 0xDEE708U, 0xB574D5U, 0xA4ADB6U, 0xEF9E2BU, 0xF605D0U, 0xBD7545U,
0xE6EE0EU, 0xCE39FBU, 0x950260U, 0xD8929DU, 0x43D9CEU, 0x086A47U, 0x31B3B1U, 0x7AA068U, 0x221ADFU, 0x294B86U,
0x72F049U, 0x73E3F8U, 0x083927U, 0x418856U, 0x5AC3C9U, 0x105020U, 0xC969B7U, 0xE2BBEEU, 0xBF2019U, 0xB41181U,
0xEFCA6AU, 0xA6FD3FU, 0xBC27A4U, 0xD53651U, 0xCE9D9AU, 0x854EA7U, 0xDC5E74U, 0xDFE5A9U, 0x26B61AU, 0x6C0D57U,
0x77DCECU, 0x3EC639U, 0x2575C3U, 0x682CD6U, 0x13AF1DU, 0x1855ECU, 0x404473U, 0x4BDF8AU, 0x12ACDDU, 0xF93754U,
0xE207A3U, 0xABD87AU, 0xF04B45U, 0xF03284U, 0xABB05BU, 0x80ABEBU, 0xD95AB4U, 0x92C10DU, 0x8FD2CEU, 0xC42833U,
0xEC3920U, 0x37C2FDU, 0x7C5106U, 0x654883U, 0x2EAAF8U, 0x37B12DU, 0x5C20B6U, 0x065B42U, 0x07C909U, 0x5C12B4U,
0x152367U, 0x2EB4FAU, 0x65CF19U, 0xFC5F40U, 0xB294FFU, 0xEBA72EU, 0xE03ED1U, 0x9B6CD0U, 0x92D70FU, 0xC944F6U,
0x801D60U, 0x9AAE19U, 0xF1F4DEU, 0xA85547U, 0xAB4EB8U, 0x729DE9U, 0x792456U, 0x223697U, 0x4BED0CU, 0x55DE71U,
0x1C03A2U, 0x07910FU, 0x4CAADCU, 0x356BA0U, 0x3E5033U, 0x67C3EEU, 0x2D9B05U, 0xB62810U, 0xFFF3EBU, 0xC4E03EU,
0x8558A5U, 0xDE0B48U, 0xD5905BU, 0x8D71A2U, 0xA26A75U, 0xFBD8ECU, 0xB08982U, 0xAB1253U, 0xE2A1ECU, 0x79FB3FU,
0x116E52U, 0x4A15C9U, 0x43861CU, 0x188FE7U, 0x537DF2U, 0x62E619U, 0x29D7C0U, 0x310C57U, 0x7A1F2EU, 0x25E5B8U,
0xAC7451U, 0xC76F86U, 0xDE9C9FU, 0x959460U, 0xCF27B1U, 0xC6FC1EU, 0xBDEDCFU, 0xF416B0U, 0xEF0429U, 0xA49FEEU,
0xBDEA17U, 0xFF7104U, 0x06A3F8U, 0x0D8A63U, 0x5219A6U, 0x5B62DDU, 0x00F348U, 0x6969B3U, 0x731A6EU, 0x38816DU,
0x61D090U, 0x6A6343U, 0x33F9FEU, 0x18B8A5U, 0xC30340U, 0x8B10DAU, 0x98E80BU, 0xD1FB74U, 0xEA20F5U, 0xA5930AU,
0xFC8E93U, 0xF75CC4U, 0xAF673DU, 0xA4E6BAU, 0xDF3D43U, 0x960F9CU, 0x0DD68DU, 0x44E572U, 0x1F7EB2U, 0x35AD09U,
0x6C9554U, 0x6746A7U, 0x365D3AU, 0x7DFCF9U, 0x64A6C4U, 0x0B351FU, 0x118CEAU, 0x58DF61U, 0x836434U, 0x8A36CFU,
0xF1AB5BU, 0xBA18A0U, 0xA343EDU, 0xE8C27EU, 0xF0F887U, 0xBB2B50U, 0xC03A69U, 0xC9C1A6U, 0x9A5317U, 0x9368C8U,
0x5CB919U, 0x26A226U, 0x2F01EFU, 0x74D919U, 0x3DCA80U, 0x2631D7U, 0x6D223EU, 0x54BAA1U, 0x1E4950U, 0x47520BU,
0x4CA79EU, 0x97BC75U, 0xBE3EA8U, 0xED479BU, 0xA4D446U, 0xBA4FF5U, 0xF13C39U, 0xE8A46AU, 0x83D7D7U, 0xDA4C0CU,
0xD1DDF9U, 0x8AA7F2U, 0xC22427U, 0x793DDCU, 0x30CE45U, 0x2B5522U, 0x6007FBU, 0x39BE6CU, 0x32AD95U, 0x42560BU,
0x4D426AU, 0x16D1B5U, 0x5F3A04U, 0x442BDBU, 0x2DF082U, 0xF6C225U, 0xFE59FCU, 0xA5880FU, 0xAEB312U, 0xF761C9U,
0x9C582CU, 0x85CBB7U, 0xCE00C3U, 0xD43118U, 0x9DAB9DU, 0xEAF866U, 0xE3437BU, 0x381288U, 0x738955U, 0x6A3BF6U,
0x2066ABU, 0x19D570U, 0x52DEC1U, 0x090E1EU, 0x00B5FFU, 0x5BE6E1U, 0x727D38U, 0x284CCFU, 0x639656U, 0xFA8531U,
0xBD3CA8U, 0xD4EF77U, 0xCFC586U, 0x841489U, 0x9C0F78U, 0xD7BCA7U, 0x8E671EU, 0xA5774DU, 0xFE8481U, 0xF79F32U,
0xAC0AEFU, 0x65F09CU, 0x5FF301U, 0x144ACAU, 0x0D193FU, 0x468224U, 0x13F0D1U, 0x18694AU, 0x63FA87U, 0x2B81F4U,
0x30106DU, 0x790A9BU, 0xE2E952U, 0x8970CDU, 0xD003BCU, 0xDB9963U, 0x838AD2U, 0x88731DU, 0xD1E064U, 0xBAFFF3U,
0xA10F2AU, 0xEC049DU, 0xBFD7D4U, 0xB7EE2BU, 0x4C7CBBU, 0x478760U, 0x1E9415U, 0x554D9EU, 0x4C7E6BU, 0x07E4B0U,
0x3D35ADU, 0x741E4EU, 0x2F8D93U, 0x26FC20U, 0x7D667DU, 0x16B586U, 0x8B8E02U, 0xC91FD9U, 0xD0456CU, 0x9BF237U,
0xC0EBCEU, 0xE92849U, 0xB29390U, 0xBBC3E7U, 0xE1787EU, 0xAA6B81U, 0x93B040U, 0xD8005FU, 0x411BAEU, 0x0AC870U,
0x51F1D1U, 0x5D328EU, 0x362837U, 0x6799E0U, 0x6C4239U, 0x37711AU, 0x3EABC7U, 0x45BA3CU, 0x0D01A9U, 0x16D6F2U,
0xDDCF17U, 0xC46D8CU, 0x8F3670U, 0xF6A723U, 0xFD5CBCU, 0xA74F5DU, 0xEAF582U, 0xF1A43BU, 0x903768U, 0x8B0CC5U,
0xC0DC16U, 0x9957CBU, 0x1324F0U, 0x4ABD25U, 0x61AECEU, 0x38545AU, 0x73C701U, 0x68FEF4U, 0x212D6FU, 0x5B3382U,
0x52C2D1U, 0x09494CU, 0x065ABFU, 0xDFA126U, 0x9CB149U, 0xA56A98U, 0xEE5927U, 0xF4C0F6U, 0xBD33B8U, 0xE62901U,
0xCFB8D6U, 0x94D32FU, 0x9F40B8U, 0xC69AF1U, 0x8CAB0EU, 0x15309FU, 0x7E6360U, 0x21DA31U, 0x2848BAU, 0x733747U,
0x72A6D4U, 0x08EDA8U, 0x435F7BU, 0x5A4CD6U, 0x119505U, 0x082658U, 0x433DE3U, 0xB8ED26U, 0xB0D6DDU, 0xEB05C8U,
0xA2BC13U, 0xA9BEEAU, 0xD6656DU, 0xDF5614U, 0x848F82U, 0xC41C5BU, 0xDF26A4U, 0x94F7A5U, 0xADCC5AU, 0x665B8BU,
0x3F1234U, 0x34A0EDU, 0x6E7BAAU, 0x076813U, 0x1CD1C4U, 0x55833DU, 0x4E1836U, 0x03A9E2U, 0x58F219U, 0x72418CU,
0x2B09F7U, 0xA89A72U, 0xF1A1A9U, 0xBA7254U, 0x81EA47U, 0xC899BAU, 0xD20279U, 0x9B13C4U, 0xC0E09FU, 0xCB7E4BU,
0xB25FF0U, 0xF98431U, 0xE4974EU, 0x2E6CD7U, 0x35FC00U, 0x5CE7A9U, 0x07147EU, 0x060D07U, 0x5D9F98U, 0x56E449U,
0x0E65A6U, 0x659EB7U, 0x7C8D49U, 0x371790U, 0x6C6623U, 0xE5FD6EU, 0x9E6EBDU, 0x921600U, 0xC985D3U, 0x82DAEEU,
0x9B7B25U, 0xD0E0F0U, 0xE1924BU, 0xAA091EU, 0xF158F5U, 0xF9E369U, 0x22F1BAU, 0x4B28C7U, 0x509B54U, 0x1B80BDU,
0x024162U, 0x497B53U, 0x01A88CU, 0x3E1B5DU, 0x7502F2U, 0x6CD12BU, 0x27EB1CU, 0x7E7AC5U, 0xDDA113U, 0x8596BAU,
0xCE5EEDU, 0xD54D14U, 0x9CF68BU, 0x87A54AU, 0xEE1C31U, 0xB58EA4U, 0xBFD55FU, 0xE66482U, 0xE93FA1U, 0x90AD7CU,
0x5B04EFU, 0x405713U, 0x09CC48U, 0x13BFEDU, 0x522736U, 0x2914E3U, 0x22CFD8U, 0x7B5E05U, 0x3061E6U, 0x29B37FU,
0x43BAA8U, 0x5849D1U, 0x91D25EU, 0xCEE0AFU, 0xC73971U, 0x9C2A40U, 0xB7919FU, 0xEF401EU, 0xA452E1U, 0xB5B9B8U,
0xFEA80FU, 0x8533D6U, 0x8C4115U, 0xD7DA28U, 0x5F6BF3U, 0x043006U, 0x4FA39DU, 0x76DBD9U, 0x394C22U, 0x20C7BFU,
0x6BB64CU, 0x312C41U, 0x187FB2U, 0x43C46FU, 0x0A55F4U, 0x192E81U, 0xD2BC4AU, 0xCBA5FBU, 0xA15624U, 0xF85DFDU,
0xF38ECBU, 0xBA3602U, 0xA125F5U, 0xCEFE6CU, 0x97CF3BU, 0x9D55C2U, 0xC4A64DU, 0x4FBFBCU, 0x1468A3U, 0x7D4352U,
0x6ED19DU, 0x270804U, 0x7D3B76U, 0x76A0ABU, 0x0FF018U, 0x0443D5U, 0x5D188EU, 0x16A93BU, 0x0932E0U, 0xC07015U,
0xFACB1EU, 0xB39AC3U, 0xE80170U, 0xE3B3ADU, 0xBAEA5EU, 0xD17956U, 0xC042A9U, 0x8A9378U, 0x912DE7U, 0xD86E86U,
0x83F559U, 0x2AC4E8U, 0x711F37U, 0x7A0D6EU, 0x26B4C9U, 0x6D6710U, 0x547CE7U, 0x1F8CFEU, 0x449720U, 0x4D3483U,
0x16EF5AU, 0x1EFE2DU, 0x6D44B4U, 0xA6174BU, 0xBF8E8AU, 0xF4FD95U, 0xED6764U, 0x86D6BBU, 0xDC8912U, 0xD10A45U,
0x8A799CU, 0x83E12AU, 0xF872F3U, 0xB10954U, 0xAA980DU, 0x6083D6U, 0x397163U, 0x3AE8B8U, 0x439BDDU, 0x481046U,
0x1302BBU, 0x5AFB68U, 0x50E875U, 0x297396U, 0x26824AU, 0x7D98F1U, 0x344BA4U, 0xAF726FU, 0xE6F5DAU, 0x9C0F01U,
0x971C38U, 0xCE85EFU, 0xC5F626U, 0x946D91U, 0xFFBDC8U, 0xE48637U, 0xAC15A6U, 0xB74C48U, 0x7EEE99U, 0x21B586U,
0x0A0677U, 0x539FA8U, 0x18CC01U, 0x007652U, 0x4B67CFU, 0x70B43CU, 0x390FF1U, 0x625ECAU, 0x6BD01FU, 0x38E3C4U,
0xB23870U, 0xCB893BU, 0x8093C6U, 0x994055U, 0xD679A8U, 0x8DAAFBU, 0xA4B176U, 0xFE018DU, 0xF7CA5CU, 0xACD963U,
0xE762B2U, 0xFE323DU, 0x1589C4U, 0x0C5A92U, 0x4F432BU, 0x17F0ECU, 0x1CAA35U, 0x673B82U, 0x6E54DBU, 0x31C724U,
0x785CA5U, 0x632C5AU, 0x29B70BU, 0x508490U, 0xDB5D6DU, 0x82CFEEU, 0x89B492U, 0xD22541U, 0xBB2EDCU, 0xA1DD27U,
0xE04F62U, 0xFB56D9U, 0xB0A50CU, 0xF9BED7U, 0xC24EFAU, 0x8F5529U, 0x55C6D0U, 0x5E3B47U, 0x07383FU, 0x2CA2F0U,
0x75D161U, 0x3E489EU, 0x25BB0FU, 0x6DA170U, 0x7630B1U, 0x174B2EU, 0x4CD8D7U, 0x470180U, 0x9E2339U, 0xD5B8FEU,
0xE9EB27U, 0xA2521DU, 0xB941C8U, 0xF0BB23U, 0xAB2AB6U, 0xA271CDU, 0xD9C250U, 0xD3DC83U, 0x8A1D6EU, 0x41A67DU,
0x58B580U, 0x3B6C5BU, 0x205ECEU, 0x6985A5U, 0x333471U, 0x3E27CAU, 0x65FD13U, 0x0CCE44U, 0x1747EDU, 0x5C143AU,
0x45AF83U, 0x8F7F54U, 0xF6643DU, 0xFDD7A2U, 0xA68E73U, 0xAF3D8CU, 0xF4E79DU, 0xB5E073U, 0x8F59AAU, 0xC40A3DU,
0x999044U, 0x922197U, 0xCB7A3AU, 0x60E9E1U, 0x3B90B4U, 0x73020FU, 0x6839DAU, 0x21FA71U, 0x3A632CU, 0x5151DFU,
0x088A43U, 0x039B80U, 0x4260FDU, 0x18F36EU, 0x33EB97U, 0xEE1848U, 0xE503C9U, 0xBCA4B6U, 0xF7FC67U, 0xEC6FD8U,
0x849C01U, 0x9F8506U, 0xD616FFU, 0x8D6C29U, 0x86FD90U, 0xFF26CFU, 0xF4150EU, 0x2C9EB1U, 0x6FEE60U, 0x74751BU,
0x39E696U, 0x429F65U, 0x4B0DB8U, 0x1056ABU, 0x1AE756U, 0x43FC9DU, 0x282F29U, 0x318172U, 0x7A90E7U, 0xE36B1CU,
0xA878D9U, 0xF2A0E2U, 0xDB133FU, 0x8008ECU, 0xC1D955U, 0xDAE292U, 0x9570EBU, 0xAC9B74U, 0xE68A85U, 0xBF514BU,
0x34635AU, 0x6FFAA5U, 0x66A93CU, 0x1D12CBU, 0x54C382U, 0x4ED915U, 0x056AECU, 0x5C2D37U, 0x779402U, 0x2607C9U,
0x2D5D1CU, 0x72ECA6U, 0xBAB7FBU, 0xA12408U, 0xC89C85U, 0xD3CF76U, 0x98542BU, 0xC177B8U, 0xCAAE45U, 0xB29CCEU,
0xB9473BU, 0xE2D660U, 0xABEDF1U, 0xA03F1EU, 0x7926C4U, 0x1A95F1U, 0x044E2AU, 0x4D49FFU, 0x56B154U, 0x1FA209U,
0x6419FAU, 0x6F4867U, 0x36D394U, 0x3C2199U, 0x653842U, 0x2EABB7U, 0x95C02CU, 0xDC525CU, 0x87CB93U, 0x8EB80AU,
0xD423FDU, 0xF152A4U, 0xAAC003U, 0xE15BDAU, 0xF82A0DU, 0xB3B134U, 0xAAB3EBU, 0xC14C0AU, 0x1B5D95U, 0x128664U,
0x49357AU, 0x002DA3U, 0x3BDE40U, 0x70C5DDU, 0x6954AEU, 0x23AE73U, 0x76ADE8U, 0x7D760DU, 0x064756U, 0x0FDCE3U,
0xD40E38U, 0x9D37F5U, 0x87E4C6U, 0xECDF1AU, 0xB54EA9U, 0xBE1470U, 0xE7B71FU, 0xEC288EU, 0xB77951U, 0xDFC3A0U,
0xC490BFU, 0x89095EU, 0x1ABA81U, 0x51E118U, 0x2853EFU, 0x234AB6U, 0x7B8910U, 0x703AC9U, 0x2B6216U, 0x62F127U,
0x59CAECU, 0x101B59U, 0x4B2082U, 0xC1F2FFU, 0x88696CU, 0xB358A1U, 0xFA9752U, 0xAD844FU, 0xA63CB4U, 0xFFEF60U,
0xF5F4EBU, 0x8C059EU, 0xC71F45U, 0xDCACF0U, 0x95772BU, 0x4E6622U, 0x67CDD5U, 0x3D9F0CU, 0x3406BBU, 0x6F75F2U,
0x24EE0DU, 0x3D7E9CU, 0x520542U, 0x4396B3U, 0x09ADBCU, 0x527C45U, 0x5BF292U, 0xA0810BU, 0xE91878U, 0xF20BB5U,
0xB9F10EU, 0xA1E0DBU, 0xEA33C0U, 0x938835U, 0x989BFEU, 0xC36342U, 0xCA6011U, 0x95FBECU, 0xFD0A6FU, 0x6E11B2U,
0x25C3C1U, 0x3CFA5CU, 0x7769A7U, 0x0EB266U, 0x058079U, 0x5E1988U, 0x167E17U, 0x0DE5EFU, 0x44B428U, 0x7F0E31U,
0x349DC6U, 0xEDC41FU, 0xE277A0U, 0xBA6DE1U, 0x99BE1EU, 0xC2178FU, 0x8B4450U, 0x90FF39U, 0xD9EFAAU, 0x823457U,
0xA88785U, 0xF1DE98U, 0xFA4D73U, 0x3377E6U, 0x68A41DU, 0x43AD48U, 0x1A1AD3U, 0x14C836U, 0x4DF1EDU, 0x0622D0U,
0x173903U, 0x7C88FEU, 0x27527DU, 0x2E41A5U, 0xF4FADAU, 0xFDBB4BU, 0x8601A4U, 0xCDD235U, 0xD4CB6AU, 0x9F7893U,
0x862304U, 0xCCB3EDU, 0xB388BAU, 0xBA5B23U, 0xE1C0DCU, 0xE8A00DU, 0x3B3F27U, 0x500CF2U, 0x48D509U, 0x034694U,
0x5A3CC7U, 0x51AD6AU, 0x0AB6B9U, 0x234544U, 0x785E57U, 0x30DE9AU, 0x2B2561U, 0x6036F4U, 0xDDCF8FU, 0x96DD5BU,
0xCF46D0U, 0xCCB729U, 0x96A4FEU, 0xDF3FC7U, 0xE44D10U, 0xADC4F9U, 0xB61366U, 0xFD2837U, 0xA4B888U, 0x8EC359U,
0x5750B6U, 0x5C49AFU, 0x07BA79U, 0x4A2080U, 0x517307U, 0x38DA7EU, 0x62C9ADU, 0x611230U, 0x38A2CBU, 0x33F98EU,
0x4A4A35U, 0x0153E0U, 0x98815BU, 0xD23A06U, 0xD929C5U, 0x80E079U, 0xEBD7AAU, 0xF20D57U, 0xBD1C4CU, 0xE6A78DU,
0xEF7472U, 0x954CE3U, 0x9CDF9CU, 0xCF8455U, 0x0437C2U, 0x1DFE3BU, 0x56EC6CU, 0x6F57D5U, 0x25061BU, 0x7E95AAU,
0x772FF5U, 0x2C7C24U, 0x05C59BU, 0x5A965AU, 0x111D21U, 0x892DBCU, 0xC2F26FU, 0x9B6192U, 0xB81891U, 0xE38B6EU,
0xEA91B6U, 0xB16221U, 0xF9FB48U, 0xC2C8DFU, 0x890226U, 0x9013F9U, 0xDBE848U, 0x02FB07U, 0x0D62D6U, 0x77906DU,
0x3E8BB0U, 0x2538C3U, 0x6C614EU, 0x77F39CU, 0x141861U, 0x4D0D7AU, 0x47968FU, 0x1EE544U, 0x157DD1U, 0xCEEEAAU,
0xA7953FU, 0xBC06D4U, 0xF57E09U, 0xABED3AU, 0xA2EEE3U, 0xD91734U, 0xD2849CU, 0x8BDEC3U, 0xC06F32U, 0xD174ADU,
0x9BA77CU, 0x201C93U, 0x690C8AU, 0x22F77DU, 0x3BF4E4U, 0x702933U, 0x4B9B5AU, 0x0380C1U, 0x585134U, 0x556AEEU,
0x0EF9CBU, 0x45A310U, 0x7C12CDU, 0xB7C97EU, 0xAFEA23U, 0xEC72C0U, 0xB7215DU, 0x9E9A8EU, 0xC50BF3U, 0xCC5068U,
0x97E28DU, 0xDDB916U, 0xC42846U, 0xAF93B9U, 0xF2D020U, 0x796CC7U, 0x223F9EU, 0x2BA429U, 0x5095F0U, 0x18473FU,
0x03DC8EU, 0x40EFD1U, 0x593620U, 0x1225BFU, 0x6BCF76U, 0x605E40U, 0xBA6599U, 0xF3B66AU, 0xE8AEF7U, 0x851DBCU,
0x9EC649U, 0xD5D5D2U, 0x8C2C27U, 0x863E7CU, 0xDFB5D9U, 0xF4C002U, 0xA55BDFU, 0xEEE9ECU, 0x75B020U, 0x3C23D3U,
0x06584AU, 0x4FCB15U, 0x1453A4U, 0x1F306BU, 0x42AB9AU, 0x09FA05U, 0x30415CU, 0x7A53ABU, 0x61AA22U, 0x2839D5U,
0xF3228CU, 0xDAD032U, 0x89C9E3U, 0x820A2CU, 0xCAB91DU, 0x91A4C6U, 0x985673U, 0xE34DB8U, 0xA8DCE5U, 0xB52756U,
0xFE358BU, 0xE6EE78U, 0x0DDF75U, 0x5654AFU, 0x5F075AU, 0x04BFC1U, 0x0D2CB4U, 0x56577FU, 0x34C6C2U, 0x2D9D11U,
0x662F48U, 0x3FB4FFU, 0x34E536U, 0x4F4E89U, 0xC61C58U, 0x988107U, 0xD132A7U, 0xCA6978U, 0x81D881U, 0xB8C296U,
0xF3114FU, 0xAA2AA8U, 0xA0FB31U, 0xF37142U, 0xDA429FU, 0x819B24U, 0x4888E1U, 0x5333FAU, 0x1AE30FU, 0x40D0D5U,
0x6F0B68U, 0x36182BU, 0x3DA0F6U, 0x646345U, 0x2F7898U, 0x14CDF3U, 0x5C9666U, 0xC704BDU, 0x8E7F4CU, 0xDDEED3U,
0xD655BAU, 0xAF062DU, 0xE49EF5U, 0xFDFD02U, 0xB7661BU, 0xA8F7F4U, 0xC18D25U, 0x9A1E9AU, 0x9305CBU, 0x48F414U,
0x43EFB5U, 0x1B1D6AU, 0x708413U, 0x698780U, 0x2A7C4DU, 0x6168BFU, 0x78F3A2U, 0x130059U, 0x0B1BCCU, 0x40CA07U,
0x1FF072U, 0x9663E9U, 0xCD9A14U, 0xE499C7U, 0xBF0AEAU, 0xF57239U, 0xECE1E4U, 0xA7BA5FU, 0xDE098FU, 0xD591E0U,
0x86E271U, 0x8F79AEU, 0xD52817U, 0x1C8350U, 0x2711A9U, 0x684C3EU, 0x71FFE7U, 0x3AE490U, 0x633619U, 0x498FE6U,
0x10DC37U, 0x1B670DU, 0x4066D8U, 0x09BC13U, 0x328FAEU, 0xFB16FDU, 0xA9C500U, 0xA2FF93U, 0xFB2C5EU, 0xF03565U,
0x8D86B0U, 0xC65D4BU, 0xDD7DCEU, 0x95E615U, 0x8EB169U, 0xE708FAU, 0xBCDB03U, 0x37C1C4U, 0x6E72FDU, 0x25232AU,
0x3DB8F3U, 0x5ECA4CU, 0x45430DU, 0x0CF0B2U, 0x57AB61U, 0x5E3ABCU, 0x210087U, 0x2BD343U, 0xF248B8U, 0xB9392DU,
0xA0A376U, 0xEBB09FU, 0x905908U, 0x99CAF1U, 0xD3F5A6U, 0xCA251FU, 0x813ED0U, 0xF2CD01U, 0xFBD63EU, 0xA046EEU,
0x29BD51U, 0x76AE98U, 0x3C274FU, 0x055476U, 0x4ECEA5U, 0x573F58U, 0x1C24DBU, 0x47B786U, 0x6ECC7DU, 0x345CE8U,
0x7D0703U, 0x66B456U, 0xAF3DECU, 0xBC6F31U, 0xD7D0A2U, 0x8EC1CFU, 0x80321CU, 0xD9A9A1U, 0xD2FB7AU, 0xA9422BU,
0xE05184U, 0xFB8A55U, 0xB22AAAU, 0xE831B3U, 0x63E264U, 0x1ADB8CU, 0x11081BU, 0x4832E2U, 0x0BA1BDU, 0x10781CU,
0x784BC3U, 0x679052U, 0x2E902DU, 0x752BFCU, 0x7EFC57U, 0x27C58AU, 0xCC57D9U, 0xD40C64U, 0x9FBFB6U, 0x84665BU,
0xCD7540U, 0xB6CF95U, 0xBF8E6EU, 0xE415FBU, 0xE62690U, 0xBFFE0DU, 0xF04DFEU, 0xC91623U, 0x028520U, 0x19BCD9U,
0x506E06U, 0x0AEDB6U, 0x23D4E9U, 0x780728U, 0x331997U, 0x3AE84EU, 0x6173B9U, 0x6840A0U, 0x129B67U, 0x598B9EU,
0xC87009U, 0x877370U, 0x9EEAEBU, 0xF5190EU, 0xAC03D4U, 0xA690C1U, 0xFDE93AU, 0xB47AF7U, 0xAF8044U, 0xC69119U,
0xDD0ACAU, 0x166977U, 0x4EF0BCU, 0x45E2C9U, 0x3C1D52U, 0x3F8E87U, 0x64D73CU, 0x296574U, 0x327E83U, 0x7A8F1AU,
0x0114EDU, 0x0A1734U, 0x53EF3BU, 0xD8FCCAU, 0x812715U, 0xEA94A4U, 0xF185EBU, 0xB95F3AU, 0xA26C85U, 0xEBB55CU,
0xB0862AU, 0x930CA3U, 0xCEDD70U, 0x85E6CDU, 0x9D7196U, 0x562A63U, 0x6D9AE8U, 0x24411DU, 0x7F5246U, 0x76EBDBU,
0x2DB928U, 0x2712E5U, 0x5E83D7U, 0x15D80AU, 0x0C6BD1U, 0x473170U, 0x54A02FU, 0xB99B9EU, 0xE34841U, 0xEAD090U,
0xB1E33FU, 0xFA2866U, 0xE31991U, 0x88C208U, 0x8154FFU, 0xDB6FB7U, 0x92BE28U, 0x89A5D9U, 0xE25606U, 0x7BCE37U,
0x30FDFCU, 0x693E21U, 0x6F2792U, 0x3495CFU, 0x5DCE6CU, 0x465DB1U, 0x0FA46AU, 0x14B75FU, 0x5F2D85U, 0x275C60U,
0x2CC7FBU, 0xF56486U, 0xFE3C55U, 0xA5ABC8U, 0xECD02BU, 0xD743F2U, 0x9FDAC5U, 0xC0A81CU, 0xC33383U, 0x9A2262U,
0xB1D93DU, 0xE8DA8DU, 0x232252U, 0x39B19BU, 0x70AAACU, 0x6B5975U, 0x024182U, 0x59921BU, 0x522974U, 0x0B38A5U,
0x01F33EU, 0x78C1CBU, 0x3758D0U, 0x242F3DU, 0xEDB4EFU, 0xB66672U, 0xBF5701U, 0xC5CCDCU, 0xCE9F77U, 0x9726A2U,
0xDCA4F9U, 0xC5FF4CU, 0xAE4E87U, 0xB51576U, 0xFDA7E9U, 0xA63C90U, 0x2F6D47U, 0x74D6CFU, 0x1BC538U, 0x0A1D21U,
0x413EDEU, 0x58E50FU, 0x127480U, 0x6B4BF1U, 0x60992EU, 0x2BA297U, 0x327340U, 0x79E809U, 0xA0DABAU, 0x8A0367U,
0xD1009DU, 0x98BB98U, 0x836A63U, 0xCE70F6U, 0xF5832DU, 0xB69850U, 0xEE29D3U, 0xE5732EU, 0xBCE0FDU, 0xB75962U,
0x4C1A13U, 0x0589DCU, 0x1EF165U, 0x5666B7U, 0x4DFDEAU, 0x268E59U, 0x7F1794U, 0x74256FU, 0x29FE7AU, 0x626F81U,
0x700404U, 0x1996DFU, 0x828FA2U, 0xCB7C31U, 0x9067CCU, 0x9B940EU, 0xE20C17U, 0xE81FE8U, 0xB1E439U, 0xFAF586U,
0xE17FC7U, 0xA88C18U, 0xD397A1U, 0x5E4276U, 0x04794FU, 0x0FEB88U, 0x5E9271U, 0x3501E6U, 0x2C9A3EU, 0x67EA51U,
0x7C61C0U, 0x34323BU, 0x6F89EEU, 0x4618F5U, 0x1D4218U, 0xD4F1CBU, 0xCFE876U, 0x841B25U, 0xB888F8U, 0xF3D053U,
0xAA7386U, 0xA168BCU, 0xF2BB69U, 0xFB8792U, 0x80541FU, 0xC8CF4CU, 0xC3FEB5U, 0x182522U, 0x1117CBU, 0x6A9E9CU,
0x234D05U, 0x3876FAU, 0x72A42BU, 0x2FBD84U, 0x240ED4U, 0x5DD54BU, 0x56C4B2U, 0x057E65U, 0x4C2D4CU, 0xD7849BU,
0xBFD762U, 0xA44DF9U, 0xEFFEACU, 0xB6A347U, 0xBD30D2U, 0xC40B29U, 0x8FDB74U, 0x9540E6U, 0xDC330BU, 0xC3BAD8U,
0x8A89E5U, 0x71533EU, 0x7AC0BBU, 0x2BB140U, 0x212A11U, 0x7838AEU, 0x13C17FU, 0x08D290U, 0x414989U, 0x1AA85EU,
0x13B2A6U, 0x494131U, 0x625AD8U, 0xBBCF87U, 0xF43516U, 0xED26E9U, 0xA6BF78U, 0x9FCC17U, 0xDD57CEU, 0x86B75DU,
0x8FACA0U, 0xD43FE3U, 0x9D445EU, 0xA6D584U, 0x6DCF71U, 0x753C6AU, 0x3EA5AFU, 0x67F654U, 0x4C4CC9U, 0x134DBAU,
0x1AB667U, 0x4125E4U, 0x097E19U, 0x12CA0AU, 0x71D1F3U, 0x78022CU, 0xA33BACU, 0xEAA953U, 0xF17A02U, 0x9B53BDU,
0xC28074U, 0xC9BB83U, 0x90299AU, 0x9BF04DU, 0xC4C3B4U, 0xAD583BU, 0xB7084AU, 0xFEB3D1U, 0x656004U, 0x2E69FEU,
0x5FDAF3U, 0x548000U, 0x0D37DDU, 0x472E4EU, 0x5CFD33U, 0x1546F8U, 0x2E164DU, 0x678D96U, 0x3CBEE3U, 0x337768U,
0xEBE5BDU, 0xC09E47U, 0x990D5EU, 0xD234A9U, 0xC9E720U, 0x887DF7U, 0xD34C0EU, 0xFB9711U, 0xA084E0U, 0xA96C2FU,
0xF27FBEU, 0xB9E4C1U, 0x001318U, 0x4B02AFU, 0x56B867U, 0x1CEB30U, 0x477289U, 0x4E8152U, 0x358AF7U, 0x3C1AACU,
0x676159U, 0x24F2C2U, 0x3C6917U, 0x57197CU, 0x8E82E1U, 0x85F112U, 0xDE68CFU, 0xD77BDDU, 0x8C9130U, 0xE400EBU,
0xFB5B5EU, 0xB0E885U, 0xA9F6D4U, 0xE2277BU, 0x9B9CA2U, 0x108F15U, 0x5A764CU, 0x0B64ABU, 0x00AF32U, 0x599CEDU,
0x72059DU, 0x29D702U, 0x60ECE3U, 0x7A7D3CU, 0x330625U, 0x0C95D6U, 0x474D0BU, 0x9E7EA8U, 0x95FDF5U, 0xCCA666U,
0x86179BU, 0xBD8D40U, 0xFCDA65U, 0xE763BFU, 0xAE304AU, 0xF58AD1U, 0xDE9B9CU, 0x86406FU, 0x8DE3F2U, 0x54B801U,
0x1B28D8U, 0x0213D7U, 0x69C026U, 0x7259B9U, 0x3A6B48U, 0x61B017U, 0x68819FU, 0x135A68U, 0x50D9B1U, 0x49E386U,
0x02325FU, 0x9A29B0U, 0xD19E23U, 0xAAC77EU, 0xA3558DU, 0xFCAE04U, 0xF5BFF3U, 0xAE04AAU, 0xC44635U, 0xDDDDC5U,
0x966C4AU, 0xCF373BU, 0xC4A4E4U, 0x1FD47DU, 0x3E4F8AU, 0x64DC43U, 0x2DA574U, 0x3637ADU, 0x7D5C56U, 0x44CFC3U,
0x0BD688U, 0x52257DU, 0x59BBE7U, 0x03AA1AU, 0x4A5119U, 0xF142C4U, 0xB89A37U, 0xB329AAU, 0xE822D1U, 0xA9D114U,
0x93C88FU, 0xDA5A7AU, 0xC1A121U, 0x8AB090U, 0xD36B5EU, 0xDC58A7U, 0xA5C0B0U, 0x2F8369U, 0x74389EU, 0x3DAB17U,
0x26D368U, 0x4F40F9U, 0x141F26U, 0x1DAEC7U, 0x473558U, 0x446721U, 0x1DDEF6U, 0x769D6EU, 0xEF0E8DU, 0xA434D0U,
0xBFE56BU, 0xF35EBEU, 0x884D45U, 0x819440U, 0xDAA69BU, 0x917D26U, 0x88ECF5U, 0xC3C788U, 0xFB150BU, 0xB02ED6U,
0x63BF24U, 0x6A6439U, 0x3153D2U, 0x188B03U, 0x43989CU, 0x0923EDU, 0x147232U, 0x5FF99BU, 0x060B4CU, 0x2D10B5U,
0x76A1A2U, 0x7FFA7BU, 0xA568D4U, 0xECD104U, 0xD7827BU, 0x9C19EAU, 0x8D6831U, 0xC6E2DCU, 0x9F71CFU, 0x950A32U,
0xEE9BE1U, 0xA3A16CU, 0xB8761FU, 0xF16FC2U, 0x6A9C79U, 0x010FACU, 0x491786U, 0x52F453U, 0x1BEF88U, 0x007C35U,
0x4B8566U, 0x32978FU, 0x316C18U, 0x697DC1U, 0x62E6BEU, 0x3B142FU, 0xD40DC0U, 0xCFCE11U, 0x86F58EU, 0xDD66F6U,
0xD53E31U, 0x8E8988U, 0xA5125FU, 0xFC6366U, 0xB7F9B9U, 0xAEAA78U, 0xE513C3U, 0xD69096U, 0x1ECB6DU, 0x4579F8U,
0x4C6033U, 0x13B34EU, 0x5888DCU, 0x615821U, 0x2AE3F2U, 0x32F0FFU, 0x792B04U, 0x220A91U, 0x0B906AU, 0xD0432BU,
0xD97294U, 0x82AD4DU, 0xC8BE9AU, 0xD90623U, 0xB2D564U, 0xEBEE9CU, 0xE02D03U, 0xBF35D2U, 0xB686ADU, 0xCCDD2CU,
0x854CD3U, 0x1EF70AU, 0x55A51DU, 0x4C1CE4U, 0x074F67U, 0x7ED49AU, 0x7476C9U, 0x2F2F75U, 0x26BCBEU, 0x75876BU,
0x1C5650U, 0x07C885U, 0x48BB7EU, 0x9022F3U, 0x9B11A0U, 0xC2CA5DU, 0xE9C8CEU, 0xA07133U, 0xFBA238U, 0xF0B9E9U,
0xA84917U, 0x835286U, 0xDAC179U, 0x913830U, 0x822B87U, 0x4BD95EU, 0x30D289U, 0x3C43A0U, 0x67B87FU, 0x6CAA8EU,
0x353311U, 0x7E4440U, 0x47DFABU, 0x0C8E3FU, 0x1634C4U, 0x5FA7D9U, 0x04CC0AU, 0xAD5DE7U, 0xF64774U, 0xBDB409U,
0xAC2DD2U, 0xE67E67U, 0xFBC5ACU, 0x90D5F9U, 0xCB0E42U, 0xC23D9FU, 0x99B67DU, 0x9047E4U, 0xEA5DB3U, 0x218E0AU,
0x38B7D5U, 0x732034U, 0x6AFA2BU, 0x21CBFAU, 0x5A1005U, 0x5B039CU, 0x01A8FBU, 0x4C7822U, 0x574395U, 0x3CD04DU,
0xA5811AU, 0xEE3BB3U, 0xB76868U, 0xBDF19DU, 0xE64286U, 0xCF1943U, 0x949BF8U, 0xDDA225U, 0xC67156U, 0x8FCACBU,
0xF59B08U, 0xF605F5U, 0x2B36EFU, 0x20EF1AU, 0x797CC1U, 0x324664U, 0x1985BFU, 0x419CE4U, 0x4A6F51U, 0x13748AU,
0x58C42FU, 0x631F74U, 0x2A0CA1U, 0x71F51AU, 0xF9E7D7U, 0xA27CA5U, 0xA99F38U, 0xD886EBU, 0x973516U, 0x8E6F1DU,
0xC5FEECU, 0xDF0133U, 0xB61282U, 0xED8ADDU, 0xE4F954U, 0xBF7AA3U, 0x74617AU, 0x6D904DU, 0x070A95U, 0x1E795AU,
0x55E0EBU, 0x0EF334U, 0x0F0845U, 0x7098CAU, 0x798313U, 0x2360E0U, 0x687BFDU, 0x71AB0EU, 0xBA10C3U, 0x830370U,
0xC8FA2DU, 0x93EDB7U, 0x9B3742U, 0xC00689U, 0xA99DBCU, 0xB25E67U, 0xF964BAU, 0xE0F509U, 0xA7AE44U, 0xFF1DB7U,
0x54C42EU, 0x0DF6F1U, 0x066D90U, 0x5D3C0EU, 0x1487FFU, 0x2F8460U, 0x675E19U, 0x3CEFDEU, 0x37B447U, 0x6E27B0U,
0x651369U, 0x9CC856U, 0xD77B97U, 0xC9604CU, 0x88B1F9U, 0x939BA2U, 0xFA4856U, 0xB1D1DDU, 0xAAE200U, 0xE33873U,
0xB829EEU, 0xB0D20DU, 0xCBC190U, 0x407AEBU, 0x19AA3EU, 0x52A1A5U, 0x4B1240U, 0x204B1BU, 0x3ED9A2U, 0x7F2274U,
0x2437ADU, 0x2DAC8AU, 0x76DF53U, 0x5D45ACU, 0x04F43DU, 0xCEBFE2U, 0xD72CC3U, 0x9C551CU, 0xE7C7E5U, 0xEEDC72U,
0xB52D1BU, 0xBCB6CCU, 0xE6A454U, 0xA95FA7U, 0x904EFAU, 0xD3A551U, 0xCA3684U, 0x01265FU, 0x5ADD6AU, 0x72CEB1U,
0x29135CU, 0x60A1CFU, 0x7BBA92U, 0x304921U, 0x2950FCU, 0x42D316U, 0x1AA903U, 0x1138F8U, 0x48E329U, 0xC7D0A6U,
0xBC48DFU, 0xFD1B08U, 0xE6A0B1U, 0xAE3366U, 0xF55AAFU, 0xFEC898U, 0x879341U, 0x8C22FEU, 0xD5392EU, 0x9EEA61U,
0x8456D0U, 0x6D450BU, 0x769EF6U, 0x3FADE5U, 0x606508U, 0x6BD6DBU, 0x3ACD46U, 0x101C3DU, 0x5927F8U, 0x02F543U,
0x096C96U, 0x505FCCU, 0xBB8C71U, 0xA296B2U, 0xE8370FU, 0xF36C5CU, 0xBADF85U, 0xE1063AU, 0xC814FBU, 0x97AF04U,
0x9CFA15U, 0xC461EAU, 0x87D23BU, 0xBE88B4U, 0x7509CCU, 0x2E721BU, 0x27E1A2U, 0x7C5965U, 0x750A7CU, 0x0F9183U,
0x44A052U, 0x5D7BE9U, 0x1669ACU, 0x0F9277U, 0x6013CAU, 0x3B0819U, 0xB3FA65U, 0xE0E3E6U, 0xA9103BU, 0xB28BC0U,
0xDB9ED5U, 0xC0642EU, 0x8B77EBU, 0xD3EC50U, 0xD80D89U, 0xA1179EU, 0xAAC477U, 0xF1F5A0U, 0x386E19U, 0x271D4FU,
0x6F8596U, 0x541639U, 0x1F6DE8U, 0x4EFE97U, 0x45B706U, 0x1C05D9U, 0x779E30U, 0x6DCF27U, 0x2474DEU, 0x3F664DU,
0xF69BB0U, 0xAD08FBU, 0x86536FU, 0xDFE094U, 0xD1E841U, 0x883B6AU, 0xC300B7U, 0xE8D164U, 0xB16BD9U, 0xF2788AU,
0xEBA167U, 0xA192FCU, 0x3A0929U, 0x53DBD2U, 0x08F2C3U, 0x01212DU, 0x5A3ABCU, 0x518B43U, 0x29D11AU, 0x62628DU,
0x7FFD64U, 0x34ACB3U, 0x6F1E8AU, 0xE64555U, 0x95C494U, 0x9D7F2BU, 0xC62C7AU, 0x8DB485U, 0x94871DU, 0xFF5CDEU,
0xE6EFE3U, 0xADB730U, 0xF524CFU, 0xFE0F56U, 0xA5DE31U, 0x48C5E8U, 0x53377FU, 0x1AAE86U, 0x01BD59U, 0x4B4678U,
0x3A50A7U, 0x31E977U, 0x683ACCU, 0x633189U, 0x38C072U, 0x71DAEFU, 0x4B493CU, 0x82B001U, 0x99A3C2U, 0xD2383FU,
0x8F4AA4U, 0xA4D3D1U, 0xFDA00AU, 0xB62B8FU, 0xACBB75U, 0xE5C028U, 0xF6539BU, 0x9F4242U, 0xC4B985U, 0x4F2FBCU,
0x167463U, 0x1CC5D2U, 0x65DE1DU, 0x2E3C4CU, 0x35A5F3U, 0x78F622U, 0x234DDDU, 0x0A5C55U, 0x408622U, 0x5BB5FBU,
0x122E6CU, 0xC1FF95U, 0xC8C4DEU, 0xB3066BU, 0xB83FB0U, 0xE0AC25U, 0xAB775EU, 0xB24793U, 0xD9DC20U, 0x828BFDU,
0x8F30AFU, 0xD46102U, 0xDCDBD9U, 0x07582CU, 0x6E0137U, 0x75B2C6U, 0x3EE809U, 0x2F7990U, 0x64C2E7U, 0x1C913EU,
0x170A89U, 0x4C3A40U, 0x45E9D6U, 0x1E42AFU, 0x571370U, 0xE889C1U, 0xA2BA0EU, 0xFB635FU, 0xF070E0U, 0xA9CF39U,
0x821DDAU, 0xD904C7U, 0x90F734U, 0x82FCE9U, 0xCB4D72U, 0xD09716U, 0x3B848DU, 0x623D78U, 0x696EA3U, 0x30F4BEU,
0x7A075DU, 0x451E80U, 0x0C8D33U, 0x17E66EU, 0x5E76B5U, 0x050D14U, 0x0E9ECBU, 0x7607BAU, 0xF57524U, 0xACEAC5U,
0xE7F91AU, 0xFC0083U, 0x9583F4U, 0xCED96DU, 0xC6688AU, 0x9D7353U, 0x92804CU, 0xCB11BDU, 0xA00B62U, 0xA9F8C3U,
0x72E398U, 0x783244U, 0x2118F7U, 0x4A8B2AU, 0x5B5249U, 0x1061D4U, 0x09FA2FU, 0x428ABAU, 0x1911F1U, 0x31C604U,
0x6AFD9FU, 0x276D62U, 0xBC2631U, 0xF795B8U, 0xCE4C4EU, 0x855F97U, 0xDDE520U, 0xD6B479U, 0x8D0FB6U, 0x8C1C07U,
0xF7C6D8U, 0xBE77A9U, 0xA53C36U, 0xEFAFDFU, 0x369648U, 0x1D4411U, 0x40DFE6U, 0x4BEE7EU, 0x103595U, 0x5902C0U,
0x43D85BU, 0x2AC9AEU, 0x316265U, 0x7AB158U, 0x23A18BU, 0x201A56U, 0xD949E5U, 0x93F2A8U, 0x882313U, 0xC139C6U,
0xDA8A3CU, 0x97D329U, 0xEC50E2U, 0xE7AA13U, 0xBFBB8CU, 0xB42075U, 0xED5322U, 0x06C8ABU, 0x1DF85CU, 0x542785U,
0x0FB4BAU, 0x0FCD7BU, 0x544FA4U, 0x7F5414U, 0x26A54BU, 0x6D3EF2U, 0x702D31U, 0x3BD7CCU, 0x13C6DFU, 0xC83D02U,
0x83AEF9U, 0x9AB77CU, 0xD15507U, 0xC84ED2U, 0xA3DF49U, 0xF9A4BDU, 0xF836F6U, 0xA3ED4BU, 0xEADC98U, 0xD14B05U,
0x9A30E6U, 0x03A0BFU, 0x4D6B00U, 0x1458D1U, 0x1FC12EU, 0x64932FU, 0x6D28F0U, 0x36BB09U, 0x7FE29FU, 0x6551E6U,
0x0E0B21U, 0x57AAB8U, 0x54B147U, 0x8D6216U, 0x86DBA9U, 0xDDC968U, 0xB412F3U, 0xAA218EU, 0xE3FC5DU, 0xF86EF0U,
0xB35523U, 0xCA945FU, 0xC1AFCCU, 0x983C11U, 0xD264FAU, 0x49D7EFU, 0x000C14U, 0x3B1FC1U, 0x7AA75AU, 0x21F4B7U,
0x2A6FA4U, 0x728E5DU, 0x5D958AU, 0x042713U, 0x4F767DU, 0x54EDACU, 0x1D5E13U, 0x8604C0U, 0xEE91ADU, 0xB5EA36U,
0xBC79E3U, 0xE77018U, 0xAC820DU, 0x9D19E6U, 0xD6283FU, 0xCEF3A8U, 0x85E0D1U, 0xDA1A47U, 0x538BAEU, 0x389079U,
0x216360U, 0x6A6B9FU, 0x30D84EU, 0x3903E1U, 0x421230U, 0x0BE94FU, 0x10FBD6U, 0x5B6011U, 0x4215E8U, 0x008EFBU,
0xF95C07U, 0xF2759CU, 0xADE659U, 0xA49D22U, 0xFF0CB7U, 0x96964CU, 0x8CE591U, 0xC77E92U, 0x9E2F6FU, 0x959CBCU,
0xCC0601U, 0xE7475AU, 0x3CFCBFU, 0x74EF25U, 0x6717F4U, 0x2E048BU, 0x15DF0AU, 0x5A6CF5U, 0x03716CU, 0x08A33BU,
0x5098C2U, 0x5B1945U, 0x20C2BCU, 0x69F063U, 0xF22972U, 0xBB1A8DU, 0xE0814DU, 0xCA52F6U, 0x936AABU, 0x98B958U,
0xC9A2C5U, 0x820306U, 0x9B593BU, 0xF4CAE0U, 0xEE7315U, 0xA7209EU, 0x7C9BCBU, 0x75C930U, 0x0E54A4U, 0x45E75FU,
0x5CBC12U, 0x173D81U, 0x0F0778U, 0x44D4AFU, 0x3FC596U, 0x363E59U, 0x65ACE8U, 0x6C9737U, 0xA346E6U, 0xD95DD9U,
0xD0FE10U, 0x8B26E6U, 0xC2357FU, 0xD9CE28U, 0x92DDC1U, 0xAB455EU, 0xE1B6AFU, 0xB8ADF4U, 0xB35861U, 0x68438AU,
0x41C157U, 0x12B864U, 0x5B2BB9U, 0x45B00AU, 0x0EC3C6U, 0x175B95U, 0x7C2828U, 0x25B3F3U, 0x2E2206U, 0x75580DU,
0x3DDBD8U, 0x86C223U, 0xCF31BAU, 0xD4AADDU, 0x9FF804U, 0xC64193U, 0xCD526AU, 0xBDA9F4U, 0xB2BD95U, 0xE92E4AU,
0xA0C5FBU, 0xBBD424U, 0xD20F7DU, 0x093DDAU, 0x01A603U, 0x5A77F0U, 0x514CEDU, 0x089E36U, 0x63A7D3U, 0x7A3448U,
0x31FF3CU, 0x2BCEE7U, 0x625462U, 0x150799U, 0x1CBC84U, 0xC7ED77U, 0x8C76AAU, 0x95C409U, 0xDF9954U, 0xE62A8FU,
0xAD213EU, 0xF6F1E1U, 0xFF4A00U, 0xA4191EU, 0x8D82C7U, 0xD7B330U, 0x9C69A9U, 0x057ACEU, 0x42C357U, 0x2B1088U,
0x303A79U, 0x7BEB76U, 0x63F087U, 0x284358U, 0x7198E1U, 0x5A88B2U, 0x017B7EU, 0x0860CDU, 0x53F510U, 0x9A0F63U,
0xA00CFEU, 0xEBB535U, 0xF2E6C0U, 0xB97DDBU, 0xEC0F2EU, 0xE796B5U, 0x9C0578U, 0xD47E0BU, 0xCFEF92U, 0x86F564U,
0x1D16ADU, 0x768F32U, 0x2FFC43U, 0x24669CU, 0x7C752DU, 0x778CE2U, 0x2E1F9BU, 0x45000CU, 0x5EF0D5U, 0x13FB62U,
0x40282BU, 0x4811D4U, 0xB38344U, 0xB8789FU, 0xE16BEAU, 0xAAB261U, 0xB38194U, 0xF81B4FU, 0xC2CA52U, 0x8BE1B1U,
0xD0726CU, 0xD903DFU, 0x829982U, 0xE94A79U, 0x7471FDU, 0x36E026U, 0x2FBA93U, 0x640DC8U, 0x3F1431U, 0x16D7B6U,
0x4D6C6FU, 0x443C18U, 0x1E8781U, 0x55947EU, 0x6C4FBFU, 0x27FFA0U, 0xBEE451U, 0xF5378FU, 0xAE0E2EU, 0xA2CD71U,
0xC9D7C8U, 0x98661FU, 0x93BDC6U, 0xC88EE5U, 0xC15438U, 0xBA45C3U, 0xF2FE56U, 0xE9290DU, 0x2230E8U, 0x3B9273U,
0x70C98FU, 0x0958DCU, 0x02A343U, 0x58B0A2U, 0x150A7DU, 0x0E5BC4U, 0x6FC897U, 0x74F33AU, 0x3F23E9U, 0x66A834U,
0xECDB0FU, 0xB542DAU, 0x9E5131U, 0xC7ABA5U, 0x8C38FEU, 0x97010BU, 0xDED290U, 0xA4CC7DU, 0xAD3D2EU, 0xF6B6B3U,
0xF9A540U, 0x205ED9U, 0x634EB6U, 0x5A9567U, 0x11A6D8U, 0x0B3F09U };
const unsigned int A_TABLE[] = { 0U, 4U, 8U, 12U, 16U, 20U, 24U, 28U, 32U, 36U, 40U, 44U,
48U, 52U, 56U, 60U, 64U, 68U, 1U, 5U, 9U, 13U, 17U, 21U };
const unsigned int B_TABLE[] = { 25U, 29U, 33U, 37U, 41U, 45U, 49U, 53U, 57U, 61U, 65U, 69U,
2U, 6U, 10U, 14U, 18U, 22U, 26U, 30U, 34U, 38U, 42U };
const unsigned int C_TABLE[] = { 46U, 50U, 54U, 58U, 62U, 66U, 70U, 3U, 7U, 11U, 15U, 19U,
23U, 27U, 31U, 35U, 39U, 43U, 47U, 51U, 55U, 59U, 63U, 67U, 71U };
CNXDNAudio::CNXDNAudio()
{
}
CNXDNAudio::~CNXDNAudio()
{
}
void CNXDNAudio::decode(const unsigned char* in, unsigned char* out) const
{
assert(in != NULL);
assert(out != NULL);
decode(in + 0U, out, 0U);
decode(in + 9U, out, 49U);
}
void CNXDNAudio::encode(const unsigned char* in, unsigned char* out) const
{
assert(in != NULL);
assert(out != NULL);
encode(in, out + 0U, 0U);
encode(in, out + 9U, 49U);
}
void CNXDNAudio::decode(const unsigned char* in, unsigned char* out, unsigned int offset) const
{
assert(in != NULL);
assert(out != NULL);
unsigned int a = 0U;
unsigned int MASK = 0x800000U;
for (unsigned int i = 0U; i < 24U; i++, MASK >>= 1) {
unsigned int aPos = A_TABLE[i];
if (READ_BIT(in, aPos))
a |= MASK;
}
unsigned int b = 0U;
MASK = 0x400000U;
for (unsigned int i = 0U; i < 23U; i++, MASK >>= 1) {
unsigned int bPos = B_TABLE[i];
if (READ_BIT(in, bPos))
b |= MASK;
}
unsigned int c = 0U;
MASK = 0x1000000U;
for (unsigned int i = 0U; i < 25U; i++, MASK >>= 1) {
unsigned int cPos = C_TABLE[i];
if (READ_BIT(in, cPos))
c |= MASK;
}
a >>= 12;
// The PRNG
b ^= (PRNG_TABLE[a] >> 1);
b >>= 11;
MASK = 0x000800U;
for (unsigned int i = 0U; i < 12U; i++, MASK >>= 1) {
unsigned int aPos = i + offset + 0U;
unsigned int bPos = i + offset + 12U;
WRITE_BIT(out, aPos, a & MASK);
WRITE_BIT(out, bPos, b & MASK);
}
MASK = 0x1000000U;
for (unsigned int i = 0U; i < 25U; i++, MASK >>= 1) {
unsigned int cPos = i + offset + 24U;
WRITE_BIT(out, cPos, c & MASK);
}
}
void CNXDNAudio::encode(const unsigned char* in, unsigned char* out, unsigned int offset) const
{
assert(in != NULL);
assert(out != NULL);
unsigned int aOrig = 0U;
unsigned int bOrig = 0U;
unsigned int cOrig = 0U;
unsigned int MASK = 0x000800U;
for (unsigned int i = 0U; i < 12U; i++, MASK >>= 1) {
unsigned int n1 = i + offset + 0U;
unsigned int n2 = i + offset + 12U;
if (READ_BIT(in, n1))
aOrig |= MASK;
if (READ_BIT(in, n2))
bOrig |= MASK;
}
MASK = 0x1000000U;
for (unsigned int i = 0U; i < 25U; i++, MASK >>= 1) {
unsigned int n = i + offset + 24U;
if (READ_BIT(in, n))
cOrig |= MASK;
}
unsigned int a = CGolay24128::encode24128(aOrig);
// The PRNG
unsigned int p = PRNG_TABLE[aOrig] >> 1;
unsigned int b = CGolay24128::encode23127(bOrig) >> 1;
b ^= p;
MASK = 0x800000U;
for (unsigned int i = 0U; i < 24U; i++, MASK >>= 1) {
unsigned int aPos = A_TABLE[i];
WRITE_BIT(out, aPos, a & MASK);
}
MASK = 0x400000U;
for (unsigned int i = 0U; i < 23U; i++, MASK >>= 1) {
unsigned int bPos = B_TABLE[i];
WRITE_BIT(out, bPos, b & MASK);
}
MASK = 0x1000000U;
for (unsigned int i = 0U; i < 25U; i++, MASK >>= 1) {
unsigned int cPos = C_TABLE[i];
WRITE_BIT(out, cPos, cOrig & MASK);
}
}

View file

@ -1,185 +0,0 @@
/*
* Copyright (C) 2018 by Jonathan Naylor G4KLX
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "NXDNCRC.h"
#include <cstdio>
#include <cassert>
const uint8_t BIT_MASK_TABLE1[] = { 0x80U, 0x40U, 0x20U, 0x10U, 0x08U, 0x04U, 0x02U, 0x01U };
#define WRITE_BIT1(p,i,b) p[(i)>>3] = (b) ? (p[(i)>>3] | BIT_MASK_TABLE1[(i)&7]) : (p[(i)>>3] & ~BIT_MASK_TABLE1[(i)&7])
#define READ_BIT1(p,i) (p[(i)>>3] & BIT_MASK_TABLE1[(i)&7])
bool CNXDNCRC::checkCRC6(const unsigned char* in, unsigned int length)
{
assert(in != NULL);
uint8_t crc = createCRC6(in, length);
uint8_t temp[1U];
temp[0U] = 0x00U;
unsigned int j = length;
for (unsigned int i = 2U; i < 8U; i++, j++) {
bool b = READ_BIT1(in, j);
WRITE_BIT1(temp, i, b);
}
return crc == temp[0U];
}
void CNXDNCRC::encodeCRC6(unsigned char* in, unsigned int length)
{
assert(in != NULL);
uint8_t crc[1U];
crc[0U] = createCRC6(in, length);
unsigned int n = length;
for (unsigned int i = 2U; i < 8U; i++, n++) {
bool b = READ_BIT1(crc, i);
WRITE_BIT1(in, n, b);
}
}
bool CNXDNCRC::checkCRC12(const unsigned char* in, unsigned int length)
{
assert(in != NULL);
uint16_t crc = createCRC12(in, length);
uint8_t temp1[2U];
temp1[0U] = (crc >> 8) & 0xFFU;
temp1[1U] = (crc >> 0) & 0xFFU;
uint8_t temp2[2U];
temp2[0U] = 0x00U;
temp2[1U] = 0x00U;
unsigned int j = length;
for (unsigned int i = 4U; i < 16U; i++, j++) {
bool b = READ_BIT1(in, j);
WRITE_BIT1(temp2, i, b);
}
return temp1[0U] == temp2[0U] && temp1[1U] == temp2[1U];
}
void CNXDNCRC::encodeCRC12(unsigned char* in, unsigned int length)
{
assert(in != NULL);
uint16_t crc = createCRC12(in, length);
uint8_t temp[2U];
temp[0U] = (crc >> 8) & 0xFFU;
temp[1U] = (crc >> 0) & 0xFFU;
unsigned int n = length;
for (unsigned int i = 4U; i < 16U; i++, n++) {
bool b = READ_BIT1(temp, i);
WRITE_BIT1(in, n, b);
}
}
bool CNXDNCRC::checkCRC15(const unsigned char* in, unsigned int length)
{
assert(in != NULL);
uint16_t crc = createCRC15(in, length);
uint8_t temp1[2U];
temp1[0U] = (crc >> 8) & 0xFFU;
temp1[1U] = (crc >> 0) & 0xFFU;
uint8_t temp2[2U];
temp2[0U] = 0x00U;
temp2[1U] = 0x00U;
unsigned int j = length;
for (unsigned int i = 1U; i < 16U; i++, j++) {
bool b = READ_BIT1(in, j);
WRITE_BIT1(temp2, i, b);
}
return temp1[0U] == temp2[0U] && temp1[1U] == temp2[1U];
}
void CNXDNCRC::encodeCRC15(unsigned char* in, unsigned int length)
{
assert(in != NULL);
uint16_t crc = createCRC15(in, length);
uint8_t temp[2U];
temp[0U] = (crc >> 8) & 0xFFU;
temp[1U] = (crc >> 0) & 0xFFU;
unsigned int n = length;
for (unsigned int i = 1U; i < 16U; i++, n++) {
bool b = READ_BIT1(temp, i);
WRITE_BIT1(in, n, b);
}
}
uint8_t CNXDNCRC::createCRC6(const unsigned char* in, unsigned int length)
{
uint8_t crc = 0x3FU;
for (unsigned int i = 0U; i < length; i++) {
bool bit1 = READ_BIT1(in, i) != 0x00U;
bool bit2 = (crc & 0x20U) == 0x20U;
crc <<= 1;
if (bit1 ^ bit2)
crc ^= 0x27U;
}
return crc & 0x3FU;
}
uint16_t CNXDNCRC::createCRC12(const unsigned char* in, unsigned int length)
{
uint16_t crc = 0x0FFFU;
for (unsigned int i = 0U; i < length; i++) {
bool bit1 = READ_BIT1(in, i) != 0x00U;
bool bit2 = (crc & 0x0800U) == 0x0800U;
crc <<= 1;
if (bit1 ^ bit2)
crc ^= 0x080FU;
}
return crc & 0x0FFFU;
}
uint16_t CNXDNCRC::createCRC15(const unsigned char* in, unsigned int length)
{
uint16_t crc = 0x7FFFU;
for (unsigned int i = 0U; i < length; i++) {
bool bit1 = READ_BIT1(in, i) != 0x00U;
bool bit2 = (crc & 0x4000U) == 0x4000U;
crc <<= 1;
if (bit1 ^ bit2)
crc ^= 0x4CC5U;
}
return crc & 0x7FFFU;
}

View file

@ -1,42 +0,0 @@
/*
* Copyright (C) 2018 by Jonathan Naylor G4KLX
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#if !defined(NXDNCRC_H)
#define NXDNCRC_H
#include <cstdint>
class CNXDNCRC
{
public:
static bool checkCRC6(const unsigned char* in, unsigned int length);
static void encodeCRC6(unsigned char* in, unsigned int length);
static bool checkCRC12(const unsigned char* in, unsigned int length);
static void encodeCRC12(unsigned char* in, unsigned int length);
static bool checkCRC15(const unsigned char* in, unsigned int length);
static void encodeCRC15(unsigned char* in, unsigned int length);
private:
static uint8_t createCRC6(const unsigned char* in, unsigned int length);
static uint16_t createCRC12(const unsigned char* in, unsigned int length);
static uint16_t createCRC15(const unsigned char* in, unsigned int length);
};
#endif

File diff suppressed because it is too large Load diff

View file

@ -1,105 +0,0 @@
/*
* Copyright (C) 2015-2020 by Jonathan Naylor G4KLX
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* 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(NXDNControl_H)
#define NXDNControl_H
#include "RSSIInterpolator.h"
#include "NXDNNetwork.h"
#include "NXDNDefines.h"
#include "NXDNLayer3.h"
#include "NXDNLookup.h"
#include "RingBuffer.h"
#include "StopWatch.h"
#include "NXDNLICH.h"
#include "Display.h"
#include "Defines.h"
#include "Timer.h"
#include "Modem.h"
#include <string>
class CNXDNControl {
public:
CNXDNControl(unsigned int ran, unsigned int id, bool selfOnly, INXDNNetwork* network, CDisplay* display, unsigned int timeout, bool duplex, bool remoteGateway, CNXDNLookup* lookup, CRSSIInterpolator* rssiMapper);
~CNXDNControl();
bool writeModem(unsigned char* data, unsigned int len);
unsigned int readModem(unsigned char* data);
void clock(unsigned int ms);
bool isBusy() const;
void enable(bool enabled);
private:
unsigned int m_ran;
unsigned int m_id;
bool m_selfOnly;
INXDNNetwork* m_network;
CDisplay* m_display;
bool m_duplex;
bool m_remoteGateway;
CNXDNLookup* m_lookup;
CRingBuffer<unsigned char> m_queue;
RPT_RF_STATE m_rfState;
RPT_NET_STATE m_netState;
CTimer m_rfTimeoutTimer;
CTimer m_netTimeoutTimer;
CTimer m_packetTimer;
CTimer m_networkWatchdog;
CStopWatch m_elapsed;
unsigned int m_rfFrames;
unsigned int m_netFrames;
unsigned int m_rfErrs;
unsigned int m_rfBits;
CNXDNLICH m_rfLastLICH;
CNXDNLayer3 m_rfLayer3;
CNXDNLayer3 m_netLayer3;
unsigned char m_rfMask;
unsigned char m_netMask;
CRSSIInterpolator* m_rssiMapper;
unsigned char m_rssi;
unsigned char m_maxRSSI;
unsigned char m_minRSSI;
unsigned int m_aveRSSI;
unsigned int m_rssiCount;
bool m_enabled;
FILE* m_fp;
bool processVoice(unsigned char usc, unsigned char option, unsigned char *data);
bool processData(unsigned char option, unsigned char *data);
void writeQueueRF(const unsigned char* data);
void writeQueueNet(const unsigned char* data);
void writeNetwork(const unsigned char* data, NXDN_NETWORK_MESSAGE_TYPE type);
void writeNetwork();
void scrambler(unsigned char* data) const;
void writeEndRF();
void writeEndNet();
bool openFile();
bool writeFile(const unsigned char* data);
void closeFile();
};
#endif

View file

@ -1,142 +0,0 @@
/*
* Copyright (C) 2009-2016,2018 by Jonathan Naylor G4KLX
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "NXDNConvolution.h"
#include <cstdio>
#include <cassert>
#include <cstring>
#include <cstdlib>
const unsigned char BIT_MASK_TABLE[] = {0x80U, 0x40U, 0x20U, 0x10U, 0x08U, 0x04U, 0x02U, 0x01U};
#define WRITE_BIT1(p,i,b) p[(i)>>3] = (b) ? (p[(i)>>3] | BIT_MASK_TABLE[(i)&7]) : (p[(i)>>3] & ~BIT_MASK_TABLE[(i)&7])
#define READ_BIT1(p,i) (p[(i)>>3] & BIT_MASK_TABLE[(i)&7])
const uint8_t BRANCH_TABLE1[] = {0U, 0U, 0U, 0U, 2U, 2U, 2U, 2U};
const uint8_t BRANCH_TABLE2[] = {0U, 2U, 2U, 0U, 0U, 2U, 2U, 0U};
const unsigned int NUM_OF_STATES_D2 = 8U;
const unsigned int NUM_OF_STATES = 16U;
const uint32_t M = 4U;
const unsigned int K = 5U;
CNXDNConvolution::CNXDNConvolution() :
m_metrics1(NULL),
m_metrics2(NULL),
m_oldMetrics(NULL),
m_newMetrics(NULL),
m_decisions(NULL),
m_dp(NULL)
{
m_metrics1 = new uint16_t[16U];
m_metrics2 = new uint16_t[16U];
m_decisions = new uint64_t[300U];
}
CNXDNConvolution::~CNXDNConvolution()
{
delete[] m_metrics1;
delete[] m_metrics2;
delete[] m_decisions;
}
void CNXDNConvolution::start()
{
::memset(m_metrics1, 0x00U, NUM_OF_STATES * sizeof(uint16_t));
::memset(m_metrics2, 0x00U, NUM_OF_STATES * sizeof(uint16_t));
m_oldMetrics = m_metrics1;
m_newMetrics = m_metrics2;
m_dp = m_decisions;
}
void CNXDNConvolution::decode(uint8_t s0, uint8_t s1)
{
*m_dp = 0U;
for (uint8_t i = 0U; i < NUM_OF_STATES_D2; i++) {
uint8_t j = i * 2U;
uint16_t metric = std::abs(BRANCH_TABLE1[i] - s0) + std::abs(BRANCH_TABLE2[i] - s1);
uint16_t m0 = m_oldMetrics[i] + metric;
uint16_t m1 = m_oldMetrics[i + NUM_OF_STATES_D2] + (M - metric);
uint8_t decision0 = (m0 >= m1) ? 1U : 0U;
m_newMetrics[j + 0U] = decision0 != 0U ? m1 : m0;
m0 = m_oldMetrics[i] + (M - metric);
m1 = m_oldMetrics[i + NUM_OF_STATES_D2] + metric;
uint8_t decision1 = (m0 >= m1) ? 1U : 0U;
m_newMetrics[j + 1U] = decision1 != 0U ? m1 : m0;
*m_dp |= (uint64_t(decision1) << (j + 1U)) | (uint64_t(decision0) << (j + 0U));
}
++m_dp;
assert((m_dp - m_decisions) <= 300);
uint16_t* tmp = m_oldMetrics;
m_oldMetrics = m_newMetrics;
m_newMetrics = tmp;
}
void CNXDNConvolution::chainback(unsigned char* out, unsigned int nBits)
{
assert(out != NULL);
uint32_t state = 0U;
while (nBits-- > 0) {
--m_dp;
uint32_t i = state >> (9 - K);
uint8_t bit = uint8_t(*m_dp >> i) & 1;
state = (bit << 7) | (state >> 1);
WRITE_BIT1(out, nBits, bit != 0U);
}
}
void CNXDNConvolution::encode(const unsigned char* in, unsigned char* out, unsigned int nBits) const
{
assert(in != NULL);
assert(out != NULL);
assert(nBits > 0U);
uint8_t d1 = 0U, d2 = 0U, d3 = 0U, d4 = 0U;
uint32_t k = 0U;
for (unsigned int i = 0U; i < nBits; i++) {
uint8_t d = READ_BIT1(in, i) ? 1U : 0U;
uint8_t g1 = (d + d3 + d4) & 1;
uint8_t g2 = (d + d1 + d2 + d4) & 1;
d4 = d3;
d3 = d2;
d2 = d1;
d1 = d;
WRITE_BIT1(out, k, g1 != 0U);
k++;
WRITE_BIT1(out, k, g2 != 0U);
k++;
}
}

View file

@ -1,45 +0,0 @@
/*
* Copyright (C) 2015,2016,2018 by Jonathan Naylor G4KLX
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#if !defined(NXDNConvolution_H)
#define NXDNConvolution_H
#include <cstdint>
class CNXDNConvolution {
public:
CNXDNConvolution();
~CNXDNConvolution();
void start();
void decode(uint8_t s0, uint8_t s1);
void chainback(unsigned char* out, unsigned int nBits);
void encode(const unsigned char* in, unsigned char* out, unsigned int nBits) const;
private:
uint16_t* m_metrics1;
uint16_t* m_metrics2;
uint16_t* m_oldMetrics;
uint16_t* m_newMetrics;
uint64_t* m_decisions;
uint64_t* m_dp;
};
#endif

View file

@ -1,102 +0,0 @@
/*
* Copyright (C) 2016,2017,2018 by Jonathan Naylor G4KLX
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#if !defined(NXDNDEFINES_H)
#define NXDNDEFINES_H
const unsigned int NXDN_RADIO_SYMBOL_LENGTH = 5U; // At 24 kHz sample rate
const unsigned int NXDN_FRAME_LENGTH_BITS = 384U;
const unsigned int NXDN_FRAME_LENGTH_BYTES = NXDN_FRAME_LENGTH_BITS / 8U;
const unsigned int NXDN_FRAME_LENGTH_SYMBOLS = NXDN_FRAME_LENGTH_BITS / 2U;
const unsigned int NXDN_FSW_LENGTH_BITS = 20U;
const unsigned int NXDN_FSW_LENGTH_SYMBOLS = NXDN_FSW_LENGTH_BITS / 2U;
const unsigned int NXDN_FSW_LENGTH_SAMPLES = NXDN_FSW_LENGTH_SYMBOLS * NXDN_RADIO_SYMBOL_LENGTH;
const unsigned char NXDN_FSW_BYTES[] = {0xCDU, 0xF5U, 0x90U};
const unsigned char NXDN_FSW_BYTES_MASK[] = {0xFFU, 0xFFU, 0xF0U};
const unsigned int NXDN_FSW_BYTES_LENGTH = 3U;
const unsigned int NXDN_LICH_LENGTH_BITS = 16U;
const unsigned int NXDN_SACCH_LENGTH_BITS = 60U;
const unsigned int NXDN_FACCH1_LENGTH_BITS = 144U;
const unsigned int NXDN_FACCH2_LENGTH_BITS = 348U;
const unsigned int NXDN_FSW_LICH_SACCH_LENGTH_BITS = NXDN_FSW_LENGTH_BITS + NXDN_LICH_LENGTH_BITS + NXDN_SACCH_LENGTH_BITS;
const unsigned int NXDN_FSW_LICH_SACCH_LENGTH_BYTES = NXDN_FSW_LICH_SACCH_LENGTH_BITS / 8U;
const unsigned char NXDN_LICH_RFCT_RCCH = 0U;
const unsigned char NXDN_LICH_RFCT_RTCH = 1U;
const unsigned char NXDN_LICH_RFCT_RDCH = 2U;
const unsigned char NXDN_LICH_RFCT_RTCH_C = 3U;
const unsigned char NXDN_LICH_USC_SACCH_NS = 0U;
const unsigned char NXDN_LICH_USC_UDCH = 1U;
const unsigned char NXDN_LICH_USC_SACCH_SS = 2U;
const unsigned char NXDN_LICH_USC_SACCH_SS_IDLE = 3U;
const unsigned char NXDN_LICH_STEAL_NONE = 3U;
const unsigned char NXDN_LICH_STEAL_FACCH1_2 = 2U;
const unsigned char NXDN_LICH_STEAL_FACCH1_1 = 1U;
const unsigned char NXDN_LICH_STEAL_FACCH = 0U;
const unsigned char NXDN_LICH_DIRECTION_INBOUND = 0U;
const unsigned char NXDN_LICH_DIRECTION_OUTBOUND = 1U;
const unsigned char NXDN_SR_SINGLE = 0U;
const unsigned char NXDN_SR_4_4 = 0U;
const unsigned char NXDN_SR_3_4 = 1U;
const unsigned char NXDN_SR_2_4 = 2U;
const unsigned char NXDN_SR_1_4 = 3U;
const unsigned char NXDN_MESSAGE_TYPE_VCALL = 0x01U;
const unsigned char NXDN_MESSAGE_TYPE_VCALL_IV = 0x03U;
const unsigned char NXDN_MESSAGE_TYPE_DCALL_HDR = 0x09U;
const unsigned char NXDN_MESSAGE_TYPE_DCALL_DATA = 0x0BU;
const unsigned char NXDN_MESSAGE_TYPE_DCALL_ACK = 0x0CU;
const unsigned char NXDN_MESSAGE_TYPE_TX_REL = 0x08U;
const unsigned char NXDN_MESSAGE_TYPE_HEAD_DLY = 0x0FU;
const unsigned char NXDN_MESSAGE_TYPE_SDCALL_REQ_HDR = 0x38U;
const unsigned char NXDN_MESSAGE_TYPE_SDCALL_REQ_DATA = 0x39U;
const unsigned char NXDN_MESSAGE_TYPE_SDCALL_RESP = 0x3BU;
const unsigned char NXDN_MESSAGE_TYPE_SDCALL_IV = 0x3AU;
const unsigned char NXDN_MESSAGE_TYPE_STAT_INQ_REQ = 0x30U;
const unsigned char NXDN_MESSAGE_TYPE_STAT_INQ_RESP = 0x31U;
const unsigned char NXDN_MESSAGE_TYPE_STAT_REQ = 0x32U;
const unsigned char NXDN_MESSAGE_TYPE_STAT_RESP = 0x33U;
const unsigned char NXDN_MESSAGE_TYPE_REM_CON_REQ = 0x34U;
const unsigned char NXDN_MESSAGE_TYPE_REM_CON_RESP = 0x35U;
const unsigned char NXDN_MESSAGE_TYPE_IDLE = 0x10U;
const unsigned char NXDN_MESSAGE_TYPE_AUTH_INQ_REQ = 0x28U;
const unsigned char NXDN_MESSAGE_TYPE_AUTH_INQ_RESP = 0x29U;
const unsigned char NXDN_MESSAGE_TYPE_PROP_FORM = 0x3FU;
const unsigned char NXDN_VOICE_CALL_OPTION_HALF_DUPLEX = 0x00U;
const unsigned char NXDN_VOICE_CALL_OPTION_DUPLEX = 0x10U;
const unsigned char NXDN_DATA_CALL_OPTION_HALF_DUPLEX = 0x00U;
const unsigned char NXDN_DATA_CALL_OPTION_DUPLEX = 0x10U;
const unsigned char NXDN_DATA_CALL_OPTION_4800 = 0x00U;
const unsigned char NXDN_DATA_CALL_OPTION_9600 = 0x02U;
const unsigned char SACCH_IDLE[] = { NXDN_MESSAGE_TYPE_IDLE, 0x00U, 0x00U };
#endif

View file

@ -1,188 +0,0 @@
/*
* Copyright (C) 2018 by Jonathan Naylor G4KLX
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "NXDNFACCH1.h"
#include "NXDNConvolution.h"
#include "NXDNDefines.h"
#include "NXDNCRC.h"
#include <cstdio>
#include <cassert>
#include <cstring>
const unsigned int INTERLEAVE_TABLE[] = {
0U, 9U, 18U, 27U, 36U, 45U, 54U, 63U, 72U, 81U, 90U, 99U, 108U, 117U, 126U, 135U,
1U, 10U, 19U, 28U, 37U, 46U, 55U, 64U, 73U, 82U, 91U, 100U, 109U, 118U, 127U, 136U,
2U, 11U, 20U, 29U, 38U, 47U, 56U, 65U, 74U, 83U, 92U, 101U, 110U, 119U, 128U, 137U,
3U, 12U, 21U, 30U, 39U, 48U, 57U, 66U, 75U, 84U, 93U, 102U, 111U, 120U, 129U, 138U,
4U, 13U, 22U, 31U, 40U, 49U, 58U, 67U, 76U, 85U, 94U, 103U, 112U, 121U, 130U, 139U,
5U, 14U, 23U, 32U, 41U, 50U, 59U, 68U, 77U, 86U, 95U, 104U, 113U, 122U, 131U, 140U,
6U, 15U, 24U, 33U, 42U, 51U, 60U, 69U, 78U, 87U, 96U, 105U, 114U, 123U, 132U, 141U,
7U, 16U, 25U, 34U, 43U, 52U, 61U, 70U, 79U, 88U, 97U, 106U, 115U, 124U, 133U, 142U,
8U, 17U, 26U, 35U, 44U, 53U, 62U, 71U, 80U, 89U, 98U, 107U, 116U, 125U, 134U, 143U };
const unsigned int PUNCTURE_LIST[] = { 1U, 5U, 9U, 13U, 17U, 21U, 25U, 29U, 33U, 37U,
41U, 45U, 49U, 53U, 57U, 61U, 65U, 69U, 73U, 77U,
81U, 85U, 89U, 93U, 97U, 101U, 105U, 109U, 113U, 117U,
121U, 125U, 129U, 133U, 137U, 141U, 145U, 149U, 153U, 157U,
161U, 165U, 169U, 173U, 177U, 181U, 185U, 189U };
const unsigned char BIT_MASK_TABLE[] = { 0x80U, 0x40U, 0x20U, 0x10U, 0x08U, 0x04U, 0x02U, 0x01U };
#define WRITE_BIT1(p,i,b) p[(i)>>3] = (b) ? (p[(i)>>3] | BIT_MASK_TABLE[(i)&7]) : (p[(i)>>3] & ~BIT_MASK_TABLE[(i)&7])
#define READ_BIT1(p,i) (p[(i)>>3] & BIT_MASK_TABLE[(i)&7])
CNXDNFACCH1::CNXDNFACCH1(const CNXDNFACCH1& facch1) :
m_data(NULL)
{
m_data = new unsigned char[10U + 2U];
::memcpy(m_data, facch1.m_data, 10U + 2U);
}
CNXDNFACCH1::CNXDNFACCH1() :
m_data(NULL)
{
m_data = new unsigned char[10U + 2U];
}
CNXDNFACCH1::~CNXDNFACCH1()
{
delete[] m_data;
}
bool CNXDNFACCH1::decode(const unsigned char* data, unsigned int offset)
{
assert(data != NULL);
unsigned char temp1[18U];
for (unsigned int i = 0U; i < NXDN_FACCH1_LENGTH_BITS; i++) {
unsigned int n = INTERLEAVE_TABLE[i] + offset;
bool b = READ_BIT1(data, n);
WRITE_BIT1(temp1, i, b);
}
uint8_t temp2[210U];
unsigned int n = 0U;
unsigned int index = 0U;
for (unsigned int i = 0U; i < NXDN_FACCH1_LENGTH_BITS; i++) {
if (n == PUNCTURE_LIST[index]) {
temp2[n++] = 1U;
index++;
}
bool b = READ_BIT1(temp1, i);
temp2[n++] = b ? 2U : 0U;
}
for (unsigned int i = 0U; i < 8U; i++) {
temp2[n++] = 0U;
}
CNXDNConvolution conv;
conv.start();
n = 0U;
for (unsigned int i = 0U; i < 100U; i++) {
uint8_t s0 = temp2[n++];
uint8_t s1 = temp2[n++];
conv.decode(s0, s1);
}
conv.chainback(m_data, 96U);
return CNXDNCRC::checkCRC12(m_data, 80U);
}
void CNXDNFACCH1::encode(unsigned char* data, unsigned int offset) const
{
assert(data != NULL);
unsigned char temp1[12U];
::memset(temp1, 0x00U, 12U);
::memcpy(temp1, m_data, 10U);
CNXDNCRC::encodeCRC12(temp1, 80U);
unsigned char temp2[24U];
CNXDNConvolution conv;
conv.encode(temp1, temp2, 96U);
unsigned char temp3[18U];
unsigned int n = 0U;
unsigned int index = 0U;
for (unsigned int i = 0U; i < 192U; i++) {
if (i != PUNCTURE_LIST[index]) {
bool b = READ_BIT1(temp2, i);
WRITE_BIT1(temp3, n, b);
n++;
} else {
index++;
}
}
for (unsigned int i = 0U; i < NXDN_FACCH1_LENGTH_BITS; i++) {
unsigned int n = INTERLEAVE_TABLE[i] + offset;
bool b = READ_BIT1(temp3, i);
WRITE_BIT1(data, n, b);
}
}
void CNXDNFACCH1::getData(unsigned char* data) const
{
assert(data != NULL);
::memcpy(data, m_data, 10U);
}
void CNXDNFACCH1::getRaw(unsigned char* data) const
{
assert(data != NULL);
::memset(data, 0x00U, 12U);
::memcpy(data, m_data, 10U);
CNXDNCRC::encodeCRC12(data, 80U);
}
void CNXDNFACCH1::setData(const unsigned char* data)
{
assert(data != NULL);
::memcpy(m_data, data, 10U);
}
void CNXDNFACCH1::setRaw(const unsigned char* data)
{
assert(data != NULL);
::memcpy(m_data, data, 12U);
}
CNXDNFACCH1& CNXDNFACCH1::operator=(const CNXDNFACCH1& facch1)
{
if (&facch1 != this)
::memcpy(m_data, facch1.m_data, 10U + 2U);
return *this;
}

View file

@ -1,44 +0,0 @@
/*
* Copyright (C) 2018 by Jonathan Naylor G4KLX
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#if !defined(NXDNFACCH1_H)
#define NXDNFACCH1_H
class CNXDNFACCH1 {
public:
CNXDNFACCH1(const CNXDNFACCH1& facch);
CNXDNFACCH1();
~CNXDNFACCH1();
bool decode(const unsigned char* data, unsigned int offset);
void encode(unsigned char* data, unsigned int offset) const;
void getData(unsigned char* data) const;
void getRaw(unsigned char* data) const;
void setData(const unsigned char* data);
void setRaw(const unsigned char* data);
CNXDNFACCH1& operator=(const CNXDNFACCH1& facch);
private:
unsigned char* m_data;
};
#endif

View file

@ -1,171 +0,0 @@
/*
* Copyright (C) 2009-2014,2016,2018-2020 by Jonathan Naylor G4KLX
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "NXDNIcomNetwork.h"
#include "NXDNDefines.h"
#include "Defines.h"
#include "Utils.h"
#include "Log.h"
#include <cstdio>
#include <cassert>
#include <cstring>
const unsigned int BUFFER_LENGTH = 200U;
CNXDNIcomNetwork::CNXDNIcomNetwork(const std::string& localAddress, unsigned int localPort, const std::string& gatewayAddress, unsigned int gatewayPort, bool debug) :
m_socket(localAddress, localPort),
m_addr(),
m_addrLen(0U),
m_debug(debug),
m_enabled(false),
m_buffer(1000U, "NXDN Network")
{
assert(gatewayPort > 0U);
assert(!gatewayAddress.empty());
if (CUDPSocket::lookup(gatewayAddress, gatewayPort, m_addr, m_addrLen) != 0)
m_addrLen = 0U;
}
CNXDNIcomNetwork::~CNXDNIcomNetwork()
{
}
bool CNXDNIcomNetwork::open()
{
if (m_addrLen == 0U) {
LogError("Unable to resolve the address of the NXDN Gateway");
return false;
}
LogMessage("Opening NXDN network connection");
return m_socket.open(m_addr);
}
bool CNXDNIcomNetwork::write(const unsigned char* data, NXDN_NETWORK_MESSAGE_TYPE type)
{
assert(data != NULL);
unsigned char buffer[110U];
::memset(buffer, 0x00U, 110U);
buffer[0U] = 'I';
buffer[1U] = 'C';
buffer[2U] = 'O';
buffer[3U] = 'M';
buffer[4U] = 0x01U;
buffer[5U] = 0x01U;
buffer[6U] = 0x08U;
buffer[7U] = 0xE0U;
switch (type) {
case NNMT_VOICE_HEADER:
case NNMT_VOICE_TRAILER:
buffer[37U] = 0x23U;
buffer[38U] = 0x1CU;
buffer[39U] = 0x21U;
break;
case NNMT_VOICE_BODY:
buffer[37U] = 0x23U;
buffer[38U] = 0x10U;
buffer[39U] = 0x21U;
break;
case NNMT_DATA_HEADER:
case NNMT_DATA_BODY:
case NNMT_DATA_TRAILER:
buffer[37U] = 0x23U;
buffer[38U] = 0x02U;
buffer[39U] = 0x18U;
break;
default:
return false;
}
::memcpy(buffer + 40U, data, 33U);
if (m_debug)
CUtils::dump(1U, "NXDN Network Data Sent", buffer, 102U);
return m_socket.write(buffer, 102U, m_addr, m_addrLen);
}
void CNXDNIcomNetwork::clock(unsigned int ms)
{
unsigned char buffer[BUFFER_LENGTH];
sockaddr_storage address;
unsigned int addrLen;
int length = m_socket.read(buffer, BUFFER_LENGTH, address, addrLen);
if (length <= 0)
return;
if (!CUDPSocket::match(m_addr, address)) {
LogMessage("NXDN, packet received from an invalid source");
return;
}
if (m_debug)
CUtils::dump(1U, "NXDN Network Data Received", buffer, length);
// Invalid packet type?
if (::memcmp(buffer, "ICOM", 4U) != 0)
return;
if (length != 102)
return;
if (!m_enabled)
return;
m_buffer.addData(buffer + 40U, 33U);
}
bool CNXDNIcomNetwork::read(unsigned char* data)
{
assert(data != NULL);
if (m_buffer.isEmpty())
return false;
m_buffer.getData(data, 33U);
return true;
}
void CNXDNIcomNetwork::reset()
{
}
void CNXDNIcomNetwork::close()
{
m_socket.close();
LogMessage("Closing NXDN network connection");
}
void CNXDNIcomNetwork::enable(bool enabled)
{
if (enabled && !m_enabled)
reset();
else if (!enabled && m_enabled)
m_buffer.clear();
m_enabled = enabled;
}

View file

@ -1,59 +0,0 @@
/*
* Copyright (C) 2009-2014,2016,2018,2020 by Jonathan Naylor G4KLX
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifndef NXDNIcomNetwork_H
#define NXDNIcomNetwork_H
#include "NXDNNetwork.h"
#include "NXDNDefines.h"
#include "RingBuffer.h"
#include "UDPSocket.h"
#include "Timer.h"
#include <cstdint>
#include <string>
class CNXDNIcomNetwork : public INXDNNetwork {
public:
CNXDNIcomNetwork(const std::string& localAddress, unsigned int localPort, const std::string& gatewayAddress, unsigned int gatewayPort, bool debug);
virtual ~CNXDNIcomNetwork();
virtual bool open();
virtual void enable(bool enabled);
virtual bool write(const unsigned char* data, NXDN_NETWORK_MESSAGE_TYPE type);
virtual bool read(unsigned char* data);
virtual void reset();
virtual void close();
virtual void clock(unsigned int ms);
private:
CUDPSocket m_socket;
sockaddr_storage m_addr;
unsigned int m_addrLen;
bool m_debug;
bool m_enabled;
CRingBuffer<unsigned char> m_buffer;
};
#endif

File diff suppressed because it is too large Load diff

View file

@ -1,100 +0,0 @@
/*
* Copyright (C) 2009-2014,2016,2018,2020 by Jonathan Naylor G4KLX
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifndef NXDNKenwoodNetwork_H
#define NXDNKenwoodNetwork_H
#include "NXDNNetwork.h"
#include "UDPSocket.h"
#include "Timer.h"
#include <cstdint>
#include <string>
#include <random>
class CNXDNKenwoodNetwork : public INXDNNetwork {
public:
CNXDNKenwoodNetwork(const std::string& localAddress, unsigned int localPort, const std::string& gwyAddress, unsigned int gwyPort, bool debug);
virtual ~CNXDNKenwoodNetwork();
virtual bool open();
virtual void enable(bool enabled);
virtual bool write(const unsigned char* data, NXDN_NETWORK_MESSAGE_TYPE type);
virtual bool read(unsigned char* data);
virtual void reset();
virtual void close();
virtual void clock(unsigned int ms);
private:
CUDPSocket m_rtpSocket;
CUDPSocket m_rtcpSocket;
sockaddr_storage m_rtcpAddr;
sockaddr_storage m_rtpAddr;
unsigned int m_rtcpAddrLen;
unsigned int m_rtpAddrLen;
bool m_enabled;
bool m_headerSeen;
bool m_seen1;
bool m_seen2;
bool m_seen3;
bool m_seen4;
unsigned char* m_sacch;
uint8_t m_sessionId;
uint16_t m_seqNo;
unsigned int m_ssrc;
bool m_debug;
uint32_t m_startSecs;
uint32_t m_startUSecs;
CTimer m_rtcpTimer;
CTimer m_hangTimer;
unsigned char m_hangType;
unsigned short m_hangSrc;
unsigned short m_hangDst;
std::mt19937 m_random;
bool processIcomVoiceHeader(const unsigned char* data);
bool processIcomVoiceData(const unsigned char* data);
bool processIcomDataHeader(const unsigned char* data);
bool processIcomDataData(const unsigned char* data);
bool processIcomDataTrailer(const unsigned char* data);
bool processKenwoodVoiceHeader(unsigned char* data);
bool processKenwoodVoiceData(unsigned char* data);
bool processKenwoodVoiceLateEntry(unsigned char* data);
bool processKenwoodData(unsigned char* data);
bool writeRTPVoiceHeader(const unsigned char* data);
bool writeRTPVoiceData(const unsigned char* data);
bool writeRTPVoiceTrailer(const unsigned char* data);
bool writeRTPDataHeader(const unsigned char* data);
bool writeRTPDataData(const unsigned char* data);
bool writeRTPDataTrailer(const unsigned char* data);
bool writeRTCPStart();
bool writeRTCPPing();
bool writeRTCPHang(unsigned char type, unsigned short src, unsigned short dst);
bool writeRTCPHang();
unsigned int readRTP(unsigned char* data);
unsigned int readRTCP(unsigned char* data);
unsigned long getTimeStamp() const;
};
#endif

View file

@ -1,162 +0,0 @@
/*
* Copyright (C) 2018 by Jonathan Naylor G4KLX
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "NXDNDefines.h"
#include "NXDNLICH.h"
#include <cstdio>
#include <cassert>
#include <cstring>
const unsigned char BIT_MASK_TABLE[] = {0x80U, 0x40U, 0x20U, 0x10U, 0x08U, 0x04U, 0x02U, 0x01U};
#define WRITE_BIT1(p,i,b) p[(i)>>3] = (b) ? (p[(i)>>3] | BIT_MASK_TABLE[(i)&7]) : (p[(i)>>3] & ~BIT_MASK_TABLE[(i)&7])
#define READ_BIT1(p,i) (p[(i)>>3] & BIT_MASK_TABLE[(i)&7])
CNXDNLICH::CNXDNLICH(const CNXDNLICH& lich) :
m_lich(NULL)
{
m_lich = new unsigned char[1U];
m_lich[0U] = lich.m_lich[0U];
}
CNXDNLICH::CNXDNLICH() :
m_lich(NULL)
{
m_lich = new unsigned char[1U];
}
CNXDNLICH::~CNXDNLICH()
{
delete[] m_lich;
}
bool CNXDNLICH::decode(const unsigned char* bytes)
{
assert(bytes != NULL);
unsigned int offset = NXDN_FSW_LENGTH_BITS;
for (unsigned int i = 0U; i < (NXDN_LICH_LENGTH_BITS / 2U); i++, offset += 2U) {
bool b = READ_BIT1(bytes, offset);
WRITE_BIT1(m_lich, i, b);
}
bool newParity = getParity();
bool origParity = (m_lich[0U] & 0x01U) == 0x01U;
return origParity == newParity;
}
void CNXDNLICH::encode(unsigned char* bytes)
{
assert(bytes != NULL);
bool parity = getParity();
if (parity)
m_lich[0U] |= 0x01U;
else
m_lich[0U] &= 0xFEU;
unsigned int offset = NXDN_FSW_LENGTH_BITS;
for (unsigned int i = 0U; i < (NXDN_LICH_LENGTH_BITS / 2U); i++) {
bool b = READ_BIT1(m_lich, i);
WRITE_BIT1(bytes, offset, b);
offset++;
WRITE_BIT1(bytes, offset, true);
offset++;
}
}
unsigned char CNXDNLICH::getRFCT() const
{
return (m_lich[0U] >> 6) & 0x03U;
}
unsigned char CNXDNLICH::getFCT() const
{
return (m_lich[0U] >> 4) & 0x03U;
}
unsigned char CNXDNLICH::getOption() const
{
return (m_lich[0U] >> 2) & 0x03U;
}
unsigned char CNXDNLICH::getDirection() const
{
return (m_lich[0U] >> 1) & 0x01U;
}
unsigned char CNXDNLICH::getRaw() const
{
bool parity = getParity();
if (parity)
m_lich[0U] |= 0x01U;
else
m_lich[0U] &= 0xFEU;
return m_lich[0U];
}
void CNXDNLICH::setRFCT(unsigned char rfct)
{
m_lich[0U] &= 0x3FU;
m_lich[0U] |= (rfct << 6) & 0xC0U;
}
void CNXDNLICH::setFCT(unsigned char usc)
{
m_lich[0U] &= 0xCFU;
m_lich[0U] |= (usc << 4) & 0x30U;
}
void CNXDNLICH::setOption(unsigned char option)
{
m_lich[0U] &= 0xF3U;
m_lich[0U] |= (option << 2) & 0x0CU;
}
void CNXDNLICH::setDirection(unsigned char direction)
{
m_lich[0U] &= 0xFDU;
m_lich[0U] |= (direction << 1) & 0x02U;
}
void CNXDNLICH::setRaw(unsigned char lich)
{
m_lich[0U] = lich;
}
CNXDNLICH& CNXDNLICH::operator=(const CNXDNLICH& lich)
{
if (&lich != this)
m_lich[0U] = lich.m_lich[0U];
return *this;
}
bool CNXDNLICH::getParity() const
{
switch (m_lich[0U] & 0xF0U) {
case 0x80U:
case 0xB0U:
return true;
default:
return false;
}
}

View file

@ -1,52 +0,0 @@
/*
* Copyright (C) 2018 by Jonathan Naylor G4KLX
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#if !defined(NXDNLICH_H)
#define NXDNLICH_H
class CNXDNLICH {
public:
CNXDNLICH(const CNXDNLICH& lich);
CNXDNLICH();
~CNXDNLICH();
bool decode(const unsigned char* bytes);
void encode(unsigned char* bytes);
unsigned char getRFCT() const;
unsigned char getFCT() const;
unsigned char getOption() const;
unsigned char getDirection() const;
unsigned char getRaw() const;
void setRFCT(unsigned char rfct);
void setFCT(unsigned char usc);
void setOption(unsigned char option);
void setDirection(unsigned char direction);
void setRaw(unsigned char lich);
CNXDNLICH& operator=(const CNXDNLICH& lich);
private:
unsigned char* m_lich;
bool getParity() const;
};
#endif

View file

@ -1,117 +0,0 @@
/*
* Copyright (C) 2018 by Jonathan Naylor G4KLX
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "NXDNDefines.h"
#include "NXDNLayer3.h"
#include <cstdio>
#include <cassert>
#include <cstring>
const unsigned char BIT_MASK_TABLE[] = { 0x80U, 0x40U, 0x20U, 0x10U, 0x08U, 0x04U, 0x02U, 0x01U };
#define WRITE_BIT1(p,i,b) p[(i)>>3] = (b) ? (p[(i)>>3] | BIT_MASK_TABLE[(i)&7]) : (p[(i)>>3] & ~BIT_MASK_TABLE[(i)&7])
#define READ_BIT1(p,i) (p[(i)>>3] & BIT_MASK_TABLE[(i)&7])
CNXDNLayer3::CNXDNLayer3(const CNXDNLayer3& layer3) :
m_data(NULL)
{
m_data = new unsigned char[22U];
::memcpy(m_data, layer3.m_data, 22U);
}
CNXDNLayer3::CNXDNLayer3() :
m_data(NULL)
{
m_data = new unsigned char[22U];
::memset(m_data, 0x00U, 22U);
}
CNXDNLayer3::~CNXDNLayer3()
{
delete[] m_data;
}
void CNXDNLayer3::decode(const unsigned char* bytes, unsigned int length, unsigned int offset)
{
assert(bytes != NULL);
for (unsigned int i = 0U; i < length; i++, offset++) {
bool b = READ_BIT1(bytes, i);
WRITE_BIT1(m_data, offset, b);
}
}
void CNXDNLayer3::encode(unsigned char* bytes, unsigned int length, unsigned int offset)
{
assert(bytes != NULL);
for (unsigned int i = 0U; i < length; i++, offset++) {
bool b = READ_BIT1(m_data, offset);
WRITE_BIT1(bytes, i, b);
}
}
unsigned char CNXDNLayer3::getMessageType() const
{
return m_data[0U] & 0x3FU;
}
unsigned short CNXDNLayer3::getSourceUnitId() const
{
return (m_data[3U] << 8) | m_data[4U];
}
unsigned short CNXDNLayer3::getDestinationGroupId() const
{
return (m_data[5U] << 8) | m_data[6U];
}
bool CNXDNLayer3::getIsGroup() const
{
return (m_data[2U] & 0x80U) != 0x80U;
}
unsigned char CNXDNLayer3::getDataBlocks() const
{
return (m_data[8U] & 0x0FU) + 1U;
}
void CNXDNLayer3::getData(unsigned char* data) const
{
::memcpy(data, m_data, 22U);
}
void CNXDNLayer3::setData(const unsigned char* data, unsigned int length)
{
::memset(m_data, 0x00U, 22U);
::memcpy(m_data, data, length);
}
void CNXDNLayer3::reset()
{
::memset(m_data, 0x00U, 22U);
}
CNXDNLayer3& CNXDNLayer3::operator=(const CNXDNLayer3& layer3)
{
if (&layer3 != this)
::memcpy(m_data, layer3.m_data, 22U);
return *this;
}

View file

@ -1,49 +0,0 @@
/*
* Copyright (C) 2018 by Jonathan Naylor G4KLX
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#if !defined(NXDNLayer3_H)
#define NXDNLayer3_H
class CNXDNLayer3 {
public:
CNXDNLayer3(const CNXDNLayer3& layer3);
CNXDNLayer3();
~CNXDNLayer3();
void decode(const unsigned char* bytes, unsigned int length, unsigned int offset = 0U);
void encode(unsigned char* bytes, unsigned int length, unsigned int offset = 0U);
unsigned char getMessageType() const;
unsigned short getSourceUnitId() const;
unsigned short getDestinationGroupId() const;
bool getIsGroup() const;
unsigned char getDataBlocks() const;
void setData(const unsigned char* data, unsigned int length);
void getData(unsigned char* data) const;
void reset();
CNXDNLayer3& operator=(const CNXDNLayer3& layer3);
private:
unsigned char* m_data;
};
#endif

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