diff --git a/.gitignore b/.gitignore
index bdb12e5..7e76400 100644
--- a/.gitignore
+++ b/.gitignore
@@ -2,3 +2,5 @@ build
.dep
*.pyc
__pycache__
+*.sqlite
+decoder/html/images/
diff --git a/decoder/base91.py b/decoder/base91.py
index 4cc6ab5..cee43a0 100644
--- a/decoder/base91.py
+++ b/decoder/base91.py
@@ -35,7 +35,7 @@ base91_alphabet = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', '
'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '!', '#', '$',
'%', '&', '(', ')', '*', '+', ',', '.', '/', ':', ';', '<', '=',
- '>', '?', '@', '[', ']', '^', '_', '`', '{', '|', '}', '~', '"']
+ '>', '?', '@', '[', ']', '^', '_', '`', '{', '-', '}', '~', '"']
decode_table = dict((v,k) for k,v in enumerate(base91_alphabet))
diff --git a/decoder/decoder.py b/decoder/decoder.py
index 82b3434..f58cc42 100755
--- a/decoder/decoder.py
+++ b/decoder/decoder.py
@@ -1,40 +1,159 @@
-#!/usr/bin/python
+#!/usr/bin/python3
-import serial,os,re,datetime
-from subprocess import call
+import serial,re
import base91
-import binascii
-import urllib2
-import io
import sys
import argparse
-import getpass
import telnetlib
import time
+import sqlite3
+import image
+import position
# Parse arguments from terminal
parser = argparse.ArgumentParser(description='APRS/SSDV decoder')
parser.add_argument('-c', '--call', help='Callsign of the station', required=True)
-parser.add_argument('-l', '--log', help='Name of the logfile')
parser.add_argument('-n', '--grouping', help='Amount packets that will be sent to the SSDV server in one request', default=1, type=int)
parser.add_argument('-d', '--device', help='Serial device (\'-\' for stdin)', default='-')
parser.add_argument('-b', '--baudrate', help='Baudrate for serial device', default=9600, type=int)
parser.add_argument('-s', '--server', help='SSDV server URL', default='https://ssdv.habhub.org/api/v0/packets')
args = parser.parse_args()
-if args.device == 'I': # Connect to APRS-IS
+# Open SQLite database
+sqlite = sqlite3.connect("decoder.sqlite")
+sqlite.cursor().execute("""
+ CREATE TABLE IF NOT EXISTS position
+ (
+ call TEXT,
+ time INTEGER,
+ org TEXT,
+ lat FLOAT,
+ lon FLOAT,
+ alt INTEGER,
+ comment TEXT,
+ sequ INTEGER,
+ tel1 INTEGER,
+ tel2 INTEGER,
+ tel3 INTEGER,
+ tel4 INTEGER,
+ tel5 INTEGER,
+ PRIMARY KEY (call, time)
+ )
+""")
+sqlite.cursor().execute("""
+ CREATE TABLE IF NOT EXISTS image
+ (
+ call TEXT,
+ time INTEGER,
+ imageID INTEGER,
+ packetID INTEGER,
+ lat FLOAT,
+ lon FLOAT,
+ alt INTEGER,
+ data TEXT,
+ PRIMARY KEY (call, time, imageID, packetID)
+ )
+""")
+
+
+""" Packet handler for received APRS packets"""
+def received_data(data):
+ # Debug
+ print('====================================================================================================')
+ print(data)
+ print('----------------------------------------------------------------------------------------------------')
+
+ # Parse line and detect data
+ # Position (.*)\>APECAN(.*?):\/([0-9]{6}h)(.{13})(.*?)\|(.*)\|
+ # Image (.*)\>APECAN(.*?):\/([0-9]{6}h)(.{13})I(.*)
+ # Log (.*)\>APECAN(.*?):\/([0-9]{6}h)(.{13})L(.*)
+
+ all = re.search("(.*)\>APECAN(.*?):\/([0-9]{6}h)(.{13})", data)
+ pos = re.search("(.*)\>APECAN(.*?):\/([0-9]{6}h)(.{13})(.*?)\|(.*)\|", data)
+ dat = re.search("(.*)\>APECAN(.*?):\/([0-9]{6}h)(.{13})(I|L)(.*)", data)
+
+ if all:
+ call = all.group(1)
+ rxer = all.group(2).split(',')[-1]
+ tim = all.group(3)
+ posi = all.group(4)
+
+ if pos: # Position packet (with comment and telementry)
+
+ comm = pos.group(5)
+ tel = pos.group(6)
+ position.insert_position(sqlite, call, tim, posi, comm, tel)
+
+ elif dat: # Data packet
+
+ typ = dat.group(5)
+ data_b91 = dat.group(6)
+ data = base91.decode(data_b91) # Decode Base91
+
+ if typ is 'I': # Image packet
+ image.insert_image(sqlite, rxer, call, tim, posi, data, args.server, args.grouping)
+ elif typ is 'L': # Log packet
+ position.insert_log(sqlite, call, data)
+
+if args.device == 'I': # Source APRS-IS
print('Connect to APRS-IS')
try:
tn = telnetlib.Telnet("rotate.aprs2.net", 14580, 3)
- tn.write("user %s filter u/APECAN\n" % args.call)
+ tn.write(("user %s filter u/APECAN\n" % args.call).encode('ascii'))
print('Connected')
except Exception as e:
print('Could not connect to APRS-IS: %s' % str(e))
print('exit...')
sys.exit(1)
-elif args.device is not '-': # Use serial connection (probably TNC)
+ wdg = time.time() + 1 # Connection watchdog
+ buf = ''
+ while True:
+ # Read data
+ try:
+ buf += tn.read_eager().decode('ascii')
+ except EOFError: # Server has connection closed
+ wdg = 0 # Tell watchdog to restart connection
+
+ # Line handler
+ if '\n' in buf:
+ pbuf = buf.split('\n')
+ for i in range(len(pbuf)-1):
+ # Separate lines handled here
+
+ # Watchdog reload
+ if '# aprsc' in pbuf[i]:
+ print('Ping from APRS-IS')
+ wdg = time.time() + 30
+ continue
+
+ # Data handling
+ received_data(pbuf[i])
+
+ buf = pbuf[-1]
+
+ # Watchdog reconnection
+ if wdg < time.time():
+ print('APRS-IS connection lost... reconnect')
+ try:
+ tn = telnetlib.Telnet("rotate.aprs2.net", 14580, 3)
+ tn.write(("user %s filter u/APECAN\n" % args.call).encode('ascii'))
+ print('Connected')
+ wdg = time.time() + 1
+ except Exception as e:
+ print('Could not connect to APRS-IS: %s' % str(e))
+ print('Try again...')
+
+ time.sleep(0.1)
+
+elif args.device is '-': # Source stdin
+
+ while True:
+ data = sys.stdin.readline()
+ received_data(data)
+
+else: # Source Serial connection
try:
serr = serial.Serial(
@@ -45,182 +164,13 @@ elif args.device is not '-': # Use serial connection (probably TNC)
sys.stderr.write('Error: Could not open serial port\n')
sys.exit(1)
-
-# Open logging file
-if args.log is not None:
- try:
- f = open(args.log, 'a')
- except:
- sys.stderr.write('Error: Could not open logging file\n')
- sys.exit(1)
-
-jsons = []
-
-def decode_callsign(code):
- callsign = ''
-
- while code > 0:
- s = code % 40
- 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(.*):\!(.*)", data)
- try:
- call = m.group(1).split(' ')[-1] # transmitter callsign
- data91 = m.group(3) # base91 encoded SSDV data (without SYNC, PacketType, Callsign, CRC, FEC)
- if len(m.group(2)) > 0:
- receiver = m.group(2).split(',')[-1]
- else:
- receiver = args.call
- except:
- return # message format incorrect (probably no APRS message or line cut off too short)
-
- if args.log is not None:
- f.write(data) # Log data to file
-
- data = base91.decode(data91) # Decode Base91
-
- 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
-
- # Create message for SSDV server (and save to array)
- ssdv = '55' + binascii.hexlify(data) + ('%08x' % crc) + (64*'0')
- jsons.append("""{
- \"type\": \"packet\",
- \"packet\": \"""" + ssdv + """\",
- \"encoding\": \"hex\",
- \"received\": \"""" + datetime.datetime.now().isoformat('T')[:19] + """Z\",
- \"receiver\": \"""" + receiver + """\"
- }""")
-
- 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
-
- req = urllib2.Request(args.server)
- req.add_header('Content-Type', 'application/json')
-
- json = "{\"type\":\"packets\",\"packets\":[" + ",".join(jsons) + "]}" # Group all SSDV packets into a big JSON
- jsons = []
-
- try:
- error = True
- while error:
- print('Send to SSDV data server')
- try:
- result = urllib2.urlopen(req, "".join(json.split(' '))) # Send packets to server
- print('Response from Server: OK')
- error = False
- except urllib2.URLError, error:
- if error.code == 400:
- print('Response from Server: %s', error.read())
- error = False
- else:
- print 'SSDV-Server connection error... try again'
-
- except urllib2.HTTPError, error: # The server did not like our packets :(
- print 'Send to SSDV data server: failed (the server did not like our packets :( )'
- print error.read()
-
-if args.device == 'I': # APRS-IS
-
- wdg = time.time() # Watchdog
- buf = ''
while True:
- buf += tn.read_eager()
- if '\n' in buf:
- pbuf = buf.split('\n')
- for i in range(len(pbuf)-1):
- # Separate lines handled here
-
- # Watchdog reload
- if '# aprsc' in pbuf[i]:
- print('Ping from APRS-IS')
- wdg = time.time()
- continue
-
- # Data handling
- print(pbuf[i])
- received_data(pbuf[i])
-
- buf = pbuf[-1]
-
- # Watchdog reconnection
- if wdg + 30 < time.time():
- print('APRS-IS connection lost... reconnect')
- try:
- tn = telnetlib.Telnet("rotate.aprs2.net", 14580, 3)
- tn.write("user %s filter u/APECAN\n" % args.call)
- print('Connected')
- wdg = time.time()
- except Exception as e:
- print('Could not connect to APRS-IS: %s' % str(e))
- print('Try again...')
-
- time.sleep(0.1)
-
-else: # stdin or serial
-
- while True:
- # 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
+ data = ''
+ while True:
+ b = serr.read(1)
+ if b == '\r' or b == '\n':
+ break
+ data += b
received_data(data)
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/decoder/html/data.php b/decoder/html/data.php
new file mode 100644
index 0000000..1e830fa
--- /dev/null
+++ b/decoder/html/data.php
@@ -0,0 +1,13 @@
+getCallsigns() as $callsign)
+ foreach($db->getRoute($callsign) as $point)
+ $data[] = $point;
+
+header("Content-Type: application/json");
+echo json_encode($data);
+?>
+
diff --git a/decoder/html/database.class.php b/decoder/html/database.class.php
new file mode 100644
index 0000000..4994ec9
--- /dev/null
+++ b/decoder/html/database.class.php
@@ -0,0 +1,48 @@
+open("/src/pecanpico9/decoder/decoder.sqlite");
+
+ if($this->lastErrorCode())
+ echo $this->lastErrorMsg();
+ }
+ function getCallsigns() {
+ $calls = array();
+
+ $query = $this->query("SELECT call FROM position GROUP BY call");
+ while($row = $query->fetchArray(SQLITE3_ASSOC))
+ $calls[] = $row['call'];
+
+ $query = $this->query("SELECT call FROM image GROUP BY call");
+ while($row = $query->fetchArray(SQLITE3_ASSOC))
+ if(!in_array($row['call'], $calls))
+ $calls[] = $row['call'];
+
+ return $calls;
+ }
+ function getRoute($callsign) {
+ $route = array();
+
+ $stmt = $this->prepare("
+ SELECT position.time,ROUND(position.lat,5) as lat,ROUND(position.lon,5) as lng,position.alt,org,
+ 'images/' || REPLACE(image.call,'-','') || '-' || image.time || '-' || image.imageID || '.jpg' AS img
+ FROM position
+ LEFT JOIN image
+ ON position.time = image.time
+ WHERE position.call = :call
+ AND position.lat != 0
+ AND position.lon != 0
+ GROUP BY position.call,position.time
+ ORDER BY position.time ASC
+ ");
+ $stmt->bindValue(':call', $callsign, SQLITE3_TEXT);
+ $query = $stmt->execute();
+
+ while($row = $query->fetchArray(SQLITE3_ASSOC))
+ $route[] = $row;
+
+ return $route;
+ }
+}
+?>
+
diff --git a/decoder/html/index.php b/decoder/html/index.php
new file mode 100644
index 0000000..59718e4
--- /dev/null
+++ b/decoder/html/index.php
@@ -0,0 +1,111 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/decoder/image.py b/decoder/image.py
new file mode 100644
index 0000000..17f2d9f
--- /dev/null
+++ b/decoder/image.py
@@ -0,0 +1,125 @@
+import binascii
+import urllib.request
+import urllib.error
+import datetime
+from position import decode_position
+from subprocess import *
+
+jsons = []
+
+def decode_callsign(code):
+ callsign = ''
+
+ while code > 0:
+ s = code % 40
+ 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
+
+"""
+Decodes an APRS/SSDV image packet (APRS header must be removed already)
+sqlite - Database handle
+reciever - The call of the receiving station
+call - The call of the transmitter
+data - Binary data
+"""
+def insert_image(sqlite, receiver, call, tim, posi, data, server, grouping):
+ global jsons
+
+ 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
+
+ # Create message for SSDV server (and save to array)
+ ssdv = '55' + binascii.hexlify(data).decode("ascii") + ('%08x' % crc) + (64*'0')
+ jsons.append("""{
+ \"type\": \"packet\",
+ \"packet\": \"""" + ssdv + """\",
+ \"encoding\": \"hex\",
+ \"received\": \"""" + datetime.datetime.now().isoformat('T')[:19] + """Z\",
+ \"receiver\": \"""" + receiver + """\"
+ }""")
+
+ # Decode various meta data
+ timd,x,y,z,dummy = decode_position(tim, posi, None)
+ imageID = data[5]
+ packetID = (data[6] << 8) | data[7]
+
+ # Debug
+ print('Received packet from %s image %d packet %d' % (call, imageID, packetID))
+
+ # Insert
+ sqlite.cursor().execute("""
+ INSERT OR REPLACE INTO image (call,time,imageID,packetID,lat,lon,alt,data)
+ VALUES (?,?,?,?,?,?,?,?)""",
+ (call, int(timd.timestamp()), imageID, packetID, y, x, int(z), ssdv)
+ )
+ sqlite.commit()
+
+ # SSDV decode
+ cur = sqlite.cursor()
+ cur.execute("SELECT GROUP_CONCAT(data,'') FROM image WHERE call = ? AND imageID = ? AND time = ? GROUP BY imageID ORDER BY packetID", (call, imageID, int(timd.timestamp())))
+ name = 'html/images/%s-%d-%d.jpg' % (call.replace('-',''), int(timd.timestamp()), imageID)
+ f = open(name, 'wb')
+ process = Popen(['./ssdv', '-d'], stdin=PIPE, stdout=f, stderr=PIPE)
+ process.stdin.write(binascii.unhexlify(cur.fetchall()[0][0]))
+ dummy,err = process.communicate()
+ f.close()
+
+ if len(jsons) >= grouping: # Enough packets collected, send them all to the server
+
+ req = urllib.request.Request(server)
+ req.add_header('Content-Type', 'application/json')
+
+ json = "{\"type\":\"packets\",\"packets\":[" + ",".join(jsons) + "]}" # Group all SSDV packets into a big JSON
+ jsons = []
+
+ try:
+ error = True
+ while error:
+ print('Send to SSDV data server')
+ try:
+ result = urllib.request.urlopen(req, "".join(json.split(' ')).encode("ascii")) # Send packets to server
+ print('Response from Server: OK')
+ error = False
+ except urllib.error.URLError as error:
+ if error.code == 400:
+ print('Response from Server: %s', error.read())
+ error = False
+ else:
+ print('SSDV-Server connection error... try again')
+
+ except urllib.error.HTTPError as error: # The server did not like our packets :(
+ print('Send to SSDV data server: failed (the server did not like our packets :( )')
+ print(error.read())
+
diff --git a/decoder/position.py b/decoder/position.py
new file mode 100644
index 0000000..808d0b9
--- /dev/null
+++ b/decoder/position.py
@@ -0,0 +1,83 @@
+from datetime import datetime,timedelta,timezone
+import sqlite3
+import base91
+
+def insert_log(sqlite, call, data):
+
+ if len(data)/10*10 != len(data): # Is not multiple of 8 bytes
+ return # APRS message sampled too short
+
+ for i in range(int(len(data)/10)):
+ tim = (data[i*10+3] << 24) | (data[i*10+2] << 16) | (data[i*10+1] << 8) | data[i*10+0]
+ lat = (data[i*10+5] << 8) | data[i*10+4]
+ lon = (data[i*10+7] << 8) | data[i*10+6]
+ alt = (data[i*10+9] << 8) | data[i*10+8]
+
+ lat = float(lat * 180) / 65536 - 90
+ lon = float(lon * 360) / 65536 - 180
+
+ tim_stringified = datetime.utcfromtimestamp(tim).strftime("%Y-%m-%d %H:%M:%S")
+ try:
+ sqlite.cursor().execute("INSERT OR FAIL INTO position (call,time,org,lat,lon,alt) VALUES (?,?,'log',?,?,?)", (call, tim, lat, lon, alt))
+ print("Decoded log from %s time %s => lat=%06.3f lon=%07.3f alt=%05d" % (call, tim_stringified, lat, lon, alt))
+ except sqlite3.IntegrityError:
+ print("Decoded log from %s time %s => lat=%06.3f lon=%07.3f alt=%05d already in db" % (call, tim_stringified, lat, lon, alt))
+
+ sqlite.commit()
+
+def decode_position(tim, posi, tel):
+ # Decode latitude
+ y3 = ord(posi[1]) - 33
+ y2 = ord(posi[2]) - 33
+ y1 = ord(posi[3]) - 33
+ y0 = ord(posi[4]) - 33
+ ye = y0 + y1*91 + y2*8281 + y3*753571
+ y = -ye / 380926.0 + 90
+
+ # Decode longitude
+ x3 = ord(posi[5]) - 33
+ x2 = ord(posi[6]) - 33
+ x1 = ord(posi[7]) - 33
+ x0 = ord(posi[8]) - 33
+ xe = x0 + x1*91 + x2*8281 + x3*753571
+ x = xe / 190463.0 - 180
+
+ # Decode altitude
+ z1 = ord(posi[10]) - 33
+ z0 = ord(posi[11]) - 33
+ ze = z0 + z1*91
+ z = pow(1.002, ze) / 3.281
+
+ # Decode time
+ timd = datetime.now()
+ timd = timd.replace(hour = int(tim[0:2]), minute = int(tim[2:4]), second = int(tim[4:6]), microsecond=0)
+ if datetime.utcnow() < timd: # Packet was sampled yesterday
+ timd -= timedelta(1)
+
+ # Decode telemetry
+ teld = [0]*6
+ if tel != None:
+ for i in range(6):
+ t1 = ord(tel[i*2+0]) - 33
+ t0 = ord(tel[i*2+1]) - 33
+ teld.append(t0 + t1*91)
+
+ return timd,x,y,z,teld
+
+def insert_position(sqlite, call, tim, posi, comm, tel): #sqlite, call, data
+ # Decode
+ timd,x,y,z,teld = decode_position(tim, posi, tel)
+
+ # Insert
+ sqlite.cursor().execute("""
+ INSERT OR REPLACE INTO position (call,time,org,lat,lon,alt,comment,sequ,tel1,tel2,tel3,tel4,tel5)
+ VALUES (?,?,'pos',?,?,?,?,?,?,?,?,?,?)""",
+ (call, int(timd.timestamp()), y, x, int(z), comm, teld[0], teld[1], teld[2], teld[3], teld[4], teld[5])
+ )
+ sqlite.commit()
+
+ # Debug
+ tim_stringified = timd.strftime("%Y-%m-%d %H:%M:%S")
+ print("Decoded position from %s time %s => lat=%f lon=%f alt=%d comment=%s, sequ=%d tel=[%d,%d,%d,%d,%d]"
+ % (call, tim_stringified, y, x, z, comm, teld[0], teld[1], teld[2], teld[3], teld[4], teld[5]))
+
diff --git a/tracker/software/config.c b/tracker/software/config.c
index e93e907..e804269 100644
--- a/tracker/software/config.c
+++ b/tracker/software/config.c
@@ -366,7 +366,7 @@ uint8_t ssdv_buffer[128*1024] __attribute__((aligned(32))); // Image buffer
systime_t track_cycle_time = S2ST(60); // Tracking cycle (all peripheral data [airpressure, GPS, temperature, ...] is collected each 60 seconds
systime_t log_cycle_time = S2ST(60); // Log cycle time in seconds (600 seconds)
-bool keep_cam_switched_on = true; // Keep camera switched on and initialized, this makes image capturing faster but takes a lot of power over long time
+bool keep_cam_switched_on = false; // Keep camera switched on and initialized, this makes image capturing faster but takes a lot of power over long time
uint16_t gps_on_vbat = 3000; // Battery voltage threshold at which GPS is switched on
uint16_t gps_off_vbat = 2500; // Battery voltage threshold at which GPS is switched off
@@ -385,19 +385,19 @@ void start_user_modules(void)
config[0].frequency.hz = 144800000; // Default frequency 144.800 MHz
config[0].trigger.type = TRIG_NEW_POINT; // Transmit when tracking manager samples new tracking point
chsnprintf(config[0].aprs_conf.callsign, 16, "DL7AD"); // APRS Callsign
- config[0].aprs_conf.ssid = 12; // APRS SSID
+ config[0].aprs_conf.ssid = 13; // APRS SSID
config[0].aprs_conf.symbol = SYM_BALLOON; // APRS Symbol
chsnprintf(config[0].aprs_conf.path, 16, "WIDE1-1"); // APRS Path
config[0].aprs_conf.preamble = 300; // APRS Preamble (300ms)
config[0].aprs_conf.tel[0] = TEL_VBAT; // APRS Telemetry parameter 1: Battery voltage
- config[0].aprs_conf.tel[1] = TEL_PBAT; // APRS Telemetry parameter 2: Battery charge/discharge power
- config[0].aprs_conf.tel[2] = TEL_RBAT; // APRS Telemetry parameter 3: Battery impedance
+ config[0].aprs_conf.tel[1] = TEL_VSOL; // APRS Telemetry parameter 2: Solar voltage
+ config[0].aprs_conf.tel[2] = TEL_PBAT; // APRS Telemetry parameter 3: Battery charge/discharge power
config[0].aprs_conf.tel[3] = TEL_TEMP; // APRS Telemetry parameter 4: Temperature
config[0].aprs_conf.tel[4] = TEL_PRESS; // APRS Telemetry parameter 5: Airpressuse
config[0].aprs_conf.tel_enc = TRUE; // Transmit Telemetry encoding information activated
config[0].aprs_conf.tel_enc_cycle = 3600; // Transmit Telemetry encoding information every 3600sec
chsnprintf(config[0].aprs_conf.tel_comment, 30, "http://ssdv.habhub.org/DL7AD");// Telemetry comment
- //start_position_thread(&config[0]);
+ start_position_thread(&config[0]);
// Module POSITION, UKHAS 2m 2FSK
config[1].power = 127; // Transmission Power
@@ -438,15 +438,15 @@ void start_user_modules(void)
config[3].packet_spacing = 20000; // Packet spacing in ms
config[3].trigger.type = TRIG_CONTINUOUSLY; // Transmit continuously
chsnprintf(config[3].aprs_conf.callsign, 16, "DL7AD"); // APRS Callsign
- config[3].aprs_conf.ssid = 12; // APRS SSID
+ config[3].aprs_conf.ssid = 14; // APRS SSID
+ config[3].aprs_conf.symbol = SYM_BALLOON; // APRS Symbol
config[3].aprs_conf.preamble = 300; // APRS Preamble (300ms)
- chsnprintf(config[3].ssdv_conf.callsign, 7, "DL7AD1"); // SSDV Callsign
config[3].ssdv_conf.ram_buffer = ssdv_buffer; // Camera buffer
config[3].ssdv_conf.ram_size = sizeof(ssdv_buffer); // Buffer size
config[3].ssdv_conf.res = RES_QVGA; // Resolution QVGA
config[3].ssdv_conf.redundantTx = true; // Redundant transmission (transmit packets twice)
config[3].ssdv_conf.quality = 4; // Image quality
- //start_image_thread(&config[3]);
+ start_image_thread(&config[3]);
// Module IMAGE, APRS 2m 2GFSK
config[4].power = 127; // Transmission Power
@@ -456,9 +456,9 @@ void start_user_modules(void)
config[4].frequency.hz = 144860000; // Transmission frequency 144.860 MHz
config[4].trigger.type = TRIG_CONTINUOUSLY; // Transmit continuously
chsnprintf(config[4].aprs_conf.callsign, 16, "DL7AD"); // APRS Callsign
- config[4].aprs_conf.ssid = 12; // APRS SSID
+ config[4].aprs_conf.ssid = 13; // APRS SSID
+ config[4].aprs_conf.symbol = SYM_BALLOON; // APRS Symbol
config[4].aprs_conf.preamble = 100; // APRS Preamble (100ms)
- chsnprintf(config[4].ssdv_conf.callsign, 7, "DL7AD2"); // SSDV Callsign
config[4].ssdv_conf.ram_buffer = ssdv_buffer; // Camera buffer
config[4].ssdv_conf.ram_size = sizeof(ssdv_buffer); // Buffer size
config[4].ssdv_conf.res = RES_VGA; // Resolution VGA
@@ -476,7 +476,7 @@ void start_user_modules(void)
config[5].fsk_conf.predelay = 1000; // Preamble (1000ms)
config[5].fsk_conf.baud = 600; // Baudrate (600baud)
config[5].fsk_conf.shift = 1000; // Frequency shift (1000Hz)
- chsnprintf(config[5].ssdv_conf.callsign, 7, "DL7AD3"); // SSDV Callsign
+ chsnprintf(config[5].ssdv_conf.callsign, 7, "DL7AD"); // SSDV Callsign
config[5].ssdv_conf.ram_buffer = ssdv_buffer; // Camera buffer
config[5].ssdv_conf.ram_size = sizeof(ssdv_buffer); // Buffer size
config[5].ssdv_conf.res = RES_QVGA; // Resolution QVGA
@@ -491,14 +491,15 @@ void start_user_modules(void)
config[6].protocol = PROT_APRS_AFSK; // Protocol APRS (AFSK)
config[6].frequency.type = FREQ_APRS_REGION; // Dynamic frequency allocation
config[6].frequency.hz = 144800000; // Default frequency 144.800 MHz
- config[6].init_delay = 60000; // Module startup delay (60 seconds)
+ config[6].init_delay = 5000; // Module startup delay (5 seconds)
config[6].trigger.type = TRIG_TIMEOUT; // Periodic cycling (every 180 seconds)
- config[6].trigger.timeout = 180; // Timeout 180 sec
+ config[6].trigger.timeout = 60; // Timeout 180 sec
chsnprintf(config[6].aprs_conf.callsign, 16, "DL7AD"); // APRS Callsign
- config[6].aprs_conf.ssid = 12; // APRS SSID
+ config[6].aprs_conf.ssid = 13; // APRS SSID
+ config[6].aprs_conf.symbol = SYM_BALLOON; // APRS Symbol
chsnprintf(config[6].aprs_conf.path, 16, "WIDE1-1"); // APRS Path
config[6].aprs_conf.preamble = 300; // APRS Preamble (300ms)
- //start_logging_thread(&config[6]);
+ start_logging_thread(&config[6]);
}
diff --git a/tracker/software/debug.c b/tracker/software/debug.c
index 01415bd..bb6d1a1 100644
--- a/tracker/software/debug.c
+++ b/tracker/software/debug.c
@@ -89,15 +89,15 @@ void readLog(BaseSequentialStream *chp, int argc, char *argv[])
(void)argc;
(void)argv;
- chprintf(chp, "id,date,time,lat,lon,alt,sats,ttff,vbat,vsol,vsub,pbat,rbat,press,temp,hum,idimg\r\n");
+ chprintf(chp, "addr,id,date,time,lat,lon,alt,sats,ttff,vbat,vsol,vsub,pbat,rbat,press,temp,hum,idimg\r\n");
trackPoint_t *tp;
for(uint16_t i=0; (tp = getLogBuffer(i)) != NULL; i++)
if(tp->id != 0xFFFFFFFF)
{
chprintf( chp,
- "%d,%04d-%02d-%02d,%02d:%02d:%02d,%d.%05d,%d.%05d,%d,%d,%d,%d.%03d,%d.%03d,%d.%03d,%d,%d,%d.%01d,%2d.%02d,%2d.%01d,%d\r\n",
- tp->id,tp->time.year, tp->time.month, tp->time.day, tp->time.hour, tp->time.minute, tp->time.day,
+ "%08x,%d,%04d-%02d-%02d,%02d:%02d:%02d,%d.%05d,%d.%05d,%d,%d,%d,%d.%03d,%d.%03d,%d.%03d,%d,%d,%d.%01d,%2d.%02d,%2d.%01d,%d\r\n",
+ tp, tp->id,tp->time.year, tp->time.month, tp->time.day, tp->time.hour, tp->time.minute, tp->time.day,
tp->gps_lat/10000000, (tp->gps_lat > 0 ? 1:-1)*(tp->gps_lat/100)%100000, tp->gps_lon/10000000, (tp->gps_lon > 0 ? 1:-1)*(tp->gps_lon/100)%100000, tp->gps_alt,
tp->gps_sats, tp->gps_ttff,
tp->adc_vbat/1000, (tp->adc_vbat%1000), tp->adc_vsol/1000, (tp->adc_vsol%1000), tp->adc_vusb/1000, (tp->adc_vusb%1000), tp->adc_pbat, tp->adc_rbat,
diff --git a/tracker/software/drivers/wrapper/padc.c b/tracker/software/drivers/wrapper/padc.c
index 81f0ce8..5eae0bb 100644
--- a/tracker/software/drivers/wrapper/padc.c
+++ b/tracker/software/drivers/wrapper/padc.c
@@ -2,10 +2,9 @@
#include "hal.h"
#include "config.h"
-#include "padc.h"
#include "pac1720.h"
-#include "debug.h"
#include "pi2c.h"
+#include
#define ADC_NUM_CHANNELS 4 /* Amount of channels (solar, battery, temperature) */
#define VCC_REF_LOW 1850 /* mV */
@@ -69,39 +68,32 @@ void doConversion(void)
deinitADC();
}
-uint16_t getBatteryVoltageMV_STM32(void)
+static uint16_t getBatteryVoltageMV_STM32(void)
{
doConversion();
return samples[2] * vcc_ref * DIVIDER_VBAT / 4096;
}
+static uint16_t getSolarVoltageMV_STM32(void)
+{
+ doConversion();
+ return samples[0] * vcc_ref * DIVIDER_VSOL / 4096;
+}
+
uint16_t getBatteryVoltageMV(void)
{
- uint16_t vbat = getBatteryVoltageMV_STM32();
+ uint16_t vbat = getBatteryVoltageMV_STM32(); // Get value from STM32
+ uint16_t vbat_pac = pac1720_getVbat(); // Get value from PAC1720
- // Get voltage from PAC1720 (PAC1720 returns false redings below 2.35V)
- if(vbat >= 2500)
- {
- uint16_t vbat_pac = pac1720_getVbat(); // Get value from PAC1720
- if(vbat_pac) // Apply it if valid
- vbat = vbat_pac;
- }
-
- return vbat;
+ return abs(vbat-vbat_pac) < 200 ? vbat_pac : vbat;
}
uint16_t getSolarVoltageMV(void)
{
- uint16_t vbat = getBatteryVoltageMV_STM32();
+ uint16_t vsol = getSolarVoltageMV_STM32(); // Get value from STM32
+ uint16_t vsol_pac = pac1720_getVsol(); // Get value from PAC1720
- // Get voltage from PAC1720 (PAC1720 returns false redings below 2.35V)
- if(vbat >= 2500)
- {
- uint16_t vsol_pac = pac1720_getVsol(); // Get value from PAC1720
- if(vsol_pac)
- return vsol_pac;
- }
- return samples[0] * vcc_ref * DIVIDER_VSOL / 4096;
+ return abs(vsol-vsol_pac) < 200 ? vsol_pac : vsol;
}
uint16_t getUSBVoltageMV(void)
diff --git a/tracker/software/drivers/wrapper/padc.h b/tracker/software/drivers/wrapper/padc.h
index e957d54..448e68b 100644
--- a/tracker/software/drivers/wrapper/padc.h
+++ b/tracker/software/drivers/wrapper/padc.h
@@ -8,7 +8,6 @@
void initADC(void);
void deinitADC(void);
-uint16_t getBatteryVoltageMV_STM32(void);
uint16_t getBatteryVoltageMV(void);
uint16_t getSolarVoltageMV(void);
uint16_t getUSBVoltageMV(void);
diff --git a/tracker/software/math/base91.c b/tracker/software/math/base91.c
index 5818ef0..a0a570f 100644
--- a/tracker/software/math/base91.c
+++ b/tracker/software/math/base91.c
@@ -51,7 +51,7 @@ const unsigned char b91_table[91] = {
'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '!', '#', '$',
'%', '&', '(', ')', '*', '+', ',', '.', '/', ':', ';', '<', '=',
- '>', '?', '@', '[', ']', '^', '_', '`', '{', '|', '}', '~', '"'
+ '>', '?', '@', '[', ']', '^', '_', '`', '{', '-', '}', '~', '"'
};
typedef struct {
diff --git a/tracker/software/protocols/aprs/aprs.c b/tracker/software/protocols/aprs/aprs.c
index 4dd789e..b06c227 100644
--- a/tracker/software/protocols/aprs/aprs.c
+++ b/tracker/software/protocols/aprs/aprs.c
@@ -37,22 +37,18 @@ static uint16_t msg_id;
* - Number of satellites being used
* - Number of cycles where GPS has been lost (if applicable in cycle)
*/
-uint32_t aprs_encode_position(uint8_t* message, mod_t mod, const aprs_conf_t *config, trackPoint_t *trackPoint)
+void aprs_encode_position(ax25_t* packet, const aprs_conf_t *config, trackPoint_t *trackPoint)
{
char temp[22];
ptime_t date = trackPoint->time;
- ax25_t packet;
- packet.data = message;
- packet.max_size = 512; // TODO: replace 512 with real size
- packet.mod = mod;
- ax25_init(&packet);
- ax25_send_header(&packet, config->callsign, config->ssid, config->path, config->preamble);
- ax25_send_byte(&packet, '/'); // Report w/ timestamp, no APRS messaging. $ = NMEA raw data
+ // Encode header
+ ax25_send_header(packet, config->callsign, config->ssid, config->path, packet->size > 0 ? 0 : config->preamble);
+ ax25_send_byte(packet, '/');
// 170915 = 17h:09m:15s zulu (not allowed in Status Reports)
chsnprintf(temp, sizeof(temp), "%02d%02d%02dh", date.hour, date.minute, date.second);
- ax25_send_string(&packet, temp);
+ ax25_send_string(packet, temp);
// Latitude
uint32_t y = 380926 * (90 - trackPoint->gps_lat/10000000.0);
@@ -77,7 +73,7 @@ uint32_t aprs_encode_position(uint8_t* message, mod_t mod, const aprs_conf_t *co
uint32_t a1 = a / 91;
uint32_t a1r = a % 91;
- uint8_t gpsFix = trackPoint->gps_lock ? GSP_FIX_OLD : GSP_FIX_CURRENT;
+ uint8_t gpsFix = trackPoint->gps_lock == GPS_LOCKED ? GSP_FIX_CURRENT : GSP_FIX_OLD;
uint8_t src = NMEA_SRC_GGA;
uint8_t origin = ORIGIN_PICO;
@@ -96,52 +92,51 @@ uint32_t aprs_encode_position(uint8_t* message, mod_t mod, const aprs_conf_t *co
temp[12] = ((gpsFix << 5) | (src << 3) | origin) + 33;
temp[13] = 0;
- ax25_send_string(&packet, temp);
+ ax25_send_string(packet, temp);
// Comments
- ax25_send_string(&packet, "SATS ");
+ ax25_send_string(packet, "SATS ");
chsnprintf(temp, sizeof(temp), "%d", trackPoint->gps_sats);
- ax25_send_string(&packet, temp);
+ ax25_send_string(packet, temp);
if(trackPoint->gps_lock == GPS_LOCKED) // GPS is locked
{
// TTFF (Time to first fix)
- ax25_send_string(&packet, " TTFF ");
+ ax25_send_string(packet, " TTFF ");
chsnprintf(temp, sizeof(temp), "%d", trackPoint->gps_ttff);
- ax25_send_string(&packet, temp);
- ax25_send_string(&packet, "sec");
+ ax25_send_string(packet, temp);
+ ax25_send_string(packet, "sec");
}
if(trackPoint->gps_lock == GPS_LOSS) { // No GPS lock
- ax25_send_string(&packet, " GPS LOSS ");
+ ax25_send_string(packet, " GPS LOSS ");
chsnprintf(temp, sizeof(temp), "%d", ++loss_of_gps_counter);
- ax25_send_string(&packet, temp);
+ ax25_send_string(packet, temp);
} else if(trackPoint->gps_lock == GPS_LOWBATT) { // GPS switched off prematurely
- ax25_send_string(&packet, " GPS LOWBATT ");
+ ax25_send_string(packet, " GPS LOWBATT ");
chsnprintf(temp, sizeof(temp), "%d", ++loss_of_gps_counter);
- ax25_send_string(&packet, temp);
+ ax25_send_string(packet, temp);
} else if(trackPoint->gps_lock == GPS_LOG) { // GPS position from log (because the tracker has been just switched on)
- ax25_send_string(&packet, " GPS FROM LOG");
+ ax25_send_string(packet, " GPS FROM LOG");
loss_of_gps_counter = 0;
} else {
loss_of_gps_counter = 0;
}
- temp[2] = 0;
-
- ax25_send_byte(&packet, '|');
+ ax25_send_byte(packet, '|');
// Sequence ID
uint32_t t = trackPoint->id & 0x1FFF;
temp[0] = t/91 + 33;
temp[1] = t%91 + 33;
- ax25_send_string(&packet, temp);
+ temp[2] = 0;
+ ax25_send_string(packet, temp);
// Telemetry parameter
for(uint8_t i=0; i<5; i++) {
@@ -159,62 +154,83 @@ uint32_t aprs_encode_position(uint8_t* message, mod_t mod, const aprs_conf_t *co
temp[0] = t/91 + 33;
temp[1] = t%91 + 33;
- ax25_send_string(&packet, temp);
+ ax25_send_string(packet, temp);
}
- ax25_send_byte(&packet, '|');
-
- ax25_send_footer(&packet);
- scramble(&packet);
- nrzi_encode(&packet);
-
- return packet.size;
-}
-
-/**
- * Transmit custom experimental packet
- */
-uint32_t aprs_encode_experimental(char packetType, uint8_t* message, mod_t mod, const aprs_conf_t *config, uint8_t *data, size_t size)
-{
- ax25_t packet;
- packet.data = message;
- packet.max_size = 512; // TODO: replace 512 with real size
- packet.mod = mod;
-
- // Encode APRS header
- ax25_init(&packet);
- ax25_send_header(&packet, config->callsign, config->ssid, config->path, config->preamble);
- ax25_send_string(&packet, "{{");
- ax25_send_byte(&packet, packetType);
-
- // Encode message
- for(uint16_t i=0; idata = message;
- packet->max_size = 8192; // TODO: replace 8192 with real size
+ packet->data = buffer;
+ packet->max_size = size;
packet->mod = mod;
// Encode APRS header
ax25_init(packet);
}
-uint32_t aprs_encode_packet_encodePacket(ax25_t* packet, char packetType, const aprs_conf_t *config, uint8_t *data, size_t size)
+void aprs_encode_data_packet(ax25_t* packet, char packetType, const aprs_conf_t *config, uint8_t *data, size_t size, trackPoint_t *trackPoint)
{
+ char temp[13];
+ ptime_t date = trackPoint->time;
+
// Encode header
ax25_send_header(packet, config->callsign, config->ssid, config->path, packet->size > 0 ? 0 : config->preamble);
+ ax25_send_byte(packet, '/');
+
+ // 170915 = 17h:09m:15s zulu (not allowed in Status Reports)
+ chsnprintf(temp, sizeof(temp), "%02d%02d%02dh", date.hour, date.minute, date.second);
+ ax25_send_string(packet, temp);
+
+ // Latitude
+ uint32_t y = 380926 * (90 - trackPoint->gps_lat/10000000.0);
+ uint32_t y3 = y / 753571;
+ uint32_t y3r = y % 753571;
+ uint32_t y2 = y3r / 8281;
+ uint32_t y2r = y3r % 8281;
+ uint32_t y1 = y2r / 91;
+ uint32_t y1r = y2r % 91;
+
+ // Longitude
+ uint32_t x = 190463 * (180 + trackPoint->gps_lon/10000000.0);
+ uint32_t x3 = x / 753571;
+ uint32_t x3r = x % 753571;
+ uint32_t x2 = x3r / 8281;
+ uint32_t x2r = x3r % 8281;
+ uint32_t x1 = x2r / 91;
+ uint32_t x1r = x2r % 91;
+
+ // Altitude
+ uint32_t a = logf(METER_TO_FEET(trackPoint->gps_alt)) / logf(1.002f);
+ uint32_t a1 = a / 91;
+ uint32_t a1r = a % 91;
+
+ uint8_t gpsFix = trackPoint->gps_lock == GPS_LOCKED ? GSP_FIX_CURRENT : GSP_FIX_OLD;
+ uint8_t src = NMEA_SRC_GGA;
+ uint8_t origin = ORIGIN_PICO;
+
+ temp[0] = (config->symbol >> 8) & 0xFF;
+ temp[1] = y3+33;
+ temp[2] = y2+33;
+ temp[3] = y1+33;
+ temp[4] = y1r+33;
+ temp[5] = x3+33;
+ temp[6] = x2+33;
+ temp[7] = x1+33;
+ temp[8] = x1r+33;
+ temp[9] = config->symbol & 0xFF;
+ temp[10] = a1+33;
+ temp[11] = a1r+33;
+ temp[12] = ((gpsFix << 5) | (src << 3) | origin) + 33;
+ temp[13] = 0;
+
+ ax25_send_string(packet, temp);
ax25_send_byte(packet, packetType);
// Encode message
@@ -223,10 +239,8 @@ uint32_t aprs_encode_packet_encodePacket(ax25_t* packet, char packetType, const
// Encode footer
ax25_send_footer(packet);
-
- return packet->size;
}
-uint32_t aprs_encode_packet_finalize(ax25_t* packet)
+uint32_t aprs_encode_finalize(ax25_t* packet)
{
scramble(packet);
nrzi_encode(packet);
@@ -236,91 +250,78 @@ uint32_t aprs_encode_packet_finalize(ax25_t* packet)
/**
* Transmit message packet
*/
-uint32_t aprs_encode_message(uint8_t* message, mod_t mod, const aprs_conf_t *config, const char *receiver, const char *text)
+void aprs_encode_message(ax25_t* packet, const aprs_conf_t *config, const char *receiver, const char *text)
{
- ax25_t packet;
- packet.data = message;
- packet.max_size = 512; // TODO: replace 512 with real size
- packet.mod = mod;
-
- // Encode APRS header
char temp[10];
- ax25_init(&packet);
- ax25_send_header(&packet, config->callsign, config->ssid, config->path, config->preamble);
- ax25_send_byte(&packet, ':');
+
+ // Encode header
+ ax25_send_header(packet, config->callsign, config->ssid, config->path, packet->size > 0 ? 0 : config->preamble);
+ ax25_send_byte(packet, ':');
chsnprintf(temp, sizeof(temp), "%-9s", receiver);
- ax25_send_string(&packet, temp);
+ ax25_send_string(packet, temp);
- ax25_send_byte(&packet, ':');
- ax25_send_string(&packet, text);
- ax25_send_byte(&packet, '{');
+ ax25_send_byte(packet, ':');
+ ax25_send_string(packet, text);
+ ax25_send_byte(packet, '{');
chsnprintf(temp, sizeof(temp), "%d", ++msg_id);
- ax25_send_string(&packet, temp);
+ ax25_send_string(packet, temp);
// Encode footer
- ax25_send_footer(&packet);
- scramble(&packet);
- nrzi_encode(&packet);
-
- return packet.size;
+ ax25_send_footer(packet);
}
/**
* Transmit APRS telemetry configuration
*/
-uint32_t aprs_encode_telemetry_configuration(uint8_t* message, mod_t mod, const aprs_conf_t *config, const telemetry_conf_t type)
+void aprs_encode_telemetry_configuration(ax25_t* packet, const aprs_conf_t *config, const telemetry_conf_t type)
{
char temp[4];
- ax25_t packet;
- packet.data = message;
- packet.max_size = 512; // TODO: replace 512 with real size
- packet.mod = mod;
- ax25_init(&packet);
- ax25_send_header(&packet, config->callsign, config->ssid, config->path, config->preamble); // Header
- ax25_send_byte(&packet, ':'); // Message flag
+ // Encode header
+ ax25_send_header(packet, config->callsign, config->ssid, config->path, packet->size > 0 ? 0 : config->preamble);
+ ax25_send_byte(packet, ':'); // Message flag
// Callsign
- ax25_send_string(&packet, config->callsign);
- ax25_send_byte(&packet, '-');
+ ax25_send_string(packet, config->callsign);
+ ax25_send_byte(packet, '-');
chsnprintf(temp, sizeof(temp), "%d", config->ssid);
- ax25_send_string(&packet, temp);
+ ax25_send_string(packet, temp);
// Padding
uint8_t length = strlen(config->callsign) + (config->ssid/10);
for(uint8_t i=length; i<7; i++)
- ax25_send_string(&packet, " ");
+ ax25_send_string(packet, " ");
- ax25_send_string(&packet, ":"); // Message separator
+ ax25_send_string(packet, ":"); // Message separator
switch(type) {
case CONF_PARM: // Telemetry parameter names
- ax25_send_string(&packet, "PARM.");
+ ax25_send_string(packet, "PARM.");
for(uint8_t i=0; i<5; i++) {
switch(config->tel[i]) {
- case TEL_SATS: ax25_send_string(&packet, "Sats"); break;
- case TEL_TTFF: ax25_send_string(&packet, "TTFF"); break;
- case TEL_VBAT: ax25_send_string(&packet, "Vbat"); break;
- case TEL_VSOL: ax25_send_string(&packet, "Vsol"); break;
- case TEL_PBAT: ax25_send_string(&packet, "Pbat"); break;
- case TEL_RBAT: ax25_send_string(&packet, "Rbat"); break;
- case TEL_HUM: ax25_send_string(&packet, "Humidity"); break;
- case TEL_PRESS: ax25_send_string(&packet, "Airpressure"); break;
- case TEL_TEMP: ax25_send_string(&packet, "Temperature"); break;
+ case TEL_SATS: ax25_send_string(packet, "Sats"); break;
+ case TEL_TTFF: ax25_send_string(packet, "TTFF"); break;
+ case TEL_VBAT: ax25_send_string(packet, "Vbat"); break;
+ case TEL_VSOL: ax25_send_string(packet, "Vsol"); break;
+ case TEL_PBAT: ax25_send_string(packet, "Pbat"); break;
+ case TEL_RBAT: ax25_send_string(packet, "Rbat"); break;
+ case TEL_HUM: ax25_send_string(packet, "Humidity"); break;
+ case TEL_PRESS: ax25_send_string(packet, "Airpressure"); break;
+ case TEL_TEMP: ax25_send_string(packet, "Temperature"); break;
}
if(i < 4)
- ax25_send_string(&packet, ",");
+ ax25_send_string(packet, ",");
}
break;
case CONF_UNIT: // Telemetry units
- ax25_send_string(&packet, "UNIT.");
+ ax25_send_string(packet, "UNIT.");
for(uint8_t i=0; i<5; i++) {
switch(config->tel[i]) {
@@ -328,89 +329,87 @@ uint32_t aprs_encode_telemetry_configuration(uint8_t* message, mod_t mod, const
break; // No unit
case TEL_TTFF:
- ax25_send_string(&packet, "sec");
+ ax25_send_string(packet, "sec");
break;
case TEL_VBAT:
case TEL_VSOL:
- ax25_send_string(&packet, "V");
+ ax25_send_string(packet, "V");
break;
case TEL_PBAT:
- ax25_send_string(&packet, "W");
+ ax25_send_string(packet, "W");
break;
case TEL_RBAT:
- ax25_send_string(&packet, "Ohm");
+ ax25_send_string(packet, "Ohm");
break;
case TEL_HUM:
- ax25_send_string(&packet, "%");
+ ax25_send_string(packet, "%");
break;
case TEL_PRESS:
- ax25_send_string(&packet, "Pa");
+ ax25_send_string(packet, "Pa");
break;
case TEL_TEMP:
- ax25_send_string(&packet, "degC");
+ ax25_send_string(packet, "degC");
break;
}
if(i < 4)
- ax25_send_string(&packet, ",");
+ ax25_send_string(packet, ",");
}
break;
case CONF_EQNS: // Telemetry conversion parameters
- ax25_send_string(&packet, "EQNS.");
+ ax25_send_string(packet, "EQNS.");
for(uint8_t i=0; i<5; i++) {
switch(config->tel[i]) {
case TEL_SATS:
case TEL_TTFF:
- ax25_send_string(&packet, "0,1,0");
+ ax25_send_string(packet, "0,1,0");
break;
case TEL_VBAT:
case TEL_VSOL:
case TEL_RBAT:
- ax25_send_string(&packet, "0,.001,0");
+ ax25_send_string(packet, "0,.001,0");
break;
case TEL_PBAT:
- ax25_send_string(&packet, "0,.001,-4.096");
+ ax25_send_string(packet, "0,.001,-4.096");
break;
case TEL_HUM:
- ax25_send_string(&packet, "0,.1,0");
+ ax25_send_string(packet, "0,.1,0");
break;
case TEL_PRESS:
- ax25_send_string(&packet, "0,12.5,500");
+ ax25_send_string(packet, "0,12.5,500");
break;
case TEL_TEMP:
- ax25_send_string(&packet, "0,.1,-100");
+ ax25_send_string(packet, "0,.1,-100");
break;
}
if(i < 4)
- ax25_send_string(&packet, ",");
+ ax25_send_string(packet, ",");
}
break;
case CONF_BITS:
- ax25_send_string(&packet, "BITS.11111111,");
- ax25_send_string(&packet, config->tel_comment);
+ ax25_send_string(packet, "BITS.11111111,");
+ ax25_send_string(packet, config->tel_comment);
break;
}
- ax25_send_footer(&packet); // Footer
- scramble(&packet);
- nrzi_encode(&packet);
-
- return packet.size;
+
+ // Encode footer
+ ax25_send_footer(packet);
}
diff --git a/tracker/software/protocols/aprs/aprs.h b/tracker/software/protocols/aprs/aprs.h
index 09404b6..ad94e94 100644
--- a/tracker/software/protocols/aprs/aprs.h
+++ b/tracker/software/protocols/aprs/aprs.h
@@ -49,14 +49,13 @@
#define SYM_CAR 0x2F3E
#define SYM_SHIP 0x2F73
-uint32_t aprs_encode_position(uint8_t* message, mod_t mod, const aprs_conf_t *config, trackPoint_t *trackPoint);
-uint32_t aprs_encode_telemetry_configuration(uint8_t* message, mod_t mod, const aprs_conf_t *config, const telemetry_conf_t type);
-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_position(ax25_t* packet, const aprs_conf_t *config, trackPoint_t *trackPoint);
+void aprs_encode_telemetry_configuration(ax25_t* packet, const aprs_conf_t *config, const telemetry_conf_t type);
+void aprs_encode_message(ax25_t* packet, const aprs_conf_t *config, const char *receiver, const char *text);
-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);
+void aprs_encode_init(ax25_t* packet, uint8_t* buffer, uint16_t size, mod_t mod);
+void aprs_encode_data_packet(ax25_t* packet, char packetType, const aprs_conf_t *config, uint8_t *data, size_t size, trackPoint_t *trackPoint);
+uint32_t aprs_encode_finalize(ax25_t* packet);
#endif
diff --git a/tracker/software/radio.c b/tracker/software/radio.c
index 09ca294..fb09c07 100644
--- a/tracker/software/radio.c
+++ b/tracker/software/radio.c
@@ -351,7 +351,7 @@ bool transmitOnRadio(radioMSG_t *msg, bool shutdown)
// Copy data
memcpy(&radio_msg, msg, sizeof(radioMSG_t));
- memcpy(&radio_buffer, msg->buffer, msg->buffer_len);
+ memcpy(&radio_buffer, msg->buffer, sizeof(radio_buffer));
radio_msg.buffer = radio_buffer;
radio_freq = freq;
diff --git a/tracker/software/threads/image.c b/tracker/software/threads/image.c
index c5374fb..687f55b 100644
--- a/tracker/software/threads/image.c
+++ b/tracker/software/threads/image.c
@@ -279,7 +279,7 @@ uint8_t gimage_id; // Global image ID (for all image threads)
mutex_t camera_mtx;
bool camera_mtx_init = false;
-void encode_ssdv(const uint8_t *image, uint32_t image_len, module_conf_t* conf, uint8_t image_id, bool redudantTx)
+void encode_ssdv(const uint8_t *image, uint32_t image_len, module_conf_t* conf, uint8_t image_id, trackPoint_t* captureLocation, bool redudantTx)
{
ssdv_t ssdv;
uint8_t pkt[SSDV_PKT_SIZE];
@@ -298,7 +298,6 @@ void encode_ssdv(const uint8_t *image, uint32_t image_len, module_conf_t* conf,
radioMSG_t msg;
uint8_t buffer[conf->packet_spacing ? 8192 : 512];
msg.buffer = buffer;
- msg.buffer_len = sizeof(buffer);
msg.bin_len = 0;
msg.freq = &conf->frequency;
msg.power = conf->power;
@@ -309,7 +308,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_packet_init(&ax25_handle, msg.buffer, msg.mod);
+ aprs_encode_init(&ax25_handle, buffer, sizeof(buffer), msg.mod);
}
while(true)
@@ -325,12 +324,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_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) msg.bin_len = aprs_encode_finalize(&ax25_handle);
+ if(ax25_handle.size > 0) transmitOnRadio(&msg, false); // Empty buffer
if(conf->protocol == PROT_APRS_2GFSK || conf->protocol == PROT_APRS_AFSK)
{
- aprs_encode_packet_init(&ax25_handle, msg.buffer, msg.mod);
- msg.bin_len = 0;
+ aprs_encode_init(&ax25_handle, buffer, sizeof(buffer), msg.mod);
}
break;
}
@@ -340,22 +338,20 @@ 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_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) msg.bin_len = aprs_encode_finalize(&ax25_handle);
+ if(ax25_handle.size > 0) transmitOnRadio(&msg, false); // Empty buffer
if(conf->protocol == PROT_APRS_2GFSK || conf->protocol == PROT_APRS_AFSK)
{
- aprs_encode_packet_init(&ax25_handle, msg.buffer, msg.mod);
- msg.bin_len = 0;
+ aprs_encode_init(&ax25_handle, buffer, sizeof(buffer), msg.mod);
}
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_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) msg.bin_len = aprs_encode_finalize(&ax25_handle);
+ if(ax25_handle.size > 0) transmitOnRadio(&msg, false); // Empty buffer
if(conf->protocol == PROT_APRS_2GFSK || conf->protocol == PROT_APRS_AFSK)
{
- aprs_encode_packet_init(&ax25_handle, msg.buffer, msg.mod);
- msg.bin_len = 0;
+ aprs_encode_init(&ax25_handle, buffer, sizeof(buffer), msg.mod);
}
return;
}
@@ -367,20 +363,19 @@ void encode_ssdv(const uint8_t *image, uint32_t image_len, module_conf_t* conf,
TRACE_INFO("IMG > Encode APRS/SSDV packet");
base91_encode(&pkt[6], pkt_base91, 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_base91, strlen((char*)pkt_base91));
+ aprs_encode_data_packet(&ax25_handle, 'I', &conf->aprs_conf, pkt_base91, strlen((char*)pkt_base91), captureLocation);
if(redudantTx)
- msg.bin_len = aprs_encode_packet_encodePacket(&ax25_handle, '!', &conf->aprs_conf, pkt_base91, strlen((char*)pkt_base91));
+ aprs_encode_data_packet(&ax25_handle, 'I', &conf->aprs_conf, pkt_base91, strlen((char*)pkt_base91), captureLocation);
// 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)
+ if(ax25_handle.size >= 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_packet_finalize(&ax25_handle);
+ msg.bin_len = aprs_encode_finalize(&ax25_handle);
transmitOnRadio(&msg, false);
// Initialize new packet buffer
- aprs_encode_packet_init(&ax25_handle, msg.buffer, msg.mod);
- msg.bin_len = 0;
+ aprs_encode_init(&ax25_handle, buffer, sizeof(buffer), msg.mod);
}
break;
@@ -487,13 +482,17 @@ THD_FUNCTION(imgThread, arg) {
bool camera_found = takePicture(&conf->ssdv_conf, true);
gimage_id++; // Increase SSDV image counter
+ // Get capture location
+ trackPoint_t captureLocation;
+ memcpy(&captureLocation, getLastTrackPoint(), sizeof(trackPoint_t));
+
// Radio transmission
if(camera_found) {
TRACE_INFO("IMG > Encode/Transmit SSDV ID=%d", gimage_id-1);
- encode_ssdv(conf->ssdv_conf.ram_buffer, conf->ssdv_conf.size_sampled, conf, gimage_id-1, conf->ssdv_conf.redundantTx);
+ encode_ssdv(conf->ssdv_conf.ram_buffer, conf->ssdv_conf.size_sampled, conf, gimage_id-1, &captureLocation, conf->ssdv_conf.redundantTx);
} else { // No camera found
TRACE_INFO("IMG > Encode/Transmit SSDV (no cam found) ID=%d", gimage_id-1);
- encode_ssdv(noCameraFound, sizeof(noCameraFound), conf, gimage_id-1, conf->ssdv_conf.redundantTx);
+ encode_ssdv(noCameraFound, sizeof(noCameraFound), conf, gimage_id-1, &captureLocation, conf->ssdv_conf.redundantTx);
}
}
diff --git a/tracker/software/threads/log.c b/tracker/software/threads/log.c
index 4b12765..3a48f14 100644
--- a/tracker/software/threads/log.c
+++ b/tracker/software/threads/log.c
@@ -145,8 +145,8 @@ THD_FUNCTION(logThread, arg)
{
// Get log from memory
- uint16_t pkt[64]; // 16 PositionPoints each 10 bytes
- uint8_t pkt_base91[BASE91LEN(128)];
+ uint16_t pkt[80]; // 16 PositionPoints each 10 bytes
+ uint8_t pkt_base91[BASE91LEN(160)];
for(uint16_t t=0; t Encode 16 log points")
@@ -156,21 +156,26 @@ THD_FUNCTION(logThread, arg)
trackPoint_t log;
getNextLogTrackPoint(&log);
- TRACE_INFO("date=%02d.%02d. time=%02d:%02d lat=%d lon=%d alt=%d", log.time.day, log.time.month, log.time.hour, log.time.minute, log.gps_lat, log.gps_lon, log.gps_alt);
+ TRACE_INFO("id=%d date=%04d-%02d-%02d time=%02d:%02d:%02d lat=%d lon=%d alt=%d", log.id, log.time.year, log.time.month, log.time.day, log.time.hour, log.time.minute,log.time.second, log.gps_lat, log.gps_lon, log.gps_alt);
+ int64_t lat = (int64_t)log.gps_lat + (int64_t)900000000 + 13733;
+ lat <<= 16;
+ lat /= 1800000000;
+ int64_t lon = (int64_t)log.gps_lon + (int64_t)1800000000 + 27466;
+ lon <<= 16;
+ lon /= 3600000000;
- pkt[i*4+0] = (log.time.minute/10) + (6*log.time.hour) + (144*(log.time.day-1)) + (4464*(log.time.month-1)); // Time/Date of year (1 = 5min, all monthes have 31days, day and month starts at 0)
- pkt[i*4+1] = (((uint64_t)((uint64_t)log.gps_lat + 900000000)) * 65535) / 1800000000; // Latitude (get full 16bit resolution over 180°)
- pkt[i*4+2] = (((uint64_t)((uint64_t)log.gps_lon + 1800000000)) * 65535) / 3600000000; // Longitude (get full 16bit resolution over 360°)
- pkt[i*4+3] = log.gps_alt; // Altitude in meters (cut off first two MSB bytes)
-
- TRACE_INFO("%04x %04x %04x %04x", pkt[i*4+0], pkt[i*4+1], pkt[i*4+2], pkt[i*4+3]);
+ uint32_t time = date2UnixTimestamp(log.time) / 1000;
+ pkt[i*5+0] = time & 0xFFFF;
+ pkt[i*5+1] = time >> 16;
+ pkt[i*5+2] = lat; // Latitude (get full 16bit resolution over 180°)
+ pkt[i*5+3] = lon; // Longitude (get full 16bit resolution over 360°)
+ pkt[i*5+4] = log.gps_alt; // Altitude in meters (cut off first two MSB bytes)
}
// Encode radio message
radioMSG_t msg;
- uint8_t buffer[256];
+ uint8_t buffer[512];
msg.buffer = buffer;
- msg.buffer_len = sizeof(buffer);
msg.freq = &conf->frequency;
msg.power = conf->power;
@@ -181,10 +186,18 @@ THD_FUNCTION(logThread, arg)
msg.afsk_conf = &(conf->afsk_conf);
msg.gfsk_conf = &(conf->gfsk_conf);
- base91_encode((uint8_t*)pkt, pkt_base91, sizeof(pkt)); // Encode base 91
- msg.bin_len = aprs_encode_experimental('L', msg.buffer, msg.mod, &conf->aprs_conf, pkt_base91, strlen((char*)pkt_base91)); // Encode APRS
+ ax25_t ax25_handle;
- transmitOnRadio(&msg, true); // Transmit packet
+ // Encode Base91
+ base91_encode((uint8_t*)pkt, pkt_base91, sizeof(pkt));
+
+ // Encode and transmit log packet
+ aprs_encode_init(&ax25_handle, buffer, sizeof(buffer), msg.mod);
+ aprs_encode_data_packet(&ax25_handle, 'L', &conf->aprs_conf, pkt_base91, strlen((char*)pkt_base91), getLastTrackPoint()); // Encode packet
+ msg.bin_len = aprs_encode_finalize(&ax25_handle);
+
+ // Transmit packet
+ transmitOnRadio(&msg, true);
break;
default:
diff --git a/tracker/software/threads/position.c b/tracker/software/threads/position.c
index 40a6fa3..6b24888 100644
--- a/tracker/software/threads/position.c
+++ b/tracker/software/threads/position.c
@@ -130,7 +130,6 @@ THD_FUNCTION(posThread, arg) {
radioMSG_t msg;
uint8_t buffer[256];
msg.buffer = buffer;
- msg.buffer_len = sizeof(buffer);
msg.freq = &conf->frequency;
msg.power = conf->power;
@@ -143,7 +142,12 @@ THD_FUNCTION(posThread, arg) {
msg.gfsk_conf = &(conf->gfsk_conf);
msg.afsk_conf = &(conf->afsk_conf);
- msg.bin_len = aprs_encode_position(msg.buffer, msg.mod, &(conf->aprs_conf), trackPoint); // Encode packet
+ ax25_t ax25_handle;
+
+ // Encode and transmit position packet
+ aprs_encode_init(&ax25_handle, buffer, sizeof(buffer), msg.mod);
+ aprs_encode_position(&ax25_handle, &(conf->aprs_conf), trackPoint); // Encode packet
+ msg.bin_len = aprs_encode_finalize(&ax25_handle);
transmitOnRadio(&msg, true);
// Telemetry encoding parameter transmission
@@ -162,7 +166,11 @@ THD_FUNCTION(posThread, arg) {
chThdSleepMilliseconds(5000); // Take a litte break between the package transmissions
const telemetry_conf_t tel_conf[] = {CONF_PARM, CONF_UNIT, CONF_EQNS, CONF_BITS};
- msg.bin_len = aprs_encode_telemetry_configuration(msg.buffer, msg.mod, &(conf->aprs_conf), tel_conf[current_conf_count]); // Encode packet
+
+ // Encode and transmit telemetry config packet
+ aprs_encode_init(&ax25_handle, buffer, sizeof(buffer), msg.mod);
+ aprs_encode_telemetry_configuration(&ax25_handle, &conf->aprs_conf, tel_conf[current_conf_count]);
+ msg.bin_len = aprs_encode_finalize(&ax25_handle);
transmitOnRadio(&msg, true);
current_conf_count++;
diff --git a/tracker/software/threads/threads.c b/tracker/software/threads/threads.c
index eea9e11..3077367 100644
--- a/tracker/software/threads/threads.c
+++ b/tracker/software/threads/threads.c
@@ -1,7 +1,6 @@
#include "ch.h"
#include "hal.h"
-#include "threads.h"
#include "tracking.h"
#include "watchdog.h"
#include "pi2c.h"
@@ -14,5 +13,6 @@ void start_essential_threads(void) {
pi2cInit(); // Initialize I2C
pac1720_init(); // Initialize current measurement
init_tracking_manager(false); // Initialize tracking manager (without GPS, GPS is initialized if needed by position thread)
+ chThdSleepMilliseconds(50); // Wait for tracking manager to initialize
}
diff --git a/tracker/software/threads/tracking.c b/tracker/software/threads/tracking.c
index b76ae3f..2a844e3 100644
--- a/tracker/software/threads/tracking.c
+++ b/tracker/software/threads/tracking.c
@@ -154,6 +154,7 @@ THD_FUNCTION(trackingThread, arg) {
if(lastLogPoint != NULL) { // If there has been stored a trackpoint, then get the last know GPS fix
TRACE_INFO("TRAC > Found track point in flash memory ID=%d", lastLogPoint->id);
+ id = lastLogPoint->id+1;
lastTrackPoint->gps_lat = lastLogPoint->gps_lat;
lastTrackPoint->gps_lon = lastLogPoint->gps_lon;
lastTrackPoint->gps_alt = lastLogPoint->gps_alt;
@@ -295,7 +296,7 @@ THD_FUNCTION(trackingThread, arg) {
// Mark GPS loss (or low batt, GPS switch off)
if(tracking_useGPS)
- tp->gps_lock = batt < gps_off_vbat ? GPS_LOWBATT : GPS_LOSS;
+ tp->gps_lock = batt < gps_off_vbat || batt < gps_on_vbat ? GPS_LOWBATT : GPS_LOSS;
else
tp->gps_lock = GPS_OFF;
tp->gps_sats = 0;
diff --git a/tracker/software/threads/tracking.h b/tracker/software/threads/tracking.h
index ae2203a..0331d7a 100644
--- a/tracker/software/threads/tracking.h
+++ b/tracker/software/threads/tracking.h
@@ -21,7 +21,7 @@ typedef struct {
gpsLock_t gps_lock; // 0: locked, 1: GPS loss, 2: low power (switched off), 3: taken from log, 4: GPS switch off permanently
int32_t gps_lat; // Latitude in °*10^7
int32_t gps_lon; // Longitude in °*10^7
- int32_t gps_alt; // Altitude in meter
+ uint16_t gps_alt; // Altitude in meter
uint8_t gps_sats; // Satellites used for solution
uint8_t gps_ttff; // Time to first fix in seconds
@@ -37,7 +37,7 @@ typedef struct {
uint16_t air_hum; // Rel. humidity in %*10 (in 0.1%)
int16_t air_temp; // Temperature in degC*100 (in 0.01°C)
- int8_t id_image; // Last image ID (this is important because it will set the image counter at reset so the last image wont get overwritten with the same image ID)
+ uint8_t id_image; // Last image ID (this is important because it will set the image counter at reset so the last image wont get overwritten with the same image ID)
} trackPoint_t;
void waitForNewTrackPoint(void);
diff --git a/tracker/software/types.h b/tracker/software/types.h
index a75103b..0b2eba8 100644
--- a/tracker/software/types.h
+++ b/tracker/software/types.h
@@ -98,7 +98,6 @@ typedef struct {
typedef struct { // Radio message type
uint8_t* buffer; // Message (data)
- uint16_t buffer_len; // Buffer size (in bytes)
uint32_t bin_len; // Binary length (it bits)
int8_t power; // Power in dBm
mod_t mod; // Modulation