diff --git a/RF24.cpp b/RF24.cpp index 6f10f7168..13c5a075a 100644 --- a/RF24.cpp +++ b/RF24.cpp @@ -14,396 +14,389 @@ void RF24::csn(bool mode) { - -#if defined (RF24_TINY) - if (ce_pin != csn_pin) { - digitalWrite(csn_pin,mode); - } - else { - if (mode == HIGH) { - PORTB |= (1<CSN HIGH - delayMicroseconds(100); // allow csn to settle. - } - else { - PORTB &= ~(1<CSN LOW - delayMicroseconds(11); // 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) - _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 - #error "Unsupported CPU frequency. Please set correct SPI divider." - #endif - - #endif -#elif defined (RF24_RPi) - if(!mode) - _SPI.chipSelect(csn_pin); -#endif - -#if !defined (RF24_LINUX) - digitalWrite(csn_pin,mode); - delayMicroseconds(csDelay); -#endif - + #if defined(RF24_TINY) + if (ce_pin != csn_pin) { + digitalWrite(csn_pin,mode); + } + else { + if (mode == HIGH) { + PORTB |= (1<CSN HIGH + delayMicroseconds(100); // allow csn to settle. + } + else { + PORTB &= ~(1<CSN LOW + delayMicroseconds(11); // 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) + _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 + #error "Unsupported CPU frequency. Please set correct SPI divider." + #endif + + #endif + #elif defined(RF24_RPi) + if(!mode) + _SPI.chipSelect(csn_pin); + #endif // defined(RF24_RPi) + + #if !defined(RF24_LINUX) + digitalWrite(csn_pin, mode); + delayMicroseconds(csDelay); + #endif // !defined(RF24_LINUX) } /****************************************************************************/ void RF24::ce(bool level) { - //Allow for 3-pin use on ATTiny - if (ce_pin != csn_pin) digitalWrite(ce_pin,level); + //Allow for 3-pin use on ATTiny + if (ce_pin != csn_pin) { + digitalWrite(ce_pin, level); + } } /****************************************************************************/ - inline void RF24::beginTransaction() { - #if defined (RF24_SPI_TRANSACTIONS) +inline void RF24::beginTransaction() +{ + #if defined(RF24_SPI_TRANSACTIONS) _SPI.beginTransaction(SPISettings(RF24_SPI_SPEED, MSBFIRST, SPI_MODE0)); - #endif + #endif // defined(RF24_SPI_TRANSACTIONS) csn(LOW); - } +} /****************************************************************************/ - inline void RF24::endTransaction() { +inline void RF24::endTransaction() +{ csn(HIGH); - #if defined (RF24_SPI_TRANSACTIONS) + #if defined(RF24_SPI_TRANSACTIONS) _SPI.endTransaction(); - #endif - } + #endif // defined(RF24_SPI_TRANSACTIONS) +} /****************************************************************************/ uint8_t RF24::read_register(uint8_t reg, uint8_t* buf, uint8_t len) { - uint8_t status; + uint8_t status; - #if defined (RF24_LINUX) - 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 = len + 1; // Add register value to transmit buffer + #if defined(RF24_LINUX) + 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 = len + 1; // Add register value to transmit buffer - *ptx++ = ( R_REGISTER | ( REGISTER_MASK & reg ) ); + *ptx++ = ( R_REGISTER | ( REGISTER_MASK & reg ) ); - while (len--){ *ptx++ = RF24_NOP; } // Dummy operation, just for reading - - _SPI.transfernb( (char *) spi_txbuff, (char *) spi_rxbuff, size); - - status = *prx++; // status is 1st byte of receive buffer + while (len--){ *ptx++ = RF24_NOP; } // Dummy operation, just for reading - // decrement before to skip status byte - while ( --size ){ *buf++ = *prx++; } - endTransaction(); //unlocks mutex and setting csn high + _SPI.transfernb( (char *) spi_txbuff, (char *) spi_rxbuff, size); -#else + status = *prx++; // status is 1st byte of receive buffer - beginTransaction(); - status = _SPI.transfer( R_REGISTER | ( REGISTER_MASK & reg ) ); - while ( len-- ){ - *buf++ = _SPI.transfer(0xff); - } - endTransaction(); + // decrement before to skip status byte + while ( --size ){ *buf++ = *prx++; } + endTransaction(); //unlocks mutex and setting csn high + #else // !defined(RF24_LINUX) -#endif + beginTransaction(); + status = _SPI.transfer(R_REGISTER | (REGISTER_MASK & reg)); + while (len --) { + *buf ++ = _SPI.transfer(0xff); + } + endTransaction(); + #endif // !defined(RF24_LINUX) - return status; + return status; } /****************************************************************************/ uint8_t RF24::read_register(uint8_t reg) { - uint8_t result; - - #if defined (RF24_LINUX) - - beginTransaction(); - - uint8_t * prx = spi_rxbuff; - uint8_t * ptx = spi_txbuff; - *ptx++ = ( R_REGISTER | ( REGISTER_MASK & reg ) ); - *ptx++ = RF24_NOP ; // Dummy operation, just for reading - - _SPI.transfernb( (char *) spi_txbuff, (char *) spi_rxbuff, 2); - result = *++prx; // result is 2nd byte of receive buffer - - endTransaction(); - #else + uint8_t result; - beginTransaction(); - _SPI.transfer( R_REGISTER | ( REGISTER_MASK & reg ) ); - result = _SPI.transfer(0xff); - endTransaction(); + #if defined(RF24_LINUX) + beginTransaction(); + + uint8_t * prx = spi_rxbuff; + uint8_t * ptx = spi_txbuff; + *ptx++ = ( R_REGISTER | ( REGISTER_MASK & reg ) ); + *ptx++ = RF24_NOP ; // Dummy operation, just for reading - #endif + _SPI.transfernb( (char *) spi_txbuff, (char *) spi_rxbuff, 2); + result = *++prx; // result is 2nd byte of receive buffer - return result; + endTransaction(); + #else // !defined(RF24_LINUX) + + beginTransaction(); + _SPI.transfer(R_REGISTER | (REGISTER_MASK & reg)); + result = _SPI.transfer(0xff); + endTransaction(); + + #endif // !defined(RF24_LINUX) + + return result; } /****************************************************************************/ uint8_t RF24::write_register(uint8_t reg, const uint8_t* buf, uint8_t len) { - uint8_t status; + uint8_t status; - #if defined (RF24_LINUX) - beginTransaction(); - uint8_t * prx = spi_rxbuff; - uint8_t * ptx = spi_txbuff; - uint8_t size = len + 1; // Add register value to transmit buffer + #if defined(RF24_LINUX) + beginTransaction(); + uint8_t * prx = spi_rxbuff; + uint8_t * ptx = spi_txbuff; + uint8_t size = len + 1; // Add register value to transmit buffer - *ptx++ = ( W_REGISTER | ( REGISTER_MASK & reg ) ); - while ( len-- ) - *ptx++ = *buf++; - - _SPI.transfernb( (char *) spi_txbuff, (char *) spi_rxbuff, size); - status = *prx; // status is 1st byte of receive buffer - endTransaction(); - #else + *ptx++ = ( W_REGISTER | ( REGISTER_MASK & reg ) ); + while ( len-- ) + *ptx++ = *buf++; - beginTransaction(); - status = _SPI.transfer( W_REGISTER | ( REGISTER_MASK & reg ) ); - while ( len-- ) - _SPI.transfer(*buf++); - endTransaction(); + _SPI.transfernb( (char *) spi_txbuff, (char *) spi_rxbuff, size); + status = *prx; // status is 1st byte of receive buffer + endTransaction(); + #else // !defined(RF24_LINUX) - #endif + beginTransaction(); + status = _SPI.transfer(W_REGISTER | (REGISTER_MASK & reg)); + while (len --) + _SPI.transfer(*buf ++); + endTransaction(); + #endif // !defined(RF24_LINUX) - return status; + return status; } /****************************************************************************/ uint8_t RF24::write_register(uint8_t reg, uint8_t value) { - uint8_t status; + uint8_t status; - IF_SERIAL_DEBUG(printf_P(PSTR("write_register(%02x,%02x)\r\n"),reg,value)); + IF_SERIAL_DEBUG(printf_P(PSTR("write_register(%02x,%02x)\r\n"), reg, value)); - #if defined (RF24_LINUX) + #if defined(RF24_LINUX) beginTransaction(); - uint8_t * prx = spi_rxbuff; - uint8_t * ptx = spi_txbuff; - *ptx++ = ( W_REGISTER | ( REGISTER_MASK & reg ) ); - *ptx = value ; - - _SPI.transfernb( (char *) spi_txbuff, (char *) spi_rxbuff, 2); - status = *prx++; // status is 1st byte of receive buffer - endTransaction(); - #else + uint8_t * prx = spi_rxbuff; + uint8_t * ptx = spi_txbuff; + *ptx++ = ( W_REGISTER | ( REGISTER_MASK & reg ) ); + *ptx = value ; - beginTransaction(); - status = _SPI.transfer( W_REGISTER | ( REGISTER_MASK & reg ) ); - _SPI.transfer(value); - endTransaction(); + _SPI.transfernb( (char *) spi_txbuff, (char *) spi_rxbuff, 2); + status = *prx++; // status is 1st byte of receive buffer + endTransaction(); + #else // !defined(RF24_LINUX) + + beginTransaction(); + status = _SPI.transfer(W_REGISTER | (REGISTER_MASK & reg)); + _SPI.transfer(value); + endTransaction(); - #endif + #endif // !defined(RF24_LINUX) - return status; + return status; } /****************************************************************************/ uint8_t RF24::write_payload(const void* buf, uint8_t data_len, const uint8_t writeType) { - uint8_t status; - const uint8_t* current = reinterpret_cast(buf); - - data_len = rf24_min(data_len, payload_size); - uint8_t blank_len = dynamic_payloads_enabled ? 0 : payload_size - data_len; - - //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) - beginTransaction(); - uint8_t * prx = spi_rxbuff; - uint8_t * ptx = spi_txbuff; + uint8_t status; + const uint8_t* current = reinterpret_cast(buf); + + data_len = rf24_min(data_len, payload_size); + uint8_t blank_len = dynamic_payloads_enabled ? 0 : payload_size - data_len; + + //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) + beginTransaction(); + uint8_t * prx = spi_rxbuff; + uint8_t * ptx = spi_txbuff; uint8_t size; - size = data_len + blank_len + 1 ; // Add register value to transmit buffer + size = data_len + blank_len + 1 ; // Add register value to transmit buffer - *ptx++ = writeType; + *ptx++ = writeType; while ( data_len-- ) *ptx++ = *current++; while ( blank_len-- ) - *ptx++ = 0; - - _SPI.transfernb( (char *) spi_txbuff, (char *) spi_rxbuff, size); - status = *prx; // status is 1st byte of receive buffer - endTransaction(); + *ptx++ = 0; + + _SPI.transfernb( (char *) spi_txbuff, (char *) spi_rxbuff, size); + status = *prx; // status is 1st byte of receive buffer + endTransaction(); - #else + #else // !defined(RF24_LINUX) - beginTransaction(); - status = _SPI.transfer( writeType ); - while ( data_len-- ) { - _SPI.transfer(*current++); - } - while ( blank_len-- ) { - _SPI.transfer(0); - } - endTransaction(); + beginTransaction(); + status = _SPI.transfer(writeType); + while (data_len --) { + _SPI.transfer(*current ++); + } + while (blank_len --) { + _SPI.transfer(0); + } + endTransaction(); - #endif + #endif // !defined(RF24_LINUX) - return status; + return status; } /****************************************************************************/ uint8_t RF24::read_payload(void* buf, uint8_t data_len) { - uint8_t status; - uint8_t* current = reinterpret_cast(buf); + uint8_t status; + uint8_t* current = reinterpret_cast(buf); - if(data_len > payload_size) data_len = payload_size; - uint8_t blank_len = dynamic_payloads_enabled ? 0 : payload_size - data_len; - - //printf("[Reading %u bytes %u blanks]",data_len,blank_len); + if (data_len > payload_size) { + data_len = payload_size; + } + uint8_t blank_len = dynamic_payloads_enabled ? 0 : payload_size - 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) - beginTransaction(); - uint8_t * prx = spi_rxbuff; - uint8_t * ptx = spi_txbuff; + IF_SERIAL_DEBUG(printf("[Reading %u bytes %u blanks]\n", data_len, blank_len); ); + + #if defined(RF24_LINUX) + beginTransaction(); + uint8_t * prx = spi_rxbuff; + uint8_t * ptx = spi_txbuff; uint8_t size; size = data_len + blank_len + 1; // Add register value to transmit buffer - *ptx++ = R_RX_PAYLOAD; - while(--size) - *ptx++ = RF24_NOP; - - size = data_len + blank_len + 1; // Size has been lost during while, re affect - - _SPI.transfernb( (char *) spi_txbuff, (char *) spi_rxbuff, size); - - status = *prx++; // 1st byte is status - + *ptx++ = R_RX_PAYLOAD; + while(--size) + *ptx++ = RF24_NOP; + + size = data_len + blank_len + 1; // Size has been lost during while, re affect + + _SPI.transfernb( (char *) spi_txbuff, (char *) spi_rxbuff, size); + + status = *prx++; // 1st byte is status + if (data_len > 0) { while ( --data_len ) // Decrement before to skip 1st status byte *current++ = *prx++; - + *current = *prx; } - endTransaction(); - #else + endTransaction(); + #else // !defined(RF24_LINUX) - beginTransaction(); - status = _SPI.transfer( R_RX_PAYLOAD ); - while ( data_len-- ) { - *current++ = _SPI.transfer(0xFF); - } - while ( blank_len-- ) { - _SPI.transfer(0xff); - } - endTransaction(); + beginTransaction(); + status = _SPI.transfer(R_RX_PAYLOAD); + while (data_len --) { + *current ++ = _SPI.transfer(0xFF); + } + while (blank_len --) { + _SPI.transfer(0xff); + } + endTransaction(); - #endif + #endif // !defined(RF24_LINUX) - return status; + return status; } /****************************************************************************/ uint8_t RF24::flush_rx(void) { - return spiTrans( FLUSH_RX ); + return spiTrans(FLUSH_RX); } /****************************************************************************/ uint8_t RF24::flush_tx(void) { - return spiTrans( FLUSH_TX ); + return spiTrans(FLUSH_TX); } /****************************************************************************/ -uint8_t RF24::spiTrans(uint8_t cmd){ +uint8_t RF24::spiTrans(uint8_t cmd) +{ + + uint8_t status; + + beginTransaction(); + status = _SPI.transfer(cmd); + endTransaction(); - uint8_t status; - - beginTransaction(); - status = _SPI.transfer( cmd ); - endTransaction(); - - return status; + return status; } /****************************************************************************/ uint8_t RF24::get_status(void) { - return spiTrans(RF24_NOP); + return spiTrans(RF24_NOP); } /****************************************************************************/ -#if !defined (MINIMAL) +#if !defined(MINIMAL) + void RF24::print_status(uint8_t status) { - printf_P(PSTR("STATUS\t\t = 0x%02x RX_DR=%x TX_DS=%x MAX_RT=%x RX_P_NO=%x TX_FULL=%x\r\n"), - status, - (status & _BV(RX_DR))?1:0, - (status & _BV(TX_DS))?1:0, - (status & _BV(MAX_RT))?1:0, - ((status >> RX_P_NO) & 0x07), - (status & _BV(TX_FULL))?1:0 - ); + printf_P(PSTR("STATUS\t\t = 0x%02x RX_DR=%x TX_DS=%x MAX_RT=%x RX_P_NO=%x TX_FULL=%x\r\n"), status, (status & _BV(RX_DR)) ? 1 : 0, + (status & _BV(TX_DS)) ? 1 : 0, (status & _BV(MAX_RT)) ? 1 : 0, ((status >> RX_P_NO) & 0x07), (status & _BV(TX_FULL)) ? 1 : 0); } /****************************************************************************/ void RF24::print_observe_tx(uint8_t value) { - printf_P(PSTR("OBSERVE_TX=%02x: POLS_CNT=%x ARC_CNT=%x\r\n"), - value, - (value >> PLOS_CNT) & 0x0F, - (value >> ARC_CNT) & 0x0F - ); + printf_P(PSTR("OBSERVE_TX=%02x: POLS_CNT=%x ARC_CNT=%x\r\n"), value, (value >> PLOS_CNT) & 0x0F, (value >> ARC_CNT) & 0x0F); } /****************************************************************************/ void RF24::print_byte_register(const char* name, uint8_t reg, uint8_t qty) { - //char extra_tab = strlen_P(name) < 8 ? '\t' : 0; - //printf_P(PSTR(PRIPSTR"\t%c ="),name,extra_tab); - #if defined (RF24_LINUX) + //char extra_tab = strlen_P(name) < 8 ? '\t' : 0; + //printf_P(PSTR(PRIPSTR"\t%c ="),name,extra_tab); + #if defined(RF24_LINUX) printf("%s\t =", name); - #else - printf_P(PSTR(PRIPSTR"\t ="),name); - #endif - while (qty--) - printf_P(PSTR(" 0x%02x"),read_register(reg++)); - printf_P(PSTR("\r\n")); + #else // !defined(RF24_LINUX) + printf_P(PSTR(PRIPSTR + "\t ="),name); + #endif // !defined(RF24_LINUX) + while (qty --) + printf_P(PSTR(" 0x%02x"), read_register(reg ++)); + printf_P(PSTR("\r\n")); } /****************************************************************************/ @@ -411,37 +404,38 @@ void RF24::print_byte_register(const char* name, uint8_t reg, uint8_t qty) void RF24::print_address_register(const char* name, uint8_t reg, uint8_t qty) { - #if defined (RF24_LINUX) + #if defined(RF24_LINUX) printf("%s\t =",name); - #else + #else // !defined(RF24_LINUX) printf_P(PSTR(PRIPSTR"\t ="),name); - #endif - while (qty--) - { - uint8_t buffer[addr_width]; - read_register(reg++,buffer,sizeof buffer); - - printf_P(PSTR(" 0x")); - uint8_t* bufptr = buffer + sizeof buffer; - while( --bufptr >= buffer ) - printf_P(PSTR("%02x"),*bufptr); - } + #endif // !defined(RF24_LINUX) + while (qty --) { + uint8_t buffer[addr_width]; + read_register(reg ++, buffer, sizeof buffer); + + printf_P(PSTR(" 0x")); + uint8_t* bufptr = buffer + sizeof buffer; + while (-- bufptr >= buffer) + printf_P(PSTR("%02x"), *bufptr); + } - printf_P(PSTR("\r\n")); + printf_P(PSTR("\r\n")); } + #endif + /****************************************************************************/ -RF24::RF24(uint16_t _cepin, uint16_t _cspin): - ce_pin(_cepin), csn_pin(_cspin), p_variant(false), - payload_size(32), dynamic_payloads_enabled(false), addr_width(5),csDelay(5)//,pipe0_reading_address(0) +RF24::RF24(uint16_t _cepin, uint16_t _cspin) + :ce_pin(_cepin), csn_pin(_cspin), p_variant(false), payload_size(32), dynamic_payloads_enabled(false), addr_width(5), + csDelay(5)//,pipe0_reading_address(0) { - pipe0_reading_address[0]=0; + pipe0_reading_address[0] = 0; } /****************************************************************************/ -#if defined (RF24_LINUX) && !defined (MRAA)//RPi constructor +#if defined(RF24_LINUX) && !defined(MRAA)//RPi constructor RF24::RF24(uint16_t _cepin, uint16_t _cspin, uint32_t _spi_speed): ce_pin(_cepin),csn_pin(_cspin),spi_speed(_spi_speed),p_variant(false), payload_size(32), dynamic_payloads_enabled(false),addr_width(5)//,pipe0_reading_address(0) @@ -454,32 +448,33 @@ RF24::RF24(uint16_t _cepin, uint16_t _cspin, uint32_t _spi_speed): void RF24::setChannel(uint8_t channel) { - const uint8_t max_channel = 125; - write_register(RF_CH,rf24_min(channel,max_channel)); + const uint8_t max_channel = 125; + write_register(RF_CH, rf24_min(channel, max_channel)); } uint8_t RF24::getChannel() { - - return read_register(RF_CH); + + return read_register(RF_CH); } + /****************************************************************************/ void RF24::setPayloadSize(uint8_t size) { - payload_size = rf24_min(size,32); + payload_size = rf24_min(size, 32); } /****************************************************************************/ uint8_t RF24::getPayloadSize(void) { - return payload_size; + return payload_size; } /****************************************************************************/ -#if !defined (MINIMAL) +#if !defined(MINIMAL) static const char rf24_datarate_e_str_0[] PROGMEM = "1MBPS"; static const char rf24_datarate_e_str_1[] PROGMEM = "2MBPS"; @@ -514,7 +509,7 @@ static const char * const rf24_pa_dbm_e_str_P[] PROGMEM = { rf24_pa_dbm_e_str_3, }; -#if defined (RF24_LINUX) + #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)"; @@ -525,263 +520,276 @@ static const char * const rf24_csn_e_str_P[] = { rf24_csn_e_str_2, rf24_csn_e_str_3, }; -#endif + #endif // defined(RF24_LINUX) void RF24::printDetails(void) { -#if defined (RF24_RPi) - printf("================ SPI Configuration ================\n" ); - if (csn_pin < BCM2835_SPI_CS_NONE ){ - printf("CSN Pin \t = %s\n",rf24_csn_e_str_P[csn_pin]); - }else{ - printf("CSN Pin \t = Custom GPIO%d%s\n", csn_pin, - csn_pin==RPI_V2_GPIO_P1_26 ? " (CE1) Software Driven" : "" ); - } - printf("CE Pin \t = Custom GPIO%d\n", ce_pin ); - printf("Clock Speed\t = " ); - switch (spi_speed) - { - case BCM2835_SPI_SPEED_64MHZ : printf("64 Mhz"); break ; - case BCM2835_SPI_SPEED_32MHZ : printf("32 Mhz"); break ; - case BCM2835_SPI_SPEED_16MHZ : printf("16 Mhz"); break ; - case BCM2835_SPI_SPEED_8MHZ : printf("8 Mhz"); break ; - case BCM2835_SPI_SPEED_4MHZ : printf("4 Mhz"); break ; - case BCM2835_SPI_SPEED_2MHZ : printf("2 Mhz"); break ; - case BCM2835_SPI_SPEED_1MHZ : printf("1 Mhz"); break ; - case BCM2835_SPI_SPEED_512KHZ: printf("512 KHz"); break ; - case BCM2835_SPI_SPEED_256KHZ: printf("256 KHz"); break ; - case BCM2835_SPI_SPEED_128KHZ: printf("128 KHz"); break ; - case BCM2835_SPI_SPEED_64KHZ : printf("64 KHz"); break ; - case BCM2835_SPI_SPEED_32KHZ : printf("32 KHz"); break ; - case BCM2835_SPI_SPEED_16KHZ : printf("16 KHz"); break ; - case BCM2835_SPI_SPEED_8KHZ : printf("8 KHz"); break ; - default : printf("8 Mhz"); break ; - } - printf("\n================ NRF Configuration ================\n"); - -#endif //Linux - - print_status(get_status()); - - print_address_register(PSTR("RX_ADDR_P0-1"),RX_ADDR_P0,2); - print_byte_register(PSTR("RX_ADDR_P2-5"),RX_ADDR_P2,4); - print_address_register(PSTR("TX_ADDR\t"),TX_ADDR); - - print_byte_register(PSTR("RX_PW_P0-6"),RX_PW_P0,6); - print_byte_register(PSTR("EN_AA\t"),EN_AA); - print_byte_register(PSTR("EN_RXADDR"),EN_RXADDR); - print_byte_register(PSTR("RF_CH\t"),RF_CH); - print_byte_register(PSTR("RF_SETUP"),RF_SETUP); - print_byte_register(PSTR("CONFIG\t"),NRF_CONFIG); - print_byte_register(PSTR("DYNPD/FEATURE"),DYNPD,2); - - printf_P(PSTR("Data Rate\t = " PRIPSTR "\r\n"),pgm_read_ptr(&rf24_datarate_e_str_P[getDataRate()])); - printf_P(PSTR("Model\t\t = " PRIPSTR "\r\n"),pgm_read_ptr(&rf24_model_e_str_P[isPVariant()])); - printf_P(PSTR("CRC Length\t = " PRIPSTR "\r\n"),pgm_read_ptr(&rf24_crclength_e_str_P[getCRCLength()])); - printf_P(PSTR("PA Power\t = " PRIPSTR "\r\n"), pgm_read_ptr(&rf24_pa_dbm_e_str_P[getPALevel()])); - -} + #if defined(RF24_RPi) + printf("================ SPI Configuration ================\n" ); + if (csn_pin < BCM2835_SPI_CS_NONE ){ + printf("CSN Pin \t = %s\n",rf24_csn_e_str_P[csn_pin]); + }else{ + printf("CSN Pin \t = Custom GPIO%d%s\n", csn_pin, + csn_pin==RPI_V2_GPIO_P1_26 ? " (CE1) Software Driven" : "" ); + } + printf("CE Pin \t = Custom GPIO%d\n", ce_pin ); + printf("Clock Speed\t = " ); + switch (spi_speed) + { + case BCM2835_SPI_SPEED_64MHZ : printf("64 Mhz"); break ; + case BCM2835_SPI_SPEED_32MHZ : printf("32 Mhz"); break ; + case BCM2835_SPI_SPEED_16MHZ : printf("16 Mhz"); break ; + case BCM2835_SPI_SPEED_8MHZ : printf("8 Mhz"); break ; + case BCM2835_SPI_SPEED_4MHZ : printf("4 Mhz"); break ; + case BCM2835_SPI_SPEED_2MHZ : printf("2 Mhz"); break ; + case BCM2835_SPI_SPEED_1MHZ : printf("1 Mhz"); break ; + case BCM2835_SPI_SPEED_512KHZ: printf("512 KHz"); break ; + case BCM2835_SPI_SPEED_256KHZ: printf("256 KHz"); break ; + case BCM2835_SPI_SPEED_128KHZ: printf("128 KHz"); break ; + case BCM2835_SPI_SPEED_64KHZ : printf("64 KHz"); break ; + case BCM2835_SPI_SPEED_32KHZ : printf("32 KHz"); break ; + case BCM2835_SPI_SPEED_16KHZ : printf("16 KHz"); break ; + case BCM2835_SPI_SPEED_8KHZ : printf("8 KHz"); break ; + default : printf("8 Mhz"); break ; + } + printf("\n================ NRF Configuration ================\n"); + + #endif // defined(RF24_RPi) + + print_status(get_status()); + + print_address_register(PSTR("RX_ADDR_P0-1"), RX_ADDR_P0, 2); + print_byte_register(PSTR("RX_ADDR_P2-5"), RX_ADDR_P2, 4); + print_address_register(PSTR("TX_ADDR\t"), TX_ADDR); + + print_byte_register(PSTR("RX_PW_P0-6"), RX_PW_P0, 6); + print_byte_register(PSTR("EN_AA\t"), EN_AA); + print_byte_register(PSTR("EN_RXADDR"), EN_RXADDR); + print_byte_register(PSTR("RF_CH\t"), RF_CH); + print_byte_register(PSTR("RF_SETUP"), RF_SETUP); + print_byte_register(PSTR("CONFIG\t"), NRF_CONFIG); + print_byte_register(PSTR("DYNPD/FEATURE"), DYNPD, 2); + + printf_P(PSTR("Data Rate\t = " + PRIPSTR + "\r\n"),pgm_read_ptr(&rf24_datarate_e_str_P[getDataRate()])); + printf_P(PSTR("Model\t\t = " + PRIPSTR + "\r\n"),pgm_read_ptr(&rf24_model_e_str_P[isPVariant()])); + printf_P(PSTR("CRC Length\t = " + PRIPSTR + "\r\n"),pgm_read_ptr(&rf24_crclength_e_str_P[getCRCLength()])); + printf_P(PSTR("PA Power\t = " + PRIPSTR + "\r\n"), pgm_read_ptr(&rf24_pa_dbm_e_str_P[getPALevel()])); + +} + +#endif // !defined(MINIMAL) -#endif /****************************************************************************/ bool RF24::begin(void) { - uint8_t setup=0; - - #if defined (RF24_LINUX) - - #if defined (MRAA) - GPIO(); - gpio.begin(ce_pin,csn_pin); - #endif - - #ifdef 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 - + uint8_t setup = 0; + + #if defined(RF24_LINUX) + + #if defined(MRAA) + GPIO(); + gpio.begin(ce_pin,csn_pin); + #endif + + #ifdef 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); - pinMode(ce_pin,OUTPUT); - ce(LOW); + pinMode(ce_pin,OUTPUT); + ce(LOW); + + delay(100); + + #elif defined(LITTLEWIRE) - delay(100); - - #elif defined(LITTLEWIRE) pinMode(csn_pin,OUTPUT); - _SPI.begin(); + _SPI.begin(); + csn(HIGH); + + #elif defined(XMEGA_D3) + if (ce_pin != csn_pin) { + pinMode(ce_pin,OUTPUT); + }; + _SPI.begin(csn_pin); + ce(LOW); csn(HIGH); - #elif defined(XMEGA_D3) - if (ce_pin != csn_pin) pinMode(ce_pin,OUTPUT); - _SPI.begin(csn_pin); - ce(LOW); - csn(HIGH); - delay(200); - #else + delay(200); + #else // Initialize pins - if (ce_pin != csn_pin) pinMode(ce_pin,OUTPUT); - - #if ! defined(LITTLEWIRE) - if (ce_pin != csn_pin) - #endif - pinMode(csn_pin,OUTPUT); - + if (ce_pin != csn_pin) { + pinMode(ce_pin, OUTPUT); + } + + #if !defined(LITTLEWIRE) + if (ce_pin != csn_pin) + #endif // !defined(LITTLEWIRE) + { + pinMode(csn_pin, OUTPUT); + } + _SPI.begin(); ce(LOW); - csn(HIGH); - #if defined (__ARDUINO_X86__) - delay(100); - #endif - #endif //Linux - - // Must allow the radio time to settle else configuration bits will not necessarily stick. - // This is actually only required following power up but some settling time also appears to - // be required after resets too. For full coverage, we'll always assume the worst. - // Enabling 16b CRC is by far the most obvious case if the wrong timing is used - or skipped. - // Technically we require 4.5ms + 14us as a worst case. We'll just call it 5ms for good measure. - // WARNING: Delay is based on P-variant whereby non-P *may* require different timing. - delay( 5 ) ; - - // Reset NRF_CONFIG and enable 16-bit CRC. - write_register( NRF_CONFIG, 0x0C ) ; - - // Set 1500uS (minimum for 32B payload in ESB@250KBPS) timeouts, to make testing a little easier - // WARNING: If this is ever lowered, either 250KBS mode with AA is broken or maximum packet - // sizes must never be used. See documentation for a more complete explanation. - setRetries(5,15); - - // Reset value is MAX - //setPALevel( RF24_PA_MAX ) ; - - // check for connected module and if this is a p nRF24l01 variant - // - if( setDataRate( RF24_250KBPS ) ) - { - p_variant = true ; - } - setup = read_register(RF_SETUP); - /*if( setup == 0b00001110 ) // register default for nRF24L01P - { - p_variant = true ; - }*/ - - // Then set the data rate to the slowest (and most reliable) speed supported by all - // hardware. - setDataRate( RF24_1MBPS ) ; - - // Initialize CRC and request 2-byte (16bit) CRC - //setCRCLength( RF24_CRC_16 ) ; - - // Disable dynamic payloads, to match dynamic_payloads_enabled setting - Reset value is 0 - toggle_features(); - write_register(FEATURE,0 ); - write_register(DYNPD,0); - dynamic_payloads_enabled = false; - - // Reset current status - // Notice reset and flush is the last thing we do - write_register(NRF_STATUS,_BV(RX_DR) | _BV(TX_DS) | _BV(MAX_RT) ); - - // Set up default configuration. Callers can always change it later. - // This channel should be universally safe and not bleed over into adjacent - // spectrum. - setChannel(76); - - // Flush buffers - flush_rx(); - flush_tx(); - - powerUp(); //Power up by default when begin() is called - - // Enable PTX, do not write CE high so radio will remain in standby I mode ( 130us max to transition to RX or TX instead of 1500us from powerUp ) - // PTX should use only 22uA of power - write_register(NRF_CONFIG, ( read_register(NRF_CONFIG) ) & ~_BV(PRIM_RX) ); - - // if setup is 0 or ff then there was no response from module - return ( setup != 0 && setup != 0xff ); + csn(HIGH); + #if defined(__ARDUINO_X86__) + delay(100); + #endif + #endif //Linux + + // Must allow the radio time to settle else configuration bits will not necessarily stick. + // This is actually only required following power up but some settling time also appears to + // be required after resets too. For full coverage, we'll always assume the worst. + // Enabling 16b CRC is by far the most obvious case if the wrong timing is used - or skipped. + // Technically we require 4.5ms + 14us as a worst case. We'll just call it 5ms for good measure. + // WARNING: Delay is based on P-variant whereby non-P *may* require different timing. + delay(5); + + // Reset NRF_CONFIG and enable 16-bit CRC. + write_register(NRF_CONFIG, 0x0C); + + // Set 1500uS (minimum for 32B payload in ESB@250KBPS) timeouts, to make testing a little easier + // WARNING: If this is ever lowered, either 250KBS mode with AA is broken or maximum packet + // sizes must never be used. See documentation for a more complete explanation. + setRetries(5, 15); + + // Reset value is MAX + //setPALevel( RF24_PA_MAX ) ; + + // check for connected module and if this is a p nRF24l01 variant + // + if (setDataRate(RF24_250KBPS)) { + p_variant = true; + } + setup = read_register(RF_SETUP); + /*if( setup == 0b00001110 ) // register default for nRF24L01P + { + p_variant = true ; + }*/ + + // Then set the data rate to the slowest (and most reliable) speed supported by all + // hardware. + setDataRate(RF24_1MBPS); + + // Initialize CRC and request 2-byte (16bit) CRC + //setCRCLength( RF24_CRC_16 ) ; + + // Disable dynamic payloads, to match dynamic_payloads_enabled setting - Reset value is 0 + toggle_features(); + write_register(FEATURE, 0); + write_register(DYNPD, 0); + dynamic_payloads_enabled = false; + + // Reset current status + // Notice reset and flush is the last thing we do + write_register(NRF_STATUS, _BV(RX_DR) | _BV(TX_DS) | _BV(MAX_RT)); + + // Set up default configuration. Callers can always change it later. + // This channel should be universally safe and not bleed over into adjacent + // spectrum. + setChannel(76); + + // Flush buffers + flush_rx(); + flush_tx(); + + powerUp(); //Power up by default when begin() is called + + // Enable PTX, do not write CE high so radio will remain in standby I mode ( 130us max to transition to RX or TX instead of 1500us from powerUp ) + // PTX should use only 22uA of power + write_register(NRF_CONFIG, (read_register(NRF_CONFIG)) & ~ _BV(PRIM_RX)); + + // if setup is 0 or ff then there was no response from module + return (setup != 0 && setup != 0xff); } /****************************************************************************/ bool RF24::isChipConnected() { - uint8_t setup = read_register(SETUP_AW); - if(setup >= 1 && setup <= 3) - { - return true; - } + uint8_t setup = read_register(SETUP_AW); + if (setup >= 1 && setup <= 3) { + return true; + } - return false; + return false; } /****************************************************************************/ void RF24::startListening(void) { - #if !defined (RF24_TINY) && ! defined(LITTLEWIRE) - powerUp(); - #endif - write_register(NRF_CONFIG, read_register(NRF_CONFIG) | _BV(PRIM_RX)); - write_register(NRF_STATUS, _BV(RX_DR) | _BV(TX_DS) | _BV(MAX_RT) ); - ce(HIGH); - // Restore the pipe0 adddress, if exists - if (pipe0_reading_address[0] > 0){ - write_register(RX_ADDR_P0, pipe0_reading_address, addr_width); - }else{ - closeReadingPipe(0); - } + #if !defined(RF24_TINY) && !defined(LITTLEWIRE) + powerUp(); + #endif + write_register(NRF_CONFIG, read_register(NRF_CONFIG) | _BV(PRIM_RX)); + write_register(NRF_STATUS, _BV(RX_DR) | _BV(TX_DS) | _BV(MAX_RT)); + ce(HIGH); + // Restore the pipe0 adddress, if exists + if (pipe0_reading_address[0] > 0) { + write_register(RX_ADDR_P0, pipe0_reading_address, addr_width); + } else { + closeReadingPipe(0); + } - // Flush buffers - //flush_rx(); - if(read_register(FEATURE) & _BV(EN_ACK_PAY)){ - flush_tx(); - } + // Flush buffers + //flush_rx(); + if (read_register(FEATURE) & _BV(EN_ACK_PAY)) { + flush_tx(); + } - // Go! - //delayMicroseconds(100); + // Go! + //delayMicroseconds(100); } /****************************************************************************/ -static const uint8_t child_pipe_enable[] PROGMEM = -{ - ERX_P0, ERX_P1, ERX_P2, ERX_P3, ERX_P4, ERX_P5 -}; +static const uint8_t child_pipe_enable[] +PROGMEM = {ERX_P0, ERX_P1, ERX_P2, ERX_P3, ERX_P4, ERX_P5}; void RF24::stopListening(void) -{ - ce(LOW); +{ + ce(LOW); - delayMicroseconds(txDelay); - - if(read_register(FEATURE) & _BV(EN_ACK_PAY)){ - delayMicroseconds(txDelay); //200 - flush_tx(); - } - //flush_rx(); - write_register(NRF_CONFIG, ( read_register(NRF_CONFIG) ) & ~_BV(PRIM_RX) ); - - #if defined (RF24_TINY) || defined (LITTLEWIRE) - // for 3 pins solution TX mode is only left with additonal powerDown/powerUp cycle - if (ce_pin == csn_pin) { - powerDown(); - powerUp(); - } - #endif - write_register(EN_RXADDR,read_register(EN_RXADDR) | _BV(pgm_read_byte(&child_pipe_enable[0]))); // Enable RX on pipe0 - - //delayMicroseconds(100); + delayMicroseconds(txDelay); + + if (read_register(FEATURE) & _BV(EN_ACK_PAY)) { + delayMicroseconds(txDelay); //200 + flush_tx(); + } + //flush_rx(); + write_register(NRF_CONFIG, (read_register(NRF_CONFIG)) & ~ _BV(PRIM_RX)); + + #if defined(RF24_TINY) || defined(LITTLEWIRE) + // for 3 pins solution TX mode is only left with additonal powerDown/powerUp cycle + if (ce_pin == csn_pin) { + powerDown(); + powerUp(); + } + #endif + write_register(EN_RXADDR, read_register(EN_RXADDR) | _BV(pgm_read_byte(&child_pipe_enable[0]))); // Enable RX on pipe0 + + //delayMicroseconds(100); } @@ -789,8 +797,8 @@ void RF24::stopListening(void) void RF24::powerDown(void) { - ce(LOW); // Guarantee CE is low on powerDown - write_register(NRF_CONFIG,read_register(NRF_CONFIG) & ~_BV(PWR_UP)); + ce(LOW); // Guarantee CE is low on powerDown + write_register(NRF_CONFIG, read_register(NRF_CONFIG) & ~ _BV(PWR_UP)); } /****************************************************************************/ @@ -798,156 +806,165 @@ void RF24::powerDown(void) //Power up now. Radio will not power down unless instructed by MCU for config changes etc. void RF24::powerUp(void) { - uint8_t cfg = read_register(NRF_CONFIG); + uint8_t cfg = read_register(NRF_CONFIG); - // if not powered up then power up and wait for the radio to initialize - if (!(cfg & _BV(PWR_UP))){ - write_register(NRF_CONFIG, cfg | _BV(PWR_UP)); + // if not powered up then power up and wait for the radio to initialize + if (! (cfg & _BV(PWR_UP))) { + write_register(NRF_CONFIG, cfg | _BV(PWR_UP)); - // For nRF24L01+ to go from power down mode to TX or RX mode it must first pass through stand-by mode. - // There must be a delay of Tpd2stby (see Table 16.) after the nRF24L01+ leaves power down mode before - // the CEis set high. - Tpd2stby can be up to 5ms per the 1.0 datasheet - delay(5); - } + // For nRF24L01+ to go from power down mode to TX or RX mode it must first pass through stand-by mode. + // There must be a delay of Tpd2stby (see Table 16.) after the nRF24L01+ leaves power down mode before + // the CEis set high. - Tpd2stby can be up to 5ms per the 1.0 datasheet + delay(5); + } } /******************************************************************/ -#if defined (FAILURE_HANDLING) || defined (RF24_LINUX) -void RF24::errNotify(){ - #if defined (SERIAL_DEBUG) || defined (RF24_LINUX) - printf_P(PSTR("RF24 HARDWARE FAIL: Radio not responding, verify pin connections, wiring, etc.\r\n")); - #endif - #if defined (FAILURE_HANDLING) - failureDetected = 1; - #else - delay(5000); - #endif +#if defined(FAILURE_HANDLING) || defined(RF24_LINUX) + +void RF24::errNotify() +{ + #if defined(SERIAL_DEBUG) || defined(RF24_LINUX) + printf_P(PSTR("RF24 HARDWARE FAIL: Radio not responding, verify pin connections, wiring, etc.\r\n")); + #endif + #if defined(FAILURE_HANDLING) + failureDetected = 1; + #else + delay(5000); + #endif } + #endif /******************************************************************/ //Similar to the previous write, clears the interrupt flags -bool RF24::write( const void* buf, uint8_t len, const bool multicast ) -{ - //Start Writing - startFastWrite(buf,len,multicast); - - //Wait until complete or failed - #if defined (FAILURE_HANDLING) || defined (RF24_LINUX) - uint32_t timer = millis(); - #endif - - while( ! ( get_status() & ( _BV(TX_DS) | _BV(MAX_RT) ))) { - #if defined (FAILURE_HANDLING) || defined (RF24_LINUX) - if(millis() - timer > 95){ - errNotify(); - #if defined (FAILURE_HANDLING) - return 0; - #else - delay(100); - #endif - } - #endif - } - - ce(LOW); - - uint8_t status = write_register(NRF_STATUS,_BV(RX_DR) | _BV(TX_DS) | _BV(MAX_RT) ); - - //Max retries exceeded - if( status & _BV(MAX_RT)){ - flush_tx(); //Only going to be 1 packet int the FIFO at a time using this method, so just flush - return 0; - } - //TX OK 1 or 0 - return 1; -} - -bool RF24::write( const void* buf, uint8_t len ){ - return write(buf,len,0); +bool RF24::write(const void* buf, uint8_t len, const bool multicast) +{ + //Start Writing + startFastWrite(buf, len, multicast); + + //Wait until complete or failed + #if defined(FAILURE_HANDLING) || defined(RF24_LINUX) + uint32_t timer = millis(); + #endif // defined(FAILURE_HANDLING) || defined(RF24_LINUX) + + while (! (get_status() & (_BV(TX_DS) | _BV(MAX_RT)))) { + #if defined(FAILURE_HANDLING) || defined(RF24_LINUX) + if (millis() - timer > 95) { + errNotify(); + #if defined(FAILURE_HANDLING) + return 0; + #else + delay(100); + #endif + } + #endif + } + + ce(LOW); + + uint8_t status = write_register(NRF_STATUS, _BV(RX_DR) | _BV(TX_DS) | _BV(MAX_RT)); + + //Max retries exceeded + if (status & _BV(MAX_RT)) { + flush_tx(); //Only going to be 1 packet int the FIFO at a time using this method, so just flush + return 0; + } + //TX OK 1 or 0 + return 1; +} + +bool RF24::write(const void* buf, uint8_t len) +{ + return write(buf, len, 0); } /****************************************************************************/ //For general use, the interrupt flags are not important to clear -bool RF24::writeBlocking( const void* buf, uint8_t len, uint32_t timeout ) +bool RF24::writeBlocking(const void* buf, uint8_t len, uint32_t timeout) { - //Block until the FIFO is NOT full. - //Keep track of the MAX retries and set auto-retry if seeing failures - //This way the FIFO will fill up and allow blocking until packets go through - //The radio will auto-clear everything in the FIFO as long as CE remains high - - uint32_t timer = millis(); //Get the time that the payload transmission started + //Block until the FIFO is NOT full. + //Keep track of the MAX retries and set auto-retry if seeing failures + //This way the FIFO will fill up and allow blocking until packets go through + //The radio will auto-clear everything in the FIFO as long as CE remains high + + uint32_t timer = millis(); //Get the time that the payload transmission started + + while ((get_status() + & (_BV(TX_FULL)))) { //Blocking only if FIFO is full. This will loop and block until TX is successful or timeout + + if (get_status() & _BV(MAX_RT)) { //If MAX Retries have been reached + reUseTX(); //Set re-transmit and clear the MAX_RT interrupt flag + if (millis() - timer > timeout) { + return 0; + } //If this payload has exceeded the user-defined timeout, exit and return 0 + } + #if defined(FAILURE_HANDLING) || defined(RF24_LINUX) + if (millis() - timer > (timeout + 95)) { + errNotify(); + #if defined(FAILURE_HANDLING) + return 0; + #endif + } + #endif - while( ( get_status() & ( _BV(TX_FULL) ))) { //Blocking only if FIFO is full. This will loop and block until TX is successful or timeout - - if( get_status() & _BV(MAX_RT)){ //If MAX Retries have been reached - reUseTX(); //Set re-transmit and clear the MAX_RT interrupt flag - if(millis() - timer > timeout){ return 0; } //If this payload has exceeded the user-defined timeout, exit and return 0 - } - #if defined (FAILURE_HANDLING) || defined (RF24_LINUX) - if(millis() - timer > (timeout+95) ){ - errNotify(); - #if defined (FAILURE_HANDLING) - return 0; - #endif - } - #endif - - } + } - //Start Writing - startFastWrite(buf,len,0); //Write the payload if a buffer is clear + //Start Writing + startFastWrite(buf, len, 0); //Write the payload if a buffer is clear - return 1; //Return 1 to indicate successful transmission + return 1; //Return 1 to indicate successful transmission } /****************************************************************************/ -void RF24::reUseTX(){ - write_register(NRF_STATUS,_BV(MAX_RT) ); //Clear max retry flag - spiTrans( REUSE_TX_PL ); - ce(LOW); //Re-Transfer packet - ce(HIGH); +void RF24::reUseTX() +{ + write_register(NRF_STATUS, _BV(MAX_RT)); //Clear max retry flag + spiTrans(REUSE_TX_PL); + ce(LOW); //Re-Transfer packet + ce(HIGH); } /****************************************************************************/ -bool RF24::writeFast( const void* buf, uint8_t len, const bool multicast ) +bool RF24::writeFast(const void* buf, uint8_t len, const bool multicast) { - //Block until the FIFO is NOT full. - //Keep track of the MAX retries and set auto-retry if seeing failures - //Return 0 so the user can control the retrys and set a timer or failure counter if required - //The radio will auto-clear everything in the FIFO as long as CE remains high + //Block until the FIFO is NOT full. + //Keep track of the MAX retries and set auto-retry if seeing failures + //Return 0 so the user can control the retrys and set a timer or failure counter if required + //The radio will auto-clear everything in the FIFO as long as CE remains high - #if defined (FAILURE_HANDLING) || defined (RF24_LINUX) - uint32_t timer = millis(); - #endif - - while( ( get_status() & ( _BV(TX_FULL) ))) { //Blocking only if FIFO is full. This will loop and block until TX is successful or fail + #if defined(FAILURE_HANDLING) || defined(RF24_LINUX) + uint32_t timer = millis(); + #endif - if( get_status() & _BV(MAX_RT)){ - //reUseTX(); //Set re-transmit - write_register(NRF_STATUS,_BV(MAX_RT) ); //Clear max retry flag - return 0; //Return 0. The previous payload has been retransmitted - //From the user perspective, if you get a 0, just keep trying to send the same payload - } - #if defined (FAILURE_HANDLING) || defined (RF24_LINUX) - if(millis() - timer > 95 ){ - errNotify(); - #if defined (FAILURE_HANDLING) - return 0; - #endif - } - #endif - } - //Start Writing - startFastWrite(buf,len,multicast); + //Blocking only if FIFO is full. This will loop and block until TX is successful or fail + while ((get_status() & (_BV(TX_FULL)))) { + if (get_status() & _BV(MAX_RT)) { + //reUseTX(); //Set re-transmit + write_register(NRF_STATUS, _BV(MAX_RT)); //Clear max retry flag + return 0; //Return 0. The previous payload has been retransmitted + // From the user perspective, if you get a 0, just keep trying to send the same payload + } + #if defined(FAILURE_HANDLING) || defined(RF24_LINUX) + if (millis() - timer > 95) { + errNotify(); + #if defined(FAILURE_HANDLING) + return 0; + #endif // defined(FAILURE_HANDLING) + } + #endif + } + //Start Writing + startFastWrite(buf, len, multicast); - return 1; + return 1; } -bool RF24::writeFast( const void* buf, uint8_t len ){ - return writeFast(buf,len,0); +bool RF24::writeFast(const void* buf, uint8_t len) +{ + return writeFast(buf, len, 0); } /****************************************************************************/ @@ -957,13 +974,14 @@ bool RF24::writeFast( const void* buf, uint8_t len ){ //Otherwise we enter Standby-II mode, which is still faster than standby mode //Also, we remove the need to keep writing the config register over and over and delaying for 150 us each time if sending a stream of data -void RF24::startFastWrite( const void* buf, uint8_t len, const bool multicast, bool startTx){ //TMRh20 +void RF24::startFastWrite(const void* buf, uint8_t len, const bool multicast, bool startTx) +{ //TMRh20 - //write_payload( buf,len); - write_payload( buf, len,multicast ? W_TX_PAYLOAD_NO_ACK : W_TX_PAYLOAD ) ; - if(startTx){ - ce(HIGH); - } + //write_payload( buf,len); + write_payload(buf, len, multicast ? W_TX_PAYLOAD_NO_ACK : W_TX_PAYLOAD); + if (startTx) { + ce(HIGH); + } } @@ -971,253 +989,257 @@ void RF24::startFastWrite( const void* buf, uint8_t len, const bool multicast, b //Added the original startWrite back in so users can still use interrupts, ack payloads, etc //Allows the library to pass all tests -void RF24::startWrite( const void* buf, uint8_t len, const bool multicast ){ - - // Send the payload - - //write_payload( buf, len ); - write_payload( buf, len,multicast? W_TX_PAYLOAD_NO_ACK : W_TX_PAYLOAD ) ; - ce(HIGH); - #if !defined(F_CPU) || F_CPU > 20000000 - delayMicroseconds(10); - #endif - ce(LOW); +void RF24::startWrite(const void* buf, uint8_t len, const bool multicast) +{ + // Send the payload + //write_payload( buf, len ); + write_payload(buf, len, multicast ? W_TX_PAYLOAD_NO_ACK : W_TX_PAYLOAD); + ce(HIGH); + #if !defined(F_CPU) || F_CPU > 20000000 + delayMicroseconds(10); + #endif + ce(LOW); } /****************************************************************************/ -bool RF24::rxFifoFull(){ - return read_register(FIFO_STATUS) & _BV(RX_FULL); +bool RF24::rxFifoFull() +{ + return read_register(FIFO_STATUS) & _BV(RX_FULL); } + /****************************************************************************/ -bool RF24::txStandBy(){ +bool RF24::txStandBy() +{ - #if defined (FAILURE_HANDLING) || defined (RF24_LINUX) - uint32_t timeout = millis(); - #endif - while( ! (read_register(FIFO_STATUS) & _BV(TX_EMPTY)) ){ - if( get_status() & _BV(MAX_RT)){ - write_register(NRF_STATUS,_BV(MAX_RT) ); - ce(LOW); - flush_tx(); //Non blocking, flush the data - return 0; - } - #if defined (FAILURE_HANDLING) || defined (RF24_LINUX) - if( millis() - timeout > 95){ - errNotify(); - #if defined (FAILURE_HANDLING) - return 0; - #endif - } - #endif - } + #if defined(FAILURE_HANDLING) || defined(RF24_LINUX) + uint32_t timeout = millis(); + #endif + while (! (read_register(FIFO_STATUS) & _BV(TX_EMPTY))) { + if (get_status() & _BV(MAX_RT)) { + write_register(NRF_STATUS, _BV(MAX_RT)); + ce(LOW); + flush_tx(); //Non blocking, flush the data + return 0; + } + #if defined(FAILURE_HANDLING) || defined(RF24_LINUX) + if (millis() - timeout > 95) { + errNotify(); + #if defined(FAILURE_HANDLING) + return 0; + #endif + } + #endif + } - ce(LOW); //Set STANDBY-I mode - return 1; + ce(LOW); //Set STANDBY-I mode + return 1; } /****************************************************************************/ -bool RF24::txStandBy(uint32_t timeout, bool startTx){ - - if(startTx){ - stopListening(); - ce(HIGH); - } - uint32_t start = millis(); +bool RF24::txStandBy(uint32_t timeout, bool startTx) +{ - while( ! (read_register(FIFO_STATUS) & _BV(TX_EMPTY)) ){ - if( get_status() & _BV(MAX_RT)){ - write_register(NRF_STATUS,_BV(MAX_RT) ); - ce(LOW); //Set re-transmit - ce(HIGH); - if(millis() - start >= timeout){ - ce(LOW); flush_tx(); return 0; - } - } - #if defined (FAILURE_HANDLING) || defined (RF24_LINUX) - if( millis() - start > (timeout+95)){ - errNotify(); - #if defined (FAILURE_HANDLING) - return 0; - #endif - } - #endif - } + if (startTx) { + stopListening(); + ce(HIGH); + } + uint32_t start = millis(); + + while (! (read_register(FIFO_STATUS) & _BV(TX_EMPTY))) { + if (get_status() & _BV(MAX_RT)) { + write_register(NRF_STATUS, _BV(MAX_RT)); + ce(LOW); // Set re-transmit + ce(HIGH); + if (millis() - start >= timeout) { + ce(LOW); + flush_tx(); + return 0; + } + } + #if defined(FAILURE_HANDLING) || defined(RF24_LINUX) + if (millis() - start > (timeout + 95)) { + errNotify(); + #if defined(FAILURE_HANDLING) + return 0; + #endif + } + #endif + } - - ce(LOW); //Set STANDBY-I mode - return 1; + ce(LOW); //Set STANDBY-I mode + return 1; } /****************************************************************************/ -void RF24::maskIRQ(bool tx, bool fail, bool rx){ +void RF24::maskIRQ(bool tx, bool fail, bool rx) +{ - uint8_t config = read_register(NRF_CONFIG); - /* clear the interrupt flags */ - config &= ~(1 << MASK_MAX_RT | 1 << MASK_TX_DS | 1 << MASK_RX_DR); - /* set the specified interrupt flags */ - config |= fail << MASK_MAX_RT | tx << MASK_TX_DS | rx << MASK_RX_DR; - write_register(NRF_CONFIG, config); + uint8_t config = read_register(NRF_CONFIG); + /* clear the interrupt flags */ + config &= ~ (1 << MASK_MAX_RT | 1 << MASK_TX_DS | 1 << MASK_RX_DR); + /* set the specified interrupt flags */ + config |= fail << MASK_MAX_RT | tx << MASK_TX_DS | rx << MASK_RX_DR; + write_register(NRF_CONFIG, config); } /****************************************************************************/ uint8_t RF24::getDynamicPayloadSize(void) { - uint8_t result = 0; + uint8_t result = 0; - #if defined (RF24_LINUX) - spi_txbuff[0] = R_RX_PL_WID; - spi_txbuff[1] = 0xff; - beginTransaction(); - _SPI.transfernb( (char *) spi_txbuff, (char *) spi_rxbuff, 2); - result = spi_rxbuff[1]; - endTransaction(); - #else - beginTransaction(); - _SPI.transfer( R_RX_PL_WID ); - result = _SPI.transfer(0xff); - endTransaction(); - #endif + #if defined(RF24_LINUX) + spi_txbuff[0] = R_RX_PL_WID; + spi_txbuff[1] = 0xff; + beginTransaction(); + _SPI.transfernb( (char *) spi_txbuff, (char *) spi_rxbuff, 2); + result = spi_rxbuff[1]; + endTransaction(); + #else + beginTransaction(); + _SPI.transfer(R_RX_PL_WID); + result = _SPI.transfer(0xff); + endTransaction(); + #endif - if(result > 32) { flush_rx(); delay(2); return 0; } - return result; + if (result > 32) { + flush_rx(); + delay(2); + return 0; + } + return result; } /****************************************************************************/ bool RF24::available(void) { - return available(NULL); + return available(NULL); } /****************************************************************************/ bool RF24::available(uint8_t* pipe_num) { - if (!( read_register(FIFO_STATUS) & _BV(RX_EMPTY) )){ - - // If the caller wants the pipe number, include that - if ( pipe_num ){ - uint8_t status = get_status(); - *pipe_num = ( status >> RX_P_NO ) & 0x07; - } - return 1; - } - + if (! (read_register(FIFO_STATUS) & _BV(RX_EMPTY))) { + + // If the caller wants the pipe number, include that + if (pipe_num) { + uint8_t status = get_status(); + *pipe_num = (status >> RX_P_NO) & 0x07; + } + return 1; + } - return 0; + return 0; } /****************************************************************************/ -void RF24::read( void* buf, uint8_t len ){ +void RF24::read(void* buf, uint8_t len) +{ - // Fetch the payload - read_payload( buf, len ); + // Fetch the payload + read_payload(buf, len); - //Clear the two possible interrupt flags with one command - write_register(NRF_STATUS,_BV(RX_DR) | _BV(MAX_RT) | _BV(TX_DS) ); + //Clear the two possible interrupt flags with one command + write_register(NRF_STATUS, _BV(RX_DR) | _BV(MAX_RT) | _BV(TX_DS)); } /****************************************************************************/ -void RF24::whatHappened(bool& tx_ok,bool& tx_fail,bool& rx_ready) +void RF24::whatHappened(bool& tx_ok, bool& tx_fail, bool& rx_ready) { - // Read the status & reset the status in one easy call - // Or is that such a good idea? - uint8_t status = write_register(NRF_STATUS,_BV(RX_DR) | _BV(TX_DS) | _BV(MAX_RT) ); + // Read the status & reset the status in one easy call + // Or is that such a good idea? + uint8_t status = write_register(NRF_STATUS, _BV(RX_DR) | _BV(TX_DS) | _BV(MAX_RT)); - // Report to the user what happened - tx_ok = status & _BV(TX_DS); - tx_fail = status & _BV(MAX_RT); - rx_ready = status & _BV(RX_DR); + // Report to the user what happened + tx_ok = status & _BV(TX_DS); + tx_fail = status & _BV(MAX_RT); + rx_ready = status & _BV(RX_DR); } /****************************************************************************/ void RF24::openWritingPipe(uint64_t value) { - // Note that AVR 8-bit uC's store this LSB first, and the NRF24L01(+) - // expects it LSB first too, so we're good. + // Note that AVR 8-bit uC's store this LSB first, and the NRF24L01(+) + // expects it LSB first too, so we're good. + + write_register(RX_ADDR_P0, reinterpret_cast(&value), addr_width); + write_register(TX_ADDR, reinterpret_cast(&value), addr_width); + - write_register(RX_ADDR_P0, reinterpret_cast(&value), addr_width); - write_register(TX_ADDR, reinterpret_cast(&value), addr_width); - - - //const uint8_t max_payload_size = 32; - //write_register(RX_PW_P0,rf24_min(payload_size,max_payload_size)); - write_register(RX_PW_P0,payload_size); + //const uint8_t max_payload_size = 32; + //write_register(RX_PW_P0,rf24_min(payload_size,max_payload_size)); + write_register(RX_PW_P0, payload_size); } /****************************************************************************/ -void RF24::openWritingPipe(const uint8_t *address) +void RF24::openWritingPipe(const uint8_t* address) { - // Note that AVR 8-bit uC's store this LSB first, and the NRF24L01(+) - // expects it LSB first too, so we're good. + // Note that AVR 8-bit uC's store this LSB first, and the NRF24L01(+) + // expects it LSB first too, so we're good. + write_register(RX_ADDR_P0, address, addr_width); + write_register(TX_ADDR, address, addr_width); - write_register(RX_ADDR_P0,address, addr_width); - write_register(TX_ADDR, address, addr_width); - - //const uint8_t max_payload_size = 32; - //write_register(RX_PW_P0,rf24_min(payload_size,max_payload_size)); - write_register(RX_PW_P0,payload_size); + //const uint8_t max_payload_size = 32; + //write_register(RX_PW_P0,rf24_min(payload_size,max_payload_size)); + write_register(RX_PW_P0, payload_size); } /****************************************************************************/ -static const uint8_t child_pipe[] PROGMEM = -{ - RX_ADDR_P0, RX_ADDR_P1, RX_ADDR_P2, RX_ADDR_P3, RX_ADDR_P4, RX_ADDR_P5 -}; -static const uint8_t child_payload_size[] PROGMEM = -{ - RX_PW_P0, RX_PW_P1, RX_PW_P2, RX_PW_P3, RX_PW_P4, RX_PW_P5 -}; - +static const uint8_t child_pipe[] +PROGMEM = {RX_ADDR_P0, RX_ADDR_P1, RX_ADDR_P2, RX_ADDR_P3, RX_ADDR_P4, RX_ADDR_P5}; +static const uint8_t child_payload_size[] +PROGMEM = {RX_PW_P0, RX_PW_P1, RX_PW_P2, RX_PW_P3, RX_PW_P4, RX_PW_P5}; void RF24::openReadingPipe(uint8_t child, uint64_t address) { - // If this is pipe 0, cache the address. This is needed because - // openWritingPipe() will overwrite the pipe 0 address, so - // startListening() will have to restore it. - if (child == 0){ - memcpy(pipe0_reading_address,&address,addr_width); - } + // If this is pipe 0, cache the address. This is needed because + // openWritingPipe() will overwrite the pipe 0 address, so + // startListening() will have to restore it. + if (child == 0) { + memcpy(pipe0_reading_address, &address, addr_width); + } - if (child <= 6) - { - // For pipes 2-5, only write the LSB - if ( child < 2 ) - write_register(pgm_read_byte(&child_pipe[child]), reinterpret_cast(&address), addr_width); - else - write_register(pgm_read_byte(&child_pipe[child]), reinterpret_cast(&address), 1); + if (child <= 6) { + // For pipes 2-5, only write the LSB + if (child < 2) { + write_register(pgm_read_byte(&child_pipe[child]), reinterpret_cast(&address), addr_width); + } else { + write_register(pgm_read_byte(&child_pipe[child]), reinterpret_cast(&address), 1); + } - write_register(pgm_read_byte(&child_payload_size[child]),payload_size); + write_register(pgm_read_byte(&child_payload_size[child]), payload_size); - // Note it would be more efficient to set all of the bits for all open - // pipes at once. However, I thought it would make the calling code - // more simple to do it this way. - write_register(EN_RXADDR,read_register(EN_RXADDR) | _BV(pgm_read_byte(&child_pipe_enable[child]))); - } + // Note it would be more efficient to set all of the bits for all open + // pipes at once. However, I thought it would make the calling code + // more simple to do it this way. + write_register(EN_RXADDR, read_register(EN_RXADDR) | _BV(pgm_read_byte(&child_pipe_enable[child]))); + } } /****************************************************************************/ -void RF24::setAddressWidth(uint8_t a_width){ +void RF24::setAddressWidth(uint8_t a_width) +{ - if(a_width -= 2){ - write_register(SETUP_AW,a_width%4); - addr_width = (a_width%4) + 2; - }else{ - write_register(SETUP_AW,0); + if (a_width -= 2) { + write_register(SETUP_AW, a_width % 4); + addr_width = (a_width % 4) + 2; + } else { + write_register(SETUP_AW, 0); addr_width = 2; } @@ -1225,37 +1247,36 @@ void RF24::setAddressWidth(uint8_t a_width){ /****************************************************************************/ -void RF24::openReadingPipe(uint8_t child, const uint8_t *address) +void RF24::openReadingPipe(uint8_t child, const uint8_t* address) { - // If this is pipe 0, cache the address. This is needed because - // openWritingPipe() will overwrite the pipe 0 address, so - // startListening() will have to restore it. - if (child == 0){ - memcpy(pipe0_reading_address,address,addr_width); - } - if (child <= 6) - { - // For pipes 2-5, only write the LSB - if ( child < 2 ){ - write_register(pgm_read_byte(&child_pipe[child]), address, addr_width); - }else{ - write_register(pgm_read_byte(&child_pipe[child]), address, 1); - } - write_register(pgm_read_byte(&child_payload_size[child]),payload_size); - - // Note it would be more efficient to set all of the bits for all open - // pipes at once. However, I thought it would make the calling code - // more simple to do it this way. - write_register(EN_RXADDR,read_register(EN_RXADDR) | _BV(pgm_read_byte(&child_pipe_enable[child]))); + // If this is pipe 0, cache the address. This is needed because + // openWritingPipe() will overwrite the pipe 0 address, so + // startListening() will have to restore it. + if (child == 0) { + memcpy(pipe0_reading_address, address, addr_width); + } + if (child <= 6) { + // For pipes 2-5, only write the LSB + if (child < 2) { + write_register(pgm_read_byte(&child_pipe[child]), address, addr_width); + } else { + write_register(pgm_read_byte(&child_pipe[child]), address, 1); + } + write_register(pgm_read_byte(&child_payload_size[child]), payload_size); + + // Note it would be more efficient to set all of the bits for all open + // pipes at once. However, I thought it would make the calling code + // more simple to do it this way. + write_register(EN_RXADDR, read_register(EN_RXADDR) | _BV(pgm_read_byte(&child_pipe_enable[child]))); - } + } } /****************************************************************************/ -void RF24::closeReadingPipe( uint8_t pipe ) +void RF24::closeReadingPipe(uint8_t pipe) { - write_register(EN_RXADDR,read_register(EN_RXADDR) & ~_BV(pgm_read_byte(&child_pipe_enable[pipe]))); + write_register(EN_RXADDR, read_register(EN_RXADDR) & ~ _BV(pgm_read_byte(&child_pipe_enable[pipe]))); } /****************************************************************************/ @@ -1263,83 +1284,81 @@ void RF24::closeReadingPipe( uint8_t pipe ) void RF24::toggle_features(void) { beginTransaction(); - _SPI.transfer( ACTIVATE ); - _SPI.transfer( 0x73 ); - endTransaction(); + _SPI.transfer(ACTIVATE); + _SPI.transfer(0x73); + endTransaction(); } /****************************************************************************/ void RF24::enableDynamicPayloads(void) { - // Enable dynamic payload throughout the system + // Enable dynamic payload throughout the system //toggle_features(); - write_register(FEATURE,read_register(FEATURE) | _BV(EN_DPL) ); + write_register(FEATURE, read_register(FEATURE) | _BV(EN_DPL)); + IF_SERIAL_DEBUG(printf("FEATURE=%i\r\n", read_register(FEATURE))); - IF_SERIAL_DEBUG(printf("FEATURE=%i\r\n",read_register(FEATURE))); + // Enable dynamic payload on all pipes + // + // Not sure the use case of only having dynamic payload on certain + // pipes, so the library does not support it. + write_register(DYNPD, read_register(DYNPD) | _BV(DPL_P5) | _BV(DPL_P4) | _BV(DPL_P3) | _BV(DPL_P2) | _BV(DPL_P1) | _BV(DPL_P0)); - // Enable dynamic payload on all pipes - // - // Not sure the use case of only having dynamic payload on certain - // pipes, so the library does not support it. - write_register(DYNPD,read_register(DYNPD) | _BV(DPL_P5) | _BV(DPL_P4) | _BV(DPL_P3) | _BV(DPL_P2) | _BV(DPL_P1) | _BV(DPL_P0)); - - dynamic_payloads_enabled = true; + dynamic_payloads_enabled = true; } /****************************************************************************/ void RF24::disableDynamicPayloads(void) { - // Disables dynamic payload throughout the system. Also disables Ack Payloads - - //toggle_features(); - write_register(FEATURE, 0); + // Disables dynamic payload throughout the system. Also disables Ack Payloads + //toggle_features(); + write_register(FEATURE, 0); - IF_SERIAL_DEBUG(printf("FEATURE=%i\r\n",read_register(FEATURE))); + IF_SERIAL_DEBUG(printf("FEATURE=%i\r\n", read_register(FEATURE))); - // Disable dynamic payload on all pipes - // - // Not sure the use case of only having dynamic payload on certain - // pipes, so the library does not support it. - write_register(DYNPD, 0); + // Disable dynamic payload on all pipes + // + // Not sure the use case of only having dynamic payload on certain + // pipes, so the library does not support it. + write_register(DYNPD, 0); - dynamic_payloads_enabled = false; + dynamic_payloads_enabled = false; } /****************************************************************************/ void RF24::enableAckPayload(void) { - // - // enable ack payload and dynamic payload features - // + // + // enable ack payload and dynamic payload features + // //toggle_features(); - write_register(FEATURE,read_register(FEATURE) | _BV(EN_ACK_PAY) | _BV(EN_DPL) ); + write_register(FEATURE, read_register(FEATURE) | _BV(EN_ACK_PAY) | _BV(EN_DPL)); - IF_SERIAL_DEBUG(printf("FEATURE=%i\r\n",read_register(FEATURE))); + IF_SERIAL_DEBUG(printf("FEATURE=%i\r\n", read_register(FEATURE))); - // - // Enable dynamic payload on pipes 0 & 1 - // - - write_register(DYNPD,read_register(DYNPD) | _BV(DPL_P1) | _BV(DPL_P0)); - dynamic_payloads_enabled = true; + // + // Enable dynamic payload on pipes 0 & 1 + // + write_register(DYNPD, read_register(DYNPD) | _BV(DPL_P1) | _BV(DPL_P0)); + dynamic_payloads_enabled = true; } /****************************************************************************/ -void RF24::enableDynamicAck(void){ - // - // enable dynamic ack features - // +void RF24::enableDynamicAck(void) +{ + // + // enable dynamic ack features + // //toggle_features(); - write_register(FEATURE,read_register(FEATURE) | _BV(EN_DYN_ACK) ); + write_register(FEATURE, read_register(FEATURE) | _BV(EN_DYN_ACK)); - IF_SERIAL_DEBUG(printf("FEATURE=%i\r\n",read_register(FEATURE))); + IF_SERIAL_DEBUG(printf("FEATURE=%i\r\n", read_register(FEATURE))); } @@ -1348,30 +1367,30 @@ void RF24::enableDynamicAck(void){ void RF24::writeAckPayload(uint8_t pipe, const void* buf, uint8_t len) { - const uint8_t* current = reinterpret_cast(buf); + const uint8_t* current = reinterpret_cast(buf); - uint8_t data_len = rf24_min(len,32); + uint8_t data_len = rf24_min(len, 32); - #if defined (RF24_LINUX) + #if defined(RF24_LINUX) beginTransaction(); uint8_t * ptx = spi_txbuff; uint8_t size = data_len + 1 ; // Add register value to transmit buffer - *ptx++ = W_ACK_PAYLOAD | ( pipe & 0x07 ); + *ptx++ = W_ACK_PAYLOAD | ( pipe & 0x07 ); while ( data_len-- ){ *ptx++ = *current++; } - + _SPI.transfern( (char *) spi_txbuff, size); - endTransaction(); - #else - beginTransaction(); - _SPI.transfer(W_ACK_PAYLOAD | ( pipe & 0x07 ) ); + endTransaction(); + #else + beginTransaction(); + _SPI.transfer(W_ACK_PAYLOAD | (pipe & 0x07)); + + while (data_len --) + _SPI.transfer(*current ++); + endTransaction(); - while ( data_len-- ) - _SPI.transfer(*current++); - endTransaction(); - - #endif + #endif } @@ -1379,57 +1398,54 @@ void RF24::writeAckPayload(uint8_t pipe, const void* buf, uint8_t len) bool RF24::isAckPayloadAvailable(void) { - return ! (read_register(FIFO_STATUS) & _BV(RX_EMPTY)); + return ! (read_register(FIFO_STATUS) & _BV(RX_EMPTY)); } /****************************************************************************/ bool RF24::isPVariant(void) { - return p_variant ; + return p_variant; } /****************************************************************************/ void RF24::setAutoAck(bool enable) { - if ( enable ) - write_register(EN_AA, 0x3F); - else - write_register(EN_AA, 0); + if (enable) { + write_register(EN_AA, 0x3F); + } else { + write_register(EN_AA, 0); + } } /****************************************************************************/ -void RF24::setAutoAck( uint8_t pipe, bool enable ) +void RF24::setAutoAck(uint8_t pipe, bool enable) { - if ( pipe <= 6 ) - { - uint8_t en_aa = read_register( EN_AA ) ; - if( enable ) - { - en_aa |= _BV(pipe) ; - } - else - { - en_aa &= ~_BV(pipe) ; + if (pipe <= 6) { + uint8_t en_aa = read_register(EN_AA); + if (enable) { + en_aa |= _BV(pipe); + } else { + en_aa &= ~ _BV(pipe); + } + write_register(EN_AA, en_aa); } - write_register( EN_AA, en_aa ) ; - } } /****************************************************************************/ bool RF24::testCarrier(void) { - return ( read_register(CD) & 1 ); + return (read_register(CD) & 1); } /****************************************************************************/ bool RF24::testRPD(void) { - return ( read_register(RPD) & 1 ) ; + return (read_register(RPD) & 1); } /****************************************************************************/ @@ -1437,16 +1453,15 @@ bool RF24::testRPD(void) void RF24::setPALevel(uint8_t level) { - uint8_t setup = read_register(RF_SETUP) & 0xF8; - - if(level > 3){ // If invalid level, go to max PA - level = (RF24_PA_MAX << 1) + 1; // +1 to support the SI24R1 chip extra bit - }else{ - level = (level << 1) + 1; // Else set level as requested - } + uint8_t setup = read_register(RF_SETUP) & 0xF8; + if (level > 3) { // If invalid level, go to max PA + level = (RF24_PA_MAX << 1) + 1; // +1 to support the SI24R1 chip extra bit + } else { + level = (level << 1) + 1; // Else set level as requested + } - write_register( RF_SETUP, setup |= level ) ; // Write it to the chip + write_register(RF_SETUP, setup |= level); // Write it to the chip } /****************************************************************************/ @@ -1454,141 +1469,126 @@ void RF24::setPALevel(uint8_t level) uint8_t RF24::getPALevel(void) { - return (read_register(RF_SETUP) & (_BV(RF_PWR_LOW) | _BV(RF_PWR_HIGH))) >> 1 ; + return (read_register(RF_SETUP) & (_BV(RF_PWR_LOW) | _BV(RF_PWR_HIGH))) >> 1; } /****************************************************************************/ bool RF24::setDataRate(rf24_datarate_e speed) { - bool result = false; - uint8_t setup = read_register(RF_SETUP) ; + bool result = false; + uint8_t setup = read_register(RF_SETUP); + + // HIGH and LOW '00' is 1Mbs - our default + setup &= ~ (_BV(RF_DR_LOW) | _BV(RF_DR_HIGH)); - // HIGH and LOW '00' is 1Mbs - our default - setup &= ~(_BV(RF_DR_LOW) | _BV(RF_DR_HIGH)) ; - - #if !defined(F_CPU) || F_CPU > 20000000 - txDelay=250; - #else //16Mhz Arduino + #if !defined(F_CPU) || F_CPU > 20000000 + txDelay = 250; + #else //16Mhz Arduino txDelay=85; - #endif - if( speed == RF24_250KBPS ) - { - // Must set the RF_DR_LOW to 1; RF_DR_HIGH (used to be RF_DR) is already 0 - // Making it '10'. - setup |= _BV( RF_DR_LOW ) ; - #if !defined(F_CPU) || F_CPU > 20000000 - txDelay=450; - #else //16Mhz Arduino - txDelay=155; - #endif - } - else - { - // Set 2Mbs, RF_DR (RF_DR_HIGH) is set 1 - // Making it '01' - if ( speed == RF24_2MBPS ) - { - setup |= _BV(RF_DR_HIGH); - #if !defined(F_CPU) || F_CPU > 20000000 - txDelay=190; - #else //16Mhz Arduino - txDelay=65; - #endif + #endif + if (speed == RF24_250KBPS) { + // Must set the RF_DR_LOW to 1; RF_DR_HIGH (used to be RF_DR) is already 0 + // Making it '10'. + setup |= _BV(RF_DR_LOW); + #if !defined(F_CPU) || F_CPU > 20000000 + txDelay = 450; + #else //16Mhz Arduino + txDelay=155; + #endif + } else { + // Set 2Mbs, RF_DR (RF_DR_HIGH) is set 1 + // Making it '01' + if (speed == RF24_2MBPS) { + setup |= _BV(RF_DR_HIGH); + #if !defined(F_CPU) || F_CPU > 20000000 + txDelay = 190; + #else //16Mhz Arduino + txDelay=65; + #endif + } } - } - write_register(RF_SETUP,setup); + write_register(RF_SETUP, setup); - // Verify our result - if ( read_register(RF_SETUP) == setup ) - { - result = true; - } - return result; + // Verify our result + if (read_register(RF_SETUP) == setup) { + result = true; + } + return result; } /****************************************************************************/ -rf24_datarate_e RF24::getDataRate( void ) +rf24_datarate_e RF24::getDataRate(void) { - rf24_datarate_e result ; - uint8_t dr = read_register(RF_SETUP) & (_BV(RF_DR_LOW) | _BV(RF_DR_HIGH)); - - // switch uses RAM (evil!) - // Order matters in our case below - if ( dr == _BV(RF_DR_LOW) ) - { - // '10' = 250KBPS - result = RF24_250KBPS ; - } - else if ( dr == _BV(RF_DR_HIGH) ) - { - // '01' = 2MBPS - result = RF24_2MBPS ; - } - else - { - // '00' = 1MBPS - result = RF24_1MBPS ; - } - return result ; + rf24_datarate_e result; + uint8_t dr = read_register(RF_SETUP) & (_BV(RF_DR_LOW) | _BV(RF_DR_HIGH)); + + // switch uses RAM (evil!) + // Order matters in our case below + if (dr == _BV(RF_DR_LOW)) { + // '10' = 250KBPS + result = RF24_250KBPS; + } else if (dr == _BV(RF_DR_HIGH)) { + // '01' = 2MBPS + result = RF24_2MBPS; + } else { + // '00' = 1MBPS + result = RF24_1MBPS; + } + return result; } /****************************************************************************/ void RF24::setCRCLength(rf24_crclength_e length) { - uint8_t config = read_register(NRF_CONFIG) & ~( _BV(CRCO) | _BV(EN_CRC)) ; - - // switch uses RAM (evil!) - if ( length == RF24_CRC_DISABLED ) - { - // Do nothing, we turned it off above. - } - else if ( length == RF24_CRC_8 ) - { - config |= _BV(EN_CRC); - } - else - { - config |= _BV(EN_CRC); - config |= _BV( CRCO ); - } - write_register( NRF_CONFIG, config ) ; + uint8_t config = read_register(NRF_CONFIG) & ~ (_BV(CRCO) | _BV(EN_CRC)); + + // switch uses RAM (evil!) + if (length == RF24_CRC_DISABLED) { + // Do nothing, we turned it off above. + } else if (length == RF24_CRC_8) { + config |= _BV(EN_CRC); + } else { + config |= _BV(EN_CRC); + config |= _BV(CRCO); + } + write_register(NRF_CONFIG, config); } /****************************************************************************/ rf24_crclength_e RF24::getCRCLength(void) { - rf24_crclength_e result = RF24_CRC_DISABLED; - - uint8_t config = read_register(NRF_CONFIG) & ( _BV(CRCO) | _BV(EN_CRC)) ; - uint8_t AA = read_register(EN_AA); - - if ( config & _BV(EN_CRC ) || AA) - { - if ( config & _BV(CRCO) ) - result = RF24_CRC_16; - else - result = RF24_CRC_8; - } + rf24_crclength_e result = RF24_CRC_DISABLED; + + uint8_t config = read_register(NRF_CONFIG) & (_BV(CRCO) | _BV(EN_CRC)); + uint8_t AA = read_register(EN_AA); + + if (config & _BV(EN_CRC) || AA) { + if (config & _BV(CRCO)) { + result = RF24_CRC_16; + } else { + result = RF24_CRC_8; + } + } - return result; + return result; } /****************************************************************************/ -void RF24::disableCRC( void ) +void RF24::disableCRC(void) { - uint8_t disable = read_register(NRF_CONFIG) & ~_BV(EN_CRC) ; - write_register( NRF_CONFIG, disable ) ; + uint8_t disable = read_register(NRF_CONFIG) & ~ _BV(EN_CRC); + write_register(NRF_CONFIG, disable); } /****************************************************************************/ void RF24::setRetries(uint8_t delay, uint8_t count) { - write_register(SETUP_RETR,(delay&0xf)< + #include #endif /** @@ -28,88 +28,101 @@ * * For use with setPALevel() */ -typedef enum { RF24_PA_MIN = 0,RF24_PA_LOW, RF24_PA_HIGH, RF24_PA_MAX, RF24_PA_ERROR } rf24_pa_dbm_e ; +typedef enum { + RF24_PA_MIN = 0, + RF24_PA_LOW, + RF24_PA_HIGH, + RF24_PA_MAX, + RF24_PA_ERROR +} rf24_pa_dbm_e; /** * Data rate. How fast data moves through the air. * * For use with setDataRate() */ -typedef enum { RF24_1MBPS = 0, RF24_2MBPS, RF24_250KBPS } rf24_datarate_e; +typedef enum { + RF24_1MBPS = 0, + RF24_2MBPS, + RF24_250KBPS +} rf24_datarate_e; /** * CRC Length. How big (if any) of a CRC is included. * * For use with setCRCLength() */ -typedef enum { RF24_CRC_DISABLED = 0, RF24_CRC_8, RF24_CRC_16 } rf24_crclength_e; +typedef enum { + RF24_CRC_DISABLED = 0, + RF24_CRC_8, + RF24_CRC_16 +} rf24_crclength_e; /** * Driver for nRF24L01(+) 2.4GHz Wireless Transceiver */ -class RF24 -{ +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 -#if defined (MRAA) - GPIO gpio; -#endif + #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 + #if defined (MRAA) + GPIO gpio; + #endif + + uint16_t ce_pin; /**< "Chip Enable" pin, activates the RX or TX role */ + uint16_t csn_pin; /**< SPI Chip select */ + uint16_t spi_speed; /**< SPI Bus Speed */ + #if defined (RF24_LINUX) || defined (XMEGA_D3) + 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 + bool p_variant; /* False for RF24L01 and true for RF24L01P */ + uint8_t payload_size; /**< Fixed size of payloads */ + bool dynamic_payloads_enabled; /**< Whether dynamic payloads are enabled. */ + uint8_t pipe0_reading_address[5]; /**< Last address set on pipe 0 for reading. */ + uint8_t addr_width; /**< The address width to use - 3,4 or 5 bytes. */ - uint16_t ce_pin; /**< "Chip Enable" pin, activates the RX or TX role */ - uint16_t csn_pin; /**< SPI Chip select */ - uint16_t spi_speed; /**< SPI Bus Speed */ -#if defined (RF24_LINUX) || defined (XMEGA_D3) - 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 - bool p_variant; /* False for RF24L01 and true for RF24L01P */ - uint8_t payload_size; /**< Fixed size of payloads */ - bool dynamic_payloads_enabled; /**< Whether dynamic payloads are enabled. */ - uint8_t pipe0_reading_address[5]; /**< Last address set on pipe 0 for reading. */ - uint8_t addr_width; /**< The address width to use - 3,4 or 5 bytes. */ - protected: - /** - * SPI transactions - * - * Common code for SPI transactions including CSN toggle - * - */ - inline void beginTransaction(); + /** + * SPI transactions + * + * Common code for SPI transactions including CSN toggle + * + */ + inline void beginTransaction(); - inline void endTransaction(); + inline void endTransaction(); public: - /** - * @name Primary public interface - * - * These are the main methods you need to operate the chip - */ - /**@{*/ + /** + * @name Primary public interface + * + * These are the main methods you need to operate the chip + */ + /**@{*/ + + /** + * Arduino Constructor + * + * Creates a new instance of this driver. Before using, you create an instance + * and send in the unique pins that this chip is connected to. + * + * @param _cepin The pin attached to Chip Enable on the RF module + * @param _cspin The pin attached to Chip Select + */ + RF24(uint16_t _cepin, uint16_t _cspin); + //#if defined (RF24_LINUX) - /** - * Arduino Constructor - * - * Creates a new instance of this driver. Before using, you create an instance - * and send in the unique pins that this chip is connected to. - * - * @param _cepin The pin attached to Chip Enable on the RF module - * @param _cspin The pin attached to Chip Select - */ - RF24(uint16_t _cepin, uint16_t _cspin); - //#if defined (RF24_LINUX) - /** * Optional Linux Constructor * @@ -120,1052 +133,1060 @@ class RF24 * @param _cspin The pin attached to Chip Select * @param spispeed For RPi, the SPI speed in MHZ ie: BCM2835_SPI_SPEED_8MHZ */ - - RF24(uint16_t _cepin, uint16_t _cspin, uint32_t spispeed ); - //#endif - - #if defined (RF24_LINUX) - virtual ~RF24() {}; - #endif - - /** - * Begin operation of the chip - * - * Call this in setup(), before calling any other methods. - * @code radio.begin() @endcode - */ - bool begin(void); - /** - * Checks if the chip is connected to the SPI bus - */ - bool isChipConnected(); + RF24(uint16_t _cepin, uint16_t _cspin, uint32_t spispeed); + //#endif - /** - * Start listening on the pipes opened for reading. - * - * 1. Be sure to call openReadingPipe() first. - * 2. Do not call write() while in this mode, without first calling stopListening(). - * 3. Call available() to check for incoming traffic, and read() to get it. - * - * @code - * Open reading pipe 1 using address CCCECCCECC - * - * byte address[] = { 0xCC,0xCE,0xCC,0xCE,0xCC }; - * radio.openReadingPipe(1,address); - * radio.startListening(); - * @endcode - */ - void startListening(void); + #if defined (RF24_LINUX) + virtual ~RF24() {}; + #endif - /** - * Stop listening for incoming messages, and switch to transmit mode. - * - * Do this before calling write(). - * @code - * radio.stopListening(); - * radio.write(&data,sizeof(data)); - * @endcode - */ - void stopListening(void); - - /** - * Check whether there are bytes available to be read - * @code - * if(radio.available()){ - * radio.read(&data,sizeof(data)); - * } - * @endcode - * @return True if there is a payload available, false if none is - */ - bool available(void); + /** + * Begin operation of the chip + * + * Call this in setup(), before calling any other methods. + * @code radio.begin() @endcode + */ + bool begin(void); - /** - * Read the available payload - * - * The size of data read is the fixed payload size, see getPayloadSize() - * - * @note I specifically chose 'void*' as a data type to make it easier - * for beginners to use. No casting needed. - * - * @note No longer boolean. Use available to determine if packets are - * available. Interrupt flags are now cleared during reads instead of - * when calling available(). - * - * @param buf Pointer to a buffer where the data should be written - * @param len Maximum number of bytes to read into the buffer - * - * @code - * if(radio.available()){ - * radio.read(&data,sizeof(data)); - * } - * @endcode - * @return No return value. Use available(). - */ - void read( void* buf, uint8_t len ); + /** + * Checks if the chip is connected to the SPI bus + */ + bool isChipConnected(); - /** - * Be sure to call openWritingPipe() first to set the destination - * of where to write to. - * - * This blocks until the message is successfully acknowledged by - * the receiver or the timeout/retransmit maxima are reached. In - * the current configuration, the max delay here is 60-70ms. - * - * The maximum size of data written is the fixed payload size, see - * getPayloadSize(). However, you can write less, and the remainder - * will just be filled with zeroes. - * - * TX/RX/RT interrupt flags will be cleared every time write is called - * - * @param buf Pointer to the data to be sent - * @param len Number of bytes to be sent - * - * @code - * radio.stopListening(); - * radio.write(&data,sizeof(data)); - * @endcode - * @return True if the payload was delivered successfully and an ACK was received, or upon successfull transmission if auto-ack is disabled. - */ - bool write( const void* buf, uint8_t len ); + /** + * Start listening on the pipes opened for reading. + * + * 1. Be sure to call openReadingPipe() first. + * 2. Do not call write() while in this mode, without first calling stopListening(). + * 3. Call available() to check for incoming traffic, and read() to get it. + * + * @code + * Open reading pipe 1 using address CCCECCCECC + * + * byte address[] = { 0xCC,0xCE,0xCC,0xCE,0xCC }; + * radio.openReadingPipe(1,address); + * radio.startListening(); + * @endcode + */ + void startListening(void); - /** - * New: Open a pipe for writing via byte array. Old addressing format retained - * for compatibility. - * - * Only one writing pipe can be open at once, but you can change the address - * you'll write to. Call stopListening() first. - * - * Addresses are assigned via a byte array, default is 5 byte address length -s * - * @code - * uint8_t addresses[][6] = {"1Node","2Node"}; - * radio.openWritingPipe(addresses[0]); - * @endcode - * @code - * uint8_t address[] = { 0xCC,0xCE,0xCC,0xCE,0xCC }; - * radio.openWritingPipe(address); - * address[0] = 0x33; - * radio.openReadingPipe(1,address); - * @endcode - * @see setAddressWidth - * - * @param address The address of the pipe to open. Coordinate these pipe - * addresses amongst nodes on the network. - */ + /** + * Stop listening for incoming messages, and switch to transmit mode. + * + * Do this before calling write(). + * @code + * radio.stopListening(); + * radio.write(&data,sizeof(data)); + * @endcode + */ + void stopListening(void); - void openWritingPipe(const uint8_t *address); + /** + * Check whether there are bytes available to be read + * @code + * if(radio.available()){ + * radio.read(&data,sizeof(data)); + * } + * @endcode + * @return True if there is a payload available, false if none is + */ + bool available(void); - /** - * Open a pipe for reading - * - * Up to 6 pipes can be open for reading at once. Open all the required - * reading pipes, and then call startListening(). - * - * @see openWritingPipe - * @see setAddressWidth - * - * @note Pipes 0 and 1 will store a full 5-byte address. Pipes 2-5 will technically - * only store a single byte, borrowing up to 4 additional bytes from pipe #1 per the - * assigned address width. - * @warning Pipes 1-5 should share the same address, except the first byte. - * Only the first byte in the array should be unique, e.g. - * @code - * uint8_t addresses[][6] = {"1Node","2Node"}; - * openReadingPipe(1,addresses[0]); - * openReadingPipe(2,addresses[1]); - * @endcode - * - * @warning Pipe 0 is also used by the writing pipe. So if you open - * pipe 0 for reading, and then startListening(), it will overwrite the - * writing pipe. Ergo, do an openWritingPipe() again before write(). - * - * @param number Which pipe# to open, 0-5. - * @param address The 24, 32 or 40 bit address of the pipe to open. - */ + /** + * Read the available payload + * + * The size of data read is the fixed payload size, see getPayloadSize() + * + * @note I specifically chose 'void*' as a data type to make it easier + * for beginners to use. No casting needed. + * + * @note No longer boolean. Use available to determine if packets are + * available. Interrupt flags are now cleared during reads instead of + * when calling available(). + * + * @param buf Pointer to a buffer where the data should be written + * @param len Maximum number of bytes to read into the buffer + * + * @code + * if(radio.available()){ + * radio.read(&data,sizeof(data)); + * } + * @endcode + * @return No return value. Use available(). + */ + void read(void* buf, uint8_t len); - void openReadingPipe(uint8_t number, const uint8_t *address); + /** + * Be sure to call openWritingPipe() first to set the destination + * of where to write to. + * + * This blocks until the message is successfully acknowledged by + * the receiver or the timeout/retransmit maxima are reached. In + * the current configuration, the max delay here is 60-70ms. + * + * The maximum size of data written is the fixed payload size, see + * getPayloadSize(). However, you can write less, and the remainder + * will just be filled with zeroes. + * + * TX/RX/RT interrupt flags will be cleared every time write is called + * + * @param buf Pointer to the data to be sent + * @param len Number of bytes to be sent + * + * @code + * radio.stopListening(); + * radio.write(&data,sizeof(data)); + * @endcode + * @return True if the payload was delivered successfully and an ACK was received, or upon successfull transmission if auto-ack is disabled. + */ + bool write(const void* buf, uint8_t len); - /**@}*/ - /** - * @name Advanced Operation - * - * Methods you can use to drive the chip in more advanced ways - */ - /**@{*/ + /** + * New: Open a pipe for writing via byte array. Old addressing format retained + * for compatibility. + * + * Only one writing pipe can be open at once, but you can change the address + * you'll write to. Call stopListening() first. + * + * Addresses are assigned via a byte array, default is 5 byte address length + s * + * @code + * uint8_t addresses[][6] = {"1Node","2Node"}; + * radio.openWritingPipe(addresses[0]); + * @endcode + * @code + * uint8_t address[] = { 0xCC,0xCE,0xCC,0xCE,0xCC }; + * radio.openWritingPipe(address); + * address[0] = 0x33; + * radio.openReadingPipe(1,address); + * @endcode + * @see setAddressWidth + * + * @param address The address of the pipe to open. Coordinate these pipe + * addresses amongst nodes on the network. + */ + + void openWritingPipe(const uint8_t* address); - /** - * Print a giant block of debugging information to stdout - * - * @warning Does nothing if stdout is not defined. See fdevopen in stdio.h - * The printf.h file is included with the library for Arduino. - * @code - * #include - * setup(){ - * Serial.begin(115200); - * printf_begin(); - * ... - * } - * @endcode - */ - void printDetails(void); + /** + * Open a pipe for reading + * + * Up to 6 pipes can be open for reading at once. Open all the required + * reading pipes, and then call startListening(). + * + * @see openWritingPipe + * @see setAddressWidth + * + * @note Pipes 0 and 1 will store a full 5-byte address. Pipes 2-5 will technically + * only store a single byte, borrowing up to 4 additional bytes from pipe #1 per the + * assigned address width. + * @warning Pipes 1-5 should share the same address, except the first byte. + * Only the first byte in the array should be unique, e.g. + * @code + * uint8_t addresses[][6] = {"1Node","2Node"}; + * openReadingPipe(1,addresses[0]); + * openReadingPipe(2,addresses[1]); + * @endcode + * + * @warning Pipe 0 is also used by the writing pipe. So if you open + * pipe 0 for reading, and then startListening(), it will overwrite the + * writing pipe. Ergo, do an openWritingPipe() again before write(). + * + * @param number Which pipe# to open, 0-5. + * @param address The 24, 32 or 40 bit address of the pipe to open. + */ + + void openReadingPipe(uint8_t number, const uint8_t* address); + + /**@}*/ + /** + * @name Advanced Operation + * + * Methods you can use to drive the chip in more advanced ways + */ + /**@{*/ - /** - * Test whether there are bytes available to be read in the - * FIFO buffers. - * - * @param[out] pipe_num Which pipe has the payload available - * - * @code - * uint8_t pipeNum; - * if(radio.available(&pipeNum)){ - * radio.read(&data,sizeof(data)); - * Serial.print("Got data on pipe"); - * Serial.println(pipeNum); - * } - * @endcode - * @return True if there is a payload available, false if none is - */ - bool available(uint8_t* pipe_num); + /** + * Print a giant block of debugging information to stdout + * + * @warning Does nothing if stdout is not defined. See fdevopen in stdio.h + * The printf.h file is included with the library for Arduino. + * @code + * #include + * setup(){ + * Serial.begin(115200); + * printf_begin(); + * ... + * } + * @endcode + */ + void printDetails(void); - /** - * Check if the radio needs to be read. Can be used to prevent data loss - * @return True if all three 32-byte radio buffers are full - */ - bool rxFifoFull(); + /** + * Test whether there are bytes available to be read in the + * FIFO buffers. + * + * @param[out] pipe_num Which pipe has the payload available + * + * @code + * uint8_t pipeNum; + * if(radio.available(&pipeNum)){ + * radio.read(&data,sizeof(data)); + * Serial.print("Got data on pipe"); + * Serial.println(pipeNum); + * } + * @endcode + * @return True if there is a payload available, false if none is + */ + bool available(uint8_t* pipe_num); - /** - * Enter low-power mode - * - * To return to normal power mode, call powerUp(). - * - * @note After calling startListening(), a basic radio will consume about 13.5mA - * at max PA level. - * During active transmission, the radio will consume about 11.5mA, but this will - * be reduced to 26uA (.026mA) between sending. - * In full powerDown mode, the radio will consume approximately 900nA (.0009mA) - * - * @code - * radio.powerDown(); - * avr_enter_sleep_mode(); // Custom function to sleep the device - * radio.powerUp(); - * @endcode - */ - void powerDown(void); + /** + * Check if the radio needs to be read. Can be used to prevent data loss + * @return True if all three 32-byte radio buffers are full + */ + bool rxFifoFull(); - /** - * Leave low-power mode - required for normal radio operation after calling powerDown() - * - * To return to low power mode, call powerDown(). - * @note This will take up to 5ms for maximum compatibility - */ - void powerUp(void) ; + /** + * Enter low-power mode + * + * To return to normal power mode, call powerUp(). + * + * @note After calling startListening(), a basic radio will consume about 13.5mA + * at max PA level. + * During active transmission, the radio will consume about 11.5mA, but this will + * be reduced to 26uA (.026mA) between sending. + * In full powerDown mode, the radio will consume approximately 900nA (.0009mA) + * + * @code + * radio.powerDown(); + * avr_enter_sleep_mode(); // Custom function to sleep the device + * radio.powerUp(); + * @endcode + */ + void powerDown(void); - /** - * Write for single NOACK writes. Optionally disables acknowledgements/autoretries for a single write. - * - * @note enableDynamicAck() must be called to enable this feature - * - * Can be used with enableAckPayload() to request a response - * @see enableDynamicAck() - * @see setAutoAck() - * @see write() - * - * @param buf Pointer to the data to be sent - * @param len Number of bytes to be sent - * @param multicast Request ACK (0), NOACK (1) - */ - bool write( const void* buf, uint8_t len, const bool multicast ); - - /** - * This will not block until the 3 FIFO buffers are filled with data. - * Once the FIFOs are full, writeFast will simply wait for success or - * timeout, and return 1 or 0 respectively. From a user perspective, just - * keep trying to send the same data. The library will keep auto retrying - * the current payload using the built in functionality. - * @warning It is important to never keep the nRF24L01 in TX mode and FIFO full for more than 4ms at a time. If the auto - * retransmit is enabled, the nRF24L01 is never in TX mode long enough to disobey this rule. Allow the FIFO - * to clear by issuing txStandBy() or ensure appropriate time between transmissions. - * - * @code - * Example (Partial blocking): - * - * radio.writeFast(&buf,32); // Writes 1 payload to the buffers - * txStandBy(); // Returns 0 if failed. 1 if success. Blocks only until MAX_RT timeout or success. Data flushed on fail. - * - * radio.writeFast(&buf,32); // Writes 1 payload to the buffers - * txStandBy(1000); // Using extended timeouts, returns 1 if success. Retries failed payloads for 1 seconds before returning 0. - * @endcode - * - * @see txStandBy() - * @see write() - * @see writeBlocking() - * - * @param buf Pointer to the data to be sent - * @param len Number of bytes to be sent - * @return True if the payload was delivered successfully false if not - */ - bool writeFast( const void* buf, uint8_t len ); + /** + * Leave low-power mode - required for normal radio operation after calling powerDown() + * + * To return to low power mode, call powerDown(). + * @note This will take up to 5ms for maximum compatibility + */ + void powerUp(void); - /** - * WriteFast for single NOACK writes. Disables acknowledgements/autoretries for a single write. - * - * @note enableDynamicAck() must be called to enable this feature - * @see enableDynamicAck() - * @see setAutoAck() - * - * @param buf Pointer to the data to be sent - * @param len Number of bytes to be sent - * @param multicast Request ACK (0) or NOACK (1) - */ - bool writeFast( const void* buf, uint8_t len, const bool multicast ); - - /** - * This function extends the auto-retry mechanism to any specified duration. - * It will not block until the 3 FIFO buffers are filled with data. - * If so the library will auto retry until a new payload is written - * or the user specified timeout period is reached. - * @warning It is important to never keep the nRF24L01 in TX mode and FIFO full for more than 4ms at a time. If the auto - * retransmit is enabled, the nRF24L01 is never in TX mode long enough to disobey this rule. Allow the FIFO - * to clear by issuing txStandBy() or ensure appropriate time between transmissions. - * - * @code - * Example (Full blocking): - * - * radio.writeBlocking(&buf,32,1000); //Wait up to 1 second to write 1 payload to the buffers - * txStandBy(1000); //Wait up to 1 second for the payload to send. Return 1 if ok, 0 if failed. - * //Blocks only until user timeout or success. Data flushed on fail. - * @endcode - * @note If used from within an interrupt, the interrupt should be disabled until completion, and sei(); called to enable millis(). - * @see txStandBy() - * @see write() - * @see writeFast() - * - * @param buf Pointer to the data to be sent - * @param len Number of bytes to be sent - * @param timeout User defined timeout in milliseconds. - * @return True if the payload was loaded into the buffer successfully false if not - */ - bool writeBlocking( const void* buf, uint8_t len, uint32_t timeout ); + /** + * Write for single NOACK writes. Optionally disables acknowledgements/autoretries for a single write. + * + * @note enableDynamicAck() must be called to enable this feature + * + * Can be used with enableAckPayload() to request a response + * @see enableDynamicAck() + * @see setAutoAck() + * @see write() + * + * @param buf Pointer to the data to be sent + * @param len Number of bytes to be sent + * @param multicast Request ACK (0), NOACK (1) + */ + bool write(const void* buf, uint8_t len, const bool multicast); - /** - * This function should be called as soon as transmission is finished to - * drop the radio back to STANDBY-I mode. If not issued, the radio will - * remain in STANDBY-II mode which, per the data sheet, is not a recommended - * operating mode. - * - * @note When transmitting data in rapid succession, it is still recommended by - * the manufacturer to drop the radio out of TX or STANDBY-II mode if there is - * time enough between sends for the FIFOs to empty. This is not required if auto-ack - * is enabled. - * - * Relies on built-in auto retry functionality. - * - * @code - * Example (Partial blocking): - * - * radio.writeFast(&buf,32); - * radio.writeFast(&buf,32); - * radio.writeFast(&buf,32); //Fills the FIFO buffers up - * bool ok = txStandBy(); //Returns 0 if failed. 1 if success. - * //Blocks only until MAX_RT timeout or success. Data flushed on fail. - * @endcode - * @see txStandBy(unsigned long timeout) - * @return True if transmission is successful - * - */ - bool txStandBy(); + /** + * This will not block until the 3 FIFO buffers are filled with data. + * Once the FIFOs are full, writeFast will simply wait for success or + * timeout, and return 1 or 0 respectively. From a user perspective, just + * keep trying to send the same data. The library will keep auto retrying + * the current payload using the built in functionality. + * @warning It is important to never keep the nRF24L01 in TX mode and FIFO full for more than 4ms at a time. If the auto + * retransmit is enabled, the nRF24L01 is never in TX mode long enough to disobey this rule. Allow the FIFO + * to clear by issuing txStandBy() or ensure appropriate time between transmissions. + * + * @code + * Example (Partial blocking): + * + * radio.writeFast(&buf,32); // Writes 1 payload to the buffers + * txStandBy(); // Returns 0 if failed. 1 if success. Blocks only until MAX_RT timeout or success. Data flushed on fail. + * + * radio.writeFast(&buf,32); // Writes 1 payload to the buffers + * txStandBy(1000); // Using extended timeouts, returns 1 if success. Retries failed payloads for 1 seconds before returning 0. + * @endcode + * + * @see txStandBy() + * @see write() + * @see writeBlocking() + * + * @param buf Pointer to the data to be sent + * @param len Number of bytes to be sent + * @return True if the payload was delivered successfully false if not + */ + bool writeFast(const void* buf, uint8_t len); - /** - * This function allows extended blocking and auto-retries per a user defined timeout - * @code - * Fully Blocking Example: - * - * radio.writeFast(&buf,32); - * radio.writeFast(&buf,32); - * radio.writeFast(&buf,32); //Fills the FIFO buffers up - * bool ok = txStandBy(1000); //Returns 0 if failed after 1 second of retries. 1 if success. - * //Blocks only until user defined timeout or success. Data flushed on fail. - * @endcode - * @note If used from within an interrupt, the interrupt should be disabled until completion, and sei(); called to enable millis(). - * @param timeout Number of milliseconds to retry failed payloads - * @return True if transmission is successful - * - */ - bool txStandBy(uint32_t timeout, bool startTx = 0); + /** + * WriteFast for single NOACK writes. Disables acknowledgements/autoretries for a single write. + * + * @note enableDynamicAck() must be called to enable this feature + * @see enableDynamicAck() + * @see setAutoAck() + * + * @param buf Pointer to the data to be sent + * @param len Number of bytes to be sent + * @param multicast Request ACK (0) or NOACK (1) + */ + bool writeFast(const void* buf, uint8_t len, const bool multicast); - /** - * Write an ack payload for the specified pipe - * - * The next time a message is received on @p pipe, the data in @p buf will - * be sent back in the acknowledgement. - * @see enableAckPayload() - * @see enableDynamicPayloads() - * @warning Only three of these can be pending at any time as there are only 3 FIFO buffers.
Dynamic payloads must be enabled. - * @note Ack payloads are handled automatically by the radio chip when a payload is received. Users should generally - * write an ack payload as soon as startListening() is called, so one is available when a regular payload is received. - * @note Ack payloads are dynamic payloads. This only works on pipes 0&1 by default. Call - * enableDynamicPayloads() to enable on all pipes. - * - * @param pipe Which pipe# (typically 1-5) will get this response. - * @param buf Pointer to data that is sent - * @param len Length of the data to send, up to 32 bytes max. Not affected - * by the static payload set by setPayloadSize(). - */ - void writeAckPayload(uint8_t pipe, const void* buf, uint8_t len); + /** + * This function extends the auto-retry mechanism to any specified duration. + * It will not block until the 3 FIFO buffers are filled with data. + * If so the library will auto retry until a new payload is written + * or the user specified timeout period is reached. + * @warning It is important to never keep the nRF24L01 in TX mode and FIFO full for more than 4ms at a time. If the auto + * retransmit is enabled, the nRF24L01 is never in TX mode long enough to disobey this rule. Allow the FIFO + * to clear by issuing txStandBy() or ensure appropriate time between transmissions. + * + * @code + * Example (Full blocking): + * + * radio.writeBlocking(&buf,32,1000); //Wait up to 1 second to write 1 payload to the buffers + * txStandBy(1000); //Wait up to 1 second for the payload to send. Return 1 if ok, 0 if failed. + * //Blocks only until user timeout or success. Data flushed on fail. + * @endcode + * @note If used from within an interrupt, the interrupt should be disabled until completion, and sei(); called to enable millis(). + * @see txStandBy() + * @see write() + * @see writeFast() + * + * @param buf Pointer to the data to be sent + * @param len Number of bytes to be sent + * @param timeout User defined timeout in milliseconds. + * @return True if the payload was loaded into the buffer successfully false if not + */ + bool writeBlocking(const void* buf, uint8_t len, uint32_t timeout); - /** - * Determine if an ack payload was received in the most recent call to - * write(). The regular available() can also be used. - * - * Call read() to retrieve the ack payload. - * - * @return True if an ack payload is available. - */ - bool isAckPayloadAvailable(void); + /** + * This function should be called as soon as transmission is finished to + * drop the radio back to STANDBY-I mode. If not issued, the radio will + * remain in STANDBY-II mode which, per the data sheet, is not a recommended + * operating mode. + * + * @note When transmitting data in rapid succession, it is still recommended by + * the manufacturer to drop the radio out of TX or STANDBY-II mode if there is + * time enough between sends for the FIFOs to empty. This is not required if auto-ack + * is enabled. + * + * Relies on built-in auto retry functionality. + * + * @code + * Example (Partial blocking): + * + * radio.writeFast(&buf,32); + * radio.writeFast(&buf,32); + * radio.writeFast(&buf,32); //Fills the FIFO buffers up + * bool ok = txStandBy(); //Returns 0 if failed. 1 if success. + * //Blocks only until MAX_RT timeout or success. Data flushed on fail. + * @endcode + * @see txStandBy(unsigned long timeout) + * @return True if transmission is successful + * + */ + bool txStandBy(); - /** - * Call this when you get an interrupt to find out why - * - * Tells you what caused the interrupt, and clears the state of - * interrupts. - * - * @param[out] tx_ok The send was successful (TX_DS) - * @param[out] tx_fail The send failed, too many retries (MAX_RT) - * @param[out] rx_ready There is a message waiting to be read (RX_DS) - */ - void whatHappened(bool& tx_ok,bool& tx_fail,bool& rx_ready); + /** + * This function allows extended blocking and auto-retries per a user defined timeout + * @code + * Fully Blocking Example: + * + * radio.writeFast(&buf,32); + * radio.writeFast(&buf,32); + * radio.writeFast(&buf,32); //Fills the FIFO buffers up + * bool ok = txStandBy(1000); //Returns 0 if failed after 1 second of retries. 1 if success. + * //Blocks only until user defined timeout or success. Data flushed on fail. + * @endcode + * @note If used from within an interrupt, the interrupt should be disabled until completion, and sei(); called to enable millis(). + * @param timeout Number of milliseconds to retry failed payloads + * @return True if transmission is successful + * + */ + bool txStandBy(uint32_t timeout, bool startTx = 0); - /** - * Non-blocking write to the open writing pipe used for buffered writes - * - * @note Optimization: This function now leaves the CE pin high, so the radio - * will remain in TX or STANDBY-II Mode until a txStandBy() command is issued. Can be used as an alternative to startWrite() - * if writing multiple payloads at once. - * @warning It is important to never keep the nRF24L01 in TX mode with FIFO full for more than 4ms at a time. If the auto - * retransmit/autoAck is enabled, the nRF24L01 is never in TX mode long enough to disobey this rule. Allow the FIFO - * to clear by issuing txStandBy() or ensure appropriate time between transmissions. - * - * @see write() - * @see writeFast() - * @see startWrite() - * @see writeBlocking() - * - * For single noAck writes see: - * @see enableDynamicAck() - * @see setAutoAck() - * - * @param buf Pointer to the data to be sent - * @param len Number of bytes to be sent - * @param multicast Request ACK (0) or NOACK (1) - * @return True if the payload was delivered successfully false if not - */ - void startFastWrite( const void* buf, uint8_t len, const bool multicast, bool startTx = 1 ); + /** + * Write an ack payload for the specified pipe + * + * The next time a message is received on @p pipe, the data in @p buf will + * be sent back in the acknowledgement. + * @see enableAckPayload() + * @see enableDynamicPayloads() + * @warning Only three of these can be pending at any time as there are only 3 FIFO buffers.
Dynamic payloads must be enabled. + * @note Ack payloads are handled automatically by the radio chip when a payload is received. Users should generally + * write an ack payload as soon as startListening() is called, so one is available when a regular payload is received. + * @note Ack payloads are dynamic payloads. This only works on pipes 0&1 by default. Call + * enableDynamicPayloads() to enable on all pipes. + * + * @param pipe Which pipe# (typically 1-5) will get this response. + * @param buf Pointer to data that is sent + * @param len Length of the data to send, up to 32 bytes max. Not affected + * by the static payload set by setPayloadSize(). + */ + void writeAckPayload(uint8_t pipe, const void* buf, uint8_t len); - /** - * Non-blocking write to the open writing pipe - * - * Just like write(), but it returns immediately. To find out what happened - * to the send, catch the IRQ and then call whatHappened(). - * - * @see write() - * @see writeFast() - * @see startFastWrite() - * @see whatHappened() - * - * For single noAck writes see: - * @see enableDynamicAck() - * @see setAutoAck() - * - * @param buf Pointer to the data to be sent - * @param len Number of bytes to be sent - * @param multicast Request ACK (0) or NOACK (1) - * - */ - void startWrite( const void* buf, uint8_t len, const bool multicast ); - - /** - * This function is mainly used internally to take advantage of the auto payload - * re-use functionality of the chip, but can be beneficial to users as well. - * - * The function will instruct the radio to re-use the data in the FIFO buffers, - * and instructs the radio to re-send once the timeout limit has been reached. - * Used by writeFast and writeBlocking to initiate retries when a TX failure - * occurs. Retries are automatically initiated except with the standard write(). - * This way, data is not flushed from the buffer until switching between modes. - * - * @note This is to be used AFTER auto-retry fails if wanting to resend - * using the built-in payload reuse features. - * After issuing reUseTX(), it will keep reending the same payload forever or until - * a payload is written to the FIFO, or a flush_tx command is given. - */ - void reUseTX(); + /** + * Determine if an ack payload was received in the most recent call to + * write(). The regular available() can also be used. + * + * Call read() to retrieve the ack payload. + * + * @return True if an ack payload is available. + */ + bool isAckPayloadAvailable(void); - /** - * Empty the transmit buffer. This is generally not required in standard operation. - * May be required in specific cases after stopListening() , if operating at 250KBPS data rate. - * - * @return Current value of status register - */ - uint8_t flush_tx(void); + /** + * Call this when you get an interrupt to find out why + * + * Tells you what caused the interrupt, and clears the state of + * interrupts. + * + * @param[out] tx_ok The send was successful (TX_DS) + * @param[out] tx_fail The send failed, too many retries (MAX_RT) + * @param[out] rx_ready There is a message waiting to be read (RX_DS) + */ + void whatHappened(bool& tx_ok, bool& tx_fail, bool& rx_ready); - /** - * Test whether there was a carrier on the line for the - * previous listening period. - * - * Useful to check for interference on the current channel. - * - * @return true if was carrier, false if not - */ - bool testCarrier(void); + /** + * Non-blocking write to the open writing pipe used for buffered writes + * + * @note Optimization: This function now leaves the CE pin high, so the radio + * will remain in TX or STANDBY-II Mode until a txStandBy() command is issued. Can be used as an alternative to startWrite() + * if writing multiple payloads at once. + * @warning It is important to never keep the nRF24L01 in TX mode with FIFO full for more than 4ms at a time. If the auto + * retransmit/autoAck is enabled, the nRF24L01 is never in TX mode long enough to disobey this rule. Allow the FIFO + * to clear by issuing txStandBy() or ensure appropriate time between transmissions. + * + * @see write() + * @see writeFast() + * @see startWrite() + * @see writeBlocking() + * + * For single noAck writes see: + * @see enableDynamicAck() + * @see setAutoAck() + * + * @param buf Pointer to the data to be sent + * @param len Number of bytes to be sent + * @param multicast Request ACK (0) or NOACK (1) + * @return True if the payload was delivered successfully false if not + */ + void startFastWrite(const void* buf, uint8_t len, const bool multicast, bool startTx = 1); - /** - * Test whether a signal (carrier or otherwise) greater than - * or equal to -64dBm is present on the channel. Valid only - * on nRF24L01P (+) hardware. On nRF24L01, use testCarrier(). - * - * Useful to check for interference on the current channel and - * channel hopping strategies. - * - * @code - * bool goodSignal = radio.testRPD(); - * if(radio.available()){ - * Serial.println(goodSignal ? "Strong signal > 64dBm" : "Weak signal < 64dBm" ); - * radio.read(0,0); - * } - * @endcode - * @return true if signal => -64dBm, false if not - */ - bool testRPD(void) ; + /** + * Non-blocking write to the open writing pipe + * + * Just like write(), but it returns immediately. To find out what happened + * to the send, catch the IRQ and then call whatHappened(). + * + * @see write() + * @see writeFast() + * @see startFastWrite() + * @see whatHappened() + * + * For single noAck writes see: + * @see enableDynamicAck() + * @see setAutoAck() + * + * @param buf Pointer to the data to be sent + * @param len Number of bytes to be sent + * @param multicast Request ACK (0) or NOACK (1) + * + */ + void startWrite(const void* buf, uint8_t len, const bool multicast); - /** - * Test whether this is a real radio, or a mock shim for - * debugging. Setting either pin to 0xff is the way to - * indicate that this is not a real radio. - * - * @return true if this is a legitimate radio - */ - bool isValid() { return ce_pin != 0xff && csn_pin != 0xff; } - - /** - * Close a pipe after it has been previously opened. - * Can be safely called without having previously opened a pipe. - * @param pipe Which pipe # to close, 0-5. - */ - void closeReadingPipe( uint8_t pipe ) ; - - /** - * - * If a failure has been detected, it usually indicates a hardware issue. By default the library - * will cease operation when a failure is detected. - * This should allow advanced users to detect and resolve intermittent hardware issues. - * - * In most cases, the radio must be re-enabled via radio.begin(); and the appropriate settings - * applied after a failure occurs, if wanting to re-enable the device immediately. - * - * The three main failure modes of the radio include: - * - * Writing to radio: Radio unresponsive - Fixed internally by adding a timeout to the internal write functions in RF24 (failure handling) - * - * Reading from radio: Available returns true always - Fixed by adding a timeout to available functions by the user. This is implemented internally in RF24Network. - * - * Radio configuration settings are lost - Fixed by monitoring a value that is different from the default, and re-configuring the radio if this setting reverts to the default. - * - * See the included example, GettingStarted_HandlingFailures - * - * @code - * if(radio.failureDetected){ - * radio.begin(); // Attempt to re-configure the radio with defaults - * radio.failureDetected = 0; // Reset the detection value - * radio.openWritingPipe(addresses[1]); // Re-configure pipe addresses - * radio.openReadingPipe(1,addresses[0]); - * report_failure(); // Blink leds, send a message, etc. to indicate failure - * } - * @endcode - */ - //#if defined (FAILURE_HANDLING) - bool failureDetected; - //#endif - - /**@}*/ - - /**@}*/ - /** - * @name Optional Configurators - * - * Methods you can use to get or set the configuration of the chip. - * None are required. Calling begin() sets up a reasonable set of - * defaults. - */ - /**@{*/ + /** + * This function is mainly used internally to take advantage of the auto payload + * re-use functionality of the chip, but can be beneficial to users as well. + * + * The function will instruct the radio to re-use the data in the FIFO buffers, + * and instructs the radio to re-send once the timeout limit has been reached. + * Used by writeFast and writeBlocking to initiate retries when a TX failure + * occurs. Retries are automatically initiated except with the standard write(). + * This way, data is not flushed from the buffer until switching between modes. + * + * @note This is to be used AFTER auto-retry fails if wanting to resend + * using the built-in payload reuse features. + * After issuing reUseTX(), it will keep reending the same payload forever or until + * a payload is written to the FIFO, or a flush_tx command is given. + */ + void reUseTX(); - /** - * Set the address width from 3 to 5 bytes (24, 32 or 40 bit) - * - * @param a_width The address width to use: 3,4 or 5 - */ + /** + * Empty the transmit buffer. This is generally not required in standard operation. + * May be required in specific cases after stopListening() , if operating at 250KBPS data rate. + * + * @return Current value of status register + */ + uint8_t flush_tx(void); - void setAddressWidth(uint8_t a_width); - - /** - * Set the number and delay of retries upon failed submit - * - * @param delay How long to wait between each retry, in multiples of 250us, - * max is 15. 0 means 250us, 15 means 4000us. - * @param count How many retries before giving up, max 15 - */ - void setRetries(uint8_t delay, uint8_t count); + /** + * Test whether there was a carrier on the line for the + * previous listening period. + * + * Useful to check for interference on the current channel. + * + * @return true if was carrier, false if not + */ + bool testCarrier(void); + + /** + * Test whether a signal (carrier or otherwise) greater than + * or equal to -64dBm is present on the channel. Valid only + * on nRF24L01P (+) hardware. On nRF24L01, use testCarrier(). + * + * Useful to check for interference on the current channel and + * channel hopping strategies. + * + * @code + * bool goodSignal = radio.testRPD(); + * if(radio.available()){ + * Serial.println(goodSignal ? "Strong signal > 64dBm" : "Weak signal < 64dBm" ); + * radio.read(0,0); + * } + * @endcode + * @return true if signal => -64dBm, false if not + */ + bool testRPD(void); + + /** + * Test whether this is a real radio, or a mock shim for + * debugging. Setting either pin to 0xff is the way to + * indicate that this is not a real radio. + * + * @return true if this is a legitimate radio + */ + bool isValid() + { + return ce_pin != 0xff && csn_pin != 0xff; + } + + /** + * Close a pipe after it has been previously opened. + * Can be safely called without having previously opened a pipe. + * @param pipe Which pipe # to close, 0-5. + */ + void closeReadingPipe(uint8_t pipe); + + /** + * + * If a failure has been detected, it usually indicates a hardware issue. By default the library + * will cease operation when a failure is detected. + * This should allow advanced users to detect and resolve intermittent hardware issues. + * + * In most cases, the radio must be re-enabled via radio.begin(); and the appropriate settings + * applied after a failure occurs, if wanting to re-enable the device immediately. + * + * The three main failure modes of the radio include: + * + * Writing to radio: Radio unresponsive - Fixed internally by adding a timeout to the internal write functions in RF24 (failure handling) + * + * Reading from radio: Available returns true always - Fixed by adding a timeout to available functions by the user. This is implemented internally in RF24Network. + * + * Radio configuration settings are lost - Fixed by monitoring a value that is different from the default, and re-configuring the radio if this setting reverts to the default. + * + * See the included example, GettingStarted_HandlingFailures + * + * @code + * if(radio.failureDetected){ + * radio.begin(); // Attempt to re-configure the radio with defaults + * radio.failureDetected = 0; // Reset the detection value + * radio.openWritingPipe(addresses[1]); // Re-configure pipe addresses + * radio.openReadingPipe(1,addresses[0]); + * report_failure(); // Blink leds, send a message, etc. to indicate failure + * } + * @endcode + */ + //#if defined (FAILURE_HANDLING) + bool failureDetected; + //#endif + + /**@}*/ + + /**@}*/ + /** + * @name Optional Configurators + * + * Methods you can use to get or set the configuration of the chip. + * None are required. Calling begin() sets up a reasonable set of + * defaults. + */ + /**@{*/ + + /** + * Set the address width from 3 to 5 bytes (24, 32 or 40 bit) + * + * @param a_width The address width to use: 3,4 or 5 + */ + + void setAddressWidth(uint8_t a_width); + + /** + * Set the number and delay of retries upon failed submit + * + * @param delay How long to wait between each retry, in multiples of 250us, + * max is 15. 0 means 250us, 15 means 4000us. + * @param count How many retries before giving up, max 15 + */ + void setRetries(uint8_t delay, uint8_t count); + + /** + * Set RF communication channel + * + * @param channel Which RF channel to communicate on, 0-125 + */ + void setChannel(uint8_t channel); - /** - * Set RF communication channel - * - * @param channel Which RF channel to communicate on, 0-125 - */ - void setChannel(uint8_t channel); - /** * Get RF communication channel * * @return The currently configured RF Channel */ - uint8_t getChannel(void); + uint8_t getChannel(void); - /** - * Set Static Payload Size - * - * This implementation uses a pre-stablished fixed payload size for all - * transmissions. If this method is never called, the driver will always - * transmit the maximum payload size (32 bytes), no matter how much - * was sent to write(). - * - * @todo Implement variable-sized payloads feature - * - * @param size The number of bytes in the payload - */ - void setPayloadSize(uint8_t size); + /** + * Set Static Payload Size + * + * This implementation uses a pre-stablished fixed payload size for all + * transmissions. If this method is never called, the driver will always + * transmit the maximum payload size (32 bytes), no matter how much + * was sent to write(). + * + * @todo Implement variable-sized payloads feature + * + * @param size The number of bytes in the payload + */ + void setPayloadSize(uint8_t size); - /** - * Get Static Payload Size - * - * @see setPayloadSize() - * - * @return The number of bytes in the payload - */ - uint8_t getPayloadSize(void); + /** + * Get Static Payload Size + * + * @see setPayloadSize() + * + * @return The number of bytes in the payload + */ + uint8_t getPayloadSize(void); - /** - * Get Dynamic Payload Size - * - * For dynamic payloads, this pulls the size of the payload off - * the chip - * - * @note Corrupt packets are now detected and flushed per the - * manufacturer. - * @code - * if(radio.available()){ - * if(radio.getDynamicPayloadSize() < 1){ - * // Corrupt payload has been flushed - * return; - * } - * radio.read(&data,sizeof(data)); - * } - * @endcode - * - * @return Payload length of last-received dynamic payload - */ - uint8_t getDynamicPayloadSize(void); + /** + * Get Dynamic Payload Size + * + * For dynamic payloads, this pulls the size of the payload off + * the chip + * + * @note Corrupt packets are now detected and flushed per the + * manufacturer. + * @code + * if(radio.available()){ + * if(radio.getDynamicPayloadSize() < 1){ + * // Corrupt payload has been flushed + * return; + * } + * radio.read(&data,sizeof(data)); + * } + * @endcode + * + * @return Payload length of last-received dynamic payload + */ + uint8_t getDynamicPayloadSize(void); - /** - * Enable custom payloads on the acknowledge packets - * - * Ack payloads are a handy way to return data back to senders without - * manually changing the radio modes on both units. - * - * @note Ack payloads are dynamic payloads. This only works on pipes 0&1 by default. Call - * enableDynamicPayloads() to enable on all pipes. - */ - void enableAckPayload(void); + /** + * Enable custom payloads on the acknowledge packets + * + * Ack payloads are a handy way to return data back to senders without + * manually changing the radio modes on both units. + * + * @note Ack payloads are dynamic payloads. This only works on pipes 0&1 by default. Call + * enableDynamicPayloads() to enable on all pipes. + */ + void enableAckPayload(void); - /** - * Enable dynamically-sized payloads - * - * This way you don't always have to send large packets just to send them - * once in a while. This enables dynamic payloads on ALL pipes. - * - */ - void enableDynamicPayloads(void); - - /** - * Disable dynamically-sized payloads - * - * This disables dynamic payloads on ALL pipes. Since Ack Payloads - * requires Dynamic Payloads, Ack Payloads are also disabled. - * If dynamic payloads are later re-enabled and ack payloads are desired - * then enableAckPayload() must be called again as well. - * - */ - void disableDynamicPayloads(void); - - /** - * Enable dynamic ACKs (single write multicast or unicast) for chosen messages - * - * @note To enable full multicast or per-pipe multicast, use setAutoAck() - * - * @warning This MUST be called prior to attempting single write NOACK calls - * @code - * radio.enableDynamicAck(); - * radio.write(&data,32,1); // Sends a payload with no acknowledgement requested - * radio.write(&data,32,0); // Sends a payload using auto-retry/autoACK - * @endcode - */ - void enableDynamicAck(); - - /** - * Determine whether the hardware is an nRF24L01+ or not. - * - * @return true if the hardware is nRF24L01+ (or compatible) and false - * if its not. - */ - bool isPVariant(void) ; + /** + * Enable dynamically-sized payloads + * + * This way you don't always have to send large packets just to send them + * once in a while. This enables dynamic payloads on ALL pipes. + * + */ + void enableDynamicPayloads(void); - /** - * Enable or disable auto-acknowlede packets - * - * This is enabled by default, so it's only needed if you want to turn - * it off for some reason. - * - * @param enable Whether to enable (true) or disable (false) auto-acks - */ - void setAutoAck(bool enable); + /** + * Disable dynamically-sized payloads + * + * This disables dynamic payloads on ALL pipes. Since Ack Payloads + * requires Dynamic Payloads, Ack Payloads are also disabled. + * If dynamic payloads are later re-enabled and ack payloads are desired + * then enableAckPayload() must be called again as well. + * + */ + void disableDynamicPayloads(void); - /** - * Enable or disable auto-acknowlede packets on a per pipeline basis. - * - * AA is enabled by default, so it's only needed if you want to turn - * it off/on for some reason on a per pipeline basis. - * - * @param pipe Which pipeline to modify - * @param enable Whether to enable (true) or disable (false) auto-acks - */ - void setAutoAck( uint8_t pipe, bool enable ) ; + /** + * Enable dynamic ACKs (single write multicast or unicast) for chosen messages + * + * @note To enable full multicast or per-pipe multicast, use setAutoAck() + * + * @warning This MUST be called prior to attempting single write NOACK calls + * @code + * radio.enableDynamicAck(); + * radio.write(&data,32,1); // Sends a payload with no acknowledgement requested + * radio.write(&data,32,0); // Sends a payload using auto-retry/autoACK + * @endcode + */ + void enableDynamicAck(); - /** - * Set Power Amplifier (PA) level to one of four levels: - * RF24_PA_MIN, RF24_PA_LOW, RF24_PA_HIGH and RF24_PA_MAX - * - * The power levels correspond to the following output levels respectively: - * NRF24L01: -18dBm, -12dBm,-6dBM, and 0dBm - * - * SI24R1: -6dBm, 0dBm, 3dBM, and 7dBm. - * - * @param level Desired PA level. - */ - void setPALevel ( uint8_t level ); + /** + * Determine whether the hardware is an nRF24L01+ or not. + * + * @return true if the hardware is nRF24L01+ (or compatible) and false + * if its not. + */ + bool isPVariant(void); - /** - * Fetches the current PA level. - * - * NRF24L01: -18dBm, -12dBm, -6dBm and 0dBm - * SI24R1: -6dBm, 0dBm, 3dBm, 7dBm - * - * @return Returns values 0 to 3 representing the PA Level. - */ - uint8_t getPALevel( void ); + /** + * Enable or disable auto-acknowlede packets + * + * This is enabled by default, so it's only needed if you want to turn + * it off for some reason. + * + * @param enable Whether to enable (true) or disable (false) auto-acks + */ + void setAutoAck(bool enable); - /** - * Set the transmission data rate - * - * @warning setting RF24_250KBPS will fail for non-plus units - * - * @param speed RF24_250KBPS for 250kbs, RF24_1MBPS for 1Mbps, or RF24_2MBPS for 2Mbps - * @return true if the change was successful - */ - bool setDataRate(rf24_datarate_e speed); + /** + * Enable or disable auto-acknowlede packets on a per pipeline basis. + * + * AA is enabled by default, so it's only needed if you want to turn + * it off/on for some reason on a per pipeline basis. + * + * @param pipe Which pipeline to modify + * @param enable Whether to enable (true) or disable (false) auto-acks + */ + void setAutoAck(uint8_t pipe, bool enable); - /** - * Fetches the transmission data rate - * - * @return Returns the hardware's currently configured datarate. The value - * is one of 250kbs, RF24_1MBPS for 1Mbps, or RF24_2MBPS, as defined in the - * rf24_datarate_e enum. - */ - rf24_datarate_e getDataRate( void ) ; + /** + * Set Power Amplifier (PA) level to one of four levels: + * RF24_PA_MIN, RF24_PA_LOW, RF24_PA_HIGH and RF24_PA_MAX + * + * The power levels correspond to the following output levels respectively: + * NRF24L01: -18dBm, -12dBm,-6dBM, and 0dBm + * + * SI24R1: -6dBm, 0dBm, 3dBM, and 7dBm. + * + * @param level Desired PA level. + */ + void setPALevel(uint8_t level); - /** - * Set the CRC length - *
CRC checking cannot be disabled if auto-ack is enabled - * @param length RF24_CRC_8 for 8-bit or RF24_CRC_16 for 16-bit - */ - void setCRCLength(rf24_crclength_e length); + /** + * Fetches the current PA level. + * + * NRF24L01: -18dBm, -12dBm, -6dBm and 0dBm + * SI24R1: -6dBm, 0dBm, 3dBm, 7dBm + * + * @return Returns values 0 to 3 representing the PA Level. + */ + uint8_t getPALevel(void); - /** - * Get the CRC length - *
CRC checking cannot be disabled if auto-ack is enabled - * @return RF24_CRC_DISABLED if disabled or RF24_CRC_8 for 8-bit or RF24_CRC_16 for 16-bit - */ - rf24_crclength_e getCRCLength(void); + /** + * Set the transmission data rate + * + * @warning setting RF24_250KBPS will fail for non-plus units + * + * @param speed RF24_250KBPS for 250kbs, RF24_1MBPS for 1Mbps, or RF24_2MBPS for 2Mbps + * @return true if the change was successful + */ + bool setDataRate(rf24_datarate_e speed); - /** - * Disable CRC validation - * - * @warning CRC cannot be disabled if auto-ack/ESB is enabled. - */ - void disableCRC( void ) ; + /** + * Fetches the transmission data rate + * + * @return Returns the hardware's currently configured datarate. The value + * is one of 250kbs, RF24_1MBPS for 1Mbps, or RF24_2MBPS, as defined in the + * rf24_datarate_e enum. + */ + rf24_datarate_e getDataRate(void); - /** - * The radio will generate interrupt signals when a transmission is complete, - * a transmission fails, or a payload is received. This allows users to mask - * those interrupts to prevent them from generating a signal on the interrupt - * pin. Interrupts are enabled on the radio chip by default. - * - * @code - * Mask all interrupts except the receive interrupt: - * - * radio.maskIRQ(1,1,0); - * @endcode - * - * @param tx_ok Mask transmission complete interrupts - * @param tx_fail Mask transmit failure interrupts - * @param rx_ready Mask payload received interrupts - */ - void maskIRQ(bool tx_ok,bool tx_fail,bool rx_ready); - - /** - * - * The driver will delay for this duration when stopListening() is called - * - * When responding to payloads, faster devices like ARM(RPi) are much faster than Arduino: - * 1. Arduino sends data to RPi, switches to RX mode - * 2. The RPi receives the data, switches to TX mode and sends before the Arduino radio is in RX mode - * 3. If AutoACK is disabled, this can be set as low as 0. If AA/ESB enabled, set to 100uS minimum on RPi - * - * @warning If set to 0, ensure 130uS delay after stopListening() and before any sends - */ - - uint32_t txDelay; - - /** - * - * On all devices but Linux and ATTiny, a small delay is added to the CSN toggling function - * - * This is intended to minimise the speed of SPI polling due to radio commands - * - * If using interrupts or timed requests, this can be set to 0 Default:5 - */ - - uint32_t csDelay; - - /**@}*/ - /** - * @name Deprecated - * - * Methods provided for backwards compabibility. - */ - /**@{*/ + /** + * Set the CRC length + *
CRC checking cannot be disabled if auto-ack is enabled + * @param length RF24_CRC_8 for 8-bit or RF24_CRC_16 for 16-bit + */ + void setCRCLength(rf24_crclength_e length); + /** + * Get the CRC length + *
CRC checking cannot be disabled if auto-ack is enabled + * @return RF24_CRC_DISABLED if disabled or RF24_CRC_8 for 8-bit or RF24_CRC_16 for 16-bit + */ + rf24_crclength_e getCRCLength(void); - /** - * Open a pipe for reading - * @note For compatibility with old code only, see new function - * - * @warning Pipes 1-5 should share the first 32 bits. - * Only the least significant byte should be unique, e.g. - * @code - * openReadingPipe(1,0xF0F0F0F0AA); - * openReadingPipe(2,0xF0F0F0F066); - * @endcode - * - * @warning Pipe 0 is also used by the writing pipe. So if you open - * pipe 0 for reading, and then startListening(), it will overwrite the - * writing pipe. Ergo, do an openWritingPipe() again before write(). - * - * @param number Which pipe# to open, 0-5. - * @param address The 40-bit address of the pipe to open. - */ - void openReadingPipe(uint8_t number, uint64_t address); + /** + * Disable CRC validation + * + * @warning CRC cannot be disabled if auto-ack/ESB is enabled. + */ + void disableCRC(void); - /** - * Open a pipe for writing - * @note For compatibility with old code only, see new function - * - * Addresses are 40-bit hex values, e.g.: - * - * @code - * openWritingPipe(0xF0F0F0F0F0); - * @endcode - * - * @param address The 40-bit address of the pipe to open. - */ - void openWritingPipe(uint64_t address); + /** + * The radio will generate interrupt signals when a transmission is complete, + * a transmission fails, or a payload is received. This allows users to mask + * those interrupts to prevent them from generating a signal on the interrupt + * pin. Interrupts are enabled on the radio chip by default. + * + * @code + * Mask all interrupts except the receive interrupt: + * + * radio.maskIRQ(1,1,0); + * @endcode + * + * @param tx_ok Mask transmission complete interrupts + * @param tx_fail Mask transmit failure interrupts + * @param rx_ready Mask payload received interrupts + */ + void maskIRQ(bool tx_ok, bool tx_fail, bool rx_ready); + + /** + * + * The driver will delay for this duration when stopListening() is called + * + * When responding to payloads, faster devices like ARM(RPi) are much faster than Arduino: + * 1. Arduino sends data to RPi, switches to RX mode + * 2. The RPi receives the data, switches to TX mode and sends before the Arduino radio is in RX mode + * 3. If AutoACK is disabled, this can be set as low as 0. If AA/ESB enabled, set to 100uS minimum on RPi + * + * @warning If set to 0, ensure 130uS delay after stopListening() and before any sends + */ + + uint32_t txDelay; + + /** + * + * On all devices but Linux and ATTiny, a small delay is added to the CSN toggling function + * + * This is intended to minimise the speed of SPI polling due to radio commands + * + * If using interrupts or timed requests, this can be set to 0 Default:5 + */ + + uint32_t csDelay; + + /**@}*/ + /** + * @name Deprecated + * + * Methods provided for backwards compabibility. + */ + /**@{*/ - /** - * Empty the receive buffer - * - * @return Current value of status register - */ - uint8_t flush_rx(void); + + /** + * Open a pipe for reading + * @note For compatibility with old code only, see new function + * + * @warning Pipes 1-5 should share the first 32 bits. + * Only the least significant byte should be unique, e.g. + * @code + * openReadingPipe(1,0xF0F0F0F0AA); + * openReadingPipe(2,0xF0F0F0F066); + * @endcode + * + * @warning Pipe 0 is also used by the writing pipe. So if you open + * pipe 0 for reading, and then startListening(), it will overwrite the + * writing pipe. Ergo, do an openWritingPipe() again before write(). + * + * @param number Which pipe# to open, 0-5. + * @param address The 40-bit address of the pipe to open. + */ + void openReadingPipe(uint8_t number, uint64_t address); + + /** + * Open a pipe for writing + * @note For compatibility with old code only, see new function + * + * Addresses are 40-bit hex values, e.g.: + * + * @code + * openWritingPipe(0xF0F0F0F0F0); + * @endcode + * + * @param address The 40-bit address of the pipe to open. + */ + void openWritingPipe(uint64_t address); + + /** + * Empty the receive buffer + * + * @return Current value of status register + */ + uint8_t flush_rx(void); private: - /** - * @name Low-level internal interface. - * - * Protected methods that address the chip directly. Regular users cannot - * ever call these. They are documented for completeness and for developers who - * may want to extend this class. - */ - /**@{*/ + /** + * @name Low-level internal interface. + * + * Protected methods that address the chip directly. Regular users cannot + * ever call these. They are documented for completeness and for developers who + * may want to extend this class. + */ + /**@{*/ - /** - * 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 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 - * - * @param level HIGH to actively begin transmission or LOW to put in standby. Please see data sheet - * for a much more detailed description of this pin. - */ - void ce(bool level); + /** + * Set chip enable + * + * @param level HIGH to actively begin transmission or LOW to put in standby. Please see data sheet + * for a much more detailed description of this pin. + */ + void ce(bool level); - /** - * Read a chunk of data in from a register - * - * @param reg Which register. Use constants from nRF24L01.h - * @param buf Where to put the data - * @param len How many bytes of data to transfer - * @return Current value of status register - */ - uint8_t read_register(uint8_t reg, uint8_t* buf, uint8_t len); + /** + * Read a chunk of data in from a register + * + * @param reg Which register. Use constants from nRF24L01.h + * @param buf Where to put the data + * @param len How many bytes of data to transfer + * @return Current value of status register + */ + uint8_t read_register(uint8_t reg, uint8_t* buf, uint8_t len); - /** - * Read single byte from a register - * - * @param reg Which register. Use constants from nRF24L01.h - * @return Current value of register @p reg - */ - uint8_t read_register(uint8_t reg); + /** + * Read single byte from a register + * + * @param reg Which register. Use constants from nRF24L01.h + * @return Current value of register @p reg + */ + uint8_t read_register(uint8_t reg); - /** - * Write a chunk of data to a register - * - * @param reg Which register. Use constants from nRF24L01.h - * @param buf Where to get the data - * @param len How many bytes of data to transfer - * @return Current value of status register - */ - uint8_t write_register(uint8_t reg, const uint8_t* buf, uint8_t len); + /** + * Write a chunk of data to a register + * + * @param reg Which register. Use constants from nRF24L01.h + * @param buf Where to get the data + * @param len How many bytes of data to transfer + * @return Current value of status register + */ + uint8_t write_register(uint8_t reg, const uint8_t* buf, uint8_t len); - /** - * Write a single byte to a register - * - * @param reg Which register. Use constants from nRF24L01.h - * @param value The new value to write - * @return Current value of status register - */ - uint8_t write_register(uint8_t reg, uint8_t value); + /** + * Write a single byte to a register + * + * @param reg Which register. Use constants from nRF24L01.h + * @param value The new value to write + * @return Current value of status register + */ + uint8_t write_register(uint8_t reg, uint8_t value); - /** - * Write the transmit payload - * - * The size of data written is the fixed payload size, see getPayloadSize() - * - * @param buf Where to get the data - * @param len Number of bytes to be sent - * @return Current value of status register - */ - uint8_t write_payload(const void* buf, uint8_t len, const uint8_t writeType); + /** + * Write the transmit payload + * + * The size of data written is the fixed payload size, see getPayloadSize() + * + * @param buf Where to get the data + * @param len Number of bytes to be sent + * @return Current value of status register + */ + uint8_t write_payload(const void* buf, uint8_t len, const uint8_t writeType); - /** - * Read the receive payload - * - * The size of data read is the fixed payload size, see getPayloadSize() - * - * @param buf Where to put the data - * @param len Maximum number of bytes to read - * @return Current value of status register - */ - uint8_t read_payload(void* buf, uint8_t len); + /** + * Read the receive payload + * + * The size of data read is the fixed payload size, see getPayloadSize() + * + * @param buf Where to put the data + * @param len Maximum number of bytes to read + * @return Current value of status register + */ + uint8_t read_payload(void* buf, uint8_t len); - /** - * Retrieve the current status of the chip - * - * @return Current value of status register - */ - uint8_t get_status(void); + /** + * Retrieve the current status of the chip + * + * @return Current value of status register + */ + uint8_t get_status(void); - #if !defined (MINIMAL) - /** - * Decode and print the given status to stdout - * - * @param status Status value to print - * - * @warning Does nothing if stdout is not defined. See fdevopen in stdio.h - */ - void print_status(uint8_t status); + #if ! defined (MINIMAL) - /** - * Decode and print the given 'observe_tx' value to stdout - * - * @param value The observe_tx value to print - * - * @warning Does nothing if stdout is not defined. See fdevopen in stdio.h - */ - void print_observe_tx(uint8_t value); + /** + * Decode and print the given status to stdout + * + * @param status Status value to print + * + * @warning Does nothing if stdout is not defined. See fdevopen in stdio.h + */ + void print_status(uint8_t status); - /** - * Print the name and value of an 8-bit register to stdout - * - * Optionally it can print some quantity of successive - * registers on the same line. This is useful for printing a group - * of related registers on one line. - * - * @param name Name of the register - * @param reg Which register. Use constants from nRF24L01.h - * @param qty How many successive registers to print - */ - void print_byte_register(const char* name, uint8_t reg, uint8_t qty = 1); + /** + * Decode and print the given 'observe_tx' value to stdout + * + * @param value The observe_tx value to print + * + * @warning Does nothing if stdout is not defined. See fdevopen in stdio.h + */ + void print_observe_tx(uint8_t value); - /** - * Print the name and value of a 40-bit address register to stdout - * - * Optionally it can print some quantity of successive - * registers on the same line. This is useful for printing a group - * of related registers on one line. - * - * @param name Name of the register - * @param reg Which register. Use constants from nRF24L01.h - * @param qty How many successive registers to print - */ - void print_address_register(const char* name, uint8_t reg, uint8_t qty = 1); -#endif - /** - * Turn on or off the special features of the chip - * - * The chip has certain 'features' which are only available when the 'features' - * are enabled. See the datasheet for details. - */ - void toggle_features(void); + /** + * Print the name and value of an 8-bit register to stdout + * + * Optionally it can print some quantity of successive + * registers on the same line. This is useful for printing a group + * of related registers on one line. + * + * @param name Name of the register + * @param reg Which register. Use constants from nRF24L01.h + * @param qty How many successive registers to print + */ + void print_byte_register(const char* name, uint8_t reg, uint8_t qty = 1); - /** - * Built in spi transfer function to simplify repeating code repeating code - */ + /** + * Print the name and value of a 40-bit address register to stdout + * + * Optionally it can print some quantity of successive + * registers on the same line. This is useful for printing a group + * of related registers on one line. + * + * @param name Name of the register + * @param reg Which register. Use constants from nRF24L01.h + * @param qty How many successive registers to print + */ + void print_address_register(const char* name, uint8_t reg, uint8_t qty = 1); + + #endif + + /** + * Turn on or off the special features of the chip + * + * The chip has certain 'features' which are only available when the 'features' + * are enabled. See the datasheet for details. + */ + void toggle_features(void); + + /** + * Built in spi transfer function to simplify repeating code repeating code + */ + + uint8_t spiTrans(uint8_t cmd); + + #if defined (FAILURE_HANDLING) || defined (RF24_LINUX) + + void errNotify(void); - uint8_t spiTrans(uint8_t cmd); - - #if defined (FAILURE_HANDLING) || defined (RF24_LINUX) - void errNotify(void); - #endif - - /**@}*/ + #endif + + /**@}*/ }; @@ -1183,18 +1204,18 @@ s * * @note When switching between sketches, the radio may need to be powered down to clear settings that are not "un-set" otherwise */ - /** - * @example gettingstarted.cpp - * For Linux
- * Updated: TMRh20 2014
- * - * This is an example of how to use the RF24 class to communicate on a basic level. Configure and write this sketch to two - * different nodes. Put one of the nodes into 'transmit' mode by connecting with the serial monitor and
- * sending a 'T'. The ping node sends the current time to the pong node, which responds by sending the value - * back. The ping node can then see how long the whole cycle took.
- * @note For a more efficient call-response scenario see the GettingStarted_CallResponse.ino example. - */ - +/** +* @example gettingstarted.cpp +* For Linux
+* Updated: TMRh20 2014
+* +* This is an example of how to use the RF24 class to communicate on a basic level. Configure and write this sketch to two +* different nodes. Put one of the nodes into 'transmit' mode by connecting with the serial monitor and
+* sending a 'T'. The ping node sends the current time to the pong node, which responds by sending the value +* back. The ping node can then see how long the whole cycle took.
+* @note For a more efficient call-response scenario see the GettingStarted_CallResponse.ino example. +*/ + /** * @example GettingStarted_CallResponse.ino * For Arduino
@@ -1206,35 +1227,35 @@ s * * switch out of Primary Receiver mode to send back a payload, but having the option to switch to
* primary transmitter if wanting to initiate communication instead of respond to a commmunication. */ - - /** - * @example gettingstarted_call_response.cpp - * For Linux
- * New: TMRh20 2014
- * - * This example continues to make use of all the normal functionality of the radios including - * the auto-ack and auto-retry features, but allows ack-payloads to be written optionlly as well.
- * This allows very fast call-response communication, with the responding radio never having to - * switch out of Primary Receiver mode to send back a payload, but having the option to switch to
- * primary transmitter if wanting to initiate communication instead of respond to a commmunication. - */ - /** - * @example GettingStarted_HandlingData.ino - * Dec 2014 - TMRh20
- * - * This example demonstrates how to send multiple variables in a single payload and work with data. As usual, it is - * generally important to include an incrementing value like millis() in the payloads to prevent errors. - */ - - /** - * @example GettingStarted_HandlingFailures.ino - * - * This example demonstrates the basic getting started functionality, but with failure handling for the radio chip. - * Addresses random radio failures etc, potentially due to loose wiring on breadboards etc. - */ - - +/** +* @example gettingstarted_call_response.cpp +* For Linux
+* New: TMRh20 2014
+* +* This example continues to make use of all the normal functionality of the radios including +* the auto-ack and auto-retry features, but allows ack-payloads to be written optionlly as well.
+* This allows very fast call-response communication, with the responding radio never having to +* switch out of Primary Receiver mode to send back a payload, but having the option to switch to
+* primary transmitter if wanting to initiate communication instead of respond to a commmunication. +*/ + +/** +* @example GettingStarted_HandlingData.ino +* Dec 2014 - TMRh20
+* +* This example demonstrates how to send multiple variables in a single payload and work with data. As usual, it is +* generally important to include an incrementing value like millis() in the payloads to prevent errors. +*/ + +/** +* @example GettingStarted_HandlingFailures.ino +* +* This example demonstrates the basic getting started functionality, but with failure handling for the radio chip. +* Addresses random radio failures etc, potentially due to loose wiring on breadboards etc. +*/ + + /** * @example Transfer.ino * For Arduino
@@ -1245,17 +1266,17 @@ s * * with the serial monitor and sending a 'T'. The data transfer will begin, * with the receiver displaying the payload count. (32Byte Payloads)
*/ - - /** - * @example transfer.cpp - * For Linux
- * This example demonstrates half-rate transfer using the FIFO buffers
- * - * It is an example of how to use the RF24 class. Write this sketch to two - * different nodes. Put one of the nodes into 'transmit' mode by connecting
- * with the serial monitor and sending a 'T'. The data transfer will begin, - * with the receiver displaying the payload count. (32Byte Payloads)
- */ + +/** +* @example transfer.cpp +* For Linux
+* This example demonstrates half-rate transfer using the FIFO buffers
+* +* It is an example of how to use the RF24 class. Write this sketch to two +* different nodes. Put one of the nodes into 'transmit' mode by connecting
+* with the serial monitor and sending a 'T'. The data transfer will begin, +* with the receiver displaying the payload count. (32Byte Payloads)
+*/ /** * @example TransferTimeouts.ino @@ -1303,12 +1324,12 @@ s * * Sleep functionality is built directly into my fork of the RF24Network library
*/ - /** - * @example pingpair_irq_simple.ino - * Dec 2014 - TMRh20
- * This is an example of how to user interrupts to interact with the radio, with bidirectional communication. - */ - +/** +* @example pingpair_irq_simple.ino +* Dec 2014 - TMRh20
+* This is an example of how to user interrupts to interact with the radio, with bidirectional communication. +*/ + /** * @example pingpair_sleepy.ino * Update: TMRh20
@@ -1318,36 +1339,36 @@ s * * ping/pong cycle, and the receiver sleeps between payloads.
*/ - /** - * @example rf24ping85.ino - * New: Contributed by https://github.com/tong67
- * This is an example of how to use the RF24 class to communicate with ATtiny85 and other node.
- */ - - /** - * @example timingSearch3pin.ino - * New: Contributed by https://github.com/tong67
- * This is an example of how to determine the correct timing for ATtiny when using only 3-pins - */ - +/** +* @example rf24ping85.ino +* New: Contributed by https://github.com/tong67
+* This is an example of how to use the RF24 class to communicate with ATtiny85 and other node.
+*/ + +/** +* @example timingSearch3pin.ino +* New: Contributed by https://github.com/tong67
+* This is an example of how to determine the correct timing for ATtiny when using only 3-pins +*/ + /** * @example pingpair_dyn.ino * * This is an example of how to use payloads of a varying (dynamic) size on Arduino. */ - - /** - * @example pingpair_dyn.cpp - * - * This is an example of how to use payloads of a varying (dynamic) size on Linux. - */ + +/** +* @example pingpair_dyn.cpp +* +* This is an example of how to use payloads of a varying (dynamic) size on Linux. +*/ /** * @example pingpair_dyn.py * * This is a python example for RPi of how to use payloads of a varying (dynamic) size. - */ - + */ + /** * @example scanner.ino * diff --git a/RF24_config.h b/RF24_config.h index 8ef822758..b3693b10d 100644 --- a/RF24_config.h +++ b/RF24_config.h @@ -1,15 +1,15 @@ /* Copyright (C) - 2011 J. Coliz - 2015-2019 TMRh20 - 2015 spaniakos - 2015 nerdralph - 2015 zador-blood-stained - 2016 akatran - 2017-2019 Avamander - 2019 IkpeohaGodson - + 2011 J. Coliz + 2015-2019 TMRh20 + 2015 spaniakos + 2015 nerdralph + 2015 zador-blood-stained + 2016 akatran + 2017-2019 Avamander + 2019 IkpeohaGodson + This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License version 2 as published by the Free Software Foundation. @@ -18,149 +18,149 @@ #ifndef __RF24_CONFIG_H__ #define __RF24_CONFIG_H__ -/*** USER DEFINES: ***/ +/*** USER DEFINES: ***/ #define FAILURE_HANDLING //#define SERIAL_DEBUG //#define MINIMAL -//#define SPI_UART // Requires library from https://github.com/TMRh20/Sketches/tree/master/SPI_UART -//#define SOFTSPI // Requires library from https://github.com/greiman/DigitalIO - +//#define SPI_UART // Requires library from https://github.com/TMRh20/Sketches/tree/master/SPI_UART +//#define SOFTSPI // Requires library from https://github.com/greiman/DigitalIO + /**********************/ #define rf24_max(a,b) (a>b?a:b) #define rf24_min(a,b) (a - - // RF modules support 10 Mhz SPI bus speed - const uint32_t RF24_SPI_SPEED = 10000000; - - #if defined (ARDUINO) && !defined (__arm__) && !defined (__ARDUINO_X86__) - #if defined SPI_UART - #include - #define _SPI uspi - #elif defined (SOFTSPI) - // change these pins to your liking - // - #ifndef SOFT_SPI_MISO_PIN - #define SOFT_SPI_MISO_PIN 9 - #endif // SOFT_SPI_MISO_PIN - - #ifndef SOFT_SPI_MOSI_PIN - #define SOFT_SPI_MOSI_PIN 8 - #endif // SOFT_SPI_MOSI_PIN - - #ifndef SOFT_SPI_SCK_PIN - #define SOFT_SPI_SCK_PIN 7 - #endif // SOFT_SPI_SCK_PIN - - const uint8_t SPI_MODE = 0; - #define _SPI spi - - #else // !defined (SPI_UART) && !defined (SOFTSPI) - #include - #define _SPI SPI - #endif // !defined (SPI_UART) && !defined (SOFTSPI) - - #else // defined (ARDUINO) && !defined (__arm__) && !defined (__ARDUINO_X86__) - // Define _BV for non-Arduino platforms and for Arduino DUE - #include - #include - #include - - #if defined(__arm__) || defined (__ARDUINO_X86__) - #if defined (__arm__) && defined (SPI_UART) - #include - #define _SPI uspi - - #else // !defined (__arm__) || !defined (SPI_UART) - #include - #define _SPI SPI - - #endif // !defined (__arm__) || !defined (SPI_UART) - #elif !defined(__arm__) && !defined (__ARDUINO_X86__) - extern HardwareSPI SPI; - - #endif // !defined(__arm__) && !defined (__ARDUINO_X86__) + #include + + // RF modules support 10 Mhz SPI bus speed + const uint32_t RF24_SPI_SPEED = 10000000; + + #if defined (ARDUINO) && !defined (__arm__) && !defined (__ARDUINO_X86__) + #if defined SPI_UART + #include + #define _SPI uspi + #elif defined (SOFTSPI) + // change these pins to your liking + // + #ifndef SOFT_SPI_MISO_PIN + #define SOFT_SPI_MISO_PIN 9 + #endif // SOFT_SPI_MISO_PIN + + #ifndef SOFT_SPI_MOSI_PIN + #define SOFT_SPI_MOSI_PIN 8 + #endif // SOFT_SPI_MOSI_PIN + + #ifndef SOFT_SPI_SCK_PIN + #define SOFT_SPI_SCK_PIN 7 + #endif // SOFT_SPI_SCK_PIN + + const uint8_t SPI_MODE = 0; + #define _SPI spi + + #else // !defined (SPI_UART) && !defined (SOFTSPI) + #include + #define _SPI SPI + #endif // !defined (SPI_UART) && !defined (SOFTSPI) + + #else // defined (ARDUINO) && !defined (__arm__) && !defined (__ARDUINO_X86__) + // Define _BV for non-Arduino platforms and for Arduino DUE + #include + #include + #include + + #if defined(__arm__) || defined (__ARDUINO_X86__) + #if defined (__arm__) && defined (SPI_UART) + #include + #define _SPI uspi + + #else // !defined (__arm__) || !defined (SPI_UART) + #include + #define _SPI SPI + + #endif // !defined (__arm__) || !defined (SPI_UART) + #elif !defined(__arm__) && !defined (__ARDUINO_X86__) + extern HardwareSPI SPI; + + #endif // !defined(__arm__) && !defined (__ARDUINO_X86__) - #define _BV(x) (1<<(x)) - #endif // defined (ARDUINO) && !defined (__arm__) && !defined (__ARDUINO_X86__) - - #ifdef SERIAL_DEBUG - #define IF_SERIAL_DEBUG(x) ({x;}) - #else - #define IF_SERIAL_DEBUG(x) - #if defined(RF24_TINY) - #define printf_P(...) - - #endif // defined(RF24_TINY) - #endif // SERIAL_DEBUG - - #if defined (__ARDUINO_X86__) - #define printf_P printf - #define _BV(bit) (1<<(bit)) - - #endif // defined (__ARDUINO_X86__) - - // Progmem is Arduino-specific - // Arduino DUE is arm and does not include avr/pgmspace - #if defined (ARDUINO_ARCH_ESP8266) || defined (ESP32) - #include - #define PRIPSTR "%s" - - #elif defined (ESP32) - #include - #define PRIPSTR "%s" - - #elif defined (ARDUINO) && !defined (ESP_PLATFORM) && ! defined (__arm__) && !defined (__ARDUINO_X86__) || defined (XMEGA) - #include - #define PRIPSTR "%S" - - #else // !defined (ARDUINO) || defined (ESP_PLATFORM) || defined (__arm__) || defined (__ARDUINO_X86__) && !defined (XMEGA) - #if !defined (ARDUINO) // This doesn't work on Arduino DUE - typedef char const char; - - #else // Fill in pgm_read_byte that is used, but missing from DUE - #define pgm_read_byte(addr) (*(const unsigned char *)(addr)) - #endif // !defined (ARDUINO) - - typedef uint16_t prog_uint16_t; - #define PSTR(x) (x) - #define printf_P printf - #define strlen_P strlen - #define PROGMEM - #define pgm_read_word(p) (*(p)) - #define pgm_read_ptr(p) (*(p)) - #define PRIPSTR "%s" - - #endif // !defined (ARDUINO) || defined (ESP_PLATFORM) || defined (__arm__) || defined (__ARDUINO_X86__) && !defined (XMEGA) + #define _BV(x) (1<<(x)) + #endif // defined (ARDUINO) && !defined (__arm__) && !defined (__ARDUINO_X86__) + + #ifdef SERIAL_DEBUG + #define IF_SERIAL_DEBUG(x) ({x;}) + #else + #define IF_SERIAL_DEBUG(x) + #if defined(RF24_TINY) + #define printf_P(...) + + #endif // defined(RF24_TINY) + #endif // SERIAL_DEBUG + + #if defined (__ARDUINO_X86__) + #define printf_P printf + #define _BV(bit) (1<<(bit)) + + #endif // defined (__ARDUINO_X86__) + + // Progmem is Arduino-specific + // Arduino DUE is arm and does not include avr/pgmspace + #if defined (ARDUINO_ARCH_ESP8266) || defined (ESP32) + #include + #define PRIPSTR "%s" + + #elif defined (ESP32) + #include + #define PRIPSTR "%s" + + #elif defined (ARDUINO) && !defined (ESP_PLATFORM) && ! defined (__arm__) && !defined (__ARDUINO_X86__) || defined (XMEGA) + #include + #define PRIPSTR "%S" + + #else // !defined (ARDUINO) || defined (ESP_PLATFORM) || defined (__arm__) || defined (__ARDUINO_X86__) && !defined (XMEGA) + #if !defined (ARDUINO) // This doesn't work on Arduino DUE + typedef char const char; + + #else // Fill in pgm_read_byte that is used, but missing from DUE + #define pgm_read_byte(addr) (*(const unsigned char *)(addr)) + #endif // !defined (ARDUINO) + + typedef uint16_t prog_uint16_t; + #define PSTR(x) (x) + #define printf_P printf + #define strlen_P strlen + #define PROGMEM + #define pgm_read_word(p) (*(p)) + #define pgm_read_ptr(p) (*(p)) + #define PRIPSTR "%s" + + #endif // !defined (ARDUINO) || defined (ESP_PLATFORM) || defined (__arm__) || defined (__ARDUINO_X86__) && !defined (XMEGA) #endif //Everything else #endif // __RF24_CONFIG_H__ diff --git a/doxygen-custom.css b/doxygen-custom.css index bec4472e8..9491c0d72 100644 --- a/doxygen-custom.css +++ b/doxygen-custom.css @@ -1,295 +1,295 @@ /* The standard CSS for doxygen */ body, table, div, p, dl { - font-family: Lucida Grande, Verdana, Geneva, Arial, sans-serif; - font-size: 12px; + font-family: Lucida Grande, Verdana, Geneva, Arial, sans-serif; + font-size: 12px; } /* @group Heading Levels */ h1 { - font-size: 150%; + font-size: 150%; } .title { - font-size: 150%; - font-weight: bold; - margin: 10px 2px; + font-size: 150%; + font-weight: bold; + margin: 10px 2px; } h2 { - font-size: 120%; + font-size: 120%; } h3 { - font-size: 100%; + font-size: 100%; } dt { - font-weight: bold; + font-weight: bold; } div.multicol { - -moz-column-gap: 1em; - -webkit-column-gap: 1em; - -moz-column-count: 3; - -webkit-column-count: 3; + -moz-column-gap: 1em; + -webkit-column-gap: 1em; + -moz-column-count: 3; + -webkit-column-count: 3; } p.startli, p.startdd, p.starttd { - margin-top: 2px; + margin-top: 2px; } p.endli { - margin-bottom: 0px; + margin-bottom: 0px; } p.enddd { - margin-bottom: 4px; + margin-bottom: 4px; } p.endtd { - margin-bottom: 2px; + margin-bottom: 2px; } /* @end */ caption { - font-weight: bold; + font-weight: bold; } span.legend { - font-size: 70%; - text-align: center; + font-size: 70%; + text-align: center; } h3.version { - font-size: 90%; - text-align: center; + font-size: 90%; + text-align: center; } -div.qindex, div.navtab{ - background-color: #EBEFF6; - border: 1px solid #A3B4D7; - text-align: center; - margin: 2px; - padding: 2px; +div.qindex, div.navtab { + background-color: #EBEFF6; + border: 1px solid #A3B4D7; + text-align: center; + margin: 2px; + padding: 2px; } div.qindex, div.navpath { - width: 100%; - line-height: 110%; + width: 100%; + line-height: 110%; } div.navtab { - margin-right: 15px; + margin-right: 15px; } /* @group Link Styling */ a { - color: #3D578C; - font-weight: normal; - text-decoration: none; + color: #3D578C; + font-weight: normal; + text-decoration: none; } .contents a:visited { - color: #4665A2; + color: #4665A2; } a:hover { - text-decoration: underline; + text-decoration: underline; } a.qindex { - font-weight: bold; + font-weight: bold; } a.qindexHL { - font-weight: bold; - background-color: #9CAFD4; - color: #ffffff; - border: 1px double #869DCA; + font-weight: bold; + background-color: #9CAFD4; + color: #ffffff; + border: 1px double #869DCA; } .contents a.qindexHL:visited { - color: #ffffff; + color: #ffffff; } a.el { - font-weight: bold; + font-weight: bold; } a.elRef { } a.code { - color: #4665A2; + color: #4665A2; } a.codeRef { - color: #4665A2; + color: #4665A2; } /* @end */ dl.el { - margin-left: -1cm; + margin-left: -1cm; } .fragment { - font-family: monospace, fixed; - font-size: 105%; + font-family: monospace, fixed; + font-size: 105%; } pre.fragment { - border: 1px solid #C4CFE5; - background-color: #FBFCFD; - padding: 4px 6px; - margin: 4px 8px 4px 2px; - overflow: auto; - word-wrap: break-word; - font-size: 9pt; - line-height: 125%; + border: 1px solid #C4CFE5; + background-color: #FBFCFD; + padding: 4px 6px; + margin: 4px 8px 4px 2px; + overflow: auto; + word-wrap: break-word; + font-size: 9pt; + line-height: 125%; } div.ah { - background-color: black; - font-weight: bold; - color: #ffffff; - margin-bottom: 3px; - margin-top: 3px; - padding: 0.2em; - border: solid thin #333; - border-radius: 0.5em; - -webkit-border-radius: .5em; - -moz-border-radius: .5em; - box-shadow: 2px 2px 3px #999; - -webkit-box-shadow: 2px 2px 3px #999; - -moz-box-shadow: rgba(0, 0, 0, 0.15) 2px 2px 2px; - background-image: -webkit-gradient(linear, left top, left bottom, from(#eee), to(#000),color-stop(0.3, #444)); - background-image: -moz-linear-gradient(center top, #eee 0%, #444 40%, #000); + background-color: black; + font-weight: bold; + color: #ffffff; + margin-bottom: 3px; + margin-top: 3px; + padding: 0.2em; + border: solid thin #333; + border-radius: 0.5em; + -webkit-border-radius: .5em; + -moz-border-radius: .5em; + box-shadow: 2px 2px 3px #999; + -webkit-box-shadow: 2px 2px 3px #999; + -moz-box-shadow: rgba(0, 0, 0, 0.15) 2px 2px 2px; + background-image: -webkit-gradient(linear, left top, left bottom, from(#eee), to(#000), color-stop(0.3, #444)); + background-image: -moz-linear-gradient(center top, #eee 0%, #444 40%, #000); } div.groupHeader { - margin-left: 16px; - margin-top: 12px; - font-weight: bold; + margin-left: 16px; + margin-top: 12px; + font-weight: bold; } div.groupText { - margin-left: 16px; - font-style: italic; + margin-left: 16px; + font-style: italic; } body { - background: white; - color: black; - margin: 0; + background: white; + color: black; + margin: 0; } div.contents { - margin-top: 10px; - margin-left: 10px; - margin-right: 5px; + margin-top: 10px; + margin-left: 10px; + margin-right: 5px; } td.indexkey { - background-color: #EBEFF6; - font-weight: bold; - border: 1px solid #C4CFE5; - margin: 2px 0px 2px 0; - padding: 2px 10px; + background-color: #EBEFF6; + font-weight: bold; + border: 1px solid #C4CFE5; + margin: 2px 0px 2px 0; + padding: 2px 10px; } td.indexvalue { - background-color: #EBEFF6; - border: 1px solid #C4CFE5; - padding: 2px 10px; - margin: 2px 0px; + background-color: #EBEFF6; + border: 1px solid #C4CFE5; + padding: 2px 10px; + margin: 2px 0px; } tr.memlist { - background-color: #EEF1F7; + background-color: #EEF1F7; } p.formulaDsp { - text-align: center; + text-align: center; } img.formulaDsp { - + } img.formulaInl { - vertical-align: middle; + vertical-align: middle; } div.center { - text-align: center; - margin-top: 0px; - margin-bottom: 0px; - padding: 0px; + text-align: center; + margin-top: 0px; + margin-bottom: 0px; + padding: 0px; } div.center img { - border: 0px; + border: 0px; } address.footer { - text-align: right; - padding-right: 12px; + text-align: right; + padding-right: 12px; } img.footer { - border: 0px; - vertical-align: middle; + border: 0px; + vertical-align: middle; } /* @group Code Colorization */ span.keyword { - color: #008000 + color: #008000 } span.keywordtype { - color: #604020 + color: #604020 } span.keywordflow { - color: #e08000 + color: #e08000 } span.comment { - color: #800000 + color: #800000 } span.preprocessor { - color: #806020 + color: #806020 } span.stringliteral { - color: #002080 + color: #002080 } span.charliteral { - color: #008080 + color: #008080 } -span.vhdldigit { - color: #ff00ff +span.vhdldigit { + color: #ff00ff } -span.vhdlchar { - color: #000000 +span.vhdlchar { + color: #000000 } -span.vhdlkeyword { - color: #700070 +span.vhdlkeyword { + color: #700070 } -span.vhdllogic { - color: #ff0000 +span.vhdllogic { + color: #ff0000 } /* @end */ @@ -314,66 +314,66 @@ input.search { */ td.tiny { - font-size: 75%; + font-size: 75%; } .dirtab { - padding: 4px; - border-collapse: collapse; - border: 1px solid #A3B4D7; + padding: 4px; + border-collapse: collapse; + border: 1px solid #A3B4D7; } th.dirtab { - background: #EBEFF6; - font-weight: bold; + background: #EBEFF6; + font-weight: bold; } hr { - height: 0px; - border: none; - border-top: 1px solid #4A6AAA; + height: 0px; + border: none; + border-top: 1px solid #4A6AAA; } hr.footer { - height: 1px; + height: 1px; } /* @group Member Descriptions */ table.memberdecls { - border-spacing: 0px; - padding: 0px; + border-spacing: 0px; + padding: 0px; } .mdescLeft, .mdescRight, .memItemLeft, .memItemRight, .memTemplItemLeft, .memTemplItemRight, .memTemplParams { - background-color: #F9FAFC; - border: none; - margin: 4px; - padding: 1px 0 0 8px; + background-color: #F9FAFC; + border: none; + margin: 4px; + padding: 1px 0 0 8px; } .mdescLeft, .mdescRight { - padding: 0px 8px 4px 8px; - color: #555; + padding: 0px 8px 4px 8px; + color: #555; } .memItemLeft, .memItemRight, .memTemplParams { - border-top: 1px solid #C4CFE5; + border-top: 1px solid #C4CFE5; } .memItemLeft, .memTemplItemLeft { - white-space: nowrap; + white-space: nowrap; } .memItemRight { - width: 100%; + width: 100%; } .memTemplParams { - color: #4665A2; - white-space: nowrap; + color: #4665A2; + white-space: nowrap; } /* @end */ @@ -383,122 +383,121 @@ table.memberdecls { /* Styles for detailed member documentation */ .memtemplate { - font-size: 80%; - color: #4665A2; - font-weight: normal; - margin-left: 9px; + font-size: 80%; + color: #4665A2; + font-weight: normal; + margin-left: 9px; } .memnav { - background-color: #EBEFF6; - border: 1px solid #A3B4D7; - text-align: center; - margin: 2px; - margin-right: 15px; - padding: 2px; + background-color: #EBEFF6; + border: 1px solid #A3B4D7; + text-align: center; + margin: 2px; + margin-right: 15px; + padding: 2px; } .mempage { - width: 100%; + width: 100%; } .memitem { - padding: 0; - margin-bottom: 10px; - margin-right: 5px; + padding: 0; + margin-bottom: 10px; + margin-right: 5px; } .memname { - white-space: nowrap; - font-weight: bold; - margin-left: 6px; + white-space: nowrap; + font-weight: bold; + margin-left: 6px; } .memproto { - border-top: 1px solid #A8B8D9; - border-left: 1px solid #A8B8D9; - border-right: 1px solid #A8B8D9; - padding: 6px 0px 6px 0px; - color: #253555; - font-weight: bold; - text-shadow: 0px 1px 1px rgba(255, 255, 255, 0.9); - /* opera specific markup */ - box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.15); - border-top-right-radius: 8px; - border-top-left-radius: 8px; - /* firefox specific markup */ - -moz-box-shadow: rgba(0, 0, 0, 0.15) 5px 5px 5px; - -moz-border-radius-topright: 8px; - -moz-border-radius-topleft: 8px; - /* webkit specific markup */ - -webkit-box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.15); - -webkit-border-top-right-radius: 8px; - -webkit-border-top-left-radius: 8px; - background-image:url('nav_f.png'); - background-repeat:repeat-x; - background-color: #E2E8F2; + border-top: 1px solid #A8B8D9; + border-left: 1px solid #A8B8D9; + border-right: 1px solid #A8B8D9; + padding: 6px 0px 6px 0px; + color: #253555; + font-weight: bold; + text-shadow: 0px 1px 1px rgba(255, 255, 255, 0.9); + /* opera specific markup */ + box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.15); + border-top-right-radius: 8px; + border-top-left-radius: 8px; + /* firefox specific markup */ + -moz-box-shadow: rgba(0, 0, 0, 0.15) 5px 5px 5px; + -moz-border-radius-topright: 8px; + -moz-border-radius-topleft: 8px; + /* webkit specific markup */ + -webkit-box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.15); + -webkit-border-top-right-radius: 8px; + -webkit-border-top-left-radius: 8px; + background-image: url('nav_f.png'); + background-repeat: repeat-x; + background-color: #E2E8F2; } .memdoc { - border-bottom: 1px solid #A8B8D9; - border-left: 1px solid #A8B8D9; - border-right: 1px solid #A8B8D9; - padding: 2px 5px; - background-color: #FBFCFD; - border-top-width: 0; - /* opera specific markup */ - border-bottom-left-radius: 8px; - border-bottom-right-radius: 8px; - box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.15); - /* firefox specific markup */ - -moz-border-radius-bottomleft: 8px; - -moz-border-radius-bottomright: 8px; - -moz-box-shadow: rgba(0, 0, 0, 0.15) 5px 5px 5px; - background-image: -moz-linear-gradient(center top, #FFFFFF 0%, #FFFFFF 60%, #F7F8FB 95%, #EEF1F7); - /* webkit specific markup */ - -webkit-border-bottom-left-radius: 8px; - -webkit-border-bottom-right-radius: 8px; - -webkit-box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.15); - background-image: -webkit-gradient(linear,center top,center bottom,from(#FFFFFF), color-stop(0.6,#FFFFFF), color-stop(0.60,#FFFFFF), color-stop(0.95,#F7F8FB), to(#EEF1F7)); + border-bottom: 1px solid #A8B8D9; + border-left: 1px solid #A8B8D9; + border-right: 1px solid #A8B8D9; + padding: 2px 5px; + background-color: #FBFCFD; + border-top-width: 0; + /* opera specific markup */ + border-bottom-left-radius: 8px; + border-bottom-right-radius: 8px; + box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.15); + /* firefox specific markup */ + -moz-border-radius-bottomleft: 8px; + -moz-border-radius-bottomright: 8px; + -moz-box-shadow: rgba(0, 0, 0, 0.15) 5px 5px 5px; + background-image: -moz-linear-gradient(center top, #FFFFFF 0%, #FFFFFF 60%, #F7F8FB 95%, #EEF1F7); + /* webkit specific markup */ + -webkit-border-bottom-left-radius: 8px; + -webkit-border-bottom-right-radius: 8px; + -webkit-box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.15); + background-image: -webkit-gradient(linear, center top, center bottom, from(#FFFFFF), color-stop(0.6, #FFFFFF), color-stop(0.60, #FFFFFF), color-stop(0.95, #F7F8FB), to(#EEF1F7)); } .paramkey { - text-align: right; + text-align: right; } .paramtype { - white-space: nowrap; + white-space: nowrap; } .paramname { - color: #602020; - white-space: nowrap; + color: #602020; + white-space: nowrap; } + .paramname em { - font-style: normal; + font-style: normal; } .params, .retval, .exception, .tparams { - border-spacing: 6px 2px; -} + border-spacing: 6px 2px; +} .params .paramname, .retval .paramname { - font-weight: bold; - vertical-align: top; + font-weight: bold; + vertical-align: top; } - + .params .paramtype { - font-style: italic; - vertical-align: top; -} - -.params .paramdir { - font-family: "courier new",courier,monospace; - vertical-align: top; + font-style: italic; + vertical-align: top; } - +.params .paramdir { + font-family: "courier new", courier, monospace; + vertical-align: top; +} /* @end */ @@ -508,22 +507,22 @@ table.memberdecls { /* for the tree view */ .ftvtree { - font-family: sans-serif; - margin: 0px; + font-family: sans-serif; + margin: 0px; } /* these are for tree view when used as main index */ .directory { - font-size: 9pt; - font-weight: bold; - margin: 5px; + font-size: 9pt; + font-weight: bold; + margin: 5px; } .directory h3 { - margin: 0px; - margin-top: 1em; - font-size: 11pt; + margin: 0px; + margin-top: 1em; + font-size: 11pt; } /* @@ -545,291 +544,261 @@ proper pixel height of your image. */ .directory > h3 { - margin-top: 0; + margin-top: 0; } .directory p { - margin: 0px; - white-space: nowrap; + margin: 0px; + white-space: nowrap; } .directory div { - display: none; - margin: 0px; + display: none; + margin: 0px; } .directory img { - vertical-align: -30%; + vertical-align: -30%; } /* these are for tree view when not used as main index */ .directory-alt { - font-size: 100%; - font-weight: bold; + font-size: 100%; + font-weight: bold; } .directory-alt h3 { - margin: 0px; - margin-top: 1em; - font-size: 11pt; + margin: 0px; + margin-top: 1em; + font-size: 11pt; } .directory-alt > h3 { - margin-top: 0; + margin-top: 0; } .directory-alt p { - margin: 0px; - white-space: nowrap; + margin: 0px; + white-space: nowrap; } .directory-alt div { - display: none; - margin: 0px; + display: none; + margin: 0px; } .directory-alt img { - vertical-align: -30%; + vertical-align: -30%; } /* @end */ div.dynheader { - margin-top: 8px; + margin-top: 8px; } address { - font-style: normal; - color: #2A3D61; + font-style: normal; + color: #2A3D61; } table.doxtable { - border-collapse:collapse; + border-collapse: collapse; } table.doxtable td, table.doxtable th { - border: 1px solid #2D4068; - padding: 3px 7px 2px; + border: 1px solid #2D4068; + padding: 3px 7px 2px; } table.doxtable th { - background-color: #374F7F; - color: #FFFFFF; - font-size: 110%; - padding-bottom: 4px; - padding-top: 5px; - text-align:left; + background-color: #374F7F; + color: #FFFFFF; + font-size: 110%; + padding-bottom: 4px; + padding-top: 5px; + text-align: left; } .tabsearch { - top: 0px; - left: 10px; - height: 36px; - background-image: url('tab_b.png'); - z-index: 101; - overflow: hidden; - font-size: 13px; -} - -.navpath ul -{ - font-size: 11px; - background-image:url('tab_b.png'); - background-repeat:repeat-x; - height:30px; - line-height:30px; - color:#8AA0CC; - border:solid 1px #C2CDE4; - overflow:hidden; - margin:0px; - padding:0px; + top: 0px; + left: 10px; + height: 36px; + background-image: url('tab_b.png'); + z-index: 101; + overflow: hidden; + font-size: 13px; +} + +.navpath ul { + font-size: 11px; + background-image: url('tab_b.png'); + background-repeat: repeat-x; + height: 30px; + line-height: 30px; + color: #8AA0CC; + border: solid 1px #C2CDE4; + overflow: hidden; + margin: 0px; + padding: 0px; } -.navpath li -{ - list-style-type:none; - float:left; - padding-left:10px; - padding-right:15px; - background-image:url('bc_s.png'); - background-repeat:no-repeat; - background-position:right; - color:#364D7C; +.navpath li { + list-style-type: none; + float: left; + padding-left: 10px; + padding-right: 15px; + background-image: url('bc_s.png'); + background-repeat: no-repeat; + background-position: right; + color: #364D7C; } -.navpath li.navelem a -{ - height:32px; - display:block; - text-decoration: none; - outline: none; +.navpath li.navelem a { + height: 32px; + display: block; + text-decoration: none; + outline: none; } -.navpath li.navelem a:hover -{ - color:#6884BD; +.navpath li.navelem a:hover { + color: #6884BD; } -.navpath li.footer -{ - list-style-type:none; - float:right; - padding-left:10px; - padding-right:15px; - background-image:none; - background-repeat:no-repeat; - background-position:right; - color:#364D7C; - font-size: 8pt; +.navpath li.footer { + list-style-type: none; + float: right; + padding-left: 10px; + padding-right: 15px; + background-image: none; + background-repeat: no-repeat; + background-position: right; + color: #364D7C; + font-size: 8pt; } -div.summary -{ - float: right; - font-size: 8pt; - padding-right: 5px; - width: 50%; - text-align: right; -} +div.summary { + float: right; + font-size: 8pt; + padding-right: 5px; + width: 50%; + text-align: right; +} -div.summary a -{ - white-space: nowrap; +div.summary a { + white-space: nowrap; } -div.ingroups -{ - font-size: 8pt; - padding-left: 5px; - width: 50%; - text-align: left; +div.ingroups { + font-size: 8pt; + padding-left: 5px; + width: 50%; + text-align: left; } -div.ingroups a -{ - white-space: nowrap; +div.ingroups a { + white-space: nowrap; } -div.header -{ - background-image:url('nav_h.png'); - background-repeat:repeat-x; - background-color: #F9FAFC; - margin: 0px; - border-bottom: 1px solid #C4CFE5; +div.header { + background-image: url('nav_h.png'); + background-repeat: repeat-x; + background-color: #F9FAFC; + margin: 0px; + border-bottom: 1px solid #C4CFE5; } -div.headertitle -{ - padding: 5px 5px 5px 10px; +div.headertitle { + padding: 5px 5px 5px 10px; } -dl -{ - padding: 0 0 0 10px; +dl { + padding: 0 0 0 10px; } -dl.note, dl.warning, dl.attention, dl.pre, dl.post, dl.invariant, dl.deprecated, dl.todo, dl.test, dl.bug -{ - border-left:4px solid; - padding: 0 0 0 6px; +dl.note, dl.warning, dl.attention, dl.pre, dl.post, dl.invariant, dl.deprecated, dl.todo, dl.test, dl.bug { + border-left: 4px solid; + padding: 0 0 0 6px; } -dl.note -{ - border-color: #D0C000; +dl.note { + border-color: #D0C000; } -dl.warning, dl.attention -{ - border-color: #FF0000; +dl.warning, dl.attention { + border-color: #FF0000; } -dl.pre, dl.post, dl.invariant -{ - border-color: #00D000; +dl.pre, dl.post, dl.invariant { + border-color: #00D000; } -dl.deprecated -{ - border-color: #505050; +dl.deprecated { + border-color: #505050; } -dl.todo -{ - border-color: #00C0E0; +dl.todo { + border-color: #00C0E0; } -dl.test -{ - border-color: #3030E0; +dl.test { + border-color: #3030E0; } -dl.bug -{ - border-color: #C08050; +dl.bug { + border-color: #C08050; } -#projectlogo -{ - text-align: center; - vertical-align: bottom; - border-collapse: separate; +#projectlogo { + text-align: center; + vertical-align: bottom; + border-collapse: separate; } - -#projectlogo img -{ - border: 0px none; + +#projectlogo img { + border: 0px none; } - -#projectname -{ - font: 300% Tahoma, Arial,sans-serif; - margin: 0px; - padding: 2px 0px; + +#projectname { + font: 300% Tahoma, Arial, sans-serif; + margin: 0px; + padding: 2px 0px; } - -#projectbrief -{ - font: 120% Tahoma, Arial,sans-serif; - margin: 0px; - padding: 0px; + +#projectbrief { + font: 120% Tahoma, Arial, sans-serif; + margin: 0px; + padding: 0px; } -#projectnumber -{ - font: 50% Tahoma, Arial,sans-serif; - margin: 0px; - padding: 0px; +#projectnumber { + font: 50% Tahoma, Arial, sans-serif; + margin: 0px; + padding: 0px; } -#titlearea -{ - padding: 0px; - margin: 0px; - width: 100%; - border-bottom: 1px solid #5373B4; +#titlearea { + padding: 0px; + margin: 0px; + width: 100%; + border-bottom: 1px solid #5373B4; } -.image -{ - text-align: left; +.image { + text-align: left; } -.dotgraph -{ - text-align: center; +.dotgraph { + text-align: center; } -.mscgraph -{ - text-align: center; +.mscgraph { + text-align: center; } -.caption -{ - font-weight: bold; +.caption { + font-weight: bold; } diff --git a/examples_linux/gettingstarted.cpp b/examples_linux/gettingstarted.cpp index d25155e83..42a369448 100644 --- a/examples_linux/gettingstarted.cpp +++ b/examples_linux/gettingstarted.cpp @@ -46,7 +46,7 @@ using namespace std; //RF24 radio(RPI_V2_GPIO_P1_15, RPI_V2_GPIO_P1_24, BCM2835_SPI_SPEED_8MHZ); // RPi generic: -RF24 radio(22,0); +RF24 radio(22, 0); /*** RPi Alternate ***/ //Note: Specify SPI BUS 0 or 1 instead of CS pin number. @@ -80,137 +80,132 @@ bool radioNumber = 1; /********************************/ // Radio pipe addresses for the 2 nodes to communicate. -const uint8_t pipes[][6] = {"1Node","2Node"}; +const uint8_t pipes[][6] = {"1Node", "2Node"}; +int main(int argc, char** argv) +{ -int main(int argc, char** argv){ + bool role_ping_out = true, role_pong_back = false; + bool role = role_pong_back; - bool role_ping_out = true, role_pong_back = false; - bool role = role_pong_back; + cout << "RF24/examples/GettingStarted/\n"; - cout << "RF24/examples/GettingStarted/\n"; + // Setup and configure rf radio + radio.begin(); - // Setup and configure rf radio - radio.begin(); + // optionally, increase the delay between retries & # of retries + radio.setRetries(15, 15); + // Dump the configuration of the rf unit for debugging + radio.printDetails(); - // optionally, increase the delay between retries & # of retries - radio.setRetries(15,15); - // Dump the configuration of the rf unit for debugging - radio.printDetails(); + /********* Role chooser ***********/ -/********* Role chooser ***********/ + printf("\n ************ Role Setup ***********\n"); + string input = ""; + char myChar = {0}; + cout << "Choose a role: Enter 0 for pong_back, 1 for ping_out (CTRL+C to exit) \n>"; + getline(cin, input); - printf("\n ************ Role Setup ***********\n"); - string input = ""; - char myChar = {0}; - cout << "Choose a role: Enter 0 for pong_back, 1 for ping_out (CTRL+C to exit) \n>"; - getline(cin,input); - - if(input.length() == 1) { - myChar = input[0]; - if(myChar == '0'){ - cout << "Role: Pong Back, awaiting transmission " << endl << endl; - }else{ cout << "Role: Ping Out, starting transmission " << endl << endl; - role = role_ping_out; - } - } -/***********************************/ - // This simple sketch opens two pipes for these two nodes to communicate - // back and forth. + if (input.length() == 1) { + myChar = input[0]; + if (myChar == '0') { + cout << "Role: Pong Back, awaiting transmission " << endl << endl; + } else { + cout << "Role: Ping Out, starting transmission " << endl << endl; + role = role_ping_out; + } + } + /***********************************/ + // This simple sketch opens two pipes for these two nodes to communicate + // back and forth. - if ( !radioNumber ) { - radio.openWritingPipe(pipes[0]); - radio.openReadingPipe(1,pipes[1]); + if (! radioNumber) { + radio.openWritingPipe(pipes[0]); + radio.openReadingPipe(1, pipes[1]); } else { - radio.openWritingPipe(pipes[1]); - radio.openReadingPipe(1,pipes[0]); + radio.openWritingPipe(pipes[1]); + radio.openReadingPipe(1, pipes[0]); } - - radio.startListening(); - - // forever loop - while (1) - { - if (role == role_ping_out) - { - // First, stop listening so we can talk. - radio.stopListening(); - - // Take the time, and send it. This will block until complete - - printf("Now sending...\n"); - unsigned long time = millis(); - - bool ok = radio.write( &time, sizeof(unsigned long) ); - - if (!ok){ - printf("failed.\n"); - } - // Now, continue listening - radio.startListening(); - - // Wait here until we get a response, or timeout (250ms) - unsigned long started_waiting_at = millis(); - bool timeout = false; - while ( ! radio.available() && ! timeout ) { - if (millis() - started_waiting_at > 200 ) - timeout = true; - } - - - // Describe the results - if ( timeout ) - { - printf("Failed, response timed out.\n"); - } - else - { - // Grab the response, compare, and send to debugging spew - unsigned long got_time; - radio.read( &got_time, sizeof(unsigned long) ); - - // Spew it - printf("Got response %lu, round-trip delay: %lu\n",got_time,millis()-got_time); - } - sleep(1); - } - - // - // Pong back role. Receive each packet, dump it out, and send it back - // - - if ( role == role_pong_back ) - { - - // if there is data ready - if ( radio.available() ) - { - // Dump the payloads until we've gotten everything - unsigned long got_time; - - // Fetch the payload, and see if this was the last one. - while(radio.available()){ - radio.read( &got_time, sizeof(unsigned long) ); - } - radio.stopListening(); - - radio.write( &got_time, sizeof(unsigned long) ); - - // Now, resume listening so we catch the next packets. - radio.startListening(); - - // Spew it - printf("Got payload(%d) %lu...\n",sizeof(unsigned long), got_time); - - delay(925); //Delay after payload responded to, minimize RPi CPU time - - } - - } - - } // forever loop - - return 0; + + radio.startListening(); + + // forever loop + while (1) { + if (role == role_ping_out) { + // First, stop listening so we can talk. + radio.stopListening(); + + // Take the time, and send it. This will block until complete + + printf("Now sending...\n"); + unsigned long time = millis(); + + bool ok = radio.write(&time, sizeof(unsigned long)); + + if (! ok) { + printf("failed.\n"); + } + // Now, continue listening + radio.startListening(); + + // Wait here until we get a response, or timeout (250ms) + unsigned long started_waiting_at = millis(); + bool timeout = false; + while (! radio.available() && ! timeout) { + if (millis() - started_waiting_at > 200) { + timeout = true; + } + } + + + // Describe the results + if (timeout) { + printf("Failed, response timed out.\n"); + } else { + // Grab the response, compare, and send to debugging spew + unsigned long got_time; + radio.read(&got_time, sizeof(unsigned long)); + + // Spew it + printf("Got response %lu, round-trip delay: %lu\n", got_time, millis() - got_time); + } + sleep(1); + } + + // + // Pong back role. Receive each packet, dump it out, and send it back + // + + if (role == role_pong_back) { + + // if there is data ready + if (radio.available()) { + // Dump the payloads until we've gotten everything + unsigned long got_time; + + // Fetch the payload, and see if this was the last one. + while (radio.available()) { + radio.read(&got_time, sizeof(unsigned long)); + } + radio.stopListening(); + + radio.write(&got_time, sizeof(unsigned long)); + + // Now, resume listening so we catch the next packets. + radio.startListening(); + + // Spew it + printf("Got payload(%d) %lu...\n", sizeof(unsigned long), got_time); + + delay(925); //Delay after payload responded to, minimize RPi CPU time + + } + + } + + } // forever loop + + return 0; } diff --git a/examples_linux/gettingstarted_call_response.cpp b/examples_linux/gettingstarted_call_response.cpp index 970151240..800cfe36d 100644 --- a/examples_linux/gettingstarted_call_response.cpp +++ b/examples_linux/gettingstarted_call_response.cpp @@ -73,97 +73,100 @@ bool radioNumber = 1; // Radio pipe addresses for the 2 nodes to communicate. -const uint8_t addresses[][6] = {"1Node","2Node"}; +const uint8_t addresses[][6] = {"1Node", "2Node"}; bool role_ping_out = 1, role_pong_back = 0, role = 0; uint8_t counter = 1; // A single byte to keep track of the data being sent back and forth -int main(int argc, char** argv){ - - - cout << "RPi/RF24/examples/gettingstarted_call_response\n"; - radio.begin(); - radio.enableAckPayload(); // Allow optional ack payloads - radio.enableDynamicPayloads(); - radio.printDetails(); // Dump the configuration of the rf unit for debugging - - -/********* Role chooser ***********/ - - printf("\n ************ Role Setup ***********\n"); - string input = ""; - char myChar = {0}; - cout << "Choose a role: Enter 0 for pong_back, 1 for ping_out (CTRL+C to exit)\n>"; - getline(cin,input); - - if(input.length() == 1) { - myChar = input[0]; - if(myChar == '0'){ - cout << "Role: Pong Back, awaiting transmission " << endl << endl; - }else{ cout << "Role: Ping Out, starting transmission " << endl << endl; - role = role_ping_out; - } - } -/***********************************/ - // This opens two pipes for these two nodes to communicate - // back and forth. - if ( !radioNumber ) { - radio.openWritingPipe(addresses[0]); - radio.openReadingPipe(1,addresses[1]); - }else{ - radio.openWritingPipe(addresses[1]); - radio.openReadingPipe(1,addresses[0]); - } - radio.startListening(); - radio.writeAckPayload(1,&counter,1); +int main(int argc, char** argv) +{ -// forever loop -while (1){ + cout << "RPi/RF24/examples/gettingstarted_call_response\n"; + radio.begin(); + radio.enableAckPayload(); // Allow optional ack payloads + radio.enableDynamicPayloads(); + radio.printDetails(); // Dump the configuration of the rf unit for debugging -/****************** Ping Out Role ***************************/ + /********* Role chooser ***********/ - if (role == role_ping_out){ // Radio is in ping mode + printf("\n ************ Role Setup ***********\n"); + string input = ""; + char myChar = {0}; + cout << "Choose a role: Enter 0 for pong_back, 1 for ping_out (CTRL+C to exit)\n>"; + getline(cin, input); - uint8_t gotByte; // Initialize a variable for the incoming response + if (input.length() == 1) { + myChar = input[0]; + if (myChar == '0') { + cout << "Role: Pong Back, awaiting transmission " << endl << endl; + } else { + cout << "Role: Ping Out, starting transmission " << endl << endl; + role = role_ping_out; + } + } + /***********************************/ + // This opens two pipes for these two nodes to communicate + // back and forth. + if (! radioNumber) { + radio.openWritingPipe(addresses[0]); + radio.openReadingPipe(1, addresses[1]); + } else { + radio.openWritingPipe(addresses[1]); + radio.openReadingPipe(1, addresses[0]); + } + radio.startListening(); + radio.writeAckPayload(1, &counter, 1); - radio.stopListening(); // First, stop listening so we can talk. - printf("Now sending %d as payload. ",counter); // Use a simple byte counter as payload - unsigned long time = millis(); // Record the current microsecond count + // forever loop + while (1) { - if ( radio.write(&counter,1) ){ // Send the counter variable to the other radio - if(!radio.available()){ // If nothing in the buffer, we got an ack but it is blank - printf("Got blank response. round-trip delay: %lu ms\n\r",millis()-time); - }else{ - while(radio.available() ){ // If an ack with payload was received - radio.read( &gotByte, 1 ); // Read it, and display the response time - printf("Got response %d, round-trip delay: %lu ms\n\r",gotByte,millis()-time); - counter++; // Increment the counter variable - } - } - }else{ printf("Sending failed.\n\r"); } // If no ack response, sending failed + /****************** Ping Out Role ***************************/ + + if (role == role_ping_out) { // Radio is in ping mode - sleep(1); // Try again later - } + uint8_t gotByte; // Initialize a variable for the incoming response -/****************** Pong Back Role ***************************/ + radio.stopListening(); // First, stop listening so we can talk. + printf("Now sending %d as payload. ", counter); // Use a simple byte counter as payload + unsigned long time = millis(); // Record the current microsecond count - if ( role == role_pong_back ) { - uint8_t pipeNo, gotByte; // Declare variables for the pipe and the byte received - if( radio.available(&pipeNo)){ // Read all available payloads - radio.read( &gotByte, 1 ); - // Since this is a call-response. Respond directly with an ack payload. - gotByte += 1; // Ack payloads are much more efficient than switching to transmit mode to respond to a call - radio.writeAckPayload(pipeNo,&gotByte, 1 ); // This can be commented out to send empty payloads. - printf("Loaded next response %d \n\r", gotByte); - delay(900); //Delay after a response to minimize CPU usage on RPi - //Expects a payload every second - } - } + if (radio.write(&counter, 1)) { // Send the counter variable to the other radio + if (! radio.available()) { // If nothing in the buffer, we got an ack but it is blank + printf("Got blank response. round-trip delay: %lu ms\n\r", millis() - time); + } else { + while (radio.available()) { // If an ack with payload was received + radio.read(&gotByte, 1); // Read it, and display the response time + printf("Got response %d, round-trip delay: %lu ms\n\r", gotByte, millis() - time); + counter ++; // Increment the counter variable + } + } + + } else { + printf("Sending failed.\n\r"); + } // If no ack response, sending failed + + sleep(1); // Try again later + } + + /****************** Pong Back Role ***************************/ + + if (role == role_pong_back) { + uint8_t pipeNo, gotByte; // Declare variables for the pipe and the byte received + if (radio.available(&pipeNo)) { // Read all available payloads + radio.read(&gotByte, 1); + // Since this is a call-response. Respond directly with an ack payload. + gotByte += 1; // Ack payloads are much more efficient than switching to transmit mode to respond to a call + radio.writeAckPayload(pipeNo, &gotByte, 1); // This can be commented out to send empty payloads. + printf("Loaded next response %d \n\r", gotByte); + delay(900); //Delay after a response to minimize CPU usage on RPi + //Expects a payload every second + } + } -} //while 1 + } //while 1 } //main diff --git a/examples_linux/interrupts/gettingstarted_call_response_int.cpp b/examples_linux/interrupts/gettingstarted_call_response_int.cpp index 7d35c4b77..b7d5948be 100644 --- a/examples_linux/interrupts/gettingstarted_call_response_int.cpp +++ b/examples_linux/interrupts/gettingstarted_call_response_int.cpp @@ -28,7 +28,7 @@ using namespace std; /****************** Raspberry Pi ***********************/ -RF24 radio(22,0); //GPIO, SPI-BUS +RF24 radio(22, 0); //GPIO, SPI-BUS /********** User Config *********/ // Assign a unique identifier for this node, 0 or 1. Arduino example uses radioNumber 0 by default. @@ -38,106 +38,110 @@ int interruptPin = 23; // Radio pipe addresses for the 2 nodes to communicate. -const uint8_t addresses[][6] = {"1Node","2Node"}; +const uint8_t addresses[][6] = {"1Node", "2Node"}; volatile bool role_ping_out = 1, role_pong_back = 0, role = 0; uint8_t counter = 1; // A single byte to keep track of the data being sent back and forth volatile bool gotResponse = false; -void intHandler(){ - - if ( role == role_pong_back ) { - uint8_t pipeNo, gotByte; // Declare variables for the pipe and the byte received - if( radio.available(&pipeNo)){ // Read all available payloads - radio.read( &gotByte, 1 ); - // Since this is a call-response. Respond directly with an ack payload. - gotByte += 1; // Ack payloads are much more efficient than switching to transmit mode to respond to a call - radio.writeAckPayload(pipeNo,&gotByte, 1 ); // This can be commented out to send empty payloads. - printf("Loaded next response %d \n\r", gotByte); - +void intHandler() +{ + + if (role == role_pong_back) { + uint8_t pipeNo, gotByte; // Declare variables for the pipe and the byte received + if (radio.available(&pipeNo)) { // Read all available payloads + radio.read(&gotByte, 1); + // Since this is a call-response. Respond directly with an ack payload. + gotByte += 1; // Ack payloads are much more efficient than switching to transmit mode to respond to a call + radio.writeAckPayload(pipeNo, &gotByte, 1); // This can be commented out to send empty payloads. + printf("Loaded next response %d \n\r", gotByte); + + } } - } } -int main(int argc, char** argv){ - - - cout << "RPi/RF24/examples/gettingstarted_call_response_int\n"; - radio.begin(); - radio.enableAckPayload(); // Allow optional ack payloads - radio.enableDynamicPayloads(); - radio.printDetails(); // Dump the configuration of the rf unit for debugging - - -/********* Role chooser ***********/ - - printf("\n ************ Role Setup ***********\n"); - string input = ""; - char myChar = {0}; - cout << "Choose a role: Enter 0 for pong_back, 1 for ping_out (CTRL+C to exit)\n>"; - getline(cin,input); - - if(input.length() == 1) { - myChar = input[0]; - if(myChar == '0'){ - cout << "Role: Pong Back, awaiting transmission " << endl << endl; - }else{ cout << "Role: Ping Out, starting transmission " << endl << endl; - role = role_ping_out; - } - } -/***********************************/ - // This opens two pipes for these two nodes to communicate - // back and forth. - if ( !radioNumber ) { - radio.openWritingPipe(addresses[0]); - radio.openReadingPipe(1,addresses[1]); - }else{ - radio.openWritingPipe(addresses[1]); - radio.openReadingPipe(1,addresses[0]); +int main(int argc, char** argv) +{ + + cout << "RPi/RF24/examples/gettingstarted_call_response_int\n"; + radio.begin(); + radio.enableAckPayload(); // Allow optional ack payloads + radio.enableDynamicPayloads(); + radio.printDetails(); // Dump the configuration of the rf unit for debugging + + + /********* Role chooser ***********/ + + printf("\n ************ Role Setup ***********\n"); + string input = ""; + char myChar = {0}; + cout << "Choose a role: Enter 0 for pong_back, 1 for ping_out (CTRL+C to exit)\n>"; + getline(cin, input); + + if (input.length() == 1) { + myChar = input[0]; + if (myChar == '0') { + cout << "Role: Pong Back, awaiting transmission " << endl << endl; + } else { + cout << "Role: Ping Out, starting transmission " << endl << endl; + role = role_ping_out; + } + } + /***********************************/ + // This opens two pipes for these two nodes to communicate + // back and forth. + if (! radioNumber) { + radio.openWritingPipe(addresses[0]); + radio.openReadingPipe(1, addresses[1]); + } else { + radio.openWritingPipe(addresses[1]); + radio.openReadingPipe(1, addresses[0]); } - radio.startListening(); - radio.writeAckPayload(1,&counter,1); - - radio.maskIRQ(1,1,0); //Mask tx_ok & tx_fail interrupts + radio.startListening(); + radio.writeAckPayload(1, &counter, 1); + + radio.maskIRQ(1, 1, 0); //Mask tx_ok & tx_fail interrupts attachInterrupt(interruptPin, INT_EDGE_FALLING, intHandler); //Attach interrupt to bcm pin 23 - -// forever loop -while (1){ + // forever loop + while (1) { -/****************** Ping Out Role ***************************/ - if (role == role_ping_out){ // Radio is in ping mode + /****************** Ping Out Role ***************************/ - uint8_t gotByte; // Initialize a variable for the incoming response + if (role == role_ping_out) { // Radio is in ping mode - radio.stopListening(); // First, stop listening so we can talk. - printf("Now sending %d as payload. ",counter); // Use a simple byte counter as payload - unsigned long time = millis(); // Record the current microsecond count + uint8_t gotByte; // Initialize a variable for the incoming response - if ( radio.write(&counter,1) ){ // Send the counter variable to the other radio - if(!radio.available()){ // If nothing in the buffer, we got an ack but it is blank - printf("Got blank response. round-trip delay: %lu ms\n\r",millis()-time); - }else{ - - while(radio.available() ){ // If an ack with payload was received - radio.read( &gotByte, 1 ); // Read it, and display the response time - printf("Got response %d, round-trip delay: %lu ms\n\r",gotByte,millis()-time); - counter++; // Increment the counter variable - } - } + radio.stopListening(); // First, stop listening so we can talk. + printf("Now sending %d as payload. ", counter); // Use a simple byte counter as payload + unsigned long time = millis(); // Record the current microsecond count - }else{ printf("Sending failed.\n\r"); } // If no ack response, sending failed + if (radio.write(&counter, 1)) { // Send the counter variable to the other radio + if (! radio.available()) { // If nothing in the buffer, we got an ack but it is blank + printf("Got blank response. round-trip delay: %lu ms\n\r", millis() - time); + } else { - sleep(1); // Try again later - } + while (radio.available()) { // If an ack with payload was received + radio.read(&gotByte, 1); // Read it, and display the response time + printf("Got response %d, round-trip delay: %lu ms\n\r", gotByte, millis() - time); + counter ++; // Increment the counter variable + } + } + + } else { + printf("Sending failed.\n\r"); + } // If no ack response, sending failed + + sleep(1); // Try again later + } -/****************** Pong Back Role ***************************/ + /****************** Pong Back Role ***************************/ -} //while 1 + } //while 1 } //main diff --git a/examples_linux/interrupts/gettingstarted_call_response_int2.cpp b/examples_linux/interrupts/gettingstarted_call_response_int2.cpp index 730a94720..986f4bf32 100644 --- a/examples_linux/interrupts/gettingstarted_call_response_int2.cpp +++ b/examples_linux/interrupts/gettingstarted_call_response_int2.cpp @@ -28,7 +28,7 @@ using namespace std; /****************** Raspberry Pi ***********************/ -RF24 radio(22,0); +RF24 radio(22, 0); /********** User Config *********/ // Assign a unique identifier for this node, 0 or 1. Arduino example uses radioNumber 0 by default. @@ -38,118 +38,119 @@ int interruptPin = 23; // Radio pipe addresses for the 2 nodes to communicate. -const uint8_t addresses[][6] = {"1Node","2Node"}; +const uint8_t addresses[][6] = {"1Node", "2Node"}; bool role_ping_out = 1, role_pong_back = 0, role = 0; uint8_t counter = 1; // A single byte to keep track of the data being sent back and forth uint32_t timer = 0; -void intHandler(){ - - bool tx_ok,tx_fail,rx; - radio.whatHappened(tx_ok,tx_fail,rx); - - if(tx_fail){ - printf("Sending failed.\n\r"); - } - - if(role == role_ping_out && tx_ok){ - if(!radio.available()){ - printf("Got blank response. round-trip delay: %u ms\n\r",millis()-timer); +void intHandler() +{ + + bool tx_ok, tx_fail, rx; + radio.whatHappened(tx_ok, tx_fail, rx); + + if (tx_fail) { + printf("Sending failed.\n\r"); } - } - - if(role == role_ping_out ){ - while(radio.available() ){ - uint8_t gotByte; - radio.read( &gotByte, 1 ); - printf("Got response %d, round-trip delay: %u ms\n\r",gotByte,millis()-timer); - counter++; + + if (role == role_ping_out && tx_ok) { + if (! radio.available()) { + printf("Got blank response. round-trip delay: %u ms\n\r", millis() - timer); + } + } + + if (role == role_ping_out) { + while (radio.available()) { + uint8_t gotByte; + radio.read(&gotByte, 1); + printf("Got response %d, round-trip delay: %u ms\n\r", gotByte, millis() - timer); + counter ++; + } + } + + if (role == role_pong_back) { + if (tx_ok) { + printf("Ack Payload Sent\n"); + } + uint8_t pipeNo, gotByte; + if (radio.available(&pipeNo)) { + radio.read(&gotByte, 1); + + gotByte += 1; + radio.writeAckPayload(pipeNo, &gotByte, 1); + printf("Loaded next response %d \n\r", gotByte); + + } } - } - - if ( role == role_pong_back){ - if(tx_ok) { - printf("Ack Payload Sent\n"); - } - uint8_t pipeNo, gotByte; - if( radio.available(&pipeNo)){ - radio.read( &gotByte, 1 ); - - gotByte += 1; - radio.writeAckPayload(pipeNo,&gotByte, 1 ); - printf("Loaded next response %d \n\r", gotByte); - - } - } - + } +int main(int argc, char** argv) +{ + + cout << "RPi/RF24/examples/gettingstarted_call_response\n"; + radio.begin(); + radio.enableAckPayload(); // Allow optional ack payloads + radio.enableDynamicPayloads(); + radio.printDetails(); // Dump the configuration of the rf unit for debugging + + + /********* Role chooser ***********/ -int main(int argc, char** argv){ - - - cout << "RPi/RF24/examples/gettingstarted_call_response\n"; - radio.begin(); - radio.enableAckPayload(); // Allow optional ack payloads - radio.enableDynamicPayloads(); - radio.printDetails(); // Dump the configuration of the rf unit for debugging - - -/********* Role chooser ***********/ - - printf("\n ************ Role Setup ***********\n"); - string input = ""; - char myChar = {0}; - cout << "Choose a role: Enter 0 for pong_back, 1 for ping_out (CTRL+C to exit)\n>"; - getline(cin,input); - - if(input.length() == 1) { - myChar = input[0]; - if(myChar == '0'){ - cout << "Role: Pong Back, awaiting transmission " << endl << endl; - }else{ cout << "Role: Ping Out, starting transmission " << endl << endl; - role = role_ping_out; - } - } -/***********************************/ - // This opens two pipes for these two nodes to communicate - // back and forth. - if ( !radioNumber ) { - radio.openWritingPipe(addresses[0]); - radio.openReadingPipe(1,addresses[1]); - }else{ - radio.openWritingPipe(addresses[1]); - radio.openReadingPipe(1,addresses[0]); + printf("\n ************ Role Setup ***********\n"); + string input = ""; + char myChar = {0}; + cout << "Choose a role: Enter 0 for pong_back, 1 for ping_out (CTRL+C to exit)\n>"; + getline(cin, input); + + if (input.length() == 1) { + myChar = input[0]; + if (myChar == '0') { + cout << "Role: Pong Back, awaiting transmission " << endl << endl; + } else { + cout << "Role: Ping Out, starting transmission " << endl << endl; + role = role_ping_out; + } + } + /***********************************/ + // This opens two pipes for these two nodes to communicate + // back and forth. + if (! radioNumber) { + radio.openWritingPipe(addresses[0]); + radio.openReadingPipe(1, addresses[1]); + } else { + radio.openWritingPipe(addresses[1]); + radio.openReadingPipe(1, addresses[0]); } - radio.startListening(); - radio.writeAckPayload(1,&counter,1); - + radio.startListening(); + radio.writeAckPayload(1, &counter, 1); + attachInterrupt(interruptPin, INT_EDGE_FALLING, intHandler); //Attach interrupt to bcm pin 23 - -// forever loop -while (1){ + + // forever loop + while (1) { -/****************** Ping Out Role ***************************/ + /****************** Ping Out Role ***************************/ - if (role == role_ping_out){ // Radio is in ping mode + if (role == role_ping_out) { // Radio is in ping mode - //uint8_t gotByte; // Initialize a variable for the incoming response + //uint8_t gotByte; // Initialize a variable for the incoming response - radio.stopListening(); // First, stop listening so we can talk. - printf("Now sending %d as payload. ",counter); // Use a simple byte counter as payload - timer = millis(); // Record the current microsecond count + radio.stopListening(); // First, stop listening so we can talk. + printf("Now sending %d as payload. ", counter); // Use a simple byte counter as payload + timer = millis(); // Record the current microsecond count - radio.startWrite(&counter,1,false); // Send the counter variable to the other radio - sleep(1); // Try again later - } + radio.startWrite(&counter, 1, false); // Send the counter variable to the other radio + sleep(1); // Try again later + } -/****************** Pong Back Role ***************************/ + /****************** Pong Back Role ***************************/ -} //while 1 + } //while 1 } //main diff --git a/examples_linux/interrupts/pingpair_dyn_int.cpp b/examples_linux/interrupts/pingpair_dyn_int.cpp index c3598f9f6..3bea46749 100644 --- a/examples_linux/interrupts/pingpair_dyn_int.cpp +++ b/examples_linux/interrupts/pingpair_dyn_int.cpp @@ -14,7 +14,6 @@ #include #include - using namespace std; // // Hardware configuration @@ -22,162 +21,156 @@ using namespace std; /****************** Raspberry Pi ***********************/ -RF24 radio(22,0); // CE GPIO, CSN SPI-BUS +RF24 radio(22, 0); // CE GPIO, CSN SPI-BUS int interruptPin = 23; // GPIO pin for interrupts /**************************************************************/ // Radio pipe addresses for the 2 nodes to communicate. -const uint64_t pipes[2] = { 0xF0F0F0F0E1LL, 0xF0F0F0F0D2LL }; - - +const uint64_t pipes[2] = {0xF0F0F0F0E1LL, 0xF0F0F0F0D2LL}; const int min_payload_size = 4; const int max_payload_size = 32; const int payload_size_increments_by = 1; int next_payload_size = min_payload_size; -char receive_payload[max_payload_size+1]; // +1 to allow room for a terminating NULL char +char receive_payload[max_payload_size + 1]; // +1 to allow room for a terminating NULL char bool role_ping_out = 1, role_pong_back = 0; bool role = 0; -void intHandler(){ - // - // Pong back role. Receive each packet, dump it out, and send it back - // - - if ( role == role_pong_back ) - { - // if there is data ready - if ( radio.available() ) - { - // Dump the payloads until we've gotten everything - uint8_t len=0; - - while (radio.available()) - { - // Fetch the payload, and see if this was the last one. - len = radio.getDynamicPayloadSize(); - radio.read( receive_payload, len ); - - // Put a zero at the end for easy printing - receive_payload[len] = 0; - - // Spew it - printf("Got payload size=%i value=%s\n\r",len,receive_payload); - } - - // First, stop listening so we can talk - radio.stopListening(); - - // Send the final one back. - radio.write( receive_payload, len ); - printf("Sent response.\n\r"); - - // Now, resume listening so we catch the next packets. - radio.startListening(); +void intHandler() +{ + // + // Pong back role. Receive each packet, dump it out, and send it back + // + + if (role == role_pong_back) { + // if there is data ready + if (radio.available()) { + // Dump the payloads until we've gotten everything + uint8_t len = 0; + + while (radio.available()) { + // Fetch the payload, and see if this was the last one. + len = radio.getDynamicPayloadSize(); + radio.read(receive_payload, len); + + // Put a zero at the end for easy printing + receive_payload[len] = 0; + + // Spew it + printf("Got payload size=%i value=%s\n\r", len, receive_payload); + } + + // First, stop listening so we can talk + radio.stopListening(); + + // Send the final one back. + radio.write(receive_payload, len); + printf("Sent response.\n\r"); + + // Now, resume listening so we catch the next packets. + radio.startListening(); + } } - } } +int main(int argc, char** argv) +{ -int main(int argc, char** argv){ + // Print preamble: + cout << "RF24/examples/pingpair_dyn/\n"; - // Print preamble: - cout << "RF24/examples/pingpair_dyn/\n"; + // Setup and configure rf radio + radio.begin(); + radio.enableDynamicPayloads(); + radio.setRetries(5, 15); + radio.printDetails(); - // Setup and configure rf radio - radio.begin(); - radio.enableDynamicPayloads(); - radio.setRetries(5,15); - radio.printDetails(); + /********* Role chooser ***********/ -/********* Role chooser ***********/ + printf("\n ************ Role Setup ***********\n"); + string input = ""; + char myChar = {0}; + cout << "Choose a role: Enter 0 for receiver, 1 for transmitter (CTRL+C to exit) \n>"; + getline(cin, input); - printf("\n ************ Role Setup ***********\n"); - string input = ""; - char myChar = {0}; - cout << "Choose a role: Enter 0 for receiver, 1 for transmitter (CTRL+C to exit) \n>"; - getline(cin,input); - - if(input.length() == 1) { - myChar = input[0]; - if(myChar == '0'){ - cout << "Role: Pong Back, awaiting transmission " << endl << endl; - }else{ cout << "Role: Ping Out, starting transmission " << endl << endl; - role = role_ping_out; - } - } -/***********************************/ + if (input.length() == 1) { + myChar = input[0]; + if (myChar == '0') { + cout << "Role: Pong Back, awaiting transmission " << endl << endl; + } else { + cout << "Role: Ping Out, starting transmission " << endl << endl; + role = role_ping_out; + } + } + /***********************************/ - if ( role == role_ping_out ) { - radio.openWritingPipe(pipes[0]); - radio.openReadingPipe(1,pipes[1]); + if (role == role_ping_out) { + radio.openWritingPipe(pipes[0]); + radio.openReadingPipe(1, pipes[1]); } else { - radio.openWritingPipe(pipes[1]); - radio.openReadingPipe(1,pipes[0]); - radio.startListening(); + radio.openWritingPipe(pipes[1]); + radio.openReadingPipe(1, pipes[0]); + radio.startListening(); } attachInterrupt(interruptPin, INT_EDGE_FALLING, intHandler); //Attach interrupt to bcm pin 23 -// forever loop - while (1) - { + // forever loop + while (1) { -if (role == role_ping_out) - { - // The payload will always be the same, what will change is how much of it we send. - static char send_payload[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ789012"; + if (role == role_ping_out) { + // The payload will always be the same, what will change is how much of it we send. + static char send_payload[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ789012"; - // First, stop listening so we can talk. - radio.stopListening(); + // First, stop listening so we can talk. + radio.stopListening(); - // Take the time, and send it. This will block until complete - printf("Now sending length %i...",next_payload_size); - radio.write( send_payload, next_payload_size ); + // Take the time, and send it. This will block until complete + printf("Now sending length %i...", next_payload_size); + radio.write(send_payload, next_payload_size); - // Now, continue listening - radio.startListening(); + // Now, continue listening + radio.startListening(); - // Wait here until we get a response, or timeout - unsigned long started_waiting_at = millis(); - bool timeout = false; - while ( ! radio.available() && ! timeout ) - if (millis() - started_waiting_at > 500 ) - timeout = true; + // Wait here until we get a response, or timeout + unsigned long started_waiting_at = millis(); + bool timeout = false; + while (! radio.available() && ! timeout) + if (millis() - started_waiting_at > 500) { + timeout = true; + } - // Describe the results - if ( timeout ) - { - printf("Failed, response timed out.\n\r"); - } - else - { - // Grab the response, compare, and send to debugging spew - uint8_t len = radio.getDynamicPayloadSize(); - radio.read( receive_payload, len ); + // Describe the results + if (timeout) { + printf("Failed, response timed out.\n\r"); + } else { + // Grab the response, compare, and send to debugging spew + uint8_t len = radio.getDynamicPayloadSize(); + radio.read(receive_payload, len); - // Put a zero at the end for easy printing - receive_payload[len] = 0; + // Put a zero at the end for easy printing + receive_payload[len] = 0; - // Spew it - printf("Got response size=%i value=%s\n\r",len,receive_payload); - } + // Spew it + printf("Got response size=%i value=%s\n\r", len, receive_payload); + } - // Update size for next time. - next_payload_size += payload_size_increments_by; - if ( next_payload_size > max_payload_size ) - next_payload_size = min_payload_size; + // Update size for next time. + next_payload_size += payload_size_increments_by; + if (next_payload_size > max_payload_size) { + next_payload_size = min_payload_size; + } - // Try again 1s later - delay(100); - } + // Try again 1s later + delay(100); + } -} + } } diff --git a/examples_linux/interrupts/transfer_interrupt.cpp b/examples_linux/interrupts/transfer_interrupt.cpp index 3fb2528db..b0a964864 100644 --- a/examples_linux/interrupts/transfer_interrupt.cpp +++ b/examples_linux/interrupts/transfer_interrupt.cpp @@ -66,127 +66,125 @@ RF24 radio(RPI_V2_GPIO_P1_15, RPI_V2_GPIO_P1_24, BCM2835_SPI_SPEED_8MHZ); /**************************************************************/ // Radio pipe addresses for the 2 nodes to communicate. -const uint64_t addresses[2] = { 0xABCDABCD71LL, 0x544d52687CLL }; - +const uint64_t addresses[2] = {0xABCDABCD71LL, 0x544d52687CLL}; uint8_t data[32]; -unsigned long startTime, stopTime, counter, rxTimer=0; +unsigned long startTime, stopTime, counter, rxTimer = 0; void intHandler() { - //Read as long data is available - //Single interrupts may be lost if a lot of data comes in. - while(radio.available()) - { - radio.read(&data,32); - counter++; + //Read as long data is available + //Single interrupts may be lost if a lot of data comes in. + while (radio.available()) { + radio.read(&data, 32); + counter ++; } } -int main(int argc, char** argv){ - - bool role_ping_out = 1, role_pong_back = 0; - bool role = 0; - - // Print preamble: - - cout << "RF24/examples/Transfer/\n"; - - radio.begin(); // Setup and configure rf radio - radio.setChannel(1); - radio.setPALevel(RF24_PA_MAX); - radio.setDataRate(RF24_1MBPS); - radio.setAutoAck(1); // Ensure autoACK is enabled - radio.setRetries(2,15); // Optionally, increase the delay between retries & # of retries - radio.setCRCLength(RF24_CRC_8); // Use 8-bit CRC for performance - radio.printDetails(); -/********* Role chooser ***********/ - - printf("\n ************ Role Setup ***********\n"); - string input = ""; - char myChar = {0}; - cout << "Choose a role: Enter 0 for receiver, 1 for transmitter (CTRL+C to exit)\n>"; - getline(cin,input); - - attachInterrupt(23, INT_EDGE_FALLING, intHandler); //Attach interrupt to bcm pin 23 - - if(input.length() == 1) { - myChar = input[0]; - if(myChar == '0'){ - cout << "Role: Pong Back, awaiting transmission " << endl << endl; - }else{ cout << "Role: Ping Out, starting transmission " << endl << endl; - role = role_ping_out; - } - } -/***********************************/ - - if ( role == role_ping_out ) { - radio.openWritingPipe(addresses[1]); - radio.openReadingPipe(1,addresses[0]); - radio.stopListening(); - } else { - radio.openWritingPipe(addresses[0]); - radio.openReadingPipe(1,addresses[1]); - radio.startListening(); +int main(int argc, char** argv) +{ + + bool role_ping_out = 1, role_pong_back = 0; + bool role = 0; + + // Print preamble: + + cout << "RF24/examples/Transfer/\n"; + + radio.begin(); // Setup and configure rf radio + radio.setChannel(1); + radio.setPALevel(RF24_PA_MAX); + radio.setDataRate(RF24_1MBPS); + radio.setAutoAck(1); // Ensure autoACK is enabled + radio.setRetries(2, 15); // Optionally, increase the delay between retries & # of retries + radio.setCRCLength(RF24_CRC_8); // Use 8-bit CRC for performance + radio.printDetails(); + /********* Role chooser ***********/ + + printf("\n ************ Role Setup ***********\n"); + string input = ""; + char myChar = {0}; + cout << "Choose a role: Enter 0 for receiver, 1 for transmitter (CTRL+C to exit)\n>"; + getline(cin, input); + + attachInterrupt(23, INT_EDGE_FALLING, intHandler); //Attach interrupt to bcm pin 23 + + if (input.length() == 1) { + myChar = input[0]; + if (myChar == '0') { + cout << "Role: Pong Back, awaiting transmission " << endl << endl; + } else { + cout << "Role: Ping Out, starting transmission " << endl << endl; + role = role_ping_out; + } } + /***********************************/ + if (role == role_ping_out) { + radio.openWritingPipe(addresses[1]); + radio.openReadingPipe(1, addresses[0]); + radio.stopListening(); + } else { + radio.openWritingPipe(addresses[0]); + radio.openReadingPipe(1, addresses[1]); + radio.startListening(); + } - for(int i=0; i<32; i++){ - data[i] = rand() % 255; //Load the buffer with random data - } + for (int i = 0; i < 32; i ++) { + data[i] = rand() % 255; //Load the buffer with random data + } // forever loop - while (1) - { - if (role == role_ping_out){ - sleep(2); - printf("Initiating Basic Data Transfer\n\r"); - - long int cycles = 10000; //Change this to a higher or lower number. - - // unsigned long pauseTime = millis(); //Uncomment if autoAck == 1 ( NOACK ) - startTime = millis(); - - for(int i=0; i 3){ // Need to drop out of TX mode every 4ms if sending a steady stream of multicast data - pauseTime = millis(); - radio.txStandBy(); // This gives the PLL time to sync back up - } - */ - } - stopTime = millis(); - - if(!radio.txStandBy()){ counter+=3; } - - float numBytes = cycles*32; - float rate = numBytes / (stopTime - startTime); - - printf("Transfer complete at %.2f KB/s \n\r",rate); - printf("%lu of %lu Packets Failed to Send\n\r",counter,cycles); - counter = 0; - - } - - - if(role == role_pong_back) - { - if(millis() - rxTimer > 1000){ - rxTimer = millis(); - printf("Rate: "); - float numBytes = counter*32; - printf("%.2f KB/s \n\r",numBytes/1000); - printf("Payload Count: %lu \n\r", counter); - counter = 0; + while (1) { + if (role == role_ping_out) { + sleep(2); + printf("Initiating Basic Data Transfer\n\r"); + + long int cycles = 10000; //Change this to a higher or lower number. + + // unsigned long pauseTime = millis(); //Uncomment if autoAck == 1 ( NOACK ) + startTime = millis(); + + for (int i = 0; i < cycles; i ++) { //Loop through a number of cycles + data[0] = i; //Change the first byte of the payload for identification + if (! radio.writeFast(&data, 32)) { //Write to the FIFO buffers + counter ++; //Keep count of failed payloads + } + + + //This is only required when NO ACK ( enableAutoAck(0) ) payloads are used + /* if(millis() - pauseTime > 3){ // Need to drop out of TX mode every 4ms if sending a steady stream of multicast data + pauseTime = millis(); + radio.txStandBy(); // This gives the PLL time to sync back up + } + */ + } + stopTime = millis(); + + if (! radio.txStandBy()) { + counter += 3; + } + + float numBytes = cycles * 32; + float rate = numBytes / (stopTime - startTime); + + printf("Transfer complete at %.2f KB/s \n\r", rate); + printf("%lu of %lu Packets Failed to Send\n\r", counter, cycles); + counter = 0; + } - delay(2); - } - -} // loop + + if (role == role_pong_back) { + if (millis() - rxTimer > 1000) { + rxTimer = millis(); + printf("Rate: "); + float numBytes = counter * 32; + printf("%.2f KB/s \n\r", numBytes / 1000); + printf("Payload Count: %lu \n\r", counter); + counter = 0; + } + delay(2); + } + + } // loop } // main diff --git a/examples_linux/pingpair_dyn.cpp b/examples_linux/pingpair_dyn.cpp index 7cae0d355..d6cc1748a 100644 --- a/examples_linux/pingpair_dyn.cpp +++ b/examples_linux/pingpair_dyn.cpp @@ -14,7 +14,6 @@ #include #include "./RF24.h" - using namespace std; // // Hardware configuration @@ -62,150 +61,144 @@ RF24 radio(RPI_V2_GPIO_P1_15, RPI_V2_GPIO_P1_24, BCM2835_SPI_SPEED_8MHZ); /**************************************************************/ // Radio pipe addresses for the 2 nodes to communicate. -const uint64_t pipes[2] = { 0xF0F0F0F0E1LL, 0xF0F0F0F0D2LL }; - - +const uint64_t pipes[2] = {0xF0F0F0F0E1LL, 0xF0F0F0F0D2LL}; const int min_payload_size = 4; const int max_payload_size = 32; const int payload_size_increments_by = 1; int next_payload_size = min_payload_size; -char receive_payload[max_payload_size+1]; // +1 to allow room for a terminating NULL char - -int main(int argc, char** argv){ +char receive_payload[max_payload_size + 1]; // +1 to allow room for a terminating NULL char - bool role_ping_out = 1, role_pong_back = 0; - bool role = 0; +int main(int argc, char** argv) +{ - // Print preamble: - cout << "RF24/examples/pingpair_dyn/\n"; + bool role_ping_out = 1, role_pong_back = 0; + bool role = 0; - // Setup and configure rf radio - radio.begin(); - radio.enableDynamicPayloads(); - radio.setRetries(5,15); - radio.printDetails(); + // Print preamble: + cout << "RF24/examples/pingpair_dyn/\n"; + // Setup and configure rf radio + radio.begin(); + radio.enableDynamicPayloads(); + radio.setRetries(5, 15); + radio.printDetails(); -/********* Role chooser ***********/ - printf("\n ************ Role Setup ***********\n"); - string input = ""; - char myChar = {0}; - cout << "Choose a role: Enter 0 for receiver, 1 for transmitter (CTRL+C to exit) \n>"; - getline(cin,input); + /********* Role chooser ***********/ - if(input.length() == 1) { - myChar = input[0]; - if(myChar == '0'){ - cout << "Role: Pong Back, awaiting transmission " << endl << endl; - }else{ cout << "Role: Ping Out, starting transmission " << endl << endl; - role = role_ping_out; - } - } -/***********************************/ + printf("\n ************ Role Setup ***********\n"); + string input = ""; + char myChar = {0}; + cout << "Choose a role: Enter 0 for receiver, 1 for transmitter (CTRL+C to exit) \n>"; + getline(cin, input); - if ( role == role_ping_out ) { - radio.openWritingPipe(pipes[0]); - radio.openReadingPipe(1,pipes[1]); - } else { - radio.openWritingPipe(pipes[1]); - radio.openReadingPipe(1,pipes[0]); - radio.startListening(); + if (input.length() == 1) { + myChar = input[0]; + if (myChar == '0') { + cout << "Role: Pong Back, awaiting transmission " << endl << endl; + } else { + cout << "Role: Ping Out, starting transmission " << endl << endl; + role = role_ping_out; + } } + /***********************************/ - -// forever loop - while (1) - { - -if (role == role_ping_out) - { - // The payload will always be the same, what will change is how much of it we send. - static char send_payload[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ789012"; - - // First, stop listening so we can talk. - radio.stopListening(); - - // Take the time, and send it. This will block until complete - printf("Now sending length %i...",next_payload_size); - radio.write( send_payload, next_payload_size ); - - // Now, continue listening - radio.startListening(); - - // Wait here until we get a response, or timeout - unsigned long started_waiting_at = millis(); - bool timeout = false; - while ( ! radio.available() && ! timeout ) - if (millis() - started_waiting_at > 500 ) - timeout = true; - - // Describe the results - if ( timeout ) - { - printf("Failed, response timed out.\n\r"); + if (role == role_ping_out) { + radio.openWritingPipe(pipes[0]); + radio.openReadingPipe(1, pipes[1]); + } else { + radio.openWritingPipe(pipes[1]); + radio.openReadingPipe(1, pipes[0]); + radio.startListening(); } - else - { - // Grab the response, compare, and send to debugging spew - uint8_t len = radio.getDynamicPayloadSize(); - radio.read( receive_payload, len ); - - // Put a zero at the end for easy printing - receive_payload[len] = 0; - // Spew it - printf("Got response size=%i value=%s\n\r",len,receive_payload); - } - // Update size for next time. - next_payload_size += payload_size_increments_by; - if ( next_payload_size > max_payload_size ) - next_payload_size = min_payload_size; - - // Try again 1s later - delay(100); - } - - // - // Pong back role. Receive each packet, dump it out, and send it back - // - - if ( role == role_pong_back ) - { - // if there is data ready - if ( radio.available() ) - { - // Dump the payloads until we've gotten everything - uint8_t len; - - while (radio.available()) - { - // Fetch the payload, and see if this was the last one. - len = radio.getDynamicPayloadSize(); - radio.read( receive_payload, len ); - - // Put a zero at the end for easy printing - receive_payload[len] = 0; - - // Spew it - printf("Got payload size=%i value=%s\n\r",len,receive_payload); - } - - // First, stop listening so we can talk - radio.stopListening(); - - // Send the final one back. - radio.write( receive_payload, len ); - printf("Sent response.\n\r"); - - // Now, resume listening so we catch the next packets. - radio.startListening(); + // forever loop + while (1) { + + if (role == role_ping_out) { + // The payload will always be the same, what will change is how much of it we send. + static char send_payload[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ789012"; + + // First, stop listening so we can talk. + radio.stopListening(); + + // Take the time, and send it. This will block until complete + printf("Now sending length %i...", next_payload_size); + radio.write(send_payload, next_payload_size); + + // Now, continue listening + radio.startListening(); + + // Wait here until we get a response, or timeout + unsigned long started_waiting_at = millis(); + bool timeout = false; + while (! radio.available() && ! timeout) + if (millis() - started_waiting_at > 500) { + timeout = true; + } + + // Describe the results + if (timeout) { + printf("Failed, response timed out.\n\r"); + } else { + // Grab the response, compare, and send to debugging spew + uint8_t len = radio.getDynamicPayloadSize(); + radio.read(receive_payload, len); + + // Put a zero at the end for easy printing + receive_payload[len] = 0; + + // Spew it + printf("Got response size=%i value=%s\n\r", len, receive_payload); + } + + // Update size for next time. + next_payload_size += payload_size_increments_by; + if (next_payload_size > max_payload_size) { + next_payload_size = min_payload_size; + } + + // Try again 1s later + delay(100); + } + + // + // Pong back role. Receive each packet, dump it out, and send it back + // + + if (role == role_pong_back) { + // if there is data ready + if (radio.available()) { + // Dump the payloads until we've gotten everything + uint8_t len; + + while (radio.available()) { + // Fetch the payload, and see if this was the last one. + len = radio.getDynamicPayloadSize(); + radio.read(receive_payload, len); + + // Put a zero at the end for easy printing + receive_payload[len] = 0; + + // Spew it + printf("Got payload size=%i value=%s\n\r", len, receive_payload); + } + + // First, stop listening so we can talk + radio.stopListening(); + + // Send the final one back. + radio.write(receive_payload, len); + printf("Sent response.\n\r"); + + // Now, resume listening so we catch the next packets. + radio.startListening(); + } + } } - } -} } diff --git a/examples_linux/transfer.cpp b/examples_linux/transfer.cpp index 584454a84..5b2300963 100644 --- a/examples_linux/transfer.cpp +++ b/examples_linux/transfer.cpp @@ -66,118 +66,119 @@ RF24 radio(RPI_V2_GPIO_P1_15, RPI_V2_GPIO_P1_24, BCM2835_SPI_SPEED_8MHZ); /**************************************************************/ // Radio pipe addresses for the 2 nodes to communicate. -const uint64_t addresses[2] = { 0xABCDABCD71LL, 0x544d52687CLL }; - +const uint64_t addresses[2] = {0xABCDABCD71LL, 0x544d52687CLL}; uint8_t data[32]; -unsigned long startTime, stopTime, counter, rxTimer=0; - -int main(int argc, char** argv){ - - bool role_ping_out = 1, role_pong_back = 0; - bool role = 0; - - // Print preamble: - - cout << "RF24/examples/Transfer/\n"; - - radio.begin(); // Setup and configure rf radio - radio.setChannel(1); - radio.setPALevel(RF24_PA_MAX); - radio.setDataRate(RF24_1MBPS); - radio.setAutoAck(1); // Ensure autoACK is enabled - radio.setRetries(2,15); // Optionally, increase the delay between retries & # of retries - radio.setCRCLength(RF24_CRC_8); // Use 8-bit CRC for performance - radio.printDetails(); -/********* Role chooser ***********/ - - printf("\n ************ Role Setup ***********\n"); - string input = ""; - char myChar = {0}; - cout << "Choose a role: Enter 0 for receiver, 1 for transmitter (CTRL+C to exit)\n>"; - getline(cin,input); - - if(input.length() == 1) { - myChar = input[0]; - if(myChar == '0'){ - cout << "Role: Pong Back, awaiting transmission " << endl << endl; - }else{ cout << "Role: Ping Out, starting transmission " << endl << endl; - role = role_ping_out; - } - } -/***********************************/ - - if ( role == role_ping_out ) { - radio.openWritingPipe(addresses[1]); - radio.openReadingPipe(1,addresses[0]); - radio.stopListening(); - } else { - radio.openWritingPipe(addresses[0]); - radio.openReadingPipe(1,addresses[1]); - radio.startListening(); +unsigned long startTime, stopTime, counter, rxTimer = 0; + +int main(int argc, char** argv) +{ + + bool role_ping_out = 1, role_pong_back = 0; + bool role = 0; + + // Print preamble: + + cout << "RF24/examples/Transfer/\n"; + + radio.begin(); // Setup and configure rf radio + radio.setChannel(1); + radio.setPALevel(RF24_PA_MAX); + radio.setDataRate(RF24_1MBPS); + radio.setAutoAck(1); // Ensure autoACK is enabled + radio.setRetries(2, 15); // Optionally, increase the delay between retries & # of retries + radio.setCRCLength(RF24_CRC_8); // Use 8-bit CRC for performance + radio.printDetails(); + /********* Role chooser ***********/ + + printf("\n ************ Role Setup ***********\n"); + string input = ""; + char myChar = {0}; + cout << "Choose a role: Enter 0 for receiver, 1 for transmitter (CTRL+C to exit)\n>"; + getline(cin, input); + + if (input.length() == 1) { + myChar = input[0]; + if (myChar == '0') { + cout << "Role: Pong Back, awaiting transmission " << endl << endl; + } else { + cout << "Role: Ping Out, starting transmission " << endl << endl; + role = role_ping_out; + } } + /***********************************/ + if (role == role_ping_out) { + radio.openWritingPipe(addresses[1]); + radio.openReadingPipe(1, addresses[0]); + radio.stopListening(); + } else { + radio.openWritingPipe(addresses[0]); + radio.openReadingPipe(1, addresses[1]); + radio.startListening(); + } - for(int i=0; i<32; i++){ - data[i] = rand() % 255; //Load the buffer with random data - } + for (int i = 0; i < 32; i ++) { + data[i] = rand() % 255; //Load the buffer with random data + } // forever loop - while (1){ - - if (role == role_ping_out){ - sleep(2); - printf("Initiating Basic Data Transfer\n\r"); - - long int cycles = 10000; //Change this to a higher or lower number. - - // unsigned long pauseTime = millis(); //Uncomment if autoAck == 1 ( NOACK ) - startTime = millis(); - - for(int i=0; i 3){ // Need to drop out of TX mode every 4ms if sending a steady stream of multicast data - pauseTime = millis(); - radio.txStandBy(); // This gives the PLL time to sync back up - } - */ - } - stopTime = millis(); - - if(!radio.txStandBy()){ counter+=3; } - - float numBytes = cycles*32; - float rate = numBytes / (stopTime - startTime); - - printf("Transfer complete at %.2f KB/s \n\r",rate); - printf("%lu of %lu Packets Failed to Send\n\r",counter,cycles); - counter = 0; - - } - - -if(role == role_pong_back){ - while(radio.available()){ - radio.read(&data,32); - counter++; - } - if(millis() - rxTimer > 1000){ - rxTimer = millis(); - printf("Rate: "); - float numBytes = counter*32; - printf("%.2f KB/s \n\r",numBytes/1000); - printf("Payload Count: %lu \n\r", counter); - counter = 0; - } - } - -} // loop + while (1) { + + if (role == role_ping_out) { + sleep(2); + printf("Initiating Basic Data Transfer\n\r"); + + long int cycles = 10000; //Change this to a higher or lower number. + + // unsigned long pauseTime = millis(); //Uncomment if autoAck == 1 ( NOACK ) + startTime = millis(); + + for (int i = 0; i < cycles; i ++) { //Loop through a number of cycles + data[0] = i; //Change the first byte of the payload for identification + if (! radio.writeFast(&data, 32)) { //Write to the FIFO buffers + counter ++; //Keep count of failed payloads + } + + + //This is only required when NO ACK ( enableAutoAck(0) ) payloads are used + /* if(millis() - pauseTime > 3){ // Need to drop out of TX mode every 4ms if sending a steady stream of multicast data + pauseTime = millis(); + radio.txStandBy(); // This gives the PLL time to sync back up + } + */ + } + stopTime = millis(); + + if (! radio.txStandBy()) { + counter += 3; + } + + float numBytes = cycles * 32; + float rate = numBytes / (stopTime - startTime); + + printf("Transfer complete at %.2f KB/s \n\r", rate); + printf("%lu of %lu Packets Failed to Send\n\r", counter, cycles); + counter = 0; + + } + + if (role == role_pong_back) { + while (radio.available()) { + radio.read(&data, 32); + counter ++; + } + if (millis() - rxTimer > 1000) { + rxTimer = millis(); + printf("Rate: "); + float numBytes = counter * 32; + printf("%.2f KB/s \n\r", numBytes / 1000); + printf("Payload Count: %lu \n\r", counter); + counter = 0; + } + } + + } // loop } // main diff --git a/library.json b/library.json index eb442ae6c..d9d65cf73 100644 --- a/library.json +++ b/library.json @@ -2,8 +2,7 @@ "name": "RF24", "keywords": "rf, radio, wireless, spi", "description": "Optimized High Speed Driver for nRF24L01(+) 2.4GHz Wireless Transceiver", - "repository": - { + "repository": { "type": "git", "url": "https://github.com/nRF24/RF24.git" }, diff --git a/nRF24L01.h b/nRF24L01.h index 5df47b013..213b611d0 100644 --- a/nRF24L01.h +++ b/nRF24L01.h @@ -24,7 +24,7 @@ */ /* Memory Map */ -#define NRF_CONFIG 0x00 +#define NRF_CONFIG 0x00 #define EN_AA 0x01 #define EN_RXADDR 0x02 #define SETUP_AW 0x03 @@ -48,8 +48,8 @@ #define RX_PW_P4 0x15 #define RX_PW_P5 0x16 #define FIFO_STATUS 0x17 -#define DYNPD 0x1C -#define FEATURE 0x1D +#define DYNPD 0x1C +#define FEATURE 0x1D /* Bit Mnemonics */ #define MASK_RX_DR 6 @@ -89,13 +89,13 @@ #define TX_EMPTY 4 #define RX_FULL 1 #define RX_EMPTY 0 -#define DPL_P5 5 -#define DPL_P4 4 -#define DPL_P3 3 -#define DPL_P2 2 -#define DPL_P1 1 -#define DPL_P0 0 -#define EN_DPL 2 +#define DPL_P5 5 +#define DPL_P4 4 +#define DPL_P3 3 +#define DPL_P2 2 +#define DPL_P1 1 +#define DPL_P0 0 +#define EN_DPL 2 #define EN_ACK_PAY 1 #define EN_DYN_ACK 0 @@ -117,7 +117,7 @@ #define LNA_HCURR 0 /* P model memory Map */ -#define RPD 0x09 +#define RPD 0x09 #define W_TX_PAYLOAD_NO_ACK 0xB0 /* P model bit Mnemonics */ diff --git a/printf.h b/printf.h index 643f434fa..ab5a869c9 100644 --- a/printf.h +++ b/printf.h @@ -5,7 +5,7 @@ modify it under the terms of the GNU General Public License version 2 as published by the Free Software Foundation. */ - /* Galileo support from spaniakos */ +/* Galileo support from spaniakos */ /** * @file printf.h @@ -17,28 +17,26 @@ #ifndef __PRINTF_H__ #define __PRINTF_H__ -#if defined (ARDUINO_ARCH_AVR) || defined(__ARDUINO_X86__) +#if defined(ARDUINO_ARCH_AVR) || defined(__ARDUINO_X86__) -int serial_putc( char c, FILE * ) +int serial_putc(char c, FILE *) { - Serial.write( c ); - + Serial.write(c); return c; } #endif void printf_begin(void) { - #if defined (ARDUINO_ARCH_AVR) - fdevopen( &serial_putc, 0 ); - - #elif defined (__ARDUINO_X86__) - //JESUS - For reddirect stdout to /dev/ttyGS0 (Serial Monitor port) - stdout = freopen("/dev/ttyGS0","w",stdout); + #if defined(ARDUINO_ARCH_AVR) + fdevopen(&serial_putc, 0); + + #elif defined(__ARDUINO_X86__) + // JESUS - For reddirect stdout to /dev/ttyGS0 (Serial Monitor port) + stdout = freopen("/dev/ttyGS0", "w", stdout); delay(500); - printf("redirecting to Serial..."); - - #endif + printf("Redirecting to Serial..."); + #endif // defined(__ARDUINO_X86__) } #endif // __PRINTF_H__ diff --git a/pyRF24/pyRF24.cpp b/pyRF24/pyRF24.cpp index 1b0445231..f1aae7155 100644 --- a/pyRF24/pyRF24.cpp +++ b/pyRF24/pyRF24.cpp @@ -13,37 +13,40 @@ void throw_ba_exception(void) bp::throw_error_already_set(); } -char *get_bytes_or_bytearray_str(bp::object buf) +char* get_bytes_or_bytearray_str(bp::object buf) { - PyObject *py_ba; + PyObject* py_ba; py_ba = buf.ptr(); - if (PyByteArray_Check(py_ba)) + if (PyByteArray_Check(py_ba)) { return PyByteArray_AsString(py_ba); - else if (PyBytes_Check(py_ba)) + } else if (PyBytes_Check(py_ba)) { return PyBytes_AsString(py_ba); - else + } else { throw_ba_exception(); + } return NULL; } int get_bytes_or_bytearray_ln(bp::object buf) { - PyObject *py_ba; + PyObject* py_ba; py_ba = buf.ptr(); - if (PyByteArray_Check(py_ba)) + if (PyByteArray_Check(py_ba)) { return PyByteArray_Size(py_ba); - else if (PyBytes_Check(py_ba)) + } else if (PyBytes_Check(py_ba)) { return PyBytes_Size(py_ba); - else + } else { throw_ba_exception(); + } return 0; } bp::object read_wrap(RF24& ref, int maxlen) { - char *buf = new char[maxlen+1]; + char* buf = new char[maxlen + 1]; ref.read(buf, maxlen); - bp::object py_ba(bp::handle<>(PyByteArray_FromStringAndSize(buf, maxlen(PyByteArray_FromStringAndSize(buf, maxlen < ref.getPayloadSize() ? maxlen : ref.getPayloadSize()))); delete[] buf; return py_ba; } @@ -96,12 +99,12 @@ void startWrite_wrap(RF24& ref, bp::object buf, const bool multicast) void openWritingPipe_wrap(RF24& ref, const bp::object address) { - ref.openWritingPipe((const uint8_t *)(get_bytes_or_bytearray_str(address))); + ref.openWritingPipe((const uint8_t*) (get_bytes_or_bytearray_str(address))); } void openReadingPipe_wrap(RF24& ref, uint8_t number, const bp::object address) { - ref.openReadingPipe(number, (const uint8_t *)(get_bytes_or_bytearray_str(address))); + ref.openReadingPipe(number, (const uint8_t*) (get_bytes_or_bytearray_str(address))); } bp::tuple whatHappened_wrap(RF24& ref) @@ -123,7 +126,8 @@ bp::tuple available_wrap(RF24& ref) return bp::make_tuple(result, pipe); } -BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS(txStandBy_wrap1, RF24::txStandBy, 0, 2) +BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS(txStandBy_wrap1, RF24::txStandBy, +0, 2) //BOOST_PYTHON_FUNCTION_OVERLOADS(txStandBy_wrap2, RF24::txStandBy, 1, 2) // ******************** enums ************************** @@ -133,198 +137,192 @@ BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS(txStandBy_wrap1, RF24::txStandBy, 0, 2) BOOST_PYTHON_MODULE(RF24){ #ifdef BCM2835_H - bp::enum_< RPiGPIOPin>("RPiGPIOPin") - .value("RPI_GPIO_P1_03", RPI_GPIO_P1_03) - .value("RPI_GPIO_P1_05", RPI_GPIO_P1_05) - .value("RPI_GPIO_P1_07", RPI_GPIO_P1_07) - .value("RPI_GPIO_P1_08", RPI_GPIO_P1_08) - .value("RPI_GPIO_P1_10", RPI_GPIO_P1_10) - .value("RPI_GPIO_P1_11", RPI_GPIO_P1_11) - .value("RPI_GPIO_P1_12", RPI_GPIO_P1_12) - .value("RPI_GPIO_P1_13", RPI_GPIO_P1_13) - .value("RPI_GPIO_P1_15", RPI_GPIO_P1_15) - .value("RPI_GPIO_P1_16", RPI_GPIO_P1_16) - .value("RPI_GPIO_P1_18", RPI_GPIO_P1_18) - .value("RPI_GPIO_P1_19", RPI_GPIO_P1_19) - .value("RPI_GPIO_P1_21", RPI_GPIO_P1_21) - .value("RPI_GPIO_P1_22", RPI_GPIO_P1_22) - .value("RPI_GPIO_P1_23", RPI_GPIO_P1_23) - .value("RPI_GPIO_P1_24", RPI_GPIO_P1_24) - .value("RPI_GPIO_P1_26", RPI_GPIO_P1_26) - .value("RPI_V2_GPIO_P1_03", RPI_V2_GPIO_P1_03) - .value("RPI_V2_GPIO_P1_05", RPI_V2_GPIO_P1_05) - .value("RPI_V2_GPIO_P1_07", RPI_V2_GPIO_P1_07) - .value("RPI_V2_GPIO_P1_08", RPI_V2_GPIO_P1_08) - .value("RPI_V2_GPIO_P1_10", RPI_V2_GPIO_P1_10) - .value("RPI_V2_GPIO_P1_11", RPI_V2_GPIO_P1_11) - .value("RPI_V2_GPIO_P1_12", RPI_V2_GPIO_P1_12) - .value("RPI_V2_GPIO_P1_13", RPI_V2_GPIO_P1_13) - .value("RPI_V2_GPIO_P1_15", RPI_V2_GPIO_P1_15) - .value("RPI_V2_GPIO_P1_16", RPI_V2_GPIO_P1_16) - .value("RPI_V2_GPIO_P1_18", RPI_V2_GPIO_P1_18) - .value("RPI_V2_GPIO_P1_19", RPI_V2_GPIO_P1_19) - .value("RPI_V2_GPIO_P1_21", RPI_V2_GPIO_P1_21) - .value("RPI_V2_GPIO_P1_22", RPI_V2_GPIO_P1_22) - .value("RPI_V2_GPIO_P1_23", RPI_V2_GPIO_P1_23) - .value("RPI_V2_GPIO_P1_24", RPI_V2_GPIO_P1_24) - .value("RPI_V2_GPIO_P1_26", RPI_V2_GPIO_P1_26) - .value("RPI_V2_GPIO_P5_03", RPI_V2_GPIO_P5_03) - .value("RPI_V2_GPIO_P5_04", RPI_V2_GPIO_P5_04) - .value("RPI_V2_GPIO_P5_05", RPI_V2_GPIO_P5_05) - .value("RPI_V2_GPIO_P5_06", RPI_V2_GPIO_P5_06) - .value("RPI_BPLUS_GPIO_J8_03", RPI_BPLUS_GPIO_J8_03) - .value("RPI_BPLUS_GPIO_J8_05", RPI_BPLUS_GPIO_J8_05) - .value("RPI_BPLUS_GPIO_J8_07", RPI_BPLUS_GPIO_J8_07) - .value("RPI_BPLUS_GPIO_J8_08", RPI_BPLUS_GPIO_J8_08) - .value("RPI_BPLUS_GPIO_J8_10", RPI_BPLUS_GPIO_J8_10) - .value("RPI_BPLUS_GPIO_J8_11", RPI_BPLUS_GPIO_J8_11) - .value("RPI_BPLUS_GPIO_J8_12", RPI_BPLUS_GPIO_J8_12) - .value("RPI_BPLUS_GPIO_J8_13", RPI_BPLUS_GPIO_J8_13) - .value("RPI_BPLUS_GPIO_J8_15", RPI_BPLUS_GPIO_J8_15) - .value("RPI_BPLUS_GPIO_J8_16", RPI_BPLUS_GPIO_J8_16) - .value("RPI_BPLUS_GPIO_J8_18", RPI_BPLUS_GPIO_J8_18) - .value("RPI_BPLUS_GPIO_J8_19", RPI_BPLUS_GPIO_J8_19) - .value("RPI_BPLUS_GPIO_J8_21", RPI_BPLUS_GPIO_J8_21) - .value("RPI_BPLUS_GPIO_J8_22", RPI_BPLUS_GPIO_J8_22) - .value("RPI_BPLUS_GPIO_J8_23", RPI_BPLUS_GPIO_J8_23) - .value("RPI_BPLUS_GPIO_J8_24", RPI_BPLUS_GPIO_J8_24) - .value("RPI_BPLUS_GPIO_J8_26", RPI_BPLUS_GPIO_J8_26) - .value("RPI_BPLUS_GPIO_J8_29", RPI_BPLUS_GPIO_J8_29) - .value("RPI_BPLUS_GPIO_J8_31", RPI_BPLUS_GPIO_J8_31) - .value("RPI_BPLUS_GPIO_J8_32", RPI_BPLUS_GPIO_J8_32) - .value("RPI_BPLUS_GPIO_J8_33", RPI_BPLUS_GPIO_J8_33) - .value("RPI_BPLUS_GPIO_J8_35", RPI_BPLUS_GPIO_J8_35) - .value("RPI_BPLUS_GPIO_J8_36", RPI_BPLUS_GPIO_J8_36) - .value("RPI_BPLUS_GPIO_J8_37", RPI_BPLUS_GPIO_J8_37) - .value("RPI_BPLUS_GPIO_J8_38", RPI_BPLUS_GPIO_J8_38) - .value("RPI_BPLUS_GPIO_J8_40", RPI_BPLUS_GPIO_J8_40) - .export_values() - ; - - bp::enum_< bcm2835SPIClockDivider>("bcm2835SPIClockDivider") - .value("BCM2835_SPI_CLOCK_DIVIDER_65536", BCM2835_SPI_CLOCK_DIVIDER_65536) - .value("BCM2835_SPI_CLOCK_DIVIDER_32768", BCM2835_SPI_CLOCK_DIVIDER_32768) - .value("BCM2835_SPI_CLOCK_DIVIDER_16384", BCM2835_SPI_CLOCK_DIVIDER_16384) - .value("BCM2835_SPI_CLOCK_DIVIDER_8192", BCM2835_SPI_CLOCK_DIVIDER_8192) - .value("BCM2835_SPI_CLOCK_DIVIDER_4096", BCM2835_SPI_CLOCK_DIVIDER_4096) - .value("BCM2835_SPI_CLOCK_DIVIDER_2048", BCM2835_SPI_CLOCK_DIVIDER_2048) - .value("BCM2835_SPI_CLOCK_DIVIDER_1024", BCM2835_SPI_CLOCK_DIVIDER_1024) - .value("BCM2835_SPI_CLOCK_DIVIDER_512", BCM2835_SPI_CLOCK_DIVIDER_512) - .value("BCM2835_SPI_CLOCK_DIVIDER_256", BCM2835_SPI_CLOCK_DIVIDER_256) - .value("BCM2835_SPI_CLOCK_DIVIDER_128", BCM2835_SPI_CLOCK_DIVIDER_128) - .value("BCM2835_SPI_CLOCK_DIVIDER_64", BCM2835_SPI_CLOCK_DIVIDER_64) - .value("BCM2835_SPI_CLOCK_DIVIDER_32", BCM2835_SPI_CLOCK_DIVIDER_32) - .value("BCM2835_SPI_CLOCK_DIVIDER_16", BCM2835_SPI_CLOCK_DIVIDER_16) - .value("BCM2835_SPI_CLOCK_DIVIDER_8", BCM2835_SPI_CLOCK_DIVIDER_8) - .value("BCM2835_SPI_CLOCK_DIVIDER_4", BCM2835_SPI_CLOCK_DIVIDER_4) - .value("BCM2835_SPI_CLOCK_DIVIDER_2", BCM2835_SPI_CLOCK_DIVIDER_2) - .value("BCM2835_SPI_CLOCK_DIVIDER_1", BCM2835_SPI_CLOCK_DIVIDER_1) - .export_values(); - - - bp::enum_< bcm2835SPIChipSelect>("bcm2835SPIChipSelect") - .value("BCM2835_SPI_CS0", BCM2835_SPI_CS0) - .value("BCM2835_SPI_CS1", BCM2835_SPI_CS1) - .value("BCM2835_SPI_CS2", BCM2835_SPI_CS2) - .value("BCM2835_SPI_CS_NONE", BCM2835_SPI_CS_NONE) - .export_values(); +bp::enum_< RPiGPIOPin>("RPiGPIOPin") + .value("RPI_GPIO_P1_03", RPI_GPIO_P1_03) + .value("RPI_GPIO_P1_05", RPI_GPIO_P1_05) + .value("RPI_GPIO_P1_07", RPI_GPIO_P1_07) + .value("RPI_GPIO_P1_08", RPI_GPIO_P1_08) + .value("RPI_GPIO_P1_10", RPI_GPIO_P1_10) + .value("RPI_GPIO_P1_11", RPI_GPIO_P1_11) + .value("RPI_GPIO_P1_12", RPI_GPIO_P1_12) + .value("RPI_GPIO_P1_13", RPI_GPIO_P1_13) + .value("RPI_GPIO_P1_15", RPI_GPIO_P1_15) + .value("RPI_GPIO_P1_16", RPI_GPIO_P1_16) + .value("RPI_GPIO_P1_18", RPI_GPIO_P1_18) + .value("RPI_GPIO_P1_19", RPI_GPIO_P1_19) + .value("RPI_GPIO_P1_21", RPI_GPIO_P1_21) + .value("RPI_GPIO_P1_22", RPI_GPIO_P1_22) + .value("RPI_GPIO_P1_23", RPI_GPIO_P1_23) + .value("RPI_GPIO_P1_24", RPI_GPIO_P1_24) + .value("RPI_GPIO_P1_26", RPI_GPIO_P1_26) + .value("RPI_V2_GPIO_P1_03", RPI_V2_GPIO_P1_03) + .value("RPI_V2_GPIO_P1_05", RPI_V2_GPIO_P1_05) + .value("RPI_V2_GPIO_P1_07", RPI_V2_GPIO_P1_07) + .value("RPI_V2_GPIO_P1_08", RPI_V2_GPIO_P1_08) + .value("RPI_V2_GPIO_P1_10", RPI_V2_GPIO_P1_10) + .value("RPI_V2_GPIO_P1_11", RPI_V2_GPIO_P1_11) + .value("RPI_V2_GPIO_P1_12", RPI_V2_GPIO_P1_12) + .value("RPI_V2_GPIO_P1_13", RPI_V2_GPIO_P1_13) + .value("RPI_V2_GPIO_P1_15", RPI_V2_GPIO_P1_15) + .value("RPI_V2_GPIO_P1_16", RPI_V2_GPIO_P1_16) + .value("RPI_V2_GPIO_P1_18", RPI_V2_GPIO_P1_18) + .value("RPI_V2_GPIO_P1_19", RPI_V2_GPIO_P1_19) + .value("RPI_V2_GPIO_P1_21", RPI_V2_GPIO_P1_21) + .value("RPI_V2_GPIO_P1_22", RPI_V2_GPIO_P1_22) + .value("RPI_V2_GPIO_P1_23", RPI_V2_GPIO_P1_23) + .value("RPI_V2_GPIO_P1_24", RPI_V2_GPIO_P1_24) + .value("RPI_V2_GPIO_P1_26", RPI_V2_GPIO_P1_26) + .value("RPI_V2_GPIO_P5_03", RPI_V2_GPIO_P5_03) + .value("RPI_V2_GPIO_P5_04", RPI_V2_GPIO_P5_04) + .value("RPI_V2_GPIO_P5_05", RPI_V2_GPIO_P5_05) + .value("RPI_V2_GPIO_P5_06", RPI_V2_GPIO_P5_06) + .value("RPI_BPLUS_GPIO_J8_03", RPI_BPLUS_GPIO_J8_03) + .value("RPI_BPLUS_GPIO_J8_05", RPI_BPLUS_GPIO_J8_05) + .value("RPI_BPLUS_GPIO_J8_07", RPI_BPLUS_GPIO_J8_07) + .value("RPI_BPLUS_GPIO_J8_08", RPI_BPLUS_GPIO_J8_08) + .value("RPI_BPLUS_GPIO_J8_10", RPI_BPLUS_GPIO_J8_10) + .value("RPI_BPLUS_GPIO_J8_11", RPI_BPLUS_GPIO_J8_11) + .value("RPI_BPLUS_GPIO_J8_12", RPI_BPLUS_GPIO_J8_12) + .value("RPI_BPLUS_GPIO_J8_13", RPI_BPLUS_GPIO_J8_13) + .value("RPI_BPLUS_GPIO_J8_15", RPI_BPLUS_GPIO_J8_15) + .value("RPI_BPLUS_GPIO_J8_16", RPI_BPLUS_GPIO_J8_16) + .value("RPI_BPLUS_GPIO_J8_18", RPI_BPLUS_GPIO_J8_18) + .value("RPI_BPLUS_GPIO_J8_19", RPI_BPLUS_GPIO_J8_19) + .value("RPI_BPLUS_GPIO_J8_21", RPI_BPLUS_GPIO_J8_21) + .value("RPI_BPLUS_GPIO_J8_22", RPI_BPLUS_GPIO_J8_22) + .value("RPI_BPLUS_GPIO_J8_23", RPI_BPLUS_GPIO_J8_23) + .value("RPI_BPLUS_GPIO_J8_24", RPI_BPLUS_GPIO_J8_24) + .value("RPI_BPLUS_GPIO_J8_26", RPI_BPLUS_GPIO_J8_26) + .value("RPI_BPLUS_GPIO_J8_29", RPI_BPLUS_GPIO_J8_29) + .value("RPI_BPLUS_GPIO_J8_31", RPI_BPLUS_GPIO_J8_31) + .value("RPI_BPLUS_GPIO_J8_32", RPI_BPLUS_GPIO_J8_32) + .value("RPI_BPLUS_GPIO_J8_33", RPI_BPLUS_GPIO_J8_33) + .value("RPI_BPLUS_GPIO_J8_35", RPI_BPLUS_GPIO_J8_35) + .value("RPI_BPLUS_GPIO_J8_36", RPI_BPLUS_GPIO_J8_36) + .value("RPI_BPLUS_GPIO_J8_37", RPI_BPLUS_GPIO_J8_37) + .value("RPI_BPLUS_GPIO_J8_38", RPI_BPLUS_GPIO_J8_38) + .value("RPI_BPLUS_GPIO_J8_40", RPI_BPLUS_GPIO_J8_40) + .export_values() + ; + +bp::enum_< bcm2835SPIClockDivider>("bcm2835SPIClockDivider") + .value("BCM2835_SPI_CLOCK_DIVIDER_65536", BCM2835_SPI_CLOCK_DIVIDER_65536) + .value("BCM2835_SPI_CLOCK_DIVIDER_32768", BCM2835_SPI_CLOCK_DIVIDER_32768) + .value("BCM2835_SPI_CLOCK_DIVIDER_16384", BCM2835_SPI_CLOCK_DIVIDER_16384) + .value("BCM2835_SPI_CLOCK_DIVIDER_8192", BCM2835_SPI_CLOCK_DIVIDER_8192) + .value("BCM2835_SPI_CLOCK_DIVIDER_4096", BCM2835_SPI_CLOCK_DIVIDER_4096) + .value("BCM2835_SPI_CLOCK_DIVIDER_2048", BCM2835_SPI_CLOCK_DIVIDER_2048) + .value("BCM2835_SPI_CLOCK_DIVIDER_1024", BCM2835_SPI_CLOCK_DIVIDER_1024) + .value("BCM2835_SPI_CLOCK_DIVIDER_512", BCM2835_SPI_CLOCK_DIVIDER_512) + .value("BCM2835_SPI_CLOCK_DIVIDER_256", BCM2835_SPI_CLOCK_DIVIDER_256) + .value("BCM2835_SPI_CLOCK_DIVIDER_128", BCM2835_SPI_CLOCK_DIVIDER_128) + .value("BCM2835_SPI_CLOCK_DIVIDER_64", BCM2835_SPI_CLOCK_DIVIDER_64) + .value("BCM2835_SPI_CLOCK_DIVIDER_32", BCM2835_SPI_CLOCK_DIVIDER_32) + .value("BCM2835_SPI_CLOCK_DIVIDER_16", BCM2835_SPI_CLOCK_DIVIDER_16) + .value("BCM2835_SPI_CLOCK_DIVIDER_8", BCM2835_SPI_CLOCK_DIVIDER_8) + .value("BCM2835_SPI_CLOCK_DIVIDER_4", BCM2835_SPI_CLOCK_DIVIDER_4) + .value("BCM2835_SPI_CLOCK_DIVIDER_2", BCM2835_SPI_CLOCK_DIVIDER_2) + .value("BCM2835_SPI_CLOCK_DIVIDER_1", BCM2835_SPI_CLOCK_DIVIDER_1) + .export_values(); + + +bp::enum_< bcm2835SPIChipSelect>("bcm2835SPIChipSelect") + .value("BCM2835_SPI_CS0", BCM2835_SPI_CS0) + .value("BCM2835_SPI_CS1", BCM2835_SPI_CS1) + .value("BCM2835_SPI_CS2", BCM2835_SPI_CS2) + .value("BCM2835_SPI_CS_NONE", BCM2835_SPI_CS_NONE) + .export_values(); // exposing '#define's for SPI speed as this is needed for RF24 constructor - bp::scope().attr("BCM2835_SPI_SPEED_64MHZ") = BCM2835_SPI_SPEED_64MHZ; - bp::scope().attr("BCM2835_SPI_SPEED_32MHZ") = BCM2835_SPI_SPEED_32MHZ; - bp::scope().attr("BCM2835_SPI_SPEED_16MHZ") = BCM2835_SPI_SPEED_16MHZ; - bp::scope().attr("BCM2835_SPI_SPEED_8MHZ") = BCM2835_SPI_SPEED_8MHZ; - bp::scope().attr("BCM2835_SPI_SPEED_4MHZ") = BCM2835_SPI_SPEED_4MHZ; - bp::scope().attr("BCM2835_SPI_SPEED_2MHZ") = BCM2835_SPI_SPEED_2MHZ; - bp::scope().attr("BCM2835_SPI_SPEED_1MHZ") = BCM2835_SPI_SPEED_1MHZ; - bp::scope().attr("BCM2835_SPI_SPEED_512KHZ") = BCM2835_SPI_SPEED_512KHZ; - bp::scope().attr("BCM2835_SPI_SPEED_256KHZ") = BCM2835_SPI_SPEED_256KHZ; - bp::scope().attr("BCM2835_SPI_SPEED_128KHZ") = BCM2835_SPI_SPEED_128KHZ; - bp::scope().attr("BCM2835_SPI_SPEED_64KHZ") = BCM2835_SPI_SPEED_64KHZ; - bp::scope().attr("BCM2835_SPI_SPEED_32KHZ") = BCM2835_SPI_SPEED_32KHZ; - bp::scope().attr("BCM2835_SPI_SPEED_16KHZ") = BCM2835_SPI_SPEED_16KHZ; - bp::scope().attr("BCM2835_SPI_SPEED_8KHZ") = BCM2835_SPI_SPEED_8KHZ; +bp::scope().attr("BCM2835_SPI_SPEED_64MHZ") = BCM2835_SPI_SPEED_64MHZ; +bp::scope().attr("BCM2835_SPI_SPEED_32MHZ") = BCM2835_SPI_SPEED_32MHZ; +bp::scope().attr("BCM2835_SPI_SPEED_16MHZ") = BCM2835_SPI_SPEED_16MHZ; +bp::scope().attr("BCM2835_SPI_SPEED_8MHZ") = BCM2835_SPI_SPEED_8MHZ; +bp::scope().attr("BCM2835_SPI_SPEED_4MHZ") = BCM2835_SPI_SPEED_4MHZ; +bp::scope().attr("BCM2835_SPI_SPEED_2MHZ") = BCM2835_SPI_SPEED_2MHZ; +bp::scope().attr("BCM2835_SPI_SPEED_1MHZ") = BCM2835_SPI_SPEED_1MHZ; +bp::scope().attr("BCM2835_SPI_SPEED_512KHZ") = BCM2835_SPI_SPEED_512KHZ; +bp::scope().attr("BCM2835_SPI_SPEED_256KHZ") = BCM2835_SPI_SPEED_256KHZ; +bp::scope().attr("BCM2835_SPI_SPEED_128KHZ") = BCM2835_SPI_SPEED_128KHZ; +bp::scope().attr("BCM2835_SPI_SPEED_64KHZ") = BCM2835_SPI_SPEED_64KHZ; +bp::scope().attr("BCM2835_SPI_SPEED_32KHZ") = BCM2835_SPI_SPEED_32KHZ; +bp::scope().attr("BCM2835_SPI_SPEED_16KHZ") = BCM2835_SPI_SPEED_16KHZ; +bp::scope().attr("BCM2835_SPI_SPEED_8KHZ") = BCM2835_SPI_SPEED_8KHZ; #endif // BCM2835_H - bp::enum_< rf24_crclength_e>("rf24_crclength_e") - .value("RF24_CRC_DISABLED", RF24_CRC_DISABLED) - .value("RF24_CRC_8", RF24_CRC_8) - .value("RF24_CRC_16", RF24_CRC_16) - .export_values() + bp::enum_("rf24_crclength_e").value("RF24_CRC_DISABLED", RF24_CRC_DISABLED).value("RF24_CRC_8", RF24_CRC_8).value( + "RF24_CRC_16", RF24_CRC_16).export_values() ; - bp::enum_< rf24_datarate_e>("rf24_datarate_e") + bp::enum_< rf24_datarate_e>("rf24_datarate_e") .value("RF24_1MBPS", RF24_1MBPS) .value("RF24_2MBPS", RF24_2MBPS) .value("RF24_250KBPS", RF24_250KBPS) - .export_values() - ; + .export_values(); - bp::enum_< rf24_pa_dbm_e>("rf24_pa_dbm_e") + bp::enum_< rf24_pa_dbm_e>("rf24_pa_dbm_e") .value("RF24_PA_MIN", RF24_PA_MIN) .value("RF24_PA_LOW", RF24_PA_LOW) .value("RF24_PA_HIGH", RF24_PA_HIGH) .value("RF24_PA_MAX", RF24_PA_MAX) .value("RF24_PA_ERROR", RF24_PA_ERROR) - .export_values() - ; + .export_values(); -// ******************** RF24 class ************************** -// - bp::class_< RF24 >( "RF24", bp::init< uint8_t, uint8_t >(( bp::arg("_cepin"), bp::arg("_cspin") )) ) -#if defined (RF24_LINUX) && !defined (MRAA) + // ******************** RF24 class ************************** + // + bp::class_< RF24 >( "RF24", bp::init< uint8_t, uint8_t >(( bp::arg("_cepin"), bp::arg("_cspin")))) + #if defined (RF24_LINUX) && ! defined (MRAA) .def( bp::init< uint8_t, uint8_t, uint32_t >(( bp::arg("_cepin"), bp::arg("_cspin"), bp::arg("spispeed") )) ) -#endif - .def("available", (bool ( ::RF24::* )( ) )( &::RF24::available ) ) + #endif + .def("available", (bool (::RF24::* )( ))( &::RF24::available )) .def("available_pipe", &available_wrap ) // needed to rename this method as python does not allow such overloading - .def("begin", &RF24::begin) + .def("begin", &RF24::begin) .def("closeReadingPipe", &RF24::closeReadingPipe) - .def("disableCRC", &RF24::disableCRC) + .def("disableCRC", &RF24::disableCRC) .def("enableAckPayload", &RF24::enableAckPayload) - .def("enableDynamicAck", &RF24::enableDynamicAck) + .def("enableDynamicAck", &RF24::enableDynamicAck) .def("enableDynamicPayloads", &RF24::enableDynamicPayloads) .def("flush_tx", &RF24::flush_tx) .def("getCRCLength", &RF24::getCRCLength) .def("getDataRate", &RF24::getDataRate) .def("getDynamicPayloadSize", &RF24::getDynamicPayloadSize) .def("getPALevel", &RF24::getPALevel) - .def("isAckPayloadAvailable", &RF24::isAckPayloadAvailable) + .def("isAckPayloadAvailable", &RF24::isAckPayloadAvailable) .def("isPVariant", &RF24::isPVariant) .def("isValid", &RF24::isValid) - .def("maskIRQ", &RF24::maskIRQ, ( bp::arg("tx_ok"), bp::arg("tx_fail"), bp::arg("rx_ready"))) - .def("openReadingPipe", &openReadingPipe_wrap, (bp::arg("number"), bp::arg("address"))) - .def("openReadingPipe", (void ( ::RF24::* )( ::uint8_t,::uint64_t ) )( &::RF24::openReadingPipe), (bp::arg("number"), bp::arg("address"))) - .def("openWritingPipe", &openWritingPipe_wrap, (bp::arg("address"))) - .def("openWritingPipe", (void ( ::RF24::* )( ::uint64_t ) )( &::RF24::openWritingPipe), ( bp::arg("address") ) ) - .def("powerDown", &RF24::powerDown) - .def("powerUp", &RF24::powerUp) + .def("maskIRQ", &RF24::maskIRQ, ( bp::arg("tx_ok"), bp::arg("tx_fail"), bp::arg("rx_ready"))) + .def("openReadingPipe", &openReadingPipe_wrap, (bp::arg("number"), bp::arg("address"))) + .def("openReadingPipe", (void (::RF24::* )(::uint8_t,::uint64_t ))( &::RF24::openReadingPipe), (bp::arg("number"), bp::arg("address"))) + .def("openWritingPipe", &openWritingPipe_wrap, (bp::arg("address"))) + .def("openWritingPipe", (void (::RF24::* )(::uint64_t ))( &::RF24::openWritingPipe), ( bp::arg("address"))) + .def("powerDown", &RF24::powerDown) + .def("powerUp", &RF24::powerUp) .def("printDetails", &RF24::printDetails) .def("reUseTX", &RF24::reUseTX) - .def("read", &read_wrap, (bp::arg("maxlen"))) + .def("read", &read_wrap, (bp::arg("maxlen"))) .def("rxFifoFull", &RF24::rxFifoFull) .def("setAddressWidth", &RF24::setAddressWidth) - .def("setAutoAck", (void ( ::RF24::* )( bool ) )( &::RF24::setAutoAck ), ( bp::arg("enable") ) ) - .def("setAutoAck", (void ( ::RF24::* )( ::uint8_t,bool ) )( &::RF24::setAutoAck ), ( bp::arg("pipe"), bp::arg("enable") ) ) - .def("setCRCLength", &RF24::setCRCLength, ( bp::arg("length") ) ) - .def("setChannel", &RF24::setChannel, ( bp::arg("channel") ) ) - .def("setDataRate", &RF24::setDataRate, ( bp::arg("speed") ) ) - .def("setPALevel", &RF24::setPALevel, ( bp::arg("level") ) ) - .def("setRetries", &RF24::setRetries , (bp::arg("delay"), bp::arg("count"))) - .def("startFastWrite", &startFastWrite_wrap1, ( bp::arg("buf"), bp::arg("len"), bp::arg("multicast") ) ) - .def("startFastWrite", &startFastWrite_wrap2, ( bp::arg("buf"), bp::arg("len"), bp::arg("multicast"), bp::arg("startTx") ) ) - .def("startListening", &RF24::startListening) - .def("startWrite", &startWrite_wrap, ( bp::arg("buf"), bp::arg("len"), bp::arg("multicast") ) ) + .def("setAutoAck", (void (::RF24::* )( bool ))( &::RF24::setAutoAck ), ( bp::arg("enable"))) + .def("setAutoAck", (void (::RF24::* )(::uint8_t, bool ))( &::RF24::setAutoAck ), ( bp::arg("pipe"), bp::arg("enable"))) + .def("setCRCLength", &RF24::setCRCLength, ( bp::arg("length"))) + .def("setChannel", &RF24::setChannel, ( bp::arg("channel"))) + .def("setDataRate", &RF24::setDataRate, ( bp::arg("speed"))) + .def("setPALevel", &RF24::setPALevel, ( bp::arg("level"))) + .def("setRetries", &RF24::setRetries, (bp::arg("delay"), bp::arg("count"))) + .def("startFastWrite", &startFastWrite_wrap1, ( bp::arg("buf"), bp::arg("len"), bp::arg("multicast"))) + .def("startFastWrite", &startFastWrite_wrap2, ( bp::arg("buf"), bp::arg("len"), bp::arg("multicast"), bp::arg("startTx"))) + .def("startListening", &RF24::startListening) + .def("startWrite", &startWrite_wrap, ( bp::arg("buf"), bp::arg("len"), bp::arg("multicast"))) .def("stopListening", &RF24::stopListening) .def("testCarrier", &RF24::testCarrier) .def("testRPD", &RF24::testRPD) - .def("txStandBy", (bool ( ::RF24::* )( ::uint32_t,bool))(&RF24::txStandBy), txStandBy_wrap1( bp::args("timeout", "startTx") ) ) - .def("whatHappened", &whatHappened_wrap) - .def("write", &write_wrap1, ( bp::arg("buf") ) ) - .def("write", &write_wrap2, ( bp::arg("buf"), bp::arg("multicast") ) ) - .def("writeAckPayload", writeAckPayload_wrap, ( bp::arg("pipe"), bp::arg("buf") ) ) - .def("writeBlocking", &writeBlocking_wrap, ( bp::arg("buf"), bp::arg("timeout") ) ) - .def("writeFast", &writeFast_wrap1, ( bp::arg("buf") ) ) - .def("writeFast", &writeFast_wrap2, ( bp::arg("buf"), bp::arg("multicast") ) ) + .def("txStandBy", (bool (::RF24::* )(::uint32_t, bool))(&RF24::txStandBy), txStandBy_wrap1( bp::args("timeout", "startTx"))) + .def("whatHappened", &whatHappened_wrap) + .def("write", &write_wrap1, ( bp::arg("buf"))) + .def("write", &write_wrap2, ( bp::arg("buf"), bp::arg("multicast"))) + .def("writeAckPayload", writeAckPayload_wrap, ( bp::arg("pipe"), bp::arg("buf"))) + .def("writeBlocking", &writeBlocking_wrap, ( bp::arg("buf"), bp::arg("timeout"))) + .def("writeFast", &writeFast_wrap1, ( bp::arg("buf"))) + .def("writeFast", &writeFast_wrap2, ( bp::arg("buf"), bp::arg("multicast"))) .add_property("payloadSize", &RF24::getPayloadSize, &RF24::setPayloadSize) - .def_readwrite( "failureDetected", &RF24::failureDetected ); -} + .def_readwrite( "failureDetected", &RF24::failureDetected );} diff --git a/pyRF24/pyRF24/pyRF24.cpp b/pyRF24/pyRF24/pyRF24.cpp index fa0322886..ad14a95de 100644 --- a/pyRF24/pyRF24/pyRF24.cpp +++ b/pyRF24/pyRF24/pyRF24.cpp @@ -13,37 +13,40 @@ void throw_ba_exception(void) bp::throw_error_already_set(); } -char *get_bytes_or_bytearray_str(bp::object buf) +char* get_bytes_or_bytearray_str(bp::object buf) { - PyObject *py_ba; + PyObject* py_ba; py_ba = buf.ptr(); - if (PyByteArray_Check(py_ba)) + if (PyByteArray_Check(py_ba)) { return PyByteArray_AsString(py_ba); - else if (PyBytes_Check(py_ba)) + } else if (PyBytes_Check(py_ba)) { return PyBytes_AsString(py_ba); - else + } else { throw_ba_exception(); + } return NULL; } int get_bytes_or_bytearray_ln(bp::object buf) { - PyObject *py_ba; + PyObject* py_ba; py_ba = buf.ptr(); - if (PyByteArray_Check(py_ba)) + if (PyByteArray_Check(py_ba)) { return PyByteArray_Size(py_ba); - else if (PyBytes_Check(py_ba)) + } else if (PyBytes_Check(py_ba)) { return PyBytes_Size(py_ba); - else + } else { throw_ba_exception(); + } return 0; } bp::object read_wrap(RF24& ref, int maxlen) { - char *buf = new char[maxlen+1]; + char* buf = new char[maxlen + 1]; ref.read(buf, maxlen); - bp::object py_ba(bp::handle<>(PyByteArray_FromStringAndSize(buf, maxlen(PyByteArray_FromStringAndSize(buf, maxlen < ref.getPayloadSize() ? maxlen : ref.getPayloadSize()))); delete[] buf; return py_ba; } @@ -96,12 +99,12 @@ void startWrite_wrap(RF24& ref, bp::object buf, const bool multicast) void openWritingPipe_wrap(RF24& ref, const bp::object address) { - ref.openWritingPipe((const uint8_t *)(get_bytes_or_bytearray_str(address))); + ref.openWritingPipe((const uint8_t*) (get_bytes_or_bytearray_str(address))); } void openReadingPipe_wrap(RF24& ref, uint8_t number, const bp::object address) { - ref.openReadingPipe(number, (const uint8_t *)(get_bytes_or_bytearray_str(address))); + ref.openReadingPipe(number, (const uint8_t*) (get_bytes_or_bytearray_str(address))); } bp::tuple whatHappened_wrap(RF24& ref) @@ -123,7 +126,8 @@ bp::tuple available_wrap(RF24& ref) return bp::make_tuple(result, pipe); } -BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS(txStandBy_wrap1, RF24::txStandBy, 0, 2) +BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS(txStandBy_wrap1, RF24::txStandBy, +0, 2) //BOOST_PYTHON_FUNCTION_OVERLOADS(txStandBy_wrap2, RF24::txStandBy, 1, 2) // ******************** enums ************************** @@ -133,196 +137,190 @@ BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS(txStandBy_wrap1, RF24::txStandBy, 0, 2) BOOST_PYTHON_MODULE(RF24){ #ifdef BCM2835_H - bp::enum_< RPiGPIOPin>("RPiGPIOPin") - .value("RPI_GPIO_P1_03", RPI_GPIO_P1_03) - .value("RPI_GPIO_P1_05", RPI_GPIO_P1_05) - .value("RPI_GPIO_P1_07", RPI_GPIO_P1_07) - .value("RPI_GPIO_P1_08", RPI_GPIO_P1_08) - .value("RPI_GPIO_P1_10", RPI_GPIO_P1_10) - .value("RPI_GPIO_P1_11", RPI_GPIO_P1_11) - .value("RPI_GPIO_P1_12", RPI_GPIO_P1_12) - .value("RPI_GPIO_P1_13", RPI_GPIO_P1_13) - .value("RPI_GPIO_P1_15", RPI_GPIO_P1_15) - .value("RPI_GPIO_P1_16", RPI_GPIO_P1_16) - .value("RPI_GPIO_P1_18", RPI_GPIO_P1_18) - .value("RPI_GPIO_P1_19", RPI_GPIO_P1_19) - .value("RPI_GPIO_P1_21", RPI_GPIO_P1_21) - .value("RPI_GPIO_P1_22", RPI_GPIO_P1_22) - .value("RPI_GPIO_P1_23", RPI_GPIO_P1_23) - .value("RPI_GPIO_P1_24", RPI_GPIO_P1_24) - .value("RPI_GPIO_P1_26", RPI_GPIO_P1_26) - .value("RPI_V2_GPIO_P1_03", RPI_V2_GPIO_P1_03) - .value("RPI_V2_GPIO_P1_05", RPI_V2_GPIO_P1_05) - .value("RPI_V2_GPIO_P1_07", RPI_V2_GPIO_P1_07) - .value("RPI_V2_GPIO_P1_08", RPI_V2_GPIO_P1_08) - .value("RPI_V2_GPIO_P1_10", RPI_V2_GPIO_P1_10) - .value("RPI_V2_GPIO_P1_11", RPI_V2_GPIO_P1_11) - .value("RPI_V2_GPIO_P1_12", RPI_V2_GPIO_P1_12) - .value("RPI_V2_GPIO_P1_13", RPI_V2_GPIO_P1_13) - .value("RPI_V2_GPIO_P1_15", RPI_V2_GPIO_P1_15) - .value("RPI_V2_GPIO_P1_16", RPI_V2_GPIO_P1_16) - .value("RPI_V2_GPIO_P1_18", RPI_V2_GPIO_P1_18) - .value("RPI_V2_GPIO_P1_19", RPI_V2_GPIO_P1_19) - .value("RPI_V2_GPIO_P1_21", RPI_V2_GPIO_P1_21) - .value("RPI_V2_GPIO_P1_22", RPI_V2_GPIO_P1_22) - .value("RPI_V2_GPIO_P1_23", RPI_V2_GPIO_P1_23) - .value("RPI_V2_GPIO_P1_24", RPI_V2_GPIO_P1_24) - .value("RPI_V2_GPIO_P1_26", RPI_V2_GPIO_P1_26) - .value("RPI_V2_GPIO_P5_03", RPI_V2_GPIO_P5_03) - .value("RPI_V2_GPIO_P5_04", RPI_V2_GPIO_P5_04) - .value("RPI_V2_GPIO_P5_05", RPI_V2_GPIO_P5_05) - .value("RPI_V2_GPIO_P5_06", RPI_V2_GPIO_P5_06) - .value("RPI_BPLUS_GPIO_J8_03", RPI_BPLUS_GPIO_J8_03) - .value("RPI_BPLUS_GPIO_J8_05", RPI_BPLUS_GPIO_J8_05) - .value("RPI_BPLUS_GPIO_J8_07", RPI_BPLUS_GPIO_J8_07) - .value("RPI_BPLUS_GPIO_J8_08", RPI_BPLUS_GPIO_J8_08) - .value("RPI_BPLUS_GPIO_J8_10", RPI_BPLUS_GPIO_J8_10) - .value("RPI_BPLUS_GPIO_J8_11", RPI_BPLUS_GPIO_J8_11) - .value("RPI_BPLUS_GPIO_J8_12", RPI_BPLUS_GPIO_J8_12) - .value("RPI_BPLUS_GPIO_J8_13", RPI_BPLUS_GPIO_J8_13) - .value("RPI_BPLUS_GPIO_J8_15", RPI_BPLUS_GPIO_J8_15) - .value("RPI_BPLUS_GPIO_J8_16", RPI_BPLUS_GPIO_J8_16) - .value("RPI_BPLUS_GPIO_J8_18", RPI_BPLUS_GPIO_J8_18) - .value("RPI_BPLUS_GPIO_J8_19", RPI_BPLUS_GPIO_J8_19) - .value("RPI_BPLUS_GPIO_J8_21", RPI_BPLUS_GPIO_J8_21) - .value("RPI_BPLUS_GPIO_J8_22", RPI_BPLUS_GPIO_J8_22) - .value("RPI_BPLUS_GPIO_J8_23", RPI_BPLUS_GPIO_J8_23) - .value("RPI_BPLUS_GPIO_J8_24", RPI_BPLUS_GPIO_J8_24) - .value("RPI_BPLUS_GPIO_J8_26", RPI_BPLUS_GPIO_J8_26) - .value("RPI_BPLUS_GPIO_J8_29", RPI_BPLUS_GPIO_J8_29) - .value("RPI_BPLUS_GPIO_J8_31", RPI_BPLUS_GPIO_J8_31) - .value("RPI_BPLUS_GPIO_J8_32", RPI_BPLUS_GPIO_J8_32) - .value("RPI_BPLUS_GPIO_J8_33", RPI_BPLUS_GPIO_J8_33) - .value("RPI_BPLUS_GPIO_J8_35", RPI_BPLUS_GPIO_J8_35) - .value("RPI_BPLUS_GPIO_J8_36", RPI_BPLUS_GPIO_J8_36) - .value("RPI_BPLUS_GPIO_J8_37", RPI_BPLUS_GPIO_J8_37) - .value("RPI_BPLUS_GPIO_J8_38", RPI_BPLUS_GPIO_J8_38) - .value("RPI_BPLUS_GPIO_J8_40", RPI_BPLUS_GPIO_J8_40) - .export_values() - ; - - bp::enum_< bcm2835SPIClockDivider>("bcm2835SPIClockDivider") - .value("BCM2835_SPI_CLOCK_DIVIDER_65536", BCM2835_SPI_CLOCK_DIVIDER_65536) - .value("BCM2835_SPI_CLOCK_DIVIDER_32768", BCM2835_SPI_CLOCK_DIVIDER_32768) - .value("BCM2835_SPI_CLOCK_DIVIDER_16384", BCM2835_SPI_CLOCK_DIVIDER_16384) - .value("BCM2835_SPI_CLOCK_DIVIDER_8192", BCM2835_SPI_CLOCK_DIVIDER_8192) - .value("BCM2835_SPI_CLOCK_DIVIDER_4096", BCM2835_SPI_CLOCK_DIVIDER_4096) - .value("BCM2835_SPI_CLOCK_DIVIDER_2048", BCM2835_SPI_CLOCK_DIVIDER_2048) - .value("BCM2835_SPI_CLOCK_DIVIDER_1024", BCM2835_SPI_CLOCK_DIVIDER_1024) - .value("BCM2835_SPI_CLOCK_DIVIDER_512", BCM2835_SPI_CLOCK_DIVIDER_512) - .value("BCM2835_SPI_CLOCK_DIVIDER_256", BCM2835_SPI_CLOCK_DIVIDER_256) - .value("BCM2835_SPI_CLOCK_DIVIDER_128", BCM2835_SPI_CLOCK_DIVIDER_128) - .value("BCM2835_SPI_CLOCK_DIVIDER_64", BCM2835_SPI_CLOCK_DIVIDER_64) - .value("BCM2835_SPI_CLOCK_DIVIDER_32", BCM2835_SPI_CLOCK_DIVIDER_32) - .value("BCM2835_SPI_CLOCK_DIVIDER_16", BCM2835_SPI_CLOCK_DIVIDER_16) - .value("BCM2835_SPI_CLOCK_DIVIDER_8", BCM2835_SPI_CLOCK_DIVIDER_8) - .value("BCM2835_SPI_CLOCK_DIVIDER_4", BCM2835_SPI_CLOCK_DIVIDER_4) - .value("BCM2835_SPI_CLOCK_DIVIDER_2", BCM2835_SPI_CLOCK_DIVIDER_2) - .value("BCM2835_SPI_CLOCK_DIVIDER_1", BCM2835_SPI_CLOCK_DIVIDER_1) - .export_values(); - - - bp::enum_< bcm2835SPIChipSelect>("bcm2835SPIChipSelect") - .value("BCM2835_SPI_CS0", BCM2835_SPI_CS0) - .value("BCM2835_SPI_CS1", BCM2835_SPI_CS1) - .value("BCM2835_SPI_CS2", BCM2835_SPI_CS2) - .value("BCM2835_SPI_CS_NONE", BCM2835_SPI_CS_NONE) - .export_values(); +bp::enum_< RPiGPIOPin>("RPiGPIOPin") + .value("RPI_GPIO_P1_03", RPI_GPIO_P1_03) + .value("RPI_GPIO_P1_05", RPI_GPIO_P1_05) + .value("RPI_GPIO_P1_07", RPI_GPIO_P1_07) + .value("RPI_GPIO_P1_08", RPI_GPIO_P1_08) + .value("RPI_GPIO_P1_10", RPI_GPIO_P1_10) + .value("RPI_GPIO_P1_11", RPI_GPIO_P1_11) + .value("RPI_GPIO_P1_12", RPI_GPIO_P1_12) + .value("RPI_GPIO_P1_13", RPI_GPIO_P1_13) + .value("RPI_GPIO_P1_15", RPI_GPIO_P1_15) + .value("RPI_GPIO_P1_16", RPI_GPIO_P1_16) + .value("RPI_GPIO_P1_18", RPI_GPIO_P1_18) + .value("RPI_GPIO_P1_19", RPI_GPIO_P1_19) + .value("RPI_GPIO_P1_21", RPI_GPIO_P1_21) + .value("RPI_GPIO_P1_22", RPI_GPIO_P1_22) + .value("RPI_GPIO_P1_23", RPI_GPIO_P1_23) + .value("RPI_GPIO_P1_24", RPI_GPIO_P1_24) + .value("RPI_GPIO_P1_26", RPI_GPIO_P1_26) + .value("RPI_V2_GPIO_P1_03", RPI_V2_GPIO_P1_03) + .value("RPI_V2_GPIO_P1_05", RPI_V2_GPIO_P1_05) + .value("RPI_V2_GPIO_P1_07", RPI_V2_GPIO_P1_07) + .value("RPI_V2_GPIO_P1_08", RPI_V2_GPIO_P1_08) + .value("RPI_V2_GPIO_P1_10", RPI_V2_GPIO_P1_10) + .value("RPI_V2_GPIO_P1_11", RPI_V2_GPIO_P1_11) + .value("RPI_V2_GPIO_P1_12", RPI_V2_GPIO_P1_12) + .value("RPI_V2_GPIO_P1_13", RPI_V2_GPIO_P1_13) + .value("RPI_V2_GPIO_P1_15", RPI_V2_GPIO_P1_15) + .value("RPI_V2_GPIO_P1_16", RPI_V2_GPIO_P1_16) + .value("RPI_V2_GPIO_P1_18", RPI_V2_GPIO_P1_18) + .value("RPI_V2_GPIO_P1_19", RPI_V2_GPIO_P1_19) + .value("RPI_V2_GPIO_P1_21", RPI_V2_GPIO_P1_21) + .value("RPI_V2_GPIO_P1_22", RPI_V2_GPIO_P1_22) + .value("RPI_V2_GPIO_P1_23", RPI_V2_GPIO_P1_23) + .value("RPI_V2_GPIO_P1_24", RPI_V2_GPIO_P1_24) + .value("RPI_V2_GPIO_P1_26", RPI_V2_GPIO_P1_26) + .value("RPI_V2_GPIO_P5_03", RPI_V2_GPIO_P5_03) + .value("RPI_V2_GPIO_P5_04", RPI_V2_GPIO_P5_04) + .value("RPI_V2_GPIO_P5_05", RPI_V2_GPIO_P5_05) + .value("RPI_V2_GPIO_P5_06", RPI_V2_GPIO_P5_06) + .value("RPI_BPLUS_GPIO_J8_03", RPI_BPLUS_GPIO_J8_03) + .value("RPI_BPLUS_GPIO_J8_05", RPI_BPLUS_GPIO_J8_05) + .value("RPI_BPLUS_GPIO_J8_07", RPI_BPLUS_GPIO_J8_07) + .value("RPI_BPLUS_GPIO_J8_08", RPI_BPLUS_GPIO_J8_08) + .value("RPI_BPLUS_GPIO_J8_10", RPI_BPLUS_GPIO_J8_10) + .value("RPI_BPLUS_GPIO_J8_11", RPI_BPLUS_GPIO_J8_11) + .value("RPI_BPLUS_GPIO_J8_12", RPI_BPLUS_GPIO_J8_12) + .value("RPI_BPLUS_GPIO_J8_13", RPI_BPLUS_GPIO_J8_13) + .value("RPI_BPLUS_GPIO_J8_15", RPI_BPLUS_GPIO_J8_15) + .value("RPI_BPLUS_GPIO_J8_16", RPI_BPLUS_GPIO_J8_16) + .value("RPI_BPLUS_GPIO_J8_18", RPI_BPLUS_GPIO_J8_18) + .value("RPI_BPLUS_GPIO_J8_19", RPI_BPLUS_GPIO_J8_19) + .value("RPI_BPLUS_GPIO_J8_21", RPI_BPLUS_GPIO_J8_21) + .value("RPI_BPLUS_GPIO_J8_22", RPI_BPLUS_GPIO_J8_22) + .value("RPI_BPLUS_GPIO_J8_23", RPI_BPLUS_GPIO_J8_23) + .value("RPI_BPLUS_GPIO_J8_24", RPI_BPLUS_GPIO_J8_24) + .value("RPI_BPLUS_GPIO_J8_26", RPI_BPLUS_GPIO_J8_26) + .value("RPI_BPLUS_GPIO_J8_29", RPI_BPLUS_GPIO_J8_29) + .value("RPI_BPLUS_GPIO_J8_31", RPI_BPLUS_GPIO_J8_31) + .value("RPI_BPLUS_GPIO_J8_32", RPI_BPLUS_GPIO_J8_32) + .value("RPI_BPLUS_GPIO_J8_33", RPI_BPLUS_GPIO_J8_33) + .value("RPI_BPLUS_GPIO_J8_35", RPI_BPLUS_GPIO_J8_35) + .value("RPI_BPLUS_GPIO_J8_36", RPI_BPLUS_GPIO_J8_36) + .value("RPI_BPLUS_GPIO_J8_37", RPI_BPLUS_GPIO_J8_37) + .value("RPI_BPLUS_GPIO_J8_38", RPI_BPLUS_GPIO_J8_38) + .value("RPI_BPLUS_GPIO_J8_40", RPI_BPLUS_GPIO_J8_40) + .export_values() + ; + +bp::enum_< bcm2835SPIClockDivider>("bcm2835SPIClockDivider") + .value("BCM2835_SPI_CLOCK_DIVIDER_65536", BCM2835_SPI_CLOCK_DIVIDER_65536) + .value("BCM2835_SPI_CLOCK_DIVIDER_32768", BCM2835_SPI_CLOCK_DIVIDER_32768) + .value("BCM2835_SPI_CLOCK_DIVIDER_16384", BCM2835_SPI_CLOCK_DIVIDER_16384) + .value("BCM2835_SPI_CLOCK_DIVIDER_8192", BCM2835_SPI_CLOCK_DIVIDER_8192) + .value("BCM2835_SPI_CLOCK_DIVIDER_4096", BCM2835_SPI_CLOCK_DIVIDER_4096) + .value("BCM2835_SPI_CLOCK_DIVIDER_2048", BCM2835_SPI_CLOCK_DIVIDER_2048) + .value("BCM2835_SPI_CLOCK_DIVIDER_1024", BCM2835_SPI_CLOCK_DIVIDER_1024) + .value("BCM2835_SPI_CLOCK_DIVIDER_512", BCM2835_SPI_CLOCK_DIVIDER_512) + .value("BCM2835_SPI_CLOCK_DIVIDER_256", BCM2835_SPI_CLOCK_DIVIDER_256) + .value("BCM2835_SPI_CLOCK_DIVIDER_128", BCM2835_SPI_CLOCK_DIVIDER_128) + .value("BCM2835_SPI_CLOCK_DIVIDER_64", BCM2835_SPI_CLOCK_DIVIDER_64) + .value("BCM2835_SPI_CLOCK_DIVIDER_32", BCM2835_SPI_CLOCK_DIVIDER_32) + .value("BCM2835_SPI_CLOCK_DIVIDER_16", BCM2835_SPI_CLOCK_DIVIDER_16) + .value("BCM2835_SPI_CLOCK_DIVIDER_8", BCM2835_SPI_CLOCK_DIVIDER_8) + .value("BCM2835_SPI_CLOCK_DIVIDER_4", BCM2835_SPI_CLOCK_DIVIDER_4) + .value("BCM2835_SPI_CLOCK_DIVIDER_2", BCM2835_SPI_CLOCK_DIVIDER_2) + .value("BCM2835_SPI_CLOCK_DIVIDER_1", BCM2835_SPI_CLOCK_DIVIDER_1) + .export_values(); + + +bp::enum_< bcm2835SPIChipSelect>("bcm2835SPIChipSelect") + .value("BCM2835_SPI_CS0", BCM2835_SPI_CS0) + .value("BCM2835_SPI_CS1", BCM2835_SPI_CS1) + .value("BCM2835_SPI_CS2", BCM2835_SPI_CS2) + .value("BCM2835_SPI_CS_NONE", BCM2835_SPI_CS_NONE) + .export_values(); // exposing '#define's for SPI speed as this is needed for RF24 constructor - bp::scope().attr("BCM2835_SPI_SPEED_64MHZ") = BCM2835_SPI_SPEED_64MHZ; - bp::scope().attr("BCM2835_SPI_SPEED_32MHZ") = BCM2835_SPI_SPEED_32MHZ; - bp::scope().attr("BCM2835_SPI_SPEED_16MHZ") = BCM2835_SPI_SPEED_16MHZ; - bp::scope().attr("BCM2835_SPI_SPEED_8MHZ") = BCM2835_SPI_SPEED_8MHZ; - bp::scope().attr("BCM2835_SPI_SPEED_4MHZ") = BCM2835_SPI_SPEED_4MHZ; - bp::scope().attr("BCM2835_SPI_SPEED_2MHZ") = BCM2835_SPI_SPEED_2MHZ; - bp::scope().attr("BCM2835_SPI_SPEED_1MHZ") = BCM2835_SPI_SPEED_1MHZ; - bp::scope().attr("BCM2835_SPI_SPEED_512KHZ") = BCM2835_SPI_SPEED_512KHZ; - bp::scope().attr("BCM2835_SPI_SPEED_256KHZ") = BCM2835_SPI_SPEED_256KHZ; - bp::scope().attr("BCM2835_SPI_SPEED_128KHZ") = BCM2835_SPI_SPEED_128KHZ; - bp::scope().attr("BCM2835_SPI_SPEED_64KHZ") = BCM2835_SPI_SPEED_64KHZ; - bp::scope().attr("BCM2835_SPI_SPEED_32KHZ") = BCM2835_SPI_SPEED_32KHZ; - bp::scope().attr("BCM2835_SPI_SPEED_16KHZ") = BCM2835_SPI_SPEED_16KHZ; - bp::scope().attr("BCM2835_SPI_SPEED_8KHZ") = BCM2835_SPI_SPEED_8KHZ; +bp::scope().attr("BCM2835_SPI_SPEED_64MHZ") = BCM2835_SPI_SPEED_64MHZ; +bp::scope().attr("BCM2835_SPI_SPEED_32MHZ") = BCM2835_SPI_SPEED_32MHZ; +bp::scope().attr("BCM2835_SPI_SPEED_16MHZ") = BCM2835_SPI_SPEED_16MHZ; +bp::scope().attr("BCM2835_SPI_SPEED_8MHZ") = BCM2835_SPI_SPEED_8MHZ; +bp::scope().attr("BCM2835_SPI_SPEED_4MHZ") = BCM2835_SPI_SPEED_4MHZ; +bp::scope().attr("BCM2835_SPI_SPEED_2MHZ") = BCM2835_SPI_SPEED_2MHZ; +bp::scope().attr("BCM2835_SPI_SPEED_1MHZ") = BCM2835_SPI_SPEED_1MHZ; +bp::scope().attr("BCM2835_SPI_SPEED_512KHZ") = BCM2835_SPI_SPEED_512KHZ; +bp::scope().attr("BCM2835_SPI_SPEED_256KHZ") = BCM2835_SPI_SPEED_256KHZ; +bp::scope().attr("BCM2835_SPI_SPEED_128KHZ") = BCM2835_SPI_SPEED_128KHZ; +bp::scope().attr("BCM2835_SPI_SPEED_64KHZ") = BCM2835_SPI_SPEED_64KHZ; +bp::scope().attr("BCM2835_SPI_SPEED_32KHZ") = BCM2835_SPI_SPEED_32KHZ; +bp::scope().attr("BCM2835_SPI_SPEED_16KHZ") = BCM2835_SPI_SPEED_16KHZ; +bp::scope().attr("BCM2835_SPI_SPEED_8KHZ") = BCM2835_SPI_SPEED_8KHZ; #endif // BCM2835_H - bp::enum_< rf24_crclength_e>("rf24_crclength_e") - .value("RF24_CRC_DISABLED", RF24_CRC_DISABLED) - .value("RF24_CRC_8", RF24_CRC_8) - .value("RF24_CRC_16", RF24_CRC_16) - .export_values() + bp::enum_("rf24_crclength_e").value("RF24_CRC_DISABLED", RF24_CRC_DISABLED).value("RF24_CRC_8", RF24_CRC_8).value( + "RF24_CRC_16", RF24_CRC_16).export_values() ; - bp::enum_< rf24_datarate_e>("rf24_datarate_e") + bp::enum_< rf24_datarate_e>("rf24_datarate_e") .value("RF24_1MBPS", RF24_1MBPS) .value("RF24_2MBPS", RF24_2MBPS) .value("RF24_250KBPS", RF24_250KBPS) - .export_values() - ; + .export_values(); - bp::enum_< rf24_pa_dbm_e>("rf24_pa_dbm_e") + bp::enum_< rf24_pa_dbm_e>("rf24_pa_dbm_e") .value("RF24_PA_MIN", RF24_PA_MIN) .value("RF24_PA_LOW", RF24_PA_LOW) .value("RF24_PA_HIGH", RF24_PA_HIGH) .value("RF24_PA_MAX", RF24_PA_MAX) .value("RF24_PA_ERROR", RF24_PA_ERROR) - .export_values() - ; + .export_values(); -// ******************** RF24 class ************************** -// - bp::class_< RF24 >( "RF24", bp::init< uint8_t, uint8_t >(( bp::arg("_cepin"), bp::arg("_cspin") )) ) - .def( bp::init< uint8_t, uint8_t, uint32_t >(( bp::arg("_cepin"), bp::arg("_cspin"), bp::arg("spispeed") )) ) - .def("available", (bool ( ::RF24::* )( ) )( &::RF24::available ) ) + // ******************** RF24 class ************************** + // + bp::class_< RF24 >( "RF24", bp::init< uint8_t, uint8_t >(( bp::arg("_cepin"), bp::arg("_cspin")))) + .def( bp::init< uint8_t, uint8_t, uint32_t >(( bp::arg("_cepin"), bp::arg("_cspin"), bp::arg("spispeed")))) + .def("available", (bool (::RF24::* )( ))( &::RF24::available )) .def("available_pipe", &available_wrap ) // needed to rename this method as python does not allow such overloading - .def("begin", &RF24::begin) + .def("begin", &RF24::begin) .def("closeReadingPipe", &RF24::closeReadingPipe) - .def("disableCRC", &RF24::disableCRC) + .def("disableCRC", &RF24::disableCRC) .def("enableAckPayload", &RF24::enableAckPayload) - .def("enableDynamicAck", &RF24::enableDynamicAck) + .def("enableDynamicAck", &RF24::enableDynamicAck) .def("enableDynamicPayloads", &RF24::enableDynamicPayloads) .def("flush_tx", &RF24::flush_tx) .def("getCRCLength", &RF24::getCRCLength) .def("getDataRate", &RF24::getDataRate) .def("getDynamicPayloadSize", &RF24::getDynamicPayloadSize) .def("getPALevel", &RF24::getPALevel) - .def("isAckPayloadAvailable", &RF24::isAckPayloadAvailable) + .def("isAckPayloadAvailable", &RF24::isAckPayloadAvailable) .def("isPVariant", &RF24::isPVariant) .def("isValid", &RF24::isValid) - .def("maskIRQ", &RF24::maskIRQ, ( bp::arg("tx_ok"), bp::arg("tx_fail"), bp::arg("rx_ready"))) - .def("openReadingPipe", &openReadingPipe_wrap, (bp::arg("number"), bp::arg("address"))) - .def("openReadingPipe", (void ( ::RF24::* )( ::uint8_t,::uint64_t ) )( &::RF24::openReadingPipe), (bp::arg("number"), bp::arg("address"))) - .def("openWritingPipe", &openWritingPipe_wrap, (bp::arg("address"))) - .def("openWritingPipe", (void ( ::RF24::* )( ::uint64_t ) )( &::RF24::openWritingPipe), ( bp::arg("address") ) ) - .def("powerDown", &RF24::powerDown) - .def("powerUp", &RF24::powerUp) + .def("maskIRQ", &RF24::maskIRQ, ( bp::arg("tx_ok"), bp::arg("tx_fail"), bp::arg("rx_ready"))) + .def("openReadingPipe", &openReadingPipe_wrap, (bp::arg("number"), bp::arg("address"))) + .def("openReadingPipe", (void (::RF24::* )(::uint8_t,::uint64_t ))( &::RF24::openReadingPipe), (bp::arg("number"), bp::arg("address"))) + .def("openWritingPipe", &openWritingPipe_wrap, (bp::arg("address"))) + .def("openWritingPipe", (void (::RF24::* )(::uint64_t ))( &::RF24::openWritingPipe), ( bp::arg("address"))) + .def("powerDown", &RF24::powerDown) + .def("powerUp", &RF24::powerUp) .def("printDetails", &RF24::printDetails) .def("reUseTX", &RF24::reUseTX) - .def("read", &read_wrap, (bp::arg("maxlen"))) + .def("read", &read_wrap, (bp::arg("maxlen"))) .def("rxFifoFull", &RF24::rxFifoFull) .def("setAddressWidth", &RF24::setAddressWidth) - .def("setAutoAck", (void ( ::RF24::* )( bool ) )( &::RF24::setAutoAck ), ( bp::arg("enable") ) ) - .def("setAutoAck", (void ( ::RF24::* )( ::uint8_t,bool ) )( &::RF24::setAutoAck ), ( bp::arg("pipe"), bp::arg("enable") ) ) - .def("setCRCLength", &RF24::setCRCLength, ( bp::arg("length") ) ) - .def("setChannel", &RF24::setChannel, ( bp::arg("channel") ) ) - .def("setDataRate", &RF24::setDataRate, ( bp::arg("speed") ) ) - .def("setPALevel", &RF24::setPALevel, ( bp::arg("level") ) ) - .def("setRetries", &RF24::setRetries , (bp::arg("delay"), bp::arg("count"))) - .def("startFastWrite", &startFastWrite_wrap1, ( bp::arg("buf"), bp::arg("len"), bp::arg("multicast") ) ) - .def("startFastWrite", &startFastWrite_wrap2, ( bp::arg("buf"), bp::arg("len"), bp::arg("multicast"), bp::arg("startTx") ) ) - .def("startListening", &RF24::startListening) - .def("startWrite", &startWrite_wrap, ( bp::arg("buf"), bp::arg("len"), bp::arg("multicast") ) ) + .def("setAutoAck", (void (::RF24::* )( bool ))( &::RF24::setAutoAck ), ( bp::arg("enable"))) + .def("setAutoAck", (void (::RF24::* )(::uint8_t, bool ))( &::RF24::setAutoAck ), ( bp::arg("pipe"), bp::arg("enable"))) + .def("setCRCLength", &RF24::setCRCLength, ( bp::arg("length"))) + .def("setChannel", &RF24::setChannel, ( bp::arg("channel"))) + .def("setDataRate", &RF24::setDataRate, ( bp::arg("speed"))) + .def("setPALevel", &RF24::setPALevel, ( bp::arg("level"))) + .def("setRetries", &RF24::setRetries, (bp::arg("delay"), bp::arg("count"))) + .def("startFastWrite", &startFastWrite_wrap1, ( bp::arg("buf"), bp::arg("len"), bp::arg("multicast"))) + .def("startFastWrite", &startFastWrite_wrap2, ( bp::arg("buf"), bp::arg("len"), bp::arg("multicast"), bp::arg("startTx"))) + .def("startListening", &RF24::startListening) + .def("startWrite", &startWrite_wrap, ( bp::arg("buf"), bp::arg("len"), bp::arg("multicast"))) .def("stopListening", &RF24::stopListening) .def("testCarrier", &RF24::testCarrier) .def("testRPD", &RF24::testRPD) - .def("txStandBy", (bool ( ::RF24::* )( ::uint32_t,bool))(&RF24::txStandBy), txStandBy_wrap1( bp::args("timeout", "startTx") ) ) - .def("whatHappened", &whatHappened_wrap) - .def("write", &write_wrap1, ( bp::arg("buf") ) ) - .def("write", &write_wrap2, ( bp::arg("buf"), bp::arg("multicast") ) ) - .def("writeAckPayload", writeAckPayload_wrap, ( bp::arg("pipe"), bp::arg("buf") ) ) - .def("writeBlocking", &writeBlocking_wrap, ( bp::arg("buf"), bp::arg("timeout") ) ) - .def("writeFast", &writeFast_wrap1, ( bp::arg("buf") ) ) - .def("writeFast", &writeFast_wrap2, ( bp::arg("buf"), bp::arg("multicast") ) ) + .def("txStandBy", (bool (::RF24::* )(::uint32_t, bool))(&RF24::txStandBy), txStandBy_wrap1( bp::args("timeout", "startTx"))) + .def("whatHappened", &whatHappened_wrap) + .def("write", &write_wrap1, ( bp::arg("buf"))) + .def("write", &write_wrap2, ( bp::arg("buf"), bp::arg("multicast"))) + .def("writeAckPayload", writeAckPayload_wrap, ( bp::arg("pipe"), bp::arg("buf"))) + .def("writeBlocking", &writeBlocking_wrap, ( bp::arg("buf"), bp::arg("timeout"))) + .def("writeFast", &writeFast_wrap1, ( bp::arg("buf"))) + .def("writeFast", &writeFast_wrap2, ( bp::arg("buf"), bp::arg("multicast"))) .add_property("payloadSize", &RF24::getPayloadSize, &RF24::setPayloadSize) - .def_readwrite( "failureDetected", &RF24::failureDetected ); -} + .def_readwrite( "failureDetected", &RF24::failureDetected );} diff --git a/pyRF24/pyRF24Mesh/pyRF24Mesh.cpp b/pyRF24/pyRF24Mesh/pyRF24Mesh.cpp index 26f6afccd..da83a865d 100644 --- a/pyRF24/pyRF24Mesh/pyRF24Mesh.cpp +++ b/pyRF24/pyRF24Mesh/pyRF24Mesh.cpp @@ -15,91 +15,93 @@ void throw_ba_exception(void) bp::throw_error_already_set(); } -char *get_bytes_or_bytearray_str(bp::object buf) +char* get_bytes_or_bytearray_str(bp::object buf) { - PyObject *py_ba; + PyObject* py_ba; py_ba = buf.ptr(); - if (PyByteArray_Check(py_ba)) + if (PyByteArray_Check(py_ba)) { return PyByteArray_AsString(py_ba); - else if (PyBytes_Check(py_ba)) + } else if (PyBytes_Check(py_ba)) { return PyBytes_AsString(py_ba); - else + } else { throw_ba_exception(); + } return NULL; } int get_bytes_or_bytearray_ln(bp::object buf) { - PyObject *py_ba; + PyObject* py_ba; py_ba = buf.ptr(); - if (PyByteArray_Check(py_ba)) + if (PyByteArray_Check(py_ba)) { return PyByteArray_Size(py_ba); - else if (PyBytes_Check(py_ba)) + } else if (PyBytes_Check(py_ba)) { return PyBytes_Size(py_ba); - else + } else { throw_ba_exception(); + } return 0; } bool write_wrap1(RF24Mesh& ref, bp::object buf, uint8_t msg_type) { - return ref.write(get_bytes_or_bytearray_str(buf), msg_type, get_bytes_or_bytearray_ln(buf)); + return ref.write(get_bytes_or_bytearray_str(buf), msg_type, get_bytes_or_bytearray_ln(buf)); } bool write_wrap2(RF24Mesh& ref, bp::object buf, uint8_t msg_type, uint8_t nodeID) { - return ref.write(get_bytes_or_bytearray_str(buf), msg_type, get_bytes_or_bytearray_ln(buf), nodeID); + return ref.write(get_bytes_or_bytearray_str(buf), msg_type, get_bytes_or_bytearray_ln(buf), nodeID); } -bool write_to_node_wrap(RF24Mesh& ref, uint16_t to_node, bp::object buf, uint8_t msg_type) +bool write_to_node_wrap(RF24Mesh& ref, uint16_t to_node, bp::object buf, uint8_t msg_type) { - return ref.write(to_node, get_bytes_or_bytearray_str(buf), msg_type, get_bytes_or_bytearray_ln(buf)); + return ref.write(to_node, get_bytes_or_bytearray_str(buf), msg_type, get_bytes_or_bytearray_ln(buf)); } // ******************** overload wrappers ************************** -BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS(begin_overload, RF24Mesh::begin, 0, 3) -BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS(getNodeID_overload, RF24Mesh::getNodeID, 0, 1) -BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS(renewAddress_overload, RF24Mesh::renewAddress, 0, 1) +BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS(begin_overload, RF24Mesh::begin, +0, 3) +BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS(getNodeID_overload, RF24Mesh::getNodeID, +0, 1) +BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS(renewAddress_overload, RF24Mesh::renewAddress, +0, 1) // ******************** RF24Mesh exposed ************************** BOOST_PYTHON_MODULE(RF24Mesh) -{ - { //::RF24Mesh - bp::class_("RF24Mesh", bp::init((bp::arg("_radio"), bp::arg("_network")))) - //bool begin(uint8_t channel = MESH_DEFAULT_CHANNEL, rf24_datarate_e data_rate = RF24_1MBPS, uint32_t timeout=MESH_RENEWAL_TIMEOUT ); - .def("begin", &RF24Mesh::begin, begin_overload(bp::args("channel", "data_rate", "timeout"))) - //uint8_t update(); - .def("update", &RF24Mesh::update) - //bool write(const void* data, uint8_t msg_type, size_t size, uint8_t nodeID=0); - .def("write", &write_wrap1, (bp::arg("data"), bp::arg("msg_type"))) - .def("write", &write_wrap2, (bp::arg("data"), bp::arg("msg_type"), bp::arg("nodeID"))) - //bool write(uint16_t to_node, const void* data, uint8_t msg_type, size_t size ); - .def("write", &write_to_node_wrap, (bp::arg("to_node"), bp::arg("data"), bp::arg("msg_type"), bp::arg("size"))) - //void setNodeID(uint8_t nodeID); - .def("setNodeID", &RF24Mesh::setNodeID, (bp::arg("nodeID"))) - //void DHCP(); - .def("DHCP", &RF24Mesh::DHCP) - //int16_t getNodeID(uint16_t address=MESH_BLANK_ID); - .def("getNodeID", &RF24Mesh::getNodeID, getNodeID_overload(bp::args("address"))) - //bool checkConnection(); - .def("checkConnection", &RF24Mesh::checkConnection) - //uint16_t renewAddress(uint32_t timeout=MESH_RENEWAL_TIMEOUT); - .def("renewAddress", &RF24Mesh::renewAddress, getNodeID_overload(bp::args("timeout"))) - //bool releaseAddress(); - .def("releaseAddress", &RF24Mesh::releaseAddress) - //int16_t getAddress(uint8_t nodeID); - .def("getAddress", &RF24Mesh::getAddress, (bp::arg("nodeID"))) - //void setChannel(uint8_t _channel); - .def("setChannel", &RF24Mesh::setChannel, (bp::arg("_channel"))) - //void setChild(bool allow); - .def("setChild", &RF24Mesh::setChild, (bp::arg("allow"))) - //void setAddress(uint8_t nodeID, uint16_t address); - .def("setAddress", &RF24Mesh::setAddress, (bp::arg("nodeID"), bp::arg("address"))) - //void saveDHCP(); - .def("saveDHCP", &RF24Mesh::saveDHCP) - //void loadDHCP(); - .def("loadDHCP", &RF24Mesh::loadDHCP) - //void setStaticAddress(uint8_t nodeID, uint16_t address); - .def("setStaticAddress", &RF24Mesh::setStaticAddress, (bp::arg("nodeID"), bp::arg("address"))); - } -} \ No newline at end of file + {{ //::RF24Mesh + bp::class_("RF24Mesh", bp::init((bp::arg("_radio"), bp::arg("_network")))) + //bool begin(uint8_t channel = MESH_DEFAULT_CHANNEL, rf24_datarate_e data_rate = RF24_1MBPS, uint32_t timeout=MESH_RENEWAL_TIMEOUT ); + .def("begin", &RF24Mesh::begin, begin_overload(bp::args("channel", "data_rate", "timeout"))) + //uint8_t update(); + .def("update", &RF24Mesh::update) + //bool write(const void* data, uint8_t msg_type, size_t size, uint8_t nodeID=0); + .def("write", &write_wrap1, (bp::arg("data"), bp::arg("msg_type"))).def("write", &write_wrap2, + (bp::arg("data"), bp::arg("msg_type"), bp::arg("nodeID"))) + //bool write(uint16_t to_node, const void* data, uint8_t msg_type, size_t size ); + .def("write", &write_to_node_wrap, (bp::arg("to_node"), bp::arg("data"), bp::arg("msg_type"), bp::arg("size"))) + //void setNodeID(uint8_t nodeID); + .def("setNodeID", &RF24Mesh::setNodeID, (bp::arg("nodeID"))) + //void DHCP(); + .def("DHCP", &RF24Mesh::DHCP) + //int16_t getNodeID(uint16_t address=MESH_BLANK_ID); + .def("getNodeID", &RF24Mesh::getNodeID, getNodeID_overload(bp::args("address"))) + //bool checkConnection(); + .def("checkConnection", &RF24Mesh::checkConnection) + //uint16_t renewAddress(uint32_t timeout=MESH_RENEWAL_TIMEOUT); + .def("renewAddress", &RF24Mesh::renewAddress, getNodeID_overload(bp::args("timeout"))) + //bool releaseAddress(); + .def("releaseAddress", &RF24Mesh::releaseAddress) + //int16_t getAddress(uint8_t nodeID); + .def("getAddress", &RF24Mesh::getAddress, (bp::arg("nodeID"))) + //void setChannel(uint8_t _channel); + .def("setChannel", &RF24Mesh::setChannel, (bp::arg("_channel"))) + //void setChild(bool allow); + .def("setChild", &RF24Mesh::setChild, (bp::arg("allow"))) + //void setAddress(uint8_t nodeID, uint16_t address); + .def("setAddress", &RF24Mesh::setAddress, (bp::arg("nodeID"), bp::arg("address"))) + //void saveDHCP(); + .def("saveDHCP", &RF24Mesh::saveDHCP) + //void loadDHCP(); + .def("loadDHCP", &RF24Mesh::loadDHCP) + //void setStaticAddress(uint8_t nodeID, uint16_t address); + .def("setStaticAddress", &RF24Mesh::setStaticAddress, (bp::arg("nodeID"), bp::arg("address")));}} \ No newline at end of file diff --git a/utility/ATTiny/RF24_arch_config.h b/utility/ATTiny/RF24_arch_config.h index 16b512cbd..dc5b0aa42 100644 --- a/utility/ATTiny/RF24_arch_config.h +++ b/utility/ATTiny/RF24_arch_config.h @@ -1,4 +1,3 @@ - /* TMRh20 2015 ATTiny Configuration File @@ -7,41 +6,41 @@ #ifndef __RF24_ARCH_CONFIG_H__ #define __RF24_ARCH_CONFIG_H__ - /*** USER DEFINES: ***/ - //#define FAILURE_HANDLING - //#define MINIMAL - /**********************/ - - #define rf24_max(a,b) (a>b?a:b) - #define rf24_min(a,b) (a - #else - #include - #endif - #include - - // Include the header file for SPI functions ( Main SPI code is contained in RF24.cpp for simplicity ) - #include "spi.h" - - #define _SPI SPI - - #ifdef SERIAL_DEBUG - #define IF_SERIAL_DEBUG(x) ({x;}) - #else - #define IF_SERIAL_DEBUG(x) - #if defined(RF24_TINY) - #define printf_P(...) +/*** USER DEFINES: ***/ +//#define FAILURE_HANDLING +//#define MINIMAL +/**********************/ + +#define rf24_max(a, b) (a>b?a:b) +#define rf24_min(a, b) (a + +#else + #include +#endif + +#include + +// Include the header file for SPI functions ( Main SPI code is contained in RF24.cpp for simplicity ) +#include "spi.h" + +#define _SPI SPI + +#ifdef SERIAL_DEBUG + #define IF_SERIAL_DEBUG(x) ({x;}) +#else + #define IF_SERIAL_DEBUG(x) + #if defined(RF24_TINY) + #define printf_P(...) #endif - #endif +#endif + +#include - #include - #define PRIPSTR "%S" - - +#define PRIPSTR "%S" #endif // __RF24_ARCH_CONFIG_H__ diff --git a/utility/ATTiny/spi.h b/utility/ATTiny/spi.h index c1864b5f4..4cba54d4c 100644 --- a/utility/ATTiny/spi.h +++ b/utility/ATTiny/spi.h @@ -5,7 +5,7 @@ * \cond HIDDEN_SYMBOLS * Class declaration for SPI helper files */ - + #include #include #include @@ -28,24 +28,26 @@ #define SPI_CLOCK_MASK 0x03 // SPR1 = bit 1, SPR0 = bit 0 on SPCR #define SPI_2XCLOCK_MASK 0x01 // SPI2X = bit 0 on SPSR - - class SPIClass { public: - static byte transfer(byte _data); + static byte transfer(byte _data); + + // SPI Configuration methods - // SPI Configuration methods + inline static void attachInterrupt(); - inline static void attachInterrupt(); - inline static void detachInterrupt(); // Default + inline static void detachInterrupt(); // Default - static void begin(); // Default - static void end(); + static void begin(); // Default + static void end(); - static void setBitOrder(uint8_t); - static void setDataMode(uint8_t); - static void setClockDivider(uint8_t); + static void setBitOrder(uint8_t); + + static void setDataMode(uint8_t); + + static void setClockDivider(uint8_t); }; + extern SPIClass SPI; /** diff --git a/utility/ATXMegaD3/RF24_arch_config.h b/utility/ATXMegaD3/RF24_arch_config.h index 53cc2f1af..9e1ba3fb9 100644 --- a/utility/ATXMegaD3/RF24_arch_config.h +++ b/utility/ATXMegaD3/RF24_arch_config.h @@ -1,4 +1,3 @@ - /* Copyright (C) 2011 J. Coliz @@ -7,22 +6,22 @@ version 2 as published by the Free Software Foundation. */ - - /** - * @file RF24_arch_config.h - * General defines and includes for RF24/Linux - */ - /** - * Example of RF24_arch_config.h for RF24 portability - * - * @defgroup Porting_General Porting: General - * - * - * @{ - */ - - +/** +* @file RF24_arch_config.h +* General defines and includes for RF24/Linux +*/ + +/** +* Example of RF24_arch_config.h for RF24 portability +* +* @defgroup Porting_General Porting: General +* +* +* @{ +*/ + + #ifndef __RF24_ARCH_CONFIG_H__ #define __RF24_ARCH_CONFIG_H__ @@ -42,9 +41,9 @@ #undef SERIAL_DEBUG #ifdef SERIAL_DEBUG -#define IF_SERIAL_DEBUG(x) ({x;}) + #define IF_SERIAL_DEBUG(x) ({x;}) #else -#define IF_SERIAL_DEBUG(x) + #define IF_SERIAL_DEBUG(x) #endif // Use the avr pgmspace commands @@ -78,7 +77,6 @@ typedef uint16_t prog_uint16_t; #define delayMicroseconds(usec) __usleep(usec) #define millis() __millis() - #endif // __RF24_ARCH_CONFIG_H__ diff --git a/utility/ATXMegaD3/compatibility.c b/utility/ATXMegaD3/compatibility.c index e909ea5af..b3c246824 100644 --- a/utility/ATXMegaD3/compatibility.c +++ b/utility/ATXMegaD3/compatibility.c @@ -3,7 +3,7 @@ * * Created: 19/1/2016 15:31:35 * Author: akatran - */ + */ #include #include @@ -13,53 +13,50 @@ volatile uint32_t _millis; void __msleep(int milisec) { - while(milisec-- >0) - { - _delay_ms(1); - } + while (milisec -- > 0) { + _delay_ms(1); + } } void __usleep(int usec) { - while(usec-- >0) - { - _delay_us(1); - } + while (usec -- > 0) { + _delay_us(1); + } } - void __start_timer() { - - // Timer details : Clock is 32MHz, Timer resolution is 8bit, Prescaler is 256, Period is 124, Real Time is 0.001s - /* Set the timer to run at the fastest rate. */ - TCE0.CTRLA = TC_CLKSEL_DIV256_gc; + // Timer details : Clock is 32MHz, Timer resolution is 8bit, Prescaler is 256, Period is 124, Real Time is 0.001s + + /* Set the timer to run at the fastest rate. */ + TCE0.CTRLA = TC_CLKSEL_DIV256_gc; + + /* Configure the timer for normal counting. */ + TCE0.CTRLB = TC_WGMODE_NORMAL_gc; - /* Configure the timer for normal counting. */ - TCE0.CTRLB = TC_WGMODE_NORMAL_gc; + /* At 2 MHz, one tick is 0.5 us. Set period to 8 us. */ + TCE0.PER = 124; + //TCC0.PER = 2; - /* At 2 MHz, one tick is 0.5 us. Set period to 8 us. */ - TCE0.PER = 124; - //TCC0.PER = 2; + /* Configure timer to generate an interrupt on overflow. */ + TCE0.INTCTRLA = TC_OVFINTLVL_HI_gc; - /* Configure timer to generate an interrupt on overflow. */ - TCE0.INTCTRLA = TC_OVFINTLVL_HI_gc; + /* Enable this interrupt level. */ + PMIC.CTRL = PMIC_LOLVLEN_bm | PMIC_MEDLVLEN_bm | PMIC_HILVLEN_bm; - /* Enable this interrupt level. */ - PMIC.CTRL = PMIC_LOLVLEN_bm | PMIC_MEDLVLEN_bm | PMIC_HILVLEN_bm; - - _millis=0; + _millis = 0; } long __millis() { - return _millis; + return _millis; } void update_milisec() { - _millis++; + _millis ++; } diff --git a/utility/ATXMegaD3/compatibility.h b/utility/ATXMegaD3/compatibility.h index 7eda40f1c..e6fc03c78 100644 --- a/utility/ATXMegaD3/compatibility.h +++ b/utility/ATXMegaD3/compatibility.h @@ -5,41 +5,45 @@ * Created on 24 June 2012, 3:08 PM */ - /** - * @file compatibility.h - * Class declaration for SPI helper files - */ +/** +* @file compatibility.h +* Class declaration for SPI helper files +*/ + +/** +* Example of compatibility.h class declaration for timing functions portability +* +* @defgroup Porting_Timing Porting: Timing +* +* +* @{ +*/ - /** - * Example of compatibility.h class declaration for timing functions portability - * - * @defgroup Porting_Timing Porting: Timing - * - * - * @{ - */ - #ifndef COMPATIBLITY_H -#define COMPATIBLITY_H +#define COMPATIBLITY_H -#ifdef __cplusplus +#ifdef __cplusplus extern "C" { #endif - + #include //#include //#include void __msleep(int milisec); + void __usleep(int usec); + void __start_timer(); + long __millis(); + void update_milisec(); -#ifdef __cplusplus +#ifdef __cplusplus } #endif -#endif /* COMPATIBLITY_H */ +#endif /* COMPATIBLITY_H */ /*@}*/ \ No newline at end of file diff --git a/utility/ATXMegaD3/gpio.cpp b/utility/ATXMegaD3/gpio.cpp index 6f2321b3e..897847a07 100644 --- a/utility/ATXMegaD3/gpio.cpp +++ b/utility/ATXMegaD3/gpio.cpp @@ -3,7 +3,7 @@ * * Created: 20/1/2016 11:57:21 * Author: akatran - */ + */ //#include "gpio_helper.h" #include "gpio.h" @@ -11,40 +11,36 @@ void GPIO::open(int port, int DDR) { - uint8_t pin; - PORT_t * p = GPIO_getPort(port,&pin); - if (DDR==0) - { - p->DIRCLR=pin; - }else if (DDR==1) - { - p->DIRSET = pin; - } + uint8_t pin; + PORT_t* p = GPIO_getPort(port, &pin); + if (DDR == 0) { + p->DIRCLR = pin; + } else if (DDR == 1) { + p->DIRSET = pin; + } } void GPIO::close(int port) { - // Nothing to do with close; + // Nothing to do with close; } int read(int port) { - uint8_t pin; - PORT_t * p = GPIO_getPort(port,&pin); - return p->IN; + uint8_t pin; + PORT_t* p = GPIO_getPort(port, &pin); + return p->IN; } -void GPIO::write(int port,int value) +void GPIO::write(int port, int value) { - uint8_t pin; - PORT_t * p = GPIO_getPort(port,&pin); - if (value==0) - { - p->OUTCLR=pin; - }else if (value==1) - { - p->OUTSET = pin; - } - + uint8_t pin; + PORT_t* p = GPIO_getPort(port, &pin); + if (value == 0) { + p->OUTCLR = pin; + } else if (value == 1) { + p->OUTSET = pin; + } + } diff --git a/utility/ATXMegaD3/gpio.h b/utility/ATXMegaD3/gpio.h index b3e65990e..50acc91cc 100644 --- a/utility/ATXMegaD3/gpio.h +++ b/utility/ATXMegaD3/gpio.h @@ -5,59 +5,61 @@ * Class declaration for SPI helper files */ - /** - * Example of gpio.h class declaration for GPIO portability - * - * @defgroup Porting_GPIO Porting: GPIO - * - * - * @{ - */ +/** +* Example of gpio.h class declaration for GPIO portability +* +* @defgroup Porting_GPIO Porting: GPIO +* +* +* @{ +*/ #ifndef GPIO_H -#define GPIO_H +#define GPIO_H #include #include "gpio_helper.h" - class GPIO { public: - /* Constants */ - static const int DIRECTION_OUT = 1; - static const int DIRECTION_IN = 0; - - static const int OUTPUT_HIGH = 1; - static const int OUTPUT_LOW = 0; - - GPIO(); - - /** - * Similar to Arduino pinMode(pin,mode); + /* Constants */ + static const int DIRECTION_OUT = 1; + static const int DIRECTION_IN = 0; + + static const int OUTPUT_HIGH = 1; + static const int OUTPUT_LOW = 0; + + GPIO(); + + /** + * Similar to Arduino pinMode(pin,mode); * @param port * @param DDR */ - static void open(int port, int DDR); - /** - * + static void open(int port, int DDR); + + /** + * * @param port */ - static void close(int port); - /** - * Similar to Arduino digitalRead(pin); + static void close(int port); + + /** + * Similar to Arduino digitalRead(pin); * @param port * @param value */ - static int read(int port); - /** - * Similar to Arduino digitalWrite(pin,state); - * @param port - * @param value - */ - static void write(int port,int value); - - virtual ~GPIO(); + static int read(int port); + + /** + * Similar to Arduino digitalWrite(pin,state); + * @param port + * @param value + */ + static void write(int port, int value); + + virtual ~GPIO(); }; -#endif /* GPIO_H */ +#endif /* GPIO_H */ /*@}*/ \ No newline at end of file diff --git a/utility/ATXMegaD3/gpio_helper.c b/utility/ATXMegaD3/gpio_helper.c index f0b66ce49..a0b5245d8 100644 --- a/utility/ATXMegaD3/gpio_helper.c +++ b/utility/ATXMegaD3/gpio_helper.c @@ -3,43 +3,37 @@ * * Created: 22/1/2016 15:28:48 * Author: akatran - */ + */ #include "gpio_helper.h" /** * Get the port corresponding in portnum. Default is PORTC. */ -PORT_t * GPIO_getPort(int pinnum, uint8_t * pin_bm) +PORT_t* GPIO_getPort(int pinnum, uint8_t* pin_bm) //PORT_t * GPIO_getPort(int portnum) { - PORT_t * port = &PORTC; - if ( (pinnum >= XMEGA_PORTA_PIN0) && (pinnum<= XMEGA_PORTA_PIN7) ) - { - port = &PORTA; - *pin_bm = (1<= XMEGA_PORTB_PIN0) && (pinnum<= XMEGA_PORTB_PIN7) ) - { - port = &PORTB; - *pin_bm = (1<<(pinnum-8)); - }else if ( (pinnum >= XMEGA_PORTC_PIN0) && (pinnum<= XMEGA_PORTC_PIN7) ) - { - port = &PORTC; - *pin_bm = (1<<(pinnum-16)); - }else if ( (pinnum >= XMEGA_PORTD_PIN0) && (pinnum<= XMEGA_PORTD_PIN7) ) - { - port = &PORTD; - *pin_bm = (1<<(pinnum-24)); - }else if ( (pinnum >= XMEGA_PORTE_PIN0) && (pinnum<= XMEGA_PORTE_PIN7) ) - { - port = &PORTE; - *pin_bm = (1<<(pinnum-32)); - }else if ( (pinnum >= XMEGA_PORTF_PIN0) && (pinnum<= XMEGA_PORTF_PIN7) ) - { - port = &PORTF; - *pin_bm = (1<<(pinnum-40)); - } + PORT_t* port = &PORTC; + if ((pinnum >= XMEGA_PORTA_PIN0) && (pinnum <= XMEGA_PORTA_PIN7)) { + port = &PORTA; + *pin_bm = (1 << pinnum); + } else if ((pinnum >= XMEGA_PORTB_PIN0) && (pinnum <= XMEGA_PORTB_PIN7)) { + port = &PORTB; + *pin_bm = (1 << (pinnum - 8)); + } else if ((pinnum >= XMEGA_PORTC_PIN0) && (pinnum <= XMEGA_PORTC_PIN7)) { + port = &PORTC; + *pin_bm = (1 << (pinnum - 16)); + } else if ((pinnum >= XMEGA_PORTD_PIN0) && (pinnum <= XMEGA_PORTD_PIN7)) { + port = &PORTD; + *pin_bm = (1 << (pinnum - 24)); + } else if ((pinnum >= XMEGA_PORTE_PIN0) && (pinnum <= XMEGA_PORTE_PIN7)) { + port = &PORTE; + *pin_bm = (1 << (pinnum - 32)); + } else if ((pinnum >= XMEGA_PORTF_PIN0) && (pinnum <= XMEGA_PORTF_PIN7)) { + port = &PORTF; + *pin_bm = (1 << (pinnum - 40)); + } - return port; + return port; } \ No newline at end of file diff --git a/utility/ATXMegaD3/gpio_helper.h b/utility/ATXMegaD3/gpio_helper.h index 27a380d87..1146fb015 100644 --- a/utility/ATXMegaD3/gpio_helper.h +++ b/utility/ATXMegaD3/gpio_helper.h @@ -3,7 +3,7 @@ * * Created: 22/1/2016 15:29:12 * Author: akatran - */ + */ #ifndef GPIO_HELPER_H_ @@ -11,7 +11,7 @@ #include -#ifdef __cplusplus +#ifdef __cplusplus extern "C" { #endif @@ -72,17 +72,14 @@ extern "C" { #define XMEGA_PORTF_PIN6 46 #define XMEGA_PORTF_PIN7 47 - - #define XMEGA_SPI_PORT_C 20 #define XMEGA_SPI_PORT_D 28 - //void GPIO_getPort(int pinnum, PORT_t * port, uint8_t pin); //void GPIO_getPort(int pinnum, PORT_t * port, uint8_t * pin_bm); -PORT_t * GPIO_getPort(int pinnum, uint8_t * pin_bm); +PORT_t* GPIO_getPort(int pinnum, uint8_t* pin_bm); -#ifdef __cplusplus +#ifdef __cplusplus } #endif diff --git a/utility/ATXMegaD3/includes.h b/utility/ATXMegaD3/includes.h index 7596433aa..cf12b0302 100644 --- a/utility/ATXMegaD3/includes.h +++ b/utility/ATXMegaD3/includes.h @@ -1,31 +1,30 @@ +/** +* @file includes.h +* Configuration defines for RF24/Linux +*/ - /** - * @file includes.h - * Configuration defines for RF24/Linux - */ +/** +* Example of includes.h for RF24 Linux portability +* +* @defgroup Porting_Includes Porting: Includes +* +* +* @{ +*/ - /** - * Example of includes.h for RF24 Linux portability - * - * @defgroup Porting_Includes Porting: Includes - * - * - * @{ - */ - #ifndef __RF24_INCLUDES_H__ #define __RF24_INCLUDES_H__ - /** - * Define a specific platform for this configuration - */ - // #define RF24_BBB - - /** - * Load the correct configuration for this platform - */ - //#include "BBB/RF24_arch_config.h" - +/** + * Define a specific platform for this configuration + */ +// #define RF24_BBB + +/** + * Load the correct configuration for this platform +*/ +//#include "BBB/RF24_arch_config.h" + #endif /*@}*/ \ No newline at end of file diff --git a/utility/ATXMegaD3/spi.cpp b/utility/ATXMegaD3/spi.cpp index f173dbe84..3db959c3b 100644 --- a/utility/ATXMegaD3/spi.cpp +++ b/utility/ATXMegaD3/spi.cpp @@ -3,7 +3,7 @@ * * Created: 20/1/2016 10:10:39 * Author: akatran - */ + */ #include #include "gpio_helper.h" @@ -13,52 +13,51 @@ using namespace std; void SPI::begin(uint8_t _port) { - if (_port==XMEGA_SPI_PORT_C) // Select SPI on PORTC - { - device = &SPIC; - port = &PORTC; - }else if (_port==XMEGA_SPI_PORT_D) // Select SPI on PORTD - { - device = &SPID; - port = &PORTD; - } - - init(); + if (_port == XMEGA_SPI_PORT_C) // Select SPI on PORTC + { + device = &SPIC; + port = &PORTC; + } else if (_port == XMEGA_SPI_PORT_D) // Select SPI on PORTD + { + device = &SPID; + port = &PORTD; + } + + init(); } uint8_t SPI::transfer(uint8_t tx_) { - register8_t data; - device->DATA = tx_; - while(!(device->STATUS & (1<<7))); - data = device->DATA; - //PORTF.OUT = data; - return data; + register8_t data; + device->DATA = tx_; + while (! (device->STATUS & (1 << 7))); + data = device->DATA; + //PORTF.OUT = data; + return data; } void SPI::init() { - port->DIRCLR = SPI_MISO_bm; - port->DIRSET = SPI_MOSI_bm | SPI_SCK_bm | SPI_SS_bm; - - //device->CTRL = 0; - device->CTRL = SPI_ENABLE_bm | SPI_MASTER_bm | SPI_MODE_0_gc | SPI_PRESCALER_DIV4_gc; - device->INTCTRL =0; //Disable interrupts + port->DIRCLR = SPI_MISO_bm; + port->DIRSET = SPI_MOSI_bm | SPI_SCK_bm | SPI_SS_bm; -} + //device->CTRL = 0; + device->CTRL = SPI_ENABLE_bm | SPI_MASTER_bm | SPI_MODE_0_gc | SPI_PRESCALER_DIV4_gc; + device->INTCTRL = 0; //Disable interrupts +} SPI::SPI() { - + } SPI::~SPI() { - + } -void operator delete(void * p) // or delete(void *, std::size_t) +void operator delete(void* p) // or delete(void *, std::size_t) { } \ No newline at end of file diff --git a/utility/ATXMegaD3/spi.h b/utility/ATXMegaD3/spi.h index b792c1980..caf479236 100644 --- a/utility/ATXMegaD3/spi.h +++ b/utility/ATXMegaD3/spi.h @@ -1,17 +1,16 @@ - /** * @file spi.h * Class declaration for SPI helper files */ - /** - * Example of spi.h class declaration for SPI portability - * - * @defgroup Porting_SPI Porting: SPI - * - * - * @{ - */ +/** +* Example of spi.h class declaration for SPI portability +* +* @defgroup Porting_SPI Porting: SPI +* +* +* @{ +*/ #ifndef __XMEGASPI_H__ #define __XMEGASPI_H__ @@ -36,53 +35,52 @@ using namespace std; - - class SPI { public: - /** - * SPI constructor - */ - SPI(); - - /** - * Start SPI - * @param port is the SPI port (XMEGA_SPI_PORT_C for SPI on PORTC, XMEGA_SPI_PORT_D on PORTD etc). - */ - void begin(uint8_t port); - /** - * Transfer a single byte - * @param tx_ Byte to send - * @return Data returned via spi - */ - uint8_t transfer(uint8_t tx_); - - /** - * Transfer a buffer of data - * @param tbuf Transmit buffer - * @param rbuf Receive buffer - * @param len Length of the data - */ - void transfernb(char* tbuf, char* rbuf, uint32_t len); - - /** - * Transfer a buffer of data without an rx buffer - * @param buf Pointer to a buffer of data - * @param len Length of the data - */ - void transfern(char* buf, uint32_t len); - - virtual ~SPI(); + /** + * SPI constructor + */ + SPI(); + + /** + * Start SPI + * @param port is the SPI port (XMEGA_SPI_PORT_C for SPI on PORTC, XMEGA_SPI_PORT_D on PORTD etc). + */ + void begin(uint8_t port); + + /** + * Transfer a single byte + * @param tx_ Byte to send + * @return Data returned via spi + */ + uint8_t transfer(uint8_t tx_); + + /** + * Transfer a buffer of data + * @param tbuf Transmit buffer + * @param rbuf Receive buffer + * @param len Length of the data + */ + void transfernb(char* tbuf, char* rbuf, uint32_t len); + + /** + * Transfer a buffer of data without an rx buffer + * @param buf Pointer to a buffer of data + * @param len Length of the data + */ + void transfern(char* buf, uint32_t len); + + virtual ~SPI(); private: - - /** Default SPI device */ - SPI_t * device; - /* Port of the SPI */ - PORT_t * port; - void init(); + /** Default SPI device */ + SPI_t* device; + /* Port of the SPI */ + PORT_t* port; + + void init(); }; #endif /*__XMEGASPI_H__*/ diff --git a/utility/Due/RF24_arch_config.h b/utility/Due/RF24_arch_config.h index 73daa902e..53399e319 100644 --- a/utility/Due/RF24_arch_config.h +++ b/utility/Due/RF24_arch_config.h @@ -1,37 +1,35 @@ - /* TMRh20 2015 RF24 Configuration file for Arduino Due - */ +*/ #ifndef __RF24_ARCH_CONFIG_H__ #define __RF24_ARCH_CONFIG_H__ - /*** USER DEFINES: ***/ - //#define FAILURE_HANDLING - //#define SERIAL_DEBUG - //#define MINIMAL - /**********************/ - #define rf24_max(a,b) (a>b?a:b) - #define rf24_min(a,b) (a - #include - - #define _BV(x) (1<<(x)) - #define _SPI SPI - - #ifdef SERIAL_DEBUG - #define IF_SERIAL_DEBUG(x) ({x;}) - #else - #define IF_SERIAL_DEBUG(x) - #endif - - #define printf_P printf - #define strlen_P strlen - #define PRIPSTR "%s" - +/*** USER DEFINES: ***/ +//#define FAILURE_HANDLING +//#define SERIAL_DEBUG +//#define MINIMAL +/**********************/ +#define rf24_max(a, b) (a>b?a:b) +#define rf24_min(a, b) (a +#include + +#define _BV(x) (1<<(x)) +#define _SPI SPI + +#ifdef SERIAL_DEBUG + #define IF_SERIAL_DEBUG(x) ({x;}) +#else + #define IF_SERIAL_DEBUG(x) +#endif + +#define printf_P printf +#define strlen_P strlen +#define PRIPSTR "%s" #endif // __RF24_CONFIG_H__ diff --git a/utility/LittleWire/RF24_arch_config.h b/utility/LittleWire/RF24_arch_config.h index 512db47f5..9bf308d8c 100644 --- a/utility/LittleWire/RF24_arch_config.h +++ b/utility/LittleWire/RF24_arch_config.h @@ -2,38 +2,38 @@ #define __ARCH_CONFIG_H__ #include - #include - #include - #include - #include - #include +#include +#include +#include +#include +#include - // Additional fixes for LittleWire - #include - #include - extern LittleWireSPI _SPI; +// Additional fixes for LittleWire +#include +#include - // GCC a Arduino Missing - #define _BV(x) (1<<(x)) - #define pgm_read_word(p) (*(p)) - #define pgm_read_byte(p) (*(p)) - #define pgm_read_ptr(p) (*(p)) - - //typedef uint16_t prog_uint16_t; - #define PSTR(x) (x) - #define printf_P printf - #define strlen_P strlen - #define PROGMEM - #define PRIPSTR "%s" +extern LittleWireSPI _SPI; - #ifdef SERIAL_DEBUG - #define IF_SERIAL_DEBUG(x) ({x;}) - #else - #define IF_SERIAL_DEBUG(x) - #if defined(RF24_TINY) - #define printf_P(...) +// GCC a Arduino Missing +#define _BV(x) (1<<(x)) +#define pgm_read_word(p) (*(p)) +#define pgm_read_byte(p) (*(p)) +#define pgm_read_ptr(p) (*(p)) + +//typedef uint16_t prog_uint16_t; +#define PSTR(x) (x) +#define printf_P printf +#define strlen_P strlen +#define PROGMEM +#define PRIPSTR "%s" + +#ifdef SERIAL_DEBUG + #define IF_SERIAL_DEBUG(x) ({x;}) +#else + #define IF_SERIAL_DEBUG(x) + #if defined(RF24_TINY) + #define printf_P(...) #endif - #endif - - +#endif + #endif diff --git a/utility/LittleWire/includes.h b/utility/LittleWire/includes.h index 8e4b6af0f..197e4473f 100644 --- a/utility/LittleWire/includes.h +++ b/utility/LittleWire/includes.h @@ -1,31 +1,30 @@ +/** +* @file includes.h +* Configuration defines for RF24/Linux +*/ - /** - * @file includes.h - * Configuration defines for RF24/Linux - */ +/** +* Example of includes.h for RF24 Linux portability +* +* @defgroup Porting_Includes Porting: Includes +* +* +* @{ +*/ - /** - * Example of includes.h for RF24 Linux portability - * - * @defgroup Porting_Includes Porting: Includes - * - * - * @{ - */ - #ifndef __RF24_INCLUDES_H__ #define __RF24_INCLUDES_H__ - /** - * Define a specific platform for this configuration - */ - #define LITTLEWIRE - - /** - * Load the correct configuration for this platform - */ - #include "LittleWire/RF24_arch_config.h" - +/** + * Define a specific platform for this configuration + */ +#define LITTLEWIRE + +/** + * Load the correct configuration for this platform +*/ +#include "LittleWire/RF24_arch_config.h" + #endif /*@}*/ diff --git a/utility/MRAA/RF24_arch_config.h b/utility/MRAA/RF24_arch_config.h index e4683ddc1..463791067 100644 --- a/utility/MRAA/RF24_arch_config.h +++ b/utility/MRAA/RF24_arch_config.h @@ -1,64 +1,64 @@ #ifndef __ARCH_CONFIG_H__ #define __ARCH_CONFIG_H__ - #include "mraa.h" - #include "spi.h" - #include "gpio.h" - #include "compatibility.h" +#include "mraa.h" +#include "spi.h" +#include "gpio.h" +#include "compatibility.h" - #include - #include - #include - #include - #include - #include - #include - #include - #include - - //#include // Precompiled arduino x86 based utiltime for timing functions +#include +#include +#include +#include +#include +#include +#include +#include +#include - // GCC a Arduino Missing - #define HIGH 1 - #define LOW 0 - #define _BV(x) (1<<(x)) - #define pgm_read_word(p) (*(p)) - #define pgm_read_byte(p) (*(p)) - #define pgm_read_ptr(p) (*(p)) - #define _SPI spi - - #define RF24_LINUX - //typedef uint16_t prog_uint16_t; - #define PSTR(x) (x) - #define printf_P printf - #define sprintf_P sprintf - #define strlen_P strlen - #define PROGMEM - #define PRIPSTR "%s" +//#include // Precompiled arduino x86 based utiltime for timing functions - #ifdef SERIAL_DEBUG - #define IF_SERIAL_DEBUG(x) ({x;}) - #else - #define IF_SERIAL_DEBUG(x) - #endif - - #define digitalWrite(pin, value) gpio.write(pin, value) - #define digitalRead(pin) GPIO::read(pin) - #define pinMode(pin, direction) gpio.open(pin, direction) +// GCC a Arduino Missing +#define HIGH 1 +#define LOW 0 +#define _BV(x) (1<<(x)) +#define pgm_read_word(p) (*(p)) +#define pgm_read_byte(p) (*(p)) +#define pgm_read_ptr(p) (*(p)) +#define _SPI spi - #ifndef __TIME_H__ - // Prophet: Redefine time functions only if precompiled arduino time is not included - #define delay(milisec) __msleep(milisec) - #define delayMicroseconds(usec) __usleep(usec) - #define millis() __millis() - #endif - - #define INPUT mraa::DIR_IN - #define OUTPUT mraa::DIR_OUT +#define RF24_LINUX +//typedef uint16_t prog_uint16_t; +#define PSTR(x) (x) +#define printf_P printf +#define sprintf_P sprintf +#define strlen_P strlen +#define PROGMEM +#define PRIPSTR "%s" - // SPI defines for ARDUINO API - #define MSBFIRST 1 - #define SPI_MODE0 mraa::SPI_MODE0 - #define SPI_CLOCK_DIV2 8000000 +#ifdef SERIAL_DEBUG + #define IF_SERIAL_DEBUG(x) ({x;}) +#else + #define IF_SERIAL_DEBUG(x) +#endif + +#define digitalWrite(pin, value) gpio.write(pin, value) +#define digitalRead(pin) GPIO::read(pin) +#define pinMode(pin, direction) gpio.open(pin, direction) + +#ifndef __TIME_H__ +// Prophet: Redefine time functions only if precompiled arduino time is not included + #define delay(milisec) __msleep(milisec) + #define delayMicroseconds(usec) __usleep(usec) + #define millis() __millis() +#endif + +#define INPUT mraa::DIR_IN +#define OUTPUT mraa::DIR_OUT + +// SPI defines for ARDUINO API +#define MSBFIRST 1 +#define SPI_MODE0 mraa::SPI_MODE0 +#define SPI_CLOCK_DIV2 8000000 #endif diff --git a/utility/MRAA/compatibility.c b/utility/MRAA/compatibility.c index afe555df1..bb8839804 100644 --- a/utility/MRAA/compatibility.c +++ b/utility/MRAA/compatibility.c @@ -1,4 +1,3 @@ - #include "compatibility.h" static struct timeval start, end; @@ -11,20 +10,20 @@ static struct timeval start, end; */ void __msleep(int milisec) { - struct timespec req = {0}; - req.tv_sec = 0; - req.tv_nsec = milisec * 1000000L; - nanosleep(&req, (struct timespec *)NULL); - //usleep(milisec*1000); + struct timespec req = {0}; + req.tv_sec = 0; + req.tv_nsec = milisec * 1000000L; + nanosleep(&req, (struct timespec*) NULL); + //usleep(milisec*1000); } void __usleep(int milisec) { - struct timespec req = {0}; - req.tv_sec = 0; - req.tv_nsec = milisec * 1000L; - nanosleep(&req, (struct timespec *)NULL); - //usleep(milisec); + struct timespec req = {0}; + req.tv_sec = 0; + req.tv_nsec = milisec * 1000L; + nanosleep(&req, (struct timespec*) NULL); + //usleep(milisec); } /** @@ -32,17 +31,17 @@ void __usleep(int milisec) */ void __start_timer() { - gettimeofday(&start, NULL); + gettimeofday(&start, NULL); } long __millis() { static long mtime, seconds, useconds; - - gettimeofday(&end, NULL); - seconds = end.tv_sec - start.tv_sec; + + gettimeofday(&end, NULL); + seconds = end.tv_sec - start.tv_sec; useconds = end.tv_usec - start.tv_usec; - mtime = ((seconds) * 1000 + useconds/1000.0) + 0.5; - return mtime; + mtime = ((seconds) * 1000 + useconds / 1000.0) + 0.5; + return mtime; } diff --git a/utility/MRAA/compatibility.h b/utility/MRAA/compatibility.h index f90083a61..b1f804a5d 100644 --- a/utility/MRAA/compatibility.h +++ b/utility/MRAA/compatibility.h @@ -6,24 +6,27 @@ */ #ifndef COMPATIBLITY_H -#define COMPATIBLITY_H +#define COMPATIBLITY_H -#ifdef __cplusplus +#ifdef __cplusplus extern "C" { #endif - + #include #include #include void __msleep(int milisec); + void __usleep(int milisec); + void __start_timer(); + long __millis(); -#ifdef __cplusplus +#ifdef __cplusplus } #endif -#endif /* COMPATIBLITY_H */ +#endif /* COMPATIBLITY_H */ diff --git a/utility/MRAA/gpio.cpp b/utility/MRAA/gpio.cpp index 93b59d1a5..38b3e355e 100644 --- a/utility/MRAA/gpio.cpp +++ b/utility/MRAA/gpio.cpp @@ -5,78 +5,81 @@ #include "gpio.h" -GPIO::GPIO() { - // Prophet: basic members initialization - gpio_ce_pin = -1; - //gpio_cs_pin = -1; - gpio_0 = NULL; - //gpio_1 = NULL; +GPIO::GPIO() +{ + // Prophet: basic members initialization + gpio_ce_pin = - 1; + //gpio_cs_pin = -1; + gpio_0 = NULL; + //gpio_1 = NULL; } -GPIO::~GPIO() { - // Prophet: this should free memory, and unexport pins when RF24 and/or GPIO gets deleted or goes out of scope - this->close(gpio_ce_pin); - //this->close(gpio_cs_pin); +GPIO::~GPIO() +{ + // Prophet: this should free memory, and unexport pins when RF24 and/or GPIO gets deleted or goes out of scope + this->close(gpio_ce_pin); + //this->close(gpio_cs_pin); } void GPIO::begin(uint8_t ce_pin, uint8_t cs_pin) -{ - gpio_ce_pin = ce_pin; - //gpio_cs_pin = cs_pin; - - // Prophet: owner can be set here, because we use our pins exclusively, and are making mraa:Gpio context persistent - // so pins will be unexported only if close is called, or on destruction - gpio_0 = new mraa::Gpio(ce_pin/*,0*/); - //gpio_1 = new mraa::Gpio(cs_pin/*,0*/); +{ + gpio_ce_pin = ce_pin; + //gpio_cs_pin = cs_pin; + + // Prophet: owner can be set here, because we use our pins exclusively, and are making mraa:Gpio context persistent + // so pins will be unexported only if close is called, or on destruction + gpio_0 = new mraa::Gpio(ce_pin/*,0*/); + //gpio_1 = new mraa::Gpio(cs_pin/*,0*/); } + void GPIO::open(int port, int DDR) -{ - if(port == gpio_ce_pin){ - gpio_0 = new mraa::Gpio(port,0); - gpio_0->useMmap(true); - gpio_0->dir( (mraa::Dir)DDR); - }/*else +{ + if (port == gpio_ce_pin) { + gpio_0 = new mraa::Gpio(port, 0); + gpio_0->useMmap(true); + gpio_0->dir((mraa::Dir) DDR); + }/*else if(port == gpio_cs_pin){ gpio_1 = new mraa::Gpio(port,0); gpio_1->useMmap(true); gpio_1->dir( (mraa::Dir)DDR); - }*/ + }*/ } void GPIO::close(int port) -{ - // Prophet: using same theme of working with port numbers as with GPIO::open, - // checking for mraa::Gpio context existence to be sure, that GPIO::begin was called - if(port == gpio_ce_pin) - { - if (gpio_0 != NULL) { - delete gpio_0; - } - } +{ + // Prophet: using same theme of working with port numbers as with GPIO::open, + // checking for mraa::Gpio context existence to be sure, that GPIO::begin was called + if (port == gpio_ce_pin) { + if (gpio_0 != NULL) { + delete gpio_0; + } + } - /*if(port == gpio_cs_pin) { - if (gpio_1 != NULL) { - delete gpio_1; - } - }*/ + /*if(port == gpio_cs_pin) { + if (gpio_1 != NULL) { + delete gpio_1; + } + }*/ } int GPIO::read(int port) -{ - if(port == gpio_ce_pin){ - return gpio_0->read(); - }/*else +{ + if (port == gpio_ce_pin) { + return gpio_0->read(); + }/*else if(port == gpio_cs_pin){ return gpio_1->read(); }*/ - return -1; + return - 1; } -void GPIO::write(int port, int value){ - - if(port == gpio_ce_pin){ - gpio_0->write( value); - }/*else +void GPIO::write(int port, int value) +{ + + if (port == gpio_ce_pin) { + gpio_0->write(value); + }/*else if(port == gpio_cs_pin){ gpio_1->write( value); }*/ diff --git a/utility/MRAA/gpio.h b/utility/MRAA/gpio.h index 5d9e442ad..312aec906 100644 --- a/utility/MRAA/gpio.h +++ b/utility/MRAA/gpio.h @@ -4,64 +4,67 @@ */ #ifndef RF24_ARCH_GPIO_H -#define RF24_ARCH_GPIO_H - /** - * @file spi.h - * \cond HIDDEN_SYMBOLS - * Class declaration for GPIO helper files - */ +#define RF24_ARCH_GPIO_H +/** +* @file spi.h +* \cond HIDDEN_SYMBOLS +* Class declaration for GPIO helper files +*/ #include #include #include "mraa.hpp" - class GPIO { public: - /* Constants */ - - GPIO(); - virtual ~GPIO(); - - /** - * Sets up GPIO on the CE & CS pins + /* Constants */ + + GPIO(); + + virtual ~GPIO(); + + /** + * Sets up GPIO on the CE & CS pins * @param ce_pin * @param cs_pin - */ - void begin(uint8_t ce_pin, uint8_t cs_pin); - - /** - * + */ + void begin(uint8_t ce_pin, uint8_t cs_pin); + + /** + * * @param port * @param DDR */ - void open(int port, int DDR); - /** - * + void open(int port, int DDR); + + /** + * * @param port */ - void close(int port); - /** - * + void close(int port); + + /** + * * @param port * @param value */ - int read(int port); - /** - * - * @param port - * @param value - */ - void write(int port,int value); + int read(int port); + + /** + * + * @param port + * @param value + */ + void write(int port, int value); private: - int gpio_ce_pin; /** ce_pin value of the RF24 device **/ - //int gpio_cs_pin; /** cs_pin value of the RF24 device **/ - mraa::Gpio* gpio_0; /** gpio object for ce_pin **/ - //mraa::Gpio* gpio_1; /** gpio object for cs_pin **/ + int gpio_ce_pin; /** ce_pin value of the RF24 device **/ + //int gpio_cs_pin; /** cs_pin value of the RF24 device **/ + mraa::Gpio* gpio_0; /** gpio object for ce_pin **/ + //mraa::Gpio* gpio_1; /** gpio object for cs_pin **/ }; /** * \endcond */ -#endif /* RF24_ARCH_GPIO_H */ +#endif /* RF24_ARCH_GPIO_H */ diff --git a/utility/MRAA/includes.h b/utility/MRAA/includes.h index 12e22b95c..feb55f46b 100644 --- a/utility/MRAA/includes.h +++ b/utility/MRAA/includes.h @@ -1,11 +1,10 @@ - #ifndef __RF24_INCLUDES_H__ #define __RF24_INCLUDES_H__ - #ifndef MRAA - #define MRAA - #endif - #include "MRAA/RF24_arch_config.h" - - +#ifndef MRAA + #define MRAA +#endif + +#include "MRAA/RF24_arch_config.h" + #endif diff --git a/utility/MRAA/spi.cpp b/utility/MRAA/spi.cpp index 73ac8a98b..893baecfe 100644 --- a/utility/MRAA/spi.cpp +++ b/utility/MRAA/spi.cpp @@ -3,45 +3,58 @@ #include "spi.h" #include "mraa.h" -SPI::SPI() { - mspi = NULL; +SPI::SPI() +{ + mspi = NULL; } +void SPI::begin(int busNo) +{ + mspi = new mraa::Spi( + busNo); // init mraa spi bus, it will handle chip select internally. For CS pin wiring user must check SPI details in hardware manual -void SPI::begin(int busNo) { - mspi = new mraa::Spi(busNo); // init mraa spi bus, it will handle chip select internally. For CS pin wiring user must check SPI details in hardware manual - - mspi->mode(mraa::SPI_MODE0); - mspi->bitPerWord(8); - mspi->frequency(8000000); // Prophet: this will try to set 8MHz, however MRAA will reset to max platform speed and syslog a message of it + mspi->mode(mraa::SPI_MODE0); + mspi->bitPerWord(8); + mspi->frequency( + 8000000); // Prophet: this will try to set 8MHz, however MRAA will reset to max platform speed and syslog a message of it } -void SPI::end() { - // Prophet: we should check for existence of mspi before deleting it - if (mspi != NULL) - delete mspi; +void SPI::end() +{ + // Prophet: we should check for existence of mspi before deleting it + if (mspi != NULL) { + delete mspi; + } } -void SPI::setBitOrder(uint8_t bit_order) { - if (mspi != NULL) - mspi->lsbmode((mraa_boolean_t)bit_order); // Prophet: bit_order +void SPI::setBitOrder(uint8_t bit_order) +{ + if (mspi != NULL) { + mspi->lsbmode((mraa_boolean_t) bit_order); + } // Prophet: bit_order } -void SPI::setDataMode(uint8_t data_mode) { - if (mspi != NULL) - mspi->mode((mraa::Spi_Mode)data_mode); +void SPI::setDataMode(uint8_t data_mode) +{ + if (mspi != NULL) { + mspi->mode((mraa::Spi_Mode) data_mode); + } } -void SPI::setClockDivider(uint32_t spi_speed) { - if (mspi != NULL) - mspi->frequency(spi_speed); +void SPI::setClockDivider(uint32_t spi_speed) +{ + if (mspi != NULL) { + mspi->frequency(spi_speed); + } } -void SPI::chipSelect(int csn_pin){ +void SPI::chipSelect(int csn_pin) +{ } -SPI::~SPI() { - // Prophet: we should call end here to free used memory and unexport SPI interface - this->end(); +SPI::~SPI() +{ + // Prophet: we should call end here to free used memory and unexport SPI interface + this->end(); } diff --git a/utility/MRAA/spi.h b/utility/MRAA/spi.h index 0c2871d2a..4b541a847 100644 --- a/utility/MRAA/spi.h +++ b/utility/MRAA/spi.h @@ -5,43 +5,50 @@ #ifndef _SPI_H_INCLUDED #define _SPI_H_INCLUDED - /** - * @file spi.h - * \cond HIDDEN_SYMBOLS - * Class declaration for SPI helper files - */ +/** +* @file spi.h +* \cond HIDDEN_SYMBOLS +* Class declaration for SPI helper files +*/ #include #include "mraa.hpp" class SPI { public: - SPI(); - virtual ~SPI(); - - mraa::Spi* mspi; - - inline uint8_t transfer(uint8_t _data); - inline void transfernb(char* tbuf, char* rbuf, uint32_t len); - inline void transfern(char* buf, uint32_t len); - - void begin(int busNo); - void end(); - - void setBitOrder(uint8_t bit_order); - void setDataMode(uint8_t data_mode); - void setClockDivider(uint32_t spi_speed); - void chipSelect(int csn_pin); -}; + SPI(); + + virtual ~SPI(); + + mraa::Spi* mspi; + + inline uint8_t transfer(uint8_t _data); + + inline void transfernb(char* tbuf, char* rbuf, uint32_t len); + + inline void transfern(char* buf, uint32_t len); + void begin(int busNo); + + void end(); + + void setBitOrder(uint8_t bit_order); + + void setDataMode(uint8_t data_mode); + + void setClockDivider(uint32_t spi_speed); + + void chipSelect(int csn_pin); +}; uint8_t SPI::transfer(uint8_t _data) { - return mspi->writeByte(_data); + return mspi->writeByte(_data); } -void SPI::transfernb(char* tbuf, char* rbuf, uint32_t len){ - mspi->transfer((uint8_t*)tbuf, (uint8_t*)rbuf, len); +void SPI::transfernb(char* tbuf, char* rbuf, uint32_t len) +{ + mspi->transfer((uint8_t*) tbuf, (uint8_t*) rbuf, len); } void SPI::transfern(char* buf, uint32_t len) diff --git a/utility/RPi/RF24_arch_config.h b/utility/RPi/RF24_arch_config.h index c656195e1..eff4befa4 100644 --- a/utility/RPi/RF24_arch_config.h +++ b/utility/RPi/RF24_arch_config.h @@ -1,44 +1,44 @@ - #ifndef __ARCH_CONFIG_H__ #define __ARCH_CONFIG_H__ - #define RF24_LINUX - - #include - #include - #include - #include - #include - #include - - #include "bcm2835.h" - #include "spi.h" - #define _SPI spi - - #if defined SPI_HAS_TRANSACTION && !defined SPI_UART && !defined SOFTSPI +#define RF24_LINUX + +#include +#include +#include +#include +#include +#include + +#include "bcm2835.h" +#include "spi.h" + +#define _SPI spi + +#if defined SPI_HAS_TRANSACTION && ! defined SPI_UART && ! defined SOFTSPI #define RF24_SPI_TRANSACTIONS - #endif - // GCC a Arduino Missing - #define _BV(x) (1<<(x)) - #define pgm_read_word(p) (*(p)) - #define pgm_read_byte(p) (*(p)) - #define pgm_read_ptr(p) (*(p)) - - //typedef uint16_t prog_uint16_t; - #define PSTR(x) (x) - #define printf_P printf - #define strlen_P strlen - #define PROGMEM - #define PRIPSTR "%s" - - #ifdef SERIAL_DEBUG - #define IF_SERIAL_DEBUG(x) ({x;}) - #else - #define IF_SERIAL_DEBUG(x) - #endif - - #define digitalWrite(pin, value) bcm2835_gpio_write(pin, value) - #define pinMode(pin,value) bcm2835_gpio_fsel(pin,value); - #define OUTPUT BCM2835_GPIO_FSEL_OUTP - +#endif +// GCC a Arduino Missing +#define _BV(x) (1<<(x)) +#define pgm_read_word(p) (*(p)) +#define pgm_read_byte(p) (*(p)) +#define pgm_read_ptr(p) (*(p)) + +//typedef uint16_t prog_uint16_t; +#define PSTR(x) (x) +#define printf_P printf +#define strlen_P strlen +#define PROGMEM +#define PRIPSTR "%s" + +#ifdef SERIAL_DEBUG + #define IF_SERIAL_DEBUG(x) ({x;}) +#else + #define IF_SERIAL_DEBUG(x) +#endif + +#define digitalWrite(pin, value) bcm2835_gpio_write(pin, value) +#define pinMode(pin, value) bcm2835_gpio_fsel(pin,value); +#define OUTPUT BCM2835_GPIO_FSEL_OUTP + #endif \ No newline at end of file diff --git a/utility/RPi/bcm2835.c b/utility/RPi/bcm2835.c index 3213ec95c..3611b680e 100644 --- a/utility/RPi/bcm2835.c +++ b/utility/RPi/bcm2835.c @@ -21,6 +21,7 @@ #include #define BCK2835_LIBRARY_BUILD + #include "bcm2835.h" /* This define enables a little test program (by default a blinking output on pin RPI_GPIO_PIN_11) @@ -39,27 +40,25 @@ /* Physical address and size of the peripherals block // May be overridden on RPi2 */ -uint32_t *bcm2835_peripherals_base = (uint32_t *)BCM2835_PERI_BASE; +uint32_t* bcm2835_peripherals_base = (uint32_t*) BCM2835_PERI_BASE; uint32_t bcm2835_peripherals_size = BCM2835_PERI_SIZE; /* Virtual memory address of the mapped peripherals block */ -uint32_t *bcm2835_peripherals = (uint32_t *)MAP_FAILED; +uint32_t* bcm2835_peripherals = (uint32_t*) MAP_FAILED; /* And the register bases within the peripherals block */ -volatile uint32_t *bcm2835_gpio = (uint32_t *)MAP_FAILED; -volatile uint32_t *bcm2835_pwm = (uint32_t *)MAP_FAILED; -volatile uint32_t *bcm2835_clk = (uint32_t *)MAP_FAILED; -volatile uint32_t *bcm2835_pads = (uint32_t *)MAP_FAILED; -volatile uint32_t *bcm2835_spi0 = (uint32_t *)MAP_FAILED; -volatile uint32_t *bcm2835_bsc0 = (uint32_t *)MAP_FAILED; -volatile uint32_t *bcm2835_bsc1 = (uint32_t *)MAP_FAILED; -volatile uint32_t *bcm2835_st = (uint32_t *)MAP_FAILED; -volatile uint32_t *bcm2835_aux = (uint32_t *)MAP_FAILED; -volatile uint32_t *bcm2835_spi1 = (uint32_t *)MAP_FAILED; - - +volatile uint32_t* bcm2835_gpio = (uint32_t*) MAP_FAILED; +volatile uint32_t* bcm2835_pwm = (uint32_t*) MAP_FAILED; +volatile uint32_t* bcm2835_clk = (uint32_t*) MAP_FAILED; +volatile uint32_t* bcm2835_pads = (uint32_t*) MAP_FAILED; +volatile uint32_t* bcm2835_spi0 = (uint32_t*) MAP_FAILED; +volatile uint32_t* bcm2835_bsc0 = (uint32_t*) MAP_FAILED; +volatile uint32_t* bcm2835_bsc1 = (uint32_t*) MAP_FAILED; +volatile uint32_t* bcm2835_st = (uint32_t*) MAP_FAILED; +volatile uint32_t* bcm2835_aux = (uint32_t*) MAP_FAILED; +volatile uint32_t* bcm2835_spi1 = (uint32_t*) MAP_FAILED; /* This variable allows us to test on hardware other than RPi. // It prevents access to the kernel memory, and does not do any peripheral access @@ -80,54 +79,38 @@ static uint8_t pud_compat_setting = BCM2835_GPIO_PUD_OFF; static int i2c_byte_wait_us = 0; // Time for millis() -static unsigned long long epoch ; +static unsigned long long epoch; /* SPI bit order. BCM2835 SPI0 only supports MSBFIRST, so we instead * have a software based bit reversal, based on a contribution by Damiano Benedetti */ static uint8_t bcm2835_spi_bit_order = BCM2835_SPI_BIT_ORDER_MSBFIRST; -static uint8_t bcm2835_byte_reverse_table[] = -{ - 0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0, - 0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0, - 0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8, - 0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8, - 0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4, - 0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4, - 0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec, - 0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc, - 0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2, - 0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2, - 0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea, - 0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa, - 0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6, - 0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6, - 0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee, - 0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe, - 0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1, - 0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1, - 0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9, - 0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9, - 0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5, - 0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5, - 0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed, - 0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd, - 0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3, - 0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3, - 0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb, - 0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb, - 0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7, - 0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7, - 0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef, - 0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff -}; +static uint8_t bcm2835_byte_reverse_table[] = {0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0, 0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, + 0xf0, 0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8, 0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, + 0x78, 0xf8, 0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4, 0x14, 0x94, 0x54, 0xd4, 0x34, + 0xb4, 0x74, 0xf4, 0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec, 0x1c, 0x9c, 0x5c, 0xdc, + 0x3c, 0xbc, 0x7c, 0xfc, 0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2, 0x12, 0x92, 0x52, + 0xd2, 0x32, 0xb2, 0x72, 0xf2, 0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea, 0x1a, 0x9a, + 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa, 0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6, 0x16, + 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6, 0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee, + 0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe, 0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, + 0xe1, 0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1, 0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, + 0x69, 0xe9, 0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9, 0x05, 0x85, 0x45, 0xc5, 0x25, + 0xa5, 0x65, 0xe5, 0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5, 0x0d, 0x8d, 0x4d, 0xcd, + 0x2d, 0xad, 0x6d, 0xed, 0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd, 0x03, 0x83, 0x43, + 0xc3, 0x23, 0xa3, 0x63, 0xe3, 0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3, 0x0b, 0x8b, + 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb, 0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb, 0x07, + 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7, 0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7, + 0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef, 0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, + 0xff}; static uint8_t bcm2835_correct_order(uint8_t b) { - if (bcm2835_spi_bit_order == BCM2835_SPI_BIT_ORDER_LSBFIRST) - return bcm2835_byte_reverse_table[b]; - else - return b; + if (bcm2835_spi_bit_order == BCM2835_SPI_BIT_ORDER_LSBFIRST) { + return bcm2835_byte_reverse_table[b]; + } else { + return b; + } } /* @@ -137,39 +120,38 @@ static uint8_t bcm2835_correct_order(uint8_t b) /* Function to return the pointers to the hardware register bases */ uint32_t* bcm2835_regbase(uint8_t regbase) { - switch (regbase) - { - case BCM2835_REGBASE_ST: - return (uint32_t *)bcm2835_st; - case BCM2835_REGBASE_GPIO: - return (uint32_t *)bcm2835_gpio; - case BCM2835_REGBASE_PWM: - return (uint32_t *)bcm2835_pwm; - case BCM2835_REGBASE_CLK: - return (uint32_t *)bcm2835_clk; - case BCM2835_REGBASE_PADS: - return (uint32_t *)bcm2835_pads; - case BCM2835_REGBASE_SPI0: - return (uint32_t *)bcm2835_spi0; - case BCM2835_REGBASE_BSC0: - return (uint32_t *)bcm2835_bsc0; - case BCM2835_REGBASE_BSC1: - return (uint32_t *)bcm2835_st; - case BCM2835_REGBASE_AUX: - return (uint32_t *)bcm2835_aux; - case BCM2835_REGBASE_SPI1: - return (uint32_t *)bcm2835_spi1; + switch (regbase) { + case BCM2835_REGBASE_ST: + return (uint32_t*) bcm2835_st; + case BCM2835_REGBASE_GPIO: + return (uint32_t*) bcm2835_gpio; + case BCM2835_REGBASE_PWM: + return (uint32_t*) bcm2835_pwm; + case BCM2835_REGBASE_CLK: + return (uint32_t*) bcm2835_clk; + case BCM2835_REGBASE_PADS: + return (uint32_t*) bcm2835_pads; + case BCM2835_REGBASE_SPI0: + return (uint32_t*) bcm2835_spi0; + case BCM2835_REGBASE_BSC0: + return (uint32_t*) bcm2835_bsc0; + case BCM2835_REGBASE_BSC1: + return (uint32_t*) bcm2835_st; + case BCM2835_REGBASE_AUX: + return (uint32_t*) bcm2835_aux; + case BCM2835_REGBASE_SPI1: + return (uint32_t*) bcm2835_spi1; } - return (uint32_t *)MAP_FAILED; + return (uint32_t*) MAP_FAILED; } -void bcm2835_set_debug(uint8_t d) +void bcm2835_set_debug(uint8_t d) { debug = d; } -unsigned int bcm2835_version(void) +unsigned int bcm2835_version(void) { return BCM2835_VERSION; } @@ -180,17 +162,14 @@ unsigned int bcm2835_version(void) uint32_t bcm2835_peri_read(volatile uint32_t* paddr) { uint32_t ret; - if (debug) - { - printf("bcm2835_peri_read paddr %p\n", (void *) paddr); - return 0; - } - else - { - __sync_synchronize(); - ret = *paddr; - __sync_synchronize(); - return ret; + if (debug) { + printf("bcm2835_peri_read paddr %p\n", (void*) paddr); + return 0; + } else { + __sync_synchronize(); + ret = *paddr; + __sync_synchronize(); + return ret; } } @@ -202,14 +181,11 @@ uint32_t bcm2835_peri_read(volatile uint32_t* paddr) */ uint32_t bcm2835_peri_read_nb(volatile uint32_t* paddr) { - if (debug) - { - printf("bcm2835_peri_read_nb paddr %p\n", paddr); - return 0; - } - else - { - return *paddr; + if (debug) { + printf("bcm2835_peri_read_nb paddr %p\n", paddr); + return 0; + } else { + return *paddr; } } @@ -218,12 +194,9 @@ uint32_t bcm2835_peri_read_nb(volatile uint32_t* paddr) void bcm2835_peri_write(volatile uint32_t* paddr, uint32_t value) { - if (debug) - { - printf("bcm2835_peri_write paddr %p, value %08X\n", paddr, value); - } - else - { + if (debug) { + printf("bcm2835_peri_write paddr %p, value %08X\n", paddr, value); + } else { __sync_synchronize(); *paddr = value; __sync_synchronize(); @@ -233,14 +206,10 @@ void bcm2835_peri_write(volatile uint32_t* paddr, uint32_t value) /* write to peripheral without the write barrier */ void bcm2835_peri_write_nb(volatile uint32_t* paddr, uint32_t value) { - if (debug) - { - printf("bcm2835_peri_write_nb paddr %p, value %08X\n", - paddr, value); - } - else - { - *paddr = value; + if (debug) { + printf("bcm2835_peri_write_nb paddr %p, value %08X\n", paddr, value); + } else { + *paddr = value; } } @@ -250,7 +219,7 @@ void bcm2835_peri_write_nb(volatile uint32_t* paddr, uint32_t value) void bcm2835_peri_set_bits(volatile uint32_t* paddr, uint32_t value, uint32_t mask) { uint32_t v = bcm2835_peri_read(paddr); - v = (v & ~mask) | (value & mask); + v = (v & ~ mask) | (value & mask); bcm2835_peri_write(paddr, v); } @@ -279,17 +248,17 @@ void bcm2835_peri_set_bits(volatile uint32_t* paddr, uint32_t value, uint32_t ma void bcm2835_gpio_fsel(uint8_t pin, uint8_t mode) { /* Function selects are 10 pins per 32 bit word, 3 bits per pin */ - volatile uint32_t* paddr = bcm2835_gpio + BCM2835_GPFSEL0/4 + (pin/10); - uint8_t shift = (pin % 10) * 3; - uint32_t mask = BCM2835_GPIO_FSEL_MASK << shift; - uint32_t value = mode << shift; + volatile uint32_t* paddr = bcm2835_gpio + BCM2835_GPFSEL0 / 4 + (pin / 10); + uint8_t shift = (pin % 10) * 3; + uint32_t mask = BCM2835_GPIO_FSEL_MASK << shift; + uint32_t value = mode << shift; bcm2835_peri_set_bits(paddr, value, mask); } /* Set output pin */ void bcm2835_gpio_set(uint8_t pin) { - volatile uint32_t* paddr = bcm2835_gpio + BCM2835_GPSET0/4 + pin/32; + volatile uint32_t* paddr = bcm2835_gpio + BCM2835_GPSET0 / 4 + pin / 32; uint8_t shift = pin % 32; bcm2835_peri_write(paddr, 1 << shift); } @@ -297,7 +266,7 @@ void bcm2835_gpio_set(uint8_t pin) /* Clear output pin */ void bcm2835_gpio_clr(uint8_t pin) { - volatile uint32_t* paddr = bcm2835_gpio + BCM2835_GPCLR0/4 + pin/32; + volatile uint32_t* paddr = bcm2835_gpio + BCM2835_GPCLR0 / 4 + pin / 32; uint8_t shift = pin % 32; bcm2835_peri_write(paddr, 1 << shift); } @@ -305,21 +274,21 @@ void bcm2835_gpio_clr(uint8_t pin) /* Set all output pins in the mask */ void bcm2835_gpio_set_multi(uint32_t mask) { - volatile uint32_t* paddr = bcm2835_gpio + BCM2835_GPSET0/4; + volatile uint32_t* paddr = bcm2835_gpio + BCM2835_GPSET0 / 4; bcm2835_peri_write(paddr, mask); } /* Clear all output pins in the mask */ void bcm2835_gpio_clr_multi(uint32_t mask) { - volatile uint32_t* paddr = bcm2835_gpio + BCM2835_GPCLR0/4; + volatile uint32_t* paddr = bcm2835_gpio + BCM2835_GPCLR0 / 4; bcm2835_peri_write(paddr, mask); } /* Read input pin */ uint8_t bcm2835_gpio_lev(uint8_t pin) { - volatile uint32_t* paddr = bcm2835_gpio + BCM2835_GPLEV0/4 + pin/32; + volatile uint32_t* paddr = bcm2835_gpio + BCM2835_GPLEV0 / 4 + pin / 32; uint8_t shift = pin % 32; uint32_t value = bcm2835_peri_read(paddr); return (value & (1 << shift)) ? HIGH : LOW; @@ -330,7 +299,7 @@ uint8_t bcm2835_gpio_lev(uint8_t pin) */ uint8_t bcm2835_gpio_eds(uint8_t pin) { - volatile uint32_t* paddr = bcm2835_gpio + BCM2835_GPEDS0/4 + pin/32; + volatile uint32_t* paddr = bcm2835_gpio + BCM2835_GPEDS0 / 4 + pin / 32; uint8_t shift = pin % 32; uint32_t value = bcm2835_peri_read(paddr); return (value & (1 << shift)) ? HIGH : LOW; @@ -338,7 +307,7 @@ uint8_t bcm2835_gpio_eds(uint8_t pin) uint32_t bcm2835_gpio_eds_multi(uint32_t mask) { - volatile uint32_t* paddr = bcm2835_gpio + BCM2835_GPEDS0/4; + volatile uint32_t* paddr = bcm2835_gpio + BCM2835_GPEDS0 / 4; uint32_t value = bcm2835_peri_read(paddr); return (value & mask); } @@ -346,7 +315,7 @@ uint32_t bcm2835_gpio_eds_multi(uint32_t mask) /* Write a 1 to clear the bit in EDS */ void bcm2835_gpio_set_eds(uint8_t pin) { - volatile uint32_t* paddr = bcm2835_gpio + BCM2835_GPEDS0/4 + pin/32; + volatile uint32_t* paddr = bcm2835_gpio + BCM2835_GPEDS0 / 4 + pin / 32; uint8_t shift = pin % 32; uint32_t value = 1 << shift; bcm2835_peri_write(paddr, value); @@ -354,21 +323,22 @@ void bcm2835_gpio_set_eds(uint8_t pin) void bcm2835_gpio_set_eds_multi(uint32_t mask) { - volatile uint32_t* paddr = bcm2835_gpio + BCM2835_GPEDS0/4; + volatile uint32_t* paddr = bcm2835_gpio + BCM2835_GPEDS0 / 4; bcm2835_peri_write(paddr, mask); } /* Rising edge detect enable */ void bcm2835_gpio_ren(uint8_t pin) { - volatile uint32_t* paddr = bcm2835_gpio + BCM2835_GPREN0/4 + pin/32; + volatile uint32_t* paddr = bcm2835_gpio + BCM2835_GPREN0 / 4 + pin / 32; uint8_t shift = pin % 32; uint32_t value = 1 << shift; bcm2835_peri_set_bits(paddr, value, value); } + void bcm2835_gpio_clr_ren(uint8_t pin) { - volatile uint32_t* paddr = bcm2835_gpio + BCM2835_GPREN0/4 + pin/32; + volatile uint32_t* paddr = bcm2835_gpio + BCM2835_GPREN0 / 4 + pin / 32; uint8_t shift = pin % 32; uint32_t value = 1 << shift; bcm2835_peri_set_bits(paddr, 0, value); @@ -377,14 +347,15 @@ void bcm2835_gpio_clr_ren(uint8_t pin) /* Falling edge detect enable */ void bcm2835_gpio_fen(uint8_t pin) { - volatile uint32_t* paddr = bcm2835_gpio + BCM2835_GPFEN0/4 + pin/32; + volatile uint32_t* paddr = bcm2835_gpio + BCM2835_GPFEN0 / 4 + pin / 32; uint8_t shift = pin % 32; uint32_t value = 1 << shift; bcm2835_peri_set_bits(paddr, value, value); } + void bcm2835_gpio_clr_fen(uint8_t pin) { - volatile uint32_t* paddr = bcm2835_gpio + BCM2835_GPFEN0/4 + pin/32; + volatile uint32_t* paddr = bcm2835_gpio + BCM2835_GPFEN0 / 4 + pin / 32; uint8_t shift = pin % 32; uint32_t value = 1 << shift; bcm2835_peri_set_bits(paddr, 0, value); @@ -393,14 +364,15 @@ void bcm2835_gpio_clr_fen(uint8_t pin) /* High detect enable */ void bcm2835_gpio_hen(uint8_t pin) { - volatile uint32_t* paddr = bcm2835_gpio + BCM2835_GPHEN0/4 + pin/32; + volatile uint32_t* paddr = bcm2835_gpio + BCM2835_GPHEN0 / 4 + pin / 32; uint8_t shift = pin % 32; uint32_t value = 1 << shift; bcm2835_peri_set_bits(paddr, value, value); } + void bcm2835_gpio_clr_hen(uint8_t pin) { - volatile uint32_t* paddr = bcm2835_gpio + BCM2835_GPHEN0/4 + pin/32; + volatile uint32_t* paddr = bcm2835_gpio + BCM2835_GPHEN0 / 4 + pin / 32; uint8_t shift = pin % 32; uint32_t value = 1 << shift; bcm2835_peri_set_bits(paddr, 0, value); @@ -409,14 +381,15 @@ void bcm2835_gpio_clr_hen(uint8_t pin) /* Low detect enable */ void bcm2835_gpio_len(uint8_t pin) { - volatile uint32_t* paddr = bcm2835_gpio + BCM2835_GPLEN0/4 + pin/32; + volatile uint32_t* paddr = bcm2835_gpio + BCM2835_GPLEN0 / 4 + pin / 32; uint8_t shift = pin % 32; uint32_t value = 1 << shift; bcm2835_peri_set_bits(paddr, value, value); } + void bcm2835_gpio_clr_len(uint8_t pin) { - volatile uint32_t* paddr = bcm2835_gpio + BCM2835_GPLEN0/4 + pin/32; + volatile uint32_t* paddr = bcm2835_gpio + BCM2835_GPLEN0 / 4 + pin / 32; uint8_t shift = pin % 32; uint32_t value = 1 << shift; bcm2835_peri_set_bits(paddr, 0, value); @@ -425,14 +398,15 @@ void bcm2835_gpio_clr_len(uint8_t pin) /* Async rising edge detect enable */ void bcm2835_gpio_aren(uint8_t pin) { - volatile uint32_t* paddr = bcm2835_gpio + BCM2835_GPAREN0/4 + pin/32; + volatile uint32_t* paddr = bcm2835_gpio + BCM2835_GPAREN0 / 4 + pin / 32; uint8_t shift = pin % 32; uint32_t value = 1 << shift; bcm2835_peri_set_bits(paddr, value, value); } + void bcm2835_gpio_clr_aren(uint8_t pin) { - volatile uint32_t* paddr = bcm2835_gpio + BCM2835_GPAREN0/4 + pin/32; + volatile uint32_t* paddr = bcm2835_gpio + BCM2835_GPAREN0 / 4 + pin / 32; uint8_t shift = pin % 32; uint32_t value = 1 << shift; bcm2835_peri_set_bits(paddr, 0, value); @@ -441,14 +415,15 @@ void bcm2835_gpio_clr_aren(uint8_t pin) /* Async falling edge detect enable */ void bcm2835_gpio_afen(uint8_t pin) { - volatile uint32_t* paddr = bcm2835_gpio + BCM2835_GPAFEN0/4 + pin/32; + volatile uint32_t* paddr = bcm2835_gpio + BCM2835_GPAFEN0 / 4 + pin / 32; uint8_t shift = pin % 32; uint32_t value = 1 << shift; bcm2835_peri_set_bits(paddr, value, value); } + void bcm2835_gpio_clr_afen(uint8_t pin) { - volatile uint32_t* paddr = bcm2835_gpio + BCM2835_GPAFEN0/4 + pin/32; + volatile uint32_t* paddr = bcm2835_gpio + BCM2835_GPAFEN0 / 4 + pin / 32; uint8_t shift = pin % 32; uint32_t value = 1 << shift; bcm2835_peri_set_bits(paddr, 0, value); @@ -457,14 +432,12 @@ void bcm2835_gpio_clr_afen(uint8_t pin) /* Set pullup/down */ void bcm2835_gpio_pud(uint8_t pud) { - if( pud_type_rpi4 ) - { + if (pud_type_rpi4) { pud_compat_setting = pud; + } else { + volatile uint32_t* paddr = bcm2835_gpio + BCM2835_GPPUD / 4; + bcm2835_peri_write(paddr, pud); } - else { - volatile uint32_t* paddr = bcm2835_gpio + BCM2835_GPPUD/4; - bcm2835_peri_write(paddr, pud); -} } /* Pullup/down clock @@ -472,26 +445,25 @@ void bcm2835_gpio_pud(uint8_t pud) */ void bcm2835_gpio_pudclk(uint8_t pin, uint8_t on) { - if( pud_type_rpi4 ) - { - if( on ) - bcm2835_gpio_set_pud( pin, pud_compat_setting); + if (pud_type_rpi4) { + if (on) { + bcm2835_gpio_set_pud(pin, pud_compat_setting); + } + } else { + volatile uint32_t* paddr = bcm2835_gpio + BCM2835_GPPUDCLK0 / 4 + pin / 32; + uint8_t shift = pin % 32; + bcm2835_peri_write(paddr, (on ? 1 : 0) << shift); } - else - { - volatile uint32_t* paddr = bcm2835_gpio + BCM2835_GPPUDCLK0/4 + pin/32; - uint8_t shift = pin % 32; - bcm2835_peri_write(paddr, (on ? 1 : 0) << shift); -} } /* Read GPIO pad behaviour for groups of GPIOs */ uint32_t bcm2835_gpio_pad(uint8_t group) { - if (bcm2835_pads == MAP_FAILED) - return 0; - - volatile uint32_t* paddr = bcm2835_pads + BCM2835_PADS_GPIO_0_27/4 + group; + if (bcm2835_pads == MAP_FAILED) { + return 0; + } + + volatile uint32_t* paddr = bcm2835_pads + BCM2835_PADS_GPIO_0_27 / 4 + group; return bcm2835_peri_read(paddr); } @@ -501,10 +473,11 @@ uint32_t bcm2835_gpio_pad(uint8_t group) */ void bcm2835_gpio_set_pad(uint8_t group, uint32_t control) { - if (bcm2835_pads == MAP_FAILED) - return; - - volatile uint32_t* paddr = bcm2835_pads + BCM2835_PADS_GPIO_0_27/4 + group; + if (bcm2835_pads == MAP_FAILED) { + return; + } + + volatile uint32_t* paddr = bcm2835_pads + BCM2835_PADS_GPIO_0_27 / 4 + group; bcm2835_peri_write(paddr, control | BCM2835_PAD_PASSWRD); } @@ -514,9 +487,9 @@ void bcm2835_gpio_set_pad(uint8_t group, uint32_t control) void bcm2835_delay(unsigned int millis) { struct timespec sleeper; - - sleeper.tv_sec = (time_t)(millis / 1000); - sleeper.tv_nsec = (long)(millis % 1000) * 1000000; + + sleeper.tv_sec = (time_t)(millis / 1000); + sleeper.tv_nsec = (long) (millis % 1000) * 1000000; nanosleep(&sleeper, NULL); } @@ -524,50 +497,47 @@ void bcm2835_delay(unsigned int millis) void bcm2835_delayMicroseconds(uint64_t micros) { struct timespec t1; - uint64_t start; - - if (debug) - { - /* Cant access sytem timers in debug mode */ - printf("bcm2835_delayMicroseconds %lld\n", (long long int) micros); - return; + uint64_t start; + + if (debug) { + /* Cant access sytem timers in debug mode */ + printf("bcm2835_delayMicroseconds %lld\n", (long long int) micros); + return; } /* Calling nanosleep() takes at least 100-200 us, so use it for // long waits and use a busy wait on the System Timer for the rest. */ - start = bcm2835_st_read(); - + start = bcm2835_st_read(); + /* Not allowed to access timer registers (result is not as precise)*/ - if (start==0) - { - t1.tv_sec = 0; - t1.tv_nsec = 1000 * (long)(micros); - nanosleep(&t1, NULL); - return; + if (start == 0) { + t1.tv_sec = 0; + t1.tv_nsec = 1000 * (long) (micros); + nanosleep(&t1, NULL); + return; + } + + if (micros > 450) { + t1.tv_sec = 0; + t1.tv_nsec = 1000 * (long) (micros - 200); + nanosleep(&t1, NULL); } - if (micros > 450) - { - t1.tv_sec = 0; - t1.tv_nsec = 1000 * (long)(micros - 200); - nanosleep(&t1, NULL); - } - bcm2835_st_delay(start, micros); } // This function is added in order to simulate arduino millis() function unsigned int bcm2835_millis(void) { -struct timeval now; -unsigned long long ms; + struct timeval now; + unsigned long long ms; -gettimeofday(&now, NULL); + gettimeofday(&now, NULL); -ms = (now.tv_sec * 1000000 + now.tv_usec) / 1000 ; + ms = (now.tv_sec * 1000000 + now.tv_usec) / 1000; -return ((uint32_t) (ms - epoch )); + return ((uint32_t)(ms - epoch)); } /* @@ -577,26 +547,28 @@ return ((uint32_t) (ms - epoch )); /* Set the state of an output */ void bcm2835_gpio_write(uint8_t pin, uint8_t on) { - if (on) - bcm2835_gpio_set(pin); - else - bcm2835_gpio_clr(pin); + if (on) { + bcm2835_gpio_set(pin); + } else { + bcm2835_gpio_clr(pin); + } } /* Set the state of a all 32 outputs in the mask to on or off */ void bcm2835_gpio_write_multi(uint32_t mask, uint8_t on) { - if (on) - bcm2835_gpio_set_multi(mask); - else - bcm2835_gpio_clr_multi(mask); + if (on) { + bcm2835_gpio_set_multi(mask); + } else { + bcm2835_gpio_clr_multi(mask); + } } /* Set the state of a all 32 outputs in the mask to the values in value */ void bcm2835_gpio_write_mask(uint32_t value, uint32_t mask) { bcm2835_gpio_set_multi(value & mask); - bcm2835_gpio_clr_multi((~value) & mask); + bcm2835_gpio_clr_multi((~ value) & mask); } /* Set the pullup/down resistor for a pin @@ -622,82 +594,90 @@ void bcm2835_gpio_write_mask(uint32_t value, uint32_t mask) */ void bcm2835_gpio_set_pud(uint8_t pin, uint8_t pud) { - if( pud_type_rpi4 ) - { + if (pud_type_rpi4) { int shiftbits = (pin & 0xf) << 1; uint32_t bits; uint32_t pull; - - switch (pud) - { - case BCM2835_GPIO_PUD_OFF: pull = 0; break; - case BCM2835_GPIO_PUD_UP: pull = 1; break; - case BCM2835_GPIO_PUD_DOWN: pull = 2; break; - default: return; + + switch (pud) { + case BCM2835_GPIO_PUD_OFF: + pull = 0; + break; + case BCM2835_GPIO_PUD_UP: + pull = 1; + break; + case BCM2835_GPIO_PUD_DOWN: + pull = 2; + break; + default: + return; } - - volatile uint32_t* paddr = bcm2835_gpio + BCM2835_GPPUPPDN0/4 + (pin >> 4); - - bits = bcm2835_peri_read_nb( paddr ); - bits &= ~(3 << shiftbits); + + volatile uint32_t* paddr = bcm2835_gpio + BCM2835_GPPUPPDN0 / 4 + (pin >> 4); + + bits = bcm2835_peri_read_nb(paddr); + bits &= ~ (3 << shiftbits); bits |= (pull << shiftbits); - - bcm2835_peri_write_nb( paddr, bits ); - - } else - { - bcm2835_gpio_pud(pud); - delayMicroseconds(10); - bcm2835_gpio_pudclk(pin, 1); - delayMicroseconds(10); - bcm2835_gpio_pud(BCM2835_GPIO_PUD_OFF); - bcm2835_gpio_pudclk(pin, 0); -} -} + bcm2835_peri_write_nb(paddr, bits); + + } else { + bcm2835_gpio_pud(pud); + delayMicroseconds(10); + bcm2835_gpio_pudclk(pin, 1); + delayMicroseconds(10); + bcm2835_gpio_pud(BCM2835_GPIO_PUD_OFF); + bcm2835_gpio_pudclk(pin, 0); + } +} uint8_t bcm2835_gpio_get_pud(uint8_t pin) { uint8_t ret = BCM2835_GPIO_PUD_ERROR; - - if( pud_type_rpi4 ) - { + + if (pud_type_rpi4) { uint32_t bits; - volatile uint32_t* paddr = bcm2835_gpio + BCM2835_GPPUPPDN0/4 + (pin >> 4); - bits = (bcm2835_peri_read_nb( paddr ) >> ((pin & 0xf)<<1)) & 0x3; - - switch (bits) - { - case 0: ret = BCM2835_GPIO_PUD_OFF; break; - case 1: ret = BCM2835_GPIO_PUD_UP; break; - case 2: ret = BCM2835_GPIO_PUD_DOWN; break; - default: ret = BCM2835_GPIO_PUD_ERROR; - } + volatile uint32_t* paddr = bcm2835_gpio + BCM2835_GPPUPPDN0 / 4 + (pin >> 4); + bits = (bcm2835_peri_read_nb(paddr) >> ((pin & 0xf) << 1)) & 0x3; + + switch (bits) { + case 0: + ret = BCM2835_GPIO_PUD_OFF; + break; + case 1: + ret = BCM2835_GPIO_PUD_UP; + break; + case 2: + ret = BCM2835_GPIO_PUD_DOWN; + break; + default: + ret = BCM2835_GPIO_PUD_ERROR; + } } - + return ret; } - int bcm2835_spi_begin(void) { volatile uint32_t* paddr; - if (bcm2835_spi0 == MAP_FAILED) - return 0; /* bcm2835_init() failed, or not root */ - + if (bcm2835_spi0 == MAP_FAILED) { + return 0; + } /* bcm2835_init() failed, or not root */ + /* Set the SPI0 pins to the Alt 0 function to enable SPI0 access on them */ bcm2835_gpio_fsel(RPI_GPIO_P1_26, BCM2835_GPIO_FSEL_ALT0); /* CE1 */ bcm2835_gpio_fsel(RPI_GPIO_P1_24, BCM2835_GPIO_FSEL_ALT0); /* CE0 */ bcm2835_gpio_fsel(RPI_GPIO_P1_21, BCM2835_GPIO_FSEL_ALT0); /* MISO */ bcm2835_gpio_fsel(RPI_GPIO_P1_19, BCM2835_GPIO_FSEL_ALT0); /* MOSI */ bcm2835_gpio_fsel(RPI_GPIO_P1_23, BCM2835_GPIO_FSEL_ALT0); /* CLK */ - + /* Set the SPI CS register to the some sensible defaults */ - paddr = bcm2835_spi0 + BCM2835_SPI0_CS/4; + paddr = bcm2835_spi0 + BCM2835_SPI0_CS / 4; bcm2835_peri_write(paddr, 0); /* All 0s */ - + /* Clear TX and RX fifos */ bcm2835_peri_write_nb(paddr, BCM2835_SPI0_CS_CLEAR); @@ -705,7 +685,7 @@ int bcm2835_spi_begin(void) } void bcm2835_spi_end(void) -{ +{ /* Set all the SPI0 pins back to input */ bcm2835_gpio_fsel(RPI_GPIO_P1_26, BCM2835_GPIO_FSEL_INPT); /* CE1 */ bcm2835_gpio_fsel(RPI_GPIO_P1_24, BCM2835_GPIO_FSEL_INPT); /* CE0 */ @@ -726,20 +706,20 @@ void bcm2835_spi_setBitOrder(uint8_t order) */ void bcm2835_spi_setClockDivider(uint16_t divider) { - volatile uint32_t* paddr = bcm2835_spi0 + BCM2835_SPI0_CLK/4; + volatile uint32_t* paddr = bcm2835_spi0 + BCM2835_SPI0_CLK / 4; bcm2835_peri_write(paddr, divider); } void bcm2835_spi_set_speed_hz(uint32_t speed_hz) { - uint16_t divider = (uint16_t) ((uint32_t) BCM2835_CORE_CLK_HZ / speed_hz); - divider &= 0xFFFE; - bcm2835_spi_setClockDivider(divider); + uint16_t divider = (uint16_t)((uint32_t) BCM2835_CORE_CLK_HZ / speed_hz); + divider &= 0xFFFE; + bcm2835_spi_setClockDivider(divider); } void bcm2835_spi_setDataMode(uint8_t mode) { - volatile uint32_t* paddr = bcm2835_spi0 + BCM2835_SPI0_CS/4; + volatile uint32_t* paddr = bcm2835_spi0 + BCM2835_SPI0_CS / 4; /* Mask in the CPO and CPHA bits of CS */ bcm2835_peri_set_bits(paddr, mode << 2, BCM2835_SPI0_CS_CPOL | BCM2835_SPI0_CS_CPHA); } @@ -747,8 +727,8 @@ void bcm2835_spi_setDataMode(uint8_t mode) /* Writes (and reads) a single byte to SPI */ uint8_t bcm2835_spi_transfer(uint8_t value) { - volatile uint32_t* paddr = bcm2835_spi0 + BCM2835_SPI0_CS/4; - volatile uint32_t* fifo = bcm2835_spi0 + BCM2835_SPI0_FIFO/4; + volatile uint32_t* paddr = bcm2835_spi0 + BCM2835_SPI0_CS / 4; + volatile uint32_t* fifo = bcm2835_spi0 + BCM2835_SPI0_FIFO / 4; uint32_t ret; /* This is Polled transfer as per section 10.6.1 @@ -762,15 +742,13 @@ uint8_t bcm2835_spi_transfer(uint8_t value) bcm2835_peri_set_bits(paddr, BCM2835_SPI0_CS_TA, BCM2835_SPI0_CS_TA); /* Maybe wait for TXD */ - while (!(bcm2835_peri_read(paddr) & BCM2835_SPI0_CS_TXD)) - ; + while (! (bcm2835_peri_read(paddr) & BCM2835_SPI0_CS_TXD)); /* Write to FIFO, no barrier */ bcm2835_peri_write_nb(fifo, bcm2835_correct_order(value)); /* Wait for DONE to be set */ - while (!(bcm2835_peri_read_nb(paddr) & BCM2835_SPI0_CS_DONE)) - ; + while (! (bcm2835_peri_read_nb(paddr) & BCM2835_SPI0_CS_DONE)); /* Read any byte that was sent back by the slave while we sere sending to it */ ret = bcm2835_correct_order(bcm2835_peri_read_nb(fifo)); @@ -784,10 +762,10 @@ uint8_t bcm2835_spi_transfer(uint8_t value) /* Writes (and reads) an number of bytes to SPI */ void bcm2835_spi_transfernb(char* tbuf, char* rbuf, uint32_t len) { - volatile uint32_t* paddr = bcm2835_spi0 + BCM2835_SPI0_CS/4; - volatile uint32_t* fifo = bcm2835_spi0 + BCM2835_SPI0_FIFO/4; - uint32_t TXCnt=0; - uint32_t RXCnt=0; + volatile uint32_t* paddr = bcm2835_spi0 + BCM2835_SPI0_CS / 4; + volatile uint32_t* fifo = bcm2835_spi0 + BCM2835_SPI0_FIFO / 4; + uint32_t TXCnt = 0; + uint32_t RXCnt = 0; /* This is Polled transfer as per section 10.6.1 // BUG ALERT: what happens if we get interupted in this section, and someone else @@ -801,24 +779,20 @@ void bcm2835_spi_transfernb(char* tbuf, char* rbuf, uint32_t len) bcm2835_peri_set_bits(paddr, BCM2835_SPI0_CS_TA, BCM2835_SPI0_CS_TA); /* Use the FIFO's to reduce the interbyte times */ - while((TXCnt < len)||(RXCnt < len)) - { + while ((TXCnt < len) || (RXCnt < len)) { /* TX fifo not full, so add some more bytes */ - while(((bcm2835_peri_read(paddr) & BCM2835_SPI0_CS_TXD))&&(TXCnt < len )) - { - bcm2835_peri_write_nb(fifo, bcm2835_correct_order(tbuf[TXCnt])); - TXCnt++; + while (((bcm2835_peri_read(paddr) & BCM2835_SPI0_CS_TXD)) && (TXCnt < len)) { + bcm2835_peri_write_nb(fifo, bcm2835_correct_order(tbuf[TXCnt])); + TXCnt ++; } /* Rx fifo not empty, so get the next received bytes */ - while(((bcm2835_peri_read(paddr) & BCM2835_SPI0_CS_RXD))&&( RXCnt < len )) - { - rbuf[RXCnt] = bcm2835_correct_order(bcm2835_peri_read_nb(fifo)); - RXCnt++; + while (((bcm2835_peri_read(paddr) & BCM2835_SPI0_CS_RXD)) && (RXCnt < len)) { + rbuf[RXCnt] = bcm2835_correct_order(bcm2835_peri_read_nb(fifo)); + RXCnt ++; } } /* Wait for DONE to be set */ - while (!(bcm2835_peri_read_nb(paddr) & BCM2835_SPI0_CS_DONE)) - ; + while (! (bcm2835_peri_read_nb(paddr) & BCM2835_SPI0_CS_DONE)); /* Set TA = 0, and also set the barrier */ bcm2835_peri_set_bits(paddr, 0, BCM2835_SPI0_CS_TA); @@ -827,8 +801,8 @@ void bcm2835_spi_transfernb(char* tbuf, char* rbuf, uint32_t len) /* Writes an number of bytes to SPI */ void bcm2835_spi_writenb(const char* tbuf, uint32_t len) { - volatile uint32_t* paddr = bcm2835_spi0 + BCM2835_SPI0_CS/4; - volatile uint32_t* fifo = bcm2835_spi0 + BCM2835_SPI0_FIFO/4; + volatile uint32_t* paddr = bcm2835_spi0 + BCM2835_SPI0_CS / 4; + volatile uint32_t* fifo = bcm2835_spi0 + BCM2835_SPI0_FIFO / 4; uint32_t i; /* This is Polled transfer as per section 10.6.1 @@ -843,24 +817,22 @@ void bcm2835_spi_writenb(const char* tbuf, uint32_t len) /* Set TA = 1 */ bcm2835_peri_set_bits(paddr, BCM2835_SPI0_CS_TA, BCM2835_SPI0_CS_TA); - for (i = 0; i < len; i++) - { - /* Maybe wait for TXD */ - while (!(bcm2835_peri_read(paddr) & BCM2835_SPI0_CS_TXD)) - ; - - /* Write to FIFO, no barrier */ - bcm2835_peri_write_nb(fifo, bcm2835_correct_order(tbuf[i])); - - /* Read from FIFO to prevent stalling */ - while (bcm2835_peri_read(paddr) & BCM2835_SPI0_CS_RXD) - (void) bcm2835_peri_read_nb(fifo); + for (i = 0; i < len; i ++) { + /* Maybe wait for TXD */ + while (! (bcm2835_peri_read(paddr) & BCM2835_SPI0_CS_TXD)); + + /* Write to FIFO, no barrier */ + bcm2835_peri_write_nb(fifo, bcm2835_correct_order(tbuf[i])); + + /* Read from FIFO to prevent stalling */ + while (bcm2835_peri_read(paddr) & BCM2835_SPI0_CS_RXD) + (void) bcm2835_peri_read_nb(fifo); } - + /* Wait for DONE to be set */ - while (!(bcm2835_peri_read_nb(paddr) & BCM2835_SPI0_CS_DONE)) { - while (bcm2835_peri_read(paddr) & BCM2835_SPI0_CS_RXD) - (void) bcm2835_peri_read_nb(fifo); + while (! (bcm2835_peri_read_nb(paddr) & BCM2835_SPI0_CS_DONE)) { + while (bcm2835_peri_read(paddr) & BCM2835_SPI0_CS_RXD) + (void) bcm2835_peri_read_nb(fifo); }; /* Set TA = 0, and also set the barrier */ @@ -877,14 +849,14 @@ void bcm2835_spi_transfern(char* buf, uint32_t len) void bcm2835_spi_chipSelect(uint8_t cs) { - volatile uint32_t* paddr = bcm2835_spi0 + BCM2835_SPI0_CS/4; + volatile uint32_t* paddr = bcm2835_spi0 + BCM2835_SPI0_CS / 4; /* Mask in the CS bits of CS */ bcm2835_peri_set_bits(paddr, cs, BCM2835_SPI0_CS_CS); } void bcm2835_spi_setChipSelectPolarity(uint8_t cs, uint8_t active) { - volatile uint32_t* paddr = bcm2835_spi0 + BCM2835_SPI0_CS/4; + volatile uint32_t* paddr = bcm2835_spi0 + BCM2835_SPI0_CS / 4; uint8_t shift = 21 + cs; /* Mask in the appropriate CSPOLn bit */ bcm2835_peri_set_bits(paddr, active << shift, 1 << shift); @@ -892,16 +864,16 @@ void bcm2835_spi_setChipSelectPolarity(uint8_t cs, uint8_t active) void bcm2835_spi_write(uint16_t data) { -#if 0 - char buf[2]; + #if 0 + char buf[2]; - buf[0] = data >> 8; - buf[1] = data & 0xFF; + buf[0] = data >> 8; + buf[1] = data & 0xFF; - bcm2835_spi_transfern(buf, 2); -#else - volatile uint32_t* paddr = bcm2835_spi0 + BCM2835_SPI0_CS/4; - volatile uint32_t* fifo = bcm2835_spi0 + BCM2835_SPI0_FIFO/4; + bcm2835_spi_transfern(buf, 2); + #else + volatile uint32_t* paddr = bcm2835_spi0 + BCM2835_SPI0_CS / 4; + volatile uint32_t* fifo = bcm2835_spi0 + BCM2835_SPI0_FIFO / 4; /* Clear TX and RX fifos */ bcm2835_peri_set_bits(paddr, BCM2835_SPI0_CS_CLEAR, BCM2835_SPI0_CS_CLEAR); @@ -909,275 +881,274 @@ void bcm2835_spi_write(uint16_t data) /* Set TA = 1 */ bcm2835_peri_set_bits(paddr, BCM2835_SPI0_CS_TA, BCM2835_SPI0_CS_TA); - /* Maybe wait for TXD */ - while (!(bcm2835_peri_read(paddr) & BCM2835_SPI0_CS_TXD)) - ; + /* Maybe wait for TXD */ + while (! (bcm2835_peri_read(paddr) & BCM2835_SPI0_CS_TXD)); - /* Write to FIFO */ - bcm2835_peri_write_nb(fifo, (uint32_t) data >> 8); - bcm2835_peri_write_nb(fifo, data & 0xFF); + /* Write to FIFO */ + bcm2835_peri_write_nb(fifo, (uint32_t) data >> 8); + bcm2835_peri_write_nb(fifo, data & 0xFF); /* Wait for DONE to be set */ - while (!(bcm2835_peri_read_nb(paddr) & BCM2835_SPI0_CS_DONE)) - ; + while (! (bcm2835_peri_read_nb(paddr) & BCM2835_SPI0_CS_DONE)); /* Set TA = 0, and also set the barrier */ bcm2835_peri_set_bits(paddr, 0, BCM2835_SPI0_CS_TA); -#endif + #endif } int bcm2835_aux_spi_begin(void) { - volatile uint32_t* enable = bcm2835_aux + BCM2835_AUX_ENABLE/4; - volatile uint32_t* cntl0 = bcm2835_spi1 + BCM2835_AUX_SPI_CNTL0/4; - volatile uint32_t* cntl1 = bcm2835_spi1 + BCM2835_AUX_SPI_CNTL1/4; + volatile uint32_t* enable = bcm2835_aux + BCM2835_AUX_ENABLE / 4; + volatile uint32_t* cntl0 = bcm2835_spi1 + BCM2835_AUX_SPI_CNTL0 / 4; + volatile uint32_t* cntl1 = bcm2835_spi1 + BCM2835_AUX_SPI_CNTL1 / 4; - if (bcm2835_spi1 == MAP_FAILED) - return 0; /* bcm2835_init() failed, or not root */ + if (bcm2835_spi1 == MAP_FAILED) { + return 0; + } /* bcm2835_init() failed, or not root */ /* Set the SPI pins to the Alt 4 function to enable SPI1 access on them */ - bcm2835_gpio_fsel(RPI_V2_GPIO_P1_36, BCM2835_GPIO_FSEL_ALT4); /* SPI1_CE2_N */ - bcm2835_gpio_fsel(RPI_V2_GPIO_P1_35, BCM2835_GPIO_FSEL_ALT4); /* SPI1_MISO */ - bcm2835_gpio_fsel(RPI_V2_GPIO_P1_38, BCM2835_GPIO_FSEL_ALT4); /* SPI1_MOSI */ - bcm2835_gpio_fsel(RPI_V2_GPIO_P1_40, BCM2835_GPIO_FSEL_ALT4); /* SPI1_SCLK */ + bcm2835_gpio_fsel(RPI_V2_GPIO_P1_36, BCM2835_GPIO_FSEL_ALT4); /* SPI1_CE2_N */ + bcm2835_gpio_fsel(RPI_V2_GPIO_P1_35, BCM2835_GPIO_FSEL_ALT4); /* SPI1_MISO */ + bcm2835_gpio_fsel(RPI_V2_GPIO_P1_38, BCM2835_GPIO_FSEL_ALT4); /* SPI1_MOSI */ + bcm2835_gpio_fsel(RPI_V2_GPIO_P1_40, BCM2835_GPIO_FSEL_ALT4); /* SPI1_SCLK */ - bcm2835_aux_spi_setClockDivider(bcm2835_aux_spi_CalcClockDivider(1000000)); // Default 1MHz SPI + bcm2835_aux_spi_setClockDivider(bcm2835_aux_spi_CalcClockDivider(1000000)); // Default 1MHz SPI - bcm2835_peri_write(enable, BCM2835_AUX_ENABLE_SPI0); - bcm2835_peri_write(cntl1, 0); - bcm2835_peri_write(cntl0, BCM2835_AUX_SPI_CNTL0_CLEARFIFO); + bcm2835_peri_write(enable, BCM2835_AUX_ENABLE_SPI0); + bcm2835_peri_write(cntl1, 0); + bcm2835_peri_write(cntl0, BCM2835_AUX_SPI_CNTL0_CLEARFIFO); return 1; /* OK */ } void bcm2835_aux_spi_end(void) { - /* Set all the SPI1 pins back to input */ - bcm2835_gpio_fsel(RPI_V2_GPIO_P1_36, BCM2835_GPIO_FSEL_INPT); /* SPI1_CE2_N */ - bcm2835_gpio_fsel(RPI_V2_GPIO_P1_35, BCM2835_GPIO_FSEL_INPT); /* SPI1_MISO */ - bcm2835_gpio_fsel(RPI_V2_GPIO_P1_38, BCM2835_GPIO_FSEL_INPT); /* SPI1_MOSI */ - bcm2835_gpio_fsel(RPI_V2_GPIO_P1_40, BCM2835_GPIO_FSEL_INPT); /* SPI1_SCLK */ + /* Set all the SPI1 pins back to input */ + bcm2835_gpio_fsel(RPI_V2_GPIO_P1_36, BCM2835_GPIO_FSEL_INPT); /* SPI1_CE2_N */ + bcm2835_gpio_fsel(RPI_V2_GPIO_P1_35, BCM2835_GPIO_FSEL_INPT); /* SPI1_MISO */ + bcm2835_gpio_fsel(RPI_V2_GPIO_P1_38, BCM2835_GPIO_FSEL_INPT); /* SPI1_MOSI */ + bcm2835_gpio_fsel(RPI_V2_GPIO_P1_40, BCM2835_GPIO_FSEL_INPT); /* SPI1_SCLK */ } -#define DIV_ROUND_UP(n,d) (((n) + (d) - 1) / (d)) +#define DIV_ROUND_UP(n, d) (((n) + (d) - 1) / (d)) uint16_t bcm2835_aux_spi_CalcClockDivider(uint32_t speed_hz) { - uint16_t divider; + uint16_t divider; - if (speed_hz < (uint32_t) BCM2835_AUX_SPI_CLOCK_MIN) { - speed_hz = (uint32_t) BCM2835_AUX_SPI_CLOCK_MIN; - } else if (speed_hz > (uint32_t) BCM2835_AUX_SPI_CLOCK_MAX) { - speed_hz = (uint32_t) BCM2835_AUX_SPI_CLOCK_MAX; - } + if (speed_hz < (uint32_t) BCM2835_AUX_SPI_CLOCK_MIN) { + speed_hz = (uint32_t) BCM2835_AUX_SPI_CLOCK_MIN; + } else if (speed_hz > (uint32_t) BCM2835_AUX_SPI_CLOCK_MAX) { + speed_hz = (uint32_t) BCM2835_AUX_SPI_CLOCK_MAX; + } - divider = (uint16_t) DIV_ROUND_UP(BCM2835_CORE_CLK_HZ, 2 * speed_hz) - 1; + divider = (uint16_t)DIV_ROUND_UP(BCM2835_CORE_CLK_HZ, 2 * speed_hz) - 1; - if (divider > (uint16_t) BCM2835_AUX_SPI_CNTL0_SPEED_MAX) { - return (uint16_t) BCM2835_AUX_SPI_CNTL0_SPEED_MAX; - } + if (divider > (uint16_t) BCM2835_AUX_SPI_CNTL0_SPEED_MAX) { + return (uint16_t) BCM2835_AUX_SPI_CNTL0_SPEED_MAX; + } - return divider; + return divider; } static uint32_t spi1_speed; void bcm2835_aux_spi_setClockDivider(uint16_t divider) { - spi1_speed = (uint32_t) divider; + spi1_speed = (uint32_t) divider; } void bcm2835_aux_spi_write(uint16_t data) { - volatile uint32_t* cntl0 = bcm2835_spi1 + BCM2835_AUX_SPI_CNTL0/4; - volatile uint32_t* cntl1 = bcm2835_spi1 + BCM2835_AUX_SPI_CNTL1/4; - volatile uint32_t* stat = bcm2835_spi1 + BCM2835_AUX_SPI_STAT/4; - volatile uint32_t* io = bcm2835_spi1 + BCM2835_AUX_SPI_IO/4; + volatile uint32_t* cntl0 = bcm2835_spi1 + BCM2835_AUX_SPI_CNTL0 / 4; + volatile uint32_t* cntl1 = bcm2835_spi1 + BCM2835_AUX_SPI_CNTL1 / 4; + volatile uint32_t* stat = bcm2835_spi1 + BCM2835_AUX_SPI_STAT / 4; + volatile uint32_t* io = bcm2835_spi1 + BCM2835_AUX_SPI_IO / 4; - uint32_t _cntl0 = (spi1_speed << BCM2835_AUX_SPI_CNTL0_SPEED_SHIFT); - _cntl0 |= BCM2835_AUX_SPI_CNTL0_CS2_N; - _cntl0 |= BCM2835_AUX_SPI_CNTL0_ENABLE; - _cntl0 |= BCM2835_AUX_SPI_CNTL0_MSBF_OUT; - _cntl0 |= 16; // Shift length + uint32_t _cntl0 = (spi1_speed << BCM2835_AUX_SPI_CNTL0_SPEED_SHIFT); + _cntl0 |= BCM2835_AUX_SPI_CNTL0_CS2_N; + _cntl0 |= BCM2835_AUX_SPI_CNTL0_ENABLE; + _cntl0 |= BCM2835_AUX_SPI_CNTL0_MSBF_OUT; + _cntl0 |= 16; // Shift length - bcm2835_peri_write(cntl0, _cntl0); - bcm2835_peri_write(cntl1, BCM2835_AUX_SPI_CNTL1_MSBF_IN); + bcm2835_peri_write(cntl0, _cntl0); + bcm2835_peri_write(cntl1, BCM2835_AUX_SPI_CNTL1_MSBF_IN); - while (bcm2835_peri_read(stat) & BCM2835_AUX_SPI_STAT_TX_FULL) - ; + while (bcm2835_peri_read(stat) & BCM2835_AUX_SPI_STAT_TX_FULL); - bcm2835_peri_write(io, (uint32_t) data << 16); + bcm2835_peri_write(io, (uint32_t) data << 16); } -void bcm2835_aux_spi_writenb(const char *tbuf, uint32_t len) { - volatile uint32_t* cntl0 = bcm2835_spi1 + BCM2835_AUX_SPI_CNTL0/4; - volatile uint32_t* cntl1 = bcm2835_spi1 + BCM2835_AUX_SPI_CNTL1/4; - volatile uint32_t* stat = bcm2835_spi1 + BCM2835_AUX_SPI_STAT/4; - volatile uint32_t* txhold = bcm2835_spi1 + BCM2835_AUX_SPI_TXHOLD/4; - volatile uint32_t* io = bcm2835_spi1 + BCM2835_AUX_SPI_IO/4; - - char *tx = (char *) tbuf; - uint32_t tx_len = len; - uint32_t count; - uint32_t data; - uint32_t i; - uint8_t byte; - - uint32_t _cntl0 = (spi1_speed << BCM2835_AUX_SPI_CNTL0_SPEED_SHIFT); - _cntl0 |= BCM2835_AUX_SPI_CNTL0_CS2_N; - _cntl0 |= BCM2835_AUX_SPI_CNTL0_ENABLE; - _cntl0 |= BCM2835_AUX_SPI_CNTL0_MSBF_OUT; - _cntl0 |= BCM2835_AUX_SPI_CNTL0_VAR_WIDTH; - - bcm2835_peri_write(cntl0, _cntl0); - bcm2835_peri_write(cntl1, BCM2835_AUX_SPI_CNTL1_MSBF_IN); - - while (tx_len > 0) { - - while (bcm2835_peri_read(stat) & BCM2835_AUX_SPI_STAT_TX_FULL) - ; - - count = MIN(tx_len, 3); - data = 0; - - for (i = 0; i < count; i++) { - byte = (tx != NULL) ? (uint8_t) *tx++ : (uint8_t) 0; - data |= byte << (8 * (2 - i)); - } - - data |= (count * 8) << 24; - tx_len -= count; - - if (tx_len != 0) { - bcm2835_peri_write(txhold, data); - } else { - bcm2835_peri_write(io, data); - } - - while (bcm2835_peri_read(stat) & BCM2835_AUX_SPI_STAT_BUSY) - ; - - (void) bcm2835_peri_read(io); - } -} - -void bcm2835_aux_spi_transfernb(const char *tbuf, char *rbuf, uint32_t len) { - volatile uint32_t* cntl0 = bcm2835_spi1 + BCM2835_AUX_SPI_CNTL0/4; - volatile uint32_t* cntl1 = bcm2835_spi1 + BCM2835_AUX_SPI_CNTL1/4; - volatile uint32_t* stat = bcm2835_spi1 + BCM2835_AUX_SPI_STAT/4; - volatile uint32_t* txhold = bcm2835_spi1 + BCM2835_AUX_SPI_TXHOLD/4; - volatile uint32_t* io = bcm2835_spi1 + BCM2835_AUX_SPI_IO/4; - - char *tx = (char *)tbuf; - char *rx = (char *)rbuf; - uint32_t tx_len = len; - uint32_t rx_len = len; - uint32_t count; - uint32_t data; - uint32_t i; - uint8_t byte; - - uint32_t _cntl0 = (spi1_speed << BCM2835_AUX_SPI_CNTL0_SPEED_SHIFT); - _cntl0 |= BCM2835_AUX_SPI_CNTL0_CS2_N; - _cntl0 |= BCM2835_AUX_SPI_CNTL0_ENABLE; - _cntl0 |= BCM2835_AUX_SPI_CNTL0_MSBF_OUT; - _cntl0 |= BCM2835_AUX_SPI_CNTL0_VAR_WIDTH; - - bcm2835_peri_write(cntl0, _cntl0); - bcm2835_peri_write(cntl1, BCM2835_AUX_SPI_CNTL1_MSBF_IN); - - while ((tx_len > 0) || (rx_len > 0)) { - - while (!(bcm2835_peri_read(stat) & BCM2835_AUX_SPI_STAT_TX_FULL) && (tx_len > 0)) { - count = MIN(tx_len, 3); - data = 0; - - for (i = 0; i < count; i++) { - byte = (tx != NULL) ? (uint8_t) *tx++ : (uint8_t) 0; - data |= byte << (8 * (2 - i)); - } - - data |= (count * 8) << 24; - tx_len -= count; - - if (tx_len != 0) { - bcm2835_peri_write(txhold, data); - } else { - bcm2835_peri_write(io, data); - } - - } - - while (!(bcm2835_peri_read(stat) & BCM2835_AUX_SPI_STAT_RX_EMPTY) && (rx_len > 0)) { - count = MIN(rx_len, 3); - data = bcm2835_peri_read(io); - - if (rbuf != NULL) { - switch (count) { - case 3: - *rx++ = (char)((data >> 16) & 0xFF); - /*@fallthrough@*/ - /* no break */ - case 2: - *rx++ = (char)((data >> 8) & 0xFF); - /*@fallthrough@*/ - /* no break */ - case 1: - *rx++ = (char)((data >> 0) & 0xFF); - } - } - - rx_len -= count; - } - - while (!(bcm2835_peri_read(stat) & BCM2835_AUX_SPI_STAT_BUSY) && (rx_len > 0)) { - count = MIN(rx_len, 3); - data = bcm2835_peri_read(io); - - if (rbuf != NULL) { - switch (count) { - case 3: - *rx++ = (char)((data >> 16) & 0xFF); - /*@fallthrough@*/ - /* no break */ - case 2: - *rx++ = (char)((data >> 8) & 0xFF); - /*@fallthrough@*/ - /* no break */ - case 1: - *rx++ = (char)((data >> 0) & 0xFF); - } - } - - rx_len -= count; - } - } -} - -void bcm2835_aux_spi_transfern(char *buf, uint32_t len) { - bcm2835_aux_spi_transfernb(buf, buf, len); +void bcm2835_aux_spi_writenb(const char* tbuf, uint32_t len) +{ + volatile uint32_t* cntl0 = bcm2835_spi1 + BCM2835_AUX_SPI_CNTL0 / 4; + volatile uint32_t* cntl1 = bcm2835_spi1 + BCM2835_AUX_SPI_CNTL1 / 4; + volatile uint32_t* stat = bcm2835_spi1 + BCM2835_AUX_SPI_STAT / 4; + volatile uint32_t* txhold = bcm2835_spi1 + BCM2835_AUX_SPI_TXHOLD / 4; + volatile uint32_t* io = bcm2835_spi1 + BCM2835_AUX_SPI_IO / 4; + + char* tx = (char*) tbuf; + uint32_t tx_len = len; + uint32_t count; + uint32_t data; + uint32_t i; + uint8_t byte; + + uint32_t _cntl0 = (spi1_speed << BCM2835_AUX_SPI_CNTL0_SPEED_SHIFT); + _cntl0 |= BCM2835_AUX_SPI_CNTL0_CS2_N; + _cntl0 |= BCM2835_AUX_SPI_CNTL0_ENABLE; + _cntl0 |= BCM2835_AUX_SPI_CNTL0_MSBF_OUT; + _cntl0 |= BCM2835_AUX_SPI_CNTL0_VAR_WIDTH; + + bcm2835_peri_write(cntl0, _cntl0); + bcm2835_peri_write(cntl1, BCM2835_AUX_SPI_CNTL1_MSBF_IN); + + while (tx_len > 0) { + + while (bcm2835_peri_read(stat) & BCM2835_AUX_SPI_STAT_TX_FULL); + + count = MIN(tx_len, 3); + data = 0; + + for (i = 0; i < count; i ++) { + byte = (tx != NULL) ? (uint8_t) * tx ++ : (uint8_t) 0; + data |= byte << (8 * (2 - i)); + } + + data |= (count * 8) << 24; + tx_len -= count; + + if (tx_len != 0) { + bcm2835_peri_write(txhold, data); + } else { + bcm2835_peri_write(io, data); + } + + while (bcm2835_peri_read(stat) & BCM2835_AUX_SPI_STAT_BUSY); + + (void) bcm2835_peri_read(io); + } +} + +void bcm2835_aux_spi_transfernb(const char* tbuf, char* rbuf, uint32_t len) +{ + volatile uint32_t* cntl0 = bcm2835_spi1 + BCM2835_AUX_SPI_CNTL0 / 4; + volatile uint32_t* cntl1 = bcm2835_spi1 + BCM2835_AUX_SPI_CNTL1 / 4; + volatile uint32_t* stat = bcm2835_spi1 + BCM2835_AUX_SPI_STAT / 4; + volatile uint32_t* txhold = bcm2835_spi1 + BCM2835_AUX_SPI_TXHOLD / 4; + volatile uint32_t* io = bcm2835_spi1 + BCM2835_AUX_SPI_IO / 4; + + char* tx = (char*) tbuf; + char* rx = (char*) rbuf; + uint32_t tx_len = len; + uint32_t rx_len = len; + uint32_t count; + uint32_t data; + uint32_t i; + uint8_t byte; + + uint32_t _cntl0 = (spi1_speed << BCM2835_AUX_SPI_CNTL0_SPEED_SHIFT); + _cntl0 |= BCM2835_AUX_SPI_CNTL0_CS2_N; + _cntl0 |= BCM2835_AUX_SPI_CNTL0_ENABLE; + _cntl0 |= BCM2835_AUX_SPI_CNTL0_MSBF_OUT; + _cntl0 |= BCM2835_AUX_SPI_CNTL0_VAR_WIDTH; + + bcm2835_peri_write(cntl0, _cntl0); + bcm2835_peri_write(cntl1, BCM2835_AUX_SPI_CNTL1_MSBF_IN); + + while ((tx_len > 0) || (rx_len > 0)) { + + while (! (bcm2835_peri_read(stat) & BCM2835_AUX_SPI_STAT_TX_FULL) && (tx_len > 0)) { + count = MIN(tx_len, 3); + data = 0; + + for (i = 0; i < count; i ++) { + byte = (tx != NULL) ? (uint8_t) * tx ++ : (uint8_t) 0; + data |= byte << (8 * (2 - i)); + } + + data |= (count * 8) << 24; + tx_len -= count; + + if (tx_len != 0) { + bcm2835_peri_write(txhold, data); + } else { + bcm2835_peri_write(io, data); + } + + } + + while (! (bcm2835_peri_read(stat) & BCM2835_AUX_SPI_STAT_RX_EMPTY) && (rx_len > 0)) { + count = MIN(rx_len, 3); + data = bcm2835_peri_read(io); + + if (rbuf != NULL) { + switch (count) { + case 3: + *rx ++ = (char) ((data >> 16) & 0xFF); + /*@fallthrough@*/ + /* no break */ + case 2: + *rx ++ = (char) ((data >> 8) & 0xFF); + /*@fallthrough@*/ + /* no break */ + case 1: + *rx ++ = (char) ((data >> 0) & 0xFF); + } + } + + rx_len -= count; + } + + while (! (bcm2835_peri_read(stat) & BCM2835_AUX_SPI_STAT_BUSY) && (rx_len > 0)) { + count = MIN(rx_len, 3); + data = bcm2835_peri_read(io); + + if (rbuf != NULL) { + switch (count) { + case 3: + *rx ++ = (char) ((data >> 16) & 0xFF); + /*@fallthrough@*/ + /* no break */ + case 2: + *rx ++ = (char) ((data >> 8) & 0xFF); + /*@fallthrough@*/ + /* no break */ + case 1: + *rx ++ = (char) ((data >> 0) & 0xFF); + } + } + + rx_len -= count; + } + } +} + +void bcm2835_aux_spi_transfern(char* buf, uint32_t len) +{ + bcm2835_aux_spi_transfernb(buf, buf, len); } int bcm2835_i2c_begin(void) { uint16_t cdiv; - if ( bcm2835_bsc0 == MAP_FAILED - || bcm2835_bsc1 == MAP_FAILED) - return 0; /* bcm2835_init() failed, or not root */ + if (bcm2835_bsc0 == MAP_FAILED || bcm2835_bsc1 == MAP_FAILED) { + return 0; + } /* bcm2835_init() failed, or not root */ -#ifdef I2C_V1 + #ifdef I2C_V1 volatile uint32_t* paddr = bcm2835_bsc0 + BCM2835_BSC_DIV/4; /* Set the I2C/BSC0 pins to the Alt 0 function to enable I2C access on them */ bcm2835_gpio_fsel(RPI_GPIO_P1_03, BCM2835_GPIO_FSEL_ALT0); /* SDA */ bcm2835_gpio_fsel(RPI_GPIO_P1_05, BCM2835_GPIO_FSEL_ALT0); /* SCL */ -#else - volatile uint32_t* paddr = bcm2835_bsc1 + BCM2835_BSC_DIV/4; + #else + volatile uint32_t* paddr = bcm2835_bsc1 + BCM2835_BSC_DIV / 4; /* Set the I2C/BSC1 pins to the Alt 0 function to enable I2C access on them */ bcm2835_gpio_fsel(RPI_V2_GPIO_P1_03, BCM2835_GPIO_FSEL_ALT0); /* SDA */ bcm2835_gpio_fsel(RPI_V2_GPIO_P1_05, BCM2835_GPIO_FSEL_ALT0); /* SCL */ -#endif + #endif /* Read the clock divider register */ cdiv = bcm2835_peri_read(paddr); @@ -1185,32 +1156,32 @@ int bcm2835_i2c_begin(void) // 1000000 = micros seconds in a second // 9 = Clocks per byte : 8 bits + ACK */ - i2c_byte_wait_us = ((float)cdiv / BCM2835_CORE_CLK_HZ) * 1000000 * 9; + i2c_byte_wait_us = ((float) cdiv / BCM2835_CORE_CLK_HZ) * 1000000 * 9; return 1; } void bcm2835_i2c_end(void) { -#ifdef I2C_V1 + #ifdef I2C_V1 /* Set all the I2C/BSC0 pins back to input */ bcm2835_gpio_fsel(RPI_GPIO_P1_03, BCM2835_GPIO_FSEL_INPT); /* SDA */ bcm2835_gpio_fsel(RPI_GPIO_P1_05, BCM2835_GPIO_FSEL_INPT); /* SCL */ -#else + #else /* Set all the I2C/BSC1 pins back to input */ bcm2835_gpio_fsel(RPI_V2_GPIO_P1_03, BCM2835_GPIO_FSEL_INPT); /* SDA */ bcm2835_gpio_fsel(RPI_V2_GPIO_P1_05, BCM2835_GPIO_FSEL_INPT); /* SCL */ -#endif + #endif } void bcm2835_i2c_setSlaveAddress(uint8_t addr) { /* Set I2C Device Address */ -#ifdef I2C_V1 + #ifdef I2C_V1 volatile uint32_t* paddr = bcm2835_bsc0 + BCM2835_BSC_A/4; -#else - volatile uint32_t* paddr = bcm2835_bsc1 + BCM2835_BSC_A/4; -#endif + #else + volatile uint32_t* paddr = bcm2835_bsc1 + BCM2835_BSC_A / 4; + #endif bcm2835_peri_write(paddr, addr); } @@ -1220,95 +1191,89 @@ void bcm2835_i2c_setSlaveAddress(uint8_t addr) */ void bcm2835_i2c_setClockDivider(uint16_t divider) { -#ifdef I2C_V1 + #ifdef I2C_V1 volatile uint32_t* paddr = bcm2835_bsc0 + BCM2835_BSC_DIV/4; -#else - volatile uint32_t* paddr = bcm2835_bsc1 + BCM2835_BSC_DIV/4; -#endif + #else + volatile uint32_t* paddr = bcm2835_bsc1 + BCM2835_BSC_DIV / 4; + #endif bcm2835_peri_write(paddr, divider); /* Calculate time for transmitting one byte // 1000000 = micros seconds in a second // 9 = Clocks per byte : 8 bits + ACK */ - i2c_byte_wait_us = ((float)divider / BCM2835_CORE_CLK_HZ) * 1000000 * 9; + i2c_byte_wait_us = ((float) divider / BCM2835_CORE_CLK_HZ) * 1000000 * 9; } /* set I2C clock divider by means of a baudrate number */ void bcm2835_i2c_set_baudrate(uint32_t baudrate) { - uint32_t divider; - /* use 0xFFFE mask to limit a max value and round down any odd number */ - divider = (BCM2835_CORE_CLK_HZ / baudrate) & 0xFFFE; - bcm2835_i2c_setClockDivider( (uint16_t)divider ); + uint32_t divider; + /* use 0xFFFE mask to limit a max value and round down any odd number */ + divider = (BCM2835_CORE_CLK_HZ / baudrate) & 0xFFFE; + bcm2835_i2c_setClockDivider((uint16_t) divider); } /* Writes an number of bytes to I2C */ -uint8_t bcm2835_i2c_write(const char * buf, uint32_t len) +uint8_t bcm2835_i2c_write(const char* buf, uint32_t len) { -#ifdef I2C_V1 + #ifdef I2C_V1 volatile uint32_t* dlen = bcm2835_bsc0 + BCM2835_BSC_DLEN/4; volatile uint32_t* fifo = bcm2835_bsc0 + BCM2835_BSC_FIFO/4; volatile uint32_t* status = bcm2835_bsc0 + BCM2835_BSC_S/4; volatile uint32_t* control = bcm2835_bsc0 + BCM2835_BSC_C/4; -#else - volatile uint32_t* dlen = bcm2835_bsc1 + BCM2835_BSC_DLEN/4; - volatile uint32_t* fifo = bcm2835_bsc1 + BCM2835_BSC_FIFO/4; - volatile uint32_t* status = bcm2835_bsc1 + BCM2835_BSC_S/4; - volatile uint32_t* control = bcm2835_bsc1 + BCM2835_BSC_C/4; -#endif + #else + volatile uint32_t* dlen = bcm2835_bsc1 + BCM2835_BSC_DLEN / 4; + volatile uint32_t* fifo = bcm2835_bsc1 + BCM2835_BSC_FIFO / 4; + volatile uint32_t* status = bcm2835_bsc1 + BCM2835_BSC_S / 4; + volatile uint32_t* control = bcm2835_bsc1 + BCM2835_BSC_C / 4; + #endif uint32_t remaining = len; uint32_t i = 0; uint8_t reason = BCM2835_I2C_REASON_OK; /* Clear FIFO */ - bcm2835_peri_set_bits(control, BCM2835_BSC_C_CLEAR_1 , BCM2835_BSC_C_CLEAR_1 ); + bcm2835_peri_set_bits(control, BCM2835_BSC_C_CLEAR_1, BCM2835_BSC_C_CLEAR_1); /* Clear Status */ bcm2835_peri_write(status, BCM2835_BSC_S_CLKT | BCM2835_BSC_S_ERR | BCM2835_BSC_S_DONE); /* Set Data Length */ bcm2835_peri_write(dlen, len); /* pre populate FIFO with max buffer */ - while( remaining && ( i < BCM2835_BSC_FIFO_SIZE ) ) - { + while (remaining && (i < BCM2835_BSC_FIFO_SIZE)) { bcm2835_peri_write_nb(fifo, buf[i]); - i++; - remaining--; + i ++; + remaining --; } - + /* Enable device and start transfer */ bcm2835_peri_write(control, BCM2835_BSC_C_I2CEN | BCM2835_BSC_C_ST); - + /* Transfer is over when BCM2835_BSC_S_DONE */ - while(!(bcm2835_peri_read(status) & BCM2835_BSC_S_DONE )) - { - while ( remaining && (bcm2835_peri_read(status) & BCM2835_BSC_S_TXD )) - { - /* Write to FIFO */ - bcm2835_peri_write(fifo, buf[i]); - i++; - remaining--; - } + while (! (bcm2835_peri_read(status) & BCM2835_BSC_S_DONE)) { + while (remaining && (bcm2835_peri_read(status) & BCM2835_BSC_S_TXD)) { + /* Write to FIFO */ + bcm2835_peri_write(fifo, buf[i]); + i ++; + remaining --; + } } /* Received a NACK */ - if (bcm2835_peri_read(status) & BCM2835_BSC_S_ERR) - { - reason = BCM2835_I2C_REASON_ERROR_NACK; + if (bcm2835_peri_read(status) & BCM2835_BSC_S_ERR) { + reason = BCM2835_I2C_REASON_ERROR_NACK; } - /* Received Clock Stretch Timeout */ - else if (bcm2835_peri_read(status) & BCM2835_BSC_S_CLKT) - { - reason = BCM2835_I2C_REASON_ERROR_CLKT; + /* Received Clock Stretch Timeout */ + else if (bcm2835_peri_read(status) & BCM2835_BSC_S_CLKT) { + reason = BCM2835_I2C_REASON_ERROR_CLKT; } - /* Not all data is sent */ - else if (remaining) - { - reason = BCM2835_I2C_REASON_ERROR_DATA; + /* Not all data is sent */ + else if (remaining) { + reason = BCM2835_I2C_REASON_ERROR_DATA; } - bcm2835_peri_set_bits(control, BCM2835_BSC_S_DONE , BCM2835_BSC_S_DONE); + bcm2835_peri_set_bits(control, BCM2835_BSC_S_DONE, BCM2835_BSC_S_DONE); return reason; } @@ -1316,72 +1281,66 @@ uint8_t bcm2835_i2c_write(const char * buf, uint32_t len) /* Read an number of bytes from I2C */ uint8_t bcm2835_i2c_read(char* buf, uint32_t len) { -#ifdef I2C_V1 + #ifdef I2C_V1 volatile uint32_t* dlen = bcm2835_bsc0 + BCM2835_BSC_DLEN/4; volatile uint32_t* fifo = bcm2835_bsc0 + BCM2835_BSC_FIFO/4; volatile uint32_t* status = bcm2835_bsc0 + BCM2835_BSC_S/4; volatile uint32_t* control = bcm2835_bsc0 + BCM2835_BSC_C/4; -#else - volatile uint32_t* dlen = bcm2835_bsc1 + BCM2835_BSC_DLEN/4; - volatile uint32_t* fifo = bcm2835_bsc1 + BCM2835_BSC_FIFO/4; - volatile uint32_t* status = bcm2835_bsc1 + BCM2835_BSC_S/4; - volatile uint32_t* control = bcm2835_bsc1 + BCM2835_BSC_C/4; -#endif + #else + volatile uint32_t* dlen = bcm2835_bsc1 + BCM2835_BSC_DLEN / 4; + volatile uint32_t* fifo = bcm2835_bsc1 + BCM2835_BSC_FIFO / 4; + volatile uint32_t* status = bcm2835_bsc1 + BCM2835_BSC_S / 4; + volatile uint32_t* control = bcm2835_bsc1 + BCM2835_BSC_C / 4; + #endif uint32_t remaining = len; uint32_t i = 0; uint8_t reason = BCM2835_I2C_REASON_OK; /* Clear FIFO */ - bcm2835_peri_set_bits(control, BCM2835_BSC_C_CLEAR_1 , BCM2835_BSC_C_CLEAR_1 ); + bcm2835_peri_set_bits(control, BCM2835_BSC_C_CLEAR_1, BCM2835_BSC_C_CLEAR_1); /* Clear Status */ bcm2835_peri_write_nb(status, BCM2835_BSC_S_CLKT | BCM2835_BSC_S_ERR | BCM2835_BSC_S_DONE); /* Set Data Length */ bcm2835_peri_write_nb(dlen, len); /* Start read */ bcm2835_peri_write_nb(control, BCM2835_BSC_C_I2CEN | BCM2835_BSC_C_ST | BCM2835_BSC_C_READ); - + /* wait for transfer to complete */ - while (!(bcm2835_peri_read_nb(status) & BCM2835_BSC_S_DONE)) - { + while (! (bcm2835_peri_read_nb(status) & BCM2835_BSC_S_DONE)) { /* we must empty the FIFO as it is populated and not use any delay */ - while (remaining && bcm2835_peri_read_nb(status) & BCM2835_BSC_S_RXD) - { - /* Read from FIFO, no barrier */ - buf[i] = bcm2835_peri_read_nb(fifo); - i++; - remaining--; - } + while (remaining && bcm2835_peri_read_nb(status) & BCM2835_BSC_S_RXD) { + /* Read from FIFO, no barrier */ + buf[i] = bcm2835_peri_read_nb(fifo); + i ++; + remaining --; + } } - + /* transfer has finished - grab any remaining stuff in FIFO */ - while (remaining && (bcm2835_peri_read_nb(status) & BCM2835_BSC_S_RXD)) - { + while (remaining && (bcm2835_peri_read_nb(status) & BCM2835_BSC_S_RXD)) { /* Read from FIFO, no barrier */ buf[i] = bcm2835_peri_read_nb(fifo); - i++; - remaining--; + i ++; + remaining --; } - + /* Received a NACK */ - if (bcm2835_peri_read(status) & BCM2835_BSC_S_ERR) - { - reason = BCM2835_I2C_REASON_ERROR_NACK; + if (bcm2835_peri_read(status) & BCM2835_BSC_S_ERR) { + reason = BCM2835_I2C_REASON_ERROR_NACK; } - /* Received Clock Stretch Timeout */ - else if (bcm2835_peri_read(status) & BCM2835_BSC_S_CLKT) - { - reason = BCM2835_I2C_REASON_ERROR_CLKT; + /* Received Clock Stretch Timeout */ + else if (bcm2835_peri_read(status) & BCM2835_BSC_S_CLKT) { + reason = BCM2835_I2C_REASON_ERROR_CLKT; } - /* Not all data is received */ - else if (remaining) - { - reason = BCM2835_I2C_REASON_ERROR_DATA; + /* Not all data is received */ + else if (remaining) { + reason = BCM2835_I2C_REASON_ERROR_DATA; } - bcm2835_peri_set_bits(control, BCM2835_BSC_S_DONE , BCM2835_BSC_S_DONE); + bcm2835_peri_set_bits(control, BCM2835_BSC_S_DONE, BCM2835_BSC_S_DONE); return reason; } @@ -1390,24 +1349,24 @@ uint8_t bcm2835_i2c_read(char* buf, uint32_t len) // the required register. Only works if your device supports this mode */ uint8_t bcm2835_i2c_read_register_rs(char* regaddr, char* buf, uint32_t len) -{ -#ifdef I2C_V1 +{ + #ifdef I2C_V1 volatile uint32_t* dlen = bcm2835_bsc0 + BCM2835_BSC_DLEN/4; volatile uint32_t* fifo = bcm2835_bsc0 + BCM2835_BSC_FIFO/4; volatile uint32_t* status = bcm2835_bsc0 + BCM2835_BSC_S/4; volatile uint32_t* control = bcm2835_bsc0 + BCM2835_BSC_C/4; -#else - volatile uint32_t* dlen = bcm2835_bsc1 + BCM2835_BSC_DLEN/4; - volatile uint32_t* fifo = bcm2835_bsc1 + BCM2835_BSC_FIFO/4; - volatile uint32_t* status = bcm2835_bsc1 + BCM2835_BSC_S/4; - volatile uint32_t* control = bcm2835_bsc1 + BCM2835_BSC_C/4; -#endif - uint32_t remaining = len; + #else + volatile uint32_t* dlen = bcm2835_bsc1 + BCM2835_BSC_DLEN / 4; + volatile uint32_t* fifo = bcm2835_bsc1 + BCM2835_BSC_FIFO / 4; + volatile uint32_t* status = bcm2835_bsc1 + BCM2835_BSC_S / 4; + volatile uint32_t* control = bcm2835_bsc1 + BCM2835_BSC_C / 4; + #endif + uint32_t remaining = len; uint32_t i = 0; uint8_t reason = BCM2835_I2C_REASON_OK; - + /* Clear FIFO */ - bcm2835_peri_set_bits(control, BCM2835_BSC_C_CLEAR_1 , BCM2835_BSC_C_CLEAR_1 ); + bcm2835_peri_set_bits(control, BCM2835_BSC_C_CLEAR_1, BCM2835_BSC_C_CLEAR_1); /* Clear Status */ bcm2835_peri_write(status, BCM2835_BSC_S_CLKT | BCM2835_BSC_S_ERR | BCM2835_BSC_S_DONE); /* Set Data Length */ @@ -1416,63 +1375,57 @@ uint8_t bcm2835_i2c_read_register_rs(char* regaddr, char* buf, uint32_t len) bcm2835_peri_write(control, BCM2835_BSC_C_I2CEN); bcm2835_peri_write(fifo, regaddr[0]); bcm2835_peri_write(control, BCM2835_BSC_C_I2CEN | BCM2835_BSC_C_ST); - + /* poll for transfer has started */ - while ( !( bcm2835_peri_read(status) & BCM2835_BSC_S_TA ) ) - { + while (! (bcm2835_peri_read(status) & BCM2835_BSC_S_TA)) { /* Linux may cause us to miss entire transfer stage */ - if(bcm2835_peri_read(status) & BCM2835_BSC_S_DONE) + if (bcm2835_peri_read(status) & BCM2835_BSC_S_DONE) { break; + } } - + /* Send a repeated start with read bit set in address */ bcm2835_peri_write(dlen, len); - bcm2835_peri_write(control, BCM2835_BSC_C_I2CEN | BCM2835_BSC_C_ST | BCM2835_BSC_C_READ ); - + bcm2835_peri_write(control, BCM2835_BSC_C_I2CEN | BCM2835_BSC_C_ST | BCM2835_BSC_C_READ); + /* Wait for write to complete and first byte back. */ bcm2835_delayMicroseconds(i2c_byte_wait_us * 3); - + /* wait for transfer to complete */ - while (!(bcm2835_peri_read(status) & BCM2835_BSC_S_DONE)) - { + while (! (bcm2835_peri_read(status) & BCM2835_BSC_S_DONE)) { /* we must empty the FIFO as it is populated and not use any delay */ - while (remaining && bcm2835_peri_read(status) & BCM2835_BSC_S_RXD) - { - /* Read from FIFO */ - buf[i] = bcm2835_peri_read(fifo); - i++; - remaining--; - } + while (remaining && bcm2835_peri_read(status) & BCM2835_BSC_S_RXD) { + /* Read from FIFO */ + buf[i] = bcm2835_peri_read(fifo); + i ++; + remaining --; + } } - + /* transfer has finished - grab any remaining stuff in FIFO */ - while (remaining && (bcm2835_peri_read(status) & BCM2835_BSC_S_RXD)) - { + while (remaining && (bcm2835_peri_read(status) & BCM2835_BSC_S_RXD)) { /* Read from FIFO */ buf[i] = bcm2835_peri_read(fifo); - i++; - remaining--; + i ++; + remaining --; } - + /* Received a NACK */ - if (bcm2835_peri_read(status) & BCM2835_BSC_S_ERR) - { - reason = BCM2835_I2C_REASON_ERROR_NACK; + if (bcm2835_peri_read(status) & BCM2835_BSC_S_ERR) { + reason = BCM2835_I2C_REASON_ERROR_NACK; } - /* Received Clock Stretch Timeout */ - else if (bcm2835_peri_read(status) & BCM2835_BSC_S_CLKT) - { - reason = BCM2835_I2C_REASON_ERROR_CLKT; + /* Received Clock Stretch Timeout */ + else if (bcm2835_peri_read(status) & BCM2835_BSC_S_CLKT) { + reason = BCM2835_I2C_REASON_ERROR_CLKT; } - /* Not all data is sent */ - else if (remaining) - { - reason = BCM2835_I2C_REASON_ERROR_DATA; + /* Not all data is sent */ + else if (remaining) { + reason = BCM2835_I2C_REASON_ERROR_DATA; } - bcm2835_peri_set_bits(control, BCM2835_BSC_S_DONE , BCM2835_BSC_S_DONE); + bcm2835_peri_set_bits(control, BCM2835_BSC_S_DONE, BCM2835_BSC_S_DONE); return reason; } @@ -1481,102 +1434,95 @@ uint8_t bcm2835_i2c_read_register_rs(char* regaddr, char* buf, uint32_t len) // (with no prior stop) and reading a response. Some devices require this behavior. */ uint8_t bcm2835_i2c_write_read_rs(char* cmds, uint32_t cmds_len, char* buf, uint32_t buf_len) -{ -#ifdef I2C_V1 +{ + #ifdef I2C_V1 volatile uint32_t* dlen = bcm2835_bsc0 + BCM2835_BSC_DLEN/4; volatile uint32_t* fifo = bcm2835_bsc0 + BCM2835_BSC_FIFO/4; volatile uint32_t* status = bcm2835_bsc0 + BCM2835_BSC_S/4; volatile uint32_t* control = bcm2835_bsc0 + BCM2835_BSC_C/4; -#else - volatile uint32_t* dlen = bcm2835_bsc1 + BCM2835_BSC_DLEN/4; - volatile uint32_t* fifo = bcm2835_bsc1 + BCM2835_BSC_FIFO/4; - volatile uint32_t* status = bcm2835_bsc1 + BCM2835_BSC_S/4; - volatile uint32_t* control = bcm2835_bsc1 + BCM2835_BSC_C/4; -#endif + #else + volatile uint32_t* dlen = bcm2835_bsc1 + BCM2835_BSC_DLEN / 4; + volatile uint32_t* fifo = bcm2835_bsc1 + BCM2835_BSC_FIFO / 4; + volatile uint32_t* status = bcm2835_bsc1 + BCM2835_BSC_S / 4; + volatile uint32_t* control = bcm2835_bsc1 + BCM2835_BSC_C / 4; + #endif uint32_t remaining = cmds_len; uint32_t i = 0; uint8_t reason = BCM2835_I2C_REASON_OK; - + /* Clear FIFO */ - bcm2835_peri_set_bits(control, BCM2835_BSC_C_CLEAR_1 , BCM2835_BSC_C_CLEAR_1 ); + bcm2835_peri_set_bits(control, BCM2835_BSC_C_CLEAR_1, BCM2835_BSC_C_CLEAR_1); /* Clear Status */ bcm2835_peri_write(status, BCM2835_BSC_S_CLKT | BCM2835_BSC_S_ERR | BCM2835_BSC_S_DONE); /* Set Data Length */ bcm2835_peri_write(dlen, cmds_len); - + /* pre populate FIFO with max buffer */ - while( remaining && ( i < BCM2835_BSC_FIFO_SIZE ) ) - { + while (remaining && (i < BCM2835_BSC_FIFO_SIZE)) { bcm2835_peri_write_nb(fifo, cmds[i]); - i++; - remaining--; + i ++; + remaining --; } /* Enable device and start transfer */ bcm2835_peri_write(control, BCM2835_BSC_C_I2CEN | BCM2835_BSC_C_ST); - + /* poll for transfer has started (way to do repeated start, from BCM2835 datasheet) */ - while ( !( bcm2835_peri_read(status) & BCM2835_BSC_S_TA ) ) - { + while (! (bcm2835_peri_read(status) & BCM2835_BSC_S_TA)) { /* Linux may cause us to miss entire transfer stage */ - if(bcm2835_peri_read_nb(status) & BCM2835_BSC_S_DONE) + if (bcm2835_peri_read_nb(status) & BCM2835_BSC_S_DONE) { break; + } } - + remaining = buf_len; i = 0; /* Send a repeated start with read bit set in address */ bcm2835_peri_write(dlen, buf_len); - bcm2835_peri_write(control, BCM2835_BSC_C_I2CEN | BCM2835_BSC_C_ST | BCM2835_BSC_C_READ ); - + bcm2835_peri_write(control, BCM2835_BSC_C_I2CEN | BCM2835_BSC_C_ST | BCM2835_BSC_C_READ); + /* Wait for write to complete and first byte back. */ bcm2835_delayMicroseconds(i2c_byte_wait_us * (cmds_len + 1)); - + /* wait for transfer to complete */ - while (!(bcm2835_peri_read_nb(status) & BCM2835_BSC_S_DONE)) - { + while (! (bcm2835_peri_read_nb(status) & BCM2835_BSC_S_DONE)) { /* we must empty the FIFO as it is populated and not use any delay */ - while (remaining && bcm2835_peri_read(status) & BCM2835_BSC_S_RXD) - { - /* Read from FIFO, no barrier */ - buf[i] = bcm2835_peri_read_nb(fifo); - i++; - remaining--; - } + while (remaining && bcm2835_peri_read(status) & BCM2835_BSC_S_RXD) { + /* Read from FIFO, no barrier */ + buf[i] = bcm2835_peri_read_nb(fifo); + i ++; + remaining --; + } } - + /* transfer has finished - grab any remaining stuff in FIFO */ - while (remaining && (bcm2835_peri_read(status) & BCM2835_BSC_S_RXD)) - { + while (remaining && (bcm2835_peri_read(status) & BCM2835_BSC_S_RXD)) { /* Read from FIFO */ buf[i] = bcm2835_peri_read(fifo); - i++; - remaining--; + i ++; + remaining --; } - + /* Received a NACK */ - if (bcm2835_peri_read(status) & BCM2835_BSC_S_ERR) - { - reason = BCM2835_I2C_REASON_ERROR_NACK; + if (bcm2835_peri_read(status) & BCM2835_BSC_S_ERR) { + reason = BCM2835_I2C_REASON_ERROR_NACK; } - /* Received Clock Stretch Timeout */ - else if (bcm2835_peri_read(status) & BCM2835_BSC_S_CLKT) - { - reason = BCM2835_I2C_REASON_ERROR_CLKT; + /* Received Clock Stretch Timeout */ + else if (bcm2835_peri_read(status) & BCM2835_BSC_S_CLKT) { + reason = BCM2835_I2C_REASON_ERROR_CLKT; } - /* Not all data is sent */ - else if (remaining) - { - reason = BCM2835_I2C_REASON_ERROR_DATA; + /* Not all data is sent */ + else if (remaining) { + reason = BCM2835_I2C_REASON_ERROR_DATA; } - bcm2835_peri_set_bits(control, BCM2835_BSC_S_DONE , BCM2835_BSC_S_DONE); + bcm2835_peri_set_bits(control, BCM2835_BSC_S_DONE, BCM2835_BSC_S_DONE); return reason; } @@ -1588,28 +1534,26 @@ uint64_t bcm2835_st_read(void) uint32_t hi, lo; uint64_t st; - if (bcm2835_st==MAP_FAILED) - return 0; + if (bcm2835_st == MAP_FAILED) { + return 0; + } - paddr = bcm2835_st + BCM2835_ST_CHI/4; + paddr = bcm2835_st + BCM2835_ST_CHI / 4; hi = bcm2835_peri_read(paddr); - paddr = bcm2835_st + BCM2835_ST_CLO/4; + paddr = bcm2835_st + BCM2835_ST_CLO / 4; lo = bcm2835_peri_read(paddr); - - paddr = bcm2835_st + BCM2835_ST_CHI/4; + + paddr = bcm2835_st + BCM2835_ST_CHI / 4; st = bcm2835_peri_read(paddr); - + /* Test for overflow */ - if (st == hi) - { + if (st == hi) { st <<= 32; st += lo; - } - else - { + } else { st <<= 32; - paddr = bcm2835_st + BCM2835_ST_CLO/4; + paddr = bcm2835_st + BCM2835_ST_CLO / 4; st += bcm2835_peri_read(paddr); } return st; @@ -1620,18 +1564,17 @@ void bcm2835_st_delay(uint64_t offset_micros, uint64_t micros) { uint64_t compare = offset_micros + micros; - while(bcm2835_st_read() < compare) - ; + while (bcm2835_st_read() < compare); } /* PWM */ void bcm2835_pwm_set_clock(uint32_t divisor) { - if ( bcm2835_clk == MAP_FAILED - || bcm2835_pwm == MAP_FAILED) - return; /* bcm2835_init() failed or not root */ - + if (bcm2835_clk == MAP_FAILED || bcm2835_pwm == MAP_FAILED) { + return; + } /* bcm2835_init() failed or not root */ + /* From Gerts code */ divisor &= 0xfff; /* Stop PWM clock */ @@ -1639,7 +1582,7 @@ void bcm2835_pwm_set_clock(uint32_t divisor) bcm2835_delay(110); /* Prevents clock going slow */ /* Wait for the clock to be not busy */ while ((bcm2835_peri_read(bcm2835_clk + BCM2835_PWMCLK_CNTL) & 0x80) != 0) - bcm2835_delay(1); + bcm2835_delay(1); /* set the clock divider and enable PWM clock */ bcm2835_peri_write(bcm2835_clk + BCM2835_PWMCLK_DIV, BCM2835_PWM_PASSWRD | (divisor << 12)); bcm2835_peri_write(bcm2835_clk + BCM2835_PWMCLK_CNTL, BCM2835_PWM_PASSWRD | 0x11); /* Source=osc and enable */ @@ -1647,69 +1590,66 @@ void bcm2835_pwm_set_clock(uint32_t divisor) void bcm2835_pwm_set_mode(uint8_t channel, uint8_t markspace, uint8_t enabled) { - if ( bcm2835_clk == MAP_FAILED - || bcm2835_pwm == MAP_FAILED) - return; /* bcm2835_init() failed or not root */ - - uint32_t control = bcm2835_peri_read(bcm2835_pwm + BCM2835_PWM_CONTROL); - - if (channel == 0) - { - if (markspace) - control |= BCM2835_PWM0_MS_MODE; - else - control &= ~BCM2835_PWM0_MS_MODE; - if (enabled) - control |= BCM2835_PWM0_ENABLE; - else - control &= ~BCM2835_PWM0_ENABLE; - } - else if (channel == 1) - { - if (markspace) - control |= BCM2835_PWM1_MS_MODE; - else - control &= ~BCM2835_PWM1_MS_MODE; - if (enabled) - control |= BCM2835_PWM1_ENABLE; - else - control &= ~BCM2835_PWM1_ENABLE; + if (bcm2835_clk == MAP_FAILED || bcm2835_pwm == MAP_FAILED) { + return; + } /* bcm2835_init() failed or not root */ + + uint32_t control = bcm2835_peri_read(bcm2835_pwm + BCM2835_PWM_CONTROL); + + if (channel == 0) { + if (markspace) + control |= BCM2835_PWM0_MS_MODE; + else + control &= ~ BCM2835_PWM0_MS_MODE; + if (enabled) + control |= BCM2835_PWM0_ENABLE; + else + control &= ~ BCM2835_PWM0_ENABLE; + } else if (channel == 1) { + if (markspace) + control |= BCM2835_PWM1_MS_MODE; + else + control &= ~ BCM2835_PWM1_MS_MODE; + if (enabled) + control |= BCM2835_PWM1_ENABLE; + else + control &= ~ BCM2835_PWM1_ENABLE; } - /* If you use the barrier here, wierd things happen, and the commands dont work */ - bcm2835_peri_write_nb(bcm2835_pwm + BCM2835_PWM_CONTROL, control); - /* bcm2835_peri_write_nb(bcm2835_pwm + BCM2835_PWM_CONTROL, BCM2835_PWM0_ENABLE | BCM2835_PWM1_ENABLE | BCM2835_PWM0_MS_MODE | BCM2835_PWM1_MS_MODE); */ + /* If you use the barrier here, wierd things happen, and the commands dont work */ + bcm2835_peri_write_nb(bcm2835_pwm + BCM2835_PWM_CONTROL, control); + /* bcm2835_peri_write_nb(bcm2835_pwm + BCM2835_PWM_CONTROL, BCM2835_PWM0_ENABLE | BCM2835_PWM1_ENABLE | BCM2835_PWM0_MS_MODE | BCM2835_PWM1_MS_MODE); */ } void bcm2835_pwm_set_range(uint8_t channel, uint32_t range) { - if ( bcm2835_clk == MAP_FAILED - || bcm2835_pwm == MAP_FAILED) - return; /* bcm2835_init() failed or not root */ + if (bcm2835_clk == MAP_FAILED || bcm2835_pwm == MAP_FAILED) { + return; + } /* bcm2835_init() failed or not root */ - if (channel == 0) - bcm2835_peri_write_nb(bcm2835_pwm + BCM2835_PWM0_RANGE, range); - else if (channel == 1) - bcm2835_peri_write_nb(bcm2835_pwm + BCM2835_PWM1_RANGE, range); + if (channel == 0) + bcm2835_peri_write_nb(bcm2835_pwm + BCM2835_PWM0_RANGE, range); + else if (channel == 1) + bcm2835_peri_write_nb(bcm2835_pwm + BCM2835_PWM1_RANGE, range); } void bcm2835_pwm_set_data(uint8_t channel, uint32_t data) { - if ( bcm2835_clk == MAP_FAILED - || bcm2835_pwm == MAP_FAILED) - return; /* bcm2835_init() failed or not root */ + if (bcm2835_clk == MAP_FAILED || bcm2835_pwm == MAP_FAILED) { + return; + } /* bcm2835_init() failed or not root */ - if (channel == 0) - bcm2835_peri_write_nb(bcm2835_pwm + BCM2835_PWM0_DATA, data); - else if (channel == 1) - bcm2835_peri_write_nb(bcm2835_pwm + BCM2835_PWM1_DATA, data); + if (channel == 0) + bcm2835_peri_write_nb(bcm2835_pwm + BCM2835_PWM0_DATA, data); + else if (channel == 1) + bcm2835_peri_write_nb(bcm2835_pwm + BCM2835_PWM1_DATA, data); } /* Allocate page-aligned memory. */ -void *malloc_aligned(size_t size) +void* malloc_aligned(size_t size) { - void *mem; + void* mem; errno = posix_memalign(&mem, BCM2835_PAGE_SIZE, size); return (errno ? NULL : mem); } @@ -1718,17 +1658,20 @@ void *malloc_aligned(size_t size) // Return mapped address on success, MAP_FAILED otherwise. // On error print message. */ -static void *mapmem(const char *msg, size_t size, int fd, off_t off) +static void* mapmem(const char* msg, size_t size, int fd, off_t off) { - void *map = mmap(NULL, size, (PROT_READ | PROT_WRITE), MAP_SHARED, fd, off); - if (map == MAP_FAILED) - fprintf(stderr, "bcm2835_init: %s mmap failed: %s\n", msg, strerror(errno)); + void* map = mmap(NULL, size, (PROT_READ | PROT_WRITE), MAP_SHARED, fd, off); + if (map == MAP_FAILED) { + fprintf(stderr, "bcm2835_init: %s mmap failed: %s\n", msg, strerror(errno)); + } return map; } -static void unmapmem(void **pmem, size_t size) +static void unmapmem(void** pmem, size_t size) { - if (*pmem == MAP_FAILED) return; + if (*pmem == MAP_FAILED) { + return; + } munmap(*pmem, size); *pmem = MAP_FAILED; } @@ -1736,79 +1679,59 @@ static void unmapmem(void **pmem, size_t size) /* Initialise this library. */ int bcm2835_init(void) { - int memfd; - int ok; - FILE *fp; - - if (debug) - { - bcm2835_peripherals = (uint32_t*)BCM2835_PERI_BASE; - - bcm2835_pads = bcm2835_peripherals + BCM2835_GPIO_PADS/4; - bcm2835_clk = bcm2835_peripherals + BCM2835_CLOCK_BASE/4; - bcm2835_gpio = bcm2835_peripherals + BCM2835_GPIO_BASE/4; - bcm2835_pwm = bcm2835_peripherals + BCM2835_GPIO_PWM/4; - bcm2835_spi0 = bcm2835_peripherals + BCM2835_SPI0_BASE/4; - bcm2835_bsc0 = bcm2835_peripherals + BCM2835_BSC0_BASE/4; - bcm2835_bsc1 = bcm2835_peripherals + BCM2835_BSC1_BASE/4; - bcm2835_st = bcm2835_peripherals + BCM2835_ST_BASE/4; - bcm2835_aux = bcm2835_peripherals + BCM2835_AUX_BASE/4; - bcm2835_spi1 = bcm2835_peripherals + BCM2835_SPI1_BASE/4; - - return 1; /* Success */ + int memfd; + int ok; + FILE* fp; + + if (debug) { + bcm2835_peripherals = (uint32_t*) BCM2835_PERI_BASE; + + bcm2835_pads = bcm2835_peripherals + BCM2835_GPIO_PADS / 4; + bcm2835_clk = bcm2835_peripherals + BCM2835_CLOCK_BASE / 4; + bcm2835_gpio = bcm2835_peripherals + BCM2835_GPIO_BASE / 4; + bcm2835_pwm = bcm2835_peripherals + BCM2835_GPIO_PWM / 4; + bcm2835_spi0 = bcm2835_peripherals + BCM2835_SPI0_BASE / 4; + bcm2835_bsc0 = bcm2835_peripherals + BCM2835_BSC0_BASE / 4; + bcm2835_bsc1 = bcm2835_peripherals + BCM2835_BSC1_BASE / 4; + bcm2835_st = bcm2835_peripherals + BCM2835_ST_BASE / 4; + bcm2835_aux = bcm2835_peripherals + BCM2835_AUX_BASE / 4; + bcm2835_spi1 = bcm2835_peripherals + BCM2835_SPI1_BASE / 4; + + return 1; /* Success */ } /* Figure out the base and size of the peripheral address block // using the device-tree. Required for RPi2/3/4, optional for RPi 1 */ - if ((fp = fopen(BMC2835_RPI2_DT_FILENAME , "rb"))) - { + if ((fp = fopen(BMC2835_RPI2_DT_FILENAME, "rb"))) { unsigned char buf[16]; uint32_t base_address; uint32_t peri_size; - if (fread(buf, 1, sizeof(buf), fp) >= 8) - { - base_address = (buf[4] << 24) | - (buf[5] << 16) | - (buf[6] << 8) | - (buf[7] << 0); - - peri_size = (buf[8] << 24) | - (buf[9] << 16) | - (buf[10] << 8) | - (buf[11] << 0); - - if (!base_address) - { + if (fread(buf, 1, sizeof(buf), fp) >= 8) { + base_address = (buf[4] << 24) | (buf[5] << 16) | (buf[6] << 8) | (buf[7] << 0); + + peri_size = (buf[8] << 24) | (buf[9] << 16) | (buf[10] << 8) | (buf[11] << 0); + + if (! base_address) { /* looks like RPI 4 */ - base_address = (buf[8] << 24) | - (buf[9] << 16) | - (buf[10] << 8) | - (buf[11] << 0); - - peri_size = (buf[12] << 24) | - (buf[13] << 16) | - (buf[14] << 8) | - (buf[15] << 0); + base_address = (buf[8] << 24) | (buf[9] << 16) | (buf[10] << 8) | (buf[11] << 0); + + peri_size = (buf[12] << 24) | (buf[13] << 16) | (buf[14] << 8) | (buf[15] << 0); } /* check for valid known range formats */ - if ((buf[0] == 0x7e) && - (buf[1] == 0x00) && - (buf[2] == 0x00) && - (buf[3] == 0x00) && - ((base_address == BCM2835_PERI_BASE) || (base_address == BCM2835_RPI2_PERI_BASE) || (base_address == BCM2835_RPI4_PERI_BASE))) - { - bcm2835_peripherals_base = (uint32_t *)base_address; + if ((buf[0] == 0x7e) && (buf[1] == 0x00) && (buf[2] == 0x00) && (buf[3] == 0x00) + && ((base_address == BCM2835_PERI_BASE) || (base_address == BCM2835_RPI2_PERI_BASE) + || (base_address == BCM2835_RPI4_PERI_BASE))) { + bcm2835_peripherals_base = (uint32_t*) base_address; bcm2835_peripherals_size = peri_size; - if( base_address == BCM2835_RPI4_PERI_BASE ) - { + if (base_address == BCM2835_RPI4_PERI_BASE) { pud_type_rpi4 = 1; } } - + } - - fclose(fp); + + fclose(fp); } /* else we are prob on RPi 1 with BCM2835, and use the hardwired defaults */ @@ -1817,64 +1740,63 @@ int bcm2835_init(void) * the fact that we can only access GPIO * else try for the /dev/mem interface and get access to everything */ - memfd = -1; + memfd = - 1; ok = 0; - if (geteuid() == 0) - { - /* Open the master /dev/mem device */ - if ((memfd = open("/dev/mem", O_RDWR | O_SYNC) ) < 0) - { - fprintf(stderr, "bcm2835_init: Unable to open /dev/mem: %s\n", - strerror(errno)) ; - goto exit; - } - - /* Base of the peripherals block is mapped to VM */ - bcm2835_peripherals = mapmem("gpio", bcm2835_peripherals_size, memfd, (off_t)bcm2835_peripherals_base); - if (bcm2835_peripherals == MAP_FAILED) goto exit; - - /* Now compute the base addresses of various peripherals, - // which are at fixed offsets within the mapped peripherals block - // Caution: bcm2835_peripherals is uint32_t*, so divide offsets by 4 - */ - bcm2835_gpio = bcm2835_peripherals + BCM2835_GPIO_BASE/4; - bcm2835_pwm = bcm2835_peripherals + BCM2835_GPIO_PWM/4; - bcm2835_clk = bcm2835_peripherals + BCM2835_CLOCK_BASE/4; - bcm2835_pads = bcm2835_peripherals + BCM2835_GPIO_PADS/4; - bcm2835_spi0 = bcm2835_peripherals + BCM2835_SPI0_BASE/4; - bcm2835_bsc0 = bcm2835_peripherals + BCM2835_BSC0_BASE/4; /* I2C */ - bcm2835_bsc1 = bcm2835_peripherals + BCM2835_BSC1_BASE/4; /* I2C */ - bcm2835_st = bcm2835_peripherals + BCM2835_ST_BASE/4; - bcm2835_aux = bcm2835_peripherals + BCM2835_AUX_BASE/4; - bcm2835_spi1 = bcm2835_peripherals + BCM2835_SPI1_BASE/4; - - ok = 1; - } - else - { - /* Not root, try /dev/gpiomem */ - /* Open the master /dev/mem device */ - if ((memfd = open("/dev/gpiomem", O_RDWR | O_SYNC) ) < 0) - { - fprintf(stderr, "bcm2835_init: Unable to open /dev/gpiomem: %s\n", - strerror(errno)) ; - goto exit; - } - - /* Base of the peripherals block is mapped to VM */ - bcm2835_peripherals_base = 0; - bcm2835_peripherals = mapmem("gpio", bcm2835_peripherals_size, memfd, (off_t)bcm2835_peripherals_base); - if (bcm2835_peripherals == MAP_FAILED) goto exit; - bcm2835_gpio = bcm2835_peripherals; - ok = 1; + if (geteuid() == 0) { + /* Open the master /dev/mem device */ + if ((memfd = open("/dev/mem", O_RDWR | O_SYNC)) < 0) { + fprintf(stderr, "bcm2835_init: Unable to open /dev/mem: %s\n", strerror(errno)); + goto exit; + } + + /* Base of the peripherals block is mapped to VM */ + bcm2835_peripherals = mapmem("gpio", bcm2835_peripherals_size, memfd, (off_t) bcm2835_peripherals_base); + if (bcm2835_peripherals == MAP_FAILED) { + goto exit; + } + + /* Now compute the base addresses of various peripherals, + // which are at fixed offsets within the mapped peripherals block + // Caution: bcm2835_peripherals is uint32_t*, so divide offsets by 4 + */ + bcm2835_gpio = bcm2835_peripherals + BCM2835_GPIO_BASE / 4; + bcm2835_pwm = bcm2835_peripherals + BCM2835_GPIO_PWM / 4; + bcm2835_clk = bcm2835_peripherals + BCM2835_CLOCK_BASE / 4; + bcm2835_pads = bcm2835_peripherals + BCM2835_GPIO_PADS / 4; + bcm2835_spi0 = bcm2835_peripherals + BCM2835_SPI0_BASE / 4; + bcm2835_bsc0 = bcm2835_peripherals + BCM2835_BSC0_BASE / 4; /* I2C */ + bcm2835_bsc1 = bcm2835_peripherals + BCM2835_BSC1_BASE / 4; /* I2C */ + bcm2835_st = bcm2835_peripherals + BCM2835_ST_BASE / 4; + bcm2835_aux = bcm2835_peripherals + BCM2835_AUX_BASE / 4; + bcm2835_spi1 = bcm2835_peripherals + BCM2835_SPI1_BASE / 4; + + ok = 1; + } else { + /* Not root, try /dev/gpiomem */ + /* Open the master /dev/mem device */ + if ((memfd = open("/dev/gpiomem", O_RDWR | O_SYNC)) < 0) { + fprintf(stderr, "bcm2835_init: Unable to open /dev/gpiomem: %s\n", strerror(errno)); + goto exit; + } + + /* Base of the peripherals block is mapped to VM */ + bcm2835_peripherals_base = 0; + bcm2835_peripherals = mapmem("gpio", bcm2835_peripherals_size, memfd, (off_t) bcm2835_peripherals_base); + if (bcm2835_peripherals == MAP_FAILED) { + goto exit; + } + bcm2835_gpio = bcm2835_peripherals; + ok = 1; } -exit: - if (memfd >= 0) + exit: + if (memfd >= 0) { close(memfd); + } - if (!ok) - bcm2835_close(); + if (! ok) { + bcm2835_close(); + } return ok; } @@ -1882,25 +1804,27 @@ int bcm2835_init(void) /* Close this library and deallocate everything */ int bcm2835_close(void) { - if (debug) return 1; /* Success */ + if (debug) { + return 1; + } /* Success */ unmapmem((void**) &bcm2835_peripherals, bcm2835_peripherals_size); bcm2835_peripherals = MAP_FAILED; bcm2835_gpio = MAP_FAILED; - bcm2835_pwm = MAP_FAILED; - bcm2835_clk = MAP_FAILED; + bcm2835_pwm = MAP_FAILED; + bcm2835_clk = MAP_FAILED; bcm2835_pads = MAP_FAILED; bcm2835_spi0 = MAP_FAILED; bcm2835_bsc0 = MAP_FAILED; bcm2835_bsc1 = MAP_FAILED; - bcm2835_st = MAP_FAILED; - bcm2835_aux = MAP_FAILED; + bcm2835_st = MAP_FAILED; + bcm2835_aux = MAP_FAILED; bcm2835_spi1 = MAP_FAILED; return 1; /* Success */ -} +} #ifdef BCM2835_TEST -/* this is a simple test program that prints out what it will do rather than +/* this is a simple test program that prints out what it will do rather than // actually doing it */ int main(int argc, char **argv) @@ -1909,7 +1833,7 @@ int main(int argc, char **argv) bcm2835_set_debug(1); if (!bcm2835_init()) - return 1; + return 1; /* Configure some GPIO pins fo some testing // Set RPI pin P1-11 to be an output @@ -1924,57 +1848,57 @@ int main(int argc, char **argv) /* and input hysteresis disabled on GPIOs 0 to 27 */ bcm2835_gpio_set_pad(BCM2835_PAD_GROUP_GPIO_0_27, BCM2835_PAD_SLEW_RATE_UNLIMITED|BCM2835_PAD_DRIVE_8mA); -#if 1 + #if 1 /* Blink */ while (1) { - /* Turn it on */ - bcm2835_gpio_write(RPI_GPIO_P1_11, HIGH); - - /* wait a bit */ - bcm2835_delay(500); - - /* turn it off */ - bcm2835_gpio_write(RPI_GPIO_P1_11, LOW); - - /* wait a bit */ - bcm2835_delay(500); + /* Turn it on */ + bcm2835_gpio_write(RPI_GPIO_P1_11, HIGH); + + /* wait a bit */ + bcm2835_delay(500); + + /* turn it off */ + bcm2835_gpio_write(RPI_GPIO_P1_11, LOW); + + /* wait a bit */ + bcm2835_delay(500); } -#endif + #endif -#if 0 + #if 0 /* Read input */ while (1) { - /* Read some data */ - uint8_t value = bcm2835_gpio_lev(RPI_GPIO_P1_15); - printf("read from pin 15: %d\n", value); - - /* wait a bit */ - bcm2835_delay(500); + /* Read some data */ + uint8_t value = bcm2835_gpio_lev(RPI_GPIO_P1_15); + printf("read from pin 15: %d\n", value); + + /* wait a bit */ + bcm2835_delay(500); } -#endif + #endif -#if 0 + #if 0 /* Look for a low event detection // eds will be set whenever pin 15 goes low */ while (1) { - if (bcm2835_gpio_eds(RPI_GPIO_P1_15)) - { - /* Now clear the eds flag by setting it to 1 */ - bcm2835_gpio_set_eds(RPI_GPIO_P1_15); - printf("low event detect for pin 15\n"); - } - - /* wait a bit */ - bcm2835_delay(500); + if (bcm2835_gpio_eds(RPI_GPIO_P1_15)) + { + /* Now clear the eds flag by setting it to 1 */ + bcm2835_gpio_set_eds(RPI_GPIO_P1_15); + printf("low event detect for pin 15\n"); } -#endif + + /* wait a bit */ + bcm2835_delay(500); + } + #endif if (!bcm2835_close()) - return 1; + return 1; return 0; } diff --git a/utility/RPi/bcm2835.h b/utility/RPi/bcm2835.h index 67050e216..859b3b1a3 100644 --- a/utility/RPi/bcm2835.h +++ b/utility/RPi/bcm2835.h @@ -560,7 +560,7 @@ This test is so any ARMv7 or higher processors with suitable GCC will use DMB. */ #if __ARM_ARCH >= 7 -#define BCM2835_HAVE_DMB + #define BCM2835_HAVE_DMB #endif /*! \defgroup constants Constants for passing to and from library functions @@ -575,11 +575,11 @@ /*! Return the minimum of 2 numbers */ #ifndef MIN -#define MIN(a, b) (a < b ? a : b) + #define MIN(a, b) (a < b ? a : b) #endif /*! Speed of the core clock core_clk */ -#define BCM2835_CORE_CLK_HZ 250000000 /*!< 250 MHz */ +#define BCM2835_CORE_CLK_HZ 250000000 /*!< 250 MHz */ /*! On all recent OSs, the base of the peripherals is read from a /proc file */ #define BMC2835_RPI2_DT_FILENAME "/proc/device-tree/soc/ranges" @@ -604,7 +604,7 @@ /*! Offsets for the bases of various peripherals within the peripherals block / Base Address of the System Timer registers */ -#define BCM2835_ST_BASE 0x3000 +#define BCM2835_ST_BASE 0x3000 /*! Base Address of the Pads registers */ #define BCM2835_GPIO_PADS 0x100000 /*! Base Address of the Clock/timer registers */ @@ -614,95 +614,92 @@ /*! Base Address of the SPI0 registers */ #define BCM2835_SPI0_BASE 0x204000 /*! Base Address of the BSC0 registers */ -#define BCM2835_BSC0_BASE 0x205000 +#define BCM2835_BSC0_BASE 0x205000 /*! Base Address of the PWM registers */ #define BCM2835_GPIO_PWM 0x20C000 /*! Base Address of the AUX registers */ -#define BCM2835_AUX_BASE 0x215000 +#define BCM2835_AUX_BASE 0x215000 /*! Base Address of the AUX_SPI1 registers */ -#define BCM2835_SPI1_BASE 0x215080 +#define BCM2835_SPI1_BASE 0x215080 /*! Base Address of the AUX_SPI2 registers */ -#define BCM2835_SPI2_BASE 0x2150C0 +#define BCM2835_SPI2_BASE 0x2150C0 /*! Base Address of the BSC1 registers */ -#define BCM2835_BSC1_BASE 0x804000 - +#define BCM2835_BSC1_BASE 0x804000 /*! Physical address and size of the peripherals block May be overridden on RPi2 */ -extern uint32_t *bcm2835_peripherals_base; +extern uint32_t* bcm2835_peripherals_base; /*! Size of the peripherals block to be mapped */ extern uint32_t bcm2835_peripherals_size; /*! Virtual memory address of the mapped peripherals block */ -extern uint32_t *bcm2835_peripherals; +extern uint32_t* bcm2835_peripherals; /*! Base of the ST (System Timer) registers. Available after bcm2835_init has been called (as root) */ -extern volatile uint32_t *bcm2835_st; +extern volatile uint32_t* bcm2835_st; /*! Base of the GPIO registers. Available after bcm2835_init has been called */ -extern volatile uint32_t *bcm2835_gpio; +extern volatile uint32_t* bcm2835_gpio; /*! Base of the PWM registers. Available after bcm2835_init has been called (as root) */ -extern volatile uint32_t *bcm2835_pwm; +extern volatile uint32_t* bcm2835_pwm; /*! Base of the CLK registers. Available after bcm2835_init has been called (as root) */ -extern volatile uint32_t *bcm2835_clk; +extern volatile uint32_t* bcm2835_clk; /*! Base of the PADS registers. Available after bcm2835_init has been called (as root) */ -extern volatile uint32_t *bcm2835_pads; +extern volatile uint32_t* bcm2835_pads; /*! Base of the SPI0 registers. Available after bcm2835_init has been called (as root) */ -extern volatile uint32_t *bcm2835_spi0; +extern volatile uint32_t* bcm2835_spi0; /*! Base of the BSC0 registers. Available after bcm2835_init has been called (as root) */ -extern volatile uint32_t *bcm2835_bsc0; +extern volatile uint32_t* bcm2835_bsc0; /*! Base of the BSC1 registers. Available after bcm2835_init has been called (as root) */ -extern volatile uint32_t *bcm2835_bsc1; +extern volatile uint32_t* bcm2835_bsc1; /*! Base of the AUX registers. Available after bcm2835_init has been called (as root) */ -extern volatile uint32_t *bcm2835_aux; +extern volatile uint32_t* bcm2835_aux; /*! Base of the SPI1 registers. Available after bcm2835_init has been called (as root) */ -extern volatile uint32_t *bcm2835_spi1; - +extern volatile uint32_t* bcm2835_spi1; /*! \brief bcm2835RegisterBase Register bases for bcm2835_regbase() */ -typedef enum -{ - BCM2835_REGBASE_ST = 1, /*!< Base of the ST (System Timer) registers. */ +typedef enum { + BCM2835_REGBASE_ST = 1, /*!< Base of the ST (System Timer) registers. */ BCM2835_REGBASE_GPIO = 2, /*!< Base of the GPIO registers. */ - BCM2835_REGBASE_PWM = 3, /*!< Base of the PWM registers. */ - BCM2835_REGBASE_CLK = 4, /*!< Base of the CLK registers. */ + BCM2835_REGBASE_PWM = 3, /*!< Base of the PWM registers. */ + BCM2835_REGBASE_CLK = 4, /*!< Base of the CLK registers. */ BCM2835_REGBASE_PADS = 5, /*!< Base of the PADS registers. */ BCM2835_REGBASE_SPI0 = 6, /*!< Base of the SPI0 registers. */ BCM2835_REGBASE_BSC0 = 7, /*!< Base of the BSC0 registers. */ BCM2835_REGBASE_BSC1 = 8, /*!< Base of the BSC1 registers. */ - BCM2835_REGBASE_AUX = 9, /*!< Base of the AUX registers. */ - BCM2835_REGBASE_SPI1 = 10 /*!< Base of the SPI1 registers. */ + BCM2835_REGBASE_AUX = 9, /*!< Base of the AUX registers. */ + BCM2835_REGBASE_SPI1 = 10 /*!< Base of the SPI1 registers. */ } bcm2835RegisterBase; /*! Size of memory page on RPi */ @@ -757,31 +754,29 @@ typedef enum /*! \brief bcm2835PortFunction Port function select modes for bcm2835_gpio_fsel() */ -typedef enum -{ - BCM2835_GPIO_FSEL_INPT = 0x00, /*!< Input 0b000 */ - BCM2835_GPIO_FSEL_OUTP = 0x01, /*!< Output 0b001 */ - BCM2835_GPIO_FSEL_ALT0 = 0x04, /*!< Alternate function 0 0b100 */ - BCM2835_GPIO_FSEL_ALT1 = 0x05, /*!< Alternate function 1 0b101 */ - BCM2835_GPIO_FSEL_ALT2 = 0x06, /*!< Alternate function 2 0b110, */ - BCM2835_GPIO_FSEL_ALT3 = 0x07, /*!< Alternate function 3 0b111 */ - BCM2835_GPIO_FSEL_ALT4 = 0x03, /*!< Alternate function 4 0b011 */ - BCM2835_GPIO_FSEL_ALT5 = 0x02, /*!< Alternate function 5 0b010 */ - BCM2835_GPIO_FSEL_MASK = 0x07 /*!< Function select bits mask 0b111 */ +typedef enum { + BCM2835_GPIO_FSEL_INPT = 0x00, /*!< Input 0b000 */ + BCM2835_GPIO_FSEL_OUTP = 0x01, /*!< Output 0b001 */ + BCM2835_GPIO_FSEL_ALT0 = 0x04, /*!< Alternate function 0 0b100 */ + BCM2835_GPIO_FSEL_ALT1 = 0x05, /*!< Alternate function 1 0b101 */ + BCM2835_GPIO_FSEL_ALT2 = 0x06, /*!< Alternate function 2 0b110, */ + BCM2835_GPIO_FSEL_ALT3 = 0x07, /*!< Alternate function 3 0b111 */ + BCM2835_GPIO_FSEL_ALT4 = 0x03, /*!< Alternate function 4 0b011 */ + BCM2835_GPIO_FSEL_ALT5 = 0x02, /*!< Alternate function 5 0b010 */ + BCM2835_GPIO_FSEL_MASK = 0x07 /*!< Function select bits mask 0b111 */ } bcm2835FunctionSelect; /*! \brief bcm2835PUDControl Pullup/Pulldown defines for bcm2835_gpio_pud() */ -typedef enum -{ - BCM2835_GPIO_PUD_OFF = 0x00, /*!< Off ? disable pull-up/down 0b00 */ - BCM2835_GPIO_PUD_DOWN = 0x01, /*!< Enable Pull Down control 0b01 */ - BCM2835_GPIO_PUD_UP = 0x02 /*!< Enable Pull Up control 0b10 */ +typedef enum { + BCM2835_GPIO_PUD_OFF = 0x00, /*!< Off ? disable pull-up/down 0b00 */ + BCM2835_GPIO_PUD_DOWN = 0x01, /*!< Enable Pull Down control 0b01 */ + BCM2835_GPIO_PUD_UP = 0x02 /*!< Enable Pull Up control 0b10 */ } bcm2835PUDControl; /* need a value for pud functions that can't work unless RPI 4 */ -#define BCM2835_GPIO_PUD_ERROR 0x08 +#define BCM2835_GPIO_PUD_ERROR 0x08 /*! Pad control register offsets from BCM2835_GPIO_PADS */ #define BCM2835_PADS_GPIO_0_27 0x002c /*!< Pad control register for pads 0 to 27 */ @@ -804,11 +799,10 @@ typedef enum /*! \brief bcm2835PadGroup Pad group specification for bcm2835_gpio_pad() */ -typedef enum -{ - BCM2835_PAD_GROUP_GPIO_0_27 = 0, /*!< Pad group for GPIO pads 0 to 27 */ - BCM2835_PAD_GROUP_GPIO_28_45 = 1, /*!< Pad group for GPIO pads 28 to 45 */ - BCM2835_PAD_GROUP_GPIO_46_53 = 2 /*!< Pad group for GPIO pads 46 to 53 */ +typedef enum { + BCM2835_PAD_GROUP_GPIO_0_27 = 0, /*!< Pad group for GPIO pads 0 to 27 */ + BCM2835_PAD_GROUP_GPIO_28_45 = 1, /*!< Pad group for GPIO pads 28 to 45 */ + BCM2835_PAD_GROUP_GPIO_46_53 = 2 /*!< Pad group for GPIO pads 46 to 53 */ } bcm2835PadGroup; /*! \brief GPIO Pin Numbers @@ -825,144 +819,142 @@ typedef enum If you are using the RPi Compute Module, just use the GPIO number: there is no need to use one of these symbolic names */ -typedef enum -{ - RPI_GPIO_P1_03 = 0, /*!< Version 1, Pin P1-03 */ - RPI_GPIO_P1_05 = 1, /*!< Version 1, Pin P1-05 */ - RPI_GPIO_P1_07 = 4, /*!< Version 1, Pin P1-07 */ - RPI_GPIO_P1_08 = 14, /*!< Version 1, Pin P1-08, defaults to alt function 0 UART0_TXD */ - RPI_GPIO_P1_10 = 15, /*!< Version 1, Pin P1-10, defaults to alt function 0 UART0_RXD */ - RPI_GPIO_P1_11 = 17, /*!< Version 1, Pin P1-11 */ - RPI_GPIO_P1_12 = 18, /*!< Version 1, Pin P1-12, can be PWM channel 0 in ALT FUN 5 */ - RPI_GPIO_P1_13 = 21, /*!< Version 1, Pin P1-13 */ - RPI_GPIO_P1_15 = 22, /*!< Version 1, Pin P1-15 */ - RPI_GPIO_P1_16 = 23, /*!< Version 1, Pin P1-16 */ - RPI_GPIO_P1_18 = 24, /*!< Version 1, Pin P1-18 */ - RPI_GPIO_P1_19 = 10, /*!< Version 1, Pin P1-19, MOSI when SPI0 in use */ - RPI_GPIO_P1_21 = 9, /*!< Version 1, Pin P1-21, MISO when SPI0 in use */ - RPI_GPIO_P1_22 = 25, /*!< Version 1, Pin P1-22 */ - RPI_GPIO_P1_23 = 11, /*!< Version 1, Pin P1-23, CLK when SPI0 in use */ - RPI_GPIO_P1_24 = 8, /*!< Version 1, Pin P1-24, CE0 when SPI0 in use */ - RPI_GPIO_P1_26 = 7, /*!< Version 1, Pin P1-26, CE1 when SPI0 in use */ +typedef enum { + RPI_GPIO_P1_03 = 0, /*!< Version 1, Pin P1-03 */ + RPI_GPIO_P1_05 = 1, /*!< Version 1, Pin P1-05 */ + RPI_GPIO_P1_07 = 4, /*!< Version 1, Pin P1-07 */ + RPI_GPIO_P1_08 = 14, /*!< Version 1, Pin P1-08, defaults to alt function 0 UART0_TXD */ + RPI_GPIO_P1_10 = 15, /*!< Version 1, Pin P1-10, defaults to alt function 0 UART0_RXD */ + RPI_GPIO_P1_11 = 17, /*!< Version 1, Pin P1-11 */ + RPI_GPIO_P1_12 = 18, /*!< Version 1, Pin P1-12, can be PWM channel 0 in ALT FUN 5 */ + RPI_GPIO_P1_13 = 21, /*!< Version 1, Pin P1-13 */ + RPI_GPIO_P1_15 = 22, /*!< Version 1, Pin P1-15 */ + RPI_GPIO_P1_16 = 23, /*!< Version 1, Pin P1-16 */ + RPI_GPIO_P1_18 = 24, /*!< Version 1, Pin P1-18 */ + RPI_GPIO_P1_19 = 10, /*!< Version 1, Pin P1-19, MOSI when SPI0 in use */ + RPI_GPIO_P1_21 = 9, /*!< Version 1, Pin P1-21, MISO when SPI0 in use */ + RPI_GPIO_P1_22 = 25, /*!< Version 1, Pin P1-22 */ + RPI_GPIO_P1_23 = 11, /*!< Version 1, Pin P1-23, CLK when SPI0 in use */ + RPI_GPIO_P1_24 = 8, /*!< Version 1, Pin P1-24, CE0 when SPI0 in use */ + RPI_GPIO_P1_26 = 7, /*!< Version 1, Pin P1-26, CE1 when SPI0 in use */ /* RPi Version 2 */ - RPI_V2_GPIO_P1_03 = 2, /*!< Version 2, Pin P1-03 */ - RPI_V2_GPIO_P1_05 = 3, /*!< Version 2, Pin P1-05 */ - RPI_V2_GPIO_P1_07 = 4, /*!< Version 2, Pin P1-07 */ - RPI_V2_GPIO_P1_08 = 14, /*!< Version 2, Pin P1-08, defaults to alt function 0 UART0_TXD */ - RPI_V2_GPIO_P1_10 = 15, /*!< Version 2, Pin P1-10, defaults to alt function 0 UART0_RXD */ - RPI_V2_GPIO_P1_11 = 17, /*!< Version 2, Pin P1-11 */ - RPI_V2_GPIO_P1_12 = 18, /*!< Version 2, Pin P1-12, can be PWM channel 0 in ALT FUN 5 */ - RPI_V2_GPIO_P1_13 = 27, /*!< Version 2, Pin P1-13 */ - RPI_V2_GPIO_P1_15 = 22, /*!< Version 2, Pin P1-15 */ - RPI_V2_GPIO_P1_16 = 23, /*!< Version 2, Pin P1-16 */ - RPI_V2_GPIO_P1_18 = 24, /*!< Version 2, Pin P1-18 */ - RPI_V2_GPIO_P1_19 = 10, /*!< Version 2, Pin P1-19, MOSI when SPI0 in use */ - RPI_V2_GPIO_P1_21 = 9, /*!< Version 2, Pin P1-21, MISO when SPI0 in use */ - RPI_V2_GPIO_P1_22 = 25, /*!< Version 2, Pin P1-22 */ - RPI_V2_GPIO_P1_23 = 11, /*!< Version 2, Pin P1-23, CLK when SPI0 in use */ - RPI_V2_GPIO_P1_24 = 8, /*!< Version 2, Pin P1-24, CE0 when SPI0 in use */ - RPI_V2_GPIO_P1_26 = 7, /*!< Version 2, Pin P1-26, CE1 when SPI0 in use */ - RPI_V2_GPIO_P1_29 = 5, /*!< Version 2, Pin P1-29 */ - RPI_V2_GPIO_P1_31 = 6, /*!< Version 2, Pin P1-31 */ - RPI_V2_GPIO_P1_32 = 12, /*!< Version 2, Pin P1-32 */ - RPI_V2_GPIO_P1_33 = 13, /*!< Version 2, Pin P1-33 */ - RPI_V2_GPIO_P1_35 = 19, /*!< Version 2, Pin P1-35, can be PWM channel 1 in ALT FUN 5 */ - RPI_V2_GPIO_P1_36 = 16, /*!< Version 2, Pin P1-36 */ - RPI_V2_GPIO_P1_37 = 26, /*!< Version 2, Pin P1-37 */ - RPI_V2_GPIO_P1_38 = 20, /*!< Version 2, Pin P1-38 */ - RPI_V2_GPIO_P1_40 = 21, /*!< Version 2, Pin P1-40 */ + RPI_V2_GPIO_P1_03 = 2, /*!< Version 2, Pin P1-03 */ + RPI_V2_GPIO_P1_05 = 3, /*!< Version 2, Pin P1-05 */ + RPI_V2_GPIO_P1_07 = 4, /*!< Version 2, Pin P1-07 */ + RPI_V2_GPIO_P1_08 = 14, /*!< Version 2, Pin P1-08, defaults to alt function 0 UART0_TXD */ + RPI_V2_GPIO_P1_10 = 15, /*!< Version 2, Pin P1-10, defaults to alt function 0 UART0_RXD */ + RPI_V2_GPIO_P1_11 = 17, /*!< Version 2, Pin P1-11 */ + RPI_V2_GPIO_P1_12 = 18, /*!< Version 2, Pin P1-12, can be PWM channel 0 in ALT FUN 5 */ + RPI_V2_GPIO_P1_13 = 27, /*!< Version 2, Pin P1-13 */ + RPI_V2_GPIO_P1_15 = 22, /*!< Version 2, Pin P1-15 */ + RPI_V2_GPIO_P1_16 = 23, /*!< Version 2, Pin P1-16 */ + RPI_V2_GPIO_P1_18 = 24, /*!< Version 2, Pin P1-18 */ + RPI_V2_GPIO_P1_19 = 10, /*!< Version 2, Pin P1-19, MOSI when SPI0 in use */ + RPI_V2_GPIO_P1_21 = 9, /*!< Version 2, Pin P1-21, MISO when SPI0 in use */ + RPI_V2_GPIO_P1_22 = 25, /*!< Version 2, Pin P1-22 */ + RPI_V2_GPIO_P1_23 = 11, /*!< Version 2, Pin P1-23, CLK when SPI0 in use */ + RPI_V2_GPIO_P1_24 = 8, /*!< Version 2, Pin P1-24, CE0 when SPI0 in use */ + RPI_V2_GPIO_P1_26 = 7, /*!< Version 2, Pin P1-26, CE1 when SPI0 in use */ + RPI_V2_GPIO_P1_29 = 5, /*!< Version 2, Pin P1-29 */ + RPI_V2_GPIO_P1_31 = 6, /*!< Version 2, Pin P1-31 */ + RPI_V2_GPIO_P1_32 = 12, /*!< Version 2, Pin P1-32 */ + RPI_V2_GPIO_P1_33 = 13, /*!< Version 2, Pin P1-33 */ + RPI_V2_GPIO_P1_35 = 19, /*!< Version 2, Pin P1-35, can be PWM channel 1 in ALT FUN 5 */ + RPI_V2_GPIO_P1_36 = 16, /*!< Version 2, Pin P1-36 */ + RPI_V2_GPIO_P1_37 = 26, /*!< Version 2, Pin P1-37 */ + RPI_V2_GPIO_P1_38 = 20, /*!< Version 2, Pin P1-38 */ + RPI_V2_GPIO_P1_40 = 21, /*!< Version 2, Pin P1-40 */ /* RPi Version 2, new plug P5 */ - RPI_V2_GPIO_P5_03 = 28, /*!< Version 2, Pin P5-03 */ - RPI_V2_GPIO_P5_04 = 29, /*!< Version 2, Pin P5-04 */ - RPI_V2_GPIO_P5_05 = 30, /*!< Version 2, Pin P5-05 */ - RPI_V2_GPIO_P5_06 = 31, /*!< Version 2, Pin P5-06 */ + RPI_V2_GPIO_P5_03 = 28, /*!< Version 2, Pin P5-03 */ + RPI_V2_GPIO_P5_04 = 29, /*!< Version 2, Pin P5-04 */ + RPI_V2_GPIO_P5_05 = 30, /*!< Version 2, Pin P5-05 */ + RPI_V2_GPIO_P5_06 = 31, /*!< Version 2, Pin P5-06 */ /* RPi B+ J8 header, also RPi 2 40 pin GPIO header */ - RPI_BPLUS_GPIO_J8_03 = 2, /*!< B+, Pin J8-03 */ - RPI_BPLUS_GPIO_J8_05 = 3, /*!< B+, Pin J8-05 */ - RPI_BPLUS_GPIO_J8_07 = 4, /*!< B+, Pin J8-07 */ - RPI_BPLUS_GPIO_J8_08 = 14, /*!< B+, Pin J8-08, defaults to alt function 0 UART0_TXD */ - RPI_BPLUS_GPIO_J8_10 = 15, /*!< B+, Pin J8-10, defaults to alt function 0 UART0_RXD */ - RPI_BPLUS_GPIO_J8_11 = 17, /*!< B+, Pin J8-11 */ - RPI_BPLUS_GPIO_J8_12 = 18, /*!< B+, Pin J8-12, can be PWM channel 0 in ALT FUN 5 */ - RPI_BPLUS_GPIO_J8_13 = 27, /*!< B+, Pin J8-13 */ - RPI_BPLUS_GPIO_J8_15 = 22, /*!< B+, Pin J8-15 */ - RPI_BPLUS_GPIO_J8_16 = 23, /*!< B+, Pin J8-16 */ - RPI_BPLUS_GPIO_J8_18 = 24, /*!< B+, Pin J8-18 */ - RPI_BPLUS_GPIO_J8_19 = 10, /*!< B+, Pin J8-19, MOSI when SPI0 in use */ - RPI_BPLUS_GPIO_J8_21 = 9, /*!< B+, Pin J8-21, MISO when SPI0 in use */ - RPI_BPLUS_GPIO_J8_22 = 25, /*!< B+, Pin J8-22 */ - RPI_BPLUS_GPIO_J8_23 = 11, /*!< B+, Pin J8-23, CLK when SPI0 in use */ - RPI_BPLUS_GPIO_J8_24 = 8, /*!< B+, Pin J8-24, CE0 when SPI0 in use */ - RPI_BPLUS_GPIO_J8_26 = 7, /*!< B+, Pin J8-26, CE1 when SPI0 in use */ - RPI_BPLUS_GPIO_J8_29 = 5, /*!< B+, Pin J8-29, */ - RPI_BPLUS_GPIO_J8_31 = 6, /*!< B+, Pin J8-31, */ - RPI_BPLUS_GPIO_J8_32 = 12, /*!< B+, Pin J8-32, */ - RPI_BPLUS_GPIO_J8_33 = 13, /*!< B+, Pin J8-33, */ - RPI_BPLUS_GPIO_J8_35 = 19, /*!< B+, Pin J8-35, can be PWM channel 1 in ALT FUN 5 */ - RPI_BPLUS_GPIO_J8_36 = 16, /*!< B+, Pin J8-36, */ - RPI_BPLUS_GPIO_J8_37 = 26, /*!< B+, Pin J8-37, */ - RPI_BPLUS_GPIO_J8_38 = 20, /*!< B+, Pin J8-38, */ - RPI_BPLUS_GPIO_J8_40 = 21 /*!< B+, Pin J8-40, */ + RPI_BPLUS_GPIO_J8_03 = 2, /*!< B+, Pin J8-03 */ + RPI_BPLUS_GPIO_J8_05 = 3, /*!< B+, Pin J8-05 */ + RPI_BPLUS_GPIO_J8_07 = 4, /*!< B+, Pin J8-07 */ + RPI_BPLUS_GPIO_J8_08 = 14, /*!< B+, Pin J8-08, defaults to alt function 0 UART0_TXD */ + RPI_BPLUS_GPIO_J8_10 = 15, /*!< B+, Pin J8-10, defaults to alt function 0 UART0_RXD */ + RPI_BPLUS_GPIO_J8_11 = 17, /*!< B+, Pin J8-11 */ + RPI_BPLUS_GPIO_J8_12 = 18, /*!< B+, Pin J8-12, can be PWM channel 0 in ALT FUN 5 */ + RPI_BPLUS_GPIO_J8_13 = 27, /*!< B+, Pin J8-13 */ + RPI_BPLUS_GPIO_J8_15 = 22, /*!< B+, Pin J8-15 */ + RPI_BPLUS_GPIO_J8_16 = 23, /*!< B+, Pin J8-16 */ + RPI_BPLUS_GPIO_J8_18 = 24, /*!< B+, Pin J8-18 */ + RPI_BPLUS_GPIO_J8_19 = 10, /*!< B+, Pin J8-19, MOSI when SPI0 in use */ + RPI_BPLUS_GPIO_J8_21 = 9, /*!< B+, Pin J8-21, MISO when SPI0 in use */ + RPI_BPLUS_GPIO_J8_22 = 25, /*!< B+, Pin J8-22 */ + RPI_BPLUS_GPIO_J8_23 = 11, /*!< B+, Pin J8-23, CLK when SPI0 in use */ + RPI_BPLUS_GPIO_J8_24 = 8, /*!< B+, Pin J8-24, CE0 when SPI0 in use */ + RPI_BPLUS_GPIO_J8_26 = 7, /*!< B+, Pin J8-26, CE1 when SPI0 in use */ + RPI_BPLUS_GPIO_J8_29 = 5, /*!< B+, Pin J8-29, */ + RPI_BPLUS_GPIO_J8_31 = 6, /*!< B+, Pin J8-31, */ + RPI_BPLUS_GPIO_J8_32 = 12, /*!< B+, Pin J8-32, */ + RPI_BPLUS_GPIO_J8_33 = 13, /*!< B+, Pin J8-33, */ + RPI_BPLUS_GPIO_J8_35 = 19, /*!< B+, Pin J8-35, can be PWM channel 1 in ALT FUN 5 */ + RPI_BPLUS_GPIO_J8_36 = 16, /*!< B+, Pin J8-36, */ + RPI_BPLUS_GPIO_J8_37 = 26, /*!< B+, Pin J8-37, */ + RPI_BPLUS_GPIO_J8_38 = 20, /*!< B+, Pin J8-38, */ + RPI_BPLUS_GPIO_J8_40 = 21 /*!< B+, Pin J8-40, */ } RPiGPIOPin; /* Defines for AUX GPIO register offsets from BCM2835_AUX_BASE. */ -#define BCM2835_AUX_IRQ 0x0000 /*!< xxx */ -#define BCM2835_AUX_ENABLE 0x0004 /*!< */ - -#define BCM2835_AUX_ENABLE_UART1 0x01 /*!< */ -#define BCM2835_AUX_ENABLE_SPI0 0x02 /*!< SPI0 (SPI1 in the device) */ -#define BCM2835_AUX_ENABLE_SPI1 0x04 /*!< SPI1 (SPI2 in the device) */ +#define BCM2835_AUX_IRQ 0x0000 /*!< xxx */ +#define BCM2835_AUX_ENABLE 0x0004 /*!< */ +#define BCM2835_AUX_ENABLE_UART1 0x01 /*!< */ +#define BCM2835_AUX_ENABLE_SPI0 0x02 /*!< SPI0 (SPI1 in the device) */ +#define BCM2835_AUX_ENABLE_SPI1 0x04 /*!< SPI1 (SPI2 in the device) */ -#define BCM2835_AUX_SPI_CNTL0 0x0000 /*!< */ -#define BCM2835_AUX_SPI_CNTL1 0x0004 /*!< */ -#define BCM2835_AUX_SPI_STAT 0x0008 /*!< */ -#define BCM2835_AUX_SPI_PEEK 0x000C /*!< Read but do not take from FF */ -#define BCM2835_AUX_SPI_IO 0x0020 /*!< Write = TX, read=RX */ -#define BCM2835_AUX_SPI_TXHOLD 0x0030 /*!< Write = TX keep CS, read=RX */ +#define BCM2835_AUX_SPI_CNTL0 0x0000 /*!< */ +#define BCM2835_AUX_SPI_CNTL1 0x0004 /*!< */ +#define BCM2835_AUX_SPI_STAT 0x0008 /*!< */ +#define BCM2835_AUX_SPI_PEEK 0x000C /*!< Read but do not take from FF */ +#define BCM2835_AUX_SPI_IO 0x0020 /*!< Write = TX, read=RX */ +#define BCM2835_AUX_SPI_TXHOLD 0x0030 /*!< Write = TX keep CS, read=RX */ -#define BCM2835_AUX_SPI_CLOCK_MIN 30500 /*!< 30,5kHz */ -#define BCM2835_AUX_SPI_CLOCK_MAX 125000000 /*!< 125Mhz */ +#define BCM2835_AUX_SPI_CLOCK_MIN 30500 /*!< 30,5kHz */ +#define BCM2835_AUX_SPI_CLOCK_MAX 125000000 /*!< 125Mhz */ -#define BCM2835_AUX_SPI_CNTL0_SPEED 0xFFF00000 /*!< */ -#define BCM2835_AUX_SPI_CNTL0_SPEED_MAX 0xFFF /*!< */ +#define BCM2835_AUX_SPI_CNTL0_SPEED 0xFFF00000 /*!< */ +#define BCM2835_AUX_SPI_CNTL0_SPEED_MAX 0xFFF /*!< */ #define BCM2835_AUX_SPI_CNTL0_SPEED_SHIFT 20 /*!< */ #define BCM2835_AUX_SPI_CNTL0_CS0_N 0x000C0000 /*!< CS 0 low */ #define BCM2835_AUX_SPI_CNTL0_CS1_N 0x000A0000 /*!< CS 1 low */ -#define BCM2835_AUX_SPI_CNTL0_CS2_N 0x00060000 /*!< CS 2 low */ - -#define BCM2835_AUX_SPI_CNTL0_POSTINPUT 0x00010000 /*!< */ -#define BCM2835_AUX_SPI_CNTL0_VAR_CS 0x00008000 /*!< */ -#define BCM2835_AUX_SPI_CNTL0_VAR_WIDTH 0x00004000 /*!< */ -#define BCM2835_AUX_SPI_CNTL0_DOUTHOLD 0x00003000 /*!< */ -#define BCM2835_AUX_SPI_CNTL0_ENABLE 0x00000800 /*!< */ -#define BCM2835_AUX_SPI_CNTL0_CPHA_IN 0x00000400 /*!< */ -#define BCM2835_AUX_SPI_CNTL0_CLEARFIFO 0x00000200 /*!< */ -#define BCM2835_AUX_SPI_CNTL0_CPHA_OUT 0x00000100 /*!< */ -#define BCM2835_AUX_SPI_CNTL0_CPOL 0x00000080 /*!< */ -#define BCM2835_AUX_SPI_CNTL0_MSBF_OUT 0x00000040 /*!< */ -#define BCM2835_AUX_SPI_CNTL0_SHIFTLEN 0x0000003F /*!< */ - -#define BCM2835_AUX_SPI_CNTL1_CSHIGH 0x00000700 /*!< */ -#define BCM2835_AUX_SPI_CNTL1_IDLE 0x00000080 /*!< */ -#define BCM2835_AUX_SPI_CNTL1_TXEMPTY 0x00000040 /*!< */ -#define BCM2835_AUX_SPI_CNTL1_MSBF_IN 0x00000002 /*!< */ -#define BCM2835_AUX_SPI_CNTL1_KEEP_IN 0x00000001 /*!< */ - -#define BCM2835_AUX_SPI_STAT_TX_LVL 0xFF000000 /*!< */ -#define BCM2835_AUX_SPI_STAT_RX_LVL 0x00FF0000 /*!< */ -#define BCM2835_AUX_SPI_STAT_TX_FULL 0x00000400 /*!< */ -#define BCM2835_AUX_SPI_STAT_TX_EMPTY 0x00000200 /*!< */ -#define BCM2835_AUX_SPI_STAT_RX_FULL 0x00000100 /*!< */ -#define BCM2835_AUX_SPI_STAT_RX_EMPTY 0x00000080 /*!< */ -#define BCM2835_AUX_SPI_STAT_BUSY 0x00000040 /*!< */ -#define BCM2835_AUX_SPI_STAT_BITCOUNT 0x0000003F /*!< */ +#define BCM2835_AUX_SPI_CNTL0_CS2_N 0x00060000 /*!< CS 2 low */ + +#define BCM2835_AUX_SPI_CNTL0_POSTINPUT 0x00010000 /*!< */ +#define BCM2835_AUX_SPI_CNTL0_VAR_CS 0x00008000 /*!< */ +#define BCM2835_AUX_SPI_CNTL0_VAR_WIDTH 0x00004000 /*!< */ +#define BCM2835_AUX_SPI_CNTL0_DOUTHOLD 0x00003000 /*!< */ +#define BCM2835_AUX_SPI_CNTL0_ENABLE 0x00000800 /*!< */ +#define BCM2835_AUX_SPI_CNTL0_CPHA_IN 0x00000400 /*!< */ +#define BCM2835_AUX_SPI_CNTL0_CLEARFIFO 0x00000200 /*!< */ +#define BCM2835_AUX_SPI_CNTL0_CPHA_OUT 0x00000100 /*!< */ +#define BCM2835_AUX_SPI_CNTL0_CPOL 0x00000080 /*!< */ +#define BCM2835_AUX_SPI_CNTL0_MSBF_OUT 0x00000040 /*!< */ +#define BCM2835_AUX_SPI_CNTL0_SHIFTLEN 0x0000003F /*!< */ + +#define BCM2835_AUX_SPI_CNTL1_CSHIGH 0x00000700 /*!< */ +#define BCM2835_AUX_SPI_CNTL1_IDLE 0x00000080 /*!< */ +#define BCM2835_AUX_SPI_CNTL1_TXEMPTY 0x00000040 /*!< */ +#define BCM2835_AUX_SPI_CNTL1_MSBF_IN 0x00000002 /*!< */ +#define BCM2835_AUX_SPI_CNTL1_KEEP_IN 0x00000001 /*!< */ + +#define BCM2835_AUX_SPI_STAT_TX_LVL 0xFF000000 /*!< */ +#define BCM2835_AUX_SPI_STAT_RX_LVL 0x00FF0000 /*!< */ +#define BCM2835_AUX_SPI_STAT_TX_FULL 0x00000400 /*!< */ +#define BCM2835_AUX_SPI_STAT_TX_EMPTY 0x00000200 /*!< */ +#define BCM2835_AUX_SPI_STAT_RX_FULL 0x00000100 /*!< */ +#define BCM2835_AUX_SPI_STAT_RX_EMPTY 0x00000080 /*!< */ +#define BCM2835_AUX_SPI_STAT_BUSY 0x00000040 /*!< */ +#define BCM2835_AUX_SPI_STAT_BITCOUNT 0x0000003F /*!< */ /* Defines for SPI GPIO register offsets from BCM2835_SPI0_BASE. @@ -1006,28 +998,25 @@ typedef enum /*! \brief bcm2835SPIBitOrder SPI Bit order Specifies the SPI data bit ordering for bcm2835_spi_setBitOrder() */ -typedef enum -{ +typedef enum { BCM2835_SPI_BIT_ORDER_LSBFIRST = 0, /*!< LSB First */ BCM2835_SPI_BIT_ORDER_MSBFIRST = 1 /*!< MSB First */ -}bcm2835SPIBitOrder; +} bcm2835SPIBitOrder; /*! \brief SPI Data mode Specify the SPI data mode to be passed to bcm2835_spi_setDataMode() */ -typedef enum -{ +typedef enum { BCM2835_SPI_MODE0 = 0, /*!< CPOL = 0, CPHA = 0 */ BCM2835_SPI_MODE1 = 1, /*!< CPOL = 0, CPHA = 1 */ BCM2835_SPI_MODE2 = 2, /*!< CPOL = 1, CPHA = 0 */ BCM2835_SPI_MODE3 = 3 /*!< CPOL = 1, CPHA = 1 */ -}bcm2835SPIMode; +} bcm2835SPIMode; /*! \brief bcm2835SPIChipSelect Specify the SPI chip select pin(s) */ -typedef enum -{ +typedef enum { BCM2835_SPI_CS0 = 0, /*!< Chip Select 0 */ BCM2835_SPI_CS1 = 1, /*!< Chip Select 1 */ BCM2835_SPI_CS2 = 2, /*!< Chip Select 2 (ie pins CS1 and CS2 are asserted) */ @@ -1048,25 +1037,24 @@ typedef enum \endcode in the config.txt */ -typedef enum -{ +typedef enum { BCM2835_SPI_CLOCK_DIVIDER_65536 = 0, /*!< 65536 = 3.814697260kHz on Rpi2, 6.1035156kHz on RPI3 */ BCM2835_SPI_CLOCK_DIVIDER_32768 = 32768, /*!< 32768 = 7.629394531kHz on Rpi2, 12.20703125kHz on RPI3 */ BCM2835_SPI_CLOCK_DIVIDER_16384 = 16384, /*!< 16384 = 15.25878906kHz on Rpi2, 24.4140625kHz on RPI3 */ - BCM2835_SPI_CLOCK_DIVIDER_8192 = 8192, /*!< 8192 = 30.51757813kHz on Rpi2, 48.828125kHz on RPI3 */ - BCM2835_SPI_CLOCK_DIVIDER_4096 = 4096, /*!< 4096 = 61.03515625kHz on Rpi2, 97.65625kHz on RPI3 */ - BCM2835_SPI_CLOCK_DIVIDER_2048 = 2048, /*!< 2048 = 122.0703125kHz on Rpi2, 195.3125kHz on RPI3 */ - BCM2835_SPI_CLOCK_DIVIDER_1024 = 1024, /*!< 1024 = 244.140625kHz on Rpi2, 390.625kHz on RPI3 */ - BCM2835_SPI_CLOCK_DIVIDER_512 = 512, /*!< 512 = 488.28125kHz on Rpi2, 781.25kHz on RPI3 */ - BCM2835_SPI_CLOCK_DIVIDER_256 = 256, /*!< 256 = 976.5625kHz on Rpi2, 1.5625MHz on RPI3 */ - BCM2835_SPI_CLOCK_DIVIDER_128 = 128, /*!< 128 = 1.953125MHz on Rpi2, 3.125MHz on RPI3 */ - BCM2835_SPI_CLOCK_DIVIDER_64 = 64, /*!< 64 = 3.90625MHz on Rpi2, 6.250MHz on RPI3 */ - BCM2835_SPI_CLOCK_DIVIDER_32 = 32, /*!< 32 = 7.8125MHz on Rpi2, 12.5MHz on RPI3 */ - BCM2835_SPI_CLOCK_DIVIDER_16 = 16, /*!< 16 = 15.625MHz on Rpi2, 25MHz on RPI3 */ - BCM2835_SPI_CLOCK_DIVIDER_8 = 8, /*!< 8 = 31.25MHz on Rpi2, 50MHz on RPI3 */ - BCM2835_SPI_CLOCK_DIVIDER_4 = 4, /*!< 4 = 62.5MHz on Rpi2, 100MHz on RPI3. Dont expect this speed to work reliably. */ - BCM2835_SPI_CLOCK_DIVIDER_2 = 2, /*!< 2 = 125MHz on Rpi2, 200MHz on RPI3, fastest you can get. Dont expect this speed to work reliably.*/ - BCM2835_SPI_CLOCK_DIVIDER_1 = 1 /*!< 1 = 3.814697260kHz on Rpi2, 6.1035156kHz on RPI3, same as 0/65536 */ + BCM2835_SPI_CLOCK_DIVIDER_8192 = 8192, /*!< 8192 = 30.51757813kHz on Rpi2, 48.828125kHz on RPI3 */ + BCM2835_SPI_CLOCK_DIVIDER_4096 = 4096, /*!< 4096 = 61.03515625kHz on Rpi2, 97.65625kHz on RPI3 */ + BCM2835_SPI_CLOCK_DIVIDER_2048 = 2048, /*!< 2048 = 122.0703125kHz on Rpi2, 195.3125kHz on RPI3 */ + BCM2835_SPI_CLOCK_DIVIDER_1024 = 1024, /*!< 1024 = 244.140625kHz on Rpi2, 390.625kHz on RPI3 */ + BCM2835_SPI_CLOCK_DIVIDER_512 = 512, /*!< 512 = 488.28125kHz on Rpi2, 781.25kHz on RPI3 */ + BCM2835_SPI_CLOCK_DIVIDER_256 = 256, /*!< 256 = 976.5625kHz on Rpi2, 1.5625MHz on RPI3 */ + BCM2835_SPI_CLOCK_DIVIDER_128 = 128, /*!< 128 = 1.953125MHz on Rpi2, 3.125MHz on RPI3 */ + BCM2835_SPI_CLOCK_DIVIDER_64 = 64, /*!< 64 = 3.90625MHz on Rpi2, 6.250MHz on RPI3 */ + BCM2835_SPI_CLOCK_DIVIDER_32 = 32, /*!< 32 = 7.8125MHz on Rpi2, 12.5MHz on RPI3 */ + BCM2835_SPI_CLOCK_DIVIDER_16 = 16, /*!< 16 = 15.625MHz on Rpi2, 25MHz on RPI3 */ + BCM2835_SPI_CLOCK_DIVIDER_8 = 8, /*!< 8 = 31.25MHz on Rpi2, 50MHz on RPI3 */ + BCM2835_SPI_CLOCK_DIVIDER_4 = 4, /*!< 4 = 62.5MHz on Rpi2, 100MHz on RPI3. Dont expect this speed to work reliably. */ + BCM2835_SPI_CLOCK_DIVIDER_2 = 2, /*!< 2 = 125MHz on Rpi2, 200MHz on RPI3, fastest you can get. Dont expect this speed to work reliably.*/ + BCM2835_SPI_CLOCK_DIVIDER_1 = 1 /*!< 1 = 3.814697260kHz on Rpi2, 6.1035156kHz on RPI3, same as 0/65536 */ } bcm2835SPIClockDivider; /// \brief bcm2835SPISpeed @@ -1091,60 +1079,58 @@ typedef enum GPIO register offsets from BCM2835_BSC*_BASE. Offsets into the BSC Peripheral block in bytes per 3.1 BSC Register Map */ -#define BCM2835_BSC_C 0x0000 /*!< BSC Master Control */ -#define BCM2835_BSC_S 0x0004 /*!< BSC Master Status */ -#define BCM2835_BSC_DLEN 0x0008 /*!< BSC Master Data Length */ -#define BCM2835_BSC_A 0x000c /*!< BSC Master Slave Address */ -#define BCM2835_BSC_FIFO 0x0010 /*!< BSC Master Data FIFO */ -#define BCM2835_BSC_DIV 0x0014 /*!< BSC Master Clock Divider */ -#define BCM2835_BSC_DEL 0x0018 /*!< BSC Master Data Delay */ -#define BCM2835_BSC_CLKT 0x001c /*!< BSC Master Clock Stretch Timeout */ +#define BCM2835_BSC_C 0x0000 /*!< BSC Master Control */ +#define BCM2835_BSC_S 0x0004 /*!< BSC Master Status */ +#define BCM2835_BSC_DLEN 0x0008 /*!< BSC Master Data Length */ +#define BCM2835_BSC_A 0x000c /*!< BSC Master Slave Address */ +#define BCM2835_BSC_FIFO 0x0010 /*!< BSC Master Data FIFO */ +#define BCM2835_BSC_DIV 0x0014 /*!< BSC Master Clock Divider */ +#define BCM2835_BSC_DEL 0x0018 /*!< BSC Master Data Delay */ +#define BCM2835_BSC_CLKT 0x001c /*!< BSC Master Clock Stretch Timeout */ /* Register masks for BSC_C */ -#define BCM2835_BSC_C_I2CEN 0x00008000 /*!< I2C Enable, 0 = disabled, 1 = enabled */ -#define BCM2835_BSC_C_INTR 0x00000400 /*!< Interrupt on RX */ -#define BCM2835_BSC_C_INTT 0x00000200 /*!< Interrupt on TX */ -#define BCM2835_BSC_C_INTD 0x00000100 /*!< Interrupt on DONE */ -#define BCM2835_BSC_C_ST 0x00000080 /*!< Start transfer, 1 = Start a new transfer */ -#define BCM2835_BSC_C_CLEAR_1 0x00000020 /*!< Clear FIFO Clear */ -#define BCM2835_BSC_C_CLEAR_2 0x00000010 /*!< Clear FIFO Clear */ -#define BCM2835_BSC_C_READ 0x00000001 /*!< Read transfer */ +#define BCM2835_BSC_C_I2CEN 0x00008000 /*!< I2C Enable, 0 = disabled, 1 = enabled */ +#define BCM2835_BSC_C_INTR 0x00000400 /*!< Interrupt on RX */ +#define BCM2835_BSC_C_INTT 0x00000200 /*!< Interrupt on TX */ +#define BCM2835_BSC_C_INTD 0x00000100 /*!< Interrupt on DONE */ +#define BCM2835_BSC_C_ST 0x00000080 /*!< Start transfer, 1 = Start a new transfer */ +#define BCM2835_BSC_C_CLEAR_1 0x00000020 /*!< Clear FIFO Clear */ +#define BCM2835_BSC_C_CLEAR_2 0x00000010 /*!< Clear FIFO Clear */ +#define BCM2835_BSC_C_READ 0x00000001 /*!< Read transfer */ /* Register masks for BSC_S */ -#define BCM2835_BSC_S_CLKT 0x00000200 /*!< Clock stretch timeout */ -#define BCM2835_BSC_S_ERR 0x00000100 /*!< ACK error */ -#define BCM2835_BSC_S_RXF 0x00000080 /*!< RXF FIFO full, 0 = FIFO is not full, 1 = FIFO is full */ -#define BCM2835_BSC_S_TXE 0x00000040 /*!< TXE FIFO full, 0 = FIFO is not full, 1 = FIFO is full */ -#define BCM2835_BSC_S_RXD 0x00000020 /*!< RXD FIFO contains data */ -#define BCM2835_BSC_S_TXD 0x00000010 /*!< TXD FIFO can accept data */ -#define BCM2835_BSC_S_RXR 0x00000008 /*!< RXR FIFO needs reading (full) */ -#define BCM2835_BSC_S_TXW 0x00000004 /*!< TXW FIFO needs writing (full) */ -#define BCM2835_BSC_S_DONE 0x00000002 /*!< Transfer DONE */ -#define BCM2835_BSC_S_TA 0x00000001 /*!< Transfer Active */ - -#define BCM2835_BSC_FIFO_SIZE 16 /*!< BSC FIFO size */ +#define BCM2835_BSC_S_CLKT 0x00000200 /*!< Clock stretch timeout */ +#define BCM2835_BSC_S_ERR 0x00000100 /*!< ACK error */ +#define BCM2835_BSC_S_RXF 0x00000080 /*!< RXF FIFO full, 0 = FIFO is not full, 1 = FIFO is full */ +#define BCM2835_BSC_S_TXE 0x00000040 /*!< TXE FIFO full, 0 = FIFO is not full, 1 = FIFO is full */ +#define BCM2835_BSC_S_RXD 0x00000020 /*!< RXD FIFO contains data */ +#define BCM2835_BSC_S_TXD 0x00000010 /*!< TXD FIFO can accept data */ +#define BCM2835_BSC_S_RXR 0x00000008 /*!< RXR FIFO needs reading (full) */ +#define BCM2835_BSC_S_TXW 0x00000004 /*!< TXW FIFO needs writing (full) */ +#define BCM2835_BSC_S_DONE 0x00000002 /*!< Transfer DONE */ +#define BCM2835_BSC_S_TA 0x00000001 /*!< Transfer Active */ + +#define BCM2835_BSC_FIFO_SIZE 16 /*!< BSC FIFO size */ /*! \brief bcm2835I2CClockDivider Specifies the divider used to generate the I2C clock from the system clock. Clock divided is based on nominal base clock rate of 250MHz */ -typedef enum -{ - BCM2835_I2C_CLOCK_DIVIDER_2500 = 2500, /*!< 2500 = 10us = 100 kHz */ - BCM2835_I2C_CLOCK_DIVIDER_626 = 626, /*!< 622 = 2.504us = 399.3610 kHz */ - BCM2835_I2C_CLOCK_DIVIDER_150 = 150, /*!< 150 = 60ns = 1.666 MHz (default at reset) */ - BCM2835_I2C_CLOCK_DIVIDER_148 = 148 /*!< 148 = 59ns = 1.689 MHz */ +typedef enum { + BCM2835_I2C_CLOCK_DIVIDER_2500 = 2500, /*!< 2500 = 10us = 100 kHz */ + BCM2835_I2C_CLOCK_DIVIDER_626 = 626, /*!< 622 = 2.504us = 399.3610 kHz */ + BCM2835_I2C_CLOCK_DIVIDER_150 = 150, /*!< 150 = 60ns = 1.666 MHz (default at reset) */ + BCM2835_I2C_CLOCK_DIVIDER_148 = 148 /*!< 148 = 59ns = 1.689 MHz */ } bcm2835I2CClockDivider; /*! \brief bcm2835I2CReasonCodes Specifies the reason codes for the bcm2835_i2c_write and bcm2835_i2c_read functions. */ -typedef enum -{ - BCM2835_I2C_REASON_OK = 0x00, /*!< Success */ - BCM2835_I2C_REASON_ERROR_NACK = 0x01, /*!< Received a NACK */ - BCM2835_I2C_REASON_ERROR_CLKT = 0x02, /*!< Received Clock Stretch Timeout */ - BCM2835_I2C_REASON_ERROR_DATA = 0x04 /*!< Not all data is sent / received */ +typedef enum { + BCM2835_I2C_REASON_OK = 0x00, /*!< Success */ + BCM2835_I2C_REASON_ERROR_NACK = 0x01, /*!< Received a NACK */ + BCM2835_I2C_REASON_ERROR_CLKT = 0x02, /*!< Received Clock Stretch Timeout */ + BCM2835_I2C_REASON_ERROR_DATA = 0x04 /*!< Not all data is sent / received */ } bcm2835I2CReasonCodes; /* Defines for ST @@ -1158,9 +1144,9 @@ typedef enum The system timer free-running counter upper register is a read-only register that returns the current value of the upper 32-bits of the free running counter. */ -#define BCM2835_ST_CS 0x0000 /*!< System Timer Control/Status */ -#define BCM2835_ST_CLO 0x0004 /*!< System Timer Counter Lower 32 bits */ -#define BCM2835_ST_CHI 0x0008 /*!< System Timer Counter Upper 32 bits */ +#define BCM2835_ST_CS 0x0000 /*!< System Timer Control/Status */ +#define BCM2835_ST_CLO 0x0004 /*!< System Timer Counter Lower 32 bits */ +#define BCM2835_ST_CHI 0x0008 /*!< System Timer Counter Upper 32 bits */ /*! @} */ @@ -1203,743 +1189,741 @@ typedef enum Clock divided is based on nominal PWM base clock rate of 19.2MHz The frequencies shown for each divider have been confirmed by measurement */ -typedef enum -{ - BCM2835_PWM_CLOCK_DIVIDER_2048 = 2048, /*!< 2048 = 9.375kHz */ - BCM2835_PWM_CLOCK_DIVIDER_1024 = 1024, /*!< 1024 = 18.75kHz */ - BCM2835_PWM_CLOCK_DIVIDER_512 = 512, /*!< 512 = 37.5kHz */ - BCM2835_PWM_CLOCK_DIVIDER_256 = 256, /*!< 256 = 75kHz */ - BCM2835_PWM_CLOCK_DIVIDER_128 = 128, /*!< 128 = 150kHz */ - BCM2835_PWM_CLOCK_DIVIDER_64 = 64, /*!< 64 = 300kHz */ - BCM2835_PWM_CLOCK_DIVIDER_32 = 32, /*!< 32 = 600.0kHz */ - BCM2835_PWM_CLOCK_DIVIDER_16 = 16, /*!< 16 = 1.2MHz */ - BCM2835_PWM_CLOCK_DIVIDER_8 = 8, /*!< 8 = 2.4MHz */ - BCM2835_PWM_CLOCK_DIVIDER_4 = 4, /*!< 4 = 4.8MHz */ - BCM2835_PWM_CLOCK_DIVIDER_2 = 2, /*!< 2 = 9.6MHz, fastest you can get */ - BCM2835_PWM_CLOCK_DIVIDER_1 = 1 /*!< 1 = 4.6875kHz, same as divider 4096 */ +typedef enum { + BCM2835_PWM_CLOCK_DIVIDER_2048 = 2048, /*!< 2048 = 9.375kHz */ + BCM2835_PWM_CLOCK_DIVIDER_1024 = 1024, /*!< 1024 = 18.75kHz */ + BCM2835_PWM_CLOCK_DIVIDER_512 = 512, /*!< 512 = 37.5kHz */ + BCM2835_PWM_CLOCK_DIVIDER_256 = 256, /*!< 256 = 75kHz */ + BCM2835_PWM_CLOCK_DIVIDER_128 = 128, /*!< 128 = 150kHz */ + BCM2835_PWM_CLOCK_DIVIDER_64 = 64, /*!< 64 = 300kHz */ + BCM2835_PWM_CLOCK_DIVIDER_32 = 32, /*!< 32 = 600.0kHz */ + BCM2835_PWM_CLOCK_DIVIDER_16 = 16, /*!< 16 = 1.2MHz */ + BCM2835_PWM_CLOCK_DIVIDER_8 = 8, /*!< 8 = 2.4MHz */ + BCM2835_PWM_CLOCK_DIVIDER_4 = 4, /*!< 4 = 4.8MHz */ + BCM2835_PWM_CLOCK_DIVIDER_2 = 2, /*!< 2 = 9.6MHz, fastest you can get */ + BCM2835_PWM_CLOCK_DIVIDER_1 = 1 /*!< 1 = 4.6875kHz, same as divider 4096 */ } bcm2835PWMClockDivider; /* Historical name compatibility */ #ifndef BCM2835_NO_DELAY_COMPATIBILITY -#define delay(x) bcm2835_delay(x) -#define delayMicroseconds(x) bcm2835_delayMicroseconds(x) -#define millis() bcm2835_millis() + #define delay(x) bcm2835_delay(x) + #define delayMicroseconds(x) bcm2835_delayMicroseconds(x) + #define millis() bcm2835_millis() #endif #ifdef __cplusplus extern "C" { #endif - /*! \defgroup init Library initialisation and management - These functions allow you to intialise and control the bcm2835 library - @{ - */ - - /*! Initialise the library by opening /dev/mem (if you are root) - or /dev/gpiomem (if you are not) - and getting pointers to the - internal memory for BCM 2835 device registers. You must call this (successfully) - before calling any other - functions in this library (except bcm2835_set_debug). - If bcm2835_init() fails by returning 0, - calling any other function may result in crashes or other failures. - If bcm2835_init() succeeds but you are not running as root, then only gpio operations - are permitted, and calling any other functions may result in crashes or other failures. . - Prints messages to stderr in case of errors. - \return 1 if successful else 0 - */ - extern int bcm2835_init(void); - - /*! Close the library, deallocating any allocated memory and closing /dev/mem - \return 1 if successful else 0 - */ - extern int bcm2835_close(void); - - /*! Sets the debug level of the library. - A value of 1 prevents mapping to /dev/mem, and makes the library print out - what it would do, rather than accessing the GPIO registers. - A value of 0, the default, causes normal operation. - Call this before calling bcm2835_init(); - \param[in] debug The new debug level. 1 means debug - */ - extern void bcm2835_set_debug(uint8_t debug); - - /*! Returns the version number of the library, same as BCM2835_VERSION - \return the current library version number - */ - extern unsigned int bcm2835_version(void); - - /*! @} */ - - /*! \defgroup lowlevel Low level register access - These functions provide low level register access, and should not generally - need to be used - - @{ - */ - - /*! Gets the base of a register - \param[in] regbase You can use one of the common values BCM2835_REGBASE_* - in \ref bcm2835RegisterBase - \return the register base - \sa Physical Addresses - */ - extern uint32_t* bcm2835_regbase(uint8_t regbase); - - /*! Reads 32 bit value from a peripheral address WITH a memory barrier before and after each read. - This is safe, but slow. The MB before protects this read from any in-flight reads that didn't - use a MB. The MB after protects subsequent reads from another peripheral. - - \param[in] paddr Physical address to read from. See BCM2835_GPIO_BASE etc. - \return the value read from the 32 bit register - \sa Physical Addresses - */ - extern uint32_t bcm2835_peri_read(volatile uint32_t* paddr); - - /*! Reads 32 bit value from a peripheral address WITHOUT the read barriers - You should only use this when: - o your code has previously called bcm2835_peri_read() for a register - within the same peripheral, and no read or write to another peripheral has occurred since. - o your code has called bcm2835_memory_barrier() since the last access to ANOTHER peripheral. - - \param[in] paddr Physical address to read from. See BCM2835_GPIO_BASE etc. - \return the value read from the 32 bit register - \sa Physical Addresses - */ - extern uint32_t bcm2835_peri_read_nb(volatile uint32_t* paddr); - - - /*! Writes 32 bit value from a peripheral address WITH a memory barrier before and after each write - This is safe, but slow. The MB before ensures that any in-flight write to another peripheral - completes before this write is issued. The MB after ensures that subsequent reads and writes - to another peripheral will see the effect of this write. - - This is a tricky optimization; if you aren't sure, use the barrier version. - - \param[in] paddr Physical address to read from. See BCM2835_GPIO_BASE etc. - \param[in] value The 32 bit value to write - \sa Physical Addresses - */ - extern void bcm2835_peri_write(volatile uint32_t* paddr, uint32_t value); - - /*! Writes 32 bit value from a peripheral address without the write barrier - You should only use this when: - o your code has previously called bcm2835_peri_write() for a register - within the same peripheral, and no other peripheral access has occurred since. - o your code has called bcm2835_memory_barrier() since the last access to ANOTHER peripheral. - - This is a tricky optimization; if you aren't sure, use the barrier version. - - \param[in] paddr Physical address to read from. See BCM2835_GPIO_BASE etc. - \param[in] value The 32 bit value to write - \sa Physical Addresses - */ - extern void bcm2835_peri_write_nb(volatile uint32_t* paddr, uint32_t value); - - /*! Alters a number of bits in a 32 peripheral regsiter. - It reads the current valu and then alters the bits defines as 1 in mask, - according to the bit value in value. - All other bits that are 0 in the mask are unaffected. - Use this to alter a subset of the bits in a register. - Memory barriers are used. Note that this is not atomic; an interrupt - routine can cause unexpected results. - \param[in] paddr Physical address to read from. See BCM2835_GPIO_BASE etc. - \param[in] value The 32 bit value to write, masked in by mask. - \param[in] mask Bitmask that defines the bits that will be altered in the register. - \sa Physical Addresses - */ - extern void bcm2835_peri_set_bits(volatile uint32_t* paddr, uint32_t value, uint32_t mask); - /*! @} end of lowlevel */ - - /*! \defgroup gpio GPIO register access - These functions allow you to control the GPIO interface. You can set the - function of each GPIO pin, read the input state and set the output state. - @{ - */ - - /*! Sets the Function Select register for the given pin, which configures - the pin as Input, Output or one of the 6 alternate functions. - \param[in] pin GPIO number, or one of RPI_GPIO_P1_* from \ref RPiGPIOPin. - \param[in] mode Mode to set the pin to, one of BCM2835_GPIO_FSEL_* from \ref bcm2835FunctionSelect - */ - extern void bcm2835_gpio_fsel(uint8_t pin, uint8_t mode); - - /*! Sets the specified pin output to - HIGH. - \param[in] pin GPIO number, or one of RPI_GPIO_P1_* from \ref RPiGPIOPin. - \sa bcm2835_gpio_write() - */ - extern void bcm2835_gpio_set(uint8_t pin); - - /*! Sets the specified pin output to - LOW. - \param[in] pin GPIO number, or one of RPI_GPIO_P1_* from \ref RPiGPIOPin. - \sa bcm2835_gpio_write() - */ - extern void bcm2835_gpio_clr(uint8_t pin); - - /*! Sets any of the first 32 GPIO output pins specified in the mask to - HIGH. - \param[in] mask Mask of pins to affect. Use eg: (1 << RPI_GPIO_P1_03) | (1 << RPI_GPIO_P1_05) - \sa bcm2835_gpio_write_multi() - */ - extern void bcm2835_gpio_set_multi(uint32_t mask); - - /*! Sets any of the first 32 GPIO output pins specified in the mask to - LOW. - \param[in] mask Mask of pins to affect. Use eg: (1 << RPI_GPIO_P1_03) | (1 << RPI_GPIO_P1_05) - \sa bcm2835_gpio_write_multi() - */ - extern void bcm2835_gpio_clr_multi(uint32_t mask); - - /*! Reads the current level on the specified - pin and returns either HIGH or LOW. Works whether or not the pin - is an input or an output. - \param[in] pin GPIO number, or one of RPI_GPIO_P1_* from \ref RPiGPIOPin. - \return the current level either HIGH or LOW - */ - extern uint8_t bcm2835_gpio_lev(uint8_t pin); - - /*! Event Detect Status. - Tests whether the specified pin has detected a level or edge - as requested by bcm2835_gpio_ren(), bcm2835_gpio_fen(), bcm2835_gpio_hen(), - bcm2835_gpio_len(), bcm2835_gpio_aren(), bcm2835_gpio_afen(). - Clear the flag for a given pin by calling bcm2835_gpio_set_eds(pin); - \param[in] pin GPIO number, or one of RPI_GPIO_P1_* from \ref RPiGPIOPin. - \return HIGH if the event detect status for the given pin is true. - */ - extern uint8_t bcm2835_gpio_eds(uint8_t pin); - - /*! Same as bcm2835_gpio_eds() but checks if any of the pins specified in - the mask have detected a level or edge. - \param[in] mask Mask of pins to check. Use eg: (1 << RPI_GPIO_P1_03) | (1 << RPI_GPIO_P1_05) - \return Mask of pins HIGH if the event detect status for the given pin is true. - */ - extern uint32_t bcm2835_gpio_eds_multi(uint32_t mask); - - /*! Sets the Event Detect Status register for a given pin to 1, - which has the effect of clearing the flag. Use this afer seeing - an Event Detect Status on the pin. - \param[in] pin GPIO number, or one of RPI_GPIO_P1_* from \ref RPiGPIOPin. - */ - extern void bcm2835_gpio_set_eds(uint8_t pin); - - /*! Same as bcm2835_gpio_set_eds() but clears the flag for any pin which - is set in the mask. - \param[in] mask Mask of pins to clear. Use eg: (1 << RPI_GPIO_P1_03) | (1 << RPI_GPIO_P1_05) - */ - extern void bcm2835_gpio_set_eds_multi(uint32_t mask); - - /*! Enable Rising Edge Detect Enable for the specified pin. - When a rising edge is detected, sets the appropriate pin in Event Detect Status. - The GPRENn registers use - synchronous edge detection. This means the input signal is sampled using the - system clock and then it is looking for a ?011? pattern on the sampled signal. This - has the effect of suppressing glitches. - \param[in] pin GPIO number, or one of RPI_GPIO_P1_* from \ref RPiGPIOPin. - */ - extern void bcm2835_gpio_ren(uint8_t pin); - - /*! Disable Rising Edge Detect Enable for the specified pin. - \param[in] pin GPIO number, or one of RPI_GPIO_P1_* from \ref RPiGPIOPin. - */ - extern void bcm2835_gpio_clr_ren(uint8_t pin); - - /*! Enable Falling Edge Detect Enable for the specified pin. - When a falling edge is detected, sets the appropriate pin in Event Detect Status. - The GPRENn registers use - synchronous edge detection. This means the input signal is sampled using the - system clock and then it is looking for a ?100? pattern on the sampled signal. This - has the effect of suppressing glitches. - \param[in] pin GPIO number, or one of RPI_GPIO_P1_* from \ref RPiGPIOPin. - */ - extern void bcm2835_gpio_fen(uint8_t pin); - - /*! Disable Falling Edge Detect Enable for the specified pin. - \param[in] pin GPIO number, or one of RPI_GPIO_P1_* from \ref RPiGPIOPin. - */ - extern void bcm2835_gpio_clr_fen(uint8_t pin); - - /*! Enable High Detect Enable for the specified pin. - When a HIGH level is detected on the pin, sets the appropriate pin in Event Detect Status. - \param[in] pin GPIO number, or one of RPI_GPIO_P1_* from \ref RPiGPIOPin. - */ - extern void bcm2835_gpio_hen(uint8_t pin); - - /*! Disable High Detect Enable for the specified pin. - \param[in] pin GPIO number, or one of RPI_GPIO_P1_* from \ref RPiGPIOPin. - */ - extern void bcm2835_gpio_clr_hen(uint8_t pin); - - /*! Enable Low Detect Enable for the specified pin. - When a LOW level is detected on the pin, sets the appropriate pin in Event Detect Status. - \param[in] pin GPIO number, or one of RPI_GPIO_P1_* from \ref RPiGPIOPin. - */ - extern void bcm2835_gpio_len(uint8_t pin); - - /*! Disable Low Detect Enable for the specified pin. - \param[in] pin GPIO number, or one of RPI_GPIO_P1_* from \ref RPiGPIOPin. - */ - extern void bcm2835_gpio_clr_len(uint8_t pin); - - /*! Enable Asynchronous Rising Edge Detect Enable for the specified pin. - When a rising edge is detected, sets the appropriate pin in Event Detect Status. - Asynchronous means the incoming signal is not sampled by the system clock. As such - rising edges of very short duration can be detected. - \param[in] pin GPIO number, or one of RPI_GPIO_P1_* from \ref RPiGPIOPin. - */ - extern void bcm2835_gpio_aren(uint8_t pin); - - /*! Disable Asynchronous Rising Edge Detect Enable for the specified pin. - \param[in] pin GPIO number, or one of RPI_GPIO_P1_* from \ref RPiGPIOPin. - */ - extern void bcm2835_gpio_clr_aren(uint8_t pin); - - /*! Enable Asynchronous Falling Edge Detect Enable for the specified pin. - When a falling edge is detected, sets the appropriate pin in Event Detect Status. - Asynchronous means the incoming signal is not sampled by the system clock. As such - falling edges of very short duration can be detected. - \param[in] pin GPIO number, or one of RPI_GPIO_P1_* from \ref RPiGPIOPin. - */ - extern void bcm2835_gpio_afen(uint8_t pin); - - /*! Disable Asynchronous Falling Edge Detect Enable for the specified pin. - \param[in] pin GPIO number, or one of RPI_GPIO_P1_* from \ref RPiGPIOPin. - */ - extern void bcm2835_gpio_clr_afen(uint8_t pin); - - /*! Sets the Pull-up/down register for the given pin. This is - used with bcm2835_gpio_pudclk() to set the Pull-up/down resistor for the given pin. - However, it is usually more convenient to use bcm2835_gpio_set_pud(). - \param[in] pud The desired Pull-up/down mode. One of BCM2835_GPIO_PUD_* from bcm2835PUDControl - On the RPI 4, although this function and bcm2835_gpio_pudclk() are supported for backward - compatibility, new code should always use bcm2835_gpio_set_pud(). - \sa bcm2835_gpio_set_pud() - */ - extern void bcm2835_gpio_pud(uint8_t pud); - - /*! Clocks the Pull-up/down value set earlier by bcm2835_gpio_pud() into the pin. - \param[in] pin GPIO number, or one of RPI_GPIO_P1_* from \ref RPiGPIOPin. - \param[in] on HIGH to clock the value from bcm2835_gpio_pud() into the pin. - LOW to remove the clock. - - On the RPI 4, although this function and bcm2835_gpio_pud() are supported for backward - compatibility, new code should always use bcm2835_gpio_set_pud(). - - \sa bcm2835_gpio_set_pud() - */ - extern void bcm2835_gpio_pudclk(uint8_t pin, uint8_t on); - - /*! Reads and returns the Pad Control for the given GPIO group. - Caution: requires root access. - \param[in] group The GPIO pad group number, one of BCM2835_PAD_GROUP_GPIO_* - \return Mask of bits from BCM2835_PAD_* from \ref bcm2835PadGroup - */ - extern uint32_t bcm2835_gpio_pad(uint8_t group); - - /*! Sets the Pad Control for the given GPIO group. - Caution: requires root access. - \param[in] group The GPIO pad group number, one of BCM2835_PAD_GROUP_GPIO_* - \param[in] control Mask of bits from BCM2835_PAD_* from \ref bcm2835PadGroup. Note - that it is not necessary to include BCM2835_PAD_PASSWRD in the mask as this - is automatically included. - */ - extern void bcm2835_gpio_set_pad(uint8_t group, uint32_t control); - - /*! Delays for the specified number of milliseconds. - Uses nanosleep(), and therefore does not use CPU until the time is up. - However, you are at the mercy of nanosleep(). From the manual for nanosleep(): - If the interval specified in req is not an exact multiple of the granularity - underlying clock (see time(7)), then the interval will be - rounded up to the next multiple. Furthermore, after the sleep completes, - there may still be a delay before the CPU becomes free to once - again execute the calling thread. - \param[in] millis Delay in milliseconds - */ - extern void bcm2835_delay (unsigned int millis); - - /*! Delays for the specified number of microseconds. - Uses a combination of nanosleep() and a busy wait loop on the BCM2835 system timers, - However, you are at the mercy of nanosleep(). From the manual for nanosleep(): - If the interval specified in req is not an exact multiple of the granularity - underlying clock (see time(7)), then the interval will be - rounded up to the next multiple. Furthermore, after the sleep completes, - there may still be a delay before the CPU becomes free to once - again execute the calling thread. - For times less than about 450 microseconds, uses a busy wait on the System Timer. - It is reported that a delay of 0 microseconds on RaspberryPi will in fact - result in a delay of about 80 microseconds. Your mileage may vary. - \param[in] micros Delay in microseconds - */ - extern void bcm2835_delayMicroseconds (uint64_t micros); - - /// Indicate the number of milliseconds since startup of PI - /// This function is like the Arduino millis function - /// \return Number of milliseconds - extern unsigned int bcm2835_millis(void); - - /*! Sets the output state of the specified pin - \param[in] pin GPIO number, or one of RPI_GPIO_P1_* from \ref RPiGPIOPin. - \param[in] on HIGH sets the output to HIGH and LOW to LOW. - */ - extern void bcm2835_gpio_write(uint8_t pin, uint8_t on); - - /*! Sets any of the first 32 GPIO output pins specified in the mask to the state given by on - \param[in] mask Mask of pins to affect. Use eg: (1 << RPI_GPIO_P1_03) | (1 << RPI_GPIO_P1_05) - \param[in] on HIGH sets the output to HIGH and LOW to LOW. - */ - extern void bcm2835_gpio_write_multi(uint32_t mask, uint8_t on); - - /*! Sets the first 32 GPIO output pins specified in the mask to the value given by value - \param[in] value values required for each bit masked in by mask, eg: (1 << RPI_GPIO_P1_03) | (1 << RPI_GPIO_P1_05) - \param[in] mask Mask of pins to affect. Use eg: (1 << RPI_GPIO_P1_03) | (1 << RPI_GPIO_P1_05) - */ - extern void bcm2835_gpio_write_mask(uint32_t value, uint32_t mask); - - /*! Sets the Pull-up/down mode for the specified pin. This is more convenient than - clocking the mode in with bcm2835_gpio_pud() and bcm2835_gpio_pudclk(). - \param[in] pin GPIO number, or one of RPI_GPIO_P1_* from \ref RPiGPIOPin. - \param[in] pud The desired Pull-up/down mode. One of BCM2835_GPIO_PUD_* from bcm2835PUDControl - */ - extern void bcm2835_gpio_set_pud(uint8_t pin, uint8_t pud); - - /*! On the BCM2711 based RPI 4, gets the current Pull-up/down mode for the specified pin. - Returns one of BCM2835_GPIO_PUD_* from bcm2835PUDControl. - On earlier RPI versions not based on the BCM2711, returns BCM2835_GPIO_PUD_ERROR - \param[in] pin GPIO number, or one of RPI_GPIO_P1_* from \ref RPiGPIOPin. - */ - - extern uint8_t bcm2835_gpio_get_pud(uint8_t pin); - - /*! @} */ - - /*! \defgroup spi SPI access - These functions let you use SPI0 (Serial Peripheral Interface) to - interface with an external SPI device. - @{ - */ - - /*! Start SPI operations. - Forces RPi SPI0 pins P1-19 (MOSI), P1-21 (MISO), P1-23 (CLK), P1-24 (CE0) and P1-26 (CE1) - to alternate function ALT0, which enables those pins for SPI interface. - You should call bcm2835_spi_end() when all SPI funcitons are complete to return the pins to - their default functions. - \sa bcm2835_spi_end() - \return 1 if successful, 0 otherwise (perhaps because you are not running as root) - */ - extern int bcm2835_spi_begin(void); - - /*! End SPI operations. - SPI0 pins P1-19 (MOSI), P1-21 (MISO), P1-23 (CLK), P1-24 (CE0) and P1-26 (CE1) - are returned to their default INPUT behaviour. - */ - extern void bcm2835_spi_end(void); - - /*! Sets the SPI bit order - Set the bit order to be used for transmit and receive. The bcm2835 SPI0 only supports BCM2835_SPI_BIT_ORDER_MSB, - so if you select BCM2835_SPI_BIT_ORDER_LSB, the bytes will be reversed in software. - The library defaults to BCM2835_SPI_BIT_ORDER_MSB. - \param[in] order The desired bit order, one of BCM2835_SPI_BIT_ORDER_*, - see \ref bcm2835SPIBitOrder - */ - extern void bcm2835_spi_setBitOrder(uint8_t order); - - /*! Sets the SPI clock divider and therefore the - SPI clock speed. - \param[in] divider The desired SPI clock divider, one of BCM2835_SPI_CLOCK_DIVIDER_*, - see \ref bcm2835SPIClockDivider - */ - extern void bcm2835_spi_setClockDivider(uint16_t divider); - - /*! Sets the SPI clock divider by converting the speed parameter to - the equivalent SPI clock divider. ( see \sa bcm2835_spi_setClockDivider) - \param[in] speed_hz The desired SPI clock speed in Hz - */ - extern void bcm2835_spi_set_speed_hz(uint32_t speed_hz); - - /*! Sets the SPI data mode - Sets the clock polariy and phase - \param[in] mode The desired data mode, one of BCM2835_SPI_MODE*, - see \ref bcm2835SPIMode - */ - extern void bcm2835_spi_setDataMode(uint8_t mode); - - /*! Sets the chip select pin(s) - When an bcm2835_spi_transfer() is made, the selected pin(s) will be asserted during the - transfer. - \param[in] cs Specifies the CS pins(s) that are used to activate the desired slave. - One of BCM2835_SPI_CS*, see \ref bcm2835SPIChipSelect - */ - extern void bcm2835_spi_chipSelect(uint8_t cs); - - /*! Sets the chip select pin polarity for a given pin - When an bcm2835_spi_transfer() occurs, the currently selected chip select pin(s) - will be asserted to the - value given by active. When transfers are not happening, the chip select pin(s) - return to the complement (inactive) value. - \param[in] cs The chip select pin to affect - \param[in] active Whether the chip select pin is to be active HIGH - */ - extern void bcm2835_spi_setChipSelectPolarity(uint8_t cs, uint8_t active); - - /*! Transfers one byte to and from the currently selected SPI slave. - Asserts the currently selected CS pins (as previously set by bcm2835_spi_chipSelect) - during the transfer. - Clocks the 8 bit value out on MOSI, and simultaneously clocks in data from MISO. - Returns the read data byte from the slave. - Uses polled transfer as per section 10.6.1 of the BCM 2835 ARM Peripherls manual - \param[in] value The 8 bit data byte to write to MOSI - \return The 8 bit byte simultaneously read from MISO - \sa bcm2835_spi_transfern() - */ - extern uint8_t bcm2835_spi_transfer(uint8_t value); - - /*! Transfers any number of bytes to and from the currently selected SPI slave. - Asserts the currently selected CS pins (as previously set by bcm2835_spi_chipSelect) - during the transfer. - Clocks the len 8 bit bytes out on MOSI, and simultaneously clocks in data from MISO. - The data read read from the slave is placed into rbuf. rbuf must be at least len bytes long - Uses polled transfer as per section 10.6.1 of the BCM 2835 ARM Peripherls manual - \param[in] tbuf Buffer of bytes to send. - \param[out] rbuf Received bytes will by put in this buffer - \param[in] len Number of bytes in the tbuf buffer, and the number of bytes to send/received - \sa bcm2835_spi_transfer() - */ - extern void bcm2835_spi_transfernb(char* tbuf, char* rbuf, uint32_t len); - - /*! Transfers any number of bytes to and from the currently selected SPI slave - using bcm2835_spi_transfernb. - The returned data from the slave replaces the transmitted data in the buffer. - \param[in,out] buf Buffer of bytes to send. Received bytes will replace the contents - \param[in] len Number of bytes int eh buffer, and the number of bytes to send/received - \sa bcm2835_spi_transfer() - */ - extern void bcm2835_spi_transfern(char* buf, uint32_t len); - - /*! Transfers any number of bytes to the currently selected SPI slave. - Asserts the currently selected CS pins (as previously set by bcm2835_spi_chipSelect) - during the transfer. - \param[in] buf Buffer of bytes to send. - \param[in] len Number of bytes in the buf buffer, and the number of bytes to send - */ - extern void bcm2835_spi_writenb(const char* buf, uint32_t len); - - /*! Transfers half-word to and from the currently selected SPI slave. - Asserts the currently selected CS pins (as previously set by bcm2835_spi_chipSelect) - during the transfer. - Clocks the 8 bit value out on MOSI, and simultaneously clocks in data from MISO. - Returns the read data byte from the slave. - Uses polled transfer as per section 10.6.1 of the BCM 2835 ARM Peripherls manual - \param[in] data The 8 bit data byte to write to MOSI - \sa bcm2835_spi_writenb() - */ - extern void bcm2835_spi_write(uint16_t data); - - /*! Start AUX SPI operations. - Forces RPi AUX SPI pins P1-36 (MOSI), P1-38 (MISO), P1-40 (CLK) and P1-36 (CE2) - to alternate function ALT4, which enables those pins for SPI interface. - \return 1 if successful, 0 otherwise (perhaps because you are not running as root) - */ - extern int bcm2835_aux_spi_begin(void); - - /*! End AUX SPI operations. - SPI1 pins P1-36 (MOSI), P1-38 (MISO), P1-40 (CLK) and P1-36 (CE2) - are returned to their default INPUT behaviour. - */ - extern void bcm2835_aux_spi_end(void); - - /*! Sets the AUX SPI clock divider and therefore the AUX SPI clock speed. - \param[in] divider The desired AUX SPI clock divider. - */ - extern void bcm2835_aux_spi_setClockDivider(uint16_t divider); - - /*! - * Calculates the input for \sa bcm2835_aux_spi_setClockDivider - * @param speed_hz A value between \sa BCM2835_AUX_SPI_CLOCK_MIN and \sa BCM2835_AUX_SPI_CLOCK_MAX - * @return Input for \sa bcm2835_aux_spi_setClockDivider - */ - extern uint16_t bcm2835_aux_spi_CalcClockDivider(uint32_t speed_hz); - - /*! Transfers half-word to and from the AUX SPI slave. - Asserts the currently selected CS pins during the transfer. - \param[in] data The 8 bit data byte to write to MOSI - \return The 8 bit byte simultaneously read from MISO - \sa bcm2835_spi_transfern() - */ - extern void bcm2835_aux_spi_write(uint16_t data); - - /*! Transfers any number of bytes to the AUX SPI slave. - Asserts the CE2 pin during the transfer. - \param[in] buf Buffer of bytes to send. - \param[in] len Number of bytes in the tbuf buffer, and the number of bytes to send - */ - extern void bcm2835_aux_spi_writenb(const char *buf, uint32_t len); - - /*! Transfers any number of bytes to and from the AUX SPI slave - using bcm2835_aux_spi_transfernb. - The returned data from the slave replaces the transmitted data in the buffer. - \param[in,out] buf Buffer of bytes to send. Received bytes will replace the contents - \param[in] len Number of bytes int eh buffer, and the number of bytes to send/received - \sa bcm2835_aux_spi_transfer() - */ - extern void bcm2835_aux_spi_transfern(char *buf, uint32_t len); - - /*! Transfers any number of bytes to and from the AUX SPI slave. - Asserts the CE2 pin during the transfer. - Clocks the len 8 bit bytes out on MOSI, and simultaneously clocks in data from MISO. - The data read read from the slave is placed into rbuf. rbuf must be at least len bytes long - \param[in] tbuf Buffer of bytes to send. - \param[out] rbuf Received bytes will by put in this buffer - \param[in] len Number of bytes in the tbuf buffer, and the number of bytes to send/received - */ - extern void bcm2835_aux_spi_transfernb(const char *tbuf, char *rbuf, uint32_t len); - - /*! @} */ - - /*! \defgroup i2c I2C access - These functions let you use I2C (The Broadcom Serial Control bus with the Philips - I2C bus/interface version 2.1 January 2000.) to interface with an external I2C device. - @{ - */ - - /*! Start I2C operations. - Forces RPi I2C pins P1-03 (SDA) and P1-05 (SCL) - to alternate function ALT0, which enables those pins for I2C interface. - You should call bcm2835_i2c_end() when all I2C functions are complete to return the pins to - their default functions - \return 1 if successful, 0 otherwise (perhaps because you are not running as root) - \sa bcm2835_i2c_end() - */ - extern int bcm2835_i2c_begin(void); - - /*! End I2C operations. - I2C pins P1-03 (SDA) and P1-05 (SCL) - are returned to their default INPUT behaviour. - */ - extern void bcm2835_i2c_end(void); - - /*! Sets the I2C slave address. - \param[in] addr The I2C slave address. - */ - extern void bcm2835_i2c_setSlaveAddress(uint8_t addr); - - /*! Sets the I2C clock divider and therefore the I2C clock speed. - \param[in] divider The desired I2C clock divider, one of BCM2835_I2C_CLOCK_DIVIDER_*, - see \ref bcm2835I2CClockDivider - */ - extern void bcm2835_i2c_setClockDivider(uint16_t divider); - - /*! Sets the I2C clock divider by converting the baudrate parameter to - the equivalent I2C clock divider. ( see \sa bcm2835_i2c_setClockDivider) - For the I2C standard 100khz you would set baudrate to 100000 - The use of baudrate corresponds to its use in the I2C kernel device - driver. (Of course, bcm2835 has nothing to do with the kernel driver) - */ - extern void bcm2835_i2c_set_baudrate(uint32_t baudrate); - - /*! Transfers any number of bytes to the currently selected I2C slave. - (as previously set by \sa bcm2835_i2c_setSlaveAddress) - \param[in] buf Buffer of bytes to send. - \param[in] len Number of bytes in the buf buffer, and the number of bytes to send. - \return reason see \ref bcm2835I2CReasonCodes - */ - extern uint8_t bcm2835_i2c_write(const char * buf, uint32_t len); - - /*! Transfers any number of bytes from the currently selected I2C slave. - (as previously set by \sa bcm2835_i2c_setSlaveAddress) - \param[in] buf Buffer of bytes to receive. - \param[in] len Number of bytes in the buf buffer, and the number of bytes to received. - \return reason see \ref bcm2835I2CReasonCodes - */ - extern uint8_t bcm2835_i2c_read(char* buf, uint32_t len); - - /*! Allows reading from I2C slaves that require a repeated start (without any prior stop) - to read after the required slave register has been set. For example, the popular - MPL3115A2 pressure and temperature sensor. Note that your device must support or - require this mode. If your device does not require this mode then the standard - combined: - \sa bcm2835_i2c_write - \sa bcm2835_i2c_read - are a better choice. - Will read from the slave previously set by \sa bcm2835_i2c_setSlaveAddress - \param[in] regaddr Buffer containing the slave register you wish to read from. - \param[in] buf Buffer of bytes to receive. - \param[in] len Number of bytes in the buf buffer, and the number of bytes to received. - \return reason see \ref bcm2835I2CReasonCodes - */ - extern uint8_t bcm2835_i2c_read_register_rs(char* regaddr, char* buf, uint32_t len); - - /*! Allows sending an arbitrary number of bytes to I2C slaves before issuing a repeated - start (with no prior stop) and reading a response. - Necessary for devices that require such behavior, such as the MLX90620. - Will write to and read from the slave previously set by \sa bcm2835_i2c_setSlaveAddress - \param[in] cmds Buffer containing the bytes to send before the repeated start condition. - \param[in] cmds_len Number of bytes to send from cmds buffer - \param[in] buf Buffer of bytes to receive. - \param[in] buf_len Number of bytes to receive in the buf buffer. - \return reason see \ref bcm2835I2CReasonCodes - */ - extern uint8_t bcm2835_i2c_write_read_rs(char* cmds, uint32_t cmds_len, char* buf, uint32_t buf_len); - - /*! @} */ - - /*! \defgroup st System Timer access - Allows access to and delays using the System Timer Counter. - @{ - */ - - /*! Read the System Timer Counter register. - \return the value read from the System Timer Counter Lower 32 bits register - */ - extern uint64_t bcm2835_st_read(void); - - /*! Delays for the specified number of microseconds with offset. - \param[in] offset_micros Offset in microseconds - \param[in] micros Delay in microseconds - */ - extern void bcm2835_st_delay(uint64_t offset_micros, uint64_t micros); - - /*! @} */ - - /*! \defgroup pwm Pulse Width Modulation - Allows control of 2 independent PWM channels. A limited subset of GPIO pins - can be connected to one of these 2 channels, allowing PWM control of GPIO pins. - You have to set the desired pin into a particular Alt Fun to PWM output. See the PWM - documentation on the Main Page. - @{ - */ - - /*! Sets the PWM clock divisor, - to control the basic PWM pulse widths. - \param[in] divisor Divides the basic 19.2MHz PWM clock. You can use one of the common - values BCM2835_PWM_CLOCK_DIVIDER_* in \ref bcm2835PWMClockDivider - */ - extern void bcm2835_pwm_set_clock(uint32_t divisor); - - /*! Sets the mode of the given PWM channel, - allowing you to control the PWM mode and enable/disable that channel - \param[in] channel The PWM channel. 0 or 1. - \param[in] markspace Set true if you want Mark-Space mode. 0 for Balanced mode. - \param[in] enabled Set true to enable this channel and produce PWM pulses. - */ - extern void bcm2835_pwm_set_mode(uint8_t channel, uint8_t markspace, uint8_t enabled); - - /*! Sets the maximum range of the PWM output. - The data value can vary between 0 and this range to control PWM output - \param[in] channel The PWM channel. 0 or 1. - \param[in] range The maximum value permitted for DATA. - */ - extern void bcm2835_pwm_set_range(uint8_t channel, uint32_t range); - - /*! Sets the PWM pulse ratio to emit to DATA/RANGE, - where RANGE is set by bcm2835_pwm_set_range(). - \param[in] channel The PWM channel. 0 or 1. - \param[in] data Controls the PWM output ratio as a fraction of the range. - Can vary from 0 to RANGE. - */ - extern void bcm2835_pwm_set_data(uint8_t channel, uint32_t data); - - /*! @} */ +/*! \defgroup init Library initialisation and management + These functions allow you to intialise and control the bcm2835 library + @{ +*/ + +/*! Initialise the library by opening /dev/mem (if you are root) + or /dev/gpiomem (if you are not) + and getting pointers to the + internal memory for BCM 2835 device registers. You must call this (successfully) + before calling any other + functions in this library (except bcm2835_set_debug). + If bcm2835_init() fails by returning 0, + calling any other function may result in crashes or other failures. + If bcm2835_init() succeeds but you are not running as root, then only gpio operations + are permitted, and calling any other functions may result in crashes or other failures. . + Prints messages to stderr in case of errors. + \return 1 if successful else 0 +*/ +extern int bcm2835_init(void); + +/*! Close the library, deallocating any allocated memory and closing /dev/mem + \return 1 if successful else 0 +*/ +extern int bcm2835_close(void); + +/*! Sets the debug level of the library. + A value of 1 prevents mapping to /dev/mem, and makes the library print out + what it would do, rather than accessing the GPIO registers. + A value of 0, the default, causes normal operation. + Call this before calling bcm2835_init(); + \param[in] debug The new debug level. 1 means debug +*/ +extern void bcm2835_set_debug(uint8_t debug); + +/*! Returns the version number of the library, same as BCM2835_VERSION + \return the current library version number +*/ +extern unsigned int bcm2835_version(void); + +/*! @} */ + +/*! \defgroup lowlevel Low level register access + These functions provide low level register access, and should not generally + need to be used + + @{ +*/ + +/*! Gets the base of a register + \param[in] regbase You can use one of the common values BCM2835_REGBASE_* + in \ref bcm2835RegisterBase + \return the register base + \sa Physical Addresses +*/ +extern uint32_t* bcm2835_regbase(uint8_t regbase); + +/*! Reads 32 bit value from a peripheral address WITH a memory barrier before and after each read. + This is safe, but slow. The MB before protects this read from any in-flight reads that didn't + use a MB. The MB after protects subsequent reads from another peripheral. + + \param[in] paddr Physical address to read from. See BCM2835_GPIO_BASE etc. + \return the value read from the 32 bit register + \sa Physical Addresses +*/ +extern uint32_t bcm2835_peri_read(volatile uint32_t* paddr); + +/*! Reads 32 bit value from a peripheral address WITHOUT the read barriers + You should only use this when: + o your code has previously called bcm2835_peri_read() for a register + within the same peripheral, and no read or write to another peripheral has occurred since. + o your code has called bcm2835_memory_barrier() since the last access to ANOTHER peripheral. + + \param[in] paddr Physical address to read from. See BCM2835_GPIO_BASE etc. + \return the value read from the 32 bit register + \sa Physical Addresses +*/ +extern uint32_t bcm2835_peri_read_nb(volatile uint32_t* paddr); + +/*! Writes 32 bit value from a peripheral address WITH a memory barrier before and after each write + This is safe, but slow. The MB before ensures that any in-flight write to another peripheral + completes before this write is issued. The MB after ensures that subsequent reads and writes + to another peripheral will see the effect of this write. + + This is a tricky optimization; if you aren't sure, use the barrier version. + + \param[in] paddr Physical address to read from. See BCM2835_GPIO_BASE etc. + \param[in] value The 32 bit value to write + \sa Physical Addresses +*/ +extern void bcm2835_peri_write(volatile uint32_t* paddr, uint32_t value); + +/*! Writes 32 bit value from a peripheral address without the write barrier + You should only use this when: + o your code has previously called bcm2835_peri_write() for a register + within the same peripheral, and no other peripheral access has occurred since. + o your code has called bcm2835_memory_barrier() since the last access to ANOTHER peripheral. + + This is a tricky optimization; if you aren't sure, use the barrier version. + + \param[in] paddr Physical address to read from. See BCM2835_GPIO_BASE etc. + \param[in] value The 32 bit value to write + \sa Physical Addresses +*/ +extern void bcm2835_peri_write_nb(volatile uint32_t* paddr, uint32_t value); + +/*! Alters a number of bits in a 32 peripheral regsiter. + It reads the current valu and then alters the bits defines as 1 in mask, + according to the bit value in value. + All other bits that are 0 in the mask are unaffected. + Use this to alter a subset of the bits in a register. + Memory barriers are used. Note that this is not atomic; an interrupt + routine can cause unexpected results. + \param[in] paddr Physical address to read from. See BCM2835_GPIO_BASE etc. + \param[in] value The 32 bit value to write, masked in by mask. + \param[in] mask Bitmask that defines the bits that will be altered in the register. + \sa Physical Addresses +*/ +extern void bcm2835_peri_set_bits(volatile uint32_t* paddr, uint32_t value, uint32_t mask); +/*! @} end of lowlevel */ + +/*! \defgroup gpio GPIO register access + These functions allow you to control the GPIO interface. You can set the + function of each GPIO pin, read the input state and set the output state. + @{ +*/ + +/*! Sets the Function Select register for the given pin, which configures + the pin as Input, Output or one of the 6 alternate functions. + \param[in] pin GPIO number, or one of RPI_GPIO_P1_* from \ref RPiGPIOPin. + \param[in] mode Mode to set the pin to, one of BCM2835_GPIO_FSEL_* from \ref bcm2835FunctionSelect +*/ +extern void bcm2835_gpio_fsel(uint8_t pin, uint8_t mode); + +/*! Sets the specified pin output to + HIGH. + \param[in] pin GPIO number, or one of RPI_GPIO_P1_* from \ref RPiGPIOPin. + \sa bcm2835_gpio_write() +*/ +extern void bcm2835_gpio_set(uint8_t pin); + +/*! Sets the specified pin output to + LOW. + \param[in] pin GPIO number, or one of RPI_GPIO_P1_* from \ref RPiGPIOPin. + \sa bcm2835_gpio_write() +*/ +extern void bcm2835_gpio_clr(uint8_t pin); + +/*! Sets any of the first 32 GPIO output pins specified in the mask to + HIGH. + \param[in] mask Mask of pins to affect. Use eg: (1 << RPI_GPIO_P1_03) | (1 << RPI_GPIO_P1_05) + \sa bcm2835_gpio_write_multi() +*/ +extern void bcm2835_gpio_set_multi(uint32_t mask); + +/*! Sets any of the first 32 GPIO output pins specified in the mask to + LOW. + \param[in] mask Mask of pins to affect. Use eg: (1 << RPI_GPIO_P1_03) | (1 << RPI_GPIO_P1_05) + \sa bcm2835_gpio_write_multi() +*/ +extern void bcm2835_gpio_clr_multi(uint32_t mask); + +/*! Reads the current level on the specified + pin and returns either HIGH or LOW. Works whether or not the pin + is an input or an output. + \param[in] pin GPIO number, or one of RPI_GPIO_P1_* from \ref RPiGPIOPin. + \return the current level either HIGH or LOW +*/ +extern uint8_t bcm2835_gpio_lev(uint8_t pin); + +/*! Event Detect Status. + Tests whether the specified pin has detected a level or edge + as requested by bcm2835_gpio_ren(), bcm2835_gpio_fen(), bcm2835_gpio_hen(), + bcm2835_gpio_len(), bcm2835_gpio_aren(), bcm2835_gpio_afen(). + Clear the flag for a given pin by calling bcm2835_gpio_set_eds(pin); + \param[in] pin GPIO number, or one of RPI_GPIO_P1_* from \ref RPiGPIOPin. + \return HIGH if the event detect status for the given pin is true. +*/ +extern uint8_t bcm2835_gpio_eds(uint8_t pin); + +/*! Same as bcm2835_gpio_eds() but checks if any of the pins specified in + the mask have detected a level or edge. + \param[in] mask Mask of pins to check. Use eg: (1 << RPI_GPIO_P1_03) | (1 << RPI_GPIO_P1_05) + \return Mask of pins HIGH if the event detect status for the given pin is true. +*/ +extern uint32_t bcm2835_gpio_eds_multi(uint32_t mask); + +/*! Sets the Event Detect Status register for a given pin to 1, + which has the effect of clearing the flag. Use this afer seeing + an Event Detect Status on the pin. + \param[in] pin GPIO number, or one of RPI_GPIO_P1_* from \ref RPiGPIOPin. +*/ +extern void bcm2835_gpio_set_eds(uint8_t pin); + +/*! Same as bcm2835_gpio_set_eds() but clears the flag for any pin which + is set in the mask. + \param[in] mask Mask of pins to clear. Use eg: (1 << RPI_GPIO_P1_03) | (1 << RPI_GPIO_P1_05) +*/ +extern void bcm2835_gpio_set_eds_multi(uint32_t mask); + +/*! Enable Rising Edge Detect Enable for the specified pin. + When a rising edge is detected, sets the appropriate pin in Event Detect Status. + The GPRENn registers use + synchronous edge detection. This means the input signal is sampled using the + system clock and then it is looking for a ?011? pattern on the sampled signal. This + has the effect of suppressing glitches. + \param[in] pin GPIO number, or one of RPI_GPIO_P1_* from \ref RPiGPIOPin. +*/ +extern void bcm2835_gpio_ren(uint8_t pin); + +/*! Disable Rising Edge Detect Enable for the specified pin. + \param[in] pin GPIO number, or one of RPI_GPIO_P1_* from \ref RPiGPIOPin. +*/ +extern void bcm2835_gpio_clr_ren(uint8_t pin); + +/*! Enable Falling Edge Detect Enable for the specified pin. + When a falling edge is detected, sets the appropriate pin in Event Detect Status. + The GPRENn registers use + synchronous edge detection. This means the input signal is sampled using the + system clock and then it is looking for a ?100? pattern on the sampled signal. This + has the effect of suppressing glitches. + \param[in] pin GPIO number, or one of RPI_GPIO_P1_* from \ref RPiGPIOPin. +*/ +extern void bcm2835_gpio_fen(uint8_t pin); + +/*! Disable Falling Edge Detect Enable for the specified pin. + \param[in] pin GPIO number, or one of RPI_GPIO_P1_* from \ref RPiGPIOPin. +*/ +extern void bcm2835_gpio_clr_fen(uint8_t pin); + +/*! Enable High Detect Enable for the specified pin. + When a HIGH level is detected on the pin, sets the appropriate pin in Event Detect Status. + \param[in] pin GPIO number, or one of RPI_GPIO_P1_* from \ref RPiGPIOPin. +*/ +extern void bcm2835_gpio_hen(uint8_t pin); + +/*! Disable High Detect Enable for the specified pin. + \param[in] pin GPIO number, or one of RPI_GPIO_P1_* from \ref RPiGPIOPin. +*/ +extern void bcm2835_gpio_clr_hen(uint8_t pin); + +/*! Enable Low Detect Enable for the specified pin. + When a LOW level is detected on the pin, sets the appropriate pin in Event Detect Status. + \param[in] pin GPIO number, or one of RPI_GPIO_P1_* from \ref RPiGPIOPin. +*/ +extern void bcm2835_gpio_len(uint8_t pin); + +/*! Disable Low Detect Enable for the specified pin. + \param[in] pin GPIO number, or one of RPI_GPIO_P1_* from \ref RPiGPIOPin. +*/ +extern void bcm2835_gpio_clr_len(uint8_t pin); + +/*! Enable Asynchronous Rising Edge Detect Enable for the specified pin. + When a rising edge is detected, sets the appropriate pin in Event Detect Status. + Asynchronous means the incoming signal is not sampled by the system clock. As such + rising edges of very short duration can be detected. + \param[in] pin GPIO number, or one of RPI_GPIO_P1_* from \ref RPiGPIOPin. +*/ +extern void bcm2835_gpio_aren(uint8_t pin); + +/*! Disable Asynchronous Rising Edge Detect Enable for the specified pin. + \param[in] pin GPIO number, or one of RPI_GPIO_P1_* from \ref RPiGPIOPin. +*/ +extern void bcm2835_gpio_clr_aren(uint8_t pin); + +/*! Enable Asynchronous Falling Edge Detect Enable for the specified pin. + When a falling edge is detected, sets the appropriate pin in Event Detect Status. + Asynchronous means the incoming signal is not sampled by the system clock. As such + falling edges of very short duration can be detected. + \param[in] pin GPIO number, or one of RPI_GPIO_P1_* from \ref RPiGPIOPin. +*/ +extern void bcm2835_gpio_afen(uint8_t pin); + +/*! Disable Asynchronous Falling Edge Detect Enable for the specified pin. + \param[in] pin GPIO number, or one of RPI_GPIO_P1_* from \ref RPiGPIOPin. +*/ +extern void bcm2835_gpio_clr_afen(uint8_t pin); + +/*! Sets the Pull-up/down register for the given pin. This is + used with bcm2835_gpio_pudclk() to set the Pull-up/down resistor for the given pin. + However, it is usually more convenient to use bcm2835_gpio_set_pud(). + \param[in] pud The desired Pull-up/down mode. One of BCM2835_GPIO_PUD_* from bcm2835PUDControl + On the RPI 4, although this function and bcm2835_gpio_pudclk() are supported for backward + compatibility, new code should always use bcm2835_gpio_set_pud(). + \sa bcm2835_gpio_set_pud() +*/ +extern void bcm2835_gpio_pud(uint8_t pud); + +/*! Clocks the Pull-up/down value set earlier by bcm2835_gpio_pud() into the pin. + \param[in] pin GPIO number, or one of RPI_GPIO_P1_* from \ref RPiGPIOPin. + \param[in] on HIGH to clock the value from bcm2835_gpio_pud() into the pin. + LOW to remove the clock. + + On the RPI 4, although this function and bcm2835_gpio_pud() are supported for backward + compatibility, new code should always use bcm2835_gpio_set_pud(). + + \sa bcm2835_gpio_set_pud() +*/ +extern void bcm2835_gpio_pudclk(uint8_t pin, uint8_t on); + +/*! Reads and returns the Pad Control for the given GPIO group. + Caution: requires root access. + \param[in] group The GPIO pad group number, one of BCM2835_PAD_GROUP_GPIO_* + \return Mask of bits from BCM2835_PAD_* from \ref bcm2835PadGroup +*/ +extern uint32_t bcm2835_gpio_pad(uint8_t group); + +/*! Sets the Pad Control for the given GPIO group. + Caution: requires root access. + \param[in] group The GPIO pad group number, one of BCM2835_PAD_GROUP_GPIO_* + \param[in] control Mask of bits from BCM2835_PAD_* from \ref bcm2835PadGroup. Note + that it is not necessary to include BCM2835_PAD_PASSWRD in the mask as this + is automatically included. +*/ +extern void bcm2835_gpio_set_pad(uint8_t group, uint32_t control); + +/*! Delays for the specified number of milliseconds. + Uses nanosleep(), and therefore does not use CPU until the time is up. + However, you are at the mercy of nanosleep(). From the manual for nanosleep(): + If the interval specified in req is not an exact multiple of the granularity + underlying clock (see time(7)), then the interval will be + rounded up to the next multiple. Furthermore, after the sleep completes, + there may still be a delay before the CPU becomes free to once + again execute the calling thread. + \param[in] millis Delay in milliseconds +*/ +extern void bcm2835_delay(unsigned int millis); + +/*! Delays for the specified number of microseconds. + Uses a combination of nanosleep() and a busy wait loop on the BCM2835 system timers, + However, you are at the mercy of nanosleep(). From the manual for nanosleep(): + If the interval specified in req is not an exact multiple of the granularity + underlying clock (see time(7)), then the interval will be + rounded up to the next multiple. Furthermore, after the sleep completes, + there may still be a delay before the CPU becomes free to once + again execute the calling thread. + For times less than about 450 microseconds, uses a busy wait on the System Timer. + It is reported that a delay of 0 microseconds on RaspberryPi will in fact + result in a delay of about 80 microseconds. Your mileage may vary. + \param[in] micros Delay in microseconds +*/ +extern void bcm2835_delayMicroseconds(uint64_t micros); + +/// Indicate the number of milliseconds since startup of PI +/// This function is like the Arduino millis function +/// \return Number of milliseconds +extern unsigned int bcm2835_millis(void); + +/*! Sets the output state of the specified pin + \param[in] pin GPIO number, or one of RPI_GPIO_P1_* from \ref RPiGPIOPin. + \param[in] on HIGH sets the output to HIGH and LOW to LOW. +*/ +extern void bcm2835_gpio_write(uint8_t pin, uint8_t on); + +/*! Sets any of the first 32 GPIO output pins specified in the mask to the state given by on + \param[in] mask Mask of pins to affect. Use eg: (1 << RPI_GPIO_P1_03) | (1 << RPI_GPIO_P1_05) + \param[in] on HIGH sets the output to HIGH and LOW to LOW. +*/ +extern void bcm2835_gpio_write_multi(uint32_t mask, uint8_t on); + +/*! Sets the first 32 GPIO output pins specified in the mask to the value given by value + \param[in] value values required for each bit masked in by mask, eg: (1 << RPI_GPIO_P1_03) | (1 << RPI_GPIO_P1_05) + \param[in] mask Mask of pins to affect. Use eg: (1 << RPI_GPIO_P1_03) | (1 << RPI_GPIO_P1_05) +*/ +extern void bcm2835_gpio_write_mask(uint32_t value, uint32_t mask); + +/*! Sets the Pull-up/down mode for the specified pin. This is more convenient than + clocking the mode in with bcm2835_gpio_pud() and bcm2835_gpio_pudclk(). + \param[in] pin GPIO number, or one of RPI_GPIO_P1_* from \ref RPiGPIOPin. + \param[in] pud The desired Pull-up/down mode. One of BCM2835_GPIO_PUD_* from bcm2835PUDControl +*/ +extern void bcm2835_gpio_set_pud(uint8_t pin, uint8_t pud); + +/*! On the BCM2711 based RPI 4, gets the current Pull-up/down mode for the specified pin. + Returns one of BCM2835_GPIO_PUD_* from bcm2835PUDControl. + On earlier RPI versions not based on the BCM2711, returns BCM2835_GPIO_PUD_ERROR + \param[in] pin GPIO number, or one of RPI_GPIO_P1_* from \ref RPiGPIOPin. +*/ + +extern uint8_t bcm2835_gpio_get_pud(uint8_t pin); + +/*! @} */ + +/*! \defgroup spi SPI access + These functions let you use SPI0 (Serial Peripheral Interface) to + interface with an external SPI device. + @{ +*/ + +/*! Start SPI operations. + Forces RPi SPI0 pins P1-19 (MOSI), P1-21 (MISO), P1-23 (CLK), P1-24 (CE0) and P1-26 (CE1) + to alternate function ALT0, which enables those pins for SPI interface. + You should call bcm2835_spi_end() when all SPI funcitons are complete to return the pins to + their default functions. + \sa bcm2835_spi_end() + \return 1 if successful, 0 otherwise (perhaps because you are not running as root) +*/ +extern int bcm2835_spi_begin(void); + +/*! End SPI operations. + SPI0 pins P1-19 (MOSI), P1-21 (MISO), P1-23 (CLK), P1-24 (CE0) and P1-26 (CE1) + are returned to their default INPUT behaviour. +*/ +extern void bcm2835_spi_end(void); + +/*! Sets the SPI bit order + Set the bit order to be used for transmit and receive. The bcm2835 SPI0 only supports BCM2835_SPI_BIT_ORDER_MSB, + so if you select BCM2835_SPI_BIT_ORDER_LSB, the bytes will be reversed in software. + The library defaults to BCM2835_SPI_BIT_ORDER_MSB. + \param[in] order The desired bit order, one of BCM2835_SPI_BIT_ORDER_*, + see \ref bcm2835SPIBitOrder +*/ +extern void bcm2835_spi_setBitOrder(uint8_t order); + +/*! Sets the SPI clock divider and therefore the + SPI clock speed. + \param[in] divider The desired SPI clock divider, one of BCM2835_SPI_CLOCK_DIVIDER_*, + see \ref bcm2835SPIClockDivider +*/ +extern void bcm2835_spi_setClockDivider(uint16_t divider); + +/*! Sets the SPI clock divider by converting the speed parameter to + the equivalent SPI clock divider. ( see \sa bcm2835_spi_setClockDivider) + \param[in] speed_hz The desired SPI clock speed in Hz +*/ +extern void bcm2835_spi_set_speed_hz(uint32_t speed_hz); + +/*! Sets the SPI data mode + Sets the clock polariy and phase + \param[in] mode The desired data mode, one of BCM2835_SPI_MODE*, + see \ref bcm2835SPIMode +*/ +extern void bcm2835_spi_setDataMode(uint8_t mode); + +/*! Sets the chip select pin(s) + When an bcm2835_spi_transfer() is made, the selected pin(s) will be asserted during the + transfer. + \param[in] cs Specifies the CS pins(s) that are used to activate the desired slave. + One of BCM2835_SPI_CS*, see \ref bcm2835SPIChipSelect +*/ +extern void bcm2835_spi_chipSelect(uint8_t cs); + +/*! Sets the chip select pin polarity for a given pin + When an bcm2835_spi_transfer() occurs, the currently selected chip select pin(s) + will be asserted to the + value given by active. When transfers are not happening, the chip select pin(s) + return to the complement (inactive) value. + \param[in] cs The chip select pin to affect + \param[in] active Whether the chip select pin is to be active HIGH +*/ +extern void bcm2835_spi_setChipSelectPolarity(uint8_t cs, uint8_t active); + +/*! Transfers one byte to and from the currently selected SPI slave. + Asserts the currently selected CS pins (as previously set by bcm2835_spi_chipSelect) + during the transfer. + Clocks the 8 bit value out on MOSI, and simultaneously clocks in data from MISO. + Returns the read data byte from the slave. + Uses polled transfer as per section 10.6.1 of the BCM 2835 ARM Peripherls manual + \param[in] value The 8 bit data byte to write to MOSI + \return The 8 bit byte simultaneously read from MISO + \sa bcm2835_spi_transfern() +*/ +extern uint8_t bcm2835_spi_transfer(uint8_t value); + +/*! Transfers any number of bytes to and from the currently selected SPI slave. + Asserts the currently selected CS pins (as previously set by bcm2835_spi_chipSelect) + during the transfer. + Clocks the len 8 bit bytes out on MOSI, and simultaneously clocks in data from MISO. + The data read read from the slave is placed into rbuf. rbuf must be at least len bytes long + Uses polled transfer as per section 10.6.1 of the BCM 2835 ARM Peripherls manual + \param[in] tbuf Buffer of bytes to send. + \param[out] rbuf Received bytes will by put in this buffer + \param[in] len Number of bytes in the tbuf buffer, and the number of bytes to send/received + \sa bcm2835_spi_transfer() +*/ +extern void bcm2835_spi_transfernb(char* tbuf, char* rbuf, uint32_t len); + +/*! Transfers any number of bytes to and from the currently selected SPI slave + using bcm2835_spi_transfernb. + The returned data from the slave replaces the transmitted data in the buffer. + \param[in,out] buf Buffer of bytes to send. Received bytes will replace the contents + \param[in] len Number of bytes int eh buffer, and the number of bytes to send/received + \sa bcm2835_spi_transfer() +*/ +extern void bcm2835_spi_transfern(char* buf, uint32_t len); + +/*! Transfers any number of bytes to the currently selected SPI slave. + Asserts the currently selected CS pins (as previously set by bcm2835_spi_chipSelect) + during the transfer. + \param[in] buf Buffer of bytes to send. + \param[in] len Number of bytes in the buf buffer, and the number of bytes to send +*/ +extern void bcm2835_spi_writenb(const char* buf, uint32_t len); + +/*! Transfers half-word to and from the currently selected SPI slave. + Asserts the currently selected CS pins (as previously set by bcm2835_spi_chipSelect) + during the transfer. + Clocks the 8 bit value out on MOSI, and simultaneously clocks in data from MISO. + Returns the read data byte from the slave. + Uses polled transfer as per section 10.6.1 of the BCM 2835 ARM Peripherls manual + \param[in] data The 8 bit data byte to write to MOSI + \sa bcm2835_spi_writenb() +*/ +extern void bcm2835_spi_write(uint16_t data); + +/*! Start AUX SPI operations. + Forces RPi AUX SPI pins P1-36 (MOSI), P1-38 (MISO), P1-40 (CLK) and P1-36 (CE2) + to alternate function ALT4, which enables those pins for SPI interface. + \return 1 if successful, 0 otherwise (perhaps because you are not running as root) +*/ +extern int bcm2835_aux_spi_begin(void); + +/*! End AUX SPI operations. + SPI1 pins P1-36 (MOSI), P1-38 (MISO), P1-40 (CLK) and P1-36 (CE2) + are returned to their default INPUT behaviour. + */ +extern void bcm2835_aux_spi_end(void); + +/*! Sets the AUX SPI clock divider and therefore the AUX SPI clock speed. + \param[in] divider The desired AUX SPI clock divider. +*/ +extern void bcm2835_aux_spi_setClockDivider(uint16_t divider); + +/*! + * Calculates the input for \sa bcm2835_aux_spi_setClockDivider + * @param speed_hz A value between \sa BCM2835_AUX_SPI_CLOCK_MIN and \sa BCM2835_AUX_SPI_CLOCK_MAX + * @return Input for \sa bcm2835_aux_spi_setClockDivider + */ +extern uint16_t bcm2835_aux_spi_CalcClockDivider(uint32_t speed_hz); + +/*! Transfers half-word to and from the AUX SPI slave. + Asserts the currently selected CS pins during the transfer. + \param[in] data The 8 bit data byte to write to MOSI + \return The 8 bit byte simultaneously read from MISO + \sa bcm2835_spi_transfern() +*/ +extern void bcm2835_aux_spi_write(uint16_t data); + +/*! Transfers any number of bytes to the AUX SPI slave. + Asserts the CE2 pin during the transfer. + \param[in] buf Buffer of bytes to send. + \param[in] len Number of bytes in the tbuf buffer, and the number of bytes to send +*/ +extern void bcm2835_aux_spi_writenb(const char* buf, uint32_t len); + +/*! Transfers any number of bytes to and from the AUX SPI slave + using bcm2835_aux_spi_transfernb. + The returned data from the slave replaces the transmitted data in the buffer. + \param[in,out] buf Buffer of bytes to send. Received bytes will replace the contents + \param[in] len Number of bytes int eh buffer, and the number of bytes to send/received + \sa bcm2835_aux_spi_transfer() +*/ +extern void bcm2835_aux_spi_transfern(char* buf, uint32_t len); + +/*! Transfers any number of bytes to and from the AUX SPI slave. + Asserts the CE2 pin during the transfer. + Clocks the len 8 bit bytes out on MOSI, and simultaneously clocks in data from MISO. + The data read read from the slave is placed into rbuf. rbuf must be at least len bytes long + \param[in] tbuf Buffer of bytes to send. + \param[out] rbuf Received bytes will by put in this buffer + \param[in] len Number of bytes in the tbuf buffer, and the number of bytes to send/received +*/ +extern void bcm2835_aux_spi_transfernb(const char* tbuf, char* rbuf, uint32_t len); + +/*! @} */ + +/*! \defgroup i2c I2C access + These functions let you use I2C (The Broadcom Serial Control bus with the Philips + I2C bus/interface version 2.1 January 2000.) to interface with an external I2C device. + @{ +*/ + +/*! Start I2C operations. + Forces RPi I2C pins P1-03 (SDA) and P1-05 (SCL) + to alternate function ALT0, which enables those pins for I2C interface. + You should call bcm2835_i2c_end() when all I2C functions are complete to return the pins to + their default functions + \return 1 if successful, 0 otherwise (perhaps because you are not running as root) + \sa bcm2835_i2c_end() +*/ +extern int bcm2835_i2c_begin(void); + +/*! End I2C operations. + I2C pins P1-03 (SDA) and P1-05 (SCL) + are returned to their default INPUT behaviour. +*/ +extern void bcm2835_i2c_end(void); + +/*! Sets the I2C slave address. + \param[in] addr The I2C slave address. +*/ +extern void bcm2835_i2c_setSlaveAddress(uint8_t addr); + +/*! Sets the I2C clock divider and therefore the I2C clock speed. + \param[in] divider The desired I2C clock divider, one of BCM2835_I2C_CLOCK_DIVIDER_*, + see \ref bcm2835I2CClockDivider +*/ +extern void bcm2835_i2c_setClockDivider(uint16_t divider); + +/*! Sets the I2C clock divider by converting the baudrate parameter to + the equivalent I2C clock divider. ( see \sa bcm2835_i2c_setClockDivider) + For the I2C standard 100khz you would set baudrate to 100000 + The use of baudrate corresponds to its use in the I2C kernel device + driver. (Of course, bcm2835 has nothing to do with the kernel driver) +*/ +extern void bcm2835_i2c_set_baudrate(uint32_t baudrate); + +/*! Transfers any number of bytes to the currently selected I2C slave. + (as previously set by \sa bcm2835_i2c_setSlaveAddress) + \param[in] buf Buffer of bytes to send. + \param[in] len Number of bytes in the buf buffer, and the number of bytes to send. + \return reason see \ref bcm2835I2CReasonCodes +*/ +extern uint8_t bcm2835_i2c_write(const char* buf, uint32_t len); + +/*! Transfers any number of bytes from the currently selected I2C slave. + (as previously set by \sa bcm2835_i2c_setSlaveAddress) + \param[in] buf Buffer of bytes to receive. + \param[in] len Number of bytes in the buf buffer, and the number of bytes to received. + \return reason see \ref bcm2835I2CReasonCodes +*/ +extern uint8_t bcm2835_i2c_read(char* buf, uint32_t len); + +/*! Allows reading from I2C slaves that require a repeated start (without any prior stop) + to read after the required slave register has been set. For example, the popular + MPL3115A2 pressure and temperature sensor. Note that your device must support or + require this mode. If your device does not require this mode then the standard + combined: + \sa bcm2835_i2c_write + \sa bcm2835_i2c_read + are a better choice. + Will read from the slave previously set by \sa bcm2835_i2c_setSlaveAddress + \param[in] regaddr Buffer containing the slave register you wish to read from. + \param[in] buf Buffer of bytes to receive. + \param[in] len Number of bytes in the buf buffer, and the number of bytes to received. + \return reason see \ref bcm2835I2CReasonCodes +*/ +extern uint8_t bcm2835_i2c_read_register_rs(char* regaddr, char* buf, uint32_t len); + +/*! Allows sending an arbitrary number of bytes to I2C slaves before issuing a repeated + start (with no prior stop) and reading a response. + Necessary for devices that require such behavior, such as the MLX90620. + Will write to and read from the slave previously set by \sa bcm2835_i2c_setSlaveAddress + \param[in] cmds Buffer containing the bytes to send before the repeated start condition. + \param[in] cmds_len Number of bytes to send from cmds buffer + \param[in] buf Buffer of bytes to receive. + \param[in] buf_len Number of bytes to receive in the buf buffer. + \return reason see \ref bcm2835I2CReasonCodes +*/ +extern uint8_t bcm2835_i2c_write_read_rs(char* cmds, uint32_t cmds_len, char* buf, uint32_t buf_len); + +/*! @} */ + +/*! \defgroup st System Timer access + Allows access to and delays using the System Timer Counter. + @{ +*/ + +/*! Read the System Timer Counter register. + \return the value read from the System Timer Counter Lower 32 bits register +*/ +extern uint64_t bcm2835_st_read(void); + +/*! Delays for the specified number of microseconds with offset. + \param[in] offset_micros Offset in microseconds + \param[in] micros Delay in microseconds +*/ +extern void bcm2835_st_delay(uint64_t offset_micros, uint64_t micros); + +/*! @} */ + +/*! \defgroup pwm Pulse Width Modulation + Allows control of 2 independent PWM channels. A limited subset of GPIO pins + can be connected to one of these 2 channels, allowing PWM control of GPIO pins. + You have to set the desired pin into a particular Alt Fun to PWM output. See the PWM + documentation on the Main Page. + @{ +*/ + +/*! Sets the PWM clock divisor, + to control the basic PWM pulse widths. + \param[in] divisor Divides the basic 19.2MHz PWM clock. You can use one of the common + values BCM2835_PWM_CLOCK_DIVIDER_* in \ref bcm2835PWMClockDivider +*/ +extern void bcm2835_pwm_set_clock(uint32_t divisor); + +/*! Sets the mode of the given PWM channel, + allowing you to control the PWM mode and enable/disable that channel + \param[in] channel The PWM channel. 0 or 1. + \param[in] markspace Set true if you want Mark-Space mode. 0 for Balanced mode. + \param[in] enabled Set true to enable this channel and produce PWM pulses. +*/ +extern void bcm2835_pwm_set_mode(uint8_t channel, uint8_t markspace, uint8_t enabled); + +/*! Sets the maximum range of the PWM output. + The data value can vary between 0 and this range to control PWM output + \param[in] channel The PWM channel. 0 or 1. + \param[in] range The maximum value permitted for DATA. +*/ +extern void bcm2835_pwm_set_range(uint8_t channel, uint32_t range); + +/*! Sets the PWM pulse ratio to emit to DATA/RANGE, + where RANGE is set by bcm2835_pwm_set_range(). + \param[in] channel The PWM channel. 0 or 1. + \param[in] data Controls the PWM output ratio as a fraction of the range. + Can vary from 0 to RANGE. +*/ +extern void bcm2835_pwm_set_data(uint8_t channel, uint32_t data); + +/*! @} */ #ifdef __cplusplus } #endif diff --git a/utility/RPi/includes.h b/utility/RPi/includes.h index f2209af36..7d84a9480 100644 --- a/utility/RPi/includes.h +++ b/utility/RPi/includes.h @@ -1,10 +1,10 @@ - #ifndef __RF24_INCLUDES_H__ #define __RF24_INCLUDES_H__ - #define RF24_RPi - #include "RPi/bcm2835.h" - #include "RPi/RF24_arch_config.h" - #include "RPi/interrupt.h" - +#define RF24_RPi + +#include "RPi/bcm2835.h" +#include "RPi/RF24_arch_config.h" +#include "RPi/interrupt.h" + #endif diff --git a/utility/RPi/interrupt.c b/utility/RPi/interrupt.c index bec034a1e..6bd98ca97 100644 --- a/utility/RPi/interrupt.c +++ b/utility/RPi/interrupt.c @@ -24,203 +24,196 @@ see #define delay(x) bcm2835_delay(x) static pthread_mutex_t pinMutex = PTHREAD_MUTEX_INITIALIZER; -static volatile int pinPass = -1 ; +static volatile int pinPass = - 1; -pthread_t threadId [64]; +pthread_t threadId[64]; // sysFds: // Map a file descriptor from the /sys/class/gpio/gpioX/value -static int sysFds [64] = -{ - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -} ; +static int sysFds[64] = {- 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, + - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, + - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,}; // ISR Data -static void (*isrFunctions [64])(void) ; +static void (* isrFunctions[64])(void); -int waitForInterrupt (int pin, int mS) +int waitForInterrupt(int pin, int mS) { - int fd, x ; - uint8_t c ; - struct pollfd polls ; + int fd, x; + uint8_t c; + struct pollfd polls; - if ((fd = sysFds [pin]) == -1) - return -2 ; + if ((fd = sysFds[pin]) == - 1) { + return - 2; + } -// Setup poll structure + // Setup poll structure - polls.fd = fd ; - polls.events = POLLPRI ; // Urgent data! + polls.fd = fd; + polls.events = POLLPRI; // Urgent data! -// Wait for it ... - x = poll (&polls, 1, mS) ; + // Wait for it ... + x = poll(&polls, 1, mS); -// Do a dummy read to clear the interrupt -// A one character read appars to be enough. -// Followed by a seek to reset it. + // Do a dummy read to clear the interrupt + // A one character read appars to be enough. + // Followed by a seek to reset it. - (void)read (fd, &c, 1) ; - lseek (fd, 0, SEEK_SET) ; + (void) read(fd, &c, 1); + lseek(fd, 0, SEEK_SET); - return x ; + return x; } - -int piHiPri (const int pri) +int piHiPri(const int pri) { - struct sched_param sched ; + struct sched_param sched; - memset (&sched, 0, sizeof(sched)) ; + memset(&sched, 0, sizeof(sched)); - if (pri > sched_get_priority_max (SCHED_RR)) - sched.sched_priority = sched_get_priority_max (SCHED_RR) ; - else - sched.sched_priority = pri ; + if (pri > sched_get_priority_max(SCHED_RR)) { + sched.sched_priority = sched_get_priority_max(SCHED_RR); + } else { + sched.sched_priority = pri; + } - return sched_setscheduler (0, SCHED_RR, &sched) ; + return sched_setscheduler(0, SCHED_RR, &sched); } - -void *interruptHandler (void *arg) +void* interruptHandler(void* arg) { - int myPin ; + int myPin; - (void)piHiPri (55) ; // Only effective if we run as root + (void) piHiPri(55); // Only effective if we run as root - myPin = pinPass ; - pinPass = -1 ; + myPin = pinPass; + pinPass = - 1; - for (;;) - if (waitForInterrupt (myPin, -1) > 0){ - pthread_mutex_lock (&pinMutex) ; - isrFunctions [myPin] () ; - pthread_mutex_unlock (&pinMutex) ; - pthread_testcancel(); //Cancel at this point if we have an cancellation request. - } + for (;;) + if (waitForInterrupt(myPin, - 1) > 0) { + pthread_mutex_lock(&pinMutex); + isrFunctions[myPin](); + pthread_mutex_unlock(&pinMutex); + pthread_testcancel(); //Cancel at this point if we have an cancellation request. + } - return NULL ; + return NULL; } - -int attachInterrupt (int pin, int mode, void (*function)(void)) +int attachInterrupt(int pin, int mode, void (* function)(void)) { - const char *modeS ; - char fName [64] ; - char pinS [8] ; - pid_t pid ; - int count, i ; - char c ; - int bcmGpioPin ; - - bcmGpioPin = pin ; - - if (mode != INT_EDGE_SETUP) - { - /**/ if (mode == INT_EDGE_FALLING) - modeS = "falling" ; - else if (mode == INT_EDGE_RISING) - modeS = "rising" ; - else - modeS = "both" ; - - sprintf (pinS, "%d", bcmGpioPin) ; - - if ((pid = fork ()) < 0) // Fail - return printf("wiringPiISR: fork failed: %s\n", strerror (errno)) ; + const char* modeS; + char fName[64]; + char pinS[8]; + pid_t pid; + int count, i; + char c; + int bcmGpioPin; + + bcmGpioPin = pin; + + if (mode != INT_EDGE_SETUP) { + /**/ if (mode == INT_EDGE_FALLING) { + modeS = "falling"; + } else if (mode == INT_EDGE_RISING) { + modeS = "rising"; + } else { + modeS = "both"; + } + + sprintf(pinS, "%d", bcmGpioPin); + + if ((pid = fork()) < 0) { // Fail + return printf("wiringPiISR: fork failed: %s\n", strerror(errno)); + } + + if (pid == 0) // Child, exec + { + /**/ if (access("/usr/local/bin/gpio", X_OK) == 0) { + execl("/usr/local/bin/gpio", "gpio", "edge", pinS, modeS, (char*) NULL); + return printf("wiringPiISR: execl failed: %s\n", strerror(errno)); + } else if (access("/usr/bin/gpio", X_OK) == 0) { + execl("/usr/bin/gpio", "gpio", "edge", pinS, modeS, (char*) NULL); + return printf("wiringPiISR: execl failed: %s\n", strerror(errno)); + } else { + return printf("wiringPiISR: Can't find gpio program\n"); + } + } else { // Parent, wait + wait(NULL); + } + } - if (pid == 0) // Child, exec - { - /**/ if (access ("/usr/local/bin/gpio", X_OK) == 0) - { - execl ("/usr/local/bin/gpio", "gpio", "edge", pinS, modeS, (char *)NULL) ; - return printf ("wiringPiISR: execl failed: %s\n", strerror (errno)) ; - } - else if (access ("/usr/bin/gpio", X_OK) == 0) - { - execl ("/usr/bin/gpio", "gpio", "edge", pinS, modeS, (char *)NULL) ; - return printf ("wiringPiISR: execl failed: %s\n", strerror (errno)) ; - } - else - return printf ("wiringPiISR: Can't find gpio program\n") ; + if (sysFds[bcmGpioPin] == - 1) { + sprintf(fName, "/sys/class/gpio/gpio%d/value", bcmGpioPin); + if ((sysFds[bcmGpioPin] = open(fName, O_RDWR)) < 0) { + return printf("wiringPiISR: unable to open %s: %s\n", fName, strerror(errno)); + } } - else // Parent, wait - wait (NULL) ; - } - - if (sysFds [bcmGpioPin] == -1) - { - sprintf (fName, "/sys/class/gpio/gpio%d/value",bcmGpioPin); - if ((sysFds [bcmGpioPin] = open (fName, O_RDWR)) < 0) - return printf ("wiringPiISR: unable to open %s: %s\n", fName, strerror (errno)) ; - } - - ioctl (sysFds [bcmGpioPin], FIONREAD, &count) ; - for (i = 0 ; i < count ; ++i) - read (sysFds [bcmGpioPin], &c, 1) ; - - isrFunctions [pin] = function ; - - pthread_mutex_lock (&pinMutex) ; - pinPass = pin ; - pthread_create (&threadId[bcmGpioPin], NULL, interruptHandler, NULL) ; - while (pinPass != -1) - delay (1) ; - pthread_mutex_unlock (&pinMutex) ; - - return 0 ; + + ioctl(sysFds[bcmGpioPin], FIONREAD, &count); + for (i = 0; i < count; ++ i) + read(sysFds[bcmGpioPin], &c, 1); + + isrFunctions[pin] = function; + + pthread_mutex_lock(&pinMutex); + pinPass = pin; + pthread_create(&threadId[bcmGpioPin], NULL, interruptHandler, NULL); + while (pinPass != - 1) + delay (1); + pthread_mutex_unlock(&pinMutex); + + return 0; } -int detachInterrupt (int pin) +int detachInterrupt(int pin) { - char pinS [8]; - const char *modeS = "none"; - pid_t pid ; - - if (pthread_cancel(threadId[pin]) != 0) //Cancel the thread - { - return 0; - } - - if (close(sysFds[pin]) != 0) //Close filehandle - { - return 0; - } - - /* Set wiringPi to 'none' interrupt mode */ - - sprintf (pinS, "%d", pin) ; - - if ((pid = fork ()) < 0) // Fail - return printf("wiringPiISR: fork failed: %s\n", strerror (errno)) ; + char pinS[8]; + const char* modeS = "none"; + pid_t pid; + + if (pthread_cancel(threadId[pin]) != 0) //Cancel the thread + { + return 0; + } + + if (close(sysFds[pin]) != 0) //Close filehandle + { + return 0; + } + + /* Set wiringPi to 'none' interrupt mode */ + + sprintf(pinS, "%d", pin); + + if ((pid = fork()) < 0) { // Fail + return printf("wiringPiISR: fork failed: %s\n", strerror(errno)); + } if (pid == 0) // Child, exec { - /**/ if (access ("/usr/local/bin/gpio", X_OK) == 0) - { - execl ("/usr/local/bin/gpio", "gpio", "edge", pinS, modeS, (char *)NULL) ; - return printf ("wiringPiISR: execl failed: %s\n", strerror (errno)) ; - } - else if (access ("/usr/bin/gpio", X_OK) == 0) - { - execl ("/usr/bin/gpio", "gpio", "edge", pinS, modeS, (char *)NULL) ; - return printf ("wiringPiISR: execl failed: %s\n", strerror (errno)) ; - } - else - return printf ("wiringPiISR: Can't find gpio program\n") ; + /**/ if (access("/usr/local/bin/gpio", X_OK) == 0) { + execl("/usr/local/bin/gpio", "gpio", "edge", pinS, modeS, (char*) NULL); + return printf("wiringPiISR: execl failed: %s\n", strerror(errno)); + } else if (access("/usr/bin/gpio", X_OK) == 0) { + execl("/usr/bin/gpio", "gpio", "edge", pinS, modeS, (char*) NULL); + return printf("wiringPiISR: execl failed: %s\n", strerror(errno)); + } else { + return printf("wiringPiISR: Can't find gpio program\n"); + } + } else { // Parent, wait + wait(NULL); } - else // Parent, wait - wait (NULL) ; - - return 1; + + return 1; } -void rfNoInterrupts(){ - pthread_mutex_lock (&pinMutex) ; +void rfNoInterrupts() +{ + pthread_mutex_lock(&pinMutex); } -void rfInterrupts(){ - pthread_mutex_unlock (&pinMutex) ; +void rfInterrupts() +{ + pthread_mutex_unlock(&pinMutex); } diff --git a/utility/RPi/interrupt.h b/utility/RPi/interrupt.h index fe6fa4f6b..e76d34e7d 100644 --- a/utility/RPi/interrupt.h +++ b/utility/RPi/interrupt.h @@ -21,11 +21,12 @@ see * fires. ********************************************************************************* */ -void *interruptHandler (void *arg); +void* interruptHandler(void* arg); #ifdef __cplusplus extern "C" { #endif + /* * waitForInterrupt: * Pi Specific. @@ -35,14 +36,14 @@ extern "C" { * way for a bit more efficiency. ********************************************************************************* */ -extern int waitForInterrupt (int pin, int mS); +extern int waitForInterrupt(int pin, int mS); /* * piHiPri: * Attempt to set a high priority schedulling for the running program ********************************************************************************* */ -extern int piHiPri (const int pri); +extern int piHiPri(const int pri); /* * attachInterrupt (Original: wiringPiISR): @@ -51,7 +52,7 @@ extern int piHiPri (const int pri); * back to the user supplied function. ********************************************************************************* */ -extern int attachInterrupt (int pin, int mode, void (*function)(void)); +extern int attachInterrupt(int pin, int mode, void (* function)(void)); /* * detachInterrupt: @@ -60,10 +61,12 @@ extern int attachInterrupt (int pin, int mode, void (*function)(void)); * setting wiringPi back to 'none' mode. ********************************************************************************* */ -extern int detachInterrupt (int pin); +extern int detachInterrupt(int pin); extern void rfNoInterrupts(); + extern void rfInterrupts(); + #ifdef __cplusplus } #endif \ No newline at end of file diff --git a/utility/RPi/spi.cpp b/utility/RPi/spi.cpp index b75d5f597..47f4f8ea1 100644 --- a/utility/RPi/spi.cpp +++ b/utility/RPi/spi.cpp @@ -5,51 +5,60 @@ static pthread_mutex_t spiMutex = PTHREAD_MUTEX_INITIALIZER; bool bcmIsInitialized = false; -SPI::SPI() { +SPI::SPI() +{ } -void SPI::begin( int busNo ) { - if(!bcmIsInitialized){ - if (!bcm2835_init()){ - return; - } +void SPI::begin(int busNo) +{ + if (! bcmIsInitialized) { + if (! bcm2835_init()) { + return; + } } bcmIsInitialized = true; bcm2835_spi_begin(); } -void SPI::beginTransaction(SPISettings settings){ - if (geteuid() != 0){ - throw -1; - } - pthread_mutex_lock (&spiMutex); - setBitOrder(settings.border); - setDataMode(settings.dmode); - setClockDivider(settings.clck); +void SPI::beginTransaction(SPISettings settings) +{ + if (geteuid() != 0) { + throw - 1; + } + pthread_mutex_lock(&spiMutex); + setBitOrder(settings.border); + setDataMode(settings.dmode); + setClockDivider(settings.clck); } -void SPI::endTransaction() { - pthread_mutex_unlock (&spiMutex); +void SPI::endTransaction() +{ + pthread_mutex_unlock(&spiMutex); } -void SPI::setBitOrder(uint8_t bit_order) { - bcm2835_spi_setBitOrder(bit_order); +void SPI::setBitOrder(uint8_t bit_order) +{ + bcm2835_spi_setBitOrder(bit_order); } -void SPI::setDataMode(uint8_t data_mode) { - bcm2835_spi_setDataMode(data_mode); +void SPI::setDataMode(uint8_t data_mode) +{ + bcm2835_spi_setDataMode(data_mode); } -void SPI::setClockDivider(uint16_t spi_speed) { - bcm2835_spi_setClockDivider(spi_speed); +void SPI::setClockDivider(uint16_t spi_speed) +{ + bcm2835_spi_setClockDivider(spi_speed); } -void SPI::chipSelect(int csn_pin){ - bcm2835_spi_chipSelect(csn_pin); - delayMicroseconds(5); +void SPI::chipSelect(int csn_pin) +{ + bcm2835_spi_chipSelect(csn_pin); + delayMicroseconds(5); } -SPI::~SPI() { +SPI::~SPI() +{ } \ No newline at end of file diff --git a/utility/RPi/spi.h b/utility/RPi/spi.h index 0f559a353..4c45bdd20 100644 --- a/utility/RPi/spi.h +++ b/utility/RPi/spi.h @@ -18,60 +18,75 @@ #define MSBFIRST BCM2835_SPI_BIT_ORDER_MSBFIRST #define SPI_MODE0 BCM2835_SPI_MODE0 #define RF24_SPI_SPEED BCM2835_SPI_SPEED_8MHZ - + class SPISettings { public: - SPISettings(uint32_t clock, uint8_t bitOrder, uint8_t dataMode) { - init(clock,bitOrder,dataMode); - } - SPISettings() { init(RF24_SPI_SPEED, MSBFIRST, SPI_MODE0); } + SPISettings(uint32_t clock, uint8_t bitOrder, uint8_t dataMode) + { + init(clock, bitOrder, dataMode); + } + + SPISettings() + { + init(RF24_SPI_SPEED, MSBFIRST, SPI_MODE0); + } uint32_t clck; uint8_t border; uint8_t dmode; private: - void init(uint32_t clock, uint8_t bitOrder, uint8_t dataMode) { - clck = clock; - border = bitOrder; - dmode = dataMode; - } - friend class SPIClass; -}; + void init(uint32_t clock, uint8_t bitOrder, uint8_t dataMode) + { + clck = clock; + border = bitOrder; + dmode = dataMode; + } + friend class SPIClass; +}; class SPI { public: - SPI(); - virtual ~SPI(); - - inline static uint8_t transfer(uint8_t _data); - inline static void transfernb(char* tbuf, char* rbuf, uint32_t len); - inline static void transfern(char* buf, uint32_t len); - - static void begin(int busNo); - static void end(); - - static void setBitOrder(uint8_t bit_order); - static void setDataMode(uint8_t data_mode); - static void setClockDivider(uint16_t spi_speed); - static void chipSelect(int csn_pin); - - static void beginTransaction(SPISettings settings); - static void endTransaction(); - - -}; + SPI(); + + virtual ~SPI(); + + inline static uint8_t transfer(uint8_t _data); + + inline static void transfernb(char* tbuf, char* rbuf, uint32_t len); + + inline static void transfern(char* buf, uint32_t len); + + static void begin(int busNo); + + static void end(); + static void setBitOrder(uint8_t bit_order); -uint8_t SPI::transfer(uint8_t _data) { + static void setDataMode(uint8_t data_mode); + + static void setClockDivider(uint16_t spi_speed); + + static void chipSelect(int csn_pin); + + static void beginTransaction(SPISettings settings); + + static void endTransaction(); + + +}; + +uint8_t SPI::transfer(uint8_t _data) +{ uint8_t data = bcm2835_spi_transfer(_data); return data; } -void SPI::transfernb(char* tbuf, char* rbuf, uint32_t len){ - bcm2835_spi_transfernb( tbuf, rbuf, len); +void SPI::transfernb(char* tbuf, char* rbuf, uint32_t len) +{ + bcm2835_spi_transfernb(tbuf, rbuf, len); } void SPI::transfern(char* buf, uint32_t len) diff --git a/utility/SPIDEV/RF24_arch_config.h b/utility/SPIDEV/RF24_arch_config.h index 424f9a1ce..1ee02fc71 100644 --- a/utility/SPIDEV/RF24_arch_config.h +++ b/utility/SPIDEV/RF24_arch_config.h @@ -1,4 +1,3 @@ - /* Copyright (C) 2011 J. Coliz @@ -29,19 +28,19 @@ //#undef SERIAL_DEBUG #ifdef SERIAL_DEBUG -#define IF_SERIAL_DEBUG(x) ({x;}) + #define IF_SERIAL_DEBUG(x) ({x;}) #else -#define IF_SERIAL_DEBUG(x) + #define IF_SERIAL_DEBUG(x) #endif // Avoid spurious warnings #if 1 -#if ! defined( NATIVE ) && defined( ARDUINO ) -#undef PROGMEM -#define PROGMEM __attribute__(( section(".progmem.data") )) -#undef PSTR -#define PSTR(s) (__extension__({static const char __c[] PROGMEM = (s); &__c[0];})) -#endif + #if ! defined( NATIVE ) && defined( ARDUINO ) + #undef PROGMEM + #define PROGMEM __attribute__(( section(".progmem.data") )) + #undef PSTR + #define PSTR(s) (__extension__({static const char __c[] PROGMEM = (s); &__c[0];})) + #endif #endif typedef uint16_t prog_uint16_t; diff --git a/utility/SPIDEV/compatibility.c b/utility/SPIDEV/compatibility.c index ec2eb0292..fe0a0c88e 100644 --- a/utility/SPIDEV/compatibility.c +++ b/utility/SPIDEV/compatibility.c @@ -1,7 +1,5 @@ - #include "compatibility.h" - static uint32_t mtime, seconds, useconds; //static struct timeval start, end; struct timespec start, end; @@ -13,40 +11,40 @@ struct timespec start, end; */ void __msleep(int milisec) { - struct timespec req;// = {0}; - req.tv_sec = (time_t) milisec / 1000; - req.tv_nsec = (milisec % 1000 ) * 1000000L; - //nanosleep(&req, (struct timespec *)NULL); - clock_nanosleep(CLOCK_REALTIME, 0, &req, NULL); + struct timespec req;// = {0}; + req.tv_sec = (time_t) milisec / 1000; + req.tv_nsec = (milisec % 1000) * 1000000L; + //nanosleep(&req, (struct timespec *)NULL); + clock_nanosleep(CLOCK_REALTIME, 0, &req, NULL); } void __usleep(int microsec) { - struct timespec req;// = {0}; - req.tv_sec = (time_t) microsec/ 1000000; - req.tv_nsec = (microsec / 1000000) * 1000; - //nanosleep(&req, (struct timespec *)NULL); - clock_nanosleep(CLOCK_REALTIME, 0, &req, NULL); + struct timespec req;// = {0}; + req.tv_sec = (time_t) microsec / 1000000; + req.tv_nsec = (microsec / 1000000) * 1000; + //nanosleep(&req, (struct timespec *)NULL); + clock_nanosleep(CLOCK_REALTIME, 0, &req, NULL); } /** * This function is added in order to simulate arduino millis() function */ - + void __start_timer() { - //gettimeofday(&start, NULL); - clock_gettime(CLOCK_MONOTONIC_RAW, &start); + //gettimeofday(&start, NULL); + clock_gettime(CLOCK_MONOTONIC_RAW, &start); } uint32_t __millis() { - //gettimeofday(&end, NULL); - clock_gettime(CLOCK_MONOTONIC_RAW,&end); - seconds = end.tv_sec - start.tv_sec; - useconds = (end.tv_nsec - start.tv_nsec)/1000; + //gettimeofday(&end, NULL); + clock_gettime(CLOCK_MONOTONIC_RAW, &end); + seconds = end.tv_sec - start.tv_sec; + useconds = (end.tv_nsec - start.tv_nsec) / 1000; - mtime = ((seconds) * 1000 + useconds/1000.0) + 0.5; - return mtime; + mtime = ((seconds) * 1000 + useconds / 1000.0) + 0.5; + return mtime; } diff --git a/utility/SPIDEV/compatibility.h b/utility/SPIDEV/compatibility.h index 74446ec36..817573c1d 100644 --- a/utility/SPIDEV/compatibility.h +++ b/utility/SPIDEV/compatibility.h @@ -7,9 +7,9 @@ */ #ifndef COMPATIBLITY_H -#define COMPATIBLITY_H +#define COMPATIBLITY_H -#ifdef __cplusplus +#ifdef __cplusplus extern "C" { #endif @@ -19,13 +19,16 @@ extern "C" { #include void __msleep(int milisec); + void __usleep(int milisec); + void __start_timer(); + uint32_t __millis(); -#ifdef __cplusplus +#ifdef __cplusplus } #endif -#endif /* COMPATIBLITY_H */ +#endif /* COMPATIBLITY_H */ diff --git a/utility/SPIDEV/gpio.cpp b/utility/SPIDEV/gpio.cpp index 3cbdf738a..f9b244a9e 100644 --- a/utility/SPIDEV/gpio.cpp +++ b/utility/SPIDEV/gpio.cpp @@ -17,129 +17,151 @@ #include #include -std::map GPIO::cache; +std::map GPIO::cache; -GPIO::GPIO() { +GPIO::GPIO() +{ } -GPIO::~GPIO() { +GPIO::~GPIO() +{ } void GPIO::open(int port, int DDR) { - FILE *f; - f = fopen("/sys/class/gpio/export", "w"); - if(f==NULL) throw GPIOException("can't export GPIO pin .check access rights"); - fprintf(f, "%d\n", port); - fclose(f); + FILE* f; + f = fopen("/sys/class/gpio/export", "w"); + if (f == NULL) { + throw GPIOException("can't export GPIO pin .check access rights"); + } + fprintf(f, "%d\n", port); + fclose(f); - int counter = 0; - char file[128]; - sprintf(file, "/sys/class/gpio/gpio%d/direction", port); + int counter = 0; + char file[128]; + sprintf(file, "/sys/class/gpio/gpio%d/direction", port); - while( ( f = fopen(file,"w")) == NULL ){ //Wait 10 seconds for the file to be accessible if not open on first attempt + while ((f = fopen(file, "w")) == NULL) { //Wait 10 seconds for the file to be accessible if not open on first attempt sleep(1); - counter++; - if(counter > 10){ - throw GPIOException("can't access /sys/class/gpio/gpio%d/direction GPIO pin. check access rights"); - /*perror("Could not open /sys/class/gpio/gpio%d/direction"); - exit(0); */ + counter ++; + if (counter > 10) { + throw GPIOException("can't access /sys/class/gpio/gpio%d/direction GPIO pin. check access rights"); + /*perror("Could not open /sys/class/gpio/gpio%d/direction"); + exit(0); */ } } - int l=(DDR==0) ? fprintf(f, "in\n") : fprintf(f, "out\n"); - if(!(l==3 || l==4)) { - fclose(f); - throw GPIOException("can't set direction on GPIO pin. check access rights"); - } - /* - if (DDR == 0) + int l = (DDR == 0) ? fprintf(f, "in\n") : fprintf(f, "out\n"); + if (! (l == 3 || l == 4)) { + fclose(f); + throw GPIOException("can't set direction on GPIO pin. check access rights"); + } + /* + if (DDR == 0) fprintf(f, "in\n"); - else printf(f, "out\n"); + else printf(f, "out\n"); */ - fclose(f); - - // Caches the GPIO descriptor; - sprintf(file, "/sys/class/gpio/gpio%d/value", port); - int flags= (DDR==0) ? O_RDONLY : O_WRONLY; - int fd=::open(file,flags); - if(fd<0) { - throw GPIOException("Can't open the GPIO"); - } else { - cache[port]=fd; // cache the fd; - lseek(fd,SEEK_SET,0); - } + fclose(f); + + // Caches the GPIO descriptor; + sprintf(file, "/sys/class/gpio/gpio%d/value", port); + int flags = (DDR == 0) ? O_RDONLY : O_WRONLY; + int fd = ::open(file, flags); + if (fd < 0) { + throw GPIOException("Can't open the GPIO"); + } else { + cache[port] = fd; // cache the fd; + lseek(fd, SEEK_SET, 0); + } } void GPIO::close(int port) { - std::map::iterator i; - i=cache.find(port); - if(i!=cache.end()){ - close(i->second); // close the cached fd - cache.erase(i); // Delete cache entry - } - // Do unexport - FILE *f; - f = fopen("/sys/class/gpio/unexport", "w"); - if(f!=NULL) { - fprintf(f, "%d\n", port); - fclose(f); - } + std::map::iterator i; + i = cache.find(port); + if (i != cache.end()) { + close(i->second); // close the cached fd + cache.erase(i); // Delete cache entry + } + // Do unexport + FILE* f; + f = fopen("/sys/class/gpio/unexport", "w"); + if (f != NULL) { + fprintf(f, "%d\n", port); + fclose(f); + } } int GPIO::read(int port) { - std::map::iterator i; - int fd; - i=cache.find(port); - if(i==cache.end()){ // Fallback to open the gpio - GPIO::open(port,GPIO::DIRECTION_IN); - i=cache.find(port); - if(i==cache.end()) throw GPIOException("can't access to GPIO"); - else fd=i->second; - } else fd=i->second; - - char c; - if(lseek(fd,0,SEEK_SET)==0 && ::read(fd,&c,1)==1){ - return (c=='0') ? 0 : 1; - } else throw GPIOException("can't access to GPIO"); - - /*FILE *f; - - char file[128]; - sprintf(file, "/sys/class/gpio/gpio%d/value", port); - f = fopen(file, "r"); - - int i; - fscanf(f, "%d", &i); - fclose(f); - return i; + std::map::iterator i; + int fd; + i = cache.find(port); + if (i == cache.end()) { // Fallback to open the gpio + GPIO::open(port, GPIO::DIRECTION_IN); + i = cache.find(port); + if (i == cache.end()) { + throw GPIOException("can't access to GPIO"); + } else { + fd = i->second; + } + } else { + fd = i->second; + } + + char c; + if (lseek(fd, 0, SEEK_SET) == 0 && ::read(fd, &c, 1) == 1) { + return (c == '0') ? 0 : 1; + } else { + throw GPIOException("can't access to GPIO"); + } + + /*FILE *f; + + char file[128]; + sprintf(file, "/sys/class/gpio/gpio%d/value", port); + f = fopen(file, "r"); + + int i; + fscanf(f, "%d", &i); + fclose(f); + return i; */ } -void GPIO::write(int port, int value){ - std::map::iterator i; - int fd; - i=cache.find(port); - if(i==cache.end()){ // Fallback to open the gpio - GPIO::open(port,GPIO::DIRECTION_OUT); - i=cache.find(port); - if(i==cache.end()) throw GPIOException("can't access to GPIO"); - else fd=i->second; - } else fd=i->second; - - if(lseek(fd,0,SEEK_SET)!=0) throw GPIOException("can't access to GPIO"); - int l=(value==0) ? ::write(fd,"0\n",2) : ::write(fd,"1\n",2); - if(l!=2) throw GPIOException("can't access to GPIO"); - - /*FILE *f; - - char file[128]; - sprintf(file, "/sys/class/gpio/gpio%d/value", port); - f = fopen(file, "w"); - - if (value == 0) fprintf(f, "0\n"); - else fprintf(f, "1\n"); - - fclose(f);*/ + +void GPIO::write(int port, int value) +{ + std::map::iterator i; + int fd; + i = cache.find(port); + if (i == cache.end()) { // Fallback to open the gpio + GPIO::open(port, GPIO::DIRECTION_OUT); + i = cache.find(port); + if (i == cache.end()) { + throw GPIOException("can't access to GPIO"); + } else { + fd = i->second; + } + } else { + fd = i->second; + } + + if (lseek(fd, 0, SEEK_SET) != 0) { + throw GPIOException("can't access to GPIO"); + } + int l = (value == 0) ? ::write(fd, "0\n", 2) : ::write(fd, "1\n", 2); + if (l != 2) { + throw GPIOException("can't access to GPIO"); + } + + /*FILE *f; + + char file[128]; + sprintf(file, "/sys/class/gpio/gpio%d/value", port); + f = fopen(file, "w"); + + if (value == 0) fprintf(f, "0\n"); + else fprintf(f, "1\n"); + + fclose(f);*/ } diff --git a/utility/SPIDEV/gpio.h b/utility/SPIDEV/gpio.h index e500e1fe5..0b986d819 100644 --- a/utility/SPIDEV/gpio.h +++ b/utility/SPIDEV/gpio.h @@ -10,7 +10,7 @@ */ #ifndef H -#define H +#define H #include #include @@ -18,8 +18,11 @@ /** Specific excpetion for SPI errors */ class GPIOException : public std::runtime_error { - public: - explicit GPIOException(const std::string& msg) : std::runtime_error(msg) { } +public: + explicit GPIOException(const std::string& msg) + :std::runtime_error(msg) + { + } }; /** @@ -43,47 +46,50 @@ typedef int GPIOfdCache_t; class GPIO { public: - /* Constants */ - static const int DIRECTION_OUT = 1; - static const int DIRECTION_IN = 0; + /* Constants */ + static const int DIRECTION_OUT = 1; + static const int DIRECTION_IN = 0; - static const int OUTPUT_HIGH = 1; - static const int OUTPUT_LOW = 0; + static const int OUTPUT_HIGH = 1; + static const int OUTPUT_LOW = 0; - GPIO(); + GPIO(); - /** - * Similar to Arduino pinMode(pin,mode); + /** + * Similar to Arduino pinMode(pin,mode); * @param port * @param DDR */ - static void open(int port, int DDR); - /** - * + static void open(int port, int DDR); + + /** + * * @param port */ - static void close(int port); - /** - * Similar to Arduino digitalRead(pin); + static void close(int port); + + /** + * Similar to Arduino digitalRead(pin); * @param port * @param value */ - static int read(int port); - /** - * Similar to Arduino digitalWrite(pin,state); - * @param port - * @param value - */ - static void write(int port,int value); + static int read(int port); + + /** + * Similar to Arduino digitalWrite(pin,state); + * @param port + * @param value + */ + static void write(int port, int value); - virtual ~GPIO(); + virtual ~GPIO(); private: - /* fd cache */ - static std::map cache; + /* fd cache */ + static std::map cache; }; /** * \endcond */ /*@}*/ -#endif /* H */ +#endif /* H */ diff --git a/utility/SPIDEV/includes.h b/utility/SPIDEV/includes.h index bc8c7b837..bc9008c28 100644 --- a/utility/SPIDEV/includes.h +++ b/utility/SPIDEV/includes.h @@ -1,8 +1,9 @@ - #ifndef __RF24_INCLUDES_H__ #define __RF24_INCLUDES_H__ #define RF24_SPIDEV - #include "SPIDEV/RF24_arch_config.h" - #include "SPIDEV/interrupt.h" + +#include "SPIDEV/RF24_arch_config.h" +#include "SPIDEV/interrupt.h" + #endif diff --git a/utility/SPIDEV/interrupt.c b/utility/SPIDEV/interrupt.c index 0344b3649..19975ef45 100644 --- a/utility/SPIDEV/interrupt.c +++ b/utility/SPIDEV/interrupt.c @@ -23,204 +23,197 @@ see //#define delay(x) bcm2835_delay(x) -static pthread_mutex_t pinMutex = PTHREAD_MUTEX_INITIALIZER ; -static volatile int pinPass = -1 ; +static pthread_mutex_t pinMutex = PTHREAD_MUTEX_INITIALIZER; +static volatile int pinPass = - 1; -pthread_t threadId [64]; +pthread_t threadId[64]; // sysFds: // Map a file descriptor from the /sys/class/gpio/gpioX/value -static int sysFds [64] = -{ - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -} ; +static int sysFds[64] = {- 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, + - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, + - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,}; // ISR Data -static void (*isrFunctions [64])(void) ; +static void (* isrFunctions[64])(void); -int waitForInterrupt (int pin, int mS) +int waitForInterrupt(int pin, int mS) { - int fd, x ; - uint8_t c ; - struct pollfd polls ; + int fd, x; + uint8_t c; + struct pollfd polls; - if ((fd = sysFds [pin]) == -1) - return -2 ; + if ((fd = sysFds[pin]) == - 1) { + return - 2; + } -// Setup poll structure + // Setup poll structure - polls.fd = fd ; - polls.events = POLLPRI ; // Urgent data! + polls.fd = fd; + polls.events = POLLPRI; // Urgent data! -// Wait for it ... - x = poll (&polls, 1, mS) ; + // Wait for it ... + x = poll(&polls, 1, mS); -// Do a dummy read to clear the interrupt -// A one character read appars to be enough. -// Followed by a seek to reset it. + // Do a dummy read to clear the interrupt + // A one character read appars to be enough. + // Followed by a seek to reset it. - (void)read (fd, &c, 1) ; - lseek (fd, 0, SEEK_SET) ; + (void) read(fd, &c, 1); + lseek(fd, 0, SEEK_SET); - return x ; + return x; } - -int piHiPri (const int pri) +int piHiPri(const int pri) { - struct sched_param sched ; + struct sched_param sched; - memset (&sched, 0, sizeof(sched)) ; + memset(&sched, 0, sizeof(sched)); - if (pri > sched_get_priority_max (SCHED_RR)) - sched.sched_priority = sched_get_priority_max (SCHED_RR) ; - else - sched.sched_priority = pri ; + if (pri > sched_get_priority_max(SCHED_RR)) { + sched.sched_priority = sched_get_priority_max(SCHED_RR); + } else { + sched.sched_priority = pri; + } - return sched_setscheduler (0, SCHED_RR, &sched) ; + return sched_setscheduler(0, SCHED_RR, &sched); } - -void *interruptHandler (void *arg) +void* interruptHandler(void* arg) { - int myPin ; + int myPin; - (void)piHiPri (55) ; // Only effective if we run as root + (void) piHiPri(55); // Only effective if we run as root - myPin = pinPass ; - pinPass = -1 ; + myPin = pinPass; + pinPass = - 1; - for (;;) - if (waitForInterrupt (myPin, -1) > 0){ - pthread_mutex_lock (&pinMutex) ; - isrFunctions [myPin] () ; - pthread_mutex_unlock (&pinMutex) ; - pthread_testcancel(); //Cancel at this point if we have an cancellation request. - } + for (;;) + if (waitForInterrupt(myPin, - 1) > 0) { + pthread_mutex_lock(&pinMutex); + isrFunctions[myPin](); + pthread_mutex_unlock(&pinMutex); + pthread_testcancel(); //Cancel at this point if we have an cancellation request. + } - return NULL ; + return NULL; } - -int attachInterrupt (int pin, int mode, void (*function)(void)) +int attachInterrupt(int pin, int mode, void (* function)(void)) { - const char *modeS ; - char fName [64] ; - char pinS [8] ; - pid_t pid ; - int count, i ; - char c ; - int bcmGpioPin ; - - bcmGpioPin = pin ; - - if (mode != INT_EDGE_SETUP) - { - /**/ if (mode == INT_EDGE_FALLING) - modeS = "falling" ; - else if (mode == INT_EDGE_RISING) - modeS = "rising" ; - else - modeS = "both" ; - - sprintf (pinS, "%d", bcmGpioPin) ; - - if ((pid = fork ()) < 0) // Fail - return printf("wiringPiISR: fork failed: %s\n", strerror (errno)) ; + const char* modeS; + char fName[64]; + char pinS[8]; + pid_t pid; + int count, i; + char c; + int bcmGpioPin; + + bcmGpioPin = pin; + + if (mode != INT_EDGE_SETUP) { + /**/ if (mode == INT_EDGE_FALLING) { + modeS = "falling"; + } else if (mode == INT_EDGE_RISING) { + modeS = "rising"; + } else { + modeS = "both"; + } + + sprintf(pinS, "%d", bcmGpioPin); + + if ((pid = fork()) < 0) { // Fail + return printf("wiringPiISR: fork failed: %s\n", strerror(errno)); + } + + if (pid == 0) // Child, exec + { + /**/ if (access("/usr/local/bin/gpio", X_OK) == 0) { + execl("/usr/local/bin/gpio", "gpio", "edge", pinS, modeS, (char*) NULL); + return printf("wiringPiISR: execl failed: %s\n", strerror(errno)); + } else if (access("/usr/bin/gpio", X_OK) == 0) { + execl("/usr/bin/gpio", "gpio", "edge", pinS, modeS, (char*) NULL); + return printf("wiringPiISR: execl failed: %s\n", strerror(errno)); + } else { + return printf("wiringPiISR: Can't find gpio program\n"); + } + } else { // Parent, wait + wait(NULL); + } + } - if (pid == 0) // Child, exec - { - /**/ if (access ("/usr/local/bin/gpio", X_OK) == 0) - { - execl ("/usr/local/bin/gpio", "gpio", "edge", pinS, modeS, (char *)NULL) ; - return printf ("wiringPiISR: execl failed: %s\n", strerror (errno)) ; - } - else if (access ("/usr/bin/gpio", X_OK) == 0) - { - execl ("/usr/bin/gpio", "gpio", "edge", pinS, modeS, (char *)NULL) ; - return printf ("wiringPiISR: execl failed: %s\n", strerror (errno)) ; - } - else - return printf ("wiringPiISR: Can't find gpio program\n") ; + if (sysFds[bcmGpioPin] == - 1) { + sprintf(fName, "/sys/class/gpio/gpio%d/value", bcmGpioPin); + if ((sysFds[bcmGpioPin] = open(fName, O_RDWR)) < 0) { + return printf("wiringPiISR: unable to open %s: %s\n", fName, strerror(errno)); + } } - else // Parent, wait - wait (NULL) ; - } - - if (sysFds [bcmGpioPin] == -1) - { - sprintf (fName, "/sys/class/gpio/gpio%d/value",bcmGpioPin); - if ((sysFds [bcmGpioPin] = open (fName, O_RDWR)) < 0) - return printf ("wiringPiISR: unable to open %s: %s\n", fName, strerror (errno)) ; - } - - ioctl (sysFds [bcmGpioPin], FIONREAD, &count) ; - for (i = 0 ; i < count ; ++i) - read (sysFds [bcmGpioPin], &c, 1) ; - - isrFunctions [pin] = function ; - - pthread_mutex_lock (&pinMutex) ; - pinPass = pin ; - pthread_create (&threadId[bcmGpioPin], NULL, interruptHandler, NULL) ; - while (pinPass != -1) - delay (1) ; - pthread_mutex_unlock (&pinMutex) ; - - return 0 ; + + ioctl(sysFds[bcmGpioPin], FIONREAD, &count); + for (i = 0; i < count; ++ i) + read(sysFds[bcmGpioPin], &c, 1); + + isrFunctions[pin] = function; + + pthread_mutex_lock(&pinMutex); + pinPass = pin; + pthread_create(&threadId[bcmGpioPin], NULL, interruptHandler, NULL); + while (pinPass != - 1) + delay (1); + pthread_mutex_unlock(&pinMutex); + + return 0; } -int detachInterrupt (int pin) +int detachInterrupt(int pin) { - char pinS [8]; - const char *modeS = "none"; - pid_t pid ; - - if (!pthread_cancel(threadId[pin])) //Cancel the thread - { - return 0; - } - - if (!close(sysFds[pin])) //Close filehandle - { - return 0; - } - - /* Set wiringPi to 'none' interrupt mode */ - - sprintf (pinS, "%d", pin) ; - - if ((pid = fork ()) < 0) // Fail - return printf("wiringPiISR: fork failed: %s\n", strerror (errno)) ; + char pinS[8]; + const char* modeS = "none"; + pid_t pid; + + if (! pthread_cancel(threadId[pin])) //Cancel the thread + { + return 0; + } + + if (! close(sysFds[pin])) //Close filehandle + { + return 0; + } + + /* Set wiringPi to 'none' interrupt mode */ + + sprintf(pinS, "%d", pin); + + if ((pid = fork()) < 0) { // Fail + return printf("wiringPiISR: fork failed: %s\n", strerror(errno)); + } if (pid == 0) // Child, exec { - /**/ if (access ("/usr/local/bin/gpio", X_OK) == 0) - { - execl ("/usr/local/bin/gpio", "gpio", "edge", pinS, modeS, (char *)NULL) ; - return printf ("wiringPiISR: execl failed: %s\n", strerror (errno)) ; - } - else if (access ("/usr/bin/gpio", X_OK) == 0) - { - execl ("/usr/bin/gpio", "gpio", "edge", pinS, modeS, (char *)NULL) ; - return printf ("wiringPiISR: execl failed: %s\n", strerror (errno)) ; - } - else - return printf ("wiringPiISR: Can't find gpio program\n") ; + /**/ if (access("/usr/local/bin/gpio", X_OK) == 0) { + execl("/usr/local/bin/gpio", "gpio", "edge", pinS, modeS, (char*) NULL); + return printf("wiringPiISR: execl failed: %s\n", strerror(errno)); + } else if (access("/usr/bin/gpio", X_OK) == 0) { + execl("/usr/bin/gpio", "gpio", "edge", pinS, modeS, (char*) NULL); + return printf("wiringPiISR: execl failed: %s\n", strerror(errno)); + } else { + return printf("wiringPiISR: Can't find gpio program\n"); + } + } else { // Parent, wait + wait(NULL); } - else // Parent, wait - wait (NULL) ; - - return 1; + + return 1; } -void rfNoInterrupts(){ - pthread_mutex_lock (&pinMutex) ; +void rfNoInterrupts() +{ + pthread_mutex_lock(&pinMutex); } -void rfInterrupts(){ - pthread_mutex_unlock (&pinMutex) ; +void rfInterrupts() +{ + pthread_mutex_unlock(&pinMutex); } \ No newline at end of file diff --git a/utility/SPIDEV/interrupt.h b/utility/SPIDEV/interrupt.h index fe6fa4f6b..e76d34e7d 100644 --- a/utility/SPIDEV/interrupt.h +++ b/utility/SPIDEV/interrupt.h @@ -21,11 +21,12 @@ see * fires. ********************************************************************************* */ -void *interruptHandler (void *arg); +void* interruptHandler(void* arg); #ifdef __cplusplus extern "C" { #endif + /* * waitForInterrupt: * Pi Specific. @@ -35,14 +36,14 @@ extern "C" { * way for a bit more efficiency. ********************************************************************************* */ -extern int waitForInterrupt (int pin, int mS); +extern int waitForInterrupt(int pin, int mS); /* * piHiPri: * Attempt to set a high priority schedulling for the running program ********************************************************************************* */ -extern int piHiPri (const int pri); +extern int piHiPri(const int pri); /* * attachInterrupt (Original: wiringPiISR): @@ -51,7 +52,7 @@ extern int piHiPri (const int pri); * back to the user supplied function. ********************************************************************************* */ -extern int attachInterrupt (int pin, int mode, void (*function)(void)); +extern int attachInterrupt(int pin, int mode, void (* function)(void)); /* * detachInterrupt: @@ -60,10 +61,12 @@ extern int attachInterrupt (int pin, int mode, void (*function)(void)); * setting wiringPi back to 'none' mode. ********************************************************************************* */ -extern int detachInterrupt (int pin); +extern int detachInterrupt(int pin); extern void rfNoInterrupts(); + extern void rfInterrupts(); + #ifdef __cplusplus } #endif \ No newline at end of file diff --git a/utility/SPIDEV/spi.cpp b/utility/SPIDEV/spi.cpp index 6b36ca337..1b1d9ccdb 100644 --- a/utility/SPIDEV/spi.cpp +++ b/utility/SPIDEV/spi.cpp @@ -22,147 +22,171 @@ #define RF24_SPIDEV_BITS 8 -SPI::SPI():fd(-1), _spi_speed(RF24_SPIDEV_SPEED) { +SPI::SPI() + :fd(- 1), _spi_speed(RF24_SPIDEV_SPEED) +{ } bool spiIsInitialized = 0; -void SPI::begin(int busNo,uint32_t spi_speed){ +void SPI::begin(int busNo, uint32_t spi_speed) +{ - if(spiIsInitialized){ - return; + if (spiIsInitialized) { + return; } - + /* set spidev accordingly to busNo like: * busNo = 23 -> /dev/spidev2.3 * * a bit messy but simple * */ - char device[] = "/dev/spidev0.0"; - device[11] += (busNo / 10) % 10; - device[13] += busNo % 10; - - if(this->fd >=0) // check whether spi is already open - { - close(this->fd); - this->fd=-1; - } - - this->fd = open(device, O_RDWR); - if (this->fd < 0) throw SPIException("can't open device"); - /* + char device[] = "/dev/spidev0.0"; + device[11] += (busNo / 10) % 10; + device[13] += busNo % 10; + + if (this->fd >= 0) // check whether spi is already open + { + close(this->fd); + this->fd = - 1; + } + + this->fd = open(device, O_RDWR); + if (this->fd < 0) { + throw SPIException("can't open device"); + } + /* { perror("can't open device"); abort(); }*/ spiIsInitialized = true; - init(spi_speed); + init(spi_speed); } void SPI::init(uint32_t speed) { - uint8_t bits = RF24_SPIDEV_BITS; - uint8_t mode = 0; - - int ret; - /* - * spi mode - */ - ret = ioctl(this->fd, SPI_IOC_WR_MODE, &mode); - if (ret == -1) throw SPIException("cant set WR spi mode"); - /*{ - perror("can't set spi mode"); - abort(); - }*/ - - ret = ioctl(this->fd, SPI_IOC_RD_MODE, &mode); - if (ret == -1) throw SPIException("can't set RD spi mode"); - /*{ - perror("can't set spi mode"); - abort(); - }*/ - - /* - * bits per word - */ - ret = ioctl(this->fd, SPI_IOC_WR_BITS_PER_WORD, &bits); - if (ret == -1) throw SPIException("can't set WR bits per word"); - /*{ - perror("can't set bits per word"); - abort(); - }*/ - - ret = ioctl(this->fd, SPI_IOC_RD_BITS_PER_WORD, &bits); - if (ret == -1) throw SPIException("can't set RD bits per word"); - /*{ - perror("can't set bits per word"); - abort(); - }*/ - /* - * max speed hz - */ - ret = ioctl(this->fd, SPI_IOC_WR_MAX_SPEED_HZ, &speed); - if (ret == -1) throw SPIException("can't WR set max speed hz"); - /*{ - perror("can't set max speed hz"); - abort(); - }*/ - - ret = ioctl(this->fd, SPI_IOC_RD_MAX_SPEED_HZ, &speed); - if (ret == -1) throw SPIException("can't RD set max speed hz"); - /*{ - perror("can't set max speed hz"); - abort(); - }*/ - _spi_speed=speed; + uint8_t bits = RF24_SPIDEV_BITS; + uint8_t mode = 0; + + int ret; + /* + * spi mode + */ + ret = ioctl(this->fd, SPI_IOC_WR_MODE, &mode); + if (ret == - 1) { + throw SPIException("cant set WR spi mode"); + } + /*{ + perror("can't set spi mode"); + abort(); + }*/ + + ret = ioctl(this->fd, SPI_IOC_RD_MODE, &mode); + if (ret == - 1) { + throw SPIException("can't set RD spi mode"); + } + /*{ + perror("can't set spi mode"); + abort(); + }*/ + + /* + * bits per word + */ + ret = ioctl(this->fd, SPI_IOC_WR_BITS_PER_WORD, &bits); + if (ret == - 1) { + throw SPIException("can't set WR bits per word"); + } + /*{ + perror("can't set bits per word"); + abort(); + }*/ + + ret = ioctl(this->fd, SPI_IOC_RD_BITS_PER_WORD, &bits); + if (ret == - 1) { + throw SPIException("can't set RD bits per word"); + } + /*{ + perror("can't set bits per word"); + abort(); + }*/ + /* + * max speed hz + */ + ret = ioctl(this->fd, SPI_IOC_WR_MAX_SPEED_HZ, &speed); + if (ret == - 1) { + throw SPIException("can't WR set max speed hz"); + } + /*{ + perror("can't set max speed hz"); + abort(); + }*/ + + ret = ioctl(this->fd, SPI_IOC_RD_MAX_SPEED_HZ, &speed); + if (ret == - 1) { + throw SPIException("can't RD set max speed hz"); + } + /*{ + perror("can't set max speed hz"); + abort(); + }*/ + _spi_speed = speed; } uint8_t SPI::transfer(uint8_t tx) { - struct spi_ioc_transfer tr; - memset(&tr, 0, sizeof(tr)); - tr.tx_buf = (unsigned long)&tx; - uint8_t rx; - tr.rx_buf = (unsigned long)℞ - tr.len = sizeof(tx); - tr.speed_hz = _spi_speed; //RF24_SPIDEV_SPEED; - tr.delay_usecs = 0; - tr.bits_per_word = RF24_SPIDEV_BITS; - tr.cs_change = 0; - - int ret; - ret = ioctl(this->fd, SPI_IOC_MESSAGE(1), &tr); - if (ret < 1) throw SPIException("can't send spi message"); - /*{ - perror("can't send spi message"); - abort(); - }*/ - - return rx; + struct spi_ioc_transfer tr; + memset(&tr, 0, sizeof(tr)); + tr.tx_buf = (unsigned long) &tx; + uint8_t rx; + tr.rx_buf = (unsigned long) ℞ + tr.len = sizeof(tx); + tr.speed_hz = _spi_speed; //RF24_SPIDEV_SPEED; + tr.delay_usecs = 0; + tr.bits_per_word = RF24_SPIDEV_BITS; + tr.cs_change = 0; + + int ret; + ret = ioctl(this->fd, SPI_IOC_MESSAGE(1), &tr); + if (ret < 1) { + throw SPIException("can't send spi message"); + } + /*{ + perror("can't send spi message"); + abort(); + }*/ + + return rx; } void SPI::transfernb(char* tbuf, char* rbuf, uint32_t len) { struct spi_ioc_transfer tr; memset(&tr, 0, sizeof(tr)); - tr.tx_buf = (unsigned long)tbuf; - tr.rx_buf = (unsigned long)rbuf; + tr.tx_buf = (unsigned long) tbuf; + tr.rx_buf = (unsigned long) rbuf; tr.len = len; tr.speed_hz = _spi_speed; //RF24_SPIDEV_SPEED; tr.delay_usecs = 0; tr.bits_per_word = RF24_SPIDEV_BITS; tr.cs_change = 0; - int ret; - ret = ioctl(this->fd, SPI_IOC_MESSAGE(1), &tr); - if (ret < 1) throw SPIException("can't send spi message"); - /*{ - perror("can't send spi message"); - abort(); - }*/ + int ret; + ret = ioctl(this->fd, SPI_IOC_MESSAGE(1), &tr); + if (ret < 1) { + throw SPIException("can't send spi message"); + } + /*{ + perror("can't send spi message"); + abort(); + }*/ } -SPI::~SPI() { - if (this->fd >= 0) close(this->fd); +SPI::~SPI() +{ + if (this->fd >= 0) { + close(this->fd); + } } diff --git a/utility/SPIDEV/spi.h b/utility/SPIDEV/spi.h index 2f3236b93..c65abeb0f 100644 --- a/utility/SPIDEV/spi.h +++ b/utility/SPIDEV/spi.h @@ -6,7 +6,7 @@ */ #ifndef SPI_H -#define SPI_H +#define SPI_H /** * @file spi.h @@ -14,80 +14,83 @@ * Class declaration for SPI helper files */ - /** - * Example GPIO.h file - * - * @defgroup SPI SPI Example - * - * See RF24_arch_config.h for additional information - * @{ - */ +/** +* Example GPIO.h file +* +* @defgroup SPI SPI Example +* +* See RF24_arch_config.h for additional information +* @{ +*/ #include #include #ifndef RF24_SPIDEV_SPEED /* 8MHz as default */ -#define RF24_SPIDEV_SPEED 8000000 + #define RF24_SPIDEV_SPEED 8000000 #endif /** Specific excpetion for SPI errors */ class SPIException : public std::runtime_error { - public: - explicit SPIException(const std::string& msg) : std::runtime_error(msg) { } +public: + explicit SPIException(const std::string& msg) + :std::runtime_error(msg) + { + } }; - class SPI { public: - /** - * SPI constructor - */ - SPI(); - - /** - * Start SPI - */ - void begin(int busNo,uint32_t spi_speed=RF24_SPIDEV_SPEED); - - /** - * Transfer a single byte - * @param tx Byte to send - * @return Data returned via spi - */ - uint8_t transfer(uint8_t tx); - - /** - * Transfer a buffer of data - * @param tbuf Transmit buffer - * @param rbuf Receive buffer - * @param len Length of the data - */ - void transfernb(char* tbuf, char* rbuf, uint32_t len); - - /** - * Transfer a buffer of data without an rx buffer - * @param buf Pointer to a buffer of data - * @param len Length of the data - */ - void transfern(char* buf, uint32_t len) { - transfernb(buf, buf, len); - } - - ~SPI(); + /** + * SPI constructor + */ + SPI(); + + /** + * Start SPI + */ + void begin(int busNo, uint32_t spi_speed = RF24_SPIDEV_SPEED); + + /** + * Transfer a single byte + * @param tx Byte to send + * @return Data returned via spi + */ + uint8_t transfer(uint8_t tx); + + /** + * Transfer a buffer of data + * @param tbuf Transmit buffer + * @param rbuf Receive buffer + * @param len Length of the data + */ + void transfernb(char* tbuf, char* rbuf, uint32_t len); + + /** + * Transfer a buffer of data without an rx buffer + * @param buf Pointer to a buffer of data + * @param len Length of the data + */ + void transfern(char* buf, uint32_t len) + { + transfernb(buf, buf, len); + } + + ~SPI(); private: - int fd; - uint32_t _spi_speed; + int fd; + uint32_t _spi_speed; - void init(uint32_t spi_speed=RF24_SPIDEV_SPEED); + void init(uint32_t spi_speed = RF24_SPIDEV_SPEED); }; /** * \endcond */ /*@}*/ -#endif /* SPI_H */ +#endif /* SPI_H */ diff --git a/utility/Teensy/RF24_arch_config.h b/utility/Teensy/RF24_arch_config.h index 4848343a1..787b42de9 100644 --- a/utility/Teensy/RF24_arch_config.h +++ b/utility/Teensy/RF24_arch_config.h @@ -1,30 +1,30 @@ - #if ARDUINO < 100 - #include - #else - #include - #endif - - #include - - #include - #include - #include - - #include - #define _SPI SPI - - #define printf Serial.printf - - #ifdef SERIAL_DEBUG - #define IF_SERIAL_DEBUG(x) ({x;}) - #else - #define IF_SERIAL_DEBUG(x) - #endif - - - #define PRIPSTR "%s" +#if ARDUINO < 100 + #include +#else + #include +#endif + +#include + +#include +#include +#include + +#include + +#define _SPI SPI + +#define printf Serial.printf + +#ifdef SERIAL_DEBUG + #define IF_SERIAL_DEBUG(x) ({x;}) +#else + #define IF_SERIAL_DEBUG(x) +#endif + +#define PRIPSTR "%s" diff --git a/utility/Template/RF24_arch_config.h b/utility/Template/RF24_arch_config.h index f63420118..3c8d84c5e 100644 --- a/utility/Template/RF24_arch_config.h +++ b/utility/Template/RF24_arch_config.h @@ -1,4 +1,3 @@ - /* Copyright (C) 2011 J. Coliz @@ -7,22 +6,22 @@ version 2 as published by the Free Software Foundation. */ - - /** - * @file RF24_arch_config.h - * General defines and includes for RF24/Linux - */ - /** - * Example of RF24_arch_config.h for RF24 portability - * - * @defgroup Porting_General Porting: General - * - * - * @{ - */ - - +/** +* @file RF24_arch_config.h +* General defines and includes for RF24/Linux +*/ + +/** +* Example of RF24_arch_config.h for RF24 portability +* +* @defgroup Porting_General Porting: General +* +* +* @{ +*/ + + #ifndef __ARCH_CONFIG_H__ #define __ARCH_CONFIG_H__ @@ -38,24 +37,24 @@ #include #include -#define _BV(x) (1<<(x)) +#define _BV(x) (1 << (x)) #define _SPI spi #undef SERIAL_DEBUG #ifdef SERIAL_DEBUG -#define IF_SERIAL_DEBUG(x) ({x;}) + #define IF_SERIAL_DEBUG(x) ({x;}) #else -#define IF_SERIAL_DEBUG(x) + #define IF_SERIAL_DEBUG(x) #endif // Avoid spurious warnings #if 1 -#if ! defined( NATIVE ) && defined( ARDUINO ) -#undef PROGMEM -#define PROGMEM __attribute__(( section(".progmem.data") )) -#undef PSTR -#define PSTR(s) (__extension__({static const char __c[] PROGMEM = (s); &__c[0];})) -#endif + #if !defined(NATIVE) && defined(ARDUINO) + #undef PROGMEM + #define PROGMEM __attribute__(( section(".progmem.data") )) + #undef PSTR + #define PSTR(s) (__extension__({static const char __c[] PROGMEM = (s); &__c[0];})) + #endif #endif typedef uint16_t prog_uint16_t; @@ -63,7 +62,7 @@ typedef uint16_t prog_uint16_t; #define printf_P printf #define strlen_P strlen #define PROGMEM -#define pgm_read_word(p) (*(p)) +#define pgm_read_word(p) (*(p)) #define PRIPSTR "%s" #define pgm_read_byte(p) (*(p)) diff --git a/utility/Template/compatibility.h b/utility/Template/compatibility.h index 34b6a2af2..4fa1d51cd 100644 --- a/utility/Template/compatibility.h +++ b/utility/Template/compatibility.h @@ -5,40 +5,43 @@ * Created on 24 June 2012, 3:08 PM */ - /** - * @file compatibility.h - * Class declaration for SPI helper files - */ +/** +* @file compatibility.h +* Class declaration for SPI helper files +*/ + +/** +* Example of compatibility.h class declaration for timing functions portability +* +* @defgroup Porting_Timing Porting: Timing +* +* +* @{ +*/ - /** - * Example of compatibility.h class declaration for timing functions portability - * - * @defgroup Porting_Timing Porting: Timing - * - * - * @{ - */ - #ifndef COMPATIBLITY_H -#define COMPATIBLITY_H +#define COMPATIBLITY_H -#ifdef __cplusplus +#ifdef __cplusplus extern "C" { #endif - + #include #include #include void __msleep(int milisec); + void __usleep(int milisec); + void __start_timer(); + long __millis(); -#ifdef __cplusplus +#ifdef __cplusplus } #endif -#endif /* COMPATIBLITY_H */ +#endif /* COMPATIBLITY_H */ /*@}*/ \ No newline at end of file diff --git a/utility/Template/gpio.h b/utility/Template/gpio.h index 9b39b68a5..8a45698f4 100644 --- a/utility/Template/gpio.h +++ b/utility/Template/gpio.h @@ -5,55 +5,59 @@ * Class declaration for SPI helper files */ - /** - * Example of gpio.h class declaration for GPIO portability - * - * @defgroup Porting_GPIO Porting: GPIO - * - * - * @{ - */ +/** +* Example of gpio.h class declaration for GPIO portability +* +* @defgroup Porting_GPIO Porting: GPIO +* +* +* @{ +*/ #ifndef H -#define H +#define H #include //class GPIO { public: - /* Constants */ - static const int DIRECTION_OUT = 1; - static const int DIRECTION_IN = 0; - - static const int OUTPUT_HIGH = 1; - static const int OUTPUT_LOW = 0; - - GPIO(); - - /** - * Similar to Arduino pinMode(pin,mode); - * @param port - * @param DDR - */ - static void open(int port, int DDR); - /** - * - * @param port - */ - static void close(int port); - /** - * Similar to Arduino digitalRead(pin); - * @param port - * @param value - */ - static int read(int port); - /** - * Similar to Arduino digitalWrite(pin,state); - * @param port - * @param value - */ - static void write(int port,int value); - - virtual ~GPIO(); +/* Constants */ +static const int DIRECTION_OUT = 1; +static const int DIRECTION_IN = 0; + +static const int OUTPUT_HIGH = 1; +static const int OUTPUT_LOW = 0; + +GPIO(); + +/** + * Similar to Arduino pinMode(pin,mode); + * @param port + * @param DDR + */ +static void open(int port, int DDR); + +/** + * + * @param port + */ +static void close(int port); + +/** + * Similar to Arduino digitalRead(pin); + * @param port + * @param value + */ +static int read(int port); + +/** +* Similar to Arduino digitalWrite(pin,state); +* @param port +* @param value +*/ +static void write(int port, int value); + +virtual ~ GPIO(); + }; /*@}*/ \ No newline at end of file diff --git a/utility/Template/includes.h b/utility/Template/includes.h index 262cea00a..d35d43dbe 100644 --- a/utility/Template/includes.h +++ b/utility/Template/includes.h @@ -1,31 +1,30 @@ +/** +* @file includes.h +* Configuration defines for RF24/Linux +*/ - /** - * @file includes.h - * Configuration defines for RF24/Linux - */ +/** +* Example of includes.h for RF24 Linux portability +* +* @defgroup Porting_Includes Porting: Includes +* +* +* @{ +*/ - /** - * Example of includes.h for RF24 Linux portability - * - * @defgroup Porting_Includes Porting: Includes - * - * - * @{ - */ - #ifndef __RF24_INCLUDES_H__ #define __RF24_INCLUDES_H__ - /** - * Define a specific platform for this configuration - */ - #define RF24_BBB - - /** - * Load the correct configuration for this platform - */ - #include "BBB/RF24_arch_config.h" - +/** + * Define a specific platform for this configuration + */ +#define RF24_BBB + +/** + * Load the correct configuration for this platform +*/ +#include "BBB/RF24_arch_config.h" + #endif /*@}*/ \ No newline at end of file diff --git a/utility/Template/spi.h b/utility/Template/spi.h index 00d5744eb..e88122571 100644 --- a/utility/Template/spi.h +++ b/utility/Template/spi.h @@ -1,17 +1,16 @@ - /** * @file spi.h * Class declaration for SPI helper files */ - /** - * Example of spi.h class declaration for SPI portability - * - * @defgroup Porting_SPI Porting: SPI - * - * - * @{ - */ +/** +* Example of spi.h class declaration for SPI portability +* +* @defgroup Porting_SPI Porting: SPI +* +* +* @{ +*/ #include #include #include @@ -22,7 +21,7 @@ #include #include #include -#include +#include using namespace std; //class SPI { @@ -30,51 +29,52 @@ using namespace std; /** * SPI constructor - */ - SPI(); - - /** - * Start SPI - */ - void begin(int busNo); - - /** - * Transfer a single byte - * @param tx_ Byte to send - * @return Data returned via spi */ - uint8_t transfer(uint8_t tx_); - - /** - * Transfer a buffer of data - * @param tbuf Transmit buffer - * @param rbuf Receive buffer - * @param len Length of the data - */ - void transfernb(char* tbuf, char* rbuf, uint32_t len); +SPI(); + +/** +* Start SPI +*/ +void begin(int busNo); - /** - * Transfer a buffer of data without an rx buffer - * @param buf Pointer to a buffer of data - * @param len Length of the data - */ - void transfern(char* buf, uint32_t len); - - virtual ~SPI(); +/** +* Transfer a single byte +* @param tx_ Byte to send +* @return Data returned via spi +*/ +uint8_t transfer(uint8_t tx_); + +/** +* Transfer a buffer of data +* @param tbuf Transmit buffer +* @param rbuf Receive buffer +* @param len Length of the data +*/ +void transfernb(char* tbuf, char* rbuf, uint32_t len); + +/** +* Transfer a buffer of data without an rx buffer +* @param buf Pointer to a buffer of data +* @param len Length of the data +*/ +void transfern(char* buf, uint32_t len); + +virtual ~ SPI(); private: - /** Default SPI device */ - string device; - /** SPI Mode set */ - uint8_t mode; - /** word size*/ - uint8_t bits; - /** Set SPI speed*/ - uint32_t speed; - int fd; +/** Default SPI device */ +string device; +/** SPI Mode set */ +uint8_t mode; +/** word size*/ +uint8_t bits; +/** Set SPI speed*/ +uint32_t speed; +int fd; + +void init(); - void init(); }; diff --git a/utility/wiringPi/RF24_arch_config.h b/utility/wiringPi/RF24_arch_config.h index 8fb4bf550..fe3d885ff 100644 --- a/utility/wiringPi/RF24_arch_config.h +++ b/utility/wiringPi/RF24_arch_config.h @@ -1,4 +1,3 @@ - /* Copyright (C) 2011 J. Coliz @@ -26,19 +25,19 @@ #undef SERIAL_DEBUG #ifdef SERIAL_DEBUG -#define IF_SERIAL_DEBUG(x) ({x;}) + #define IF_SERIAL_DEBUG(x) ({x;}) #else -#define IF_SERIAL_DEBUG(x) + #define IF_SERIAL_DEBUG(x) #endif // Avoid spurious warnings #if 1 -#if ! defined( NATIVE ) && defined( ARDUINO ) -#undef PROGMEM -#define PROGMEM __attribute__(( section(".progmem.data") )) -#undef PSTR -#define PSTR(s) (__extension__({static const char __c[] PROGMEM = (s); &__c[0];})) -#endif + #if ! defined( NATIVE ) && defined( ARDUINO ) + #undef PROGMEM + #define PROGMEM __attribute__(( section(".progmem.data") )) + #undef PSTR + #define PSTR(s) (__extension__({static const char __c[] PROGMEM = (s); &__c[0];})) + #endif #endif typedef uint16_t prog_uint16_t; diff --git a/utility/wiringPi/includes.h b/utility/wiringPi/includes.h index c8b877511..b11c94a1b 100644 --- a/utility/wiringPi/includes.h +++ b/utility/wiringPi/includes.h @@ -1,30 +1,29 @@ +/** +* @file includes.h +* Configuration defines for RF24/Linux +*/ - /** - * @file includes.h - * Configuration defines for RF24/Linux - */ - - /** - * Example of includes.h for RF24 Linux portability - * - * @defgroup Porting_Includes Porting: Includes - * - * - * @{ - */ +/** +* Example of includes.h for RF24 Linux portability +* +* @defgroup Porting_Includes Porting: Includes +* +* +* @{ +*/ #ifndef __RF24_INCLUDES_H__ #define __RF24_INCLUDES_H__ - /** - * Define RF24_WIRINGPI configuration for RaspberryPi platform - */ - #define RF24_WIRINGPI +/** + * Define RF24_WIRINGPI configuration for RaspberryPi platform + */ +#define RF24_WIRINGPI - /** - * Load the correct configuration for this platform - */ - #include "wiringPi/RF24_arch_config.h" +/** + * Load the correct configuration for this platform + */ +#include "wiringPi/RF24_arch_config.h" #endif /*@}*/ \ No newline at end of file diff --git a/utility/wiringPi/spi.cpp b/utility/wiringPi/spi.cpp index 90d358bb4..7194eb74e 100644 --- a/utility/wiringPi/spi.cpp +++ b/utility/wiringPi/spi.cpp @@ -19,8 +19,8 @@ #include #include -#define RF24_SPI_SPEED 8 * 1000000 // 8Mhz -#define RF24_SPI_CHANNEL 0 +#define RF24_SPI_SPEED 8 * 1000000 // 8Mhz +#define RF24_SPI_CHANNEL 0 SPI::SPI():fd(-1) { @@ -30,14 +30,13 @@ SPI::SPI():fd(-1) void SPI::begin(int csn_pin) { // initialize the wiringPiSPI - if ((this->fd = wiringPiSPISetup(RF24_SPI_CHANNEL, RF24_SPI_SPEED)) < 0) - { + if ((this->fd = wiringPiSPISetup(RF24_SPI_CHANNEL, RF24_SPI_SPEED)) < 0) { printf("Cannot configure the SPI device!\n"); fflush(stdout); abort(); - } - else + } else { printf("Configured SPI fd: %d - pin: %d\n", fd, csn_pin); + } } uint8_t SPI::transfer(uint8_t tx) @@ -45,8 +44,7 @@ uint8_t SPI::transfer(uint8_t tx) memset(&msgByte, 0, sizeof(msgByte)); memcpy(&msgByte, &tx, sizeof(tx)); - if(wiringPiSPIDataRW(RF24_SPI_CHANNEL, &msgByte, sizeof(tx)) < 0) - { + if (wiringPiSPIDataRW(RF24_SPI_CHANNEL, &msgByte, sizeof(tx)) < 0) { printf("transfer(): Cannot send data: %s\n", strerror(errno)); fflush(stdout); abort(); @@ -59,8 +57,7 @@ void SPI::transfern(char* buf, uint32_t len) { printf("transfern(tx: %s)\n", buf); - if(wiringPiSPIDataRW(RF24_SPI_CHANNEL, (uint8_t *)buf, len) < 0) - { + if (wiringPiSPIDataRW(RF24_SPI_CHANNEL, (uint8_t*) buf, len) < 0) { printf("transfern(): Cannot send data %s\n", strerror(errno)); fflush(stdout); abort(); @@ -73,8 +70,7 @@ void SPI::transfernb(char* tbuf, char* rbuf, uint32_t len) memset(msg, 0, sizeof(msg)); memcpy(msg, tbuf, len); - if(wiringPiSPIDataRW(RF24_SPI_CHANNEL, msg, len) < 0) - { + if (wiringPiSPIDataRW(RF24_SPI_CHANNEL, msg, len) < 0) { printf("transfernb() Cannot send data %s\n", strerror(errno)); fflush(stdout); abort(); @@ -85,8 +81,7 @@ void SPI::transfernb(char* tbuf, char* rbuf, uint32_t len) SPI::~SPI() { - if (!(this->fd < 0)) - { + if (this->fd >= 0) { close(this->fd); this->fd = -1; } diff --git a/utility/wiringPi/spi.h b/utility/wiringPi/spi.h index 8fde9e474..18e408391 100644 --- a/utility/wiringPi/spi.h +++ b/utility/wiringPi/spi.h @@ -1,70 +1,70 @@ - /** * @file spi.h * Class declaration for SPI helper files */ #ifndef SPI_H -#define SPI_H +#define SPI_H - /** - * Example of spi.h class declaration for SPI portability - * - * @defgroup Porting_SPI Porting: SPI - * - * @{ - */ +/** +* Example of spi.h class declaration for SPI portability +* +* @defgroup Porting_SPI Porting: SPI +* +* @{ +*/ #include #include using namespace std; + class SPI { public: - /** - * SPI default constructor - */ - SPI(); + /** + * SPI default constructor + */ + SPI(); - /** - * Start SPI communication - * @param pin used for SPI - */ - void begin(int); + /** + * Start SPI communication + * @param pin used for SPI + */ + void begin(int); - /** - * Transfer a single byte of data - * @param tx Byte to send - * @return Data returned via spi - */ - uint8_t transfer(uint8_t); + /** + * Transfer a single byte of data + * @param tx Byte to send + * @return Data returned via spi + */ + uint8_t transfer(uint8_t); - /** - * Transfer a buffer of data using rx and tx buffer - * @param tbuf Transmit buffer - * @param rbuf Receive buffer - * @param len Length of the data - */ - void transfernb(char*, char*, uint32_t); + /** + * Transfer a buffer of data using rx and tx buffer + * @param tbuf Transmit buffer + * @param rbuf Receive buffer + * @param len Length of the data + */ + void transfernb(char*, char*, uint32_t); - /** - * Transfer a buffer of data without using an rx buffer - * @param buf Pointer to a buffer of data - * @param len Length of the data - */ - void transfern(char*, const uint32_t); + /** + * Transfer a buffer of data without using an rx buffer + * @param buf Pointer to a buffer of data + * @param len Length of the data + */ + void transfern(char*, const uint32_t); - /** - * SPI destructor - */ - virtual ~SPI(); + /** + * SPI destructor + */ + virtual ~SPI(); private: - int fd; - uint8_t msg[32 + 1]; - uint8_t msgByte; + int fd; + uint8_t msg[32 + 1]; + uint8_t msgByte; }; /*@}*/ -#endif /* SPI_H */ +#endif /* SPI_H */ diff --git a/wikidoc.xslt b/wikidoc.xslt index b94d3ef6c..6a3d61363 100644 --- a/wikidoc.xslt +++ b/wikidoc.xslt @@ -1,41 +1,47 @@ - - - - - - - === === - - - - - '''' - -Parameters: + + + + + + + === === + + + + + + + '''' + + + Parameters: + + + * '''': + + + + + + + Returns: - - - * '''': - - - - - -Returns: - -* - - -Warning: - - - - <pre> </pre> - - - - - + * + + + + Warning: + + + + <pre> + + </pre> + + + + +