From 010207ea64bc5b9a04d8f3a5a110e821ae81e9bb Mon Sep 17 00:00:00 2001 From: Hyeonki Hong Date: Mon, 5 Aug 2019 14:30:31 +0900 Subject: [PATCH] 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. --- wiringPi/odroidc1.c | 2 + wiringPi/odroidc2.c | 2 + wiringPi/odroidn1.c | 2 + wiringPi/odroidn2.c | 275 ++++++++++++++++++++++++++++++++++++------- wiringPi/odroidn2.h | 22 ++++ wiringPi/odroidxu3.c | 2 + wiringPi/wiringPi.c | 111 +++++++++++++++-- wiringPi/wiringPi.h | 14 ++- 8 files changed, 377 insertions(+), 53 deletions(-) diff --git a/wiringPi/odroidc1.c b/wiringPi/odroidc1.c index 0b69e1e..b04045e 100755 --- a/wiringPi/odroidc1.c +++ b/wiringPi/odroidc1.c @@ -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"); diff --git a/wiringPi/odroidc2.c b/wiringPi/odroidc2.c index 20593d4..1078054 100755 --- a/wiringPi/odroidc2.c +++ b/wiringPi/odroidc2.c @@ -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"); diff --git a/wiringPi/odroidn1.c b/wiringPi/odroidn1.c index 7eee3d9..d69e3f1 100755 --- a/wiringPi/odroidn1.c +++ b/wiringPi/odroidn1.c @@ -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"); diff --git a/wiringPi/odroidn2.c b/wiringPi/odroidn2.c index 96b77a7..2c4970e 100755 --- a/wiringPi/odroidn2.c +++ b/wiringPi/odroidn2.c @@ -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; diff --git a/wiringPi/odroidn2.h b/wiringPi/odroidn2.h index c584092..dddc7db 100755 --- a/wiringPi/odroidn2.h +++ b/wiringPi/odroidn2.h @@ -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 diff --git a/wiringPi/odroidxu3.c b/wiringPi/odroidxu3.c index d8b6b4f..9fe24aa 100755 --- a/wiringPi/odroidxu3.c +++ b/wiringPi/odroidxu3.c @@ -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"); diff --git a/wiringPi/wiringPi.c b/wiringPi/wiringPi.c index 84a1e86..870315e 100755 --- a/wiringPi/wiringPi.c +++ b/wiringPi/wiringPi.c @@ -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, + * 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)); diff --git a/wiringPi/wiringPi.h b/wiringPi/wiringPi.h index f2b7199..00fdb0b 100755 --- a/wiringPi/wiringPi.h +++ b/wiringPi/wiringPi.h @@ -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);