@@ -1 +1 @@ | |||
3.6 | |||
3.7 |
@@ -816,7 +816,7 @@ static void doPwmClock (int argc, char *argv []) | |||
if ((clock < 1) || (clock > 4095)) | |||
{ | |||
fprintf (stderr, "%s: clock must be between 0 and 4096\n", argv [0]) ; | |||
fprintf (stderr, "%s: pwm clock must be between 1 and 4095\n", argv [0]) ; | |||
exit (1) ; | |||
} | |||
@@ -1,3 +1,3 @@ | |||
#define VERSION "3.6" | |||
#define VERSION "3.7" | |||
#define VERSION_MAJOR 3 | |||
#define VERSION_MINOR 6 | |||
#define VERSION_MINOR 7 |
@@ -1,47 +1,64 @@ | |||
CC = gcc | |||
CFLAGS = -Wall | |||
LDFLAGS = | |||
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 | |||
# Need BCM19 <-> BCM26, +PWM: BCM12 <-> BCM13, BCM18 <-> BCM17 connected (1kOhm) | |||
tests = wiringpi_test1_sysfs wiringpi_test2_sysfs wiringpi_test3_device_wpi wiringpi_test4_device_phys wiringpi_test5_default wiringpi_test6_isr wiringpi_test7_version wiringpi_test8_pwm wiringpi_test9_pwm | |||
xotests = wiringpi_xotest_test1_spi | |||
# Need XO hardware | |||
xotests = wiringpi_xotest_test1_spi wiringpi_i2c_test1_pcf8574 wiringpi_test8_pwm wiringpi_test9_pwm | |||
i2ctests = wiringpi_i2c_test1_pcf8574 | |||
# Need PiFace hardware and BCM23 <-> BCM24 , BCM18 <-> BCM17 connected (1kOhm), and PiFace Out7<->In4, Out6<->In5, R0_NO<->In6, R0_NO<->In7, R_C<-100Ohm->GND | |||
pifacetests = wiringpi_piface_test1 wiringpi_test8_pwm wiringpi_test9_pwm | |||
all: $(tests) $(xotests) $(i2ctests) | |||
all: $(tests) $(xotests) $(pifacetests) | |||
wiringpi_test1_sysfs: | |||
wiringpi_test1_sysfs: | |||
${CC} ${CFLAGS} wiringpi_test1_sysfs.c -o wiringpi_test1_sysfs -lwiringPi | |||
wiringpi_test2_sysfs: | |||
wiringpi_test2_sysfs: | |||
${CC} ${CFLAGS} wiringpi_test2_sysfs.c -o wiringpi_test2_sysfs -lwiringPi | |||
wiringpi_test3_device_wpi: | |||
wiringpi_test3_device_wpi: | |||
${CC} ${CFLAGS} wiringpi_test3_device_wpi.c -o wiringpi_test3_device_wpi -lwiringPi | |||
wiringpi_test4_device_phys: | |||
wiringpi_test4_device_phys: | |||
${CC} ${CFLAGS} wiringpi_test4_device_phys.c -o wiringpi_test4_device_phys -lwiringPi | |||
wiringpi_test5_default: | |||
wiringpi_test5_default: | |||
${CC} ${CFLAGS} wiringpi_test5_default.c -o wiringpi_test5_default -lwiringPi | |||
wiringpi_test6_isr: | |||
wiringpi_test6_isr: | |||
${CC} ${CFLAGS} wiringpi_test6_isr.c -o wiringpi_test6_isr -lwiringPi | |||
wiringpi_test7_version: | |||
wiringpi_test7_version: | |||
${CC} ${CFLAGS} wiringpi_test7_version.c -o wiringpi_test7_version -lwiringPi | |||
wiringpi_test8_pwm: | |||
${CC} ${CFLAGS} wiringpi_test8_pwm.c -o wiringpi_test8_pwm -lwiringPi | |||
wiringpi_test9_pwm: | |||
${CC} ${CFLAGS} wiringpi_test9_pwm.c -o wiringpi_test9_pwm -lwiringPi | |||
wiringpi_piface_test1: | |||
${CC} ${CFLAGS} wiringpi_piface_test1.c -o wiringpi_piface_test1 -lwiringPi -lwiringPiDev | |||
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 [ $${t} = *"8_pwm" ] || [ $${t} = *"9_pwm" ]; then \ | |||
time sudo ./$${t} ; \ | |||
else \ | |||
time ./$${t} ; \ | |||
fi ; \ | |||
if [ $$? -ne 0 ]; then \ | |||
error_state=true ; \ | |||
fi ; \ | |||
@@ -57,7 +74,11 @@ xotest: | |||
@error_state=false ; \ | |||
for t in $(tests) $(xotests) ; do \ | |||
echo === XO unit test: $${t} === ; \ | |||
time ./$${t} ; \ | |||
if [ $${t} = *"8_pwm" ] || [ $${t} = *"9_pwm" ]; then \ | |||
time sudo ./$${t} ; \ | |||
else \ | |||
time ./$${t} ; \ | |||
fi ; \ | |||
if [ $$? -ne 0 ]; then \ | |||
error_state=true ; \ | |||
fi ; \ | |||
@@ -69,23 +90,27 @@ xotest: | |||
echo "\n\e[5mSTD/XO TEST SUCCESS\e[0m\n"; \ | |||
fi | |||
i2ctest: | |||
pifacetest: | |||
@error_state=false ; \ | |||
for t in $(tests) $(i2ctests) ; do \ | |||
echo === I2C unit test: $${t} === ; \ | |||
time ./$${t} ; \ | |||
for t in $(tests) $(pifacetests) ; do \ | |||
echo === PiFace unit test: $${t} === ; \ | |||
if [ $${t} = *"8_pwm" ] || [ $${t} = *"9_pwm" ]; then \ | |||
time sudo ./$${t} ; \ | |||
else \ | |||
time ./$${t} ; \ | |||
fi ; \ | |||
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"; \ | |||
echo "\n\e[5mPIFACE TEST FAILED\e[0m\n"; \ | |||
else \ | |||
echo "\n\e[5mSTD/I2C TEST SUCCESS\e[0m\n"; \ | |||
echo "\n\e[5mPIFACE TEST SUCCESS\e[0m\n"; \ | |||
fi | |||
clean: | |||
for t in $(tests) $(xotests) $(i2ctests) ; do \ | |||
clean: | |||
for t in $(tests) $(xotests) $(pifacetests) ; do \ | |||
rm -fv $${t} ; \ | |||
done |
@@ -0,0 +1,133 @@ | |||
// WiringPi piface program IN, OUT, PULL | |||
// Compile: gcc -Wall wiringpi_piface_test1.c -o wiringpi_piface_test1 -lwiringPi -lwiringPiDev | |||
#include "wpi_test.h" | |||
#include <piFace.h> | |||
// Use 200 as the pin-base for the PiFace board, and change all pins | |||
// for the LED and relays | |||
const int PIFACE = 200; //Mapped wiringpi IO address | |||
const int defaultsleep = 200000; // 200 ms | |||
void ReadUntilTimeout(int GPIO, int expect, int timeoutSec) { | |||
const int intervaluS = 250000; //250ms | |||
int in; | |||
const char* strexpect = expect ? "HIGH" : "LOW"; | |||
for(int loop=0, end=(timeoutSec*1000000/intervaluS); loop<end; ++loop) { | |||
in = digitalRead(GPIO); | |||
if (in==expect) { | |||
printf( "took %g sec to set %s\n", loop*intervaluS/1000000.0, strexpect); | |||
break; | |||
} | |||
delayMicroseconds(intervaluS); | |||
printf(".");fflush(stdout); | |||
} | |||
if (in!=expect) { | |||
printf( "timeout reached %d sec to set %s\n", timeoutSec, strexpect); | |||
} | |||
CheckGPIO(GPIO, -1, expect) ; | |||
} | |||
int main (int argc, char *argv []) { | |||
int major, minor; | |||
wiringPiVersion(&major, &minor); | |||
printf("Testing piface functions with WiringPi %d.%d\n",major, minor); | |||
printf("------------------------------------------\n\n"); | |||
// initialise wiringPi | |||
if (wiringPiSetupSys() == -1) { | |||
printf("wiringPiSetupSys failed\n\n"); | |||
exit(EXIT_FAILURE); | |||
} | |||
piFaceSetup (PIFACE); // Setup the PiFace board with default addr 0, 0 | |||
const int RELAY0 = PIFACE+0; | |||
const int RELAY0IN = PIFACE+6; | |||
const int RELAY1 = PIFACE+1; | |||
const int RELAY1IN = PIFACE+7; | |||
printf("\nRelays async:\n"); | |||
pullUpDnControl(RELAY0IN, PUD_UP); | |||
pullUpDnControl(RELAY1IN, PUD_UP); | |||
for (int loop = 0, end=3 ; loop<end ; ++loop) { | |||
int sleep = defaultsleep*(end-loop); | |||
printf("sleep %d ms:\n", sleep/1000); | |||
digitalWrite (RELAY0, HIGH); | |||
delayMicroseconds(sleep); | |||
CheckInversGPIO(RELAY0IN, -1, HIGH) ; | |||
digitalWrite (RELAY0, LOW); | |||
delayMicroseconds(sleep); | |||
CheckInversGPIO(RELAY0IN, -1, LOW); | |||
digitalWrite (RELAY1, HIGH); | |||
delayMicroseconds(sleep); | |||
CheckInversGPIO(RELAY1IN, -1, HIGH); | |||
digitalWrite (RELAY1, LOW); | |||
delayMicroseconds(sleep); | |||
CheckInversGPIO(RELAY1IN, -1, LOW); | |||
} | |||
const int OUT7 = PIFACE+7; | |||
const int OUT7IN = PIFACE+4; | |||
const int OUT6 = PIFACE+6; | |||
const int OUT6IN = PIFACE+5; | |||
printf("\nOUT6/7 sync:\n"); | |||
delayMicroseconds(defaultsleep); | |||
for (int loop = 0, end=3 ; loop<end ; ++loop) { | |||
digitalWrite (OUT7, HIGH); | |||
delayMicroseconds(defaultsleep); | |||
CheckInversGPIO(OUT7IN, -1, HIGH); | |||
digitalWrite (OUT7, LOW); | |||
delayMicroseconds(defaultsleep); | |||
CheckInversGPIO(OUT7IN, -1, LOW); | |||
digitalWrite (OUT6, HIGH); | |||
delayMicroseconds(defaultsleep); | |||
CheckInversGPIO(OUT6IN, -1, HIGH); | |||
digitalWrite (OUT6, LOW); | |||
delayMicroseconds(defaultsleep); | |||
CheckInversGPIO(OUT6IN, -1, LOW); | |||
} | |||
printf("\nRelays sync:\n"); | |||
for (int loop = 0, end=3 ; loop<end ; ++loop) { | |||
int sleep = defaultsleep*(end-loop); | |||
printf("sleep %d ms:\n", sleep/1000); | |||
digitalWrite (RELAY0, HIGH); | |||
digitalWrite (RELAY1, HIGH); | |||
delayMicroseconds(sleep); | |||
CheckInversGPIO(RELAY0IN, -1, HIGH) ; | |||
CheckInversGPIO(RELAY1IN, -1, HIGH) ; | |||
digitalWrite (RELAY0, LOW); | |||
digitalWrite (RELAY1, LOW); | |||
delayMicroseconds(sleep); | |||
CheckInversGPIO(RELAY0IN, -1, LOW) ; | |||
CheckInversGPIO(RELAY1IN, -1, LOW) ; | |||
} | |||
printf("\nInput pull up/down resistor:\n"); | |||
for (int IN = 0 ; IN <= 7 ; ++IN) { | |||
if (4==IN || 5==IN) { | |||
continue; //4 & 5 connected from out to in -> test not possible | |||
} | |||
//6 & 7 connected from relais NO (normaly open) to in -> test possible | |||
delayMicroseconds(defaultsleep); | |||
pullUpDnControl (PIFACE + IN, PUD_UP) ; | |||
ReadUntilTimeout(PIFACE + IN, HIGH, 2) ; | |||
pullUpDnControl (PIFACE + IN, PUD_DOWN) ; | |||
// cool down very slowly, connect 680 kOhm pull down resistor to make ist faster | |||
ReadUntilTimeout(PIFACE + IN, LOW, 60) ; | |||
pullUpDnControl (PIFACE + IN, PUD_UP) ; // finally up | |||
ReadUntilTimeout(PIFACE + IN, HIGH, 2) ; | |||
} | |||
return UnitTestState(); | |||
} |
@@ -7,8 +7,8 @@ | |||
#include <sys/time.h> | |||
const int GPIO = 19; | |||
const int GPIOIN = 26; | |||
int GPIO = 19; | |||
int GPIOIN = 26; | |||
const int ToggleValue = 4; | |||
@@ -21,6 +21,11 @@ int main (void) { | |||
printf("wiringPiSetupSys failed\n\n"); | |||
exit(EXIT_FAILURE); | |||
} | |||
if (!piBoard40Pin()) { | |||
GPIO = 23; | |||
GPIOIN = 24; | |||
} | |||
pinMode(GPIOIN, INPUT); | |||
pinMode(GPIO, OUTPUT); | |||
@@ -7,8 +7,8 @@ | |||
#include <sys/time.h> | |||
const int GPIO = 19; | |||
const int GPIOIN = 26; | |||
int GPIO = 19; | |||
int GPIOIN = 26; | |||
const int ToggleValue = 4; | |||
@@ -21,6 +21,11 @@ int main (void) { | |||
printf("wiringPiSetupSys failed\n\n"); | |||
exit(EXIT_FAILURE); | |||
} | |||
if (!piBoard40Pin()) { | |||
GPIO = 23; | |||
GPIOIN = 24; | |||
} | |||
pinMode(GPIOIN, INPUT); | |||
pinMode(GPIO, OUTPUT); | |||
@@ -7,8 +7,8 @@ | |||
#include <sys/time.h> | |||
const int GPIO = 24; //BCM 19 | |||
const int GPIOIN = 25; //BCM 26; | |||
int GPIO = 24; //BCM 19 | |||
int GPIOIN = 25; //BCM 26; | |||
const int ToggleValue = 4; | |||
@@ -21,6 +21,11 @@ int main (void) { | |||
printf("wiringPiSetupGpioDevice failed\n\n"); | |||
exit(EXIT_FAILURE); | |||
} | |||
if (!piBoard40Pin()) { | |||
GPIO = 4; //BCM 23 | |||
GPIOIN = 5; //BCM 24 | |||
} | |||
pinMode(GPIOIN, INPUT); | |||
pinMode(GPIO, OUTPUT); | |||
@@ -7,8 +7,8 @@ | |||
#include <sys/time.h> | |||
const int GPIO = 35; //BCM 19 | |||
const int GPIOIN = 37; //BCM 26; | |||
int GPIO = 35; //BCM 19 | |||
int GPIOIN = 37; //BCM 26; | |||
const int ToggleValue = 4; | |||
@@ -21,6 +21,11 @@ int main (void) { | |||
printf("wiringPiSetupGpioDevice failed\n\n"); | |||
exit(EXIT_FAILURE); | |||
} | |||
if (!piBoard40Pin()) { | |||
GPIO = 16; //BCM 23 | |||
GPIOIN = 18; //BCM 24 | |||
} | |||
pinMode(GPIOIN, INPUT); | |||
pinMode(GPIO, OUTPUT); | |||
@@ -7,8 +7,8 @@ | |||
#include <sys/time.h> | |||
const int GPIO = 19; | |||
const int GPIOIN = 26; | |||
int GPIO = 19; | |||
int GPIOIN = 26; | |||
const int ToggleValue = 4; | |||
int RaspberryPiModel = -1; | |||
@@ -58,6 +58,10 @@ int main (void) { | |||
} else { | |||
printf("Raspberry Pi with BCM GPIO found (not Pi 5)\n"); | |||
} | |||
if (!piBoard40Pin()) { | |||
GPIO = 23; | |||
GPIOIN = 24; | |||
} | |||
enum WPIPinAlt AltGpio = WPI_ALT_UNKNOWN; | |||
@@ -8,8 +8,8 @@ | |||
#include <sys/time.h> | |||
const int GPIO = 19; | |||
const int GPIOIN = 26; | |||
int GPIO = 19; | |||
int GPIOIN = 26; | |||
const int ToggleValue = 4; | |||
@@ -115,55 +115,61 @@ double DurationTime(int Enge, int OUTpin, int IRQpin) { | |||
return fTime; | |||
} | |||
int main (void) { | |||
const int IRQpin = GPIOIN ; | |||
const int OUTpin = GPIO ; | |||
int major, minor; | |||
wiringPiVersion(&major, &minor); | |||
int major, minor; | |||
wiringPiVersion(&major, &minor); | |||
printf("WiringPi GPIO test program 1 (using GPIO%d (output) and GPIO%d (input))\n", GPIO, GPIOIN); | |||
printf(" testing irq\n"); | |||
printf("\nISR test (WiringPi %d.%d)\n", major, minor); | |||
wiringPiSetupGpio() ; | |||
pinMode(IRQpin, INPUT); | |||
pinMode(OUTpin, OUTPUT); | |||
digitalWrite (OUTpin, LOW) ; | |||
printf("Testing IRQ @ GPIO%d with trigger @ GPIO%d rising\n", IRQpin, OUTpin); | |||
wiringPiISR (IRQpin, INT_EDGE_RISING, &wfi) ; | |||
sleep(1); | |||
StartSequence (INT_EDGE_RISING, OUTpin); | |||
printf("Testing close\n"); | |||
wiringPiISRStop (IRQpin) ; | |||
printf("Testing IRQ @ GPIO%d with trigger @ GPIO%d falling\n", IRQpin, OUTpin); | |||
wiringPiISR (IRQpin, INT_EDGE_FALLING, &wfi) ; | |||
sleep(1); | |||
StartSequence (INT_EDGE_FALLING, OUTpin); | |||
printf("Testing close\n"); | |||
wiringPiISRStop (IRQpin) ; | |||
printf("Testing IRQ @ GPIO%d with trigger @ GPIO%d both\n", IRQpin, OUTpin); | |||
wiringPiISR (IRQpin, INT_EDGE_BOTH, &wfi) ; | |||
sleep(1); | |||
StartSequence (INT_EDGE_BOTH, OUTpin); | |||
printf("Testing close\n"); | |||
wiringPiISRStop (IRQpin) ; | |||
for (int count=0; count<2; count++) { | |||
printf("Measuring duration IRQ @ GPIO%d with trigger @ GPIO%d rising\n", IRQpin, OUTpin); | |||
DurationTime(INT_EDGE_RISING, OUTpin, IRQpin); | |||
printf("Measuring duration IRQ @ GPIO%d with trigger @ GPIO%d falling\n", IRQpin, OUTpin); | |||
DurationTime(INT_EDGE_FALLING, OUTpin, IRQpin); | |||
} | |||
pinMode(OUTpin, INPUT); | |||
return UnitTestState(); | |||
printf("\nISR test (WiringPi %d.%d)\n", major, minor); | |||
wiringPiSetupGpio() ; | |||
if (!piBoard40Pin()) { | |||
GPIO = 23; | |||
GPIOIN = 24; | |||
} | |||
int IRQpin = GPIOIN ; | |||
int OUTpin = GPIO ; | |||
pinMode(IRQpin, INPUT); | |||
pinMode(OUTpin, OUTPUT); | |||
digitalWrite (OUTpin, LOW) ; | |||
printf("Testing IRQ @ GPIO%d with trigger @ GPIO%d rising\n", IRQpin, OUTpin); | |||
wiringPiISR (IRQpin, INT_EDGE_RISING, &wfi) ; | |||
sleep(1); | |||
StartSequence (INT_EDGE_RISING, OUTpin); | |||
printf("Testing close\n"); | |||
wiringPiISRStop (IRQpin) ; | |||
printf("Testing IRQ @ GPIO%d with trigger @ GPIO%d falling\n", IRQpin, OUTpin); | |||
wiringPiISR (IRQpin, INT_EDGE_FALLING, &wfi) ; | |||
sleep(1); | |||
StartSequence (INT_EDGE_FALLING, OUTpin); | |||
printf("Testing close\n"); | |||
wiringPiISRStop (IRQpin) ; | |||
printf("Testing IRQ @ GPIO%d with trigger @ GPIO%d both\n", IRQpin, OUTpin); | |||
wiringPiISR (IRQpin, INT_EDGE_BOTH, &wfi) ; | |||
sleep(1); | |||
StartSequence (INT_EDGE_BOTH, OUTpin); | |||
printf("Testing close\n"); | |||
wiringPiISRStop (IRQpin) ; | |||
for (int count=0; count<2; count++) { | |||
printf("Measuring duration IRQ @ GPIO%d with trigger @ GPIO%d rising\n", IRQpin, OUTpin); | |||
DurationTime(INT_EDGE_RISING, OUTpin, IRQpin); | |||
printf("Measuring duration IRQ @ GPIO%d with trigger @ GPIO%d falling\n", IRQpin, OUTpin); | |||
DurationTime(INT_EDGE_FALLING, OUTpin, IRQpin); | |||
} | |||
pinMode(OUTpin, INPUT); | |||
return UnitTestState(); | |||
} |
@@ -0,0 +1,186 @@ | |||
// WiringPi test program: PWM test | |||
// Compile: gcc -Wall wiringpi_test8_pwm.c -o wiringpi_test8_pwm -lwiringPi | |||
#include "wpi_test.h" | |||
#include <string.h> | |||
#include <errno.h> | |||
#include <unistd.h> | |||
#include <sys/time.h> | |||
#include <time.h> | |||
#include <stdint.h> | |||
int PWM_OUT[4] = { 18, 12, 13, 19 }; | |||
int PWM_IN[4] = { 17, 13, 12, 26 }; | |||
volatile int gCounter = 0; | |||
//Interrupt Service Routine for FREQIN | |||
void ISR_FREQIN(void) { | |||
gCounter++; | |||
} | |||
double MeasureAndCheckFreqTolerance(const char* msg, double expect_freq, int tolerance) { | |||
double fFrequency; | |||
clock_t CPUClockBegin, CPUClockEnd; | |||
int CountBegin, CountEnd; | |||
double CPUClockInterval, CountInterval; | |||
double elapsed_time, CPULoad; | |||
uint64_t tbegin, tend; | |||
int SleepMs = 1200; | |||
CPUClockBegin = clock(); | |||
tbegin = piMicros64(); | |||
CountBegin = gCounter; | |||
delay(SleepMs); | |||
CountEnd = gCounter; | |||
CPUClockEnd = clock(); | |||
tend = piMicros64(); | |||
elapsed_time = (double)(tend-tbegin)/1.0e6; | |||
CountInterval = CountEnd - CountBegin; | |||
CPUClockInterval = CPUClockEnd - CPUClockBegin; | |||
CPULoad = CPUClockInterval*100.0 / CLOCKS_PER_SEC / elapsed_time; | |||
fFrequency = CountInterval / elapsed_time / 1000; | |||
printf("\nInterval: time: %.6f sec (CPU: %3.1f %%), count: %g -> frequency: %.3f kHz\n", | |||
elapsed_time, CPULoad, CountInterval, fFrequency); | |||
CheckSameDouble("Wait for freq. meas.", elapsed_time, SleepMs/1000.0, 0.1); //100ms tolerance. maybe problematic on high freq/cpu load | |||
CheckSameDouble(msg, fFrequency, expect_freq, (expect_freq!=0.0) ? expect_freq*tolerance/100 : 0.1); //x% tolerance | |||
return fFrequency; | |||
} | |||
double MeasureAndCheckFreq(const char* msg, double expect_freq) { | |||
return MeasureAndCheckFreqTolerance(msg, expect_freq, 2); | |||
} | |||
int main (void) { | |||
int major, minor; | |||
int PWM, FREQIN; | |||
wiringPiVersion(&major, &minor); | |||
printf("WiringPi PWM GPIO test program 8\n"); | |||
printf("PWM/ISR test (WiringPi %d.%d)\n", major, minor); | |||
wiringPiSetupGpio() ; | |||
int rev, mem, maker, overVolted, RaspberryPiModel; | |||
piBoardId(&RaspberryPiModel, &rev, &mem, &maker, &overVolted); | |||
CheckNotSame("Model: ", RaspberryPiModel, -1); | |||
PWM = 18; | |||
FREQIN = 17; | |||
printf("Register ISR@%d\n", PWM); | |||
// INT_EDGE_BOTH, INT_EDGE_FALLING, INT_EDGE_RISING only one ISR per input | |||
int result = wiringPiISR(FREQIN, INT_EDGE_RISING, &ISR_FREQIN); | |||
CheckSame("Register ISR", result, 0); | |||
if (result < 0) { | |||
printf("Unable to setup ISR for GPIO %d (%s)\n\n", FREQIN, strerror(errno)); | |||
return UnitTestState(); | |||
} | |||
printf("\n==> Set pwm 0%% and enable PWM output with PWM_OUTPUT (default mode)\n"); | |||
pwmWrite(PWM, 0); // <-- Allways start with 0 Hz | |||
pinMode(PWM, PWM_OUTPUT); //Mode BAL, pwmr=1024, pwmc=32 | |||
delay(250); | |||
double duty_fact = 0.0; | |||
double freq = 0.0; | |||
MeasureAndCheckFreq("PMW Pi0-4:BAL/Pi5:MS without change", freq); | |||
printf("Keep pwm 0%% and set mode MS\n"); | |||
pwmSetMode(PWM_MODE_MS); | |||
delay(250); | |||
MeasureAndCheckFreq("PWM MS without change", freq); | |||
int pwmc; | |||
int pwmr; | |||
int pwm; | |||
if (RaspberryPiModel!=PI_MODEL_5) { | |||
pwmSetMode(PWM_MODE_BAL); | |||
pwmc = 1000; | |||
pwmr = 1024; | |||
pwm = 512; | |||
duty_fact = (double)pwm/(double)pwmr; | |||
printf("\n==> set mode BAL, pwmc=%d, pwmr=%d, pwm=%d, duty=%g%%\n", pwmc, pwmr, pwm, duty_fact*100); | |||
pwmSetClock(pwmc); | |||
pwmSetRange(pwmr); | |||
pwmWrite(PWM, pwm); | |||
delay(250); | |||
freq = 19200.0/pwmc*duty_fact; | |||
MeasureAndCheckFreq("PWM BAL with settings", freq); | |||
} | |||
pwmSetMode(PWM_MODE_MS); | |||
pwmc = 10; | |||
pwmr = 256; | |||
pwm = 171; | |||
duty_fact = (double)pwm/(double)pwmr; | |||
printf("\n==> set mode MS, pwmc=%d, pwmr=%d, pwm%d, duty=%g%%\n", pwmc, pwmr, pwm, duty_fact*100); | |||
pwmSetClock(pwmc); | |||
pwmSetRange(pwmr); | |||
pwmWrite(PWM, pwm); | |||
delay(250); | |||
freq = 19200.0/(double)pwmc/(double)pwmr; | |||
MeasureAndCheckFreq("PWM BAL with settings", freq); | |||
printf("set PWM@GPIO%d (output) off\n", PWM); | |||
pinMode(PWM, PM_OFF); | |||
delay(1000); | |||
MeasureAndCheckFreq("PMW off", 0.0); | |||
if (RaspberryPiModel!=PI_MODEL_5) { | |||
pwmc = 800; | |||
pwmr = 2048; | |||
pwm = 768; | |||
duty_fact = (double)pwm/(double)pwmr; | |||
printf("\n==> set mode PWM_BAL_OUTPUT, pwmc=%d, pwmr=%d, pwm%d, duty=%g%%\n", pwmc, pwmr, pwm, duty_fact*100); | |||
pwmSetRange(pwmr); | |||
pwmSetClock(pwmc); | |||
pwmWrite(PWM, pwm); | |||
pinMode(PWM, PWM_BAL_OUTPUT); | |||
delay(250); | |||
freq = 19200.0/pwmc*duty_fact; | |||
MeasureAndCheckFreq("PMW BAL start values", freq); | |||
} | |||
printf("set PWM@GPIO%d (output) off\n", PWM); | |||
pinMode(PWM, PM_OFF); | |||
delay(1000); | |||
MeasureAndCheckFreq("PMW off", 0.0); | |||
printf("Set pwm settings and enable PWM\n"); | |||
pwmc = 5; | |||
pwmr = 1024; | |||
pwm = 768; | |||
duty_fact = (double)pwm/(double)pwmr; | |||
printf("\n==> set mode PWM_MS_OUTPUT, pwmc=%d, pwmr=%d, pwm%d, duty=%g%%\n", pwmc, pwmr, pwm, duty_fact*100); | |||
pwmSetRange(pwmr); | |||
pwmSetClock(pwmc); | |||
pwmWrite(PWM, pwm); | |||
pinMode(PWM, PWM_MS_OUTPUT); | |||
delay(250); | |||
freq = 19200.0/(double)pwmc/(double)pwmr; | |||
MeasureAndCheckFreq("PMW MS start values", freq); | |||
printf("set PWM@GPIO%d (output) off\n", PWM); | |||
pinMode(PWM, PM_OFF); | |||
delay(1000); | |||
MeasureAndCheckFreq("PMW off", 0.0); | |||
printf("set PWM0 CLK off @ Pi5\n"); | |||
pwmSetClock(0); | |||
result = wiringPiISRStop(FREQIN); | |||
CheckSame("\n\nRelease ISR", result, 0); | |||
if (result < 0) { | |||
printf("Unable to release ISR for GPIO %d (%s)\n\n", FREQIN, strerror(errno)); | |||
return UnitTestState(); | |||
} | |||
return UnitTestState(); | |||
} |
@@ -0,0 +1,225 @@ | |||
// WiringPi test program: PWM test | |||
// Compile: gcc -Wall wiringpi_test9_pwm.c -o wiringpi_test9_pwm -lwiringPi | |||
#include "wpi_test.h" | |||
#include <string.h> | |||
#include <errno.h> | |||
#include <unistd.h> | |||
#include <sys/time.h> | |||
#include <time.h> | |||
#include <stdint.h> | |||
int PWM_OUT[4] = { 18, 12, 13, 19 }; | |||
int PWM_IN[4] = { 17, 13, 12, 26 }; | |||
volatile int gCounter = 0; | |||
//Interrupt Service Routine for FREQIN | |||
void ISR_FREQIN(void) { | |||
gCounter++; | |||
} | |||
double MeasureAndCheckFreq(const char* msg, double expect_freq) { | |||
double fFrequency; | |||
clock_t CPUClockBegin, CPUClockEnd; | |||
int CountBegin, CountEnd; | |||
double CPUClockInterval, CountInterval; | |||
double elapsed_time, CPULoad; | |||
uint64_t tbegin, tend; | |||
int SleepMs = 1200; | |||
CPUClockBegin = clock(); | |||
tbegin = piMicros64(); | |||
CountBegin = gCounter; | |||
delay(SleepMs); | |||
CountEnd = gCounter; | |||
CPUClockEnd = clock(); | |||
tend = piMicros64(); | |||
elapsed_time = (double)(tend-tbegin)/1.0e6; | |||
CountInterval = CountEnd - CountBegin; | |||
CPUClockInterval = CPUClockEnd - CPUClockBegin; | |||
CPULoad = CPUClockInterval*100.0 / CLOCKS_PER_SEC / elapsed_time; | |||
fFrequency = CountInterval / elapsed_time / 1000; | |||
printf("\nInterval: time: %.6f sec (CPU: %3.1f %%), count: %g -> frequency: %.3f kHz\n", | |||
elapsed_time, CPULoad, CountInterval, fFrequency); | |||
CheckSameDouble("Wait for freq. meas.", elapsed_time, SleepMs/1000.0, 0.1); //100ms tolerance. maybe problematic on high freq/cpu load | |||
CheckSameDouble(msg, fFrequency, expect_freq, expect_freq*2/100); //2% toleranc | |||
return fFrequency; | |||
} | |||
int tests_pwmc[7] = {1456, 1000, 512, 100, 2000, 3000, 4000}; | |||
int tests_duty[7] = { 512, 768, 682, 922, 256, 341, 102}; | |||
int tests_pwmr[12]= { 50, 100, 200, 512, 1024, 1456, 2000, 3000, 5000, 10000, 15000, 20000}; | |||
int tests_pwm[3] = { 50, 25, 75}; | |||
int main (void) { | |||
int major, minor; | |||
char msg[255]; | |||
int testruns = 4; | |||
int PWM, FREQIN; | |||
wiringPiVersion(&major, &minor); | |||
printf("WiringPi GPIO test program 9\n"); | |||
printf("PWM/ISR test (WiringPi %d.%d)\n", major, minor); | |||
wiringPiSetupGpio() ; | |||
int rev, mem, maker, overVolted, RaspberryPiModel; | |||
piBoardId(&RaspberryPiModel, &rev, &mem, &maker, &overVolted); | |||
CheckNotSame("Model: ", RaspberryPiModel, -1); | |||
int Pi4 = 0; | |||
int Pi5 = 0; | |||
double MaxFreq = 100.0; | |||
switch(RaspberryPiModel) { | |||
case PI_MODEL_A: | |||
case PI_MODEL_B: | |||
case PI_MODEL_BP: | |||
case PI_MODEL_AP: | |||
case PI_MODEL_ZERO: | |||
case PI_MODEL_ZERO_W: | |||
case PI_MODEL_CM: | |||
MaxFreq = 13.0; // 12.5 kHz -> ~40% CPU@800 MHz | |||
printf(" - Pi1/BCM2835 detected, will skip tests with frequency above %g kHz\n", MaxFreq); | |||
break; | |||
case PI_MODEL_2: | |||
MaxFreq = 20.0; | |||
printf(" - Pi2/BCM2836 detected, will skip tests with frequency above %g kHz\n", MaxFreq); | |||
break; | |||
case PI_MODEL_3B: | |||
case PI_MODEL_CM3: | |||
case PI_MODEL_3BP: | |||
case PI_MODEL_3AP: | |||
case PI_MODEL_CM3P: | |||
case PI_MODEL_ZERO_2W: | |||
MaxFreq = 50.0; | |||
printf(" - Pi3/BCM2837 detected, will skip tests with frequency above %g kHz\n", MaxFreq); | |||
break; | |||
case PI_MODEL_4B: | |||
case PI_MODEL_400: | |||
case PI_MODEL_CM4: | |||
case PI_MODEL_CM4S: | |||
Pi4 = 1; | |||
break; | |||
case PI_MODEL_5: | |||
Pi5 = 1; | |||
break; | |||
} | |||
if (!piBoard40Pin()) { | |||
testruns = 1; // only fist PWM0, supported | |||
} | |||
for (int testrun=0; testrun<testruns; testrun++) { | |||
PWM = PWM_OUT[testrun]; | |||
FREQIN = PWM_IN[testrun]; | |||
printf("using PWM@GPIO%d (output) and GPIO%d (input)\n", PWM, FREQIN); | |||
delay(1000); | |||
printf("\n"); | |||
printf("*********************************\n"); | |||
printf("* PWM BAL mode *\n"); | |||
printf("*********************************\n"); | |||
const int pmw = 512; | |||
int pmwr = 1024; //default! | |||
printf("Set pwm 50%% and enable PWM output (600 kHz?) \n"); | |||
pwmWrite(PWM, pmw); //50% Duty | |||
pinMode(PWM, PWM_OUTPUT); //Mode BAL, pwmr=1024, pwmc=32 | |||
printf("pwmc 4.8kHz\n"); | |||
pwmSetClock(2000); | |||
delay(250); | |||
printf("Register ISR@%d\n", PWM); | |||
// INT_EDGE_BOTH, INT_EDGE_FALLING, INT_EDGE_RISING only one ISR per input | |||
int result = wiringPiISR(FREQIN, INT_EDGE_RISING, &ISR_FREQIN); | |||
CheckSame("Register ISR", result, 0); | |||
if (result < 0) { | |||
printf("Unable to setup ISR for GPIO %d (%s)\n\n", FREQIN, strerror(errno)); | |||
return UnitTestState(); | |||
} | |||
printf("Wait for start ...\n"); | |||
delay(500); | |||
printf("Start:\n"); | |||
//MeasureAndCheckFreq("50\% Duty (default)", 300.000); //FAIL , freq (pwmc=32) to high for irq count | |||
if(!Pi5) { | |||
for (int c_duty=0, c_duty_end = sizeof(tests_duty)/sizeof(tests_duty[0]); c_duty<c_duty_end; c_duty++) { | |||
double tests_duty_corr; | |||
if (tests_duty[c_duty]>(pmwr/2)) { | |||
tests_duty_corr = pmwr-tests_duty[c_duty]; | |||
} else { | |||
tests_duty_corr = tests_duty[c_duty]; | |||
} | |||
double duty_fact = tests_duty_corr/(double)pmwr; | |||
printf("\n%d/%d set duty %d/%d\n",c_duty+1, c_duty_end, tests_duty[c_duty], pmwr); | |||
pwmWrite(PWM, tests_duty[c_duty]); | |||
for (int c_pwmc=0, end = sizeof(tests_pwmc)/sizeof(tests_pwmc[0]); c_pwmc<end; c_pwmc++) { | |||
int pwmc = tests_pwmc[c_pwmc]; | |||
if (Pi4 && pwmc>1456) { | |||
printf("* Set clock (pwmc) %d not possible on BCM2711 system (OSC 54 MHz), ignore\n", pwmc); | |||
continue; | |||
} | |||
double freq = 19200.0/pwmc*duty_fact; | |||
if (freq>MaxFreq) { | |||
printf("* Set clock (pwmc) %d not possible on system (to slow to measure %g kHz with ISR), ignore\n", pwmc, freq); | |||
continue; | |||
} | |||
pwmSetClock(pwmc); | |||
delay(250); | |||
sprintf(msg, "Set Clock (pwmc) %d, %d%% duty", pwmc, tests_duty[c_duty]*100/pmwr); | |||
MeasureAndCheckFreq(msg, freq); | |||
} | |||
} | |||
} | |||
delay(250); | |||
printf("\n"); | |||
printf("*********************************\n"); | |||
printf("* PWM MS mode *\n"); | |||
printf("*********************************\n"); | |||
int pwmc = 10; | |||
printf("SetClock pwmc=%d and enable MS mode\n", pwmc); | |||
pwmSetClock(pwmc); | |||
pwmSetMode(PWM_MODE_MS); | |||
printf("Wait for start ...\n"); | |||
delay(250); | |||
printf("Start:\n"); | |||
for (int c_pmwr=0, c_pmwr_end = sizeof(tests_pwmr)/sizeof(tests_pwmr[0]); c_pmwr<c_pmwr_end; c_pmwr++) { | |||
int pwmr = tests_pwmr[c_pmwr]; | |||
double freq = 19200.0/(double)pwmc/(double)pwmr; | |||
if (freq>MaxFreq) { | |||
printf("* Set Clock (pwmc, pwmr) %d, %d not possible on system (to slow to measure %g kHz with ISR), ignore\n", pwmc, pwmr, freq); | |||
continue; | |||
} | |||
sprintf(msg, "Set range (pwmr) %d", pwmr); | |||
pwmSetRange(pwmr); | |||
for (int c_pmw=0, c_pmw_end = sizeof(tests_pwm)/sizeof(tests_pwm[0]); c_pmw<c_pmw_end; c_pmw++) { | |||
int pwm = pwmr*tests_pwm[c_pmw]/100; | |||
sprintf(msg, "Set pwm %d/%d (%d %%)", pwm, pwmr, tests_pwm[c_pmw]); | |||
pwmWrite(PWM, pwm); | |||
delay(250); | |||
MeasureAndCheckFreq(msg, freq); | |||
} | |||
} | |||
result = wiringPiISRStop(FREQIN); | |||
CheckSame("\n\nRelease ISR", result, 0); | |||
if (result < 0) { | |||
printf("Unable to release ISR for GPIO %d (%s)\n\n", FREQIN, strerror(errno)); | |||
return UnitTestState(); | |||
} | |||
printf("set PWM@GPIO%d (output) back to input\n", PWM); | |||
pinMode(PWM, INPUT); | |||
} | |||
printf("\nDid %d PWM GPIO tests with model %d\n", testruns, RaspberryPiModel); | |||
return UnitTestState(); | |||
} |
@@ -47,7 +47,7 @@ void checkVoltage(float expect, const char* szexpect) { | |||
int CH1 = AnalogRead(spiChannel, 1, &returnvalue); | |||
//float value0 = CH0 * fRefVoltage / fResolution; | |||
float value1 = CH1 * fRefVoltage / fResolution; | |||
CheckSameFloat(szexpect, value1, expect); | |||
CheckSameFloat(szexpect, value1, expect, 0.1); | |||
delayMicroseconds(300); | |||
} | |||
@@ -20,14 +20,14 @@ void CheckGPIO(int GPIO, int GPIOIN, int out) { | |||
int in = out; | |||
if (GPIOIN>=0) { | |||
in = digitalRead(GPIOIN); | |||
in = digitalRead(GPIOIN); | |||
} | |||
int readback = digitalRead(GPIO); | |||
int pass = 0; | |||
if (out==readback && in==out) { | |||
pass = 1; | |||
} | |||
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); | |||
@@ -44,6 +44,11 @@ void CheckGPIO(int GPIO, int GPIOIN, int out) { | |||
} | |||
void CheckInversGPIO(int GPIO, int GPIOIN, int out) { | |||
CheckGPIO(GPIO, GPIOIN, out==HIGH ? LOW : HIGH); | |||
} | |||
void digitalWriteEx(int GPIO, int GPIOIN, int mode) { | |||
digitalWrite(GPIO, mode); | |||
delayMicroseconds(5000); | |||
@@ -90,8 +95,21 @@ void CheckNotSame(const char* msg, int value, int expect) { | |||
} | |||
void CheckSameFloat(const char* msg, float value, float expect) { | |||
if (fabs(value-expect)<0.08) { | |||
void CheckSameFloat(const char* msg, float value, float expect, float epsilon) { | |||
if (fabs(value-expect)<epsilon) { | |||
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; | |||
} | |||
} | |||
void CheckSameFloatX(const char* msg, float value, float expect) { | |||
return CheckSameFloat(msg, value, expect, 0.08f); | |||
} | |||
void CheckSameDouble(const char* msg, double value, double expect, double epsilon) { | |||
if (fabs(value-expect)<epsilon) { | |||
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); | |||
@@ -118,14 +118,20 @@ struct wiringPiNodeStruct *wiringPiNodes = NULL ; | |||
// Port function select bits | |||
#define FSEL_INPT 0b000 | |||
#define FSEL_OUTP 0b001 | |||
#define FSEL_ALT0 0b100 | |||
#define FSEL_ALT1 0b101 | |||
#define FSEL_ALT2 0b110 | |||
#define FSEL_ALT3 0b111 | |||
#define FSEL_ALT4 0b011 | |||
#define FSEL_ALT5 0b010 | |||
#define FSEL_INPT 0b000 //0 | |||
#define FSEL_OUTP 0b001 //1 | |||
#define FSEL_ALT0 0b100 //4 | |||
#define FSEL_ALT1 0b101 //5 | |||
#define FSEL_ALT2 0b110 //6 | |||
#define FSEL_ALT3 0b111 //7 | |||
#define FSEL_ALT4 0b011 //3 | |||
#define FSEL_ALT5 0b010 //2 | |||
//RP1 defines | |||
#define FSEL_ALT6 8 | |||
#define FSEL_ALT7 9 | |||
#define FSEL_ALT8 10 | |||
#define FSEL_ALT9 11 | |||
//RP1 chip (@Pi5) - 3.1.1. Function select | |||
#define RP1_FSEL_ALT0 0x00 | |||
@@ -166,10 +172,40 @@ 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); | |||
const unsigned int RP1_PWM0_GLOBAL_CTRL = 0; | |||
const unsigned int RP1_PWM0_FIFO_CTRL = 1; | |||
const unsigned int RP1_PWM0_COMMON_RANGE= 2; | |||
const unsigned int RP1_PWM0_COMMON_DUTY = 3; | |||
const unsigned int RP1_PWM0_DUTY_FIFO = 4; | |||
const unsigned int RP1_PWM0_CHAN_START = 5; | |||
//offset channel | |||
const unsigned int RP1_PWM0_CHAN_CTRL = 0; | |||
const unsigned int RP1_PWM0_CHAN_RANGE = 1; | |||
const unsigned int RP1_PWM0_CHAN_PHASE = 2; | |||
const unsigned int RP1_PWM0_CHAN_DUTY = 3; | |||
const unsigned int RP1_PWM0_CHAN_OFFSET= 4; | |||
const unsigned int RP1_PWM0_CHAN0_RANGE = RP1_PWM0_CHAN_START+RP1_PWM0_CHAN_OFFSET*0+RP1_PWM0_CHAN_RANGE; | |||
const unsigned int RP1_PWM0_CHAN1_RANGE = RP1_PWM0_CHAN_START+RP1_PWM0_CHAN_OFFSET*1+RP1_PWM0_CHAN_RANGE; | |||
const unsigned int RP1_PWM0_CHAN2_RANGE = RP1_PWM0_CHAN_START+RP1_PWM0_CHAN_OFFSET*2+RP1_PWM0_CHAN_RANGE; | |||
const unsigned int RP1_PWM0_CHAN3_RANGE = RP1_PWM0_CHAN_START+RP1_PWM0_CHAN_OFFSET*3+RP1_PWM0_CHAN_RANGE; | |||
const unsigned int RP1_PWM_CTRL_SETUPDATE = 0x80000000; // Bit 32 | |||
const unsigned int RP1_PWM_TRAIL_EDGE_MS = 0x1; | |||
const unsigned int RP1_PWM_FIFO_POP_MASK = 0x100; // Bit 8 | |||
const unsigned int RP1_CLK_PWM0_CTRL_DISABLE_MAGIC = 0x10000000; // Default after boot | |||
const unsigned int RP1_CLK_PWM0_CTRL_ENABLE_MAGIC = 0x11000840; // Reverse engineered, because of missing documentation, don't known meaning of of bits | |||
const unsigned int CLK_PWM0_CTRL = (0x00074/4); | |||
const unsigned int CLK_PWM0_DIV_INT = (0x00078/4); | |||
const unsigned int CLK_PWM0_DIV_FRAC = (0x0007C/4); | |||
const unsigned int CLK_PWM0_SEL = (0x00080/4); | |||
//RP1 chip (@Pi5) address | |||
const unsigned long long RP1_64_BASE_Addr = 0x1f000d0000; | |||
const unsigned int RP1_BASE_Addr = 0x40000000; | |||
const unsigned int RP1_PWM0_Addr = 0x40098000; // Adress is not mapped to gpiomem device! | |||
const unsigned int RP1_CLOCK_Addr = 0x40018000; // Adress is not mapped to gpiomem device, lower than RP1_IO0_Addr | |||
const unsigned int RP1_PWM0_Addr = 0x40098000; // Adress is not mapped to gpiomem device, lower than RP1_IO0_Addr | |||
const unsigned int RP1_IO0_Addr = 0x400d0000; | |||
const unsigned int RP1_SYS_RIO0_Addr = 0x400e0000; | |||
const unsigned int RP1_PADS0_Addr = 0x400f0000; | |||
@@ -195,7 +231,7 @@ const unsigned short pciemem_RP1_Ventor= 0x1de4; | |||
const unsigned short pciemem_RP1_Device= 0x0001; | |||
static volatile unsigned int GPIO_PADS ; | |||
static volatile unsigned int GPIO_CLOCK_BASE ; | |||
static volatile unsigned int GPIO_CLOCK_ADR ; | |||
static volatile unsigned int GPIO_BASE ; | |||
static volatile unsigned int GPIO_TIMER ; | |||
static volatile unsigned int GPIO_PWM ; | |||
@@ -238,6 +274,11 @@ static int wiringPiSetuped = FALSE ; | |||
#define PWM1_SERIAL 0x0200 // Run in serial mode | |||
#define PWM1_ENABLE 0x0100 // Channel Enable | |||
const int PWMCLK_DIVI_MAX = 0xFFF; // 3 Byte max size for Clock devider | |||
const int OSC_FREQ_DEFAULT = 192; // x100kHz OSC | |||
const int OSC_FREQ_BCM2711 = 540; // x100kHz OSC | |||
const int OSC_FREQ_BCM2712 = 500; // x100kHz OSC - cat /sys/kernel/debug/clk/clk_summary | grep pwm0 | |||
// Timer | |||
// Word offsets | |||
@@ -557,6 +598,27 @@ int piBoard() { | |||
return RaspberryPiModel<0 ? 0 : 1; | |||
} | |||
int piBoard40Pin() { | |||
if (!piBoard()){ | |||
// Board not detected | |||
return -1; | |||
} | |||
switch(RaspberryPiModel){ | |||
case PI_MODEL_A: | |||
case PI_MODEL_B: | |||
return 0; | |||
// PI_MODEL_CM | |||
// PI_MODEL_CM3 | |||
// PI_MODEL_CM4 | |||
// PI_MODEL_CM4S | |||
// ? guess yes | |||
default: | |||
return 1; | |||
} | |||
} | |||
int GetMaxPin() { | |||
return PI_MODEL_5 == RaspberryPiModel ? 27 : 63; | |||
} | |||
@@ -564,10 +626,10 @@ int GetMaxPin() { | |||
#define RETURN_ON_MODEL5 if (PI_MODEL_5 == RaspberryPiModel) { if (wiringPiDebug) printf("Function not supported on Pi5\n"); return; } | |||
int FailOnModel5() { | |||
int FailOnModel5(const char *function) { | |||
if (PI_MODEL_5 == RaspberryPiModel) { | |||
return wiringPiFailure (WPI_ALMOST, "Function not supported on Raspberry Pi 5.\n" | |||
" Unable to continue. Keep an eye of new versions at https://github.com/wiringpi/wiringpi\n") ; | |||
return wiringPiFailure (WPI_ALMOST, "Function '%s' not supported on Raspberry Pi 5.\n" | |||
" Unable to continue. Keep an eye of new versions at https://github.com/wiringpi/wiringpi\n", function) ; | |||
} | |||
return 0; | |||
} | |||
@@ -690,8 +752,8 @@ static uint8_t gpioToPUDCLK [] = | |||
static uint8_t gpioToPwmALT [] = | |||
{ | |||
0, 0, 0, 0, 0, 0, 0, 0, // 0 -> 7 | |||
0, 0, 0, 0, FSEL_ALT0, FSEL_ALT0, 0, 0, // 8 -> 15 | |||
0, 0, FSEL_ALT5, FSEL_ALT5, 0, 0, 0, 0, // 16 -> 23 | |||
0, 0, 0, 0, FSEL_ALT0, FSEL_ALT0, 0, 0, // 8 -> 15 | |||
0, 0, FSEL_ALT5, FSEL_ALT5, 0, 0, 0, 0, // 16 -> 23 | |||
0, 0, 0, 0, 0, 0, 0, 0, // 24 -> 31 | |||
0, 0, 0, 0, 0, 0, 0, 0, // 32 -> 39 | |||
FSEL_ALT0, FSEL_ALT0, 0, 0, 0, FSEL_ALT0, 0, 0, // 40 -> 47 | |||
@@ -706,8 +768,8 @@ static uint8_t gpioToPwmALT [] = | |||
static uint8_t gpioToPwmPort [] = | |||
{ | |||
0, 0, 0, 0, 0, 0, 0, 0, // 0 -> 7 | |||
0, 0, 0, 0, PWM0_DATA, PWM1_DATA, 0, 0, // 8 -> 15 | |||
0, 0, PWM0_DATA, PWM1_DATA, 0, 0, 0, 0, // 16 -> 23 | |||
0, 0, 0, 0, PWM0_DATA, PWM1_DATA, 0, 0, // 8 -> 15 | |||
0, 0, PWM0_DATA, PWM1_DATA, 0, 0, 0, 0, // 16 -> 23 | |||
0, 0, 0, 0, 0, 0, 0, 0, // 24 -> 31 | |||
0, 0, 0, 0, 0, 0, 0, 0, // 32 -> 39 | |||
PWM0_DATA, PWM1_DATA, 0, 0, 0, PWM1_DATA, 0, 0, // 40 -> 47 | |||
@@ -1131,6 +1193,7 @@ void piBoardId (int *model, int *rev, int *mem, int *maker, int *warranty) | |||
case PI_MODEL_4B: | |||
case PI_MODEL_400: | |||
case PI_MODEL_CM4: | |||
case PI_MODEL_CM4S: | |||
piGpioBase = GPIO_PERI_BASE_2711 ; | |||
piGpioPupOffset = GPPUPPDN0 ; | |||
break ; | |||
@@ -1261,7 +1324,7 @@ void setPadDrive (int group, int value) | |||
int getAlt (int pin) | |||
{ | |||
int fSel, shift, alt ; | |||
int alt; | |||
pin &= 63 ; | |||
@@ -1292,29 +1355,28 @@ int getAlt (int pin) | |||
11 = alternate function 9 | |||
*/ | |||
switch(alt) { | |||
case 0: return 4; | |||
case 1: return 5; | |||
case 2: return 6; | |||
case 3: return 7; | |||
case 4: return 3; | |||
case 0: return FSEL_ALT0; | |||
case 1: return FSEL_ALT1; | |||
case 2: return FSEL_ALT2; | |||
case 3: return FSEL_ALT3; | |||
case 4: return FSEL_ALT4; | |||
case RP1_FSEL_GPIO: { | |||
unsigned int outputmask = gpio[2*pin] & 0x3000; //Bit13-OETOPAD + Bit12-OEFROMPERI | |||
return (outputmask==0x3000) ? 1 : 0; //1=OUT 0=IN | |||
return (outputmask==0x3000) ? FSEL_OUTP : FSEL_INPT; | |||
} | |||
case 6: return 8; | |||
case 7: return 9; | |||
case 8: return 10; | |||
case 9: return 11; | |||
case 6: return FSEL_ALT6; | |||
case 7: return FSEL_ALT7; | |||
case 8: return FSEL_ALT8; | |||
case RP1_FSEL_NONE: return FSEL_ALT9; | |||
default:return alt; | |||
} | |||
} else { | |||
fSel = gpioToGPFSEL [pin] ; | |||
shift = gpioToShift [pin] ; | |||
int fSel = gpioToGPFSEL [pin] ; | |||
int shift = gpioToShift [pin] ; | |||
alt = (*(gpio + fSel) >> shift) & 7 ; | |||
} | |||
return alt ; | |||
return alt; | |||
} | |||
@@ -1333,11 +1395,20 @@ void pwmSetMode (int mode) | |||
{ | |||
if ((wiringPiMode == WPI_MODE_PINS) || (wiringPiMode == WPI_MODE_PHYS) || (wiringPiMode == WPI_MODE_GPIO)) | |||
{ | |||
FailOnModel5(); | |||
if (mode == PWM_MODE_MS) | |||
if (PI_MODEL_5 == RaspberryPiModel) { | |||
if(mode != PWM_MODE_MS) { | |||
fprintf(stderr, "pwmSetMode: Raspberry Pi 5 missing feature PWM BAL mode\n"); | |||
} | |||
return; | |||
} | |||
if (mode == PWM_MODE_MS) { | |||
*(pwm + PWM_CONTROL) = PWM0_ENABLE | PWM1_ENABLE | PWM0_MS_MODE | PWM1_MS_MODE ; | |||
else | |||
} else { | |||
*(pwm + PWM_CONTROL) = PWM0_ENABLE | PWM1_ENABLE ; | |||
} | |||
if (wiringPiDebug) { | |||
printf ("Enable PWM mode: %s. Current register: 0x%08X\n", mode == PWM_MODE_MS ? "mark:space (freq. stable)" : "balanced (freq. change)", *(pwm + PWM_CONTROL)); | |||
} | |||
} | |||
} | |||
@@ -1351,11 +1422,32 @@ void pwmSetMode (int mode) | |||
void pwmSetRange (unsigned int range) | |||
{ | |||
FailOnModel5(); | |||
if ((wiringPiMode == WPI_MODE_PINS) || (wiringPiMode == WPI_MODE_PHYS) || (wiringPiMode == WPI_MODE_GPIO)) | |||
{ | |||
*(pwm + PWM0_RANGE) = range ; delayMicroseconds (10) ; | |||
*(pwm + PWM1_RANGE) = range ; delayMicroseconds (10) ; | |||
/* would be possible on ms mode but not on bal, deactivated, use pwmc modify instead | |||
if (piGpioBase == GPIO_PERI_BASE_2711) { | |||
range = (OSC_FREQ_BCM2711*range)/OSC_FREQ_DEFAULT; | |||
} | |||
*/ | |||
if (!pwm) { | |||
fprintf(stderr, "wiringPi: pwmSetRange but no pwm memory available, ignoring\n"); | |||
return; | |||
} | |||
int readback = 0x00; | |||
if (PI_MODEL_5 == RaspberryPiModel) { | |||
pwm[RP1_PWM0_CHAN0_RANGE] = range; | |||
pwm[RP1_PWM0_CHAN1_RANGE] = range; | |||
pwm[RP1_PWM0_CHAN2_RANGE] = range; | |||
pwm[RP1_PWM0_CHAN3_RANGE] = range; | |||
readback = pwm[RP1_PWM0_CHAN0_RANGE]; | |||
} else { | |||
*(pwm + PWM0_RANGE) = range ; delayMicroseconds (10) ; | |||
*(pwm + PWM1_RANGE) = range ; delayMicroseconds (10) ; | |||
readback = *(pwm + PWM0_RANGE); | |||
} | |||
if (wiringPiDebug) { | |||
printf ("PWM range: %u. Current register: 0x%08X\n", range, readback); | |||
} | |||
} | |||
} | |||
@@ -1371,19 +1463,45 @@ void pwmSetRange (unsigned int range) | |||
void pwmSetClock (int divisor) | |||
{ | |||
uint32_t pwm_control ; | |||
FailOnModel5(); | |||
if (piGpioBase == GPIO_PERI_BASE_2711) | |||
{ | |||
divisor = 540*divisor/192; | |||
if (!clk) { | |||
fprintf(stderr, "wiringPi: pwmSetClock but no clk memory available, ignoring\n"); | |||
return; | |||
} | |||
divisor &= 4095 ; | |||
if (divisor > PWMCLK_DIVI_MAX) { | |||
divisor = PWMCLK_DIVI_MAX; // even on Pi5 4095 is OK | |||
} | |||
if (PI_MODEL_5 == RaspberryPiModel) { | |||
if (divisor < 1) { | |||
if (wiringPiDebug) { printf("Disable PWM0 clock"); } | |||
clk[CLK_PWM0_CTRL] = RP1_CLK_PWM0_CTRL_DISABLE_MAGIC; // 0 = disable on Pi5 | |||
} else { | |||
divisor = (OSC_FREQ_BCM2712*divisor)/OSC_FREQ_DEFAULT; | |||
if (wiringPiDebug) { | |||
printf ("PWM clock divisor: %d\n", divisor) ; | |||
} | |||
//clk[CLK_PWM0_CTRL] = RP1_CLK_PWM0_CTRL_DISABLE_MAGIC; | |||
//delayMicroseconds(100); | |||
clk[CLK_PWM0_DIV_INT] = divisor; | |||
clk[CLK_PWM0_DIV_FRAC] = 0; | |||
clk[CLK_PWM0_SEL] = 1; | |||
clk[CLK_PWM0_CTRL] = RP1_CLK_PWM0_CTRL_ENABLE_MAGIC; | |||
} | |||
return; | |||
} | |||
if (piGpioBase == GPIO_PERI_BASE_2711) { | |||
//calculate value for OSC 54MHz -> 19.2MHz | |||
// Pi 4 max divisor is 1456, Pi0-3 is 4095 (0xFFF) | |||
divisor = (OSC_FREQ_BCM2711*divisor)/OSC_FREQ_DEFAULT; | |||
} | |||
if (divisor < 1) { | |||
divisor = 1; | |||
} | |||
if ((wiringPiMode == WPI_MODE_PINS) || (wiringPiMode == WPI_MODE_PHYS) || (wiringPiMode == WPI_MODE_GPIO)) | |||
{ | |||
if (wiringPiDebug) | |||
printf ("Setting to: %d. Current: 0x%08X\n", divisor, *(clk + PWMCLK_DIV)) ; | |||
if (wiringPiDebug) { | |||
printf ("PWM clock divisor: Old register: 0x%08X\n", *(clk + PWMCLK_DIV)) ; | |||
} | |||
pwm_control = *(pwm + PWM_CONTROL) ; // preserve PWM_CONTROL | |||
// We need to stop PWM prior to stopping PWM clock in MS mode otherwise BUSY | |||
@@ -1408,8 +1526,9 @@ void pwmSetClock (int divisor) | |||
*(clk + PWMCLK_CNTL) = BCM_PASSWORD | 0x11 ; // Start PWM clock | |||
*(pwm + PWM_CONTROL) = pwm_control ; // restore PWM_CONTROL | |||
if (wiringPiDebug) | |||
printf ("Set to: %d. Now : 0x%08X\n", divisor, *(clk + PWMCLK_DIV)) ; | |||
if (wiringPiDebug) { | |||
printf ("PWM clock divisor %d. Current register: 0x%08X\n", divisor, *(clk + PWMCLK_DIV)); | |||
} | |||
} | |||
} | |||
@@ -1424,7 +1543,7 @@ void gpioClockSet (int pin, int freq) | |||
{ | |||
int divi, divr, divf ; | |||
FailOnModel5(); | |||
FailOnModel5("gpioClockSet"); | |||
pin &= 63 ; | |||
/**/ if (wiringPiMode == WPI_MODE_PINS) | |||
@@ -1438,9 +1557,9 @@ void gpioClockSet (int pin, int freq) | |||
divr = 19200000 % freq ; | |||
divf = (int)((double)divr * 4096.0 / 19200000.0) ; | |||
if (divi > 4095) | |||
divi = 4095 ; | |||
if (divi > PWMCLK_DIVI_MAX) { | |||
divi = PWMCLK_DIVI_MAX; | |||
} | |||
*(clk + gpioToClkCon [pin]) = BCM_PASSWORD | GPIO_CLOCK_SOURCE ; // Stop GPIO Clock | |||
while ((*(clk + gpioToClkCon [pin]) & 0x80) != 0) // ... and wait | |||
; | |||
@@ -1613,9 +1732,6 @@ int requestLine(int pin, unsigned int lineRequestFlags) { | |||
void pinModeAlt (int pin, int mode) | |||
{ | |||
int fSel, shift ; | |||
RETURN_ON_MODEL5 | |||
setupCheck ("pinModeAlt") ; | |||
if ((pin & PI_GPIO_MASK) == 0) // On-board pin | |||
@@ -1628,20 +1744,49 @@ void pinModeAlt (int pin, int mode) | |||
return ; | |||
if (PI_MODEL_5 == RaspberryPiModel) { | |||
//confusion! diffrent to to BCM! this is taking directly the value for the register | |||
/* | |||
"alt0" 0b100 | |||
"alt1" 0b101 | |||
"alt2" 0b110 | |||
"alt3" 0b111 | |||
"alt4" 0b011 | |||
"alt5" 0b010 | |||
*/ | |||
gpio[2*pin+1] = (mode & RP1_FSEL_NONE_HW) | RP1_DEBOUNCE_DEFAULT; //0-4 function, 5-11 debounce time | |||
int modeRP1; | |||
switch(mode) { | |||
case FSEL_ALT0: | |||
modeRP1 = 0; | |||
break; | |||
case FSEL_ALT1: | |||
modeRP1 = 1; | |||
break; | |||
case FSEL_ALT2: | |||
modeRP1 = 2; | |||
break; | |||
case FSEL_ALT3: | |||
modeRP1 = 3; | |||
break; | |||
case FSEL_ALT4: | |||
modeRP1 = 4; | |||
break; | |||
case FSEL_ALT5: | |||
modeRP1 = 5; | |||
break; | |||
case FSEL_ALT6: | |||
modeRP1 = 6; | |||
break; | |||
case FSEL_ALT7: | |||
modeRP1 = 7; | |||
break; | |||
case FSEL_ALT8: | |||
modeRP1 = 8; | |||
break; | |||
case FSEL_OUTP: | |||
case FSEL_INPT: | |||
modeRP1 = RP1_FSEL_GPIO; | |||
break; | |||
default: | |||
fprintf(stderr, "pinModeAlt: invalid mode %d\n", mode); | |||
return; | |||
} | |||
//printf("pinModeAlt: Pi5 alt pin %d to %d\n", pin, modeRP1); | |||
gpio[2*pin+1] = (modeRP1 & RP1_FSEL_NONE_HW) | RP1_DEBOUNCE_DEFAULT; //0-4 function, 5-11 debounce time | |||
} else { | |||
fSel = gpioToGPFSEL [pin] ; | |||
shift = gpioToShift [pin] ; | |||
int fSel = gpioToGPFSEL [pin] ; | |||
int shift = gpioToShift [pin] ; | |||
*(gpio + fSel) = (*(gpio + fSel) & ~(7 << shift)) | ((mode & 0x7) << shift) ; | |||
} | |||
@@ -1749,6 +1894,15 @@ void pinMode (int pin, int mode) | |||
} else { | |||
*(gpio + fSel) = (*(gpio + fSel) & ~(7 << shift)) ; // Sets bits to zero = input | |||
} | |||
if (PM_OFF==mode && !usingGpioMem && pwm && gpioToPwmALT[pin]>0) { //PWM pin -> reset | |||
pwmWrite(origPin, 0); | |||
int channel = gpioToPwmPort[pin]; | |||
if (channel>=0 && channel<=3 && PI_MODEL_5 == RaspberryPiModel) { | |||
unsigned int ctrl = pwm[RP1_PWM0_GLOBAL_CTRL]; | |||
pwm[RP1_PWM0_GLOBAL_CTRL] = (ctrl & ~(1<<channel)) | RP1_PWM_CTRL_SETUPDATE; | |||
//printf("Disable PWM0[%d] (0x%08X->0x%08X)\n", channel, ctrl, pwm[RP1_PWM0_GLOBAL_CTRL]); | |||
} | |||
} | |||
} else if (mode == OUTPUT) { | |||
if (PI_MODEL_5 == RaspberryPiModel) { | |||
pads[1+pin] = (pin<=8) ? RP1_PAD_DEFAULT_0TO8 : RP1_PAD_DEFAULT_FROM9; | |||
@@ -1766,22 +1920,41 @@ void pinMode (int pin, int mode) | |||
pinMode (origPin, PWM_OUTPUT) ; // Call myself to enable PWM mode | |||
pwmSetMode (PWM_MODE_MS) ; | |||
} | |||
else if (mode == PWM_OUTPUT) | |||
{ | |||
RETURN_ON_MODEL5 | |||
if ((alt = gpioToPwmALT [pin]) == 0) // Not a hardware capable PWM pin | |||
return ; | |||
else if (PWM_OUTPUT==mode || PWM_MS_OUTPUT==mode || PWM_BAL_OUTPUT==mode) { | |||
usingGpioMemCheck ("pinMode PWM") ; | |||
// Set pin to PWM mode | |||
*(gpio + fSel) = (*(gpio + fSel) & ~(7 << shift)) | (alt << shift) ; | |||
delayMicroseconds (110) ; // See comments in pwmSetClockWPi | |||
usingGpioMemCheck("pinMode PWM") ; // exit on error! | |||
alt = gpioToPwmALT[pin]; | |||
if (0==alt) { // Not a hardware capable PWM pin | |||
return; | |||
} | |||
int channel = gpioToPwmPort[pin]; | |||
if (PI_MODEL_5 == RaspberryPiModel) { | |||
if (channel>=0 && channel<=3) { | |||
// enable channel pwm m:s mode | |||
pwm[RP1_PWM0_CHAN_START+RP1_PWM0_CHAN_OFFSET*channel+RP1_PWM0_CHAN_CTRL] = (RP1_PWM_TRAIL_EDGE_MS | RP1_PWM_FIFO_POP_MASK); | |||
// enable pwm global | |||
unsigned int ctrl = pwm[RP1_PWM0_GLOBAL_CTRL]; | |||
pwm[RP1_PWM0_GLOBAL_CTRL] = ctrl | (1<<channel) | RP1_PWM_CTRL_SETUPDATE; | |||
//printf("Enable PWM0[%d] (0x%08X->0x%08X)\n", channel, ctrl, pwm[RP1_PWM0_GLOBAL_CTRL]); | |||
//change GPIO mode | |||
pads[1+pin] = RP1_PAD_DEFAULT_FROM9; // enable output | |||
pinModeAlt(origPin, alt); //switch to PWM mode | |||
} | |||
} else { | |||
// Set pin to PWM mode | |||
*(gpio + fSel) = (*(gpio + fSel) & ~(7 << shift)) | (alt << shift) ; | |||
delayMicroseconds (110) ; // See comments in pwmSetClockWPi | |||
pwmSetMode (PWM_MODE_BAL) ; // Pi default mode | |||
pwmSetRange (1024) ; // Default range of 1024 | |||
pwmSetClock (32) ; // 19.2 / 32 = 600KHz - Also starts the PWM | |||
if (PWM_OUTPUT==mode || PWM_BAL_OUTPUT==mode) { | |||
pwmSetMode(PWM_MODE_BAL); // Pi default mode | |||
} else { | |||
pwmSetMode(PWM_MODE_MS); | |||
} | |||
} | |||
if (PWM_OUTPUT==mode) { // predefine | |||
pwmSetRange (1024) ; // Default range of 1024 | |||
pwmSetClock (32) ; // 19.2 / 32 = 600KHz - Also starts the PWM | |||
} | |||
} | |||
else if (mode == GPIO_CLOCK) | |||
{ | |||
@@ -2121,7 +2294,6 @@ void pwmWrite (int pin, int value) | |||
{ | |||
struct wiringPiNodeStruct *node = wiringPiNodes ; | |||
FailOnModel5(); | |||
setupCheck ("pwmWrite") ; | |||
if ((pin & PI_GPIO_MASK) == 0) // On-Board Pin | |||
@@ -2133,8 +2305,29 @@ void pwmWrite (int pin, int value) | |||
else if (wiringPiMode != WPI_MODE_GPIO) | |||
return ; | |||
/* would be possible on ms mode but not on bal, deactivated, use pwmc modify instead | |||
if (piGpioBase == GPIO_PERI_BASE_2711) { | |||
value = (OSC_FREQ_BCM2711*value)/OSC_FREQ_DEFAULT; | |||
} | |||
*/ | |||
usingGpioMemCheck ("pwmWrite") ; | |||
*(pwm + gpioToPwmPort [pin]) = value ; | |||
int channel = gpioToPwmPort[pin]; | |||
int readback = 0x00; | |||
if (PI_MODEL_5 == RaspberryPiModel ) { | |||
if (channel>=0 && channel<=3) { | |||
unsigned int addr = RP1_PWM0_CHAN_START+RP1_PWM0_CHAN_OFFSET*channel+RP1_PWM0_CHAN_DUTY; | |||
pwm[addr] = value; | |||
readback = pwm[addr]; | |||
} else { | |||
fprintf(stderr, "pwmWrite: invalid channel at GPIO pin %d \n", pin); | |||
} | |||
} else { | |||
*(pwm + channel) = value ; | |||
readback = *(pwm + channel); | |||
} | |||
if (wiringPiDebug) { | |||
printf ("PWM value(duty): %u. Current register: 0x%08X\n", value, readback); | |||
} | |||
} | |||
else | |||
{ | |||
@@ -2191,8 +2384,6 @@ void analogWrite (int pin, int value) | |||
void pwmToneWrite (int pin, int freq) | |||
{ | |||
FailOnModel5(); | |||
setupCheck ("pwmToneWrite") ; | |||
if (freq == 0) | |||
@@ -2230,7 +2421,7 @@ void digitalWriteByte (const int value) | |||
int mask = 1 ; | |||
int pin ; | |||
FailOnModel5(); | |||
FailOnModel5("digitalWriteByte"); | |||
if (wiringPiMode == WPI_MODE_GPIO_SYS) | |||
{ | |||
@@ -2259,7 +2450,7 @@ unsigned int digitalReadByte (void) | |||
uint32_t raw ; | |||
uint32_t data = 0 ; | |||
FailOnModel5(); | |||
FailOnModel5("digitalReadByte"); | |||
if (wiringPiMode == WPI_MODE_GPIO_SYS) | |||
{ | |||
@@ -2290,7 +2481,7 @@ unsigned int digitalReadByte (void) | |||
void digitalWriteByte2 (const int value) | |||
{ | |||
FailOnModel5(); | |||
FailOnModel5("digitalWriteByte2"); | |||
if (wiringPiMode == WPI_MODE_GPIO_SYS) | |||
{ | |||
@@ -2306,7 +2497,7 @@ unsigned int digitalReadByte2 (void) | |||
{ | |||
uint32_t data = 0 ; | |||
FailOnModel5(); | |||
FailOnModel5("digitalReadByte2"); | |||
if (wiringPiMode == WPI_MODE_GPIO_SYS) | |||
{ | |||
@@ -2722,6 +2913,15 @@ unsigned int micros (void) | |||
return (uint32_t)(now - epochMicro) ; | |||
} | |||
unsigned long long piMicros64(void) { | |||
struct timespec ts; | |||
clock_gettime (CLOCK_MONOTONIC_RAW, &ts) ; | |||
uint64_t now = (uint64_t)ts.tv_sec * (uint64_t)1000000 + (uint64_t)(ts.tv_nsec / 1000) ; | |||
return (now - epochMicro) ; | |||
} | |||
/* | |||
* wiringPiVersion: | |||
* Return our current version number | |||
@@ -2868,6 +3068,17 @@ int wiringPiSetup (void) | |||
if (PI_MODEL_5 == model) { | |||
gpiomemGlobal = pciemem_RP1; | |||
gpiomemModule = gpiomem_RP1; | |||
// PWM alt pins @RP1 - need to be translated to RP1_FSEL with pinModeAlt | |||
gpioToPwmALT[12] = FSEL_ALT0; | |||
gpioToPwmALT[13] = FSEL_ALT0; | |||
gpioToPwmALT[18] = FSEL_ALT3; | |||
gpioToPwmALT[19] = FSEL_ALT3; | |||
//PWM0 channel @RP1 | |||
gpioToPwmPort[12] = 0; | |||
gpioToPwmPort[13] = 1; | |||
gpioToPwmPort[18] = 2; | |||
gpioToPwmPort[19] = 3; | |||
} | |||
usingGpioMem = FALSE; | |||
@@ -2894,10 +3105,10 @@ int wiringPiSetup (void) | |||
if (PI_MODEL_5 != model) { | |||
//Set the offsets into the memory interface. | |||
GPIO_PADS = piGpioBase + 0x00100000 ; | |||
GPIO_CLOCK_BASE = piGpioBase + 0x00101000 ; | |||
GPIO_PADS = piGpioBase + 0x00100000 ; | |||
GPIO_CLOCK_ADR = piGpioBase + 0x00101000 ; | |||
GPIO_BASE = piGpioBase + 0x00200000 ; | |||
GPIO_TIMER = piGpioBase + 0x0000B000 ; | |||
GPIO_TIMER = piGpioBase + 0x0000B000 ; | |||
GPIO_PWM = piGpioBase + 0x0020C000 ; | |||
GPIO_RIO = 0x00 ; | |||
@@ -2917,7 +3128,7 @@ int wiringPiSetup (void) | |||
// Clock control (needed for PWM) | |||
clk = (uint32_t *)mmap(0, BLOCK_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED, fd, GPIO_CLOCK_BASE) ; | |||
clk = (uint32_t *)mmap(0, BLOCK_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED, fd, GPIO_CLOCK_ADR) ; | |||
if (clk == MAP_FAILED) | |||
return wiringPiFailure (WPI_ALMOST, "wiringPiSetup: mmap (CLOCK) failed: %s\n", strerror (errno)) ; | |||
@@ -2953,7 +3164,7 @@ int wiringPiSetup (void) | |||
unsigned int MMAP_size = (usingGpioMem) ? gpiomem_RP1_Size : pciemem_RP1_Size; | |||
GPIO_PADS = (RP1_PADS0_Addr-RP1_IO0_Addr) ; | |||
GPIO_CLOCK_BASE = 0x00; | |||
GPIO_CLOCK_ADR = (RP1_CLOCK_Addr-RP1_BASE_Addr); | |||
GPIO_BASE = (RP1_IO0_Addr-RP1_BASE_Addr) ; | |||
GPIO_TIMER = 0x00; | |||
GPIO_PWM = RP1_PWM0_Addr-RP1_BASE_Addr; | |||
@@ -2965,8 +3176,12 @@ int wiringPiSetup (void) | |||
return wiringPiFailure (WPI_ALMOST, "wiringPiSetup: mmap failed: %s\n", strerror (errno)) ; | |||
if (usingGpioMem) { | |||
gpio = base; // RP1 start adress of map memory for gpio (same as module memory) | |||
pwm = NULL; // outside of mapped memory, PWM not available from none root | |||
clk = NULL; // outside of mapped memory, CLK main not available from none root | |||
} else { | |||
gpio = &base[GPIO_BASE/4];// RP1 start adress of map memory for gpio | |||
gpio = &base[GPIO_BASE/4]; // RP1 start adress of map memory for gpio | |||
pwm = &base[GPIO_PWM/4]; // RP1 start adress of map memory for pwm0 | |||
clk = &base[GPIO_CLOCK_ADR/4]; // RP1 start adress of map memory for clocks_main | |||
} | |||
pads = &gpio[GPIO_PADS/4]; // RP1 start adress of map memory for pads | |||
rio = &gpio[GPIO_RIO/4]; // RP1 start adress of map memory for rio | |||
@@ -2976,19 +3191,19 @@ int wiringPiSetup (void) | |||
// Export the base addresses for any external software that might need them | |||
_wiringPiBase = base ; | |||
_wiringPiGpio = gpio ; | |||
_wiringPiPwm = NULL ; | |||
_wiringPiClk = NULL ; | |||
_wiringPiPwm = pwm ; | |||
_wiringPiClk = clk ; | |||
_wiringPiPads = pads ; | |||
_wiringPiTimer = NULL ; | |||
_wiringPiRio = rio ; | |||
} | |||
if (wiringPiDebug) { | |||
printf ("wiringPi: memory map gpio 0x%x %s\n", GPIO_BASE , _wiringPiGpio ? "valid" : "invalid"); | |||
printf ("wiringPi: memory map pads 0x%x %s\n", GPIO_PADS , _wiringPiPads ? "valid" : "invalid"); | |||
printf ("wiringPi: memory map rio 0x%x %s\n", GPIO_RIO , _wiringPiRio ? "valid" : "invalid"); | |||
printf ("wiringPi: memory map pwm 0x%x %s\n", GPIO_PWM , _wiringPiPwm ? "valid" : "invalid"); | |||
printf ("wiringPi: memory map clk 0x%x %s\n", GPIO_CLOCK_BASE, _wiringPiClk ? "valid" : "invalid"); | |||
printf ("wiringPi: memory map timer 0x%x %s\n", GPIO_TIMER,_wiringPiTimer ? "valid" : "invalid"); | |||
printf ("wiringPi: memory map gpio 0x%x %s\n", GPIO_BASE , _wiringPiGpio ? "valid" : "invalid"); | |||
printf ("wiringPi: memory map pads 0x%x %s\n", GPIO_PADS , _wiringPiPads ? "valid" : "invalid"); | |||
printf ("wiringPi: memory map rio 0x%x %s\n", GPIO_RIO , _wiringPiRio ? "valid" : "invalid"); | |||
printf ("wiringPi: memory map pwm0 0x%x %s\n", GPIO_PWM , _wiringPiPwm ? "valid" : "invalid"); | |||
printf ("wiringPi: memory map clocks 0x%x %s\n", GPIO_CLOCK_ADR, _wiringPiClk ? "valid" : "invalid"); | |||
printf ("wiringPi: memory map timer 0x%x %s\n", GPIO_TIMER ,_wiringPiTimer ? "valid" : "invalid"); | |||
} | |||
initialiseEpoch () ; | |||
@@ -58,10 +58,12 @@ | |||
// Pin modes | |||
#define INPUT 0 | |||
#define OUTPUT 1 | |||
#define PWM_OUTPUT 2 | |||
#define GPIO_CLOCK 3 | |||
#define INPUT 0 | |||
#define OUTPUT 1 | |||
#define PWM_OUTPUT 2 | |||
#define PWM_MS_OUTPUT 8 | |||
#define PWM_BAL_OUTPUT 9 | |||
#define GPIO_CLOCK 3 | |||
#define SOFT_PWM_OUTPUT 4 | |||
#define SOFT_TONE_OUTPUT 5 | |||
#define PWM_TONE_OUTPUT 6 | |||
@@ -268,6 +270,7 @@ extern int wiringPiSetupPiFaceForGpioProg (void) ; // Don't use this - for gpio | |||
extern int piGpioLayout (void) ; | |||
extern int piBoardRev (void) ; // Deprecated, but does the same as piGpioLayout | |||
extern void piBoardId (int *model, int *rev, int *mem, int *maker, int *overVolted) ; | |||
extern int piBoard40Pin (void) ; // Interface V3.7 | |||
extern int wpiPinToGpio (int wpiPin) ; | |||
extern int physPinToGpio (int physPin) ; | |||
extern void setPadDrive (int group, int value) ; | |||
@@ -308,6 +311,8 @@ extern void delayMicroseconds (unsigned int howLong) ; | |||
extern unsigned int millis (void) ; | |||
extern unsigned int micros (void) ; | |||
extern unsigned long long piMicros64(void); // Interface V3.7 | |||
#ifdef __cplusplus | |||
} | |||
#endif | |||