PyFT8 3.0.0__tar.gz → 3.0.2__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (29) hide show
  1. {pyft8-3.0.0 → pyft8-3.0.2}/PKG-INFO +4 -3
  2. {pyft8-3.0.0 → pyft8-3.0.2}/PyFT8/databases.py +3 -3
  3. {pyft8-3.0.0 → pyft8-3.0.2}/PyFT8/pskreporter.py +2 -1
  4. {pyft8-3.0.0 → pyft8-3.0.2}/PyFT8/pyft8.py +1 -1
  5. {pyft8-3.0.0 → pyft8-3.0.2}/PyFT8/transmitter.py +68 -36
  6. {pyft8-3.0.0 → pyft8-3.0.2}/PyFT8.egg-info/PKG-INFO +4 -3
  7. {pyft8-3.0.0 → pyft8-3.0.2}/README.md +3 -2
  8. {pyft8-3.0.0 → pyft8-3.0.2}/pyproject.toml +1 -1
  9. {pyft8-3.0.0 → pyft8-3.0.2}/LICENSE +0 -0
  10. {pyft8-3.0.0 → pyft8-3.0.2}/MANIFEST.in +0 -0
  11. {pyft8-3.0.0 → pyft8-3.0.2}/PyFT8/__init__.py +0 -0
  12. {pyft8-3.0.0 → pyft8-3.0.2}/PyFT8/gui.py +0 -0
  13. {pyft8-3.0.0 → pyft8-3.0.2}/PyFT8/receiver.py +0 -0
  14. {pyft8-3.0.0 → pyft8-3.0.2}/PyFT8/rigctrl.py +0 -0
  15. {pyft8-3.0.0 → pyft8-3.0.2}/PyFT8/time_utils.py +0 -0
  16. {pyft8-3.0.0 → pyft8-3.0.2}/PyFT8.egg-info/SOURCES.txt +0 -0
  17. {pyft8-3.0.0 → pyft8-3.0.2}/PyFT8.egg-info/dependency_links.txt +0 -0
  18. {pyft8-3.0.0 → pyft8-3.0.2}/PyFT8.egg-info/entry_points.txt +0 -0
  19. {pyft8-3.0.0 → pyft8-3.0.2}/PyFT8.egg-info/requires.txt +0 -0
  20. {pyft8-3.0.0 → pyft8-3.0.2}/PyFT8.egg-info/top_level.txt +0 -0
  21. {pyft8-3.0.0 → pyft8-3.0.2}/setup.cfg +0 -0
  22. {pyft8-3.0.0 → pyft8-3.0.2}/tests/dev/CQ AAAA.py +0 -0
  23. {pyft8-3.0.0 → pyft8-3.0.2}/tests/dev/osd.py +0 -0
  24. {pyft8-3.0.0 → pyft8-3.0.2}/tests/dev/test_generate_wav.py +0 -0
  25. {pyft8-3.0.0 → pyft8-3.0.2}/tests/dev/test_loopback_performance.py +0 -0
  26. {pyft8-3.0.0 → pyft8-3.0.2}/tests/dev/view_worked_before.py +0 -0
  27. {pyft8-3.0.0 → pyft8-3.0.2}/tests/plot_baseline.py +0 -0
  28. {pyft8-3.0.0 → pyft8-3.0.2}/tests/spare.py +0 -0
  29. {pyft8-3.0.0 → pyft8-3.0.2}/tests/test_batch_and_live.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: PyFT8
3
- Version: 3.0.0
3
+ Version: 3.0.2
4
4
  Summary: FT8 Decoding and Encoding in Python with test/loopback code
5
5
  Author-email: G1OJS <g1ojs@yahoo.com>
6
6
  License-Expression: GPL-3.0-or-later
@@ -27,7 +27,8 @@ PyFT8 is somewhat experimental, with a focus on demonstrating FT8 written in Pyt
27
27
  If you're interested in how this works, maybe have a look at [MiniPyFT8](https://github.com/G1OJS/MiniPyFT8) which puts all of the receive code in a single 300 line Python file.
28
28
 
29
29
  ## Features
30
- - Rx and Tx of standard messages with optional /P and /R, and nonstandard calls plus hashed calls
30
+ - Rx and Tx of standard messages with optional /P and /R
31
+ - RX of nonstandard calls plus hashed calls
31
32
  - Launches quickly (~2 seconds on my old Dell Optiplex 790)
32
33
  - Use with or without gui (receive and send messages via command line commands)
