Updated wiringPi to add new PWM controls.pull/22/head
@@ -41,7 +41,7 @@ OBJ = gpio.o | |||||
all: gpio | all: gpio | ||||
gpio: gpio.o | |||||
gpio: gpio.o /usr/local/lib/libwiringPi.a | |||||
@echo [LD] | @echo [LD] | ||||
@$(CC) -o $@ gpio.o $(LDFLAGS) $(LIBS) | @$(CC) -o $@ gpio.o $(LDFLAGS) $(LIBS) | ||||
@@ -4,20 +4,38 @@ | |||||
gpio \- Command-line access to Raspberry Pi and PiFace GPIO | gpio \- Command-line access to Raspberry Pi and PiFace GPIO | ||||
.SH SYNOPSIS | .SH SYNOPSIS | ||||
.TP | |||||
.B gpio | .B gpio | ||||
.RB [ \-v ] | |||||
.TP | |||||
.B \-v | |||||
.PP | |||||
.B gpio | .B gpio | ||||
.RB [ \-g ] | |||||
.RB < read/write/pwm/mode ...> | |||||
.TP | |||||
.B [ \-g ] | |||||
.B read/write/pwm/mode ... | |||||
.PP | |||||
.B gpio | .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 | .B gpio | ||||
.RB < export/edge/unexport/unexportall/exports ...> | |||||
.B load \ i2c/spi | |||||
.SH DESCRIPTION | .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. | pull-up, pull-down or tristate (off) controls. | ||||
.TP | .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 | .B export | ||||
Export a GPIO pin in the \fI/sys/class/gpio\fR directory. Use like the | 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 | 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. | Un-Export a GPIO pin in the /sys/class/gpio directory. | ||||
.TP | .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 | .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" | .SH "WiringPi vs. GPIO Pin numbering" | ||||
@@ -170,7 +210,7 @@ Gordon Henderson | |||||
.SH "REPORTING BUGS" | .SH "REPORTING BUGS" | ||||
Report bugs to <gordon@drogon.net> | |||||
Report bugs to <projects@drogon.net> | |||||
.SH COPYRIGHT | .SH COPYRIGHT | ||||
@@ -46,6 +46,8 @@ char *usage = "Usage: gpio -v\n" | |||||
" gpio [-p] <read/write/mode> ...\n" | " gpio [-p] <read/write/mode> ...\n" | ||||
" gpio export/edge/unexport/unexportall/exports ...\n" | " gpio export/edge/unexport/unexportall/exports ...\n" | ||||
" gpio drive <group> <value>\n" | " gpio drive <group> <value>\n" | ||||
" gpio pwm-bal/pwm-ms \n" | |||||
" gpio pwmr <range> \n" | |||||
" gpio load spi/i2c" ; | " gpio load spi/i2c" ; | ||||
@@ -487,18 +489,12 @@ void doMode (int argc, char *argv []) | |||||
mode = argv [3] ; | 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 | 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/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 <range>\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: | * main: | ||||
* Start here | * Start here | ||||
********************************************************************************* | ********************************************************************************* | ||||
@@ -734,18 +763,22 @@ int main (int argc, char *argv []) | |||||
wpMode = WPI_MODE_PINS ; | 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 | // 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 | else | ||||
{ | { | ||||
fprintf (stderr, "%s: Unknown command: %s. (read/write/pwm/mode/drive expected)\n", argv [0], argv [1]) ; | fprintf (stderr, "%s: Unknown command: %s. (read/write/pwm/mode/drive expected)\n", argv [0], argv [1]) ; | ||||
@@ -79,6 +79,8 @@ void (*setPadDrive) (int group, int value) ; | |||||
int (*digitalRead) (int pin) ; | int (*digitalRead) (int pin) ; | ||||
int (*waitForInterrupt) (int pin, int mS) ; | int (*waitForInterrupt) (int pin, int mS) ; | ||||
void (*delayMicroseconds) (unsigned int howLong) ; | void (*delayMicroseconds) (unsigned int howLong) ; | ||||
void (*pwmSetMode) (int mode) ; | |||||
void (*pwmSetRange) (unsigned int range) ; | |||||
#ifndef TRUE | #ifndef TRUE | ||||
@@ -377,22 +379,25 @@ void pinModeGpio (int pin, int mode) | |||||
if (!pwmRunning) | if (!pwmRunning) | ||||
{ | { | ||||
*(pwm + PWM_CONTROL) = 0 ; // Stop PWM | |||||
delayMicroseconds (10) ; | |||||
// Gert/Doms Values | // 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 | *(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) ; | delayMicroseconds (10) ; | ||||
*(pwm + PWM0_RANGE) = 0x400 ; delayMicroseconds (10) ; | |||||
*(pwm + PWM1_RANGE) = 0x400 ; delayMicroseconds (10) ; | |||||
// Enable PWMs | // Enable PWMs | ||||
*(pwm + PWM0_DATA) = 512 ; | *(pwm + PWM0_DATA) = 512 ; | ||||
*(pwm + PWM1_DATA) = 512 ; | *(pwm + PWM1_DATA) = 512 ; | ||||
// Balanced mode (default) | |||||
*(pwm + PWM_CONTROL) = PWM0_ENABLE | PWM1_ENABLE ; | *(pwm + PWM_CONTROL) = PWM0_ENABLE | PWM1_ENABLE ; | ||||
pwmRunning = TRUE ; | 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 | #ifdef notYetReady | ||||
/* | /* | ||||
* pinED01: | * pinED01: | ||||
@@ -774,6 +811,8 @@ int wiringPiSetup (void) | |||||
digitalRead = digitalReadWPi ; | digitalRead = digitalReadWPi ; | ||||
waitForInterrupt = waitForInterruptWPi ; | waitForInterrupt = waitForInterruptWPi ; | ||||
delayMicroseconds = delayMicrosecondsWPi ; | delayMicroseconds = delayMicrosecondsWPi ; | ||||
pwmSetMode = pwmSetModeWPi ; | |||||
pwmSetRange = pwmSetRangeWPi ; | |||||
// Open the master /dev/memory device | // Open the master /dev/memory device | ||||
@@ -928,6 +967,8 @@ int wiringPiSetupGpio (void) | |||||
digitalRead = digitalReadGpio ; | digitalRead = digitalReadGpio ; | ||||
waitForInterrupt = waitForInterruptGpio ; | waitForInterrupt = waitForInterruptGpio ; | ||||
delayMicroseconds = delayMicrosecondsWPi ; // Same | delayMicroseconds = delayMicrosecondsWPi ; // Same | ||||
pwmSetMode = pwmSetModeWPi ; | |||||
pwmSetRange = pwmSetRangeWPi ; | |||||
return 0 ; | return 0 ; | ||||
} | } | ||||
@@ -956,6 +997,9 @@ int wiringPiSetupSys (void) | |||||
digitalRead = digitalReadSys ; | digitalRead = digitalReadSys ; | ||||
waitForInterrupt = waitForInterruptSys ; | waitForInterrupt = waitForInterruptSys ; | ||||
delayMicroseconds = delayMicrosecondsSys ; | delayMicroseconds = delayMicrosecondsSys ; | ||||
pwmSetMode = pwmSetModeSys ; | |||||
pwmSetRange = pwmSetRangeSys ; | |||||
// Open and scan the directory, looking for exported GPIOs, and pre-open | // Open and scan the directory, looking for exported GPIOs, and pre-open | ||||
// the 'value' interface to speed things up for later | // the 'value' interface to speed things up for later | ||||
@@ -41,6 +41,12 @@ | |||||
#define PUD_DOWN 1 | #define PUD_DOWN 1 | ||||
#define PUD_UP 2 | #define PUD_UP 2 | ||||
// PWM | |||||
#define PWM_MODE_MS 0 | |||||
#define PWM_MODE_BAL 1 | |||||
// Function prototypes | // Function prototypes | ||||
// c++ wrappers thanks to a commend by Nick Lott | // c++ wrappers thanks to a commend by Nick Lott | ||||
// (and others on the Raspberry Pi forums) | // (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 void (*setPadDrive) (int group, int value) ; | ||||
extern int (*digitalRead) (int pin) ; | extern int (*digitalRead) (int pin) ; | ||||
extern void (*delayMicroseconds) (unsigned int howLong) ; | extern void (*delayMicroseconds) (unsigned int howLong) ; | ||||
extern void (*pwmSetMode) (int mode) ; | |||||
extern void (*pwmSetRange) (unsigned int range) ; | |||||
// Interrupts | // Interrupts | ||||