aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authortslil clingman <tslil@posteo.de>2021-01-20 01:09:22 -0500
committertslil <tslil@posteo.de>2026-08-28 19:37:41 +0100
commit3b9c9d71f8a30d8a38c78f49cb19f616040a9dc5 (patch)
treec61d55be0abd9a26f44ca3adce9bd9e8b71e0f63
parent277a2c0984a9bbe7e966d62ae05445c494d09455 (diff)
Closing in on lcd!
-rw-r--r--.clang_complete1
-rw-r--r--3rd-party/LCDHD44780.c381
-rw-r--r--3rd-party/LCDHD44780.h195
-rw-r--r--3rd-party/bcm2835-COPYING674
-rw-r--r--3rd-party/bcm2835.c2029
-rw-r--r--3rd-party/bcm2835.h2029
-rw-r--r--Makefile2
-rw-r--r--config-buildroot (renamed from buildroot-config)0
-rw-r--r--src/ct1986.c53
9 files changed, 29 insertions, 5335 deletions
diff --git a/.clang_complete b/.clang_complete
index e9c2aee..3e2e760 100644
--- a/.clang_complete
+++ b/.clang_complete
@@ -1,2 +1 @@
-Iinclude/
--I3rd-party/
diff --git a/3rd-party/LCDHD44780.c b/3rd-party/LCDHD44780.c
deleted file mode 100644
index 8a01a20..0000000
--- a/3rd-party/LCDHD44780.c
+++ /dev/null
@@ -1,381 +0,0 @@
-/*##############################################################*/
-/* Author: Marcus Nasarek */
-/* File: LCDH44780.c */
-/* Compile with: */
-/* gcc -Wall -c LCDHD44780.c -o LCDHD44780.o */
-/* License: */
-/* */
-/* 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/>. */
-/* */
-/*##############################################################*/
-
-#include "LCDHD44780.h"
-
-void init_gpio(void)
-{
- // Set all pins to output
- bcm2835_gpio_fsel(LCD_RS, BCM2835_GPIO_FSEL_OUTP);
- bcm2835_gpio_fsel(LCD_D4, BCM2835_GPIO_FSEL_OUTP);
- bcm2835_gpio_fsel(LCD_D5, BCM2835_GPIO_FSEL_OUTP);
- bcm2835_gpio_fsel(LCD_D6, BCM2835_GPIO_FSEL_OUTP);
- bcm2835_gpio_fsel(LCD_D7, BCM2835_GPIO_FSEL_OUTP);
- bcm2835_gpio_fsel(LCD_E, BCM2835_GPIO_FSEL_OUTP);
-
- bcm2835_delayMicroseconds(C_DELAY);
-
- // Set all pins to LOW
- bcm2835_gpio_clr(LCD_RS);
- bcm2835_gpio_clr(LCD_D4);
- bcm2835_gpio_clr(LCD_D5);
- bcm2835_gpio_clr(LCD_D5);
- bcm2835_gpio_clr(LCD_D7);
- bcm2835_gpio_clr(LCD_E);
-
-}
-
-void pulse_e(void)
-{
- // Toogle ENABLE pin in us
- // bcm2835_gpio_fsel(LCD_E, BCM2835_GPIO_FSEL_OUTP);
- bcm2835_delayMicroseconds(E_DELAY);
- bcm2835_gpio_set(LCD_E);
- bcm2835_delayMicroseconds(E_DATA_PULSE);
- bcm2835_gpio_clr(LCD_E);
- (LCD_DATA) ? bcm2835_delayMicroseconds(E_DATA_PULSE) :bcm2835_delayMicroseconds(E_CMD_PULSE);
-}
-
-void init_lcd(void)
-{
- init_gpio();
-
- /*
- The busy flag (BF) is kept in the busy state
- until the initialization ends (BF = 1). The
- busy state lasts for 10 ms after VCC rises to 4.5 V
- */
-
- /*
- --- symbols:
- I/D = 1: Increment
- I/D = 0: Decrement
- S = 1: Accompanies display shift
- S/C = 1: Display shift
- S/C = 0: Cursor move
- R/L = 1: Shift to the right
- R/L = 0: Shift to the left
- DL = 1: 8 bits, DL = 0: 4 bits
- N = 1: 2 lines, N = 0: 1 line
- F = 1: 5
- ×
- 10 dots, F = 0: 5
- ×
- 8 dots
- BF = 1: Internally operating
- BF = 0: Instructions acceptable
- */
-
- /*
- --- Display init after turn on:
- 1. Display clear
- 2. Function set:
- DL = 1; 8-bit interface data
- N = 0; 1-line display
- F = 0; 5×8 dot character font
- 3. Display on/off control:
- D = 0; Display off
- C = 0; Cursor off
- B = 0; Blinking off
- 4. Entry mode set:
- I/D = 1; Increment by 1
- S = 0; No shift
- */
-
- // begin of "warming up"
- // see fig 24 on page 46 of datasheet
-
- // Function set -
- // Sets interface data length
- // (DL), number of display lines
- // (N), and character font (F).
- // RS R/W DB7 DB6 DB5 DB4 DB3 DB2 DB1 DB0
- // 0 0 0 0 1 DL N F - -
- // DL = 0 --> 4 bit data length (1 = 8 bit)
- // N = 1 --> 2 line display (0 = 1 line)
- // F = 0 --> 5x8 dot character font
- // 0x33 =
- // 0 0 0 0 1 1 0 0 1 1
- // --> ?
- write_to_lcd(0x33, LCD_CMD);
- bcm2835_delayMicroseconds(100);
-
- // Function set -
- // Sets interface data length
- // (DL), number of display lines
- // (N), and character font (F).
- // RS R/W DB7 DB6 DB5 DB4 DB3 DB2 DB1 DB0
- // 0 0 0 0 1 DL N F - -
- // DL = 0 --> 4 bit data length (1 = 8 bit)
- // N = 1 --> 2 line display (0 = 1 line)
- // F = 0 --> 5x8 dot character font
- // 0x32 =
- // 0 0 0 0 1 1 0 0 1 0
- // --> ?
- write_to_lcd(0x32, LCD_CMD);
- bcm2835_delayMicroseconds(R_EXEC_TIME);
-
- // end of "warming up"
-
- lcd_function_set(TWO_LINES);
-
- lcd_control(DISPLAY_ON);
-
- lcd_entry_mode(ADDR_INCREMENT);
-
- clear_lcd();
-
-}
-
-void lcd_function_set(uint8_t control_flags)
-{
- // Function set -
- // Sets interface data length
- // (DL), number of display lines
- // (N), and character font (F).
- // RS R/W DB7 DB6 DB5 DB4 DB3 DB2 DB1 DB0
- // 0 0 0 0 1 DL N F - -
- // DL = 0 --> 4 bit data length (1 = 8 bit)
- // N = 1 --> 2 line display (0 = 1 line)
- // F = 0 --> 5x8 dot character font
- // F = 1 --> 5x10 dot character font
- // 0x28 =
- // 0 0 0 0 1 0 1 0 0 0
- write_to_lcd(LCD_FUNCTION_SET | control_flags, LCD_CMD);
- bcm2835_delayMicroseconds(R_EXEC_TIME);
-}
-
-void lcd_control(uint8_t control_flags)
-{
- // Display on/off control -
- // Sets entire display (D) on/off,
- // cursor on/off (C), and
- // blinking of cursor position
- // character (B).
- // RS R/W DB7 DB6 DB5 DB4 DB3 DB2 DB1 DB0
- // 0 0 0 0 0 0 1 D C B
- // D = 1 --> display on
- // C = 0 --> cursor off
- // B = 0 --> blinking off
- write_to_lcd(LCD_CONTROL | control_flags, LCD_CMD);
- bcm2835_delayMicroseconds(R_EXEC_TIME);
-}
-
-void lcd_shift_control(uint8_t control_flags)
-{
- // Cursor or display shift -
- // Moves the cursor and shifts
- // display without chaning
- // DDRAM contents.
- // Execution time 37us
- // RS R/W DB7 DB6 DB5 DB4 DB3 DB2 DB1 DB0
- // 0 0 0 0 0 1 S/C R/L - -
- // S/C = cursor/display shift
- // S/C = 0 --> cursor shift
- // R/L = shift direction
- // R/L = 1 --> shift to right
- write_to_lcd(CURSOR_DISPLAY_SHIFT | control_flags, LCD_CMD);
- bcm2835_delayMicroseconds(R_EXEC_TIME);
-}
-
-void lcd_entry_mode(uint8_t control_flags)
-{
- // Entry mode set -
- // Sets cursor move direction
- // and specifies display shift.
- // These operations are
- // performed during data write
- // and read.
- // Execution time 37us
- // RS R/W DB7 DB6 DB5 DB4 DB3 DB2 DB1 DB0
- // 0 0 0 0 0 0 0 1 I/D S
- // I/D = increment/decrement address pointer
- // I/D = 1 --> increment
- // S = 0 --> no shift
- write_to_lcd(LCD_ENTRY_MODE | control_flags, LCD_CMD);
- bcm2835_delayMicroseconds(R_EXEC_TIME);
-}
-
-void clear_lcd(void) {
- // Clear display -
- // Clears entire display and
- // sets DDRAM address 0 in
- // address counter:
- // RS R/W DB7 DB6 DB5 DB4 DB3 DB2 DB1 DB0
- // 0 0 0 0 0 0 0 0 0 1
- write_to_lcd(0x01, LCD_CMD);
- bcm2835_delayMicroseconds(R_EXEC_TIME);
-}
-
-void return_home(void)
-{
- // Return home -
- // Sets DDRAM address to 0
- // in address counter. Also
- // returns display from being
- // shifted to original position
- // DDRAM contents remains unchanged
- // RS R/W DB7 DB6 DB5 DB4 DB3 DB2 DB1 DB0
- // 0 0 0 0 0 0 0 0 1 -
- write_to_lcd(0x02, LCD_CMD);
- bcm2835_delayMicroseconds(R_EXEC_TIME);
-}
-
-
-void display_off(void)
-{
- lcd_control(DISPLAY_OFF);
-}
-
-void show_cursor(bool on)
-{
- uint8_t cursor_flag;
- cursor_flag = ( on ? CURSOR_ON : 0x00);
- lcd_control(DISPLAY_ON | cursor_flag);
-}
-
-void cursor_blinking(bool on)
-{
- uint8_t blinking_flag;
- blinking_flag = ( on ? BLINKING_ON : 0x00);
- lcd_control(DISPLAY_ON | blinking_flag);
-}
-
-void set_cursor(uint8_t addr)
-{
- // Set DDRAM address
- // RS R/W DB7 DB6 DB5 DB4 DB3 DB2 DB1 DB0
- // 0 0 1 ADD ADD ADD ADD ADD ADD ADD
- write_to_lcd(addr, LCD_CMD);
- bcm2835_delayMicroseconds(R_EXEC_TIME);
- // fprintf(stdout,"cursor on addr: 0x%0x\n", addr);
-}
-
-void shift_cursor(uint8_t direction)
-{
- lcd_shift_control(CURSOR_SHIFT | direction);
-}
-
-void shift_display(uint8_t direction)
-{
- lcd_shift_control(DISPLAY_SHIFT | direction);
-}
-
-void write_to_lcd(uint8_t byte, uint8_t mode)
-{
- switch (mode) {
- case LCD_CMD:
- bcm2835_gpio_clr(LCD_RS);
- // fprintf(stdout, "Set RS to cmd mode\n");
- break;
- case LCD_DATA:
- bcm2835_gpio_set(LCD_RS);
- // fprintf(stdout, "Set RS to data mode for '%c'\n", byte);
- break;
- default:
- // fprintf(stderr, "mode for setting GPIO pin unknown: %i\n", mode);
- exit(EXIT_FAILURE);
- }
-
- // write high bits
- bcm2835_gpio_clr(LCD_D4);
- bcm2835_gpio_clr(LCD_D5);
- bcm2835_gpio_clr(LCD_D6);
- bcm2835_gpio_clr(LCD_D7);
-
- if ((byte & 0x10) == 0x10) {
- bcm2835_gpio_set(LCD_D4);
- }
- if ((byte & 0x20) == 0x20) {
- bcm2835_gpio_set(LCD_D5);
- }
- if ((byte & 0x40) == 0x40) {
- bcm2835_gpio_set(LCD_D6);
- }
- if ((byte & 0x80) == 0x80) {
- bcm2835_gpio_set(LCD_D7);
- }
-
- // Toogle ENABLE pin in us
- pulse_e();
-
- // write low bits
- bcm2835_gpio_clr(LCD_D4);
- bcm2835_gpio_clr(LCD_D5);
- bcm2835_gpio_clr(LCD_D6);
- bcm2835_gpio_clr(LCD_D7);
-
- if ((byte & 0x01) == 0x01) {
- bcm2835_gpio_set(LCD_D4);
- }
- if ((byte & 0x02) == 0x02) {
- bcm2835_gpio_set(LCD_D5);
- }
- if ((byte & 0x04) == 0x04) {
- bcm2835_gpio_set(LCD_D6);
- }
- if ((byte & 0x08) == 0x08) {
- bcm2835_gpio_set(LCD_D7);
- }
-
- pulse_e();
-
-}
-
-void write_string(char *str)
-{
- uint16_t i;
- uint8_t len = 0;
-
- len = (strlen(str) > LCD_WIDTH ? LCD_WIDTH : strlen(str));
-
- for (i=0; i<len;i++) {
- write_to_lcd(str[i], LCD_DATA);
- }
-}
-
-void gpio_reset(void)
-{
- // bcm2835_gpio_fsel(LCD_RS, BCM2835_GPIO_PUD_OFF);
- // bcm2835_gpio_fsel(LCD_E, BCM2835_GPIO_PUD_OFF);
- // bcm2835_gpio_fsel(LCD_D4, BCM2835_GPIO_PUD_OFF);
- // bcm2835_gpio_fsel(LCD_D5, BCM2835_GPIO_PUD_OFF);
- // bcm2835_gpio_fsel(LCD_D6, BCM2835_GPIO_PUD_OFF);
- // bcm2835_gpio_fsel(LCD_D7, BCM2835_GPIO_PUD_OFF);
-
- // bcm2835_gpio_fsel(LCD_RS, BCM2835_GPIO_FSEL_INPT);
- // bcm2835_gpio_fsel(LCD_E, BCM2835_GPIO_FSEL_INPT);
- // bcm2835_gpio_fsel(LCD_D4, BCM2835_GPIO_FSEL_INPT);
- // bcm2835_gpio_fsel(LCD_D5, BCM2835_GPIO_FSEL_INPT);
- // bcm2835_gpio_fsel(LCD_D6, BCM2835_GPIO_FSEL_INPT);
- // bcm2835_gpio_fsel(LCD_D7, BCM2835_GPIO_FSEL_INPT);
-
- bcm2835_gpio_clr(LCD_RS);
- bcm2835_gpio_clr(LCD_E);
- bcm2835_gpio_clr(LCD_D4);
- bcm2835_gpio_clr(LCD_D5);
- bcm2835_gpio_clr(LCD_D6);
- bcm2835_gpio_clr(LCD_D7);
-}
diff --git a/3rd-party/LCDHD44780.h b/3rd-party/LCDHD44780.h
deleted file mode 100644
index 8e2e953..0000000
--- a/3rd-party/LCDHD44780.h
+++ /dev/null
@@ -1,195 +0,0 @@
-/*##############################################################*/
-/* Author: Marcus Nasarek */
-/* File: LCDH44780.h */
-/* License: */
-/* */
-/* 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/>. */
-/* */
-/*##############################################################*/
-
-// Thanks to Matt Hawkins (http://www.raspberrypi-spy.co.uk)
-// The wiring for the LCD is as follows:
-// 1 : GND
-// 2 : 5V
-// 3 : Contrast (0-5V)*
-// 4 : RS (Register Select)
-// 5 : R/W (Read Write) - GROUND THIS PIN
-// 6 : Enable or Strobe
-// 7 : Data Bit 0 - NOT USED
-// 8 : Data Bit 1 - NOT USED
-// 9 : Data Bit 2 - NOT USED
-// 10: Data Bit 3 - NOT USED
-// 11: Data Bit 4
-// 12: Data Bit 5
-// 13: Data Bit 6
-// 14: Data Bit 7
-// 15: LCD Backlight +5V**
-// 16: LCD Backlight GND
-
-#ifndef _LCDHD44780_H_
-#define _LCDHD44780_H_
-
-#include <stdlib.h>
-#include <stdbool.h>
-#include <stdio.h>
-#include <string.h>
-#include <stdbool.h>
-#include <bcm2835.h>
-
-// Define GPIO pin to LCD pin mapping
-#define LCD_RS 21
-#define LCD_E 20
-#define LCD_D4 26
-#define LCD_D5 19
-#define LCD_D6 13
-#define LCD_D7 6
-
-// Define some device constants
-// Maximum characters per line
-#define LCD_WIDTH 16
-#define LCD_DATA HIGH
-#define LCD_CMD LOW
-
-// Function set -
-// Sets interface data length
-// (DL), number of display lines
-// (N), and character font (F).
-// RS R/W DB7 DB6 DB5 DB4 DB3 DB2 DB1 DB0
-// 0 0 0 0 1 DL N F - -
-// DL = 0 --> 4 bit data length (1 = 8 bit)
-// N = 1 --> 2 line display (0 = 1 line)
-// F = 0 --> 5x8 dot character font
-// F = 1 --> 5x10 dot character font
-// 0x28 =
-// 0 0 0 0 1 0 1 0 0 0
-#define LCD_FUNCTION_SET 0x20
-#define DATA_LENGTH 0x10
-#define TWO_LINES 0x08
-#define BIG_FONT_SET 0x04
-
-
-
-// Display control flags
-// Sets entire display (D) on/off,
-// cursor on/off (C), and
-// blinking of cursor position
-// character (B).
-// RS R/W DB7 DB6 DB5 DB4 DB3 DB2 DB1 DB0
-// 0 0 0 0 0 0 1 D C B
-// D = 1 --> display on
-// C = 0 --> cursor off
-// B = 0 --> blinking off
-#define LCD_CONTROL 0x08 // display control
-#define DISPLAY_ON 0x04
-#define DISPLAY_OFF 0x00
-#define CURSOR_ON 0x02
-#define BLINKING_ON 0x01
-
-// Entry mode set -
-// Sets cursor move direction
-// and specifies display shift.
-// These operations are
-// performed during data write
-// and read.
-// Execution time 37us
-// RS R/W DB7 DB6 DB5 DB4 DB3 DB2 DB1 DB0
-// 0 0 0 0 0 0 0 1 I/D S
-// I/D = increment/decrement address pointer
-// I/D = 1 --> increment
-// S = 0 --> no shift
-#define LCD_ENTRY_MODE 0x04
-#define ADDR_INCREMENT 0x02
-#define LINE_SHIFT 0x01
-
-// Cursor or display shift -
-// Moves the cursor and shifts
-// display without chaning
-// DDRAM contents.
-// Execution time 37us
-// RS R/W DB7 DB6 DB5 DB4 DB3 DB2 DB1 DB0
-// 0 0 0 0 0 1 S/C R/L - -
-// S/C = cursor/display shift
-// S/C = 0 --> cursor shift
-// R/L = shift direction
-// R/L = 1 --> shift to right
-#define CURSOR_DISPLAY_SHIFT 0x10
-#define CURSOR_SHIFT 0x00
-#define DISPLAY_SHIFT 0x08
-#define SHIFT_RIGHT 0x04
-#define SHIFT_LEFT 0x00
-
-
-// LCD DDRAM address for the 1st line
-// bits DB0..DB6 --> 0x00..0x4F
-// DB7 = 1 --> offset = 0x80
-// RS R/W DB7 DB6 DB5 DB4 DB3 DB2 DB1 DB0
-// 0 0 1 ADD ADD ADD ADD ADD ADD ADD
-// 0x80 =
-// 0 0 1 0 0 0 0 0 0 0
-#define LCD_LINE_1 0x80
-// LCD DDRAM address for the 2nd line
-// 2 lines with equal # of addresses
-// DB7 = 1 --> offset = 0x80 + (0x00..0x4F)/2 = 0xC0
-#define LCD_LINE_2 0xC0
-
-// Timing constants in us
-#define E_DELAY 1 // us
-#define E_CMD_PULSE 5000 // us
-#define E_DATA_PULSE 5000 // us
-#define C_DELAY 1 // us
-#define R_EXEC_TIME 50 // us
-#define GPIO_RISING 10 // ms
-
-#define MAX_WAIT 100
-
-void init_gpio(void);
-
-void init_lcd(void);
-
-void lcd_function_set(uint8_t control_flags);
-
-void lcd_control(uint8_t control_flags);
-
-void lcd_entry_mode(uint8_t control_flags);
-
-void lcd_shift_control(uint8_t control_flags);
-
-void clear_lcd(void);
-
-void set_cursor(uint8_t addr);
-
-void display_off(void);
-
-void show_cursor(bool on);
-
-void cursor_blinking(bool on);
-
-void shift_cursor(uint8_t direction);
-
-void shift_display(uint8_t direction);
-
-void return_home(void);
-
-void write_to_lcd(uint8_t byte, uint8_t mode);
-
-void write_string(char *str);
-
-uint8_t read_from_lcd(uint8_t mode);
-
-void gpio_reset(void);
-
-#endif
diff --git a/3rd-party/bcm2835-COPYING b/3rd-party/bcm2835-COPYING
deleted file mode 100644
index e72bfdd..0000000
--- a/3rd-party/bcm2835-COPYING
+++ /dev/null
@@ -1,674 +0,0 @@
- GNU GENERAL PUBLIC LICENSE
- Version 3, 29 June 2007
-
- Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
- Everyone is permitted to copy and distribute verbatim copies
- of this license document, but changing it is not allowed.
-
- Preamble
-
- The GNU General Public License is a free, copyleft license for
-software and other kinds of works.
-
- The licenses for most software and other practical works are designed
-to take away your freedom to share and change the works. By contrast,
-the GNU General Public License is intended to guarantee your freedom to
-share and change all versions of a program--to make sure it remains free
-software for all its users. We, the Free Software Foundation, use the
-GNU General Public License for most of our software; it applies also to
-any other work released this way by its authors. You can apply it to
-your programs, too.
-
- When we speak of free software, we are referring to freedom, not
-price. Our General Public Licenses are designed to make sure that you
-have the freedom to distribute copies of free software (and charge for
-them if you wish), that you receive source code or can get it if you
-want it, that you can change the software or use pieces of it in new
-free programs, and that you know you can do these things.
-
- To protect your rights, we need to prevent others from denying you
-these rights or asking you to surrender the rights. Therefore, you have
-certain responsibilities if you distribute copies of the software, or if
-you modify it: responsibilities to respect the freedom of others.
-
- For example, if you distribute copies of such a program, whether
-gratis or for a fee, you must pass on to the recipients the same
-freedoms that you received. You must make sure that they, too, receive
-or can get the source code. And you must show them these terms so they
-know their rights.
-
- Developers that use the GNU GPL protect your rights with two steps:
-(1) assert copyright on the software, and (2) offer you this License
-giving you legal permission to copy, distribute and/or modify it.
-
- For the developers' and authors' protection, the GPL clearly explains
-that there is no warranty for this free software. For both users' and
-authors' sake, the GPL requires that modified versions be marked as
-changed, so that their problems will not be attributed erroneously to
-authors of previous versions.
-
- Some devices are designed to deny users access to install or run
-modified versions of the software inside them, although the manufacturer
-can do so. This is fundamentally incompatible with the aim of
-protecting users' freedom to change the software. The systematic
-pattern of such abuse occurs in the area of products for individuals to
-use, which is precisely where it is most unacceptable. Therefore, we
-have designed this version of the GPL to prohibit the practice for those
-products. If such problems arise substantially in other domains, we
-stand ready to extend this provision to those domains in future versions
-of the GPL, as needed to protect the freedom of users.
-
- Finally, every program is threatened constantly by software patents.
-States should not allow patents to restrict development and use of
-software on general-purpose computers, but in those that do, we wish to
-avoid the special danger that patents applied to a free program could
-make it effectively proprietary. To prevent this, the GPL assures that
-patents cannot be used to render the program non-free.
-
- The precise terms and conditions for copying, distribution and
-modification follow.
-
- TERMS AND CONDITIONS
-
- 0. Definitions.
-
- "This License" refers to version 3 of the GNU General Public License.
-
- "Copyright" also means copyright-like laws that apply to other kinds of
-works, such as semiconductor masks.
-
- "The Program" refers to any copyrightable work licensed under this
-License. Each licensee is addressed as "you". "Licensees" and
-"recipients" may be individuals or organizations.
-
- To "modify" a work means to copy from or adapt all or part of the work
-in a fashion requiring copyright permission, other than the making of an
-exact copy. The resulting work is called a "modified version" of the
-earlier work or a work "based on" the earlier work.
-
- A "covered work" means either the unmodified Program or a work based
-on the Program.
-
- To "propagate" a work means to do anything with it that, without
-permission, would make you directly or secondarily liable for
-infringement under applicable copyright law, except executing it on a
-computer or modifying a private copy. Propagation includes copying,
-distribution (with or without modification), making available to the
-public, and in some countries other activities as well.
-
- To "convey" a work means any kind of propagation that enables other
-parties to make or receive copies. Mere interaction with a user through
-a computer network, with no transfer of a copy, is not conveying.
-
- An interactive user interface displays "Appropriate Legal Notices"
-to the extent that it includes a convenient and prominently visible
-feature that (1) displays an appropriate copyright notice, and (2)
-tells the user that there is no warranty for the work (except to the
-extent that warranties are provided), that licensees may convey the
-work under this License, and how to view a copy of this License. If
-the interface presents a list of user commands or options, such as a
-menu, a prominent item in the list meets this criterion.
-
- 1. Source Code.
-
- The "source code" for a work means the preferred form of the work
-for making modifications to it. "Object code" means any non-source
-form of a work.
-
- A "Standard Interface" means an interface that either is an official
-standard defined by a recognized standards body, or, in the case of
-interfaces specified for a particular programming language, one that
-is widely used among developers working in that language.
-
- The "System Libraries" of an executable work include anything, other
-than the work as a whole, that (a) is included in the normal form of
-packaging a Major Component, but which is not part of that Major
-Component, and (b) serves only to enable use of the work with that
-Major Component, or to implement a Standard Interface for which an
-implementation is available to the public in source code form. A
-"Major Component", in this context, means a major essential component
-(kernel, window system, and so on) of the specific operating system
-(if any) on which the executable work runs, or a compiler used to
-produce the work, or an object code interpreter used to run it.
-
- The "Corresponding Source" for a work in object code form means all
-the source code needed to generate, install, and (for an executable
-work) run the object code and to modify the work, including scripts to
-control those activities. However, it does not include the work's
-System Libraries, or general-purpose tools or generally available free
-programs which are used unmodified in performing those activities but
-which are not part of the work. For example, Corresponding Source
-includes interface definition files associated with source files for
-the work, and the source code for shared libraries and dynamically
-linked subprograms that the work is specifically designed to require,
-such as by intimate data communication or control flow between those
-subprograms and other parts of the work.
-
- The Corresponding Source need not include anything that users
-can regenerate automatically from other parts of the Corresponding
-Source.
-
- The Corresponding Source for a work in source code form is that
-same work.
-
- 2. Basic Permissions.
-
- All rights granted under this License are granted for the term of
-copyright on the Program, and are irrevocable provided the stated
-conditions are met. This License explicitly affirms your unlimited
-permission to run the unmodified Program. The output from running a
-covered work is covered by this License only if the output, given its
-content, constitutes a covered work. This License acknowledges your
-rights of fair use or other equivalent, as provided by copyright law.
-
- You may make, run and propagate covered works that you do not
-convey, without conditions so long as your license otherwise remains
-in force. You may convey covered works to others for the sole purpose
-of having them make modifications exclusively for you, or provide you
-with facilities for running those works, provided that you comply with
-the terms of this License in conveying all material for which you do
-not control copyright. Those thus making or running the covered works
-for you must do so exclusively on your behalf, under your direction
-and control, on terms that prohibit them from making any copies of
-your copyrighted material outside their relationship with you.
-
- Conveying under any other circumstances is permitted solely under
-the conditions stated below. Sublicensing is not allowed; section 10
-makes it unnecessary.
-
- 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
-
- No covered work shall be deemed part of an effective technological
-measure under any applicable law fulfilling obligations under article
-11 of the WIPO copyright treaty adopted on 20 December 1996, or
-similar laws prohibiting or restricting circumvention of such
-measures.
-
- When you convey a covered work, you waive any legal power to forbid
-circumvention of technological measures to the extent such circumvention
-is effected by exercising rights under this License with respect to
-the covered work, and you disclaim any intention to limit operation or
-modification of the work as a means of enforcing, against the work's
-users, your or third parties' legal rights to forbid circumvention of
-technological measures.
-
- 4. Conveying Verbatim Copies.
-
- You may convey verbatim copies of the Program's source code as you
-receive it, in any medium, provided that you conspicuously and
-appropriately publish on each copy an appropriate copyright notice;
-keep intact all notices stating that this License and any
-non-permissive terms added in accord with section 7 apply to the code;
-keep intact all notices of the absence of any warranty; and give all
-recipients a copy of this License along with the Program.
-
- You may charge any price or no price for each copy that you convey,
-and you may offer support or warranty protection for a fee.
-
- 5. Conveying Modified Source Versions.
-
- You may convey a work based on the Program, or the modifications to
-produce it from the Program, in the form of source code under the
-terms of section 4, provided that you also meet all of these conditions:
-
- a) The work must carry prominent notices stating that you modified
- it, and giving a relevant date.
-
- b) The work must carry prominent notices stating that it is
- released under this License and any conditions added under section
- 7. This requirement modifies the requirement in section 4 to
- "keep intact all notices".
-
- c) You must license the entire work, as a whole, under this
- License to anyone who comes into possession of a copy. This
- License will therefore apply, along with any applicable section 7
- additional terms, to the whole of the work, and all its parts,
- regardless of how they are packaged. This License gives no
- permission to license the work in any other way, but it does not
- invalidate such permission if you have separately received it.
-
- d) If the work has interactive user interfaces, each must display
- Appropriate Legal Notices; however, if the Program has interactive
- interfaces that do not display Appropriate Legal Notices, your
- work need not make them do so.
-
- A compilation of a covered work with other separate and independent
-works, which are not by their nature extensions of the covered work,
-and which are not combined with it such as to form a larger program,
-in or on a volume of a storage or distribution medium, is called an
-"aggregate" if the compilation and its resulting copyright are not
-used to limit the access or legal rights of the compilation's users
-beyond what the individual works permit. Inclusion of a covered work
-in an aggregate does not cause this License to apply to the other
-parts of the aggregate.
-
- 6. Conveying Non-Source Forms.
-
- You may convey a covered work in object code form under the terms
-of sections 4 and 5, provided that you also convey the
-machine-readable Corresponding Source under the terms of this License,
-in one of these ways:
-
- a) Convey the object code in, or embodied in, a physical product
- (including a physical distribution medium), accompanied by the
- Corresponding Source fixed on a durable physical medium
- customarily used for software interchange.
-
- b) Convey the object code in, or embodied in, a physical product
- (including a physical distribution medium), accompanied by a
- written offer, valid for at least three years and valid for as
- long as you offer spare parts or customer support for that product
- model, to give anyone who possesses the object code either (1) a
- copy of the Corresponding Source for all the software in the
- product that is covered by this License, on a durable physical
- medium customarily used for software interchange, for a price no
- more than your reasonable cost of physically performing this
- conveying of source, or (2) access to copy the
- Corresponding Source from a network server at no charge.
-
- c) Convey individual copies of the object code with a copy of the
- written offer to provide the Corresponding Source. This
- alternative is allowed only occasionally and noncommercially, and
- only if you received the object code with such an offer, in accord
- with subsection 6b.
-
- d) Convey the object code by offering access from a designated
- place (gratis or for a charge), and offer equivalent access to the
- Corresponding Source in the same way through the same place at no
- further charge. You need not require recipients to copy the
- Corresponding Source along with the object code. If the place to
- copy the object code is a network server, the Corresponding Source
- may be on a different server (operated by you or a third party)
- that supports equivalent copying facilities, provided you maintain
- clear directions next to the object code saying where to find the
- Corresponding Source. Regardless of what server hosts the
- Corresponding Source, you remain obligated to ensure that it is
- available for as long as needed to satisfy these requirements.
-
- e) Convey the object code using peer-to-peer transmission, provided
- you inform other peers where the object code and Corresponding
- Source of the work are being offered to the general public at no
- charge under subsection 6d.
-
- A separable portion of the object code, whose source code is excluded
-from the Corresponding Source as a System Library, need not be
-included in conveying the object code work.
-
- A "User Product" is either (1) a "consumer product", which means any
-tangible personal property which is normally used for personal, family,
-or household purposes, or (2) anything designed or sold for incorporation
-into a dwelling. In determining whether a product is a consumer product,
-doubtful cases shall be resolved in favor of coverage. For a particular
-product received by a particular user, "normally used" refers to a
-typical or common use of that class of product, regardless of the status
-of the particular user or of the way in which the particular user
-actually uses, or expects or is expected to use, the product. A product
-is a consumer product regardless of whether the product has substantial
-commercial, industrial or non-consumer uses, unless such uses represent
-the only significant mode of use of the product.
-
- "Installation Information" for a User Product means any methods,
-procedures, authorization keys, or other information required to install
-and execute modified versions of a covered work in that User Product from
-a modified version of its Corresponding Source. The information must
-suffice to ensure that the continued functioning of the modified object
-code is in no case prevented or interfered with solely because
-modification has been made.
-
- If you convey an object code work under this section in, or with, or
-specifically for use in, a User Product, and the conveying occurs as
-part of a transaction in which the right of possession and use of the
-User Product is transferred to the recipient in perpetuity or for a
-fixed term (regardless of how the transaction is characterized), the
-Corresponding Source conveyed under this section must be accompanied
-by the Installation Information. But this requirement does not apply
-if neither you nor any third party retains the ability to install
-modified object code on the User Product (for example, the work has
-been installed in ROM).
-
- The requirement to provide Installation Information does not include a
-requirement to continue to provide support service, warranty, or updates
-for a work that has been modified or installed by the recipient, or for
-the User Product in which it has been modified or installed. Access to a
-network may be denied when the modification itself materially and
-adversely affects the operation of the network or violates the rules and
-protocols for communication across the network.
-
- Corresponding Source conveyed, and Installation Information provided,
-in accord with this section must be in a format that is publicly
-documented (and with an implementation available to the public in
-source code form), and must require no special password or key for
-unpacking, reading or copying.
-
- 7. Additional Terms.
-
- "Additional permissions" are terms that supplement the terms of this
-License by making exceptions from one or more of its conditions.
-Additional permissions that are applicable to the entire Program shall
-be treated as though they were included in this License, to the extent
-that they are valid under applicable law. If additional permissions
-apply only to part of the Program, that part may be used separately
-under those permissions, but the entire Program remains governed by
-this License without regard to the additional permissions.
-
- When you convey a copy of a covered work, you may at your option
-remove any additional permissions from that copy, or from any part of
-it. (Additional permissions may be written to require their own
-removal in certain cases when you modify the work.) You may place
-additional permissions on material, added by you to a covered work,
-for which you have or can give appropriate copyright permission.
-
- Notwithstanding any other provision of this License, for material you
-add to a covered work, you may (if authorized by the copyright holders of
-that material) supplement the terms of this License with terms:
-
- a) Disclaiming warranty or limiting liability differently from the
- terms of sections 15 and 16 of this License; or
-
- b) Requiring preservation of specified reasonable legal notices or
- author attributions in that material or in the Appropriate Legal
- Notices displayed by works containing it; or
-
- c) Prohibiting misrepresentation of the origin of that material, or
- requiring that modified versions of such material be marked in
- reasonable ways as different from the original version; or
-
- d) Limiting the use for publicity purposes of names of licensors or
- authors of the material; or
-
- e) Declining to grant rights under trademark law for use of some
- trade names, trademarks, or service marks; or
-
- f) Requiring indemnification of licensors and authors of that
- material by anyone who conveys the material (or modified versions of
- it) with contractual assumptions of liability to the recipient, for
- any liability that these contractual assumptions directly impose on
- those licensors and authors.
-
- All other non-permissive additional terms are considered "further
-restrictions" within the meaning of section 10. If the Program as you
-received it, or any part of it, contains a notice stating that it is
-governed by this License along with a term that is a further
-restriction, you may remove that term. If a license document contains
-a further restriction but permits relicensing or conveying under this
-License, you may add to a covered work material governed by the terms
-of that license document, provided that the further restriction does
-not survive such relicensing or conveying.
-
- If you add terms to a covered work in accord with this section, you
-must place, in the relevant source files, a statement of the
-additional terms that apply to those files, or a notice indicating
-where to find the applicable terms.
-
- Additional terms, permissive or non-permissive, may be stated in the
-form of a separately written license, or stated as exceptions;
-the above requirements apply either way.
-
- 8. Termination.
-
- You may not propagate or modify a covered work except as expressly
-provided under this License. Any attempt otherwise to propagate or
-modify it is void, and will automatically terminate your rights under
-this License (including any patent licenses granted under the third
-paragraph of section 11).
-
- However, if you cease all violation of this License, then your
-license from a particular copyright holder is reinstated (a)
-provisionally, unless and until the copyright holder explicitly and
-finally terminates your license, and (b) permanently, if the copyright
-holder fails to notify you of the violation by some reasonable means
-prior to 60 days after the cessation.
-
- Moreover, your license from a particular copyright holder is
-reinstated permanently if the copyright holder notifies you of the
-violation by some reasonable means, this is the first time you have
-received notice of violation of this License (for any work) from that
-copyright holder, and you cure the violation prior to 30 days after
-your receipt of the notice.
-
- Termination of your rights under this section does not terminate the
-licenses of parties who have received copies or rights from you under
-this License. If your rights have been terminated and not permanently
-reinstated, you do not qualify to receive new licenses for the same
-material under section 10.
-
- 9. Acceptance Not Required for Having Copies.
-
- You are not required to accept this License in order to receive or
-run a copy of the Program. Ancillary propagation of a covered work
-occurring solely as a consequence of using peer-to-peer transmission
-to receive a copy likewise does not require acceptance. However,
-nothing other than this License grants you permission to propagate or
-modify any covered work. These actions infringe copyright if you do
-not accept this License. Therefore, by modifying or propagating a
-covered work, you indicate your acceptance of this License to do so.
-
- 10. Automatic Licensing of Downstream Recipients.
-
- Each time you convey a covered work, the recipient automatically
-receives a license from the original licensors, to run, modify and
-propagate that work, subject to this License. You are not responsible
-for enforcing compliance by third parties with this License.
-
- An "entity transaction" is a transaction transferring control of an
-organization, or substantially all assets of one, or subdividing an
-organization, or merging organizations. If propagation of a covered
-work results from an entity transaction, each party to that
-transaction who receives a copy of the work also receives whatever
-licenses to the work the party's predecessor in interest had or could
-give under the previous paragraph, plus a right to possession of the
-Corresponding Source of the work from the predecessor in interest, if
-the predecessor has it or can get it with reasonable efforts.
-
- You may not impose any further restrictions on the exercise of the
-rights granted or affirmed under this License. For example, you may
-not impose a license fee, royalty, or other charge for exercise of
-rights granted under this License, and you may not initiate litigation
-(including a cross-claim or counterclaim in a lawsuit) alleging that
-any patent claim is infringed by making, using, selling, offering for
-sale, or importing the Program or any portion of it.
-
- 11. Patents.
-
- A "contributor" is a copyright holder who authorizes use under this
-License of the Program or a work on which the Program is based. The
-work thus licensed is called the contributor's "contributor version".
-
- A contributor's "essential patent claims" are all patent claims
-owned or controlled by the contributor, whether already acquired or
-hereafter acquired, that would be infringed by some manner, permitted
-by this License, of making, using, or selling its contributor version,
-but do not include claims that would be infringed only as a
-consequence of further modification of the contributor version. For
-purposes of this definition, "control" includes the right to grant
-patent sublicenses in a manner consistent with the requirements of
-this License.
-
- Each contributor grants you a non-exclusive, worldwide, royalty-free
-patent license under the contributor's essential patent claims, to
-make, use, sell, offer for sale, import and otherwise run, modify and
-propagate the contents of its contributor version.
-
- In the following three paragraphs, a "patent license" is any express
-agreement or commitment, however denominated, not to enforce a patent
-(such as an express permission to practice a patent or covenant not to
-sue for patent infringement). To "grant" such a patent license to a
-party means to make such an agreement or commitment not to enforce a
-patent against the party.
-
- If you convey a covered work, knowingly relying on a patent license,
-and the Corresponding Source of the work is not available for anyone
-to copy, free of charge and under the terms of this License, through a
-publicly available network server or other readily accessible means,
-then you must either (1) cause the Corresponding Source to be so
-available, or (2) arrange to deprive yourself of the benefit of the
-patent license for this particular work, or (3) arrange, in a manner
-consistent with the requirements of this License, to extend the patent
-license to downstream recipients. "Knowingly relying" means you have
-actual knowledge that, but for the patent license, your conveying the
-covered work in a country, or your recipient's use of the covered work
-in a country, would infringe one or more identifiable patents in that
-country that you have reason to believe are valid.
-
- If, pursuant to or in connection with a single transaction or
-arrangement, you convey, or propagate by procuring conveyance of, a
-covered work, and grant a patent license to some of the parties
-receiving the covered work authorizing them to use, propagate, modify
-or convey a specific copy of the covered work, then the patent license
-you grant is automatically extended to all recipients of the covered
-work and works based on it.
-
- A patent license is "discriminatory" if it does not include within
-the scope of its coverage, prohibits the exercise of, or is
-conditioned on the non-exercise of one or more of the rights that are
-specifically granted under this License. You may not convey a covered
-work if you are a party to an arrangement with a third party that is
-in the business of distributing software, under which you make payment
-to the third party based on the extent of your activity of conveying
-the work, and under which the third party grants, to any of the
-parties who would receive the covered work from you, a discriminatory
-patent license (a) in connection with copies of the covered work
-conveyed by you (or copies made from those copies), or (b) primarily
-for and in connection with specific products or compilations that
-contain the covered work, unless you entered into that arrangement,
-or that patent license was granted, prior to 28 March 2007.
-
- Nothing in this License shall be construed as excluding or limiting
-any implied license or other defenses to infringement that may
-otherwise be available to you under applicable patent law.
-
- 12. No Surrender of Others' Freedom.
-
- If conditions are imposed on you (whether by court order, agreement or
-otherwise) that contradict the conditions of this License, they do not
-excuse you from the conditions of this License. If you cannot convey a
-covered work so as to satisfy simultaneously your obligations under this
-License and any other pertinent obligations, then as a consequence you may
-not convey it at all. For example, if you agree to terms that obligate you
-to collect a royalty for further conveying from those to whom you convey
-the Program, the only way you could satisfy both those terms and this
-License would be to refrain entirely from conveying the Program.
-
- 13. Use with the GNU Affero General Public License.
-
- Notwithstanding any other provision of this License, you have
-permission to link or combine any covered work with a work licensed
-under version 3 of the GNU Affero General Public License into a single
-combined work, and to convey the resulting work. The terms of this
-License will continue to apply to the part which is the covered work,
-but the special requirements of the GNU Affero General Public License,
-section 13, concerning interaction through a network will apply to the
-combination as such.
-
- 14. Revised Versions of this License.
-
- The Free Software Foundation may publish revised and/or new versions of
-the GNU General Public License from time to time. Such new versions will
-be similar in spirit to the present version, but may differ in detail to
-address new problems or concerns.
-
- Each version is given a distinguishing version number. If the
-Program specifies that a certain numbered version of the GNU General
-Public License "or any later version" applies to it, you have the
-option of following the terms and conditions either of that numbered
-version or of any later version published by the Free Software
-Foundation. If the Program does not specify a version number of the
-GNU General Public License, you may choose any version ever published
-by the Free Software Foundation.
-
- If the Program specifies that a proxy can decide which future
-versions of the GNU General Public License can be used, that proxy's
-public statement of acceptance of a version permanently authorizes you
-to choose that version for the Program.
-
- Later license versions may give you additional or different
-permissions. However, no additional obligations are imposed on any
-author or copyright holder as a result of your choosing to follow a
-later version.
-
- 15. Disclaimer of Warranty.
-
- THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
-APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
-HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
-OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
-THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
-IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
-ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
-
- 16. Limitation of Liability.
-
- IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
-WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
-THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
-GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
-USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
-DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
-PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
-EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
-SUCH DAMAGES.
-
- 17. Interpretation of Sections 15 and 16.
-
- If the disclaimer of warranty and limitation of liability provided
-above cannot be given local legal effect according to their terms,
-reviewing courts shall apply local law that most closely approximates
-an absolute waiver of all civil liability in connection with the
-Program, unless a warranty or assumption of liability accompanies a
-copy of the Program in return for a fee.
-
- END OF TERMS AND CONDITIONS
-
- How to Apply These Terms to Your New Programs
-
- If you develop a new program, and you want it to be of the greatest
-possible use to the public, the best way to achieve this is to make it
-free software which everyone can redistribute and change under these terms.
-
- To do so, attach the following notices to the program. It is safest
-to attach them to the start of each source file to most effectively
-state the exclusion of warranty; and each file should have at least
-the "copyright" line and a pointer to where the full notice is found.
-
- <one line to give the program's name and a brief idea of what it does.>
- Copyright (C) <year> <name of author>
-
- 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 <https://www.gnu.org/licenses/>.
-
-Also add information on how to contact you by electronic and paper mail.
-
- If the program does terminal interaction, make it output a short
-notice like this when it starts in an interactive mode:
-
- <program> Copyright (C) <year> <name of author>
- This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
- This is free software, and you are welcome to redistribute it
- under certain conditions; type `show c' for details.
-
-The hypothetical commands `show w' and `show c' should show the appropriate
-parts of the General Public License. Of course, your program's commands
-might be different; for a GUI interface, you would use an "about box".
-
- You should also get your employer (if you work as a programmer) or school,
-if any, to sign a "copyright disclaimer" for the program, if necessary.
-For more information on this, and how to apply and follow the GNU GPL, see
-<https://www.gnu.org/licenses/>.
-
- The GNU General Public License does not permit incorporating your program
-into proprietary programs. If your program is a subroutine library, you
-may consider it more useful to permit linking proprietary applications with
-the library. If this is what you want to do, use the GNU Lesser General
-Public License instead of this License. But first, please read
-<https://www.gnu.org/licenses/why-not-lgpl.html>. \ No newline at end of file
diff --git a/3rd-party/bcm2835.c b/3rd-party/bcm2835.c
deleted file mode 100644
index 14064ee..0000000
--- a/3rd-party/bcm2835.c
+++ /dev/null
@@ -1,2029 +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.28 2020/01/11 05:07:13 mikem Exp mikem $
-*/
-#include <stdlib.h>
-#include <stdio.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <sys/mman.h>
-#include <string.h>
-#include <time.h>
-#include <unistd.h>
-#include <sys/types.h>
-
-#define BCK2835_LIBRARY_BUILD
-#include "bcm2835.h"
-
-/* This define enables a little test program (by default a blinking output on pin RPI_GPIO_PIN_11)
-// You can do some safe, non-destructive testing on any platform with:
-// gcc bcm2835.c -D BCM2835_TEST
-// ./a.out
-*/
-/*#define BCM2835_TEST*/
-
-/* Uncommenting this define compiles alternative I2C code for the version 1 RPi
-// The P1 header I2C pins are connected to SDA0 and SCL0 on V1.
-// By default I2C code is generated for the V2 RPi which has SDA1 and SCL1 connected.
-*/
-/* #define I2C_V1*/
-
-/* Physical address and size of the peripherals block
-// May be overridden on RPi2
-*/
-off_t bcm2835_peripherals_base = BCM2835_PERI_BASE;
-size_t bcm2835_peripherals_size = BCM2835_PERI_SIZE;
-
-/* Virtual memory address of the mapped peripherals block
- */
-uint32_t *bcm2835_peripherals = (uint32_t *)MAP_FAILED;
-
-/* And the register bases within the peripherals block
- */
-volatile uint32_t *bcm2835_gpio = (uint32_t *)MAP_FAILED;
-volatile uint32_t *bcm2835_pwm = (uint32_t *)MAP_FAILED;
-volatile uint32_t *bcm2835_clk = (uint32_t *)MAP_FAILED;
-volatile uint32_t *bcm2835_pads = (uint32_t *)MAP_FAILED;
-volatile uint32_t *bcm2835_spi0 = (uint32_t *)MAP_FAILED;
-volatile uint32_t *bcm2835_bsc0 = (uint32_t *)MAP_FAILED;
-volatile uint32_t *bcm2835_bsc1 = (uint32_t *)MAP_FAILED;
-volatile uint32_t *bcm2835_st = (uint32_t *)MAP_FAILED;
-volatile uint32_t *bcm2835_aux = (uint32_t *)MAP_FAILED;
-volatile uint32_t *bcm2835_spi1 = (uint32_t *)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;
-
-/* RPI 4 has different pullup registers - we need to know if we have that type */
-
-static uint8_t pud_type_rpi4 = 0;
-
-/* RPI 4 has different pullup operation - make backwards compat */
-
-static uint8_t pud_compat_setting = BCM2835_GPIO_PUD_OFF;
-
-/* I2C The time needed to transmit one byte. In microseconds.
- */
-static int i2c_byte_wait_us = 0;
-
-/* SPI bit order. BCM2835 SPI0 only supports MSBFIRST, so we instead
- * have a software based bit reversal, based on a contribution by Damiano Benedetti
- */
-static uint8_t bcm2835_spi_bit_order = BCM2835_SPI_BIT_ORDER_MSBFIRST;
-static uint8_t bcm2835_byte_reverse_table[] =
-{
- 0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0,
- 0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0,
- 0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8,
- 0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8,
- 0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4,
- 0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4,
- 0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec,
- 0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc,
- 0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2,
- 0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2,
- 0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea,
- 0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa,
- 0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6,
- 0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6,
- 0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee,
- 0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe,
- 0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1,
- 0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1,
- 0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9,
- 0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9,
- 0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5,
- 0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5,
- 0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed,
- 0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd,
- 0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3,
- 0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3,
- 0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb,
- 0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb,
- 0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7,
- 0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7,
- 0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef,
- 0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff
-};
-
-static uint8_t bcm2835_correct_order(uint8_t b)
-{
- if (bcm2835_spi_bit_order == BCM2835_SPI_BIT_ORDER_LSBFIRST)
- return bcm2835_byte_reverse_table[b];
- else
- return b;
-}
-
-#ifdef BCM2835_HAVE_LIBCAP
-#include <sys/capability.h>
-static int bcm2835_has_capability(cap_value_t capability)
-{
- int ok = 0;
- cap_t cap = cap_get_proc();
- if (cap)
- {
- cap_flag_value_t value;
- if (cap_get_flag(cap,capability,CAP_EFFECTIVE,&value) == 0 && value == CAP_SET)
- ok = 1;
- cap_free(cap);
- }
- return ok;
-}
-#endif
-
-/*
-// Low level register access functions
-*/
-
-/* Function to return the pointers to the hardware register bases */
-uint32_t* bcm2835_regbase(uint8_t regbase)
-{
- switch (regbase)
- {
- case BCM2835_REGBASE_ST:
- return (uint32_t *)bcm2835_st;
- case BCM2835_REGBASE_GPIO:
- return (uint32_t *)bcm2835_gpio;
- case BCM2835_REGBASE_PWM:
- return (uint32_t *)bcm2835_pwm;
- case BCM2835_REGBASE_CLK:
- return (uint32_t *)bcm2835_clk;
- case BCM2835_REGBASE_PADS:
- return (uint32_t *)bcm2835_pads;
- case BCM2835_REGBASE_SPI0:
- return (uint32_t *)bcm2835_spi0;
- case BCM2835_REGBASE_BSC0:
- return (uint32_t *)bcm2835_bsc0;
- case BCM2835_REGBASE_BSC1:
- return (uint32_t *)bcm2835_st;
- case BCM2835_REGBASE_AUX:
- return (uint32_t *)bcm2835_aux;
- case BCM2835_REGBASE_SPI1:
- return (uint32_t *)bcm2835_spi1;
-
- }
- return (uint32_t *)MAP_FAILED;
-}
-
-void bcm2835_set_debug(uint8_t d)
-{
- debug = d;
-}
-
-unsigned int bcm2835_version(void)
-{
- return BCM2835_VERSION;
-}
-
-/* Read with memory barriers from peripheral
- *
- */
-uint32_t bcm2835_peri_read(volatile uint32_t* paddr)
-{
- uint32_t ret;
- if (debug)
- {
- printf("bcm2835_peri_read paddr %p\n", (void *) paddr);
- return 0;
- }
- else
- {
- __sync_synchronize();
- ret = *paddr;
- __sync_synchronize();
- return ret;
- }
-}
-
-/* read from peripheral without the read barrier
- * This can only be used if more reads to THE SAME peripheral
- * will follow. The sequence must terminate with memory barrier
- * before any read or write to another peripheral can occur.
- * The MB can be explicit, or one of the barrier read/write calls.
- */
-uint32_t bcm2835_peri_read_nb(volatile uint32_t* paddr)
-{
- if (debug)
- {
- printf("bcm2835_peri_read_nb paddr %p\n", paddr);
- return 0;
- }
- else
- {
- return *paddr;
- }
-}
-
-/* Write with memory barriers to peripheral
- */
-
-void bcm2835_peri_write(volatile uint32_t* paddr, uint32_t value)
-{
- if (debug)
- {
- printf("bcm2835_peri_write paddr %p, value %08X\n", paddr, value);
- }
- else
- {
- __sync_synchronize();
- *paddr = value;
- __sync_synchronize();
- }
-}
-
-/* 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 %p, value %08X\n",
- paddr, value);
- }
- else
- {
- *paddr = value;
- }
-}
-
-/* Set/clear only the bits in value covered by the mask
- * This is not atomic - can be interrupted.
- */
-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;
-}
-
-uint32_t bcm2835_gpio_eds_multi(uint32_t mask)
-{
- volatile uint32_t* paddr = bcm2835_gpio + BCM2835_GPEDS0/4;
- uint32_t value = bcm2835_peri_read(paddr);
- return (value & mask);
-}
-
-/* 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);
-}
-
-void bcm2835_gpio_set_eds_multi(uint32_t mask)
-{
- volatile uint32_t* paddr = bcm2835_gpio + BCM2835_GPEDS0/4;
- bcm2835_peri_write(paddr, mask);
-}
-
-/* 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)
-{
- if( pud_type_rpi4 )
- {
- pud_compat_setting = pud;
- }
- else {
- 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)
-{
- if( pud_type_rpi4 )
- {
- if( on )
- bcm2835_gpio_set_pud( pin, pud_compat_setting);
- }
- else
- {
- 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)
-{
- if (bcm2835_pads == MAP_FAILED)
- return 0;
-
- volatile uint32_t* paddr = bcm2835_pads + BCM2835_PADS_GPIO_0_27/4 + group;
- return bcm2835_peri_read(paddr);
-}
-
-/* Set GPIO pad behaviour for groups of GPIOs
-// powerup value for all 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)
-{
- if (bcm2835_pads == MAP_FAILED)
- return;
-
- volatile uint32_t* paddr = bcm2835_pads + BCM2835_PADS_GPIO_0_27/4 + group;
- bcm2835_peri_write(paddr, control | BCM2835_PAD_PASSWRD);
-}
-
-/* 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;
-
- if (debug)
- {
- /* Cant access sytem timers in debug mode */
- printf("bcm2835_delayMicroseconds %lld\n", (long long int) micros);
- return;
- }
-
- /* 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();
-
- /* Not allowed to access timer registers (result is not as precise)*/
- if (start==0)
- {
- t1.tv_sec = 0;
- t1.tv_nsec = 1000 * (long)(micros);
- nanosleep(&t1, NULL);
- return;
- }
-
- 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
-//
-// RPI 4 uses a different PUD method - no clock
-
-*/
-void bcm2835_gpio_set_pud(uint8_t pin, uint8_t pud)
-{
- if( pud_type_rpi4 )
- {
- int shiftbits = (pin & 0xf) << 1;
- uint32_t bits;
- uint32_t pull;
-
- switch (pud)
- {
- case BCM2835_GPIO_PUD_OFF: pull = 0; break;
- case BCM2835_GPIO_PUD_UP: pull = 1; break;
- case BCM2835_GPIO_PUD_DOWN: pull = 2; break;
- default: return;
- }
-
- volatile uint32_t* paddr = bcm2835_gpio + BCM2835_GPPUPPDN0/4 + (pin >> 4);
-
- bits = bcm2835_peri_read_nb( paddr );
- bits &= ~(3 << shiftbits);
- bits |= (pull << shiftbits);
-
- bcm2835_peri_write_nb( paddr, bits );
-
- } else
- {
- 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);
-}
-
-}
-
-
-uint8_t bcm2835_gpio_get_pud(uint8_t pin)
-{
- uint8_t ret = BCM2835_GPIO_PUD_ERROR;
-
- if( pud_type_rpi4 )
- {
- uint32_t bits;
- volatile uint32_t* paddr = bcm2835_gpio + BCM2835_GPPUPPDN0/4 + (pin >> 4);
- bits = (bcm2835_peri_read_nb( paddr ) >> ((pin & 0xf)<<1)) & 0x3;
-
- switch (bits)
- {
- case 0: ret = BCM2835_GPIO_PUD_OFF; break;
- case 1: ret = BCM2835_GPIO_PUD_UP; break;
- case 2: ret = BCM2835_GPIO_PUD_DOWN; break;
- default: ret = BCM2835_GPIO_PUD_ERROR;
- }
- }
-
- return ret;
-}
-
-static void bcm2835_aux_spi_reset(void)
- {
- volatile uint32_t* cntl0 = bcm2835_spi1 + BCM2835_AUX_SPI_CNTL0/4;
- volatile uint32_t* cntl1 = bcm2835_spi1 + BCM2835_AUX_SPI_CNTL1/4;
-
- bcm2835_peri_write(cntl1, 0);
- bcm2835_peri_write(cntl0, BCM2835_AUX_SPI_CNTL0_CLEARFIFO);
-}
-
-int bcm2835_spi_begin(void)
-{
- volatile uint32_t* paddr;
-
- if (bcm2835_spi0 == MAP_FAILED)
- return 0; /* bcm2835_init() failed, or not root */
-
- /* 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 */
- 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);
-
- return 1; // OK
-}
-
-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 = order;
-}
-
-/* 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_set_speed_hz(uint32_t speed_hz)
-{
- uint16_t divider = (uint16_t) ((uint32_t) BCM2835_CORE_CLK_HZ / speed_hz);
- divider &= 0xFFFE;
- bcm2835_spi_setClockDivider(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;
- uint32_t ret;
-
- /* 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))
- ;
-
- /* Write to FIFO, no barrier */
- bcm2835_peri_write_nb(fifo, bcm2835_correct_order(value));
-
- /* Wait for DONE to be set */
- while (!(bcm2835_peri_read_nb(paddr) & BCM2835_SPI0_CS_DONE))
- ;
-
- /* Read any byte that was sent back by the slave while we sere sending to it */
- ret = bcm2835_correct_order(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;
- uint32_t TXCnt=0;
- uint32_t RXCnt=0;
-
- /* 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);
-
- /* Use the FIFO's to reduce the interbyte times */
- while((TXCnt < len)||(RXCnt < len))
- {
- /* TX fifo not full, so add some more bytes */
- while(((bcm2835_peri_read(paddr) & BCM2835_SPI0_CS_TXD))&&(TXCnt < len ))
- {
- bcm2835_peri_write_nb(fifo, bcm2835_correct_order(tbuf[TXCnt]));
- TXCnt++;
- }
- /* Rx fifo not empty, so get the next received bytes */
- while(((bcm2835_peri_read(paddr) & BCM2835_SPI0_CS_RXD))&&( RXCnt < len ))
- {
- rbuf[RXCnt] = bcm2835_correct_order(bcm2835_peri_read_nb(fifo));
- RXCnt++;
- }
- }
- /* 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 an number of bytes to SPI */
-void bcm2835_spi_writenb(const 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;
- uint32_t i;
-
- /* 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?
- // Answer: an ISR is required to issue the required memory barriers.
- */
-
- /* 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);
-
- 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, bcm2835_correct_order(tbuf[i]));
-
- /* Read from FIFO to prevent stalling */
- while (bcm2835_peri_read(paddr) & BCM2835_SPI0_CS_RXD)
- (void) bcm2835_peri_read_nb(fifo);
- }
-
- /* Wait for DONE to be set */
- while (!(bcm2835_peri_read_nb(paddr) & BCM2835_SPI0_CS_DONE)) {
- while (bcm2835_peri_read(paddr) & BCM2835_SPI0_CS_RXD)
- (void) bcm2835_peri_read_nb(fifo);
- };
-
- /* 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_spi_write(uint16_t data)
-{
-#if 0
- char buf[2];
-
- buf[0] = data >> 8;
- buf[1] = data & 0xFF;
-
- bcm2835_spi_transfern(buf, 2);
-#else
- volatile uint32_t* paddr = bcm2835_spi0 + BCM2835_SPI0_CS/4;
- volatile uint32_t* fifo = bcm2835_spi0 + BCM2835_SPI0_FIFO/4;
-
- /* 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))
- ;
-
- /* Write to FIFO */
- bcm2835_peri_write_nb(fifo, (uint32_t) data >> 8);
- bcm2835_peri_write_nb(fifo, data & 0xFF);
-
-
- /* 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);
-#endif
-}
-
-int bcm2835_aux_spi_begin(void)
-{
- volatile uint32_t* enable = bcm2835_aux + BCM2835_AUX_ENABLE/4;
- volatile uint32_t* cntl0 = bcm2835_spi1 + BCM2835_AUX_SPI_CNTL0/4;
- volatile uint32_t* cntl1 = bcm2835_spi1 + BCM2835_AUX_SPI_CNTL1/4;
-
- if (bcm2835_spi1 == MAP_FAILED)
- return 0; /* bcm2835_init() failed, or not root */
-
- /* Set the SPI pins to the Alt 4 function to enable SPI1 access on them */
- bcm2835_gpio_fsel(RPI_V2_GPIO_P1_36, BCM2835_GPIO_FSEL_ALT4); /* SPI1_CE2_N */
- bcm2835_gpio_fsel(RPI_V2_GPIO_P1_35, BCM2835_GPIO_FSEL_ALT4); /* SPI1_MISO */
- bcm2835_gpio_fsel(RPI_V2_GPIO_P1_38, BCM2835_GPIO_FSEL_ALT4); /* SPI1_MOSI */
- bcm2835_gpio_fsel(RPI_V2_GPIO_P1_40, BCM2835_GPIO_FSEL_ALT4); /* SPI1_SCLK */
-
- bcm2835_aux_spi_setClockDivider(bcm2835_aux_spi_CalcClockDivider(1000000)); // Default 1MHz SPI
-
- bcm2835_peri_write(enable, BCM2835_AUX_ENABLE_SPI0);
- bcm2835_peri_write(cntl1, 0);
- bcm2835_peri_write(cntl0, BCM2835_AUX_SPI_CNTL0_CLEARFIFO);
-
- return 1; /* OK */
-}
-
-void bcm2835_aux_spi_end(void)
-{
- /* Set all the SPI1 pins back to input */
- bcm2835_gpio_fsel(RPI_V2_GPIO_P1_36, BCM2835_GPIO_FSEL_INPT); /* SPI1_CE2_N */
- bcm2835_gpio_fsel(RPI_V2_GPIO_P1_35, BCM2835_GPIO_FSEL_INPT); /* SPI1_MISO */
- bcm2835_gpio_fsel(RPI_V2_GPIO_P1_38, BCM2835_GPIO_FSEL_INPT); /* SPI1_MOSI */
- bcm2835_gpio_fsel(RPI_V2_GPIO_P1_40, BCM2835_GPIO_FSEL_INPT); /* SPI1_SCLK */
-}
-
-#define DIV_ROUND_UP(n,d) (((n) + (d) - 1) / (d))
-
-uint16_t bcm2835_aux_spi_CalcClockDivider(uint32_t speed_hz)
-{
- uint16_t divider;
-
- if (speed_hz < (uint32_t) BCM2835_AUX_SPI_CLOCK_MIN) {
- speed_hz = (uint32_t) BCM2835_AUX_SPI_CLOCK_MIN;
- } else if (speed_hz > (uint32_t) BCM2835_AUX_SPI_CLOCK_MAX) {
- speed_hz = (uint32_t) BCM2835_AUX_SPI_CLOCK_MAX;
- }
-
- divider = (uint16_t) DIV_ROUND_UP(BCM2835_CORE_CLK_HZ, 2 * speed_hz) - 1;
-
- if (divider > (uint16_t) BCM2835_AUX_SPI_CNTL0_SPEED_MAX) {
- return (uint16_t) BCM2835_AUX_SPI_CNTL0_SPEED_MAX;
- }
-
- return divider;
-}
-
-static uint32_t spi1_speed;
-
-void bcm2835_aux_spi_setClockDivider(uint16_t divider)
-{
- spi1_speed = (uint32_t) divider;
-}
-
-void bcm2835_aux_spi_write(uint16_t data)
-{
- volatile uint32_t* cntl0 = bcm2835_spi1 + BCM2835_AUX_SPI_CNTL0/4;
- volatile uint32_t* cntl1 = bcm2835_spi1 + BCM2835_AUX_SPI_CNTL1/4;
- volatile uint32_t* stat = bcm2835_spi1 + BCM2835_AUX_SPI_STAT/4;
- volatile uint32_t* io = bcm2835_spi1 + BCM2835_AUX_SPI_IO/4;
-
- uint32_t _cntl0 = (spi1_speed << BCM2835_AUX_SPI_CNTL0_SPEED_SHIFT);
- _cntl0 |= BCM2835_AUX_SPI_CNTL0_CS2_N;
- _cntl0 |= BCM2835_AUX_SPI_CNTL0_ENABLE;
- _cntl0 |= BCM2835_AUX_SPI_CNTL0_MSBF_OUT;
- _cntl0 |= 16; // Shift length
-
- bcm2835_peri_write(cntl0, _cntl0);
- bcm2835_peri_write(cntl1, BCM2835_AUX_SPI_CNTL1_MSBF_IN);
-
- while (bcm2835_peri_read(stat) & BCM2835_AUX_SPI_STAT_TX_FULL)
- ;
-
- bcm2835_peri_write(io, (uint32_t) data << 16);
-}
-
-void bcm2835_aux_spi_writenb(const char *tbuf, uint32_t len) {
- volatile uint32_t* cntl0 = bcm2835_spi1 + BCM2835_AUX_SPI_CNTL0/4;
- volatile uint32_t* cntl1 = bcm2835_spi1 + BCM2835_AUX_SPI_CNTL1/4;
- volatile uint32_t* stat = bcm2835_spi1 + BCM2835_AUX_SPI_STAT/4;
- volatile uint32_t* txhold = bcm2835_spi1 + BCM2835_AUX_SPI_TXHOLD/4;
- volatile uint32_t* io = bcm2835_spi1 + BCM2835_AUX_SPI_IO/4;
-
- char *tx = (char *) tbuf;
- uint32_t tx_len = len;
- uint32_t count;
- uint32_t data;
- uint32_t i;
- uint8_t byte;
-
- uint32_t _cntl0 = (spi1_speed << BCM2835_AUX_SPI_CNTL0_SPEED_SHIFT);
- _cntl0 |= BCM2835_AUX_SPI_CNTL0_CS2_N;
- _cntl0 |= BCM2835_AUX_SPI_CNTL0_ENABLE;
- _cntl0 |= BCM2835_AUX_SPI_CNTL0_MSBF_OUT;
- _cntl0 |= BCM2835_AUX_SPI_CNTL0_VAR_WIDTH;
-
- bcm2835_peri_write(cntl0, _cntl0);
- bcm2835_peri_write(cntl1, BCM2835_AUX_SPI_CNTL1_MSBF_IN);
-
- while (tx_len > 0) {
-
- while (bcm2835_peri_read(stat) & BCM2835_AUX_SPI_STAT_TX_FULL)
- ;
-
- count = MIN(tx_len, 3);
- data = 0;
-
- for (i = 0; i < count; i++) {
- byte = (tx != NULL) ? (uint8_t) *tx++ : (uint8_t) 0;
- data |= byte << (8 * (2 - i));
- }
-
- data |= (count * 8) << 24;
- tx_len -= count;
-
- if (tx_len != 0) {
- bcm2835_peri_write(txhold, data);
- } else {
- bcm2835_peri_write(io, data);
- }
-
- while (bcm2835_peri_read(stat) & BCM2835_AUX_SPI_STAT_BUSY)
- ;
-
- (void) bcm2835_peri_read(io);
- }
-}
-
-void bcm2835_aux_spi_transfernb(const char *tbuf, char *rbuf, uint32_t len) {
- volatile uint32_t* cntl0 = bcm2835_spi1 + BCM2835_AUX_SPI_CNTL0/4;
- volatile uint32_t* cntl1 = bcm2835_spi1 + BCM2835_AUX_SPI_CNTL1/4;
- volatile uint32_t* stat = bcm2835_spi1 + BCM2835_AUX_SPI_STAT/4;
- volatile uint32_t* txhold = bcm2835_spi1 + BCM2835_AUX_SPI_TXHOLD/4;
- volatile uint32_t* io = bcm2835_spi1 + BCM2835_AUX_SPI_IO/4;
-
- char *tx = (char *)tbuf;
- char *rx = (char *)rbuf;
- uint32_t tx_len = len;
- uint32_t rx_len = len;
- uint32_t count;
- uint32_t data;
- uint32_t i;
- uint8_t byte;
-
- uint32_t _cntl0 = (spi1_speed << BCM2835_AUX_SPI_CNTL0_SPEED_SHIFT);
- _cntl0 |= BCM2835_AUX_SPI_CNTL0_CS2_N;
- _cntl0 |= BCM2835_AUX_SPI_CNTL0_ENABLE;
- _cntl0 |= BCM2835_AUX_SPI_CNTL0_MSBF_OUT;
- _cntl0 |= BCM2835_AUX_SPI_CNTL0_VAR_WIDTH;
-
- bcm2835_peri_write(cntl0, _cntl0);
- bcm2835_peri_write(cntl1, BCM2835_AUX_SPI_CNTL1_MSBF_IN);
-
- while ((tx_len > 0) || (rx_len > 0)) {
-
- while (!(bcm2835_peri_read(stat) & BCM2835_AUX_SPI_STAT_TX_FULL) && (tx_len > 0)) {
- count = MIN(tx_len, 3);
- data = 0;
-
- for (i = 0; i < count; i++) {
- byte = (tx != NULL) ? (uint8_t) *tx++ : (uint8_t) 0;
- data |= byte << (8 * (2 - i));
- }
-
- data |= (count * 8) << 24;
- tx_len -= count;
-
- if (tx_len != 0) {
- bcm2835_peri_write(txhold, data);
- } else {
- bcm2835_peri_write(io, data);
- }
-
- }
-
- while (!(bcm2835_peri_read(stat) & BCM2835_AUX_SPI_STAT_RX_EMPTY) && (rx_len > 0)) {
- count = MIN(rx_len, 3);
- data = bcm2835_peri_read(io);
-
- if (rbuf != NULL) {
- switch (count) {
- case 3:
- *rx++ = (char)((data >> 16) & 0xFF);
- /*@fallthrough@*/
- /* no break */
- case 2:
- *rx++ = (char)((data >> 8) & 0xFF);
- /*@fallthrough@*/
- /* no break */
- case 1:
- *rx++ = (char)((data >> 0) & 0xFF);
- }
- }
-
- rx_len -= count;
- }
-
- while (!(bcm2835_peri_read(stat) & BCM2835_AUX_SPI_STAT_BUSY) && (rx_len > 0)) {
- count = MIN(rx_len, 3);
- data = bcm2835_peri_read(io);
-
- if (rbuf != NULL) {
- switch (count) {
- case 3:
- *rx++ = (char)((data >> 16) & 0xFF);
- /*@fallthrough@*/
- /* no break */
- case 2:
- *rx++ = (char)((data >> 8) & 0xFF);
- /*@fallthrough@*/
- /* no break */
- case 1:
- *rx++ = (char)((data >> 0) & 0xFF);
- }
- }
-
- rx_len -= count;
- }
- }
-}
-
-void bcm2835_aux_spi_transfern(char *buf, uint32_t len) {
- bcm2835_aux_spi_transfernb(buf, buf, len);
-}
-
-/* Writes (and reads) a single byte to AUX SPI */
-uint8_t bcm2835_aux_spi_transfer(uint8_t value)
-{
- volatile uint32_t* cntl0 = bcm2835_spi1 + BCM2835_AUX_SPI_CNTL0/4;
- volatile uint32_t* cntl1 = bcm2835_spi1 + BCM2835_AUX_SPI_CNTL1/4;
- volatile uint32_t* stat = bcm2835_spi1 + BCM2835_AUX_SPI_STAT/4;
- volatile uint32_t* io = bcm2835_spi1 + BCM2835_AUX_SPI_IO/4;
-
- uint32_t data;
-
- uint32_t _cntl0 = (spi1_speed << BCM2835_AUX_SPI_CNTL0_SPEED_SHIFT);
- _cntl0 |= BCM2835_AUX_SPI_CNTL0_CS2_N;
- _cntl0 |= BCM2835_AUX_SPI_CNTL0_ENABLE;
- _cntl0 |= BCM2835_AUX_SPI_CNTL0_MSBF_OUT;
- _cntl0 |= BCM2835_AUX_SPI_CNTL0_CPHA_IN;
- _cntl0 |= 8; // Shift length.
-
- uint32_t _cntl1 = BCM2835_AUX_SPI_CNTL1_MSBF_IN;
-
- bcm2835_peri_write(cntl1, _cntl1);
- bcm2835_peri_write(cntl0, _cntl0);
-
- bcm2835_peri_write(io, (uint32_t) bcm2835_correct_order(value) << 24);
-
- while (bcm2835_peri_read(stat) & BCM2835_AUX_SPI_STAT_BUSY)
- ;
-
- data = bcm2835_correct_order(bcm2835_peri_read(io) & 0xff);
-
- bcm2835_aux_spi_reset();
-
- return data;
-}
-
-
-int bcm2835_i2c_begin(void)
-{
- uint16_t cdiv;
-
- if ( bcm2835_bsc0 == MAP_FAILED
- || bcm2835_bsc1 == MAP_FAILED)
- return 0; /* bcm2835_init() failed, or not root */
-
-#ifdef I2C_V1
- volatile uint32_t* paddr = bcm2835_bsc0 + BCM2835_BSC_DIV/4;
- /* Set the I2C/BSC0 pins to the Alt 0 function to enable I2C access on them */
- bcm2835_gpio_fsel(RPI_GPIO_P1_03, BCM2835_GPIO_FSEL_ALT0); /* SDA */
- bcm2835_gpio_fsel(RPI_GPIO_P1_05, BCM2835_GPIO_FSEL_ALT0); /* SCL */
-#else
- 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 */
-#endif
-
- /* Read the clock divider register */
- 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;
-
- return 1;
-}
-
-void bcm2835_i2c_end(void)
-{
-#ifdef I2C_V1
- /* Set all the I2C/BSC0 pins back to input */
- bcm2835_gpio_fsel(RPI_GPIO_P1_03, BCM2835_GPIO_FSEL_INPT); /* SDA */
- bcm2835_gpio_fsel(RPI_GPIO_P1_05, BCM2835_GPIO_FSEL_INPT); /* SCL */
-#else
- /* 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 */
-#endif
-}
-
-void bcm2835_i2c_setSlaveAddress(uint8_t addr)
-{
- /* Set I2C Device Address */
-#ifdef I2C_V1
- volatile uint32_t* paddr = bcm2835_bsc0 + BCM2835_BSC_A/4;
-#else
- volatile uint32_t* paddr = bcm2835_bsc1 + BCM2835_BSC_A/4;
-#endif
- 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)
-{
-#ifdef I2C_V1
- volatile uint32_t* paddr = bcm2835_bsc0 + BCM2835_BSC_DIV/4;
-#else
- volatile uint32_t* paddr = bcm2835_bsc1 + BCM2835_BSC_DIV/4;
-#endif
- 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)
-{
-#ifdef I2C_V1
- volatile uint32_t* dlen = bcm2835_bsc0 + BCM2835_BSC_DLEN/4;
- volatile uint32_t* fifo = bcm2835_bsc0 + BCM2835_BSC_FIFO/4;
- volatile uint32_t* status = bcm2835_bsc0 + BCM2835_BSC_S/4;
- volatile uint32_t* control = bcm2835_bsc0 + BCM2835_BSC_C/4;
-#else
- 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;
-#endif
-
- uint32_t remaining = len;
- uint32_t i = 0;
- uint8_t reason = BCM2835_I2C_REASON_OK;
-
- /* Clear FIFO */
- bcm2835_peri_set_bits(control, BCM2835_BSC_C_CLEAR_1 , BCM2835_BSC_C_CLEAR_1 );
- /* Clear Status */
- bcm2835_peri_write(status, BCM2835_BSC_S_CLKT | BCM2835_BSC_S_ERR | BCM2835_BSC_S_DONE);
- /* Set Data Length */
- bcm2835_peri_write(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(control, BCM2835_BSC_C_I2CEN | BCM2835_BSC_C_ST);
-
- /* Transfer is over when BCM2835_BSC_S_DONE */
- while(!(bcm2835_peri_read(status) & BCM2835_BSC_S_DONE ))
- {
- while ( remaining && (bcm2835_peri_read(status) & BCM2835_BSC_S_TXD ))
- {
- /* Write to FIFO */
- bcm2835_peri_write(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)
-{
-#ifdef I2C_V1
- volatile uint32_t* dlen = bcm2835_bsc0 + BCM2835_BSC_DLEN/4;
- volatile uint32_t* fifo = bcm2835_bsc0 + BCM2835_BSC_FIFO/4;
- volatile uint32_t* status = bcm2835_bsc0 + BCM2835_BSC_S/4;
- volatile uint32_t* control = bcm2835_bsc0 + BCM2835_BSC_C/4;
-#else
- 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;
-#endif
-
- uint32_t remaining = len;
- uint32_t i = 0;
- uint8_t reason = BCM2835_I2C_REASON_OK;
-
- /* Clear FIFO */
- bcm2835_peri_set_bits(control, BCM2835_BSC_C_CLEAR_1 , BCM2835_BSC_C_CLEAR_1 );
- /* Clear Status */
- 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 (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 received */
- else if (remaining)
- {
- reason = BCM2835_I2C_REASON_ERROR_DATA;
- }
-
- bcm2835_peri_set_bits(status, 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)
-{
-#ifdef I2C_V1
- volatile uint32_t* dlen = bcm2835_bsc0 + BCM2835_BSC_DLEN/4;
- volatile uint32_t* fifo = bcm2835_bsc0 + BCM2835_BSC_FIFO/4;
- volatile uint32_t* status = bcm2835_bsc0 + BCM2835_BSC_S/4;
- volatile uint32_t* control = bcm2835_bsc0 + BCM2835_BSC_C/4;
-#else
- 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;
-#endif
- uint32_t remaining = len;
- uint32_t i = 0;
- uint8_t reason = BCM2835_I2C_REASON_OK;
-
- /* Clear FIFO */
- bcm2835_peri_set_bits(control, BCM2835_BSC_C_CLEAR_1 , BCM2835_BSC_C_CLEAR_1 );
- /* Clear Status */
- bcm2835_peri_write(status, BCM2835_BSC_S_CLKT | BCM2835_BSC_S_ERR | BCM2835_BSC_S_DONE);
- /* Set Data Length */
- bcm2835_peri_write(dlen, 1);
- /* Enable device and start transfer */
- bcm2835_peri_write(control, BCM2835_BSC_C_I2CEN);
- bcm2835_peri_write(fifo, regaddr[0]);
- bcm2835_peri_write(control, BCM2835_BSC_C_I2CEN | BCM2835_BSC_C_ST);
-
- /* poll for transfer has started */
- while ( !( bcm2835_peri_read(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(dlen, len);
- bcm2835_peri_write(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(status) & BCM2835_BSC_S_DONE))
- {
- /* we must empty the FIFO as it is populated and not use any delay */
- while (remaining && bcm2835_peri_read(status) & BCM2835_BSC_S_RXD)
- {
- /* Read from FIFO */
- buf[i] = bcm2835_peri_read(fifo);
- i++;
- remaining--;
- }
- }
-
- /* transfer has finished - grab any remaining stuff in FIFO */
- while (remaining && (bcm2835_peri_read(status) & BCM2835_BSC_S_RXD))
- {
- /* Read from FIFO */
- buf[i] = bcm2835_peri_read(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;
-}
-
-/* Sending an arbitrary number of bytes before issuing a repeated start
-// (with no prior stop) and reading a response. Some devices require this behavior.
-*/
-uint8_t bcm2835_i2c_write_read_rs(char* cmds, uint32_t cmds_len, char* buf, uint32_t buf_len)
-{
-#ifdef I2C_V1
- volatile uint32_t* dlen = bcm2835_bsc0 + BCM2835_BSC_DLEN/4;
- volatile uint32_t* fifo = bcm2835_bsc0 + BCM2835_BSC_FIFO/4;
- volatile uint32_t* status = bcm2835_bsc0 + BCM2835_BSC_S/4;
- volatile uint32_t* control = bcm2835_bsc0 + BCM2835_BSC_C/4;
-#else
- 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;
-#endif
-
- uint32_t remaining = cmds_len;
- uint32_t i = 0;
- uint8_t reason = BCM2835_I2C_REASON_OK;
-
- /* Clear FIFO */
- bcm2835_peri_set_bits(control, BCM2835_BSC_C_CLEAR_1 , BCM2835_BSC_C_CLEAR_1 );
-
- /* Clear Status */
- bcm2835_peri_write(status, BCM2835_BSC_S_CLKT | BCM2835_BSC_S_ERR | BCM2835_BSC_S_DONE);
-
- /* Set Data Length */
- bcm2835_peri_write(dlen, cmds_len);
-
- /* pre populate FIFO with max buffer */
- while( remaining && ( i < BCM2835_BSC_FIFO_SIZE ) )
- {
- bcm2835_peri_write_nb(fifo, cmds[i]);
- i++;
- remaining--;
- }
-
- /* Enable device and start transfer */
- bcm2835_peri_write(control, BCM2835_BSC_C_I2CEN | BCM2835_BSC_C_ST);
-
- /* poll for transfer has started (way to do repeated start, from BCM2835 datasheet) */
- while ( !( bcm2835_peri_read(status) & BCM2835_BSC_S_TA ) )
- {
- /* Linux may cause us to miss entire transfer stage */
- if(bcm2835_peri_read_nb(status) & BCM2835_BSC_S_DONE)
- break;
- }
-
- remaining = buf_len;
- i = 0;
-
- /* Send a repeated start with read bit set in address */
- bcm2835_peri_write(dlen, buf_len);
- bcm2835_peri_write(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 * (cmds_len + 1));
-
- /* 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(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(status) & BCM2835_BSC_S_RXD))
- {
- /* Read from FIFO */
- buf[i] = bcm2835_peri_read(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;
- uint32_t hi, lo;
- uint64_t st;
-
- if (bcm2835_st==MAP_FAILED)
- return 0;
-
- paddr = bcm2835_st + BCM2835_ST_CHI/4;
- hi = bcm2835_peri_read(paddr);
-
- paddr = bcm2835_st + BCM2835_ST_CLO/4;
- lo = bcm2835_peri_read(paddr);
-
- paddr = bcm2835_st + BCM2835_ST_CHI/4;
- st = bcm2835_peri_read(paddr);
-
- /* Test for overflow */
- if (st == hi)
- {
- st <<= 32;
- st += lo;
- }
- else
- {
- 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)
- ;
-}
-
-/* PWM */
-
-void bcm2835_pwm_set_clock(uint32_t divisor)
-{
- if ( bcm2835_clk == MAP_FAILED
- || bcm2835_pwm == MAP_FAILED)
- return; /* bcm2835_init() failed or not root */
-
- /* From Gerts code */
- divisor &= 0xfff;
- /* Stop PWM clock */
- bcm2835_peri_write(bcm2835_clk + BCM2835_PWMCLK_CNTL, BCM2835_PWM_PASSWRD | 0x01);
- bcm2835_delay(110); /* Prevents clock going slow */
- /* Wait for the clock to be not busy */
- while ((bcm2835_peri_read(bcm2835_clk + BCM2835_PWMCLK_CNTL) & 0x80) != 0)
- bcm2835_delay(1);
- /* set the clock divider and enable PWM clock */
- bcm2835_peri_write(bcm2835_clk + BCM2835_PWMCLK_DIV, BCM2835_PWM_PASSWRD | (divisor << 12));
- bcm2835_peri_write(bcm2835_clk + BCM2835_PWMCLK_CNTL, BCM2835_PWM_PASSWRD | 0x11); /* Source=osc and enable */
-}
-
-void bcm2835_pwm_set_mode(uint8_t channel, uint8_t markspace, uint8_t enabled)
-{
- if ( bcm2835_clk == MAP_FAILED
- || bcm2835_pwm == MAP_FAILED)
- return; /* bcm2835_init() failed or not root */
-
- uint32_t control = bcm2835_peri_read(bcm2835_pwm + BCM2835_PWM_CONTROL);
-
- if (channel == 0)
- {
- if (markspace)
- control |= BCM2835_PWM0_MS_MODE;
- else
- control &= ~BCM2835_PWM0_MS_MODE;
- if (enabled)
- control |= BCM2835_PWM0_ENABLE;
- else
- control &= ~BCM2835_PWM0_ENABLE;
- }
- else if (channel == 1)
- {
- if (markspace)
- control |= BCM2835_PWM1_MS_MODE;
- else
- control &= ~BCM2835_PWM1_MS_MODE;
- if (enabled)
- control |= BCM2835_PWM1_ENABLE;
- else
- control &= ~BCM2835_PWM1_ENABLE;
- }
-
- /* If you use the barrier here, wierd things happen, and the commands dont work */
- bcm2835_peri_write_nb(bcm2835_pwm + BCM2835_PWM_CONTROL, control);
- /* bcm2835_peri_write_nb(bcm2835_pwm + BCM2835_PWM_CONTROL, BCM2835_PWM0_ENABLE | BCM2835_PWM1_ENABLE | BCM2835_PWM0_MS_MODE | BCM2835_PWM1_MS_MODE); */
-
-}
-
-void bcm2835_pwm_set_range(uint8_t channel, uint32_t range)
-{
- if ( bcm2835_clk == MAP_FAILED
- || bcm2835_pwm == MAP_FAILED)
- return; /* bcm2835_init() failed or not root */
-
- if (channel == 0)
- bcm2835_peri_write_nb(bcm2835_pwm + BCM2835_PWM0_RANGE, range);
- else if (channel == 1)
- bcm2835_peri_write_nb(bcm2835_pwm + BCM2835_PWM1_RANGE, range);
-}
-
-void bcm2835_pwm_set_data(uint8_t channel, uint32_t data)
-{
- if ( bcm2835_clk == MAP_FAILED
- || bcm2835_pwm == MAP_FAILED)
- return; /* bcm2835_init() failed or not root */
-
- if (channel == 0)
- bcm2835_peri_write_nb(bcm2835_pwm + BCM2835_PWM0_DATA, data);
- else if (channel == 1)
- bcm2835_peri_write_nb(bcm2835_pwm + BCM2835_PWM1_DATA, data);
-}
-
-/* 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 == MAP_FAILED)
- 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)
-{
- int memfd;
- int ok;
- FILE *fp;
-
- if (debug)
- {
- bcm2835_peripherals = (uint32_t*)BCM2835_PERI_BASE;
-
- bcm2835_pads = bcm2835_peripherals + BCM2835_GPIO_PADS/4;
- bcm2835_clk = bcm2835_peripherals + BCM2835_CLOCK_BASE/4;
- bcm2835_gpio = bcm2835_peripherals + BCM2835_GPIO_BASE/4;
- bcm2835_pwm = bcm2835_peripherals + BCM2835_GPIO_PWM/4;
- bcm2835_spi0 = bcm2835_peripherals + BCM2835_SPI0_BASE/4;
- bcm2835_bsc0 = bcm2835_peripherals + BCM2835_BSC0_BASE/4;
- bcm2835_bsc1 = bcm2835_peripherals + BCM2835_BSC1_BASE/4;
- bcm2835_st = bcm2835_peripherals + BCM2835_ST_BASE/4;
- bcm2835_aux = bcm2835_peripherals + BCM2835_AUX_BASE/4;
- bcm2835_spi1 = bcm2835_peripherals + BCM2835_SPI1_BASE/4;
-
- return 1; /* Success */
- }
-
- /* Figure out the base and size of the peripheral address block
- // using the device-tree. Required for RPi2/3/4, optional for RPi 1
- */
- if ((fp = fopen(BMC2835_RPI2_DT_FILENAME , "rb")))
- {
- unsigned char buf[16];
- uint32_t base_address;
- uint32_t peri_size;
- if (fread(buf, 1, sizeof(buf), fp) >= 8)
- {
- base_address = (buf[4] << 24) |
- (buf[5] << 16) |
- (buf[6] << 8) |
- (buf[7] << 0);
-
- peri_size = (buf[8] << 24) |
- (buf[9] << 16) |
- (buf[10] << 8) |
- (buf[11] << 0);
-
- if (!base_address)
- {
- /* looks like RPI 4 */
- base_address = (buf[8] << 24) |
- (buf[9] << 16) |
- (buf[10] << 8) |
- (buf[11] << 0);
-
- peri_size = (buf[12] << 24) |
- (buf[13] << 16) |
- (buf[14] << 8) |
- (buf[15] << 0);
- }
- /* check for valid known range formats */
- if ((buf[0] == 0x7e) &&
- (buf[1] == 0x00) &&
- (buf[2] == 0x00) &&
- (buf[3] == 0x00) &&
- ((base_address == BCM2835_PERI_BASE) || (base_address == BCM2835_RPI2_PERI_BASE) || (base_address == BCM2835_RPI4_PERI_BASE)))
- {
- bcm2835_peripherals_base = (off_t)base_address;
- bcm2835_peripherals_size = (size_t)peri_size;
- if( base_address == BCM2835_RPI4_PERI_BASE )
- {
- pud_type_rpi4 = 1;
- }
- }
-
- }
-
- fclose(fp);
- }
- /* else we are prob on RPi 1 with BCM2835, and use the hardwired defaults */
-
- /* Now get ready to map the peripherals block
- * If we are not root, try for the new /dev/gpiomem interface and accept
- * the fact that we can only access GPIO
- * else try for the /dev/mem interface and get access to everything
- */
- memfd = -1;
- ok = 0;
- if (geteuid() == 0
-#ifdef BCM2835_HAVE_LIBCAP
- || bcm2835_has_capability(CAP_SYS_RAWIO)
-#endif
- )
- {
- /* Open the master /dev/mem 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;
- }
-
- /* Base of the peripherals block is mapped to VM */
- bcm2835_peripherals = mapmem("gpio", bcm2835_peripherals_size, memfd, bcm2835_peripherals_base);
- if (bcm2835_peripherals == MAP_FAILED) goto exit;
-
- /* Now compute the base addresses of various peripherals,
- // which are at fixed offsets within the mapped peripherals block
- // Caution: bcm2835_peripherals is uint32_t*, so divide offsets by 4
- */
- bcm2835_gpio = bcm2835_peripherals + BCM2835_GPIO_BASE/4;
- bcm2835_pwm = bcm2835_peripherals + BCM2835_GPIO_PWM/4;
- bcm2835_clk = bcm2835_peripherals + BCM2835_CLOCK_BASE/4;
- bcm2835_pads = bcm2835_peripherals + BCM2835_GPIO_PADS/4;
- bcm2835_spi0 = bcm2835_peripherals + BCM2835_SPI0_BASE/4;
- bcm2835_bsc0 = bcm2835_peripherals + BCM2835_BSC0_BASE/4; /* I2C */
- bcm2835_bsc1 = bcm2835_peripherals + BCM2835_BSC1_BASE/4; /* I2C */
- bcm2835_st = bcm2835_peripherals + BCM2835_ST_BASE/4;
- bcm2835_aux = bcm2835_peripherals + BCM2835_AUX_BASE/4;
- bcm2835_spi1 = bcm2835_peripherals + BCM2835_SPI1_BASE/4;
-
- ok = 1;
- }
- else
- {
- /* Not root, try /dev/gpiomem */
- /* Open the master /dev/mem device */
- if ((memfd = open("/dev/gpiomem", O_RDWR | O_SYNC) ) < 0)
- {
- fprintf(stderr, "bcm2835_init: Unable to open /dev/gpiomem: %s\n",
- strerror(errno)) ;
- goto exit;
- }
-
- /* Base of the peripherals block is mapped to VM */
- bcm2835_peripherals_base = 0;
- bcm2835_peripherals = mapmem("gpio", bcm2835_peripherals_size, memfd, bcm2835_peripherals_base);
- if (bcm2835_peripherals == MAP_FAILED) goto exit;
- bcm2835_gpio = bcm2835_peripherals;
- 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_peripherals, bcm2835_peripherals_size);
- bcm2835_peripherals = MAP_FAILED;
- bcm2835_gpio = MAP_FAILED;
- bcm2835_pwm = MAP_FAILED;
- bcm2835_clk = MAP_FAILED;
- bcm2835_pads = MAP_FAILED;
- bcm2835_spi0 = MAP_FAILED;
- bcm2835_bsc0 = MAP_FAILED;
- bcm2835_bsc1 = MAP_FAILED;
- bcm2835_st = MAP_FAILED;
- bcm2835_aux = MAP_FAILED;
- bcm2835_spi1 = MAP_FAILED;
- 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/3rd-party/bcm2835.h b/3rd-party/bcm2835.h
deleted file mode 100644
index 7d3e3b9..0000000
--- a/3rd-party/bcm2835.h
+++ /dev/null
@@ -1,2029 +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.26 2020/01/11 05:07:13 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, as used in the RaspberryPi,
- 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).
-
- Works on all versions upt to and including RPI 4.
- Works with all versions of Debian up to and including Debian Buster 10.
-
- 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.68.tar.gz
- You can find the latest version at http://www.airspayce.com/mikem/bcm2835
-
- Several example programs are provided.
-
- Based on data in http://elinux.org/RPi_Low-level_peripherals and
- http://www.raspberrypi.org/wp-content/uploads/2012/02/BCM2835-ARM-Peripherals.pdf
- and http://www.scribd.com/doc/101830961/GPIO-Pads-Control2
-
- You can also find online help and discussion at http://groups.google.com/group/bcm2835
- Please use that group for all questions and discussions on this topic.
- Do not contact the author directly, unless it is to discuss commercial licensing.
- Before asking a question or reporting a bug, please read
- - http://en.wikipedia.org/wiki/Wikipedia:Reference_desk/How_to_ask_a_software_question
- - http://www.catb.org/esr/faqs/smart-questions.html
- - http://www.chiark.greenend.org.uk/~shgtatham/bugs.html
-
- Tested on debian6-19-04-2012, 2012-07-15-wheezy-raspbian, 2013-07-26-wheezy-raspbian
- and Occidentalisv01, 2016-02-09 Raspbian Jessie.
- CAUTION: it has been observed that when detect enables such as bcm2835_gpio_len()
- are used and the pin is pulled LOW
- it can cause temporary hangs on 2012-07-15-wheezy-raspbian, 2013-07-26-wheezy-raspbian
- and Occidentalisv01.
- Reason for this is not yet determined, but we suspect that an interrupt handler is
- hitting a hard loop on those OSs.
- If you must use bcm2835_gpio_len() and friends, make sure you disable the pins with
- bcm2835_gpio_clr_len() and friends after use.
-
- \par Running as root
-
- Prior to the release of Raspbian Jessie in Feb 2016, access to any
- peripheral device via /dev/mem on the RPi required the process to
- run as root. Raspbian Jessie permits non-root users to access the
- GPIO peripheral (only) via /dev/gpiomem, and this library supports
- that limited mode of operation.
-
- If the library runs with effective UID of 0 (ie root), then
- bcm2835_init() will attempt to open /dev/mem, and, if successful, it
- will permit use of all peripherals and library functions.
-
- If the library runs with any other effective UID (ie not root), then
- bcm2835_init() will attempt to open /dev/gpiomem, and, if
- successful, will only permit GPIO operations. In particular,
- bcm2835_spi_begin() and bcm2835_i2c_begin() will return false and all
- other non-gpio operations may fail silently or crash.
-
- If your program needs acccess to /dev/mem but not as root,
- and if you have the libcap-dev package installed on the target,
- you can compile this library to use
- libcap2 so that it tests whether the exceutable has the cap_sys_rawio capability, and therefore
- permission to access /dev/mem.
- To enable this ability, uncomment the #define BCM2835_HAVE_LIBCAP in bcm2835.h or
- -DBCM2835_HAVE_LIBCAP on your compiler command line.
- After your program has been compiled:
- \code
- sudo setcap cap_sys_rawio+ep *myprogname*
- \endcode
- You also need to do these steps on the host once, to support libcap and not-root read/write access
- to /dev/mem:
- 1. Install libcap support
- \code
- sudo apt-get install libcap2 libcap-dev
- 2. Add current user to kmem group
- \code
- sudo adduser $USER kmem
- \endcode
- 3. Allow write access to /dev/mem by members of kmem group
- \code
- echo 'SUBSYSTEM=="mem", KERNEL=="mem", GROUP="kmem", MODE="0660"' | sudo tee /etc/udev/rules.d/98-mem.rules
- \endcode
- \code
- sudo reboot
- \endcode
-
- \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.
-
- On RPI 2, the peripheral addresses are different and the bcm2835 library gets them
- from reading /proc/device-tree/soc/ranges. This is only availble with recent versions of the kernel on RPI 2.
-
- After initialisation, 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
- bcm2835_aux
- bcm2835_spi1
-
- \par Raspberry Pi 2 (RPI2)
-
- For this library to work correctly on RPI2, you MUST have the device tree support enabled in the kernel.
- You should also ensure you are using the latest version of Linux. The library has been tested on RPI2
- with 2015-02-16-raspbian-wheezy and ArchLinuxARM-rpi-2 as of 2015-03-29.
-
- When device tree suport is enabled, the file /proc/device-tree/soc/ranges will appear in the file system,
- and the bcm2835 module relies on its presence to correctly run on RPI2 (it is optional for RPI1).
- Without device tree support enabled and the presence of this file, it will not work on RPI2.
-
- To enable device tree support:
-
- \code
- sudo raspi-config
- under Advanced Options - enable Device Tree
- Reboot.
- \endcode
-
- \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)
-
- Although it is possible to select high speeds for the SPI interface, up to 125MHz (see bcm2835_spi_setClockDivider())
- you should not expect to actually achieve those sorts of speeds with the RPi wiring. Our tests on RPi 2 show that the
- SPI CLK line when unloaded has a resonant frequency of about 40MHz, and when loaded, the MOSI and MISO lines
- ring at an even lower frequency. Measurements show that SPI waveforms are very poor and unusable at 62 and 125MHz.
- Dont expect any speed faster than 31MHz to work reliably.
-
- The bcm2835_aux_spi_* functions allow you to control the BCM 2835 SPI1 interface,
- allowing you to send and received data by SPI (Serial Peripheral Interface).
-
- The Raspberry Pi GPIO pins used for AUX SPI (SPI1) are:
-
- - P1-38 (MOSI)
- - P1-35 (MISO)
- - P1-40 (CLK)
- - P1-36 (CE2)
-
- \par I2C Pins
-
- The bcm2835_i2c_* functions allow you to control the BCM 2835 BSC interface,
- allowing you to send and received data by I2C ("eye-squared cee"; generically referred to as "two-wire interface") .
- For more information about I?C, see http://en.wikipedia.org/wiki/I%C2%B2C
-
- The Raspberry Pi V2 GPIO pins used for I2C are:
-
- - P1-03 (SDA)
- - P1-05 (SLC)
-
- \par PWM
-
- The BCM2835 supports hardware PWM on a limited subset of GPIO pins. This bcm2835 library provides
- functions for configuring and controlling PWM output on these pins.
-
- The BCM2835 contains 2 independent PWM channels (0 and 1), each of which be connnected to a limited subset of
- GPIO pins. The following GPIO pins may be connected to the following PWM channels (from section 9.5):
- \code
- GPIO PIN RPi pin PWM Channel ALT FUN
- 12 0 0
- 13 1 0
- 18 1-12 0 5
- 19 1 5
- 40 0 0
- 41 1 0
- 45 1 0
- 52 0 1
- 53 1 1
- \endcode
- In order for a GPIO pin to emit output from its PWM channel, it must be set to the Alt Function given above.
- Note carefully that current versions of the Raspberry Pi only expose one of these pins (GPIO 18 = RPi Pin 1-12)
- on the IO headers, and therefore this is the only IO pin on the RPi that can be used for PWM.
- Further it must be set to ALT FUN 5 to get PWM output.
-
- Both PWM channels are driven by the same PWM clock, whose clock dvider can be varied using
- bcm2835_pwm_set_clock(). Each channel can be separately enabled with bcm2835_pwm_set_mode().
- The average output of the PWM channel is determined by the ratio of DATA/RANGE for that channel.
- Use bcm2835_pwm_set_range() to set the range and bcm2835_pwm_set_data() to set the data in that ratio
-
- Each PWM channel can run in either Balanced or Mark-Space mode. In Balanced mode, the hardware
- sends a combination of clock pulses that results in an overall DATA pulses per RANGE pulses.
- In Mark-Space mode, the hardware sets the output HIGH for DATA clock pulses wide, followed by
- LOW for RANGE-DATA clock pulses.
-
- The PWM clock can be set to control the PWM pulse widths. The PWM clock is derived from
- a 19.2MHz clock. You can set any divider, but some common ones are provided by the BCM2835_PWM_CLOCK_DIVIDER_*
- values of \ref bcm2835PWMClockDivider.
-
- For example, say you wanted to drive a DC motor with PWM at about 1kHz,
- and control the speed in 1/1024 increments from
- 0/1024 (stopped) through to 1024/1024 (full on). In that case you might set the
- clock divider to be 16, and the RANGE to 1024. The pulse repetition frequency will be
- 1.2MHz/1024 = 1171.875Hz.
-
- \par Interactions with other systems
-
- In order for bcm2835 library SPI to work, you may need to disable the SPI kernel module using:
-
- \code
- sudo raspi-config
- under Advanced Options - enable Device Tree
- under Advanced Options - disable SPI
- Reboot.
- \endcode
-
- Since bcm2835 accesses the lowest level hardware interfaces (in eh intererests of speed and flexibility)
- there can be intercations with other low level software trying to do similar things.
-
- It seems that with "latest" 8.0 Jessie 4.9.24-v7+ kernel PWM just won't
- work unless you disable audio. There's a line
- \code
- dtparam=audio=on
- \endcode
- in the /boot/config.txt.
- Comment it out like this:
- \code
- #dtparam=audio=on
- \endcode
-
- \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
- #define <sched.h>
- #define <sys/mman.h>
-
- 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 Crashing on some versions of Raspbian
- Some people have reported that various versions of Rasbian will crash or hang
- if certain GPIO pins are toggled: https://github.com/raspberrypi/linux/issues/2550
- when using bcm2835.
- A workaround is to add this line to your /boot/config.txt:
- \code
- dtoverlay=gpio-no-irq
- \endcode
-
- \par Bindings to other languages
-
- mikem has made Perl bindings available at CPAN:
- http://search.cpan.org/~mikem/Device-BCM2835-1.9/lib/Device/BCM2835.pm
- Matthew Baker has kindly made Python bindings available at:
- https: github.com/mubeta06/py-libbcm2835
- Gary Marks has created a Serial Peripheral Interface (SPI) command-line utility
- for Raspberry Pi, based on the bcm2835 library. The
- utility, spincl, is licensed under Open Source GNU GPLv3 by iP Solutions (http://ipsolutionscorp.com), as a
- free download with source included: http://ipsolutionscorp.com/raspberry-pi-spi-utility/
-
- \par Open Source Licensing GPL V3
-
- 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 3 when your application is
- distributed. See https://www.gnu.org/licenses/gpl-3.0.html and COPYING
-
- \par Commercial Licensing
-
- This is the appropriate option if you are creating proprietary applications
- and you are not prepared to distribute and share the source code of your
- application. To purchase a commercial license, contact info@airspayce.com
-
- \par Acknowledgements
-
- Some of this code has been inspired by Dom and Gert.
- The I2C code has been inspired by Alan Barr.
-
- \par Revision History
-
- \version 1.0 Initial release
-
- \version 1.1 Minor bug fixes
-
- \version 1.2 Added support for SPI
-
- \version 1.3 Added bcm2835_spi_transfern()
-
- \version 1.4 Fixed a problem that prevented SPI CE1 being used. Reported by David Robinson.
-
- \version 1.5 Added bcm2835_close() to deinit the library. Suggested by C?sar Ortiz
-
- \version 1.6 Document testing on 2012-07-15-wheezy-raspbian and Occidentalisv01
- Functions bcm2835_gpio_ren(), bcm2835_gpio_fen(), bcm2835_gpio_hen()
- bcm2835_gpio_len(), bcm2835_gpio_aren() and bcm2835_gpio_afen() now
- changes only the pin specified. Other pins that were already previously
- enabled stay enabled.
- Added bcm2835_gpio_clr_ren(), bcm2835_gpio_clr_fen(), bcm2835_gpio_clr_hen()
- bcm2835_gpio_clr_len(), bcm2835_gpio_clr_aren(), bcm2835_gpio_clr_afen()
- to clear the enable for individual pins, suggested by Andreas Sundstrom.
-
- \version 1.7 Added bcm2835_spi_transfernb to support different buffers for read and write.
-
- \version 1.8 Improvements to read barrier, as suggested by maddin.
-
- \version 1.9 Improvements contributed by mikew:
- I noticed that it was mallocing memory for the mmaps on /dev/mem.
- It's not necessary to do that, you can just mmap the file directly,
- so I've removed the mallocs (and frees).
- I've also modified delayMicroseconds() to use nanosleep() for long waits,
- and a busy wait on a high resolution timer for the rest. This is because
- I've found that calling nanosleep() takes at least 100-200 us.
- You need to link using '-lrt' using this version.
- I've added some unsigned casts to the debug prints to silence compiler
- warnings I was getting, fixed some typos, and changed the value of
- BCM2835_PAD_HYSTERESIS_ENABLED to 0x08 as per Gert van Loo's doc at
- http://www.scribd.com/doc/101830961/GPIO-Pads-Control2
- Also added a define for the passwrd value that Gert says is needed to
- change pad control settings.
-
- \version 1.10 Changed the names of the delay functions to bcm2835_delay()
- and bcm2835_delayMicroseconds() to prevent collisions with wiringPi.
- Macros to map delay()-> bcm2835_delay() and
- Macros to map delayMicroseconds()-> bcm2835_delayMicroseconds(), which
- can be disabled by defining BCM2835_NO_DELAY_COMPATIBILITY
-
- \version 1.11 Fixed incorrect link to download file
-
- \version 1.12 New GPIO pin definitions for RPi version 2 (which has a different GPIO mapping)
-
- \version 1.13 New GPIO pin definitions for RPi version 2 plug P5
- Hardware base pointers are now available (after initialisation) externally as bcm2835_gpio
- bcm2835_pwm bcm2835_clk bcm2835_pads bcm2835_spi0.
-
- \version 1.14 Now compiles even if CLOCK_MONOTONIC_RAW is not available, uses CLOCK_MONOTONIC instead.
- Fixed errors in documentation of SPI divider frequencies based on 250MHz clock.
- Reported by Ben Simpson.
-
- \version 1.15 Added bcm2835_close() to end of examples as suggested by Mark Wolfe.
-
- \version 1.16 Added bcm2835_gpio_set_multi, bcm2835_gpio_clr_multi and bcm2835_gpio_write_multi
- to allow a mask of pins to be set all at once. Requested by Sebastian Loncar.
-
- \version 1.17 Added bcm2835_gpio_write_mask. Requested by Sebastian Loncar.
-
- \version 1.18 Added bcm2835_i2c_* functions. Changes to bcm2835_delayMicroseconds:
- now uses the RPi system timer counter, instead of clock_gettime, for improved accuracy.
- No need to link with -lrt now. Contributed by Arjan van Vught.
- \version 1.19 Removed inlines added by previous patch since they don't seem to work everywhere.
- Reported by olly.
-
- \version 1.20 Patch from Mark Dootson to close /dev/mem after access to the peripherals has been granted.
-
- \version 1.21 delayMicroseconds is now not susceptible to 32 bit timer overruns.
- Patch courtesy Jeremy Mortis.
-
- \version 1.22 Fixed incorrect definition of BCM2835_GPFEN0 which broke the ability to set
- falling edge events. Reported by Mark Dootson.
-
- \version 1.23 Added bcm2835_i2c_set_baudrate and bcm2835_i2c_read_register_rs.
- Improvements to bcm2835_i2c_read and bcm2835_i2c_write functions
- to fix ocasional reads not completing. Patched by Mark Dootson.
-
- \version 1.24 Mark Dootson p[atched a problem with his previously submitted code
- under high load from other processes.
-
- \version 1.25 Updated author and distribution location details to airspayce.com
-
- \version 1.26 Added missing unmapmem for pads in bcm2835_close to prevent a memory leak.
- Reported by Hartmut Henkel.
-
- \version 1.27 bcm2835_gpio_set_pad() no longer needs BCM2835_PAD_PASSWRD: it is
- now automatically included.
- Added support for PWM mode with bcm2835_pwm_* functions.
-
- \version 1.28 Fixed a problem where bcm2835_spi_writenb() would have problems with transfers of more than
- 64 bytes dues to read buffer filling. Patched by Peter Würtz.
-
- \version 1.29 Further fix to SPI from Peter Würtz.
-
- \version 1.30 10 microsecond delays from bcm2835_spi_transfer and bcm2835_spi_transfern for
- significant performance improvements, Patch by Alan Watson.
-
- \version 1.31 Fix a GCC warning about dummy variable, patched by Alan Watson. Thanks.
-
- \version 1.32 Added option I2C_V1 definition to compile for version 1 RPi.
- By default I2C code is generated for the V2 RPi which has SDA1 and SCL1 connected.
- Contributed by Malcolm Wiles based on work by Arvi Govindaraj.
-
- \version 1.33 Added command line utilities i2c and gpio to examples. Contributed by Shahrooz Shahparnia.
-
- \version 1.34 Added bcm2835_i2c_write_read_rs() which writes an arbitrary number of bytes,
- sends a repeat start, and reads from the device. Contributed by Eduardo Steinhorst.
-
- \version 1.35 Fix build errors when compiled under Qt. Also performance improvements with SPI transfers. Contributed b Udo Klaas.
-
- \version 1.36 Make automake's test runner detect that we're skipping tests when not root, the second
- one makes us skip the test when using fakeroot (as used when building
- Debian packages). Contributed by Guido Günther.
-
- \version 1.37 Moved confiure.in to configure.ac as receommnded by autoreconf.<br>
- Improvements to bcm2835_st_read to account for possible timer overflow, contributed by 'Ed'.<br>
- Added definitions for Raspberry Pi B+ J8 header GPIO pins.<br>
-
- \version 1.38 Added bcm2835_regbase for the benefit of C# wrappers, patch by Frank Hommers <br>
-
- \version 1.39 Beta version of RPi2 compatibility. Not tested here on RPi2 hardware.
- Testers please confirm correct operation on RPi2.<br>
- Unnecessary 'volatile' qualifiers removed from all variables and signatures.<br>
- Removed unsupportable PWM dividers, based on a report from Christophe Cecillon.<br>
- Minor improvements to spi.c example.<br>
-
- \version 1.40 Correct operation on RPi2 has been confirmed.<br>
- Fixed a number of compiler errors and warnings that occur when bcm2835.h is included
- in code compiled with -Wall -Woverflow -Wstrict-overflow -Wshadow -Wextra -pedantic.
- Reported by tlhackque.<br>
- Fixed a problem where calling bcm2835_delayMicroseconds loops forever when debug is set. Reported by tlhackque.<br>
- Reinstated use of volatile in 2 functions where there was a danger of lost reads or writes. Reported by tlhackque.<br>
-
- \version 1.41 Added BCM2835_VERSION macro and new function bcm2835_version(); Requested by tlhackque.<br>
- Improvements to peripheral memory barriers as suggested by tlhackque.<br>
- Reinstated some necessary volatile declarations as requested by tlhackque.<br>
-
- \version 1.42 Further improvements to memory barriers with the patient assistance and patches of tlhackque.<br>
-
- \version 1.43 Fixed problems with compiling barriers on RPI 2 with Arch Linux and gcc 4.9.2.
- Reported and patched by Lars Christensen.<br>
- Testing on RPI 2, with ArchLinuxARM-rpi-2-latest and 2015-02-16-raspbian-wheezy.<br>
-
- \version 1.44 Added documention about the need for device tree to be enabled on RPI2.<br>
- Improvements to detection of availability of DMB instruction based on value of __ARM_ARCH macro.<br>
-
- \version 1.45 Fixed an error in the pad group offsets that would prevent bcm2835_gpio_set_pad()
- and bcm2835_gpio_pad() working correctly with non-0 pad groups. Reported by Guido.
-
- \version 1.46 2015-09-18
- Added symbolic definitions for remaining pins on 40 pin GPIO header on RPi 2. <br>
-
- \version 1.47 2015-11-18
- Fixed possibly incorrect reads in bcm2835_i2c_read_register_rs, patch from Eckhardt Ulrich.<br>
-
- \version 1.48 2015-12-08
- Added patch from Eckhardt Ulrich that fixed problems that could cause hanging with bcm2835_i2c_read_register_rs
- and others.
-
- \version 1.49 2016-01-05
- Added patch from Jonathan Perkin with new functions bcm2835_gpio_eds_multi() and bcm2835_gpio_set_eds_multi().
-
- \version 1.50 2016-02-28
- Added support for running as non-root, permitting access to GPIO only. Functions
- bcm2835_spi_begin() and bcm2835_i2c_begin() will now return 0 if not running as root
- (which prevents access to the SPI and I2C peripherals, amongst others).
- Testing on Raspbian Jessie.
-
- \version 1.51 2016-11-03
- Added documentation about SPI clock divider and resulting SPI speeds on RPi3.
- Fixed a problem where seg fault could occur in bcm2835_delayMicroseconds() if not running as root. Patch from Pok.
-
- \version 1.52 2017-02-03
- Added link to commercial license purchasing.
-
- \version 1.53 2018-01-14
- Added support for AUX SPI (SPI1)
- Contributed by Arjan van Vught (http://www.raspberrypi-dmx.org/)
-
- \version 1.54 2018-01-17
- Fixed compile errors in new AUX spi code under some circumstances.
-
- \version 1.55 2018-01-20
- Fixed version numbers.
- Fixed some warnings.
-
- \version 1.56 2018-06-10
- Supports bcm2835_spi_setBitOrder(BCM2835_SPI_BIT_ORDER_LSBFIRST), after which SPI bytes are reversed on read or write.
- Based on a suggestion by Damiano Benedetti.
-
- \version 1.57 2018-08-28
- Added SPI function bcm2835_spi_set_speed_hz(uint32_t speed_hz);
- Contributed by Arjan van Vught (http://www.raspberrypi-dmx.org/)
-
- \version 1.58 2018-11-29
- Added examples/spiram, which shows how to use the included little library (spiram.c and spiram.h)
- to read and write SPI RAM chips such as 23K256-I/P
-
- \version 1.59 2019-05-22
- Fixed a bug in bcm2835_i2c_read reported by Charles Hayward where a noisy I2C line cold cause a seg fault by
- reading too many characters.
-
- \version 1.60 2019-07-23
- Applied patch from Mark Dootson for RPi 4 compatibility. Thanks Mark. Not tested here on RPi4, but others report it works.
- Tested as still working correctly on earlier RPi models. Tested with Debian Buster on earlier models
-
- \version 1.61 2020-01-11
- Fixed errors in the documentation for bcm2835_spi_write.
- Fixes issue seen on Raspberry Pi 4 boards where 64-bit off_t is used by
- default via -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64. The offset was
- being incorrectly converted, this way is clearer and fixes the problem. Contributed by Jonathan Perkin.
-
- \version 1.62 2020-01-12
- Fixed a problem that could cause compile failures with size_t and off_t
-
- \version 1.63 2020-03-07
- Added bcm2835_aux_spi_transfer, contributed by Michivi
- Adopted GPL V3 licensing
-
- \version 1.64 2020-04-11
- Fixed error in definitions of BCM2835_AUX_SPI_STAT_TX_LVL and BCM2835_AUX_SPI_STAT_RX_LVL. Patch from
- Eric Marzec. Thanks.
-
- \version 1.65, 1.66 2020-04-16
- Added support for use of capability cap_sys_rawio to determine if access to /dev/mem is available for non-root
- users. Contributed by Doug McFadyen.
-
- \version 1.67, 1.66 2020-06-11
- Fixed an error in bcm2835_i2c_read() where the status byte was not correctly updated with BCM2835_BSC_S_DONE
- Reported by Zihan. Thanks.
-
- \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 <stdint.h>
-
-#define BCM2835_VERSION 10066 /* Version 1.66 */
-
-// Define this if you want to use libcap2 to determine if you have the cap_sys_rawio capability
-// and therefore the capability of opening /dev/mem, even if you are not root.
-// See the comments above in the documentation for 'Running As Root'
-//#define BCM2835_HAVE_LIBCAP
-
-/* RPi 2 is ARM v7, and has DMB instruction for memory barriers.
- Older RPis are ARM v6 and don't, so a coprocessor instruction must be used instead.
- However, not all versions of gcc in all distros support the dmb assembler instruction even on compatible processors.
- This test is so any ARMv7 or higher processors with suitable GCC will use DMB.
-*/
-#if __ARM_ARCH >= 7
-#define BCM2835_HAVE_DMB
-#endif
-
-/*! \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
-
-/*! Return the minimum of 2 numbers */
-#ifndef MIN
-#define MIN(a, b) (a < b ? a : b)
-#endif
-
-/*! Speed of the core clock core_clk */
-#define BCM2835_CORE_CLK_HZ 250000000 /*!< 250 MHz */
-
-/*! On all recent OSs, the base of the peripherals is read from a /proc file */
-#define BMC2835_RPI2_DT_FILENAME "/proc/device-tree/soc/ranges"
-
-/*! Physical addresses for various peripheral register sets
- Base Physical Address of the BCM 2835 peripheral registers
- Note this is different for the RPi2 BCM2836, where this is derived from /proc/device-tree/soc/ranges
- If /proc/device-tree/soc/ranges exists on a RPi 1 OS, it would be expected to contain the
- following numbers:
-*/
-/*! Peripherals block base address on RPi 1 */
-#define BCM2835_PERI_BASE 0x20000000
-/*! Size of the peripherals block on RPi 1 */
-#define BCM2835_PERI_SIZE 0x01000000
-/*! Alternate base address for RPI 2 / 3 */
-#define BCM2835_RPI2_PERI_BASE 0x3F000000
-/*! Alternate base address for RPI 4 */
-#define BCM2835_RPI4_PERI_BASE 0xFE000000
-/*! Alternate size for RPI 4 */
-#define BCM2835_RPI4_PERI_SIZE 0x01800000
-
-/*! Offsets for the bases of various peripherals within the peripherals block
- / Base Address of the System Timer registers
-*/
-#define BCM2835_ST_BASE 0x3000
-/*! Base Address of the Pads registers */
-#define BCM2835_GPIO_PADS 0x100000
-/*! Base Address of the Clock/timer registers */
-#define BCM2835_CLOCK_BASE 0x101000
-/*! Base Address of the GPIO registers */
-#define BCM2835_GPIO_BASE 0x200000
-/*! Base Address of the SPI0 registers */
-#define BCM2835_SPI0_BASE 0x204000
-/*! Base Address of the BSC0 registers */
-#define BCM2835_BSC0_BASE 0x205000
-/*! Base Address of the PWM registers */
-#define BCM2835_GPIO_PWM 0x20C000
-/*! Base Address of the AUX registers */
-#define BCM2835_AUX_BASE 0x215000
-/*! Base Address of the AUX_SPI1 registers */
-#define BCM2835_SPI1_BASE 0x215080
-/*! Base Address of the AUX_SPI2 registers */
-#define BCM2835_SPI2_BASE 0x2150C0
-/*! Base Address of the BSC1 registers */
-#define BCM2835_BSC1_BASE 0x804000
-
-#include <stdlib.h>
-
-/*! Physical address and size of the peripherals block
- May be overridden on RPi2
-*/
-extern off_t bcm2835_peripherals_base;
-/*! Size of the peripherals block to be mapped */
-extern size_t bcm2835_peripherals_size;
-
-/*! Virtual memory address of the mapped peripherals block */
-extern uint32_t *bcm2835_peripherals;
-
-/*! Base of the ST (System Timer) registers.
- Available after bcm2835_init has been called (as root)
-*/
-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 (as root)
-*/
-extern volatile uint32_t *bcm2835_pwm;
-
-/*! Base of the CLK registers.
- Available after bcm2835_init has been called (as root)
-*/
-extern volatile uint32_t *bcm2835_clk;
-
-/*! Base of the PADS registers.
- Available after bcm2835_init has been called (as root)
-*/
-extern volatile uint32_t *bcm2835_pads;
-
-/*! Base of the SPI0 registers.
- Available after bcm2835_init has been called (as root)
-*/
-extern volatile uint32_t *bcm2835_spi0;
-
-/*! Base of the BSC0 registers.
- Available after bcm2835_init has been called (as root)
-*/
-extern volatile uint32_t *bcm2835_bsc0;
-
-/*! Base of the BSC1 registers.
- Available after bcm2835_init has been called (as root)
-*/
-extern volatile uint32_t *bcm2835_bsc1;
-
-/*! Base of the AUX registers.
- Available after bcm2835_init has been called (as root)
-*/
-extern volatile uint32_t *bcm2835_aux;
-
-/*! Base of the SPI1 registers.
- Available after bcm2835_init has been called (as root)
-*/
-extern volatile uint32_t *bcm2835_spi1;
-
-
-/*! \brief bcm2835RegisterBase
- Register bases for bcm2835_regbase()
-*/
-typedef enum
-{
- BCM2835_REGBASE_ST = 1, /*!< Base of the ST (System Timer) registers. */
- BCM2835_REGBASE_GPIO = 2, /*!< Base of the GPIO registers. */
- BCM2835_REGBASE_PWM = 3, /*!< Base of the PWM registers. */
- BCM2835_REGBASE_CLK = 4, /*!< Base of the CLK registers. */
- BCM2835_REGBASE_PADS = 5, /*!< Base of the PADS registers. */
- BCM2835_REGBASE_SPI0 = 6, /*!< Base of the SPI0 registers. */
- BCM2835_REGBASE_BSC0 = 7, /*!< Base of the BSC0 registers. */
- BCM2835_REGBASE_BSC1 = 8, /*!< Base of the BSC1 registers. */
- BCM2835_REGBASE_AUX = 9, /*!< Base of the AUX registers. */
- BCM2835_REGBASE_SPI1 = 10 /*!< Base of the SPI1 registers. */
-} bcm2835RegisterBase;
-
-/*! Size of memory page on RPi */
-#define BCM2835_PAGE_SIZE (4*1024)
-/*! Size of memory block on RPi */
-#define BCM2835_BLOCK_SIZE (4*1024)
-
-
-/* Defines for GPIO
- The BCM2835 has 54 GPIO pins.
- BCM2835 data sheet, Page 90 onwards.
-*/
-/*! GPIO register offsets from BCM2835_GPIO_BASE.
- Offsets into the GPIO Peripheral block in bytes per 6.1 Register View
-*/
-#define BCM2835_GPFSEL0 0x0000 /*!< GPIO Function Select 0 */
-#define BCM2835_GPFSEL1 0x0004 /*!< GPIO Function Select 1 */
-#define BCM2835_GPFSEL2 0x0008 /*!< GPIO Function Select 2 */
-#define BCM2835_GPFSEL3 0x000c /*!< GPIO Function Select 3 */
-#define BCM2835_GPFSEL4 0x0010 /*!< GPIO Function Select 4 */
-#define BCM2835_GPFSEL5 0x0014 /*!< GPIO Function Select 5 */
-#define BCM2835_GPSET0 0x001c /*!< GPIO Pin Output Set 0 */
-#define BCM2835_GPSET1 0x0020 /*!< GPIO Pin Output Set 1 */
-#define BCM2835_GPCLR0 0x0028 /*!< GPIO Pin Output Clear 0 */
-#define BCM2835_GPCLR1 0x002c /*!< GPIO Pin Output Clear 1 */
-#define BCM2835_GPLEV0 0x0034 /*!< GPIO Pin Level 0 */
-#define BCM2835_GPLEV1 0x0038 /*!< GPIO Pin Level 1 */
-#define BCM2835_GPEDS0 0x0040 /*!< GPIO Pin Event Detect Status 0 */
-#define BCM2835_GPEDS1 0x0044 /*!< GPIO Pin Event Detect Status 1 */
-#define BCM2835_GPREN0 0x004c /*!< GPIO Pin Rising Edge Detect Enable 0 */
-#define BCM2835_GPREN1 0x0050 /*!< GPIO Pin Rising Edge Detect Enable 1 */
-#define BCM2835_GPFEN0 0x0058 /*!< GPIO Pin Falling Edge Detect Enable 0 */
-#define BCM2835_GPFEN1 0x005c /*!< GPIO Pin Falling Edge Detect Enable 1 */
-#define BCM2835_GPHEN0 0x0064 /*!< GPIO Pin High Detect Enable 0 */
-#define BCM2835_GPHEN1 0x0068 /*!< GPIO Pin High Detect Enable 1 */
-#define BCM2835_GPLEN0 0x0070 /*!< GPIO Pin Low Detect Enable 0 */
-#define BCM2835_GPLEN1 0x0074 /*!< GPIO Pin Low Detect Enable 1 */
-#define BCM2835_GPAREN0 0x007c /*!< GPIO Pin Async. Rising Edge Detect 0 */
-#define BCM2835_GPAREN1 0x0080 /*!< GPIO Pin Async. Rising Edge Detect 1 */
-#define BCM2835_GPAFEN0 0x0088 /*!< GPIO Pin Async. Falling Edge Detect 0 */
-#define BCM2835_GPAFEN1 0x008c /*!< GPIO Pin Async. Falling Edge Detect 1 */
-#define BCM2835_GPPUD 0x0094 /*!< GPIO Pin Pull-up/down Enable */
-#define BCM2835_GPPUDCLK0 0x0098 /*!< GPIO Pin Pull-up/down Enable Clock 0 */
-#define BCM2835_GPPUDCLK1 0x009c /*!< GPIO Pin Pull-up/down Enable Clock 1 */
-
-/* 2711 has a different method for pin pull-up/down/enable */
-#define BCM2835_GPPUPPDN0 0x00e4 /* Pin pull-up/down for pins 15:0 */
-#define BCM2835_GPPUPPDN1 0x00e8 /* Pin pull-up/down for pins 31:16 */
-#define BCM2835_GPPUPPDN2 0x00ec /* Pin pull-up/down for pins 47:32 */
-#define BCM2835_GPPUPPDN3 0x00f0 /* Pin pull-up/down for pins 57:48 */
-
-/*! \brief bcm2835PortFunction
- Port function select modes for bcm2835_gpio_fsel()
-*/
-typedef enum
-{
- BCM2835_GPIO_FSEL_INPT = 0x00, /*!< Input 0b000 */
- BCM2835_GPIO_FSEL_OUTP = 0x01, /*!< Output 0b001 */
- BCM2835_GPIO_FSEL_ALT0 = 0x04, /*!< Alternate function 0 0b100 */
- BCM2835_GPIO_FSEL_ALT1 = 0x05, /*!< Alternate function 1 0b101 */
- BCM2835_GPIO_FSEL_ALT2 = 0x06, /*!< Alternate function 2 0b110, */
- BCM2835_GPIO_FSEL_ALT3 = 0x07, /*!< Alternate function 3 0b111 */
- BCM2835_GPIO_FSEL_ALT4 = 0x03, /*!< Alternate function 4 0b011 */
- BCM2835_GPIO_FSEL_ALT5 = 0x02, /*!< Alternate function 5 0b010 */
- BCM2835_GPIO_FSEL_MASK = 0x07 /*!< Function select bits mask 0b111 */
-} bcm2835FunctionSelect;
-
-/*! \brief bcm2835PUDControl
- Pullup/Pulldown defines for bcm2835_gpio_pud()
-*/
-typedef enum
-{
- BCM2835_GPIO_PUD_OFF = 0x00, /*!< Off ? disable pull-up/down 0b00 */
- BCM2835_GPIO_PUD_DOWN = 0x01, /*!< Enable Pull Down control 0b01 */
- BCM2835_GPIO_PUD_UP = 0x02 /*!< Enable Pull Up control 0b10 */
-} bcm2835PUDControl;
-
-/* need a value for pud functions that can't work unless RPI 4 */
-#define BCM2835_GPIO_PUD_ERROR 0x08
-
-/*! 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_*.
- RPi B+ has yet differnet pinouts and these are defined in RPI_BPLUS_*.
- At bootup, pins 8 and 10 are set to UART0_TXD, UART0_RXD (ie the alt0 function) respectively
- When SPI0 is in use (ie after bcm2835_spi_begin()), SPI0 pins are dedicated to SPI
- and cant be controlled independently.
- If you are using the RPi Compute Module, just use the GPIO number: there is no need to use one of these
- symbolic names
-*/
-typedef enum
-{
- RPI_GPIO_P1_03 = 0, /*!< Version 1, Pin P1-03 */
- RPI_GPIO_P1_05 = 1, /*!< Version 1, Pin P1-05 */
- RPI_GPIO_P1_07 = 4, /*!< Version 1, Pin P1-07 */
- RPI_GPIO_P1_08 = 14, /*!< Version 1, Pin P1-08, defaults to alt function 0 UART0_TXD */
- RPI_GPIO_P1_10 = 15, /*!< Version 1, Pin P1-10, defaults to alt function 0 UART0_RXD */
- RPI_GPIO_P1_11 = 17, /*!< Version 1, Pin P1-11 */
- RPI_GPIO_P1_12 = 18, /*!< Version 1, Pin P1-12, can be PWM channel 0 in ALT FUN 5 */
- RPI_GPIO_P1_13 = 21, /*!< Version 1, Pin P1-13 */
- RPI_GPIO_P1_15 = 22, /*!< Version 1, Pin P1-15 */
- RPI_GPIO_P1_16 = 23, /*!< Version 1, Pin P1-16 */
- RPI_GPIO_P1_18 = 24, /*!< Version 1, Pin P1-18 */
- RPI_GPIO_P1_19 = 10, /*!< Version 1, Pin P1-19, MOSI when SPI0 in use */
- RPI_GPIO_P1_21 = 9, /*!< Version 1, Pin P1-21, MISO when SPI0 in use */
- RPI_GPIO_P1_22 = 25, /*!< Version 1, Pin P1-22 */
- RPI_GPIO_P1_23 = 11, /*!< Version 1, Pin P1-23, CLK when SPI0 in use */
- RPI_GPIO_P1_24 = 8, /*!< Version 1, Pin P1-24, CE0 when SPI0 in use */
- RPI_GPIO_P1_26 = 7, /*!< Version 1, Pin P1-26, CE1 when SPI0 in use */
-
- /* RPi Version 2 */
- RPI_V2_GPIO_P1_03 = 2, /*!< Version 2, Pin P1-03 */
- RPI_V2_GPIO_P1_05 = 3, /*!< Version 2, Pin P1-05 */
- RPI_V2_GPIO_P1_07 = 4, /*!< Version 2, Pin P1-07 */
- RPI_V2_GPIO_P1_08 = 14, /*!< Version 2, Pin P1-08, defaults to alt function 0 UART0_TXD */
- RPI_V2_GPIO_P1_10 = 15, /*!< Version 2, Pin P1-10, defaults to alt function 0 UART0_RXD */
- RPI_V2_GPIO_P1_11 = 17, /*!< Version 2, Pin P1-11 */
- RPI_V2_GPIO_P1_12 = 18, /*!< Version 2, Pin P1-12, can be PWM channel 0 in ALT FUN 5 */
- RPI_V2_GPIO_P1_13 = 27, /*!< Version 2, Pin P1-13 */
- RPI_V2_GPIO_P1_15 = 22, /*!< Version 2, Pin P1-15 */
- RPI_V2_GPIO_P1_16 = 23, /*!< Version 2, Pin P1-16 */
- RPI_V2_GPIO_P1_18 = 24, /*!< Version 2, Pin P1-18 */
- RPI_V2_GPIO_P1_19 = 10, /*!< Version 2, Pin P1-19, MOSI when SPI0 in use */
- RPI_V2_GPIO_P1_21 = 9, /*!< Version 2, Pin P1-21, MISO when SPI0 in use */
- RPI_V2_GPIO_P1_22 = 25, /*!< Version 2, Pin P1-22 */
- RPI_V2_GPIO_P1_23 = 11, /*!< Version 2, Pin P1-23, CLK when SPI0 in use */
- RPI_V2_GPIO_P1_24 = 8, /*!< Version 2, Pin P1-24, CE0 when SPI0 in use */
- RPI_V2_GPIO_P1_26 = 7, /*!< Version 2, Pin P1-26, CE1 when SPI0 in use */
- RPI_V2_GPIO_P1_29 = 5, /*!< Version 2, Pin P1-29 */
- RPI_V2_GPIO_P1_31 = 6, /*!< Version 2, Pin P1-31 */
- RPI_V2_GPIO_P1_32 = 12, /*!< Version 2, Pin P1-32 */
- RPI_V2_GPIO_P1_33 = 13, /*!< Version 2, Pin P1-33 */
- RPI_V2_GPIO_P1_35 = 19, /*!< Version 2, Pin P1-35, can be PWM channel 1 in ALT FUN 5 */
- RPI_V2_GPIO_P1_36 = 16, /*!< Version 2, Pin P1-36 */
- RPI_V2_GPIO_P1_37 = 26, /*!< Version 2, Pin P1-37 */
- RPI_V2_GPIO_P1_38 = 20, /*!< Version 2, Pin P1-38 */
- RPI_V2_GPIO_P1_40 = 21, /*!< Version 2, Pin P1-40 */
-
- /* RPi Version 2, new plug P5 */
- RPI_V2_GPIO_P5_03 = 28, /*!< Version 2, Pin P5-03 */
- RPI_V2_GPIO_P5_04 = 29, /*!< Version 2, Pin P5-04 */
- RPI_V2_GPIO_P5_05 = 30, /*!< Version 2, Pin P5-05 */
- RPI_V2_GPIO_P5_06 = 31, /*!< Version 2, Pin P5-06 */
-
- /* RPi B+ J8 header, also RPi 2 40 pin GPIO header */
- RPI_BPLUS_GPIO_J8_03 = 2, /*!< B+, Pin J8-03 */
- RPI_BPLUS_GPIO_J8_05 = 3, /*!< B+, Pin J8-05 */
- RPI_BPLUS_GPIO_J8_07 = 4, /*!< B+, Pin J8-07 */
- RPI_BPLUS_GPIO_J8_08 = 14, /*!< B+, Pin J8-08, defaults to alt function 0 UART0_TXD */
- RPI_BPLUS_GPIO_J8_10 = 15, /*!< B+, Pin J8-10, defaults to alt function 0 UART0_RXD */
- RPI_BPLUS_GPIO_J8_11 = 17, /*!< B+, Pin J8-11 */
- RPI_BPLUS_GPIO_J8_12 = 18, /*!< B+, Pin J8-12, can be PWM channel 0 in ALT FUN 5 */
- RPI_BPLUS_GPIO_J8_13 = 27, /*!< B+, Pin J8-13 */
- RPI_BPLUS_GPIO_J8_15 = 22, /*!< B+, Pin J8-15 */
- RPI_BPLUS_GPIO_J8_16 = 23, /*!< B+, Pin J8-16 */
- RPI_BPLUS_GPIO_J8_18 = 24, /*!< B+, Pin J8-18 */
- RPI_BPLUS_GPIO_J8_19 = 10, /*!< B+, Pin J8-19, MOSI when SPI0 in use */
- RPI_BPLUS_GPIO_J8_21 = 9, /*!< B+, Pin J8-21, MISO when SPI0 in use */
- RPI_BPLUS_GPIO_J8_22 = 25, /*!< B+, Pin J8-22 */
- RPI_BPLUS_GPIO_J8_23 = 11, /*!< B+, Pin J8-23, CLK when SPI0 in use */
- RPI_BPLUS_GPIO_J8_24 = 8, /*!< B+, Pin J8-24, CE0 when SPI0 in use */
- RPI_BPLUS_GPIO_J8_26 = 7, /*!< B+, Pin J8-26, CE1 when SPI0 in use */
- RPI_BPLUS_GPIO_J8_29 = 5, /*!< B+, Pin J8-29, */
- RPI_BPLUS_GPIO_J8_31 = 6, /*!< B+, Pin J8-31, */
- RPI_BPLUS_GPIO_J8_32 = 12, /*!< B+, Pin J8-32, */
- RPI_BPLUS_GPIO_J8_33 = 13, /*!< B+, Pin J8-33, */
- RPI_BPLUS_GPIO_J8_35 = 19, /*!< B+, Pin J8-35, can be PWM channel 1 in ALT FUN 5 */
- RPI_BPLUS_GPIO_J8_36 = 16, /*!< B+, Pin J8-36, */
- RPI_BPLUS_GPIO_J8_37 = 26, /*!< B+, Pin J8-37, */
- RPI_BPLUS_GPIO_J8_38 = 20, /*!< B+, Pin J8-38, */
- RPI_BPLUS_GPIO_J8_40 = 21 /*!< B+, Pin J8-40, */
-} RPiGPIOPin;
-
-/* Defines for AUX
- GPIO register offsets from BCM2835_AUX_BASE.
-*/
-#define BCM2835_AUX_IRQ 0x0000 /*!< xxx */
-#define BCM2835_AUX_ENABLE 0x0004 /*!< */
-
-#define BCM2835_AUX_ENABLE_UART1 0x01 /*!< */
-#define BCM2835_AUX_ENABLE_SPI0 0x02 /*!< SPI0 (SPI1 in the device) */
-#define BCM2835_AUX_ENABLE_SPI1 0x04 /*!< SPI1 (SPI2 in the device) */
-
-
-#define BCM2835_AUX_SPI_CNTL0 0x0000 /*!< */
-#define BCM2835_AUX_SPI_CNTL1 0x0004 /*!< */
-#define BCM2835_AUX_SPI_STAT 0x0008 /*!< */
-#define BCM2835_AUX_SPI_PEEK 0x000C /*!< Read but do not take from FF */
-#define BCM2835_AUX_SPI_IO 0x0020 /*!< Write = TX, read=RX */
-#define BCM2835_AUX_SPI_TXHOLD 0x0030 /*!< Write = TX keep CS, read=RX */
-
-#define BCM2835_AUX_SPI_CLOCK_MIN 30500 /*!< 30,5kHz */
-#define BCM2835_AUX_SPI_CLOCK_MAX 125000000 /*!< 125Mhz */
-
-#define BCM2835_AUX_SPI_CNTL0_SPEED 0xFFF00000 /*!< */
-#define BCM2835_AUX_SPI_CNTL0_SPEED_MAX 0xFFF /*!< */
-#define BCM2835_AUX_SPI_CNTL0_SPEED_SHIFT 20 /*!< */
-
-#define BCM2835_AUX_SPI_CNTL0_CS0_N 0x000C0000 /*!< CS 0 low */
-#define BCM2835_AUX_SPI_CNTL0_CS1_N 0x000A0000 /*!< CS 1 low */
-#define BCM2835_AUX_SPI_CNTL0_CS2_N 0x00060000 /*!< CS 2 low */
-
-#define BCM2835_AUX_SPI_CNTL0_POSTINPUT 0x00010000 /*!< */
-#define BCM2835_AUX_SPI_CNTL0_VAR_CS 0x00008000 /*!< */
-#define BCM2835_AUX_SPI_CNTL0_VAR_WIDTH 0x00004000 /*!< */
-#define BCM2835_AUX_SPI_CNTL0_DOUTHOLD 0x00003000 /*!< */
-#define BCM2835_AUX_SPI_CNTL0_ENABLE 0x00000800 /*!< */
-#define BCM2835_AUX_SPI_CNTL0_CPHA_IN 0x00000400 /*!< */
-#define BCM2835_AUX_SPI_CNTL0_CLEARFIFO 0x00000200 /*!< */
-#define BCM2835_AUX_SPI_CNTL0_CPHA_OUT 0x00000100 /*!< */
-#define BCM2835_AUX_SPI_CNTL0_CPOL 0x00000080 /*!< */
-#define BCM2835_AUX_SPI_CNTL0_MSBF_OUT 0x00000040 /*!< */
-#define BCM2835_AUX_SPI_CNTL0_SHIFTLEN 0x0000003F /*!< */
-
-#define BCM2835_AUX_SPI_CNTL1_CSHIGH 0x00000700 /*!< */
-#define BCM2835_AUX_SPI_CNTL1_IDLE 0x00000080 /*!< */
-#define BCM2835_AUX_SPI_CNTL1_TXEMPTY 0x00000040 /*!< */
-#define BCM2835_AUX_SPI_CNTL1_MSBF_IN 0x00000002 /*!< */
-#define BCM2835_AUX_SPI_CNTL1_KEEP_IN 0x00000001 /*!< */
-
-#define BCM2835_AUX_SPI_STAT_TX_LVL 0xF0000000 /*!< */
-#define BCM2835_AUX_SPI_STAT_RX_LVL 0x00F00000 /*!< */
-#define BCM2835_AUX_SPI_STAT_TX_FULL 0x00000400 /*!< */
-#define BCM2835_AUX_SPI_STAT_TX_EMPTY 0x00000200 /*!< */
-#define BCM2835_AUX_SPI_STAT_RX_FULL 0x00000100 /*!< */
-#define BCM2835_AUX_SPI_STAT_RX_EMPTY 0x00000080 /*!< */
-#define BCM2835_AUX_SPI_STAT_BUSY 0x00000040 /*!< */
-#define BCM2835_AUX_SPI_STAT_BITCOUNT 0x0000003F /*!< */
-
-/* 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 core clock rate of 250MHz on RPi1 and RPi2, and 400MHz on RPi3.
- It is reported that (contrary to the documentation) any even divider may used.
- The frequencies shown for each divider have been confirmed by measurement on RPi1 and RPi2.
- The system clock frequency on RPi3 is different, so the frequency you get from a given divider will be different.
- See comments in 'SPI Pins' for information about reliable SPI speeds.
- Note: it is possible to change the core clock rate of the RPi 3 back to 250MHz, by putting
- \code
- core_freq=250
- \endcode
- in the config.txt
-*/
-typedef enum
-{
- BCM2835_SPI_CLOCK_DIVIDER_65536 = 0, /*!< 65536 = 3.814697260kHz on Rpi2, 6.1035156kHz on RPI3 */
- BCM2835_SPI_CLOCK_DIVIDER_32768 = 32768, /*!< 32768 = 7.629394531kHz on Rpi2, 12.20703125kHz on RPI3 */
- BCM2835_SPI_CLOCK_DIVIDER_16384 = 16384, /*!< 16384 = 15.25878906kHz on Rpi2, 24.4140625kHz on RPI3 */
- BCM2835_SPI_CLOCK_DIVIDER_8192 = 8192, /*!< 8192 = 30.51757813kHz on Rpi2, 48.828125kHz on RPI3 */
- BCM2835_SPI_CLOCK_DIVIDER_4096 = 4096, /*!< 4096 = 61.03515625kHz on Rpi2, 97.65625kHz on RPI3 */
- BCM2835_SPI_CLOCK_DIVIDER_2048 = 2048, /*!< 2048 = 122.0703125kHz on Rpi2, 195.3125kHz on RPI3 */
- BCM2835_SPI_CLOCK_DIVIDER_1024 = 1024, /*!< 1024 = 244.140625kHz on Rpi2, 390.625kHz on RPI3 */
- BCM2835_SPI_CLOCK_DIVIDER_512 = 512, /*!< 512 = 488.28125kHz on Rpi2, 781.25kHz on RPI3 */
- BCM2835_SPI_CLOCK_DIVIDER_256 = 256, /*!< 256 = 976.5625kHz on Rpi2, 1.5625MHz on RPI3 */
- BCM2835_SPI_CLOCK_DIVIDER_128 = 128, /*!< 128 = 1.953125MHz on Rpi2, 3.125MHz on RPI3 */
- BCM2835_SPI_CLOCK_DIVIDER_64 = 64, /*!< 64 = 3.90625MHz on Rpi2, 6.250MHz on RPI3 */
- BCM2835_SPI_CLOCK_DIVIDER_32 = 32, /*!< 32 = 7.8125MHz on Rpi2, 12.5MHz on RPI3 */
- BCM2835_SPI_CLOCK_DIVIDER_16 = 16, /*!< 16 = 15.625MHz on Rpi2, 25MHz on RPI3 */
- BCM2835_SPI_CLOCK_DIVIDER_8 = 8, /*!< 8 = 31.25MHz on Rpi2, 50MHz on RPI3 */
- BCM2835_SPI_CLOCK_DIVIDER_4 = 4, /*!< 4 = 62.5MHz on Rpi2, 100MHz on RPI3. Dont expect this speed to work reliably. */
- BCM2835_SPI_CLOCK_DIVIDER_2 = 2, /*!< 2 = 125MHz on Rpi2, 200MHz on RPI3, fastest you can get. Dont expect this speed to work reliably.*/
- BCM2835_SPI_CLOCK_DIVIDER_1 = 1 /*!< 1 = 3.814697260kHz on Rpi2, 6.1035156kHz on RPI3, same as 0/65536 */
-} bcm2835SPIClockDivider;
-
-/* Defines for I2C
- GPIO register offsets from BCM2835_BSC*_BASE.
- Offsets into the BSC Peripheral block in bytes per 3.1 BSC Register Map
-*/
-#define BCM2835_BSC_C 0x0000 /*!< BSC Master Control */
-#define BCM2835_BSC_S 0x0004 /*!< BSC Master Status */
-#define BCM2835_BSC_DLEN 0x0008 /*!< BSC Master Data Length */
-#define BCM2835_BSC_A 0x000c /*!< BSC Master Slave Address */
-#define BCM2835_BSC_FIFO 0x0010 /*!< BSC Master Data FIFO */
-#define BCM2835_BSC_DIV 0x0014 /*!< BSC Master Clock Divider */
-#define BCM2835_BSC_DEL 0x0018 /*!< BSC Master Data Delay */
-#define BCM2835_BSC_CLKT 0x001c /*!< BSC Master Clock Stretch Timeout */
-
-/* Register masks for BSC_C */
-#define BCM2835_BSC_C_I2CEN 0x00008000 /*!< I2C Enable, 0 = disabled, 1 = enabled */
-#define BCM2835_BSC_C_INTR 0x00000400 /*!< Interrupt on RX */
-#define BCM2835_BSC_C_INTT 0x00000200 /*!< Interrupt on TX */
-#define BCM2835_BSC_C_INTD 0x00000100 /*!< Interrupt on DONE */
-#define BCM2835_BSC_C_ST 0x00000080 /*!< Start transfer, 1 = Start a new transfer */
-#define BCM2835_BSC_C_CLEAR_1 0x00000020 /*!< Clear FIFO Clear */
-#define BCM2835_BSC_C_CLEAR_2 0x00000010 /*!< Clear FIFO Clear */
-#define BCM2835_BSC_C_READ 0x00000001 /*!< Read transfer */
-
-/* Register masks for BSC_S */
-#define BCM2835_BSC_S_CLKT 0x00000200 /*!< Clock stretch timeout */
-#define BCM2835_BSC_S_ERR 0x00000100 /*!< ACK error */
-#define BCM2835_BSC_S_RXF 0x00000080 /*!< RXF FIFO full, 0 = FIFO is not full, 1 = FIFO is full */
-#define BCM2835_BSC_S_TXE 0x00000040 /*!< TXE FIFO full, 0 = FIFO is not full, 1 = FIFO is full */
-#define BCM2835_BSC_S_RXD 0x00000020 /*!< RXD FIFO contains data */
-#define BCM2835_BSC_S_TXD 0x00000010 /*!< TXD FIFO can accept data */
-#define BCM2835_BSC_S_RXR 0x00000008 /*!< RXR FIFO needs reading (full) */
-#define BCM2835_BSC_S_TXW 0x00000004 /*!< TXW FIFO needs writing (full) */
-#define BCM2835_BSC_S_DONE 0x00000002 /*!< Transfer DONE */
-#define BCM2835_BSC_S_TA 0x00000001 /*!< Transfer Active */
-
-#define BCM2835_BSC_FIFO_SIZE 16 /*!< BSC FIFO size */
-
-/*! \brief bcm2835I2CClockDivider
- Specifies the divider used to generate the I2C clock from the system clock.
- Clock divided is based on nominal base clock rate of 250MHz
-*/
-typedef enum
-{
- BCM2835_I2C_CLOCK_DIVIDER_2500 = 2500, /*!< 2500 = 10us = 100 kHz */
- BCM2835_I2C_CLOCK_DIVIDER_626 = 626, /*!< 622 = 2.504us = 399.3610 kHz */
- BCM2835_I2C_CLOCK_DIVIDER_150 = 150, /*!< 150 = 60ns = 1.666 MHz (default at reset) */
- BCM2835_I2C_CLOCK_DIVIDER_148 = 148 /*!< 148 = 59ns = 1.689 MHz */
-} bcm2835I2CClockDivider;
-
-/*! \brief bcm2835I2CReasonCodes
- Specifies the reason codes for the bcm2835_i2c_write and bcm2835_i2c_read functions.
-*/
-typedef enum
-{
- BCM2835_I2C_REASON_OK = 0x00, /*!< Success */
- BCM2835_I2C_REASON_ERROR_NACK = 0x01, /*!< Received a NACK */
- BCM2835_I2C_REASON_ERROR_CLKT = 0x02, /*!< Received Clock Stretch Timeout */
- BCM2835_I2C_REASON_ERROR_DATA = 0x04 /*!< Not all data is sent / received */
-} bcm2835I2CReasonCodes;
-
-/* Defines for ST
- GPIO register offsets from BCM2835_ST_BASE.
- Offsets into the ST Peripheral block in bytes per 12.1 System Timer Registers
- The System Timer peripheral provides four 32-bit timer channels and a single 64-bit free running counter.
- BCM2835_ST_CLO is the System Timer Counter Lower bits register.
- The system timer free-running counter lower register is a read-only register that returns the current value
- of the lower 32-bits of the free running counter.
- BCM2835_ST_CHI is the System Timer Counter Upper bits register.
- The system timer free-running counter upper register is a read-only register that returns the current value
- of the upper 32-bits of the free running counter.
-*/
-#define BCM2835_ST_CS 0x0000 /*!< System Timer Control/Status */
-#define BCM2835_ST_CLO 0x0004 /*!< System Timer Counter Lower 32 bits */
-#define BCM2835_ST_CHI 0x0008 /*!< System Timer Counter Upper 32 bits */
-
-/*! @} */
-
-
-/* Defines for PWM, word offsets (ie 4 byte multiples) */
-#define BCM2835_PWM_CONTROL 0
-#define BCM2835_PWM_STATUS 1
-#define BCM2835_PWM_DMAC 2
-#define BCM2835_PWM0_RANGE 4
-#define BCM2835_PWM0_DATA 5
-#define BCM2835_PWM_FIF1 6
-#define BCM2835_PWM1_RANGE 8
-#define BCM2835_PWM1_DATA 9
-
-/* Defines for PWM Clock, word offsets (ie 4 byte multiples) */
-#define BCM2835_PWMCLK_CNTL 40
-#define BCM2835_PWMCLK_DIV 41
-#define BCM2835_PWM_PASSWRD (0x5A << 24) /*!< Password to enable setting PWM clock */
-
-#define BCM2835_PWM1_MS_MODE 0x8000 /*!< Run in Mark/Space mode */
-#define BCM2835_PWM1_USEFIFO 0x2000 /*!< Data from FIFO */
-#define BCM2835_PWM1_REVPOLAR 0x1000 /*!< Reverse polarity */
-#define BCM2835_PWM1_OFFSTATE 0x0800 /*!< Ouput Off state */
-#define BCM2835_PWM1_REPEATFF 0x0400 /*!< Repeat last value if FIFO empty */
-#define BCM2835_PWM1_SERIAL 0x0200 /*!< Run in serial mode */
-#define BCM2835_PWM1_ENABLE 0x0100 /*!< Channel Enable */
-
-#define BCM2835_PWM0_MS_MODE 0x0080 /*!< Run in Mark/Space mode */
-#define BCM2835_PWM_CLEAR_FIFO 0x0040 /*!< Clear FIFO */
-#define BCM2835_PWM0_USEFIFO 0x0020 /*!< Data from FIFO */
-#define BCM2835_PWM0_REVPOLAR 0x0010 /*!< Reverse polarity */
-#define BCM2835_PWM0_OFFSTATE 0x0008 /*!< Ouput Off state */
-#define BCM2835_PWM0_REPEATFF 0x0004 /*!< Repeat last value if FIFO empty */
-#define BCM2835_PWM0_SERIAL 0x0002 /*!< Run in serial mode */
-#define BCM2835_PWM0_ENABLE 0x0001 /*!< Channel Enable */
-
-/*! \brief bcm2835PWMClockDivider
- Specifies the divider used to generate the PWM clock from the system clock.
- Figures below give the divider, clock period and clock frequency.
- Clock divided is based on nominal PWM base clock rate of 19.2MHz
- The frequencies shown for each divider have been confirmed by measurement
-*/
-typedef enum
-{
- BCM2835_PWM_CLOCK_DIVIDER_2048 = 2048, /*!< 2048 = 9.375kHz */
- BCM2835_PWM_CLOCK_DIVIDER_1024 = 1024, /*!< 1024 = 18.75kHz */
- BCM2835_PWM_CLOCK_DIVIDER_512 = 512, /*!< 512 = 37.5kHz */
- BCM2835_PWM_CLOCK_DIVIDER_256 = 256, /*!< 256 = 75kHz */
- BCM2835_PWM_CLOCK_DIVIDER_128 = 128, /*!< 128 = 150kHz */
- BCM2835_PWM_CLOCK_DIVIDER_64 = 64, /*!< 64 = 300kHz */
- BCM2835_PWM_CLOCK_DIVIDER_32 = 32, /*!< 32 = 600.0kHz */
- BCM2835_PWM_CLOCK_DIVIDER_16 = 16, /*!< 16 = 1.2MHz */
- BCM2835_PWM_CLOCK_DIVIDER_8 = 8, /*!< 8 = 2.4MHz */
- BCM2835_PWM_CLOCK_DIVIDER_4 = 4, /*!< 4 = 4.8MHz */
- BCM2835_PWM_CLOCK_DIVIDER_2 = 2, /*!< 2 = 9.6MHz, fastest you can get */
- BCM2835_PWM_CLOCK_DIVIDER_1 = 1 /*!< 1 = 4.6875kHz, same as divider 4096 */
-} bcm2835PWMClockDivider;
-
-/* 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 (if you are root)
- or /dev/gpiomem (if you are not)
- 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.
- If bcm2835_init() succeeds but you are not running as root, then only gpio operations
- are permitted, and calling any other functions 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);
-
- /*! Returns the version number of the library, same as BCM2835_VERSION
- \return the current library version number
- */
- extern unsigned int bcm2835_version(void);
-
- /*! @} */
-
- /*! \defgroup lowlevel Low level register access
- These functions provide low level register access, and should not generally
- need to be used
-
- @{
- */
-
- /*! Gets the base of a register
- \param[in] regbase You can use one of the common values BCM2835_REGBASE_*
- in \ref bcm2835RegisterBase
- \return the register base
- \sa Physical Addresses
- */
- extern uint32_t* bcm2835_regbase(uint8_t regbase);
-
- /*! Reads 32 bit value from a peripheral address WITH a memory barrier before and after each read.
- This is safe, but slow. The MB before protects this read from any in-flight reads that didn't
- use a MB. The MB after protects subsequent reads from another peripheral.
-
- \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 barriers
- You should only use this when:
- o your code has previously called bcm2835_peri_read() for a register
- within the same peripheral, and no read or write to another peripheral has occurred since.
- o your code has called bcm2835_memory_barrier() since the last access to ANOTHER peripheral.
-
- \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 WITH a memory barrier before and after each write
- This is safe, but slow. The MB before ensures that any in-flight write to another peripheral
- completes before this write is issued. The MB after ensures that subsequent reads and writes
- to another peripheral will see the effect of this write.
-
- This is a tricky optimization; if you aren't sure, use the barrier version.
-
- \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:
- o your code has previously called bcm2835_peri_write() for a register
- within the same peripheral, and no other peripheral access has occurred since.
- o your code has called bcm2835_memory_barrier() since the last access to ANOTHER peripheral.
-
- This is a tricky optimization; if you aren't sure, use the barrier version.
-
- \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 defines 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.
- Memory barriers are used. Note that this is not atomic; an interrupt
- routine can cause unexpected results.
- \param[in] paddr Physical address to read from. See BCM2835_GPIO_BASE etc.
- \param[in] value The 32 bit value to write, masked in by mask.
- \param[in] mask Bitmask that defines the bits that will be altered in the register.
- \sa Physical Addresses
- */
- extern void bcm2835_peri_set_bits(volatile uint32_t* paddr, uint32_t value, uint32_t mask);
- /*! @} end of lowlevel */
-
- /*! \defgroup gpio GPIO register access
- These functions allow you to control the GPIO interface. You can set the
- function of each GPIO pin, read the input state and set the output state.
- @{
- */
-
- /*! Sets the Function Select register for the given pin, which configures
- the pin as Input, Output or one of the 6 alternate functions.
- \param[in] pin GPIO number, or one of RPI_GPIO_P1_* from \ref RPiGPIOPin.
- \param[in] mode Mode to set the pin to, one of BCM2835_GPIO_FSEL_* from \ref bcm2835FunctionSelect
- */
- extern void bcm2835_gpio_fsel(uint8_t pin, uint8_t mode);
-
- /*! Sets the specified pin output to
- HIGH.
- \param[in] pin GPIO number, or one of RPI_GPIO_P1_* from \ref RPiGPIOPin.
- \sa bcm2835_gpio_write()
- */
- extern void bcm2835_gpio_set(uint8_t pin);
-
- /*! Sets the specified pin output to
- LOW.
- \param[in] pin GPIO number, or one of RPI_GPIO_P1_* from \ref RPiGPIOPin.
- \sa bcm2835_gpio_write()
- */
- extern void bcm2835_gpio_clr(uint8_t pin);
-
- /*! Sets any of the first 32 GPIO output pins specified in the mask to
- HIGH.
- \param[in] mask Mask of pins to affect. Use eg: (1 << RPI_GPIO_P1_03) | (1 << RPI_GPIO_P1_05)
- \sa bcm2835_gpio_write_multi()
- */
- extern void bcm2835_gpio_set_multi(uint32_t mask);
-
- /*! Sets any of the first 32 GPIO output pins specified in the mask to
- LOW.
- \param[in] mask Mask of pins to affect. Use eg: (1 << RPI_GPIO_P1_03) | (1 << RPI_GPIO_P1_05)
- \sa bcm2835_gpio_write_multi()
- */
- extern void bcm2835_gpio_clr_multi(uint32_t mask);
-
- /*! Reads the current level on the specified
- pin and returns either HIGH or LOW. Works whether or not the pin
- is an input or an output.
- \param[in] pin GPIO number, or one of RPI_GPIO_P1_* from \ref RPiGPIOPin.
- \return the current level either HIGH or LOW
- */
- extern uint8_t bcm2835_gpio_lev(uint8_t pin);
-
- /*! Event Detect Status.
- Tests whether the specified pin has detected a level or edge
- as requested by bcm2835_gpio_ren(), bcm2835_gpio_fen(), bcm2835_gpio_hen(),
- bcm2835_gpio_len(), bcm2835_gpio_aren(), bcm2835_gpio_afen().
- Clear the flag for a given pin by calling bcm2835_gpio_set_eds(pin);
- \param[in] pin GPIO number, or one of RPI_GPIO_P1_* from \ref RPiGPIOPin.
- \return HIGH if the event detect status for the given pin is true.
- */
- extern uint8_t bcm2835_gpio_eds(uint8_t pin);
-
- /*! Same as bcm2835_gpio_eds() but checks if any of the pins specified in
- the mask have detected a level or edge.
- \param[in] mask Mask of pins to check. Use eg: (1 << RPI_GPIO_P1_03) | (1 << RPI_GPIO_P1_05)
- \return Mask of pins HIGH if the event detect status for the given pin is true.
- */
- extern uint32_t bcm2835_gpio_eds_multi(uint32_t mask);
-
- /*! 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);
-
- /*! Same as bcm2835_gpio_set_eds() but clears the flag for any pin which
- is set in the mask.
- \param[in] mask Mask of pins to clear. Use eg: (1 << RPI_GPIO_P1_03) | (1 << RPI_GPIO_P1_05)
- */
- extern void bcm2835_gpio_set_eds_multi(uint32_t mask);
-
- /*! 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
- On the RPI 4, although this function and bcm2835_gpio_pudclk() are supported for backward
- compatibility, new code should always use bcm2835_gpio_set_pud().
- \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.
-
- On the RPI 4, although this function and bcm2835_gpio_pud() are supported for backward
- compatibility, new code should always use bcm2835_gpio_set_pud().
-
- \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.
- Caution: requires root access.
- \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.
- Caution: requires root access.
- \param[in] group The GPIO pad group number, one of BCM2835_PAD_GROUP_GPIO_*
- \param[in] control Mask of bits from BCM2835_PAD_* from \ref bcm2835PadGroup. Note
- that it is not necessary to include BCM2835_PAD_PASSWRD in the mask as this
- is automatically included.
- */
- extern void bcm2835_gpio_set_pad(uint8_t group, uint32_t control);
-
- /*! Delays for the specified number of milliseconds.
- Uses nanosleep(), and therefore does not use CPU until the time is up.
- However, you are at the mercy of nanosleep(). From the manual for nanosleep():
- If the interval specified in req is not an exact multiple of the granularity
- underlying clock (see time(7)), then the interval will be
- rounded up to the next multiple. Furthermore, after the sleep completes,
- there may still be a delay before the CPU becomes free to once
- again execute the calling thread.
- \param[in] millis Delay in milliseconds
- */
- extern void bcm2835_delay (unsigned int millis);
-
- /*! Delays for the specified number of microseconds.
- Uses a combination of nanosleep() and a busy wait loop on the BCM2835 system timers,
- However, you are at the mercy of nanosleep(). From the manual for nanosleep():
- If the interval specified in req is not an exact multiple of the granularity
- underlying clock (see time(7)), then the interval will be
- rounded up to the next multiple. Furthermore, after the sleep completes,
- there may still be a delay before the CPU becomes free to once
- again execute the calling thread.
- For times less than about 450 microseconds, uses a busy wait on the System Timer.
- It is reported that a delay of 0 microseconds on RaspberryPi will in fact
- result in a delay of about 80 microseconds. Your mileage may vary.
- \param[in] micros Delay in microseconds
- */
- extern void bcm2835_delayMicroseconds (uint64_t micros);
-
- /*! Sets the output state of the specified pin
- \param[in] pin GPIO number, or one of RPI_GPIO_P1_* from \ref RPiGPIOPin.
- \param[in] on HIGH sets the output to HIGH and LOW to LOW.
- */
- extern void bcm2835_gpio_write(uint8_t pin, uint8_t on);
-
- /*! Sets any of the first 32 GPIO output pins specified in the mask to the state given by on
- \param[in] mask Mask of pins to affect. Use eg: (1 << RPI_GPIO_P1_03) | (1 << RPI_GPIO_P1_05)
- \param[in] on HIGH sets the output to HIGH and LOW to LOW.
- */
- extern void bcm2835_gpio_write_multi(uint32_t mask, uint8_t on);
-
- /*! Sets the first 32 GPIO output pins specified in the mask to the value given by value
- \param[in] value values required for each bit masked in by mask, eg: (1 << RPI_GPIO_P1_03) | (1 << RPI_GPIO_P1_05)
- \param[in] mask Mask of pins to affect. Use eg: (1 << RPI_GPIO_P1_03) | (1 << RPI_GPIO_P1_05)
- */
- extern void bcm2835_gpio_write_mask(uint32_t value, uint32_t mask);
-
- /*! Sets the Pull-up/down mode for the specified pin. This is more convenient than
- clocking the mode in with bcm2835_gpio_pud() and bcm2835_gpio_pudclk().
- \param[in] pin GPIO number, or one of RPI_GPIO_P1_* from \ref RPiGPIOPin.
- \param[in] pud The desired Pull-up/down mode. One of BCM2835_GPIO_PUD_* from bcm2835PUDControl
- */
- extern void bcm2835_gpio_set_pud(uint8_t pin, uint8_t pud);
-
- /*! On the BCM2711 based RPI 4, gets the current Pull-up/down mode for the specified pin.
- Returns one of BCM2835_GPIO_PUD_* from bcm2835PUDControl.
- On earlier RPI versions not based on the BCM2711, returns BCM2835_GPIO_PUD_ERROR
- \param[in] pin GPIO number, or one of RPI_GPIO_P1_* from \ref RPiGPIOPin.
- */
-
- extern uint8_t bcm2835_gpio_get_pud(uint8_t pin);
-
- /*! @} */
-
- /*! \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()
- \return 1 if successful, 0 otherwise (perhaps because you are not running as root)
- */
- extern int 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
- Set the bit order to be used for transmit and receive. The bcm2835 SPI0 only supports BCM2835_SPI_BIT_ORDER_MSB,
- so if you select BCM2835_SPI_BIT_ORDER_LSB, the bytes will be reversed in software.
- The library defaults to BCM2835_SPI_BIT_ORDER_MSB.
- \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 clock divider by converting the speed parameter to
- the equivalent SPI clock divider. ( see \sa bcm2835_spi_setClockDivider)
- \param[in] speed_hz The desired SPI clock speed in Hz
- */
- extern void bcm2835_spi_set_speed_hz(uint32_t speed_hz);
-
- /*! 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 buf buffer, and the number of bytes to send
- */
- extern void bcm2835_spi_writenb(const char* buf, uint32_t len);
-
- /*! Transfers half-word to 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.
- Uses polled transfer as per section 10.6.1 of the BCM 2835 ARM Peripherls manual
- \param[in] data The 8 bit data byte to write to MOSI
- \sa bcm2835_spi_writenb()
- */
- extern void bcm2835_spi_write(uint16_t data);
-
- /*! Start AUX SPI operations.
- Forces RPi AUX SPI pins P1-38 (MOSI), P1-38 (MISO), P1-40 (CLK) and P1-36 (CE2)
- to alternate function ALT4, which enables those pins for SPI interface.
- \return 1 if successful, 0 otherwise (perhaps because you are not running as root)
- */
- extern int bcm2835_aux_spi_begin(void);
-
- /*! End AUX SPI operations.
- SPI1 pins P1-38 (MOSI), P1-38 (MISO), P1-40 (CLK) and P1-36 (CE2)
- are returned to their default INPUT behaviour.
- */
- extern void bcm2835_aux_spi_end(void);
-
- /*! Sets the AUX SPI clock divider and therefore the AUX SPI clock speed.
- \param[in] divider The desired AUX SPI clock divider.
- */
- extern void bcm2835_aux_spi_setClockDivider(uint16_t divider);
-
- /*!
- * Calculates the input for \sa bcm2835_aux_spi_setClockDivider
- * @param speed_hz A value between \sa BCM2835_AUX_SPI_CLOCK_MIN and \sa BCM2835_AUX_SPI_CLOCK_MAX
- * @return Input for \sa bcm2835_aux_spi_setClockDivider
- */
- extern uint16_t bcm2835_aux_spi_CalcClockDivider(uint32_t speed_hz);
-
- /*! Transfers half-word to the AUX SPI slave.
- Asserts the currently selected CS pins during the transfer.
- \param[in] data The 8 bit data byte to write to MOSI
- \return The 16 bit byte simultaneously read from MISO
- \sa bcm2835_spi_transfern()
- */
- extern void bcm2835_aux_spi_write(uint16_t data);
-
- /*! Transfers any number of bytes to the AUX SPI slave.
- Asserts the CE2 pin 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_aux_spi_writenb(const char *buf, uint32_t len);
-
- /*! Transfers any number of bytes to and from the AUX SPI slave
- using bcm2835_aux_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 in the buffer, and the number of bytes to send/received
- \sa bcm2835_aux_spi_transfer()
- */
- extern void bcm2835_aux_spi_transfern(char *buf, uint32_t len);
-
- /*! Transfers any number of bytes to and from the AUX SPI slave.
- Asserts the CE2 pin 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
- \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
- */
- extern void bcm2835_aux_spi_transfernb(const char *tbuf, char *rbuf, uint32_t len);
-
- /*! Transfers one byte to and from the AUX SPI slave.
- Clocks the 8 bit value out on MOSI, and simultaneously clocks in data from MISO.
- Returns the read data byte from the slave.
- \param[in] value The 8 bit data byte to write to MOSI
- \return The 8 bit byte simultaneously read from MISO
- \sa bcm2835_aux_spi_transfern()
- */
- extern uint8_t bcm2835_aux_spi_transfer(uint8_t value);
-
- /*! @} */
-
- /*! \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
- \return 1 if successful, 0 otherwise (perhaps because you are not running as root)
- \sa bcm2835_i2c_end()
- */
- extern int bcm2835_i2c_begin(void);
-
- /*! End I2C operations.
- I2C pins P1-03 (SDA) and P1-05 (SCL)
- are returned to their default INPUT behaviour.
- */
- extern void bcm2835_i2c_end(void);
-
- /*! Sets the I2C slave address.
- \param[in] addr The I2C slave address.
- */
- extern void bcm2835_i2c_setSlaveAddress(uint8_t addr);
-
- /*! Sets the I2C clock divider and therefore the I2C clock speed.
- \param[in] divider The desired I2C clock divider, one of BCM2835_I2C_CLOCK_DIVIDER_*,
- see \ref bcm2835I2CClockDivider
- */
- extern void bcm2835_i2c_setClockDivider(uint16_t divider);
-
- /*! Sets the I2C clock divider by converting the baudrate parameter to
- the equivalent I2C clock divider. ( see \sa bcm2835_i2c_setClockDivider)
- For the I2C standard 100khz you would set baudrate to 100000
- The use of baudrate corresponds to its use in the I2C kernel device
- driver. (Of course, bcm2835 has nothing to do with the kernel driver)
- */
- extern void bcm2835_i2c_set_baudrate(uint32_t baudrate);
-
- /*! Transfers any number of bytes to the currently selected I2C slave.
- (as previously set by \sa bcm2835_i2c_setSlaveAddress)
- \param[in] buf Buffer of bytes to send.
- \param[in] len Number of bytes in the buf buffer, and the number of bytes to send.
- \return reason see \ref bcm2835I2CReasonCodes
- */
- extern uint8_t bcm2835_i2c_write(const char * buf, uint32_t len);
-
- /*! Transfers any number of bytes from the currently selected I2C slave.
- (as previously set by \sa bcm2835_i2c_setSlaveAddress)
- \param[in] buf Buffer of bytes to receive.
- \param[in] len Number of bytes in the buf buffer, and the number of bytes to received.
- \return reason see \ref bcm2835I2CReasonCodes
- */
- extern uint8_t bcm2835_i2c_read(char* buf, uint32_t len);
-
- /*! Allows reading from I2C slaves that require a repeated start (without any prior stop)
- to read after the required slave register has been set. For example, the popular
- MPL3115A2 pressure and temperature sensor. Note that your device must support or
- require this mode. If your device does not require this mode then the standard
- combined:
- \sa bcm2835_i2c_write
- \sa bcm2835_i2c_read
- are a better choice.
- Will read from the slave previously set by \sa bcm2835_i2c_setSlaveAddress
- \param[in] regaddr Buffer containing the slave register you wish to read from.
- \param[in] buf Buffer of bytes to receive.
- \param[in] len Number of bytes in the buf buffer, and the number of bytes to received.
- \return reason see \ref bcm2835I2CReasonCodes
- */
- extern uint8_t bcm2835_i2c_read_register_rs(char* regaddr, char* buf, uint32_t len);
-
- /*! Allows sending an arbitrary number of bytes to I2C slaves before issuing a repeated
- start (with no prior stop) and reading a response.
- Necessary for devices that require such behavior, such as the MLX90620.
- Will write to and read from the slave previously set by \sa bcm2835_i2c_setSlaveAddress
- \param[in] cmds Buffer containing the bytes to send before the repeated start condition.
- \param[in] cmds_len Number of bytes to send from cmds buffer
- \param[in] buf Buffer of bytes to receive.
- \param[in] buf_len Number of bytes to receive in the buf buffer.
- \return reason see \ref bcm2835I2CReasonCodes
- */
- extern uint8_t bcm2835_i2c_write_read_rs(char* cmds, uint32_t cmds_len, char* buf, uint32_t buf_len);
-
- /*! @} */
-
- /*! \defgroup st System Timer access
- Allows access to and delays using the System Timer Counter.
- @{
- */
-
- /*! Read the System Timer Counter register.
- \return the value read from the System Timer Counter Lower 32 bits register
- */
- extern uint64_t bcm2835_st_read(void);
-
- /*! Delays for the specified number of microseconds with offset.
- \param[in] offset_micros Offset in microseconds
- \param[in] micros Delay in microseconds
- */
- extern void bcm2835_st_delay(uint64_t offset_micros, uint64_t micros);
-
- /*! @} */
-
- /*! \defgroup pwm Pulse Width Modulation
- Allows control of 2 independent PWM channels. A limited subset of GPIO pins
- can be connected to one of these 2 channels, allowing PWM control of GPIO pins.
- You have to set the desired pin into a particular Alt Fun to PWM output. See the PWM
- documentation on the Main Page.
- @{
- */
-
- /*! Sets the PWM clock divisor,
- to control the basic PWM pulse widths.
- \param[in] divisor Divides the basic 19.2MHz PWM clock. You can use one of the common
- values BCM2835_PWM_CLOCK_DIVIDER_* in \ref bcm2835PWMClockDivider
- */
- extern void bcm2835_pwm_set_clock(uint32_t divisor);
-
- /*! Sets the mode of the given PWM channel,
- allowing you to control the PWM mode and enable/disable that channel
- \param[in] channel The PWM channel. 0 or 1.
- \param[in] markspace Set true if you want Mark-Space mode. 0 for Balanced mode.
- \param[in] enabled Set true to enable this channel and produce PWM pulses.
- */
- extern void bcm2835_pwm_set_mode(uint8_t channel, uint8_t markspace, uint8_t enabled);
-
- /*! Sets the maximum range of the PWM output.
- The data value can vary between 0 and this range to control PWM output
- \param[in] channel The PWM channel. 0 or 1.
- \param[in] range The maximum value permitted for DATA.
- */
- extern void bcm2835_pwm_set_range(uint8_t channel, uint32_t range);
-
- /*! Sets the PWM pulse ratio to emit to DATA/RANGE,
- where RANGE is set by bcm2835_pwm_set_range().
- \param[in] channel The PWM channel. 0 or 1.
- \param[in] data Controls the PWM output ratio as a fraction of the range.
- Can vary from 0 to RANGE.
- */
- extern void bcm2835_pwm_set_data(uint8_t channel, uint32_t data);
-
- /*! @} */
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* BCM2835_H */
-
-/*! @example blink.c
- Blinks RPi GPIO pin 11 on and off
-*/
-
-/*! @example input.c
- Reads the state of an RPi input pin
-*/
-
-/*! @example event.c
- Shows how to use event detection on an input pin
-*/
-
-/*! @example spi.c
- Shows how to use SPI interface to transfer a byte to and from an SPI device
-*/
-
-/*! @example spin.c
- Shows how to use SPI interface to transfer a number of bytes to and from an SPI device
-*/
-
-/*! @example pwm.c
- Shows how to use PWM to control GPIO pins
-*/
-
-/*! @example i2c.c
-Command line utility for executing i2c commands with the
-Broadcom bcm2835. Contributed by Shahrooz Shahparnia.
-*/
-
-/*! example gpio.c
- Command line utility for executing gpio commands with the
- Broadcom bcm2835. Contributed by Shahrooz Shahparnia.
-*/
-
-/*! example spimem_test.c
- Shows how to use the included little library (spiram.c and spiram.h)
- to read and write SPI RAM chips such as 23K256-I/P
-*/
diff --git a/Makefile b/Makefile
index 77785c6..c12d1ab 100644
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
IDIR=include
TDIR=3rd-party
DEFINES=-DDETERMINISTIC
-CFLAGS=-static -O3 -Wall -Wextra -std=c99 -D_DEFAULT_SOURCE $(DEFINES) -I$(IDIR) -I$(TDIR)
+CFLAGS=-O3 -Wall -Wextra -std=c99 -D_DEFAULT_SOURCE $(DEFINES) -I$(IDIR) -I$(TDIR)
LIBS=
SRCS=$(wildcard include/*.c) $(wildcard 3rd-party/*.c)
diff --git a/buildroot-config b/config-buildroot
index a7ddbd0..a7ddbd0 100644
--- a/buildroot-config
+++ b/config-buildroot
diff --git a/src/ct1986.c b/src/ct1986.c
index 44e64e7..91d70b0 100644
--- a/src/ct1986.c
+++ b/src/ct1986.c
@@ -4,7 +4,8 @@
#include <tak.h>
#include <minimax_cnn1986.h>
-#include <LCDHD44780.h>
+
+FILE *lcd = NULL;
static char *gamelog = 0;
static int human, search_depth;
@@ -37,8 +38,9 @@ static void
end_game(char *line, char *win) {
append_to_gamelog(line, 0);
append_to_gamelog(win, 1);
- write_string("Game over: ");
- write_string(win);
+ fputs("Game over: ",lcd);
+ fputs(win,lcd);
+ fflush(lcd);
}
static int
@@ -47,10 +49,10 @@ handle_turn(char *line) {
uint8_t new_win = (won == 0xFF);
switch (do_ptn(line)) {
// Errors
- case PTN_INVALID: { write_string("Invalid PTN."); return -1; break; }
- case ACT_ILLEGAL: { write_string("Illegal action."); return -1; break; }
+ case PTN_INVALID: { fputs("Invalid PTN.",lcd); return -1; break; }
+ case ACT_ILLEGAL: { fputs("Illegal action.",lcd); return -1; break; }
case ACT_OVERFLOW: {
- write_string("Move would cause internal overflow, select another.");
+ fputs("Move would cause internal overflow, select another.");
return EXIT_FAILURE;
break;
}
@@ -66,7 +68,7 @@ handle_turn(char *line) {
case WIN_ROAD_WHITE: { end_game(line,"R-0"); break; }
}
}
- write_string("Game over, enter `new' to play again.");
+ fputs("Game over, enter `new' to play again.");
if (! new_win) return EXIT_FAILURE;
break;
}
@@ -84,9 +86,10 @@ handle_turn(char *line) {
static void
new_game(uint8_t size) {
reset_state(size);
- write_string("New 5x5 game! ct1986 at search depth ");
- write_to_lcd(search_depth + '0', LCD_DATA);
- write_to_lcd('.', LCD_DATA);
+ fputs("New 5x5 game! ct1986 at search depth ");
+ fputc(search_depth + '0', lcd);
+ fputc('.', lcd);
+ fflush(lcd);
if (gamelog) gamelog = realloc(gamelog, sizeof(char));
else gamelog = malloc(sizeof(char));
gamelog[0] = 0;
@@ -95,24 +98,24 @@ new_game(uint8_t size) {
static void
dot(const uint8_t depth) {
if (depth == 0) {
- write_to_lcd('#', LCD_DATA);
+ fputc('#', lcd);
}
}
static int
ct1986_turn(const uint8_t search_depth) {
// Prepare progress bar
- write_string("Computing ");
+ fputs("Computing ");
// Run the minimax
float minimax = ct1986_generate(search_depth);
// Failed to find a move?
if ((minimax <= -infty && (ply & 1) == 1)
||(minimax >= infty && (ply & 1) == 0)) {
- write_string("Opponent concedes!");
+ fputs("Opponent concedes!");
return EXIT_FAILURE;
} else {
- write_string("Result: ");
- write_string(ct1986_ptn);
+ fputs("Result: ");
+ fputs(ct1986_ptn);
handle_turn(ct1986_ptn);
return EXIT_SUCCESS;
}
@@ -121,10 +124,10 @@ ct1986_turn(const uint8_t search_depth) {
static int
input_is_not_turn(const char *line) {
if (!strcmp(line,"help")) {
- write_string("Valid commands: depth [0-9], help, new, \
+ fputs("Valid commands: depth [0-9], help, new, \
play (b|w), self-play, <PTN>.");
} else if (!strcmp(line,"log")) {
- write_string(gamelog);
+ fputs(gamelog);
} else if (!strcmp(line,"new")) {
new_game(5);
} else if (!strcmp(line,"self-play")) {
@@ -132,10 +135,11 @@ play (b|w), self-play, <PTN>.");
} else if (!strncmp(line,"depth",5)) {
if (strnlen(line,7) == 7 && line[6] >= '0' && line[6] <= '9') {
search_depth = line[6] - '0';
- write_string("New search depth: ");
- write_to_lcd(line[6], LCD_DATA);
+ fputs("New search depth: ",lcd);
+ fputc(line[6], lcd);
+ fflush(lcd);
} else {
- write_string("Usage: depth [0-9].");
+ fputs("Usage: depth [0-9].",lcd);
}
} else if (!strncmp(line,"play",4)) {
if (strnlen(line,7) == 6
@@ -145,7 +149,7 @@ play (b|w), self-play, <PTN>.");
human = 1 - (line[5] & 1);
new_game(5);
} else {
- write_string("Usage: play (b|w).\n");
+ fputs("Usage: play (b|w).\n", lcd);
}
} else {
return EXIT_FAILURE;
@@ -158,9 +162,8 @@ main(int argc, char **argv) {
(void)(argc);
(void)(argv);
- puts("Init.");
- init_lcd();
- puts("Starting up.");
+ lcd = fopen("/dev/lcd","w");
+ if (lcd == NULL) return EXIT_FAILURE;
// Set up output function for ct1986
ct1986_display_progress = &dot;
@@ -174,7 +177,7 @@ main(int argc, char **argv) {
size_t alloc_size;
for (int playing = 1; playing;) {
- write_string("Welcome to ct1986!");
+ fputs("Welcome to ct1986!\n",lcd); fflush(lcd);
fflush(stdout);
while ((human == 0) && (read = getline(&line, &alloc_size, stdin)) != -1) {
if (read) {