442 lines
11 KiB
Go
442 lines
11 KiB
Go
package bladerf
|
|
|
|
// #cgo darwin CFLAGS: -I/usr/local/include
|
|
// #cgo darwin LDFLAGS: -L/usr/local/lib
|
|
// #cgo LDFLAGS: -lbladeRF
|
|
// #include <libbladeRF.h>
|
|
//
|
|
// extern void* cbGo(struct bladerf *dev, struct bladerf_stream *stream, struct bladerf_metadata *md, void* samples, size_t num_samples, void* user_data);
|
|
import "C"
|
|
import (
|
|
error2 "bladerf/error"
|
|
"fmt"
|
|
"unsafe"
|
|
)
|
|
|
|
//export cbGo
|
|
func cbGo(dev *C.struct_bladerf,
|
|
stream *C.struct_bladerf_stream,
|
|
metadata *C.struct_bladerf_metadata,
|
|
samples unsafe.Pointer,
|
|
numSamples C.size_t,
|
|
userData unsafe.Pointer) unsafe.Pointer {
|
|
|
|
data := (*[0]uint16)(samples)
|
|
|
|
if len(*data) > 0 {
|
|
println(data)
|
|
} else {
|
|
println(data)
|
|
}
|
|
|
|
var rv unsafe.Pointer
|
|
return rv
|
|
}
|
|
|
|
type GainMode int
|
|
type Backend int
|
|
type Direction int
|
|
type ChannelLayout int
|
|
type Correction int
|
|
type Format int
|
|
type Loopback int
|
|
type RXMux int
|
|
type ClockSelect int
|
|
type PowerSource int
|
|
type PMICRegister int
|
|
type IOModule int
|
|
|
|
const (
|
|
IOTX IOModule = C.BLADERF_MODULE_TX
|
|
IORX IOModule = C.BLADERF_MODULE_RX
|
|
)
|
|
|
|
const (
|
|
Default GainMode = C.BLADERF_GAIN_DEFAULT
|
|
Manual GainMode = C.BLADERF_GAIN_MGC
|
|
FastAttack_AGC GainMode = C.BLADERF_GAIN_FASTATTACK_AGC
|
|
SlowAttack_AGC GainMode = C.BLADERF_GAIN_SLOWATTACK_AGC
|
|
Hybrid_AGC GainMode = C.BLADERF_GAIN_HYBRID_AGC
|
|
)
|
|
|
|
const (
|
|
Any Backend = C.BLADERF_BACKEND_ANY
|
|
Linux Backend = C.BLADERF_BACKEND_LINUX
|
|
LibUSB Backend = C.BLADERF_BACKEND_LIBUSB
|
|
Cypress Backend = C.BLADERF_BACKEND_CYPRESS
|
|
Dummy Backend = C.BLADERF_BACKEND_DUMMY
|
|
)
|
|
|
|
const (
|
|
TX Direction = C.BLADERF_TX
|
|
RX Direction = C.BLADERF_RX
|
|
)
|
|
|
|
const (
|
|
RX_X1 ChannelLayout = C.BLADERF_RX_X1
|
|
TX_X1 ChannelLayout = C.BLADERF_TX_X1
|
|
RX_X2 ChannelLayout = C.BLADERF_RX_X2
|
|
TX_X2 ChannelLayout = C.BLADERF_TX_X2
|
|
)
|
|
|
|
const (
|
|
DCOFF_I Correction = C.BLADERF_CORR_DCOFF_I
|
|
DCOFF_Q Correction = C.BLADERF_CORR_DCOFF_Q
|
|
PHASE Correction = C.BLADERF_CORR_PHASE
|
|
GAIN Correction = C.BLADERF_CORR_GAIN
|
|
)
|
|
|
|
const (
|
|
SC16_Q11 Format = C.BLADERF_FORMAT_SC16_Q11
|
|
SC16_Q11_META Format = C.BLADERF_FORMAT_SC16_Q11_META
|
|
)
|
|
|
|
const (
|
|
Disabled Loopback = C.BLADERF_LB_NONE
|
|
Firmware Loopback = C.BLADERF_LB_FIRMWARE
|
|
BB_TXLPF_RXVGA2 Loopback = C.BLADERF_LB_BB_TXLPF_RXVGA2
|
|
BB_TXVGA1_RXVGA2 Loopback = C.BLADERF_LB_BB_TXVGA1_RXVGA2
|
|
BB_TXLPF_RXLPF Loopback = C.BLADERF_LB_BB_TXLPF_RXLPF
|
|
BB_TXVGA1_RXLPF Loopback = C.BLADERF_LB_BB_TXVGA1_RXLPF
|
|
RF_LNA1 Loopback = C.BLADERF_LB_RF_LNA1
|
|
RF_LNA2 Loopback = C.BLADERF_LB_RF_LNA2
|
|
RF_LNA3 Loopback = C.BLADERF_LB_RF_LNA3
|
|
RFIC_BIST Loopback = C.BLADERF_LB_RFIC_BIST
|
|
)
|
|
|
|
const (
|
|
Invalid RXMux = C.BLADERF_RX_MUX_INVALID
|
|
Baseband RXMux = C.BLADERF_RX_MUX_BASEBAND
|
|
Counter_12bit RXMux = C.BLADERF_RX_MUX_12BIT_COUNTER
|
|
Counter_32bit RXMux = C.BLADERF_RX_MUX_32BIT_COUNTER
|
|
Digital_Loopback RXMux = C.BLADERF_RX_MUX_DIGITAL_LOOPBACK
|
|
)
|
|
const (
|
|
ClockSelectUnknown ClockSelect = -99
|
|
ClockSelectVCTCXO ClockSelect = C.CLOCK_SELECT_ONBOARD
|
|
ClockSelectExternal ClockSelect = C.CLOCK_SELECT_EXTERNAL
|
|
)
|
|
|
|
const (
|
|
PowerSourceUnknown PowerSource = C.BLADERF_UNKNOWN
|
|
PowerSourceDC_Barrel PowerSource = C.BLADERF_PS_DC
|
|
PowerSourceUSB_VBUS PowerSource = C.BLADERF_PS_USB_VBUS
|
|
)
|
|
|
|
const (
|
|
Configuration PMICRegister = C.BLADERF_PMIC_CONFIGURATION
|
|
Voltage_shunt PMICRegister = C.BLADERF_PMIC_VOLTAGE_SHUNT
|
|
Voltage_bus PMICRegister = C.BLADERF_PMIC_VOLTAGE_BUS
|
|
Power PMICRegister = C.BLADERF_PMIC_POWER
|
|
Current PMICRegister = C.BLADERF_PMIC_CURRENT
|
|
Calibration PMICRegister = C.BLADERF_PMIC_CALIBRATION
|
|
)
|
|
|
|
const (
|
|
RX_V int = 0x0
|
|
TX_V int = 0x1
|
|
)
|
|
|
|
const (
|
|
BLADERF_VCTCXO_FREQUENCY = 38.4e6
|
|
BLADERF_REFIN_DEFAULT = 10.0e6
|
|
BLADERF_SERIAL_LENGTH = 33
|
|
)
|
|
|
|
func checkError(e error) {
|
|
if e != nil {
|
|
fmt.Printf(e.Error())
|
|
}
|
|
}
|
|
|
|
type Version struct {
|
|
version *C.struct_bladerf_version
|
|
major int
|
|
minor int
|
|
patch int
|
|
describe string
|
|
}
|
|
|
|
type DevInfo struct {
|
|
devInfo *C.struct_bladerf_devinfo
|
|
}
|
|
|
|
type Range struct {
|
|
bfRange *C.struct_bladerf_range
|
|
}
|
|
|
|
type BladeRF struct {
|
|
bladeRF *C.struct_bladerf
|
|
}
|
|
|
|
type Module struct {
|
|
module *C.struct_bladerf_module
|
|
}
|
|
|
|
type Stream struct {
|
|
stream *C.struct_bladerf_stream
|
|
}
|
|
|
|
func GetVersion() Version {
|
|
var version C.struct_bladerf_version
|
|
C.bladerf_version(&version)
|
|
return Version{version: &version, major: int(version.major), minor: int(version.minor), patch: int(version.patch), describe: C.GoString(version.describe)}
|
|
}
|
|
|
|
func PrintVersion(version Version) {
|
|
fmt.Printf("v%d.%d.%d (\"%s\")", version.major, version.minor, version.patch, version.describe)
|
|
}
|
|
|
|
func GetError(e C.int) error {
|
|
if e == 0 {
|
|
return nil
|
|
}
|
|
|
|
return error2.Error(e)
|
|
}
|
|
|
|
func LoadFpga(bladeRF BladeRF, imagePath string) {
|
|
path := C.CString(imagePath)
|
|
defer C.free(unsafe.Pointer(path))
|
|
|
|
C.bladerf_load_fpga(bladeRF.bladeRF, path)
|
|
C.bladerf_close(bladeRF.bladeRF)
|
|
}
|
|
|
|
func FreeDeviceList(devInfo DevInfo) {
|
|
C.bladerf_free_device_list(devInfo.devInfo)
|
|
}
|
|
|
|
func GetDeviceList() []DevInfo {
|
|
var devInfo *C.struct_bladerf_devinfo
|
|
var devices []DevInfo
|
|
|
|
count := int(C.bladerf_get_device_list(&devInfo))
|
|
|
|
if count < 1 {
|
|
return devices
|
|
}
|
|
|
|
first := DevInfo{devInfo: devInfo}
|
|
|
|
defer FreeDeviceList(first)
|
|
|
|
devices = append(devices, first)
|
|
|
|
for i := 0; i < count-1; i++ {
|
|
size := unsafe.Sizeof(*devInfo)
|
|
devInfo = (*C.struct_bladerf_devinfo)(unsafe.Pointer(uintptr(unsafe.Pointer(devInfo)) + size))
|
|
devices = append(devices, DevInfo{devInfo: devInfo})
|
|
}
|
|
|
|
return devices
|
|
}
|
|
|
|
func GetBootloaderList() []DevInfo {
|
|
var devInfo *C.struct_bladerf_devinfo
|
|
var devices []DevInfo
|
|
|
|
count := int(C.bladerf_get_bootloader_list(&devInfo))
|
|
|
|
if count < 1 {
|
|
return devices
|
|
}
|
|
|
|
first := DevInfo{devInfo: devInfo}
|
|
|
|
defer FreeDeviceList(first)
|
|
|
|
devices = append(devices, first)
|
|
|
|
for i := 0; i < count-1; i++ {
|
|
size := unsafe.Sizeof(*devInfo)
|
|
devInfo = (*C.struct_bladerf_devinfo)(unsafe.Pointer(uintptr(unsafe.Pointer(devInfo)) + size))
|
|
devices = append(devices, DevInfo{devInfo: devInfo})
|
|
}
|
|
|
|
return devices
|
|
}
|
|
|
|
func CHANNEL_RX(ch int) int {
|
|
return (ch << 1) | RX_V
|
|
}
|
|
|
|
func CHANNEL_TX(ch int) int {
|
|
return (ch << 1) | TX_V
|
|
}
|
|
|
|
func GetDevInfo() DevInfo {
|
|
var devInfo C.struct_bladerf_devinfo
|
|
C.bladerf_init_devinfo(&devInfo)
|
|
return DevInfo{devInfo: &devInfo}
|
|
}
|
|
|
|
func OpenWithDevInfo(devInfo DevInfo) BladeRF {
|
|
var bladeRF *C.struct_bladerf
|
|
C.bladerf_open_with_devinfo(&bladeRF, devInfo.devInfo)
|
|
return BladeRF{bladeRF: bladeRF}
|
|
}
|
|
|
|
func OpenWithDeviceIdentifier(identify string) BladeRF {
|
|
var bladeRF *C.struct_bladerf
|
|
C.bladerf_open(&bladeRF, C.CString(identify))
|
|
return BladeRF{bladeRF: bladeRF}
|
|
}
|
|
|
|
func Open() BladeRF {
|
|
var bladeRF *C.struct_bladerf
|
|
C.bladerf_open(&bladeRF, nil)
|
|
return BladeRF{bladeRF: bladeRF}
|
|
}
|
|
|
|
func Close(bladeRF BladeRF) {
|
|
C.bladerf_close(bladeRF.bladeRF)
|
|
}
|
|
|
|
func SetLoopback(bladeRF *BladeRF, loopback Loopback) {
|
|
C.bladerf_set_loopback((*bladeRF).bladeRF, C.bladerf_loopback(loopback))
|
|
}
|
|
|
|
func SetFrequency(bladeRF *BladeRF, module IOModule, frequency int) error {
|
|
return GetError(C.bladerf_set_frequency((*bladeRF).bladeRF, C.bladerf_module(module), C.ulonglong(frequency)))
|
|
}
|
|
|
|
func SetSampleRate(bladeRF *BladeRF, module IOModule, sampleRate int) error {
|
|
var actual C.uint
|
|
err := GetError(C.bladerf_set_sample_rate((*bladeRF).bladeRF, C.bladerf_module(module), C.uint(sampleRate), &actual))
|
|
|
|
if err == nil {
|
|
println(uint(actual))
|
|
}
|
|
|
|
return err
|
|
}
|
|
|
|
func GetSampleRateRange(bladeRF *BladeRF, module IOModule) (int, int, int, error) {
|
|
var bfRange *C.struct_bladerf_range
|
|
|
|
err := GetError(C.bladerf_get_sample_rate_range((*bladeRF).bladeRF, C.bladerf_module(module), &bfRange))
|
|
|
|
if err != nil {
|
|
return 0, 0, 0, err
|
|
}
|
|
|
|
return int(bfRange.min), int(bfRange.max), int(bfRange.step), 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))
|
|
}
|
|
|
|
func DisableModule(bladeRF *BladeRF, direction Direction) error {
|
|
return GetError(C.bladerf_enable_module((*bladeRF).bladeRF, C.bladerf_module(direction), false))
|
|
}
|
|
|
|
var call = 0
|
|
|
|
func do_work() bool {
|
|
call = call + 1
|
|
return call >= 5000
|
|
}
|
|
|
|
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 * 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, C.uint(bufferSize), &metadata, 32))
|
|
if err == nil {
|
|
done = do_work()
|
|
if done {
|
|
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))
|
|
}
|
|
}
|
|
} else {
|
|
fmt.Printf("Failed to RX samples: %s", err)
|
|
}
|
|
}
|
|
|
|
return results
|
|
}
|
|
|
|
func InitStream(bladeRF *BladeRF, format Format, numBuffers int, samplesPerBuffer int, numTransfers int) *Stream {
|
|
var buffers *unsafe.Pointer
|
|
var data unsafe.Pointer
|
|
var rxStream *C.struct_bladerf_stream
|
|
|
|
stream := Stream{stream: rxStream}
|
|
|
|
C.bladerf_init_stream(
|
|
&((stream).stream),
|
|
(*bladeRF).bladeRF,
|
|
(*[0]byte)((C.cbGo)),
|
|
&buffers, C.ulong(numBuffers),
|
|
C.bladerf_format(format),
|
|
C.ulong(samplesPerBuffer),
|
|
C.ulong(numTransfers),
|
|
data,
|
|
)
|
|
|
|
return &stream
|
|
}
|
|
|
|
func DeInitStream(stream *Stream) {
|
|
C.bladerf_deinit_stream(stream.stream)
|
|
}
|
|
|
|
func GetStreamTimeout(bladeRF *BladeRF, direction Direction) int {
|
|
var timeout C.uint
|
|
err := GetError(C.bladerf_get_stream_timeout((*bladeRF).bladeRF, C.bladerf_direction(direction), &timeout))
|
|
fmt.Println(err)
|
|
return int(timeout)
|
|
}
|
|
|
|
func SetStreamTimeout(bladeRF *BladeRF, direction Direction, timeout int) {
|
|
err := GetError(C.bladerf_set_stream_timeout((*bladeRF).bladeRF, C.bladerf_direction(direction), C.uint(timeout)))
|
|
fmt.Println(err)
|
|
}
|
|
|
|
func SyncConfig(bladeRF *BladeRF, layout ChannelLayout, format Format, numBuffers int, bufferSize int, numTransfers int, timeout int) error {
|
|
err := GetError(C.bladerf_sync_config((*bladeRF).bladeRF, C.bladerf_channel_layout(layout), C.bladerf_format(format), C.uint(numBuffers), C.uint(bufferSize), C.uint(numTransfers), C.uint(timeout)))
|
|
return err
|
|
}
|
|
|
|
func StartStream(stream *Stream, layout ChannelLayout) {
|
|
err := GetError(C.bladerf_stream(stream.stream, C.bladerf_channel_layout(layout)))
|
|
fmt.Println(err)
|
|
}
|