JTEncode.cpp 25 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015
  1. /*
  2. * JTEncode.cpp - JT65/JT9/WSPR/FSQ encoder library for Arduino
  3. *
  4. * Copyright (C) 2015-2016 Jason Milldrum <milldrum@gmail.com>
  5. *
  6. * Based on the algorithms presented in the WSJT software suite.
  7. * Thanks to Andy Talbot G4JNT for the whitepaper on the WSPR encoding
  8. * process that helped me to understand all of this.
  9. *
  10. * This program is free software: you can redistribute it and/or modify
  11. * it under the terms of the GNU General Public License as published by
  12. * the Free Software Foundation, either version 3 of the License, or
  13. * (at your option) any later version.
  14. *
  15. * This program is distributed in the hope that it will be useful,
  16. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  17. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  18. * GNU General Public License for more details.
  19. *
  20. * You should have received a copy of the GNU General Public License
  21. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  22. */
  23. #include "JTEncode.h"
  24. #include <string.h>
  25. #include <ctype.h>
  26. #include <stdlib.h>
  27. #include <stdint.h>
  28. #include <stdio.h>
  29. #if defined(__AVR_ATmega328P__) || defined(__AVR_ATmega168__) || defined(__AVR_ATmega32U4__) || defined(__AVR_ATmega16U4__)
  30. #include <avr/pgmspace.h>
  31. #endif
  32. #include "Arduino.h"
  33. // Define an upper bound on the number of glyphs. Defining it this
  34. // way allows adding characters without having to update a hard-coded
  35. // upper bound.
  36. #define NGLYPHS (sizeof(fsq_code_table)/sizeof(fsq_code_table[0]))
  37. /* Public Class Members */
  38. JTEncode::JTEncode(void)
  39. {
  40. // Initialize the Reed-Solomon encoder
  41. rs_inst = (struct rs *)(intptr_t)init_rs_int(6, 0x43, 3, 1, 51, 0);
  42. }
  43. /*
  44. * jt65_encode(const char * msg, uint8_t * symbols)
  45. *
  46. * Takes an arbitrary message of up to 13 allowable characters and returns
  47. * a channel symbol table.
  48. *
  49. * message - Plaintext Type 6 message.
  50. * symbols - Array of channel symbols to transmit retunred by the method.
  51. * Ensure that you pass a uint8_t array of size JT65_SYMBOL_COUNT to the method.
  52. *
  53. */
  54. void JTEncode::jt65_encode(const char * msg, uint8_t * symbols)
  55. {
  56. char message[14];
  57. memset(message, 0, 14);
  58. strcpy(message, msg);
  59. // Ensure that the message text conforms to standards
  60. // --------------------------------------------------
  61. jt_message_prep(message);
  62. // Bit packing
  63. // -----------
  64. uint8_t c[12];
  65. jt65_bit_packing(message, c);
  66. // Reed-Solomon encoding
  67. // ---------------------
  68. uint8_t s[JT65_ENCODE_COUNT];
  69. rs_encode(c, s);
  70. // Interleaving
  71. // ------------
  72. jt65_interleave(s);
  73. // Gray Code
  74. // ---------
  75. jt_gray_code(s, JT65_ENCODE_COUNT);
  76. // Merge with sync vector
  77. // ----------------------
  78. jt65_merge_sync_vector(s, symbols);
  79. }
  80. /*
  81. * jt9_encode(const char * msg, uint8_t * symbols)
  82. *
  83. * Takes an arbitrary message of up to 13 allowable characters and returns
  84. * a channel symbol table.
  85. *
  86. * message - Plaintext Type 6 message.
  87. * symbols - Array of channel symbols to transmit retunred by the method.
  88. * Ensure that you pass a uint8_t array of size JT9_SYMBOL_COUNT to the method.
  89. *
  90. */
  91. void JTEncode::jt9_encode(const char * msg, uint8_t * symbols)
  92. {
  93. char message[14];
  94. memset(message, 0, 14);
  95. strcpy(message, msg);
  96. // Ensure that the message text conforms to standards
  97. // --------------------------------------------------
  98. jt_message_prep(message);
  99. // Bit packing
  100. // -----------
  101. uint8_t c[13];
  102. jt9_bit_packing(message, c);
  103. // Convolutional Encoding
  104. // ---------------------
  105. uint8_t s[JT9_BIT_COUNT];
  106. convolve(c, s, 13, JT9_BIT_COUNT);
  107. // Interleaving
  108. // ------------
  109. jt9_interleave(s);
  110. // Pack into 3-bit symbols
  111. // -----------------------
  112. uint8_t a[JT9_ENCODE_COUNT];
  113. jt9_packbits(s, a);
  114. // Gray Code
  115. // ---------
  116. jt_gray_code(a, JT9_ENCODE_COUNT);
  117. // Merge with sync vector
  118. // ----------------------
  119. jt9_merge_sync_vector(a, symbols);
  120. }
  121. /*
  122. * jt4_encode(const char * msg, uint8_t * symbols)
  123. *
  124. * Takes an arbitrary message of up to 13 allowable characters and returns
  125. * a channel symbol table.
  126. *
  127. * message - Plaintext Type 6 message.
  128. * symbols - Array of channel symbols to transmit retunred by the method.
  129. * Ensure that you pass a uint8_t array of size JT4_SYMBOL_COUNT to the method.
  130. *
  131. */
  132. void JTEncode::jt4_encode(const char * msg, uint8_t * symbols)
  133. {
  134. char message[14];
  135. memset(message, 0, 14);
  136. strcpy(message, msg);
  137. // Ensure that the message text conforms to standards
  138. // --------------------------------------------------
  139. jt_message_prep(message);
  140. // Bit packing
  141. // -----------
  142. uint8_t c[13];
  143. jt9_bit_packing(message, c);
  144. // Convolutional Encoding
  145. // ---------------------
  146. uint8_t s[JT4_SYMBOL_COUNT];
  147. convolve(c, s, 13, JT4_BIT_COUNT);
  148. // Interleaving
  149. // ------------
  150. jt9_interleave(s);
  151. memmove(s + 1, s, JT4_BIT_COUNT);
  152. s[0] = 0; // Append a 0 bit to start of sequence
  153. // Merge with sync vector
  154. // ----------------------
  155. jt4_merge_sync_vector(s, symbols);
  156. }
  157. /*
  158. * wspr_encode(const char * call, const char * loc, const uint8_t dbm, uint8_t * symbols)
  159. *
  160. * Takes an arbitrary message of up to 13 allowable characters and returns
  161. *
  162. * call - Callsign (6 characters maximum).
  163. * loc - Maidenhead grid locator (4 charcters maximum).
  164. * dbm - Output power in dBm.
  165. * symbols - Array of channel symbols to transmit retunred by the method.
  166. * Ensure that you pass a uint8_t array of size WSPR_SYMBOL_COUNT to the method.
  167. *
  168. */
  169. void JTEncode::wspr_encode(const char * call, const char * loc, const uint8_t dbm, uint8_t * symbols)
  170. {
  171. char call_[7];
  172. char loc_[5];
  173. uint8_t dbm_ = dbm;
  174. strcpy(call_, call);
  175. strcpy(loc_, loc);
  176. // Ensure that the message text conforms to standards
  177. // --------------------------------------------------
  178. wspr_message_prep(call_, loc_, dbm_);
  179. // Bit packing
  180. // -----------
  181. uint8_t c[11];
  182. wspr_bit_packing(c);
  183. // Convolutional Encoding
  184. // ---------------------
  185. uint8_t s[WSPR_SYMBOL_COUNT];
  186. convolve(c, s, 11, WSPR_BIT_COUNT);
  187. // Interleaving
  188. // ------------
  189. wspr_interleave(s);
  190. // Merge with sync vector
  191. // ----------------------
  192. wspr_merge_sync_vector(s, symbols);
  193. }
  194. /*
  195. * fsq_encode(const char * from_call, const char * message, uint8_t * symbols)
  196. *
  197. * Takes an arbitrary message and returns a FSQ channel symbol table.
  198. *
  199. * from_call - Callsign of issuing station (maximum size: 20)
  200. * message - Null-terminated message string, no greater than 130 chars in length
  201. * symbols - Array of channel symbols to transmit retunred by the method.
  202. * Ensure that you pass a uint8_t array of at least the size of the message
  203. * plus 5 characters to the method. Terminated in 0xFF.
  204. *
  205. */
  206. void JTEncode::fsq_encode(const char * from_call, const char * message, uint8_t * symbols)
  207. {
  208. char tx_buffer[155];
  209. char * tx_message;
  210. uint16_t symbol_pos = 0;
  211. uint8_t i, fch, vcode1, vcode2, tone;
  212. uint8_t cur_tone = 0;
  213. // Clear out the transmit buffer
  214. // -----------------------------
  215. memset(tx_buffer, 0, 155);
  216. // Create the message to be transmitted
  217. // ------------------------------------
  218. sprintf(tx_buffer, " \n%s: %s", from_call, message);
  219. tx_message = tx_buffer;
  220. // Iterate through the message and encode
  221. // --------------------------------------
  222. while(*tx_message != '\0')
  223. {
  224. for(i = 0; i < NGLYPHS; i++)
  225. {
  226. uint8_t ch = (uint8_t)*tx_message;
  227. // Check each element of the varicode table to see if we've found the
  228. // character we're trying to send.
  229. fch = pgm_read_byte(&fsq_code_table[i].ch);
  230. if(fch == ch)
  231. {
  232. // Found the character, now fetch the varicode chars
  233. vcode1 = pgm_read_byte(&(fsq_code_table[i].var[0]));
  234. vcode2 = pgm_read_byte(&(fsq_code_table[i].var[1]));
  235. // Transmit the appropriate tone per a varicode char
  236. if(vcode2 == 0)
  237. {
  238. // If the 2nd varicode char is a 0 in the table,
  239. // we are transmitting a lowercase character, and thus
  240. // only transmit one tone for this character.
  241. // Generate tone
  242. cur_tone = ((cur_tone + vcode1 + 1) % 33);
  243. symbols[symbol_pos++] = cur_tone;
  244. }
  245. else
  246. {
  247. // If the 2nd varicode char is anything other than 0 in
  248. // the table, then we need to transmit both
  249. // Generate 1st tone
  250. cur_tone = ((cur_tone + vcode1 + 1) % 33);
  251. symbols[symbol_pos++] = cur_tone;
  252. // Generate 2nd tone
  253. cur_tone = ((cur_tone + vcode2 + 1) % 33);
  254. symbols[symbol_pos++] = cur_tone;
  255. }
  256. break; // We've found and transmitted the char,
  257. // so exit the for loop
  258. }
  259. }
  260. tx_message++;
  261. }
  262. // Message termination
  263. // ----------------
  264. symbols[symbol_pos] = 0xff;
  265. }
  266. /*
  267. * fsq_dir_encode(const char * from_call, const char * to_call, const char cmd, const char * message, uint8_t * symbols)
  268. *
  269. * Takes an arbitrary message and returns a FSQ channel symbol table.
  270. *
  271. * from_call - Callsign from which message is directed (maximum size: 20)
  272. * to_call - Callsign to which message is directed (maximum size: 20)
  273. * cmd - Directed command
  274. * message - Null-terminated message string, no greater than 100 chars in length
  275. * symbols - Array of channel symbols to transmit retunred by the method.
  276. * Ensure that you pass a uint8_t array of at least the size of the message
  277. * plus 5 characters to the method. Terminated in 0xFF.
  278. *
  279. */
  280. void JTEncode::fsq_dir_encode(const char * from_call, const char * to_call, const char cmd, const char * message, uint8_t * symbols)
  281. {
  282. char tx_buffer[155];
  283. char * tx_message;
  284. uint16_t symbol_pos = 0;
  285. uint8_t i, fch, vcode1, vcode2, tone, from_call_crc;
  286. uint8_t cur_tone = 0;
  287. // Generate a CRC on from_call
  288. // ---------------------------
  289. from_call_crc = crc8(from_call);
  290. // Clear out the transmit buffer
  291. // -----------------------------
  292. memset(tx_buffer, 0, 155);
  293. // Create the message to be transmitted
  294. // We are building a directed message here.
  295. // FSQ very specifically needs " \b " in
  296. // directed mode to indicate EOT. A single backspace won't do it.
  297. sprintf(tx_buffer, " \n%s:%02x%s%c%s%s", from_call, from_call_crc, to_call, cmd, message, " \b ");
  298. tx_message = tx_buffer;
  299. // Iterate through the message and encode
  300. // --------------------------------------
  301. while(*tx_message != '\0')
  302. {
  303. for(i = 0; i < NGLYPHS; i++)
  304. {
  305. uint8_t ch = (uint8_t)*tx_message;
  306. // Check each element of the varicode table to see if we've found the
  307. // character we're trying to send.
  308. fch = pgm_read_byte(&fsq_code_table[i].ch);
  309. if(fch == ch)
  310. {
  311. // Found the character, now fetch the varicode chars
  312. vcode1 = pgm_read_byte(&(fsq_code_table[i].var[0]));
  313. vcode2 = pgm_read_byte(&(fsq_code_table[i].var[1]));
  314. // Transmit the appropriate tone per a varicode char
  315. if(vcode2 == 0)
  316. {
  317. // If the 2nd varicode char is a 0 in the table,
  318. // we are transmitting a lowercase character, and thus
  319. // only transmit one tone for this character.
  320. // Generate tone
  321. cur_tone = ((cur_tone + vcode1 + 1) % 33);
  322. symbols[symbol_pos++] = cur_tone;
  323. }
  324. else
  325. {
  326. // If the 2nd varicode char is anything other than 0 in
  327. // the table, then we need to transmit both
  328. // Generate 1st tone
  329. cur_tone = ((cur_tone + vcode1 + 1) % 33);
  330. symbols[symbol_pos++] = cur_tone;
  331. // Generate 2nd tone
  332. cur_tone = ((cur_tone + vcode2 + 1) % 33);
  333. symbols[symbol_pos++] = cur_tone;
  334. }
  335. break; // We've found and transmitted the char,
  336. // so exit the for loop
  337. }
  338. }
  339. tx_message++;
  340. }
  341. // Message termination
  342. // ----------------
  343. symbols[symbol_pos] = 0xff;
  344. }
  345. /* Private Class Members */
  346. uint8_t JTEncode::jt_code(char c)
  347. {
  348. // Validate the input then return the proper integer code.
  349. // Return 255 as an error code if the char is not allowed.
  350. if(isdigit(c))
  351. {
  352. return (uint8_t)(c - 48);
  353. }
  354. else if(c >= 'A' && c <= 'Z')
  355. {
  356. return (uint8_t)(c - 55);
  357. }
  358. else if(c == ' ')
  359. {
  360. return 36;
  361. }
  362. else if(c == '+')
  363. {
  364. return 37;
  365. }
  366. else if(c == '-')
  367. {
  368. return 38;
  369. }
  370. else if(c == '.')
  371. {
  372. return 39;
  373. }
  374. else if(c == '/')
  375. {
  376. return 40;
  377. }
  378. else if(c == '?')
  379. {
  380. return 41;
  381. }
  382. else
  383. {
  384. return 255;
  385. }
  386. }
  387. uint8_t JTEncode::wspr_code(char c)
  388. {
  389. // Validate the input then return the proper integer code.
  390. // Return 255 as an error code if the char is not allowed.
  391. if(isdigit(c))
  392. {
  393. return (uint8_t)(c - 48);
  394. }
  395. else if(c == ' ')
  396. {
  397. return 36;
  398. }
  399. else if(c >= 'A' && c <= 'Z')
  400. {
  401. return (uint8_t)(c - 55);
  402. }
  403. else
  404. {
  405. return 255;
  406. }
  407. }
  408. uint8_t JTEncode::gray_code(uint8_t c)
  409. {
  410. return (c >> 1) ^ c;
  411. }
  412. void JTEncode::jt_message_prep(char * message)
  413. {
  414. uint8_t i;
  415. // Pad the message with trailing spaces
  416. uint8_t len = strlen(message);
  417. if(len < 13)
  418. {
  419. for(i = len; i <= 13; i++)
  420. {
  421. message[i] = ' ';
  422. }
  423. }
  424. // Convert all chars to uppercase
  425. for(i = 0; i < 13; i++)
  426. {
  427. if(islower(message[i]))
  428. {
  429. message[i] = toupper(message[i]);
  430. }
  431. }
  432. }
  433. void JTEncode::wspr_message_prep(char * call, char * loc, uint8_t dbm)
  434. {
  435. // Callsign validation and padding
  436. // -------------------------------
  437. // If only the 2nd character is a digit, then pad with a space.
  438. // If this happens, then the callsign will be truncated if it is
  439. // longer than 5 characters.
  440. if((call[1] >= '0' && call[1] <= '9') && (call[2] < '0' || call[2] > '9'))
  441. {
  442. memmove(call + 1, call, 5);
  443. call[0] = ' ';
  444. }
  445. // Now the 3rd charcter in the callsign must be a digit
  446. if(call[2] < '0' || call[2] > '9')
  447. {
  448. // TODO: need a better way to handle this
  449. call[2] = '0';
  450. }
  451. // Ensure that the only allowed characters are digits and
  452. // uppercase letters
  453. uint8_t i;
  454. for(i = 0; i < 6; i++)
  455. {
  456. call[i] = toupper(call[i]);
  457. if(!(isdigit(call[i]) || isupper(call[i])))
  458. {
  459. call[i] = ' ';
  460. }
  461. }
  462. memcpy(callsign, call, 6);
  463. // Grid locator validation
  464. for(i = 0; i < 4; i++)
  465. {
  466. loc[i] = toupper(loc[i]);
  467. if(!(isdigit(loc[i]) || (loc[i] >= 'A' && loc[i] <= 'R')))
  468. {
  469. memcpy(loc, "AA00", 5);
  470. //loc = "AA00";
  471. }
  472. }
  473. memcpy(locator, loc, 4);
  474. // Power level validation
  475. // Only certain increments are allowed
  476. if(dbm > 60)
  477. {
  478. dbm = 60;
  479. }
  480. const uint8_t valid_dbm[19] =
  481. {0, 3, 7, 10, 13, 17, 20, 23, 27, 30, 33, 37, 40,
  482. 43, 47, 50, 53, 57, 60};
  483. for(i = 0; i < 19; i++)
  484. {
  485. if(dbm == valid_dbm[i])
  486. {
  487. power = dbm;
  488. }
  489. }
  490. // If we got this far, we have an invalid power level, so we'll round down
  491. for(i = 1; i < 19; i++)
  492. {
  493. if(dbm < valid_dbm[i] && dbm >= valid_dbm[i - 1])
  494. {
  495. power = valid_dbm[i - 1];
  496. }
  497. }
  498. }
  499. void JTEncode::jt65_bit_packing(char * message, uint8_t * c)
  500. {
  501. uint32_t n1, n2, n3;
  502. // Find the N values
  503. n1 = jt_code(message[0]);
  504. n1 = n1 * 42 + jt_code(message[1]);
  505. n1 = n1 * 42 + jt_code(message[2]);
  506. n1 = n1 * 42 + jt_code(message[3]);
  507. n1 = n1 * 42 + jt_code(message[4]);
  508. n2 = jt_code(message[5]);
  509. n2 = n2 * 42 + jt_code(message[6]);
  510. n2 = n2 * 42 + jt_code(message[7]);
  511. n2 = n2 * 42 + jt_code(message[8]);
  512. n2 = n2 * 42 + jt_code(message[9]);
  513. n3 = jt_code(message[10]);
  514. n3 = n3 * 42 + jt_code(message[11]);
  515. n3 = n3 * 42 + jt_code(message[12]);
  516. // Pack bits 15 and 16 of N3 into N1 and N2,
  517. // then mask reset of N3 bits
  518. n1 = (n1 << 1) + ((n3 >> 15) & 1);
  519. n2 = (n2 << 1) + ((n3 >> 16) & 1);
  520. n3 = n3 & 0x7fff;
  521. // Set the freeform message flag
  522. n3 += 32768;
  523. c[0] = (n1 >> 22) & 0x003f;
  524. c[1] = (n1 >> 16) & 0x003f;
  525. c[2] = (n1 >> 10) & 0x003f;
  526. c[3] = (n1 >> 4) & 0x003f;
  527. c[4] = ((n1 & 0x000f) << 2) + ((n2 >> 26) & 0x0003);
  528. c[5] = (n2 >> 20) & 0x003f;
  529. c[6] = (n2 >> 14) & 0x003f;
  530. c[7] = (n2 >> 8) & 0x003f;
  531. c[8] = (n2 >> 2) & 0x003f;
  532. c[9] = ((n2 & 0x0003) << 4) + ((n3 >> 12) & 0x000f);
  533. c[10] = (n3 >> 6) & 0x003f;
  534. c[11] = n3 & 0x003f;
  535. }
  536. void JTEncode::jt9_bit_packing(char * message, uint8_t * c)
  537. {
  538. uint32_t n1, n2, n3;
  539. // Find the N values
  540. n1 = jt_code(message[0]);
  541. n1 = n1 * 42 + jt_code(message[1]);
  542. n1 = n1 * 42 + jt_code(message[2]);
  543. n1 = n1 * 42 + jt_code(message[3]);
  544. n1 = n1 * 42 + jt_code(message[4]);
  545. n2 = jt_code(message[5]);
  546. n2 = n2 * 42 + jt_code(message[6]);
  547. n2 = n2 * 42 + jt_code(message[7]);
  548. n2 = n2 * 42 + jt_code(message[8]);
  549. n2 = n2 * 42 + jt_code(message[9]);
  550. n3 = jt_code(message[10]);
  551. n3 = n3 * 42 + jt_code(message[11]);
  552. n3 = n3 * 42 + jt_code(message[12]);
  553. // Pack bits 15 and 16 of N3 into N1 and N2,
  554. // then mask reset of N3 bits
  555. n1 = (n1 << 1) + ((n3 >> 15) & 1);
  556. n2 = (n2 << 1) + ((n3 >> 16) & 1);
  557. n3 = n3 & 0x7fff;
  558. // Set the freeform message flag
  559. n3 += 32768;
  560. // 71 message bits to pack, plus 1 bit flag for freeform message.
  561. // 31 zero bits appended to end.
  562. // N1 and N2 are 28 bits each, N3 is 16 bits
  563. // A little less work to start with the least-significant bits
  564. c[3] = (uint8_t)((n1 & 0x0f) << 4);
  565. n1 = n1 >> 4;
  566. c[2] = (uint8_t)(n1 & 0xff);
  567. n1 = n1 >> 8;
  568. c[1] = (uint8_t)(n1 & 0xff);
  569. n1 = n1 >> 8;
  570. c[0] = (uint8_t)(n1 & 0xff);
  571. c[6] = (uint8_t)(n2 & 0xff);
  572. n2 = n2 >> 8;
  573. c[5] = (uint8_t)(n2 & 0xff);
  574. n2 = n2 >> 8;
  575. c[4] = (uint8_t)(n2 & 0xff);
  576. n2 = n2 >> 8;
  577. c[3] |= (uint8_t)(n2 & 0x0f);
  578. c[8] = (uint8_t)(n3 & 0xff);
  579. n3 = n3 >> 8;
  580. c[7] = (uint8_t)(n3 & 0xff);
  581. c[9] = 0;
  582. c[10] = 0;
  583. c[11] = 0;
  584. c[12] = 0;
  585. }
  586. void JTEncode::wspr_bit_packing(uint8_t * c)
  587. {
  588. uint32_t n, m;
  589. n = wspr_code(callsign[0]);
  590. n = n * 36 + wspr_code(callsign[1]);
  591. n = n * 10 + wspr_code(callsign[2]);
  592. n = n * 27 + (wspr_code(callsign[3]) - 10);
  593. n = n * 27 + (wspr_code(callsign[4]) - 10);
  594. n = n * 27 + (wspr_code(callsign[5]) - 10);
  595. m = ((179 - 10 * (locator[0] - 'A') - (locator[2] - '0')) * 180) +
  596. (10 * (locator[1] - 'A')) + (locator[3] - '0');
  597. m = (m * 128) + power + 64;
  598. // Callsign is 28 bits, locator/power is 22 bits.
  599. // A little less work to start with the least-significant bits
  600. c[3] = (uint8_t)((n & 0x0f) << 4);
  601. n = n >> 4;
  602. c[2] = (uint8_t)(n & 0xff);
  603. n = n >> 8;
  604. c[1] = (uint8_t)(n & 0xff);
  605. n = n >> 8;
  606. c[0] = (uint8_t)(n & 0xff);
  607. c[6] = (uint8_t)((m & 0x03) << 6);
  608. m = m >> 2;
  609. c[5] = (uint8_t)(m & 0xff);
  610. m = m >> 8;
  611. c[4] = (uint8_t)(m & 0xff);
  612. m = m >> 8;
  613. c[3] |= (uint8_t)(m & 0x0f);
  614. c[7] = 0;
  615. c[8] = 0;
  616. c[9] = 0;
  617. c[10] = 0;
  618. }
  619. void JTEncode::jt65_interleave(uint8_t * s)
  620. {
  621. uint8_t i, j;
  622. uint8_t d[JT65_ENCODE_COUNT];
  623. // Interleave
  624. for(i = 0; i < 9; i++)
  625. {
  626. for(j = 0; j < 7; j++)
  627. {
  628. d[(j * 9) + i] = s[(i * 7) + j];
  629. }
  630. }
  631. memcpy(s, d, JT65_ENCODE_COUNT);
  632. }
  633. void JTEncode::jt9_interleave(uint8_t * s)
  634. {
  635. uint8_t i, j;
  636. uint8_t d[JT9_BIT_COUNT];
  637. // Do the interleave
  638. for(i = 0; i < JT9_BIT_COUNT; i++)
  639. {
  640. //#if defined(__AVR_ATmega328P__) || defined(__AVR_ATmega168__) || defined(__AVR_ATmega32U4__) || defined(__AVR_ATmega16U4__)
  641. #if defined(__arm__)
  642. d[jt9i[i]] = s[i];
  643. #else
  644. j = pgm_read_byte(&jt9i[i]);
  645. d[j] = s[i];
  646. #endif
  647. }
  648. memcpy(s, d, JT9_BIT_COUNT);
  649. }
  650. void JTEncode::wspr_interleave(uint8_t * s)
  651. {
  652. uint8_t d[WSPR_BIT_COUNT];
  653. uint8_t rev, index_temp, i, j, k;
  654. i = 0;
  655. for(j = 0; j < 255; j++)
  656. {
  657. // Bit reverse the index
  658. index_temp = j;
  659. rev = 0;
  660. for(k = 0; k < 8; k++)
  661. {
  662. if(index_temp & 0x01)
  663. {
  664. rev = rev | (1 << (7 - k));
  665. }
  666. index_temp = index_temp >> 1;
  667. }
  668. if(rev < WSPR_BIT_COUNT)
  669. {
  670. d[rev] = s[i];
  671. i++;
  672. }
  673. if(i >= WSPR_BIT_COUNT)
  674. {
  675. break;
  676. }
  677. }
  678. memcpy(s, d, WSPR_BIT_COUNT);
  679. }
  680. void JTEncode::jt9_packbits(uint8_t * d, uint8_t * a)
  681. {
  682. uint8_t i, k;
  683. k = 0;
  684. memset(a, 0, JT9_ENCODE_COUNT);
  685. for(i = 0; i < JT9_ENCODE_COUNT; i++)
  686. {
  687. a[i] = (d[k] & 1) << 2;
  688. k++;
  689. a[i] |= ((d[k] & 1) << 1);
  690. k++;
  691. a[i] |= (d[k] & 1);
  692. k++;
  693. }
  694. }
  695. void JTEncode::jt_gray_code(uint8_t * g, uint8_t symbol_count)
  696. {
  697. uint8_t i;
  698. for(i = 0; i < symbol_count; i++)
  699. {
  700. g[i] = gray_code(g[i]);
  701. }
  702. }
  703. void JTEncode::jt65_merge_sync_vector(uint8_t * g, uint8_t * symbols)
  704. {
  705. uint8_t i, j = 0;
  706. const uint8_t sync_vector[JT65_SYMBOL_COUNT] =
  707. {1, 0, 0, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0, 0,
  708. 0, 1, 0, 1, 1, 0, 0, 1, 0, 0, 0, 1, 1, 1, 0, 0, 1, 1, 1, 1,
  709. 0, 1, 1, 0, 1, 1, 1, 1, 0, 0, 0, 1, 1, 0, 1, 0, 1, 0, 1, 1,
  710. 0, 0, 1, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1,
  711. 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1,
  712. 0, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 1,
  713. 1, 1, 1, 1, 1, 1};
  714. for(i = 0; i < JT65_SYMBOL_COUNT; i++)
  715. {
  716. if(sync_vector[i])
  717. {
  718. symbols[i] = 0;
  719. }
  720. else
  721. {
  722. symbols[i] = g[j] + 2;
  723. j++;
  724. }
  725. }
  726. }
  727. void JTEncode::jt9_merge_sync_vector(uint8_t * g, uint8_t * symbols)
  728. {
  729. uint8_t i, j = 0;
  730. const uint8_t sync_vector[JT9_SYMBOL_COUNT] =
  731. {1, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0,
  732. 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0,
  733. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 1,
  734. 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,
  735. 0, 0, 1, 0, 1};
  736. for(i = 0; i < JT9_SYMBOL_COUNT; i++)
  737. {
  738. if(sync_vector[i])
  739. {
  740. symbols[i] = 0;
  741. }
  742. else
  743. {
  744. symbols[i] = g[j] + 1;
  745. j++;
  746. }
  747. }
  748. }
  749. void JTEncode::jt4_merge_sync_vector(uint8_t * g, uint8_t * symbols)
  750. {
  751. uint8_t i;
  752. const uint8_t sync_vector[JT4_SYMBOL_COUNT] =
  753. {0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 0, 1, 1, 0, 0, 1, 0, 1, 0, 0, 0,
  754. 0, 0, 0, 0, 1, 1, 0, 0, 0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,1 ,0 ,1 ,1,
  755. 0, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0,
  756. 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 1, 1, 1, 0, 1, 1, 0,
  757. 0, 1, 0, 0, 0, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 0,
  758. 1, 0, 1, 0, 1, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 0, 1, 0, 1, 1, 0, 1,
  759. 1, 1, 1, 0, 0, 0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 1, 1, 1, 0, 1, 1, 1,
  760. 0, 1, 1, 1, 0, 0, 1, 0, 0, 0, 1, 1, 0, 1, 1, 0, 0, 1, 0, 0, 0, 1,
  761. 1, 1, 1, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 1, 1,
  762. 0, 1, 1, 1, 1, 0, 1, 0, 1};
  763. for(i = 0; i < JT4_SYMBOL_COUNT; i++)
  764. {
  765. symbols[i] = sync_vector[i] + (2 * g[i]);
  766. }
  767. }
  768. void JTEncode::wspr_merge_sync_vector(uint8_t * g, uint8_t * symbols)
  769. {
  770. uint8_t i;
  771. const uint8_t sync_vector[WSPR_SYMBOL_COUNT] =
  772. {1, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 1, 0, 0, 0, 1, 0, 0,
  773. 1, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 1, 0, 0,
  774. 0, 0, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 0, 1, 1, 0, 1,
  775. 0, 0, 0, 0, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 0, 1, 0,
  776. 1, 1, 0, 0, 0, 1, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1,
  777. 0, 0, 1, 0, 0, 1, 1, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 0, 1,
  778. 1, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0,
  779. 1, 1, 0, 1, 0, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0};
  780. for(i = 0; i < WSPR_SYMBOL_COUNT; i++)
  781. {
  782. symbols[i] = sync_vector[i] + (2 * g[i]);
  783. }
  784. }
  785. void JTEncode::convolve(uint8_t * c, uint8_t * s, uint8_t message_size, uint8_t bit_size)
  786. {
  787. uint32_t reg_0 = 0;
  788. uint32_t reg_1 = 0;
  789. uint32_t reg_temp = 0;
  790. uint8_t input_bit, parity_bit;
  791. uint8_t bit_count = 0;
  792. uint8_t i, j, k;
  793. for(i = 0; i < message_size; i++)
  794. {
  795. for(j = 0; j < 8; j++)
  796. {
  797. // Set input bit according the MSB of current element
  798. input_bit = (((c[i] << j) & 0x80) == 0x80) ? 1 : 0;
  799. // Shift both registers and put in the new input bit
  800. reg_0 = reg_0 << 1;
  801. reg_1 = reg_1 << 1;
  802. reg_0 |= (uint32_t)input_bit;
  803. reg_1 |= (uint32_t)input_bit;
  804. // AND Register 0 with feedback taps, calculate parity
  805. reg_temp = reg_0 & 0xf2d05351;
  806. parity_bit = 0;
  807. for(k = 0; k < 32; k++)
  808. {
  809. parity_bit = parity_bit ^ (reg_temp & 0x01);
  810. reg_temp = reg_temp >> 1;
  811. }
  812. s[bit_count] = parity_bit;
  813. bit_count++;
  814. // AND Register 1 with feedback taps, calculate parity
  815. reg_temp = reg_1 & 0xe4613c47;
  816. parity_bit = 0;
  817. for(k = 0; k < 32; k++)
  818. {
  819. parity_bit = parity_bit ^ (reg_temp & 0x01);
  820. reg_temp = reg_temp >> 1;
  821. }
  822. s[bit_count] = parity_bit;
  823. bit_count++;
  824. if(bit_count >= bit_size)
  825. {
  826. break;
  827. }
  828. }
  829. }
  830. }
  831. void JTEncode::rs_encode(uint8_t * data, uint8_t * symbols)
  832. {
  833. // Adapted from wrapkarn.c in the WSJT-X source code
  834. uint8_t dat1[12];
  835. uint8_t b[51];
  836. uint8_t sym[JT65_ENCODE_COUNT];
  837. uint8_t i;
  838. // Reverse data order for the Karn codec.
  839. for(i = 0; i < 12; i++)
  840. {
  841. dat1[i] = data[11 - i];
  842. }
  843. // Compute the parity symbols
  844. encode_rs_int(rs_inst, dat1, b);
  845. // Move parity symbols and data into symbols array, in reverse order.
  846. for (i = 0; i < 51; i++)
  847. {
  848. sym[50 - i] = b[i];
  849. }
  850. for (i = 0; i < 12; i++)
  851. {
  852. sym[i + 51] = dat1[11 - i];
  853. }
  854. memcpy(symbols, sym, JT65_ENCODE_COUNT);
  855. }
  856. uint8_t JTEncode::crc8(const char * text)
  857. {
  858. uint8_t crc = '\0';
  859. uint8_t ch;
  860. int i;
  861. for(i = 0; i < strlen(text); i++)
  862. {
  863. ch = text[i];
  864. //#if defined(__AVR_ATmega328P__) || defined(__AVR_ATmega168__) || defined(__AVR_ATmega32U4__) || defined(__AVR_ATmega16U4__)
  865. #if defined(__arm__)
  866. crc = crc8_table[(crc) ^ ch];
  867. #else
  868. crc = pgm_read_byte(&(crc8_table[(crc) ^ ch]));
  869. #endif
  870. crc &= 0xFF;
  871. }
  872. return crc;
  873. }