From c745ef50c9ed718e5ec9f6029db356af341a8f51 Mon Sep 17 00:00:00 2001 From: Sven Steudte Date: Tue, 9 Jan 2018 06:01:19 +0100 Subject: [PATCH] Updated APRS protocols and much more - Removed secondary decoder - Updated image encoding at tracker firmware - Updated image encoding at decoder software - Implemented more sophisticated website - Added error transmission - Adjusted MCU speed to the highest rate - Implemented configuration that allows GPS to be switched on permanently at a certain battery voltage - Decreased humidity sensor accuray - Imcreased voltage measurement accuracy - Added temperature measurements of STM32 and Si4464 to TrackPoint struct - Added light intensity measurements of OV5640 to TrackPoint struct - Cleaned up (removed unused things) - Implemented more accurate measurements for PAC1720 - Implemented failure detection for PAC1720 and ublox chips - Fixed bug in Si4464 driver which used power when switched off - Added more data readouts for GPS receiver (pDOP, gpsFixOK) - Changed way of determination if GPS fix is good - Implemented temperature measurement of STM32 - Added error detection of I2C bus - Removed Milliseconds from ptime_t - Fixed bug in timestamp conversion - Removed RBAT measurement implementation (it was very inaccurate) - Avoid radio being switched off when next packet is waiting for being transmitted - Tidied up tracking manager --- decoder/decoder.py | 113 +++-- decoder/html/Database.class.php | 51 ++ decoder/html/Image.class.php | 19 + decoder/html/Telemetry.class.php | 168 +++++++ decoder/html/Tracker.class.php | 133 +++++ decoder/html/ajax/telemetry.php | 16 + decoder/html/data.php | 13 - decoder/html/database.class.php | 49 -- decoder/html/footer.inc.php | 3 + decoder/html/header.inc.php | 23 + decoder/html/helper.inc.php | 11 + decoder/html/images.php | 124 +++++ decoder/html/index (copy 1).php | 103 ++++ decoder/html/index.php | 104 +--- decoder/html/sidebar.inc.php | 23 + decoder/html/style.css | 42 ++ decoder/html/telemetry.php | 591 +++++++++++++++++++++++ decoder/image.py | 219 ++++----- decoder/pecan_rx_gui/base91.py | 93 ---- decoder/pecan_rx_gui/decoder.py | 178 ------- decoder/pecan_rx_gui/ssdv | Bin 130616 -> 0 bytes decoder/pecan_rx_gui/ssdv_OSX10.11.6 | Bin 49612 -> 0 bytes decoder/position.py | 52 +- decoder/ssdv | Bin 130616 -> 271280 bytes tracker/software/config.c | 10 +- tracker/software/config.h | 3 +- tracker/software/debug.c | 10 +- tracker/software/debug.h | 6 - tracker/software/drivers/bme280.c | 4 +- tracker/software/drivers/bme280.h | 2 +- tracker/software/drivers/ov5640.c | 43 +- tracker/software/drivers/ov5640.h | 4 +- tracker/software/drivers/pac1720.c | 190 ++++---- tracker/software/drivers/pac1720.h | 15 +- tracker/software/drivers/si4464.c | 27 +- tracker/software/drivers/si4464.h | 3 +- tracker/software/drivers/ublox.c | 51 +- tracker/software/drivers/ublox.h | 4 +- tracker/software/drivers/wrapper/padc.c | 26 +- tracker/software/drivers/wrapper/padc.h | 8 +- tracker/software/drivers/wrapper/pi2c.c | 11 + tracker/software/drivers/wrapper/pi2c.h | 2 + tracker/software/drivers/wrapper/ptime.c | 70 ++- tracker/software/drivers/wrapper/ptime.h | 7 +- tracker/software/mcuconf.h | 8 +- tracker/software/protocols/aprs/aprs.c | 134 +---- tracker/software/protocols/aprs/aprs.h | 2 +- tracker/software/protocols/aprs/ax25.c | 2 +- tracker/software/protocols/ssdv/ssdv.c | 24 + tracker/software/protocols/ssdv/ssdv.h | 2 + tracker/software/radio.c | 35 +- tracker/software/radio.h | 1 + tracker/software/sleep.c | 12 +- tracker/software/threads/image.c | 49 +- tracker/software/threads/log.c | 9 +- tracker/software/threads/position.c | 17 +- tracker/software/threads/threads.c | 2 +- tracker/software/threads/tracking.c | 391 +++++++-------- tracker/software/threads/tracking.h | 66 ++- tracker/software/threads/watchdog.c | 2 +- tracker/software/types.h | 7 +- 61 files changed, 2148 insertions(+), 1239 deletions(-) create mode 100644 decoder/html/Database.class.php create mode 100644 decoder/html/Image.class.php create mode 100644 decoder/html/Telemetry.class.php create mode 100644 decoder/html/Tracker.class.php create mode 100644 decoder/html/ajax/telemetry.php delete mode 100644 decoder/html/data.php delete mode 100644 decoder/html/database.class.php create mode 100644 decoder/html/footer.inc.php create mode 100644 decoder/html/header.inc.php create mode 100644 decoder/html/helper.inc.php create mode 100644 decoder/html/images.php create mode 100644 decoder/html/index (copy 1).php create mode 100644 decoder/html/sidebar.inc.php create mode 100644 decoder/html/style.css create mode 100644 decoder/html/telemetry.php delete mode 100644 decoder/pecan_rx_gui/base91.py delete mode 100755 decoder/pecan_rx_gui/decoder.py delete mode 100755 decoder/pecan_rx_gui/ssdv delete mode 100755 decoder/pecan_rx_gui/ssdv_OSX10.11.6 diff --git a/decoder/decoder.py b/decoder/decoder.py index d1233ee..fc0868d 100755 --- a/decoder/decoder.py +++ b/decoder/decoder.py @@ -1,6 +1,6 @@ #!/usr/bin/python3 -import serial,re +import serial,re,io import base91 import sys import argparse @@ -12,11 +12,10 @@ import position # Parse arguments from terminal parser = argparse.ArgumentParser(description='APRS/SSDV decoder') -parser.add_argument('-c', '--call', help='Callsign of the station', default='N0CALL') -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('-c', '--call', help='Callsign of the station', default='DL7AD') 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') +parser.add_argument('-v', '--verbose', help='Activates more debug messages', action="store_true") args = parser.parse_args() # Open SQLite database @@ -25,36 +24,58 @@ sqlite.cursor().execute(""" CREATE TABLE IF NOT EXISTS position ( call TEXT, - time INTEGER, + rxtime INTEGER, org TEXT, - lat FLOAT, - lon FLOAT, - alt INTEGER, - isnew INTEGER, - comment TEXT, - sequ INTEGER, - tel1 INTEGER, - tel2 INTEGER, - tel3 INTEGER, - tel4 INTEGER, - tel5 INTEGER, - PRIMARY KEY (call, time) + + reset INTEGER, + id INTEGER, + time INTEGER, + + adc_vsol INTEGER, + adc_vbat INTEGER, + pac_vsol INTEGER, + pac_vbat INTEGER, + pac_pbat INTEGER, + pac_psol INTEGER, + + light_intensity INTEGER, + + gps_time INTEGER, + gps_lock INTEGER, + gps_sats INTEGER, + gps_ttff INTEGER, + gps_pdop INTEGER, + gps_alt INTEGER, + gps_lat INTEGER, + gps_lon INTEGER, + + sen_i1_press INTEGER, + sen_e1_press INTEGER, + sen_e2_press INTEGER, + sen_i1_temp INTEGER, + sen_e1_temp INTEGER, + sen_e2_temp INTEGER, + sen_i1_hum INTEGER, + sen_e1_hum INTEGER, + sen_e2_hum INTEGER, + + stm32_temp INTEGER, + si4464_temp INTEGER, + + sys_time INTEGER, + sys_error INTEGER ) """) sqlite.cursor().execute(""" CREATE TABLE IF NOT EXISTS image ( + id INTEGER, call TEXT, - time INTEGER, + rxtime INTEGER, imageID INTEGER, packetID INTEGER, - lat FLOAT, - lon FLOAT, - alt INTEGER, - data1 TEXT, - data2 TEXT, - crc TEXT, - PRIMARY KEY (call, time, imageID, packetID) + data TEXT, + PRIMARY KEY (call,id,packetID) ) """) @@ -66,36 +87,35 @@ def received_data(data): # 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|J|L)(.*)", data) + all = re.search("(.*)\>APECAN(.*?):", data) + pos = re.search("(.*)\>APECAN(.*?):\!(.{13})(.*?)\|(.*)\|", data) + dat = re.search("(.*)\>APECAN(.*?):\{\{(I|L)(.*)", data) - if all: + if pos or dat: # Debug - print('='*100) - print(data) - print('-'*100) + if args.verbose: + print('='*100) + print(data.strip()) + print('-'*100) call = all.group(1).split(' ')[-1] rxer = all.group(2).split(',')[-1] if not len(rxer): rxer = args.call - 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) + posi = pos.group(3) + comm = pos.group(4) + tel = pos.group(5) + position.insert_position(sqlite, call, posi, comm, tel) elif dat: # Data packet - typ = dat.group(5) - data_b91 = dat.group(6) - data = base91.decode(data_b91) # Decode Base91 + typ = dat.group(3) + data = base91.decode(dat.group(4)) # Decode Base91 - if typ is 'I' or typ is 'J': # Image packet - image.insert_image(sqlite, rxer, call, tim, posi, data, typ, args.server, args.grouping) + if typ is 'I': # Image packet + image.insert_image(sqlite, rxer, call, data) elif typ is 'L': # Log packet position.insert_log(sqlite, call, data) @@ -111,12 +131,12 @@ if args.device == 'I': # Source APRS-IS print('exit...') sys.exit(1) - wdg = time.time() + 1 # Connection watchdog + wdg = time.time() + 10 # Connection watchdog buf = '' while True: # Read data try: - buf += tn.read_eager().decode('ascii') + buf += tn.read_eager().decode('charmap') except EOFError: # Server has connection closed wdg = 0 # Tell watchdog to restart connection except UnicodeDecodeError: @@ -146,7 +166,7 @@ if args.device == 'I': # Source APRS-IS 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 + wdg = time.time() + 10 except Exception as e: print('Could not connect to APRS-IS: %s' % str(e)) print('Try again...') @@ -156,8 +176,7 @@ if args.device == 'I': # Source APRS-IS elif args.device is '-': # Source stdin while True: - data = sys.stdin.readline() - received_data(data) + received_data(sys.stdin.readline()) else: # Source Serial connection diff --git a/decoder/html/Database.class.php b/decoder/html/Database.class.php new file mode 100644 index 0000000..14facd4 --- /dev/null +++ b/decoder/html/Database.class.php @@ -0,0 +1,51 @@ +open("/src/pecanpico9/decoder/decoder.sqlite"); + + if($this->lastErrorCode()) + echo $this->lastErrorMsg(); + } + + static function getInstance() { + if(self::$instance == null) + self::$instance = new Database(); + return self::$instance; + } + + function close() { + parent::close(); + } + + function getTracker() { + $tracker = array(); + + $query = $this->query(" + SELECT call,MAX(rxtime) + FROM ( + SELECT call,rxtime FROM position + UNION ALL + SELECT call,rxtime FROM image + ) + GROUP BY call + ORDER BY rxtime DESC + "); + while($row = $query->fetchArray(SQLITE3_ASSOC)) + $tracker[] = new Tracker($row['call']); + + return $tracker; + } +} +?> + + + + + + + + diff --git a/decoder/html/Image.class.php b/decoder/html/Image.class.php new file mode 100644 index 0000000..d74fc0e --- /dev/null +++ b/decoder/html/Image.class.php @@ -0,0 +1,19 @@ +id = $sqlResult['id']; + $this->call = $sqlResult['call']; + + $this->time_first = $sqlResult['time_first']; + $this->time_last = $sqlResult['time_last']; + + $this->imageID = $sqlResult['imageID']; + $this->packetID = $sqlResult['packetID']; + $this->count = $sqlResult['count']; + + } +} +?> + diff --git a/decoder/html/Telemetry.class.php b/decoder/html/Telemetry.class.php new file mode 100644 index 0000000..3175247 --- /dev/null +++ b/decoder/html/Telemetry.class.php @@ -0,0 +1,168 @@ +reset = $sqlResult['reset']; + $this->id = $sqlResult['id']; + + $this->rxtime = $sqlResult['rxtime']; + + $this->call = $sqlResult['call']; + + $this->adc_vsol = $sqlResult['adc_vsol']; + $this->adc_vbat = $sqlResult['adc_vbat']; + $this->pac_vsol = $sqlResult['pac_vsol']; + $this->pac_vbat = $sqlResult['pac_vbat']; + $this->pac_pbat = $sqlResult['pac_pbat']; + $this->pac_psol = $sqlResult['pac_psol']; + + $this->gps_time = $sqlResult['gps_time']; + $this->gps_lock = $sqlResult['gps_lock']; + $this->gps_sats = $sqlResult['gps_sats']; + $this->gps_ttff = $sqlResult['gps_ttff']; + $this->gps_pdop = $sqlResult['gps_pdop']; + $this->gps_alt = $sqlResult['gps_alt']; + $this->gps_lat = $sqlResult['gps_lat']; + $this->gps_lon = $sqlResult['gps_lon']; + + $this->sen_i1_press = $sqlResult['sen_i1_press']; + $this->sen_e1_press = $sqlResult['sen_e1_press']; + $this->sen_e2_press = $sqlResult['sen_e2_press']; + $this->sen_i1_temp = $sqlResult['sen_i1_temp']; + $this->sen_e1_temp = $sqlResult['sen_e1_temp']; + $this->sen_e2_temp = $sqlResult['sen_e2_temp']; + $this->sen_i1_hum = $sqlResult['sen_i1_hum']; + $this->sen_e1_hum = $sqlResult['sen_e1_hum']; + $this->sen_e2_hum = $sqlResult['sen_e2_hum']; + + $this->stm32_temp = $sqlResult['stm32_temp']; + $this->si4464_temp = $sqlResult['si4464_temp']; + + $this->light_intensity = $sqlResult['light_intensity']; + + $this->sys_time = $sqlResult['sys_time']; + $this->sys_error = $sqlResult['sys_error']; + + $this->err_i2c1 = ($this->sys_error >> 0) & 0x1; + $this->err_i2c2 = ($this->sys_error >> 1) & 0x1; + $this->err_eva7m = ($this->sys_error >> 2) & 0x1; + $this->err_pac1720 = ($this->sys_error >> 3) & 0x3; + $this->err_ov5640 = ($this->sys_error >> 5) & 0x3; + $this->err_bme280_i1 = ($this->sys_error >> 8) & 0x1; + $this->err_bme280_e1 = ($this->sys_error >> 9) & 0x1; + $this->err_bme280_e2 = ($this->sys_error >> 10) & 0x1; + + } + /*function getOV9655Error($type) { + $error = ($this->sys_error >> 4) & 0x3; + if($type == self::TYPE_INT) + return $error; + + switch($error) { + case 0: return $this->colorize($type, self::COL_GREEN, "OK"); + case 1: return $this->colorize($type, self::COL_RED, "I2C Error - Camera not found"); + case 2: return $this->colorize($type, self::COL_RED, "DMA abort - last buffer segment"); + case 3: return $this->colorize($type, self::COL_RED, "DMA FIFO error"); + case 4: return $this->colorize($type, self::COL_RED, "DMA stream transfer error"); + case 5: return $this->colorize($type, self::COL_RED, "DMA direct mode error"); + } + } + function getGPSStatus($type) { + if($type == self::TYPE_INT) + return $this->gps_lock; + + switch($this->gps_lock) { + case 0: return $this->colorize($type, self::COL_GREEN, "GPS locked"); + case 1: return $this->colorize($type, self::COL_GREEN, "GPS locked - kept switched on"); + case 2: return $this->colorize($type, self::COL_RED, "GPS loss"); + case 3: return $this->colorize($type, self::COL_ORANGE, "Low Batt before switched on"); + case 4: return $this->colorize($type, self::COL_ORANGE, "Low Batt while switched on"); + case 5: return $this->colorize($type, self::COL_GREEN, "Data from memory"); + case 6: return $this->colorize($type, self::COL_RED, "GPS communication error"); + } + } + function getEVA7MError($type) { + $error = ($this->sys_error >> 2) & 0x1; + if($type == self::TYPE_INT) + return $error; + + switch($error) { + case 0: return $this->colorize($type, self::COL_GREEN, "OK"); + case 1: return $this->colorize($type, self::COL_RED, "Fail"); + } + } + function getI2cError($loc, $type) { + $error = $loc == self::LOC_INT ? $this->sys_error & 0x1 : ($this->sys_error >> 1) & 0x1; + if($type == self::TYPE_INT) + return $error; + + switch($error) { + case 0: return $this->colorize($type, self::COL_GREEN, "OK"); + case 1: return $this->colorize($type, self::COL_RED, "Fail"); + } + } + function getPAC1720Error($type) { + $error = ($this->sys_error >> 3) & 0x1; + if($type == self::TYPE_INT) + return $error; + + switch($error) { + case 0: return $this->colorize($type, self::COL_GREEN, "OK"); + case 1: return $this->colorize($type, self::COL_RED, "Fail"); + } + } + function getBME280Error($type, $loc) { + switch($loc) { + case self::LOC_INT1: $error = ($this->sys_error >> 7) & 0x1; break; + case self::LOC_EXT1: $error = ($this->sys_error >> 8) & 0x1; break; + case self::LOC_EXT2: $error = ($this->sys_error >> 9) & 0x1; break; + } + if($type == self::TYPE_INT) + return $error; + + switch($error) { + case 0: return $this->colorize($type, self::COL_GREEN, "OK"); + case 1: return $this->colorize($type, self::COL_RED, "Fail"); + } + } + + private function colorize($type, $color, $str) { + if($type == self::TYPE_HTML) + return "$str"; + elseif($type == self::TYPE_STR) + return $str; + }*/ +} +?> + + + + + + + + + + + + + + + + + diff --git a/decoder/html/Tracker.class.php b/decoder/html/Tracker.class.php new file mode 100644 index 0000000..dcb7ae6 --- /dev/null +++ b/decoder/html/Tracker.class.php @@ -0,0 +1,133 @@ +call = $call; + } + + function getLastActivity() { + $act = array(); + + $stmt = Database::getInstance()->prepare(" + SELECT * FROM ( + SELECT CAST(STRFTIME('%s', 'now') as DECIMAL) - rxtime as lasttime,'pos' as type FROM position WHERE call = :call + UNION ALL + SELECT CAST(STRFTIME('%s', 'now') as DECIMAL) - rxtime as lasttime,'img' as type FROM image WHERE call = :call + ) + GROUP BY type + ORDER BY lasttime DESC + "); + $stmt->bindValue(':call', $this->call, SQLITE3_TEXT); + $query = $stmt->execute(); + + while($row = $query->fetchArray(SQLITE3_ASSOC)) + $act[$row['type']] = $row['lasttime']; + + return $act; + } + function getPictures($from, $to=NULL) { + if(is_null($to)) + $to = time() + 1; + + if($from > $to) + return array(); // Error $from is larger than $to + + if($from - $to > 64281600) + $from = $from + 64281600; // Max. 744 days (2 non leap years + 14 weeks) + + $stmt = Database::getInstance()->prepare(" + SELECT t.id,call,MIN(rxtime) as time_first,MAX(rxtime) as time_last, + COUNT(*) as count,imageID,MAX(packetID) as packetID + FROM ( + SELECT id + FROM image + WHERE :from <= rxtime + AND rxtime <= :to + AND call = :call + GROUP BY id + ORDER BY id ASC + ) as s + JOIN image t ON t.id = s.id + GROUP BY t.id + "); + $stmt->bindValue(':call', $this->call, SQLITE3_TEXT); + $stmt->bindValue(':from', $from, SQLITE3_INTEGER); + $stmt->bindValue(':to', $to, SQLITE3_INTEGER); + $query = $stmt->execute(); + + $pics = array(); + while($row = $query->fetchArray(SQLITE3_ASSOC)) + $pics[] = new Image($row); + + return $pics; + } + function getLastTelemetry() { + $stmt = Database::getInstance()->prepare("SELECT * FROM position WHERE call = :call ORDER BY rxtime DESC LIMIT 1"); + $stmt->bindValue(':call', $this->call, SQLITE3_TEXT); + $query = $stmt->execute(); + + return new Telemetry($query->fetchArray(SQLITE3_ASSOC)); + } + function getTelemetry($from, $to=NULL) { + if(is_null($to)) + $to = time() + 1; + + if($from > $to) + return array(); // Error $from is larger than $to + + if($from - $to > 64281600) + $from = $from + 64281600; // Max. 744 days (2 non leap years + 14 weeks) + + $stmt = Database::getInstance()->prepare("SELECT * FROM position WHERE :from <= rxtime AND rxtime <= :to AND call = :call ORDER BY rxtime ASC"); + $stmt->bindValue(':call', $this->call, SQLITE3_TEXT); + $stmt->bindValue(':from', $from, SQLITE3_INTEGER); + $stmt->bindValue(':to', $to, SQLITE3_INTEGER); + $query = $stmt->execute(); + + $datasets = array(); + while($row = $query->fetchArray(SQLITE3_ASSOC)) { + $datasets[] = new Telemetry($row); + } + + return $datasets; + } + function getPacketCount() { + $stmt = Database::getInstance()->prepare("SELECT * + FROM ( + SELECT COUNT(*) as cnt86400,'pos' as type FROM position WHERE call = :call AND rxtime+86400 > CAST(STRFTIME('%s', 'now') as DECIMAL) + UNION ALL + SELECT COUNT(*) as cnt86400,'img' as type FROM image WHERE call = :call AND rxtime+86400 > CAST(STRFTIME('%s', 'now') as DECIMAL) + ) AS a + JOIN ( + SELECT COUNT(*) as cnt3600,'pos' as type FROM position WHERE call = :call AND rxtime+3600 > CAST(STRFTIME('%s', 'now') as DECIMAL) + UNION ALL + SELECT COUNT(*) as cnt3600,'img' as type FROM image WHERE call = :call AND rxtime+3600 > CAST(STRFTIME('%s', 'now') as DECIMAL) + ) AS b + JOIN ( + SELECT COUNT(*) as cnt300,'pos' as type FROM position WHERE call = :call AND rxtime+300 > CAST(STRFTIME('%s', 'now') as DECIMAL) + UNION ALL + SELECT COUNT(*) as cnt300,'img' as type FROM image WHERE call = :call AND rxtime+300 > CAST(STRFTIME('%s', 'now') as DECIMAL) + ) AS c + WHERE a.type = b.type + AND a.type = c.type + "); + $stmt->bindValue(':call', $this->call, SQLITE3_TEXT); + $query = $stmt->execute(); + + $ret = array(); + while($row = $query->fetchArray(SQLITE3_ASSOC)) + $ret[$row['type']] = $row; + + return $ret; + } + function getCall() { + return $this->call; + } +} +?> diff --git a/decoder/html/ajax/telemetry.php b/decoder/html/ajax/telemetry.php new file mode 100644 index 0000000..318ee2c --- /dev/null +++ b/decoder/html/ajax/telemetry.php @@ -0,0 +1,16 @@ + $tracker->getTelemetry($_GET['from']), + "images" => $tracker->getPictures($_GET['from']), + "lastActivity" => $tracker->getLastActivity(), + "packetCount" => $tracker->getPacketCount(), + "time" => time() +)); +?> + diff --git a/decoder/html/data.php b/decoder/html/data.php deleted file mode 100644 index 1e830fa..0000000 --- a/decoder/html/data.php +++ /dev/null @@ -1,13 +0,0 @@ -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 deleted file mode 100644 index 40c3c76..0000000 --- a/decoder/html/database.class.php +++ /dev/null @@ -1,49 +0,0 @@ -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 - AND position.isnew = 1 - -- AND position.time + 86400*14 > CAST(strftime('%s', 'now') as DECIMAL) - 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/footer.inc.php b/decoder/html/footer.inc.php new file mode 100644 index 0000000..e9fc917 --- /dev/null +++ b/decoder/html/footer.inc.php @@ -0,0 +1,3 @@ +close(); +?> diff --git a/decoder/html/header.inc.php b/decoder/html/header.inc.php new file mode 100644 index 0000000..245167e --- /dev/null +++ b/decoder/html/header.inc.php @@ -0,0 +1,23 @@ + + + + +Balloon Health +getLastTelemetry(); +} + +$range = isset($_GET['range']) && is_numeric($_GET['range']) ? $_GET['range'] : 86400; +?> + + + diff --git a/decoder/html/helper.inc.php b/decoder/html/helper.inc.php new file mode 100644 index 0000000..325e9c0 --- /dev/null +++ b/decoder/html/helper.inc.php @@ -0,0 +1,11 @@ + diff --git a/decoder/html/images.php b/decoder/html/images.php new file mode 100644 index 0000000..42c54ab --- /dev/null +++ b/decoder/html/images.php @@ -0,0 +1,124 @@ + + + + + + + + + + + +
+  Range: + 1h + 3h + 6h + 12h + 24h + 2d + 3d + 5d + 7d + 14d + 21d + 30d +
+ +
+ + + + + diff --git a/decoder/html/index (copy 1).php b/decoder/html/index (copy 1).php new file mode 100644 index 0000000..12d8e09 --- /dev/null +++ b/decoder/html/index (copy 1).php @@ -0,0 +1,103 @@ + + + + + + + + +
+ + + + + diff --git a/decoder/html/index.php b/decoder/html/index.php index 12d8e09..4de5f70 100644 --- a/decoder/html/index.php +++ b/decoder/html/index.php @@ -1,103 +1,13 @@ - - - - - -
- - + - + diff --git a/decoder/html/sidebar.inc.php b/decoder/html/sidebar.inc.php new file mode 100644 index 0000000..2a32eb8 --- /dev/null +++ b/decoder/html/sidebar.inc.php @@ -0,0 +1,23 @@ +
+ getTracker(); + foreach($trackers as $tr) { + + $cnt = $tr->getPacketCount(); + + echo "
+ getCall() . "\">" . $tr->getCall() . " ... + getCall() . "\">Map + getCall() . "\">Images
+ Last Activity: " . time_format(max($tr->getLastActivity())) . "
+ Packets: " . number_format($cnt['img']['cnt300'] + $cnt['pos']['cnt300']) . " (5m), " . number_format($cnt['img']['cnt3600'] + $cnt['pos']['cnt3600']) . " (1h) +
"; + + } + ?> +
diff --git a/decoder/html/style.css b/decoder/html/style.css new file mode 100644 index 0000000..b916e1b --- /dev/null +++ b/decoder/html/style.css @@ -0,0 +1,42 @@ +html, body { + font: 10pt Monospace; + margin: 0; + margin: 0; + height: 100%; +} +.inner { + margin: 3px; + padding: 3px; + border: solid 1px #777777; +} +.call { + background-color: #DDDDDD; + padding: 5px; + margin: 4px 0; +} +a { + text-decoration: none; +} +a:hover { + text-decoration: underline; +} +img { + margin: 3px; +} +.pic { + display: inline-block; + float: left; + border: solid 1px #777777; + margin: 3px 3px; + padding: 4px; + font: 9pt Monospace; +} +.pic img { + margin: 0; +} +td,th { + vertical-align: top; + text-align: left; + padding: 1px 0; + margin: 0; +} diff --git a/decoder/html/telemetry.php b/decoder/html/telemetry.php new file mode 100644 index 0000000..8a9ea90 --- /dev/null +++ b/decoder/html/telemetry.php @@ -0,0 +1,591 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + getPacketCount(); + $act = $tracker->getLastActivity(); + ?> + + + + + + + + + + + + + + + + + + + + + + + + +
Call:
Serial:Reset , ID
Time: + RX:  
+ SYS: s
+
GPS: +
+ Sats, TTFF s, pDOP
+ Time:
+ ° ° +
Packets:5m1h24hLast
POS:
IMG:
LOG:????m?s ago
+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Battery:mVSTM, mVPAC, mWPAC
Solar:mVSTM, mVPAC, mWPAC
Sensors:BME280I1:Pa, °C, %
BME280E1:Pa, °C, %
BME280E2:Pa, °C, %
Temp.:°CSTM, °CSi4464
LightOV5640
+
+
+
+ + + + + +
+ + + + + + + + + + + + + + + + + + + + + + +
I2CINT
I2CEXT
EVA7M:
PAC1720:
OV5640:
+
+ + + + + + + + + + + + + + +
BME280I1:
BME280E1:
BME280E2:
+
+
+
+  Range: + 1h + 3h + 6h + 12h + 24h + 2d + 3d + 5d + 7d + 14d + 21d + 30d +
+ + + + + diff --git a/decoder/image.py b/decoder/image.py index 9ea9042..c2464f5 100644 --- a/decoder/image.py +++ b/decoder/image.py @@ -1,11 +1,12 @@ import binascii import urllib.request import urllib.error -import datetime +from datetime import datetime from position import decode_position from subprocess import * - -jsons = [] +import time +import threading +from shutil import copyfile def decode_callsign(code): callsign = '' @@ -31,153 +32,99 @@ def encode_callsign(callsign): 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, typ, server, grouping): - global jsons +imageProcessor = None +imageData = {} +lock = threading.RLock() - if not (typ is 'I' and len(data) == 125) and not (typ is 'J' and len(data) == 124): +def imgproc(): + global imageData + + while True: + with lock: + for _id in imageData: + (call, data) = imageData[_id] + + filename = 'html/images/%s-%d.jpg' % (call.replace('-',''), _id) + f = open(filename, 'wb') + process = Popen(['./ssdv', '-d'], stdin=PIPE, stdout=f, stderr=PIPE) + process.stdin.write(data) + dummy,err = process.communicate() + f.close() + + filename2 = 'html/images/%s.jpg' % (call.replace('-','')) + copyfile(filename, filename2) + + imageData = {} # Clear data + + time.sleep(1) + +w = time.time() +def insert_image(sqlite, receiver, call, data): + global imageProcessor,imageData,w + + if len(data) != 174: return # APRS message has invalid type or length (or both) + cur = sqlite.cursor() + # Decode various meta data - timd,x,y,z,teld,new = decode_position(tim, posi, None) imageID = data[0] packetID = (data[1] << 8) | data[2] data = binascii.hexlify(data[3:]).decode("ascii") + # 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 = ('68%08x%02x%04x' % (encode_callsign(bcall), imageID, packetID)) + data + data += "%08x" % (binascii.crc32(binascii.unhexlify(data)) & 0xffffffff) + + timd = int(datetime.now().timestamp()) + + # Find image ID (or generate new one) + _id = None + cur.execute("SELECT id,packetID FROM image WHERE call = ? AND imageID = ? AND rxtime+15*60 >= ? ORDER BY rxtime DESC LIMIT 1", (call, imageID, timd)) + fetch = cur.fetchall() + if len(fetch): + _id = fetch[0][0] + lastPacketId = fetch[0][1] + + if _id is None or lastPacketId > packetID: + # Generate ID + cur.execute("SELECT id+1 FROM image ORDER BY id DESC LIMIT 1") + fetch = cur.fetchall() + if len(fetch): + _id = fetch[0][0] + else: # No entries in the database + _id = 0 + # Debug - print('Received %s-Packet Image %d Packet %d' % (typ, imageID, packetID)) + print('Received image packet %d Packet %d ServerID %d' % (imageID, packetID, _id)) - # Insert - sqlite.cursor().execute(""" - INSERT OR IGNORE INTO image (call,time,imageID,packetID,lat,lon,alt) - VALUES (?,?,?,?,?,?,?)""", - (call, int(timd.timestamp()), imageID, packetID, y, x, int(z)) - ) - sqlite.commit() - - if typ is 'I': - - # 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 = ('67%08x%02x%04x' % (encode_callsign(bcall), imageID, packetID)) + data - - sqlite.cursor().execute(""" - UPDATE image - SET data1 = ? - WHERE call = ? - AND time = ? - AND imageID = ? - AND packetID = ?""", - (data, call, int(timd.timestamp()), imageID, packetID) - ) - - elif typ is 'J': - - sqlite.cursor().execute(""" - UPDATE image - SET data2 = ? - WHERE call = ? - AND time = ? - AND imageID = ? - AND packetID = ?""", - (data, call, int(timd.timestamp()), imageID, packetID) - ) - - sqlite.commit() - - # Get both data entries - cur = sqlite.cursor() + # Insert into database cur.execute(""" - SELECT data1,data2 - FROM image - WHERE call = ? - AND time = ? - AND imageID = ? - AND packetID = ?""", - (call, int(timd.timestamp()), imageID, packetID) + INSERT OR IGNORE INTO image (call,rxtime,imageID,packetID,data,id) + VALUES (?,?,?,?,?,?)""", + (call, timd, imageID, packetID, data, _id) ) - row = cur.fetchall()[0] - if row[0] != None and row[1] != None: # Both entries have been received - - data = ''.join(row) - - # Calculate CRC for SSDV server - crc = binascii.crc32(binascii.unhexlify(data)) & 0xffffffff - - # Update CRC in DB - sqlite.cursor().execute(""" - UPDATE image - SET crc = ? - WHERE call = ? - AND time = ? - AND imageID = ? - AND packetID = ?""", - ("%08x" % crc, call, int(timd.timestamp()), imageID, packetID) - ) + if w+0.5 < time.time(): sqlite.commit() + w = time.time() - # SSDV decode - cur = sqlite.cursor() - cur.execute("SELECT GROUP_CONCAT('55' || data1 || data2 || crc, '') 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() + with lock: + cur.execute("SELECT GROUP_CONCAT('55' || data || '"+(144*'0')+"', '') FROM image WHERE id = ? GROUP BY id ORDER BY packetID", (_id,)) + data = cur.fetchall()[0][0] + imageData[_id] = (call, binascii.unhexlify(data)) - # Create message for SSDV server (and save to array) - ssdv = '55' + data + ('%08x' % crc) - jsons.append("""{ - \"type\": \"packet\", - \"packet\": \"""" + ssdv + """\", - \"encoding\": \"hex\", - \"received\": \"""" + datetime.datetime.now().isoformat('T')[:19] + """Z\", - \"receiver\": \"""" + receiver + """\" - }""") - - 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: - err = True - while err: - print('Send to SSDV data server') - try: - result = urllib.request.urlopen(req, "".join(json.split(' ')).encode("ascii")) # Send packets to server - print('Response from SSDV-Server: OK') - err = False - except urllib.error.URLError as error: - if not hasattr(error, 'code'): # (Bug in urllib) most likely network not available - print('Error: Could not connect to SSDV-Server') - elif error.code == 400: - print('Response from SSDV-Server: %s' % error.read().decode('ascii').replace('\n','')) - err = 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()) + if imageProcessor is None: + imageProcessor = threading.Thread(target=imgproc) + imageProcessor.start() diff --git a/decoder/pecan_rx_gui/base91.py b/decoder/pecan_rx_gui/base91.py deleted file mode 100644 index 4cc6ab5..0000000 --- a/decoder/pecan_rx_gui/base91.py +++ /dev/null @@ -1,93 +0,0 @@ -# Base91 encode/decode for Python 2 and Python 3 -# -# Copyright (c) 2012 Adrien Beraud -# Copyright (c) 2015 Guillaume Jacquenot -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are met: -# -# * Redistributions of source code must retain the above copyright notice, -# this list of conditions and the following disclaimer. -# * Redistributions in binary form must reproduce the above copyright notice, -# this list of conditions and the following disclaimer in the documentation -# and/or other materials provided with the distribution. -# * Neither the name of Adrien Beraud, Wisdom Vibes Pte. Ltd., nor the names -# of its contributors may be used to endorse or promote products derived -# from this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE -# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, -# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -# -import struct - -base91_alphabet = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', - 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', - 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', - '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)) - -def decode(encoded_str): - ''' Decode Base91 string to a bytearray ''' - v = -1 - b = 0 - n = 0 - out = bytearray() - for strletter in encoded_str: - if not strletter in decode_table: - continue - c = decode_table[strletter] - if(v < 0): - v = c - else: - v += c*91 - b |= v << n - n += 13 if (v & 8191)>88 else 14 - while True: - out += struct.pack('B', b&255) - b >>= 8 - n -= 8 - if not n>7: - break - v = -1 - if v+1: - out += struct.pack('B', (b | v << n) & 255 ) - return out - -def encode(bindata): - ''' Encode a bytearray to a Base91 string ''' - b = 0 - n = 0 - out = '' - for count in range(len(bindata)): - byte = bindata[count:count+1] - b |= struct.unpack('B', byte)[0] << n - n += 8 - if n>13: - v = b & 8191 - if v > 88: - b >>= 13 - n -= 13 - else: - v = b & 16383 - b >>= 14 - n -= 14 - out += base91_alphabet[v % 91] + base91_alphabet[v // 91] - if n: - out += base91_alphabet[b % 91] - if n>7 or b>90: - out += base91_alphabet[b // 91] - return out - diff --git a/decoder/pecan_rx_gui/decoder.py b/decoder/pecan_rx_gui/decoder.py deleted file mode 100755 index 8bc084b..0000000 --- a/decoder/pecan_rx_gui/decoder.py +++ /dev/null @@ -1,178 +0,0 @@ -#!/usr/bin/python - -import serial,os,re,datetime -from subprocess import call -import base91 -import binascii -import urllib2 -import io -import sys -import argparse -import pygame, random -from pygame.locals import * -import pygame.time -from subprocess import * -from cStringIO import StringIO - -send_to_server = False -SCREENX = 1024 -SCREENY = 768 -pygame.font.init() -myfont = pygame.font.SysFont('Comic Sans MS', 20) -textsurface = myfont.render('Callsign: DL7AD2 Image ID: 07 Resolution: 640x480', False, (0, 255, 255)) -pygame.init() -screen = pygame.display.set_mode((SCREENX, SCREENY)) -background = pygame.Surface(screen.get_rect().size) -displaygroup = pygame.sprite.RenderUpdates() -updategroup = pygame.sprite.Group() -clock = pygame.time.Clock() -pygame.display.set_caption('PecanRXGui v.1.0.0 (Q)uit (s)end image') - -# Parse arguments from terminal -parser = argparse.ArgumentParser(description='APRS/SSDV decoder') -parser.add_argument('-c', '--call', help='Callsign of the station') -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='Server URL', default='https://ssdv.habhub.org/api/v0/packets') -args = parser.parse_args() - -if args.device == 'I': # Connect to APRS-IS - aprsis = aprs.TCP('DL4MDW', aprs_filter='t/u u/APECAN') - aprsis.start() - -elif args.device is not '-': # Use serial connection (probably TNC) - try: - serr = serial.Serial( - port=args.device, - baudrate=args.baudrate, - ) - except: - 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: - try: - logfile = open(args.log, 'a') - except: - sys.stderr.write('Error: Could not open logging file\n') - sys.exit(1) - -jsons = [] -current_filename = 'data.csv' -buf = '' -jpg = '' -imgbuf = '' - -def received_data(data): - global jsons, old_filename, current_filename, send_to_server, buf, imgbuf - - if str(type(data)) == "": # APRS-IS - - call = str(data.source) - aprs = data.text[3:] - receiver = 'APRS-IS/' + str(data.path.pop()) - - else: # serial or stdin - - # Parse line and detect data - m = re.search("(.*)\>APECAN(.*):\{\{I(.*)", data) - if m: - try: - call = m.group(1) - aprs = m.group(3) - receiver = 'bla' - except: - return # message format incorrect (probably no APRS message or line cut off too short) - else: - m = re.search("\[(.*)\]\[(.*)\] DATA \> (.*)", data) - try: - aprs = m.group(3) - except: - return - - if args.log is not None: - logfile.write(data) # Log data to file - - data = base91.decode(aprs) # Decode Base91 - - # 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') - - if len(data) != 219: - return # APRS message sampled too short - - if (data[7] + data[6] * 256) == 0: - buf = '' - buf += binascii.unhexlify(ssdv) - - command = ['./ssdv', '-d'] - process = Popen(command, stdin=PIPE, stdout=PIPE, stderr=PIPE) - process.stdin.write(buf) - jpg,dummy = process.communicate() - imgbuf = StringIO(jpg) - - if send_to_server is False: - return - else: - if len(jsons) >= args.grouping: - 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: - try: - result = urllib2.urlopen(req, "".join(json.split(' '))) # Send packets to server - print 'Send to SSDV data server: OK' - error = False - except urllib2.URLError, error: - print 'Send to SSDV data server: failed (connection error :( trying 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 - aprsis.receive(callback=received_data) # Register APRS callback -else: - # read data from console ? - while 1: - for event in pygame.event.get(): - if event.type == QUIT: - exit(0) - - if event.type == pygame.KEYDOWN: - if event.key == pygame.K_q: - exit(0) - elif event.key == pygame.K_s: - send_to_server^=True - - data = sys.stdin.readline() if args.device is '-' else ser.readline() # Read a line - received_data(data) - - displaygroup.clear(screen, background) - updategroup.update() - filename = str("currximg.jpg") - try: - img=pygame.image.load(imgbuf) - textsurface = myfont.render("Call: %s send: %d" % (args.call, send_to_server), False, (0, 255, 255)) - screen.blit(img,(0,0)) - screen.blit(textsurface,(0,0)) - pygame.display.flip() - pygame.display.update(displaygroup.draw(screen)) - except Exception as e: - print str(e) - textsurface = myfont.render('Error %s' % (e), False, (255, 100, 100)) - screen.blit(textsurface,(0,0)) - pygame.display.flip() - pygame.display.update(displaygroup.draw(screen)) - - clock.tick(500) diff --git a/decoder/pecan_rx_gui/ssdv b/decoder/pecan_rx_gui/ssdv deleted file mode 100755 index 716d76e30244f91dd2c3a7f26e6c5309daa9f612..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 130616 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

iAHnCUKd#P2J07i` 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

RLXfN97amFd- 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 QeWZSV@Hus({ZKUj1+&52lmGw# diff --git a/decoder/pecan_rx_gui/ssdv_OSX10.11.6 b/decoder/pecan_rx_gui/ssdv_OSX10.11.6 deleted file mode 100755 index 3547fb4c15430410a1b81d55bcfd531c92e86c64..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 49612 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 H;>Q06zs8nO diff --git a/decoder/position.py b/decoder/position.py index a993ce1..507e0b3 100644 --- a/decoder/position.py +++ b/decoder/position.py @@ -1,6 +1,7 @@ from datetime import datetime,timedelta,timezone import sqlite3 import base91 +import struct def insert_log(sqlite, call, data): @@ -25,7 +26,7 @@ def insert_log(sqlite, call, data): sqlite.commit() -def decode_position(tim, posi, tel): +def decode_position(posi, tel): # Decode latitude y3 = ord(posi[1]) - 33 y2 = ord(posi[2]) - 33 @@ -48,12 +49,8 @@ def decode_position(tim, posi, tel): ze = z0 + z1*91 z = pow(1.002, ze) / 3.281 - # Decode time + # Time timd = datetime.now(timezone.utc) - timd = timd.replace(hour = int(tim[0:2]), minute = int(tim[2:4]), second = int(tim[4:6]), microsecond=0) - now = datetime.now(timezone.utc) - if now < timd: # Packet was sampled yesterday - timd -= timedelta(1) # Decode GPS Fix Type isnew = ((ord(posi[12])-33) >> 5) & 0x1 @@ -68,15 +65,23 @@ def decode_position(tim, posi, tel): return timd,x,y,z,teld,isnew -def insert_position(sqlite, call, tim, posi, comm, tel): #sqlite, call, data - # Decode - timd,x,y,z,teld,isnew = decode_position(tim, posi, tel) +def insert_position(sqlite, call, posi, comm, tel): #sqlite, call, data + # Decode position + timd,x,y,z,teld,isnew = decode_position(posi, tel) + + # Decode comment + data = base91.decode(comm) + (adc_vsol,adc_vbat,pac_vsol,pac_vbat,pac_pbat,pac_psol,light_intensity, + gps_lock,gps_sats,gps_ttff,gps_pdop,gps_alt,gps_lat, + gps_lon,sen_i1_press,sen_e1_press,sen_e2_press,sen_i1_temp,sen_e1_temp, + sen_e2_temp,sen_i1_hum,sen_e1_hum,sen_e2_hum,dummy2,stm32_temp, + si4464_temp,reset,_id,gps_time,sys_time,sys_error) = struct.unpack('HHHHhhHBBBBHiiIIIhhhBBBBhhHIIII', data[:72]) # Insert - sqlite.cursor().execute(""" - INSERT OR REPLACE INTO position (call,time,org,lat,lon,alt,isnew,comment,sequ,tel1,tel2,tel3,tel4,tel5) - VALUES (?,?,'pos',?,?,?,?,?,?,?,?,?,?,?)""", - (call, int(timd.timestamp()), y, x, int(z), isnew, comm, teld[0], teld[1], teld[2], teld[3], teld[4], teld[5]) + sqlite.cursor().execute( + """INSERT INTO position (call,rxtime,org,adc_vsol,adc_vbat,pac_vsol,pac_vbat,pac_pbat,pac_psol,light_intensity,gps_lock,gps_sats,gps_ttff,gps_pdop,gps_alt,gps_lat,gps_lon,sen_i1_press,sen_e1_press,sen_e2_press,sen_i1_temp,sen_e1_temp,sen_e2_temp,sen_i1_hum,sen_e1_hum,sen_e2_hum,sys_error,stm32_temp,si4464_temp,reset,id,sys_time,gps_time) + VALUES (?,?,'pos',?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)""", + (call,int(timd.timestamp()), adc_vsol,adc_vbat,pac_vsol,pac_vbat,pac_pbat,pac_psol,light_intensity,gps_lock,gps_sats,gps_ttff,gps_pdop,gps_alt,gps_lat,gps_lon,sen_i1_press,sen_e1_press,sen_e2_press,sen_i1_temp,sen_e1_temp,sen_e2_temp,sen_i1_hum,sen_e1_hum,sen_e2_hum,sys_error,stm32_temp,si4464_temp,reset,_id,sys_time,gps_time) ) sqlite.commit() @@ -85,3 +90,24 @@ def insert_position(sqlite, call, tim, posi, comm, tel): #sqlite, call, data print("Decoded position from %s time %s => lat=%f lon=%f alt=%d new=%d comment=%s, sequ=%d tel=[%d,%d,%d,%d,%d]" % (call, tim_stringified, y, x, int(z), isnew, comm, teld[0], teld[1], teld[2], teld[3], teld[4], teld[5])) + + + + + + + + + + + + + + + + + + + + + diff --git a/decoder/ssdv b/decoder/ssdv index 716d76e30244f91dd2c3a7f26e6c5309daa9f612..9418d715e402cc0d8b3e5487d03a110e97d97b58 100755 GIT binary patch literal 271280 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 f+P~emHu8L%ivxQ8``A;bU)s6lS>w2tJ literal 130616 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

iAHnCUKd#P2J07i` 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

RLXfN97amFd- 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 QeWZSV@Hus({ZKUj1+&52lmGw# diff --git a/tracker/software/config.c b/tracker/software/config.c index 1fba492..c3ca3e3 100644 --- a/tracker/software/config.c +++ b/tracker/software/config.c @@ -362,13 +362,14 @@ module_conf_t config[7]; -uint8_t ssdv_buffer[128*1024] __attribute__((aligned(32))); // Image buffer +uint8_t ssdv_buffer[256*1024] __attribute__((aligned(32))); // Image buffer -systime_t track_cycle_time = S2ST(30); // Tracking cycle (all peripheral data [airpressure, GPS, temperature, ...] is collected each 60 seconds -systime_t log_cycle_time = S2ST(30); // Log cycle time in seconds (600 seconds) +systime_t track_cycle_time = S2ST(60); // Tracking cycle (all peripheral data [airpressure, GPS, temperature, ...] is collected each 60 seconds 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 +uint16_t gps_onper_vbat = 3000; // Battery voltage threshold at which GPS is kept switched on all time. This value must be larger + // than gps_on_vbat and gps_off_vbat otherwise this value has no effect. Value 0 disables this feature void start_user_modules(void) { @@ -439,7 +440,6 @@ void start_user_modules(void) config[3].trigger.type = TRIG_CONTINUOUSLY; // Transmit continuously chsnprintf(config[3].aprs_conf.callsign, 16, "DL7AD"); // APRS Callsign 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) config[3].ssdv_conf.ram_buffer = ssdv_buffer; // Camera buffer config[3].ssdv_conf.ram_size = sizeof(ssdv_buffer); // Buffer size @@ -457,7 +457,6 @@ void start_user_modules(void) config[4].trigger.type = TRIG_CONTINUOUSLY; // Transmit continuously chsnprintf(config[4].aprs_conf.callsign, 16, "DL7AD"); // APRS Callsign 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) config[4].ssdv_conf.ram_buffer = ssdv_buffer; // Camera buffer config[4].ssdv_conf.ram_size = sizeof(ssdv_buffer); // Buffer size @@ -496,7 +495,6 @@ void start_user_modules(void) config[6].trigger.timeout = 60; // Timeout 180 sec chsnprintf(config[6].aprs_conf.callsign, 16, "DL7AD"); // APRS Callsign 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]); diff --git a/tracker/software/config.h b/tracker/software/config.h index 86124db..5d8f199 100644 --- a/tracker/software/config.h +++ b/tracker/software/config.h @@ -14,7 +14,7 @@ * save energy using 1.8V. This option is activated automatically if ACTIVATE_USB is set * true. */ -#define ACTIVATE_USB TRUE /* If set to true, the USB interface will be switched on. The tracker is also switched to +#define ACTIVATE_USB FALSE /* If set to true, the USB interface will be switched on. The tracker is also switched to * 3V, because USB would not work at 1.8V. Note that the transmission power is increased * too when operating at 3V. This option will also run the STM32 at 48MHz (AHB) permanently * because USB needs that speed, otherwise it is running at 6MHz which saves a lot of power. */ @@ -32,6 +32,7 @@ extern systime_t log_cycle_time; extern bool keep_cam_switched_on; extern uint16_t gps_on_vbat; extern uint16_t gps_off_vbat; +extern uint16_t gps_onper_vbat; #endif diff --git a/tracker/software/debug.c b/tracker/software/debug.c index bb6d1a1..8a0df00 100644 --- a/tracker/software/debug.c +++ b/tracker/software/debug.c @@ -89,19 +89,19 @@ void readLog(BaseSequentialStream *chp, int argc, char *argv[]) (void)argc; (void)argv; - chprintf(chp, "addr,id,date,time,lat,lon,alt,sats,ttff,vbat,vsol,vsub,pbat,rbat,press,temp,hum,idimg\r\n"); + chprintf(chp, "addr,id,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, - "%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, + "%08x,%d,%d,%d.%05d,%d.%05d,%d,%d,%d,%d.%03d,%d.%03d,%d,%d.%01d,%2d.%02d,%2d.%01d\r\n", + tp, tp->id, tp->gps_time, 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, - tp->air_press/10, tp->air_press%10, tp->air_temp/100, tp->air_temp%100, tp->air_hum/10, tp->air_hum%10, tp->id_image + tp->adc_vbat/1000, (tp->adc_vbat%1000), tp->adc_vsol/1000, (tp->adc_vsol%1000), tp->pac_pbat, + tp->sen_i1_press/10, tp->sen_i1_press%10, tp->sen_i1_temp/100, tp->sen_i1_temp%100, tp->sen_i1_hum/10, tp->sen_i1_hum%10 ); } } diff --git a/tracker/software/debug.h b/tracker/software/debug.h index 60a6123..4780601 100644 --- a/tracker/software/debug.h +++ b/tracker/software/debug.h @@ -98,12 +98,6 @@ extern bool debug_on_usb; chMtxUnlock(&trace_mtx); \ } -#define PRINT_TIME(thd) { \ - ptime_t dbgtime; \ - getTime(&dbgtime); \ - TRACE_INFO("%-4s > Current time: %02d-%02d-%02d %02d:%02d:%02d:%03d", thd, dbgtime.year, dbgtime.month, dbgtime.day, dbgtime.hour, dbgtime.minute, dbgtime.second, dbgtime.millisecond); \ -} - void debugOnUSB(BaseSequentialStream *chp, int argc, char *argv[]); void printConfig(BaseSequentialStream *chp, int argc, char *argv[]); void printPicture(BaseSequentialStream *chp, int argc, char *argv[]); diff --git a/tracker/software/drivers/bme280.c b/tracker/software/drivers/bme280.c index eb5bc21..1876257 100644 --- a/tracker/software/drivers/bme280.c +++ b/tracker/software/drivers/bme280.c @@ -139,7 +139,7 @@ uint32_t BME280_getPressure(bme280_t *handle, uint16_t means) { * Reads the relative humidity * @return rel. humidity in % * 10 */ -uint16_t BME280_getHumidity(bme280_t *handle) { +uint8_t BME280_getHumidity(bme280_t *handle) { int32_t adc_H; uint16_t tmp; I2C_read16(handle->address, BME280_REGISTER_HUMIDDATA, &tmp); @@ -160,7 +160,7 @@ uint16_t BME280_getHumidity(bme280_t *handle) { v_x1_u32r = (v_x1_u32r < 0) ? 0 : v_x1_u32r; v_x1_u32r = (v_x1_u32r > 419430400) ? 419430400 : v_x1_u32r; float h = (v_x1_u32r>>12); - return h / 102; + return h / 1020; } /** diff --git a/tracker/software/drivers/bme280.h b/tracker/software/drivers/bme280.h index cc24f36..3918daa 100644 --- a/tracker/software/drivers/bme280.h +++ b/tracker/software/drivers/bme280.h @@ -90,7 +90,7 @@ bool BME280_isAvailable(uint8_t address); void BME280_Init(bme280_t *handle, uint8_t address); int16_t BME280_getTemperature(bme280_t *handle); uint32_t BME280_getPressure(bme280_t *handle, uint16_t means); -uint16_t BME280_getHumidity(bme280_t *handle); +uint8_t BME280_getHumidity(bme280_t *handle); int32_t BME280_getAltitude(uint32_t seaLevel, uint32_t atmospheric); #endif diff --git a/tracker/software/drivers/ov5640.c b/tracker/software/drivers/ov5640.c index 24fa22e..f35c509 100644 --- a/tracker/software/drivers/ov5640.c +++ b/tracker/software/drivers/ov5640.c @@ -12,6 +12,9 @@ #include "padc.h" #include +static uint32_t lightIntensity; +static uint8_t error; + struct regval_list { uint16_t reg; uint8_t val; @@ -962,6 +965,8 @@ CH_IRQ_HANDLER(Vector5C) { bool OV5640_Capture(uint8_t* buffer, uint32_t size) { + OV5640_setLightIntensity(); + /* * Note: * If there are no Chibios devices enabled that use DMA then... @@ -1073,21 +1078,31 @@ bool OV5640_Capture(uint8_t* buffer, uint32_t size) // Capture done, unlock I2C I2C_Unlock(); - if(dma_error) { - if(dma_flags & STM32_DMA_ISR_HTIF) + if(dma_error) + { + if(dma_flags & STM32_DMA_ISR_HTIF) { TRACE_ERROR("CAM > DMA abort - last buffer segment"); - if(dma_flags & STM32_DMA_ISR_FEIF) + error = 0x2; + } + if(dma_flags & STM32_DMA_ISR_FEIF) { TRACE_ERROR("CAM > DMA FIFO error"); - if(dma_flags & STM32_DMA_ISR_TEIF) + error = 0x3; + } + if(dma_flags & STM32_DMA_ISR_TEIF) { TRACE_ERROR("CAM > DMA stream transfer error"); - if(dma_flags & STM32_DMA_ISR_DMEIF) + error = 0x4; + } + if(dma_flags & STM32_DMA_ISR_DMEIF) { TRACE_ERROR("CAM > DMA direct mode error"); + error = 0x5; + } TRACE_ERROR("CAM > Error capturing image"); return false; } TRACE_INFO("CAM > Capture success"); + error = 0x0; return true; } @@ -1226,6 +1241,8 @@ void OV5640_init(void) chThdSleepMilliseconds(100); + OV5640_setLightIntensity(); + // Send settings to OV5640 TRACE_INFO("CAM > Transmit config to camera"); OV5640_TransmitConfig(); @@ -1281,6 +1298,7 @@ bool OV5640_isAvailable(void) if(I2C_read8_16bitreg(OV5640_I2C_ADR, 0x300A, &val) && I2C_read8_16bitreg(OV5640_I2C_ADR, 0x300B, &val2)) { ret = val == 0x56 && val2 == 0x40; } else { + error = 0x1; ret = false; } @@ -1294,12 +1312,23 @@ bool OV5640_isAvailable(void) return ret; } -uint32_t OV5640_getLightIntensity(void) +void OV5640_setLightIntensity(void) { uint8_t val1,val2,val3; I2C_read8_16bitreg(OV5640_I2C_ADR, 0x3C1B, &val1); I2C_read8_16bitreg(OV5640_I2C_ADR, 0x3C1C, &val2); I2C_read8_16bitreg(OV5640_I2C_ADR, 0x3C1D, &val3); - return (val1 << 16) | (val2 << 8) | val3; + lightIntensity = (val1 << 16) | (val2 << 8) | val3; +} + +uint32_t OV5640_getLastLightIntensity(void) +{ + uint32_t ret = lightIntensity; + return ret; +} + +uint8_t OV5640_hasError(void) +{ + return error; } diff --git a/tracker/software/drivers/ov5640.h b/tracker/software/drivers/ov5640.h index b2eef26..2d6976f 100644 --- a/tracker/software/drivers/ov5640.h +++ b/tracker/software/drivers/ov5640.h @@ -21,7 +21,9 @@ void OV5640_SetResolution(resolution_t res); void OV5640_init(void); void OV5640_deinit(void); bool OV5640_isAvailable(void); -uint32_t OV5640_getLightIntensity(void); +void OV5640_setLightIntensity(void); +uint32_t OV5640_getLastLightIntensity(void); +uint8_t OV5640_hasError(void); #endif diff --git a/tracker/software/drivers/pac1720.c b/tracker/software/drivers/pac1720.c index 7192c47..a82c1d9 100644 --- a/tracker/software/drivers/pac1720.c +++ b/tracker/software/drivers/pac1720.c @@ -12,72 +12,77 @@ * FSC = FSR / R_sense */ -#define FSR 80 /* Full-scale-rage voltage in mV */ +#define FSR 10 /* Full-scale-rage voltage in mV */ #define DENO 2047 /* Denominator see Tab. 4-5 in PAC1720 datasheet */ #define FSV (40 - 40 / (DENO)) #define FSC ((FSR) / (PAC1720_RSENSE)) static int32_t pac1720_pbat; -static int32_t pac1720_pbat_counter; -static int32_t pac1720_rbat; -static int32_t pac1720_rbat_counter; +static int32_t pac1720_psol; +static int32_t pac1720_vbat; +static int32_t pac1720_vsol; +static int32_t pac1720_counter; -int16_t pac1720_getPbat(void) { +static uint8_t error; + +static mutex_t mtx; +bool mtx_init = false; + +static void pac1720_lock(void) { + // Initialize mutex + if(!mtx_init) + chMtxObjectInit(&mtx); + mtx_init = true; + + chMtxLock(&mtx); +} + +static void pac1720_unlock(void) +{ + chMtxUnlock(&mtx); +} + +int16_t pac1720_get_pbat(void) { int32_t fsp = FSV * FSC; int16_t val; uint8_t sign; if(I2C_read16(PAC1720_ADDRESS, PAC1720_CH2_PWR_RAT_HIGH, (uint16_t*)&val)) { I2C_read8(PAC1720_ADDRESS, PAC1720_CH2_VSENSE_HIGH, &sign); - return (sign >> 7 ? -1 : 1) * (val * fsp / 65535); + return (sign >> 7 ? -1 : 1) * 10 * (val * fsp / 65535); } else { + error |= 0x1; return 0; // PAC1720 not available (maybe Vcc too low) } } -int16_t pac1720_getAvgPbat(void) { - // Return current value if time interval too short - if(!pac1720_pbat_counter) - return pac1720_getPbat(); +int16_t pac1720_get_psol(void) { + return 0; +} - // Calculate average power - int16_t ret = pac1720_pbat / pac1720_pbat_counter; +uint16_t pac1720_get_vbat(void) { + uint16_t val; + if(!I2C_read16(PAC1720_ADDRESS, PAC1720_CH2_VSOURCE_HIGH, &val)) { + error |= 0x1; + return 0; // PAC1720 not available (maybe Vcc too low) + } - // Reset current measurement - pac1720_pbat = 0; - pac1720_pbat_counter = 0; + uint16_t ret = (val >> 5) * 20000 / 0x400; + + if(ret < 1500) + error |= 0x2; // The chip is unreliable return ret; } -uint16_t pac1720_getVbat(void) { +uint16_t pac1720_get_vsol(void) { uint16_t val; - if(!I2C_read16(PAC1720_ADDRESS, PAC1720_CH2_VSOURCE_HIGH, &val)) + if(!I2C_read16(PAC1720_ADDRESS, PAC1720_CH1_VSOURCE_HIGH, &val)) { + error |= 0x1; return 0; // PAC1720 not available (maybe Vcc too low) + } - return (val >> 5) * 20000 / 0x400; -} - -int16_t pac1720_getAvgRbat(void) { - // Return current value if time interval too short - if(!pac1720_rbat_counter) - return 0; - - // Calculate average power - int16_t ret = pac1720_rbat / pac1720_rbat_counter; - - // Reset current measurement - pac1720_rbat = 0; - pac1720_rbat_counter = 0; - - return ret; -} - -uint16_t pac1720_getVsol(void) { - uint16_t val; - if(!I2C_read16(PAC1720_ADDRESS, PAC1720_CH1_VSOURCE_HIGH, &val)) - return 0; // PAC1720 not available (maybe Vcc too low) return (val >> 5) * 20000 / 0x400; } @@ -85,53 +90,74 @@ uint16_t pac1720_getVsol(void) { bool pac1720_isAvailable(void) { uint8_t val; - if(I2C_read8(PAC1720_ADDRESS, PAC1720_PRODUCT_ID, &val)) + if(I2C_read8(PAC1720_ADDRESS, PAC1720_PRODUCT_ID, &val)) { + error |= val != 0x57; return val == 0x57; - else + } else { + error |= 0x1; return false; // PAC1720 not available (maybe Vcc too low) + } +} + +static void sendConfig(void) +{ + /* Write for both channels + * Current sensor sampling time 80ms (Denominator 2047) + * Current sensing average enabled 0x3 + * Current sensing range +-10mV (FSR) + */ + I2C_write8(PAC1720_ADDRESS, PAC1720_CH1_VSENSE_SAMP_CONFIG, 0x5C); + I2C_write8(PAC1720_ADDRESS, PAC1720_CH2_VSENSE_SAMP_CONFIG, 0x5C); + I2C_write8(PAC1720_ADDRESS, PAC1720_V_SOURCE_SAMP_CONFIG, 0xFF); +} + +void pac1720_get_avg(uint16_t* vbat, uint16_t* vsol, int16_t* pbat, int16_t* psol) { + // Return current value if time interval too short + if(!pac1720_counter) { + *vbat = pac1720_get_vbat(); + *vsol = pac1720_get_vsol(); + *pbat = pac1720_get_pbat(); + *psol = pac1720_get_psol(); + return; + } + + pac1720_lock(); + + // Calculate average power + *vbat = pac1720_vbat / pac1720_counter; + *vsol = pac1720_vsol / pac1720_counter; + *pbat = pac1720_pbat / pac1720_counter; + *psol = pac1720_psol / pac1720_counter; + + // Reset current measurement + pac1720_vbat = 0; + pac1720_vsol = 0; + pac1720_pbat = 0; + pac1720_psol = 0; + pac1720_counter = 0; + + pac1720_unlock(); } THD_FUNCTION(pac1720_thd, arg) { (void)arg; - uint32_t counter = 0; - int32_t u1 = 999999; - int32_t p1 = 999999; - int32_t u2 = -999999; - int32_t p2 = -999999; while(true) { - // Sample data - int32_t v = pac1720_getVbat(); - int32_t p = pac1720_getPbat(); + // Send config + sendConfig(); // Measure battery power - pac1720_pbat += p; - pac1720_pbat_counter++; + pac1720_lock(); + pac1720_vbat += pac1720_get_vbat(); + pac1720_vsol += pac1720_get_vsol(); + pac1720_pbat += pac1720_get_pbat(); + pac1720_psol += pac1720_get_psol(); + pac1720_counter++; + pac1720_unlock(); - // Measure battery impedance - if(p < p1) { - u1 = v; - p1 = p; - } - if(p > p2) { - u2 = v; - p2 = p; - } - if(++counter%10 == 0 && abs(p1-p2) > 100 && abs(u1-u2) > 0 && p1*u2 != p2*u1) - { - int32_t rbat = abs((u1*u2*(u1-u2)) / (p1*u2 - p2*u1)); - pac1720_rbat += rbat; - pac1720_rbat_counter++; - - u1 = 999999; - p1 = 999999; - u2 = -999999; - p2 = -999999; - } - - chThdSleepMilliseconds(50); + chThdSleepMilliseconds(200); } } @@ -143,16 +169,18 @@ void pac1720_init(void) palSetLineMode(LINE_SOL_SHORT_EN, PAL_MODE_OUTPUT_PUSHPULL); palSetLine(LINE_SOL_SHORT_EN); - /* Write for both channels - * Current sensor sampling time 80ms (Denominator 2047) - * Current sensing average enabled 0x3 - * Current sensing range +-80mV (FSR) - */ - I2C_write8(PAC1720_ADDRESS, PAC1720_CH1_VSENSE_SAMP_CONFIG, 0x5F); - I2C_write8(PAC1720_ADDRESS, PAC1720_CH2_VSENSE_SAMP_CONFIG, 0x5F); - I2C_write8(PAC1720_ADDRESS, PAC1720_V_SOURCE_SAMP_CONFIG, 0xFF); + // Send config + sendConfig(); TRACE_INFO("PAC > Init PAC1720 continuous measurement"); chThdCreateFromHeap(NULL, THD_WORKING_AREA_SIZE(512), "PAC1720", LOWPRIO, pac1720_thd, NULL); + chThdSleepMilliseconds(10); +} + +uint8_t pac1720_hasError(void) +{ + uint8_t ret = error; + error = 0x0; + return ret; } diff --git a/tracker/software/drivers/pac1720.h b/tracker/software/drivers/pac1720.h index dd42e84..29fa32c 100644 --- a/tracker/software/drivers/pac1720.h +++ b/tracker/software/drivers/pac1720.h @@ -49,13 +49,14 @@ #define PAC1720_REVISION 0xFF -void pac1720_init(void); -int16_t pac1720_getIsol(void); -int16_t pac1720_getPbat(void); -int16_t pac1720_getAvgPbat(void); -uint16_t pac1720_getVbat(void); -int16_t pac1720_getAvgRbat(void); -uint16_t pac1720_getVsol(void); +int16_t pac1720_get_pbat(void); +int16_t pac1720_get_psol(void); +uint16_t pac1720_get_vbat(void); +uint16_t pac1720_get_vsol(void); bool pac1720_isAvailable(void); +void pac1720_get_avg(uint16_t* vbat, uint16_t* vsol, int16_t* pbat, int16_t* psol); +void pac1720_init(void); +uint8_t pac1720_hasError(void); #endif + diff --git a/tracker/software/drivers/si4464.c b/tracker/software/drivers/si4464.c index 32b54cf..ebd73f9 100644 --- a/tracker/software/drivers/si4464.c +++ b/tracker/software/drivers/si4464.c @@ -18,8 +18,9 @@ static const SPIConfig ls_spicfg = { }; #define getSPIDriver() &ls_spicfg -uint32_t outdiv; -bool initialized = false; +static uint32_t outdiv; +static bool initialized = false; +static int16_t lastTemp; /** * Initializes Si4464 transceiver chip. Adjustes the frequency which is shifted by variable @@ -37,7 +38,7 @@ void Si4464_Init(void) { palSetLine(LINE_RADIO_CS); // Reset radio - Si4464_shutdown(); + palSetLine(LINE_RADIO_SDN); palSetLine(LINE_OSC_EN); // Activate Oscillator chThdSleepMilliseconds(10); @@ -104,7 +105,8 @@ void Si4464_Init(void) { Si4464_write(use_lsb_first, 5); // Temperature readout - TRACE_INFO("SI > Transmitter temperature %d degC", Si4464_getTemperature()); + lastTemp = Si4464_getTemperature(); + TRACE_INFO("SI > Transmitter temperature %d degC", lastTemp/100); initialized = true; } @@ -293,10 +295,14 @@ void stopTx(void) { } void Si4464_shutdown(void) { - palSetLine(LINE_RADIO_SDN); // Power down chip + palSetLineMode(LINE_SPI_SCK, PAL_MODE_INPUT_PULLDOWN); // SCK + palSetLineMode(LINE_SPI_MISO, PAL_MODE_INPUT_PULLDOWN); // MISO + palSetLineMode(LINE_SPI_MOSI, PAL_MODE_INPUT_PULLDOWN); // MOSI + palSetLineMode(LINE_RADIO_CS, PAL_MODE_INPUT_PULLDOWN); // RADIO CS + palSetLineMode(LINE_RADIO_SDN, PAL_MODE_INPUT_PULLDOWN); // RADIO SDN + palSetLineMode(LINE_OSC_EN, PAL_MODE_OUTPUT_PUSHPULL); // Oscillator + palSetLine(LINE_IO_LED1); // Set indication LED - palClearLine(LINE_OSC_EN); // Shutdown oscillator - RADIO_WRITE_GPIO(false); // Set GPIO1 low initialized = false; } @@ -351,11 +357,14 @@ uint8_t Si4464_getState(void) { return rxData[2]; } -int8_t Si4464_getTemperature(void) { +int16_t Si4464_getTemperature(void) { uint8_t txData[2] = {0x14, 0x10}; uint8_t rxData[8]; Si4464_read(txData, 2, rxData, 8); uint16_t adc = rxData[7] | ((rxData[6] & 0x7) << 8); - return (899*adc)/4096 - 293; + return (89900*adc)/4096 - 29300; } +int16_t Si4464_getLastTemperature(void) { + return lastTemp; +} diff --git a/tracker/software/drivers/si4464.h b/tracker/software/drivers/si4464.h index d8a25a2..3e857ce 100644 --- a/tracker/software/drivers/si4464.h +++ b/tracker/software/drivers/si4464.h @@ -39,7 +39,8 @@ bool radioTune(uint32_t frequency, uint16_t shift, int8_t level, uint16_t size); void Si4464_writeFIFO(uint8_t *msg, uint8_t size); uint8_t Si4464_freeFIFO(void); uint8_t Si4464_getState(void); -int8_t Si4464_getTemperature(void); +int16_t Si4464_getTemperature(void); +int16_t Si4464_getLastTemperature(void); #endif diff --git a/tracker/software/drivers/ublox.c b/tracker/software/drivers/ublox.c index 843c1da..5bb1fa5 100644 --- a/tracker/software/drivers/ublox.c +++ b/tracker/software/drivers/ublox.c @@ -186,35 +186,48 @@ uint16_t gps_receive_payload(uint8_t class_id, uint8_t msg_id, unsigned char *pa * */ bool gps_get_fix(gpsFix_t *fix) { - static uint8_t response[92]; + static uint8_t navpvt[128]; + static uint8_t navstatus[32]; // Transmit request - uint8_t pvt[] = {0xB5, 0x62, 0x01, 0x07, 0x00, 0x00, 0x08, 0x19}; - gps_transmit_string(pvt, sizeof(pvt)); + uint8_t navpvt_req[] = {0xB5, 0x62, 0x01, 0x07, 0x00, 0x00, 0x08, 0x19}; + gps_transmit_string(navpvt_req, sizeof(navpvt_req)); - if(!gps_receive_payload(0x01, 0x07, response, 5000)) { // Receive request - TRACE_ERROR("GPS > PVT Polling FAILED"); + if(!gps_receive_payload(0x01, 0x07, navpvt, 3000)) { // Receive request + TRACE_ERROR("GPS > NAV-PVT Polling FAILED"); return false; } - fix->num_svs = response[23]; - fix->type = response[20]; + uint8_t navstatus_req[] = {0xB5, 0x62, 0x01, 0x03, 0x00, 0x00, 0x04, 0x0D}; + gps_transmit_string(navstatus_req, sizeof(navstatus_req)); - fix->time.year = response[4] + (response[5] << 8); - fix->time.month = response[6]; - fix->time.day = response[7]; - fix->time.hour = response[8]; - fix->time.minute = response[9]; - fix->time.second = response[10]; + if(!gps_receive_payload(0x01, 0x03, navstatus, 3000)) { // Receive request + TRACE_ERROR("GPS > NAV-STATUS Polling FAILED"); + return false; + } + + // Extract data from message + fix->fixOK = navstatus[5] & 0x1; + fix->pdop = navpvt[76] + (navpvt[77] << 8); + + fix->num_svs = navpvt[23]; + fix->type = navpvt[20]; + + fix->time.year = navpvt[4] + (navpvt[5] << 8); + fix->time.month = navpvt[6]; + fix->time.day = navpvt[7]; + fix->time.hour = navpvt[8]; + fix->time.minute = navpvt[9]; + fix->time.second = navpvt[10]; fix->lat = (int32_t) ( - (uint32_t)(response[28]) + ((uint32_t)(response[29]) << 8) + ((uint32_t)(response[30]) << 16) + ((uint32_t)(response[31]) << 24) + (uint32_t)(navpvt[28]) + ((uint32_t)(navpvt[29]) << 8) + ((uint32_t)(navpvt[30]) << 16) + ((uint32_t)(navpvt[31]) << 24) ); fix->lon = (int32_t) ( - (uint32_t)(response[24]) + ((uint32_t)(response[25]) << 8) + ((uint32_t)(response[26]) << 16) + ((uint32_t)(response[27]) << 24) + (uint32_t)(navpvt[24]) + ((uint32_t)(navpvt[25]) << 8) + ((uint32_t)(navpvt[26]) << 16) + ((uint32_t)(navpvt[27]) << 24) ); int32_t alt_tmp = (((int32_t) - ((uint32_t)(response[36]) + ((uint32_t)(response[37]) << 8) + ((uint32_t)(response[38]) << 16) + ((uint32_t)(response[39]) << 24)) + ((uint32_t)(navpvt[36]) + ((uint32_t)(navpvt[37]) << 8) + ((uint32_t)(navpvt[38]) << 16) + ((uint32_t)(navpvt[39]) << 24)) ) / 1000); if (alt_tmp <= 0) { fix->alt = 1; @@ -224,10 +237,10 @@ bool gps_get_fix(gpsFix_t *fix) { fix->alt = (uint16_t)alt_tmp; } - TRACE_INFO("GPS > PVT Polling OK time=%04d-%02d-%02d %02d:%02d:%02d lat=%d.%05d lon=%d.%05d alt=%dm sats=%d", + TRACE_INFO("GPS > Polling OK time=%04d-%02d-%02d %02d:%02d:%02d lat=%d.%05d lon=%d.%05d alt=%dm sats=%d fixOK=%d pDOP=%d.%02d", fix->time.year, fix->time.month, fix->time.day, fix->time.hour, fix->time.minute, fix->time.day, fix->lat/10000000, (fix->lat > 0 ? 1:-1)*(fix->lat/100)%100000, fix->lon/10000000, (fix->lon > 0 ? 1:-1)*(fix->lon/100)%100000, - fix->alt, fix->num_svs + fix->alt, fix->num_svs, fix->fixOK, fix->pdop/100, fix->pdop%100 ); return true; @@ -385,7 +398,7 @@ bool GPS_Init(void) { return false; } - cntr = 5; + cntr = 3; while((status = gps_set_airborne_model()) == false && cntr--); if(status) { TRACE_INFO("GPS > ... Set airborne model OK"); diff --git a/tracker/software/drivers/ublox.h b/tracker/software/drivers/ublox.h index 3b82256..ea8aeee 100644 --- a/tracker/software/drivers/ublox.h +++ b/tracker/software/drivers/ublox.h @@ -15,7 +15,7 @@ //#define UBLOX_USE_UART #define UBLOX_USE_I2C -#define isGPSLocked(pos) ((pos)->type == 3 && (pos)->num_svs >= 5) +#define isGPSLocked(pos) ((pos)->type == 3 && (pos)->num_svs >= 4 && (pos)->fixOK == true) typedef struct { ptime_t time; // Time @@ -24,6 +24,8 @@ typedef struct { int32_t lat; // latitude in deg * 10^7, range -90 .. +90 * 10^7 int32_t lon; // longitude in deg * 10^7, range -180 .. +180 * 10^7 int32_t alt; // altitude in m, range 0m, up to ~40000m, clamped + bool fixOK; // Flag that is set to true, when DOP is with the limits + uint16_t pdop; // Position DOP } gpsFix_t; uint8_t gps_set_gps_only(void); diff --git a/tracker/software/drivers/wrapper/padc.c b/tracker/software/drivers/wrapper/padc.c index 5eae0bb..6859964 100644 --- a/tracker/software/drivers/wrapper/padc.c +++ b/tracker/software/drivers/wrapper/padc.c @@ -68,44 +68,28 @@ void doConversion(void) deinitADC(); } -static uint16_t getBatteryVoltageMV_STM32(void) +uint16_t stm32_get_vbat(void) { doConversion(); return samples[2] * vcc_ref * DIVIDER_VBAT / 4096; } -static uint16_t getSolarVoltageMV_STM32(void) +uint16_t stm32_get_vsol(void) { doConversion(); return samples[0] * vcc_ref * DIVIDER_VSOL / 4096; } -uint16_t getBatteryVoltageMV(void) -{ - uint16_t vbat = getBatteryVoltageMV_STM32(); // Get value from STM32 - uint16_t vbat_pac = pac1720_getVbat(); // Get value from PAC1720 - - return abs(vbat-vbat_pac) < 200 ? vbat_pac : vbat; -} - -uint16_t getSolarVoltageMV(void) -{ - uint16_t vsol = getSolarVoltageMV_STM32(); // Get value from STM32 - uint16_t vsol_pac = pac1720_getVsol(); // Get value from PAC1720 - - return abs(vsol-vsol_pac) < 200 ? vsol_pac : vsol; -} - -uint16_t getUSBVoltageMV(void) +uint16_t stm32_get_vusb(void) { doConversion(); return samples[1] * vcc_ref * DIVIDER_VUSB / 4096; } -uint16_t getSTM32Temperature(void) +uint16_t stm32_get_temp(void) { doConversion(); - return samples[3]; + return (((int32_t)samples[3]*40 * vcc_ref / 4096)-30400) + 2500 + 850/*Calibration*/; } void boost_voltage(bool boost) diff --git a/tracker/software/drivers/wrapper/padc.h b/tracker/software/drivers/wrapper/padc.h index 448e68b..33be789 100644 --- a/tracker/software/drivers/wrapper/padc.h +++ b/tracker/software/drivers/wrapper/padc.h @@ -8,10 +8,10 @@ void initADC(void); void deinitADC(void); -uint16_t getBatteryVoltageMV(void); -uint16_t getSolarVoltageMV(void); -uint16_t getUSBVoltageMV(void); -uint16_t getSTM32Temperature(void); +uint16_t stm32_get_vbat(void); +uint16_t stm32_get_vsol(void); +uint16_t stm32_get_vusb(void); +uint16_t stm32_get_temp(void); void boost_voltage(bool boost); #endif diff --git a/tracker/software/drivers/wrapper/pi2c.c b/tracker/software/drivers/wrapper/pi2c.c index f3ebdb7..f129a5c 100644 --- a/tracker/software/drivers/wrapper/pi2c.c +++ b/tracker/software/drivers/wrapper/pi2c.c @@ -8,6 +8,8 @@ #define I2C_DRIVER (&I2CD1) +static uint8_t error; + const I2CConfig _i2cfg = { OPMODE_I2C, 200000, @@ -23,8 +25,12 @@ static bool I2C_transmit(uint8_t addr, uint8_t *txbuf, uint32_t txbytes, uint8_t if(i2c_status == MSG_TIMEOUT) { // Restart I2C at timeout TRACE_ERROR("I2C > TIMEOUT (ADDR 0x%02x)", addr); + error = 0x1; } else if(i2c_status == MSG_RESET) { TRACE_ERROR("I2C > RESET (ADDR 0x%02x)", addr); + error = 0x0; + } else { + error = 0x0; } return i2c_status == MSG_OK; @@ -97,3 +103,8 @@ bool I2C_write8_16bitreg(uint8_t address, uint16_t reg, uint8_t value) // 16bit return I2C_transmit(address, txbuf, 3, NULL, 0, MS2ST(100)); } +uint8_t I2C_hasError(void) +{ + return error; +} + diff --git a/tracker/software/drivers/wrapper/pi2c.h b/tracker/software/drivers/wrapper/pi2c.h index a743252..463b511 100644 --- a/tracker/software/drivers/wrapper/pi2c.h +++ b/tracker/software/drivers/wrapper/pi2c.h @@ -26,5 +26,7 @@ bool I2C_read16_LE(uint8_t address, uint8_t reg, uint16_t *val); void I2C_Lock(void); void I2C_Unlock(void); +uint8_t I2C_hasError(void); + #endif diff --git a/tracker/software/drivers/wrapper/ptime.c b/tracker/software/drivers/wrapper/ptime.c index dc92541..83fc943 100644 --- a/tracker/software/drivers/wrapper/ptime.c +++ b/tracker/software/drivers/wrapper/ptime.c @@ -10,28 +10,27 @@ const uint16_t leapYear[] = {0,31,60,91,121,152,182,213,244,274,305,335,366}; * @param time Date to be converted * @return UNIX timestamp in milliseconds */ -uint64_t date2UnixTimestamp(ptime_t time) { - uint64_t timeC = 0; - timeC = time.second; - timeC += time.minute * 60; - timeC += time.hour * 3600; - timeC += (time.day-1) * 86400; +uint32_t date2UnixTimestamp(ptime_t *date) { + uint32_t timeC = 0; + timeC = date->second; + timeC += date->minute * 60; + timeC += date->hour * 3600; + timeC += (date->day-1) * 86400; - if(time.year % 4 == 0) { // is leapyear? - timeC += leapYear[time.month-1] * 86400; + if(date->year % 4 == 0) { // is leapyear? + timeC += leapYear[date->month-1] * 86400; } else { - timeC += nonLeapYear[time.month-1] * 86400; + timeC += nonLeapYear[date->month-1] * 86400; } - uint16_t i; - for(i=1970; iyear; i++) { if(i % 4 == 0) { // is leapyear? timeC += 31622400; } else { timeC += 31536000; } } - return timeC * 1000 + time.millisecond; + return timeC; } /** @@ -40,32 +39,26 @@ uint64_t date2UnixTimestamp(ptime_t time) { * @param UNIX timestamp in milliseconds * @return Date in Julian calendar format */ -ptime_t unixTimestamp2Date(uint64_t time) { - ptime_t date; - uint64_t dateRaw = time / 1000; - - date.year = 1970; +void unixTimestamp2Date(ptime_t *date, uint32_t time) { + date->year = 1970; while(true) { - uint32_t secondsInThisYear = date.year % 4 ? 31536000 : 31622400; - if(dateRaw >= secondsInThisYear) { - dateRaw -= secondsInThisYear; - date.year++; + uint32_t secondsInThisYear = date->year % 4 ? 31536000 : 31622400; + if(time >= secondsInThisYear) { + time -= secondsInThisYear; + date->year++; } else { break; } } - for(date.month=1; (date.year%4 ? nonLeapYear[date.month] : (uint32_t)(leapYear[date.month])*86400)<=dateRaw; date.month++); - dateRaw -= (date.year%4 ? nonLeapYear[date.month-1] : leapYear[date.month-1])*86400; + for(date->month=1; (date->year%4 ? nonLeapYear[date->month]*86400 : leapYear[date->month]*86400)<=time; date->month++); + time -= (date->year%4 ? nonLeapYear[date->month-1] : leapYear[date->month-1])*86400; - date.day = (dateRaw / 86400) + 1; - date.hour = (dateRaw % 86400) / 3600; - date.minute = (dateRaw % 3600) / 60; - date.second = dateRaw % 60; - date.millisecond = time % 1000; - - return date; + date->day = (time / 86400) + 1; + date->hour = (time % 86400) / 3600; + date->minute = (time % 3600) / 60; + date->second = time % 60; } /** @@ -73,6 +66,7 @@ ptime_t unixTimestamp2Date(uint64_t time) { * @return Date in Julian calendar format */ void getTime(ptime_t *date) { + TRACE_INFO("GPS > Get time from RTC"); RTCDateTime timespec; rtcGetTime(&RTCD1, ×pec); @@ -82,22 +76,20 @@ void getTime(ptime_t *date) { date->hour = timespec.millisecond / 3600000; date->minute = (timespec.millisecond%3600000) / 60000; date->second = (timespec.millisecond / 1000) % 60; - date->millisecond = timespec.millisecond % 1000; } /** * Sets the STM32 internal time (RTC) * @param date Date in Julian calendar format */ -void setTime(ptime_t date) { - RTCDateTime timespec; - timespec.year = date.year - 2000; - timespec.month = date.month; - timespec.day = date.day; - timespec.millisecond = date.hour * 3600000 + date.minute * 60000 + date.second * 1000 + date.millisecond; - +void setTime(ptime_t *date) { TRACE_INFO("GPS > Calibrate RTC"); - PRINT_TIME("RTC"); + RTCDateTime timespec; + timespec.year = date->year - 2000; + timespec.month = date->month; + timespec.day = date->day; + timespec.millisecond = date->hour * 3600000 + date->minute * 60000 + date->second * 1000; + rtcSetTime(&RTCD1, ×pec); } diff --git a/tracker/software/drivers/wrapper/ptime.h b/tracker/software/drivers/wrapper/ptime.h index 290005b..7d334c7 100644 --- a/tracker/software/drivers/wrapper/ptime.h +++ b/tracker/software/drivers/wrapper/ptime.h @@ -10,13 +10,12 @@ typedef struct { uint8_t hour; uint8_t minute; uint8_t second; - uint16_t millisecond; } ptime_t; -uint64_t date2UnixTimestamp(ptime_t time); -ptime_t unixTimestamp2Date(uint64_t time); +uint32_t date2UnixTimestamp(ptime_t *date); +void unixTimestamp2Date(ptime_t *date, uint32_t time); void getTime(ptime_t *date); -void setTime(ptime_t date); +void setTime(ptime_t *date); #endif diff --git a/tracker/software/mcuconf.h b/tracker/software/mcuconf.h index ec0e75b..58cd2c5 100644 --- a/tracker/software/mcuconf.h +++ b/tracker/software/mcuconf.h @@ -48,15 +48,15 @@ #define STM32_PLLSRC STM32_PLLSRC_HSI #define STM32_PLLM_VALUE 16 #define STM32_PLLN_VALUE 192 -#define STM32_PLLP_VALUE 4 +#define STM32_PLLP_VALUE 2 #define STM32_PLLQ_VALUE 4 #if ACTIVATE_USB /* Activate 48MHz when USB is activated, otherwise 6MHz */ #define STM32_HPRE STM32_HPRE_DIV1 #else -#define STM32_HPRE STM32_HPRE_DIV16 +#define STM32_HPRE STM32_HPRE_DIV1 #endif -#define STM32_PPRE1 STM32_PPRE1_DIV1 -#define STM32_PPRE2 STM32_PPRE2_DIV1 +#define STM32_PPRE1 STM32_PPRE1_DIV2 +#define STM32_PPRE2 STM32_PPRE2_DIV2 #define STM32_RTCSEL STM32_RTCSEL_LSI #define STM32_RTCPRE_VALUE 8 #define STM32_MCO1SEL STM32_MCO1SEL_PLL diff --git a/tracker/software/protocols/aprs/aprs.c b/tracker/software/protocols/aprs/aprs.c index 6fc1158..5da6c63 100644 --- a/tracker/software/protocols/aprs/aprs.c +++ b/tracker/software/protocols/aprs/aprs.c @@ -21,10 +21,10 @@ #include #include #include "debug.h" +#include "base91.h" #define METER_TO_FEET(m) (((m)*26876) / 8192) -static uint16_t loss_of_gps_counter; static uint16_t msg_id; /** @@ -39,16 +39,11 @@ static uint16_t msg_id; */ void aprs_encode_position(ax25_t* packet, const aprs_conf_t *config, trackPoint_t *trackPoint) { - char temp[22]; - ptime_t date = trackPoint->time; + char temp[128]; // 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_byte(packet, '!'); // Latitude uint32_t y = 380926 * (90 - trackPoint->gps_lat/10000000.0); @@ -73,7 +68,7 @@ void aprs_encode_position(ax25_t* packet, const aprs_conf_t *config, trackPoint_ 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 gpsFix = trackPoint->gps_lock == GPS_LOCKED1 || trackPoint->gps_lock == GPS_LOCKED2 ? GSP_FIX_CURRENT : GSP_FIX_OLD; uint8_t src = NMEA_SRC_GGA; uint8_t origin = ORIGIN_PICO; @@ -95,50 +90,9 @@ void aprs_encode_position(ax25_t* packet, const aprs_conf_t *config, trackPoint_ ax25_send_string(packet, temp); // Comments - ax25_send_string(packet, "SATS "); - chsnprintf(temp, sizeof(temp), "%d", trackPoint->gps_sats); + base91_encode((uint8_t*)trackPoint, (uint8_t*)temp, sizeof(trackPoint_t)); ax25_send_string(packet, temp); - switch(trackPoint->gps_lock) { - case GPS_LOCKED: // GPS is locked - // TTFF (Time to first fix) - ax25_send_string(packet, " TTFF "); - chsnprintf(temp, sizeof(temp), "%d", trackPoint->gps_ttff); - ax25_send_string(packet, temp); - ax25_send_string(packet, "sec"); - loss_of_gps_counter = 0; - break; - - case GPS_LOSS: // No GPS lock - ax25_send_string(packet, " GPS LOSS "); - chsnprintf(temp, sizeof(temp), "%d", ++loss_of_gps_counter); - ax25_send_string(packet, temp); - break; - - case GPS_LOWBATT1: // GPS switched off prematurely - ax25_send_string(packet, " GPS LOWBATT1 "); - chsnprintf(temp, sizeof(temp), "%d", ++loss_of_gps_counter); - ax25_send_string(packet, temp); - break; - - case GPS_LOWBATT2: // GPS switched off prematurely - ax25_send_string(packet, " GPS LOWBATT2 "); - chsnprintf(temp, sizeof(temp), "%d", ++loss_of_gps_counter); - ax25_send_string(packet, temp); - break; - - case GPS_ERROR: // GPS error - ax25_send_string(packet, " GPS ERROR "); - chsnprintf(temp, sizeof(temp), "%d", ++loss_of_gps_counter); - ax25_send_string(packet, temp); - break; - - case GPS_LOG: // GPS position from log (because the tracker has been just switched on) - ax25_send_string(packet, " GPS FROM LOG"); - loss_of_gps_counter = 0; - break; - } - ax25_send_byte(packet, '|'); // Sequence ID @@ -151,15 +105,14 @@ void aprs_encode_position(ax25_t* packet, const aprs_conf_t *config, trackPoint_ // Telemetry parameter for(uint8_t i=0; i<5; i++) { switch(config->tel[i]) { - case TEL_SATS: t = trackPoint->gps_sats; break; - case TEL_TTFF: t = trackPoint->gps_ttff; break; - case TEL_VBAT: t = trackPoint->adc_vbat; break; - case TEL_VSOL: t = trackPoint->adc_vsol; break; - case TEL_PBAT: t = trackPoint->adc_pbat+4096; break; - case TEL_RBAT: t = trackPoint->adc_rbat; break; - case TEL_HUM: t = trackPoint->air_hum; break; - case TEL_PRESS: t = trackPoint->air_press/125 - 40; break; - case TEL_TEMP: t = trackPoint->air_temp/10 + 1000; break; + case TEL_SATS: t = trackPoint->gps_sats; break; + case TEL_TTFF: t = trackPoint->gps_ttff; break; + case TEL_VBAT: t = trackPoint->adc_vbat; break; + case TEL_VSOL: t = trackPoint->adc_vsol; break; + case TEL_PBAT: t = trackPoint->pac_pbat+4096; break; + case TEL_HUM: t = trackPoint->sen_i1_hum; break; + case TEL_PRESS: t = trackPoint->sen_i1_press/125 - 40; break; + case TEL_TEMP: t = trackPoint->sen_i1_temp/10 + 1000; break; } temp[0] = t/91 + 33; @@ -185,62 +138,11 @@ void aprs_encode_init(ax25_t* packet, uint8_t* buffer, uint16_t size, mod_t mod) // Encode APRS header ax25_init(packet); } -void aprs_encode_data_packet(ax25_t* packet, char packetType, const aprs_conf_t *config, uint8_t *data, size_t size, trackPoint_t *trackPoint) +void aprs_encode_data_packet(ax25_t* packet, char packetType, const aprs_conf_t *config, uint8_t *data, size_t size) { - 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_string(packet, "{{"); ax25_send_byte(packet, packetType); // Encode message @@ -318,7 +220,6 @@ void aprs_encode_telemetry_configuration(ax25_t* packet, const aprs_conf_t *conf 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; @@ -351,10 +252,6 @@ void aprs_encode_telemetry_configuration(ax25_t* packet, const aprs_conf_t *conf ax25_send_string(packet, "W"); break; - case TEL_RBAT: - ax25_send_string(packet, "Ohm"); - break; - case TEL_HUM: ax25_send_string(packet, "%"); break; @@ -386,7 +283,6 @@ void aprs_encode_telemetry_configuration(ax25_t* packet, const aprs_conf_t *conf case TEL_VBAT: case TEL_VSOL: - case TEL_RBAT: ax25_send_string(packet, "0,.001,0"); break; diff --git a/tracker/software/protocols/aprs/aprs.h b/tracker/software/protocols/aprs/aprs.h index ad94e94..5e51d6d 100644 --- a/tracker/software/protocols/aprs/aprs.h +++ b/tracker/software/protocols/aprs/aprs.h @@ -54,7 +54,7 @@ void aprs_encode_telemetry_configuration(ax25_t* packet, const aprs_conf_t *conf void aprs_encode_message(ax25_t* packet, const aprs_conf_t *config, const char *receiver, const char *text); 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); +void aprs_encode_data_packet(ax25_t* packet, char packetType, const aprs_conf_t *config, uint8_t *data, size_t size); uint32_t aprs_encode_finalize(ax25_t* packet); #endif diff --git a/tracker/software/protocols/aprs/ax25.c b/tracker/software/protocols/aprs/ax25.c index a8d1c26..f852826 100644 --- a/tracker/software/protocols/aprs/ax25.c +++ b/tracker/software/protocols/aprs/ax25.c @@ -133,7 +133,7 @@ void ax25_send_header(ax25_t *packet, const char *callsign, uint8_t ssid, const } for(i=0; ipkt_size_payload = SSDV_PKT_SIZE - SSDV_PKT_SIZE_HEADER - SSDV_PKT_SIZE_CRC; s->pkt_size_crcdata = SSDV_PKT_SIZE_HEADER + s->pkt_size_payload - 1; break; + + case SSDV_TYPE_PADDING: + s->pkt_size_payload = SSDV_PKT_SIZE - SSDV_PKT_SIZE_HEADER - SSDV_PKT_SIZE_CRC - SSDV_PKT_SIZE_PADDING; + s->pkt_size_crcdata = SSDV_PKT_SIZE_HEADER + s->pkt_size_payload - 1; + break; } } @@ -1411,6 +1416,25 @@ char ssdv_dec_is_packet(uint8_t *packet, int *errors) type = SSDV_TYPE_NORMAL; } } + else if(pkt[1] == 0x66 + SSDV_TYPE_PADDING) + { + /* Test for a valid NOFEC packet */ + pkt_size_payload = SSDV_PKT_SIZE - SSDV_PKT_SIZE_HEADER - SSDV_PKT_SIZE_CRC - SSDV_PKT_SIZE_PADDING; + pkt_size_crcdata = SSDV_PKT_SIZE_HEADER + pkt_size_payload - 1; + + /* No FEC scan */ + if(errors) *errors = 0; + + /* Test the checksum */ + x = crc32(&pkt[1], pkt_size_crcdata); + + i = 1 + pkt_size_crcdata; + if(x == (pkt[i + 3] | (pkt[i + 2] << 8) | (pkt[i + 1] << 16) | (pkt[i] << 24))) + { + /* Valid, set the type and continue */ + type = SSDV_TYPE_PADDING; + } + } if(type == SSDV_TYPE_INVALID) { diff --git a/tracker/software/protocols/ssdv/ssdv.h b/tracker/software/protocols/ssdv/ssdv.h index a005ec4..b4e6cae 100644 --- a/tracker/software/protocols/ssdv/ssdv.h +++ b/tracker/software/protocols/ssdv/ssdv.h @@ -36,6 +36,7 @@ extern "C" { #define SSDV_PKT_SIZE_HEADER (0x0F) #define SSDV_PKT_SIZE_CRC (0x04) #define SSDV_PKT_SIZE_RSCODES (0x20) +#define SSDV_PKT_SIZE_PADDING (0x48) #define TBL_LEN (546) /* Maximum size of the DQT and DHT tables */ #define HBUFF_LEN (16) /* Extra space for reading marker data */ @@ -45,6 +46,7 @@ extern "C" { #define SSDV_TYPE_INVALID (0xFF) #define SSDV_TYPE_NORMAL (0x00) #define SSDV_TYPE_NOFEC (0x01) +#define SSDV_TYPE_PADDING (0x02) typedef struct { diff --git a/tracker/software/radio.c b/tracker/software/radio.c index e9ff38b..d4fe2a1 100644 --- a/tracker/software/radio.c +++ b/tracker/software/radio.c @@ -31,6 +31,7 @@ static uint32_t txj; // Bytecounter // Radio related static mutex_t radio_mtx; // Radio mutex +static bool nextTransmissionWaiting; // Flag that informs the feeder thread to keep the radio switched on bool radio_mtx_init = false; static mod_t active_mod = MOD_NOT_SET; static radioMSG_t radio_msg; @@ -265,7 +266,7 @@ THD_FUNCTION(si_fifo_feeder_thd, arg) } Si4464_writeFIFO(&radio_msg.buffer[c], more); // Write into FIFO c += more; - chThdSleepMilliseconds(15); // That value is ok up to 38k4 + chThdSleepMilliseconds(15); // That value is ok up to 96k } // Shutdown radio (and wait for Si4464 to finish transmission) @@ -322,11 +323,17 @@ void shutdownRadio(void) { // Wait for PH to finish transmission while(Si4464_getState() == SI4464_STATE_TX) - chThdSleepMilliseconds(10); + chThdSleepMilliseconds(1); - TRACE_INFO("RAD > Shutdown radio"); - Si4464_shutdown(); - active_mod = MOD_NOT_SET; + if(!nextTransmissionWaiting) { // No thread is waiting for radio, so shutdown radio + TRACE_INFO("RAD > Transmission finished"); + TRACE_INFO("RAD > Shutdown radio"); + Si4464_shutdown(); + active_mod = MOD_NOT_SET; + } else { + TRACE_INFO("RAD > Transmission finished"); + TRACE_INFO("RAD > Keep radio switched on"); + } } /** @@ -477,6 +484,23 @@ void lockRadio(void) chMtxObjectInit(&radio_mtx); radio_mtx_init = true; + chMtxLock(&radio_mtx); + nextTransmissionWaiting = true; + + // Wait for old feeder thread to terminate + if(feeder_thd != NULL) // No waiting on first use + chThdWait(feeder_thd); +} + +/* This method is only called by image.c. It's not different to lockRadio() with + * the exception that the radio it shutdown after transmission (if there is any) */ +void lockRadioByCamera(void) +{ + // Initialize mutex + if(!radio_mtx_init) + chMtxObjectInit(&radio_mtx); + radio_mtx_init = true; + chMtxLock(&radio_mtx); // Wait for old feeder thread to terminate @@ -486,6 +510,7 @@ void lockRadio(void) void unlockRadio(void) { + nextTransmissionWaiting = false; chMtxUnlock(&radio_mtx); } diff --git a/tracker/software/radio.h b/tracker/software/radio.h index 549511f..810ec65 100644 --- a/tracker/software/radio.h +++ b/tracker/software/radio.h @@ -23,6 +23,7 @@ bool transmitOnRadio(radioMSG_t *msg, bool shutdown); void shutdownRadio(void); uint32_t getFrequency(freq_conf_t *config); void lockRadio(void); +void lockRadioByCamera(void); void unlockRadio(void); THD_FUNCTION(moduleRADIO, arg); diff --git a/tracker/software/sleep.c b/tracker/software/sleep.c index 9944ba9..872c590 100644 --- a/tracker/software/sleep.c +++ b/tracker/software/sleep.c @@ -15,16 +15,16 @@ bool p_sleep(const sleep_conf_t *config) switch(config->type) { case SLEEP_WHEN_VBAT_BELOW_THRES: - return getBatteryVoltageMV() < config->vbat_thres; + return stm32_get_vbat() < config->vbat_thres; - case SLEEP_WHEN_RBAT_BELOW_THRES: - return getLastTrackPoint()->adc_rbat < config->rbat_thres; // FIXME + case SLEEP_WHEN_VSOL_BELOW_THRES: + return stm32_get_vsol() < config->vsol_thres; case SLEEP_WHEN_VBAT_ABOVE_THRES: - return getBatteryVoltageMV() > config->vbat_thres; + return stm32_get_vbat() > config->vbat_thres; - case SLEEP_WHEN_RBAT_ABOVE_THRES: - return getLastTrackPoint()->adc_rbat > config->rbat_thres; // FIXME + case SLEEP_WHEN_VSOL_ABOVE_THRES: + return stm32_get_vsol() > config->vsol_thres; case SLEEP_WHEN_DISCHARGING: case SLEEP_WHEN_CHARGING: diff --git a/tracker/software/threads/image.c b/tracker/software/threads/image.c index 4ff5953..0f84920 100644 --- a/tracker/software/threads/image.c +++ b/tracker/software/threads/image.c @@ -301,12 +301,11 @@ static void flush_ssdv_buffer(prot_t protocol, ax25_t *ax25_handle, radioMSG_t * } } -void encode_ssdv(const uint8_t *image, uint32_t image_len, module_conf_t* conf, uint8_t image_id, trackPoint_t* captureLocation, bool redudantTx) +void encode_ssdv(const uint8_t *image, uint32_t image_len, module_conf_t* conf, uint8_t image_id, bool redudantTx) { ssdv_t ssdv; uint8_t pkt[SSDV_PKT_SIZE]; - uint8_t pkt_base91i[160]; - uint8_t pkt_base91j[160]; + uint8_t pkt_base91[256]; const uint8_t *b; uint32_t bi = 0; uint8_t c = SSDV_OK; @@ -314,7 +313,7 @@ void encode_ssdv(const uint8_t *image, uint32_t image_len, module_conf_t* conf, // Init SSDV (FEC at 2FSK, non FEC at APRS) bi = 0; - ssdv_enc_init(&ssdv, conf->protocol == PROT_SSDV_2FSK ? SSDV_TYPE_NORMAL : SSDV_TYPE_NOFEC, conf->ssdv_conf.callsign, image_id, conf->ssdv_conf.quality); + ssdv_enc_init(&ssdv, conf->protocol == PROT_SSDV_2FSK ? SSDV_TYPE_NORMAL : SSDV_TYPE_PADDING, conf->ssdv_conf.callsign, image_id, conf->ssdv_conf.quality); ssdv_enc_set_buffer(&ssdv, pkt); // Init transmission packet @@ -371,27 +370,11 @@ void encode_ssdv(const uint8_t *image, uint32_t image_len, module_conf_t* conf, TRACE_INFO("IMG > Encode APRS/SSDV packet"); // Sync byte, CRC and FEC of SSDV not transmitted (because its not neccessary inside an APRS packet) - base91_encode(&pkt[6 ], pkt_base91i, 109+16); - pkt[112+16] = pkt[6]; - pkt[113+16] = pkt[7]; - pkt[114+16] = pkt[8]; - base91_encode(&pkt[112+16], pkt_base91j, 108+16); + base91_encode(&pkt[6], pkt_base91, 174); - aprs_encode_data_packet(&ax25_handle, 'I', &conf->aprs_conf, pkt_base91i, strlen((char*)pkt_base91i), captureLocation); - aprs_encode_data_packet(&ax25_handle, 'J', &conf->aprs_conf, pkt_base91j, strlen((char*)pkt_base91j), captureLocation); + aprs_encode_data_packet(&ax25_handle, 'I', &conf->aprs_conf, pkt_base91, strlen((char*)pkt_base91)); if(redudantTx) - { - if(conf->protocol == PROT_APRS_AFSK) // AFSK can handle max. 2 packets in the buffer - { - // Transmit packets - flush_ssdv_buffer(conf->protocol, &ax25_handle, &msg); - - // Initialize new packet buffer - aprs_encode_init(&ax25_handle, buffer, sizeof(buffer), msg.mod); - } - aprs_encode_data_packet(&ax25_handle, 'I', &conf->aprs_conf, pkt_base91i, strlen((char*)pkt_base91i), captureLocation); - aprs_encode_data_packet(&ax25_handle, 'J', &conf->aprs_conf, pkt_base91j, strlen((char*)pkt_base91j), captureLocation); - } + aprs_encode_data_packet(&ax25_handle, 'I', &conf->aprs_conf, pkt_base91, strlen((char*)pkt_base91)); // Transmit if buffer is almost full or if single packet transmission is activated (packet_spacing != 0) // or if AFSK is selected (because the encoding takes a lot of buffer) @@ -402,9 +385,6 @@ void encode_ssdv(const uint8_t *image, uint32_t image_len, module_conf_t* conf, // Initialize new packet buffer aprs_encode_init(&ax25_handle, buffer, sizeof(buffer), msg.mod); - - if(!conf->packet_spacing) - chThdSleepMilliseconds(8000); // Leave a little break because it will overflow some devices } break; @@ -432,6 +412,8 @@ void encode_ssdv(const uint8_t *image, uint32_t image_len, module_conf_t* conf, TRACE_ERROR("IMG > Unsupported protocol selected for module IMAGE"); } + chThdSleepMilliseconds(100); // Leave other threads some time + // Packet spacing (delay) if(conf->packet_spacing) chThdSleepMilliseconds(conf->packet_spacing); @@ -445,6 +427,7 @@ void encode_ssdv(const uint8_t *image, uint32_t image_len, module_conf_t* conf, */ static bool analyze_image(uint8_t *image, uint32_t image_len) { + return true; #if !OV5640_USE_DMA_DBM if(image_len >= 65535) { @@ -461,7 +444,7 @@ static bool analyze_image(uint8_t *image, uint32_t image_len) uint16_t i = 0; uint8_t c = SSDV_OK; - ssdv_enc_init(&ssdv, SSDV_TYPE_NORMAL, "", 0, 7); + ssdv_enc_init(&ssdv, SSDV_TYPE_NOFEC, "", 0, 7); ssdv_enc_set_buffer(&ssdv, pkt); while(true) // FIXME: I get caught in these loops occasionally and never return @@ -515,7 +498,7 @@ bool takePicture(ssdv_conf_t *conf, bool enableJpegValidation) camera_found = true; // Lock Radio (The radio uses the same DMA for SPI as the camera) - lockRadio(); // Lock radio + lockRadioByCamera(); // Lock radio uint8_t cntr = 5; bool jpegValid; @@ -582,17 +565,13 @@ 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, &captureLocation, conf->ssdv_conf.redundantTx); + encode_ssdv(conf->ssdv_conf.ram_buffer, conf->ssdv_conf.size_sampled, conf, gimage_id-1, 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, &captureLocation, conf->ssdv_conf.redundantTx); + encode_ssdv(noCameraFound, sizeof(noCameraFound), conf, gimage_id-1, conf->ssdv_conf.redundantTx); } } @@ -609,7 +588,7 @@ void start_image_thread(module_conf_t *conf) TRACE_ERROR("IMG > Could not startup thread (not enough memory available)"); } else { register_thread_at_wdg(conf); - conf->wdg_timeout = chVTGetSystemTimeX() + S2ST(1); + conf->wdg_timeout = chVTGetSystemTimeX() + S2ST(1) + MS2ST(conf->init_delay); } } diff --git a/tracker/software/threads/log.c b/tracker/software/threads/log.c index 0b2c81f..2916f5d 100644 --- a/tracker/software/threads/log.c +++ b/tracker/software/threads/log.c @@ -159,7 +159,7 @@ THD_FUNCTION(logThread, arg) trackPoint_t log; getNextLogTrackPoint(&log); - 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); + TRACE_INFO("id=%d time=%d lat=%d lon=%d alt=%d", log.id, log.gps_time, 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; @@ -167,9 +167,8 @@ THD_FUNCTION(logThread, arg) lon <<= 16; lon /= 3600000000; - uint32_t time = date2UnixTimestamp(log.time) / 1000; - pkt[i*5+0] = time & 0xFFFF; - pkt[i*5+1] = time >> 16; + pkt[i*5+0] = log.gps_time & 0xFFFF; + pkt[i*5+1] = log.gps_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) @@ -196,7 +195,7 @@ THD_FUNCTION(logThread, arg) // 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 + aprs_encode_data_packet(&ax25_handle, 'L', &conf->aprs_conf, pkt_base91, strlen((char*)pkt_base91)); // Encode packet msg.bin_len = aprs_encode_finalize(&ax25_handle); // Transmit packet diff --git a/tracker/software/threads/position.c b/tracker/software/threads/position.c index 8c90638..85403d5 100644 --- a/tracker/software/threads/position.c +++ b/tracker/software/threads/position.c @@ -70,12 +70,15 @@ void positionToMaidenhead(char m[], double lat, double lon) * Replaces placeholders with variables */ void replace_placeholders(char* fskmsg, uint16_t size, trackPoint_t *tp) { + ptime_t time; + unixTimestamp2Date(&time, tp->gps_time); + char buf[16]; chsnprintf(buf, sizeof(buf), "%d", tp->id); str_replace(fskmsg, size, "", buf); - chsnprintf(buf, sizeof(buf), "%04d-%02d-%02d", tp->time.year, tp->time.month, tp->time.day); + chsnprintf(buf, sizeof(buf), "%04d-%02d-%02d", time.year, time.month, time.day); str_replace(fskmsg, size, "", buf); - chsnprintf(buf, sizeof(buf), "%02d:%02d:%02d", tp->time.hour, tp->time.minute, tp->time.second); + chsnprintf(buf, sizeof(buf), "%02d:%02d:%02d", time.hour, time.minute, time.second); str_replace(fskmsg, size, "