|
@@ -238,6 +238,10 @@ static int wiringPiSetuped = FALSE ; |
|
|
#define PWM1_SERIAL 0x0200 // Run in serial mode |
|
|
#define PWM1_SERIAL 0x0200 // Run in serial mode |
|
|
#define PWM1_ENABLE 0x0100 // Channel Enable |
|
|
#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 |
|
|
// Timer |
|
|
// Word offsets |
|
|
// Word offsets |
|
|
|
|
|
|
|
@@ -1355,10 +1359,14 @@ void pwmSetMode (int mode) |
|
|
if ((wiringPiMode == WPI_MODE_PINS) || (wiringPiMode == WPI_MODE_PHYS) || (wiringPiMode == WPI_MODE_GPIO)) |
|
|
if ((wiringPiMode == WPI_MODE_PINS) || (wiringPiMode == WPI_MODE_PHYS) || (wiringPiMode == WPI_MODE_GPIO)) |
|
|
{ |
|
|
{ |
|
|
FailOnModel5(); |
|
|
FailOnModel5(); |
|
|
if (mode == PWM_MODE_MS) |
|
|
|
|
|
|
|
|
if (mode == PWM_MODE_MS) { |
|
|
*(pwm + PWM_CONTROL) = PWM0_ENABLE | PWM1_ENABLE | PWM0_MS_MODE | PWM1_MS_MODE ; |
|
|
*(pwm + PWM_CONTROL) = PWM0_ENABLE | PWM1_ENABLE | PWM0_MS_MODE | PWM1_MS_MODE ; |
|
|
else |
|
|
|
|
|
|
|
|
} else { |
|
|
*(pwm + PWM_CONTROL) = PWM0_ENABLE | PWM1_ENABLE ; |
|
|
*(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(); |
|
|
FailOnModel5(); |
|
|
if ((wiringPiMode == WPI_MODE_PINS) || (wiringPiMode == WPI_MODE_PHYS) || (wiringPiMode == WPI_MODE_GPIO)) |
|
|
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 + PWM0_RANGE) = range ; delayMicroseconds (10) ; |
|
|
*(pwm + PWM1_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 ; |
|
|
uint32_t pwm_control ; |
|
|
|
|
|
|
|
|
FailOnModel5(); |
|
|
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 ((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 |
|
|
pwm_control = *(pwm + PWM_CONTROL) ; // preserve PWM_CONTROL |
|
|
|
|
|
|
|
|
// We need to stop PWM prior to stopping PWM clock in MS mode otherwise BUSY |
|
|
// 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 |
|
|
*(clk + PWMCLK_CNTL) = BCM_PASSWORD | 0x11 ; // Start PWM clock |
|
|
*(pwm + PWM_CONTROL) = pwm_control ; // restore PWM_CONTROL |
|
|
*(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 ; |
|
|
divr = 19200000 % freq ; |
|
|
divf = (int)((double)divr * 4096.0 / 19200000.0) ; |
|
|
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 |
|
|
*(clk + gpioToClkCon [pin]) = BCM_PASSWORD | GPIO_CLOCK_SOURCE ; // Stop GPIO Clock |
|
|
while ((*(clk + gpioToClkCon [pin]) & 0x80) != 0) // ... and wait |
|
|
while ((*(clk + gpioToClkCon [pin]) & 0x80) != 0) // ... and wait |
|
|
; |
|
|
; |
|
@@ -2154,8 +2177,16 @@ void pwmWrite (int pin, int value) |
|
|
else if (wiringPiMode != WPI_MODE_GPIO) |
|
|
else if (wiringPiMode != WPI_MODE_GPIO) |
|
|
return ; |
|
|
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") ; |
|
|
usingGpioMemCheck ("pwmWrite") ; |
|
|
*(pwm + gpioToPwmPort [pin]) = value ; |
|
|
*(pwm + gpioToPwmPort [pin]) = value ; |
|
|
|
|
|
if (wiringPiDebug) { |
|
|
|
|
|
printf ("PWM value: %u. Current register: 0x%08X\n", value, *(pwm + gpioToPwmPort[pin])); |
|
|
|
|
|
} |
|
|
} |
|
|
} |
|
|
else |
|
|
else |
|
|
{ |
|
|
{ |
|
@@ -2743,6 +2774,15 @@ unsigned int micros (void) |
|
|
return (uint32_t)(now - epochMicro) ; |
|
|
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: |
|
|
* wiringPiVersion: |
|
|
* Return our current version number |
|
|
* Return our current version number |
|
|