Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

LoRa WAN US915 Support #603

Closed
wants to merge 4 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions lora/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,9 @@ const (
const (
MHz_868_1 = 868100000
MHz_868_5 = 868500000
MHz_902_3 = 902300000
Mhz_903_0 = 903000000
MHZ_915_0 = 915000000
MHz_916_8 = 916800000
MHz_923_3 = 923300000
)
56 changes: 31 additions & 25 deletions lora/lorawan/adaptor.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,13 +52,13 @@ func SetPublicNetwork(enabled bool) {
}

// ApplyChannelConfig sets current Lora modulation according to current regional settings
func applyChannelConfig(ch *region.Channel) {
ActiveRadio.SetFrequency(ch.Frequency)
ActiveRadio.SetBandwidth(ch.Bandwidth)
ActiveRadio.SetCodingRate(ch.CodingRate)
ActiveRadio.SetSpreadingFactor(ch.SpreadingFactor)
ActiveRadio.SetPreambleLength(ch.PreambleLength)
ActiveRadio.SetTxPower(ch.TxPowerDBm)
func applyChannelConfig(ch region.Channel) {
ActiveRadio.SetFrequency(ch.Frequency())
ActiveRadio.SetBandwidth(ch.Bandwidth())
ActiveRadio.SetCodingRate(ch.CodingRate())
ActiveRadio.SetSpreadingFactor(ch.SpreadingFactor())
ActiveRadio.SetPreambleLength(ch.PreambleLength())
ActiveRadio.SetTxPower(ch.TxPowerDBm())
// Lorawan defaults to explicit headers
ActiveRadio.SetHeaderType(lora.HeaderExplicit)
ActiveRadio.SetCrc(true)
Expand All @@ -84,24 +84,30 @@ func Join(otaa *Otaa, session *Session) error {
return err
}

// Prepare radio for Join Tx
applyChannelConfig(regionSettings.JoinRequestChannel())
ActiveRadio.SetIqMode(lora.IQStandard)
ActiveRadio.Tx(payload, LORA_TX_TIMEOUT)
if err != nil {
return err
}

// Wait for JoinAccept
applyChannelConfig(regionSettings.JoinAcceptChannel())
ActiveRadio.SetIqMode(lora.IQInverted)
resp, err = ActiveRadio.Rx(LORA_RX_TIMEOUT)
if err != nil {
return err
}

if resp == nil {
return ErrNoJoinAcceptReceived
for {
joinRequestChannel := regionSettings.JoinRequestChannel()
joinAcceptChannel := regionSettings.JoinAcceptChannel()

// Prepare radio for Join Tx
applyChannelConfig(joinRequestChannel)
ActiveRadio.SetIqMode(lora.IQStandard)
ActiveRadio.Tx(payload, LORA_TX_TIMEOUT)
if err != nil {
return err
}

// Wait for JoinAccept
if joinAcceptChannel.Frequency() != 0 {
applyChannelConfig(joinAcceptChannel)
}
ActiveRadio.SetIqMode(lora.IQInverted)
resp, err = ActiveRadio.Rx(LORA_RX_TIMEOUT)
if err == nil && resp != nil {
break
}
if !joinAcceptChannel.Next() {
return ErrNoJoinAcceptReceived
}
}

err = otaa.DecodeJoinAccept(resp, session)
Expand Down
51 changes: 42 additions & 9 deletions lora/lorawan/region/au915.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,27 +7,56 @@ const (
AU915_DEFAULT_TX_POWER_DBM = 20
)

type ChannelAU struct {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks like identical code for all ChannelXX types-
Should we have a base channel type and compose these "higher" level types with it?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ie:

type channel struct {
	frequency       uint32
	bandwidth       uint8
	spreadingFactor uint8
	codingRate      uint8
	preambleLength  uint16
	txPowerDBm      int8
}
// Implement methods for channel here...

type ChannelAU struct {
     channel // Exposes exported channel methods.
}

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@soypat that sounds like an excellent refactoring for a subsequent PR.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I will submit a PR that does exactly this later on...

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See #611

frequency uint32
bandwidth uint8
spreadingFactor uint8
codingRate uint8
preambleLength uint16
txPowerDBm int8
}

// Getter functions
func (c *ChannelAU) Frequency() uint32 { return c.frequency }
func (c *ChannelAU) Bandwidth() uint8 { return c.bandwidth }
func (c *ChannelAU) SpreadingFactor() uint8 { return c.spreadingFactor }
func (c *ChannelAU) CodingRate() uint8 { return c.codingRate }
func (c *ChannelAU) PreambleLength() uint16 { return c.preambleLength }
func (c *ChannelAU) TxPowerDBm() int8 { return c.txPowerDBm }

// Set functions
func (c *ChannelAU) SetFrequency(v uint32) { c.frequency = v }
func (c *ChannelAU) SetBandwidth(v uint8) { c.bandwidth = v }
func (c *ChannelAU) SetSpreadingFactor(v uint8) { c.spreadingFactor = v }
func (c *ChannelAU) SetCodingRate(v uint8) { c.codingRate = v }
func (c *ChannelAU) SetPreambleLength(v uint16) { c.preambleLength = v }
func (c *ChannelAU) SetTxPowerDBm(v int8) { c.txPowerDBm = v }

func (c *ChannelAU) Next() bool {
return false
}

type RegionSettingsAU915 struct {
joinRequestChannel *Channel
joinAcceptChannel *Channel
uplinkChannel *Channel
joinRequestChannel *ChannelAU
joinAcceptChannel *ChannelAU
uplinkChannel *ChannelAU
}

func AU915() *RegionSettingsAU915 {
return &RegionSettingsAU915{
joinRequestChannel: &Channel{lora.MHz_916_8,
joinRequestChannel: &ChannelAU{lora.MHz_916_8,
lora.Bandwidth_125_0,
lora.SpreadingFactor9,
lora.CodingRate4_5,
AU915_DEFAULT_PREAMBLE_LEN,
AU915_DEFAULT_TX_POWER_DBM},
joinAcceptChannel: &Channel{lora.MHz_923_3,
joinAcceptChannel: &ChannelAU{lora.MHz_923_3,
lora.Bandwidth_500_0,
lora.SpreadingFactor9,
lora.CodingRate4_5,
AU915_DEFAULT_PREAMBLE_LEN,
AU915_DEFAULT_TX_POWER_DBM},
uplinkChannel: &Channel{lora.MHz_916_8,
uplinkChannel: &ChannelAU{lora.MHz_916_8,
lora.Bandwidth_125_0,
lora.SpreadingFactor9,
lora.CodingRate4_5,
Expand All @@ -36,14 +65,18 @@ func AU915() *RegionSettingsAU915 {
}
}

func (r *RegionSettingsAU915) JoinRequestChannel() *Channel {
func Next(c *ChannelAU) bool {
return false
}

func (r *RegionSettingsAU915) JoinRequestChannel() Channel {
return r.joinRequestChannel
}

func (r *RegionSettingsAU915) JoinAcceptChannel() *Channel {
func (r *RegionSettingsAU915) JoinAcceptChannel() Channel {
return r.joinAcceptChannel
}

func (r *RegionSettingsAU915) UplinkChannel() *Channel {
func (r *RegionSettingsAU915) UplinkChannel() Channel {
return r.uplinkChannel
}
47 changes: 38 additions & 9 deletions lora/lorawan/region/eu868.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,27 +7,56 @@ const (
EU868_DEFAULT_TX_POWER_DBM = 20
)

type ChannelEU struct {
frequency uint32
bandwidth uint8
spreadingFactor uint8
codingRate uint8
preambleLength uint16
txPowerDBm int8
}

// Getter functions
func (c *ChannelEU) Frequency() uint32 { return c.frequency }
func (c *ChannelEU) Bandwidth() uint8 { return c.bandwidth }
func (c *ChannelEU) SpreadingFactor() uint8 { return c.spreadingFactor }
func (c *ChannelEU) CodingRate() uint8 { return c.codingRate }
func (c *ChannelEU) PreambleLength() uint16 { return c.preambleLength }
func (c *ChannelEU) TxPowerDBm() int8 { return c.txPowerDBm }

// Set functions
func (c *ChannelEU) SetFrequency(v uint32) { c.frequency = v }
func (c *ChannelEU) SetBandwidth(v uint8) { c.bandwidth = v }
func (c *ChannelEU) SetSpreadingFactor(v uint8) { c.spreadingFactor = v }
func (c *ChannelEU) SetCodingRate(v uint8) { c.codingRate = v }
func (c *ChannelEU) SetPreambleLength(v uint16) { c.preambleLength = v }
func (c *ChannelEU) SetTxPowerDBm(v int8) { c.txPowerDBm = v }

func (c *ChannelEU) Next() bool {
return false
}

type RegionSettingsEU868 struct {
joinRequestChannel *Channel
joinAcceptChannel *Channel
uplinkChannel *Channel
joinRequestChannel *ChannelEU
joinAcceptChannel *ChannelEU
uplinkChannel *ChannelEU
}

func EU868() *RegionSettingsEU868 {
return &RegionSettingsEU868{
joinRequestChannel: &Channel{lora.MHz_868_1,
joinRequestChannel: &ChannelEU{lora.MHz_868_1,
lora.Bandwidth_125_0,
lora.SpreadingFactor9,
lora.CodingRate4_7,
EU868_DEFAULT_PREAMBLE_LEN,
EU868_DEFAULT_TX_POWER_DBM},
joinAcceptChannel: &Channel{lora.MHz_868_1,
joinAcceptChannel: &ChannelEU{lora.MHz_868_1,
lora.Bandwidth_125_0,
lora.SpreadingFactor9,
lora.CodingRate4_7,
EU868_DEFAULT_PREAMBLE_LEN,
EU868_DEFAULT_TX_POWER_DBM},
uplinkChannel: &Channel{lora.MHz_868_1,
uplinkChannel: &ChannelEU{lora.MHz_868_1,
lora.Bandwidth_125_0,
lora.SpreadingFactor9,
lora.CodingRate4_7,
Expand All @@ -36,14 +65,14 @@ func EU868() *RegionSettingsEU868 {
}
}

func (r *RegionSettingsEU868) JoinRequestChannel() *Channel {
func (r *RegionSettingsEU868) JoinRequestChannel() Channel {
return r.joinRequestChannel
}

func (r *RegionSettingsEU868) JoinAcceptChannel() *Channel {
func (r *RegionSettingsEU868) JoinAcceptChannel() Channel {
return r.joinAcceptChannel
}

func (r *RegionSettingsEU868) UplinkChannel() *Channel {
func (r *RegionSettingsEU868) UplinkChannel() Channel {
return r.uplinkChannel
}
23 changes: 12 additions & 11 deletions lora/lorawan/region/regionset.go
Original file line number Diff line number Diff line change
@@ -1,16 +1,17 @@
package region

type Channel struct {
Frequency uint32
Bandwidth uint8
SpreadingFactor uint8
CodingRate uint8
PreambleLength uint16
TxPowerDBm int8
type RegionSettings interface {
JoinRequestChannel() Channel
JoinAcceptChannel() Channel
UplinkChannel() Channel
}

type RegionSettings interface {
JoinRequestChannel() *Channel
JoinAcceptChannel() *Channel
UplinkChannel() *Channel
type Channel interface {
Next() bool
Frequency() uint32
Bandwidth() uint8
SpreadingFactor() uint8
CodingRate() uint8
PreambleLength() uint16
TxPowerDBm() int8
}
118 changes: 118 additions & 0 deletions lora/lorawan/region/us915.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
package region

import "tinygo.org/x/drivers/lora"

const (
US915_DEFAULT_PREAMBLE_LEN = 8
US915_DEFAULT_TX_POWER_DBM = 20
US915_FREQUENCY_INCREMENT_DR_0 = 200000 // only for 125 kHz Bandwidth
US915_FREQUENCY_INCREMENT_DR_4 = 1600000 // only for 500 kHz Bandwidth
)

type ChannelUS struct {
frequency uint32
bandwidth uint8
spreadingFactor uint8
codingRate uint8
preambleLength uint16
txPowerDBm int8
}

// Getter functions
func (c *ChannelUS) Frequency() uint32 { return c.frequency }
func (c *ChannelUS) Bandwidth() uint8 { return c.bandwidth }
func (c *ChannelUS) SpreadingFactor() uint8 { return c.spreadingFactor }
func (c *ChannelUS) CodingRate() uint8 { return c.codingRate }
func (c *ChannelUS) PreambleLength() uint16 { return c.preambleLength }
func (c *ChannelUS) TxPowerDBm() int8 { return c.txPowerDBm }

// Set functions
// TODO: validate input
func (c *ChannelUS) SetFrequency(v uint32) { c.frequency = v }
func (c *ChannelUS) SetBandwidth(v uint8) { c.bandwidth = v }
func (c *ChannelUS) SetSpreadingFactor(v uint8) { c.spreadingFactor = v }
func (c *ChannelUS) SetCodingRate(v uint8) { c.codingRate = v }
func (c *ChannelUS) SetPreambleLength(v uint16) { c.preambleLength = v }
func (c *ChannelUS) SetTxPowerDBm(v int8) { c.txPowerDBm = v }

func (c *ChannelUS) Next() bool {
switch c.Bandwidth() {
case lora.Bandwidth_125_0:
freq, ok := stepFrequency125(c.frequency)
if ok {
c.frequency = freq
} else {
c.frequency = lora.Mhz_903_0
c.bandwidth = lora.Bandwidth_500_0
}
case lora.Bandwidth_500_0:
freq, ok := stepFrequency500(c.frequency)
if ok {
c.frequency = freq
} else {
// there are no more frequencies to check after sweeping all 8 500 kHz channels
return false
}
}

return true
}

func stepFrequency125(freq uint32) (uint32, bool) {
f := freq + US915_FREQUENCY_INCREMENT_DR_0
if f >= lora.MHZ_915_0 {
return 0, false
}

return f, true
}

func stepFrequency500(freq uint32) (uint32, bool) {
f := freq + US915_FREQUENCY_INCREMENT_DR_4
if f >= lora.MHZ_915_0 {
return 0, false
}

return f, true
}

type RegionSettingsUS915 struct {
joinRequestChannel *ChannelUS
joinAcceptChannel *ChannelUS
uplinkChannel *ChannelUS
}

func US915() *RegionSettingsUS915 {
return &RegionSettingsUS915{
joinRequestChannel: &ChannelUS{lora.MHz_902_3,
lora.Bandwidth_125_0,
lora.SpreadingFactor10,
lora.CodingRate4_5,
US915_DEFAULT_PREAMBLE_LEN,
US915_DEFAULT_TX_POWER_DBM},
joinAcceptChannel: &ChannelUS{0,
lora.Bandwidth_500_0,
lora.SpreadingFactor9,
lora.CodingRate4_5,
US915_DEFAULT_PREAMBLE_LEN,
US915_DEFAULT_TX_POWER_DBM},
uplinkChannel: &ChannelUS{lora.Mhz_903_0,
lora.Bandwidth_500_0,
lora.SpreadingFactor9,
lora.CodingRate4_5,
US915_DEFAULT_PREAMBLE_LEN,
US915_DEFAULT_TX_POWER_DBM},
}
}

func (r *RegionSettingsUS915) JoinRequestChannel() Channel {
return r.joinRequestChannel
}

func (r *RegionSettingsUS915) JoinAcceptChannel() Channel {
return r.joinAcceptChannel
}

func (r *RegionSettingsUS915) UplinkChannel() Channel {
return r.uplinkChannel
}