Browse Source

le leleyeleyleyle witcher

pull/1/head
Eray Arslan 2 years ago
parent
commit
163016f55f
  1. 34
      bladerf.go
  2. 214
      bladerf_test.go
  3. 8
      go.mod
  4. 54
      go.sum

34
bladerf.go

@ -324,14 +324,31 @@ func GetSampleRateRange(bladeRF *BladeRF, module IOModule) (int, int, int, error @@ -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 { @@ -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))

214
bladerf_test.go

@ -4,138 +4,40 @@ import ( @@ -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
for i := range out {
out[i] = 0
}
}
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))
}
pr = lp[i]
pj = lp[i+1]
func GetFinalData(input []int16) []complex64 {
var complexFloat = make([]complex64, len(input)/2)
fm.lowpassed[i/2] = int16(pcm)
for i := 0; i < len(complexFloat); i++ {
complexFloat[i] = complex(float32(input[2*i])/2048, float32(input[2*i+1])/2048)
}
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
}
d.lowpassed = d.lowpassed[:i2]
return complexFloat
}
func TestBladeRF(t *testing.T) {
@ -160,16 +62,9 @@ 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,78 +80,69 @@ func TestStream(t *testing.T) { @@ -185,78 +80,69 @@ 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)
} else {
fmt.Printf("Min: %d, Max: %d, Step: %d\n", min, max, step)
}
err = SetSampleRate(&rf, IORX, max)
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, 32, 8192, 8, 3500)
err = SyncConfig(&rf, RX_X1, SC16_Q11, 16, audioBufferSize, 8, 32)
if err != nil {
log2.Fatal(err)
}
err = EnableModule(&rf, RX)
actual, err := SetBandwidth(&rf, IORX, 240000)
if err != nil {
log2.Fatal(err)
} else {
println(actual)
}
err = SetGain(&rf, IORX, 9)
err = EnableModule(&rf, RX)
if err != nil {
log2.Fatal(err)
}
p := make([]int16, 10000)
results := SyncRX(&rf)
//var complexFloat = make([]float32, 10000)
//for i := 0; i < 10000 ; i++ {
// complexFloat[i] = float32(results[2*i])/float32(2048) + float32(results[2*i+1])/float32(2048.0)
//}
d.lowpassed = results
fmDemod(&d)
lowPass(&d)
err = DisableModule(&rf, RX)
err = SetGainMode(&rf, IORX, Hybrid_AGC)
if err != nil {
log2.Fatal(err)
}
out := make([]int16, 8192)
e := &echo{buffer: make([]float32, 10000)}
demodulator = demodcore.MakeWBFMDemodulator(uint32(2e6), 80e3, 48000)
e.Stream, err = portaudio.OpenDefaultStream(0, 1, 10000, len(d.lowpassed), &out)
defer stream.Close()
portaudio.Initialize()
h, _ := portaudio.DefaultHostApi()
stream.Start()
p := portaudio.LowLatencyParameters(nil, h.DefaultOutputDevice)
p.Input.Channels = 0
p.Output.Channels = 1
p.SampleRate = 48000
p.FramesPerBuffer = audioBufferSize
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) { @@ -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

@ -2,4 +2,10 @@ module bladerf @@ -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

@ -1,2 +1,56 @@ @@ -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…
Cancel
Save