acid-drop

- Hacking the planet from a LilyGo T-Deck using custom firmware
git clone git://git.acid.vegas/acid-drop.git
Log | Files | Refs | Archive | README | LICENSE

Module.cpp (13876B)

      1 #include "Module.h"
      2 
      3 #if defined(RADIOLIB_BUILD_ARDUINO)
      4 
      5 // we need this to emulate tone() on mbed Arduino boards
      6 #if defined(RADIOLIB_MBED_TONE_OVERRIDE)
      7 #include "mbed.h"
      8 mbed::PwmOut *pwmPin = NULL;
      9 #endif
     10 
     11 Module::Module(RADIOLIB_PIN_TYPE cs, RADIOLIB_PIN_TYPE irq, RADIOLIB_PIN_TYPE rst, RADIOLIB_PIN_TYPE gpio):
     12   _cs(cs),
     13   _irq(irq),
     14   _rst(rst),
     15   _gpio(gpio)
     16 {
     17   _spi = &RADIOLIB_DEFAULT_SPI;
     18   _initInterface = true;
     19 
     20   // this is Arduino build, pre-set callbacks
     21   setCb_pinMode(::pinMode);
     22   setCb_digitalRead(::digitalRead);
     23   setCb_digitalWrite(::digitalWrite);
     24   #if !defined(RADIOLIB_TONE_UNSUPPORTED)
     25   setCb_tone(::tone);
     26   setCb_noTone(::noTone);
     27   #endif
     28   setCb_attachInterrupt(::attachInterrupt);
     29   setCb_detachInterrupt(::detachInterrupt);
     30   #if !defined(RADIOLIB_YIELD_UNSUPPORTED)
     31   setCb_yield(::yield);
     32   #endif
     33   setCb_delay(::delay);
     34   setCb_delayMicroseconds(::delayMicroseconds);
     35   setCb_millis(::millis);
     36   setCb_micros(::micros);
     37   setCb_pulseIn(::pulseIn);
     38   setCb_SPIbegin(&Module::SPIbegin);
     39   setCb_SPIbeginTransaction(&Module::beginTransaction);
     40   setCb_SPItransfer(&Module::transfer);
     41   setCb_SPIendTransaction(&Module::endTransaction);
     42   setCb_SPIend(&Module::end);
     43 }
     44 
     45 Module::Module(RADIOLIB_PIN_TYPE cs, RADIOLIB_PIN_TYPE irq, RADIOLIB_PIN_TYPE rst, RADIOLIB_PIN_TYPE gpio, SPIClass& spi, SPISettings spiSettings):
     46   _cs(cs),
     47   _irq(irq),
     48   _rst(rst),
     49   _gpio(gpio),
     50   _spiSettings(spiSettings)
     51 {
     52   _spi = &spi;
     53   _initInterface = false;
     54 
     55   // this is Arduino build, pre-set callbacks
     56   setCb_pinMode(::pinMode);
     57   setCb_digitalRead(::digitalRead);
     58   setCb_digitalWrite(::digitalWrite);
     59   #if !defined(RADIOLIB_TONE_UNSUPPORTED)
     60   setCb_tone(::tone);
     61   setCb_noTone(::noTone);
     62   #endif
     63   setCb_attachInterrupt(::attachInterrupt);
     64   setCb_detachInterrupt(::detachInterrupt);
     65   #if !defined(RADIOLIB_YIELD_UNSUPPORTED)
     66   setCb_yield(::yield);
     67   #endif
     68   setCb_delay(::delay);
     69   setCb_delayMicroseconds(::delayMicroseconds);
     70   setCb_millis(::millis);
     71   setCb_micros(::micros);
     72   setCb_pulseIn(::pulseIn);
     73   setCb_SPIbegin(&Module::SPIbegin);
     74   setCb_SPIbeginTransaction(&Module::beginTransaction);
     75   setCb_SPItransfer(&Module::transfer);
     76   setCb_SPIendTransaction(&Module::endTransaction);
     77   setCb_SPIend(&Module::end);
     78 }
     79 #else
     80 
     81 Module::Module(RADIOLIB_PIN_TYPE cs, RADIOLIB_PIN_TYPE irq, RADIOLIB_PIN_TYPE rst, RADIOLIB_PIN_TYPE gpio):
     82   _cs(cs),
     83   _irq(irq),
     84   _rst(rst),
     85   _gpio(gpio)
     86 {
     87   // not an Arduino build, it's up to the user to set all callbacks
     88 }
     89 
     90 #endif
     91 
     92 Module::Module(const Module& mod) {
     93   *this = mod;
     94 }
     95 
     96 Module& Module::operator=(const Module& mod) {
     97   this->SPIreadCommand = mod.SPIreadCommand;
     98   this->SPIwriteCommand = mod.SPIwriteCommand;
     99   this->_cs = mod.getCs();
    100   this->_irq = mod.getIrq();
    101   this->_rst = mod.getRst();
    102   this->_gpio = mod.getGpio();
    103 
    104   return(*this);
    105 }
    106 
    107 void Module::init() {
    108   this->pinMode(_cs, OUTPUT);
    109   this->digitalWrite(_cs, HIGH);
    110 #if defined(RADIOLIB_BUILD_ARDUINO)
    111   if(_initInterface) {
    112     (this->*cb_SPIbegin)();
    113   }
    114 #endif
    115 }
    116 
    117 void Module::term() {
    118   // stop hardware interfaces (if they were initialized by the library)
    119 #if defined(RADIOLIB_BUILD_ARDUINO)
    120   if(!_initInterface) {
    121     return;
    122   }
    123 
    124   if(_spi != nullptr) {
    125     this->SPIend();
    126   }
    127 #endif
    128 }
    129 
    130 int16_t Module::SPIgetRegValue(uint8_t reg, uint8_t msb, uint8_t lsb) {
    131   if((msb > 7) || (lsb > 7) || (lsb > msb)) {
    132     return(RADIOLIB_ERR_INVALID_BIT_RANGE);
    133   }
    134 
    135   uint8_t rawValue = SPIreadRegister(reg);
    136   uint8_t maskedValue = rawValue & ((0b11111111 << lsb) & (0b11111111 >> (7 - msb)));
    137   return(maskedValue);
    138 }
    139 
    140 int16_t Module::SPIsetRegValue(uint8_t reg, uint8_t value, uint8_t msb, uint8_t lsb, uint8_t checkInterval, uint8_t checkMask) {
    141   if((msb > 7) || (lsb > 7) || (lsb > msb)) {
    142     return(RADIOLIB_ERR_INVALID_BIT_RANGE);
    143   }
    144 
    145   uint8_t currentValue = SPIreadRegister(reg);
    146   uint8_t mask = ~((0b11111111 << (msb + 1)) | (0b11111111 >> (8 - lsb)));
    147   uint8_t newValue = (currentValue & ~mask) | (value & mask);
    148   SPIwriteRegister(reg, newValue);
    149 
    150   #if defined(RADIOLIB_SPI_PARANOID)
    151     // check register value each millisecond until check interval is reached
    152     // some registers need a bit of time to process the change (e.g. SX127X_REG_OP_MODE)
    153     uint32_t start = this->micros();
    154     uint8_t readValue = 0x00;
    155     while(this->micros() - start < (checkInterval * 1000)) {
    156       readValue = SPIreadRegister(reg);
    157       if((readValue & checkMask) == (newValue & checkMask)) {
    158         // check passed, we can stop the loop
    159         return(RADIOLIB_ERR_NONE);
    160       }
    161     }
    162 
    163     // check failed, print debug info
    164     RADIOLIB_DEBUG_PRINTLN();
    165     RADIOLIB_DEBUG_PRINT(F("address:\t0x"));
    166     RADIOLIB_DEBUG_PRINTLN(reg, HEX);
    167     RADIOLIB_DEBUG_PRINT(F("bits:\t\t"));
    168     RADIOLIB_DEBUG_PRINT(msb);
    169     RADIOLIB_DEBUG_PRINT(' ');
    170     RADIOLIB_DEBUG_PRINTLN(lsb);
    171     RADIOLIB_DEBUG_PRINT(F("value:\t\t0b"));
    172     RADIOLIB_DEBUG_PRINTLN(value, BIN);
    173     RADIOLIB_DEBUG_PRINT(F("current:\t0b"));
    174     RADIOLIB_DEBUG_PRINTLN(currentValue, BIN);
    175     RADIOLIB_DEBUG_PRINT(F("mask:\t\t0b"));
    176     RADIOLIB_DEBUG_PRINTLN(mask, BIN);
    177     RADIOLIB_DEBUG_PRINT(F("new:\t\t0b"));
    178     RADIOLIB_DEBUG_PRINTLN(newValue, BIN);
    179     RADIOLIB_DEBUG_PRINT(F("read:\t\t0b"));
    180     RADIOLIB_DEBUG_PRINTLN(readValue, BIN);
    181     RADIOLIB_DEBUG_PRINTLN();
    182 
    183     return(RADIOLIB_ERR_SPI_WRITE_FAILED);
    184   #else
    185     return(RADIOLIB_ERR_NONE);
    186   #endif
    187 }
    188 
    189 void Module::SPIreadRegisterBurst(uint8_t reg, uint8_t numBytes, uint8_t* inBytes) {
    190   SPItransfer(SPIreadCommand, reg, NULL, inBytes, numBytes);
    191 }
    192 
    193 uint8_t Module::SPIreadRegister(uint8_t reg) {
    194   uint8_t resp = 0;
    195   SPItransfer(SPIreadCommand, reg, NULL, &resp, 1);
    196   return(resp);
    197 }
    198 
    199 void Module::SPIwriteRegisterBurst(uint8_t reg, uint8_t* data, uint8_t numBytes) {
    200   SPItransfer(SPIwriteCommand, reg, data, NULL, numBytes);
    201 }
    202 
    203 void Module::SPIwriteRegister(uint8_t reg, uint8_t data) {
    204   SPItransfer(SPIwriteCommand, reg, &data, NULL, 1);
    205 }
    206 
    207 void Module::SPItransfer(uint8_t cmd, uint8_t reg, uint8_t* dataOut, uint8_t* dataIn, uint8_t numBytes) {
    208   // start SPI transaction
    209   this->SPIbeginTransaction();
    210 
    211   // pull CS low
    212   this->digitalWrite(_cs, LOW);
    213 
    214   // send SPI register address with access command
    215   this->SPItransfer(reg | cmd);
    216   #if defined(RADIOLIB_VERBOSE)
    217     if(cmd == SPIwriteCommand) {
    218       RADIOLIB_VERBOSE_PRINT('W');
    219     } else if(cmd == SPIreadCommand) {
    220       RADIOLIB_VERBOSE_PRINT('R');
    221     }
    222     RADIOLIB_VERBOSE_PRINT('\t')
    223     RADIOLIB_VERBOSE_PRINT(reg, HEX);
    224     RADIOLIB_VERBOSE_PRINT('\t');
    225   #endif
    226 
    227   // send data or get response
    228   if(cmd == SPIwriteCommand) {
    229     if(dataOut != NULL) {
    230       for(size_t n = 0; n < numBytes; n++) {
    231         this->SPItransfer(dataOut[n]);
    232         RADIOLIB_VERBOSE_PRINT(dataOut[n], HEX);
    233         RADIOLIB_VERBOSE_PRINT('\t');
    234       }
    235     }
    236   } else if (cmd == SPIreadCommand) {
    237     if(dataIn != NULL) {
    238       for(size_t n = 0; n < numBytes; n++) {
    239         dataIn[n] = this->SPItransfer(0x00);
    240         RADIOLIB_VERBOSE_PRINT(dataIn[n], HEX);
    241         RADIOLIB_VERBOSE_PRINT('\t');
    242       }
    243     }
    244   }
    245   RADIOLIB_VERBOSE_PRINTLN();
    246 
    247   // release CS
    248   this->digitalWrite(_cs, HIGH);
    249 
    250   // end SPI transaction
    251   this->SPIendTransaction();
    252 }
    253 
    254 void Module::pinMode(RADIOLIB_PIN_TYPE pin, RADIOLIB_PIN_MODE mode) {
    255   if((pin == RADIOLIB_NC) || (cb_pinMode == nullptr)) {
    256     return;
    257   }
    258   cb_pinMode(pin, mode);
    259 }
    260 
    261 void Module::digitalWrite(RADIOLIB_PIN_TYPE pin, RADIOLIB_PIN_STATUS value) {
    262   if((pin == RADIOLIB_NC) || (cb_digitalWrite == nullptr)) {
    263     return;
    264   }
    265   cb_digitalWrite(pin, value);
    266 }
    267 
    268 RADIOLIB_PIN_STATUS Module::digitalRead(RADIOLIB_PIN_TYPE pin) {
    269   if((pin == RADIOLIB_NC) || (cb_digitalRead == nullptr)) {
    270     return((RADIOLIB_PIN_STATUS)0);
    271   }
    272   return(cb_digitalRead(pin));
    273 }
    274 
    275 #if defined(ESP32)
    276 // we need to cache the previous tone value for emulation on ESP32
    277 int32_t prev = -1;
    278 #endif
    279 
    280 void Module::tone(RADIOLIB_PIN_TYPE pin, uint16_t value, uint32_t duration) {
    281   #if !defined(RADIOLIB_TONE_UNSUPPORTED)
    282   if((pin == RADIOLIB_NC) || (cb_tone == nullptr)) {
    283     return;
    284   }
    285   cb_tone(pin, value, duration);
    286   #else
    287   if(pin == RADIOLIB_NC) {
    288     return;
    289   }
    290     #if defined(ESP32)
    291       // ESP32 tone() emulation
    292       (void)duration;
    293       if(prev == -1) {
    294         ledcAttachPin(pin, RADIOLIB_TONE_ESP32_CHANNEL);
    295       }
    296       if(prev != value) {
    297         ledcWriteTone(RADIOLIB_TONE_ESP32_CHANNEL, value);
    298       }
    299       prev = value;
    300     #elif defined(RADIOLIB_MBED_TONE_OVERRIDE)
    301       // better tone for mbed OS boards
    302       (void)duration;
    303       if(!pwmPin) {
    304         pwmPin = new mbed::PwmOut(digitalPinToPinName(pin));
    305       }
    306       pwmPin->period(1.0 / value);
    307       pwmPin->write(0.5);
    308     #else
    309       (void)value;
    310       (void)duration;
    311     #endif
    312   #endif
    313 }
    314 
    315 void Module::noTone(RADIOLIB_PIN_TYPE pin) {
    316   #if !defined(RADIOLIB_TONE_UNSUPPORTED)
    317   if((pin == RADIOLIB_NC) || (cb_noTone == nullptr)) {
    318     return;
    319   }
    320   #if defined(ARDUINO_ARCH_STM32)
    321   cb_noTone(pin, false);
    322   #else
    323   cb_noTone(pin);
    324   #endif
    325   #else
    326   if(pin == RADIOLIB_NC) {
    327     return;
    328   }
    329     #if defined(ESP32)
    330       // ESP32 tone() emulation
    331       ledcDetachPin(pin);
    332       ledcWrite(RADIOLIB_TONE_ESP32_CHANNEL, 0);
    333       prev = -1;
    334     #elif defined(RADIOLIB_MBED_TONE_OVERRIDE)
    335       // better tone for mbed OS boards
    336       (void)pin;
    337       pwmPin->suspend();
    338     #endif
    339   #endif
    340 }
    341 
    342 void Module::attachInterrupt(RADIOLIB_PIN_TYPE interruptNum, void (*userFunc)(void), RADIOLIB_INTERRUPT_STATUS mode) {
    343   if((interruptNum == RADIOLIB_NC) || (cb_attachInterrupt == nullptr)) {
    344     return;
    345   }
    346   cb_attachInterrupt(interruptNum, userFunc, mode);
    347 }
    348 
    349 void Module::detachInterrupt(RADIOLIB_PIN_TYPE interruptNum) {
    350   if((interruptNum == RADIOLIB_NC) || (cb_detachInterrupt == nullptr)) {
    351     return;
    352   }
    353   cb_detachInterrupt(interruptNum);
    354 }
    355 
    356 void Module::yield() {
    357   if(cb_yield == nullptr) {
    358     return;
    359   }
    360   #if !defined(RADIOLIB_YIELD_UNSUPPORTED)
    361   cb_yield();
    362   #endif
    363 }
    364 
    365 void Module::delay(uint32_t ms) {
    366   if(cb_delay == nullptr) {
    367     return;
    368   }
    369   cb_delay(ms);
    370 }
    371 
    372 void Module::delayMicroseconds(uint32_t us) {
    373   if(cb_delayMicroseconds == nullptr) {
    374     return;
    375   }
    376   cb_delayMicroseconds(us);
    377 }
    378 
    379 uint32_t Module::millis() {
    380   if(cb_millis == nullptr) {
    381     return(0);
    382   }
    383   return(cb_millis());
    384 }
    385 
    386 uint32_t Module::micros() {
    387   if(cb_micros == nullptr) {
    388     return(0);
    389   }
    390   return(cb_micros());
    391 }
    392 
    393 uint32_t Module::pulseIn(RADIOLIB_PIN_TYPE pin, RADIOLIB_PIN_STATUS state, uint32_t timeout) {
    394   if(cb_pulseIn == nullptr) {
    395     return(0);
    396   }
    397   return(cb_pulseIn(pin, state, timeout));
    398 }
    399 
    400 void Module::begin() {
    401 #if defined(RADIOLIB_BUILD_ARDUINO)
    402   if(cb_SPIbegin == nullptr) {
    403     return;
    404   }
    405   (this->*cb_SPIbegin)();
    406 #endif
    407 }
    408 
    409 void Module::beginTransaction() {
    410 #if defined(RADIOLIB_BUILD_ARDUINO)
    411   if(cb_SPIbeginTransaction == nullptr) {
    412     return;
    413   }
    414   (this->*cb_SPIbeginTransaction)();
    415 #endif
    416 }
    417 
    418 uint8_t Module::transfer(uint8_t b) {
    419 #if defined(RADIOLIB_BUILD_ARDUINO)
    420   if(cb_SPItransfer == nullptr) {
    421     return(0xFF);
    422   }
    423   return((this->*cb_SPItransfer)(b));
    424 #endif
    425 }
    426 
    427 void Module::endTransaction() {
    428 #if defined(RADIOLIB_BUILD_ARDUINO)
    429   if(cb_SPIendTransaction == nullptr) {
    430     return;
    431   }
    432   (this->*cb_SPIendTransaction)();
    433 #endif
    434 }
    435 
    436 void Module::end() {
    437 #if defined(RADIOLIB_BUILD_ARDUINO)
    438   if(cb_SPIend == nullptr) {
    439     return;
    440   }
    441   (this->*cb_SPIend)();
    442 #endif
    443 }
    444 
    445 #if defined(RADIOLIB_BUILD_ARDUINO)
    446 void Module::SPIbegin() {
    447   _spi->begin();
    448 }
    449 #endif
    450 
    451 void Module::SPIbeginTransaction() {
    452 #if defined(RADIOLIB_BUILD_ARDUINO)
    453   _spi->beginTransaction(_spiSettings);
    454 #endif
    455 }
    456 
    457 uint8_t Module::SPItransfer(uint8_t b) {
    458 #if defined(RADIOLIB_BUILD_ARDUINO)
    459   return(_spi->transfer(b));
    460 #endif
    461 }
    462 
    463 void Module::SPIendTransaction() {
    464 #if defined(RADIOLIB_BUILD_ARDUINO)
    465   _spi->endTransaction();
    466 #endif
    467 }
    468 
    469 #if defined(RADIOLIB_BUILD_ARDUINO)
    470 void Module::SPIend() {
    471   _spi->end();
    472 }
    473 #endif
    474 
    475 uint8_t Module::flipBits(uint8_t b) {
    476   b = (b & 0xF0) >> 4 | (b & 0x0F) << 4;
    477   b = (b & 0xCC) >> 2 | (b & 0x33) << 2;
    478   b = (b & 0xAA) >> 1 | (b & 0x55) << 1;
    479   return b;
    480 }
    481 
    482 uint16_t Module::flipBits16(uint16_t i) {
    483   i = (i & 0xFF00) >> 8 | (i & 0x00FF) << 8;
    484   i = (i & 0xF0F0) >> 4 | (i & 0x0F0F) << 4;
    485   i = (i & 0xCCCC) >> 2 | (i & 0x3333) << 2;
    486   i = (i & 0xAAAA) >> 1 | (i & 0x5555) << 1;
    487   return i;
    488 }
    489 
    490 void Module::hexdump(uint8_t* data, size_t len) {
    491   size_t rem_len = len;
    492   for(int i = 0; i < len; i+=16) {
    493     char str[80];
    494     sprintf(str, "%07x  ", i);
    495     size_t line_len = 16;
    496     if(rem_len < line_len) {
    497       line_len = rem_len;
    498     }
    499     for(int j = 0; j < line_len; j++) {
    500       sprintf(&str[8 + j*3], "%02x ", data[i+j]);
    501     }
    502     for(int j = line_len; j < 16; j++) {
    503       sprintf(&str[8 + j*3], "   ");
    504     }
    505     str[56] = '|';
    506     str[57] = ' ';
    507     for(int j = 0; j < line_len; j++) {
    508       char c = data[i+j];
    509       if((c < ' ') || (c > '~')) {
    510         c = '.';
    511       }
    512       sprintf(&str[58 + j], "%c", c);
    513     }
    514     for(int j = line_len; j < 16; j++) {
    515       sprintf(&str[58 + j], "   ");
    516     }
    517     RADIOLIB_DEBUG_PRINTLN(str);
    518     rem_len -= 16;
    519   }
    520 }
    521 
    522 void Module::regdump(uint8_t start, uint8_t len) {
    523   #if defined(RADIOLIB_STATIC_ONLY)
    524     uint8_t buff[RADIOLIB_STATIC_ARRAY_SIZE];
    525   #else
    526     uint8_t* buff = new uint8_t[len];
    527   #endif
    528   SPIreadRegisterBurst(start, len, buff);
    529   hexdump(buff, len);
    530   #if !defined(RADIOLIB_STATIC_ONLY)
    531     delete[] buff;
    532   #endif
    533 }
    534 
    535 void Module::setRfSwitchPins(RADIOLIB_PIN_TYPE rxEn, RADIOLIB_PIN_TYPE txEn) {
    536   _useRfSwitch = true;
    537   _rxEn = rxEn;
    538   _txEn = txEn;
    539   this->pinMode(rxEn, OUTPUT);
    540   this->pinMode(txEn, OUTPUT);
    541 }
    542 
    543 void Module::setRfSwitchState(RADIOLIB_PIN_STATUS rxPinState, RADIOLIB_PIN_STATUS txPinState) {
    544   // check RF switch control is enabled
    545   if(!_useRfSwitch) {
    546     return;
    547   }
    548 
    549   // set pins
    550   this->digitalWrite(_rxEn, rxPinState);
    551   this->digitalWrite(_txEn, txPinState);
    552 }