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:
Wed Oct 21 01:03:34 2015 +0000
Revision:
8:0faa1bb768b5
Parent:
4:1a9a62cf220f
Child:
9:83ae7f34e88c
parse channel mask in join accept, tx power table, channel search in nextJoinState()

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