@@ -1 +1 @@ | |||
3.4 | |||
3.6 |
@@ -48,7 +48,7 @@ high | low | |||
range | |||
.PP | |||
.B gpio | |||
.B load \ i2c/spi ... | |||
.B i2cd | |||
.PP | |||
.B gpio | |||
.B gbr | |||
@@ -67,8 +67,7 @@ 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. | |||
It can also control the IO's on the PiFace IO board and load the SPI and I2C | |||
kernel modules if required. | |||
It can also control the IO's on the PiFace IO board. | |||
.SH OPTIONS | |||
@@ -208,6 +207,10 @@ Change the PWM mode to balanced (the default) or mark:space ratio (traditional) | |||
Change the PWM range register. The default is 1024. | |||
.TP | |||
.B i2cd | |||
Executes i2c-detect for the default I2C port on the P1 connector. | |||
.TP | |||
.B gbr | |||
channel | |||
@@ -72,15 +72,11 @@ char *usage = "Usage: gpio -v\n" | |||
" gpio <mode/read/write/aread/awritewb/pwm/pwmTone/clock> ...\n" | |||
" gpio <toggle/blink> <pin>\n" | |||
" gpio readall\n" | |||
// " gpio unexportall/exports\n" | |||
// " gpio export/edge/unexport ...\n" | |||
" gpio wfi <pin> <mode>\n" | |||
" gpio drive <group> <value>\n" | |||
" gpio pwm-bal/pwm-ms \n" | |||
" gpio pwmr <range> \n" | |||
" gpio pwmc <divider> \n" | |||
" gpio load spi/i2c\n" | |||
" gpio unload spi/i2c\n" | |||
" gpio i2cd/i2cdetect\n" | |||
" gpio rbx/rbd\n" | |||
" gpio wb <value>\n" | |||
@@ -110,287 +106,6 @@ static int decodePin (const char *str) | |||
#endif | |||
/* | |||
* findExecutable: | |||
* Code to locate the path to the given executable. We have a fixed list | |||
* of locations to try which completely overrides any $PATH environment. | |||
* This may be detrimental, however it avoids the reliance on $PATH | |||
* which may be a security issue when this program is run a set-uid-root. | |||
********************************************************************************* | |||
*/ | |||
static const char *searchPath [] = | |||
{ | |||
"/sbin", | |||
"/usr/sbin", | |||
"/bin", | |||
"/usr/bin", | |||
NULL, | |||
} ; | |||
static char *findExecutable (const char *progName) | |||
{ | |||
static char *path = NULL ; | |||
int len = strlen (progName) ; | |||
int i = 0 ; | |||
struct stat statBuf ; | |||
for (i = 0 ; searchPath [i] != NULL ; ++i) | |||
{ | |||
path = malloc (strlen (searchPath [i]) + len + 2) ; | |||
sprintf (path, "%s/%s", searchPath [i], progName) ; | |||
if (stat (path, &statBuf) == 0) | |||
return path ; | |||
free (path) ; | |||
} | |||
return NULL ; | |||
} | |||
/* | |||
* changeOwner: | |||
* Change the ownership of the file to the real userId of the calling | |||
* program so we can access it. | |||
********************************************************************************* | |||
*/ | |||
static void changeOwner (char *cmd, char *file) | |||
{ | |||
uid_t uid = getuid () ; | |||
uid_t gid = getgid () ; | |||
if (chown (file, uid, gid) != 0) | |||
{ | |||
// Removed (ignoring) the check for not existing as I'm fed-up with morons telling me that | |||
// the warning message is an error. | |||
if (errno != ENOENT) | |||
fprintf (stderr, "%s: Unable to change ownership of %s: %s\n", cmd, file, strerror (errno)) ; | |||
} | |||
} | |||
/* | |||
* moduleLoaded: | |||
* Return true/false if the supplied module is loaded | |||
********************************************************************************* | |||
*/ | |||
static int moduleLoaded (char *modName) | |||
{ | |||
int len = strlen (modName) ; | |||
int found = FALSE ; | |||
FILE *fd = fopen ("/proc/modules", "r") ; | |||
char line [80] ; | |||
if (fd == NULL) | |||
{ | |||
fprintf (stderr, "gpio: Unable to check /proc/modules: %s\n", strerror (errno)) ; | |||
exit (1) ; | |||
} | |||
while (fgets (line, 80, fd) != NULL) | |||
{ | |||
if (strncmp (line, modName, len) != 0) | |||
continue ; | |||
found = TRUE ; | |||
break ; | |||
} | |||
fclose (fd) ; | |||
return found ; | |||
} | |||
/* | |||
* doLoad: | |||
* Load either the spi or i2c modules and change device ownerships, etc. | |||
********************************************************************************* | |||
*/ | |||
static void checkDevTree (char *argv []) | |||
{ | |||
struct stat statBuf ; | |||
if (stat ("/proc/device-tree", &statBuf) == 0) // We're on a devtree system ... | |||
{ | |||
fprintf (stderr, | |||
"%s: Unable to load/unload modules as this Pi has the device tree enabled.\n" | |||
" You need to run the raspi-config program (as root) and select the\n" | |||
" modules (SPI or I2C) that you wish to load/unload there and reboot.\n", argv [0]) ; | |||
exit (1) ; | |||
} | |||
} | |||
static void _doLoadUsage (char *argv []) | |||
{ | |||
fprintf (stderr, "Usage: %s load <spi/i2c> [I2C baudrate in Kb/sec]\n", argv [0]) ; | |||
exit (1) ; | |||
} | |||
static void doLoad (int argc, char *argv []) | |||
{ | |||
char *module1, *module2 ; | |||
char cmd [80] ; | |||
char *file1, *file2 ; | |||
char args1 [32], args2 [32] ; | |||
checkDevTree (argv) ; | |||
if (argc < 3) | |||
_doLoadUsage (argv) ; | |||
args1 [0] = args2 [0] = 0 ; | |||
/**/ if (strcasecmp (argv [2], "spi") == 0) | |||
{ | |||
module1 = "spidev" ; | |||
module2 = "spi_bcm2708" ; | |||
file1 = "/dev/spidev0.0" ; | |||
file2 = "/dev/spidev0.1" ; | |||
if (argc == 4) | |||
{ | |||
fprintf (stderr, "%s: Unable to set the buffer size now. Load aborted. Please see the man page.\n", argv [0]) ; | |||
exit (1) ; | |||
} | |||
else if (argc > 4) | |||
_doLoadUsage (argv) ; | |||
} | |||
else if (strcasecmp (argv [2], "i2c") == 0) | |||
{ | |||
module1 = "i2c_dev" ; | |||
module2 = "i2c_bcm2708" ; | |||
file1 = "/dev/i2c-0" ; | |||
file2 = "/dev/i2c-1" ; | |||
if (argc == 4) | |||
sprintf (args2, " baudrate=%d", atoi (argv [3]) * 1000) ; | |||
else if (argc > 4) | |||
_doLoadUsage (argv) ; | |||
} | |||
else | |||
_doLoadUsage (argv) ; | |||
if (findExecutable ("modprobe") == NULL) | |||
printf ("No found\n") ; | |||
if (!moduleLoaded (module1)) | |||
{ | |||
sprintf (cmd, "%s %s%s", findExecutable (MODPROBE), module1, args1) ; | |||
int ret = system(cmd); | |||
if (ret == -1) { | |||
perror("Error executing command"); | |||
} else if (WIFEXITED(ret)) { | |||
int exit_status = WEXITSTATUS(ret); | |||
if (exit_status != 0) { | |||
fprintf(stderr, "Command failed with exit status %d\n", exit_status); | |||
} | |||
} else { | |||
fprintf(stderr, "Command terminated by signal\n"); | |||
} | |||
} | |||
if (!moduleLoaded (module2)) | |||
{ | |||
sprintf (cmd, "%s %s%s", findExecutable (MODPROBE), module2, args2) ; | |||
int ret = system(cmd); | |||
if (ret == -1) { | |||
perror("Error executing command"); | |||
} else if (WIFEXITED(ret)) { | |||
int exit_status = WEXITSTATUS(ret); | |||
if (exit_status != 0) { | |||
fprintf(stderr, "Command failed with exit status %d\n", exit_status); | |||
} | |||
} else { | |||
fprintf(stderr, "Command terminated by signal\n"); | |||
} | |||
} | |||
if (!moduleLoaded (module2)) | |||
{ | |||
fprintf (stderr, "%s: Unable to load %s\n", argv [0], module2) ; | |||
exit (1) ; | |||
} | |||
sleep (1) ; // To let things get settled | |||
changeOwner (argv [0], file1) ; | |||
changeOwner (argv [0], file2) ; | |||
} | |||
/* | |||
* doUnLoad: | |||
* Un-Load either the spi or i2c modules and change device ownerships, etc. | |||
********************************************************************************* | |||
*/ | |||
static void _doUnLoadUsage (char *argv []) | |||
{ | |||
fprintf (stderr, "Usage: %s unload <spi/i2c>\n", argv [0]) ; | |||
exit (1) ; | |||
} | |||
static void doUnLoad (int argc, char *argv []) | |||
{ | |||
char *module1, *module2 ; | |||
char cmd [80] ; | |||
checkDevTree (argv) ; | |||
if (argc != 3) | |||
_doUnLoadUsage (argv) ; | |||
/**/ if (strcasecmp (argv [2], "spi") == 0) | |||
{ | |||
module1 = "spidev" ; | |||
module2 = "spi_bcm2708" ; | |||
} | |||
else if (strcasecmp (argv [2], "i2c") == 0) | |||
{ | |||
module1 = "i2c_dev" ; | |||
module2 = "i2c_bcm2708" ; | |||
} | |||
else | |||
_doUnLoadUsage (argv) ; | |||
if (moduleLoaded (module1)) | |||
{ | |||
sprintf (cmd, "%s %s", findExecutable (RMMOD), module1) ; | |||
int ret = system(cmd); | |||
if (ret == -1) { | |||
perror("Error executing command"); | |||
} else if (WIFEXITED(ret)) { | |||
int exit_status = WEXITSTATUS(ret); | |||
if (exit_status != 0) { | |||
fprintf(stderr, "Command failed with exit status %d\n", exit_status); | |||
} | |||
} else { | |||
fprintf(stderr, "Command terminated by signal\n"); | |||
} | |||
} | |||
if (moduleLoaded (module2)) | |||
{ | |||
sprintf (cmd, "%s %s", findExecutable (RMMOD), module2) ; | |||
int ret = system(cmd); | |||
if (ret == -1) { | |||
perror("Error executing command"); | |||
} else if (WIFEXITED(ret)) { | |||
int exit_status = WEXITSTATUS(ret); | |||
if (exit_status != 0) { | |||
fprintf(stderr, "Command failed with exit status %d\n", exit_status); | |||
} | |||
} else { | |||
fprintf(stderr, "Command terminated by signal\n"); | |||
} | |||
} | |||
} | |||
/* | |||
* doI2Cdetect: | |||
@@ -398,28 +113,19 @@ static void doUnLoad (int argc, char *argv []) | |||
********************************************************************************* | |||
*/ | |||
static void doI2Cdetect (UNU int argc, char *argv []) | |||
static void doI2Cdetect (const char *progName) | |||
{ | |||
int port = piGpioLayout () == GPIO_LAYOUT_PI1_REV1 ? 0 : 1 ; | |||
char *c, *command ; | |||
char command[64]; | |||
if ((c = findExecutable (I2CDETECT)) == NULL) | |||
{ | |||
fprintf (stderr, "%s: Unable to find i2cdetect command: %s\n", argv [0], strerror (errno)) ; | |||
return ; | |||
snprintf(command, 64, "i2cdetect -y %d", port); | |||
int ret = system(command); | |||
if (ret < 0) { | |||
fprintf (stderr, "%s: Unable to run i2cdetect: %s\n", progName, strerror(errno)); | |||
} | |||
if (!moduleLoaded ("i2c_dev")) | |||
{ | |||
fprintf (stderr, "%s: The I2C kernel module(s) are not loaded.\n", argv [0]) ; | |||
return ; | |||
if (0x7F00 == (ret & 0xFF00)) { | |||
fprintf (stderr, "%s: i2cdetect not found, please install i2c-tools\n", progName); | |||
} | |||
command = malloc (strlen (c) + 16) ; | |||
sprintf (command, "%s -y %d", c, port) ; | |||
if (system (command) < 0) | |||
fprintf (stderr, "%s: Unable to run i2cdetect: %s\n", argv [0], strerror (errno)) ; | |||
} | |||
@@ -427,6 +133,10 @@ void SYSFS_DEPRECATED(const char *progName) { | |||
fprintf(stderr, "%s: GPIO Sysfs Interface for Userspace is deprecated (https://www.kernel.org/doc/Documentation/gpio/sysfs.txt).\n Function is now useless and empty.\n\n", progName); | |||
} | |||
void LOAD_DEPRECATED(const char *progName) { | |||
fprintf(stderr, "%s: load/unload modules is deprecated. You need to run the raspi-config program (as root) and select the interface option (SPI or I2C) that you wish to de-/activate.\n\n", progName); | |||
} | |||
/* | |||
* doExports: -> deprecated, removed | |||
* List all GPIO exports | |||
@@ -1269,7 +979,7 @@ int main (int argc, char *argv []) | |||
exit (EXIT_FAILURE) ; | |||
} | |||
// Initial test for /sys/class/gpio operations: - -> deprecated, empty but still there | |||
// Initial test for /sys/class/gpio operations: --> deprecated, empty but still there | |||
/**/ if (strcasecmp (argv [1], "exports" ) == 0) { SYSFS_DEPRECATED(argv[0]); return 0 ; } | |||
else if (strcasecmp (argv [1], "export" ) == 0) { SYSFS_DEPRECATED(argv[0]); return 0 ; } | |||
@@ -1277,10 +987,10 @@ int main (int argc, char *argv []) | |||
else if (strcasecmp (argv [1], "unexport" ) == 0) { SYSFS_DEPRECATED(argv[0]); return 0 ; } | |||
else if (strcasecmp (argv [1], "unexportall") == 0) { SYSFS_DEPRECATED(argv[0]); return 0 ; } | |||
// Check for load command: | |||
// Check for un-/load command: --> deprecated, empty but still there | |||
if (strcasecmp (argv [1], "load" ) == 0) { doLoad (argc, argv) ; return 0 ; } | |||
if (strcasecmp (argv [1], "unload" ) == 0) { doUnLoad (argc, argv) ; return 0 ; } | |||
if (strcasecmp (argv [1], "load" ) == 0) { LOAD_DEPRECATED(argv[0]) ; return 0 ; } | |||
if (strcasecmp (argv [1], "unload" ) == 0) { LOAD_DEPRECATED(argv[0]) ; return 0 ; } | |||
// Check for usb power command | |||
@@ -1413,8 +1123,8 @@ int main (int argc, char *argv []) | |||
else if (strcasecmp (argv [1], "nreadall" ) == 0) doReadall () ; | |||
else if (strcasecmp (argv [1], "pins" ) == 0) doReadall () ; | |||
else if (strcasecmp (argv [1], "qmode" ) == 0) doQmode (argc, argv) ; | |||
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], "i2cdetect") == 0) doI2Cdetect (argv [0]) ; | |||
else if (strcasecmp (argv [1], "i2cd" ) == 0) doI2Cdetect (argv [0]) ; | |||
else if (strcasecmp (argv [1], "reset" ) == 0) doReset (argv [0]) ; | |||
else if (strcasecmp (argv [1], "wb" ) == 0) doWriteByte (argc, argv) ; | |||
else if (strcasecmp (argv [1], "rbx" ) == 0) doReadByte (argc, argv, TRUE) ; | |||
@@ -1,3 +1,3 @@ | |||
#define VERSION "3.4" | |||
#define VERSION "3.6" | |||
#define VERSION_MAJOR 3 | |||
#define VERSION_MINOR 4 | |||
#define VERSION_MINOR 6 |
@@ -1,7 +1,7 @@ | |||
/* | |||
* pcf8574.c: | |||
* Extend wiringPi with the PCF8574 I2C GPIO expander chip | |||
* Copyright (c) 2013 Gordon Henderson | |||
* Copyright (c) 2013-2024 Gordon Henderson and contributors | |||
*********************************************************************** | |||
* This file is part of wiringPi: | |||
* https://github.com/WiringPi/WiringPi/ | |||
@@ -33,8 +33,9 @@ | |||
/* | |||
* myPinMode: | |||
* The PCF8574 is an odd chip - the pins are effectively bi-directional, | |||
* however the pins should be drven high when used as an input pin... | |||
* The PCF8574 is a 8-Bit I/O Expander with Open-drain output. | |||
* The pins are effectively bi-directional, | |||
* however the pins should be driven high when used as an input pin... | |||
* So, we're effectively copying digitalWrite... | |||
********************************************************************************* | |||
*/ | |||
@@ -102,7 +103,7 @@ static int myDigitalRead (struct wiringPiNodeStruct *node, int pin) | |||
* pcf8574Setup: | |||
* Create a new instance of a PCF8574 I2C GPIO interface. We know it | |||
* has 8 pins, so all we need to know here is the I2C address and the | |||
* user-defined pin base. | |||
* user-defined pin base. Default address (A0-A3 low) is 0x20. | |||
********************************************************************************* | |||
*/ | |||
@@ -4,7 +4,11 @@ LDFLAGS = | |||
tests = wiringpi_test1_sysfs wiringpi_test2_sysfs wiringpi_test3_device_wpi wiringpi_test4_device_phys wiringpi_test5_default wiringpi_test6_isr wiringpi_test7_version | |||
all: $(tests) | |||
xotests = wiringpi_xotest_test1_spi | |||
i2ctests = wiringpi_i2c_test1_pcf8574 | |||
all: $(tests) $(xotests) $(i2ctests) | |||
wiringpi_test1_sysfs: | |||
${CC} ${CFLAGS} wiringpi_test1_sysfs.c -o wiringpi_test1_sysfs -lwiringPi | |||
@@ -27,12 +31,61 @@ wiringpi_test6_isr: | |||
wiringpi_test7_version: | |||
${CC} ${CFLAGS} wiringpi_test7_version.c -o wiringpi_test7_version -lwiringPi | |||
wiringpi_xotest_test1_spi: | |||
${CC} ${CFLAGS} wiringpi_xotest_test1_spi.c -o wiringpi_xotest_test1_spi -lwiringPi | |||
wiringpi_i2c_test1_pcf8574: | |||
${CC} ${CFLAGS} wiringpi_i2c_test1_pcf8574.c -o wiringpi_i2c_test1_pcf8574 -lwiringPi | |||
test: | |||
@error_state=false ; \ | |||
for t in $(tests) ; do \ | |||
echo === unit test: $${t} === ; \ | |||
time ./$${t}; \ | |||
if [ $$? -ne 0 ]; then \ | |||
error_state=true ; \ | |||
fi ; \ | |||
echo ; echo ; \ | |||
done ; \ | |||
if [ "$$error_state" = true ]; then \ | |||
echo "\n\e[5mSTD TEST FAILED\e[0m\n"; \ | |||
else \ | |||
echo "\n\e[5mSTD TEST SUCCESS\e[0m\n"; \ | |||
fi | |||
xotest: | |||
@error_state=false ; \ | |||
for t in $(tests) $(xotests) ; do \ | |||
echo === XO unit test: $${t} === ; \ | |||
time ./$${t} ; \ | |||
if [ $$? -ne 0 ]; then \ | |||
error_state=true ; \ | |||
fi ; \ | |||
echo ; echo ; \ | |||
done | |||
if [ "$$error_state" = true ]; then \ | |||
echo "\n\e[5mSTD/XO TEST FAILED\e[0m\n"; \ | |||
else \ | |||
echo "\n\e[5mSTD/XO TEST SUCCESS\e[0m\n"; \ | |||
fi | |||
i2ctest: | |||
@error_state=false ; \ | |||
for t in $(tests) $(i2ctests) ; do \ | |||
echo === I2C unit test: $${t} === ; \ | |||
time ./$${t} ; \ | |||
if [ $$? -ne 0 ]; then \ | |||
error_state=true ; \ | |||
fi ; \ | |||
echo ; echo ; \ | |||
done | |||
if [ "$$error_state" = true ]; then \ | |||
echo "\n\e[5mSTD/I2C TEST FAILED\e[0m\n"; \ | |||
else \ | |||
echo "\n\e[5mSTD/I2C TEST SUCCESS\e[0m\n"; \ | |||
fi | |||
clean: | |||
for t in $(tests) ; do rm -fv $${t} ; done | |||
for t in $(tests) $(xotests) $(i2ctests) ; do \ | |||
rm -fv $${t} ; \ | |||
done |
@@ -0,0 +1,112 @@ | |||
// WiringPi test program: I2C functions (need PCF8574) | |||
// Compile: gcc -Wall wiringpi_i2c_test1.c -o wiringpi_i2c_test1 -lwiringPi | |||
#include "wpi_test.h" | |||
#include "pcf8574.h" | |||
#include "wiringPiI2C.h" | |||
const int pinBase = 1020; | |||
const int i2cAdress = 0x20; | |||
int ShowAll() { | |||
int in; | |||
int value = 0; | |||
printf("pin: 0 1 2 3 4 5 6 7\nval: "); | |||
for (int pin=0; pin<=7; ++pin) { | |||
in = digitalRead(pinBase + pin); | |||
printf("%d ", in); | |||
if(in==HIGH) { value |= (0x01<<pin); } | |||
} | |||
printf(" = 0x%02X\n", value); | |||
return value; | |||
} | |||
void testPin(const char* msg, int fd, int pin , int value) { | |||
printf("%s:\n", msg); | |||
int in = digitalRead(pinBase + pin); | |||
CheckSame("digitalRead", in, value); | |||
int expect = HIGH==value ? (0x1<<pin) : 0; | |||
int pinmask = 0x01<<pin; | |||
int i2cread = wiringPiI2CRead(fd); | |||
CheckSame("wiringPiI2CRead", i2cread & pinmask, expect); | |||
//printf("Value = 0x%X\n",i2cread); | |||
uint8_t i2cvalue = HIGH==value ? 0x00 : 0xFF; | |||
int result = wiringPiI2CRawRead(fd, &i2cvalue, 1); | |||
CheckSame("wiringPiI2CRawRead result", result, 1); | |||
CheckSame("wiringPiI2CRawRead", i2cvalue & pinmask, expect); | |||
//printf("Value = 0x%X\n",i2cvalue); | |||
} | |||
int main (void) { | |||
int major, minor; | |||
wiringPiVersion(&major, &minor); | |||
printf("Testing I2C functions with PCF8574 (WiringPi %d.%d)\n",major, minor); | |||
printf("-------------------------------------------------\n\n"); | |||
int ret = pcf8574Setup (pinBase, i2cAdress); | |||
if (ret!=1) { | |||
FailAndExitWithErrno("pcf8574Setup", ret); | |||
} | |||
int fd = wiringPiI2CSetup (i2cAdress); | |||
if (fd<=0) { | |||
FailAndExitWithErrno("wiringPiI2CSetup", fd); | |||
} | |||
CheckSame("I2C fd", fd, 4); | |||
ShowAll(); | |||
int pin = 3; | |||
testPin("Test pin 3 high", fd, pin , HIGH); | |||
testPin("Test pin 4 high", fd, pin+1, HIGH); | |||
digitalWrite(pinBase + pin, LOW); | |||
testPin("Test pin 3 low", fd, pin , LOW); | |||
testPin("Test pin 4 high", fd, pin+1, HIGH); | |||
ShowAll(); | |||
digitalWrite(pinBase + pin, HIGH); | |||
testPin("Test pin 3 high", fd, pin , HIGH); | |||
testPin("Test pin 4 high", fd, pin+1, HIGH); | |||
ShowAll(); | |||
printf("\nwiringPiI2CReadReg8:\n"); | |||
int i2cin, expect; | |||
i2cin = wiringPiI2CReadReg8(fd, 0x00); | |||
expect = ShowAll(); | |||
CheckSame("all low wiringPiI2CReadReg8", i2cin, expect); | |||
i2cin = wiringPiI2CReadReg8(fd, 0xFF); | |||
expect =ShowAll(); | |||
CheckSame("all high wiringPiI2CReadReg8", i2cin, expect); | |||
printf("\nwiringPiI2CReadBlockData:\n"); | |||
uint8_t value; | |||
int result; | |||
value = 0xFF; | |||
result = wiringPiI2CReadBlockData(fd, 0x00, &value, 1); | |||
CheckSame("wiringPiI2CReadBlockData result", result, 1); | |||
expect = ShowAll(); | |||
CheckSame("all high wiringPiI2CReadBlockData", value, expect); | |||
printf("\n"); | |||
value = 0x00; | |||
result = wiringPiI2CReadBlockData(fd, 0xFF, &value, 1); | |||
CheckSame("wiringPiI2CReadBlockData result", result, 1); | |||
expect = ShowAll(); | |||
CheckSame("all low wiringPiI2CReadBlockData", value, expect); | |||
return UnitTestState(); | |||
} | |||
@@ -0,0 +1,112 @@ | |||
// WiringPi test program: SPI functions (need MCP3202 hardware @ CE1, ch0=Vdd, ch1=Vdd/2) | |||
// Compile: gcc -Wall wiringpi_spi_test1_mcp3202.c -o wiringpi_spi_test1_mcp3202 -lwiringPi | |||
#include <unistd.h> | |||
#include <stdint.h> | |||
#include <signal.h> | |||
#include <time.h> | |||
#include "wpi_test.h" | |||
#include <wiringPiSPI.h> | |||
const float fRefVoltage = 3.3f; | |||
const float fResolution = 4096; //12-Bit | |||
const int spiChannel = 1; | |||
const int spiSpeedInit = 250000; // Hz | |||
int AnalogRead(int spiChannel, int analogChannel, int* returnvalue) { | |||
if (analogChannel<0 || analogChannel>1) { | |||
return -1; | |||
} | |||
unsigned char spiData[3]; | |||
unsigned char chanBits; | |||
if (analogChannel == 0) { | |||
chanBits = 0b11010000; | |||
} else { | |||
chanBits = 0b11110000; | |||
} | |||
spiData[0] = chanBits; | |||
spiData[1] = 0; | |||
spiData[2] = 0; | |||
*returnvalue = wiringPiSPIxDataRW(0, spiChannel, spiData, 3); | |||
return ((spiData [0] << 9) | (spiData [1] << 1) | (spiData[2] >> 7)) & 0xFFF; | |||
} | |||
int main(int argc, char *argv []){ | |||
int hSPI; | |||
int CH0,CH1; | |||
float value0, value1; | |||
int returnvalue; | |||
int spiSpeed; | |||
int major, minor; | |||
wiringPiVersion(&major, &minor); | |||
printf("Testing SPI functions with WiringPi %d.%d\n",major, minor); | |||
printf("------------------------------------------\n\n"); | |||
wiringPiSetup(); | |||
spiSpeed = spiSpeedInit; | |||
for (int testno=0; testno<=2; testno++) { | |||
printf("\nTest 5d with %g MHz SPI Speed\n", spiSpeed/1000000.0f); | |||
if ((hSPI = wiringPiSPISetup (spiChannel, spiSpeed)) < 0) { | |||
FailAndExitWithErrno("wiringPiSPISetup", hSPI); | |||
} | |||
int hSPIOld=hSPI; | |||
//printf("\nSPI fd = %d\n call close now\n", hSPI); | |||
int ret = wiringPiSPIClose(spiChannel); | |||
if (ret!=0) { | |||
FailAndExitWithErrno("wiringPiSPIClose", ret); | |||
} | |||
if ((hSPI = wiringPiSPIxSetupMode(0, spiChannel, spiSpeed, 0)) < 0) { | |||
FailAndExitWithErrno("wiringPiSPIxSetup", hSPI); | |||
} | |||
CheckSame("SPISetup, Close and SPIxSetup handle", hSPI, hSPIOld); | |||
delayMicroseconds(500000); | |||
returnvalue = -1; | |||
CH0 = AnalogRead(spiChannel, 0, &returnvalue); | |||
CheckSame("CH0 wiringPiSPIxDataRW return", returnvalue, 3); | |||
value0 = CH0 * fRefVoltage / fResolution; | |||
CheckSameFloat("CH0 value (VDD)", value0, 3.3f); | |||
printf("\n"); | |||
delayMicroseconds(500000); | |||
returnvalue = -1; | |||
CH1 = AnalogRead(spiChannel, 1, &returnvalue); | |||
CheckSame("CH1 wiringPiSPIxDataRW return", returnvalue, 3); | |||
value1 = CH1 * fRefVoltage / fResolution; | |||
CheckSameFloat("CH1 value (1/2)", value1, 1.65f); | |||
printf("\n"); | |||
ret = wiringPiSPIxClose(0, spiChannel); | |||
CheckSame("wiringPiSPIxClose result", ret, 0); | |||
if (ret!=0) { | |||
FailAndExitWithErrno("wiringPiSPIxClose", ret); | |||
} | |||
ret = wiringPiSPIxGetFd(0, spiChannel); | |||
CheckSame("Fd after wiringPiSPIxGetFd", ret, -1); | |||
ret = wiringPiSPIGetFd(spiChannel); | |||
CheckSame("Fd after wiringPiSPIGetFd", ret, -1); | |||
spiSpeed += spiSpeed; | |||
} | |||
printf("\n"); | |||
hSPI = wiringPiSPISetup (3, spiSpeedInit); | |||
CheckSame("\nwiringPiSPISetup with wrong channel", hSPI, -22); | |||
// will result in exit! - not useful in test code | |||
//hSPI = wiringPiSPIxSetupMode (3, 0, spiSpeedInit,0); | |||
//CheckSame("\nwiringPiSPISetup with wrong channel", hSPI, -22); | |||
return UnitTestState(); | |||
} | |||
@@ -2,9 +2,7 @@ | |||
// Compile: gcc -Wall wiringpi_test1_device.c -o wiringpi_test1_device -lwiringPi | |||
#include "wpi_test.h" | |||
#include <stdlib.h> | |||
#include <signal.h> | |||
#include <string.h> | |||
#include <time.h> | |||
#include <sys/time.h> | |||
@@ -52,6 +50,6 @@ int main (void) { | |||
//Error wrong direction - only for fun | |||
digitalWrite(GPIO, LOW); | |||
return(EXIT_SUCCESS); | |||
return UnitTestState(); | |||
} | |||
@@ -2,9 +2,7 @@ | |||
// Compile: gcc -Wall wiringpi_test2_device.c -o wiringpi_test2_device -lwiringPi | |||
#include "wpi_test.h" | |||
#include <stdlib.h> | |||
#include <signal.h> | |||
#include <string.h> | |||
#include <time.h> | |||
#include <sys/time.h> | |||
@@ -50,5 +48,5 @@ int main (void) { | |||
CheckGPIO(GPIO, GPIOIN, LOW); | |||
delayMicroseconds(600000); | |||
return(EXIT_SUCCESS); | |||
return UnitTestState(); | |||
} |
@@ -2,9 +2,7 @@ | |||
// Compile: gcc -Wall wiringpi_test3_device.c -o wiringpi_test3_device -lwiringPi | |||
#include "wpi_test.h" | |||
#include <stdlib.h> | |||
#include <signal.h> | |||
#include <string.h> | |||
#include <time.h> | |||
#include <sys/time.h> | |||
@@ -50,5 +48,5 @@ int main (void) { | |||
CheckGPIO(GPIO, GPIOIN, LOW); | |||
delayMicroseconds(600000); | |||
return(EXIT_SUCCESS); | |||
return UnitTestState(); | |||
} |
@@ -2,9 +2,7 @@ | |||
// Compile: gcc -Wall wiringpi_test4_device.c -o wiringpi_test4_device -lwiringPi | |||
#include "wpi_test.h" | |||
#include <stdlib.h> | |||
#include <signal.h> | |||
#include <string.h> | |||
#include <time.h> | |||
#include <sys/time.h> | |||
@@ -50,5 +48,5 @@ int main (void) { | |||
CheckGPIO(GPIO, GPIOIN, LOW); | |||
delayMicroseconds(600000); | |||
return(EXIT_SUCCESS); | |||
return UnitTestState(); | |||
} |
@@ -2,9 +2,7 @@ | |||
// Compile: gcc -Wall wiringpi_test1_device.c -o wiringpi_test1_device -lwiringPi | |||
#include "wpi_test.h" | |||
#include <stdlib.h> | |||
#include <signal.h> | |||
#include <string.h> | |||
#include <time.h> | |||
#include <sys/time.h> | |||
@@ -12,6 +10,34 @@ | |||
const int GPIO = 19; | |||
const int GPIOIN = 26; | |||
const int ToggleValue = 4; | |||
int RaspberryPiModel = -1; | |||
void SetAndCheckMode(int pin, int mode) { | |||
enum WPIPinAlt AltGpio = WPI_ALT_UNKNOWN; | |||
switch(mode) { | |||
case INPUT: | |||
pinMode(pin, INPUT); | |||
AltGpio = getPinModeAlt(pin); | |||
CheckSame("Pin mode input", AltGpio, WPI_ALT_INPUT); | |||
break; | |||
case OUTPUT: | |||
pinMode(pin, OUTPUT); | |||
AltGpio = getPinModeAlt(pin); | |||
CheckSame("Pin mode output", AltGpio, WPI_ALT_OUTPUT); | |||
break; | |||
case PM_OFF: | |||
pinMode(pin, PM_OFF); | |||
AltGpio = getPinModeAlt(pin); | |||
CheckSame("Pin mode off(input)", AltGpio, (PI_MODEL_5 == RaspberryPiModel) ? WPI_NONE : WPI_ALT_INPUT); | |||
break; | |||
default: | |||
pinMode(pin, mode); | |||
printf("pinmode %d of pin %d not checked", mode, pin); | |||
break; | |||
} | |||
} | |||
int main (void) { | |||
@@ -23,8 +49,23 @@ int main (void) { | |||
printf("wiringPiSetupGpio failed\n\n"); | |||
exit(EXIT_FAILURE); | |||
} | |||
pinMode(GPIOIN, INPUT); | |||
pinMode(GPIO, OUTPUT); | |||
int rev, mem, maker, overVolted; | |||
piBoardId(&RaspberryPiModel, &rev, &mem, &maker, &overVolted); | |||
CheckNotSame("Model: ", RaspberryPiModel, -1); | |||
if (PI_MODEL_5 == RaspberryPiModel) { | |||
printf("Raspberry Pi 5 with RP1 found\n"); | |||
} else { | |||
printf("Raspberry Pi with BCM GPIO found (not Pi 5)\n"); | |||
} | |||
enum WPIPinAlt AltGpio = WPI_ALT_UNKNOWN; | |||
AltGpio = getPinModeAlt(23); | |||
CheckSame("Pin mode default", AltGpio, PI_MODEL_5 == RaspberryPiModel ? WPI_NONE : WPI_ALT_INPUT); | |||
SetAndCheckMode(GPIOIN, INPUT); | |||
SetAndCheckMode(GPIO, OUTPUT); | |||
printf("toggle %d times ...\n", ToggleValue); | |||
for (int loop=1; loop<ToggleValue; loop++) { | |||
@@ -38,7 +79,9 @@ int main (void) { | |||
printf("\nWiringPi GPIO test program (using GPIO%d (input pull up/down) and GPIO%d (input))\n", GPIO, GPIOIN); | |||
pullUpDnControl (GPIO, PUD_UP); | |||
pinMode(GPIO, INPUT); | |||
SetAndCheckMode(GPIO, INPUT); | |||
delayMicroseconds(3000000); | |||
pullUpDnControl (GPIOIN, PUD_OFF); | |||
@@ -52,6 +95,11 @@ int main (void) { | |||
//Error wrong direction - only for fun | |||
digitalWrite(GPIO, LOW); | |||
return(EXIT_SUCCESS); | |||
} | |||
SetAndCheckMode(GPIO, OUTPUT); | |||
SetAndCheckMode(GPIO, PM_OFF); | |||
//pinModeAlt (GPIO, 0x1F); | |||
//AltGpio = getPinModeAlt(GPIO); | |||
//CheckSame("Pin mode off(default)", AltGpio, 0x1F); | |||
return UnitTestState(); | |||
} |
@@ -4,7 +4,6 @@ | |||
#include "wpi_test.h" | |||
#include <string.h> | |||
#include <errno.h> | |||
#include <stdlib.h> | |||
#include <unistd.h> | |||
#include <sys/time.h> | |||
@@ -166,5 +165,5 @@ int main (void) { | |||
} | |||
pinMode(OUTpin, INPUT); | |||
return 0 ; | |||
return UnitTestState(); | |||
} |
@@ -8,4 +8,6 @@ int main (void) { | |||
CheckSame("version major", major, VERSION_MAJOR); | |||
CheckSame("version minor", minor, VERSION_MINOR); | |||
return UnitTestState(); | |||
} |
@@ -0,0 +1,178 @@ | |||
// WiringPi test program: SPI functions (need XO hardware) | |||
// Compile: gcc -Wall wiringpi_xotest_test1_spi.c -o wiringpi_xotest_test1_spi -lwiringPi | |||
#include <unistd.h> | |||
#include <stdint.h> | |||
#include <signal.h> | |||
#include <time.h> | |||
#include "wpi_test.h" | |||
#include <wiringPiSPI.h> | |||
#define TRUE (1==1) | |||
#define FALSE (!TRUE) | |||
#define CHAN_CONFIG_SINGLE 8 | |||
#define CHAN_CONFIG_DIFF 0 | |||
const float fRefVoltage = 3.3f; | |||
const float fResolution = 4096; //12-Bit | |||
const int spiChannel = 1; | |||
const int spiSpeed = 1000000; // MHz | |||
int AnalogRead(int spiChannel, int analogChannel, int* returnvalue) { | |||
if (analogChannel<0 || analogChannel>1) { | |||
return -1; | |||
} | |||
unsigned char spiData[3]; | |||
unsigned char chanBits; | |||
if (analogChannel == 0) { | |||
chanBits = 0b11010000; | |||
} else { | |||
chanBits = 0b11110000; | |||
} | |||
spiData[0] = chanBits; | |||
spiData[1] = 0; | |||
spiData[2] = 0; | |||
*returnvalue = wiringPiSPIxDataRW(0, spiChannel, spiData, 3); | |||
return ((spiData [0] << 9) | (spiData [1] << 1) | (spiData[2] >> 7)) & 0xFFF; | |||
} | |||
void checkVoltage(float expect, const char* szexpect) { | |||
int returnvalue; | |||
//int CH0 = AnalogRead(spiChannel, 0, &returnvalue); | |||
int CH1 = AnalogRead(spiChannel, 1, &returnvalue); | |||
//float value0 = CH0 * fRefVoltage / fResolution; | |||
float value1 = CH1 * fRefVoltage / fResolution; | |||
CheckSameFloat(szexpect, value1, expect); | |||
delayMicroseconds(300); | |||
} | |||
int main(int argc, char *argv []){ | |||
const int GPIOIn = 29; | |||
int hSPI; | |||
//int CH0; | |||
int CH1; | |||
int major, minor; | |||
wiringPiVersion(&major, &minor); | |||
printf("Testing SPI functions with WiringPi %d.%d\n",major, minor); | |||
printf("------------------------------------------\n\n"); | |||
wiringPiSetup(); | |||
if ((hSPI = wiringPiSPISetup (spiChannel, spiSpeed)) < 0) { | |||
FailAndExitWithErrno("wiringPiSPISetup", hSPI); | |||
} | |||
int hSPIOld=hSPI; | |||
//printf("\nSPI fd = %d\n call close now\n", hSPI); | |||
int ret = wiringPiSPIClose(spiChannel); | |||
if (ret!=0) { | |||
FailAndExitWithErrno("wiringPiSPIClose", ret); | |||
} | |||
if ((hSPI = wiringPiSPIxSetupMode(0, spiChannel, spiSpeed, 0)) < 0) { | |||
FailAndExitWithErrno("wiringPiSPIxSetup", hSPI); | |||
} | |||
CheckSame("SPISetup, Close and SPIxSetup handle", hSPI, hSPIOld); | |||
int returnvalue; | |||
//CH0 = AnalogRead(spiChannel, 0, &returnvalue); | |||
CH1 = AnalogRead(spiChannel, 1, &returnvalue); | |||
CheckSame("SPI reading ioctl result (byte count) ", returnvalue, 3); | |||
//float value0 = CH0 * fRefVoltage / fResolution; | |||
//float value1 = CH1 * fRefVoltage / fResolution; | |||
pinMode(21, OUTPUT); | |||
pinMode(22, INPUT); | |||
pinMode(24, INPUT); | |||
pinMode(25, INPUT); | |||
pinMode(27, INPUT); | |||
pinMode(28, INPUT); | |||
pinMode(GPIOIn, INPUT); | |||
digitalWriteEx(21, GPIOIn, LOW); | |||
checkVoltage(0.1f, "Analog value 1xLow"); | |||
checkVoltage(0.1f, "Analog value 1xLow"); | |||
digitalWriteEx(21, GPIOIn, HIGH); | |||
checkVoltage(3.1f, "Analog value 1xHigh"); | |||
pinMode(22, OUTPUT); | |||
digitalWriteEx(22, -1, LOW); | |||
checkVoltage(1.65f, "Analog value Half (1H/1L)"); | |||
digitalWriteEx(22, GPIOIn, HIGH); | |||
checkVoltage(3.2f, "Analog value 2xHigh"); | |||
pinMode(24, OUTPUT); | |||
digitalWriteEx(24, GPIOIn, HIGH); | |||
checkVoltage(3.2f, "Analog value 3xHigh"); | |||
digitalWriteEx(24, -1, LOW); | |||
checkVoltage(2.2f, "Analog value 2xHigh/1xLow"); | |||
checkVoltage(2.2f, "Analog value 2xHigh/1xLow"); | |||
pinMode(25, OUTPUT); | |||
digitalWriteEx(25, GPIOIn, HIGH); | |||
checkVoltage(2.475f, "Analog value 3xHigh/1xLow"); | |||
digitalWriteEx(25, -1, LOW); | |||
checkVoltage(1.65f, "Analog value Half (2H/2L)"); | |||
pinMode(27, OUTPUT); | |||
digitalWriteEx(27, GPIOIn, HIGH); | |||
checkVoltage(1.98f, "Analog value 3xHigh/2xLow"); | |||
digitalWriteEx(27, -1, LOW); | |||
checkVoltage(1.32f, "Analog value Half (2H/3L)"); | |||
pinMode(28, OUTPUT); | |||
digitalWriteEx(28, GPIOIn, LOW); | |||
checkVoltage(1.100f, "Analog value 2xHigh/4xLow"); | |||
digitalWriteEx(28, GPIOIn, HIGH); | |||
checkVoltage(1.65f, "Analog value Half (3H/3L)"); | |||
digitalWriteEx(27, GPIOIn, HIGH); | |||
checkVoltage(2.2f, "Analog value 4xHigh/2xLow"); | |||
digitalWriteEx(25, GPIOIn, HIGH); | |||
checkVoltage(2.75f, "Analog value 5xHigh/1xLow"); | |||
digitalWriteEx(24, GPIOIn, HIGH); | |||
checkVoltage(3.3f, "Analog value 6xHigh"); | |||
CH1 = AnalogRead(3, 1, &returnvalue); | |||
CheckSame("\nReading Wrong channel 3 result ", CH1, 0); | |||
CheckSame("\nReading Wrong channel 3 ioctl result ", returnvalue, -EINVAL); | |||
CH1 = AnalogRead(2, 1, &returnvalue); | |||
CheckSame("\nReading Wrong channel 2 result ", CH1, 0); | |||
CheckSame("\nReading Wrong channel 3 ioctl result ", returnvalue, -EBADF); | |||
pinMode(22, INPUT); | |||
pinMode(21, INPUT); | |||
pinMode(24, INPUT); | |||
pinMode(25, INPUT); | |||
pinMode(27, INPUT); | |||
pinMode(28, INPUT); | |||
ret = wiringPiSPIxClose(0, spiChannel); | |||
CheckSame("wiringPiSPIxClose result", ret, 0); | |||
if (ret!=0) { | |||
FailAndExitWithErrno("wiringPiSPIxClose", ret); | |||
} | |||
ret = wiringPiSPIxGetFd(0, spiChannel); | |||
CheckSame("Fd after close", ret, -1); | |||
return UnitTestState(); | |||
} | |||
@@ -1,48 +1,120 @@ | |||
#include <wiringPi.h> | |||
#include <stdio.h> | |||
#include <stdlib.h> | |||
#include <math.h> | |||
#include <errno.h> | |||
#include <string.h> | |||
#define COLORDEF "\x1B[0m" | |||
#define COLORRED "\x1B[31m" | |||
#define COLORGRN "\x1B[32m" | |||
#define BOLD "\x1B[1m" | |||
#define FINALCOLRED "\x1B[7;49;91m" | |||
#define FINALCOLGRN "\x1B[7;49;32m" | |||
unsigned int globalError = 0; | |||
void CheckGPIO(int GPIO, int GPIOIN, int out) { | |||
int in = digitalRead(GPIOIN); | |||
int read = digitalRead(GPIO); | |||
int pass = 0; | |||
if (out==in && in==read) { | |||
pass = 1; | |||
} | |||
if (pass) { | |||
printf("GPIO%d = %d (GPIO%d = %d) -> %spassed%s\n", GPIOIN, in, GPIO, read, COLORGRN, COLORDEF ); | |||
} else { | |||
printf("GPIO%d = %d (GPIO%d = %d) -> %sfailed%s\n", GPIOIN, in, GPIO, read, COLORRED, COLORDEF ); | |||
} | |||
int in = out; | |||
if (GPIOIN>=0) { | |||
in = digitalRead(GPIOIN); | |||
} | |||
int readback = digitalRead(GPIO); | |||
int pass = 0; | |||
if (out==readback && in==out) { | |||
pass = 1; | |||
} | |||
if (GPIOIN>=0) { | |||
printf("set GPIO%02d = %d (readback %d), in GPIO%02d = %d ", GPIO, out, readback, GPIOIN, in); | |||
} else { | |||
printf("set GPIO%02d = %d (readback %d) ", GPIO, out, readback); | |||
} | |||
if (pass) { | |||
printf("-> %spassed%s\n", COLORGRN, COLORDEF ); | |||
} else { | |||
globalError=1; | |||
printf("-> %sfailed%s\n", COLORRED, COLORDEF ); | |||
} | |||
} | |||
void digitalWriteEx(int GPIO, int GPIOIN, int mode) { | |||
digitalWrite(GPIO, mode); | |||
printf("out = %d ", mode); | |||
delayMicroseconds(5000); | |||
CheckGPIO(GPIO, GPIOIN, mode); | |||
digitalWrite(GPIO, mode); | |||
delayMicroseconds(5000); | |||
CheckGPIO(GPIO, GPIOIN, mode); | |||
} | |||
void pullUpDnControlEx (int GPIO, int GPIOIN, int mode) { | |||
pullUpDnControl (GPIO, mode); | |||
int out = mode==PUD_UP ? 1:0; | |||
printf("in = %4s ", mode==PUD_UP ? "up":"down"); | |||
delayMicroseconds(5000); | |||
CheckGPIO(GPIO, GPIOIN, out); | |||
pullUpDnControl (GPIO, mode); | |||
int out = mode==PUD_UP ? 1:0; | |||
printf("in = %4s ", mode==PUD_UP ? "up":"down"); | |||
delayMicroseconds(5000); | |||
CheckGPIO(GPIO, GPIOIN, out); | |||
} | |||
void CheckSameText(const char* msg, const char* value, const char* expect) { | |||
if (!strcmp(value, expect)) { | |||
printf("%39s (%10s==%10s) -> %spassed%s\n", msg, value, expect, COLORGRN, COLORDEF); | |||
} else { | |||
printf("%39s (%10s<>%10s) -> %sfailed%s\n", msg, value, expect, COLORRED, COLORDEF); | |||
globalError=1; | |||
} | |||
} | |||
void CheckSame(const char* msg, int value, int expect) { | |||
if (value==expect) { | |||
printf("%s -> %spassed%s\n", msg, COLORGRN, COLORDEF ); | |||
} else { | |||
printf("%s -> %sfailed%s\n", msg, COLORRED, COLORDEF ); | |||
} | |||
if (value==expect) { | |||
printf("%39s (% 3d==% 3d) -> %spassed%s\n", msg, value, expect, COLORGRN, COLORDEF); | |||
} else { | |||
printf("%39s (% 3d<>% 3d) -> %sfailed%s\n", msg, value, expect, COLORRED, COLORDEF); | |||
globalError=1; | |||
} | |||
} | |||
void CheckNotSame(const char* msg, int value, int expect) { | |||
if (value!=expect) { | |||
printf("%39s (% 3d<>% 3d) -> %spassed%s\n", msg, value, expect, COLORGRN, COLORDEF); | |||
} else { | |||
printf("%39s (% 3d==% 3d) -> %sfailed%s\n", msg, value, expect, COLORRED, COLORDEF); | |||
globalError=1; | |||
} | |||
} | |||
void CheckSameFloat(const char* msg, float value, float expect) { | |||
if (fabs(value-expect)<0.08) { | |||
printf("%35s (%.3f==%.3f) -> %spassed%s \n", msg, value, expect, COLORGRN, COLORDEF); | |||
} else { | |||
printf("%35s (%.3f<>%.3f) -> %sfailed%s \n" , msg, value, expect, COLORRED, COLORDEF); | |||
globalError=1; | |||
} | |||
} | |||
int UnitTestState() { | |||
printf("\n\nUNIT TEST STATE: "); | |||
if (globalError) { | |||
printf(" %sFAILED%s\n\n", FINALCOLRED, COLORDEF); | |||
return EXIT_FAILURE; | |||
} else { | |||
printf(" %sPASSED%s\n\n", FINALCOLGRN, COLORDEF); | |||
return EXIT_SUCCESS; | |||
} | |||
} | |||
void FailAndExitWithErrno(const char* msg, int ret) { | |||
printf("%s (Return=%d, Err: %s) -> %sfailed%s \n" , msg, ret, strerror(errno), COLORRED, COLORDEF); | |||
globalError=1; | |||
exit(UnitTestState()); | |||
} | |||
@@ -156,8 +156,12 @@ const unsigned int RP1_DEBOUNCE_DEFAULT_VALUE = 4; | |||
const unsigned int RP1_DEBOUNCE_MASK = 0x7f; | |||
const unsigned int RP1_DEBOUNCE_DEFAULT = (RP1_DEBOUNCE_DEFAULT_VALUE << 5); | |||
const unsigned int RP1_IRQRESET = 0x10000000; //CTRL Bit 28 | |||
const unsigned int RP1_PAD_DEFAULT_0TO8 = (0x0B | 0x70); //Slewfast, Schmitt, PullUp, | 12mA, Input enable | |||
const unsigned int RP1_PAD_DEFAULT_FROM9 = (0x07 | 0x70); //Slewfast, Schmitt, PullDown, | 12mA, Input enable | |||
const unsigned int RP1_PAD_IC_DEFAULT_0TO8 = 0x9A; //pull-up, Schmitt | |||
const unsigned int RP1_PAD_IC_DEFAULT_FROM9 = 0x96; //pull-down, Schmitt | |||
const unsigned int RP1_PAD_DRIVE_MASK = 0x00000030; | |||
const unsigned int RP1_INV_PAD_DRIVE_MASK = ~(RP1_PAD_DRIVE_MASK); | |||
@@ -1314,6 +1318,11 @@ int getAlt (int pin) | |||
} | |||
enum WPIPinAlt getPinModeAlt(int pin) { | |||
return (enum WPIPinAlt) getAlt(pin); | |||
} | |||
/* | |||
* pwmSetMode: | |||
* Select the native "balanced" mode, or standard mark:space mode | |||
@@ -1727,11 +1736,16 @@ void pinMode (int pin, int mode) | |||
fSel = gpioToGPFSEL [pin] ; | |||
shift = gpioToShift [pin] ; | |||
if (mode == INPUT) { | |||
if (INPUT==mode || PM_OFF==mode) { | |||
if (PI_MODEL_5 == RaspberryPiModel) { | |||
pads[1+pin] = (pin<=8) ? RP1_PAD_DEFAULT_0TO8 : RP1_PAD_DEFAULT_FROM9; | |||
gpio[2*pin+1] = RP1_FSEL_GPIO | RP1_DEBOUNCE_DEFAULT; // GPIO | |||
rio[RP1_RIO_OE + RP1_CLR_OFFSET] = 1<<pin; // Input | |||
if (INPUT==mode) { | |||
pads[1+pin] = (pin<=8) ? RP1_PAD_DEFAULT_0TO8 : RP1_PAD_DEFAULT_FROM9; | |||
gpio[2*pin+1] = RP1_FSEL_GPIO | RP1_DEBOUNCE_DEFAULT; // GPIO | |||
rio[RP1_RIO_OE + RP1_CLR_OFFSET] = 1<<pin; // Input | |||
} else { //PM_OFF | |||
pads[1+pin] = (pin<=8) ? RP1_PAD_IC_DEFAULT_0TO8 : RP1_PAD_IC_DEFAULT_FROM9; | |||
gpio[2*pin+1] = RP1_IRQRESET | RP1_FSEL_NONE_HW | RP1_DEBOUNCE_DEFAULT; // default but with irq reset | |||
} | |||
} else { | |||
*(gpio + fSel) = (*(gpio + fSel) & ~(7 << shift)) ; // Sets bits to zero = input | |||
} | |||
@@ -225,8 +225,28 @@ extern int wiringPiSetupPhys (void) ; | |||
extern int wiringPiSetupPinType (enum WPIPinType pinType); //Interface V3.3 | |||
extern int wiringPiSetupGpioDevice(enum WPIPinType pinType); //Interface V3.3 | |||
enum WPIPinAlt { | |||
WPI_ALT_UNKNOWN = -1, | |||
WPI_ALT_INPUT = 0, | |||
WPI_ALT_OUTPUT, | |||
WPI_ALT5, | |||
WPI_ALT4, | |||
WPI_ALT0, | |||
WPI_ALT1, | |||
WPI_ALT2, | |||
WPI_ALT3, | |||
WPI_ALT6, | |||
WPI_ALT7, | |||
WPI_ALT8, | |||
WPI_ALT9, | |||
WPI_NONE = 0x1F, // Pi5 default | |||
}; | |||
extern int wiringPiGpioDeviceGetFd(); //Interface V3.3 | |||
extern void pinModeAlt (int pin, int mode) ; | |||
extern enum WPIPinAlt getPinModeAlt (int pin) ; // Interface V3.5, same as getAlt but wie enum | |||
extern void pinMode (int pin, int mode) ; | |||
extern void pullUpDnControl (int pin, int pud) ; | |||
extern int digitalRead (int pin) ; | |||
@@ -1,7 +1,7 @@ | |||
/* | |||
* wiringPiI2C.c: | |||
* Simplified I2C access routines | |||
* Copyright (c) 2013 Gordon Henderson | |||
* Copyright (c) 2013-2024 Gordon Henderson and contributors | |||
*********************************************************************** | |||
* This file is part of wiringPi: | |||
* https://github.com/WiringPi/WiringPi/ | |||
@@ -1,7 +1,7 @@ | |||
/* | |||
* wiringPiI2C.h: | |||
* Simplified I2C access routines | |||
* Copyright (c) 2013 Gordon Henderson | |||
* Copyright (c) 2013-2024 Gordon Henderson and contributors | |||
*********************************************************************** | |||
* This file is part of wiringPi: | |||
* https://github.com/WiringPi/WiringPi/ | |||
@@ -24,6 +24,7 @@ | |||
#include <stdio.h> | |||
#include <unistd.h> | |||
#include <stdint.h> | |||
#include <stdlib.h> | |||
#include <fcntl.h> | |||
@@ -32,9 +33,7 @@ | |||
#include <sys/ioctl.h> | |||
#include <asm/ioctl.h> | |||
#include <linux/spi/spidev.h> | |||
#include "wiringPi.h" | |||
#include "wiringPiSPI.h" | |||
@@ -45,10 +44,49 @@ | |||
//static const char *spiDev1 = "/dev/spidev0.1" ; | |||
static const uint8_t spiBPW = 8 ; | |||
static const uint16_t spiDelay = 0 ; | |||
//https://datasheets.raspberrypi.com/cm4/cm4-datasheet.pdf | |||
const uint8_t WPI_MaxSPINumbers = 7 ; | |||
const uint8_t WPI_MaxSPIChannels = 3 ; | |||
static uint32_t spiSpeeds [7][3] = | |||
{ | |||
{0, 0, 0}, | |||
{0, 0, 0}, | |||
{0, 0, 0}, | |||
{0, 0, 0}, | |||
{0, 0, 0}, | |||
{0, 0, 0}, | |||
{0, 0, 0}, | |||
}; | |||
static int spiFds [7][3] = | |||
{ | |||
{-1, -1, -1}, | |||
{-1, -1, -1}, | |||
{-1, -1, -1}, | |||
{-1, -1, -1}, | |||
{-1, -1, -1}, | |||
{-1, -1, -1}, | |||
{-1, -1, -1}, | |||
}; | |||
int SPICheckLimits(const int number, const int channel) { | |||
if (channel<0 || channel>=WPI_MaxSPIChannels) { | |||
fprintf (stderr, "wiringPiSPI: Invalid SPI channel (%d, valid range 0-%d)", channel, WPI_MaxSPIChannels-1); | |||
return -EINVAL; | |||
} | |||
if (number<0 || number>=WPI_MaxSPINumbers) { | |||
fprintf (stderr, "wiringPiSPI: Invalid SPI number (%d, valid range 0-%d)", number, WPI_MaxSPINumbers-1); | |||
return -EINVAL; | |||
} | |||
return 0; //sucess | |||
} | |||
static uint32_t spiSpeeds [2] ; | |||
static int spiFds [2] ; | |||
#define RETURN_ON_LIMIT_FAIL int ret = SPICheckLimits(number, channel); if(ret!=0) { return ret; }; | |||
/* | |||
* wiringPiSPIGetFd: | |||
@@ -56,9 +94,16 @@ static int spiFds [2] ; | |||
********************************************************************************* | |||
*/ | |||
int wiringPiSPIGetFd (int channel) | |||
int wiringPiSPIxGetFd(const int number, int channel) | |||
{ | |||
return spiFds [channel & 1] ; | |||
if (SPICheckLimits(number, channel)!=0) { | |||
return -1; | |||
} | |||
return spiFds[number][channel]; | |||
} | |||
int wiringPiSPIGetFd(int channel) { | |||
return wiringPiSPIxGetFd(0, channel); | |||
} | |||
@@ -71,27 +116,33 @@ int wiringPiSPIGetFd (int channel) | |||
********************************************************************************* | |||
*/ | |||
int wiringPiSPIDataRW (int channel, unsigned char *data, int len) | |||
int wiringPiSPIxDataRW (const int number, const int channel, unsigned char *data, const int len) | |||
{ | |||
struct spi_ioc_transfer spi ; | |||
channel &= 1 ; | |||
RETURN_ON_LIMIT_FAIL | |||
if (-1==spiFds[number][channel]) { | |||
fprintf (stderr, "wiringPiSPI: Invalid SPI number/channel (need wiringPiSPIxSetupMode before read/write)"); | |||
return -EBADF; | |||
} | |||
struct spi_ioc_transfer spi ; | |||
// Mentioned in spidev.h but not used in the original kernel documentation | |||
// test program )-: | |||
memset (&spi, 0, sizeof (spi)) ; | |||
spi.tx_buf = (unsigned long)data ; | |||
spi.rx_buf = (unsigned long)data ; | |||
spi.len = len ; | |||
spi.delay_usecs = spiDelay ; | |||
spi.speed_hz = spiSpeeds [channel] ; | |||
spi.speed_hz = spiSpeeds [number][channel] ; | |||
spi.bits_per_word = spiBPW ; | |||
return ioctl (spiFds [channel], SPI_IOC_MESSAGE(1), &spi) ; | |||
return ioctl (spiFds[number][channel], SPI_IOC_MESSAGE(1), &spi) ; | |||
} | |||
int wiringPiSPIDataRW (int channel, unsigned char *data, int len) { | |||
return wiringPiSPIxDataRW(0, channel, data, len); | |||
} | |||
/* | |||
* wiringPiSPISetupMode: | |||
@@ -99,46 +150,68 @@ int wiringPiSPIDataRW (int channel, unsigned char *data, int len) | |||
********************************************************************************* | |||
*/ | |||
int wiringPiSPISetupMode (int channel, int speed, int mode) | |||
int wiringPiSPIxSetupMode(const int number, const int channel, const int speed, const int mode) | |||
{ | |||
int fd ; | |||
char spiDev [32] ; | |||
mode &= 3 ; // Mode is 0, 1, 2 or 3 | |||
RETURN_ON_LIMIT_FAIL | |||
if (mode<0 || mode>3) { // Mode is 0, 1, 2 or 3 original | |||
fprintf (stderr, "wiringPiSPI: Invalid mode (%d, valid range 0-%d)", mode, 3); | |||
return -EINVAL; | |||
} | |||
// Channel can be anything - lets hope for the best | |||
// channel &= 1 ; // Channel is 0 or 1 | |||
snprintf (spiDev, 31, "/dev/spidev0.%d", channel) ; | |||
if ((fd = open (spiDev, O_RDWR)) < 0) | |||
return wiringPiFailure (WPI_ALMOST, "Unable to open SPI device: %s\n", strerror (errno)) ; | |||
spiSpeeds [channel] = speed ; | |||
spiFds [channel] = fd ; | |||
snprintf (spiDev, 31, "/dev/spidev%d.%d", number, channel) ; | |||
if ((fd = open (spiDev, O_RDWR)) < 0) { | |||
return wiringPiFailure (WPI_ALMOST, "Unable to open SPI device %s: %s\n", spiDev, strerror (errno)) ; | |||
} | |||
spiSpeeds [number][channel] = speed ; | |||
spiFds [number][channel] = fd ; | |||
// Set SPI parameters. | |||
if (ioctl (fd, SPI_IOC_WR_MODE, &mode) < 0) | |||
return wiringPiFailure (WPI_ALMOST, "SPI Mode Change failure: %s\n", strerror (errno)) ; | |||
return wiringPiFailure (WPI_ALMOST, "SPI mode change failure: %s\n", strerror (errno)) ; | |||
if (ioctl (fd, SPI_IOC_WR_BITS_PER_WORD, &spiBPW) < 0) | |||
return wiringPiFailure (WPI_ALMOST, "SPI BPW Change failure: %s\n", strerror (errno)) ; | |||
return wiringPiFailure (WPI_ALMOST, "SPI BPW change failure: %s\n", strerror (errno)) ; | |||
if (ioctl (fd, SPI_IOC_WR_MAX_SPEED_HZ, &speed) < 0) | |||
return wiringPiFailure (WPI_ALMOST, "SPI Speed Change failure: %s\n", strerror (errno)) ; | |||
return wiringPiFailure (WPI_ALMOST, "SPI speed change failure: %s\n", strerror (errno)) ; | |||
return fd ; | |||
} | |||
int wiringPiSPISetupMode (int channel, int speed, int mode) { | |||
return wiringPiSPIxSetupMode (0, channel, speed, mode); | |||
} | |||
/* | |||
* wiringPiSPISetup: | |||
* Open the SPI device, and set it up, etc. in the default MODE 0 | |||
********************************************************************************* | |||
*/ | |||
int wiringPiSPISetup (int channel, int speed) | |||
{ | |||
return wiringPiSPISetupMode (channel, speed, 0) ; | |||
int wiringPiSPISetup (int channel, int speed) { | |||
return wiringPiSPIxSetupMode(0, channel, speed, 0) ; | |||
} | |||
int wiringPiSPIxClose (const int number, const int channel) { | |||
RETURN_ON_LIMIT_FAIL | |||
if (spiFds[number][channel]>0) { | |||
ret = close(spiFds[number][channel]); | |||
} | |||
spiSpeeds [number][channel] = 0 ; | |||
spiFds [number][channel] = -1 ; | |||
return ret; | |||
} | |||
int wiringPiSPIClose (const int channel) { | |||
return wiringPiSPIxClose (0, channel); | |||
} | |||
@@ -1,7 +1,7 @@ | |||
/* | |||
* wiringPiSPI.h: | |||
* Simplified SPI access routines | |||
* Copyright (c) 2012-2015 Gordon Henderson | |||
* Copyright (c) 2012-2024 Gordon Henderson and contributors | |||
*********************************************************************** | |||
* This file is part of wiringPi: | |||
* https://github.com/WiringPi/WiringPi/ | |||
@@ -26,10 +26,20 @@ | |||
extern "C" { | |||
#endif | |||
int wiringPiSPIGetFd (int channel) ; | |||
int wiringPiSPIDataRW (int channel, unsigned char *data, int len) ; | |||
int wiringPiSPISetupMode (int channel, int speed, int mode) ; | |||
int wiringPiSPISetup (int channel, int speed) ; | |||
int wiringPiSPIClose (const int channel); //Interface 3.5 | |||
//Interface 3.5 | |||
int wiringPiSPIxGetFd (const int number, const int channel) ; | |||
int wiringPiSPIxDataRW (const int number, const int channel, unsigned char *data, const int len) ; | |||
int wiringPiSPIxSetupMode (const int number, const int channel, const int speed, const int mode) ; | |||
int wiringPiSPIxSetup (const int number, const int channel, const int speed) ; | |||
int wiringPiSPIxClose (const int number, const int channel); | |||
#ifdef __cplusplus | |||
} | |||