RPi SPI functionality and RPi fix for startWrite

- Enabled use of hardware CS1 pin
- Removed custom_cs code for software driven CSN
- Modified BCM driver to allow use of hardware SPI pins not in use while
SPI is active.
- Updated constructor in examples
This commit is contained in:
TMRh20
2014-04-25 19:38:08 -06:00
parent cd8bb19dc3
commit 6530f954a1
10 changed files with 376 additions and 398 deletions
+1
View File
@@ -37,4 +37,5 @@ Supported Boards:
* Mega Types (2560, 1280, etc) * Mega Types (2560, 1280, etc)
* ARM (Arduino Due) via extended SPI methods * ARM (Arduino Due) via extended SPI methods
* ATTiny 24/44/84 25/45/85 * ATTiny 24/44/84 25/45/85
* Raspberry Pi
* See the [documentation](http://tmrh20.github.io/) for more info * See the [documentation](http://tmrh20.github.io/) for more info
+85 -72
View File
@@ -4,12 +4,12 @@
This program is free software; you can redistribute it and/or This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License modify it under the terms of the GNU General Public License
version 2 as published by the Free Software Foundation. version 2 as published by the Free Software Foundation.
03/17/2013 : Charles-Henri Hallard (http://hallard.me) 03/17/2013 : Charles-Henri Hallard (http://hallard.me)
Modified to use with Arduipi board http://hallard.me/arduipi Modified to use with Arduipi board http://hallard.me/arduipi
Changed to use modified bcm2835 library Changed to use modified bcm2835 library
TMRh20 2014: Updated to work with optimized RF24 and RF24 Network Arduino libs. TMRh20 2014: Updated to work with optimized RF24 and RF24 Network Arduino libs.
*/ */
@@ -53,7 +53,7 @@ uint8_t RF24::read_register(uint8_t reg)
*ptx++ = ( R_REGISTER | ( REGISTER_MASK & reg ) ); *ptx++ = ( R_REGISTER | ( REGISTER_MASK & reg ) );
*ptx++ = NOP ; // Dummy operation, just for reading *ptx++ = NOP ; // Dummy operation, just for reading
bcm2835_spi_transfernb( (char *) spi_txbuff, (char *) spi_rxbuff, 2); bcm2835_spi_transfernb( (char *) spi_txbuff, (char *) spi_rxbuff, 2);
result = *++prx; // result is 2nd byte of receive buffer result = *++prx; // result is 2nd byte of receive buffer
@@ -71,12 +71,12 @@ uint8_t RF24::write_register(uint8_t reg, uint8_t value)
*ptx++ = ( W_REGISTER | ( REGISTER_MASK & reg ) ); *ptx++ = ( W_REGISTER | ( REGISTER_MASK & reg ) );
*ptx = value ; *ptx = value ;
bcm2835_spi_transfernb( (char *) spi_txbuff, (char *) spi_rxbuff, 2); bcm2835_spi_transfernb( (char *) spi_txbuff, (char *) spi_rxbuff, 2);
status = *prx++; // status is 1st byte of receive buffer status = *prx++; // status is 1st byte of receive buffer
if (debug) if (debug)
printf("write_register(%02x,%02x)\r\n",reg,value); printf("write_register(%02x,%02x)\r\n",reg,value);
return status; return status;
@@ -90,7 +90,7 @@ uint8_t RF24::write_register(uint8_t reg, const uint8_t* buf, uint8_t len)
uint8_t * prx = spi_rxbuff; uint8_t * prx = spi_rxbuff;
uint8_t * ptx = spi_txbuff; uint8_t * ptx = spi_txbuff;
uint8_t size = len + 1; // Add register value to transmit buffer uint8_t size = len + 1; // Add register value to transmit buffer
*ptx++ = ( W_REGISTER | ( REGISTER_MASK & reg ) ); *ptx++ = ( W_REGISTER | ( REGISTER_MASK & reg ) );
while ( len-- ) while ( len-- )
*ptx++ = *buf++; *ptx++ = *buf++;
@@ -98,7 +98,7 @@ uint8_t RF24::write_register(uint8_t reg, const uint8_t* buf, uint8_t len)
bcm2835_spi_transfernb( (char *) spi_txbuff, (char *) spi_rxbuff, size); bcm2835_spi_transfernb( (char *) spi_txbuff, (char *) spi_rxbuff, size);
status = *prx; // status is 1st byte of receive buffer status = *prx; // status is 1st byte of receive buffer
return status; return status;
} }
@@ -110,15 +110,15 @@ uint8_t RF24::write_payload(const void* buf, uint8_t len, const uint8_t writeTyp
uint8_t status; uint8_t status;
uint8_t * prx = spi_rxbuff; uint8_t * prx = spi_rxbuff;
uint8_t * ptx = spi_txbuff; uint8_t * ptx = spi_txbuff;
uint8_t size ; uint8_t size ;
const uint8_t* current = reinterpret_cast<const uint8_t*>(buf); const uint8_t* current = reinterpret_cast<const uint8_t*>(buf);
uint8_t data_len = min(len,payload_size); uint8_t data_len = min(len,payload_size);
uint8_t blank_len = dynamic_payloads_enabled ? 0 : payload_size - data_len; uint8_t blank_len = dynamic_payloads_enabled ? 0 : payload_size - data_len;
size = data_len + blank_len + 1 ; // Add register value to transmit buffer size = data_len + blank_len + 1 ; // Add register value to transmit buffer
if (debug) if (debug)
printf("[Writing %u bytes %u blanks]",data_len,blank_len); printf("[Writing %u bytes %u blanks]",data_len,blank_len);
@@ -126,13 +126,13 @@ uint8_t RF24::write_payload(const void* buf, uint8_t len, const uint8_t writeTyp
while ( data_len-- ) while ( data_len-- )
*ptx++ = *current++; *ptx++ = *current++;
while ( blank_len-- ) while ( blank_len-- )
*ptx++ = 0; *ptx++ = 0;
bcm2835_spi_transfernb( (char *) spi_txbuff, (char *) spi_rxbuff, size); bcm2835_spi_transfernb( (char *) spi_txbuff, (char *) spi_rxbuff, size);
status = *prx; // status is 1st byte of receive buffer status = *prx; // status is 1st byte of receive buffer
return status; return status;
} }
@@ -143,30 +143,30 @@ uint8_t RF24::read_payload(void* buf, uint8_t len)
uint8_t status; uint8_t status;
uint8_t * prx = spi_rxbuff; uint8_t * prx = spi_rxbuff;
uint8_t * ptx = spi_txbuff; uint8_t * ptx = spi_txbuff;
uint8_t size ; uint8_t size ;
uint8_t* current = reinterpret_cast<uint8_t*>(buf); uint8_t* current = reinterpret_cast<uint8_t*>(buf);
uint8_t data_len = min(len,payload_size); uint8_t data_len = min(len,payload_size);
uint8_t blank_len = dynamic_payloads_enabled ? 0 : payload_size - data_len; uint8_t blank_len = dynamic_payloads_enabled ? 0 : payload_size - data_len;
size = data_len + blank_len + 1; // Add register value to transmit buffer size = data_len + blank_len + 1; // Add register value to transmit buffer
if (debug) if (debug)
printf("[Reading %u bytes %u blanks]",data_len,blank_len); printf("[Reading %u bytes %u blanks]",data_len,blank_len);
*ptx++ = R_RX_PAYLOAD; *ptx++ = R_RX_PAYLOAD;
while(size--) while(size--)
*ptx++ = NOP; *ptx++ = NOP;
// Size has been lost during while, re affect // Size has been lost during while, re affect
size = data_len + blank_len + 1; // Add register value to transmit buffer size = data_len + blank_len + 1; // Add register value to transmit buffer
bcm2835_spi_transfernb( (char *) spi_txbuff, (char *) spi_rxbuff, size); bcm2835_spi_transfernb( (char *) spi_txbuff, (char *) spi_rxbuff, size);
// 1st byte is status // 1st byte is status
status = *prx++; status = *prx++;
// Decrement before to skip 1st status byte // Decrement before to skip 1st status byte
while ( --size ) while ( --size )
*current++ = *prx++; *current++ = *prx++;
@@ -264,7 +264,7 @@ void RF24::print_address_register(const char* name, uint8_t reg, uint8_t qty)
/****************************************************************************/ /****************************************************************************/
RF24::RF24(uint8_t _cepin, uint8_t _cspin, uint32_t _spi_speed): RF24::RF24(uint8_t _cepin, uint8_t _cspin, uint32_t _spi_speed):
ce_pin(_cepin), csn_pin(_cspin), spi_speed(_spi_speed), wide_band(true), p_variant(false), ce_pin(_cepin), csn_pin(_cspin), spi_speed(_spi_speed), wide_band(true), p_variant(false),
payload_size(32), dynamic_payloads_enabled(false), payload_size(32), dynamic_payloads_enabled(false),
pipe0_reading_address(0) pipe0_reading_address(0)
{ {
@@ -324,7 +324,7 @@ static const char rf24_pa_dbm_e_str_0[] = "PA_MIN";
static const char rf24_pa_dbm_e_str_1[] = "PA_LOW"; static const char rf24_pa_dbm_e_str_1[] = "PA_LOW";
static const char rf24_pa_dbm_e_str_2[] = "PA_HIGH"; static const char rf24_pa_dbm_e_str_2[] = "PA_HIGH";
static const char rf24_pa_dbm_e_str_3[] = "PA_MAX"; static const char rf24_pa_dbm_e_str_3[] = "PA_MAX";
static const char * const rf24_pa_dbm_e_str_P[] = { static const char * const rf24_pa_dbm_e_str_P[] = {
rf24_pa_dbm_e_str_0, rf24_pa_dbm_e_str_0,
rf24_pa_dbm_e_str_1, rf24_pa_dbm_e_str_1,
rf24_pa_dbm_e_str_2, rf24_pa_dbm_e_str_2,
@@ -335,7 +335,7 @@ 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_1[] = "CE1 (PI Hardware Driven)";
static const char rf24_csn_e_str_2[] = "CE2 (PI Hardware Driven)"; static const char rf24_csn_e_str_2[] = "CE2 (PI Hardware Driven)";
static const char rf24_csn_e_str_3[] = "Custom GPIO Software Driven"; static const char rf24_csn_e_str_3[] = "Custom GPIO Software Driven";
static const char * const rf24_csn_e_str_P[] = { static const char * const rf24_csn_e_str_P[] = {
rf24_csn_e_str_0, rf24_csn_e_str_0,
rf24_csn_e_str_1, rf24_csn_e_str_1,
rf24_csn_e_str_2, rf24_csn_e_str_2,
@@ -352,13 +352,13 @@ void RF24::printDetails(void)
printf("CSN Pin \t = %s\n",rf24_csn_e_str_P[csn_pin]); printf("CSN Pin \t = %s\n",rf24_csn_e_str_P[csn_pin]);
} }
else else
{ {
printf("CSN Pin \t = Custom GPIO%d%s\n", csn_pin, printf("CSN Pin \t = Custom GPIO%d%s\n", csn_pin,
csn_pin==RPI_V2_GPIO_P1_26 ? " (CE1) Software Driven" : "" ); csn_pin==RPI_V2_GPIO_P1_26 ? " (CE1) Software Driven" : "" );
} }
printf("CE Pin \t = Custom GPIO%d\n", ce_pin ); printf("CE Pin \t = Custom GPIO%d\n", ce_pin );
// SPI Bus Speed // SPI Bus Speed
printf("Clock Speed\t = " ); printf("Clock Speed\t = " );
switch (spi_speed) switch (spi_speed)
@@ -409,32 +409,45 @@ bool RF24::begin(void)
{ {
debug = false; debug = false;
//debug = true; //debug = true;
// This initialize the SPI bus with
// csn pin as chip select (custom or not)
// Init BCM2835 chipset for talking with us // Init BCM2835 chipset for talking with us
if (!bcm2835_init()){ if (!bcm2835_init()){
return false; return false;
} }
// Initialise the CE pin of NRF24 (chip enable)
bcm2835_gpio_fsel(ce_pin, BCM2835_GPIO_FSEL_OUTP); switch(csn_pin){ //Ensure valid hardware CS pin
bcm2835_gpio_write(ce_pin, LOW); case 0: break;
case 1: break;
case 8: csn_pin = 0; break;
case 7: csn_pin = 1; break;
default: csn_pin = 0; break;
}
bcm2835_spi_begin();
// used to drive custom I/O to trigger my logic analyser // used to drive custom I/O to trigger my logic analyser
// bcm2835_gpio_fsel(GPIO_CTRL_PIN , BCM2835_GPIO_FSEL_OUTP); // bcm2835_gpio_fsel(GPIO_CTRL_PIN , BCM2835_GPIO_FSEL_OUTP);
// start the SPI library: // start the SPI library:
// Note the NRF24 wants mode 0, MSB first and default to 1 Mbps // Note the NRF24 wants mode 0, MSB first and default to 1 Mbps
bcm2835_spi_setBitOrder(BCM2835_SPI_BIT_ORDER_MSBFIRST); bcm2835_spi_setBitOrder(BCM2835_SPI_BIT_ORDER_MSBFIRST);
bcm2835_spi_setDataMode(BCM2835_SPI_MODE0); bcm2835_spi_setDataMode(BCM2835_SPI_MODE0);
// Set SPI bus Speed // Set SPI bus Speed
bcm2835_spi_setClockDivider(spi_speed); bcm2835_spi_setClockDivider(spi_speed);
if(csn_pin <= BCM2835_SPI_CS_NONE){ // Choose hardware CSN pin
bcm2835_spi_chipSelect(csn_pin); bcm2835_spi_chipSelect(csn_pin);
}
// This initialize the SPI bus with
// csn pin as chip select (custom or not) // Initialise the CE pin of NRF24 (chip enable) after the CSN pin, so that
bcm2835_spi_begin(csn_pin); // The input mode is not changed if using one of the hardware CE pins
bcm2835_gpio_fsel(ce_pin, BCM2835_GPIO_FSEL_OUTP);
bcm2835_gpio_write(ce_pin, LOW);
// wait 100ms // wait 100ms
delay(100); delay(100);
@@ -453,14 +466,14 @@ bool RF24::begin(void)
{ {
p_variant = true ; p_variant = true ;
} }
// Then set the data rate to the slowest (and most reliable) speed supported by all // Then set the data rate to the slowest (and most reliable) speed supported by all
// hardware. // hardware.
setDataRate( RF24_1MBPS ) ; setDataRate( RF24_1MBPS ) ;
// Initialize CRC and request 2-byte (16bit) CRC // Initialize CRC and request 2-byte (16bit) CRC
setCRCLength( RF24_CRC_16 ) ; setCRCLength( RF24_CRC_16 ) ;
// Reset current status // Reset current status
// Notice reset and flush is the last thing we do // Notice reset and flush is the last thing we do
write_register(STATUS,_BV(RX_DR) | _BV(TX_DS) | _BV(MAX_RT) ); write_register(STATUS,_BV(RX_DR) | _BV(TX_DS) | _BV(MAX_RT) );
@@ -479,7 +492,7 @@ bool RF24::begin(void)
// 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 ) // 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 // PTX should use only 22uA of power
write_register(CONFIG, ( read_register(CONFIG) ) & ~_BV(PRIM_RX) ); write_register(CONFIG, ( read_register(CONFIG) ) & ~_BV(PRIM_RX) );
return true; return true;
} }
@@ -501,7 +514,7 @@ void RF24::startListening(void)
// Go! // Go!
bcm2835_gpio_write(ce_pin, HIGH); bcm2835_gpio_write(ce_pin, HIGH);
// wait for the radio to come up (130us actually only needed) // wait for the radio to come up (130us actually only needed)
//delayMicroseconds(130); //delayMicroseconds(130);
} }
@@ -514,7 +527,7 @@ void RF24::stopListening(void)
flush_tx(); flush_tx();
flush_rx(); flush_rx();
write_register(CONFIG, ( read_register(CONFIG) ) & ~_BV(PRIM_RX) ); write_register(CONFIG, ( read_register(CONFIG) ) & ~_BV(PRIM_RX) );
} }
/****************************************************************************/ /****************************************************************************/
@@ -528,7 +541,7 @@ void RF24::powerDown(void)
/****************************************************************************/ /****************************************************************************/
void RF24::powerUp(void) void RF24::powerUp(void)
{ {
bool up = read_register(CONFIG) & _BV(PWR_UP); bool up = read_register(CONFIG) & _BV(PWR_UP);
if(! up ){ if(! up ){
@@ -536,7 +549,7 @@ void RF24::powerUp(void)
delay(5); delay(5);
} }
} }
/******************************************************************/ /******************************************************************/
@@ -544,13 +557,13 @@ void RF24::powerUp(void)
bool RF24::write( const void* buf, uint8_t len, const bool multicast ){ bool RF24::write( const void* buf, uint8_t len, const bool multicast ){
// Begin the write // Begin the write
startWrite(buf,len, multicast); startFastWrite(buf,len, multicast);
//Wait until complete or failed //Wait until complete or failed
// If this hangs, it ain't coming back, no sense in timing out // If this hangs, it ain't coming back, no sense in timing out
while( ! ( get_status() & ( _BV(TX_DS) | _BV(MAX_RT) ))) { } while( ! ( get_status() & ( _BV(TX_DS) | _BV(MAX_RT) ))) { }
uint8_t status = write_register(STATUS,_BV(RX_DR) | _BV(TX_DS) | _BV(MAX_RT) ); uint8_t status = write_register(STATUS,_BV(RX_DR) | _BV(TX_DS) | _BV(MAX_RT) );
bcm2835_gpio_write(ce_pin, LOW); bcm2835_gpio_write(ce_pin, LOW);
@@ -566,7 +579,7 @@ bool RF24::write( const void* buf, uint8_t len, const bool multicast ){
bool RF24::write( const void* buf, uint8_t len ){ bool RF24::write( const void* buf, uint8_t len ){
return write(buf,len,0); return write(buf,len,0);
} }
/****************************************************************************/ /****************************************************************************/
@@ -600,7 +613,7 @@ bool RF24::writeBlocking( const void* buf, uint8_t len, uint32_t timeout )
void RF24::reUseTX(){ void RF24::reUseTX(){
write_register(STATUS,_BV(MAX_RT) ); //Clear max retry flag write_register(STATUS,_BV(MAX_RT) ); //Clear max retry flag
//spiTrans( REUSE_TX_PL ); //spiTrans( REUSE_TX_PL );
bcm2835_spi_transfer( REUSE_TX_PL); bcm2835_spi_transfer( REUSE_TX_PL);
bcm2835_gpio_write(ce_pin, LOW); //Re-Transfer packet bcm2835_gpio_write(ce_pin, LOW); //Re-Transfer packet
bcm2835_gpio_write(ce_pin, HIGH); bcm2835_gpio_write(ce_pin, HIGH);
} }
@@ -648,18 +661,18 @@ void RF24::startFastWrite( const void* buf, uint8_t len, const bool multicast){
bcm2835_gpio_write(ce_pin, HIGH); bcm2835_gpio_write(ce_pin, HIGH);
} }
/****************************************************************************/ /****************************************************************************/
void RF24::startWrite( const void* buf, uint8_t len, const bool multicast ) void RF24::startWrite( const void* buf, uint8_t len, const bool multicast )
{ {
// Send the payload // Send the payload
write_payload( buf, len,multicast ? W_TX_PAYLOAD_NO_ACK : W_TX_PAYLOAD ) ; write_payload( buf, len,multicast ? W_TX_PAYLOAD_NO_ACK : W_TX_PAYLOAD ) ;
bcm2835_gpio_write(ce_pin, HIGH); bcm2835_gpio_write(ce_pin, HIGH);
//bcm2835_gpio_write(ce_pin, LOW); delayMicroseconds(10);
bcm2835_gpio_write(ce_pin, LOW);
} }
/****************************************************************************/ /****************************************************************************/
@@ -736,7 +749,7 @@ bool RF24::available(uint8_t* pipe_num)
//Check the FIFO buffer to see if data is waitng to be read //Check the FIFO buffer to see if data is waitng to be read
if (!( read_register(FIFO_STATUS) & _BV(RX_EMPTY) )){ if (!( read_register(FIFO_STATUS) & _BV(RX_EMPTY) )){
// If the caller wants the pipe number, include that // If the caller wants the pipe number, include that
if ( pipe_num ){ if ( pipe_num ){
@@ -840,12 +853,12 @@ void RF24::toggle_features(void)
void RF24::enableDynamicPayloads(void) void RF24::enableDynamicPayloads(void)
{ {
// So enable them and try again // So enable them and try again
toggle_features(); toggle_features();
write_register(FEATURE,read_register(FEATURE) | _BV(EN_DPL) ); write_register(FEATURE,read_register(FEATURE) | _BV(EN_DPL) );
if (debug) if (debug)
printf("FEATURE=%i\r\n",read_register(FEATURE)); printf("FEATURE=%i\r\n",read_register(FEATURE));
// Enable dynamic payload on all pipes // Enable dynamic payload on all pipes
@@ -900,14 +913,14 @@ void RF24::writeAckPayload(uint8_t pipe, const void* buf, uint8_t len)
{ {
uint8_t * ptx = spi_txbuff; uint8_t * ptx = spi_txbuff;
uint8_t size ; uint8_t size ;
const uint8_t* current = reinterpret_cast<const uint8_t*>(buf); const uint8_t* current = reinterpret_cast<const uint8_t*>(buf);
uint8_t data_len = min(len,payload_size); uint8_t data_len = min(len,payload_size);
size = data_len + 1 ; // Add register value to transmit buffer size = data_len + 1 ; // Add register value to transmit buffer
if (debug){ if (debug){
printf("[Writing %u bytes]",data_len); printf("[Writing %u bytes]",data_len);
} }
@@ -917,9 +930,9 @@ void RF24::writeAckPayload(uint8_t pipe, const void* buf, uint8_t len)
} }
bcm2835_spi_transfern( (char *) spi_txbuff, size); bcm2835_spi_transfern( (char *) spi_txbuff, size);
} }
/****************************************************************************/ /****************************************************************************/
bool RF24::isAckPayloadAvailable(void) bool RF24::isAckPayloadAvailable(void)
@@ -1053,7 +1066,7 @@ rf24_datarate_e RF24::getDataRate( void )
{ {
rf24_datarate_e result ; rf24_datarate_e result ;
uint8_t dr = read_register(RF_SETUP) & (_BV(RF_DR_LOW) | _BV(RF_DR_HIGH)); uint8_t dr = read_register(RF_SETUP) & (_BV(RF_DR_LOW) | _BV(RF_DR_HIGH));
// switch uses RAM (evil!) // switch uses RAM (evil!)
// Order matters in our case below // Order matters in our case below
if ( dr == _BV(RF_DR_LOW) ) if ( dr == _BV(RF_DR_LOW) )
@@ -1079,11 +1092,11 @@ rf24_datarate_e RF24::getDataRate( void )
void RF24::setCRCLength(rf24_crclength_e length) void RF24::setCRCLength(rf24_crclength_e length)
{ {
uint8_t config = read_register(CONFIG) & ~( _BV(CRCO) | _BV(EN_CRC)) ; uint8_t config = read_register(CONFIG) & ~( _BV(CRCO) | _BV(EN_CRC)) ;
// switch uses RAM (evil!) // switch uses RAM (evil!)
if ( length == RF24_CRC_DISABLED ) if ( length == RF24_CRC_DISABLED )
{ {
// Do nothing, we turned it off above. // Do nothing, we turned it off above.
} }
else if ( length == RF24_CRC_8 ) else if ( length == RF24_CRC_8 )
{ {
+93 -145
View File
@@ -59,7 +59,7 @@ static uint8_t debug = 0;
static int i2c_byte_wait_us = 0; static int i2c_byte_wait_us = 0;
// SPI Custom Chip Select Pin // SPI Custom Chip Select Pin
static int spi_custom_cs = 0; //static int spi_custom_cs = 0;
// Time for millis() // Time for millis()
static unsigned long long epoch ; static unsigned long long epoch ;
@@ -365,7 +365,7 @@ void bcm2835_gpio_set_pad(uint8_t group, uint32_t control)
void bcm2835_delay(unsigned int millis) void bcm2835_delay(unsigned int millis)
{ {
struct timespec sleeper; struct timespec sleeper;
sleeper.tv_sec = (time_t)(millis / 1000); sleeper.tv_sec = (time_t)(millis / 1000);
sleeper.tv_nsec = (long)(millis % 1000) * 1000000; sleeper.tv_nsec = (long)(millis % 1000) * 1000000;
nanosleep(&sleeper, NULL); nanosleep(&sleeper, NULL);
@@ -376,18 +376,18 @@ void bcm2835_delayMicroseconds(uint64_t micros)
{ {
struct timespec t1; struct timespec t1;
uint64_t start; uint64_t start;
// Calling nanosleep() takes at least 100-200 us, so use it for // 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. // long waits and use a busy wait on the System Timer for the rest.
start = bcm2835_st_read(); start = bcm2835_st_read();
if (micros > 450) if (micros > 450)
{ {
t1.tv_sec = 0; t1.tv_sec = 0;
t1.tv_nsec = 1000 * (long)(micros - 200); t1.tv_nsec = 1000 * (long)(micros - 200);
nanosleep(&t1, NULL); nanosleep(&t1, NULL);
} }
bcm2835_st_delay(start, micros); bcm2835_st_delay(start, micros);
} }
@@ -460,91 +460,31 @@ void bcm2835_gpio_set_pud(uint8_t pin, uint8_t pud)
bcm2835_gpio_pudclk(pin, 0); bcm2835_gpio_pudclk(pin, 0);
} }
void bcm2835_spi_begin(uint8_t cs) void bcm2835_spi_begin()
{ {
/*
// Set the SPI0 pins to the Alt 0 function to enable SPI0 access on them // 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_26, BCM2835_GPIO_FSEL_ALT0); // CE1
// Enable CE0 by default, will be disabled if bcm2835_chipSelect() is called using another pin
bcm2835_gpio_fsel(RPI_GPIO_P1_24, BCM2835_GPIO_FSEL_ALT0); // CE0 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_21, BCM2835_GPIO_FSEL_ALT0); // MISO
bcm2835_gpio_fsel(RPI_GPIO_P1_19, BCM2835_GPIO_FSEL_ALT0); // MOSI bcm2835_gpio_fsel(RPI_GPIO_P1_19, BCM2835_GPIO_FSEL_ALT0); // MOSI
bcm2835_gpio_fsel(RPI_GPIO_P1_23, BCM2835_GPIO_FSEL_ALT0); // CLK bcm2835_gpio_fsel(RPI_GPIO_P1_23, BCM2835_GPIO_FSEL_ALT0); // CLK
// Set the SPI CS register to the some sensible defaults // Set the SPI CS register to the some sensible defaults
volatile uint32_t* paddr = bcm2835_spi0 + BCM2835_SPI0_CS/4; volatile uint32_t* paddr = bcm2835_spi0 + BCM2835_SPI0_CS/4;
bcm2835_peri_write(paddr, 0); // All 0s bcm2835_peri_write(paddr, 0); // All 0s
// Clear TX and RX fifos // Clear TX and RX fifos
bcm2835_peri_write_nb(paddr, BCM2835_SPI0_CS_CLEAR); bcm2835_peri_write_nb(paddr, BCM2835_SPI0_CS_CLEAR);
*/
volatile uint32_t* paddr = bcm2835_spi0 + BCM2835_SPI0_CS/4;
// Set the SPI0 pins to the Alt 0 function to enable SPI0 access on them
// except if we need custom Chip Select Pin
// printf("bcm2835_spi_begin -> spi_custom_cs = %d \n",cs );
// Do we need custom chip select control or
// drive CE1 manually (because CE1 does not work with hardware)
if ( cs > BCM2835_SPI_CS_NONE || cs == BCM2835_SPI_CS1 )
{
// indicate we will use a custom GPIO port
spi_custom_cs = cs ;
// ok hard CE1 not working, drive it manually
if (cs == BCM2835_SPI_CS1 )
{
// Dirty Hack CE1 in now custom Chip Select GPIO 26
// the real CE1 pin
spi_custom_cs = RPI_GPIO_P1_26 ;
bcm2835_gpio_fsel(spi_custom_cs, BCM2835_GPIO_FSEL_OUTP);
bcm2835_gpio_write(spi_custom_cs, HIGH);
}
// Mask in we use custom CS (not sure it has a real effect)
bcm2835_peri_set_bits(paddr, BCM2835_SPI_CS_NONE, BCM2835_SPI0_CS_CS);
}
// Ok hardware driving of chip select
else
{
// Just in case
spi_custom_cs = 0 ;
// Mask in the CS bits of CS
bcm2835_peri_set_bits(paddr, cs, BCM2835_SPI0_CS_CS);
}
// Now we can drive the I/O as asked
if (spi_custom_cs == 0)
{
// Not custom CS, so hardware driven
bcm2835_gpio_fsel(RPI_GPIO_P1_24, BCM2835_GPIO_FSEL_ALT0); // CE0
bcm2835_gpio_fsel(RPI_GPIO_P1_26, BCM2835_GPIO_FSEL_ALT0); // CE1
}
else
{
// so set custom CS as output, High level by default
bcm2835_gpio_fsel(spi_custom_cs, BCM2835_GPIO_FSEL_OUTP); // Custom GPIO
bcm2835_gpio_write(spi_custom_cs, HIGH);
}
// Classic pin, hardware driven
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
bcm2835_peri_write(paddr, 0); // All 0s
// Clear TX and RX fifos
bcm2835_peri_write_nb(paddr, BCM2835_SPI0_CS_CLEAR);
} }
void bcm2835_spi_end(void) void bcm2835_spi_end(void)
{ {
// Set all the SPI0 pins back to input /* // Set all the SPI0 pins back to input
if (spi_custom_cs == 0) if (spi_custom_cs == 0)
{ {
bcm2835_gpio_fsel(RPI_GPIO_P1_26, BCM2835_GPIO_FSEL_INPT); // CE1 bcm2835_gpio_fsel(RPI_GPIO_P1_26, BCM2835_GPIO_FSEL_INPT); // CE1
@@ -557,26 +497,25 @@ void bcm2835_spi_end(void)
bcm2835_gpio_fsel(RPI_GPIO_P1_21, BCM2835_GPIO_FSEL_INPT); // MISO bcm2835_gpio_fsel(RPI_GPIO_P1_21, BCM2835_GPIO_FSEL_INPT); // MISO
bcm2835_gpio_fsel(RPI_GPIO_P1_19, BCM2835_GPIO_FSEL_INPT); // MOSI bcm2835_gpio_fsel(RPI_GPIO_P1_19, BCM2835_GPIO_FSEL_INPT); // MOSI
bcm2835_gpio_fsel(RPI_GPIO_P1_23, BCM2835_GPIO_FSEL_INPT); // CLK bcm2835_gpio_fsel(RPI_GPIO_P1_23, BCM2835_GPIO_FSEL_INPT); // CLK
*/
/*
// Set all the SPI0 pins back to input // 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_26, BCM2835_GPIO_FSEL_INPT); // CE1
bcm2835_gpio_fsel(RPI_GPIO_P1_24, BCM2835_GPIO_FSEL_INPT); // CE0 bcm2835_gpio_fsel(RPI_GPIO_P1_24, BCM2835_GPIO_FSEL_INPT); // CE0
bcm2835_gpio_fsel(RPI_GPIO_P1_21, BCM2835_GPIO_FSEL_INPT); // MISO bcm2835_gpio_fsel(RPI_GPIO_P1_21, BCM2835_GPIO_FSEL_INPT); // MISO
bcm2835_gpio_fsel(RPI_GPIO_P1_19, BCM2835_GPIO_FSEL_INPT); // MOSI bcm2835_gpio_fsel(RPI_GPIO_P1_19, BCM2835_GPIO_FSEL_INPT); // MOSI
bcm2835_gpio_fsel(RPI_GPIO_P1_23, BCM2835_GPIO_FSEL_INPT); // CLK bcm2835_gpio_fsel(RPI_GPIO_P1_23, BCM2835_GPIO_FSEL_INPT); // CLK
*/
} }
/*
// Drive Custom chip select pin // Drive Custom chip select pin
void bcm2835_spi_setChipSelect(uint8_t level) void bcm2835_spi_setChipSelect(uint8_t level)
{ {
// Do this only if we are using custom ChipSelect I/O // Do this only if we are using custom ChipSelect I/O
if ( spi_custom_cs > BCM2835_SPI_CS_NONE ) if ( spi_custom_cs > BCM2835_SPI_CS_NONE )
bcm2835_gpio_write(spi_custom_cs, level); bcm2835_gpio_write(spi_custom_cs, level);
} }*/
void bcm2835_spi_setBitOrder(uint8_t order) void bcm2835_spi_setBitOrder(uint8_t order)
@@ -606,14 +545,15 @@ uint8_t bcm2835_spi_transfer(uint8_t value)
{ {
volatile uint32_t* paddr = bcm2835_spi0 + BCM2835_SPI0_CS/4; volatile uint32_t* paddr = bcm2835_spi0 + BCM2835_SPI0_CS/4;
volatile uint32_t* fifo = bcm2835_spi0 + BCM2835_SPI0_FIFO/4; volatile uint32_t* fifo = bcm2835_spi0 + BCM2835_SPI0_FIFO/4;
// Custom chip select LOW // Custom chip select LOW
if(spi_custom_cs > BCM2835_SPI_CS_NONE){ /*if(spi_custom_cs > BCM2835_SPI_CS_NONE){
bcm2835_spi_setChipSelect(LOW); bcm2835_spi_setChipSelect(LOW);
} }*/
// This is Polled transfer as per section 10.6.1 // This is Polled transfer as per section 10.6.1
// BUG ALERT: what happens if we get interupted in this section, and someone else // BUG ALERT: what happens if we get interupted in this section, and someone else
// accesses a different peripheral? // accesses a different peripheral?
// Clear TX and RX fifos // Clear TX and RX fifos
bcm2835_peri_set_bits(paddr, BCM2835_SPI0_CS_CLEAR, BCM2835_SPI0_CS_CLEAR); bcm2835_peri_set_bits(paddr, BCM2835_SPI0_CS_CLEAR, BCM2835_SPI0_CS_CLEAR);
@@ -640,9 +580,9 @@ uint8_t bcm2835_spi_transfer(uint8_t value)
bcm2835_peri_set_bits(paddr, 0, BCM2835_SPI0_CS_TA); bcm2835_peri_set_bits(paddr, 0, BCM2835_SPI0_CS_TA);
// Custom chip select HIGH // Custom chip select HIGH
if(spi_custom_cs > BCM2835_SPI_CS_NONE){ //if(spi_custom_cs > BCM2835_SPI_CS_NONE){
bcm2835_spi_setChipSelect(HIGH); // bcm2835_spi_setChipSelect(HIGH);
} //}
return ret; return ret;
} }
@@ -656,7 +596,7 @@ void bcm2835_spi_transfernb(char* tbuf, char* rbuf, uint32_t len)
// This is Polled transfer as per section 10.6.1 // This is Polled transfer as per section 10.6.1
// BUG ALERT: what happens if we get interupted in this section, and someone else // BUG ALERT: what happens if we get interupted in this section, and someone else
// accesses a different peripheral? // accesses a different peripheral?
// Clear TX and RX fifos // Clear TX and RX fifos
bcm2835_peri_set_bits(paddr, BCM2835_SPI0_CS_CLEAR, BCM2835_SPI0_CS_CLEAR); bcm2835_peri_set_bits(paddr, BCM2835_SPI0_CS_CLEAR, BCM2835_SPI0_CS_CLEAR);
@@ -696,9 +636,9 @@ void bcm2835_spi_writenb(char* tbuf, uint32_t len)
volatile uint32_t* paddr = bcm2835_spi0 + BCM2835_SPI0_CS/4; volatile uint32_t* paddr = bcm2835_spi0 + BCM2835_SPI0_CS/4;
volatile uint32_t* fifo = bcm2835_spi0 + BCM2835_SPI0_FIFO/4; volatile uint32_t* fifo = bcm2835_spi0 + BCM2835_SPI0_FIFO/4;
if(spi_custom_cs > BCM2835_SPI_CS_NONE){ //if(spi_custom_cs > BCM2835_SPI_CS_NONE){
bcm2835_spi_setChipSelect(LOW); // bcm2835_spi_setChipSelect(LOW);
} //}
// This is Polled transfer as per section 10.6.1 // This is Polled transfer as per section 10.6.1
// BUG ALERT: what happens if we get interupted in this section, and someone else // BUG ALERT: what happens if we get interupted in this section, and someone else
// accesses a different peripheral? // accesses a different peripheral?
@@ -715,15 +655,15 @@ void bcm2835_spi_writenb(char* tbuf, uint32_t len)
// Maybe wait for TXD // 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 // Write to FIFO, no barrier
bcm2835_peri_write_nb(fifo, tbuf[i]); bcm2835_peri_write_nb(fifo, tbuf[i]);
// Read from FIFO to prevent stalling // Read from FIFO to prevent stalling
while (bcm2835_peri_read(paddr) & BCM2835_SPI0_CS_RXD) while (bcm2835_peri_read(paddr) & BCM2835_SPI0_CS_RXD)
(void) bcm2835_peri_read_nb(fifo); (void) bcm2835_peri_read_nb(fifo);
} }
// Wait for DONE to be set // 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)) {
while (bcm2835_peri_read(paddr) & BCM2835_SPI0_CS_RXD) while (bcm2835_peri_read(paddr) & BCM2835_SPI0_CS_RXD)
@@ -732,10 +672,10 @@ void bcm2835_spi_writenb(char* tbuf, uint32_t len)
// Set TA = 0, and also set the barrier // Set TA = 0, and also set the barrier
bcm2835_peri_set_bits(paddr, 0, BCM2835_SPI0_CS_TA); bcm2835_peri_set_bits(paddr, 0, BCM2835_SPI0_CS_TA);
if(spi_custom_cs > BCM2835_SPI_CS_NONE){ //if(spi_custom_cs > BCM2835_SPI_CS_NONE){
bcm2835_spi_setChipSelect(HIGH); // bcm2835_spi_setChipSelect(HIGH);
} //}
} }
// Writes (and reads) an number of bytes to SPI // Writes (and reads) an number of bytes to SPI
@@ -748,6 +688,14 @@ void bcm2835_spi_transfern(char* buf, uint32_t len)
void bcm2835_spi_chipSelect(uint8_t cs) 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;
if(cs){
bcm2835_gpio_fsel(RPI_GPIO_P1_26, BCM2835_GPIO_FSEL_ALT0); // CE1
bcm2835_gpio_fsel(RPI_GPIO_P1_24, BCM2835_GPIO_FSEL_INPT); // Revert default of CE0 back to input
}else{
bcm2835_gpio_fsel(RPI_GPIO_P1_24, BCM2835_GPIO_FSEL_ALT0); // CE0
}
// Mask in the CS bits of CS // Mask in the CS bits of CS
bcm2835_peri_set_bits(paddr, cs, BCM2835_SPI0_CS_CS); bcm2835_peri_set_bits(paddr, cs, BCM2835_SPI0_CS_CS);
} }
@@ -772,7 +720,7 @@ void bcm2835_i2c_begin(void)
// Set the I2C/BSC1 pins to the Alt 0 function to enable I2C access on them // 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_03, BCM2835_GPIO_FSEL_ALT0); // SDA
bcm2835_gpio_fsel(RPI_V2_GPIO_P1_05, BCM2835_GPIO_FSEL_ALT0); // SCL bcm2835_gpio_fsel(RPI_V2_GPIO_P1_05, BCM2835_GPIO_FSEL_ALT0); // SCL
#endif #endif
// Read the clock divider register // Read the clock divider register
uint16_t cdiv = bcm2835_peri_read(paddr); uint16_t cdiv = bcm2835_peri_read(paddr);
@@ -800,7 +748,7 @@ void bcm2835_i2c_setSlaveAddress(uint8_t addr)
// Set I2C Device Address // Set I2C Device Address
#ifdef I2C_V1 #ifdef I2C_V1
volatile uint32_t* paddr = bcm2835_bsc0 + BCM2835_BSC_A/4; volatile uint32_t* paddr = bcm2835_bsc0 + BCM2835_BSC_A/4;
#else #else
volatile uint32_t* paddr = bcm2835_bsc1 + BCM2835_BSC_A/4; volatile uint32_t* paddr = bcm2835_bsc1 + BCM2835_BSC_A/4;
#endif #endif
bcm2835_peri_write(paddr, addr); bcm2835_peri_write(paddr, addr);
@@ -815,7 +763,7 @@ void bcm2835_i2c_setClockDivider(uint16_t divider)
volatile uint32_t* paddr = bcm2835_bsc0 + BCM2835_BSC_DIV/4; volatile uint32_t* paddr = bcm2835_bsc0 + BCM2835_BSC_DIV/4;
#else #else
volatile uint32_t* paddr = bcm2835_bsc1 + BCM2835_BSC_DIV/4; volatile uint32_t* paddr = bcm2835_bsc1 + BCM2835_BSC_DIV/4;
#endif #endif
bcm2835_peri_write(paddr, divider); bcm2835_peri_write(paddr, divider);
// Calculate time for transmitting one byte // Calculate time for transmitting one byte
// 1000000 = micros seconds in a second // 1000000 = micros seconds in a second
@@ -845,7 +793,7 @@ uint8_t bcm2835_i2c_write(const char * buf, uint32_t len)
volatile uint32_t* fifo = bcm2835_bsc1 + BCM2835_BSC_FIFO/4; volatile uint32_t* fifo = bcm2835_bsc1 + BCM2835_BSC_FIFO/4;
volatile uint32_t* status = bcm2835_bsc1 + BCM2835_BSC_S/4; volatile uint32_t* status = bcm2835_bsc1 + BCM2835_BSC_S/4;
volatile uint32_t* control = bcm2835_bsc1 + BCM2835_BSC_C/4; volatile uint32_t* control = bcm2835_bsc1 + BCM2835_BSC_C/4;
#endif #endif
uint32_t remaining = len; uint32_t remaining = len;
uint32_t i = 0; uint32_t i = 0;
@@ -864,10 +812,10 @@ uint8_t bcm2835_i2c_write(const char * buf, uint32_t len)
i++; i++;
remaining--; remaining--;
} }
// Enable device and start transfer // Enable device and start transfer
bcm2835_peri_write_nb(control, BCM2835_BSC_C_I2CEN | BCM2835_BSC_C_ST); bcm2835_peri_write_nb(control, BCM2835_BSC_C_I2CEN | BCM2835_BSC_C_ST);
// Transfer is over when BCM2835_BSC_S_DONE // Transfer is over when BCM2835_BSC_S_DONE
while(!(bcm2835_peri_read_nb(status) & BCM2835_BSC_S_DONE )) while(!(bcm2835_peri_read_nb(status) & BCM2835_BSC_S_DONE ))
{ {
@@ -916,7 +864,7 @@ uint8_t bcm2835_i2c_read(char* buf, uint32_t len)
volatile uint32_t* fifo = bcm2835_bsc1 + BCM2835_BSC_FIFO/4; volatile uint32_t* fifo = bcm2835_bsc1 + BCM2835_BSC_FIFO/4;
volatile uint32_t* status = bcm2835_bsc1 + BCM2835_BSC_S/4; volatile uint32_t* status = bcm2835_bsc1 + BCM2835_BSC_S/4;
volatile uint32_t* control = bcm2835_bsc1 + BCM2835_BSC_C/4; volatile uint32_t* control = bcm2835_bsc1 + BCM2835_BSC_C/4;
#endif #endif
uint32_t remaining = len; uint32_t remaining = len;
uint32_t i = 0; uint32_t i = 0;
@@ -930,7 +878,7 @@ uint8_t bcm2835_i2c_read(char* buf, uint32_t len)
bcm2835_peri_write_nb(dlen, len); bcm2835_peri_write_nb(dlen, len);
// Start read // Start read
bcm2835_peri_write_nb(control, BCM2835_BSC_C_I2CEN | BCM2835_BSC_C_ST | BCM2835_BSC_C_READ); bcm2835_peri_write_nb(control, BCM2835_BSC_C_I2CEN | BCM2835_BSC_C_ST | BCM2835_BSC_C_READ);
// wait for transfer to complete // 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))
{ {
@@ -943,7 +891,7 @@ uint8_t bcm2835_i2c_read(char* buf, uint32_t len)
remaining--; remaining--;
} }
} }
// transfer has finished - grab any remaining stuff in FIFO // 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))
{ {
@@ -952,7 +900,7 @@ uint8_t bcm2835_i2c_read(char* buf, uint32_t len)
i++; i++;
remaining--; remaining--;
} }
// Received a NACK // Received a NACK
if (bcm2835_peri_read(status) & BCM2835_BSC_S_ERR) if (bcm2835_peri_read(status) & BCM2835_BSC_S_ERR)
{ {
@@ -979,7 +927,7 @@ uint8_t bcm2835_i2c_read(char* buf, uint32_t len)
// Read an number of bytes from I2C sending a repeated start after writing // Read an number of bytes from I2C sending a repeated start after writing
// the required register. Only works if your device supports this mode // 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) 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* dlen = bcm2835_bsc0 + BCM2835_BSC_DLEN/4;
volatile uint32_t* fifo = bcm2835_bsc0 + BCM2835_BSC_FIFO/4; volatile uint32_t* fifo = bcm2835_bsc0 + BCM2835_BSC_FIFO/4;
@@ -990,11 +938,11 @@ uint8_t bcm2835_i2c_read_register_rs(char* regaddr, char* buf, uint32_t len)
volatile uint32_t* fifo = bcm2835_bsc1 + BCM2835_BSC_FIFO/4; volatile uint32_t* fifo = bcm2835_bsc1 + BCM2835_BSC_FIFO/4;
volatile uint32_t* status = bcm2835_bsc1 + BCM2835_BSC_S/4; volatile uint32_t* status = bcm2835_bsc1 + BCM2835_BSC_S/4;
volatile uint32_t* control = bcm2835_bsc1 + BCM2835_BSC_C/4; volatile uint32_t* control = bcm2835_bsc1 + BCM2835_BSC_C/4;
#endif #endif
uint32_t remaining = len; uint32_t remaining = len;
uint32_t i = 0; uint32_t i = 0;
uint8_t reason = BCM2835_I2C_REASON_OK; uint8_t reason = BCM2835_I2C_REASON_OK;
// Clear FIFO // 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 // Clear Status
@@ -1005,7 +953,7 @@ uint8_t bcm2835_i2c_read_register_rs(char* regaddr, char* buf, uint32_t len)
bcm2835_peri_write_nb(control, BCM2835_BSC_C_I2CEN); bcm2835_peri_write_nb(control, BCM2835_BSC_C_I2CEN);
bcm2835_peri_write_nb(fifo, regaddr[0]); bcm2835_peri_write_nb(fifo, regaddr[0]);
bcm2835_peri_write_nb(control, BCM2835_BSC_C_I2CEN | BCM2835_BSC_C_ST); bcm2835_peri_write_nb(control, BCM2835_BSC_C_I2CEN | BCM2835_BSC_C_ST);
// poll for transfer has started // poll for transfer has started
while ( !( bcm2835_peri_read_nb(status) & BCM2835_BSC_S_TA ) ) while ( !( bcm2835_peri_read_nb(status) & BCM2835_BSC_S_TA ) )
{ {
@@ -1013,14 +961,14 @@ uint8_t bcm2835_i2c_read_register_rs(char* regaddr, char* buf, uint32_t len)
if(bcm2835_peri_read(status) & BCM2835_BSC_S_DONE) if(bcm2835_peri_read(status) & BCM2835_BSC_S_DONE)
break; break;
} }
// Send a repeated start with read bit set in address // Send a repeated start with read bit set in address
bcm2835_peri_write_nb(dlen, len); bcm2835_peri_write_nb(dlen, len);
bcm2835_peri_write_nb(control, BCM2835_BSC_C_I2CEN | BCM2835_BSC_C_ST | BCM2835_BSC_C_READ ); bcm2835_peri_write_nb(control, BCM2835_BSC_C_I2CEN | BCM2835_BSC_C_ST | BCM2835_BSC_C_READ );
// Wait for write to complete and first byte back. // Wait for write to complete and first byte back.
bcm2835_delayMicroseconds(i2c_byte_wait_us * 3); bcm2835_delayMicroseconds(i2c_byte_wait_us * 3);
// wait for transfer to complete // 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))
{ {
@@ -1033,7 +981,7 @@ uint8_t bcm2835_i2c_read_register_rs(char* regaddr, char* buf, uint32_t len)
remaining--; remaining--;
} }
} }
// transfer has finished - grab any remaining stuff in FIFO // 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))
{ {
@@ -1042,7 +990,7 @@ uint8_t bcm2835_i2c_read_register_rs(char* regaddr, char* buf, uint32_t len)
i++; i++;
remaining--; remaining--;
} }
// Received a NACK // Received a NACK
if (bcm2835_peri_read(status) & BCM2835_BSC_S_ERR) if (bcm2835_peri_read(status) & BCM2835_BSC_S_ERR)
{ {
@@ -1066,10 +1014,10 @@ uint8_t bcm2835_i2c_read_register_rs(char* regaddr, char* buf, uint32_t len)
return reason; return reason;
} }
// Sending an arbitrary number of bytes before issuing a repeated start // Sending an arbitrary number of bytes before issuing a repeated start
// (with no prior stop) and reading a response. Some devices require this behavior. // (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) 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* dlen = bcm2835_bsc0 + BCM2835_BSC_DLEN/4;
volatile uint32_t* fifo = bcm2835_bsc0 + BCM2835_BSC_FIFO/4; volatile uint32_t* fifo = bcm2835_bsc0 + BCM2835_BSC_FIFO/4;
@@ -1080,12 +1028,12 @@ uint8_t bcm2835_i2c_write_read_rs(char* cmds, uint32_t cmds_len, char* buf, uint
volatile uint32_t* fifo = bcm2835_bsc1 + BCM2835_BSC_FIFO/4; volatile uint32_t* fifo = bcm2835_bsc1 + BCM2835_BSC_FIFO/4;
volatile uint32_t* status = bcm2835_bsc1 + BCM2835_BSC_S/4; volatile uint32_t* status = bcm2835_bsc1 + BCM2835_BSC_S/4;
volatile uint32_t* control = bcm2835_bsc1 + BCM2835_BSC_C/4; volatile uint32_t* control = bcm2835_bsc1 + BCM2835_BSC_C/4;
#endif #endif
uint32_t remaining = cmds_len; uint32_t remaining = cmds_len;
uint32_t i = 0; uint32_t i = 0;
uint8_t reason = BCM2835_I2C_REASON_OK; uint8_t reason = BCM2835_I2C_REASON_OK;
// Clear FIFO // 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 );
@@ -1094,7 +1042,7 @@ uint8_t bcm2835_i2c_write_read_rs(char* cmds, uint32_t cmds_len, char* buf, uint
// Set Data Length // Set Data Length
bcm2835_peri_write_nb(dlen, cmds_len); bcm2835_peri_write_nb(dlen, cmds_len);
// pre populate FIFO with max buffer // pre populate FIFO with max buffer
while( remaining && ( i < BCM2835_BSC_FIFO_SIZE ) ) while( remaining && ( i < BCM2835_BSC_FIFO_SIZE ) )
{ {
@@ -1103,9 +1051,9 @@ uint8_t bcm2835_i2c_write_read_rs(char* cmds, uint32_t cmds_len, char* buf, uint
remaining--; remaining--;
} }
// Enable device and start transfer // Enable device and start transfer
bcm2835_peri_write_nb(control, BCM2835_BSC_C_I2CEN | BCM2835_BSC_C_ST); bcm2835_peri_write_nb(control, BCM2835_BSC_C_I2CEN | BCM2835_BSC_C_ST);
// poll for transfer has started (way to do repeated start, from BCM2835 datasheet) // poll for transfer has started (way to do repeated start, from BCM2835 datasheet)
while ( !( bcm2835_peri_read_nb(status) & BCM2835_BSC_S_TA ) ) while ( !( bcm2835_peri_read_nb(status) & BCM2835_BSC_S_TA ) )
{ {
@@ -1113,17 +1061,17 @@ uint8_t bcm2835_i2c_write_read_rs(char* cmds, uint32_t cmds_len, char* buf, uint
if(bcm2835_peri_read(status) & BCM2835_BSC_S_DONE) if(bcm2835_peri_read(status) & BCM2835_BSC_S_DONE)
break; break;
} }
remaining = buf_len; remaining = buf_len;
i = 0; i = 0;
// Send a repeated start with read bit set in address // Send a repeated start with read bit set in address
bcm2835_peri_write_nb(dlen, buf_len); bcm2835_peri_write_nb(dlen, buf_len);
bcm2835_peri_write_nb(control, BCM2835_BSC_C_I2CEN | BCM2835_BSC_C_ST | BCM2835_BSC_C_READ ); bcm2835_peri_write_nb(control, BCM2835_BSC_C_I2CEN | BCM2835_BSC_C_ST | BCM2835_BSC_C_READ );
// Wait for write to complete and first byte back. // Wait for write to complete and first byte back.
bcm2835_delayMicroseconds(i2c_byte_wait_us * (cmds_len + 1)); bcm2835_delayMicroseconds(i2c_byte_wait_us * (cmds_len + 1));
// wait for transfer to complete // 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))
{ {
@@ -1136,7 +1084,7 @@ uint8_t bcm2835_i2c_write_read_rs(char* cmds, uint32_t cmds_len, char* buf, uint
remaining--; remaining--;
} }
} }
// transfer has finished - grab any remaining stuff in FIFO // 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))
{ {
@@ -1145,7 +1093,7 @@ uint8_t bcm2835_i2c_write_read_rs(char* cmds, uint32_t cmds_len, char* buf, uint
i++; i++;
remaining--; remaining--;
} }
// Received a NACK // Received a NACK
if (bcm2835_peri_read(status) & BCM2835_BSC_S_ERR) if (bcm2835_peri_read(status) & BCM2835_BSC_S_ERR)
{ {
@@ -1202,7 +1150,7 @@ void bcm2835_pwm_set_clock(uint32_t divisor)
bcm2835_delay(110); // Prevents clock going slow bcm2835_delay(110); // Prevents clock going slow
// Wait for the clock to be not busy // Wait for the clock to be not busy
while ((bcm2835_peri_read(bcm2835_clk + BCM2835_PWMCLK_CNTL) & 0x80) != 0) 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 // 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_DIV, BCM2835_PWM_PASSWRD | (divisor << 12));
bcm2835_peri_write(bcm2835_clk + BCM2835_PWMCLK_CNTL, BCM2835_PWM_PASSWRD | 0x11); // Source=osc and enable bcm2835_peri_write(bcm2835_clk + BCM2835_PWMCLK_CNTL, BCM2835_PWM_PASSWRD | 0x11); // Source=osc and enable
@@ -1288,7 +1236,7 @@ int bcm2835_init(void)
{ {
struct timeval tv ; struct timeval tv ;
if (debug) if (debug)
{ {
bcm2835_pads = (uint32_t*)BCM2835_GPIO_PADS; bcm2835_pads = (uint32_t*)BCM2835_GPIO_PADS;
bcm2835_clk = (uint32_t*)BCM2835_CLOCK_BASE; bcm2835_clk = (uint32_t*)BCM2835_CLOCK_BASE;
@@ -1303,13 +1251,13 @@ int bcm2835_init(void)
int memfd = -1; int memfd = -1;
int ok = 0; int ok = 0;
// Open the master /dev/memory device // Open the master /dev/memory device
if ((memfd = open("/dev/mem", O_RDWR | O_SYNC) ) < 0) if ((memfd = open("/dev/mem", O_RDWR | O_SYNC) ) < 0)
{ {
fprintf(stderr, "bcm2835_init: Unable to open /dev/mem: %s\n", fprintf(stderr, "bcm2835_init: Unable to open /dev/mem: %s\n",
strerror(errno)) ; strerror(errno)) ;
goto exit; goto exit;
} }
// GPIO: // GPIO:
bcm2835_gpio = (volatile uint32_t *)mapmem("gpio", BCM2835_BLOCK_SIZE, memfd, BCM2835_GPIO_BASE); bcm2835_gpio = (volatile uint32_t *)mapmem("gpio", BCM2835_BLOCK_SIZE, memfd, BCM2835_GPIO_BASE);
if (bcm2835_gpio == MAP_FAILED) goto exit; if (bcm2835_gpio == MAP_FAILED) goto exit;
@@ -1321,10 +1269,10 @@ int bcm2835_init(void)
// Clock control (needed for PWM) // Clock control (needed for PWM)
bcm2835_clk = (volatile uint32_t *)mapmem("clk", BCM2835_BLOCK_SIZE, memfd, BCM2835_CLOCK_BASE); bcm2835_clk = (volatile uint32_t *)mapmem("clk", BCM2835_BLOCK_SIZE, memfd, BCM2835_CLOCK_BASE);
if (bcm2835_clk == MAP_FAILED) goto exit; if (bcm2835_clk == MAP_FAILED) goto exit;
bcm2835_pads = (volatile uint32_t *)mapmem("pads", BCM2835_BLOCK_SIZE, memfd, BCM2835_GPIO_PADS); bcm2835_pads = (volatile uint32_t *)mapmem("pads", BCM2835_BLOCK_SIZE, memfd, BCM2835_GPIO_PADS);
if (bcm2835_pads == MAP_FAILED) goto exit; if (bcm2835_pads == MAP_FAILED) goto exit;
bcm2835_spi0 = (volatile uint32_t *)mapmem("spi0", BCM2835_BLOCK_SIZE, memfd, BCM2835_SPI0_BASE); bcm2835_spi0 = (volatile uint32_t *)mapmem("spi0", BCM2835_BLOCK_SIZE, memfd, BCM2835_SPI0_BASE);
if (bcm2835_spi0 == MAP_FAILED) goto exit; if (bcm2835_spi0 == MAP_FAILED) goto exit;
@@ -1367,10 +1315,10 @@ int bcm2835_close(void)
unmapmem((void**) &bcm2835_st, BCM2835_BLOCK_SIZE); unmapmem((void**) &bcm2835_st, BCM2835_BLOCK_SIZE);
unmapmem((void**) &bcm2835_pads, BCM2835_BLOCK_SIZE); unmapmem((void**) &bcm2835_pads, BCM2835_BLOCK_SIZE);
return 1; // Success return 1; // Success
} }
#ifdef BCM2835_TEST #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 // actually doing it
int main(int argc, char **argv) int main(int argc, char **argv)
{ {
@@ -1398,13 +1346,13 @@ int main(int argc, char **argv)
{ {
// Turn it on // Turn it on
bcm2835_gpio_write(RPI_GPIO_P1_11, HIGH); bcm2835_gpio_write(RPI_GPIO_P1_11, HIGH);
// wait a bit // wait a bit
bcm2835_delay(500); bcm2835_delay(500);
// turn it off // turn it off
bcm2835_gpio_write(RPI_GPIO_P1_11, LOW); bcm2835_gpio_write(RPI_GPIO_P1_11, LOW);
// wait a bit // wait a bit
bcm2835_delay(500); bcm2835_delay(500);
} }
@@ -1417,7 +1365,7 @@ int main(int argc, char **argv)
// Read some data // Read some data
uint8_t value = bcm2835_gpio_lev(RPI_GPIO_P1_15); uint8_t value = bcm2835_gpio_lev(RPI_GPIO_P1_15);
printf("read from pin 15: %d\n", value); printf("read from pin 15: %d\n", value);
// wait a bit // wait a bit
bcm2835_delay(500); bcm2835_delay(500);
} }
+127 -127
View File
@@ -16,7 +16,7 @@
// //
/// \mainpage C library for Broadcom BCM 2835 as used in Raspberry Pi /// \mainpage C library for Broadcom BCM 2835 as used in Raspberry Pi
/// ///
/// This is a C library for Raspberry Pi (RPi). It provides access to /// This is a C library for Raspberry Pi (RPi). It provides access to
/// GPIO and other IO functions on the Broadcom BCM 2835 chip, /// GPIO and other IO functions on the Broadcom BCM 2835 chip,
/// allowing access to the GPIO pins on the /// allowing access to the GPIO pins on the
/// 26 pin IDE plug on the RPi board so you can control and interface with various external devices. /// 26 pin IDE plug on the RPi board so you can control and interface with various external devices.
@@ -25,34 +25,34 @@
/// and for accessing the system timers. /// and for accessing the system timers.
/// Pin event detection is supported by polling (interrupts are not supported). /// Pin event detection is supported by polling (interrupts are not supported).
/// ///
/// It is C++ compatible, and installs as a header file and non-shared library on /// It is C++ compatible, and installs as a header file and non-shared library on
/// any Linux-based distro (but clearly is no use except on Raspberry Pi or another board with /// any Linux-based distro (but clearly is no use except on Raspberry Pi or another board with
/// BCM 2835). /// BCM 2835).
/// ///
/// The version of the package that this documentation refers to can be downloaded /// The version of the package that this documentation refers to can be downloaded
/// from http://www.airspayce.com/mikem/bcm2835/bcm2835-1.36.tar.gz /// from http://www.airspayce.com/mikem/bcm2835/bcm2835-1.36.tar.gz
/// You can find the latest version at http://www.airspayce.com/mikem/bcm2835 /// You can find the latest version at http://www.airspayce.com/mikem/bcm2835
/// ///
/// Several example programs are provided. /// Several example programs are provided.
/// ///
/// Based on data in http://elinux.org/RPi_Low-level_peripherals and /// Based on data in http://elinux.org/RPi_Low-level_peripherals and
/// http://www.raspberrypi.org/wp-content/uploads/2012/02/BCM2835-ARM-Peripherals.pdf /// http://www.raspberrypi.org/wp-content/uploads/2012/02/BCM2835-ARM-Peripherals.pdf
/// and http://www.scribd.com/doc/101830961/GPIO-Pads-Control2 /// and http://www.scribd.com/doc/101830961/GPIO-Pads-Control2
/// ///
/// You can also find online help and discussion at http://groups.google.com/group/bcm2835 /// You can also find online help and discussion at http://groups.google.com/group/bcm2835
/// Please use that group for all questions and discussions on this topic. /// Please use that group for all questions and discussions on this topic.
/// Do not contact the author directly, unless it is to discuss commercial licensing. /// Do not contact the author directly, unless it is to discuss commercial licensing.
/// ///
/// Tested on debian6-19-04-2012, 2012-07-15-wheezy-raspbian, 2013-07-26-wheezy-raspbian /// Tested on debian6-19-04-2012, 2012-07-15-wheezy-raspbian, 2013-07-26-wheezy-raspbian
/// and Occidentalisv01 /// and Occidentalisv01
/// CAUTION: it has been observed that when detect enables such as bcm2835_gpio_len() /// CAUTION: it has been observed that when detect enables such as bcm2835_gpio_len()
/// are used and the pin is pulled LOW /// are used and the pin is pulled LOW
/// it can cause temporary hangs on 2012-07-15-wheezy-raspbian, 2013-07-26-wheezy-raspbian /// it can cause temporary hangs on 2012-07-15-wheezy-raspbian, 2013-07-26-wheezy-raspbian
/// and Occidentalisv01. /// and Occidentalisv01.
/// Reason for this is not yet determined, but we suspect that an interrupt handler is /// Reason for this is not yet determined, but we suspect that an interrupt handler is
/// hitting a hard loop on those OSs. /// hitting a hard loop on those OSs.
/// If you must use bcm2835_gpio_len() and friends, make sure you disable the pins with /// If you must use bcm2835_gpio_len() and friends, make sure you disable the pins with
/// bcm2835_gpio_clr_len() and friends after use. /// bcm2835_gpio_clr_len() and friends after use.
/// ///
/// \par Installation /// \par Installation
/// ///
@@ -71,10 +71,10 @@
/// ///
/// \par Physical Addresses /// \par Physical Addresses
/// ///
/// The functions bcm2835_peri_read(), bcm2835_peri_write() and bcm2835_peri_set_bits() /// The functions bcm2835_peri_read(), bcm2835_peri_write() and bcm2835_peri_set_bits()
/// are low level peripheral register access functions. They are designed to use /// are low level peripheral register access functions. They are designed to use
/// physical addresses as described in section 1.2.3 ARM physical addresses /// physical addresses as described in section 1.2.3 ARM physical addresses
/// of the BCM2835 ARM Peripherals manual. /// of the BCM2835 ARM Peripherals manual.
/// Physical addresses range from 0x20000000 to 0x20FFFFFF for peripherals. The bus /// Physical addresses range from 0x20000000 to 0x20FFFFFF for peripherals. The bus
/// addresses for peripherals are set up to map onto the peripheral bus address range starting at /// addresses for peripherals are set up to map onto the peripheral bus address range starting at
/// 0x7E000000. Thus a peripheral advertised in the manual at bus address 0x7Ennnnnn is available at /// 0x7E000000. Thus a peripheral advertised in the manual at bus address 0x7Ennnnnn is available at
@@ -93,37 +93,37 @@
/// ///
/// \par Pin Numbering /// \par Pin Numbering
/// ///
/// The GPIO pin numbering as used by RPi is different to and inconsistent with the underlying /// The GPIO pin numbering as used by RPi is different to and inconsistent with the underlying
/// BCM 2835 chip pin numbering. http://elinux.org/RPi_BCM2835_GPIOs /// BCM 2835 chip pin numbering. http://elinux.org/RPi_BCM2835_GPIOs
/// ///
/// RPi has a 26 pin IDE header that provides access to some of the GPIO pins on the BCM 2835, /// RPi has a 26 pin IDE header that provides access to some of the GPIO pins on the BCM 2835,
/// as well as power and ground pins. Not all GPIO pins on the BCM 2835 are available on the /// as well as power and ground pins. Not all GPIO pins on the BCM 2835 are available on the
/// IDE header. /// IDE header.
/// ///
/// RPi Version 2 also has a P5 connector with 4 GPIO pins, 5V, 3.3V and Gnd. /// RPi Version 2 also has a P5 connector with 4 GPIO pins, 5V, 3.3V and Gnd.
/// ///
/// The functions in this library are designed to be passed the BCM 2835 GPIO pin number and _not_ /// The functions in this library are designed to be passed the BCM 2835 GPIO pin number and _not_
/// the RPi pin number. There are symbolic definitions for each of the available pins /// the RPi pin number. There are symbolic definitions for each of the available pins
/// that you should use for convenience. See \ref RPiGPIOPin. /// that you should use for convenience. See \ref RPiGPIOPin.
/// ///
/// \par SPI Pins /// \par SPI Pins
/// ///
/// The bcm2835_spi_* functions allow you to control the BCM 2835 SPI0 interface, /// The bcm2835_spi_* functions allow you to control the BCM 2835 SPI0 interface,
/// allowing you to send and received data by SPI (Serial Peripheral Interface). /// allowing you to send and received data by SPI (Serial Peripheral Interface).
/// For more information about SPI, see http://en.wikipedia.org/wiki/Serial_Peripheral_Interface_Bus /// For more information about SPI, see http://en.wikipedia.org/wiki/Serial_Peripheral_Interface_Bus
/// ///
/// When bcm2835_spi_begin() is called it changes the bahaviour of the SPI interface pins from their /// When bcm2835_spi_begin() is called it changes the bahaviour of the SPI interface pins from their
/// default GPIO behaviour in order to support SPI. While SPI is in use, you will not be able /// default GPIO behaviour in order to support SPI. While SPI is in use, you will not be able
/// to control the state of the SPI pins through the usual bcm2835_spi_gpio_write(). /// to control the state of the SPI pins through the usual bcm2835_spi_gpio_write().
/// When bcm2835_spi_end() is called, the SPI pins will all revert to inputs, and can then be /// When bcm2835_spi_end() is called, the SPI pins will all revert to inputs, and can then be
/// configured and controled with the usual bcm2835_gpio_* calls. /// configured and controled with the usual bcm2835_gpio_* calls.
/// ///
/// The Raspberry Pi GPIO pins used for SPI are: /// The Raspberry Pi GPIO pins used for SPI are:
/// ///
/// - P1-19 (MOSI) /// - P1-19 (MOSI)
/// - P1-21 (MISO) /// - P1-21 (MISO)
/// - P1-23 (CLK) /// - P1-23 (CLK)
/// - P1-24 (CE0) /// - P1-24 (CE0)
/// - P1-26 (CE1) /// - P1-26 (CE1)
/// ///
/// \par I2C Pins /// \par I2C Pins
@@ -139,10 +139,10 @@
/// ///
/// \par PWM /// \par PWM
/// ///
/// The BCM2835 supports hardware PWM on a limited subset of GPIO pins. This bcm2835 library provides /// The BCM2835 supports hardware PWM on a limited subset of GPIO pins. This bcm2835 library provides
/// functions for configuring and controlling PWM output on these pins. /// functions for configuring and controlling PWM output on these pins.
/// ///
/// The BCM2835 contains 2 independent PWM channels (0 and 1), each of which be connnected to a limited subset of /// The BCM2835 contains 2 independent PWM channels (0 and 1), each of which be connnected to a limited subset of
/// GPIO pins. The following GPIO pins may be connected to the following PWM channels (from section 9.5): /// GPIO pins. The following GPIO pins may be connected to the following PWM channels (from section 9.5):
/// \code /// \code
/// GPIO PIN RPi pin PWM Channel ALT FUN /// GPIO PIN RPi pin PWM Channel ALT FUN
@@ -161,34 +161,34 @@
/// on the IO headers, and therefore this is the only IO pin on the RPi that can be used for PWM. /// on the IO headers, and therefore this is the only IO pin on the RPi that can be used for PWM.
/// Further it must be set to ALT FUN 5 to get PWM output. /// Further it must be set to ALT FUN 5 to get PWM output.
/// ///
/// Both PWM channels are driven by the same PWM clock, whose clock dvider can be varied using /// Both PWM channels are driven by the same PWM clock, whose clock dvider can be varied using
/// bcm2835_pwm_set_clock(). Each channel can be separately enabled with bcm2835_pwm_set_mode(). /// bcm2835_pwm_set_clock(). Each channel can be separately enabled with bcm2835_pwm_set_mode().
/// The average output of the PWM channel is determined by the ratio of DATA/RANGE for that channel. /// The average output of the PWM channel is determined by the ratio of DATA/RANGE for that channel.
/// Use bcm2835_pwm_set_range() to set the range and bcm2835_pwm_set_data() to set the data in that ratio /// Use bcm2835_pwm_set_range() to set the range and bcm2835_pwm_set_data() to set the data in that ratio
/// ///
/// Each PWM channel can run in either Balanced or Mark-Space mode. In Balanced mode, the hardware /// Each PWM channel can run in either Balanced or Mark-Space mode. In Balanced mode, the hardware
/// sends a combination of clock pulses that results in an overall DATA pulses per RANGE pulses. /// sends a combination of clock pulses that results in an overall DATA pulses per RANGE pulses.
/// In Mark-Space mode, the hardware sets the output HIGH for DATA clock pulses wide, followed by /// In Mark-Space mode, the hardware sets the output HIGH for DATA clock pulses wide, followed by
/// LOW for RANGE-DATA clock pulses. /// LOW for RANGE-DATA clock pulses.
/// ///
/// The PWM clock can be set to control the PWM pulse widths. The PWM clock is derived from /// The PWM clock can be set to control the PWM pulse widths. The PWM clock is derived from
/// a 19.2MHz clock. You can set any divider, but some common ones are provided by the BCM2835_PWM_CLOCK_DIVIDER_* /// a 19.2MHz clock. You can set any divider, but some common ones are provided by the BCM2835_PWM_CLOCK_DIVIDER_*
/// values of \ref bcm2835PWMClockDivider. /// values of \ref bcm2835PWMClockDivider.
/// ///
/// For example, say you wanted to drive a DC motor with PWM at about 1kHz, /// For example, say you wanted to drive a DC motor with PWM at about 1kHz,
/// and control the speed in 1/1024 increments from /// and control the speed in 1/1024 increments from
/// 0/1024 (stopped) through to 1024/1024 (full on). In that case you might set the /// 0/1024 (stopped) through to 1024/1024 (full on). In that case you might set the
/// clock divider to be 16, and the RANGE to 1024. The pulse repetition frequency will be /// clock divider to be 16, and the RANGE to 1024. The pulse repetition frequency will be
/// 1.2MHz/1024 = 1171.875Hz. /// 1.2MHz/1024 = 1171.875Hz.
/// ///
/// \par Real Time performance constraints /// \par Real Time performance constraints
/// ///
/// The bcm2835 is a library for user programs (i.e. they run in 'userland'). /// The bcm2835 is a library for user programs (i.e. they run in 'userland').
/// Such programs are not part of the kernel and are usually /// Such programs are not part of the kernel and are usually
/// subject to paging and swapping by the kernel while it does other things besides running your program. /// subject to paging and swapping by the kernel while it does other things besides running your program.
/// This means that you should not expect to get real-time performance or /// This means that you should not expect to get real-time performance or
/// real-time timing constraints from such programs. In particular, there is no guarantee that the /// real-time timing constraints from such programs. In particular, there is no guarantee that the
/// bcm2835_delay() and bcm2835_delayMicroseconds() will return after exactly the time requested. /// bcm2835_delay() and bcm2835_delayMicroseconds() will return after exactly the time requested.
/// In fact, depending on other activity on the host, IO etc, you might get significantly longer delay times /// In fact, depending on other activity on the host, IO etc, you might get significantly longer delay times
/// than the one you asked for. So please dont expect to get exactly the time delay you request. /// than the one you asked for. So please dont expect to get exactly the time delay you request.
/// ///
@@ -208,9 +208,9 @@
/// http://search.cpan.org/~mikem/Device-BCM2835-1.9/lib/Device/BCM2835.pm /// http://search.cpan.org/~mikem/Device-BCM2835-1.9/lib/Device/BCM2835.pm
/// Matthew Baker has kindly made Python bindings available at: /// Matthew Baker has kindly made Python bindings available at:
/// https://github.com/mubeta06/py-libbcm2835 /// https://github.com/mubeta06/py-libbcm2835
/// Gary Marks has created a Serial Peripheral Interface (SPI) command-line utility /// Gary Marks has created a Serial Peripheral Interface (SPI) command-line utility
/// for Raspberry Pi, based on the bcm2835 library. The /// for Raspberry Pi, based on the bcm2835 library. The
/// utility, spincl, is licensed under Open Source GNU GPLv3 by iP Solutions (http://ipsolutionscorp.com), as a /// utility, spincl, is licensed under Open Source GNU GPLv3 by iP Solutions (http://ipsolutionscorp.com), as a
/// free download with source included: http://ipsolutionscorp.com/raspberry-pi-spi-utility/ /// free download with source included: http://ipsolutionscorp.com/raspberry-pi-spi-utility/
/// ///
/// \par Open Source Licensing GPL V2 /// \par Open Source Licensing GPL V2
@@ -226,7 +226,7 @@
/// ///
/// Some of this code has been inspired by Dom and Gert. /// Some of this code has been inspired by Dom and Gert.
/// The I2C code has been inspired by Alan Barr. /// The I2C code has been inspired by Alan Barr.
/// ///
/// \par Revision History /// \par Revision History
/// ///
/// \version 1.0 Initial release /// \version 1.0 Initial release
@@ -237,15 +237,15 @@
/// \version 1.5 Added bcm2835_close() to deinit the library. Suggested by C?sar Ortiz /// \version 1.5 Added bcm2835_close() to deinit the library. Suggested by C?sar Ortiz
/// \version 1.6 Document testing on 2012-07-15-wheezy-raspbian and Occidentalisv01 /// \version 1.6 Document testing on 2012-07-15-wheezy-raspbian and Occidentalisv01
/// Functions bcm2835_gpio_ren(), bcm2835_gpio_fen(), bcm2835_gpio_hen() /// Functions bcm2835_gpio_ren(), bcm2835_gpio_fen(), bcm2835_gpio_hen()
/// bcm2835_gpio_len(), bcm2835_gpio_aren() and bcm2835_gpio_afen() now /// bcm2835_gpio_len(), bcm2835_gpio_aren() and bcm2835_gpio_afen() now
/// changes only the pin specified. Other pins that were already previously /// changes only the pin specified. Other pins that were already previously
/// enabled stay enabled. /// enabled stay enabled.
/// Added bcm2835_gpio_clr_ren(), bcm2835_gpio_clr_fen(), bcm2835_gpio_clr_hen() /// Added bcm2835_gpio_clr_ren(), bcm2835_gpio_clr_fen(), bcm2835_gpio_clr_hen()
/// bcm2835_gpio_clr_len(), bcm2835_gpio_clr_aren(), bcm2835_gpio_clr_afen() /// bcm2835_gpio_clr_len(), bcm2835_gpio_clr_aren(), bcm2835_gpio_clr_afen()
/// to clear the enable for individual pins, suggested by Andreas Sundstrom. /// to clear the enable for individual pins, suggested by Andreas Sundstrom.
/// \version 1.7 Added bcm2835_spi_transfernb to support different buffers for read and write. /// \version 1.7 Added bcm2835_spi_transfernb to support different buffers for read and write.
/// \version 1.8 Improvements to read barrier, as suggested by maddin. /// \version 1.8 Improvements to read barrier, as suggested by maddin.
/// \version 1.9 Improvements contributed by mikew: /// \version 1.9 Improvements contributed by mikew:
/// I noticed that it was mallocing memory for the mmaps on /dev/mem. /// I noticed that it was mallocing memory for the mmaps on /dev/mem.
/// It's not necessary to do that, you can just mmap the file directly, /// It's not necessary to do that, you can just mmap the file directly,
/// so I've removed the mallocs (and frees). /// so I've removed the mallocs (and frees).
@@ -259,40 +259,40 @@
/// http://www.scribd.com/doc/101830961/GPIO-Pads-Control2 /// http://www.scribd.com/doc/101830961/GPIO-Pads-Control2
/// Also added a define for the passwrd value that Gert says is needed to /// Also added a define for the passwrd value that Gert says is needed to
/// change pad control settings. /// change pad control settings.
/// \version 1.10 Changed the names of the delay functions to bcm2835_delay() /// \version 1.10 Changed the names of the delay functions to bcm2835_delay()
/// and bcm2835_delayMicroseconds() to prevent collisions with wiringPi. /// and bcm2835_delayMicroseconds() to prevent collisions with wiringPi.
/// Macros to map delay()-> bcm2835_delay() and /// Macros to map delay()-> bcm2835_delay() and
/// Macros to map delayMicroseconds()-> bcm2835_delayMicroseconds(), which /// Macros to map delayMicroseconds()-> bcm2835_delayMicroseconds(), which
/// can be disabled by defining BCM2835_NO_DELAY_COMPATIBILITY /// can be disabled by defining BCM2835_NO_DELAY_COMPATIBILITY
/// \version 1.11 Fixed incorrect link to download file /// \version 1.11 Fixed incorrect link to download file
/// \version 1.12 New GPIO pin definitions for RPi version 2 (which has a different GPIO mapping) /// \version 1.12 New GPIO pin definitions for RPi version 2 (which has a different GPIO mapping)
/// \version 1.13 New GPIO pin definitions for RPi version 2 plug P5 /// \version 1.13 New GPIO pin definitions for RPi version 2 plug P5
/// Hardware base pointers are now available (after initialisation) externally as bcm2835_gpio /// Hardware base pointers are now available (after initialisation) externally as bcm2835_gpio
/// bcm2835_pwm bcm2835_clk bcm2835_pads bcm2835_spi0. /// bcm2835_pwm bcm2835_clk bcm2835_pads bcm2835_spi0.
/// \version 1.14 Now compiles even if CLOCK_MONOTONIC_RAW is not available, uses CLOCK_MONOTONIC instead. /// \version 1.14 Now compiles even if CLOCK_MONOTONIC_RAW is not available, uses CLOCK_MONOTONIC instead.
/// Fixed errors in documentation of SPI divider frequencies based on 250MHz clock. /// Fixed errors in documentation of SPI divider frequencies based on 250MHz clock.
/// Reported by Ben Simpson. /// Reported by Ben Simpson.
/// \version 1.15 Added bcm2835_close() to end of examples as suggested by Mark Wolfe. /// \version 1.15 Added bcm2835_close() to end of examples as suggested by Mark Wolfe.
/// \version 1.16 Added bcm2835_gpio_set_multi, bcm2835_gpio_clr_multi and bcm2835_gpio_write_multi /// \version 1.16 Added bcm2835_gpio_set_multi, bcm2835_gpio_clr_multi and bcm2835_gpio_write_multi
/// to allow a mask of pins to be set all at once. Requested by Sebastian Loncar. /// to allow a mask of pins to be set all at once. Requested by Sebastian Loncar.
/// \version 1.17 Added bcm2835_gpio_write_mask. Requested by Sebastian Loncar. /// \version 1.17 Added bcm2835_gpio_write_mask. Requested by Sebastian Loncar.
/// \version 1.18 Added bcm2835_i2c_* functions. Changes to bcm2835_delayMicroseconds: /// \version 1.18 Added bcm2835_i2c_* functions. Changes to bcm2835_delayMicroseconds:
/// now uses the RPi system timer counter, instead of clock_gettime, for improved accuracy. /// now uses the RPi system timer counter, instead of clock_gettime, for improved accuracy.
/// No need to link with -lrt now. Contributed by Arjan van Vught. /// No need to link with -lrt now. Contributed by Arjan van Vught.
/// \version 1.19 Removed inlines added by previous patch since they don't seem to work everywhere. /// \version 1.19 Removed inlines added by previous patch since they don't seem to work everywhere.
/// Reported by olly. /// Reported by olly.
/// \version 1.20 Patch from Mark Dootson to close /dev/mem after access to the peripherals has been granted. /// \version 1.20 Patch from Mark Dootson to close /dev/mem after access to the peripherals has been granted.
/// \version 1.21 delayMicroseconds is now not susceptible to 32 bit timer overruns. /// \version 1.21 delayMicroseconds is now not susceptible to 32 bit timer overruns.
/// Patch courtesy Jeremy Mortis. /// Patch courtesy Jeremy Mortis.
/// \version 1.22 Fixed incorrect definition of BCM2835_GPFEN0 which broke the ability to set /// \version 1.22 Fixed incorrect definition of BCM2835_GPFEN0 which broke the ability to set
/// falling edge events. Reported by Mark Dootson. /// falling edge events. Reported by Mark Dootson.
/// \version 1.23 Added bcm2835_i2c_set_baudrate and bcm2835_i2c_read_register_rs. /// \version 1.23 Added bcm2835_i2c_set_baudrate and bcm2835_i2c_read_register_rs.
/// Improvements to bcm2835_i2c_read and bcm2835_i2c_write functions /// Improvements to bcm2835_i2c_read and bcm2835_i2c_write functions
/// to fix ocasional reads not completing. Patched by Mark Dootson. /// to fix ocasional reads not completing. Patched by Mark Dootson.
/// \version 1.24 Mark Dootson p[atched a problem with his previously submitted code /// \version 1.24 Mark Dootson p[atched a problem with his previously submitted code
/// under high load from other processes. /// under high load from other processes.
/// \version 1.25 Updated author and distribution location details to airspayce.com /// \version 1.25 Updated author and distribution location details to airspayce.com
/// \version 1.26 Added missing unmapmem for pads in bcm2835_close to prevent a memory leak. /// \version 1.26 Added missing unmapmem for pads in bcm2835_close to prevent a memory leak.
/// Reported by Hartmut Henkel. /// Reported by Hartmut Henkel.
/// \version 1.27 bcm2835_gpio_set_pad() no longer needs BCM2835_PAD_PASSWRD: it is /// \version 1.27 bcm2835_gpio_set_pad() no longer needs BCM2835_PAD_PASSWRD: it is
/// now automatically included. /// now automatically included.
@@ -303,11 +303,11 @@
/// \version 1.30 10 microsecond delays from bcm2835_spi_transfer and bcm2835_spi_transfern for /// \version 1.30 10 microsecond delays from bcm2835_spi_transfer and bcm2835_spi_transfern for
/// significant performance improvements, Patch by Alan Watson. /// significant performance improvements, Patch by Alan Watson.
/// \version 1.31 Fix a GCC warning about dummy variable, patched by Alan Watson. Thanks. /// \version 1.31 Fix a GCC warning about dummy variable, patched by Alan Watson. Thanks.
/// \version 1.32 Added option I2C_V1 definition to compile for version 1 RPi. /// \version 1.32 Added option I2C_V1 definition to compile for version 1 RPi.
/// By default I2C code is generated for the V2 RPi which has SDA1 and SCL1 connected. /// By default I2C code is generated for the V2 RPi which has SDA1 and SCL1 connected.
/// Contributed by Malcolm Wiles based on work by Arvi Govindaraj. /// Contributed by Malcolm Wiles based on work by Arvi Govindaraj.
/// \version 1.33 Added command line utilities i2c and gpio to examples. Contributed by Shahrooz Shahparnia. /// \version 1.33 Added command line utilities i2c and gpio to examples. Contributed by Shahrooz Shahparnia.
/// \version 1.34 Added bcm2835_i2c_write_read_rs() which writes an arbitrary number of bytes, /// \version 1.34 Added bcm2835_i2c_write_read_rs() which writes an arbitrary number of bytes,
/// sends a repeat start, and reads from the device. Contributed by Eduardo Steinhorst. /// sends a repeat start, and reads from the device. Contributed by Eduardo Steinhorst.
/// \version 1.35 Fix build errors when compiled under Qt. Also performance improvements with SPI transfers. Contributed by Udo Klaas. /// \version 1.35 Fix build errors when compiled under Qt. Also performance improvements with SPI transfers. Contributed by Udo Klaas.
/// \version 1.36 Make automake's test runner detect that we're skipping tests when not root, the second /// \version 1.36 Make automake's test runner detect that we're skipping tests when not root, the second
@@ -539,7 +539,7 @@ typedef enum
} RPiGPIOPin; } RPiGPIOPin;
// Defines for SPI // Defines for SPI
// GPIO register offsets from BCM2835_SPI0_BASE. // GPIO register offsets from BCM2835_SPI0_BASE.
// Offsets into the SPI Peripheral block in bytes per 10.5 SPI Register Map // Offsets into the SPI Peripheral block in bytes per 10.5 SPI Register Map
#define BCM2835_SPI0_CS 0x0000 ///< SPI Master Control and Status #define BCM2835_SPI0_CS 0x0000 ///< SPI Master Control and Status
#define BCM2835_SPI0_FIFO 0x0004 ///< SPI Master TX and RX FIFOs #define BCM2835_SPI0_FIFO 0x0004 ///< SPI Master TX and RX FIFOs
@@ -570,8 +570,8 @@ typedef enum
#define BCM2835_SPI0_CS_TA 0x00000080 ///< Transfer Active #define BCM2835_SPI0_CS_TA 0x00000080 ///< Transfer Active
#define BCM2835_SPI0_CS_CSPOL 0x00000040 ///< Chip Select Polarity #define BCM2835_SPI0_CS_CSPOL 0x00000040 ///< Chip Select Polarity
#define BCM2835_SPI0_CS_CLEAR 0x00000030 ///< Clear FIFO Clear RX and TX #define BCM2835_SPI0_CS_CLEAR 0x00000030 ///< Clear FIFO Clear RX and TX
#define BCM2835_SPI0_CS_CLEAR_RX 0x00000020 ///< Clear FIFO Clear RX #define BCM2835_SPI0_CS_CLEAR_RX 0x00000020 ///< Clear FIFO Clear RX
#define BCM2835_SPI0_CS_CLEAR_TX 0x00000010 ///< Clear FIFO Clear TX #define BCM2835_SPI0_CS_CLEAR_TX 0x00000010 ///< Clear FIFO Clear TX
#define BCM2835_SPI0_CS_CPOL 0x00000008 ///< Clock Polarity #define BCM2835_SPI0_CS_CPOL 0x00000008 ///< Clock Polarity
#define BCM2835_SPI0_CS_CPHA 0x00000004 ///< Clock Phase #define BCM2835_SPI0_CS_CPHA 0x00000004 ///< Clock Phase
#define BCM2835_SPI0_CS_CS 0x00000003 ///< Chip Select #define BCM2835_SPI0_CS_CS 0x00000003 ///< Chip Select
@@ -597,13 +597,13 @@ typedef enum
/// \brief bcm2835SPIChipSelect /// \brief bcm2835SPIChipSelect
/// Specify the SPI chip select pin(s) /// Specify the SPI chip select pin(s)
typedef enum typedef enum
{ {
// Can also use non-standard pins with this lib // Can also use non-standard pins with this lib
BCM2835_SPI_CS0 = 0, ///< Chip Select 0 BCM2835_SPI_CS0 = 0, ///< Chip Select 0
BCM2835_SPI_CS1 = 1, ///< Chip Select 1 BCM2835_SPI_CS1 = 1, ///< Chip Select 1
BCM2835_SPI_CS2 = 2, ///< Chip Select 2 (ie pins CS1 and CS2 are asserted) BCM2835_SPI_CS2 = 2, ///< Chip Select 2 (ie pins CS1 and CS2 are asserted)
BCM2835_SPI_CS_NONE = 3, ///< No CS, control it yourself BCM2835_SPI_CS_NONE = 3, ///< No CS, control it yourself
// Only GPIO > 3 can be used (to not interfere with the previous value just above ) // Only GPIO > 3 can be used (to not interfere with the previous value just above )
// Lucky we have plenty of theese pins // Lucky we have plenty of theese pins
BCM2835_SPI_CS_GPIO4 = RPI_V2_GPIO_P1_07, /// BCM GPIO 4 BCM2835_SPI_CS_GPIO4 = RPI_V2_GPIO_P1_07, /// BCM GPIO 4
@@ -617,7 +617,7 @@ typedef enum
BCM2835_SPI_CS_GPIO29 = RPI_V2_GPIO_P5_04, /// BCM GPIO 29 BCM2835_SPI_CS_GPIO29 = RPI_V2_GPIO_P5_04, /// BCM GPIO 29
BCM2835_SPI_CS_GPIO30 = RPI_V2_GPIO_P5_05, /// BCM GPIO 30 BCM2835_SPI_CS_GPIO30 = RPI_V2_GPIO_P5_05, /// BCM GPIO 30
BCM2835_SPI_CS_GPIO31 = RPI_V2_GPIO_P5_06, /// BCM GPIO 31 BCM2835_SPI_CS_GPIO31 = RPI_V2_GPIO_P5_06, /// BCM GPIO 31
} bcm2835SPIChipSelect; } bcm2835SPIChipSelect;
/// \brief bcm2835SPIClockDivider /// \brief bcm2835SPIClockDivider
@@ -812,11 +812,11 @@ extern "C" {
/// These functions allow you to intialise and control the bcm2835 library /// These functions allow you to intialise and control the bcm2835 library
/// @{ /// @{
/// Initialise the library by opening /dev/mem and getting pointers to the /// Initialise the library by opening /dev/mem and getting pointers to the
/// internal memory for BCM 2835 device registers. You must call this (successfully) /// internal memory for BCM 2835 device registers. You must call this (successfully)
/// before calling any other /// before calling any other
/// functions in this library (except bcm2835_set_debug). /// functions in this library (except bcm2835_set_debug).
/// If bcm2835_init() fails by returning 0, /// If bcm2835_init() fails by returning 0,
/// calling any other function may result in crashes or other failures. /// calling any other function may result in crashes or other failures.
/// Prints messages to stderr in case of errors. /// Prints messages to stderr in case of errors.
/// \return 1 if successful else 0 /// \return 1 if successful else 0
@@ -838,12 +838,12 @@ extern "C" {
/// \defgroup lowlevel Low level register access /// \defgroup lowlevel Low level register access
/// These functions provide low level register access, and should not generally /// These functions provide low level register access, and should not generally
/// need to be used /// need to be used
/// ///
/// @{ /// @{
/// Reads 32 bit value from a peripheral address /// Reads 32 bit value from a peripheral address
/// The read is done twice, and is therefore always safe in terms of /// The read is done twice, and is therefore always safe in terms of
/// manual section 1.3 Peripheral access precautions for correct memory ordering /// manual section 1.3 Peripheral access precautions for correct memory ordering
/// \param[in] paddr Physical address to read from. See BCM2835_GPIO_BASE etc. /// \param[in] paddr Physical address to read from. See BCM2835_GPIO_BASE etc.
/// \return the value read from the 32 bit register /// \return the value read from the 32 bit register
@@ -861,7 +861,7 @@ extern "C" {
/// Writes 32 bit value from a peripheral address /// Writes 32 bit value from a peripheral address
/// The write is done twice, and is therefore always safe in terms of /// The write is done twice, and is therefore always safe in terms of
/// manual section 1.3 Peripheral access precautions for correct memory ordering /// manual section 1.3 Peripheral access precautions for correct memory ordering
/// \param[in] paddr Physical address to read from. See BCM2835_GPIO_BASE etc. /// \param[in] paddr Physical address to read from. See BCM2835_GPIO_BASE etc.
/// \param[in] value The 32 bit value to write /// \param[in] value The 32 bit value to write
@@ -877,11 +877,11 @@ extern "C" {
extern void bcm2835_peri_write_nb(volatile uint32_t* paddr, uint32_t value); extern void bcm2835_peri_write_nb(volatile uint32_t* paddr, uint32_t value);
/// Alters a number of bits in a 32 peripheral regsiter. /// Alters a number of bits in a 32 peripheral regsiter.
/// It reads the current valu and then alters the bits deines as 1 in mask, /// It reads the current valu and then alters the bits deines as 1 in mask,
/// according to the bit value in value. /// according to the bit value in value.
/// All other bits that are 0 in the mask are unaffected. /// All other bits that are 0 in the mask are unaffected.
/// Use this to alter a subset of the bits in a register. /// Use this to alter a subset of the bits in a register.
/// The write is done twice, and is therefore always safe in terms of /// The write is done twice, and is therefore always safe in terms of
/// manual section 1.3 Peripheral access precautions for correct memory ordering /// manual section 1.3 Peripheral access precautions for correct memory ordering
/// \param[in] paddr Physical address to read from. See BCM2835_GPIO_BASE etc. /// \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] value The 32 bit value to write, masked in by mask.
@@ -891,7 +891,7 @@ extern "C" {
/// @} // end of lowlevel /// @} // end of lowlevel
/// \defgroup gpio GPIO register access /// \defgroup gpio GPIO register access
/// These functions allow you to control the GPIO interface. You can set the /// 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. /// function of each GPIO pin, read the input state and set the output state.
/// @{ /// @{
@@ -901,31 +901,31 @@ extern "C" {
/// \param[in] mode Mode to set the pin to, one of BCM2835_GPIO_FSEL_* from \ref bcm2835FunctionSelect /// \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); extern void bcm2835_gpio_fsel(uint8_t pin, uint8_t mode);
/// Sets the specified pin output to /// Sets the specified pin output to
/// HIGH. /// HIGH.
/// \param[in] pin GPIO number, or one of RPI_GPIO_P1_* from \ref RPiGPIOPin. /// \param[in] pin GPIO number, or one of RPI_GPIO_P1_* from \ref RPiGPIOPin.
/// \sa bcm2835_gpio_write() /// \sa bcm2835_gpio_write()
extern void bcm2835_gpio_set(uint8_t pin); extern void bcm2835_gpio_set(uint8_t pin);
/// Sets the specified pin output to /// Sets the specified pin output to
/// LOW. /// LOW.
/// \param[in] pin GPIO number, or one of RPI_GPIO_P1_* from \ref RPiGPIOPin. /// \param[in] pin GPIO number, or one of RPI_GPIO_P1_* from \ref RPiGPIOPin.
/// \sa bcm2835_gpio_write() /// \sa bcm2835_gpio_write()
extern void bcm2835_gpio_clr(uint8_t pin); extern void bcm2835_gpio_clr(uint8_t pin);
/// Sets any of the first 32 GPIO output pins specified in the mask to /// Sets any of the first 32 GPIO output pins specified in the mask to
/// HIGH. /// HIGH.
/// \param[in] mask Mask of pins to affect. Use 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)
/// \sa bcm2835_gpio_write_multi() /// \sa bcm2835_gpio_write_multi()
extern void bcm2835_gpio_set_multi(uint32_t mask); extern void bcm2835_gpio_set_multi(uint32_t mask);
/// Sets any of the first 32 GPIO output pins specified in the mask to /// Sets any of the first 32 GPIO output pins specified in the mask to
/// LOW. /// LOW.
/// \param[in] mask Mask of pins to affect. Use 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)
/// \sa bcm2835_gpio_write_multi() /// \sa bcm2835_gpio_write_multi()
extern void bcm2835_gpio_clr_multi(uint32_t mask); extern void bcm2835_gpio_clr_multi(uint32_t mask);
/// Reads the current level on the specified /// Reads the current level on the specified
/// pin and returns either HIGH or LOW. Works whether or not the pin /// pin and returns either HIGH or LOW. Works whether or not the pin
/// is an input or an output. /// is an input or an output.
/// \param[in] pin GPIO number, or one of RPI_GPIO_P1_* from \ref RPiGPIOPin. /// \param[in] pin GPIO number, or one of RPI_GPIO_P1_* from \ref RPiGPIOPin.
@@ -934,14 +934,14 @@ extern "C" {
/// Event Detect Status. /// Event Detect Status.
/// Tests whether the specified pin has detected a level or edge /// Tests whether the specified pin has detected a level or edge
/// as requested by bcm2835_gpio_ren(), bcm2835_gpio_fen(), bcm2835_gpio_hen(), /// as requested by bcm2835_gpio_ren(), bcm2835_gpio_fen(), bcm2835_gpio_hen(),
/// bcm2835_gpio_len(), bcm2835_gpio_aren(), bcm2835_gpio_afen(). /// bcm2835_gpio_len(), bcm2835_gpio_aren(), bcm2835_gpio_afen().
/// Clear the flag for a given pin by calling bcm2835_gpio_set_eds(pin); /// 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. /// \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. /// \return HIGH if the event detect status for the given pin is true.
extern uint8_t bcm2835_gpio_eds(uint8_t pin); extern uint8_t bcm2835_gpio_eds(uint8_t pin);
/// Sets the Event Detect Status register for a given pin to 1, /// Sets the Event Detect Status register for a given pin to 1,
/// which has the effect of clearing the flag. Use this afer seeing /// which has the effect of clearing the flag. Use this afer seeing
/// an Event Detect Status on the pin. /// an Event Detect Status on the pin.
/// \param[in] pin GPIO number, or one of RPI_GPIO_P1_* from \ref RPiGPIOPin. /// \param[in] pin GPIO number, or one of RPI_GPIO_P1_* from \ref RPiGPIOPin.
@@ -1022,8 +1022,8 @@ extern "C" {
/// Clocks the Pull-up/down value set earlier by bcm2835_gpio_pud() into the pin. /// 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] 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. /// \param[in] on HIGH to clock the value from bcm2835_gpio_pud() into the pin.
/// LOW to remove the clock. /// LOW to remove the clock.
/// \sa bcm2835_gpio_set_pud() /// \sa bcm2835_gpio_set_pud()
extern void bcm2835_gpio_pudclk(uint8_t pin, uint8_t on); extern void bcm2835_gpio_pudclk(uint8_t pin, uint8_t on);
@@ -1034,7 +1034,7 @@ extern "C" {
/// Sets the Pad Control for the given GPIO group. /// Sets the Pad Control for the given GPIO group.
/// \param[in] group The GPIO pad group number, one of BCM2835_PAD_GROUP_GPIO_* /// \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 /// \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 /// that it is not necessary to include BCM2835_PAD_PASSWRD in the mask as this
/// is automatically included. /// is automatically included.
extern void bcm2835_gpio_set_pad(uint8_t group, uint32_t control); extern void bcm2835_gpio_set_pad(uint8_t group, uint32_t control);
@@ -1042,9 +1042,9 @@ extern "C" {
/// Delays for the specified number of milliseconds. /// Delays for the specified number of milliseconds.
/// Uses nanosleep(), and therefore does not use CPU until the time is up. /// 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(): /// 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 /// If the interval specified in req is not an exact multiple of the granularity
/// underlying clock (see time(7)), then the interval will be /// underlying clock (see time(7)), then the interval will be
/// rounded up to the next multiple. Furthermore, after the sleep completes, /// rounded up to the next multiple. Furthermore, after the sleep completes,
/// there may still be a delay before the CPU becomes free to once /// there may still be a delay before the CPU becomes free to once
/// again execute the calling thread. /// again execute the calling thread.
/// \param[in] millis Delay in milliseconds /// \param[in] millis Delay in milliseconds
@@ -1053,9 +1053,9 @@ extern "C" {
/// Delays for the specified number of microseconds. /// Delays for the specified number of microseconds.
/// Uses a combination of nanosleep() and a busy wait loop on the BCM2835 system timers, /// 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(): /// 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 /// If the interval specified in req is not an exact multiple of the granularity
/// underlying clock (see time(7)), then the interval will be /// underlying clock (see time(7)), then the interval will be
/// rounded up to the next multiple. Furthermore, after the sleep completes, /// rounded up to the next multiple. Furthermore, after the sleep completes,
/// there may still be a delay before the CPU becomes free to once /// there may still be a delay before the CPU becomes free to once
/// again execute the calling thread. /// again execute the calling thread.
/// For times less than about 450 microseconds, uses a busy wait on the System Timer. /// For times less than about 450 microseconds, uses a busy wait on the System Timer.
@@ -1063,7 +1063,7 @@ extern "C" {
/// result in a delay of about 80 microseconds. Your mileage may vary. /// result in a delay of about 80 microseconds. Your mileage may vary.
/// \param[in] micros Delay in microseconds /// \param[in] micros Delay in microseconds
extern void bcm2835_delayMicroseconds (uint64_t micros); extern void bcm2835_delayMicroseconds (uint64_t micros);
/// Indicate the number of milliseconds since startup of PI /// Indicate the number of milliseconds since startup of PI
/// This function is like the Arduino millis function /// This function is like the Arduino millis function
/// \return Number of milliseconds /// \return Number of milliseconds
@@ -1090,24 +1090,24 @@ extern "C" {
/// \param[in] pud The desired Pull-up/down mode. One of BCM2835_GPIO_PUD_* from bcm2835PUDControl /// \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); extern void bcm2835_gpio_set_pud(uint8_t pin, uint8_t pud);
/// @} /// @}
/// \defgroup spi SPI access /// \defgroup spi SPI access
/// These functions let you use SPI0 (Serial Peripheral Interface) to /// These functions let you use SPI0 (Serial Peripheral Interface) to
/// interface with an external SPI device. /// interface with an external SPI device.
/// @{ /// @{
/// Start SPI operations. /// Start SPI operations.
/// Forces RPi SPI0 pins P1-19 (MOSI), P1-21 (MISO), P1-23 (CLK), P1-24 (CE0) and P1-26 (CE1) /// 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. /// to alternate function ALT0, which enables those pins for SPI interface.
/// \param[in] cs Specifies the CS pins(s) that are used to activate the desired slave. /// \param[in] cs Specifies the CS pins(s) that are used to activate the desired slave.
/// One of BCM2835_SPI_CS*, see \ref bcm2835SPIChipSelect /// One of BCM2835_SPI_CS*, see \ref bcm2835SPIChipSelect
/// or one of One of BCM2835_SPI_CS*, see \ref bcm2835SPIChipSelect /// or one of One of BCM2835_SPI_CS*, see \ref bcm2835SPIChipSelect
/// by default PI hardware driven using CE0 /// by default PI hardware driven using CE0
/// You should call bcm2835_spi_end() when all SPI funcitons are complete to return the pins to /// You should call bcm2835_spi_end() when all SPI funcitons are complete to return the pins to
/// their default functions /// their default functions
/// \sa bcm2835_spi_end() /// \sa bcm2835_spi_end()
extern void bcm2835_spi_begin(uint8_t cs); extern void bcm2835_spi_begin();
/// End SPI operations. /// End SPI operations.
/// SPI0 pins P1-19 (MOSI), P1-21 (MISO), P1-23 (CLK), P1-24 (CE0) and P1-26 (CE1) /// SPI0 pins P1-19 (MOSI), P1-21 (MISO), P1-23 (CLK), P1-24 (CE0) and P1-26 (CE1)
@@ -1115,64 +1115,64 @@ extern "C" {
extern void bcm2835_spi_end(void); extern void bcm2835_spi_end(void);
/// Sets the SPI custom Chip Select pin to correct level /// Sets the SPI custom Chip Select pin to correct level
/// Defaults to /// Defaults to
/// \param[in] level The desired level, LOW or HIGH, /// \param[in] level The desired level, LOW or HIGH,
extern void bcm2835_spi_setChipSelect(uint8_t level); extern void bcm2835_spi_setChipSelect(uint8_t level);
/// Sets the SPI bit order /// Sets the SPI bit order
/// NOTE: has no effect. Not supported by SPI0. /// NOTE: has no effect. Not supported by SPI0.
/// Defaults to /// Defaults to
/// \param[in] order The desired bit order, one of BCM2835_SPI_BIT_ORDER_*, /// \param[in] order The desired bit order, one of BCM2835_SPI_BIT_ORDER_*,
/// see \ref bcm2835SPIBitOrder /// see \ref bcm2835SPIBitOrder
extern void bcm2835_spi_setBitOrder(uint8_t order); extern void bcm2835_spi_setBitOrder(uint8_t order);
/// Sets the SPI clock divider and therefore the /// Sets the SPI clock divider and therefore the
/// SPI clock speed. /// SPI clock speed.
/// \param[in] divider The desired SPI clock divider, one of BCM2835_SPI_CLOCK_DIVIDER_*, /// \param[in] divider The desired SPI clock divider, one of BCM2835_SPI_CLOCK_DIVIDER_*,
/// see \ref bcm2835SPIClockDivider /// see \ref bcm2835SPIClockDivider
extern void bcm2835_spi_setClockDivider(uint16_t divider); extern void bcm2835_spi_setClockDivider(uint16_t divider);
/// Sets the SPI data mode /// Sets the SPI data mode
/// Sets the clock polariy and phase /// Sets the clock polariy and phase
/// \param[in] mode The desired data mode, one of BCM2835_SPI_MODE*, /// \param[in] mode The desired data mode, one of BCM2835_SPI_MODE*,
/// see \ref bcm2835SPIMode /// see \ref bcm2835SPIMode
extern void bcm2835_spi_setDataMode(uint8_t mode); extern void bcm2835_spi_setDataMode(uint8_t mode);
/// Sets the chip select pin(s) /// Sets the chip select pin(s)
/// When an bcm2835_spi_transfer() is made, the selected pin(s) will be asserted during the /// When an bcm2835_spi_transfer() is made, the selected pin(s) will be asserted during the
/// transfer. /// transfer.
/// \param[in] cs Specifies the CS pins(s) that are used to activate the desired slave. /// \param[in] cs Specifies the CS pins(s) that are used to activate the desired slave.
/// One of BCM2835_SPI_CS*, see \ref bcm2835SPIChipSelect /// One of BCM2835_SPI_CS*, see \ref bcm2835SPIChipSelect
/// or one of One of BCM2835_SPI_CS*, see \ref bcm2835SPIChipSelect /// or one of One of BCM2835_SPI_CS*, see \ref bcm2835SPIChipSelect
extern void bcm2835_spi_chipSelect(uint8_t cs); extern void bcm2835_spi_chipSelect(uint8_t cs);
/// Sets the chip select pin polarity for a given pin /// Sets the chip select pin polarity for a given pin
/// When an bcm2835_spi_transfer() occurs, the currently selected chip select pin(s) /// When an bcm2835_spi_transfer() occurs, the currently selected chip select pin(s)
/// will be asserted to the /// will be asserted to the
/// value given by active. When transfers are not happening, the chip select pin(s) /// value given by active. When transfers are not happening, the chip select pin(s)
/// return to the complement (inactive) value. /// return to the complement (inactive) value.
/// \param[in] cs The chip select pin to affect /// \param[in] cs The chip select pin to affect
/// \param[in] active Whether the chip select pin is to be active HIGH /// \param[in] active Whether the chip select pin is to be active HIGH
extern void bcm2835_spi_setChipSelectPolarity(uint8_t cs, uint8_t active); extern void bcm2835_spi_setChipSelectPolarity(uint8_t cs, uint8_t active);
/// Transfers one byte to and from the currently selected SPI slave. /// Transfers one byte to and from the currently selected SPI slave.
/// Asserts the currently selected CS pins (as previously set by bcm2835_spi_chipSelect) /// Asserts the currently selected CS pins (as previously set by bcm2835_spi_chipSelect)
/// during the transfer. /// during the transfer.
/// Clocks the 8 bit value out on MOSI, and simultaneously clocks in data from MISO. /// Clocks the 8 bit value out on MOSI, and simultaneously clocks in data from MISO.
/// Returns the read data byte from the slave. /// Returns the read data byte from the slave.
/// Uses polled transfer as per section 10.6.1 of the BCM 2835 ARM Peripherls manual /// 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 /// \param[in] value The 8 bit data byte to write to MOSI
/// \return The 8 bit byte simultaneously read from MISO /// \return The 8 bit byte simultaneously read from MISO
/// \sa bcm2835_spi_transfern() /// \sa bcm2835_spi_transfern()
extern uint8_t bcm2835_spi_transfer(uint8_t value); extern uint8_t bcm2835_spi_transfer(uint8_t value);
/// Transfers any number of bytes to and from the currently selected SPI slave. /// 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) /// Asserts the currently selected CS pins (as previously set by bcm2835_spi_chipSelect)
/// during the transfer. /// during the transfer.
/// Clocks the len 8 bit bytes out on MOSI, and simultaneously clocks in data from MISO. /// 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 /// 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 /// 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[in] tbuf Buffer of bytes to send.
/// \param[out] rbuf Received bytes will by put in this buffer /// \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 /// \param[in] len Number of bytes in the tbuf buffer, and the number of bytes to send/received
/// \sa bcm2835_spi_transfer() /// \sa bcm2835_spi_transfer()
@@ -1284,7 +1284,7 @@ extern "C" {
/// \param[in] micros Delay in microseconds /// \param[in] micros Delay in microseconds
extern void bcm2835_st_delay(uint64_t offset_micros, uint64_t micros); extern void bcm2835_st_delay(uint64_t offset_micros, uint64_t micros);
/// @} /// @}
/// \defgroup pwm Pulse Width Modulation /// \defgroup pwm Pulse Width Modulation
/// Allows control of 2 independent PWM channels. A limited subset of GPIO pins /// Allows control of 2 independent PWM channels. A limited subset of GPIO pins
@@ -1293,12 +1293,12 @@ extern "C" {
/// documentation on the Main Page. /// documentation on the Main Page.
/// @{ /// @{
/// Sets the PWM clock divisor, /// Sets the PWM clock divisor,
/// to control the basic PWM pulse widths. /// to control the basic PWM pulse widths.
/// \param[in] divisor Divides the basic 19.2MHz PWM clock. You can use one of the common /// \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 /// values BCM2835_PWM_CLOCK_DIVIDER_* in \ref bcm2835PWMClockDivider
extern void bcm2835_pwm_set_clock(uint32_t divisor); extern void bcm2835_pwm_set_clock(uint32_t divisor);
/// Sets the mode of the given PWM channel, /// Sets the mode of the given PWM channel,
/// allowing you to control the PWM mode and enable/disable that channel /// allowing you to control the PWM mode and enable/disable that channel
/// \param[in] channel The PWM channel. 0 or 1. /// \param[in] channel The PWM channel. 0 or 1.
@@ -1311,15 +1311,15 @@ extern "C" {
/// \param[in] channel The PWM channel. 0 or 1. /// \param[in] channel The PWM channel. 0 or 1.
/// \param[in] range The maximum value permitted for DATA. /// \param[in] range The maximum value permitted for DATA.
extern void bcm2835_pwm_set_range(uint8_t channel, uint32_t range); extern void bcm2835_pwm_set_range(uint8_t channel, uint32_t range);
/// Sets the PWM pulse ratio to emit to DATA/RANGE, /// Sets the PWM pulse ratio to emit to DATA/RANGE,
/// where RANGE is set by bcm2835_pwm_set_range(). /// where RANGE is set by bcm2835_pwm_set_range().
/// \param[in] channel The PWM channel. 0 or 1. /// \param[in] channel The PWM channel. 0 or 1.
/// \param[in] data Controls the PWM output ratio as a fraction of the range. /// \param[in] data Controls the PWM output ratio as a fraction of the range.
/// Can vary from 0 to RANGE. /// Can vary from 0 to RANGE.
extern void bcm2835_pwm_set_data(uint8_t channel, uint32_t data); extern void bcm2835_pwm_set_data(uint8_t channel, uint32_t data);
/// @} /// @}
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif
@@ -1345,9 +1345,9 @@ extern "C" {
/// Shows how to use PWM to control GPIO pins /// Shows how to use PWM to control GPIO pins
/// @example i2c.c /// @example i2c.c
/// Command line utility for executing i2c commands with the /// Command line utility for executing i2c commands with the
/// Broadcom bcm2835. Contributed by Shahrooz Shahparnia. /// Broadcom bcm2835. Contributed by Shahrooz Shahparnia.
/// example gpio.c /// example gpio.c
/// Command line utility for executing gpio commands with the /// Command line utility for executing gpio commands with the
/// Broadcom bcm2835. Contributed by Shahrooz Shahparnia. /// Broadcom bcm2835. Contributed by Shahrooz Shahparnia.
+4 -5
View File
@@ -32,15 +32,14 @@ using namespace std;
// CE Pin, CSN Pin, SPI Speed // CE Pin, CSN Pin, SPI Speed
// Setup for GPIO 22 CE and GPIO 25 CSN with SPI Speed @ 1Mhz // Setup for GPIO 22 CE and CE1 CSN with SPI Speed @ 1Mhz
//RF24 radio(RPI_V2_GPIO_P1_22, RPI_V2_GPIO_P1_18, BCM2835_SPI_SPEED_1MHZ); //RF24 radio(RPI_V2_GPIO_P1_22, RPI_V2_GPIO_P1_26, BCM2835_SPI_SPEED_1MHZ);
// Setup for GPIO 22 CE and CE0 CSN with SPI Speed @ 4Mhz // Setup for GPIO 22 CE and CE0 CSN with SPI Speed @ 4Mhz
//RF24 radio(RPI_V2_GPIO_P1_15, BCM2835_SPI_CS0, BCM2835_SPI_SPEED_4MHZ); //RF24 radio(RPI_V2_GPIO_P1_15, BCM2835_SPI_CS0, BCM2835_SPI_SPEED_4MHZ);
// Setup for GPIO 22 CE and CE1 CSN with SPI Speed @ 8Mhz // Setup for GPIO 22 CE and CE0 CSN with SPI Speed @ 8Mhz
//RF24 radio(RPI_V2_GPIO_P1_15, RPI_V2_GPIO_P1_26, BCM2835_SPI_SPEED_8MHZ); RF24 radio(RPI_V2_GPIO_P1_15, RPI_V2_GPIO_P1_24, BCM2835_SPI_SPEED_8MHZ);
RF24 radio(RPI_V2_GPIO_P1_15,BCM2835_SPI_CS0, BCM2835_SPI_SPEED_8MHZ);
@@ -27,15 +27,14 @@ using namespace std;
// CE Pin, CSN Pin, SPI Speed // CE Pin, CSN Pin, SPI Speed
// Setup for GPIO 22 CE and GPIO 25 CSN with SPI Speed @ 1Mhz // Setup for GPIO 22 CE and CE1 CSN with SPI Speed @ 1Mhz
//RF24 radio(RPI_V2_GPIO_P1_22, RPI_V2_GPIO_P1_18, BCM2835_SPI_SPEED_1MHZ); //RF24 radio(RPI_V2_GPIO_P1_22, RPI_V2_GPIO_P1_26, BCM2835_SPI_SPEED_1MHZ);
// Setup for GPIO 22 CE and CE0 CSN with SPI Speed @ 4Mhz // Setup for GPIO 22 CE and CE0 CSN with SPI Speed @ 4Mhz
//RF24 radio(RPI_V2_GPIO_P1_15, BCM2835_SPI_CS0, BCM2835_SPI_SPEED_4MHZ); //RF24 radio(RPI_V2_GPIO_P1_15, BCM2835_SPI_CS0, BCM2835_SPI_SPEED_4MHZ);
// Setup for GPIO 22 CE and CE1 CSN with SPI Speed @ 8Mhz // Setup for GPIO 22 CE and CE0 CSN with SPI Speed @ 8Mhz
RF24 radio(RPI_V2_GPIO_P1_15, BCM2835_SPI_CS0, BCM2835_SPI_SPEED_8MHZ); 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. // Radio pipe addresses for the 2 nodes to communicate.
+10 -10
View File
@@ -3,9 +3,9 @@
*/ */
/** /**
* Example using Dynamic Payloads * Example using Dynamic Payloads
* *
* This is an example of how to use payloads of a varying (dynamic) size. * This is an example of how to use payloads of a varying (dynamic) size.
*/ */
#include <cstdlib> #include <cstdlib>
@@ -22,14 +22,14 @@ using namespace std;
// CE Pin, CSN Pin, SPI Speed // CE Pin, CSN Pin, SPI Speed
// Setup for GPIO 22 CE and GPIO 25 CSN with SPI Speed @ 1Mhz // Setup for GPIO 22 CE and CE1 CSN with SPI Speed @ 1Mhz
//RF24 radio(RPI_V2_GPIO_P1_22, RPI_V2_GPIO_P1_18, BCM2835_SPI_SPEED_1MHZ); //RF24 radio(RPI_V2_GPIO_P1_22, RPI_V2_GPIO_P1_26, BCM2835_SPI_SPEED_1MHZ);
// Setup for GPIO 22 CE and CE0 CSN with SPI Speed @ 4Mhz // Setup for GPIO 22 CE and CE0 CSN with SPI Speed @ 4Mhz
//RF24 radio(RPI_V2_GPIO_P1_15, BCM2835_SPI_CS0, BCM2835_SPI_SPEED_4MHZ); //RF24 radio(RPI_V2_GPIO_P1_15, BCM2835_SPI_CS0, BCM2835_SPI_SPEED_4MHZ);
// Setup for GPIO 22 CE and CE1 CSN with SPI Speed @ 8Mhz // Setup for GPIO 22 CE and CE0 CSN with SPI Speed @ 8Mhz
RF24 radio(RPI_V2_GPIO_P1_15, RPI_V2_GPIO_P1_26, BCM2835_SPI_SPEED_8MHZ); 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. // Radio pipe addresses for the 2 nodes to communicate.
@@ -47,7 +47,7 @@ char receive_payload[max_payload_size+1]; // +1 to allow room for a terminating
int main(int argc, char** argv){ int main(int argc, char** argv){
// Print preamble: // Print preamble:
printf("RF24/examples/pingpair_dyn/\n"); printf("RF24/examples/pingpair_dyn/\n");
@@ -65,7 +65,7 @@ int main(int argc, char** argv){
char myChar = {0}; char myChar = {0};
cout << "Choose a role: Enter 0 for receiver, 1 for transmitter (CTRL+C to exit) \n>"; cout << "Choose a role: Enter 0 for receiver, 1 for transmitter (CTRL+C to exit) \n>";
getline(cin,input); getline(cin,input);
if(input.length() == 1) { if(input.length() == 1) {
myChar = input[0]; myChar = input[0];
if(myChar == '0'){ if(myChar == '0'){
@@ -129,7 +129,7 @@ if (role == role_ping_out)
// Spew it // Spew it
printf("Got response size=%i value=%s\n\r",len,receive_payload); printf("Got response size=%i value=%s\n\r",len,receive_payload);
} }
// Update size for next time. // Update size for next time.
next_payload_size += payload_size_increments_by; next_payload_size += payload_size_increments_by;
if ( next_payload_size > max_payload_size ) if ( next_payload_size > max_payload_size )
+18 -18
View File
@@ -7,7 +7,7 @@ TMRh20 2014
*/ */
/** General Data Transfer Rate Test /** General Data Transfer Rate Test
* This example demonstrates basic data transfer functionality with the * This example demonstrates basic data transfer functionality with the
updated library. This example will display the transfer rates acheived using updated library. This example will display the transfer rates acheived using
the slower form of high-speed transfer using blocking-writes. the slower form of high-speed transfer using blocking-writes.
*/ */
@@ -26,14 +26,14 @@ using namespace std;
// CE Pin, CSN Pin, SPI Speed // CE Pin, CSN Pin, SPI Speed
// Setup for GPIO 22 CE and GPIO 25 CSN with SPI Speed @ 1Mhz // Setup for GPIO 22 CE and CE1 CSN with SPI Speed @ 1Mhz
//RF24 radio(RPI_V2_GPIO_P1_22, RPI_V2_GPIO_P1_18, BCM2835_SPI_SPEED_1MHZ); //RF24 radio(RPI_V2_GPIO_P1_22, RPI_V2_GPIO_P1_26, BCM2835_SPI_SPEED_1MHZ);
// Setup for GPIO 22 CE and CE0 CSN with SPI Speed @ 4Mhz // Setup for GPIO 22 CE and CE0 CSN with SPI Speed @ 4Mhz
//RF24 radio(RPI_V2_GPIO_P1_15, BCM2835_SPI_CS0, BCM2835_SPI_SPEED_4MHZ); //RF24 radio(RPI_V2_GPIO_P1_15, BCM2835_SPI_CS0, BCM2835_SPI_SPEED_4MHZ);
// Setup for GPIO 22 CE and CE1 CSN with SPI Speed @ 8Mhz // Setup for GPIO 22 CE and CE0 CSN with SPI Speed @ 8Mhz
RF24 radio(RPI_V2_GPIO_P1_15, RPI_V2_GPIO_P1_26, BCM2835_SPI_SPEED_8MHZ); RF24 radio(RPI_V2_GPIO_P1_15, RPI_V2_GPIO_P1_24, BCM2835_SPI_SPEED_8MHZ);
@@ -42,16 +42,16 @@ const uint64_t addresses[2] = { 0xABCDABCD71LL, 0x544d52687CLL };
bool role_ping_out = 1, role_pong_back = 0; bool role_ping_out = 1, role_pong_back = 0;
bool role = 0; bool role = 0;
uint8_t data[32]; uint8_t data[32];
unsigned long startTime, stopTime, counter, rxTimer=0; unsigned long startTime, stopTime, counter, rxTimer=0;
int main(int argc, char** argv){ int main(int argc, char** argv){
// Print preamble: // Print preamble:
printf("RF24/examples/Transfer/\n"); printf("RF24/examples/Transfer/\n");
radio.begin(); // Setup and configure rf radio radio.begin(); // Setup and configure rf radio
radio.setChannel(1); radio.setChannel(1);
radio.setPALevel(RF24_PA_MAX); radio.setPALevel(RF24_PA_MAX);
@@ -67,7 +67,7 @@ int main(int argc, char** argv){
char myChar = {0}; char myChar = {0};
cout << "Choose a role: Enter 0 for receiver, 1 for transmitter (CTRL+C to exit)\n>"; cout << "Choose a role: Enter 0 for receiver, 1 for transmitter (CTRL+C to exit)\n>";
getline(cin,input); getline(cin,input);
if(input.length() == 1) { if(input.length() == 1) {
myChar = input[0]; myChar = input[0];
if(myChar == '0'){ if(myChar == '0'){
@@ -86,8 +86,8 @@ int main(int argc, char** argv){
radio.openReadingPipe(1,addresses[0]); radio.openReadingPipe(1,addresses[0]);
radio.startListening(); radio.startListening();
} }
for(int i=0; i<32; i++){ for(int i=0; i<32; i++){
data[i] = rand() % 255; //Load the buffer with random data data[i] = rand() % 255; //Load the buffer with random data
} }
@@ -105,7 +105,7 @@ int main(int argc, char** argv){
for(int i=0; i<cycles; i++){ //Loop through a number of cycles 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 data[0] = i; //Change the first byte of the payload for identification
if(!radio.writeFast(&data,32)){ //Write to the FIFO buffers if(!radio.writeFast(&data,32)){ //Write to the FIFO buffers
counter++; //Keep count of failed payloads counter++; //Keep count of failed payloads
} }
} }
@@ -115,16 +115,16 @@ int main(int argc, char** argv){
float numBytes = cycles*32; float numBytes = cycles*32;
float rate = numBytes / (stopTime - startTime); float rate = numBytes / (stopTime - startTime);
printf("Transfer complete at %.2f KB/s \n\r",rate); printf("Transfer complete at %.2f KB/s \n\r",rate);
printf("%lu of %lu Packets Failed to Send\n\r",counter,cycles); printf("%lu of %lu Packets Failed to Send\n\r",counter,cycles);
counter = 0; counter = 0;
} }
if(role == role_pong_back){ if(role == role_pong_back){
while(radio.available()){ while(radio.available()){
radio.read(&data,32); radio.read(&data,32);
counter++; counter++;
} }
+17 -8
View File
@@ -75,24 +75,33 @@ Connection Info
Using pin 15/GPIO 22 for CE, pin 24/GPIO8 (CE0) for CSN Using pin 15/GPIO 22 for CE, pin 24/GPIO8 (CE0) for CSN
Can use either RPi CE0 or CE1 pins for radio CSN.
Choose any RPi output pin for radio CE pin.
**Constructor:** **Constructor:**
``` ```
RF24 radio(RPI_V2_GPIO_P1_15,BCM2835_SPI_CS0, BCM2835_SPI_SPEED_8MHZ); RF24 radio(RPI_V2_GPIO_P1_15,BCM2835_SPI_CS0, BCM2835_SPI_SPEED_8MHZ);
or
RF24 radio(RPI_V2_GPIO_P1_15,BCM2835_SPI_CS1, BCM2835_SPI_SPEED_8MHZ);
``` ```
**Pins:** **Pins:**
|NRF24L01 | RPI | P1 Connector | |NRF24L01 | RPI | P1 Connector |
|----- |----------- | -------------| |-----|-----------|-------------|
|VCC: | rpi-3v3 | (17) | | VCC | rpi-3v3 | (17) |
|GND: | rpi-gnd | (25) | | GND | rpi-gnd | (25) |
|CE: | rpi-gpio22 | (15) | | CE | rpi-gpio22 | (15) |
|CSN: | rpi-gpio8 | (24) | | CSN | rpi-gpio8 | (24) |
|SCK: | rpi-sckl | (23) | | SCK | rpi-sckl | (23) |
|MOSI: | rpi-mosi | (19) | | MOSI | rpi-mosi | (19) |
|MISO: | rpi-miso | (21) | | MISO | rpi-miso | (21) |
See http://www.airspayce.com/mikem/bcm2835/index.html for BCM2835 class documentation.
Note: The BCM library has been customized slightly to allow use of hardware CE pins not
in use for SPI, and to include a millis() function.
**************** ****************
+17 -8
View File
@@ -75,24 +75,33 @@ Connection Info
Using pin 15/GPIO 22 for CE, pin 24/GPIO8 (CE0) for CSN Using pin 15/GPIO 22 for CE, pin 24/GPIO8 (CE0) for CSN
Can use either RPi CE0 or CE1 pins for radio CSN.
Choose any RPi output pin for radio CE pin.
**Constructor:** **Constructor:**
``` ```
RF24 radio(RPI_V2_GPIO_P1_15,BCM2835_SPI_CS0, BCM2835_SPI_SPEED_8MHZ); RF24 radio(RPI_V2_GPIO_P1_15,BCM2835_SPI_CS0, BCM2835_SPI_SPEED_8MHZ);
or
RF24 radio(RPI_V2_GPIO_P1_15,BCM2835_SPI_CS1, BCM2835_SPI_SPEED_8MHZ);
``` ```
**Pins:** **Pins:**
|NRF24L01 | RPI | P1 Connector | |NRF24L01 | RPI | P1 Connector |
|----- |----------- | -------------| |-----|-----------|-------------|
|VCC: | rpi-3v3 | (17) | | VCC | rpi-3v3 | (17) |
|GND: | rpi-gnd | (25) | | GND | rpi-gnd | (25) |
|CE: | rpi-gpio22 | (15) | | CE | rpi-gpio22 | (15) |
|CSN: | rpi-gpio8 | (24) | | CSN | rpi-gpio8 | (24) |
|SCK: | rpi-sckl | (23) | | SCK | rpi-sckl | (23) |
|MOSI: | rpi-mosi | (19) | | MOSI | rpi-mosi | (19) |
|MISO: | rpi-miso | (21) | | MISO | rpi-miso | (21) |
See http://www.airspayce.com/mikem/bcm2835/index.html for BCM2835 class documentation.
Note: The BCM library has been customized slightly to allow use of hardware CE pins not
in use for SPI, and to include a millis() function.
**************** ****************