diff --git a/dump1090 b/dump1090 index 1ab60624..9a4fb850 160000 --- a/dump1090 +++ b/dump1090 @@ -1 +1 @@ -Subproject commit 1ab60624329e538d4b950121542174bed5d00810 +Subproject commit 9a4fb850937565cfeadd1e5889cddbf93f45faf5 diff --git a/image/config.txt b/image/config.txt index df043d3a..937f43be 100644 --- a/image/config.txt +++ b/image/config.txt @@ -5,3 +5,6 @@ max_usb_current=1 dtparam=i2c1=on dtparam=i2c1_baudrate=400000 dtparam=i2c_arm_baudrate=400000 + +# move RPi3 Bluetooth off of hardware UART to free up connection for GPS +dtoverlay=pi3-miniuart-bt diff --git a/image/stxAliases.txt b/image/stxAliases.txt index a5fa24db..e5a36168 100644 --- a/image/stxAliases.txt +++ b/image/stxAliases.txt @@ -21,8 +21,8 @@ alias kal1='kal -d 1 -s GSM850 -g 47' alias kalChan0='function _kalChan0 () { kal -d 0 -g 47 -c $1; unset -f _kalChan0; }; _kalChan0' alias kalChan1='function _kalChan1 () { kal -d 1 -g 47 -c $1; unset -f _kalChan1; }; _kalChan1' -alias setSerial0='function _setSerial0 () { rtl_eeprom -d 0 -s stx:0:$1; unset -f _setSerial0 }; _setSerial0' -alias setSerial1='function _setSerial0 () { rtl_eeprom -d 1 -s stx:0:$1; unset -f _setSerial1 }; _setSerial1' +alias setSerial0='function _setSerial0 () { rtl_eeprom -d 0 -s stx:0:$1; unset -f _setSerial0; }; _setSerial0' +alias setSerial1='function _setSerial0 () { rtl_eeprom -d 1 -s stx:0:$1; unset -f _setSerial1; }; _setSerial1' alias stratux-help='_stxhelp' diff --git a/main/datalog.go b/main/datalog.go index 48164b17..4f99e93e 100644 --- a/main/datalog.go +++ b/main/datalog.go @@ -20,7 +20,6 @@ import ( "reflect" "strconv" "strings" - // "sync" "time" ) @@ -34,8 +33,17 @@ type StratuxTimestamp struct { StratuxClock_value time.Time GPSClock_value time.Time // The value of this is either from the GPS or extrapolated from the GPS via stratuxClock if pref is 1 or 2. It is time.Time{} if 0. PreferredTime_value time.Time + StartupID int64 } +// 'startup' table creates a new entry each time the daemon is started. This keeps track of sequential starts, even if the +// timestamp is ambiguous (units with no GPS). This struct is just a placeholder for an empty table (other than primary key). +type StratuxStartup struct { + id int64 + Fill string +} + +var stratuxStartupID int64 var dataLogTimestamps []StratuxTimestamp var dataLogCurTimestamp int64 // Current timestamp bucket. This is an index on dataLogTimestamps which is not necessarily the db id. @@ -49,7 +57,6 @@ var dataLogCurTimestamp int64 // Current timestamp bucket. This is an index on d func checkTimestamp() bool { thisCurTimestamp := dataLogCurTimestamp if stratuxClock.Since(dataLogTimestamps[thisCurTimestamp].StratuxClock_value) >= LOG_TIMESTAMP_RESOLUTION { - //FIXME: mutex. var ts StratuxTimestamp ts.id = 0 ts.Time_type_preference = 0 // stratuxClock. @@ -73,10 +80,8 @@ func checkTimestamp() bool { } } - //logTimestampMutex.Lock() // if we need to protect against simultaneous insertions dataLogTimestamps = append(dataLogTimestamps, ts) dataLogCurTimestamp = int64(len(dataLogTimestamps) - 1) - //logTimestampMutex.Unlock() return false } return true @@ -196,11 +201,12 @@ func makeTable(i interface{}, tbl string, db *sql.DB) { } // Add the timestamp_id field to link up with the timestamp table. - if tbl != "timestamp" { + if tbl != "timestamp" && tbl != "startup" { fields = append(fields, "timestamp_id INTEGER") } tblCreate := fmt.Sprintf("CREATE TABLE %s (id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, %s)", tbl, strings.Join(fields, ", ")) + _, err := db.Exec(tblCreate) if err != nil { fmt.Printf("ERROR: %s\n", err.Error()) @@ -293,12 +299,13 @@ func insertData(i interface{}, tbl string, db *sql.DB, ts_num int64) int64 { } // Add the timestamp_id field to link up with the timestamp table. - if tbl != "timestamp" { + if tbl != "timestamp" && tbl != "startup" { keys = append(keys, "timestamp_id") if dataLogTimestamps[ts_num].id == 0 { //FIXME: This is somewhat convoluted. When insertData() is called for a ts_num that corresponds to a timestamp with no database id, // then it inserts that timestamp via the same interface and the id is updated in the structure via the below lines // (dataLogTimestamps[ts_num].id = id). + dataLogTimestamps[ts_num].StartupID = stratuxStartupID insertData(dataLogTimestamps[ts_num], "timestamp", db, ts_num) // Updates dataLogTimestamps[ts_num].id. } values = append(values, strconv.FormatInt(dataLogTimestamps[ts_num].id, 10)) @@ -319,11 +326,11 @@ func insertData(i interface{}, tbl string, db *sql.DB, ts_num int64) int64 { insertBatchIfs[tbl] = append(insertBatchIfs[tbl], ifs) - if tbl == "timestamp" { // Immediate insert always for "timestamp" table. - res, err := bulkInsert("timestamp", db) // Bulk insert of 1, always. + if tbl == "timestamp" || tbl == "startup" { // Immediate insert always for "timestamp" and "startup" table. + res, err := bulkInsert(tbl, db) // Bulk insert of 1, always. if err == nil { id, err := res.LastInsertId() - if err == nil { + if err == nil && tbl == "timestamp" { // Special handling for timestamps. Update the timestamp ID. ts := dataLogTimestamps[ts_num] ts.id = id dataLogTimestamps[ts_num] = ts @@ -341,7 +348,6 @@ type DataLogRow struct { ts_num int64 } -//var logTimestampMutex *sync.Mutex var dataLogChan chan DataLogRow var shutdownDataLog chan bool @@ -412,8 +418,6 @@ func dataLog() { dataLogTimestamps = append(dataLogTimestamps, ts) dataLogCurTimestamp = 0 - //logTimestampMutex = &sync.Mutex{} - // Check if we need to create a new database. createDatabase := false @@ -449,8 +453,12 @@ func dataLog() { makeTable(msg{}, "messages", db) makeTable(esmsg{}, "es_messages", db) makeTable(Dump1090TermMessage{}, "dump1090_terminal", db) + makeTable(StratuxStartup{}, "startup", db) } + // The first entry to be created is the "startup" entry. + stratuxStartupID = insertData(StratuxStartup{}, "startup", db, 0) + for { select { case r := <-dataLogChan: @@ -474,7 +482,6 @@ func dataLog() { func setDataLogTimeWithGPS(sit SituationData) { if isGPSClockValid() { - //FIXME: mutex. var ts StratuxTimestamp // Piggyback a GPS time update from this update. ts.id = 0 @@ -483,10 +490,8 @@ func setDataLogTimeWithGPS(sit SituationData) { ts.GPSClock_value = sit.GPSTime ts.PreferredTime_value = sit.GPSTime - //logTimestampMutex.Lock() dataLogTimestamps = append(dataLogTimestamps, ts) dataLogCurTimestamp = int64(len(dataLogTimestamps) - 1) - //logTimestampMutex.Unlock() } } diff --git a/main/ry835ai.go b/main/ry835ai.go index 7e00003e..c1b7c22d 100644 --- a/main/ry835ai.go +++ b/main/ry835ai.go @@ -136,9 +136,9 @@ func initGPSSerial() bool { device = "/dev/ttyUSB0" } else if _, err := os.Stat("/dev/ttyACM0"); err == nil { device = "/dev/ttyACM0" - } else if _, err := os.Stat("/dev/ttyS0"); err == nil { - device = "/dev/ttyS0" - } else if _, err := os.Stat("/dev/ttyAMA0"); err == nil { + //} else if _, err := os.Stat("/dev/ttyS0"); err == nil { // ttyS0 appears to be mini UART on RPi 3 + // device = "/dev/ttyS0" + } else if _, err := os.Stat("/dev/ttyAMA0"); err == nil { // ttyAMA0 is PL011 UART (GPIO pins 8 and 10) on all RPi device = "/dev/ttyAMA0" } else { log.Printf("No suitable device found.\n") diff --git a/main/traffic.go b/main/traffic.go index a6f27f7f..0711e958 100644 --- a/main/traffic.go +++ b/main/traffic.go @@ -96,20 +96,22 @@ type TrafficInfo struct { Vvel int16 // feet per minute Timestamp time.Time // timestamp of traffic message, UTC - // Parameters starting at 'Age' are calculated after message receipt. + // Parameters starting at 'Age' are calculated from last message receipt on each call of sendTrafficUpdates(). // Mode S transmits position and track in separate messages, and altitude can also be // received from interrogations. Age float64 // Age of last valid position fix, seconds ago. AgeLastAlt float64 // Age of last altitude message, seconds ago. - Last_seen time.Time // time of last position update, relative to Stratux startup. Used for timing out expired data. - Last_alt time.Time // time of last altitude update, relative to Stratux startup - Last_GnssDiff time.Time // time of last GnssDiffFromBaroAlt update, relative to Stratux startup - Last_GnssDiffAlt int32 // altitude at last GnssDiffFromBaroAlt update - Last_speed time.Time // time of last velocity / track update, relative to Stratux startup - Last_source uint8 // last SDR on which this target was observed + Last_seen time.Time // Time of last position update (stratuxClock). Used for timing out expired data. + Last_alt time.Time // Time of last altitude update (stratuxClock). + Last_GnssDiff time.Time // Time of last GnssDiffFromBaroAlt update (stratuxClock). + Last_GnssDiffAlt int32 // Altitude at last GnssDiffFromBaroAlt update. + Last_speed time.Time // Time of last velocity and track update (stratuxClock). + Last_source uint8 // Last frequency on which this target was received. ExtrapolatedPosition bool // TO-DO: True if Stratux is "coasting" the target from last known position. - Bearing float64 // TO-DO: Bearing in degrees true to traffic from ownship - Distance float64 // TO-DO: Distance to traffic from ownship + Bearing float64 // Bearing in degrees true to traffic from ownship, if it can be calculated. + Distance float64 // Distance to traffic from ownship, if it can be calculated. + //FIXME: Some indicator that Bearing and Distance are valid, since they aren't always available. + //FIXME: Rename variables for consistency, especially "Last_". } type dump1090Data struct { diff --git a/test/mtk_config.sh b/test/mtk_config.sh new file mode 100644 index 00000000..e16afd0d --- /dev/null +++ b/test/mtk_config.sh @@ -0,0 +1,73 @@ +#!/bin/bash +# +# mtk_config.sh: Script to set up MTK3339 receiver for Stratux. +# Resets receiver to 9600 and 1 Hz GPRMC messaging, then enables +# WAAS, 5 Hz position reporting, the NMEA messages needed by +# Stratux, and 38400 bps serial output. + +printf "About to configure MTK3339 receiver on /dev/ttyAMA0.\n" +printf "Press ctrl-C to abort or any other key to continue.\n" +read + +# Iterate through common bitrates and send commands to reduce output to 1 Hz / 9600 bps. +printf "Setting MTK and RPi baud rate of /dev/ttyAMA0 to 9600. Iterating through common rates.\n" +printf "Current /dev/ttyAMA0 baudrate.\n" +printf "\$PMTK220,1000*1F\r\n" > /dev/ttyAMA0 +printf "\$PMTK251,9600*17\r\n" > /dev/ttyAMA0 +sleep 0.2 +printf "38400 bps.\n" +stty -F /dev/ttyAMA0 38400 +printf "\$PMTK220,1000*1F\r\n" > /dev/ttyAMA0 +printf "\$PMTK251,9600*17\r\n" > /dev/ttyAMA0 +sleep 0.2 +printf "115200 bps.\n" +printf "\$PMTK220,1000*1F\r\n" > /dev/ttyAMA0 +stty -F /dev/ttyAMA0 115200 +printf "\$PMTK220,1000*1F\r\n" > /dev/ttyAMA0 +printf "\$PMTK251,9600*17\r\n" > /dev/ttyAMA0 +sleep 0.2 +printf "57600 bps.\n" +stty -F /dev/ttyAMA0 57600 +printf "\$PMTK220,1000*1F\r\n" > /dev/ttyAMA0 +printf "\$PMTK251,9600*17\r\n" > /dev/ttyAMA0 +sleep 0.2 +printf "19200 bps.\n" +stty -F /dev/ttyAMA0 19200 +printf "\$PMTK220,1000*1F\r\n" > /dev/ttyAMA0 +printf "\$PMTK251,9600*17\r\n" > /dev/ttyAMA0 +sleep 0.2 +printf "4800 bps.\n" +stty -F /dev/ttyAMA0 4800 +printf "\$PMTK220,1000*1F\r\n" > /dev/ttyAMA0 +printf "\$PMTK251,9600*17\r\n" > /dev/ttyAMA0 +sleep 0.2 + + +stty -F /dev/ttyAMA0 9600 +printf "\$PMTK314,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0*29\r\n" > /dev/ttyAMA0 + +printf "MTK has been set to 9600 baud with RMC messages at 1 Hz.\n" +printf "Press ctrl-C to abort, or any other key enter to continue with setup.\n" +read + +# Now start the Stratux setup. +printf "Sending MTK command to set GPS baud rate to 38400\n" +printf "\$PMTK251,38400*27\r\n" > /dev/ttyAMA0 + +printf "Setting RPi baud rate of /dev/ttyAMA0 to 38400\n" +stty -F /dev/ttyAMA0 38400 +sleep 0.2 +printf "Sending MTK command to configure NMEA message output\n" +printf "\$PMTK314,0,1,1,1,5,5,0,0,0,0,0,0,0,0,0,0,0,0,0*29\r\n" > /dev/ttyAMA0 +sleep 0.2 +printf "Sending MTK commands to enable WAAS\n" +printf "\$PMTK301,2*2E\r\n" > /dev/ttyAMA0 +sleep 0.2 +printf "\$PMTK513,1*28\r\n" > /dev/ttyAMA0 +sleep 0.2 +printf "Sending MTK commands to enable 5 Hz position reporting\n" +printf "\$PMTK220,200*2C\r\n" > /dev/ttyAMA0 + +# Finally, test the connection. +printf "Opening /dev/ttyAMA0 to listen to GPS. Press ctrl-C to cancel.\n" +cat /dev/ttyAMA0 \ No newline at end of file