33
34
  - Automatically chooses clearest Tx frequency
@@ -127,7 +128,7 @@ PyFT8 doesn't decode / encode *all* message types. The table below shows which a
127
128
  |1|Std Msg |Y| Y |Standard <=6 char callsigns, can include /R |
128
129
  |2|EU VHF |Y|Y| Standard <=6 char callsigns, can include /P |
129
130
  |3|RTTY RU | | | |
130
- |4|NonStd Call |Y|Y| <=11 char callsigns + hashed call|
131
+ |4|NonStd Call |Y|N| <=11 char callsigns + hashed call|
131
132
  |5|EU VHF | | | |
132
133
 
133
134
  ## Acknowledgements
@@ -1,7 +1,7 @@
1
1
  from PyFT8.pskreporter import PSKR_MQTT_listener
2
2
  import threading, time, os, pickle, json
3
3
 
4
- call_hashes = {}
4
+ call_hashes, hashes_for_calls = {}, {}
5
5
 
6
6
  def add_call_hashes(call):
7
7
  global call_hashes
@@ -17,9 +17,9 @@ def add_call_hashes(call):
17
17
  x = x * 47055833459
18
18
  x = x & ((1 << 64) - 1)
19
19
  x = x >> (64 - m)
20
- hashes.append(x)
20
+ hashes.append((x, m))
21
21
  call_hashes[(x, m)] = call
22
- return hashes
22
+ hashes_for_calls[call] = hashes
23
23
 
24
24
  def grid_to_latlong(grid, centre = True):
25
25
  lat, lon = -90, -180
@@ -9,7 +9,8 @@ class PSKR_MQTT_listener:
9
9
  def __init__(self, home_square, on_spot):
10
10
  self.home_square = home_square
11
11
  self.on_spot = on_spot
12
- mqttc = mqtt.Client(mqtt.CallbackAPIVersion.VERSION2)
12
+ client_id = "PyFT8_" + ''.join(random.choice('0123456789ABCDEF') for i in range(16))
13
+ mqttc = mqtt.Client(mqtt.CallbackAPIVersion.VERSION2, client_id)
13
14
  mqttc.on_connect = self.on_connect
14
15
  mqttc.on_message = self.on_message
15
16
  try:
@@ -12,7 +12,7 @@ from PyFT8.time_utils import global_time_utils
12
12
  from PyFT8.rigctrl import Rig_hamlib
13
13
  from PyFT8.databases import History, ADIF
14
14
 
15
- VER = '3.0.0'
15
+ VER = '3.0.2'
16
16
 
17
17
  MAX_TX_START_SECONDS = 2.5
18
18
  HEARING_PANEL_LIFE_MINS = 20
@@ -2,7 +2,7 @@ import numpy as np
2
2
  import wave
3
3
  import pyaudio
4
4
  import time
5
- from PyFT8.databases import add_call_hashes
5
+ from PyFT8.databases import hashes_for_calls, add_call_hashes
6
6
 
7
7
  #==================== AUDIO OUT ================================================================
8
8
 
@@ -56,35 +56,42 @@ class AudioOut:
56
56
  stream.stop_stream()
57
57
  stream.close()
58
58
 
