Senet / lmic_MOTE_L152RC

Dependents:   Senet NAMote

Fork of lmic_MOTE_L152RC_2 by Dave Kjendal

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