diff --git a/decoder/base128.py b/decoder/base128.py new file mode 100644 index 0000000..b61bfac --- /dev/null +++ b/decoder/base128.py @@ -0,0 +1,126 @@ +# Copyright 2013-2016 Alex Danilo +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# Base 128/192 encoding experiment. +# +# Ths is just a quick experiment to see what sort of speed we get by encoding +# a contiguous 128 value range in bytes that replaces base 64 with it's low level +# conditionals and bit-bashing for decode. +# +# Ultimately, the encoding I'd like to use is a 192 value encoding which yields +# 7.5 bits/byte - i.e. approx. 6.66% loss encoding binary data in a text-safe +# transfer form. The 128 value coding is just to test the basis of the +# speed and compressibility of the result and is easy to use in JS. The 192 +# value encoding is more efficient but likely a lot trickier to use from JS. +# +# NB: This is using ISO-9959-1 as it's basis. The source code will break if you +# try to view as UTF-8. + + +# The decode table reverses the encoding back to bits. Note, that since the most we can encode is 7.5 bits, we can never +# generate 0xFF in the decode so use that to mark 0xFF encoding bytes. + +import struct + +dtab = [ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 187, 0xFF, 188, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 189, 190, 0xFF, 0xFF, 0xFF, + 191, 0xFE, 0xFF, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, + 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, + 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, + 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 0xFF, 57, 58, 59, + 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, + 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, + 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, + 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, + 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, + 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, + 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186 +] + +# Reserve " (0x3E) as delimiter for easy manipulation in JS, '!' as stuffing character and generation for JS - the ranges 23->7E then A0->FF create the encoding. +# That's enough for the base 128 version but we need 4 more characters to encode 7.5 bits/byte so the last set is carefully chosen from within +# the control character range using values that are safe for editors. +etab = "#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~\xA0\xA1\xA2\xA3\xA4\xA5\xA6\xA7\xA8\xA9\xAA\xAB\xAC\xAD\xAE\xAF\xB0\xB1\xB2\xB3\xB4\xB5\xB6\xB7\xB8\xB9\xBA\xBB\xBC\xBD\xBE\xBF\xC0\xC1\xC2\xC3\xC4\xC5\xC6\xC7\xC8\xC9\xCA\xCB\xCC\xCD\xCE\xCF\xD0\xD1\xD2\xD3\xD4\xD5\xD6\xD7\xD8\xD9\xDA\xDB\xDC\xDD\xDE\xDF\xE0\xE1\xE2\xE3\xE4\xE5\xE6\xE7\xE8\xE9\xEA\xEB\xEC\xED\xEE\xEF\xF0\xF1\xF2\xF3\xF4\xF5\xF6\xF7\xF8\xF9\xFA\xFB\xFC\xFD\xFE\xFF\t\x0B\x1B\x1C "; + +INBYTES = 7 +OUTBYTES = 8 + +def encode(infile): + outfile = '' + k = 0 + + while k < len(infile): + _len = 0 + _in = [] + for i in range(INBYTES): + _in.append(infile[k]) + k += 1 + _len += 1 + if k >= len(infile): + break + + if _len > 0: + topbits = 0 + mask = 0x40 + for i in range(_len): + outfile += etab[_in[i] & 0x7F] + if _in[i] > 0x7F: + topbits |= mask + mask >>= 1 + + if _len < INBYTES: + outfile += '!' + + outfile += etab[topbits] + + return outfile + +def decode(infile): + out = bytearray() + k = 0 + + while k < len(infile): + _len = 0 + _in = [] + for i in range(OUTBYTES): + _in.append(ord(infile[k])) + k += 1 + _len += 1; + if k >= len(infile): + break + + if _len > 0: + topbits = dtab[_in[_len - 1]] + mask = 0x40 + _len = 0 + for i in range(len(_in)-1): + if _in[i] == 0x21: + break + _len += 1 + _in[i] = dtab[_in[i]] + if _in[i] == 0xFF: + return 0 + if topbits & mask: + _in[i] |= 0x80 + mask >>= 1 + + for i in range(_len): + out += struct.pack('B', _in[i]) + + return out + diff --git a/decoder/base192.py b/decoder/base192.py new file mode 100644 index 0000000..54f3d7c --- /dev/null +++ b/decoder/base192.py @@ -0,0 +1,148 @@ +# Copyright 2013-2016 Alex Danilo +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# Base 128/192 encoding experiment. +# +# Ths is just a quick experiment to see what sort of speed we get by encoding +# a contiguous 128 value range in bytes that replaces base 64 with it's low level +# conditionals and bit-bashing for decode. +# +# Ultimately, the encoding I'd like to use is a 192 value encoding which yields +# 7.5 bits/byte - i.e. approx. 6.66% loss encoding binary data in a text-safe +# transfer form. The 128 value coding is just to test the basis of the +# speed and compressibility of the result and is easy to use in JS. The 192 +# value encoding is more efficient but likely a lot trickier to use from JS. +# +# NB: This is using ISO-9959-1 as it's basis. The source code will break if you +# try to view as UTF-8. + + +# The decode table reverses the encoding back to bits. Note, that since the most we can encode is 7.5 bits, we can never +# generate 0xFF in the decode so use that to mark 0xFF encoding bytes. +dtab = [ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 187, 0xFF, 188, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 189, 190, 0xFF, 0xFF, 0xFF, + 191, 0xFE, 0xFF, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, + 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, + 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, + 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 0xFF, 57, 58, 59, + 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, + 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, + 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, + 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, + 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, + 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, + 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186 +] + +# Reserve " (0x3E) as delimiter for easy manipulation in JS, '!' as stuffing character and generation for JS - the ranges 23->7E then A0->FF create the encoding. +# That's enough for the base 128 version but we need 4 more characters to encode 7.5 bits/byte so the last set is carefully chosen from within +# the control character range using values that are safe for editors. +etab = "#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~\xA0\xA1\xA2\xA3\xA4\xA5\xA6\xA7\xA8\xA9\xAA\xAB\xAC\xAD\xAE\xAF\xB0\xB1\xB2\xB3\xB4\xB5\xB6\xB7\xB8\xB9\xBA\xBB\xBC\xBD\xBE\xBF\xC0\xC1\xC2\xC3\xC4\xC5\xC6\xC7\xC8\xC9\xCA\xCB\xCC\xCD\xCE\xCF\xD0\xD1\xD2\xD3\xD4\xD5\xD6\xD7\xD8\xD9\xDA\xDB\xDC\xDD\xDE\xDF\xE0\xE1\xE2\xE3\xE4\xE5\xE6\xE7\xE8\xE9\xEA\xEB\xEC\xED\xEE\xEF\xF0\xF1\xF2\xF3\xF4\xF5\xF6\xF7\xF8\xF9\xFA\xFB\xFC\xFD\xFE\xFF\t\x0B\x1B\x1C "; + +BIGINBYTES = 15 +BIGOUTBYTES = 16 + +# Perform 120 bit binary number conversion into base 192 packed as bytes. +def base192_encode(_in): + out = [0]*BIGOUTBYTES + for i in range(BIGOUTBYTES): + val = _in % 192 + out[i] = val & 0xFF + _in /= 192 + return out,_in + +# Perform base 192 into binary conversion. +def base192_decode(_in): + out = 0 + i = BIGOUTBYTES - 1 + while i >= 0: + out *= 192 + out += _in[i] + i -= 1 + return out,_in + +# Encode 7.5 bits per output byte. +# +# To do this means doing a base conversion into base 192 then encode the +# digits one per byte using the encoding table. We convert 15 bytes to +# 16 this way. In order to achieve that we need to do division on +# a 120 bit number (the 15 bytes of input) to generate the base 192 digits. +# +# NB: This quick test program is assuming little-endian byte order so we +# can use the inbuilt 128 bit types for the division. For portability +# we should really use something like Knuth's arbitrary precision +# division algorithms. +def b192_encode(infile): + #int i, len, 0xFE; + value = 0 + k = 0 + outfile = '' + + while k < len(infile): + _len = 0 + for i in range(BIGINBYTES): + value += ord(infile[k]) << (i*8) + k += 1 + _len += 1 + if k == len(infile): + break + + if _len > 0: + + out,value = base192_encode(value) + _len += 1; # Always outputs 1 byte more than the input + for i in range(_len): + outfile += etab[out[i]] + + if BIGINBYTES-i > 0: # Need to mark early end with the pad character + outfile += '!' + + return outfile + +def b192_decode(infile): + value = 0 + j = 0 + outfile = [] + + while j+1 < len(infile): + _len = pad = 0 + i = -1 + _in = [] + for i in range(BIGOUTBYTES): + + if j+1 == len(infile): # Shouldn't happen for valid 0xFEded content + break + + _in.append(dtab[ord(infile[j])]) + j += 1 + + if _in[i] == 0xFF: # 0xFF character in the encoding set + return 0 + + _len += 1 + + if _len > 0: + while len(_in) < BIGOUTBYTES: # Fill MSBs with 0 - NB up to 128 bits, top 8 never used + _in.append(0) + value,_in = base192_decode(_in) + _len -= 1 # Output always shrinks by one byte + for i in range(_len): + outfile.append((value >> (i*8)) & 0xFF) + + return outfile + diff --git a/decoder/decoder.py b/decoder/decoder.py index 9f3cba6..c4426a9 100755 --- a/decoder/decoder.py +++ b/decoder/decoder.py @@ -2,7 +2,7 @@ import serial,os,re,datetime from subprocess import call -import base91 +import base128 import binascii import urllib2 import io @@ -45,8 +45,6 @@ elif args.device is not '-': # Use serial connection (probably TNC) sys.stderr.write('Error: Could not open serial port\n') sys.exit(1) - ser = io.TextIOWrapper(io.BufferedRWPair(serr, serr, 1), newline = '\r', line_buffering = True) # Define Newline as \r - # Open logging file if args.log is not None: @@ -60,25 +58,37 @@ jsons = [] def decode_callsign(code): callsign = '' - + while code > 0: s = code % 40 - if s == 0: callsign += '-' + if s == 0: callsign += '-' elif s < 11: callsign += chr(47 + s) elif s < 14: callsign += '-' else: callsign += chr(51 + s) code /= 40 - + return callsign +def encode_callsign(callsign): + x = 0 + for i in range(len(callsign)-1,-1,-1): + x *= 40 + c = ord(callsign[i]) + if c >= 65 and c <= 90: x += c - 51 + elif c >= 97 and c <= 122: x += c - 83 + elif c >= 48 and c <= 57: x += c - 47 + + return x + + + def received_data(data): global jsons - # Parse line and detect data - m = re.search("(.*)\>APECAN(.*):\{\{I(.*)", data) + m = re.search("(.*)\>APECAN(.*):\!(.*)", data) try: - call = m.group(1) - aprs = m.group(3) + call = m.group(1).split(' ')[-1] # transmitter callsign + data128 = m.group(3) # base128 encoded SSDV data (without SYNC, PacketType, Callsign, CRC, FEC) if len(m.group(2)) > 0: receiver = m.group(2).split(',')[-1] else: @@ -89,11 +99,24 @@ def received_data(data): if args.log is not None: f.write(data) # Log data to file - data = base91.decode(aprs) # Decode Base91 + data = base128.decode(data128) # Decode Base128 - if len(data) != 219: + if len(data) != 214: return # APRS message sampled too short + # Encode callsign (ensure callsign has no more than 6 chars) + bcall = call.split('-') # Split callsign and SSID + if len(bcall) == 1: # No SSID available, so take the callsign + bcall = bcall[0][0:6] + elif(len(bcall[0]) < 5): # Callsign has 4 chars, so take it with the SSID + bcall = bcall[0] + bcall[1][0:2] + elif(len(bcall[0]) < 6): # Callsign has 5 chars, so take it with the last digit of the SSID + bcall = bcall[0] + bcall[1][-1] + else: + bcall = bcall[0][0:6] # Callsign has 6 chars, so take the call without SSID + + data = binascii.unhexlify('66%08x' % encode_callsign(bcall)) + data + # Calculate CRC for SSDV server crc = binascii.crc32(data) & 0xffffffff @@ -107,7 +130,6 @@ def received_data(data): \"receiver\": \"""" + receiver + """\" }""") - call = decode_callsign(0x1000000*data[1] + 0x10000*data[2] + 0x100*data[3] + data[4]) print datetime.datetime.now().isoformat('T') + ' Received packet call %s image %d packet %d' % (call, data[5], 0x100*data[6]+data[7]) if len(jsons) >= args.grouping: # Enough packets collected, send them all to the server @@ -177,6 +199,28 @@ if args.device == 'I': # APRS-IS else: # stdin or serial while True: - data = sys.stdin.readline() if args.device is '-' else ser.readline() # Read a line + # Read data + if args.device is '-': + data = sys.stdin.readline() + else: + data = '' + while True: + b = serr.read(1) + if b == '\r' or b == '\n': + break + data += b + received_data(data) + + + + + + + + + + + + diff --git a/decoder/pecan_rx_gui/ssdv b/decoder/pecan_rx_gui/ssdv new file mode 100755 index 0000000..716d76e Binary files /dev/null and b/decoder/pecan_rx_gui/ssdv differ diff --git a/tracker/software/Makefile b/tracker/software/Makefile index 79c5272..96d2947 100644 --- a/tracker/software/Makefile +++ b/tracker/software/Makefile @@ -144,6 +144,7 @@ CSRC = $(STARTUPSRC) \ sleep.c \ threads/threads.c \ math/base.c \ + math/base128.c \ math/sgp4.c \ math/geofence.c \ config.c \ diff --git a/tracker/software/math/base128.c b/tracker/software/math/base128.c new file mode 100644 index 0000000..ab0d73e --- /dev/null +++ b/tracker/software/math/base128.c @@ -0,0 +1,119 @@ +#include + +#define PADCHAR '!' +#define INBYTES 7 +#define OUTBYTES 8 + +#define ZOF_TAB 256 +#define BAD 0xFF +#define PAD 0xFE /* Encoded '!' is padding */ + +static const unsigned char dtab[ZOF_TAB] = +{ + BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD, 187, BAD, 188, BAD, BAD, BAD, BAD, + BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD, 189, 190, BAD, BAD, BAD, + 191, PAD, BAD, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, + 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, + 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, + 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, BAD, 57, 58, 59, + 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, + 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, BAD, + BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD, + BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD, + 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, + 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, + 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, + 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, + 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, + 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, +}; +static const char *etab = "#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~" + "\xA0\xA1\xA2\xA3\xA4\xA5\xA6\xA7\xA8\xA9\xAA\xAB\xAC\xAD\xAE\xAF\xB0\xB1\xB2\xB3\xB4\xB5\xB6\xB7\xB8\xB9\xBA\xBB\xBC\xBD\xBE\xBF" + "\xC0\xC1\xC2\xC3\xC4\xC5\xC6\xC7\xC8\xC9\xCA\xCB\xCC\xCD\xCE\xCF\xD0\xD1\xD2\xD3\xD4\xD5\xD6\xD7\xD8\xD9\xDA\xDB\xDC\xDD\xDE\xDF" + "\xE0\xE1\xE2\xE3\xE4\xE5\xE6\xE7\xE8\xE9\xEA\xEB\xEC\xED\xEE\xEF\xF0\xF1\xF2\xF3\xF4\xF5\xF6\xF7\xF8\xF9\xFA\xFB\xFC\xFD\xFE\xFF" + "\t\x0B\x1B\x1C "; + +uint32_t b128_encode(uint8_t *infile, uint8_t *outfile, uint32_t input_length) +{ + unsigned char in[INBYTES]; + unsigned char topbits, mask; + int i, len; + uint32_t k = 0; + uint32_t j = 0; + + while(k < input_length) + { + len = 0; + for (i = 0; i < INBYTES; i++) + { + in[i] = infile[k++]; + len++; + if (k >= input_length) { + break; + } + } + if (len > 0) + { + topbits = 0; + mask = 0x40; + for (i = 0; i < len; i++) + { + outfile[j++] = etab[in[i] & 0x7F]; + if (in[i] > 0x7F) + topbits |= mask; + mask >>= 1; + } + if (len < INBYTES) /* Need to pad */ + { + outfile[j++] = PADCHAR; + } + outfile[j++] = etab[topbits]; + } + } + outfile[j] = 0; + return j; +} + +uint32_t b128_decode(uint8_t *infile, uint8_t *outfile, uint32_t input_length) +{ + unsigned char in[OUTBYTES]; + unsigned char topbits, mask; + int i, len; + uint32_t k = 0; + uint32_t j = 0; + + while(k < input_length) + { + len = 0; + for (i = 0; i < OUTBYTES; i++) + { + in[i] = infile[k++]; + len++; + if (k >= input_length) + break; + } + if (len > 0) + { + topbits = dtab[in[len - 1]]; + mask = 0x40; + for (len = i = 0; i < INBYTES; i++) + { + if (in[i] == PADCHAR) + break; + len++; + in[i] = dtab[in[i]]; + if (in[i] == BAD) /* Illegal encoding character, bail out */ + return 0; + if (topbits & mask) + in[i] |= 0x80; + mask >>= 1; + } + for (i = 0; i < len; i++) + { + outfile[j++] = in[i]; + } + } + } + return j; +} + diff --git a/tracker/software/math/base128.h b/tracker/software/math/base128.h new file mode 100644 index 0000000..3b237e6 --- /dev/null +++ b/tracker/software/math/base128.h @@ -0,0 +1,10 @@ +#ifndef __BASE128_H__ +#define __BASE128_H__ + +#include + +uint32_t b128_encode(uint8_t *infile, uint8_t *outfile, uint32_t input_length); +uint32_t b128_decode(uint8_t *infile, uint8_t *outfile, uint32_t input_length); + +#endif + diff --git a/tracker/software/protocols/aprs/aprs.c b/tracker/software/protocols/aprs/aprs.c index be59c74..b388ab8 100644 --- a/tracker/software/protocols/aprs/aprs.c +++ b/tracker/software/protocols/aprs/aprs.c @@ -203,7 +203,7 @@ uint32_t aprs_encode_experimental(char packetType, uint8_t* message, mod_t mod, /** * Transmit custom data packet (the methods aprs_encode_data allow multiple APRS packets in a row without preable being sent) */ -void aprs_encode_data_init(ax25_t* packet, uint8_t* message, mod_t mod) +void aprs_encode_packet_init(ax25_t* packet, uint8_t* message, mod_t mod) { packet->data = message; packet->max_size = 8192; // TODO: replace 8192 with real size @@ -212,11 +212,10 @@ void aprs_encode_data_init(ax25_t* packet, uint8_t* message, mod_t mod) // Encode APRS header ax25_init(packet); } -uint32_t aprs_encode_data_encodePacket(ax25_t* packet, char packetType, const aprs_conf_t *config, uint8_t *data, size_t size) +uint32_t aprs_encode_packet_encodePacket(ax25_t* packet, char packetType, const aprs_conf_t *config, uint8_t *data, size_t size) { // Encode header ax25_send_header(packet, config->callsign, config->ssid, config->path, packet->size > 0 ? 0 : config->preamble); - ax25_send_string(packet, "{{"); ax25_send_byte(packet, packetType); // Encode message @@ -228,7 +227,7 @@ uint32_t aprs_encode_data_encodePacket(ax25_t* packet, char packetType, const ap return packet->size; } -uint32_t aprs_encode_data_finalize(ax25_t* packet) +uint32_t aprs_encode_packet_finalize(ax25_t* packet) { scramble(packet); nrzi_encode(packet); diff --git a/tracker/software/protocols/aprs/aprs.h b/tracker/software/protocols/aprs/aprs.h index c6ff7ec..09404b6 100644 --- a/tracker/software/protocols/aprs/aprs.h +++ b/tracker/software/protocols/aprs/aprs.h @@ -54,9 +54,9 @@ uint32_t aprs_encode_telemetry_configuration(uint8_t* message, mod_t mod, const uint32_t aprs_encode_message(uint8_t* message, mod_t mod, const aprs_conf_t *config, const char *receiver, const char *text); uint32_t aprs_encode_experimental(char packetType, uint8_t* message, mod_t mod, const aprs_conf_t *config, uint8_t *data, size_t size); -void aprs_encode_data_init(ax25_t* packet, uint8_t* message, mod_t mod); -uint32_t aprs_encode_data_encodePacket(ax25_t* packet, char packetType, const aprs_conf_t *config, uint8_t *data, size_t size); -uint32_t aprs_encode_data_finalize(ax25_t* packet); +void aprs_encode_packet_init(ax25_t* packet, uint8_t* message, mod_t mod); +uint32_t aprs_encode_packet_encodePacket(ax25_t* packet, char packetType, const aprs_conf_t *config, uint8_t *data, size_t size); +uint32_t aprs_encode_packet_finalize(ax25_t* packet); #endif diff --git a/tracker/software/threads/image.c b/tracker/software/threads/image.c index 4e863ef..bd59bae 100644 --- a/tracker/software/threads/image.c +++ b/tracker/software/threads/image.c @@ -8,7 +8,7 @@ #include "ssdv.h" #include "aprs.h" #include "radio.h" -#include "base.h" +#include "base128.h" #include #include "types.h" #include "sleep.h" @@ -273,6 +273,8 @@ const uint8_t noCameraFound[4071] = { 0xBD, 0xC0, 0x20, 0x00, 0x01, 0xFF, 0xD9 }; +#include + uint8_t gimage_id; // Global image ID (for all image threads) mutex_t camera_mtx; bool camera_mtx_init = false; @@ -281,7 +283,7 @@ void encode_ssdv(const uint8_t *image, uint32_t image_len, module_conf_t* conf, { ssdv_t ssdv; uint8_t pkt[SSDV_PKT_SIZE]; - uint8_t pkt_base91[BASE91LEN(SSDV_PKT_SIZE-37)]; + uint8_t pkt_base128[256]; const uint8_t *b; uint32_t bi = 0; uint8_t c = SSDV_OK; @@ -304,7 +306,7 @@ void encode_ssdv(const uint8_t *image, uint32_t image_len, module_conf_t* conf, msg.mod = conf->protocol == PROT_APRS_AFSK ? MOD_AFSK : MOD_2GFSK; msg.afsk_conf = &(conf->afsk_conf); msg.gfsk_conf = &(conf->gfsk_conf); - aprs_encode_data_init(&ax25_handle, msg.msg, msg.mod); + aprs_encode_packet_init(&ax25_handle, msg.msg, msg.mod); } while(true) @@ -320,11 +322,11 @@ void encode_ssdv(const uint8_t *image, uint32_t image_len, module_conf_t* conf, if(r <= 0) { TRACE_ERROR("SSDV > Premature end of file"); - if(conf->protocol == PROT_APRS_2GFSK || conf->protocol == PROT_APRS_AFSK) msg.bin_len = aprs_encode_data_finalize(&ax25_handle); + if(conf->protocol == PROT_APRS_2GFSK || conf->protocol == PROT_APRS_AFSK) msg.bin_len = aprs_encode_packet_finalize(&ax25_handle); if(msg.bin_len > 0) transmitOnRadio(&msg, false); // Empty buffer if(conf->protocol == PROT_APRS_2GFSK || conf->protocol == PROT_APRS_AFSK) { - aprs_encode_data_init(&ax25_handle, msg.msg, msg.mod); + aprs_encode_packet_init(&ax25_handle, msg.msg, msg.mod); msg.bin_len = 0; } break; @@ -335,21 +337,21 @@ void encode_ssdv(const uint8_t *image, uint32_t image_len, module_conf_t* conf, if(c == SSDV_EOI) { TRACE_INFO("SSDV > ssdv_enc_get_packet said EOI"); - if(conf->protocol == PROT_APRS_2GFSK || conf->protocol == PROT_APRS_AFSK) msg.bin_len = aprs_encode_data_finalize(&ax25_handle); + if(conf->protocol == PROT_APRS_2GFSK || conf->protocol == PROT_APRS_AFSK) msg.bin_len = aprs_encode_packet_finalize(&ax25_handle); if(msg.bin_len > 0) transmitOnRadio(&msg, false); // Empty buffer if(conf->protocol == PROT_APRS_2GFSK || conf->protocol == PROT_APRS_AFSK) { - aprs_encode_data_init(&ax25_handle, msg.msg, msg.mod); + aprs_encode_packet_init(&ax25_handle, msg.msg, msg.mod); msg.bin_len = 0; } break; } else if(c != SSDV_OK) { TRACE_ERROR("SSDV > ssdv_enc_get_packet failed: %i", c); - if(conf->protocol == PROT_APRS_2GFSK || conf->protocol == PROT_APRS_AFSK) msg.bin_len = aprs_encode_data_finalize(&ax25_handle); + if(conf->protocol == PROT_APRS_2GFSK || conf->protocol == PROT_APRS_AFSK) msg.bin_len = aprs_encode_packet_finalize(&ax25_handle); if(msg.bin_len > 0) transmitOnRadio(&msg, false); // Empty buffer if(conf->protocol == PROT_APRS_2GFSK || conf->protocol == PROT_APRS_AFSK) { - aprs_encode_data_init(&ax25_handle, msg.msg, msg.mod); + aprs_encode_packet_init(&ax25_handle, msg.msg, msg.mod); msg.bin_len = 0; } return; @@ -360,20 +362,21 @@ void encode_ssdv(const uint8_t *image, uint32_t image_len, module_conf_t* conf, case PROT_APRS_AFSK: // Encode packet TRACE_INFO("IMG > Encode APRS/SSDV packet"); - base91_encode(&pkt[1], pkt_base91, sizeof(pkt)-37); // Sync byte, CRC and FEC of SSDV not transmitted - msg.bin_len = aprs_encode_data_encodePacket(&ax25_handle, 'I', &conf->aprs_conf, pkt_base91, strlen((char*)pkt_base91)); + b128_encode(&pkt[6], pkt_base128, sizeof(pkt)-42); // Sync byte, CRC and FEC of SSDV not transmitted (because its not neccessary inside an APRS packet) + + msg.bin_len = aprs_encode_packet_encodePacket(&ax25_handle, '!', &conf->aprs_conf, pkt_base128, strlen((char*)pkt_base128)); if(redudantTx) - msg.bin_len = aprs_encode_data_encodePacket(&ax25_handle, 'I', &conf->aprs_conf, pkt_base91, strlen((char*)pkt_base91)); + msg.bin_len = aprs_encode_packet_encodePacket(&ax25_handle, '!', &conf->aprs_conf, pkt_base128, strlen((char*)pkt_base128)); // Transmit if(msg.bin_len >= 58000 || conf->packet_spacing) // Transmit if buffer is almost full or if single packet transmission is activated (packet_spacing != 0) { // Transmit packets - msg.bin_len = aprs_encode_data_finalize(&ax25_handle); + msg.bin_len = aprs_encode_packet_finalize(&ax25_handle); transmitOnRadio(&msg, false); // Initialize new packet buffer - aprs_encode_data_init(&ax25_handle, msg.msg, msg.mod); + aprs_encode_packet_init(&ax25_handle, msg.msg, msg.mod); msg.bin_len = 0; } break;