├── .gitignore ├── MANIFEST.in ├── README.rst ├── fbsd_gpio ├── __init__.py ├── constant.py └── spibb.py ├── generate.py ├── setup.py └── tox.ini /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | 6 | # C extensions 7 | *.so 8 | 9 | # Distribution / packaging 10 | .Python 11 | env/ 12 | build/ 13 | develop-eggs/ 14 | dist/ 15 | downloads/ 16 | eggs/ 17 | .eggs/ 18 | lib/ 19 | lib64/ 20 | parts/ 21 | sdist/ 22 | var/ 23 | *.egg-info/ 24 | .installed.cfg 25 | *.egg 26 | 27 | # PyInstaller 28 | # Usually these files are written by a python script from a template 29 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 30 | *.manifest 31 | *.spec 32 | 33 | # Installer logs 34 | pip-log.txt 35 | pip-delete-this-directory.txt 36 | 37 | # Unit test / coverage reports 38 | htmlcov/ 39 | .tox/ 40 | .coverage 41 | .coverage.* 42 | .cache 43 | nosetests.xml 44 | coverage.xml 45 | *,cover 46 | .hypothesis/ 47 | 48 | # Translations 49 | *.mo 50 | *.pot 51 | 52 | # Django stuff: 53 | *.log 54 | 55 | # Sphinx documentation 56 | docs/_build/ 57 | 58 | # PyBuilder 59 | target/ 60 | 61 | #Ipython Notebook 62 | .ipynb_checkpoints 63 | -------------------------------------------------------------------------------- /MANIFEST.in: -------------------------------------------------------------------------------- 1 | include generate.py 2 | -------------------------------------------------------------------------------- /README.rst: -------------------------------------------------------------------------------- 1 | fbsd_gpio: cffi-based Python bindings for FreeBSD libgpio 2 | ========================================================= 3 | 4 | Requirements: 5 | 6 | - Python 2.7 or 3.4 7 | - cffi 8 | 9 | How to install 10 | -------------- 11 | 12 | Python package on FreeBSD 11 have problem when using python source that needed to compile thing, so the easiest way is to use the binary packages uploaded to pypi: 13 | 14 | .. code-block:: shell 15 | 16 | pip install --only-binary freebsd-11 fbsd_gpio 17 | 18 | How to use 19 | ---------- 20 | 21 | The fbsd_gpio module expose two classes, GpioController and GpioPin 22 | 23 | Use gpio controller unit 0 (/dev/gpioc0) and list all the pins name: 24 | 25 | .. code-block:: python 26 | 27 | from fbsd_gpio import GpioController 28 | 29 | gpioc = GpioController(0) 30 | for pin in gpioc: 31 | print(pin) 32 | 33 | Set pin 127 to output and logical value 1 34 | 35 | .. code-block:: python 36 | 37 | from fbsd_gpio import GpioController, GPIO_VALUE_HIGH 38 | 39 | gpioc = GpioController(0) 40 | gpioc.pin_output(127) 41 | # The two following lines are equivalent 42 | gpioc.pin_set(127, GPIO_VALUE_HIGH) 43 | gpioc.pin_high(127) 44 | 45 | Alternativelly you can use the GpioPin class: 46 | 47 | .. code-block:: python 48 | 49 | from fbsd_gpio import GpioPin, GPIO_VALUE_HIGH 50 | 51 | pin = GpioPin(127, unit=0) 52 | pin.ouput = True 53 | # The following lines are equivalent 54 | pin.set(GPIO_VALUE_HIGH) 55 | pin.high() 56 | pin(GPIO_VALUE_HIGH) 57 | 58 | Or use the name of the pin directly: 59 | 60 | .. code-block:: python 61 | 62 | from fbsd_gpio import GpioController, GPIO_VALUE_HIGH 63 | 64 | gpioc = GpioController(0) 65 | gpioc.gpioled0.output = True 66 | # The three following lines are equivalent 67 | gpioc.gpioled.set(GPIO_VALUE_HIGH) 68 | gpioc.gpioled0.high() 69 | gpioc.gpioled0(GPIO_VALUE_HIGH) 70 | 71 | Get the value of a pin: 72 | 73 | .. code-block:: python 74 | 75 | from fbsd_gpio import GpioPin 76 | 77 | pin = GpioPin(128, unit=0) 78 | if pin.input: 79 | print('Pin is input mode') 80 | else 81 | print('Pin is output mode') 82 | # The two following lines are equivalent 83 | value = pin.get() 84 | value = pin() 85 | 86 | Toggle the value of a pin: 87 | 88 | .. code-block:: python 89 | 90 | from fbsd_gpio import GpioPin 91 | 92 | pin = GpioPin(128, unit=0) 93 | pin.toggle() 94 | 95 | Change the name of a pin: 96 | 97 | .. code-block:: python 98 | 99 | from fbsd_gpio import GpioPin 100 | 101 | pin = GpioPin(128, unit=0) 102 | pin.name = 'green_led' 103 | -------------------------------------------------------------------------------- /fbsd_gpio/__init__.py: -------------------------------------------------------------------------------- 1 | from _fbsd_gpio import ffi, lib as _gpio 2 | 3 | from .constant import * 4 | 5 | 6 | GPIOCONTROLLERPOOL = {} 7 | 8 | 9 | class GpioController(object): 10 | def __init__(self, unit): 11 | """GpioController __init__ 12 | :param: unit The GPIO controller unit to operate on 13 | """ 14 | self._handle = None 15 | self._unit = unit 16 | 17 | def __del__(self): 18 | self.close() 19 | 20 | def __getattr__(self, pinname): 21 | """Magic method to obtain a GpioPin by it's name 22 | :param pinname: The pin name 23 | :returns: A GpioPin object 24 | """ 25 | pin_list = self.pin_list() 26 | for pin in pin_list: 27 | if pin.name == pinname: 28 | return pin 29 | raise AttributeError 30 | 31 | def __iter__(self): 32 | """Yield every pin available by this controller 33 | """ 34 | pin_list = self.pin_list() 35 | for pin in pin_list: 36 | yield pin 37 | 38 | def open(self): 39 | """Obtain an handle for the gpio controller 40 | """ 41 | try: 42 | if GPIOCONTROLLERPOOL[self._unit]['handle'] != -1: 43 | GPIOCONTROLLERPOOL[self._unit]['ref'] = GPIOCONTROLLERPOOL[self._unit]['ref'] + 1 44 | return 45 | except KeyError: 46 | GPIOCONTROLLERPOOL[self._unit] = {} 47 | GPIOCONTROLLERPOOL[self._unit]['handle'] = _gpio.gpio_open(self._unit) 48 | if GPIOCONTROLLERPOOL[self._unit]['handle'] == -1: 49 | del GPIOCONTROLLERPOOL[self._unit] 50 | raise IOError 51 | GPIOCONTROLLERPOOL[self._unit]['ref'] = 1 52 | 53 | def close(self): 54 | """Close the handle for the gpio controller 55 | """ 56 | try: 57 | GPIOCONTROLLERPOOL[self._unit]['ref'] = GPIOCONTROLLERPOOL[self._unit]['ref'] - 1 58 | if GPIOCONTROLLERPOOL[self._unit]['ref'] == 0: 59 | _gpio.gpio_close(GPIOCONTROLLERPOOL[self._unit]['handle']) 60 | del GPIOCONTROLLERPOOL[self._unit] 61 | except KeyError: 62 | pass 63 | 64 | @property 65 | def handle(self): 66 | """The handle for the gpio controller 67 | :returns: The handle 68 | """ 69 | try: 70 | return GPIOCONTROLLERPOOL[self._unit]['handle'] 71 | except KeyError: 72 | self.open() 73 | return GPIOCONTROLLERPOOL[self._unit]['handle'] 74 | 75 | def pin_config(self, pin): 76 | """Get the pin configuration 77 | :param pin: The pin number 78 | :returns: The capabilities, flags and name 79 | """ 80 | pin_cfg = ffi.new('gpio_config_t *') 81 | pin_cfg.g_pin = pin 82 | if _gpio.gpio_pin_config(self.handle, pin_cfg) != 0: 83 | raise ValueError 84 | 85 | caps = [] 86 | for cap in GPIO_CAPS: 87 | if pin_cfg.g_caps & cap: 88 | caps.append(cap) 89 | 90 | flags = [] 91 | for cap in GPIO_CAPS: 92 | if pin_cfg.g_flags & cap: 93 | flags.append(cap) 94 | 95 | return caps, flags, ffi.string(pin_cfg.g_name).decode('utf8') 96 | 97 | def pin_get_caps(self, pin): 98 | """Get the pin capabilities 99 | :param pin: The pin number 100 | :returns: The capabilities 101 | """ 102 | 103 | return self.pin_config(pin)[0] 104 | 105 | def pin_get_flags(self, pin): 106 | """Get the pin current settings 107 | :param pin: The pin number 108 | :returns: The settings 109 | """ 110 | 111 | return self.pin_config(pin)[1] 112 | 113 | def pin_set_flags(self, pin, flags): 114 | """Set pin configuration flags 115 | :param pin: The pin number 116 | :param flags: The pin flags 117 | """ 118 | pin_cfg = ffi.new('gpio_config_t *') 119 | pin_cfg.g_pin = pin 120 | pin_cfg.g_flags = flags 121 | if _gpio.gpio_pin_set_flags(self.handle, pin_cfg) != 0: 122 | raise ValueError 123 | 124 | def pin_set_name(self, pin, name): 125 | """Set the name of the pin 126 | :param name: The name 127 | """ 128 | if _gpio.gpio_pin_set_name(self.handle, pin, name) != 0: 129 | raise IOError 130 | 131 | def pin_low(self, pin): 132 | """Set the pin value to 0 133 | :param pin: The pin number 134 | """ 135 | if _gpio.gpio_pin_low(self.handle, pin) != 0: 136 | raise IOError 137 | 138 | def pin_high(self, pin): 139 | """Set the pin value to 1 140 | :param pin: The pin number 141 | """ 142 | if _gpio.gpio_pin_high(self.handle, pin) != 0: 143 | raise IOError 144 | 145 | def pin_toggle(self, pin): 146 | """Toggle the value of the pin 147 | :param pin: The pin number 148 | """ 149 | if _gpio.gpio_pin_toggle(self.handle, pin) != 0: 150 | raise IOError 151 | 152 | def pin_input(self, pin): 153 | """Set the pin to input mode 154 | :param pin: The pin number 155 | """ 156 | if _gpio.gpio_pin_input(self.handle, pin) != 0: 157 | raise IOError 158 | 159 | def pin_output(self, pin): 160 | """Set the pin to output mode 161 | :param pin: The pin number 162 | """ 163 | if _gpio.gpio_pin_output(self.handle, pin) != 0: 164 | raise IOError 165 | 166 | def pin_set(self, pin, value): 167 | """Set the pin value 168 | :param pin: The pin number 169 | ;param value: The value to be set (0 or 1) 170 | """ 171 | if value not in GPIO_VALUES: 172 | raise ValueError 173 | if _gpio.gpio_pin_set(self.handle, pin, value) != 0: 174 | raise IOError 175 | 176 | def pin_get(self, pin): 177 | """Get the value of the pin 178 | :param pin: The pin number 179 | :returns: The value 180 | """ 181 | ret = _gpio.gpio_pin_get(self.handle, pin) 182 | if ret == -1: 183 | raise IOError 184 | return ret 185 | 186 | def pin_list(self): 187 | """Get a list of GpioPin object that the controller manages 188 | :returns: The list of GpioPin 189 | """ 190 | i = 0 191 | pin_list = [] 192 | while True: 193 | try: 194 | pin = GpioPin(i, controller=self) 195 | except ValueError: 196 | break 197 | pin_list.append(pin) 198 | i = i + 1 199 | 200 | return pin_list 201 | 202 | def pin(self, num): 203 | """Return a GpioPin based on the number 204 | :param num: The pin number 205 | :returns: A GpioPin object 206 | """ 207 | return GpioPin(num, controller=self) 208 | 209 | def pin_exists(self, num): 210 | """Test if a pin exists in the gpio controller 211 | :param num: THe pin number 212 | """ 213 | 214 | try: 215 | self.pin_config(num) 216 | except ValueError: 217 | return False 218 | return True 219 | 220 | def wait_for_event(self, pin, events, poll=0.1): 221 | """Blocking function to wait for a event 222 | :param pin: The pin number 223 | :param events: The events to wait for 224 | :param poll: THe time between checks 225 | :returns: The triggered event 226 | """ 227 | 228 | for event in events: 229 | if event not in GPIO_EVENTS: 230 | raise ValueError 231 | 232 | from time import sleep 233 | 234 | value = self.pin_get(pin) 235 | while True: 236 | sleep(poll) 237 | newvalue = self.pin_get(pin) 238 | event = 0 239 | if value == GPIO_VALUE_LOW and newvalue == GPIO_VALUE_HIGH: 240 | event = GPIO_EVENT_RISING 241 | elif value == GPIO_VALUE_HIGH and newvalue == GPIO_VALUE_LOW: 242 | event = GPIO_EVENT_FALLING 243 | if event in events: 244 | return event 245 | value = newvalue 246 | 247 | 248 | class GpioPin(object): 249 | def __init__(self, num, unit=None, controller=None): 250 | """GpioPin __init__ 251 | :param num: The pin number 252 | :param unit: The controller unit number 253 | :param controller: The GpioController object 254 | """ 255 | self._num = num 256 | self._controller = controller 257 | if unit is not None: 258 | self._controller = GpioController(unit) 259 | 260 | if not self._controller: 261 | raise ValueError 262 | 263 | if self._controller.pin_exists(num) == False: 264 | raise ValueError 265 | 266 | def __repr__(self): 267 | """Return the name as the representation 268 | """ 269 | return self.name 270 | 271 | def __call__(self, value=None): 272 | """Set or get the value of the pin 273 | :param value: If set, set the value of the pin 274 | """ 275 | if value: 276 | self._controller.pin_set(self._num, value) 277 | return self._controller.pin_get(self._num) 278 | 279 | @property 280 | def name(self): 281 | """Return the name of the pin 282 | """ 283 | return self._controller.pin_config(self._num)[2] 284 | 285 | @name.setter 286 | def name(self, name): 287 | """Set the name of the pin 288 | :param name: The name 289 | """ 290 | self._controller.pin_set_name(self._num, name) 291 | 292 | @property 293 | def input(self): 294 | """Returns True if the pin is in input mode 295 | """ 296 | if GPIO_PIN_INPUT in self.flags: 297 | return True 298 | return False 299 | 300 | @input.setter 301 | def input(self, input): 302 | """Set the pin mode to input 303 | :param input: True to set it to input, False to set it to output 304 | """ 305 | if input: 306 | self._controller.pin_input(self._num) 307 | else: 308 | self._controller.pin_output(self._num) 309 | 310 | @property 311 | def output(self): 312 | """Returns True if the pin is in output mode 313 | """ 314 | if GPIO_PIN_OUTPUT in self.flags: 315 | return True 316 | return False 317 | 318 | @output.setter 319 | def output(self, output): 320 | """Set the pin mode to output 321 | :param output: True to set it to output, False to set it to input 322 | """ 323 | if output: 324 | self._controller.pin_output(self._num) 325 | else: 326 | self._controller.pin_input(self._num) 327 | 328 | @property 329 | def caps(self): 330 | """Returns the pin capabilities 331 | """ 332 | 333 | return self._controller.pin_get_caps(self._num) 334 | 335 | @property 336 | def flags(self): 337 | """Returns the pin configuration flags 338 | """ 339 | 340 | return self._controller.pin_get_flags(self._num) 341 | 342 | @flags.setter 343 | def flags(self, flags): 344 | """Set the pin configuration flags 345 | """ 346 | self._controller.pin_set_flags(self._num, flags) 347 | 348 | def low(self): 349 | """Set the pin to low 350 | """ 351 | self._controller.pin_low(self._num) 352 | 353 | def high(self): 354 | """Set the pin to high 355 | """ 356 | self._controller.pin_high(self._num) 357 | 358 | def toggle(self): 359 | """Toggle the pin value 360 | """ 361 | self._controller.pin_toggle(self._num) 362 | 363 | def set(self, value): 364 | """Set the pin value 365 | :param value: The value 366 | """ 367 | self._controller.pin_set(self._num, value) 368 | 369 | def get(self): 370 | """Get the pin value 371 | """ 372 | return self._controller.pin_get(self._num) 373 | 374 | def wait_for_event(self, events, poll=0.1): 375 | """Block until event 376 | :param events: The events to wait for 377 | :param poll: The time between checks 378 | :returns: The triggered event 379 | """ 380 | return self._controller.wait_for_event(self._num, events, poll=poll) 381 | -------------------------------------------------------------------------------- /fbsd_gpio/constant.py: -------------------------------------------------------------------------------- 1 | # 2 | # Pin caps/flags 3 | # 4 | GPIO_PIN_INPUT = 0x1 5 | GPIO_PIN_OUTPUT = 0x2 6 | GPIO_PIN_OPENDRAIN = 0x4 7 | GPIO_PIN_PUSHPULL = 0x8 8 | GPIO_PIN_TRISTATE = 0x10 9 | GPIO_PIN_PULLUP = 0x20 10 | GPIO_PIN_PULLDOWN = 0x40 11 | GPIO_PIN_INVIN = 0x80 12 | GPIO_PIN_INVOUT = 0x100 13 | GPIO_PIN_PULSTATE = 0x200 14 | 15 | GPIO_CAPS = [GPIO_PIN_INPUT, 16 | GPIO_PIN_OUTPUT, 17 | GPIO_PIN_OPENDRAIN, 18 | GPIO_PIN_PUSHPULL, 19 | GPIO_PIN_TRISTATE, 20 | GPIO_PIN_PULLUP, 21 | GPIO_PIN_PULLDOWN, 22 | GPIO_PIN_INVIN, 23 | GPIO_PIN_INVOUT, 24 | GPIO_PIN_PULSTATE] 25 | 26 | # 27 | # Pin Values 28 | # 29 | GPIO_VALUE_LOW = 0 30 | GPIO_VALUE_HIGH = 1 31 | 32 | GPIO_VALUES = [GPIO_VALUE_LOW, GPIO_VALUE_HIGH] 33 | 34 | # 35 | # Event related value 36 | # 37 | GPIO_EVENT_FALLING = 0x1 38 | GPIO_EVENT_RISING = 0x2 39 | 40 | GPIO_EVENTS = [GPIO_EVENT_RISING, GPIO_EVENT_FALLING] 41 | -------------------------------------------------------------------------------- /fbsd_gpio/spibb.py: -------------------------------------------------------------------------------- 1 | from time import sleep 2 | 3 | from fbsd_gpio import ( 4 | GpioPin, 5 | GPIO_PIN_PULLDOWN, 6 | GPIO_PIN_PULLUP, 7 | ) 8 | 9 | SPI_MODE_NONE = 0 10 | SPI_MODE_CPHA = 1 11 | SPI_MODE_CPOL = 2 12 | SPI_MODE_CPOL_CPHA = 3 13 | 14 | 15 | class GpioSPIBB(object): 16 | def __init__(self, sclk, mosi, miso, ss, mode=0): 17 | self._sclk = GpioPin(sclk[1], unit=sclk[0]) 18 | self._mosi = GpioPin(mosi[1], unit=mosi[0]) 19 | self._miso = GpioPin(miso[1], unit=miso[0]) 20 | self._ss = GpioPin(ss[1], unit=ss[0]) 21 | 22 | self._sclk.output = True 23 | self._sclk.flags = GPIO_PIN_PULLDOWN 24 | self._mosi.output = True 25 | self._mosi.flags = GPIO_PIN_PULLDOWN 26 | self._miso.input = True 27 | self._miso.flags = GPIO_PIN_PULLDOWN 28 | self._ss.output = True 29 | self._ss.flags = GPIO_PIN_PULLUP 30 | 31 | self._ss.high() 32 | self._mode = mode 33 | 34 | def transfer_byte(self, data): 35 | """Transfer a byte 36 | :param data: The byte to transfer 37 | :returns: The byte that was read 38 | """ 39 | bitmask = 0x80 40 | ret = 0 41 | for i in range(0, 8): 42 | if data & bitmask: 43 | self._mosi.high() 44 | else: 45 | self._mosi.low() 46 | 47 | self._sclk.toggle() 48 | sleep(0.0001) 49 | ret = ret << 1 50 | if self._miso(): 51 | ret = ret | 1 52 | self._sclk.toggle() 53 | sleep(0.0001) 54 | 55 | bitmask = bitmask >> 1 56 | return ret 57 | 58 | def transfer_begin(self): 59 | """Begin a transfer""" 60 | self._ss.low() 61 | 62 | if self._mode == SPI_MODE_CPOL or self._mode == SPI_MODE_CPHA: 63 | self._sclk.high() 64 | else: 65 | self._sclk.low() 66 | 67 | def transfer_end(self): 68 | """End a transfer""" 69 | if self._mode == SPI_MODE_CPOL or self._mode == SPI_MODE_CPHA: 70 | self._sclk.high() 71 | else: 72 | self._sclk.low() 73 | self._ss.high() 74 | 75 | def transfer(self, data): 76 | """Do an SPI transfer 77 | :param data: A list of byte to transfer 78 | :returns: The list a read bytes 79 | """ 80 | self.transfer_begin() 81 | 82 | ret = [] 83 | for b in data: 84 | ret.append(self.transfer_byte(b)) 85 | 86 | self.transfer_end() 87 | 88 | return ret 89 | -------------------------------------------------------------------------------- /generate.py: -------------------------------------------------------------------------------- 1 | from cffi import FFI 2 | ffi = FFI() 3 | 4 | ffi.set_source("_fbsd_gpio", 5 | """ 6 | #include 7 | #include 8 | """, 9 | libraries=['gpio']) 10 | 11 | ffi.cdef(""" 12 | /* From sys/gpio.h and libgpio.h */ 13 | /* Copyright (c) 2009, Oleksandr Tymoshenko */ 14 | /* Copyright (c) 2013-2014 Rui Paulo */ 15 | /* Copyright (c) 2009 Marc Balmer */ 16 | /* Copyright (c) 2004 Alexander Yurchenko */ 17 | 18 | /* GPIO pin states */ 19 | #define GPIO_PIN_LOW 0x00 /* low level (logical 0) */ 20 | #define GPIO_PIN_HIGH 0x01 /* high level (logical 1) */ 21 | 22 | /* Max name length of a pin */ 23 | #define GPIOMAXNAME 64 24 | 25 | #define GPIO_INVALID_HANDLE -1 26 | typedef int gpio_handle_t; 27 | typedef uint32_t gpio_pin_t; 28 | 29 | /* 30 | * Structure describing a GPIO pin configuration. 31 | */ 32 | typedef struct { 33 | gpio_pin_t g_pin; 34 | char g_name[GPIOMAXNAME]; 35 | uint32_t g_caps; 36 | uint32_t g_flags; 37 | } gpio_config_t; 38 | 39 | typedef enum { 40 | GPIO_VALUE_INVALID = -1, 41 | GPIO_VALUE_LOW = GPIO_PIN_LOW, 42 | GPIO_VALUE_HIGH = GPIO_PIN_HIGH 43 | } gpio_value_t; 44 | 45 | /* 46 | * Open /dev/gpiocN or a specific device. 47 | */ 48 | gpio_handle_t gpio_open(unsigned int); 49 | gpio_handle_t gpio_open_device(const char *); 50 | void gpio_close(gpio_handle_t); 51 | /* 52 | * Get a list of all the GPIO pins. 53 | */ 54 | int gpio_pin_list(gpio_handle_t, gpio_config_t **); 55 | /* 56 | * GPIO pin configuration. 57 | * 58 | * Retrieve the configuration of a specific GPIO pin. The pin number is 59 | * passed through the gpio_config_t structure. 60 | */ 61 | int gpio_pin_config(gpio_handle_t, gpio_config_t *); 62 | /* 63 | * Sets the GPIO pin name. The pin number and pin name to be set are passed 64 | * as parameters. 65 | */ 66 | int gpio_pin_set_name(gpio_handle_t, gpio_pin_t, char *); 67 | /* 68 | * Sets the GPIO flags on a specific GPIO pin. The pin number and the flags 69 | * to be set are passed through the gpio_config_t structure. 70 | */ 71 | int gpio_pin_set_flags(gpio_handle_t, gpio_config_t *); 72 | /* 73 | * GPIO pin values. 74 | */ 75 | int gpio_pin_get(gpio_handle_t, gpio_pin_t); 76 | int gpio_pin_set(gpio_handle_t, gpio_pin_t, int); 77 | int gpio_pin_toggle(gpio_handle_t, gpio_pin_t); 78 | /* 79 | * Helper functions to set pin states. 80 | */ 81 | int gpio_pin_low(gpio_handle_t, gpio_pin_t); 82 | int gpio_pin_high(gpio_handle_t, gpio_pin_t); 83 | /* 84 | * Helper functions to configure pins. 85 | */ 86 | int gpio_pin_input(gpio_handle_t, gpio_pin_t); 87 | int gpio_pin_output(gpio_handle_t, gpio_pin_t); 88 | int gpio_pin_opendrain(gpio_handle_t, gpio_pin_t); 89 | int gpio_pin_pushpull(gpio_handle_t, gpio_pin_t); 90 | int gpio_pin_tristate(gpio_handle_t, gpio_pin_t); 91 | int gpio_pin_pullup(gpio_handle_t, gpio_pin_t); 92 | int gpio_pin_pulldown(gpio_handle_t, gpio_pin_t); 93 | int gpio_pin_invin(gpio_handle_t, gpio_pin_t); 94 | int gpio_pin_invout(gpio_handle_t, gpio_pin_t); 95 | int gpio_pin_pulsate(gpio_handle_t, gpio_pin_t); 96 | """) 97 | 98 | if __name__ == "__main__": 99 | ffi.compile() 100 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | from setuptools import setup 2 | 3 | setup( 4 | name='fbsd_gpio', 5 | version='0.5.0', 6 | url='https://github.com/evadot/fbsd_gpio_py', 7 | license='BSD', 8 | author='Emmanuel Vadot', 9 | author_email='manu@bidouilliste.com', 10 | description='cffi-based Python bindings for FreeBSD GPIO', 11 | long_description=open('README.rst').read(), 12 | classifiers=[ 13 | 'Development Status :: 5 - Production/Stable', 14 | 'Intended Audience :: Developers', 15 | 'License :: OSI Approved :: BSD License', 16 | 'Operating System :: POSIX :: BSD :: FreeBSD', 17 | 'Programming Language :: Python', 18 | 'Programming Language :: Python :: 2.7', 19 | 'Programming Language :: Python :: 3', 20 | 'Programming Language :: Python :: 3.4', 21 | 'Programming Language :: Python :: Implementation :: CPython', 22 | ], 23 | keywords='FreeBSD GPIO', 24 | packages=['fbsd_gpio'], 25 | setup_requires=["cffi>=1.0.0"], 26 | cffi_modules=["generate.py:ffi"], 27 | install_requires=['cffi'], 28 | ) 29 | -------------------------------------------------------------------------------- /tox.ini: -------------------------------------------------------------------------------- 1 | [tox] 2 | envlist = flake8 3 | 4 | [testenv:flake8] 5 | deps = flake8 6 | commands = flake8 setup.py fbsd_gpio 7 | 8 | [flake8] 9 | max-line-length = 160 10 | exclude = tests/* 11 | max-complexity = 10 12 | ignore = F403 --------------------------------------------------------------------------------