mbed API for Raspberry Pi boards.
mbedPi
This is an attempt to implement a limited number of mbed APIs for Raspberry Pi single-board computers. The project was inspired by and based on the arduPi library developed for the Arduino by Cooking Hacks .
Specifications
- Chip: Broadcom BCM2836 SoC
- Core architecture: Quad-core ARM Cortex-A7
- CPU frequency: 900 MHz
- GPU: Dual Core VideoCore IV® Multimedia Co-Processor
- Memory: 1GB LPDDR2
- Operating System: Boots from Micro SD card, running a version of the Linux operating system
- Power: Micro USB socket 5V, 2A
Connectors
- Ethernet: 10/100 BaseT Ethernet socket
- Video Output: HDMI (rev 1.3 & 1.4)
- Audio Output: 3.5mm jack, HDMI
- USB: 4 x USB 2.0 Connector
- GPIO Connector: 40-pin 2.54 mm (100 mil) expansion header: 2x20 strip providing 27 GPIO pins as well as +3.3 V, +5 V and GND supply lines
- Camera Connector: 15-pin MIPI Camera Serial Interface (CSI-2)
- JTAG: Not populated
- Display Connector: Display Serial Interface (DSI) 15 way flat flex cable connector with two data lanes and a clock lane
- Memory Card Slot: Micro SDIO
GPIO connector pinout
Information
Only the labels printed in blue/white or green/white (i.e. p3, gpio2 ...) must be used in your code. The other labels are given as information (alternate-functions, power pins, ...).
Building programs for the Raspberry Pi with mbedPi
I use Qt Creator for development, however you can use any other IDE available on the Raspberry Pi (e.g. Geany) if you like. For a quick try:
- Install Qt and the Qt Creator onto your Raspberry Pi. Then create a new "Blinky" Plain non-Qt C++ Project as follows:
- Change the main code as below:
main.cpp
#include "mbedPi.h" int main() { DigitalOut myled(p7); while(1) { myled = 1; // LED is ON wait(0.2); // 200 ms myled = 0; // LED is OFF wait(1.0); // 1 sec printf("Blink\r\n"); } }
- Copy the mbedPi.zip file into your project's folder and unzip.
- Add the mbedPi.h and mbedPi.cpp files to your project by right clicking on the "Blinky" project and then clicking on the "Add Existing Files..." option in the local menu:
- Double click on Blinky.pro to open it for editing and add new libraries by inserting a new line as follows:
- Compile the project.
- Connect an LED through a 1k resistor to pin 7 and the ground on the Raspberry Pi GPIO connector.
- Run the binary as sudo (sudo ./Blinky) and you should see the LED blinking.
- Press Ctrl+c to stop running the application.
Diff: mbedPi.h
- Revision:
- 0:91392e1f8551
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mbedPi.h Tue Oct 18 18:18:37 2016 +0000 @@ -0,0 +1,601 @@ +/* + * Copyright (C) 2016 Zoltan Hudak + * hudakz@outlook.com + * + * Portions Copyright (C) Libelium Comunicaciones Distribuidas S.L. + * http://www.libelium.com + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + * Version 1.0 + */ +// +/*$off*/ +#ifndef MBEDPI_H +#define MBEDPI_H + +#include <errno.h> +#include <fcntl.h> +#include <netinet/in.h> +#include <signal.h> +#include <stdlib.h> +#include <stdio.h> +#include <sys/ipc.h> +#include <sys/sem.h> +#include <sys/socket.h> +#include <sys/time.h> +#include <sys/types.h> +#include <sys/wait.h> +#include <sys/mman.h> +#include <string.h> +#include <time.h> +#include <termios.h> +#include <ctype.h> +#include <sys/ioctl.h> +#include <limits.h> +#include <algorithm> +#include <limits.h> +#include <pthread.h> +#include <poll.h> + +#define IOBASE 0x20000000 +#define GPIO_BASE (IOBASE + 0x200000) +#define BCM2835_SPI0_BASE (IOBASE + 0x204000) +#define BCM2835_BSC1_BASE (IOBASE + 0x804000) + +// 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 +#define BCM2835_CORE_CLK_HZ 250000000 ///< 250 MHz + + /// \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; + +typedef enum +{ + RPI_V2_GPIO_P1_03 = 2, ///< Version 2, Pin P1-03 + RPI_V2_GPIO_P1_05 = 3, ///< Version 2, Pin P1-05 +} RPiGPIOPin; + +#define BSC0_C *(bsc0.addr + 0x00) +#define BSC0_S *(bsc0.addr + 0x01) +#define BSC0_DLEN *(bsc0.addr + 0x02) +#define BSC0_A *(bsc0.addr + 0x03) +#define BSC0_FIFO *(bsc0.addr + 0x04) + +#define BSC_C_I2CEN (1<< 15) +#define BSC_C_INTR (1<< 10) +#define BSC_C_INTT (1<< 9) +#define BSC_C_INTD (1<< 8) +#define BSC_C_ST (1<< 7) +#define BSC_C_CLEAR (1<< 4) +#define BSC_C_READ 1 + +#define START_READ BSC_C_I2CEN|BSC_C_ST|BSC_C_CLEAR|BSC_C_READ +#define START_WRITE BSC_C_I2CEN|BSC_C_ST + +#define BSC_S_CLKT (1<< 9) +#define BSC_S_ERR (1<< 8) +#define BSC_S_RXF (1<< 7) +#define BSC_S_TXE (1<< 6) +#define BSC_S_RXD (1<< 5) +#define BSC_S_TXD (1<< 4) +#define BSC_S_RXR (1<< 3) +#define BSC_S_TXW (1<< 2) +#define BSC_S_DONE (1<< 1) +#define BSC_S_TA 1 + +#define CLEAR_STATUS BSC_S_CLKT|BSC_S_ERR|BSC_S_DONE + +#define GPFSEL0 *(gpio.addr + 0) +#define GPFSEL1 *(gpio.addr + 1) +#define GPFSEL2 *(gpio.addr + 2) +#define GPFSEL3 *(gpio.addr + 3) +#define GPFSEL4 *(gpio.addr + 4) +#define GPFSEL5 *(gpio.addr + 5) +// Reserved @ word offset 6 +#define GPSET0 *(gpio.addr + 7) +#define GPSET1 *(gpio.addr + 8) +// Reserved @ word offset 9 +#define GPCLR0 *(gpio.addr + 10) +#define GPCLR1 *(gpio.addr + 11) +// Reserved @ word offset 12 +#define GPLEV0 *(gpio.addr + 13) +#define GPLEV1 *(gpio.addr + 14) + +#define PAGESIZE 4096 +#define BLOCK_SIZE 4096 + +/// 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 + +#define BCM2835_GPFSEL0 0x0000 ///< GPIO Function Select 0 + +#define BCM2835_GPEDS0 0x0040 ///< GPIO Pin Event Detect Status 0 +#define BCM2835_GPREN0 0x004c ///< GPIO Pin Rising Edge Detect Enable 0 +#define BCM2835_GPFEN0 0x0048 ///< GPIO Pin Falling Edge Detect Enable 0 +#define BCM2835_GPHEN0 0x0064 ///< GPIO Pin High Detect Enable 0 +#define BCM2835_GPLEN0 0x0070 ///< GPIO Pin Low Detect Enable 0 + +static int REV = 0; + +typedef enum { + // Not connected + NC = (int)0xFFFFFFFF, + + // GPIO names + gpio2 = 2, + gpio3 = 3, + gpio4 = 4, + gpio5 = 5, + gpio6 = 6, + gpio7 = 7, + gpio8 = 8, + gpio9 = 9, + gpio10 = 10, + gpio11 = 11, + gpio12 = 12, + gpio13 = 13, + gpio14 = 14, + gpio15 = 15, + gpio16 = 16, + gpio17 = 17, + gpio18 = 18, + gpio19 = 19, + gpio20 = 20, + gpio21 = 21, + gpio22 = 22, + gpio23 = 23, + gpio24 = 24, + gpio25 = 25, + gpio26 = 26, + gpio27 = 27, + + // Rapsberry Pi pin names + p3 = gpio2, + p5 = gpio3, + p7 = gpio4, + p8 = gpio14, + p10 = gpio15, + p11 = gpio17, + p12 = gpio18, + p13 = gpio27, + p15 = gpio22, + p16 = gpio23, + p18 = gpio24, + p19 = gpio10, + p21 = gpio9, + p22 = gpio25, + p23 = gpio11, + p24 = gpio8, + p26 = gpio7, + p29 = gpio5, + p31 = gpio6, + p32 = gpio12, + p33 = gpio13, + p35 = gpio19, + p36 = gpio16, + p37 = gpio26, + p38 = gpio20, + p40 = gpio21, + + // Extension board V2.1 pin names + P0 = gpio17, + P1 = gpio18, + P2 = gpio27, + P3 = gpio22, + P4 = gpio23, + P5 = gpio24, + P6 = gpio25, + P7 = gpio4, + CE1 = gpio7, + CE0 = gpio8, + CS = gpio8, + SCLK = gpio11, + MISO = gpio9, + MOSI = gpio10, + RXD = gpio15, + TXD = gpio14, + SCL = gpio3, + SDA = gpio2, + PWM = gpio18 + +} PinName; + +typedef enum +{ + PIN_INPUT, + PIN_OUTPUT +} PinDirection; + +typedef enum +{ + PullNone, + PullUp, + PullDown, + OpenDrain, + PullDefault = PullNone +} PinMode; + +typedef void (*FunctionPointer) (void); + +/// \brief bcm2835SPIBitOrder +/// Specifies the SPI data bit ordering +typedef enum +{ + LSBFIRST = 0, ///< LSB First + MSBFIRST = 1///< MSB First +}bcm2835SPIBitOrder; + +/// \brief bcm2835SPIMode +/// Specify the SPI data mode +typedef enum +{ + SPI_MODE0 = 0, ///< CPOL = 0, CPHA = 0 + SPI_MODE1 = 1, ///< CPOL = 0, CPHA = 1 + SPI_MODE2 = 2, ///< CPOL = 1, CPHA = 0 + SPI_MODE3 = 3, ///< CPOL = 1, CPHA = 1 +}bcm2835SPIMode; + +/// \brief bcm2835SPIChipSelect +/// Specify the SPI chip select pin(s) +typedef enum +{ + SPI_CS0 = 0, ///< Chip Select 0 + SPI_CS1 = 1, ///< Chip Select 1 + SPI_CS2 = 2, ///< Chip Select 2 (ie pins CS1 and CS2 are asserted) + 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. +typedef enum +{ + SPI_CLOCK_DIV65536 = 0, ///< 65536 = 256us = 4kHz + SPI_CLOCK_DIV32768 = 32768, ///< 32768 = 126us = 8kHz + SPI_CLOCK_DIV16384 = 16384, ///< 16384 = 64us = 15.625kHz + SPI_CLOCK_DIV8192 = 8192, ///< 8192 = 32us = 31.25kHz + SPI_CLOCK_DIV4096 = 4096, ///< 4096 = 16us = 62.5kHz + SPI_CLOCK_DIV2048 = 2048, ///< 2048 = 8us = 125kHz + SPI_CLOCK_DIV1024 = 1024, ///< 1024 = 4us = 250kHz + SPI_CLOCK_DIV512 = 512, ///< 512 = 2us = 500kHz + SPI_CLOCK_DIV256 = 256, ///< 256 = 1us = 1MHz + SPI_CLOCK_DIV128 = 128, ///< 128 = 500ns = = 2MHz + SPI_CLOCK_DIV64 = 64, ///< 64 = 250ns = 4MHz + SPI_CLOCK_DIV32 = 32, ///< 32 = 125ns = 8MHz + SPI_CLOCK_DIV16 = 16, ///< 16 = 50ns = 20MHz + SPI_CLOCK_DIV8 = 8, ///< 8 = 25ns = 40MHz + SPI_CLOCK_DIV4 = 4, ///< 4 = 12.5ns 80MHz + SPI_CLOCK_DIV2 = 2, ///< 2 = 6.25ns = 160MHz + SPI_CLOCK_DIV1 = 1, ///< 0 = 256us = 4kHz +} bcm2835SPIClockDivider; + +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; + +namespace unistd { + //All functions of unistd.h must be called like this: unistd::the_function() + #include <unistd.h> +} + +enum Representation{ + BIN, + OCT, + DEC, + HEX, + BYTE +}; + +typedef enum { + LOW = 0, + HIGH = 1, + RISING = 2, + FALLING = 3, + BOTH = 4 +} Digivalue; +// +/*$on*/ +// +typedef bool boolean; +typedef unsigned char byte; + +struct bcm2835_peripheral +{ + unsigned long addr_p; + int mem_fd; + void* map; + volatile unsigned int* addr; +}; + +struct ThreadArg +{ + void (*func) (); + int pin; +}; + +void wait(float s); +void wait_ms(int ms); +void wait_us(int us); + +void gpio_dir(PinName pin, PinDirection direction); +void gpio_mode(PinName pin, PinMode mode); +void gpio_write(PinName pin, int value); +int gpio_read(PinName pin); +uint8_t shiftIn(PinName dPin, PinName cPin, bcm2835SPIBitOrder order); +void shiftOut(PinName dPin, PinName cPin, bcm2835SPIBitOrder order, uint8_t val); +void attachInterrupt(PinName p, void (*f) (), Digivalue m); +void detachInterrupt(PinName p); + +class DigitalIn +{ +public: + DigitalIn(PinName pin) : gpio(pin) { gpio_dir(gpio, PIN_INPUT); gpio_write(gpio, LOW); } + DigitalIn(PinName pin, PinMode mode) : gpio(pin) { gpio_dir(gpio, PIN_INPUT); gpio_mode(pin, mode); } + int read(void) { return gpio_read(gpio); } + void mode(PinMode mode) { mode == PullUp ? gpio_write(gpio, HIGH) : gpio_write(gpio, LOW); } + void attach(FunctionPointer fptr, Digivalue m) { attachInterrupt(gpio, fptr, m); } + operator int(void) { return read(); } +protected: + PinName gpio; +}; + +class DigitalOut +{ +public: + DigitalOut(PinName pin) : gpio(pin) { gpio_dir(gpio, PIN_OUTPUT); } + DigitalOut(PinName pin, int value) : gpio(pin) { gpio_dir(gpio, PIN_OUTPUT); gpio_write(gpio, value); } + void write(int value) { gpio_write(gpio, value); } + int read(void) { return gpio_read(gpio); } + DigitalOut &operator =(int value) { write(value); return *this; } + DigitalOut &operator =(DigitalOut& rhs) { write(rhs.read()); return *this; } + operator int(void) { return read(); } +protected: + PinName gpio; +}; + +class DigitalInOut +{ +public: + DigitalInOut(PinName pin) : gpio(pin) { PinMode(PIN_INPUT); } + DigitalInOut(PinName pin, PinDirection direction, PinMode mode, int value) : + gpio(pin) { + if(direction == PIN_INPUT) { + gpio_dir(gpio, PIN_INPUT); + if(mode == PullUp) + gpio_write(gpio, HIGH); + else + gpio_write(gpio, LOW); + } + else { + gpio_dir(gpio, PIN_OUTPUT); + gpio_write(gpio, value); + } + } + void write(int value) { gpio_write(gpio, value); } + int read(void) { return gpio_read(gpio); } + void output(void) { gpio_dir(gpio, PIN_OUTPUT); } + void input(void) { gpio_dir(gpio, PIN_INPUT); } + DigitalInOut &operator =(int value) { write(value); return *this; } + operator int(void) { return read(); } +protected: + PinName gpio; +}; + +class InterruptIn +{ +public: + InterruptIn(PinName pin) : + _digitalIn(pin) { } + + void rise(FunctionPointer fptr) { _digitalIn.attach(fptr, RISING); } + void fall(FunctionPointer fptr) { _digitalIn.attach(fptr, FALLING); } + void both(FunctionPointer fptr) { _digitalIn.attach(fptr, BOTH); } + int read(void) { return _digitalIn.read(); } + void mode(PinMode mode) { _digitalIn.mode(mode); } + operator int(void) { return _digitalIn.read(); } +protected: + DigitalIn _digitalIn; +}; + +class Serial +{ +private: + int sd, status; + const char* serialPort; + unsigned char c; + struct termios options; + int speed; + long timeOut; + timespec time1, time2; + timespec timeDiff(timespec start, timespec close); + char* int2bin(int i); + char* int2hex(int i); + char* int2oct(int i); +public: + Serial(void); + void baud(int serialSpeed); + int readable(void); + char read(void); + int readBytes(char message[], int size); + int readBytesUntil(char character, char buffer[], int length); + bool find(const char* target); + bool findUntil(const char* target, const char* terminal); + long parseInt(void); + float parseFloat(void); + char peek(void); + void printf(const char* format, ...); + int write(uint8_t message); + int write(const char* message); + int write(char* message, int size); + void flush(void); + void setTimeout(long millis); + void close(void); +}; + +class I2C +{ +private: + int i2c_byte_wait_us; + int i2c_bytes_to_read; + void dump_bsc_status(void); + + void wait_i2c_done(void); +public: + I2C(void); + void begin(void); + void beginTransmission(unsigned char address); + void write(char data); + uint8_t write(const char* buf, uint32_t len); + void endTransmission(void); + void requestFrom(unsigned char address, int quantity); + unsigned char read(void); + uint8_t read(char* buf); + uint8_t read_rs(char* regaddr, char* buf, uint32_t len); +}; + +class SPI +{ +public: + SPI(void); + void begin(void); + void end(void); + void setBitOrder(uint8_t order); + void setClockDivider(uint16_t divider); + void setDataMode(uint8_t mode); + void chipSelect(uint8_t cs); + void setChipSelectPolarity(uint8_t cs, uint8_t active); + uint8_t transfer(uint8_t value); + void transfernb(char* tbuf, char* rbuf, uint32_t len); +}; + +class Peripheral +{ +private: + int memfd; + int map_peripheral(struct bcm2835_peripheral* p); + void unmap_peripheral(struct bcm2835_peripheral* p); +public: + Peripheral(void); + ~Peripheral(void); +}; + +/* Helper functions */ +int getBoardRev(void); +uint32_t* mapmem(const char* msg, size_t size, int fd, off_t off); +void setBoardRev(int rev); +pthread_t* getThreadIdFromPin(int pin); +void* threadFunction(void* args); +uint32_t bcm2835_peri_read(volatile uint32_t* paddr); +uint32_t bcm2835_peri_read_nb(volatile uint32_t* paddr); +void bcm2835_peri_write(volatile uint32_t* paddr, uint32_t value); +void bcm2835_peri_write_nb(volatile uint32_t* paddr, uint32_t value); +void bcm2835_peri_set_bits(volatile uint32_t* paddr, uint32_t value, uint32_t mask); +void bcm2835_gpio_fsel(uint8_t pin, uint8_t mode); + +#endif // MBEDPI_H