59
- #==================== PACK AND ENCODE ================================================================
60
- generator_matrix_rows = ["8329ce11bf31eaf509f27fc", "761c264e25c259335493132", "dc265902fb277c6410a1bdc", "1b3f417858cd2dd33ec7f62", "09fda4fee04195fd034783a", "077cccc11b8873ed5c3d48a", "29b62afe3ca036f4fe1a9da", "6054faf5f35d96d3b0c8c3e", "e20798e4310eed27884ae90", "775c9c08e80e26ddae56318", "b0b811028c2bf997213487c", "18a0c9231fc60adf5c5ea32", "76471e8302a0721e01b12b8", "ffbccb80ca8341fafb47b2e", "66a72a158f9325a2bf67170", "c4243689fe85b1c51363a18", "0dff739414d1a1b34b1c270", "15b48830636c8b99894972e", "29a89c0d3de81d665489b0e", "4f126f37fa51cbe61bd6b94", "99c47239d0d97d3c84e0940", "1919b75119765621bb4f1e8", "09db12d731faee0b86df6b8", "488fc33df43fbdeea4eafb4", "827423ee40b675f756eb5fe", "abe197c484cb74757144a9a", "2b500e4bc0ec5a6d2bdbdd0", "c474aa53d70218761669360", "8eba1a13db3390bd6718cec", "753844673a27782cc42012e", "06ff83a145c37035a5c1268", "3b37417858cc2dd33ec3f62", "9a4a5a28ee17ca9c324842c", "bc29f465309c977e89610a4", "2663ae6ddf8b5ce2bb29488", "46f231efe457034c1814418", "3fb2ce85abe9b0c72e06fbe", "de87481f282c153971a0a2e", "fcd7ccf23c69fa99bba1412", "f0261447e9490ca8e474cec", "4410115818196f95cdd7012", "088fc31df4bfbde2a4eafb4", "b8fef1b6307729fb0a078c0", "5afea7acccb77bbc9d99a90", "49a7016ac653f65ecdc9076", "1944d085be4e7da8d6cc7d0", "251f62adc4032f0ee714002", "56471f8702a0721e00b12b8", "2b8e4923f2dd51e2d537fa0", "6b550a40a66f4755de95c26", "a18ad28d4e27fe92a4f6c84", "10c2e586388cb82a3d80758", "ef34a41817ee02133db2eb0", "7e9c0c54325a9c15836e000", "3693e572d1fde4cdf079e86", "bfb2cec5abe1b0c72e07fbe", "7ee18230c583cccc57d4b08", "a066cb2fedafc9f52664126", "bb23725abc47cc5f4cc4cd2", "ded9dba3bee40c59b5609b4", "d9a7016ac653e6decdc9036", "9ad46aed5f707f280ab5fc4", "e5921c77822587316d7d3c2", "4f14da8242a8b86dca73352", "8b8b507ad467d4441df770e", "22831c9cf1169467ad04b68", "213b838fe2ae54c38ee7180", "5d926b6dd71f085181a4e12", "66ab79d4b29ee6e69509e56", "958148682d748a38dd68baa", "b8ce020cf069c32a723ab14", "f4331d6d461607e95752746", "6da23ba424b9596133cf9c8", "a636bcbc7b30c5fbeae67fe", "5cb0d86a07df654a9089a20", "f11f106848780fc9ecdd80a", "1fbb5364fb8d2c9d730d5ba", "fcb86bc70a50c9d02a5d034", "a534433029eac15f322e34c", "c989d9c7c3d3b8c55d75130", "7bb38b2f0186d46643ae962", "2644ebadeb44b9467d1f42c", "608cc857594bfbb55d69600"]
61
- kGEN = np.array([int(row,16)>>1 for row in generator_matrix_rows])
59
+ #==================== PACK ================================================================
60
+
61
+ def ifindex(arr, val, default = None):
62
+ return arr.index(val) if val in arr else default
62
63
 
63
64
  def pack_message(c1, c2, gr):
64
65
  symbols, bits77 = _pack_message(c1, c2, gr)
65
66
  return symbols
66
67
 
67
68
  def _pack_message(c1, c2, gr):
68
- c28a, p1a = pack_ft8_c28(c1)
69
- c28b, p1b = pack_ft8_c28(c2)
69
+ c29a, c29b = pack_ft8_c29(c1), pack_ft8_c29(c2)
70
70
  g15, ir = pack_ft8_g15(gr)
71
- i3 = 2 if c1.endswith('/P') or c2.endswith('/P') else 1
72
- n3 = 0
73
- if(c28a>=0 and c28b>=0):
71
+ if c29a and c29b:
72
+ c28a, p1a = c29a
73
+ c28b, p1b = c29b
74
+ i3 = 2 if c1.endswith('/P') or c2.endswith('/P') else 1
75
+ n3 = 0
76
+ bits77 = (c28a<<28+1+1+1+15+3) | (p1a<<28+1+1+15+3) | (c28b<<1+1+15+3) | (p1b <<1+15+3) | (ir<<15+3) | (g15<< 3) | (i3)
77
+ symbols = encode_bits77(bits77)
78
+ if c29b and not c29a:
79
+ add_call_hashes(c1)
80
+ c28a, p1a = 2063592 + hashes_for_calls[c1][2][0], 0
81
+ c28b, p1b = c29b
82
+ i3 = 2 if c2.endswith('/P') else 1
83
+ n3 = 0
74
84
  bits77 = (c28a<<28+1+1+1+15+3) | (p1a<<28+1+1+15+3) | (c28b<<1+1+15+3) | (p1b <<1+15+3) | (ir<<15+3) | (g15<< 3) | (i3)
75
85
  symbols = encode_bits77(bits77)
