diff --git a/binding.gyp b/binding.gyp index 52b524b..8fe0c73 100755 --- a/binding.gyp +++ b/binding.gyp @@ -2,11 +2,11 @@ "targets": [ { "variables": { - "dht_verbose%": "false" + "dht_verbose%": "false", + "banana_pro%": "false" }, "target_name": "node_dht_sensor", "sources": [ - "src/bcm2835/bcm2835.c", "src/node-dht-sensor.cpp", "src/dht-sensor.cpp", "src/util.cpp" @@ -21,6 +21,17 @@ "conditions": [ ["dht_verbose=='true'", { "defines": [ "VERBOSE" ] + }], + ["banana_pro=='true'", { + "sources": [ + "src/bcm2835_bp/bcm2835.c", + ], + "defines": [ "BANANA_PRO" ] + }], + ["banana_pro=='false'", { + "sources": [ + "src/bcm2835/bcm2835.c", + ] }] ] } diff --git a/src/bcm2835_bp/bcm2835.c b/src/bcm2835_bp/bcm2835.c new file mode 100644 index 0000000..0dd6934 --- /dev/null +++ b/src/bcm2835_bp/bcm2835.c @@ -0,0 +1,1279 @@ +// from https://github.com/LeMaker/bcm2835_BP/tree/master/src + +// bcm2835.c +// C and C++ support for Broadcom BCM 2835 as used in Raspberry Pi +// http://elinux.org/RPi_Low-level_peripherals +// http://www.raspberrypi.org/wp-content/uploads/2012/02/BCM2835-ARM-Peripherals.pdf +// +// Author: Mike McCauley +// Copyright (C) 2011-2013 Mike McCauley +// $Id: bcm2835.c,v 1.16 2014/08/21 01:26:42 mikem Exp mikem $ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include /*Add for BananaPro by LeMaker Team*/ +#include /*Add for BananaPro by LeMaker Team*/ +#include /*Add for BananaPro by LeMaker Team*/ + +#include "bcm2835.h" + +// This define enables a little test program (by default a blinking output on pin RPI_GPIO_PIN_11) +// You can do some safe, non-destructive testing on any platform with: +// gcc bcm2835.c -D BCM2835_TEST +// ./a.out +//#define BCM2835_TEST + +// Uncommenting this define compiles alternative I2C code for the version 1 RPi +// The P1 header I2C pins are connected to SDA0 and SCL0 on V1. +// By default I2C code is generated for the V2 RPi which has SDA1 and SCL1 connected. +// #define I2C_V1 + +/*Add for BananaPro by LeMaker Team*/ +#define GPIONUM 28 +#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0])) +static uint8_t mode; +static uint8_t bits = 8; +static uint32_t speed = 500000; +static uint16_t delay; +static uint8_t channel = 0; /*default CE0*/ + +static int32_t BpiPin[GPIONUM] = +{ + 257,256, //BCM GPIO0,1 + 53,52, //BCM GPIO2,3 + 226,35, //BCM GPIO4,5 + 277,270, //BCM GPIO6,7 + 266,269, //BCM GPIO8,9 + 268,267, //BCM GPIO10,11 + 276,45, //BCM GPIO12,13 + 228,229, //BCM GPIO14,15 + 38,275, //BCM GPIO16,17 + 259,39, //BCM GPIO18,19 + 44, 40, //BCM GPIO20,21 + 273,244, //BCM GPIO22,23 + 245,272, //BCM GPIO24,25 + 37, 274, //BCM GPIO26,27 +}; +static uint8_t GpioDetectType[32] = {0x0}; +static uint32_t ReadRisingCnt = 0; +static uint32_t ReadFallCnt = 0; +static uint8_t RisingModeValue = 1; +static uint8_t FallModeValue = 0; + +union i2c_smbus_data +{ + uint8_t byte ; + uint16_t word ; + uint8_t block [I2C_SMBUS_BLOCK_MAX + 2] ; // block [0] is used for length + one more for PEC +} ; + +struct i2c_smbus_ioctl_data +{ + char read_write ; + uint8_t command ; + int size ; + union i2c_smbus_data *data ; +} ; +/*end 2015.01.05*/ + +/*Add for BananaPro by LeMaker Team*/ +volatile uint32_t *sunxi_gpio = (volatile uint32_t *)MAP_FAILED; +volatile uint32_t *sunxi_pwm = (volatile uint32_t *)MAP_FAILED; +volatile uint32_t *sunxi_spi0 = (volatile uint32_t *)MAP_FAILED; +volatile uint32_t *sunxi_iic2 = (volatile uint32_t *)MAP_FAILED; + +/*end 2015.01.05 */ + +// This variable allows us to test on hardware other than RPi. +// It prevents access to the kernel memory, and does not do any peripheral access +// Instead it prints out what it _would_ do if debug were 0 +static uint8_t debug = 0; + +// I2C The time needed to transmit one byte. In microseconds. +static int i2c_byte_wait_us = 0; + +/*Add for BananaPro by LeMaker Team*/ +static uint32_t pwm_period; +static int i2c_fd = -1; +static int spi_fd = -1; + +/*end 2015.01.05*/ + +// +// Low level register access functions +// + +// Function to return the pointers to the hardware register bases +uint32_t* bcm2835_regbase(uint8_t regbase) +{ + switch (regbase) + { + case BCM2835_REGBASE_GPIO: + return (uint32_t *)sunxi_gpio; + case BCM2835_REGBASE_PWM: + return (uint32_t *)sunxi_pwm; + case BCM2835_REGBASE_SPI0: + return (uint32_t *)sunxi_spi0; + case BCM2835_REGBASE_IIC2: + return (uint32_t *)sunxi_iic2; + + } + return (uint32_t *)MAP_FAILED; +} + +void bcm2835_set_debug(uint8_t d) +{ + debug = d; +} + +// safe read from peripheral +uint32_t bcm2835_peri_read(volatile uint32_t* paddr) +{ + if (debug) + { + printf("bcm2835_peri_read paddr %08X\n", (unsigned) paddr); + return 0; + } + else + { + // Make sure we dont return the _last_ read which might get lost + // if subsequent code changes to a different peripheral + uint32_t ret = *paddr; + *paddr; // Read without assigneing to an unused variable + return ret; + } +} + +// read from peripheral without the read barrier +uint32_t bcm2835_peri_read_nb(volatile uint32_t* paddr) +{ + if (debug) + { + printf("bcm2835_peri_read_nb paddr %08X\n", (unsigned) paddr); + return 0; + } + else + { + return *paddr; + } +} + +// safe write to peripheral +void bcm2835_peri_write(volatile uint32_t* paddr, uint32_t value) +{ + if (debug) + { + printf("bcm2835_peri_write paddr %08X, value %08X\n", (unsigned) paddr, value); + } + else + { + // Make sure we don't rely on the first write, which may get + // lost if the previous access was to a different peripheral. + *paddr = value; + *paddr = value; + } +} + +// write to peripheral without the write barrier +void bcm2835_peri_write_nb(volatile uint32_t* paddr, uint32_t value) +{ + if (debug) + { + printf("bcm2835_peri_write_nb paddr %08X, value %08X\n", + (unsigned) paddr, value); + } + else + { + *paddr = value; + } +} + +// Set/clear only the bits in value covered by the mask +void bcm2835_peri_set_bits(volatile uint32_t* paddr, uint32_t value, uint32_t mask) +{ + uint32_t v = bcm2835_peri_read(paddr); + v = (v & ~mask) | (value & mask); + bcm2835_peri_write(paddr, v); +} + +// +// Low level convenience functions +// + +// Function select +// pin is a BCM2835 GPIO pin number NOT RPi pin number +// There are 6 control registers, each control the functions of a block +// of 10 pins. +// Each control register has 10 sets of 3 bits per GPIO pin: +// +// 000 = GPIO Pin X is an input +// 001 = GPIO Pin X is an output +// 100 = GPIO Pin X takes alternate function 0 +// 101 = GPIO Pin X takes alternate function 1 +// 110 = GPIO Pin X takes alternate function 2 +// 111 = GPIO Pin X takes alternate function 3 +// 011 = GPIO Pin X takes alternate function 4 +// 010 = GPIO Pin X takes alternate function 5 +// +// So the 3 bits for port X are: +// X / 10 + ((X % 10) * 3) + +/*Modify for BananaPro by LeMaker Team*/ +void bcm2835_gpio_fsel(uint8_t pin, uint8_t mode) +{ + // Function selects are 10 pins per 32 bit word, 3 bits per pin + int32_t bpipin = BpiPin[pin]; + volatile uint32_t* paddr = sunxi_gpio + ((SUNXI_GPIO_CFG_OFFSET + (bpipin/32) * 0x24 + ((bpipin%32)/8) *0x04) >> 2); + uint8_t shift = (bpipin % 8) * 4; + uint32_t mask = BCM2835_GPIO_FSEL_MASK << shift; + uint32_t value = mode << shift; + if(debug)printf("bcm2835_gpio_fsel:before write:0x%x.\n",bcm2835_peri_read(paddr)); + bcm2835_peri_set_bits(paddr, value, mask); + if(debug)printf("bcm2835_gpio_fsel:after write:0x%x.\n",bcm2835_peri_read(paddr)); + +} + +/*Modify for BananaPro by LeMaker Team*/ +// Set output pin +void bcm2835_gpio_set(uint8_t pin) +{ + + int32_t bpipin = BpiPin[pin]; + + volatile uint32_t* paddr = sunxi_gpio + ((SUNXI_GPIO_DAT_OFFSET +(bpipin/32) * 0x24) >> 2); + uint8_t shift = bpipin % 32; + uint32_t mask = 0x01 << shift; + uint32_t value = 1 << shift; + bcm2835_peri_set_bits(paddr, value, mask); + +} + +/*Modify for BananaPro by LeMaker Team*/ +// Clear output pin +void bcm2835_gpio_clr(uint8_t pin) +{ + int32_t bpipin = BpiPin[pin]; + volatile uint32_t* paddr = sunxi_gpio + ((SUNXI_GPIO_DAT_OFFSET +(bpipin/32) * 0x24) >> 2); + uint8_t shift = bpipin % 32; + uint32_t mask = 0x01 << shift; + uint32_t value = 0 << shift; + bcm2835_peri_set_bits(paddr, value, mask); +} + +/*Modify for BananaPro by LeMaker Team*/ +// Set all output pins in the mask +void bcm2835_gpio_set_multi(uint32_t mask) +{ + uint8_t i = 0; + for(i;i < GPIONUM;i++){ + if(mask & 0x01){ + if(BpiPin[i] > 0){ + int32_t bpipin = BpiPin[i]; + + volatile uint32_t* paddr = sunxi_gpio + ((SUNXI_GPIO_DAT_OFFSET +(bpipin/32) * 0x24) >> 2); + uint8_t shift = bpipin % 32; + uint32_t mask_bit = 0x01 << shift; + uint32_t value = 1 << shift; + bcm2835_peri_set_bits(paddr, value, mask_bit); + } + } + mask = mask >>1; + } +} + +/*Modify for BananaPro by LeMaker Team*/ +// Clear all output pins in the mask +void bcm2835_gpio_clr_multi(uint32_t mask) +{ + uint8_t i = 0; + for(i;i < GPIONUM;i++){ + if(mask & 0x01){ + if(BpiPin[i] > 0){ + int32_t bpipin = BpiPin[i]; + //printf("pin = %d.\n",bpipin); + volatile uint32_t* paddr = sunxi_gpio + ((SUNXI_GPIO_DAT_OFFSET +(bpipin/32) * 0x24) >> 2); + uint8_t shift = bpipin % 32; + uint32_t mask_bit = 0x01 << shift; + uint32_t value = 0 << shift; + bcm2835_peri_set_bits(paddr, value, mask_bit); + } + } + mask = mask >>1; + } +} + +/*Modify for BananaPro by LeMaker Team*/ +// Read input pin +uint8_t bcm2835_gpio_lev(uint8_t pin) +{ + if(BpiPin[pin] > 0){ + int32_t bpipin = BpiPin[pin]; + volatile uint32_t* paddr = sunxi_gpio + ((SUNXI_GPIO_DAT_OFFSET +(bpipin/32) * 0x24) >> 2); + uint8_t shift = bpipin % 32; + uint32_t value = bcm2835_peri_read(paddr); + return (value & (1 << shift)) ? HIGH : LOW; + } +} + +/*Modify for BananaPro by LeMaker Team*/ +// See if an event detection bit is set +// Sigh cant support interrupts yet +uint8_t bcm2835_gpio_eds(uint8_t pin) +{ + uint8_t value,rising,i = 0; + if(GpioDetectType[pin] == 0x01){//low detect + value = bcm2835_gpio_lev(pin); + if(value) + return 0x00; + else + return 0x01; + } else if(GpioDetectType[pin] == 0x02){//high detect + value = bcm2835_gpio_lev(pin); + if(value) + return 0x01; + else + return 0x00; + } else if(GpioDetectType[pin] == 0x04){//Rising edge detect + if(ReadRisingCnt== 0){ + RisingModeValue = bcm2835_gpio_lev(pin); + ReadRisingCnt = 1; + } + while(i++ < 200) + { + value = bcm2835_gpio_lev(pin); + if(value == 0) { + RisingModeValue = 0; + } + if((value == 1) && (RisingModeValue == 0)){ + ReadRisingCnt = 0; + RisingModeValue = 1; + //printf("Rising edge detect.\n"); + return 0x01; + } + } + return 0x00; + }else if(GpioDetectType[pin] == 0x08){//fall edge detect + if(ReadFallCnt== 0){ + FallModeValue = bcm2835_gpio_lev(pin); + ReadFallCnt = 1; + } + while(i++ < 200) + { + value = bcm2835_gpio_lev(pin); + if(value == 1) { + FallModeValue = 1; + } + if((value == 0) && (FallModeValue == 1)){ + ReadFallCnt = 0; + //printf("Falling edge detect.\n"); + FallModeValue = 0; + return 0x01; + } + } + return 0x00; + + } + else{ + printf("gpio detect type is wrong.\n"); + } +} + +/*Modify for BananaPro by LeMaker Team*/ +// Write a 1 to clear the bit in EDS +void bcm2835_gpio_set_eds(uint8_t pin) +{ + bcm2835_delay(500); +} + +/*Modify for BananaPro by LeMaker Team*/ +// Rising edge detect enable +void bcm2835_gpio_ren(uint8_t pin) +{ + GpioDetectType[pin] = 0x04; +} + +/*Modify for BananaPro by LeMaker Team*/ +void bcm2835_gpio_clr_ren(uint8_t pin) +{ + GpioDetectType[pin] &= 0xFB; +} + +/*Modify for BananaPro by LeMaker Team*/ +// Falling edge detect enable +void bcm2835_gpio_fen(uint8_t pin) +{ + GpioDetectType[pin] = 0x08; +} + +/*Modify for BananaPro by LeMaker Team*/ +void bcm2835_gpio_clr_fen(uint8_t pin) +{ + GpioDetectType[pin] &= 0xF7; +} + +/*Modify for BananaPro by LeMaker Team*/ +// High detect enable +void bcm2835_gpio_hen(uint8_t pin) +{ + GpioDetectType[pin] = 0x02; +} + +/*Modify for BananaPro by LeMaker Team*/ +void bcm2835_gpio_clr_hen(uint8_t pin) +{ + GpioDetectType[pin] &= 0xFD; +} + +/*Modify for BananaPro by LeMaker Team*/ +// Low detect enable +void bcm2835_gpio_len(uint8_t pin) +{ + GpioDetectType[pin] = 0x01; +} + +/*Modify for BananaPro by LeMaker Team*/ +void bcm2835_gpio_clr_len(uint8_t pin) +{ + GpioDetectType[pin] &= 0xFE; +} + +/*Modify for BananaPro by LeMaker Team*/ +// Async rising edge detect enable +void bcm2835_gpio_aren(uint8_t pin) +{ + GpioDetectType[pin] = 0x04; +} + +/*Modify for BananaPro by LeMaker Team*/ +void bcm2835_gpio_clr_aren(uint8_t pin) +{ + GpioDetectType[pin] &= 0xFB; +} + +/*Modify for BananaPro by LeMaker Team*/ +// Async falling edge detect enable +void bcm2835_gpio_afen(uint8_t pin) +{ + GpioDetectType[pin] = 0x08; +} + +/*Modify for BananaPro by LeMaker Team*/ +void bcm2835_gpio_clr_afen(uint8_t pin) +{ + GpioDetectType[pin] &= 0xF7; +} + +/*Modify for BananaPro by LeMaker Team*/ +// Set pullup/down +void bcm2835_gpio_pud(uint8_t pud) +{ + return; +} + +/*Modify for BananaPro by LeMaker Team*/ +// Pullup/down clock +// Clocks the value of pud into the GPIO pin +void bcm2835_gpio_pudclk(uint8_t pin, uint8_t on) +{ + return; +} + +/*Modify for BananaPro by LeMaker Team*/ +// Read GPIO pad behaviour for groups of GPIOs +uint32_t bcm2835_gpio_pad(uint8_t group) +{ + return 0; +} + +/*Modify for BananaPro by LeMaker Team*/ +// Set GPIO pad behaviour for groups of GPIOs +// powerup value for al pads is +// BCM2835_PAD_SLEW_RATE_UNLIMITED | BCM2835_PAD_HYSTERESIS_ENABLED | BCM2835_PAD_DRIVE_8mA +void bcm2835_gpio_set_pad(uint8_t group, uint32_t control) +{ + return; +} + +// Some convenient arduino-like functions +// milliseconds +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); +} +/*Add for BananaPro by LeMaker Team*/ +void delayMicrosecondsHard (unsigned int howLong) +{ + struct timeval tNow, tLong, tEnd ; + + gettimeofday (&tNow, NULL) ; + tLong.tv_sec = howLong / 1000000 ; + tLong.tv_usec = howLong % 1000000 ; + timeradd (&tNow, &tLong, &tEnd) ; + + while (timercmp (&tNow, &tEnd, <)) + gettimeofday (&tNow, NULL) ; +} + +/*end 2014.01.05*/ + +/*Modify for BananaPro by LeMaker Team*/ +// microseconds +void bcm2835_delayMicroseconds(uint64_t micros) +{ + struct timespec sleeper ; + + if (micros == 0) + return ; + else if (micros < 100) + delayMicrosecondsHard (micros) ; + else{ + sleeper.tv_sec = (time_t)(micros / 1000000); + sleeper.tv_nsec = (long)(micros % 1000) * 1000; + nanosleep(&sleeper, NULL); + } +} + +// +// Higher level convenience functions +// + +// Set the state of an output +void bcm2835_gpio_write(uint8_t pin, uint8_t on) +{ + if (on) + bcm2835_gpio_set(pin); + else + bcm2835_gpio_clr(pin); +} + +// Set the state of a all 32 outputs in the mask to on or off +void bcm2835_gpio_write_multi(uint32_t mask, uint8_t on) +{ + if (on) + bcm2835_gpio_set_multi(mask); + else + bcm2835_gpio_clr_multi(mask); +} + +// Set the state of a all 32 outputs in the mask to the values in value +void bcm2835_gpio_write_mask(uint32_t value, uint32_t mask) +{ + bcm2835_gpio_set_multi(value & mask); + bcm2835_gpio_clr_multi((~value) & mask); +} + +// Set the pullup/down resistor for a pin +// +// The GPIO Pull-up/down Clock Registers control the actuation of internal pull-downs on +// the respective GPIO pins. These registers must be used in conjunction with the GPPUD +// register to effect GPIO Pull-up/down changes. The following sequence of events is +// required: +// 1. Write to GPPUD to set the required control signal (i.e. Pull-up or Pull-Down or neither +// to remove the current Pull-up/down) +// 2. Wait 150 cycles ? this provides the required set-up time for the control signal +// 3. Write to GPPUDCLK0/1 to clock the control signal into the GPIO pads you wish to +// modify ? NOTE only the pads which receive a clock will be modified, all others will +// retain their previous state. +// 4. Wait 150 cycles ? this provides the required hold time for the control signal +// 5. Write to GPPUD to remove the control signal +// 6. Write to GPPUDCLK0/1 to remove the clock +// +// RPi has P1-03 and P1-05 with 1k8 pullup resistor + +/*Modify for BananaPro by LeMaker Team*/ +void bcm2835_gpio_set_pud(uint8_t pin, uint8_t pud) +{ + // Function selects are 10 pins per 32 bit word, 3 bits per pin + if(BpiPin[pin] > 0){ + int32_t bpipin = BpiPin[pin]; + volatile uint32_t* paddr = sunxi_gpio + ((SUNXI_GPIO_PUL_OFFSET + (bpipin/32) * 0x24 + ((bpipin%32)/16) *0x04) >> 2); + uint8_t shift = (bpipin % 16) * 2; + uint32_t mask = BCM2835_GPIO_PUD_MASK << shift; + uint32_t value = pud << shift; +// printf("before write:0x%x.\n",bcm2835_peri_read(paddr)); +// printf("value = 0x%x,mask = 0x%x.\n",value,mask); + bcm2835_peri_set_bits(paddr, value, mask); +// printf("after write:0x%x.\n",bcm2835_peri_read(paddr)); + } +} + +/*Modify for BananaPro by LeMaker Team*/ +void bcm2835_spi_begin(void) +{ + int ret; + spi_fd = open ("/dev/spidev0.0", O_RDWR); + + if( spi_fd< 0){ + fprintf(stderr, "Unable to open /dev/spidev0.0: %s\n", strerror(errno)) ; + return; + } + ret = ioctl(spi_fd, SPI_IOC_WR_BITS_PER_WORD, &bits); + if (ret == -1) { + printf("set SPI_IOC_WR_BITS_PER_WORD failed:%s\n", strerror(errno)); + return; + } + + ret = ioctl(spi_fd, SPI_IOC_WR_MAX_SPEED_HZ, &speed); + if (ret == -1){ + fprintf (stderr, "set SPI_IOC_WR_MAX_SPEED_HZ failed:%s\n",strerror(errno)) ; + return; + } + + printf("open /dev/spidev0.0 ok..\n"); +} + +/*Modify for BananaPro by LeMaker Team*/ +void bcm2835_spi_end(void) +{ + // Set all the SPI0 pins back to input + close(spi_fd); +} + +void bcm2835_spi_setBitOrder(uint8_t order) +{ + // BCM2835_SPI_BIT_ORDER_MSBFIRST is the only one suported by SPI0 +} + +/*Modify for BananaPro by LeMaker Team*/ +// defaults to 0, which means a divider of 65536. +// The divisor must be a power of 2. Odd numbers +// rounded down. The maximum SPI clock rate is +// of the APB clock +void bcm2835_spi_setClockDivider(uint32_t divider) +{ + int ret; + speed = divider; + + ret = ioctl(spi_fd, SPI_IOC_WR_MAX_SPEED_HZ, &speed); + if (ret == -1){ + fprintf (stderr, "set SPI_IOC_WR_MAX_SPEED_HZ failed:%s\n",strerror(errno)) ; + return; + } +} + +/*Modify for BananaPro by LeMaker Team*/ +void bcm2835_spi_setDataMode(uint8_t mode) +{ + int ret; + if (mode < 0 ||mode > 3){ + printf("Waring: spi DataMode should be 0~3.\n"); + return; + } + ret = ioctl(spi_fd, SPI_IOC_WR_MODE, &mode); + if (ret == -1) { + printf("ioctl: set SPI WR mode failed.\n"); + return; + } +} + +/*Modify for BananaPro by LeMaker Team*/ +// Writes (and reads) a single byte to SPI +uint8_t bcm2835_spi_transfer(uint8_t value) +{ + struct spi_ioc_transfer spi ; + uint8_t rx_value,tx_value,ret; + tx_value = value; + rx_value = value; + + spi.tx_buf = (unsigned long)&tx_value; + spi.rx_buf = (unsigned long)&rx_value ; + spi.len = 1 ; + spi.delay_usecs = 0 ; + spi.speed_hz = speed ; + spi.bits_per_word = 8 ; + + if(ret = ioctl (spi_fd, SPI_IOC_MESSAGE(1), &spi) < 0){ + fprintf (stderr, "transfer failed:%s\n", strerror(errno)) ; + return ret; + } + else + { + return rx_value; + } +} + +/*Modify for BananaPro by LeMaker Team*/ +// Writes (and reads) an number of bytes to SPI +void bcm2835_spi_transfernb(char* tbuf, char* rbuf, uint32_t len) +{ + uint8_t value,i,rx_data; + i = 0; + while(len > 0){ + value = tbuf[i]; + rx_data = bcm2835_spi_transfer(value); + rbuf[i] = rx_data; + len--; + i++; + } +} + +/*Modify for BananaPro by LeMaker Team*/ +// Writes an number of bytes to SPI +void bcm2835_spi_writenb(char* tbuf, uint32_t len) +{ + uint8_t value,i; + i = 0; + while(len > 0){ + value = tbuf[i]; + bcm2835_spi_transfer(value); + len--; + i++; + } +} + +// Writes (and reads) an number of bytes to SPI +// Read bytes are copied over onto the transmit buffer +void bcm2835_spi_transfern(char* buf, uint32_t len) +{ + bcm2835_spi_transfernb(buf, buf, len); +} + +/*Modify for BananaPro by LeMaker Team*/ +void bcm2835_spi_chipSelect(uint8_t cs) +{ + volatile uint32_t *paddr; + paddr = sunxi_spi0 + SUNXI_SPI0_CTRL/4; + bcm2835_peri_set_bits(paddr,cs<<12,SUNXI_SPI0_CS_CS); + +//CS ouput mode: 0-automatic output 1-manual output CS + bcm2835_peri_set_bits(paddr,0<<16,SUNXI_SPIO_CS_CTRL); + +} + +/*Modify for BananaPro by LeMaker Team*/ +void bcm2835_spi_setChipSelectPolarity(uint8_t cs, uint8_t active) +{ + volatile uint32_t* paddr ; + if (active) + active = 0; + else + active = 1; + + paddr = sunxi_spi0 + SUNXI_SPI0_CTRL/4; + bcm2835_peri_set_bits(paddr,active<<4, SUNXI_SPIO_CS_POL); + +} + +/*Add for BananaPro by LeMaker Team*/ +static inline int i2c_smbus_access (int fd, char rw, uint8_t command, int size, union i2c_smbus_data *data) +{ + struct i2c_smbus_ioctl_data args ; + + args.read_write = rw ; + args.command = command ; + args.size = size ; + args.data = data ; + return ioctl (fd, I2C_SMBUS, &args) ; +} +/*end 2014.01.05*/ + +/*Modify for BananaPro by LeMaker Team*/ +void bcm2835_i2c_begin(void) +{ + if ((i2c_fd= open ("/dev/i2c-2", O_RDWR)) < 0) + { + fprintf(stderr, "bcm2835_i2c_begin: Unable to open /dev/i2c-2: %s\n",strerror(errno)) ; + } + printf("open dev/i2c-2 ok..\n"); + +} + +/*Modify for BananaPro by LeMaker Team*/ +void bcm2835_i2c_end(void) +{ + close(i2c_fd); +} + +/*Modify for BananaPro by LeMaker Team*/ +void bcm2835_i2c_setSlaveAddress(uint8_t addr) +{ + // Set I2C Device Address + if (ioctl (i2c_fd, I2C_SLAVE, addr) < 0){ + fprintf(stderr, "bcm2835_i2c_setSlaveAddress: set slave addr failed: %s\n",strerror(errno)) ; + } + printf("set slave addr ok.\n"); +} + +/*Modify for BananaPro by LeMaker Team*/ +// defaults to 0x5dc, should result in a 166.666 kHz I2C clock frequency. +// The divisor must be a power of 2. Odd numbers +// rounded down. +void bcm2835_i2c_setClockDivider(uint16_t divider) +{ + uint32_t value; + volatile uint32_t* paddr; + if(divider ==BCM2835_I2C_CLOCK_DIVIDER_148) + value = 0x12; + else if(divider == BCM2835_I2C_CLOCK_DIVIDER_150) + value = 0x1A; + else if(divider == BCM2835_I2C_CLOCK_DIVIDER_626) + value = 0x2A; + else + value = 0x52; + paddr = sunxi_iic2 + I2C2_CLK_OFFSET/4; + bcm2835_peri_write(paddr,value); + +} + +/*Modify for BananaPro by LeMaker Team*/ +// set I2C clock divider by means of a baudrate number +void bcm2835_i2c_set_baudrate(uint32_t baudrate) +{ + uint32_t divider; + if(baudrate > 400000) + baudrate = 400000; + else if(baudrate < 100000) + baudrate = 100000; + if(baudrate > 340000) + divider = BCM2835_I2C_CLOCK_DIVIDER_148; + else if(baudrate > 240000) + divider = BCM2835_I2C_CLOCK_DIVIDER_150; + else if(baudrate > 150000) + divider = BCM2835_I2C_CLOCK_DIVIDER_626; + else divider = BCM2835_I2C_CLOCK_DIVIDER_2500; + bcm2835_i2c_setClockDivider( (uint16_t)divider ); +} + +/*Modify for BananaPro by LeMaker Team*/ +// Writes an number of bytes to I2C +uint8_t bcm2835_i2c_write(const char * buf, uint32_t len) +{ + int ret,i; + + union i2c_smbus_data data ; + for(i = 0;i < len;i++) + { + data.byte = *(buf + i); + //printf("write:data.byte = 0x%x\n",data.byte); + ret = i2c_smbus_access (i2c_fd, I2C_SMBUS_WRITE, data.byte, I2C_SMBUS_BYTE, NULL); + if(ret < 0){ + printf("i2c write failed:%s\n", strerror(errno)); + break; + } + } + return ret; +} + +/*Modify for BananaPro by LeMaker Team*/ +// Read an number of bytes from I2C +uint8_t bcm2835_i2c_read(char* buf, uint32_t len) +{ + int ret,i; + union i2c_smbus_data data ; + for(i = 0;i < len;i++) + { + ret = i2c_smbus_access (i2c_fd, I2C_SMBUS_READ, 0, I2C_SMBUS_BYTE, &data); + if(ret < 0){ + printf("i2c read failed:%s\n",strerror(errno)); + break; + } + //printf("read:data.byte = 0x%x.\n",data.byte&0xff); + *(buf + i) = data.byte&0xFF; + } + return ret; +} + +/*Modify for BananaPro by LeMaker Team*/ +// 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) +{ + int ret,i; + union i2c_smbus_data data ; + uint8_t reg = *regaddr; + if (len == 1){ + ret = i2c_smbus_access (i2c_fd, I2C_SMBUS_READ, reg, I2C_SMBUS_BYTE, &data) ; + if(ret < 0){ + printf("i2c read failed:%s\n",strerror(errno)); + } + *buf = data.byte&0xFF; + } else if (len == 2) { + ret = i2c_smbus_access (i2c_fd, I2C_SMBUS_READ, reg, I2C_SMBUS_WORD_DATA, &data) ; + if(ret < 0){ + printf("i2c read failed:%s\n",strerror(errno)); + } + *buf = data.word&0xFFFF; + } else { + for(i = 0;i < len;i++) + { + ret = i2c_smbus_access (i2c_fd, I2C_SMBUS_READ, reg, I2C_SMBUS_BYTE, &data) ; + if(ret < 0){ + printf("i2c read failed:%s\n",strerror(errno)); + } + *(buf + i) = data.byte&0xFF; + } + } + return ret; +} + +/*Modify for BananaPro by LeMaker Team*/ +// 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) +{ + uint8_t ret; + ret = bcm2835_i2c_write(cmds,cmds_len); + ret = bcm2835_i2c_read(buf,buf_len); + return ret; +} + +/*Modify for BananaPro by LeMaker Team*/ +// Read the System Timer Counter (64-bits) +uint64_t bcm2835_st_read(void) +{ + return 0; +} + +/*Modify for BananaPro by LeMaker Team*/ +// Delays for the specified number of microseconds with offset +void bcm2835_st_delay(uint64_t offset_micros, uint64_t micros) +{ + return; +} + +// PWM + +/*Modify for BananaPro by LeMaker Team*/ +void bcm2835_pwm_set_clock(uint32_t divisor) +{ + volatile uint32_t* paddr; + uint8_t value; + paddr = sunxi_pwm + (SUNXI_PWM_CTRL_OFFSET /4); + if((divisor == BCM2835_PWM_CLOCK_DIVIDER_32768) ||(divisor == BCM2835_PWM_CLOCK_DIVIDER_16384)) + value = 0x0C; + else if((divisor == BCM2835_PWM_CLOCK_DIVIDER_8192) ||(divisor ==BCM2835_PWM_CLOCK_DIVIDER_4096)) + value = 0x0B; + else if(divisor ==BCM2835_PWM_CLOCK_DIVIDER_2048) + value = 0x0A; + else if(divisor == BCM2835_PWM_CLOCK_DIVIDER_1024) + value = 0x09; + else if(divisor == BCM2835_PWM_CLOCK_DIVIDER_512) + value = 0x08; + else if(divisor == BCM2835_PWM_CLOCK_DIVIDER_256) + value = 0x08; + else if((divisor ==BCM2835_PWM_CLOCK_DIVIDER_128)||(divisor ==BCM2835_PWM_CLOCK_DIVIDER_64)) + value = 0x04; + else if((divisor ==BCM2835_PWM_CLOCK_DIVIDER_32) ||(divisor ==BCM2835_PWM_CLOCK_DIVIDER_32)) + value = 0x03; + else if((divisor ==BCM2835_PWM_CLOCK_DIVIDER_16) ||(divisor ==BCM2835_PWM_CLOCK_DIVIDER_8)) + value = 0x02; + else if((divisor ==BCM2835_PWM_CLOCK_DIVIDER_4) ||(divisor ==BCM2835_PWM_CLOCK_DIVIDER_2)) + value = 0x01; + else value = 0x00; + bcm2835_peri_set_bits(paddr,value << 15,SUNXI_PWM_CLKDIV_MASK); + +} + +/*Modify for BananaPro by LeMaker Team*/ +// +void bcm2835_pwm_set_mode(uint8_t channel, uint8_t markspace, uint8_t enabled) +{ + volatile uint32_t* paddr; + if(markspace == 0) + markspace = 1; + else + markspace = 0; + paddr = sunxi_pwm + (SUNXI_PWM_CTRL_OFFSET /4); + bcm2835_peri_set_bits(paddr,markspace<< 22,0x01<<22); + +} + +/*Modify for BananaPro by LeMaker Team*/ +//compatible with the RPI PWM channel +//RPI:PWM0 <----> BPR:PWM1 +void bcm2835_pwm_set_range(uint8_t channel, uint32_t range) +{ + volatile uint32_t* paddr; + + if(channel == 1) + paddr = sunxi_pwm + (SUNXI_PWM_CH0_OFFSET /4); + else if(channel == 0) + paddr = sunxi_pwm + (SUNXI_PWM_CH1_OFFSET/4); + if(range >= 0xFFFF) + range = 0xFFFF; + bcm2835_peri_set_bits(paddr,range<< 16,0xFFFF<<16); + } + +/*Modify for BananaPro by LeMaker Team*/ +//compatible with the RPI PWM channel +//RPI:PWM0 <----> BPR:PWM1 +void bcm2835_pwm_set_data(uint8_t channel, uint32_t data) +{ + uint32_t value,temp; + volatile uint32_t* paddr; + if(channel == 1) + paddr = sunxi_pwm + (SUNXI_PWM_CH0_OFFSET /4); + else if(channel == 0) + paddr = sunxi_pwm + (SUNXI_PWM_CH1_OFFSET/4); + if(data >= 0xFFFF) + data = 0xFFFF; + value = bcm2835_peri_read(paddr); + value >>=16; + if(data > value) + data = value; + bcm2835_peri_set_bits(paddr,data,0xFFFF); + paddr = sunxi_pwm + (SUNXI_PWM_CTRL_OFFSET>>2); + temp = bcm2835_peri_read(paddr); + if(channel == 1) + temp |= 0x230; + else + temp |= 0x380000; + bcm2835_peri_write(paddr,temp); +} + +// Allocate page-aligned memory. +void *malloc_aligned(size_t size) +{ + void *mem; + errno = posix_memalign(&mem, BCM2835_PAGE_SIZE, size); + return (errno ? NULL : mem); +} + +// Map 'size' bytes starting at 'off' in file 'fd' to memory. +// Return mapped address on success, MAP_FAILED otherwise. +// On error print message. +static void *mapmem(const char *msg, size_t size, int fd, off_t off) +{ + void *map = mmap(NULL, size, (PROT_READ | PROT_WRITE), MAP_SHARED, fd, off); + if (MAP_FAILED == map) + fprintf(stderr, "bcm2835_init: %s mmap failed: %s\n", msg, strerror(errno)); + return map; +} + +static void unmapmem(void **pmem, size_t size) +{ + if (*pmem == MAP_FAILED) return; + munmap(*pmem, size); + *pmem = MAP_FAILED; +} +/*Add for BananaPro by LeMaker Team*/ +static int get_cpuinfo_revision(void) +{ + FILE *fp; + char buffer[1024]; + char hardware[1024]; + char *ret; + + if ((fp = fopen("/proc/cpuinfo", "r")) == NULL) + return -1; + + while(!feof(fp)) + { + ret = fgets(buffer, sizeof(buffer) , fp); + sscanf(buffer, "Hardware : %s", hardware); + if (strcmp(hardware, "sun7i") == 0) + { + return 1; + } + } + fclose(fp); + return 0; +} + +/*end 2015.01.05*/ + + /*Modify for BananaPro by LeMaker Team*/ +// Initialise this library. +int bcm2835_init(void) +{ + int memfd = -1; + int ok = 0; + uint32_t mmap_base; + uint32_t mmap_seek; + volatile uint32_t *sunxi_tmp; + + if (1 != get_cpuinfo_revision()) + { + fprintf(stderr, "bcm3825_init: The current version only support the BananaPro !\n"); + goto exit; + } + // Open the master /dev/memory device + if ((memfd = open("/dev/mem", O_RDWR | O_SYNC) ) < 0) + { + fprintf(stderr, "bcm2835_init: Unable to open /dev/mem: %s\n", + strerror(errno)) ; + goto exit; + } + + if (debug) + { + sunxi_gpio = (uint32_t*)SUNXI_GPIO_BASE; + sunxi_pwm = (uint32_t*)SUNXI_GPIO_PWM; + sunxi_spi0 = (uint32_t*)SUNXI_SPI0_BASE; + sunxi_iic2 = (uint32_t*)SUNXI_IIC2_BASE; + return 1; + } + mmap_base = (SUNXI_GPIO_BASE & (~MAP_MASK)); + mmap_seek = (SUNXI_GPIO_BASE-mmap_base)>> 2; + sunxi_gpio = (uint32_t *)mmap(NULL, MAP_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, memfd, mmap_base); + if (MAP_FAILED == sunxi_gpio) + { + fprintf(stderr, "bcm2835_init: %s mmap failed: %s\n", "sunxi_gpio", strerror(errno)); + goto exit; + } + sunxi_tmp = sunxi_gpio; + /*gpio register base address*/ + sunxi_gpio += mmap_seek; + + mmap_base = (SUNXI_GPIO_PWM &(~MAP_MASK)); + mmap_seek = (SUNXI_GPIO_PWM - mmap_base) >> 2; + /*pwm register base address*/ + sunxi_pwm = sunxi_tmp + mmap_seek; + + /*spi register base address*/ + sunxi_spi0 = (uint32_t *)mmap(NULL, MAP_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, memfd, SUNXI_SPI0_BASE); + if (MAP_FAILED == sunxi_spi0) + { + fprintf(stderr, "bcm2835_init: %s mmap failed: %s\n", "sunxi_spi0", strerror(errno)); + goto exit; + } + + mmap_base = (SUNXI_IIC2_BASE &(~MAP_MASK)); + mmap_seek = (SUNXI_IIC2_BASE - mmap_base) >> 2; + sunxi_iic2 = (uint32_t *)mmap(NULL, MAP_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, memfd, mmap_base); + if (MAP_FAILED == sunxi_iic2) + { + fprintf(stderr, "bcm2835_init: %s mmap failed: %s\n", "sunxi_iic2", strerror(errno)); + goto exit; + } + /*iic2 register base address*/ + sunxi_iic2 += mmap_seek; + + ok = 1; + + exit: + if (memfd >= 0) + close(memfd); + + if (!ok) + bcm2835_close(); + + return ok; +} + +/*Modify for BananaPro by LeMaker Team*/ +// Close this library and deallocate everything +int bcm2835_close(void) +{ + uint32_t mmap_base; + uint32_t mmap_seek; + if (debug) return 1; // Success + + mmap_base = (SUNXI_GPIO_BASE & (~MAP_MASK)); + mmap_seek = (SUNXI_GPIO_BASE - mmap_base)>> 2; + sunxi_gpio -= mmap_seek; + if(MAP_FAILED == sunxi_gpio) return 1; + else + { + munmap((void *)sunxi_gpio, MAP_SIZE); + sunxi_gpio = MAP_FAILED; + } + + if(MAP_FAILED == sunxi_spi0) return 1; + else + { + munmap((void *)sunxi_spi0, MAP_SIZE); + sunxi_spi0 = MAP_FAILED; + } + + mmap_base = (SUNXI_IIC2_BASE & (~MAP_MASK)); + mmap_seek = (SUNXI_IIC2_BASE - mmap_base)>> 2; + sunxi_iic2 -= mmap_seek; + if(MAP_FAILED == sunxi_iic2) return 1; + else + { + munmap((void *)sunxi_iic2, MAP_SIZE); + sunxi_iic2 = MAP_FAILED; + } + + return 1; +} + +#ifdef BCM2835_TEST +// this is a simple test program that prints out what it will do rather than +// actually doing it +int main(int argc, char **argv) +{ + // Be non-destructive + bcm2835_set_debug(1); + + if (!bcm2835_init()) + return 1; + + // Configure some GPIO pins fo some testing + // Set RPI pin P1-11 to be an output + bcm2835_gpio_fsel(RPI_GPIO_P1_11, BCM2835_GPIO_FSEL_OUTP); + // Set RPI pin P1-15 to be an input + bcm2835_gpio_fsel(RPI_GPIO_P1_15, BCM2835_GPIO_FSEL_INPT); + // with a pullup + bcm2835_gpio_set_pud(RPI_GPIO_P1_15, BCM2835_GPIO_PUD_UP); + // And a low detect enable + bcm2835_gpio_len(RPI_GPIO_P1_15); + // and input hysteresis disabled on GPIOs 0 to 27 + bcm2835_gpio_set_pad(BCM2835_PAD_GROUP_GPIO_0_27, BCM2835_PAD_SLEW_RATE_UNLIMITED|BCM2835_PAD_DRIVE_8mA); + +#if 1 + // Blink + while (1) + { + // Turn it on + bcm2835_gpio_write(RPI_GPIO_P1_11, HIGH); + + // wait a bit + bcm2835_delay(500); + + // turn it off + bcm2835_gpio_write(RPI_GPIO_P1_11, LOW); + + // wait a bit + bcm2835_delay(500); + } +#endif + +#if 0 + // Read input + while (1) + { + // Read some data + uint8_t value = bcm2835_gpio_lev(RPI_GPIO_P1_15); + printf("read from pin 15: %d\n", value); + + // wait a bit + bcm2835_delay(500); + } +#endif + +#if 0 + // Look for a low event detection + // eds will be set whenever pin 15 goes low + while (1) + { + if (bcm2835_gpio_eds(RPI_GPIO_P1_15)) + { + // Now clear the eds flag by setting it to 1 + bcm2835_gpio_set_eds(RPI_GPIO_P1_15); + printf("low event detect for pin 15\n"); + } + + // wait a bit + bcm2835_delay(500); + } +#endif + + if (!bcm2835_close()) + return 1; + + return 0; +} +#endif diff --git a/src/bcm2835_bp/bcm2835.h b/src/bcm2835_bp/bcm2835.h new file mode 100644 index 0000000..34f106b --- /dev/null +++ b/src/bcm2835_bp/bcm2835.h @@ -0,0 +1,1434 @@ +// from https://github.com/LeMaker/bcm2835_BP/tree/master/src + +// bcm2835.h +// +// C and C++ support for Broadcom BCM 2835 as used in Raspberry Pi +// +// Author: Mike McCauley +// Copyright (C) 2011-2013 Mike McCauley +// $Id: bcm2835.h,v 1.14 2014/08/21 01:26:42 mikem Exp mikem $ +// +/// \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 +/// 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. +/// +/// It provides functions for reading digital inputs and setting digital outputs, using SPI and I2C, +/// 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 +/// BCM 2835). +/// +/// The version of the package that this documentation refers to can be downloaded +/// from http://www.airspayce.com/mikem/bcm2835/bcm2835-1.38.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 +/// 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. +/// Do not contact the author directly, unless it is to discuss commercial licensing. +/// Before asking a question or reporting a bug, please read http://www.catb.org/esr/faqs/smart-questions.html +/// +/// 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() +/// 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. +/// +/// \par Installation +/// +/// This library consists of a single non-shared library and header file, which will be +/// installed in the usual places by make install +/// +/// \code +/// # download the latest version of the library, say bcm2835-1.xx.tar.gz, then: +/// tar zxvf bcm2835-1.xx.tar.gz +/// cd bcm2835-1.xx +/// ./configure +/// make +/// sudo make check +/// sudo make install +/// \endcode +/// +/// \par Physical Addresses +/// +/// 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. +/// 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 +/// physical address 0x20nnnnnn. +/// +/// The base address of the various peripheral registers are available with the following +/// externals: +/// bcm2835_gpio +/// bcm2835_pwm +/// bcm2835_clk +/// bcm2835_pads +/// bcm2835_spio0 +/// bcm2835_st +/// bcm2835_bsc0 +/// bcm2835_bsc1 +/// +/// \par Pin Numbering +/// +/// 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 +/// 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 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, +/// 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 +/// 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-26 (CE1) +/// +/// \par I2C Pins +/// +/// The bcm2835_i2c_* functions allow you to control the BCM 2835 BSC interface, +/// allowing you to send and received data by I2C ("eye-squared cee"; generically referred to as "two-wire interface") . +/// For more information about I?C, see http://en.wikipedia.org/wiki/I%C2%B2C +/// +/// The Raspberry Pi V2 GPIO pins used for I2C are: +/// +/// - P1-03 (SDA) +/// - P1-05 (SLC) +/// +/// \par PWM +/// +/// 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 +/// 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 +/// 12 0 0 +/// 13 1 0 +/// 18 1-12 0 5 +/// 19 1 5 +/// 40 0 0 +/// 41 1 0 +/// 45 1 0 +/// 52 0 1 +/// 53 1 1 +/// \endcode +/// In order for a GPIO pin to emit output from its PWM channel, it must be set to the Alt Function given above. +/// Note carefully that current versions of the Raspberry Pi only expose one of these pins (GPIO 18 = RPi Pin 1-12) +/// 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 +/// 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 +/// 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. +/// +/// 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 +/// 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'). +/// 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. +/// 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. +/// +/// Arjan reports that you can prevent swapping on Linux with the following code fragment: +/// +/// \code +/// struct sched_param sp; +/// memset(&sp, 0, sizeof(sp)); +/// sp.sched_priority = sched_get_priority_max(SCHED_FIFO); +/// sched_setscheduler(0, SCHED_FIFO, &sp); +/// mlockall(MCL_CURRENT | MCL_FUTURE); +/// \endcode +/// +/// \par Bindings to other languages +/// +/// mikem has made Perl bindings available at CPAN: +/// 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 +/// free download with source included: http://ipsolutionscorp.com/raspberry-pi-spi-utility/ +/// +/// \par Open Source Licensing GPL V2 +/// +/// This is the appropriate option if you want to share the source code of your +/// application with everyone you distribute it to, and you also want to give them +/// the right to share who uses it. If you wish to use this software under Open +/// Source Licensing, you must contribute all your source code to the open source +/// community in accordance with the GPL Version 2 when your application is +/// distributed. See http://www.gnu.org/copyleft/gpl.html and COPYING +/// +/// \par Acknowledgements +/// +/// 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 +/// \version 1.1 Minor bug fixes +/// \version 1.2 Added support for SPI +/// \version 1.3 Added bcm2835_spi_transfern() +/// \version 1.4 Fixed a problem that prevented SPI CE1 being used. Reported by David Robinson. +/// \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 +/// 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() +/// 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: +/// 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). +/// I've also modified delayMicroseconds() to use nanosleep() for long waits, +/// and a busy wait on a high resolution timer for the rest. This is because +/// I've found that calling nanosleep() takes at least 100-200 us. +/// You need to link using '-lrt' using this version. +/// I've added some unsigned casts to the debug prints to silence compiler +/// warnings I was getting, fixed some typos, and changed the value of +/// BCM2835_PAD_HYSTERESIS_ENABLED to 0x08 as per Gert van Loo's doc at +/// 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() +/// 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.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. +/// 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. +/// 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. +/// 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. +/// Patch courtesy Jeremy Mortis. +/// \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. +/// 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. +/// \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. +/// Reported by Hartmut Henkel. +/// \version 1.27 bcm2835_gpio_set_pad() no longer needs BCM2835_PAD_PASSWRD: it is +/// now automatically included. +/// Added suport for PWM mode with bcm2835_pwm_* functions. +/// \version 1.28 Fixed a problem where bcm2835_spi_writenb() would have problems with transfers of more than +/// 64 bytes dues to read buffer filling. Patched by Peter Würtz. +/// \version 1.29 Further fix to SPI from Peter Würtz. +/// \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. +/// 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, +/// 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 +/// one makes us skip the test when using fakeroot (as used when building +/// Debian packages). Contributed by Guido Günther. +/// \version 1.37 Moved confiure.in to configure.ac as receommnded by autoreconf.
+/// Improvements to bcm2835_st_read to account for possible timer overflow, contributed by 'Ed'.
+/// Added definitions for Raspberry Pi B+ J8 header GPIO pins.
+/// \version 1.38 Added bcm2835_regbase for the benefit of C# wrappers, patch by Frank Hommers
+/// +/// \author Mike McCauley (mikem@airspayce.com) DO NOT CONTACT THE AUTHOR DIRECTLY: USE THE LISTS + + + +// Defines for BCM2835 +#ifndef BCM2835_H +#define BCM2835_H + +#include + +/// \defgroup constants Constants for passing to and from library functions +/// The values here are designed to be passed to various functions in the bcm2835 library. +/// @{ + + +/// This means pin HIGH, true, 3.3volts on a pin. +#define HIGH 0x1 +/// This means pin LOW, false, 0volts on a pin. +#define LOW 0x0 + +/// Speed of the core clock core_clk +#define BCM2835_CORE_CLK_HZ 250000000 ///< 250 MHz + +// Physical addresses for various peripheral register sets +/// Base Physical Address of the BCM 2835 peripheral registers +#define BCM2835_PERI_BASE 0x20000000 +/// Base Physical Address of the System Timer registers +#define BCM2835_ST_BASE (BCM2835_PERI_BASE + 0x3000) +/// Base Physical Address of the Pads registers +#define BCM2835_GPIO_PADS (BCM2835_PERI_BASE + 0x100000) +/// Base Physical Address of the Clock/timer registers +#define BCM2835_CLOCK_BASE (BCM2835_PERI_BASE + 0x101000) +/// Base Physical Address of the GPIO registers +#define BCM2835_GPIO_BASE (BCM2835_PERI_BASE + 0x200000) +/// Base Physical Address of the SPI0 registers +#define BCM2835_SPI0_BASE (BCM2835_PERI_BASE + 0x204000) +/// Base Physical Address of the BSC0 registers +#define BCM2835_BSC0_BASE (BCM2835_PERI_BASE + 0x205000) +/// Base Physical Address of the PWM registers +#define BCM2835_GPIO_PWM (BCM2835_PERI_BASE + 0x20C000) + /// Base Physical Address of the BSC1 registers +#define BCM2835_BSC1_BASE (BCM2835_PERI_BASE + 0x804000) + +/// Base of the GPIO registers. +/// Available after bcm2835_init has been called +extern volatile uint32_t *sunxi_gpio; + +/// Base of the PWM registers. +/// Available after bcm2835_init has been called +extern volatile uint32_t *sunxi_pwm; + +/// Base of the SPI0 registers. +/// Available after bcm2835_init has been called +extern volatile uint32_t *sunxi_spi0; + +/// Base of the iic2 registers. +/// Available after bcm2835_init has been called +extern volatile uint32_t *sunxi_iic2; + +/// \brief bcm2835RegisterBase +/// Register bases for bcm2835_regbase() +typedef enum +{ + BCM2835_REGBASE_ST = 1, ///< Base of the ST (System Timer) registers. + BCM2835_REGBASE_GPIO = 2, ///< Base of the GPIO registers. + BCM2835_REGBASE_PWM = 3, ///< Base of the PWM registers. + BCM2835_REGBASE_CLK = 4, ///< Base of the CLK registers. + BCM2835_REGBASE_PADS = 5, ///< Base of the PADS registers. + BCM2835_REGBASE_SPI0 = 6, ///< Base of the SPI0 registers. + BCM2835_REGBASE_BSC0 = 7, ///< Base of the BSC0 registers. + BCM2835_REGBASE_BSC1 = 8, ///< Base of the BSC1 registers. + BCM2835_REGBASE_IIC2 = 9 /*Add for BananaPro by LeMaker Team*/ +} bcm2835RegisterBase; + +/// Size of memory page on RPi +#define BCM2835_PAGE_SIZE (4*1024) +/// Size of memory block on RPi +#define BCM2835_BLOCK_SIZE (4*1024) + + +// Defines for GPIO +// The BCM2835 has 54 GPIO pins. +// BCM2835 data sheet, Page 90 onwards. +/// GPIO register offsets from BCM2835_GPIO_BASE. Offsets into the GPIO Peripheral block in bytes per 6.1 Register View +#define BCM2835_GPFSEL0 0x0000 ///< GPIO Function Select 0 +#define BCM2835_GPFSEL1 0x0004 ///< GPIO Function Select 1 +#define BCM2835_GPFSEL2 0x0008 ///< GPIO Function Select 2 +#define BCM2835_GPFSEL3 0x000c ///< GPIO Function Select 3 +#define BCM2835_GPFSEL4 0x0010 ///< GPIO Function Select 4 +#define BCM2835_GPFSEL5 0x0014 ///< GPIO Function Select 5 +#define BCM2835_GPSET0 0x001c ///< GPIO Pin Output Set 0 +#define BCM2835_GPSET1 0x0020 ///< GPIO Pin Output Set 1 +#define BCM2835_GPCLR0 0x0028 ///< GPIO Pin Output Clear 0 +#define BCM2835_GPCLR1 0x002c ///< GPIO Pin Output Clear 1 +#define BCM2835_GPLEV0 0x0034 ///< GPIO Pin Level 0 +#define BCM2835_GPLEV1 0x0038 ///< GPIO Pin Level 1 +#define BCM2835_GPEDS0 0x0040 ///< GPIO Pin Event Detect Status 0 +#define BCM2835_GPEDS1 0x0044 ///< GPIO Pin Event Detect Status 1 +#define BCM2835_GPREN0 0x004c ///< GPIO Pin Rising Edge Detect Enable 0 +#define BCM2835_GPREN1 0x0050 ///< GPIO Pin Rising Edge Detect Enable 1 +#define BCM2835_GPFEN0 0x0058 ///< GPIO Pin Falling Edge Detect Enable 0 +#define BCM2835_GPFEN1 0x005c ///< GPIO Pin Falling Edge Detect Enable 1 +#define BCM2835_GPHEN0 0x0064 ///< GPIO Pin High Detect Enable 0 +#define BCM2835_GPHEN1 0x0068 ///< GPIO Pin High Detect Enable 1 +#define BCM2835_GPLEN0 0x0070 ///< GPIO Pin Low Detect Enable 0 +#define BCM2835_GPLEN1 0x0074 ///< GPIO Pin Low Detect Enable 1 +#define BCM2835_GPAREN0 0x007c ///< GPIO Pin Async. Rising Edge Detect 0 +#define BCM2835_GPAREN1 0x0080 ///< GPIO Pin Async. Rising Edge Detect 1 +#define BCM2835_GPAFEN0 0x0088 ///< GPIO Pin Async. Falling Edge Detect 0 +#define BCM2835_GPAFEN1 0x008c ///< GPIO Pin Async. Falling Edge Detect 1 +#define BCM2835_GPPUD 0x0094 ///< GPIO Pin Pull-up/down Enable +#define BCM2835_GPPUDCLK0 0x0098 ///< GPIO Pin Pull-up/down Enable Clock 0 +#define BCM2835_GPPUDCLK1 0x009c ///< GPIO Pin Pull-up/down Enable Clock 1 + +/// \brief bcm2835PortFunction +/// Port function select modes for bcm2835_gpio_fsel() +typedef enum +{ + BCM2835_GPIO_FSEL_INPT = 0b000, ///< Input + BCM2835_GPIO_FSEL_OUTP = 0b001, ///< Output + BCM2835_GPIO_FSEL_ALT0 = 0b100, ///< Alternate function 0 + BCM2835_GPIO_FSEL_ALT1 = 0b101, ///< Alternate function 1 + BCM2835_GPIO_FSEL_ALT2 = 0b110, ///< Alternate function 2 + BCM2835_GPIO_FSEL_ALT3 = 0b111, ///< Alternate function 3 + BCM2835_GPIO_FSEL_ALT4 = 0b011, ///< Alternate function 4 + BCM2835_GPIO_FSEL_ALT5 = 0b010, ///< Alternate function 5 + BCM2835_GPIO_FSEL_MASK = 0b111 ///< Function select bits mask +} bcm2835FunctionSelect; + +/// \brief bcm2835PUDControl +/// Pullup/Pulldown defines for bcm2835_gpio_pud() +typedef enum +{ + BCM2835_GPIO_PUD_OFF = 0b00, ///< Off ? disable pull-up/down + BCM2835_GPIO_PUD_DOWN = 0b10, ///< Enable Pull Down control (modify for BananaPro by LeMaker Team) + BCM2835_GPIO_PUD_UP = 0b01, ///< Enable Pull Up control (modify for BananaPro by LeMaker Team) + BCM2835_GPIO_PUD_MASK = 0b11 //(add for BananaPro by LeMaker Team) +} bcm2835PUDControl; + +/// Pad control register offsets from BCM2835_GPIO_PADS +#define BCM2835_PADS_GPIO_0_27 0x002c ///< Pad control register for pads 0 to 27 +#define BCM2835_PADS_GPIO_28_45 0x0030 ///< Pad control register for pads 28 to 45 +#define BCM2835_PADS_GPIO_46_53 0x0034 ///< Pad control register for pads 46 to 53 + +/// Pad Control masks +#define BCM2835_PAD_PASSWRD (0x5A << 24) ///< Password to enable setting pad mask +#define BCM2835_PAD_SLEW_RATE_UNLIMITED 0x10 ///< Slew rate unlimited +#define BCM2835_PAD_HYSTERESIS_ENABLED 0x08 ///< Hysteresis enabled +#define BCM2835_PAD_DRIVE_2mA 0x00 ///< 2mA drive current +#define BCM2835_PAD_DRIVE_4mA 0x01 ///< 4mA drive current +#define BCM2835_PAD_DRIVE_6mA 0x02 ///< 6mA drive current +#define BCM2835_PAD_DRIVE_8mA 0x03 ///< 8mA drive current +#define BCM2835_PAD_DRIVE_10mA 0x04 ///< 10mA drive current +#define BCM2835_PAD_DRIVE_12mA 0x05 ///< 12mA drive current +#define BCM2835_PAD_DRIVE_14mA 0x06 ///< 14mA drive current +#define BCM2835_PAD_DRIVE_16mA 0x07 ///< 16mA drive current + +/*Add for BananaPro by LeMaker Team*/ +//I2C definitions +#define I2C_TIMEOUT 0x0702 +#define I2C_SLAVE 0x0703 +#define I2C_SMBUS 0x0720 /* SMBus-level access */ +#define I2C_FUNCS 0x0705 +#define I2C_SMBUS_READ 1 +#define I2C_SMBUS_WRITE 0 + +#define I2C_SMBUS_QUICK 0 +#define I2C_SMBUS_BYTE 1 +#define I2C_SMBUS_BYTE_DATA 2 +#define I2C_SMBUS_WORD_DATA 3 +#define I2C_SMBUS_PROC_CALL 4 +#define I2C_SMBUS_BLOCK_DATA 5 +#define I2C_SMBUS_I2C_BLOCK_BROKEN 6 +#define I2C_SMBUS_BLOCK_PROC_CALL 7 /* SMBus 2.0 */ +#define I2C_SMBUS_I2C_BLOCK_DATA 8 +// SMBus messages + +#define I2C_SMBUS_BLOCK_MAX 32 /* As specified in SMBus standard */ +#define I2C_SMBUS_I2C_BLOCK_MAX 32 /* Not specified but we use same structure */ +/*end 2015.01.05*/ + +/// \brief bcm2835PadGroup +/// Pad group specification for bcm2835_gpio_pad() +typedef enum +{ + BCM2835_PAD_GROUP_GPIO_0_27 = 0, ///< Pad group for GPIO pads 0 to 27 + BCM2835_PAD_GROUP_GPIO_28_45 = 1, ///< Pad group for GPIO pads 28 to 45 + BCM2835_PAD_GROUP_GPIO_46_53 = 2 ///< Pad group for GPIO pads 46 to 53 +} bcm2835PadGroup; + +/// \brief GPIO Pin Numbers +/// +/// Here we define Raspberry Pin GPIO pins on P1 in terms of the underlying BCM GPIO pin numbers. +/// These can be passed as a pin number to any function requiring a pin. +/// Not all pins on the RPi 26 bin IDE plug are connected to GPIO pins +/// and some can adopt an alternate function. +/// RPi version 2 has some slightly different pinouts, and these are values RPI_V2_*. +/// RPi B+ has yet differnet pinouts and these are defined in RPI_BPLUS_*. +/// At bootup, pins 8 and 10 are set to UART0_TXD, UART0_RXD (ie the alt0 function) respectively +/// When SPI0 is in use (ie after bcm2835_spi_begin()), SPI0 pins are dedicated to SPI +/// and cant be controlled independently. +/// If you are using the RPi Compute Module, just use the GPIO number: there is no need to use one of these +/// symbolic names +typedef enum +{ + RPI_GPIO_P1_03 = 0, ///< Version 1, Pin P1-03 + RPI_GPIO_P1_05 = 1, ///< Version 1, Pin P1-05 + RPI_GPIO_P1_07 = 4, ///< Version 1, Pin P1-07 + RPI_GPIO_P1_08 = 14, ///< Version 1, Pin P1-08, defaults to alt function 0 UART0_TXD + RPI_GPIO_P1_10 = 15, ///< Version 1, Pin P1-10, defaults to alt function 0 UART0_RXD + RPI_GPIO_P1_11 = 17, ///< Version 1, Pin P1-11 + RPI_GPIO_P1_12 = 18, ///< Version 1, Pin P1-12, can be PWM channel 0 in ALT FUN 5 + RPI_GPIO_P1_13 = 21, ///< Version 1, Pin P1-13 + RPI_GPIO_P1_15 = 22, ///< Version 1, Pin P1-15 + RPI_GPIO_P1_16 = 23, ///< Version 1, Pin P1-16 + RPI_GPIO_P1_18 = 24, ///< Version 1, Pin P1-18 + RPI_GPIO_P1_19 = 10, ///< Version 1, Pin P1-19, MOSI when SPI0 in use + RPI_GPIO_P1_21 = 9, ///< Version 1, Pin P1-21, MISO when SPI0 in use + RPI_GPIO_P1_22 = 25, ///< Version 1, Pin P1-22 + RPI_GPIO_P1_23 = 11, ///< Version 1, Pin P1-23, CLK when SPI0 in use + RPI_GPIO_P1_24 = 8, ///< Version 1, Pin P1-24, CE0 when SPI0 in use + RPI_GPIO_P1_26 = 7, ///< Version 1, Pin P1-26, CE1 when SPI0 in use + + // RPi Version 2 + RPI_V2_GPIO_P1_03 = 2, ///< Version 2, Pin P1-03 + RPI_V2_GPIO_P1_05 = 3, ///< Version 2, Pin P1-05 + RPI_V2_GPIO_P1_07 = 4, ///< Version 2, Pin P1-07 + RPI_V2_GPIO_P1_08 = 14, ///< Version 2, Pin P1-08, defaults to alt function 0 UART0_TXD + RPI_V2_GPIO_P1_10 = 15, ///< Version 2, Pin P1-10, defaults to alt function 0 UART0_RXD + RPI_V2_GPIO_P1_11 = 17, ///< Version 2, Pin P1-11 + RPI_V2_GPIO_P1_12 = 18, ///< Version 2, Pin P1-12, can be PWM channel 0 in ALT FUN 5 + RPI_V2_GPIO_P1_13 = 27, ///< Version 2, Pin P1-13 + RPI_V2_GPIO_P1_15 = 22, ///< Version 2, Pin P1-15 + RPI_V2_GPIO_P1_16 = 23, ///< Version 2, Pin P1-16 + RPI_V2_GPIO_P1_18 = 24, ///< Version 2, Pin P1-18 + RPI_V2_GPIO_P1_19 = 10, ///< Version 2, Pin P1-19, MOSI when SPI0 in use + RPI_V2_GPIO_P1_21 = 9, ///< Version 2, Pin P1-21, MISO when SPI0 in use + RPI_V2_GPIO_P1_22 = 25, ///< Version 2, Pin P1-22 + RPI_V2_GPIO_P1_23 = 11, ///< Version 2, Pin P1-23, CLK when SPI0 in use + RPI_V2_GPIO_P1_24 = 8, ///< Version 2, Pin P1-24, CE0 when SPI0 in use + RPI_V2_GPIO_P1_26 = 7, ///< Version 2, Pin P1-26, CE1 when SPI0 in use + + // RPi Version 2, new plug P5 + RPI_V2_GPIO_P5_03 = 28, ///< Version 2, Pin P5-03 + RPI_V2_GPIO_P5_04 = 29, ///< Version 2, Pin P5-04 + RPI_V2_GPIO_P5_05 = 30, ///< Version 2, Pin P5-05 + RPI_V2_GPIO_P5_06 = 31, ///< Version 2, Pin P5-06 + + // RPi B+ J8 header + RPI_BPLUS_GPIO_J8_03 = 2, ///< B+, Pin J8-03 + RPI_BPLUS_GPIO_J8_05 = 3, ///< B+, Pin J8-05 + RPI_BPLUS_GPIO_J8_07 = 4, ///< B+, Pin J8-07 + RPI_BPLUS_GPIO_J8_08 = 14, ///< B+, Pin J8-08, defaults to alt function 0 UART0_TXD + RPI_BPLUS_GPIO_J8_10 = 15, ///< B+, Pin J8-10, defaults to alt function 0 UART0_RXD + RPI_BPLUS_GPIO_J8_11 = 17, ///< B+, Pin J8-11 + RPI_BPLUS_GPIO_J8_12 = 18, ///< B+, Pin J8-12, can be PWM channel 0 in ALT FUN 5 + RPI_BPLUS_GPIO_J8_13 = 27, ///< B+, Pin J8-13 + RPI_BPLUS_GPIO_J8_15 = 22, ///< B+, Pin J8-15 + RPI_BPLUS_GPIO_J8_16 = 23, ///< B+, Pin J8-16 + RPI_BPLUS_GPIO_J8_18 = 24, ///< B+, Pin J8-18 + RPI_BPLUS_GPIO_J8_19 = 10, ///< B+, Pin J8-19, MOSI when SPI0 in use + RPI_BPLUS_GPIO_J8_21 = 9, ///< B+, Pin J8-21, MISO when SPI0 in use + RPI_BPLUS_GPIO_J8_22 = 25, ///< B+, Pin J8-22 + RPI_BPLUS_GPIO_J8_23 = 11, ///< B+, Pin J8-23, CLK when SPI0 in use + RPI_BPLUS_GPIO_J8_24 = 8, ///< B+, Pin J8-24, CE0 when SPI0 in use + RPI_BPLUS_GPIO_J8_26 = 7, ///< B+, Pin J8-26, CE1 when SPI0 in use + RPI_BPLUS_GPIO_J8_29 = 5, ///< B+, Pin J8-29, + RPI_BPLUS_GPIO_J8_31 = 6, ///< B+, Pin J8-31, + RPI_BPLUS_GPIO_J8_32 = 12, ///< B+, Pin J8-32, + RPI_BPLUS_GPIO_J8_33 = 13, ///< B+, Pin J8-33, + RPI_BPLUS_GPIO_J8_35 = 19, ///< B+, Pin J8-35, + RPI_BPLUS_GPIO_J8_36 = 16, ///< B+, Pin J8-36, + RPI_BPLUS_GPIO_J8_37 = 26, ///< B+, Pin J8-37, + RPI_BPLUS_GPIO_J8_38 = 20, ///< B+, Pin J8-38, + RPI_BPLUS_GPIO_J8_40 = 21, ///< B+, Pin J8-40, +} RPiGPIOPin; + +// Defines for SPI +// 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 +#define BCM2835_SPI0_CLK 0x0008 ///< SPI Master Clock Divider +#define BCM2835_SPI0_DLEN 0x000c ///< SPI Master Data Length +#define BCM2835_SPI0_LTOH 0x0010 ///< SPI LOSSI mode TOH +#define BCM2835_SPI0_DC 0x0014 ///< SPI DMA DREQ Controls + +// Register masks for SPI0_CS +#define BCM2835_SPI0_CS_LEN_LONG 0x02000000 ///< Enable Long data word in Lossi mode if DMA_LEN is set +#define BCM2835_SPI0_CS_DMA_LEN 0x01000000 ///< Enable DMA mode in Lossi mode +#define BCM2835_SPI0_CS_CSPOL2 0x00800000 ///< Chip Select 2 Polarity +#define BCM2835_SPI0_CS_CSPOL1 0x00400000 ///< Chip Select 1 Polarity +#define BCM2835_SPI0_CS_CSPOL0 0x00200000 ///< Chip Select 0 Polarity +#define BCM2835_SPI0_CS_RXF 0x00100000 ///< RXF - RX FIFO Full +#define BCM2835_SPI0_CS_RXR 0x00080000 ///< RXR RX FIFO needs Reading ( full) +#define BCM2835_SPI0_CS_TXD 0x00040000 ///< TXD TX FIFO can accept Data +#define BCM2835_SPI0_CS_RXD 0x00020000 ///< RXD RX FIFO contains Data +#define BCM2835_SPI0_CS_DONE 0x00010000 ///< Done transfer Done +#define BCM2835_SPI0_CS_TE_EN 0x00008000 ///< Unused +#define BCM2835_SPI0_CS_LMONO 0x00004000 ///< Unused +#define BCM2835_SPI0_CS_LEN 0x00002000 ///< LEN LoSSI enable +#define BCM2835_SPI0_CS_REN 0x00001000 ///< REN Read Enable +#define BCM2835_SPI0_CS_ADCS 0x00000800 ///< ADCS Automatically Deassert Chip Select +#define BCM2835_SPI0_CS_INTR 0x00000400 ///< INTR Interrupt on RXR +#define BCM2835_SPI0_CS_INTD 0x00000200 ///< INTD Interrupt on Done +#define BCM2835_SPI0_CS_DMAEN 0x00000100 ///< DMAEN DMA Enable +#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_CPOL 0x00000008 ///< Clock Polarity +#define BCM2835_SPI0_CS_CPHA 0x00000004 ///< Clock Phase +#define BCM2835_SPI0_CS_CS 0x00000003 ///< Chip Select + +/// \brief bcm2835SPIBitOrder SPI Bit order +/// Specifies the SPI data bit ordering for bcm2835_spi_setBitOrder() +typedef enum +{ + BCM2835_SPI_BIT_ORDER_LSBFIRST = 0, ///< LSB First + BCM2835_SPI_BIT_ORDER_MSBFIRST = 1 ///< MSB First +}bcm2835SPIBitOrder; + +/// \brief SPI Data mode +/// Specify the SPI data mode to be passed to bcm2835_spi_setDataMode() +typedef enum +{ + BCM2835_SPI_MODE0 = 0, ///< CPOL = 0, CPHA = 0 + BCM2835_SPI_MODE1 = 1, ///< CPOL = 0, CPHA = 1 + BCM2835_SPI_MODE2 = 2, ///< CPOL = 1, CPHA = 0 + BCM2835_SPI_MODE3 = 3, ///< CPOL = 1, CPHA = 1 +}bcm2835SPIMode; + +/// \brief bcm2835SPIChipSelect +/// Specify the SPI chip select pin(s) +typedef enum +{ + BCM2835_SPI_CS0 = 0, ///< Chip Select 0 + BCM2835_SPI_CS1 = 1, ///< Chip Select 1 + BCM2835_SPI_CS2 = 2, ///< Chip Select 2 (ie pins CS1 and CS2 are asserted) + BCM2835_SPI_CS_NONE = 3, ///< No CS, control it yourself +} bcm2835SPIChipSelect; + +/// \brief bcm2835SPIClockDivider +/// Specifies the divider used to generate the SPI clock from the system clock. +/// Figures below give the divider, clock period and clock frequency. +/// Clock divided is based on nominal base clock rate of 250MHz +/// It is reported that (contrary to the documentation) any even divider may used. +/// The frequencies shown for each divider have been confirmed by measurement +typedef enum +{ + BCM2835_SPI_CLOCK_DIVIDER_65536 = 3814, ///< 65536 = 262.144us = 3.814697260kHz + BCM2835_SPI_CLOCK_DIVIDER_32768 = 7629, ///< 32768 = 131.072us = 7.629394531kHz + BCM2835_SPI_CLOCK_DIVIDER_16384 = 15258, ///< 16384 = 65.536us = 15.25878906kHz + BCM2835_SPI_CLOCK_DIVIDER_8192 = 30517, ///< 8192 = 32.768us = 30.51757813kHz + BCM2835_SPI_CLOCK_DIVIDER_4096 = 61035, ///< 4096 = 16.384us = 61.03515625kHz + BCM2835_SPI_CLOCK_DIVIDER_2048 = 122070, ///< 2048 = 8.192us = 122.0703125kHz + BCM2835_SPI_CLOCK_DIVIDER_1024 = 244140, ///< 1024 = 4.096us = 244.140625kHz + BCM2835_SPI_CLOCK_DIVIDER_512 = 488281, ///< 512 = 2.048us = 488.28125kHz + BCM2835_SPI_CLOCK_DIVIDER_256 = 976562, ///< 256 = 1.024us = 976.5625kHz + BCM2835_SPI_CLOCK_DIVIDER_128 = 1953125, ///< 128 = 512ns = = 1.953125MHz + BCM2835_SPI_CLOCK_DIVIDER_64 = 3906250, ///< 64 = 256ns = 3.90625MHz + BCM2835_SPI_CLOCK_DIVIDER_32 = 7812500, ///< 32 = 128ns = 7.8125MHz + BCM2835_SPI_CLOCK_DIVIDER_16 = 15625000, ///< 16 = 64ns = 15.625MHz + BCM2835_SPI_CLOCK_DIVIDER_8 = 31250000, ///< 8 = 32ns = 31.25MHz + BCM2835_SPI_CLOCK_DIVIDER_4 = 62500000, ///< 4 = 16ns = 62.5MHz + BCM2835_SPI_CLOCK_DIVIDER_2 = 125000000, ///< 2 = 8ns = 125MHz, fastest you can get + BCM2835_SPI_CLOCK_DIVIDER_1 = 3814, ///< 1 = 262.144us = 3.814697260kHz, same as 0/65536 + +} bcm2835SPIClockDivider; + +// Defines for I2C +// GPIO register offsets from BCM2835_BSC*_BASE. +// Offsets into the BSC Peripheral block in bytes per 3.1 BSC Register Map +#define BCM2835_BSC_C 0x0000 ///< BSC Master Control +#define BCM2835_BSC_S 0x0004 ///< BSC Master Status +#define BCM2835_BSC_DLEN 0x0008 ///< BSC Master Data Length +#define BCM2835_BSC_A 0x000c ///< BSC Master Slave Address +#define BCM2835_BSC_FIFO 0x0010 ///< BSC Master Data FIFO +#define BCM2835_BSC_DIV 0x0014 ///< BSC Master Clock Divider +#define BCM2835_BSC_DEL 0x0018 ///< BSC Master Data Delay +#define BCM2835_BSC_CLKT 0x001c ///< BSC Master Clock Stretch Timeout + +// Register masks for BSC_C +#define BCM2835_BSC_C_I2CEN 0x00008000 ///< I2C Enable, 0 = disabled, 1 = enabled +#define BCM2835_BSC_C_INTR 0x00000400 ///< Interrupt on RX +#define BCM2835_BSC_C_INTT 0x00000200 ///< Interrupt on TX +#define BCM2835_BSC_C_INTD 0x00000100 ///< Interrupt on DONE +#define BCM2835_BSC_C_ST 0x00000080 ///< Start transfer, 1 = Start a new transfer +#define BCM2835_BSC_C_CLEAR_1 0x00000020 ///< Clear FIFO Clear +#define BCM2835_BSC_C_CLEAR_2 0x00000010 ///< Clear FIFO Clear +#define BCM2835_BSC_C_READ 0x00000001 ///< Read transfer + +// Register masks for BSC_S +#define BCM2835_BSC_S_CLKT 0x00000200 ///< Clock stretch timeout +#define BCM2835_BSC_S_ERR 0x00000100 ///< ACK error +#define BCM2835_BSC_S_RXF 0x00000080 ///< RXF FIFO full, 0 = FIFO is not full, 1 = FIFO is full +#define BCM2835_BSC_S_TXE 0x00000040 ///< TXE FIFO full, 0 = FIFO is not full, 1 = FIFO is full +#define BCM2835_BSC_S_RXD 0x00000020 ///< RXD FIFO contains data +#define BCM2835_BSC_S_TXD 0x00000010 ///< TXD FIFO can accept data +#define BCM2835_BSC_S_RXR 0x00000008 ///< RXR FIFO needs reading (full) +#define BCM2835_BSC_S_TXW 0x00000004 ///< TXW FIFO needs writing (full) +#define BCM2835_BSC_S_DONE 0x00000002 ///< Transfer DONE +#define BCM2835_BSC_S_TA 0x00000001 ///< Transfer Active + +#define BCM2835_BSC_FIFO_SIZE 16 ///< BSC FIFO size + +/// \brief bcm2835I2CClockDivider +/// Specifies the divider used to generate the I2C clock from the system clock. +/// Clock divided is based on nominal base clock rate of 250MHz +typedef enum +{ + BCM2835_I2C_CLOCK_DIVIDER_2500 = 2500, ///< 2500 = 10us = 100 kHz + BCM2835_I2C_CLOCK_DIVIDER_626 = 626, ///< 622 = 2.504us = 399.3610 kHz + BCM2835_I2C_CLOCK_DIVIDER_150 = 150, ///< 150 = 60ns = 1.666 MHz (default at reset) + BCM2835_I2C_CLOCK_DIVIDER_148 = 148, ///< 148 = 59ns = 1.689 MHz +} bcm2835I2CClockDivider; + +/// \brief bcm2835I2CReasonCodes +/// Specifies the reason codes for the bcm2835_i2c_write and bcm2835_i2c_read functions. +typedef enum +{ + BCM2835_I2C_REASON_OK = 0x00, ///< Success + BCM2835_I2C_REASON_ERROR_NACK = 0x01, ///< Received a NACK + BCM2835_I2C_REASON_ERROR_CLKT = 0x02, ///< Received Clock Stretch Timeout + BCM2835_I2C_REASON_ERROR_DATA = 0x04, ///< Not all data is sent / received +} bcm2835I2CReasonCodes; + +// Defines for ST +// GPIO register offsets from BCM2835_ST_BASE. +// Offsets into the ST Peripheral block in bytes per 12.1 System Timer Registers +// The System Timer peripheral provides four 32-bit timer channels and a single 64-bit free running counter. +// BCM2835_ST_CLO is the System Timer Counter Lower bits register. +// The system timer free-running counter lower register is a read-only register that returns the current value +// of the lower 32-bits of the free running counter. +// BCM2835_ST_CHI is the System Timer Counter Upper bits register. +// The system timer free-running counter upper register is a read-only register that returns the current value +// of the upper 32-bits of the free running counter. +#define BCM2835_ST_CS 0x0000 ///< System Timer Control/Status +#define BCM2835_ST_CLO 0x0004 ///< System Timer Counter Lower 32 bits +#define BCM2835_ST_CHI 0x0008 ///< System Timer Counter Upper 32 bits + +/// @} + + +// Defines for PWM, word offsets (ie 4 byte multiples) +#define BCM2835_PWM_CONTROL 0 +#define BCM2835_PWM_STATUS 1 +#define BCM2835_PWM_DMAC 2 +#define BCM2835_PWM0_RANGE 4 +#define BCM2835_PWM0_DATA 5 +#define BCM2835_PWM_FIF1 6 +#define BCM2835_PWM1_RANGE 8 +#define BCM2835_PWM1_DATA 9 + +// Defines for PWM Clock, word offsets (ie 4 byte multiples) +#define BCM2835_PWMCLK_CNTL 40 +#define BCM2835_PWMCLK_DIV 41 +#define BCM2835_PWM_PASSWRD (0x5A << 24) ///< Password to enable setting PWM clock + +#define BCM2835_PWM1_MS_MODE 0x8000 ///< Run in Mark/Space mode +#define BCM2835_PWM1_USEFIFO 0x2000 ///< Data from FIFO +#define BCM2835_PWM1_REVPOLAR 0x1000 ///< Reverse polarity +#define BCM2835_PWM1_OFFSTATE 0x0800 ///< Ouput Off state +#define BCM2835_PWM1_REPEATFF 0x0400 ///< Repeat last value if FIFO empty +#define BCM2835_PWM1_SERIAL 0x0200 ///< Run in serial mode +#define BCM2835_PWM1_ENABLE 0x0100 ///< Channel Enable + +#define BCM2835_PWM0_MS_MODE 0x0080 ///< Run in Mark/Space mode +#define BCM2835_PWM_CLEAR_FIFO 0x0040 ///< Clear FIFO +#define BCM2835_PWM0_USEFIFO 0x0020 ///< Data from FIFO +#define BCM2835_PWM0_REVPOLAR 0x0010 ///< Reverse polarity +#define BCM2835_PWM0_OFFSTATE 0x0008 ///< Ouput Off state +#define BCM2835_PWM0_REPEATFF 0x0004 ///< Repeat last value if FIFO empty +#define BCM2835_PWM0_SERIAL 0x0002 ///< Run in serial mode +#define BCM2835_PWM0_ENABLE 0x0001 ///< Channel Enable + +/// \brief bcm2835PWMClockDivider +/// Specifies the divider used to generate the PWM clock from the system clock. +/// Figures below give the divider, clock period and clock frequency. +/// Clock divided is based on nominal PWM base clock rate of 19.2MHz +/// The frequencies shown for each divider have been confirmed by measurement +typedef enum +{ + BCM2835_PWM_CLOCK_DIVIDER_32768 = 32768, ///< 32768 = 585Hz + BCM2835_PWM_CLOCK_DIVIDER_16384 = 16384, ///< 16384 = 1171.8Hz + BCM2835_PWM_CLOCK_DIVIDER_8192 = 8192, ///< 8192 = 2.34375kHz + BCM2835_PWM_CLOCK_DIVIDER_4096 = 4096, ///< 4096 = 4.6875kHz + BCM2835_PWM_CLOCK_DIVIDER_2048 = 2048, ///< 2048 = 9.375kHz + BCM2835_PWM_CLOCK_DIVIDER_1024 = 1024, ///< 1024 = 18.75kHz + BCM2835_PWM_CLOCK_DIVIDER_512 = 512, ///< 512 = 37.5kHz + BCM2835_PWM_CLOCK_DIVIDER_256 = 256, ///< 256 = 75kHz + BCM2835_PWM_CLOCK_DIVIDER_128 = 128, ///< 128 = 150kHz + BCM2835_PWM_CLOCK_DIVIDER_64 = 64, ///< 64 = 300kHz + BCM2835_PWM_CLOCK_DIVIDER_32 = 32, ///< 32 = 600.0kHz + BCM2835_PWM_CLOCK_DIVIDER_16 = 16, ///< 16 = 1.2MHz + BCM2835_PWM_CLOCK_DIVIDER_8 = 8, ///< 8 = 2.4MHz + BCM2835_PWM_CLOCK_DIVIDER_4 = 4, ///< 4 = 4.8MHz + BCM2835_PWM_CLOCK_DIVIDER_2 = 2, ///< 2 = 9.6MHz, fastest you can get + BCM2835_PWM_CLOCK_DIVIDER_1 = 1, ///< 1 = 4.6875kHz, same as divider 4096 +} bcm2835PWMClockDivider; + +/*Add for BananaPro by LeMaker Team*/ +#define SUNXI_PERI_BASE 0x01C20000 +/// Base Physical Address of the System Timer registers +#define SUNXI_ST_BASE (SUNXI_PERI_BASE + 0x3000) +/// Base Physical Address of the Pads registers +#define SUNXI_GPIO_PADS (SUNXI_PERI_BASE + 0x800) +/// Base Physical Address of the Clock/timer registers +#define SUNXI_CLOCK_BASE (SUNXI_PERI_BASE + 0x101000) +/// Base Physical Address of the GPIO registers +#define SUNXI_GPIO_BASE (SUNXI_PERI_BASE + 0x800) +/// Offset Address of the GPIO CFG registers +#define SUNXI_GPIO_CFG_OFFSET (0x00) +/// Offset Address of the GPIO DAT registers +#define SUNXI_GPIO_DAT_OFFSET (0x10) +/// Offset Address of the GPIO PUL registers +#define SUNXI_GPIO_PUL_OFFSET (0x1C) +/// Base Physical Address of the SPI0 registers +#define SUNXI_SPI0_BASE (0x01C05000) +/// Base Physical Address of the BSC0 registers +#define SUNXI_BSC0_BASE (SUNXI_PERI_BASE + 0x205000) +/// Base Physical Address of the PWM registers +#define SUNXI_GPIO_PWM (SUNXI_PERI_BASE + 0xC00) +/// Offset Address of the PWM CFG registers +#define SUNXI_PWM_CTRL_OFFSET (0x200) +/// Offset Address of the PWM CH0 registers +#define SUNXI_PWM_CH0_OFFSET (0x204) +/// Offset Address of the PWM CH1 registers +#define SUNXI_PWM_CH1_OFFSET (0x208) + /// Base Physical Address of the BSC1 registers +#define SUNXI_BSC1_BASE (SUNXI_PERI_BASE + 0x804000) +#define SUNXI_IIC2_BASE (SUNXI_PERI_BASE + 0xB400) +#define I2C2_CLK_OFFSET 0x14 +#define SUNXI_TIMER_BASE (0x01C20C00) +#define MAP_SIZE (4096) +#define MAP_MASK (MAP_SIZE - 1) + +#define SUNXI_PWM_CLKDIV_MASK (0xF<<15) + +#define SUNXI_SPI0_CLK 0x1C ///< SPI Master Clock Divider +#define SUNXI_SPI0_RXDATA 0x00//RX data reg +#define SUNXI_SPI0_TXDATA 0x04//TX data reg +#define SUNXI_SPI0_CTRL 0x08//control reg +#define SUNXI_SPI0_INT_CTL 0x0C//int control reg +#define SUNXI_SPI0_STAT 0x10//status reg +#define SUNXI_SPI0_DMA_CTRL 0x14//DMA control reg +#define SUNXI_SPI0_BC 0x20//burst counter reg +#define SUNXI_SPI0_TC 0x24//transmit counter reg +#define SUNXI_SPI0_FIFO_STA (0x28) + +#define SUNXI_SPI0_CS_CS 0x3000 ///< Chip Select +#define SUNXI_SPIO_CS_CTRL 0x10000 +#define SUNXI_SPIO_CS_POL 0x10 +#define SUNXI_SPI0_MASTER_MASK 0x2 ///master or slave +#define SUNXI_SPI0_MSBFIRST_MASK 0x40 ///MSB +#define SUNXI_SPI0_STAT_MASK (0x7f|(0x7f<<8)|(0x3<<16)) +#define SUNXI_SPI0_DRQEN_MASK (0x1f|(0x1f<<8)) +#define SUNXI_SPI0_FIFORST_MASK (3<<8) +#define SUNXI_SPI0_CTL_XCH_MASK (0x1 << 10) + +#define SUNXI_SPI0_INTEN_RO (0x1 << 5) //rxFIFO Overflow Interrupt Enable ---used for error detect +#define SUNXI_SPI0_INTEN_RU (0x1 << 6) // rxFIFO Underrun Interrupt Enable ---used for error detect + +#define SUNXI_SPI0_INTEN_TO (0x1 << 13) // txFIFO Overflow Interrupt Enable +#define SUNXI_SPI0_INTEN_TC (0x1 << 16) // Transfer Completed Interrupt Enable +#define SUNXI_SPI0_INTEN_ERR (SUNXI_SPI0_INTEN_TO|SUNXI_SPI0_INTEN_RU|SUNXI_SPI0_INTEN_RO) //NO txFIFO underrun +#define SUNXI_SPI0_INTEN_MASK (0x7f|(0x7f<<8)|(0x3<<16)) +#define SUNXI_SPI0_FIFO_TXCNT (0x7F << 16)// txFIFO counter +#define SUNXI_SPI0_TXCNT_BIT_POS (16) +#define SUNXI_SPI0_FIFO_RXCNT (0x7F << 0) // rxFIFO counter + +/*end 2014.12.29*/ + +// Historical name compatibility +#ifndef BCM2835_NO_DELAY_COMPATIBILITY +#define delay(x) bcm2835_delay(x) +#define delayMicroseconds(x) bcm2835_delayMicroseconds(x) +#endif + +#ifdef __cplusplus +extern "C" { +#endif + + /// \defgroup init Library initialisation and management + /// These functions allow you to intialise and control the bcm2835 library + /// @{ + + /// Initialise the library by opening /dev/mem and getting pointers to the + /// internal memory for BCM 2835 device registers. You must call this (successfully) + /// before calling any other + /// functions in this library (except bcm2835_set_debug). + /// If bcm2835_init() fails by returning 0, + /// calling any other function may result in crashes or other failures. + /// Prints messages to stderr in case of errors. + /// \return 1 if successful else 0 + extern int bcm2835_init(void); + + /// Close the library, deallocating any allocated memory and closing /dev/mem + /// \return 1 if successful else 0 + extern int bcm2835_close(void); + + /// Sets the debug level of the library. + /// A value of 1 prevents mapping to /dev/mem, and makes the library print out + /// what it would do, rather than accessing the GPIO registers. + /// A value of 0, the default, causes normal operation. + /// Call this before calling bcm2835_init(); + /// \param[in] debug The new debug level. 1 means debug + extern void bcm2835_set_debug(uint8_t debug); + + /// @} // end of init + + /// \defgroup lowlevel Low level register access + /// These functions provide low level register access, and should not generally + /// need to be used + /// + /// @{ + + /// Gets the base of a register + /// \param[in] regbase You can use one of the common values BCM2835_REGBASE_* + /// in \ref bcm2835RegisterBase + /// \return the register base + /// \sa Physical Addresses + extern uint32_t* bcm2835_regbase(uint8_t regbase); + + /// Reads 32 bit value from a peripheral address + /// 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 + /// \sa Physical Addresses + extern uint32_t bcm2835_peri_read(volatile uint32_t* paddr); + + + /// Reads 32 bit value from a peripheral address without the read barrier + /// You should only use this when your code has previously called bcm2835_peri_read() + /// within the same peripheral, and no other peripheral access has occurred since. + /// \param[in] paddr Physical address to read from. See BCM2835_GPIO_BASE etc. + /// \return the value read from the 32 bit register + /// \sa Physical Addresses + extern uint32_t bcm2835_peri_read_nb(volatile uint32_t* paddr); + + + /// Writes 32 bit value from a peripheral address + /// 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 + /// \sa Physical Addresses + extern void bcm2835_peri_write(volatile uint32_t* paddr, uint32_t value); + + /// Writes 32 bit value from a peripheral address without the write barrier + /// You should only use this when your code has previously called bcm2835_peri_write() + /// within the same peripheral, and no other peripheral access has occurred since. + /// \param[in] paddr Physical address to read from. See BCM2835_GPIO_BASE etc. + /// \param[in] value The 32 bit value to write + /// \sa Physical Addresses + extern void bcm2835_peri_write_nb(volatile uint32_t* paddr, uint32_t value); + + /// Alters a number of bits in a 32 peripheral regsiter. + /// It reads the current valu and then alters the bits 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 + /// 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. + /// \param[in] mask Bitmask that defines the bits that will be altered in the register. + /// \sa Physical Addresses + extern void bcm2835_peri_set_bits(volatile uint32_t* paddr, uint32_t value, uint32_t mask); + /// @} // end of lowlevel + + /// \defgroup gpio GPIO register access + /// These functions allow you to control the GPIO interface. You can set the + /// function of each GPIO pin, read the input state and set the output state. + /// @{ + + /// Sets the Function Select register for the given pin, which configures + /// the pin as Input, Output or one of the 6 alternate functions. + /// \param[in] pin GPIO number, or one of RPI_GPIO_P1_* from \ref RPiGPIOPin. + /// \param[in] mode Mode to set the pin to, one of BCM2835_GPIO_FSEL_* from \ref bcm2835FunctionSelect + extern void bcm2835_gpio_fsel(uint8_t pin, uint8_t mode); + + /// Sets the specified pin output to + /// HIGH. + /// \param[in] pin GPIO number, or one of RPI_GPIO_P1_* from \ref RPiGPIOPin. + /// \sa bcm2835_gpio_write() + extern void bcm2835_gpio_set(uint8_t pin); + + /// Sets the specified pin output to + /// LOW. + /// \param[in] pin GPIO number, or one of RPI_GPIO_P1_* from \ref RPiGPIOPin. + /// \sa bcm2835_gpio_write() + extern void bcm2835_gpio_clr(uint8_t pin); + + /// Sets any of the first 32 GPIO output pins specified in the mask to + /// HIGH. + /// \param[in] mask Mask of pins to affect. Use eg: (1 << RPI_GPIO_P1_03) | (1 << RPI_GPIO_P1_05) + /// \sa bcm2835_gpio_write_multi() + extern void bcm2835_gpio_set_multi(uint32_t mask); + + /// Sets any of the first 32 GPIO output pins specified in the mask to + /// LOW. + /// \param[in] mask Mask of pins to affect. Use eg: (1 << RPI_GPIO_P1_03) | (1 << RPI_GPIO_P1_05) + /// \sa bcm2835_gpio_write_multi() + extern void bcm2835_gpio_clr_multi(uint32_t mask); + + /// Reads the current level on the specified + /// pin and returns either HIGH or LOW. Works whether or not the pin + /// is an input or an output. + /// \param[in] pin GPIO number, or one of RPI_GPIO_P1_* from \ref RPiGPIOPin. + /// \return the current level either HIGH or LOW + extern uint8_t bcm2835_gpio_lev(uint8_t pin); + + /// Event Detect Status. + /// Tests whether the specified pin has detected a level or edge + /// as requested by bcm2835_gpio_ren(), bcm2835_gpio_fen(), bcm2835_gpio_hen(), + /// bcm2835_gpio_len(), bcm2835_gpio_aren(), bcm2835_gpio_afen(). + /// Clear the flag for a given pin by calling bcm2835_gpio_set_eds(pin); + /// \param[in] pin GPIO number, or one of RPI_GPIO_P1_* from \ref RPiGPIOPin. + /// \return HIGH if the event detect status for the given pin is true. + extern uint8_t bcm2835_gpio_eds(uint8_t pin); + + /// Sets the Event Detect Status register for a given pin to 1, + /// which has the effect of clearing the flag. Use this afer seeing + /// an Event Detect Status on the pin. + /// \param[in] pin GPIO number, or one of RPI_GPIO_P1_* from \ref RPiGPIOPin. + extern void bcm2835_gpio_set_eds(uint8_t pin); + + /// Enable Rising Edge Detect Enable for the specified pin. + /// When a rising edge is detected, sets the appropriate pin in Event Detect Status. + /// The GPRENn registers use + /// synchronous edge detection. This means the input signal is sampled using the + /// system clock and then it is looking for a ?011? pattern on the sampled signal. This + /// has the effect of suppressing glitches. + /// \param[in] pin GPIO number, or one of RPI_GPIO_P1_* from \ref RPiGPIOPin. + extern void bcm2835_gpio_ren(uint8_t pin); + + /// Disable Rising Edge Detect Enable for the specified pin. + /// \param[in] pin GPIO number, or one of RPI_GPIO_P1_* from \ref RPiGPIOPin. + extern void bcm2835_gpio_clr_ren(uint8_t pin); + + /// Enable Falling Edge Detect Enable for the specified pin. + /// When a falling edge is detected, sets the appropriate pin in Event Detect Status. + /// The GPRENn registers use + /// synchronous edge detection. This means the input signal is sampled using the + /// system clock and then it is looking for a ?100? pattern on the sampled signal. This + /// has the effect of suppressing glitches. + /// \param[in] pin GPIO number, or one of RPI_GPIO_P1_* from \ref RPiGPIOPin. + extern void bcm2835_gpio_fen(uint8_t pin); + + /// Disable Falling Edge Detect Enable for the specified pin. + /// \param[in] pin GPIO number, or one of RPI_GPIO_P1_* from \ref RPiGPIOPin. + extern void bcm2835_gpio_clr_fen(uint8_t pin); + + /// Enable High Detect Enable for the specified pin. + /// When a HIGH level is detected on the pin, sets the appropriate pin in Event Detect Status. + /// \param[in] pin GPIO number, or one of RPI_GPIO_P1_* from \ref RPiGPIOPin. + extern void bcm2835_gpio_hen(uint8_t pin); + + /// Disable High Detect Enable for the specified pin. + /// \param[in] pin GPIO number, or one of RPI_GPIO_P1_* from \ref RPiGPIOPin. + extern void bcm2835_gpio_clr_hen(uint8_t pin); + + /// Enable Low Detect Enable for the specified pin. + /// When a LOW level is detected on the pin, sets the appropriate pin in Event Detect Status. + /// \param[in] pin GPIO number, or one of RPI_GPIO_P1_* from \ref RPiGPIOPin. + extern void bcm2835_gpio_len(uint8_t pin); + + /// Disable Low Detect Enable for the specified pin. + /// \param[in] pin GPIO number, or one of RPI_GPIO_P1_* from \ref RPiGPIOPin. + extern void bcm2835_gpio_clr_len(uint8_t pin); + + /// Enable Asynchronous Rising Edge Detect Enable for the specified pin. + /// When a rising edge is detected, sets the appropriate pin in Event Detect Status. + /// Asynchronous means the incoming signal is not sampled by the system clock. As such + /// rising edges of very short duration can be detected. + /// \param[in] pin GPIO number, or one of RPI_GPIO_P1_* from \ref RPiGPIOPin. + extern void bcm2835_gpio_aren(uint8_t pin); + + /// Disable Asynchronous Rising Edge Detect Enable for the specified pin. + /// \param[in] pin GPIO number, or one of RPI_GPIO_P1_* from \ref RPiGPIOPin. + extern void bcm2835_gpio_clr_aren(uint8_t pin); + + /// Enable Asynchronous Falling Edge Detect Enable for the specified pin. + /// When a falling edge is detected, sets the appropriate pin in Event Detect Status. + /// Asynchronous means the incoming signal is not sampled by the system clock. As such + /// falling edges of very short duration can be detected. + /// \param[in] pin GPIO number, or one of RPI_GPIO_P1_* from \ref RPiGPIOPin. + extern void bcm2835_gpio_afen(uint8_t pin); + + /// Disable Asynchronous Falling Edge Detect Enable for the specified pin. + /// \param[in] pin GPIO number, or one of RPI_GPIO_P1_* from \ref RPiGPIOPin. + extern void bcm2835_gpio_clr_afen(uint8_t pin); + + /// Sets the Pull-up/down register for the given pin. This is + /// used with bcm2835_gpio_pudclk() to set the Pull-up/down resistor for the given pin. + /// However, it is usually more convenient to use bcm2835_gpio_set_pud(). + /// \param[in] pud The desired Pull-up/down mode. One of BCM2835_GPIO_PUD_* from bcm2835PUDControl + /// \sa bcm2835_gpio_set_pud() + extern void bcm2835_gpio_pud(uint8_t pud); + + /// Clocks the Pull-up/down value set earlier by bcm2835_gpio_pud() into the pin. + /// \param[in] pin GPIO number, or one of RPI_GPIO_P1_* from \ref RPiGPIOPin. + /// \param[in] on HIGH to clock the value from bcm2835_gpio_pud() into the pin. + /// LOW to remove the clock. + /// \sa bcm2835_gpio_set_pud() + extern void bcm2835_gpio_pudclk(uint8_t pin, uint8_t on); + + /// Reads and returns the Pad Control for the given GPIO group. + /// \param[in] group The GPIO pad group number, one of BCM2835_PAD_GROUP_GPIO_* + /// \return Mask of bits from BCM2835_PAD_* from \ref bcm2835PadGroup + extern uint32_t bcm2835_gpio_pad(uint8_t group); + + /// Sets the Pad Control for the given GPIO group. + /// \param[in] group The GPIO pad group number, one of BCM2835_PAD_GROUP_GPIO_* + /// \param[in] control Mask of bits from BCM2835_PAD_* from \ref bcm2835PadGroup. Note + /// that it is not necessary to include BCM2835_PAD_PASSWRD in the mask as this + /// is automatically included. + extern void bcm2835_gpio_set_pad(uint8_t group, uint32_t control); + + /// Delays for the specified number of milliseconds. + /// Uses nanosleep(), and therefore does not use CPU until the time is up. + /// However, you are at the mercy of nanosleep(). From the manual for nanosleep(): + /// If the interval specified in req is not an exact multiple of the granularity + /// underlying clock (see time(7)), then the interval will be + /// rounded up to the next multiple. Furthermore, after the sleep completes, + /// there may still be a delay before the CPU becomes free to once + /// again execute the calling thread. + /// \param[in] millis Delay in milliseconds + extern void bcm2835_delay (unsigned int millis); + + /// Delays for the specified number of microseconds. + /// Uses a combination of nanosleep() and a busy wait loop on the BCM2835 system timers, + /// However, you are at the mercy of nanosleep(). From the manual for nanosleep(): + /// If the interval specified in req is not an exact multiple of the granularity + /// underlying clock (see time(7)), then the interval will be + /// rounded up to the next multiple. Furthermore, after the sleep completes, + /// there may still be a delay before the CPU becomes free to once + /// again execute the calling thread. + /// For times less than about 450 microseconds, uses a busy wait on the System Timer. + /// It is reported that a delay of 0 microseconds on RaspberryPi will in fact + /// result in a delay of about 80 microseconds. Your mileage may vary. + /// \param[in] micros Delay in microseconds + extern void bcm2835_delayMicroseconds (uint64_t micros); + + /// Sets the output state of the specified pin + /// \param[in] pin GPIO number, or one of RPI_GPIO_P1_* from \ref RPiGPIOPin. + /// \param[in] on HIGH sets the output to HIGH and LOW to LOW. + extern void bcm2835_gpio_write(uint8_t pin, uint8_t on); + + /// Sets any of the first 32 GPIO output pins specified in the mask to the state given by on + /// \param[in] mask Mask of pins to affect. Use eg: (1 << RPI_GPIO_P1_03) | (1 << RPI_GPIO_P1_05) + /// \param[in] on HIGH sets the output to HIGH and LOW to LOW. + extern void bcm2835_gpio_write_multi(uint32_t mask, uint8_t on); + + /// Sets the first 32 GPIO output pins specified in the mask to the value given by value + /// \param[in] value values required for each bit masked in by mask, eg: (1 << RPI_GPIO_P1_03) | (1 << RPI_GPIO_P1_05) + /// \param[in] mask Mask of pins to affect. Use eg: (1 << RPI_GPIO_P1_03) | (1 << RPI_GPIO_P1_05) + extern void bcm2835_gpio_write_mask(uint32_t value, uint32_t mask); + + /// Sets the Pull-up/down mode for the specified pin. This is more convenient than + /// clocking the mode in with bcm2835_gpio_pud() and bcm2835_gpio_pudclk(). + /// \param[in] pin GPIO number, or one of RPI_GPIO_P1_* from \ref RPiGPIOPin. + /// \param[in] pud The desired Pull-up/down mode. One of BCM2835_GPIO_PUD_* from bcm2835PUDControl + extern void bcm2835_gpio_set_pud(uint8_t pin, uint8_t pud); + + /// @} + + /// \defgroup spi SPI access + /// These functions let you use SPI0 (Serial Peripheral Interface) to + /// interface with an external SPI device. + /// @{ + + /// Start SPI operations. + /// Forces RPi SPI0 pins P1-19 (MOSI), P1-21 (MISO), P1-23 (CLK), P1-24 (CE0) and P1-26 (CE1) + /// to alternate function ALT0, which enables those pins for SPI interface. + /// You should call bcm2835_spi_end() when all SPI funcitons are complete to return the pins to + /// their default functions + /// \sa bcm2835_spi_end() + extern void bcm2835_spi_begin(void); + + /// End SPI operations. + /// SPI0 pins P1-19 (MOSI), P1-21 (MISO), P1-23 (CLK), P1-24 (CE0) and P1-26 (CE1) + /// are returned to their default INPUT behaviour. + extern void bcm2835_spi_end(void); + + /// Sets the SPI bit order + /// NOTE: has no effect. Not supported by SPI0. + /// 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_*, + /// see \ref bcm2835SPIClockDivider + extern void bcm2835_spi_setClockDivider(uint32_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*, + /// see \ref bcm2835SPIMode + extern void bcm2835_spi_setDataMode(uint8_t mode); + + /// Sets the chip select pin(s) + /// When an bcm2835_spi_transfer() is made, the selected pin(s) will be asserted during the + /// transfer. + /// \param[in] cs Specifies the CS pins(s) that are used to activate the desired slave. + /// One of BCM2835_SPI_CS*, see \ref bcm2835SPIChipSelect + extern void bcm2835_spi_chipSelect(uint8_t cs); + + /// Sets the chip select pin polarity for a given pin + /// When an bcm2835_spi_transfer() occurs, the currently selected chip select pin(s) + /// will be asserted to the + /// value given by active. When transfers are not happening, the chip select pin(s) + /// return to the complement (inactive) value. + /// \param[in] cs The chip select pin to affect + /// \param[in] active Whether the chip select pin is to be active HIGH + extern void bcm2835_spi_setChipSelectPolarity(uint8_t cs, uint8_t active); + + /// Transfers one byte to and from the currently selected SPI slave. + /// Asserts the currently selected CS pins (as previously set by bcm2835_spi_chipSelect) + /// during the transfer. + /// Clocks the 8 bit value out on MOSI, and simultaneously clocks in data from MISO. + /// Returns the read data byte from the slave. + /// Uses polled transfer as per section 10.6.1 of the BCM 2835 ARM Peripherls manual + /// \param[in] value The 8 bit data byte to write to MOSI + /// \return The 8 bit byte simultaneously read from MISO + /// \sa bcm2835_spi_transfern() + extern uint8_t bcm2835_spi_transfer(uint8_t value); + + /// Transfers any number of bytes to and from the currently selected SPI slave. + /// Asserts the currently selected CS pins (as previously set by bcm2835_spi_chipSelect) + /// during the transfer. + /// Clocks the len 8 bit bytes out on MOSI, and simultaneously clocks in data from MISO. + /// The data read read from the slave is placed into rbuf. rbuf must be at least len bytes long + /// Uses polled transfer as per section 10.6.1 of the BCM 2835 ARM Peripherls manual + /// \param[in] tbuf Buffer of bytes to send. + /// \param[out] rbuf Received bytes will by put in this buffer + /// \param[in] len Number of bytes in the tbuf buffer, and the number of bytes to send/received + /// \sa bcm2835_spi_transfer() + extern void bcm2835_spi_transfernb(char* tbuf, char* rbuf, uint32_t len); + + /// Transfers any number of bytes to and from the currently selected SPI slave + /// using bcm2835_spi_transfernb. + /// The returned data from the slave replaces the transmitted data in the buffer. + /// \param[in,out] buf Buffer of bytes to send. Received bytes will replace the contents + /// \param[in] len Number of bytes int eh buffer, and the number of bytes to send/received + /// \sa bcm2835_spi_transfer() + extern void bcm2835_spi_transfern(char* buf, uint32_t len); + + /// Transfers any number of bytes to the currently selected SPI slave. + /// Asserts the currently selected CS pins (as previously set by bcm2835_spi_chipSelect) + /// during the transfer. + /// \param[in] buf Buffer of bytes to send. + /// \param[in] len Number of bytes in the tbuf buffer, and the number of bytes to send + extern void bcm2835_spi_writenb(char* buf, uint32_t len); + + /// @} + + /// \defgroup i2c I2C access + /// These functions let you use I2C (The Broadcom Serial Control bus with the Philips + /// I2C bus/interface version 2.1 January 2000.) to interface with an external I2C device. + /// @{ + + /// Start I2C operations. + /// Forces RPi I2C pins P1-03 (SDA) and P1-05 (SCL) + /// to alternate function ALT0, which enables those pins for I2C interface. + /// You should call bcm2835_i2c_end() when all I2C functions are complete to return the pins to + /// their default functions + /// \sa bcm2835_i2c_end() + extern void bcm2835_i2c_begin(void); + + /// End I2C operations. + /// I2C pins P1-03 (SDA) and P1-05 (SCL) + /// are returned to their default INPUT behaviour. + extern void bcm2835_i2c_end(void); + + /// Sets the I2C slave address. + /// \param[in] addr The I2C slave address. + extern void bcm2835_i2c_setSlaveAddress(uint8_t addr); + + /// Sets the I2C clock divider and therefore the I2C clock speed. + /// \param[in] divider The desired I2C clock divider, one of BCM2835_I2C_CLOCK_DIVIDER_*, + /// see \ref bcm2835I2CClockDivider + extern void bcm2835_i2c_setClockDivider(uint16_t divider); + + /// Sets the I2C clock divider by converting the baudrate parameter to + /// the equivalent I2C clock divider. ( see \sa bcm2835_i2c_setClockDivider) + /// For the I2C standard 100khz you would set baudrate to 100000 + /// The use of baudrate corresponds to its use in the I2C kernel device + /// driver. (Of course, bcm2835 has nothing to do with the kernel driver) + extern void bcm2835_i2c_set_baudrate(uint32_t baudrate); + + /// Transfers any number of bytes to the currently selected I2C slave. + /// (as previously set by \sa bcm2835_i2c_setSlaveAddress) + /// \param[in] buf Buffer of bytes to send. + /// \param[in] len Number of bytes in the buf buffer, and the number of bytes to send. + /// \return reason see \ref bcm2835I2CReasonCodes + extern uint8_t bcm2835_i2c_write(const char * buf, uint32_t len); + + /// Transfers any number of bytes from the currently selected I2C slave. + /// (as previously set by \sa bcm2835_i2c_setSlaveAddress) + /// \param[in] buf Buffer of bytes to receive. + /// \param[in] len Number of bytes in the buf buffer, and the number of bytes to received. + /// \return reason see \ref bcm2835I2CReasonCodes + extern uint8_t bcm2835_i2c_read(char* buf, uint32_t len); + + /// Allows reading from I2C slaves that require a repeated start (without any prior stop) + /// to read after the required slave register has been set. For example, the popular + /// MPL3115A2 pressure and temperature sensor. Note that your device must support or + /// require this mode. If your device does not require this mode then the standard + /// combined: + /// \sa bcm2835_i2c_write + /// \sa bcm2835_i2c_read + /// are a better choice. + /// Will read from the slave previously set by \sa bcm2835_i2c_setSlaveAddress + /// \param[in] regaddr Buffer containing the slave register you wish to read from. + /// \param[in] buf Buffer of bytes to receive. + /// \param[in] len Number of bytes in the buf buffer, and the number of bytes to received. + /// \return reason see \ref bcm2835I2CReasonCodes + extern uint8_t bcm2835_i2c_read_register_rs(char* regaddr, char* buf, uint32_t len); + + /// Allows sending an arbitrary number of bytes to I2C slaves before issuing a repeated + /// start (with no prior stop) and reading a response. + /// Necessary for devices that require such behavior, such as the MLX90620. + /// Will write to and read from the slave previously set by \sa bcm2835_i2c_setSlaveAddress + /// \param[in] cmds Buffer containing the bytes to send before the repeated start condition. + /// \param[in] cmds_len Number of bytes to send from cmds buffer + /// \param[in] buf Buffer of bytes to receive. + /// \param[in] buf_len Number of bytes to receive in the buf buffer. + /// \return reason see \ref bcm2835I2CReasonCodes + extern uint8_t bcm2835_i2c_write_read_rs(char* cmds, uint32_t cmds_len, char* buf, uint32_t buf_len); + + /// @} + + /// \defgroup st System Timer access + /// Allows access to and delays using the System Timer Counter. + /// @{ + + /// Read the System Timer Counter register. + /// \return the value read from the System Timer Counter Lower 32 bits register + extern uint64_t bcm2835_st_read(void); + + /// Delays for the specified number of microseconds with offset. + /// \param[in] offset_micros Offset in microseconds + /// \param[in] micros Delay in microseconds + extern void bcm2835_st_delay(uint64_t offset_micros, uint64_t micros); + + /// @} + + /// \defgroup pwm Pulse Width Modulation + /// Allows control of 2 independent PWM channels. A limited subset of GPIO pins + /// can be connected to one of these 2 channels, allowing PWM control of GPIO pins. + /// You have to set the desired pin into a particular Alt Fun to PWM output. See the PWM + /// documentation on the Main Page. + /// @{ + + /// Sets the PWM clock divisor, + /// to control the basic PWM pulse widths. + /// \param[in] divisor Divides the basic 19.2MHz PWM clock. You can use one of the common + /// values BCM2835_PWM_CLOCK_DIVIDER_* in \ref bcm2835PWMClockDivider + extern void bcm2835_pwm_set_clock(uint32_t divisor); + + /// Sets the mode of the given PWM channel, + /// allowing you to control the PWM mode and enable/disable that channel + /// \param[in] channel The PWM channel. 0 or 1. + /// \param[in] markspace Set true if you want Mark-Space mode. 0 for Balanced mode. + /// \param[in] enabled Set true to enable this channel and produce PWM pulses. + extern void bcm2835_pwm_set_mode(uint8_t channel, uint8_t markspace, uint8_t enabled); + + /// Sets the maximum range of the PWM output. + /// The data value can vary between 0 and this range to control PWM output + /// \param[in] channel The PWM channel. 0 or 1. + /// \param[in] range The maximum value permitted for DATA. + extern void bcm2835_pwm_set_range(uint8_t channel, uint32_t range); + + /// Sets the PWM pulse ratio to emit to DATA/RANGE, + /// where RANGE is set by bcm2835_pwm_set_range(). + /// \param[in] channel The PWM channel. 0 or 1. + /// \param[in] data Controls the PWM output ratio as a fraction of the range. + /// Can vary from 0 to RANGE. + extern void bcm2835_pwm_set_data(uint8_t channel, uint32_t data); + + /// @} +#ifdef __cplusplus +} +#endif + +#endif // BCM2835_H + +/// @example blink.c +/// Blinks RPi GPIO pin 11 on and off + +/// @example input.c +/// Reads the state of an RPi input pin + +/// @example event.c +/// Shows how to use event detection on an input pin + +/// @example spi.c +/// Shows how to use SPI interface to transfer a byte to and from an SPI device + +/// @example spin.c +/// Shows how to use SPI interface to transfer a number of bytes to and from an SPI device + +/// @example pwm.c +/// Shows how to use PWM to control GPIO pins + +/// @example i2c.c +/// 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 +/// Broadcom bcm2835. Contributed by Shahrooz Shahparnia. diff --git a/src/dht-sensor.cpp b/src/dht-sensor.cpp index 34aed48..3c32e11 100755 --- a/src/dht-sensor.cpp +++ b/src/dht-sensor.cpp @@ -1,7 +1,13 @@ #include #include #include + +#ifdef BANANA_PRO +#include "bcm2835_bp/bcm2835.h" +#else #include "bcm2835/bcm2835.h" +#endif + #include #define BCM2708_PERI_BASE 0x20000000