Compare commits

...

821 commits

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
c800a4d369
Merge pull request #652 from ct1jib/patch-1
Update MMDVM.ini
2020-11-11 09:20:41 +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
Andy CA6JAU
a42e8f74c1 Add ID for SkyBridge HS board 2020-11-08 18:46:19 -03: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
Jorge (George)
54413e0891
Update MMDVM.ini
Change address of DMR Network stanza
2020-11-06 10:52:34 +00:00
Jonathan Naylor
18c8b95829 Convert M17 to use the new M17 Gateway. 2020-11-01 16:07:36 +00:00
Jonathan Naylor
72654cf02a Fix missing Log.h handling in UDPSocket.cpp 2020-10-31 22:08:38 +00:00
Jonathan Naylor
06ba457da2 Merge branch 'SimpleDMR' into AX25_FM 2020-10-31 21:45:48 +00:00
Jonathan Naylor
9559cdb060 Merge branch 'SimpleDMR' into M17 2020-10-31 21:41:45 +00:00
Jonathan Naylor
a0d60b894d Add optional log file rotation and UDP socket reopening. 2020-10-31 21:35:09 +00:00
Jonathan Naylor
ff8c9edb49 Merge branch 'SimpleDMR' into AX25_FM 2020-10-31 21:05:17 +00:00
Jonathan Naylor
08ad50d578 Merge branch 'SimpleDMR' into M17 2020-10-31 21:04:43 +00:00
Jonathan Naylor
34b3bc6166 Merge branch 'master' into SimpleDMR 2020-10-31 21:04:16 +00:00
Jonathan Naylor
424407cb82
Merge pull request #649 from shawnchain/fix-osx-error-bg5hhp
Fix osx compile error
2020-10-31 16:08:00 +00:00
Shawn Chain
258c8a1202 Fix osx compile error 2020-10-31 19:53:00 +08:00
Jonathan Naylor
cd5624c2fb Merge branch 'SimpleDMR' into M17 2020-10-30 13:58:32 +00:00
Jonathan Naylor
098cc74c9e Merge branch 'SimpleDMR' into AX25_FM 2020-10-30 13:57:58 +00:00
Jonathan Naylor
bbe44df3e9 Merge branch 'master' into SimpleDMR 2020-10-30 13:47:25 +00:00
Jonathan Naylor
99cdcf1f50
Merge pull request #522 from sp5lg/master
DStar SelfOnly with WhiteList
2020-10-30 13:44:54 +00:00
Jonathan Naylor
e983aa7109
Merge pull request #629 from s-s-s/patch-1
Added a new address the id's list
2020-10-30 13:43:37 +00:00
Jonathan Naylor
fc34f27f63
Merge pull request #644 from jg1uaa/master
CNetworkInfo::getNetworkInterface() FreeBSD support
2020-10-30 13:41:19 +00:00
Jonathan Naylor
62c0165d3d Merge branch 'master' into SimpleDMR 2020-10-30 13:38:05 +00:00
Jonathan Naylor
61afb194c5 Revert "Merge pull request #648 from xfxian/logrotate"
This reverts commit 9932394840, reversing
changes made to cfc313e5b9.
2020-10-30 13:34:13 +00:00
Florian (DF2ET)
9932394840
Merge pull request #648 from xfxian/logrotate
Introducing RotateLog configuration option that allows disabling timestamps on the logfiles.
2020-10-29 22:48:55 +01:00
Jacob Schramm
7a5bbda248 Changing RotateLogs to TimestampLogs 2020-10-29 22:45:57 +01:00
Jacob Schramm
53ae146667 Introducing RotateLog configuration option that allows disabling timestamps on the logfiles. 2020-10-29 00:08:04 +01:00
Jonathan Naylor
31002c2757 Allow encrypted M17 data to be rejected. 2020-10-26 10:10:31 +00:00
Jonathan Naylor
d0e8574187 Handle the return value for M17 RF transmissions. 2020-10-26 09:39:16 +00:00
Jonathan Naylor
9c13baef82 Remove the CRC processing from the networking side. 2020-10-25 13:15:51 +00:00
Jonathan Naylor
2ff0e52558 Add M17 BER debug info. 2020-10-25 12:48:23 +00:00
Jonathan Naylor
9688929c3d Fix the M17 LICH fragment encoding. 2020-10-21 10:41:06 +01:00
Jonathan Naylor
bab4b50d30 Handle EOT on rejected frames correctly. 2020-10-21 10:17:52 +01:00
Jonathan Naylor
1bb1e9da59 M17 bug fixing. 2020-10-20 14:26:47 +01:00
Jonathan Naylor
d58a0c53b5 Add the SelfOnly processing for M17. 2020-10-20 09:40:29 +01:00
Jonathan Naylor
9567ac0b20 Use defined lengths instead of magic numbers. 2020-10-19 11:00:45 +01:00
Jonathan Naylor
28e013acb7 Clean up the frame processing for RF and network. 2020-10-19 10:37:23 +01:00
Jonathan Naylor
d2bf8eb744 Fix Linux compile. 2020-10-18 23:28:29 +01:00
Jonathan Naylor
551556b65d Update the Makefiles. 2020-10-18 23:24:46 +01:00
Jonathan Naylor
b46d2f586c Add the M17 TFT Serial image. 2020-10-18 23:05:53 +01:00
Jonathan Naylor
ef07f3c035 Update the puncturing tables. 2020-10-18 23:00:16 +01:00
Jonathan Naylor
5b57557a79 Start on the convolution FEC. 2020-10-18 22:23:18 +01:00
Jonathan Naylor
c549cf3594 Add the LICH processing. 2020-10-18 20:44:03 +01:00
Jonathan Naylor
a00ecbe7d9 Get the CRC and callsign mangling working correctly. 2020-10-18 20:04:44 +01:00
Jonathan Naylor
521da9b54d Add the CRC and callsign encoding. 2020-10-18 14:51:52 +01:00
Jonathan Naylor
48f95be982 Mostly complete processing of RF frames. 2020-10-17 21:59:27 +01:00
Jonathan Naylor
9a72e95ec0 Clean compile(-ish), still more to do. 2020-10-17 16:47:19 +01:00
Jonathan Naylor
8946038e0e Add M17 reflector linking and start on the frame handling. 2020-10-17 16:25:48 +01:00
uaa
54a945ee6d Merge branch 'master' of http://github.com/jg1uaa/MMDVMHost 2020-10-17 18:33:28 +09:00
Jonathan Naylor
b921f99d0a WIP on M17. 2020-10-16 10:35:19 +01:00
Jonathan Naylor
6e9174cf4c Improve the M17 networking. 2020-10-15 15:44:59 +01:00
Jonathan Naylor
e0f4928db5 Handle M17 in the display code. 2020-10-15 14:32:56 +01:00
Jonathan Naylor
80a77bd12a Add the M17 page to the Nextion displays. 2020-10-15 13:59:28 +01:00
Jonathan Naylor
8536294b76 Initial work on the M17 protocol. 2020-10-14 16:16:54 +01:00
Jonathan Naylor
e2a4ccfc05 Merge branch 'SimpleDMR' into AX25_FM 2020-10-13 10:12:58 +01:00
Jonathan Naylor
ff19408e2d Fix bug added in FICH regeneration. 2020-10-13 10:11:13 +01:00
Jonathan Naylor
c1171bc052 Regenerate the FICH correctly. 2020-10-13 10:07:31 +01:00
SASANO Takayoshi
1f72bf16d8 add OSX support to NetworkInfo.cpp (EXPERIMENTAL) 2020-10-10 04:48:59 +09:00
SASANO Takayoshi
630551f6fd CNetworkInfo::getNetworkInterface() FreeBSD support
modified IPv4 default routing information request code to support FreeBSD
2020-10-07 19:12:47 +09:00
Jonathan Naylor
35e9a2a830 Merge branch 'SimpleDMR' into AX25_FM 2020-10-07 10:33:06 +01:00
Jonathan Naylor
eb2510898d Merge branch 'master' into SimpleDMR 2020-10-07 10:32:42 +01:00
Jonathan Naylor
cfc313e5b9 Fix buffer overflow. 2020-10-07 10:32:12 +01:00
Jonathan Naylor
2fc62e0e7a Merge branch 'SimpleDMR' into AX25_FM 2020-10-06 10:51:15 +01:00
Jonathan Naylor
91ad967f6d Merge branch 'master' into SimpleDMR 2020-10-06 10:14:16 +01:00
Jonathan Naylor
2d557ffe30
Merge pull request #642 from jg1uaa/master
CNetworkInfo::getNetworkInterface() OpenBSD/NetBSD support
2020-10-06 10:05:21 +01:00
SASANO Takayoshi
f2c399308b CNetworkInfo::getNetworkInterface display IP address is limited to IPv4
Displayed IP address is now IPv4 only due to referring IPv4 routing table
to get default route.

This feature is used by hotspots which have small LCD or OLED display
to show IP address to remote login. No effects to connect other reflectors.

If completely disabled IPv4 world will come, the code need to be revised.
2020-10-06 06:58:35 +09:00
SASANO Takayoshi
879b426308 CNetworkInfo::getNetworkInterface() OpenBSD/NetBSD support
added IPv4 default routing information request code for OpenBSD/NetBSD.
2020-10-06 06:17:55 +09:00
Jonathan Naylor
7c81128d77 Merge branch 'SimpleDMR' into AX25_FM 2020-10-05 12:50:52 +01:00
Jonathan Naylor
64a20d9d08 Merge branch 'master' into SimpleDMR 2020-10-05 12:48:57 +01:00
Jonathan Naylor
5dc3308ef4 NetBSD and other changes. 2020-10-05 12:46:54 +01:00
Jonathan Naylor
20e8d4079d Merge branch 'SimpleDMR' into AX25_FM 2020-09-25 12:35:34 +01:00
Jonathan Naylor
e872ca37cd Merge branch 'master' into SimpleDMR 2020-09-25 12:34:58 +01:00
Jonathan Naylor
9ccc94923e
Merge pull request #640 from jg1uaa/oled-userdb
fix scroll direction
2020-09-25 12:34:19 +01:00
SASANO Takayoshi
9bf68e2eb7 fix scroll direction
all messages except clearCWInt(), scroll direction is inverted.
almost all languages are written from left to right,
so scrolling direction should be "display new right-side characters".
2020-09-25 19:02:36 +08:00
Jonathan Naylor
3f125f055c Merge branch 'SimpleDMR' into AX25_FM 2020-09-24 14:05:18 +01:00
Jonathan Naylor
768599af84 Merge branch 'master' into SimpleDMR 2020-09-24 13:58:44 +01:00
Jonathan Naylor
4ffc5cdb71 Reduce the amount of YSF debug logging. 2020-09-24 13:53:17 +01:00
Jonathan Naylor
040ea4a15c Regenerate the odd VW mode message after the header. 2020-09-24 13:47:31 +01:00
Jonathan Naylor
d92d41b4fd
Merge pull request #639 from jg1uaa/oled-userdb
add UserDB display for OLED
2020-09-24 13:00:51 +01:00
SASANO Takayoshi
e818d0f500 add UserDB display for OLED
To display UserDB on DMR mode, set Slot1=0 and Slot2=1 in [DMR Network]
section.
2020-09-24 18:58:10 +08:00
Jonathan Naylor
c5ce304edb Merge branch 'master' into SimpleDMR 2020-09-22 15:55:13 +01:00
Jonathan Naylor
ba476b6fec Use normal logging for UDPSocket. 2020-09-22 15:51:10 +01:00
Jonathan Naylor
83b92f98e7
Merge pull request #638 from jg1uaa/oled-userdb
Makefile.Pi.OLED revised
2020-09-22 07:58:36 +01:00
SASANO Takayoshi
d77d44fd4b Makefile.Pi.OLED revised
- use system default compiler (cc/c++) instead of gcc/g++
- no need to link wiringPi library, remove -lwiringPi
2020-09-22 07:43:20 +08:00
Jonathan Naylor
6d313fce51 Merge branch 'SimpleDMR' into AX25_FM 2020-09-20 21:32:11 +01:00
Jonathan Naylor
5eabb93078 Fix Windows execution. 2020-09-20 21:31:32 +01:00
Jonathan Naylor
b2ba671071 Fix Windows compilation. 2020-09-20 14:07:42 +01:00
Jonathan Naylor
c2a1aeb581 Merge branch 'SimpleDMR' into AX25_FM 2020-09-08 10:11:38 +01:00
Jonathan Naylor
6d6fcc7f93 Merge branch 'master' into SimpleDMR 2020-09-08 10:11:15 +01:00
Jonathan Naylor
75652b04ae Ignore any incoming YSF options messages. 2020-09-08 10:10:25 +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
43f4cdf092 Make all of the other Makefiles use the system default compilers. 2020-09-06 14:29:29 +01:00
Jonathan Naylor
98b1e6478b Merge branch 'SimpleDMR' into AX25_FM 2020-09-06 14:27:55 +01:00
Jonathan Naylor
7d3e899104 Clean ups for IPv6. 2020-09-06 12:54:08 +01:00
Jonathan Naylor
e45f0edec4 Merge branch 'ipv6' into SimpleDMR 2020-09-06 11:57:11 +01:00
Jonathan Naylor
e935fc1085
Merge pull request #636 from jg1uaa/ipv6
UDPSocket renewal
2020-09-06 11:52:13 +01:00
SASANO Takayoshi
f2543de3da fix CUDPSocket(port) constructor bug
constructor CUDPSocket(port) cannot create properly, fixed
2020-09-06 16:32:33 +09:00
SASANO Takayoshi
9856025923 rewrite for UDPSocket renewal 2020-09-06 15:52:46 +09:00
SASANO Takayoshi
def0edbaca UDPSocket renewal (2)
introduced YSFClients code

	match_addr(addr1, addr2) -> match(addr1, addr2, IMT_ADDRESS_ONLY)
	isnone() -> isNone()
	open(sockaddr_storage&) added (this refers address family only)
2020-09-06 15:48:22 +09:00
SASANO Takayoshi
457be810a3 UDPSocket renewal
Currently there is six variations of (IPv4) UDPSocket.cpp.

- FMClients, NXDNClients, P25Clients, YSFClients(YSFParrot)
	use ::fprintf() for logging

- YSFClients(YSFReflector)
	use LogError() and LogInfo() for logging
	special open(string &bindaddr) function

- YSFClients(YSFGateway), DAPNETGateway
	use LogError() and LogInfo() for logging

- P25Clients, DMRGateway
	use LogError() for logging
	no LogInfo("Opening UDP port on") message

- NXDNClients
	use LogError() for logging
	no LogInfo("Opening UDP port on") message
	add #include <ifaddrs.h>

- MMDVMHost
	use LogError() for logging
	no LogInfo("Opening UDP port on") message
	no assert(!address.empty()) at constructor

to avoid explosion, commonized them.

	switch ::fprintf()/LogError by #define HAVE_LOG_H
	always display LogInfo("Opening UDP port on") message
	delete #include <ifaddrs.h>, this is not needed
	no assert(!address.empty()) at constructor

and to support YSFReflector, add multiple socket support.
default is #define UDP_SOCKET_MAX 1 so normally this feature is disabled.

added these functions.

	CUDPSocket()	(constructor without any parameters)
	open(index, af, addr, port)
	close(index)

CUDPSocket() means CUDPSocket(address = "", port = 0)
index selects socket, address and port is defined at open.

to have compatibility for old codes, these function works as

	CUDPSocket(addr, port)	store addr and port to index #0
	CUDPSocket(port)	store addr = "" and port to index #0
	open()		open with addr and port of index #0, AF_UNSPEC
	open(af)	open with addr and port of index #0, specified af
	close()		close *all* sockets

read/write operation is for all opened sockets.
2020-09-06 12:09:37 +09:00
Jonathan Naylor
2502ee94d7 Merge branch 'SimpleDMR' into AX25_FM 2020-09-03 12:10:01 +01:00
Jonathan Naylor
3de54f6dd8 Merge branch 'ipv6' into SimpleDMR 2020-09-03 11:43:42 +01:00
Jonathan Naylor
132fb62d56 Small cleanups. 2020-08-30 14:54:51 +01:00
Jonathan Naylor
2349520964 Remove the location information from the new config message. 2020-08-27 10:13:02 +01:00
Jonathan Naylor
01da0ded7f Remove the unused SHA256 functions. 2020-08-27 09:00:49 +01:00
Jonathan Naylor
98879b5c14 Reinstated the location field. 2020-08-26 12:13:34 +01:00
Jonathan Naylor
a9c9ff6011 Changes for the simplified protocol. 2020-08-26 10:18:57 +01:00
Jonathan Naylor
66a17f4849 Simplify the Host to DMR Gateway protocol. 2020-08-26 09:29:11 +01:00
Jonathan Naylor
d5bbd77304 Merge branch 'master' into AX25_FM 2020-08-14 09:34:30 +01:00
Jonathan Naylor
f71c8ce7bc
Merge pull request #633 from on7lds/dev
change tx and rx frequency display precision (to reflect ini file significant figures)
2020-08-14 09:33:53 +01:00
ON7LDS
70d596fea4 change tx and rx frequency display precision (to reflect ini file significant figures) 2020-08-13 21:23:42 +02:00
Jonathan Naylor
739550885b Merge branch 'master' into AX25_FM 2020-08-10 14:31:53 +01:00
Jonathan Naylor
cdf62f1601
Merge pull request #630 from stefansaraev/oled-buildfix
OLED: fix build after f070410f7 and c7fbeecc5
2020-08-10 14:30:25 +01:00
Stefan Saraev
f48cfcc70c OLED: fix build after f070410f7 and c7fbeecc5
============================
Display.cpp: In static member function 'static CDisplay* CDisplay::createDisplay(const CConf&, CUMP*, CModem*)':
Display.cpp:645:128: error: invalid new-expression of abstract class type 'COLED'
  645 |   display = new COLED(type, brightness, invert, scroll, rotate, logosaver, conf.getDMRNetworkSlot1(), conf.getDMRNetworkSlot2());
      |                                                                                                                                ^
In file included from Display.cpp:39:
OLED.h:40:7: note:   because the following virtual functions are pure within 'COLED':
   40 | class COLED : public CDisplay
      |       ^~~~~
In file included from Display.cpp:19:
Display.h:105:15: note: 	'virtual void CDisplay::writeFusionInt(const char*, const char*, unsigned char, const char*, const char*)'
  105 |  virtual void writeFusionInt(const char* source, const char* dest, unsigned char dgid, const char* type, const char* origin) = 0;
============================
2020-08-10 16:26:07 +03:00
Sergei
1cc79413b7
Added a new address the id's list
A new address with the id's list format optimized for pistar as well. Extra spaces in the line were removed.
2020-08-10 15:36:12 +03:00
Jonathan Naylor
97a10c7e30 Merge branch 'master' into AX25_FM 2020-08-09 19:40:37 +01:00
Jonathan Naylor
c7fbeecc50 Change the displays to show the DG-ID instead of the TO field for YSF. 2020-08-09 19:23:18 +01:00
Jonathan Naylor
82ea772269 Merge branch 'master' into AX25_FM 2020-08-09 15:09:46 +01:00
Jonathan Naylor
f070410f7e Display and log the DG-ID in the Fusion mode. 2020-08-09 15:09:08 +01:00
Jonathan Naylor
8a6f14e6e6 Merge branch 'master' into AX25_FM 2020-08-05 15:00:23 +01:00
Jonathan Naylor
b0d828123b
Merge pull request #624 from msraya/master
Remove DG-ID clear to zero in order to use DG-ID room switch in C4FM servers
2020-08-04 19:40:08 +01:00
msraya
ffd90f6941 Remove DG-ID clear to zero 2020-08-04 18:03:50 +01:00
Manuel Sánchez Raya
c21e325ddb
Merge pull request #1 from g4klx/master
Update fork to last version
2020-08-04 18:51:46 +02:00
Jonathan Naylor
3776ed2b1b Merge branch 'master' into AX25_FM 2020-08-04 10:39:23 +01:00
Jonathan Naylor
c57a313677 Revert "YSF updated from msraya."
This reverts commit 7a1b71ecf5.
2020-08-04 10:34:18 +01:00
Jonathan Naylor
11c8403829 Merge branch 'master' into AX25_FM 2020-08-04 10:04:47 +01:00
Jonathan Naylor
34c759df5f
Merge pull request #623 from msraya/master
Update files to remove DG-ID and maintain consistency in code
2020-08-03 20:22:41 +01:00
msraya
9ab838f653 Update files to remove DG-ID and maintain consistency in code 2020-08-03 19:56:08 +01:00
msraya
52ca12e88a Update files to remove DG-ID and mantain consistency in code 2020-08-03 19:48:25 +01:00
Jonathan Naylor
e01b153a86
Merge pull request #621 from msraya/patch-2
Do not remove DG-ID information for use in new servers
2020-08-03 19:14:20 +01:00
Manuel Sánchez Raya
01d8fe1a58
Do not remove DG-ID information for use in new servers
Please remove reset to zero or setting of DG-ID because is not necessary. 
There are many reflectors that use DG-ID to change communication between TGs or rooms.
2020-08-03 19:38:21 +02: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
34db212360
Merge pull request #617 from jg1uaa/ipv6
IPv6: catch up current source
2020-07-14 14:15:16 +01:00
Jonathan Naylor
3e6d5d5a7f Add UseCOSAsLockout and FM Access Mode parameters. 2020-07-13 16:02:04 +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
SASANO Takayoshi
c40291dcc2 Merge remote-tracking branch 'upstream/master' into ipv6 2020-07-04 18:48:13 +09:00
Jonathan Naylor
16fac0b41c
Merge pull request #616 from jg1uaa/master
permit inline comment (2)
2020-07-04 10:45:25 +01:00
SASANO Takayoshi
1ded19c5b2 permit inline comment (2)
To implement this feature, using strtok() is not enough.

This cannot handle this case:

	Key=#value#comment

