to produce a nicer 'readall' output too. It also understands new pins 53,54,55 and 56 in wiringPiSetupPhys() mode to represent the pins on the P5 connector on the Rev 2 Pi's Changes to pinMode() to allow new modes SOFT_PWM and SOFT_TONE.pull/22/head
@@ -79,6 +79,7 @@ char *usage = "Usage: gpio -v\n" | |||
" gpio gbw <channel> <value>" ; // No trailing newline needed here. | |||
#ifdef NOT_FOR_NOW | |||
/* | |||
* decodePin: | |||
* Decode a pin "number" which can actually be a pin name to represent | |||
@@ -96,6 +97,7 @@ static int decodePin (const char *str) | |||
return 0 ; | |||
} | |||
#endif | |||
/* | |||
@@ -1042,6 +1044,8 @@ static void doPwmClock (int argc, char *argv []) | |||
int main (int argc, char *argv []) | |||
{ | |||
int i ; | |||
int model, rev, mem ; | |||
char *maker ; | |||
if (getenv ("WIRINGPI_DEBUG") != NULL) | |||
{ | |||
@@ -1086,7 +1090,10 @@ int main (int argc, char *argv []) | |||
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 ()) ; | |||
piBoardId (&model, &rev, &mem, &maker) ; | |||
printf ("Raspberry Pi Details:\n") ; | |||
printf (" Type: %s, Revision: %s, Memory: %dMB, Maker: %s\n", | |||
piModelNames [model], piRevisionNames [rev], mem, maker) ; | |||
return 0 ; | |||
} | |||
@@ -39,6 +39,17 @@ extern int wpMode ; | |||
void doPins (void) | |||
{ | |||
int model, rev, mem ; | |||
char *maker ; | |||
piBoardId (&model, &rev, &mem, &maker) ; | |||
if (model == PI_MODEL_CM) | |||
{ | |||
printf ("This Raspberry Pi is a Compute Module.\n") ; | |||
printf (" (who knows what's been done to the pins!)\n") ; | |||
return ; | |||
} | |||
printf ("This Raspberry Pi is a revision %d board.\n", piBoardRev ()) ; | |||
printf ( | |||
@@ -37,6 +37,11 @@ | |||
extern int wpMode ; | |||
#ifndef TRUE | |||
# define TRUE (1==1) | |||
# define FALSE (1==2) | |||
#endif | |||
/* | |||
* doReadallExternal: | |||
* A relatively crude way to read the pins on an external device. | |||
@@ -90,7 +95,7 @@ static int wpiToPhys [64] = | |||
3, 5, // 8...9 | |||
24, 26, 19, 21, 23, // 10..14 | |||
8, 10, // 15..16 | |||
3, 4, 5, 6, // 17..20 | |||
53, 54, 55, 56, // 17..20 | |||
0,0,0,0,0,0,0,0,0,0,0, // 20..31 | |||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 32..47 | |||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 47..63 | |||
@@ -115,11 +120,11 @@ static int physToWpi [64] = | |||
14, 10, | |||
-1, 11, // 25, 26 | |||
// Padding: | |||
-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 | |||
-1, -1, -1, -1, -1, // ... 52 | |||
28, 29, 30, 31, // ... 53, 54, 55, 56 - P5 | |||
-1, -1, -1, -1, -1, -1, -1, // ... 63 | |||
} ; | |||
static char *physNames [64] = | |||
@@ -140,9 +145,11 @@ static char *physNames [64] = | |||
"SCLK", "CE0", | |||
"0v", "CE1", | |||
NULL,NULL,NULL,NULL,NULL, | |||
NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL, | |||
NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL, | |||
NULL,NULL,NULL,NULL,NULL, // ... 31 | |||
NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL, // ... 47 | |||
NULL,NULL,NULL,NULL,NULL, // ... 52 | |||
"GPIO8", "GPIO9", "GPIO10", "GPIO11", // ... 53, 54, 55, 56 - P5 | |||
NULL,NULL,NULL,NULL,NULL,NULL, // ... 63 | |||
} ; | |||
static void readallPhys (int physPin) | |||
@@ -225,6 +232,38 @@ static void readallPhys (int physPin) | |||
} | |||
int cmReadall (void) | |||
{ | |||
int model, rev, mem ; | |||
int pin ; | |||
char *maker ; | |||
piBoardId (&model, &rev, &mem, &maker) ; | |||
if (model != PI_MODEL_CM) | |||
return FALSE ; | |||
printf ("+-----+------+-------+ +-----+------+-------+\n") ; | |||
printf ("| Pin | Mode | Value | | Pin | Mode | Value |\n") ; | |||
printf ("+-----+------+-------+ +-----+------+-------+\n") ; | |||
for (pin = 0 ; pin < 28 ; ++pin) | |||
{ | |||
printf ("| %3d ", pin) ; | |||
printf ("| %-4s ", alts [getAlt (pin)]) ; | |||
printf ("| %s ", digitalRead (pin) == HIGH ? "High" : "Low ") ; | |||
printf ("| ") ; | |||
printf ("| %3d ", pin + 28) ; | |||
printf ("| %-4s ", alts [getAlt (pin + 28)]) ; | |||
printf ("| %s ", digitalRead (pin + 28) == HIGH ? "High" : "Low ") ; | |||
printf ("|\n") ; | |||
} | |||
printf ("+-----+------+-------+ +-----+------+-------+\n") ; | |||
return TRUE ; | |||
} | |||
void doReadall (void) | |||
{ | |||
int pin ; | |||
@@ -235,6 +274,9 @@ void doReadall (void) | |||
return ; | |||
} | |||
if (cmReadall ()) | |||
return ; | |||
/**/ if (wpMode == WPI_MODE_GPIO) | |||
{ | |||
printf (" +-----+-------+------+----+-Rev%d-----+----+------+-------+-----+\n", piBoardRev ()) ; | |||
@@ -275,6 +317,9 @@ void doReadallOld (void) | |||
return ; | |||
} | |||
if (cmReadall ()) | |||
return ; | |||
printf ("+----------+-Rev%d-+------+--------+------+-------+\n", piBoardRev ()) ; | |||
printf ("| wiringPi | GPIO | Phys | Name | Mode | Value |\n") ; | |||
printf ("+----------+------+------+--------+------+-------+\n") ; | |||
@@ -67,11 +67,15 @@ int newPin = -1 ; | |||
static PI_THREAD (softPwmThread) | |||
{ | |||
int pin, mark, space ; | |||
struct sched_param param ; | |||
param.sched_priority = sched_get_priority_max (SCHED_RR) ; | |||
pthread_setschedparam (pthread_self (), SCHED_RR, ¶m) ; | |||
pin = newPin ; | |||
newPin = -1 ; | |||
piHiPri (50) ; | |||
piHiPri (90) ; | |||
for (;;) | |||
{ | |||
@@ -159,5 +163,5 @@ void softPwmStop (int pin) | |||
pthread_join (threads [pin], NULL) ; | |||
range [pin] = 0 ; | |||
digitalWrite (pin, LOW) ; | |||
} | |||
} | |||
} |
@@ -36,7 +36,8 @@ | |||
#define PULSE_TIME 100 | |||
static int freqs [MAX_PINS] ; | |||
static int freqs [MAX_PINS] ; | |||
static pthread_t threads [MAX_PINS] ; | |||
static int newPin = -1 ; | |||
@@ -50,6 +51,10 @@ static int newPin = -1 ; | |||
static PI_THREAD (softToneThread) | |||
{ | |||
int pin, freq, halfPeriod ; | |||
struct sched_param param ; | |||
param.sched_priority = sched_get_priority_max (SCHED_RR) ; | |||
pthread_setschedparam (pthread_self (), SCHED_RR, ¶m) ; | |||
pin = newPin ; | |||
newPin = -1 ; | |||
@@ -105,17 +110,41 @@ void softToneWrite (int pin, int freq) | |||
int softToneCreate (int pin) | |||
{ | |||
int res ; | |||
pthread_t myThread ; | |||
pinMode (pin, OUTPUT) ; | |||
digitalWrite (pin, LOW) ; | |||
if (threads [pin] != 0) | |||
return -1 ; | |||
freqs [pin] = 0 ; | |||
newPin = pin ; | |||
res = piThreadCreate (softToneThread) ; | |||
res = pthread_create (&myThread, NULL, softToneThread, NULL) ; | |||
while (newPin != -1) | |||
delay (1) ; | |||
threads [pin] = myThread ; | |||
return res ; | |||
} | |||
/* | |||
* softToneStop: | |||
* Stop an existing softTone thread | |||
********************************************************************************* | |||
*/ | |||
void softToneStop (int pin) | |||
{ | |||
if (threads [pin] != 0) | |||
{ | |||
pthread_cancel (threads [pin]) ; | |||
pthread_join (threads [pin], NULL) ; | |||
threads [pin] = 0 ; | |||
digitalWrite (pin, LOW) ; | |||
} | |||
} |
@@ -31,6 +31,7 @@ extern "C" { | |||
#endif | |||
extern int softToneCreate (int pin) ; | |||
extern void softToneStop (int pin) ; | |||
extern void softToneWrite (int pin, int freq) ; | |||
#ifdef __cplusplus | |||
@@ -71,6 +71,7 @@ | |||
#include <sys/ioctl.h> | |||
#include "softPwm.h" | |||
#include "softTone.h" | |||
#include "wiringPi.h" | |||
@@ -272,6 +273,7 @@ static int pinToGpioR2 [64] = | |||
// physToGpio: | |||
// Take a physical pin (1 through 26) and re-map it to the BCM_GPIO pin | |||
// Cope for 2 different board revisions here. | |||
// Also add in the P5 connector, so the P5 pins are 3,4,5,6, so 53,54,55,56 | |||
static int *physToGpio ; | |||
@@ -292,8 +294,6 @@ static int physToGpioR1 [64] = | |||
11, 8, | |||
-1, 7, // 25, 26 | |||
// Padding: | |||
-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 | |||
@@ -316,11 +316,13 @@ static int physToGpioR2 [64] = | |||
11, 8, | |||
-1, 7, // 25, 26 | |||
// Padding: | |||
// the P5 connector on the Rev 2 boards: | |||
-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 | |||
-1, -1, -1, -1, -1, // ... 52 | |||
28, 29, 30, 31, // ... 53, 54, 55, 56 - P5 | |||
-1, -1, -1, -1, -1, -1, -1, // ... 63 | |||
} ; | |||
@@ -547,22 +549,30 @@ int wiringPiFailure (int fatal, const char *message, ...) | |||
* | |||
* Much confusion here )-: | |||
* Seems there are some 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 (Early reports? | |||
* 0005 - Rev 2 (but error?) | |||
* 0006 - Rev 2 | |||
* 0008 - Rev 2 - Model A | |||
* 000e - Rev 2 + 512MB | |||
* 000f - Rev 2 + 512MB | |||
* 0001 - Not used (Compute - default to Rev 2) | |||
* 0002 - Model B, Rev 1, 256MB | |||
* 0003 - Model B, Rev 1.1, 256MB, Fuses/D14 removed. | |||
* 0004 - Model B, Rev 2, 256MB, Sony | |||
* 0005 - Model B, Rev 2, 256MB, Qisda | |||
* 0006 - Model B, Rev 2, 256MB, Egoman | |||
* 0007 - Model A, Rev 2, 256MB, Egoman | |||
* 0008 - Model A, Rev 2, 256MB, Sony | |||
* 0009 - Model A, Rev 2, 256MB, Qisda | |||
* 000d - Model B, Rev 2, 512MB, Egoman | |||
* 000e - Model B, Rev 2, 512MB, Sony | |||
* 000f - Model B, Rev 2, 512MB, Qisda | |||
* 0011 - Pi compute Module | |||
* | |||
* A small thorn is the olde style overvolting - that will add in | |||
* 1000000 | |||
* | |||
* The Pi compute module has an revision of 0011 - since we only check the | |||
* last digit, then it's 1, therefore it'll default to not 2 or 3 for a | |||
* Rev 1, so will appear as a Rev 2. This is fine for the most part, but | |||
* we'll properly detect the Compute Module later and adjust accordingly. | |||
* | |||
********************************************************************************* | |||
*/ | |||
@@ -635,6 +645,89 @@ int piBoardRev (void) | |||
/* | |||
* piBoardId: | |||
* Do more digging into the board revision string as above, but return | |||
* as much details as we can. | |||
********************************************************************************* | |||
*/ | |||
const char *piModelNames [] = | |||
{ | |||
"Model A", | |||
"Model B", | |||
"Compute Module", | |||
} ; | |||
const char *piRevisionNames[] = | |||
{ | |||
"1", | |||
"1.1", | |||
"2", | |||
} ; | |||
void piBoardId (int *model, int *rev, int *mem, char **maker) | |||
{ | |||
FILE *cpuFd ; | |||
char line [120] ; | |||
char *c ; | |||
piBoardRev () ; // Call this first to make sure all's OK. Don't care about the result. | |||
if ((cpuFd = fopen ("/proc/cpuinfo", "r")) == NULL) | |||
piBoardRevOops ("Unable to open /proc/cpuinfo") ; | |||
while (fgets (line, 120, cpuFd) != NULL) | |||
if (strncmp (line, "Revision", 8) == 0) | |||
break ; | |||
fclose (cpuFd) ; | |||
if (strncmp (line, "Revision", 8) != 0) | |||
piBoardRevOops ("No \"Revision\" line") ; | |||
// Chomp trailing CR/NL | |||
for (c = &line [strlen (line) - 1] ; (*c == '\n') || (*c == '\r') ; --c) | |||
*c = 0 ; | |||
if (wiringPiDebug) | |||
printf ("piboardId: Revision string: %s\n", line) ; | |||
// Scan to first digit | |||
for (c = line ; *c ; ++c) | |||
if (isdigit (*c)) | |||
break ; | |||
// Make sure its long enough | |||
if (strlen (c) < 4) | |||
piBoardRevOops ("Bogus \"Revision\" line") ; | |||
// Extract last 4 characters: | |||
c = c + strlen (c) - 4 ; | |||
// Fill out the replys as appropriate | |||
/**/ if (strcmp (c, "0002") == 0) { *model = 1 ; *rev = 0 ; *mem = 256 ; *maker = "China" ; } | |||
else if (strcmp (c, "0003") == 0) { *model = 1 ; *rev = 1 ; *mem = 256 ; *maker = "China" ; } | |||
else if (strcmp (c, "0004") == 0) { *model = 1 ; *rev = 2 ; *mem = 256 ; *maker = "Sony" ; } | |||
else if (strcmp (c, "0005") == 0) { *model = 1 ; *rev = 2 ; *mem = 256 ; *maker = "Qisda" ; } | |||
else if (strcmp (c, "0006") == 0) { *model = 1 ; *rev = 2 ; *mem = 256 ; *maker = "Egoman" ; } | |||
else if (strcmp (c, "0007") == 0) { *model = 0 ; *rev = 2 ; *mem = 256 ; *maker = "Egoman" ; } | |||
else if (strcmp (c, "0008") == 0) { *model = 0 ; *rev = 2 ; *mem = 256 ; *maker = "Sony" ; } | |||
else if (strcmp (c, "0009") == 0) { *model = 1 ; *rev = 2 ; *mem = 256 ; *maker = "Qisda" ; } | |||
else if (strcmp (c, "000d") == 0) { *model = 1 ; *rev = 2 ; *mem = 512 ; *maker = "Egoman" ; } | |||
else if (strcmp (c, "000e") == 0) { *model = 1 ; *rev = 2 ; *mem = 512 ; *maker = "Sony" ; } | |||
else if (strcmp (c, "000f") == 0) { *model = 1 ; *rev = 2 ; *mem = 512 ; *maker = "Egoman" ; } | |||
else if (strcmp (c, "0011") == 0) { *model = 2 ; *rev = 1 ; *mem = 512 ; *maker = "Sony" ; } | |||
else { *model = 0 ; *rev = 0 ; *mem = 0 ; *maker = "Unkn" ; } | |||
} | |||
/* | |||
* wpiPinToGpio: | |||
* Translate a wiringPi Pin number to native GPIO pin number. | |||
* Provided for external support. | |||
@@ -974,7 +1067,8 @@ void pinMode (int pin, int mode) | |||
else if (wiringPiMode != WPI_MODE_GPIO) | |||
return ; | |||
softPwmStop (origPin) ; | |||
softPwmStop (origPin) ; | |||
softToneStop (origPin) ; | |||
fSel = gpioToGPFSEL [pin] ; | |||
shift = gpioToShift [pin] ; | |||
@@ -985,6 +1079,8 @@ void pinMode (int pin, int mode) | |||
*(gpio + fSel) = (*(gpio + fSel) & ~(7 << shift)) | (1 << shift) ; | |||
else if (mode == SOFT_PWM_OUTPUT) | |||
softPwmCreate (origPin, 0, 100) ; | |||
else if (mode == SOFT_TONE_OUTPUT) | |||
softToneCreate (origPin) ; | |||
else if (mode == PWM_OUTPUT) | |||
{ | |||
if ((alt = gpioToPwmALT [pin]) == 0) // Not a hardware capable PWM pin | |||
@@ -1376,8 +1472,18 @@ int wiringPiISR (int pin, int mode, void (*function)(void)) | |||
if (pid == 0) // Child, exec | |||
{ | |||
execl ("/usr/local/bin/gpio", "gpio", "edge", pinS, modeS, (char *)NULL) ; | |||
return wiringPiFailure (WPI_FATAL, "wiringPiISR: execl failed: %s\n", strerror (errno)) ; | |||
if (access ("/usr/local/bin/gpio", X_OK)) | |||
{ | |||
execl ("/usr/local/bin/gpio", "gpio", "edge", pinS, modeS, (char *)NULL) ; | |||
return wiringPiFailure (WPI_FATAL, "wiringPiISR: execl failed: %s\n", strerror (errno)) ; | |||
} | |||
else if (access ("/usr/bin/gpio", X_OK)) | |||
{ | |||
execl ("/usr/bin/gpio", "gpio", "edge", pinS, modeS, (char *)NULL) ; | |||
return wiringPiFailure (WPI_FATAL, "wiringPiISR: execl failed: %s\n", strerror (errno)) ; | |||
} | |||
else | |||
return wiringPiFailure (WPI_FATAL, "wiringPiISR: Can't find gpio program\n") ; | |||
} | |||
else // Parent, wait | |||
wait (NULL) ; | |||
@@ -1538,13 +1644,17 @@ unsigned int micros (void) | |||
* | |||
* Default setup: Initialises the system into wiringPi Pin mode and uses the | |||
* memory mapped hardware directly. | |||
* | |||
* Changed now to revert to "gpio" mode if we're running on a Compute Module. | |||
********************************************************************************* | |||
*/ | |||
int wiringPiSetup (void) | |||
{ | |||
int fd ; | |||
int boardRev ; | |||
int fd ; | |||
int boardRev ; | |||
int model, rev, mem ; | |||
char *maker ; | |||
if (getenv (ENV_DEBUG) != NULL) | |||
wiringPiDebug = TRUE ; | |||
@@ -1618,7 +1728,13 @@ int wiringPiSetup (void) | |||
initialiseEpoch () ; | |||
wiringPiMode = WPI_MODE_PINS ; | |||
// If we're running on a compute module, then wiringPi pin numbers don't really many anything... | |||
piBoardId (&model, &rev, &mem, &maker) ; | |||
if (model == PI_MODEL_CM) | |||
wiringPiMode = WPI_MODE_GPIO ; | |||
else | |||
wiringPiMode = WPI_MODE_PINS ; | |||
return 0 ; | |||
} | |||
@@ -43,6 +43,7 @@ | |||
#define PWM_OUTPUT 2 | |||
#define GPIO_CLOCK 3 | |||
#define SOFT_PWM_OUTPUT 4 | |||
#define SOFT_TONE_OUTPUT 5 | |||
#define LOW 0 | |||
#define HIGH 1 | |||
@@ -65,6 +66,13 @@ | |||
#define INT_EDGE_RISING 2 | |||
#define INT_EDGE_BOTH 3 | |||
// Pi model types | |||
#define PI_MODEL_A 0 | |||
#define PI_MODEL_B 1 | |||
#define PI_MODEL_CM 2 | |||
// Threads | |||
#define PI_THREAD(X) void *X (void *dummy) | |||
@@ -116,6 +124,12 @@ extern struct wiringPiNodeStruct *wiringPiNodes ; | |||
extern "C" { | |||
#endif | |||
// Data | |||
extern const char *piModelNames [] ; | |||
extern const char *piRevisionNames[] ; | |||
extern const char *piComputeRevisionNames[] ; | |||
// Internal | |||
extern int wiringPiFailure (int fatal, const char *message, ...) ; | |||
@@ -148,6 +162,7 @@ extern int wiringPiSetupPiFaceForGpioProg (void) ; // Don't use this - for gpio | |||
// On-Board Raspberry Pi hardware specific stuff | |||
extern int piBoardRev (void) ; | |||
extern void piBoardId (int *model, int *rev, int *mem, char **maker) ; | |||
extern int wpiPinToGpio (int wpiPin) ; | |||
extern int physPinToGpio (int physPin) ; | |||
extern void setPadDrive (int group, int value) ; | |||