Skip to content

Commit

Permalink
Update to RPi.GPIO 0.7.0
Browse files Browse the repository at this point in the history
  • Loading branch information
ClockVapor committed Jul 21, 2020
1 parent 1a8f5d2 commit 91c4df5
Show file tree
Hide file tree
Showing 17 changed files with 347 additions and 201 deletions.
2 changes: 1 addition & 1 deletion .gemspec
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
Gem::Specification.new do |s|
s.name = 'rpi_gpio'
s.version = '0.3.3'
s.version = '0.4.0'
s.licenses = ['MIT']
s.summary = 'Ruby conversion of RPi.GPIO Python module'
s.description = s.summary
Expand Down
5 changes: 2 additions & 3 deletions LICENSE
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
The MIT License (MIT)

Copyright (c) 2014-2015 Nick Lowery
Copyright (c) 2013-2014 Ben Croston
Copyright (c) 2014-2020 Nick Lowery
Copyright (c) 2012-2014 Ben Croston

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
Expand All @@ -20,4 +20,3 @@ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# rpi_gpio v0.3.3
# rpi_gpio v0.4.0

Ruby conversion of [RPi.GPIO Python module](https://pypi.python.org/pypi/RPi.GPIO)

Expand All @@ -9,7 +9,7 @@ Manipulate your Raspberry Pi's GPIO pins from Ruby!
- Boolean input/output
- Software-driven PWM (written in C for speed)

Up-to-date with RPi.GPIO Python module version 0.6.3, so it works on all Raspberry Pi models!
Up-to-date with RPi.GPIO Python module version 0.7.0, so it works on all Raspberry Pi models!

## Sample Usage

Expand Down Expand Up @@ -139,7 +139,7 @@ to clean up all pins and to also reset the selected numbering mode.

Original Python code by Ben Croston modified for Ruby by Nick Lowery

Copyright (c) 2014-2015 [Nick Lowery](https://github.com/ClockVapor)
Copyright (c) 2014-2020 [Nick Lowery](https://github.com/ClockVapor)

View LICENSE for full license.

113 changes: 63 additions & 50 deletions ext/rpi_gpio/c_gpio.c
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
/*
Original code by Ben Croston modified for Ruby by Nick Lowery
(github.com/clockvapor)
Copyright (c) 2014-2016 Nick Lowery
Copyright (c) 2014-2020 Nick Lowery
Copyright (c) 2013-2015 Ben Croston
Copyright (c) 2012-2019 Ben Croston
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
Expand Down Expand Up @@ -47,6 +47,11 @@ SOFTWARE.
#define PULLUPDN_OFFSET 37 // 0x0094 / 4
#define PULLUPDNCLK_OFFSET 38 // 0x0098 / 4

#define PULLUPDN_OFFSET_2711_0 57
#define PULLUPDN_OFFSET_2711_1 58
#define PULLUPDN_OFFSET_2711_2 59
#define PULLUPDN_OFFSET_2711_3 60

#define PAGE_SIZE (4*1024)
#define BLOCK_SIZE (4*1024)

Expand All @@ -65,7 +70,7 @@ int setup(void)
{
int mem_fd;
uint8_t *gpio_mem;
uint32_t peri_base;
uint32_t peri_base = 0;
uint32_t gpio_base;
unsigned char buf[4];
FILE *fp;
Expand All @@ -76,8 +81,7 @@ int setup(void)
// try /dev/gpiomem first - this does not require root privs
if ((mem_fd = open("/dev/gpiomem", O_RDWR|O_SYNC)) > 0)
{
gpio_map = (uint32_t *)mmap(NULL, BLOCK_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED, mem_fd, 0);
if ((uint32_t)gpio_map < 0) {
if ((gpio_map = (uint32_t *)mmap(NULL, BLOCK_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED, mem_fd, 0)) == MAP_FAILED) {
return SETUP_MMAP_FAIL;
} else {
return SETUP_OK;
Expand All @@ -99,8 +103,7 @@ int setup(void)
if ((fp = fopen("/proc/cpuinfo", "r")) == NULL)
return SETUP_CPUINFO_FAIL;

while(!feof(fp) && !found) {
fgets(buffer, sizeof(buffer), fp);
while(!feof(fp) && !found && fgets(buffer, sizeof(buffer), fp)) {
sscanf(buffer, "Hardware : %s", hardware);
if (strcmp(hardware, "BCM2708") == 0 || strcmp(hardware, "BCM2835") == 0) {
// pi 1 hardware
Expand All @@ -117,26 +120,22 @@ int setup(void)
return SETUP_NOT_RPI_FAIL;
}

if (!peri_base)
return SETUP_NOT_RPI_FAIL;
gpio_base = peri_base + GPIO_BASE_OFFSET;

// mmap the GPIO memory registers
if ((mem_fd = open("/dev/mem", O_RDWR|O_SYNC) ) < 0) {
if ((mem_fd = open("/dev/mem", O_RDWR|O_SYNC) ) < 0)
return SETUP_DEVMEM_FAIL;
}

if ((gpio_mem = malloc(BLOCK_SIZE + (PAGE_SIZE-1))) == NULL) {
if ((gpio_mem = malloc(BLOCK_SIZE + (PAGE_SIZE-1))) == NULL)
return SETUP_MALLOC_FAIL;
}

if ((uint32_t)gpio_mem % PAGE_SIZE) {
gpio_mem += PAGE_SIZE - ((uint32_t) gpio_mem % PAGE_SIZE);
}

gpio_map = (uint32_t *) mmap((void *) gpio_mem, BLOCK_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED|MAP_FIXED, mem_fd, gpio_base);
if ((uint32_t)gpio_mem % PAGE_SIZE)
gpio_mem += PAGE_SIZE - ((uint32_t)gpio_mem % PAGE_SIZE);

if ((uint32_t) gpio_map < 0) {
if ((gpio_map = (uint32_t *)mmap( (void *)gpio_mem, BLOCK_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED|MAP_FIXED, mem_fd, gpio_base)) == MAP_FAILED)
return SETUP_MMAP_FAIL;
}

return SETUP_OK;
}
Expand All @@ -158,9 +157,8 @@ int eventdetected(int gpio)
offset = EVENT_DETECT_OFFSET + (gpio/32);
bit = (1 << (gpio%32));
value = *(gpio_map+offset) & bit;
if (value) {
if (value)
clear_event_detect(gpio);
}
return value;
}

Expand All @@ -169,11 +167,10 @@ void set_rising_event(int gpio, int enable)
int offset = RISING_ED_OFFSET + (gpio/32);
int shift = (gpio%32);

if (enable) {
if (enable)
*(gpio_map+offset) |= 1 << shift;
} else {
else
*(gpio_map+offset) &= ~(1 << shift);
}
clear_event_detect(gpio);
}

Expand All @@ -196,11 +193,10 @@ void set_high_event(int gpio, int enable)
int offset = HIGH_DETECT_OFFSET + (gpio/32);
int shift = (gpio%32);

if (enable) {
if (enable)
*(gpio_map+offset) |= (1 << shift);
} else {
else
*(gpio_map+offset) &= ~(1 << shift);
}
clear_event_detect(gpio);
}

Expand All @@ -209,33 +205,51 @@ void set_low_event(int gpio, int enable)
int offset = LOW_DETECT_OFFSET + (gpio/32);
int shift = (gpio%32);

if (enable) {
if (enable)
*(gpio_map+offset) |= 1 << shift;
} else {
else
*(gpio_map+offset) &= ~(1 << shift);
}
clear_event_detect(gpio);
}

void set_pullupdn(int gpio, int pud)
{
int clk_offset = PULLUPDNCLK_OFFSET + (gpio/32);
int shift = (gpio%32);

if (pud == PUD_DOWN) {
*(gpio_map+PULLUPDN_OFFSET) = (*(gpio_map+PULLUPDN_OFFSET) & ~3) |
PUD_DOWN;
} else if (pud == PUD_UP) {
*(gpio_map+PULLUPDN_OFFSET) = (*(gpio_map+PULLUPDN_OFFSET) & ~3) | PUD_UP;
} else { // pud == PUD_OFF
// Check GPIO register
int is2711 = *(gpio_map+PULLUPDN_OFFSET_2711_3) != 0x6770696f;
if (is2711) {
// Pi 4 Pull-up/down method
int pullreg = PULLUPDN_OFFSET_2711_0 + (gpio >> 4);
int pullshift = (gpio & 0xf) << 1;
unsigned int pullbits;
unsigned int pull = 0;
switch (pud) {
case PUD_OFF: pull = 0; break;
case PUD_UP: pull = 1; break;
case PUD_DOWN: pull = 2; break;
default: pull = 0; // switch PUD to OFF for other values
}
pullbits = *(gpio_map + pullreg);
pullbits &= ~(3 << pullshift);
pullbits |= (pull << pullshift);
*(gpio_map + pullreg) = pullbits;
} else {
// Legacy Pull-up/down method
int clk_offset = PULLUPDNCLK_OFFSET + (gpio/32);
int shift = (gpio%32);

if (pud == PUD_DOWN) {
*(gpio_map+PULLUPDN_OFFSET) = (*(gpio_map+PULLUPDN_OFFSET) & ~3) | PUD_DOWN;
} else if (pud == PUD_UP) {
*(gpio_map+PULLUPDN_OFFSET) = (*(gpio_map+PULLUPDN_OFFSET) & ~3) | PUD_UP;
} else { // pud == PUD_OFF
*(gpio_map+PULLUPDN_OFFSET) &= ~3;
}
short_wait();
*(gpio_map+clk_offset) = 1 << shift;
short_wait();
*(gpio_map+PULLUPDN_OFFSET) &= ~3;
*(gpio_map+clk_offset) = 0;
}

short_wait();
*(gpio_map+clk_offset) = 1 << shift;
short_wait();
*(gpio_map+PULLUPDN_OFFSET) &= ~3;
*(gpio_map+clk_offset) = 0;
}

void setup_gpio(int gpio, int direction, int pud)
Expand Down Expand Up @@ -265,12 +279,11 @@ void output_gpio(int gpio, int value)
{
int offset, shift;

if (value) { // value == HIGH
if (value) // value == HIGH
offset = SET_OFFSET + (gpio/32);
} else { // value == LOW
offset = CLR_OFFSET + (gpio/32);
}

else // value == LOW
offset = CLR_OFFSET + (gpio/32);

shift = (gpio%32);

*(gpio_map+offset) = 1 << shift;
Expand All @@ -288,5 +301,5 @@ int input_gpio(int gpio)

void cleanup(void)
{
munmap((void *) gpio_map, BLOCK_SIZE);
munmap((void *)gpio_map, BLOCK_SIZE);
}
10 changes: 5 additions & 5 deletions ext/rpi_gpio/c_gpio.h
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/*
Original code by Ben Croston modified for Ruby by Nick Lowery
(github.com/clockvapor)
Copyright (c) 2014-2016 Nick Lowery
Copyright (c) 2014-2020 Nick Lowery
Copyright (c) 2013-2015 Ben Croston
Expand Down Expand Up @@ -36,10 +36,10 @@ void set_low_event(int gpio, int enable);
int eventdetected(int gpio);
void cleanup(void);

#define SETUP_OK 0
#define SETUP_DEVMEM_FAIL 1
#define SETUP_MALLOC_FAIL 2
#define SETUP_MMAP_FAIL 3
#define SETUP_OK 0
#define SETUP_DEVMEM_FAIL 1
#define SETUP_MALLOC_FAIL 2
#define SETUP_MMAP_FAIL 3
#define SETUP_CPUINFO_FAIL 4
#define SETUP_NOT_RPI_FAIL 5

Expand Down
14 changes: 5 additions & 9 deletions ext/rpi_gpio/common.c
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/*
Original code by Ben Croston modified for Ruby by Nick Lowery
(github.com/clockvapor)
Copyright (c) 2014-2016 Nick Lowery
Copyright (c) 2014-2020 Nick Lowery
Copyright (c) 2013-2014 Ben Croston
Expand Down Expand Up @@ -47,8 +47,7 @@ int check_gpio_priv(void)
// check mmap setup has worked
if (!module_setup)
{
rb_raise(rb_eRuntimeError, "no access to /dev/mem. Try "
"running as root!");
rb_raise(rb_eRuntimeError, "no access to /dev/mem. Try running as root!");
return 2;
}
return 0;
Expand All @@ -67,10 +66,8 @@ int get_gpio_number(int channel, unsigned int *gpio)

// check channel number is in range
if ( (gpio_mode == BCM && (channel < 0 || channel > 53))
|| (gpio_mode == BOARD && (channel < 1 || channel > 26) &&
rpiinfo.p1_revision != 3)
|| (gpio_mode == BOARD && (channel < 1 || channel > 40) &&
rpiinfo.p1_revision == 3))
|| (gpio_mode == BOARD && (channel < 1 || channel > 26) && rpiinfo.p1_revision != 3)
|| (gpio_mode == BOARD && (channel < 1 || channel > 40) && rpiinfo.p1_revision == 3) )
{
rb_raise(rb_eArgError, "the channel sent is invalid on a Raspberry Pi");
return 4;
Expand All @@ -81,8 +78,7 @@ int get_gpio_number(int channel, unsigned int *gpio)
{
if (*(*pin_to_gpio+channel) == -1)
{
rb_raise(rb_eArgError, "the channel sent is invalid on a Raspberry "
"Pi");
rb_raise(rb_eArgError, "the channel sent is invalid on a Raspberry Pi");
return 5;
} else {
*gpio = *(*pin_to_gpio+channel);
Expand Down
2 changes: 1 addition & 1 deletion ext/rpi_gpio/common.h
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/*
Original code by Ben Croston modified for Ruby by Nick Lowery
(github.com/clockvapor)
Copyright (c) 2014-2016 Nick Lowery
Copyright (c) 2014-2020 Nick Lowery
Copyright (c) 2013-2015 Ben Croston
Expand Down
Loading

0 comments on commit 91c4df5

Please sign in to comment.