76
- else:
77
- i3 = 4
78
- full_call = c1 if c28b>0 else c2
79
- hash_call = c2 if c28b>0 else c1
80
- c58 = pack_ft8_c58(full_call)
81
- hashes = add_call_hashes(hash_call)
82
- swp = 1 if hash_call == c2 else 0
83
- rrr, cq_ = 0, 0
84
- if gr in ('RRR', 'RR73', '73'):
85
- rrr = ('', 'RRR', 'RR73', '73').index(gr)
86
- bits77 = (hashes[1]<<58+1+2+1+3) | (c58 <<1+2+1+3) | (swp<<2+1+3) | (rrr<<1+3) | (cq_<<3) | (i3)
86
+ if c29a and not c29b:
87
+ add_call_hashes(c2)
88
+ c28b, p1b = 2063592 + hashes_for_calls[c2][2][0], 0
89
+ c28a, p1a = c29a
90
+ i3 = 2 if c1.endswith('/P') else 1
91
+ n3 = 0
92
+ bits77 = (c28a<<28+1+1+1+15+3) | (p1a<<28+1+1+15+3) | (c28b<<1+1+15+3) | (p1b <<1+15+3) | (ir<<15+3) | (g15<< 3) | (i3)
87
93
  symbols = encode_bits77(bits77)
94
+
88
95
  return symbols, bits77
89
96
 
90
97
 
@@ -96,24 +103,23 @@ def pack_ft8_c58(call):
96
103
  n58 = n58*38 + chars.index(call[i])
97
104
  return n58
98
105
 
99
- def pack_ft8_c28(call):
100
- if '/' in call and not call.endswith("P") and not call.endswith("R"): return -1, 0
101
- tkns = ['DE','QRZ','CQ']
102
- if (call in tkns):
103
- c28, p1 = tkns.index(call), 0
104
- else:
106
+ def pack_ft8_c29(call):
107
+ if '/' not in call or call.endswith("P") or call.endswith("R"):
108
+ t = ifindex(['DE','QRZ','CQ'], call)
109
+ if t is not None:
110
+ return t, 0
105
111
  p1 = 1 if call[-2:] in ('/P', '/R') else 0
106
112
  call = call.replace('/P','').replace('/R','')
107
- if len(call) > 6:
108
- return -1, 0
109
- prepend_space = '' if call[2].isdigit() else ' '
110
- call = (prepend_space + call + ' ')[:6]
111
- a = ' 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ'
112
- b = ' ABCDEFGHIJKLMNOPQRSTUVWXYZ'
113
- x = [a.index(call[0]), a.index(call[1])-1, a.index(call[2])-1, b.index(call[3]), b.index(call[4]), b.index(call[5]), 1 ]
114
- y = [36*10*27*27*27, 10*27*27*27, 27*27*27, 27*27, 27, 1, 2_063_592 + 4_194_304]
115
- c28 = int(np.dot(x,y))
116
- return c28, p1
113
+ if len(call) <= 6:
114
+ prepend_space = '' if call[2].isdigit() else ' '
115
+ call = (prepend_space + call + ' ')[:6]
116
+ a = ' 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ'
117
+ b = ' ABCDEFGHIJKLMNOPQRSTUVWXYZ'
118
+ x = [ifindex(a, call[0]), ifindex(a[1:], call[1]), ifindex(a[1:], call[2]), ifindex(b, call[3]), ifindex(b, call[4]), ifindex(b, call[5]), 1 ]
119
+ if not None in x:
120
+ y = [36*10*27*27*27, 10*27*27*27, 27*27*27, 27*27, 27, 1, 2_063_592 + 4_194_304]
121
+ c28 = int(np.dot(x,y))
122
+ return c28, p1
117
123
 
118
124
  def pack_ft8_g15(txt):
119
125
  ir = 0
@@ -138,6 +144,11 @@ def pack_ft8_g15(txt):
138
144
  v = v * 10 + int(txt[3])
139
145
  return int(v), ir
140
146
 
