sx1261/2 driver

Dependents:   alarm_slave iq_sx126x sx126x_simple_TX_shield_2020a sx126x_simple_RX_shield_2020a ... more

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers sx126x.cpp Source File

sx126x.cpp

00001 #include "sx12xx.h"
00002 
00003 Callback<void()> SX126x::dio1_topHalf;    // low latency ISR context
00004 
00005 void SX126x::dio1isr()
00006 {
00007     if (dio1_topHalf)
00008         dio1_topHalf.call();
00009 }
00010 
00011 SX126x::SX126x(SPI& _spi, PinName _nss, PinName _busy, PinName _dio1)
00012     : spi(_spi), nss(_nss), busy(_busy), dio1(_dio1)
00013 {
00014     uint8_t buf[8];
00015     IrqFlags_t irqEnable;
00016 
00017     nss = 1;
00018 
00019     dio1.rise(dio1isr);
00020 
00021 
00022     irqEnable.word = 0;
00023     irqEnable.bits.TxDone = 1;
00024     irqEnable.bits.RxDone = 1;
00025     irqEnable.bits.Timeout = 1;
00026 
00027     buf[0] = irqEnable.word >> 8;    // enable bits
00028     buf[1] = irqEnable.word; // enable bits
00029     buf[2] = irqEnable.word >> 8;     // dio1
00030     buf[3] = irqEnable.word;  // dio1
00031     buf[4] = 0; // dio2
00032     buf[5] = 0; // dio2
00033     buf[6] = 0; // dio3
00034     buf[7] = 0; // dio3
00035     xfer(OPCODE_SET_DIO_IRQ_PARAMS, 8, 0, buf);
00036 
00037 }
00038 
00039 void SX126x::PrintChipStatus(status_t status)
00040 {
00041     printf("%02x cmdStatus:", status.octet);
00042     switch (status.bits.cmdStatus) {
00043         case 0: printf("Reserved"); break;
00044         case 1: printf("RFU"); break;
00045         case 2: printf("dataAvail"); break;
00046         case 3: printf("cmdTimeout"); break;
00047         case 4: printf("cmdError"); break;
00048         case 5: printf("execFail"); break;
00049         case 6: printf("cmdTxDone"); break;
00050     }
00051     printf(" chipMode:");
00052     switch (status.bits.chipMode) {
00053         case 0: printf("Unused"); break;
00054         case 1: printf("RFU"); break;
00055         case 2: printf("STBY_RC"); break;
00056         case 3: printf("STBY_XOSC"); break;
00057         case 4: printf("FS"); break;
00058         case 5: printf("RX"); break;
00059         case 6: printf("TX"); break;
00060     }
00061     printf("\r\n");
00062 }
00063 
00064 void SX126x::service()
00065 {
00066     IrqFlags_t irqFlags, clearIrqFlags;
00067     uint8_t buf[4];
00068 
00069     if (busy) {
00070         return;
00071     }
00072 
00073     while (dio1) {
00074         xfer(OPCODE_GET_IRQ_STATUS, 0, 3, buf);
00075         irqFlags.word = buf[1] << 8;
00076         irqFlags.word |= buf[2];
00077         clearIrqFlags.word = 0;
00078         if (irqFlags.bits.TxDone) {
00079             chipMode = CHIPMODE_NONE;
00080             if (chipModeChange)
00081                 chipModeChange.call();  // might change to Rx
00082             if (txDone)
00083                 txDone.call();
00084             clearIrqFlags.bits.TxDone = 1;
00085         }
00086         if (irqFlags.bits.RxDone) {
00087             if (rxDone) {
00088                 uint8_t len;
00089                 float snr, rssi;
00090                 int8_t s;
00091                 xfer(OPCODE_GET_RX_BUFFER_STATUS, 0, 3, buf);
00092                 len = buf[1];
00093                 ReadBuffer(len, buf[2]);
00094                 xfer(OPCODE_GET_PACKET_STATUS, 0, 4, buf);
00095                 rssi = -buf[1] / 2.0;   // TODO FSK
00096                 s = buf[2];
00097                 snr = s / 4.0;
00098                 rxDone(len, rssi, snr);
00099             }
00100             clearIrqFlags.bits.RxDone = 1;
00101         }
00102         if (irqFlags.bits.Timeout) {
00103             if (chipMode != CHIPMODE_NONE) {
00104                 if (timeout)
00105                     timeout(chipMode == CHIPMODE_TX);
00106             }
00107             chipMode = CHIPMODE_NONE;
00108             if (chipModeChange)
00109                 chipModeChange.call();
00110             clearIrqFlags.bits.Timeout = 1;
00111         }
00112         if (irqFlags.bits.CadDone) {
00113             if (cadDone)
00114                 cadDone(irqFlags.bits.CadDetected);
00115 
00116             clearIrqFlags.bits.CadDone = 1;
00117             clearIrqFlags.bits.CadDetected = irqFlags.bits.CadDetected;
00118         }
00119         if (irqFlags.bits.PreambleDetected) {
00120             clearIrqFlags.bits.PreambleDetected = 1;
00121             if (preambleDetected)
00122                 preambleDetected();
00123         }
00124 
00125         if (clearIrqFlags.word != 0) {
00126             buf[0] = clearIrqFlags.word >> 8;
00127             buf[1] = (uint8_t)clearIrqFlags.word;
00128             xfer(OPCODE_CLEAR_IRQ_STATUS, 2, 0, buf);
00129         }
00130 
00131     } // ...while (dio1)
00132 
00133 } // ..service()
00134 
00135 void SX126x::xfer(uint8_t opcode, uint8_t wlen, uint8_t rlen, uint8_t* ptr)
00136 {
00137     const uint8_t* stopPtr;
00138     const uint8_t* wstop;
00139     const uint8_t* rstop;
00140     uint8_t nop = 0;
00141 
00142     if (sleeping) {
00143         nss = 0;
00144         while (busy)
00145             ;
00146         sleeping = false;
00147     } else {
00148         while (busy)
00149             ;
00150         nss = 0;
00151     }
00152 
00153     spi.write(opcode);
00154 
00155     wstop = ptr + wlen;
00156     rstop = ptr + rlen;
00157     if (rlen > wlen)
00158         stopPtr = rstop;
00159     else
00160         stopPtr = wstop;
00161 
00162     for (; ptr < stopPtr; ptr++) {
00163         if (ptr < wstop && ptr < rstop)
00164             *ptr = spi.write(*ptr);
00165         else if (ptr < wstop)
00166             spi.write(*ptr);
00167         else
00168             *ptr = spi.write(nop);    // n >= write length: send NOP
00169     }
00170 
00171     nss = 1;
00172 
00173     if (opcode == OPCODE_SET_SLEEP)
00174         sleeping = true;
00175 }
00176 
00177 void SX126x::start_tx(uint8_t pktLen)
00178 {
00179     uint8_t buf[8];
00180 
00181     {
00182         uint8_t i;
00183 
00184         while (busy)
00185             ;
00186 
00187         nss = 0;
00188         spi.write(OPCODE_WRITE_BUFFER);
00189         spi.write(0);   // offset
00190         i = 0;
00191         for (i = 0; i < pktLen; i++) {
00192             spi.write(tx_buf[i]);
00193         }
00194         nss = 1;
00195     }
00196 
00197     buf[0] = 0x40;
00198     buf[1] = 0x00;
00199     buf[2] = 0x00;
00200     xfer(OPCODE_SET_TX, 3, 0, buf);
00201 
00202     chipMode = CHIPMODE_TX;
00203     if (chipModeChange)
00204         chipModeChange.call();
00205 }
00206 
00207 void SX126x::start_rx(unsigned timeout)
00208 {
00209     uint8_t buf[8];
00210 
00211     buf[0] = timeout >> 16;
00212     buf[1] = timeout >> 8;
00213     buf[2] = timeout;
00214     xfer(OPCODE_SET_RX, 3, 0, buf);
00215 
00216     chipMode = CHIPMODE_RX;
00217     if (chipModeChange)
00218         chipModeChange.call();
00219 }
00220 
00221 uint8_t SX126x::setMHz(float MHz)
00222 {
00223     unsigned frf = MHz * MHZ_TO_FRF;
00224     uint8_t buf[4];
00225 
00226     buf[0] = frf >> 24;
00227     buf[1] = frf >> 16;
00228     buf[2] = frf >> 8;
00229     buf[3] = frf;
00230     xfer(OPCODE_SET_RF_FREQUENCY, 4, 0, buf);
00231     return buf[3];
00232 }
00233 
00234 float SX126x::getMHz()
00235 {
00236     uint32_t frf = readReg(REG_ADDR_RFFREQ, 4);
00237     return frf / (float)MHZ_TO_FRF;
00238 }
00239 
00240 void SX126x::setPacketType(uint8_t type)
00241 {
00242     xfer(OPCODE_SET_PACKET_TYPE, 1, 0, &type);
00243 }
00244 
00245 uint8_t SX126x::getPacketType()
00246 {
00247     uint8_t buf[2];
00248     xfer(OPCODE_GET_PACKET_TYPE, 0, 2, buf);
00249     return buf[1];
00250 }
00251 
00252 void SX126x::SetDIO2AsRfSwitchCtrl(uint8_t en)
00253 {
00254     xfer(OPCODE_SET_DIO2_AS_RFSWITCH, 1, 0, &en);
00255 }
00256 
00257 void SX126x::ReadBuffer(uint8_t size, uint8_t offset)
00258 {
00259     unsigned i;
00260     while (busy)
00261         ;
00262 
00263     nss = 0;
00264 
00265     spi.write(OPCODE_READ_BUFFER);
00266     spi.write(offset);
00267     spi.write(0);   // NOP
00268     i = 0;
00269     for (i = 0; i < size; i++) {
00270         rx_buf[i] = spi.write(0);
00271     }
00272 
00273     nss = 1;
00274 }
00275 
00276 void SX126x::set_tx_dbm(bool is1262, int8_t dbm)
00277 {
00278     uint8_t buf[4];
00279     // use OCP default
00280 
00281     buf[3] = 1;
00282     if (is1262) {
00283         buf[0] = 4;
00284         buf[1] = 7;
00285         buf[2] = 0;
00286 
00287         if (dbm > 22)
00288             dbm = 22;
00289         else if (dbm < -3)
00290             dbm = -3;
00291     } else {
00292         if (dbm == 15)
00293             buf[0] = 6;
00294         else
00295             buf[0] = 4;
00296         buf[1] = 0;
00297         buf[2] = 1;
00298 
00299         if (dbm > 14)
00300             dbm = 14;
00301         else if (dbm < -3)
00302             dbm = -3;
00303     }
00304     xfer(OPCODE_SET_PA_CONFIG, 4, 0, buf);
00305 
00306     if (is1262 && dbm > 18) {
00307         /* OCP is set by chip whenever SetPaConfig() is called */
00308         writeReg(REG_ADDR_OCP, 0x38, 1);
00309     }
00310 
00311     // SetTxParams
00312     buf[0] = dbm;
00313     //if (opt == 0) txco
00314     buf[1] = SET_RAMP_200U;
00315     xfer(OPCODE_SET_TX_PARAMS, 2, 0, buf);
00316 }
00317 
00318 void SX126x::writeReg(uint16_t addr, uint32_t data, uint8_t len)
00319 {
00320     uint8_t buf[6];
00321     uint8_t n;
00322     buf[0] = addr >> 8;
00323     buf[1] = (uint8_t)addr;
00324     for (n = len; n > 0; n--) {
00325         buf[n+1] = (uint8_t)data;
00326         data >>= 8;
00327     }
00328     xfer(OPCODE_WRITE_REGISTER, 2+len, 2+len, buf);
00329 }
00330 
00331 void SX126x::setStandby(stby_t stby)
00332 {
00333     uint8_t octet = stby;
00334     xfer(OPCODE_SET_STANDBY, 1, 0, &octet);
00335 
00336     chipMode = CHIPMODE_NONE;
00337     if (chipModeChange)
00338         chipModeChange.call();
00339 }
00340 
00341 void SX126x::setFS()
00342 {
00343     xfer(OPCODE_SET_FS, 0, 0, NULL);
00344 
00345     chipMode = CHIPMODE_NONE;
00346     if (chipModeChange)
00347         chipModeChange.call();
00348 }
00349 
00350 void SX126x::setCAD()
00351 {
00352     xfer(OPCODE_SET_CAD, 0, 0, NULL);
00353 
00354     chipMode = CHIPMODE_RX;
00355     if (chipModeChange)
00356         chipModeChange.call();
00357 }
00358 
00359 void SX126x::setSleep(bool warmStart, bool rtcWakeup)
00360 {
00361     sleepConfig_t sc;
00362 
00363     sc.octet = 0;
00364     sc.bits.rtcWakeup = rtcWakeup;
00365     sc.bits.warmStart = warmStart;
00366     xfer(OPCODE_SET_SLEEP, 1, 0, &sc.octet);
00367 
00368     chipMode = CHIPMODE_NONE;
00369     if (chipModeChange)
00370         chipModeChange.call();
00371 }
00372 
00373 void SX126x::hw_reset(PinName pin)
00374 {
00375     DigitalInOut nrst(pin);
00376     nrst.output();
00377     nrst = 0;
00378 #if (MBED_MAJOR_VERSION < 6)
00379     ThisThread::sleep_for(1);
00380 #else
00381     ThisThread::sleep_for(1ms);
00382 #endif
00383     nrst = 1;
00384     nrst.mode(PullUp);
00385     nrst.input();
00386 
00387     while (busy)
00388         ;
00389 }
00390 
00391 uint32_t SX126x::readReg(uint16_t addr, uint8_t len)
00392 {
00393     uint32_t ret = 0;
00394     unsigned i;
00395 
00396     uint8_t buf[7];
00397     buf[0] = addr >> 8;
00398     buf[1] = (uint8_t)addr;
00399     xfer(OPCODE_READ_REGISTER, 2, 3+len, buf);
00400     for (i = 0; i < len; i++) {
00401         ret <<= 8;
00402         ret |= buf[i+3];
00403     }
00404     return ret;
00405 }
00406 
00407 void SX126x::setBufferBase(uint8_t txAddr, uint8_t rxAddr)
00408 {
00409     uint8_t buf[2];
00410 
00411     buf[0] = 0; // TX base address
00412     buf[1] = 0; // RX base address
00413     xfer(OPCODE_SET_BUFFER_BASE_ADDR, 2, 0, buf);
00414 }