le leleyeleyleyle witcher
This commit is contained in:
parent
718b75ece3
commit
163016f55f
34
bladerf.go
34
bladerf.go
|
@ -324,14 +324,31 @@ func GetSampleRateRange(bladeRF *BladeRF, module IOModule) (int, int, int, error
|
|||
return int(bfRange.min), int(bfRange.max), int(bfRange.step), nil
|
||||
}
|
||||
|
||||
func SetBandwidth(bladeRF *BladeRF, module IOModule, bandwidth int) {
|
||||
C.bladerf_set_bandwidth((*bladeRF).bladeRF, C.bladerf_module(module), C.uint(bandwidth), nil)
|
||||
func SetBandwidth(bladeRF *BladeRF, module IOModule, bandwidth int) (int, error) {
|
||||
var actual C.bladerf_bandwidth
|
||||
return int(actual), GetError(C.bladerf_set_bandwidth((*bladeRF).bladeRF, C.bladerf_module(module), C.uint(bandwidth), &actual))
|
||||
}
|
||||
|
||||
func SetGain(bladeRF *BladeRF, module IOModule, gain int) error {
|
||||
return GetError(C.bladerf_set_gain((*bladeRF).bladeRF, C.bladerf_module(module), C.int(gain)))
|
||||
}
|
||||
|
||||
func GetGainMode(bladeRF *BladeRF, module IOModule) (GainMode, error) {
|
||||
var mode C.bladerf_gain_mode
|
||||
|
||||
err := GetError(C.bladerf_get_gain_mode((*bladeRF).bladeRF, C.bladerf_module(module), &mode))
|
||||
result := GainMode(int(mode))
|
||||
if err == nil {
|
||||
return result, nil
|
||||
}
|
||||
|
||||
return -1, err
|
||||
}
|
||||
|
||||
func SetGainMode(bladeRF *BladeRF, module IOModule, mode GainMode) error {
|
||||
return GetError(C.bladerf_set_gain_mode((*bladeRF).bladeRF, C.bladerf_module(module), C.bladerf_gain_mode(mode)))
|
||||
}
|
||||
|
||||
func EnableModule(bladeRF *BladeRF, direction Direction) error {
|
||||
return GetError(C.bladerf_enable_module((*bladeRF).bladeRF, C.bladerf_module(direction), true))
|
||||
}
|
||||
|
@ -347,29 +364,22 @@ func do_work() bool {
|
|||
return call >= 5000
|
||||
}
|
||||
|
||||
func process_sample(addr unsafe.Pointer, size uint) {
|
||||
|
||||
}
|
||||
|
||||
func SyncRX(bladeRF *BladeRF) []int16 {
|
||||
func SyncRX(bladeRF *BladeRF, bufferSize uintptr) []int16 {
|
||||
var metadata C.struct_bladerf_metadata
|
||||
|
||||
var buff *C.int16_t
|
||||
size := unsafe.Sizeof(*buff)
|
||||
start := C.malloc(C.size_t(size * 10000 * 2 * 1))
|
||||
start := C.malloc(C.size_t(size * bufferSize * 2 * 1))
|
||||
|
||||
var err error
|
||||
var done bool
|
||||
var results []int16
|
||||
|
||||
for err == nil && !done {
|
||||
err = GetError(C.bladerf_sync_rx((*bladeRF).bladeRF, start, 10000, &metadata, 5000))
|
||||
err = GetError(C.bladerf_sync_rx((*bladeRF).bladeRF, start, C.uint(bufferSize), &metadata, 32))
|
||||
if err == nil {
|
||||
done = do_work()
|
||||
if done {
|
||||
println("DONE!")
|
||||
process_sample(start, uint(metadata.actual_count))
|
||||
|
||||
for i := 0; i < (int(metadata.actual_count)); i++ {
|
||||
n := (*C.int16_t)(unsafe.Pointer(uintptr(start) + (size * uintptr(i))))
|
||||
results = append(results, int16(*n))
|
||||
|
|
232
bladerf_test.go
232
bladerf_test.go
|
@ -4,138 +4,40 @@ import (
|
|||
"bladerf/log"
|
||||
"fmt"
|
||||
"github.com/gordonklaus/portaudio"
|
||||
fifo "github.com/racerxdl/go.fifo"
|
||||
"github.com/racerxdl/segdsp/demodcore"
|
||||
log2 "log"
|
||||
"math"
|
||||
"os"
|
||||
"os/signal"
|
||||
"testing"
|
||||
)
|
||||
|
||||
type agcState struct {
|
||||
gainNum int32
|
||||
gainDen int32
|
||||
gainMax int32
|
||||
peakTarget int
|
||||
attackStep int
|
||||
decayStep int
|
||||
err int
|
||||
}
|
||||
const audioBufferSize = 8192 / 2
|
||||
|
||||
type demodState struct {
|
||||
lowpassed []int16
|
||||
rateIn int
|
||||
rateOut int
|
||||
rateOut2 int
|
||||
nowR int16
|
||||
nowJ int16
|
||||
preR int16
|
||||
preJ int16
|
||||
prevIndex int
|
||||
// min 1, max 256
|
||||
downsample int
|
||||
postDownsample int
|
||||
outputScale int
|
||||
squelchLevel int
|
||||
conseqSquelch int
|
||||
squelchHits int
|
||||
customAtan int
|
||||
deemph bool
|
||||
deemphA int
|
||||
nowLpr int
|
||||
prevLprIndex int
|
||||
modeDemod func(fm *demodState)
|
||||
agcEnable bool
|
||||
agc agcState
|
||||
}
|
||||
var audioStream *portaudio.Stream
|
||||
var audioFifo = fifo.NewQueue()
|
||||
|
||||
func polarDiscriminant(ar, aj, br, bj int) int {
|
||||
var cr, cj int
|
||||
var angle float64
|
||||
cr = ar*br - aj*-bj
|
||||
cj = aj*br + ar*-bj
|
||||
angle = math.Atan2(float64(cj), float64(cr))
|
||||
return int(angle / math.Pi * (1 << 14))
|
||||
}
|
||||
var demodulator demodcore.DemodCore
|
||||
|
||||
func fastAtan2(y, x int) int {
|
||||
var pi4, pi34, yabs, angle int
|
||||
pi4 = 1 << 12
|
||||
pi34 = 3 * (1 << 12) // note pi = 1<<14
|
||||
if x == 0 && y == 0 {
|
||||
return 0
|
||||
}
|
||||
yabs = y
|
||||
if yabs < 0 {
|
||||
yabs = -yabs
|
||||
}
|
||||
if x >= 0 {
|
||||
angle = pi4 - pi4*(x-yabs)/(x+yabs)
|
||||
func ProcessAudio(out []float32) {
|
||||
if audioFifo.Len() > 0 {
|
||||
var z = audioFifo.Next().([]float32)
|
||||
copy(out, z)
|
||||
} else {
|
||||
angle = pi34 - pi4*(x+yabs)/(yabs-x)
|
||||
}
|
||||
if y < 0 {
|
||||
return -angle
|
||||
}
|
||||
return angle
|
||||
}
|
||||
|
||||
func polarDiscFast(ar, aj, br, bj int) int {
|
||||
var cr, cj int
|
||||
cr = ar*br - aj*-bj
|
||||
cj = aj*br + ar*-bj
|
||||
return fastAtan2(cj, cr)
|
||||
}
|
||||
|
||||
var d = demodState{
|
||||
rateIn: 170000,
|
||||
rateOut: 170000,
|
||||
rateOut2: 32000,
|
||||
customAtan: 1,
|
||||
deemph: true,
|
||||
squelchLevel: 0,
|
||||
}
|
||||
|
||||
func fmDemod(fm *demodState) {
|
||||
var i, pcm int
|
||||
lp := fm.lowpassed
|
||||
lpLen := len(fm.lowpassed)
|
||||
pr := fm.preR
|
||||
pj := fm.preJ
|
||||
for i = 2; i < (lpLen - 1); i += 2 {
|
||||
switch fm.customAtan {
|
||||
case 0:
|
||||
pcm = polarDiscriminant(int(lp[i]), int(lp[i+1]), int(pr), int(pj))
|
||||
case 1:
|
||||
pcm = polarDiscFast(int(lp[i]), int(lp[i+1]), int(pr), int(pj))
|
||||
for i := range out {
|
||||
out[i] = 0
|
||||
}
|
||||
pr = lp[i]
|
||||
pj = lp[i+1]
|
||||
|
||||
fm.lowpassed[i/2] = int16(pcm)
|
||||
}
|
||||
fm.preR = pr
|
||||
fm.preJ = pj
|
||||
fm.lowpassed = fm.lowpassed[:lpLen/2]
|
||||
}
|
||||
|
||||
func lowPass(d *demodState) {
|
||||
var i, i2 int
|
||||
for i < len(d.lowpassed) {
|
||||
d.nowR += d.lowpassed[i]
|
||||
d.nowJ += d.lowpassed[i+1]
|
||||
i += 2
|
||||
d.prevIndex++
|
||||
if d.prevIndex < d.downsample {
|
||||
continue
|
||||
}
|
||||
d.lowpassed[i2] = d.nowR // * d.output_scale;
|
||||
d.lowpassed[i2+1] = d.nowJ // * d.output_scale;
|
||||
d.prevIndex = 0
|
||||
d.nowR = 0
|
||||
d.nowJ = 0
|
||||
i2 += 2
|
||||
func GetFinalData(input []int16) []complex64 {
|
||||
var complexFloat = make([]complex64, len(input)/2)
|
||||
|
||||
for i := 0; i < len(complexFloat); i++ {
|
||||
complexFloat[i] = complex(float32(input[2*i])/2048, float32(input[2*i+1])/2048)
|
||||
}
|
||||
d.lowpassed = d.lowpassed[:i2]
|
||||
|
||||
return complexFloat
|
||||
}
|
||||
|
||||
func TestBladeRF(t *testing.T) {
|
||||
|
@ -160,16 +62,9 @@ func TestBladeRF(t *testing.T) {
|
|||
Close(rf)
|
||||
}
|
||||
|
||||
type echo struct {
|
||||
*portaudio.Stream
|
||||
buffer []float32
|
||||
i int
|
||||
}
|
||||
|
||||
func TestStream(t *testing.T) {
|
||||
var err error
|
||||
|
||||
|
||||
sig := make(chan os.Signal, 1)
|
||||
signal.Notify(sig, os.Interrupt, os.Kill)
|
||||
|
||||
|
@ -185,26 +80,30 @@ func TestStream(t *testing.T) {
|
|||
rf := OpenWithDevInfo(devices[0])
|
||||
defer Close(rf)
|
||||
|
||||
err = SetFrequency(&rf, IORX, 90800000)
|
||||
err = SetFrequency(&rf, IORX, 96600000)
|
||||
if err != nil {
|
||||
log2.Fatal(err)
|
||||
}
|
||||
|
||||
min, max, step, errRange := GetSampleRateRange(&rf, IORX)
|
||||
if errRange != nil {
|
||||
min, max, step, err := GetSampleRateRange(&rf, IORX)
|
||||
if err != nil {
|
||||
log2.Fatal(err)
|
||||
}
|
||||
fmt.Printf("Min: %d, Max: %d, Step: %d\n", min, max, step)
|
||||
err = SetSampleRate(&rf, IORX, 4e6)
|
||||
if err != nil {
|
||||
log2.Fatal(err)
|
||||
}
|
||||
err = SyncConfig(&rf, RX_X1, SC16_Q11, 16, audioBufferSize, 8, 32)
|
||||
if err != nil {
|
||||
log2.Fatal(err)
|
||||
}
|
||||
|
||||
actual, err := SetBandwidth(&rf, IORX, 240000)
|
||||
if err != nil {
|
||||
log2.Fatal(err)
|
||||
} else {
|
||||
fmt.Printf("Min: %d, Max: %d, Step: %d\n", min, max, step)
|
||||
}
|
||||
|
||||
err = SetSampleRate(&rf, IORX, max)
|
||||
if err != nil {
|
||||
log2.Fatal(err)
|
||||
}
|
||||
|
||||
err = SyncConfig(&rf, RX_X1, SC16_Q11, 32, 8192, 8, 3500)
|
||||
if err != nil {
|
||||
log2.Fatal(err)
|
||||
println(actual)
|
||||
}
|
||||
|
||||
err = EnableModule(&rf, RX)
|
||||
|
@ -212,51 +111,38 @@ func TestStream(t *testing.T) {
|
|||
log2.Fatal(err)
|
||||
}
|
||||
|
||||
err = SetGain(&rf, IORX, 9)
|
||||
err = SetGainMode(&rf, IORX, Hybrid_AGC)
|
||||
if err != nil {
|
||||
log2.Fatal(err)
|
||||
}
|
||||
|
||||
p := make([]int16, 10000)
|
||||
demodulator = demodcore.MakeWBFMDemodulator(uint32(2e6), 80e3, 48000)
|
||||
|
||||
results := SyncRX(&rf)
|
||||
//var complexFloat = make([]float32, 10000)
|
||||
portaudio.Initialize()
|
||||
h, _ := portaudio.DefaultHostApi()
|
||||
|
||||
//for i := 0; i < 10000 ; i++ {
|
||||
// complexFloat[i] = float32(results[2*i])/float32(2048) + float32(results[2*i+1])/float32(2048.0)
|
||||
//}
|
||||
p := portaudio.LowLatencyParameters(nil, h.DefaultOutputDevice)
|
||||
p.Input.Channels = 0
|
||||
p.Output.Channels = 1
|
||||
p.SampleRate = 48000
|
||||
p.FramesPerBuffer = audioBufferSize
|
||||
|
||||
d.lowpassed = results
|
||||
fmDemod(&d)
|
||||
lowPass(&d)
|
||||
|
||||
err = DisableModule(&rf, RX)
|
||||
if err != nil {
|
||||
log2.Fatal(err)
|
||||
}
|
||||
|
||||
out := make([]int16, 8192)
|
||||
|
||||
e := &echo{buffer: make([]float32, 10000)}
|
||||
|
||||
e.Stream, err = portaudio.OpenDefaultStream(0, 1, 10000, len(d.lowpassed), &out)
|
||||
defer stream.Close()
|
||||
|
||||
stream.Start()
|
||||
|
||||
defer stream.Close()
|
||||
defer stream.Stop()
|
||||
audioStream, _ = portaudio.OpenStream(p, ProcessAudio)
|
||||
_ = audioStream.Start()
|
||||
|
||||
for {
|
||||
out = d.lowpassed
|
||||
stream.Write()
|
||||
select {
|
||||
case <-sig:
|
||||
return
|
||||
default:
|
||||
out := demodulator.Work(GetFinalData(SyncRX(&rf, audioBufferSize)))
|
||||
|
||||
if out != nil {
|
||||
var o = out.(demodcore.DemodData)
|
||||
var nBf = make([]float32, len(o.Data))
|
||||
copy(nBf, o.Data)
|
||||
var buffs = len(nBf) / audioBufferSize
|
||||
for i := 0; i < buffs; i++ {
|
||||
audioFifo.Add(nBf[audioBufferSize*i : audioBufferSize*(i+1)])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func TestAsyncStream(t *testing.T) {
|
||||
|
@ -272,7 +158,7 @@ func TestAsyncStream(t *testing.T) {
|
|||
rf := OpenWithDevInfo(devices[0])
|
||||
defer Close(rf)
|
||||
|
||||
SetSampleRate(&rf, IORX, 1000000)
|
||||
SetSampleRate(&rf, IORX, 4000000)
|
||||
EnableModule(&rf, RX)
|
||||
|
||||
rxStream := InitStream(&rf, SC16_Q11, 32, 32768, 16)
|
||||
|
|
8
go.mod
8
go.mod
|
@ -2,4 +2,10 @@ module bladerf
|
|||
|
||||
go 1.13
|
||||
|
||||
require github.com/gordonklaus/portaudio v0.0.0-20180817120803-00e7307ccd93
|
||||
require (
|
||||
github.com/gordonklaus/portaudio v0.0.0-20180817120803-00e7307ccd93
|
||||
github.com/mattetti/audio v0.0.0-20190404201502-c6aebeb78429
|
||||
github.com/oov/audio v0.0.0-20171004131523-88a2be6dbe38
|
||||
github.com/racerxdl/go.fifo v0.0.0-20180604061744-c6aa83afe374
|
||||
github.com/racerxdl/segdsp v0.0.0-20190413213320-dfaea7c39d3a
|
||||
)
|
||||
|
|
54
go.sum
54
go.sum
|
@ -1,2 +1,56 @@
|
|||
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
|
||||
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
|
||||
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/go-gl/gl v0.0.0-20180407155706-68e253793080/go.mod h1:482civXOzJJCPzJ4ZOX/pwvXBWSnzD4OKMdH4ClKGbk=
|
||||
github.com/go-gl/glfw v0.0.0-20180426074136-46a8d530c326/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
|
||||
github.com/gofrs/uuid v3.2.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM=
|
||||
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k=
|
||||
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
|
||||
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
|
||||
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/gordonklaus/portaudio v0.0.0-20180817120803-00e7307ccd93 h1:TSG+DyZBnazM22ZHyHLeUkzM34ClkJRjIWHTq4btvek=
|
||||
github.com/gordonklaus/portaudio v0.0.0-20180817120803-00e7307ccd93/go.mod h1:HfYnZi/ARQKG0dwH5HNDmPCHdLiFiBf+SI7DbhW7et4=
|
||||
github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
|
||||
github.com/jung-kurt/gofpdf v1.0.0/go.mod h1:7Id9E/uU8ce6rXgefFLlgrJj/GYY22cpxn+r32jIOes=
|
||||
github.com/llgcode/draw2d v0.0.0-20180825133448-f52c8a71aff0/go.mod h1:mVa0dA29Db2S4LVqDYLlsePDzRJLDfdhVZiI15uY0FA=
|
||||
github.com/llgcode/ps v0.0.0-20150911083025-f1443b32eedb/go.mod h1:1l8ky+Ew27CMX29uG+a2hNOKpeNYEQjjtiALiBlFQbY=
|
||||
github.com/logrusorgru/aurora v0.0.0-20181002194514-a7b3b318ed4e/go.mod h1:7rIyQOR62GCctdiQpZ/zOJlFyk6y+94wXzv6RNZgaR4=
|
||||
github.com/mattetti/audio v0.0.0-20190404201502-c6aebeb78429 h1:5YWANgpchDSYJ0R6i3ODpZ4KN/1Jm9MZcFDtAtegjNM=
|
||||
github.com/mattetti/audio v0.0.0-20190404201502-c6aebeb78429/go.mod h1:LlQmBGkOuV/SKzEDXBPKauvN2UqCgzXO2XjecTGj40s=
|
||||
github.com/mattn/go-pointer v0.0.0-20180825124634-49522c3f3791/go.mod h1:2zXcozF6qYGgmsG+SeTZz3oAbFLdD3OWqnUbNvJZAlc=
|
||||
github.com/myriadrf/limedrv v0.0.0-20190225221912-8583a26e3fce/go.mod h1:/SXVBJBHAVLlvLU1B1n0a0QPcZBtqF1VpH5POPZzuBw=
|
||||
github.com/oov/audio v0.0.0-20171004131523-88a2be6dbe38 h1:4Upfs5rLQdx7KwBct3bmPYAhWsDDJdx660gYb7Lv9TQ=
|
||||
github.com/oov/audio v0.0.0-20171004131523-88a2be6dbe38/go.mod h1:Xj06yMta9R1RSKiHmxL0Bo2TB8wiKVnMgA0KVopHHkk=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/quan-to/slog v0.0.0-20190317205605-56a2b4159924/go.mod h1:xc9X6JvWjqAAIox9u4uuolisjwl/GbfkktH6f+nOgqU=
|
||||
github.com/racerxdl/fastconvert v0.0.0-20190129064530-871b6f6cd82a/go.mod h1:V4kP6uu5nqjDVGhlYMtT/7JG7WJjXnipMGcQ8PFeUqU=
|
||||
github.com/racerxdl/go.fifo v0.0.0-20180604061744-c6aa83afe374 h1:P2TDDsGEWzzfhAnthdQc+Vwmv/+xEKHwoNFF3Swl6X0=
|
||||
github.com/racerxdl/go.fifo v0.0.0-20180604061744-c6aa83afe374/go.mod h1:CvYWG6Py4TRzGCUVX2n8+CjE6mrME/+kHkkGmbDA5zw=
|
||||
github.com/racerxdl/radioserver v0.0.0-20190316070955-f8953f368ce1/go.mod h1:cSQupBUlkn/QhajTmf6QMErp3PbTVT5Xdd5DSiE0hAI=
|
||||
github.com/racerxdl/radioserver v0.0.0-20190324175745-bd3bd7179419/go.mod h1:N4ejKokz1jnGfAd3KNgO8E6YMCMP4ZgaHXBEdHBQrP8=
|
||||
github.com/racerxdl/segdsp v0.0.0-20190321214158-1cd3e325e91a/go.mod h1:nQDTqJjqr+YsSQw+CVY58Xag4KVqfoi6TgkSXMHlUO4=
|
||||
github.com/racerxdl/segdsp v0.0.0-20190413213320-dfaea7c39d3a h1:2QJXxaBOGMsjoZ++ecsek0SE/V4bbraCITBNVji4+4M=
|
||||
github.com/racerxdl/segdsp v0.0.0-20190413213320-dfaea7c39d3a/go.mod h1:NXNN9LqX1oeK6+o+xm+Dz8ANz+i1uILw4HsL0sq5tzE=
|
||||
github.com/racerxdl/spy2go v0.0.0-20190103011754-14102c047be5/go.mod h1:ioS4oIwJsgrSeKKPATMpsbJQdi4p2Xsbg3V5j2nCOzM=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/image v0.0.0-20180708004352-c73c2afc3b81/go.mod h1:ux5Hcp/YLpHSI86hEcLt0YII63i6oz57MZXIpbrjZUs=
|
||||
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190322120337-addf6b3196f6/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
|
||||
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
|
||||
google.golang.org/grpc v1.19.1/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
|
||||
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
|
||||
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
|
|
Loading…
Reference in New Issue