147
+ #============ ENCODE ========================================================================================================================
148
+
149
+ generator_matrix_rows = ["8329ce11bf31eaf509f27fc", "761c264e25c259335493132", "dc265902fb277c6410a1bdc", "1b3f417858cd2dd33ec7f62", "09fda4fee04195fd034783a", "077cccc11b8873ed5c3d48a", "29b62afe3ca036f4fe1a9da", "6054faf5f35d96d3b0c8c3e", "e20798e4310eed27884ae90", "775c9c08e80e26ddae56318", "b0b811028c2bf997213487c", "18a0c9231fc60adf5c5ea32", "76471e8302a0721e01b12b8", "ffbccb80ca8341fafb47b2e", "66a72a158f9325a2bf67170", "c4243689fe85b1c51363a18", "0dff739414d1a1b34b1c270", "15b48830636c8b99894972e", "29a89c0d3de81d665489b0e", "4f126f37fa51cbe61bd6b94", "99c47239d0d97d3c84e0940", "1919b75119765621bb4f1e8", "09db12d731faee0b86df6b8", "488fc33df43fbdeea4eafb4", "827423ee40b675f756eb5fe", "abe197c484cb74757144a9a", "2b500e4bc0ec5a6d2bdbdd0", "c474aa53d70218761669360", "8eba1a13db3390bd6718cec", "753844673a27782cc42012e", "06ff83a145c37035a5c1268", "3b37417858cc2dd33ec3f62", "9a4a5a28ee17ca9c324842c", "bc29f465309c977e89610a4", "2663ae6ddf8b5ce2bb29488", "46f231efe457034c1814418", "3fb2ce85abe9b0c72e06fbe", "de87481f282c153971a0a2e", "fcd7ccf23c69fa99bba1412", "f0261447e9490ca8e474cec", "4410115818196f95cdd7012", "088fc31df4bfbde2a4eafb4", "b8fef1b6307729fb0a078c0", "5afea7acccb77bbc9d99a90", "49a7016ac653f65ecdc9076", "1944d085be4e7da8d6cc7d0", "251f62adc4032f0ee714002", "56471f8702a0721e00b12b8", "2b8e4923f2dd51e2d537fa0", "6b550a40a66f4755de95c26", "a18ad28d4e27fe92a4f6c84", "10c2e586388cb82a3d80758", "ef34a41817ee02133db2eb0", "7e9c0c54325a9c15836e000", "3693e572d1fde4cdf079e86", "bfb2cec5abe1b0c72e07fbe", "7ee18230c583cccc57d4b08", "a066cb2fedafc9f52664126", "bb23725abc47cc5f4cc4cd2", "ded9dba3bee40c59b5609b4", "d9a7016ac653e6decdc9036", "9ad46aed5f707f280ab5fc4", "e5921c77822587316d7d3c2", "4f14da8242a8b86dca73352", "8b8b507ad467d4441df770e", "22831c9cf1169467ad04b68", "213b838fe2ae54c38ee7180", "5d926b6dd71f085181a4e12", "66ab79d4b29ee6e69509e56", "958148682d748a38dd68baa", "b8ce020cf069c32a723ab14", "f4331d6d461607e95752746", "6da23ba424b9596133cf9c8", "a636bcbc7b30c5fbeae67fe", "5cb0d86a07df654a9089a20", "f11f106848780fc9ecdd80a", "1fbb5364fb8d2c9d730d5ba", "fcb86bc70a50c9d02a5d034", "a534433029eac15f322e34c", "c989d9c7c3d3b8c55d75130", "7bb38b2f0186d46643ae962", "2644ebadeb44b9467d1f42c", "608cc857594bfbb55d69600"]
150
+ kGEN = np.array([int(row,16)>>1 for row in generator_matrix_rows])
151
+
141
152
  def ldpc_encode(msg_crc: int) -> int:
142
153
  msg_crc = int(msg_crc)
143
154
  parity_bits = 0
@@ -182,6 +193,8 @@ def append_crc(bits77_int):
182
193
  #==================== TESTS ================================================================
183
194
 
184
195
  if __name__ == "__main__":
196
+
197
+ print("Test standard calls")
185
198
  OK = True
