kopia lustrzana https://github.com/cyoung/stratux
UAT and ES mode/hardware handling
rodzic
7bfb0067b4
commit
595f50cc2f
325
main/sdr.go
325
main/sdr.go
|
@ -1,133 +1,200 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"log"
|
||||
"os/exec"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"../godump978"
|
||||
rtl "github.com/jpoirier/gortlsdr"
|
||||
"log"
|
||||
"time"
|
||||
)
|
||||
|
||||
var uatSDR int // Index.
|
||||
var esSDR int // Index.
|
||||
type UAT struct {
|
||||
dev *rtl.Context
|
||||
indexID int
|
||||
}
|
||||
|
||||
type ES struct {
|
||||
dev *rtl.Context
|
||||
indexID int
|
||||
}
|
||||
|
||||
var UATDev *UAT
|
||||
var ESDev *ES
|
||||
|
||||
var uat_shutdown chan int
|
||||
var uat_wg *sync.WaitGroup = &sync.WaitGroup{}
|
||||
|
||||
var es_shutdown chan int
|
||||
var es_wg *sync.WaitGroup = &sync.WaitGroup{}
|
||||
|
||||
var maxSignalStrength int
|
||||
|
||||
// Read 978MHz from SDR.
|
||||
func sdrReader() {
|
||||
var err error
|
||||
var dev *rtl.Context
|
||||
|
||||
log.Printf("===== UAT Device name: %s =====\n", rtl.GetDeviceName(uatSDR))
|
||||
if dev, err = rtl.Open(uatSDR); err != nil {
|
||||
log.Printf("\tOpen Failed, exiting\n")
|
||||
uatSDR = -1
|
||||
func (e *ES) read() {
|
||||
defer es_wg.Done()
|
||||
log.Println("Entered ES read() ...")
|
||||
cmd := exec.Command("/usr/bin/dump1090", "--net", "--device-index", strconv.Itoa(e.indexID))
|
||||
err := cmd.Start()
|
||||
if err != nil {
|
||||
log.Printf("Error executing /usr/bin/dump1090: %s\n", err.Error())
|
||||
return
|
||||
}
|
||||
defer dev.Close()
|
||||
m, p, s, err := dev.GetUsbStrings()
|
||||
if err != nil {
|
||||
log.Printf("\tGetUsbStrings Failed - error: %s\n", err)
|
||||
} else {
|
||||
log.Printf("\tGetUsbStrings - %s %s %s\n", m, p, s)
|
||||
log.Println("Executed /usr/bin/dump1090 successfully...")
|
||||
for {
|
||||
select {
|
||||
default:
|
||||
time.Sleep(1 * time.Second)
|
||||
case _ = <-es_shutdown:
|
||||
log.Println("ES read(): shutdown msg received, calling cmd.Process.Kill() ...")
|
||||
cmd.Process.Kill()
|
||||
log.Println("\t kill successful...")
|
||||
return
|
||||
}
|
||||
}
|
||||
log.Printf("\tGetTunerType: %s\n", dev.GetTunerType())
|
||||
}
|
||||
|
||||
func (u *UAT) read() {
|
||||
defer uat_wg.Done()
|
||||
// defer u.dev.Close()
|
||||
log.Println("Entered UAT read() ...")
|
||||
var buffer = make([]uint8, rtl.DefaultBufLength)
|
||||
for {
|
||||
select {
|
||||
default:
|
||||
nRead, err := u.dev.ReadSync(buffer, rtl.DefaultBufLength)
|
||||
if err != nil {
|
||||
log.Printf("\tReadSync Failed - error: %s\n", err)
|
||||
break
|
||||
}
|
||||
// log.Printf("\tReadSync %d\n", nRead)
|
||||
if nRead > 0 {
|
||||
buf := buffer[:nRead]
|
||||
godump978.InChan <- buf
|
||||
}
|
||||
case _ = <-uat_shutdown:
|
||||
log.Println("UAT read(): shutdown msg received...")
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (e *ES) sdrConfig() (err error) {
|
||||
return
|
||||
}
|
||||
|
||||
// Read 978MHz from SDR.
|
||||
func (u *UAT) sdrConfig() (err error) {
|
||||
log.Printf("===== UAT Device name: %s =====\n", rtl.GetDeviceName(u.indexID))
|
||||
if u.dev, err = rtl.Open(u.indexID); err != nil {
|
||||
log.Printf("\tUAT Open Failed...\n")
|
||||
return
|
||||
}
|
||||
log.Printf("\tGetTunerType: %s\n", u.dev.GetTunerType())
|
||||
|
||||
//---------- Set Tuner Gain ----------
|
||||
tgain := 480
|
||||
|
||||
err = dev.SetTunerGainMode(true)
|
||||
err = u.dev.SetTunerGainMode(true)
|
||||
if err != nil {
|
||||
u.dev.Close()
|
||||
log.Printf("\tSetTunerGainMode Failed - error: %s\n", err)
|
||||
return
|
||||
} else {
|
||||
log.Printf("\tSetTunerGainMode Successful\n")
|
||||
}
|
||||
|
||||
err = dev.SetTunerGain(tgain)
|
||||
tgain := 480
|
||||
err = u.dev.SetTunerGain(tgain)
|
||||
if err != nil {
|
||||
u.dev.Close()
|
||||
log.Printf("\tSetTunerGain Failed - error: %s\n", err)
|
||||
return
|
||||
} else {
|
||||
log.Printf("\tSetTunerGain Successful\n")
|
||||
}
|
||||
|
||||
//---------- Get/Set Sample Rate ----------
|
||||
samplerate := 2083334
|
||||
err = dev.SetSampleRate(samplerate)
|
||||
err = u.dev.SetSampleRate(samplerate)
|
||||
if err != nil {
|
||||
u.dev.Close()
|
||||
log.Printf("\tSetSampleRate Failed - error: %s\n", err)
|
||||
return
|
||||
} else {
|
||||
log.Printf("\tSetSampleRate - rate: %d\n", samplerate)
|
||||
}
|
||||
log.Printf("\tGetSampleRate: %d\n", dev.GetSampleRate())
|
||||
log.Printf("\tGetSampleRate: %d\n", u.dev.GetSampleRate())
|
||||
|
||||
//---------- Get/Set Xtal Freq ----------
|
||||
rtlFreq, tunerFreq, err := dev.GetXtalFreq()
|
||||
rtlFreq, tunerFreq, err := u.dev.GetXtalFreq()
|
||||
if err != nil {
|
||||
u.dev.Close()
|
||||
log.Printf("\tGetXtalFreq Failed - error: %s\n", err)
|
||||
return
|
||||
} else {
|
||||
log.Printf("\tGetXtalFreq - Rtl: %d, Tuner: %d\n", rtlFreq, tunerFreq)
|
||||
}
|
||||
|
||||
newRTLFreq := 28800000
|
||||
newTunerFreq := 28800000
|
||||
err = dev.SetXtalFreq(newRTLFreq, newTunerFreq)
|
||||
err = u.dev.SetXtalFreq(newRTLFreq, newTunerFreq)
|
||||
if err != nil {
|
||||
u.dev.Close()
|
||||
log.Printf("\tSetXtalFreq Failed - error: %s\n", err)
|
||||
return
|
||||
} else {
|
||||
log.Printf("\tSetXtalFreq - Center freq: %d, Tuner freq: %d\n",
|
||||
newRTLFreq, newTunerFreq)
|
||||
}
|
||||
|
||||
//---------- Get/Set Center Freq ----------
|
||||
err = dev.SetCenterFreq(978000000)
|
||||
err = u.dev.SetCenterFreq(978000000)
|
||||
if err != nil {
|
||||
u.dev.Close()
|
||||
log.Printf("\tSetCenterFreq 978MHz Failed, error: %s\n", err)
|
||||
return
|
||||
} else {
|
||||
log.Printf("\tSetCenterFreq 978MHz Successful\n")
|
||||
}
|
||||
|
||||
log.Printf("\tGetCenterFreq: %d\n", dev.GetCenterFreq())
|
||||
log.Printf("\tGetCenterFreq: %d\n", u.dev.GetCenterFreq())
|
||||
|
||||
//---------- Set Bandwidth ----------
|
||||
bw := 1000000
|
||||
log.Printf("\tSetting Bandwidth: %d\n", bw)
|
||||
if err = dev.SetTunerBw(bw); err != nil {
|
||||
if err = u.dev.SetTunerBw(bw); err != nil {
|
||||
u.dev.Close()
|
||||
log.Printf("\tSetTunerBw %d Failed, error: %s\n", bw, err)
|
||||
return
|
||||
} else {
|
||||
log.Printf("\tSetTunerBw %d Successful\n", bw)
|
||||
}
|
||||
|
||||
if err = dev.ResetBuffer(); err == nil {
|
||||
log.Printf("\tResetBuffer Successful\n")
|
||||
} else {
|
||||
if err = u.dev.ResetBuffer(); err != nil {
|
||||
u.dev.Close()
|
||||
log.Printf("\tResetBuffer Failed - error: %s\n", err)
|
||||
return
|
||||
} else {
|
||||
log.Printf("\tResetBuffer Successful\n")
|
||||
}
|
||||
//---------- Get/Set Freq Correction ----------
|
||||
freqCorr := dev.GetFreqCorrection()
|
||||
freqCorr := u.dev.GetFreqCorrection()
|
||||
log.Printf("\tGetFreqCorrection: %d\n", freqCorr)
|
||||
err = dev.SetFreqCorrection(globalSettings.PPM)
|
||||
err = u.dev.SetFreqCorrection(globalSettings.PPM)
|
||||
if err != nil {
|
||||
u.dev.Close()
|
||||
log.Printf("\tSetFreqCorrection %d Failed, error: %s\n", globalSettings.PPM, err)
|
||||
return
|
||||
} else {
|
||||
log.Printf("\tSetFreqCorrection %d Successful\n", globalSettings.PPM)
|
||||
}
|
||||
|
||||
for uatSDR != -1 {
|
||||
var buffer = make([]uint8, rtl.DefaultBufLength)
|
||||
nRead, err := dev.ReadSync(buffer, rtl.DefaultBufLength)
|
||||
if err != nil {
|
||||
log.Printf("\tReadSync Failed - error: %s\n", err)
|
||||
uatSDR = -1
|
||||
break
|
||||
} else {
|
||||
// log.Printf("\tReadSync %d\n", nRead)
|
||||
buf := buffer[:nRead]
|
||||
godump978.InChan <- buf
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// Read from the godump978 channel - on or off.
|
||||
func uatReader() {
|
||||
log.Println("Entered uatReader() ...")
|
||||
for {
|
||||
uat := <-godump978.OutChan
|
||||
o, msgtype := parseInput(uat)
|
||||
|
@ -137,34 +204,158 @@ func uatReader() {
|
|||
}
|
||||
}
|
||||
|
||||
func (u *UAT) shutdown() {
|
||||
log.Println("Entered UAT shutdown() ...")
|
||||
close(uat_shutdown) // signal to shutdown
|
||||
log.Println("UAT shutdown(): closing device ...")
|
||||
// XXX: how to preempt ReadSync?
|
||||
// the assumption is that calling Close()
|
||||
// causes ReadSync to return immediately
|
||||
u.dev.Close()
|
||||
log.Println("UAT shutdown(): calling uat_wg.Wait() ...")
|
||||
uat_wg.Wait() // Wait for the goroutine to shutdown
|
||||
log.Println("UAT shutdown(): uat_wg.Wait() returned...")
|
||||
}
|
||||
|
||||
func (e *ES) shutdown() {
|
||||
log.Println("Entered ES shutdown() ...")
|
||||
close(es_shutdown) // signal to shutdown
|
||||
log.Println("ES shutdown(): calling es_wg.Wait() ...")
|
||||
es_wg.Wait() // Wait for the goroutine to shutdown
|
||||
log.Println("ES shutdown(): es_wg.Wait() returned...")
|
||||
}
|
||||
|
||||
var devMap = map[int]string{0: "", 1: ""}
|
||||
|
||||
// Watch for config/device changes.
|
||||
func sdrWatcher() {
|
||||
timer := time.NewTicker(1 * time.Second)
|
||||
for {
|
||||
<-timer.C
|
||||
// Update device count.
|
||||
globalStatus.Devices = uint(rtl.GetDeviceCount())
|
||||
time.Sleep(1 * time.Second)
|
||||
count := rtl.GetDeviceCount()
|
||||
log.Println("DeviceCount...", count)
|
||||
|
||||
if uatSDR == -1 && globalSettings.UAT_Enabled {
|
||||
if globalStatus.Devices == 0 {
|
||||
log.Printf("No RTL-SDR devices.\n")
|
||||
continue
|
||||
}
|
||||
uatSDR = 0
|
||||
go sdrReader()
|
||||
// support two and only two dongles
|
||||
if count > 2 {
|
||||
count = 2
|
||||
}
|
||||
if esSDR == -1 && globalSettings.ES_Enabled {
|
||||
if globalStatus.Devices == 0 || (globalStatus.Devices == 1 && globalSettings.UAT_Enabled) {
|
||||
log.Printf("Not enough RTL-SDR devices.\n")
|
||||
|
||||
// cleanup if necessary
|
||||
if count < 1 || (!globalSettings.UAT_Enabled && !globalSettings.ES_Enabled) {
|
||||
log.Println("doing cleanup...")
|
||||
if UATDev != nil {
|
||||
UATDev.shutdown()
|
||||
UATDev = nil
|
||||
}
|
||||
esSDR = 1
|
||||
if ESDev != nil {
|
||||
ESDev.shutdown()
|
||||
ESDev = nil
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
if count == 1 {
|
||||
if UATDev != nil && ESDev == nil {
|
||||
UATDev.indexID = 0
|
||||
} else if UATDev == nil && ESDev != nil {
|
||||
ESDev.indexID = 0
|
||||
}
|
||||
}
|
||||
|
||||
ids := []string{"", ""}
|
||||
for i := 0; i < count; i++ {
|
||||
// manufact, product, serial, err
|
||||
_, _, s, _ := rtl.GetDeviceUsbStrings(i)
|
||||
ids[i] = s
|
||||
}
|
||||
|
||||
// UAT specific handling
|
||||
// When count is one, favor UAT in the case where the user
|
||||
// has enabled both UAT and ES via the web interface.
|
||||
id := 0
|
||||
if globalSettings.UAT_Enabled {
|
||||
if count == 1 {
|
||||
if ESDev != nil {
|
||||
ESDev.shutdown()
|
||||
ESDev = nil
|
||||
}
|
||||
} else { // count == 2
|
||||
if UATDev == nil && ESDev != nil {
|
||||
if ESDev.indexID == 0 {
|
||||
id = 1
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if UATDev == nil {
|
||||
// preference check based on stratux
|
||||
// hardware serial when it exists
|
||||
serial := ids[id]
|
||||
if strings.HasPrefix(serial, "stratux:1090") {
|
||||
log.Println("Settings conflict: 978UAT set via WebUI but hardware serial says stratux:1090")
|
||||
} else {
|
||||
UATDev = &UAT{indexID: id}
|
||||
if err := UATDev.sdrConfig(); err != nil {
|
||||
UATDev = nil
|
||||
} else {
|
||||
uat_shutdown = make(chan int)
|
||||
uat_wg.Add(1)
|
||||
go UATDev.read()
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if UATDev != nil {
|
||||
UATDev.shutdown()
|
||||
UATDev = nil
|
||||
if count == 1 && ESDev != nil {
|
||||
ESDev.indexID = 0
|
||||
}
|
||||
}
|
||||
|
||||
// ES specific handling
|
||||
id = 0
|
||||
if globalSettings.ES_Enabled {
|
||||
if count == 1 {
|
||||
if globalSettings.UAT_Enabled {
|
||||
// defer to the UAT handler
|
||||
goto End
|
||||
}
|
||||
} else { // count == 2
|
||||
if ESDev == nil && UATDev != nil {
|
||||
if UATDev.indexID == 0 {
|
||||
id = 1
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ESDev == nil {
|
||||
// preference check based on stratux
|
||||
// hardware serial when it exists
|
||||
serial := ids[id]
|
||||
if strings.HasPrefix(serial, "stratux:978") {
|
||||
log.Println("Settings conflict: 1090ES set via WebUI but hardware serial says stratux:978")
|
||||
} else {
|
||||
ESDev = &ES{indexID: id}
|
||||
if err := ESDev.sdrConfig(); err != nil {
|
||||
ESDev = nil
|
||||
} else {
|
||||
es_shutdown = make(chan int)
|
||||
es_wg.Add(1)
|
||||
go ESDev.read()
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if ESDev != nil {
|
||||
ESDev.shutdown()
|
||||
ESDev = nil
|
||||
if count == 1 && UATDev != nil {
|
||||
UATDev.indexID = 0
|
||||
}
|
||||
}
|
||||
End:
|
||||
}
|
||||
}
|
||||
|
||||
func sdrInit() {
|
||||
uatSDR = -1
|
||||
esSDR = -1
|
||||
go sdrWatcher()
|
||||
go uatReader()
|
||||
godump978.Dump978Init()
|
||||
|
|
Ładowanie…
Reference in New Issue