Refactoring

master
Friedl Ulrich 10 years ago
parent 654112c45c
commit 4a9335b6d0

@ -8,6 +8,11 @@ import (
"github.com/fulr/spidev" "github.com/fulr/spidev"
) )
const (
spiPath = "/dev/spidev0.0"
irqPin = gpio.GPIO25
)
// Device RFM69 Device // Device RFM69 Device
type Device struct { type Device struct {
SpiDevice *spidev.SPIDevice SpiDevice *spidev.SPIDevice
@ -36,21 +41,41 @@ type Data struct {
} }
// NewDevice creates a new device // NewDevice creates a new device
func NewDevice(spi *spidev.SPIDevice, gpio gpio.Pin, nodeID, networkID byte, isRfm69HW bool) (*Device, error) { func NewDevice(nodeID, networkID byte, isRfm69HW bool) (*Device, error) {
pin, err := gpio.OpenPin(irqPin, gpio.ModeInput)
if err != nil {
return nil, err
}
spi, err := spidev.NewSPIDevice(spiPath)
if err != nil {
return nil, err
}
ret := &Device{ ret := &Device{
SpiDevice: spi, SpiDevice: spi,
gpio: gpio, gpio: pin,
network: networkID, network: networkID,
address: nodeID, address: nodeID,
isRFM69HW: isRfm69HW, isRFM69HW: isRfm69HW,
powerLevel: 31, powerLevel: 31,
} }
err := ret.setup() err = ret.setup()
return ret, err return ret, err
} }
// Close cleans up
func (r *Device) Close() error {
err := r.gpio.Close()
if err != nil {
return err
}
r.SpiDevice.Close()
return err
}
func (r *Device) writeReg(addr, data byte) error { func (r *Device) writeReg(addr, data byte) error {
tx := make([]byte, 2) tx := make([]byte, 2)
tx[0] = addr | 0x80 tx[0] = addr | 0x80
@ -82,11 +107,9 @@ func (r *Device) setup() error {
/* 0x04 */ {REG_BITRATELSB, RF_BITRATELSB_55555}, /* 0x04 */ {REG_BITRATELSB, RF_BITRATELSB_55555},
/* 0x05 */ {REG_FDEVMSB, RF_FDEVMSB_50000}, // default: 5KHz, (FDEV + BitRate / 2 <= 500KHz) /* 0x05 */ {REG_FDEVMSB, RF_FDEVMSB_50000}, // default: 5KHz, (FDEV + BitRate / 2 <= 500KHz)
/* 0x06 */ {REG_FDEVLSB, RF_FDEVLSB_50000}, /* 0x06 */ {REG_FDEVLSB, RF_FDEVLSB_50000},
/* 0x07 */ {REG_FRFMSB, RF_FRFMSB_868}, /* 0x07 */ {REG_FRFMSB, RF_FRFMSB_868},
/* 0x08 */ {REG_FRFMID, RF_FRFMID_868}, /* 0x08 */ {REG_FRFMID, RF_FRFMID_868},
/* 0x09 */ {REG_FRFLSB, RF_FRFLSB_868}, /* 0x09 */ {REG_FRFLSB, RF_FRFLSB_868},
// looks like PA1 and PA2 are not implemented on RFM69W, hence the max output power is 13dBm // looks like PA1 and PA2 are not implemented on RFM69W, hence the max output power is 13dBm
// +17dBm and +20dBm are possible on RFM69HW // +17dBm and +20dBm are possible on RFM69HW
// +13dBm formula: Pout = -18 + OutputPower (with PA0 or PA1**) // +13dBm formula: Pout = -18 + OutputPower (with PA0 or PA1**)
@ -94,7 +117,6 @@ func (r *Device) setup() error {
// +20dBm formula: Pout = -11 + OutputPower (with PA1 and PA2)** and high power PA settings (section 3.3.7 in datasheet) // +20dBm formula: Pout = -11 + OutputPower (with PA1 and PA2)** and high power PA settings (section 3.3.7 in datasheet)
///* 0x11 */ { REG_PALEVEL, RF_PALEVEL_PA0_ON | RF_PALEVEL_PA1_OFF | RF_PALEVEL_PA2_OFF | RF_PALEVEL_OUTPUTPOWER_11111}, ///* 0x11 */ { REG_PALEVEL, RF_PALEVEL_PA0_ON | RF_PALEVEL_PA1_OFF | RF_PALEVEL_PA2_OFF | RF_PALEVEL_OUTPUTPOWER_11111},
///* 0x13 */ { REG_OCP, RF_OCP_ON | RF_OCP_TRIM_95 }, // over current protection (default is 95mA) ///* 0x13 */ { REG_OCP, RF_OCP_ON | RF_OCP_TRIM_95 }, // over current protection (default is 95mA)
// RXBW defaults are { REG_RXBW, RF_RXBW_DCCFREQ_010 | RF_RXBW_MANT_24 | RF_RXBW_EXP_5} (RxBw: 10.4KHz) // RXBW defaults are { REG_RXBW, RF_RXBW_DCCFREQ_010 | RF_RXBW_MANT_24 | RF_RXBW_EXP_5} (RxBw: 10.4KHz)
/* 0x19 */ {REG_RXBW, RF_RXBW_DCCFREQ_010 | RF_RXBW_MANT_16 | RF_RXBW_EXP_2}, // (BitRate < 2 * RxBw) /* 0x19 */ {REG_RXBW, RF_RXBW_DCCFREQ_010 | RF_RXBW_MANT_16 | RF_RXBW_EXP_2}, // (BitRate < 2 * RxBw)
//for BR-19200: /* 0x19 */ { REG_RXBW, RF_RXBW_DCCFREQ_010 | RF_RXBW_MANT_24 | RF_RXBW_EXP_3 }, //for BR-19200: /* 0x19 */ { REG_RXBW, RF_RXBW_DCCFREQ_010 | RF_RXBW_MANT_24 | RF_RXBW_EXP_3 },
@ -114,48 +136,37 @@ func (r *Device) setup() error {
//for BR-19200: /* 0x3D */ { REG_PACKETCONFIG2, RF_PACKET2_RXRESTARTDELAY_NONE | RF_PACKET2_AUTORXRESTART_ON | RF_PACKET2_AES_OFF }, // RXRESTARTDELAY must match transmitter PA ramp-down time (bitrate dependent) //for BR-19200: /* 0x3D */ { REG_PACKETCONFIG2, RF_PACKET2_RXRESTARTDELAY_NONE | RF_PACKET2_AUTORXRESTART_ON | RF_PACKET2_AES_OFF }, // RXRESTARTDELAY must match transmitter PA ramp-down time (bitrate dependent)
/* 0x6F */ {REG_TESTDAGC, RF_DAGC_IMPROVED_LOWBETA0}, // run DAGC continuously in RX mode for Fading Margin Improvement, recommended default for AfcLowBetaOn=0 /* 0x6F */ {REG_TESTDAGC, RF_DAGC_IMPROVED_LOWBETA0}, // run DAGC continuously in RX mode for Fading Margin Improvement, recommended default for AfcLowBetaOn=0
} }
for data, err := r.readReg(REG_SYNCVALUE1); err == nil && data != 0xAA; data, err = r.readReg(REG_SYNCVALUE1) { for data, err := r.readReg(REG_SYNCVALUE1); err == nil && data != 0xAA; data, err = r.readReg(REG_SYNCVALUE1) {
err := r.writeReg(REG_SYNCVALUE1, 0xAA) err := r.writeReg(REG_SYNCVALUE1, 0xAA)
if err != nil { if err != nil {
return err return err
} }
} }
for data, err := r.readReg(REG_SYNCVALUE1); err == nil && data != 0x55; data, err = r.readReg(REG_SYNCVALUE1) { for data, err := r.readReg(REG_SYNCVALUE1); err == nil && data != 0x55; data, err = r.readReg(REG_SYNCVALUE1) {
r.writeReg(REG_SYNCVALUE1, 0x55) r.writeReg(REG_SYNCVALUE1, 0x55)
if err != nil { if err != nil {
return err return err
} }
} }
for _, c := range config { for _, c := range config {
err := r.writeReg(c[0], c[1]) err := r.writeReg(c[0], c[1])
if err != nil { if err != nil {
return err return err
} }
} }
// Encryption is persistent between resets and can trip you up during debugging.
// Disable it during initialization so we always start from a known state.
err := r.Encrypt([]byte{}) err := r.Encrypt([]byte{})
if err != nil { if err != nil {
return err return err
} }
// called regardless if it's a RFM69W or RFM69HW
err = r.setHighPower(r.isRFM69HW) err = r.setHighPower(r.isRFM69HW)
if err != nil { if err != nil {
return err return err
} }
err = r.SetMode(RF_OPMODE_STANDBY) err = r.SetMode(RF_OPMODE_STANDBY)
if err != nil { if err != nil {
return err return err
} }
err = r.waitForMode() err = r.waitForMode()
return err return err
} }
@ -192,53 +203,54 @@ func (r *Device) SetMode(newMode byte) error {
if newMode == r.mode { if newMode == r.mode {
return nil return nil
} }
err := r.readWriteReg(REG_OPMODE, 0xE3, newMode) err := r.readWriteReg(REG_OPMODE, 0xE3, newMode)
if err != nil { if err != nil {
return err return err
} }
if r.isRFM69HW && (newMode == RF_OPMODE_RECEIVER || newMode == RF_OPMODE_TRANSMITTER) { if r.isRFM69HW && (newMode == RF_OPMODE_RECEIVER || newMode == RF_OPMODE_TRANSMITTER) {
err := r.setHighPowerRegs(newMode == RF_OPMODE_TRANSMITTER) err := r.setHighPowerRegs(newMode == RF_OPMODE_TRANSMITTER)
if err != nil { if err != nil {
return err return err
} }
} }
// we are using packet mode, so this check is not really needed
// but waiting for mode ready is necessary when going from sleep because the FIFO may not be immediately available from previous mode
if r.mode == RF_OPMODE_SLEEP { if r.mode == RF_OPMODE_SLEEP {
err = r.waitForMode() err = r.waitForMode()
if err != nil { if err != nil {
return err return err
} }
} }
r.mode = newMode r.mode = newMode
return nil return nil
} }
// SetModeAndWait sets the mode and waits for it
func (r *Device) SetModeAndWait(newMode byte) error {
err := r.SetMode(RF_OPMODE_STANDBY)
if err != nil {
return err
}
err = r.waitForMode()
if err != nil {
return err
}
return nil
}
func (r *Device) setHighPower(turnOn bool) error { func (r *Device) setHighPower(turnOn bool) error {
r.isRFM69HW = turnOn r.isRFM69HW = turnOn
ocp := byte(RF_OCP_ON) ocp := byte(RF_OCP_ON)
if r.isRFM69HW { if r.isRFM69HW {
ocp = RF_OCP_OFF ocp = RF_OCP_OFF
} }
err := r.writeReg(REG_OCP, ocp) err := r.writeReg(REG_OCP, ocp)
if err != nil { if err != nil {
return err return err
} }
if r.isRFM69HW {
if r.isRFM69HW { // turning ON
// enable P1 & P2 amplifier stages
err = r.readWriteReg(REG_PALEVEL, 0x1F, RF_PALEVEL_PA1_ON|RF_PALEVEL_PA2_ON) err = r.readWriteReg(REG_PALEVEL, 0x1F, RF_PALEVEL_PA1_ON|RF_PALEVEL_PA2_ON)
} else { } else {
// enable P0 only
err = r.readWriteReg(REG_PALEVEL, 0, RF_PALEVEL_PA0_ON|RF_PALEVEL_PA1_OFF|RF_PALEVEL_PA2_OFF|r.powerLevel) err = r.readWriteReg(REG_PALEVEL, 0, RF_PALEVEL_PA0_ON|RF_PALEVEL_PA1_OFF|RF_PALEVEL_PA2_OFF|r.powerLevel)
} }
return err return err
} }
@ -341,16 +353,13 @@ func (r *Device) writeFifo(data *Data) error {
tx[1] = byte(buffersize + 3) tx[1] = byte(buffersize + 3)
tx[2] = data.ToAddress tx[2] = data.ToAddress
tx[3] = r.address tx[3] = r.address
if data.RequestAck { if data.RequestAck {
tx[4] = 0x40 tx[4] = 0x40
} }
if data.SendAck { if data.SendAck {
tx[4] = 0x80 tx[4] = 0x80
} }
copy(tx[5:], data.Data[:buffersize]) copy(tx[5:], data.Data[:buffersize])
_, err := r.SpiDevice.Xfer(tx) _, err := r.SpiDevice.Xfer(tx)
return err return err
} }
@ -358,34 +367,28 @@ func (r *Device) writeFifo(data *Data) error {
func (r *Device) readFifo() (Data, error) { func (r *Device) readFifo() (Data, error) {
var err error var err error
data := Data{} data := Data{}
data.Rssi, err = r.readRSSI(false) data.Rssi, err = r.readRSSI(false)
if err != nil { if err != nil {
return data, err return data, err
} }
tx := new([67]byte) tx := new([67]byte)
tx[0] = REG_FIFO & 0x7f tx[0] = REG_FIFO & 0x7f
rx, err := r.SpiDevice.Xfer(tx[:3]) rx, err := r.SpiDevice.Xfer(tx[:3])
if err != nil { if err != nil {
return data, err return data, err
} }
data.ToAddress = rx[2] data.ToAddress = rx[2]
length := rx[1] - 3 length := rx[1] - 3
if length > 66 { if length > 66 {
length = 66 length = 66
} }
rx, err = r.SpiDevice.Xfer(tx[:length+3]) rx, err = r.SpiDevice.Xfer(tx[:length+3])
if err != nil { if err != nil {
return data, err return data, err
} }
data.FromAddress = rx[1] data.FromAddress = rx[1]
data.SendAck = bool(rx[2]&0x80 > 0) data.SendAck = bool(rx[2]&0x80 > 0)
data.RequestAck = bool(rx[2]&0x40 > 0) data.RequestAck = bool(rx[2]&0x40 > 0)
data.Data = rx[3:] data.Data = rx[3:]
return data, nil return data, nil
} }

@ -7,122 +7,85 @@ import (
) )
// Loop is the main receive and transmit handling loop // Loop is the main receive and transmit handling loop
func (r *Device) Loop() (chan Data, chan Data, chan int) { func (r *Device) Loop() (chan Data, chan int) {
quit := make(chan int) quit := make(chan int)
txChan := make(chan Data, 5) ch := make(chan Data, 5)
rxChan := make(chan Data, 5) go r.loopInternal(ch, quit)
return ch, quit
go func() { }
irq := make(chan int)
r.gpio.BeginWatch(gpio.EdgeRising, func() {
irq <- 1
})
err := r.SetMode(RF_OPMODE_RECEIVER)
if err != nil {
log.Print(err)
return
}
defer r.SetMode(RF_OPMODE_STANDBY)
for {
select {
case dataToTransmit := <-txChan:
// TODO: can send?
r.readWriteReg(REG_PACKETCONFIG2, 0xFB, RF_PACKET2_RXRESTART) // avoid RX deadlocks
err = r.SetMode(RF_OPMODE_STANDBY)
if err != nil {
log.Fatal(err)
}
err = r.waitForMode()
if err != nil {
log.Fatal(err)
}
err = r.writeReg(REG_DIOMAPPING1, RF_DIOMAPPING1_DIO0_00)
if err != nil {
log.Fatal(err)
}
err = r.writeFifo(&dataToTransmit)
if err != nil {
log.Fatal(err)
}
log.Print("transmit", dataToTransmit)
err = r.SetMode(RF_OPMODE_TRANSMITTER)
if err != nil {
log.Fatal(err)
}
<-irq
log.Print("transmit done")
err = r.SetMode(RF_OPMODE_STANDBY)
if err != nil {
log.Fatal(err)
}
err = r.waitForMode()
if err != nil {
log.Fatal(err)
}
err = r.writeReg(REG_DIOMAPPING1, RF_DIOMAPPING1_DIO0_01)
if err != nil {
log.Fatal(err)
}
err = r.SetMode(RF_OPMODE_RECEIVER)
if err != nil {
log.Fatal(err)
}
case <-irq:
if r.mode != RF_OPMODE_RECEIVER {
continue
}
flags, err := r.readReg(REG_IRQFLAGS2)
if err != nil {
return
}
if flags&RF_IRQFLAGS2_PAYLOADREADY == 0 {
continue
}
data, err := r.readFifo()
if err != nil {
log.Print(err)
return
}
log.Print("receive", data)
if data.ToAddress != 255 && data.RequestAck {
resp := Data{
FromAddress: r.address,
ToAddress: data.FromAddress,
SendAck: true,
}
txChan <- resp
}
rxChan <- data
err = r.SetMode(RF_OPMODE_RECEIVER)
if err != nil {
log.Fatal(err)
}
case <-quit: func (r *Device) loopInternal(ch chan Data, quit chan int) {
quit <- 1 irq := make(chan int)
r.gpio.BeginWatch(gpio.EdgeRising, func() {
irq <- 1
})
defer r.gpio.EndWatch()
err := r.SetMode(RF_OPMODE_RECEIVER)
if err != nil {
log.Print(err)
return
}
defer r.SetMode(RF_OPMODE_STANDBY)
for {
select {
case dataToTransmit := <-ch:
// TODO: can send?
r.readWriteReg(REG_PACKETCONFIG2, 0xFB, RF_PACKET2_RXRESTART) // avoid RX deadlocks
err = r.SetModeAndWait(RF_OPMODE_STANDBY)
if err != nil {
log.Fatal(err)
}
err = r.writeReg(REG_DIOMAPPING1, RF_DIOMAPPING1_DIO0_00)
if err != nil {
log.Fatal(err)
}
err = r.writeFifo(&dataToTransmit)
if err != nil {
log.Fatal(err)
}
err = r.SetMode(RF_OPMODE_TRANSMITTER)
if err != nil {
log.Fatal(err)
}
<-irq
err = r.SetModeAndWait(RF_OPMODE_STANDBY)
if err != nil {
log.Fatal(err)
}
err = r.writeReg(REG_DIOMAPPING1, RF_DIOMAPPING1_DIO0_01)
if err != nil {
log.Fatal(err)
}
err = r.SetMode(RF_OPMODE_RECEIVER)
if err != nil {
log.Fatal(err)
}
case <-irq:
if r.mode != RF_OPMODE_RECEIVER {
continue
}
flags, err := r.readReg(REG_IRQFLAGS2)
if err != nil {
return return
} }
if flags&RF_IRQFLAGS2_PAYLOADREADY == 0 {
continue
}
data, err := r.readFifo()
if err != nil {
log.Print(err)
return
}
ch <- data
err = r.SetMode(RF_OPMODE_RECEIVER)
if err != nil {
log.Fatal(err)
}
case <-quit:
quit <- 1
return
} }
}() }
return rxChan, txChan, quit
} }

Loading…
Cancel
Save