186
199
  msgs = [("G1OJS/P", "G1OJS/P", "IO90"),("WM3PEN","EA6VQ","+08"),("E67A/P","EA6VQ","R-08"),
187
200
  ("CQ","CT7ARQ/P","JO03"), ("EC5A","9A5E","RR73"), ("EC5A/P","9A5E","73"), ("EC5A/MM","9A5E","73"),
@@ -195,5 +208,24 @@ if __name__ == "__main__":
195
208
  #print(''.join([str(s) for s in symbols]))
196
209
  print("\nPASSED" if OK else "\nFAILED")
197
210
 
211
+ print("\nTest non-standard calls")
212
+ OK = True
213
+ msgs = [("SX200M","G1OJS","IO90"),
214
+ ("G1OJS","SX200M","CB21"),
215
+ ("CQ","SX200M","CB21")]
216
+ expected_symbols = ["3140652203407700750145313654745000003140652276403052651370607066332604363140652",
217
+ "",
218
+ "3140652564261623472565070174400214333140652601351750040163007617513443213140652"]
219
+ for i, msg_tx in enumerate(msgs):
220
+ symbols, bits77 = _pack_message(*msg_tx)
221
+ from PyFT8.receiver import unpack
222
+ msg_rx = unpack(bits77)
223
+ print(f"\n{msg_tx}\n{msg_rx}")
224
+ OK = OK and (msg_tx == msg_rx) or 'implemented' in msg_rx
225
+ print(f"exp: {expected_symbols[i]}")
226
+ print(f"gen: {''.join([str(s) for s in symbols])}")
227
+ print("\nPASSED" if OK else "\nFAILED")
228
+
229
+ print("\nUnpack 'CQ DX G1OJS IO90'")
198
230
  print(unpack(int('00000000000000000100011011110000010010000000000111000001100011111000010010001',2)))
199
231
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: PyFT8
3
- Version: 3.0.0
3
+ Version: 3.0.2
4
4
  Summary: FT8 Decoding and Encoding in Python with test/loopback code
5
5
  Author-email: G1OJS <g1ojs@yahoo.com>
6
6
  License-Expression: GPL-3.0-or-later
@@ -27,7 +27,8 @@ PyFT8 is somewhat experimental, with a focus on demonstrating FT8 written in Pyt
27
27
  If you're interested in how this works, maybe have a look at [MiniPyFT8](https://github.com/G1OJS/MiniPyFT8) which puts all of the receive code in a single 300 line Python file.
28
28
 
29
29
  ## Features
30
- - Rx and Tx of standard messages with optional /P and /R, and nonstandard calls plus hashed calls
30
+ - Rx and Tx of standard messages with optional /P and /R
31
+ - RX of nonstandard calls plus hashed calls
31
32
  - Launches quickly (~2 seconds on my old Dell Optiplex 790)
32
33
  - Use with or without gui (receive and send messages via command line commands)
33
34
  - Automatically chooses clearest Tx frequency
@@ -127,7 +128,7 @@ PyFT8 doesn't decode / encode *all* message types. The table below shows which a
127
128
  |1|Std Msg |Y| Y |Standard <=6 char callsigns, can include /R |
128
129
  |2|EU VHF |Y|Y| Standard <=6 char callsigns, can include /P |
129
130
  |3|RTTY RU | | | |
130
- |4|NonStd Call |Y|Y| <=11 char callsigns + hashed call|
131
+ |4|NonStd Call |Y|N| <=11 char callsigns + hashed call|
131
132
  |5|EU VHF | | | |
132
133
 
133
134
  ## Acknowledgements
@@ -8,7 +8,8 @@ PyFT8 is somewhat experimental, with a focus on demonstrating FT8 written in Pyt
8
8
  If you're interested in how this works, maybe have a look at [MiniPyFT8](https://github.com/G1OJS/MiniPyFT8) which puts all of the receive code in a single 300 line Python file.
9
9
 
10
10
  ## Features
11
- - Rx and Tx of standard messages with optional /P and /R, and nonstandard calls plus hashed calls
11
+ - Rx and Tx of standard messages with optional /P and /R
12
+ - RX of nonstandard calls plus hashed calls
12
13
  - Launches quickly (~2 seconds on my old Dell Optiplex 790)
13
14
  - Use with or without gui (receive and send messages via command line commands)
14
15
  - Automatically chooses clearest Tx frequency
@@ -108,7 +109,7 @@ PyFT8 doesn't decode / encode *all* message types. The table below shows which a
108
109
  |1|Std Msg |Y| Y |Standard <=6 char callsigns, can include /R |
109
110
  |2|EU VHF |Y|Y| Standard <=6 char callsigns, can include /P |
110
111
  |3|RTTY RU | | | |
111
- |4|NonStd Call |Y|Y| <=11 char callsigns + hashed call|
112
+ |4|NonStd Call |Y|N| <=11 char callsigns + hashed call|
112
113
  |5|EU VHF | | | |
113
114
 
114
115
  ## Acknowledgements
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "PyFT8"
3
- version = "3.0.0"
3
+ version = "3.0.2"
4
4
  license = "GPL-3.0-or-later"
5
5
 
6
6
  authors = [
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes