ODROID-N2: Add new support for hardware PWM
Servo motors are typically controlled 1000 us ~ 2000 us pulse widths. So default PWM period was set to 2500us.
This commit is contained in:
committed by
Joshua Yang
parent
714fd072a9
commit
010207ea64
@@ -655,6 +655,8 @@ static void init_gpio_mmap (void)
|
||||
msg (MSG_ERR,
|
||||
"wiringPiSetup: Unable to open /dev/gpiomem: %s\n",
|
||||
strerror (errno));
|
||||
|
||||
setUsingGpioMem( TRUE );
|
||||
} else
|
||||
msg (MSG_ERR,
|
||||
"wiringPiSetup: /dev/gpiomem doesn't exist. Please try again with sudo.\n");
|
||||
|
||||
@@ -692,6 +692,8 @@ static void init_gpio_mmap (void)
|
||||
msg (MSG_ERR,
|
||||
"wiringPiSetup: Unable to open /dev/gpiomem: %s\n",
|
||||
strerror (errno));
|
||||
|
||||
setUsingGpioMem( TRUE );
|
||||
} else
|
||||
msg (MSG_ERR,
|
||||
"wiringPiSetup: /dev/gpiomem doesn't exist. Please try again with sudo.\n");
|
||||
|
||||
@@ -667,6 +667,8 @@ static void init_gpio_mmap (void)
|
||||
msg (MSG_ERR,
|
||||
"wiringPiSetup: Unable to open /dev/gpiomem: %s\n",
|
||||
strerror (errno));
|
||||
|
||||
setUsingGpioMem( TRUE );
|
||||
} else
|
||||
msg (MSG_ERR,
|
||||
"wiringPiSetup: /dev/gpiomem doesn't exist. Please try again with sudo.\n");
|
||||
|
||||
@@ -29,57 +29,133 @@
|
||||
// wiringPi gpio map define
|
||||
/*----------------------------------------------------------------------------*/
|
||||
static const int pinToGpio_rev1[64] = {
|
||||
// wiringPi number to native gpio number
|
||||
479, 492, // 0 | 1 : GPIOX.3, GPIOX.16
|
||||
480, 483, // 2 | 3 : GPIOX.4, GPIOX.7
|
||||
476, 477, // 4 | 5 : GPIOX.0, GPIOX.1
|
||||
478, 473, // 6 | 7 : GPIOX.2, GPIOA.13
|
||||
493, 494, // 8 | 9 : GPIOX.17(I2C-2_SDA), GPIOX.18(I2C-2_SCL)
|
||||
486, 464, // 10 | 11 : GPIOX.10, GPIOA.4
|
||||
484, 485, // 12 | 13 : GPIOX.8, GPIOX.9
|
||||
487, 488, // 14 | 15 : GPIOX.11, GPIOX.12
|
||||
489, -1, // 16 | 17 : GPIOX.13,
|
||||
-1, -1, // 18 | 19 :
|
||||
-1, 490, // 20 | 21 : , GPIOX.14
|
||||
491, 481, // 22 | 23 : GPIOX.15, GPIOX.5
|
||||
482, -1, // 24 | 25 : GPIOX.6, ADC.AIN3
|
||||
472, 495, // 26 | 27 : GPIOA.12, GPIOX.19
|
||||
-1, -1, // 28 | 29 : REF1.8V OUT, ADC.AIN2
|
||||
474, 475, // 30 | 31 : GPIOA.14(I2C-3_SDA), GPIOA.15(I2C-3_SCL)
|
||||
// wiringPi number to native gpio number
|
||||
479, 492, // GPIOX.3 0 | 1 GPIOX.16(PWM_E)
|
||||
480, 483, // GPIOX.4 2 | 3 GPIOX.7(PWM_F)
|
||||
476, 477, // GPIOX.0 4 | 5 GPIOX.1
|
||||
478, 473, // GPIOX.2 6 | 7 GPIOA.13
|
||||
493, 494, // GPIOX.17(I2C-2_SDA) 8 | 9 GPIOX.18(I2C-2_SCL)
|
||||
486, 464, // GPIOX.10 10 | 11 GPIOA.4
|
||||
484, 485, // GPIOX.8 12 | 13 GPIOX.9
|
||||
487, 488, // GPIOX.11 14 | 15 GPIOX.12
|
||||
489, -1, // GPIOX.13 16 | 17
|
||||
-1, -1, // 18 | 19
|
||||
-1, 490, // 20 | 21 GPIOX.14
|
||||
491, 481, // GPIOX.15 22 | 23 GPIOX.5(PWM_C)
|
||||
482, -1, // GPIOX.6(PWM_D) 24 | 25 ADC.AIN3
|
||||
472, 495, // GPIOA.12 26 | 27 GPIOX.19
|
||||
-1, -1, // REF1.8V OUT 28 | 29 ADC.AIN2
|
||||
474, 475, // GPIOA.14(I2C-3_SDA) 30 | 31 GPIOA.15(I2C-3_SCL)
|
||||
// Padding:
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 32...47
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 48...63
|
||||
};
|
||||
|
||||
static const int phyToGpio_rev1[64] = {
|
||||
// physical header pin number to native gpio number
|
||||
-1, // 0
|
||||
-1, -1, // 1 | 2 : 3.3V, 5.0V
|
||||
493, -1, // 3 | 4 : GPIOX.17(I2C-2_SDA), 5.0V
|
||||
494, -1, // 5 | 6 : GPIOX.18(I2C-2_SCL), GND
|
||||
473, 488, // 7 | 8 : GPIOA.13, GPIOX.12(UART_TX_B)
|
||||
-1, 489, // 9 | 10 : GND, GPIOX.13(UART_RX_B)
|
||||
479, 492, // 11 | 12 : GPIOX.3, GPIOX.16
|
||||
480, -1, // 13 | 14 : GPIOX.4, GND
|
||||
483, 476, // 15 | 16 : GPIOX.7, GPIOX.0
|
||||
-1, 477, // 17 | 18 : 3.3V, GPIOX.1
|
||||
484, -1, // 19 | 20 : GPIOX.8(SPI_MOSI), GND
|
||||
485, 478, // 21 | 22 : GPIOX.9(SPI_MISO), GPIOX.2
|
||||
487, 486, // 23 | 24 : GPIOX.11(SPI_SCLK), GPIOX.10(SPI_CE0)
|
||||
-1, 464, // 25 | 26 : GND, GPIOA.4(SPI_CE1)
|
||||
474, 475, // 27 | 28 : GPIOA.14(I2C-3_SDA), GPIOA.15(I2C-3_SCL)
|
||||
490, -1, // 29 | 30 : GPIOX.14, GND
|
||||
491, 472, // 31 | 32 : GPIOX.15, GPIOA.12
|
||||
481, -1, // 33 | 34 : GPIOX.5, GND
|
||||
482, 495, // 35 | 36 : GPIOX.6, GPIOX.19
|
||||
-1, -1, // 37 | 38 : ADC.AIN3, 1.8V REF OUT
|
||||
-1, -1, // 39 | 40 : GND, ADC.AIN2
|
||||
// physical header pin number to native gpio number
|
||||
-1, // 0
|
||||
-1, -1, // 3.3V 1 | 2 5.0V
|
||||
493, -1, // GPIOX.17(I2C-2_SDA) 3 | 4 5.0V
|
||||
494, -1, // GPIOX.18(I2C-2_SCL) 5 | 6 GND
|
||||
473, 488, // GPIOA.13 7 | 8 GPIOX.12(UART_TX_B)
|
||||
-1, 489, // GND 9 | 10 GPIOX.13(UART_RX_B)
|
||||
479, 492, // GPIOX.3 11 | 12 GPIOX.16(PWM_E)
|
||||
480, -1, // GPIOX.4 13 | 14 GND
|
||||
483, 476, // GPIOX.7(PWM_F) 15 | 16 GPIOX.0
|
||||
-1, 477, // 3.3V 17 | 18 GPIOX.1
|
||||
484, -1, // GPIOX.8(SPI_MOSI) 19 | 20 GND
|
||||
485, 478, // GPIOX.9(SPI_MISO) 21 | 22 GPIOX.2
|
||||
487, 486, // GPIOX.11(SPI_SCLK) 23 | 24 GPIOX.10(SPI_CE0)
|
||||
-1, 464, // GND 25 | 26 GPIOA.4(SPI_CE1)
|
||||
474, 475, // GPIOA.14(I2C-3_SDA) 27 | 28 GPIOA.15(I2C-3_SCL)
|
||||
490, -1, // GPIOX.14 29 | 30 GND
|
||||
491, 472, // GPIOX.15 31 | 32 GPIOA.12
|
||||
481, -1, // GPIOX.5(PWM_C) 33 | 34 GND
|
||||
482, 495, // GPIOX.6(PWM_D) 35 | 36 GPIOX.19
|
||||
-1, -1, // ADC.AIN3 37 | 38 1.8V REF OUT
|
||||
-1, -1, // GND 39 | 40 ADC.AIN2
|
||||
// Not used
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, // 41...48
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, // 49...56
|
||||
-1, -1, -1, -1, -1, -1, -1 // 57...63
|
||||
};
|
||||
|
||||
static int16_t _gpioTophysPin [] = {
|
||||
// (native gpio number - N2_GPIOA_PIN_START) to physical header pin number
|
||||
-1, // 0 + N2_GPIOA_PIN_START(460)
|
||||
-1, -1, // 1 | 2
|
||||
-1, 26, // 3 | 4 GPIOA.4(SPI_CE1)
|
||||
-1, -1, // 5 | 6
|
||||
-1, -1, // 7 | 8
|
||||
-1, -1, // 9 | 10
|
||||
-1, 32, // 11 | 12 GPIOA.12
|
||||
7, 27, // GPIOA.13 13 | 14 GPIOA.14(I2C-3_SDA)
|
||||
28, 16, // GPIOA.15(I2C-3_SCL) 15 | 16 GPIOX.0
|
||||
18, 22, // GPIOX.1 17 | 18 GPIOX.2
|
||||
11, 13, // GPIOX.3 19 | 20 GPIOX.4
|
||||
33, 35, // GPIOX.5(PWM_C) 21 | 22 GPIOX.6(PWM_D)
|
||||
15, 19, // GPIOX.7(PWM_F) 23 | 24 GPIOX.8(SPI_MOSI)
|
||||
21, 24, // GPIOX.9(SPI_MISO) 25 | 26 GPIOX.10(SPI_CE0)
|
||||
23, 8, // GPIOX.11(SPI_SCLK) 27 | 28 GPIOX.12(UART_TX_B)
|
||||
10, 29, // GPIOX.13(UART_RX_B) 29 | 30 GPIOX.14
|
||||
31, 12, // GPIOX.15 31 | 32 GPIOX.16(PWM_E)
|
||||
3, 5, // GPIOX.17(I2C-2_SDA) 33 | 34 GPIOX.18(I2C-2_SCL)
|
||||
36, -1, // GPIOX.19 35 | 36
|
||||
-1, -1, // 37 | 38
|
||||
-1, -1, // 39 | 40
|
||||
// Not used
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, // 41...48
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, // 49...56
|
||||
-1, -1, -1, -1, -1, -1, -1 // 57...63
|
||||
};
|
||||
|
||||
static int8_t _gpioToPwmPin [] = {
|
||||
// (native gpio number - N2_GPIOA_PIN_START) to PWM pin number
|
||||
-1, // 0 + N2_GPIOA_PIN_START(460)
|
||||
-1, -1, // 1 | 2
|
||||
-1, -1, // 3 | 4 GPIOA.4(SPI_CE1)
|
||||
-1, -1, // 5 | 6
|
||||
-1, -1, // 7 | 8
|
||||
-1, -1, // 9 | 10
|
||||
-1, -1, // 11 | 12 GPIOA.12
|
||||
-1, -1, // GPIOA.13 13 | 14 GPIOA.14(I2C-3_SDA)
|
||||
-1, -1, // GPIOA.15(I2C-3_SCL) 15 | 16 GPIOX.0
|
||||
-1, -1, // GPIOX.1 17 | 18 GPIOX.2
|
||||
-1, -1, // GPIOX.3 19 | 20 GPIOX.4
|
||||
2, 3, // GPIOX.5(PWM_C) 21 | 22 GPIOX.6(PWM_D)
|
||||
5, -1, // GPIOX.7(PWM_F) 23 | 24 GPIOX.8(SPI_MOSI)
|
||||
-1, -1, // GPIOX.9(SPI_MISO) 25 | 26 GPIOX.10(SPI_CE0)
|
||||
-1, -1, // GPIOX.11(SPI_SCLK) 27 | 28 GPIOX.12(UART_TX_B)
|
||||
-1, -1, // GPIOX.13(UART_RX_B) 29 | 30 GPIOX.14
|
||||
-1, 4, // GPIOX.15 31 | 32 GPIOX.16(PWM_E)
|
||||
-1, -1, // GPIOX.17(I2C-2_SDA) 33 | 34 GPIOX.18(I2C-2_SCL)
|
||||
-1, -1, // GPIOX.19 35 | 36
|
||||
-1, -1, // 37 | 38
|
||||
-1, -1, // 39 | 40
|
||||
// Not used
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, // 41...48
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, // 49...56
|
||||
-1, -1, -1, -1, -1, -1, -1 // 57...63
|
||||
};
|
||||
|
||||
static uint16_t pwmPinToALT [] = {
|
||||
0, 0, // A, B
|
||||
4, 4, // C 481 GPIOX.5 , D 482 GPIOX.6
|
||||
1, 1 // E 492 GPIOX.16, F 483 GPIOX.7
|
||||
};
|
||||
|
||||
static uint16_t pwmPinToRange [] = {
|
||||
0, 0, // A, B
|
||||
0, 0, // C 481 GPIOX.5 , D 482 GPIOX.6
|
||||
0, 0 // E 492 GPIOX.16, F 483 GPIOX.7
|
||||
};
|
||||
|
||||
static uint16_t pwmPinToDutyOffset [] = {
|
||||
N2_PWM_0_DUTY_CYCLE_OFFSET, N2_PWM_1_DUTY_CYCLE_OFFSET, // A, B
|
||||
N2_PWM_0_DUTY_CYCLE_OFFSET, N2_PWM_1_DUTY_CYCLE_OFFSET, // C 481 GPIOX.5 , D 482 GPIOX.6
|
||||
N2_PWM_0_DUTY_CYCLE_OFFSET, N2_PWM_1_DUTY_CYCLE_OFFSET // E 492 GPIOX.16, F 483 GPIOX.7
|
||||
};
|
||||
|
||||
/*----------------------------------------------------------------------------*/
|
||||
//
|
||||
// Global variable define
|
||||
@@ -94,6 +170,7 @@ static int adcFds[2];
|
||||
|
||||
/* GPIO mmap control */
|
||||
static volatile uint32_t *gpio;
|
||||
static volatile uint32_t *pwm[3];
|
||||
|
||||
/* wiringPi Global library */
|
||||
static struct libodroid *lib = NULL;
|
||||
@@ -109,6 +186,8 @@ static int gpioToShiftReg (int pin);
|
||||
static int gpioToGPFSELReg (int pin);
|
||||
static int gpioToDSReg (int pin);
|
||||
static int gpioToMuxReg (int pin);
|
||||
static int gpioToPwmPin (int pin);
|
||||
static int gpioTophysPin (int pin) UNU;
|
||||
|
||||
/*----------------------------------------------------------------------------*/
|
||||
// wiringPi core function
|
||||
@@ -122,10 +201,14 @@ static int _getPUPD (int pin);
|
||||
static int _pullUpDnControl (int pin, int pud);
|
||||
static int _digitalRead (int pin);
|
||||
static int _digitalWrite (int pin, int value);
|
||||
static int _pwmWrite (int pin, int value);
|
||||
static int _analogRead (int pin);
|
||||
static int _digitalWriteByte (const unsigned int value);
|
||||
static unsigned int _digitalReadByte (void);
|
||||
|
||||
static void _pwmSetRange (unsigned int range);
|
||||
static void _pwmSetClock (int divisor);
|
||||
|
||||
/*----------------------------------------------------------------------------*/
|
||||
// board init function
|
||||
/*----------------------------------------------------------------------------*/
|
||||
@@ -258,6 +341,18 @@ static int gpioToMuxReg (int pin)
|
||||
}
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------*/
|
||||
static int gpioToPwmPin (int pin)
|
||||
{
|
||||
return _gpioToPwmPin[pin - N2_GPIOA_PIN_START];
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------*/
|
||||
static int gpioTophysPin (int pin)
|
||||
{
|
||||
return _gpioTophysPin[pin - N2_GPIOA_PIN_START];
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------*/
|
||||
static int _getModeToGpio (int mode, int pin)
|
||||
{
|
||||
@@ -335,7 +430,7 @@ static int _getPadDrive (int pin)
|
||||
/*----------------------------------------------------------------------------*/
|
||||
static int _pinMode (int pin, int mode)
|
||||
{
|
||||
int fsel, shift, origPin = pin;
|
||||
int fsel, mux, target, shift, origPin = pin;
|
||||
|
||||
if (lib->mode == MODE_GPIO_SYS)
|
||||
return -1;
|
||||
@@ -346,14 +441,18 @@ static int _pinMode (int pin, int mode)
|
||||
softPwmStop (origPin);
|
||||
softToneStop (origPin);
|
||||
|
||||
fsel = gpioToGPFSELReg(pin);
|
||||
shift = gpioToShiftReg (pin);
|
||||
fsel = gpioToGPFSELReg(pin);
|
||||
mux = gpioToMuxReg(pin);
|
||||
shift = gpioToShiftReg (pin);
|
||||
target = shift * 4;
|
||||
|
||||
switch (mode) {
|
||||
case INPUT:
|
||||
*(gpio + mux) = (*(gpio + mux) & ~(0xF << target));
|
||||
*(gpio + fsel) = (*(gpio + fsel) | (1 << shift));
|
||||
break;
|
||||
case OUTPUT:
|
||||
*(gpio + mux) = (*(gpio + mux) & ~(0xF << target));
|
||||
*(gpio + fsel) = (*(gpio + fsel) & ~(1 << shift));
|
||||
break;
|
||||
case SOFT_PWM_OUTPUT:
|
||||
@@ -361,6 +460,30 @@ static int _pinMode (int pin, int mode)
|
||||
break;
|
||||
case SOFT_TONE_OUTPUT:
|
||||
softToneCreate (origPin);
|
||||
break;
|
||||
case PWM_OUTPUT:
|
||||
usingGpioMemCheck ("pinMode PWM");
|
||||
|
||||
int pwm_pin, alt;
|
||||
pwm_pin = gpioToPwmPin(pin);
|
||||
if( pwm_pin == -1 )
|
||||
{
|
||||
msg(MSG_WARN, "%s : This pin does not support hardware PWM mode.\n", __func__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
alt = pwmPinToALT[pwm_pin];
|
||||
*(gpio + mux) = (*(gpio + mux) & ~(0xF << target)) | (alt << target);
|
||||
|
||||
/**
|
||||
* 24 MHz / 120
|
||||
* 200 kHz / 500
|
||||
* frequency of PWM: 400 Hz
|
||||
* period of PWM: 2500 us
|
||||
*/
|
||||
_pwmSetClock(120);
|
||||
_pwmSetRange(500);
|
||||
|
||||
break;
|
||||
default:
|
||||
msg(MSG_WARN, "%s : Unknown Mode %d\n", __func__, mode);
|
||||
@@ -499,6 +622,34 @@ static int _digitalWrite (int pin, int value)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------*/
|
||||
static int _pwmWrite (int pin, int value)
|
||||
{
|
||||
/**
|
||||
* @todo Add node
|
||||
* struct wiringPiNodeStruct *node = wiringPiNodes;
|
||||
*/
|
||||
|
||||
setupCheck ("pwmWrite") ;
|
||||
|
||||
if (lib->mode == MODE_GPIO_SYS)
|
||||
return -1;
|
||||
|
||||
if ((pin = _getModeToGpio(lib->mode, pin)) < 0)
|
||||
return -1;
|
||||
|
||||
int pwm_pin = gpioToPwmPin(pin);
|
||||
uint16_t range = pwmPinToRange[pwm_pin];
|
||||
|
||||
if( value > range ) {
|
||||
value = range;
|
||||
}
|
||||
|
||||
*(pwm[pwm_pin/2] + pwmPinToDutyOffset[pwm_pin]) = (value << 16) | (range - value);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------*/
|
||||
static int _analogRead (int pin)
|
||||
{
|
||||
@@ -572,6 +723,34 @@ static int _digitalWriteByte (const unsigned int value)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------*/
|
||||
void _pwmSetRange (unsigned int range)
|
||||
{
|
||||
range = range & 0xFFFF;
|
||||
for( int i = 0; i < 6; ++i )
|
||||
{
|
||||
pwmPinToRange[i] = range;
|
||||
}
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------*/
|
||||
void _pwmSetClock (int divisor)
|
||||
{
|
||||
divisor = (divisor - 1) & 0x7F;
|
||||
|
||||
for(uint16_t i = 1; i < 3; ++i) {
|
||||
*( pwm[i] + N2_PWM_MISC_REG_01_OFFSET ) = \
|
||||
(1 << N2_PWM_1_CLK_EN) \
|
||||
| ( divisor << N2_PWM_1_CLK_DIV0) \
|
||||
| (1 << N2_PWM_0_CLK_EN) \
|
||||
| ( divisor << N2_PWM_0_CLK_DIV0) \
|
||||
| (0 << N2_PWM_1_CLK_SEL0) \
|
||||
| (0 << N2_PWM_0_CLK_SEL0) \
|
||||
| (1 << N2_PWM_1_EN) \
|
||||
| (1 << N2_PWM_0_EN);
|
||||
}
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------*/
|
||||
static unsigned int _digitalReadByte (void)
|
||||
{
|
||||
@@ -596,6 +775,8 @@ static void init_gpio_mmap (void)
|
||||
msg(MSG_ERR,
|
||||
"wiringPiSetup: Unable to open /dev/gpiomem: %s\n",
|
||||
strerror (errno));
|
||||
|
||||
setUsingGpioMem( TRUE );
|
||||
} else
|
||||
msg(MSG_ERR,
|
||||
"wiringPiSetup: /dev/gpiomem doesn't exist. Please try again with sudo.\n");
|
||||
@@ -619,6 +800,12 @@ static void init_gpio_mmap (void)
|
||||
msg(MSG_ERR, "wiringPiSetup: mmap (GPIO) failed: %s \n", strerror (errno));
|
||||
else
|
||||
gpio = (uint32_t *) mapped;
|
||||
|
||||
for(uint16_t i = 1; i < 3; ++i) {
|
||||
pwm[i] = ( uint32_t * )mmap( 0, BLOCK_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, N2_GPIO_PWM_BASE + (0x1000 * (2 - i)) );
|
||||
if( ( void * )pwm == MAP_FAILED )
|
||||
msg(MSG_ERR, "wiringPiSetup: mmap (PWM) failed: %s \n", strerror (errno));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -655,10 +842,14 @@ void init_odroidn2 (struct libodroid *libwiring)
|
||||
libwiring->pullUpDnControl = _pullUpDnControl;
|
||||
libwiring->digitalRead = _digitalRead;
|
||||
libwiring->digitalWrite = _digitalWrite;
|
||||
libwiring->pwmWrite = _pwmWrite;
|
||||
libwiring->analogRead = _analogRead;
|
||||
libwiring->digitalWriteByte = _digitalWriteByte;
|
||||
libwiring->digitalReadByte = _digitalReadByte;
|
||||
|
||||
libwiring->pwmSetRange =_pwmSetRange;
|
||||
libwiring->pwmSetClock =_pwmSetClock;
|
||||
|
||||
/* specify pin base number */
|
||||
libwiring->pinBase = N2_GPIO_PIN_BASE;
|
||||
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
#define N2_GPIO_MASK (0xFFFFFF00)
|
||||
#define N2_GPIO_BASE 0xff634000
|
||||
#define N2_GPIO_PWM_BASE 0xFFD19000
|
||||
|
||||
#define N2_GPIO_PIN_BASE 410
|
||||
|
||||
@@ -40,6 +41,27 @@
|
||||
#define N2_GPIOA_MUX_D_REG_OFFSET 0x1BD
|
||||
#define N2_GPIOA_MUX_E_REG_OFFSET 0x1BE
|
||||
|
||||
/// S922X datasheet p.1075
|
||||
#define N2_PWM_CD_OFFSET 0x1000
|
||||
#define N2_PWM_EF_OFFSET 0
|
||||
#define N2_PWM_0_DUTY_CYCLE_OFFSET 0x00
|
||||
#define N2_PWM_1_DUTY_CYCLE_OFFSET 0x01
|
||||
#define N2_PWM_MISC_REG_01_OFFSET 0x02
|
||||
|
||||
/// PWM_MISC_REG_CD
|
||||
#define N2_PWM_1_INV_EN ( 27 )
|
||||
#define N2_PWM_0_INV_EN ( 26 )
|
||||
#define N2_PWM_1_CLK_EN ( 23 )
|
||||
#define N2_PWM_1_CLK_DIV0 ( 16 ) /// 22 ~ 16
|
||||
#define N2_PWM_0_CLK_EN ( 15 )
|
||||
#define N2_PWM_0_CLK_DIV0 ( 8 ) /// 14 ~ 8
|
||||
#define N2_PWM_1_CLK_SEL0 ( 6 ) /// 7 ~ 6
|
||||
#define N2_PWM_0_CLK_SEL0 ( 4 ) /// 5 ~ 4
|
||||
#define N2_PWM_1_DS_EN ( 3 )
|
||||
#define N2_PWM_0_DS_EN ( 2 )
|
||||
#define N2_PWM_1_EN ( 1 )
|
||||
#define N2_PWM_0_EN ( 0 )
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
@@ -664,6 +664,8 @@ static void init_gpio_mmap (void)
|
||||
msg (MSG_ERR,
|
||||
"wiringPiSetup: Unable to open /dev/gpiomem: %s\n",
|
||||
strerror (errno));
|
||||
|
||||
setUsingGpioMem( TRUE );
|
||||
} else
|
||||
msg (MSG_ERR,
|
||||
"wiringPiSetup: /dev/gpiomem doesn't exist. Please try again with sudo.\n");
|
||||
|
||||
@@ -124,6 +124,9 @@ extern void delay (unsigned int howLong) ;
|
||||
// ODROID Wiring Library
|
||||
struct libodroid libwiring;
|
||||
|
||||
unsigned int usingGpioMem = FALSE;
|
||||
int wiringPiSetuped = FALSE;
|
||||
|
||||
/*----------------------------------------------------------------------------*/
|
||||
//
|
||||
// Return true/false if the supplied module is loaded
|
||||
@@ -186,14 +189,10 @@ static void warn_msg(const char *func)
|
||||
//
|
||||
/*----------------------------------------------------------------------------*/
|
||||
static void UNU piGpioLayoutOops (const char UNU *why) { warn_msg(__func__); return; }
|
||||
void pwmSetMode (int UNU mode) { warn_msg(__func__); return; }
|
||||
void pwmSetRange (unsigned int UNU range) { warn_msg(__func__); return; }
|
||||
void pwmSetClock (int UNU divisor) { warn_msg(__func__); return; }
|
||||
void gpioClockSet (int UNU pin, int UNU freq) { warn_msg(__func__); return; }
|
||||
|
||||
/* core unsupport function */
|
||||
void pinModeAlt (int UNU pin, int UNU mode) { warn_msg(__func__); return; }
|
||||
void pwmWrite (int UNU pin, int UNU value) { warn_msg(__func__); return; }
|
||||
void analogWrite (int UNU pin, int UNU value) { warn_msg(__func__); return; }
|
||||
void pwmToneWrite (int UNU pin, int UNU freq) { warn_msg(__func__); return; }
|
||||
void digitalWriteByte2 (const int UNU value) { warn_msg(__func__); return; }
|
||||
@@ -276,6 +275,43 @@ int wiringPiFailure (int fatal, const char *message, ...)
|
||||
return 0 ;
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/*
|
||||
* setupCheck
|
||||
* Another sanity check because some users forget to call the setup
|
||||
* function. Mosty because they need feeding C drip by drip )-:
|
||||
*/
|
||||
/*----------------------------------------------------------------------------*/
|
||||
void setupCheck (const char *fName)
|
||||
{
|
||||
if (!wiringPiSetuped) {
|
||||
fprintf (stderr, "%s: You have not called one of the wiringPiSetup\n"
|
||||
" functions, so I'm aborting your program before it crashes anyway.\n", fName) ;
|
||||
exit (EXIT_FAILURE) ;
|
||||
}
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/*
|
||||
* gpioMemCheck:
|
||||
* See if we're using the /dev/gpiomem interface, if-so then some operations
|
||||
* can't be done and will crash the Pi.
|
||||
*/
|
||||
/*----------------------------------------------------------------------------*/
|
||||
void usingGpioMemCheck (const char *what)
|
||||
{
|
||||
if (usingGpioMem) {
|
||||
fprintf (stderr, "%s: Unable to do this when using /dev/gpiomem. Try sudo?\n", what) ;
|
||||
exit (EXIT_FAILURE) ;
|
||||
}
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------*/
|
||||
void setUsingGpioMem( const unsigned int value )
|
||||
{
|
||||
usingGpioMem = value;
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------*/
|
||||
int piGpioLayout (void)
|
||||
{
|
||||
@@ -511,6 +547,57 @@ int getAlt (int pin)
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/*
|
||||
* pwmSetMode:
|
||||
* Select the native "balanced" mode, or standard mark:space mode
|
||||
*/
|
||||
/*----------------------------------------------------------------------------*/
|
||||
|
||||
void pwmSetMode (int mode)
|
||||
{
|
||||
if (libwiring.pwmSetMode) {
|
||||
libwiring.pwmSetMode(mode);
|
||||
} else {
|
||||
warn_msg(__func__);
|
||||
}
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/*
|
||||
* pwmSetRange:
|
||||
* Set the PWM range register. We set both range registers to the same
|
||||
* value. If you want different in your own code, then write your own.
|
||||
*/
|
||||
/*----------------------------------------------------------------------------*/
|
||||
|
||||
void pwmSetRange (unsigned int range)
|
||||
{
|
||||
if (libwiring.pwmSetRange) {
|
||||
libwiring.pwmSetRange(range);
|
||||
} else {
|
||||
warn_msg(__func__);
|
||||
}
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/*
|
||||
* pwmSetClock:
|
||||
* Set/Change the PWM clock. Originally my code, but changed
|
||||
* (for the better!) by Chris Hall, <chris@kchall.plus.com>
|
||||
* after further study of the manual and testing with a 'scope
|
||||
*/
|
||||
/*----------------------------------------------------------------------------*/
|
||||
|
||||
void pwmSetClock (int divisor)
|
||||
{
|
||||
if (libwiring.pwmSetClock) {
|
||||
libwiring.pwmSetClock(divisor);
|
||||
} else {
|
||||
warn_msg(__func__);
|
||||
}
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/*
|
||||
* getPUPD:
|
||||
@@ -564,6 +651,16 @@ void digitalWrite (int pin, int value)
|
||||
msg(MSG_WARN, "%s: Not available for pin %d. \n", __func__, pin);
|
||||
}
|
||||
|
||||
void pwmWrite(int pin, int value)
|
||||
{
|
||||
if (libwiring.pwmWrite) {
|
||||
if (libwiring.pwmWrite(pin, value) < 0)
|
||||
msg(MSG_WARN, "%s: Not available for pin %d. \n", __func__, pin);
|
||||
} else {
|
||||
warn_msg(__func__);
|
||||
}
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------*/
|
||||
int analogRead (int pin)
|
||||
{
|
||||
@@ -932,12 +1029,10 @@ void wiringPiVersion (int *major, char **minor)
|
||||
int wiringPiSetup (void)
|
||||
{
|
||||
int i;
|
||||
static int alreadyDoneThis = FALSE;
|
||||
|
||||
if (alreadyDoneThis)
|
||||
if (wiringPiSetuped)
|
||||
return 0;
|
||||
|
||||
alreadyDoneThis = TRUE;
|
||||
wiringPiSetuped = TRUE;
|
||||
|
||||
// libwiring init
|
||||
memset(&libwiring, 0x00, sizeof(struct libodroid));
|
||||
|
||||
@@ -134,10 +134,15 @@ struct libodroid
|
||||
int (*pullUpDnControl) (int pin, int pud);
|
||||
int (*digitalRead) (int pin);
|
||||
int (*digitalWrite) (int pin, int value);
|
||||
int (*pwmWrite) (int pin, int value);
|
||||
int (*analogRead) (int pin);
|
||||
int (*digitalWriteByte) (const unsigned int value);
|
||||
unsigned int (*digitalReadByte) (void);
|
||||
|
||||
void (*pwmSetMode) (int mode);
|
||||
void (*pwmSetRange) (unsigned int range);
|
||||
void (*pwmSetClock) (int divisor);
|
||||
|
||||
/* ISR Function pointer */
|
||||
void (*isrFunctions[256])(void);
|
||||
pthread_t isrThreadIds[256];
|
||||
@@ -238,9 +243,12 @@ extern struct wiringPiNodeStruct *wiringPiFindNode (int pin);
|
||||
extern struct wiringPiNodeStruct *wiringPiNewNode (int pinBase, int numPins);
|
||||
|
||||
// Internal WiringPi functions
|
||||
extern int wiringPiFailure (int fatal, const char *message, ...);
|
||||
extern int msg (int type, const char *message, ...);
|
||||
extern int moduleLoaded (char *);
|
||||
extern int wiringPiFailure (int fatal, const char *message, ...);
|
||||
extern int msg (int type, const char *message, ...);
|
||||
extern int moduleLoaded (char *);
|
||||
extern void setupCheck (const char *fName);
|
||||
extern void usingGpioMemCheck (const char *what);
|
||||
extern void setUsingGpioMem ( const unsigned int value );
|
||||
|
||||
// Core WiringPi functions
|
||||
extern void wiringPiVersion (int *major, char **minor);
|
||||
|
||||
Reference in New Issue
Block a user