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:
Fri Dec 04 01:05:11 2015 +0000
Revision:
10:6c0830baf10f
Parent:
9:83ae7f34e88c
correct DR4 channel used in 8ch mode.  added JOIN_SINGLE_CHANNEL_BLOCK option for faster joining in 8ch mode.

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 8:0faa1bb768b5 402 /* pd2=0 pd2=1
dudmuck 8:0faa1bb768b5 403 op pab rfo rfo
dudmuck 8:0faa1bb768b5 404 0 4.6 18.5 27.0
dudmuck 8:0faa1bb768b5 405 1 5.6 21.1 28.1
dudmuck 8:0faa1bb768b5 406 2 6.7 23.3 29.1
dudmuck 8:0faa1bb768b5 407 3 7.7 25.3 30.1
dudmuck 8:0faa1bb768b5 408 4 8.8 26.2 30.7
dudmuck 8:0faa1bb768b5 409 5 9.8 27.3 31.2
dudmuck 8:0faa1bb768b5 410 6 10.7 28.1 31.6
dudmuck 8:0faa1bb768b5 411 7 11.7 28.6 32.2
dudmuck 8:0faa1bb768b5 412 8 12.8 29.2 32.4
dudmuck 8:0faa1bb768b5 413 9 13.7 29.9 32.9
dudmuck 8:0faa1bb768b5 414 10 14.7 30.5 33.1
dudmuck 8:0faa1bb768b5 415 11 15.6 30.8 33.4
dudmuck 8:0faa1bb768b5 416 12 16.4 30.9 33.6
dudmuck 8:0faa1bb768b5 417 13 17.1 31.0 33.7
dudmuck 8:0faa1bb768b5 418 14 17.8 31.1 33.7
dudmuck 8:0faa1bb768b5 419 15 18.4 31.1 33.7
dudmuck 8:0faa1bb768b5 420 */
dudmuck 8:0faa1bb768b5 421 // txpow: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
dudmuck 8:0faa1bb768b5 422 static const u1_t boost_table[20] = { 0, 0, 0, 0, 0, 1, 2, 3, 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 14, 15 };
dudmuck 8:0faa1bb768b5 423
dudmuck 8:0faa1bb768b5 424 // txpow: 20 21 22 23 24 25 26 27 28 29 30
dudmuck 8:0faa1bb768b5 425 static const u1_t rfo_table[11] = { 1, 1, 1, 2, 2, 3, 4, 5, 6, 8, 9 };
dudmuck 8:0faa1bb768b5 426
dudmuck 0:f2716e543d97 427 static void configPower () {
dudmuck 0:f2716e543d97 428 #ifdef CFG_sx1276_radio
dudmuck 0:f2716e543d97 429 // no boost used for now
dudmuck 0:f2716e543d97 430 s1_t pw = (s1_t)LMIC.txpow;
dudmuck 0:f2716e543d97 431 if(pw >= 17) {
dudmuck 0:f2716e543d97 432 pw = 15;
dudmuck 0:f2716e543d97 433 } else if(pw < 2) {
dudmuck 0:f2716e543d97 434 pw = 2;
dudmuck 0:f2716e543d97 435 }
dudmuck 0:f2716e543d97 436 // check board type for BOOST pin
dudmuck 0:f2716e543d97 437 writeReg(RegPaConfig, (u1_t)(0x80|(pw&0xf)));
dudmuck 0:f2716e543d97 438 writeReg(RegPaDac, readReg(RegPaDac)|0x4);
dudmuck 0:f2716e543d97 439
dudmuck 0:f2716e543d97 440 #elif defined(CFG_sx1272_radio)
dudmuck 8:0faa1bb768b5 441
dudmuck 2:edb5d1f3deeb 442 /* NA-mote TX power config: */
dudmuck 8:0faa1bb768b5 443 if (LMIC.txpow > 19) {
dudmuck 2:edb5d1f3deeb 444 PaSelect = 0x00; // use RFO
dudmuck 8:0faa1bb768b5 445 writeReg(RegPaConfig, PaSelect | rfo_table[LMIC.txpow-20]);
dudmuck 8:0faa1bb768b5 446 pd2 = 0;
dudmuck 2:edb5d1f3deeb 447 } else {
dudmuck 2:edb5d1f3deeb 448 PaSelect = 0x80; // use PA_BOOST
dudmuck 8:0faa1bb768b5 449 writeReg(RegPaConfig, PaSelect | boost_table[LMIC.txpow]);
dudmuck 0:f2716e543d97 450 }
dudmuck 2:edb5d1f3deeb 451
dudmuck 0:f2716e543d97 452 #else
dudmuck 0:f2716e543d97 453 #error Missing CFG_sx1272_radio/CFG_sx1276_radio
dudmuck 0:f2716e543d97 454 #endif /* CFG_sx1272_radio */
dudmuck 0:f2716e543d97 455 }
dudmuck 0:f2716e543d97 456
dudmuck 0:f2716e543d97 457 static void txfsk () {
dudmuck 0:f2716e543d97 458 // select FSK modem (from sleep mode)
dudmuck 0:f2716e543d97 459 writeReg(RegOpMode, 0x10); // FSK, BT=0.5
dudmuck 0:f2716e543d97 460 ASSERT(readReg(RegOpMode) == 0x10);
dudmuck 0:f2716e543d97 461 // enter standby mode (required for FIFO loading))
dudmuck 0:f2716e543d97 462 opmode(OPMODE_STANDBY);
dudmuck 0:f2716e543d97 463 // set bitrate
dudmuck 0:f2716e543d97 464 writeReg(FSKRegBitrateMsb, 0x02); // 50kbps
dudmuck 0:f2716e543d97 465 writeReg(FSKRegBitrateLsb, 0x80);
dudmuck 0:f2716e543d97 466 // set frequency deviation
dudmuck 0:f2716e543d97 467 writeReg(FSKRegFdevMsb, 0x01); // +/- 25kHz
dudmuck 0:f2716e543d97 468 writeReg(FSKRegFdevLsb, 0x99);
dudmuck 0:f2716e543d97 469 // frame and packet handler settings
dudmuck 0:f2716e543d97 470 writeReg(FSKRegPreambleMsb, 0x00);
dudmuck 0:f2716e543d97 471 writeReg(FSKRegPreambleLsb, 0x05);
dudmuck 0:f2716e543d97 472 writeReg(FSKRegSyncConfig, 0x12);
dudmuck 0:f2716e543d97 473 writeReg(FSKRegPacketConfig1, 0xD0);
dudmuck 0:f2716e543d97 474 writeReg(FSKRegPacketConfig2, 0x40);
dudmuck 0:f2716e543d97 475 writeReg(FSKRegSyncValue1, 0xC1);
dudmuck 0:f2716e543d97 476 writeReg(FSKRegSyncValue2, 0x94);
dudmuck 0:f2716e543d97 477 writeReg(FSKRegSyncValue3, 0xC1);
dudmuck 0:f2716e543d97 478 // configure frequency
dudmuck 0:f2716e543d97 479 configChannel();
dudmuck 0:f2716e543d97 480 // configure output power
dudmuck 0:f2716e543d97 481 configPower();
dudmuck 0:f2716e543d97 482
dudmuck 0:f2716e543d97 483 // set the IRQ mapping DIO0=PacketSent DIO1=NOP DIO2=NOP
dudmuck 0:f2716e543d97 484 writeReg(RegDioMapping1, MAP_DIO0_FSK_READY|MAP_DIO1_FSK_NOP|MAP_DIO2_FSK_TXNOP);
dudmuck 0:f2716e543d97 485
dudmuck 0:f2716e543d97 486 // initialize the payload size and address pointers
dudmuck 0:f2716e543d97 487 writeReg(FSKRegPayloadLength, LMIC.dataLen+1); // (insert length byte into payload))
dudmuck 0:f2716e543d97 488
dudmuck 0:f2716e543d97 489 // download length byte and buffer to the radio FIFO
dudmuck 0:f2716e543d97 490 writeReg(RegFifo, LMIC.dataLen);
dudmuck 0:f2716e543d97 491 writeBuf(RegFifo, LMIC.frame, LMIC.dataLen);
dudmuck 0:f2716e543d97 492
dudmuck 0:f2716e543d97 493 // enable antenna switch for TX
dudmuck 2:edb5d1f3deeb 494 //hal_pin_rxtx(1); usint hal_opmode
dudmuck 0:f2716e543d97 495
dudmuck 0:f2716e543d97 496 // now we actually start the transmission
dudmuck 0:f2716e543d97 497 opmode(OPMODE_TX);
dudmuck 0:f2716e543d97 498 }
dudmuck 0:f2716e543d97 499
dudmuck 0:f2716e543d97 500 static void txlora () {
dudmuck 0:f2716e543d97 501 // select LoRa modem (from sleep mode)
dudmuck 0:f2716e543d97 502 //writeReg(RegOpMode, OPMODE_LORA);
dudmuck 0:f2716e543d97 503 opmodeLora();
dudmuck 0:f2716e543d97 504 ASSERT((readReg(RegOpMode) & OPMODE_LORA) != 0);
dudmuck 0:f2716e543d97 505
dudmuck 0:f2716e543d97 506 // enter standby mode (required for FIFO loading))
dudmuck 0:f2716e543d97 507 opmode(OPMODE_STANDBY);
dudmuck 0:f2716e543d97 508 // configure LoRa modem (cfg1, cfg2)
dudmuck 0:f2716e543d97 509 configLoraModem();
dudmuck 0:f2716e543d97 510 // configure frequency
dudmuck 0:f2716e543d97 511 configChannel();
dudmuck 0:f2716e543d97 512 // configure output power
dudmuck 0:f2716e543d97 513 writeReg(RegPaRamp, (readReg(RegPaRamp) & 0xF0) | 0x08); // set PA ramp-up time 50 uSec
dudmuck 0:f2716e543d97 514 configPower();
dudmuck 0:f2716e543d97 515 // set sync word
dudmuck 0:f2716e543d97 516 writeReg(LORARegSyncWord, LORA_MAC_PREAMBLE);
dudmuck 0:f2716e543d97 517
dudmuck 0:f2716e543d97 518 // set the IRQ mapping DIO0=TxDone DIO1=NOP DIO2=NOP
dudmuck 0:f2716e543d97 519 writeReg(RegDioMapping1, MAP_DIO0_LORA_TXDONE|MAP_DIO1_LORA_NOP|MAP_DIO2_LORA_NOP);
dudmuck 0:f2716e543d97 520 // clear all radio IRQ flags
dudmuck 0:f2716e543d97 521 writeReg(LORARegIrqFlags, 0xFF);
dudmuck 0:f2716e543d97 522 // mask all IRQs but TxDone
dudmuck 0:f2716e543d97 523 writeReg(LORARegIrqFlagsMask, ~IRQ_LORA_TXDONE_MASK);
dudmuck 0:f2716e543d97 524
dudmuck 0:f2716e543d97 525 // initialize the payload size and address pointers
dudmuck 0:f2716e543d97 526 writeReg(LORARegFifoTxBaseAddr, 0x00);
dudmuck 0:f2716e543d97 527 writeReg(LORARegFifoAddrPtr, 0x00);
dudmuck 0:f2716e543d97 528 writeReg(LORARegPayloadLength, LMIC.dataLen);
dudmuck 0:f2716e543d97 529
dudmuck 0:f2716e543d97 530 // download buffer to the radio FIFO
dudmuck 0:f2716e543d97 531 writeBuf(RegFifo, LMIC.frame, LMIC.dataLen);
dudmuck 0:f2716e543d97 532
dudmuck 0:f2716e543d97 533 // enable antenna switch for TX
dudmuck 2:edb5d1f3deeb 534 //hal_pin_rxtx(1); using hal_opmode
dudmuck 0:f2716e543d97 535
dudmuck 0:f2716e543d97 536 // now we actually start the transmission
dudmuck 0:f2716e543d97 537 opmode(OPMODE_TX);
dudmuck 0:f2716e543d97 538 }
dudmuck 0:f2716e543d97 539
dudmuck 0:f2716e543d97 540 // start transmitter (buf=LMIC.frame, len=LMIC.dataLen)
dudmuck 0:f2716e543d97 541 static void starttx () {
dudmuck 0:f2716e543d97 542 ASSERT( (readReg(RegOpMode) & OPMODE_MASK) == OPMODE_SLEEP );
dudmuck 0:f2716e543d97 543 if(getSf(LMIC.rps) == FSK) { // FSK modem
dudmuck 0:f2716e543d97 544 txfsk();
dudmuck 0:f2716e543d97 545 } else { // LoRa modem
dudmuck 0:f2716e543d97 546 txlora();
dudmuck 0:f2716e543d97 547 }
dudmuck 0:f2716e543d97 548 // the radio will go back to STANDBY mode as soon as the TX is finished
dudmuck 0:f2716e543d97 549 // the corresponding IRQ will inform us about completion.
dudmuck 0:f2716e543d97 550 }
dudmuck 0:f2716e543d97 551
dudmuck 0:f2716e543d97 552 enum { RXMODE_SINGLE, RXMODE_SCAN, RXMODE_RSSI };
dudmuck 0:f2716e543d97 553
dudmuck 0:f2716e543d97 554 static const u1_t rxlorairqmask[] = {
dudmuck 0:f2716e543d97 555 [RXMODE_SINGLE] = IRQ_LORA_RXDONE_MASK|IRQ_LORA_RXTOUT_MASK,
dudmuck 0:f2716e543d97 556 [RXMODE_SCAN] = IRQ_LORA_RXDONE_MASK,
dudmuck 0:f2716e543d97 557 [RXMODE_RSSI] = 0x00,
dudmuck 0:f2716e543d97 558 };
dudmuck 0:f2716e543d97 559
dudmuck 0:f2716e543d97 560 // start LoRa receiver (time=LMIC.rxtime, timeout=LMIC.rxsyms, result=LMIC.frame[LMIC.dataLen])
dudmuck 0:f2716e543d97 561 static void rxlora (u1_t rxmode) {
dudmuck 0:f2716e543d97 562 // select LoRa modem (from sleep mode)
dudmuck 0:f2716e543d97 563 opmodeLora();
dudmuck 0:f2716e543d97 564 ASSERT((readReg(RegOpMode) & OPMODE_LORA) != 0);
dudmuck 0:f2716e543d97 565 // enter standby mode (warm up))
dudmuck 0:f2716e543d97 566 opmode(OPMODE_STANDBY);
dudmuck 0:f2716e543d97 567 // don't use MAC settings at startup
dudmuck 0:f2716e543d97 568 if(rxmode == RXMODE_RSSI) { // use fixed settings for rssi scan
dudmuck 0:f2716e543d97 569 writeReg(LORARegModemConfig1, RXLORA_RXMODE_RSSI_REG_MODEM_CONFIG1);
dudmuck 0:f2716e543d97 570 writeReg(LORARegModemConfig2, RXLORA_RXMODE_RSSI_REG_MODEM_CONFIG2);
dudmuck 0:f2716e543d97 571 } else { // single or continuous rx mode
dudmuck 0:f2716e543d97 572 // configure LoRa modem (cfg1, cfg2)
dudmuck 0:f2716e543d97 573 configLoraModem();
dudmuck 0:f2716e543d97 574 // configure frequency
dudmuck 0:f2716e543d97 575 configChannel();
dudmuck 0:f2716e543d97 576 }
dudmuck 0:f2716e543d97 577 // set LNA gain
dudmuck 0:f2716e543d97 578 writeReg(RegLna, LNA_RX_GAIN);
dudmuck 0:f2716e543d97 579 // set max payload size
dudmuck 0:f2716e543d97 580 writeReg(LORARegPayloadMaxLength, 64);
dudmuck 0:f2716e543d97 581 // use inverted I/Q signal (prevent mote-to-mote communication)
dudmuck 0:f2716e543d97 582 writeReg(LORARegInvertIQ, readReg(LORARegInvertIQ)|(1<<6));
dudmuck 0:f2716e543d97 583 // set symbol timeout (for single rx)
dudmuck 0:f2716e543d97 584 writeReg(LORARegSymbTimeoutLsb, LMIC.rxsyms);
dudmuck 0:f2716e543d97 585 // set sync word
dudmuck 0:f2716e543d97 586 writeReg(LORARegSyncWord, LORA_MAC_PREAMBLE);
dudmuck 0:f2716e543d97 587
dudmuck 0:f2716e543d97 588 // configure DIO mapping DIO0=RxDone DIO1=RxTout DIO2=NOP
dudmuck 0:f2716e543d97 589 writeReg(RegDioMapping1, MAP_DIO0_LORA_RXDONE|MAP_DIO1_LORA_RXTOUT|MAP_DIO2_LORA_NOP);
dudmuck 0:f2716e543d97 590 // clear all radio IRQ flags
dudmuck 0:f2716e543d97 591 writeReg(LORARegIrqFlags, 0xFF);
dudmuck 0:f2716e543d97 592 // enable required radio IRQs
dudmuck 0:f2716e543d97 593 writeReg(LORARegIrqFlagsMask, ~rxlorairqmask[rxmode]);
dudmuck 0:f2716e543d97 594
dudmuck 0:f2716e543d97 595 // enable antenna switch for RX
dudmuck 2:edb5d1f3deeb 596 //hal_pin_rxtx(0); using hal_opmode
dudmuck 0:f2716e543d97 597
dudmuck 0:f2716e543d97 598 // now instruct the radio to receive
dudmuck 0:f2716e543d97 599 if (rxmode == RXMODE_SINGLE) { // single rx
dudmuck 0:f2716e543d97 600 hal_waitUntil(LMIC.rxtime); // busy wait until exact rx time
dudmuck 0:f2716e543d97 601 opmode(OPMODE_RX_SINGLE);
dudmuck 0:f2716e543d97 602 } else { // continous rx (scan or rssi)
dudmuck 0:f2716e543d97 603 opmode(OPMODE_RX);
dudmuck 0:f2716e543d97 604 }
dudmuck 0:f2716e543d97 605 }
dudmuck 0:f2716e543d97 606
dudmuck 0:f2716e543d97 607 static void rxfsk (u1_t rxmode) {
dudmuck 0:f2716e543d97 608 // only single rx (no continuous scanning, no noise sampling)
dudmuck 0:f2716e543d97 609 ASSERT( rxmode == RXMODE_SINGLE );
dudmuck 0:f2716e543d97 610 // select FSK modem (from sleep mode)
dudmuck 0:f2716e543d97 611 //writeReg(RegOpMode, 0x00); // (not LoRa)
dudmuck 0:f2716e543d97 612 opmodeFSK();
dudmuck 0:f2716e543d97 613 ASSERT((readReg(RegOpMode) & OPMODE_LORA) == 0);
dudmuck 0:f2716e543d97 614 // enter standby mode (warm up))
dudmuck 0:f2716e543d97 615 opmode(OPMODE_STANDBY);
dudmuck 0:f2716e543d97 616 // configure frequency
dudmuck 0:f2716e543d97 617 configChannel();
dudmuck 0:f2716e543d97 618 // set LNA gain
dudmuck 0:f2716e543d97 619 //writeReg(RegLna, 0x20|0x03); // max gain, boost enable
dudmuck 0:f2716e543d97 620 writeReg(RegLna, LNA_RX_GAIN);
dudmuck 0:f2716e543d97 621 // configure receiver
dudmuck 0:f2716e543d97 622 writeReg(FSKRegRxConfig, 0x1E); // AFC auto, AGC, trigger on preamble?!?
dudmuck 0:f2716e543d97 623 // set receiver bandwidth
dudmuck 0:f2716e543d97 624 writeReg(FSKRegRxBw, 0x0B); // 50kHz SSb
dudmuck 0:f2716e543d97 625 // set AFC bandwidth
dudmuck 0:f2716e543d97 626 writeReg(FSKRegAfcBw, 0x12); // 83.3kHz SSB
dudmuck 0:f2716e543d97 627 // set preamble detection
dudmuck 0:f2716e543d97 628 writeReg(FSKRegPreambleDetect, 0xAA); // enable, 2 bytes, 10 chip errors
dudmuck 0:f2716e543d97 629 // set sync config
dudmuck 0:f2716e543d97 630 writeReg(FSKRegSyncConfig, 0x12); // no auto restart, preamble 0xAA, enable, fill FIFO, 3 bytes sync
dudmuck 0:f2716e543d97 631 // set packet config
dudmuck 0:f2716e543d97 632 writeReg(FSKRegPacketConfig1, 0xD8); // var-length, whitening, crc, no auto-clear, no adr filter
dudmuck 0:f2716e543d97 633 writeReg(FSKRegPacketConfig2, 0x40); // packet mode
dudmuck 0:f2716e543d97 634 // set sync value
dudmuck 0:f2716e543d97 635 writeReg(FSKRegSyncValue1, 0xC1);
dudmuck 0:f2716e543d97 636 writeReg(FSKRegSyncValue2, 0x94);
dudmuck 0:f2716e543d97 637 writeReg(FSKRegSyncValue3, 0xC1);
dudmuck 0:f2716e543d97 638 // set preamble timeout
dudmuck 0:f2716e543d97 639 writeReg(FSKRegRxTimeout2, 0xFF);//(LMIC.rxsyms+1)/2);
dudmuck 0:f2716e543d97 640 // set bitrate
dudmuck 0:f2716e543d97 641 writeReg(FSKRegBitrateMsb, 0x02); // 50kbps
dudmuck 0:f2716e543d97 642 writeReg(FSKRegBitrateLsb, 0x80);
dudmuck 0:f2716e543d97 643 // set frequency deviation
dudmuck 0:f2716e543d97 644 writeReg(FSKRegFdevMsb, 0x01); // +/- 25kHz
dudmuck 0:f2716e543d97 645 writeReg(FSKRegFdevLsb, 0x99);
dudmuck 0:f2716e543d97 646
dudmuck 0:f2716e543d97 647 // configure DIO mapping DIO0=PayloadReady DIO1=NOP DIO2=TimeOut
dudmuck 0:f2716e543d97 648 writeReg(RegDioMapping1, MAP_DIO0_FSK_READY|MAP_DIO1_FSK_NOP|MAP_DIO2_FSK_TIMEOUT);
dudmuck 0:f2716e543d97 649
dudmuck 0:f2716e543d97 650 // enable antenna switch for RX
dudmuck 2:edb5d1f3deeb 651 //hal_pin_rxtx(0); using hal_opmode
dudmuck 0:f2716e543d97 652
dudmuck 0:f2716e543d97 653 // now instruct the radio to receive
dudmuck 0:f2716e543d97 654 hal_waitUntil(LMIC.rxtime); // busy wait until exact rx time
dudmuck 0:f2716e543d97 655 opmode(OPMODE_RX); // no single rx mode available in FSK
dudmuck 0:f2716e543d97 656 }
dudmuck 0:f2716e543d97 657
dudmuck 0:f2716e543d97 658 static void startrx (u1_t rxmode) {
dudmuck 0:f2716e543d97 659 ASSERT( (readReg(RegOpMode) & OPMODE_MASK) == OPMODE_SLEEP );
dudmuck 0:f2716e543d97 660 if(getSf(LMIC.rps) == FSK) { // FSK modem
dudmuck 0:f2716e543d97 661 rxfsk(rxmode);
dudmuck 0:f2716e543d97 662 } else { // LoRa modem
dudmuck 0:f2716e543d97 663 rxlora(rxmode);
dudmuck 0:f2716e543d97 664 }
dudmuck 0:f2716e543d97 665 // the radio will go back to STANDBY mode as soon as the RX is finished
dudmuck 0:f2716e543d97 666 // or timed out, and the corresponding IRQ will inform us about completion.
dudmuck 0:f2716e543d97 667 }
dudmuck 0:f2716e543d97 668
dudmuck 0:f2716e543d97 669 // get random seed from wideband noise rssi
dudmuck 0:f2716e543d97 670 void radio_init () {
dudmuck 0:f2716e543d97 671 hal_disableIRQs();
dudmuck 0:f2716e543d97 672
dudmuck 0:f2716e543d97 673 // manually reset radio
dudmuck 0:f2716e543d97 674 #ifdef CFG_sx1276_radio
dudmuck 0:f2716e543d97 675 hal_pin_rst(0); // drive RST pin low
dudmuck 0:f2716e543d97 676 #else
dudmuck 0:f2716e543d97 677 hal_pin_rst(1); // drive RST pin high
dudmuck 0:f2716e543d97 678 #endif
dudmuck 0:f2716e543d97 679 hal_waitUntil(os_getTime()+ms2osticks(1)); // wait >100us
dudmuck 0:f2716e543d97 680 hal_pin_rst(2); // configure RST pin floating!
dudmuck 0:f2716e543d97 681 hal_waitUntil(os_getTime()+ms2osticks(5)); // wait 5ms
dudmuck 0:f2716e543d97 682
dudmuck 0:f2716e543d97 683 opmode(OPMODE_SLEEP);
dudmuck 0:f2716e543d97 684
dudmuck 0:f2716e543d97 685 // some sanity checks, e.g., read version number
dudmuck 0:f2716e543d97 686 u1_t v = readReg(RegVersion);
dudmuck 0:f2716e543d97 687 #ifdef CFG_sx1276_radio
dudmuck 0:f2716e543d97 688 ASSERT(v == 0x12 );
dudmuck 0:f2716e543d97 689 #elif defined(CFG_sx1272_radio)
dudmuck 0:f2716e543d97 690 ASSERT(v == 0x22);
dudmuck 0:f2716e543d97 691 #else
dudmuck 0:f2716e543d97 692 #error Missing CFG_sx1272_radio/CFG_sx1276_radio
dudmuck 0:f2716e543d97 693 #endif
dudmuck 0:f2716e543d97 694 // seed 15-byte randomness via noise rssi
dudmuck 0:f2716e543d97 695 rxlora(RXMODE_RSSI);
dudmuck 0:f2716e543d97 696 while( (readReg(RegOpMode) & OPMODE_MASK) != OPMODE_RX ); // continuous rx
dudmuck 0:f2716e543d97 697 for(int i=1; i<16; i++) {
dudmuck 0:f2716e543d97 698 for(int j=0; j<8; j++) {
dudmuck 0:f2716e543d97 699 u1_t b; // wait for two non-identical subsequent least-significant bits
dudmuck 0:f2716e543d97 700 while( (b = readReg(LORARegRssiWideband) & 0x01) == (readReg(LORARegRssiWideband) & 0x01) );
dudmuck 0:f2716e543d97 701 randbuf[i] = (randbuf[i] << 1) | b;
dudmuck 0:f2716e543d97 702 }
dudmuck 0:f2716e543d97 703 }
dudmuck 0:f2716e543d97 704 randbuf[0] = 16; // set initial index
dudmuck 0:f2716e543d97 705
dudmuck 0:f2716e543d97 706 #ifdef CFG_sx1276mb1_board
dudmuck 0:f2716e543d97 707 // chain calibration
dudmuck 0:f2716e543d97 708 writeReg(RegPaConfig, 0);
dudmuck 0:f2716e543d97 709
dudmuck 0:f2716e543d97 710 // Launch Rx chain calibration for LF band
dudmuck 0:f2716e543d97 711 writeReg(FSKRegImageCal, (readReg(FSKRegImageCal) & RF_IMAGECAL_IMAGECAL_MASK)|RF_IMAGECAL_IMAGECAL_START);
dudmuck 0:f2716e543d97 712 while((readReg(FSKRegImageCal)&RF_IMAGECAL_IMAGECAL_RUNNING) == RF_IMAGECAL_IMAGECAL_RUNNING){ ; }
dudmuck 0:f2716e543d97 713
dudmuck 0:f2716e543d97 714 // Sets a Frequency in HF band
dudmuck 0:f2716e543d97 715 u4_t frf = 868000000;
dudmuck 0:f2716e543d97 716 writeReg(RegFrfMsb, (u1_t)(frf>>16));
dudmuck 0:f2716e543d97 717 writeReg(RegFrfMid, (u1_t)(frf>> 8));
dudmuck 0:f2716e543d97 718 writeReg(RegFrfLsb, (u1_t)(frf>> 0));
dudmuck 0:f2716e543d97 719
dudmuck 0:f2716e543d97 720 // Launch Rx chain calibration for HF band
dudmuck 0:f2716e543d97 721 writeReg(FSKRegImageCal, (readReg(FSKRegImageCal) & RF_IMAGECAL_IMAGECAL_MASK)|RF_IMAGECAL_IMAGECAL_START);
dudmuck 0:f2716e543d97 722 while((readReg(FSKRegImageCal) & RF_IMAGECAL_IMAGECAL_RUNNING) == RF_IMAGECAL_IMAGECAL_RUNNING) { ; }
dudmuck 0:f2716e543d97 723 #endif /* CFG_sx1276mb1_board */
dudmuck 0:f2716e543d97 724
dudmuck 0:f2716e543d97 725 /* SF12/500KHz RX improvement (0x1d/0x19 choice): must match setting of LORARegInvertIQ */
dudmuck 0:f2716e543d97 726 writeReg(LORARegTimingInvert, 0x19);
dudmuck 0:f2716e543d97 727
dudmuck 0:f2716e543d97 728 opmode(OPMODE_SLEEP);
dudmuck 0:f2716e543d97 729
dudmuck 0:f2716e543d97 730 hal_enableIRQs();
dudmuck 0:f2716e543d97 731 }
dudmuck 0:f2716e543d97 732
dudmuck 0:f2716e543d97 733 // return next random byte derived from seed buffer
dudmuck 0:f2716e543d97 734 // (buf[0] holds index of next byte to be returned)
dudmuck 0:f2716e543d97 735 u1_t radio_rand1 () {
dudmuck 0:f2716e543d97 736 u1_t i = randbuf[0];
dudmuck 0:f2716e543d97 737 ASSERT( i != 0 );
dudmuck 0:f2716e543d97 738 if( i==16 ) {
dudmuck 0:f2716e543d97 739 os_aes(AES_ENC, randbuf, 16); // encrypt seed with any key
dudmuck 0:f2716e543d97 740 i = 0;
dudmuck 0:f2716e543d97 741 }
dudmuck 0:f2716e543d97 742 u1_t v = randbuf[i++];
dudmuck 0:f2716e543d97 743 randbuf[0] = i;
dudmuck 0:f2716e543d97 744 return v;
dudmuck 0:f2716e543d97 745 }
dudmuck 0:f2716e543d97 746
dudmuck 0:f2716e543d97 747 u1_t radio_rssi () {
dudmuck 0:f2716e543d97 748 hal_disableIRQs();
dudmuck 0:f2716e543d97 749 u1_t r = readReg(LORARegRssiValue);
dudmuck 0:f2716e543d97 750 hal_enableIRQs();
dudmuck 0:f2716e543d97 751 return r;
dudmuck 0:f2716e543d97 752 }
dudmuck 0:f2716e543d97 753
dudmuck 0:f2716e543d97 754 static const u2_t LORA_RXDONE_FIXUP[] = {
dudmuck 0:f2716e543d97 755 [FSK] = us2osticks(0), // ( 0 ticks)
dudmuck 0:f2716e543d97 756 [SF7] = us2osticks(0), // ( 0 ticks)
dudmuck 0:f2716e543d97 757 [SF8] = us2osticks(1648), // ( 54 ticks)
dudmuck 0:f2716e543d97 758 [SF9] = us2osticks(3265), // ( 107 ticks)
dudmuck 0:f2716e543d97 759 [SF10] = us2osticks(7049), // ( 231 ticks)
dudmuck 0:f2716e543d97 760 [SF11] = us2osticks(13641), // ( 447 ticks)
dudmuck 0:f2716e543d97 761 [SF12] = us2osticks(31189), // (1022 ticks)
dudmuck 0:f2716e543d97 762 };
dudmuck 0:f2716e543d97 763
dudmuck 0:f2716e543d97 764 // called by hal ext IRQ handler
dudmuck 0:f2716e543d97 765 // (radio goes to stanby mode after tx/rx operations)
dudmuck 0:f2716e543d97 766 void radio_irq_handler (u1_t dio) {
dudmuck 0:f2716e543d97 767 ostime_t now = os_getTime();
dudmuck 0:f2716e543d97 768 if( (readReg(RegOpMode) & OPMODE_LORA) != 0) { // LORA modem
dudmuck 0:f2716e543d97 769 u1_t flags = readReg(LORARegIrqFlags);
dudmuck 0:f2716e543d97 770 if( flags & IRQ_LORA_TXDONE_MASK ) {
dudmuck 0:f2716e543d97 771 // save exact tx time
dudmuck 0:f2716e543d97 772 LMIC.txend = now - us2osticks(43); // TXDONE FIXUP
dudmuck 0:f2716e543d97 773 } else if( flags & IRQ_LORA_RXDONE_MASK ) {
dudmuck 0:f2716e543d97 774 // save exact rx time
dudmuck 0:f2716e543d97 775 if(getBw(LMIC.rps) == BW125) {
dudmuck 0:f2716e543d97 776 now -= LORA_RXDONE_FIXUP[getSf(LMIC.rps)];
dudmuck 0:f2716e543d97 777 }
dudmuck 0:f2716e543d97 778 LMIC.rxtime = now;
dudmuck 0:f2716e543d97 779 // read the PDU and inform the MAC that we received something
dudmuck 0:f2716e543d97 780 LMIC.dataLen = (readReg(LORARegModemConfig1) & SX1272_MC1_IMPLICIT_HEADER_MODE_ON) ?
dudmuck 0:f2716e543d97 781 readReg(LORARegPayloadLength) : readReg(LORARegRxNbBytes);
dudmuck 0:f2716e543d97 782 // set FIFO read address pointer
dudmuck 0:f2716e543d97 783 writeReg(LORARegFifoAddrPtr, readReg(LORARegFifoRxCurrentAddr));
dudmuck 0:f2716e543d97 784 // now read the FIFO
dudmuck 0:f2716e543d97 785 readBuf(RegFifo, LMIC.frame, LMIC.dataLen);
dudmuck 0:f2716e543d97 786 // read rx quality parameters
dudmuck 0:f2716e543d97 787 LMIC.snr = readReg(LORARegPktSnrValue); // SNR [dB] * 4
dudmuck 0:f2716e543d97 788 LMIC.rssi = readReg(LORARegPktRssiValue) - 125 + 64; // RSSI [dBm] (-196...+63)
dudmuck 0:f2716e543d97 789 } else if( flags & IRQ_LORA_RXTOUT_MASK ) {
dudmuck 0:f2716e543d97 790 // indicate timeout
dudmuck 0:f2716e543d97 791 LMIC.dataLen = 0;
dudmuck 0:f2716e543d97 792 }
dudmuck 0:f2716e543d97 793 // mask all radio IRQs
dudmuck 0:f2716e543d97 794 writeReg(LORARegIrqFlagsMask, 0xFF);
dudmuck 0:f2716e543d97 795 // clear radio IRQ flags
dudmuck 0:f2716e543d97 796 writeReg(LORARegIrqFlags, 0xFF);
dudmuck 0:f2716e543d97 797 } else { // FSK modem
dudmuck 0:f2716e543d97 798 u1_t flags1 = readReg(FSKRegIrqFlags1);
dudmuck 0:f2716e543d97 799 u1_t flags2 = readReg(FSKRegIrqFlags2);
dudmuck 0:f2716e543d97 800 if( flags2 & IRQ_FSK2_PACKETSENT_MASK ) {
dudmuck 0:f2716e543d97 801 // save exact tx time
dudmuck 0:f2716e543d97 802 LMIC.txend = now;
dudmuck 0:f2716e543d97 803 } else if( flags2 & IRQ_FSK2_PAYLOADREADY_MASK ) {
dudmuck 0:f2716e543d97 804 // save exact rx time
dudmuck 0:f2716e543d97 805 LMIC.rxtime = now;
dudmuck 0:f2716e543d97 806 // read the PDU and inform the MAC that we received something
dudmuck 0:f2716e543d97 807 LMIC.dataLen = readReg(FSKRegPayloadLength);
dudmuck 0:f2716e543d97 808 // now read the FIFO
dudmuck 0:f2716e543d97 809 readBuf(RegFifo, LMIC.frame, LMIC.dataLen);
dudmuck 0:f2716e543d97 810 // read rx quality parameters
dudmuck 0:f2716e543d97 811 LMIC.snr = 0; // determine snr
dudmuck 0:f2716e543d97 812 LMIC.rssi = 0; // determine rssi
dudmuck 0:f2716e543d97 813 } else if( flags1 & IRQ_FSK1_TIMEOUT_MASK ) {
dudmuck 0:f2716e543d97 814 // indicate timeout
dudmuck 0:f2716e543d97 815 LMIC.dataLen = 0;
dudmuck 0:f2716e543d97 816 } else {
dudmuck 0:f2716e543d97 817 while(1);
dudmuck 0:f2716e543d97 818 }
dudmuck 0:f2716e543d97 819 }
dudmuck 0:f2716e543d97 820 // go from stanby to sleep
dudmuck 0:f2716e543d97 821 opmode(OPMODE_SLEEP);
dudmuck 0:f2716e543d97 822 // run os job (use preset func ptr)
dudmuck 0:f2716e543d97 823 os_setCallback(&LMIC.osjob, LMIC.osjob.func);
dudmuck 0:f2716e543d97 824 }
dudmuck 0:f2716e543d97 825
dudmuck 0:f2716e543d97 826 void os_radio (u1_t mode) {
dudmuck 0:f2716e543d97 827 hal_disableIRQs();
dudmuck 0:f2716e543d97 828 switch (mode) {
dudmuck 0:f2716e543d97 829 case RADIO_RST:
dudmuck 0:f2716e543d97 830 // put radio to sleep
dudmuck 0:f2716e543d97 831 opmode(OPMODE_SLEEP);
dudmuck 0:f2716e543d97 832 break;
dudmuck 0:f2716e543d97 833
dudmuck 0:f2716e543d97 834 case RADIO_TX:
dudmuck 0:f2716e543d97 835 // transmit frame now
dudmuck 0:f2716e543d97 836 starttx(); // buf=LMIC.frame, len=LMIC.dataLen
dudmuck 0:f2716e543d97 837 break;
dudmuck 0:f2716e543d97 838
dudmuck 0:f2716e543d97 839 case RADIO_RX:
dudmuck 0:f2716e543d97 840 // receive frame now (exactly at rxtime)
dudmuck 0:f2716e543d97 841 startrx(RXMODE_SINGLE); // buf=LMIC.frame, time=LMIC.rxtime, timeout=LMIC.rxsyms
dudmuck 0:f2716e543d97 842 break;
dudmuck 0:f2716e543d97 843
dudmuck 0:f2716e543d97 844 case RADIO_RXON:
dudmuck 0:f2716e543d97 845 // start scanning for beacon now
dudmuck 0:f2716e543d97 846 startrx(RXMODE_SCAN); // buf=LMIC.frame
dudmuck 0:f2716e543d97 847 break;
dudmuck 0:f2716e543d97 848 }
dudmuck 0:f2716e543d97 849 hal_enableIRQs();
dudmuck 0:f2716e543d97 850 }