it will be #value is the contents of Key. And,

	Key=value 	#comment
	(there is a space and a tab between value and #comment)

this will be value<space><tab>. Sometimes these trailing spaces and
tabs makes thing wrong.

Whether in-line comment is used or not, delete trailing space/tab after
value.
2020-07-04 17:58:00 +09:00
SASANO Takayoshi
9137399ea9 NXDNKenwoodNetwork: IPv6 support 2020-07-03 06:56:36 +09:00
SASANO Takayoshi
8a0db8cb8b NXDNIcomNetwork: IPv6 support 2020-07-03 04:40:41 +09:00
SASANO Takayoshi
6de0bdb536 add match_addr()
match() compares IP address and port
match_addr() compares IP address only
2020-07-03 04:35:22 +09:00
SASANO Takayoshi
74adbd4895 Merge remote-tracking branch 'upstream/master' into ipv6
simply merged upstream code.

following files are conflicted, all fixed
GPSD.h, MobileGPS.cpp, NXDNNetwork.cpp, NXDNNetwork.h, UDPSocket.h

NXDNIcomNetwork and NXDNKenwoodNetwork is still original code,
not support IPv6-UDPSocket yet.
2020-07-03 04:17:14 +09: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
5dcdfd8159
Merge pull request #615 from jg1uaa/master
permit inline comment and hex-value to ScreenLayout of Nextion
2020-07-02 13:20:20 +01:00
SASANO Takayoshi
15a8e87c3e permit inline comment and ScreenLayout of Nextion
two minor improvements

- ScreenLayout in Nextion section can use hexadecimal (0xXXXXX),
  octal (0XXXX) and decimal value
- in-line comment enabled

	example:
	# conventional comment, the line starts with #
	[Section]
	Key=value # this is new style comment
	Key="quoted value # this is not comment"
	Key="quoted value" # this is prohibited (not comment)
2020-07-02 18:47:33 +09:00
SASANO Takayoshi
c8e31ce657 Merge remote-tracking branch 'upstream/master' 2020-07-02 18:23:10 +09:00
SASANO Takayoshi
4217ccebc4 remove getLocalAddress()
It was used for NXDNKenwoodNetwork.cpp to creates SSRC.
currently SSRC uses random value, this function is no longer used.
2020-07-02 06:59:51 +09:00
Jonathan Naylor
ee2e997cfd
Merge pull request #613 from jg1uaa/master
replace rand() -> MT19937 random number generator
2020-07-01 22:55:27 +01:00
SASANO Takayoshi
dfaedb450b replace rand() -> MT19937 random number generator
sometimes rand() makes problem so replace it to MT19937 in C++11 <random>.
2020-07-02 06:40:26 +09: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
4dd39696b4 Remove unused UDPSocket code. 2020-07-01 13:38:23 +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
8edfc62049
Merge pull request #612 from jg1uaa/master
m_ssrc use random value
2020-07-01 13:16:52 +01:00
SASANO Takayoshi
0892aaaaae eliminate SSRC range 0x00000001 - 0xfffffffe 2020-07-01 20:39:22 +09:00
SASANO Takayoshi
79b3eaa57a replace SSRC source from IPv4 address to random number
Previous implementation uses SSRC as IPv4 address that is same behaviour
of Kenwood's NXDN repeater.

RFC 3350 RTP protocol recommends SSRC uses random number.
So I use MT19937 random number generator instead of IP address.

And if this is no problem, I will do two changes.

- replace rand() in DMRNetwork.cpp and DStarNetwork.cpp to MT19937
- remove getLocalAddress() in UDPSocket.cpp
2020-07-01 19:48:07 +09: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
SASANO Takayoshi
974251485d Merge remote-tracking branch 'upstream/master' 2020-06-30 19:41:27 +09:00
Jonathan Naylor
e339de8fee Merge branch 'master' into AX25 2020-06-30 11:40:55 +01:00
SASANO Takayoshi
236d467c1a change ScreenLayout definition for Nextion
to add new feature easily, the definition of ScreenLayout in [Nextion]
has changed like this.

ScreenLayout < 8: compatibile setting for old config file

	0: G4KLX @ 9600bps
	1: (reserved)
	2: ON7LDS @ 9600bps
	3: ON7LDS-DIY @ 9600bps
	4: ON7LDS-DIY @ 115200bps

ScreenLayout >= 8: new world, set the bit to enable each feature

	bit3 (8)	use 115200bps
	bit4 (16)	Display DMR Talker Alias
	bit5 (32)	Colour change when displaying TA
	bit6 (64)	Font size change when displaying long TA text
	bit7 (128)	Display DIY status when MMDVM IDLE

old settings are same as:

	0 -> 0
	2 -> 112 (16+32+64)
	3 -> 144 (16+128)
	4 -> 152 (8+16+128)
2020-06-30 19:40:34 +09:00
Jonathan Naylor
df47466aa2 Use USE_GPSD instead of USE_GPS. 2020-06-30 11:38:25 +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
be8c29da3e Fix Windows compilation. 2020-06-29 11:50:33 +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
edce667018 Replace MobileGPS with gpsd. 2020-06-29 11:25:10 +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
1dc91b9a64 Add the install target to the other makefiles. 2020-06-25 09:55:28 +01:00
Jonathan Naylor
28d64e7c3d Merge branch 'master' into AX25 2020-06-25 09:44:55 +01:00
Jonathan Naylor
c174c10caf
Merge pull request #604 from jcyfkimi/master
Add install rule into Makefile
2020-06-25 09:35:24 +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
Kimi Jin
325b30d30b Add install rules into Makefile. This will insatll MMDVMHost and RemoteCommand to /usr/local/bin/ path, so need exec with command 'sudo make install'. 2020-06-24 13:33:23 +08:00
jcyfkimi
e8c21493c1
Merge pull request #1 from g4klx/master
Update to newest version
2020-06-24 13:28:59 +08: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
50888777e6
Merge pull request #602 from AndyTaylorTweet/master
Update OLED.cpp
2020-06-15 18:13:23 +01:00
Andy Taylor
3313fe8ec3
Update OLED.cpp
Modify the OLED code to only allow scroll commands when scrolling is enabled
2020-06-15 17:00:37 +01:00
Jonathan Naylor
7c95e231e2
Merge pull request #601 from jg1uaa/master
change ScreenLayout definition for Nextion
2020-06-14 08:30:26 +01:00
SASANO Takayoshi
36a852b38b change ScreenLayout definition for Nextion
to add new feature easily, the definition of ScreenLayout in [Nextion]
has changed like this.

ScreenLayout < 8: compatibile setting for old config file

	0: G4KLX @ 9600bps
	1: (reserved)
	2: ON7LDS @ 9600bps
	3: ON7LDS-DIY @ 9600bps
	4: ON7LDS-DIY @ 115200bps

ScreenLayout >= 8: new world, set the bit to enable each feature

	bit3 (8)	use 115200bps
	bit4 (16)	Display DMR Talker Alias
	bit5 (32)	Colour change when displaying TA
	bit6 (64)	Font size change when displaying long TA text
	bit7 (128)	Display DIY status when MMDVM IDLE

old settings are same as:

	0 -> 0
	2 -> 112 (16+32+64)
	3 -> 144 (16+128)
	4 -> 152 (8+16+128)
2020-06-14 16:00:20 +09:00
Jonathan Naylor
1ab09e21fe Merge branch 'master' into Kenwood 2020-06-13 17:48:03 +01:00
Jonathan Naylor
19c8c6515c
Merge pull request #565 from jg1uaa/ipv6
add IPv6 support
2020-06-12 12:53:36 +01:00
SASANO Takayoshi
816f8ea0a1 Merge remote-tracking branch 'origin' into ipv6 2020-06-12 20:24:17 +09: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
933b9ef014 Fix crash with POCSAG and no network. 2020-06-08 14:34:29 +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
Jonathan Naylor
4c7a2526e5 Merge branch 'master' into Kenwood 2020-05-28 11:50:44 +01:00
Jonathan Naylor
7bfe2f2b2f Fix Linux compile. 2020-05-27 12:52:15 +01:00
Jonathan Naylor
0b7efee2a7 Upgrade the Kenwood protocol to pass data calls. 2020-05-27 12:47:21 +01:00
Jonathan Naylor
924baeacd1 More work on integrating the Kenwood NXDN protocol. 2020-05-27 12:07:21 +01:00
Jonathan Naylor
45eafe3672 Start adding the Kenwood protocol as an option. 2020-05-27 11:38:46 +01:00
Jonathan Naylor
e7ffcb5090
Merge pull request #594 from m0vse/FM
Update RemoteCommand to disable/enable network modes
2020-05-25 20:39:15 +01:00
m0vse
26243c0247 Update RemoteCommand to disable/enable network modes 2020-05-25 20:29:49 +01: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
Jonathan Naylor
0dbfe896bb Update README. 2020-05-21 11:17:02 +01:00
Geoffrey Merck
1290f9c49e do not write EOT when network is not set 2020-05-20 18:07:57 +02:00
Jonathan Naylor
4eb534aab6 Remove extraneous logging message. 2020-05-18 11:20:44 +01:00
Jonathan Naylor
eb4dcc22a7
Merge pull request #592 from shawnchain/update_null_modem
Update NullModem code to sync with FM changes
2020-05-18 06:34:24 +01:00
Shawn Chain
953530c23b Update NullModem code to sycn with FM changes 2020-05-18 13:28:55 +08: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
bcf0ddc2b3
Merge pull request #588 from alistairuk/patch-1
Quoted "Listening" for the lcdproc widget_set command
2020-05-14 15:11:26 +01:00
Alistair MacDonald
b5658a6478
Quoted "Listening" for the lcdproc widget_set command
Adding quotes increases comparability. Although optional for single words it is unusual not to have it quoted. Previously some here were quoted and some where not.
2020-05-14 15:09:56 +01:00
Jonathan Naylor
9e52db3ef3 Merge branch 'FM' into FM_Ext 2020-05-13 12:06:35 +01:00
Jonathan Naylor
dc5438e3aa Merge branch 'master' into FM 2020-05-13 12:06:16 +01:00
Jonathan Naylor
083cc1155b Merge branch 'master' into TXHang 2020-05-13 12:05:39 +01:00
Jonathan Naylor
8ac6a1b208 Merge branch 'FM' into FM_Ext 2020-05-12 16:24:42 +01:00
Jonathan Naylor
ce121c59da Add the low CTCSS threshold value. 2020-05-12 13:43:43 +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
2ae966b7fb Fix for Windows compilation. 2020-05-09 12:47:26 +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
800b7a30af
Merge pull request #582 from f1rmb/redirect_stderr_to_log_when_in_daemon_mode
Redirect stderr messages to the log file
2020-05-09 11:45:22 +01:00
Daniel Caujolle-Bert
c3efabf56c
Redirect stderr messages to the log file, as in daemon mode assert() failure are silent and make wrong INI file hard to fix. 2020-05-09 12:11:08 +02: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
Jonathan Naylor
d6b367b8b5 Add the P25 and NXDN transmit hang timer settings. 2020-05-06 17:10:23 +01:00
Jonathan Naylor
5410ca3ce8 Add the COSInvert parameter. 2020-05-06 11:26:54 +01:00
Jonathan Naylor
da0f1a6a76 Merge branch 'master' into FM 2020-05-05 20:53:40 +01:00
Jonathan Naylor
7718676928
Merge pull request #579 from AndyTaylorTweet/master
Expand remote commands to allow sending text as CW
2020-05-05 20:45:12 +01:00
Andy Taylor
ff492a518f
Update MMDVMHost.cpp 2020-05-05 19:30:56 +01:00
Andy Taylor
d3f4b1f90c
Update RemoteControl.h 2020-05-05 19:27:12 +01:00
Andy Taylor
8b2b3d344a
Update RemoteControl.cpp 2020-05-05 19:26:12 +01:00
Andy Taylor
dd2f5fbe26
Update MMDVMHost.cpp 2020-05-05 19:24:29 +01:00
Jonathan Naylor
1a142e36cb Host support for the CallsignAtLatch option. 2020-05-04 22:30:16 +01:00
Jonathan Naylor
6d6cee119d Merge branch 'master' into FM 2020-05-03 19:06:05 +01:00
Jonathan Naylor
97327be963
Merge pull request #577 from AndyTaylorTweet/master
Update HD44780.cpp
2020-05-03 19:03:35 +01:00
Andy Taylor
7e145d288a
Update HD44780.cpp
The section at line 402 is mostly the same as the section at line 294, I suspect the new section should be setFMInt() instead....
2020-05-03 18:33:22 +01:00
Jonathan Naylor
5fe70ee654
Merge pull request #575 from m0vse/FM
Add enable/disable commands to RemoteCommand
2020-05-02 21:56:30 +01:00
m0vse
9796b400c8 Add enable/disable commands to RemoteCommand 2020-05-02 21:40:55 +01:00
Jonathan Naylor
3687eb71a8 Add FM to the OLED display. 2020-05-02 20:42:54 +01:00
Jonathan Naylor
4a923fb27e Rename RXBoost to RFAudioBoost. 2020-04-28 14:39:14 +01:00
Jonathan Naylor
70ca7c06dd Pass the RX level to the FM controller. 2020-04-26 21:50:03 +01:00
Jonathan Naylor
463bda2688 Bump the version date. 2020-04-26 13:23:26 +01:00
Jonathan Naylor
56746e1320 Add the maximum deviation level. 2020-04-25 22:43:14 +01:00
Jonathan Naylor
3d1602e50e Add two more FM parameters. 2020-04-25 15:15:56 +01:00
Jonathan Naylor
ac344cec69 Allow for a global callsign. 2020-04-24 15:37:26 +01:00
Jonathan Naylor
a73c0dbd72 Rescale some of the levels. 2020-04-24 13:16:21 +01:00
Jonathan Naylor
fbdee0edf1 Remove the FM RX level. 2020-04-24 12:59:33 +01:00
Jonathan Naylor
0d956b16fa Add a second callsign level setting. 2020-04-22 21:51:43 +01:00
Jonathan Naylor
6df6094ebf Change the levels for FM. 2020-04-21 21:46:39 +01:00
Jonathan Naylor
93effcad3d Convert the CTCSS threshold to a raw value. 2020-04-20 13:21:56 +01:00
Jonathan Naylor
cb732c9a62 Only allow FM mode in full duplex. 2020-04-19 16:11:55 +01:00
Jonathan Naylor
a450c2b2ad
Merge pull request #567 from F4FXL/FM
Fix Set FM params after creating modem, not before
2020-04-19 16:07:32 +01:00
Geoffrey Merck
9acd523bc3 Fix Set FM params after creating modem, not before 2020-04-19 16:36:29 +02:00
Jonathan Naylor
c359d874b5 Regularise the FM configuration. 2020-04-18 14:59:19 +01:00
Jonathan Naylor
11cd5679a7 Simplify the FM configuration. 2020-04-18 13:43:36 +01:00
Jonathan Naylor
f8bce3823a Allow for a seperate FM timeout value. 2020-04-15 14:14:38 +01:00
Jonathan Naylor
960a60f382 Pass the net ack text to the modem. 2020-04-14 12:22:23 +01:00
Jonathan Naylor
1f17aec1f1 Add the minimum time for a 'K' parameter. 2020-04-13 15:53:18 +01:00
Jonathan Naylor
58aff1ab77 Split the RF and Network acks. 2020-04-13 13:36:16 +01:00
Jonathan Naylor
211e96a86d Convert to percentages. 2020-04-12 16:01:28 +01:00
Jonathan Naylor
927f31cdfa Move the levels to the overall MMDVM control message. 2020-04-12 15:10:51 +01:00
Jonathan Naylor
dcdfca39d7 Add FM mode display. 2020-04-11 20:42:05 +01:00
SASANO Takayoshi
5df1fe551f add IPv6 support for RemoteControl
To specify IP(v4/v6) address for RemoteControl port,
add Address parameter in [RemoteControl] section to MMDVM.ini.

Different from other Address(es), the default IP address of RemoteControl
is 127.0.0.1 for security.
2020-04-11 13:12:19 +09:00
Jonathan Naylor
c381f2ceac Convert the callsign and ack to upper case. 2020-04-10 13:52:49 +01:00
Jonathan Naylor
8cd75ce787 Add the FM repeater modem parameter writes. 2020-04-09 22:55:20 +01:00
Jonathan Naylor
535ddba1a0 Beginnings of FM support. 2020-04-09 22:02:47 +01:00
SASANO Takayoshi
88bbb0cd0f use getaddrinfo() AI_PASSIVE flag, to remove "::" and "0.0.0.0" 2020-04-06 18:35:12 +09:00
SASANO Takayoshi
15b5011ebf rewrite with getaddrinfo() API to support IPv6
Currently LCDproc seems to be IPv6 unsupported, but this code is
modified for the future IPv6-supported LCDproc.
2020-04-06 18:35:12 +09:00
SASANO Takayoshi
dad47317e6 set INADDR_ANY/IN6ADDR_ANY_INIT address string to m_socket
when CUDPSocket::open() is called with m_address (in CUDPSocket) is nothing,
IPv4 socket is created by "0.0.0.0" (INADDR_ANY) address.

This causes a problem that DMRGateway cannot connect to reflector on IPv6.
To choose default INADDR_ANY/IN6ADDR_ANY_INIT address, added
open(address_family) in UDPSocket.cpp.

Following code sets address string at construction, not modified.
	NXDNNetwork.cpp
	POCSAGNetwork.cpp
	YSFNetwork.cpp

Other codes does not set, modified open() -> open(address_family)
	DMRNetwork.cpp
	DStarNetwork.cpp
	MMDVMHost.cpp
	MobileGPS.cpp
	P25Network.cpp
	RemoteCommand.cpp
	RemoteControl.cpp

I think there is more clever method, but I have no other idea.

Maybe IPv6 support for digital radio works, but RemoteControl can work
IPv4 only.
2020-04-06 18:35:12 +09:00
SASANO Takayoshi
c92039d83b modified for IPv6 supported CUDPSocket 2020-04-06 18:34:54 +09:00
Jonathan Naylor
4c4ea170b6 Add correct copyright. 2020-04-03 17:09:17 +01:00
Jonathan Naylor
63ee2eb98c
Merge pull request #564 from f1rmb/silence_DMRTA_warning
Remove warning
2020-03-30 20:04:21 +01:00
Daniel Caujolle-Bert
e780e8bd30
Remove warning 2020-03-30 20:30:43 +02:00
SASANO Takayoshi
5dccd5c5ce add match(), isnone() utility function
match() checks address family, IP address and port between
two sockaddr_storages.

isnone() checks sockaddr_storage has INADDR_NONE IPv4 address.
(sockaddr_storage has this address when lookup() failed)
2020-03-28 04:37:51 +09:00
SASANO Takayoshi
022d1a768b add IPv6 support (code from DAPNETGateway-IPv6) 2020-03-27 06:25:54 +09:00
Jonathan Naylor
90c5b24e9f
Merge pull request #562 from jg1uaa/master
Simplify termios setting for serial port
2020-03-25 07:36:30 +00:00
SASANO Takayoshi
ac50244de3 Simplify termios setting for serial port
Testing MMDVMCal on OpenBSD/armv7 + BananaPi BPI-P2 requires CLOCAL flag.
Flags for termios should be same between OSX and other OSes
so unified them (except VMIN and VTIME setting).
2020-03-25 14:32:27 +09:00
Jonathan Naylor
6d27b8d957
Merge pull request #561 from jg1uaa/userdb
UserDB support (NXDN/DMR)
2020-03-24 22:19:04 +00:00
SASANO Takayoshi
d7d83ff4d0 use findWithName() to display user information when netork voice transmission 2020-03-15 10:36:57 +09:00
SASANO Takayoshi
e036ac8be3 revise snprintf() format string to simplify display layout (all modes) 2020-03-12 21:48:21 +09:00
SASANO Takayoshi
cc62fb62b7 add NXDN user data display 2020-03-10 06:14:17 +09:00
SASANO Takayoshi
36414acc6a add UserDB-based NXDN display interface 2020-03-10 05:46:24 +09:00
SASANO Takayoshi
d2751897fb cosme 2020-03-10 05:26:45 +09:00
SASANO Takayoshi
f6b5036651 NXDNLookup now use UserDB 2020-03-09 22:23:55 +09:00
SASANO Takayoshi
136a148480 delete unused variable 2020-03-09 22:16:21 +09:00
SASANO Takayoshi
6febd661f6 add return value description of writeDMRIntEx() 2020-03-09 20:48:14 +09:00
SASANO Takayoshi
92a3441116 code cleanup: remove unneeded std::string() 2020-03-08 20:47:48 +09:00
SASANO Takayoshi
5bd54e97cb add writeDMRIntEx() to support UserDB display 2020-03-08 08:43:57 +09:00
SASANO Takayoshi
4ff77c50d6 use UserDBentry from findWithName() to writeDMR(), add writeDMREx() 2020-03-08 08:06:27 +09:00
SASANO Takayoshi
abf17e19fc get() goes const, add clear() 2020-03-08 07:55:08 +09:00
SASANO Takayoshi
b7f5fdd8a2 use class UserDB (user-info storage) 2020-03-07 16:52:11 +09:00
SASANO Takayoshi
9b15454f96 makeindex() needs clear old result, add index.clear() 2020-03-07 16:44:50 +09:00
SASANO Takayoshi
a2911fa5c3 avoid registing "" string to reduce memory consumption 2020-03-06 21:56:00 +09:00
SASANO Takayoshi
92d9973ace revise LogWarning message, and cosmetic changes 2020-03-05 19:26:02 +09:00
SASANO Takayoshi
8ff3913729 add user database storage
simply added UserDB* source code and modified Makefile.
others are untouched.
2020-03-05 06:35:14 +09:00
Jonathan Naylor
ab13f355d5 Add decode for Call Alert and Call Alert Ack CSBKs. 2020-03-02 12:10:44 +00:00
Jonathan Naylor
8d87037ee5
Merge pull request #558 from jg1uaa/master
TFTSurenoo: Simplify DMR status display
2020-02-29 12:15:32 +00:00
SASANO Takayoshi
0bc6bcdb26 Fix DMR status display for duplex mode
Previous change (simplyfy DMR status display) did not consider
DMR duplex mode.

Now DMR simplex mode uses 2-lines style, duplex mode 4-lines like this.

	Listening
	TS1
	N Callsign
	TS2 TGxx

For this change, statusLine() no longer have meaning.
It will be removed in the future.
2020-02-29 06:51:26 +09:00
SASANO Takayoshi
ead41ba9a5 Simplify DMR status display
Old DMR status display takes 4 lines i.e.:

	1 Listening
	(unused line here)
	2 N Callsign
	TGxx

To make room for display area for future development, DMR status display
are changed to 2-lines style like this:

	N Callsign
	TS2 TGxx

And, added three small changes:

	- use statusLine() macro to change layout easily
	- use two -> three colors
		yellow: radio mode (DMR, YSF, etc)
		cyan: main status (callsign, TG/Timeslot)
		dark green: additional information (D* reflector etc) *NEW*
	- rename statusLine_offset() -> statusLineOffset()
2020-02-28 04:53:14 +09:00
Jonathan Naylor
b0fe8dc607
Merge pull request #557 from jg1uaa/master
TFTSurenoo: stability fix (workaround for display is not cleared)
2020-02-25 22:44:56 +00:00
SASANO Takayoshi
a117d70c56 send CR+LF (command terminator) first at refreshDisplay()
Sometimes BOXF (box fill) command at refreshDisplay() fails.
Normally this is not occured, but running MMDVMHost for long time
(about one day) we see this problem.

The reason is unknown. But if LCD panel receives garbage character between
calling refreshDisplay(), first command (BOXF) at latter-called
refresDdisplay() will fail.

For workaround, send CR+LF command terminator first at this function.
2020-02-24 17:52:30 +09:00
Jonathan Naylor
2a9d90b7c7
Merge pull request #555 from jg1uaa/master
Lookup name on DMR network late entry (2)
2020-02-17 11:56:34 +00:00
SASANO Takayoshi
45013ac179 Lookup name on DMR network late entry (2)
There is two cases that shows "received network late entry"

1. dataType == DT_VOICE_PI_HEADER && m_netState != RS_NET_AUDIO
2. dataType == DT_VOICE_SYNC && m_netState == RS_NET_IDLE

case 1 is already treated. this fix is for case 2.
2020-02-17 19:57:47 +09:00
SASANO Takayoshi
b86bc820e8 Merge remote-tracking branch 'upstream/master' 2020-02-17 07:02:02 +09:00
Jonathan Naylor
4450caeddc Update the copyright date. 2020-02-16 15:56:31 +00:00
Jonathan Naylor
fa08abfded Lookup name on DMR network late entry. 2020-02-16 15:52:42 +00:00
Jonathan Naylor
8b172f1221
Merge pull request #551 from jg1uaa/master
improve refreshing display
2020-02-16 15:45:01 +00:00
SASANO Takayoshi
88304997d4 Merge remote-tracking branch 'upstream/master' 2020-02-15 07:55:36 +09:00
Jonathan Naylor
d70a124f47 Update files to VS2019. 2020-02-14 20:53:21 +00:00
SASANO Takayoshi
60e82737b9 improve refreshing display
Display space character with DCV command to clear screen, but this command is
very slow. I tested filling whole 160x128 area with 8x16 character by DCV16
command, it took 540msec.

This is the worst case, but display refresh period has extended to 600ms
for safety.

To clear screen, use BOXF command instead. And, reduced issuing DCV command.
2020-01-18 06:29:49 +09:00
Jonathan Naylor
95c1bbb8e6
Merge pull request #550 from f1rmb/OPENGD77_HS
Identify OpenGD77 hotspot.
2020-01-10 11:28:47 +00:00
Daniel Caujolle-Bert
5686942519
Identify OpenGD77 hotspot. 2020-01-08 10:58:41 +01:00
Jonathan Naylor
3fa72d853d Fix compilation warnings. 2019-12-27 17:26:46 +00:00
Jonathan Naylor
a0ec58539a Remove duplication of frames. 2019-12-15 22:22:47 +00:00
Jonathan Naylor
3b7452feda Update for VS2017 2019-12-15 22:20:03 +00:00
Jonathan Naylor
0e78fafa91
Merge pull request #543 from jg1uaa/master
Add Surenoo UART-TFT panel (1.8inch, 128x160) support.
2019-12-08 21:44:04 +00:00
SASANO Takayoshi
be6f59ba5f fix copyright header
Add coder's name.

This code is forked from TFTSerial.cpp and TFTSerial.h
so original author's credit is kept.
2019-12-09 06:38:21 +09:00
Jonathan Naylor
ce5a212bd3
Merge pull request #542 from shawnchain/fix_emb_fec
Fix DMREMB FEC decode bug
2019-12-07 16:18:42 +00:00
Shawn Chain
ab226cec27 change variable type to unsigned char 2019-12-07 23:25:57 +08:00
Shawn Chain
31408d4a33 Fix DMREMB fec decode bug 2019-12-07 15:47:43 +08:00
Jonathan Naylor
6713e0f52b
Merge pull request #540 from simonvik/patch-1
Add wiringpi as build dep when building the oled target.
2019-12-04 14:12:26 +00:00
Simon Vikström
1ba4879224
Update OLED.md
wiringpi is needed when building the OLED target.
2019-12-04 15:07:54 +01:00
SASANO Takayoshi
f3844ceae8 Add Surenoo UART-TFT panel (1.8inch, 128x160) support.
HobbyTronics TFT Shield has discontinued, here is a replacement TFT module
that can be controlled from UART.

Different from TFT Shield, it cannot display figures that stored in
micro SD card. So appearance is simplified like OLED.

Surenoo module sometimes ignores display commands (in busy stuation?),
this driver buffers display status and refresh at clockInt().
2019-12-01 16:33:19 +09:00
Jonathan Naylor
b29e1d0050
Merge pull request #536 from maierp/maier_p_dont_remove_ovcm
Don't remove OVCM bit. Only set it when configured.
2019-11-29 16:15:10 +00:00
Patrick Maier
9234dfcf6a Don't remove OVCM bit. Only set it when configured. 2019-11-23 11:11:53 +01:00
Jonathan Naylor
ed7f593e07 Remove the duplicate end of DMR transmission network message. 2019-11-20 08:13:26 +00:00
Jonathan Naylor
de88f09b68
Merge pull request #534 from shawnchain/fix_ovcm_config
Change ovcm config to int value
2019-11-19 07:53:18 +00:00
Shawn Chain
2ecd9b3440 fix OVCM enum logical check 2019-11-19 11:05:45 +08:00
Shawn Chain
c2584066d8 Correct the m_ovcm flag check in DMRSlot 2019-11-18 20:47:56 +08:00
Shawn Chain
88d91e420a use enum DMR_OVCM_TYPES 2019-11-17 10:57:58 +08:00
Shawn Chain
d5b08ea7ea fix config comment typo 2019-11-16 23:14:55 +08:00
Shawn Chain
2f9595949a Change ovcm config to int value 2019-11-16 23:06:26 +08:00
Jonathan Naylor
aa7ae2371c
Merge pull request #533 from maierp/maier_p_ovcm_rx
Config setting for sending OVCM to network (RX)
2019-11-15 11:58:02 +00:00
Jonathan Naylor
b38ba239a8 Merge branch 'master' into dmr_beacons 2019-11-13 08:41:11 +00:00
Patrick Maier
7cdbbdecb0 fix missing changes of ovcmRX in MMDVMHost.cpp 2019-11-09 20:50:03 +01:00
Patrick Maier
6caffb2bc0 Separate the config if OVCM should be supported in sending and receiving direction 2019-11-09 17:22:39 +01:00
Jonathan Naylor
8d88d8e5ed Update the NXDN IDs file from radioid.net. 2019-11-07 14:02:40 +00:00
Jonathan Naylor
484b0f3e25 Update the DMR Ids. 2019-11-07 13:53:57 +00:00
Jonathan Naylor
231efdf567 Clean up the OVCM CSBK code. 2019-11-07 13:47:19 +00:00
Jonathan Naylor
e74df4875b
Merge pull request #532 from maierp/maierp_ovcm_in_csbk
Include ovcm also in csbk
2019-11-06 15:28:34 +00:00
Florian (DF2ET)
fa8d735b1b
Merge pull request #531 from shawnchain/disable_ovcm_ini
Comment out the OVCM=1 in MMDVM.ini
2019-11-06 06:51:57 +01:00
Shawn Chain
c18c0a3105 Comment out the OVCM=1 in MMDVM.ini 2019-11-06 13:23:49 +08:00
Jonathan Naylor
bc5a1d24c4 Make the default for OVCM to be off. 2019-11-05 15:49:00 +00:00
Jonathan Naylor
f4f745d58c Fix variable scope bug. 2019-11-05 12:44:56 +00:00
phl0
4be7ccd924
Fix changed type for dmr_Beacons 2019-11-05 12:50:59 +01:00
Jonathan Naylor
ef1631ac33 Convert strncpy to memcpy to avoid static analysis complaints. 2019-11-05 09:01:49 +00:00
Jonathan Naylor
98e0869257 Re-introduce optional network DMR beacons. 2019-11-05 08:42:21 +00:00
Jonathan Naylor
079c95aac1
Merge pull request #527 from R1IK-Yakov/patch-1
Update NXDN.csv
2019-10-24 12:02:48 +01:00
Yakov Danilov
e885c84f6e
Update NXDN.csv
Add 10713,R1IK,Yakov,Danilov,Syktyvkar,Komi,Russia,nxdn.r1ik.ru
2019-10-22 17:05:40 +03:00
Patrick Maier
529fdf88eb possible fix 2019-10-18 20:13:08 +02:00
maierp
1ed79d01c0
Merge pull request #2 from maierp/master
Merge changes from master to sidebranch
2019-10-18 19:58:16 +02:00
maierp
cd40f6602d
Merge pull request #1 from g4klx/master
Merge new commits from g4ktx/MMDVMHost to maierp/MMDVMHost
2019-10-18 19:56:14 +02:00
Patrick Maier
1993262c52 Also set the OVCM bit in the two supported CSBKs: "Unit to Unit Voice Service Request CSBK" and "Unit to Unit Voice Service Answer Response CSBK" 2019-10-18 19:40:35 +02:00
Jonathan Naylor
56298d14c4
Merge pull request #525 from dk5ras/dk5ras-OVCM-patch-1
Fix issue in DMRLC.cpp
2019-10-15 12:14:37 +01:00
Ralph A. Schmid
0711a2b391
Fix issue in DMRLC.cpp
The position of the OVCM bit was counted from the wrong end of the byte - fixed this (DK5MP and me had the same issue when we made our first OVCM tests)...
2019-10-15 12:24:58 +02:00
Jonathan Naylor
6bababeb96 Add OVCM support. 2019-10-11 18:24:25 +01:00
Jonathan Naylor
16a8bfd757 Remove use of NULL m_rfLC. 2019-10-10 13:06:28 +01:00
Jonathan Naylor
4f3ca97e69 Remove use of NULL m_netLC. 2019-10-10 11:53:08 +01:00
sp5lg
bb0bd4bb46 DStar SelfOnly with WhiteList (beautyfied) 2019-10-06 16:29:57 +02:00
sp5lg
ed79a7176a DStar SelfOnly with WhiteList 2019-10-06 16:15:25 +02:00
Jonathan Naylor
87e60a81f8 Add end of transmission data to DMR. 2019-09-29 17:30:25 +01:00
Jonathan Naylor
0b7f2e1e4b Add end of transmission data for D-Star. 2019-09-29 17:06:22 +01:00
Jonathan Naylor
0eae2c8224 Add extra end of transmission data for YSF. 2019-09-29 16:59:11 +01:00
Jonathan Naylor
881b32f0a9 Add extra information for NXDN end of transmission. 2019-09-29 16:53:57 +01:00
Jonathan Naylor
54ae56942f Add P25 end of transmission data. 2019-09-29 16:34:56 +01:00
Florian Wolters
005590b6aa
Minor code beauty 2019-09-27 22:48:57 +02:00
Florian (DF2ET)
78753cbbad
Merge pull request #521 from sp5lg/master
Introducing LogoScreensaver=1 or 0 parameter for blanking OLED display
2019-09-27 22:46:30 +02:00
sp5lg
bd5117b9e4 Introducing LogoScreensaver=1 or 0 parameter for blanking OLED diplays in idle 2019-09-27 22:28:57 +02:00
Jonathan Naylor
d0dbb1127b
Merge pull request #516 from hewittc/overflow
Fix a couple of buffer overflows
2019-09-03 21:17:51 +01:00
Christopher Hewitt
06af86b70d Adding missing P25 FEC table entry to avoid buffer overflow. 2019-09-03 15:22:35 -04:00
Christopher Hewitt
839a8c83ea Increase data buffer size to avoid buffer overflow for P25. 2019-09-03 15:22:24 -04:00
Andy CA6JAU
0b9c1b1362 Support for D2RG MMDVM_HS 2019-05-29 21:22:53 -04:00
Jonathan Naylor
99c8b23f41
Merge pull request #506 from shawnchain/pr503-cleanup
update OLED.h
2019-05-15 17:38:26 +01:00
Shawn Chain
750ef77321 update OLED.h 2019-05-15 23:32:10 +08:00
Jonathan Naylor
73bf04ad4b
Merge pull request #505 from shawnchain/pr503-cleanup
remove unused variables from OLED class
2019-05-14 13:25:19 +01:00
Shawn Chain
814059ff35 remove unused variables from OLED class 2019-05-14 18:19:02 +08:00
Jonathan Naylor
ffd5cd1a0b Fix the Windows build for the CASTInfo display driver. 2019-05-11 11:40:08 +01:00
Jonathan Naylor
2aa130e22f
Merge pull request #503 from GuusvanDooren/master
QSO info removed from OLED. QSO info add via CASTInfo.
2019-05-10 22:06:34 +01:00
GuusvanDooren
847652f8ce Update make files. 2019-05-10 22:54:14 +02:00
GuusvanDooren
6d83bfb8bc QSO info removed from OLED. QSO info add via CASTInfo. 2019-05-10 20:44:01 +02:00
Jonathan Naylor
5acef270d1
Merge pull request #498 from jg1uaa/master
Add OpenBSD support
2019-03-18 08:03:53 +00:00
SASANO Takayoshi
7cf1e602e6 Use system default compiler. At least there is no difference under Linux.
OpenBSD's gcc is old (4.2) so we have to use clang-6.0.0 compiler.
2019-03-13 20:33:02 +09:00
SASANO Takayoshi
4e910ef970 I2C support is only Linux.
So code should be compiled under Linux, not avoiding Apple.
2019-03-13 20:30:49 +09:00
SASANO Takayoshi
e5a1ed5de5 There is no I2C related code, <linux/i2c-dev.h> removed. 2019-03-13 20:29:45 +09:00
SASANO Takayoshi
9d3a58c103 <netinet/in.h> of Linux automatically includes <sys/socket.h>,
but OpenBSD's not. So added it.
2019-03-13 20:18:12 +09:00
Andy CA6JAU
c47d783d2d
Merge pull request #496 from jake-b/master
Minor fix for status bar scrolling
2019-03-09 15:06:37 -03:00
Jake
ed71aab1da Minor fix for status bar scrolling 2019-03-09 13:04:12 -05:00
Jonathan Naylor
e88964a777 Simplify the tty test. 2019-02-28 07:56:00 +00:00
Jonathan Naylor
9350fa8483 Allow for non-TTY links to the modem. 2019-02-27 19:36:17 +00:00
Jonathan Naylor
0dd446eb29 Fix compile issue. 2019-02-12 20:45:03 +00:00
Jonathan Naylor
72fe13780f Remove the old System Fusion SQL config option and processing. 2019-02-12 11:29:05 +00:00
Jonathan Naylor
c3c5fe1a5a Remove more redundant code. 2019-01-31 08:29:31 +00:00
Jonathan Naylor
26bbbefc40 Bump the version date. 2019-01-31 08:25:49 +00:00
Jonathan Naylor
f88c9826a7 Remove redundant code. 2019-01-31 08:25:35 +00:00
Jonathan Naylor
6d719353c6 Loosen fast data admission criteria. 2019-01-30 20:20:15 +00:00
Jonathan Naylor
317bda0177 Check the guard byte on fast data as well as the mini header. 2019-01-29 22:32:24 +00:00
Jonathan Naylor
9cc2bfaaec Fix the silence insertion for D-Star. 2019-01-28 07:50:43 +00:00
Jonathan Naylor
99d4a9bc51 Simplify the D-Star sequence number processing. 2019-01-27 20:15:14 +00:00
Jonathan Naylor
ff0082b18b Only test the slow data type in the correct place. 2019-01-26 19:25:12 +00:00
Jonathan Naylor
6c07786f1b Merge branch 'master' into fast_data 2019-01-26 12:57:59 +00:00
Jonathan Naylor
fe2a01e1b1 Fix DMR beacon bug spotted by Shawnchain. 2019-01-26 12:56:24 +00:00
Jonathan Naylor
59cb07329d Place the scrambled null data regeneration into the right place. 2019-01-25 12:40:31 +00:00
Jonathan Naylor
16bf9d5745 Don't forget to descramble the byte first. 2019-01-25 11:38:03 +00:00
Jonathan Naylor
a9b7179d13 New way to detect D-Star fast data mode. 2019-01-25 11:23:51 +00:00
219 changed files with 45405 additions and 27586 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;

99
CASTInfo.cpp Normal file
View file

@ -0,0 +1,99 @@
/*
* Copyright (C) 2016,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 "CASTInfo.h"
static bool networkInfoInitialized = false;
static unsigned char passCounter = 0;
CCASTInfo::CCASTInfo(CModem* modem) :
CDisplay(),
m_modem(modem),
m_ipaddress()
{
}
CCASTInfo::~CCASTInfo()
{
}
bool CCASTInfo::open()
{
return true;
}
void CCASTInfo::setIdleInt()
{
unsigned char info[100U];
CNetworkInfo* m_network;
passCounter ++;
if (passCounter > 253U)
networkInfoInitialized = false;
if (! networkInfoInitialized) {
//LogMessage("Initialize CNetworkInfo");
info[0]=0;
m_network = new CNetworkInfo;
m_network->getNetworkInterface(info);
m_ipaddress = (char*)info;
delete m_network;
if (m_modem != NULL)
m_modem->writeIPInfo(m_ipaddress);
networkInfoInitialized = true;
passCounter = 0;
}
}
void CCASTInfo::setErrorInt(const char* text)
{
}
void CCASTInfo::setLockoutInt()
{
}
void CCASTInfo::setQuitInt()
{
}
void CCASTInfo::writeDMRInt(unsigned int slotNo, const std::string& src, bool group, const std::string& dst, const char* type)
{
if (m_modem != NULL)
m_modem->writeDMRInfo(slotNo, src, group, dst, type);
}
void CCASTInfo::clearDMRInt(unsigned int slotNo)
{
}
void CCASTInfo::writeCWInt()
{
}
void CCASTInfo::clearCWInt()
{
}
void CCASTInfo::close()
{
}

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2018 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
@ -16,48 +16,41 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/ */
#ifndef MobileGPS_H #if !defined(CASTINFO_H)
#define MobileGPS_H #define CASTINFO_H
#include "DMRNetwork.h" #include "Display.h"
#include "UDPSocket.h"
#include "Timer.h"
#include <string> #include <string>
#if !defined(_WIN32) && !defined(_WIN64) #include "NetworkInfo.h"
#include <netdb.h> #include "Modem.h"
#include <sys/time.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <errno.h>
#else
#include <winsock.h>
#endif
class CMobileGPS { class CCASTInfo : public CDisplay
{
public: public:
CMobileGPS(const std::string& address, unsigned int port, CDMRNetwork* network); CCASTInfo(CModem* modem);
~CMobileGPS(); virtual ~CCASTInfo();
bool open(); virtual bool open();
void clock(unsigned int ms); virtual void close();
void close(); protected:
virtual void setIdleInt();
virtual void setErrorInt(const char* text);
virtual void setLockoutInt();
virtual void setQuitInt();
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 writeCWInt();
virtual void clearCWInt();
private: private:
CTimer m_idTimer; CModem* m_modem;
in_addr m_address; std::string m_ipaddress;
unsigned int m_port;
CUDPSocket m_socket;
CDMRNetwork* m_network;
bool pollGPS();
void sendReport();
}; };
#endif #endif

922
Conf.cpp

File diff suppressed because it is too large Load diff

264
Conf.h
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
@ -54,6 +54,7 @@ public:
unsigned int getLogFileLevel() const; unsigned int getLogFileLevel() const;
std::string getLogFilePath() const; std::string getLogFilePath() const;
std::string getLogFileRoot() const; std::string getLogFileRoot() const;
bool getLogFileRotate() const;
// The CW ID section // The CW ID section
bool getCWIdEnabled() const; bool getCWIdEnabled() const;
@ -64,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;
@ -89,37 +92,25 @@ public:
float getModemYSFTXLevel() const; float getModemYSFTXLevel() const;
float getModemP25TXLevel() const; float getModemP25TXLevel() const;
float getModemNXDNTXLevel() const; float getModemNXDNTXLevel() const;
float getModemM17TXLevel() const;
float getModemPOCSAGTXLevel() const; float getModemPOCSAGTXLevel() const;
float getModemFMTXLevel() const;
float getModemAX25TXLevel() const;
std::string getModemRSSIMappingFile() const; std::string getModemRSSIMappingFile() const;
bool getModemUseCOSAsLockout() const;
bool getModemTrace() const; bool getModemTrace() const;
bool getModemDebug() const; bool getModemDebug() const;
// 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
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;
bool getDStarAckReply() const;
unsigned int getDStarAckTime() const;
bool getDStarAckMessage() const;
bool getDStarErrorReply() const;
bool getDStarRemoteGateway() const;
unsigned int getDStarModeHang() const;
// The DMR section // The DMR section
bool getDMREnabled() const; bool getDMREnabled() const;
bool getDMRBeacons() const; DMR_BEACONS getDMRBeacons() const;
unsigned int getDMRBeaconInterval() const; unsigned int getDMRBeaconInterval() const;
unsigned int getDMRBeaconDuration() const; unsigned int getDMRBeaconDuration() const;
unsigned int getDMRId() const; unsigned int getDMRId() const;
@ -135,51 +126,15 @@ public:
unsigned int getDMRCallHang() const; unsigned int getDMRCallHang() const;
unsigned int getDMRTXHang() const; unsigned int getDMRTXHang() const;
unsigned int getDMRModeHang() const; unsigned int getDMRModeHang() const;
DMR_OVCM_TYPES getDMROVCM() const;
// The System Fusion section
bool getFusionEnabled() const;
bool getFusionLowDeviation() const;
bool getFusionRemoteGateway() const;
bool getFusionSelfOnly() const;
unsigned int getFusionTXHang() const;
bool getFusionSQLEnabled() const;
unsigned char getFusionSQL() 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 getP25ModeHang() const;
// The NXDN section
bool getNXDNEnabled() const;
unsigned int getNXDNId() const;
unsigned int getNXDNRAN() const;
bool getNXDNSelfOnly() const;
bool getNXDNRemoteGateway() const;
unsigned int getNXDNModeHang() const;
// The POCSAG section
bool getPOCSAGEnabled() const;
unsigned int getPOCSAGFrequency() 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 // 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;
@ -188,41 +143,6 @@ public:
bool getDMRNetworkSlot2() const; bool getDMRNetworkSlot2() const;
unsigned int getDMRNetworkModeHang() const; unsigned int getDMRNetworkModeHang() const;
// The System Fusion Network 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 getNXDNGatewayAddress() const;
unsigned int getNXDNGatewayPort() const;
std::string getNXDNLocalAddress() const;
unsigned int getNXDNLocalPort() const;
unsigned int getNXDNNetworkModeHang() const;
bool getNXDNNetworkDebug() 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 // The TFTSERIAL section
std::string getTFTSerialPort() const; std::string getTFTSerialPort() const;
unsigned int getTFTSerialBrightness() const; unsigned int getTFTSerialBrightness() const;
@ -254,12 +174,12 @@ public:
bool getOLEDInvert() const; bool getOLEDInvert() const;
bool getOLEDScroll() const; bool getOLEDScroll() const;
bool getOLEDRotate() const; bool getOLEDRotate() const;
bool getOLEDCast() const; bool getOLEDLogoScreensaver() const;
// 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;
@ -268,14 +188,10 @@ public:
bool getLockFileEnabled() const; bool getLockFileEnabled() const;
std::string getLockFileName() const; std::string getLockFileName() const;
// The Mobile GPS section
bool getMobileGPSEnabled() const;
std::string getMobileGPSAddress() const;
unsigned int getMobileGPSPort() const;
// The Remote Control section // The Remote Control section
bool getRemoteControlEnabled() const; bool getRemoteControlEnabled() const;
unsigned int getRemoteControlPort() const; std::string getRemoteControlAddress() const;
unsigned short getRemoteControlPort() const;
private: private:
std::string m_file; std::string m_file;
@ -300,6 +216,7 @@ private:
unsigned int m_logFileLevel; unsigned int m_logFileLevel;
std::string m_logFilePath; std::string m_logFilePath;
std::string m_logFileRoot; std::string m_logFileRoot;
bool m_logFileRotate;
bool m_cwIdEnabled; bool m_cwIdEnabled;
unsigned int m_cwIdTime; unsigned int m_cwIdTime;
@ -311,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;
@ -326,38 +249,20 @@ 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_modemPOCSAGTXLevel;
std::string m_modemRSSIMappingFile; std::string m_modemRSSIMappingFile;
bool m_modemUseCOSAsLockout;
bool m_modemTrace; bool m_modemTrace;
bool m_modemDebug; bool m_modemDebug;
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;
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;
bool m_dmrBeacons; DMR_BEACONS m_dmrBeacons;
unsigned int m_dmrBeaconInterval; unsigned int m_dmrBeaconInterval;
unsigned int m_dmrBeaconDuration; unsigned int m_dmrBeaconDuration;
unsigned int m_dmrId; unsigned int m_dmrId;
@ -373,45 +278,14 @@ private:
unsigned int m_dmrCallHang; unsigned int m_dmrCallHang;
unsigned int m_dmrTXHang; unsigned int m_dmrTXHang;
unsigned int m_dmrModeHang; unsigned int m_dmrModeHang;
DMR_OVCM_TYPES m_dmrOVCM;
bool m_fusionEnabled;
bool m_fusionLowDeviation;
bool m_fusionRemoteGateway;
bool m_fusionSelfOnly;
unsigned int m_fusionTXHang;
bool m_fusionSQLEnabled;
unsigned char m_fusionSQL;
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_p25ModeHang;
bool m_nxdnEnabled;
unsigned int m_nxdnId;
unsigned int m_nxdnRAN;
bool m_nxdnSelfOnly;
bool m_nxdnRemoteGateway;
unsigned int m_nxdnModeHang;
bool m_pocsagEnabled;
unsigned int m_pocsagFrequency;
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;
@ -420,37 +294,6 @@ private:
bool m_dmrNetworkSlot2; bool m_dmrNetworkSlot2;
unsigned int m_dmrNetworkModeHang; unsigned int m_dmrNetworkModeHang;
bool m_fusionNetworkEnabled;
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_nxdnGatewayAddress;
unsigned int m_nxdnGatewayPort;
std::string m_nxdnLocalAddress;
unsigned int m_nxdnLocalPort;
unsigned int m_nxdnNetworkModeHang;
bool m_nxdnNetworkDebug;
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; std::string m_tftSerialPort;
unsigned int m_tftSerialBrightness; unsigned int m_tftSerialBrightness;
@ -478,11 +321,11 @@ private:
bool m_oledInvert; bool m_oledInvert;
bool m_oledScroll; bool m_oledScroll;
bool m_oledRotate; bool m_oledRotate;
bool m_oledCast; 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;
@ -490,12 +333,9 @@ private:
bool m_lockFileEnabled; bool m_lockFileEnabled;
std::string m_lockFileName; std::string m_lockFileName;
bool m_mobileGPSEnabled;
std::string m_mobileGPSAddress;
unsigned int m_mobileGPSPort;
bool m_remoteControlEnabled; bool m_remoteControlEnabled;
unsigned int m_remoteControlPort; std::string m_remoteControlAddress;
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,6 @@
/* /*
* Copyright (C) 2015,2016 by Jonathan Naylor G4KLX * Copyright (C) 2015,2016,2020,2021,2022 by Jonathan Naylor G4KLX
* 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
* 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
@ -33,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];
} }
@ -80,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;
@ -89,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;
@ -110,6 +114,39 @@ bool CDMRCSBK::put(const unsigned char* bytes)
CUtils::dump(1U, "Negative Acknowledge Response CSBK", m_data, 12U); CUtils::dump(1U, "Negative Acknowledge Response CSBK", m_data, 12U);
break; break;
case CSBKO_CALL_ALERT:
m_GI = false;
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];
m_dataContent = false;
m_CBF = 0U;
CUtils::dump(1U, "Call Alert CSBK", m_data, 12U);
break;
case CSBKO_CALL_ALERT_ACK:
m_GI = false;
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];
m_dataContent = false;
m_CBF = 0U;
CUtils::dump(1U, "Call Alert Ack CSBK", m_data, 12U);
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;
@ -149,6 +186,23 @@ unsigned char CDMRCSBK::getFID() const
return m_FID; return m_FID;
} }
bool CDMRCSBK::getOVCM() const
{
return m_OVCM;
}
void CDMRCSBK::setOVCM(bool ovcm)
{
if (m_CSBKO == CSBKO_UUVREQ || m_CSBKO == CSBKO_UUANSRSP) {
m_OVCM = ovcm;
if (ovcm)
m_data[2U] |= 0x04U;
else
m_data[2U] &= 0xFBU;
}
}
bool CDMRCSBK::getGI() const bool CDMRCSBK::getGI() const
{ {
return m_GI; return m_GI;

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2015,2016 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
@ -26,6 +26,9 @@ enum CSBKO {
CSBKO_UUVREQ = 0x04, CSBKO_UUVREQ = 0x04,
CSBKO_UUANSRSP = 0x05, CSBKO_UUANSRSP = 0x05,
CSBKO_CTCSBK = 0x07, CSBKO_CTCSBK = 0x07,
CSBKO_CALL_ALERT = 0x1F,
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
@ -45,6 +48,10 @@ public:
CSBKO getCSBKO() const; CSBKO getCSBKO() const;
unsigned char getFID() const; unsigned char getFID() const;
// Set/Get the OVCM bit in the supported CSBKs
bool getOVCM() const;
void setOVCM(bool ovcm);
// For BS Dwn Act // For BS Dwn Act
unsigned int getBSId() const; unsigned int getBSId() const;
@ -69,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) : 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,7 +38,14 @@ 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);
CDMRSlot::init(colorCode, embeddedLCOnly, dumpTAData, callHang, modem, network, display, duplex, m_lookup, rssi, jitter); //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);
} }
CDMRControl::~CDMRControl() CDMRControl::~CDMRControl()
@ -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); 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

View file

@ -44,11 +44,11 @@ void CDMREMB::putData(const unsigned char* data)
DMREMB[1U] = (data[18U] << 4) & 0xF0U; DMREMB[1U] = (data[18U] << 4) & 0xF0U;
DMREMB[1U] |= (data[19U] >> 4) & 0x0FU; DMREMB[1U] |= (data[19U] >> 4) & 0x0FU;
CQR1676::decode(DMREMB); unsigned char code = CQR1676::decode(DMREMB);
m_colorCode = (DMREMB[0U] >> 4) & 0x0FU; m_colorCode = (code >> 4) & 0x0FU;
m_PI = (DMREMB[0U] & 0x08U) == 0x08U; m_PI = (code & 0x08U) == 0x08U;
m_LCSS = (DMREMB[0U] >> 1) & 0x03U; m_LCSS = (code >> 1) & 0x03U;
} }
void CDMREMB::getData(unsigned char* data) const void CDMREMB::getData(unsigned char* data) const

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

42048
DMRIds.dat

File diff suppressed because it is too large Load diff

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2015,2016 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
@ -184,6 +184,19 @@ void CDMRLC::setFID(unsigned char fid)
m_FID = fid; m_FID = fid;
} }
bool CDMRLC::getOVCM() const
{
return (m_options & 0x04U) == 0x04U;
}
void CDMRLC::setOVCM(bool ovcm)
{
if (ovcm)
m_options |= 0x04U;
else
m_options &= 0xFBU;
}
unsigned int CDMRLC::getSrcId() const unsigned int CDMRLC::getSrcId() const
{ {
return m_srcId; return m_srcId;

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2015,2016 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
@ -39,6 +39,9 @@ public:
FLCO getFLCO() const; FLCO getFLCO() const;
void setFLCO(FLCO flco); void setFLCO(FLCO flco);
bool getOVCM() const;
void setOVCM(bool ovcm);
unsigned char getFID() const; unsigned char getFID() const;
void setFID(unsigned char fid); void setFID(unsigned char fid);

View file

@ -30,8 +30,8 @@ CThread(),
m_filename(filename), m_filename(filename),
m_reloadTime(reloadTime), m_reloadTime(reloadTime),
m_table(), m_table(),
m_mutex(), m_stop(false),
m_stop(false) m_reload(false)
{ {
} }
@ -41,7 +41,7 @@ CDMRLookup::~CDMRLookup()
bool CDMRLookup::read() bool CDMRLookup::read()
{ {
bool ret = load(); bool ret = m_table.load(m_filename);
if (m_reloadTime > 0U) if (m_reloadTime > 0U)
run(); run();
@ -49,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");
@ -60,9 +68,10 @@ void CDMRLookup::entry()
sleep(1000U); sleep(1000U);
timer.clock(); timer.clock();
if (timer.hasExpired()) { if (timer.hasExpired() || m_reload) {
load(); m_table.load(m_filename);
timer.start(); timer.start();
m_reload = false;
} }
} }
@ -81,118 +90,47 @@ void CDMRLookup::stop()
wait(); wait();
} }
std::string CDMRLookup::findWithName(unsigned int id) void CDMRLookup::findWithName(unsigned int id, class CUserDBentry *entry)
{ {
std::string callsign; if (id == 0xFFFFFFFU) {
entry->clear();
if (id == 0xFFFFFFU) entry->set(keyCALLSIGN, "ALL");
return std::string("ALL"); return;
m_mutex.lock();
try {
callsign = m_table.at(id);
LogDebug("FindWithName =%s",callsign.c_str());
} catch (...) {
char text[10U];
::sprintf(text, "%u", id);
callsign = std::string(text);
} }
m_mutex.unlock(); if (m_table.lookup(id, entry)) {
LogDebug("FindWithName =%s %s", entry->get(keyCALLSIGN).c_str(), entry->get(keyFIRST_NAME).c_str());
} else {
entry->clear();
return callsign; char text[10U];
::snprintf(text, sizeof(text), "%u", id);
entry->set(keyCALLSIGN, text);
}
return;
} }
std::string CDMRLookup::find(unsigned int id) std::string CDMRLookup::find(unsigned int id)
{ {
std::string callsign; std::string callsign;
std::string b;
if (id == 0xFFFFFFFU)
if (id == 0xFFFFFFU)
return std::string("ALL"); return std::string("ALL");
m_mutex.lock(); class CUserDBentry entry;
if (m_table.lookup(id, &entry)) {
try { callsign = entry.get(keyCALLSIGN);
b = m_table.at(id);
size_t n = b.find(" ");
if (n > 0) {
callsign = b.substr(0,n);
} else { } else {
LogDebug("b=%s",b.c_str());
callsign = b;
}
} catch (...) {
char text[10U]; char text[10U];
::sprintf(text, "%u", id); ::snprintf(text, sizeof(text), "%u", id);
callsign = std::string(text); callsign = std::string(text);
} }
m_mutex.unlock();
return callsign; return callsign;
} }
bool CDMRLookup::exists(unsigned int id) bool CDMRLookup::exists(unsigned int id)
{ {
m_mutex.lock(); return m_table.lookup(id, NULL);
bool found = m_table.count(id) == 1U;
m_mutex.unlock();
return found;
}
bool CDMRLookup::load()
{
FILE* fp = ::fopen(m_filename.c_str(), "rt");
if (fp == NULL) {
LogWarning("Cannot open the DMR Id lookup file - %s", m_filename.c_str());
return false;
}
m_mutex.lock();
// Remove the old entries
m_table.clear();
char buffer[100U];
while (::fgets(buffer, 100U, fp) != NULL) {
if (buffer[0U] == '#')
continue;
char* p1 = ::strtok(buffer, " \t\r\n");
char* p2 = ::strtok(NULL, " \r\n"); // tokenize to eol to capture name as well
if (p1 != NULL && p2 != NULL) {
unsigned int id = (unsigned int)::atoi(p1);
for (char* p = p2; *p != 0x00U; p++) {
if(*p == 0x09U)
*p = 0x20U;
else
*p = ::toupper(*p);
}
m_table[id] = std::string(p2);
}
}
m_mutex.unlock();
::fclose(fp);
size_t size = m_table.size();
if (size == 0U)
return false;
LogInfo("Loaded %u Ids to the DMR callsign lookup table", size);
return true;
} }

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
@ -20,10 +20,9 @@
#define DMRLookup_H #define DMRLookup_H
#include "Thread.h" #include "Thread.h"
#include "Mutex.h" #include "UserDB.h"
#include <string> #include <string>
#include <unordered_map>
class CDMRLookup : public CThread { class CDMRLookup : public CThread {
public: public:
@ -32,10 +31,12 @@ 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);
std::string findWithName(unsigned int id); void findWithName(unsigned int id, class CUserDBentry *entry);
bool exists(unsigned int id); bool exists(unsigned int id);
@ -44,11 +45,9 @@ public:
private: private:
std::string m_filename; std::string m_filename;
unsigned int m_reloadTime; unsigned int m_reloadTime;
std::unordered_map<unsigned int, std::string> m_table; class CUserDB m_table;
CMutex m_mutex;
bool m_stop; bool m_stop;
bool m_reload;
bool load();
}; };
#endif #endif

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2015-2019 by Jonathan Naylor G4KLX * Copyright (C) 2015-2020 by Jonathan Naylor G4KLX
* *
* This program is free software; you can redistribute it and/or modify * 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,659 +18,6 @@
#include "DMRNetwork.h" #include "DMRNetwork.h"
#include "StopWatch.h" IDMRNetwork::~IDMRNetwork()
#include "SHA256.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;
CDMRNetwork::CDMRNetwork(const std::string& address, unsigned int port, unsigned int local, unsigned int id, const std::string& password, bool duplex, const char* version, bool debug, bool slot1, bool slot2, HW_TYPE hwType) :
m_addressStr(address),
m_address(),
m_port(port),
m_id(NULL),
m_password(password),
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_status(WAITING_CONNECT),
m_retryTimer(1000U, 10U),
m_timeoutTimer(1000U, 60U),
m_buffer(NULL),
m_salt(NULL),
m_streamId(NULL),
m_rxData(1000U, "DMR Network"),
m_options(),
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_address = CUDPSocket::lookup(address);
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;
CStopWatch stopWatch;
::srand(stopWatch.start());
m_streamId[0U] = ::rand() + 1U;
m_streamId[1U] = ::rand() + 1U;
}
CDMRNetwork::~CDMRNetwork()
{
delete[] m_buffer;
delete[] m_salt;
delete[] m_streamId;
delete[] m_id;
}
void CDMRNetwork::setOptions(const std::string& options)
{
m_options = options;
}
void CDMRNetwork::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 CDMRNetwork::open()
{
LogMessage("DMR, Opening DMR Network");
if (m_address.s_addr == INADDR_NONE)
m_address = CUDPSocket::lookup(m_addressStr);
m_status = WAITING_CONNECT;
m_timeoutTimer.stop();
m_retryTimer.start();
return true;
}
void CDMRNetwork::enable(bool enabled)
{
if (!enabled && m_enabled)
m_rxData.clear();
m_enabled = enabled;
}
bool CDMRNetwork::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 CDMRNetwork::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;
unsigned int count = 1U;
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] = ::rand() + 1U;
count = 2U;
}
if (dataType == DT_CSBK || dataType == DT_DATA_HEADER) {
m_streamId[slotIndex] = ::rand() + 1U;
count = 1U;
}
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();
if (m_debug)
CUtils::dump(1U, "Network Transmitted", buffer, HOMEBREW_DATA_PACKET_LENGTH);
for (unsigned int i = 0U; i < count; i++)
write(buffer, HOMEBREW_DATA_PACKET_LENGTH);
return true;
}
bool CDMRNetwork::writeRadioPosition(unsigned int id, const unsigned char* data)
{
if (m_status != RUNNING)
return false;
unsigned char buffer[20U];
::memcpy(buffer + 0U, "DMRG", 4U);
::memcpy(buffer + 4U, m_id, 4U);
buffer[8U] = id >> 16;
buffer[9U] = id >> 8;
buffer[10U] = id >> 0;
::memcpy(buffer + 11U, data + 2U, 7U);
return write(buffer, 18U);
}
bool CDMRNetwork::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);
::memcpy(buffer + 4U, m_id, 4U);
buffer[8U] = id >> 16;
buffer[9U] = id >> 8;
buffer[10U] = id >> 0;
buffer[11U] = type;
::memcpy(buffer + 12U, data + 2U, 7U);
return write(buffer, 19U);
}
bool CDMRNetwork::writeHomePosition(float latitude, float longitude)
{
m_latitude = latitude;
m_longitude = longitude;
if (m_status != RUNNING)
return false;
char buffer[50U];
::memcpy(buffer + 0U, "RPTG", 4U);
::memcpy(buffer + 4U, m_id, 4U);
::sprintf(buffer + 8U, "%08f%09f", latitude, longitude);
return write((unsigned char*)buffer, 25U);
}
void CDMRNetwork::close()
{
LogMessage("DMR, Closing DMR Network");
if (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 CDMRNetwork::clock(unsigned int ms)
{
if (m_status == WAITING_CONNECT) {
m_retryTimer.clock(ms);
if (m_retryTimer.isRunning() && m_retryTimer.hasExpired()) {
bool ret = m_socket.open();
if (ret) {
ret = writeLogin();
if (!ret)
return;
m_status = WAITING_LOGIN;
m_timeoutTimer.start();
}
m_retryTimer.start();
}
return;
}
in_addr address;
unsigned int port;
int length = m_socket.read(m_buffer, BUFFER_LENGTH, address, port);
if (length < 0) {
LogError("DMR, Socket has failed, retrying connection to the master");
close();
open();
return;
}
// if (m_debug && length > 0)
// CUtils::dump(1U, "Network Received", m_buffer, length);
if (length > 0 && m_address.s_addr == address.s_addr && m_port == port) {
if (::memcmp(m_buffer, "DMRD", 4U) == 0) {
if (m_enabled) {
if (m_debug)
CUtils::dump(1U, "Network Received", m_buffer, length);
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();
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();
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("Unknown packet from the master", m_buffer, length);
}
}
m_retryTimer.clock(ms);
if (m_retryTimer.isRunning() && m_retryTimer.hasExpired()) {
switch (m_status) {
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();
}
m_timeoutTimer.clock(ms);
if (m_timeoutTimer.isRunning() && m_timeoutTimer.hasExpired()) {
LogError("DMR, Connection to the master has timed out, retrying connection");
close();
open();
}
}
bool CDMRNetwork::writeLogin()
{
unsigned char buffer[8U];
::memcpy(buffer + 0U, "RPTL", 4U);
::memcpy(buffer + 4U, m_id, 4U);
return write(buffer, 8U);
}
bool CDMRNetwork::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 CDMRNetwork::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 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_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 CDMRNetwork::writePing()
{
unsigned char buffer[11U];
::memcpy(buffer + 0U, "RPTPING", 7U);
::memcpy(buffer + 7U, m_id, 4U);
return write(buffer, 11U);
}
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_address, m_port);
if (!ret) {
LogError("DMR, Socket has failed when writing data to the master, retrying connection");
m_socket.close();
open();
return false;
}
return true;
} }

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2015,2016,2017,2018 by Jonathan Naylor G4KLX * Copyright (C) 2015,2016,2017,2018,2020,2021 by Jonathan Naylor G4KLX
* *
* This program is free software; you can redistribute it and/or modify * 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,101 +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>
class CDMRNetwork class IDMRNetwork
{ {
public: public:
CDMRNetwork(const std::string& address, unsigned int port, unsigned int local, unsigned int id, const std::string& password, bool duplex, const char* version, bool debug, bool slot1, bool slot2, HW_TYPE hwType); virtual ~IDMRNetwork() = 0;
~CDMRNetwork();
void setOptions(const std::string& options); virtual void setOptions(const std::string& options) = 0;
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 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;
bool open(); virtual bool open() = 0;
void enable(bool enabled); virtual void enable(bool enabled) = 0;
bool read(CDMRData& data); virtual bool read(CDMRData& data) = 0;
bool write(const CDMRData& data); virtual bool write(const CDMRData& data) = 0;
bool writeRadioPosition(unsigned int id, const unsigned char* data); virtual bool writeRadioPosition(unsigned int id, const unsigned char* data) = 0;
bool writeTalkerAlias(unsigned int id, unsigned char type, const unsigned char* data); virtual bool writeTalkerAlias(unsigned int id, unsigned char type, const unsigned char* data) = 0;
bool writeHomePosition(float latitude, float longitude); virtual bool wantsBeacon() = 0;
bool wantsBeacon(); virtual void clock(unsigned int ms) = 0;
void clock(unsigned int ms); virtual bool isConnected() const = 0;
void close(); virtual void close(bool sayGoodbye) = 0;
private: private:
std::string m_addressStr;
in_addr m_address;
unsigned int m_port;
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;
unsigned char* m_salt;
uint32_t* m_streamId;
CRingBuffer<unsigned char> m_rxData;
std::string m_options;
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 #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
@ -38,11 +38,12 @@ 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;
unsigned int CDMRSlot::m_hangCount = 3U * 17U; unsigned int CDMRSlot::m_hangCount = 3U * 17U;
DMR_OVCM_TYPES CDMRSlot::m_ovcm = DMR_OVCM_OFF;
CRSSIInterpolator* CDMRSlot::m_rssiMapper = NULL; CRSSIInterpolator* CDMRSlot::m_rssiMapper = NULL;
@ -141,10 +142,14 @@ bool CDMRSlot::writeModem(unsigned char *data, unsigned int len)
return false; return false;
if (data[0U] == TAG_LOST && m_rfState == RS_RF_AUDIO) { if (data[0U] == TAG_LOST && m_rfState == RS_RF_AUDIO) {
std::string src = m_lookup->find(m_rfLC->getSrcId());
std::string dst = m_lookup->find(m_rfLC->getDstId());
FLCO flco = m_rfLC->getFLCO();
if (m_rssi != 0U) if (m_rssi != 0U)
LogMessage("DMR Slot %u, RF voice transmission lost, %.1f seconds, BER: %.1f%%, RSSI: -%u/-%u/-%u dBm", m_slotNo, float(m_rfFrames) / 16.667F, float(m_rfErrs * 100U) / float(m_rfBits), m_minRSSI, m_maxRSSI, m_aveRSSI / m_rssiCount); LogMessage("DMR Slot %u, RF voice transmission lost from %s to %s%s, %.1f seconds, BER: %.1f%%, RSSI: -%u/-%u/-%u dBm", m_slotNo, src.c_str(), flco == FLCO_GROUP ? "TG " : "", dst.c_str(), float(m_rfFrames) / 16.667F, float(m_rfErrs * 100U) / float(m_rfBits), m_minRSSI, m_maxRSSI, m_aveRSSI / m_rssiCount);
else else
LogMessage("DMR Slot %u, RF voice transmission lost, %.1f seconds, BER: %.1f%%", m_slotNo, float(m_rfFrames) / 16.667F, float(m_rfErrs * 100U) / float(m_rfBits)); LogMessage("DMR Slot %u, RF voice transmission lost from %s to %s%s, %.1f seconds, BER: %.1f%%", m_slotNo, src.c_str(), flco == FLCO_GROUP ? "TG " : "", dst.c_str(), float(m_rfFrames) / 16.667F, float(m_rfErrs * 100U) / float(m_rfBits));
if (m_rfTimeout) { if (m_rfTimeout) {
writeEndRF(); writeEndRF();
return false; return false;
@ -155,7 +160,11 @@ bool CDMRSlot::writeModem(unsigned char *data, unsigned int len)
} }
if (data[0U] == TAG_LOST && m_rfState == RS_RF_DATA) { if (data[0U] == TAG_LOST && m_rfState == RS_RF_DATA) {
LogMessage("DMR Slot %u, RF data transmission lost", m_slotNo); std::string src = m_lookup->find(m_rfLC->getSrcId());
std::string dst = m_lookup->find(m_rfLC->getDstId());
FLCO flco = m_rfLC->getFLCO();
LogMessage("DMR Slot %u, RF data transmission lost from %s to %s%s", m_slotNo, src.c_str(), flco == FLCO_GROUP ? "TG " : "", dst.c_str());
writeEndRF(); writeEndRF();
return false; return false;
} }
@ -215,15 +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;
} }
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
@ -327,7 +343,6 @@ bool CDMRSlot::writeModem(unsigned char *data, unsigned int len)
data[0U] = TAG_EOT; data[0U] = TAG_EOT;
data[1U] = 0x00U; data[1U] = 0x00U;
writeNetworkRF(data, DT_TERMINATOR_WITH_LC);
writeNetworkRF(data, DT_TERMINATOR_WITH_LC); writeNetworkRF(data, DT_TERMINATOR_WITH_LC);
if (m_duplex) { if (m_duplex) {
@ -336,10 +351,14 @@ bool CDMRSlot::writeModem(unsigned char *data, unsigned int len)
} }
} }
std::string src = m_lookup->find(m_rfLC->getSrcId());
std::string dst = m_lookup->find(m_rfLC->getDstId());
FLCO flco = m_rfLC->getFLCO();
if (m_rssi != 0U) if (m_rssi != 0U)
LogMessage("DMR Slot %u, received RF end of voice transmission, %.1f seconds, BER: %.1f%%, RSSI: -%u/-%u/-%u dBm", m_slotNo, float(m_rfFrames) / 16.667F, float(m_rfErrs * 100U) / float(m_rfBits), m_minRSSI, m_maxRSSI, m_aveRSSI / m_rssiCount); LogMessage("DMR Slot %u, received RF end of voice transmission from %s to %s%s, %.1f seconds, BER: %.1f%%, RSSI: -%u/-%u/-%u dBm", m_slotNo, src.c_str(), flco == FLCO_GROUP ? "TG " : "", dst.c_str(), float(m_rfFrames) / 16.667F, float(m_rfErrs * 100U) / float(m_rfBits), m_minRSSI, m_maxRSSI, m_aveRSSI / m_rssiCount);
else else
LogMessage("DMR Slot %u, received RF end of voice transmission, %.1f seconds, BER: %.1f%%", m_slotNo, float(m_rfFrames) / 16.667F, float(m_rfErrs * 100U) / float(m_rfBits)); LogMessage("DMR Slot %u, received RF end of voice transmission from %s to %s%s, %.1f seconds, BER: %.1f%%", m_slotNo, src.c_str(), flco == FLCO_GROUP ? "TG " : "", dst.c_str(), float(m_rfFrames) / 16.667F, float(m_rfErrs * 100U) / float(m_rfBits));
m_display->writeDMRTA(m_slotNo, NULL, " "); m_display->writeDMRTA(m_slotNo, NULL, " ");
@ -365,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;
} }
@ -408,7 +429,7 @@ bool CDMRSlot::writeModem(unsigned char *data, unsigned int len)
LogMessage("DMR Slot %u, received RF data header from %s to %s%s, %u blocks", m_slotNo, src.c_str(), gi ? "TG ": "", dst.c_str(), m_rfFrames); LogMessage("DMR Slot %u, received RF data header from %s to %s%s, %u blocks", m_slotNo, src.c_str(), gi ? "TG ": "", dst.c_str(), m_rfFrames);
if (m_rfFrames == 0U) { if (m_rfFrames == 0U) {
LogMessage("DMR Slot %u, ended RF data transmission", m_slotNo); LogMessage("DMR Slot %u, ended RF data transmission from %s to %s%s", m_slotNo, src.c_str(), gi ? "TG " : "", dst.c_str());
writeEndRF(); writeEndRF();
} }
@ -423,6 +444,12 @@ bool CDMRSlot::writeModem(unsigned char *data, unsigned int len)
if (csbko == CSBKO_BSDWNACT) if (csbko == CSBKO_BSDWNACT)
return false; return false;
// set the OVCM bit for the supported csbk
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();
unsigned int dstId = csbk.getDstId(); unsigned int dstId = csbk.getDstId();
@ -430,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;
} }
} }
@ -472,6 +501,15 @@ bool CDMRSlot::writeModem(unsigned char *data, unsigned int len)
case CSBKO_PRECCSBK: case CSBKO_PRECCSBK:
LogMessage("DMR Slot %u, received RF %s Preamble CSBK (%u to follow) from %s to %s%s", m_slotNo, csbk.getDataContent() ? "Data" : "CSBK", csbk.getCBF(), src.c_str(), gi ? "TG ": "", dst.c_str()); LogMessage("DMR Slot %u, received RF %s Preamble CSBK (%u to follow) from %s to %s%s", m_slotNo, csbk.getDataContent() ? "Data" : "CSBK", csbk.getCBF(), src.c_str(), gi ? "TG ": "", dst.c_str());
break; break;
case CSBKO_CALL_ALERT:
LogMessage("DMR Slot %u, received RF Call Alert CSBK from %s to %s%s", m_slotNo, src.c_str(), gi ? "TG " : "", dst.c_str());
break;
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());
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;
@ -634,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) {
@ -653,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) {
@ -672,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) {
@ -691,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) {
@ -763,15 +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;
} }
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
@ -1027,6 +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);
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
@ -1084,7 +1134,8 @@ void CDMRSlot::writeNetwork(const CDMRData& dmrData)
setShortLC(m_slotNo, dstId, flco, ACTIVITY_VOICE); setShortLC(m_slotNo, dstId, flco, ACTIVITY_VOICE);
std::string src = m_lookup->find(srcId); std::string src = m_lookup->find(srcId);
std::string dst = m_lookup->find(dstId); std::string dst = m_lookup->find(dstId);
std::string cn = m_lookup->findWithName(srcId); class CUserDBentry cn;
m_lookup->findWithName(srcId, &cn);
m_display->writeDMR(m_slotNo, cn, flco == FLCO_GROUP, dst, "N"); m_display->writeDMR(m_slotNo, cn, flco == FLCO_GROUP, dst, "N");
#if defined(DUMP_DMR) #if defined(DUMP_DMR)
@ -1100,6 +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();
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;
@ -1150,11 +1206,12 @@ void CDMRSlot::writeNetwork(const CDMRData& dmrData)
m_netState = RS_NET_AUDIO; m_netState = RS_NET_AUDIO;
setShortLC(m_slotNo, dstId, m_netLC->getFLCO(), ACTIVITY_VOICE); setShortLC(m_slotNo, dstId, m_netLC->getFLCO(), ACTIVITY_VOICE);
std::string src = m_lookup->find(srcId); std::string src = m_lookup->find(srcId);
std::string dst = m_lookup->find(dstId); std::string dst = m_lookup->find(dstId);
class CUserDBentry cn;
m_lookup->findWithName(srcId, &cn);
m_display->writeDMR(m_slotNo, src, m_netLC->getFLCO() == FLCO_GROUP, dst, "N"); m_display->writeDMR(m_slotNo, cn, m_netLC->getFLCO() == FLCO_GROUP, dst, "N");
LogMessage("DMR Slot %u, received network late entry from %s to %s%s", m_slotNo, src.c_str(), m_netLC->getFLCO() == FLCO_GROUP ? "TG " : "", dst.c_str()); LogMessage("DMR Slot %u, received network late entry from %s to %s%s", m_slotNo, src.c_str(), m_netLC->getFLCO() == FLCO_GROUP ? "TG " : "", dst.c_str());
} }
@ -1216,9 +1273,13 @@ void CDMRSlot::writeNetwork(const CDMRData& dmrData)
writeFile(data); writeFile(data);
closeFile(); closeFile();
#endif #endif
std::string src = m_lookup->find(m_netLC->getSrcId());
std::string dst = m_lookup->find(m_netLC->getDstId());
FLCO flco = m_netLC->getFLCO();
// We've received the voice header and terminator haven't we? // We've received the voice header and terminator haven't we?
m_netFrames += 2U; m_netFrames += 2U;
LogMessage("DMR Slot %u, received network end of voice transmission, %.1f seconds, %u%% packet loss, BER: %.1f%%", m_slotNo, float(m_netFrames) / 16.667F, (m_netLost * 100U) / m_netFrames, float(m_netErrs * 100U) / float(m_netBits)); LogMessage("DMR Slot %u, received network end of voice transmission from %s to %s%s, %.1f seconds, %u%% packet loss, BER: %.1f%%", m_slotNo, src.c_str(), flco == FLCO_GROUP ? "TG " : "", dst.c_str(), float(m_netFrames) / 16.667F, (m_netLost * 100U) / m_netFrames, float(m_netErrs * 100U) / float(m_netBits));
m_display->writeDMRTA(m_slotNo, NULL, " "); m_display->writeDMRTA(m_slotNo, NULL, " ");
writeEndNet(); writeEndNet();
} else if (dataType == DT_DATA_HEADER) { } else if (dataType == DT_DATA_HEADER) {
@ -1271,7 +1332,7 @@ void CDMRSlot::writeNetwork(const CDMRData& dmrData)
LogMessage("DMR Slot %u, received network data header from %s to %s%s, %u blocks", m_slotNo, src.c_str(), gi ? "TG ": "", dst.c_str(), m_netFrames); LogMessage("DMR Slot %u, received network data header from %s to %s%s, %u blocks", m_slotNo, src.c_str(), gi ? "TG ": "", dst.c_str(), m_netFrames);
if (m_netFrames == 0U) { if (m_netFrames == 0U) {
LogMessage("DMR Slot %u, ended network data transmission", m_slotNo); LogMessage("DMR Slot %u, ended network data transmission from %s to %s%s", m_slotNo, src.c_str(), gi ? "TG " : "", dst.c_str());
writeEndNet(); writeEndNet();
} }
} else if (dataType == DT_VOICE_SYNC) { } else if (dataType == DT_VOICE_SYNC) {
@ -1281,6 +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();
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
@ -1343,8 +1409,10 @@ void CDMRSlot::writeNetwork(const CDMRData& dmrData)
std::string src = m_lookup->find(srcId); std::string src = m_lookup->find(srcId);
std::string dst = m_lookup->find(dstId); std::string dst = m_lookup->find(dstId);
class CUserDBentry cn;
m_lookup->findWithName(srcId, &cn);
m_display->writeDMR(m_slotNo, src, m_netLC->getFLCO() == FLCO_GROUP, dst, "N"); m_display->writeDMR(m_slotNo, cn, m_netLC->getFLCO() == FLCO_GROUP, dst, "N");
LogMessage("DMR Slot %u, received network late entry from %s to %s%s", m_slotNo, src.c_str(), m_netLC->getFLCO() == FLCO_GROUP ? "TG " : "", dst.c_str()); LogMessage("DMR Slot %u, received network late entry from %s to %s%s", m_slotNo, src.c_str(), m_netLC->getFLCO() == FLCO_GROUP ? "TG " : "", dst.c_str());
} }
@ -1549,6 +1617,12 @@ void CDMRSlot::writeNetwork(const CDMRData& dmrData)
if (csbko == CSBKO_BSDWNACT) if (csbko == CSBKO_BSDWNACT)
return; return;
// set the OVCM bit for the supported csbk
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();
unsigned int dstId = csbk.getDstId(); unsigned int dstId = csbk.getDstId();
@ -1613,6 +1687,15 @@ void CDMRSlot::writeNetwork(const CDMRData& dmrData)
case CSBKO_PRECCSBK: case CSBKO_PRECCSBK:
LogMessage("DMR Slot %u, received network %s Preamble CSBK (%u to follow) from %s to %s%s", m_slotNo, csbk.getDataContent() ? "Data" : "CSBK", csbk.getCBF(), src.c_str(), gi ? "TG " : "", dst.c_str()); LogMessage("DMR Slot %u, received network %s Preamble CSBK (%u to follow) from %s to %s%s", m_slotNo, csbk.getDataContent() ? "Data" : "CSBK", csbk.getCBF(), src.c_str(), gi ? "TG " : "", dst.c_str());
break; break;
case CSBKO_CALL_ALERT:
LogMessage("DMR Slot %u, received network Call Alert CSBK from %s to %s%s", m_slotNo, src.c_str(), gi ? "TG " : "", dst.c_str());
break;
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());
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;
@ -1853,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) 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);
@ -1869,6 +1952,7 @@ void CDMRSlot::init(unsigned int colorCode, bool embeddedLCOnly, bool dumpTAData
m_duplex = duplex; m_duplex = duplex;
m_lookup = lookup; m_lookup = lookup;
m_hangCount = callHang * 17U; m_hangCount = callHang * 17U;
m_ovcm = ovcm;
m_rssiMapper = rssiMapper; m_rssiMapper = rssiMapper;

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); 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,11 +118,12 @@ 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;
static unsigned int m_hangCount; static unsigned int m_hangCount;
static DMR_OVCM_TYPES m_ovcm;
static CRSSIInterpolator* m_rssiMapper; static CRSSIInterpolator* m_rssiMapper;

View file

@ -72,7 +72,7 @@ bool CDMRTA::decodeTA()
unsigned int TAformat = (talkerAlias[0] >> 6U) & 0x03U; unsigned int TAformat = (talkerAlias[0] >> 6U) & 0x03U;
unsigned int TAsize = (talkerAlias[0] >> 1U) & 0x1FU; unsigned int TAsize = (talkerAlias[0] >> 1U) & 0x1FU;
::strncpy(m_TA, "(could not decode)", sizeof(m_TA)); ::strcpy(m_TA, "(could not decode)");
switch (TAformat) { switch (TAformat) {
case 0U: // 7 bit case 0U: // 7 bit
@ -96,7 +96,7 @@ bool CDMRTA::decodeTA()
case 1U: // ISO 8 bit case 1U: // ISO 8 bit
case 2U: // UTF8 case 2U: // UTF8
::strncpy(m_TA, (char*)talkerAlias + 1U, sizeof(m_TA)); ::memcpy(m_TA, talkerAlias + 1U, sizeof(m_TA));
break; break;
case 3U: // UTF16 poor man's conversion case 3U: // UTF16 poor man's conversion
@ -117,9 +117,9 @@ bool CDMRTA::decodeTA()
if (TAlen > TAsize) { if (TAlen > TAsize) {
if (TAlen < 29U) if (TAlen < 29U)
strcat(m_TA," ?"); strcat(m_TA, " ?");
else else
strcpy(m_TA + 28U," ?"); strcpy(m_TA + 28U, " ?");
} }
return TAlen >= TAsize; return TAlen >= TAsize;

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,128 +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, 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;
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 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_KENWOOD_DATA_MODE_BYTES[] = { 0xEEU, 0xC2U, 0xA1U, 0xC8U, 0x42U, 0x6EU, 0x52U, 0x51U, 0xC3U };
const unsigned char DSTAR_ICOM_DATA_MODE_BYTES1[] = { 0xB2U, 0x4DU, 0x22U, 0x48U, 0xC0U, 0x16U, 0x28U, 0x26U, 0xC8U };
const unsigned char DSTAR_ICOM_DATA_MODE_BYTES2[] = { 0x70U, 0x4FU, 0x93U, 0x40U, 0x64U, 0x74U, 0x6DU, 0x30U, 0x2BU };
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_SQUELCH = 0xC0U;
const unsigned char DSTAR_SLOW_DATA_LENGTH_MASK = 0x0FU;
const unsigned char DSTAR_SCRAMBLER_BYTES[] = {0x70U, 0x4FU, 0x93U};
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,336 +0,0 @@
/*
* Copyright (C) 2009-2014,2016,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.
*/
#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_address(),
m_port(gatewayPort),
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_address = CUDPSocket::lookup(gatewayAddress);
m_linkReflector = new unsigned char[DSTAR_LONG_CALLSIGN_LENGTH];
CStopWatch stopWatch;
::srand(stopWatch.start());
}
CDStarNetwork::~CDStarNetwork()
{
delete[] m_linkReflector;
}
bool CDStarNetwork::open()
{
LogMessage("Opening D-Star network connection");
if (m_address.s_addr == INADDR_NONE)
return false;
m_pollTimer.start();
return m_socket.open();
}
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
m_outId = (::rand() % 65535U) + 1U;
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_address, m_port);
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_address, m_port);
}
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_address, m_port);
}
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];
in_addr address;
unsigned int port;
int length = m_socket.read(buffer, BUFFER_LENGTH, address, port);
if (length <= 0)
return;
// Check if the data is for us
if (m_address.s_addr != address.s_addr || m_port != port) {
LogMessage("D-Star packet received from an invalid source, %08X != %08X and/or %u != %u", m_address.s_addr, address.s_addr, m_port, port);
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,71 +0,0 @@
/*
* Copyright (C) 2009-2014,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 DStarNetwork_H
#define DStarNetwork_H
#include "DStarDefines.h"
#include "RingBuffer.h"
#include "UDPSocket.h"
#include "Timer.h"
#include <cstdint>
#include <string>
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;
in_addr m_address;
unsigned int m_port;
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;
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 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,12 +20,8 @@
#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_CW = 98U; const unsigned char MODE_CW = 98U;
const unsigned char MODE_LOCKOUT = 99U; const unsigned char MODE_LOCKOUT = 99U;
const unsigned char MODE_ERROR = 100U; const unsigned char MODE_ERROR = 100U;
@ -36,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,
@ -44,7 +42,10 @@ enum HW_TYPE {
HWT_MMDVM_HS_DUAL_HAT, HWT_MMDVM_HS_DUAL_HAT,
HWT_NANO_HOTSPOT, HWT_NANO_HOTSPOT,
HWT_NANO_DV, HWT_NANO_DV,
HWT_D2RG_MMDVM_HS,
HWT_MMDVM_HS, HWT_MMDVM_HS,
HWT_OPENGD77_HS,
HWT_SKYBRIDGE,
HWT_UNKNOWN HWT_UNKNOWN
}; };
@ -52,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
@ -60,7 +62,22 @@ 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
}; };
enum DMR_BEACONS {
DMR_BEACONS_OFF,
DMR_BEACONS_NETWORK,
DMR_BEACONS_TIMED
};
enum DMR_OVCM_TYPES {
DMR_OVCM_OFF,
DMR_OVCM_RX_ON,
DMR_OVCM_TX_ON,
DMR_OVCM_ON,
DMR_OVCM_FORCE_OFF
};
#endif #endif

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2016,2017,2018 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,15 +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 "LCDproc.h" #include "LCDproc.h"
#include "Nextion.h" #include "Nextion.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)
@ -99,42 +99,6 @@ void CDisplay::setQuit()
setQuitInt(); setQuitInt();
} }
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);
@ -149,6 +113,29 @@ void CDisplay::writeDMR(unsigned int slotNo, const std::string& src, bool group,
writeDMRInt(slotNo, src, group, dst, type); writeDMRInt(slotNo, src, group, dst, type);
} }
void CDisplay::writeDMR(unsigned int slotNo, const class CUserDBentry& src, bool group, const std::string& dst, const char* type)
{
assert(type != NULL);
if (slotNo == 1U) {
m_timer1.start();
m_mode1 = MODE_IDLE;
} else {
m_timer2.start();
m_mode2 = MODE_IDLE;
}
if (int err = writeDMRIntEx(slotNo, src, group, dst, type)) {
std::string src_str = src.get(keyCALLSIGN);
if (err < 0 && !src.get(keyFIRST_NAME).empty()) {
// emulate the result of old CDMRLookup::findWithName()
// (it returned callsign and firstname)
src_str += " " + src.get(keyFIRST_NAME);
}
writeDMRInt(slotNo, src_str, group, dst, type);
}
}
void CDisplay::writeDMRRSSI(unsigned int slotNo, unsigned char rssi) void CDisplay::writeDMRRSSI(unsigned int slotNo, unsigned char rssi)
{ {
if (rssi != 0U) if (rssi != 0U)
@ -165,6 +152,7 @@ void CDisplay::writeDMRBER(unsigned int slotNo, float ber)
{ {
writeDMRBERInt(slotNo, ber); writeDMRBERInt(slotNo, ber);
} }
void CDisplay::clearDMR(unsigned int slotNo) void CDisplay::clearDMR(unsigned int slotNo)
{ {
if (slotNo == 1U) { if (slotNo == 1U) {
@ -186,126 +174,6 @@ void CDisplay::clearDMR(unsigned int slotNo)
} }
} }
void CDisplay::writeFusion(const char* source, const char* dest, 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, 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::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::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();
@ -319,36 +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_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;
@ -376,12 +219,18 @@ void CDisplay::clockInt(unsigned int ms)
{ {
} }
void CDisplay::writeDStarRSSIInt(unsigned char rssi) int CDisplay::writeDMRIntEx(unsigned int slotNo, const class CUserDBentry& src, bool group, const std::string& dst, const char* type)
{
}
void CDisplay::writeDStarBERInt(float ber)
{ {
/*
* return value:
* < 0 error condition (i.e. not supported)
* -> call writeXXXXInt() to display
* = 0 no error, writeXXXXIntEx() displayed whole status
* = 1 no error, writeXXXXIntEx() displayed partial status
* -> call writeXXXXInt() to display remain part
* > 1 reserved for future use
*/
return -1; // not supported
} }
void CDisplay::writeDMRRSSIInt(unsigned int slotNo, unsigned char rssi) void CDisplay::writeDMRRSSIInt(unsigned int slotNo, unsigned char rssi)
@ -396,32 +245,9 @@ 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)
{
}
/* 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;
@ -431,7 +257,7 @@ CDisplay* CDisplay::createDisplay(const CConf& conf, CUMP* ump, CModem* modem)
LogInfo("Display Parameters"); LogInfo("Display Parameters");
LogInfo(" Type: %s", type.c_str()); LogInfo(" Type: %s", type.c_str());
if (type == "TFT Serial") { if (type == "TFT Surenoo") {
std::string port = conf.getTFTSerialPort(); std::string port = conf.getTFTSerialPort();
unsigned int brightness = conf.getTFTSerialBrightness(); unsigned int brightness = conf.getTFTSerialBrightness();
@ -440,11 +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, SERIAL_9600); serial = new CUARTController(port, 115200U);
display = new CTFTSerial(conf.getCallsign(), dmrid, serial, brightness); display = new CTFTSurenoo(conf.getCallsign(), dmrid, serial, brightness, conf.getDuplex());
} 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();
@ -483,23 +309,16 @@ 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, conf.getLocation()); 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, conf.getLocation());
} else { } else {
LogInfo(" NullDisplay loaded"); unsigned int baudrate = 9600U;
display = new CNullDisplay; if (screenLayout == 4U)
} baudrate = 115200U;
} else {
SERIAL_SPEED baudrate = SERIAL_9600;
if (screenLayout==4U)
baudrate = SERIAL_115200;
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, conf.getLocation()); display = new CNextion(conf.getCallsign(), dmrid, serial, brightness, displayClock, utc, idleBrightness, screenLayout, txFrequency, rxFrequency, displayTempInF);
} }
} else if (type == "LCDproc") { } else if (type == "LCDproc") {
std::string address = conf.getLCDprocAddress(); std::string address = conf.getLCDprocAddress();
@ -568,10 +387,12 @@ CDisplay* CDisplay::createDisplay(const CConf& conf, CUMP* ump, CModem* modem)
bool invert = conf.getOLEDInvert(); bool invert = conf.getOLEDInvert();
bool scroll = conf.getOLEDScroll(); bool scroll = conf.getOLEDScroll();
bool rotate = conf.getOLEDRotate(); bool rotate = conf.getOLEDRotate();
bool cast = conf.getOLEDCast(); bool logosaver = conf.getOLEDLogoScreensaver();
display = new COLED(type, brightness, invert, scroll, rotate, conf.getDMRNetworkSlot1(), conf.getDMRNetworkSlot2(), cast ? modem : NULL); display = new COLED(type, brightness, invert, scroll, rotate, logosaver, conf.getDuplex());
#endif #endif
} else if (type == "CAST") {
display = new CCASTInfo(modem);
} else { } else {
LogWarning("No valid display found, disabling"); LogWarning("No valid display found, disabling");
display = new CNullDisplay; display = new CNullDisplay;

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2016,2017,2018 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
@ -20,6 +20,8 @@
#define DISPLAY_H #define DISPLAY_H
#include "Timer.h" #include "Timer.h"
#include "UserDBentry.h"
#include "Modem.h"
#include <string> #include <string>
@ -27,7 +29,6 @@
class CConf; class CConf;
class CModem; class CModem;
class CUMP;
class CDisplay class CDisplay
{ {
@ -41,43 +42,22 @@ public:
void setLockout(); void setLockout();
void setError(const char* text); void setError(const char* text);
void setQuit(); void setQuit();
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 writeDMRRSSI(unsigned int slotNo, unsigned char rssi); void writeDMRRSSI(unsigned int slotNo, unsigned char rssi);
void writeDMRBER(unsigned int slotNo, float ber); void writeDMRBER(unsigned int slotNo, float ber);
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, 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 writeNXDNRSSI(unsigned char rssi);
void writeNXDNBER(float ber);
void clearNXDN();
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;
@ -85,35 +65,13 @@ protected:
virtual void setErrorInt(const char* text) = 0; virtual void setErrorInt(const char* text) = 0;
virtual void setQuitInt() = 0; virtual void setQuitInt() = 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 void writeDMRRSSIInt(unsigned int slotNo, unsigned char rssi); virtual void writeDMRRSSIInt(unsigned int slotNo, unsigned char rssi);
virtual void writeDMRTAInt(unsigned int slotNo, unsigned char* talkerAlias, const char* type); virtual void writeDMRTAInt(unsigned int slotNo, unsigned char* talkerAlias, const char* type);
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, 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 void writeNXDNRSSIInt(unsigned char rssi);
virtual void writeNXDNBERInt(float ber);
virtual void clearNXDNInt() = 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 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(),
@ -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;
@ -399,6 +400,37 @@ void CHD44780::setQuitInt()
m_dmr = false; m_dmr = false;
} }
void CHD44780::setFMInt()
{
m_clockDisplayTimer.stop();
::lcdClear(m_fd);
#ifdef ADAFRUIT_DISPLAY
adafruitLCDColour(AC_WHITE);
#endif
if (m_pwm) {
if (m_pwmPin != 1U)
::softPwmWrite(m_pwmPin, m_pwmDim);
else
::pwmWrite(m_pwmPin, (m_pwmDim / 100) * 1024);
}
// Print callsign and ID at on top row for all screen sizes
::lcdPosition(m_fd, 0, 0);
::lcdPrintf(m_fd, "%-6s", m_callsign.c_str());
::lcdPosition(m_fd, m_cols - 7, 0);
::lcdPrintf(m_fd, "%7u", m_dmrid);
// Print MMDVM and Idle on bottom row for all screen sizes
::lcdPosition(m_fd, 0, m_rows - 1);
::lcdPuts(m_fd, "MMDVM");
::lcdPosition(m_fd, m_cols - 4, m_rows - 1);
::lcdPuts(m_fd, "FM"); // Gets overwritten by clock on 2 line screen
m_dmr = false;
}
void CHD44780::writeDStarInt(const char* my1, const char* my2, const char* your, const char* type, const char* reflector) void CHD44780::writeDStarInt(const char* my1, const char* my2, const char* your, const char* type, const char* reflector)
{ {
assert(my1 != NULL); assert(my1 != NULL);
@ -432,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);
@ -568,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);
@ -591,18 +621,16 @@ 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) {
::lcdPosition(m_fd, 0, (m_rows / 2) - 2); ::lcdPosition(m_fd, 0, (m_rows / 2) - 2);
@ -616,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);
@ -628,12 +655,12 @@ 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;
@ -691,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);
@ -706,7 +732,7 @@ void CHD44780::clearDMRInt(unsigned int slotNo)
} }
} }
void CHD44780::writeFusionInt(const char* source, const char* dest, const char* type, const char* origin) void CHD44780::writeFusionInt(const char* source, const char* dest, unsigned char dgid, const char* type, const char* origin)
{ {
assert(source != NULL); assert(source != NULL);
assert(dest != NULL); assert(dest != NULL);
@ -731,31 +757,27 @@ void CHD44780::writeFusionInt(const char* source, const char* dest, const char*
::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);
::sprintf(m_buffer1, "%.10s", dest); ::sprintf(m_buffer1, "DG-ID %u", dgid);
::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);
::sprintf(m_buffer1, "%.10s", dest); ::sprintf(m_buffer1, "DG-ID %u", dgid);
::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 > %.10s", source, 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);
@ -782,7 +804,6 @@ void CHD44780::clearFusionInt()
#ifdef ADAFRUIT_DISPLAY #ifdef ADAFRUIT_DISPLAY
adafruitLCDColour(AC_PURPLE); adafruitLCDColour(AC_PURPLE);
#endif #endif
m_clockDisplayTimer.stop(); // Stop the clock display m_clockDisplayTimer.stop(); // Stop the clock display
if (m_rows == 2U && m_cols == 16U) { if (m_rows == 2U && m_cols == 16U) {
@ -835,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);
@ -849,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);
@ -858,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);
@ -939,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);
@ -953,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);
@ -962,9 +976,7 @@ 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);
} }
@ -1020,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()
@ -1052,17 +1163,16 @@ void CHD44780::clockInt(unsigned int ms)
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);

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2016,2017,2018 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
@ -101,6 +101,7 @@ 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 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);
@ -110,7 +111,7 @@ protected:
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, 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();
@ -122,6 +123,10 @@ protected:
virtual void writeNXDNRSSIInt(unsigned char rssi); virtual void writeNXDNRSSIInt(unsigned char rssi);
virtual void clearNXDNInt(); virtual void clearNXDNInt();
virtual void writeM17Int(const char* source, const char* dest, const char* type);
virtual void writeM17RSSIInt(unsigned char rssi);
virtual void clearM17Int();
virtual void writePOCSAGInt(uint32_t ric, const std::string& message); virtual void writePOCSAGInt(uint32_t ric, const std::string& message);
virtual void clearPOCSAGInt(); virtual void clearPOCSAGInt();

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(__APPLE__)
#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(__APPLE__)
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 does not support OSX"
#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(__APPLE__)
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(__APPLE__)
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) 2015,2016 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,30 +17,34 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/ */
#if !defined(YSFConvolution_H) #if !defined(IIRDIRECTFORM1FILTER_H)
#define YSFConvolution_H #define IIRDIRECTFORM1FILTER_H
#include <cstdint> class CIIRDirectForm1Filter
{
class CYSFConvolution {
public: public:
CYSFConvolution(); CIIRDirectForm1Filter(float b0, float b1, float b2, float, float a1, float a2, float additionalGaindB);
~CYSFConvolution(); float filter(float sample);
void reset();
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: private:
uint16_t* m_metrics1; // delay line
uint16_t* m_metrics2; float m_x2; // x[n-2]
uint16_t* m_oldMetrics; float m_y2; // y[n-2]
uint16_t* m_newMetrics; float m_x1; // x[n-1]
uint64_t* m_decisions; float m_y1; // y[n-1]
uint64_t* m_dp;
// 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.

BIN
Images/M17.bmp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 57 KiB

View file

@ -1,6 +1,6 @@
/* /*
* Copyright (C) 2016,2017,2018 by Tony Corbett G0WFV * Copyright (C) 2016,2017,2018 by Tony Corbett G0WFV
* Copyright (C) 2018 by Jonathan Naylor G4KLX * Copyright (C) 2018,2020 by Jonathan Naylor G4KLX
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@ -72,7 +72,7 @@
#include <unistd.h> #include <unistd.h>
#include <stdarg.h> #include <stdarg.h>
#else #else
#include <winsock.h> #include <ws2tcpip.h>
#endif #endif
#define BUFFER_MAX_LEN 128 #define BUFFER_MAX_LEN 128
@ -95,8 +95,9 @@ 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
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),
@ -121,44 +122,53 @@ CLCDproc::~CLCDproc()
bool CLCDproc::open() bool CLCDproc::open()
{ {
const char *server; int err;
unsigned int port, localPort; unsigned int addrlen;
struct sockaddr_in serverAddress, clientAddress; std::string port, localPort;
struct hostent *h; struct sockaddr_storage serverAddress, clientAddress;
struct addrinfo hints, *res;
server = m_address.c_str(); port = std::to_string(m_port);
port = m_port; localPort = std::to_string(m_localPort);
localPort = m_localPort; memset(&hints, 0, sizeof(hints));
/* Lookup the hostname address */
hints.ai_flags = AI_NUMERICSERV;
hints.ai_socktype = SOCK_STREAM;
err = getaddrinfo(m_address.c_str(), port.c_str(), &hints, &res);
if (err) {
LogError("LCDproc, cannot lookup server");
return false;
}
memcpy(&serverAddress, res->ai_addr, addrlen = res->ai_addrlen);
freeaddrinfo(res);
/* Lookup the client address (random port - need to specify manual port from ini file) */
hints.ai_flags = AI_NUMERICSERV | AI_PASSIVE;
hints.ai_family = serverAddress.ss_family;
err = getaddrinfo(NULL, localPort.c_str(), &hints, &res);
if (err) {
LogError("LCDproc, cannot lookup client");
return false;
}
memcpy(&clientAddress, res->ai_addr, res->ai_addrlen);
freeaddrinfo(res);
/* Create TCP socket */ /* Create TCP socket */
m_socketfd = socket(AF_INET, SOCK_STREAM, 0); m_socketfd = socket(clientAddress.ss_family, SOCK_STREAM, 0);
if (m_socketfd == -1) { if (m_socketfd == -1) {
LogError("LCDproc, failed to create socket"); LogError("LCDproc, failed to create socket");
return false; return false;
} }
/* Sets client address (random port - need to specify manual port from ini file?) */
clientAddress.sin_family = AF_INET;
clientAddress.sin_addr.s_addr = htonl(INADDR_ANY);
//clientAddress.sin_port = htons(0);
clientAddress.sin_port = htons(localPort);
/* Bind the address to the socket */ /* Bind the address to the socket */
if (bind(m_socketfd, (struct sockaddr *)&clientAddress, sizeof(clientAddress)) == -1) { if (bind(m_socketfd, (struct sockaddr *)&clientAddress, addrlen) == -1) {
LogError("LCDproc, error whilst binding address"); LogError("LCDproc, error whilst binding address");
return false; return false;
} }
/* Lookup the hostname address */ /* Connect to server */
h = gethostbyname(server); if (connect(m_socketfd, (struct sockaddr *)&serverAddress, addrlen) == -1) {
/* Sets server address */
serverAddress.sin_family = h->h_addrtype;
memcpy((char*)&serverAddress.sin_addr.s_addr, h->h_addr_list[0], h->h_length);
serverAddress.sin_port = htons(port);
if (connect(m_socketfd, (struct sockaddr * )&serverAddress, sizeof(serverAddress))==-1) {
LogError("LCDproc, cannot connect to server"); LogError("LCDproc, cannot connect to server");
return false; return false;
} }
@ -179,6 +189,7 @@ void CLCDproc::setIdleInt()
socketPrintf(m_socketfd, "screen_set YSF -priority hidden"); socketPrintf(m_socketfd, "screen_set YSF -priority hidden");
socketPrintf(m_socketfd, "screen_set P25 -priority hidden"); socketPrintf(m_socketfd, "screen_set P25 -priority hidden");
socketPrintf(m_socketfd, "screen_set NXDN -priority hidden"); socketPrintf(m_socketfd, "screen_set NXDN -priority hidden");
socketPrintf(m_socketfd, "screen_set M17 -priority hidden");
socketPrintf(m_socketfd, "widget_set Status Status %u %u Idle", m_cols - 3, m_rows); socketPrintf(m_socketfd, "widget_set Status Status %u %u Idle", m_cols - 3, m_rows);
socketPrintf(m_socketfd, "output 0"); // Clear all LEDs socketPrintf(m_socketfd, "output 0"); // Clear all LEDs
} }
@ -198,6 +209,7 @@ void CLCDproc::setErrorInt(const char* text)
socketPrintf(m_socketfd, "screen_set YSF -priority hidden"); socketPrintf(m_socketfd, "screen_set YSF -priority hidden");
socketPrintf(m_socketfd, "screen_set P25 -priority hidden"); socketPrintf(m_socketfd, "screen_set P25 -priority hidden");
socketPrintf(m_socketfd, "screen_set NXDN -priority hidden"); socketPrintf(m_socketfd, "screen_set NXDN -priority hidden");
socketPrintf(m_socketfd, "screen_set M17 -priority hidden");
socketPrintf(m_socketfd, "widget_set Status Status %u %u Error", m_cols - 4, m_rows); socketPrintf(m_socketfd, "widget_set Status Status %u %u Error", m_cols - 4, m_rows);
socketPrintf(m_socketfd, "output 0"); // Clear all LEDs socketPrintf(m_socketfd, "output 0"); // Clear all LEDs
} }
@ -215,6 +227,7 @@ void CLCDproc::setLockoutInt()
socketPrintf(m_socketfd, "screen_set YSF -priority hidden"); socketPrintf(m_socketfd, "screen_set YSF -priority hidden");
socketPrintf(m_socketfd, "screen_set P25 -priority hidden"); socketPrintf(m_socketfd, "screen_set P25 -priority hidden");
socketPrintf(m_socketfd, "screen_set NXDN -priority hidden"); socketPrintf(m_socketfd, "screen_set NXDN -priority hidden");
socketPrintf(m_socketfd, "screen_set M17 -priority hidden");
socketPrintf(m_socketfd, "widget_set Status Status %u %u Lockout", m_cols - 6, m_rows); socketPrintf(m_socketfd, "widget_set Status Status %u %u Lockout", m_cols - 6, m_rows);
socketPrintf(m_socketfd, "output 0"); // Clear all LEDs socketPrintf(m_socketfd, "output 0"); // Clear all LEDs
} }
@ -234,6 +247,7 @@ void CLCDproc::setQuitInt()
socketPrintf(m_socketfd, "screen_set YSF -priority hidden"); socketPrintf(m_socketfd, "screen_set YSF -priority hidden");
socketPrintf(m_socketfd, "screen_set P25 -priority hidden"); socketPrintf(m_socketfd, "screen_set P25 -priority hidden");
socketPrintf(m_socketfd, "screen_set NXDN -priority hidden"); socketPrintf(m_socketfd, "screen_set NXDN -priority hidden");
socketPrintf(m_socketfd, "screen_set M17 -priority hidden");
socketPrintf(m_socketfd, "widget_set Status Status %u %u Stopped", m_cols - 6, m_rows); socketPrintf(m_socketfd, "widget_set Status Status %u %u Stopped", m_cols - 6, m_rows);
socketPrintf(m_socketfd, "output 0"); // Clear all LEDs socketPrintf(m_socketfd, "output 0"); // Clear all LEDs
} }
@ -241,6 +255,24 @@ void CLCDproc::setQuitInt()
m_dmr = false; m_dmr = false;
} }
void CLCDproc::setFMInt()
{
m_clockDisplayTimer.stop(); // Stop the clock display
if (m_screensDefined) {
socketPrintf(m_socketfd, "screen_set DStar -priority hidden");
socketPrintf(m_socketfd, "screen_set DMR -priority hidden");
socketPrintf(m_socketfd, "screen_set YSF -priority hidden");
socketPrintf(m_socketfd, "screen_set P25 -priority hidden");
socketPrintf(m_socketfd, "screen_set NXDN -priority hidden");
socketPrintf(m_socketfd, "screen_set M17 -priority hidden");
socketPrintf(m_socketfd, "widget_set Status Status %u %u FM", m_cols - 6, m_rows);
socketPrintf(m_socketfd, "output 0"); // Clear all LEDs
}
m_dmr = false;
}
void CLCDproc::writeDStarInt(const char* my1, const char* my2, const char* your, const char* type, const char* reflector) void CLCDproc::writeDStarInt(const char* my1, const char* my2, const char* your, const char* type, const char* reflector)
{ {
assert(my1 != NULL); assert(my1 != NULL);
@ -294,7 +326,7 @@ void CLCDproc::clearDStarInt()
{ {
m_clockDisplayTimer.stop(); // Stop the clock display m_clockDisplayTimer.stop(); // Stop the clock display
socketPrintf(m_socketfd, "widget_set DStar Line2 1 2 15 2 h 3 Listening"); socketPrintf(m_socketfd, "widget_set DStar Line2 1 2 15 2 h 3 \"Listening\"");
socketPrintf(m_socketfd, "widget_set DStar Line3 1 3 15 3 h 3 \"\""); socketPrintf(m_socketfd, "widget_set DStar Line3 1 3 15 3 h 3 \"\"");
socketPrintf(m_socketfd, "widget_set DStar Line4 1 4 15 4 h 3 \"\""); socketPrintf(m_socketfd, "widget_set DStar Line4 1 4 15 4 h 3 \"\"");
socketPrintf(m_socketfd, "output 8"); // Set LED4 color green socketPrintf(m_socketfd, "output 8"); // Set LED4 color green
@ -387,7 +419,7 @@ void CLCDproc::clearDMRInt(unsigned int slotNo)
socketPrintf(m_socketfd, "widget_set DMR Slot2RSSI %u %u %*.s", (m_cols / 2) + 1, 4, m_cols / 2, " "); socketPrintf(m_socketfd, "widget_set DMR Slot2RSSI %u %u %*.s", (m_cols / 2) + 1, 4, m_cols / 2, " ");
} }
} else { } else {
socketPrintf(m_socketfd, "widget_set DMR Slot1 1 2 15 2 h 3 Listening"); socketPrintf(m_socketfd, "widget_set DMR Slot1 1 2 15 2 h 3 \"Listening\"");
socketPrintf(m_socketfd, "widget_set DMR Slot2 1 3 15 3 h 3 \"\""); socketPrintf(m_socketfd, "widget_set DMR Slot2 1 3 15 3 h 3 \"\"");
socketPrintf(m_socketfd, "widget_set DMR Slot2RSSI %u %u %*.s", (m_cols / 2) + 1, 4, m_cols / 2, " "); socketPrintf(m_socketfd, "widget_set DMR Slot2RSSI %u %u %*.s", (m_cols / 2) + 1, 4, m_cols / 2, " ");
} }
@ -396,7 +428,7 @@ void CLCDproc::clearDMRInt(unsigned int slotNo)
// LED 3 Green 4 Red 64 Yellow 68 // LED 3 Green 4 Red 64 Yellow 68
void CLCDproc::writeFusionInt(const char* source, const char* dest, const char* type, const char* origin) void CLCDproc::writeFusionInt(const char* source, const char* dest, unsigned char dgid, const char* type, const char* origin)
{ {
assert(source != NULL); assert(source != NULL);
assert(dest != NULL); assert(dest != NULL);
@ -409,10 +441,10 @@ void CLCDproc::writeFusionInt(const char* source, const char* dest, const char*
socketPrintf(m_socketfd, "widget_set YSF Mode 1 1 \"System Fusion\""); socketPrintf(m_socketfd, "widget_set YSF Mode 1 1 \"System Fusion\"");
if (m_rows == 2U) { if (m_rows == 2U) {
socketPrintf(m_socketfd, "widget_set YSF Line2 1 2 15 2 h 3 \"%.10s > %s%u\"", source, dest); socketPrintf(m_socketfd, "widget_set YSF Line2 1 2 15 2 h 3 \"%.10s > DG-ID %u\"", source, dgid);
} else { } else {
socketPrintf(m_socketfd, "widget_set YSF Line2 1 2 15 2 h 3 \"%.10s >\"", source); socketPrintf(m_socketfd, "widget_set YSF Line2 1 2 15 2 h 3 \"%.10s >\"", source);
socketPrintf(m_socketfd, "widget_set YSF Line3 1 3 15 3 h 3 \"%s%u\"", dest); socketPrintf(m_socketfd, "widget_set YSF Line3 1 3 15 3 h 3 \"DG-ID %u\"", dgid);
socketPrintf(m_socketfd, "output 64"); // Set LED3 color red socketPrintf(m_socketfd, "output 64"); // Set LED3 color red
} }
@ -422,9 +454,8 @@ void CLCDproc::writeFusionInt(const char* source, const char* dest, const char*
void CLCDproc::writeFusionRSSIInt(unsigned char rssi) void CLCDproc::writeFusionRSSIInt(unsigned char rssi)
{ {
if (m_rssiCount1 == 0U) { if (m_rssiCount1 == 0U)
socketPrintf(m_socketfd, "widget_set YSF Line4 1 4 %u 4 h 3 \"-%3udBm\"", m_cols - 1, rssi); socketPrintf(m_socketfd, "widget_set YSF Line4 1 4 %u 4 h 3 \"-%3udBm\"", m_cols - 1, rssi);
}
m_rssiCount1++; m_rssiCount1++;
if (m_rssiCount1 >= YSF_RSSI_COUNT) if (m_rssiCount1 >= YSF_RSSI_COUNT)
@ -435,7 +466,7 @@ void CLCDproc::clearFusionInt()
{ {
m_clockDisplayTimer.stop(); // Stop the clock display m_clockDisplayTimer.stop(); // Stop the clock display
socketPrintf(m_socketfd, "widget_set YSF Line2 1 2 15 2 h 3 Listening"); socketPrintf(m_socketfd, "widget_set YSF Line2 1 2 15 2 h 3 \"Listening\"");
socketPrintf(m_socketfd, "widget_set YSF Line3 1 3 15 3 h 3 \"\""); socketPrintf(m_socketfd, "widget_set YSF Line3 1 3 15 3 h 3 \"\"");
socketPrintf(m_socketfd, "widget_set YSF Line4 1 4 15 4 h 3 \"\""); socketPrintf(m_socketfd, "widget_set YSF Line4 1 4 15 4 h 3 \"\"");
socketPrintf(m_socketfd, "output 4"); // Set LED3 color green socketPrintf(m_socketfd, "output 4"); // Set LED3 color green
@ -480,7 +511,7 @@ void CLCDproc::clearP25Int()
{ {
m_clockDisplayTimer.stop(); // Stop the clock display m_clockDisplayTimer.stop(); // Stop the clock display
socketPrintf(m_socketfd, "widget_set P25 Line2 1 2 15 2 h 3 Listening"); socketPrintf(m_socketfd, "widget_set P25 Line2 1 2 15 2 h 3 \"Listening\"");
socketPrintf(m_socketfd, "widget_set P25 Line3 1 3 15 3 h 3 \"\""); socketPrintf(m_socketfd, "widget_set P25 Line3 1 3 15 3 h 3 \"\"");
socketPrintf(m_socketfd, "widget_set P25 Line4 1 4 15 4 h 3 \"\""); socketPrintf(m_socketfd, "widget_set P25 Line4 1 4 15 4 h 3 \"\"");
socketPrintf(m_socketfd, "output 2"); // Set LED2 color green socketPrintf(m_socketfd, "output 2"); // Set LED2 color green
@ -525,12 +556,57 @@ void CLCDproc::clearNXDNInt()
{ {
m_clockDisplayTimer.stop(); // Stop the clock display m_clockDisplayTimer.stop(); // Stop the clock display
socketPrintf(m_socketfd, "widget_set NXDN Line2 1 2 15 2 h 3 Listening"); socketPrintf(m_socketfd, "widget_set NXDN Line2 1 2 15 2 h 3 \"Listening\"");
socketPrintf(m_socketfd, "widget_set NXDN Line3 1 3 15 3 h 3 \"\""); socketPrintf(m_socketfd, "widget_set NXDN Line3 1 3 15 3 h 3 \"\"");
socketPrintf(m_socketfd, "widget_set NXDN Line4 1 4 15 4 h 3 \"\""); socketPrintf(m_socketfd, "widget_set NXDN Line4 1 4 15 4 h 3 \"\"");
socketPrintf(m_socketfd, "output 16"); // Set LED5 color green socketPrintf(m_socketfd, "output 16"); // Set LED5 color green
} }
void CLCDproc::writeM17Int(const char* source, const char* dest, const char* type)
{
assert(source != NULL);
assert(dest != NULL);
assert(type != NULL);
m_clockDisplayTimer.stop(); // Stop the clock display
socketPrintf(m_socketfd, "screen_set M17 -priority foreground");
socketPrintf(m_socketfd, "widget_set M17 Mode 1 1 M17");
if (m_rows == 2U) {
socketPrintf(m_socketfd, "widget_set M17 Line2 1 2 15 2 h 3 \"%.9s > %.9s\"", source, dest);
}
else {
socketPrintf(m_socketfd, "widget_set M17 Line2 1 2 15 2 h 3 \"%.9s >\"", source);
socketPrintf(m_socketfd, "widget_set M17 Line3 1 3 15 3 h 3 \"%.9ss\"", dest);
socketPrintf(m_socketfd, "output 255"); // Set LED5 color red
}
m_dmr = false;
m_rssiCount1 = 0U;
}
void CLCDproc::writeM17RSSIInt(unsigned char rssi)
{
if (m_rssiCount1 == 0U) {
socketPrintf(m_socketfd, "widget_set M17 Line4 1 4 %u 4 h 3 \"-%3udBm\"", m_cols - 1, rssi);
}
m_rssiCount1++;
if (m_rssiCount1 >= M17_RSSI_COUNT)
m_rssiCount1 = 0U;
}
void CLCDproc::clearM17Int()
{
m_clockDisplayTimer.stop(); // Stop the clock display
socketPrintf(m_socketfd, "widget_set M17 Line2 1 2 15 2 h 3 \"Listening\"");
socketPrintf(m_socketfd, "widget_set M17 Line3 1 3 15 3 h 3 \"\"");
socketPrintf(m_socketfd, "widget_set M17 Line4 1 4 15 4 h 3 \"\"");
socketPrintf(m_socketfd, "output 16"); // Set LED5 color green
}
void CLCDproc::writePOCSAGInt(uint32_t ric, const std::string& message) void CLCDproc::writePOCSAGInt(uint32_t ric, const std::string& message)
{ {
} }
@ -752,7 +828,7 @@ void CLCDproc::defineScreens()
socketPrintf(m_socketfd, "widget_add DStar Line4 scroller"); socketPrintf(m_socketfd, "widget_add DStar Line4 scroller");
/* Do we need to pre-populate the values?? /* Do we need to pre-populate the values??
socketPrintf(m_socketfd, "widget_set DStar Line2 1 2 15 2 h 3 Listening"); socketPrintf(m_socketfd, "widget_set DStar Line2 1 2 15 2 h 3 \"Listening\"");
socketPrintf(m_socketfd, "widget_set DStar Line3 1 3 15 3 h 3 \"\""); socketPrintf(m_socketfd, "widget_set DStar Line3 1 3 15 3 h 3 \"\"");
socketPrintf(m_socketfd, "widget_set DStar Line4 1 4 15 4 h 3 \"\""); socketPrintf(m_socketfd, "widget_set DStar Line4 1 4 15 4 h 3 \"\"");
*/ */
@ -773,8 +849,8 @@ void CLCDproc::defineScreens()
/* Do we need to pre-populate the values?? /* Do we need to pre-populate the values??
socketPrintf(m_socketfd, "widget_set DMR Slot1_ 1 %u 1", m_rows / 2); socketPrintf(m_socketfd, "widget_set DMR Slot1_ 1 %u 1", m_rows / 2);
socketPrintf(m_socketfd, "widget_set DMR Slot2_ 1 %u 2", m_rows / 2 + 1); socketPrintf(m_socketfd, "widget_set DMR Slot2_ 1 %u 2", m_rows / 2 + 1);
socketPrintf(m_socketfd, "widget_set DMR Slot1 3 1 15 1 h 3 Listening"); socketPrintf(m_socketfd, "widget_set DMR Slot1 3 1 15 1 h 3 \"Listening\"");
socketPrintf(m_socketfd, "widget_set DMR Slot2 3 2 15 2 h 3 Listening"); socketPrintf(m_socketfd, "widget_set DMR Slot2 3 2 15 2 h 3 \"Listening\"");
*/ */
// The YSF Screen // The YSF Screen
@ -788,7 +864,7 @@ void CLCDproc::defineScreens()
socketPrintf(m_socketfd, "widget_add YSF Line4 scroller"); socketPrintf(m_socketfd, "widget_add YSF Line4 scroller");
/* Do we need to pre-populate the values?? /* Do we need to pre-populate the values??
socketPrintf(m_socketfd, "widget_set YSF Line2 2 1 15 1 h 3 Listening"); socketPrintf(m_socketfd, "widget_set YSF Line2 2 1 15 1 h 3 \"Listening\"");
socketPrintf(m_socketfd, "widget_set YSF Line3 3 1 15 1 h 3 \" \""); socketPrintf(m_socketfd, "widget_set YSF Line3 3 1 15 1 h 3 \" \"");
socketPrintf(m_socketfd, "widget_set YSF Line4 4 2 15 2 h 3 \" \""); socketPrintf(m_socketfd, "widget_set YSF Line4 4 2 15 2 h 3 \" \"");
*/ */
@ -804,7 +880,7 @@ void CLCDproc::defineScreens()
socketPrintf(m_socketfd, "widget_add P25 Line4 scroller"); socketPrintf(m_socketfd, "widget_add P25 Line4 scroller");
/* Do we need to pre-populate the values?? /* Do we need to pre-populate the values??
socketPrintf(m_socketfd, "widget_set P25 Line3 2 1 15 1 h 3 Listening"); socketPrintf(m_socketfd, "widget_set P25 Line3 2 1 15 1 h 3 \"Listening\"");
socketPrintf(m_socketfd, "widget_set P25 Line3 3 1 15 1 h 3 \" \""); socketPrintf(m_socketfd, "widget_set P25 Line3 3 1 15 1 h 3 \" \"");
socketPrintf(m_socketfd, "widget_set P25 Line4 4 2 15 2 h 3 \" \""); socketPrintf(m_socketfd, "widget_set P25 Line4 4 2 15 2 h 3 \" \"");
*/ */
@ -820,10 +896,26 @@ void CLCDproc::defineScreens()
socketPrintf(m_socketfd, "widget_add NXDN Line4 scroller"); socketPrintf(m_socketfd, "widget_add NXDN Line4 scroller");
/* Do we need to pre-populate the values?? /* Do we need to pre-populate the values??
socketPrintf(m_socketfd, "widget_set NXDN Line3 2 1 15 1 h 3 Listening"); socketPrintf(m_socketfd, "widget_set NXDN Line3 2 1 15 1 h 3 \"Listening\"");
socketPrintf(m_socketfd, "widget_set NXDN Line3 3 1 15 1 h 3 \" \""); socketPrintf(m_socketfd, "widget_set NXDN Line3 3 1 15 1 h 3 \" \"");
socketPrintf(m_socketfd, "widget_set NXDN Line4 4 2 15 2 h 3 \" \""); socketPrintf(m_socketfd, "widget_set NXDN Line4 4 2 15 2 h 3 \" \"");
*/ */
// The M17 Screen
socketPrintf(m_socketfd, "screen_add M17");
socketPrintf(m_socketfd, "screen_set M17 -name M17 -heartbeat on -priority hidden -backlight on");
socketPrintf(m_socketfd, "widget_add M17 Mode string");
socketPrintf(m_socketfd, "widget_add M17 Line2 scroller");
socketPrintf(m_socketfd, "widget_add M17 Line3 scroller");
socketPrintf(m_socketfd, "widget_add M17 Line4 scroller");
/* Do we need to pre-populate the values??
socketPrintf(m_socketfd, "widget_set M17 Line3 2 1 15 1 h 3 \"Listening\"");
socketPrintf(m_socketfd, "widget_set M17 Line3 3 1 15 1 h 3 \" \"");
socketPrintf(m_socketfd, "widget_set M17 Line4 4 2 15 2 h 3 \" \"");
*/
m_screensDefined = true; m_screensDefined = true;
} }

View file

@ -1,6 +1,6 @@
/* /*
* Copyright (C) 2016,2017 by Tony Corbett G0WFV * Copyright (C) 2016,2017 by Tony Corbett G0WFV
* Copyright (C) 2018 by Jonathan Naylor G4KLX * Copyright (C) 2018,2020 by Jonathan Naylor G4KLX
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@ -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();
@ -40,7 +40,7 @@ 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 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);
@ -50,7 +50,7 @@ protected:
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, 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();
@ -62,6 +62,10 @@ protected:
virtual void writeNXDNRSSIInt(unsigned char rssi); virtual void writeNXDNRSSIInt(unsigned char rssi);
virtual void clearNXDNInt(); virtual void clearNXDNInt();
virtual void writeM17Int(const char* source, const char* dest, const char* type);
virtual void writeM17RSSIInt(unsigned char rssi);
virtual void clearM17Int();
virtual void writePOCSAGInt(uint32_t ric, const std::string& message); virtual void writePOCSAGInt(uint32_t ric, const std::string& message);
virtual void clearPOCSAGInt(); virtual void clearPOCSAGInt();
@ -73,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;

74
Log.cpp
View file

@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2015,2016 by Jonathan Naylor G4KLX * Copyright (C) 2015,2016,2020 by Jonathan Naylor G4KLX
* *
* This program is free software; you can redistribute it and/or modify * 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,6 +22,7 @@
#include <Windows.h> #include <Windows.h>
#else #else
#include <sys/time.h> #include <sys/time.h>
#include <unistd.h>
#endif #endif
#include <cstdio> #include <cstdio>
@ -34,8 +35,10 @@
static unsigned int m_fileLevel = 2U; static unsigned int m_fileLevel = 2U;
static std::string m_filePath; static std::string m_filePath;
static std::string m_fileRoot; static std::string m_fileRoot;
static bool m_fileRotate = true;
static FILE* m_fpLog = NULL; static FILE* m_fpLog = NULL;
static bool m_daemon = false;
static unsigned int m_displayLevel = 2U; static unsigned int m_displayLevel = 2U;
@ -43,8 +46,10 @@ static struct tm m_tm;
static char LEVELS[] = " DMIWEF"; static char LEVELS[] = " DMIWEF";
static bool LogOpen() static bool logOpenRotate()
{ {
bool status = false;
if (m_fileLevel == 0U) if (m_fileLevel == 0U)
return true; return true;
@ -61,25 +66,76 @@ static bool LogOpen()
::fclose(m_fpLog); ::fclose(m_fpLog);
} }
char filename[100U]; char filename[200U];
#if defined(_WIN32) || defined(_WIN64) #if defined(_WIN32) || defined(_WIN64)
::sprintf(filename, "%s\\%s-%04d-%02d-%02d.log", m_filePath.c_str(), m_fileRoot.c_str(), tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday); ::sprintf(filename, "%s\\%s-%04d-%02d-%02d.log", m_filePath.c_str(), m_fileRoot.c_str(), tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday);
#else #else
::sprintf(filename, "%s/%s-%04d-%02d-%02d.log", m_filePath.c_str(), m_fileRoot.c_str(), tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday); ::sprintf(filename, "%s/%s-%04d-%02d-%02d.log", m_filePath.c_str(), m_fileRoot.c_str(), tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday);
#endif #endif
m_fpLog = ::fopen(filename, "a+t"); if ((m_fpLog = ::fopen(filename, "a+t")) != NULL) {
status = true;
#if !defined(_WIN32) && !defined(_WIN64)
if (m_daemon)
dup2(fileno(m_fpLog), fileno(stderr));
#endif
}
m_tm = *tm; m_tm = *tm;
return m_fpLog != NULL; return status;
} }
bool LogInitialise(const std::string& filePath, const std::string& fileRoot, unsigned int fileLevel, unsigned int displayLevel) static bool logOpenNoRotate()
{
bool status = false;
if (m_fileLevel == 0U)
return true;
if (m_fpLog != NULL)
return true;
char filename[200U];
#if defined(_WIN32) || defined(_WIN64)
::sprintf(filename, "%s\\%s.log", m_filePath.c_str(), m_fileRoot.c_str());
#else
::sprintf(filename, "%s/%s.log", m_filePath.c_str(), m_fileRoot.c_str());
#endif
if ((m_fpLog = ::fopen(filename, "a+t")) != NULL) {
status = true;
#if !defined(_WIN32) && !defined(_WIN64)
if (m_daemon)
dup2(fileno(m_fpLog), fileno(stderr));
#endif
}
return status;
}
bool LogOpen()
{
if (m_fileRotate)
return logOpenRotate();
else
return logOpenNoRotate();
}
bool LogInitialise(bool daemon, const std::string& filePath, const std::string& fileRoot, unsigned int fileLevel, unsigned int displayLevel, bool rotate)
{ {
m_filePath = filePath; m_filePath = filePath;
m_fileRoot = fileRoot; m_fileRoot = fileRoot;
m_fileLevel = fileLevel; m_fileLevel = fileLevel;
m_displayLevel = displayLevel; m_displayLevel = displayLevel;
m_daemon = daemon;
m_fileRotate = rotate;
if (m_daemon)
m_displayLevel = 0U;
return ::LogOpen(); return ::LogOpen();
} }
@ -93,7 +149,7 @@ void Log(unsigned int level, const char* fmt, ...)
{ {
assert(fmt != NULL); assert(fmt != NULL);
char buffer[300U]; char buffer[501U];
#if defined(_WIN32) || defined(_WIN64) #if defined(_WIN32) || defined(_WIN64)
SYSTEMTIME st; SYSTEMTIME st;
::GetSystemTime(&st); ::GetSystemTime(&st);
@ -105,13 +161,13 @@ 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.%03lu ", 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 / 1000U); ::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;
va_start(vl, fmt); va_start(vl, fmt);
::vsprintf(buffer + ::strlen(buffer), fmt, vl); ::vsnprintf(buffer + ::strlen(buffer), 500, fmt, vl);
va_end(vl); va_end(vl);

4
Log.h
View file

@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2015,2016 by Jonathan Naylor G4KLX * Copyright (C) 2015,2016,2020 by Jonathan Naylor G4KLX
* *
* This program is free software; you can redistribute it and/or modify * 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
@ -30,7 +30,7 @@
extern void Log(unsigned int level, const char* fmt, ...); extern void Log(unsigned int level, const char* fmt, ...);
extern bool LogInitialise(const std::string& filePath, const std::string& fileRoot, unsigned int fileLevel, unsigned int displayLevel); extern bool LogInitialise(bool daemon, const std::string& filePath, const std::string& fileRoot, unsigned int fileLevel, unsigned int displayLevel, bool rotate);
extern void LogFinalise(); extern void LogFinalise();
#endif #endif

155
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
@ -13,12 +13,6 @@ Daemon=0
RXFrequency=435000000 RXFrequency=435000000
TXFrequency=435000000 TXFrequency=435000000
Power=1 Power=1
Latitude=0.0
Longitude=0.0
Height=0
Location=Nowhere
Description=Multi-Mode Repeater
URL=www.google.co.uk
[Log] [Log]
# Logging levels, 0=No logging # Logging levels, 0=No logging
@ -26,6 +20,7 @@ DisplayLevel=1
FileLevel=1 FileLevel=1
FilePath=. FilePath=.
FileRoot=MMDVM FileRoot=MMDVM
FileRotate=1
[CW Id] [CW Id]
Enable=1 Enable=1
@ -36,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=\\.\COM3
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
@ -58,14 +60,9 @@ 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
# POCSAGTXLevel=50
RSSIMappingFile=RSSI.dat RSSIMappingFile=RSSI.dat
UseCOSAsLockout=0
Trace=0 Trace=0
Debug=0 Debug=0
@ -76,28 +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
[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
@ -107,88 +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, 4=force off
[System Fusion] # OVCM=0
Enable=1
LowDeviation=0
SelfOnly=0
TXHang=4
#DGID=1
RemoteGateway=0
# ModeHang=10
[P25]
Enable=1
NAC=293
SelfOnly=0
OverrideUIDCheck=0
RemoteGateway=0
# ModeHang=10
[NXDN]
Enable=1
RAN=1
SelfOnly=0
RemoteGateway=0
# ModeHang=10
[POCSAG]
Enable=1
Frequency=439987500
[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=44.131.4.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.
Type=Direct
LocalAddress=127.0.0.1
LocalPort=62032
RemoteAddress=127.0.0.1
RemotePort=62031
# Password=P@ssw0rd1234
Jitter=360 Jitter=360
# Local=62032
Password=PASSWORD
# Options=
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
LocalAddress=127.0.0.1
LocalPort=14021
GatewayAddress=127.0.0.1
GatewayPort=14020
# 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
@ -234,6 +150,7 @@ Invert=0
Scroll=1 Scroll=1
Rotate=0 Rotate=0
Cast=0 Cast=0
LogoScreensaver=1
[LCDproc] [LCDproc]
Address=localhost Address=localhost
@ -247,11 +164,7 @@ UTC=0
Enable=0 Enable=0
File=/tmp/MMDVM_Active.lck File=/tmp/MMDVM_Active.lck
[Mobile GPS]
Enable=0
Address=127.0.0.1
Port=7834
[Remote Control] [Remote Control]
Enable=0 Enable=0
Address=127.0.0.1
Port=7642 Port=7642

File diff suppressed because it is too large Load diff

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
@ -20,31 +20,34 @@
#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 "NXDNLookup.h" //#include "M17Control.h"
#include "YSFNetwork.h" //#include "NXDNLookup.h"
#include "P25Network.h" //#include "YSFNetwork.h"
//#include "P25Network.h"
#include "DMRNetwork.h" #include "DMRNetwork.h"
//#include "M17Network.h"
//#include "FMNetwork.h"
#include "DMRLookup.h" #include "DMRLookup.h"
#include "MobileGPS.h" //#include "FMControl.h"
#include "Display.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>
class CMMDVMHost class CMMDVMHost
{ {
public: public:
@ -53,35 +56,33 @@ 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;
CPOCSAGControl* m_pocsag;
CDStarNetwork* m_dstarNetwork;
CDMRNetwork* m_dmrNetwork;
CYSFNetwork* m_ysfNetwork;
CP25Network* m_p25Network;
CNXDNNetwork* m_nxdnNetwork;
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;
unsigned int m_ysfRFModeHang; unsigned int m_ysfRFModeHang;
unsigned int m_p25RFModeHang; unsigned int m_p25RFModeHang;
unsigned int m_nxdnRFModeHang; unsigned int m_nxdnRFModeHang;
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;
unsigned int m_p25NetModeHang; unsigned int m_p25NetModeHang;
unsigned int m_nxdnNetModeHang; unsigned int m_nxdnNetModeHang;
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;
@ -92,16 +93,17 @@ private:
bool m_ysfEnabled; bool m_ysfEnabled;
bool m_p25Enabled; bool m_p25Enabled;
bool m_nxdnEnabled; bool m_nxdnEnabled;
bool m_m17Enabled;
bool m_pocsagEnabled; bool m_pocsagEnabled;
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;
bool m_lockFileEnabled; bool m_lockFileEnabled;
std::string m_lockFileName; std::string m_lockFileName;
CMobileGPS* m_mobileGPS;
CRemoteControl* m_remoteControl; CRemoteControl* m_remoteControl;
bool m_fixedMode; bool m_fixedMode;
@ -112,10 +114,14 @@ private:
bool createYSFNetwork(); bool createYSFNetwork();
bool createP25Network(); bool createP25Network();
bool createNXDNNetwork(); bool createNXDNNetwork();
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);
void processEnableCommand(bool& mode, bool enabled);
void setMode(unsigned char mode); void setMode(unsigned char mode);

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,336 +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.15063.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>v141</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v141</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v141</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v141</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>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>_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>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>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="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="MMDVMHost.h" />
<ClInclude Include="MobileGPS.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="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="SHA256.h" />
<ClInclude Include="StopWatch.h" />
<ClInclude Include="Sync.h" />
<ClInclude Include="TFTSerial.h" />
<ClInclude Include="Thread.h" />
<ClInclude Include="Timer.h" />
<ClInclude Include="UDPSocket.h" />
<ClInclude Include="UMP.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="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="MMDVMHost.cpp" />
<ClCompile Include="MobileGPS.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="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="SHA256.cpp" />
<ClCompile Include="StopWatch.cpp" />
<ClCompile Include="Sync.cpp" />
<ClCompile Include="TFTSerial.cpp" />
<ClCompile Include="Thread.cpp" />
<ClCompile Include="Timer.cpp" />
<ClCompile Include="UDPSocket.cpp" />
<ClCompile Include="UMP.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,542 +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="SHA256.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="MobileGPS.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="NullModem.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="DMRTA.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="SHA256.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="MobileGPS.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="NullModem.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="DMRTA.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
</Project>

View file

@ -1,19 +1,19 @@
# This makefile is for all platforms, but doesn't include support for the HD44780, OLED, or PCF8574 displays on the Raspberry Pi. # This makefile is for all platforms, but doesn't include support for the HD44780, OLED, or PCF8574 displays on the Raspberry Pi.
CC = gcc CC = cc
CXX = g++ CXX = c++
CFLAGS = -g -O3 -Wall -std=c++0x -pthread 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 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 DStarNetwork.o \ DMRDirectNetwork.o DMREMB.o DMREmbeddedData.o DMRFullLC.o DMRGatewayNetwork.o DMRLookup.o DMRLC.o DMRNetwork.o DMRShortLC.o DMRSlot.o DMRSlotType.o \
DStarSlowData.o Golay2087.o Golay24128.o Hamming.o I2CController.o LCDproc.o Log.o MMDVMHost.o MobileGPS.o Modem.o ModemSerialPort.o Mutex.o \ DMRAccessControl.o DMRTA.o DMRTrellis.o Golay2087.o Golay24128.o\
NetworkInfo.o Nextion.o NullDisplay.o NullModem.o NXDNAudio.o NXDNControl.o NXDNConvolution.o NXDNCRC.o NXDNFACCH1.o NXDNLayer3.o NXDNLICH.o \ Hamming.o I2CController.o IIRDirectForm1Filter.o LCDproc.o Log.o MMDVMHost.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 \ Modem.o ModemPort.o ModemSerialPort.o Mutex.o NetworkInfo.o Nextion.o NullController.o NullDisplay.o \
POCSAGControl.o POCSAGNetwork.o QR1676.o RemoteControl.o RS129.o RS241213.o RSSIInterpolator.o SerialController.o SerialPort.o SHA256.o StopWatch.o Sync.o TFTSerial.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 \
Thread.o Timer.o UDPSocket.o UMP.o Utils.o YSFControl.o YSFConvolution.o YSFFICH.o YSFNetwork.o YSFPayload.o Timer.o UARTController.o UDPController.o UDPSocket.o UserDB.o UserDBentry.o Utils.o
all: MMDVMHost RemoteCommand all: MMDVMHost RemoteCommand
@ -26,6 +26,33 @@ RemoteCommand: Log.o RemoteCommand.o UDPSocket.o
%.o: %.cpp %.o: %.cpp
$(CXX) $(CFLAGS) -c -o $@ $< $(CXX) $(CFLAGS) -c -o $@ $<
.PHONY install:
install: all
install -m 755 MMDVMHost /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,19 +1,19 @@
# This makefile is for use with the Raspberry Pi. The wiringpi library is needed. # This makefile is for use with the Raspberry Pi. The wiringpi library is needed.
CC = gcc CC = cc
CXX = g++ CXX = c++
CFLAGS = -g -O3 -Wall -std=c++0x -pthread -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 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 DStarNetwork.o \ DMRDirectNetwork.o DMREMB.o DMREmbeddedData.o DMRFullLC.o DMRGatewayNetwork.o DMRLookup.o DMRLC.o DMRNetwork.o DMRShortLC.o DMRSlot.o DMRSlotType.o \
DStarSlowData.o Golay2087.o Golay24128.o Hamming.o I2CController.o LCDproc.o Log.o MMDVMHost.o MobileGPS.o Modem.o ModemSerialPort.o Mutex.o \ DMRAccessControl.o DMRTA.o DMRTrellis.o Golay2087.o Golay24128.o\
NetworkInfo.o Nextion.o NullDisplay.o NullModem.o NXDNAudio.o NXDNControl.o NXDNConvolution.o NXDNCRC.o NXDNFACCH1.o NXDNLayer3.o NXDNLICH.o NXDNLookup.o \ Hamming.o I2CController.o IIRDirectForm1Filter.o LCDproc.o Log.o MMDVMHost.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 \ Modem.o ModemPort.o ModemSerialPort.o Mutex.o NetworkInfo.o Nextion.o NullController.o NullDisplay.o \
POCSAGNetwork.o QR1676.o RemoteControl.o RS129.o RS241213.o RSSIInterpolator.o SerialController.o SerialPort.o SHA256.o StopWatch.o Sync.o TFTSerial.o Thread.o Timer.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 \
UDPSocket.o UMP.o Utils.o YSFControl.o YSFConvolution.o YSFFICH.o YSFNetwork.o YSFPayload.o Timer.o UARTController.o UDPController.o UDPSocket.o UserDB.o UserDBentry.o Utils.o
all: MMDVMHost RemoteCommand all: MMDVMHost RemoteCommand
@ -26,6 +26,33 @@ RemoteCommand: Log.o RemoteCommand.o UDPSocket.o
%.o: %.cpp %.o: %.cpp
$(CXX) $(CFLAGS) -c -o $@ $< $(CXX) $(CFLAGS) -c -o $@ $<
.PHONY install:
install: all
install -m 755 MMDVMHost /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,39 +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 = gcc
CXX = g++
CFLAGS = -g -O3 -Wall -std=c++0x -pthread -DHD44780 -DADAFRUIT_DISPLAY -I/usr/local/include
LIBS = -lwiringPi -lwiringPiDev -lpthread
LDFLAGS = -g -L/usr/local/lib
OBJECTS = \
AMBEFEC.o BCH.o BPTC19696.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 MMDVMHost.o MobileGPS.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 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 SHA256.o StopWatch.o Sync.o TFTSerial.o Thread.o \
Timer.o UDPSocket.o UMP.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 $@ $<
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,38 +0,0 @@
# This makefile is for use with the Raspberry Pi when using an HD44780 compatible display. The wiringpi library is needed.
CC = gcc
CXX = g++
CFLAGS = -g -O3 -Wall -std=c++0x -pthread -DHD44780 -I/usr/local/include
LIBS = -lwiringPi -lwiringPiDev -lpthread
LDFLAGS = -g -L/usr/local/lib
OBJECTS = \
AMBEFEC.o BCH.o BPTC19696.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 MMDVMHost.o MobileGPS.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 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 SHA256.o StopWatch.o Sync.o TFTSerial.o Thread.o \
Timer.o UDPSocket.o UMP.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 $@ $<
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,38 +0,0 @@
# This makefile is for use with the Raspberry Pi when using an OLED display. The wiringpi library is needed.
CC = gcc
CXX = g++
CFLAGS = -g -O3 -Wall -std=c++0x -pthread -DOLED -I/usr/local/include
LIBS = -lArduiPi_OLED -lwiringPi -lpthread
LDFLAGS = -g -L/usr/local/lib
OBJECTS = \
AMBEFEC.o BCH.o BPTC19696.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 MMDVMHost.o MobileGPS.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 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 SHA256.o StopWatch.o Sync.o TFTSerial.o Thread.o \
Timer.o UDPSocket.o UMP.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 $@ $<
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,39 +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 = gcc
CXX = g++
CFLAGS = -g -O3 -Wall -std=c++0x -pthread -DHD44780 -DPCF8574_DISPLAY -I/usr/local/include
LIBS = -lwiringPi -lwiringPiDev -lpthread
LDFLAGS = -g -L/usr/local/lib
OBJECTS = \
AMBEFEC.o BCH.o BPTC19696.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 MMDVMHost.o MobileGPS.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 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 SHA256.o StopWatch.o Sync.o TFTSerial.o Thread.o \
Timer.o UDPSocket.o UMP.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 $@ $<
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,38 +0,0 @@
# This makefile is for Solaris using gcc
CC = gcc
CXX = g++
CFLAGS = -g -O3 -Wall -std=c++0x -pthread
LIBS = -lpthread -lsocket
LDFLAGS = -g
OBJECTS = \
AMBEFEC.o BCH.o BPTC19696.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 LCDproc.o Log.o MMDVMHost.o MobileGPS.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 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 SHA256.o StopWatch.o Sync.o TFTSerial.o Thread.o Timer.o UDPSocket.o \
UMP.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 $@ $<
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,101 +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 "MobileGPS.h"
#include <cstdio>
#include <cassert>
#include <cstring>
#include <cmath>
CMobileGPS::CMobileGPS(const std::string& address, unsigned int port, CDMRNetwork* network) :
m_idTimer(1000U, 60U),
m_address(),
m_port(port),
m_socket(),
m_network(network)
{
assert(!address.empty());
assert(port > 0U);
assert(network != NULL);
m_address = CUDPSocket::lookup(address);
}
CMobileGPS::~CMobileGPS()
{
}
bool CMobileGPS::open()
{
bool ret = m_socket.open();
if (!ret)
return false;
m_idTimer.start();
return true;
}
void CMobileGPS::clock(unsigned int ms)
{
m_idTimer.clock(ms);
if (m_idTimer.hasExpired()) {
pollGPS();
m_idTimer.start();
}
sendReport();
}
void CMobileGPS::close()
{
m_socket.close();
}
bool CMobileGPS::pollGPS()
{
return m_socket.write((unsigned char*)"MMDVMHost", 9U, m_address, m_port);
}
void CMobileGPS::sendReport()
{
// Grab GPS data if it's available
unsigned char buffer[200U];
in_addr address;
unsigned int port;
int ret = m_socket.read(buffer, 200U, address, port);
if (ret <= 0)
return;
buffer[ret] = '\0';
// Parse the GPS data
char* pLatitude = ::strtok((char*)buffer, ",\n"); // Latitude
char* pLongitude = ::strtok(NULL, ",\n"); // Longitude
if (pLatitude == NULL || pLongitude == NULL)
return;
float latitude = float(::atof(pLatitude));
float longitude = float(::atof(pLongitude));
m_network->writeHomePosition(latitude, longitude);
}

1228
Modem.cpp

File diff suppressed because it is too large Load diff

184
Modem.h
View file

@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2011-2018 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,86 +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 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 pocsagEnabled); 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 pocsagLevel); 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 setTransparentDataParams(unsigned int sendFrameType); void setP25Params(unsigned int txHang);
void setNXDNParams(unsigned int txHang);
void setM17Params(unsigned int txHang);
void setAX25Params(int rxTwist, unsigned int txDelay, unsigned int slotTime, unsigned int pPersist);
void setTransparentDataParams(unsigned int sendFrameType);
virtual bool open(); 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 setFMAckParams(const std::string& rfAck, unsigned int ackSpeed, unsigned int ackFrequency, unsigned int ackMinTime, unsigned int ackDelay, float ackLevel);
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 unsigned int readDStarData(unsigned char* data); bool open();
virtual unsigned int readDMRData1(unsigned char* data);
virtual unsigned int readDMRData2(unsigned char* data);
virtual unsigned int readYSFData(unsigned char* data);
virtual unsigned int readP25Data(unsigned char* data);
virtual unsigned int readNXDNData(unsigned char* data);
virtual unsigned int readTransparentData(unsigned char* data);
virtual unsigned int readSerial(unsigned char* data, unsigned int length); bool hasDStar() const;
bool hasDMR() const;
bool hasYSF() const;
bool hasP25() const;
bool hasNXDN() const;
bool hasM17() const;
bool hasPOCSAG() const;
bool hasFM() const;
bool hasAX25() const;
virtual bool hasDStarSpace() const; unsigned int getVersion() const;
virtual bool hasDMRSpace1() const;
virtual bool hasDMRSpace2() const;
virtual bool hasYSFSpace() const;
virtual bool hasP25Space() const;
virtual bool hasNXDNSpace() const;
virtual bool hasPOCSAGSpace() const;
virtual bool hasTX() const; unsigned int readDStarData(unsigned char* data);
virtual bool hasCD() const; unsigned int readDMRData1(unsigned char* data);
unsigned int readDMRData2(unsigned char* data);
unsigned int readYSFData(unsigned char* data);
unsigned int readP25Data(unsigned char* data);
unsigned int readNXDNData(unsigned char* data);
unsigned int readM17Data(unsigned char* data);
unsigned int readFMData(unsigned char* data);
unsigned int readAX25Data(unsigned char* data);
virtual bool hasLockout() const; bool hasDStarSpace() const;
virtual bool hasError() 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 writeDStarData(const unsigned char* data, unsigned int length); bool hasTX() const;
virtual bool writeDMRData1(const unsigned char* data, unsigned int length); bool hasCD() const;
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 writePOCSAGData(const unsigned char* data, unsigned int length);
virtual bool writeTransparentData(const unsigned char* data, unsigned int length); bool hasLockout() const;
bool hasError() const;
virtual bool writeDStarInfo(const char* my1, const char* my2, const char* your, const char* type, const char* reflector); bool writeConfig();
virtual bool writeDMRInfo(unsigned int slotNo, const std::string& src, bool group, const std::string& dst, const char* type); bool writeDMRData1(const unsigned char* data, unsigned int length);
virtual bool writeYSFInfo(const char* source, const char* dest, const char* type, const char* origin); bool writeDMRData2(const unsigned char* data, unsigned int length);
virtual bool writeP25Info(const char* source, bool group, unsigned int dest, const char* type); bool writeDMRInfo(unsigned int slotNo, const std::string& src, bool group, const std::string& dst, const char* type);
virtual bool writeNXDNInfo(const char* source, bool group, unsigned int dest, const char* type); bool writeIPInfo(const std::string& address);
virtual bool writePOCSAGInfo(unsigned int ric, const std::string& message);
virtual bool writeIPInfo(const std::string& address);
virtual bool writeDMRStart(bool tx); bool writeDMRStart(bool tx);
virtual bool writeDMRShortLC(const unsigned char* lc); bool writeDMRShortLC(const unsigned char* lc);
virtual bool writeDMRAbort(unsigned int slotNo); bool writeDMRAbort(unsigned int slotNo);
virtual bool writeSerial(const unsigned char* data, unsigned int length); bool writeTransparentData(const unsigned char* data, unsigned int length);
unsigned int readTransparentData(unsigned char* data);
virtual bool setMode(unsigned char mode); bool writeSerial(const unsigned char* data, unsigned int length);
unsigned int readSerial(unsigned char* data, unsigned int length);
virtual bool sendCWId(const std::string& callsign); unsigned char getMode() const;
bool setMode(unsigned char mode);
virtual HW_TYPE getHWType() const; bool sendCWId(const std::string& callsign);
virtual void clock(unsigned int ms); HW_TYPE getHWType() const;
virtual void close(); void clock(unsigned int ms);
static CModem* createModem(const std::string& port, bool duplex, bool rxInvert, bool txInvert, bool pttInvert, unsigned int txDelay, unsigned int dmrDelay, bool trace, bool debug); void close();
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;
bool m_duplex; bool m_duplex;
bool m_rxInvert; bool m_rxInvert;
bool m_txInvert; bool m_txInvert;
@ -120,66 +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_pocsagTXLevel;
float m_rfLevel; float m_rfLevel;
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_pocsagEnabled;
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_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_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;
HW_TYPE m_hwType; HW_TYPE m_hwType;
unsigned char m_capabilities1;
unsigned char m_capabilities2;
bool readVersion(); bool readVersion();
bool readStatus(); bool readStatus();
bool setConfig(); bool setConfig1();
bool setConfig2();
bool setFrequency(); bool setFrequency();
bool setFMCallsignParams();
bool setFMAckParams();
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();

1627
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-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(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, CNXDNNetwork* 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;
CNXDNNetwork* 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,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,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,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

View file

@ -1,160 +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.
*/
#include "NXDNLookup.h"
#include "Timer.h"
#include "Log.h"
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cctype>
CNXDNLookup::CNXDNLookup(const std::string& filename, unsigned int reloadTime) :
CThread(),
m_filename(filename),
m_reloadTime(reloadTime),
m_table(),
m_mutex(),
m_stop(false)
{
}
CNXDNLookup::~CNXDNLookup()
{
}
bool CNXDNLookup::read()
{
bool ret = load();
if (m_reloadTime > 0U)
run();
return ret;
}
void CNXDNLookup::entry()
{
LogInfo("Started the NXDN Id lookup reload thread");
CTimer timer(1U, 3600U * m_reloadTime);
timer.start();
while (!m_stop) {
sleep(1000U);
timer.clock();
if (timer.hasExpired()) {
load();
timer.start();
}
}
LogInfo("Stopped the NXDN Id lookup reload thread");
}
void CNXDNLookup::stop()
{
if (m_reloadTime == 0U) {
delete this;
return;
}
m_stop = true;
wait();
}
std::string CNXDNLookup::find(unsigned int id)
{
std::string callsign;
if (id == 0xFFFFU)
return std::string("ALL");
m_mutex.lock();
try {
callsign = m_table.at(id);
} catch (...) {
char text[10U];
::sprintf(text, "%u", id);
callsign = std::string(text);
}
m_mutex.unlock();
return callsign;
}
bool CNXDNLookup::exists(unsigned int id)
{
m_mutex.lock();
bool found = m_table.count(id) == 1U;
m_mutex.unlock();
return found;
}
bool CNXDNLookup::load()
{
FILE* fp = ::fopen(m_filename.c_str(), "rt");
if (fp == NULL) {
LogWarning("Cannot open the NXDN Id lookup file - %s", m_filename.c_str());
return false;
}
m_mutex.lock();
// Remove the old entries
m_table.clear();
char buffer[100U];
while (::fgets(buffer, 100U, fp) != NULL) {
if (buffer[0U] == '#')
continue;
char* p1 = ::strtok(buffer, ",\t\r\n");
char* p2 = ::strtok(NULL, ",\t\r\n");
if (p1 != NULL && p2 != NULL) {
unsigned int id = (unsigned int)::atoi(p1);
if (id > 0U) {
for (char* p = p2; *p != 0x00U; p++)
*p = ::toupper(*p);
m_table[id] = std::string(p2);
}
}
}
m_mutex.unlock();
::fclose(fp);
size_t size = m_table.size();
if (size == 0U)
return false;
LogInfo("Loaded %u Ids to the NXDN callsign lookup table", size);
return true;
}

View file

@ -1,53 +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.
*/
#ifndef NXDNLookup_H
#define NXDNLookup_H
#include "Thread.h"
#include "Mutex.h"
#include <string>
#include <unordered_map>
class CNXDNLookup : public CThread {
public:
CNXDNLookup(const std::string& filename, unsigned int reloadTime);
virtual ~CNXDNLookup();
bool read();
virtual void entry();
std::string find(unsigned int id);
bool exists(unsigned int id);
void stop();
private:
std::string m_filename;
unsigned int m_reloadTime;
std::unordered_map<unsigned int, std::string> m_table;
CMutex m_mutex;
bool m_stop;
bool load();
};
#endif

View file

@ -1,169 +0,0 @@
/*
* Copyright (C) 2009-2014,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.
*/
#include "NXDNDefines.h"
#include "NXDNNetwork.h"
#include "Defines.h"
#include "Utils.h"
#include "Log.h"
#include <cstdio>
#include <cassert>
#include <cstring>
const unsigned int BUFFER_LENGTH = 200U;
CNXDNNetwork::CNXDNNetwork(const std::string& localAddress, unsigned int localPort, const std::string& gatewayAddress, unsigned int gatewayPort, bool debug) :
m_socket(localAddress, localPort),
m_address(),
m_port(gatewayPort),
m_debug(debug),
m_enabled(false),
m_buffer(1000U, "NXDN Network")
{
assert(gatewayPort > 0U);
assert(!gatewayAddress.empty());
m_address = CUDPSocket::lookup(gatewayAddress);
}
CNXDNNetwork::~CNXDNNetwork()
{
}
bool CNXDNNetwork::open()
{
LogMessage("Opening NXDN network connection");
if (m_address.s_addr == INADDR_NONE)
return false;
return m_socket.open();
}
bool CNXDNNetwork::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_address, m_port);
}
void CNXDNNetwork::clock(unsigned int ms)
{
unsigned char buffer[BUFFER_LENGTH];
in_addr address;
unsigned int port;
int length = m_socket.read(buffer, BUFFER_LENGTH, address, port);
if (length <= 0)
return;
// Check if the data is for us
if (m_address.s_addr != address.s_addr || port != m_port) {
LogMessage("NXDN packet received from an invalid source, %08X != %08X and/or %u != %u", m_address.s_addr, address.s_addr, m_port, port);
return;
}
// Invalid packet type?
if (::memcmp(buffer, "ICOM", 4U) != 0)
return;
if (length != 102)
return;
if (!m_enabled)
return;
if (m_debug)
CUtils::dump(1U, "NXDN Network Data Received", buffer, length);
m_buffer.addData(buffer + 40U, 33U);
}
bool CNXDNNetwork::read(unsigned char* data)
{
assert(data != NULL);
if (m_buffer.isEmpty())
return false;
m_buffer.getData(data, 33U);
return true;
}
void CNXDNNetwork::reset()
{
}
void CNXDNNetwork::close()
{
m_socket.close();
LogMessage("Closing NXDN network connection");
}
void CNXDNNetwork::enable(bool enabled)
{
if (enabled && !m_enabled)
reset();
else if (!enabled && m_enabled)
m_buffer.clear();
m_enabled = enabled;
}

View file

@ -1,67 +0,0 @@
/*
* Copyright (C) 2009-2014,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.
*/
#ifndef NXDNNetwork_H
#define NXDNNetwork_H
#include "NXDNDefines.h"
#include "RingBuffer.h"
#include "UDPSocket.h"
#include "Timer.h"
#include <cstdint>
#include <string>
enum NXDN_NETWORK_MESSAGE_TYPE {
NNMT_VOICE_HEADER,
NNMT_VOICE_BODY,
NNMT_VOICE_TRAILER,
NNMT_DATA_HEADER,
NNMT_DATA_BODY,
NNMT_DATA_TRAILER
};
class CNXDNNetwork {
public:
CNXDNNetwork(const std::string& localAddress, unsigned int localPort, const std::string& gatewayAddress, unsigned int gatewayPort, bool debug);
~CNXDNNetwork();
bool open();
void enable(bool enabled);
bool write(const unsigned char* data, NXDN_NETWORK_MESSAGE_TYPE type);
bool read(unsigned char* data);
void reset();
void close();
void clock(unsigned int ms);
private:
CUDPSocket m_socket;
in_addr m_address;
unsigned int m_port;
bool m_debug;
bool m_enabled;
CRingBuffer<unsigned char> m_buffer;
};
#endif

View file

@ -1,214 +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 "NXDNSACCH.h"
#include "NXDNConvolution.h"
#include "NXDNDefines.h"
#include "NXDNCRC.h"
#include <cstdio>
#include <cassert>
#include <cstring>
const unsigned int INTERLEAVE_TABLE[] = {
0U, 5U, 10U, 15U, 20U, 25U, 30U, 35U, 40U, 45U, 50U, 55U,
1U, 6U, 11U, 16U, 21U, 26U, 31U, 36U, 41U, 46U, 51U, 56U,
2U, 7U, 12U, 17U, 22U, 27U, 32U, 37U, 42U, 47U, 52U, 57U,
3U, 8U, 13U, 18U, 23U, 28U, 33U, 38U, 43U, 48U, 53U, 58U,
4U, 9U, 14U, 19U, 24U, 29U, 34U, 39U, 44U, 49U, 54U, 59U
};
const unsigned int PUNCTURE_LIST[] = { 5U, 11U, 17U, 23U, 29U, 35U, 41U, 47U, 53U, 59U, 65U, 71U };
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])
CNXDNSACCH::CNXDNSACCH(const CNXDNSACCH& sacch) :
m_data(NULL)
{
m_data = new unsigned char[5U];
::memcpy(m_data, sacch.m_data, 5U);
}
CNXDNSACCH::CNXDNSACCH() :
m_data(NULL)
{
m_data = new unsigned char[5U];
}
CNXDNSACCH::~CNXDNSACCH()
{
delete[] m_data;
}
bool CNXDNSACCH::decode(const unsigned char* data)
{
assert(data != NULL);
unsigned char temp1[8U];
for (unsigned int i = 0U; i < NXDN_SACCH_LENGTH_BITS; i++) {
unsigned int n = INTERLEAVE_TABLE[i] + NXDN_FSW_LENGTH_BITS + NXDN_LICH_LENGTH_BITS;
bool b = READ_BIT1(data, n);
WRITE_BIT1(temp1, i, b);
}
uint8_t temp2[90U];
unsigned int n = 0U;
unsigned int index = 0U;
for (unsigned int i = 0U; i < NXDN_SACCH_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 < 40U; i++) {
uint8_t s0 = temp2[n++];
uint8_t s1 = temp2[n++];
conv.decode(s0, s1);
}
conv.chainback(m_data, 36U);
return CNXDNCRC::checkCRC6(m_data, 26U);
}
void CNXDNSACCH::encode(unsigned char* data) const
{
assert(data != NULL);
unsigned char temp1[5U];
::memset(temp1, 0x00U, 5U);
for (unsigned int i = 0U; i < 26U; i++) {
bool b = READ_BIT1(m_data, i);
WRITE_BIT1(temp1, i, b);
}
CNXDNCRC::encodeCRC6(temp1, 26U);
unsigned char temp2[9U];
CNXDNConvolution conv;
conv.encode(temp1, temp2, 36U);
unsigned char temp3[8U];
unsigned int n = 0U;
unsigned int index = 0U;
for (unsigned int i = 0U; i < 72U; 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_SACCH_LENGTH_BITS; i++) {
unsigned int n = INTERLEAVE_TABLE[i] + NXDN_FSW_LENGTH_BITS + NXDN_LICH_LENGTH_BITS;
bool b = READ_BIT1(temp3, i);
WRITE_BIT1(data, n, b);
}
}
unsigned char CNXDNSACCH::getRAN() const
{
return m_data[0U] & 0x3FU;
}
unsigned char CNXDNSACCH::getStructure() const
{
return (m_data[0U] >> 6) & 0x03U;
}
void CNXDNSACCH::getData(unsigned char* data) const
{
assert(data != NULL);
unsigned int offset = 8U;
for (unsigned int i = 0U; i < 18U; i++, offset++) {
bool b = READ_BIT1(m_data, offset);
WRITE_BIT1(data, i, b);
}
}
void CNXDNSACCH::getRaw(unsigned char* data) const
{
assert(data != NULL);
::memcpy(data, m_data, 4U);
CNXDNCRC::encodeCRC6(data, 26U);
}
void CNXDNSACCH::setRAN(unsigned char ran)
{
m_data[0U] &= 0xC0U;
m_data[0U] |= ran;
}
void CNXDNSACCH::setStructure(unsigned char structure)
{
m_data[0U] &= 0x3FU;
m_data[0U] |= (structure << 6) & 0xC0U;
}
void CNXDNSACCH::setData(const unsigned char* data)
{
assert(data != NULL);
unsigned int offset = 8U;
for (unsigned int i = 0U; i < 18U; i++, offset++) {
bool b = READ_BIT1(data, i);
WRITE_BIT1(m_data, offset, b);
}
}
void CNXDNSACCH::setRaw(const unsigned char* data)
{
assert(data != NULL);
::memcpy(m_data, data, 4U);
}
CNXDNSACCH& CNXDNSACCH::operator=(const CNXDNSACCH& sacch)
{
if (&sacch != this)
::memcpy(m_data, sacch.m_data, 5U);
return *this;
}

View file

@ -1,50 +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(NXDNSACCH_H)
#define NXDNSACCH_H
class CNXDNSACCH {
public:
CNXDNSACCH(const CNXDNSACCH& sacch);
CNXDNSACCH();
~CNXDNSACCH();
bool decode(const unsigned char* data);
void encode(unsigned char* data) const;
unsigned char getRAN() const;
unsigned char getStructure() const;
void getData(unsigned char* data) const;
void getRaw(unsigned char* data) const;
void setRAN(unsigned char ran);
void setStructure(unsigned char structure);
void setData(const unsigned char* data);
void setRaw(const unsigned char* data);
CNXDNSACCH& operator=(const CNXDNSACCH& sacch);
private:
unsigned char* m_data;
};
#endif

View file

@ -1,217 +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 "NXDNUDCH.h"
#include "NXDNConvolution.h"
#include "NXDNDefines.h"
#include "NXDNCRC.h"
#include <cstdio>
#include <cassert>
#include <cstring>
const unsigned int INTERLEAVE_TABLE[] = {
0U, 29U, 58U, 87U, 116U, 145U, 174U, 203U, 232U, 261U, 290U, 319U,
1U, 30U, 59U, 88U, 117U, 146U, 175U, 204U, 233U, 262U, 291U, 320U,
2U, 31U, 60U, 89U, 118U, 147U, 176U, 205U, 234U, 263U, 292U, 321U,
3U, 32U, 61U, 90U, 119U, 148U, 177U, 206U, 235U, 264U, 293U, 322U,
4U, 33U, 62U, 91U, 120U, 149U, 178U, 207U, 236U, 265U, 294U, 323U,
5U, 34U, 63U, 92U, 121U, 150U, 179U, 208U, 237U, 266U, 295U, 324U,
6U, 35U, 64U, 93U, 122U, 151U, 180U, 209U, 238U, 267U, 296U, 325U,
7U, 36U, 65U, 94U, 123U, 152U, 181U, 210U, 239U, 268U, 297U, 326U,
8U, 37U, 66U, 95U, 124U, 153U, 182U, 211U, 240U, 269U, 298U, 327U,
9U, 38U, 67U, 96U, 125U, 154U, 183U, 212U, 241U, 270U, 299U, 328U,
10U, 39U, 68U, 97U, 126U, 155U, 184U, 213U, 242U, 271U, 300U, 329U,
11U, 40U, 69U, 98U, 127U, 156U, 185U, 214U, 243U, 272U, 301U, 330U,
12U, 41U, 70U, 99U, 128U, 157U, 186U, 215U, 244U, 273U, 302U, 331U,
13U, 42U, 71U, 100U, 129U, 158U, 187U, 216U, 245U, 274U, 303U, 332U,
14U, 43U, 72U, 101U, 130U, 159U, 188U, 217U, 246U, 275U, 304U, 333U,
15U, 44U, 73U, 102U, 131U, 160U, 189U, 218U, 247U, 276U, 305U, 334U,
16U, 45U, 74U, 103U, 132U, 161U, 190U, 219U, 248U, 277U, 306U, 335U,
17U, 46U, 75U, 104U, 133U, 162U, 191U, 220U, 249U, 278U, 307U, 336U,
18U, 47U, 76U, 105U, 134U, 163U, 192U, 221U, 250U, 279U, 308U, 337U,
19U, 48U, 77U, 106U, 135U, 164U, 193U, 222U, 251U, 280U, 309U, 338U,
20U, 49U, 78U, 107U, 136U, 165U, 194U, 223U, 252U, 281U, 310U, 339U,
21U, 50U, 79U, 108U, 137U, 166U, 195U, 224U, 253U, 282U, 311U, 340U,
22U, 51U, 80U, 109U, 138U, 167U, 196U, 225U, 254U, 283U, 312U, 341U,
23U, 52U, 81U, 110U, 139U, 168U, 197U, 226U, 255U, 284U, 313U, 342U,
24U, 53U, 82U, 111U, 140U, 169U, 198U, 227U, 256U, 285U, 314U, 343U,
25U, 54U, 83U, 112U, 141U, 170U, 199U, 228U, 257U, 286U, 315U, 344U,
26U, 55U, 84U, 113U, 142U, 171U, 200U, 229U, 258U, 287U, 316U, 345U,
27U, 56U, 85U, 114U, 143U, 172U, 201U, 230U, 259U, 288U, 317U, 346U,
28U, 57U, 86U, 115U, 144U, 173U, 202U, 231U, 260U, 289U, 318U, 347U };
const unsigned int PUNCTURE_LIST[] = { 3U, 11U, 17U, 25U, 31U, 39U, 45U, 53U, 59U, 67U,
73U, 81U, 87U, 95U, 101U, 109U, 115U, 123U, 129U, 137U,
143U, 151U, 157U, 165U, 171U, 179U, 185U, 193U, 199U, 207U,
213U, 221U, 227U, 235U, 241U, 249U, 255U, 263U, 269U, 277U,
283U, 291U, 297U, 305U, 311U, 319U, 325U, 333U, 339U, 347U,
353U, 361U, 367U, 375U, 381U, 389U, 395U, 403U };
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])
CNXDNUDCH::CNXDNUDCH(const CNXDNUDCH& udch) :
m_data(NULL)
{
m_data = new unsigned char[23U + 3U];
::memcpy(m_data, udch.m_data, 23U + 3U);
}
CNXDNUDCH::CNXDNUDCH() :
m_data(NULL)
{
m_data = new unsigned char[23U + 3U];
}
CNXDNUDCH::~CNXDNUDCH()
{
delete[] m_data;
}
bool CNXDNUDCH::decode(const unsigned char* data)
{
assert(data != NULL);
unsigned char temp1[44U];
for (unsigned int i = 0U; i < NXDN_FACCH2_LENGTH_BITS; i++) {
unsigned int n = INTERLEAVE_TABLE[i] + NXDN_FSW_LENGTH_BITS + NXDN_LICH_LENGTH_BITS;
bool b = READ_BIT1(data, n);
WRITE_BIT1(temp1, i, b);
}
uint8_t temp2[420U];
unsigned int n = 0U;
unsigned int index = 0U;
for (unsigned int i = 0U; i < NXDN_FACCH2_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 < 207U; i++) {
uint8_t s0 = temp2[n++];
uint8_t s1 = temp2[n++];
conv.decode(s0, s1);
}
conv.chainback(m_data, 203U);
return CNXDNCRC::checkCRC15(m_data, 184U);
}
void CNXDNUDCH::encode(unsigned char* data) const
{
assert(data != NULL);
unsigned char temp1[25U];
::memset(temp1, 0x00U, 25U);
::memcpy(temp1, m_data, 23U);
CNXDNCRC::encodeCRC15(temp1, 184U);
unsigned char temp2[51U];
CNXDNConvolution conv;
conv.encode(temp1, temp2, 203U);
unsigned char temp3[44U];
unsigned int n = 0U;
unsigned int index = 0U;
for (unsigned int i = 0U; i < 406U; 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_FACCH2_LENGTH_BITS; i++) {
unsigned int n = INTERLEAVE_TABLE[i] + NXDN_FSW_LENGTH_BITS + NXDN_LICH_LENGTH_BITS;
bool b = READ_BIT1(temp3, i);
WRITE_BIT1(data, n, b);
}
}
unsigned char CNXDNUDCH::getRAN() const
{
return m_data[0U] & 0x3FU;
}
void CNXDNUDCH::getData(unsigned char* data) const
{
assert(data != NULL);
::memcpy(data, m_data + 1U, 22U);
}
void CNXDNUDCH::getRaw(unsigned char* data) const
{
assert(data != NULL);
::memset(data, 0x00U, 25U);
::memcpy(data, m_data, 23U);
}
void CNXDNUDCH::setRAN(unsigned char ran)
{
m_data[0U] = ran;
}
void CNXDNUDCH::setData(const unsigned char* data)
{
assert(data != NULL);
::memcpy(m_data + 1U, data, 22U);
}
void CNXDNUDCH::setRaw(const unsigned char* data)
{
assert(data != NULL);
::memcpy(m_data, data, 25U);
}
CNXDNUDCH& CNXDNUDCH::operator=(const CNXDNUDCH& udch)
{
if (&udch != this)
::memcpy(m_data, udch.m_data, 23U + 2U);
return *this;
}

View file

@ -1,48 +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(NXDNUDCH_H)
#define NXDNUDCH_H
class CNXDNUDCH {
public:
CNXDNUDCH(const CNXDNUDCH& udch);
CNXDNUDCH();
~CNXDNUDCH();
bool decode(const unsigned char* data);
void encode(unsigned char* data) const;
unsigned char getRAN() const;
void getData(unsigned char* data) const;
void getRaw(unsigned char* data) const;
void setRAN(unsigned char ran);
void setData(const unsigned char* data);
void setRaw(const unsigned char* data);
CNXDNUDCH& operator=(const CNXDNUDCH& udch);
private:
unsigned char* m_data;
};
#endif

View file

@ -26,12 +26,18 @@
#include <clocale> #include <clocale>
#include <sys/types.h> #include <sys/types.h>
#if !defined(_WIN32) && !defined(_WIN64) #if defined(__linux__) || defined(__OpenBSD__) || defined(__NetBSD__) || defined(__FreeBSD__) || defined(__APPLE__)
#include <ifaddrs.h> #include <ifaddrs.h>
#include <sys/socket.h>
#include <netinet/in.h> #include <netinet/in.h>
#include <arpa/inet.h> #include <arpa/inet.h>
#include <netdb.h> #include <netdb.h>
#else #if defined(__OpenBSD__) || defined(__NetBSD__) || defined(__FreeBSD__) || defined(__APPLE__)
#include <sys/sysctl.h>
#include <net/if.h>
#include <net/route.h>
#endif
#elif defined(_WIN32) || defined(_WIN64)
#include <ws2tcpip.h> #include <ws2tcpip.h>
#include <iphlpapi.h> #include <iphlpapi.h>
#pragma comment(lib, "iphlpapi.lib") #pragma comment(lib, "iphlpapi.lib")
@ -60,17 +66,16 @@ void CNetworkInfo::getNetworkInterface(unsigned char* info)
::strcpy((char*)info, "(address unknown)"); ::strcpy((char*)info, "(address unknown)");
#if !defined(_WIN32) && !defined(_WIN64) #if defined(__linux__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__FreeBSD__) || defined(__APPLE__)
const unsigned int IFLISTSIZ = 25U; char* dflt = NULL;
FILE* fp = ::fopen("/proc/net/route" , "r"); #if defined(__linux__)
FILE* fp = ::fopen("/proc/net/route" , "r"); // IPv4 routing
if (fp == NULL) { if (fp == NULL) {
LogError("Unabled to open /proc/route"); LogError("Unabled to open /proc/route");
return; return;
} }
char* dflt = NULL;
char line[100U]; char line[100U];
while (::fgets(line, 100U, fp)) { while (::fgets(line, 100U, fp)) {
char* p1 = strtok(line , " \t"); char* p1 = strtok(line , " \t");
@ -86,11 +91,60 @@ void CNetworkInfo::getNetworkInterface(unsigned char* info)
::fclose(fp); ::fclose(fp);
#elif defined(__OpenBSD__) || defined(__NetBSD__) || defined(__FreeBSD__) || defined(__APPLE__)
int mib[] = {
CTL_NET,
PF_ROUTE,
0, // protocol
AF_INET, // IPv4 routing
NET_RT_DUMP,
0, // show all routes
#if defined(__OpenBSD__) || defined(__FreeBSD__)
0, // table id
#endif
};
const int cnt = sizeof(mib) / sizeof(int);
size_t size;
char ifname[IF_NAMESIZE] = {};
if (::sysctl(mib, cnt, NULL, &size, NULL, 0) == -1 || size <= 0) {
LogError("Unable to estimate routing table size");
return;
}
char *buf = new char[size];
if (::sysctl(mib, cnt, buf, &size, NULL, 0) == -1) {
LogError("Unable to get routing table");
delete[] buf;
return;
}
struct rt_msghdr *rtm;
for (char *p = buf; p < buf + size; p += rtm->rtm_msglen) {
rtm = (struct rt_msghdr *)p;
if (rtm->rtm_version != RTM_VERSION)
continue;
#if defined(__OpenBSD__)
struct sockaddr_in *sa = (struct sockaddr_in *)(p + rtm->rtm_hdrlen);
#elif defined(__NetBSD__) || defined(__FreeBSD__) || defined(__APPLE__)
struct sockaddr_in *sa = (struct sockaddr_in *)(rtm + 1);
#endif
if (sa->sin_addr.s_addr == INADDR_ANY) {
::if_indextoname(rtm->rtm_index, ifname);
break;
}
}
delete[] buf;
if (::strlen(ifname))
dflt = ifname;
#endif
if (dflt == NULL) { if (dflt == NULL) {
LogError("Unable to find the default route"); LogError("Unable to find the default route");
return; return;
} }
const unsigned int IFLISTSIZ = 25U;
char interfacelist[IFLISTSIZ][50+INET6_ADDRSTRLEN]; char interfacelist[IFLISTSIZ][50+INET6_ADDRSTRLEN];
for (unsigned int n = 0U; n < IFLISTSIZ; n++) for (unsigned int n = 0U; n < IFLISTSIZ; n++)
interfacelist[n][0] = 0; interfacelist[n][0] = 0;
@ -118,12 +172,13 @@ void CNetworkInfo::getNetworkInterface(unsigned char* info)
if (family == AF_INET) { if (family == AF_INET) {
::sprintf(interfacelist[ifnr], "%s:%s", ifa->ifa_name, host); ::sprintf(interfacelist[ifnr], "%s:%s", ifa->ifa_name, host);
LogInfo(" IPv4: %s", interfacelist[ifnr]); LogInfo(" IPv4: %s", interfacelist[ifnr]);
ifnr++;
} else { } else {
::sprintf(interfacelist[ifnr], "%s:%s", ifa->ifa_name, host); ::sprintf(interfacelist[ifnr], "%s:%s", ifa->ifa_name, host);
LogInfo(" IPv6: %s", interfacelist[ifnr]); LogInfo(" IPv6: %s", interfacelist[ifnr]);
// due to default routing is for IPv4, other
// protocols are not candidate to display.
} }
ifnr++;
} }
} }
@ -143,7 +198,7 @@ void CNetworkInfo::getNetworkInterface(unsigned char* info)
} }
LogInfo(" IP to show: %s", info); LogInfo(" IP to show: %s", info);
#else #elif defined(_WIN32) || defined(_WIN64)
PMIB_IPFORWARDTABLE pIpForwardTable = (MIB_IPFORWARDTABLE *)::malloc(sizeof(MIB_IPFORWARDTABLE)); PMIB_IPFORWARDTABLE pIpForwardTable = (MIB_IPFORWARDTABLE *)::malloc(sizeof(MIB_IPFORWARDTABLE));
if (pIpForwardTable == NULL) { if (pIpForwardTable == NULL) {
LogError("Error allocating memory"); LogError("Error allocating memory");

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2016,2017,2018 by Jonathan Naylor G4KLX * Copyright (C) 2016,2017,2018,2020 by Jonathan Naylor G4KLX
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@ -25,20 +25,21 @@
#include <cstring> #include <cstring>
#include <ctime> #include <ctime>
#include <clocale> #include <clocale>
//#include <unistd.h>
const unsigned int DSTAR_RSSI_COUNT = 3U; // 3 * 420ms = 1260ms
const unsigned int DSTAR_BER_COUNT = 63U; // 63 * 20ms = 1260ms
const unsigned int DMR_RSSI_COUNT = 4U; // 4 * 360ms = 1440ms const unsigned int DMR_RSSI_COUNT = 4U; // 4 * 360ms = 1440ms
const unsigned int DMR_BER_COUNT = 24U; // 24 * 60ms = 1440ms const unsigned int DMR_BER_COUNT = 24U; // 24 * 60ms = 1440ms
const unsigned int YSF_RSSI_COUNT = 13U; // 13 * 100ms = 1300ms
const unsigned int YSF_BER_COUNT = 13U; // 13 * 100ms = 1300ms
const unsigned int P25_RSSI_COUNT = 7U; // 7 * 180ms = 1260ms
const unsigned int P25_BER_COUNT = 7U; // 7 * 180ms = 1260ms
const unsigned int NXDN_RSSI_COUNT = 28U; // 28 * 40ms = 1120ms
const unsigned int NXDN_BER_COUNT = 28U; // 28 * 40ms = 1120ms
CNextion::CNextion(const std::string& callsign, unsigned int dmrid, ISerialPort* serial, unsigned int brightness, bool displayClock, bool utc, unsigned int idleBrightness, unsigned int screenLayout, unsigned int txFrequency, unsigned int rxFrequency, bool displayTempInF, const std::string& location) : #define LAYOUT_COMPAT_MASK (7 << 0) // compatibility for old setting
#define LAYOUT_TA_ENABLE (1 << 4) // enable Talker Alias (TA) display
#define LAYOUT_TA_COLOUR (1 << 5) // TA display with font colour change
#define LAYOUT_TA_FONTSIZE (1 << 6) // TA display with font size change
#define LAYOUT_DIY (1 << 7) // use ON7LDS-DIY layout
// bit[3:2] is used in Display.cpp to set connection speed for LCD panel.
// 00:low, others:high-speed. bit[2] is overlapped with LAYOUT_COMPAT_MASK.
#define LAYOUT_HIGHSPEED (3 << 2)
CNextion::CNextion(const std::string& callsign, unsigned int dmrid, ISerialPort* serial, unsigned int brightness, bool displayClock, bool utc, unsigned int idleBrightness, unsigned int screenLayout, unsigned int txFrequency, unsigned int rxFrequency, bool displayTempInF) :
CDisplay(), CDisplay(),
m_callsign(callsign), m_callsign(callsign),
m_ipaddress("(ip unknown)"), m_ipaddress("(ip unknown)"),
@ -49,7 +50,7 @@ m_mode(MODE_IDLE),
m_displayClock(displayClock), m_displayClock(displayClock),
m_utc(utc), m_utc(utc),
m_idleBrightness(idleBrightness), m_idleBrightness(idleBrightness),
m_screenLayout(screenLayout), m_screenLayout(0),
m_clockDisplayTimer(1000U, 0U, 400U), m_clockDisplayTimer(1000U, 0U, 400U),
m_rssiAccum1(0U), m_rssiAccum1(0U),
m_rssiAccum2(0U), m_rssiAccum2(0U),
@ -63,11 +64,27 @@ m_txFrequency(txFrequency),
m_rxFrequency(rxFrequency), m_rxFrequency(rxFrequency),
m_fl_txFrequency(0.0F), m_fl_txFrequency(0.0F),
m_fl_rxFrequency(0.0F), m_fl_rxFrequency(0.0F),
m_displayTempInF(displayTempInF), m_displayTempInF(displayTempInF)
m_location(location)
{ {
assert(serial != NULL); assert(serial != NULL);
assert(brightness >= 0U && brightness <= 100U); assert(brightness >= 0U && brightness <= 100U);
static const unsigned int feature_set[] = {
0, // 0: G4KLX
0, // 1: (reserved, low speed)
// 2: ON7LDS
LAYOUT_TA_ENABLE | LAYOUT_TA_COLOUR | LAYOUT_TA_FONTSIZE,
LAYOUT_TA_ENABLE | LAYOUT_DIY, // 3: ON7LDS-DIY
LAYOUT_TA_ENABLE | LAYOUT_DIY, // 4: ON7LDS-DIY (high speed)
0, // 5: (reserved, high speed)
0, // 6: (reserved, high speed)
0, // 7: (reserved, high speed)
};
if (screenLayout & ~LAYOUT_COMPAT_MASK)
m_screenLayout = screenLayout & ~LAYOUT_COMPAT_MASK;
else
m_screenLayout = feature_set[screenLayout];
} }
CNextion::~CNextion() CNextion::~CNextion()
@ -94,15 +111,14 @@ bool CNextion::open()
sendCommand("bkcmd=0"); sendCommand("bkcmd=0");
sendCommandAction(0U); sendCommandAction(0U);
m_fl_txFrequency = float(m_txFrequency) / 1000000.0F; m_fl_txFrequency = double(m_txFrequency) / 1000000.0F;
m_fl_rxFrequency = float(m_rxFrequency) / 1000000.0F; m_fl_rxFrequency = double(m_rxFrequency) / 1000000.0F;
setIdle(); setIdle();
return true; return true;
} }
void CNextion::setIdleInt() void CNextion::setIdleInt()
{ {
// a few bits borrowed from Lieven De Samblanx ON7LDS, NextionDriver // a few bits borrowed from Lieven De Samblanx ON7LDS, NextionDriver
@ -119,18 +135,18 @@ void CNextion::setIdleInt()
::sprintf(command, "t0.txt=\"%s/%u\"", m_callsign.c_str(), m_dmrid); ::sprintf(command, "t0.txt=\"%s/%u\"", m_callsign.c_str(), m_dmrid);
sendCommand(command); sendCommand(command);
if (m_screenLayout > 2U) { if (m_screenLayout & LAYOUT_DIY) {
::sprintf(command, "t4.txt=\"%s\"", m_callsign.c_str()); ::sprintf(command, "t4.txt=\"%s\"", m_callsign.c_str());
sendCommand(command); sendCommand(command);
::sprintf(command, "t5.txt=\"%u\"", m_dmrid); ::sprintf(command, "t5.txt=\"%u\"", m_dmrid);
sendCommand(command); sendCommand(command);
sendCommandAction(17U); sendCommandAction(17U);
::sprintf(command, "t30.txt=\"%3.4f\"",m_fl_rxFrequency); // RX freq ::sprintf(command, "t30.txt=\"%3.6f\"",m_fl_rxFrequency); // RX freq
sendCommand(command); sendCommand(command);
sendCommandAction(20U); sendCommandAction(20U);
::sprintf(command, "t32.txt=\"%3.4f\"",m_fl_txFrequency); // TX freq ::sprintf(command, "t32.txt=\"%3.6f\"",m_fl_txFrequency); // TX freq
sendCommand(command); sendCommand(command);
sendCommandAction(21U); sendCommandAction(21U);
@ -153,10 +169,6 @@ void CNextion::setIdleInt()
sendCommandAction(22U); sendCommandAction(22U);
} }
} }
::sprintf(command, "t31.txt=\"%s\"", m_location.c_str()); // location
sendCommand(command);
sendCommandAction(23U);
} else { } else {
sendCommandAction(17U); sendCommandAction(17U);
} }
@ -240,88 +252,6 @@ void CNextion::setQuitInt()
m_mode = MODE_QUIT; m_mode = MODE_QUIT;
} }
void CNextion::writeDStarInt(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);
if (m_mode != MODE_DSTAR) {
sendCommand("page DStar");
sendCommandAction(2U);
}
char text[50U];
if (m_brightness>0) {
::sprintf(text, "dim=%u", m_brightness);
sendCommand(text);
}
::sprintf(text, "t0.txt=\"%s %.8s/%4.4s\"", type, my1, my2);
sendCommand(text);
sendCommandAction(42U);
::sprintf(text, "t1.txt=\"%.8s\"", your);
sendCommand(text);
sendCommandAction(45U);
if (::strcmp(reflector, " ") != 0) {
::sprintf(text, "t2.txt=\"via %.8s\"", reflector);
sendCommand(text);
sendCommandAction(46U);
}
m_clockDisplayTimer.stop();
m_mode = MODE_DSTAR;
m_rssiAccum1 = 0U;
m_berAccum1 = 0.0F;
m_rssiCount1 = 0U;
m_berCount1 = 0U;
}
void CNextion::writeDStarRSSIInt(unsigned char rssi)
{
m_rssiAccum1 += rssi;
m_rssiCount1++;
if (m_rssiCount1 == DSTAR_RSSI_COUNT) {
char text[25U];
::sprintf(text, "t3.txt=\"-%udBm\"", m_rssiAccum1 / DSTAR_RSSI_COUNT);
sendCommand(text);
sendCommandAction(47U);
m_rssiAccum1 = 0U;
m_rssiCount1 = 0U;
}
}
void CNextion::writeDStarBERInt(float ber)
{
m_berAccum1 += ber;
m_berCount1++;
if (m_berCount1 == DSTAR_BER_COUNT) {
char text[25U];
::sprintf(text, "t4.txt=\"%.1f%%\"", m_berAccum1 / float(DSTAR_BER_COUNT));
sendCommand(text);
sendCommandAction(48U);
m_berAccum1 = 0.0F;
m_berCount1 = 0U;
}
}
void CNextion::clearDStarInt()
{
sendCommand("t0.txt=\"Listening\"");
sendCommandAction(41U);
sendCommand("t1.txt=\"\"");
sendCommand("t2.txt=\"\"");
sendCommand("t3.txt=\"\"");
sendCommand("t4.txt=\"\"");
}
void CNextion::writeDMRInt(unsigned int slotNo, const std::string& src, bool group, const std::string& dst, const char* type) void CNextion::writeDMRInt(unsigned int slotNo, const std::string& src, bool group, const std::string& dst, const char* type)
{ {
assert(type != NULL); assert(type != NULL);
@ -332,16 +262,20 @@ void CNextion::writeDMRInt(unsigned int slotNo, const std::string& src, bool gro
if (slotNo == 1U) { if (slotNo == 1U) {
if (m_screenLayout == 2U) { if (m_screenLayout & LAYOUT_TA_ENABLE) {
if (m_screenLayout & LAYOUT_TA_COLOUR)
sendCommand("t2.pco=0"); sendCommand("t2.pco=0");
if (m_screenLayout & LAYOUT_TA_FONTSIZE)
sendCommand("t2.font=4"); sendCommand("t2.font=4");
} }
sendCommand("t2.txt=\"2 Listening\""); sendCommand("t2.txt=\"2 Listening\"");
sendCommandAction(69U); sendCommandAction(69U);
} else { } else {
if (m_screenLayout == 2U) { if (m_screenLayout & LAYOUT_TA_ENABLE) {
if (m_screenLayout & LAYOUT_TA_COLOUR)
sendCommand("t0.pco=0"); sendCommand("t0.pco=0");
if (m_screenLayout & LAYOUT_TA_FONTSIZE)
sendCommand("t0.font=4"); sendCommand("t0.font=4");
} }
@ -359,8 +293,10 @@ void CNextion::writeDMRInt(unsigned int slotNo, const std::string& src, bool gro
if (slotNo == 1U) { if (slotNo == 1U) {
::sprintf(text, "t0.txt=\"1 %s %s\"", type, src.c_str()); ::sprintf(text, "t0.txt=\"1 %s %s\"", type, src.c_str());
if (m_screenLayout == 2U) { if (m_screenLayout & LAYOUT_TA_ENABLE) {
if (m_screenLayout & LAYOUT_TA_COLOUR)
sendCommand("t0.pco=0"); sendCommand("t0.pco=0");
if (m_screenLayout & LAYOUT_TA_FONTSIZE)
sendCommand("t0.font=4"); sendCommand("t0.font=4");
} }
@ -373,8 +309,10 @@ void CNextion::writeDMRInt(unsigned int slotNo, const std::string& src, bool gro
} else { } else {
::sprintf(text, "t2.txt=\"2 %s %s\"", type, src.c_str()); ::sprintf(text, "t2.txt=\"2 %s %s\"", type, src.c_str());
if (m_screenLayout == 2U) { if (m_screenLayout & LAYOUT_TA_ENABLE) {
if (m_screenLayout & LAYOUT_TA_COLOUR)
sendCommand("t2.pco=0"); sendCommand("t2.pco=0");
if (m_screenLayout & LAYOUT_TA_FONTSIZE)
sendCommand("t2.font=4"); sendCommand("t2.font=4");
} }
@ -430,15 +368,17 @@ void CNextion::writeDMRRSSIInt(unsigned int slotNo, unsigned char rssi)
void CNextion::writeDMRTAInt(unsigned int slotNo, unsigned char* talkerAlias, const char* type) void CNextion::writeDMRTAInt(unsigned int slotNo, unsigned char* talkerAlias, const char* type)
{ {
if (m_screenLayout < 2U) if (!(m_screenLayout & LAYOUT_TA_ENABLE))
return; return;
if (type[0] == ' ') { if (type[0] == ' ') {
if (slotNo == 1U) { if (slotNo == 1U) {
if (m_screenLayout == 2U) sendCommand("t0.pco=33808"); if (m_screenLayout & LAYOUT_TA_COLOUR)
sendCommand("t0.pco=33808");
sendCommandAction(64U); sendCommandAction(64U);
} else { } else {
if (m_screenLayout == 2U) sendCommand("t2.pco=33808"); if (m_screenLayout & LAYOUT_TA_COLOUR)
sendCommand("t2.pco=33808");
sendCommandAction(72U); sendCommandAction(72U);
} }
@ -449,33 +389,36 @@ void CNextion::writeDMRTAInt(unsigned int slotNo, unsigned char* talkerAlias, co
char text[50U]; char text[50U];
::sprintf(text, "t0.txt=\"1 %s %s\"", type, talkerAlias); ::sprintf(text, "t0.txt=\"1 %s %s\"", type, talkerAlias);
if (m_screenLayout == 2U) { if (m_screenLayout & LAYOUT_TA_FONTSIZE) {
if (::strlen((char*)talkerAlias) > (16U-4U)) if (::strlen((char*)talkerAlias) > (16U-4U))
sendCommand("t0.font=3"); sendCommand("t0.font=3");
if (::strlen((char*)talkerAlias) > (20U-4U)) if (::strlen((char*)talkerAlias) > (20U-4U))
sendCommand("t0.font=2"); sendCommand("t0.font=2");
if (::strlen((char*)talkerAlias) > (24U-4U)) if (::strlen((char*)talkerAlias) > (24U-4U))
sendCommand("t0.font=1"); sendCommand("t0.font=1");
sendCommand("t0.pco=1024");
} }
if (m_screenLayout & LAYOUT_TA_COLOUR)
sendCommand("t0.pco=1024");
sendCommand(text); sendCommand(text);
sendCommandAction(63U); sendCommandAction(63U);
} else { } else {
char text[50U]; char text[50U];
::sprintf(text, "t2.txt=\"2 %s %s\"", type, talkerAlias); ::sprintf(text, "t2.txt=\"2 %s %s\"", type, talkerAlias);
if (m_screenLayout == 2U) { if (m_screenLayout & LAYOUT_TA_FONTSIZE) {
if (::strlen((char*)talkerAlias) > (16U-4U)) if (::strlen((char*)talkerAlias) > (16U-4U))
sendCommand("t2.font=3"); sendCommand("t2.font=3");
if (::strlen((char*)talkerAlias) > (20U-4U)) if (::strlen((char*)talkerAlias) > (20U-4U))
sendCommand("t2.font=2"); sendCommand("t2.font=2");
if (::strlen((char*)talkerAlias) > (24U-4U)) if (::strlen((char*)talkerAlias) > (24U-4U))
sendCommand("t2.font=1"); sendCommand("t2.font=1");
sendCommand("t2.pco=1024");
} }
if (m_screenLayout & LAYOUT_TA_COLOUR)
sendCommand("t2.pco=1024");
sendCommand(text); sendCommand(text);
sendCommandAction(71U); sendCommandAction(71U);
} }
@ -517,8 +460,10 @@ void CNextion::clearDMRInt(unsigned int slotNo)
sendCommand("t0.txt=\"1 Listening\""); sendCommand("t0.txt=\"1 Listening\"");
sendCommandAction(61U); sendCommandAction(61U);
if (m_screenLayout == 2U) { if (m_screenLayout & LAYOUT_TA_ENABLE) {
if (m_screenLayout & LAYOUT_TA_COLOUR)
sendCommand("t0.pco=0"); sendCommand("t0.pco=0");
if (m_screenLayout & LAYOUT_TA_FONTSIZE)
sendCommand("t0.font=4"); sendCommand("t0.font=4");
} }
@ -529,8 +474,10 @@ void CNextion::clearDMRInt(unsigned int slotNo)
sendCommand("t2.txt=\"2 Listening\""); sendCommand("t2.txt=\"2 Listening\"");
sendCommandAction(69U); sendCommandAction(69U);
if (m_screenLayout == 2U) { if (m_screenLayout & LAYOUT_TA_ENABLE) {
if (m_screenLayout & LAYOUT_TA_COLOUR)
sendCommand("t2.pco=0"); sendCommand("t2.pco=0");
if (m_screenLayout & LAYOUT_TA_FONTSIZE)
sendCommand("t2.font=4"); sendCommand("t2.font=4");
} }
@ -540,264 +487,6 @@ void CNextion::clearDMRInt(unsigned int slotNo)
} }
} }
void CNextion::writeFusionInt(const char* source, const char* dest, const char* type, const char* origin)
{
assert(source != NULL);
assert(dest != NULL);
assert(type != NULL);
assert(origin != NULL);
if (m_mode != MODE_YSF) {
sendCommand("page YSF");
sendCommandAction(4U);
}
char text[30U];
if (m_brightness>0) {
::sprintf(text, "dim=%u", m_brightness);
sendCommand(text);
}
::sprintf(text, "t0.txt=\"%s %.10s\"", type, source);
sendCommand(text);
sendCommandAction(82U);
::sprintf(text, "t1.txt=\"%.10s\"", dest);
sendCommand(text);
sendCommandAction(83U);
if (::strcmp(origin, " ") != 0) {
::sprintf(text, "t2.txt=\"at %.10s\"", origin);
sendCommand(text);
sendCommandAction(84U);
}
m_clockDisplayTimer.stop();
m_mode = MODE_YSF;
m_rssiAccum1 = 0U;
m_berAccum1 = 0.0F;
m_rssiCount1 = 0U;
m_berCount1 = 0U;
}
void CNextion::writeFusionRSSIInt(unsigned char rssi)
{
m_rssiAccum1 += rssi;
m_rssiCount1++;
if (m_rssiCount1 == YSF_RSSI_COUNT) {
char text[25U];
::sprintf(text, "t3.txt=\"-%udBm\"", m_rssiAccum1 / YSF_RSSI_COUNT);
sendCommand(text);
sendCommandAction(85U);
m_rssiAccum1 = 0U;
m_rssiCount1 = 0U;
}
}
void CNextion::writeFusionBERInt(float ber)
{
m_berAccum1 += ber;
m_berCount1++;
if (m_berCount1 == YSF_BER_COUNT) {
char text[25U];
::sprintf(text, "t4.txt=\"%.1f%%\"", m_berAccum1 / float(YSF_BER_COUNT));
sendCommand(text);
sendCommandAction(86U);
m_berAccum1 = 0.0F;
m_berCount1 = 0U;
}
}
void CNextion::clearFusionInt()
{
sendCommand("t0.txt=\"Listening\"");
sendCommandAction(81U);
sendCommand("t1.txt=\"\"");
sendCommand("t2.txt=\"\"");
sendCommand("t3.txt=\"\"");
sendCommand("t4.txt=\"\"");
}
void CNextion::writeP25Int(const char* source, bool group, unsigned int dest, const char* type)
{
assert(source != NULL);
assert(type != NULL);
if (m_mode != MODE_P25) {
sendCommand("page P25");
sendCommandAction(5U);
}
char text[30U];
if (m_brightness>0) {
::sprintf(text, "dim=%u", m_brightness);
sendCommand(text);
}
::sprintf(text, "t0.txt=\"%s %.10s\"", type, source);
sendCommand(text);
sendCommandAction(102U);
::sprintf(text, "t1.txt=\"%s%u\"", group ? "TG" : "", dest);
sendCommand(text);
sendCommandAction(103U);
m_clockDisplayTimer.stop();
m_mode = MODE_P25;
m_rssiAccum1 = 0U;
m_berAccum1 = 0.0F;
m_rssiCount1 = 0U;
m_berCount1 = 0U;
}
void CNextion::writeP25RSSIInt(unsigned char rssi)
{
m_rssiAccum1 += rssi;
m_rssiCount1++;
if (m_rssiCount1 == P25_RSSI_COUNT) {
char text[25U];
::sprintf(text, "t2.txt=\"-%udBm\"", m_rssiAccum1 / P25_RSSI_COUNT);
sendCommand(text);
sendCommandAction(104U);
m_rssiAccum1 = 0U;
m_rssiCount1 = 0U;
}
}
void CNextion::writeP25BERInt(float ber)
{
m_berAccum1 += ber;
m_berCount1++;
if (m_berCount1 == P25_BER_COUNT) {
char text[25U];
::sprintf(text, "t3.txt=\"%.1f%%\"", m_berAccum1 / float(P25_BER_COUNT));
sendCommand(text);
sendCommandAction(105U);
m_berAccum1 = 0.0F;
m_berCount1 = 0U;
}
}
void CNextion::clearP25Int()
{
sendCommand("t0.txt=\"Listening\"");
sendCommandAction(101U);
sendCommand("t1.txt=\"\"");
sendCommand("t2.txt=\"\"");
sendCommand("t3.txt=\"\"");
}
void CNextion::writeNXDNInt(const char* source, bool group, unsigned int dest, const char* type)
{
assert(source != NULL);
assert(type != NULL);
if (m_mode != MODE_NXDN) {
sendCommand("page NXDN");
sendCommandAction(6U);
}
char text[30U];
if (m_brightness>0) {
::sprintf(text, "dim=%u", m_brightness);
sendCommand(text);
}
::sprintf(text, "t0.txt=\"%s %.10s\"", type, source);
sendCommand(text);
sendCommandAction(122U);
::sprintf(text, "t1.txt=\"%s%u\"", group ? "TG" : "", dest);
sendCommand(text);
sendCommandAction(123U);
m_clockDisplayTimer.stop();
m_mode = MODE_NXDN;
m_rssiAccum1 = 0U;
m_berAccum1 = 0.0F;
m_rssiCount1 = 0U;
m_berCount1 = 0U;
}
void CNextion::writeNXDNRSSIInt(unsigned char rssi)
{
m_rssiAccum1 += rssi;
m_rssiCount1++;
if (m_rssiCount1 == NXDN_RSSI_COUNT) {
char text[25U];
::sprintf(text, "t2.txt=\"-%udBm\"", m_rssiAccum1 / NXDN_RSSI_COUNT);
sendCommand(text);
sendCommandAction(124U);
m_rssiAccum1 = 0U;
m_rssiCount1 = 0U;
}
}
void CNextion::writeNXDNBERInt(float ber)
{
m_berAccum1 += ber;
m_berCount1++;
if (m_berCount1 == NXDN_BER_COUNT) {
char text[25U];
::sprintf(text, "t3.txt=\"%.1f%%\"", m_berAccum1 / float(NXDN_BER_COUNT));
sendCommand(text);
sendCommandAction(125U);
m_berAccum1 = 0.0F;
m_berCount1 = 0U;
}
}
void CNextion::clearNXDNInt()
{
sendCommand("t0.txt=\"Listening\"");
sendCommandAction(121U);
sendCommand("t1.txt=\"\"");
sendCommand("t2.txt=\"\"");
sendCommand("t3.txt=\"\"");
}
void CNextion::writePOCSAGInt(uint32_t ric, const std::string& message)
{
if (m_mode != MODE_POCSAG) {
sendCommand("page POCSAG");
sendCommandAction(7U);
}
char text[200U];
if (m_brightness>0) {
::sprintf(text, "dim=%u", m_brightness);
sendCommand(text);
}
::sprintf(text, "t0.txt=\"RIC: %u\"", ric);
sendCommand(text);
sendCommandAction(132U);
::sprintf(text, "t1.txt=\"%s\"", message.c_str());
sendCommand(text);
sendCommandAction(133U);
m_clockDisplayTimer.stop();
m_mode = MODE_POCSAG;
}
void CNextion::clearPOCSAGInt()
{
sendCommand("t0.txt=\"Waiting\"");
sendCommandAction(134U);
sendCommand("t1.txt=\"\"");
}
void CNextion::writeCWInt() void CNextion::writeCWInt()
{ {
sendCommand("t1.txt=\"Sending CW Ident\""); sendCommand("t1.txt=\"Sending CW Ident\"");
@ -844,7 +533,7 @@ void CNextion::close()
void CNextion::sendCommandAction(unsigned int status) void CNextion::sendCommandAction(unsigned int status)
{ {
if (m_screenLayout<3U) if (!(m_screenLayout & LAYOUT_DIY))
return; return;
char text[30U]; char text[30U];
@ -863,4 +552,4 @@ void CNextion::sendCommand(const char* command)
// we must add a bit of a delay to allow the display to process the commands, else some are getting mangled. // we must add a bit of a delay to allow the display to process the commands, else some are getting mangled.
// 10 ms is just a guess, but seems to be sufficient. // 10 ms is just a guess, but seems to be sufficient.
CThread::sleep(10U); CThread::sleep(10U);
} }

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2016,2017,2018 by Jonathan Naylor G4KLX * Copyright (C) 2016,2017,2018,2020 by Jonathan Naylor G4KLX
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@ -29,7 +29,7 @@
class CNextion : public CDisplay class CNextion : public CDisplay
{ {
public: public:
CNextion(const std::string& callsign, unsigned int dmrid, ISerialPort* serial, unsigned int brightness, bool displayClock, bool utc, unsigned int idleBrightness, unsigned int screenLayout, unsigned int txFrequency, unsigned int rxFrequency, bool displayTempInF, const std::string& location); CNextion(const std::string& callsign, unsigned int dmrid, ISerialPort* serial, unsigned int brightness, bool displayClock, bool utc, unsigned int idleBrightness, unsigned int screenLayout, unsigned int txFrequency, unsigned int rxFrequency, bool displayTempInF);
virtual ~CNextion(); virtual ~CNextion();
virtual bool open(); virtual bool open();
@ -42,11 +42,6 @@ protected:
virtual void setLockoutInt(); virtual void setLockoutInt();
virtual void setQuitInt(); virtual void setQuitInt();
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 writeDStarBERInt(float ber);
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 writeDMRTAInt(unsigned int slotNo, unsigned char* talkerAlias, const char* type); virtual void writeDMRTAInt(unsigned int slotNo, unsigned char* talkerAlias, const char* type);
@ -54,24 +49,6 @@ protected:
virtual void writeDMRBERInt(unsigned int slotNo, float ber); virtual void writeDMRBERInt(unsigned int slotNo, float ber);
virtual void clearDMRInt(unsigned int slotNo); virtual void clearDMRInt(unsigned int slotNo);
virtual void writeFusionInt(const char* source, const char* dest, const char* type, const char* origin);
virtual void writeFusionRSSIInt(unsigned char rssi);
virtual void writeFusionBERInt(float ber);
virtual void clearFusionInt();
virtual void writeP25Int(const char* source, bool group, unsigned int dest, const char* type);
virtual void writeP25RSSIInt(unsigned char rssi);
virtual void writeP25BERInt(float ber);
virtual void clearP25Int();
virtual void writeNXDNInt(const char* source, bool group, unsigned int dest, const char* type);
virtual void writeNXDNRSSIInt(unsigned char rssi);
virtual void writeNXDNBERInt(float ber);
virtual void clearNXDNInt();
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();
@ -99,10 +76,9 @@ private:
unsigned int m_berCount2; unsigned int m_berCount2;
unsigned int m_txFrequency; unsigned int m_txFrequency;
unsigned int m_rxFrequency; unsigned int m_rxFrequency;
float m_fl_txFrequency; double m_fl_txFrequency;
float m_fl_rxFrequency; double m_fl_rxFrequency;
bool m_displayTempInF; bool m_displayTempInF;
std::string m_location;
void sendCommand(const char* command); void sendCommand(const char* command);
void sendCommandAction(unsigned int status); void sendCommandAction(unsigned int status);

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