LMIC for MOTE_L152RC

Dependents:   lmic_transmit

LoRa WAN in C for NA-mote 72

Currently version 1.5


LoRaWAN network configuration for end-device

The following three pieces of information uniquely identifies end-device to network to allow over-the-air activation. These are stored in the end-device prior to join procedure.

AppEUI

Uniquely identifies application provider of end-device.

Least-significant byte first, 8 bytes. Use LMIC_reverse_memcpy() for AppEUI to keep same byte order as that on lora server.

example C code

static const u1_t APPEUI[8]  = { 0x01, 0x00, 0x01, 0x00, 0x00, 0x0C, 0x25, 0x00 };

This is copied into LMIC by os_getArtEui() callback function in application.

DevEUI

End-device ID, unique to each end-node.

Least-significant byte first, 8 bytes. Use LMIC_reverse_memcpy() for DevEUI to keep same byte order as that on lora server.

example C code

static const u1_t DEVEUI[8]  = { 0x00, 0x00, 0x00, 0x00, 0x01, 0x0C, 0x25, 0x00 }; 

This is copied into LMIC by os_getDevEui() callback function in application.

AppKey (aka DevKey)

128-bit (16byte) AES key.

example C code

static const u1_t DEVKEY[16] = { 0xe4, 0x72, 0x71, 0xc5, 0xf5, 0x30, 0xa9, 0x9f, 0xcf, 0xc4, 0x0e, 0xab, 0xea, 0xd7, 0x19, 0x42 };

This is copied into LMIC by os_getDevKey() callback function in application.

Using over-the air activation, the end-device (LMIC) performs a join procedure every time it starts for first time, or has lost session context information. When join procedure has successfully completed, the end-device will have a network session key (NwkSKey) and an application session key (AppSKey), which are used for encryption and message integrity check.


configuration with http://us01-iot.semtech.com/

  • log in to server
  • click on Applications
  • find your application and click it
  • go to configure motes
  • to create a mote, you may enter a new DevEUI
    • you may copy-paste the 16byte application key from an already existing mote, if you desire.

Information

DevEUI is entered in reverse order into C-code from that shown on server (unique device ID).

AppEUI is entered in reverse order into C-code from that shown on server.

AppEUI is equivalent to "Application"

transmit power limits

FCC Part 15 rules permit one watt of transmit power when more than 50 channels are used. When received by a 64-channel gateway, the maximum power may be used.

However, if end-device is sending to a 8-channel gateway (single SX1301), the maximum transmit power permitted is +20dBm.

To configure LMIC for use with 8-channel gateway, CHNL_HYBRID should be defined in in config.h, and should be undefined for use with 64-channel gateway.

CHNL_HYBRID125KHz500KHz
defined valuechannelschannel
00 to 764
18 to 1565
216 to 2366
324 to 3167
432 to 3968
540 to 4769
648 to 5570
756 to 6371
undef0 to 6364 to 71
Committer:
dudmuck
Date:
Tue Jul 07 18:25:05 2015 +0000
Revision:
4:1a9a62cf220f
Parent:
3:d87012f45bf6
Child:
8:0faa1bb768b5
correct the value of MAP_DIO2_LORA_NOP

Who changed what in which revision?

