From be20125bcd9ba4adc567f2715bd73762b0d5b7de Mon Sep 17 00:00:00 2001 From: John Comeau Date: Mon, 3 Jul 2017 17:12:25 -0700 Subject: [PATCH 01/60] first stab at ARTIK 710 mapping, woefully incomplete --- contrib/board_files/artik_710.conf | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 contrib/board_files/artik_710.conf diff --git a/contrib/board_files/artik_710.conf b/contrib/board_files/artik_710.conf new file mode 100644 index 0000000..2b4952e --- /dev/null +++ b/contrib/board_files/artik_710.conf @@ -0,0 +1,17 @@ +[board] +model = Samsung ARTIK 710 + +[GPIO] +# https://developer.artik.io/documentation/developer-guide/gpio/ +# gpio-mapping.html +GPIO0 = 128 +GPIO1 = 129 +GPIO2 = 130 +GPIO3 = 46 +GPIO4 = 14 +GPIO5 = 41 +GPIO6 = 25 +SW403 = 30 +SW404 = 32 +RED_LED = 28 +BLUE_LED = 38 From 86b961a3fec010ed655991cd56cc4ad8688421d9 Mon Sep 17 00:00:00 2001 From: John Comeau Date: Mon, 3 Jul 2017 23:27:24 -0700 Subject: [PATCH 02/60] found another source --- contrib/board_files/artik_710.conf | 347 ++++++++++++++++++++++++++++- 1 file changed, 341 insertions(+), 6 deletions(-) diff --git a/contrib/board_files/artik_710.conf b/contrib/board_files/artik_710.conf index 2b4952e..393be70 100644 --- a/contrib/board_files/artik_710.conf +++ b/contrib/board_files/artik_710.conf @@ -4,14 +4,349 @@ model = Samsung ARTIK 710 [GPIO] # https://developer.artik.io/documentation/developer-guide/gpio/ # gpio-mapping.html -GPIO0 = 128 -GPIO1 = 129 -GPIO2 = 130 -GPIO3 = 46 +# and https://static.artik.io/files/SW_UserGuide_ARTIK-710_V1.0.pdf gave some +# more clues, upon which I extrapolated -- jc at unternet dot net +GPIOA0 = 0 +GPA0 = 0 +GPIO7 = 0 +GPIOA1 = 1 +GPA1 = 1 +GPIOA2 = 2 +GPA2 = 2 +GPIOA3 = 3 +GPA3 = 3 +GPIOA4 = 4 +GPA4 = 4 +GPIOA5 = 5 +GPA5 = 5 +GPIOA6 = 6 +GPA6 = 6 +GPIOA7 = 7 +GPA7 = 7 +GPIOA8 = 8 +GPA8 = 8 +GPIOA9 = 9 +GPA9 = 9 +GPIOA10 = 10 +GPA10 = 10 +GPIOA11 = 11 +GPA11 = 11 +GPIOA12 = 12 +GPA12 = 12 +GPIOA13 = 13 +GPA13 = 13 +GPIOA14 = 14 +GPA14 = 14 GPIO4 = 14 -GPIO5 = 41 +GPIOA15 = 15 +GPA15 = 15 +GPIOA16 = 16 +GPA16 = 16 +GPIOA17 = 17 +GPA17 = 17 +GPIOA18 = 18 +GPA18 = 18 +GPIOA19 = 19 +GPA19 = 19 +GPIOA20 = 20 +GPA20 = 20 +GPIOA21 = 21 +GPA21 = 21 +GPIOA22 = 22 +GPA22 = 22 +GPIOA23 = 23 +GPA23 = 23 +GPIOA24 = 24 +GPA24 = 24 +GPIOA25 = 25 +GPA25 = 25 GPIO6 = 25 +GPIOA26 = 26 +GPA26 = 26 +GPIO8 = 26 +GPIOA27 = 27 +GPA27 = 27 +GPIO9 = 27 +GPIOA28 = 28 +GPA28 = 28 +RED_LED = 28 +GPIOA29 = 29 +GPA29 = 29 +GPIOA30 = 30 +GPA30 = 30 SW403 = 30 +GPIOA31 = 31 +GPA31 = 31 +GPIOB0 = 32 +GPB0 = 32 SW404 = 32 -RED_LED = 28 +GPIOB1 = 33 +GPB1 = 33 +GPIOB2 = 34 +GPB2 = 34 +GPIOB3 = 35 +GPB3 = 35 +GPIOB4 = 36 +GPB4 = 36 +GPIOB5 = 37 +GPB5 = 37 +GPIOB6 = 38 +GPB6 = 38 BLUE_LED = 38 +GPIOB7 = 39 +GPB7 = 39 +GPIOB8 = 40 +GPB8 = 40 +GPIOB9 = 41 +GPB9 = 41 +GPIO5 = 41 +GPIOB10 = 42 +GPB10 = 42 +GPIOB11 = 43 +GPB11 = 43 +GPIOB12 = 44 +GPB12 = 44 +GPIOB13 = 45 +GPB13 = 45 +GPIOB14 = 46 +GBP14 = 46 +GPIO3 = 46 +GPIOB15 = 47 +GPB15 = 47 +GPIOB16 = 48 +GPB16 = 48 +GPIOB17 = 49 +GPB17 = 49 +GPIOB18 = 50 +GPB18 = 50 +GPIOB19 = 51 +GPB19 = 51 +GPIOB20 = 52 +GPB20 = 52 +GPIOB21 = 53 +GPB21 = 53 +GPIOB22 = 54 +GPB22 = 54 +GPIOB23 = 55 +GPB23 = 55 +GPIOB24 = 56 +GPB24 = 56 +GPIOB25 = 57 +GPB25 = 57 +GPIOB26 = 58 +GPB26 = 58 +GPIOB27 = 59 +GPB27 = 59 +GPIOB28 = 60 +GPB28 = 60 +UART0_RX = 60 +GPIOB29 = 61 +GPB29 = 61 +UART0_TX = 61 +GPIOB30 = 62 +GPB30 = 62 +GPIOB31 = 63 +GPB31 = 63 +GPIOC0 = 64 +GPC0 = 64 +GPIOC1 = 65 +GPC1 = 65 +GPIOC2 = 66 +GPC2 = 66 +GPIOC3 = 67 +GPC3 = 67 +GPIOC4 = 68 +GPC4 = 68 +GPIOC5 = 69 +GPC5 = 69 +GPIOC6 = 70 +GPC6 = 70 +GPIOC7 = 71 +GPC7 = 71 +GPIOC8 = 72 +GPC8 = 72 +GPIOC9 = 73 +GPC9 = 73 +SPI_CLK = 73 +GPIOC10 = 74 +GPC10 = 74 +SPI_CS = 74 +GPIOC11 = 75 +GPC11 = 75 +SPI_MISO = 75 +GPIOC12 = 76 +GPC12 = 76 +SPI_MOSI = 76 +GPIOC13 = 77 +GPC13 = 77 +GPIOC14 = 78 +GPC14 = 78 +GPIOC15 = 79 +GPC15 = 79 +GPIOC16 = 80 +GPC16 = 80 +GPIOC17 = 81 +GPC17 = 81 +GPIOC18 = 82 +GPC18 = 82 +GPIOC19 = 83 +GPC19 = 83 +GPIOC20 = 84 +GPC20 = 84 +GPIOC21 = 85 +GPC21 = 85 +GPIOC22 = 86 +GPC22 = 86 +GPIOC23 = 87 +GPC23 = 87 +GPIOC24 = 88 +GPC24 = 88 +GPIOC25 = 89 +GPC25 = 89 +GPIOC26 = 90 +GPC26 = 90 +GPIOC27 = 91 +GPC27 = 91 +GPIOC28 = 92 +GPC28 = 92 +GPIOC29 = 93 +GPC29 = 93 +GPIOC30 = 94 +GPC30 = 94 +GPIOC31 = 95 +GPC31 = 95 +GPIOD0 = 96 +GPD0 = 96 +GPIOD1 = 97 +GPD1 = 97 +GPIOD2 = 98 +GPD2 = 98 +GPIOD3 = 99 +GPD3 = 99 +GPIOD4 = 100 +GPD4 = 100 +I2C_SCL = 100 +GPIOD5 = 101 +GPD5 = 101 +I2C_SDA = 101 +GPIOD6 = 102 +GPD6 = 102 +GPIOD7 = 103 +GPD7 = 103 +GPIOD8 = 104 +GPD8 = 104 +GPIOD9 = 105 +GPD9 = 105 +GPIOD10 = 106 +GPD10 = 106 +GPIOD11 = 107 +GPD11 = 107 +GPIOD12 = 108 +GPD12 = 108 +GPIOD13 = 109 +GPD13 = 109 +GPIOD14 = 110 +GPD14 = 110 +GPIOD15 = 111 +GPD15 = 111 +GPIOD16 = 112 +GPD16 = 112 +GPIOD17 = 113 +GPD17 = 113 +GPIOD18 = 114 +GPD18 = 114 +GPIOD19 = 115 +GPD19 = 115 +GPIOD20 = 116 +GPD20 = 116 +GPIOD21 = 117 +GPD21 = 117 +GPIOD22 = 118 +GPD22 = 118 +GPIOD23 = 119 +GPD23 = 119 +GPIOD24 = 120 +GPD24 = 120 +GPIOD25 = 121 +GPD25 = 121 +GPIOD26 = 122 +GPD26 = 122 +GPIOD27 = 123 +GPD27 = 123 +GPIOD28 = 124 +GPD28 = 124 +GPIOD29 = 125 +GPD29 = 125 +GPIOD30 = 126 +GPD30 = 126 +GPIOD31 = 127 +GPD31 = 127 +GPIOE0 = 128 +GPE0 = 128 +GPIO0 = 128 +GPIOE1 = 129 +GPE1 = 129 +GPIO1 = 129 +GPIOE2 = 130 +GPE2 = 130 +GPIO2 = 130 +GPIOE3 = 131 +GPE3 = 131 +GPIOE4 = 132 +GPE4 = 132 +GPIOE5 = 133 +GPE5 = 133 +GPIOE6 = 134 +GPE6 = 134 +GPIOE7 = 135 +GPE7 = 135 +GPIOE8 = 136 +GPE8 = 136 +GPIOE9 = 137 +GPE9 = 137 +GPIOE10 = 138 +GPE10 = 138 +GPIOE11 = 139 +GPE11 = 139 +GPIOE12 = 140 +GPE12 = 140 +GPIOE13 = 141 +GPE13 = 141 +GPIOE14 = 142 +GPE14 = 142 +GPIOE15 = 143 +GPE15 = 143 +GPIOE16 = 144 +GPE16 = 144 +GPIOE17 = 145 +GPE17 = 145 +GPIOE18 = 146 +GPE18 = 146 +GPIOE19 = 147 +GPE19 = 147 +GPIOE20 = 148 +GPE20 = 148 +GPIOE21 = 149 +GPE21 = 149 +GPIOE22 = 150 +GPE22 = 150 +GPIOE23 = 151 +GPE23 = 151 +GPIOE24 = 152 +GPE24 = 152 +GPIOE25 = 153 +GPE25 = 153 +GPIOE26 = 154 +GPE26 = 154 +GPIOE27 = 155 +GPE27 = 155 +GPIOE28 = 156 +GPE28 = 156 +GPIOE29 = 157 +GPE29 = 157 +GPIOE30 = 158 +GPE30 = 158 +GPIOE31 = 159 +GPE31 = 159 +AGPIO0 = 161 +ALIVE1 = 161 From b1e414c52beb93ec4de7749d69d0d72ff5c94b1a Mon Sep 17 00:00:00 2001 From: John Comeau Date: Mon, 3 Jul 2017 23:31:42 -0700 Subject: [PATCH 03/60] correction --- contrib/board_files/artik_710.conf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contrib/board_files/artik_710.conf b/contrib/board_files/artik_710.conf index 393be70..46d764d 100644 --- a/contrib/board_files/artik_710.conf +++ b/contrib/board_files/artik_710.conf @@ -109,7 +109,7 @@ GPB12 = 44 GPIOB13 = 45 GPB13 = 45 GPIOB14 = 46 -GBP14 = 46 +GPB14 = 46 GPIO3 = 46 GPIOB15 = 47 GPB15 = 47 From ce7a55d9ef4197f73de09c15f9b5fee3fb60e9a4 Mon Sep 17 00:00:00 2001 From: John Comeau Date: Tue, 4 Jul 2017 00:54:06 -0700 Subject: [PATCH 04/60] for some reason ldconfig did not get run, possibly because I ran `make install` without `sudo` at first? in any case, this addition cannot hurt. --- static-docs/docs/index.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/static-docs/docs/index.md b/static-docs/docs/index.md index ea107b7..3df5296 100644 --- a/static-docs/docs/index.md +++ b/static-docs/docs/index.md @@ -146,6 +146,12 @@ Install the library using make make install ``` +Run `ldconfig` to update library cache + +```text +sudo ldconfig +``` + ## Documentation Written documentation can be found at From 06b685efa18e6a9259c5dc84a1d90a5fb560eeca Mon Sep 17 00:00:00 2001 From: John Comeau Date: Fri, 7 Jul 2017 12:58:24 -0700 Subject: [PATCH 05/60] fixes sigsegv when ignorant programmer doesn't use `open` or `request_gpios` --- bindings/python/gpio.py | 10 ++++++++++ lib/gpio.c | 6 ++++++ 2 files changed, 16 insertions(+) diff --git a/bindings/python/gpio.py b/bindings/python/gpio.py index 4c4823e..ffbe3df 100644 --- a/bindings/python/gpio.py +++ b/bindings/python/gpio.py @@ -64,6 +64,7 @@ def close(self): self._gpio = None def set_direction(self, direction, edge): + assert self._gpio is not None self._validate_direction(direction, edge) api.libsoc_gpio_set_direction(self._gpio, self.direction) if self.direction == DIRECTION_INPUT: @@ -71,11 +72,13 @@ def set_direction(self, direction, edge): raise IOError('Error setting edge for GPIO_%d' % self.id) def set_edge(self, edge): + assert self._gpio is not None self._validate_direction(self.direction, edge) if api.libsoc_gpio_set_edge(self._gpio, self.edge) != 0: raise IOError('Error setting edge for GPIO_%d' % self.id) def get_direction(self): + assert self._gpio is not None d = api.libsoc_gpio_get_direction(self._gpio) if d == -1: raise IOError('Error reading GPIO_%d direction: %d' % self.id) @@ -100,26 +103,31 @@ def set_debug(enabled): api.libsoc_set_debug(v) def set_high(self): + assert self._gpio is not None assert self.direction == DIRECTION_OUTPUT api.libsoc_gpio_set_level(self._gpio, 1) def set_low(self): + assert self._gpio is not None assert self.direction == DIRECTION_OUTPUT api.libsoc_gpio_set_level(self._gpio, 0) def is_high(self): + assert self._gpio is not None l = api.libsoc_gpio_get_level(self._gpio) if l == -1: raise IOError('Error reading GPIO_%d level' % self.id) return l == 1 def wait_for_interrupt(self, timeout): + assert self._gpio is not None assert self.direction == DIRECTION_INPUT if api.libsoc_gpio_wait_interrupt(self._gpio, timeout) != 0: raise IOError('Error waiting for interrupt on GPIO_%d' % self.id) def get_edge(self): '''Return the edge the GPIO is configured with.''' + assert self._gpio is not None assert self.direction == DIRECTION_INPUT e = api.libsoc_gpio_get_edge(self._gpio) if e == -1: @@ -132,6 +140,7 @@ def poll(self, timeout_ms=-1): polling. Returns True if an interrupt occurred, False on an error or timeout ''' + assert self._gpio is not None return api.libsoc_gpio_poll(self._gpio, timeout_ms) == 0 def start_interrupt_handler(self, interrupt_callback): @@ -139,6 +148,7 @@ def start_interrupt_handler(self, interrupt_callback): encountered, the interrupt_callback function will be run. This thread can be stopped by calling interrupt_handler.stop() ''' + assert self._gpio is not None ih = InterruptHandler(self, interrupt_callback) ih.start() while not ih.running: diff --git a/lib/gpio.c b/lib/gpio.c index 26891f0..c578558 100644 --- a/lib/gpio.c +++ b/lib/gpio.c @@ -409,6 +409,12 @@ libsoc_gpio_poll (gpio * gpio, int timeout) char c; // do an initial read to clear interrupt, + if (gpio == NULL) + { + libsoc_gpio_debug (__func__, -1, "invalid gpio pointer"); + return LS_INT_ERROR; + } + rc = lseek(gpio->value_fd, 0, SEEK_SET); rc = read(gpio->value_fd, &c, 1); From 75f7109807418c06a262ceb428ec5964f18a5401 Mon Sep 17 00:00:00 2001 From: John Comeau Date: Sat, 8 Jul 2017 16:17:42 -0700 Subject: [PATCH 06/60] [[ is a bashism --- test/test_configure.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/test_configure.sh b/test/test_configure.sh index 473628d..fe09ef0 100755 --- a/test/test_configure.sh +++ b/test/test_configure.sh @@ -1,4 +1,4 @@ -#! /bin/sh -e +#! /bin/bash -e python2=1 python3=1 From 92d699fbaaa99d1aaa815d46919a88643ebecef3 Mon Sep 17 00:00:00 2001 From: John Comeau Date: Sat, 8 Jul 2017 23:15:16 -0700 Subject: [PATCH 07/60] ln on older BBB doesn't have `r` option --- contrib/board_files/Makefile.am | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contrib/board_files/Makefile.am b/contrib/board_files/Makefile.am index b28d6e2..dc5df5b 100644 --- a/contrib/board_files/Makefile.am +++ b/contrib/board_files/Makefile.am @@ -10,7 +10,7 @@ installdirs-local: install -d $(DESTDIR)$(sysconfdir) install-data-hook: installdirs-local - ln -srf $(DESTDIR)$(pkgdatadir)/@board@.conf $(DESTDIR)$(sysconfdir)/libsoc.conf + ln -srf $(DESTDIR)$(pkgdatadir)/@board@.conf $(DESTDIR)$(sysconfdir)/libsoc.conf || ln -sf $(DESTDIR)$(pkgdatadir)/@board@.conf $(DESTDIR)$(sysconfdir)/libsoc.conf endif uninstall-local: From 8064be91d3b5b10eae436c2d62b3406e5c9060f0 Mon Sep 17 00:00:00 2001 From: John Comeau Date: Sun, 9 Jul 2017 23:01:43 -0700 Subject: [PATCH 08/60] more consistent indentation --- lib/gpio.c | 56 +++++++++++++++++++++++++++--------------------------- lib/i2c.c | 14 +++++++------- lib/pwm.c | 53 +++++++++++++++++++++++++-------------------------- 3 files changed, 61 insertions(+), 62 deletions(-) diff --git a/lib/gpio.c b/lib/gpio.c index c578558..54a070b 100644 --- a/lib/gpio.c +++ b/lib/gpio.c @@ -34,13 +34,13 @@ libsoc_gpio_debug (const char *func, int gpio, char *format, ...) va_end (args); if (gpio >= 0) - { - fprintf (stderr, " (%d, %s)", gpio, func); - } + { + fprintf (stderr, " (%d, %s)", gpio, func); + } else - { - fprintf (stderr, " (NULL, %s)", func); - } + { + fprintf (stderr, " (NULL, %s)", func); + } fprintf (stderr, "\n"); } @@ -57,8 +57,8 @@ libsoc_gpio_request (unsigned int gpio_id, gpio_mode mode) if (mode != LS_GPIO_SHARED && mode != LS_GPIO_GREEDY && mode != LS_GPIO_WEAK) { libsoc_gpio_debug (__func__, gpio_id, - "mode was not set, or invalid," - " setting mode to LS_GPIO_SHARED"); + "mode was not set, or invalid," + " setting mode to LS_GPIO_SHARED"); mode = LS_GPIO_SHARED; } @@ -71,30 +71,30 @@ libsoc_gpio_request (unsigned int gpio_id, gpio_mode mode) libsoc_gpio_debug (__func__, gpio_id, "GPIO already exported"); switch (mode) - { - case LS_GPIO_WEAK: - { - return NULL; - } - - case LS_GPIO_SHARED: - { - shared = 1; - break; - } - - default: - { - break; - } - } + { + case LS_GPIO_WEAK: + { + return NULL; + } + + case LS_GPIO_SHARED: + { + shared = 1; + break; + } + + default: + { + break; + } + } } else { int fd = file_open ("/sys/class/gpio/export", O_SYNC | O_WRONLY); if (fd < 0) - return NULL; + return NULL; sprintf (tmp_str, "%d", gpio_id); @@ -210,8 +210,8 @@ libsoc_gpio_set_direction (gpio * current_gpio, gpio_direction direction) } libsoc_gpio_debug (__func__, current_gpio->gpio, - "setting direction to %s", - gpio_direction_strings[direction]); + "setting direction to %s", + gpio_direction_strings[direction]); sprintf (path, "/sys/class/gpio/gpio%d/direction", current_gpio->gpio); diff --git a/lib/i2c.c b/lib/i2c.c index ad11743..73dc1a3 100644 --- a/lib/i2c.c +++ b/lib/i2c.c @@ -27,14 +27,14 @@ libsoc_i2c_debug (const char *func, i2c * i2c, char *format, ...) va_end (args); if (i2c == NULL) - { - fprintf (stderr, " (NULL, %s)", func); - } + { + fprintf (stderr, " (NULL, %s)", func); + } else - { - fprintf (stderr, " (i2c-%d, %d, %s)", i2c->bus, - i2c->address, func); - } + { + fprintf (stderr, " (i2c-%d, %d, %s)", i2c->bus, + i2c->address, func); + } fprintf (stderr, "\n"); } diff --git a/lib/pwm.c b/lib/pwm.c index 94a20d9..8f03b20 100644 --- a/lib/pwm.c +++ b/lib/pwm.c @@ -29,7 +29,7 @@ void libsoc_pwm_debug (const char *func, unsigned int chip, vfprintf (stderr, format, args); va_end (args); - fprintf (stderr, " ((%d,%d), %s)", chip, pwm, func); + fprintf (stderr, " ((%d,%d), %s)", chip, pwm, func); fprintf (stderr, "\n"); } @@ -46,7 +46,7 @@ pwm* libsoc_pwm_request (unsigned int chip, unsigned int pwm_num, if (mode != LS_PWM_SHARED && mode != LS_PWM_GREEDY && mode != LS_PWM_WEAK) { libsoc_pwm_debug (__func__, chip, pwm_num, - "mode was not set, or invalid, setting mode to LS_PWM_SHARED"); + "mode was not set, or invalid, setting mode to LS_PWM_SHARED"); mode = LS_PWM_SHARED; } @@ -60,23 +60,23 @@ pwm* libsoc_pwm_request (unsigned int chip, unsigned int pwm_num, libsoc_pwm_debug(__func__, chip, pwm_num, "PWM already exported"); switch(mode) - { - case LS_PWM_WEAK: - { - return NULL; - } - - case LS_PWM_SHARED: - { - shared = 1; - break; - } - - default: - { - break; - } - } + { + case LS_PWM_WEAK: + { + return NULL; + } + + case LS_PWM_SHARED: + { + shared = 1; + break; + } + + default: + { + break; + } + } } else { @@ -91,13 +91,12 @@ pwm* libsoc_pwm_request (unsigned int chip, unsigned int pwm_num, sprintf(tmp_str, "/sys/class/pwm/pwmchip%d/pwm%d/enable", chip, pwm_num); if (!file_valid(tmp_str)) - { - libsoc_pwm_debug(__func__, chip, pwm_num, - "failed to export PWM"); + { + libsoc_pwm_debug(__func__, chip, pwm_num, "failed to export PWM"); perror("libsoc-pwm-debug"); - return NULL; - } + return NULL; + } } new_pwm = malloc(sizeof(pwm)); @@ -114,7 +113,8 @@ pwm* libsoc_pwm_request (unsigned int chip, unsigned int pwm_num, if (new_pwm->enable_fd < 0 || new_pwm->period_fd < 0 || new_pwm->duty_fd < 0) { free(new_pwm); - libsoc_pwm_debug(__func__, chip, pwm_num, "Failed to open pwm sysfs file: %d", new_pwm->enable_fd); + libsoc_pwm_debug(__func__, chip, pwm_num, + "Failed to open pwm sysfs file: %d", new_pwm->enable_fd); return NULL; } @@ -215,8 +215,7 @@ pwm_enabled libsoc_pwm_get_enabled(pwm *pwm) if(val == 1) { - libsoc_pwm_debug(__func__, pwm->chip, pwm->pwm, - "read as enabled"); + libsoc_pwm_debug(__func__, pwm->chip, pwm->pwm, "read as enabled"); return ENABLED; } else if (val == 0) From ea88f7570e4cde21593db457c012bad02b760df1 Mon Sep 17 00:00:00 2001 From: John Comeau Date: Sun, 9 Jul 2017 23:09:49 -0700 Subject: [PATCH 09/60] finished indentation for lib/ --- lib/board.c | 31 ++++++++++++++++--------------- lib/conffile.c | 2 +- lib/gpio.c | 34 +++++++++++++++++----------------- 3 files changed, 34 insertions(+), 33 deletions(-) diff --git a/lib/board.c b/lib/board.c index 75d1072..c423950 100644 --- a/lib/board.c +++ b/lib/board.c @@ -28,8 +28,8 @@ _probe_config(conffile *conf) if (probed) { int rc = strcmp(probed, match); - free(probed); - return !rc; + free(probed); + return !rc; } } else @@ -58,22 +58,23 @@ _probe() char *ext = strrchr(dp->d_name, '.'); if (ext && !strcmp(ext, ".conf")) { - strcpy(tmp, confs_dir); - strcat(tmp, "/"); - strcat(tmp, dp->d_name); - conf = conffile_load(tmp); - if (conf) - { - libsoc_debug(__func__, "probing %s for board support", tmp); + strcpy(tmp, confs_dir); + strcat(tmp, "/"); + strcat(tmp, dp->d_name); + conf = conffile_load(tmp); + if (conf) + { + libsoc_debug(__func__, + "probing %s for board support", tmp); if(_probe_config(conf)) - { - libsoc_debug(__func__, "probing match for %s", tmp); + { + libsoc_debug(__func__, "probing match for %s", tmp); bc = calloc(1, sizeof(board_config)); bc->conf = conf; - } - else - conffile_free(conf); - } + } + else + conffile_free(conf); + } } } } while (dp != NULL && bc == NULL); diff --git a/lib/conffile.c b/lib/conffile.c index f3b31b2..77348a4 100644 --- a/lib/conffile.c +++ b/lib/conffile.c @@ -55,7 +55,7 @@ conffile_load(const char *path) while(fgets(line, sizeof(line), fp)) { if (*line == '#' || *line == '\0' || *line == '\n') - continue; + continue; if (line[0] == '[') { // new section diff --git a/lib/gpio.c b/lib/gpio.c index 54a070b..fae9da8 100644 --- a/lib/gpio.c +++ b/lib/gpio.c @@ -99,20 +99,20 @@ libsoc_gpio_request (unsigned int gpio_id, gpio_mode mode) sprintf (tmp_str, "%d", gpio_id); if (file_write (fd, tmp_str, STR_BUF) < 0) - return NULL; + return NULL; if (file_close (fd)) - return NULL; + return NULL; sprintf (tmp_str, "/sys/class/gpio/gpio%d", gpio_id); if (!file_valid (tmp_str)) - { - libsoc_gpio_debug (__func__, gpio_id, - "gpio did not export correctly"); - perror ("libsoc-gpio-debug"); - return NULL; - } + { + libsoc_gpio_debug (__func__, gpio_id, + "gpio did not export correctly"); + perror ("libsoc-gpio-debug"); + return NULL; + } } new_gpio = malloc (sizeof (gpio)); @@ -259,13 +259,13 @@ libsoc_gpio_get_direction (gpio * current_gpio) if (strncmp (tmp_str, "in", 2) <= 0) { libsoc_gpio_debug (__func__, current_gpio->gpio, - "read direction as input"); + "read direction as input"); return INPUT; } else { libsoc_gpio_debug (__func__, current_gpio->gpio, - "read direction as output"); + "read direction as output"); return OUTPUT; } } @@ -280,7 +280,7 @@ libsoc_gpio_set_level (gpio * current_gpio, gpio_level level) } libsoc_gpio_debug (__func__, current_gpio->gpio, "setting level to %d", - level); + level); if (file_write (current_gpio->value_fd, gpio_level_strings[level], 1) < 0) return EXIT_FAILURE; @@ -333,7 +333,7 @@ libsoc_gpio_set_edge (gpio * current_gpio, gpio_edge edge) } libsoc_gpio_debug (__func__, current_gpio->gpio, "setting edge to %s", - gpio_edge_strings[edge]); + gpio_edge_strings[edge]); sprintf (path, "/sys/class/gpio/gpio%d/edge", current_gpio->gpio); @@ -386,13 +386,13 @@ libsoc_gpio_get_edge (gpio * current_gpio) else if (strncmp (tmp_str, "f", 1) == 0) { libsoc_gpio_debug (__func__, current_gpio->gpio, - "read edge as falling"); + "read edge as falling"); return FALLING; } else if (strncmp (tmp_str, "b", 1) == 0) { libsoc_gpio_debug (__func__, current_gpio->gpio, - "read edge as both"); + "read edge as both"); return BOTH; } else @@ -454,7 +454,7 @@ libsoc_gpio_wait_interrupt (gpio * gpio, int timeout) if (test_edge == EDGE_ERROR || test_edge == NONE) { libsoc_gpio_debug (__func__, gpio->gpio, - "edge must be FALLING, RISING or BOTH"); + "edge must be FALLING, RISING or BOTH"); return LS_INT_ERROR; } @@ -480,7 +480,7 @@ __libsoc_new_interrupt_callback_thread (void *void_gpio) int libsoc_gpio_callback_interrupt (gpio * gpio, int (*callback_fn) (void *), - void *arg) + void *arg) { pthread_t *poll_thread = malloc (sizeof (pthread_t)); pthread_attr_t pthread_attr; @@ -504,7 +504,7 @@ libsoc_gpio_callback_interrupt (gpio * gpio, int (*callback_fn) (void *), pthread_mutex_lock(&new_gpio_callback->ready); int ret = pthread_create (poll_thread, NULL, - __libsoc_new_interrupt_callback_thread, gpio); + __libsoc_new_interrupt_callback_thread, gpio); if (ret == 0) { From 497d3948bf4fa8543c5aa42cd9109b476a6d3a02 Mon Sep 17 00:00:00 2001 From: John Comeau Date: Tue, 11 Jul 2017 14:59:27 -0700 Subject: [PATCH 10/60] added more pins that can only be used with device overlays --- contrib/board_files/beaglebone_black.conf | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/contrib/board_files/beaglebone_black.conf b/contrib/board_files/beaglebone_black.conf index 4c15de1..3d7308b 100644 --- a/contrib/board_files/beaglebone_black.conf +++ b/contrib/board_files/beaglebone_black.conf @@ -72,3 +72,18 @@ P8_44 = 73 P8_45 = 70 P8_46 = 71 +# https://github.com/CircuitCo/BeagleBone-Black/blob/rev_b/BBB_SRM.pdf +# calculate GPIO IDs from GPIOn_mm (e.g. GPIO1_21) as (n * 32) + mm + +GPIO1_21 = 53 +LED_USR0 = 53 +GPIO1_22 = 54 +LED_USR1 = 54 +GPIO1_23 = 55 +LED_USR2 = 55 +GPIO1_24 = 56 +LED_USR3 = 56 +GPIO2_8 = 72 +LCD_DATA2 = 72 +BOOT_BUTTON = 72 +S2 = 72 From 8c33c954f933e82eaade7556c1204dce54cb6bf0 Mon Sep 17 00:00:00 2001 From: John Comeau Date: Thu, 13 Jul 2017 16:16:49 -0700 Subject: [PATCH 11/60] about to test __enter__ and __exit__ --- bindings/python/gpio.py | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/bindings/python/gpio.py b/bindings/python/gpio.py index ffbe3df..a416ef0 100644 --- a/bindings/python/gpio.py +++ b/bindings/python/gpio.py @@ -2,6 +2,7 @@ import contextlib import threading import time +import logging from ._libsoc import ( DIRECTION_INPUT, DIRECTION_OUTPUT, @@ -57,12 +58,25 @@ def open(self): raise IOError('Unable to open GPIO_%d' % self.id) self.set_direction(self.direction, self.edge) + def __enter__(self): + ''' + Allows `with` statement to open the GPIO + ''' + self.open() + return self + def close(self): '''Cleans up the memory and resources allocated by the open method.''' if self._gpio: api.libsoc_gpio_free(self._gpio) self._gpio = None + def __exit__(self, *exception): + ''' + Called automatically at end of `with` block + ''' + self.close() + def set_direction(self, direction, edge): assert self._gpio is not None self._validate_direction(direction, edge) From fc639348f0f6a0613995189b82264866625b18a1 Mon Sep 17 00:00:00 2001 From: John Comeau Date: Thu, 13 Jul 2017 18:15:37 -0700 Subject: [PATCH 12/60] possibly dodgy changes to operation, should *not* affect current code and may or may not be useful going forward. due to the way my development is set up, I need to commit in order to test. --- bindings/python/gpio.py | 35 ++++++++++++++++++++++------------- 1 file changed, 22 insertions(+), 13 deletions(-) diff --git a/bindings/python/gpio.py b/bindings/python/gpio.py index a416ef0..ed97877 100644 --- a/bindings/python/gpio.py +++ b/bindings/python/gpio.py @@ -12,8 +12,12 @@ class InterruptHandler(threading.Thread): - def __init__(self, gpio, interrupt_callback): - super(InterruptHandler, self).__init__() + def __init__(self, gpio, interrupt_callback, **kwargs): + ''' + Some of the kwargs you might want to supply are `name`, `args` + (to be passed to the handler) and `kwargs` (also for the handler) + ''' + super(InterruptHandler, self).__init__(**kwargs) self.gpio = gpio self.isr_cb = interrupt_callback self.running = False @@ -22,10 +26,11 @@ def run(self): self.running = True while self.running: if self.gpio.poll(1000): - self.isr_cb() + self.isr_cb(*self.args, **self.kwargs) def stop(self): self.running = False + self.gpio.handler = None class GPIO(object): @@ -40,6 +45,7 @@ def __init__(self, id, direction, edge=EDGE_NONE, mode=LS_GPIO_SHARED): self._validate_direction(direction, edge) self.mode = mode self._gpio = None + self.handler = None def _validate_direction(self, direction, edge=EDGE_NONE): if direction not in (DIRECTION_INPUT, DIRECTION_OUTPUT): @@ -157,18 +163,21 @@ def poll(self, timeout_ms=-1): assert self._gpio is not None return api.libsoc_gpio_poll(self._gpio, timeout_ms) == 0 - def start_interrupt_handler(self, interrupt_callback): - '''Returns a thread that continuosly polls the GPIO. If an interrupt is - encountered, the interrupt_callback function will be run. This - thread can be stopped by calling interrupt_handler.stop() + def start_interrupt_handler(self, interrupt_callback, **kwargs): ''' - assert self._gpio is not None - ih = InterruptHandler(self, interrupt_callback) - ih.start() - while not ih.running: - time.sleep(0.01) - return ih + Returns a thread that continuosly polls the GPIO. If an interrupt is + encountered, the interrupt_callback function will be run. This + thread can be stopped by calling interrupt_handler.stop() + The handler points to the GPIO and vice versa, so that the handler + thread can easily access its state. + ''' + assert self._gpio is not None + self.handler = InterruptHandler(self, interrupt_callback, **kwargs) + self.handler.start() + while not self.handler.running: + time.sleep(0.001) + return self.handler @contextlib.contextmanager def request_gpios(gpios): From c73d8917dd3f6d8a14fc5a8534c7726dccad352a Mon Sep 17 00:00:00 2001 From: John Comeau Date: Thu, 13 Jul 2017 18:47:23 -0700 Subject: [PATCH 13/60] using threading.Thread internals. sloppy, but should work for now. --- bindings/python/gpio.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bindings/python/gpio.py b/bindings/python/gpio.py index ed97877..c1f5062 100644 --- a/bindings/python/gpio.py +++ b/bindings/python/gpio.py @@ -26,7 +26,7 @@ def run(self): self.running = True while self.running: if self.gpio.poll(1000): - self.isr_cb(*self.args, **self.kwargs) + self.isr_cb(*self.__args, **self.__kwargs) # from Thread def stop(self): self.running = False From db9c0b56277c6c808fb7455b0b432125c2a8f5dc Mon Sep 17 00:00:00 2001 From: John Comeau Date: Thu, 13 Jul 2017 18:53:08 -0700 Subject: [PATCH 14/60] last try didn't work: AttributeError: 'InterruptHandler' object has no attribute '_InterruptHandler__args' --- bindings/python/gpio.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/bindings/python/gpio.py b/bindings/python/gpio.py index c1f5062..3670a89 100644 --- a/bindings/python/gpio.py +++ b/bindings/python/gpio.py @@ -21,12 +21,14 @@ def __init__(self, gpio, interrupt_callback, **kwargs): self.gpio = gpio self.isr_cb = interrupt_callback self.running = False + self.callback_args = kwargs.get('args') or (,) + self.callback_kwargs = kwargs.get('kwargs') or {} def run(self): self.running = True while self.running: if self.gpio.poll(1000): - self.isr_cb(*self.__args, **self.__kwargs) # from Thread + self.isr_cb(*self.callback_args, **self.callback_kwargs) def stop(self): self.running = False From 2dfbe0c9c22d687aa6ce242ff5f26991a3e8018f Mon Sep 17 00:00:00 2001 From: John Comeau Date: Thu, 13 Jul 2017 18:54:25 -0700 Subject: [PATCH 15/60] ugh. empty tuple. --- bindings/python/gpio.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bindings/python/gpio.py b/bindings/python/gpio.py index 3670a89..8a5bb33 100644 --- a/bindings/python/gpio.py +++ b/bindings/python/gpio.py @@ -21,7 +21,7 @@ def __init__(self, gpio, interrupt_callback, **kwargs): self.gpio = gpio self.isr_cb = interrupt_callback self.running = False - self.callback_args = kwargs.get('args') or (,) + self.callback_args = kwargs.get('args') or () self.callback_kwargs = kwargs.get('kwargs') or {} def run(self): From 600ae4ff01ec555262fbf9dd82adf9fba371a269 Mon Sep 17 00:00:00 2001 From: John Comeau Date: Fri, 14 Jul 2017 02:04:23 -0700 Subject: [PATCH 16/60] doesn't work yet --- test/switched_led.py | 74 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 74 insertions(+) create mode 100644 test/switched_led.py diff --git a/test/switched_led.py b/test/switched_led.py new file mode 100644 index 0000000..79ebe0f --- /dev/null +++ b/test/switched_led.py @@ -0,0 +1,74 @@ +#!/usr/bin/python -OO +''' +Switched LED test, using interrupts on inputs and driving outputs. + +Assumes switches are pulled low when pressed, and output must be +high to drive LED. + +The default values are for the ARTIK 710 developer board, with mapping +from https://developer.artik.io/documentation/developer-guide/gpio/ +gpio-mapping.html. + +Device Sysfs mapping Note + +SW403 GPIO 30 Nearest board edge, next to red LED400 +SW404 GPIO 32 Next to blue LED401 +LED400 GPIO 28 Red LED +LED401 GPIO 38 Blue LED +''' +import sys +import logging +from libsoc import gpio +# run as `python switched_led.py` for verbose logging +logging.basicConfig(level=logging.DEBUG if __debug__ else logging.INFO) +PAIRS = {} # switch-LED pairs +NAMES = { # edit for your board, or set to empty dict + 30: 'SW403', + 32: 'SW404', + 28: 'LED400', + 38: 'LED401', +} + +def switchtest(*gpios): + ''' + Run the switched LED test with given GPIO numbers. + ''' + switches = gpios[::2] + leds = gpios[1::2] + for switch, led in zip(switches, leds): + switch_signal = gpio.GPIO( + switch, gpio.DIRECTION_INPUT, gpio.EDGE_BOTH) + led_signal = gpio.GPIO(led, gpio.DIRECTION_OUTPUT) + led_signal.set_low() # start with all LEDs off + PAIRS[switch_signal] = led_signal + # now the pairs are established, we can enable interrupts + try: + with gpio.request_gpios([g.id for g in PAIRS.keys() + PAIRS.values()]): + for switch_signal in PAIRS: + switch_signal.start_interrupt_handler( + activator, args=(switch_signal,)) + logging.info('Push a switch to see its LED light; ' + 'Control-C to exit.') + except KeyboardInterrupt: + sys.exit + +def activator(signal): + ''' + Called when a switch transitions to high or low. + + We turn LED on or off depending on whether the switch is down or up. + ''' + logging.debug('Switch %d activated', NAMES.get(signal.id, signal.id)) + if signal.is_low(): + PAIRS[signal].set_high() + else: + PAIRS[signal].set_low() + +if __name__ == '__main__': + gpios = map(int, sys.argv[1:]) or [30, 28, 32, 38] + logging.debug('GPIOs: %s', gpios) + if len(gpios) % 2 == 0: + switchtest(gpios) + else: + logging.fatal('Must specify GPIOs of each switch followed by its LED') + From fab2905ea2d28ea4e147decbc6858bbc5ebd2c9b Mon Sep 17 00:00:00 2001 From: John Comeau Date: Fri, 14 Jul 2017 02:06:39 -0700 Subject: [PATCH 17/60] still doesn't work but at least keeps going until ^C --- test/switched_led.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/test/switched_led.py b/test/switched_led.py index 79ebe0f..d157c4b 100644 --- a/test/switched_led.py +++ b/test/switched_led.py @@ -17,6 +17,7 @@ LED401 GPIO 38 Blue LED ''' import sys +import time import logging from libsoc import gpio # run as `python switched_led.py` for verbose logging @@ -49,6 +50,8 @@ def switchtest(*gpios): activator, args=(switch_signal,)) logging.info('Push a switch to see its LED light; ' 'Control-C to exit.') + while True: + time.sleep(60) # wait until user gets bored except KeyboardInterrupt: sys.exit From dfdf00258fc347f116b2b9b92af8f7961edc30a7 Mon Sep 17 00:00:00 2001 From: John Comeau Date: Fri, 14 Jul 2017 02:14:54 -0700 Subject: [PATCH 18/60] AttributeError: 'GPIO' object has no attribute 'is_low' --- test/switched_led.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/test/switched_led.py b/test/switched_led.py index d157c4b..0247337 100644 --- a/test/switched_led.py +++ b/test/switched_led.py @@ -30,7 +30,7 @@ 38: 'LED401', } -def switchtest(*gpios): +def switchtest(gpios): ''' Run the switched LED test with given GPIO numbers. ''' @@ -40,11 +40,13 @@ def switchtest(*gpios): switch_signal = gpio.GPIO( switch, gpio.DIRECTION_INPUT, gpio.EDGE_BOTH) led_signal = gpio.GPIO(led, gpio.DIRECTION_OUTPUT) - led_signal.set_low() # start with all LEDs off + with led_signal as signal: + signal.set_low() # start with all LEDs off PAIRS[switch_signal] = led_signal # now the pairs are established, we can enable interrupts + logging.debug('PAIRS: %s', PAIRS) try: - with gpio.request_gpios([g.id for g in PAIRS.keys() + PAIRS.values()]): + with gpio.request_gpios(PAIRS.keys() + PAIRS.values()): for switch_signal in PAIRS: switch_signal.start_interrupt_handler( activator, args=(switch_signal,)) From aa7a716c95c21dd8089dd2ce7d36dea1b8d0cffc Mon Sep 17 00:00:00 2001 From: John Comeau Date: Fri, 14 Jul 2017 02:25:29 -0700 Subject: [PATCH 19/60] works but ^C just hangs with optimization --- test/switched_led.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/test/switched_led.py b/test/switched_led.py index 0247337..95f1574 100644 --- a/test/switched_led.py +++ b/test/switched_led.py @@ -63,11 +63,11 @@ def activator(signal): We turn LED on or off depending on whether the switch is down or up. ''' - logging.debug('Switch %d activated', NAMES.get(signal.id, signal.id)) - if signal.is_low(): - PAIRS[signal].set_high() - else: + logging.debug('Switch %s activated', NAMES.get(signal.id, signal.id)) + if signal.is_high(): PAIRS[signal].set_low() + else: + PAIRS[signal].set_high() if __name__ == '__main__': gpios = map(int, sys.argv[1:]) or [30, 28, 32, 38] From 89ea02e40e6a21b0223d0e9f6cd31198b63d3c87 Mon Sep 17 00:00:00 2001 From: John Comeau Date: Fri, 14 Jul 2017 02:39:03 -0700 Subject: [PATCH 20/60] finally works --- test/switched_led.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/test/switched_led.py b/test/switched_led.py index 95f1574..500d826 100644 --- a/test/switched_led.py +++ b/test/switched_led.py @@ -54,8 +54,10 @@ def switchtest(gpios): 'Control-C to exit.') while True: time.sleep(60) # wait until user gets bored - except KeyboardInterrupt: - sys.exit + except (KeyboardInterrupt, SystemExit): + logging.info('It may take a few seconds for handlers to stop.') + for switch in PAIRS: + switch.handler.stop() def activator(signal): ''' From 770a8362d5ef6e878544a37f52d9d29e0a2b41c1 Mon Sep 17 00:00:00 2001 From: John Comeau Date: Thu, 20 Jul 2017 07:10:25 -0700 Subject: [PATCH 21/60] about to test adc, copied from pwm sources and modified --- lib/Makefile.am | 17 +++--- lib/adc.c | 112 +++++++++++++++++++++++++++++++++++++++ lib/include/libsoc_adc.h | 59 +++++++++++++++++++++ test/switched_led.py | 0 4 files changed, 181 insertions(+), 7 deletions(-) create mode 100644 lib/adc.c create mode 100644 lib/include/libsoc_adc.h mode change 100644 => 100755 test/switched_led.py diff --git a/lib/Makefile.am b/lib/Makefile.am index 83020b2..5411d8a 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am @@ -3,18 +3,20 @@ include_HEADERS = include/libsoc_gpio.h \ include/libsoc_spi.h \ include/libsoc_i2c.h \ include/libsoc_pwm.h \ + include/libsoc_adc.h \ include/libsoc_board.h \ include/libsoc_conffile.h \ include/libsoc_debug.h libsoc_la_SOURCES = gpio.c \ - spi.c \ - file.c \ - i2c.c \ - pwm.c \ - board.c \ - conffile.c \ - debug.c + spi.c \ + file.c \ + i2c.c \ + pwm.c \ + adc.c \ + board.c \ + conffile.c \ + debug.c libsoc_la_CPPFLAGS = -I${top_srcdir}/lib/include @@ -22,3 +24,4 @@ libsoc_la_CPPFLAGS = -I${top_srcdir}/lib/include libsoc_la_LDFLAGS = -version-info 6:2:4 AM_CFLAGS = -DDATA_DIR=\"$(DESTDIR)$(pkgdatadir)\" -DLIBSOC_CONF=\"@sysconfdir@/libsoc.conf\" +# vim: tabstop=8 expandtab shiftwidth=2 softtabstop=2 diff --git a/lib/adc.c b/lib/adc.c new file mode 100644 index 0000000..7cc046a --- /dev/null +++ b/lib/adc.c @@ -0,0 +1,112 @@ +#include +#include +#include +#include +#include +#include +#include + +#include "libsoc_file.h" +#include "libsoc_debug.h" +#include "libsoc_adc.h" + +#define STR_BUF 256 + +void libsoc_adc_debug (const char *func, unsigned int chip, + unsigned int adc, char *format, ...) +{ +#ifdef DEBUG + if (libsoc_get_debug ()) + { + va_list args; + + fprintf (stderr, "libsoc-adc-debug: "); + + va_start (args, format); + vfprintf (stderr, format, args); + va_end (args); + + fprintf (stderr, " ((%d,%d), %s)", chip, adc, func); + + fprintf (stderr, "\n"); + } +#endif +} + +adc* libsoc_adc_request (unsigned int chip, unsigned int adc_num); +{ + adc *new_adc; + char chip_str[STR_BUF]; + char adc_str[STR_BUF]; + int i, j; + size_t result; + + libsoc_adc_debug (__func__, chip, adc_num, "requested ADC"); + + for (i = 0; i < sizeof(ADC_DEVICE_FORMAT); i++) + { + result = snprintf(chip_str, STR_BUF, ADC_DEVICE_FORMAT[i], chip); + if (result < 0) + { + perror("Failed formatting chip string"); + return NULL; + } + if (result >= STR_BUF) + { + fprintf(stderr, "Chip format string \"%s\" too long for buffer\n", + ADC_DEVICE_FORMAT[i]); + return NULL; + } + if (file_valid(chip_str)) + { + libsoc_adc_debug(__func__, chip, adc_num, "Found requested chip"); + for (j = 0; j < sizeof(ADC_READ_FORMAT), j++) + { + strncpy(adc_str, chip_str, STR_BUF); + strncpy(adc_str + result, ADC_READ_FORMAT[j], + STR_BUF - strlen(adc_str)); + if (strlen(adc_str) > STR_BUF) + { + perror("Failed formatting device string"); + return NULL; + } + if (file_valid(adc_str)) + { + libsoc_adc_debug(__func__, chip, adc_num, "Found requested ADC pin"); + new_adc = malloc(sizeof(adc)); + new_adc->fd = file_open(adc_str, O_RDONLY); + } + if (new_adc->fd < 0) + { + free(new_pwm); + libsoc_pwm_debug(__func__, chip, adc_num, + "Failed to open adc sysfs file: %d", new_adc->fd); + return NULL; + } + new_adc->chip = chip; + new_adc->adc = adc_num; + return new_adc; + } + } + } +} + +int libsoc_adc_free(adc *adc) +{ + if (adc == NULL) + { + libsoc_adc_debug(__func__, -1, -1, "invalid adc pointer"); + return EXIT_FAILURE; + } + + if (file_close(adc->fd) < 0) + { + return EXIT_FAILURE; + } + + free(adc); + return EXIT_SUCCESS; +} +/* + * vim: tabstop=8 expandtab shiftwidth=2 softtabstop=2 + */ diff --git a/lib/include/libsoc_adc.h b/lib/include/libsoc_adc.h new file mode 100644 index 0000000..0339ce3 --- /dev/null +++ b/lib/include/libsoc_adc.h @@ -0,0 +1,59 @@ +#ifndef _LIBSOC_ADC_H_ +#define _LIBSOC_ADC_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +static const char ADC_DEVICE_FORMAT[][] = { + "/sys/devices/12d10000.adc/iio:device%d", // ARTIK 1020 + "/sys/devices/platform/c0000000.soc/c0053000.adc/iio:device%d", // 710 + "/sys/devices/126c0000.adc/iio:device%d" // ARTIK 520 +}; + +static const char ADC_READ_FORMAT[][] = { + "/in_voltage%d_raw" +}; + +/** + * \struct adc + * \brief representation of a single requested adc + * \param unsigned int adc - adc num + * \param unsigned int adc_chip - adc chip num + * \param int fd - file descriptor to adc file + */ + +typedef struct { + unsigned int chip; + unsigned int adc; + int fd; +} adc; + +/** + * \fn adc* libsoc_adc_request(unsigned int adc_chip, unsigned int adc_num) + * \brief request an adc to use + * \param unsigned int adc_chip - the chip number that controls the adc you + wish to use + * \param unsigned int adc_num - the adc number number within your adc chip + * \return pointer to adc* on success NULL on fail + * + */ + +adc* libsoc_adc_request(unsigned int adc_chip, unsigned int adc_num); + +/** + * \fn int libsoc_adc_free(adc* adc) + * \brief free a previously requested adc + * \param adc* adc - valid pointer to a requested adc + * \return EXIT_SUCCESS or EXIT_FAILURE + */ + +int libsoc_adc_free(adc *adc); + +#ifdef __cplusplus +} +#endif +#endif +/* + * vim: tabstop=8 expandtab shiftwidth=2 softtabstop=2 + */ diff --git a/test/switched_led.py b/test/switched_led.py old mode 100644 new mode 100755 From 8c405bd83b384e0de50de7e48f6132cd57c697fe Mon Sep 17 00:00:00 2001 From: John Comeau Date: Thu, 20 Jul 2017 07:27:57 -0700 Subject: [PATCH 22/60] fixed buggy code --- lib/adc.c | 14 ++++++++------ lib/include/libsoc_adc.h | 4 ++-- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/lib/adc.c b/lib/adc.c index 7cc046a..9cc531b 100644 --- a/lib/adc.c +++ b/lib/adc.c @@ -33,7 +33,7 @@ void libsoc_adc_debug (const char *func, unsigned int chip, #endif } -adc* libsoc_adc_request (unsigned int chip, unsigned int adc_num); +adc* libsoc_adc_request (unsigned int chip, unsigned int adc_num) { adc *new_adc; char chip_str[STR_BUF]; @@ -60,7 +60,7 @@ adc* libsoc_adc_request (unsigned int chip, unsigned int adc_num); if (file_valid(chip_str)) { libsoc_adc_debug(__func__, chip, adc_num, "Found requested chip"); - for (j = 0; j < sizeof(ADC_READ_FORMAT), j++) + for (j = 0; j < sizeof(ADC_READ_FORMAT); j++) { strncpy(adc_str, chip_str, STR_BUF); strncpy(adc_str + result, ADC_READ_FORMAT[j], @@ -72,15 +72,15 @@ adc* libsoc_adc_request (unsigned int chip, unsigned int adc_num); } if (file_valid(adc_str)) { - libsoc_adc_debug(__func__, chip, adc_num, "Found requested ADC pin"); + libsoc_adc_debug(__func__, chip, adc_num, "Found requested ADC"); new_adc = malloc(sizeof(adc)); new_adc->fd = file_open(adc_str, O_RDONLY); } if (new_adc->fd < 0) { - free(new_pwm); - libsoc_pwm_debug(__func__, chip, adc_num, - "Failed to open adc sysfs file: %d", new_adc->fd); + free(new_adc); + libsoc_adc_debug(__func__, chip, adc_num, + "Failed to open adc sysfs file: %d", new_adc->fd); return NULL; } new_adc->chip = chip; @@ -89,6 +89,8 @@ adc* libsoc_adc_request (unsigned int chip, unsigned int adc_num); } } } + libsoc_adc_debug(__func__, chip, adc_num, "Found no such ADC available"); + return NULL; } int libsoc_adc_free(adc *adc) diff --git a/lib/include/libsoc_adc.h b/lib/include/libsoc_adc.h index 0339ce3..05e7cc9 100644 --- a/lib/include/libsoc_adc.h +++ b/lib/include/libsoc_adc.h @@ -5,13 +5,13 @@ extern "C" { #endif -static const char ADC_DEVICE_FORMAT[][] = { +static const char ADC_DEVICE_FORMAT[][64] = { "/sys/devices/12d10000.adc/iio:device%d", // ARTIK 1020 "/sys/devices/platform/c0000000.soc/c0053000.adc/iio:device%d", // 710 "/sys/devices/126c0000.adc/iio:device%d" // ARTIK 520 }; -static const char ADC_READ_FORMAT[][] = { +static const char ADC_READ_FORMAT[][32] = { "/in_voltage%d_raw" }; From 1446a9bc10a4036de5cb70726e2d107c3bf85b6a Mon Sep 17 00:00:00 2001 From: John Comeau Date: Thu, 20 Jul 2017 08:37:11 -0700 Subject: [PATCH 23/60] untested changes to lib/adc.c and untested testcase --- Makefile | 886 ++++++++++++++++++++++++++++++++++++++++++++++++ lib/adc.c | 18 + test/adc_test.c | 52 +++ 3 files changed, 956 insertions(+) create mode 100644 Makefile create mode 100644 test/adc_test.c diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..4aed3f7 --- /dev/null +++ b/Makefile @@ -0,0 +1,886 @@ +# Makefile.in generated by automake 1.15 from Makefile.am. +# Makefile. Generated from Makefile.in by configure. + +# Copyright (C) 1994-2014 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + + + + +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/libsoc +pkgincludedir = $(includedir)/libsoc +pkglibdir = $(libdir)/libsoc +pkglibexecdir = $(libexecdir)/libsoc +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = x86_64-unknown-linux-gnu +host_triplet = x86_64-unknown-linux-gnu +target_triplet = x86_64-unknown-linux-gnu +am__append_1 = bindings/python +subdir = . +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/config/m4/libtool.m4 \ + $(top_srcdir)/config/m4/ltoptions.m4 \ + $(top_srcdir)/config/m4/ltsugar.m4 \ + $(top_srcdir)/config/m4/ltversion.m4 \ + $(top_srcdir)/config/m4/lt~obsolete.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(top_srcdir)/configure \ + $(am__configure_deps) $(am__DIST_COMMON) +am__CONFIG_DISTCLEAN_FILES = config.status config.cache config.log \ + configure.lineno config.status.lineno +mkinstalldirs = $(install_sh) -d +CONFIG_CLEAN_FILES = libsoc.pc +CONFIG_CLEAN_VPATH_FILES = +AM_V_P = $(am__v_P_$(V)) +am__v_P_ = $(am__v_P_$(AM_DEFAULT_VERBOSITY)) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_$(V)) +am__v_GEN_ = $(am__v_GEN_$(AM_DEFAULT_VERBOSITY)) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_$(V)) +am__v_at_ = $(am__v_at_$(AM_DEFAULT_VERBOSITY)) +am__v_at_0 = @ +am__v_at_1 = +SOURCES = +DIST_SOURCES = +RECURSIVE_TARGETS = all-recursive check-recursive cscopelist-recursive \ + ctags-recursive dvi-recursive html-recursive info-recursive \ + install-data-recursive install-dvi-recursive \ + install-exec-recursive install-html-recursive \ + install-info-recursive install-pdf-recursive \ + install-ps-recursive install-recursive installcheck-recursive \ + installdirs-recursive pdf-recursive ps-recursive \ + tags-recursive uninstall-recursive +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +am__base_list = \ + sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ + sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' +am__uninstall_files_from_dir = { \ + test -z "$$files" \ + || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ + || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ + $(am__cd) "$$dir" && rm -f $$files; }; \ + } +am__installdirs = "$(DESTDIR)$(pkgconfigdir)" +DATA = $(pkgconfig_DATA) +RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ + distclean-recursive maintainer-clean-recursive +am__recursive_targets = \ + $(RECURSIVE_TARGETS) \ + $(RECURSIVE_CLEAN_TARGETS) \ + $(am__extra_recursive_targets) +AM_RECURSIVE_TARGETS = $(am__recursive_targets:-recursive=) TAGS CTAGS \ + cscope distdir dist dist-all distcheck +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +ETAGS = etags +CTAGS = ctags +CSCOPE = cscope +DIST_SUBDIRS = lib contrib/board_files bindings/python +am__DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/libsoc.pc.in \ + $(top_srcdir)/config/autoconf/compile \ + $(top_srcdir)/config/autoconf/config.guess \ + $(top_srcdir)/config/autoconf/config.sub \ + $(top_srcdir)/config/autoconf/install-sh \ + $(top_srcdir)/config/autoconf/ltmain.sh \ + $(top_srcdir)/config/autoconf/missing ChangeLog \ + config/autoconf/compile config/autoconf/config.guess \ + config/autoconf/config.sub config/autoconf/depcomp \ + config/autoconf/install-sh config/autoconf/ltmain.sh \ + config/autoconf/missing config/autoconf/py-compile +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +distdir = $(PACKAGE)-$(VERSION) +top_distdir = $(distdir) +am__remove_distdir = \ + if test -d "$(distdir)"; then \ + find "$(distdir)" -type d ! -perm -200 -exec chmod u+w {} ';' \ + && rm -rf "$(distdir)" \ + || { sleep 5 && rm -rf "$(distdir)"; }; \ + else :; fi +am__post_remove_distdir = $(am__remove_distdir) +am__relativize = \ + dir0=`pwd`; \ + sed_first='s,^\([^/]*\)/.*$$,\1,'; \ + sed_rest='s,^[^/]*/*,,'; \ + sed_last='s,^.*/\([^/]*\)$$,\1,'; \ + sed_butlast='s,/*[^/]*$$,,'; \ + while test -n "$$dir1"; do \ + first=`echo "$$dir1" | sed -e "$$sed_first"`; \ + if test "$$first" != "."; then \ + if test "$$first" = ".."; then \ + dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \ + dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \ + else \ + first2=`echo "$$dir2" | sed -e "$$sed_first"`; \ + if test "$$first2" = "$$first"; then \ + dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \ + else \ + dir2="../$$dir2"; \ + fi; \ + dir0="$$dir0"/"$$first"; \ + fi; \ + fi; \ + dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \ + done; \ + reldir="$$dir2" +DIST_ARCHIVES = $(distdir).tar.gz +GZIP_ENV = --best +DIST_TARGETS = dist-gzip +distuninstallcheck_listfiles = find . -type f -print +am__distuninstallcheck_listfiles = $(distuninstallcheck_listfiles) \ + | sed 's|^\./|$(prefix)/|' | grep -v '$(infodir)/dir$$' +distcleancheck_listfiles = find . -type f -print +ACLOCAL = ${SHELL} /usr/src/libsoc/config/autoconf/missing aclocal-1.15 +AMTAR = $${TAR-tar} +AM_DEFAULT_VERBOSITY = 0 +AR = ar +AUTOCONF = ${SHELL} /usr/src/libsoc/config/autoconf/missing autoconf +AUTOHEADER = ${SHELL} /usr/src/libsoc/config/autoconf/missing autoheader +AUTOMAKE = ${SHELL} /usr/src/libsoc/config/autoconf/missing automake-1.15 +AWK = gawk +CC = gcc +CCDEPMODE = depmode=gcc3 +CFLAGS = -g -O2 +CPP = gcc -E +CPPFLAGS = +CYGPATH_W = echo +DEFS = -DPACKAGE_NAME=\"libsoc\" -DPACKAGE_TARNAME=\"libsoc\" -DPACKAGE_VERSION=\"0.8.2\" -DPACKAGE_STRING=\"libsoc\ 0.8.2\" -DPACKAGE_BUGREPORT=\"\" -DPACKAGE_URL=\"\" -DPACKAGE=\"libsoc\" -DVERSION=\"0.8.2\" -DSTDC_HEADERS=1 -DHAVE_SYS_TYPES_H=1 -DHAVE_SYS_STAT_H=1 -DHAVE_STDLIB_H=1 -DHAVE_STRING_H=1 -DHAVE_MEMORY_H=1 -DHAVE_STRINGS_H=1 -DHAVE_INTTYPES_H=1 -DHAVE_STDINT_H=1 -DHAVE_UNISTD_H=1 -DHAVE_DLFCN_H=1 -DLT_OBJDIR=\".libs/\" -DDEBUG=1 +DEPDIR = .deps +DLLTOOL = false +DSYMUTIL = +DUMPBIN = +ECHO_C = +ECHO_N = -n +ECHO_T = +EGREP = /bin/grep -E +EXEEXT = +FGREP = /bin/grep -F +GREP = /bin/grep +INSTALL = /usr/bin/install -c +INSTALL_DATA = ${INSTALL} -m 644 +INSTALL_PROGRAM = ${INSTALL} +INSTALL_SCRIPT = ${INSTALL} +INSTALL_STRIP_PROGRAM = $(install_sh) -c -s +LD = /usr/bin/ld -m elf_i386 +LDFLAGS = +LIBOBJS = +LIBS = -lpthread +LIBTOOL = $(SHELL) $(top_builddir)/libtool +LIPO = +LN_S = ln -s +LTLIBOBJS = +LT_SYS_LIBRARY_PATH = +MAKEINFO = ${SHELL} /usr/src/libsoc/config/autoconf/missing makeinfo +MANIFEST_TOOL = : +MKDIR_P = /bin/mkdir -p +NM = /usr/bin/nm -B +NMEDIT = +OBJDUMP = objdump +OBJEXT = o +OTOOL = +OTOOL64 = +PACKAGE = libsoc +PACKAGE_BUGREPORT = +PACKAGE_NAME = libsoc +PACKAGE_STRING = libsoc 0.8.2 +PACKAGE_TARNAME = libsoc +PACKAGE_URL = +PACKAGE_VERSION = 0.8.2 +PATH_SEPARATOR = : +PKG_CONFIG = /usr/bin/pkg-config +PKG_CONFIG_LIBDIR = +PKG_CONFIG_PATH = +PYTHON = python2 +PYTHON_CFLAGS = -I/usr/include/python2.7 -I/usr/include/i386-linux-gnu/python2.7 +PYTHON_EXEC_PREFIX = ${exec_prefix} +PYTHON_LIBS = -lpython2.7 +PYTHON_PLATFORM = linux2 +PYTHON_PREFIX = ${prefix} +PYTHON_VERSION = 2.7 +RANLIB = ranlib +SED = /bin/sed +SET_MAKE = +SHELL = /bin/bash +STRIP = strip +VERSION = 0.8.2 +abs_builddir = /usr/src/libsoc +abs_srcdir = /usr/src/libsoc +abs_top_builddir = /usr/src/libsoc +abs_top_srcdir = /usr/src/libsoc +ac_ct_AR = ar +ac_ct_CC = gcc +ac_ct_DUMPBIN = +am__include = include +am__leading_dot = . +am__quote = +am__tar = $${TAR-tar} chof - "$$tardir" +am__untar = $${TAR-tar} xf - +bindir = ${exec_prefix}/bin +board = artik_710 +build = x86_64-unknown-linux-gnu +build_alias = +build_cpu = x86_64 +build_os = linux-gnu +build_vendor = unknown +builddir = . +datadir = ${datarootdir} +datarootdir = ${prefix}/share +docdir = ${datarootdir}/doc/${PACKAGE_TARNAME} +dvidir = ${docdir} +exec_prefix = ${prefix} +host = x86_64-unknown-linux-gnu +host_alias = +host_cpu = x86_64 +host_os = linux-gnu +host_vendor = unknown +htmldir = ${docdir} +includedir = ${prefix}/include +infodir = ${datarootdir}/info +install_sh = ${SHELL} /usr/src/libsoc/config/autoconf/install-sh +libdir = ${exec_prefix}/lib +libexecdir = ${exec_prefix}/libexec +localedir = ${datarootdir}/locale +localstatedir = ${prefix}/var +mandir = ${datarootdir}/man +mkdir_p = $(MKDIR_P) +oldincludedir = /usr/include +pdfdir = ${docdir} +pkgpyexecdir = ${pyexecdir}/libsoc +pkgpythondir = ${pythondir}/libsoc +prefix = /usr/local +program_transform_name = s,x,x, +psdir = ${docdir} +pyexecdir = ${exec_prefix}/lib/python2.7/dist-packages +pythondir = ${prefix}/lib/python2.7/dist-packages +runstatedir = ${localstatedir}/run +sbindir = ${exec_prefix}/sbin +sharedstatedir = ${prefix}/com +srcdir = . +sysconfdir = ${prefix}/etc +target = x86_64-unknown-linux-gnu +target_alias = +target_cpu = x86_64 +target_os = linux-gnu +target_vendor = unknown +top_build_prefix = +top_builddir = . +top_srcdir = . +ACLOCAL_AMFLAGS = -I config/m4 +AUTOMAKE_OPTIONS = subdir-objects +pkgconfigdir = $(libdir)/pkgconfig +pkgconfig_DATA = libsoc.pc +EXTRA_DIST = libsoc.pc.in +CLEANFILES = libsoc.pc +SUBDIRS = lib contrib/board_files $(am__append_1) +all: all-recursive + +.SUFFIXES: +am--refresh: Makefile + @: +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + echo ' cd $(srcdir) && $(AUTOMAKE) --foreign'; \ + $(am__cd) $(srcdir) && $(AUTOMAKE) --foreign \ + && exit 0; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + echo ' $(SHELL) ./config.status'; \ + $(SHELL) ./config.status;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + $(SHELL) ./config.status --recheck + +$(top_srcdir)/configure: $(am__configure_deps) + $(am__cd) $(srcdir) && $(AUTOCONF) +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + $(am__cd) $(srcdir) && $(ACLOCAL) $(ACLOCAL_AMFLAGS) +$(am__aclocal_m4_deps): +libsoc.pc: $(top_builddir)/config.status $(srcdir)/libsoc.pc.in + cd $(top_builddir) && $(SHELL) ./config.status $@ + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +distclean-libtool: + -rm -f libtool config.lt +install-pkgconfigDATA: $(pkgconfig_DATA) + @$(NORMAL_INSTALL) + @list='$(pkgconfig_DATA)'; test -n "$(pkgconfigdir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(pkgconfigdir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(pkgconfigdir)" || exit 1; \ + fi; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(pkgconfigdir)'"; \ + $(INSTALL_DATA) $$files "$(DESTDIR)$(pkgconfigdir)" || exit $$?; \ + done + +uninstall-pkgconfigDATA: + @$(NORMAL_UNINSTALL) + @list='$(pkgconfig_DATA)'; test -n "$(pkgconfigdir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + dir='$(DESTDIR)$(pkgconfigdir)'; $(am__uninstall_files_from_dir) + +# This directory's subdirectories are mostly independent; you can cd +# into them and run 'make' without going through this Makefile. +# To change the values of 'make' variables: instead of editing Makefiles, +# (1) if the variable is set in 'config.status', edit 'config.status' +# (which will cause the Makefiles to be regenerated when you run 'make'); +# (2) otherwise, pass the desired values on the 'make' command line. +$(am__recursive_targets): + @fail=; \ + if $(am__make_keepgoing); then \ + failcom='fail=yes'; \ + else \ + failcom='exit 1'; \ + fi; \ + dot_seen=no; \ + target=`echo $@ | sed s/-recursive//`; \ + case "$@" in \ + distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ + *) list='$(SUBDIRS)' ;; \ + esac; \ + for subdir in $$list; do \ + echo "Making $$target in $$subdir"; \ + if test "$$subdir" = "."; then \ + dot_seen=yes; \ + local_target="$$target-am"; \ + else \ + local_target="$$target"; \ + fi; \ + ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ + || eval $$failcom; \ + done; \ + if test "$$dot_seen" = "no"; then \ + $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ + fi; test -z "$$fail" + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-recursive +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ + include_option=--etags-include; \ + empty_fix=.; \ + else \ + include_option=--include; \ + empty_fix=; \ + fi; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + test ! -f $$subdir/TAGS || \ + set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \ + fi; \ + done; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-recursive + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscope: cscope.files + test ! -s cscope.files \ + || $(CSCOPE) -b -q $(AM_CSCOPEFLAGS) $(CSCOPEFLAGS) -i cscope.files $(CSCOPE_ARGS) +clean-cscope: + -rm -f cscope.files +cscope.files: clean-cscope cscopelist +cscopelist: cscopelist-recursive + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + -rm -f cscope.out cscope.in.out cscope.po.out cscope.files + +distdir: $(DISTFILES) + $(am__remove_distdir) + test -d "$(distdir)" || mkdir "$(distdir)" + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done + @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + $(am__make_dryrun) \ + || test -d "$(distdir)/$$subdir" \ + || $(MKDIR_P) "$(distdir)/$$subdir" \ + || exit 1; \ + dir1=$$subdir; dir2="$(distdir)/$$subdir"; \ + $(am__relativize); \ + new_distdir=$$reldir; \ + dir1=$$subdir; dir2="$(top_distdir)"; \ + $(am__relativize); \ + new_top_distdir=$$reldir; \ + echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \ + echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \ + ($(am__cd) $$subdir && \ + $(MAKE) $(AM_MAKEFLAGS) \ + top_distdir="$$new_top_distdir" \ + distdir="$$new_distdir" \ + am__remove_distdir=: \ + am__skip_length_check=: \ + am__skip_mode_fix=: \ + distdir) \ + || exit 1; \ + fi; \ + done + -test -n "$(am__skip_mode_fix)" \ + || find "$(distdir)" -type d ! -perm -755 \ + -exec chmod u+rwx,go+rx {} \; -o \ + ! -type d ! -perm -444 -links 1 -exec chmod a+r {} \; -o \ + ! -type d ! -perm -400 -exec chmod a+r {} \; -o \ + ! -type d ! -perm -444 -exec $(install_sh) -c -m a+r {} {} \; \ + || chmod -R a+r "$(distdir)" +dist-gzip: distdir + tardir=$(distdir) && $(am__tar) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz + $(am__post_remove_distdir) + +dist-bzip2: distdir + tardir=$(distdir) && $(am__tar) | BZIP2=$${BZIP2--9} bzip2 -c >$(distdir).tar.bz2 + $(am__post_remove_distdir) + +dist-lzip: distdir + tardir=$(distdir) && $(am__tar) | lzip -c $${LZIP_OPT--9} >$(distdir).tar.lz + $(am__post_remove_distdir) + +dist-xz: distdir + tardir=$(distdir) && $(am__tar) | XZ_OPT=$${XZ_OPT--e} xz -c >$(distdir).tar.xz + $(am__post_remove_distdir) + +dist-tarZ: distdir + @echo WARNING: "Support for distribution archives compressed with" \ + "legacy program 'compress' is deprecated." >&2 + @echo WARNING: "It will be removed altogether in Automake 2.0" >&2 + tardir=$(distdir) && $(am__tar) | compress -c >$(distdir).tar.Z + $(am__post_remove_distdir) + +dist-shar: distdir + @echo WARNING: "Support for shar distribution archives is" \ + "deprecated." >&2 + @echo WARNING: "It will be removed altogether in Automake 2.0" >&2 + shar $(distdir) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).shar.gz + $(am__post_remove_distdir) + +dist-zip: distdir + -rm -f $(distdir).zip + zip -rq $(distdir).zip $(distdir) + $(am__post_remove_distdir) + +dist dist-all: + $(MAKE) $(AM_MAKEFLAGS) $(DIST_TARGETS) am__post_remove_distdir='@:' + $(am__post_remove_distdir) + +# This target untars the dist file and tries a VPATH configuration. Then +# it guarantees that the distribution is self-contained by making another +# tarfile. +distcheck: dist + case '$(DIST_ARCHIVES)' in \ + *.tar.gz*) \ + GZIP=$(GZIP_ENV) gzip -dc $(distdir).tar.gz | $(am__untar) ;;\ + *.tar.bz2*) \ + bzip2 -dc $(distdir).tar.bz2 | $(am__untar) ;;\ + *.tar.lz*) \ + lzip -dc $(distdir).tar.lz | $(am__untar) ;;\ + *.tar.xz*) \ + xz -dc $(distdir).tar.xz | $(am__untar) ;;\ + *.tar.Z*) \ + uncompress -c $(distdir).tar.Z | $(am__untar) ;;\ + *.shar.gz*) \ + GZIP=$(GZIP_ENV) gzip -dc $(distdir).shar.gz | unshar ;;\ + *.zip*) \ + unzip $(distdir).zip ;;\ + esac + chmod -R a-w $(distdir) + chmod u+w $(distdir) + mkdir $(distdir)/_build $(distdir)/_build/sub $(distdir)/_inst + chmod a-w $(distdir) + test -d $(distdir)/_build || exit 0; \ + dc_install_base=`$(am__cd) $(distdir)/_inst && pwd | sed -e 's,^[^:\\/]:[\\/],/,'` \ + && dc_destdir="$${TMPDIR-/tmp}/am-dc-$$$$/" \ + && am__cwd=`pwd` \ + && $(am__cd) $(distdir)/_build/sub \ + && ../../configure \ + $(AM_DISTCHECK_CONFIGURE_FLAGS) \ + $(DISTCHECK_CONFIGURE_FLAGS) \ + --srcdir=../.. --prefix="$$dc_install_base" \ + && $(MAKE) $(AM_MAKEFLAGS) \ + && $(MAKE) $(AM_MAKEFLAGS) dvi \ + && $(MAKE) $(AM_MAKEFLAGS) check \ + && $(MAKE) $(AM_MAKEFLAGS) install \ + && $(MAKE) $(AM_MAKEFLAGS) installcheck \ + && $(MAKE) $(AM_MAKEFLAGS) uninstall \ + && $(MAKE) $(AM_MAKEFLAGS) distuninstallcheck_dir="$$dc_install_base" \ + distuninstallcheck \ + && chmod -R a-w "$$dc_install_base" \ + && ({ \ + (cd ../.. && umask 077 && mkdir "$$dc_destdir") \ + && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" install \ + && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" uninstall \ + && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" \ + distuninstallcheck_dir="$$dc_destdir" distuninstallcheck; \ + } || { rm -rf "$$dc_destdir"; exit 1; }) \ + && rm -rf "$$dc_destdir" \ + && $(MAKE) $(AM_MAKEFLAGS) dist \ + && rm -rf $(DIST_ARCHIVES) \ + && $(MAKE) $(AM_MAKEFLAGS) distcleancheck \ + && cd "$$am__cwd" \ + || exit 1 + $(am__post_remove_distdir) + @(echo "$(distdir) archives ready for distribution: "; \ + list='$(DIST_ARCHIVES)'; for i in $$list; do echo $$i; done) | \ + sed -e 1h -e 1s/./=/g -e 1p -e 1x -e '$$p' -e '$$x' +distuninstallcheck: + @test -n '$(distuninstallcheck_dir)' || { \ + echo 'ERROR: trying to run $@ with an empty' \ + '$$(distuninstallcheck_dir)' >&2; \ + exit 1; \ + }; \ + $(am__cd) '$(distuninstallcheck_dir)' || { \ + echo 'ERROR: cannot chdir into $(distuninstallcheck_dir)' >&2; \ + exit 1; \ + }; \ + test `$(am__distuninstallcheck_listfiles) | wc -l` -eq 0 \ + || { echo "ERROR: files left after uninstall:" ; \ + if test -n "$(DESTDIR)"; then \ + echo " (check DESTDIR support)"; \ + fi ; \ + $(distuninstallcheck_listfiles) ; \ + exit 1; } >&2 +distcleancheck: distclean + @if test '$(srcdir)' = . ; then \ + echo "ERROR: distcleancheck can only run from a VPATH build" ; \ + exit 1 ; \ + fi + @test `$(distcleancheck_listfiles) | wc -l` -eq 0 \ + || { echo "ERROR: files left in build directory after distclean:" ; \ + $(distcleancheck_listfiles) ; \ + exit 1; } >&2 +check-am: all-am +check: check-recursive +all-am: Makefile $(DATA) +installdirs: installdirs-recursive +installdirs-am: + for dir in "$(DESTDIR)$(pkgconfigdir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-recursive +install-exec: install-exec-recursive +install-data: install-data-recursive +uninstall: uninstall-recursive + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-recursive +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-recursive + +clean-am: clean-generic clean-libtool mostlyclean-am + +distclean: distclean-recursive + -rm -f $(am__CONFIG_DISTCLEAN_FILES) + -rm -f Makefile +distclean-am: clean-am distclean-generic distclean-libtool \ + distclean-tags + +dvi: dvi-recursive + +dvi-am: + +html: html-recursive + +html-am: + +info: info-recursive + +info-am: + +install-data-am: install-pkgconfigDATA + +install-dvi: install-dvi-recursive + +install-dvi-am: + +install-exec-am: + +install-html: install-html-recursive + +install-html-am: + +install-info: install-info-recursive + +install-info-am: + +install-man: + +install-pdf: install-pdf-recursive + +install-pdf-am: + +install-ps: install-ps-recursive + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-recursive + -rm -f $(am__CONFIG_DISTCLEAN_FILES) + -rm -rf $(top_srcdir)/autom4te.cache + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-recursive + +mostlyclean-am: mostlyclean-generic mostlyclean-libtool + +pdf: pdf-recursive + +pdf-am: + +ps: ps-recursive + +ps-am: + +uninstall-am: uninstall-pkgconfigDATA + +.MAKE: $(am__recursive_targets) install-am install-strip + +.PHONY: $(am__recursive_targets) CTAGS GTAGS TAGS all all-am \ + am--refresh check check-am clean clean-cscope clean-generic \ + clean-libtool cscope cscopelist-am ctags ctags-am dist \ + dist-all dist-bzip2 dist-gzip dist-lzip dist-shar dist-tarZ \ + dist-xz dist-zip distcheck distclean distclean-generic \ + distclean-libtool distclean-tags distcleancheck distdir \ + distuninstallcheck dvi dvi-am html html-am info info-am \ + install install-am install-data install-data-am install-dvi \ + install-dvi-am install-exec install-exec-am install-html \ + install-html-am install-info install-info-am install-man \ + install-pdf install-pdf-am install-pkgconfigDATA install-ps \ + install-ps-am install-strip installcheck installcheck-am \ + installdirs installdirs-am maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-generic \ + mostlyclean-libtool pdf pdf-am ps ps-am tags tags-am uninstall \ + uninstall-am uninstall-pkgconfigDATA + +.PRECIOUS: Makefile + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/lib/adc.c b/lib/adc.c index 9cc531b..1883f27 100644 --- a/lib/adc.c +++ b/lib/adc.c @@ -93,6 +93,24 @@ adc* libsoc_adc_request (unsigned int chip, unsigned int adc_num) return NULL; } +int libsoc_adc_get_value (adc *adc) +{ + char value[64] = ""; // only 12 bit number but anticipating future needs + char *result; + if (adc == NULL) + { + libsoc_adc_debug(__func__, -1, -1, "invalid adc pointer"); + return -1; + } + result = fgets(value, 64, adc->fd); + if (result != value || strlen(value) < 1) + { + libsoc_adc_debug(__func__, adc->chip, adc->adc, "ADC read failure"); + return -1; + } + return atoi(value); +} + int libsoc_adc_free(adc *adc) { if (adc == NULL) diff --git a/test/adc_test.c b/test/adc_test.c new file mode 100644 index 0000000..6116442 --- /dev/null +++ b/test/adc_test.c @@ -0,0 +1,52 @@ +#include +#include +#include +#include + +#include "libsoc_adc.h" +#include "libsoc_debug.h" + +/** + * + * This adc_test is intended to be run on Samsung ARTIK 710 hardware, + * however, it can work on any board with an ADC sysfs implementation, + * if the lib/include/libsoc_adc.h file is modified accordingly. + * + * The ADC sysfs interface is still vendor-specific as of 2017-07-20. + * + * ADC sysfs Documentation: https://developer.artik.io/documentation/ + * developer-guide/gpio/kernel-gpio.html + */ + +#define ADC_OUTPUT_CHIP 0 +#define ADC_PIN 1 + +int main(void) +{ + int ret = EXIT_FAILURE; + adc *adc; + int value; + + libsoc_set_debug(1); + + adc *adc = libsoc_adc_request(ADC_OUTPUT_CHIP, ADC_PIN); + + if (!adc) + { + fprintf(stderr, "Failed to get ADC\n"); + } + else + { + value = libsoc_adc_get_value(adc); + if (value < 0) + { + fprintf(stderr, "Failed to read ADC value\n"); + } + else + { + ret = EXIT_SUCCESS; + } + libsoc_adc_free(adc); + } + return ret; +} From 77cca37991051f9e07eba9963ed7601e7d2adb83 Mon Sep 17 00:00:00 2001 From: John Comeau Date: Thu, 20 Jul 2017 08:56:56 -0700 Subject: [PATCH 24/60] use the correct functions --- lib/adc.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/lib/adc.c b/lib/adc.c index 1883f27..834bdc3 100644 --- a/lib/adc.c +++ b/lib/adc.c @@ -96,18 +96,19 @@ adc* libsoc_adc_request (unsigned int chip, unsigned int adc_num) int libsoc_adc_get_value (adc *adc) { char value[64] = ""; // only 12 bit number but anticipating future needs - char *result; + int result; if (adc == NULL) { libsoc_adc_debug(__func__, -1, -1, "invalid adc pointer"); return -1; } - result = fgets(value, 64, adc->fd); - if (result != value || strlen(value) < 1) + result = file_read(adc->fd, value, 64); + if (result < 0 || strlen(value) < 1 || strlen(value) > 64) { libsoc_adc_debug(__func__, adc->chip, adc->adc, "ADC read failure"); return -1; } + libsoc_adc_debug(__func__, adc->chip, adc->adc, "ADC value: \"%s\"", value); return atoi(value); } From 3335200c700e5861f7371f8bb0a1906486fd5deb Mon Sep 17 00:00:00 2001 From: John Comeau Date: Thu, 20 Jul 2017 08:58:24 -0700 Subject: [PATCH 25/60] added Makefile for test, needs to be fleshed out --- test/Makefile | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 test/Makefile diff --git a/test/Makefile b/test/Makefile new file mode 100644 index 0000000..1445c21 --- /dev/null +++ b/test/Makefile @@ -0,0 +1,4 @@ +all: adc_test.test + +%.test: % + ./$< From 60354072735a2b6adb76cdeb38efa2b2fd56865f Mon Sep 17 00:00:00 2001 From: John Comeau Date: Thu, 20 Jul 2017 09:12:12 -0700 Subject: [PATCH 26/60] =?UTF-8?q?jcomeau@aspire:/usr/src/libsoc$=20make=20?= =?UTF-8?q?-C=20test=20adc=5Ftest=20make:=20Entering=20directory=20'/usr/s?= =?UTF-8?q?rc/libsoc/test'=20cc=20=20=20=20=20adc=5Ftest.c=20=20=20-o=20ad?= =?UTF-8?q?c=5Ftest=20adc=5Ftest.c:=20In=20function=20=E2=80=98main?= =?UTF-8?q?=E2=80=99:=20adc=5Ftest.c:32:7:=20error:=20invalid=20operands?= =?UTF-8?q?=20to=20binary=20*=20(have=20=E2=80=98adc=20*=20{aka=20struct?= =?UTF-8?q?=20=20*}=E2=80=99=20and=20=E2=80=98adc=20*=20{aka=20?= =?UTF-8?q?struct=20=20*}=E2=80=99)=20=20=20=20adc=20*adc=20=3D?= =?UTF-8?q?=20libsoc=5Fadc=5Frequest(ADC=5FOUTPUT=5FCHIP,=20ADC=5FPIN);=20?= =?UTF-8?q?=20=20=20=20=20=20=20^=20adc=5Ftest.c:40:13:=20warning:=20impli?= =?UTF-8?q?cit=20declaration=20of=20function=20=E2=80=98libsoc=5Fadc=5Fget?= =?UTF-8?q?=5Fvalue=E2=80=99=20[-Wimplicit-function-declaration]=20=20=20?= =?UTF-8?q?=20=20=20value=20=3D=20libsoc=5Fadc=5Fget=5Fvalue(adc);=20=20?= =?UTF-8?q?=20=20=20=20=20=20=20=20=20=20=20=20^~~~~~~~~~~~~~~~~~~~=20:=20recipe=20for=20target=20'adc=5Ftest'=20failed=20make:?= =?UTF-8?q?=20***=20[adc=5Ftest]=20Error=201=20make:=20Leaving=20directory?= =?UTF-8?q?=20'/usr/src/libsoc/test'?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- test/Makefile | 2 ++ 1 file changed, 2 insertions(+) diff --git a/test/Makefile b/test/Makefile index 1445c21..b0415cd 100644 --- a/test/Makefile +++ b/test/Makefile @@ -1,3 +1,5 @@ +CPATH += ../lib/include +export all: adc_test.test %.test: % From 1734cc417bf8ca83d3fac5ba64447c5371b639da Mon Sep 17 00:00:00 2001 From: John Comeau Date: Thu, 20 Jul 2017 09:38:38 -0700 Subject: [PATCH 27/60] more bugs fixed --- Makefile | 3 +++ lib/include/libsoc_adc.h | 10 ++++++++++ test/Makefile | 3 ++- test/adc_test.c | 2 +- 4 files changed, 16 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index 4aed3f7..45335cf 100644 --- a/Makefile +++ b/Makefile @@ -387,6 +387,7 @@ pkgconfig_DATA = libsoc.pc EXTRA_DIST = libsoc.pc.in CLEANFILES = libsoc.pc SUBDIRS = lib contrib/board_files $(am__append_1) +export all: all-recursive .SUFFIXES: @@ -884,3 +885,5 @@ uninstall-am: uninstall-pkgconfigDATA # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: +env: + env diff --git a/lib/include/libsoc_adc.h b/lib/include/libsoc_adc.h index 05e7cc9..03b6d94 100644 --- a/lib/include/libsoc_adc.h +++ b/lib/include/libsoc_adc.h @@ -41,6 +41,16 @@ typedef struct { adc* libsoc_adc_request(unsigned int adc_chip, unsigned int adc_num); +/** + * \fn int libsoc_adc_get_value(adc *adc) + * \brief read value from ADC + * \param pointer to adc* + * \return int positive value read on success -1 on fail + * + */ + +int libsoc_adc_get_value (adc *adc); + /** * \fn int libsoc_adc_free(adc* adc) * \brief free a previously requested adc diff --git a/test/Makefile b/test/Makefile index b0415cd..92d5e67 100644 --- a/test/Makefile +++ b/test/Makefile @@ -1,6 +1,7 @@ CPATH += ../lib/include export all: adc_test.test - +%: %.c + gcc -o $@ $< -lsoc %.test: % ./$< diff --git a/test/adc_test.c b/test/adc_test.c index 6116442..98fc904 100644 --- a/test/adc_test.c +++ b/test/adc_test.c @@ -29,7 +29,7 @@ int main(void) libsoc_set_debug(1); - adc *adc = libsoc_adc_request(ADC_OUTPUT_CHIP, ADC_PIN); + adc = libsoc_adc_request(ADC_OUTPUT_CHIP, ADC_PIN); if (!adc) { From 0bd4ba6d30720da3af1041c4d086ad975d5fdb19 Mon Sep 17 00:00:00 2001 From: John Comeau Date: Thu, 20 Jul 2017 10:44:21 -0700 Subject: [PATCH 28/60] implicit rules aren't chaining for some reason, so kludged it --- lib/adc.c | 5 ++++- test/Makefile | 3 ++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/lib/adc.c b/lib/adc.c index 834bdc3..f28c502 100644 --- a/lib/adc.c +++ b/lib/adc.c @@ -11,6 +11,8 @@ #include "libsoc_adc.h" #define STR_BUF 256 +/* https://stackoverflow.com/a/34135270/493161 */ +#define LENGTH(array) ((int) (sizeof (array) / sizeof(array)[0])) void libsoc_adc_debug (const char *func, unsigned int chip, unsigned int adc, char *format, ...) @@ -43,8 +45,9 @@ adc* libsoc_adc_request (unsigned int chip, unsigned int adc_num) libsoc_adc_debug (__func__, chip, adc_num, "requested ADC"); - for (i = 0; i < sizeof(ADC_DEVICE_FORMAT); i++) + for (i = 0; i < LENGTH(ADC_DEVICE_FORMAT); i++) { + libsoc_adc_debug (__func__, chip, adc_num, "trying format string %d", i); result = snprintf(chip_str, STR_BUF, ADC_DEVICE_FORMAT[i], chip); if (result < 0) { diff --git a/test/Makefile b/test/Makefile index 92d5e67..c17a00a 100644 --- a/test/Makefile +++ b/test/Makefile @@ -1,6 +1,7 @@ CPATH += ../lib/include +LIBRARY_PATH := ../lib/.libs $(LIBRARY_PATH) export -all: adc_test.test +test: adc_test adc_test.test %: %.c gcc -o $@ $< -lsoc %.test: % From 357f8b3a5a0b3109dc7351124a1907feb41929e9 Mon Sep 17 00:00:00 2001 From: John Comeau Date: Thu, 20 Jul 2017 10:57:40 -0700 Subject: [PATCH 29/60] fixed bug and hopefully segfault crash --- lib/adc.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/adc.c b/lib/adc.c index f28c502..f8b73ca 100644 --- a/lib/adc.c +++ b/lib/adc.c @@ -65,8 +65,10 @@ adc* libsoc_adc_request (unsigned int chip, unsigned int adc_num) libsoc_adc_debug(__func__, chip, adc_num, "Found requested chip"); for (j = 0; j < sizeof(ADC_READ_FORMAT); j++) { + libsoc_adc_debug (__func__, chip, adc_num, + "trying pin format string %d", j); strncpy(adc_str, chip_str, STR_BUF); - strncpy(adc_str + result, ADC_READ_FORMAT[j], + strncpy(adc_str + strlen(adc_str), ADC_READ_FORMAT[j], STR_BUF - strlen(adc_str)); if (strlen(adc_str) > STR_BUF) { From d01a149f2b63c1010fb46eda5cff29beeae501f5 Mon Sep 17 00:00:00 2001 From: John Comeau Date: Thu, 20 Jul 2017 11:02:15 -0700 Subject: [PATCH 30/60] another attempt to solve segfault --- lib/adc.c | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/adc.c b/lib/adc.c index f8b73ca..986039e 100644 --- a/lib/adc.c +++ b/lib/adc.c @@ -75,6 +75,7 @@ adc* libsoc_adc_request (unsigned int chip, unsigned int adc_num) perror("Failed formatting device string"); return NULL; } + libsoc_adc_debug(__func__, chip, adc_num, "Checking path %s", adc_str); if (file_valid(adc_str)) { libsoc_adc_debug(__func__, chip, adc_num, "Found requested ADC"); From 06c810a24969d228fc35dd2c201aa52942a85dba Mon Sep 17 00:00:00 2001 From: John Comeau Date: Thu, 20 Jul 2017 11:10:10 -0700 Subject: [PATCH 31/60] string was not being formatted --- lib/adc.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/adc.c b/lib/adc.c index 986039e..d945f69 100644 --- a/lib/adc.c +++ b/lib/adc.c @@ -41,7 +41,7 @@ adc* libsoc_adc_request (unsigned int chip, unsigned int adc_num) char chip_str[STR_BUF]; char adc_str[STR_BUF]; int i, j; - size_t result; + int result; libsoc_adc_debug (__func__, chip, adc_num, "requested ADC"); @@ -68,9 +68,9 @@ adc* libsoc_adc_request (unsigned int chip, unsigned int adc_num) libsoc_adc_debug (__func__, chip, adc_num, "trying pin format string %d", j); strncpy(adc_str, chip_str, STR_BUF); - strncpy(adc_str + strlen(adc_str), ADC_READ_FORMAT[j], - STR_BUF - strlen(adc_str)); - if (strlen(adc_str) > STR_BUF) + result = snprintf(adc_str + strlen(adc_str), STR_BUF - strlen(adc_str), + ADC_READ_FORMAT[j], adc_num); + if (result < 0 || strlen(adc_str) > STR_BUF) { perror("Failed formatting device string"); return NULL; From 4de0f74278f999f649d2ebd9727536c12e1443c7 Mon Sep 17 00:00:00 2001 From: John Comeau Date: Thu, 20 Jul 2017 11:14:20 -0700 Subject: [PATCH 32/60] fix newline problem on ADC read --- lib/adc.c | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/adc.c b/lib/adc.c index d945f69..82f37ce 100644 --- a/lib/adc.c +++ b/lib/adc.c @@ -114,6 +114,7 @@ int libsoc_adc_get_value (adc *adc) libsoc_adc_debug(__func__, adc->chip, adc->adc, "ADC read failure"); return -1; } + if (value[strlen(value)] == '\n') value[strlen(value)] = '\0'; libsoc_adc_debug(__func__, adc->chip, adc->adc, "ADC value: \"%s\"", value); return atoi(value); } From 44e8b81ebd7cdcd65efc6922249eec9e389a5e2e Mon Sep 17 00:00:00 2001 From: John Comeau Date: Thu, 20 Jul 2017 11:18:45 -0700 Subject: [PATCH 33/60] obiwan error --- lib/adc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/adc.c b/lib/adc.c index 82f37ce..57aa4aa 100644 --- a/lib/adc.c +++ b/lib/adc.c @@ -114,7 +114,7 @@ int libsoc_adc_get_value (adc *adc) libsoc_adc_debug(__func__, adc->chip, adc->adc, "ADC read failure"); return -1; } - if (value[strlen(value)] == '\n') value[strlen(value)] = '\0'; + if (value[strlen(value) - 1] == '\n') value[strlen(value) - 1] = '\0'; libsoc_adc_debug(__func__, adc->chip, adc->adc, "ADC value: \"%s\"", value); return atoi(value); } From 2b79ca5843aaef6ad9906c5fa2912ea9ba359db8 Mon Sep 17 00:00:00 2001 From: John Comeau Date: Thu, 20 Jul 2017 11:55:38 -0700 Subject: [PATCH 34/60] adding Python test for adc, untested --- bindings/python/Makefile.am | 2 +- bindings/python/__init__.py | 1 + bindings/python/adc.py | 51 +++++++++++++++++++++++++++++++++++++ test/adc_test.py | 17 +++++++++++++ test/i2c_test.py | 0 5 files changed, 70 insertions(+), 1 deletion(-) create mode 100755 bindings/python/adc.py create mode 100755 test/adc_test.py mode change 100644 => 100755 test/i2c_test.py diff --git a/bindings/python/Makefile.am b/bindings/python/Makefile.am index 1814992..5fa3506 100644 --- a/bindings/python/Makefile.am +++ b/bindings/python/Makefile.am @@ -1,5 +1,5 @@ libsocdir = $(pyexecdir)/libsoc -libsoc_PYTHON = __init__.py gpio.py i2c.py spi.py +libsoc_PYTHON = __init__.py gpio.py i2c.py spi.py adc.py AM_CPPFLAGS = $(PYTHON_CFLAGS) -I${top_srcdir}/lib/include -DLIBSOC_SO=\"libsoc.so\" diff --git a/bindings/python/__init__.py b/bindings/python/__init__.py index 45a4275..c42b2d6 100644 --- a/bindings/python/__init__.py +++ b/bindings/python/__init__.py @@ -2,3 +2,4 @@ from .gpio import * # NOQA from .i2c import * # NOQA from .spi import * # NOQA +from .adc import * # NOQA diff --git a/bindings/python/adc.py b/bindings/python/adc.py new file mode 100755 index 0000000..2ee6888 --- /dev/null +++ b/bindings/python/adc.py @@ -0,0 +1,51 @@ +#!/usr/bin/python +import sys +from ctypes import create_string_buffer + +from ._libsoc import api + +PY3 = sys.version_info >= (3, 0) + +class ADC(object): + def __init__(self, chip, pin): + if not isinstance(chip, int): + raise TypeError('Invalid chip id must be an "int"') + if not isinstance(pin, int): + raise TypeError('Invalid adc pin must be an "int"') + self.chip = chip + self.pin = pin + self._adc = None + + def __enter__(self): + self.open() + return self + + def __exit__(self, type, value, traceback): + self.close() + + def open(self): + ''' + Opens a file descriptor to the GPIO and configures it. + ''' + assert self._adc is None + self._adc = api.libsoc_adc_request(self.chip, self.pin) + if self._adc == 0: # NULL from native code + raise IOError( + 'Unable to open adc chip(%d) pin(%d)' % (self.chip, self.pin)) + + def close(self): + '''Cleans up the memory and resources allocated by the open method.''' + if self._adc: + api.libsoc_adc_free(self._adc) + self._adc = None + + @staticmethod + def set_debug(enabled): + v = 0 + if enabled: + v = 1 + api.libsoc_set_debug(v) + + def read(self): + if api.libsoc_adc_get_value(self._adc) == -1: + raise IOError('Error reading adc value') diff --git a/test/adc_test.py b/test/adc_test.py new file mode 100755 index 0000000..b410f1f --- /dev/null +++ b/test/adc_test.py @@ -0,0 +1,17 @@ +#!/usr/bin/python +''' +Test for ADC module +''' +from libsoc import ADC + +def test_adc(): + ''' + built-in test routine + ''' + for index in range(8): + adc = ADC(0, index) + print('Value read at ADC(%d, %d): %d' % (adc.chip, adc.pin, adc.read())) + +if __name__ == '__main__': + test_adc() + diff --git a/test/i2c_test.py b/test/i2c_test.py old mode 100644 new mode 100755 From a520efeab4f5b6006815d83c065635b60b4e3d65 Mon Sep 17 00:00:00 2001 From: John Comeau Date: Thu, 20 Jul 2017 12:07:26 -0700 Subject: [PATCH 35/60] working on adc_test.py --- test/adc_test.py | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/test/adc_test.py b/test/adc_test.py index b410f1f..55dcaf7 100755 --- a/test/adc_test.py +++ b/test/adc_test.py @@ -9,8 +9,13 @@ def test_adc(): built-in test routine ''' for index in range(8): - adc = ADC(0, index) - print('Value read at ADC(%d, %d): %d' % (adc.chip, adc.pin, adc.read())) + value = None + try: + adc = ADC(0, index) + value = adc.read() + except IOError: + pass + print('Value read at ADC(%d, %d): %s' % (adc.chip, adc.pin, value)) if __name__ == '__main__': test_adc() From 8c0cd4bc999a2783d22a6ae5a61cffebee73e006 Mon Sep 17 00:00:00 2001 From: John Comeau Date: Thu, 20 Jul 2017 12:12:35 -0700 Subject: [PATCH 36/60] enabled low-level debugging --- test/adc_test.py | 1 + 1 file changed, 1 insertion(+) diff --git a/test/adc_test.py b/test/adc_test.py index 55dcaf7..9c631a8 100755 --- a/test/adc_test.py +++ b/test/adc_test.py @@ -3,6 +3,7 @@ Test for ADC module ''' from libsoc import ADC +ADC.set_debug(__debug__) def test_adc(): ''' From 862cb58f1d2513e39f6a76a3b517c5bfabf1f852 Mon Sep 17 00:00:00 2001 From: John Comeau Date: Thu, 20 Jul 2017 12:22:14 -0700 Subject: [PATCH 37/60] debugging ADC Python test --- bindings/python/adc.py | 8 ++++++++ lib/adc.c | 4 ++-- test/adc_test.c | 2 +- test/adc_test.py | 6 +++--- 4 files changed, 14 insertions(+), 6 deletions(-) diff --git a/bindings/python/adc.py b/bindings/python/adc.py index 2ee6888..e2979b6 100755 --- a/bindings/python/adc.py +++ b/bindings/python/adc.py @@ -7,6 +7,14 @@ PY3 = sys.version_info >= (3, 0) class ADC(object): + ''' + Represents an ADC pin. + + Example of use: + + with ADC(0, 0) as adc: + print adc.read() + ''' def __init__(self, chip, pin): if not isinstance(chip, int): raise TypeError('Invalid chip id must be an "int"') diff --git a/lib/adc.c b/lib/adc.c index 57aa4aa..e2ed55d 100644 --- a/lib/adc.c +++ b/lib/adc.c @@ -105,7 +105,7 @@ int libsoc_adc_get_value (adc *adc) int result; if (adc == NULL) { - libsoc_adc_debug(__func__, -1, -1, "invalid adc pointer"); + libsoc_adc_debug(__func__, -1, -1, "invalid adc pointer NULL"); return -1; } result = file_read(adc->fd, value, 64); @@ -123,7 +123,7 @@ int libsoc_adc_free(adc *adc) { if (adc == NULL) { - libsoc_adc_debug(__func__, -1, -1, "invalid adc pointer"); + libsoc_adc_debug(__func__, -1, -1, "invalid adc pointer NULL"); return EXIT_FAILURE; } diff --git a/test/adc_test.c b/test/adc_test.c index 98fc904..84f854c 100644 --- a/test/adc_test.c +++ b/test/adc_test.c @@ -19,7 +19,7 @@ */ #define ADC_OUTPUT_CHIP 0 -#define ADC_PIN 1 +#define ADC_PIN 0 int main(void) { diff --git a/test/adc_test.py b/test/adc_test.py index 9c631a8..1ab517c 100755 --- a/test/adc_test.py +++ b/test/adc_test.py @@ -7,13 +7,13 @@ def test_adc(): ''' - built-in test routine + ADC test routine ''' for index in range(8): value = None try: - adc = ADC(0, index) - value = adc.read() + with ADC(0, index) as adc: + value = adc.read() except IOError: pass print('Value read at ADC(%d, %d): %s' % (adc.chip, adc.pin, value)) From 73f920050ea360f93df499f70fdba59dea6be0f6 Mon Sep 17 00:00:00 2001 From: John Comeau Date: Thu, 20 Jul 2017 15:26:15 -0700 Subject: [PATCH 38/60] bugfix for adc_test, untested pwm_test --- bindings/python/Makefile.am | 2 +- bindings/python/adc.py | 4 +- bindings/python/pwm.py | 97 +++++++++++++++++++++++++++++++++++++ test/adc_test.py | 8 +-- test/pwm_test.py | 59 ++++++++++++++++++++++ 5 files changed, 163 insertions(+), 7 deletions(-) create mode 100644 bindings/python/pwm.py create mode 100755 test/pwm_test.py diff --git a/bindings/python/Makefile.am b/bindings/python/Makefile.am index 5fa3506..c9d6197 100644 --- a/bindings/python/Makefile.am +++ b/bindings/python/Makefile.am @@ -1,5 +1,5 @@ libsocdir = $(pyexecdir)/libsoc -libsoc_PYTHON = __init__.py gpio.py i2c.py spi.py adc.py +libsoc_PYTHON = __init__.py gpio.py i2c.py spi.py adc.py pwm.py AM_CPPFLAGS = $(PYTHON_CFLAGS) -I${top_srcdir}/lib/include -DLIBSOC_SO=\"libsoc.so\" diff --git a/bindings/python/adc.py b/bindings/python/adc.py index e2979b6..3c2ac3f 100755 --- a/bindings/python/adc.py +++ b/bindings/python/adc.py @@ -1,7 +1,5 @@ -#!/usr/bin/python +#!/usr/bin/python -OO import sys -from ctypes import create_string_buffer - from ._libsoc import api PY3 = sys.version_info >= (3, 0) diff --git a/bindings/python/pwm.py b/bindings/python/pwm.py new file mode 100644 index 0000000..81d3f4e --- /dev/null +++ b/bindings/python/pwm.py @@ -0,0 +1,97 @@ +#!/usr/bin/python -OO +import sys +from ._libsoc import api + +PY3 = sys.version_info >= (3, 0) + +MODE = { + 'shared': api.LS_PWM_SHARED, + 'greedy': api.LS_PWM_GREEDY, + 'weak': api.LS_PWM_WEAK +} + +POLARITY = { + 'normal': 'n', + 'inverse': 'i', + 'n': 'normal', + 'i': 'inverse' +} + +class PWM(object): + ''' + Represents a GPIO configured for PWM (pulse width modulation). + + Example of use: + + with PWM(0, 0) as pwm: + pwm.write(.25) + ''' + def __init__(self, chip, pin, mode='shared', **kwargs): + ''' + Initialize a PWM output. + + mode can be LS_PWM_SHARED (default), LS_PWM_GREEDY, or LS_PWM_WEAK. + ''' + if not isinstance(chip, int): + raise TypeError('Invalid chip id must be an "int"') + if not isinstance(pin, int): + raise TypeError('Invalid adc pin must be an "int"') + self.chip = chip + self.pin = pin + self.mode = MODE[mode] + self.period = kwargs.get('period') + self.duty_cycle = kwargs.get('duty_cycle') + self.polarity = kwargs.get('polarity') + self._pwm = None + + period = property( + lambda self: api.libsoc_pwm_get_period(self), + lambda self, value: api.libsoc_pwm_set_period(self, value)) + + duty_cycle = property( + lambda self: api.libsoc_pwm_get_duty_cycle(self), + lambda self, value: api.libsoc_pwm_set_duty_cycle(self, value)) + + polarity = property( + lambda self: POLARITY[api.libsoc_pwm_get_polarity(self)], + lambda self, value: api.libsoc_pwm_set_polarity(self, POLARITY[value])) + + enabled = property( + lambda self: api.libsoc_pwm_get_enabled(self), + lambda self, value: api.libsoc_pwm_set_enabled(self, value)) + + def __enter__(self): + self.open() + return self + + def __exit__(self, type, value, traceback): + self.close() + + def open(self): + ''' + Opens a file descriptor to the GPIO and configures it. + ''' + assert self._pwm is None + self._pwm = api.libsoc_pwm_request(self.chip, self.pin, self.mode) + if self._pwm == 0: # NULL from native code + raise IOError( + 'Unable to open pwm chip(%d) pin(%d)' % (self.chip, self.pin)) + + def close(self): + '''Cleans up the memory and resources allocated by the open method.''' + if self._pwm: + api.libsoc_pwm_free(self._pwm) + self._pwm = None + + @staticmethod + def set_debug(enabled): + v = 0 + if enabled: + v = 1 + api.libsoc_set_debug(v) + + def on(self): + self.enabled = ENABLED + + def off(self): + self.enabled = DISABLED diff --git a/test/adc_test.py b/test/adc_test.py index 1ab517c..04edaeb 100755 --- a/test/adc_test.py +++ b/test/adc_test.py @@ -1,7 +1,8 @@ -#!/usr/bin/python +#!/usr/bin/python -OO ''' Test for ADC module ''' +import sys, os from libsoc import ADC ADC.set_debug(__debug__) @@ -14,9 +15,10 @@ def test_adc(): try: with ADC(0, index) as adc: value = adc.read() + print('Value read at ADC(%d, %d): %s' % ( + adc.chip, adc.pin, value)) except IOError: - pass - print('Value read at ADC(%d, %d): %s' % (adc.chip, adc.pin, value)) + sys.stderr.write('No such ADC (%d, %d)\n' % (0, index)) if __name__ == '__main__': test_adc() diff --git a/test/pwm_test.py b/test/pwm_test.py new file mode 100755 index 0000000..ea1d6e9 --- /dev/null +++ b/test/pwm_test.py @@ -0,0 +1,59 @@ +#!/usr/bin/python +''' +Simple test of the PWM API + +Should duplicate function of pwm_test.c (q.v.) +''' +import sys, os +from ast import literal_eval +from libsoc import PWM +PWM.set_debug(__debug__) + +def test_pwm(chip=0, pin=1, mode='shared', polarity='normal', period=10, + duty_cycle=5, enabled=False): + ''' + Duplicate pwm_test.c + ''' + kwargs = {k: safe_int(v) for k, v in locals().items()} + pwm = PWM(**kwargs) + for key in kwargs: + value = getattr(pwm, key) + if value != kwargs[key]: + sys.stderr.write('Wrong value %s for pwm.%s\n' % (value, key)) + try: + pwm.duty_cycle = pwm.period + 5 + raise SystemError('The system allowed a duty cycle over 100%') + except ValueError: + pass + pwm.on() + if not pwm.enabled: + raise SystemError('The PWM would not turn on') + pwm.off() + if pwm.enabled: + raise SystemError('The PWM would not shut off') + +def safe_int(string): + ''' + Returns an int if it parses as one, otherwise a string + ''' + try: + number = literal_eval(string) + if isinstance(number, int): + return number + else: + raise TypeError('Not a number') + except ValueError, TypeError: + return string + +if __name__ == '__main__': + ''' + You can set chip and pin number on the command line + + Also other properties in this order: + mode: 'shared', 'greedy', or 'weak' + polarity: 'normal' or 'inverse' + period: an integer up to hardware limit (1000000000 for ARTIK7) + duty_cycle: an integer up to `period` + enabled: 1 (on) or 0 (off) + ''' + test_pwm(*sys.argv[1:]) From cdd2a9ec33f2fbd675eadcd0e23d7bc979b44d43 Mon Sep 17 00:00:00 2001 From: John Comeau Date: Thu, 20 Jul 2017 15:41:57 -0700 Subject: [PATCH 39/60] still debugging adc and pwm --- bindings/python/__init__.py | 1 + lib/adc.c | 10 +++++++--- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/bindings/python/__init__.py b/bindings/python/__init__.py index c42b2d6..cd93628 100644 --- a/bindings/python/__init__.py +++ b/bindings/python/__init__.py @@ -3,3 +3,4 @@ from .i2c import * # NOQA from .spi import * # NOQA from .adc import * # NOQA +from .pwm import * # NOQA diff --git a/lib/adc.c b/lib/adc.c index e2ed55d..92d23c9 100644 --- a/lib/adc.c +++ b/lib/adc.c @@ -102,7 +102,7 @@ adc* libsoc_adc_request (unsigned int chip, unsigned int adc_num) int libsoc_adc_get_value (adc *adc) { char value[64] = ""; // only 12 bit number but anticipating future needs - int result; + long result; if (adc == NULL) { libsoc_adc_debug(__func__, -1, -1, "invalid adc pointer NULL"); @@ -115,8 +115,12 @@ int libsoc_adc_get_value (adc *adc) return -1; } if (value[strlen(value) - 1] == '\n') value[strlen(value) - 1] = '\0'; - libsoc_adc_debug(__func__, adc->chip, adc->adc, "ADC value: \"%s\"", value); - return atoi(value); + libsoc_adc_debug(__func__, adc->chip, adc->adc, "ADC string: \"%s\"", value); + result = strtol(value, NULL, 10); + if (result == LONG_MAX) libsoc_adc_debug(__func__, adc->chip, adc->adc, + "Failed conversion to long integer"); + libsoc_adc_debug(__func__, adc->chip, adc->adc, "ADC value: %d", result); + return result; } int libsoc_adc_free(adc *adc) From a5404f779751ad610f976d5a764bb77128d66ba5 Mon Sep 17 00:00:00 2001 From: John Comeau Date: Thu, 20 Jul 2017 15:45:27 -0700 Subject: [PATCH 40/60] debugging adc support --- lib/adc.c | 1 + test/Makefile | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/adc.c b/lib/adc.c index 92d23c9..48c5d47 100644 --- a/lib/adc.c +++ b/lib/adc.c @@ -1,4 +1,5 @@ #include +#include #include #include #include diff --git a/test/Makefile b/test/Makefile index c17a00a..9bf68a0 100644 --- a/test/Makefile +++ b/test/Makefile @@ -1,7 +1,8 @@ CPATH += ../lib/include LIBRARY_PATH := ../lib/.libs $(LIBRARY_PATH) export -test: adc_test adc_test.test +test: adc_test adc_test.test adc_test.py.test \ + pwm_test pwm_test.test pwm_test.py.test %: %.c gcc -o $@ $< -lsoc %.test: % From f1db3a99b22491d4f3dda9f80b282e53eb97ba5f Mon Sep 17 00:00:00 2001 From: John Comeau Date: Thu, 20 Jul 2017 15:50:30 -0700 Subject: [PATCH 41/60] constants were not found --- bindings/python/libsoc_python.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/bindings/python/libsoc_python.c b/bindings/python/libsoc_python.c index adc6c37..81e4b85 100644 --- a/bindings/python/libsoc_python.c +++ b/bindings/python/libsoc_python.c @@ -2,6 +2,7 @@ #include "libsoc_gpio.h" #include "libsoc_spi.h" +#include "libsoc_pwm.h" static PyMethodDef functions[] = { {NULL, NULL, 0, NULL} /* Sentinel */ @@ -30,6 +31,10 @@ _add_constants(PyObject *m) PyModule_AddIntConstant(m, "LS_GPIO_GREEDY", LS_GPIO_GREEDY); PyModule_AddIntConstant(m, "LS_GPIO_WEAK", LS_GPIO_WEAK); + PyModule_AddIntConstant(m, "LS_PWM_SHARED", LS_GPIO_SHARED); + PyModule_AddIntConstant(m, "LS_PWM_GREEDY", LS_GPIO_GREEDY); + PyModule_AddIntConstant(m, "LS_PWM_WEAK", LS_GPIO_WEAK); + PyModule_AddIntConstant(m, "BITS_8", BITS_8); PyModule_AddIntConstant(m, "BITS_16", BITS_16); PyModule_AddIntConstant(m, "BPW_ERROR", BPW_ERROR); From d21f5b8e840c9c05040b341db70907a78c7d2b4b Mon Sep 17 00:00:00 2001 From: John Comeau Date: Thu, 20 Jul 2017 15:52:39 -0700 Subject: [PATCH 42/60] trying another way to import constants --- bindings/python/pwm.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/bindings/python/pwm.py b/bindings/python/pwm.py index 81d3f4e..2df9966 100644 --- a/bindings/python/pwm.py +++ b/bindings/python/pwm.py @@ -1,13 +1,13 @@ #!/usr/bin/python -OO import sys -from ._libsoc import api +from ._libsoc import api, LS_PWM_SHARED, LS_PWM_GREEDY, LS_PWM_WEAK PY3 = sys.version_info >= (3, 0) MODE = { - 'shared': api.LS_PWM_SHARED, - 'greedy': api.LS_PWM_GREEDY, - 'weak': api.LS_PWM_WEAK + 'shared': LS_PWM_SHARED, + 'greedy': LS_PWM_GREEDY, + 'weak': LS_PWM_WEAK } POLARITY = { From a3debce408941203193e50cde3ce8aef0cbb9e3a Mon Sep 17 00:00:00 2001 From: John Comeau Date: Thu, 20 Jul 2017 16:22:35 -0700 Subject: [PATCH 43/60] fixing adc and pwm python modules --- bindings/python/adc.py | 4 +++- bindings/python/pwm.py | 50 ++++++++++++++++++++++++++---------------- 2 files changed, 34 insertions(+), 20 deletions(-) diff --git a/bindings/python/adc.py b/bindings/python/adc.py index 3c2ac3f..7cc09a1 100755 --- a/bindings/python/adc.py +++ b/bindings/python/adc.py @@ -53,5 +53,7 @@ def set_debug(enabled): api.libsoc_set_debug(v) def read(self): - if api.libsoc_adc_get_value(self._adc) == -1: + value = api.libsoc_adc_get_value(self._adc) + if value == -1: raise IOError('Error reading adc value') + return value diff --git a/bindings/python/pwm.py b/bindings/python/pwm.py index 2df9966..89c94d7 100644 --- a/bindings/python/pwm.py +++ b/bindings/python/pwm.py @@ -1,6 +1,7 @@ #!/usr/bin/python -OO -import sys +import sys, logging from ._libsoc import api, LS_PWM_SHARED, LS_PWM_GREEDY, LS_PWM_WEAK +logging.basicConfig(level=logging.DEBUG if __debug__ else logging.INFO) PY3 = sys.version_info >= (3, 0) @@ -30,7 +31,7 @@ def __init__(self, chip, pin, mode='shared', **kwargs): ''' Initialize a PWM output. - mode can be LS_PWM_SHARED (default), LS_PWM_GREEDY, or LS_PWM_WEAK. + mode can be 'shared' (default), 'greedy', or 'weak' ''' if not isinstance(chip, int): raise TypeError('Invalid chip id must be an "int"') @@ -38,30 +39,41 @@ def __init__(self, chip, pin, mode='shared', **kwargs): raise TypeError('Invalid adc pin must be an "int"') self.chip = chip self.pin = pin - self.mode = MODE[mode] - self.period = kwargs.get('period') - self.duty_cycle = kwargs.get('duty_cycle') - self.polarity = kwargs.get('polarity') + logging.debug("locals(): %s", locals()) + self.mode = mode + self.period = kwargs.get('period', None) + self.duty_cycle = kwargs.get('duty_cycle', None) + self.polarity = kwargs.get('polarity', None) + self.enabled = kwargs.get('enabled', None) self._pwm = None - period = property( - lambda self: api.libsoc_pwm_get_period(self), - lambda self, value: api.libsoc_pwm_set_period(self, value)) + pwm_period = property( + lambda self: api.libsoc_pwm_get_period(self._pwm), + lambda self, value: api.libsoc_pwm_set_period(self._pwm, value)) - duty_cycle = property( - lambda self: api.libsoc_pwm_get_duty_cycle(self), - lambda self, value: api.libsoc_pwm_set_duty_cycle(self, value)) + pwm_duty_cycle = property( + lambda self: api.libsoc_pwm_get_duty_cycle(self._pwm), + lambda self, value: api.libsoc_pwm_set_duty_cycle(self._pwm, value)) - polarity = property( - lambda self: POLARITY[api.libsoc_pwm_get_polarity(self)], - lambda self, value: api.libsoc_pwm_set_polarity(self, POLARITY[value])) + pwm_polarity = property( + lambda self: POLARITY[api.libsoc_pwm_get_polarity(self._pwm)], + lambda self, value: api.libsoc_pwm_set_polarity(self._pwm, + POLARITY[value])) - enabled = property( - lambda self: api.libsoc_pwm_get_enabled(self), - lambda self, value: api.libsoc_pwm_set_enabled(self, value)) + pwm_enabled = property( + lambda self: api.libsoc_pwm_get_enabled(self._pwm), + lambda self, value: api.libsoc_pwm_set_enabled(self._pwm, value)) def __enter__(self): self.open() + if self.period is not None: + self.pwm_period = self.period + if self.duty_cycle is not None: + self.pwm_duty_cycle = self.duty_cycle + if self.polarity is not None: + self.pwm_polarity = POLARITY[self.polarity] + if self.enabled is not None: + self.pwm_enabled = self.enabled return self def __exit__(self, type, value, traceback): @@ -72,7 +84,7 @@ def open(self): Opens a file descriptor to the GPIO and configures it. ''' assert self._pwm is None - self._pwm = api.libsoc_pwm_request(self.chip, self.pin, self.mode) + self._pwm = api.libsoc_pwm_request(self.chip, self.pin, MODE[self.mode]) if self._pwm == 0: # NULL from native code raise IOError( 'Unable to open pwm chip(%d) pin(%d)' % (self.chip, self.pin)) From 0d0f7cd59a4aa3fd210c245faee33391b83a6e57 Mon Sep 17 00:00:00 2001 From: John Comeau Date: Thu, 20 Jul 2017 16:36:26 -0700 Subject: [PATCH 44/60] I had the mapping of POLARITY wrong --- bindings/python/pwm.py | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/bindings/python/pwm.py b/bindings/python/pwm.py index 89c94d7..3c5f002 100644 --- a/bindings/python/pwm.py +++ b/bindings/python/pwm.py @@ -11,13 +11,16 @@ 'weak': LS_PWM_WEAK } +MODE.update({v: k for k, v in MODE.items()}) + POLARITY = { - 'normal': 'n', - 'inverse': 'i', - 'n': 'normal', - 'i': 'inverse' + 'normal': 0, + 'inversed': 1, + 'error': -1, } +POLARITY.update({v: k for k, v in POLARITY.items()}) + class PWM(object): ''' Represents a GPIO configured for PWM (pulse width modulation). From b20f955bea03d2cd6c69864b9dfd5819b84ee39c Mon Sep 17 00:00:00 2001 From: John Comeau Date: Thu, 20 Jul 2017 17:04:10 -0700 Subject: [PATCH 45/60] another round of debugging --- bindings/python/pwm.py | 34 +++++++++++++++------------------- test/pwm_test.py | 16 +++++++++------- 2 files changed, 24 insertions(+), 26 deletions(-) diff --git a/bindings/python/pwm.py b/bindings/python/pwm.py index 3c5f002..9abffb3 100644 --- a/bindings/python/pwm.py +++ b/bindings/python/pwm.py @@ -42,41 +42,37 @@ def __init__(self, chip, pin, mode='shared', **kwargs): raise TypeError('Invalid adc pin must be an "int"') self.chip = chip self.pin = pin - logging.debug("locals(): %s", locals()) self.mode = mode - self.period = kwargs.get('period', None) - self.duty_cycle = kwargs.get('duty_cycle', None) - self.polarity = kwargs.get('polarity', None) - self.enabled = kwargs.get('enabled', None) + self.args = locals() self._pwm = None - pwm_period = property( + period = property( lambda self: api.libsoc_pwm_get_period(self._pwm), lambda self, value: api.libsoc_pwm_set_period(self._pwm, value)) - pwm_duty_cycle = property( + duty_cycle = property( lambda self: api.libsoc_pwm_get_duty_cycle(self._pwm), lambda self, value: api.libsoc_pwm_set_duty_cycle(self._pwm, value)) - pwm_polarity = property( + polarity = property( lambda self: POLARITY[api.libsoc_pwm_get_polarity(self._pwm)], lambda self, value: api.libsoc_pwm_set_polarity(self._pwm, POLARITY[value])) - pwm_enabled = property( + enabled = property( lambda self: api.libsoc_pwm_get_enabled(self._pwm), lambda self, value: api.libsoc_pwm_set_enabled(self._pwm, value)) def __enter__(self): self.open() - if self.period is not None: - self.pwm_period = self.period - if self.duty_cycle is not None: - self.pwm_duty_cycle = self.duty_cycle - if self.polarity is not None: - self.pwm_polarity = POLARITY[self.polarity] - if self.enabled is not None: - self.pwm_enabled = self.enabled + if self.args['period'] is not None: + self.period = self.args['period'] + if self.args['duty_cycle'] is not None: + self.duty_cycle = self.args['duty_cycle'] + if self.args['polarity'] is not None: + self.polarity = POLARITY[self.args['polarity']] + if self.args['enabled'] is not None: + self.enabled = self.args['enabled'] return self def __exit__(self, type, value, traceback): @@ -106,7 +102,7 @@ def set_debug(enabled): api.libsoc_set_debug(v) def on(self): - self.enabled = ENABLED + self.enabled = 1 def off(self): - self.enabled = DISABLED + self.enabled = 0 diff --git a/test/pwm_test.py b/test/pwm_test.py index ea1d6e9..2ebdfa7 100755 --- a/test/pwm_test.py +++ b/test/pwm_test.py @@ -4,10 +4,11 @@ Should duplicate function of pwm_test.c (q.v.) ''' -import sys, os +import sys, os, logging from ast import literal_eval from libsoc import PWM PWM.set_debug(__debug__) +logging.basicConfig(level=logging.DEBUG if __debug__ else logging.INFO) def test_pwm(chip=0, pin=1, mode='shared', polarity='normal', period=10, duty_cycle=5, enabled=False): @@ -20,17 +21,18 @@ def test_pwm(chip=0, pin=1, mode='shared', polarity='normal', period=10, value = getattr(pwm, key) if value != kwargs[key]: sys.stderr.write('Wrong value %s for pwm.%s\n' % (value, key)) - try: - pwm.duty_cycle = pwm.period + 5 - raise SystemError('The system allowed a duty cycle over 100%') - except ValueError: + pwm.duty_cycle = pwm.period + 5 + if pwm.duty_cycle == pwm.period + 5: + logging.error('PWM allowed a duty cycle > 100%') + else: + logging.debug('PWM properly rejected >100% duty cycle') pass pwm.on() if not pwm.enabled: - raise SystemError('The PWM would not turn on') + logging.error('The PWM would not turn on') pwm.off() if pwm.enabled: - raise SystemError('The PWM would not shut off') + logging.error('The PWM would not shut off') def safe_int(string): ''' From 130eb530814a339f0837f4b1110b076651710e31 Mon Sep 17 00:00:00 2001 From: John Comeau Date: Thu, 20 Jul 2017 17:25:21 -0700 Subject: [PATCH 46/60] pwm_test now takes args, Makefile will pass them --- test/Makefile | 3 ++- test/pwm_test.c | 8 +++++--- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/test/Makefile b/test/Makefile index 9bf68a0..994438d 100644 --- a/test/Makefile +++ b/test/Makefile @@ -5,5 +5,6 @@ test: adc_test adc_test.test adc_test.py.test \ pwm_test pwm_test.test pwm_test.py.test %: %.c gcc -o $@ $< -lsoc +# example: `make ARGS="2 0" pwm_test.test` on ARTIK 710 %.test: % - ./$< + ./$< $(ARGS) diff --git a/test/pwm_test.c b/test/pwm_test.c index 902e9a1..65e236d 100644 --- a/test/pwm_test.c +++ b/test/pwm_test.c @@ -22,13 +22,15 @@ #define PWM_OUTPUT_CHIP 0 #define PWM_CHIP_OUTPUT 1 -int main(void) +int main(int argc, char **argv) { - int ret = EXIT_SUCCESS; + int ret = EXIT_SUCCESS, chip, output; + chip = argc > 1 ? atoi(argv[1]) : PWM_OUTPUT_CHIP; + output = argc > 2 ? atoi(argv[2]) : PWM_CHIP_OUTPUT; libsoc_set_debug(1); - pwm *pwm = libsoc_pwm_request(PWM_OUTPUT_CHIP, PWM_CHIP_OUTPUT, LS_PWM_SHARED); + pwm *pwm = libsoc_pwm_request(chip, output, LS_PWM_SHARED); if (!pwm) { From a454c6236f21b4c8f06f6e75b2cb2988242eae5c Mon Sep 17 00:00:00 2001 From: John Comeau Date: Thu, 20 Jul 2017 17:35:23 -0700 Subject: [PATCH 47/60] got bit by the failure to "open" again --- test/Makefile | 2 +- test/pwm_test.py | 34 +++++++++++++++++----------------- 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/test/Makefile b/test/Makefile index 994438d..2765f66 100644 --- a/test/Makefile +++ b/test/Makefile @@ -5,6 +5,6 @@ test: adc_test adc_test.test adc_test.py.test \ pwm_test pwm_test.test pwm_test.py.test %: %.c gcc -o $@ $< -lsoc -# example: `make ARGS="2 0" pwm_test.test` on ARTIK 710 +# example: `make ARGS="0 2" pwm_test.test` on ARTIK 710 %.test: % ./$< $(ARGS) diff --git a/test/pwm_test.py b/test/pwm_test.py index 2ebdfa7..f2091ac 100755 --- a/test/pwm_test.py +++ b/test/pwm_test.py @@ -16,23 +16,23 @@ def test_pwm(chip=0, pin=1, mode='shared', polarity='normal', period=10, Duplicate pwm_test.c ''' kwargs = {k: safe_int(v) for k, v in locals().items()} - pwm = PWM(**kwargs) - for key in kwargs: - value = getattr(pwm, key) - if value != kwargs[key]: - sys.stderr.write('Wrong value %s for pwm.%s\n' % (value, key)) - pwm.duty_cycle = pwm.period + 5 - if pwm.duty_cycle == pwm.period + 5: - logging.error('PWM allowed a duty cycle > 100%') - else: - logging.debug('PWM properly rejected >100% duty cycle') - pass - pwm.on() - if not pwm.enabled: - logging.error('The PWM would not turn on') - pwm.off() - if pwm.enabled: - logging.error('The PWM would not shut off') + with PWM(**kwargs) as pwm: + for key in kwargs: + value = getattr(pwm, key) + if value != kwargs[key]: + sys.stderr.write('Wrong value %s for pwm.%s\n' % (value, key)) + pwm.duty_cycle = pwm.period + 5 + if pwm.duty_cycle == pwm.period + 5: + logging.error('PWM allowed a duty cycle > 100%') + else: + logging.debug('PWM properly rejected >100% duty cycle') + pass + pwm.on() + if not pwm.enabled: + logging.error('The PWM would not turn on') + pwm.off() + if pwm.enabled: + logging.error('The PWM would not shut off') def safe_int(string): ''' From 9d562f96c5e9e80d294bc15aa3fe3ffdac685c14 Mon Sep 17 00:00:00 2001 From: John Comeau Date: Thu, 20 Jul 2017 17:44:11 -0700 Subject: [PATCH 48/60] still debugging pwm Python module --- bindings/python/pwm.py | 19 ++++++++++--------- test/Makefile | 2 +- test/pwm_test.py | 1 + 3 files changed, 12 insertions(+), 10 deletions(-) diff --git a/bindings/python/pwm.py b/bindings/python/pwm.py index 9abffb3..68f73d1 100644 --- a/bindings/python/pwm.py +++ b/bindings/python/pwm.py @@ -43,7 +43,8 @@ def __init__(self, chip, pin, mode='shared', **kwargs): self.chip = chip self.pin = pin self.mode = mode - self.args = locals() + self.kwargs = locals() + logging.debug('self.kwargs: %s', self.kwargs) self._pwm = None period = property( @@ -65,14 +66,14 @@ def __init__(self, chip, pin, mode='shared', **kwargs): def __enter__(self): self.open() - if self.args['period'] is not None: - self.period = self.args['period'] - if self.args['duty_cycle'] is not None: - self.duty_cycle = self.args['duty_cycle'] - if self.args['polarity'] is not None: - self.polarity = POLARITY[self.args['polarity']] - if self.args['enabled'] is not None: - self.enabled = self.args['enabled'] + if self.kwargs.get('period') is not None: + self.period = self.kwargs['period'] + if self.kwargs.get('duty_cycle') is not None: + self.duty_cycle = self.kwargs['duty_cycle'] + if self.kwargs.get('polarity') is not None: + self.polarity = POLARITY[self.kwargs['polarity']] + if self.kwargs.get('enabled') is not None: + self.enabled = self.kwargs['enabled'] return self def __exit__(self, type, value, traceback): diff --git a/test/Makefile b/test/Makefile index 2765f66..9a9ef13 100644 --- a/test/Makefile +++ b/test/Makefile @@ -5,6 +5,6 @@ test: adc_test adc_test.test adc_test.py.test \ pwm_test pwm_test.test pwm_test.py.test %: %.c gcc -o $@ $< -lsoc -# example: `make ARGS="0 2" pwm_test.test` on ARTIK 710 +# example: `make ARGS="0 2 shared normal 1000 500" pwm_test.test` on ARTIK 710 %.test: % ./$< $(ARGS) diff --git a/test/pwm_test.py b/test/pwm_test.py index f2091ac..f67e080 100755 --- a/test/pwm_test.py +++ b/test/pwm_test.py @@ -16,6 +16,7 @@ def test_pwm(chip=0, pin=1, mode='shared', polarity='normal', period=10, Duplicate pwm_test.c ''' kwargs = {k: safe_int(v) for k, v in locals().items()} + logging.debug('kwargs: %s', kwargs) with PWM(**kwargs) as pwm: for key in kwargs: value = getattr(pwm, key) From 29aee8fea9b9ca7f7e97e26f023a0e35b9697323 Mon Sep 17 00:00:00 2001 From: John Comeau Date: Thu, 20 Jul 2017 18:16:16 -0700 Subject: [PATCH 49/60] yet more debugging --- bindings/python/pwm.py | 20 ++++++++++++-------- test/pwm_test.c | 16 +++++++++------- test/pwm_test.py | 13 ++++++------- 3 files changed, 27 insertions(+), 22 deletions(-) diff --git a/bindings/python/pwm.py b/bindings/python/pwm.py index 68f73d1..0d7b376 100644 --- a/bindings/python/pwm.py +++ b/bindings/python/pwm.py @@ -66,14 +66,6 @@ def __init__(self, chip, pin, mode='shared', **kwargs): def __enter__(self): self.open() - if self.kwargs.get('period') is not None: - self.period = self.kwargs['period'] - if self.kwargs.get('duty_cycle') is not None: - self.duty_cycle = self.kwargs['duty_cycle'] - if self.kwargs.get('polarity') is not None: - self.polarity = POLARITY[self.kwargs['polarity']] - if self.kwargs.get('enabled') is not None: - self.enabled = self.kwargs['enabled'] return self def __exit__(self, type, value, traceback): @@ -88,6 +80,18 @@ def open(self): if self._pwm == 0: # NULL from native code raise IOError( 'Unable to open pwm chip(%d) pin(%d)' % (self.chip, self.pin)) + if self.kwargs.get('period') is not None: + logging.debug('setting period to %s', self.kwargs['period']) + self.period = self.kwargs['period'] + if self.kwargs.get('duty_cycle') is not None: + logging.debug('setting duty cycle to %s', self.kwargs['duty_cycle']) + self.duty_cycle = self.kwargs['duty_cycle'] + if self.kwargs.get('polarity') is not None: + logging.debug('setting polarity to %s', self.kwargs['polarity']) + self.polarity = POLARITY[self.kwargs['polarity']] + if self.kwargs.get('enabled') is not None: + logging.debug('setting enabled to %s', self.kwargs['enabled']) + self.enabled = self.kwargs['enabled'] def close(self): '''Cleans up the memory and resources allocated by the open method.''' diff --git a/test/pwm_test.c b/test/pwm_test.c index 65e236d..3aa623e 100644 --- a/test/pwm_test.c +++ b/test/pwm_test.c @@ -25,9 +25,11 @@ int main(int argc, char **argv) { int ret = EXIT_SUCCESS, chip, output; + long period, duty_cycle; chip = argc > 1 ? atoi(argv[1]) : PWM_OUTPUT_CHIP; output = argc > 2 ? atoi(argv[2]) : PWM_CHIP_OUTPUT; - + period = argc > 3 ? atol(argv[3]) : 10; + duty_cycle = argc > 4 ? atol(argv[4]) : 5; libsoc_set_debug(1); pwm *pwm = libsoc_pwm_request(chip, output, LS_PWM_SHARED); @@ -60,21 +62,21 @@ int main(int argc, char **argv) goto fail; } - libsoc_pwm_set_period(pwm, 10); + libsoc_pwm_set_period(pwm, period); int current_period = libsoc_pwm_get_period(pwm); - if (current_period != 10) + if (current_period != period) { printf("Failed period test\n"); goto fail; } - libsoc_pwm_set_duty_cycle(pwm, 5); + libsoc_pwm_set_duty_cycle(pwm, duty_cycle); int current_duty = libsoc_pwm_get_duty_cycle(pwm); - if (current_duty != 5) + if (current_duty != duty_cycle) { printf("Failed duty test\n"); goto fail; @@ -82,11 +84,11 @@ int main(int argc, char **argv) // This command should fail as the duty should not // be allowed to be greater than the period - libsoc_pwm_set_duty_cycle(pwm, 15); + libsoc_pwm_set_duty_cycle(pwm, period + duty_cycle); current_duty = libsoc_pwm_get_duty_cycle(pwm); - if (current_duty != 5) + if (current_duty != duty_cycle) { printf("Failed duty test, this may be a problem with the kernel driver, continuing...\n"); } diff --git a/test/pwm_test.py b/test/pwm_test.py index f67e080..1fa9a97 100755 --- a/test/pwm_test.py +++ b/test/pwm_test.py @@ -10,8 +10,8 @@ PWM.set_debug(__debug__) logging.basicConfig(level=logging.DEBUG if __debug__ else logging.INFO) -def test_pwm(chip=0, pin=1, mode='shared', polarity='normal', period=10, - duty_cycle=5, enabled=False): +def test_pwm(chip=0, pin=1, mode='shared', polarity='normal', period=1000, + duty_cycle=500, enabled=False): ''' Duplicate pwm_test.c ''' @@ -20,10 +20,9 @@ def test_pwm(chip=0, pin=1, mode='shared', polarity='normal', period=10, with PWM(**kwargs) as pwm: for key in kwargs: value = getattr(pwm, key) - if value != kwargs[key]: - sys.stderr.write('Wrong value %s for pwm.%s\n' % (value, key)) - pwm.duty_cycle = pwm.period + 5 - if pwm.duty_cycle == pwm.period + 5: + logging.debug('Check value %s for pwm.%s\n' % (value, key)) + pwm.duty_cycle = pwm.period + pwm.duty_cycle + if pwm.duty_cycle != pwm.duty_cycle: logging.error('PWM allowed a duty cycle > 100%') else: logging.debug('PWM properly rejected >100% duty cycle') @@ -46,7 +45,7 @@ def safe_int(string): else: raise TypeError('Not a number') except ValueError, TypeError: - return string + return string or None if __name__ == '__main__': ''' From 26d4f426c0393074c171e38934d1cb6c9f73898a Mon Sep 17 00:00:00 2001 From: John Comeau Date: Thu, 20 Jul 2017 18:23:09 -0700 Subject: [PATCH 50/60] PWM not setting initial values as passed in --- test/pwm_test.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/pwm_test.py b/test/pwm_test.py index 1fa9a97..73f7f3e 100755 --- a/test/pwm_test.py +++ b/test/pwm_test.py @@ -20,7 +20,7 @@ def test_pwm(chip=0, pin=1, mode='shared', polarity='normal', period=1000, with PWM(**kwargs) as pwm: for key in kwargs: value = getattr(pwm, key) - logging.debug('Check value %s for pwm.%s\n' % (value, key)) + logging.debug('Check value %s for pwm.%s', value, key) pwm.duty_cycle = pwm.period + pwm.duty_cycle if pwm.duty_cycle != pwm.duty_cycle: logging.error('PWM allowed a duty cycle > 100%') From 0f7e9eeea7e09722fb381f6ee61f9e0e9310fdba Mon Sep 17 00:00:00 2001 From: John Comeau Date: Thu, 20 Jul 2017 18:32:16 -0700 Subject: [PATCH 51/60] shows args --- test/pwm_test.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/test/pwm_test.c b/test/pwm_test.c index 3aa623e..06ee48f 100644 --- a/test/pwm_test.c +++ b/test/pwm_test.c @@ -31,6 +31,8 @@ int main(int argc, char **argv) period = argc > 3 ? atol(argv[3]) : 10; duty_cycle = argc > 4 ? atol(argv[4]) : 5; libsoc_set_debug(1); + fprintf(stderr, "Initializing PWM with parameters %d, %d, %d, %d\n", + chip, output, period, duty_cycle); pwm *pwm = libsoc_pwm_request(chip, output, LS_PWM_SHARED); From d535c9b420f54acaa45e583ae2e8331e0ee8de72 Mon Sep 17 00:00:00 2001 From: John Comeau Date: Thu, 20 Jul 2017 18:34:29 -0700 Subject: [PATCH 52/60] atol fails on ARTIK, returns 0 --- test/pwm_test.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/pwm_test.c b/test/pwm_test.c index 06ee48f..4dcf7f6 100644 --- a/test/pwm_test.c +++ b/test/pwm_test.c @@ -28,8 +28,8 @@ int main(int argc, char **argv) long period, duty_cycle; chip = argc > 1 ? atoi(argv[1]) : PWM_OUTPUT_CHIP; output = argc > 2 ? atoi(argv[2]) : PWM_CHIP_OUTPUT; - period = argc > 3 ? atol(argv[3]) : 10; - duty_cycle = argc > 4 ? atol(argv[4]) : 5; + period = argc > 3 ? atoi(argv[3]) : 10; + duty_cycle = argc > 4 ? atoi(argv[4]) : 5; libsoc_set_debug(1); fprintf(stderr, "Initializing PWM with parameters %d, %d, %d, %d\n", chip, output, period, duty_cycle); From 9ca3242c12b90dbe78084028af7b644655ee6492 Mon Sep 17 00:00:00 2001 From: John Comeau Date: Thu, 20 Jul 2017 19:03:41 -0700 Subject: [PATCH 53/60] turns out the problem with atol wasn't. I just entered the args as for the Python test, "0 2 shared normal 11111 5555" which is why I was getting 0 for the 3rd and 4th numbers. still trying to find out why pwm_test.py doesn't set given values. --- bindings/python/pwm.py | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/bindings/python/pwm.py b/bindings/python/pwm.py index 0d7b376..2e58890 100644 --- a/bindings/python/pwm.py +++ b/bindings/python/pwm.py @@ -28,7 +28,7 @@ class PWM(object): Example of use: with PWM(0, 0) as pwm: - pwm.write(.25) + pwm.enable = 1 ''' def __init__(self, chip, pin, mode='shared', **kwargs): ''' @@ -76,10 +76,12 @@ def open(self): Opens a file descriptor to the GPIO and configures it. ''' assert self._pwm is None + logging.debug('Opening PWM for use') self._pwm = api.libsoc_pwm_request(self.chip, self.pin, MODE[self.mode]) if self._pwm == 0: # NULL from native code raise IOError( 'Unable to open pwm chip(%d) pin(%d)' % (self.chip, self.pin)) + logging.debug('Setting values: %s', self.kwargs) if self.kwargs.get('period') is not None: logging.debug('setting period to %s', self.kwargs['period']) self.period = self.kwargs['period'] @@ -94,7 +96,12 @@ def open(self): self.enabled = self.kwargs['enabled'] def close(self): - '''Cleans up the memory and resources allocated by the open method.''' + ''' + Cleans up the memory and resources allocated by the open method. + + Note that in "shared" mode it does not unexport the pin: see + lib/pwm.c. + ''' if self._pwm: api.libsoc_pwm_free(self._pwm) self._pwm = None From baef0f8f4f6ef3eea4cc4b8b5a25c9ef700a2f66 Mon Sep 17 00:00:00 2001 From: John Comeau Date: Thu, 20 Jul 2017 19:12:46 -0700 Subject: [PATCH 54/60] changed order to match pwm_test.c, maybe fixed settings problem --- bindings/python/pwm.py | 2 +- test/pwm_test.py | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/bindings/python/pwm.py b/bindings/python/pwm.py index 2e58890..6380969 100644 --- a/bindings/python/pwm.py +++ b/bindings/python/pwm.py @@ -43,7 +43,7 @@ def __init__(self, chip, pin, mode='shared', **kwargs): self.chip = chip self.pin = pin self.mode = mode - self.kwargs = locals() + self.kwargs = kwargs logging.debug('self.kwargs: %s', self.kwargs) self._pwm = None diff --git a/test/pwm_test.py b/test/pwm_test.py index 73f7f3e..74137a7 100755 --- a/test/pwm_test.py +++ b/test/pwm_test.py @@ -10,8 +10,8 @@ PWM.set_debug(__debug__) logging.basicConfig(level=logging.DEBUG if __debug__ else logging.INFO) -def test_pwm(chip=0, pin=1, mode='shared', polarity='normal', period=1000, - duty_cycle=500, enabled=False): +def test_pwm(chip=0, pin=1, period=10, duty_cycle=5, + mode='shared', polarity='normal', enabled=False): ''' Duplicate pwm_test.c ''' @@ -52,10 +52,10 @@ def safe_int(string): You can set chip and pin number on the command line Also other properties in this order: - mode: 'shared', 'greedy', or 'weak' - polarity: 'normal' or 'inverse' period: an integer up to hardware limit (1000000000 for ARTIK7) duty_cycle: an integer up to `period` + mode: 'shared', 'greedy', or 'weak' + polarity: 'normal' or 'inverse' enabled: 1 (on) or 0 (off) ''' test_pwm(*sys.argv[1:]) From d8478cd67b94b25a440d831afeaa6aaadbd469e2 Mon Sep 17 00:00:00 2001 From: John Comeau Date: Thu, 20 Jul 2017 19:16:30 -0700 Subject: [PATCH 55/60] fixing misleading "error" in pwm.c --- .gitignore | 1 + lib/pwm.c | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 301e929..23b89b9 100644 --- a/.gitignore +++ b/.gitignore @@ -25,6 +25,7 @@ test/gpio_test test/spi_test test/i2c_test test/pwm_test +test/adc_test libtool libsoc.pc *.la diff --git a/lib/pwm.c b/lib/pwm.c index 8f03b20..9e08840 100644 --- a/lib/pwm.c +++ b/lib/pwm.c @@ -347,7 +347,7 @@ int libsoc_pwm_get_polarity(pwm *pwm) polarity = POLARITY_ERROR; } - if (polarity > 0) + if (polarity > -1) { libsoc_pwm_debug(__func__, pwm->chip, pwm->pwm, "got polarity as %s", pwm_polarity_strings[polarity]); } From fef36ceb5a3a2a6c23f1d960e906b14a6d5c9f59 Mon Sep 17 00:00:00 2001 From: John Comeau Date: Fri, 21 Jul 2017 08:14:58 -0700 Subject: [PATCH 56/60] make it easier to test individual ADCs --- test/adc_test.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/test/adc_test.c b/test/adc_test.c index 84f854c..fd4602f 100644 --- a/test/adc_test.c +++ b/test/adc_test.c @@ -18,18 +18,18 @@ * developer-guide/gpio/kernel-gpio.html */ -#define ADC_OUTPUT_CHIP 0 -#define ADC_PIN 0 - -int main(void) +int main(int argc, char *argv[]) { int ret = EXIT_FAILURE; adc *adc; - int value; + int chip = 0, pin = 0, value; + + if (argc > 1) chip = atoi(argv[1]); + if (argc > 2) pin = atoi(argv[2]); libsoc_set_debug(1); - adc = libsoc_adc_request(ADC_OUTPUT_CHIP, ADC_PIN); + adc = libsoc_adc_request(chip, pin); if (!adc) { From 63c091534f708241e8b98f0f2ef06c4fdc8f9f81 Mon Sep 17 00:00:00 2001 From: John Comeau Date: Fri, 21 Jul 2017 08:25:25 -0700 Subject: [PATCH 57/60] fixed conversion of 0 to None --- test/pwm_test.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/test/pwm_test.py b/test/pwm_test.py index 74137a7..e38a6ff 100755 --- a/test/pwm_test.py +++ b/test/pwm_test.py @@ -15,6 +15,7 @@ def test_pwm(chip=0, pin=1, period=10, duty_cycle=5, ''' Duplicate pwm_test.c ''' + logging.debug('locals(): %s', locals()) kwargs = {k: safe_int(v) for k, v in locals().items()} logging.debug('kwargs: %s', kwargs) with PWM(**kwargs) as pwm: @@ -38,6 +39,8 @@ def safe_int(string): ''' Returns an int if it parses as one, otherwise a string ''' + if isinstance(string, int): + return string try: number = literal_eval(string) if isinstance(number, int): From 61363310da9a178647239326ae25abad7fa89054 Mon Sep 17 00:00:00 2001 From: John Comeau Date: Fri, 21 Jul 2017 08:31:20 -0700 Subject: [PATCH 58/60] eliminate unnecessary traceback --- test/pwm_test.py | 36 ++++++++++++++++++++---------------- 1 file changed, 20 insertions(+), 16 deletions(-) diff --git a/test/pwm_test.py b/test/pwm_test.py index e38a6ff..90a7d59 100755 --- a/test/pwm_test.py +++ b/test/pwm_test.py @@ -18,22 +18,26 @@ def test_pwm(chip=0, pin=1, period=10, duty_cycle=5, logging.debug('locals(): %s', locals()) kwargs = {k: safe_int(v) for k, v in locals().items()} logging.debug('kwargs: %s', kwargs) - with PWM(**kwargs) as pwm: - for key in kwargs: - value = getattr(pwm, key) - logging.debug('Check value %s for pwm.%s', value, key) - pwm.duty_cycle = pwm.period + pwm.duty_cycle - if pwm.duty_cycle != pwm.duty_cycle: - logging.error('PWM allowed a duty cycle > 100%') - else: - logging.debug('PWM properly rejected >100% duty cycle') - pass - pwm.on() - if not pwm.enabled: - logging.error('The PWM would not turn on') - pwm.off() - if pwm.enabled: - logging.error('The PWM would not shut off') + try: + with PWM(**kwargs) as pwm: + for key in kwargs: + value = getattr(pwm, key) + logging.debug('Check value %s for pwm.%s', value, key) + pwm.duty_cycle = pwm.period + pwm.duty_cycle + if pwm.duty_cycle != pwm.duty_cycle: + logging.error('PWM allowed a duty cycle > 100%') + else: + logging.debug('PWM properly rejected >100% duty cycle') + pass + pwm.on() + if not pwm.enabled: + logging.error('The PWM would not turn on') + pwm.off() + if pwm.enabled: + logging.error('The PWM would not shut off') + except IOError: + logging.fatal('No such PWM %s was found', kwargs) + sys.exit(1) def safe_int(string): ''' From 9097884887ead176de74f0ac245885e3689eb16c Mon Sep 17 00:00:00 2001 From: John Comeau Date: Fri, 21 Jul 2017 08:44:37 -0700 Subject: [PATCH 59/60] maybe fixed segfault bug --- lib/adc.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/lib/adc.c b/lib/adc.c index 48c5d47..f67d633 100644 --- a/lib/adc.c +++ b/lib/adc.c @@ -82,17 +82,17 @@ adc* libsoc_adc_request (unsigned int chip, unsigned int adc_num) libsoc_adc_debug(__func__, chip, adc_num, "Found requested ADC"); new_adc = malloc(sizeof(adc)); new_adc->fd = file_open(adc_str, O_RDONLY); - } - if (new_adc->fd < 0) - { - free(new_adc); - libsoc_adc_debug(__func__, chip, adc_num, - "Failed to open adc sysfs file: %d", new_adc->fd); - return NULL; + if (new_adc->fd < 0) + { + free(new_adc); + libsoc_adc_debug(__func__, chip, adc_num, + "Failed to open adc sysfs file: %d", new_adc->fd); + return NULL; + } + new_adc->chip = chip; + new_adc->adc = adc_num; + return new_adc; } - new_adc->chip = chip; - new_adc->adc = adc_num; - return new_adc; } } } From d3c457cfccce8e0af2ea4664a54d5a1ab555c104 Mon Sep 17 00:00:00 2001 From: John Comeau Date: Fri, 21 Jul 2017 08:46:49 -0700 Subject: [PATCH 60/60] another segfault hopefully fixed :le sigh: --- lib/adc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/adc.c b/lib/adc.c index f67d633..a35042c 100644 --- a/lib/adc.c +++ b/lib/adc.c @@ -64,7 +64,7 @@ adc* libsoc_adc_request (unsigned int chip, unsigned int adc_num) if (file_valid(chip_str)) { libsoc_adc_debug(__func__, chip, adc_num, "Found requested chip"); - for (j = 0; j < sizeof(ADC_READ_FORMAT); j++) + for (j = 0; j < LENGTH(ADC_READ_FORMAT); j++) { libsoc_adc_debug (__func__, chip, adc_num, "trying pin format string %d", j);