Commit 6530f954 authored by TMRh20's avatar TMRh20

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
parent cd8bb19d
......@@ -37,4 +37,5 @@ Supported Boards:
* Mega Types (2560, 1280, etc)
* ARM (Arduino Due) via extended SPI methods
* ATTiny 24/44/84 25/45/85
* Raspberry Pi
* See the [documentation](http://tmrh20.github.io/) for more info
\ No newline at end of file
......@@ -4,12 +4,12 @@
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
version 2 as published by the Free Software Foundation.
03/17/2013 : Charles-Henri Hallard (http://hallard.me)
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.
*/
......@@ -53,7 +53,7 @@ uint8_t RF24::read_register(uint8_t reg)
*ptx++ = ( R_REGISTER | ( REGISTER_MASK & reg ) );
*ptx++ = NOP ; // Dummy operation, just for reading
bcm2835_spi_transfernb( (char *) spi_txbuff, (char *) spi_rxbuff, 2);
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 = value ;
bcm2835_spi_transfernb( (char *) spi_txbuff, (char *) spi_rxbuff, 2);
status = *prx++; // status is 1st byte of receive buffer
if (debug)
if (debug)
printf("write_register(%02x,%02x)\r\n",reg,value);
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 * ptx = spi_txbuff;
uint8_t size = len + 1; // Add register value to transmit buffer
*ptx++ = ( W_REGISTER | ( REGISTER_MASK & reg ) );
while ( len-- )
*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);
status = *prx; // status is 1st byte of receive buffer
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 * prx = spi_rxbuff;
uint8_t * ptx = spi_txbuff;
uint8_t size ;
uint8_t size ;
const uint8_t* current = reinterpret_cast<const uint8_t*>(buf);
uint8_t data_len = min(len,payload_size);
uint8_t blank_len = dynamic_payloads_enabled ? 0 : payload_size - data_len;
size = data_len + blank_len + 1 ; // Add register value to transmit buffer
if (debug)
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-- )
*ptx++ = *current++;
while ( blank_len-- )
*ptx++ = 0;
*ptx++ = 0;
bcm2835_spi_transfernb( (char *) spi_txbuff, (char *) spi_rxbuff, size);
status = *prx; // status is 1st byte of receive buffer
return status;
}
......@@ -143,30 +143,30 @@ uint8_t RF24::read_payload(void* buf, uint8_t len)
uint8_t status;
uint8_t * prx = spi_rxbuff;
uint8_t * ptx = spi_txbuff;
uint8_t size ;
uint8_t size ;
uint8_t* current = reinterpret_cast<uint8_t*>(buf);
uint8_t data_len = min(len,payload_size);
uint8_t blank_len = dynamic_payloads_enabled ? 0 : payload_size - data_len;
size = data_len + blank_len + 1; // Add register value to transmit buffer
if (debug)
printf("[Reading %u bytes %u blanks]",data_len,blank_len);
*ptx++ = R_RX_PAYLOAD;
while(size--)
*ptx++ = NOP;
// Size has been lost during while, re affect
size = data_len + blank_len + 1; // Add register value to transmit buffer
bcm2835_spi_transfernb( (char *) spi_txbuff, (char *) spi_rxbuff, size);
// 1st byte is status
status = *prx++;
// Decrement before to skip 1st status byte
while ( --size )
*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):
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),
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_2[] = "PA_HIGH";
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_1,
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_2[] = "CE2 (PI Hardware Driven)";
static const char rf24_csn_e_str_3[] = "Custom GPIO Software Driven";
static const char * const rf24_csn_e_str_P[] = {
static const char * const rf24_csn_e_str_P[] = {
rf24_csn_e_str_0,
rf24_csn_e_str_1,
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]);
}
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" : "" );
}
printf("CE Pin \t = Custom GPIO%d\n", ce_pin );
// SPI Bus Speed
printf("Clock Speed\t = " );
switch (spi_speed)
......@@ -409,32 +409,45 @@ bool RF24::begin(void)
{
debug = false;
//debug = true;
// This initialize the SPI bus with
// csn pin as chip select (custom or not)
// Init BCM2835 chipset for talking with us
if (!bcm2835_init()){
return false;
}
// Initialise the CE pin of NRF24 (chip enable)
bcm2835_gpio_fsel(ce_pin, BCM2835_GPIO_FSEL_OUTP);
bcm2835_gpio_write(ce_pin, LOW);
switch(csn_pin){ //Ensure valid hardware CS pin
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
// bcm2835_gpio_fsel(GPIO_CTRL_PIN , BCM2835_GPIO_FSEL_OUTP);
// start the SPI library:
// Note the NRF24 wants mode 0, MSB first and default to 1 Mbps
bcm2835_spi_setBitOrder(BCM2835_SPI_BIT_ORDER_MSBFIRST);
bcm2835_spi_setDataMode(BCM2835_SPI_MODE0);
bcm2835_spi_setBitOrder(BCM2835_SPI_BIT_ORDER_MSBFIRST);
bcm2835_spi_setDataMode(BCM2835_SPI_MODE0);
// Set SPI bus Speed
bcm2835_spi_setClockDivider(spi_speed);
if(csn_pin <= BCM2835_SPI_CS_NONE){
bcm2835_spi_chipSelect(csn_pin);
}
// This initialize the SPI bus with
// csn pin as chip select (custom or not)
bcm2835_spi_begin(csn_pin);
// Choose hardware CSN pin
bcm2835_spi_chipSelect(csn_pin);
// Initialise the CE pin of NRF24 (chip enable) after the CSN pin, so that
// 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
delay(100);
......@@ -453,14 +466,14 @@ bool RF24::begin(void)
{
p_variant = true ;
}
// Then set the data rate to the slowest (and most reliable) speed supported by all
// hardware.
setDataRate( RF24_1MBPS ) ;
// Initialize CRC and request 2-byte (16bit) CRC
setCRCLength( RF24_CRC_16 ) ;
// Reset current status
// Notice reset and flush is the last thing we do
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 )
// PTX should use only 22uA of power
write_register(CONFIG, ( read_register(CONFIG) ) & ~_BV(PRIM_RX) );
return true;
}
......@@ -501,7 +514,7 @@ void RF24::startListening(void)
// Go!
bcm2835_gpio_write(ce_pin, HIGH);
// wait for the radio to come up (130us actually only needed)
//delayMicroseconds(130);
}
......@@ -514,7 +527,7 @@ void RF24::stopListening(void)
flush_tx();
flush_rx();
write_register(CONFIG, ( read_register(CONFIG) ) & ~_BV(PRIM_RX) );
}
/****************************************************************************/
......@@ -528,7 +541,7 @@ void RF24::powerDown(void)
/****************************************************************************/
void RF24::powerUp(void)
{
{
bool up = read_register(CONFIG) & _BV(PWR_UP);
if(! up ){
......@@ -536,7 +549,7 @@ void RF24::powerUp(void)
delay(5);
}
}
/******************************************************************/
......@@ -544,13 +557,13 @@ void RF24::powerUp(void)
bool RF24::write( const void* buf, uint8_t len, const bool multicast ){
// Begin the write
startWrite(buf,len, multicast);
startFastWrite(buf,len, multicast);
//Wait until complete or failed
// If this hangs, it ain't coming back, no sense in timing out
while( ! ( get_status() & ( _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);
......@@ -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 ){
return write(buf,len,0);
}
}
/****************************************************************************/
......@@ -600,7 +613,7 @@ bool RF24::writeBlocking( const void* buf, uint8_t len, uint32_t timeout )
void RF24::reUseTX(){
write_register(STATUS,_BV(MAX_RT) ); //Clear max retry flag
//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, HIGH);
}
......@@ -648,18 +661,18 @@ void RF24::startFastWrite( const void* buf, uint8_t len, const bool multicast){
bcm2835_gpio_write(ce_pin, HIGH);
}
/****************************************************************************/
void RF24::startWrite( const void* buf, uint8_t len, const bool multicast )
{
// 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, 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
if (!( read_register(FIFO_STATUS) & _BV(RX_EMPTY) )){
// If the caller wants the pipe number, include that
if ( pipe_num ){
......@@ -840,12 +853,12 @@ void RF24::toggle_features(void)
void RF24::enableDynamicPayloads(void)
{
// So enable them and try again
toggle_features();
write_register(FEATURE,read_register(FEATURE) | _BV(EN_DPL) );
if (debug)
if (debug)
printf("FEATURE=%i\r\n",read_register(FEATURE));
// 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 size ;
uint8_t size ;
const uint8_t* current = reinterpret_cast<const uint8_t*>(buf);
uint8_t data_len = min(len,payload_size);
size = data_len + 1 ; // Add register value to transmit buffer
if (debug){
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);
}
}
/****************************************************************************/
bool RF24::isAckPayloadAvailable(void)
......@@ -1053,7 +1066,7 @@ rf24_datarate_e RF24::getDataRate( void )
{
rf24_datarate_e result ;
uint8_t dr = read_register(RF_SETUP) & (_BV(RF_DR_LOW) | _BV(RF_DR_HIGH));
// switch uses RAM (evil!)
// Order matters in our case below
if ( dr == _BV(RF_DR_LOW) )
......@@ -1079,11 +1092,11 @@ rf24_datarate_e RF24::getDataRate( void )
void RF24::setCRCLength(rf24_crclength_e length)
{
uint8_t config = read_register(CONFIG) & ~( _BV(CRCO) | _BV(EN_CRC)) ;
// switch uses RAM (evil!)
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 )
{
......
......@@ -59,7 +59,7 @@ static uint8_t debug = 0;
static int i2c_byte_wait_us = 0;
// SPI Custom Chip Select Pin
static int spi_custom_cs = 0;
//static int spi_custom_cs = 0;
// Time for millis()
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)
{
struct timespec sleeper;
sleeper.tv_sec = (time_t)(millis / 1000);
sleeper.tv_nsec = (long)(millis % 1000) * 1000000;
nanosleep(&sleeper, NULL);
......@@ -376,18 +376,18 @@ void bcm2835_delayMicroseconds(uint64_t micros)
{
struct timespec t1;
uint64_t start;
// Calling nanosleep() takes at least 100-200 us, so use it for
// long waits and use a busy wait on the System Timer for the rest.
start = bcm2835_st_read();
if (micros > 450)
{
t1.tv_sec = 0;
t1.tv_nsec = 1000 * (long)(micros - 200);
nanosleep(&t1, NULL);
}
}
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);
}
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
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_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
volatile uint32_t* paddr = bcm2835_spi0 + BCM2835_SPI0_CS/4;
bcm2835_peri_write(paddr, 0); // All 0s
// Clear TX and RX fifos
bcm2835_peri_write_nb(paddr, BCM2835_SPI0_CS_CLEAR);
*/
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)
{
// Set all the SPI0 pins back to input
{
/* // Set all the SPI0 pins back to input
if (spi_custom_cs == 0)
{
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_19, BCM2835_GPIO_FSEL_INPT); // MOSI
bcm2835_gpio_fsel(RPI_GPIO_P1_23, BCM2835_GPIO_FSEL_INPT); // CLK
/*
*/
// Set all the SPI0 pins back to input
bcm2835_gpio_fsel(RPI_GPIO_P1_26, BCM2835_GPIO_FSEL_INPT); // CE1
bcm2835_gpio_fsel(RPI_GPIO_P1_24, BCM2835_GPIO_FSEL_INPT); // CE0
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_23, BCM2835_GPIO_FSEL_INPT); // CLK
*/
}
/*
// Drive Custom chip select pin
void bcm2835_spi_setChipSelect(uint8_t level)
{
// Do this only if we are using custom ChipSelect I/O
if ( spi_custom_cs > BCM2835_SPI_CS_NONE )
bcm2835_gpio_write(spi_custom_cs, level);
}
}*/
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* fifo = bcm2835_spi0 + BCM2835_SPI0_FIFO/4;
// Custom chip select LOW
if(spi_custom_cs > BCM2835_SPI_CS_NONE){
/*if(spi_custom_cs > BCM2835_SPI_CS_NONE){
bcm2835_spi_setChipSelect(LOW);
}
}*/
// This is Polled transfer as per section 10.6.1
// 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
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);
// Custom chip select HIGH
if(spi_custom_cs > BCM2835_SPI_CS_NONE){
bcm2835_spi_setChipSelect(HIGH);
}
//if(spi_custom_cs > BCM2835_SPI_CS_NONE){
// bcm2835_spi_setChipSelect(HIGH);
//}
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
// 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
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* fifo = bcm2835_spi0 + BCM2835_SPI0_FIFO/4;
if(spi_custom_cs > BCM2835_SPI_CS_NONE){
bcm2835_spi_setChipSelect(LOW);
}
//if(spi_custom_cs > BCM2835_SPI_CS_NONE){
// bcm2835_spi_setChipSelect(LOW);
//}
// This is Polled transfer as per section 10.6.1
// BUG ALERT: what happens if we get interupted in this section, and someone else
// accesses a different peripheral?
......@@ -715,15 +655,15 @@ void bcm2835_spi_writenb(char* tbuf, uint32_t len)
// Maybe wait for TXD
while (!(bcm2835_peri_read(paddr) & BCM2835_SPI0_CS_TXD))
;
// Write to FIFO, no barrier
bcm2835_peri_write_nb(fifo, tbuf[i]);
// Read from FIFO to prevent stalling
while (bcm2835_peri_read(paddr) & BCM2835_SPI0_CS_RXD)
(void) bcm2835_peri_read_nb(fifo);
}
// Wait for DONE to be set
while (!(bcm2835_peri_read_nb(paddr) & BCM2835_SPI0_CS_DONE)) {
while (bcm2835_peri_read(paddr) & BCM2835_SPI0_CS_RXD)
......@@ -732,10 +672,10 @@ void bcm2835_spi_writenb(char* tbuf, uint32_t len)
// Set TA = 0, and also set the barrier
bcm2835_peri_set_bits(paddr, 0, BCM2835_SPI0_CS_TA);
if(spi_custom_cs > BCM2835_SPI_CS_NONE){
bcm2835_spi_setChipSelect(HIGH);
}
//if(spi_custom_cs > BCM2835_SPI_CS_NONE){
// bcm2835_spi_setChipSelect(HIGH);
//}
}
// 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)
{
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
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
bcm2835_gpio_fsel(RPI_V2_GPIO_P1_03, BCM2835_GPIO_FSEL_ALT0); // SDA
bcm2835_gpio_fsel(RPI_V2_GPIO_P1_05, BCM2835_GPIO_FSEL_ALT0); // SCL
#endif
#endif
// Read the clock divider register
uint16_t cdiv = bcm2835_peri_read(paddr);
......@@ -800,7 +748,7 @@ void bcm2835_i2c_setSlaveAddress(uint8_t addr)
// Set I2C Device Address
#ifdef I2C_V1
volatile uint32_t* paddr = bcm2835_bsc0 + BCM2835_BSC_A/4;
#else
#else
volatile uint32_t* paddr = bcm2835_bsc1 + BCM2835_BSC_A/4;
#endif
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;
#else
volatile uint32_t* paddr = bcm2835_bsc1 + BCM2835_BSC_DIV/4;
#endif
#endif
bcm2835_peri_write(paddr, divider);
// Calculate time for transmitting one byte
// 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* status = bcm2835_bsc1 + BCM2835_BSC_S/4;
volatile uint32_t* control = bcm2835_bsc1 + BCM2835_BSC_C/4;
#endif
#endif
uint32_t remaining = len;
uint32_t i = 0;
......@@ -864,10 +812,10 @@ uint8_t bcm2835_i2c_write(const char * buf, uint32_t len)
i++;
remaining--;
}
// Enable device and start transfer
bcm2835_peri_write_nb(control, BCM2835_BSC_C_I2CEN | BCM2835_BSC_C_ST);
// Transfer is over when 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* status = bcm2835_bsc1 + BCM2835_BSC_S/4;
volatile uint32_t* control = bcm2835_bsc1 + BCM2835_BSC_C/4;
#endif
#endif
uint32_t remaining = len;
uint32_t i = 0;
......@@ -930,7 +878,7 @@ uint8_t bcm2835_i2c_read(char* buf, uint32_t len)
bcm2835_peri_write_nb(dlen, len);
// Start read
bcm2835_peri_write_nb(control, BCM2835_BSC_C_I2CEN | BCM2835_BSC_C_ST | BCM2835_BSC_C_READ);
// wait for transfer to complete
while (!(bcm2835_peri_read_nb(status) & BCM2835_BSC_S_DONE))
{
......@@ -943,7 +891,7 @@ uint8_t bcm2835_i2c_read(char* buf, uint32_t len)
remaining--;
}
}
// transfer has finished - grab any remaining stuff in FIFO
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++;
remaining--;
}
// Received a NACK
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
// the required register. Only works if your device supports this mode
uint8_t bcm2835_i2c_read_register_rs(char* regaddr, char* buf, uint32_t len)
{
{
#ifdef I2C_V1
volatile uint32_t* dlen = bcm2835_bsc0 + BCM2835_BSC_DLEN/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* status = bcm2835_bsc1 + BCM2835_BSC_S/4;
volatile uint32_t* control = bcm2835_bsc1 + BCM2835_BSC_C/4;
#endif
#endif
uint32_t remaining = len;
uint32_t i = 0;
uint8_t reason = BCM2835_I2C_REASON_OK;
// Clear FIFO
bcm2835_peri_set_bits(control, BCM2835_BSC_C_CLEAR_1 , BCM2835_BSC_C_CLEAR_1 );
// 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(fifo, regaddr[0]);
bcm2835_peri_write_nb(control, BCM2835_BSC_C_I2CEN | BCM2835_BSC_C_ST);
// poll for transfer has started
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)
break;
}
// Send a repeated start with read bit set in address
bcm2835_peri_write_nb(dlen, len);
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);
// wait for transfer to complete
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--;
}
}
// transfer has finished - grab any remaining stuff in FIFO
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++;
remaining--;
}
// Received a NACK
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;
}
// 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.
uint8_t bcm2835_i2c_write_read_rs(char* cmds, uint32_t cmds_len, char* buf, uint32_t buf_len)
{
{
#ifdef I2C_V1
volatile uint32_t* dlen = bcm2835_bsc0 + BCM2835_BSC_DLEN/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* status = bcm2835_bsc1 + BCM2835_BSC_S/4;
volatile uint32_t* control = bcm2835_bsc1 + BCM2835_BSC_C/4;
#endif
#endif
uint32_t remaining = cmds_len;
uint32_t i = 0;
uint8_t reason = BCM2835_I2C_REASON_OK;
// Clear FIFO
bcm2835_peri_set_bits(control, BCM2835_BSC_C_CLEAR_1 , BCM2835_BSC_C_CLEAR_1 );
......@@ -1094,7 +1042,7 @@ uint8_t bcm2835_i2c_write_read_rs(char* cmds, uint32_t cmds_len, char* buf, uint
// Set Data Length
bcm2835_peri_write_nb(dlen, cmds_len);
// pre populate FIFO with max buffer
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--;
}
// Enable device and start transfer
// Enable device and start transfer
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)
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)
break;
}
remaining = buf_len;
i = 0;
// Send a repeated start with read bit set in address
bcm2835_peri_write_nb(dlen, buf_len);
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));
// wait for transfer to complete
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--;
}
}
// transfer has finished - grab any remaining stuff in FIFO
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++;
remaining--;
}
// Received a NACK
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
// Wait for the clock to be not busy
while ((bcm2835_peri_read(bcm2835_clk + BCM2835_PWMCLK_CNTL) & 0x80) != 0)
bcm2835_delay(1);
bcm2835_delay(1);
// set the clock divider and enable PWM clock
bcm2835_peri_write(bcm2835_clk + BCM2835_PWMCLK_DIV, BCM2835_PWM_PASSWRD | (divisor << 12));
bcm2835_peri_write(bcm2835_clk + BCM2835_PWMCLK_CNTL, BCM2835_PWM_PASSWRD | 0x11); // Source=osc and enable
......@@ -1288,7 +1236,7 @@ int bcm2835_init(void)
{
struct timeval tv ;
if (debug)
if (debug)
{
bcm2835_pads = (uint32_t*)BCM2835_GPIO_PADS;
bcm2835_clk = (uint32_t*)BCM2835_CLOCK_BASE;
......@@ -1303,13 +1251,13 @@ int bcm2835_init(void)
int memfd = -1;
int ok = 0;
// 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",
strerror(errno)) ;
goto exit;
}
// GPIO:
bcm2835_gpio = (volatile uint32_t *)mapmem("gpio", BCM2835_BLOCK_SIZE, memfd, BCM2835_GPIO_BASE);
if (bcm2835_gpio == MAP_FAILED) goto exit;
......@@ -1321,10 +1269,10 @@ int bcm2835_init(void)
// Clock control (needed for PWM)
bcm2835_clk = (volatile uint32_t *)mapmem("clk", BCM2835_BLOCK_SIZE, memfd, BCM2835_CLOCK_BASE);
if (bcm2835_clk == MAP_FAILED) goto exit;
bcm2835_pads = (volatile uint32_t *)mapmem("pads", BCM2835_BLOCK_SIZE, memfd, BCM2835_GPIO_PADS);
if (bcm2835_pads == MAP_FAILED) goto exit;
bcm2835_spi0 = (volatile uint32_t *)mapmem("spi0", BCM2835_BLOCK_SIZE, memfd, BCM2835_SPI0_BASE);
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_pads, BCM2835_BLOCK_SIZE);
return 1; // Success
}
}
#ifdef BCM2835_TEST
// this is a simple test program that prints out what it will do rather than
// this is a simple test program that prints out what it will do rather than
// actually doing it
int main(int argc, char **argv)
{
......@@ -1398,13 +1346,13 @@ int main(int argc, char **argv)
{
// Turn it on
bcm2835_gpio_write(RPI_GPIO_P1_11, HIGH);
// wait a bit
bcm2835_delay(500);
// turn it off
bcm2835_gpio_write(RPI_GPIO_P1_11, LOW);
// wait a bit
bcm2835_delay(500);
}
......@@ -1417,7 +1365,7 @@ int main(int argc, char **argv)
// Read some data
uint8_t value = bcm2835_gpio_lev(RPI_GPIO_P1_15);
printf("read from pin 15: %d\n", value);
// wait a bit
bcm2835_delay(500);
}
......
......@@ -16,7 +16,7 @@
//
/// \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,
/// 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.
......@@ -25,34 +25,34 @@
/// and for accessing the system timers.
/// 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
/// any Linux-based distro (but clearly is no use except on Raspberry Pi or another board with
/// 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
/// 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
/// You can find the latest version at http://www.airspayce.com/mikem/bcm2835
///
/// 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
/// 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
/// 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.
///
/// Tested on debian6-19-04-2012, 2012-07-15-wheezy-raspbian, 2013-07-26-wheezy-raspbian
/// 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
/// it can cause temporary hangs on 2012-07-15-wheezy-raspbian, 2013-07-26-wheezy-raspbian
/// and Occidentalisv01.
/// Reason for this is not yet determined, but we suspect that an interrupt handler is
/// hitting a hard loop on those OSs.
/// If you must use bcm2835_gpio_len() and friends, make sure you disable the pins with
/// bcm2835_gpio_clr_len() and friends after use.
/// If you must use bcm2835_gpio_len() and friends, make sure you disable the pins with
/// bcm2835_gpio_clr_len() and friends after use.
///
/// \par Installation
///
......@@ -71,10 +71,10 @@
///
/// \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
/// 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
/// 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
......@@ -93,37 +93,37 @@
///
/// \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
///
///
/// 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.
///
/// 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
/// that you should use for convenience. See \ref RPiGPIOPin.
///
/// \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).
/// 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
/// default GPIO behaviour in order to support SPI. While SPI is in use, you will not be able
/// 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
/// 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
/// configured and controled with the usual bcm2835_gpio_* calls.
///
/// The Raspberry Pi GPIO pins used for SPI are:
///
///
/// - P1-19 (MOSI)
/// - P1-21 (MISO)
/// - P1-23 (CLK)
/// - P1-24 (CE0)
/// - P1-21 (MISO)
/// - P1-23 (CLK)
/// - P1-24 (CE0)
/// - P1-26 (CE1)
///
/// \par I2C Pins
......@@ -139,10 +139,10 @@
///
/// \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.
///
/// 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):
/// \code
/// 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.
/// 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().
/// 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
///
/// 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.
/// In Mark-Space mode, the hardware sets the output HIGH for DATA clock pulses wide, followed by
/// LOW for RANGE-DATA clock pulses.
/// In Mark-Space mode, the hardware sets the output HIGH for DATA clock pulses wide, followed by
/// 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_*
/// values of \ref bcm2835PWMClockDivider.
///
/// For example, say you wanted to drive a DC motor with PWM at about 1kHz,
/// 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
///
/// For example, say you wanted to drive a DC motor with PWM at about 1kHz,
/// 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
/// clock divider to be 16, and the RANGE to 1024. The pulse repetition frequency will be
/// 1.2MHz/1024 = 1171.875Hz.
///
/// \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
/// 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
/// 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.
/// 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
/// 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.
/// 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.
///
......@@ -208,9 +208,9 @@
/// http://search.cpan.org/~mikem/Device-BCM2835-1.9/lib/Device/BCM2835.pm
/// Matthew Baker has kindly made Python bindings available at:
/// https://github.com/mubeta06/py-libbcm2835
/// Gary Marks has created a Serial Peripheral Interface (SPI) command-line utility
/// 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
/// Gary Marks has created a Serial Peripheral Interface (SPI) command-line utility
/// 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
/// free download with source included: http://ipsolutionscorp.com/raspberry-pi-spi-utility/
///
/// \par Open Source Licensing GPL V2
......@@ -226,7 +226,7 @@
///
/// Some of this code has been inspired by Dom and Gert.
/// The I2C code has been inspired by Alan Barr.
///
///
/// \par Revision History
///
/// \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.6 Document testing on 2012-07-15-wheezy-raspbian and Occidentalisv01
/// 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
/// enabled stay enabled.
/// 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.
/// \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.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.
/// It's not necessary to do that, you can just mmap the file directly,
/// so I've removed the mallocs (and frees).
......@@ -259,40 +259,40 @@
/// http://www.scribd.com/doc/101830961/GPIO-Pads-Control2
/// Also added a define for the passwrd value that Gert says is needed to
/// 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.
/// Macros to map delay()-> bcm2835_delay() and
/// Macros to map delayMicroseconds()-> bcm2835_delayMicroseconds(), which
/// can be disabled by defining BCM2835_NO_DELAY_COMPATIBILITY
/// \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
/// Hardware base pointers are now available (after initialisation) externally as bcm2835_gpio
/// 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.
/// 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.
/// \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
/// 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.18 Added bcm2835_i2c_* functions. Changes to bcm2835_delayMicroseconds:
/// now uses the RPi system timer counter, instead of clock_gettime, for improved accuracy.
/// \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.
/// 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.
/// \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.
/// \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.
/// \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
/// to fix ocasional reads not completing. Patched by Mark Dootson.
/// \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.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.
/// \version 1.27 bcm2835_gpio_set_pad() no longer needs BCM2835_PAD_PASSWRD: it is
/// now automatically included.
......@@ -303,11 +303,11 @@
/// \version 1.30 10 microsecond delays from bcm2835_spi_transfer and bcm2835_spi_transfern for
/// significant performance improvements, Patch by Alan Watson.
/// \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.
/// 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.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.
/// \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
......@@ -539,7 +539,7 @@ typedef enum
} RPiGPIOPin;
// 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
#define BCM2835_SPI0_CS 0x0000 ///< SPI Master Control and Status
#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_CSPOL 0x00000040 ///< Chip Select Polarity
#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_TX 0x00000010 ///< Clear FIFO Clear TX
#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_CPOL 0x00000008 ///< Clock Polarity
#define BCM2835_SPI0_CS_CPHA 0x00000004 ///< Clock Phase
#define BCM2835_SPI0_CS_CS 0x00000003 ///< Chip Select
......@@ -597,13 +597,13 @@ typedef enum
/// \brief bcm2835SPIChipSelect
/// Specify the SPI chip select pin(s)
typedef enum
{
{
// Can also use non-standard pins with this lib
BCM2835_SPI_CS0 = 0, ///< Chip Select 0
BCM2835_SPI_CS1 = 1, ///< Chip Select 1
BCM2835_SPI_CS2 = 2, ///< Chip Select 2 (ie pins CS1 and CS2 are asserted)
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 )
// Lucky we have plenty of theese pins
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_GPIO30 = RPI_V2_GPIO_P5_05, /// BCM GPIO 30
BCM2835_SPI_CS_GPIO31 = RPI_V2_GPIO_P5_06, /// BCM GPIO 31
} bcm2835SPIChipSelect;
/// \brief bcm2835SPIClockDivider
......@@ -812,11 +812,11 @@ extern "C" {
/// 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)
/// before calling any other
/// functions in this library (except bcm2835_set_debug).
/// If bcm2835_init() fails by returning 0,
/// before calling any other
/// functions in this library (except bcm2835_set_debug).
/// If bcm2835_init() fails by returning 0,
/// calling any other function may result in crashes or other failures.
/// Prints messages to stderr in case of errors.
/// \return 1 if successful else 0
......@@ -838,12 +838,12 @@ extern "C" {
/// \defgroup lowlevel Low level register access
/// 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
/// 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
/// \param[in] paddr Physical address to read from. See BCM2835_GPIO_BASE etc.
/// \return the value read from the 32 bit register
......@@ -861,7 +861,7 @@ extern "C" {
/// 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
/// \param[in] paddr Physical address to read from. See BCM2835_GPIO_BASE etc.
/// \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);
/// 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,
/// according to the bit value in value.
/// It reads the current valu and then alters the bits deines as 1 in mask,
/// according to the bit value in value.
/// All other bits that are 0 in the mask are unaffected.
/// Use this to alter a subset of the bits in a register.
/// 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
/// \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.
......@@ -891,7 +891,7 @@ extern "C" {
/// @} // end of lowlevel
/// \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.
/// @{
......@@ -901,31 +901,31 @@ extern "C" {
/// \param[in] mode Mode to set the pin to, one of BCM2835_GPIO_FSEL_* from \ref bcm2835FunctionSelect
extern void bcm2835_gpio_fsel(uint8_t pin, uint8_t mode);
/// Sets the specified pin output to
/// Sets the specified pin output to
/// HIGH.
/// \param[in] pin GPIO number, or one of RPI_GPIO_P1_* from \ref RPiGPIOPin.
/// \sa bcm2835_gpio_write()
extern void bcm2835_gpio_set(uint8_t pin);
/// Sets the specified pin output to
/// Sets the specified pin output to
/// LOW.
/// \param[in] pin GPIO number, or one of RPI_GPIO_P1_* from \ref RPiGPIOPin.
/// \sa bcm2835_gpio_write()
extern void bcm2835_gpio_clr(uint8_t pin);
/// Sets any of the first 32 GPIO output pins specified in the mask to
/// Sets any of the first 32 GPIO output pins specified in the mask to
/// HIGH.
/// \param[in] mask Mask of pins to affect. Use eg: (1 << RPI_GPIO_P1_03) | (1 << RPI_GPIO_P1_05)
/// \sa bcm2835_gpio_write_multi()
extern void bcm2835_gpio_set_multi(uint32_t mask);
/// Sets any of the first 32 GPIO output pins specified in the mask to
/// Sets any of the first 32 GPIO output pins specified in the mask to
/// LOW.
/// \param[in] mask Mask of pins to affect. Use eg: (1 << RPI_GPIO_P1_03) | (1 << RPI_GPIO_P1_05)
/// \sa bcm2835_gpio_write_multi()
extern void bcm2835_gpio_clr_multi(uint32_t mask);
/// Reads the current level on the specified
/// Reads the current level on the specified
/// pin and returns either HIGH or LOW. Works whether or not the pin
/// is an input or an output.
/// \param[in] pin GPIO number, or one of RPI_GPIO_P1_* from \ref RPiGPIOPin.
......@@ -934,14 +934,14 @@ extern "C" {
/// Event Detect Status.
/// Tests whether the specified pin has detected a level or edge
/// as requested by bcm2835_gpio_ren(), bcm2835_gpio_fen(), bcm2835_gpio_hen(),
/// as requested by bcm2835_gpio_ren(), bcm2835_gpio_fen(), bcm2835_gpio_hen(),
/// bcm2835_gpio_len(), bcm2835_gpio_aren(), bcm2835_gpio_afen().
/// Clear the flag for a given pin by calling bcm2835_gpio_set_eds(pin);
/// \param[in] pin GPIO number, or one of RPI_GPIO_P1_* from \ref RPiGPIOPin.
/// \return HIGH if the event detect status for the given pin is true.
extern uint8_t bcm2835_gpio_eds(uint8_t pin);
/// 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
/// an Event Detect Status on the pin.
/// \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.
/// \param[in] pin GPIO number, or one of RPI_GPIO_P1_* from \ref RPiGPIOPin.
/// \param[in] on HIGH to clock the value from bcm2835_gpio_pud() into the pin.
/// LOW to remove the clock.
/// \param[in] on HIGH to clock the value from bcm2835_gpio_pud() into the pin.
/// LOW to remove the clock.
/// \sa bcm2835_gpio_set_pud()
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.
/// \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
/// is automatically included.
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.
/// Uses nanosleep(), and therefore does not use CPU until the time is up.
/// However, you are at the mercy of nanosleep(). From the manual for nanosleep():
/// If the interval specified in req is not an exact multiple of the granularity
/// If the interval specified in req is not an exact multiple of the granularity
/// underlying clock (see time(7)), then the interval will be
/// rounded up to the next multiple. Furthermore, after the sleep completes,
/// rounded up to the next multiple. Furthermore, after the sleep completes,
/// there may still be a delay before the CPU becomes free to once
/// again execute the calling thread.
/// \param[in] millis Delay in milliseconds
......@@ -1053,9 +1053,9 @@ extern "C" {
/// Delays for the specified number of microseconds.
/// Uses a combination of nanosleep() and a busy wait loop on the BCM2835 system timers,
/// However, you are at the mercy of nanosleep(). From the manual for nanosleep():
/// If the interval specified in req is not an exact multiple of the granularity
/// If the interval specified in req is not an exact multiple of the granularity
/// underlying clock (see time(7)), then the interval will be
/// rounded up to the next multiple. Furthermore, after the sleep completes,
/// rounded up to the next multiple. Furthermore, after the sleep completes,
/// there may still be a delay before the CPU becomes free to once
/// again execute the calling thread.
/// For times less than about 450 microseconds, uses a busy wait on the System Timer.
......@@ -1063,7 +1063,7 @@ extern "C" {
/// result in a delay of about 80 microseconds. Your mileage may vary.
/// \param[in] micros Delay in microseconds
extern void bcm2835_delayMicroseconds (uint64_t micros);
/// Indicate the number of milliseconds since startup of PI
/// This function is like the Arduino millis function
/// \return Number of milliseconds
......@@ -1090,24 +1090,24 @@ extern "C" {
/// \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);
/// @}
/// @}
/// \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.
/// @{
/// Start SPI operations.
/// Forces RPi SPI0 pins P1-19 (MOSI), P1-21 (MISO), P1-23 (CLK), P1-24 (CE0) and P1-26 (CE1)
/// to alternate function ALT0, which enables those pins for SPI interface.
/// \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
/// or one of One of BCM2835_SPI_CS*, see \ref bcm2835SPIChipSelect
/// by default PI hardware driven using CE0
/// You should call bcm2835_spi_end() when all SPI funcitons are complete to return the pins to
/// by default PI hardware driven using CE0
/// You should call bcm2835_spi_end() when all SPI funcitons are complete to return the pins to
/// their default functions
/// \sa bcm2835_spi_end()
extern void bcm2835_spi_begin(uint8_t cs);
extern void bcm2835_spi_begin();
/// End SPI operations.
/// 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);
/// Sets the SPI custom Chip Select pin to correct level
/// Defaults to
/// \param[in] level The desired level, LOW or HIGH,
/// Defaults to
/// \param[in] level The desired level, LOW or HIGH,
extern void bcm2835_spi_setChipSelect(uint8_t level);
/// Sets the SPI bit order
/// NOTE: has no effect. Not supported by SPI0.
/// Defaults to
/// \param[in] order The desired bit order, one of BCM2835_SPI_BIT_ORDER_*,
/// Defaults to
/// \param[in] order The desired bit order, one of BCM2835_SPI_BIT_ORDER_*,
/// see \ref bcm2835SPIBitOrder
extern void bcm2835_spi_setBitOrder(uint8_t order);
/// Sets the SPI clock divider and therefore the
/// SPI clock speed.
/// \param[in] divider The desired SPI clock divider, one of BCM2835_SPI_CLOCK_DIVIDER_*,
/// Sets the SPI clock divider and therefore the
/// SPI clock speed.
/// \param[in] divider The desired SPI clock divider, one of BCM2835_SPI_CLOCK_DIVIDER_*,
/// see \ref bcm2835SPIClockDivider
extern void bcm2835_spi_setClockDivider(uint16_t divider);
/// Sets the SPI data mode
/// 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
extern void bcm2835_spi_setDataMode(uint8_t mode);
/// Sets the chip select pin(s)
/// When an bcm2835_spi_transfer() is made, the selected pin(s) will be asserted during the
/// transfer.
/// \param[in] cs Specifies the CS pins(s) that are used to activate the desired slave.
/// \param[in] cs Specifies the CS pins(s) that are used to activate the desired slave.
/// 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);
/// Sets the chip select pin polarity for a given pin
/// When an bcm2835_spi_transfer() occurs, the currently selected chip select pin(s)
/// will be asserted to the
/// value given by active. When transfers are not happening, the chip select pin(s)
/// When an bcm2835_spi_transfer() occurs, the currently selected chip select pin(s)
/// will be asserted to the
/// value given by active. When transfers are not happening, the chip select pin(s)
/// return to the complement (inactive) value.
/// \param[in] cs The chip select pin to affect
/// \param[in] active Whether the chip select pin is to be active HIGH
extern void bcm2835_spi_setChipSelectPolarity(uint8_t cs, uint8_t active);
/// Transfers one byte to and from the currently selected SPI slave.
/// Asserts the currently selected CS pins (as previously set by bcm2835_spi_chipSelect)
/// Asserts the currently selected CS pins (as previously set by bcm2835_spi_chipSelect)
/// during the transfer.
/// Clocks the 8 bit value out on MOSI, and simultaneously clocks in data from MISO.
/// Clocks the 8 bit value out on MOSI, and simultaneously clocks in data from MISO.
/// Returns the read data byte from the slave.
/// Uses polled transfer as per section 10.6.1 of the BCM 2835 ARM Peripherls manual
/// \param[in] value The 8 bit data byte to write to MOSI
/// \return The 8 bit byte simultaneously read from MISO
/// \sa bcm2835_spi_transfern()
extern uint8_t bcm2835_spi_transfer(uint8_t value);
/// Transfers any number of bytes to and from the currently selected SPI slave.
/// Asserts the currently selected CS pins (as previously set by bcm2835_spi_chipSelect)
/// Asserts the currently selected CS pins (as previously set by bcm2835_spi_chipSelect)
/// during the transfer.
/// Clocks the len 8 bit bytes out on MOSI, and simultaneously clocks in data from MISO.
/// Clocks the len 8 bit bytes out on MOSI, and simultaneously clocks in data from MISO.
/// The data read read from the slave is placed into rbuf. rbuf must be at least len bytes long
/// Uses polled transfer as per section 10.6.1 of the BCM 2835 ARM Peripherls manual
/// \param[in] tbuf Buffer of bytes to send.
/// \param[in] tbuf Buffer of bytes to send.
/// \param[out] rbuf Received bytes will by put in this buffer
/// \param[in] len Number of bytes in the tbuf buffer, and the number of bytes to send/received
/// \sa bcm2835_spi_transfer()
......@@ -1284,7 +1284,7 @@ extern "C" {
/// \param[in] micros Delay in microseconds
extern void bcm2835_st_delay(uint64_t offset_micros, uint64_t micros);
/// @}
/// @}
/// \defgroup pwm Pulse Width Modulation
/// Allows control of 2 independent PWM channels. A limited subset of GPIO pins
......@@ -1293,12 +1293,12 @@ extern "C" {
/// documentation on the Main Page.
/// @{
/// Sets the PWM clock divisor,
/// Sets the PWM clock divisor,
/// to control the basic PWM pulse widths.
/// \param[in] divisor Divides the basic 19.2MHz PWM clock. You can use one of the common
/// values BCM2835_PWM_CLOCK_DIVIDER_* in \ref bcm2835PWMClockDivider
extern void bcm2835_pwm_set_clock(uint32_t divisor);
/// Sets the mode of the given PWM channel,
/// allowing you to control the PWM mode and enable/disable that channel
/// \param[in] channel The PWM channel. 0 or 1.
......@@ -1311,15 +1311,15 @@ extern "C" {
/// \param[in] channel The PWM channel. 0 or 1.
/// \param[in] range The maximum value permitted for DATA.
extern void bcm2835_pwm_set_range(uint8_t channel, uint32_t range);
/// Sets the PWM pulse ratio to emit to DATA/RANGE,
/// Sets the PWM pulse ratio to emit to DATA/RANGE,
/// where RANGE is set by bcm2835_pwm_set_range().
/// \param[in] channel The PWM channel. 0 or 1.
/// \param[in] data Controls the PWM output ratio as a fraction of the range.
/// \param[in] data Controls the PWM output ratio as a fraction of the range.
/// Can vary from 0 to RANGE.
extern void bcm2835_pwm_set_data(uint8_t channel, uint32_t data);
/// @}
/// @}
#ifdef __cplusplus
}
#endif
......@@ -1345,9 +1345,9 @@ extern "C" {
/// Shows how to use PWM to control GPIO pins
/// @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.
/// 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.
......@@ -32,15 +32,14 @@ using namespace std;
// CE Pin, CSN Pin, SPI Speed
// Setup for GPIO 22 CE and GPIO 25 CSN with SPI Speed @ 1Mhz
//RF24 radio(RPI_V2_GPIO_P1_22, RPI_V2_GPIO_P1_18, BCM2835_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_26, BCM2835_SPI_SPEED_1MHZ);
// 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);
// Setup for GPIO 22 CE and CE1 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,BCM2835_SPI_CS0, BCM2835_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_24, BCM2835_SPI_SPEED_8MHZ);
......
......@@ -27,15 +27,14 @@ using namespace std;
// CE Pin, CSN Pin, SPI Speed
// Setup for GPIO 22 CE and GPIO 25 CSN with SPI Speed @ 1Mhz
//RF24 radio(RPI_V2_GPIO_P1_22, RPI_V2_GPIO_P1_18, BCM2835_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_26, BCM2835_SPI_SPEED_1MHZ);
// 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);
// Setup for GPIO 22 CE and CE1 CSN with SPI Speed @ 8Mhz
RF24 radio(RPI_V2_GPIO_P1_15, BCM2835_SPI_CS0, BCM2835_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_24, BCM2835_SPI_SPEED_8MHZ);
// Radio pipe addresses for the 2 nodes to communicate.
......
......@@ -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>
......@@ -22,14 +22,14 @@ using namespace std;
// CE Pin, CSN Pin, SPI Speed
// Setup for GPIO 22 CE and GPIO 25 CSN with SPI Speed @ 1Mhz
//RF24 radio(RPI_V2_GPIO_P1_22, RPI_V2_GPIO_P1_18, BCM2835_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_26, BCM2835_SPI_SPEED_1MHZ);
// 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
RF24 radio(RPI_V2_GPIO_P1_15, RPI_V2_GPIO_P1_26, BCM2835_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_24, BCM2835_SPI_SPEED_8MHZ);
// 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){
// Print preamble:
printf("RF24/examples/pingpair_dyn/\n");
......@@ -65,7 +65,7 @@ int main(int argc, char** argv){
char myChar = {0};
cout << "Choose a role: Enter 0 for receiver, 1 for transmitter (CTRL+C to exit) \n>";
getline(cin,input);
if(input.length() == 1) {
myChar = input[0];
if(myChar == '0'){
......@@ -129,7 +129,7 @@ if (role == role_ping_out)
// Spew it
printf("Got response size=%i value=%s\n\r",len,receive_payload);
}
// Update size for next time.
next_payload_size += payload_size_increments_by;
if ( next_payload_size > max_payload_size )
......
......@@ -7,7 +7,7 @@ TMRh20 2014
*/
/** 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
the slower form of high-speed transfer using blocking-writes.
*/
......@@ -26,14 +26,14 @@ using namespace std;
// CE Pin, CSN Pin, SPI Speed
// Setup for GPIO 22 CE and GPIO 25 CSN with SPI Speed @ 1Mhz
//RF24 radio(RPI_V2_GPIO_P1_22, RPI_V2_GPIO_P1_18, BCM2835_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_26, BCM2835_SPI_SPEED_1MHZ);
// 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
RF24 radio(RPI_V2_GPIO_P1_15, RPI_V2_GPIO_P1_26, BCM2835_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_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 = 0;
uint8_t data[32];
unsigned long startTime, stopTime, counter, rxTimer=0;
uint8_t data[32];
unsigned long startTime, stopTime, counter, rxTimer=0;
int main(int argc, char** argv){
// Print preamble:
printf("RF24/examples/Transfer/\n");
radio.begin(); // Setup and configure rf radio
radio.setChannel(1);
radio.setPALevel(RF24_PA_MAX);
......@@ -67,7 +67,7 @@ int main(int argc, char** argv){
char myChar = {0};
cout << "Choose a role: Enter 0 for receiver, 1 for transmitter (CTRL+C to exit)\n>";
getline(cin,input);
if(input.length() == 1) {
myChar = input[0];
if(myChar == '0'){
......@@ -86,8 +86,8 @@ int main(int argc, char** argv){
radio.openReadingPipe(1,addresses[0]);
radio.startListening();
}
for(int i=0; i<32; i++){
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
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
}
}
......@@ -115,16 +115,16 @@ int main(int argc, char** argv){
float numBytes = cycles*32;
float rate = numBytes / (stopTime - startTime);
printf("Transfer complete at %.2f KB/s \n\r",rate);
printf("%lu of %lu Packets Failed to Send\n\r",counter,cycles);
counter = 0;
counter = 0;
}
if(role == role_pong_back){
while(radio.available()){
while(radio.available()){
radio.read(&data,32);
counter++;
}
......
......@@ -75,24 +75,33 @@ Connection Info
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:**
```
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:**
|NRF24L01 | RPI | P1 Connector |
|----- |----------- | -------------|
|VCC: | rpi-3v3 | (17) |
|GND: | rpi-gnd | (25) |
|CE: | rpi-gpio22 | (15) |
|CSN: | rpi-gpio8 | (24) |
|SCK: | rpi-sckl | (23) |
|MOSI: | rpi-mosi | (19) |
|MISO: | rpi-miso | (21) |
|-----|-----------|-------------|
| VCC | rpi-3v3 | (17) |
| GND | rpi-gnd | (25) |
| CE | rpi-gpio22 | (15) |
| CSN | rpi-gpio8 | (24) |
| SCK | rpi-sckl | (23) |
| MOSI | rpi-mosi | (19) |
| 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.
****************
......
......@@ -75,24 +75,33 @@ Connection Info
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:**
```
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:**
|NRF24L01 | RPI | P1 Connector |
|----- |----------- | -------------|
|VCC: | rpi-3v3 | (17) |
|GND: | rpi-gnd | (25) |
|CE: | rpi-gpio22 | (15) |
|CSN: | rpi-gpio8 | (24) |
|SCK: | rpi-sckl | (23) |
|MOSI: | rpi-mosi | (19) |
|MISO: | rpi-miso | (21) |
|-----|-----------|-------------|
| VCC | rpi-3v3 | (17) |
| GND | rpi-gnd | (25) |
| CE | rpi-gpio22 | (15) |
| CSN | rpi-gpio8 | (24) |
| SCK | rpi-sckl | (23) |
| MOSI | rpi-mosi | (19) |
| 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.
****************
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment