diff --git a/INSTALL b/INSTALL new file mode 100644 index 0000000..8a6d38e --- /dev/null +++ b/INSTALL @@ -0,0 +1,48 @@ + +How to install wiringPi +======================= + +The easiest way is to use the supplied 'build' script: + + ./build + +that should do a complete install or upgrade of wiringPi for you. + +That will install a dynamic library. + +Some distributions do not have /usr/local/lib in the default LD_LIBRARY_PATH. To +fix this, you need to edit /etc/ld.so.conf and add in a single line: + + /usr/local/lib + +then run the ldconfig command. + + sudo ldconfig + +If you want to install a static library, you may need to do this manually: + + cd wiringPi + make static + sudo make install-static + + +To un-install wiringPi: + + ./build uninstall + + +I2C: + +If your system has the correct i2c-dev libraries and headers installed, +then the I2C helpers will be compiled into wiringPi. If you want to +use the I2C helpers and don't have them installed, then under Raspbian, +issue the command: + + sudo apt-get install libi2c-dev + +Consult the documentation for your system if you are not running Raspbian. + +Gordon Henderson + +projects@drogon.net +https://projects.drogon.net/ diff --git a/People b/People index e0c262c..8be8b6d 100644 --- a/People +++ b/People @@ -13,3 +13,15 @@ Chris McSweeny inside the dealyMicrosecondsHard() function. And spotting a couple of schoolboy errors in the (experimental) softServo code, prompting me to completely re-write it. + +Armin (Via projects website) + Some pointers about the i2c-dev.h files. + +Arno Wagner + Suggestions for the mmap calls in wiringPiSetup() + +CHARLES Thibaut: + A small issue in softTone + +Xian Stannard + Fixing some typos in the man page! diff --git a/README.TXT b/README.TXT new file mode 100644 index 0000000..0fce86a --- /dev/null +++ b/README.TXT @@ -0,0 +1,26 @@ + +wiringPi README +=============== + +Please note that the official way to get wiringPi is via git from +git.drogon.net and not GitHub. + +ie. + + git clone git://git.drogon.net/wiringPi + +The version of wiringPi held on GitHub by "Gadgetoid" is used to build the +wiringPython, Ruby, Perl, etc. wrappers for these other languages. This +version may lag the official Drogon release. Pull requests may not be +accepted to Github.... + +Please see + + https://projects.drogon.net/raspberry-pi/wiringpi/ + +for the official documentation, etc. and the best way to submit bug reports, etc. +is by sending an email to projects@drogon.net + +Thanks! + + -Gordon diff --git a/build b/build index 740b512..cbb1a4f 100755 --- a/build +++ b/build @@ -1,5 +1,18 @@ #!/bin/bash +check-make-ok() +{ + if [ $? != 0 ]; then + echo "" + echo "Make Failed..." + echo "Please check the messages and fix any problems. If you're still stuck," + echo "then please email all the output and as many details as you can to" + echo " projects@drogon.net" + echo "" + exit 1 + fi +} + if [ x$1 = "xclean" ]; then echo Cleaning echo @@ -9,8 +22,10 @@ if [ x$1 = "xclean" ]; then make clean cd ../examples make clean - cd .. -elif [ x$1 = "xuninstall" ]; then + exit +fi + +if [ x$1 = "xuninstall" ]; then echo Uninstalling echo echo "WiringPi library" @@ -21,24 +36,50 @@ elif [ x$1 = "xuninstall" ]; then cd ../gpio sudo make uninstall cd .. -else - echo wiringPi Build script - please wait... + exit +fi + + + echo "wiringPi Build script" + echo "=====================" + echo + +# Check for I2C being installed... +# ... and if-so, then automatically make the I2C helpers + + if [ -f /usr/include/linux/i2c-dev.h ]; then + grep -q i2c_smbus_read_byte /usr/include/linux/i2c-dev.h + if [ $? = 0 ]; then + target=i2c + echo "Building wiringPi with the I2C helper libraries." + else + target=all + echo "The wiringPi I2C helper libraries will not be built." + fi + fi + echo echo "WiringPi library" cd wiringPi - make + sudo make uninstall + make $target + check-make-ok sudo make install + check-make-ok + echo echo "GPIO Utility" cd ../gpio make + check-make-ok sudo make install - echo - echo "Examples" - cd ../examples - make - cd .. -fi + check-make-ok + +# echo +# echo "Examples" +# cd ../examples +# make +# cd .. echo echo All Done. diff --git a/examples/Makefile b/examples/Makefile index 738d36c..defd510 100644 --- a/examples/Makefile +++ b/examples/Makefile @@ -30,15 +30,15 @@ INCLUDE = -I/usr/local/include CFLAGS = $(DEBUG) -Wall $(INCLUDE) -Winline -pipe LDFLAGS = -L/usr/local/lib -LDLIBS = -lwiringPi +LDLIBS = -lwiringPi -lpthread -lm # Should not alter anything below this line ############################################################################### -SRC = test1.c test2.c speed.c lcd.c wfi.c \ - piface.c gertboard.c nes.c \ - pwm.c tone.c servo.c \ - delayTest.c serialRead.c okLed.c +SRC = blink.c test1.c test2.c speed.c lcd.c wfi.c isr.c isr-osc.c \ + piface.c gertboard.c nes.c \ + pwm.c tone.c servo.c \ + delayTest.c serialRead.c serialTest.c okLed.c OBJ = $(SRC:.c=.o) @@ -49,6 +49,12 @@ all: @echo " $(BINS)" | fmt @echo "" +really-all: $(BINS) + +blink: blink.o + @echo [link] + @$(CC) -o $@ blink.o $(LDFLAGS) $(LDLIBS) + test1: test1.o @echo [link] @$(CC) -o $@ test1.o $(LDFLAGS) $(LDLIBS) @@ -69,21 +75,29 @@ wfi: wfi.o @echo [link] @$(CC) -o $@ wfi.o $(LDFLAGS) $(LDLIBS) +isr: isr.o + @echo [link] + @$(CC) -o $@ isr.o $(LDFLAGS) $(LDLIBS) + +isr-osc: isr-osc.o + @echo [link] + @$(CC) -o $@ isr-osc.o $(LDFLAGS) $(LDLIBS) + piface: piface.o @echo [link] - @$(CC) -o $@ piface.o $(LDFLAGS) $(LDLIBS) -lpthread + @$(CC) -o $@ piface.o $(LDFLAGS) $(LDLIBS) gertboard: gertboard.o @echo [link] - @$(CC) -o $@ gertboard.o $(LDFLAGS) $(LDLIBS) -lm + @$(CC) -o $@ gertboard.o $(LDFLAGS) $(LDLIBS) nes: nes.o @echo [link] - @$(CC) -o $@ nes.o $(LDFLAGS) $(LDLIBS) -lm + @$(CC) -o $@ nes.o $(LDFLAGS) $(LDLIBS) pwm: pwm.o @echo [link] - @$(CC) -o $@ pwm.o $(LDFLAGS) $(LDLIBS) -lm -lpthread + @$(CC) -o $@ pwm.o $(LDFLAGS) $(LDLIBS) delayTest: delayTest.o @echo [link] @@ -93,6 +107,10 @@ serialRead: serialRead.o @echo [link] @$(CC) -o $@ serialRead.o $(LDFLAGS) $(LDLIBS) +serialTest: serialTest.o + @echo [link] + @$(CC) -o $@ serialTest.o $(LDFLAGS) $(LDLIBS) + okLed: okLed.o @echo [link] @$(CC) -o $@ okLed.o $(LDFLAGS) $(LDLIBS) diff --git a/examples/README.TXT b/examples/README.TXT index 2bf6f1e..33263b1 100644 --- a/examples/README.TXT +++ b/examples/README.TXT @@ -10,5 +10,9 @@ To compile an individual example, just type make exampleName -Where exampleName is one of: +To really compile everything: + + make really-all + +The individual tests are: diff --git a/examples/blink.c b/examples/blink.c new file mode 100644 index 0000000..bb9f856 --- /dev/null +++ b/examples/blink.c @@ -0,0 +1,50 @@ +/* + * blink.c: + * Standard "blink" program in wiringPi. Blinks an LED connected + * to the first GPIO pin. + * + * Copyright (c) 2012-2013 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 . + *********************************************************************** + */ + +#include +#include + +// LED Pin - wiringPi pin 0 is BCM_GPIO 17. + +#define LED 0 + +int main (void) +{ + printf ("Raspberry Pi blink\n") ; + + if (wiringPiSetup () == -1) + return 1 ; + + pinMode (LED, OUTPUT) ; + + for (;;) + { + digitalWrite (LED, 1) ; // On + delay (500) ; // mS + digitalWrite (LED, 0) ; // Off + delay (500) ; + } + return 0 ; +} diff --git a/examples/blink.rtb b/examples/blink.rtb new file mode 100644 index 0000000..eb7d26c --- /dev/null +++ b/examples/blink.rtb @@ -0,0 +1,30 @@ +// blink.rtb: +// Blink program in Return to Basic +// +// Copyright (c) 2012-2013 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 . + *********************************************************************** +// +PinMode (0, 1) // Output +CYCLE + DigitalWrite (0, 1) // Pin 0 ON + WAIT (0.5) // 0.5 seconds + DigitalWrite (0, 0) + WAIT (0.5) +REPEAT +END diff --git a/examples/blink.sh b/examples/blink.sh new file mode 100644 index 0000000..2aa378a --- /dev/null +++ b/examples/blink.sh @@ -0,0 +1,37 @@ +#!/bin/sh +# +# blink.sh: +# Standard "blink" program in wiringPi. Blinks an LED connected +# to the first GPIO pin. +# +# Copyright (c) 2012-2013 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 . +####################################################################### + +# LED Pin - wiringPi pin 0 is BCM_GPIO 17. + +LED=0 + +gpio mode $PIN out + +while true; do + gpio write $PIN 1 + sleep 0.5 + gpio write $PIN 0 + sleep 0.5 +done diff --git a/examples/delayTest.c b/examples/delayTest.c index d05f3ff..4c8b6ca 100644 --- a/examples/delayTest.c +++ b/examples/delayTest.c @@ -1,3 +1,27 @@ +/* + * delayTest.c: + * Just a little test program I'm using to experiment with + * various timings and latency, etc. + * + * Copyright (c) 2012-2013 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 . + *********************************************************************** + */ #include #include diff --git a/examples/gertboard.c b/examples/gertboard.c index 8f26dd4..f02e27d 100644 --- a/examples/gertboard.c +++ b/examples/gertboard.c @@ -1,4 +1,3 @@ - /* * gertboard.c: * Simple test for the SPI bus on the Gertboard @@ -10,6 +9,24 @@ * copy this value to D/A port 1 and use a 'scope on both D/A ports * to check all's well. * + * Copyright (c) 2012-2013 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 . + *********************************************************************** */ #include diff --git a/examples/header.h b/examples/header.h new file mode 100644 index 0000000..82f723d --- /dev/null +++ b/examples/header.h @@ -0,0 +1,23 @@ +/* + * file.c: + * + * Copyright (c) 2012-2013 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 . + *********************************************************************** + */ + diff --git a/examples/isr-osc.c b/examples/isr-osc.c new file mode 100644 index 0000000..a872ee3 --- /dev/null +++ b/examples/isr-osc.c @@ -0,0 +1,118 @@ +/* + * isr-osc.c: + * Wait for Interrupt test program - ISR method - interrupt oscillator + * + * How to test: + * + * IMPORTANT: To run this test we connect 2 GPIO pins together, but + * before we do that YOU must make sure that they are both setup + * the right way. If they are set to outputs and one is high and one low, + * then you connect the wire, you'll create a short and that won't be good. + * + * Before making the connection, type: + * gpio mode 0 output + * gpio write 0 0 + * gpio mode 1 input + * then you can connect them together. + * + * Run the program, then: + * gpio write 0 1 + * gpio write 0 0 + * + * at which point it will trigger an interrupt and the program will + * then do the up/down toggling for itself and run at full speed, and + * it will report the number of interrupts recieved every second. + * + * Copyright (c) 2013 Gordon Henderson. projects@drogon.net + *********************************************************************** + * 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 . + *********************************************************************** + */ + +#include +#include +#include +#include +#include + + +// What GPIO input are we using? +// This is a wiringPi pin number + +#define OUT_PIN 0 +#define IN_PIN 1 + +// globalCounter: +// Global variable to count interrupts +// Should be declared volatile to make sure the compiler doesn't cache it. + +static volatile int globalCounter = 0 ; + +/* + * myInterrupt: + ********************************************************************************* + */ + +void myInterrupt (void) +{ + digitalWrite (OUT_PIN, 1) ; + ++globalCounter ; + digitalWrite (OUT_PIN, 0) ; +} + + +/* + ********************************************************************************* + * main + ********************************************************************************* + */ + +int main (void) +{ + int myCounter = 0 ; + int lastCounter = 0 ; + + if (wiringPiSetup () < 0) + { + fprintf (stderr, "Unable to setup wiringPi: %s\n", strerror (errno)) ; + return 1 ; + } + + pinMode (OUT_PIN, OUTPUT) ; + pinMode (IN_PIN, INPUT) ; + + if (wiringPiISR (IN_PIN, INT_EDGE_FALLING, &myInterrupt) < 0) + { + fprintf (stderr, "Unable to setup ISR: %s\n", strerror (errno)) ; + return 1 ; + } + + for (;;) + { + printf ("Waiting ... ") ; fflush (stdout) ; + + while (myCounter == globalCounter) + delay (1000) ; + + printf (" Done. counter: %6d: %6d\n", + globalCounter, myCounter - lastCounter) ; + lastCounter = myCounter ; + myCounter = globalCounter ; + } + + return 0 ; +} diff --git a/examples/isr.c b/examples/isr.c new file mode 100644 index 0000000..2bef54a --- /dev/null +++ b/examples/isr.c @@ -0,0 +1,99 @@ +/* + * isr.c: + * Wait for Interrupt test program - ISR method + * + * How to test: + * Use the SoC's pull-up and pull down resistors that are avalable + * on input pins. So compile & run this program (via sudo), then + * in another terminal: + * gpio mode 0 up + * gpio mode 0 down + * at which point it should trigger an interrupt. Toggle the pin + * up/down to generate more interrupts to test. + * + * Copyright (c) 2013 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 . + *********************************************************************** + */ + +#include +#include +#include +#include +#include + + +// What GPIO input are we using? +// This is a wiringPi pin number + +#define BUTTON_PIN 0 + +// globalCounter: +// Global variable to count interrupts +// Should be declared volatile to make sure the compiler doesn't cache it. + +static volatile int globalCounter = 0 ; + + +/* + * myInterrupt: + ********************************************************************************* + */ + +void myInterrupt (void) +{ + ++globalCounter ; +} + + +/* + ********************************************************************************* + * main + ********************************************************************************* + */ + +int main (void) +{ + int myCounter = 0 ; + + if (wiringPiSetup () < 0) + { + fprintf (stderr, "Unable to setup wiringPi: %s\n", strerror (errno)) ; + return 1 ; + } + + if (wiringPiISR (BUTTON_PIN, INT_EDGE_FALLING, &myInterrupt) < 0) + { + fprintf (stderr, "Unable to setup ISR: %s\n", strerror (errno)) ; + return 1 ; + } + + + for (;;) + { + printf ("Waiting ... ") ; fflush (stdout) ; + + while (myCounter == globalCounter) + delay (100) ; + + printf (" Done. counter: %5d\n", globalCounter) ; + myCounter = globalCounter ; + } + + return 0 ; +} diff --git a/examples/nes.c b/examples/nes.c index 1a485bd..31908e8 100644 --- a/examples/nes.c +++ b/examples/nes.c @@ -1,3 +1,26 @@ +/* + * nes.c: + * Test program for an old NES controller connected to the Pi. + * + * Copyright (c) 2012-2013 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 . + *********************************************************************** + */ #include #include diff --git a/examples/okLed.c b/examples/okLed.c index 3bf21e2..9b3a170 100644 --- a/examples/okLed.c +++ b/examples/okLed.c @@ -1,7 +1,6 @@ /* - * okLed: + * okLed.c: * Make the OK LED on the Pi Pulsate... - * Copyright (c) 2012 gordon Henderson, but please Share and Enjoy! * * Originally posted to the Raspberry Pi forums: * http://www.raspberrypi.org/phpBB3/viewtopic.php?p=162581#p162581 @@ -10,6 +9,24 @@ * e.g. by putting it in /etc/rc.local and running it in the * background & * + * Copyright (c) 2012-2013 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 . + *********************************************************************** */ #include @@ -17,6 +34,7 @@ #include #include #include +#include #include #include diff --git a/examples/piface.c b/examples/piface.c index 3305bf9..0f00960 100644 --- a/examples/piface.c +++ b/examples/piface.c @@ -1,9 +1,27 @@ - /* - * piface.c: - * Simple test for the PiFace + * piFace.c: + * Simple test for the PiFace interface board. * * Read the buttons and output the same to the LEDs + * + * Copyright (c) 2012-2013 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 . + *********************************************************************** */ #include diff --git a/examples/pwm.c b/examples/pwm.c index 09b4ae0..c1fc331 100644 --- a/examples/pwm.c +++ b/examples/pwm.c @@ -1,3 +1,27 @@ +/* + * pwm.c: + * Test of the software PWM driver. Needs 12 LEDs connected + * to the Pi. + * + * Copyright (c) 2012-2013 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 . + *********************************************************************** + */ #include #include diff --git a/examples/serialRead.c b/examples/serialRead.c index 34b9bad..9ee11ac 100644 --- a/examples/serialRead.c +++ b/examples/serialRead.c @@ -1,8 +1,25 @@ - /* - * serialRead.c: + * serial.c: * Example program to read bytes from the Serial line * + * Copyright (c) 2012-2013 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 . + *********************************************************************** */ #include diff --git a/examples/serialTest.c b/examples/serialTest.c new file mode 100644 index 0000000..0d6da5f --- /dev/null +++ b/examples/serialTest.c @@ -0,0 +1,75 @@ +/* + * serialTest.c: + * Very simple program to test the serial port. Expects + * the port to be looped back to itself + * + * Copyright (c) 2012-2013 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 . + *********************************************************************** + */ + +#include +#include +#include + +#include +#include + +int main () +{ + int fd ; + int count ; + unsigned int nextTime ; + + if ((fd = serialOpen ("/dev/ttyAMA0", 115200)) < 0) + { + fprintf (stderr, "Unable to open serial device: %s\n", strerror (errno)) ; + return 1 ; + } + + if (wiringPiSetup () == -1) + { + fprintf (stdout, "Unable to start wiringPi: %s\n", strerror (errno)) ; + return 1 ; + } + + nextTime = millis () + 300 ; + + for (count = 0 ; count < 256 ; ) + { + if (millis () > nextTime) + { + printf ("\nOut: %3d: ", count) ; + fflush (stdout) ; + serialPutchar (fd, count) ; + nextTime += 300 ; + ++count ; + } + + delay (3) ; + + while (serialDataAvail (fd)) + { + printf (" -> %3d", serialGetchar (fd)) ; + fflush (stdout) ; + } + } + + printf ("\n") ; + return 0 ; +} diff --git a/examples/servo.c b/examples/servo.c index 0237832..aa1ab05 100644 --- a/examples/servo.c +++ b/examples/servo.c @@ -1,3 +1,27 @@ +/* + * servo.c: + * Test of the softServo code. + * Do not use this code - use the servoBlaster kernel module instead + * + * Copyright (c) 2012-2013 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 . + *********************************************************************** + */ #include #include diff --git a/examples/speed.c b/examples/speed.c index 2f5d990..863317e 100644 --- a/examples/speed.c +++ b/examples/speed.c @@ -1,8 +1,26 @@ - /* * speed.c: * Simple program to measure the speed of the various GPIO * access mechanisms. + * + * Copyright (c) 2012-2013 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 . + *********************************************************************** */ #include diff --git a/examples/test1.c b/examples/test1.c index 7eb0abd..4c75711 100644 --- a/examples/test1.c +++ b/examples/test1.c @@ -1,7 +1,27 @@ - /* * test1.c: * Simple test program to test the wiringPi functions + * This is a sequencer to make a patter appear on 8 LEDs + * connected to the GPIO pins. + * + * Copyright (c) 2012-2013 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 . + *********************************************************************** */ #include diff --git a/examples/test2.c b/examples/test2.c index e34013c..580591e 100644 --- a/examples/test2.c +++ b/examples/test2.c @@ -1,8 +1,25 @@ - /* * test2.c: - * Simple test program to test the wiringPi functions - * PWM test + * This tests the hardware PWM channel. + * + * Copyright (c) 2012-2013 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 . + *********************************************************************** */ #include diff --git a/examples/tone.c b/examples/tone.c index 8b1fcd7..0e8a47d 100644 --- a/examples/tone.c +++ b/examples/tone.c @@ -1,3 +1,27 @@ +/* + * tone.c: + * Test of the softTone module in wiringPi + * Plays a scale out on pin 3 - connect pizeo disc to pin 3 & 0v + * + * Copyright (c) 2012-2013 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 . + *********************************************************************** + */ #include #include @@ -6,15 +30,13 @@ #include #include -#define RANGE 100 -#define NUM_LEDS 12 +#define PIN 3 int scale [8] = { 262, 294, 330, 349, 392, 440, 494, 525 } ; int main () { - int i, j ; - char buf [80] ; + int i ; if (wiringPiSetup () == -1) { @@ -22,14 +44,14 @@ int main () return 1 ; } - softToneCreate (3) ; + softToneCreate (PIN) ; for (;;) { for (i = 0 ; i < 8 ; ++i) { printf ("%3d\n", i) ; - softToneWrite (3, scale [i]) ; + softToneWrite (PIN, scale [i]) ; delay (500) ; } } diff --git a/examples/wfi.c b/examples/wfi.c index 9efcc2c..6bb6892 100644 --- a/examples/wfi.c +++ b/examples/wfi.c @@ -2,7 +2,17 @@ * wfi.c: * Wait for Interrupt test program * - * Copyright (c) 2012 Gordon Henderson. + * This program demonstrates the use of the waitForInterrupt() + * function in wiringPi. It listens to a button input on + * BCM_GPIO pin 17 (wiringPi pin 0) + * + * The biggest issue with this method is that it really only works + * well in Sys mode. + * + * Jan 2013: This way of doing things is sort of deprecated now, see + * the wiringPiISR() function instead and the isr.c test program here. + * + * Copyright (c) 2012-2013 Gordon Henderson. *********************************************************************** * This file is part of wiringPi: * https://projects.drogon.net/raspberry-pi/wiringpi/ @@ -33,9 +43,8 @@ #define COUNT_KEY 0 // What BCM_GPIO input are we using? -// GPIO 0 is one of the I2C pins with an on-board pull-up -#define BUTTON_PIN 0 +#define BUTTON_PIN 17 // Debounce time in mS @@ -63,13 +72,11 @@ PI_THREAD (waitForIt) int debounceTime = 0 ; (void)piHiPri (10) ; // Set this thread to be high priority - digitalWrite (18, 1) ; for (;;) { if (waitForInterrupt (BUTTON_PIN, -1) > 0) // Got it { - // Bouncing? if (millis () < debounceTime) @@ -80,7 +87,6 @@ PI_THREAD (waitForIt) // We have a valid one - digitalWrite (17, state) ; state ^= 1 ; piLock (COUNT_KEY) ; @@ -89,7 +95,7 @@ PI_THREAD (waitForIt) // Wait for key to be released - while (digitalRead (0) == LOW) + while (digitalRead (BUTTON_PIN) == LOW) delay (1) ; debounceTime = millis () + DEBOUNCE_TIME ; @@ -108,11 +114,9 @@ void setup (void) { // Use the gpio program to initialise the hardware -// (This is the crude, but effective bit) +// (This is the crude, but effective) - system ("gpio edge 0 falling") ; - system ("gpio export 17 out") ; - system ("gpio export 18 out") ; + system ("gpio edge 17 falling") ; // Setup wiringPi @@ -120,9 +124,8 @@ void setup (void) // Fire off our interrupt handler - piThreadCreate (waitForIt) ; + piThreadCreate (waitForIt) ; - digitalWrite (17, 0) ; } @@ -147,7 +150,7 @@ int main (void) piLock (COUNT_KEY) ; myCounter = globalCounter ; piUnlock (COUNT_KEY) ; - delay (5000) ; + delay (500) ; } printf (" Done. myCounter: %5d\n", myCounter) ; diff --git a/gpio/Makefile b/gpio/Makefile index 5693c44..a043962 100644 --- a/gpio/Makefile +++ b/gpio/Makefile @@ -30,7 +30,7 @@ INCLUDE = -I/usr/local/include CFLAGS = $(DEBUG) -Wall $(INCLUDE) -Winline -pipe LDFLAGS = -L/usr/local/lib -LIBS = -lwiringPi +LIBS = -lwiringPi -lpthread -lm # May not need to alter anything below this line ############################################################################### @@ -70,8 +70,8 @@ install: .PHONEY: uninstall uninstall: @echo "[UnInstall]" - rm -f /usr/local/bin/gpio - rm -f /usr/local/man/man1/gpio.1 + @rm -f /usr/local/bin/gpio + @rm -f /usr/local/man/man1/gpio.1 .PHONEY: depend depend: diff --git a/gpio/gpio b/gpio/gpio new file mode 100755 index 0000000..54df96a Binary files /dev/null and b/gpio/gpio differ diff --git a/gpio/gpio.1 b/gpio/gpio.1 index c39e5dc..ec65519 100644 --- a/gpio/gpio.1 +++ b/gpio/gpio.1 @@ -9,7 +9,7 @@ gpio \- Command-line access to Raspberry Pi and PiFace GPIO .PP .B gpio .B [ \-g ] -.B read/write/wb/pwm/mode ... +.B read/write/wb/pwm/clock/mode ... .PP .B gpio .B [ \-p ] @@ -38,7 +38,7 @@ group value range .PP .B gpio -.B load \ i2c/spi +.B load \ i2c/spi ... .PP .B gpio .B gbr @@ -57,6 +57,9 @@ converters on the Gertboard. It's designed for simple testing and diagnostic purposes, but can be used in shell scripts for general if somewhat slow control of the GPIO pins. +It can also control the IO's on the PiFace IO board and load the SPI and I2C +kernel modules if required. + Additionally, it can be used to set the exports in the \fI/sys/class/gpio\fR system directory to allow subsequent programs to use the \fR/sys/class/gpio\fR interface without needing to be run as root. @@ -70,6 +73,8 @@ Output the current version including the board revision of the Raspberry Pi. .TP .B \-g Use the BCM_GPIO pins numbers rather than wiringPi pin numbers. +\fINOTE:\fR The BCM_GPIO pin numbers are always used with the +export and edge commands. .TP .B \-p @@ -99,7 +104,13 @@ mode. .TP .B pwm -Write a PWM value (0-1023) to the given pin. +Write a PWM value (0-1023) to the given pin. The pin needs to be put +into PWM mode first. + +.TP +.B clock +Set the output frequency on the given pin. The pin needs to be put into +clock mode first. .TP .B mode @@ -163,9 +174,18 @@ Change the PWM mode to balanced (the default) or mark:space ratio (traditional) Change the PWM range register. The default is 1024. .TP -.B load i2c/spi -This loads the i2c or the spi drivers into the system and changes the permissions on -the associated /dev/ entries so that the current user has access to them. +.B load i2c [baudrate] +This loads the i2c or drivers into the kernel and changes the permissions +on the associated /dev/ entries so that the current user has access to +them. Optionally it will set the I2C baudrate to that supplied (or as +close as the Pi can manage) The default speed is 100Kb/sec. + +.TP +.B load spi [buffer size in KB] +This loads the spi drivers into the kernel and changes the permissions +on the associated /dev/ entries so that the current user has access to +them. Optionally it will set the SPI buffer size to that supplied. The +default is 4KB. .TP .B gbr @@ -183,7 +203,7 @@ SPI digital to analogue converter. The board jumpers need to be in-place to do this operation. -.SH "WiringPi vs. GPIO Pin numbering" +.SH "WiringPi vs. BCM_GPIO Pin numbering" .PP .TS @@ -213,6 +233,12 @@ _ 20 - 31 .TE +Note that "r1" and "r2" above refers to the board revision. Normally +wiringPi detects the correct board revision with use for it's own +numbering scheme, but if you are using a Revision 2 board with some +of the pins which change numbers between revisions you will need +to alter your software. + .SH FILES .TP 2.2i @@ -264,4 +290,5 @@ warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. .SH TRADEMARKS AND ACKNOWLEDGEMENTS -Raspberry Pi is a trademark of the Raspberry Pi Foundation. +Raspberry Pi is a trademark of the Raspberry Pi Foundation. See +http://raspberrypi.org/ for full details. diff --git a/gpio/gpio.c b/gpio/gpio.c index 52fcb6f..e71e432 100644 --- a/gpio/gpio.c +++ b/gpio/gpio.c @@ -35,18 +35,20 @@ #include #include +extern int wiringPiDebug ; + #ifndef TRUE # define TRUE (1==1) # define FALSE (1==2) #endif -#define VERSION "1.5" +#define VERSION "1.12" static int wpMode ; char *usage = "Usage: gpio -v\n" " gpio -h\n" - " gpio [-g] ...\n" + " gpio [-g] ...\n" " gpio [-p] ...\n" " gpio readall\n" " gpio unexportall/exports ...\n" @@ -127,7 +129,7 @@ static int moduleLoaded (char *modName) static void _doLoadUsage (char *argv []) { - fprintf (stderr, "Usage: %s load \n", argv [0]) ; + fprintf (stderr, "Usage: %s load [SPI bufferSize in KB | I2C baudrate in Kb/sec]\n", argv [0]) ; exit (1) ; } @@ -136,16 +138,23 @@ static void doLoad (int argc, char *argv []) char *module1, *module2 ; char cmd [80] ; char *file1, *file2 ; + char args1 [32], args2 [32] ; - if (argc != 3) + if (argc < 3) _doLoadUsage (argv) ; + args1 [0] = args2 [0] = 0 ; + /**/ if (strcasecmp (argv [2], "spi") == 0) { module1 = "spidev" ; module2 = "spi_bcm2708" ; file1 = "/dev/spidev0.0" ; file2 = "/dev/spidev0.1" ; + if (argc == 4) + sprintf (args1, " bufsiz=%d", atoi (argv [3]) * 1024) ; + else if (argc > 4) + _doLoadUsage (argv) ; } else if (strcasecmp (argv [2], "i2c") == 0) { @@ -153,19 +162,23 @@ static void doLoad (int argc, char *argv []) module2 = "i2c_bcm2708" ; file1 = "/dev/i2c-0" ; file2 = "/dev/i2c-1" ; + if (argc == 4) + sprintf (args2, " baudrate=%d", atoi (argv [3]) * 1000) ; + else if (argc > 4) + _doLoadUsage (argv) ; } else _doLoadUsage (argv) ; if (!moduleLoaded (module1)) { - sprintf (cmd, "modprobe %s", module1) ; + sprintf (cmd, "modprobe %s%s", module1, args1) ; system (cmd) ; } if (!moduleLoaded (module2)) { - sprintf (cmd, "modprobe %s", module2) ; + sprintf (cmd, "modprobe %s%s", module2, args2) ; system (cmd) ; } @@ -190,55 +203,39 @@ static void doLoad (int argc, char *argv []) static char *pinNames [] = { - "GPIO 0", - "GPIO 1", - "GPIO 2", - "GPIO 3", - "GPIO 4", - "GPIO 5", - "GPIO 6", - "GPIO 7", - "SDA ", - "SCL ", - "CE0 ", - "CE1 ", - "MOSI ", - "MISO ", - "SCLK ", - "TxD ", - "RxD ", - "GPIO 8", - "GPIO 9", - "GPIO10", - "GPIO11", + "GPIO 0", "GPIO 1", "GPIO 2", "GPIO 3", "GPIO 4", "GPIO 5", "GPIO 6", "GPIO 7", + "SDA ", "SCL ", + "CE0 ", "CE1 ", "MOSI ", "MISO ", "SCLK ", + "TxD ", "RxD ", + "GPIO 8", "GPIO 9", "GPIO10", "GPIO11", +} ; + +static char *alts [] = +{ + "IN ", "OUT ", "ALT5", "ALT4", "ALT0", "ALT1", "ALT2", "ALT3" } ; static void doReadall (void) { int pin ; - printf ("+----------+------+--------+-------+\n") ; - printf ("| wiringPi | GPIO | Name | Value |\n") ; - printf ("+----------+------+--------+-------+\n") ; - - for (pin = 0 ; pin < NUM_PINS ; ++pin) - printf ("| %6d | %3d | %s | %s |\n", - pin, wpiPinToGpio (pin), - pinNames [pin], - digitalRead (pin) == HIGH ? "High" : "Low ") ; + printf ("+----------+------+--------+------+-------+\n") ; + printf ("| wiringPi | GPIO | Name | Mode | Value |\n") ; + printf ("+----------+------+--------+------+-------+\n") ; - printf ("+----------+------+--------+-------+\n") ; - - if (piBoardRev () == 1) - return ; + for (pin = 0 ; pin < 64 ; ++pin) + { + if (wpiPinToGpio (pin) == -1) + continue ; - for (pin = 17 ; pin <= 20 ; ++pin) - printf ("| %6d | %3d | %s | %s |\n", + printf ("| %6d | %3d | %s | %s | %s |\n", pin, wpiPinToGpio (pin), pinNames [pin], + alts [getAlt (pin)], digitalRead (pin) == HIGH ? "High" : "Low ") ; + } - printf ("+----------+------+--------+-------+\n") ; + printf ("+----------+------+--------+------+-------+\n") ; } @@ -544,15 +541,16 @@ void doMode (int argc, char *argv []) mode = argv [3] ; - /**/ if (strcasecmp (mode, "in") == 0) pinMode (pin, INPUT) ; - else if (strcasecmp (mode, "out") == 0) pinMode (pin, OUTPUT) ; - else if (strcasecmp (mode, "pwm") == 0) pinMode (pin, PWM_OUTPUT) ; - else if (strcasecmp (mode, "up") == 0) pullUpDnControl (pin, PUD_UP) ; - else if (strcasecmp (mode, "down") == 0) pullUpDnControl (pin, PUD_DOWN) ; - else if (strcasecmp (mode, "tri") == 0) pullUpDnControl (pin, PUD_OFF) ; + /**/ if (strcasecmp (mode, "in") == 0) pinMode (pin, INPUT) ; + else if (strcasecmp (mode, "out") == 0) pinMode (pin, OUTPUT) ; + else if (strcasecmp (mode, "pwm") == 0) pinMode (pin, PWM_OUTPUT) ; + else if (strcasecmp (mode, "clock") == 0) pinMode (pin, GPIO_CLOCK) ; + else if (strcasecmp (mode, "up") == 0) pullUpDnControl (pin, PUD_UP) ; + else if (strcasecmp (mode, "down") == 0) pullUpDnControl (pin, PUD_DOWN) ; + else if (strcasecmp (mode, "tri") == 0) pullUpDnControl (pin, PUD_OFF) ; else { - fprintf (stderr, "%s: Invalid mode: %s. Should be in/out/pwm/up/down/tri\n", argv [1], mode) ; + fprintf (stderr, "%s: Invalid mode: %s. Should be in/out/pwm/clock/up/down/tri\n", argv [1], mode) ; exit (1) ; } } @@ -758,6 +756,33 @@ void doRead (int argc, char *argv []) /* + * doClock: + * Output a clock on a pin + ********************************************************************************* + */ + +void doClock (int argc, char *argv []) +{ + int pin, freq ; + + if (argc != 4) + { + fprintf (stderr, "Usage: %s clock \n", argv [0]) ; + exit (1) ; + } + + pin = atoi (argv [2]) ; + + if ((wpMode == WPI_MODE_PINS) && ((pin < 0) || (pin >= NUM_PINS))) + return ; + + freq = atoi (argv [3]) ; + + gpioClockSet (pin, freq) ; +} + + +/* * doPwm: * Output a PWM value on a pin ********************************************************************************* @@ -848,6 +873,12 @@ int main (int argc, char *argv []) { int i ; + if (getenv ("WIRINGPI_DEBUG") != NULL) + { + printf ("gpio: wiringPi debug mode enabled\n") ; + wiringPiDebug = TRUE ; + } + if (argc == 1) { fprintf (stderr, "%s\n", usage) ; @@ -977,6 +1008,7 @@ int main (int argc, char *argv []) else if (strcasecmp (argv [1], "write") == 0) doWrite (argc, argv) ; else if (strcasecmp (argv [1], "wb") == 0) doWriteByte (argc, argv) ; else if (strcasecmp (argv [1], "pwm" ) == 0) doPwm (argc, argv) ; + else if (strcasecmp (argv [1], "clock") == 0) doClock (argc, argv) ; else if (strcasecmp (argv [1], "mode" ) == 0) doMode (argc, argv) ; else { diff --git a/wiringPi/Makefile b/wiringPi/Makefile index e18a654..c6a4555 100644 --- a/wiringPi/Makefile +++ b/wiringPi/Makefile @@ -1,4 +1,4 @@ -# +# ; # Makefile: # wiringPi - Wiring Compatable library for the Raspberry Pi # @@ -45,13 +45,19 @@ LIBS = SRC = wiringPi.c wiringPiFace.c wiringSerial.c wiringShift.c \ gertboard.c \ piNes.c \ - lcd.c piHiPri.c piThread.c wiringPiSPI.c \ + lcd.c piHiPri.c piThread.c \ + wiringPiSPI.c \ softPwm.c softServo.c softTone.c +SRC_I2C = wiringPiI2C.c + OBJ = $(SRC:.c=.o) -all: $(STATIC) $(DYNAMIC) -#all: $(DYNAMIC) +OBJ_I2C = $(SRC_I2C:.c=.o) + +all: $(DYNAMIC) + +static: $(STATIC) $(STATIC): $(OBJ) @echo "[Link (Static)]" @@ -63,13 +69,17 @@ $(DYNAMIC): $(OBJ) @echo "[Link (Dynamic)]" @$(CC) -shared -Wl,-soname,libwiringPi.so.1 -o libwiringPi.so.1.0 -lpthread $(OBJ) +i2c: $(OBJ) $(OBJ_I2C) + @echo "[Link (Dynamic + I2C)]" + @$(CC) -shared -Wl,-soname,libwiringPi.so.1 -o libwiringPi.so.1.0 -lpthread $(OBJ) $(OBJ_I2C) + .c.o: @echo [Compile] $< @$(CC) -c $(CFLAGS) $< -o $@ .PHONEY: clean clean: - rm -f $(OBJ) *~ core tags Makefile.bak libwiringPi.* + rm -f $(OBJ) $(OBJ_I2C) *~ core tags Makefile.bak libwiringPi.* .PHONEY: tags tags: $(SRC) @@ -77,7 +87,7 @@ tags: $(SRC) @ctags $(SRC) .PHONEY: install -install: $(TARGET) +install: $(DYNAMIC) @echo "[Install]" @install -m 0755 -d $(DESTDIR)$(PREFIX)/lib @install -m 0755 -d $(DESTDIR)$(PREFIX)/include @@ -91,12 +101,17 @@ install: $(TARGET) @install -m 0644 softTone.h $(DESTDIR)$(PREFIX)/include @install -m 0644 lcd.h $(DESTDIR)$(PREFIX)/include @install -m 0644 wiringPiSPI.h $(DESTDIR)$(PREFIX)/include - @install -m 0755 libwiringPi.a $(DESTDIR)$(PREFIX)/lib + @install -m 0644 wiringPiI2C.h $(DESTDIR)$(PREFIX)/include @install -m 0755 libwiringPi.so.$(VERSION) $(DESTDIR)$(PREFIX)/lib @ln -sf $(DESTDIR)$(PREFIX)/lib/libwiringPi.so.$(VERSION) $(DESTDIR)/lib/libwiringPi.so @ln -sf $(DESTDIR)$(PREFIX)/lib/libwiringPi.so.$(VERSION) $(DESTDIR)/lib/libwiringPi.so.1 @ldconfig +.PHONEY: install-static +install-static: $(STATIC) + @echo "[Install Static]" + @install -m 0755 libwiringPi.a $(DESTDIR)$(PREFIX)/lib + .PHONEY: uninstall uninstall: @echo "[UnInstall]" @@ -110,13 +125,14 @@ uninstall: @rm -f $(DESTDIR)$(PREFIX)/include/softTone.h @rm -f $(DESTDIR)$(PREFIX)/include/lcd.h @rm -f $(DESTDIR)$(PREFIX)/include/wiringPiSPI.h + @rm -f $(DESTDIR)$(PREFIX)/include/wiringPiI2C.h @rm -f $(DESTDIR)$(PREFIX)/lib/libwiringPi.* @ldconfig .PHONEY: depend depend: - makedepend -Y $(SRC) + makedepend -Y $(SRC) $(SRC_I2C) # DO NOT DELETE @@ -129,5 +145,8 @@ piNes.o: wiringPi.h piNes.h lcd.o: wiringPi.h lcd.h piHiPri.o: wiringPi.h piThread.o: wiringPi.h -softPwm.o: wiringPi.h softPwm.h wiringPiSPI.o: wiringPiSPI.h +softPwm.o: wiringPi.h softPwm.h +softServo.o: wiringPi.h softServo.h +softTone.o: wiringPi.h softTone.h +wiringPiI2C.o: wiringPi.h wiringPiI2C.h diff --git a/wiringPi/lcd.c b/wiringPi/lcd.c index aa58cab..f123db2 100644 --- a/wiringPi/lcd.c +++ b/wiringPi/lcd.c @@ -175,6 +175,18 @@ void lcdClear (int fd) /* + * lcdSendCommand: + * Send any arbitary command to the display + ********************************************************************************* + */ + +void lcdSendCommand (int fd, uint8_t command) +{ + struct lcdDataStruct *lcd = lcds [fd] ; + putCommand (lcd, command) ; +} + +/* * lcdPosition: * Update the position of the cursor on the display ********************************************************************************* diff --git a/wiringPi/lcd.h b/wiringPi/lcd.h index ecd1d25..beebb75 100644 --- a/wiringPi/lcd.h +++ b/wiringPi/lcd.h @@ -30,12 +30,13 @@ extern "C" { #endif -extern void lcdHome (int fd) ; -extern void lcdClear (int fd) ; -extern void lcdPosition (int fd, int x, int y) ; -extern void lcdPutchar (int fd, uint8_t data) ; -extern void lcdPuts (int fd, char *string) ; -extern void lcdPrintf (int fd, char *message, ...) ; +extern void lcdHome (int fd) ; +extern void lcdClear (int fd) ; +extern void lcdSendCommand (int fd, uint8_t command) ; +extern void lcdPosition (int fd, int x, int y) ; +extern void lcdPutchar (int fd, uint8_t data) ; +extern void lcdPuts (int fd, char *string) ; +extern void lcdPrintf (int fd, char *message, ...) ; extern int lcdInit (int rows, int cols, int bits, int rs, int strb, int d0, int d1, int d2, int d3, int d4, int d5, int d6, int d7) ; diff --git a/wiringPi/libwiringPi.so.1.0 b/wiringPi/libwiringPi.so.1.0 new file mode 100755 index 0000000..7c87ee9 Binary files /dev/null and b/wiringPi/libwiringPi.so.1.0 differ diff --git a/wiringPi/q2w.c b/wiringPi/q2w.c new file mode 100644 index 0000000..31486da --- /dev/null +++ b/wiringPi/q2w.c @@ -0,0 +1,89 @@ +/* + * q2w.c: + *********************************************************************** + */ + +#include +#include +#include +#include +#include + +#include +#include + +// MCP23S17 Registers + +#define IOCON 0x0A + +#define IODIRA 0x00 +#define IPOLA 0x02 +#define GPINTENA 0x04 +#define DEFVALA 0x06 +#define INTCONA 0x08 +#define GPPUA 0x0C +#define INTFA 0x0E +#define INTCAPA 0x10 +#define GPIOA 0x12 +#define OLATA 0x14 + +#define IODIRB 0x01 +#define IPOLB 0x03 +#define GPINTENB 0x05 +#define DEFVALB 0x07 +#define INTCONB 0x09 +#define GPPUB 0x0D +#define INTFB 0x0F +#define INTCAPB 0x11 +#define GPIOB 0x13 +#define OLATB 0x15 + +// Bits in the IOCON register + +#define IOCON_BANK_MODE 0x80 +#define IOCON_MIRROR 0x40 +#define IOCON_SEQOP 0x20 +#define IOCON_DISSLW 0x10 +#define IOCON_HAEN 0x08 +#define IOCON_ODR 0x04 +#define IOCON_INTPOL 0x02 +#define IOCON_UNUSED 0x01 + +// Default initialisation mode + +#define IOCON_INIT (IOCON_SEQOP) + + + +/* + ********************************************************************************* + * The works + ********************************************************************************* + */ + +int main (int argc, char *argv []) +{ + int q2w ; + +// if (wiringPiSetup () == -1) +// { fprintf (stderr, "q2w: Unable to initialise wiringPi: %s\n", strerror (errno)) ; return 1 ; } + + if ((q2w = wiringPiI2CSetup (0x20)) == -1) + { fprintf (stderr, "q2w: Unable to initialise I2C: %s\n", strerror (errno)) ; return 1 ; } + +// Very simple direct control of the MCP23017: + + wiringPiI2CWriteReg8 (q2w, IOCON, IOCON_INIT) ; + wiringPiI2CWriteReg8 (q2w, IODIRA, 0x00) ; // Port A -> Outputs + wiringPiI2CWriteReg8 (q2w, IODIRB, 0x00) ; // Port B -> Outputs + + for (;;) + { + wiringPiI2CWriteReg8 (q2w, GPIOA, 0x00) ; // All Off + delay (500) ; + wiringPiI2CWriteReg8 (q2w, GPIOA, 0xFF) ; // All On + delay (500) ; + } + + return 0 ; +} diff --git a/wiringPi/softServo.c b/wiringPi/softServo.c index a6ff1fb..9de9f4f 100644 --- a/wiringPi/softServo.c +++ b/wiringPi/softServo.c @@ -54,6 +54,15 @@ // the multipexing, but it does need to be at least 10mS, and preferably 16 // from what I've been able to determine. +// WARNING: +// This code is really experimental. It was written in response to some people +// asking for a servo driver, however while it works, there is too much +// jitter to successfully drive a small servo - I have tried it with a micro +// servo and it worked, but the servo ran hot due to the jitter in the signal +// being sent to it. +// +// If you want servo control for the Pi, then use the servoblaster kernel +// module. #define MAX_SERVOS 8 diff --git a/wiringPi/softTone.c b/wiringPi/softTone.c index d14c2a2..8463627 100644 --- a/wiringPi/softTone.c +++ b/wiringPi/softTone.c @@ -59,7 +59,9 @@ static PI_THREAD (softToneThread) for (;;) { frewq = frewqs [pin] ; - if (frewq != 0) + if (frewq == 0) + delay (1) ; + else { halfPeriod = 500000 / frewq ; diff --git a/wiringPi/wiringPi.c b/wiringPi/wiringPi.c index df4d969..a68ae33 100644 --- a/wiringPi/wiringPi.c +++ b/wiringPi/wiringPi.c @@ -51,9 +51,6 @@ // Added in the 2 UART pins // Change maxPins to numPins to more accurately reflect purpose -// Pad drive current fiddling - -#undef DEBUG_PADS #include #include @@ -65,24 +62,27 @@ #include #include #include +#include #include #include -#include #include +#include +#include #include "wiringPi.h" // Function stubs void (*pinMode) (int pin, int mode) ; +int (*getAlt) (int pin) ; void (*pullUpDnControl) (int pin, int pud) ; void (*digitalWrite) (int pin, int value) ; void (*digitalWriteByte) (int value) ; void (*pwmWrite) (int pin, int value) ; +void (*gpioClockSet) (int pin, int value) ; void (*setPadDrive) (int group, int value) ; int (*digitalRead) (int pin) ; int (*waitForInterrupt) (int pin, int mS) ; -void (*delayMicroseconds) (unsigned int howLong) ; void (*pwmSetMode) (int mode) ; void (*pwmSetRange) (unsigned int range) ; void (*pwmSetClock) (int divisor) ; @@ -98,6 +98,24 @@ void (*pwmSetClock) (int divisor) ; #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 @@ -111,20 +129,21 @@ void (*pwmSetClock) (int divisor) ; #define FSEL_ALT5 0b010 // Access from ARM Running Linux -// Take from Gert/Doms code. Some of this is not in the manual +// Taken from Gert/Doms code. Some of this is not in the manual // that I can find )-: -#define BCM2708_PERI_BASE 0x20000000 -#define GPIO_PADS (BCM2708_PERI_BASE + 0x100000) -#define CLOCK_BASE (BCM2708_PERI_BASE + 0x101000) -#define GPIO_BASE (BCM2708_PERI_BASE + 0x200000) -#define GPIO_TIMER (BCM2708_PERI_BASE + 0x00B000) -#define GPIO_PWM (BCM2708_PERI_BASE + 0x20C000) +#define BCM2708_PERI_BASE 0x20000000 +#define GPIO_PADS (BCM2708_PERI_BASE + 0x00100000) +#define CLOCK_BASE (BCM2708_PERI_BASE + 0x00101000) +#define GPIO_BASE (BCM2708_PERI_BASE + 0x00200000) +#define GPIO_TIMER (BCM2708_PERI_BASE + 0x0000B000) +#define GPIO_PWM (BCM2708_PERI_BASE + 0x0020C000) #define PAGE_SIZE (4*1024) #define BLOCK_SIZE (4*1024) // PWM +// Word offsets into the PWM control region #define PWM_CONTROL 0 #define PWM_STATUS 1 @@ -133,17 +152,11 @@ void (*pwmSetClock) (int divisor) ; #define PWM1_RANGE 8 #define PWM1_DATA 9 +// Clock regsiter offsets + #define PWMCLK_CNTL 40 #define PWMCLK_DIV 41 -#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 - #define PWM0_MS_MODE 0x0080 // Run in MS mode #define PWM0_USEFIFO 0x0020 // Data from FIFO #define PWM0_REVPOLAR 0x0010 // Reverse polarity @@ -152,7 +165,16 @@ void (*pwmSetClock) (int divisor) ; #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) @@ -173,33 +195,28 @@ static volatile uint32_t *pads ; static volatile uint32_t *timer ; static volatile uint32_t *timerIrqRaw ; -// Debugging +// Time for easy calculations -static int wiringPiDebug = FALSE ; +static uint64_t epochMilli, epochMicro ; -// 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: -// -// 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) +// Misc + +static int wiringPiMode = WPI_MODE_UNINITIALISED ; + +// Debugging + +int wiringPiDebug = FALSE ; // sysFds: // Map a file descriptor from the /sys/class/gpio/gpioX/value static int sysFds [64] ; +// 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! @@ -329,11 +346,14 @@ static uint8_t gpioToFEN [] = #endif -// gpioToPUDCLK -// (Word) offset to the Pull Up Down Clock regsiter +// 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, @@ -356,6 +376,9 @@ static uint8_t gpioToPwmALT [] = 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 @@ -369,10 +392,55 @@ static uint8_t gpioToPwmPort [] = } ; +// 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 respectivey, however I'll include the full +// list for completeness - maybe one day... -// Time for easy calculations +#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 +} ; -static unsigned long long epoch ; /* * Functions @@ -407,9 +475,11 @@ int wpiPinToGpio (int wpiPin) * 0001 - Not used * 0002 - Rev 1 * 0003 - Rev 1 - * 0004 - Rev 2 - * 0005 - Rev 2 (but error) + * 0004 - Rev 2 (Early reports? + * 0005 - Rev 2 (but error?) * 0006 - Rev 2 + * 0008 - Rev 2 - Model A + * 000e - Rev 2 + 512MB * 000f - Rev 2 + 512MB * * A small thorn is the olde style overvolting - that will add in @@ -418,6 +488,15 @@ int wpiPinToGpio (int wpiPin) ********************************************************************************* */ +static void piBoardRevOops (char *why) +{ + fprintf (stderr, "piBoardRev: Unable to determine board revision from /proc/cpuinfo\n") ; + fprintf (stderr, " -> %s\n", why) ; + fprintf (stderr, " -> You may want to check:\n") ; + fprintf (stderr, " -> http://www.raspberrypi.org/phpBB3/viewtopic.php?p=184410#p184410\n") ; + exit (EXIT_FAILURE) ; +} + int piBoardRev (void) { FILE *cpuFd ; @@ -425,13 +504,11 @@ int piBoardRev (void) char *c, lastChar ; static int boardRev = -1 ; -// No point checking twice... - - if (boardRev != -1) + if (boardRev != -1) // No point checking twice return boardRev ; if ((cpuFd = fopen ("/proc/cpuinfo", "r")) == NULL) - return -1 ; + piBoardRevOops ("Unable to open /proc/cpuinfo") ; while (fgets (line, 120, cpuFd) != NULL) if (strncmp (line, "Revision", 8) == 0) @@ -439,25 +516,21 @@ int piBoardRev (void) fclose (cpuFd) ; - if (line == NULL) - { - fprintf (stderr, "piBoardRev: Unable to determine board revision from /proc/cpuinfo\n") ; - fprintf (stderr, " (No \"Revision\" line)\n") ; - errno = 0 ; - return -1 ; - } + if (strncmp (line, "Revision", 8) != 0) + piBoardRevOops ("No \"Revision\" line") ; + + for (c = &line [strlen (line) - 1] ; (*c == '\n') || (*c == '\r') ; --c) + *c = 0 ; + if (wiringPiDebug) + printf ("piboardRev: Revision string: %s\n", line) ; + for (c = line ; *c ; ++c) if (isdigit (*c)) break ; if (!isdigit (*c)) - { - fprintf (stderr, "piBoardRev: Unable to determine board revision from /proc/cpuinfo\n") ; - fprintf (stderr, " (No numeric revision string in: \"%s\"\n", line) ; - errno = 0 ; - return -1 ; - } + piBoardRevOops ("No numeric revision string") ; // If you have overvolted the Pi, then it appears that the revision // has 100000 added to it! @@ -466,26 +539,18 @@ int piBoardRev (void) if (strlen (c) != 4) printf ("piboardRev: This Pi has/is overvolted!\n") ; - lastChar = c [strlen (c) - 2] ; + lastChar = line [strlen (line) - 1] ; + + if (wiringPiDebug) + printf ("piboardRev: lastChar is: '%c' (%d, 0x%02X)\n", lastChar, lastChar, lastChar) ; /**/ if ((lastChar == '2') || (lastChar == '3')) boardRev = 1 ; else boardRev = 2 ; -#ifdef DO_WE_CARE_ABOUT_THIS_NOW - else - { - fprintf (stderr, "WARNING: wiringPi: Unable to determine board revision from \"%d\"\n", r) ; - fprintf (stderr, " -> You may want to check:\n") ; - fprintf (stderr, " -> http://www.raspberrypi.org/phpBB3/viewtopic.php?p=184410#p184410\n") ; - fprintf (stderr, " -> Assuming a Rev 1 board\n") ; - boardRev = 1 ; - } -#endif - if (wiringPiDebug) - printf ("piboardRev: Revision string: %s, board revision: %d\n", c, boardRev) ; + printf ("piBoardRev: Returning revision: %d\n", boardRev) ; return boardRev ; } @@ -493,15 +558,14 @@ int piBoardRev (void) /* - * pinMode: - * Sets the mode of a pin to be input, output or PWM output + * getAlt: + * Returns the ALT bits for a given port. Only really of-use + * for the gpio readall command (I think) ********************************************************************************* */ -void pinModeGpio (int pin, int mode) +int getAltGpio (int pin) { -// register int barrier ; - int fSel, shift, alt ; pin &= 63 ; @@ -509,73 +573,19 @@ void pinModeGpio (int pin, int mode) 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 == PWM_OUTPUT) - { - if ((alt = gpioToPwmALT [pin]) == 0) // Not a PWM pin - return ; - -// Set pin to PWM mode - - *(gpio + fSel) = (*(gpio + fSel) & ~(7 << shift)) | (alt << shift) ; - - delayMicroseconds (110) ; // See comments in pwmSetClockWPi - *(gpio + fSel) = (*(gpio + fSel) & ~(7 << shift)) | (alt << shift) ; - -// Page 107 of the BCM Peripherals manual talks about the GPIO clocks, -// but I'm assuming (hoping!) that this applies to other clocks too. - - *(pwm + PWM_CONTROL) = 0 ; // Stop PWM - - *(clk + PWMCLK_CNTL) = BCM_PASSWORD | 0x01 ; // Stop PWM Clock - delayMicroseconds (110) ; // See comments in pwmSetClockWPi - - while ((*(clk + PWMCLK_CNTL) & 0x80) != 0) // Wait for clock to be !BUSY - delayMicroseconds (1) ; - - *(clk + PWMCLK_DIV) = BCM_PASSWORD | (32 << 12) ; // set pwm div to 32 (19.2/32 = 600KHz) - *(clk + PWMCLK_CNTL) = BCM_PASSWORD | 0x11 ; // enable clk - - delayMicroseconds (110) ; // See comments in pwmSetClockWPi - -// Default range register of 1024 - - *(pwm + PWM0_RANGE) = 1024 ; delayMicroseconds (10) ; - *(pwm + PWM1_RANGE) = 1024 ; delayMicroseconds (10) ; - *(pwm + PWM0_DATA) = 0 ; delayMicroseconds (10) ; - *(pwm + PWM1_DATA) = 0 ; delayMicroseconds (10) ; - -// Enable PWMs in balanced mode (default) - - *(pwm + PWM_CONTROL) = PWM0_ENABLE | PWM1_ENABLE ; - - delay (100) ; - } - - -// When we change mode of any pin, we remove the pull up/downs -// Or we used to... Hm. Commented out now because for some wieird reason, -// it seems to block subsequent attempts to set the pull up/downs and I've -// not quite gotten to the bottom of why this happens -// The down-side is that the pull up/downs are rememberd in the SoC between -// power cycles, so it's going to be a good idea to explicitly set them in -// any new code. -// -// pullUpDnControl (pin, PUD_OFF) ; + alt = (*(gpio + fSel) >> shift) & 7 ; + return alt ; } -void pinModeWPi (int pin, int mode) +int getAltWPi (int pin) { - pinModeGpio (pinToGpio [pin & 63], mode) ; + return getAltGpio (pinToGpio [pin & 63]) ; } -void pinModeSys (int pin, int mode) +int getAltSys (int pin) { - return ; + return 0 ; } @@ -620,7 +630,7 @@ void pwmSetRangeSys (unsigned int range) void pwmSetClockWPi (int divisor) { - unsigned int pwm_control ; + uint32_t pwm_control ; divisor &= 4095 ; if (wiringPiDebug) @@ -741,11 +751,11 @@ void digitalWriteByteGpio (int value) else pinSet |= (1 << pinToGpio [pin]) ; - *(gpio + gpioToGPCLR [0]) = pinClr ; - *(gpio + gpioToGPSET [0]) = pinSet ; - mask <<= 1 ; } + + *(gpio + gpioToGPCLR [0]) = pinClr ; + *(gpio + gpioToGPSET [0]) = pinSet ; } void digitalWriteByteSys (int value) @@ -789,6 +799,44 @@ void pwmWriteSys (int pin, int value) /* + * gpioClockSet: + * Set the freuency on a GPIO clock pin + ********************************************************************************* + */ + +void gpioClockSetGpio (int pin, int freq) +{ + int divi, divr, divf ; + + pin &= 63 ; + + 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 +} + +void gpioClockSetWPi (int pin, int freq) +{ + gpioClockSetGpio (pinToGpio [pin & 63], freq) ; +} + +void gpioClockSetSys (int pin, int freq) +{ + return ; +} + + +/* * setPadDrive: * Set the PAD driver value ********************************************************************************* @@ -804,10 +852,11 @@ void setPadDriveWPi (int group, int value) wrVal = BCM_PASSWORD | 0x18 | (value & 7) ; *(pads + group + 11) = wrVal ; -#ifdef DEBUG_PADS - printf ("setPadDrive: Group: %d, value: %d (%08X)\n", group, value, wrVal) ; - printf ("Read : %08X\n", *(pads + group + 11)) ; -#endif + if (wiringPiDebug) + { + printf ("setPadDrive: Group: %d, value: %d (%08X)\n", group, value, wrVal) ; + printf ("Read : %08X\n", *(pads + group + 11)) ; + } } void setPadDriveGpio (int group, int value) @@ -895,6 +944,65 @@ void pullUpDnControlSys (int pin, int pud) /* + * pinMode: + * Sets the mode of a pin to be input, output or PWM output + ********************************************************************************* + */ + +void pinModeGpio (int pin, int mode) +{ +// register int barrier ; + + int fSel, shift, alt ; + + pin &= 63 ; + + 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 == PWM_OUTPUT) + { + if ((alt = gpioToPwmALT [pin]) == 0) // Not a PWM pin + return ; + +// Set pin to PWM mode + + *(gpio + fSel) = (*(gpio + fSel) & ~(7 << shift)) | (alt << shift) ; + delayMicroseconds (110) ; // See comments in pwmSetClockWPi + + pwmSetModeWPi (PWM_MODE_BAL) ; // Pi default mode + pwmSetRangeWPi (1024) ; // Default range of 1024 + pwmSetClockWPi (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 ; + +// Set pin to GPIO_CLOCK mode and set the clock frequency to 100KHz + + *(gpio + fSel) = (*(gpio + fSel) & ~(7 << shift)) | (alt << shift) ; + delayMicroseconds (110) ; + gpioClockSetGpio (pin, 100000) ; + } +} + +void pinModeWPi (int pin, int mode) +{ + pinModeGpio (pinToGpio [pin & 63], mode) ; +} + +void pinModeSys (int pin, int mode) +{ + return ; +} + + +/* * waitForInterrupt: * Wait for Interrupt on a GPIO pin. * This is actually done via the /sys/class/gpio interface regardless of @@ -906,22 +1014,12 @@ void pullUpDnControlSys (int pin, int pud) int waitForInterruptSys (int pin, int mS) { int fd, x ; - char buf [8] ; + uint8_t c ; struct pollfd polls ; if ((fd = sysFds [pin & 63]) == -1) return -2 ; -// Do a dummy read - - x = read (fd, buf, 6) ; - if (x < 0) - return x ; - -// And seek - - lseek (fd, 0, SEEK_SET) ; - // Setup poll structure polls.fd = fd ; @@ -929,7 +1027,14 @@ int waitForInterruptSys (int pin, int mS) // Wait for it ... - return poll (&polls, 1, mS) ; + x = poll (&polls, 1, mS) ; + +// Do a dummy read to clear the interrupt +// A one character read appars to be enough. + + (void)read (fd, &c, 1) ; + + return x ; } int waitForInterruptWPi (int pin, int mS) @@ -944,6 +1049,123 @@ int waitForInterruptGpio (int pin, int mS) /* + * 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 (void *arg) +{ + int myPin = *(int *)arg ; + + (void)piHiPri (55) ; // Only effective if we run as root + + for (;;) + if (waitForInterruptSys (myPin, -1) > 0) + isrFunctions [myPin] () ; + + return NULL ; +} + + +/* + * wiringPiISR: + * 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 ; + char fName [64] ; + char *modeS ; + char pinS [8] ; + pid_t pid ; + int count, i ; + uint8_t c ; + + pin &= 63 ; + + if (wiringPiMode == WPI_MODE_UNINITIALISED) + { + fprintf (stderr, "wiringPiISR: wiringPi has not been initialised. Unable to continue.\n") ; + exit (EXIT_FAILURE) ; + } + else if (wiringPiMode == WPI_MODE_PINS) + pin = pinToGpio [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", pin) ; + + if ((pid = fork ()) < 0) // Fail + return pid ; + + if (pid == 0) // Child, exec + { + execl ("/usr/local/bin/gpio", "gpio", "edge", pinS, modeS, (char *)NULL) ; + return -1 ; // Failure ... + } + else // Parent, wait + wait (NULL) ; + } + +// Now pre-open the /sys/class node - it may already be open if +// we are in Sys mode, but this will do no harm. + + sprintf (fName, "/sys/class/gpio/gpio%d/value", pin) ; + if ((sysFds [pin] = open (fName, O_RDWR)) < 0) + return -1 ; + +// Clear any initial pending interrupt + + ioctl (sysFds [pin], FIONREAD, &count) ; + for (i = 0 ; i < count ; ++i) + read (sysFds [pin], &c, 1) ; + + isrFunctions [pin] = function ; + + pthread_create (&threadId, NULL, interruptHandler, &pin) ; + + delay (1) ; + + return 0 ; +} + + +/* + * initialiseEpoch: + * Initialise our start-of-time variable to be the current unix + * time in milliseconds. + ********************************************************************************* + */ + +static void initialiseEpoch (void) +{ + 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) ; +} + +/* * delay: * Wait for some number of milli seconds ********************************************************************************* @@ -978,28 +1200,8 @@ void delay (unsigned int howLong) ********************************************************************************* */ -void delayMicrosecondsSys (unsigned int howLong) -{ - struct timespec sleeper, dummy ; - - sleeper.tv_sec = 0 ; - sleeper.tv_nsec = (long)(howLong * 1000) ; - - nanosleep (&sleeper, &dummy) ; -} - void delayMicrosecondsHard (unsigned int howLong) { -#ifdef HARD_TIMER - volatile unsigned int dummy ; - - *(timer + TIMER_LOAD) = howLong ; - *(timer + TIMER_IRQ_CLR) = 0 ; - - dummy = *timerIrqRaw ; - while (dummy == 0) - dummy = *timerIrqRaw ; -#else struct timeval tNow, tLong, tEnd ; gettimeofday (&tNow, NULL) ; @@ -1009,10 +1211,9 @@ void delayMicrosecondsHard (unsigned int howLong) while (timercmp (&tNow, &tEnd, <)) gettimeofday (&tNow, NULL) ; -#endif } -void delayMicrosecondsWPi (unsigned int howLong) +void delayMicroseconds (unsigned int howLong) { struct timespec sleeper ; @@ -1038,13 +1239,30 @@ void delayMicrosecondsWPi (unsigned int howLong) unsigned int millis (void) { struct timeval tv ; - unsigned long long t1 ; + uint64_t now ; gettimeofday (&tv, NULL) ; + now = (uint64_t)tv.tv_sec * (uint64_t)1000 + (uint64_t)(tv.tv_usec / 1000) ; + + return (uint32_t)(now - epochMilli) ; +} - t1 = (tv.tv_sec * 1000000 + tv.tv_usec) / 1000 ; - return (uint32_t)(t1 - epoch) ; +/* + * micros: + * Return a number of microseconds as an unsigned int. + ********************************************************************************* + */ + +unsigned int micros (void) +{ + struct timeval tv ; + uint64_t now ; + + gettimeofday (&tv, NULL) ; + now = (uint64_t)tv.tv_sec * (uint64_t)1000000 + (uint64_t)tv.tv_usec ; + + return (uint32_t)(now - epochMicro) ; } @@ -1061,30 +1279,37 @@ int wiringPiSetup (void) { int fd ; int boardRev ; - uint8_t *gpioMem, *pwmMem, *clkMem, *padsMem, *timerMem ; - struct timeval tv ; + + if (geteuid () != 0) + { + fprintf (stderr, "wiringPi:\n Must be root to call wiringPiSetup().\n (Did you forget sudo?)\n") ; + exit (EXIT_FAILURE) ; + } if (getenv ("WIRINGPI_DEBUG") != NULL) + { + printf ("wiringPi: Debug mode enabled\n") ; wiringPiDebug = TRUE ; + } if (wiringPiDebug) printf ("wiringPi: wiringPiSetup called\n") ; pinMode = pinModeWPi ; + getAlt = getAltWPi ; pullUpDnControl = pullUpDnControlWPi ; digitalWrite = digitalWriteWPi ; digitalWriteByte = digitalWriteByteGpio ; // Same code + gpioClockSet = gpioClockSetWPi ; pwmWrite = pwmWriteWPi ; setPadDrive = setPadDriveWPi ; digitalRead = digitalReadWPi ; waitForInterrupt = waitForInterruptWPi ; - delayMicroseconds = delayMicrosecondsWPi ; pwmSetMode = pwmSetModeWPi ; pwmSetRange = pwmSetRangeWPi ; pwmSetClock = pwmSetClockWPi ; - if ((boardRev = piBoardRev ()) < 0) - return -1 ; + boardRev = piBoardRev () ; if (boardRev == 1) pinToGpio = pinToGpioR1 ; @@ -1095,111 +1320,82 @@ int wiringPiSetup (void) if ((fd = open ("/dev/mem", O_RDWR | O_SYNC) ) < 0) { - fprintf (stderr, "wiringPiSetup: Unable to open /dev/mem: %s\n", strerror (errno)) ; + if (wiringPiDebug) + { + int serr = errno ; + fprintf (stderr, "wiringPiSetup: Unable to open /dev/mem: %s\n", strerror (errno)) ; + errno = serr ; + } return -1 ; } // GPIO: -// Allocate 2 pages - 1 ... - - if ((gpioMem = malloc (BLOCK_SIZE + (PAGE_SIZE-1))) == NULL) + gpio = (uint32_t *)mmap(0, BLOCK_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED, fd, GPIO_BASE) ; + if ((int32_t)gpio == -1) { - fprintf (stderr, "wiringPiSetup: malloc failed: %s\n", strerror (errno)) ; - return -1 ; - } - -// ... presumably to make sure we can round it up to a whole page size - - if (((uint32_t)gpioMem % PAGE_SIZE) != 0) - gpioMem += PAGE_SIZE - ((uint32_t)gpioMem % PAGE_SIZE) ; - - gpio = (uint32_t *)mmap((caddr_t)gpioMem, BLOCK_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED|MAP_FIXED, fd, GPIO_BASE) ; - - if ((int32_t)gpio < 0) - { - fprintf (stderr, "wiringPiSetup: mmap failed: %s\n", strerror (errno)) ; + if (wiringPiDebug) + { + int serr = errno ; + fprintf (stderr, "wiringPiSetup: mmap failed: %s\n", strerror (errno)) ; + errno = serr ; + } return -1 ; } // PWM - if ((pwmMem = malloc (BLOCK_SIZE + (PAGE_SIZE-1))) == NULL) + pwm = (uint32_t *)mmap(0, BLOCK_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED, fd, GPIO_PWM) ; + if ((int32_t)pwm == -1) { - fprintf (stderr, "wiringPiSetup: pwmMem malloc failed: %s\n", strerror (errno)) ; - return -1 ; - } - - if (((uint32_t)pwmMem % PAGE_SIZE) != 0) - pwmMem += PAGE_SIZE - ((uint32_t)pwmMem % PAGE_SIZE) ; - - pwm = (uint32_t *)mmap(pwmMem, BLOCK_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED|MAP_FIXED, fd, GPIO_PWM) ; - - if ((int32_t)pwm < 0) - { - fprintf (stderr, "wiringPiSetup: mmap failed (pwm): %s\n", strerror (errno)) ; + if (wiringPiDebug) + { + int serr = errno ; + fprintf (stderr, "wiringPiSetup: mmap failed (pwm): %s\n", strerror (errno)) ; + errno = serr ; + } return -1 ; } // Clock control (needed for PWM) - if ((clkMem = malloc (BLOCK_SIZE + (PAGE_SIZE-1))) == NULL) - { - fprintf (stderr, "wiringPiSetup: clkMem malloc failed: %s\n", strerror (errno)) ; - return -1 ; - } - - if (((uint32_t)clkMem % PAGE_SIZE) != 0) - clkMem += PAGE_SIZE - ((uint32_t)clkMem % PAGE_SIZE) ; - - clk = (uint32_t *)mmap(clkMem, BLOCK_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED|MAP_FIXED, fd, CLOCK_BASE) ; - - if ((int32_t)clk < 0) + clk = (uint32_t *)mmap(0, BLOCK_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED, fd, CLOCK_BASE) ; + if ((int32_t)clk == -1) { - fprintf (stderr, "wiringPiSetup: mmap failed (clk): %s\n", strerror (errno)) ; + if (wiringPiDebug) + { + int serr = errno ; + fprintf (stderr, "wiringPiSetup: mmap failed (clk): %s\n", strerror (errno)) ; + errno = serr ; + } return -1 ; } // The drive pads - if ((padsMem = malloc (BLOCK_SIZE + (PAGE_SIZE-1))) == NULL) + pads = (uint32_t *)mmap(0, BLOCK_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED, fd, GPIO_PADS) ; + if ((int32_t)pads == -1) { - fprintf (stderr, "wiringPiSetup: padsMem malloc failed: %s\n", strerror (errno)) ; + if (wiringPiDebug) + { + int serr = errno ; + fprintf (stderr, "wiringPiSetup: mmap failed (pads): %s\n", strerror (errno)) ; + errno = serr ; + } return -1 ; } - if (((uint32_t)padsMem % PAGE_SIZE) != 0) - padsMem += PAGE_SIZE - ((uint32_t)padsMem % PAGE_SIZE) ; - - pads = (uint32_t *)mmap(padsMem, BLOCK_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED|MAP_FIXED, fd, GPIO_PADS) ; - - if ((int32_t)pads < 0) - { - fprintf (stderr, "wiringPiSetup: mmap failed (pads): %s\n", strerror (errno)) ; - return -1 ; - } - -#ifdef DEBUG_PADS - printf ("Checking pads @ 0x%08X\n", (unsigned int)pads) ; - printf (" -> %08X %08X %08X\n", *(pads + 11), *(pads + 12), *(pads + 13)) ; -#endif - // The system timer - if ((timerMem = malloc (BLOCK_SIZE + (PAGE_SIZE-1))) == NULL) + timer = (uint32_t *)mmap(0, BLOCK_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED, fd, GPIO_TIMER) ; + if ((int32_t)timer == -1) { - fprintf (stderr, "wiringPiSetup: timerMem malloc failed: %s\n", strerror (errno)) ; - return -1 ; - } - - if (((uint32_t)timerMem % PAGE_SIZE) != 0) - timerMem += PAGE_SIZE - ((uint32_t)timerMem % PAGE_SIZE) ; - - timer = (uint32_t *)mmap(timerMem, BLOCK_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED|MAP_FIXED, fd, GPIO_TIMER) ; - - if ((int32_t)timer < 0) - { - fprintf (stderr, "wiringPiSetup: mmap failed (timer): %s\n", strerror (errno)) ; + if (wiringPiDebug) + { + int serr = errno ; + fprintf (stderr, "wiringPiSetup: mmap failed (timer): %s\n", strerror (errno)) ; + errno = serr ; + } return -1 ; } @@ -1211,10 +1407,9 @@ int wiringPiSetup (void) *(timer + TIMER_PRE_DIV) = 0x00000F9 ; timerIrqRaw = timer + TIMER_IRQ_RAW ; -// Initialise our epoch for millis() + initialiseEpoch () ; - gettimeofday (&tv, NULL) ; - epoch = (tv.tv_sec * 1000000 + tv.tv_usec) / 1000 ; + wiringPiMode = WPI_MODE_PINS ; return 0 ; } @@ -1233,25 +1428,34 @@ int wiringPiSetupGpio (void) { int x ; - if (wiringPiDebug) - printf ("wiringPi: wiringPiSetupGpio called\n") ; + if (geteuid () != 0) + { + fprintf (stderr, "Must be root to call wiringPiSetupGpio(). (Did you forget sudo?)\n") ; + exit (EXIT_FAILURE) ; + } if ((x = wiringPiSetup ()) < 0) return x ; + if (wiringPiDebug) + printf ("wiringPi: wiringPiSetupGpio called\n") ; + pinMode = pinModeGpio ; + getAlt = getAltGpio ; pullUpDnControl = pullUpDnControlGpio ; digitalWrite = digitalWriteGpio ; digitalWriteByte = digitalWriteByteGpio ; + gpioClockSet = gpioClockSetGpio ; pwmWrite = pwmWriteGpio ; setPadDrive = setPadDriveGpio ; digitalRead = digitalReadGpio ; waitForInterrupt = waitForInterruptGpio ; - delayMicroseconds = delayMicrosecondsWPi ; // Same pwmSetMode = pwmSetModeWPi ; pwmSetRange = pwmSetRangeWPi ; pwmSetClock = pwmSetClockWPi ; + wiringPiMode = WPI_MODE_GPIO ; + return 0 ; } @@ -1269,34 +1473,35 @@ int wiringPiSetupSys (void) { int boardRev ; int pin ; - struct timeval tv ; char fName [128] ; + if (getenv ("WIRINGPI_DEBUG") != NULL) + wiringPiDebug = TRUE ; + if (wiringPiDebug) printf ("wiringPi: wiringPiSetupSys called\n") ; pinMode = pinModeSys ; + getAlt = getAltSys ; pullUpDnControl = pullUpDnControlSys ; digitalWrite = digitalWriteSys ; digitalWriteByte = digitalWriteByteSys ; + gpioClockSet = gpioClockSetSys ; pwmWrite = pwmWriteSys ; setPadDrive = setPadDriveSys ; digitalRead = digitalReadSys ; waitForInterrupt = waitForInterruptSys ; - delayMicroseconds = delayMicrosecondsSys ; pwmSetMode = pwmSetModeSys ; pwmSetRange = pwmSetRangeSys ; pwmSetClock = pwmSetClockSys ; - if ((boardRev = piBoardRev ()) < 0) - return -1 ; + boardRev = piBoardRev () ; if (boardRev == 1) pinToGpio = pinToGpioR1 ; else pinToGpio = pinToGpioR2 ; - // Open and scan the directory, looking for exported GPIOs, and pre-open // the 'value' interface to speed things up for later @@ -1306,10 +1511,9 @@ int wiringPiSetupSys (void) sysFds [pin] = open (fName, O_RDWR) ; } -// Initialise the epoch for mills() ... + initialiseEpoch () ; - gettimeofday (&tv, NULL) ; - epoch = (tv.tv_sec * 1000000 + tv.tv_usec) / 1000 ; + wiringPiMode = WPI_MODE_GPIO_SYS ; return 0 ; } diff --git a/wiringPi/wiringPi.h b/wiringPi/wiringPi.h index 6a7278e..18c6da5 100644 --- a/wiringPi/wiringPi.h +++ b/wiringPi/wiringPi.h @@ -23,32 +23,50 @@ // Handy defines +// Deprecated #define NUM_PINS 17 #define WPI_MODE_PINS 0 #define WPI_MODE_GPIO 1 #define WPI_MODE_GPIO_SYS 2 #define WPI_MODE_PIFACE 3 +#define WPI_MODE_UNINITIALISED -1 -#define INPUT 0 -#define OUTPUT 1 -#define PWM_OUTPUT 2 +// Pin modes -#define LOW 0 -#define HIGH 1 +#define INPUT 0 +#define OUTPUT 1 +#define PWM_OUTPUT 2 +#define GPIO_CLOCK 3 -#define PUD_OFF 0 -#define PUD_DOWN 1 -#define PUD_UP 2 +#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 +#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 + +// Threads + +#define PI_THREAD(X) void *X (void *dummy) // Function prototypes -// c++ wrappers thanks to a commend by Nick Lott +// c++ wrappers thanks to a comment by Nick Lott // (and others on the Raspberry Pi forums) #ifdef __cplusplus @@ -68,13 +86,14 @@ extern int wpiPinToGpio (int wpiPin) ; extern int wiringPiSetupPiFaceForGpioProg (void) ; // Don't use this - for gpio program only extern void (*pinMode) (int pin, int mode) ; +extern int (*getAlt) (int pin) ; extern void (*pullUpDnControl) (int pin, int pud) ; extern void (*digitalWrite) (int pin, int value) ; extern void (*digitalWriteByte) (int value) ; +extern void (*gpioClockSet) (int pin, int freq) ; extern void (*pwmWrite) (int pin, int value) ; extern void (*setPadDrive) (int group, int value) ; extern int (*digitalRead) (int pin) ; -extern void (*delayMicroseconds) (unsigned int howLong) ; extern void (*pwmSetMode) (int mode) ; extern void (*pwmSetRange) (unsigned int range) ; extern void (*pwmSetClock) (int divisor) ; @@ -82,11 +101,10 @@ extern void (*pwmSetClock) (int divisor) ; // Interrupts extern int (*waitForInterrupt) (int pin, int mS) ; +extern int wiringPiISR (int pin, int mode, void (*function)(void)) ; // Threads -#define PI_THREAD(X) void *X (void *dummy) - extern int piThreadCreate (void *(*fn)(void *)) ; extern void piLock (int key) ; extern void piUnlock (int key) ; @@ -99,7 +117,9 @@ extern int piHiPri (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 } diff --git a/wiringPi/wiringPiI2C.c b/wiringPi/wiringPiI2C.c new file mode 100644 index 0000000..93fe1d3 --- /dev/null +++ b/wiringPi/wiringPiI2C.c @@ -0,0 +1,122 @@ +/* + * wiringPiI2C.c: + * Simplified I2C access routines + * Copyright (c) 2013 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 . + *********************************************************************** + */ + +#include +#include +#include +#include +#include + +#include "wiringPi.h" +#include "wiringPiI2C.h" + + +/* + * wiringPiI2CRead: + * Simple device read + ********************************************************************************* + */ + +int wiringPiI2CRead (int fd) +{ + return i2c_smbus_read_byte (fd) ; +} + + +/* + * wiringPiI2CReadReg8: wiringPiI2CReadReg16: + * Read an 8 or 16-bit value from a regsiter on the device + ********************************************************************************* + */ + +int wiringPiI2CReadReg8 (int fd, int reg) +{ + return i2c_smbus_read_byte_data (fd, reg) ; +} + +int wiringPiI2CReadReg16 (int fd, int reg) +{ + return i2c_smbus_read_word_data (fd, reg) ; +} + + +/* + * wiringPiI2CWrite: + * Simple device write + ********************************************************************************* + */ + +int wiringPiI2CWrite (int fd, int data) +{ + return i2c_smbus_write_byte (fd, data) ; +} + + +/* + * wiringPiI2CWriteReg8: wiringPiI2CWriteReg16: + * Write an 8 or 16-bit value to the given register + ********************************************************************************* + */ + +int wiringPiI2CWriteReg8 (int fd, int reg, int data) +{ + return i2c_smbus_write_byte_data (fd, reg, data) ; +} + +int wiringPiI2CWriteReg16 (int fd, int reg, int data) +{ + return i2c_smbus_write_word_data (fd, reg, data) ; +} + + +/* + * wiringPiI2CSetup: + * Open the I2C device, and regsiter the target device + ********************************************************************************* + */ + +int wiringPiI2CSetup (int devId) +{ + int rev, fd ; + char *device ; + + if ((rev = piBoardRev ()) < 0) + { + fprintf (stderr, "wiringPiI2CSetup: Unable to determine Pi board revision\n") ; + exit (1) ; + } + + if (rev == 1) + device = "/dev/i2c-0" ; + else + device = "/dev/i2c-1" ; + + if ((fd = open (device, O_RDWR)) < 0) + return -1 ; + + if (ioctl (fd, I2C_SLAVE, devId) < 0) + return -1 ; + + return fd ; +} diff --git a/wiringPi/wiringPiI2C.h b/wiringPi/wiringPiI2C.h new file mode 100644 index 0000000..6710ff4 --- /dev/null +++ b/wiringPi/wiringPiI2C.h @@ -0,0 +1,41 @@ +/* + * wiringPiI2C.h: + * Simplified I2C access routines + * Copyright (c) 2013 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 . + *********************************************************************** + */ + +#ifdef __cplusplus +extern "C" { +#endif + +extern int wiringPiI2CRead (int fd) ; +extern int wiringPiI2CReadReg8 (int fd, int reg) ; +extern int wiringPiI2CReadReg16 (int fd, int reg) ; + +extern int wiringPiI2CWrite (int fd, int data) ; +extern int wiringPiI2CWriteReg8 (int fd, int reg, int data) ; +extern int wiringPiI2CWriteReg16 (int fd, int reg, int data) ; + +int wiringPiI2CSetup (int devId) ; + +#ifdef __cplusplus +} +#endif