diff --git a/gpio/gpio.c b/gpio/gpio.c index 714e790..dc6528a 100644 --- a/gpio/gpio.c +++ b/gpio/gpio.c @@ -173,40 +173,6 @@ static void changeOwner (char *cmd, char *file) /* - * moduleLoaded: - * Return true/false if the supplied module is loaded - ********************************************************************************* - */ - -static int moduleLoaded (char *modName) -{ - int len = strlen (modName) ; - int found = FALSE ; - FILE *fd = fopen ("/proc/modules", "r") ; - char line [80] ; - - if (fd == NULL) - { - fprintf (stderr, "gpio: Unable to check /proc/modules: %s\n", strerror (errno)) ; - exit (1) ; - } - - while (fgets (line, 80, fd) != NULL) - { - if (strncmp (line, modName, len) != 0) - continue ; - - found = TRUE ; - break ; - } - - fclose (fd) ; - - return found ; -} - - -/* * doLoad: * Load either the spi or i2c modules and change device ownerships, etc. ********************************************************************************* @@ -812,6 +778,7 @@ static void doPadDrive (int argc, char *argv []) static void doUsbP (int argc, char *argv []) { +/* int model, rev, mem, maker, overVolted ; if (argc != 3) @@ -852,6 +819,8 @@ static void doUsbP (int argc, char *argv []) fprintf (stderr, "Usage: %s usbp high|low\n", argv [0]) ; exit (1) ; + */ + return; } @@ -1417,7 +1386,7 @@ int main (int argc, char *argv []) for (i = 2 ; i < argc ; ++i) argv [i - 1] = argv [i] ; --argc ; - wpMode = WPI_MODE_GPIO ; + wpMode = MODE_GPIO ; } // Check for -1 argument @@ -1429,7 +1398,7 @@ int main (int argc, char *argv []) for (i = 2 ; i < argc ; ++i) argv [i - 1] = argv [i] ; --argc ; - wpMode = WPI_MODE_PHYS ; + wpMode = MODE_PHYS ; } // Check for -p argument for PiFace @@ -1441,7 +1410,7 @@ int main (int argc, char *argv []) for (i = 2 ; i < argc ; ++i) argv [i - 1] = argv [i] ; --argc ; - wpMode = WPI_MODE_PIFACE ; + wpMode = MODE_PIFACE ; } // Check for -z argument so we don't actually initialise wiringPi @@ -1451,7 +1420,7 @@ int main (int argc, char *argv []) for (i = 2 ; i < argc ; ++i) argv [i - 1] = argv [i] ; --argc ; - wpMode = WPI_MODE_UNINITIALISED ; + wpMode = MODE_UNINITIALISED ; } // Default to wiringPi mode @@ -1459,7 +1428,7 @@ int main (int argc, char *argv []) else { wiringPiSetup () ; - wpMode = WPI_MODE_PINS ; + wpMode = MODE_PINS ; } // Check for -x argument to load in a new extension diff --git a/gpio/readall.c b/gpio/readall.c index 9396c6d..70f1b1f 100644 --- a/gpio/readall.c +++ b/gpio/readall.c @@ -77,9 +77,14 @@ static void doReadallExternal (void) static char *alts [] = { - "IN", "OUT", "ALT5", "ALT4", "ALT0", "ALT1", "ALT2", "ALT3" + "IN", "OUT", "ALT0", "ALT1", "ALT2", "ALT3", "ALT4", "ALT5" } ; +static const char *pupd [] = +{ + "DSBLD", "P/U", "P/D" +}; + static int physToWpi [64] = { -1, // 0 @@ -113,283 +118,249 @@ static int physToWpi [64] = -1, -1, -1, -1, -1, -1, -1, -1, -1 } ; -static char *physNames [64] = +/*------------------------------------------------------------------------------------------*/ +static const char *physNamesKhadasVim1[64] = { + NULL, + " 5V","GND ", + " 5V","PIN.DV25", + " HUB_DM1","PIN.DV24", + " HUB_DP1","GND ", + " GND","PIN.DV27", + " 5V","PIN.DV26", + " HUB_DM2","3.3V ", + " HUB_DP2","GND ", + " GND","PIN.H7 ", + " ADC.CH0","PIN.H6 ", + " GND","PIN.H9 ", + " ADC.CH2","PIN.H8 ", + " SPDIF","PIN.AO6 ", + " GND","GND ", + " PIN.AO5","PIN.AO3 ", + " PIN.AO4","RTC_CLK ", + " GND","PIN.H5 ", + " PIN.AO1","PWR_EN ", + " PIN.AO2","PWM_F ", + " 3.3V","GND ", + NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL, + NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL, + NULL,NULL,NULL, +}; + +static const char *physNamesKhadasVim2[64] = { + NULL, + " 5V","GND ", + " 5v","PIN.DV25", + " USB_DM","PIN.DV24", + " USB_DP","GND ", + " GND","PIN.DV27", + "PIN.DV21","PIN.DV26", + "PIN.DV22","3.3V ", + "PIN.DV23","GND ", + " GND","PIN.H7 ", + " ADC0","PIN.H6 ", + " 1.8V","PIN.H9 ", + " ADC1","PIN.H8 ", + " SPDIF","PIN.AO6 ", + " GND","GND ", + " PIN.AO5","PIN.DV29", + " PIN.AO4","RTC_CLK ", + " GND","PIN.H5 ", + " PIN.AO1","EXP_INT ", + " PIN.AO0","PIN.DV13", + " 3.3v","GND ", + //Not used + NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL, + NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL, + NULL,NULL,NULL, +}; + +static const char *physNamesKhadasVim3[64] = { + NULL, + " 5V","GND ", + " 5V","PIN.A15 ", + " USB_DM","PIN.A14 ", + " USB_DP","GND ", + " GND","PIN.AO2 ", + " MCU3V3","PIN.AO3 ", + " MCUNRST","3V3 ", + " MCUSWIM","GND ", + " GND","PIN.A1 ", + " ADC0","PIN.A0 ", + " 1V8","PIN.A3 ", + " ADC1","PIN.A2 ", + " SPDIF","PIN.A4 ", + " GND3","GND ", + " PIN.H6","PWM-F ", + " PIN.H7","RTC ", + " GND","PIN.H4 ", + " PIN.AO1","MCU-FA1 ", + " PIN.AO0","PIN.Z15 ", + " 3V3","GND ", + //Not used + NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL, + NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL, + NULL,NULL,NULL, +}; + + +static void readallPhysKhadas (int model, int rev, int physPin, const char *physNames[]) { - NULL, - - " 3.3v", "5v ", - " SDA.1", "5v ", - " SCL.1", "0v ", - "GPIO. 7", "TxD ", - " 0v", "RxD ", - "GPIO. 0", "GPIO. 1", - "GPIO. 2", "0v ", - "GPIO. 3", "GPIO. 4", - " 3.3v", "GPIO. 5", - " MOSI", "0v ", - " MISO", "GPIO. 6", - " SCLK", "CE0 ", - " 0v", "CE1 ", - " SDA.0", "SCL.0 ", - "GPIO.21", "0v ", - "GPIO.22", "GPIO.26", - "GPIO.23", "0v ", - "GPIO.24", "GPIO.27", - "GPIO.25", "GPIO.28", - " 0v", "GPIO.29", - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - "GPIO.17", "GPIO.18", - "GPIO.19", "GPIO.20", - NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL, -} ; - - -/* - * readallPhys: - * Given a physical pin output the data on it and the next pin: - *| BCM | wPi | Name | Mode | Val| Physical |Val | Mode | Name | wPi | BCM | - ********************************************************************************* - */ - -static void readallPhys (int physPin) -{ - int pin ; - - if (physPinToGpio (physPin) == -1) - printf (" | | ") ; - else - printf (" | %3d | %3d", physPinToGpio (physPin), physToWpi [physPin]) ; - - printf (" | %s", physNames [physPin]) ; - - if (physToWpi [physPin] == -1) - printf (" | | ") ; - else - { - /**/ if (wpMode == WPI_MODE_GPIO) - pin = physPinToGpio (physPin) ; - else if (wpMode == WPI_MODE_PHYS) - pin = physPin ; - else - pin = physToWpi [physPin] ; - - printf (" | %4s", alts [getAlt (pin)]) ; - printf (" | %d", digitalRead (pin)) ; - } - -// Pin numbers: - - printf (" | %2d", physPin) ; - ++physPin ; - printf (" || %-2d", physPin) ; - -// Same, reversed - - if (physToWpi [physPin] == -1) - printf (" | | ") ; - else - { - /**/ if (wpMode == WPI_MODE_GPIO) - pin = physPinToGpio (physPin) ; - else if (wpMode == WPI_MODE_PHYS) - pin = physPin ; - else - pin = physToWpi [physPin] ; - - printf (" | %d", digitalRead (pin)) ; - printf (" | %-4s", alts [getAlt (pin)]) ; - } - - printf (" | %-5s", physNames [physPin]) ; - - if (physToWpi [physPin] == -1) - printf (" | | ") ; - else - printf (" | %-3d | %-3d", physToWpi [physPin], physPinToGpio (physPin)) ; - - printf (" |\n") ; + int pin; + + //GPIO, wPi pin number + if ((physPinToGpio (physPin) == -1) && (physToWpi [physPin] == -1)) + printf (" | | ") ; + else if (physPinToGpio (physPin) != -1) + printf (" | %3d | %3d", physPinToGpio (physPin), physToWpi [physPin]); + else + printf (" | | %3d", physToWpi [physPin]); + + // GPIO pin name + printf (" | %s", physNames [physPin]); + + // GPIO pin mode, value, drive strength, pupd + if ((physToWpi [physPin] == -1) || (physPinToGpio (physPin) == -1)){ + printf (" | | | | ") ; + } + + else { + if (wpMode == MODE_GPIO) + pin = physPinToGpio (physPin); + else if(wpMode == MODE_PHYS) + pin = physPin; + else{ + pin = physToWpi [physPin]; + } + printf (" | %4s", alts [getAlt (pin)]); + printf (" | %d", digitalRead (pin)); + switch(model) { + case MODEL_KHADAS_VIM1: + case MODEL_KHADAS_VIM2: + case MODEL_KHADAS_VIM3: + printf (" | | %5s", pupd[getPUPD(pin)]); + break; + default: + break; + } + } + + // Physical pin number + printf (" | %2d", physPin); + ++physPin; + printf (" || %-2d", physPin); + + // GPIO pin mode, value, drive strength, pupd + if ((physToWpi [physPin] == -1) || (physPinToGpio (physPin) == -1)) + printf (" | | | | "); + else { + if(wpMode == MODE_GPIO) + pin = physPinToGpio (physPin); + else if(wpMode == MODE_PHYS) + pin = physPin; + else + pin = physToWpi [physPin]; + + switch(model){ + case MODEL_KHADAS_VIM1: + case MODEL_KHADAS_VIM2: + case MODEL_KHADAS_VIM3: + printf (" | %-5s | ", pupd[getPUPD(pin)]); + break; + default: + break; + } + printf (" | %d", digitalRead (pin)); + printf (" | %-4s", alts [getAlt (pin)]); + } + + // GPIO pin name + printf (" | %-6s", physNames [physPin]); + + //GPIO, wPi pin number + if ((physPinToGpio (physPin) == -1) && (physToWpi [physPin] == -1)) + printf (" | | ") ; + else if(physPinToGpio (physPin) != -1) + printf (" | %-3d | %-3d", physToWpi [physPin], physPinToGpio (physPin)); + else + printf (" | %-3d | ", physToWpi [physPin]); + + printf (" |\n") ; } - -/* - * allReadall: - * Read all the pins regardless of the model. Primarily of use for - * the compute module, but handy for other fiddling... - ********************************************************************************* - */ - -static void allReadall (void) +/*--------------------------------------------------------------------------------------*/ +void ReadallKhadas(int model, int rev, const char *physNames[]) { - int pin ; - - printf ("+-----+------+-------+ +-----+------+-------+\n") ; - printf ("| Pin | Mode | Value | | Pin | Mode | Value |\n") ; - printf ("+-----+------+-------+ +-----+------+-------+\n") ; - - for (pin = 0 ; pin < 27 ; ++pin) - { - printf ("| %3d ", pin) ; - printf ("| %-4s ", alts [getAlt (pin)]) ; - printf ("| %s ", digitalRead (pin) == HIGH ? "High" : "Low ") ; - printf ("| ") ; - printf ("| %3d ", pin + 27) ; - printf ("| %-4s ", alts [getAlt (pin + 27)]) ; - printf ("| %s ", digitalRead (pin + 27) == HIGH ? "High" : "Low ") ; - printf ("|\n") ; - } - - printf ("+-----+------+-------+ +-----+------+-------+\n") ; + int pin; + printf (" | GPIO | wPi | Name | Mode | V | DS | PU/PD | Physical | PU/PD | DS | V | Mode | Name | wPi | GPIO |\n"); + printf (" +------+-----+----------+------+---+----+-------+----++----+-------+----+---+------+----------+-----+------+\n"); + for (pin = 1 ; pin <= 40 ; pin += 2) + readallPhysKhadas (model, rev, pin, physNames); + printf (" +------+-----+----------+------+---+----+-------+----++----+-------+----+---+------+----------+-----+------+\n"); } - -/* - * abReadall: - * Read all the pins on the model A or B. - ********************************************************************************* - */ - -void abReadall (int model, int rev) +/*--------------------------------------------------------------------------------------*/ +/* doReadall */ +/* Read all the GPIO pins */ +/* We also want to use this to read the state of pins on an externally */ +/* connected device, so we need to do some fiddling with the internal */ +/* wiringPi node structures - since the gpio command can only use */ +/* one external device at a time, we'll use that to our advantage... */ +/*--------------------------------------------------------------------------------------*/ +void doReadall(void) { - int pin ; - char *type ; - - if (model == PI_MODEL_A) - type = " A" ; - else - if (rev == PI_VERSION_2) - type = "B2" ; - else - type = "B1" ; - - printf (" +-----+-----+---------+------+---+-Model %s-+---+------+---------+-----+-----+\n", type) ; - printf (" | BCM | wPi | Name | Mode | V | Physical | V | Mode | Name | wPi | BCM |\n") ; - printf (" +-----+-----+---------+------+---+----++----+---+------+---------+-----+-----+\n") ; - for (pin = 1 ; pin <= 26 ; pin += 2) - readallPhys (pin) ; - - if (rev == PI_VERSION_2) // B version 2 - { - printf (" +-----+-----+---------+------+---+----++----+---+------+---------+-----+-----+\n") ; - for (pin = 51 ; pin <= 54 ; pin += 2) - readallPhys (pin) ; - } - - printf (" +-----+-----+---------+------+---+----++----+---+------+---------+-----+-----+\n") ; - printf (" | BCM | wPi | Name | Mode | V | Physical | V | Mode | Name | wPi | BCM |\n") ; - printf (" +-----+-----+---------+------+---+-Model %s-+---+------+---------+-----+-----+\n", type) ; + int model, rev, mem, maker, overVolted; + + const char **physNames; + + // External readall + if (wiringPiNodes != NULL) { + doReadallExternal (); + return; + } + + piBoardId(&model, &rev, &mem, &maker, &overVolted); + + switch(model){ + case MODEL_KHADAS_VIM1: + printf (" +------+-----+----------+------+---+----+---- Model KDADAS-VIM1---+----+---+------+----------+-----+------+\n") ; + physNames = physNamesKhadasVim1; + break; + case MODEL_KHADAS_VIM2: + printf (" +------+-----+----------+------+---+----+---- Model KDADAS-VIM2---+----+---+------+----------+-----+------+\n") ; + physNames = physNamesKhadasVim2; + break; + case MODEL_KHADAS_VIM3: + printf (" +------+-----+----------+------+---+----+---- Model KDADAS-VIM3---+----+---+------+----------+-----+------+\n") ; + physNames = physNamesKhadasVim3; + break; + default: + printf ("Oops - unable to determine board type... model: %d\n", model); + return; + } + ReadallKhadas(model, rev, physNames); } - -/* - * piPlusReadall: - * Read all the pins on the model A+ or the B+ or actually, all 40-pin Pi's - ********************************************************************************* - */ - -static void plus2header (int model) +/*--------------------------------------------------------------------------------------*/ +/* doAllReadall */ +/* Force reading of all pins regardless of Pi model */ +/*--------------------------------------------------------------------------------------*/ +void doAllReadall(void) { - /**/ if (model == PI_MODEL_AP) - printf (" +-----+-----+---------+------+---+---Pi A+--+---+------+---------+-----+-----+\n") ; - else if (model == PI_MODEL_BP) - printf (" +-----+-----+---------+------+---+---Pi B+--+---+------+---------+-----+-----+\n") ; - else if (model == PI_MODEL_ZERO) - printf (" +-----+-----+---------+------+---+-Pi Zero--+---+------+---------+-----+-----+\n") ; - else if (model == PI_MODEL_ZERO_W) - printf (" +-----+-----+---------+------+---+-Pi ZeroW-+---+------+---------+-----+-----+\n") ; - else if (model == PI_MODEL_2) - printf (" +-----+-----+---------+------+---+---Pi 2---+---+------+---------+-----+-----+\n") ; - else if (model == PI_MODEL_3) - printf (" +-----+-----+---------+------+---+---Pi 3---+---+------+---------+-----+-----+\n") ; - else if (model == PI_MODEL_3P) - printf (" +-----+-----+---------+------+---+---Pi 3+--+---+------+---------+-----+-----+\n") ; - else - printf (" +-----+-----+---------+------+---+---Pi ?---+---+------+---------+-----+-----+\n") ; + doReadall(); } - -static void piPlusReadall (int model) +/*--------------------------------------------------------------------------------------*/ +void doQmode(int argc, char *argv[]) { - int pin ; - - plus2header (model) ; - - printf (" | BCM | wPi | Name | Mode | V | Physical | V | Mode | Name | wPi | BCM |\n") ; - printf (" +-----+-----+---------+------+---+----++----+---+------+---------+-----+-----+\n") ; - for (pin = 1 ; pin <= 40 ; pin += 2) - readallPhys (pin) ; - printf (" +-----+-----+---------+------+---+----++----+---+------+---------+-----+-----+\n") ; - printf (" | BCM | wPi | Name | Mode | V | Physical | V | Mode | Name | wPi | BCM |\n") ; - - plus2header (model) ; -} - - -/* - * doReadall: - * Generic read all pins called from main program. Works out the Pi type - * and calls the appropriate function. - ********************************************************************************* - */ - -void doReadall (void) -{ - int model, rev, mem, maker, overVolted ; - - if (wiringPiNodes != NULL) // External readall - { - doReadallExternal () ; - return ; - } - - piBoardId (&model, &rev, &mem, &maker, &overVolted) ; - - /**/ if ((model == PI_MODEL_A) || (model == PI_MODEL_B)) - abReadall (model, rev) ; - else if ((model == PI_MODEL_BP) || (model == PI_MODEL_AP) || - (model == PI_MODEL_2) || - (model == PI_MODEL_3) || (model == PI_MODEL_3P) || - (model == PI_MODEL_ZERO) || (model == PI_MODEL_ZERO_W)) - piPlusReadall (model) ; - else if ((model == PI_MODEL_CM) || (model == PI_MODEL_CM3)) - allReadall () ; - else - printf ("Oops - unable to determine board type... model: %d\n", model) ; -} - - -/* - * doAllReadall: - * Force reading of all pins regardless of Pi model - ********************************************************************************* - */ - -void doAllReadall (void) -{ - allReadall () ; -} - - -/* - * doQmode: - * Query mode on a pin - ********************************************************************************* - */ - -void doQmode (int argc, char *argv []) -{ - int pin ; - - if (argc != 3) - { - fprintf (stderr, "Usage: %s qmode pin\n", argv [0]) ; - exit (EXIT_FAILURE) ; - } - - pin = atoi (argv [2]) ; - printf ("%s\n", alts [getAlt (pin)]) ; + int pin; + if(argc != 3){ + fprintf (stderr, "Usage: %s qmode pin\n", argv [0]) ; + exit(EXIT_FAILURE); + } + + pin = atoi(argv[2]); + printf("%s\n", alts[getAlt(pin)]); } +/*--------------------------------------------------------------------------------------*/ +/*--------------------------------------------------------------------------------------*/ diff --git a/wiringPi/Makefile b/wiringPi/Makefile index 287fa58..be34f10 100644 --- a/wiringPi/Makefile +++ b/wiringPi/Makefile @@ -61,7 +61,10 @@ SRC = wiringPi.c \ bmp180.c htu21d.c ds18b20.c rht03.c \ drcSerial.c drcNet.c \ pseudoPins.c \ - wpiExtensions.c + wpiExtensions.c \ + khadas_vim1.c \ + khadas_vim2.c \ + khadas_vim3.c HEADERS = $(shell ls *.h) @@ -128,6 +131,11 @@ depend: # DO NOT DELETE +#KHADAS Boards +khadas_vim1.o : wiringPi.h khadas_vim1.h +khadas_vim2.o : wiringPi.h khadas_vim2.h +khadas_vim3.o : wiringPi.h khadas_vim3.h + wiringPi.o: softPwm.h softTone.h wiringPi.h ../version.h wiringSerial.o: wiringSerial.h wiringShift.o: wiringPi.h wiringShift.h diff --git a/wiringPi/rht03.c b/wiringPi/rht03.c index 1129cfd..678b011 100644 --- a/wiringPi/rht03.c +++ b/wiringPi/rht03.c @@ -238,8 +238,8 @@ int rht03Setup (const int pinBase, const int piPin) { struct wiringPiNodeStruct *node ; - if ((piPin & PI_GPIO_MASK) != 0) // Must be an on-board pin - return FALSE ; + //if ((piPin & PI_GPIO_MASK) != 0) // Must be an on-board pin + // return FALSE ; // 2 pins - temperature and humidity diff --git a/wiringPi/wiringPi.c b/wiringPi/wiringPi.c index 586b148..b42f415 100644 --- a/wiringPi/wiringPi.c +++ b/wiringPi/wiringPi.c @@ -1,57 +1,9 @@ -/* - * wiringPi: - * Arduino look-a-like Wiring library for the Raspberry Pi - * Copyright (c) 2012-2017 Gordon Henderson - * Additional code for pwmSetClock by Chris Hall - * - * Thanks to code samples from Gert Jan van Loo and the - * BCM2835 ARM Peripherals manual, however it's missing - * the clock section /grr/mutter/ - *********************************************************************** - * This file is part of wiringPi: - * https://projects.drogon.net/raspberry-pi/wiringpi/ - * - * wiringPi is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * wiringPi 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 Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with wiringPi. - * If not, see . - *********************************************************************** - */ - -// Revisions: -// 19 Jul 2012: -// Moved to the LGPL -// Added an abstraction layer to the main routines to save a tiny -// bit of run-time and make the clode a little cleaner (if a little -// larger) -// Added waitForInterrupt code -// Added piHiPri code -// -// 9 Jul 2012: -// Added in support to use the /sys/class/gpio interface. -// 2 Jul 2012: -// Fixed a few more bugs to do with range-checking when in GPIO mode. -// 11 Jun 2012: -// Fixed some typos. -// Added c++ support for the .h file -// Added a new function to allow for using my "pin" numbers, or native -// GPIO pin numbers. -// Removed my busy-loop delay and replaced it with a call to delayMicroseconds -// -// 02 May 2012: -// Added in the 2 UART pins -// Change maxPins to numPins to more accurately reflect purpose - - +/*--------------------------------------------------------------------------------------*/ +/* */ +/* WiringPi Library for KHADAS */ +/* */ +/*--------------------------------------------------------------------------------------*/ +#define _XOPEN_SOURCE #include #include #include @@ -77,2376 +29,791 @@ #include "wiringPi.h" #include "../version.h" -// Environment Variables - -#define ENV_DEBUG "WIRINGPI_DEBUG" -#define ENV_CODES "WIRINGPI_CODES" -#define ENV_GPIOMEM "WIRINGPI_GPIOMEM" - - -// Extend wiringPi with other pin-based devices and keep track of -// them in this structure - -struct wiringPiNodeStruct *wiringPiNodes = NULL ; - -// BCM Magic - -#define BCM_PASSWORD 0x5A000000 - - -// The BCM2835 has 54 GPIO pins. -// BCM2835 data sheet, Page 90 onwards. -// 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 - the ALT values -// -// 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) - -// Port function select bits - -#define FSEL_INPT 0b000 -#define FSEL_OUTP 0b001 -#define FSEL_ALT0 0b100 -#define FSEL_ALT1 0b101 -#define FSEL_ALT2 0b110 -#define FSEL_ALT3 0b111 -#define FSEL_ALT4 0b011 -#define FSEL_ALT5 0b010 - -// Access from ARM Running Linux -// Taken from Gert/Doms code. Some of this is not in the manual -// that I can find )-: -// -// Updates in September 2015 - all now static variables (and apologies for the caps) -// due to the Pi v2, v3, etc. and the new /dev/gpiomem interface - -static volatile unsigned int GPIO_PADS ; -static volatile unsigned int GPIO_CLOCK_BASE ; -static volatile unsigned int GPIO_BASE ; -static volatile unsigned int GPIO_TIMER ; -static volatile unsigned int GPIO_PWM ; - -#define PAGE_SIZE (4*1024) -#define BLOCK_SIZE (4*1024) - -static unsigned int usingGpioMem = FALSE ; -static int wiringPiSetuped = FALSE ; - -// PWM -// Word offsets into the PWM control region - -#define PWM_CONTROL 0 -#define PWM_STATUS 1 -#define PWM0_RANGE 4 -#define PWM0_DATA 5 -#define PWM1_RANGE 8 -#define PWM1_DATA 9 - -// Clock regsiter offsets - -#define PWMCLK_CNTL 40 -#define PWMCLK_DIV 41 - -#define PWM0_MS_MODE 0x0080 // Run in MS mode -#define PWM0_USEFIFO 0x0020 // Data from FIFO -#define PWM0_REVPOLAR 0x0010 // Reverse polarity -#define PWM0_OFFSTATE 0x0008 // Ouput Off state -#define PWM0_REPEATFF 0x0004 // Repeat last value if FIFO empty -#define PWM0_SERIAL 0x0002 // Run in serial mode -#define PWM0_ENABLE 0x0001 // Channel Enable - -#define PWM1_MS_MODE 0x8000 // Run in MS mode -#define PWM1_USEFIFO 0x2000 // Data from FIFO -#define PWM1_REVPOLAR 0x1000 // Reverse polarity -#define PWM1_OFFSTATE 0x0800 // Ouput Off state -#define PWM1_REPEATFF 0x0400 // Repeat last value if FIFO empty -#define PWM1_SERIAL 0x0200 // Run in serial mode -#define PWM1_ENABLE 0x0100 // Channel Enable - -// Timer -// Word offsets - -#define TIMER_LOAD (0x400 >> 2) -#define TIMER_VALUE (0x404 >> 2) -#define TIMER_CONTROL (0x408 >> 2) -#define TIMER_IRQ_CLR (0x40C >> 2) -#define TIMER_IRQ_RAW (0x410 >> 2) -#define TIMER_IRQ_MASK (0x414 >> 2) -#define TIMER_RELOAD (0x418 >> 2) -#define TIMER_PRE_DIV (0x41C >> 2) -#define TIMER_COUNTER (0x420 >> 2) - -// Locals to hold pointers to the hardware - -static volatile unsigned int *gpio ; -static volatile unsigned int *pwm ; -static volatile unsigned int *clk ; -static volatile unsigned int *pads ; -static volatile unsigned int *timer ; -static volatile unsigned int *timerIrqRaw ; - -// Export variables for the hardware pointers - -volatile unsigned int *_wiringPiGpio ; -volatile unsigned int *_wiringPiPwm ; -volatile unsigned int *_wiringPiClk ; -volatile unsigned int *_wiringPiPads ; -volatile unsigned int *_wiringPiTimer ; -volatile unsigned int *_wiringPiTimerIrqRaw ; - - -// Data for use with the boardId functions. -// The order of entries here to correspond with the PI_MODEL_X -// and PI_VERSION_X defines in wiringPi.h -// Only intended for the gpio command - use at your own risk! - -// piGpioBase: -// The base address of the GPIO memory mapped hardware IO - -#define GPIO_PERI_BASE_OLD 0x20000000 -#define GPIO_PERI_BASE_NEW 0x3F000000 - -static volatile unsigned int piGpioBase = 0 ; - -const char *piModelNames [16] = -{ - "Model A", // 0 - "Model B", // 1 - "Model A+", // 2 - "Model B+", // 3 - "Pi 2", // 4 - "Alpha", // 5 - "CM", // 6 - "Unknown07", // 07 - "Pi 3", // 08 - "Pi Zero", // 09 - "CM3", // 10 - "Unknown11", // 11 - "Pi Zero-W", // 12 - "Pi 3+", // 13 - "Unknown14", // 14 - "Unknown15", // 15 -} ; - -const char *piRevisionNames [16] = -{ - "00", - "01", - "02", - "03", - "04", - "05", - "06", - "07", - "08", - "09", - "10", - "11", - "12", - "13", - "14", - "15", -} ; - -const char *piMakerNames [16] = -{ - "Sony", // 0 - "Egoman", // 1 - "Embest", // 2 - "Unknown", // 3 - "Embest", // 4 - "Unknown05", // 5 - "Unknown06", // 6 - "Unknown07", // 7 - "Unknown08", // 8 - "Unknown09", // 9 - "Unknown10", // 10 - "Unknown11", // 11 - "Unknown12", // 12 - "Unknown13", // 13 - "Unknown14", // 14 - "Unknown15", // 15 -} ; - -const int piMemorySize [8] = -{ - 256, // 0 - 512, // 1 - 1024, // 2 - 0, // 3 - 0, // 4 - 0, // 5 - 0, // 6 - 0, // 7 -} ; - -// Time for easy calculations - -static uint64_t epochMilli, epochMicro ; - -// Misc - -static int wiringPiMode = WPI_MODE_UNINITIALISED ; -static volatile int pinPass = -1 ; +#include "khadas_vim1.h" +#include "khadas_vim2.h" +#include "khadas_vim3.h" + +/*--------------------------------------------------------------------------------------*/ +/* Const string define */ +/*--------------------------------------------------------------------------------------*/ + +const char *piModelNames [16] = { + "Unknown", + "KHADAS-VIM1", + "KHADAS-VIM2", + "KHADAS-VIM3", +}; + +const char *piRevisionNames [16] = { + "00", + "01", + "02", + "03", + "04", + "05", + "06", + "07", + "08", + "09", + "10", + "11", + "12", + "13", + "14", + "15", +}; + +const char *piMakerNames [16] = { + "Unknown", + "Amlogic", + "ROCKCHIP", + "Unknown03", + "Unknown04", + "Unknown05", + "Unknown06", + "Unknown07", + "Unknown08", + "Unknown09", + "Unknown10", + "Unknown11", + "Unknown12", + "Unknown13", + "Unknown14", + "Unknown15", +}; + +const int piMemorySize [8] = { + 256, + 512, + 1024, + 2048, + 4096, + 8192, + 0, + 0, +}; + +/*--------------------------------------------------------------------------------------*/ + +//Misc +static volatile int pinPass = -1; static pthread_mutex_t pinMutex ; -// Debugging & Return codes - -int wiringPiDebug = FALSE ; -int wiringPiReturnCodes = FALSE ; - -// Use /dev/gpiomem ? - -int wiringPiTryGpioMem = FALSE ; - -// sysFds: -// Map a file descriptor from the /sys/class/gpio/gpioX/value - -static int sysFds [64] = -{ - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -} ; - -// ISR Data - -static void (*isrFunctions [64])(void) ; - - -// Doing it the Arduino way with lookup tables... -// Yes, it's probably more innefficient than all the bit-twidling, but it -// does tend to make it all a bit clearer. At least to me! - -// pinToGpio: -// Take a Wiring pin (0 through X) and re-map it to the BCM_GPIO pin -// Cope for 3 different board revisions here. - -static int *pinToGpio ; - -// Revision 1, 1.1: - -static int pinToGpioR1 [64] = -{ - 17, 18, 21, 22, 23, 24, 25, 4, // From the Original Wiki - GPIO 0 through 7: wpi 0 - 7 - 0, 1, // I2C - SDA1, SCL1 wpi 8 - 9 - 8, 7, // SPI - CE1, CE0 wpi 10 - 11 - 10, 9, 11, // SPI - MOSI, MISO, SCLK wpi 12 - 14 - 14, 15, // UART - Tx, Rx wpi 15 - 16 - -// Padding: - - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // ... 31 - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // ... 47 - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // ... 63 -} ; - -// Revision 2: - -static int pinToGpioR2 [64] = -{ - 17, 18, 27, 22, 23, 24, 25, 4, // From the Original Wiki - GPIO 0 through 7: wpi 0 - 7 - 2, 3, // I2C - SDA0, SCL0 wpi 8 - 9 - 8, 7, // SPI - CE1, CE0 wpi 10 - 11 - 10, 9, 11, // SPI - MOSI, MISO, SCLK wpi 12 - 14 - 14, 15, // UART - Tx, Rx wpi 15 - 16 - 28, 29, 30, 31, // Rev 2: New GPIOs 8 though 11 wpi 17 - 20 - 5, 6, 13, 19, 26, // B+ wpi 21, 22, 23, 24, 25 - 12, 16, 20, 21, // B+ wpi 26, 27, 28, 29 - 0, 1, // B+ wpi 30, 31 - -// Padding: - - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // ... 47 - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // ... 63 -} ; - - -// physToGpio: -// Take a physical pin (1 through 26) and re-map it to the BCM_GPIO pin -// Cope for 2 different board revisions here. -// Also add in the P5 connector, so the P5 pins are 3,4,5,6, so 53,54,55,56 - -static int *physToGpio ; - -static int physToGpioR1 [64] = -{ - -1, // 0 - -1, -1, // 1, 2 - 0, -1, - 1, -1, - 4, 14, - -1, 15, - 17, 18, - 21, -1, - 22, 23, - -1, 24, - 10, -1, - 9, 25, - 11, 8, - -1, 7, // 25, 26 - - -1, -1, -1, -1, -1, // ... 31 - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // ... 47 - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // ... 63 -} ; - -static int physToGpioR2 [64] = -{ - -1, // 0 - -1, -1, // 1, 2 - 2, -1, - 3, -1, - 4, 14, - -1, 15, - 17, 18, - 27, -1, - 22, 23, - -1, 24, - 10, -1, - 9, 25, - 11, 8, - -1, 7, // 25, 26 - -// B+ - - 0, 1, - 5, -1, - 6, 12, - 13, -1, - 19, 16, - 26, 20, - -1, 21, - -// the P5 connector on the Rev 2 boards: - - -1, -1, - -1, -1, - -1, -1, - -1, -1, - -1, -1, - 28, 29, - 30, 31, - -1, -1, - -1, -1, - -1, -1, - -1, -1, -} ; - -// gpioToGPFSEL: -// Map a BCM_GPIO pin to it's Function Selection -// control port. (GPFSEL 0-5) -// Groups of 10 - 3 bits per Function - 30 bits per port - -static uint8_t gpioToGPFSEL [] = -{ - 0,0,0,0,0,0,0,0,0,0, - 1,1,1,1,1,1,1,1,1,1, - 2,2,2,2,2,2,2,2,2,2, - 3,3,3,3,3,3,3,3,3,3, - 4,4,4,4,4,4,4,4,4,4, - 5,5,5,5,5,5,5,5,5,5, -} ; - - -// gpioToShift -// Define the shift up for the 3 bits per pin in each GPFSEL port - -static uint8_t gpioToShift [] = -{ - 0,3,6,9,12,15,18,21,24,27, - 0,3,6,9,12,15,18,21,24,27, - 0,3,6,9,12,15,18,21,24,27, - 0,3,6,9,12,15,18,21,24,27, - 0,3,6,9,12,15,18,21,24,27, - 0,3,6,9,12,15,18,21,24,27, -} ; +//Debugging & return codes +int wiringPiDebug = FALSE; +int wiringPiReturnCodes = FALSE; +struct libkhadas libwiring; -// gpioToGPSET: -// (Word) offset to the GPIO Set registers for each GPIO pin +/*--------------------------------------------------------------------------------------*/ +/* Return ture/false if the supplied module is loaded */ +/*--------------------------------------------------------------------------------------*/ -static uint8_t gpioToGPSET [] = +int moduleLoaded (char *modName) { - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, -} ; - -// gpioToGPCLR: -// (Word) offset to the GPIO Clear registers for each GPIO pin - -static uint8_t gpioToGPCLR [] = -{ - 10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10, - 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, -} ; - - -// gpioToGPLEV: -// (Word) offset to the GPIO Input level registers for each GPIO pin - -static uint8_t gpioToGPLEV [] = -{ - 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, - 14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14, -} ; - - -#ifdef notYetReady -// gpioToEDS -// (Word) offset to the Event Detect Status - -static uint8_t gpioToEDS [] = -{ - 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, - 17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17, -} ; - -// gpioToREN -// (Word) offset to the Rising edge ENable register - -static uint8_t gpioToREN [] = -{ - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, -} ; - -// gpioToFEN -// (Word) offset to the Falling edgde ENable register - -static uint8_t gpioToFEN [] = -{ - 22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22, - 23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23, -} ; -#endif - - -// GPPUD: -// GPIO Pin pull up/down register - -#define GPPUD 37 - -// gpioToPUDCLK -// (Word) offset to the Pull Up Down Clock regsiter - -static uint8_t gpioToPUDCLK [] = -{ - 38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38, - 39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39, -} ; - - -// gpioToPwmALT -// the ALT value to put a GPIO pin into PWM mode - -static uint8_t gpioToPwmALT [] = -{ - 0, 0, 0, 0, 0, 0, 0, 0, // 0 -> 7 - 0, 0, 0, 0, FSEL_ALT0, FSEL_ALT0, 0, 0, // 8 -> 15 - 0, 0, FSEL_ALT5, FSEL_ALT5, 0, 0, 0, 0, // 16 -> 23 - 0, 0, 0, 0, 0, 0, 0, 0, // 24 -> 31 - 0, 0, 0, 0, 0, 0, 0, 0, // 32 -> 39 - FSEL_ALT0, FSEL_ALT0, 0, 0, 0, FSEL_ALT0, 0, 0, // 40 -> 47 - 0, 0, 0, 0, 0, 0, 0, 0, // 48 -> 55 - 0, 0, 0, 0, 0, 0, 0, 0, // 56 -> 63 -} ; - - -// gpioToPwmPort -// The port value to put a GPIO pin into PWM mode - -static uint8_t gpioToPwmPort [] = -{ - 0, 0, 0, 0, 0, 0, 0, 0, // 0 -> 7 - 0, 0, 0, 0, PWM0_DATA, PWM1_DATA, 0, 0, // 8 -> 15 - 0, 0, PWM0_DATA, PWM1_DATA, 0, 0, 0, 0, // 16 -> 23 - 0, 0, 0, 0, 0, 0, 0, 0, // 24 -> 31 - 0, 0, 0, 0, 0, 0, 0, 0, // 32 -> 39 - PWM0_DATA, PWM1_DATA, 0, 0, 0, PWM1_DATA, 0, 0, // 40 -> 47 - 0, 0, 0, 0, 0, 0, 0, 0, // 48 -> 55 - 0, 0, 0, 0, 0, 0, 0, 0, // 56 -> 63 - -} ; - -// gpioToGpClkALT: -// ALT value to put a GPIO pin into GP Clock mode. -// On the Pi we can really only use BCM_GPIO_4 and BCM_GPIO_21 -// for clocks 0 and 1 respectively, however I'll include the full -// list for completeness - maybe one day... - -#define GPIO_CLOCK_SOURCE 1 - -// gpioToGpClkALT0: - -static uint8_t gpioToGpClkALT0 [] = -{ - 0, 0, 0, 0, FSEL_ALT0, FSEL_ALT0, FSEL_ALT0, 0, // 0 -> 7 - 0, 0, 0, 0, 0, 0, 0, 0, // 8 -> 15 - 0, 0, 0, 0, FSEL_ALT5, FSEL_ALT5, 0, 0, // 16 -> 23 - 0, 0, 0, 0, 0, 0, 0, 0, // 24 -> 31 - FSEL_ALT0, 0, FSEL_ALT0, 0, 0, 0, 0, 0, // 32 -> 39 - 0, 0, FSEL_ALT0, FSEL_ALT0, FSEL_ALT0, 0, 0, 0, // 40 -> 47 - 0, 0, 0, 0, 0, 0, 0, 0, // 48 -> 55 - 0, 0, 0, 0, 0, 0, 0, 0, // 56 -> 63 -} ; - -// gpioToClk: -// (word) Offsets to the clock Control and Divisor register - -static uint8_t gpioToClkCon [] = -{ - -1, -1, -1, -1, 28, 30, 32, -1, // 0 -> 7 - -1, -1, -1, -1, -1, -1, -1, -1, // 8 -> 15 - -1, -1, -1, -1, 28, 30, -1, -1, // 16 -> 23 - -1, -1, -1, -1, -1, -1, -1, -1, // 24 -> 31 - 28, -1, 28, -1, -1, -1, -1, -1, // 32 -> 39 - -1, -1, 28, 30, 28, -1, -1, -1, // 40 -> 47 - -1, -1, -1, -1, -1, -1, -1, -1, // 48 -> 55 - -1, -1, -1, -1, -1, -1, -1, -1, // 56 -> 63 -} ; - -static uint8_t gpioToClkDiv [] = -{ - -1, -1, -1, -1, 29, 31, 33, -1, // 0 -> 7 - -1, -1, -1, -1, -1, -1, -1, -1, // 8 -> 15 - -1, -1, -1, -1, 29, 31, -1, -1, // 16 -> 23 - -1, -1, -1, -1, -1, -1, -1, -1, // 24 -> 31 - 29, -1, 29, -1, -1, -1, -1, -1, // 32 -> 39 - -1, -1, 29, 31, 29, -1, -1, -1, // 40 -> 47 - -1, -1, -1, -1, -1, -1, -1, -1, // 48 -> 55 - -1, -1, -1, -1, -1, -1, -1, -1, // 56 -> 63 -} ; - - -/* - * Functions - ********************************************************************************* - */ - - -/* - * wiringPiFailure: - * Fail. Or not. - ********************************************************************************* - */ - -int wiringPiFailure (int fatal, const char *message, ...) -{ - va_list argp ; - char buffer [1024] ; - - if (!fatal && wiringPiReturnCodes) - return -1 ; + int len = strlen(modName); + int found = FALSE ; + FILE *fd = fopen ("/proc/modules", "r"); + char line [80]; - va_start (argp, message) ; - vsnprintf (buffer, 1023, message, argp) ; - va_end (argp) ; + if (NULL == fd) { + fprintf(stderr, "gpio:Unable to check /proc/modules: %s\n",strerror(errno)); + exit(1); + } - fprintf (stderr, "%s", buffer) ; - exit (EXIT_FAILURE) ; - - return 0 ; -} - - -/* - * setupCheck - * Another sanity check because some users forget to call the setup - * function. Mosty because they need feeding C drip by drip )-: - ********************************************************************************* - */ - -static void setupCheck (const char *fName) -{ - if (!wiringPiSetuped) - { - fprintf (stderr, "%s: You have not called one of the wiringPiSetup\n" - " functions, so I'm aborting your program before it crashes anyway.\n", fName) ; - exit (EXIT_FAILURE) ; - } -} - -/* - * gpioMemCheck: - * See if we're using the /dev/gpiomem interface, if-so then some operations - * can't be done and will crash the Pi. - ********************************************************************************* - */ - -static void usingGpioMemCheck (const char *what) -{ - if (usingGpioMem) - { - fprintf (stderr, "%s: Unable to do this when using /dev/gpiomem. Try sudo?\n", what) ; - exit (EXIT_FAILURE) ; - } -} - - - -/* - * piGpioLayout: - * Return a number representing the hardware revision of the board. - * This is not strictly the board revision but is used to check the - * layout of the GPIO connector - and there are 2 types that we are - * really interested in here. The very earliest Pi's and the - * ones that came after that which switched some pins .... - * - * Revision 1 really means the early Model A and B's. - * Revision 2 is everything else - it covers the B, B+ and CM. - * ... and the Pi 2 - which is a B+ ++ ... - * ... and the Pi 0 - which is an A+ ... - * - * The main difference between the revision 1 and 2 system that I use here - * is the mapping of the GPIO pins. From revision 2, the Pi Foundation changed - * 3 GPIO pins on the (original) 26-way header - BCM_GPIO 22 was dropped and - * replaced with 27, and 0 + 1 - I2C bus 0 was changed to 2 + 3; I2C bus 1. - * - * Additionally, here we set the piModel2 flag too. This is again, nothing to - * do with the actual model, but the major version numbers - the GPIO base - * hardware address changed at model 2 and above (not the Zero though) - * - ********************************************************************************* - */ - -static void piGpioLayoutOops (const char *why) -{ - fprintf (stderr, "Oops: Unable to determine board revision from /proc/cpuinfo\n") ; - fprintf (stderr, " -> %s\n", why) ; - fprintf (stderr, " -> You'd best google the error to find out why.\n") ; -//fprintf (stderr, " -> http://www.raspberrypi.org/phpBB3/viewtopic.php?p=184410#p184410\n") ; - exit (EXIT_FAILURE) ; -} - -int piGpioLayout (void) -{ - FILE *cpuFd ; - char line [120] ; - char *c ; - static int gpioLayout = -1 ; - - if (gpioLayout != -1) // No point checking twice - return gpioLayout ; - - if ((cpuFd = fopen ("/proc/cpuinfo", "r")) == NULL) - piGpioLayoutOops ("Unable to open /proc/cpuinfo") ; - -// Start by looking for the Architecture to make sure we're really running -// on a Pi. I'm getting fed-up with people whinging at me because -// they can't get it to work on weirdFruitPi boards... - - while (fgets (line, 120, cpuFd) != NULL) - if (strncmp (line, "Hardware", 8) == 0) - break ; - - if (strncmp (line, "Hardware", 8) != 0) - piGpioLayoutOops ("No \"Hardware\" line") ; - - if (wiringPiDebug) - printf ("piGpioLayout: Hardware: %s\n", line) ; - -// See if it's BCM2708 or BCM2709 or the new BCM2835. - -// OK. As of Kernel 4.8, we have BCM2835 only, regardless of model. -// However I still want to check because it will trap the cheapskates and rip- -// off merchants who want to use wiringPi on non-Raspberry Pi platforms - which -// I do not support so don't email me your bleating whinges about anything -// other than a genuine Raspberry Pi. - -#ifdef DONT_CARE_ANYMORE - if (! (strstr (line, "BCM2708") || strstr (line, "BCM2709") || strstr (line, "BCM2835"))) - { - fprintf (stderr, "Unable to determine hardware version. I see: %s,\n", line) ; - fprintf (stderr, " - expecting BCM2708, BCM2709 or BCM2835.\n") ; - fprintf (stderr, "If this is a genuine Raspberry Pi then please report this\n") ; - fprintf (stderr, "to projects@drogon.net. If this is not a Raspberry Pi then you\n") ; - fprintf (stderr, "are on your own as wiringPi is designed to support the\n") ; - fprintf (stderr, "Raspberry Pi ONLY.\n") ; - exit (EXIT_FAILURE) ; - } -#endif - -// Actually... That has caused me more than 10,000 emails so-far. Mosty by -// people who think they know better by creating a statically linked -// version that will not run with a new 4.9 kernel. I utterly hate and -// despise those people. -// -// I also get bleats from people running other than Raspbian with another -// distros compiled kernel rather than a foundation compiled kernel, so -// this might actually help them. It might not - I only have the capacity -// to support Raspbian. -// -// However, I've decided to leave this check out and rely purely on the -// Revision: line for now. It will not work on a non-pi hardware or weird -// kernels that don't give you a suitable revision line. - -// So - we're Probably on a Raspberry Pi. Check the revision field for the real -// hardware type -// In-future, I ought to use the device tree as there are now Pi entries in -// /proc/device-tree/ ... -// but I'll leave that for the next revision. Or the next. - -// Isolate the Revision line - - rewind (cpuFd) ; - while (fgets (line, 120, cpuFd) != NULL) - if (strncmp (line, "Revision", 8) == 0) - break ; - - fclose (cpuFd) ; - - if (strncmp (line, "Revision", 8) != 0) - piGpioLayoutOops ("No \"Revision\" line") ; - -// Chomp trailing CR/NL - - for (c = &line [strlen (line) - 1] ; (*c == '\n') || (*c == '\r') ; --c) - *c = 0 ; - - if (wiringPiDebug) - printf ("piGpioLayout: Revision string: %s\n", line) ; - -// Scan to the first character of the revision number - - for (c = line ; *c ; ++c) - if (*c == ':') - break ; - - if (*c != ':') - piGpioLayoutOops ("Bogus \"Revision\" line (no colon)") ; - -// Chomp spaces - - ++c ; - while (isspace (*c)) - ++c ; - - if (!isxdigit (*c)) - piGpioLayoutOops ("Bogus \"Revision\" line (no hex digit at start of revision)") ; - -// Make sure its long enough - - if (strlen (c) < 4) - piGpioLayoutOops ("Bogus revision line (too small)") ; - -// Isolate last 4 characters: (in-case of overvolting or new encoding scheme) - - c = c + strlen (c) - 4 ; - - if (wiringPiDebug) - printf ("piGpioLayout: last4Chars are: \"%s\"\n", c) ; - - if ( (strcmp (c, "0002") == 0) || (strcmp (c, "0003") == 0)) - gpioLayout = 1 ; - else - gpioLayout = 2 ; // Covers everything else from the B revision 2 to the B+, the Pi v2, v3, zero and CM's. - - if (wiringPiDebug) - printf ("piGpioLayoutOops: Returning revision: %d\n", gpioLayout) ; - - return gpioLayout ; -} - -/* - * piBoardRev: - * Deprecated, but does the same as piGpioLayout - ********************************************************************************* - */ - -int piBoardRev (void) -{ - return piGpioLayout () ; + while (NULL != fgets (line, 80, fd)) { + if(0 != strncmp(line,modName, len)) + continue; + found = TRUE; + break; + } + fclose (fd); + return found; } - - -/* - * piBoardId: - * Return the real details of the board we have. - * - * This is undocumented and really only intended for the GPIO command. - * Use at your own risk! - * - * Seems there are some boards with 0000 in them (mistake in manufacture) - * So the distinction between boards that I can see is: - * - * 0000 - Error - * 0001 - Not used - * - * Original Pi boards: - * 0002 - Model B, Rev 1, 256MB, Egoman - * 0003 - Model B, Rev 1.1, 256MB, Egoman, Fuses/D14 removed. - * - * Newer Pi's with remapped GPIO: - * 0004 - Model B, Rev 1.2, 256MB, Sony - * 0005 - Model B, Rev 1.2, 256MB, Egoman - * 0006 - Model B, Rev 1.2, 256MB, Egoman - * - * 0007 - Model A, Rev 1.2, 256MB, Egoman - * 0008 - Model A, Rev 1.2, 256MB, Sony - * 0009 - Model A, Rev 1.2, 256MB, Egoman - * - * 000d - Model B, Rev 1.2, 512MB, Egoman (Red Pi, Blue Pi?) - * 000e - Model B, Rev 1.2, 512MB, Sony - * 000f - Model B, Rev 1.2, 512MB, Egoman - * - * 0010 - Model B+, Rev 1.2, 512MB, Sony - * 0013 - Model B+ Rev 1.2, 512MB, Embest - * 0016 - Model B+ Rev 1.2, 512MB, Sony - * 0019 - Model B+ Rev 1.2, 512MB, Egoman - * - * 0011 - Pi CM, Rev 1.1, 512MB, Sony - * 0014 - Pi CM, Rev 1.1, 512MB, Embest - * 0017 - Pi CM, Rev 1.1, 512MB, Sony - * 001a - Pi CM, Rev 1.1, 512MB, Egoman - * - * 0012 - Model A+ Rev 1.1, 256MB, Sony - * 0015 - Model A+ Rev 1.1, 512MB, Embest - * 0018 - Model A+ Rev 1.1, 256MB, Sony - * 001b - Model A+ Rev 1.1, 256MB, Egoman - * - * A small thorn is the olde style overvolting - that will add in - * 1000000 - * - * The Pi compute module has an revision of 0011 or 0014 - since we only - * check the last digit, then it's 1, therefore it'll default to not 2 or - * 3 for a Rev 1, so will appear as a Rev 2. This is fine for the most part, but - * we'll properly detect the Compute Module later and adjust accordingly. - * - * And then things changed with the introduction of the v2... - * - * For Pi v2 and subsequent models - e.g. the Zero: - * - * [USER:8] [NEW:1] [MEMSIZE:3] [MANUFACTURER:4] [PROCESSOR:4] [TYPE:8] [REV:4] - * NEW 23: will be 1 for the new scheme, 0 for the old scheme - * MEMSIZE 20: 0=256M 1=512M 2=1G - * MANUFACTURER 16: 0=SONY 1=EGOMAN 2=EMBEST - * PROCESSOR 12: 0=2835 1=2836 - * TYPE 04: 0=MODELA 1=MODELB 2=MODELA+ 3=MODELB+ 4=Pi2 MODEL B 5=ALPHA 6=CM - * REV 00: 0=REV0 1=REV1 2=REV2 - ********************************************************************************* - */ - -void piBoardId (int *model, int *rev, int *mem, int *maker, int *warranty) +int msg (int type, const char *message, ...) { - FILE *cpuFd ; - char line [120] ; - char *c ; - unsigned int revision ; - int bRev, bType, bProc, bMfg, bMem, bWarranty ; - -// Will deal with the properly later on - for now, lets just get it going... -// unsigned int modelNum ; - - (void)piGpioLayout () ; // Call this first to make sure all's OK. Don't care about the result. - - if ((cpuFd = fopen ("/proc/cpuinfo", "r")) == NULL) - piGpioLayoutOops ("Unable to open /proc/cpuinfo") ; - - while (fgets (line, 120, cpuFd) != NULL) - if (strncmp (line, "Revision", 8) == 0) - break ; - - fclose (cpuFd) ; - - if (strncmp (line, "Revision", 8) != 0) - piGpioLayoutOops ("No \"Revision\" line") ; - -// Chomp trailing CR/NL - - for (c = &line [strlen (line) - 1] ; (*c == '\n') || (*c == '\r') ; --c) - *c = 0 ; - - if (wiringPiDebug) - printf ("piBoardId: Revision string: %s\n", line) ; - -// Need to work out if it's using the new or old encoding scheme: - -// Scan to the first character of the revision number - - for (c = line ; *c ; ++c) - if (*c == ':') - break ; - - if (*c != ':') - piGpioLayoutOops ("Bogus \"Revision\" line (no colon)") ; - -// Chomp spaces - - ++c ; - while (isspace (*c)) - ++c ; - - if (!isxdigit (*c)) - piGpioLayoutOops ("Bogus \"Revision\" line (no hex digit at start of revision)") ; - - revision = (unsigned int)strtol (c, NULL, 16) ; // Hex number with no leading 0x + va_list argp; + char buffer[1024]; -// Check for new way: + va_start (argp,message); + vsnprintf (buffer, 1023, message, argp); + va_end(argp); - if ((revision & (1 << 23)) != 0) // New way - { - if (wiringPiDebug) - printf ("piBoardId: New Way: revision is: %08X\n", revision) ; + fprintf(stderr, "%s : %s", type == MSG_WARN ? "warn": "err" , buffer); - bRev = (revision & (0x0F << 0)) >> 0 ; - bType = (revision & (0xFF << 4)) >> 4 ; - bProc = (revision & (0x0F << 12)) >> 12 ; // Not used for now. - bMfg = (revision & (0x0F << 16)) >> 16 ; - bMem = (revision & (0x07 << 20)) >> 20 ; - bWarranty = (revision & (0x03 << 24)) != 0 ; - - *model = bType ; - *rev = bRev ; - *mem = bMem ; - *maker = bMfg ; - *warranty = bWarranty ; - - if (wiringPiDebug) - printf ("piBoardId: rev: %d, type: %d, proc: %d, mfg: %d, mem: %d, warranty: %d\n", - bRev, bType, bProc, bMfg, bMem, bWarranty) ; - } - else // Old way - { - if (wiringPiDebug) - printf ("piBoardId: Old Way: revision is: %s\n", c) ; - - if (!isdigit (*c)) - piGpioLayoutOops ("Bogus \"Revision\" line (no digit at start of revision)") ; - -// Make sure its long enough - - if (strlen (c) < 4) - piGpioLayoutOops ("Bogus \"Revision\" line (not long enough)") ; - -// If longer than 4, we'll assume it's been overvolted - - *warranty = strlen (c) > 4 ; - -// Extract last 4 characters: - - c = c + strlen (c) - 4 ; - -// Fill out the replys as appropriate - - /**/ if (strcmp (c, "0002") == 0) { *model = PI_MODEL_B ; *rev = PI_VERSION_1 ; *mem = 0 ; *maker = PI_MAKER_EGOMAN ; } - else if (strcmp (c, "0003") == 0) { *model = PI_MODEL_B ; *rev = PI_VERSION_1_1 ; *mem = 0 ; *maker = PI_MAKER_EGOMAN ; } - - else if (strcmp (c, "0004") == 0) { *model = PI_MODEL_B ; *rev = PI_VERSION_1_2 ; *mem = 0 ; *maker = PI_MAKER_SONY ; } - else if (strcmp (c, "0005") == 0) { *model = PI_MODEL_B ; *rev = PI_VERSION_1_2 ; *mem = 0 ; *maker = PI_MAKER_EGOMAN ; } - else if (strcmp (c, "0006") == 0) { *model = PI_MODEL_B ; *rev = PI_VERSION_1_2 ; *mem = 0 ; *maker = PI_MAKER_EGOMAN ; } - - else if (strcmp (c, "0007") == 0) { *model = PI_MODEL_A ; *rev = PI_VERSION_1_2 ; *mem = 0 ; *maker = PI_MAKER_EGOMAN ; } - else if (strcmp (c, "0008") == 0) { *model = PI_MODEL_A ; *rev = PI_VERSION_1_2 ; *mem = 0 ; *maker = PI_MAKER_SONY ; ; } - else if (strcmp (c, "0009") == 0) { *model = PI_MODEL_A ; *rev = PI_VERSION_1_2 ; *mem = 0 ; *maker = PI_MAKER_EGOMAN ; } - - else if (strcmp (c, "000d") == 0) { *model = PI_MODEL_B ; *rev = PI_VERSION_1_2 ; *mem = 1 ; *maker = PI_MAKER_EGOMAN ; } - else if (strcmp (c, "000e") == 0) { *model = PI_MODEL_B ; *rev = PI_VERSION_1_2 ; *mem = 1 ; *maker = PI_MAKER_SONY ; } - else if (strcmp (c, "000f") == 0) { *model = PI_MODEL_B ; *rev = PI_VERSION_1_2 ; *mem = 1 ; *maker = PI_MAKER_EGOMAN ; } - - else if (strcmp (c, "0010") == 0) { *model = PI_MODEL_BP ; *rev = PI_VERSION_1_2 ; *mem = 1 ; *maker = PI_MAKER_SONY ; } - else if (strcmp (c, "0013") == 0) { *model = PI_MODEL_BP ; *rev = PI_VERSION_1_2 ; *mem = 1 ; *maker = PI_MAKER_EMBEST ; } - else if (strcmp (c, "0016") == 0) { *model = PI_MODEL_BP ; *rev = PI_VERSION_1_2 ; *mem = 1 ; *maker = PI_MAKER_SONY ; } - else if (strcmp (c, "0019") == 0) { *model = PI_MODEL_BP ; *rev = PI_VERSION_1_2 ; *mem = 1 ; *maker = PI_MAKER_EGOMAN ; } - - else if (strcmp (c, "0011") == 0) { *model = PI_MODEL_CM ; *rev = PI_VERSION_1_1 ; *mem = 1 ; *maker = PI_MAKER_SONY ; } - else if (strcmp (c, "0014") == 0) { *model = PI_MODEL_CM ; *rev = PI_VERSION_1_1 ; *mem = 1 ; *maker = PI_MAKER_EMBEST ; } - else if (strcmp (c, "0017") == 0) { *model = PI_MODEL_CM ; *rev = PI_VERSION_1_1 ; *mem = 1 ; *maker = PI_MAKER_SONY ; } - else if (strcmp (c, "001a") == 0) { *model = PI_MODEL_CM ; *rev = PI_VERSION_1_1 ; *mem = 1 ; *maker = PI_MAKER_EGOMAN ; } - - else if (strcmp (c, "0012") == 0) { *model = PI_MODEL_AP ; *rev = PI_VERSION_1_1 ; *mem = 0 ; *maker = PI_MAKER_SONY ; } - else if (strcmp (c, "0015") == 0) { *model = PI_MODEL_AP ; *rev = PI_VERSION_1_1 ; *mem = 1 ; *maker = PI_MAKER_EMBEST ; } - else if (strcmp (c, "0018") == 0) { *model = PI_MODEL_AP ; *rev = PI_VERSION_1_1 ; *mem = 0 ; *maker = PI_MAKER_SONY ; } - else if (strcmp (c, "001b") == 0) { *model = PI_MODEL_AP ; *rev = PI_VERSION_1_1 ; *mem = 0 ; *maker = PI_MAKER_EGOMAN ; } - - else { *model = 0 ; *rev = 0 ; *mem = 0 ; *maker = 0 ; } - } + if(type != MSG_WARN) + exit(EXIT_FAILURE); + return 0; } - +/*----------------------------------------------------------------------------------------*/ -/* - * wpiPinToGpio: - * Translate a wiringPi Pin number to native GPIO pin number. - * Provided for external support. - ********************************************************************************* - */ - -int wpiPinToGpio (int wpiPin) +static void warn_msg(const char *func) { - return pinToGpio [wpiPin & 63] ; + msg(MSG_WARN, "(%s):THis function is not supported by KHADAS Board.\n", func); } +/*------------------------------------------------------------------------------------------*/ +/* Unsupport Function list on KHADAs */ +/*------------------------------------------------------------------------------------------*/ +static void piGpioLayoutOps (const char *why) {warn_msg(__func__);return;} +void pwmSetMode (int mode) {warn_msg(__func__);return;} +void pwmSetRange (unsigned int range) {warn_msg(__func__);return;} +void pwmSetClock (int divisor) {warn_msg(__func__);return;} +void gpioClockSet (int pin, int freq) {warn_msg(__func__);return;} -/* - * physPinToGpio: - * Translate a physical Pin number to native GPIO pin number. - * Provided for external support. - ********************************************************************************* - */ +/* core unsupport function */ +void pinModeAlt (int pin, int mode) {warn_msg(__func__);return;} +void pwmWrite (int pin, int value) {warn_msg(__func__);return;} +void analogWrite (int pin, int value) {warn_msg(__func__);return;} +void pwmToneWrite (int pin, int freq) {warn_msg(__func__);return;} +void digitalWriteByte2 (const int vaule) {warn_msg(__func__);return;} +unsigned int digitalReadByte2 (void) {warn_msg(__func__); return -1;} -int physPinToGpio (int physPin) -{ - return physToGpio [physPin & 63] ; -} +/*------------------------------------------------------------------------------------------*/ +/* extend wiringPi with other pin-base devices and keep track of */ +/* them in this structure */ +/*------------------------------------------------------------------------------------------*/ +struct wiringPiNodeStruct *wiringPiNodes = NULL; +struct wiringPiNodeStruct *wiringPiFindNode(int pin) {return NULL;} -/* - * setPadDrive: - * Set the PAD driver value - ********************************************************************************* - */ +static void pinModeDummy (UNU struct wiringPiNodeStruct *node, UNU int pin, UNU int mode) +{return;} +static void pullUpDnControlDummy(UNU struct wiringPiNodeStruct *node, UNU int pin, UNU int pud) +{return;} +static unsigned int digitalRead8Dummy (UNU struct wiringPiNodeStruct *node, UNU int UNU pin) +{return 0;} +static void digitalWrite8Demmy (UNU struct wiringPiNodeStruct *node, UNU int pin,UNU int value) +{return;} +static int digitalReadDummy (UNU struct wiringPiNodeStruct *node, UNU int UNU pin) +{return LOW;} +static void digitalWriteDummy (UNU struct wiringPiNodeStruct *node, UNU int pin, UNU int value){return;} +static void pwmWriteDummy (UNU struct wiringPiNodeStruct *node, UNU int pin, UNU int value) +{return;} +static int analogReadDummy (UNU struct wiringPiNodeStruct *node, UNU int pin) +{return 0;} +static int analogWriteDummy (UNU struct wiringPiNodeStruct *node,UNU int pin, UNU int value) +{return 0;} -void setPadDrive (int group, int value) +struct wiringPiNodeStruct *wiringPiNewNode (int pinBase, int numPins) { - uint32_t wrVal ; - - if ((wiringPiMode == WPI_MODE_PINS) || (wiringPiMode == WPI_MODE_PHYS) || (wiringPiMode == WPI_MODE_GPIO)) - { - if ((group < 0) || (group > 2)) - return ; - - wrVal = BCM_PASSWORD | 0x18 | (value & 7) ; - *(pads + group + 11) = wrVal ; - - if (wiringPiDebug) - { - printf ("setPadDrive: Group: %d, value: %d (%08X)\n", group, value, wrVal) ; - printf ("Read : %08X\n", *(pads + group + 11)) ; - } - } -} + int pin; + struct wiringPiNodeStruct *node; + + //Mininum pin base is 64 + if(pinBase < 64){ + (void)wiringPiFailure(WPI_FATAL, "wiriingPiNode: pinBase of %d is < 64\n", pinBase); + } + //Check all pins in-base there is overlap: + for(pin = pinBase; pin < (pinBase + numPins); ++pin) + if(NULL != wiringPiFindNode(pin)) + (void)wiringPiFailure(WPI_FATAL,"wiringPiNewMode: pin %d overlaps with exising definition\n", pin); + node = (struct wiringPiNodeStruct *)calloc(sizeof(struct wiringPiNodeStruct), 1); + if(NULL == node) + (void)wiringPiFailure(WPI_FATAL, "wiringPiNewNode: Unable to allocate memory: %s\n", strerror(errno)); + + node->pinBase = pinBase; + node->pinMax = pinBase + numPins -1; + node->pinMode = pinModeDummy; + node->pullUpDnControl = pullUpDnControlDummy; + node->digitalRead = digitalReadDummy; + node->pwmWrite = digitalWriteDummy; + node->analogRead = analogReadDummy; + node->analogWrite = analogWriteDummy; + node->next = wiringPiNodes; + wiringPiNodes = node; +// node->digitalWrite8 = digitalWrite8Dummy; +// node->digitalRead8 = digitalRead8Dummy; + + return node; +} + +/*------------------------------------------------------------------------------------------*/ +/* wiringPiFailure : fail or not */ +/*------------------------------------------------------------------------------------------*/ +int wiringPiFailure(int fatal, const char *message, ...) +{ + va_list argp; + char buffer [1024]; + + if(!fatal && wiringPiReturnCodes) + return -1; + + va_start(argp, message); + vsnprintf(buffer, 1023, message, argp); + va_end(argp); + fprintf(stderr, "%s", buffer); + exit(EXIT_FAILURE); + + return 0; +} + +/*------------------------------------------------------------------------------------------*/ +int piGpioLayout(void) +{ + FILE *cpuFd; + char line[120]; + char *c; + static int gpioLayout = -1; + + if(-1 != gpioLayout) + return gpioLayout; + + gpioLayout = 1; + + if(NULL == (cpuFd = fopen("/proc/cpuinfo","r"))) + wiringPiFailure(WPI_FATAL, "Unable to open /proc/cpuinfo"); + + while(NULL != fgets(line, 120, cpuFd)) + if(0 == strncmp(line, "Hardware", 8)) + break; + + if(0 != strncmp(line, "Hardware", 8) != 0) + wiringPiFailure(WPI_FATAL, "No \"Hardware\" line"); + + if(wiringPiDebug) + printf ("piGpioLayout: Hardware: %s\n", line) ; + + if (!(strstr (line, "Khadas"))) + wiringPiFailure (WPI_FATAL, "** This board is not KHADAS. **"); + + rewind(cpuFd); + + gpioLayout = 1; + + if(strstr(line, "VIM3")){ + libwiring.model = MODEL_KHADAS_VIM3; + libwiring.maker = MAKER_AMLOGIC; + libwiring.mem = 2; + libwiring.rev = 1; + }else if(strstr(line, "VIM2")){ + libwiring.model = MODEL_KHADAS_VIM2; + libwiring.maker = MAKER_AMLOGIC; + libwiring.mem = 2; + libwiring.rev = 1; + }else if(strstr(line, "VIM")){ + libwiring.model = MODEL_KHADAS_VIM1; + libwiring.maker = MAKER_AMLOGIC; + libwiring.mem = 2; + libwiring.rev = 1; + }else + printf("MODEL SETUP ERROR\n"); + fclose(cpuFd); + if (wiringPiDebug) + printf ("BoardRev: Returning revision: %d\n", libwiring.rev) ; + + return libwiring.rev; +} + + +/*------------------------------------------------------------------------------------------*/ +int piBoardRev(void) +{ + return piGpioLayout(); +} + +/*------------------------------------------------------------------------------------------*/ +/* piBoradId */ +/* return the real details of the board we have. */ +/*------------------------------------------------------------------------------------------*/ - -/* - * getAlt: - * Returns the ALT bits for a given port. Only really of-use - * for the gpio readall command (I think) - ********************************************************************************* - */ - -int getAlt (int pin) +void piBoardId(int *model, int *rev, int *mem, int *maker, int *warranty) { - int fSel, shift, alt ; - - pin &= 63 ; - - /**/ if (wiringPiMode == WPI_MODE_PINS) - pin = pinToGpio [pin] ; - else if (wiringPiMode == WPI_MODE_PHYS) - pin = physToGpio [pin] ; - else if (wiringPiMode != WPI_MODE_GPIO) - return 0 ; - - fSel = gpioToGPFSEL [pin] ; - shift = gpioToShift [pin] ; - - alt = (*(gpio + fSel) >> shift) & 7 ; - - return alt ; + (void)piGpioLayout (); + *model = libwiring.model; + *maker = libwiring.maker; + *rev = libwiring.rev; + *mem = libwiring.mem; + *warranty = 1; } - -/* - * pwmSetMode: - * Select the native "balanced" mode, or standard mark:space mode - ********************************************************************************* - */ - -void pwmSetMode (int mode) +/*------------------------------------------------------------------------------------------*/ +/* wpPinToGpio */ +/*------------------------------------------------------------------------------------------*/ +int wpiPinToGpio(int wpiPin) { - if ((wiringPiMode == WPI_MODE_PINS) || (wiringPiMode == WPI_MODE_PHYS) || (wiringPiMode == WPI_MODE_GPIO)) - { - if (mode == PWM_MODE_MS) - *(pwm + PWM_CONTROL) = PWM0_ENABLE | PWM1_ENABLE | PWM0_MS_MODE | PWM1_MS_MODE ; - else - *(pwm + PWM_CONTROL) = PWM0_ENABLE | PWM1_ENABLE ; - } -} + if(libwiring.getModeToGpio) + return libwiring.getModeToGpio(MODE_PINS, wpiPin); - -/* - * pwmSetRange: - * Set the PWM range register. We set both range registers to the same - * value. If you want different in your own code, then write your own. - ********************************************************************************* - */ - -void pwmSetRange (unsigned int range) -{ - if ((wiringPiMode == WPI_MODE_PINS) || (wiringPiMode == WPI_MODE_PHYS) || (wiringPiMode == WPI_MODE_GPIO)) - { - *(pwm + PWM0_RANGE) = range ; delayMicroseconds (10) ; - *(pwm + PWM1_RANGE) = range ; delayMicroseconds (10) ; - } + return -1; } - -/* - * pwmSetClock: - * Set/Change the PWM clock. Originally my code, but changed - * (for the better!) by Chris Hall, - * after further study of the manual and testing with a 'scope - ********************************************************************************* - */ - -void pwmSetClock (int divisor) +/*------------------------------------------------------------------------------------------*/ +/* physPinToGpio */ +/*------------------------------------------------------------------------------------------*/ +int physPinToGpio(int wpiPin) { - uint32_t pwm_control ; - divisor &= 4095 ; - - if ((wiringPiMode == WPI_MODE_PINS) || (wiringPiMode == WPI_MODE_PHYS) || (wiringPiMode == WPI_MODE_GPIO)) - { - if (wiringPiDebug) - printf ("Setting to: %d. Current: 0x%08X\n", divisor, *(clk + PWMCLK_DIV)) ; - - pwm_control = *(pwm + PWM_CONTROL) ; // preserve PWM_CONTROL - -// We need to stop PWM prior to stopping PWM clock in MS mode otherwise BUSY -// stays high. - - *(pwm + PWM_CONTROL) = 0 ; // Stop PWM - -// Stop PWM clock before changing divisor. The delay after this does need to -// this big (95uS occasionally fails, 100uS OK), it's almost as though the BUSY -// flag is not working properly in balanced mode. Without the delay when DIV is -// adjusted the clock sometimes switches to very slow, once slow further DIV -// adjustments do nothing and it's difficult to get out of this mode. - - *(clk + PWMCLK_CNTL) = BCM_PASSWORD | 0x01 ; // Stop PWM Clock - delayMicroseconds (110) ; // prevents clock going sloooow - - while ((*(clk + PWMCLK_CNTL) & 0x80) != 0) // Wait for clock to be !BUSY - delayMicroseconds (1) ; - - *(clk + PWMCLK_DIV) = BCM_PASSWORD | (divisor << 12) ; - - *(clk + PWMCLK_CNTL) = BCM_PASSWORD | 0x11 ; // Start PWM clock - *(pwm + PWM_CONTROL) = pwm_control ; // restore PWM_CONTROL - - if (wiringPiDebug) - printf ("Set to: %d. Now : 0x%08X\n", divisor, *(clk + PWMCLK_DIV)) ; - } + if(libwiring.getModeToGpio) + return libwiring.getModeToGpio(MODE_PHYS, wpiPin); + return -1; } - -/* - * gpioClockSet: - * Set the frequency on a GPIO clock pin - ********************************************************************************* - */ - -void gpioClockSet (int pin, int freq) +/*------------------------------------------------------------------------------------------*/ +/* setPadDrive */ +/*------------------------------------------------------------------------------------------*/ +void setPadDrive(int pin, int value) { - int divi, divr, divf ; - - pin &= 63 ; - - /**/ if (wiringPiMode == WPI_MODE_PINS) - pin = pinToGpio [pin] ; - else if (wiringPiMode == WPI_MODE_PHYS) - pin = physToGpio [pin] ; - else if (wiringPiMode != WPI_MODE_GPIO) - return ; - - divi = 19200000 / freq ; - divr = 19200000 % freq ; - divf = (int)((double)divr * 4096.0 / 19200000.0) ; - - if (divi > 4095) - divi = 4095 ; - - *(clk + gpioToClkCon [pin]) = BCM_PASSWORD | GPIO_CLOCK_SOURCE ; // Stop GPIO Clock - while ((*(clk + gpioToClkCon [pin]) & 0x80) != 0) // ... and wait - ; - - *(clk + gpioToClkDiv [pin]) = BCM_PASSWORD | (divi << 12) | divf ; // Set dividers - *(clk + gpioToClkCon [pin]) = BCM_PASSWORD | 0x10 | GPIO_CLOCK_SOURCE ; // Start Clock + if(libwiring.setPadDrive) + return libwiring.setPadDrive(pin, value); + + return ; } - -/* - * wiringPiFindNode: - * Locate our device node - ********************************************************************************* - */ - -struct wiringPiNodeStruct *wiringPiFindNode (int pin) +/*------------------------------------------------------------------------------------------*/ +/* getPadDrive */ +/*------------------------------------------------------------------------------------------*/ +int getPadDrive (int pin) { - struct wiringPiNodeStruct *node = wiringPiNodes ; + if (libwiring.getPadDrive) + return libwiring.getPadDrive(pin); - while (node != NULL) - if ((pin >= node->pinBase) && (pin <= node->pinMax)) - return node ; - else - node = node->next ; - - return NULL ; + return -1; } - -/* - * wiringPiNewNode: - * Create a new GPIO node into the wiringPi handling system - ********************************************************************************* - */ - -static void pinModeDummy (UNU struct wiringPiNodeStruct *node, UNU int pin, UNU int mode) { return ; } -static void pullUpDnControlDummy (UNU struct wiringPiNodeStruct *node, UNU int pin, UNU int pud) { return ; } -static unsigned int digitalRead8Dummy (UNU struct wiringPiNodeStruct *node, UNU int UNU pin) { return 0 ; } -static void digitalWrite8Dummy (UNU struct wiringPiNodeStruct *node, UNU int pin, UNU int value) { return ; } -static int digitalReadDummy (UNU struct wiringPiNodeStruct *node, UNU int UNU pin) { return LOW ; } -static void digitalWriteDummy (UNU struct wiringPiNodeStruct *node, UNU int pin, UNU int value) { return ; } -static void pwmWriteDummy (UNU struct wiringPiNodeStruct *node, UNU int pin, UNU int value) { return ; } -static int analogReadDummy (UNU struct wiringPiNodeStruct *node, UNU int pin) { return 0 ; } -static void analogWriteDummy (UNU struct wiringPiNodeStruct *node, UNU int pin, UNU int value) { return ; } - -struct wiringPiNodeStruct *wiringPiNewNode (int pinBase, int numPins) +/*------------------------------------------------------------------------------------------*/ +/* getAlt */ +/*------------------------------------------------------------------------------------------*/ +int getAlt (int pin) { - int pin ; - struct wiringPiNodeStruct *node ; - -// Minimum pin base is 64 - - if (pinBase < 64) - (void)wiringPiFailure (WPI_FATAL, "wiringPiNewNode: pinBase of %d is < 64\n", pinBase) ; - -// Check all pins in-case there is overlap: - - for (pin = pinBase ; pin < (pinBase + numPins) ; ++pin) - if (wiringPiFindNode (pin) != NULL) - (void)wiringPiFailure (WPI_FATAL, "wiringPiNewNode: Pin %d overlaps with existing definition\n", pin) ; - - node = (struct wiringPiNodeStruct *)calloc (sizeof (struct wiringPiNodeStruct), 1) ; // calloc zeros - if (node == NULL) - (void)wiringPiFailure (WPI_FATAL, "wiringPiNewNode: Unable to allocate memory: %s\n", strerror (errno)) ; - - node->pinBase = pinBase ; - node->pinMax = pinBase + numPins - 1 ; - node->pinMode = pinModeDummy ; - node->pullUpDnControl = pullUpDnControlDummy ; - node->digitalRead = digitalReadDummy ; -//node->digitalRead8 = digitalRead8Dummy ; - node->digitalWrite = digitalWriteDummy ; -//node->digitalWrite8 = digitalWrite8Dummy ; - node->pwmWrite = pwmWriteDummy ; - node->analogRead = analogReadDummy ; - node->analogWrite = analogWriteDummy ; - node->next = wiringPiNodes ; - wiringPiNodes = node ; - - return node ; -} + if (libwiring.getAlt) + return libwiring.getAlt(pin); - -#ifdef notYetReady -/* - * pinED01: - * pinED10: - * Enables edge-detect mode on a pin - from a 0 to a 1 or 1 to 0 - * Pin must already be in input mode with appropriate pull up/downs set. - ********************************************************************************* - */ - -void pinEnableED01Pi (int pin) -{ - pin = pinToGpio [pin & 63] ; + return -1; } -#endif - -/* - ********************************************************************************* - * Core Functions - ********************************************************************************* - */ - -/* - * pinModeAlt: - * This is an un-documented special to let you set any pin to any mode - ********************************************************************************* - */ - -void pinModeAlt (int pin, int mode) +int getPUPD(int pin) { - int fSel, shift ; - - setupCheck ("pinModeAlt") ; - - if ((pin & PI_GPIO_MASK) == 0) // On-board pin - { - /**/ if (wiringPiMode == WPI_MODE_PINS) - pin = pinToGpio [pin] ; - else if (wiringPiMode == WPI_MODE_PHYS) - pin = physToGpio [pin] ; - else if (wiringPiMode != WPI_MODE_GPIO) - return ; - - fSel = gpioToGPFSEL [pin] ; - shift = gpioToShift [pin] ; - - *(gpio + fSel) = (*(gpio + fSel) & ~(7 << shift)) | ((mode & 0x7) << shift) ; - } + if (libwiring.getPUPD) + return libwiring.getPUPD(pin); + + return -1; } - -/* - * pinMode: - * Sets the mode of a pin to be input, output or PWM output - ********************************************************************************* - */ - +/*------------------------------------------------------------------------------------------*/ +/* */ +/* Core Functions */ +/* */ +/*------------------------------------------------------------------------------------------*/ void pinMode (int pin, int mode) { - int fSel, shift, alt ; - struct wiringPiNodeStruct *node = wiringPiNodes ; - int origPin = pin ; - - setupCheck ("pinMode") ; - - if ((pin & PI_GPIO_MASK) == 0) // On-board pin - { - /**/ if (wiringPiMode == WPI_MODE_PINS) - pin = pinToGpio [pin] ; - else if (wiringPiMode == WPI_MODE_PHYS) - pin = physToGpio [pin] ; - else if (wiringPiMode != WPI_MODE_GPIO) - return ; - - softPwmStop (origPin) ; - softToneStop (origPin) ; - - fSel = gpioToGPFSEL [pin] ; - shift = gpioToShift [pin] ; - - /**/ if (mode == INPUT) - *(gpio + fSel) = (*(gpio + fSel) & ~(7 << shift)) ; // Sets bits to zero = input - else if (mode == OUTPUT) - *(gpio + fSel) = (*(gpio + fSel) & ~(7 << shift)) | (1 << shift) ; - else if (mode == SOFT_PWM_OUTPUT) - softPwmCreate (origPin, 0, 100) ; - else if (mode == SOFT_TONE_OUTPUT) - softToneCreate (origPin) ; - else if (mode == PWM_TONE_OUTPUT) - { - pinMode (origPin, PWM_OUTPUT) ; // Call myself to enable PWM mode - pwmSetMode (PWM_MODE_MS) ; - } - else if (mode == PWM_OUTPUT) - { - if ((alt = gpioToPwmALT [pin]) == 0) // Not a hardware capable PWM pin - return ; - - usingGpioMemCheck ("pinMode PWM") ; - -// Set pin to PWM mode - - *(gpio + fSel) = (*(gpio + fSel) & ~(7 << shift)) | (alt << shift) ; - delayMicroseconds (110) ; // See comments in pwmSetClockWPi - - pwmSetMode (PWM_MODE_BAL) ; // Pi default mode - pwmSetRange (1024) ; // Default range of 1024 - pwmSetClock (32) ; // 19.2 / 32 = 600KHz - Also starts the PWM - } - else if (mode == GPIO_CLOCK) - { - if ((alt = gpioToGpClkALT0 [pin]) == 0) // Not a GPIO_CLOCK pin - return ; - - usingGpioMemCheck ("pinMode CLOCK") ; - -// Set pin to GPIO_CLOCK mode and set the clock frequency to 100KHz - - *(gpio + fSel) = (*(gpio + fSel) & ~(7 << shift)) | (alt << shift) ; - delayMicroseconds (110) ; - gpioClockSet (pin, 100000) ; - } - } - else - { - if ((node = wiringPiFindNode (pin)) != NULL) - node->pinMode (node, pin, mode) ; - return ; - } + if (libwiring.pinMode) + return libwiring.pinMode(pin, mode); } - - -/* - * pullUpDownCtrl: - * Control the internal pull-up/down resistors on a GPIO pin. - ********************************************************************************* - */ - -void pullUpDnControl (int pin, int pud) +/*------------------------------------------------------------------------------------------*/ +void pullUpDnControl(int pin, int pud) { - struct wiringPiNodeStruct *node = wiringPiNodes ; - - setupCheck ("pullUpDnControl") ; - - if ((pin & PI_GPIO_MASK) == 0) // On-Board Pin - { - /**/ if (wiringPiMode == WPI_MODE_PINS) - pin = pinToGpio [pin] ; - else if (wiringPiMode == WPI_MODE_PHYS) - pin = physToGpio [pin] ; - else if (wiringPiMode != WPI_MODE_GPIO) - return ; - - *(gpio + GPPUD) = pud & 3 ; delayMicroseconds (5) ; - *(gpio + gpioToPUDCLK [pin]) = 1 << (pin & 31) ; delayMicroseconds (5) ; - - *(gpio + GPPUD) = 0 ; delayMicroseconds (5) ; - *(gpio + gpioToPUDCLK [pin]) = 0 ; delayMicroseconds (5) ; - } - else // Extension module - { - if ((node = wiringPiFindNode (pin)) != NULL) - node->pullUpDnControl (node, pin, pud) ; - return ; - } + if (libwiring.pullUpDnControl) + return libwiring.pullUpDnControl(pin, pud); } - - -/* - * digitalRead: - * Read the value of a given Pin, returning HIGH or LOW - ********************************************************************************* - */ - +/*------------------------------------------------------------------------------------------*/ int digitalRead (int pin) { - char c ; - struct wiringPiNodeStruct *node = wiringPiNodes ; - - if ((pin & PI_GPIO_MASK) == 0) // On-Board Pin - { - /**/ if (wiringPiMode == WPI_MODE_GPIO_SYS) // Sys mode - { - if (sysFds [pin] == -1) - return LOW ; - - lseek (sysFds [pin], 0L, SEEK_SET) ; - read (sysFds [pin], &c, 1) ; - return (c == '0') ? LOW : HIGH ; - } - else if (wiringPiMode == WPI_MODE_PINS) - pin = pinToGpio [pin] ; - else if (wiringPiMode == WPI_MODE_PHYS) - pin = physToGpio [pin] ; - else if (wiringPiMode != WPI_MODE_GPIO) - return LOW ; - - if ((*(gpio + gpioToGPLEV [pin]) & (1 << (pin & 31))) != 0) - return HIGH ; - else - return LOW ; - } - else - { - if ((node = wiringPiFindNode (pin)) == NULL) - return LOW ; - return node->digitalRead (node, pin) ; - } -} - - -/* - * digitalRead8: - * Read 8-bits (a byte) from given start pin. - ********************************************************************************* + if (libwiring.digitalRead) + return libwiring.digitalRead(pin); -unsigned int digitalRead8 (int pin) -{ - struct wiringPiNodeStruct *node = wiringPiNodes ; - - if ((pin & PI_GPIO_MASK) == 0) // On-Board Pin - return 0 ; - else - { - if ((node = wiringPiFindNode (pin)) == NULL) - return LOW ; - return node->digitalRead8 (node, pin) ; - } + return -1; } - */ - - -/* - * digitalWrite: - * Set an output bit - ********************************************************************************* - */ - -void digitalWrite (int pin, int value) +/*------------------------------------------------------------------------------------------*/ +void digitalWrite(int pin, int value) { - struct wiringPiNodeStruct *node = wiringPiNodes ; - - if ((pin & PI_GPIO_MASK) == 0) // On-Board Pin - { - /**/ if (wiringPiMode == WPI_MODE_GPIO_SYS) // Sys mode - { - if (sysFds [pin] != -1) - { - if (value == LOW) - write (sysFds [pin], "0\n", 2) ; - else - write (sysFds [pin], "1\n", 2) ; - } - return ; - } - else if (wiringPiMode == WPI_MODE_PINS) - pin = pinToGpio [pin] ; - else if (wiringPiMode == WPI_MODE_PHYS) - pin = physToGpio [pin] ; - else if (wiringPiMode != WPI_MODE_GPIO) - return ; - - if (value == LOW) - *(gpio + gpioToGPCLR [pin]) = 1 << (pin & 31) ; - else - *(gpio + gpioToGPSET [pin]) = 1 << (pin & 31) ; - } - else - { - if ((node = wiringPiFindNode (pin)) != NULL) - node->digitalWrite (node, pin, value) ; - } + if (libwiring.digitalWrite) + return libwiring.digitalWrite(pin, value); } - - -/* - * digitalWrite8: - * Set an output 8-bit byte on the device from the given pin number - ********************************************************************************* - -void digitalWrite8 (int pin, int value) -{ - struct wiringPiNodeStruct *node = wiringPiNodes ; - - if ((pin & PI_GPIO_MASK) == 0) // On-Board Pin - return ; - else - { - if ((node = wiringPiFindNode (pin)) != NULL) - node->digitalWrite8 (node, pin, value) ; - } -} - */ - - -/* - * pwmWrite: - * Set an output PWM value - ********************************************************************************* - */ - -void pwmWrite (int pin, int value) -{ - struct wiringPiNodeStruct *node = wiringPiNodes ; - - setupCheck ("pwmWrite") ; - - if ((pin & PI_GPIO_MASK) == 0) // On-Board Pin - { - /**/ if (wiringPiMode == WPI_MODE_PINS) - pin = pinToGpio [pin] ; - else if (wiringPiMode == WPI_MODE_PHYS) - pin = physToGpio [pin] ; - else if (wiringPiMode != WPI_MODE_GPIO) - return ; - - usingGpioMemCheck ("pwmWrite") ; - *(pwm + gpioToPwmPort [pin]) = value ; - } - else - { - if ((node = wiringPiFindNode (pin)) != NULL) - node->pwmWrite (node, pin, value) ; - } -} - - -/* - * analogRead: - * Read the analog value of a given Pin. - * There is no on-board Pi analog hardware, - * so this needs to go to a new node. - ********************************************************************************* - */ - +/*------------------------------------------------------------------------------------------*/ int analogRead (int pin) { - struct wiringPiNodeStruct *node = wiringPiNodes ; - - if ((node = wiringPiFindNode (pin)) == NULL) - return 0 ; - else - return node->analogRead (node, pin) ; + if (libwiring.analogRead) + return libwiring.analogRead(pin); + return -1; } - - -/* - * analogWrite: - * Write the analog value to the given Pin. - * There is no on-board Pi analog hardware, - * so this needs to go to a new node. - ********************************************************************************* - */ - -void analogWrite (int pin, int value) -{ - struct wiringPiNodeStruct *node = wiringPiNodes ; - - if ((node = wiringPiFindNode (pin)) == NULL) - return ; - - node->analogWrite (node, pin, value) ; -} - - -/* - * pwmToneWrite: - * Pi Specific. - * Output the given frequency on the Pi's PWM pin - ********************************************************************************* - */ - -void pwmToneWrite (int pin, int freq) -{ - int range ; - - setupCheck ("pwmToneWrite") ; - - if (freq == 0) - pwmWrite (pin, 0) ; // Off - else - { - range = 600000 / freq ; - pwmSetRange (range) ; - pwmWrite (pin, freq / 2) ; - } -} - - - -/* - * digitalWriteByte: - * digitalReadByte: - * Pi Specific - * Write an 8-bit byte to the first 8 GPIO pins - try to do it as - * fast as possible. - * However it still needs 2 operations to set the bits, so any external - * hardware must not rely on seeing a change as there will be a change - * to set the outputs bits to zero, then another change to set the 1's - * Reading is just bit fiddling. - * These are wiringPi pin numbers 0..7, or BCM_GPIO pin numbers - * 17, 18, 22, 23, 24, 24, 4 on a Pi v1 rev 0-3 - * 17, 18, 27, 23, 24, 24, 4 on a Pi v1 rev 3 onwards or B+, 2, 3, zero - ********************************************************************************* - */ - +/*------------------------------------------------------------------------------------------*/ void digitalWriteByte (const int value) { - uint32_t pinSet = 0 ; - uint32_t pinClr = 0 ; - int mask = 1 ; - int pin ; - - /**/ if (wiringPiMode == WPI_MODE_GPIO_SYS) - { - for (pin = 0 ; pin < 8 ; ++pin) - { - digitalWrite (pinToGpio [pin], value & mask) ; - mask <<= 1 ; - } - return ; - } - else - { - for (pin = 0 ; pin < 8 ; ++pin) - { - if ((value & mask) == 0) - pinClr |= (1 << pinToGpio [pin]) ; - else - pinSet |= (1 << pinToGpio [pin]) ; - - mask <<= 1 ; - } - - *(gpio + gpioToGPCLR [0]) = pinClr ; - *(gpio + gpioToGPSET [0]) = pinSet ; - } + if (libwiring.digitalWriteByte) + return libwiring.digitalWriteByte(value); } - +/*------------------------------------------------------------------------------------------*/ unsigned int digitalReadByte (void) { - int pin, x ; - uint32_t raw ; - uint32_t data = 0 ; - - /**/ if (wiringPiMode == WPI_MODE_GPIO_SYS) - { - for (pin = 0 ; pin < 8 ; ++pin) - { - x = digitalRead (pinToGpio [pin]) ; - data = (data << 1) | x ; - } - } - else - { - raw = *(gpio + gpioToGPLEV [0]) ; // First bank for these pins - for (pin = 0 ; pin < 8 ; ++pin) - { - x = pinToGpio [pin] ; - data = (data << 1) | (((raw & (1 << x)) == 0) ? 0 : 1) ; - } - } - return data ; -} - - -/* - * digitalWriteByte2: - * digitalReadByte2: - * Pi Specific - * Write an 8-bit byte to the second set of 8 GPIO pins. This is marginally - * faster than the first lot as these are consecutive BCM_GPIO pin numbers. - * However they overlap with the original read/write bytes. - ********************************************************************************* - */ - -void digitalWriteByte2 (const int value) -{ - register int mask = 1 ; - register int pin ; - - /**/ if (wiringPiMode == WPI_MODE_GPIO_SYS) - { - for (pin = 20 ; pin < 28 ; ++pin) - { - digitalWrite (pin, value & mask) ; - mask <<= 1 ; - } - return ; - } - else - { - *(gpio + gpioToGPCLR [0]) = (~value & 0xFF) << 20 ; // 0x0FF00000; ILJ > CHANGE: Old causes glitch - *(gpio + gpioToGPSET [0]) = ( value & 0xFF) << 20 ; - } -} - -unsigned int digitalReadByte2 (void) -{ - int pin, x ; - uint32_t data = 0 ; - - /**/ if (wiringPiMode == WPI_MODE_GPIO_SYS) - { - for (pin = 20 ; pin < 28 ; ++pin) - { - x = digitalRead (pin) ; - data = (data << 1) | x ; - } - } - else - data = ((*(gpio + gpioToGPLEV [0])) >> 20) & 0xFF ; // First bank for these pins - - return data ; + if (libwiring.digitalReadByte) + return libwiring.digitalReadByte(); + return -1; } - - -/* - * waitForInterrupt: - * Pi Specific. - * Wait for Interrupt on a GPIO pin. - * This is actually done via the /sys/class/gpio interface regardless of - * the wiringPi access mode in-use. Maybe sometime it might get a better - * way for a bit more efficiency. - ********************************************************************************* - */ - +/*------------------------------------------------------------------------------------------*/ int waitForInterrupt (int pin, int mS) { - int fd, x ; - uint8_t c ; - struct pollfd polls ; - - /**/ if (wiringPiMode == WPI_MODE_PINS) - pin = pinToGpio [pin] ; - else if (wiringPiMode == WPI_MODE_PHYS) - pin = physToGpio [pin] ; - - if ((fd = sysFds [pin]) == -1) - return -2 ; - -// Setup poll structure + int fd, x; + uint8_t c; + struct pollfd polls; + if ((fd = libwiring.sysFds[PIN_NUM_CALC_SYSFD(pin)]) == -1) + return -2; - polls.fd = fd ; - polls.events = POLLPRI | POLLERR ; + //Setup poll structure + polls.fd = fd; + polls.events = POLLPRI | POLLERR; -// Wait for it ... + // Wait for it ... + x = poll (&polls, 1, mS) ; - x = poll (&polls, 1, mS) ; - -// If no error, do a dummy read to clear the interrupt -// A one character read appars to be enough. - - if (x > 0) - { - lseek (fd, 0, SEEK_SET) ; // Rewind - (void)read (fd, &c, 1) ; // Read & clear - } - - return x ; + // If no error, do a dummy read to clear the interrupt + // A one character read appars to be enough. + if (x > 0) { + lseek (fd, 0, SEEK_SET); + (void)read (fd, &c, 1); + } + return x; } - - -/* - * interruptHandler: - * This is a thread and gets started to wait for the interrupt we're - * hoping to catch. It will call the user-function when the interrupt - * fires. - ********************************************************************************* - */ - +/*-------------------------------------------------------------------------------------------*/ static void *interruptHandler (UNU void *arg) { - int myPin ; - - (void)piHiPri (55) ; // Only effective if we run as root - - myPin = pinPass ; - pinPass = -1 ; - - for (;;) - if (waitForInterrupt (myPin, -1) > 0) - isrFunctions [myPin] () ; - - return NULL ; + int myPin; + (void)piHiPri (55) ; // Only effective if we run as root + myPin = pinPass; + pinPass = -1; + for (;;) + if (waitForInterrupt (myPin, -1) > 0) + libwiring.isrFunctions [PIN_NUM_CALC_SYSFD(myPin)] (); + return NULL; } - - -/* - * wiringPiISR: - * Pi Specific. - * Take the details and create an interrupt handler that will do a call- - * back to the user supplied function. - ********************************************************************************* - */ - +/*-------------------------------------------------------------------------------------------*/ int wiringPiISR (int pin, int mode, void (*function)(void)) { - pthread_t threadId ; - const char *modeS ; - char fName [64] ; - char pinS [8] ; - pid_t pid ; - int count, i ; - char c ; - int bcmGpioPin ; - - if ((pin < 0) || (pin > 63)) - return wiringPiFailure (WPI_FATAL, "wiringPiISR: pin must be 0-63 (%d)\n", pin) ; - - /**/ if (wiringPiMode == WPI_MODE_UNINITIALISED) - return wiringPiFailure (WPI_FATAL, "wiringPiISR: wiringPi has not been initialised. Unable to continue.\n") ; - else if (wiringPiMode == WPI_MODE_PINS) - bcmGpioPin = pinToGpio [pin] ; - else if (wiringPiMode == WPI_MODE_PHYS) - bcmGpioPin = physToGpio [pin] ; - else - bcmGpioPin = pin ; - -// Now export the pin and set the right edge -// We're going to use the gpio program to do this, so it assumes -// a full installation of wiringPi. It's a bit 'clunky', but it -// is a way that will work when we're running in "Sys" mode, as -// a non-root user. (without sudo) - - if (mode != INT_EDGE_SETUP) - { - /**/ if (mode == INT_EDGE_FALLING) - modeS = "falling" ; - else if (mode == INT_EDGE_RISING) - modeS = "rising" ; - else - modeS = "both" ; - - sprintf (pinS, "%d", bcmGpioPin) ; - - if ((pid = fork ()) < 0) // Fail - return wiringPiFailure (WPI_FATAL, "wiringPiISR: fork failed: %s\n", strerror (errno)) ; - - if (pid == 0) // Child, exec - { - /**/ if (access ("/usr/local/bin/gpio", X_OK) == 0) - { - execl ("/usr/local/bin/gpio", "gpio", "edge", pinS, modeS, (char *)NULL) ; - return wiringPiFailure (WPI_FATAL, "wiringPiISR: execl failed: %s\n", strerror (errno)) ; - } - else if (access ("/usr/bin/gpio", X_OK) == 0) - { - execl ("/usr/bin/gpio", "gpio", "edge", pinS, modeS, (char *)NULL) ; - return wiringPiFailure (WPI_FATAL, "wiringPiISR: execl failed: %s\n", strerror (errno)) ; - } - else - return wiringPiFailure (WPI_FATAL, "wiringPiISR: Can't find gpio program\n") ; - } - else // Parent, wait - wait (NULL) ; - } - -// Now pre-open the /sys/class node - but it may already be open if -// we are in Sys mode... - - if (sysFds [bcmGpioPin] == -1) - { - sprintf (fName, "/sys/class/gpio/gpio%d/value", bcmGpioPin) ; - if ((sysFds [bcmGpioPin] = open (fName, O_RDWR)) < 0) - return wiringPiFailure (WPI_FATAL, "wiringPiISR: unable to open %s: %s\n", fName, strerror (errno)) ; - } - -// Clear any initial pending interrupt - - ioctl (sysFds [bcmGpioPin], FIONREAD, &count) ; - for (i = 0 ; i < count ; ++i) - read (sysFds [bcmGpioPin], &c, 1) ; - - isrFunctions [pin] = function ; - - pthread_mutex_lock (&pinMutex) ; - pinPass = pin ; - pthread_create (&threadId, NULL, interruptHandler, NULL) ; - while (pinPass != -1) - delay (1) ; - pthread_mutex_unlock (&pinMutex) ; - - return 0 ; -} - - -/* - * initialiseEpoch: - * Initialise our start-of-time variable to be the current unix - * time in milliseconds and microseconds. - ********************************************************************************* - */ - + pthread_t threadId; + const char *modeS; + char fName [64]; + char pinS [8]; + pid_t pid; + int count, i; + char c; + int GpioPin; + + if (libwiring.mode == MODE_UNINITIALISED) + return wiringPiFailure ( + WPI_FATAL, + "wiringPiISR: wiringPi has not been initialised. " \ + "Unable to continue.\n"); + + if (libwiring.getModeToGpio) + GpioPin = libwiring.getModeToGpio(libwiring.mode, pin); + else + return wiringPiFailure ( + WPI_FATAL, + "%s: getModeToGpio function not initialize!\n", + __func__); + + // Now export the pin and set the right edge + // We're going to use the gpio program to do this, so it assumes + // a full installation of wiringPi. It's a bit 'clunky', but it + // is a way that will work when we're running in "Sys" mode, as + // a non-root user. (without sudo) + if (mode != INT_EDGE_SETUP){ + if (mode == INT_EDGE_FALLING) + modeS = "falling"; + else if (mode == INT_EDGE_RISING) + modeS = "rising"; + else + modeS = "both"; + + sprintf (pinS, "%d", GpioPin); + + if ((pid = fork ()) < 0) + return wiringPiFailure ( + WPI_FATAL, + "wiringPiISR: fork failed: %s\n", + strerror (errno)); + + // Child, exec + if (pid == 0) { + if (access ("/usr/local/bin/gpio", X_OK) == 0) { + execl ("/usr/local/bin/gpio", "gpio", "edge", + pinS, modeS, (char *)NULL) ; + return wiringPiFailure ( + WPI_FATAL, + "wiringPiISR: execl failed: %s\n", + strerror (errno)); + }else if(access ("/usr/bin/gpio", X_OK) == 0){ + execl ("/usr/bin/gpio", "gpio", "edge", + pinS, modeS, (char *)NULL); + return wiringPiFailure ( + WPI_FATAL, + "wiringPiISR: execl failed: %s\n", + strerror (errno)); + }else + return wiringPiFailure ( + WPI_FATAL, + "wiringPiISR: Can't find gpio program\n"); + }else + wait (NULL) ; + } + + // Now pre-open the /sys/class node - but it may already be open if + // we are in Sys mode... + + if (libwiring.sysFds [PIN_NUM_CALC_SYSFD(GpioPin)] == -1) { + sprintf (fName, "/sys/class/gpio/gpio%d/value", GpioPin) ; + + if ((libwiring.sysFds [PIN_NUM_CALC_SYSFD(GpioPin)] = open (fName, O_RDWR)) < 0) + return wiringPiFailure ( + WPI_FATAL, + "wiringPiISR: unable to open %s: %s\n", + fName, strerror (errno)) ; + } + + // Clear any initial pending interrupt + ioctl (libwiring.sysFds [PIN_NUM_CALC_SYSFD(GpioPin)], FIONREAD, &count); + for (i = 0 ; i < count ; ++i) + (void)read (libwiring.sysFds [PIN_NUM_CALC_SYSFD(GpioPin)], &c, 1); + + libwiring.isrFunctions [PIN_NUM_CALC_SYSFD(GpioPin)] = function ; + + pthread_mutex_lock(&pinMutex); + pinPass = GpioPin; + pthread_create (&threadId, NULL, interruptHandler, NULL); + while (pinPass != -1) + delay (1) ; + pthread_mutex_unlock (&pinMutex); + + return 0; +} +/*-------------------------------------------------------------------------------------------*/ static void initialiseEpoch (void) { -#ifdef OLD_WAY - struct timeval tv ; +#ifdef OLD_WAY + struct timeval tv; - gettimeofday (&tv, NULL) ; - epochMilli = (uint64_t)tv.tv_sec * (uint64_t)1000 + (uint64_t)(tv.tv_usec / 1000) ; - epochMicro = (uint64_t)tv.tv_sec * (uint64_t)1000000 + (uint64_t)(tv.tv_usec) ; + gettimeofday (&tv, NULL); + libwiring.epochMilli = (uint64_t)tv.tv_sec * (uint64_t)1000 + (uint64_t)(tv.tv_usec / 1000); + libwiring.epochMicro = (uint64_t)tv.tv_sec * (uint64_t)1000000 + (uint64_t)(tv.tv_usec); #else - struct timespec ts ; + struct timespec ts; - clock_gettime (CLOCK_MONOTONIC_RAW, &ts) ; - epochMilli = (uint64_t)ts.tv_sec * (uint64_t)1000 + (uint64_t)(ts.tv_nsec / 1000000L) ; - epochMicro = (uint64_t)ts.tv_sec * (uint64_t)1000000 + (uint64_t)(ts.tv_nsec / 1000L) ; + clock_gettime (CLOCK_MONOTONIC_RAW, &ts); + libwiring.epochMilli = (uint64_t)ts.tv_sec*(uint64_t)1000 + (uint64_t)(ts.tv_nsec/1000000L); + libwiring.epochMicro = (uint64_t)ts.tv_sec*(uint64_t)1000000 + (uint64_t)(ts.tv_nsec/1000L); #endif } - -/* - * delay: - * Wait for some number of milliseconds - ********************************************************************************* - */ - +/*-------------------------------------------------------------------------------------------*/ void delay (unsigned int howLong) { - struct timespec sleeper, dummy ; + struct timespec sleeper, dummy; - sleeper.tv_sec = (time_t)(howLong / 1000) ; - sleeper.tv_nsec = (long)(howLong % 1000) * 1000000 ; + sleeper.tv_sec = (time_t)(howLong/1000); + sleeper.tv_nsec = (long)(howLong % 1000) * 1000000; - nanosleep (&sleeper, &dummy) ; + nanosleep(&sleeper, &dummy); } +/*-------------------------------------------------------------------------------------------*/ - -/* - * delayMicroseconds: - * This is somewhat intersting. It seems that on the Pi, a single call - * to nanosleep takes some 80 to 130 microseconds anyway, so while - * obeying the standards (may take longer), it's not always what we - * want! - * - * So what I'll do now is if the delay is less than 100uS we'll do it - * in a hard loop, watching a built-in counter on the ARM chip. This is - * somewhat sub-optimal in that it uses 100% CPU, something not an issue - * in a microcontroller, but under a multi-tasking, multi-user OS, it's - * wastefull, however we've no real choice )-: - * - * Plan B: It seems all might not be well with that plan, so changing it - * to use gettimeofday () and poll on that instead... - ********************************************************************************* - */ - -void delayMicrosecondsHard (unsigned int howLong) +void delayMicrosecondsHard(unsigned int howLong) { - struct timeval tNow, tLong, tEnd ; + struct timeval tNow, tLong, tEnd; - gettimeofday (&tNow, NULL) ; - tLong.tv_sec = howLong / 1000000 ; - tLong.tv_usec = howLong % 1000000 ; - timeradd (&tNow, &tLong, &tEnd) ; - - while (timercmp (&tNow, &tEnd, <)) - gettimeofday (&tNow, NULL) ; + gettimeofday (&tNow, NULL); + tLong.tv_sec = howLong / 1000000; + tLong.tv_usec = howLong % 1000000; + timeradd (&tNow, &tLong, &tEnd); + while (timercmp (&tNow, &tEnd, <)) + gettimeofday (&tNow, NULL); } -void delayMicroseconds (unsigned int howLong) -{ - struct timespec sleeper ; - unsigned int uSecs = howLong % 1000000 ; - unsigned int wSecs = howLong / 1000000 ; - - /**/ if (howLong == 0) - return ; - else if (howLong < 100) - delayMicrosecondsHard (howLong) ; - else - { - sleeper.tv_sec = wSecs ; - sleeper.tv_nsec = (long)(uSecs * 1000L) ; - nanosleep (&sleeper, NULL) ; - } -} +/*-------------------------------------------------------------------------------------------*/ +void delayMicroseconds(unsigned int howLong) +{ + struct timespec sleeper; + unsigned int uSecs = howLong % 1000000; + unsigned int wSecs = howLong / 1000000; -/* - * millis: - * Return a number of milliseconds as an unsigned int. - * Wraps at 49 days. - ********************************************************************************* - */ + if (howLong == 0) + return ; + else if (howLong < 100) + delayMicrosecondsHard (howLong); + else { + sleeper.tv_sec = wSecs; + sleeper.tv_nsec = (long)(uSecs * 1000L); + nanosleep (&sleeper, NULL); + } +} +/*--------------------------------------------------------------------------------------------*/ unsigned int millis (void) { - uint64_t now ; + uint64_t now; -#ifdef OLD_WAY - struct timeval tv ; - - gettimeofday (&tv, NULL) ; - now = (uint64_t)tv.tv_sec * (uint64_t)1000 + (uint64_t)(tv.tv_usec / 1000) ; +#ifdef OLD_WAY + struct timeval tv; + gettimeofday (&tv, NULL); + now = (uint64_t)tv.tv_sec * (uint64_t)1000 + (uint64_t)(tv.tv_usec / 1000); #else - struct timespec ts ; + struct timespec ts; - clock_gettime (CLOCK_MONOTONIC_RAW, &ts) ; - now = (uint64_t)ts.tv_sec * (uint64_t)1000 + (uint64_t)(ts.tv_nsec / 1000000L) ; -#endif + clock_gettime(CLOCK_MONOTONIC_RAW, &ts); + now = (uint64_t)ts.tv_sec * (uint64_t)1000 + (uint64_t)(ts.tv_nsec / 1000000L); - return (uint32_t)(now - epochMilli) ; +#endif + return (uint32_t)(now - libwiring.epochMilli); } +/*-------------------------------------------------------------------------------------------*/ +unsigned int micros(void) +{ + uint64_t now; -/* - * micros: - * Return a number of microseconds as an unsigned int. - * Wraps after 71 minutes. - ********************************************************************************* - */ +#ifdef OLD_WAY + struct timeval tv; -unsigned int micros (void) -{ - uint64_t now ; -#ifdef OLD_WAY - struct timeval tv ; + gettimeofday (&tv, NULL); + now = (uint64_t)tv.tv_sec * (uint64_t)1000000 + (uint64_t)tv.tv_usec; - gettimeofday (&tv, NULL) ; - now = (uint64_t)tv.tv_sec * (uint64_t)1000000 + (uint64_t)tv.tv_usec ; #else - struct timespec ts ; + struct timespec ts; - clock_gettime (CLOCK_MONOTONIC_RAW, &ts) ; - now = (uint64_t)ts.tv_sec * (uint64_t)1000000 + (uint64_t)(ts.tv_nsec / 1000) ; -#endif + clock_gettime (CLOCK_MONOTONIC_RAW, &ts); + now = (uint64_t)ts.tv_sec * (uint64_t)1000000 + (uint64_t)(ts.tv_nsec / 1000); +#endif + return (uint32_t)(now - libwiring.epochMicro); - return (uint32_t)(now - epochMicro) ; } -/* - * wiringPiVersion: - * Return our current version number - ********************************************************************************* - */ - +/*------------------------------------------------------------------------------------------*/ void wiringPiVersion (int *major, int *minor) { - *major = VERSION_MAJOR ; - *minor = VERSION_MINOR ; -} - - -/* - * wiringPiSetup: - * Must be called once at the start of your program execution. - * - * Default setup: Initialises the system into wiringPi Pin mode and uses the - * memory mapped hardware directly. - * - * Changed now to revert to "gpio" mode if we're running on a Compute Module. - ********************************************************************************* - */ - -int wiringPiSetup (void) -{ - int fd ; - int model, rev, mem, maker, overVolted ; - -// It's actually a fatal error to call any of the wiringPiSetup routines more than once, -// (you run out of file handles!) but I'm fed-up with the useless twats who email -// me bleating that there is a bug in my code, so screw-em. - - if (wiringPiSetuped) - return 0 ; - - wiringPiSetuped = TRUE ; - - if (getenv (ENV_DEBUG) != NULL) - wiringPiDebug = TRUE ; - - if (getenv (ENV_CODES) != NULL) - wiringPiReturnCodes = TRUE ; - - if (wiringPiDebug) - printf ("wiringPi: wiringPiSetup called\n") ; - -// Get the board ID information. We're not really using the information here, -// but it will give us information like the GPIO layout scheme (2 variants -// on the older 26-pin Pi's) and the GPIO peripheral base address. -// and if we're running on a compute module, then wiringPi pin numbers -// don't really many anything, so force native BCM mode anyway. - - piBoardId (&model, &rev, &mem, &maker, &overVolted) ; - - if ((model == PI_MODEL_CM) || (model == PI_MODEL_CM3)) - wiringPiMode = WPI_MODE_GPIO ; - else - wiringPiMode = WPI_MODE_PINS ; - - /**/ if (piGpioLayout () == 1) // A, B, Rev 1, 1.1 - { - pinToGpio = pinToGpioR1 ; - physToGpio = physToGpioR1 ; - } - else // A2, B2, A+, B+, CM, Pi2, Pi3, Zero - { - pinToGpio = pinToGpioR2 ; - physToGpio = physToGpioR2 ; - } - -// ... - - switch (model) - { - case PI_MODEL_A: case PI_MODEL_B: - case PI_MODEL_AP: case PI_MODEL_BP: - case PI_ALPHA: case PI_MODEL_CM: - case PI_MODEL_ZERO: case PI_MODEL_ZERO_W: - piGpioBase = GPIO_PERI_BASE_OLD ; - break ; - - default: - piGpioBase = GPIO_PERI_BASE_NEW ; - break ; - } - -// Open the master /dev/ memory control device -// Device strategy: December 2016: -// Try /dev/mem. If that fails, then -// try /dev/gpiomem. If that fails then game over. - - if ((fd = open ("/dev/mem", O_RDWR | O_SYNC | O_CLOEXEC)) < 0) - { - if ((fd = open ("/dev/gpiomem", O_RDWR | O_SYNC | O_CLOEXEC) ) >= 0) // We're using gpiomem - { - piGpioBase = 0 ; - usingGpioMem = TRUE ; - } - else - return wiringPiFailure (WPI_ALMOST, "wiringPiSetup: Unable to open /dev/mem or /dev/gpiomem: %s.\n" - " Aborting your program because if it can not access the GPIO\n" - " hardware then it most certianly won't work\n" - " Try running with sudo?\n", strerror (errno)) ; - } - -// Set the offsets into the memory interface. - - GPIO_PADS = piGpioBase + 0x00100000 ; - GPIO_CLOCK_BASE = piGpioBase + 0x00101000 ; - GPIO_BASE = piGpioBase + 0x00200000 ; - GPIO_TIMER = piGpioBase + 0x0000B000 ; - GPIO_PWM = piGpioBase + 0x0020C000 ; - -// Map the individual hardware components - -// GPIO: - - gpio = (uint32_t *)mmap(0, BLOCK_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED, fd, GPIO_BASE) ; - if (gpio == MAP_FAILED) - return wiringPiFailure (WPI_ALMOST, "wiringPiSetup: mmap (GPIO) failed: %s\n", strerror (errno)) ; - -// PWM - - pwm = (uint32_t *)mmap(0, BLOCK_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED, fd, GPIO_PWM) ; - if (pwm == MAP_FAILED) - return wiringPiFailure (WPI_ALMOST, "wiringPiSetup: mmap (PWM) failed: %s\n", strerror (errno)) ; - -// Clock control (needed for PWM) - - clk = (uint32_t *)mmap(0, BLOCK_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED, fd, GPIO_CLOCK_BASE) ; - if (clk == MAP_FAILED) - return wiringPiFailure (WPI_ALMOST, "wiringPiSetup: mmap (CLOCK) failed: %s\n", strerror (errno)) ; - -// The drive pads - - pads = (uint32_t *)mmap(0, BLOCK_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED, fd, GPIO_PADS) ; - if (pads == MAP_FAILED) - return wiringPiFailure (WPI_ALMOST, "wiringPiSetup: mmap (PADS) failed: %s\n", strerror (errno)) ; - -// The system timer - - timer = (uint32_t *)mmap(0, BLOCK_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED, fd, GPIO_TIMER) ; - if (timer == MAP_FAILED) - return wiringPiFailure (WPI_ALMOST, "wiringPiSetup: mmap (TIMER) failed: %s\n", strerror (errno)) ; - -// Set the timer to free-running, 1MHz. -// 0xF9 is 249, the timer divide is base clock / (divide+1) -// so base clock is 250MHz / 250 = 1MHz. - - *(timer + TIMER_CONTROL) = 0x0000280 ; - *(timer + TIMER_PRE_DIV) = 0x00000F9 ; - timerIrqRaw = timer + TIMER_IRQ_RAW ; - -// Export the base addresses for any external software that might need them - - _wiringPiGpio = gpio ; - _wiringPiPwm = pwm ; - _wiringPiClk = clk ; - _wiringPiPads = pads ; - _wiringPiTimer = timer ; - - initialiseEpoch () ; - - return 0 ; -} - - -/* - * wiringPiSetupGpio: - * Must be called once at the start of your program execution. - * - * GPIO setup: Initialises the system into GPIO Pin mode and uses the - * memory mapped hardware directly. - ********************************************************************************* - */ + *major = VERSION_MAJOR; + *minor = VERSION_MINOR; +} + +/*------------------------------------------------------------------------------------------*/ +int wiringPiSetup(void) +{ + int i; + static int alreadyDoneThis = FALSE; + + if(alreadyDoneThis) + return 0; + + alreadyDoneThis = TRUE; + + // libwiring init + memset(&libwiring, 0x00, sizeof(struct libkhadas)); + // sysFds init + for(i = 0; i < 256; i++) + libwiring.sysFds[i] = -1; + // init wiringPi node + libwiring.mode = MODE_UNINITIALISED; + + if (getenv (ENV_DEBUG) != NULL) + wiringPiDebug = TRUE; + + if (getenv (ENV_CODES) != NULL) + wiringPiReturnCodes = TRUE; + + (void)piGpioLayout(); + + if(wiringPiDebug) { + printf ("wiringPi: wiringPiSetup called\n"); + printf ("Model Name : %s\n", piModelNames[libwiring.model]); + printf ("Model Maker : %s\n", piMakerNames[libwiring.maker]); + printf ("Model MEM : %d\n", libwiring.mem); + printf ("Model REV : %d\n", libwiring.rev); + } + + switch (libwiring.model) { + case MODEL_KHADAS_VIM1: + init_khadas_vim1(&libwiring); + break; + case MODEL_KHADAS_VIM2: + init_khadas_vim2(&libwiring); + break; + case MODEL_KHADAS_VIM3: + init_khadas_vim3(&libwiring); + break; + default: + return wiringPiFailure (WPI_ALMOST,"wiringPiSetup: Unknown model\n"); + } + + initialiseEpoch(); + + libwiring.mode = MODE_PINS; + return 0; +} + +/*------------------------------------------------------------------------------------------*/ +/* wiringPiSetupGpio */ +/* Must be called once at the start of your program execution. */ +/* Phys setup: Initialises the system into Physical Pin mode and uses the */ +/* memory mapped hardware directly. */ +/*------------------------------------------------------------------------------------------*/ int wiringPiSetupGpio (void) { - (void)wiringPiSetup () ; + (void)wiringPiSetup(); - if (wiringPiDebug) - printf ("wiringPi: wiringPiSetupGpio called\n") ; + if (wiringPiDebug) + printf ("wiringPi: wiringPiSetupGpio called\n"); - wiringPiMode = WPI_MODE_GPIO ; - - return 0 ; + libwiring.mode = MODE_GPIO; + return 0; } - -/* - * wiringPiSetupPhys: - * Must be called once at the start of your program execution. - * - * Phys setup: Initialises the system into Physical Pin mode and uses the - * memory mapped hardware directly. - ********************************************************************************* - */ - +/*------------------------------------------------------------------------------------------*/ +/* wiringPiSetupPhys */ +/* Must be called once at the start of your program execution. */ +/* Phys setup: Initialises the system into Physical Pin mode and uses the */ +/* memory mapped hardware directly. */ +/*------------------------------------------------------------------------------------------*/ int wiringPiSetupPhys (void) { - (void)wiringPiSetup () ; + (void)wiringPiSetup (); - if (wiringPiDebug) - printf ("wiringPi: wiringPiSetupPhys called\n") ; + if (wiringPiDebug) + printf ("wiringPi: wiringPiSetupPhys called\n"); - wiringPiMode = WPI_MODE_PHYS ; - - return 0 ; + libwiring.mode = MODE_PHYS; + return 0; } - -/* - * wiringPiSetupSys: - * Must be called once at the start of your program execution. - * - * Initialisation (again), however this time we are using the /sys/class/gpio - * interface to the GPIO systems - slightly slower, but always usable as - * a non-root user, assuming the devices are already exported and setup correctly. - */ - +/*------------------------------------------------------------------------------------------*/ +/* wiringPiSetupSys */ +/* Must be called once at the start of your program execution. */ +/* Initialisation (again), however this time we are using the /sys/class/gpio */ +/* interface to the GPIO systems - slightly slower, but always usable as */ +/* a non-root user, assuming the devices are already exported and setup correctly. */ +/*------------------------------------------------------------------------------------------*/ int wiringPiSetupSys (void) { - int pin ; - char fName [128] ; - - if (wiringPiSetuped) - return 0 ; - - wiringPiSetuped = TRUE ; + int pin; + char fName [128]; - if (getenv (ENV_DEBUG) != NULL) - wiringPiDebug = TRUE ; + (void)wiringPiSetup(); - if (getenv (ENV_CODES) != NULL) - wiringPiReturnCodes = TRUE ; + if (wiringPiDebug) + printf ("wiringPi: wiringPiSetupSys called\n"); - if (wiringPiDebug) - printf ("wiringPi: wiringPiSetupSys called\n") ; + //Open and scan the directory, looking for exported GPIOs, and pre-open + // the 'value' interface to speed things up for later - if (piGpioLayout () == 1) - { - pinToGpio = pinToGpioR1 ; - physToGpio = physToGpioR1 ; - } - else - { - pinToGpio = pinToGpioR2 ; - physToGpio = physToGpioR2 ; - } + for (pin = 0 ; pin < 256 ; ++pin) + { + switch(libwiring.model){ + default: + sprintf (fName, "/sys/class/gpio/gpio%d/value", pin); + break; + } -// Open and scan the directory, looking for exported GPIOs, and pre-open -// the 'value' interface to speed things up for later - - for (pin = 0 ; pin < 64 ; ++pin) - { - sprintf (fName, "/sys/class/gpio/gpio%d/value", pin) ; - sysFds [pin] = open (fName, O_RDWR) ; - } + libwiring.sysFds [pin] = open (fName, O_RDWR); + } - initialiseEpoch () ; + initialiseEpoch(); - wiringPiMode = WPI_MODE_GPIO_SYS ; - - return 0 ; + libwiring.mode = MODE_GPIO_SYS; + return 0; } + +/*------------------------------------------------------------------------------------------*/ +/*------------------------------------------------------------------------------------------*/ +/*------------------------------------------------------------------------------------------*/ diff --git a/wiringPi/wiringPi.h b/wiringPi/wiringPi.h index ae5d647..fb7211a 100644 --- a/wiringPi/wiringPi.h +++ b/wiringPi/wiringPi.h @@ -24,34 +24,43 @@ #ifndef __WIRING_PI_H__ #define __WIRING_PI_H__ -// C doesn't have true/false by default and I can never remember which -// way round they are, so ... -// (and yes, I know about stdbool.h but I like capitals for these and I'm old) +#include +#include +#include +#include + #ifndef TRUE # define TRUE (1==1) # define FALSE (!TRUE) #endif -// GCC warning suppressor +#define PIN_NUM_CALC_SYSFD(x) (x>225 ? x - libwiring.pinBase : x) +// GCC warning suppressor #define UNU __attribute__((unused)) -// Mask for the bottom 64 pins which belong to the Raspberry Pi -// The others are available for the other devices +#define ENV_DEBUG "WIRINGPI_DEBUG" +#define ENV_CODES "WIRINGPI_CODES" +#define ENV_GPIOMEM "WIRINGPI_GPIOMEM" -#define PI_GPIO_MASK (0xFFFFFFC0) +#define MODEL_UNKNOWN 0 +#define MODEL_KHADAS_VIM1 1 +#define MODEL_KHADAS_VIM2 2 +#define MODEL_KHADAS_VIM3 3 -// Handy defines +#define MAKER_UNKNOWN 0 +#define MAKER_AMLOGIC 1 +#define MAKER_ROCKCHIP 2 // wiringPi modes -#define WPI_MODE_PINS 0 -#define WPI_MODE_GPIO 1 -#define WPI_MODE_GPIO_SYS 2 -#define WPI_MODE_PHYS 3 -#define WPI_MODE_PIFACE 4 -#define WPI_MODE_UNINITIALISED -1 +#define MODE_PINS 0 +#define MODE_GPIO 1 +#define MODE_GPIO_SYS 2 +#define MODE_PHYS 3 +#define MODE_PIFACE 4 +#define MODE_UNINITIALISED -1 // Pin modes @@ -84,32 +93,8 @@ #define INT_EDGE_RISING 2 #define INT_EDGE_BOTH 3 -// Pi model types and version numbers -// Intended for the GPIO program Use at your own risk. - -#define PI_MODEL_A 0 -#define PI_MODEL_B 1 -#define PI_MODEL_AP 2 -#define PI_MODEL_BP 3 -#define PI_MODEL_2 4 -#define PI_ALPHA 5 -#define PI_MODEL_CM 6 -#define PI_MODEL_07 7 -#define PI_MODEL_3 8 -#define PI_MODEL_ZERO 9 -#define PI_MODEL_CM3 10 -#define PI_MODEL_ZERO_W 12 -#define PI_MODEL_3P 13 - -#define PI_VERSION_1 0 -#define PI_VERSION_1_1 1 -#define PI_VERSION_1_2 2 -#define PI_VERSION_2 3 - -#define PI_MAKER_SONY 0 -#define PI_MAKER_EGOMAN 1 -#define PI_MAKER_EMBEST 2 -#define PI_MAKER_UNKNOWN 3 +//Module names +#define AML_MODULE_I2C "aml_i2c" extern const char *piModelNames [16] ; extern const char *piRevisionNames [16] ; @@ -128,6 +113,87 @@ extern const int piMemorySize [ 8] ; #define WPI_FATAL (1==1) #define WPI_ALMOST (1==2) +#define PAGE_SIZE (4*1024) +#define BLOCK_SIZE (4*1024) + +#define MSG_ERR -1 +#define MSG_WARN -2 + +struct libkhadas +{ + /* H/W model info */ + int model, rev, mem, maker; + + /* wiringPi init mode */ + int mode; + + /* wiringPi core func */ + int (*getModeToGpio) (int mode, int pin); + void (*setPadDrive) (int pin, int value); + int (*getPadDrive) (int pin); + void (*pinMode) (int pin, int mode); + int (*getAlt) (int pin); + int (*getPUPD) (int pin); + void (*pullUpDnControl) (int pin, int pud); + int (*digitalRead) (int pin); + void (*digitalWrite) (int pin, int value); + int (*analogRead) (int pin); + void (*digitalWriteByte) (const int value); + unsigned int (*digitalReadByte) (void); + + /* ISR Function pointer */ + void (*isrFunctions[256])(void); + + /* GPIO sysfs file discripter */ + int sysFds[256]; + + /* GPIO pin base number */ + int pinBase; + + // Time for easy calculations + uint64_t epochMilli, epochMicro ; +}; + + +union reg_bitfield { + unsigned int wvalue; + struct { + unsigned int bit0 : 1; + unsigned int bit1 : 1; + unsigned int bit2 : 1; + unsigned int bit3 : 1; + unsigned int bit4 : 1; + unsigned int bit5 : 1; + unsigned int bit6 : 1; + unsigned int bit7 : 1; + unsigned int bit8 : 1; + unsigned int bit9 : 1; + unsigned int bit10 : 1; + unsigned int bit11 : 1; + unsigned int bit12 : 1; + unsigned int bit13 : 1; + unsigned int bit14 : 1; + unsigned int bit15 : 1; + unsigned int bit16 : 1; + unsigned int bit17 : 1; + unsigned int bit18 : 1; + unsigned int bit19 : 1; + unsigned int bit20 : 1; + unsigned int bit21 : 1; + unsigned int bit22 : 1; + unsigned int bit23 : 1; + unsigned int bit24 : 1; + unsigned int bit25 : 1; + unsigned int bit26 : 1; + unsigned int bit27 : 1; + unsigned int bit28 : 1; + unsigned int bit29 : 1; + unsigned int bit30 : 1; + unsigned int bit31 : 1; + + } bits; +}; + // wiringPiNodeStruct: // This describes additional device nodes in the extended wiringPi @@ -165,12 +231,12 @@ extern struct wiringPiNodeStruct *wiringPiNodes ; // Export variables for the hardware pointers -extern volatile unsigned int *_wiringPiGpio ; -extern volatile unsigned int *_wiringPiPwm ; -extern volatile unsigned int *_wiringPiClk ; -extern volatile unsigned int *_wiringPiPads ; -extern volatile unsigned int *_wiringPiTimer ; -extern volatile unsigned int *_wiringPiTimerIrqRaw ; +//extern volatile unsigned int *_wiringPiGpio ; +//extern volatile unsigned int *_wiringPiPwm ; +//extern volatile unsigned int *_wiringPiClk ; +//extern volatile unsigned int *_wiringPiPads ; +//extern volatile unsigned int *_wiringPiTimer ; +//extern volatile unsigned int *_wiringPiTimerIrqRaw ; // Function prototypes @@ -183,9 +249,11 @@ extern "C" { // Data -// Internal +// Internal WiringPi functions extern int wiringPiFailure (int fatal, const char *message, ...) ; +extern int msg (int type, const char *message, ...); +extern int moduleLoaded (char *); // Core wiringPi functions @@ -198,67 +266,60 @@ extern int wiringPiSetupSys (void) ; extern int wiringPiSetupGpio (void) ; extern int wiringPiSetupPhys (void) ; -extern void pinModeAlt (int pin, int mode) ; -extern void pinMode (int pin, int mode) ; -extern void pullUpDnControl (int pin, int pud) ; -extern int digitalRead (int pin) ; -extern void digitalWrite (int pin, int value) ; -extern unsigned int digitalRead8 (int pin) ; -extern void digitalWrite8 (int pin, int value) ; -extern void pwmWrite (int pin, int value) ; -extern int analogRead (int pin) ; -extern void analogWrite (int pin, int value) ; - -// PiFace specifics -// (Deprecated) - -extern int wiringPiSetupPiFace (void) ; -extern int wiringPiSetupPiFaceForGpioProg (void) ; // Don't use this - for gpio program only - -// On-Board Raspberry Pi hardware specific stuff - -extern int piGpioLayout (void) ; -extern int piBoardRev (void) ; // Deprecated -extern void piBoardId (int *model, int *rev, int *mem, int *maker, int *overVolted) ; -extern int wpiPinToGpio (int wpiPin) ; -extern int physPinToGpio (int physPin) ; -extern void setPadDrive (int group, int value) ; -extern int getAlt (int pin) ; -extern void pwmToneWrite (int pin, int freq) ; -extern void pwmSetMode (int mode) ; -extern void pwmSetRange (unsigned int range) ; -extern void pwmSetClock (int divisor) ; -extern void gpioClockSet (int pin, int freq) ; -extern unsigned int digitalReadByte (void) ; -extern unsigned int digitalReadByte2 (void) ; -extern void digitalWriteByte (int value) ; -extern void digitalWriteByte2 (int value) ; - -// Interrupts -// (Also Pi hardware specific) - -extern int waitForInterrupt (int pin, int mS) ; -extern int wiringPiISR (int pin, int mode, void (*function)(void)) ; - -// Threads - -extern int piThreadCreate (void *(*fn)(void *)) ; -extern void piLock (int key) ; -extern void piUnlock (int key) ; - -// Schedulling priority - -extern int piHiPri (const int pri) ; - -// Extras from arduino land - -extern void delay (unsigned int howLong) ; -extern void delayMicroseconds (unsigned int howLong) ; -extern unsigned int millis (void) ; -extern unsigned int micros (void) ; +extern int getModeToGpio (int wpiPin); +extern void setPadDrive (int pin, int value); +extern int getPadDrive (int pin); +extern int getAlt (int pin); +extern int getPUPD (int pin); +extern void pinMode (int pin,int mode); +extern void pullUpDnControl (int pin, int pud); +extern int digitalRead (int pin); +extern void digitalWrite (int pin, int value); +extern unsigned int digitalReadByte (void); +extern void digitalWriteByte (const int vaule); +extern void pwmWrite (int pin, int value); +extern int analogRead (int pin); + +//Hardware Specific stuffs +extern int piGpioLayout (void); +extern int piBoardRev (void); +extern void piBoardId (int *model, int *rev, int *mem, int *maker, int *warranty); +extern int wpiPinToGpio (int wpiPin); +extern int physPinToGpio (int physPin); + +//Unsupported +extern void pinModeAlt (int pin, int mode); +extern void analogWrite (int pin, int value); +extern void pwmToneWrite (int pin, int freq); +extern void pwmSetMode (int mode); +extern void pwmSetRange (unsigned int range); +extern void pwmSetClock (int divisor); +extern void gpioClockSet (int pin, int freq); +extern unsigned int digitalReadByte (void); +extern unsigned int digitalReadByte2 (void); +extern void digitalWriteByte (int value); +extern void digitalWriteByte2 (int value); + +//Interrupt +extern int waitForInterrupt (int pin, int mS); +extern int wiringPiISR (int pin, int mode, void (*function)(void)); + +//Threads +extern int piThreadCreate (void *(*fn)(void *)); +extern void piLock (int key); +extern void piUnlock (int key); + +//Schedulling priority +//extern void piHiPri (unsigned int howLong); + +//From Arduino land +extern void delay (unsigned int howLang); +extern void delayMicroseconds (unsigned int howLang); +extern unsigned int millis (void); +extern unsigned int micros (void); #ifdef __cplusplus } #endif -#endif +#endif /* __WIRING_H__ */ diff --git a/wiringPi/wiringPi_copy.c b/wiringPi/wiringPi_copy.c new file mode 100644 index 0000000..586b148 --- /dev/null +++ b/wiringPi/wiringPi_copy.c @@ -0,0 +1,2452 @@ +/* + * wiringPi: + * Arduino look-a-like Wiring library for the Raspberry Pi + * Copyright (c) 2012-2017 Gordon Henderson + * Additional code for pwmSetClock by Chris Hall + * + * Thanks to code samples from Gert Jan van Loo and the + * BCM2835 ARM Peripherals manual, however it's missing + * the clock section /grr/mutter/ + *********************************************************************** + * This file is part of wiringPi: + * https://projects.drogon.net/raspberry-pi/wiringpi/ + * + * wiringPi is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * wiringPi 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 Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with wiringPi. + * If not, see . + *********************************************************************** + */ + +// Revisions: +// 19 Jul 2012: +// Moved to the LGPL +// Added an abstraction layer to the main routines to save a tiny +// bit of run-time and make the clode a little cleaner (if a little +// larger) +// Added waitForInterrupt code +// Added piHiPri code +// +// 9 Jul 2012: +// Added in support to use the /sys/class/gpio interface. +// 2 Jul 2012: +// Fixed a few more bugs to do with range-checking when in GPIO mode. +// 11 Jun 2012: +// Fixed some typos. +// Added c++ support for the .h file +// Added a new function to allow for using my "pin" numbers, or native +// GPIO pin numbers. +// Removed my busy-loop delay and replaced it with a call to delayMicroseconds +// +// 02 May 2012: +// Added in the 2 UART pins +// Change maxPins to numPins to more accurately reflect purpose + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "softPwm.h" +#include "softTone.h" + +#include "wiringPi.h" +#include "../version.h" + +// Environment Variables + +#define ENV_DEBUG "WIRINGPI_DEBUG" +#define ENV_CODES "WIRINGPI_CODES" +#define ENV_GPIOMEM "WIRINGPI_GPIOMEM" + + +// Extend wiringPi with other pin-based devices and keep track of +// them in this structure + +struct wiringPiNodeStruct *wiringPiNodes = NULL ; + +// BCM Magic + +#define BCM_PASSWORD 0x5A000000 + + +// The BCM2835 has 54 GPIO pins. +// BCM2835 data sheet, Page 90 onwards. +// 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 - the ALT values +// +// 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) + +// Port function select bits + +#define FSEL_INPT 0b000 +#define FSEL_OUTP 0b001 +#define FSEL_ALT0 0b100 +#define FSEL_ALT1 0b101 +#define FSEL_ALT2 0b110 +#define FSEL_ALT3 0b111 +#define FSEL_ALT4 0b011 +#define FSEL_ALT5 0b010 + +// Access from ARM Running Linux +// Taken from Gert/Doms code. Some of this is not in the manual +// that I can find )-: +// +// Updates in September 2015 - all now static variables (and apologies for the caps) +// due to the Pi v2, v3, etc. and the new /dev/gpiomem interface + +static volatile unsigned int GPIO_PADS ; +static volatile unsigned int GPIO_CLOCK_BASE ; +static volatile unsigned int GPIO_BASE ; +static volatile unsigned int GPIO_TIMER ; +static volatile unsigned int GPIO_PWM ; + +#define PAGE_SIZE (4*1024) +#define BLOCK_SIZE (4*1024) + +static unsigned int usingGpioMem = FALSE ; +static int wiringPiSetuped = FALSE ; + +// PWM +// Word offsets into the PWM control region + +#define PWM_CONTROL 0 +#define PWM_STATUS 1 +#define PWM0_RANGE 4 +#define PWM0_DATA 5 +#define PWM1_RANGE 8 +#define PWM1_DATA 9 + +// Clock regsiter offsets + +#define PWMCLK_CNTL 40 +#define PWMCLK_DIV 41 + +#define PWM0_MS_MODE 0x0080 // Run in MS mode +#define PWM0_USEFIFO 0x0020 // Data from FIFO +#define PWM0_REVPOLAR 0x0010 // Reverse polarity +#define PWM0_OFFSTATE 0x0008 // Ouput Off state +#define PWM0_REPEATFF 0x0004 // Repeat last value if FIFO empty +#define PWM0_SERIAL 0x0002 // Run in serial mode +#define PWM0_ENABLE 0x0001 // Channel Enable + +#define PWM1_MS_MODE 0x8000 // Run in MS mode +#define PWM1_USEFIFO 0x2000 // Data from FIFO +#define PWM1_REVPOLAR 0x1000 // Reverse polarity +#define PWM1_OFFSTATE 0x0800 // Ouput Off state +#define PWM1_REPEATFF 0x0400 // Repeat last value if FIFO empty +#define PWM1_SERIAL 0x0200 // Run in serial mode +#define PWM1_ENABLE 0x0100 // Channel Enable + +// Timer +// Word offsets + +#define TIMER_LOAD (0x400 >> 2) +#define TIMER_VALUE (0x404 >> 2) +#define TIMER_CONTROL (0x408 >> 2) +#define TIMER_IRQ_CLR (0x40C >> 2) +#define TIMER_IRQ_RAW (0x410 >> 2) +#define TIMER_IRQ_MASK (0x414 >> 2) +#define TIMER_RELOAD (0x418 >> 2) +#define TIMER_PRE_DIV (0x41C >> 2) +#define TIMER_COUNTER (0x420 >> 2) + +// Locals to hold pointers to the hardware + +static volatile unsigned int *gpio ; +static volatile unsigned int *pwm ; +static volatile unsigned int *clk ; +static volatile unsigned int *pads ; +static volatile unsigned int *timer ; +static volatile unsigned int *timerIrqRaw ; + +// Export variables for the hardware pointers + +volatile unsigned int *_wiringPiGpio ; +volatile unsigned int *_wiringPiPwm ; +volatile unsigned int *_wiringPiClk ; +volatile unsigned int *_wiringPiPads ; +volatile unsigned int *_wiringPiTimer ; +volatile unsigned int *_wiringPiTimerIrqRaw ; + + +// Data for use with the boardId functions. +// The order of entries here to correspond with the PI_MODEL_X +// and PI_VERSION_X defines in wiringPi.h +// Only intended for the gpio command - use at your own risk! + +// piGpioBase: +// The base address of the GPIO memory mapped hardware IO + +#define GPIO_PERI_BASE_OLD 0x20000000 +#define GPIO_PERI_BASE_NEW 0x3F000000 + +static volatile unsigned int piGpioBase = 0 ; + +const char *piModelNames [16] = +{ + "Model A", // 0 + "Model B", // 1 + "Model A+", // 2 + "Model B+", // 3 + "Pi 2", // 4 + "Alpha", // 5 + "CM", // 6 + "Unknown07", // 07 + "Pi 3", // 08 + "Pi Zero", // 09 + "CM3", // 10 + "Unknown11", // 11 + "Pi Zero-W", // 12 + "Pi 3+", // 13 + "Unknown14", // 14 + "Unknown15", // 15 +} ; + +const char *piRevisionNames [16] = +{ + "00", + "01", + "02", + "03", + "04", + "05", + "06", + "07", + "08", + "09", + "10", + "11", + "12", + "13", + "14", + "15", +} ; + +const char *piMakerNames [16] = +{ + "Sony", // 0 + "Egoman", // 1 + "Embest", // 2 + "Unknown", // 3 + "Embest", // 4 + "Unknown05", // 5 + "Unknown06", // 6 + "Unknown07", // 7 + "Unknown08", // 8 + "Unknown09", // 9 + "Unknown10", // 10 + "Unknown11", // 11 + "Unknown12", // 12 + "Unknown13", // 13 + "Unknown14", // 14 + "Unknown15", // 15 +} ; + +const int piMemorySize [8] = +{ + 256, // 0 + 512, // 1 + 1024, // 2 + 0, // 3 + 0, // 4 + 0, // 5 + 0, // 6 + 0, // 7 +} ; + +// Time for easy calculations + +static uint64_t epochMilli, epochMicro ; + +// Misc + +static int wiringPiMode = WPI_MODE_UNINITIALISED ; +static volatile int pinPass = -1 ; +static pthread_mutex_t pinMutex ; + +// Debugging & Return codes + +int wiringPiDebug = FALSE ; +int wiringPiReturnCodes = FALSE ; + +// Use /dev/gpiomem ? + +int wiringPiTryGpioMem = FALSE ; + +// sysFds: +// Map a file descriptor from the /sys/class/gpio/gpioX/value + +static int sysFds [64] = +{ + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, +} ; + +// ISR Data + +static void (*isrFunctions [64])(void) ; + + +// Doing it the Arduino way with lookup tables... +// Yes, it's probably more innefficient than all the bit-twidling, but it +// does tend to make it all a bit clearer. At least to me! + +// pinToGpio: +// Take a Wiring pin (0 through X) and re-map it to the BCM_GPIO pin +// Cope for 3 different board revisions here. + +static int *pinToGpio ; + +// Revision 1, 1.1: + +static int pinToGpioR1 [64] = +{ + 17, 18, 21, 22, 23, 24, 25, 4, // From the Original Wiki - GPIO 0 through 7: wpi 0 - 7 + 0, 1, // I2C - SDA1, SCL1 wpi 8 - 9 + 8, 7, // SPI - CE1, CE0 wpi 10 - 11 + 10, 9, 11, // SPI - MOSI, MISO, SCLK wpi 12 - 14 + 14, 15, // UART - Tx, Rx wpi 15 - 16 + +// Padding: + + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // ... 31 + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // ... 47 + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // ... 63 +} ; + +// Revision 2: + +static int pinToGpioR2 [64] = +{ + 17, 18, 27, 22, 23, 24, 25, 4, // From the Original Wiki - GPIO 0 through 7: wpi 0 - 7 + 2, 3, // I2C - SDA0, SCL0 wpi 8 - 9 + 8, 7, // SPI - CE1, CE0 wpi 10 - 11 + 10, 9, 11, // SPI - MOSI, MISO, SCLK wpi 12 - 14 + 14, 15, // UART - Tx, Rx wpi 15 - 16 + 28, 29, 30, 31, // Rev 2: New GPIOs 8 though 11 wpi 17 - 20 + 5, 6, 13, 19, 26, // B+ wpi 21, 22, 23, 24, 25 + 12, 16, 20, 21, // B+ wpi 26, 27, 28, 29 + 0, 1, // B+ wpi 30, 31 + +// Padding: + + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // ... 47 + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // ... 63 +} ; + + +// physToGpio: +// Take a physical pin (1 through 26) and re-map it to the BCM_GPIO pin +// Cope for 2 different board revisions here. +// Also add in the P5 connector, so the P5 pins are 3,4,5,6, so 53,54,55,56 + +static int *physToGpio ; + +static int physToGpioR1 [64] = +{ + -1, // 0 + -1, -1, // 1, 2 + 0, -1, + 1, -1, + 4, 14, + -1, 15, + 17, 18, + 21, -1, + 22, 23, + -1, 24, + 10, -1, + 9, 25, + 11, 8, + -1, 7, // 25, 26 + + -1, -1, -1, -1, -1, // ... 31 + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // ... 47 + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // ... 63 +} ; + +static int physToGpioR2 [64] = +{ + -1, // 0 + -1, -1, // 1, 2 + 2, -1, + 3, -1, + 4, 14, + -1, 15, + 17, 18, + 27, -1, + 22, 23, + -1, 24, + 10, -1, + 9, 25, + 11, 8, + -1, 7, // 25, 26 + +// B+ + + 0, 1, + 5, -1, + 6, 12, + 13, -1, + 19, 16, + 26, 20, + -1, 21, + +// the P5 connector on the Rev 2 boards: + + -1, -1, + -1, -1, + -1, -1, + -1, -1, + -1, -1, + 28, 29, + 30, 31, + -1, -1, + -1, -1, + -1, -1, + -1, -1, +} ; + +// gpioToGPFSEL: +// Map a BCM_GPIO pin to it's Function Selection +// control port. (GPFSEL 0-5) +// Groups of 10 - 3 bits per Function - 30 bits per port + +static uint8_t gpioToGPFSEL [] = +{ + 0,0,0,0,0,0,0,0,0,0, + 1,1,1,1,1,1,1,1,1,1, + 2,2,2,2,2,2,2,2,2,2, + 3,3,3,3,3,3,3,3,3,3, + 4,4,4,4,4,4,4,4,4,4, + 5,5,5,5,5,5,5,5,5,5, +} ; + + +// gpioToShift +// Define the shift up for the 3 bits per pin in each GPFSEL port + +static uint8_t gpioToShift [] = +{ + 0,3,6,9,12,15,18,21,24,27, + 0,3,6,9,12,15,18,21,24,27, + 0,3,6,9,12,15,18,21,24,27, + 0,3,6,9,12,15,18,21,24,27, + 0,3,6,9,12,15,18,21,24,27, + 0,3,6,9,12,15,18,21,24,27, +} ; + + +// gpioToGPSET: +// (Word) offset to the GPIO Set registers for each GPIO pin + +static uint8_t gpioToGPSET [] = +{ + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, +} ; + +// gpioToGPCLR: +// (Word) offset to the GPIO Clear registers for each GPIO pin + +static uint8_t gpioToGPCLR [] = +{ + 10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, +} ; + + +// gpioToGPLEV: +// (Word) offset to the GPIO Input level registers for each GPIO pin + +static uint8_t gpioToGPLEV [] = +{ + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14, +} ; + + +#ifdef notYetReady +// gpioToEDS +// (Word) offset to the Event Detect Status + +static uint8_t gpioToEDS [] = +{ + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17, +} ; + +// gpioToREN +// (Word) offset to the Rising edge ENable register + +static uint8_t gpioToREN [] = +{ + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, +} ; + +// gpioToFEN +// (Word) offset to the Falling edgde ENable register + +static uint8_t gpioToFEN [] = +{ + 22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22, + 23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23, +} ; +#endif + + +// GPPUD: +// GPIO Pin pull up/down register + +#define GPPUD 37 + +// gpioToPUDCLK +// (Word) offset to the Pull Up Down Clock regsiter + +static uint8_t gpioToPUDCLK [] = +{ + 38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38, + 39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39, +} ; + + +// gpioToPwmALT +// the ALT value to put a GPIO pin into PWM mode + +static uint8_t gpioToPwmALT [] = +{ + 0, 0, 0, 0, 0, 0, 0, 0, // 0 -> 7 + 0, 0, 0, 0, FSEL_ALT0, FSEL_ALT0, 0, 0, // 8 -> 15 + 0, 0, FSEL_ALT5, FSEL_ALT5, 0, 0, 0, 0, // 16 -> 23 + 0, 0, 0, 0, 0, 0, 0, 0, // 24 -> 31 + 0, 0, 0, 0, 0, 0, 0, 0, // 32 -> 39 + FSEL_ALT0, FSEL_ALT0, 0, 0, 0, FSEL_ALT0, 0, 0, // 40 -> 47 + 0, 0, 0, 0, 0, 0, 0, 0, // 48 -> 55 + 0, 0, 0, 0, 0, 0, 0, 0, // 56 -> 63 +} ; + + +// gpioToPwmPort +// The port value to put a GPIO pin into PWM mode + +static uint8_t gpioToPwmPort [] = +{ + 0, 0, 0, 0, 0, 0, 0, 0, // 0 -> 7 + 0, 0, 0, 0, PWM0_DATA, PWM1_DATA, 0, 0, // 8 -> 15 + 0, 0, PWM0_DATA, PWM1_DATA, 0, 0, 0, 0, // 16 -> 23 + 0, 0, 0, 0, 0, 0, 0, 0, // 24 -> 31 + 0, 0, 0, 0, 0, 0, 0, 0, // 32 -> 39 + PWM0_DATA, PWM1_DATA, 0, 0, 0, PWM1_DATA, 0, 0, // 40 -> 47 + 0, 0, 0, 0, 0, 0, 0, 0, // 48 -> 55 + 0, 0, 0, 0, 0, 0, 0, 0, // 56 -> 63 + +} ; + +// gpioToGpClkALT: +// ALT value to put a GPIO pin into GP Clock mode. +// On the Pi we can really only use BCM_GPIO_4 and BCM_GPIO_21 +// for clocks 0 and 1 respectively, however I'll include the full +// list for completeness - maybe one day... + +#define GPIO_CLOCK_SOURCE 1 + +// gpioToGpClkALT0: + +static uint8_t gpioToGpClkALT0 [] = +{ + 0, 0, 0, 0, FSEL_ALT0, FSEL_ALT0, FSEL_ALT0, 0, // 0 -> 7 + 0, 0, 0, 0, 0, 0, 0, 0, // 8 -> 15 + 0, 0, 0, 0, FSEL_ALT5, FSEL_ALT5, 0, 0, // 16 -> 23 + 0, 0, 0, 0, 0, 0, 0, 0, // 24 -> 31 + FSEL_ALT0, 0, FSEL_ALT0, 0, 0, 0, 0, 0, // 32 -> 39 + 0, 0, FSEL_ALT0, FSEL_ALT0, FSEL_ALT0, 0, 0, 0, // 40 -> 47 + 0, 0, 0, 0, 0, 0, 0, 0, // 48 -> 55 + 0, 0, 0, 0, 0, 0, 0, 0, // 56 -> 63 +} ; + +// gpioToClk: +// (word) Offsets to the clock Control and Divisor register + +static uint8_t gpioToClkCon [] = +{ + -1, -1, -1, -1, 28, 30, 32, -1, // 0 -> 7 + -1, -1, -1, -1, -1, -1, -1, -1, // 8 -> 15 + -1, -1, -1, -1, 28, 30, -1, -1, // 16 -> 23 + -1, -1, -1, -1, -1, -1, -1, -1, // 24 -> 31 + 28, -1, 28, -1, -1, -1, -1, -1, // 32 -> 39 + -1, -1, 28, 30, 28, -1, -1, -1, // 40 -> 47 + -1, -1, -1, -1, -1, -1, -1, -1, // 48 -> 55 + -1, -1, -1, -1, -1, -1, -1, -1, // 56 -> 63 +} ; + +static uint8_t gpioToClkDiv [] = +{ + -1, -1, -1, -1, 29, 31, 33, -1, // 0 -> 7 + -1, -1, -1, -1, -1, -1, -1, -1, // 8 -> 15 + -1, -1, -1, -1, 29, 31, -1, -1, // 16 -> 23 + -1, -1, -1, -1, -1, -1, -1, -1, // 24 -> 31 + 29, -1, 29, -1, -1, -1, -1, -1, // 32 -> 39 + -1, -1, 29, 31, 29, -1, -1, -1, // 40 -> 47 + -1, -1, -1, -1, -1, -1, -1, -1, // 48 -> 55 + -1, -1, -1, -1, -1, -1, -1, -1, // 56 -> 63 +} ; + + +/* + * Functions + ********************************************************************************* + */ + + +/* + * wiringPiFailure: + * Fail. Or not. + ********************************************************************************* + */ + +int wiringPiFailure (int fatal, const char *message, ...) +{ + va_list argp ; + char buffer [1024] ; + + if (!fatal && wiringPiReturnCodes) + return -1 ; + + va_start (argp, message) ; + vsnprintf (buffer, 1023, message, argp) ; + va_end (argp) ; + + fprintf (stderr, "%s", buffer) ; + exit (EXIT_FAILURE) ; + + return 0 ; +} + + +/* + * setupCheck + * Another sanity check because some users forget to call the setup + * function. Mosty because they need feeding C drip by drip )-: + ********************************************************************************* + */ + +static void setupCheck (const char *fName) +{ + if (!wiringPiSetuped) + { + fprintf (stderr, "%s: You have not called one of the wiringPiSetup\n" + " functions, so I'm aborting your program before it crashes anyway.\n", fName) ; + exit (EXIT_FAILURE) ; + } +} + +/* + * gpioMemCheck: + * See if we're using the /dev/gpiomem interface, if-so then some operations + * can't be done and will crash the Pi. + ********************************************************************************* + */ + +static void usingGpioMemCheck (const char *what) +{ + if (usingGpioMem) + { + fprintf (stderr, "%s: Unable to do this when using /dev/gpiomem. Try sudo?\n", what) ; + exit (EXIT_FAILURE) ; + } +} + + + +/* + * piGpioLayout: + * Return a number representing the hardware revision of the board. + * This is not strictly the board revision but is used to check the + * layout of the GPIO connector - and there are 2 types that we are + * really interested in here. The very earliest Pi's and the + * ones that came after that which switched some pins .... + * + * Revision 1 really means the early Model A and B's. + * Revision 2 is everything else - it covers the B, B+ and CM. + * ... and the Pi 2 - which is a B+ ++ ... + * ... and the Pi 0 - which is an A+ ... + * + * The main difference between the revision 1 and 2 system that I use here + * is the mapping of the GPIO pins. From revision 2, the Pi Foundation changed + * 3 GPIO pins on the (original) 26-way header - BCM_GPIO 22 was dropped and + * replaced with 27, and 0 + 1 - I2C bus 0 was changed to 2 + 3; I2C bus 1. + * + * Additionally, here we set the piModel2 flag too. This is again, nothing to + * do with the actual model, but the major version numbers - the GPIO base + * hardware address changed at model 2 and above (not the Zero though) + * + ********************************************************************************* + */ + +static void piGpioLayoutOops (const char *why) +{ + fprintf (stderr, "Oops: Unable to determine board revision from /proc/cpuinfo\n") ; + fprintf (stderr, " -> %s\n", why) ; + fprintf (stderr, " -> You'd best google the error to find out why.\n") ; +//fprintf (stderr, " -> http://www.raspberrypi.org/phpBB3/viewtopic.php?p=184410#p184410\n") ; + exit (EXIT_FAILURE) ; +} + +int piGpioLayout (void) +{ + FILE *cpuFd ; + char line [120] ; + char *c ; + static int gpioLayout = -1 ; + + if (gpioLayout != -1) // No point checking twice + return gpioLayout ; + + if ((cpuFd = fopen ("/proc/cpuinfo", "r")) == NULL) + piGpioLayoutOops ("Unable to open /proc/cpuinfo") ; + +// Start by looking for the Architecture to make sure we're really running +// on a Pi. I'm getting fed-up with people whinging at me because +// they can't get it to work on weirdFruitPi boards... + + while (fgets (line, 120, cpuFd) != NULL) + if (strncmp (line, "Hardware", 8) == 0) + break ; + + if (strncmp (line, "Hardware", 8) != 0) + piGpioLayoutOops ("No \"Hardware\" line") ; + + if (wiringPiDebug) + printf ("piGpioLayout: Hardware: %s\n", line) ; + +// See if it's BCM2708 or BCM2709 or the new BCM2835. + +// OK. As of Kernel 4.8, we have BCM2835 only, regardless of model. +// However I still want to check because it will trap the cheapskates and rip- +// off merchants who want to use wiringPi on non-Raspberry Pi platforms - which +// I do not support so don't email me your bleating whinges about anything +// other than a genuine Raspberry Pi. + +#ifdef DONT_CARE_ANYMORE + if (! (strstr (line, "BCM2708") || strstr (line, "BCM2709") || strstr (line, "BCM2835"))) + { + fprintf (stderr, "Unable to determine hardware version. I see: %s,\n", line) ; + fprintf (stderr, " - expecting BCM2708, BCM2709 or BCM2835.\n") ; + fprintf (stderr, "If this is a genuine Raspberry Pi then please report this\n") ; + fprintf (stderr, "to projects@drogon.net. If this is not a Raspberry Pi then you\n") ; + fprintf (stderr, "are on your own as wiringPi is designed to support the\n") ; + fprintf (stderr, "Raspberry Pi ONLY.\n") ; + exit (EXIT_FAILURE) ; + } +#endif + +// Actually... That has caused me more than 10,000 emails so-far. Mosty by +// people who think they know better by creating a statically linked +// version that will not run with a new 4.9 kernel. I utterly hate and +// despise those people. +// +// I also get bleats from people running other than Raspbian with another +// distros compiled kernel rather than a foundation compiled kernel, so +// this might actually help them. It might not - I only have the capacity +// to support Raspbian. +// +// However, I've decided to leave this check out and rely purely on the +// Revision: line for now. It will not work on a non-pi hardware or weird +// kernels that don't give you a suitable revision line. + +// So - we're Probably on a Raspberry Pi. Check the revision field for the real +// hardware type +// In-future, I ought to use the device tree as there are now Pi entries in +// /proc/device-tree/ ... +// but I'll leave that for the next revision. Or the next. + +// Isolate the Revision line + + rewind (cpuFd) ; + while (fgets (line, 120, cpuFd) != NULL) + if (strncmp (line, "Revision", 8) == 0) + break ; + + fclose (cpuFd) ; + + if (strncmp (line, "Revision", 8) != 0) + piGpioLayoutOops ("No \"Revision\" line") ; + +// Chomp trailing CR/NL + + for (c = &line [strlen (line) - 1] ; (*c == '\n') || (*c == '\r') ; --c) + *c = 0 ; + + if (wiringPiDebug) + printf ("piGpioLayout: Revision string: %s\n", line) ; + +// Scan to the first character of the revision number + + for (c = line ; *c ; ++c) + if (*c == ':') + break ; + + if (*c != ':') + piGpioLayoutOops ("Bogus \"Revision\" line (no colon)") ; + +// Chomp spaces + + ++c ; + while (isspace (*c)) + ++c ; + + if (!isxdigit (*c)) + piGpioLayoutOops ("Bogus \"Revision\" line (no hex digit at start of revision)") ; + +// Make sure its long enough + + if (strlen (c) < 4) + piGpioLayoutOops ("Bogus revision line (too small)") ; + +// Isolate last 4 characters: (in-case of overvolting or new encoding scheme) + + c = c + strlen (c) - 4 ; + + if (wiringPiDebug) + printf ("piGpioLayout: last4Chars are: \"%s\"\n", c) ; + + if ( (strcmp (c, "0002") == 0) || (strcmp (c, "0003") == 0)) + gpioLayout = 1 ; + else + gpioLayout = 2 ; // Covers everything else from the B revision 2 to the B+, the Pi v2, v3, zero and CM's. + + if (wiringPiDebug) + printf ("piGpioLayoutOops: Returning revision: %d\n", gpioLayout) ; + + return gpioLayout ; +} + +/* + * piBoardRev: + * Deprecated, but does the same as piGpioLayout + ********************************************************************************* + */ + +int piBoardRev (void) +{ + return piGpioLayout () ; +} + + + +/* + * piBoardId: + * Return the real details of the board we have. + * + * This is undocumented and really only intended for the GPIO command. + * Use at your own risk! + * + * Seems there are some boards with 0000 in them (mistake in manufacture) + * So the distinction between boards that I can see is: + * + * 0000 - Error + * 0001 - Not used + * + * Original Pi boards: + * 0002 - Model B, Rev 1, 256MB, Egoman + * 0003 - Model B, Rev 1.1, 256MB, Egoman, Fuses/D14 removed. + * + * Newer Pi's with remapped GPIO: + * 0004 - Model B, Rev 1.2, 256MB, Sony + * 0005 - Model B, Rev 1.2, 256MB, Egoman + * 0006 - Model B, Rev 1.2, 256MB, Egoman + * + * 0007 - Model A, Rev 1.2, 256MB, Egoman + * 0008 - Model A, Rev 1.2, 256MB, Sony + * 0009 - Model A, Rev 1.2, 256MB, Egoman + * + * 000d - Model B, Rev 1.2, 512MB, Egoman (Red Pi, Blue Pi?) + * 000e - Model B, Rev 1.2, 512MB, Sony + * 000f - Model B, Rev 1.2, 512MB, Egoman + * + * 0010 - Model B+, Rev 1.2, 512MB, Sony + * 0013 - Model B+ Rev 1.2, 512MB, Embest + * 0016 - Model B+ Rev 1.2, 512MB, Sony + * 0019 - Model B+ Rev 1.2, 512MB, Egoman + * + * 0011 - Pi CM, Rev 1.1, 512MB, Sony + * 0014 - Pi CM, Rev 1.1, 512MB, Embest + * 0017 - Pi CM, Rev 1.1, 512MB, Sony + * 001a - Pi CM, Rev 1.1, 512MB, Egoman + * + * 0012 - Model A+ Rev 1.1, 256MB, Sony + * 0015 - Model A+ Rev 1.1, 512MB, Embest + * 0018 - Model A+ Rev 1.1, 256MB, Sony + * 001b - Model A+ Rev 1.1, 256MB, Egoman + * + * A small thorn is the olde style overvolting - that will add in + * 1000000 + * + * The Pi compute module has an revision of 0011 or 0014 - since we only + * check the last digit, then it's 1, therefore it'll default to not 2 or + * 3 for a Rev 1, so will appear as a Rev 2. This is fine for the most part, but + * we'll properly detect the Compute Module later and adjust accordingly. + * + * And then things changed with the introduction of the v2... + * + * For Pi v2 and subsequent models - e.g. the Zero: + * + * [USER:8] [NEW:1] [MEMSIZE:3] [MANUFACTURER:4] [PROCESSOR:4] [TYPE:8] [REV:4] + * NEW 23: will be 1 for the new scheme, 0 for the old scheme + * MEMSIZE 20: 0=256M 1=512M 2=1G + * MANUFACTURER 16: 0=SONY 1=EGOMAN 2=EMBEST + * PROCESSOR 12: 0=2835 1=2836 + * TYPE 04: 0=MODELA 1=MODELB 2=MODELA+ 3=MODELB+ 4=Pi2 MODEL B 5=ALPHA 6=CM + * REV 00: 0=REV0 1=REV1 2=REV2 + ********************************************************************************* + */ + +void piBoardId (int *model, int *rev, int *mem, int *maker, int *warranty) +{ + FILE *cpuFd ; + char line [120] ; + char *c ; + unsigned int revision ; + int bRev, bType, bProc, bMfg, bMem, bWarranty ; + +// Will deal with the properly later on - for now, lets just get it going... +// unsigned int modelNum ; + + (void)piGpioLayout () ; // Call this first to make sure all's OK. Don't care about the result. + + if ((cpuFd = fopen ("/proc/cpuinfo", "r")) == NULL) + piGpioLayoutOops ("Unable to open /proc/cpuinfo") ; + + while (fgets (line, 120, cpuFd) != NULL) + if (strncmp (line, "Revision", 8) == 0) + break ; + + fclose (cpuFd) ; + + if (strncmp (line, "Revision", 8) != 0) + piGpioLayoutOops ("No \"Revision\" line") ; + +// Chomp trailing CR/NL + + for (c = &line [strlen (line) - 1] ; (*c == '\n') || (*c == '\r') ; --c) + *c = 0 ; + + if (wiringPiDebug) + printf ("piBoardId: Revision string: %s\n", line) ; + +// Need to work out if it's using the new or old encoding scheme: + +// Scan to the first character of the revision number + + for (c = line ; *c ; ++c) + if (*c == ':') + break ; + + if (*c != ':') + piGpioLayoutOops ("Bogus \"Revision\" line (no colon)") ; + +// Chomp spaces + + ++c ; + while (isspace (*c)) + ++c ; + + if (!isxdigit (*c)) + piGpioLayoutOops ("Bogus \"Revision\" line (no hex digit at start of revision)") ; + + revision = (unsigned int)strtol (c, NULL, 16) ; // Hex number with no leading 0x + +// Check for new way: + + if ((revision & (1 << 23)) != 0) // New way + { + if (wiringPiDebug) + printf ("piBoardId: New Way: revision is: %08X\n", revision) ; + + bRev = (revision & (0x0F << 0)) >> 0 ; + bType = (revision & (0xFF << 4)) >> 4 ; + bProc = (revision & (0x0F << 12)) >> 12 ; // Not used for now. + bMfg = (revision & (0x0F << 16)) >> 16 ; + bMem = (revision & (0x07 << 20)) >> 20 ; + bWarranty = (revision & (0x03 << 24)) != 0 ; + + *model = bType ; + *rev = bRev ; + *mem = bMem ; + *maker = bMfg ; + *warranty = bWarranty ; + + if (wiringPiDebug) + printf ("piBoardId: rev: %d, type: %d, proc: %d, mfg: %d, mem: %d, warranty: %d\n", + bRev, bType, bProc, bMfg, bMem, bWarranty) ; + } + else // Old way + { + if (wiringPiDebug) + printf ("piBoardId: Old Way: revision is: %s\n", c) ; + + if (!isdigit (*c)) + piGpioLayoutOops ("Bogus \"Revision\" line (no digit at start of revision)") ; + +// Make sure its long enough + + if (strlen (c) < 4) + piGpioLayoutOops ("Bogus \"Revision\" line (not long enough)") ; + +// If longer than 4, we'll assume it's been overvolted + + *warranty = strlen (c) > 4 ; + +// Extract last 4 characters: + + c = c + strlen (c) - 4 ; + +// Fill out the replys as appropriate + + /**/ if (strcmp (c, "0002") == 0) { *model = PI_MODEL_B ; *rev = PI_VERSION_1 ; *mem = 0 ; *maker = PI_MAKER_EGOMAN ; } + else if (strcmp (c, "0003") == 0) { *model = PI_MODEL_B ; *rev = PI_VERSION_1_1 ; *mem = 0 ; *maker = PI_MAKER_EGOMAN ; } + + else if (strcmp (c, "0004") == 0) { *model = PI_MODEL_B ; *rev = PI_VERSION_1_2 ; *mem = 0 ; *maker = PI_MAKER_SONY ; } + else if (strcmp (c, "0005") == 0) { *model = PI_MODEL_B ; *rev = PI_VERSION_1_2 ; *mem = 0 ; *maker = PI_MAKER_EGOMAN ; } + else if (strcmp (c, "0006") == 0) { *model = PI_MODEL_B ; *rev = PI_VERSION_1_2 ; *mem = 0 ; *maker = PI_MAKER_EGOMAN ; } + + else if (strcmp (c, "0007") == 0) { *model = PI_MODEL_A ; *rev = PI_VERSION_1_2 ; *mem = 0 ; *maker = PI_MAKER_EGOMAN ; } + else if (strcmp (c, "0008") == 0) { *model = PI_MODEL_A ; *rev = PI_VERSION_1_2 ; *mem = 0 ; *maker = PI_MAKER_SONY ; ; } + else if (strcmp (c, "0009") == 0) { *model = PI_MODEL_A ; *rev = PI_VERSION_1_2 ; *mem = 0 ; *maker = PI_MAKER_EGOMAN ; } + + else if (strcmp (c, "000d") == 0) { *model = PI_MODEL_B ; *rev = PI_VERSION_1_2 ; *mem = 1 ; *maker = PI_MAKER_EGOMAN ; } + else if (strcmp (c, "000e") == 0) { *model = PI_MODEL_B ; *rev = PI_VERSION_1_2 ; *mem = 1 ; *maker = PI_MAKER_SONY ; } + else if (strcmp (c, "000f") == 0) { *model = PI_MODEL_B ; *rev = PI_VERSION_1_2 ; *mem = 1 ; *maker = PI_MAKER_EGOMAN ; } + + else if (strcmp (c, "0010") == 0) { *model = PI_MODEL_BP ; *rev = PI_VERSION_1_2 ; *mem = 1 ; *maker = PI_MAKER_SONY ; } + else if (strcmp (c, "0013") == 0) { *model = PI_MODEL_BP ; *rev = PI_VERSION_1_2 ; *mem = 1 ; *maker = PI_MAKER_EMBEST ; } + else if (strcmp (c, "0016") == 0) { *model = PI_MODEL_BP ; *rev = PI_VERSION_1_2 ; *mem = 1 ; *maker = PI_MAKER_SONY ; } + else if (strcmp (c, "0019") == 0) { *model = PI_MODEL_BP ; *rev = PI_VERSION_1_2 ; *mem = 1 ; *maker = PI_MAKER_EGOMAN ; } + + else if (strcmp (c, "0011") == 0) { *model = PI_MODEL_CM ; *rev = PI_VERSION_1_1 ; *mem = 1 ; *maker = PI_MAKER_SONY ; } + else if (strcmp (c, "0014") == 0) { *model = PI_MODEL_CM ; *rev = PI_VERSION_1_1 ; *mem = 1 ; *maker = PI_MAKER_EMBEST ; } + else if (strcmp (c, "0017") == 0) { *model = PI_MODEL_CM ; *rev = PI_VERSION_1_1 ; *mem = 1 ; *maker = PI_MAKER_SONY ; } + else if (strcmp (c, "001a") == 0) { *model = PI_MODEL_CM ; *rev = PI_VERSION_1_1 ; *mem = 1 ; *maker = PI_MAKER_EGOMAN ; } + + else if (strcmp (c, "0012") == 0) { *model = PI_MODEL_AP ; *rev = PI_VERSION_1_1 ; *mem = 0 ; *maker = PI_MAKER_SONY ; } + else if (strcmp (c, "0015") == 0) { *model = PI_MODEL_AP ; *rev = PI_VERSION_1_1 ; *mem = 1 ; *maker = PI_MAKER_EMBEST ; } + else if (strcmp (c, "0018") == 0) { *model = PI_MODEL_AP ; *rev = PI_VERSION_1_1 ; *mem = 0 ; *maker = PI_MAKER_SONY ; } + else if (strcmp (c, "001b") == 0) { *model = PI_MODEL_AP ; *rev = PI_VERSION_1_1 ; *mem = 0 ; *maker = PI_MAKER_EGOMAN ; } + + else { *model = 0 ; *rev = 0 ; *mem = 0 ; *maker = 0 ; } + } +} + + + +/* + * wpiPinToGpio: + * Translate a wiringPi Pin number to native GPIO pin number. + * Provided for external support. + ********************************************************************************* + */ + +int wpiPinToGpio (int wpiPin) +{ + return pinToGpio [wpiPin & 63] ; +} + + +/* + * physPinToGpio: + * Translate a physical Pin number to native GPIO pin number. + * Provided for external support. + ********************************************************************************* + */ + +int physPinToGpio (int physPin) +{ + return physToGpio [physPin & 63] ; +} + + +/* + * setPadDrive: + * Set the PAD driver value + ********************************************************************************* + */ + +void setPadDrive (int group, int value) +{ + uint32_t wrVal ; + + if ((wiringPiMode == WPI_MODE_PINS) || (wiringPiMode == WPI_MODE_PHYS) || (wiringPiMode == WPI_MODE_GPIO)) + { + if ((group < 0) || (group > 2)) + return ; + + wrVal = BCM_PASSWORD | 0x18 | (value & 7) ; + *(pads + group + 11) = wrVal ; + + if (wiringPiDebug) + { + printf ("setPadDrive: Group: %d, value: %d (%08X)\n", group, value, wrVal) ; + printf ("Read : %08X\n", *(pads + group + 11)) ; + } + } +} + + +/* + * getAlt: + * Returns the ALT bits for a given port. Only really of-use + * for the gpio readall command (I think) + ********************************************************************************* + */ + +int getAlt (int pin) +{ + int fSel, shift, alt ; + + pin &= 63 ; + + /**/ if (wiringPiMode == WPI_MODE_PINS) + pin = pinToGpio [pin] ; + else if (wiringPiMode == WPI_MODE_PHYS) + pin = physToGpio [pin] ; + else if (wiringPiMode != WPI_MODE_GPIO) + return 0 ; + + fSel = gpioToGPFSEL [pin] ; + shift = gpioToShift [pin] ; + + alt = (*(gpio + fSel) >> shift) & 7 ; + + return alt ; +} + + +/* + * pwmSetMode: + * Select the native "balanced" mode, or standard mark:space mode + ********************************************************************************* + */ + +void pwmSetMode (int mode) +{ + if ((wiringPiMode == WPI_MODE_PINS) || (wiringPiMode == WPI_MODE_PHYS) || (wiringPiMode == WPI_MODE_GPIO)) + { + if (mode == PWM_MODE_MS) + *(pwm + PWM_CONTROL) = PWM0_ENABLE | PWM1_ENABLE | PWM0_MS_MODE | PWM1_MS_MODE ; + else + *(pwm + PWM_CONTROL) = PWM0_ENABLE | PWM1_ENABLE ; + } +} + + +/* + * pwmSetRange: + * Set the PWM range register. We set both range registers to the same + * value. If you want different in your own code, then write your own. + ********************************************************************************* + */ + +void pwmSetRange (unsigned int range) +{ + if ((wiringPiMode == WPI_MODE_PINS) || (wiringPiMode == WPI_MODE_PHYS) || (wiringPiMode == WPI_MODE_GPIO)) + { + *(pwm + PWM0_RANGE) = range ; delayMicroseconds (10) ; + *(pwm + PWM1_RANGE) = range ; delayMicroseconds (10) ; + } +} + + +/* + * pwmSetClock: + * Set/Change the PWM clock. Originally my code, but changed + * (for the better!) by Chris Hall, + * after further study of the manual and testing with a 'scope + ********************************************************************************* + */ + +void pwmSetClock (int divisor) +{ + uint32_t pwm_control ; + divisor &= 4095 ; + + if ((wiringPiMode == WPI_MODE_PINS) || (wiringPiMode == WPI_MODE_PHYS) || (wiringPiMode == WPI_MODE_GPIO)) + { + if (wiringPiDebug) + printf ("Setting to: %d. Current: 0x%08X\n", divisor, *(clk + PWMCLK_DIV)) ; + + pwm_control = *(pwm + PWM_CONTROL) ; // preserve PWM_CONTROL + +// We need to stop PWM prior to stopping PWM clock in MS mode otherwise BUSY +// stays high. + + *(pwm + PWM_CONTROL) = 0 ; // Stop PWM + +// Stop PWM clock before changing divisor. The delay after this does need to +// this big (95uS occasionally fails, 100uS OK), it's almost as though the BUSY +// flag is not working properly in balanced mode. Without the delay when DIV is +// adjusted the clock sometimes switches to very slow, once slow further DIV +// adjustments do nothing and it's difficult to get out of this mode. + + *(clk + PWMCLK_CNTL) = BCM_PASSWORD | 0x01 ; // Stop PWM Clock + delayMicroseconds (110) ; // prevents clock going sloooow + + while ((*(clk + PWMCLK_CNTL) & 0x80) != 0) // Wait for clock to be !BUSY + delayMicroseconds (1) ; + + *(clk + PWMCLK_DIV) = BCM_PASSWORD | (divisor << 12) ; + + *(clk + PWMCLK_CNTL) = BCM_PASSWORD | 0x11 ; // Start PWM clock + *(pwm + PWM_CONTROL) = pwm_control ; // restore PWM_CONTROL + + if (wiringPiDebug) + printf ("Set to: %d. Now : 0x%08X\n", divisor, *(clk + PWMCLK_DIV)) ; + } +} + + +/* + * gpioClockSet: + * Set the frequency on a GPIO clock pin + ********************************************************************************* + */ + +void gpioClockSet (int pin, int freq) +{ + int divi, divr, divf ; + + pin &= 63 ; + + /**/ if (wiringPiMode == WPI_MODE_PINS) + pin = pinToGpio [pin] ; + else if (wiringPiMode == WPI_MODE_PHYS) + pin = physToGpio [pin] ; + else if (wiringPiMode != WPI_MODE_GPIO) + return ; + + divi = 19200000 / freq ; + divr = 19200000 % freq ; + divf = (int)((double)divr * 4096.0 / 19200000.0) ; + + if (divi > 4095) + divi = 4095 ; + + *(clk + gpioToClkCon [pin]) = BCM_PASSWORD | GPIO_CLOCK_SOURCE ; // Stop GPIO Clock + while ((*(clk + gpioToClkCon [pin]) & 0x80) != 0) // ... and wait + ; + + *(clk + gpioToClkDiv [pin]) = BCM_PASSWORD | (divi << 12) | divf ; // Set dividers + *(clk + gpioToClkCon [pin]) = BCM_PASSWORD | 0x10 | GPIO_CLOCK_SOURCE ; // Start Clock +} + + +/* + * wiringPiFindNode: + * Locate our device node + ********************************************************************************* + */ + +struct wiringPiNodeStruct *wiringPiFindNode (int pin) +{ + struct wiringPiNodeStruct *node = wiringPiNodes ; + + while (node != NULL) + if ((pin >= node->pinBase) && (pin <= node->pinMax)) + return node ; + else + node = node->next ; + + return NULL ; +} + + +/* + * wiringPiNewNode: + * Create a new GPIO node into the wiringPi handling system + ********************************************************************************* + */ + +static void pinModeDummy (UNU struct wiringPiNodeStruct *node, UNU int pin, UNU int mode) { return ; } +static void pullUpDnControlDummy (UNU struct wiringPiNodeStruct *node, UNU int pin, UNU int pud) { return ; } +static unsigned int digitalRead8Dummy (UNU struct wiringPiNodeStruct *node, UNU int UNU pin) { return 0 ; } +static void digitalWrite8Dummy (UNU struct wiringPiNodeStruct *node, UNU int pin, UNU int value) { return ; } +static int digitalReadDummy (UNU struct wiringPiNodeStruct *node, UNU int UNU pin) { return LOW ; } +static void digitalWriteDummy (UNU struct wiringPiNodeStruct *node, UNU int pin, UNU int value) { return ; } +static void pwmWriteDummy (UNU struct wiringPiNodeStruct *node, UNU int pin, UNU int value) { return ; } +static int analogReadDummy (UNU struct wiringPiNodeStruct *node, UNU int pin) { return 0 ; } +static void analogWriteDummy (UNU struct wiringPiNodeStruct *node, UNU int pin, UNU int value) { return ; } + +struct wiringPiNodeStruct *wiringPiNewNode (int pinBase, int numPins) +{ + int pin ; + struct wiringPiNodeStruct *node ; + +// Minimum pin base is 64 + + if (pinBase < 64) + (void)wiringPiFailure (WPI_FATAL, "wiringPiNewNode: pinBase of %d is < 64\n", pinBase) ; + +// Check all pins in-case there is overlap: + + for (pin = pinBase ; pin < (pinBase + numPins) ; ++pin) + if (wiringPiFindNode (pin) != NULL) + (void)wiringPiFailure (WPI_FATAL, "wiringPiNewNode: Pin %d overlaps with existing definition\n", pin) ; + + node = (struct wiringPiNodeStruct *)calloc (sizeof (struct wiringPiNodeStruct), 1) ; // calloc zeros + if (node == NULL) + (void)wiringPiFailure (WPI_FATAL, "wiringPiNewNode: Unable to allocate memory: %s\n", strerror (errno)) ; + + node->pinBase = pinBase ; + node->pinMax = pinBase + numPins - 1 ; + node->pinMode = pinModeDummy ; + node->pullUpDnControl = pullUpDnControlDummy ; + node->digitalRead = digitalReadDummy ; +//node->digitalRead8 = digitalRead8Dummy ; + node->digitalWrite = digitalWriteDummy ; +//node->digitalWrite8 = digitalWrite8Dummy ; + node->pwmWrite = pwmWriteDummy ; + node->analogRead = analogReadDummy ; + node->analogWrite = analogWriteDummy ; + node->next = wiringPiNodes ; + wiringPiNodes = node ; + + return node ; +} + + +#ifdef notYetReady +/* + * pinED01: + * pinED10: + * Enables edge-detect mode on a pin - from a 0 to a 1 or 1 to 0 + * Pin must already be in input mode with appropriate pull up/downs set. + ********************************************************************************* + */ + +void pinEnableED01Pi (int pin) +{ + pin = pinToGpio [pin & 63] ; +} +#endif + + +/* + ********************************************************************************* + * Core Functions + ********************************************************************************* + */ + +/* + * pinModeAlt: + * This is an un-documented special to let you set any pin to any mode + ********************************************************************************* + */ + +void pinModeAlt (int pin, int mode) +{ + int fSel, shift ; + + setupCheck ("pinModeAlt") ; + + if ((pin & PI_GPIO_MASK) == 0) // On-board pin + { + /**/ if (wiringPiMode == WPI_MODE_PINS) + pin = pinToGpio [pin] ; + else if (wiringPiMode == WPI_MODE_PHYS) + pin = physToGpio [pin] ; + else if (wiringPiMode != WPI_MODE_GPIO) + return ; + + fSel = gpioToGPFSEL [pin] ; + shift = gpioToShift [pin] ; + + *(gpio + fSel) = (*(gpio + fSel) & ~(7 << shift)) | ((mode & 0x7) << shift) ; + } +} + + +/* + * pinMode: + * Sets the mode of a pin to be input, output or PWM output + ********************************************************************************* + */ + +void pinMode (int pin, int mode) +{ + int fSel, shift, alt ; + struct wiringPiNodeStruct *node = wiringPiNodes ; + int origPin = pin ; + + setupCheck ("pinMode") ; + + if ((pin & PI_GPIO_MASK) == 0) // On-board pin + { + /**/ if (wiringPiMode == WPI_MODE_PINS) + pin = pinToGpio [pin] ; + else if (wiringPiMode == WPI_MODE_PHYS) + pin = physToGpio [pin] ; + else if (wiringPiMode != WPI_MODE_GPIO) + return ; + + softPwmStop (origPin) ; + softToneStop (origPin) ; + + fSel = gpioToGPFSEL [pin] ; + shift = gpioToShift [pin] ; + + /**/ if (mode == INPUT) + *(gpio + fSel) = (*(gpio + fSel) & ~(7 << shift)) ; // Sets bits to zero = input + else if (mode == OUTPUT) + *(gpio + fSel) = (*(gpio + fSel) & ~(7 << shift)) | (1 << shift) ; + else if (mode == SOFT_PWM_OUTPUT) + softPwmCreate (origPin, 0, 100) ; + else if (mode == SOFT_TONE_OUTPUT) + softToneCreate (origPin) ; + else if (mode == PWM_TONE_OUTPUT) + { + pinMode (origPin, PWM_OUTPUT) ; // Call myself to enable PWM mode + pwmSetMode (PWM_MODE_MS) ; + } + else if (mode == PWM_OUTPUT) + { + if ((alt = gpioToPwmALT [pin]) == 0) // Not a hardware capable PWM pin + return ; + + usingGpioMemCheck ("pinMode PWM") ; + +// Set pin to PWM mode + + *(gpio + fSel) = (*(gpio + fSel) & ~(7 << shift)) | (alt << shift) ; + delayMicroseconds (110) ; // See comments in pwmSetClockWPi + + pwmSetMode (PWM_MODE_BAL) ; // Pi default mode + pwmSetRange (1024) ; // Default range of 1024 + pwmSetClock (32) ; // 19.2 / 32 = 600KHz - Also starts the PWM + } + else if (mode == GPIO_CLOCK) + { + if ((alt = gpioToGpClkALT0 [pin]) == 0) // Not a GPIO_CLOCK pin + return ; + + usingGpioMemCheck ("pinMode CLOCK") ; + +// Set pin to GPIO_CLOCK mode and set the clock frequency to 100KHz + + *(gpio + fSel) = (*(gpio + fSel) & ~(7 << shift)) | (alt << shift) ; + delayMicroseconds (110) ; + gpioClockSet (pin, 100000) ; + } + } + else + { + if ((node = wiringPiFindNode (pin)) != NULL) + node->pinMode (node, pin, mode) ; + return ; + } +} + + +/* + * pullUpDownCtrl: + * Control the internal pull-up/down resistors on a GPIO pin. + ********************************************************************************* + */ + +void pullUpDnControl (int pin, int pud) +{ + struct wiringPiNodeStruct *node = wiringPiNodes ; + + setupCheck ("pullUpDnControl") ; + + if ((pin & PI_GPIO_MASK) == 0) // On-Board Pin + { + /**/ if (wiringPiMode == WPI_MODE_PINS) + pin = pinToGpio [pin] ; + else if (wiringPiMode == WPI_MODE_PHYS) + pin = physToGpio [pin] ; + else if (wiringPiMode != WPI_MODE_GPIO) + return ; + + *(gpio + GPPUD) = pud & 3 ; delayMicroseconds (5) ; + *(gpio + gpioToPUDCLK [pin]) = 1 << (pin & 31) ; delayMicroseconds (5) ; + + *(gpio + GPPUD) = 0 ; delayMicroseconds (5) ; + *(gpio + gpioToPUDCLK [pin]) = 0 ; delayMicroseconds (5) ; + } + else // Extension module + { + if ((node = wiringPiFindNode (pin)) != NULL) + node->pullUpDnControl (node, pin, pud) ; + return ; + } +} + + +/* + * digitalRead: + * Read the value of a given Pin, returning HIGH or LOW + ********************************************************************************* + */ + +int digitalRead (int pin) +{ + char c ; + struct wiringPiNodeStruct *node = wiringPiNodes ; + + if ((pin & PI_GPIO_MASK) == 0) // On-Board Pin + { + /**/ if (wiringPiMode == WPI_MODE_GPIO_SYS) // Sys mode + { + if (sysFds [pin] == -1) + return LOW ; + + lseek (sysFds [pin], 0L, SEEK_SET) ; + read (sysFds [pin], &c, 1) ; + return (c == '0') ? LOW : HIGH ; + } + else if (wiringPiMode == WPI_MODE_PINS) + pin = pinToGpio [pin] ; + else if (wiringPiMode == WPI_MODE_PHYS) + pin = physToGpio [pin] ; + else if (wiringPiMode != WPI_MODE_GPIO) + return LOW ; + + if ((*(gpio + gpioToGPLEV [pin]) & (1 << (pin & 31))) != 0) + return HIGH ; + else + return LOW ; + } + else + { + if ((node = wiringPiFindNode (pin)) == NULL) + return LOW ; + return node->digitalRead (node, pin) ; + } +} + + +/* + * digitalRead8: + * Read 8-bits (a byte) from given start pin. + ********************************************************************************* + +unsigned int digitalRead8 (int pin) +{ + struct wiringPiNodeStruct *node = wiringPiNodes ; + + if ((pin & PI_GPIO_MASK) == 0) // On-Board Pin + return 0 ; + else + { + if ((node = wiringPiFindNode (pin)) == NULL) + return LOW ; + return node->digitalRead8 (node, pin) ; + } +} + */ + + +/* + * digitalWrite: + * Set an output bit + ********************************************************************************* + */ + +void digitalWrite (int pin, int value) +{ + struct wiringPiNodeStruct *node = wiringPiNodes ; + + if ((pin & PI_GPIO_MASK) == 0) // On-Board Pin + { + /**/ if (wiringPiMode == WPI_MODE_GPIO_SYS) // Sys mode + { + if (sysFds [pin] != -1) + { + if (value == LOW) + write (sysFds [pin], "0\n", 2) ; + else + write (sysFds [pin], "1\n", 2) ; + } + return ; + } + else if (wiringPiMode == WPI_MODE_PINS) + pin = pinToGpio [pin] ; + else if (wiringPiMode == WPI_MODE_PHYS) + pin = physToGpio [pin] ; + else if (wiringPiMode != WPI_MODE_GPIO) + return ; + + if (value == LOW) + *(gpio + gpioToGPCLR [pin]) = 1 << (pin & 31) ; + else + *(gpio + gpioToGPSET [pin]) = 1 << (pin & 31) ; + } + else + { + if ((node = wiringPiFindNode (pin)) != NULL) + node->digitalWrite (node, pin, value) ; + } +} + + +/* + * digitalWrite8: + * Set an output 8-bit byte on the device from the given pin number + ********************************************************************************* + +void digitalWrite8 (int pin, int value) +{ + struct wiringPiNodeStruct *node = wiringPiNodes ; + + if ((pin & PI_GPIO_MASK) == 0) // On-Board Pin + return ; + else + { + if ((node = wiringPiFindNode (pin)) != NULL) + node->digitalWrite8 (node, pin, value) ; + } +} + */ + + +/* + * pwmWrite: + * Set an output PWM value + ********************************************************************************* + */ + +void pwmWrite (int pin, int value) +{ + struct wiringPiNodeStruct *node = wiringPiNodes ; + + setupCheck ("pwmWrite") ; + + if ((pin & PI_GPIO_MASK) == 0) // On-Board Pin + { + /**/ if (wiringPiMode == WPI_MODE_PINS) + pin = pinToGpio [pin] ; + else if (wiringPiMode == WPI_MODE_PHYS) + pin = physToGpio [pin] ; + else if (wiringPiMode != WPI_MODE_GPIO) + return ; + + usingGpioMemCheck ("pwmWrite") ; + *(pwm + gpioToPwmPort [pin]) = value ; + } + else + { + if ((node = wiringPiFindNode (pin)) != NULL) + node->pwmWrite (node, pin, value) ; + } +} + + +/* + * analogRead: + * Read the analog value of a given Pin. + * There is no on-board Pi analog hardware, + * so this needs to go to a new node. + ********************************************************************************* + */ + +int analogRead (int pin) +{ + struct wiringPiNodeStruct *node = wiringPiNodes ; + + if ((node = wiringPiFindNode (pin)) == NULL) + return 0 ; + else + return node->analogRead (node, pin) ; +} + + +/* + * analogWrite: + * Write the analog value to the given Pin. + * There is no on-board Pi analog hardware, + * so this needs to go to a new node. + ********************************************************************************* + */ + +void analogWrite (int pin, int value) +{ + struct wiringPiNodeStruct *node = wiringPiNodes ; + + if ((node = wiringPiFindNode (pin)) == NULL) + return ; + + node->analogWrite (node, pin, value) ; +} + + +/* + * pwmToneWrite: + * Pi Specific. + * Output the given frequency on the Pi's PWM pin + ********************************************************************************* + */ + +void pwmToneWrite (int pin, int freq) +{ + int range ; + + setupCheck ("pwmToneWrite") ; + + if (freq == 0) + pwmWrite (pin, 0) ; // Off + else + { + range = 600000 / freq ; + pwmSetRange (range) ; + pwmWrite (pin, freq / 2) ; + } +} + + + +/* + * digitalWriteByte: + * digitalReadByte: + * Pi Specific + * Write an 8-bit byte to the first 8 GPIO pins - try to do it as + * fast as possible. + * However it still needs 2 operations to set the bits, so any external + * hardware must not rely on seeing a change as there will be a change + * to set the outputs bits to zero, then another change to set the 1's + * Reading is just bit fiddling. + * These are wiringPi pin numbers 0..7, or BCM_GPIO pin numbers + * 17, 18, 22, 23, 24, 24, 4 on a Pi v1 rev 0-3 + * 17, 18, 27, 23, 24, 24, 4 on a Pi v1 rev 3 onwards or B+, 2, 3, zero + ********************************************************************************* + */ + +void digitalWriteByte (const int value) +{ + uint32_t pinSet = 0 ; + uint32_t pinClr = 0 ; + int mask = 1 ; + int pin ; + + /**/ if (wiringPiMode == WPI_MODE_GPIO_SYS) + { + for (pin = 0 ; pin < 8 ; ++pin) + { + digitalWrite (pinToGpio [pin], value & mask) ; + mask <<= 1 ; + } + return ; + } + else + { + for (pin = 0 ; pin < 8 ; ++pin) + { + if ((value & mask) == 0) + pinClr |= (1 << pinToGpio [pin]) ; + else + pinSet |= (1 << pinToGpio [pin]) ; + + mask <<= 1 ; + } + + *(gpio + gpioToGPCLR [0]) = pinClr ; + *(gpio + gpioToGPSET [0]) = pinSet ; + } +} + +unsigned int digitalReadByte (void) +{ + int pin, x ; + uint32_t raw ; + uint32_t data = 0 ; + + /**/ if (wiringPiMode == WPI_MODE_GPIO_SYS) + { + for (pin = 0 ; pin < 8 ; ++pin) + { + x = digitalRead (pinToGpio [pin]) ; + data = (data << 1) | x ; + } + } + else + { + raw = *(gpio + gpioToGPLEV [0]) ; // First bank for these pins + for (pin = 0 ; pin < 8 ; ++pin) + { + x = pinToGpio [pin] ; + data = (data << 1) | (((raw & (1 << x)) == 0) ? 0 : 1) ; + } + } + return data ; +} + + +/* + * digitalWriteByte2: + * digitalReadByte2: + * Pi Specific + * Write an 8-bit byte to the second set of 8 GPIO pins. This is marginally + * faster than the first lot as these are consecutive BCM_GPIO pin numbers. + * However they overlap with the original read/write bytes. + ********************************************************************************* + */ + +void digitalWriteByte2 (const int value) +{ + register int mask = 1 ; + register int pin ; + + /**/ if (wiringPiMode == WPI_MODE_GPIO_SYS) + { + for (pin = 20 ; pin < 28 ; ++pin) + { + digitalWrite (pin, value & mask) ; + mask <<= 1 ; + } + return ; + } + else + { + *(gpio + gpioToGPCLR [0]) = (~value & 0xFF) << 20 ; // 0x0FF00000; ILJ > CHANGE: Old causes glitch + *(gpio + gpioToGPSET [0]) = ( value & 0xFF) << 20 ; + } +} + +unsigned int digitalReadByte2 (void) +{ + int pin, x ; + uint32_t data = 0 ; + + /**/ if (wiringPiMode == WPI_MODE_GPIO_SYS) + { + for (pin = 20 ; pin < 28 ; ++pin) + { + x = digitalRead (pin) ; + data = (data << 1) | x ; + } + } + else + data = ((*(gpio + gpioToGPLEV [0])) >> 20) & 0xFF ; // First bank for these pins + + return data ; +} + + +/* + * waitForInterrupt: + * Pi Specific. + * Wait for Interrupt on a GPIO pin. + * This is actually done via the /sys/class/gpio interface regardless of + * the wiringPi access mode in-use. Maybe sometime it might get a better + * way for a bit more efficiency. + ********************************************************************************* + */ + +int waitForInterrupt (int pin, int mS) +{ + int fd, x ; + uint8_t c ; + struct pollfd polls ; + + /**/ if (wiringPiMode == WPI_MODE_PINS) + pin = pinToGpio [pin] ; + else if (wiringPiMode == WPI_MODE_PHYS) + pin = physToGpio [pin] ; + + if ((fd = sysFds [pin]) == -1) + return -2 ; + +// Setup poll structure + + polls.fd = fd ; + polls.events = POLLPRI | POLLERR ; + +// Wait for it ... + + x = poll (&polls, 1, mS) ; + +// If no error, do a dummy read to clear the interrupt +// A one character read appars to be enough. + + if (x > 0) + { + lseek (fd, 0, SEEK_SET) ; // Rewind + (void)read (fd, &c, 1) ; // Read & clear + } + + return x ; +} + + +/* + * interruptHandler: + * This is a thread and gets started to wait for the interrupt we're + * hoping to catch. It will call the user-function when the interrupt + * fires. + ********************************************************************************* + */ + +static void *interruptHandler (UNU void *arg) +{ + int myPin ; + + (void)piHiPri (55) ; // Only effective if we run as root + + myPin = pinPass ; + pinPass = -1 ; + + for (;;) + if (waitForInterrupt (myPin, -1) > 0) + isrFunctions [myPin] () ; + + return NULL ; +} + + +/* + * wiringPiISR: + * Pi Specific. + * Take the details and create an interrupt handler that will do a call- + * back to the user supplied function. + ********************************************************************************* + */ + +int wiringPiISR (int pin, int mode, void (*function)(void)) +{ + pthread_t threadId ; + const char *modeS ; + char fName [64] ; + char pinS [8] ; + pid_t pid ; + int count, i ; + char c ; + int bcmGpioPin ; + + if ((pin < 0) || (pin > 63)) + return wiringPiFailure (WPI_FATAL, "wiringPiISR: pin must be 0-63 (%d)\n", pin) ; + + /**/ if (wiringPiMode == WPI_MODE_UNINITIALISED) + return wiringPiFailure (WPI_FATAL, "wiringPiISR: wiringPi has not been initialised. Unable to continue.\n") ; + else if (wiringPiMode == WPI_MODE_PINS) + bcmGpioPin = pinToGpio [pin] ; + else if (wiringPiMode == WPI_MODE_PHYS) + bcmGpioPin = physToGpio [pin] ; + else + bcmGpioPin = pin ; + +// Now export the pin and set the right edge +// We're going to use the gpio program to do this, so it assumes +// a full installation of wiringPi. It's a bit 'clunky', but it +// is a way that will work when we're running in "Sys" mode, as +// a non-root user. (without sudo) + + if (mode != INT_EDGE_SETUP) + { + /**/ if (mode == INT_EDGE_FALLING) + modeS = "falling" ; + else if (mode == INT_EDGE_RISING) + modeS = "rising" ; + else + modeS = "both" ; + + sprintf (pinS, "%d", bcmGpioPin) ; + + if ((pid = fork ()) < 0) // Fail + return wiringPiFailure (WPI_FATAL, "wiringPiISR: fork failed: %s\n", strerror (errno)) ; + + if (pid == 0) // Child, exec + { + /**/ if (access ("/usr/local/bin/gpio", X_OK) == 0) + { + execl ("/usr/local/bin/gpio", "gpio", "edge", pinS, modeS, (char *)NULL) ; + return wiringPiFailure (WPI_FATAL, "wiringPiISR: execl failed: %s\n", strerror (errno)) ; + } + else if (access ("/usr/bin/gpio", X_OK) == 0) + { + execl ("/usr/bin/gpio", "gpio", "edge", pinS, modeS, (char *)NULL) ; + return wiringPiFailure (WPI_FATAL, "wiringPiISR: execl failed: %s\n", strerror (errno)) ; + } + else + return wiringPiFailure (WPI_FATAL, "wiringPiISR: Can't find gpio program\n") ; + } + else // Parent, wait + wait (NULL) ; + } + +// Now pre-open the /sys/class node - but it may already be open if +// we are in Sys mode... + + if (sysFds [bcmGpioPin] == -1) + { + sprintf (fName, "/sys/class/gpio/gpio%d/value", bcmGpioPin) ; + if ((sysFds [bcmGpioPin] = open (fName, O_RDWR)) < 0) + return wiringPiFailure (WPI_FATAL, "wiringPiISR: unable to open %s: %s\n", fName, strerror (errno)) ; + } + +// Clear any initial pending interrupt + + ioctl (sysFds [bcmGpioPin], FIONREAD, &count) ; + for (i = 0 ; i < count ; ++i) + read (sysFds [bcmGpioPin], &c, 1) ; + + isrFunctions [pin] = function ; + + pthread_mutex_lock (&pinMutex) ; + pinPass = pin ; + pthread_create (&threadId, NULL, interruptHandler, NULL) ; + while (pinPass != -1) + delay (1) ; + pthread_mutex_unlock (&pinMutex) ; + + return 0 ; +} + + +/* + * initialiseEpoch: + * Initialise our start-of-time variable to be the current unix + * time in milliseconds and microseconds. + ********************************************************************************* + */ + +static void initialiseEpoch (void) +{ +#ifdef OLD_WAY + struct timeval tv ; + + gettimeofday (&tv, NULL) ; + epochMilli = (uint64_t)tv.tv_sec * (uint64_t)1000 + (uint64_t)(tv.tv_usec / 1000) ; + epochMicro = (uint64_t)tv.tv_sec * (uint64_t)1000000 + (uint64_t)(tv.tv_usec) ; +#else + struct timespec ts ; + + clock_gettime (CLOCK_MONOTONIC_RAW, &ts) ; + epochMilli = (uint64_t)ts.tv_sec * (uint64_t)1000 + (uint64_t)(ts.tv_nsec / 1000000L) ; + epochMicro = (uint64_t)ts.tv_sec * (uint64_t)1000000 + (uint64_t)(ts.tv_nsec / 1000L) ; +#endif +} + + +/* + * delay: + * Wait for some number of milliseconds + ********************************************************************************* + */ + +void delay (unsigned int howLong) +{ + struct timespec sleeper, dummy ; + + sleeper.tv_sec = (time_t)(howLong / 1000) ; + sleeper.tv_nsec = (long)(howLong % 1000) * 1000000 ; + + nanosleep (&sleeper, &dummy) ; +} + + +/* + * delayMicroseconds: + * This is somewhat intersting. It seems that on the Pi, a single call + * to nanosleep takes some 80 to 130 microseconds anyway, so while + * obeying the standards (may take longer), it's not always what we + * want! + * + * So what I'll do now is if the delay is less than 100uS we'll do it + * in a hard loop, watching a built-in counter on the ARM chip. This is + * somewhat sub-optimal in that it uses 100% CPU, something not an issue + * in a microcontroller, but under a multi-tasking, multi-user OS, it's + * wastefull, however we've no real choice )-: + * + * Plan B: It seems all might not be well with that plan, so changing it + * to use gettimeofday () and poll on that instead... + ********************************************************************************* + */ + +void delayMicrosecondsHard (unsigned int howLong) +{ + struct timeval tNow, tLong, tEnd ; + + gettimeofday (&tNow, NULL) ; + tLong.tv_sec = howLong / 1000000 ; + tLong.tv_usec = howLong % 1000000 ; + timeradd (&tNow, &tLong, &tEnd) ; + + while (timercmp (&tNow, &tEnd, <)) + gettimeofday (&tNow, NULL) ; +} + +void delayMicroseconds (unsigned int howLong) +{ + struct timespec sleeper ; + unsigned int uSecs = howLong % 1000000 ; + unsigned int wSecs = howLong / 1000000 ; + + /**/ if (howLong == 0) + return ; + else if (howLong < 100) + delayMicrosecondsHard (howLong) ; + else + { + sleeper.tv_sec = wSecs ; + sleeper.tv_nsec = (long)(uSecs * 1000L) ; + nanosleep (&sleeper, NULL) ; + } +} + + +/* + * millis: + * Return a number of milliseconds as an unsigned int. + * Wraps at 49 days. + ********************************************************************************* + */ + +unsigned int millis (void) +{ + uint64_t now ; + +#ifdef OLD_WAY + struct timeval tv ; + + gettimeofday (&tv, NULL) ; + now = (uint64_t)tv.tv_sec * (uint64_t)1000 + (uint64_t)(tv.tv_usec / 1000) ; + +#else + struct timespec ts ; + + clock_gettime (CLOCK_MONOTONIC_RAW, &ts) ; + now = (uint64_t)ts.tv_sec * (uint64_t)1000 + (uint64_t)(ts.tv_nsec / 1000000L) ; +#endif + + return (uint32_t)(now - epochMilli) ; +} + + +/* + * micros: + * Return a number of microseconds as an unsigned int. + * Wraps after 71 minutes. + ********************************************************************************* + */ + +unsigned int micros (void) +{ + uint64_t now ; +#ifdef OLD_WAY + struct timeval tv ; + + gettimeofday (&tv, NULL) ; + now = (uint64_t)tv.tv_sec * (uint64_t)1000000 + (uint64_t)tv.tv_usec ; +#else + struct timespec ts ; + + clock_gettime (CLOCK_MONOTONIC_RAW, &ts) ; + now = (uint64_t)ts.tv_sec * (uint64_t)1000000 + (uint64_t)(ts.tv_nsec / 1000) ; +#endif + + + return (uint32_t)(now - epochMicro) ; +} + +/* + * wiringPiVersion: + * Return our current version number + ********************************************************************************* + */ + +void wiringPiVersion (int *major, int *minor) +{ + *major = VERSION_MAJOR ; + *minor = VERSION_MINOR ; +} + + +/* + * wiringPiSetup: + * Must be called once at the start of your program execution. + * + * Default setup: Initialises the system into wiringPi Pin mode and uses the + * memory mapped hardware directly. + * + * Changed now to revert to "gpio" mode if we're running on a Compute Module. + ********************************************************************************* + */ + +int wiringPiSetup (void) +{ + int fd ; + int model, rev, mem, maker, overVolted ; + +// It's actually a fatal error to call any of the wiringPiSetup routines more than once, +// (you run out of file handles!) but I'm fed-up with the useless twats who email +// me bleating that there is a bug in my code, so screw-em. + + if (wiringPiSetuped) + return 0 ; + + wiringPiSetuped = TRUE ; + + if (getenv (ENV_DEBUG) != NULL) + wiringPiDebug = TRUE ; + + if (getenv (ENV_CODES) != NULL) + wiringPiReturnCodes = TRUE ; + + if (wiringPiDebug) + printf ("wiringPi: wiringPiSetup called\n") ; + +// Get the board ID information. We're not really using the information here, +// but it will give us information like the GPIO layout scheme (2 variants +// on the older 26-pin Pi's) and the GPIO peripheral base address. +// and if we're running on a compute module, then wiringPi pin numbers +// don't really many anything, so force native BCM mode anyway. + + piBoardId (&model, &rev, &mem, &maker, &overVolted) ; + + if ((model == PI_MODEL_CM) || (model == PI_MODEL_CM3)) + wiringPiMode = WPI_MODE_GPIO ; + else + wiringPiMode = WPI_MODE_PINS ; + + /**/ if (piGpioLayout () == 1) // A, B, Rev 1, 1.1 + { + pinToGpio = pinToGpioR1 ; + physToGpio = physToGpioR1 ; + } + else // A2, B2, A+, B+, CM, Pi2, Pi3, Zero + { + pinToGpio = pinToGpioR2 ; + physToGpio = physToGpioR2 ; + } + +// ... + + switch (model) + { + case PI_MODEL_A: case PI_MODEL_B: + case PI_MODEL_AP: case PI_MODEL_BP: + case PI_ALPHA: case PI_MODEL_CM: + case PI_MODEL_ZERO: case PI_MODEL_ZERO_W: + piGpioBase = GPIO_PERI_BASE_OLD ; + break ; + + default: + piGpioBase = GPIO_PERI_BASE_NEW ; + break ; + } + +// Open the master /dev/ memory control device +// Device strategy: December 2016: +// Try /dev/mem. If that fails, then +// try /dev/gpiomem. If that fails then game over. + + if ((fd = open ("/dev/mem", O_RDWR | O_SYNC | O_CLOEXEC)) < 0) + { + if ((fd = open ("/dev/gpiomem", O_RDWR | O_SYNC | O_CLOEXEC) ) >= 0) // We're using gpiomem + { + piGpioBase = 0 ; + usingGpioMem = TRUE ; + } + else + return wiringPiFailure (WPI_ALMOST, "wiringPiSetup: Unable to open /dev/mem or /dev/gpiomem: %s.\n" + " Aborting your program because if it can not access the GPIO\n" + " hardware then it most certianly won't work\n" + " Try running with sudo?\n", strerror (errno)) ; + } + +// Set the offsets into the memory interface. + + GPIO_PADS = piGpioBase + 0x00100000 ; + GPIO_CLOCK_BASE = piGpioBase + 0x00101000 ; + GPIO_BASE = piGpioBase + 0x00200000 ; + GPIO_TIMER = piGpioBase + 0x0000B000 ; + GPIO_PWM = piGpioBase + 0x0020C000 ; + +// Map the individual hardware components + +// GPIO: + + gpio = (uint32_t *)mmap(0, BLOCK_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED, fd, GPIO_BASE) ; + if (gpio == MAP_FAILED) + return wiringPiFailure (WPI_ALMOST, "wiringPiSetup: mmap (GPIO) failed: %s\n", strerror (errno)) ; + +// PWM + + pwm = (uint32_t *)mmap(0, BLOCK_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED, fd, GPIO_PWM) ; + if (pwm == MAP_FAILED) + return wiringPiFailure (WPI_ALMOST, "wiringPiSetup: mmap (PWM) failed: %s\n", strerror (errno)) ; + +// Clock control (needed for PWM) + + clk = (uint32_t *)mmap(0, BLOCK_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED, fd, GPIO_CLOCK_BASE) ; + if (clk == MAP_FAILED) + return wiringPiFailure (WPI_ALMOST, "wiringPiSetup: mmap (CLOCK) failed: %s\n", strerror (errno)) ; + +// The drive pads + + pads = (uint32_t *)mmap(0, BLOCK_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED, fd, GPIO_PADS) ; + if (pads == MAP_FAILED) + return wiringPiFailure (WPI_ALMOST, "wiringPiSetup: mmap (PADS) failed: %s\n", strerror (errno)) ; + +// The system timer + + timer = (uint32_t *)mmap(0, BLOCK_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED, fd, GPIO_TIMER) ; + if (timer == MAP_FAILED) + return wiringPiFailure (WPI_ALMOST, "wiringPiSetup: mmap (TIMER) failed: %s\n", strerror (errno)) ; + +// Set the timer to free-running, 1MHz. +// 0xF9 is 249, the timer divide is base clock / (divide+1) +// so base clock is 250MHz / 250 = 1MHz. + + *(timer + TIMER_CONTROL) = 0x0000280 ; + *(timer + TIMER_PRE_DIV) = 0x00000F9 ; + timerIrqRaw = timer + TIMER_IRQ_RAW ; + +// Export the base addresses for any external software that might need them + + _wiringPiGpio = gpio ; + _wiringPiPwm = pwm ; + _wiringPiClk = clk ; + _wiringPiPads = pads ; + _wiringPiTimer = timer ; + + initialiseEpoch () ; + + return 0 ; +} + + +/* + * wiringPiSetupGpio: + * Must be called once at the start of your program execution. + * + * GPIO setup: Initialises the system into GPIO Pin mode and uses the + * memory mapped hardware directly. + ********************************************************************************* + */ + +int wiringPiSetupGpio (void) +{ + (void)wiringPiSetup () ; + + if (wiringPiDebug) + printf ("wiringPi: wiringPiSetupGpio called\n") ; + + wiringPiMode = WPI_MODE_GPIO ; + + return 0 ; +} + + +/* + * wiringPiSetupPhys: + * Must be called once at the start of your program execution. + * + * Phys setup: Initialises the system into Physical Pin mode and uses the + * memory mapped hardware directly. + ********************************************************************************* + */ + +int wiringPiSetupPhys (void) +{ + (void)wiringPiSetup () ; + + if (wiringPiDebug) + printf ("wiringPi: wiringPiSetupPhys called\n") ; + + wiringPiMode = WPI_MODE_PHYS ; + + return 0 ; +} + + +/* + * wiringPiSetupSys: + * Must be called once at the start of your program execution. + * + * Initialisation (again), however this time we are using the /sys/class/gpio + * interface to the GPIO systems - slightly slower, but always usable as + * a non-root user, assuming the devices are already exported and setup correctly. + */ + +int wiringPiSetupSys (void) +{ + int pin ; + char fName [128] ; + + if (wiringPiSetuped) + return 0 ; + + wiringPiSetuped = TRUE ; + + if (getenv (ENV_DEBUG) != NULL) + wiringPiDebug = TRUE ; + + if (getenv (ENV_CODES) != NULL) + wiringPiReturnCodes = TRUE ; + + if (wiringPiDebug) + printf ("wiringPi: wiringPiSetupSys called\n") ; + + if (piGpioLayout () == 1) + { + pinToGpio = pinToGpioR1 ; + physToGpio = physToGpioR1 ; + } + else + { + pinToGpio = pinToGpioR2 ; + physToGpio = physToGpioR2 ; + } + +// Open and scan the directory, looking for exported GPIOs, and pre-open +// the 'value' interface to speed things up for later + + for (pin = 0 ; pin < 64 ; ++pin) + { + sprintf (fName, "/sys/class/gpio/gpio%d/value", pin) ; + sysFds [pin] = open (fName, O_RDWR) ; + } + + initialiseEpoch () ; + + wiringPiMode = WPI_MODE_GPIO_SYS ; + + return 0 ; +} diff --git a/wiringPi/wiringPi_copy.h b/wiringPi/wiringPi_copy.h new file mode 100644 index 0000000..ae5d647 --- /dev/null +++ b/wiringPi/wiringPi_copy.h @@ -0,0 +1,264 @@ +/* + * wiringPi.h: + * Arduino like Wiring library for the Raspberry Pi. + * Copyright (c) 2012-2017 Gordon Henderson + *********************************************************************** + * This file is part of wiringPi: + * https://projects.drogon.net/raspberry-pi/wiringpi/ + * + * wiringPi is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * wiringPi 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 Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with wiringPi. If not, see . + *********************************************************************** + */ + +#ifndef __WIRING_PI_H__ +#define __WIRING_PI_H__ + +// C doesn't have true/false by default and I can never remember which +// way round they are, so ... +// (and yes, I know about stdbool.h but I like capitals for these and I'm old) + +#ifndef TRUE +# define TRUE (1==1) +# define FALSE (!TRUE) +#endif + +// GCC warning suppressor + +#define UNU __attribute__((unused)) + +// Mask for the bottom 64 pins which belong to the Raspberry Pi +// The others are available for the other devices + +#define PI_GPIO_MASK (0xFFFFFFC0) + +// Handy defines + +// wiringPi modes + +#define WPI_MODE_PINS 0 +#define WPI_MODE_GPIO 1 +#define WPI_MODE_GPIO_SYS 2 +#define WPI_MODE_PHYS 3 +#define WPI_MODE_PIFACE 4 +#define WPI_MODE_UNINITIALISED -1 + +// Pin modes + +#define INPUT 0 +#define OUTPUT 1 +#define PWM_OUTPUT 2 +#define GPIO_CLOCK 3 +#define SOFT_PWM_OUTPUT 4 +#define SOFT_TONE_OUTPUT 5 +#define PWM_TONE_OUTPUT 6 + +#define LOW 0 +#define HIGH 1 + +// Pull up/down/none + +#define PUD_OFF 0 +#define PUD_DOWN 1 +#define PUD_UP 2 + +// PWM + +#define PWM_MODE_MS 0 +#define PWM_MODE_BAL 1 + +// Interrupt levels + +#define INT_EDGE_SETUP 0 +#define INT_EDGE_FALLING 1 +#define INT_EDGE_RISING 2 +#define INT_EDGE_BOTH 3 + +// Pi model types and version numbers +// Intended for the GPIO program Use at your own risk. + +#define PI_MODEL_A 0 +#define PI_MODEL_B 1 +#define PI_MODEL_AP 2 +#define PI_MODEL_BP 3 +#define PI_MODEL_2 4 +#define PI_ALPHA 5 +#define PI_MODEL_CM 6 +#define PI_MODEL_07 7 +#define PI_MODEL_3 8 +#define PI_MODEL_ZERO 9 +#define PI_MODEL_CM3 10 +#define PI_MODEL_ZERO_W 12 +#define PI_MODEL_3P 13 + +#define PI_VERSION_1 0 +#define PI_VERSION_1_1 1 +#define PI_VERSION_1_2 2 +#define PI_VERSION_2 3 + +#define PI_MAKER_SONY 0 +#define PI_MAKER_EGOMAN 1 +#define PI_MAKER_EMBEST 2 +#define PI_MAKER_UNKNOWN 3 + +extern const char *piModelNames [16] ; +extern const char *piRevisionNames [16] ; +extern const char *piMakerNames [16] ; +extern const int piMemorySize [ 8] ; + + +// Intended for the GPIO program Use at your own risk. + +// Threads + +#define PI_THREAD(X) void *X (UNU void *dummy) + +// Failure modes + +#define WPI_FATAL (1==1) +#define WPI_ALMOST (1==2) + + +// wiringPiNodeStruct: +// This describes additional device nodes in the extended wiringPi +// 2.0 scheme of things. +// It's a simple linked list for now, but will hopefully migrate to +// a binary tree for efficiency reasons - but then again, the chances +// of more than 1 or 2 devices being added are fairly slim, so who +// knows.... + +struct wiringPiNodeStruct +{ + int pinBase ; + int pinMax ; + + int fd ; // Node specific + unsigned int data0 ; // ditto + unsigned int data1 ; // ditto + unsigned int data2 ; // ditto + unsigned int data3 ; // ditto + + void (*pinMode) (struct wiringPiNodeStruct *node, int pin, int mode) ; + void (*pullUpDnControl) (struct wiringPiNodeStruct *node, int pin, int mode) ; + int (*digitalRead) (struct wiringPiNodeStruct *node, int pin) ; +//unsigned int (*digitalRead8) (struct wiringPiNodeStruct *node, int pin) ; + void (*digitalWrite) (struct wiringPiNodeStruct *node, int pin, int value) ; +// void (*digitalWrite8) (struct wiringPiNodeStruct *node, int pin, int value) ; + void (*pwmWrite) (struct wiringPiNodeStruct *node, int pin, int value) ; + int (*analogRead) (struct wiringPiNodeStruct *node, int pin) ; + void (*analogWrite) (struct wiringPiNodeStruct *node, int pin, int value) ; + + struct wiringPiNodeStruct *next ; +} ; + +extern struct wiringPiNodeStruct *wiringPiNodes ; + +// Export variables for the hardware pointers + +extern volatile unsigned int *_wiringPiGpio ; +extern volatile unsigned int *_wiringPiPwm ; +extern volatile unsigned int *_wiringPiClk ; +extern volatile unsigned int *_wiringPiPads ; +extern volatile unsigned int *_wiringPiTimer ; +extern volatile unsigned int *_wiringPiTimerIrqRaw ; + + +// Function prototypes +// c++ wrappers thanks to a comment by Nick Lott +// (and others on the Raspberry Pi forums) + +#ifdef __cplusplus +extern "C" { +#endif + +// Data + +// Internal + +extern int wiringPiFailure (int fatal, const char *message, ...) ; + +// Core wiringPi functions + +extern struct wiringPiNodeStruct *wiringPiFindNode (int pin) ; +extern struct wiringPiNodeStruct *wiringPiNewNode (int pinBase, int numPins) ; + +extern void wiringPiVersion (int *major, int *minor) ; +extern int wiringPiSetup (void) ; +extern int wiringPiSetupSys (void) ; +extern int wiringPiSetupGpio (void) ; +extern int wiringPiSetupPhys (void) ; + +extern void pinModeAlt (int pin, int mode) ; +extern void pinMode (int pin, int mode) ; +extern void pullUpDnControl (int pin, int pud) ; +extern int digitalRead (int pin) ; +extern void digitalWrite (int pin, int value) ; +extern unsigned int digitalRead8 (int pin) ; +extern void digitalWrite8 (int pin, int value) ; +extern void pwmWrite (int pin, int value) ; +extern int analogRead (int pin) ; +extern void analogWrite (int pin, int value) ; + +// PiFace specifics +// (Deprecated) + +extern int wiringPiSetupPiFace (void) ; +extern int wiringPiSetupPiFaceForGpioProg (void) ; // Don't use this - for gpio program only + +// On-Board Raspberry Pi hardware specific stuff + +extern int piGpioLayout (void) ; +extern int piBoardRev (void) ; // Deprecated +extern void piBoardId (int *model, int *rev, int *mem, int *maker, int *overVolted) ; +extern int wpiPinToGpio (int wpiPin) ; +extern int physPinToGpio (int physPin) ; +extern void setPadDrive (int group, int value) ; +extern int getAlt (int pin) ; +extern void pwmToneWrite (int pin, int freq) ; +extern void pwmSetMode (int mode) ; +extern void pwmSetRange (unsigned int range) ; +extern void pwmSetClock (int divisor) ; +extern void gpioClockSet (int pin, int freq) ; +extern unsigned int digitalReadByte (void) ; +extern unsigned int digitalReadByte2 (void) ; +extern void digitalWriteByte (int value) ; +extern void digitalWriteByte2 (int value) ; + +// Interrupts +// (Also Pi hardware specific) + +extern int waitForInterrupt (int pin, int mS) ; +extern int wiringPiISR (int pin, int mode, void (*function)(void)) ; + +// Threads + +extern int piThreadCreate (void *(*fn)(void *)) ; +extern void piLock (int key) ; +extern void piUnlock (int key) ; + +// Schedulling priority + +extern int piHiPri (const int pri) ; + +// Extras from arduino land + +extern void delay (unsigned int howLong) ; +extern void delayMicroseconds (unsigned int howLong) ; +extern unsigned int millis (void) ; +extern unsigned int micros (void) ; + +#ifdef __cplusplus +} +#endif + +#endif