diff --git a/People b/People new file mode 100644 index 0000000..2c5fa92 --- /dev/null +++ b/People @@ -0,0 +1,10 @@ + +Just a quick note to some people who've provided help, suggestions, +bug-fixes, etc. along the way... + +Nick Lott: (And others) + Hints about making it work with C++ + +Philipp Stefan Neininger: + Minor bug in the Makefile to do with cross compiling + diff --git a/examples/Makefile b/examples/Makefile index 450e0dc..16bf7e2 100644 --- a/examples/Makefile +++ b/examples/Makefile @@ -39,7 +39,12 @@ SRC = test1.c test2.c speed.c lcd.c wfi.c piface.c gertboard.c nes.c delayTest.c OBJ = test1.o test2.o speed.o lcd.o wfi.o piface.o gertboard.o nes.o delayTest.o softPwm.o -all: test1 test2 speed lcd wfi piface gertboard nes softPwm +BINS = test1 test2 speed lcd wfi piface gertboard nes delayTest softPwm + +all: + @cat README.TXT + @echo " $(BINS)" | fmt + @echo "" test1: test1.o @echo [link] @@ -77,7 +82,6 @@ softPwm: softPwm.o @echo [link] $(CC) -o $@ softPwm.o $(LDFLAGS) $(LIBS) -lm -lpthread - delayTest: delayTest.o @echo [link] $(CC) -o $@ delayTest.o $(LDFLAGS) $(LIBS) diff --git a/examples/README.TXT b/examples/README.TXT new file mode 100644 index 0000000..2bf6f1e --- /dev/null +++ b/examples/README.TXT @@ -0,0 +1,14 @@ + +wiringPi Examples +================= + +There are now too many examples to compile them all in a sensible time, +and you probably don't want to compile or run them all anyway, so they +have been separated out. + +To compile an individual example, just type + + make exampleName + +Where exampleName is one of: + diff --git a/gpio/Makefile b/gpio/Makefile index a92dd5f..5693c44 100644 --- a/gpio/Makefile +++ b/gpio/Makefile @@ -24,7 +24,7 @@ #DEBUG = -g -O0 -DEBUG = -O3 +DEBUG = -O2 CC = gcc INCLUDE = -I/usr/local/include CFLAGS = $(DEBUG) -Wall $(INCLUDE) -Winline -pipe @@ -32,42 +32,49 @@ CFLAGS = $(DEBUG) -Wall $(INCLUDE) -Winline -pipe LDFLAGS = -L/usr/local/lib LIBS = -lwiringPi -# Should not alter anything below this line +# May not need to alter anything below this line ############################################################################### SRC = gpio.c -OBJ = gpio.o +OBJ = $(SRC:.c=.o) all: gpio -gpio: gpio.o /usr/local/lib/libwiringPi.a - @echo [LD] +gpio: gpio.o + @echo [Link] @$(CC) -o $@ gpio.o $(LDFLAGS) $(LIBS) .c.o: - @echo [CC] $< + @echo [Compile] $< @$(CC) -c $(CFLAGS) $< -o $@ +.PHONEY: clean clean: - rm -f $(OBJ) gpio *~ core tags + rm -f $(OBJ) gpio *~ core tags *.bak +.PHONEY: tags tags: $(SRC) @echo [ctags] @ctags $(SRC) -depend: - makedepend -Y $(SRC) - +.PHONEY: install install: - cp gpio /usr/local/bin - chown root.root /usr/local/bin/gpio - chmod 4755 /usr/local/bin/gpio - mkdir -p /usr/local/man/man1 - cp gpio.1 /usr/local/man/man1 + @echo "[Install]" + @cp gpio /usr/local/bin + @chown root.root /usr/local/bin/gpio + @chmod 4755 /usr/local/bin/gpio + @mkdir -p /usr/local/man/man1 + @cp gpio.1 /usr/local/man/man1 +.PHONEY: uninstall uninstall: + @echo "[UnInstall]" rm -f /usr/local/bin/gpio rm -f /usr/local/man/man1/gpio.1 +.PHONEY: depend +depend: + makedepend -Y $(SRC) + # DO NOT DELETE diff --git a/gpio/gpio.1 b/gpio/gpio.1 index bc8e36e..be38791 100644 --- a/gpio/gpio.1 +++ b/gpio/gpio.1 @@ -1,4 +1,4 @@ -.TH "GPIO" "14 June 2012" "Command-Line access to Raspberry Pi and PiFace GPIO" +.TH "GPIO" "21st October 2012" "Command-Line access to Raspberry Pi and PiFace GPIO" .SH NAME gpio \- Command-line access to Raspberry Pi and PiFace GPIO @@ -17,6 +17,9 @@ gpio \- Command-line access to Raspberry Pi and PiFace GPIO .B ... .PP .B gpio +.B readall +.PP +.B gpio .B unexportall/exports .PP .B gpio @@ -48,9 +51,9 @@ channel value .SH DESCRIPTION .B GPIO -is a swiss army knofe of a command line tool to allow the user easy +is a swiss army knife of a command line tool to allow the user easy access to the GPIO pins on the Raspberry Pi and the SPI A/D and D/A -convertors on the Gertboard. It's designed for simple testing and +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. @@ -62,7 +65,7 @@ interface without needing to be run as root. .TP .B \-v -Output the current version +Output the current version including the board revision of the Raspberry Pi. .TP .B \-g @@ -73,20 +76,26 @@ Use the BCM_GPIO pins numbers rather than wiringPi pin numbers. Use the PiFace interface board and its corresponding pin numbers. .TP -.B read +.B read Read the digital value of the given pin and print 0 or 1 to represent the respective logic levels. .TP -.B write +.B write Write the given value (0 or 1) to the pin. .TP -.B pwm +.B readall +Output a table of all GPIO pins values. The values represent the actual values read +if the pin is in input mode, or the last value written if the pin is in output +mode. + +.TP +.B pwm Write a PWM value (0-1023) to the given pin. .TP -.B mode +.B mode Set a pin into \fIinput\fR, \fIoutput\fR or \fIpwm\fR mode. Can also use the literals \fIup\fR, \fIdown\fR or \fItri\fR to set the internal pull-up, pull-down or tristate (off) controls. @@ -122,7 +131,7 @@ the direction to input and set the edge interrupt method to \fInone\fR, above and note that \fBBCM_GPIO\fR pin number is used not not wiringPi pin numbering. -Like the export commands abovem ownership is set to that of the +Like the export commands above, ownership is set to that of the calling user, allowing subsequent access from user programs without requiring root/sudo. @@ -155,7 +164,7 @@ the associated /dev/ entries so that the current user has access to them. .B gbr channel -This reads the analog to digital convertor on the Gertboard on the given +This reads the analog to digital converter on the Gertboard on the given channel. The board jumpers need to be in-place to do this operation. .TP @@ -163,7 +172,7 @@ channel. The board jumpers need to be in-place to do this operation. channel value This writes the supplied value to the output channel on the Gertboards -SPI digital to analogue convertor. +SPI digital to analogue converter. The board jumpers need to be in-place to do this operation. @@ -171,26 +180,30 @@ The board jumpers need to be in-place to do this operation. .PP .TS -r r l. -WiringPi GPIO Function +r r r l. +WiringPi GPIO-r1 GPIO-r2 Function _ -0 17 -1 18 (PWM) -2 21 -3 22 -4 23 -5 24 -6 25 -7 4 -8 0 SDA0 -9 1 SCL0 -10 8 SPI CE0 -11 7 SPI CE1 -12 10 SPI MOSI -13 9 SPI MISO -14 11 SPI SCLK -15 14 TxD -16 15 RxD +0 17 17 +1 18 18 (PWM) +2 21 27 +3 22 22 +4 23 23 +5 24 24 +6 25 25 +7 4 4 +8 0 2 I2C: SDA0 +9 1 3 I2C: SCL0 +10 8 8 SPI: CE0 +11 7 7 SPI: CE1 +12 10 10 SPI: MOSI +13 9 9 SPI: MISO +14 11 11 SPI: SCLK +15 14 14 TxD +16 15 16 RxD +17 - 28 +18 - 29 +19 - 30 +20 - 31 .TE .SH FILES @@ -234,10 +247,14 @@ Gordon Henderson .SH "REPORTING BUGS" -Report bugs to +Please report bugs to .SH COPYRIGHT Copyright (c) 2012 Gordon Henderson This is free software; see the source for copying conditions. There is NO 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. diff --git a/gpio/gpio.c b/gpio/gpio.c index b696542..f019c1f 100644 --- a/gpio/gpio.c +++ b/gpio/gpio.c @@ -40,7 +40,7 @@ # define FALSE (1==2) #endif -#define VERSION "1.2" +#define VERSION "1.4" static int wpMode ; @@ -48,13 +48,16 @@ char *usage = "Usage: gpio -v\n" " gpio -h\n" " gpio [-g] ...\n" " gpio [-p] ...\n" - " gpio export/edge/unexport/unexportall/exports ...\n" + " gpio readall\n" + " gpio unexportall/exports ...\n" + " gpio export/edge/unexport ...\n" " gpio drive \n" " gpio pwm-bal/pwm-ms \n" " gpio pwmr \n" + " gpio pwmc \n" " gpio load spi/i2c\n" " gpio gbr \n" - " gpio gbw \n" ; + " gpio gbw " ; // No trailing newline needed here. /* @@ -171,6 +174,65 @@ static void doLoad (int argc, char *argv []) } +/* + * doReadall: + * Read all the GPIO pins + ********************************************************************************* + */ + +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", +} ; + +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") ; + + if (piBoardRev () == 1) + return ; + + for (pin = 17 ; pin <= 20 ; ++pin) + printf ("| %6d | %3d | %s | %s |\n", + pin, wpiPinToGpio (pin), + pinNames [pin], + digitalRead (pin) == HIGH ? "High" : "Low ") ; + + printf ("+----------+------+--------+-------+\n") ; +} + /* * doExports: @@ -687,8 +749,8 @@ void doPwm (int argc, char *argv []) /* - * doPwmMode: doPwmRange: - * Change the PWM mode and Range values + * doPwmMode: doPwmRange: doPwmClock: + * Change the PWM mode, range and clock divider values ********************************************************************************* */ @@ -718,6 +780,27 @@ static void doPwmRange (int argc, char *argv []) pwmSetRange (range) ; } +static void doPwmClock (int argc, char *argv []) +{ + unsigned int clock ; + + if (argc != 3) + { + fprintf (stderr, "Usage: %s pwmc \n", argv [0]) ; + exit (1) ; + } + + clock = (unsigned int)strtoul (argv [2], NULL, 10) ; + + if ((clock < 1) || (clock > 4095)) + { + fprintf (stderr, "%s: clock must be between 0 and 4096\n", argv [0]) ; + exit (1) ; + } + + pwmSetClock (clock) ; +} + /* * main: @@ -731,7 +814,7 @@ int main (int argc, char *argv []) if (argc == 1) { - fprintf (stderr, "%s: %s\n", argv [0], usage) ; + fprintf (stderr, "%s\n", usage) ; return 1 ; } @@ -747,6 +830,8 @@ int main (int argc, char *argv []) printf ("Copyright (c) 2012 Gordon Henderson\n") ; printf ("This is free software with ABSOLUTELY NO WARRANTY.\n") ; printf ("For details type: %s -warranty\n", argv [0]) ; + printf ("\n") ; + printf ("This Raspberry Pi is a revision %d board.\n", piBoardRev ()) ; return 0 ; } @@ -785,9 +870,8 @@ int main (int argc, char *argv []) else if (strcasecmp (argv [1], "unexportall") == 0) { doUnexportall (argc, argv) ; return 0 ; } else if (strcasecmp (argv [1], "unexport" ) == 0) { doUnexport (argc, argv) ; return 0 ; } -// Check for drive or load commands: +// Check for load command: - if (strcasecmp (argv [1], "drive") == 0) { doPadDrive (argc, argv) ; return 0 ; } if (strcasecmp (argv [1], "load" ) == 0) { doLoad (argc, argv) ; return 0 ; } // Gertboard commands @@ -839,21 +923,24 @@ int main (int argc, char *argv []) wpMode = WPI_MODE_PINS ; } -// Check for PWM operations +// Check for PWM or Pad Drive operations if (wpMode != WPI_MODE_PIFACE) { - if (strcasecmp (argv [1], "pwm-bal") == 0) { doPwmMode (PWM_MODE_BAL) ; return 0 ; } - if (strcasecmp (argv [1], "pwm-ms") == 0) { doPwmMode (PWM_MODE_MS) ; return 0 ; } - if (strcasecmp (argv [1], "pwmr") == 0) { doPwmRange (argc, argv) ; return 0 ; } + if (strcasecmp (argv [1], "pwm-bal") == 0) { doPwmMode (PWM_MODE_BAL) ; return 0 ; } + if (strcasecmp (argv [1], "pwm-ms") == 0) { doPwmMode (PWM_MODE_MS) ; return 0 ; } + if (strcasecmp (argv [1], "pwmr") == 0) { doPwmRange (argc, argv) ; return 0 ; } + if (strcasecmp (argv [1], "pwmc") == 0) { doPwmClock (argc, argv) ; return 0 ; } + if (strcasecmp (argv [1], "drive") == 0) { doPadDrive (argc, argv) ; return 0 ; } } // Check for wiring commands - /**/ if (strcasecmp (argv [1], "read" ) == 0) doRead (argc, argv) ; - else if (strcasecmp (argv [1], "write") == 0) doWrite (argc, argv) ; - else if (strcasecmp (argv [1], "pwm" ) == 0) doPwm (argc, argv) ; - else if (strcasecmp (argv [1], "mode" ) == 0) doMode (argc, argv) ; + /**/ if (strcasecmp (argv [1], "readall" ) == 0) doReadall () ; + else if (strcasecmp (argv [1], "read" ) == 0) doRead (argc, argv) ; + else if (strcasecmp (argv [1], "write") == 0) doWrite (argc, argv) ; + else if (strcasecmp (argv [1], "pwm" ) == 0) doPwm (argc, argv) ; + else if (strcasecmp (argv [1], "mode" ) == 0) doMode (argc, argv) ; else { fprintf (stderr, "%s: Unknown command: %s.\n", argv [0], argv [1]) ; diff --git a/gpio/test.sh b/gpio/test.sh index 7127528..a7c2bb2 100755 --- a/gpio/test.sh +++ b/gpio/test.sh @@ -1,4 +1,25 @@ #!/bin/bash +# +# test.sh: +# Simple test: Assumes LEDs on Pins 0-7 and lights them +# in-turn. +################################################################################# +# This file is part of wiringPi: +# Wiring Compatable library for the Raspberry Pi +# +# 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 . +################################################################################# # Simple test - assumes LEDs on Pins 0-7. diff --git a/wiringPi/Makefile b/wiringPi/Makefile index 3c23e96..c0a39f9 100644 --- a/wiringPi/Makefile +++ b/wiringPi/Makefile @@ -21,64 +21,93 @@ # along with wiringPi. If not, see . ################################################################################# +DYN_VERS_MAJ=1 +DYN_VERS_MIN=0 -TARGET=libwiringPi.a +STATIC=libwiringPi.a +DYNAMIC=libwiringPi.so.$(DYN_VERS_MAJ).$(DYN_VERS_MIN) #DEBUG = -g -O0 -DEBUG = -O3 +DEBUG = -O2 CC = gcc INCLUDE = -I. -CFLAGS = $(DEBUG) -Wall $(INCLUDE) -Winline -pipe +CFLAGS = $(DEBUG) -Wall $(INCLUDE) -Winline -pipe -fPIC LIBS = # Should not alter anything below this line ############################################################################### -SRC = wiringPi.c wiringPiFace.c wiringSerial.c wiringShift.c lcd.c piHiPri.c piThread.c +SRC = wiringPi.c wiringPiFace.c wiringSerial.c wiringShift.c \ + gertboard.c \ + piNes.c \ + lcd.c piHiPri.c piThread.c softPwm.c wiringPiSPI.c -OBJ = wiringPi.o wiringPiFace.o wiringSerial.o wiringShift.o lcd.o piHiPri.o piThread.o +OBJ = $(SRC:.c=.o) -all: $(TARGET) +#all: $(STATIC) $(DYNAMIC) +all: $(DYNAMIC) -$(TARGET): $(OBJ) - @echo [AR] $(OBJ) - @ar rcs $(TARGET) $(OBJ) - @ranlib $(TARGET) - @size $(TARGET) +$(STATIC): $(OBJ) + @echo [Link (Static)] + @ar rcs $(STATIC) $(OBJ) + @ranlib $(STATIC) + @size $(STATIC) + +$(DYNAMIC): $(OBJ) + @echo [Link] + @$(CC) -shared -Wl,-soname,libwiringPi.so.1 -o libwiringPi.so.1.0 -lpthread $(OBJ) .c.o: - @echo [CC] $< + @echo [Compile] $< @$(CC) -c $(CFLAGS) $< -o $@ +.PHONEY: clean clean: - rm -f $(OBJ) $(TARGET) *~ core tags Makefile.bak + rm -f $(OBJ) *~ core tags Makefile.bak libwiringPi.* +.PHONEY: tags tags: $(SRC) @echo [ctags] @ctags $(SRC) -depend: - makedepend -Y $(SRC) - +.PHONEY: install install: $(TARGET) - @echo [install] - install -m 0755 -d /usr/local/lib - install -m 0755 -d /usr/local/include - install -m 0644 wiringPi.h /usr/local/include - install -m 0644 wiringSerial.h /usr/local/include - install -m 0644 wiringShift.h /usr/local/include - install -m 0644 lcd.h /usr/local/include - install -m 0644 libwiringPi.a /usr/local/lib - + @echo "[Install]" + @install -m 0755 -d /usr/local/lib + @install -m 0755 -d /usr/local/include + @install -m 0644 wiringPi.h /usr/local/include + @install -m 0644 wiringSerial.h /usr/local/include + @install -m 0644 wiringShift.h /usr/local/include + @install -m 0644 gertboard.h /usr/local/include + @install -m 0644 piNes.h /usr/local/include + @install -m 0644 softPwm.h /usr/local/include + @install -m 0644 lcd.h /usr/local/include + @install -m 0644 wiringPiSPI.h /usr/local/include +# @install -m 0644 libwiringPi.a /usr/local/lib + @install -m 0755 libwiringPi.so.1.0 /usr/local/lib + @ln -sf /usr/local/lib/libwiringPi.so.1.0 /usr/local/lib/libwiringPi.so + @ln -sf /usr/local/lib/libwiringPi.so.1.0 /usr/local/lib/libwiringPi.so.1 + @ldconfig + +.PHONEY: uninstall uninstall: - @echo [uninstall] - rm -f /usr/local/include/lcd.h - rm -f /usr/local/include/wiringShift.h - rm -f /usr/local/include/wiringPi.h - rm -f /usr/local/lib/libwiringPi.a - - + @echo "[UnInstall]" + @rm -f /usr/local/include/wiringPi.h + @rm -f /usr/local/include/wiringSerial.h + @rm -f /usr/local/include/wiringShift.h + @rm -f /usr/local/include/gertboard.h + @rm -f /usr/local/include/piNes.h + @rm -f /usr/local/include/softPwm.h + @rm -f /usr/local/include/lcd.h + @rm -f /usr/local/include/wiringPiSPI.h + @rm -f /usr/local/lib/libwiringPi.* + @ldconfig + + +.PHONEY: depend +depend: + makedepend -Y $(SRC) # DO NOT DELETE @@ -86,6 +115,10 @@ wiringPi.o: wiringPi.h wiringPiFace.o: wiringPi.h wiringSerial.o: wiringSerial.h wiringShift.o: wiringPi.h wiringShift.h +gertboard.o: wiringPiSPI.h gertboard.h +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 diff --git a/wiringPi/README b/wiringPi/README index 781510a..c79754e 100644 --- a/wiringPi/README +++ b/wiringPi/README @@ -1,6 +1,8 @@ WiringPi: An implementation of most of the Arduino Wiring - functions for the Raspberry Pi + functions for the Raspberry Pi, + along with many more features and libraries to support + hardware, etc. on the Raspberry Pi Full details at: https://projects.drogon.net/raspberry-pi/wiringpi/ diff --git a/wiringPi/lcd.c b/wiringPi/lcd.c index 6826a60..aa58cab 100644 --- a/wiringPi/lcd.c +++ b/wiringPi/lcd.c @@ -75,7 +75,10 @@ struct lcdDataStruct *lcds [MAX_LCDS] ; static void strobe (struct lcdDataStruct *lcd) { - digitalWrite (lcd->strbPin, 1) ; delayMicroseconds (1) ; + +// Note timing changes for new version of delayMicroseconds () + + digitalWrite (lcd->strbPin, 1) ; delayMicroseconds (50) ; digitalWrite (lcd->strbPin, 0) ; delayMicroseconds (50) ; } diff --git a/wiringPi/lcd.h b/wiringPi/lcd.h index d4c724c..ecd1d25 100644 --- a/wiringPi/lcd.h +++ b/wiringPi/lcd.h @@ -26,6 +26,10 @@ #define MAX_LCDS 8 +#ifdef __cplusplus +extern "C" { +#endif + extern void lcdHome (int fd) ; extern void lcdClear (int fd) ; extern void lcdPosition (int fd, int x, int y) ; @@ -33,10 +37,6 @@ extern void lcdPutchar (int fd, uint8_t data) ; extern void lcdPuts (int fd, char *string) ; extern void lcdPrintf (int fd, char *message, ...) ; -#ifdef __cplusplus -extern "C" { -#endif - 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/wiringPi.c b/wiringPi/wiringPi.c index 39c34da..9fe3ab1 100644 --- a/wiringPi/wiringPi.c +++ b/wiringPi/wiringPi.c @@ -2,6 +2,7 @@ * wiringPi: * Arduino compatable (ish) Wiring library for the Raspberry Pi * Copyright (c) 2012 Gordon Henderson + * Additional code for pwmSetClock by Chris Hall * * Thanks to code samples from Gert Jan van Loo and the * BCM2835 ARM Peripherals manual, however it's missing @@ -56,6 +57,8 @@ #include #include +#include +#include #include #include #include @@ -81,6 +84,7 @@ int (*waitForInterrupt) (int pin, int mS) ; void (*delayMicroseconds) (unsigned int howLong) ; void (*pwmSetMode) (int mode) ; void (*pwmSetRange) (unsigned int range) ; +void (*pwmSetClock) (int divisor) ; #ifndef TRUE @@ -166,9 +170,12 @@ static volatile uint32_t *pwm ; static volatile uint32_t *clk ; static volatile uint32_t *pads ; static volatile uint32_t *timer ; - static volatile uint32_t *timerIrqRaw ; +// Debugging + +static int wiringPiDebug = FALSE ; + // The BCM2835 has 54 GPIO pins. // BCM2835 data sheet, Page 90 onwards. // There are 6 control registers, each control the functions of a block @@ -198,8 +205,11 @@ static int sysFds [64] ; // pinToGpio: // Take a Wiring pin (0 through X) and re-map it to the BCM_GPIO pin +// Cope for 2 different board revieions here + +static int *pinToGpio ; -static int pinToGpio [64] = +static int pinToGpioR1 [64] = { 17, 18, 21, 22, 23, 24, 25, 4, // From the Original Wiki - GPIO 0 through 7 0, 1, // I2C - SDA0, SCL0 @@ -209,11 +219,28 @@ static int pinToGpio [64] = // Padding: - -1, -1, -1,-1,-1,-1,-1, -1, -1, -1, -1, -1, -1, -1, -1, // ... 31 + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // ... 31 + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // ... 47 + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // ... 63 +} ; + +static int pinToGpioR2 [64] = +{ + 17, 18, 27, 22, 23, 24, 25, 4, // From the Original Wiki - GPIO 0 through 7: wpi 0 - 7 + 2, 3, // I2C - SDA0, SCL0 wpi 8 - 9 + 8, 7, // SPI - CE1, CE0 wpi 10 - 11 + 10, 9, 11, // SPI - MOSI, MISO, SCLK wpi 12 - 14 + 14, 15, // UART - Tx, Rx wpi 15 - 16 + 28, 29, 30, 31, // New GPIOs 8 though 11 wpi 17 - 20 + +// Padding: + + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // ... 31 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // ... 47 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // ... 63 } ; + // gpioToGPFSEL: // Map a BCM_GPIO pin to it's control port. (GPFSEL 0-5) @@ -227,6 +254,7 @@ static uint8_t gpioToGPFSEL [] = 5,5,5,5,5,5,5,5,5,5, } ; + // gpioToShift // Define the shift up for the 3 bits per pin in each GPFSEL port @@ -239,6 +267,7 @@ static uint8_t gpioToShift [] = 0,3,6,9,12,15,18,21,24,27, } ; + // gpioToGPSET: // (Word) offset to the GPIO Set registers for each GPIO pin @@ -248,6 +277,7 @@ static uint8_t gpioToGPSET [] = 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, } ; + // gpioToGPCLR: // (Word) offset to the GPIO Clear registers for each GPIO pin @@ -257,6 +287,7 @@ static uint8_t gpioToGPCLR [] = 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, } ; + // gpioToGPLEV: // (Word) offset to the GPIO Input level registers for each GPIO pin @@ -266,6 +297,7 @@ static uint8_t gpioToGPLEV [] = 14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14, } ; + #ifdef notYetReady // gpioToEDS // (Word) offset to the Event Detect Status @@ -295,6 +327,7 @@ static uint8_t gpioToFEN [] = } ; #endif + // gpioToPUDCLK // (Word) offset to the Pull Up Down Clock regsiter @@ -306,6 +339,7 @@ static uint8_t gpioToPUDCLK [] = 39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39, } ; + // gpioToPwmALT // the ALT value to put a GPIO pin into PWM mode @@ -339,7 +373,122 @@ static uint8_t gpioToPwmPort [] = static unsigned long long epoch ; -////////////////////////////////////////////////////////////////////////////////// +/* + * Functions + ********************************************************************************* + */ + + +/* + * wpiPinToGpio: + * Translate a wiringPi Pin number to native GPIO pin number. + * (We don't use this here, prefering to just do the lookup directly, + * but it's been requested!) + ********************************************************************************* + */ + +int wpiPinToGpio (int wpiPin) +{ + return pinToGpio [wpiPin & 63] ; +} + + +/* + * piBoardRev: + * Return a number representing the hardware revision of the board. + * Revision is currently 1 or 2. -1 is returned on error. + * + * Much confusion here )-: + * Seems there ar esome boards with 0000 in them (mistake in manufacture) + * and some board with 0005 in them (another mistake in manufacture). + * So the distinction between boards that I can see is: + * 0000 - Error + * 0001 - Not used + * 0002 - Rev 1 + * 0003 - Rev 1 + * 0004 - Rev 2 + * 0005 - Rev 2 + * 0006 - Rev 2 + * 000f - Rev 2 + 512MB + * + * A small thorn is the olde style overvolting - that will add in + * 1000000 + * + ********************************************************************************* + */ + +int piBoardRev (void) +{ + FILE *cpuFd ; + char line [120] ; + char *c, lastChar ; + static int boardRev = -1 ; + +// No point checking twice... + + if (boardRev != -1) + return boardRev ; + + if ((cpuFd = fopen ("/proc/cpuinfo", "r")) == NULL) + return -1 ; + + while (fgets (line, 120, cpuFd) != NULL) + if (strncmp (line, "Revision", 8) == 0) + break ; + + 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 ; + } + + 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 ; + } + +// If you have overvolted the Pi, then it appears that the revision +// has 100000 added to it! + + if (wiringPiDebug) + if (strlen (c) != 4) + printf ("piboardRev: This Pi has/is overvolted!\n") ; + + lastChar = c [strlen (c) - 2] ; + + /**/ 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) ; + + return boardRev ; +} + /* @@ -350,7 +499,6 @@ static unsigned long long epoch ; void pinModeGpio (int pin, int mode) { - static int pwmRunning = FALSE ; int fSel, shift, alt ; pin &= 63 ; @@ -371,38 +519,28 @@ void pinModeGpio (int pin, int mode) *(gpio + fSel) = (*(gpio + fSel) & ~(7 << shift)) | (alt << shift) ; -// We didn't initialise the PWM hardware at setup time - because it's possible that -// something else is using the PWM - e.g. the Audio systems! So if we use PWM -// here, then we're assuming that nothing else is, otherwise things are going -// to sound a bit funny... - - if (!pwmRunning) - { - - *(pwm + PWM_CONTROL) = 0 ; // Stop PWM - delayMicroseconds (10) ; - -// Gert/Doms Values - *(clk + PWMCLK_DIV) = BCM_PASSWORD | (32<<12) ; // set pwm div to 32 (19.2/32 = 600KHz) - *(clk + PWMCLK_CNTL) = BCM_PASSWORD | 0x11 ; // Source=osc and enable - - delayMicroseconds (10) ; +// 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 + PWM0_RANGE) = 0x400 ; delayMicroseconds (10) ; - *(pwm + PWM1_RANGE) = 0x400 ; delayMicroseconds (10) ; + *(pwm + PWM_CONTROL) = 0 ; // Stop PWM + *(clk + PWMCLK_CNTL) = BCM_PASSWORD | 0x01 ; // Stop PWM Clock + delayMicroseconds (110) ; // See comments in pwmSetClockWPi -// Enable PWMs + (void)*(pwm + PWM_CONTROL) ; + while ((*(pwm + PWM_CONTROL) & 0x80) != 0) // Wait for clock to be !BUSY + delayMicroseconds (1) ; - *(pwm + PWM0_DATA) = 512 ; - *(pwm + PWM1_DATA) = 512 ; + *(clk + PWMCLK_DIV) = BCM_PASSWORD | (32 << 12) ; // set pwm div to 32 (19.2/32 = 600KHz) + *(clk + PWMCLK_CNTL) = BCM_PASSWORD | 0x11 ; // enable clk -// Balanced mode (default) +// Default range regsiter of 1024 - *(pwm + PWM_CONTROL) = PWM0_ENABLE | PWM1_ENABLE ; + *(pwm + PWM0_DATA) = 0 ; *(pwm + PWM0_RANGE) = 1024 ; + *(pwm + PWM1_DATA) = 0 ; *(pwm + PWM1_RANGE) = 1024 ; - pwmRunning = TRUE ; - } +// Enable PWMs in balanced mode (default) + *(pwm + PWM_CONTROL) = PWM0_ENABLE | PWM1_ENABLE ; } // When we change mode of any pin, we remove the pull up/downs @@ -459,6 +597,55 @@ void pwmSetRangeSys (unsigned int range) return ; } +/* + * pwmSetClockWPi: + * Set/Change the PWM clock. Originally my code, but changed + * (for the better!) by Chris Hall, + * after further study of the manual and testing with a 'scope + ********************************************************************************* + */ + +void pwmSetClockWPi (int divisor) +{ + unsigned int pwm_control ; + divisor &= 4095 ; + + if (wiringPiDebug) + printf ("Setting to: %d. Current: 0x%08X\n", divisor, *(clk + PWMCLK_DIV)) ; + + pwm_control = *(pwm + PWM_CONTROL) ; // preserve PWM_CONTROL + +// We need to stop PWM prior to stopping PWM clock in MS mode otherwise BUSY +// stays high. + + *(pwm + PWM_CONTROL) = 0 ; // Stop PWM + +// Stop PWM clock before changing divisor. The delay after this does need to +// this big (95uS occasionally fails, 100uS OK), it's almost as though the BUSY +// flag is not working properly in balanced mode. Without the delay when DIV is +// adjusted the clock sometimes switches to very slow, once slow further DIV +// adjustments do nothing and it's difficult to get out of this mode. + + *(clk + PWMCLK_CNTL) = BCM_PASSWORD | 0x01 ; // Stop PWM Clock + delayMicroseconds (110) ; // prevents clock going sloooow + + while ((*(pwm + PWM_CONTROL) & 0x80) != 0) // Wait for clock to be !BUSY + delayMicroseconds (1) ; + + *(clk + PWMCLK_DIV) = BCM_PASSWORD | (divisor << 12) ; + + *(clk + PWMCLK_CNTL) = BCM_PASSWORD | 0x11 ; // Start PWM clock + *(pwm + PWM_CONTROL) = pwm_control ; // restore PWM_CONTROL + + if (wiringPiDebug) + printf ("Set to: %d. Now : 0x%08X\n", divisor, *(clk + PWMCLK_DIV)) ; +} + +void pwmSetClockSys (int divisor) +{ + return ; +} + #ifdef notYetReady /* @@ -518,7 +705,7 @@ void digitalWriteSys (int pin, int value) /* - * pwnWrite: + * pwmWrite: * Set an output PWM value ********************************************************************************* */ @@ -699,8 +886,6 @@ int waitForInterruptGpio (int pin, int mS) } - - /* * delay: * Wait for some number of milli seconds @@ -800,9 +985,16 @@ unsigned int millis (void) int wiringPiSetup (void) { int fd ; + int boardRev ; uint8_t *gpioMem, *pwmMem, *clkMem, *padsMem, *timerMem ; struct timeval tv ; + if (getenv ("WIRINGPI_DEBUG") != NULL) + wiringPiDebug = TRUE ; + + if (wiringPiDebug) + printf ("wiringPi: wiringPiSetup called\n") ; + pinMode = pinModeWPi ; pullUpDnControl = pullUpDnControlWPi ; digitalWrite = digitalWriteWPi ; @@ -813,7 +1005,16 @@ int wiringPiSetup (void) delayMicroseconds = delayMicrosecondsWPi ; pwmSetMode = pwmSetModeWPi ; pwmSetRange = pwmSetRangeWPi ; + pwmSetClock = pwmSetClockWPi ; + if ((boardRev = piBoardRev ()) < 0) + return -1 ; + + if (boardRev == 1) + pinToGpio = pinToGpioR1 ; + else + pinToGpio = pinToGpioR2 ; + // Open the master /dev/memory device if ((fd = open ("/dev/mem", O_RDWR | O_SYNC) ) < 0) @@ -954,9 +1155,12 @@ int wiringPiSetup (void) int wiringPiSetupGpio (void) { - int x = wiringPiSetup () ; + int x ; + + if (wiringPiDebug) + printf ("wiringPi: wiringPiSetupGpio called\n") ; - if (x != 0) + if ((x = wiringPiSetup ()) < 0) return x ; pinMode = pinModeGpio ; @@ -969,6 +1173,7 @@ int wiringPiSetupGpio (void) delayMicroseconds = delayMicrosecondsWPi ; // Same pwmSetMode = pwmSetModeWPi ; pwmSetRange = pwmSetRangeWPi ; + pwmSetClock = pwmSetClockWPi ; return 0 ; } @@ -989,6 +1194,9 @@ int wiringPiSetupSys (void) struct timeval tv ; char fName [128] ; + if (wiringPiDebug) + printf ("wiringPi: wiringPiSetupSys called\n") ; + pinMode = pinModeSys ; pullUpDnControl = pullUpDnControlSys ; digitalWrite = digitalWriteSys ; @@ -999,6 +1207,7 @@ int wiringPiSetupSys (void) delayMicroseconds = delayMicrosecondsSys ; pwmSetMode = pwmSetModeSys ; pwmSetRange = pwmSetRangeSys ; + pwmSetClock = pwmSetClockSys ; // Open and scan the directory, looking for exported GPIOs, and pre-open diff --git a/wiringPi/wiringPi.h b/wiringPi/wiringPi.h index 1d21fa0..cab3080 100644 --- a/wiringPi/wiringPi.h +++ b/wiringPi/wiringPi.h @@ -62,6 +62,9 @@ extern int wiringPiSetupSys (void) ; extern int wiringPiSetupGpio (void) ; extern int wiringPiSetupPiFace (void) ; +extern int piBoardRev (void) ; +extern int wpiPinToGpio (int wpiPin) ; + extern int wiringPiSetupPiFaceForGpioProg (void) ; // Don't use this - for gpio program only extern void (*pinMode) (int pin, int mode) ; @@ -73,6 +76,7 @@ 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) ; // Interrupts