From 5399409d4ab86bfbe141257a119a573a7087ce2f Mon Sep 17 00:00:00 2001 From: mstroh76 Date: Sat, 8 Jun 2024 18:59:06 +0200 Subject: [PATCH 01/19] #256 i2c to XO, prepare piface --- wiringPi/test/Makefile | 24 +++++++++++++++--------- wiringPi/test/wiringpi_piface_test1.c | 17 +++++++++++++++++ 2 files changed, 32 insertions(+), 9 deletions(-) create mode 100644 wiringPi/test/wiringpi_piface_test1.c diff --git a/wiringPi/test/Makefile b/wiringPi/test/Makefile index cbcd3d8..764201b 100644 --- a/wiringPi/test/Makefile +++ b/wiringPi/test/Makefile @@ -2,13 +2,16 @@ CC = gcc CFLAGS = -Wall LDFLAGS = +# Need BCM26 <-> BCM19 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 -xotests = wiringpi_xotest_test1_spi +# Need XO hardware +xotests = wiringpi_xotest_test1_spi wiringpi_i2c_test1_pcf8574 -i2ctests = wiringpi_i2c_test1_pcf8574 +# Need PiFace hardware and tests condition +pifacetests = wiringpi_piface_test1 -all: $(tests) $(xotests) $(i2ctests) +all: $(tests) $(xotests) $(pifacetests) wiringpi_test1_sysfs: ${CC} ${CFLAGS} wiringpi_test1_sysfs.c -o wiringpi_test1_sysfs -lwiringPi @@ -37,6 +40,9 @@ wiringpi_xotest_test1_spi: wiringpi_i2c_test1_pcf8574: ${CC} ${CFLAGS} wiringpi_i2c_test1_pcf8574.c -o wiringpi_i2c_test1_pcf8574 -lwiringPi +wiringpi_piface_test1: + ${CC} ${CFLAGS} wiringpi_piface_test1.c -o wiringpi_piface_test1 -lwiringPi + test: @error_state=false ; \ for t in $(tests) ; do \ @@ -69,10 +75,10 @@ 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} === ; \ + for t in $(tests) $(pifacetests) ; do \ + echo === PiFace unit test: $${t} === ; \ time ./$${t} ; \ if [ $$? -ne 0 ]; then \ error_state=true ; \ @@ -80,12 +86,12 @@ i2ctest: 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 \ + for t in $(tests) $(xotests) $(pifacetests) ; do \ rm -fv $${t} ; \ done diff --git a/wiringPi/test/wiringpi_piface_test1.c b/wiringPi/test/wiringpi_piface_test1.c new file mode 100644 index 0000000..686efdb --- /dev/null +++ b/wiringPi/test/wiringpi_piface_test1.c @@ -0,0 +1,17 @@ +#include "wpi_test.h" +#include "../../version.h" + +// PiFace dummy + +int main (void) { + int major, minor; + + + wiringPiVersion(&major, &minor); + printf("Testing piface functions with WiringPi %d.%d\n",major, minor); + printf("------------------------------------------\n\n"); + + + + return UnitTestState(); +} From b5a14486244426a3f89e0146db1e9fc9753e6ded Mon Sep 17 00:00:00 2001 From: mstroh76 Date: Sun, 16 Jun 2024 16:29:58 +0200 Subject: [PATCH 02/19] #256 PiFace test --- wiringPi/test/Makefile | 2 +- wiringPi/test/wiringpi_piface_test1.c | 137 +++++++++++++++++++-- wiringPi/test/wiringpi_test1_sysfs.c | 9 +- wiringPi/test/wiringpi_test2_sysfs.c | 9 +- wiringPi/test/wiringpi_test3_device_wpi.c | 9 +- wiringPi/test/wiringpi_test4_device_phys.c | 9 +- wiringPi/test/wiringpi_test5_default.c | 8 +- wiringPi/test/wiringpi_test6_isr.c | 86 +++++++------ wiringPi/test/wpi_test.h | 13 +- wiringPi/wiringPi.c | 21 ++++ wiringPi/wiringPi.h | 1 + 11 files changed, 237 insertions(+), 67 deletions(-) diff --git a/wiringPi/test/Makefile b/wiringPi/test/Makefile index 764201b..5c711cb 100644 --- a/wiringPi/test/Makefile +++ b/wiringPi/test/Makefile @@ -41,7 +41,7 @@ wiringpi_i2c_test1_pcf8574: ${CC} ${CFLAGS} wiringpi_i2c_test1_pcf8574.c -o wiringpi_i2c_test1_pcf8574 -lwiringPi wiringpi_piface_test1: - ${CC} ${CFLAGS} wiringpi_piface_test1.c -o wiringpi_piface_test1 -lwiringPi + ${CC} ${CFLAGS} wiringpi_piface_test1.c -o wiringpi_piface_test1 -lwiringPi -lwiringPiDev test: @error_state=false ; \ diff --git a/wiringPi/test/wiringpi_piface_test1.c b/wiringPi/test/wiringpi_piface_test1.c index 686efdb..c70861b 100644 --- a/wiringPi/test/wiringpi_piface_test1.c +++ b/wiringPi/test/wiringpi_piface_test1.c @@ -1,17 +1,130 @@ -#include "wpi_test.h" -#include "../../version.h" +// WiringPi piface program IN, OUT, PULL +// Compile: gcc -Wall wiringpi_piface_test1.c -o wiringpi_piface_test1 -lwiringPi -lwiringPiDev -// PiFace dummy +#include "wpi_test.h" +#include -int main (void) { - int major, minor; +// 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 - wiringPiVersion(&major, &minor); - printf("Testing piface functions with WiringPi %d.%d\n",major, minor); - printf("------------------------------------------\n\n"); - - - - return UnitTestState(); +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 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(); } diff --git a/wiringPi/test/wiringpi_test1_sysfs.c b/wiringPi/test/wiringpi_test1_sysfs.c index 45a62fe..a97f85e 100644 --- a/wiringPi/test/wiringpi_test1_sysfs.c +++ b/wiringPi/test/wiringpi_test1_sysfs.c @@ -7,8 +7,8 @@ #include -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); diff --git a/wiringPi/test/wiringpi_test2_sysfs.c b/wiringPi/test/wiringpi_test2_sysfs.c index 0e5a0d2..76c48d3 100644 --- a/wiringPi/test/wiringpi_test2_sysfs.c +++ b/wiringPi/test/wiringpi_test2_sysfs.c @@ -7,8 +7,8 @@ #include -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); diff --git a/wiringPi/test/wiringpi_test3_device_wpi.c b/wiringPi/test/wiringpi_test3_device_wpi.c index 24af1bc..4176459 100644 --- a/wiringPi/test/wiringpi_test3_device_wpi.c +++ b/wiringPi/test/wiringpi_test3_device_wpi.c @@ -7,8 +7,8 @@ #include -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); diff --git a/wiringPi/test/wiringpi_test4_device_phys.c b/wiringPi/test/wiringpi_test4_device_phys.c index ecd07a5..31157b8 100644 --- a/wiringPi/test/wiringpi_test4_device_phys.c +++ b/wiringPi/test/wiringpi_test4_device_phys.c @@ -7,8 +7,8 @@ #include -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); diff --git a/wiringPi/test/wiringpi_test5_default.c b/wiringPi/test/wiringpi_test5_default.c index 8223090..ecf80bf 100644 --- a/wiringPi/test/wiringpi_test5_default.c +++ b/wiringPi/test/wiringpi_test5_default.c @@ -7,8 +7,8 @@ #include -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; diff --git a/wiringPi/test/wiringpi_test6_isr.c b/wiringPi/test/wiringpi_test6_isr.c index 24f1496..644fa50 100644 --- a/wiringPi/test/wiringpi_test6_isr.c +++ b/wiringPi/test/wiringpi_test6_isr.c @@ -8,8 +8,8 @@ #include -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 main (void) { + + 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); + printf("\nISR test (WiringPi %d.%d)\n", major, minor); - wiringPiSetupGpio() ; - - pinMode(IRQpin, INPUT); - pinMode(OUTpin, OUTPUT); - digitalWrite (OUTpin, LOW) ; + 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 rising\n", IRQpin, OUTpin); + wiringPiISR (IRQpin, INT_EDGE_RISING, &wfi) ; + sleep(1); + StartSequence (INT_EDGE_RISING, OUTpin); + printf("Testing close\n"); - 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) ; + 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) ; + 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) ; - 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("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) ; - printf("Measuring duration IRQ @ GPIO%d with trigger @ GPIO%d falling\n", IRQpin, OUTpin); - DurationTime(INT_EDGE_FALLING, OUTpin, IRQpin); - } - pinMode(OUTpin, INPUT); + 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); - return UnitTestState(); + 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(); } diff --git a/wiringPi/test/wpi_test.h b/wiringPi/test/wpi_test.h index a2c3b19..d29b363 100644 --- a/wiringPi/test/wpi_test.h +++ b/wiringPi/test/wpi_test.h @@ -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); diff --git a/wiringPi/wiringPi.c b/wiringPi/wiringPi.c index 22d2010..d98b8cc 100644 --- a/wiringPi/wiringPi.c +++ b/wiringPi/wiringPi.c @@ -557,6 +557,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; } diff --git a/wiringPi/wiringPi.h b/wiringPi/wiringPi.h index 9a26b74..3938189 100644 --- a/wiringPi/wiringPi.h +++ b/wiringPi/wiringPi.h @@ -268,6 +268,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) ; From ffccd873a45fb4010ee9471e6ee2cfedb48ba48c Mon Sep 17 00:00:00 2001 From: mstroh76 Date: Sun, 14 Jul 2024 18:32:40 +0200 Subject: [PATCH 03/19] #261 --- VERSION | 2 +- gpio/gpio.c | 2 +- version.h | 4 +-- wiringPi/wiringPi.c | 68 +++++++++++++++++++++++++++++++++++---------- wiringPi/wiringPi.h | 2 ++ 5 files changed, 60 insertions(+), 18 deletions(-) diff --git a/VERSION b/VERSION index 3faf9b8..548d713 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -3.6 \ No newline at end of file +3.7 \ No newline at end of file diff --git a/gpio/gpio.c b/gpio/gpio.c index d468ed9..a563b24 100644 --- a/gpio/gpio.c +++ b/gpio/gpio.c @@ -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) ; } diff --git a/version.h b/version.h index cfc643f..8d97c49 100644 --- a/version.h +++ b/version.h @@ -1,3 +1,3 @@ -#define VERSION "3.6" +#define VERSION "3.7" #define VERSION_MAJOR 3 -#define VERSION_MINOR 6 \ No newline at end of file +#define VERSION_MINOR 7 diff --git a/wiringPi/wiringPi.c b/wiringPi/wiringPi.c index d98b8cc..6ac946b 100644 --- a/wiringPi/wiringPi.c +++ b/wiringPi/wiringPi.c @@ -238,6 +238,10 @@ 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 + // Timer // Word offsets @@ -1355,10 +1359,14 @@ void pwmSetMode (int mode) if ((wiringPiMode == WPI_MODE_PINS) || (wiringPiMode == WPI_MODE_PHYS) || (wiringPiMode == WPI_MODE_GPIO)) { FailOnModel5(); - if (mode == PWM_MODE_MS) + 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)); + } } } @@ -1375,8 +1383,16 @@ void pwmSetRange (unsigned int range) FailOnModel5(); if ((wiringPiMode == WPI_MODE_PINS) || (wiringPiMode == WPI_MODE_PHYS) || (wiringPiMode == WPI_MODE_GPIO)) { + /* 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; + } + */ *(pwm + PWM0_RANGE) = range ; delayMicroseconds (10) ; *(pwm + PWM1_RANGE) = range ; delayMicroseconds (10) ; + if (wiringPiDebug) { + printf ("PWM range: %u. Current register: 0x%08X\n", range, *(pwm + PWM0_RANGE)); + } } } @@ -1394,17 +1410,23 @@ void pwmSetClock (int divisor) uint32_t pwm_control ; FailOnModel5(); - if (piGpioBase == GPIO_PERI_BASE_2711) - { - divisor = 540*divisor/192; + 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 > PWMCLK_DIVI_MAX) { + divisor = PWMCLK_DIVI_MAX; + } + if (divisor < 1) { + divisor = 1; } - divisor &= 4095 ; 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 @@ -1429,8 +1451,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)); + } } } @@ -1459,9 +1482,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 ; @@ -2154,8 +2177,16 @@ 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 ; + if (wiringPiDebug) { + printf ("PWM value: %u. Current register: 0x%08X\n", value, *(pwm + gpioToPwmPort[pin])); + } } else { @@ -2743,6 +2774,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 diff --git a/wiringPi/wiringPi.h b/wiringPi/wiringPi.h index 3938189..64cbb55 100644 --- a/wiringPi/wiringPi.h +++ b/wiringPi/wiringPi.h @@ -309,6 +309,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 From 66bbc3a6a9adf6d4cec6a94a315bdb2416a53ed5 Mon Sep 17 00:00:00 2001 From: mstroh76 Date: Sun, 14 Jul 2024 18:34:41 +0200 Subject: [PATCH 04/19] #263 --- wiringPi/test/wiringpi_test9_pwm.c | 159 +++++++++++++++++++++++++++++ wiringPi/test/wpi_test.h | 10 ++ 2 files changed, 169 insertions(+) create mode 100644 wiringPi/test/wiringpi_test9_pwm.c diff --git a/wiringPi/test/wiringpi_test9_pwm.c b/wiringPi/test/wiringpi_test9_pwm.c new file mode 100644 index 0000000..ca0b349 --- /dev/null +++ b/wiringPi/test/wiringpi_test9_pwm.c @@ -0,0 +1,159 @@ +// WiringPi test program: PWM test +// Compile: gcc -Wall wiringpi_test9_pwm.c -o wiringpi_test9_pwm -lwiringPi + +#include "wpi_test.h" +#include +#include +#include +#include +#include +#include + + +int PWM0 = 12; +int FREQIN = 6; + +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("Interval: 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% tolerance + + 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[10]= { 100, 512, 1024, 1456, 2000, 3000, 5000, 10000, 15000, 20000}; + +int main (void) { + + int major, minor; + char msg[255]; + + wiringPiVersion(&major, &minor); + + printf("WiringPi GPIO test program 9 (using PWM@GPIO%d (output) and GPIO%d (input))\n", PWM0, FREQIN); + printf(" pwm0 irq time\n"); + + printf("\nPWM/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); + + if (!piBoard40Pin()) { + PWM0 = 18; + FREQIN = 17; + } +// 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(); + } + + int Pi4 = 0; + switch(RaspberryPiModel) { + case PI_MODEL_4B: + case PI_MODEL_400: + case PI_MODEL_CM4: + case PI_MODEL_CM4S: + Pi4 = 1; + break; + case PI_MODEL_5: + return UnitTestState(); //not supported so far + } + + printf("\nPWM0 BAL mode:\n"); + printf("==============\n"); + + pinMode(PWM0, PWM_OUTPUT); //pwmr=1024, pwmc=32 + const int pmw = 512; + int pmwr = 1024; + pwmWrite(PWM0, pmw); //50% Duty + //MeasureAndCheckFreq("50\% Duty (default)", 300.000); //FAIL , freq (pwmc=32) to high for irq count + + for (int c_duty=0, c_duty_end = sizeof(tests_duty)/sizeof(tests_duty[0]); 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(PWM0, tests_duty[c_duty]); + + for (int c_pwmc=0, end = sizeof(tests_pwmc)/sizeof(tests_pwmc[0]); c_pwmc1456) { + printf("* Set Clock (pwmc) %d not possible on BCM2711 system (OSC 54 MHz), ignore\n", tests_pwmc[c_pwmc]); + continue; + } + pwmSetClock(tests_pwmc[c_pwmc]); + delay(250); + double freq = 19200.0/tests_pwmc[c_pwmc]*duty_fact; + sprintf(msg, "Set Clock (pwmc) %d, %d%% duty", tests_pwmc[c_pwmc], tests_duty[c_duty]*100/pmwr); + MeasureAndCheckFreq(msg, freq); + } + + } + + delay(250); + pwmSetMode(PWM_MODE_MS) ; + printf("\nPWM0 MS mode:\n"); + printf("==============\n"); + + int pwmc = 10; + pwmSetClock(pwmc); + delay(2500); + + for (int c_pmwr=0, c_pmwr_end = sizeof(tests_pwmr)/sizeof(tests_pwmr[0]); c_pmwr %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) { From 0fab17c768fcacac279bca034f6e4574dd8eeaa2 Mon Sep 17 00:00:00 2001 From: mstroh76 Date: Sun, 14 Jul 2024 18:37:03 +0200 Subject: [PATCH 05/19] #262 --- wiringPi/wiringPi.c | 1 + 1 file changed, 1 insertion(+) diff --git a/wiringPi/wiringPi.c b/wiringPi/wiringPi.c index 6ac946b..f5e8d41 100644 --- a/wiringPi/wiringPi.c +++ b/wiringPi/wiringPi.c @@ -1156,6 +1156,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 ; From 8241cd619ee94aacd0abe39b08fffc2a2d077159 Mon Sep 17 00:00:00 2001 From: mstroh76 Date: Sat, 10 Aug 2024 18:27:07 +0200 Subject: [PATCH 06/19] #263 PiFace PWM unit test --- wiringPi/test/Makefile | 46 +++-- wiringPi/test/wiringpi_test9_pwm.c | 271 ++++++++++++++++++----------- 2 files changed, 199 insertions(+), 118 deletions(-) diff --git a/wiringPi/test/Makefile b/wiringPi/test/Makefile index 5c711cb..5272961 100644 --- a/wiringPi/test/Makefile +++ b/wiringPi/test/Makefile @@ -1,6 +1,6 @@ CC = gcc CFLAGS = -Wall -LDFLAGS = +LDFLAGS = # Need BCM26 <-> BCM19 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 @@ -9,45 +9,53 @@ tests = wiringpi_test1_sysfs wiringpi_test2_sysfs wiringpi_test3_device_wpi wiri xotests = wiringpi_xotest_test1_spi wiringpi_i2c_test1_pcf8574 # Need PiFace hardware and tests condition -pifacetests = wiringpi_piface_test1 +pifacetests = wiringpi_piface_test1 wiringpi_test9_pwm 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_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 -wiringpi_piface_test1: - ${CC} ${CFLAGS} wiringpi_piface_test1.c -o wiringpi_piface_test1 -lwiringPi -lwiringPiDev test: @error_state=false ; \ for t in $(tests) ; do \ echo === unit test: $${t} === ; \ - time ./$${t}; \ + if [ $${t} = *"pwm" ]; then \ + time sudo ./$${t} ; \ + else \ + time ./$${t} ; \ + fi ; \ if [ $$? -ne 0 ]; then \ error_state=true ; \ fi ; \ @@ -63,7 +71,11 @@ xotest: @error_state=false ; \ for t in $(tests) $(xotests) ; do \ echo === XO unit test: $${t} === ; \ - time ./$${t} ; \ + if [ $${t} = *"pwm" ]; then \ + time sudo ./$${t} ; \ + else \ + time ./$${t} ; \ + fi ; \ if [ $$? -ne 0 ]; then \ error_state=true ; \ fi ; \ @@ -79,7 +91,11 @@ pifacetest: @error_state=false ; \ for t in $(tests) $(pifacetests) ; do \ echo === PiFace unit test: $${t} === ; \ - time ./$${t} ; \ + if [ $${t} = *"pwm" ]; then \ + time sudo ./$${t} ; \ + else \ + time ./$${t} ; \ + fi ; \ if [ $$? -ne 0 ]; then \ error_state=true ; \ fi ; \ @@ -91,7 +107,7 @@ pifacetest: echo "\n\e[5mPIFACE TEST SUCCESS\e[0m\n"; \ fi -clean: +clean: for t in $(tests) $(xotests) $(pifacetests) ; do \ rm -fv $${t} ; \ done diff --git a/wiringPi/test/wiringpi_test9_pwm.c b/wiringPi/test/wiringpi_test9_pwm.c index ca0b349..fedc2ce 100644 --- a/wiringPi/test/wiringpi_test9_pwm.c +++ b/wiringPi/test/wiringpi_test9_pwm.c @@ -9,151 +9,216 @@ #include #include +/* +int PWM0[2] = {18, 12}; +int PWM0_IN[2] = {17, 13}; +int PWM1[2] = {13, 19}; +int PWM1_IN[2] = {12, 16}; +*/ -int PWM0 = 12; -int FREQIN = 6; +int PWM_OUT[4] = { 18, 12, 13, 19 }; +int PWM_IN[4] = { 17, 13, 12, 16 }; volatile int gCounter = 0; //Interrupt Service Routine for FREQIN void ISR_FREQIN(void) { - gCounter++; + 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; + 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(); + tbegin = piMicros64(); CountBegin = gCounter; delay(SleepMs); CountEnd = gCounter; CPUClockEnd = clock(); - tend = piMicros64(); + tend = piMicros64(); elapsed_time = (double)(tend-tbegin)/1.0e6; CountInterval = CountEnd - CountBegin; - CPUClockInterval = CPUClockEnd - CPUClockBegin; + CPUClockInterval = CPUClockEnd - CPUClockBegin; CPULoad = CPUClockInterval*100.0 / CLOCKS_PER_SEC / elapsed_time; fFrequency = CountInterval / elapsed_time / 1000; - printf("Interval: time: %.6f sec (CPU: %3.1f %%), count: %g -> frequency: %.3f kHz\n", + 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% tolerance - + 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[10]= { 100, 512, 1024, 1456, 2000, 3000, 5000, 10000, 15000, 20000}; +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 major, minor; + char msg[255]; + int testruns = 4; + int PWM, FREQIN; - wiringPiVersion(&major, &minor); + wiringPiVersion(&major, &minor); - printf("WiringPi GPIO test program 9 (using PWM@GPIO%d (output) and GPIO%d (input))\n", PWM0, FREQIN); - printf(" pwm0 irq time\n"); + printf("WiringPi GPIO test program 9\n"); + printf("PWM/ISR test (WiringPi %d.%d)\n", major, minor); - printf("\nPWM/ISR test (WiringPi %d.%d)\n", major, minor); + wiringPiSetupGpio() ; - wiringPiSetupGpio() ; - - int rev, mem, maker, overVolted, RaspberryPiModel; - piBoardId(&RaspberryPiModel, &rev, &mem, &maker, &overVolted); - CheckNotSame("Model: ", RaspberryPiModel, -1); - - if (!piBoard40Pin()) { - PWM0 = 18; - FREQIN = 17; - } -// 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(); - } - - int Pi4 = 0; - switch(RaspberryPiModel) { - case PI_MODEL_4B: - case PI_MODEL_400: - case PI_MODEL_CM4: - case PI_MODEL_CM4S: - Pi4 = 1; - break; - case PI_MODEL_5: - return UnitTestState(); //not supported so far - } - - printf("\nPWM0 BAL mode:\n"); - printf("==============\n"); - - pinMode(PWM0, PWM_OUTPUT); //pwmr=1024, pwmc=32 - const int pmw = 512; - int pmwr = 1024; - pwmWrite(PWM0, pmw); //50% Duty - //MeasureAndCheckFreq("50\% Duty (default)", 300.000); //FAIL , freq (pwmc=32) to high for irq count - - for (int c_duty=0, c_duty_end = sizeof(tests_duty)/sizeof(tests_duty[0]); 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(PWM0, tests_duty[c_duty]); - - for (int c_pwmc=0, end = sizeof(tests_pwmc)/sizeof(tests_pwmc[0]); c_pwmc1456) { - printf("* Set Clock (pwmc) %d not possible on BCM2711 system (OSC 54 MHz), ignore\n", tests_pwmc[c_pwmc]); - continue; + int rev, mem, maker, overVolted, RaspberryPiModel; + piBoardId(&RaspberryPiModel, &rev, &mem, &maker, &overVolted); + CheckNotSame("Model: ", RaspberryPiModel, -1); + int Pi4 = 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: + return UnitTestState(); //not supported so far } - pwmSetClock(tests_pwmc[c_pwmc]); - delay(250); - double freq = 19200.0/tests_pwmc[c_pwmc]*duty_fact; - sprintf(msg, "Set Clock (pwmc) %d, %d%% duty", tests_pwmc[c_pwmc], tests_duty[c_duty]*100/pmwr); - MeasureAndCheckFreq(msg, freq); + + if (!piBoard40Pin()) { + testruns = 1; // only fist PWM0, supported } - } + for (int testrun=0; testrun(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_pwmc1456) { + 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"); + pwmSetMode(PWM_MODE_MS) ; + + int pwmc = 10; + pwmSetClock(pwmc); + delay(2500); + + for (int c_pmwr=0, c_pmwr_end = sizeof(tests_pwmr)/sizeof(tests_pwmr[0]); c_pmwrMaxFreq) { + 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 Date: Sat, 10 Aug 2024 18:32:18 +0200 Subject: [PATCH 07/19] #256 PiFace test, fix relais test --- wiringPi/test/wiringpi_piface_test1.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/wiringPi/test/wiringpi_piface_test1.c b/wiringPi/test/wiringpi_piface_test1.c index c70861b..78619f3 100644 --- a/wiringPi/test/wiringpi_piface_test1.c +++ b/wiringPi/test/wiringpi_piface_test1.c @@ -49,7 +49,10 @@ int main (int argc, char *argv []) { 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 Date: Mon, 19 Aug 2024 13:29:55 +0200 Subject: [PATCH 08/19] #263 PWM test for all supported GPIOs --- wiringPi/test/wiringpi_test9_pwm.c | 113 +++++++++++----------- wiringPi/test/wiringpi_xotest_test1_spi.c | 2 +- wiringPi/test/wpi_test.h | 7 +- 3 files changed, 60 insertions(+), 62 deletions(-) diff --git a/wiringPi/test/wiringpi_test9_pwm.c b/wiringPi/test/wiringpi_test9_pwm.c index fedc2ce..21f7911 100644 --- a/wiringPi/test/wiringpi_test9_pwm.c +++ b/wiringPi/test/wiringpi_test9_pwm.c @@ -9,15 +9,8 @@ #include #include -/* -int PWM0[2] = {18, 12}; -int PWM0_IN[2] = {17, 13}; -int PWM1[2] = {13, 19}; -int PWM1_IN[2] = {12, 16}; -*/ - int PWM_OUT[4] = { 18, 12, 13, 19 }; -int PWM_IN[4] = { 17, 13, 12, 16 }; +int PWM_IN[4] = { 17, 13, 12, 26 }; volatile int gCounter = 0; @@ -27,25 +20,25 @@ void ISR_FREQIN(void) { } double MeasureAndCheckFreq(const char* msg, double expect_freq) { - double fFrequency; - clock_t CPUClockBegin, CPUClockEnd; - int CountBegin, CountEnd; - double CPUClockInterval, CountInterval; - double elapsed_time, CPULoad; + 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(); + tbegin = piMicros64(); CountBegin = gCounter; delay(SleepMs); CountEnd = gCounter; CPUClockEnd = clock(); - tend = piMicros64(); + tend = piMicros64(); elapsed_time = (double)(tend-tbegin)/1.0e6; CountInterval = CountEnd - CountBegin; - CPUClockInterval = CPUClockEnd - CPUClockBegin; + CPUClockInterval = CPUClockEnd - CPUClockBegin; CPULoad = CPUClockInterval*100.0 / CLOCKS_PER_SEC / elapsed_time; fFrequency = CountInterval / elapsed_time / 1000; @@ -121,29 +114,35 @@ int main (void) { } for (int testrun=0; testrunMaxFreq) { - 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; + 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 %spassed%s \n", msg, value, expect, COLORGRN, COLORDEF); } else { printf("%35s (%.3f<>%.3f) -> %sfailed%s \n" , msg, value, expect, COLORRED, COLORDEF); @@ -104,6 +104,9 @@ void CheckSameFloat(const char* msg, float value, float expect) { } } +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) Date: Mon, 19 Aug 2024 14:02:21 +0200 Subject: [PATCH 09/19] #263 Add PWM to Makefile --- wiringPi/test/Makefile | 8 ++++---- wiringPi/test/wiringpi_test9_pwm.c | 5 ++++- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/wiringPi/test/Makefile b/wiringPi/test/Makefile index 5272961..352b53f 100644 --- a/wiringPi/test/Makefile +++ b/wiringPi/test/Makefile @@ -2,13 +2,13 @@ CC = gcc CFLAGS = -Wall LDFLAGS = -# Need BCM26 <-> BCM19 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 +# 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_test9_pwm # Need XO hardware -xotests = wiringpi_xotest_test1_spi wiringpi_i2c_test1_pcf8574 +xotests = wiringpi_xotest_test1_spi wiringpi_i2c_test1_pcf8574 wiringpi_test9_pwm -# Need PiFace hardware and tests condition +# 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_test9_pwm all: $(tests) $(xotests) $(pifacetests) diff --git a/wiringPi/test/wiringpi_test9_pwm.c b/wiringPi/test/wiringpi_test9_pwm.c index 21f7911..b1bf561 100644 --- a/wiringPi/test/wiringpi_test9_pwm.c +++ b/wiringPi/test/wiringpi_test9_pwm.c @@ -141,7 +141,7 @@ int main (void) { return UnitTestState(); } printf("Wait for start ...\n"); - delay(250); + delay(500); printf("Start:\n"); //MeasureAndCheckFreq("50\% Duty (default)", 300.000); //FAIL , freq (pwmc=32) to high for irq count @@ -215,5 +215,8 @@ int main (void) { 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(); } From 6992794f1da0ca025d798db21beabd9c98568d3b Mon Sep 17 00:00:00 2001 From: mstroh76 Date: Fri, 23 Aug 2024 16:30:08 +0200 Subject: [PATCH 10/19] #267 new output commands PWM_MODE_BAL & PWM_MODE_MS --- wiringPi/wiringPi.c | 23 +++++++++++++++-------- wiringPi/wiringPi.h | 10 ++++++---- 2 files changed, 21 insertions(+), 12 deletions(-) diff --git a/wiringPi/wiringPi.c b/wiringPi/wiringPi.c index f5e8d41..38d7a8f 100644 --- a/wiringPi/wiringPi.c +++ b/wiringPi/wiringPi.c @@ -1794,6 +1794,9 @@ void pinMode (int pin, int mode) } else { *(gpio + fSel) = (*(gpio + fSel) & ~(7 << shift)) ; // Sets bits to zero = input } + if (PM_OFF==mode && !usingGpioMem && pwm && PI_MODEL_5!=RaspberryPiModel && gpioToPwmALT[pin]>0) { //PWM pin -> reset + pwmWrite(origPin, 0); + } } else if (mode == OUTPUT) { if (PI_MODEL_5 == RaspberryPiModel) { pads[1+pin] = (pin<=8) ? RP1_PAD_DEFAULT_0TO8 : RP1_PAD_DEFAULT_FROM9; @@ -1811,22 +1814,26 @@ 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) - { + else if (PWM_OUTPUT==mode || PWM_MS_OUTPUT==mode || PWM_BAL_OUTPUT==mode) { RETURN_ON_MODEL5 if ((alt = gpioToPwmALT [pin]) == 0) // Not a hardware capable PWM pin return ; - usingGpioMemCheck ("pinMode PWM") ; - -// Set pin to PWM mode + usingGpioMemCheck("pinMode PWM") ; // exit on error! + // 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) { diff --git a/wiringPi/wiringPi.h b/wiringPi/wiringPi.h index 64cbb55..79a895a 100644 --- a/wiringPi/wiringPi.h +++ b/wiringPi/wiringPi.h @@ -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 From 0ce38bd09121a3485f42c8f5cd9bb905a9e85a07 Mon Sep 17 00:00:00 2001 From: mstroh76 Date: Fri, 23 Aug 2024 16:31:53 +0200 Subject: [PATCH 11/19] #263 New pwm unit test for start stop reset --- wiringPi/test/wiringpi_test8_pwm.c | 172 +++++++++++++++++++++++++++++ wiringPi/test/wiringpi_test9_pwm.c | 70 ++++++------ 2 files changed, 207 insertions(+), 35 deletions(-) create mode 100644 wiringPi/test/wiringpi_test8_pwm.c diff --git a/wiringPi/test/wiringpi_test8_pwm.c b/wiringPi/test/wiringpi_test8_pwm.c new file mode 100644 index 0000000..02bd122 --- /dev/null +++ b/wiringPi/test/wiringpi_test8_pwm.c @@ -0,0 +1,172 @@ +// WiringPi test program: PWM test +// Compile: gcc -Wall wiringpi_test8_pwm.c -o wiringpi_test8_pwm -lwiringPi + +#include "wpi_test.h" +#include +#include +#include +#include +#include +#include + +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!=0.0) ? expect_freq*2/100:0.1); //2% tolerance + return fFrequency; +} + + +int main (void) { + + int major, minor; +// char msg[255]; + 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); + switch(RaspberryPiModel) { + case PI_MODEL_5: + return UnitTestState(); //not supported so far + } + + 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("Set pwm 0%% and enable PWM output\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 BAL without change", freq); + + pwmSetMode(PWM_MODE_MS); + delay(250); + MeasureAndCheckFreq("PWM MS without change", freq); + + // Now Change values + pwmSetMode(PWM_MODE_BAL); + int pwmc = 1000; + int pwmr = 1024; + int pwm = 512; + pwmSetClock(pwmc); + pwmSetRange(pwmr); + pwmWrite(PWM, pwm); + delay(250); + duty_fact = (double)pwm/(double)pwmr; + printf("duty factor: %g\n", duty_fact); + freq = 19200.0/pwmc*duty_fact; + MeasureAndCheckFreq("PWM BAL with settings", freq); + + pwmSetMode(PWM_MODE_MS); + pwmc = 10; + pwmr = 256; + pwm = 171; + pwmSetClock(pwmc); + pwmSetRange(pwmr); + pwmWrite(PWM, pwm); + delay(250); + duty_fact = (double)pwm/(double)pwmr; + printf("duty factor: %g\n", duty_fact); + 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); + + printf("Set pwm settings and enable PWM\n"); + pwmc = 800; + pwmr = 2048; + pwm = 768; + pwmSetRange(pwmr); + pwmSetClock(pwmc); + pwmWrite(PWM, pwm); + pinMode(PWM, PWM_BAL_OUTPUT); + delay(250); + duty_fact = (double)pwm/(double)pwmr; + printf("duty factor: %g\n", duty_fact); + 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; + pwmSetRange(pwmr); + pwmSetClock(pwmc); + pwmWrite(PWM, pwm); + pinMode(PWM, PWM_MS_OUTPUT); + delay(250); + duty_fact = (double)pwm/(double)pwmr; + printf("duty factor: %g\n", duty_fact); + freq = 19200.0/(double)pwmc/(double)pwmr; + MeasureAndCheckFreq("PMW MS start values", 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(); + } + + return UnitTestState(); +} \ No newline at end of file diff --git a/wiringPi/test/wiringpi_test9_pwm.c b/wiringPi/test/wiringpi_test9_pwm.c index b1bf561..ab38ad5 100644 --- a/wiringPi/test/wiringpi_test9_pwm.c +++ b/wiringPi/test/wiringpi_test9_pwm.c @@ -73,41 +73,41 @@ int main (void) { int rev, mem, maker, overVolted, RaspberryPiModel; piBoardId(&RaspberryPiModel, &rev, &mem, &maker, &overVolted); CheckNotSame("Model: ", RaspberryPiModel, -1); - int Pi4 = 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: - return UnitTestState(); //not supported so far - } + int Pi4 = 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: + return UnitTestState(); //not supported so far + } if (!piBoard40Pin()) { testruns = 1; // only fist PWM0, supported From f2b23cfb0dbc8a988b8929aaacf8245047dbb047 Mon Sep 17 00:00:00 2001 From: mstroh76 Date: Fri, 30 Aug 2024 19:51:18 +0200 Subject: [PATCH 12/19] #258 Pi5 full PWM support --- wiringPi/wiringPi.c | 332 +++++++++++++++++++++++++++++++------------- 1 file changed, 239 insertions(+), 93 deletions(-) diff --git a/wiringPi/wiringPi.c b/wiringPi/wiringPi.c index 38d7a8f..eb2090e 100644 --- a/wiringPi/wiringPi.c +++ b/wiringPi/wiringPi.c @@ -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 ; @@ -241,6 +277,7 @@ static int wiringPiSetuped = FALSE ; 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 @@ -589,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; } @@ -715,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 @@ -731,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 @@ -1287,7 +1324,7 @@ void setPadDrive (int group, int value) int getAlt (int pin) { - int fSel, shift, alt ; + int alt; pin &= 63 ; @@ -1318,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; } @@ -1359,7 +1395,12 @@ void pwmSetMode (int mode) { if ((wiringPiMode == WPI_MODE_PINS) || (wiringPiMode == WPI_MODE_PHYS) || (wiringPiMode == WPI_MODE_GPIO)) { - FailOnModel5(); + 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 { @@ -1381,7 +1422,6 @@ void pwmSetMode (int mode) void pwmSetRange (unsigned int range) { - FailOnModel5(); if ((wiringPiMode == WPI_MODE_PINS) || (wiringPiMode == WPI_MODE_PHYS) || (wiringPiMode == WPI_MODE_GPIO)) { /* would be possible on ms mode but not on bal, deactivated, use pwmc modify instead @@ -1389,10 +1429,24 @@ void pwmSetRange (unsigned int range) range = (OSC_FREQ_BCM2711*range)/OSC_FREQ_DEFAULT; } */ - *(pwm + PWM0_RANGE) = range ; delayMicroseconds (10) ; - *(pwm + PWM1_RANGE) = range ; delayMicroseconds (10) ; + 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, *(pwm + PWM0_RANGE)); + printf ("PWM range: %u. Current register: 0x%08X\n", range, readback); } } } @@ -1409,20 +1463,40 @@ void pwmSetRange (unsigned int range) void pwmSetClock (int divisor) { uint32_t pwm_control ; + if (!clk) { + fprintf(stderr, "wiringPi: pwmSetClock but no clk memory available, ignoring\n"); + return; + } - FailOnModel5(); + 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 > PWMCLK_DIVI_MAX) { - divisor = PWMCLK_DIVI_MAX; - } if (divisor < 1) { divisor = 1; } - if ((wiringPiMode == WPI_MODE_PINS) || (wiringPiMode == WPI_MODE_PHYS) || (wiringPiMode == WPI_MODE_GPIO)) { if (wiringPiDebug) { @@ -1469,7 +1543,7 @@ void gpioClockSet (int pin, int freq) { int divi, divr, divf ; - FailOnModel5(); + FailOnModel5("gpioClockSet"); pin &= 63 ; /**/ if (wiringPiMode == WPI_MODE_PINS) @@ -1658,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 @@ -1673,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) ; } @@ -1794,8 +1894,14 @@ void pinMode (int pin, int mode) } else { *(gpio + fSel) = (*(gpio + fSel) & ~(7 << shift)) ; // Sets bits to zero = input } - if (PM_OFF==mode && !usingGpioMem && pwm && PI_MODEL_5!=RaspberryPiModel && gpioToPwmALT[pin]>0) { //PWM pin -> reset + 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<0x%08X)\n", channel, ctrl, pwm[RP1_PWM0_GLOBAL_CTRL]); + } } } else if (mode == OUTPUT) { if (PI_MODEL_5 == RaspberryPiModel) { @@ -1815,20 +1921,35 @@ void pinMode (int pin, int mode) pwmSetMode (PWM_MODE_MS) ; } else if (PWM_OUTPUT==mode || PWM_MS_OUTPUT==mode || PWM_BAL_OUTPUT==mode) { - RETURN_ON_MODEL5 - if ((alt = gpioToPwmALT [pin]) == 0) // Not a hardware capable PWM pin - return ; usingGpioMemCheck("pinMode PWM") ; // exit on error! - - // Set pin to PWM mode - *(gpio + fSel) = (*(gpio + fSel) & ~(7 << shift)) | (alt << shift) ; - delayMicroseconds (110) ; // See comments in pwmSetClockWPi - - if (PWM_OUTPUT==mode || PWM_BAL_OUTPUT==mode) { - pwmSetMode(PWM_MODE_BAL); // Pi default mode + 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<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 { - pwmSetMode(PWM_MODE_MS); + // Set pin to PWM mode + *(gpio + fSel) = (*(gpio + fSel) & ~(7 << shift)) | (alt << shift) ; + delayMicroseconds (110) ; // See comments in pwmSetClockWPi + + 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 @@ -2173,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 @@ -2191,9 +2311,22 @@ void pwmWrite (int pin, int value) } */ 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: %u. Current register: 0x%08X\n", value, *(pwm + gpioToPwmPort[pin])); + printf ("PWM value(duty): %u. Current register: 0x%08X\n", value, readback); } } else @@ -2251,8 +2384,6 @@ void analogWrite (int pin, int value) void pwmToneWrite (int pin, int freq) { - FailOnModel5(); - setupCheck ("pwmToneWrite") ; if (freq == 0) @@ -2290,7 +2421,7 @@ void digitalWriteByte (const int value) int mask = 1 ; int pin ; - FailOnModel5(); + FailOnModel5("digitalWriteByte"); if (wiringPiMode == WPI_MODE_GPIO_SYS) { @@ -2319,7 +2450,7 @@ unsigned int digitalReadByte (void) uint32_t raw ; uint32_t data = 0 ; - FailOnModel5(); + FailOnModel5("digitalReadByte"); if (wiringPiMode == WPI_MODE_GPIO_SYS) { @@ -2350,7 +2481,7 @@ unsigned int digitalReadByte (void) void digitalWriteByte2 (const int value) { - FailOnModel5(); + FailOnModel5("digitalWriteByte2"); if (wiringPiMode == WPI_MODE_GPIO_SYS) { @@ -2366,7 +2497,7 @@ unsigned int digitalReadByte2 (void) { uint32_t data = 0 ; - FailOnModel5(); + FailOnModel5("digitalReadByte2"); if (wiringPiMode == WPI_MODE_GPIO_SYS) { @@ -2937,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; @@ -2963,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 ; @@ -2986,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)) ; @@ -3022,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; @@ -3034,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 @@ -3045,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 () ; From 7e1a168e12e816e4d36e0bd444c8c875710bf71a Mon Sep 17 00:00:00 2001 From: mstroh76 Date: Fri, 30 Aug 2024 19:55:27 +0200 Subject: [PATCH 13/19] #263 Pi5 changes --- wiringPi/test/Makefile | 9 ++- wiringPi/test/wiringpi_test8_pwm.c | 104 ++++++++++++++++------------- wiringPi/test/wiringpi_test9_pwm.c | 7 +- 3 files changed, 70 insertions(+), 50 deletions(-) diff --git a/wiringPi/test/Makefile b/wiringPi/test/Makefile index 352b53f..4fcd8ea 100644 --- a/wiringPi/test/Makefile +++ b/wiringPi/test/Makefile @@ -3,13 +3,13 @@ CFLAGS = -Wall LDFLAGS = # 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_test9_pwm +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 # Need XO hardware -xotests = wiringpi_xotest_test1_spi wiringpi_i2c_test1_pcf8574 wiringpi_test9_pwm +xotests = wiringpi_xotest_test1_spi wiringpi_i2c_test1_pcf8574 wiringpi_test8_pwm wiringpi_test9_pwm # 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_test9_pwm +pifacetests = wiringpi_piface_test1 wiringpi_test8_pwm wiringpi_test9_pwm all: $(tests) $(xotests) $(pifacetests) @@ -34,6 +34,9 @@ wiringpi_test6_isr: 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 diff --git a/wiringPi/test/wiringpi_test8_pwm.c b/wiringPi/test/wiringpi_test8_pwm.c index 02bd122..fa8a859 100644 --- a/wiringPi/test/wiringpi_test8_pwm.c +++ b/wiringPi/test/wiringpi_test8_pwm.c @@ -19,7 +19,7 @@ void ISR_FREQIN(void) { gCounter++; } -double MeasureAndCheckFreq(const char* msg, double expect_freq) { +double MeasureAndCheckFreqTolerance(const char* msg, double expect_freq, int tolerance) { double fFrequency; clock_t CPUClockBegin, CPUClockEnd; int CountBegin, CountEnd; @@ -46,15 +46,18 @@ double MeasureAndCheckFreq(const char* msg, double expect_freq) { 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*2/100:0.1); //2% tolerance + 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; -// char msg[255]; int PWM, FREQIN; wiringPiVersion(&major, &minor); @@ -67,10 +70,6 @@ int main (void) { int rev, mem, maker, overVolted, RaspberryPiModel; piBoardId(&RaspberryPiModel, &rev, &mem, &maker, &overVolted); CheckNotSame("Model: ", RaspberryPiModel, -1); - switch(RaspberryPiModel) { - case PI_MODEL_5: - return UnitTestState(); //not supported so far - } PWM = 18; FREQIN = 17; @@ -84,83 +83,98 @@ int main (void) { return UnitTestState(); } - printf("Set pwm 0%% and enable PWM output\n"); + 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 BAL without change", freq); + 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); - // Now Change values - pwmSetMode(PWM_MODE_BAL); - int pwmc = 1000; - int pwmr = 1024; - int pwm = 512; - pwmSetClock(pwmc); - pwmSetRange(pwmr); - pwmWrite(PWM, pwm); - delay(250); - duty_fact = (double)pwm/(double)pwmr; - printf("duty factor: %g\n", duty_fact); - freq = 19200.0/pwmc*duty_fact; - MeasureAndCheckFreq("PWM BAL with settings", 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); - duty_fact = (double)pwm/(double)pwmr; - printf("duty factor: %g\n", duty_fact); + 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); + delay(1000); MeasureAndCheckFreq("PMW off", 0.0); - printf("Set pwm settings and enable PWM\n"); - pwmc = 800; - pwmr = 2048; - pwm = 768; - pwmSetRange(pwmr); - pwmSetClock(pwmc); - pwmWrite(PWM, pwm); - pinMode(PWM, PWM_BAL_OUTPUT); - delay(250); - duty_fact = (double)pwm/(double)pwmr; - printf("duty factor: %g\n", duty_fact); - freq = 19200.0/pwmc*duty_fact; - MeasureAndCheckFreq("PMW BAL start values", freq); + 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); + 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); + pwmWrite(PWM, pwm); pinMode(PWM, PWM_MS_OUTPUT); - delay(250); - duty_fact = (double)pwm/(double)pwmr; - printf("duty factor: %g\n", duty_fact); + 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) { @@ -169,4 +183,4 @@ int main (void) { } return UnitTestState(); -} \ No newline at end of file +} diff --git a/wiringPi/test/wiringpi_test9_pwm.c b/wiringPi/test/wiringpi_test9_pwm.c index ab38ad5..a368395 100644 --- a/wiringPi/test/wiringpi_test9_pwm.c +++ b/wiringPi/test/wiringpi_test9_pwm.c @@ -74,6 +74,7 @@ int main (void) { 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: @@ -106,7 +107,8 @@ int main (void) { Pi4 = 1; break; case PI_MODEL_5: - return UnitTestState(); //not supported so far + Pi5 = 1; + break; } if (!piBoard40Pin()) { @@ -144,7 +146,7 @@ int main (void) { 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(pmwr/2)) { @@ -174,6 +176,7 @@ int main (void) { MeasureAndCheckFreq(msg, freq); } } + } delay(250); printf("\n"); From bf8be468b20a597c8e5a66884397ae6bc0bfde92 Mon Sep 17 00:00:00 2001 From: mstroh76 Date: Fri, 30 Aug 2024 20:38:31 +0200 Subject: [PATCH 14/19] #263 Makefile *pwm check not working --- wiringPi/test/Makefile | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/wiringPi/test/Makefile b/wiringPi/test/Makefile index 4fcd8ea..7c379a7 100644 --- a/wiringPi/test/Makefile +++ b/wiringPi/test/Makefile @@ -54,7 +54,7 @@ test: @error_state=false ; \ for t in $(tests) ; do \ echo === unit test: $${t} === ; \ - if [ $${t} = *"pwm" ]; then \ + if [ $${t} = *"8_pwm" ] || [ $${t} = *"9_pwm" ]; then \ time sudo ./$${t} ; \ else \ time ./$${t} ; \ @@ -74,7 +74,7 @@ xotest: @error_state=false ; \ for t in $(tests) $(xotests) ; do \ echo === XO unit test: $${t} === ; \ - if [ $${t} = *"pwm" ]; then \ + if [ $${t} = *"8_pwm" ] || [ $${t} = *"9_pwm" ]; then \ time sudo ./$${t} ; \ else \ time ./$${t} ; \ @@ -94,7 +94,7 @@ pifacetest: @error_state=false ; \ for t in $(tests) $(pifacetests) ; do \ echo === PiFace unit test: $${t} === ; \ - if [ $${t} = *"pwm" ]; then \ + if [ $${t} = *"8_pwm" ] || [ $${t} = *"9_pwm" ]; then \ time sudo ./$${t} ; \ else \ time ./$${t} ; \ From f8d6bd1fc4aff587a5297b2e8f55c61a22c2023a Mon Sep 17 00:00:00 2001 From: mstroh76 Date: Sat, 31 Aug 2024 18:19:56 +0200 Subject: [PATCH 15/19] Update README.md for Pi 5 --- README.md | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index de2dc3a..8208ed6 100644 --- a/README.md +++ b/README.md @@ -1,11 +1,15 @@ -# WiringPi +# WiringPi Library +Welcome to the WiringPi Library, the highly performant GPIO access library for Raspberry Pi boards. This library is written in C and is designed to provide fast and efficient control of the GPIO pins by directly accessing the hardware registers using DMA. +Key Features: +- **Support:** WiringPi supports all Raspberry Pi Boards including Pi 5 ( :construction: On the Pi 5, only the GCLK functionality is currently not supported due to missing documentation of the RP1 chip.). +- **High Performance:** By directly accessing the hardware registers, WiringPi ensures minimal latency and maximum performance for your GPIO operations. +- **Wide Adoption:** WiringPi is widely used in numerous projects, making it a reliable choice for your Raspberry Pi GPIO needs. -WiringPi is a _performant_ GPIO access library written in C for Raspberry Pi boards. +Whether you’re working on a simple LED blink project or a complex automation system, WiringPi provides the tools you need to get the job done efficiently. -:warning:️ :construction: on Pi5, PWM support is currently under development and _will not work at this point_. If you're interested in the progress, please check the [corresponding issue](https://github.com/GrazerComputerClub/WiringPi/issues/21). +## How to use: - -To compile programs with wiringPi, you need to include `wiringPi.h` as well as link against `wiringPi`: +To compile programs with wiringPi Library, you need to include `wiringPi.h` as well as link against `wiringPi`: ```c #include // Include WiringPi library! @@ -143,7 +147,7 @@ Please don't email GC2 for reporting issues, you might [contact us](mailto:wirin ## History -This repository is the continuation of 'Gordon's wiringPi' which has been [deprecated](https://web.archive.org/web/20220405225008/http://wiringpi.com/wiringpi-deprecated/), a while ago. +This repository is the continuation of 'Gordon's wiringPi 2.5' which has been [deprecated](https://web.archive.org/web/20220405225008/http://wiringpi.com/wiringpi-deprecated/), a while ago. * The last "old wiringPi" source of Gordon's release can be found at the [`final_source_2.50`](https://github.com/WiringPi/WiringPi/tree/final_official_2.50) tag. From 2783aa2c2053df0ff54358b0dc000595d99e756e Mon Sep 17 00:00:00 2001 From: mstroh76 Date: Sat, 31 Aug 2024 18:21:45 +0200 Subject: [PATCH 16/19] Update README.md --- README.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 8208ed6..a1b70a4 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,8 @@ # WiringPi Library -Welcome to the WiringPi Library, the highly performant GPIO access library for Raspberry Pi boards. This library is written in C and is designed to provide fast and efficient control of the GPIO pins by directly accessing the hardware registers using DMA. -Key Features: -- **Support:** WiringPi supports all Raspberry Pi Boards including Pi 5 ( :construction: On the Pi 5, only the GCLK functionality is currently not supported due to missing documentation of the RP1 chip.). +Welcome to the WiringPi Library, the highly performant GPIO access library for Raspberry Pi boards. This library is written in C and is designed to provide fast and efficient control of the GPIO pins by directly accessing the hardware registers using DMA. + +**Key Features:** +- **Support:** WiringPi supports all Raspberry Pi Boards including Pi 5 ( :construction: On the Pi 5, only the GCLK functionality is currently not supported due to missing documentation of the RP1 chip). - **High Performance:** By directly accessing the hardware registers, WiringPi ensures minimal latency and maximum performance for your GPIO operations. - **Wide Adoption:** WiringPi is widely used in numerous projects, making it a reliable choice for your Raspberry Pi GPIO needs. From 3301e19c67bee133c51ac501141677480bf19444 Mon Sep 17 00:00:00 2001 From: mstroh76 Date: Sat, 31 Aug 2024 18:22:09 +0200 Subject: [PATCH 17/19] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index a1b70a4..7125be7 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ Welcome to the WiringPi Library, the highly performant GPIO access library for R Whether you’re working on a simple LED blink project or a complex automation system, WiringPi provides the tools you need to get the job done efficiently. -## How to use: +## How to use To compile programs with wiringPi Library, you need to include `wiringPi.h` as well as link against `wiringPi`: From 385d5b4b253228cccc2b0a49801c114bbb854202 Mon Sep 17 00:00:00 2001 From: mstroh76 Date: Sat, 31 Aug 2024 18:45:23 +0200 Subject: [PATCH 18/19] #271 Pi4 too high freq at pwmc 100 --- VERSION | 2 +- version.h | 4 ++-- wiringPi/test/wiringpi_test9_pwm.c | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/VERSION b/VERSION index 548d713..cc1923a 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -3.7 \ No newline at end of file +3.8 diff --git a/version.h b/version.h index 8d97c49..b79a6e9 100644 --- a/version.h +++ b/version.h @@ -1,3 +1,3 @@ -#define VERSION "3.7" +#define VERSION "3.8" #define VERSION_MAJOR 3 -#define VERSION_MINOR 7 +#define VERSION_MINOR 8 diff --git a/wiringPi/test/wiringpi_test9_pwm.c b/wiringPi/test/wiringpi_test9_pwm.c index a368395..19baa12 100644 --- a/wiringPi/test/wiringpi_test9_pwm.c +++ b/wiringPi/test/wiringpi_test9_pwm.c @@ -51,7 +51,7 @@ double MeasureAndCheckFreq(const char* msg, double expect_freq) { } -int tests_pwmc[7] = {1456, 1000, 512, 100, 2000, 3000, 4000}; +int tests_pwmc[7] = {1456, 1000, 512, 200, 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}; From 6c57a7dcbf2e078ef3eff98c9974d815fa9cac2b Mon Sep 17 00:00:00 2001 From: mstroh76 Date: Sat, 31 Aug 2024 20:15:42 +0200 Subject: [PATCH 19/19] #271 Problem with PWM BAL mode and low clock settings removed --- wiringPi/test/wiringpi_test8_pwm.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/wiringPi/test/wiringpi_test8_pwm.c b/wiringPi/test/wiringpi_test8_pwm.c index fa8a859..b690fc5 100644 --- a/wiringPi/test/wiringpi_test8_pwm.c +++ b/wiringPi/test/wiringpi_test8_pwm.c @@ -120,7 +120,7 @@ int main (void) { 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); + 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); @@ -138,7 +138,7 @@ int main (void) { 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); + 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); @@ -154,11 +154,12 @@ int main (void) { MeasureAndCheckFreq("PMW off", 0.0); printf("Set pwm settings and enable PWM\n"); - pwmc = 5; + //pwmc = 5; //Problem with Pi0/1 after setting, PWM stops working, maybe IRQ problem or PWM BAL with that high freq (>2 MHz) + pwmc = 35; //PWM BAL would be >400 kHz 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); + 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);