@@ -1 +1 @@ | |||||
3.5 | |||||
3.6 |
@@ -1,3 +1,3 @@ | |||||
#define VERSION "3.5" | |||||
#define VERSION "3.6" | |||||
#define VERSION_MAJOR 3 | #define VERSION_MAJOR 3 | ||||
#define VERSION_MINOR 5 | |||||
#define VERSION_MINOR 6 |
@@ -1,7 +1,7 @@ | |||||
/* | /* | ||||
* pcf8574.c: | * pcf8574.c: | ||||
* Extend wiringPi with the PCF8574 I2C GPIO expander chip | * 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: | * This file is part of wiringPi: | ||||
* https://github.com/WiringPi/WiringPi/ | * https://github.com/WiringPi/WiringPi/ | ||||
@@ -33,8 +33,9 @@ | |||||
/* | /* | ||||
* myPinMode: | * 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... | * So, we're effectively copying digitalWrite... | ||||
********************************************************************************* | ********************************************************************************* | ||||
*/ | */ | ||||
@@ -102,7 +103,7 @@ static int myDigitalRead (struct wiringPiNodeStruct *node, int pin) | |||||
* pcf8574Setup: | * pcf8574Setup: | ||||
* Create a new instance of a PCF8574 I2C GPIO interface. We know it | * 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 | * 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 | 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: | wiringpi_test1_sysfs: | ||||
${CC} ${CFLAGS} wiringpi_test1_sysfs.c -o wiringpi_test1_sysfs -lwiringPi | ${CC} ${CFLAGS} wiringpi_test1_sysfs.c -o wiringpi_test1_sysfs -lwiringPi | ||||
@@ -27,12 +31,61 @@ wiringpi_test6_isr: | |||||
wiringpi_test7_version: | wiringpi_test7_version: | ||||
${CC} ${CFLAGS} wiringpi_test7_version.c -o wiringpi_test7_version -lwiringPi | ${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: | test: | ||||
@error_state=false ; \ | |||||
for t in $(tests) ; do \ | for t in $(tests) ; do \ | ||||
echo === unit test: $${t} === ; \ | 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} ; \ | time ./$${t} ; \ | ||||
if [ $$? -ne 0 ]; then \ | |||||
error_state=true ; \ | |||||
fi ; \ | |||||
echo ; echo ; \ | echo ; echo ; \ | ||||
done | 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: | 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 | // Compile: gcc -Wall wiringpi_test1_device.c -o wiringpi_test1_device -lwiringPi | ||||
#include "wpi_test.h" | #include "wpi_test.h" | ||||
#include <stdlib.h> | |||||
#include <signal.h> | #include <signal.h> | ||||
#include <string.h> | |||||
#include <time.h> | #include <time.h> | ||||
#include <sys/time.h> | #include <sys/time.h> | ||||
@@ -52,6 +50,6 @@ int main (void) { | |||||
//Error wrong direction - only for fun | //Error wrong direction - only for fun | ||||
digitalWrite(GPIO, LOW); | digitalWrite(GPIO, LOW); | ||||
return(EXIT_SUCCESS); | |||||
return UnitTestState(); | |||||
} | } | ||||
@@ -2,9 +2,7 @@ | |||||
// Compile: gcc -Wall wiringpi_test2_device.c -o wiringpi_test2_device -lwiringPi | // Compile: gcc -Wall wiringpi_test2_device.c -o wiringpi_test2_device -lwiringPi | ||||
#include "wpi_test.h" | #include "wpi_test.h" | ||||
#include <stdlib.h> | |||||
#include <signal.h> | #include <signal.h> | ||||
#include <string.h> | |||||
#include <time.h> | #include <time.h> | ||||
#include <sys/time.h> | #include <sys/time.h> | ||||
@@ -50,5 +48,5 @@ int main (void) { | |||||
CheckGPIO(GPIO, GPIOIN, LOW); | CheckGPIO(GPIO, GPIOIN, LOW); | ||||
delayMicroseconds(600000); | delayMicroseconds(600000); | ||||
return(EXIT_SUCCESS); | |||||
return UnitTestState(); | |||||
} | } |
@@ -2,9 +2,7 @@ | |||||
// Compile: gcc -Wall wiringpi_test3_device.c -o wiringpi_test3_device -lwiringPi | // Compile: gcc -Wall wiringpi_test3_device.c -o wiringpi_test3_device -lwiringPi | ||||
#include "wpi_test.h" | #include "wpi_test.h" | ||||
#include <stdlib.h> | |||||
#include <signal.h> | #include <signal.h> | ||||
#include <string.h> | |||||
#include <time.h> | #include <time.h> | ||||
#include <sys/time.h> | #include <sys/time.h> | ||||
@@ -50,5 +48,5 @@ int main (void) { | |||||
CheckGPIO(GPIO, GPIOIN, LOW); | CheckGPIO(GPIO, GPIOIN, LOW); | ||||
delayMicroseconds(600000); | delayMicroseconds(600000); | ||||
return(EXIT_SUCCESS); | |||||
return UnitTestState(); | |||||
} | } |
@@ -2,9 +2,7 @@ | |||||
// Compile: gcc -Wall wiringpi_test4_device.c -o wiringpi_test4_device -lwiringPi | // Compile: gcc -Wall wiringpi_test4_device.c -o wiringpi_test4_device -lwiringPi | ||||
#include "wpi_test.h" | #include "wpi_test.h" | ||||
#include <stdlib.h> | |||||
#include <signal.h> | #include <signal.h> | ||||
#include <string.h> | |||||
#include <time.h> | #include <time.h> | ||||
#include <sys/time.h> | #include <sys/time.h> | ||||
@@ -50,5 +48,5 @@ int main (void) { | |||||
CheckGPIO(GPIO, GPIOIN, LOW); | CheckGPIO(GPIO, GPIOIN, LOW); | ||||
delayMicroseconds(600000); | delayMicroseconds(600000); | ||||
return(EXIT_SUCCESS); | |||||
return UnitTestState(); | |||||
} | } |
@@ -2,9 +2,7 @@ | |||||
// Compile: gcc -Wall wiringpi_test1_device.c -o wiringpi_test1_device -lwiringPi | // Compile: gcc -Wall wiringpi_test1_device.c -o wiringpi_test1_device -lwiringPi | ||||
#include "wpi_test.h" | #include "wpi_test.h" | ||||
#include <stdlib.h> | |||||
#include <signal.h> | #include <signal.h> | ||||
#include <string.h> | |||||
#include <time.h> | #include <time.h> | ||||
#include <sys/time.h> | #include <sys/time.h> | ||||
@@ -12,6 +10,34 @@ | |||||
const int GPIO = 19; | const int GPIO = 19; | ||||
const int GPIOIN = 26; | const int GPIOIN = 26; | ||||
const int ToggleValue = 4; | 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) { | int main (void) { | ||||
@@ -23,8 +49,23 @@ int main (void) { | |||||
printf("wiringPiSetupGpio failed\n\n"); | printf("wiringPiSetupGpio failed\n\n"); | ||||
exit(EXIT_FAILURE); | 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); | printf("toggle %d times ...\n", ToggleValue); | ||||
for (int loop=1; loop<ToggleValue; loop++) { | 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); | printf("\nWiringPi GPIO test program (using GPIO%d (input pull up/down) and GPIO%d (input))\n", GPIO, GPIOIN); | ||||
pullUpDnControl (GPIO, PUD_UP); | pullUpDnControl (GPIO, PUD_UP); | ||||
pinMode(GPIO, INPUT); | |||||
SetAndCheckMode(GPIO, INPUT); | |||||
delayMicroseconds(3000000); | delayMicroseconds(3000000); | ||||
pullUpDnControl (GPIOIN, PUD_OFF); | pullUpDnControl (GPIOIN, PUD_OFF); | ||||
@@ -52,6 +95,11 @@ int main (void) { | |||||
//Error wrong direction - only for fun | //Error wrong direction - only for fun | ||||
digitalWrite(GPIO, LOW); | 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 "wpi_test.h" | ||||
#include <string.h> | #include <string.h> | ||||
#include <errno.h> | #include <errno.h> | ||||
#include <stdlib.h> | |||||
#include <unistd.h> | #include <unistd.h> | ||||
#include <sys/time.h> | #include <sys/time.h> | ||||
@@ -166,5 +165,5 @@ int main (void) { | |||||
} | } | ||||
pinMode(OUTpin, INPUT); | pinMode(OUTpin, INPUT); | ||||
return 0 ; | |||||
return UnitTestState(); | |||||
} | } |
@@ -8,4 +8,6 @@ int main (void) { | |||||
CheckSame("version major", major, VERSION_MAJOR); | CheckSame("version major", major, VERSION_MAJOR); | ||||
CheckSame("version minor", minor, VERSION_MINOR); | 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 <wiringPi.h> | ||||
#include <stdio.h> | #include <stdio.h> | ||||
#include <stdlib.h> | |||||
#include <math.h> | |||||
#include <errno.h> | |||||
#include <string.h> | |||||
#define COLORDEF "\x1B[0m" | #define COLORDEF "\x1B[0m" | ||||
#define COLORRED "\x1B[31m" | #define COLORRED "\x1B[31m" | ||||
#define COLORGRN "\x1B[32m" | #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) { | 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) { | 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) { | 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) { | 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_MASK = 0x7f; | ||||
const unsigned int RP1_DEBOUNCE_DEFAULT = (RP1_DEBOUNCE_DEFAULT_VALUE << 5); | 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_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_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_PAD_DRIVE_MASK = 0x00000030; | ||||
const unsigned int RP1_INV_PAD_DRIVE_MASK = ~(RP1_PAD_DRIVE_MASK); | 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: | * pwmSetMode: | ||||
* Select the native "balanced" mode, or standard mark:space mode | * Select the native "balanced" mode, or standard mark:space mode | ||||
@@ -1727,11 +1736,16 @@ void pinMode (int pin, int mode) | |||||
fSel = gpioToGPFSEL [pin] ; | fSel = gpioToGPFSEL [pin] ; | ||||
shift = gpioToShift [pin] ; | shift = gpioToShift [pin] ; | ||||
if (mode == INPUT) { | |||||
if (INPUT==mode || PM_OFF==mode) { | |||||
if (PI_MODEL_5 == RaspberryPiModel) { | 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 { | } else { | ||||
*(gpio + fSel) = (*(gpio + fSel) & ~(7 << shift)) ; // Sets bits to zero = input | *(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 wiringPiSetupPinType (enum WPIPinType pinType); //Interface V3.3 | ||||
extern int wiringPiSetupGpioDevice(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 int wiringPiGpioDeviceGetFd(); //Interface V3.3 | ||||
extern void pinModeAlt (int pin, int mode) ; | 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 pinMode (int pin, int mode) ; | ||||
extern void pullUpDnControl (int pin, int pud) ; | extern void pullUpDnControl (int pin, int pud) ; | ||||
extern int digitalRead (int pin) ; | extern int digitalRead (int pin) ; | ||||
@@ -1,7 +1,7 @@ | |||||
/* | /* | ||||
* wiringPiI2C.c: | * wiringPiI2C.c: | ||||
* Simplified I2C access routines | * Simplified I2C access routines | ||||
* Copyright (c) 2013 Gordon Henderson | |||||
* Copyright (c) 2013-2024 Gordon Henderson and contributors | |||||
*********************************************************************** | *********************************************************************** | ||||
* This file is part of wiringPi: | * This file is part of wiringPi: | ||||
* https://github.com/WiringPi/WiringPi/ | * https://github.com/WiringPi/WiringPi/ | ||||
@@ -1,7 +1,7 @@ | |||||
/* | /* | ||||
* wiringPiI2C.h: | * wiringPiI2C.h: | ||||
* Simplified I2C access routines | * Simplified I2C access routines | ||||
* Copyright (c) 2013 Gordon Henderson | |||||
* Copyright (c) 2013-2024 Gordon Henderson and contributors | |||||
*********************************************************************** | *********************************************************************** | ||||
* This file is part of wiringPi: | * This file is part of wiringPi: | ||||
* https://github.com/WiringPi/WiringPi/ | * https://github.com/WiringPi/WiringPi/ | ||||
@@ -24,6 +24,7 @@ | |||||
#include <stdio.h> | #include <stdio.h> | ||||
#include <unistd.h> | |||||
#include <stdint.h> | #include <stdint.h> | ||||
#include <stdlib.h> | #include <stdlib.h> | ||||
#include <fcntl.h> | #include <fcntl.h> | ||||
@@ -32,9 +33,7 @@ | |||||
#include <sys/ioctl.h> | #include <sys/ioctl.h> | ||||
#include <asm/ioctl.h> | #include <asm/ioctl.h> | ||||
#include <linux/spi/spidev.h> | #include <linux/spi/spidev.h> | ||||
#include "wiringPi.h" | #include "wiringPi.h" | ||||
#include "wiringPiSPI.h" | #include "wiringPiSPI.h" | ||||
@@ -45,10 +44,49 @@ | |||||
//static const char *spiDev1 = "/dev/spidev0.1" ; | //static const char *spiDev1 = "/dev/spidev0.1" ; | ||||
static const uint8_t spiBPW = 8 ; | static const uint8_t spiBPW = 8 ; | ||||
static const uint16_t spiDelay = 0 ; | 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: | * 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 | // Mentioned in spidev.h but not used in the original kernel documentation | ||||
// test program )-: | // test program )-: | ||||
memset (&spi, 0, sizeof (spi)) ; | memset (&spi, 0, sizeof (spi)) ; | ||||
spi.tx_buf = (unsigned long)data ; | spi.tx_buf = (unsigned long)data ; | ||||
spi.rx_buf = (unsigned long)data ; | spi.rx_buf = (unsigned long)data ; | ||||
spi.len = len ; | spi.len = len ; | ||||
spi.delay_usecs = spiDelay ; | spi.delay_usecs = spiDelay ; | ||||
spi.speed_hz = spiSpeeds [channel] ; | |||||
spi.speed_hz = spiSpeeds [number][channel] ; | |||||
spi.bits_per_word = spiBPW ; | 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: | * 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 ; | int fd ; | ||||
char spiDev [32] ; | 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. | // Set SPI parameters. | ||||
if (ioctl (fd, SPI_IOC_WR_MODE, &mode) < 0) | 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) | 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) | 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 ; | return fd ; | ||||
} | } | ||||
int wiringPiSPISetupMode (int channel, int speed, int mode) { | |||||
return wiringPiSPIxSetupMode (0, channel, speed, mode); | |||||
} | |||||
/* | /* | ||||
* wiringPiSPISetup: | * wiringPiSPISetup: | ||||
* Open the SPI device, and set it up, etc. in the default MODE 0 | * 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: | * wiringPiSPI.h: | ||||
* Simplified SPI access routines | * Simplified SPI access routines | ||||
* Copyright (c) 2012-2015 Gordon Henderson | |||||
* Copyright (c) 2012-2024 Gordon Henderson and contributors | |||||
*********************************************************************** | *********************************************************************** | ||||
* This file is part of wiringPi: | * This file is part of wiringPi: | ||||
* https://github.com/WiringPi/WiringPi/ | * https://github.com/WiringPi/WiringPi/ | ||||
@@ -26,10 +26,20 @@ | |||||
extern "C" { | extern "C" { | ||||
#endif | #endif | ||||
int wiringPiSPIGetFd (int channel) ; | int wiringPiSPIGetFd (int channel) ; | ||||
int wiringPiSPIDataRW (int channel, unsigned char *data, int len) ; | int wiringPiSPIDataRW (int channel, unsigned char *data, int len) ; | ||||
int wiringPiSPISetupMode (int channel, int speed, int mode) ; | int wiringPiSPISetupMode (int channel, int speed, int mode) ; | ||||
int wiringPiSPISetup (int channel, int speed) ; | 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 | #ifdef __cplusplus | ||||
} | } | ||||