sx1276

package
v0.0.0-...-6570e0f Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jun 25, 2017 License: Apache-2.0 Imports: 6 Imported by: 0

Documentation

Overview

The SX1276 package interfaces with a HopeRF RFM95/96/97/98 LoRA radio connected to an SPI bus.

The RFM9x modules use a Semtech SX1276 radio chip. This package has also been tested with a Dorji DRF1278 module and it should work fine with other radio modules using the same chip. Note that the SX1276, SX1277, SX1278, and SX1279 all function identically and only differ in which RF bands they support.

The driver is fully interrupt driven and requires that the radio's DIO0 pin be connected to an interrupt capable GPIO pin. The transmit and receive interface uses a pair of tx and rx channels, each having a small amount of buffering.

In general, other than a few user errors (such as passing too large a packet to Send) there should be no errors during the radio's operation unless there is a hardware failure. For this reason radio interface errors are treated as fatal: if such an error occurs the rx channel is closed and the error is recorded in the Radio struct where it can be retrieved using the Error function. The object will be unusable for further operation and the client code will have to create and initialize a fresh object which will re-establish communication with the radio chip.

Limitations

This driver uses the SX1276 in LoRA mode only.

Only the explicit header mode is supported, this means that spreading factor 6 cannot be used and thus the maximum data rate available is 21875bps.

The methods on the Radio object are not concurrency safe. Since they all deal with configuration this should not pose difficulties. The Error function may be called from multiple goroutines and obviously the TX and RX channels work well with concurrency.

Index

Constants

View Source
const (
	DataNoAck = iota // data packet, no ack requested
	DataAck          // data packet, ack requested
	Ack              // ACK packet
	Special          // special packet, unused for now
)

Packet kinds

View Source
const (
	REG_FIFO        = 0x00
	REG_OPMODE      = 0x01
	REG_FRFMSB      = 0x06
	REG_PACONFIG    = 0x09
	REG_OCP         = 0x0B
	REG_LNA         = 0x0C
	REG_FIFOPTR     = 0x0D
	REG_FIFOTXBASE  = 0x0E
	REG_FIFORXBASE  = 0x0F
	REG_FIFORXCURR  = 0x10
	REG_IRQMASK     = 0x11
	REG_IRQFLAGS    = 0x12
	REG_RXBYTES     = 0x13
	REG_MODEMSTAT   = 0x18
	REG_PKTSNR      = 0x19
	REG_PKTRSSI     = 0x1A
	REG_CURRSSI     = 0x1B
	REG_HOPCHAN     = 0x1C
	REG_MODEMCONF1  = 0x1D
	REG_MODEMCONF2  = 0x1E
	REG_SYMBTIMEOUT = 0x1F
	REG_PREAMBLE    = 0x21
	REG_PAYLENGTH   = 0x22
	REG_PAYMAX      = 0x23
	REG_FIFORXLAST  = 0x25
	REG_MODEMCONF3  = 0x26
	REG_PPMCORR     = 0x27
	REG_FEI         = 0x28
	REG_DETECTOPT   = 0x31
	REG_DETECTTHR   = 0x37
	REG_SYNC        = 0x39
	REG_DIOMAPPING1 = 0x40
	REG_DIOMAPPING2 = 0x41
	REG_VERSION     = 0x42
	REG_TCXO        = 0x4B
	REG_PADAC       = 0x4D
	REG_FORMERTEMP  = 0x5B
)
View Source
const (
	MODE_SLEEP = iota
	MODE_STANDBY
	MODE_FS_TX     // frequency synthesis TX
	MODE_TX        // TX
	MODE_FS_RX     // frequency synthesis RX
	MODE_RX_CONT   // RX continuous
	MODE_RX_SINGLE // RX single
	MODE_CAD       // channel activity detection
)
View Source
const (
	// IRQ mask and flags registers
	IRQ_RXTIMEOUT = 1 << 7
	IRQ_RXDONE    = 1 << 6
	IRQ_CRCERR    = 1 << 5
	IRQ_VALIDHDR  = 1 << 4
	IRQ_TXDONE    = 1 << 3
	IRQ_CADDONE   = 1 << 2
	IRQ_FHSCHG    = 1 << 1
	IRQ_CADDETECT = 1 << 0
)

Variables

View Source
var Configs = map[string]Config{

	"lora.bw500cr45sf7":  {0x92, 0x74, 0x04, "31250bps, 20B in   14ms"},
	"lora.bw125cr45sf7":  {0x72, 0x74, 0x04, " 7813bps, 20B in   57ms"},
	"lora.bw125cr48sf12": {0x78, 0xc4, 0x04, "  183bps, 20B in 1712ms"},
	"lora.bw31cr48sf9":   {0x48, 0x94, 0x04, "  275bps, 20B in  987ms"},

	"lorawan.bw125sf12": {0x72, 0xc4, 0x0C, "  250bps, 20B in 1319ms, -137dBm"},
	"lorawan.bw125sf11": {0x72, 0xb4, 0x0C, "  440bps, 20B in  660ms, -136dBm"},
	"lorawan.bw125sf10": {0x72, 0xa4, 0x04, "  980bps, 20B in  370ms, -134dBm"},
	"lorawan.bw125sf9":  {0x72, 0x94, 0x04, " 1760bps, 20B in  185ms, -131dBm"},
	"lorawan.bw125sf8":  {0x72, 0x84, 0x04, " 3125bps, 20B in  103ms, -128dBm"},
	"lorawan.bw125sf7":  {0x72, 0x74, 0x04, " 5470bps, 20B in   57ms, -125dBm"},
	"lorawan.bw250sf7":  {0x82, 0x74, 0x04, "11000bps, 20B in   28ms, -122dBm"},
}

