driver for sx1280

Dependents:   alarm_slave_extended_SX1280 alarm_master_extended_Vance_SX1280

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers sx1280.cpp Source File

sx1280.cpp

00001 #include "sx12xx.h"
00002 
00003 Callback<void()> SX128x::diox_topHalf;    // low latency ISR context
00004 
00005 const float SX128x::timeOutStep[] = { 0.015625, 0.0625, 1, 4 };
00006 
00007 void SX128x::dioxisr()
00008 {
00009     if (diox_topHalf)
00010         diox_topHalf.call();
00011 }
00012 
00013 SX128x::SX128x(SPI& _spi, PinName _nss, PinName _busy, PinName _diox, PinName _nrst)
00014     : spi(_spi), nss(_nss), busy(_busy), diox(_diox), nrst(_nrst)
00015 {
00016     unsigned busyCnt = 0;
00017     nss = 1;
00018 
00019     while (busy) {
00020         if (++busyCnt > 0x80000) {
00021             hw_reset();
00022         }
00023     }
00024 
00025     periodBase = 3;
00026 
00027     diox.rise(dioxisr);
00028 }
00029 
00030 uint8_t SX128x::xfer(uint8_t opcode, uint8_t wlen, uint8_t rlen, uint8_t* ptr)
00031 {
00032     const uint8_t* stopPtr;
00033     const uint8_t* wstop;
00034     const uint8_t* rstop;
00035     uint8_t nop = 0;
00036     uint8_t ret;
00037 
00038     if (opcode != OPCODE_GET_STATUS) {
00039         if (sleeping) {
00040             nss = 0;
00041             while (busy)
00042                 ;
00043             sleeping = false;
00044         } else {
00045             while (busy)
00046                 ;
00047 
00048             nss = 0;
00049         }
00050     } else
00051         nss = 0;
00052 
00053     ret = spi.write(opcode);
00054 
00055     wstop = ptr + wlen;
00056     rstop = ptr + rlen;
00057     if (rlen > wlen)
00058         stopPtr = rstop;
00059     else
00060         stopPtr = wstop;
00061 
00062     for (; ptr < stopPtr; ptr++) {
00063         if (ptr < wstop && ptr < rstop)
00064             *ptr = spi.write(*ptr);
00065         else if (ptr < wstop)
00066             spi.write(*ptr);
00067         else
00068             *ptr = spi.write(nop);    // n >= write length: send NOP
00069     }
00070 
00071     nss = 1;
00072 
00073     if (opcode == OPCODE_SET_SLEEP)
00074         sleeping = true;
00075 
00076     return ret;
00077 }
00078 
00079 uint32_t SX128x::readReg(uint16_t addr, uint8_t len)
00080 {
00081     uint32_t ret = 0;
00082     unsigned i;
00083 
00084     uint8_t buf[7];
00085     buf[0] = addr >> 8;
00086     buf[1] = (uint8_t)addr;
00087     xfer(OPCODE_READ_REGISTER, 2, 3+len, buf);
00088     for (i = 0; i < len; i++) {
00089         ret <<= 8;
00090         ret |= buf[i+3];
00091     }
00092     return ret;
00093 }
00094 
00095 void SX128x::start_tx(uint8_t pktLen, float timeout_ms)
00096 {
00097     IrqFlags_t irqEnable;
00098     uint8_t buf[8];
00099 
00100     irqEnable.word = 0;
00101     irqEnable.bits.TxDone = 1;
00102     irqEnable.bits.RxTxTimeout = 1;
00103 
00104     buf[0] = irqEnable.word >> 8;    // enable bits
00105     buf[1] = irqEnable.word; // enable bits
00106     buf[2] = irqEnable.word >> 8;     // dio1
00107     buf[3] = irqEnable.word;  // dio1
00108     buf[4] = 0; // dio2
00109     buf[5] = 0; // dio2
00110     buf[6] = 0; // dio3
00111     buf[7] = 0; // dio3
00112     xfer(OPCODE_SET_DIO_IRQ_PARAMS, 8, 0, buf);
00113 
00114     {
00115         uint8_t i;
00116 
00117         while (busy)
00118             ;
00119 
00120         nss = 0;
00121         spi.write(OPCODE_WRITE_BUFFER);
00122         spi.write(0);   // offset
00123         i = 0;
00124         for (i = 0; i < pktLen; i++) {
00125             spi.write(tx_buf[i]);
00126         }
00127         nss = 1;
00128     }
00129 
00130     buf[0] = periodBase;
00131     if (timeout_ms > 0) {
00132         unsigned t_o = timeout_ms / timeOutStep[periodBase];
00133         buf[1] = t_o >> 8;
00134         buf[2] = t_o;
00135     } else {
00136         /* no timeout */
00137         buf[1] = 0;
00138         buf[2] = 0;
00139     }
00140     xfer(OPCODE_SET_TX, 3, 0, buf);
00141 
00142     chipMode = CHIPMODE_TX;
00143     if (chipModeChange)
00144         chipModeChange.call();
00145 }
00146 
00147 void SX128x::hw_reset()
00148 {
00149     nrst.output();
00150     nrst = 0;
00151 #if (MBED_MAJOR_VERSION < 6)
00152     ThisThread::sleep_for(1);
00153 #else
00154     ThisThread::sleep_for(1ms);
00155 #endif
00156     nrst = 1;
00157     nrst.mode(PullUp);
00158     nrst.input();
00159 
00160     while (busy)
00161         ;
00162 }
00163 
00164 uint64_t SX128x::getSyncAddr(uint8_t num)
00165 {
00166     uint64_t ret;
00167     unsigned regAdr = REG_ADDR_PKT_SYNC_ADRS_1 + ((num-1) * 5);
00168     ret = readReg(regAdr, 1);
00169     ret <<= 32;
00170     ret |= readReg(regAdr+1, 4);
00171     return ret;
00172 }
00173 
00174 void SX128x::setSyncAddr(uint8_t num, uint64_t sa)
00175 {
00176     unsigned regAdr = REG_ADDR_PKT_SYNC_ADRS_1 + ((num-1) * 5);
00177     writeReg(regAdr+1, sa & 0xffffffff, 4);
00178     sa >>= 32;
00179     writeReg(regAdr, sa & 0xff, 1);
00180 }
00181 
00182 void SX128x::set_tx_dbm(int8_t dbm)
00183 {
00184     uint8_t buf[2];
00185 
00186     buf[0] = dbm;
00187     buf[1] = RADIO_RAMP_20_US;
00188     xfer(OPCODE_SET_TX_PARAMS, 2, 0, buf);
00189 }
00190 
00191 void SX128x::setMHz(float MHz)
00192 {
00193     unsigned frf = MHz / PLL_STEP_MHZ;
00194     uint8_t buf[3];
00195 
00196     buf[0] = frf >> 16;
00197     buf[1] = frf >> 8;
00198     buf[2] = frf;
00199     xfer(OPCODE_SET_RF_FREQUENCY, 3, 0, buf);
00200 }
00201 
00202 float SX128x::getMHz()
00203 {
00204     uint32_t frf;
00205     if (pktType == PACKET_TYPE_LORA)
00206         frf = readReg(REG_ADDR_LORA_SD_FREQ, 3);
00207     else
00208         frf = readReg(REG_ADDR_RFFREQ, 3);
00209 
00210     return frf * PLL_STEP_MHZ;
00211 }
00212 
00213 void SX128x::setStandby(stby_t stby)
00214 {
00215     uint8_t octet = stby;
00216     xfer(OPCODE_SET_STANDBY, 1, 0, &octet);
00217 
00218     chipMode = CHIPMODE_NONE;
00219     if (chipModeChange)
00220         chipModeChange.call();
00221 }
00222 
00223 void SX128x::setCAD()
00224 {
00225     IrqFlags_t irqEnable;
00226     uint8_t buf[8];
00227 
00228     irqEnable.word = 0;
00229     irqEnable.bits.CadDone = 1;
00230     irqEnable.bits.CadDetected = 1;
00231     irqEnable.bits.RxDone = 1;
00232     irqEnable.bits.RxTxTimeout = 1;
00233 
00234     buf[0] = irqEnable.word >> 8;    // enable bits
00235     buf[1] = irqEnable.word; // enable bits
00236     buf[2] = irqEnable.word >> 8;     // dio1
00237     buf[3] = irqEnable.word;  // dio1
00238     buf[4] = 0; // dio2
00239     buf[5] = 0; // dio2
00240     buf[6] = 0; // dio3
00241     buf[7] = 0; // dio3
00242     xfer(OPCODE_SET_DIO_IRQ_PARAMS, 8, 0, buf);
00243 
00244     xfer(OPCODE_SET_CAD, 0, 0, NULL);
00245 
00246     chipMode = CHIPMODE_RX;
00247     if (chipModeChange)
00248         chipModeChange.call();
00249 }
00250 
00251 void SX128x::setFS()
00252 {
00253     xfer(OPCODE_SET_FS, 0, 0, NULL);
00254 
00255     chipMode = CHIPMODE_NONE;
00256     if (chipModeChange)
00257         chipModeChange.call();
00258 }
00259 
00260 void SX128x::setSleep(bool warm)
00261 {
00262     sleepConfig_t sc;
00263 
00264     if (warm) {
00265         xfer(OPCODE_SAVE_CONTEXT, 0, 0, NULL);
00266     }
00267 
00268     chipMode = CHIPMODE_NONE;
00269     if (chipModeChange)
00270         chipModeChange.call();
00271 
00272     sc.octet = 0;
00273     sc.retentionBits.dataRAM         = warm;
00274     sc.retentionBits.dataBuffer      = warm;
00275     sc.retentionBits.instructionRAM  = warm;
00276     xfer(OPCODE_SET_SLEEP, 1, 0, &sc.octet);
00277 }
00278 
00279 uint8_t SX128x::getPacketType()
00280 {
00281     uint8_t buf[2];
00282 
00283     xfer(OPCODE_GET_PACKET_TYPE, 0, 2, buf);
00284     pktType = buf[1];
00285 
00286     return buf[1];
00287 }
00288 
00289 void SX128x::setPacketType(uint8_t type)
00290 {
00291     xfer(OPCODE_SET_PACKET_TYPE, 1, 0, &type);
00292     pktType = type;
00293 }
00294 
00295 void SX128x::setBufferBase(uint8_t txAddr, uint8_t rxAddr)
00296 {
00297     uint8_t buf[2];
00298 
00299     buf[0] = txAddr; // TX base address
00300     buf[1] = rxAddr; // RX base address
00301     xfer(OPCODE_SET_BUFFER_BASE_ADDR, 2, 0, buf);
00302 }
00303 
00304 void SX128x::setRegulator(uint8_t rmp)
00305 {
00306     xfer(OPCODE_SET_REGULATOR_MODE, 1, 0, &rmp);
00307 }
00308 
00309 void SX128x::start_rx(float timeout_ms)
00310 {
00311     IrqFlags_t irqEnable;
00312     uint8_t buf[8];
00313     unsigned t_o;
00314 
00315     irqEnable.word = 0;
00316     irqEnable.bits.RxDone = 1;
00317     irqEnable.bits.RxTxTimeout = 1;
00318 
00319     buf[0] = irqEnable.word >> 8;    // enable bits
00320     buf[1] = irqEnable.word; // enable bits
00321     buf[2] = irqEnable.word >> 8;     // dio1
00322     buf[3] = irqEnable.word;  // dio1
00323     buf[4] = 0; // dio2
00324     buf[5] = 0; // dio2
00325     buf[6] = 0; // dio3
00326     buf[7] = 0; // dio3
00327     xfer(OPCODE_SET_DIO_IRQ_PARAMS, 8, 0, buf);
00328 
00329     buf[0] = periodBase;
00330     if (timeout_ms > 0) {
00331         t_o = timeout_ms / timeOutStep[periodBase];
00332         buf[1] = t_o >> 8;
00333         buf[2] = t_o;
00334     } else {
00335         /* receive packets forever */
00336         buf[1] = 0xff;
00337         buf[2] = 0xff;
00338     }
00339     xfer(OPCODE_SET_RX, 3, 0, buf);
00340 
00341     chipMode = CHIPMODE_RX;
00342     if (chipModeChange) {
00343         chipModeChange.call();
00344     }
00345 }
00346 
00347 void SX128x::service()
00348 {
00349     IrqFlags_t irqFlags, clearIrqFlags;
00350     uint8_t buf[6];
00351     pktStatus_t pktStatus;
00352     //status_t st;
00353 
00354     if (busy) {
00355         return;
00356     }
00357 
00358     while (diox) {
00359         xfer(OPCODE_GET_IRQ_STATUS, 0, 3, buf);
00360         /*st.octet = buf[0]; */
00361         irqFlags.word = buf[1] << 8;
00362         irqFlags.word |= buf[2];
00363         clearIrqFlags.word = 0;
00364         if (irqFlags.bits.TxDone) {
00365             chipMode = CHIPMODE_NONE;
00366             if (chipModeChange)
00367                 chipModeChange.call();
00368             if (txDone)
00369                 txDone.call();  // might change to Rx
00370             clearIrqFlags.bits.TxDone = 1;
00371         }
00372         if (irqFlags.bits.RxDone) {
00373             if (rxDone) {
00374                 uint8_t len, slen;
00375                 xfer(OPCODE_GET_RX_BUFFER_STATUS, 0, 3, buf);
00376                 /*st.octet = buf[0]; */
00377                 if (buf[1] == 0)
00378                     len = readReg(REG_ADDR_LORA_TX_PAYLOAD_LENGTH, 1);  // lora implicit
00379                 else
00380                     len = buf[1];
00381 
00382                 ReadBuffer(len, buf[2]);
00383 
00384                 if (pktType == PACKET_TYPE_LORA || pktType == PACKET_TYPE_RANGING) {
00385                     slen = 3;
00386                     pktStatus.buf[3] = 0;
00387                     pktStatus.buf[4] = 0;
00388                     pktStatus.buf[5] = 0;
00389                 } else
00390                     slen = 6;
00391 
00392                 xfer(OPCODE_GET_PACKET_STATUS, 0, slen, pktStatus.buf);
00393                 rxDone(len, &pktStatus);
00394             }
00395 
00396             clearIrqFlags.bits.RxDone = 1;
00397         }
00398         if (irqFlags.bits.RxTxTimeout) {
00399             if (chipMode != CHIPMODE_NONE) {
00400                 if (timeout)
00401                     timeout(chipMode == CHIPMODE_TX);
00402             }
00403             chipMode = CHIPMODE_NONE;
00404             if (chipModeChange)
00405                 chipModeChange.call();
00406             clearIrqFlags.bits.RxTxTimeout = 1;
00407         }
00408 
00409         if (irqFlags.bits.CadDone) {
00410             if (cadDone)
00411                 cadDone(irqFlags.bits.CadDetected );
00412 
00413             clearIrqFlags.bits.CadDone = 1;
00414             clearIrqFlags.bits.CadDetected = irqFlags.bits.CadDetected;
00415         }
00416 
00417         if (clearIrqFlags.word != 0) {
00418             buf[0] = clearIrqFlags.word >> 8;
00419             buf[1] = (uint8_t)clearIrqFlags.word;
00420             xfer(OPCODE_CLEAR_IRQ_STATUS, 2, 0, buf);
00421         }
00422 
00423     } // ...while (diox)
00424 
00425 } // ..service()
00426 
00427 void SX128x::writeReg(uint16_t addr, uint32_t data, uint8_t len)
00428 {
00429     uint8_t buf[6];
00430     uint8_t n;
00431     buf[0] = addr >> 8;
00432     buf[1] = (uint8_t)addr;
00433     for (n = len; n > 0; n--) {
00434         buf[n+1] = (uint8_t)data;
00435         data >>= 8;
00436     }
00437     xfer(OPCODE_WRITE_REGISTER, 2+len, 2+len, buf);
00438 }
00439 
00440 void SX128x::ReadBuffer(uint8_t size, uint8_t offset)
00441 {
00442     //status_t st;
00443     unsigned i;
00444 
00445     while (busy)
00446         ;
00447 
00448     nss = 0;
00449 
00450     /*st.octet =*/ spi.write(OPCODE_READ_BUFFER);
00451     /*st.octet =*/ spi.write(offset);
00452     /*st.octet =*/ spi.write(0);   // NOP
00453     i = 0;
00454     for (i = 0; i < size; i++) {
00455         rx_buf[i] = spi.write(0);
00456     }
00457 
00458     nss = 1;
00459 }
00460