diff --git a/RF24.cpp b/RF24.cpp index 9e5b4a8..af00758 100644 --- a/RF24.cpp +++ b/RF24.cpp @@ -12,228 +12,24 @@ /****************************************************************************/ -void RF24::csn(bool mode) -{ -#if defined(RF24_TINY) - if (ce_pin != csn_pin) { - digitalWrite(csn_pin, mode); - } - else { - if (mode == HIGH) { - PORTB |= (1 << PINB2); // SCK->CSN HIGH - delayMicroseconds(RF24_CSN_SETTLE_HIGH_DELAY); // allow csn to settle. - } - else { - PORTB &= ~(1 << PINB2); // SCK->CSN LOW - delayMicroseconds(RF24_CSN_SETTLE_LOW_DELAY); // allow csn to settle - } - } - // Return, CSN toggle complete - return; - -#elif defined(ARDUINO) && !defined(RF24_SPI_TRANSACTIONS) - // Minimum ideal SPI bus speed is 2x data rate - // If we assume 2Mbs data rate and 16Mhz clock, a - // divider of 4 is the minimum we want. - // CLK:BUS 8Mhz:2Mhz, 16Mhz:4Mhz, or 20Mhz:5Mhz - - #if !defined(SOFTSPI) - // applies to SPI_UART and inherent hardware SPI - #if defined(RF24_SPI_PTR) - _spi->setBitOrder(MSBFIRST); - _spi->setDataMode(SPI_MODE0); - - #if !defined(F_CPU) || F_CPU < 20000000 - _spi->setClockDivider(SPI_CLOCK_DIV2); - #elif F_CPU < 40000000 - _spi->setClockDivider(SPI_CLOCK_DIV4); - #elif F_CPU < 80000000 - _spi->setClockDivider(SPI_CLOCK_DIV8); - #elif F_CPU < 160000000 - _spi->setClockDivider(SPI_CLOCK_DIV16); - #elif F_CPU < 320000000 - _spi->setClockDivider(SPI_CLOCK_DIV32); - #elif F_CPU < 640000000 - _spi->setClockDivider(SPI_CLOCK_DIV64); - #elif F_CPU < 1280000000 - _spi->setClockDivider(SPI_CLOCK_DIV128); - #else // F_CPU >= 1280000000 - #error "Unsupported CPU frequency. Please set correct SPI divider." - #endif // F_CPU to SPI_CLOCK_DIV translation - - #else // !defined(RF24_SPI_PTR) - _SPI.setBitOrder(MSBFIRST); - _SPI.setDataMode(SPI_MODE0); - - #if !defined(F_CPU) || F_CPU < 20000000 - _SPI.setClockDivider(SPI_CLOCK_DIV2); - #elif F_CPU < 40000000 - _SPI.setClockDivider(SPI_CLOCK_DIV4); - #elif F_CPU < 80000000 - _SPI.setClockDivider(SPI_CLOCK_DIV8); - #elif F_CPU < 160000000 - _SPI.setClockDivider(SPI_CLOCK_DIV16); - #elif F_CPU < 320000000 - _SPI.setClockDivider(SPI_CLOCK_DIV32); - #elif F_CPU < 640000000 - _SPI.setClockDivider(SPI_CLOCK_DIV64); - #elif F_CPU < 1280000000 - _SPI.setClockDivider(SPI_CLOCK_DIV128); - #else // F_CPU >= 1280000000 - #error "Unsupported CPU frequency. Please set correct SPI divider." - #endif // F_CPU to SPI_CLOCK_DIV translation - #endif // !defined(RF24_SPI_PTR) - #endif // !defined(SOFTSPI) - -#elif defined(RF24_RPi) - if (!mode) - _SPI.chipSelect(csn_pin); -#endif // defined(RF24_RPi) - -#if !defined(RF24_LINUX) - digitalWrite(csn_pin, mode); - delayMicroseconds(csDelay); -#else - static_cast(mode); // ignore -Wunused-parameter -#endif // !defined(RF24_LINUX) -} - -/****************************************************************************/ - void RF24::ce(bool level) { -#ifndef RF24_LINUX - //Allow for 3-pin use on ATTiny - if (ce_pin != csn_pin) { -#endif - digitalWrite(ce_pin, level); -#ifndef RF24_LINUX - } -#endif -} - -/****************************************************************************/ - -inline void RF24::beginTransaction() -{ -#if defined(RF24_SPI_TRANSACTIONS) - #if defined(RF24_SPI_PTR) - #if defined(RF24_RP2) - _spi->beginTransaction(spi_speed); - #else // ! defined (RF24_RP2) - _spi->beginTransaction(SPISettings(spi_speed, MSBFIRST, SPI_MODE0)); - #endif // ! defined (RF24_RP2) - #else // !defined(RF24_SPI_PTR) - _SPI.beginTransaction(SPISettings(spi_speed, MSBFIRST, SPI_MODE0)); - #endif // !defined(RF24_SPI_PTR) -#endif // defined (RF24_SPI_TRANSACTIONS) - csn(LOW); -} - -/****************************************************************************/ - -inline void RF24::endTransaction() -{ - csn(HIGH); -#if defined(RF24_SPI_TRANSACTIONS) - #if defined(RF24_SPI_PTR) - _spi->endTransaction(); - #else // !defined(RF24_SPI_PTR) - _SPI.endTransaction(); - #endif // !defined(RF24_SPI_PTR) -#endif // defined (RF24_SPI_TRANSACTIONS) + hal->ce(level); } /****************************************************************************/ void RF24::read_register(uint8_t reg, uint8_t* buf, uint8_t len) { -#if defined(RF24_LINUX) || defined(RF24_RP2) - beginTransaction(); //configures the spi settings for RPi, locks mutex and setting csn low - uint8_t* prx = spi_rxbuff; - uint8_t* ptx = spi_txbuff; - uint8_t size = static_cast(len + 1); // Add register value to transmit buffer - - *ptx++ = (R_REGISTER | reg); - - while (len--) { - *ptx++ = RF24_NOP; // Dummy operation, just for reading - } - - #if defined(RF24_RP2) - _spi->transfernb((const uint8_t*)spi_txbuff, spi_rxbuff, size); - #else // !defined (RF24_RP2) - _SPI.transfernb(reinterpret_cast(spi_txbuff), reinterpret_cast(spi_rxbuff), size); - #endif // !defined (RF24_RP2) - - status = *prx++; // status is 1st byte of receive buffer - - // decrement before to skip status byte - while (--size) { - *buf++ = *prx++; - } - - endTransaction(); // unlocks mutex and setting csn high - -#else // !defined(RF24_LINUX) && !defined(RF24_RP2) - - beginTransaction(); - #if defined(RF24_SPI_PTR) - status = _spi->transfer(R_REGISTER | reg); - while (len--) { - *buf++ = _spi->transfer(0xFF); - } - - #else // !defined(RF24_SPI_PTR) - status = _SPI.transfer(R_REGISTER | reg); - while (len--) { - *buf++ = _SPI.transfer(0xFF); - } - - #endif // !defined(RF24_SPI_PTR) - endTransaction(); -#endif // !defined(RF24_LINUX) && !defined(RF24_RP2) + status = hal->read(R_REGISTER | reg, buf, len); } /****************************************************************************/ uint8_t RF24::read_register(uint8_t reg) { - uint8_t result; - -#if defined(RF24_LINUX) || defined(RF24_RP2) - beginTransaction(); - - uint8_t* prx = spi_rxbuff; - uint8_t* ptx = spi_txbuff; - *ptx++ = (R_REGISTER | reg); - *ptx++ = RF24_NOP; // Dummy operation, just for reading - - #if defined(RF24_RP2) - _spi->transfernb((const uint8_t*)spi_txbuff, spi_rxbuff, 2); - #else // !defined(RF24_RP2) - _SPI.transfernb(reinterpret_cast(spi_txbuff), reinterpret_cast(spi_rxbuff), 2); - #endif // !defined(RF24_RP2) - - status = *prx; // status is 1st byte of receive buffer - result = *++prx; // result is 2nd byte of receive buffer - - endTransaction(); -#else // !defined(RF24_LINUX) && !defined(RF24_RP2) - - beginTransaction(); - #if defined(RF24_SPI_PTR) - status = _spi->transfer(R_REGISTER | reg); - result = _spi->transfer(0xff); - - #else // !defined(RF24_SPI_PTR) - status = _SPI.transfer(R_REGISTER | reg); - result = _SPI.transfer(0xff); - - #endif // !defined(RF24_SPI_PTR) - endTransaction(); -#endif // !defined(RF24_LINUX) && !defined(RF24_RP2) - + uint8_t result = 0xff; + status = hal->read(R_REGISTER | reg, &result, sizeof(result)); return result; } @@ -241,43 +37,7 @@ uint8_t RF24::read_register(uint8_t reg) void RF24::write_register(uint8_t reg, const uint8_t* buf, uint8_t len) { -#if defined(RF24_LINUX) || defined(RF24_RP2) - beginTransaction(); - uint8_t* prx = spi_rxbuff; - uint8_t* ptx = spi_txbuff; - uint8_t size = static_cast(len + 1); // Add register value to transmit buffer - - *ptx++ = (W_REGISTER | (REGISTER_MASK & reg)); - while (len--) { - *ptx++ = *buf++; - } - - #if defined(RF24_RP2) - _spi->transfernb((const uint8_t*)spi_txbuff, spi_rxbuff, size); - #else // !defined(RF24_RP2) - _SPI.transfernb(reinterpret_cast(spi_txbuff), reinterpret_cast(spi_rxbuff), size); - #endif // !defined(RF24_RP2) - - status = *prx; // status is 1st byte of receive buffer - endTransaction(); -#else // !defined(RF24_LINUX) && !defined(RF24_RP2) - - beginTransaction(); - #if defined(RF24_SPI_PTR) - status = _spi->transfer(W_REGISTER | reg); - while (len--) { - _spi->transfer(*buf++); - } - - #else // !defined(RF24_SPI_PTR) - status = _SPI.transfer(W_REGISTER | reg); - while (len--) { - _SPI.transfer(*buf++); - } - - #endif // !defined(RF24_SPI_PTR) - endTransaction(); -#endif // !defined(RF24_LINUX) && !defined(RF24_RP2) + status = hal->write(W_REGISTER | reg, buf, len); } /****************************************************************************/ @@ -288,47 +48,11 @@ void RF24::write_register(uint8_t reg, uint8_t value, bool is_cmd_only) if (reg != RF24_NOP) { // don't print the get_status() operation IF_SERIAL_DEBUG(printf_P(PSTR("write_register(%02x)\r\n"), reg)); } - beginTransaction(); -#if defined(RF24_LINUX) - status = _SPI.transfer(W_REGISTER | reg); -#else // !defined(RF24_LINUX) || defined (RF24_RP2) - #if defined(RF24_SPI_PTR) - status = _spi->transfer(W_REGISTER | reg); - #else // !defined (RF24_SPI_PTR) - status = _SPI.transfer(W_REGISTER | reg); - #endif // !defined (RF24_SPI_PTR) -#endif // !defined(RF24_LINUX) || defined(RF24_RP2) - endTransaction(); + status = hal->write(W_REGISTER | reg, nullptr, 0); } else { IF_SERIAL_DEBUG(printf_P(PSTR("write_register(%02x,%02x)\r\n"), reg, value)); -#if defined(RF24_LINUX) || defined(RF24_RP2) - beginTransaction(); - uint8_t* prx = spi_rxbuff; - uint8_t* ptx = spi_txbuff; - *ptx++ = (W_REGISTER | reg); - *ptx = value; - - #if defined(RF24_RP2) - _spi->transfernb((const uint8_t*)spi_txbuff, spi_rxbuff, 2); - #else // !defined(RF24_RP2) - _SPI.transfernb(reinterpret_cast(spi_txbuff), reinterpret_cast(spi_rxbuff), 2); - #endif // !defined(RF24_RP2) - - status = *prx++; // status is 1st byte of receive buffer - endTransaction(); -#else // !defined(RF24_LINUX) && !defined(RF24_RP2) - - beginTransaction(); - #if defined(RF24_SPI_PTR) - status = _spi->transfer(W_REGISTER | reg); - _spi->transfer(value); - #else // !defined(RF24_SPI_PTR) - status = _SPI.transfer(W_REGISTER | reg); - _SPI.transfer(value); - #endif // !defined(RF24_SPI_PTR) - endTransaction(); -#endif // !defined(RF24_LINUX) && !defined(RF24_RP2) + status = hal->write(W_REGISTER | reg, &value, sizeof(value)); } } @@ -347,60 +71,8 @@ void RF24::write_payload(const void* buf, uint8_t data_len, const uint8_t writeT data_len = rf24_min(data_len, static_cast(32)); } - //printf("[Writing %u bytes %u blanks]",data_len,blank_len); IF_SERIAL_DEBUG(printf("[Writing %u bytes %u blanks]\n", data_len, blank_len);); - -#if defined(RF24_LINUX) || defined(RF24_RP2) - beginTransaction(); - uint8_t* prx = spi_rxbuff; - uint8_t* ptx = spi_txbuff; - uint8_t size; - size = static_cast(data_len + blank_len + 1); // Add register value to transmit buffer - - *ptx++ = writeType; - while (data_len--) { - *ptx++ = *current++; - } - - while (blank_len--) { - *ptx++ = 0; - } - - #if defined(RF24_RP2) - _spi->transfernb((const uint8_t*)spi_txbuff, spi_rxbuff, size); - #else // !defined(RF24_RP2) - _SPI.transfernb(reinterpret_cast(spi_txbuff), reinterpret_cast(spi_rxbuff), size); - #endif // !defined(RF24_RP2) - - status = *prx; // status is 1st byte of receive buffer - endTransaction(); - -#else // !defined(RF24_LINUX) && !defined(RF24_RP2) - - beginTransaction(); - #if defined(RF24_SPI_PTR) - status = _spi->transfer(writeType); - while (data_len--) { - _spi->transfer(*current++); - } - - while (blank_len--) { - _spi->transfer(0); - } - - #else // !defined(RF24_SPI_PTR) - status = _SPI.transfer(writeType); - while (data_len--) { - _SPI.transfer(*current++); - } - - while (blank_len--) { - _SPI.transfer(0); - } - - #endif // !defined(RF24_SPI_PTR) - endTransaction(); -#endif // !defined(RF24_LINUX) && !defined(RF24_RP2) + status = hal->write(writeType, current, data_len, blank_len); } /****************************************************************************/ @@ -421,65 +93,7 @@ void RF24::read_payload(void* buf, uint8_t data_len) //printf("[Reading %u bytes %u blanks]",data_len,blank_len); IF_SERIAL_DEBUG(printf("[Reading %u bytes %u blanks]\n", data_len, blank_len);); - -#if defined(RF24_LINUX) || defined(RF24_RP2) - beginTransaction(); - uint8_t* prx = spi_rxbuff; - uint8_t* ptx = spi_txbuff; - uint8_t size; - size = static_cast(data_len + blank_len + 1); // Add register value to transmit buffer - - *ptx++ = R_RX_PAYLOAD; - while (--size) { - *ptx++ = RF24_NOP; - } - - size = static_cast(data_len + blank_len + 1); // Size has been lost during while, re affect - - #if defined(RF24_RP2) - _spi->transfernb((const uint8_t*)spi_txbuff, spi_rxbuff, size); - #else // !defined(RF24_RP2) - _SPI.transfernb(reinterpret_cast(spi_txbuff), reinterpret_cast(spi_rxbuff), size); - #endif // !defined(RF24_RP2) - - status = *prx++; // 1st byte is status - - if (data_len > 0) { - // Decrement before to skip 1st status byte - while (--data_len) { - *current++ = *prx++; - } - - *current = *prx; - } - endTransaction(); -#else // !defined(RF24_LINUX) && !defined(RF24_RP2) - - beginTransaction(); - #if defined(RF24_SPI_PTR) - status = _spi->transfer(R_RX_PAYLOAD); - while (data_len--) { - *current++ = _spi->transfer(0xFF); - } - - while (blank_len--) { - _spi->transfer(0xFF); - } - - #else // !defined(RF24_SPI_PTR) - status = _SPI.transfer(R_RX_PAYLOAD); - while (data_len--) { - *current++ = _SPI.transfer(0xFF); - } - - while (blank_len--) { - _SPI.transfer(0xff); - } - - #endif // !defined(RF24_SPI_PTR) - endTransaction(); - -#endif // !defined(RF24_LINUX) && !defined(RF24_RP2) + status = hal->read(R_RX_PAYLOAD, current, data_len, blank_len); } /****************************************************************************/ @@ -577,16 +191,16 @@ uint8_t RF24::sprintf_address_register(char* out_buffer, uint8_t reg, uint8_t qt /****************************************************************************/ -RF24::RF24(rf24_gpio_pin_t _cepin, rf24_gpio_pin_t _cspin, uint32_t _spi_speed) - : ce_pin(_cepin), csn_pin(_cspin), spi_speed(_spi_speed), payload_size(32), _is_p_variant(false), _is_p0_rx(false), addr_width(5), dynamic_payloads_enabled(true), csDelay(5) +RF24::RF24(RF24_hal* _hal) + : hal(_hal), payload_size(32), _is_p_variant(false), _is_p0_rx(false), addr_width(5), dynamic_payloads_enabled(true), csDelay(5) { _init_obj(); } /****************************************************************************/ -RF24::RF24(uint32_t _spi_speed) - : ce_pin(RF24_PIN_INVALID), csn_pin(RF24_PIN_INVALID), spi_speed(_spi_speed), payload_size(32), _is_p_variant(false), _is_p0_rx(false), addr_width(5), dynamic_payloads_enabled(true), csDelay(5) +RF24::RF24() + : hal(nullptr), payload_size(32), _is_p_variant(false), _is_p0_rx(false), addr_width(5), dynamic_payloads_enabled(true), csDelay(5) { _init_obj(); } @@ -595,16 +209,7 @@ RF24::RF24(uint32_t _spi_speed) void RF24::_init_obj() { - // Use a pointer on the Arduino platform - -#if defined(RF24_SPI_PTR) && !defined(RF24_RP2) - _spi = &SPI; -#endif // defined (RF24_SPI_PTR) - pipe0_reading_address[0] = 0; - if (spi_speed <= 35000) { //Handle old BCM2835 speed constants, default to RF24_SPI_SPEED - spi_speed = RF24_SPI_SPEED; - } } /****************************************************************************/ @@ -677,19 +282,6 @@ static const PROGMEM char* const rf24_pa_dbm_e_str_P[] = { rf24_pa_dbm_e_str_3, }; - #if defined(RF24_LINUX) -static const char rf24_csn_e_str_0[] = "CE0 (PI Hardware Driven)"; -static const char rf24_csn_e_str_1[] = "CE1 (PI Hardware Driven)"; -static const char rf24_csn_e_str_2[] = "CE2 (PI Hardware Driven)"; -static const char rf24_csn_e_str_3[] = "Custom GPIO Software Driven"; -static const char* const rf24_csn_e_str_P[] = { - rf24_csn_e_str_0, - rf24_csn_e_str_1, - rf24_csn_e_str_2, - rf24_csn_e_str_3, -}; - #endif // defined(RF24_LINUX) - static const PROGMEM char rf24_feature_e_str_on[] = "= Enabled"; static const PROGMEM char rf24_feature_e_str_allowed[] = "= Allowed"; static const PROGMEM char rf24_feature_e_str_open[] = " open "; @@ -704,19 +296,6 @@ static const PROGMEM char* const rf24_feature_e_str_P[] = { void RF24::printDetails(void) { - - #if defined(RF24_LINUX) - printf("================ SPI Configuration ================\n"); - uint8_t bus_ce = static_cast(csn_pin % 10); - uint8_t bus_numb = static_cast((csn_pin - bus_ce) / 10); - printf("CSN Pin\t\t= /dev/spidev%d.%d\n", bus_numb, bus_ce); - printf("CE Pin\t\t= Custom GPIO%d\n", ce_pin); - #endif - printf_P(PSTR("SPI Speedz\t= %d Mhz\n"), static_cast(spi_speed / 1000000)); //Print the SPI speed on non-Linux devices - #if defined(RF24_LINUX) - printf("================ NRF Configuration ================\n"); - #endif // defined(RF24_LINUX) - print_status(get_status()); print_address_register(PSTR("RX_ADDR_P0-1"), RX_ADDR_P0, 2); @@ -748,19 +327,6 @@ void RF24::printDetails(void) void RF24::printPrettyDetails(void) { - - #if defined(RF24_LINUX) - printf("================ SPI Configuration ================\n"); - uint8_t bus_ce = static_cast(csn_pin % 10); - uint8_t bus_numb = static_cast((csn_pin - bus_ce) / 10); - printf("CSN Pin\t\t\t= /dev/spidev%d.%d\n", bus_numb, bus_ce); - printf("CE Pin\t\t\t= Custom GPIO%d\n", ce_pin); - #endif - printf_P(PSTR("SPI Frequency\t\t= %d Mhz\n"), static_cast(spi_speed / 1000000)); //Print the SPI speed on non-Linux devices - #if defined(RF24_LINUX) - printf("================ NRF Configuration ================\n"); - #endif // defined(RF24_LINUX) - uint8_t channel = getChannel(); uint16_t frequency = static_cast(channel + 2400); printf_P(PSTR("Channel\t\t\t= %u (~ %u MHz)\r\n"), channel, frequency); @@ -846,11 +412,6 @@ void RF24::printPrettyDetails(void) uint16_t RF24::sprintfPrettyDetails(char* debugging_information) { const char* format_string = PSTR( - "================ SPI Configuration ================\n" - "CSN Pin\t\t\t= %d\n" - "CE Pin\t\t\t= %d\n" - "SPI Frequency\t\t= %d Mhz\n" - "================ NRF Configuration ================\n" "Channel\t\t\t= %u (~ %u MHz)\n" "RF Data Rate\t\t" PRIPSTR "\n" "RF Power Amplifier\t" PRIPSTR "\n" @@ -870,8 +431,7 @@ uint16_t RF24::sprintfPrettyDetails(char* debugging_information) const char* format_str3 = PSTR("\nPipe %d (" PRIPSTR ") bound\t= 0x"); uint16_t offset = sprintf_P( - debugging_information, format_string, csn_pin, ce_pin, - static_cast(spi_speed / 1000000), getChannel(), + debugging_information, format_string, getChannel(), static_cast(getChannel() + 2400), (char*)(pgm_read_ptr(&rf24_datarate_e_str_P[getDataRate()])), (char*)(pgm_read_ptr(&rf24_pa_dbm_e_str_P[getPALevel()])), @@ -940,87 +500,26 @@ void RF24::encodeRadioDetails(uint8_t* encoded_details) *encoded_details++ = read_register(i); } } - *encoded_details++ = ce_pin >> 4; - *encoded_details++ = ce_pin & 0xFF; - *encoded_details++ = csn_pin >> 4; - *encoded_details++ = csn_pin & 0xFF; - *encoded_details = static_cast((spi_speed / 1000000) | _BV(_is_p_variant * 4)); } #endif // !defined(MINIMAL) /****************************************************************************/ -#if defined(RF24_SPI_PTR) || defined(DOXYGEN_FORCED) -// does not apply to RF24_LINUX -bool RF24::begin(_SPI* spiBus) +bool RF24::begin(void) { - _spi = spiBus; return _init_pins() && _init_radio(); } /****************************************************************************/ -bool RF24::begin(_SPI* spiBus, rf24_gpio_pin_t _cepin, rf24_gpio_pin_t _cspin) +bool RF24::begin(RF24_hal* _hal) { - ce_pin = _cepin; - csn_pin = _cspin; - return begin(spiBus); -} - -#endif // defined (RF24_SPI_PTR) || defined (DOXYGEN_FORCED) - -/****************************************************************************/ - -bool RF24::begin(rf24_gpio_pin_t _cepin, rf24_gpio_pin_t _cspin) -{ - ce_pin = _cepin; - csn_pin = _cspin; + hal = _hal; return begin(); } /****************************************************************************/ -bool RF24::begin(void) -{ -#if defined(RF24_LINUX) - #if defined(RF24_RPi) - switch (csn_pin) { // Ensure valid hardware CS pin - case 0: break; - case 1: break; - // Allow BCM2835 enums for RPi - case 8: csn_pin = 0; break; - case 7: csn_pin = 1; break; - case 18: csn_pin = 10; break; // to make it work on SPI1 - case 17: csn_pin = 11; break; - case 16: csn_pin = 12; break; - default: csn_pin = 0; break; - } - #endif // RF24_RPi - - _SPI.begin(csn_pin, spi_speed); - -#elif defined(XMEGA_D3) - _spi->begin(csn_pin); - -#elif defined(RF24_RP2) - _spi = new SPI(); - _spi->begin(PICO_DEFAULT_SPI ? spi1 : spi0); - -#else // using an Arduino platform || defined (LITTLEWIRE) - - #if defined(RF24_SPI_PTR) - _spi->begin(); - #else // !defined(RF24_SPI_PTR) - _SPI.begin(); - #endif // !defined(RF24_SPI_PTR) - -#endif // !defined(XMEGA_D3) && !defined(RF24_LINUX) - - return _init_pins() && _init_radio(); -} - -/****************************************************************************/ - bool RF24::_init_pins() { if (!isValid()) { @@ -1028,46 +527,7 @@ bool RF24::_init_pins() return false; } -#if defined(RF24_LINUX) - - #if defined(MRAA) - GPIO(); - gpio.begin(ce_pin, csn_pin); - #endif - - pinMode(ce_pin, OUTPUT); - ce(LOW); - delay(100); - -#elif defined(LITTLEWIRE) - pinMode(csn_pin, OUTPUT); - csn(HIGH); - -#elif defined(XMEGA_D3) - if (ce_pin != csn_pin) { - pinMode(ce_pin, OUTPUT); - }; - ce(LOW); - csn(HIGH); - delay(200); - -#else // using an Arduino platform - - // Initialize pins - if (ce_pin != csn_pin) { - pinMode(ce_pin, OUTPUT); - pinMode(csn_pin, OUTPUT); - } - - ce(LOW); - csn(HIGH); - - #if defined(__ARDUINO_X86__) - delay(100); - #endif -#endif // !defined(XMEGA_D3) && !defined(LITTLEWIRE) && !defined(RF24_LINUX) - - return true; // assuming pins are connected properly + return hal->begin(); } /****************************************************************************/ @@ -1151,7 +611,7 @@ bool RF24::isChipConnected() bool RF24::isValid() { - return ce_pin != RF24_PIN_INVALID && csn_pin != RF24_PIN_INVALID; + return hal != nullptr; } /****************************************************************************/ @@ -1675,15 +1135,8 @@ void RF24::closeReadingPipe(uint8_t pipe) void RF24::toggle_features(void) { - beginTransaction(); -#if defined(RF24_SPI_PTR) - status = _spi->transfer(ACTIVATE); - _spi->transfer(0x73); -#else - status = _SPI.transfer(ACTIVATE); - _SPI.transfer(0x73); -#endif - endTransaction(); + uint8_t value = 0x73; + status = hal->write(ACTIVATE, &value, sizeof(value)); } /****************************************************************************/ @@ -1871,6 +1324,11 @@ uint8_t RF24::getARC(void) return read_register(OBSERVE_TX) & 0x0F; } +uint8_t RF24::getPLOS(void) +{ + return (read_register(OBSERVE_TX) >> 4) & 0x0F; +} + /****************************************************************************/ bool RF24::setDataRate(rf24_datarate_e speed) diff --git a/RF24.h b/RF24.h index dbd32ae..74ae35d 100644 --- a/RF24.h +++ b/RF24.h @@ -16,12 +16,7 @@ #define __RF24_H__ #include "RF24_config.h" - -#if defined(RF24_LINUX) || defined(LITTLEWIRE) - #include "utility/includes.h" -#elif defined SOFTSPI - #include -#endif +#include "RF24_hal.h" /** * @defgroup PALevel Power Amplifier level @@ -115,29 +110,8 @@ typedef enum class RF24 { private: -#ifdef SOFTSPI - SoftSPI spi; -#elif defined(SPI_UART) - SPIUARTClass uspi; -#endif - -#if defined(RF24_LINUX) || defined(XMEGA_D3) /* XMEGA can use SPI class */ - SPI spi; -#endif // defined (RF24_LINUX) || defined (XMEGA_D3) -#if defined(RF24_SPI_PTR) - _SPI* _spi; -#endif // defined (RF24_SPI_PTR) -#if defined(MRAA) - GPIO gpio; -#endif + RF24_hal *hal; - rf24_gpio_pin_t ce_pin; /* "Chip Enable" pin, activates the RX or TX role */ - rf24_gpio_pin_t csn_pin; /* SPI Chip select */ - uint32_t spi_speed; /* SPI Bus Speed */ -#if defined(RF24_LINUX) || defined(XMEGA_D3) || defined(RF24_RP2) - uint8_t spi_rxbuff[32 + 1]; //SPI receive buffer (payload max 32 bytes) - uint8_t spi_txbuff[32 + 1]; //SPI transmit buffer (payload max 32 bytes + 1 byte for the command) -#endif uint8_t status; /* The status byte returned from every SPI transaction */ uint8_t payload_size; /* Fixed size of payloads */ uint8_t pipe0_reading_address[5]; /* Last address set on pipe 0 for reading. */ @@ -146,16 +120,6 @@ private: bool _is_p0_rx; /* For keeping track of pipe 0's usage in user-triggered RX mode. */ protected: - /** - * SPI transactions - * - * Common code for SPI transactions including CSN toggle - * - */ - inline void beginTransaction(); - - inline void endTransaction(); - /** Whether ack payloads are enabled. */ bool ack_payloads_enabled; /** The address width to use (3, 4 or 5 bytes). */ @@ -198,30 +162,15 @@ public: * * See [Related Pages](pages.html) for device specific information * - * @param _cepin The pin attached to Chip Enable on the RF module - * @param _cspin The pin attached to Chip Select (often labeled CSN) on the radio module. - * - For the Arduino Due board, the [Arduino Due extended SPI feature](https://www.arduino.cc/en/Reference/DueExtendedSPI) - * is not supported. This means that the Due's pins 4, 10, or 52 are not mandated options (can use any digital output pin) for - * the radio's CSN pin. - * @param _spi_speed The SPI speed in Hz ie: 1000000 == 1Mhz - * - Users can specify default SPI speed by modifying @ref RF24_SPI_SPEED in @ref RF24_config.h - * - For Arduino, the default SPI speed will only be properly configured this way on devices supporting SPI TRANSACTIONS - * - Older/Unsupported Arduino devices will use a default clock divider & settings configuration - * - For Linux: The old way of setting SPI speeds using BCM2835 driver enums has been removed as of v1.3.7 + * @param _hal A pointer to the device specific hardware abstraction layer */ - RF24(rf24_gpio_pin_t _cepin, rf24_gpio_pin_t _cspin, uint32_t _spi_speed = RF24_SPI_SPEED); + RF24(RF24_hal *_hal); /** * A constructor for initializing the radio's hardware dynamically - * @warning You MUST use begin(rf24_gpio_pin_t, rf24_gpio_pin_t) or begin(_SPI*, rf24_gpio_pin_t, rf24_gpio_pin_t) to pass both the - * digital output pin numbers connected to the radio's CE and CSN pins. - * @param _spi_speed The SPI speed in Hz ie: 1000000 == 1Mhz - * - Users can specify default SPI speed by modifying @ref RF24_SPI_SPEED in @ref RF24_config.h - * - For Arduino, the default SPI speed will only be properly configured this way on devices supporting SPI TRANSACTIONS - * - Older/Unsupported Arduino devices will use a default clock divider & settings configuration - * - For Linux: The old way of setting SPI speeds using BCM2835 driver enums has been removed as of v1.3.7 + * @warning You MUST use begin(RF24_hal*) */ - RF24(uint32_t _spi_speed = RF24_SPI_SPEED); + RF24(void); #if defined(RF24_LINUX) virtual ~RF24() {}; @@ -243,58 +192,16 @@ public: */ bool begin(void); -#if defined(RF24_SPI_PTR) || defined(DOXYGEN_FORCED) /** * Same as begin(), but allows specifying a non-default SPI bus to use. * - * @note This function assumes the `SPI::begin()` method was called before to - * calling this function. - * - * @warning This function is for the Arduino platforms only - * - * @param spiBus A pointer or reference to an instantiated SPI bus object. - * The `_SPI` datatype is a "wrapped" definition that will represent - * various SPI implementations based on the specified platform. - * @see Review the [Arduino support page](md_docs_arduino.html). - * - * @return same result as begin() - */ - bool begin(_SPI* spiBus); - - /** - * Same as begin(), but allows dynamically specifying a SPI bus, CE pin, - * and CSN pin to use. - * - * @note This function assumes the `SPI::begin()` method was called before to - * calling this function. - * * @warning This function is for the Arduino platforms only * - * @param spiBus A pointer or reference to an instantiated SPI bus object. - * The `_SPI` datatype is a "wrapped" definition that will represent - * various SPI implementations based on the specified platform. - * @param _cepin The pin attached to Chip Enable on the RF module - * @param _cspin The pin attached to Chip Select (often labeled CSN) on the radio module. - * - For the Arduino Due board, the [Arduino Due extended SPI feature](https://www.arduino.cc/en/Reference/DueExtendedSPI) - * is not supported. This means that the Due's pins 4, 10, or 52 are not mandated options (can use any digital output pin) for the radio's CSN pin. + * @param _hal A pointer to the device specific hardware abstraction layer * - * @see Review the [Arduino support page](md_docs_arduino.html). - * - * @return same result as begin() - */ - bool begin(_SPI* spiBus, rf24_gpio_pin_t _cepin, rf24_gpio_pin_t _cspin); -#endif // defined (RF24_SPI_PTR) || defined (DOXYGEN_FORCED) - - /** - * Same as begin(), but allows dynamically specifying a CE pin - * and CSN pin to use. - * @param _cepin The pin attached to Chip Enable on the RF module - * @param _cspin The pin attached to Chip Select (often labeled CSN) on the radio module. - * - For the Arduino Due board, the [Arduino Due extended SPI feature](https://www.arduino.cc/en/Reference/DueExtendedSPI) - * is not supported. This means that the Due's pins 4, 10, or 52 are not mandated options (can use any digital output pin) for the radio's CSN pin. * @return same result as begin() */ - bool begin(rf24_gpio_pin_t _cepin, rf24_gpio_pin_t _cspin); + bool begin(RF24_hal* _hal); /** * Checks if the chip is connected to the SPI bus @@ -667,12 +574,12 @@ public: * This function uses much less ram than other `*print*Details()` methods. * * @code - * uint8_t encoded_details[43] = {0}; + * uint8_t encoded_details[38] = {0}; * radio.encodeRadioDetails(encoded_details); * @endcode * * @param encoded_status The uint8_t array that RF24 radio details are - * encoded into. This array must be at least 43 bytes in length; any less would surely + * encoded into. This array must be at least 38 bytes in length; any less would surely * cause undefined behavior. * * Registers names and/or data corresponding to the index of the `encoded_details` array: @@ -704,9 +611,6 @@ public: * | 35 | FIFO_STATUS | * | 36 | DYNPD | * | 37 | FEATURE | - * | 38-39 | ce_pin | - * | 40-41 | csn_pin | - * | 42 | SPI speed (in MHz) or'd with (isPlusVariant << 4) | */ void encodeRadioDetails(uint8_t* encoded_status); @@ -1644,6 +1548,7 @@ public: * @return Returns values from 0 to 15. */ uint8_t getARC(void); + uint8_t getPLOS(void); /** * Set the transmission @ref Datarate @@ -1896,18 +1801,6 @@ private: */ bool _init_pins(); - /** - * Set chip select pin - * - * Running SPI bus at PI_CLOCK_DIV2 so we don't waste time transferring data - * and best of all, we make use of the radio's FIFO buffers. A lower speed - * means we're less likely to effectively leverage our FIFOs and pay a higher - * AVR runtime cost as toll. - * - * @param mode HIGH to take this unit off the SPI bus, LOW to put it on - */ - void csn(bool mode); - /** * Set chip enable * diff --git a/RF24_hal.cpp b/RF24_hal.cpp new file mode 100644 index 0000000..3cc78e4 --- /dev/null +++ b/RF24_hal.cpp @@ -0,0 +1 @@ +#include "RF24_hal.h" diff --git a/RF24_hal.h b/RF24_hal.h new file mode 100644 index 0000000..baceab3 --- /dev/null +++ b/RF24_hal.h @@ -0,0 +1,15 @@ +#pragma once + +#include "RF24_config.h" + +class RF24_hal +{ +public: + virtual void ce(bool level) = 0; + virtual uint8_t read(uint8_t cmd, uint8_t* buf, uint8_t len) = 0; + virtual uint8_t read(uint8_t cmd, uint8_t* buf, uint8_t data_len, uint8_t blank_len) = 0; + virtual uint8_t write(uint8_t cmd, const uint8_t* buf, uint8_t len) = 0; + virtual uint8_t write(uint8_t cmd, const uint8_t* buf, uint8_t len, uint8_t blank_len) = 0; + virtual bool begin() = 0; + virtual void end() = 0; +};