From f99ffeda401362658a69ea3df98744738ded3554 Mon Sep 17 00:00:00 2001 From: Gordon Henderson Date: Sun, 19 Aug 2012 15:12:45 +0100 Subject: [PATCH] Updated the GPIO command to add in new features for PWM Updated wiringPi to add new PWM controls. --- gpio/Makefile | 2 +- gpio/gpio.1 | 70 +++++++++++++++++++++++++++++++++++++----------- gpio/gpio.c | 77 ++++++++++++++++++++++++++++++++++++++--------------- wiringPi/wiringPi.c | 58 +++++++++++++++++++++++++++++++++++----- wiringPi/wiringPi.h | 8 ++++++ 5 files changed, 170 insertions(+), 45 deletions(-) diff --git a/gpio/Makefile b/gpio/Makefile index c0740c9..a92dd5f 100644 --- a/gpio/Makefile +++ b/gpio/Makefile @@ -41,7 +41,7 @@ OBJ = gpio.o all: gpio -gpio: gpio.o +gpio: gpio.o /usr/local/lib/libwiringPi.a @echo [LD] @$(CC) -o $@ gpio.o $(LDFLAGS) $(LIBS) diff --git a/gpio/gpio.1 b/gpio/gpio.1 index 7da64b2..73e43c8 100644 --- a/gpio/gpio.1 +++ b/gpio/gpio.1 @@ -4,20 +4,38 @@ gpio \- Command-line access to Raspberry Pi and PiFace GPIO .SH SYNOPSIS -.TP .B gpio -.RB [ \-v ] -.TP +.B \-v +.PP .B gpio -.RB [ \-g ] -.RB < read/write/pwm/mode ...> -.TP +.B [ \-g ] +.B read/write/pwm/mode ... +.PP .B gpio -.RB [ \-p ] -.RB < read/write/mode ...> -.TP +.B [ \-p ] +.B read/write/mode +.B ... +.PP +.B gpio +.B unexportall/exports +.PP +.B gpio +.B export/edge/unexport +.B ... +.PP +.B gpio +.B drive +group value +.PP +.B gpio +.B pwm-bal/pwm-ms +.PP +.B gpio +.B pwmr +range +.PP .B gpio -.RB < export/edge/unexport/unexportall/exports ...> +.B load \ i2c/spi .SH DESCRIPTION @@ -65,6 +83,14 @@ use the literals \fIup\fR, \fIdown\fR or \fItri\fR to set the internal pull-up, pull-down or tristate (off) controls. .TP +.B unexportall +Un-Export all the GPIO pins in the /sys/class/gpio directory. + +.TP +.B exports +Print a list (if any) of all the exported GPIO pins and their current values. + +.TP .B export Export a GPIO pin in the \fI/sys/class/gpio\fR directory. Use like the mode command above however only \fIin\fR and \fIout\fR are supported at @@ -96,12 +122,26 @@ requiring root/sudo. Un-Export a GPIO pin in the /sys/class/gpio directory. .TP -.B unexportall -Un-Export all the GPIO pins in the /sys/class/gpio directory. +.B drive +group value + +Change the pad driver value for the given pad group to the supplied drive +value. Group is 0, 1 or 2 and value is 0-7. Do not use unless you are +absolutely sure you know what you're doing. .TP -.B exports -Print a list (if any) of all the exported GPIO pins and their current values. +.B pwm-bal/pwm-ms +Change the PWM mode to balanced (the default) or mark:space ratio (traditional) + +.TP +.B pwmr +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. + .SH "WiringPi vs. GPIO Pin numbering" @@ -170,7 +210,7 @@ Gordon Henderson .SH "REPORTING BUGS" -Report bugs to +Report bugs to .SH COPYRIGHT diff --git a/gpio/gpio.c b/gpio/gpio.c index 54dfbc3..1d12aab 100644 --- a/gpio/gpio.c +++ b/gpio/gpio.c @@ -46,6 +46,8 @@ char *usage = "Usage: gpio -v\n" " gpio [-p] ...\n" " gpio export/edge/unexport/unexportall/exports ...\n" " gpio drive \n" + " gpio pwm-bal/pwm-ms \n" + " gpio pwmr \n" " gpio load spi/i2c" ; @@ -487,18 +489,12 @@ 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, "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) ; @@ -630,6 +626,39 @@ void doPwm (int argc, char *argv []) /* + * doPwmMode: doPwmRange: + * Change the PWM mode and Range values + ********************************************************************************* + */ + +static void doPwmMode (int mode) +{ + pwmSetMode (mode) ; +} + +static void doPwmRange (int argc, char *argv []) +{ + unsigned int range ; + + if (argc != 3) + { + fprintf (stderr, "Usage: %s pwmr \n", argv [0]) ; + exit (1) ; + } + + range = (unsigned int)strtoul (argv [2], NULL, 10) ; + + if (range == 0) + { + fprintf (stderr, "%s: range must be > 0\n", argv [0]) ; + exit (1) ; + } + + pwmSetRange (range) ; +} + + +/* * main: * Start here ********************************************************************************* @@ -734,18 +763,22 @@ int main (int argc, char *argv []) wpMode = WPI_MODE_PINS ; } +// Check for PWM 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 ; } + } + // Check for wiring commands - /**/ if (strcasecmp (argv [1], "write" ) == 0) - doWrite (argc, argv) ; - else if (strcasecmp (argv [1], "read" ) == 0) - doRead (argc, argv) ; - else if (strcasecmp (argv [1], "mode" ) == 0) - doMode (argc, argv) ; - else if (strcasecmp (argv [1], "pwm" ) == 0) - doPwm (argc, argv) ; - else if (strcasecmp (argv [1], "drive" ) == 0) - doPadDrive (argc, argv) ; + /**/ if (strcasecmp (argv [1], "write" ) == 0) doWrite (argc, argv) ; + else if (strcasecmp (argv [1], "read" ) == 0) doRead (argc, argv) ; + else if (strcasecmp (argv [1], "mode" ) == 0) doMode (argc, argv) ; + else if (strcasecmp (argv [1], "pwm" ) == 0) doPwm (argc, argv) ; + else if (strcasecmp (argv [1], "drive" ) == 0) doPadDrive (argc, argv) ; else { fprintf (stderr, "%s: Unknown command: %s. (read/write/pwm/mode/drive expected)\n", argv [0], argv [1]) ; diff --git a/wiringPi/wiringPi.c b/wiringPi/wiringPi.c index 0a4da30..bd3c999 100644 --- a/wiringPi/wiringPi.c +++ b/wiringPi/wiringPi.c @@ -79,6 +79,8 @@ 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) ; #ifndef TRUE @@ -377,22 +379,25 @@ void pinModeGpio (int pin, int mode) 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/3 = 600KHz) + *(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 - digitalWrite (pin, LOW) ; - *(pwm + PWM_CONTROL) = 0 ; // Disable PWM - delayMicroseconds (10) ; - *(pwm + PWM0_RANGE) = 0x400 ; - delayMicroseconds (10) ; - *(pwm + PWM1_RANGE) = 0x400 ; + delayMicroseconds (10) ; + *(pwm + PWM0_RANGE) = 0x400 ; delayMicroseconds (10) ; + *(pwm + PWM1_RANGE) = 0x400 ; delayMicroseconds (10) ; + // Enable PWMs *(pwm + PWM0_DATA) = 512 ; *(pwm + PWM1_DATA) = 512 ; +// Balanced mode (default) + *(pwm + PWM_CONTROL) = PWM0_ENABLE | PWM1_ENABLE ; pwmRunning = TRUE ; @@ -423,6 +428,38 @@ void pinModeSys (int pin, int mode) } +/* + * pwmControl: + * Allow the user to control some of the PWM functions + ********************************************************************************* + */ + +void pwmSetModeWPi (int mode) +{ + if (mode == PWM_MODE_MS) + *(pwm + PWM_CONTROL) = PWM0_ENABLE | PWM1_ENABLE | PWM0_MS_MODE | PWM1_MS_MODE ; + else + *(pwm + PWM_CONTROL) = PWM0_ENABLE | PWM1_ENABLE ; +} + +void pwmSetModeSys (int mode) +{ + return ; +} + + +void pwmSetRangeWPi (unsigned int range) +{ + *(pwm + PWM0_RANGE) = range ; delayMicroseconds (10) ; + *(pwm + PWM1_RANGE) = range ; delayMicroseconds (10) ; +} + +void pwmSetRangeSys (unsigned int range) +{ + return ; +} + + #ifdef notYetReady /* * pinED01: @@ -774,6 +811,8 @@ int wiringPiSetup (void) digitalRead = digitalReadWPi ; waitForInterrupt = waitForInterruptWPi ; delayMicroseconds = delayMicrosecondsWPi ; + pwmSetMode = pwmSetModeWPi ; + pwmSetRange = pwmSetRangeWPi ; // Open the master /dev/memory device @@ -928,6 +967,8 @@ int wiringPiSetupGpio (void) digitalRead = digitalReadGpio ; waitForInterrupt = waitForInterruptGpio ; delayMicroseconds = delayMicrosecondsWPi ; // Same + pwmSetMode = pwmSetModeWPi ; + pwmSetRange = pwmSetRangeWPi ; return 0 ; } @@ -956,6 +997,9 @@ int wiringPiSetupSys (void) digitalRead = digitalReadSys ; waitForInterrupt = waitForInterruptSys ; delayMicroseconds = delayMicrosecondsSys ; + pwmSetMode = pwmSetModeSys ; + pwmSetRange = pwmSetRangeSys ; + // Open and scan the directory, looking for exported GPIOs, and pre-open // the 'value' interface to speed things up for later diff --git a/wiringPi/wiringPi.h b/wiringPi/wiringPi.h index 03ab787..1d21fa0 100644 --- a/wiringPi/wiringPi.h +++ b/wiringPi/wiringPi.h @@ -41,6 +41,12 @@ #define PUD_DOWN 1 #define PUD_UP 2 +// PWM + +#define PWM_MODE_MS 0 +#define PWM_MODE_BAL 1 + + // Function prototypes // c++ wrappers thanks to a commend by Nick Lott // (and others on the Raspberry Pi forums) @@ -65,6 +71,8 @@ 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) ; // Interrupts