From 54935bab036e10216f688ac5dfc21170376826c3 Mon Sep 17 00:00:00 2001 From: Rene Hopf Date: Thu, 28 Nov 2013 17:54:07 +0100 Subject: [PATCH 1/2] fixed magic line --- software/piffind.py | 3 ++- software/pifload.py | 5 +++-- software/pifweb.py | 3 ++- 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/software/piffind.py b/software/piffind.py index 2879eb5..1144e6d 100644 --- a/software/piffind.py +++ b/software/piffind.py @@ -1,3 +1,5 @@ +#!/usr/bin/env python + #---------------------------------------------------------------------- # Name: piffind.py # Purpose: sarch for the XO2 via the smbus Python library @@ -8,7 +10,6 @@ # Copyright: (c) Tim 2013 # Licence: Creative Commons Attribution-ShareAlike 3.0 Unported License. #---------------------------------------------------------------------- -#!/usr/bin/env python import sys, ctypes, pifglobs from ctypes import * diff --git a/software/pifload.py b/software/pifload.py index 2a4d378..7c3d27c 100644 --- a/software/pifload.py +++ b/software/pifload.py @@ -1,3 +1,5 @@ +#!/usr/bin/env python + #---------------------------------------------------------------------- # Name: pifload.py # Purpose: load a configuration into a pif board via the hidapi DLL/SO @@ -8,7 +10,6 @@ # Copyright: (c) Tim 2013 # Licence: Creative Commons Attribution-ShareAlike 3.0 Unported License. #---------------------------------------------------------------------- -#!/usr/bin/env python import sys, ctypes, pifglobs from ctypes import * @@ -257,7 +258,7 @@ def main(): print('Configuration file is ' + jedecFile) pifglobs.pif = ctypes.CDLL("libpif.so") - + print('hallo') strBuf = create_string_buffer(1000) rv = pifglobs.pif.pifVersion(strBuf, sizeof(strBuf)) print('Using pif library version: %s\n' % repr(strBuf.value)) diff --git a/software/pifweb.py b/software/pifweb.py index ad9a511..245bcb1 100644 --- a/software/pifweb.py +++ b/software/pifweb.py @@ -1,3 +1,5 @@ +#!/usr/bin/env python + ##--------------------------------------------------------- # Name: pifweb.py # Purpose: control a pif board via a web server @@ -12,7 +14,6 @@ # # windows command line start: python pifweb.py # -#!/usr/bin/env python import sys, web, ctypes, pifglobs from web import form From 302eeb9013879ae7be3fc1f97b3f92d934fae93b Mon Sep 17 00:00:00 2001 From: Rene Hopf Date: Thu, 28 Nov 2013 17:57:52 +0100 Subject: [PATCH 2/2] removed static bcm lib, gcc 4.7 Compatibility --- software/src/bcm2835.c | 1082 ----------------------------------- software/src/bcm2835.h | 1129 ------------------------------------- software/src/lowlevel.cpp | 2 +- software/src/makefile | 6 +- software/src/pif.cpp | 14 +- software/src/piffind.cpp | 2 +- 6 files changed, 12 insertions(+), 2223 deletions(-) delete mode 100644 software/src/bcm2835.c delete mode 100644 software/src/bcm2835.h diff --git a/software/src/bcm2835.c b/software/src/bcm2835.c deleted file mode 100644 index 021e4fe..0000000 --- a/software/src/bcm2835.c +++ /dev/null @@ -1,1082 +0,0 @@ -// 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.10 2013/03/18 05:57:36 mikem Exp mikem $ - -#include -#include -#include -#include -#include -#include -#include -#include - -#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 - -// Pointers to the hardware register bases -volatile uint32_t *bcm2835_gpio = MAP_FAILED; -volatile uint32_t *bcm2835_pwm = MAP_FAILED; -volatile uint32_t *bcm2835_clk = MAP_FAILED; -volatile uint32_t *bcm2835_pads = MAP_FAILED; -volatile uint32_t *bcm2835_spi0 = MAP_FAILED; -volatile uint32_t *bcm2835_bsc0 = MAP_FAILED; -volatile uint32_t *bcm2835_bsc1 = MAP_FAILED; -volatile uint32_t *bcm2835_st = MAP_FAILED; - - -// This variable allows us to test on hardware other than RPi. -// It prevents access to the kernel memory, and does not do any peripheral access -// 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; - -// -// Low level register access functions -// - -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; - uint32_t dummy = *paddr; - 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) -void bcm2835_gpio_fsel(uint8_t pin, uint8_t mode) -{ - // Function selects are 10 pins per 32 bit word, 3 bits per pin - volatile uint32_t* paddr = bcm2835_gpio + BCM2835_GPFSEL0/4 + (pin/10); - uint8_t shift = (pin % 10) * 3; - uint32_t mask = BCM2835_GPIO_FSEL_MASK << shift; - uint32_t value = mode << shift; - bcm2835_peri_set_bits(paddr, value, mask); -} - -// Set output pin -void bcm2835_gpio_set(uint8_t pin) -{ - volatile uint32_t* paddr = bcm2835_gpio + BCM2835_GPSET0/4 + pin/32; - uint8_t shift = pin % 32; - bcm2835_peri_write(paddr, 1 << shift); -} - -// Clear output pin -void bcm2835_gpio_clr(uint8_t pin) -{ - volatile uint32_t* paddr = bcm2835_gpio + BCM2835_GPCLR0/4 + pin/32; - uint8_t shift = pin % 32; - bcm2835_peri_write(paddr, 1 << shift); -} - -// Set all output pins in the mask -void bcm2835_gpio_set_multi(uint32_t mask) -{ - volatile uint32_t* paddr = bcm2835_gpio + BCM2835_GPSET0/4; - bcm2835_peri_write(paddr, mask); -} - -// Clear all output pins in the mask -void bcm2835_gpio_clr_multi(uint32_t mask) -{ - volatile uint32_t* paddr = bcm2835_gpio + BCM2835_GPCLR0/4; - bcm2835_peri_write(paddr, mask); -} - -// Read input pin -uint8_t bcm2835_gpio_lev(uint8_t pin) -{ - volatile uint32_t* paddr = bcm2835_gpio + BCM2835_GPLEV0/4 + pin/32; - uint8_t shift = pin % 32; - uint32_t value = bcm2835_peri_read(paddr); - return (value & (1 << shift)) ? HIGH : LOW; -} - -// See if an event detection bit is set -// Sigh cant support interrupts yet -uint8_t bcm2835_gpio_eds(uint8_t pin) -{ - volatile uint32_t* paddr = bcm2835_gpio + BCM2835_GPEDS0/4 + pin/32; - uint8_t shift = pin % 32; - uint32_t value = bcm2835_peri_read(paddr); - return (value & (1 << shift)) ? HIGH : LOW; -} - -// Write a 1 to clear the bit in EDS -void bcm2835_gpio_set_eds(uint8_t pin) -{ - volatile uint32_t* paddr = bcm2835_gpio + BCM2835_GPEDS0/4 + pin/32; - uint8_t shift = pin % 32; - uint32_t value = 1 << shift; - bcm2835_peri_write(paddr, value); -} - -// Rising edge detect enable -void bcm2835_gpio_ren(uint8_t pin) -{ - volatile uint32_t* paddr = bcm2835_gpio + BCM2835_GPREN0/4 + pin/32; - uint8_t shift = pin % 32; - uint32_t value = 1 << shift; - bcm2835_peri_set_bits(paddr, value, value); -} -void bcm2835_gpio_clr_ren(uint8_t pin) -{ - volatile uint32_t* paddr = bcm2835_gpio + BCM2835_GPREN0/4 + pin/32; - uint8_t shift = pin % 32; - uint32_t value = 1 << shift; - bcm2835_peri_set_bits(paddr, 0, value); -} - -// Falling edge detect enable -void bcm2835_gpio_fen(uint8_t pin) -{ - volatile uint32_t* paddr = bcm2835_gpio + BCM2835_GPFEN0/4 + pin/32; - uint8_t shift = pin % 32; - uint32_t value = 1 << shift; - bcm2835_peri_set_bits(paddr, value, value); -} -void bcm2835_gpio_clr_fen(uint8_t pin) -{ - volatile uint32_t* paddr = bcm2835_gpio + BCM2835_GPFEN0/4 + pin/32; - uint8_t shift = pin % 32; - uint32_t value = 1 << shift; - bcm2835_peri_set_bits(paddr, 0, value); -} - -// High detect enable -void bcm2835_gpio_hen(uint8_t pin) -{ - volatile uint32_t* paddr = bcm2835_gpio + BCM2835_GPHEN0/4 + pin/32; - uint8_t shift = pin % 32; - uint32_t value = 1 << shift; - bcm2835_peri_set_bits(paddr, value, value); -} -void bcm2835_gpio_clr_hen(uint8_t pin) -{ - volatile uint32_t* paddr = bcm2835_gpio + BCM2835_GPHEN0/4 + pin/32; - uint8_t shift = pin % 32; - uint32_t value = 1 << shift; - bcm2835_peri_set_bits(paddr, 0, value); -} - -// Low detect enable -void bcm2835_gpio_len(uint8_t pin) -{ - volatile uint32_t* paddr = bcm2835_gpio + BCM2835_GPLEN0/4 + pin/32; - uint8_t shift = pin % 32; - uint32_t value = 1 << shift; - bcm2835_peri_set_bits(paddr, value, value); -} -void bcm2835_gpio_clr_len(uint8_t pin) -{ - volatile uint32_t* paddr = bcm2835_gpio + BCM2835_GPLEN0/4 + pin/32; - uint8_t shift = pin % 32; - uint32_t value = 1 << shift; - bcm2835_peri_set_bits(paddr, 0, value); -} - -// Async rising edge detect enable -void bcm2835_gpio_aren(uint8_t pin) -{ - volatile uint32_t* paddr = bcm2835_gpio + BCM2835_GPAREN0/4 + pin/32; - uint8_t shift = pin % 32; - uint32_t value = 1 << shift; - bcm2835_peri_set_bits(paddr, value, value); -} -void bcm2835_gpio_clr_aren(uint8_t pin) -{ - volatile uint32_t* paddr = bcm2835_gpio + BCM2835_GPAREN0/4 + pin/32; - uint8_t shift = pin % 32; - uint32_t value = 1 << shift; - bcm2835_peri_set_bits(paddr, 0, value); -} - -// Async falling edge detect enable -void bcm2835_gpio_afen(uint8_t pin) -{ - volatile uint32_t* paddr = bcm2835_gpio + BCM2835_GPAFEN0/4 + pin/32; - uint8_t shift = pin % 32; - uint32_t value = 1 << shift; - bcm2835_peri_set_bits(paddr, value, value); -} -void bcm2835_gpio_clr_afen(uint8_t pin) -{ - volatile uint32_t* paddr = bcm2835_gpio + BCM2835_GPAFEN0/4 + pin/32; - uint8_t shift = pin % 32; - uint32_t value = 1 << shift; - bcm2835_peri_set_bits(paddr, 0, value); -} - -// Set pullup/down -void bcm2835_gpio_pud(uint8_t pud) -{ - volatile uint32_t* paddr = bcm2835_gpio + BCM2835_GPPUD/4; - bcm2835_peri_write(paddr, pud); -} - -// Pullup/down clock -// Clocks the value of pud into the GPIO pin -void bcm2835_gpio_pudclk(uint8_t pin, uint8_t on) -{ - volatile uint32_t* paddr = bcm2835_gpio + BCM2835_GPPUDCLK0/4 + pin/32; - uint8_t shift = pin % 32; - bcm2835_peri_write(paddr, (on ? 1 : 0) << shift); -} - -// Read GPIO pad behaviour for groups of GPIOs -uint32_t bcm2835_gpio_pad(uint8_t group) -{ - volatile uint32_t* paddr = bcm2835_pads + BCM2835_PADS_GPIO_0_27/4 + group*2; - return bcm2835_peri_read(paddr); -} - -// 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) -{ - volatile uint32_t* paddr = bcm2835_pads + BCM2835_PADS_GPIO_0_27/4 + group*2; - bcm2835_peri_write(paddr, control); -} - -// 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); -} - -// microseconds -void bcm2835_delayMicroseconds(uint64_t micros) -{ - struct timespec t1; - uint64_t start; - - // Calling nanosleep() takes at least 100-200 us, so use it for - // long waits and use a busy wait on the System Timer for the rest. - start = bcm2835_st_read(); - - if (micros > 450) - { - t1.tv_sec = 0; - t1.tv_nsec = 1000 * (long)(micros - 200); - nanosleep(&t1, NULL); - } - - bcm2835_st_delay(start, micros); -} - -// -// 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 -void bcm2835_gpio_set_pud(uint8_t pin, uint8_t pud) -{ - bcm2835_gpio_pud(pud); - delayMicroseconds(10); - bcm2835_gpio_pudclk(pin, 1); - delayMicroseconds(10); - bcm2835_gpio_pud(BCM2835_GPIO_PUD_OFF); - bcm2835_gpio_pudclk(pin, 0); -} - -void bcm2835_spi_begin(void) -{ - // Set the SPI0 pins to the Alt 0 function to enable SPI0 access on them - bcm2835_gpio_fsel(RPI_GPIO_P1_26, BCM2835_GPIO_FSEL_ALT0); // CE1 - bcm2835_gpio_fsel(RPI_GPIO_P1_24, BCM2835_GPIO_FSEL_ALT0); // CE0 - bcm2835_gpio_fsel(RPI_GPIO_P1_21, BCM2835_GPIO_FSEL_ALT0); // MISO - bcm2835_gpio_fsel(RPI_GPIO_P1_19, BCM2835_GPIO_FSEL_ALT0); // MOSI - bcm2835_gpio_fsel(RPI_GPIO_P1_23, BCM2835_GPIO_FSEL_ALT0); // CLK - - // Set the SPI CS register to the some sensible defaults - volatile uint32_t* paddr = bcm2835_spi0 + BCM2835_SPI0_CS/4; - bcm2835_peri_write(paddr, 0); // All 0s - - // Clear TX and RX fifos - bcm2835_peri_write_nb(paddr, BCM2835_SPI0_CS_CLEAR); -} - -void bcm2835_spi_end(void) -{ - // Set all the SPI0 pins back to input - bcm2835_gpio_fsel(RPI_GPIO_P1_26, BCM2835_GPIO_FSEL_INPT); // CE1 - bcm2835_gpio_fsel(RPI_GPIO_P1_24, BCM2835_GPIO_FSEL_INPT); // CE0 - bcm2835_gpio_fsel(RPI_GPIO_P1_21, BCM2835_GPIO_FSEL_INPT); // MISO - bcm2835_gpio_fsel(RPI_GPIO_P1_19, BCM2835_GPIO_FSEL_INPT); // MOSI - bcm2835_gpio_fsel(RPI_GPIO_P1_23, BCM2835_GPIO_FSEL_INPT); // CLK -} - -void bcm2835_spi_setBitOrder(uint8_t order) -{ - // BCM2835_SPI_BIT_ORDER_MSBFIRST is the only one suported by SPI0 -} - -// 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(uint16_t divider) -{ - volatile uint32_t* paddr = bcm2835_spi0 + BCM2835_SPI0_CLK/4; - bcm2835_peri_write(paddr, divider); -} - -void bcm2835_spi_setDataMode(uint8_t mode) -{ - volatile uint32_t* paddr = bcm2835_spi0 + BCM2835_SPI0_CS/4; - // Mask in the CPO and CPHA bits of CS - bcm2835_peri_set_bits(paddr, mode << 2, BCM2835_SPI0_CS_CPOL | BCM2835_SPI0_CS_CPHA); -} - -// Writes (and reads) a single byte to SPI -uint8_t bcm2835_spi_transfer(uint8_t value) -{ - volatile uint32_t* paddr = bcm2835_spi0 + BCM2835_SPI0_CS/4; - volatile uint32_t* fifo = bcm2835_spi0 + BCM2835_SPI0_FIFO/4; - - // This is Polled transfer as per section 10.6.1 - // BUG ALERT: what happens if we get interupted in this section, and someone else - // accesses a different peripheral? - // Clear TX and RX fifos - bcm2835_peri_set_bits(paddr, BCM2835_SPI0_CS_CLEAR, BCM2835_SPI0_CS_CLEAR); - - // Set TA = 1 - bcm2835_peri_set_bits(paddr, BCM2835_SPI0_CS_TA, BCM2835_SPI0_CS_TA); - - // Maybe wait for TXD - while (!(bcm2835_peri_read(paddr) & BCM2835_SPI0_CS_TXD)) - delayMicroseconds(10); - - // Write to FIFO, no barrier - bcm2835_peri_write_nb(fifo, value); - - // Wait for DONE to be set - while (!(bcm2835_peri_read_nb(paddr) & BCM2835_SPI0_CS_DONE)) - delayMicroseconds(10); - - // Read any byte that was sent back by the slave while we sere sending to it - uint32_t ret = bcm2835_peri_read_nb(fifo); - - // Set TA = 0, and also set the barrier - bcm2835_peri_set_bits(paddr, 0, BCM2835_SPI0_CS_TA); - - return ret; -} - -// Writes (and reads) an number of bytes to SPI -void bcm2835_spi_transfernb(char* tbuf, char* rbuf, uint32_t len) -{ - volatile uint32_t* paddr = bcm2835_spi0 + BCM2835_SPI0_CS/4; - volatile uint32_t* fifo = bcm2835_spi0 + BCM2835_SPI0_FIFO/4; - - // This is Polled transfer as per section 10.6.1 - // BUG ALERT: what happens if we get interupted in this section, and someone else - // accesses a different peripheral? - - // Clear TX and RX fifos - bcm2835_peri_set_bits(paddr, BCM2835_SPI0_CS_CLEAR, BCM2835_SPI0_CS_CLEAR); - - // Set TA = 1 - bcm2835_peri_set_bits(paddr, BCM2835_SPI0_CS_TA, BCM2835_SPI0_CS_TA); - - uint32_t i; - for (i = 0; i < len; i++) - { - // Maybe wait for TXD - while (!(bcm2835_peri_read(paddr) & BCM2835_SPI0_CS_TXD)) - delayMicroseconds(10); - - // Write to FIFO, no barrier - bcm2835_peri_write_nb(fifo, tbuf[i]); - - // Wait for RXD - while (!(bcm2835_peri_read(paddr) & BCM2835_SPI0_CS_RXD)) - delayMicroseconds(10); - - // then read the data byte - rbuf[i] = bcm2835_peri_read_nb(fifo); - } - // Wait for DONE to be set - while (!(bcm2835_peri_read_nb(paddr) & BCM2835_SPI0_CS_DONE)) - delayMicroseconds(10); - - // Set TA = 0, and also set the barrier - bcm2835_peri_set_bits(paddr, 0, BCM2835_SPI0_CS_TA); -} - -// Writes an number of bytes to SPI -void bcm2835_spi_writenb(char* tbuf, uint32_t len) -{ - volatile uint32_t* paddr = bcm2835_spi0 + BCM2835_SPI0_CS/4; - volatile uint32_t* fifo = bcm2835_spi0 + BCM2835_SPI0_FIFO/4; - - // This is Polled transfer as per section 10.6.1 - // BUG ALERT: what happens if we get interupted in this section, and someone else - // accesses a different peripheral? - - // Clear TX and RX fifos - bcm2835_peri_set_bits(paddr, BCM2835_SPI0_CS_CLEAR, BCM2835_SPI0_CS_CLEAR); - - // Set TA = 1 - bcm2835_peri_set_bits(paddr, BCM2835_SPI0_CS_TA, BCM2835_SPI0_CS_TA); - - uint32_t i; - for (i = 0; i < len; i++) - { - // Maybe wait for TXD - while (!(bcm2835_peri_read(paddr) & BCM2835_SPI0_CS_TXD)) - ; - - // Write to FIFO, no barrier - bcm2835_peri_write_nb(fifo, tbuf[i]); - } - - // Wait for DONE to be set - while (!(bcm2835_peri_read_nb(paddr) & BCM2835_SPI0_CS_DONE)) - ; - - // Set TA = 0, and also set the barrier - bcm2835_peri_set_bits(paddr, 0, BCM2835_SPI0_CS_TA); -} - -// 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); -} - -void bcm2835_spi_chipSelect(uint8_t cs) -{ - volatile uint32_t* paddr = bcm2835_spi0 + BCM2835_SPI0_CS/4; - // Mask in the CS bits of CS - bcm2835_peri_set_bits(paddr, cs, BCM2835_SPI0_CS_CS); -} - -void bcm2835_spi_setChipSelectPolarity(uint8_t cs, uint8_t active) -{ - volatile uint32_t* paddr = bcm2835_spi0 + BCM2835_SPI0_CS/4; - uint8_t shift = 21 + cs; - // Mask in the appropriate CSPOLn bit - bcm2835_peri_set_bits(paddr, active << shift, 1 << shift); -} - -void bcm2835_i2c_begin(void) -{ - volatile uint32_t* paddr = bcm2835_bsc1 + BCM2835_BSC_DIV/4; - - // Set the I2C/BSC1 pins to the Alt 0 function to enable I2C access on them - bcm2835_gpio_fsel(RPI_V2_GPIO_P1_03, BCM2835_GPIO_FSEL_ALT0); // SDA - bcm2835_gpio_fsel(RPI_V2_GPIO_P1_05, BCM2835_GPIO_FSEL_ALT0); // SCL - - // Read the clock divider register - uint16_t cdiv = bcm2835_peri_read(paddr); - // Calculate time for transmitting one byte - // 1000000 = micros seconds in a second - // 9 = Clocks per byte : 8 bits + ACK - i2c_byte_wait_us = ((float)cdiv / BCM2835_CORE_CLK_HZ) * 1000000 * 9; -} - -void bcm2835_i2c_end(void) -{ - // Set all the I2C/BSC1 pins back to input - bcm2835_gpio_fsel(RPI_V2_GPIO_P1_03, BCM2835_GPIO_FSEL_INPT); // SDA - bcm2835_gpio_fsel(RPI_V2_GPIO_P1_05, BCM2835_GPIO_FSEL_INPT); // SCL -} - -void bcm2835_i2c_setSlaveAddress(uint8_t addr) -{ - // Set I2C Device Address - volatile uint32_t* paddr = bcm2835_bsc1 + BCM2835_BSC_A/4; - bcm2835_peri_write(paddr, addr); -} - -// 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) -{ - volatile uint32_t* paddr = bcm2835_bsc1 + BCM2835_BSC_DIV/4; - bcm2835_peri_write(paddr, divider); - // Calculate time for transmitting one byte - // 1000000 = micros seconds in a second - // 9 = Clocks per byte : 8 bits + ACK - i2c_byte_wait_us = ((float)divider / BCM2835_CORE_CLK_HZ) * 1000000 * 9; -} - -// set I2C clock divider by means of a baudrate number -void bcm2835_i2c_set_baudrate(uint32_t baudrate) -{ - uint32_t divider; - // use 0xFFFE mask to limit a max value and round down any odd number - divider = (BCM2835_CORE_CLK_HZ / baudrate) & 0xFFFE; - bcm2835_i2c_setClockDivider( (uint16_t)divider ); -} - -// Writes an number of bytes to I2C -uint8_t bcm2835_i2c_write(const char * buf, uint32_t len) -{ - volatile uint32_t* dlen = bcm2835_bsc1 + BCM2835_BSC_DLEN/4; - volatile uint32_t* fifo = bcm2835_bsc1 + BCM2835_BSC_FIFO/4; - volatile uint32_t* status = bcm2835_bsc1 + BCM2835_BSC_S/4; - volatile uint32_t* control = bcm2835_bsc1 + BCM2835_BSC_C/4; - - uint32_t remaining = len; - uint32_t i = 0; - uint8_t reason = BCM2835_I2C_REASON_OK; - - // Clear FIFO - bcm2835_peri_set_bits(control, BCM2835_BSC_C_CLEAR_1 , BCM2835_BSC_C_CLEAR_1 ); - // Clear Status - bcm2835_peri_write_nb(status, BCM2835_BSC_S_CLKT | BCM2835_BSC_S_ERR | BCM2835_BSC_S_DONE); - // Set Data Length - bcm2835_peri_write_nb(dlen, len); - // pre populate FIFO with max buffer - while( remaining && ( i < BCM2835_BSC_FIFO_SIZE ) ) - { - bcm2835_peri_write_nb(fifo, buf[i]); - i++; - remaining--; - } - - // Enable device and start transfer - bcm2835_peri_write_nb(control, BCM2835_BSC_C_I2CEN | BCM2835_BSC_C_ST); - - // Transfer is over when BCM2835_BSC_S_DONE - while(!(bcm2835_peri_read_nb(status) & BCM2835_BSC_S_DONE )) - { - while ( remaining && (bcm2835_peri_read_nb(status) & BCM2835_BSC_S_TXD )) - { - // Write to FIFO, no barrier - bcm2835_peri_write_nb(fifo, buf[i]); - i++; - remaining--; - } - } - - // Received a NACK - if (bcm2835_peri_read(status) & BCM2835_BSC_S_ERR) - { - reason = BCM2835_I2C_REASON_ERROR_NACK; - } - - // Received Clock Stretch Timeout - else if (bcm2835_peri_read(status) & BCM2835_BSC_S_CLKT) - { - reason = BCM2835_I2C_REASON_ERROR_CLKT; - } - - // Not all data is sent - else if (remaining) - { - reason = BCM2835_I2C_REASON_ERROR_DATA; - } - - bcm2835_peri_set_bits(control, BCM2835_BSC_S_DONE , BCM2835_BSC_S_DONE); - - return reason; -} - -// Read an number of bytes from I2C -uint8_t bcm2835_i2c_read(char* buf, uint32_t len) -{ - volatile uint32_t* dlen = bcm2835_bsc1 + BCM2835_BSC_DLEN/4; - volatile uint32_t* fifo = bcm2835_bsc1 + BCM2835_BSC_FIFO/4; - volatile uint32_t* status = bcm2835_bsc1 + BCM2835_BSC_S/4; - volatile uint32_t* control = bcm2835_bsc1 + BCM2835_BSC_C/4; - - uint32_t remaining = len; - uint32_t i = 0; - uint8_t reason = BCM2835_I2C_REASON_OK; - - // Clear FIFO - bcm2835_peri_set_bits(control, BCM2835_BSC_C_CLEAR_1 , BCM2835_BSC_C_CLEAR_1 ); - // Clear Status - bcm2835_peri_write_nb(status, BCM2835_BSC_S_CLKT | BCM2835_BSC_S_ERR | BCM2835_BSC_S_DONE); - // Set Data Length - bcm2835_peri_write_nb(dlen, len); - // Start read - bcm2835_peri_write_nb(control, BCM2835_BSC_C_I2CEN | BCM2835_BSC_C_ST | BCM2835_BSC_C_READ); - - // wait for transfer to complete - while (!(bcm2835_peri_read_nb(status) & BCM2835_BSC_S_DONE)) - { - // we must empty the FIFO as it is populated and not use any delay - while (bcm2835_peri_read_nb(status) & BCM2835_BSC_S_RXD) - { - // Read from FIFO, no barrier - buf[i] = bcm2835_peri_read_nb(fifo); - i++; - remaining--; - } - } - - // transfer has finished - grab any remaining stuff in FIFO - while (remaining && (bcm2835_peri_read_nb(status) & BCM2835_BSC_S_RXD)) - { - // Read from FIFO, no barrier - buf[i] = bcm2835_peri_read_nb(fifo); - i++; - remaining--; - } - - // Received a NACK - if (bcm2835_peri_read(status) & BCM2835_BSC_S_ERR) - { - reason = BCM2835_I2C_REASON_ERROR_NACK; - } - - // Received Clock Stretch Timeout - else if (bcm2835_peri_read(status) & BCM2835_BSC_S_CLKT) - { - reason = BCM2835_I2C_REASON_ERROR_CLKT; - } - - // Not all data is received - else if (remaining) - { - reason = BCM2835_I2C_REASON_ERROR_DATA; - } - - bcm2835_peri_set_bits(control, BCM2835_BSC_S_DONE , BCM2835_BSC_S_DONE); - - return reason; -} - -// 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) -{ - volatile uint32_t* dlen = bcm2835_bsc1 + BCM2835_BSC_DLEN/4; - volatile uint32_t* fifo = bcm2835_bsc1 + BCM2835_BSC_FIFO/4; - volatile uint32_t* status = bcm2835_bsc1 + BCM2835_BSC_S/4; - volatile uint32_t* control = bcm2835_bsc1 + BCM2835_BSC_C/4; - - uint32_t remaining = len; - uint32_t i = 0; - uint8_t reason = BCM2835_I2C_REASON_OK; - - // Clear FIFO - bcm2835_peri_set_bits(control, BCM2835_BSC_C_CLEAR_1 , BCM2835_BSC_C_CLEAR_1 ); - // Clear Status - bcm2835_peri_write_nb(status, BCM2835_BSC_S_CLKT | BCM2835_BSC_S_ERR | BCM2835_BSC_S_DONE); - // Set Data Length - bcm2835_peri_write_nb(dlen, 1); - // Enable device and start transfer - bcm2835_peri_write_nb(control, BCM2835_BSC_C_I2CEN); - bcm2835_peri_write_nb(fifo, regaddr[0]); - bcm2835_peri_write_nb(control, BCM2835_BSC_C_I2CEN | BCM2835_BSC_C_ST); - - // poll for transfer has started - while ( !( bcm2835_peri_read_nb(status) & BCM2835_BSC_S_TA ) ) - { - // Linux may cause us to miss entire transfer stage - if(bcm2835_peri_read(status) & BCM2835_BSC_S_DONE) - break; - } - - // Send a repeated start with read bit set in address - bcm2835_peri_write_nb(dlen, len); - bcm2835_peri_write_nb(control, BCM2835_BSC_C_I2CEN | BCM2835_BSC_C_ST | BCM2835_BSC_C_READ ); - - // Wait for write to complete and first byte back. - bcm2835_delayMicroseconds(i2c_byte_wait_us * 3); - - // wait for transfer to complete - while (!(bcm2835_peri_read_nb(status) & BCM2835_BSC_S_DONE)) - { - // we must empty the FIFO as it is populated and not use any delay - while (remaining && bcm2835_peri_read_nb(status) & BCM2835_BSC_S_RXD) - { - // Read from FIFO, no barrier - buf[i] = bcm2835_peri_read_nb(fifo); - i++; - remaining--; - } - } - - // transfer has finished - grab any remaining stuff in FIFO - while (remaining && (bcm2835_peri_read_nb(status) & BCM2835_BSC_S_RXD)) - { - // Read from FIFO, no barrier - buf[i] = bcm2835_peri_read_nb(fifo); - i++; - remaining--; - } - - // Received a NACK - if (bcm2835_peri_read(status) & BCM2835_BSC_S_ERR) - { - reason = BCM2835_I2C_REASON_ERROR_NACK; - } - - // Received Clock Stretch Timeout - else if (bcm2835_peri_read(status) & BCM2835_BSC_S_CLKT) - { - reason = BCM2835_I2C_REASON_ERROR_CLKT; - } - - // Not all data is sent - else if (remaining) - { - reason = BCM2835_I2C_REASON_ERROR_DATA; - } - - bcm2835_peri_set_bits(control, BCM2835_BSC_S_DONE , BCM2835_BSC_S_DONE); - - return reason; -} - -// Read the System Timer Counter (64-bits) -uint64_t bcm2835_st_read(void) -{ - volatile uint32_t* paddr; - uint64_t st; - paddr = bcm2835_st + BCM2835_ST_CHI/4; - st = bcm2835_peri_read(paddr); - st <<= 32; - paddr = bcm2835_st + BCM2835_ST_CLO/4; - st += bcm2835_peri_read(paddr); - return st; -} - -// Delays for the specified number of microseconds with offset -void bcm2835_st_delay(uint64_t offset_micros, uint64_t micros) -{ - uint64_t compare = offset_micros + micros; - - while(bcm2835_st_read() < compare) - ; -} - -// 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; -} - -// Initialise this library. -int bcm2835_init(void) -{ - if (debug) - { - bcm2835_pads = (uint32_t*)BCM2835_GPIO_PADS; - bcm2835_clk = (uint32_t*)BCM2835_CLOCK_BASE; - bcm2835_gpio = (uint32_t*)BCM2835_GPIO_BASE; - bcm2835_pwm = (uint32_t*)BCM2835_GPIO_PWM; - bcm2835_spi0 = (uint32_t*)BCM2835_SPI0_BASE; - bcm2835_bsc0 = (uint32_t*)BCM2835_BSC0_BASE; - bcm2835_bsc1 = (uint32_t*)BCM2835_BSC1_BASE; - bcm2835_st = (uint32_t*)BCM2835_ST_BASE; - return 1; // Success - } - int memfd = -1; - int ok = 0; - // 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; - } - - // GPIO: - bcm2835_gpio = mapmem("gpio", BCM2835_BLOCK_SIZE, memfd, BCM2835_GPIO_BASE); - if (bcm2835_gpio == MAP_FAILED) goto exit; - - // PWM - bcm2835_pwm = mapmem("pwm", BCM2835_BLOCK_SIZE, memfd, BCM2835_GPIO_PWM); - if (bcm2835_pwm == MAP_FAILED) goto exit; - - // Clock control (needed for PWM) - bcm2835_clk = mapmem("clk", BCM2835_BLOCK_SIZE, memfd, BCM2835_CLOCK_BASE); - if (bcm2835_clk == MAP_FAILED) goto exit; - - bcm2835_pads = mapmem("pads", BCM2835_BLOCK_SIZE, memfd, BCM2835_GPIO_PADS); - if (bcm2835_pads == MAP_FAILED) goto exit; - - bcm2835_spi0 = mapmem("spi0", BCM2835_BLOCK_SIZE, memfd, BCM2835_SPI0_BASE); - if (bcm2835_spi0 == MAP_FAILED) goto exit; - - // I2C - bcm2835_bsc0 = mapmem("bsc0", BCM2835_BLOCK_SIZE, memfd, BCM2835_BSC0_BASE); - if (bcm2835_bsc0 == MAP_FAILED) goto exit; - - bcm2835_bsc1 = mapmem("bsc1", BCM2835_BLOCK_SIZE, memfd, BCM2835_BSC1_BASE); - if (bcm2835_bsc1 == MAP_FAILED) goto exit; - - // ST - bcm2835_st = mapmem("st", BCM2835_BLOCK_SIZE, memfd, BCM2835_ST_BASE); - if (bcm2835_st == MAP_FAILED) goto exit; - - ok = 1; - -exit: - if (memfd >= 0) - close(memfd); - - if (!ok) - bcm2835_close(); - - return ok; -} - -// Close this library and deallocate everything -int bcm2835_close(void) -{ - if (debug) return 1; // Success - unmapmem((void**) &bcm2835_gpio, BCM2835_BLOCK_SIZE); - unmapmem((void**) &bcm2835_pwm, BCM2835_BLOCK_SIZE); - unmapmem((void**) &bcm2835_clk, BCM2835_BLOCK_SIZE); - unmapmem((void**) &bcm2835_spi0, BCM2835_BLOCK_SIZE); - unmapmem((void**) &bcm2835_bsc0, BCM2835_BLOCK_SIZE); - unmapmem((void**) &bcm2835_bsc1, BCM2835_BLOCK_SIZE); - unmapmem((void**) &bcm2835_st, BCM2835_BLOCK_SIZE); - unmapmem((void**) &bcm2835_pads, BCM2835_BLOCK_SIZE); - return 1; // Success -} - -#ifdef BCM2835_TEST -// this is a simple test program that prints out what it will do rather than -// 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/software/src/bcm2835.h b/software/src/bcm2835.h deleted file mode 100644 index e533093..0000000 --- a/software/src/bcm2835.h +++ /dev/null @@ -1,1129 +0,0 @@ -// 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.8 2013/02/15 22:06:09 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.26.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. -/// -/// Tested on debian6-19-04-2012, 2012-07-15-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 and Occidentalisv01. -/// Reason for this is not yet determined, but 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_cler_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 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 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. -/// \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 ST (System Timer) registers. -/// Available after bcm2835_init has been called -extern volatile uint32_t *bcm2835_st; - -/// Base of the GPIO registers. -/// Available after bcm2835_init has been called -extern volatile uint32_t *bcm2835_gpio; - -/// Base of the PWM registers. -/// Available after bcm2835_init has been called -extern volatile uint32_t *bcm2835_pwm; - -/// Base of the CLK registers. -/// Available after bcm2835_init has been called -extern volatile uint32_t *bcm2835_clk; - -/// Base of the PADS registers. -/// Available after bcm2835_init has been called -extern volatile uint32_t *bcm2835_pads; - -/// Base of the SPI0 registers. -/// Available after bcm2835_init has been called -extern volatile uint32_t *bcm2835_spi0; - -/// Base of the BSC0 registers. -/// Available after bcm2835_init has been called -extern volatile uint32_t *bcm2835_bsc0; - -/// Base of the BSC1 registers. -/// Available after bcm2835_init has been called -extern volatile uint32_t *bcm2835_bsc1; - -/// 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 = 0b01, ///< Enable Pull Down control - BCM2835_GPIO_PUD_UP = 0b10 ///< Enable Pull Up control -} 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 - -/// \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_*. -/// 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()), pins 19, 21, 23, 24, 26 are dedicated to SPI -/// and cant be controlled independently -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 - 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 - 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 - -} 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 = 0, ///< 65536 = 262.144us = 3.814697260kHz - BCM2835_SPI_CLOCK_DIVIDER_32768 = 32768, ///< 32768 = 131.072us = 7.629394531kHz - BCM2835_SPI_CLOCK_DIVIDER_16384 = 16384, ///< 16384 = 65.536us = 15.25878906kHz - BCM2835_SPI_CLOCK_DIVIDER_8192 = 8192, ///< 8192 = 32.768us = 30/51757813kHz - BCM2835_SPI_CLOCK_DIVIDER_4096 = 4096, ///< 4096 = 16.384us = 61.03515625kHz - BCM2835_SPI_CLOCK_DIVIDER_2048 = 2048, ///< 2048 = 8.192us = 122.0703125kHz - BCM2835_SPI_CLOCK_DIVIDER_1024 = 1024, ///< 1024 = 4.096us = 244.140625kHz - BCM2835_SPI_CLOCK_DIVIDER_512 = 512, ///< 512 = 2.048us = 488.28125kHz - BCM2835_SPI_CLOCK_DIVIDER_256 = 256, ///< 256 = 1.024us = 976.5625MHz - BCM2835_SPI_CLOCK_DIVIDER_128 = 128, ///< 128 = 512ns = = 1.953125MHz - BCM2835_SPI_CLOCK_DIVIDER_64 = 64, ///< 64 = 256ns = 3.90625MHz - BCM2835_SPI_CLOCK_DIVIDER_32 = 32, ///< 32 = 128ns = 7.8125MHz - BCM2835_SPI_CLOCK_DIVIDER_16 = 16, ///< 16 = 64ns = 15.625MHz - BCM2835_SPI_CLOCK_DIVIDER_8 = 8, ///< 8 = 32ns = 31.25MHz - BCM2835_SPI_CLOCK_DIVIDER_4 = 4, ///< 4 = 16ns = 62.5MHz - BCM2835_SPI_CLOCK_DIVIDER_2 = 2, ///< 2 = 8ns = 125MHz, fastest you can get - BCM2835_SPI_CLOCK_DIVIDER_1 = 1, ///< 0 = 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 -#define BCM2835_PWM_CONTROL 0 -#define BCM2835_PWM_STATUS 1 -#define BCM2835_PWM0_RANGE 4 -#define BCM2835_PWM0_DATA 5 -#define BCM2835_PWM1_RANGE 8 -#define BCM2835_PWM1_DATA 9 - -#define BCM2835_PWMCLK_CNTL 40 -#define BCM2835_PWMCLK_DIV 41 - -#define BCM2835_PWM1_MS_MODE 0x8000 /// Run in MS 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 MS mode -#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 - -// 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 - /// - /// @{ - - /// 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 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 th 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 - 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(uint16_t divider); - - /// Sets the SPI data mode - /// Sets the clock polariy and phase - /// \param[in] mode The desired data mode, one of BCM2835_SPI_MODE*, - /// 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); - - /// @} - - /// \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 - 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); - - /// @} - -#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 diff --git a/software/src/lowlevel.cpp b/software/src/lowlevel.cpp index e15f6cc..b82bda9 100644 --- a/software/src/lowlevel.cpp +++ b/software/src/lowlevel.cpp @@ -13,7 +13,7 @@ #endif #include "lowlevel.h" -#include "bcm2835.h" +#include #define XO2_I2C_CLOCK_SPEED (400 * 1000) diff --git a/software/src/makefile b/software/src/makefile index 0d3e350..e544223 100644 --- a/software/src/makefile +++ b/software/src/makefile @@ -4,11 +4,11 @@ CXXFLAGS = -ansi $(UNIFLAGS) -fvisibility-inlines-hidden CC = gcc CCFLAGS = $(UNIFLAGS) -DEPS = pif.h pifwrap.h lowlevel.h bcm2835.h llbufs.h -OBJS = pif.o pifwrap.o lowlevel.o bcm2835.o +DEPS = pif.h pifwrap.h lowlevel.h llbufs.h +OBJS = pif.o pifwrap.o lowlevel.o TARGET = libpif.so LIBS = -lstdc++ -LDFLAGS = -shared -Wl,-soname,$(TARGET) -fvisibility=hidden +LDFLAGS = -shared -Wl,-soname,$(TARGET) -fvisibility=hidden -lbcm2835 diff --git a/software/src/pif.cpp b/software/src/pif.cpp index 136098f..00e08a3 100644 --- a/software/src/pif.cpp +++ b/software/src/pif.cpp @@ -130,7 +130,7 @@ Non-Volatile Register (NVR) Commands #include #include "lowlevel.h" -#include "bcm2835.h" +#include #include "pif.h" #define ISC_ERASE 0x0e @@ -246,7 +246,7 @@ bool Tpif::_setUfmPageAddr(int pageNumber) { bool Tpif::progDone() { bool ok = _doSimple(ISC_PROG_DONE); // sleep for 200us - nanosleep((struct timespec[]){{0, (200 * MICROSEC)}}, NULL); + nanosleep((const struct timespec[]){{0, (200 * MICROSEC)}}, NULL); return ok; } @@ -255,7 +255,7 @@ bool Tpif::refresh() { oBuf.byte(ISC_REFRESH).byte(0).byte(0); bool ok = _cfgWrite(oBuf); // sleep for 5ms - nanosleep((struct timespec[]){{0, (5 * MILLISEC)}}, NULL); + nanosleep((const struct timespec[]){{0, (5 * MILLISEC)}}, NULL); return ok; } @@ -276,13 +276,13 @@ bool Tpif::eraseUfm() { //--------------------------------------------------------------------- bool Tpif::enableCfgInterfaceOffline() { bool ok = _doSimple(ISC_ENABLE_PROG, 0x08); - nanosleep((struct timespec[]){{0, (5 * MICROSEC)}}, NULL); + nanosleep((const struct timespec[]){{0, (5 * MICROSEC)}}, NULL); return ok; } bool Tpif::enableCfgInterfaceTransparent() { bool ok = _doSimple(ISC_ENABLE_X, 0x08); - nanosleep((struct timespec[]){{0, (5 * MICROSEC)}}, NULL); + nanosleep((const struct timespec[]){{0, (5 * MICROSEC)}}, NULL); return ok; } @@ -309,7 +309,7 @@ bool Tpif::_progPage(int Acmd, const uint8_t *p) { bool ok = _cfgWrite(oBuf); // sleep for 200us - nanosleep((struct timespec[]){{0, (200 * MICROSEC)}}, NULL); + nanosleep((const struct timespec[]){{0, (200 * MICROSEC)}}, NULL); return ok; } @@ -387,7 +387,7 @@ bool Tpif::setUsercode(uint8_t* p) { bool ok = _cfgWrite(oBuf); // sleep for 200us - nanosleep((struct timespec[]){{0, (200 * MICROSEC)}}, NULL); + nanosleep((const struct timespec[]){{0, (200 * MICROSEC)}}, NULL); return ok; } diff --git a/software/src/piffind.cpp b/software/src/piffind.cpp index e3103fc..b15bba5 100644 --- a/software/src/piffind.cpp +++ b/software/src/piffind.cpp @@ -20,7 +20,7 @@ int main() { if (h) { uint32_t v = 99; - bool x = getDeviceIdCode(h, &v); + bool x = pifGetDeviceIdCode(h, &v); printf("\nresult=%d, ID code=%x", x, v); pifClose(h);