From 05e2f67e7f43d83195fff108bcd952e7afe917ce Mon Sep 17 00:00:00 2001 From: Gordon Henderson Date: Tue, 20 May 2014 11:43:07 +0100 Subject: [PATCH] changed to pin mode to support softPwm. bugfix in blink.sh - wring pin improving the maxdetect routing - a little. gpio pins --- examples/blink.sh | 2 +- examples/blink6drcs.c | 115 ++++++++++++++++++++++++++++++++++++++++++ examples/rht03.c | 5 ++ gpio/Makefile | 12 ++--- gpio/gpio.1 | 27 +++++++++- gpio/gpio.c | 9 +++- gpio/pins.c | 70 +++++++++++++++++++++++++ wiringPi/softPwm.c | 49 +++++++++++++++--- wiringPi/softPwm.h | 1 + wiringPi/wiringPi.c | 11 +++- wiringPi/wiringPi.h | 1 + 11 files changed, 281 insertions(+), 21 deletions(-) create mode 100644 examples/blink6drcs.c create mode 100644 gpio/pins.c diff --git a/examples/blink.sh b/examples/blink.sh index 2aa378a..7755383 100644 --- a/examples/blink.sh +++ b/examples/blink.sh @@ -25,7 +25,7 @@ # LED Pin - wiringPi pin 0 is BCM_GPIO 17. -LED=0 +PIN=0 gpio mode $PIN out diff --git a/examples/blink6drcs.c b/examples/blink6drcs.c new file mode 100644 index 0000000..32f4921 --- /dev/null +++ b/examples/blink6drcs.c @@ -0,0 +1,115 @@ +/* + * blink6drcs.c: + * Simple sequence over 6 pins on a remote DRC board. + * Aimed at the Gertduino, but it's fairly generic. + * This version uses DRC to talk to the ATmega on the Gertduino + * + * Copyright (c) 2012-2014 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 + +#define GERT_BASE 100 + +static int pinMap [] = +{ + GERT_BASE + 6, GERT_BASE + 5, GERT_BASE + 3, GERT_BASE + 10, GERT_BASE + 9, GERT_BASE + 13, +} ; + +// Simple sequencer data +// Triplets of LED, On/Off and delay + + +int data [] = +{ + 0, 1, 1, + 1, 1, 1, + 0, 0, 0, 2, 1, 1, + 1, 0, 0, 3, 1, 1, + 2, 0, 0, 4, 1, 1, + 3, 0, 0, 5, 1, 1, + 4, 0, 1, + 5, 0, 1, + + 0, 0, 1, // Extra delay + +// Back again + + 5, 1, 1, + 4, 1, 1, + 5, 0, 0, 3, 1, 1, + 4, 0, 0, 2, 1, 1, + 3, 0, 0, 1, 1, 1, + 2, 0, 0, 0, 1, 1, + 1, 0, 1, + 0, 0, 1, + + 0, 0, 1, // Extra delay + + 0, 9, 0, // End marker + +} ; + + +int main (void) +{ + int pin ; + int dataPtr ; + int l, s, d ; + + printf ("Raspberry Pi - 6-LED Sequence\n") ; + printf ("=============================\n") ; + printf ("\n") ; + printf (" Use the 2 buttons to temporarily speed up the sequence\n") ; + + wiringPiSetupSys () ; // Not using the Pi's GPIO here + drcSetupSerial (GERT_BASE, 20, "/dev/ttyAMA0", 115200) ; + + for (pin = 0 ; pin < 6 ; ++pin) + pinMode (pinMap [pin], OUTPUT) ; + + pinMode (GERT_BASE + 16, INPUT) ; // Buttons + pinMode (GERT_BASE + 17, INPUT) ; + + pullUpDnControl (GERT_BASE + 16, PUD_UP) ; + pullUpDnControl (GERT_BASE + 17, PUD_UP) ; + + dataPtr = 0 ; + + for (;;) + { + l = data [dataPtr++] ; // LED + s = data [dataPtr++] ; // State + d = data [dataPtr++] ; // Duration (10ths) + + if (s == 9) // 9 -> End Marker + { + dataPtr = 0 ; + continue ; + } + + digitalWrite (pinMap [l], s) ; + delay (d * digitalRead (GERT_BASE + 16) * 15 + digitalRead (GERT_BASE + 17) * 20) ; + } + + return 0 ; +} diff --git a/examples/rht03.c b/examples/rht03.c index e0cc116..566e954 100644 --- a/examples/rht03.c +++ b/examples/rht03.c @@ -56,6 +56,11 @@ int main (void) { temp = newTemp ; rh = newRh ; + if ((temp & 0x8000) != 0) // Negative + { + temp &= 0x7FFF ; + temp = -temp ; + } printf ("Temp: %5.1f, RH: %5.1f%%\n", temp / 10.0, rh / 10.0) ; } } diff --git a/gpio/Makefile b/gpio/Makefile index 8fa12d5..37b4887 100644 --- a/gpio/Makefile +++ b/gpio/Makefile @@ -38,7 +38,7 @@ LIBS = -lwiringPi -lwiringPiDev -lpthread -lm # May not need to alter anything below this line ############################################################################### -SRC = gpio.c extensions.c readall.c +SRC = gpio.c extensions.c readall.c pins.c OBJ = $(SRC:.c=.o) @@ -52,17 +52,17 @@ gpio: $(OBJ) @echo [Compile] $< @$(CC) -c $(CFLAGS) $< -o $@ -.PHONEY: clean +.PHONY: clean clean: @echo "[Clean]" @rm -f $(OBJ) gpio *~ core tags *.bak -.PHONEY: tags +.PHONY: tags tags: $(SRC) @echo [ctags] @ctags $(SRC) -.PHONEY: install +.PHONY: install install: @echo "[Install]" @cp gpio $(DESTDIR)$(PREFIX)/bin @@ -71,13 +71,13 @@ install: @mkdir -p $(DESTDIR)$(PREFIX)/man/man1 @cp gpio.1 $(DESTDIR)$(PREFIX)/man/man1 -.PHONEY: uninstall +.PHONY: uninstall uninstall: @echo "[UnInstall]" @rm -f $(DESTDIR)$(PREFIX)/bin/gpio @rm -f $(DESTDIR)$(PREFIX)/man/man1/gpio.1 -.PHONEY: depend +.PHONY: depend depend: makedepend -Y $(SRC) diff --git a/gpio/gpio.1 b/gpio/gpio.1 index e1cba32..7300466 100644 --- a/gpio/gpio.1 +++ b/gpio/gpio.1 @@ -114,6 +114,28 @@ respective logic levels. Write the given value (0 or 1) to the pin. You need to set the pin to output mode first. +.TP +.B aread +Read the analog value of the given pin. This needs to be uses in +conjunction with a -x flag to add in an extension that handles analog +inputs. respective logic levels. + +e.g. gpio -x mcp3002:200:0 aread 200 + +will read the first analog input on an mcp3002 SPI ADC chip. + +.TP +.B awrite +Write the analog value to the given pin. This needs to be used in +conjunction with a -x flag to add in an extension that handles analog +inputs. respective logic levels. + +e.g. gpio -x mcp4802:200:0 awrite 200 128 + +will write the value 128 to the first DAC port on an mcp4802 chip on +the Pi's SPI bus 0. + + .TP .B wb Write the given byte to the 8 main GPIO pins. You can prefix it with 0x @@ -132,8 +154,9 @@ digital and analog read on each pin in-turn. .TP .B reset -Resets the GPIO - As much as it's possible to do. All pins are set to input -mode and all the internal pull-up/down resistors are disconnected (tristate mode). +Resets the GPIO - As much as it's possible to do. All pins are set to +input mode and all the internal pull-up/down resistors are disconnected +(tristate mode). The reset command is usable with an extension module (via the -x parameter), but it's limited to turning the pin into input mode (if applicable) and diff --git a/gpio/gpio.c b/gpio/gpio.c index b65af0e..d941db5 100644 --- a/gpio/gpio.c +++ b/gpio/gpio.c @@ -43,15 +43,19 @@ extern int wiringPiDebug ; +// External functions I can't be bothered creating a separate .h file for: + extern void doReadall (void) ; extern void doReadallOld (void) ; +extern void doPins (void) ; + #ifndef TRUE # define TRUE (1==1) # define FALSE (1==2) #endif -#define VERSION "2.13" +#define VERSION "2.14" #define I2CDETECT "/usr/sbin/i2cdetect" int wpMode ; @@ -1078,7 +1082,7 @@ int main (int argc, char *argv []) if (strcmp (argv [1], "-v") == 0) { printf ("gpio version: %s\n", VERSION) ; - printf ("Copyright (c) 2012-2013 Gordon Henderson\n") ; + printf ("Copyright (c) 2012-2014 Gordon Henderson\n") ; printf ("This is free software with ABSOLUTELY NO WARRANTY.\n") ; printf ("For details type: %s -warranty\n", argv [0]) ; printf ("\n") ; @@ -1220,6 +1224,7 @@ int main (int argc, char *argv []) else if (strcasecmp (argv [1], "drive" ) == 0) doPadDrive (argc, argv) ; else if (strcasecmp (argv [1], "readall" ) == 0) doReadallOld () ; else if (strcasecmp (argv [1], "nreadall" ) == 0) doReadall () ; + else if (strcasecmp (argv [1], "pins" ) == 0) doPins () ; else if (strcasecmp (argv [1], "i2cdetect") == 0) doI2Cdetect (argc, argv) ; else if (strcasecmp (argv [1], "i2cd" ) == 0) doI2Cdetect (argc, argv) ; else if (strcasecmp (argv [1], "reset" ) == 0) doReset (argv [0]) ; diff --git a/gpio/pins.c b/gpio/pins.c new file mode 100644 index 0000000..6df3cb2 --- /dev/null +++ b/gpio/pins.c @@ -0,0 +1,70 @@ +/* + * pins.c: + * Just display a handy Pi pinnout diagram. + * 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 +#include +#include +#include +#include +#include + +#include + +extern int wpMode ; + +void doPins (void) +{ + printf ("This Raspberry Pi is a revision %d board.\n", piBoardRev ()) ; + + printf ( +" +-----+--------+------------+--------+-----+\n" +" | Pin | Name || P1 Pin || Name | Pin |\n" +" +-----+--------+------------+--------+-----+\n" +" | | 3.3v || 1 oo 2 || 5v | |\n" +" | 8 | SDA || 3 oo 4 || 5v | |\n" +" | 9 | SCL || 5 oo 6 || Gnd | |\n" +" | 7 | GPIO 7 || 7 oo 8 || TxD | 15 |\n" +" | | GND || 9 oo 10 || RxD | 16 |\n" +" | 0 | GPIO 0 || 11 oo 12 || GPIO 1 | 1 |\n" +" | 2 | GPIO 2 || 13 oo 14 || Gnd | |\n" +" | 3 | GPIO 3 || 15 oo 16 || GPIO 4 | 4 |\n" +" | | 3.3v || 17 oo 18 || GPIO 5 | 5 |\n" +" | 12 | MOSI || 19 oo 20 || Gnd | |\n" +" | 13 | MISO || 21 oo 22 || GPIO 6 | 6 |\n" +" | 14 | SCLK || 23 oo 24 || CE 0 | 10 |\n" +" | | Gnd || 25 oo 26 || CE 1 | 11 |\n" +" +-----+--------+------------+--------+-----+\n") ; + +/*** + +--- + | 5v| 5v| Gnd | TxD | RxD | G1 | Gnd | G4 | G5 | G + | 2 | 4 | 6 | 8 | 10 | 12 | 14 | 16 | 18 | 20 | 22 | 24 | 26 |\n" + | 1 | 3 | 5 | 7 | 9 | 11 | 13 | 15 | 17 | 19 | 21 | 23 | 25 |\n" +***/ + +} diff --git a/wiringPi/softPwm.c b/wiringPi/softPwm.c index a4f0fc4..0bde180 100644 --- a/wiringPi/softPwm.c +++ b/wiringPi/softPwm.c @@ -1,7 +1,7 @@ /* * softPwm.c: * Provide 2 channels of software driven PWM. - * Copyright (c) 2012 Gordon Henderson + * Copyright (c) 2012-2014 Gordon Henderson *********************************************************************** * This file is part of wiringPi: * https://projects.drogon.net/raspberry-pi/wiringpi/ @@ -28,17 +28,22 @@ #include "wiringPi.h" #include "softPwm.h" +// MAX_PINS: +// This is more than the number of Pi pins because we can actually softPwm +// pins that are on GPIO expanders. It's not that efficient and more than 1 or +// 2 pins on e.g. (SPI) mcp23s17 won't really be that effective, however... + #define MAX_PINS 1024 // The PWM Frequency is derived from the "pulse time" below. Essentially, // the frequency is a function of the range and this pulse time. -// The total period will be range * pulse time in uS, so a pulse time -// of 100 and a range of 100 gives a period of 100 * 100 = 10,000 uS +// The total period will be range * pulse time in µS, so a pulse time +// of 100 and a range of 100 gives a period of 100 * 100 = 10,000 µS // which is a frequency of 100Hz. // // It's possible to get a higher frequency by lowering the pulse time, // however CPU uage will skyrocket as wiringPi uses a hard-loop to time -// periods under 100uS - this is because the Linux timer calls are just +// periods under 100µS - this is because the Linux timer calls are just // accurate at all, and have an overhead. // // Another way to increase the frequency is to reduce the range - however @@ -46,8 +51,9 @@ #define PULSE_TIME 100 -static int marks [MAX_PINS] ; -static int range [MAX_PINS] ; +static int marks [MAX_PINS] ; +static int range [MAX_PINS] ; +static pthread_t threads [MAX_PINS] ; int newPin = -1 ; @@ -106,13 +112,20 @@ void softPwmWrite (int pin, int value) /* * softPwmCreate: - * Create a new PWM thread. + * Create a new softPWM thread. ********************************************************************************* */ int softPwmCreate (int pin, int initialValue, int pwmRange) { int res ; + pthread_t myThread ; + + if (range [pin] != 0) // Already running on this pin + return -1 ; + + if (range <= 0) + return -1 ; pinMode (pin, OUTPUT) ; digitalWrite (pin, LOW) ; @@ -121,10 +134,30 @@ int softPwmCreate (int pin, int initialValue, int pwmRange) range [pin] = pwmRange ; newPin = pin ; - res = piThreadCreate (softPwmThread) ; + res = pthread_create (&myThread, NULL, softPwmThread, NULL) ; while (newPin != -1) delay (1) ; + threads [pin] = myThread ; + return res ; } + + +/* + * softPwmStop: + * Stop an existing softPWM thread + ********************************************************************************* + */ + +void softPwmStop (int pin) +{ + if (range [pin] != 0) + { + pthread_cancel (threads [pin]) ; + pthread_join (threads [pin], NULL) ; + range [pin] = 0 ; + digitalWrite (pin, LOW) ; +} +} diff --git a/wiringPi/softPwm.h b/wiringPi/softPwm.h index 28ad299..0351da5 100644 --- a/wiringPi/softPwm.h +++ b/wiringPi/softPwm.h @@ -28,6 +28,7 @@ extern "C" { extern int softPwmCreate (int pin, int value, int range) ; extern void softPwmWrite (int pin, int value) ; +extern void softPwmStop (int pin) ; #ifdef __cplusplus } diff --git a/wiringPi/wiringPi.c b/wiringPi/wiringPi.c index b54ad29..4660a67 100644 --- a/wiringPi/wiringPi.c +++ b/wiringPi/wiringPi.c @@ -70,6 +70,8 @@ #include #include +#include "softPwm.h" + #include "wiringPi.h" #ifndef TRUE @@ -961,6 +963,7 @@ void pinMode (int pin, int mode) { int fSel, shift, alt ; struct wiringPiNodeStruct *node = wiringPiNodes ; + int origPin = pin ; if ((pin & PI_GPIO_MASK) == 0) // On-board pin { @@ -971,6 +974,8 @@ void pinMode (int pin, int mode) else if (wiringPiMode != WPI_MODE_GPIO) return ; + softPwmStop (origPin) ; + fSel = gpioToGPFSEL [pin] ; shift = gpioToShift [pin] ; @@ -978,9 +983,11 @@ void pinMode (int pin, int mode) *(gpio + fSel) = (*(gpio + fSel) & ~(7 << shift)) ; // Sets bits to zero = input else if (mode == OUTPUT) *(gpio + fSel) = (*(gpio + fSel) & ~(7 << shift)) | (1 << shift) ; + else if (mode == SOFT_PWM_OUTPUT) + softPwmCreate (origPin, 0, 100) ; else if (mode == PWM_OUTPUT) { - if ((alt = gpioToPwmALT [pin]) == 0) // Not a PWM pin + if ((alt = gpioToPwmALT [pin]) == 0) // Not a hardware capable PWM pin return ; // Set pin to PWM mode @@ -990,7 +997,7 @@ void pinMode (int pin, int mode) pwmSetMode (PWM_MODE_BAL) ; // Pi default mode pwmSetRange (1024) ; // Default range of 1024 - pwmSetClock (32) ; // 19.2 / 32 = 600KHz - Also starts the PWM + pwmSetClock (32) ; // 19.2 / 32 = 600KHz - Also starts the PWM } else if (mode == GPIO_CLOCK) { diff --git a/wiringPi/wiringPi.h b/wiringPi/wiringPi.h index ce4680a..4eea3e5 100644 --- a/wiringPi/wiringPi.h +++ b/wiringPi/wiringPi.h @@ -42,6 +42,7 @@ #define OUTPUT 1 #define PWM_OUTPUT 2 #define GPIO_CLOCK 3 +#define SOFT_PWM_OUTPUT 4 #define LOW 0 #define HIGH 1 -- 2.30.2