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:
Hyeonki Hong
2019-08-05 14:30:31 +09:00
committed by Joshua Yang
parent 714fd072a9
commit 010207ea64
8 changed files with 377 additions and 53 deletions

View File

@@ -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");

View File

@@ -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");

View File

@@ -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");

View File

@@ -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;

View File

@@ -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

View File

@@ -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");

View File

@@ -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));

View File

@@ -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);