hello world

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(PTC1);   // power amplifier voltage control pin *** TODO ***
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     printf("txpow:%d ", LMIC.txpow);
00429 #ifdef CFG_sx1276_radio
00430     // no boost used for now
00431     s1_t pw = (s1_t)LMIC.txpow;
00432     if(pw >= 17) {
00433         pw = 15;
00434     } else if(pw < 2) {
00435         pw = 2;
00436     }
00437     // check board type for BOOST pin
00438     writeReg(RegPaConfig, (u1_t)(0x80|(pw&0xf)));
00439     writeReg(RegPaDac, readReg(RegPaDac)|0x4);
00440 
00441 #elif defined(CFG_sx1272_radio)
00442 
00443     /* NA-mote TX power config: */
00444     if (LMIC.txpow > 19) {
00445         PaSelect = 0x00;    // use RFO
00446         writeReg(RegPaConfig, PaSelect | rfo_table[LMIC.txpow-20]);
00447 //        pd2 = 0;
00448     } else {
00449         PaSelect = 0x80;    // use PA_BOOST 
00450         writeReg(RegPaConfig, PaSelect | boost_table[LMIC.txpow]);
00451     }
00452     //printf("PaConfig:%02x\r\n", readReg(RegPaConfig));
00453     
00454 #else
00455 #error Missing CFG_sx1272_radio/CFG_sx1276_radio
00456 #endif /* CFG_sx1272_radio */
00457 }
00458 
00459 static void txfsk () {
00460     // select FSK modem (from sleep mode)
00461     writeReg(RegOpMode, 0x10); // FSK, BT=0.5
00462     ASSERT(readReg(RegOpMode) == 0x10);
00463     // enter standby mode (required for FIFO loading))
00464     opmode(OPMODE_STANDBY);
00465     // set bitrate
00466     writeReg(FSKRegBitrateMsb, 0x02); // 50kbps
00467     writeReg(FSKRegBitrateLsb, 0x80);
00468     // set frequency deviation
00469     writeReg(FSKRegFdevMsb, 0x01); // +/- 25kHz
00470     writeReg(FSKRegFdevLsb, 0x99);
00471     // frame and packet handler settings
00472     writeReg(FSKRegPreambleMsb, 0x00);
00473     writeReg(FSKRegPreambleLsb, 0x05);
00474     writeReg(FSKRegSyncConfig, 0x12);
00475     writeReg(FSKRegPacketConfig1, 0xD0);
00476     writeReg(FSKRegPacketConfig2, 0x40);
00477     writeReg(FSKRegSyncValue1, 0xC1);
00478     writeReg(FSKRegSyncValue2, 0x94);
00479     writeReg(FSKRegSyncValue3, 0xC1);
00480     // configure frequency
00481     configChannel();
00482     // configure output power
00483     configPower();
00484 
00485     // set the IRQ mapping DIO0=PacketSent DIO1=NOP DIO2=NOP
00486     writeReg(RegDioMapping1, MAP_DIO0_FSK_READY|MAP_DIO1_FSK_NOP|MAP_DIO2_FSK_TXNOP);
00487 
00488     // initialize the payload size and address pointers    
00489     writeReg(FSKRegPayloadLength, LMIC.dataLen+1); // (insert length byte into payload))
00490 
00491     // download length byte and buffer to the radio FIFO
00492     writeReg(RegFifo, LMIC.dataLen);
00493     writeBuf(RegFifo, LMIC.frame, LMIC.dataLen);
00494 
00495     // enable antenna switch for TX
00496     //hal_pin_rxtx(1); usint hal_opmode
00497     
00498     // now we actually start the transmission
00499     opmode(OPMODE_TX);
00500 }
00501 
00502 static void txlora () {
00503     // select LoRa modem (from sleep mode)
00504     //writeReg(RegOpMode, OPMODE_LORA);
00505     opmodeLora();
00506     ASSERT((readReg(RegOpMode) & OPMODE_LORA) != 0);
00507 
00508     // enter standby mode (required for FIFO loading))
00509     opmode(OPMODE_STANDBY);
00510     // configure LoRa modem (cfg1, cfg2)
00511     configLoraModem();
00512     // configure frequency
00513     configChannel();
00514     // configure output power
00515     writeReg(RegPaRamp, (readReg(RegPaRamp) & 0xF0) | 0x08); // set PA ramp-up time 50 uSec
00516     configPower();
00517     // set sync word
00518     writeReg(LORARegSyncWord, LORA_MAC_PREAMBLE);
00519     
00520     // set the IRQ mapping DIO0=TxDone DIO1=NOP DIO2=NOP
00521     writeReg(RegDioMapping1, MAP_DIO0_LORA_TXDONE|MAP_DIO1_LORA_NOP|MAP_DIO2_LORA_NOP);
00522     // clear all radio IRQ flags
00523     writeReg(LORARegIrqFlags, 0xFF);
00524     // mask all IRQs but TxDone
00525     writeReg(LORARegIrqFlagsMask, ~IRQ_LORA_TXDONE_MASK);
00526 
00527     // initialize the payload size and address pointers    
00528     writeReg(LORARegFifoTxBaseAddr, 0x00);
00529     writeReg(LORARegFifoAddrPtr, 0x00);
00530     writeReg(LORARegPayloadLength, LMIC.dataLen);
00531        
00532     // download buffer to the radio FIFO
00533     writeBuf(RegFifo, LMIC.frame, LMIC.dataLen);
00534 
00535     // enable antenna switch for TX
00536     //hal_pin_rxtx(1); using hal_opmode
00537     
00538     // now we actually start the transmission
00539     opmode(OPMODE_TX);
00540 }
00541 
00542 // start transmitter (buf=LMIC.frame, len=LMIC.dataLen)
00543 static void starttx () {
00544     ASSERT( (readReg(RegOpMode) & OPMODE_MASK) == OPMODE_SLEEP );
00545     if(getSf(LMIC.rps) == FSK) { // FSK modem
00546         txfsk();
00547     } else { // LoRa modem
00548         txlora();
00549     }
00550     // the radio will go back to STANDBY mode as soon as the TX is finished
00551     // the corresponding IRQ will inform us about completion.
00552 }
00553 
00554 enum { RXMODE_SINGLE, RXMODE_SCAN, RXMODE_RSSI };
00555 
00556 static const u1_t rxlorairqmask[] = {
00557     [RXMODE_SINGLE] = IRQ_LORA_RXDONE_MASK|IRQ_LORA_RXTOUT_MASK,
00558     [RXMODE_SCAN]   = IRQ_LORA_RXDONE_MASK,
00559     [RXMODE_RSSI]   = 0x00,
00560 };
00561 
00562 // start LoRa receiver (time=LMIC.rxtime, timeout=LMIC.rxsyms, result=LMIC.frame[LMIC.dataLen])
00563 static void rxlora (u1_t rxmode) {
00564     // select LoRa modem (from sleep mode)
00565     opmodeLora();
00566     ASSERT((readReg(RegOpMode) & OPMODE_LORA) != 0);
00567     // enter standby mode (warm up))
00568     opmode(OPMODE_STANDBY);
00569     // don't use MAC settings at startup
00570     if(rxmode == RXMODE_RSSI) { // use fixed settings for rssi scan
00571         writeReg(LORARegModemConfig1, RXLORA_RXMODE_RSSI_REG_MODEM_CONFIG1);
00572         writeReg(LORARegModemConfig2, RXLORA_RXMODE_RSSI_REG_MODEM_CONFIG2);
00573     } else { // single or continuous rx mode
00574         // configure LoRa modem (cfg1, cfg2)
00575         configLoraModem();
00576         // configure frequency
00577         configChannel();
00578     }
00579     // set LNA gain
00580     writeReg(RegLna, LNA_RX_GAIN); 
00581     // set max payload size
00582     writeReg(LORARegPayloadMaxLength, 64);
00583     // use inverted I/Q signal (prevent mote-to-mote communication)
00584     writeReg(LORARegInvertIQ, readReg(LORARegInvertIQ)|(1<<6));
00585     // set symbol timeout (for single rx)
00586     writeReg(LORARegSymbTimeoutLsb, LMIC.rxsyms);
00587     // set sync word
00588     writeReg(LORARegSyncWord, LORA_MAC_PREAMBLE);
00589     
00590     // configure DIO mapping DIO0=RxDone DIO1=RxTout DIO2=NOP
00591     writeReg(RegDioMapping1, MAP_DIO0_LORA_RXDONE|MAP_DIO1_LORA_RXTOUT|MAP_DIO2_LORA_NOP);
00592     // clear all radio IRQ flags
00593     writeReg(LORARegIrqFlags, 0xFF);
00594     // enable required radio IRQs
00595     writeReg(LORARegIrqFlagsMask, ~rxlorairqmask[rxmode]);
00596 
00597     // enable antenna switch for RX
00598     //hal_pin_rxtx(0); using hal_opmode
00599 
00600     // now instruct the radio to receive
00601     if (rxmode == RXMODE_SINGLE) { // single rx
00602         hal_waitUntil(LMIC.rxtime); // busy wait until exact rx time
00603         opmode(OPMODE_RX_SINGLE);
00604     } else { // continous rx (scan or rssi)
00605         opmode(OPMODE_RX); 
00606     }
00607 }
00608 
00609 static void rxfsk (u1_t rxmode) {
00610     // only single rx (no continuous scanning, no noise sampling)
00611     ASSERT( rxmode == RXMODE_SINGLE );
00612     // select FSK modem (from sleep mode)
00613     //writeReg(RegOpMode, 0x00); // (not LoRa)
00614     opmodeFSK();
00615     ASSERT((readReg(RegOpMode) & OPMODE_LORA) == 0);
00616     // enter standby mode (warm up))
00617     opmode(OPMODE_STANDBY);
00618     // configure frequency
00619     configChannel();
00620     // set LNA gain
00621     //writeReg(RegLna, 0x20|0x03); // max gain, boost enable
00622     writeReg(RegLna, LNA_RX_GAIN);
00623     // configure receiver
00624     writeReg(FSKRegRxConfig, 0x1E); // AFC auto, AGC, trigger on preamble?!?
00625     // set receiver bandwidth
00626     writeReg(FSKRegRxBw, 0x0B); // 50kHz SSb
00627     // set AFC bandwidth
00628     writeReg(FSKRegAfcBw, 0x12); // 83.3kHz SSB
00629     // set preamble detection
00630     writeReg(FSKRegPreambleDetect, 0xAA); // enable, 2 bytes, 10 chip errors
00631     // set sync config
00632     writeReg(FSKRegSyncConfig, 0x12); // no auto restart, preamble 0xAA, enable, fill FIFO, 3 bytes sync
00633     // set packet config
00634     writeReg(FSKRegPacketConfig1, 0xD8); // var-length, whitening, crc, no auto-clear, no adr filter
00635     writeReg(FSKRegPacketConfig2, 0x40); // packet mode
00636     // set sync value
00637     writeReg(FSKRegSyncValue1, 0xC1);
00638     writeReg(FSKRegSyncValue2, 0x94);
00639     writeReg(FSKRegSyncValue3, 0xC1);
00640     // set preamble timeout
00641     writeReg(FSKRegRxTimeout2, 0xFF);//(LMIC.rxsyms+1)/2);
00642     // set bitrate
00643     writeReg(FSKRegBitrateMsb, 0x02); // 50kbps
00644     writeReg(FSKRegBitrateLsb, 0x80);
00645     // set frequency deviation
00646     writeReg(FSKRegFdevMsb, 0x01); // +/- 25kHz
00647     writeReg(FSKRegFdevLsb, 0x99);
00648     
00649     // configure DIO mapping DIO0=PayloadReady DIO1=NOP DIO2=TimeOut
00650     writeReg(RegDioMapping1, MAP_DIO0_FSK_READY|MAP_DIO1_FSK_NOP|MAP_DIO2_FSK_TIMEOUT);
00651 
00652     // enable antenna switch for RX
00653     //hal_pin_rxtx(0); using hal_opmode
00654     
00655     // now instruct the radio to receive
00656     hal_waitUntil(LMIC.rxtime); // busy wait until exact rx time
00657     opmode(OPMODE_RX); // no single rx mode available in FSK
00658 }
00659 
00660 static void startrx (u1_t rxmode) {
00661     ASSERT( (readReg(RegOpMode) & OPMODE_MASK) == OPMODE_SLEEP );
00662     if(getSf(LMIC.rps) == FSK) { // FSK modem
00663         rxfsk(rxmode);
00664     } else { // LoRa modem
00665         rxlora(rxmode);
00666     }
00667     // the radio will go back to STANDBY mode as soon as the RX is finished
00668     // or timed out, and the corresponding IRQ will inform us about completion.
00669 }
00670 
00671 // get random seed from wideband noise rssi
00672 void radio_init () {
00673     hal_disableIRQs();
00674 
00675     // manually reset radio
00676 #ifdef CFG_sx1276_radio
00677     hal_pin_rst(0); // drive RST pin low
00678 #else
00679     hal_pin_rst(1); // drive RST pin high
00680 #endif
00681     hal_waitUntil(os_getTime()+ms2osticks(1)); // wait >100us
00682     hal_pin_rst(2); // configure RST pin floating!
00683     hal_waitUntil(os_getTime()+ms2osticks(5)); // wait 5ms
00684 
00685     opmode(OPMODE_SLEEP);
00686 
00687     // some sanity checks, e.g., read version number
00688     u1_t v = readReg(RegVersion);
00689 #ifdef CFG_sx1276_radio
00690     ASSERT(v == 0x12 ); 
00691 #elif defined(CFG_sx1272_radio)
00692     ASSERT(v == 0x22);
00693 #else
00694 #error Missing CFG_sx1272_radio/CFG_sx1276_radio
00695 #endif
00696     // seed 15-byte randomness via noise rssi
00697     rxlora(RXMODE_RSSI);
00698     while( (readReg(RegOpMode) & OPMODE_MASK) != OPMODE_RX ); // continuous rx
00699     for(int i=1; i<16; i++) {
00700         for(int j=0; j<8; j++) {
00701             u1_t b; // wait for two non-identical subsequent least-significant bits
00702             while( (b = readReg(LORARegRssiWideband) & 0x01) == (readReg(LORARegRssiWideband) & 0x01) );
00703             randbuf[i] = (randbuf[i] << 1) | b;
00704         }
00705     }
00706     randbuf[0] = 16; // set initial index
00707   
00708 #ifdef CFG_sx1276mb1_board
00709     // chain calibration
00710     writeReg(RegPaConfig, 0);
00711     
00712     // Launch Rx chain calibration for LF band
00713     writeReg(FSKRegImageCal, (readReg(FSKRegImageCal) & RF_IMAGECAL_IMAGECAL_MASK)|RF_IMAGECAL_IMAGECAL_START);
00714     while((readReg(FSKRegImageCal)&RF_IMAGECAL_IMAGECAL_RUNNING) == RF_IMAGECAL_IMAGECAL_RUNNING){ ; }
00715 
00716     // Sets a Frequency in HF band
00717     u4_t frf = 868000000;
00718     writeReg(RegFrfMsb, (u1_t)(frf>>16));
00719     writeReg(RegFrfMid, (u1_t)(frf>> 8));
00720     writeReg(RegFrfLsb, (u1_t)(frf>> 0));
00721 
00722     // Launch Rx chain calibration for HF band 
00723     writeReg(FSKRegImageCal, (readReg(FSKRegImageCal) & RF_IMAGECAL_IMAGECAL_MASK)|RF_IMAGECAL_IMAGECAL_START);
00724     while((readReg(FSKRegImageCal) & RF_IMAGECAL_IMAGECAL_RUNNING) == RF_IMAGECAL_IMAGECAL_RUNNING) { ; }
00725 #endif /* CFG_sx1276mb1_board */
00726 
00727     /* SF12/500KHz RX improvement (0x1d/0x19 choice): must match setting of LORARegInvertIQ */
00728     writeReg(LORARegTimingInvert, 0x19);
00729 
00730     opmode(OPMODE_SLEEP);
00731 
00732     hal_enableIRQs();
00733 }
00734 
00735 // return next random byte derived from seed buffer
00736 // (buf[0] holds index of next byte to be returned)
00737 u1_t radio_rand1 () {
00738     u1_t i = randbuf[0];
00739     ASSERT( i != 0 );
00740     if( i==16 ) {
00741         os_aes(AES_ENC, randbuf, 16); // encrypt seed with any key
00742         i = 0;
00743     }
00744     u1_t v = randbuf[i++];
00745     randbuf[0] = i;
00746     return v;
00747 }
00748 
00749 u1_t radio_rssi () {
00750     hal_disableIRQs();
00751     u1_t r = readReg(LORARegRssiValue);
00752     hal_enableIRQs();
00753     return r;
00754 }
00755 
00756 static const u2_t LORA_RXDONE_FIXUP[] = {
00757     [FSK]  =     us2osticks(0), // (   0 ticks)
00758     [SF7]  =     us2osticks(0), // (   0 ticks)
00759     [SF8]  =  us2osticks(1648), // (  54 ticks)
00760     [SF9]  =  us2osticks(3265), // ( 107 ticks)
00761     [SF10] =  us2osticks(7049), // ( 231 ticks)
00762     [SF11] = us2osticks(13641), // ( 447 ticks)
00763     [SF12] = us2osticks(31189), // (1022 ticks)
00764 };
00765 
00766 // called by hal ext IRQ handler
00767 // (radio goes to stanby mode after tx/rx operations)
00768 void radio_irq_handler (u1_t dio) {
00769     ostime_t now = os_getTime();
00770     if( (readReg(RegOpMode) & OPMODE_LORA) != 0) { // LORA modem
00771         u1_t flags = readReg(LORARegIrqFlags);
00772         if( flags & IRQ_LORA_TXDONE_MASK ) {
00773             // save exact tx time
00774             LMIC.txend = now - us2osticks(43); // TXDONE FIXUP
00775         } else if( flags & IRQ_LORA_RXDONE_MASK ) {
00776             // save exact rx time
00777             if(getBw(LMIC.rps) == BW125) {
00778                 now -= LORA_RXDONE_FIXUP[getSf(LMIC.rps)];
00779             }
00780             LMIC.rxtime = now;
00781             // read the PDU and inform the MAC that we received something
00782             LMIC.dataLen = (readReg(LORARegModemConfig1) & SX1272_MC1_IMPLICIT_HEADER_MODE_ON) ?
00783                 readReg(LORARegPayloadLength) : readReg(LORARegRxNbBytes);
00784             // set FIFO read address pointer
00785             writeReg(LORARegFifoAddrPtr, readReg(LORARegFifoRxCurrentAddr)); 
00786             // now read the FIFO
00787             readBuf(RegFifo, LMIC.frame, LMIC.dataLen);
00788             // read rx quality parameters
00789             LMIC.snr  = readReg(LORARegPktSnrValue); // SNR [dB] * 4
00790             LMIC.rssi = readReg(LORARegPktRssiValue) - 125 + 64; // RSSI [dBm] (-196...+63)
00791         } else if( flags & IRQ_LORA_RXTOUT_MASK ) {
00792             // indicate timeout
00793             LMIC.dataLen = 0;
00794         }
00795         // mask all radio IRQs
00796         writeReg(LORARegIrqFlagsMask, 0xFF);
00797         // clear radio IRQ flags
00798         writeReg(LORARegIrqFlags, 0xFF);
00799     } else { // FSK modem
00800         u1_t flags1 = readReg(FSKRegIrqFlags1);
00801         u1_t flags2 = readReg(FSKRegIrqFlags2);
00802         if( flags2 & IRQ_FSK2_PACKETSENT_MASK ) {
00803             // save exact tx time
00804             LMIC.txend = now;
00805         } else if( flags2 & IRQ_FSK2_PAYLOADREADY_MASK ) {
00806             // save exact rx time
00807             LMIC.rxtime = now;
00808             // read the PDU and inform the MAC that we received something
00809             LMIC.dataLen = readReg(FSKRegPayloadLength);
00810             // now read the FIFO
00811             readBuf(RegFifo, LMIC.frame, LMIC.dataLen);
00812             // read rx quality parameters
00813             LMIC.snr  = 0; // determine snr
00814             LMIC.rssi = 0; // determine rssi
00815         } else if( flags1 & IRQ_FSK1_TIMEOUT_MASK ) {
00816             // indicate timeout
00817             LMIC.dataLen = 0;
00818         } else {
00819             while(1);
00820         }
00821     }
00822     // go from stanby to sleep
00823     opmode(OPMODE_SLEEP);
00824     // run os job (use preset func ptr)
00825     os_setCallback(&LMIC.osjob, LMIC.osjob.func);
00826 }
00827 
00828 void os_radio (u1_t mode) {
00829     hal_disableIRQs();
00830     switch (mode) {
00831       case RADIO_RST:
00832         // put radio to sleep
00833         opmode(OPMODE_SLEEP);
00834         break;
00835 
00836       case RADIO_TX:
00837         // transmit frame now
00838         starttx(); // buf=LMIC.frame, len=LMIC.dataLen
00839         break;
00840       
00841       case RADIO_RX:
00842         // receive frame now (exactly at rxtime)
00843         startrx(RXMODE_SINGLE); // buf=LMIC.frame, time=LMIC.rxtime, timeout=LMIC.rxsyms
00844         break;
00845 
00846       case RADIO_RXON:
00847         // start scanning for beacon now
00848         startrx(RXMODE_SCAN); // buf=LMIC.frame
00849         break;
00850     }
00851     hal_enableIRQs();
00852 }