Configs is the table of supported configurations and their corresponding register settings. In order to operate at a new bit rate the table can be extended by the client. The names use bw: bandwidth in kHz, cr: coding rate 4/5..4/8, and sf: spreading factor.

Functions

func JLLEncode

func JLLEncode(kind byte, toGW bool, node byte, fmt byte, payload []byte, rssi, fei int) []byte

JLLEncode encodes a JeeLabs LoRa (JLL) packet.

A JLL packet consists of a header byte, a packet type byte, the payload, and optionally an info trailer. If the rssi parameter is 0 JLLEncode does not append the info trailer.

The packet header byte is very similar to the rf12 JeeLabs header: http://jeelabs.org/2011/06/10/rf12-broadcasts-and-acks/index.html Bit 7 ctrl: 0=data 1=special. Bit 6 dest: 0=to-GW 1=from-GW. Bit 5 ack : 0=no-ack 1=ack-req. Bits 0-4: 32 nodes, 0=broadcast, 31=anonymous tx-only no-ack nodes. The following ctrl/ack combinations are used: c=0, a=0 : data, no ack requested. c=0, a=1 : data, ack requested. c=1, a=0 : ack. c=1, a=1 : special (undefined for now).

The packet type byte indicates what the format of the payload is and supports 127 different payload formats using bits 0..6. The topmost bit is used to indicate whether an info trailer is present (value 1) or not (value 0). The info trailer consists of 2 bytes: min(RSSI[dBm]+164,127) and FEI[Hz]/128 (signed) of the the most recent packet received from the other party. The top bit of the RSSI byte is unused.

Two packet types are reserved:

0: empty packet, typically used for acks, may have an info trailer.
1: node details: Vstart[mV], Vend[mV], Temp[cC], PktSent, PktRecv, Pout[dBm],
   Fadj[Hz], RSSIavg[dBm].

Types

type Config

type Config struct {
	Conf1 byte   // ModemConfig1: bw, coding rate, implicit/expl header
	Conf2 byte   // ModemConfig2: sperading, mode, crc
	Conf3 byte   // ModemConfig3: low data rate opt, LNA gain
	Info  string // info for humans
}

Config describes the SX127x configuration to achieve a specific bandwidth, spreading factor, and coding rate.

type JLLRxPacket

type JLLRxPacket struct {
	Kind    byte // one of the 4 packet kinds
	ToGW    bool // direction: to/from gateway
	Node    byte // node number
	Fmt     byte // packet format
	RemRSSI int  // rssi from trailer, 0 if none
	RemFEI  int  // fei from trailer, none if rssi==0
	RxPacket
}

JLLRxPacket holds a decoded JeeLabs LoRa packet.

func JLLDecode

func JLLDecode(packet *RxPacket) (*JLLRxPacket, error)

JLLDecode decodes a JeeLabs LoRa packet. See JLLEncode for a description of the packet format.

type LogPrintf

type LogPrintf func(format string, v ...interface{})

LogPrintf is a function used by the driver to print logging info.

type Radio

type Radio struct {

	// state
	sync.Mutex // guard concurrent access to the radio
	// contains filtered or unexported fields
}

Radio represents a Semtech SX127x LoRA radio.

func New

func New(port spi.Port, intr gpio.PinIn, opts RadioOpts) (*Radio, error)

New initializes an sx1276 Radio given an spi.Conn and an interrupt pin, and places the radio in receive mode.

To transmit, push packet payloads into the returned txChan. Received packets will be sent on the returned rxChan, which has a small amount of buffering. The rxChan will be closed if a persistent error occurs when communicating with the device, use the Error() function to retrieve the error.

func (*Radio) Error

func (r *Radio) Error() error

Error returns any persistent error that may have been encountered.

func (*Radio) Receive

func (r *Radio) Receive() (*RxPacket, error)

worker is an endless loop that processes interrupts for reception as well as packets enqueued for transmit.

func (*Radio) SetConfig

func (r *Radio) SetConfig(config string)

SetConfig sets the modem configuration using one of the entries in the Configs table. If the entry specified does not exist, nothing is changed.

func (*Radio) SetFrequency

func (r *Radio) SetFrequency(freq uint32)

SetFrequency changes the center frequency at which the radio transmits and receives. The frequency can be specified at any scale (hz, khz, mhz). The frequency value is not checked and invalid values will simply cause the radio not to work particularly well.

func (*Radio) SetLogger

func (r *Radio) SetLogger(l LogPrintf)

SetLogger sets a logging function, nil may be used to disable logging, which is the default.

func (*Radio) SetPower

func (r *Radio) SetPower(dBm byte)

SetPower configures the radio for the specified output power. It only supports the high-power amp because RFM9x modules don't have the lower-power amps connected to anything.

The datasheet is confusing about how PaConfig gets set and the formula for OutputPower looks incorrect. Fortunately Semtech provides reference code...

func (*Radio) Transmit

func (r *Radio) Transmit(payload []byte) error

Transmit switches the radio's mode and starts transmitting a packet.

type RadioOpts

type RadioOpts struct {
	Sync   byte      // RF sync byte
	Freq   uint32    // center frequency in Hz, Khz, or Mhz
	Config string    // entry in Configs table to use
	Logger LogPrintf // function to use for logging
}

RadioOpts contains options used when initilizing a Radio.

type RxPacket

type RxPacket struct {
	Payload []byte    // payload, excluding length & crc
	Snr     int       // signal-to-noise in dB for packet
	Rssi    int       // rssi in dB for packet
	Fei     int       // frequency error in Hz for packet
	Lna     int       // dB of LNA applied
	At      time.Time // time of recv interrupt
}

RxPacket is a received packet with stats.

type Temporary

type Temporary interface {
	Temporary() bool
}

Temporary is an interface implemented by errors that are temporary and thus worth retrying.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL