Senet-ized LMIC for MOTE_L152RC

Fork of lmic_MOTE_L152RC by Semtech

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers radio.cpp Source File

radio.cpp

00001 /*******************************************************************************
00002  * Copyright (c) 2014-2015 IBM Corporation.
00003  * All rights reserved. This program and the accompanying materials
00004  * are made available under the terms of the Eclipse Public License v1.0
00005  * which accompanies this distribution, and is available at
00006  * http://www.eclipse.org/legal/epl-v10.html
00007  *
00008  * Contributors:
00009  *    IBM Zurich Research Lab - initial API, implementation and documentation
00010  *******************************************************************************/
00011 
00012 #include "lmic.h"
00013 #include "mbed.h"
00014 
00015 // ---------------------------------------- 
00016 // Registers Mapping
00017 #define RegFifo                                    0x00 // common
00018 #define RegOpMode                                  0x01 // common
00019 #define FSKRegBitrateMsb                           0x02
00020 #define FSKRegBitrateLsb                           0x03
00021 #define FSKRegFdevMsb                              0x04
00022 #define FSKRegFdevLsb                              0x05
00023 #define RegFrfMsb                                  0x06 // common
00024 #define RegFrfMid                                  0x07 // common
00025 #define RegFrfLsb                                  0x08 // common
00026 #define RegPaConfig                                0x09 // common
00027 #define RegPaRamp                                  0x0A // common
00028 #define RegOcp                                     0x0B // common
00029 #define RegLna                                     0x0C // common
00030 #define FSKRegRxConfig                             0x0D
00031 #define LORARegFifoAddrPtr                         0x0D
00032 #define FSKRegRssiConfig                           0x0E
00033 #define LORARegFifoTxBaseAddr                      0x0E
00034 #define FSKRegRssiCollision                        0x0F
00035 #define LORARegFifoRxBaseAddr                      0x0F 
00036 #define FSKRegRssiThresh                           0x10
00037 #define LORARegFifoRxCurrentAddr                   0x10
00038 #define FSKRegRssiValue                            0x11
00039 #define LORARegIrqFlagsMask                        0x11 
00040 #define FSKRegRxBw                                 0x12
00041 #define LORARegIrqFlags                            0x12 
00042 #define FSKRegAfcBw                                0x13
00043 #define LORARegRxNbBytes                           0x13 
00044 #define FSKRegOokPeak                              0x14
00045 #define LORARegRxHeaderCntValueMsb                 0x14 
00046 #define FSKRegOokFix                               0x15
00047 #define LORARegRxHeaderCntValueLsb                 0x15 
00048 #define FSKRegOokAvg                               0x16
00049 #define LORARegRxPacketCntValueMsb                 0x16 
00050 #define LORARegRxpacketCntValueLsb                 0x17 
00051 #define LORARegModemStat                           0x18 
00052 #define LORARegPktSnrValue                         0x19 
00053 #define FSKRegAfcFei                               0x1A
00054 #define LORARegPktRssiValue                        0x1A 
00055 #define FSKRegAfcMsb                               0x1B
00056 #define LORARegRssiValue                           0x1B 
00057 #define FSKRegAfcLsb                               0x1C
00058 #define LORARegHopChannel                          0x1C 
00059 #define FSKRegFeiMsb                               0x1D
00060 #define LORARegModemConfig1                        0x1D 
00061 #define FSKRegFeiLsb                               0x1E
00062 #define LORARegModemConfig2                        0x1E 
00063 #define FSKRegPreambleDetect                       0x1F
00064 #define LORARegSymbTimeoutLsb                      0x1F 
00065 #define FSKRegRxTimeout1                           0x20
00066 #define LORARegPreambleMsb                         0x20 
00067 #define FSKRegRxTimeout2                           0x21
00068 #define LORARegPreambleLsb                         0x21 
00069 #define FSKRegRxTimeout3                           0x22
00070 #define LORARegPayloadLength                       0x22 
00071 #define FSKRegRxDelay                              0x23
00072 #define LORARegPayloadMaxLength                    0x23 
00073 #define FSKRegOsc                                  0x24
00074 #define LORARegHopPeriod                           0x24 
00075 #define FSKRegPreambleMsb                          0x25
00076 #define LORARegFifoRxByteAddr                      0x25
00077 #define LORARegModemConfig3                        0x26
00078 #define FSKRegPreambleLsb                          0x26
00079 #define FSKRegSyncConfig                           0x27
00080 #define LORARegFeiMsb                              0x28
00081 #define FSKRegSyncValue1                           0x28
00082 #define LORAFeiMib                                 0x29
00083 #define FSKRegSyncValue2                           0x29
00084 #define LORARegFeiLsb                              0x2A
00085 #define FSKRegSyncValue3                           0x2A
00086 #define FSKRegSyncValue4                           0x2B
00087 #define LORARegRssiWideband                        0x2C
00088 #define FSKRegSyncValue5                           0x2C
00089 #define FSKRegSyncValue6                           0x2D
00090 #define FSKRegSyncValue7                           0x2E
00091 #define FSKRegSyncValue8                           0x2F
00092 #define FSKRegPacketConfig1                        0x30
00093 #define FSKRegPacketConfig2                        0x31
00094 #define LORARegDetectOptimize                      0x31
00095 #define FSKRegPayloadLength                        0x32
00096 #define FSKRegNodeAdrs                             0x33
00097 #define LORARegInvertIQ                            0x33
00098 #define FSKRegBroadcastAdrs                        0x34
00099 #define FSKRegFifoThresh                           0x35
00100 #define FSKRegSeqConfig1                           0x36
00101 #define FSKRegSeqConfig2                           0x37
00102 #define LORARegDetectionThreshold                  0x37
00103 #define FSKRegTimerResol                           0x38
00104 #define FSKRegTimer1Coef                           0x39
00105 #define LORARegSyncWord                            0x39
00106 #define FSKRegTimer2Coef                           0x3A
00107 #define FSKRegImageCal                             0x3B
00108 #define LORARegTimingInvert                        0x3B // bit2 in 0x3b set low when bit6 in 0x33 set hi (RX invert)
00109 #define FSKRegTemp                                 0x3C
00110 #define FSKRegLowBat                               0x3D
00111 #define FSKRegIrqFlags1                            0x3E
00112 #define FSKRegIrqFlags2                            0x3F
00113 #define RegDioMapping1                             0x40 // common
00114 #define RegDioMapping2                             0x41 // common
00115 #define RegVersion                                 0x42 // common
00116 // #define RegAgcRef                                  0x43 // common
00117 // #define RegAgcThresh1                              0x44 // common
00118 // #define RegAgcThresh2                              0x45 // common
00119 // #define RegAgcThresh3                              0x46 // common
00120 // #define RegPllHop                                  0x4B // common
00121 // #define RegTcxo                                    0x58 // common
00122 #define RegPaDac                                   0x5A // common
00123 // #define RegPll                                     0x5C // common
00124 // #define RegPllLowPn                                0x5E // common
00125 // #define RegFormerTemp                              0x6C // common
00126 // #define RegBitRateFrac                             0x70 // common
00127 
00128 // ----------------------------------------
00129 // spread factors and mode for RegModemConfig2
00130 #define SX1272_MC2_FSK  0x00
00131 #define SX1272_MC2_SF7  0x70
00132 #define SX1272_MC2_SF8  0x80
00133 #define SX1272_MC2_SF9  0x90
00134 #define SX1272_MC2_SF10 0xA0
00135 #define SX1272_MC2_SF11 0xB0
00136 #define SX1272_MC2_SF12 0xC0
00137 // bandwidth for RegModemConfig1
00138 #define SX1272_MC1_BW_125  0x00
00139 #define SX1272_MC1_BW_250  0x40
00140 #define SX1272_MC1_BW_500  0x80
00141 // coding rate for RegModemConfig1
00142 #define SX1272_MC1_CR_4_5 0x08
00143 #define SX1272_MC1_CR_4_6 0x10
00144 #define SX1272_MC1_CR_4_7 0x18
00145 #define SX1272_MC1_CR_4_8 0x20
00146 #define SX1272_MC1_IMPLICIT_HEADER_MODE_ON 0x04 // required for receive
00147 #define SX1272_MC1_RX_PAYLOAD_CRCON        0x02
00148 #define SX1272_MC1_LOW_DATA_RATE_OPTIMIZE  0x01 // mandated for SF11 and SF12
00149 // transmit power configuration for RegPaConfig
00150 #define SX1272_PAC_PA_SELECT_PA_BOOST 0x80
00151 #define SX1272_PAC_PA_SELECT_RFIO_PIN 0x00
00152 
00153 
00154 // sx1276 RegModemConfig1
00155 #define SX1276_MC1_BW_125                0x70
00156 #define SX1276_MC1_BW_250                0x80
00157 #define SX1276_MC1_BW_500                0x90
00158 #define SX1276_MC1_CR_4_5            0x02
00159 #define SX1276_MC1_CR_4_6            0x04
00160 #define SX1276_MC1_CR_4_7            0x06
00161 #define SX1276_MC1_CR_4_8            0x08
00162 
00163 #define SX1276_MC1_IMPLICIT_HEADER_MODE_ON    0x01 
00164                                                     
00165 // sx1276 RegModemConfig2          
00166 #define SX1276_MC2_RX_PAYLOAD_CRCON        0x04
00167 
00168 // sx1276 RegModemConfig3          
00169 #define SX1276_MC3_LOW_DATA_RATE_OPTIMIZE  0x08
00170 #define SX1276_MC3_AGCAUTO                 0x04
00171 
00172 // preamble for lora networks (nibbles swapped)
00173 #define LORA_MAC_PREAMBLE                  0x34
00174 
00175 #define RXLORA_RXMODE_RSSI_REG_MODEM_CONFIG1 0x0A
00176 #ifdef CFG_sx1276_radio
00177 #define RXLORA_RXMODE_RSSI_REG_MODEM_CONFIG2 0x70
00178 #elif defined(CFG_sx1272_radio)
00179 #define RXLORA_RXMODE_RSSI_REG_MODEM_CONFIG2 0x74
00180 #endif
00181 
00182 
00183 
00184 // ---------------------------------------- 
00185 // Constants for radio registers
00186 #define OPMODE_LORA      0x80
00187 #define OPMODE_MASK      0x07
00188 #define OPMODE_SLEEP     0x00
00189 #define OPMODE_STANDBY   0x01
00190 #define OPMODE_FSTX      0x02
00191 #define OPMODE_TX        0x03
00192 #define OPMODE_FSRX      0x04
00193 #define OPMODE_RX        0x05
00194 #define OPMODE_RX_SINGLE 0x06 
00195 #define OPMODE_CAD       0x07 
00196 
00197 // ----------------------------------------
00198 // Bits masking the corresponding IRQs from the radio
00199 #define IRQ_LORA_RXTOUT_MASK 0x80
00200 #define IRQ_LORA_RXDONE_MASK 0x40
00201 #define IRQ_LORA_CRCERR_MASK 0x20
00202 #define IRQ_LORA_HEADER_MASK 0x10
00203 #define IRQ_LORA_TXDONE_MASK 0x08
00204 #define IRQ_LORA_CDDONE_MASK 0x04
00205 #define IRQ_LORA_FHSSCH_MASK 0x02
00206 #define IRQ_LORA_CDDETD_MASK 0x01
00207 
00208 #define IRQ_FSK1_MODEREADY_MASK         0x80
00209 #define IRQ_FSK1_RXREADY_MASK           0x40
00210 #define IRQ_FSK1_TXREADY_MASK           0x20
00211 #define IRQ_FSK1_PLLLOCK_MASK           0x10
00212 #define IRQ_FSK1_RSSI_MASK              0x08
00213 #define IRQ_FSK1_TIMEOUT_MASK           0x04
00214 #define IRQ_FSK1_PREAMBLEDETECT_MASK    0x02
00215 #define IRQ_FSK1_SYNCADDRESSMATCH_MASK  0x01
00216 #define IRQ_FSK2_FIFOFULL_MASK          0x80
00217 #define IRQ_FSK2_FIFOEMPTY_MASK         0x40
00218 #define IRQ_FSK2_FIFOLEVEL_MASK         0x20
00219 #define IRQ_FSK2_FIFOOVERRUN_MASK       0x10
00220 #define IRQ_FSK2_PACKETSENT_MASK        0x08
00221 #define IRQ_FSK2_PAYLOADREADY_MASK      0x04
00222 #define IRQ_FSK2_CRCOK_MASK             0x02
00223 #define IRQ_FSK2_LOWBAT_MASK            0x01
00224 
00225 // ----------------------------------------
00226 // DIO function mappings                D0D1D2D3
00227 #define MAP_DIO0_LORA_RXDONE   0x00  // 00------
00228 #define MAP_DIO0_LORA_TXDONE   0x40  // 01------
00229 #define MAP_DIO1_LORA_RXTOUT   0x00  // --00----
00230 #define MAP_DIO1_LORA_NOP      0x30  // --11----
00231 #define MAP_DIO2_LORA_NOP      0x0c  // ----11--
00232 
00233 #define MAP_DIO0_FSK_READY     0x00  // 00------ (packet sent / payload ready)
00234 #define MAP_DIO1_FSK_NOP       0x30  // --11----
00235 #define MAP_DIO2_FSK_TXNOP     0x04  // ----01--
00236 #define MAP_DIO2_FSK_TIMEOUT   0x08  // ----10--
00237 
00238 
00239 // FSK IMAGECAL defines
00240 #define RF_IMAGECAL_AUTOIMAGECAL_MASK               0x7F
00241 #define RF_IMAGECAL_AUTOIMAGECAL_ON                 0x80
00242 #define RF_IMAGECAL_AUTOIMAGECAL_OFF                0x00  // Default
00243 
00244 #define RF_IMAGECAL_IMAGECAL_MASK                   0xBF
00245 #define RF_IMAGECAL_IMAGECAL_START                  0x40
00246 
00247 #define RF_IMAGECAL_IMAGECAL_RUNNING                0x20
00248 #define RF_IMAGECAL_IMAGECAL_DONE                   0x00  // Default
00249 
00250 
00251 // RADIO STATE
00252 // (initialized by radio_init(), used by radio_rand1())
00253 static u1_t randbuf[16];
00254 static u1_t PaSelect;
00255 
00256 #ifdef CFG_sx1276_radio
00257 #define LNA_RX_GAIN (0x20|0x1)
00258 #elif defined(CFG_sx1272_radio)
00259 #define LNA_RX_GAIN (0x20|0x03)
00260 #else
00261 #error Missing CFG_sx1272_radio/CFG_sx1276_radio
00262 #endif
00263 
00264 
00265 static void writeReg (u1_t addr, u1_t data ) {
00266     hal_pin_nss(0);
00267     hal_spi(addr | 0x80);
00268     hal_spi(data);
00269     hal_pin_nss(1);
00270 }
00271 
00272 static u1_t readReg (u1_t addr) {
00273     hal_pin_nss(0);
00274     hal_spi(addr & 0x7F);
00275     u1_t val = hal_spi(0x00);
00276     hal_pin_nss(1);
00277     return val;
00278 }
00279 
00280 static void writeBuf (u1_t addr, xref2u1_t buf, u1_t len) {
00281     hal_pin_nss(0);
00282     hal_spi(addr | 0x80);
00283     for (u1_t i=0; i<len; i++) {
00284         hal_spi(buf[i]);
00285     }
00286     hal_pin_nss(1);
00287 }
00288 
00289 static void readBuf (u1_t addr, xref2u1_t buf, u1_t len) {
00290     hal_pin_nss(0);
00291     hal_spi(addr & 0x7F);
00292     for (u1_t i=0; i<len; i++) {
00293         buf[i] = hal_spi(0x00);
00294     }
00295     hal_pin_nss(1);
00296 }
00297 
00298 static void opmode (u1_t mode) {      
00299     hal_opmode(mode, PaSelect);
00300     writeReg(RegOpMode, (readReg(RegOpMode) & ~OPMODE_MASK) | mode);
00301 }
00302 
00303 static void opmodeLora() {
00304     u1_t u = OPMODE_LORA;
00305 #ifdef CFG_sx1276_radio
00306     u |= 0x8;   // TBD: sx1276 high freq
00307 #endif
00308     writeReg(RegOpMode, u);
00309 }
00310 
00311 static void opmodeFSK() {
00312     u1_t u = 0;
00313 #ifdef CFG_sx1276_radio
00314     u |= 0x8;   // TBD: sx1276 high freq
00315 #endif
00316     writeReg(RegOpMode, u);
00317 }
00318 
00319 // configure LoRa modem (cfg1, cfg2)
00320 static void configLoraModem () {
00321     sf_t sf = getSf(LMIC.rps);
00322 
00323 #ifdef CFG_sx1276_radio
00324         u1_t mc1 = 0, mc2 = 0, mc3 = 0;
00325 
00326         switch (getBw(LMIC.rps)) {
00327         case BW125: mc1 |= SX1276_MC1_BW_125; break;
00328         case BW250: mc1 |= SX1276_MC1_BW_250; break;
00329         case BW500: mc1 |= SX1276_MC1_BW_500; break;
00330         default:
00331             ASSERT(0);
00332         }
00333         switch( getCr(LMIC.rps) ) {
00334         case CR_4_5: mc1 |= SX1276_MC1_CR_4_5; break;
00335         case CR_4_6: mc1 |= SX1276_MC1_CR_4_6; break;
00336         case CR_4_7: mc1 |= SX1276_MC1_CR_4_7; break;
00337         case CR_4_8: mc1 |= SX1276_MC1_CR_4_8; break;
00338         default:
00339             ASSERT(0);
00340         }
00341 
00342         if (getIh(LMIC.rps)) {
00343             mc1 |= SX1276_MC1_IMPLICIT_HEADER_MODE_ON;
00344             writeReg(LORARegPayloadLength, getIh(LMIC.rps)); // required length
00345         }
00346         // set ModemConfig1
00347         writeReg(LORARegModemConfig1, mc1);
00348 
00349         mc2 = (SX1272_MC2_SF7 + ((sf-1)<<4));
00350         if (getNocrc(LMIC.rps) == 0) {
00351             mc2 |= SX1276_MC2_RX_PAYLOAD_CRCON;
00352         }
00353         writeReg(LORARegModemConfig2, mc2);
00354         
00355         mc3 = SX1276_MC3_AGCAUTO;
00356         if ((sf == SF11 || sf == SF12) && getBw(LMIC.rps) == BW125) {
00357             mc3 |= SX1276_MC3_LOW_DATA_RATE_OPTIMIZE;
00358         }
00359         writeReg(LORARegModemConfig3, mc3);
00360 #elif defined(CFG_sx1272_radio)
00361         u1_t mc1 = (getBw(LMIC.rps)<<6);
00362 
00363         switch( getCr(LMIC.rps) ) {
00364         case CR_4_5: mc1 |= SX1272_MC1_CR_4_5; break;
00365         case CR_4_6: mc1 |= SX1272_MC1_CR_4_6; break;
00366         case CR_4_7: mc1 |= SX1272_MC1_CR_4_7; break;
00367         case CR_4_8: mc1 |= SX1272_MC1_CR_4_8; break;
00368         }
00369         
00370         if ((sf == SF11 || sf == SF12) && getBw(LMIC.rps) == BW125) {
00371             mc1 |= SX1272_MC1_LOW_DATA_RATE_OPTIMIZE;
00372         }
00373         
00374         if (getNocrc(LMIC.rps) == 0) {
00375             mc1 |= SX1272_MC1_RX_PAYLOAD_CRCON;
00376         }
00377         
00378         if (getIh(LMIC.rps)) {
00379             mc1 |= SX1272_MC1_IMPLICIT_HEADER_MODE_ON;
00380             writeReg(LORARegPayloadLength, getIh(LMIC.rps)); // required length
00381         }
00382         // set ModemConfig1
00383         writeReg(LORARegModemConfig1, mc1);
00384         
00385         // set ModemConfig2 (sf, AgcAutoOn=1 SymbTimeoutHi=00)
00386         writeReg(LORARegModemConfig2, (SX1272_MC2_SF7 + ((sf-1)<<4)) | 0x04);
00387 #else
00388 #error Missing CFG_sx1272_radio/CFG_sx1276_radio
00389 #endif /* CFG_sx1272_radio */
00390 }
00391 
00392 static void configChannel () {
00393     // set frequency: FQ = (FRF * 32 Mhz) / (2 ^ 19)
00394     u8_t frf = ((u8_t)LMIC.freq << 19) / 32000000;
00395     writeReg(RegFrfMsb, (u1_t)(frf>>16));
00396     writeReg(RegFrfMid, (u1_t)(frf>> 8));
00397     writeReg(RegFrfLsb, (u1_t)(frf>> 0));
00398 }
00399 
00400 DigitalOut pd2(PD_2);   // power amplifier voltage control pin
00401 
00402 /*     pd2=0   pd2=1
00403 op pab  rfo     rfo
00404 0  4.6  18.5    27.0
00405 1  5.6  21.1    28.1
00406 2  6.7  23.3    29.1
00407 3  7.7  25.3    30.1
00408 4  8.8  26.2    30.7
00409 5  9.8  27.3    31.2
00410 6  10.7 28.1    31.6
00411 7  11.7 28.6    32.2
00412 8  12.8 29.2    32.4
00413 9  13.7 29.9    32.9
00414 10 14.7 30.5    33.1
00415 11 15.6 30.8    33.4
00416 12 16.4 30.9    33.6
00417 13 17.1 31.0    33.7
00418 14 17.8 31.1    33.7
00419 15 18.4 31.1    33.7
00420 */
00421 //                     txpow:   0  1  2  3  4  5  6  7  8  9 10 11 12 13 14  15  16  17  18  19
00422 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 };
00423 
00424 //                     txpow:  20 21 22 23 24 25 26 27 28 29 30
00425 static const u1_t   rfo_table[11] = { 1, 1, 1, 2, 2, 3, 4, 5, 6, 8, 9 }; 
00426 
00427 static void configPower () {
00428 #ifdef CFG_sx1276_radio
00429     // no boost used for now
00430     s1_t pw = (s1_t)LMIC.txpow;
00431     if(pw >= 17) {
00432         pw = 15;
00433     } else if(pw < 2) {
00434         pw = 2;
00435     }
00436     // check board type for BOOST pin
00437     writeReg(RegPaConfig, (u1_t)(0x80|(pw&0xf)));
00438     writeReg(RegPaDac, readReg(RegPaDac)|0x4);
00439 
00440 #elif defined(CFG_sx1272_radio)
00441 
00442     /* NA-mote TX power config: */
00443     if (LMIC.txpow > 19) {
00444         PaSelect = 0x00;    // use RFO
00445         writeReg(RegPaConfig, PaSelect | rfo_table[LMIC.txpow-20]);
00446         pd2 = 0;
00447     } else {
00448         PaSelect = 0x80;    // use PA_BOOST 
00449         writeReg(RegPaConfig, PaSelect | boost_table[LMIC.txpow]);
00450     }
00451     
00452 #else
00453 #error Missing CFG_sx1272_radio/CFG_sx1276_radio
00454 #endif /* CFG_sx1272_radio */
00455 }
00456 
00457 static void txfsk () {
00458     // select FSK modem (from sleep mode)
00459     writeReg(RegOpMode, 0x10); // FSK, BT=0.5
00460     ASSERT(readReg(RegOpMode) == 0x10);
00461     // enter standby mode (required for FIFO loading))
00462     opmode(OPMODE_STANDBY);
00463     // set bitrate
00464     writeReg(FSKRegBitrateMsb, 0x02); // 50kbps
00465     writeReg(FSKRegBitrateLsb, 0x80);
00466     // set frequency deviation
00467     writeReg(FSKRegFdevMsb, 0x01); // +/- 25kHz
00468     writeReg(FSKRegFdevLsb, 0x99);
00469     // frame and packet handler settings
00470     writeReg(FSKRegPreambleMsb, 0x00);
00471     writeReg(FSKRegPreambleLsb, 0x05);
00472     writeReg(FSKRegSyncConfig, 0x12);
00473     writeReg(FSKRegPacketConfig1, 0xD0);
00474     writeReg(FSKRegPacketConfig2, 0x40);
00475     writeReg(FSKRegSyncValue1, 0xC1);
00476     writeReg(FSKRegSyncValue2, 0x94);
00477     writeReg(FSKRegSyncValue3, 0xC1);
00478     // configure frequency
00479     configChannel();
00480     // configure output power
00481     configPower();
00482 
00483     // set the IRQ mapping DIO0=PacketSent DIO1=NOP DIO2=NOP
00484     writeReg(RegDioMapping1, MAP_DIO0_FSK_READY|MAP_DIO1_FSK_NOP|MAP_DIO2_FSK_TXNOP);
00485 
00486     // initialize the payload size and address pointers    
00487     writeReg(FSKRegPayloadLength, LMIC.dataLen+1); // (insert length byte into payload))
00488 
00489     // download length byte and buffer to the radio FIFO
00490     writeReg(RegFifo, LMIC.dataLen);
00491     writeBuf(RegFifo, LMIC.frame, LMIC.dataLen);
00492 
00493     // enable antenna switch for TX
00494     //hal_pin_rxtx(1); usint hal_opmode
00495     
00496     // now we actually start the transmission
00497     opmode(OPMODE_TX);
00498 }
00499 
00500 static void txlora () {
00501     // select LoRa modem (from sleep mode)
00502     //writeReg(RegOpMode, OPMODE_LORA);
00503     opmodeLora();
00504     ASSERT((readReg(RegOpMode) & OPMODE_LORA) != 0);
00505 
00506     // enter standby mode (required for FIFO loading))
00507     opmode(OPMODE_STANDBY);
00508     // configure LoRa modem (cfg1, cfg2)
00509     configLoraModem();
00510     // configure frequency
00511     configChannel();
00512     // configure output power
00513     writeReg(RegPaRamp, (readReg(RegPaRamp) & 0xF0) | 0x08); // set PA ramp-up time 50 uSec
00514     configPower();
00515     // set sync word
00516     writeReg(LORARegSyncWord, LORA_MAC_PREAMBLE);
00517     
00518     // set the IRQ mapping DIO0=TxDone DIO1=NOP DIO2=NOP
00519     writeReg(RegDioMapping1, MAP_DIO0_LORA_TXDONE|MAP_DIO1_LORA_NOP|MAP_DIO2_LORA_NOP);
00520     // clear all radio IRQ flags
00521     writeReg(LORARegIrqFlags, 0xFF);
00522     // mask all IRQs but TxDone
00523     writeReg(LORARegIrqFlagsMask, ~IRQ_LORA_TXDONE_MASK);
00524 
00525     // initialize the payload size and address pointers    
00526     writeReg(LORARegFifoTxBaseAddr, 0x00);
00527     writeReg(LORARegFifoAddrPtr, 0x00);
00528     writeReg(LORARegPayloadLength, LMIC.dataLen);
00529        
00530     // download buffer to the radio FIFO
00531     writeBuf(RegFifo, LMIC.frame, LMIC.dataLen);
00532 
00533     // enable antenna switch for TX
00534     //hal_pin_rxtx(1); using hal_opmode
00535     
00536     // now we actually start the transmission
00537     opmode(OPMODE_TX);
00538 }
00539 
00540 // start transmitter (buf=LMIC.frame, len=LMIC.dataLen)
00541 static void starttx () {
00542     ASSERT( (readReg(RegOpMode) & OPMODE_MASK) == OPMODE_SLEEP );
00543     if(getSf(LMIC.rps) == FSK) { // FSK modem
00544         txfsk();
00545     } else { // LoRa modem
00546         txlora();
00547     }
00548     // the radio will go back to STANDBY mode as soon as the TX is finished
00549     // the corresponding IRQ will inform us about completion.
00550 }
00551 
00552 enum { RXMODE_SINGLE, RXMODE_SCAN, RXMODE_RSSI };
00553 
00554 static const u1_t rxlorairqmask[] = {
00555     [RXMODE_SINGLE] = IRQ_LORA_RXDONE_MASK|IRQ_LORA_RXTOUT_MASK,
00556     [RXMODE_SCAN]   = IRQ_LORA_RXDONE_MASK,
00557     [RXMODE_RSSI]   = 0x00,
00558 };
00559 
00560 // start LoRa receiver (time=LMIC.rxtime, timeout=LMIC.rxsyms, result=LMIC.frame[LMIC.dataLen])
00561 static void rxlora (u1_t rxmode) {
00562     // select LoRa modem (from sleep mode)
00563     opmodeLora();
00564     ASSERT((readReg(RegOpMode) & OPMODE_LORA) != 0);
00565     // enter standby mode (warm up))
00566     opmode(OPMODE_STANDBY);
00567     // don't use MAC settings at startup
00568     if(rxmode == RXMODE_RSSI) { // use fixed settings for rssi scan
00569         writeReg(LORARegModemConfig1, RXLORA_RXMODE_RSSI_REG_MODEM_CONFIG1);
00570         writeReg(LORARegModemConfig2, RXLORA_RXMODE_RSSI_REG_MODEM_CONFIG2);
00571     } else { // single or continuous rx mode
00572         // configure LoRa modem (cfg1, cfg2)
00573         configLoraModem();
00574         // configure frequency
00575         configChannel();
00576     }
00577     // set LNA gain
00578     writeReg(RegLna, LNA_RX_GAIN); 
00579     // set max payload size
00580     writeReg(LORARegPayloadMaxLength, 64);
00581     // use inverted I/Q signal (prevent mote-to-mote communication)
00582     writeReg(LORARegInvertIQ, readReg(LORARegInvertIQ)|(1<<6));
00583     // set symbol timeout (for single rx)
00584     writeReg(LORARegSymbTimeoutLsb, LMIC.rxsyms);
00585     // set sync word
00586     writeReg(LORARegSyncWord, LORA_MAC_PREAMBLE);
00587     
00588     // configure DIO mapping DIO0=RxDone DIO1=RxTout DIO2=NOP
00589     writeReg(RegDioMapping1, MAP_DIO0_LORA_RXDONE|MAP_DIO1_LORA_RXTOUT|MAP_DIO2_LORA_NOP);
00590     // clear all radio IRQ flags
00591     writeReg(LORARegIrqFlags, 0xFF);
00592     // enable required radio IRQs
00593     writeReg(LORARegIrqFlagsMask, ~rxlorairqmask[rxmode]);
00594 
00595     // enable antenna switch for RX
00596     //hal_pin_rxtx(0); using hal_opmode
00597 
00598     // now instruct the radio to receive
00599     if (rxmode == RXMODE_SINGLE) { // single rx
00600         hal_waitUntil(LMIC.rxtime); // busy wait until exact rx time
00601         opmode(OPMODE_RX_SINGLE);
00602     } else { // continous rx (scan or rssi)
00603         opmode(OPMODE_RX); 
00604     }
00605 }
00606 
00607 static void rxfsk (u1_t rxmode) {
00608     // only single rx (no continuous scanning, no noise sampling)
00609     ASSERT( rxmode == RXMODE_SINGLE );
00610     // select FSK modem (from sleep mode)
00611     //writeReg(RegOpMode, 0x00); // (not LoRa)
00612     opmodeFSK();
00613     ASSERT((readReg(RegOpMode) & OPMODE_LORA) == 0);
00614     // enter standby mode (warm up))
00615     opmode(OPMODE_STANDBY);
00616     // configure frequency
00617     configChannel();
00618     // set LNA gain
00619     //writeReg(RegLna, 0x20|0x03); // max gain, boost enable
00620     writeReg(RegLna, LNA_RX_GAIN);
00621     // configure receiver
00622     writeReg(FSKRegRxConfig, 0x1E); // AFC auto, AGC, trigger on preamble?!?
00623     // set receiver bandwidth
00624     writeReg(FSKRegRxBw, 0x0B); // 50kHz SSb
00625     // set AFC bandwidth
00626     writeReg(FSKRegAfcBw, 0x12); // 83.3kHz SSB
00627     // set preamble detection
00628     writeReg(FSKRegPreambleDetect, 0xAA); // enable, 2 bytes, 10 chip errors
00629     // set sync config
00630     writeReg(FSKRegSyncConfig, 0x12); // no auto restart, preamble 0xAA, enable, fill FIFO, 3 bytes sync
00631     // set packet config
00632     writeReg(FSKRegPacketConfig1, 0xD8); // var-length, whitening, crc, no auto-clear, no adr filter
00633     writeReg(FSKRegPacketConfig2, 0x40); // packet mode
00634     // set sync value
00635     writeReg(FSKRegSyncValue1, 0xC1);
00636     writeReg(FSKRegSyncValue2, 0x94);
00637     writeReg(FSKRegSyncValue3, 0xC1);
00638     // set preamble timeout
00639     writeReg(FSKRegRxTimeout2, 0xFF);//(LMIC.rxsyms+1)/2);
00640     // set bitrate
00641     writeReg(FSKRegBitrateMsb, 0x02); // 50kbps
00642     writeReg(FSKRegBitrateLsb, 0x80);
00643     // set frequency deviation
00644     writeReg(FSKRegFdevMsb, 0x01); // +/- 25kHz
00645     writeReg(FSKRegFdevLsb, 0x99);
00646     
00647     // configure DIO mapping DIO0=PayloadReady DIO1=NOP DIO2=TimeOut
00648     writeReg(RegDioMapping1, MAP_DIO0_FSK_READY|MAP_DIO1_FSK_NOP|MAP_DIO2_FSK_TIMEOUT);
00649 
00650     // enable antenna switch for RX
00651     //hal_pin_rxtx(0); using hal_opmode
00652     
00653     // now instruct the radio to receive
00654     hal_waitUntil(LMIC.rxtime); // busy wait until exact rx time
00655     opmode(OPMODE_RX); // no single rx mode available in FSK
00656 }
00657 
00658 static void startrx (u1_t rxmode) {
00659     ASSERT( (readReg(RegOpMode) & OPMODE_MASK) == OPMODE_SLEEP );
00660     if(getSf(LMIC.rps) == FSK) { // FSK modem
00661         rxfsk(rxmode);
00662     } else { // LoRa modem
00663         rxlora(rxmode);
00664     }
00665     // the radio will go back to STANDBY mode as soon as the RX is finished
00666     // or timed out, and the corresponding IRQ will inform us about completion.
00667 }
00668 
00669 // get random seed from wideband noise rssi
00670 void radio_init () {
00671     hal_disableIRQs();
00672 
00673     // manually reset radio
00674 #ifdef CFG_sx1276_radio
00675     hal_pin_rst(0); // drive RST pin low
00676 #else
00677     hal_pin_rst(1); // drive RST pin high
00678 #endif
00679     hal_waitUntil(os_getTime()+ms2osticks(1)); // wait >100us
00680     hal_pin_rst(2); // configure RST pin floating!
00681     hal_waitUntil(os_getTime()+ms2osticks(5)); // wait 5ms
00682 
00683     opmode(OPMODE_SLEEP);
00684 
00685     // some sanity checks, e.g., read version number
00686     u1_t v = readReg(RegVersion);
00687 #ifdef CFG_sx1276_radio
00688     ASSERT(v == 0x12 ); 
00689 #elif defined(CFG_sx1272_radio)
00690     ASSERT(v == 0x22);
00691 #else
00692 #error Missing CFG_sx1272_radio/CFG_sx1276_radio
00693 #endif
00694     // seed 15-byte randomness via noise rssi
00695     rxlora(RXMODE_RSSI);
00696     while( (readReg(RegOpMode) & OPMODE_MASK) != OPMODE_RX ); // continuous rx
00697     for(int i=1; i<16; i++) {
00698         for(int j=0; j<8; j++) {
00699             u1_t b; // wait for two non-identical subsequent least-significant bits
00700             while( (b = readReg(LORARegRssiWideband) & 0x01) == (readReg(LORARegRssiWideband) & 0x01) );
00701             randbuf[i] = (randbuf[i] << 1) | b;
00702         }
00703     }
00704     randbuf[0] = 16; // set initial index
00705   
00706 #ifdef CFG_sx1276mb1_board
00707     // chain calibration
00708     writeReg(RegPaConfig, 0);
00709     
00710     // Launch Rx chain calibration for LF band
00711     writeReg(FSKRegImageCal, (readReg(FSKRegImageCal) & RF_IMAGECAL_IMAGECAL_MASK)|RF_IMAGECAL_IMAGECAL_START);
00712     while((readReg(FSKRegImageCal)&RF_IMAGECAL_IMAGECAL_RUNNING) == RF_IMAGECAL_IMAGECAL_RUNNING){ ; }
00713 
00714     // Sets a Frequency in HF band
00715     u4_t frf = 868000000;
00716     writeReg(RegFrfMsb, (u1_t)(frf>>16));
00717     writeReg(RegFrfMid, (u1_t)(frf>> 8));
00718     writeReg(RegFrfLsb, (u1_t)(frf>> 0));
00719 
00720     // Launch Rx chain calibration for HF band 
00721     writeReg(FSKRegImageCal, (readReg(FSKRegImageCal) & RF_IMAGECAL_IMAGECAL_MASK)|RF_IMAGECAL_IMAGECAL_START);
00722     while((readReg(FSKRegImageCal) & RF_IMAGECAL_IMAGECAL_RUNNING) == RF_IMAGECAL_IMAGECAL_RUNNING) { ; }
00723 #endif /* CFG_sx1276mb1_board */
00724 
00725     /* SF12/500KHz RX improvement (0x1d/0x19 choice): must match setting of LORARegInvertIQ */
00726     writeReg(LORARegTimingInvert, 0x19);
00727 
00728     opmode(OPMODE_SLEEP);
00729 
00730     hal_enableIRQs();
00731 }
00732 
00733 // return next random byte derived from seed buffer
00734 // (buf[0] holds index of next byte to be returned)
00735 u1_t radio_rand1 () {
00736     u1_t i = randbuf[0];
00737     ASSERT( i != 0 );
00738     if( i==16 ) {
00739         os_aes(AES_ENC, randbuf, 16); // encrypt seed with any key
00740         i = 0;
00741     }
00742     u1_t v = randbuf[i++];
00743     randbuf[0] = i;
00744     return v;
00745 }
00746 
00747 u1_t radio_rssi () {
00748     hal_disableIRQs();
00749     u1_t r = readReg(LORARegRssiValue);
00750     hal_enableIRQs();
00751     return r;
00752 }
00753 
00754 static const u2_t LORA_RXDONE_FIXUP[] = {
00755     [FSK]  =     us2osticks(0), // (   0 ticks)
00756     [SF7]  =     us2osticks(0), // (   0 ticks)
00757     [SF8]  =  us2osticks(1648), // (  54 ticks)
00758     [SF9]  =  us2osticks(3265), // ( 107 ticks)
00759     [SF10] =  us2osticks(7049), // ( 231 ticks)
00760     [SF11] = us2osticks(13641), // ( 447 ticks)
00761     [SF12] = us2osticks(31189), // (1022 ticks)
00762 };
00763 
00764 // called by hal ext IRQ handler
00765 // (radio goes to stanby mode after tx/rx operations)
00766 void radio_irq_handler (u1_t dio) {
00767     ostime_t now = os_getTime();
00768     if( (readReg(RegOpMode) & OPMODE_LORA) != 0) { // LORA modem
00769         u1_t flags = readReg(LORARegIrqFlags);
00770         if( flags & IRQ_LORA_TXDONE_MASK ) {
00771             // save exact tx time
00772             LMIC.txend = now - us2osticks(43); // TXDONE FIXUP
00773         } else if( flags & IRQ_LORA_RXDONE_MASK ) {
00774             // save exact rx time
00775             if(getBw(LMIC.rps) == BW125) {
00776                 now -= LORA_RXDONE_FIXUP[getSf(LMIC.rps)];
00777             }
00778             LMIC.rxtime = now;
00779             // read the PDU and inform the MAC that we received something
00780             LMIC.dataLen = (readReg(LORARegModemConfig1) & SX1272_MC1_IMPLICIT_HEADER_MODE_ON) ?
00781                 readReg(LORARegPayloadLength) : readReg(LORARegRxNbBytes);
00782             // set FIFO read address pointer
00783             writeReg(LORARegFifoAddrPtr, readReg(LORARegFifoRxCurrentAddr)); 
00784             // now read the FIFO
00785             readBuf(RegFifo, LMIC.frame, LMIC.dataLen);
00786             // read rx quality parameters
00787             LMIC.snr  = readReg(LORARegPktSnrValue); // SNR [dB] * 4
00788             LMIC.rssi = readReg(LORARegPktRssiValue) - 125 + 64; // RSSI [dBm] (-196...+63)
00789         } else if( flags & IRQ_LORA_RXTOUT_MASK ) {
00790             // indicate timeout
00791             LMIC.dataLen = 0;
00792         }
00793         // mask all radio IRQs
00794         writeReg(LORARegIrqFlagsMask, 0xFF);
00795         // clear radio IRQ flags
00796         writeReg(LORARegIrqFlags, 0xFF);
00797     } else { // FSK modem
00798         u1_t flags1 = readReg(FSKRegIrqFlags1);
00799         u1_t flags2 = readReg(FSKRegIrqFlags2);
00800         if( flags2 & IRQ_FSK2_PACKETSENT_MASK ) {
00801             // save exact tx time
00802             LMIC.txend = now;
00803         } else if( flags2 & IRQ_FSK2_PAYLOADREADY_MASK ) {
00804             // save exact rx time
00805             LMIC.rxtime = now;
00806             // read the PDU and inform the MAC that we received something
00807             LMIC.dataLen = readReg(FSKRegPayloadLength);
00808             // now read the FIFO
00809             readBuf(RegFifo, LMIC.frame, LMIC.dataLen);
00810             // read rx quality parameters
00811             LMIC.snr  = 0; // determine snr
00812             LMIC.rssi = 0; // determine rssi
00813         } else if( flags1 & IRQ_FSK1_TIMEOUT_MASK ) {
00814             // indicate timeout
00815             LMIC.dataLen = 0;
00816         } else {
00817             while(1);
00818         }
00819     }
00820     // go from stanby to sleep
00821     opmode(OPMODE_SLEEP);
00822     // run os job (use preset func ptr)
00823     os_setCallback(&LMIC.osjob, LMIC.osjob.func);
00824 }
00825 
00826 void os_radio (u1_t mode) {
00827     hal_disableIRQs();
00828     switch (mode) {
00829       case RADIO_RST:
00830         // put radio to sleep
00831         opmode(OPMODE_SLEEP);
00832         break;
00833 
00834       case RADIO_TX:
00835         // transmit frame now
00836         starttx(); // buf=LMIC.frame, len=LMIC.dataLen
00837         break;
00838       
00839       case RADIO_RX:
00840         // receive frame now (exactly at rxtime)
00841         startrx(RXMODE_SINGLE); // buf=LMIC.frame, time=LMIC.rxtime, timeout=LMIC.rxsyms
00842         break;
00843 
00844       case RADIO_RXON:
00845         // start scanning for beacon now
00846         startrx(RXMODE_SCAN); // buf=LMIC.frame
00847         break;
00848     }
00849     hal_enableIRQs();
00850 }