UserRevisionLine numberNew contents of line
dudmuck 0:f2716e543d97 1 /*******************************************************************************
dudmuck 0:f2716e543d97 2 * Copyright (c) 2014-2015 IBM Corporation.
dudmuck 0:f2716e543d97 3 * All rights reserved. This program and the accompanying materials
dudmuck 0:f2716e543d97 4 * are made available under the terms of the Eclipse Public License v1.0
dudmuck 0:f2716e543d97 5 * which accompanies this distribution, and is available at
dudmuck 0:f2716e543d97 6 * http://www.eclipse.org/legal/epl-v10.html
dudmuck 0:f2716e543d97 7 *
dudmuck 0:f2716e543d97 8 * Contributors:
dudmuck 0:f2716e543d97 9 * IBM Zurich Research Lab - initial API, implementation and documentation
dudmuck 0:f2716e543d97 10 *******************************************************************************/
dudmuck 0:f2716e543d97 11
dudmuck 0:f2716e543d97 12 #include "lmic.h"
dudmuck 3:d87012f45bf6 13 #include "mbed.h"
dudmuck 0:f2716e543d97 14
dudmuck 0:f2716e543d97 15 // ----------------------------------------
dudmuck 0:f2716e543d97 16 // Registers Mapping
dudmuck 0:f2716e543d97 17 #define RegFifo 0x00 // common
dudmuck 0:f2716e543d97 18 #define RegOpMode 0x01 // common
dudmuck 0:f2716e543d97 19 #define FSKRegBitrateMsb 0x02
dudmuck 0:f2716e543d97 20 #define FSKRegBitrateLsb 0x03
dudmuck 0:f2716e543d97 21 #define FSKRegFdevMsb 0x04
dudmuck 0:f2716e543d97 22 #define FSKRegFdevLsb 0x05
dudmuck 0:f2716e543d97 23 #define RegFrfMsb 0x06 // common
dudmuck 0:f2716e543d97 24 #define RegFrfMid 0x07 // common
dudmuck 0:f2716e543d97 25 #define RegFrfLsb 0x08 // common
dudmuck 0:f2716e543d97 26 #define RegPaConfig 0x09 // common
dudmuck 0:f2716e543d97 27 #define RegPaRamp 0x0A // common
dudmuck 0:f2716e543d97 28 #define RegOcp 0x0B // common
dudmuck 0:f2716e543d97 29 #define RegLna 0x0C // common
dudmuck 0:f2716e543d97 30 #define FSKRegRxConfig 0x0D
dudmuck 0:f2716e543d97 31 #define LORARegFifoAddrPtr 0x0D
dudmuck 0:f2716e543d97 32 #define FSKRegRssiConfig 0x0E
dudmuck 0:f2716e543d97 33 #define LORARegFifoTxBaseAddr 0x0E
dudmuck 0:f2716e543d97 34 #define FSKRegRssiCollision 0x0F
dudmuck 0:f2716e543d97 35 #define LORARegFifoRxBaseAddr 0x0F
dudmuck 0:f2716e543d97 36 #define FSKRegRssiThresh 0x10
dudmuck 0:f2716e543d97 37 #define LORARegFifoRxCurrentAddr 0x10
dudmuck 0:f2716e543d97 38 #define FSKRegRssiValue 0x11
dudmuck 0:f2716e543d97 39 #define LORARegIrqFlagsMask 0x11
dudmuck 0:f2716e543d97 40 #define FSKRegRxBw 0x12
dudmuck 0:f2716e543d97 41 #define LORARegIrqFlags 0x12
dudmuck 0:f2716e543d97 42 #define FSKRegAfcBw 0x13
dudmuck 0:f2716e543d97 43 #define LORARegRxNbBytes 0x13
dudmuck 0:f2716e543d97 44 #define FSKRegOokPeak 0x14
dudmuck 0:f2716e543d97 45 #define LORARegRxHeaderCntValueMsb 0x14
dudmuck 0:f2716e543d97 46 #define FSKRegOokFix 0x15
dudmuck 0:f2716e543d97 47 #define LORARegRxHeaderCntValueLsb 0x15
dudmuck 0:f2716e543d97 48 #define FSKRegOokAvg 0x16
dudmuck 0:f2716e543d97 49 #define LORARegRxPacketCntValueMsb 0x16
dudmuck 0:f2716e543d97 50 #define LORARegRxpacketCntValueLsb 0x17
dudmuck 0:f2716e543d97 51 #define LORARegModemStat 0x18
dudmuck 0:f2716e543d97 52 #define LORARegPktSnrValue 0x19
dudmuck 0:f2716e543d97 53 #define FSKRegAfcFei 0x1A
dudmuck 0:f2716e543d97 54 #define LORARegPktRssiValue 0x1A
dudmuck 0:f2716e543d97 55 #define FSKRegAfcMsb 0x1B
dudmuck 0:f2716e543d97 56 #define LORARegRssiValue 0x1B
dudmuck 0:f2716e543d97 57 #define FSKRegAfcLsb 0x1C
dudmuck 0:f2716e543d97 58 #define LORARegHopChannel 0x1C
dudmuck 0:f2716e543d97 59 #define FSKRegFeiMsb 0x1D
dudmuck 0:f2716e543d97 60 #define LORARegModemConfig1 0x1D
dudmuck 0:f2716e543d97 61 #define FSKRegFeiLsb 0x1E
dudmuck 0:f2716e543d97 62 #define LORARegModemConfig2 0x1E
dudmuck 0:f2716e543d97 63 #define FSKRegPreambleDetect 0x1F
dudmuck 0:f2716e543d97 64 #define LORARegSymbTimeoutLsb 0x1F
dudmuck 0:f2716e543d97 65 #define FSKRegRxTimeout1 0x20
dudmuck 0:f2716e543d97 66 #define LORARegPreambleMsb 0x20
dudmuck 0:f2716e543d97 67 #define FSKRegRxTimeout2 0x21
dudmuck 0:f2716e543d97 68 #define LORARegPreambleLsb 0x21
dudmuck 0:f2716e543d97 69 #define FSKRegRxTimeout3 0x22
dudmuck 0:f2716e543d97 70 #define LORARegPayloadLength 0x22
dudmuck 0:f2716e543d97 71 #define FSKRegRxDelay 0x23
dudmuck 0:f2716e543d97 72 #define LORARegPayloadMaxLength 0x23
dudmuck 0:f2716e543d97 73 #define FSKRegOsc 0x24
dudmuck 0:f2716e543d97 74 #define LORARegHopPeriod 0x24
dudmuck 0:f2716e543d97 75 #define FSKRegPreambleMsb 0x25
dudmuck 0:f2716e543d97 76 #define LORARegFifoRxByteAddr 0x25
dudmuck 0:f2716e543d97 77 #define LORARegModemConfig3 0x26
dudmuck 0:f2716e543d97 78 #define FSKRegPreambleLsb 0x26
dudmuck 0:f2716e543d97 79 #define FSKRegSyncConfig 0x27
dudmuck 0:f2716e543d97 80 #define LORARegFeiMsb 0x28
dudmuck 0:f2716e543d97 81 #define FSKRegSyncValue1 0x28
dudmuck 0:f2716e543d97 82 #define LORAFeiMib 0x29
dudmuck 0:f2716e543d97 83 #define FSKRegSyncValue2 0x29
dudmuck 0:f2716e543d97 84 #define LORARegFeiLsb 0x2A
dudmuck 0:f2716e543d97 85 #define FSKRegSyncValue3 0x2A
dudmuck 0:f2716e543d97 86 #define FSKRegSyncValue4 0x2B
dudmuck 0:f2716e543d97 87 #define LORARegRssiWideband 0x2C
dudmuck 0:f2716e543d97 88 #define FSKRegSyncValue5 0x2C
dudmuck 0:f2716e543d97 89 #define FSKRegSyncValue6 0x2D
dudmuck 0:f2716e543d97 90 #define FSKRegSyncValue7 0x2E
dudmuck 0:f2716e543d97 91 #define FSKRegSyncValue8 0x2F
dudmuck 0:f2716e543d97 92 #define FSKRegPacketConfig1 0x30
dudmuck 0:f2716e543d97 93 #define FSKRegPacketConfig2 0x31
dudmuck 0:f2716e543d97 94 #define LORARegDetectOptimize 0x31
dudmuck 0:f2716e543d97 95 #define FSKRegPayloadLength 0x32
dudmuck 0:f2716e543d97 96 #define FSKRegNodeAdrs 0x33
dudmuck 0:f2716e543d97 97 #define LORARegInvertIQ 0x33
dudmuck 0:f2716e543d97 98 #define FSKRegBroadcastAdrs 0x34
dudmuck 0:f2716e543d97 99 #define FSKRegFifoThresh 0x35
dudmuck 0:f2716e543d97 100 #define FSKRegSeqConfig1 0x36
dudmuck 0:f2716e543d97 101 #define FSKRegSeqConfig2 0x37
dudmuck 0:f2716e543d97 102 #define LORARegDetectionThreshold 0x37
dudmuck 0:f2716e543d97 103 #define FSKRegTimerResol 0x38
dudmuck 0:f2716e543d97 104 #define FSKRegTimer1Coef 0x39
dudmuck 0:f2716e543d97 105 #define LORARegSyncWord 0x39
dudmuck 0:f2716e543d97 106 #define FSKRegTimer2Coef 0x3A
dudmuck 0:f2716e543d97 107 #define FSKRegImageCal 0x3B
dudmuck 3:d87012f45bf6 108 #define LORARegTimingInvert 0x3B // bit2 in 0x3b set low when bit6 in 0x33 set hi (RX invert)
dudmuck 0:f2716e543d97 109 #define FSKRegTemp 0x3C
dudmuck 0:f2716e543d97 110 #define FSKRegLowBat 0x3D
dudmuck 0:f2716e543d97 111 #define FSKRegIrqFlags1 0x3E
dudmuck 0:f2716e543d97 112 #define FSKRegIrqFlags2 0x3F
dudmuck 0:f2716e543d97 113 #define RegDioMapping1 0x40 // common
dudmuck 0:f2716e543d97 114 #define RegDioMapping2 0x41 // common
dudmuck 0:f2716e543d97 115 #define RegVersion 0x42 // common
dudmuck 0:f2716e543d97 116 // #define RegAgcRef 0x43 // common
dudmuck 0:f2716e543d97 117 // #define RegAgcThresh1 0x44 // common
dudmuck 0:f2716e543d97 118 // #define RegAgcThresh2 0x45 // common
dudmuck 0:f2716e543d97 119 // #define RegAgcThresh3 0x46 // common
dudmuck 0:f2716e543d97 120 // #define RegPllHop 0x4B // common
dudmuck 0:f2716e543d97 121 // #define RegTcxo 0x58 // common
dudmuck 0:f2716e543d97 122 #define RegPaDac 0x5A // common
dudmuck 0:f2716e543d97 123 // #define RegPll 0x5C // common
dudmuck 0:f2716e543d97 124 // #define RegPllLowPn 0x5E // common
dudmuck 0:f2716e543d97 125 // #define RegFormerTemp 0x6C // common
dudmuck 0:f2716e543d97 126 // #define RegBitRateFrac 0x70 // common
dudmuck 0:f2716e543d97 127
dudmuck 0:f2716e543d97 128 // ----------------------------------------
dudmuck 0:f2716e543d97 129 // spread factors and mode for RegModemConfig2
dudmuck 0:f2716e543d97 130 #define SX1272_MC2_FSK 0x00
dudmuck 0:f2716e543d97 131 #define SX1272_MC2_SF7 0x70
dudmuck 0:f2716e543d97 132 #define SX1272_MC2_SF8 0x80
dudmuck 0:f2716e543d97 133 #define SX1272_MC2_SF9 0x90
dudmuck 0:f2716e543d97 134 #define SX1272_MC2_SF10 0xA0
dudmuck 0:f2716e543d97 135 #define SX1272_MC2_SF11 0xB0
dudmuck 0:f2716e543d97 136 #define SX1272_MC2_SF12 0xC0
dudmuck 0:f2716e543d97 137 // bandwidth for RegModemConfig1
dudmuck 0:f2716e543d97 138 #define SX1272_MC1_BW_125 0x00
dudmuck 0:f2716e543d97 139 #define SX1272_MC1_BW_250 0x40
dudmuck 0:f2716e543d97 140 #define SX1272_MC1_BW_500 0x80
dudmuck 0:f2716e543d97 141 // coding rate for RegModemConfig1
dudmuck 0:f2716e543d97 142 #define SX1272_MC1_CR_4_5 0x08
dudmuck 0:f2716e543d97 143 #define SX1272_MC1_CR_4_6 0x10
dudmuck 0:f2716e543d97 144 #define SX1272_MC1_CR_4_7 0x18
dudmuck 0:f2716e543d97 145 #define SX1272_MC1_CR_4_8 0x20
dudmuck 0:f2716e543d97 146 #define SX1272_MC1_IMPLICIT_HEADER_MODE_ON 0x04 // required for receive
dudmuck 0:f2716e543d97 147 #define SX1272_MC1_RX_PAYLOAD_CRCON 0x02
dudmuck 0:f2716e543d97 148 #define SX1272_MC1_LOW_DATA_RATE_OPTIMIZE 0x01 // mandated for SF11 and SF12
dudmuck 0:f2716e543d97 149 // transmit power configuration for RegPaConfig
dudmuck 0:f2716e543d97 150 #define SX1272_PAC_PA_SELECT_PA_BOOST 0x80
dudmuck 0:f2716e543d97 151 #define SX1272_PAC_PA_SELECT_RFIO_PIN 0x00
dudmuck 0:f2716e543d97 152
dudmuck 0:f2716e543d97 153
dudmuck 0:f2716e543d97 154 // sx1276 RegModemConfig1
dudmuck 0:f2716e543d97 155 #define SX1276_MC1_BW_125 0x70
dudmuck 0:f2716e543d97 156 #define SX1276_MC1_BW_250 0x80
dudmuck 0:f2716e543d97 157 #define SX1276_MC1_BW_500 0x90
dudmuck 0:f2716e543d97 158 #define SX1276_MC1_CR_4_5 0x02
dudmuck 0:f2716e543d97 159 #define SX1276_MC1_CR_4_6 0x04
dudmuck 0:f2716e543d97 160 #define SX1276_MC1_CR_4_7 0x06
dudmuck 0:f2716e543d97 161 #define SX1276_MC1_CR_4_8 0x08
dudmuck 0:f2716e543d97 162
dudmuck 0:f2716e543d97 163 #define SX1276_MC1_IMPLICIT_HEADER_MODE_ON 0x01
dudmuck 0:f2716e543d97 164
dudmuck 0:f2716e543d97 165 // sx1276 RegModemConfig2
dudmuck 0:f2716e543d97 166 #define SX1276_MC2_RX_PAYLOAD_CRCON 0x04
dudmuck 0:f2716e543d97 167
dudmuck 0:f2716e543d97 168 // sx1276 RegModemConfig3
dudmuck 0:f2716e543d97 169 #define SX1276_MC3_LOW_DATA_RATE_OPTIMIZE 0x08
dudmuck 0:f2716e543d97 170 #define SX1276_MC3_AGCAUTO 0x04
dudmuck 0:f2716e543d97 171
dudmuck 0:f2716e543d97 172 // preamble for lora networks (nibbles swapped)
dudmuck 0:f2716e543d97 173 #define LORA_MAC_PREAMBLE 0x34
dudmuck 0:f2716e543d97 174
dudmuck 0:f2716e543d97 175 #define RXLORA_RXMODE_RSSI_REG_MODEM_CONFIG1 0x0A
dudmuck 0:f2716e543d97 176 #ifdef CFG_sx1276_radio
dudmuck 0:f2716e543d97 177 #define RXLORA_RXMODE_RSSI_REG_MODEM_CONFIG2 0x70
dudmuck 0:f2716e543d97 178 #elif defined(CFG_sx1272_radio)
dudmuck 0:f2716e543d97 179 #define RXLORA_RXMODE_RSSI_REG_MODEM_CONFIG2 0x74
dudmuck 0:f2716e543d97 180 #endif
dudmuck 0:f2716e543d97 181
dudmuck 0:f2716e543d97 182
dudmuck 0:f2716e543d97 183
dudmuck 0:f2716e543d97 184 // ----------------------------------------
dudmuck 0:f2716e543d97 185 // Constants for radio registers
dudmuck 0:f2716e543d97 186 #define OPMODE_LORA 0x80
dudmuck 0:f2716e543d97 187 #define OPMODE_MASK 0x07
dudmuck 0:f2716e543d97 188 #define OPMODE_SLEEP 0x00
dudmuck 0:f2716e543d97 189 #define OPMODE_STANDBY 0x01
dudmuck 0:f2716e543d97 190 #define OPMODE_FSTX 0x02
dudmuck 0:f2716e543d97 191 #define OPMODE_TX 0x03
dudmuck 0:f2716e543d97 192 #define OPMODE_FSRX 0x04
dudmuck 0:f2716e543d97 193 #define OPMODE_RX 0x05
dudmuck 0:f2716e543d97 194 #define OPMODE_RX_SINGLE 0x06
dudmuck 0:f2716e543d97 195 #define OPMODE_CAD 0x07
dudmuck 0:f2716e543d97 196
dudmuck 0:f2716e543d97 197 // ----------------------------------------
dudmuck 0:f2716e543d97 198 // Bits masking the corresponding IRQs from the radio
dudmuck 0:f2716e543d97 199 #define IRQ_LORA_RXTOUT_MASK 0x80
dudmuck 0:f2716e543d97 200 #define IRQ_LORA_RXDONE_MASK 0x40
dudmuck 0:f2716e543d97 201 #define IRQ_LORA_CRCERR_MASK 0x20
dudmuck 0:f2716e543d97 202 #define IRQ_LORA_HEADER_MASK 0x10
dudmuck 0:f2716e543d97 203 #define IRQ_LORA_TXDONE_MASK 0x08
dudmuck 0:f2716e543d97 204 #define IRQ_LORA_CDDONE_MASK 0x04
dudmuck 0:f2716e543d97 205 #define IRQ_LORA_FHSSCH_MASK 0x02
dudmuck 0:f2716e543d97 206 #define IRQ_LORA_CDDETD_MASK 0x01
dudmuck 0:f2716e543d97 207
dudmuck 0:f2716e543d97 208 #define IRQ_FSK1_MODEREADY_MASK 0x80
dudmuck 0:f2716e543d97 209 #define IRQ_FSK1_RXREADY_MASK 0x40
dudmuck 0:f2716e543d97 210 #define IRQ_FSK1_TXREADY_MASK 0x20
dudmuck 0:f2716e543d97 211 #define IRQ_FSK1_PLLLOCK_MASK 0x10
dudmuck 0:f2716e543d97 212 #define IRQ_FSK1_RSSI_MASK 0x08
dudmuck 0:f2716e543d97 213 #define IRQ_FSK1_TIMEOUT_MASK 0x04
dudmuck 0:f2716e543d97 214 #define IRQ_FSK1_PREAMBLEDETECT_MASK 0x02
dudmuck 0:f2716e543d97 215 #define IRQ_FSK1_SYNCADDRESSMATCH_MASK 0x01
dudmuck 0:f2716e543d97 216 #define IRQ_FSK2_FIFOFULL_MASK 0x80
dudmuck 0:f2716e543d97 217 #define IRQ_FSK2_FIFOEMPTY_MASK 0x40
dudmuck 0:f2716e543d97 218 #define IRQ_FSK2_FIFOLEVEL_MASK 0x20
dudmuck 0:f2716e543d97 219 #define IRQ_FSK2_FIFOOVERRUN_MASK 0x10
dudmuck 0:f2716e543d97 220 #define IRQ_FSK2_PACKETSENT_MASK 0x08
dudmuck 0:f2716e543d97 221 #define IRQ_FSK2_PAYLOADREADY_MASK 0x04
dudmuck 0:f2716e543d97 222 #define IRQ_FSK2_CRCOK_MASK 0x02
dudmuck 0:f2716e543d97 223 #define IRQ_FSK2_LOWBAT_MASK 0x01
dudmuck 0:f2716e543d97 224
dudmuck 0:f2716e543d97 225 // ----------------------------------------
dudmuck 0:f2716e543d97 226 // DIO function mappings D0D1D2D3
dudmuck 0:f2716e543d97 227 #define MAP_DIO0_LORA_RXDONE 0x00 // 00------
dudmuck 0:f2716e543d97 228 #define MAP_DIO0_LORA_TXDONE 0x40 // 01------
dudmuck 0:f2716e543d97 229 #define MAP_DIO1_LORA_RXTOUT 0x00 // --00----
dudmuck 0:f2716e543d97 230 #define MAP_DIO1_LORA_NOP 0x30 // --11----
dudmuck 4:1a9a62cf220f 231 #define MAP_DIO2_LORA_NOP 0x0c // ----11--
dudmuck 0:f2716e543d97 232
dudmuck 0:f2716e543d97 233 #define MAP_DIO0_FSK_READY 0x00 // 00------ (packet sent / payload ready)
dudmuck 0:f2716e543d97 234 #define MAP_DIO1_FSK_NOP 0x30 // --11----
dudmuck 0:f2716e543d97 235 #define MAP_DIO2_FSK_TXNOP 0x04 // ----01--
dudmuck 0:f2716e543d97 236 #define MAP_DIO2_FSK_TIMEOUT 0x08 // ----10--
dudmuck 0:f2716e543d97 237
dudmuck 0:f2716e543d97 238
dudmuck 0:f2716e543d97 239 // FSK IMAGECAL defines
dudmuck 0:f2716e543d97 240 #define RF_IMAGECAL_AUTOIMAGECAL_MASK 0x7F
dudmuck 0:f2716e543d97 241 #define RF_IMAGECAL_AUTOIMAGECAL_ON 0x80
dudmuck 0:f2716e543d97 242 #define RF_IMAGECAL_AUTOIMAGECAL_OFF 0x00 // Default
dudmuck 0:f2716e543d97 243
dudmuck 0:f2716e543d97 244 #define RF_IMAGECAL_IMAGECAL_MASK 0xBF
dudmuck 0:f2716e543d97 245 #define RF_IMAGECAL_IMAGECAL_START 0x40
dudmuck 0:f2716e543d97 246
dudmuck 0:f2716e543d97 247 #define RF_IMAGECAL_IMAGECAL_RUNNING 0x20
dudmuck 0:f2716e543d97 248 #define RF_IMAGECAL_IMAGECAL_DONE 0x00 // Default
dudmuck 0:f2716e543d97 249
dudmuck 0:f2716e543d97 250
dudmuck 0:f2716e543d97 251 // RADIO STATE
dudmuck 0:f2716e543d97 252 // (initialized by radio_init(), used by radio_rand1())
dudmuck 0:f2716e543d97 253 static u1_t randbuf[16];
dudmuck 0:f2716e543d97 254 static u1_t PaSelect;
dudmuck 0:f2716e543d97 255
dudmuck 0:f2716e543d97 256 #ifdef CFG_sx1276_radio
dudmuck 0:f2716e543d97 257 #define LNA_RX_GAIN (0x20|0x1)
dudmuck 0:f2716e543d97 258 #elif defined(CFG_sx1272_radio)
dudmuck 0:f2716e543d97 259 #define LNA_RX_GAIN (0x20|0x03)
dudmuck 0:f2716e543d97 260 #else
dudmuck 0:f2716e543d97 261 #error Missing CFG_sx1272_radio/CFG_sx1276_radio
dudmuck 0:f2716e543d97 262 #endif
dudmuck 0:f2716e543d97 263
dudmuck 0:f2716e543d97 264
dudmuck 0:f2716e543d97 265 static void writeReg (u1_t addr, u1_t data ) {
dudmuck 0:f2716e543d97 266 hal_pin_nss(0);
dudmuck 0:f2716e543d97 267 hal_spi(addr | 0x80);
dudmuck 0:f2716e543d97 268 hal_spi(data);
dudmuck 0:f2716e543d97 269 hal_pin_nss(1);
dudmuck 0:f2716e543d97 270 }
dudmuck 0:f2716e543d97 271
dudmuck 0:f2716e543d97 272 static u1_t readReg (u1_t addr) {
dudmuck 0:f2716e543d97 273 hal_pin_nss(0);
dudmuck 0:f2716e543d97 274 hal_spi(addr & 0x7F);
dudmuck 0:f2716e543d97 275 u1_t val = hal_spi(0x00);
dudmuck 0:f2716e543d97 276 hal_pin_nss(1);
dudmuck 0:f2716e543d97 277 return val;
dudmuck 0:f2716e543d97 278 }
dudmuck 0:f2716e543d97 279
dudmuck 0:f2716e543d97 280 static void writeBuf (u1_t addr, xref2u1_t buf, u1_t len) {
dudmuck 0:f2716e543d97 281 hal_pin_nss(0);
dudmuck 0:f2716e543d97 282 hal_spi(addr | 0x80);
dudmuck 0:f2716e543d97 283 for (u1_t i=0; i<len; i++) {
dudmuck 0:f2716e543d97 284 hal_spi(buf[i]);
dudmuck 0:f2716e543d97 285 }
dudmuck 0:f2716e543d97 286 hal_pin_nss(1);
dudmuck 0:f2716e543d97 287 }
dudmuck 0:f2716e543d97 288
dudmuck 0:f2716e543d97 289 static void readBuf (u1_t addr, xref2u1_t buf, u1_t len) {
dudmuck 0:f2716e543d97 290 hal_pin_nss(0);
dudmuck 0:f2716e543d97 291 hal_spi(addr & 0x7F);
dudmuck 0:f2716e543d97 292 for (u1_t i=0; i<len; i++) {
dudmuck 0:f2716e543d97 293 buf[i] = hal_spi(0x00);
dudmuck 0:f2716e543d97 294 }
dudmuck 0:f2716e543d97 295 hal_pin_nss(1);
dudmuck 0:f2716e543d97 296 }
dudmuck 0:f2716e543d97 297
dudmuck 4:1a9a62cf220f 298 static void opmode (u1_t mode) {
dudmuck 0:f2716e543d97 299 hal_opmode(mode, PaSelect);
dudmuck 0:f2716e543d97 300 writeReg(RegOpMode, (readReg(RegOpMode) & ~OPMODE_MASK) | mode);
dudmuck 0:f2716e543d97 301 }
dudmuck 0:f2716e543d97 302
dudmuck 0:f2716e543d97 303 static void opmodeLora() {
dudmuck 0:f2716e543d97 304 u1_t u = OPMODE_LORA;
dudmuck 0:f2716e543d97 305 #ifdef CFG_sx1276_radio
dudmuck 0:f2716e543d97 306 u |= 0x8; // TBD: sx1276 high freq
dudmuck 0:f2716e543d97 307 #endif
dudmuck 0:f2716e543d97 308 writeReg(RegOpMode, u);
dudmuck 0:f2716e543d97 309 }
dudmuck 0:f2716e543d97 310
dudmuck 0:f2716e543d97 311 static void opmodeFSK() {
dudmuck 0:f2716e543d97 312 u1_t u = 0;
dudmuck 0:f2716e543d97 313 #ifdef CFG_sx1276_radio
dudmuck 0:f2716e543d97 314 u |= 0x8; // TBD: sx1276 high freq
dudmuck 0:f2716e543d97 315 #endif
dudmuck 0:f2716e543d97 316 writeReg(RegOpMode, u);
dudmuck 0:f2716e543d97 317 }
dudmuck 0:f2716e543d97 318
dudmuck 0:f2716e543d97 319 // configure LoRa modem (cfg1, cfg2)
dudmuck 0:f2716e543d97 320 static void configLoraModem () {
dudmuck 0:f2716e543d97 321 sf_t sf = getSf(LMIC.rps);
dudmuck 0:f2716e543d97 322
dudmuck 0:f2716e543d97 323 #ifdef CFG_sx1276_radio
dudmuck 0:f2716e543d97 324 u1_t mc1 = 0, mc2 = 0, mc3 = 0;
dudmuck 0:f2716e543d97 325
dudmuck 0:f2716e543d97 326 switch (getBw(LMIC.rps)) {
dudmuck 0:f2716e543d97 327 case BW125: mc1 |= SX1276_MC1_BW_125; break;
dudmuck 0:f2716e543d97 328 case BW250: mc1 |= SX1276_MC1_BW_250; break;
dudmuck 0:f2716e543d97 329 case BW500: mc1 |= SX1276_MC1_BW_500; break;
dudmuck 0:f2716e543d97 330 default:
dudmuck 0:f2716e543d97 331 ASSERT(0);
dudmuck 0:f2716e543d97 332 }
dudmuck 0:f2716e543d97 333 switch( getCr(LMIC.rps) ) {
dudmuck 0:f2716e543d97 334 case CR_4_5: mc1 |= SX1276_MC1_CR_4_5; break;
dudmuck 0:f2716e543d97 335 case CR_4_6: mc1 |= SX1276_MC1_CR_4_6; break;
dudmuck 0:f2716e543d97 336 case CR_4_7: mc1 |= SX1276_MC1_CR_4_7; break;
dudmuck 0:f2716e543d97 337 case CR_4_8: mc1 |= SX1276_MC1_CR_4_8; break;
dudmuck 0:f2716e543d97 338 default:
dudmuck 0:f2716e543d97 339 ASSERT(0);
dudmuck 0:f2716e543d97 340 }
dudmuck 0:f2716e543d97 341
dudmuck 0:f2716e543d97 342 if (getIh(LMIC.rps)) {
dudmuck 0:f2716e543d97 343 mc1 |= SX1276_MC1_IMPLICIT_HEADER_MODE_ON;
dudmuck 0:f2716e543d97 344 writeReg(LORARegPayloadLength, getIh(LMIC.rps)); // required length
dudmuck 0:f2716e543d97 345 }
dudmuck 0:f2716e543d97 346 // set ModemConfig1
dudmuck 0:f2716e543d97 347 writeReg(LORARegModemConfig1, mc1);
dudmuck 0:f2716e543d97 348
dudmuck 0:f2716e543d97 349 mc2 = (SX1272_MC2_SF7 + ((sf-1)<<4));
dudmuck 0:f2716e543d97 350 if (getNocrc(LMIC.rps) == 0) {
dudmuck 0:f2716e543d97 351 mc2 |= SX1276_MC2_RX_PAYLOAD_CRCON;
dudmuck 0:f2716e543d97 352 }
dudmuck 0:f2716e543d97 353 writeReg(LORARegModemConfig2, mc2);
dudmuck 0:f2716e543d97 354
dudmuck 0:f2716e543d97 355 mc3 = SX1276_MC3_AGCAUTO;
dudmuck 0:f2716e543d97 356 if ((sf == SF11 || sf == SF12) && getBw(LMIC.rps) == BW125) {
dudmuck 0:f2716e543d97 357 mc3 |= SX1276_MC3_LOW_DATA_RATE_OPTIMIZE;
dudmuck 0:f2716e543d97 358 }
dudmuck 0:f2716e543d97 359 writeReg(LORARegModemConfig3, mc3);
dudmuck 0:f2716e543d97 360 #elif defined(CFG_sx1272_radio)
dudmuck 0:f2716e543d97 361 u1_t mc1 = (getBw(LMIC.rps)<<6);
dudmuck 0:f2716e543d97 362
dudmuck 0:f2716e543d97 363 switch( getCr(LMIC.rps) ) {
dudmuck 0:f2716e543d97 364 case CR_4_5: mc1 |= SX1272_MC1_CR_4_5; break;
dudmuck 0:f2716e543d97 365 case CR_4_6: mc1 |= SX1272_MC1_CR_4_6; break;
dudmuck 0:f2716e543d97 366 case CR_4_7: mc1 |= SX1272_MC1_CR_4_7; break;
dudmuck 0:f2716e543d97 367 case CR_4_8: mc1 |= SX1272_MC1_CR_4_8; break;
dudmuck 0:f2716e543d97 368 }
dudmuck 0:f2716e543d97 369
dudmuck 0:f2716e543d97 370 if ((sf == SF11 || sf == SF12) && getBw(LMIC.rps) == BW125) {
dudmuck 0:f2716e543d97 371 mc1 |= SX1272_MC1_LOW_DATA_RATE_OPTIMIZE;
dudmuck 0:f2716e543d97 372 }
dudmuck 0:f2716e543d97 373
dudmuck 0:f2716e543d97 374 if (getNocrc(LMIC.rps) == 0) {
dudmuck 0:f2716e543d97 375 mc1 |= SX1272_MC1_RX_PAYLOAD_CRCON;
dudmuck 0:f2716e543d97 376 }
dudmuck 0:f2716e543d97 377
dudmuck 0:f2716e543d97 378 if (getIh(LMIC.rps)) {
dudmuck 0:f2716e543d97 379 mc1 |= SX1272_MC1_IMPLICIT_HEADER_MODE_ON;
dudmuck 0:f2716e543d97 380 writeReg(LORARegPayloadLength, getIh(LMIC.rps)); // required length
dudmuck 0:f2716e543d97 381 }
dudmuck 0:f2716e543d97 382 // set ModemConfig1
dudmuck 0:f2716e543d97 383 writeReg(LORARegModemConfig1, mc1);
dudmuck 0:f2716e543d97 384
dudmuck 0:f2716e543d97 385 // set ModemConfig2 (sf, AgcAutoOn=1 SymbTimeoutHi=00)
dudmuck 0:f2716e543d97 386 writeReg(LORARegModemConfig2, (SX1272_MC2_SF7 + ((sf-1)<<4)) | 0x04);
dudmuck 0:f2716e543d97 387 #else
dudmuck 0:f2716e543d97 388 #error Missing CFG_sx1272_radio/CFG_sx1276_radio
dudmuck 0:f2716e543d97 389 #endif /* CFG_sx1272_radio */
dudmuck 0:f2716e543d97 390 }
dudmuck 0:f2716e543d97 391
dudmuck 0:f2716e543d97 392 static void configChannel () {
dudmuck 0:f2716e543d97 393 // set frequency: FQ = (FRF * 32 Mhz) / (2 ^ 19)
dudmuck 0:f2716e543d97 394 u8_t frf = ((u8_t)LMIC.freq << 19) / 32000000;
dudmuck 0:f2716e543d97 395 writeReg(RegFrfMsb, (u1_t)(frf>>16));
dudmuck 0:f2716e543d97 396 writeReg(RegFrfMid, (u1_t)(frf>> 8));
dudmuck 0:f2716e543d97 397 writeReg(RegFrfLsb, (u1_t)(frf>> 0));
dudmuck 0:f2716e543d97 398 }
dudmuck 0:f2716e543d97 399
dudmuck 3:d87012f45bf6 400 DigitalOut pd2(PD_2); // power amplifier voltage control pin
dudmuck 0:f2716e543d97 401
dudmuck 0:f2716e543d97 402 static void configPower () {
dudmuck 0:f2716e543d97 403 #ifdef CFG_sx1276_radio
dudmuck 0:f2716e543d97 404 // no boost used for now
dudmuck 0:f2716e543d97 405 s1_t pw = (s1_t)LMIC.txpow;
dudmuck 0:f2716e543d97 406 if(pw >= 17) {
dudmuck 0:f2716e543d97 407 pw = 15;
dudmuck 0:f2716e543d97 408 } else if(pw < 2) {
dudmuck 0:f2716e543d97 409 pw = 2;
dudmuck 0:f2716e543d97 410 }
dudmuck 0:f2716e543d97 411 // check board type for BOOST pin
dudmuck 0:f2716e543d97 412 writeReg(RegPaConfig, (u1_t)(0x80|(pw&0xf)));
dudmuck 0:f2716e543d97 413 writeReg(RegPaDac, readReg(RegPaDac)|0x4);
dudmuck 0:f2716e543d97 414
dudmuck 0:f2716e543d97 415 #elif defined(CFG_sx1272_radio)
dudmuck 0:f2716e543d97 416 // set PA config (2-17 dBm using PA_BOOST)
dudmuck 0:f2716e543d97 417 s1_t pw = (s1_t)LMIC.txpow;
dudmuck 2:edb5d1f3deeb 418 /*if(pw > 17) {
dudmuck 0:f2716e543d97 419 pw = 17;
dudmuck 0:f2716e543d97 420 } else if(pw < 2) {
dudmuck 0:f2716e543d97 421 pw = 2;
dudmuck 2:edb5d1f3deeb 422 }*/
dudmuck 2:edb5d1f3deeb 423 /* NA-mote TX power config: */
dudmuck 2:edb5d1f3deeb 424 if (pw > 23) {
dudmuck 2:edb5d1f3deeb 425 // use RFO with external amplifier
dudmuck 2:edb5d1f3deeb 426 PaSelect = 0x00; // use RFO
dudmuck 2:edb5d1f3deeb 427 writeReg(RegPaConfig, (u1_t)(PaSelect|(pw-25)));
dudmuck 3:d87012f45bf6 428 if (pw > 26)
dudmuck 3:d87012f45bf6 429 pd2 = 1;
dudmuck 3:d87012f45bf6 430 else
dudmuck 3:d87012f45bf6 431 pd2 = 0;
dudmuck 2:edb5d1f3deeb 432 } else {
dudmuck 3:d87012f45bf6 433 // use PA_BOOST direct to antenna
dudmuck 2:edb5d1f3deeb 434 PaSelect = 0x80; // use PA_BOOST
dudmuck 2:edb5d1f3deeb 435 if (pw > 17)
dudmuck 2:edb5d1f3deeb 436 pw = 17;
dudmuck 2:edb5d1f3deeb 437 writeReg(RegPaConfig, (u1_t)(PaSelect|(pw-2)));
dudmuck 0:f2716e543d97 438 }
dudmuck 0:f2716e543d97 439
dudmuck 2:edb5d1f3deeb 440
dudmuck 0:f2716e543d97 441 #else
dudmuck 0:f2716e543d97 442 #error Missing CFG_sx1272_radio/CFG_sx1276_radio
dudmuck 0:f2716e543d97 443 #endif /* CFG_sx1272_radio */
dudmuck 0:f2716e543d97 444 }
dudmuck 0:f2716e543d97 445
dudmuck 0:f2716e543d97 446 static void txfsk () {
dudmuck 0:f2716e543d97 447 // select FSK modem (from sleep mode)
dudmuck 0:f2716e543d97 448 writeReg(RegOpMode, 0x10); // FSK, BT=0.5
dudmuck 0:f2716e543d97 449 ASSERT(readReg(RegOpMode) == 0x10);
dudmuck 0:f2716e543d97 450 // enter standby mode (required for FIFO loading))
dudmuck 0:f2716e543d97 451 opmode(OPMODE_STANDBY);
dudmuck 0:f2716e543d97 452 // set bitrate
dudmuck 0:f2716e543d97 453 writeReg(FSKRegBitrateMsb, 0x02); // 50kbps
dudmuck 0:f2716e543d97 454 writeReg(FSKRegBitrateLsb, 0x80);
dudmuck 0:f2716e543d97 455 // set frequency deviation
dudmuck 0:f2716e543d97 456 writeReg(FSKRegFdevMsb, 0x01); // +/- 25kHz
dudmuck 0:f2716e543d97 457 writeReg(FSKRegFdevLsb, 0x99);
dudmuck 0:f2716e543d97 458 // frame and packet handler settings
dudmuck 0:f2716e543d97 459 writeReg(FSKRegPreambleMsb, 0x00);
dudmuck 0:f2716e543d97 460 writeReg(FSKRegPreambleLsb, 0x05);
dudmuck 0:f2716e543d97 461 writeReg(FSKRegSyncConfig, 0x12);
dudmuck 0:f2716e543d97 462 writeReg(FSKRegPacketConfig1, 0xD0);
dudmuck 0:f2716e543d97 463 writeReg(FSKRegPacketConfig2, 0x40);
dudmuck 0:f2716e543d97 464 writeReg(FSKRegSyncValue1, 0xC1);
dudmuck 0:f2716e543d97 465 writeReg(FSKRegSyncValue2, 0x94);
dudmuck 0:f2716e543d97 466 writeReg(FSKRegSyncValue3, 0xC1);
dudmuck 0:f2716e543d97 467 // configure frequency
dudmuck 0:f2716e543d97 468 configChannel();
dudmuck 0:f2716e543d97 469 // configure output power
dudmuck 0:f2716e543d97 470 configPower();
dudmuck 0:f2716e543d97 471
dudmuck 0:f2716e543d97 472 // set the IRQ mapping DIO0=PacketSent DIO1=NOP DIO2=NOP
dudmuck 0:f2716e543d97 473 writeReg(RegDioMapping1, MAP_DIO0_FSK_READY|MAP_DIO1_FSK_NOP|MAP_DIO2_FSK_TXNOP);
dudmuck 0:f2716e543d97 474
dudmuck 0:f2716e543d97 475 // initialize the payload size and address pointers
dudmuck 0:f2716e543d97 476 writeReg(FSKRegPayloadLength, LMIC.dataLen+1); // (insert length byte into payload))
dudmuck 0:f2716e543d97 477
dudmuck 0:f2716e543d97 478 // download length byte and buffer to the radio FIFO
dudmuck 0:f2716e543d97 479 writeReg(RegFifo, LMIC.dataLen);
dudmuck 0:f2716e543d97 480 writeBuf(RegFifo, LMIC.frame, LMIC.dataLen);
dudmuck 0:f2716e543d97 481
dudmuck 0:f2716e543d97 482 // enable antenna switch for TX
dudmuck 2:edb5d1f3deeb 483 //hal_pin_rxtx(1); usint hal_opmode
dudmuck 0:f2716e543d97 484
dudmuck 0:f2716e543d97 485 // now we actually start the transmission
dudmuck 0:f2716e543d97 486 opmode(OPMODE_TX);
dudmuck 0:f2716e543d97 487 }
dudmuck 0:f2716e543d97 488
dudmuck 0:f2716e543d97 489 static void txlora () {
dudmuck 0:f2716e543d97 490 // select LoRa modem (from sleep mode)
dudmuck 0:f2716e543d97 491 //writeReg(RegOpMode, OPMODE_LORA);
dudmuck 0:f2716e543d97 492 opmodeLora();
dudmuck 0:f2716e543d97 493 ASSERT((readReg(RegOpMode) & OPMODE_LORA) != 0);
dudmuck 0:f2716e543d97 494
dudmuck 0:f2716e543d97 495 // enter standby mode (required for FIFO loading))
dudmuck 0:f2716e543d97 496 opmode(OPMODE_STANDBY);
dudmuck 0:f2716e543d97 497 // configure LoRa modem (cfg1, cfg2)
dudmuck 0:f2716e543d97 498 configLoraModem();
dudmuck 0:f2716e543d97 499 // configure frequency
dudmuck 0:f2716e543d97 500 configChannel();
dudmuck 0:f2716e543d97 501 // configure output power
dudmuck 0:f2716e543d97 502 writeReg(RegPaRamp, (readReg(RegPaRamp) & 0xF0) | 0x08); // set PA ramp-up time 50 uSec
dudmuck 0:f2716e543d97 503 configPower();
dudmuck 0:f2716e543d97 504 // set sync word
dudmuck 0:f2716e543d97 505 writeReg(LORARegSyncWord, LORA_MAC_PREAMBLE);
dudmuck 0:f2716e543d97 506
dudmuck 0:f2716e543d97 507 // set the IRQ mapping DIO0=TxDone DIO1=NOP DIO2=NOP
dudmuck 0:f2716e543d97 508 writeReg(RegDioMapping1, MAP_DIO0_LORA_TXDONE|MAP_DIO1_LORA_NOP|MAP_DIO2_LORA_NOP);
dudmuck 0:f2716e543d97 509 // clear all radio IRQ flags
dudmuck 0:f2716e543d97 510 writeReg(LORARegIrqFlags, 0xFF);
dudmuck 0:f2716e543d97 511 // mask all IRQs but TxDone
dudmuck 0:f2716e543d97 512 writeReg(LORARegIrqFlagsMask, ~IRQ_LORA_TXDONE_MASK);
dudmuck 0:f2716e543d97 513
dudmuck 0:f2716e543d97 514 // initialize the payload size and address pointers
dudmuck 0:f2716e543d97 515 writeReg(LORARegFifoTxBaseAddr, 0x00);
dudmuck 0:f2716e543d97 516 writeReg(LORARegFifoAddrPtr, 0x00);
dudmuck 0:f2716e543d97 517 writeReg(LORARegPayloadLength, LMIC.dataLen);
dudmuck 0:f2716e543d97 518
dudmuck 0:f2716e543d97 519 // download buffer to the radio FIFO
dudmuck 0:f2716e543d97 520 writeBuf(RegFifo, LMIC.frame, LMIC.dataLen);
dudmuck 0:f2716e543d97 521
dudmuck 0:f2716e543d97 522 // enable antenna switch for TX
dudmuck 2:edb5d1f3deeb 523 //hal_pin_rxtx(1); using hal_opmode
dudmuck 0:f2716e543d97 524
dudmuck 0:f2716e543d97 525 // now we actually start the transmission
dudmuck 0:f2716e543d97 526 opmode(OPMODE_TX);
dudmuck 0:f2716e543d97 527 }
dudmuck 0:f2716e543d97 528
dudmuck 0:f2716e543d97 529 // start transmitter (buf=LMIC.frame, len=LMIC.dataLen)
dudmuck 0:f2716e543d97 530 static void starttx () {
dudmuck 0:f2716e543d97 531 ASSERT( (readReg(RegOpMode) & OPMODE_MASK) == OPMODE_SLEEP );
dudmuck 0:f2716e543d97 532 if(getSf(LMIC.rps) == FSK) { // FSK modem
dudmuck 0:f2716e543d97 533 txfsk();
dudmuck 0:f2716e543d97 534 } else { // LoRa modem
dudmuck 0:f2716e543d97 535 txlora();
dudmuck 0:f2716e543d97 536 }
dudmuck 0:f2716e543d97 537 // the radio will go back to STANDBY mode as soon as the TX is finished
dudmuck 0:f2716e543d97 538 // the corresponding IRQ will inform us about completion.
dudmuck 0:f2716e543d97 539 }
dudmuck 0:f2716e543d97 540
dudmuck 0:f2716e543d97 541 enum { RXMODE_SINGLE, RXMODE_SCAN, RXMODE_RSSI };
dudmuck 0:f2716e543d97 542
dudmuck 0:f2716e543d97 543 static const u1_t rxlorairqmask[] = {
dudmuck 0:f2716e543d97 544 [RXMODE_SINGLE] = IRQ_LORA_RXDONE_MASK|IRQ_LORA_RXTOUT_MASK,
dudmuck 0:f2716e543d97 545 [RXMODE_SCAN] = IRQ_LORA_RXDONE_MASK,
dudmuck 0:f2716e543d97 546 [RXMODE_RSSI] = 0x00,
dudmuck 0:f2716e543d97 547 };
dudmuck 0:f2716e543d97 548
dudmuck 0:f2716e543d97 549 // start LoRa receiver (time=LMIC.rxtime, timeout=LMIC.rxsyms, result=LMIC.frame[LMIC.dataLen])
dudmuck 0:f2716e543d97 550 static void rxlora (u1_t rxmode) {
dudmuck 0:f2716e543d97 551 // select LoRa modem (from sleep mode)
dudmuck 0:f2716e543d97 552 opmodeLora();
dudmuck 0:f2716e543d97 553 ASSERT((readReg(RegOpMode) & OPMODE_LORA) != 0);
dudmuck 0:f2716e543d97 554 // enter standby mode (warm up))
dudmuck 0:f2716e543d97 555 opmode(OPMODE_STANDBY);
dudmuck 0:f2716e543d97 556 // don't use MAC settings at startup
dudmuck 0:f2716e543d97 557 if(rxmode == RXMODE_RSSI) { // use fixed settings for rssi scan
dudmuck 0:f2716e543d97 558 writeReg(LORARegModemConfig1, RXLORA_RXMODE_RSSI_REG_MODEM_CONFIG1);
dudmuck 0:f2716e543d97 559 writeReg(LORARegModemConfig2, RXLORA_RXMODE_RSSI_REG_MODEM_CONFIG2);
dudmuck 0:f2716e543d97 560 } else { // single or continuous rx mode
dudmuck 0:f2716e543d97 561 // configure LoRa modem (cfg1, cfg2)
dudmuck 0:f2716e543d97 562 configLoraModem();
dudmuck 0:f2716e543d97 563 // configure frequency
dudmuck 0:f2716e543d97 564 configChannel();
dudmuck 0:f2716e543d97 565 }
dudmuck 0:f2716e543d97 566 // set LNA gain
dudmuck 0:f2716e543d97 567 writeReg(RegLna, LNA_RX_GAIN);
dudmuck 0:f2716e543d97 568 // set max payload size
dudmuck 0:f2716e543d97 569 writeReg(LORARegPayloadMaxLength, 64);
dudmuck 0:f2716e543d97 570 // use inverted I/Q signal (prevent mote-to-mote communication)
dudmuck 0:f2716e543d97 571 writeReg(LORARegInvertIQ, readReg(LORARegInvertIQ)|(1<<6));
dudmuck 0:f2716e543d97 572 // set symbol timeout (for single rx)
dudmuck 0:f2716e543d97 573 writeReg(LORARegSymbTimeoutLsb, LMIC.rxsyms);
dudmuck 0:f2716e543d97 574 // set sync word
dudmuck 0:f2716e543d97 575 writeReg(LORARegSyncWord, LORA_MAC_PREAMBLE);
dudmuck 0:f2716e543d97 576
dudmuck 0:f2716e543d97 577 // configure DIO mapping DIO0=RxDone DIO1=RxTout DIO2=NOP
dudmuck 0:f2716e543d97 578 writeReg(RegDioMapping1, MAP_DIO0_LORA_RXDONE|MAP_DIO1_LORA_RXTOUT|MAP_DIO2_LORA_NOP);
dudmuck 0:f2716e543d97 579 // clear all radio IRQ flags
dudmuck 0:f2716e543d97 580 writeReg(LORARegIrqFlags, 0xFF);
dudmuck 0:f2716e543d97 581 // enable required radio IRQs
dudmuck 0:f2716e543d97 582 writeReg(LORARegIrqFlagsMask, ~rxlorairqmask[rxmode]);
dudmuck 0:f2716e543d97 583
dudmuck 0:f2716e543d97 584 // enable antenna switch for RX
dudmuck 2:edb5d1f3deeb 585 //hal_pin_rxtx(0); using hal_opmode
dudmuck 0:f2716e543d97 586
dudmuck 0:f2716e543d97 587 // now instruct the radio to receive
dudmuck 0:f2716e543d97 588 if (rxmode == RXMODE_SINGLE) { // single rx
dudmuck 0:f2716e543d97 589 hal_waitUntil(LMIC.rxtime); // busy wait until exact rx time
dudmuck 0:f2716e543d97 590 opmode(OPMODE_RX_SINGLE);
dudmuck 0:f2716e543d97 591 } else { // continous rx (scan or rssi)
dudmuck 0:f2716e543d97 592 opmode(OPMODE_RX);
dudmuck 0:f2716e543d97 593 }
dudmuck 0:f2716e543d97 594 }
dudmuck 0:f2716e543d97 595
dudmuck 0:f2716e543d97 596 static void rxfsk (u1_t rxmode) {
dudmuck 0:f2716e543d97 597 // only single rx (no continuous scanning, no noise sampling)
dudmuck 0:f2716e543d97 598 ASSERT( rxmode == RXMODE_SINGLE );
dudmuck 0:f2716e543d97 599 // select FSK modem (from sleep mode)
dudmuck 0:f2716e543d97 600 //writeReg(RegOpMode, 0x00); // (not LoRa)
dudmuck 0:f2716e543d97 601 opmodeFSK();
dudmuck 0:f2716e543d97 602 ASSERT((readReg(RegOpMode) & OPMODE_LORA) == 0);
dudmuck 0:f2716e543d97 603 // enter standby mode (warm up))
dudmuck 0:f2716e543d97 604 opmode(OPMODE_STANDBY);
dudmuck 0:f2716e543d97 605 // configure frequency
dudmuck 0:f2716e543d97 606 configChannel();
dudmuck 0:f2716e543d97 607 // set LNA gain
dudmuck 0:f2716e543d97 608 //writeReg(RegLna, 0x20|0x03); // max gain, boost enable
dudmuck 0:f2716e543d97 609 writeReg(RegLna, LNA_RX_GAIN);
dudmuck 0:f2716e543d97 610 // configure receiver
dudmuck 0:f2716e543d97 611 writeReg(FSKRegRxConfig, 0x1E); // AFC auto, AGC, trigger on preamble?!?
dudmuck 0:f2716e543d97 612 // set receiver bandwidth
dudmuck 0:f2716e543d97 613 writeReg(FSKRegRxBw, 0x0B); // 50kHz SSb
dudmuck 0:f2716e543d97 614 // set AFC bandwidth
dudmuck 0:f2716e543d97 615 writeReg(FSKRegAfcBw, 0x12); // 83.3kHz SSB
dudmuck 0:f2716e543d97 616 // set preamble detection
dudmuck 0:f2716e543d97 617 writeReg(FSKRegPreambleDetect, 0xAA); // enable, 2 bytes, 10 chip errors
dudmuck 0:f2716e543d97 618 // set sync config
dudmuck 0:f2716e543d97 619 writeReg(FSKRegSyncConfig, 0x12); // no auto restart, preamble 0xAA, enable, fill FIFO, 3 bytes sync
dudmuck 0:f2716e543d97 620 // set packet config
dudmuck 0:f2716e543d97 621 writeReg(FSKRegPacketConfig1, 0xD8); // var-length, whitening, crc, no auto-clear, no adr filter
dudmuck 0:f2716e543d97 622 writeReg(FSKRegPacketConfig2, 0x40); // packet mode
dudmuck 0:f2716e543d97 623 // set sync value
dudmuck 0:f2716e543d97 624 writeReg(FSKRegSyncValue1, 0xC1);
dudmuck 0:f2716e543d97 625 writeReg(FSKRegSyncValue2, 0x94);
dudmuck 0:f2716e543d97 626 writeReg(FSKRegSyncValue3, 0xC1);
dudmuck 0:f2716e543d97 627 // set preamble timeout
dudmuck 0:f2716e543d97 628 writeReg(FSKRegRxTimeout2, 0xFF);//(LMIC.rxsyms+1)/2);
dudmuck 0:f2716e543d97 629 // set bitrate
dudmuck 0:f2716e543d97 630 writeReg(FSKRegBitrateMsb, 0x02); // 50kbps
dudmuck 0:f2716e543d97 631 writeReg(FSKRegBitrateLsb, 0x80);
dudmuck 0:f2716e543d97 632 // set frequency deviation
dudmuck 0:f2716e543d97 633 writeReg(FSKRegFdevMsb, 0x01); // +/- 25kHz
dudmuck 0:f2716e543d97 634 writeReg(FSKRegFdevLsb, 0x99);
dudmuck 0:f2716e543d97 635
dudmuck 0:f2716e543d97 636 // configure DIO mapping DIO0=PayloadReady DIO1=NOP DIO2=TimeOut
dudmuck 0:f2716e543d97 637 writeReg(RegDioMapping1, MAP_DIO0_FSK_READY|MAP_DIO1_FSK_NOP|MAP_DIO2_FSK_TIMEOUT);
dudmuck 0:f2716e543d97 638
dudmuck 0:f2716e543d97 639 // enable antenna switch for RX
dudmuck 2:edb5d1f3deeb 640 //hal_pin_rxtx(0); using hal_opmode
dudmuck 0:f2716e543d97 641
dudmuck 0:f2716e543d97 642 // now instruct the radio to receive
dudmuck 0:f2716e543d97 643 hal_waitUntil(LMIC.rxtime); // busy wait until exact rx time
dudmuck 0:f2716e543d97 644 opmode(OPMODE_RX); // no single rx mode available in FSK
dudmuck 0:f2716e543d97 645 }
dudmuck 0:f2716e543d97 646
dudmuck 0:f2716e543d97 647 static void startrx (u1_t rxmode) {
dudmuck 0:f2716e543d97 648 ASSERT( (readReg(RegOpMode) & OPMODE_MASK) == OPMODE_SLEEP );
dudmuck 0:f2716e543d97 649 if(getSf(LMIC.rps) == FSK) { // FSK modem
dudmuck 0:f2716e543d97 650 rxfsk(rxmode);
dudmuck 0:f2716e543d97 651 } else { // LoRa modem
dudmuck 0:f2716e543d97 652 rxlora(rxmode);
dudmuck 0:f2716e543d97 653 }
dudmuck 0:f2716e543d97 654 // the radio will go back to STANDBY mode as soon as the RX is finished
dudmuck 0:f2716e543d97 655 // or timed out, and the corresponding IRQ will inform us about completion.
dudmuck 0:f2716e543d97 656 }
dudmuck 0:f2716e543d97 657
dudmuck 0:f2716e543d97 658 // get random seed from wideband noise rssi
dudmuck 0:f2716e543d97 659 void radio_init () {
dudmuck 0:f2716e543d97 660 hal_disableIRQs();
dudmuck 0:f2716e543d97 661
dudmuck 0:f2716e543d97 662 // manually reset radio
dudmuck 0:f2716e543d97 663 #ifdef CFG_sx1276_radio
dudmuck 0:f2716e543d97 664 hal_pin_rst(0); // drive RST pin low
dudmuck 0:f2716e543d97 665 #else
dudmuck 0:f2716e543d97 666 hal_pin_rst(1); // drive RST pin high
dudmuck 0:f2716e543d97 667 #endif
dudmuck 0:f2716e543d97 668 hal_waitUntil(os_getTime()+ms2osticks(1)); // wait >100us
dudmuck 0:f2716e543d97 669 hal_pin_rst(2); // configure RST pin floating!
dudmuck 0:f2716e543d97 670 hal_waitUntil(os_getTime()+ms2osticks(5)); // wait 5ms
dudmuck 0:f2716e543d97 671
dudmuck 0:f2716e543d97 672 opmode(OPMODE_SLEEP);
dudmuck 0:f2716e543d97 673
dudmuck 0:f2716e543d97 674 // some sanity checks, e.g., read version number
dudmuck 0:f2716e543d97 675 u1_t v = readReg(RegVersion);
dudmuck 0:f2716e543d97 676 #ifdef CFG_sx1276_radio
dudmuck 0:f2716e543d97 677 ASSERT(v == 0x12 );
dudmuck 0:f2716e543d97 678 #elif defined(CFG_sx1272_radio)
dudmuck 0:f2716e543d97 679 ASSERT(v == 0x22);
dudmuck 0:f2716e543d97 680 #else
dudmuck 0:f2716e543d97 681 #error Missing CFG_sx1272_radio/CFG_sx1276_radio
dudmuck 0:f2716e543d97 682 #endif
dudmuck 0:f2716e543d97 683 // seed 15-byte randomness via noise rssi
dudmuck 0:f2716e543d97 684 rxlora(RXMODE_RSSI);
dudmuck 0:f2716e543d97 685 while( (readReg(RegOpMode) & OPMODE_MASK) != OPMODE_RX ); // continuous rx
dudmuck 0:f2716e543d97 686 for(int i=1; i<16; i++) {
dudmuck 0:f2716e543d97 687 for(int j=0; j<8; j++) {
dudmuck 0:f2716e543d97 688 u1_t b; // wait for two non-identical subsequent least-significant bits
dudmuck 0:f2716e543d97 689 while( (b = readReg(LORARegRssiWideband) & 0x01) == (readReg(LORARegRssiWideband) & 0x01) );
dudmuck 0:f2716e543d97 690 randbuf[i] = (randbuf[i] << 1) | b;
dudmuck 0:f2716e543d97 691 }
dudmuck 0:f2716e543d97 692 }
dudmuck 0:f2716e543d97 693 randbuf[0] = 16; // set initial index
dudmuck 0:f2716e543d97 694
dudmuck 0:f2716e543d97 695 #ifdef CFG_sx1276mb1_board
dudmuck 0:f2716e543d97 696 // chain calibration
dudmuck 0:f2716e543d97 697 writeReg(RegPaConfig, 0);
dudmuck 0:f2716e543d97 698
dudmuck 0:f2716e543d97 699 // Launch Rx chain calibration for LF band
dudmuck 0:f2716e543d97 700 writeReg(FSKRegImageCal, (readReg(FSKRegImageCal) & RF_IMAGECAL_IMAGECAL_MASK)|RF_IMAGECAL_IMAGECAL_START);
dudmuck 0:f2716e543d97 701 while((readReg(FSKRegImageCal)&RF_IMAGECAL_IMAGECAL_RUNNING) == RF_IMAGECAL_IMAGECAL_RUNNING){ ; }
dudmuck 0:f2716e543d97 702
dudmuck 0:f2716e543d97 703 // Sets a Frequency in HF band
dudmuck 0:f2716e543d97 704 u4_t frf = 868000000;
dudmuck 0:f2716e543d97 705 writeReg(RegFrfMsb, (u1_t)(frf>>16));
dudmuck 0:f2716e543d97 706 writeReg(RegFrfMid, (u1_t)(frf>> 8));
dudmuck 0:f2716e543d97 707 writeReg(RegFrfLsb, (u1_t)(frf>> 0));
dudmuck 0:f2716e543d97 708
dudmuck 0:f2716e543d97 709 // Launch Rx chain calibration for HF band
dudmuck 0:f2716e543d97 710 writeReg(FSKRegImageCal, (readReg(FSKRegImageCal) & RF_IMAGECAL_IMAGECAL_MASK)|RF_IMAGECAL_IMAGECAL_START);
dudmuck 0:f2716e543d97 711 while((readReg(FSKRegImageCal) & RF_IMAGECAL_IMAGECAL_RUNNING) == RF_IMAGECAL_IMAGECAL_RUNNING) { ; }
dudmuck 0:f2716e543d97 712 #endif /* CFG_sx1276mb1_board */
dudmuck 0:f2716e543d97 713
dudmuck 0:f2716e543d97 714 /* SF12/500KHz RX improvement (0x1d/0x19 choice): must match setting of LORARegInvertIQ */
dudmuck 0:f2716e543d97 715 writeReg(LORARegTimingInvert, 0x19);
dudmuck 0:f2716e543d97 716
dudmuck 0:f2716e543d97 717 opmode(OPMODE_SLEEP);
dudmuck 0:f2716e543d97 718
dudmuck 0:f2716e543d97 719 hal_enableIRQs();
dudmuck 0:f2716e543d97 720 }
dudmuck 0:f2716e543d97 721
dudmuck 0:f2716e543d97 722 // return next random byte derived from seed buffer
dudmuck 0:f2716e543d97 723 // (buf[0] holds index of next byte to be returned)
dudmuck 0:f2716e543d97 724 u1_t radio_rand1 () {
dudmuck 0:f2716e543d97 725 u1_t i = randbuf[0];
dudmuck 0:f2716e543d97 726 ASSERT( i != 0 );
dudmuck 0:f2716e543d97 727 if( i==16 ) {
dudmuck 0:f2716e543d97 728 os_aes(AES_ENC, randbuf, 16); // encrypt seed with any key
dudmuck 0:f2716e543d97 729 i = 0;
dudmuck 0:f2716e543d97 730 }
dudmuck 0:f2716e543d97 731 u1_t v = randbuf[i++];
dudmuck 0:f2716e543d97 732 randbuf[0] = i;
dudmuck 0:f2716e543d97 733 return v;
dudmuck 0:f2716e543d97 734 }
dudmuck 0:f2716e543d97 735
dudmuck 0:f2716e543d97 736 u1_t radio_rssi () {
dudmuck 0:f2716e543d97 737 hal_disableIRQs();
dudmuck 0:f2716e543d97 738 u1_t r = readReg(LORARegRssiValue);
dudmuck 0:f2716e543d97 739 hal_enableIRQs();
dudmuck 0:f2716e543d97 740 return r;
dudmuck 0:f2716e543d97 741 }
dudmuck 0:f2716e543d97 742
dudmuck 0:f2716e543d97 743 static const u2_t LORA_RXDONE_FIXUP[] = {
dudmuck 0:f2716e543d97 744 [FSK] = us2osticks(0), // ( 0 ticks)
dudmuck 0:f2716e543d97 745 [SF7] = us2osticks(0), // ( 0 ticks)
dudmuck 0:f2716e543d97 746 [SF8] = us2osticks(1648), // ( 54 ticks)
dudmuck 0:f2716e543d97 747 [SF9] = us2osticks(3265), // ( 107 ticks)
dudmuck 0:f2716e543d97 748 [SF10] = us2osticks(7049), // ( 231 ticks)
dudmuck 0:f2716e543d97 749 [SF11] = us2osticks(13641), // ( 447 ticks)
dudmuck 0:f2716e543d97 750 [SF12] = us2osticks(31189), // (1022 ticks)
dudmuck 0:f2716e543d97 751 };
dudmuck 0:f2716e543d97 752
dudmuck 0:f2716e543d97 753 // called by hal ext IRQ handler
dudmuck 0:f2716e543d97 754 // (radio goes to stanby mode after tx/rx operations)
dudmuck 0:f2716e543d97 755 void radio_irq_handler (u1_t dio) {
dudmuck 0:f2716e543d97 756 ostime_t now = os_getTime();
dudmuck 0:f2716e543d97 757 if( (readReg(RegOpMode) & OPMODE_LORA) != 0) { // LORA modem
dudmuck 0:f2716e543d97 758 u1_t flags = readReg(LORARegIrqFlags);
dudmuck 0:f2716e543d97 759 if( flags & IRQ_LORA_TXDONE_MASK ) {
dudmuck 0:f2716e543d97 760 // save exact tx time
dudmuck 0:f2716e543d97 761 LMIC.txend = now - us2osticks(43); // TXDONE FIXUP
dudmuck 0:f2716e543d97 762 } else if( flags & IRQ_LORA_RXDONE_MASK ) {
dudmuck 0:f2716e543d97 763 // save exact rx time
dudmuck 0:f2716e543d97 764 if(getBw(LMIC.rps) == BW125) {
dudmuck 0:f2716e543d97 765 now -= LORA_RXDONE_FIXUP[getSf(LMIC.rps)];
dudmuck 0:f2716e543d97 766 }
dudmuck 0:f2716e543d97 767 LMIC.rxtime = now;
dudmuck 0:f2716e543d97 768 // read the PDU and inform the MAC that we received something
dudmuck 0:f2716e543d97 769 LMIC.dataLen = (readReg(LORARegModemConfig1) & SX1272_MC1_IMPLICIT_HEADER_MODE_ON) ?
dudmuck 0:f2716e543d97 770 readReg(LORARegPayloadLength) : readReg(LORARegRxNbBytes);
dudmuck 0:f2716e543d97 771 // set FIFO read address pointer
dudmuck 0:f2716e543d97 772 writeReg(LORARegFifoAddrPtr, readReg(LORARegFifoRxCurrentAddr));
dudmuck 0:f2716e543d97 773 // now read the FIFO
dudmuck 0:f2716e543d97 774 readBuf(RegFifo, LMIC.frame, LMIC.dataLen);
dudmuck 0:f2716e543d97 775 // read rx quality parameters
dudmuck 0:f2716e543d97 776 LMIC.snr = readReg(LORARegPktSnrValue); // SNR [dB] * 4
dudmuck 0:f2716e543d97 777 LMIC.rssi = readReg(LORARegPktRssiValue) - 125 + 64; // RSSI [dBm] (-196...+63)
dudmuck 0:f2716e543d97 778 } else if( flags & IRQ_LORA_RXTOUT_MASK ) {
dudmuck 0:f2716e543d97 779 // indicate timeout
dudmuck 0:f2716e543d97 780 LMIC.dataLen = 0;
dudmuck 0:f2716e543d97 781 }
dudmuck 0:f2716e543d97 782 // mask all radio IRQs
dudmuck 0:f2716e543d97 783 writeReg(LORARegIrqFlagsMask, 0xFF);
dudmuck 0:f2716e543d97 784 // clear radio IRQ flags
dudmuck 0:f2716e543d97 785 writeReg(LORARegIrqFlags, 0xFF);
dudmuck 0:f2716e543d97 786 } else { // FSK modem
dudmuck 0:f2716e543d97 787 u1_t flags1 = readReg(FSKRegIrqFlags1);
dudmuck 0:f2716e543d97 788 u1_t flags2 = readReg(FSKRegIrqFlags2);
dudmuck 0:f2716e543d97 789 if( flags2 & IRQ_FSK2_PACKETSENT_MASK ) {
dudmuck 0:f2716e543d97 790 // save exact tx time
dudmuck 0:f2716e543d97 791 LMIC.txend = now;
dudmuck 0:f2716e543d97 792 } else if( flags2 & IRQ_FSK2_PAYLOADREADY_MASK ) {
dudmuck 0:f2716e543d97 793 // save exact rx time
dudmuck 0:f2716e543d97 794 LMIC.rxtime = now;
dudmuck 0:f2716e543d97 795 // read the PDU and inform the MAC that we received something
dudmuck 0:f2716e543d97 796 LMIC.dataLen = readReg(FSKRegPayloadLength);
dudmuck 0:f2716e543d97 797 // now read the FIFO
dudmuck 0:f2716e543d97 798 readBuf(RegFifo, LMIC.frame, LMIC.dataLen);
dudmuck 0:f2716e543d97 799 // read rx quality parameters
dudmuck 0:f2716e543d97 800 LMIC.snr = 0; // determine snr
dudmuck 0:f2716e543d97 801 LMIC.rssi = 0; // determine rssi
dudmuck 0:f2716e543d97 802 } else if( flags1 & IRQ_FSK1_TIMEOUT_MASK ) {
dudmuck 0:f2716e543d97 803 // indicate timeout
dudmuck 0:f2716e543d97 804 LMIC.dataLen = 0;
dudmuck 0:f2716e543d97 805 } else {
dudmuck 0:f2716e543d97 806 while(1);
dudmuck 0:f2716e543d97 807 }
dudmuck 0:f2716e543d97 808 }
dudmuck 0:f2716e543d97 809 // go from stanby to sleep
dudmuck 0:f2716e543d97 810 opmode(OPMODE_SLEEP);
dudmuck 0:f2716e543d97 811 // run os job (use preset func ptr)
dudmuck 0:f2716e543d97 812 os_setCallback(&LMIC.osjob, LMIC.osjob.func);
dudmuck 0:f2716e543d97 813 }
dudmuck 0:f2716e543d97 814
dudmuck 0:f2716e543d97 815 void os_radio (u1_t mode) {
dudmuck 0:f2716e543d97 816 hal_disableIRQs();
dudmuck 0:f2716e543d97 817 switch (mode) {
dudmuck 0:f2716e543d97 818 case RADIO_RST:
dudmuck 0:f2716e543d97 819 // put radio to sleep
dudmuck 0:f2716e543d97 820 opmode(OPMODE_SLEEP);
dudmuck 0:f2716e543d97 821 break;
dudmuck 0:f2716e543d97 822
dudmuck 0:f2716e543d97 823 case RADIO_TX:
dudmuck 0:f2716e543d97 824 // transmit frame now
dudmuck 0:f2716e543d97 825 starttx(); // buf=LMIC.frame, len=LMIC.dataLen
dudmuck 0:f2716e543d97 826 break;
dudmuck 0:f2716e543d97 827
dudmuck 0:f2716e543d97 828 case RADIO_RX:
dudmuck 0:f2716e543d97 829 // receive frame now (exactly at rxtime)
dudmuck 0:f2716e543d97 830 startrx(RXMODE_SINGLE); // buf=LMIC.frame, time=LMIC.rxtime, timeout=LMIC.rxsyms
dudmuck 0:f2716e543d97 831 break;
dudmuck 0:f2716e543d97 832
dudmuck 0:f2716e543d97 833 case RADIO_RXON:
dudmuck 0:f2716e543d97 834 // start scanning for beacon now
dudmuck 0:f2716e543d97 835 startrx(RXMODE_SCAN); // buf=LMIC.frame
dudmuck 0:f2716e543d97 836 break;
dudmuck 0:f2716e543d97 837 }
dudmuck 0:f2716e543d97 838 hal_enableIRQs();
dudmuck 0:f2716e543d97 839 }