@@ -118,14 +118,20 @@ struct wiringPiNodeStruct *wiringPiNodes = NULL ;
// Port function select bits
// 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
//RP1 chip (@Pi5) - 3.1.1. Function select
#define RP1_FSEL_ALT0 0x00
#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_PAD_DRIVE_MASK = 0x00000030;
const unsigned int RP1_INV_PAD_DRIVE_MASK = ~(RP1_PAD_DRIVE_MASK);
const unsigned int RP1_INV_PAD_DRIVE_MASK = ~(RP1_PAD_DRIVE_MASK);
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
//RP1 chip (@Pi5) address
const unsigned long long RP1_64_BASE_Addr = 0x1f000d0000;
const unsigned long long RP1_64_BASE_Addr = 0x1f000d0000;
const unsigned int RP1_BASE_Addr = 0x40000000;
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_IO0_Addr = 0x400d0000;
const unsigned int RP1_SYS_RIO0_Addr = 0x400e0000;
const unsigned int RP1_SYS_RIO0_Addr = 0x400e0000;
const unsigned int RP1_PADS0_Addr = 0x400f0000;
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;
const unsigned short pciemem_RP1_Device= 0x0001;
static volatile unsigned int GPIO_PADS ;
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_BASE ;
static volatile unsigned int GPIO_TIMER ;
static volatile unsigned int GPIO_TIMER ;
static volatile unsigned int GPIO_PWM ;
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 PWMCLK_DIVI_MAX = 0xFFF; // 3 Byte max size for Clock devider
const int OSC_FREQ_DEFAULT = 192; // x100kHz OSC
const int OSC_FREQ_DEFAULT = 192; // x100kHz OSC
const int OSC_FREQ_BCM2711 = 540; // 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
// Timer
// Word offsets
// 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; }
#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) {
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;
return 0;
}
}
@@ -715,8 +752,8 @@ static uint8_t gpioToPUDCLK [] =
static uint8_t gpioToPwmALT [] =
static uint8_t gpioToPwmALT [] =
{
{
0, 0, 0, 0, 0, 0, 0, 0, // 0 -> 7
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, // 24 -> 31
0, 0, 0, 0, 0, 0, 0, 0, // 32 -> 39
0, 0, 0, 0, 0, 0, 0, 0, // 32 -> 39
FSEL_ALT0, FSEL_ALT0, 0, 0, 0, FSEL_ALT0, 0, 0, // 40 -> 47
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 [] =
static uint8_t gpioToPwmPort [] =
{
{
0, 0, 0, 0, 0, 0, 0, 0, // 0 -> 7
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, // 24 -> 31
0, 0, 0, 0, 0, 0, 0, 0, // 32 -> 39
0, 0, 0, 0, 0, 0, 0, 0, // 32 -> 39
PWM0_DATA, PWM1_DATA, 0, 0, 0, PWM1_DATA, 0, 0, // 40 -> 47
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 getAlt (int pin)
{
{
int fSel, shift, alt ;
int alt;
pin &= 63 ;
pin &= 63 ;
@@ -1318,29 +1355,28 @@ int getAlt (int pin)
11 = alternate function 9
11 = alternate function 9
*/
*/
switch(alt) {
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: {
case RP1_FSEL_GPIO: {
unsigned int outputmask = gpio[2*pin] & 0x3000; //Bit13-OETOPAD + Bit12-OEFROMPERI
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;
default:return alt;
}
}
} else {
} else {
fSel = gpioToGPFSEL [pin] ;
shift = gpioToShift [pin] ;
int fSel = gpioToGPFSEL [pin] ;
int shift = gpioToShift [pin] ;
alt = (*(gpio + fSel) >> shift) & 7 ;
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))
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) {
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 {
@@ -1381,7 +1422,6 @@ void pwmSetMode (int mode)
void pwmSetRange (unsigned int range)
void pwmSetRange (unsigned int range)
{
{
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
/* 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;
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) {
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)
void pwmSetClock (int divisor)
{
{
uint32_t pwm_control ;
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) {
if (piGpioBase == GPIO_PERI_BASE_2711) {
//calculate value for OSC 54MHz -> 19.2MHz
//calculate value for OSC 54MHz -> 19.2MHz
// Pi 4 max divisor is 1456, Pi0-3 is 4095 (0xFFF)
// Pi 4 max divisor is 1456, Pi0-3 is 4095 (0xFFF)
divisor = (OSC_FREQ_BCM2711*divisor)/OSC_FREQ_DEFAULT;
divisor = (OSC_FREQ_BCM2711*divisor)/OSC_FREQ_DEFAULT;
}
}
if (divisor > PWMCLK_DIVI_MAX) {
divisor = PWMCLK_DIVI_MAX;
}
if (divisor < 1) {
if (divisor < 1) {
divisor = 1;
divisor = 1;
}
}
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) {
if (wiringPiDebug) {
@@ -1469,7 +1543,7 @@ void gpioClockSet (int pin, int freq)
{
{
int divi, divr, divf ;
int divi, divr, divf ;
FailOnModel5();
FailOnModel5("gpioClockSet" );
pin &= 63 ;
pin &= 63 ;
/**/ if (wiringPiMode == WPI_MODE_PINS)
/**/ if (wiringPiMode == WPI_MODE_PINS)
@@ -1658,9 +1732,6 @@ int requestLine(int pin, unsigned int lineRequestFlags) {
void pinModeAlt (int pin, int mode)
void pinModeAlt (int pin, int mode)
{
{
int fSel, shift ;
RETURN_ON_MODEL5
setupCheck ("pinModeAlt") ;
setupCheck ("pinModeAlt") ;
if ((pin & PI_GPIO_MASK) == 0) // On-board pin
if ((pin & PI_GPIO_MASK) == 0) // On-board pin
@@ -1673,20 +1744,49 @@ void pinModeAlt (int pin, int mode)
return ;
return ;
if (PI_MODEL_5 == RaspberryPiModel) {
if (PI_MODEL_5 == RaspberryPiModel) {
//confusion! diffrent to to BCM! this is taking directly the value for the register
//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 {
} else {
fSel = gpioToGPFSEL [pin] ;
shift = gpioToShift [pin] ;
int fSel = gpioToGPFSEL [pin] ;
int shift = gpioToShift [pin] ;
*(gpio + fSel) = (*(gpio + fSel) & ~(7 << shift)) | ((mode & 0x7) << shift) ;
*(gpio + fSel) = (*(gpio + fSel) & ~(7 << shift)) | ((mode & 0x7) << shift) ;
}
}
@@ -1794,8 +1894,14 @@ void pinMode (int pin, int mode)
} else {
} else {
*(gpio + fSel) = (*(gpio + fSel) & ~(7 << shift)) ; // Sets bits to zero = input
*(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);
pwmWrite(origPin, 0);
int channel = gpioToPwmPort[pin];
if (channel>=0 && channel<=3 && PI_MODEL_5 == RaspberryPiModel) {
unsigned int ctrl = pwm[RP1_PWM0_GLOBAL_CTRL];
pwm[RP1_PWM0_GLOBAL_CTRL] = (ctrl & ~(1<<channel)) | RP1_PWM_CTRL_SETUPDATE;
//printf("Disable PWM0[%d] (0x%08X->0x%08X)\n", channel, ctrl, pwm[RP1_PWM0_GLOBAL_CTRL]);
}
}
}
} else if (mode == OUTPUT) {
} else if (mode == OUTPUT) {
if (PI_MODEL_5 == RaspberryPiModel) {
if (PI_MODEL_5 == RaspberryPiModel) {
@@ -1815,20 +1921,35 @@ void pinMode (int pin, int mode)
pwmSetMode (PWM_MODE_MS) ;
pwmSetMode (PWM_MODE_MS) ;
}
}
else if (PWM_OUTPUT==mode || PWM_MS_OUTPUT==mode || PWM_BAL_OUTPUT==mode) {
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!
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<<channel) | RP1_PWM_CTRL_SETUPDATE;
//printf("Enable PWM0[%d] (0x%08X->0x%08X)\n", channel, ctrl, pwm[RP1_PWM0_GLOBAL_CTRL]);
//change GPIO mode
pads[1+pin] = RP1_PAD_DEFAULT_FROM9; // enable output
pinModeAlt(origPin, alt); //switch to PWM mode
}
} else {
} 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
if (PWM_OUTPUT==mode) { // predefine
pwmSetRange (1024) ; // Default range of 1024
pwmSetRange (1024) ; // Default range of 1024
@@ -2173,7 +2294,6 @@ void pwmWrite (int pin, int value)
{
{
struct wiringPiNodeStruct *node = wiringPiNodes ;
struct wiringPiNodeStruct *node = wiringPiNodes ;
FailOnModel5();
setupCheck ("pwmWrite") ;
setupCheck ("pwmWrite") ;
if ((pin & PI_GPIO_MASK) == 0) // On-Board Pin
if ((pin & PI_GPIO_MASK) == 0) // On-Board Pin
@@ -2191,9 +2311,22 @@ void pwmWrite (int pin, int value)
}
}
*/
*/
usingGpioMemCheck ("pwmWrite") ;
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) {
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
else
@@ -2251,8 +2384,6 @@ void analogWrite (int pin, int value)
void pwmToneWrite (int pin, int freq)
void pwmToneWrite (int pin, int freq)
{
{
FailOnModel5();
setupCheck ("pwmToneWrite") ;
setupCheck ("pwmToneWrite") ;
if (freq == 0)
if (freq == 0)
@@ -2290,7 +2421,7 @@ void digitalWriteByte (const int value)
int mask = 1 ;
int mask = 1 ;
int pin ;
int pin ;
FailOnModel5();
FailOnModel5("digitalWriteByte" );
if (wiringPiMode == WPI_MODE_GPIO_SYS)
if (wiringPiMode == WPI_MODE_GPIO_SYS)
{
{
@@ -2319,7 +2450,7 @@ unsigned int digitalReadByte (void)
uint32_t raw ;
uint32_t raw ;
uint32_t data = 0 ;
uint32_t data = 0 ;
FailOnModel5();
FailOnModel5("digitalReadByte" );
if (wiringPiMode == WPI_MODE_GPIO_SYS)
if (wiringPiMode == WPI_MODE_GPIO_SYS)
{
{
@@ -2350,7 +2481,7 @@ unsigned int digitalReadByte (void)
void digitalWriteByte2 (const int value)
void digitalWriteByte2 (const int value)
{
{
FailOnModel5();
FailOnModel5("digitalWriteByte2" );
if (wiringPiMode == WPI_MODE_GPIO_SYS)
if (wiringPiMode == WPI_MODE_GPIO_SYS)
{
{
@@ -2366,7 +2497,7 @@ unsigned int digitalReadByte2 (void)
{
{
uint32_t data = 0 ;
uint32_t data = 0 ;
FailOnModel5();
FailOnModel5("digitalReadByte2" );
if (wiringPiMode == WPI_MODE_GPIO_SYS)
if (wiringPiMode == WPI_MODE_GPIO_SYS)
{
{
@@ -2937,6 +3068,17 @@ int wiringPiSetup (void)
if (PI_MODEL_5 == model) {
if (PI_MODEL_5 == model) {
gpiomemGlobal = pciemem_RP1;
gpiomemGlobal = pciemem_RP1;
gpiomemModule = gpiomem_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;
usingGpioMem = FALSE;
@@ -2963,10 +3105,10 @@ int wiringPiSetup (void)
if (PI_MODEL_5 != model) {
if (PI_MODEL_5 != model) {
//Set the offsets into the memory interface.
//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_BASE = piGpioBase + 0x00200000 ;
GPIO_TIMER = piGpioBase + 0x0000B000 ;
GPIO_TIMER = piGpioBase + 0x0000B000 ;
GPIO_PWM = piGpioBase + 0x0020C000 ;
GPIO_PWM = piGpioBase + 0x0020C000 ;
GPIO_RIO = 0x00 ;
GPIO_RIO = 0x00 ;
@@ -2986,7 +3128,7 @@ int wiringPiSetup (void)
// Clock control (needed for PWM)
// 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)
if (clk == MAP_FAILED)
return wiringPiFailure (WPI_ALMOST, "wiringPiSetup: mmap (CLOCK) failed: %s\n", strerror (errno)) ;
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;
unsigned int MMAP_size = (usingGpioMem) ? gpiomem_RP1_Size : pciemem_RP1_Size;
GPIO_PADS = (RP1_PADS0_Addr-RP1_IO0_Addr) ;
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_BASE = (RP1_IO0_Addr-RP1_BASE_Addr) ;
GPIO_TIMER = 0x00;
GPIO_TIMER = 0x00;
GPIO_PWM = RP1_PWM0_Addr-RP1_BASE_Addr;
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)) ;
return wiringPiFailure (WPI_ALMOST, "wiringPiSetup: mmap failed: %s\n", strerror (errno)) ;
if (usingGpioMem) {
if (usingGpioMem) {
gpio = base; // RP1 start adress of map memory for gpio (same as module memory)
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 {
} 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
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
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
// Export the base addresses for any external software that might need them
_wiringPiBase = base ;
_wiringPiBase = base ;
_wiringPiGpio = gpio ;
_wiringPiGpio = gpio ;
_wiringPiPwm = NULL ;
_wiringPiClk = NULL ;
_wiringPiPwm = pwm ;
_wiringPiClk = clk ;
_wiringPiPads = pads ;
_wiringPiPads = pads ;
_wiringPiTimer = NULL ;
_wiringPiTimer = NULL ;
_wiringPiRio = rio ;
_wiringPiRio = rio ;
}
}
if (wiringPiDebug) {
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 () ;
initialiseEpoch () ;