From b9ac1a394a765fb460b4b4ac943639b6b1709fb4 Mon Sep 17 00:00:00 2001 From: cyoung Date: Wed, 25 Apr 2018 16:08:46 -0400 Subject: [PATCH 01/14] Initial testing code. --- Makefile | 2 +- main/gen_gdl90.go | 1 + main/lowpower_uat.go | 128 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 130 insertions(+), 1 deletion(-) create mode 100644 main/lowpower_uat.go diff --git a/Makefile b/Makefile index 14a297f6..bb1b286d 100644 --- a/Makefile +++ b/Makefile @@ -15,7 +15,7 @@ all: xgen_gdl90: go get -t -d -v ./main ./godump978 ./uatparse ./sensors - go build $(BUILDINFO) -p 4 main/gen_gdl90.go main/traffic.go main/gps.go main/network.go main/managementinterface.go main/sdr.go main/ping.go main/uibroadcast.go main/monotonic.go main/datalog.go main/equations.go main/sensors.go main/cputemp.go + go build $(BUILDINFO) -p 4 main/gen_gdl90.go main/traffic.go main/gps.go main/network.go main/managementinterface.go main/sdr.go main/ping.go main/uibroadcast.go main/monotonic.go main/datalog.go main/equations.go main/sensors.go main/cputemp.go main/lowpower_uat.go fancontrol: go get -t -d -v ./main diff --git a/main/gen_gdl90.go b/main/gen_gdl90.go index d4ee896f..4c9549e5 100644 --- a/main/gen_gdl90.go +++ b/main/gen_gdl90.go @@ -1486,6 +1486,7 @@ func main() { crcInit() // Initialize CRC16 table. sdrInit() + initUATRadioSerial() pingInit() initTraffic() diff --git a/main/lowpower_uat.go b/main/lowpower_uat.go new file mode 100644 index 00000000..bcd8f42c --- /dev/null +++ b/main/lowpower_uat.go @@ -0,0 +1,128 @@ +package main + +import ( + "encoding/hex" + "errors" + "github.com/uavionix/serial" + "log" + "unsafe" +) + +/* + +#cgo LDFLAGS: -ldump978 + +#include +#include "../dump978/fec.h" + +*/ +import "C" + +var radioSerialConfig *serial.Config +var radioSerialPort *serial.Port + +func initUATRadioSerial() error { + // Init for FEC routines. + C.init_fec() + // Initialize port at 2Mbaud. + radioSerialConfig = &serial.Config{Name: "/dev/ttyACM0", Baud: 2000000} + p, err := serial.OpenPort(radioSerialConfig) + if err != nil { + log.Printf("serial port err: %s\n", err.Error()) + return errors.New("serial port failed to initialize") + } + + radioSerialPort = p + + // Start a goroutine to watch the serial port. + go radioSerialPortReader() + return nil +} + +/* + radioSerialPortReader(). + Loop to read data from the radio serial port. +*/ +var radioMagic = []byte{0x0a, 0xb0, 0xcd, 0xe0} + +func radioSerialPortReader() { + tmpBuf := make([]byte, 1024) // Read buffer. + var buf []byte // Message buffer. + if radioSerialPort == nil { + return + } + defer radioSerialPort.Close() + for { + n, err := radioSerialPort.Read(tmpBuf) + if err != nil { + log.Printf("serial port err, shutting down radio: %s\n", err.Error()) + return + } + buf = append(buf, tmpBuf[:n]...) + bufLen := len(buf) + var finBuf []byte // Truncated buffer, with processed messages extracted. + var numMessages int // Number of messages extracted. + // Search for a suitable message to extract. + for i := 0; i < bufLen-6; i++ { + if (buf[i] == radioMagic[0]) && (buf[i+1] == radioMagic[1]) && (buf[i+2] == radioMagic[2]) && (buf[i+3] == radioMagic[3]) { + // Found the magic sequence. Get the length. + msgLen := int(uint16(buf[i+4]) + (uint16(buf[i+5]) << 8)) + // Check if we've read enough to finish this message. + if bufLen < i+6+msgLen { + break // Wait for more of the message to come in. + } + // Message is long enough. + processRadioMessage(buf[i+6 : i+6+msgLen]) + // Remove everything in the buffer before this message. + finBuf = buf[i+6+msgLen:] + numMessages++ + } + } + if numMessages > 0 { + buf = finBuf + } + } +} + +/* + processRadioMessage(). + Processes a single message from the radio. De-interleaves (when necessary), checks Reed-Solomon, passes to main process. +*/ + +func processRadioMessage(msg []byte) { + log.Printf("processRadioMessage(): %d %s\n", len(msg), hex.EncodeToString(msg)) + var toRelay string + switch len(msg) { + case 552: + to := make([]byte, 552) + var rs_errors int + i := int(C.correct_uplink_frame((*C.uint8_t)(unsafe.Pointer(&msg[0])), (*C.uint8_t)(unsafe.Pointer(&to[0])), (*C.int)(unsafe.Pointer(&rs_errors)))) + toRelay = "+" + hex.EncodeToString(to[:432]) + ";" + log.Printf("i=%d, rs_errors=%d, msg=%s\n", i, rs_errors, toRelay) + case 48: + to := make([]byte, 48) + copy(to, msg) + var rs_errors int + i := int(C.correct_adsb_frame((*C.uint8_t)(unsafe.Pointer(&to[0])), (*C.int)(unsafe.Pointer(&rs_errors)))) + if i == 1 { + // Short ADS-B frame. + toRelay = "-" + hex.EncodeToString(to[:18]) + ";" + log.Printf("i=%d, rs_errors=%d, msg=%s\n", i, rs_errors, toRelay) + } else if i == 2 { + // Long ADS-B frame. + toRelay = "-" + hex.EncodeToString(to[:34]) + ";" + log.Printf("i=%d, rs_errors=%d, msg=%s\n", i, rs_errors, toRelay) + } else { + log.Printf("i=%d, rs_errors=%d, msg=%s\n", i, rs_errors, hex.EncodeToString(to)) + } + default: + log.Printf("processRadioMessage(): unhandled message size %d\n", len(msg)) + } + + if len(toRelay) > 0 { + o, msgtype := parseInput(toRelay) + if o != nil && msgtype != 0 { + relayMessage(msgtype, o) + } + } +} From d8a9d5c1a394cbcb3da1d0aeb3f000b49b690c84 Mon Sep 17 00:00:00 2001 From: cyoung Date: Tue, 1 May 2018 13:41:31 -0400 Subject: [PATCH 02/14] Add signal strength and timestamp parsing. --- main/lowpower_uat.go | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/main/lowpower_uat.go b/main/lowpower_uat.go index bcd8f42c..fe340242 100644 --- a/main/lowpower_uat.go +++ b/main/lowpower_uat.go @@ -66,7 +66,7 @@ func radioSerialPortReader() { for i := 0; i < bufLen-6; i++ { if (buf[i] == radioMagic[0]) && (buf[i+1] == radioMagic[1]) && (buf[i+2] == radioMagic[2]) && (buf[i+3] == radioMagic[3]) { // Found the magic sequence. Get the length. - msgLen := int(uint16(buf[i+4]) + (uint16(buf[i+5]) << 8)) + msgLen := int(uint16(buf[i+4])+(uint16(buf[i+5])<<8)) + 5 // 5 bytes for RSSI and TS. // Check if we've read enough to finish this message. if bufLen < i+6+msgLen { break // Wait for more of the message to come in. @@ -91,13 +91,25 @@ func radioSerialPortReader() { func processRadioMessage(msg []byte) { log.Printf("processRadioMessage(): %d %s\n", len(msg), hex.EncodeToString(msg)) + + // RSSI and message timestamp are prepended to the actual packet. + + // RSSI + rssiRaw := int8(msg[0]) + rssiAdjusted := int16(rssiRaw) - 132 // -132 dBm, calculated minimum RSSI. + rssiDump978 := int16(1000 * (10 ^ (float64(rssiAdjusted) / 20))) + + _ := uint32(msg[1]) + (uint32(msg[2]) << 8) + (uint32(msg[3]) << 16) + (uint32(msg[4]) << 24) // Timestamp. Currently unused. + + msg = msg[5:] + var toRelay string switch len(msg) { case 552: to := make([]byte, 552) var rs_errors int i := int(C.correct_uplink_frame((*C.uint8_t)(unsafe.Pointer(&msg[0])), (*C.uint8_t)(unsafe.Pointer(&to[0])), (*C.int)(unsafe.Pointer(&rs_errors)))) - toRelay = "+" + hex.EncodeToString(to[:432]) + ";" + toRelay = fmt.Sprintf("+%s;ss=%d;", hex.EncodeToString(to[:432]), rssiDump978) log.Printf("i=%d, rs_errors=%d, msg=%s\n", i, rs_errors, toRelay) case 48: to := make([]byte, 48) @@ -106,11 +118,11 @@ func processRadioMessage(msg []byte) { i := int(C.correct_adsb_frame((*C.uint8_t)(unsafe.Pointer(&to[0])), (*C.int)(unsafe.Pointer(&rs_errors)))) if i == 1 { // Short ADS-B frame. - toRelay = "-" + hex.EncodeToString(to[:18]) + ";" + toRelay = fmt.Sprintf("-%s;ss=%d;", hex.EncodeToString(to[:18]), rssiDump978) log.Printf("i=%d, rs_errors=%d, msg=%s\n", i, rs_errors, toRelay) } else if i == 2 { // Long ADS-B frame. - toRelay = "-" + hex.EncodeToString(to[:34]) + ";" + toRelay = fmt.Sprintf("-%s;ss=%d;", hex.EncodeToString(to[:34]), rssiDump978) log.Printf("i=%d, rs_errors=%d, msg=%s\n", i, rs_errors, toRelay) } else { log.Printf("i=%d, rs_errors=%d, msg=%s\n", i, rs_errors, hex.EncodeToString(to)) From 164b00396fb41452b9fea3cbe2eee3caf8b8a8d3 Mon Sep 17 00:00:00 2001 From: cyoung Date: Mon, 21 May 2018 14:27:34 -0400 Subject: [PATCH 03/14] Remove FEC computations on Pi side. --- main/lowpower_uat.go | 64 ++++++++++++++------------------------------ 1 file changed, 20 insertions(+), 44 deletions(-) diff --git a/main/lowpower_uat.go b/main/lowpower_uat.go index fe340242..af15c7ad 100644 --- a/main/lowpower_uat.go +++ b/main/lowpower_uat.go @@ -3,27 +3,16 @@ package main import ( "encoding/hex" "errors" + "fmt" "github.com/uavionix/serial" "log" - "unsafe" + "math" ) -/* - -#cgo LDFLAGS: -ldump978 - -#include -#include "../dump978/fec.h" - -*/ -import "C" - var radioSerialConfig *serial.Config var radioSerialPort *serial.Port func initUATRadioSerial() error { - // Init for FEC routines. - C.init_fec() // Initialize port at 2Mbaud. radioSerialConfig = &serial.Config{Name: "/dev/ttyACM0", Baud: 2000000} p, err := serial.OpenPort(radioSerialConfig) @@ -66,7 +55,7 @@ func radioSerialPortReader() { for i := 0; i < bufLen-6; i++ { if (buf[i] == radioMagic[0]) && (buf[i+1] == radioMagic[1]) && (buf[i+2] == radioMagic[2]) && (buf[i+3] == radioMagic[3]) { // Found the magic sequence. Get the length. - msgLen := int(uint16(buf[i+4])+(uint16(buf[i+5])<<8)) + 5 // 5 bytes for RSSI and TS. + msgLen := int(uint16(buf[i+4])+(uint16(buf[i+5])<<8)) + 6 // 6 bytes for rs_errors, RSSI, and TS. // Check if we've read enough to finish this message. if bufLen < i+6+msgLen { break // Wait for more of the message to come in. @@ -92,45 +81,32 @@ func radioSerialPortReader() { func processRadioMessage(msg []byte) { log.Printf("processRadioMessage(): %d %s\n", len(msg), hex.EncodeToString(msg)) - // RSSI and message timestamp are prepended to the actual packet. + // rs_errors, RSSI, and message timestamp are prepended to the actual packet. + + // rs_errors. + rs_errors := int8(msg[0]) // RSSI - rssiRaw := int8(msg[0]) + rssiRaw := int8(msg[1]) rssiAdjusted := int16(rssiRaw) - 132 // -132 dBm, calculated minimum RSSI. - rssiDump978 := int16(1000 * (10 ^ (float64(rssiAdjusted) / 20))) + l := math.Pow(10.0, float64(rssiAdjusted)/20.0) + rssiDump978 := int16(1000.0 * l) - _ := uint32(msg[1]) + (uint32(msg[2]) << 8) + (uint32(msg[3]) << 16) + (uint32(msg[4]) << 24) // Timestamp. Currently unused. + // Timestamp. + //ts := uint32(msg[2]) + (uint32(msg[3]) << 8) + (uint32(msg[4]) << 16) + (uint32(msg[5]) << 24) // Timestamp. Currently unused. - msg = msg[5:] + msg = msg[6:] var toRelay string - switch len(msg) { - case 552: - to := make([]byte, 552) - var rs_errors int - i := int(C.correct_uplink_frame((*C.uint8_t)(unsafe.Pointer(&msg[0])), (*C.uint8_t)(unsafe.Pointer(&to[0])), (*C.int)(unsafe.Pointer(&rs_errors)))) - toRelay = fmt.Sprintf("+%s;ss=%d;", hex.EncodeToString(to[:432]), rssiDump978) - log.Printf("i=%d, rs_errors=%d, msg=%s\n", i, rs_errors, toRelay) - case 48: - to := make([]byte, 48) - copy(to, msg) - var rs_errors int - i := int(C.correct_adsb_frame((*C.uint8_t)(unsafe.Pointer(&to[0])), (*C.int)(unsafe.Pointer(&rs_errors)))) - if i == 1 { - // Short ADS-B frame. - toRelay = fmt.Sprintf("-%s;ss=%d;", hex.EncodeToString(to[:18]), rssiDump978) - log.Printf("i=%d, rs_errors=%d, msg=%s\n", i, rs_errors, toRelay) - } else if i == 2 { - // Long ADS-B frame. - toRelay = fmt.Sprintf("-%s;ss=%d;", hex.EncodeToString(to[:34]), rssiDump978) - log.Printf("i=%d, rs_errors=%d, msg=%s\n", i, rs_errors, toRelay) - } else { - log.Printf("i=%d, rs_errors=%d, msg=%s\n", i, rs_errors, hex.EncodeToString(to)) - } - default: - log.Printf("processRadioMessage(): unhandled message size %d\n", len(msg)) + if len(msg) < 432 { + toRelay = "-" // Downlink. + } else { + toRelay = "+" // Uplink. } + toRelay += fmt.Sprintf("%s;ss=%d;", hex.EncodeToString(msg), rssiDump978) + log.Printf("rs_errors=%d, msg=%s\n", rs_errors, toRelay) + if len(toRelay) > 0 { o, msgtype := parseInput(toRelay) if o != nil && msgtype != 0 { From 462de2843f11f3d3b223e0dc633c897f7cdce8ba Mon Sep 17 00:00:00 2001 From: cyoung Date: Mon, 11 Jun 2018 16:50:33 -0400 Subject: [PATCH 04/14] Revert back to FEC calculating code. --- main/lowpower_uat.go | 66 ++++++++++++++++++++++++++------------------ 1 file changed, 39 insertions(+), 27 deletions(-) diff --git a/main/lowpower_uat.go b/main/lowpower_uat.go index af15c7ad..bcd8f42c 100644 --- a/main/lowpower_uat.go +++ b/main/lowpower_uat.go @@ -3,16 +3,27 @@ package main import ( "encoding/hex" "errors" - "fmt" "github.com/uavionix/serial" "log" - "math" + "unsafe" ) +/* + +#cgo LDFLAGS: -ldump978 + +#include +#include "../dump978/fec.h" + +*/ +import "C" + var radioSerialConfig *serial.Config var radioSerialPort *serial.Port func initUATRadioSerial() error { + // Init for FEC routines. + C.init_fec() // Initialize port at 2Mbaud. radioSerialConfig = &serial.Config{Name: "/dev/ttyACM0", Baud: 2000000} p, err := serial.OpenPort(radioSerialConfig) @@ -55,7 +66,7 @@ func radioSerialPortReader() { for i := 0; i < bufLen-6; i++ { if (buf[i] == radioMagic[0]) && (buf[i+1] == radioMagic[1]) && (buf[i+2] == radioMagic[2]) && (buf[i+3] == radioMagic[3]) { // Found the magic sequence. Get the length. - msgLen := int(uint16(buf[i+4])+(uint16(buf[i+5])<<8)) + 6 // 6 bytes for rs_errors, RSSI, and TS. + msgLen := int(uint16(buf[i+4]) + (uint16(buf[i+5]) << 8)) // Check if we've read enough to finish this message. if bufLen < i+6+msgLen { break // Wait for more of the message to come in. @@ -80,33 +91,34 @@ func radioSerialPortReader() { func processRadioMessage(msg []byte) { log.Printf("processRadioMessage(): %d %s\n", len(msg), hex.EncodeToString(msg)) - - // rs_errors, RSSI, and message timestamp are prepended to the actual packet. - - // rs_errors. - rs_errors := int8(msg[0]) - - // RSSI - rssiRaw := int8(msg[1]) - rssiAdjusted := int16(rssiRaw) - 132 // -132 dBm, calculated minimum RSSI. - l := math.Pow(10.0, float64(rssiAdjusted)/20.0) - rssiDump978 := int16(1000.0 * l) - - // Timestamp. - //ts := uint32(msg[2]) + (uint32(msg[3]) << 8) + (uint32(msg[4]) << 16) + (uint32(msg[5]) << 24) // Timestamp. Currently unused. - - msg = msg[6:] - var toRelay string - if len(msg) < 432 { - toRelay = "-" // Downlink. - } else { - toRelay = "+" // Uplink. + switch len(msg) { + case 552: + to := make([]byte, 552) + var rs_errors int + i := int(C.correct_uplink_frame((*C.uint8_t)(unsafe.Pointer(&msg[0])), (*C.uint8_t)(unsafe.Pointer(&to[0])), (*C.int)(unsafe.Pointer(&rs_errors)))) + toRelay = "+" + hex.EncodeToString(to[:432]) + ";" + log.Printf("i=%d, rs_errors=%d, msg=%s\n", i, rs_errors, toRelay) + case 48: + to := make([]byte, 48) + copy(to, msg) + var rs_errors int + i := int(C.correct_adsb_frame((*C.uint8_t)(unsafe.Pointer(&to[0])), (*C.int)(unsafe.Pointer(&rs_errors)))) + if i == 1 { + // Short ADS-B frame. + toRelay = "-" + hex.EncodeToString(to[:18]) + ";" + log.Printf("i=%d, rs_errors=%d, msg=%s\n", i, rs_errors, toRelay) + } else if i == 2 { + // Long ADS-B frame. + toRelay = "-" + hex.EncodeToString(to[:34]) + ";" + log.Printf("i=%d, rs_errors=%d, msg=%s\n", i, rs_errors, toRelay) + } else { + log.Printf("i=%d, rs_errors=%d, msg=%s\n", i, rs_errors, hex.EncodeToString(to)) + } + default: + log.Printf("processRadioMessage(): unhandled message size %d\n", len(msg)) } - toRelay += fmt.Sprintf("%s;ss=%d;", hex.EncodeToString(msg), rssiDump978) - log.Printf("rs_errors=%d, msg=%s\n", rs_errors, toRelay) - if len(toRelay) > 0 { o, msgtype := parseInput(toRelay) if o != nil && msgtype != 0 { From 7142edb3ba96b87f3a4688e87380c6b685bf1e6e Mon Sep 17 00:00:00 2001 From: cyoung Date: Mon, 11 Jun 2018 16:56:14 -0400 Subject: [PATCH 05/14] Restore RSSI/timestamp parsing. --- main/lowpower_uat.go | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/main/lowpower_uat.go b/main/lowpower_uat.go index bcd8f42c..d96841ef 100644 --- a/main/lowpower_uat.go +++ b/main/lowpower_uat.go @@ -66,7 +66,7 @@ func radioSerialPortReader() { for i := 0; i < bufLen-6; i++ { if (buf[i] == radioMagic[0]) && (buf[i+1] == radioMagic[1]) && (buf[i+2] == radioMagic[2]) && (buf[i+3] == radioMagic[3]) { // Found the magic sequence. Get the length. - msgLen := int(uint16(buf[i+4]) + (uint16(buf[i+5]) << 8)) + msgLen := int(uint16(buf[i+4])+(uint16(buf[i+5])<<8)) + 5 // 5 bytes for RSSI and TS. // Check if we've read enough to finish this message. if bufLen < i+6+msgLen { break // Wait for more of the message to come in. @@ -91,13 +91,26 @@ func radioSerialPortReader() { func processRadioMessage(msg []byte) { log.Printf("processRadioMessage(): %d %s\n", len(msg), hex.EncodeToString(msg)) + + // RSSI and message timestamp are prepended to the actual packet. + + // RSSI + rssiRaw := int8(msg[0]) + //rssiAdjusted := int16(rssiRaw) - 132 // -132 dBm, calculated minimum RSSI. + //rssiDump978 := int16(1000 * (10 ^ (float64(rssiAdjusted) / 20))) + rssiDump978 := rssiRaw + + _ := uint32(msg[1]) + (uint32(msg[2]) << 8) + (uint32(msg[3]) << 16) + (uint32(msg[4]) << 24) // Timestamp. Currently unused. + + msg = msg[5:] + var toRelay string switch len(msg) { case 552: to := make([]byte, 552) var rs_errors int i := int(C.correct_uplink_frame((*C.uint8_t)(unsafe.Pointer(&msg[0])), (*C.uint8_t)(unsafe.Pointer(&to[0])), (*C.int)(unsafe.Pointer(&rs_errors)))) - toRelay = "+" + hex.EncodeToString(to[:432]) + ";" + toRelay = fmt.Sprintf("+%s;ss=%d;", hex.EncodeToString(to[:432]), rssiDump978) log.Printf("i=%d, rs_errors=%d, msg=%s\n", i, rs_errors, toRelay) case 48: to := make([]byte, 48) @@ -106,11 +119,11 @@ func processRadioMessage(msg []byte) { i := int(C.correct_adsb_frame((*C.uint8_t)(unsafe.Pointer(&to[0])), (*C.int)(unsafe.Pointer(&rs_errors)))) if i == 1 { // Short ADS-B frame. - toRelay = "-" + hex.EncodeToString(to[:18]) + ";" + toRelay = fmt.Sprintf("-%s;ss=%d;", hex.EncodeToString(to[:18]), rssiDump978) log.Printf("i=%d, rs_errors=%d, msg=%s\n", i, rs_errors, toRelay) } else if i == 2 { // Long ADS-B frame. - toRelay = "-" + hex.EncodeToString(to[:34]) + ";" + toRelay = fmt.Sprintf("-%s;ss=%d;", hex.EncodeToString(to[:34]), rssiDump978) log.Printf("i=%d, rs_errors=%d, msg=%s\n", i, rs_errors, toRelay) } else { log.Printf("i=%d, rs_errors=%d, msg=%s\n", i, rs_errors, hex.EncodeToString(to)) From 2dca39c7d81627b2a0d1f9c1fb0d079385a2447e Mon Sep 17 00:00:00 2001 From: cyoung Date: Mon, 11 Jun 2018 19:02:38 -0400 Subject: [PATCH 06/14] Add udev rules. Change start-up sequence (fixes race condition -- receiving UAT packets before init is complete). --- image/10-stratux.rules | 4 ++++ main/gen_gdl90.go | 5 ++++- main/lowpower_uat.go | 6 ++++-- 3 files changed, 12 insertions(+), 3 deletions(-) diff --git a/image/10-stratux.rules b/image/10-stratux.rules index 14b20ca6..8a5b6fed 100644 --- a/image/10-stratux.rules +++ b/image/10-stratux.rules @@ -12,6 +12,10 @@ SUBSYSTEMS=="usb", ATTRS{idVendor}=="1546", ATTRS{idProduct}=="01a6", SYMLINK+=" #SUBSYSTEMS=="usb", ATTRS{idVendor}=="1546", ATTRS{idProduct}=="01a7", SYMLINK+="vk172" #SUBSYSTEMS=="usb", ATTRS{idVendor}=="1546", ATTRS{idProduct}=="01a6", SYMLINK+="vk162" +# Stratux uatradio. +# 0424:9514 (LaunchPad) +SUBSYSTEMS=="usb", ATTRS{idVendor}=="0424", ATTRS{idProduct}=="9514", SYMLINK+="uatradio" + # pl2303 devices are indistinguishable using idVendor and idProduct. diff --git a/main/gen_gdl90.go b/main/gen_gdl90.go index 53961400..b68cb12a 100644 --- a/main/gen_gdl90.go +++ b/main/gen_gdl90.go @@ -1533,7 +1533,6 @@ func main() { crcInit() // Initialize CRC16 table. sdrInit() - initUATRadioSerial() pingInit() initTraffic() @@ -1574,6 +1573,10 @@ func main() { globalStatus.CPUTemp = cpuTemp }) + // Start reading from serial UAT radio. + //FIXME: Follow 978 SDR option, or make a new one. + initUATRadioSerial() + reader := bufio.NewReader(os.Stdin) if *replayFlag == true { diff --git a/main/lowpower_uat.go b/main/lowpower_uat.go index d96841ef..ebb4157a 100644 --- a/main/lowpower_uat.go +++ b/main/lowpower_uat.go @@ -3,8 +3,10 @@ package main import ( "encoding/hex" "errors" + "fmt" "github.com/uavionix/serial" "log" + "time" "unsafe" ) @@ -25,7 +27,7 @@ func initUATRadioSerial() error { // Init for FEC routines. C.init_fec() // Initialize port at 2Mbaud. - radioSerialConfig = &serial.Config{Name: "/dev/ttyACM0", Baud: 2000000} + radioSerialConfig = &serial.Config{Name: "/dev/uatradio", Baud: 2000000} p, err := serial.OpenPort(radioSerialConfig) if err != nil { log.Printf("serial port err: %s\n", err.Error()) @@ -100,7 +102,7 @@ func processRadioMessage(msg []byte) { //rssiDump978 := int16(1000 * (10 ^ (float64(rssiAdjusted) / 20))) rssiDump978 := rssiRaw - _ := uint32(msg[1]) + (uint32(msg[2]) << 8) + (uint32(msg[3]) << 16) + (uint32(msg[4]) << 24) // Timestamp. Currently unused. + //_ := uint32(msg[1]) + (uint32(msg[2]) << 8) + (uint32(msg[3]) << 16) + (uint32(msg[4]) << 24) // Timestamp. Currently unused. msg = msg[5:] From fbb64a434552a53edf149ec2be040ee4e8c2143e Mon Sep 17 00:00:00 2001 From: cyoung Date: Wed, 13 Jun 2018 15:10:11 -0400 Subject: [PATCH 07/14] Cleanup. Add /dev/uatradio rule. --- image/10-stratux.rules | 4 ++-- main/lowpower_uat.go | 1 - 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/image/10-stratux.rules b/image/10-stratux.rules index 8a5b6fed..414ea8bc 100644 --- a/image/10-stratux.rules +++ b/image/10-stratux.rules @@ -13,8 +13,8 @@ SUBSYSTEMS=="usb", ATTRS{idVendor}=="1546", ATTRS{idProduct}=="01a6", SYMLINK+=" #SUBSYSTEMS=="usb", ATTRS{idVendor}=="1546", ATTRS{idProduct}=="01a6", SYMLINK+="vk162" # Stratux uatradio. -# 0424:9514 (LaunchPad) -SUBSYSTEMS=="usb", ATTRS{idVendor}=="0424", ATTRS{idProduct}=="9514", SYMLINK+="uatradio" +# 0403:7028 (Stratux UATRadio) +ATTRS{idProduct}=="7028", ATTRS{idVendor}=="0403", RUN+="/sbin/modprobe -q ftdi_sio" RUN+="/bin/sh -c 'echo 0403 7028 > /sys/bus/usb-serial/drivers/ftdi_sio/new_id'", OWNER="root", MODE="0666", SYMLINK+="uatradio" diff --git a/main/lowpower_uat.go b/main/lowpower_uat.go index ebb4157a..bab3710b 100644 --- a/main/lowpower_uat.go +++ b/main/lowpower_uat.go @@ -6,7 +6,6 @@ import ( "fmt" "github.com/uavionix/serial" "log" - "time" "unsafe" ) From 8703b4c124719e82010409c71cbf8c75575666ff Mon Sep 17 00:00:00 2001 From: cyoung Date: Tue, 10 Jul 2018 17:42:44 -0400 Subject: [PATCH 08/14] Don't relay uncorrectable (rs_errors=9999) messages. --- .DS_Store | Bin 0 -> 6148 bytes main/lowpower_uat.go | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) create mode 100644 .DS_Store diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..5008ddfcf53c02e82d7eee2e57c38e5672ef89f6 GIT binary patch literal 6148 zcmeH~Jr2S!425mzP>H1@V-^m;4Wg<&0T*E43hX&L&p$$qDprKhvt+--jT7}7np#A3 zem<@ulZcFPQ@L2!n>{z**++&mCkOWA81W14cNZlEfg7;MkzE(HCqgga^y>{tEnwC%0;vJ&^%eQ zLs35+`xjp>T0 0 { + if len(toRelay) > 0 && rs_errors != 9999 { o, msgtype := parseInput(toRelay) if o != nil && msgtype != 0 { relayMessage(msgtype, o) From 4b0f7f47cf48455b8138017a93c37127d8c2fcf1 Mon Sep 17 00:00:00 2001 From: cyoung Date: Fri, 13 Jul 2018 12:03:36 -0400 Subject: [PATCH 09/14] Scope error fix. --- main/lowpower_uat.go | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/main/lowpower_uat.go b/main/lowpower_uat.go index 969ead0b..d12f4224 100644 --- a/main/lowpower_uat.go +++ b/main/lowpower_uat.go @@ -106,17 +106,16 @@ func processRadioMessage(msg []byte) { msg = msg[5:] var toRelay string + var rs_errors int switch len(msg) { case 552: to := make([]byte, 552) - var rs_errors int i := int(C.correct_uplink_frame((*C.uint8_t)(unsafe.Pointer(&msg[0])), (*C.uint8_t)(unsafe.Pointer(&to[0])), (*C.int)(unsafe.Pointer(&rs_errors)))) toRelay = fmt.Sprintf("+%s;ss=%d;", hex.EncodeToString(to[:432]), rssiDump978) log.Printf("i=%d, rs_errors=%d, msg=%s\n", i, rs_errors, toRelay) case 48: to := make([]byte, 48) copy(to, msg) - var rs_errors int i := int(C.correct_adsb_frame((*C.uint8_t)(unsafe.Pointer(&to[0])), (*C.int)(unsafe.Pointer(&rs_errors)))) if i == 1 { // Short ADS-B frame. From 578148e5f2435c257393cbc960826c24d9c75a88 Mon Sep 17 00:00:00 2001 From: cyoung Date: Mon, 13 Aug 2018 22:52:01 -0400 Subject: [PATCH 10/14] Change to stratux/serial. --- main/lowpower_uat.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/main/lowpower_uat.go b/main/lowpower_uat.go index d12f4224..21a7c0b1 100644 --- a/main/lowpower_uat.go +++ b/main/lowpower_uat.go @@ -4,7 +4,7 @@ import ( "encoding/hex" "errors" "fmt" - "github.com/uavionix/serial" + "github.com/stratux/serial" "log" "unsafe" ) From beed8e7c1aaaa765898285dc34aa6e43df5e18e4 Mon Sep 17 00:00:00 2001 From: cyoung Date: Thu, 27 Sep 2018 11:11:44 -0400 Subject: [PATCH 11/14] Remove debug logging. --- main/lowpower_uat.go | 7 ------- 1 file changed, 7 deletions(-) diff --git a/main/lowpower_uat.go b/main/lowpower_uat.go index 21a7c0b1..25a92fe8 100644 --- a/main/lowpower_uat.go +++ b/main/lowpower_uat.go @@ -91,8 +91,6 @@ func radioSerialPortReader() { */ func processRadioMessage(msg []byte) { - log.Printf("processRadioMessage(): %d %s\n", len(msg), hex.EncodeToString(msg)) - // RSSI and message timestamp are prepended to the actual packet. // RSSI @@ -112,7 +110,6 @@ func processRadioMessage(msg []byte) { to := make([]byte, 552) i := int(C.correct_uplink_frame((*C.uint8_t)(unsafe.Pointer(&msg[0])), (*C.uint8_t)(unsafe.Pointer(&to[0])), (*C.int)(unsafe.Pointer(&rs_errors)))) toRelay = fmt.Sprintf("+%s;ss=%d;", hex.EncodeToString(to[:432]), rssiDump978) - log.Printf("i=%d, rs_errors=%d, msg=%s\n", i, rs_errors, toRelay) case 48: to := make([]byte, 48) copy(to, msg) @@ -120,13 +117,9 @@ func processRadioMessage(msg []byte) { if i == 1 { // Short ADS-B frame. toRelay = fmt.Sprintf("-%s;ss=%d;", hex.EncodeToString(to[:18]), rssiDump978) - log.Printf("i=%d, rs_errors=%d, msg=%s\n", i, rs_errors, toRelay) } else if i == 2 { // Long ADS-B frame. toRelay = fmt.Sprintf("-%s;ss=%d;", hex.EncodeToString(to[:34]), rssiDump978) - log.Printf("i=%d, rs_errors=%d, msg=%s\n", i, rs_errors, toRelay) - } else { - log.Printf("i=%d, rs_errors=%d, msg=%s\n", i, rs_errors, hex.EncodeToString(to)) } default: log.Printf("processRadioMessage(): unhandled message size %d\n", len(msg)) From 96338b413d79bed34ceb81a073735fd77aef0987 Mon Sep 17 00:00:00 2001 From: cyoung Date: Thu, 27 Sep 2018 11:33:47 -0400 Subject: [PATCH 12/14] Add /dev/uatradio on a one second interval. --- main/gen_gdl90.go | 2 +- main/lowpower_uat.go | 50 ++++++++++++++++++++++++++++++-------------- main/sdr.go | 3 +++ 3 files changed, 38 insertions(+), 17 deletions(-) diff --git a/main/gen_gdl90.go b/main/gen_gdl90.go index b68cb12a..e77773dc 100644 --- a/main/gen_gdl90.go +++ b/main/gen_gdl90.go @@ -1132,6 +1132,7 @@ type status struct { UAT_traffic_targets_tracking uint16 ES_traffic_targets_tracking uint16 Ping_connected bool + UATRadio_connected bool GPS_satellites_locked uint16 GPS_satellites_seen uint16 GPS_satellites_tracked uint16 @@ -1574,7 +1575,6 @@ func main() { }) // Start reading from serial UAT radio. - //FIXME: Follow 978 SDR option, or make a new one. initUATRadioSerial() reader := bufio.NewReader(os.Stdin) diff --git a/main/lowpower_uat.go b/main/lowpower_uat.go index 25a92fe8..0ae14720 100644 --- a/main/lowpower_uat.go +++ b/main/lowpower_uat.go @@ -6,6 +6,8 @@ import ( "fmt" "github.com/stratux/serial" "log" + "os" + "time" "unsafe" ) @@ -25,18 +27,34 @@ var radioSerialPort *serial.Port func initUATRadioSerial() error { // Init for FEC routines. C.init_fec() - // Initialize port at 2Mbaud. - radioSerialConfig = &serial.Config{Name: "/dev/uatradio", Baud: 2000000} - p, err := serial.OpenPort(radioSerialConfig) - if err != nil { - log.Printf("serial port err: %s\n", err.Error()) - return errors.New("serial port failed to initialize") - } + go func() { + watchTicker := time.NewTicker(1 * time.Second) + for { + <-watchTicker.C + // Watch for the radio or change in settings. + if !globalSettings.UAT_Enabled || globalStatus.UATRadio_connected { + // UAT not enabled or radio already set up. Continue. + continue + } + if _, err := os.Stat("/dev/uatradio"); err != nil { + // Device not connected. + continue + } + // Initialize port at 2Mbaud. + radioSerialConfig = &serial.Config{Name: "/dev/uatradio", Baud: 2000000} + p, err := serial.OpenPort(radioSerialConfig) + if err != nil { + log.Printf("serial port err: %s\n", err.Error()) + continue + } - radioSerialPort = p + radioSerialPort = p + globalStatus.UATRadio_connected = true - // Start a goroutine to watch the serial port. - go radioSerialPortReader() + // Start a goroutine to watch the serial port. + go radioSerialPortReader(radioSerialPort) + } + }() return nil } @@ -46,15 +64,15 @@ func initUATRadioSerial() error { */ var radioMagic = []byte{0x0a, 0xb0, 0xcd, 0xe0} -func radioSerialPortReader() { +func radioSerialPortReader(serialPort *serial.Port) { + defer func() { + globalStatus.UATRadio_connected = false + serialPort.Close() + }() tmpBuf := make([]byte, 1024) // Read buffer. var buf []byte // Message buffer. - if radioSerialPort == nil { - return - } - defer radioSerialPort.Close() for { - n, err := radioSerialPort.Read(tmpBuf) + n, err := serialPort.Read(tmpBuf) if err != nil { log.Printf("serial port err, shutting down radio: %s\n", err.Error()) return diff --git a/main/sdr.go b/main/sdr.go index 40fab42f..6bbd771c 100644 --- a/main/sdr.go +++ b/main/sdr.go @@ -522,6 +522,9 @@ func sdrWatcher() { esEnabled := globalSettings.ES_Enabled uatEnabled := globalSettings.UAT_Enabled count := rtl.GetDeviceCount() + if UATRadio_connected { + count++ + } atomic.StoreUint32(&globalStatus.Devices, uint32(count)) // support up to two dongles From 517ad79632f3c43b67a2b1b5519da73b920197ed Mon Sep 17 00:00:00 2001 From: cyoung Date: Thu, 27 Sep 2018 11:40:22 -0400 Subject: [PATCH 13/14] Imports/unused variable fix. --- main/lowpower_uat.go | 3 +-- main/sdr.go | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/main/lowpower_uat.go b/main/lowpower_uat.go index 0ae14720..13f6e2c8 100644 --- a/main/lowpower_uat.go +++ b/main/lowpower_uat.go @@ -2,7 +2,6 @@ package main import ( "encoding/hex" - "errors" "fmt" "github.com/stratux/serial" "log" @@ -126,7 +125,7 @@ func processRadioMessage(msg []byte) { switch len(msg) { case 552: to := make([]byte, 552) - i := int(C.correct_uplink_frame((*C.uint8_t)(unsafe.Pointer(&msg[0])), (*C.uint8_t)(unsafe.Pointer(&to[0])), (*C.int)(unsafe.Pointer(&rs_errors)))) + C.correct_uplink_frame((*C.uint8_t)(unsafe.Pointer(&msg[0])), (*C.uint8_t)(unsafe.Pointer(&to[0])), (*C.int)(unsafe.Pointer(&rs_errors))) toRelay = fmt.Sprintf("+%s;ss=%d;", hex.EncodeToString(to[:432]), rssiDump978) case 48: to := make([]byte, 48) diff --git a/main/sdr.go b/main/sdr.go index 6bbd771c..d0295e7d 100644 --- a/main/sdr.go +++ b/main/sdr.go @@ -522,7 +522,7 @@ func sdrWatcher() { esEnabled := globalSettings.ES_Enabled uatEnabled := globalSettings.UAT_Enabled count := rtl.GetDeviceCount() - if UATRadio_connected { + if globalStatus.UATRadio_connected { count++ } atomic.StoreUint32(&globalStatus.Devices, uint32(count)) From cd4b75681077448b4be5ac5600b3599b93b449d6 Mon Sep 17 00:00:00 2001 From: cyoung Date: Thu, 27 Sep 2018 14:23:03 -0400 Subject: [PATCH 14/14] Add log output. Change SDR count only for interface. --- main/lowpower_uat.go | 6 +++++- main/sdr.go | 5 +++-- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/main/lowpower_uat.go b/main/lowpower_uat.go index 13f6e2c8..321cbe52 100644 --- a/main/lowpower_uat.go +++ b/main/lowpower_uat.go @@ -39,14 +39,18 @@ func initUATRadioSerial() error { // Device not connected. continue } + log.Printf("===== UAT Device Name : UATRadio v1.0 =====\n") + // Initialize port at 2Mbaud. radioSerialConfig = &serial.Config{Name: "/dev/uatradio", Baud: 2000000} p, err := serial.OpenPort(radioSerialConfig) if err != nil { - log.Printf("serial port err: %s\n", err.Error()) + log.Printf("\tUAT Open Failed: %s\n", err.Error()) continue } + log.Printf("\tUATRadio init success.\n") + radioSerialPort = p globalStatus.UATRadio_connected = true diff --git a/main/sdr.go b/main/sdr.go index d0295e7d..596e9974 100644 --- a/main/sdr.go +++ b/main/sdr.go @@ -522,10 +522,11 @@ func sdrWatcher() { esEnabled := globalSettings.ES_Enabled uatEnabled := globalSettings.UAT_Enabled count := rtl.GetDeviceCount() + interfaceCount := count if globalStatus.UATRadio_connected { - count++ + interfaceCount++ } - atomic.StoreUint32(&globalStatus.Devices, uint32(count)) + atomic.StoreUint32(&globalStatus.Devices, uint32(interfaceCount)) // support up to two dongles if count > 2 {