├── pyA20 ├── __init__.py ├── gpio │ ├── __init__.py │ ├── port │ │ ├── __init__.py │ │ └── port.c │ ├── connector │ │ ├── __init__.py │ │ └── connector.c │ ├── mapping_has_mistake.h │ ├── mapping.h │ ├── gpio_lib.c │ ├── gpio_lib.h │ ├── gpio.c │ └── mapping.h.backA20.h ├── i2c │ ├── __init__.py │ ├── i2c_lib.h │ ├── i2c_lib.c │ └── i2c.c ├── spi │ ├── __init__.py │ ├── spi_lib.h │ ├── spi_lib.c │ └── spi.c └── utilities │ ├── color.h │ └── color.py ├── CHANGES.txt ├── README.md ├── examples ├── blink_led.py ├── blink_led_PG6.py ├── read_button.py ├── read_eeprom.py ├── blink_POWER_STATUS_PL10.py └── read_key_PG7.py ├── setup.py ├── README.txt └── PKG-INFO /pyA20/__init__.py: -------------------------------------------------------------------------------- 1 | __author__ = 'stefan' 2 | -------------------------------------------------------------------------------- /pyA20/gpio/__init__.py: -------------------------------------------------------------------------------- 1 | __author__ = 'stefan' 2 | -------------------------------------------------------------------------------- /pyA20/i2c/__init__.py: -------------------------------------------------------------------------------- 1 | __author__ = 'stefan' 2 | -------------------------------------------------------------------------------- /pyA20/spi/__init__.py: -------------------------------------------------------------------------------- 1 | __author__ = 'stefan' 2 | -------------------------------------------------------------------------------- /pyA20/gpio/port/__init__.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | """ 3 | """ 4 | 5 | import < Something > 6 | 7 | __author__ = "Stefan Mavrodiev" 8 | __copyright__ = "Copyright 2014, Olimex LTD" 9 | __credits__ = ["Stefan Mavrodiev"] 10 | __license__ = "GPL" 11 | __version__ = "2.0" 12 | __maintainer__ = __author__ 13 | __email__ = "support@olimex.com" -------------------------------------------------------------------------------- /pyA20/gpio/connector/__init__.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | """ 3 | """ 4 | 5 | import < Something > 6 | 7 | __author__ = "Stefan Mavrodiev" 8 | __copyright__ = "Copyright 2014, Olimex LTD" 9 | __credits__ = ["Stefan Mavrodiev"] 10 | __license__ = "GPL" 11 | __version__ = "2.0" 12 | __maintainer__ = __author__ 13 | __email__ = "support@olimex.com" -------------------------------------------------------------------------------- /CHANGES.txt: -------------------------------------------------------------------------------- 1 | Changelog 2 | ========= 3 | * pyA20 0.2.1 (30 JUN 2015) 4 | * Fixed gpio1 connector constants 5 | * Fixed issue with SPI xfer function 6 | 7 | * pyA20 0.2.0 (02 SEP 2014) 8 | * Updated to enable SPI and I2C control 9 | * GPIO constant in separate modules 10 | * Added example files 11 | * Added support for Python3 12 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # orangepi_PC_gpio_pyH3 2 | python control orangepi_PC ext GPIO ALLwinner H3 base on pyA20 0.2.1 3 | 4 | 5 | open source modified base on pyA20 6 | 7 | reference 8 | https://www.olimex.com/wiki/A20-OLinuXino-MICRO 9 | pyA20 10 | https://pypi.python.org/pypi/pyA20 11 | 12 | install :: 13 | 14 | python setup.py install 15 | 16 | 17 | 18 | author :duxingkei chow 19 | email :277563381@qq.com 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | -------------------------------------------------------------------------------- /pyA20/utilities/color.h: -------------------------------------------------------------------------------- 1 | #ifndef __COLOR_H 2 | #define __COLOR 3 | 4 | /* Text attributes */ 5 | #define ESC "\033[0m" 6 | #define BOLD "\033[1m" 7 | #define UNDER "\033[4m" 8 | #define BLINK "\033[5m" 9 | 10 | /* Foreground colors */ 11 | #define BLACK "\033[30m" 12 | #define RED "\033[31m" 13 | #define GREEN "\033[32m" 14 | #define YELLOW "\033[33m" 15 | #define BLUE "\033[34m" 16 | #define MAGENTA "\033[35m" 17 | #define CYAN "\033[36m" 18 | #define WHITE "\033]37m" 19 | 20 | /* Background colors*/ 21 | #define BBLACK "\033[40m" 22 | #define BRED "\033[41m" 23 | #define BGREEN "\033[42m" 24 | #define BYELLOW "\033[43m" 25 | #define BBLUE "\033[44m" 26 | #define BAGENTA "\033[45m" 27 | #define BCYAN "\033[46m" 28 | #define BWHITE "\033]47m" 29 | 30 | 31 | #endif -------------------------------------------------------------------------------- /examples/blink_led.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | """Basic blinking led example. 3 | 4 | The led on A20-OLinuXino-MICRO blinks with rate of 1Hz like "heartbeat". 5 | """ 6 | 7 | import os 8 | import sys 9 | 10 | if not os.getegid() == 0: 11 | sys.exit('Script must be run as root') 12 | 13 | 14 | from time import sleep 15 | from pyA20.gpio import gpio 16 | from pyA20.gpio import port 17 | 18 | __author__ = "Stefan Mavrodiev" 19 | __copyright__ = "Copyright 2014, Olimex LTD" 20 | __credits__ = ["Stefan Mavrodiev"] 21 | __license__ = "GPL" 22 | __version__ = "2.0" 23 | __maintainer__ = __author__ 24 | __email__ = "support@olimex.com" 25 | 26 | 27 | led = port.PA12 28 | 29 | gpio.init() 30 | gpio.setcfg(led, gpio.OUTPUT) 31 | 32 | try: 33 | print ("Press CTRL+C to exit") 34 | while True: 35 | gpio.output(led, 1) 36 | sleep(0.1) 37 | gpio.output(led, 0) 38 | sleep(0.1) 39 | 40 | gpio.output(led, 1) 41 | sleep(0.1) 42 | gpio.output(led, 0) 43 | sleep(0.1) 44 | 45 | sleep(0.6) 46 | except KeyboardInterrupt: 47 | print ("Goodbye.") -------------------------------------------------------------------------------- /examples/blink_led_PG6.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | """Basic blinking led example. 3 | 4 | The led on A20-OLinuXino-MICRO blinks with rate of 1Hz like "heartbeat". 5 | """ 6 | 7 | import os 8 | import sys 9 | 10 | if not os.getegid() == 0: 11 | sys.exit('Script must be run as root') 12 | 13 | 14 | from time import sleep 15 | from pyA20.gpio import gpio 16 | from pyA20.gpio import port 17 | 18 | __author__ = "Stefan Mavrodiev" 19 | __copyright__ = "Copyright 2014, Olimex LTD" 20 | __credits__ = ["Stefan Mavrodiev"] 21 | __license__ = "GPL" 22 | __version__ = "2.0" 23 | __maintainer__ = __author__ 24 | __email__ = "support@olimex.com" 25 | 26 | 27 | led = port.PG6 28 | 29 | gpio.init() 30 | gpio.setcfg(led, gpio.OUTPUT) 31 | 32 | try: 33 | print ("Press CTRL+C to exit") 34 | while True: 35 | gpio.output(led, 1) 36 | print "led set 1 \r\n" 37 | sleep(2) 38 | gpio.output(led, 0) 39 | print "led set 0 \r\n" 40 | sleep(2) 41 | """ 42 | gpio.output(led, 1) 43 | sleep(0.1) 44 | gpio.output(led, 0) 45 | sleep(0.1) 46 | 47 | sleep(0.6) 48 | """ 49 | except KeyboardInterrupt: 50 | print ("Goodbye.") -------------------------------------------------------------------------------- /pyA20/i2c/i2c_lib.h: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * This file is part of pyA20. 4 | * i2c_lib.h is python I2C extension. 5 | * 6 | * Copyright (c) 2014 Stefan Mavrodiev @ OLIMEX LTD, 7 | * 8 | * pyA20 is free software; you can redistribute it and/or modify 9 | * it under the terms of the GNU General Public License as published by 10 | * the Free Software Foundation; either version 2 of the License, or 11 | * (at your option) any later version. 12 | * 13 | * This program is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | * GNU General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU General Public License 19 | * along with this program; if not, write to the Free Software 20 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 21 | * MA 02110-1301, USA. 22 | */ 23 | 24 | #ifndef _I2C_LIB_H 25 | #define _I2C_LIB_H 26 | 27 | extern int i2c_open(char *device, uint8_t address); 28 | extern int i2c_close(int fd); 29 | extern int i2c_send(int fd, uint8_t *buffer, uint8_t num_bytes); 30 | extern int i2c_read(int fd, uint8_t *buffer, uint8_t num_bytes); 31 | 32 | #endif -------------------------------------------------------------------------------- /examples/read_button.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | """Read button. 3 | 4 | Make gpio input and enable pull-up resistor. 5 | """ 6 | 7 | import os 8 | import sys 9 | 10 | if not os.getegid() == 0: 11 | sys.exit('Script must be run as root') 12 | 13 | 14 | from pyA20.gpio import gpio 15 | from pyA20.gpio import connector 16 | from pyA20.gpio import port 17 | 18 | __author__ = "Stefan Mavrodiev" 19 | __copyright__ = "Copyright 2014, Olimex LTD" 20 | __credits__ = ["Stefan Mavrodiev"] 21 | __license__ = "GPL" 22 | __version__ = "2.0" 23 | __maintainer__ = __author__ 24 | __email__ = "support@olimex.com" 25 | 26 | led = connector.gpio0p0 # This is the same as port.PH2 27 | button = connector.gpio3p40 28 | 29 | """Init gpio module""" 30 | gpio.init() 31 | 32 | """Set directions""" 33 | gpio.setcfg(led, gpio.OUTPUT) 34 | gpio.setcfg(button, gpio.INPUT) 35 | 36 | """Enable pullup resistor""" 37 | gpio.pullup(button, gpio.PULLUP) 38 | #gpio.pullup(button, gpio.PULLDOWN) # Optionally you can use pull-down resistor 39 | 40 | try: 41 | print ("Press CTRL+C to exit") 42 | while True: 43 | state = gpio.input(button) # Read button state 44 | 45 | """Since we use pull-up the logic will be inverted""" 46 | gpio.output(led, not state) 47 | 48 | except KeyboardInterrupt: 49 | print ("Goodbye.") 50 | -------------------------------------------------------------------------------- /examples/read_eeprom.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | """Read from the EEPROM chip on A20-OLinuXino-MICRO 3 | 4 | On the board there is small chip U3. This is 16kb eeprom memory AT24C16BN. 5 | The i2c address can be different, but on this specific board is 0x50. 6 | 7 | The text will be big mess if python3 is used. 8 | """ 9 | 10 | from pyA20 import i2c 11 | 12 | __author__ = "Stefan Mavrodiev" 13 | __copyright__ = "Copyright 2014, Olimex LTD" 14 | __credits__ = ["Stefan Mavrodiev"] 15 | __license__ = "GPL" 16 | __version__ = "2.0" 17 | __maintainer__ = __author__ 18 | __email__ = "support@olimex.com" 19 | 20 | eeprom_address = 0x50 21 | 22 | """Initialize i2c bus""" 23 | i2c.init("/dev/i2c-1") 24 | i2c.open(eeprom_address) 25 | 26 | """Set address pointer to the first""" 27 | i2c.write([0x00]) 28 | 29 | print "Dump eeprom:" 30 | print "="*24 31 | 32 | print " ", 33 | for i in xrange(16): 34 | print " %x" % i, 35 | 36 | print "\t", 37 | for i in xrange(16): 38 | print "%x" % i, 39 | print "" 40 | 41 | """Print data""" 42 | for i in xrange(128): 43 | page = i2c.read(16) 44 | print "%03x:" % (i*0x10), 45 | for j in xrange(0, 16): 46 | print "%02x" % page[j], 47 | 48 | """Print characters""" 49 | print "\t", 50 | for j in xrange(16): 51 | if page[j] <= 126 and page[j] >= 32: 52 | print chr(page[j]), 53 | else: 54 | print '.', 55 | print "" 56 | 57 | i2c.close() -------------------------------------------------------------------------------- /pyA20/spi/spi_lib.h: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * This file is part of pyA20. 4 | * spi_lib.c is python SPI extension. 5 | * 6 | * Copyright (c) 2014 Stefan Mavrodiev @ OLIMEX LTD, 7 | * 8 | * pyA20 is free software; you can redistribute it and/or modify 9 | * it under the terms of the GNU General Public License as published by 10 | * the Free Software Foundation; either version 2 of the License, or 11 | * (at your option) any later version. 12 | * 13 | * This program is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | * GNU General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU General Public License 19 | * along with this program; if not, write to the Free Software 20 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 21 | * MA 02110-1301, USA. 22 | */ 23 | 24 | #ifndef _I2C_LIB_H 25 | #define _I2C_LIB_H 26 | 27 | #include 28 | 29 | typedef struct { 30 | uint8_t mode; 31 | uint8_t bits_per_word; 32 | uint32_t speed; 33 | uint16_t delay; 34 | } spi_config_t; 35 | 36 | extern int spi_open(char *device, spi_config_t config); 37 | extern int spi_close(int fd); 38 | extern int spi_xfer(int fd, uint8_t *tx_buffer, uint8_t tx_len, uint8_t *rx_buffer, uint8_t rx_len); 39 | extern int spi_read(int fd, uint8_t *rx_buffer, uint8_t rx_len); 40 | extern int spi_write(int fd, uint8_t *tx_buffer, uint8_t tx_len); 41 | 42 | 43 | #endif 44 | -------------------------------------------------------------------------------- /examples/blink_POWER_STATUS_PL10.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | """Basic blinking led example. 3 | 4 | The led on A20-OLinuXino-MICRO blinks with rate of 1Hz like "heartbeat". 5 | """ 6 | 7 | import os 8 | import sys 9 | 10 | if not os.getegid() == 0: 11 | sys.exit('Script must be run as root') 12 | 13 | 14 | from time import sleep 15 | from pyA20.gpio import gpio 16 | from pyA20.gpio import port 17 | #//BY CHOW 18 | from pyA20.gpio import connector 19 | 20 | __author__ = "Stefan Mavrodiev" 21 | __copyright__ = "Copyright 2014, Olimex LTD" 22 | __credits__ = ["Stefan Mavrodiev"] 23 | __license__ = "GPL" 24 | __version__ = "2.0" 25 | __maintainer__ = __author__ 26 | __email__ = "support@olimex.com" 27 | 28 | 29 | # 30 | """ 31 | */ {"LED", 32 | { 33 | { "POWER_LED", SUNXI_GPL(10), 1 }, 34 | { "STATUS_LED", SUNXI_GPA(15), 2 }, 35 | """ 36 | #led = connector.LEDp1 # This is the same as port.POWER_LED 37 | led = connector.LEDp2 # This is the same as port.STATUS_LED 38 | #led = port.POWER_LED 39 | #led = port.STATUS_LED 40 | 41 | gpio.init() 42 | gpio.setcfg(led, gpio.OUTPUT) 43 | 44 | try: 45 | print ("Press CTRL+C to exit") 46 | while True: 47 | gpio.output(led, 1) 48 | print "led set 1 \r\n" 49 | sleep(2) 50 | gpio.output(led, 0) 51 | print "led set 0 \r\n" 52 | sleep(2) 53 | """ 54 | gpio.output(led, 1) 55 | sleep(0.1) 56 | gpio.output(led, 0) 57 | sleep(0.1) 58 | 59 | sleep(0.6) 60 | """ 61 | except KeyboardInterrupt: 62 | print ("Goodbye.") 63 | -------------------------------------------------------------------------------- /examples/read_key_PG7.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | """Read button. 3 | 4 | Make gpio input and enable pull-up resistor. 5 | """ 6 | 7 | import os 8 | import sys 9 | 10 | if not os.getegid() == 0: 11 | sys.exit('Script must be run as root') 12 | 13 | from time import sleep 14 | from pyA20.gpio import gpio 15 | from pyA20.gpio import connector 16 | from pyA20.gpio import port 17 | 18 | __author__ = "Stefan Mavrodiev" 19 | __copyright__ = "Copyright 2014, Olimex LTD" 20 | __credits__ = ["Stefan Mavrodiev"] 21 | __license__ = "GPL" 22 | __version__ = "2.0" 23 | __maintainer__ = __author__ 24 | __email__ = "support@olimex.com" 25 | 26 | led = connector.gpio1p38 # This is the same as port.PH2 27 | button = connector.gpio1p40 #CHOW 28 | 29 | """Init gpio module""" 30 | gpio.init() 31 | 32 | """Set directions""" 33 | gpio.setcfg(led, gpio.OUTPUT) 34 | gpio.setcfg(button, gpio.INPUT) 35 | 36 | """Enable pullup resistor""" 37 | gpio.pullup(button, gpio.PULLUP) 38 | #gpio.pullup(button, gpio.PULLDOWN) # Optionally you can use pull-down resistor 39 | state =1 40 | value_out = 1 41 | try: 42 | print ("Press CTRL+C to exit") 43 | while True: 44 | """Since we use pull-up the logic will be inverted""" 45 | gpio.output(led, value_out) 46 | print "led out value is %d"%value_out 47 | if value_out == 1: value_out = 0 48 | else : value_out = 1 49 | sleep(1) 50 | state = gpio.input(button) # Read button state 51 | print "get button state is %d"%state 52 | sleep(2) 53 | 54 | 55 | 56 | except KeyboardInterrupt: 57 | print ("Goodbye.") 58 | -------------------------------------------------------------------------------- /pyA20/i2c/i2c_lib.c: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * This file is part of pyA20. 4 | * i2c_lib.c is python I2C extension. 5 | * 6 | * Copyright (c) 2014 Stefan Mavrodiev @ OLIMEX LTD, 7 | * 8 | * pyA20 is free software; you can redistribute it and/or modify 9 | * it under the terms of the GNU General Public License as published by 10 | * the Free Software Foundation; either version 2 of the License, or 11 | * (at your option) any later version. 12 | * 13 | * This program is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | * GNU General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU General Public License 19 | * along with this program; if not, write to the Free Software 20 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 21 | * MA 02110-1301, USA. 22 | */ 23 | 24 | 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | 31 | #include 32 | 33 | #include 34 | #include 35 | 36 | int i2c_open(char *device, uint8_t address) { 37 | int fd; 38 | int ret; 39 | 40 | fd = open(device, O_RDWR); 41 | if (fd < 0) 42 | return fd; 43 | 44 | ret = ioctl(fd, I2C_SLAVE_FORCE, address); 45 | if (ret < 0) 46 | return ret; 47 | 48 | return fd; 49 | 50 | } 51 | 52 | int i2c_close(int fd) { 53 | return (close(fd)); 54 | } 55 | 56 | int i2c_send(int fd, uint8_t *buffer, uint8_t num_bytes) { 57 | return (write(fd, buffer, num_bytes)); 58 | } 59 | 60 | int i2c_read(int fd, uint8_t *buffer, uint8_t num_bytes) { 61 | return (read(fd, buffer, num_bytes)); 62 | } 63 | -------------------------------------------------------------------------------- /pyA20/gpio/port/port.c: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * This file is part of pyA20. 4 | * port.c is python GPIO extension. 5 | * 6 | * Copyright (c) 2014 Stefan Mavrodiev @ OLIMEX LTD, 7 | * 8 | * pyA20 is free software; you can redistribute it and/or modify 9 | * it under the terms of the GNU General Public License as published by 10 | * the Free Software Foundation; either version 2 of the License, or 11 | * (at your option) any later version. 12 | * 13 | * This program is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | * GNU General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU General Public License 19 | * along with this program; if not, write to the Free Software 20 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 21 | * MA 02110-1301, USA. 22 | */ 23 | 24 | #include "Python.h" 25 | #include "../mapping.h" 26 | 27 | 28 | PyMethodDef module_methods[] = { 29 | {NULL, NULL, 0, NULL} 30 | }; 31 | 32 | 33 | #if PY_MAJOR_VERSION >= 3 34 | static struct PyModuleDef module_def = { 35 | PyModuleDef_HEAD_INIT, 36 | "port", 37 | NULL, 38 | -1, 39 | module_methods 40 | }; 41 | #endif 42 | 43 | PyMODINIT_FUNC 44 | #if PY_MAJOR_VERSION >= 3 45 | PyInit_port(void) { 46 | #else 47 | initport(void) { 48 | #endif 49 | PyObject* module = NULL; 50 | 51 | 52 | #if PY_MAJOR_VERSION >= 3 53 | module = PyModule_Create(&module_def); 54 | #else 55 | module = Py_InitModule("port", module_methods); 56 | #endif 57 | 58 | 59 | if (module == NULL) 60 | #if PY_MAJOR_VERSION >= 3 61 | return module; 62 | #else 63 | return; 64 | #endif 65 | 66 | int i; 67 | int j; 68 | for(i = 0; i < sizeof(gpio)/sizeof(gpio[0]); i++){ 69 | for(j = 0; j < 40; j++){ 70 | if(!strcmp(gpio[i].pins[j].name, "")){ 71 | break; 72 | }else{ 73 | PyModule_AddObject(module, gpio[i].pins[j].name, Py_BuildValue("i", gpio[i].pins[j].offset)); 74 | } 75 | } 76 | } 77 | 78 | #if PY_MAJOR_VERSION >= 3 79 | return module; 80 | #else 81 | return; 82 | #endif 83 | } -------------------------------------------------------------------------------- /pyA20/gpio/connector/connector.c: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * This file is part of pyA20. 4 | * connector.c is python GPIO extension. 5 | * 6 | * Copyright (c) 2014 Stefan Mavrodiev @ OLIMEX LTD, 7 | * 8 | * pyA20 is free software; you can redistribute it and/or modify 9 | * it under the terms of the GNU General Public License as published by 10 | * the Free Software Foundation; either version 2 of the License, or 11 | * (at your option) any later version. 12 | * 13 | * This program is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | * GNU General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU General Public License 19 | * along with this program; if not, write to the Free Software 20 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 21 | * MA 02110-1301, USA. 22 | */ 23 | 24 | #include "Python.h" 25 | #include "../mapping.h" 26 | 27 | 28 | PyMethodDef module_methods[] = { 29 | {NULL, NULL, 0, NULL} 30 | }; 31 | 32 | 33 | #if PY_MAJOR_VERSION >= 3 34 | static struct PyModuleDef module_def = { 35 | PyModuleDef_HEAD_INIT, 36 | "connector", 37 | NULL, 38 | -1, 39 | module_methods 40 | }; 41 | #endif 42 | 43 | PyMODINIT_FUNC 44 | #if PY_MAJOR_VERSION >= 3 45 | PyInit_connector(void) { 46 | #else 47 | initconnector(void) { 48 | #endif 49 | PyObject* module = NULL; 50 | 51 | 52 | #if PY_MAJOR_VERSION >= 3 53 | module = PyModule_Create(&module_def); 54 | #else 55 | module = Py_InitModule("connector", module_methods); 56 | #endif 57 | 58 | 59 | if (module == NULL) 60 | #if PY_MAJOR_VERSION >= 3 61 | return module; 62 | #else 63 | return; 64 | #endif 65 | 66 | int i; 67 | int j; 68 | char name[20]; 69 | for(i = 0; i < sizeof(gpio)/sizeof(gpio[0]); i++){ 70 | for(j = 0; j < 40; j++){ 71 | if(!strcmp(gpio[i].pins[j].name, "")){ 72 | break; 73 | }else{ 74 | sprintf(name, "%sp%d", gpio[i].connector_name, gpio[i].pins[j].pin_number); 75 | PyModule_AddObject(module, name, Py_BuildValue("i", gpio[i].pins[j].offset)); 76 | } 77 | } 78 | } 79 | 80 | #if PY_MAJOR_VERSION >= 3 81 | return module; 82 | #else 83 | return; 84 | #endif 85 | } -------------------------------------------------------------------------------- /pyA20/gpio/mapping_has_mistake.h: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * This file is part of pyA20. 4 | * mapping.h is python GPIO extension. 5 | * 6 | * Copyright (c) 2014 Stefan Mavrodiev @ OLIMEX LTD, 7 | * 8 | * pyA20 is free software; you can redistribute it and/or modify 9 | * it under the terms of the GNU General Public License as published by 10 | * the Free Software Foundation; either version 2 of the License, or 11 | * (at your option) any later version. 12 | * 13 | * This program is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | * GNU General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU General Public License 19 | * along with this program; if not, write to the Free Software 20 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 21 | * MA 02110-1301, USA. 22 | */ 23 | 24 | #ifndef __MAPPING_H 25 | #define __MAPPING_H 26 | 27 | #include "gpio_lib.h" 28 | 29 | /** 30 | Structure that describe all gpio 31 | */ 32 | typedef struct _pin { 33 | char name[10]; // The processor pin 34 | int offset; // Memory offset for the pin 35 | int pin_number; // Number on the connector 36 | }pin_t; 37 | 38 | typedef struct _gpio { 39 | char connector_name[10]; 40 | pin_t pins[41]; 41 | }gpio_t; 42 | 43 | 44 | gpio_t gpio[] = { 45 | 46 | /* 47 | #define PIN_PG0 SUNXI_GPG(0) 48 | 49 | */ {"gpio1", 50 | { 51 | { "PA12", SUNXI_GPA(12), 3 }, 52 | { "PA11", SUNXI_GPA(11), 5 }, 53 | { "PA6", SUNXI_GPA(6), 7 }, 54 | { "PA0", SUNXI_GPA(0), 11 }, 55 | { "PA1", SUNXI_GPA(1), 13 }, 56 | { "PA3", SUNXI_GPA(3), 15 }, 57 | { "PC0", SUNXI_GPC(0), 19 }, 58 | { "PC1", SUNXI_GPC(1), 21 }, 59 | { "PC2", SUNXI_GPC(2), 23 }, 60 | { "PA19", SUNXI_GPA(19), 27 }, 61 | { "PA7", SUNXI_GPA(7), 29 }, 62 | { "PA8", SUNXI_GPA(8), 31 }, 63 | { "PA9", SUNXI_GPA(9), 33 }, 64 | { "PA10", SUNXI_GPA(10), 35 }, 65 | { "PA20", SUNXI_GPA(20), 37 }, 66 | // 67 | { "PA13", SUNXI_GPA(13), 8 }, 68 | { "PA14", SUNXI_GPA(14), 10 }, 69 | { "PD14", SUNXI_GPD(14), 12 }, 70 | { "PC4", SUNXI_GPC(4), 16 }, 71 | { "PC7", SUNXI_GPC(7), 18 }, 72 | { "PA2", SUNXI_GPA(2), 22 }, 73 | { "PC3", SUNXI_GPC(3), 24 }, 74 | { "PA21", SUNXI_GPA(21), 26 }, 75 | { "PA18", SUNXI_GPA(18), 28 }, 76 | { "PG8", SUNXI_GPG(8), 32 }, 77 | { "PG9", SUNXI_GPG(9), 36 }, 78 | { "PG6", SUNXI_GPG(6), 38 }, 79 | { "PG7", SUNXI_GPG(7), 40 }, 80 | { 81 | { 0, 0, 0} 82 | }, 83 | } 84 | }, 85 | /* 86 | #define PIN_PG0 SUNXI_GPG(0) 87 | 88 | */ {"LED", 89 | { 90 | { "POWER_LED", SUNXI_GPL(10), 1 }, 91 | { "STATUS_LED", SUNXI_GPA(15), 2 }, 92 | { 93 | { 0, 0, 0} 94 | }, 95 | } 96 | }, 97 | }; 98 | 99 | 100 | 101 | #endif 102 | -------------------------------------------------------------------------------- /pyA20/spi/spi_lib.c: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * This file is part of pyA20. 4 | * sppi_lib.c is python SPI extension. 5 | * 6 | * Copyright (c) 2014 Stefan Mavrodiev @ OLIMEX LTD, 7 | * 8 | * pyA20 is free software; you can redistribute it and/or modify 9 | * it under the terms of the GNU General Public License as published by 10 | * the Free Software Foundation; either version 2 of the License, or 11 | * (at your option) any later version. 12 | * 13 | * This program is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | * GNU General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU General Public License 19 | * along with this program; if not, write to the Free Software 20 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 21 | * MA 02110-1301, USA. 22 | */ 23 | 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | 33 | #include 34 | 35 | #include "spi_lib.h" 36 | 37 | int spi_open(char *device, spi_config_t config) { 38 | int fd; 39 | 40 | /* Open block device */ 41 | fd = open(device, O_RDWR); 42 | if (fd < 0) { 43 | return fd; 44 | } 45 | 46 | /* Set SPI_POL and SPI_PHA */ 47 | if (ioctl(fd, SPI_IOC_WR_MODE, &config.mode) < 0) { 48 | return -1; 49 | } 50 | if (ioctl(fd, SPI_IOC_RD_MODE, &config.mode) < 0) { 51 | return -1; 52 | } 53 | 54 | /* Set bits per word*/ 55 | if (ioctl(fd, SPI_IOC_WR_BITS_PER_WORD, &config.bits_per_word) < 0) { 56 | return -1; 57 | } 58 | if (ioctl(fd, SPI_IOC_RD_BITS_PER_WORD, &config.bits_per_word) < 0) { 59 | return -1; 60 | } 61 | 62 | /* Set SPI speed*/ 63 | if (ioctl(fd, SPI_IOC_WR_MAX_SPEED_HZ, &config.speed) < 0) { 64 | return -1; 65 | } 66 | if (ioctl(fd, SPI_IOC_RD_MAX_SPEED_HZ, &config.speed) < 0) { 67 | return -1; 68 | } 69 | 70 | /* Return file descriptor */ 71 | return fd; 72 | } 73 | 74 | int spi_close(int fd) { 75 | return close(fd); 76 | } 77 | 78 | int spi_xfer(int fd, uint8_t *tx_buffer, uint8_t tx_len, uint8_t *rx_buffer, uint8_t rx_len){ 79 | struct spi_ioc_transfer spi_message[2]; 80 | memset(spi_message, 0, sizeof(spi_message)); 81 | 82 | spi_message[0].rx_buf = (unsigned long)tx_buffer; 83 | spi_message[0].len = tx_len; 84 | 85 | spi_message[1].tx_buf = (unsigned long)rx_buffer; 86 | spi_message[1].len = rx_len; 87 | 88 | return ioctl(fd, SPI_IOC_MESSAGE(2), spi_message); 89 | } 90 | 91 | int spi_read(int fd, uint8_t *rx_buffer, uint8_t rx_len){ 92 | struct spi_ioc_transfer spi_message[1]; 93 | memset(spi_message, 0, sizeof(spi_message)); 94 | 95 | spi_message[0].rx_buf = (unsigned long)rx_buffer; 96 | spi_message[0].len = rx_len; 97 | 98 | return ioctl(fd, SPI_IOC_MESSAGE(1), spi_message); 99 | } 100 | 101 | int spi_write(int fd, uint8_t *tx_buffer, uint8_t tx_len){ 102 | struct spi_ioc_transfer spi_message[1]; 103 | memset(spi_message, 0, sizeof(spi_message)); 104 | 105 | spi_message[0].tx_buf = (unsigned long)tx_buffer; 106 | spi_message[0].len = tx_len; 107 | 108 | return ioctl(fd, SPI_IOC_MESSAGE(1), spi_message); 109 | } 110 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | from distutils.core import setup 2 | from distutils.core import Extension 3 | from distutils.command.build_ext import build_ext as _build_ext 4 | 5 | import sys 6 | 7 | processor_type = "sun8i" 8 | 9 | try: 10 | input = raw_input 11 | except NameError: 12 | pass 13 | 14 | 15 | def print_color(text): 16 | """ 17 | Print text in yellow :) 18 | :param text: String to be colored 19 | :return: Colored text 20 | """ 21 | 22 | return '\033[0;33m' + text + '\033[0m' 23 | 24 | 25 | def print_warning(): 26 | """ 27 | Print confirmation dialog 28 | :return: 29 | """ 30 | print (print_color("Warning! ") + "Detected and target processor mismatch. ") 31 | 32 | 33 | var = input("Do you want to continue [Y/n]? ") 34 | if var == 'Y' or var == 'y': 35 | return 36 | else: 37 | print ("Abort.") 38 | sys.exit(1) 39 | 40 | 41 | def check_processor(): 42 | """ 43 | Detect processor type 44 | :return: 45 | """ 46 | cpuinfo = open("/proc/cpuinfo", 'r') 47 | for line in cpuinfo: 48 | if "Hardware" in line: 49 | processor = line.split(":")[1].rstrip() 50 | 51 | if "sun4i" in processor: 52 | print ("Detected processor: " + print_color(processor) + " (Probably Allwinner A10)") 53 | 54 | elif "sun5i" in processor: 55 | print ("Detected processor: " + print_color(processor) + " (Probably Allwinner A13)") 56 | 57 | elif "sun7i" in processor: 58 | print ("Detected processor: " + print_color(processor) + " (Probably Allwinner A20)") 59 | 60 | elif "sun8i" in processor: 61 | print ("Detected processor: " + print_color(processor) + " (Probably Allwinner H3)") 62 | 63 | else: 64 | print ("Detected processor: " + print_color("unknown")) 65 | 66 | 67 | if processor_type not in processor: 68 | print_warning() 69 | 70 | return 71 | 72 | print ("No processor detected") 73 | print_warning() 74 | 75 | 76 | class build_ext(_build_ext): 77 | def run(self): 78 | check_processor() 79 | _build_ext.run(self) 80 | 81 | 82 | modules = [ 83 | Extension('pyA20.gpio.gpio', sources=['pyA20/gpio/gpio_lib.c', 'pyA20/gpio/gpio.c']), 84 | 85 | Extension('pyA20.i2c', sources=['pyA20/i2c/i2c_lib.c', 'pyA20/i2c/i2c.c']), 86 | 87 | Extension('pyA20.spi', sources=['pyA20/spi/spi_lib.c', 'pyA20/spi/spi.c']), 88 | 89 | Extension('pyA20.gpio.connector', sources=['pyA20/gpio/connector/connector.c']), 90 | 91 | Extension('pyA20.gpio.port', sources=['pyA20/gpio/port/port.c']), 92 | 93 | ] 94 | 95 | setup( 96 | name='pyA20', 97 | version='0.2.1', 98 | author='Stefan Mavrodiev', 99 | author_email='support@olimex.com', 100 | url='https://www.olimex.com/', 101 | license='MIT', 102 | packages=['pyA20', 'pyA20.gpio'], 103 | description='Control GPIO, I2C and SPI', 104 | long_description=open('README.txt').read() + open('CHANGES.txt').read(), 105 | classifiers=['Development Status :: 3 - Alpha', 106 | 'Environment :: Console', 107 | 'Intended Audience :: Developers', 108 | 'Intended Audience :: Education', 109 | 'License :: OSI Approved :: MIT License', 110 | 'Operating System :: POSIX :: Linux', 111 | 'Programming Language :: Python', 112 | 'Topic :: Home Automation', 113 | 'Topic :: Software Development :: Embedded Systems' 114 | ], 115 | ext_modules=modules, 116 | cmdclass={'build_ext': build_ext} 117 | ) 118 | -------------------------------------------------------------------------------- /pyA20/gpio/mapping.h: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * This file is part of pyA20. 4 | * mapping.h is python GPIO extension. 5 | * 6 | * Copyright (c) 2014 Stefan Mavrodiev @ OLIMEX LTD, 7 | * 8 | * pyA20 is free software; you can redistribute it and/or modify 9 | * it under the terms of the GNU General Public License as published by 10 | * the Free Software Foundation; either version 2 of the License, or 11 | * (at your option) any later version. 12 | * 13 | * This program is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | * GNU General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU General Public License 19 | * along with this program; if not, write to the Free Software 20 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 21 | * MA 02110-1301, USA. 22 | */ 23 | 24 | #ifndef __MAPPING_H 25 | #define __MAPPING_H 26 | 27 | #include "gpio_lib.h" 28 | 29 | /** 30 | Structure that describe all gpio 31 | */ 32 | typedef struct _pin { 33 | char name[10]; // The processor pin 34 | int offset; // Memory offset for the pin 35 | int pin_number; // Number on the connector 36 | }pin_t; 37 | 38 | typedef struct _gpio { 39 | char connector_name[10]; 40 | pin_t pins[41]; 41 | }gpio_t; 42 | 43 | 44 | gpio_t gpio[] = { 45 | 46 | /* 47 | #define PIN_PG0 SUNXI_GPG(0) 48 | 49 | */ {"gpio1", 50 | { 51 | { "PA12", SUNXI_GPA(12), 3 }, 52 | { "PA11", SUNXI_GPA(11), 5 }, 53 | { "PA6", SUNXI_GPA(6), 7 }, 54 | /* 55 | thanks nopnop2002 56 | /orangepi_PC_gpio_pyH3/pyA20/gpio/mapping.h 57 | 58 | It is a mistake. 59 | { "PA0", SUNXI_GPA(0), 11 }, 60 | { "PA1", SUNXI_GPA(1), 13 }, 61 | 62 | It is right. 63 | { "PA1", SUNXI_GPA(1), 11 }, 64 | { "PA0", SUNXI_GPA(0), 13 }, 65 | 66 | sorry My poor English 67 | 68 | 69 | { "PA0", SUNXI_GPA(0), 11 }, 70 | { "PA1", SUNXI_GPA(1), 13 }, 71 | 72 | */ 73 | { "PA1", SUNXI_GPA(1), 11 }, 74 | { "PA0", SUNXI_GPA(0), 13 }, 75 | 76 | { "PA3", SUNXI_GPA(3), 15 }, 77 | { "PC0", SUNXI_GPC(0), 19 }, 78 | { "PC1", SUNXI_GPC(1), 21 }, 79 | { "PC2", SUNXI_GPC(2), 23 }, 80 | { "PA19", SUNXI_GPA(19), 27 }, 81 | { "PA7", SUNXI_GPA(7), 29 }, 82 | { "PA8", SUNXI_GPA(8), 31 }, 83 | { "PA9", SUNXI_GPA(9), 33 }, 84 | { "PA10", SUNXI_GPA(10), 35 }, 85 | { "PA20", SUNXI_GPA(20), 37 }, 86 | // 87 | { "PA13", SUNXI_GPA(13), 8 }, 88 | { "PA14", SUNXI_GPA(14), 10 }, 89 | { "PD14", SUNXI_GPD(14), 12 }, 90 | { "PC4", SUNXI_GPC(4), 16 }, 91 | { "PC7", SUNXI_GPC(7), 18 }, 92 | { "PA2", SUNXI_GPA(2), 22 }, 93 | { "PC3", SUNXI_GPC(3), 24 }, 94 | { "PA21", SUNXI_GPA(21), 26 }, 95 | { "PA18", SUNXI_GPA(18), 28 }, 96 | { "PG8", SUNXI_GPG(8), 32 }, 97 | { "PG9", SUNXI_GPG(9), 36 }, 98 | { "PG6", SUNXI_GPG(6), 38 }, 99 | { "PG7", SUNXI_GPG(7), 40 }, 100 | { 101 | { 0, 0, 0} 102 | }, 103 | } 104 | }, 105 | /* 106 | #define PIN_PG0 SUNXI_GPG(0) 107 | 108 | */ {"LED", 109 | { 110 | { "POWER_LED", SUNXI_GPL(10), 1 }, 111 | { "STATUS_LED", SUNXI_GPA(15), 2 }, 112 | { 113 | { 0, 0, 0} 114 | }, 115 | } 116 | }, 117 | }; 118 | 119 | 120 | 121 | #endif 122 | -------------------------------------------------------------------------------- /pyA20/gpio/gpio_lib.c: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * This file is part of pyA20. 4 | * gpio_lib.c is python GPIO extension. 5 | * 6 | * Copyright (c) 2014 Stefan Mavrodiev @ OLIMEX LTD, 7 | * 8 | * pyA20 is free software; you can redistribute it and/or modify 9 | * it under the terms of the GNU General Public License as published by 10 | * the Free Software Foundation; either version 2 of the License, or 11 | * (at your option) any later version. 12 | * 13 | * This program is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | * GNU General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU General Public License 19 | * along with this program; if not, write to the Free Software 20 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 21 | * MA 02110-1301, USA. 22 | */ 23 | 24 | 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | #include 37 | #include 38 | #include 39 | 40 | #include "gpio_lib.h" 41 | 42 | unsigned int SUNXI_PIO_BASE = 0; 43 | 44 | int sunxi_gpio_init(void) { 45 | int fd; 46 | unsigned int addr_start, addr_offset; 47 | unsigned int PageSize, PageMask; 48 | void *pc; 49 | 50 | fd = open("/dev/mem", O_RDWR); 51 | if (fd < 0) { 52 | return (-1); 53 | } 54 | 55 | 56 | PageSize = sysconf(_SC_PAGESIZE); 57 | PageMask = (~(PageSize - 1)); 58 | 59 | addr_start = SW_PORTC_IO_BASE & PageMask; 60 | addr_offset = SW_PORTC_IO_BASE & ~PageMask; 61 | 62 | pc = (void *) mmap(0, PageSize * 2, PROT_READ | PROT_WRITE, MAP_SHARED, fd, addr_start); 63 | if (pc == MAP_FAILED) { 64 | return (-1); 65 | } 66 | 67 | SUNXI_PIO_BASE = (unsigned int) pc; 68 | SUNXI_PIO_BASE += addr_offset; 69 | 70 | close(fd); 71 | return 0; 72 | } 73 | 74 | int sunxi_gpio_set_cfgpin(unsigned int pin, unsigned int val) { 75 | 76 | unsigned int cfg; 77 | unsigned int bank = GPIO_BANK(pin); 78 | unsigned int index = GPIO_CFG_INDEX(pin); 79 | unsigned int offset = GPIO_CFG_OFFSET(pin); 80 | 81 | if (SUNXI_PIO_BASE == 0) { 82 | return -1; 83 | } 84 | 85 | struct sunxi_gpio *pio = 86 | &((struct sunxi_gpio_reg *) SUNXI_PIO_BASE)->gpio_bank[bank]; 87 | 88 | 89 | cfg = *(&pio->cfg[0] + index); 90 | cfg &= ~(0xf << offset); 91 | cfg |= val << offset; 92 | 93 | *(&pio->cfg[0] + index) = cfg; 94 | 95 | return 0; 96 | } 97 | 98 | int sunxi_gpio_get_cfgpin(unsigned int pin) { 99 | 100 | unsigned int cfg; 101 | unsigned int bank = GPIO_BANK(pin); 102 | unsigned int index = GPIO_CFG_INDEX(pin); 103 | unsigned int offset = GPIO_CFG_OFFSET(pin); 104 | if (SUNXI_PIO_BASE == 0) { 105 | return -1; 106 | } 107 | struct sunxi_gpio *pio = &((struct sunxi_gpio_reg *) SUNXI_PIO_BASE)->gpio_bank[bank]; 108 | cfg = *(&pio->cfg[0] + index); 109 | cfg >>= offset; 110 | return (cfg & 0xf); 111 | } 112 | 113 | int sunxi_gpio_output(unsigned int pin, unsigned int val) { 114 | 115 | unsigned int bank = GPIO_BANK(pin); 116 | unsigned int num = GPIO_NUM(pin); 117 | 118 | if (SUNXI_PIO_BASE == 0) { 119 | return -1; 120 | } 121 | struct sunxi_gpio *pio = &((struct sunxi_gpio_reg *) SUNXI_PIO_BASE)->gpio_bank[bank]; 122 | 123 | if (val) 124 | *(&pio->dat) |= 1 << num; 125 | else 126 | *(&pio->dat) &= ~(1 << num); 127 | 128 | return 0; 129 | } 130 | 131 | int sunxi_gpio_pullup(unsigned int pin, unsigned int pull) { 132 | 133 | unsigned int cfg; 134 | unsigned int bank = GPIO_BANK(pin); 135 | unsigned int index = GPIO_PUL_INDEX(pin); 136 | unsigned int offset = GPIO_PUL_OFFSET(pin); 137 | 138 | if (SUNXI_PIO_BASE == 0) { 139 | return -1; 140 | } 141 | 142 | struct sunxi_gpio *pio = 143 | &((struct sunxi_gpio_reg *) SUNXI_PIO_BASE)->gpio_bank[bank]; 144 | 145 | cfg = *(&pio->pull[0] + index); 146 | cfg &= ~(0x3 << offset); 147 | cfg |= pull << offset; 148 | 149 | *(&pio->pull[0] + index) = cfg; 150 | 151 | return 0; 152 | } 153 | 154 | int sunxi_gpio_input(unsigned int pin) { 155 | 156 | unsigned int dat; 157 | unsigned int bank = GPIO_BANK(pin); 158 | unsigned int num = GPIO_NUM(pin); 159 | 160 | if (SUNXI_PIO_BASE == 0) { 161 | return -1; 162 | } 163 | 164 | struct sunxi_gpio *pio = &((struct sunxi_gpio_reg *) SUNXI_PIO_BASE)->gpio_bank[bank]; 165 | 166 | dat = *(&pio->dat); 167 | dat >>= num; 168 | 169 | return (dat & 0x1); 170 | } 171 | -------------------------------------------------------------------------------- /README.txt: -------------------------------------------------------------------------------- 1 | This package provide methods for controlling GPIO pins, I2C and SPI buses. 2 | This is written for A20-OLinuXino-MICRO, but it can be used with other boards. If you do 3 | this we cannot guarantee proper operation of the module. Before using this 4 | package we recommend reading the article at olimex wiki: 5 | 6 | https://www.olimex.com/wiki/A20-OLinuXino-MICRO 7 | 8 | When using GPIO make sure that the desired gpio is not used by another periphery. 9 | 10 | GPIO METHODS 11 | ============ 12 | 13 | init() - Make initialization of the module. Always must be called first. 14 | getcfg() - Read current configuration of gpio. 15 | setcfg() - Write configuration to gpio. 16 | input() - Return current value of gpio. 17 | output() - Set output value. 18 | pullup() - Set pull-up/pull-down. 19 | 20 | 21 | The available constants are: 22 | 23 | NAME - EQUALS TO 24 | ==== ========= 25 | HIGH -> 1 26 | LOW -> 0 27 | INPUT -> 0 28 | OUPTUT -> 1 29 | PULLUP -> 1 30 | PULLDOWN -> 2 31 | 32 | 33 | The gpio are named two ways: 34 | 35 | By port name: PH0, PG2, PE10, etc. 36 | These can be imported from port module: 37 | 38 | >>> from pyA20.gpio import port 39 | >>> dir(port) 40 | 41 | By connector name and pin number: gpio2p12, gpio3p8, lcdp18, uext1p3 and etc. 42 | These can be imported from connector module: 43 | 44 | >>> from pyA20.gpio import connector 45 | >>> dir(connector) 46 | 47 | Generally these constants are just an offset in the memory from the base GPIO address, so they can 48 | be assigned to a number type variable. 49 | 50 | >>> led = port.PH2 51 | >>> print led 52 | 226 53 | 54 | 55 | 56 | I2C METHODS 57 | =========== 58 | 59 | init() - Make initialization of the module 60 | open() - Begin communication with slave device 61 | read() - Read from slave device 62 | write() - Write data to slave device 63 | close() - End communication with slave device 64 | 65 | 66 | SPI METHODS 67 | =========== 68 | 69 | open() - Open SPI bus with given configuration 70 | read() - Read data from slave device without write 71 | write() - Write data to slave device without read 72 | xfer() - Do write and after that read 73 | close() - Close SPI bus 74 | 75 | 76 | 77 | Examples 78 | ======== 79 | 80 | GPIO:: 81 | 82 | #!/usr/bin/env python 83 | 84 | from pyA20.gpio import gpio 85 | from pyA20.gpio import port 86 | from pyA20.gpio import connector 87 | 88 | gpio.init() #Initialize module. Always called first 89 | 90 | gpio.setcfg(port.PG9, gpio.OUTPUT) #Configure LED1 as output 91 | gpio.setcfg(port.PG9, 1) #This is the same as above 92 | 93 | gpio.setcfg(port.PE11, gpio.INPUT) #Configure PE11 as input 94 | gpio.setcfg(port.PE11, 0) #Same as above 95 | 96 | gpio.pullup(port.PE11, 0) #Clear pullups 97 | gpio.pullup(port.PE11, gpio.PULLDOWN) #Enable pull-down 98 | gpio.pullup(port.PE11, gpio.PULLUP) #Enable pull-up 99 | 100 | while True: 101 | if gpio.input(port.PE11) == 1: 102 | gpio.output(port.PG9, gpio.LOW) 103 | gpio.output(port.PG9, 0) 104 | else: 105 | gpio.output(port.PG9, gpio.HIGH) 106 | gpio.output(port.PG9, 1) 107 | 108 | 109 | I2C:: 110 | 111 | #!/usr/bin/env python 112 | 113 | from pyA20 import i2c 114 | 115 | i2c.init("/dev/i2c-2") #Initialize module to use /dev/i2c-2 116 | i2c.open(0x55) #The slave device address is 0x55 117 | 118 | #If we want to write to some register 119 | i2c.write([0xAA, 0x20]) #Write 0x20 to register 0xAA 120 | i2c.write([0xAA, 0x10, 0x11, 0x12]) #Do continuous write with start address 0xAA 121 | 122 | #If we want to do write and read 123 | i2c.write([0xAA]) #Set address at 0xAA register 124 | value = i2c.read(1) #Read 1 byte with start address 0xAA 125 | 126 | i2c.close() #End communication with slave device 127 | 128 | 129 | SPI:: 130 | 131 | #!/usr/bin/env python 132 | 133 | from pyA20 import spi 134 | 135 | spi.open("/dev/spidev2.0") 136 | #Open SPI device with default settings 137 | # mode : 0 138 | # speed : 100000kHz 139 | # delay : 0 140 | # bits-per-word: 8 141 | 142 | #Different ways to open device 143 | spi.open("/dev/spidev2.0", mode=1) 144 | spi.open("/dev/spidev2.0", mode=2, delay=0) 145 | spi.open("/dev/spidev2.0", mode=3, delay=0, bits_per_word=8) 146 | spi.open("/dev/spidev2.0", mode=0, delay=0, bits_per_word=8, speed=100000) 147 | 148 | spi.write([0x01, 0x02]) #Write 2 bytes to slave device 149 | spi.read(2) #Read 2 bytes from slave device 150 | spi.xfer([0x01, 0x02], 2) #Write 2 byte and then read 2 bytes. 151 | 152 | spi.close() #Close SPI bus 153 | 154 | 155 | It's important that you run your python script as root! 156 | 157 | 158 | -------------------------------------------------------------------------------- /pyA20/gpio/gpio_lib.h: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * This file is part of pyA20. 4 | * gpio_lib.h is python GPIO extension. 5 | * 6 | * Copyright (c) 2014 Stefan Mavrodiev @ OLIMEX LTD, 7 | * 8 | * pyA20 is free software; you can redistribute it and/or modify 9 | * it under the terms of the GNU General Public License as published by 10 | * the Free Software Foundation; either version 2 of the License, or 11 | * (at your option) any later version. 12 | * 13 | * This program is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | * GNU General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU General Public License 19 | * along with this program; if not, write to the Free Software 20 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 21 | * MA 02110-1301, USA. 22 | */ 23 | 24 | #ifndef _GPIO_LIB_H_ 25 | #define _GPIO_LIB_H_ 26 | 27 | #define SW_PORTC_IO_BASE 0x01c20800 28 | 29 | 30 | #define SUNXI_GPIO_A 0 31 | #define SUNXI_GPIO_B 1 32 | #define SUNXI_GPIO_C 2 33 | #define SUNXI_GPIO_D 3 34 | #define SUNXI_GPIO_E 4 35 | #define SUNXI_GPIO_F 5 36 | #define SUNXI_GPIO_G 6 37 | //by chow add 38 | #define SUNXI_GPIO_H 7 39 | #define SUNXI_GPIO_I 8 40 | #define SUNXI_GPIO_J 9 41 | #define SUNXI_GPIO_K 10 42 | #define SUNXI_GPIO_L 11 43 | #define SUNXI_GPIO_M 12 44 | #define SUNXI_GPIO_N 13 45 | #define SUNXI_GPIO_O 14 46 | 47 | 48 | struct sunxi_gpio { 49 | unsigned int cfg[4]; 50 | unsigned int dat; 51 | unsigned int drv[2]; 52 | unsigned int pull[2]; 53 | }; 54 | 55 | /* gpio interrupt control */ 56 | struct sunxi_gpio_int { 57 | unsigned int cfg[3]; 58 | unsigned int ctl; 59 | unsigned int sta; 60 | unsigned int deb; 61 | }; 62 | 63 | struct sunxi_gpio_reg { 64 | struct sunxi_gpio gpio_bank[9]; 65 | unsigned char res[0xbc]; 66 | struct sunxi_gpio_int gpio_int; 67 | }; 68 | 69 | #define GPIO_BANK(pin) ((pin) >> 5) 70 | #define GPIO_NUM(pin) ((pin) & 0x1F) 71 | 72 | #define GPIO_CFG_INDEX(pin) (((pin) & 0x1F) >> 3) 73 | #define GPIO_CFG_OFFSET(pin) ((((pin) & 0x1F) & 0x7) << 2) 74 | 75 | #define GPIO_PUL_INDEX(pin) (((pin) & 0x1F )>> 4) 76 | #define GPIO_PUL_OFFSET(pin) (((pin) & 0x0F) << 1) 77 | 78 | /* GPIO bank sizes */ 79 | #define SUNXI_GPIO_A_NR (32) 80 | #define SUNXI_GPIO_B_NR (32) 81 | #define SUNXI_GPIO_C_NR (32) 82 | #define SUNXI_GPIO_D_NR (32) 83 | #define SUNXI_GPIO_E_NR (32) 84 | #define SUNXI_GPIO_F_NR (32) 85 | #define SUNXI_GPIO_G_NR (32) 86 | //BY CHOW add 87 | #define SUNXI_GPIO_H_NR (32) 88 | #define SUNXI_GPIO_I_NR (32) 89 | #define SUNXI_GPIO_J_NR (32) 90 | #define SUNXI_GPIO_K_NR (32) 91 | #define SUNXI_GPIO_L_NR (32) 92 | #define SUNXI_GPIO_M_NR (32) 93 | #define SUNXI_GPIO_N_NR (32) 94 | #define SUNXI_GPIO_O_NR (32) 95 | // 96 | 97 | 98 | #define SUNXI_GPIO_NEXT(__gpio) ((__gpio##_START)+(__gpio##_NR)+0) 99 | 100 | enum sunxi_gpio_number { 101 | SUNXI_GPIO_A_START = 0, 102 | SUNXI_GPIO_B_START = SUNXI_GPIO_NEXT(SUNXI_GPIO_A), //32 103 | SUNXI_GPIO_C_START = SUNXI_GPIO_NEXT(SUNXI_GPIO_B), //64 104 | SUNXI_GPIO_D_START = SUNXI_GPIO_NEXT(SUNXI_GPIO_C), //96 105 | SUNXI_GPIO_E_START = SUNXI_GPIO_NEXT(SUNXI_GPIO_D), //128 106 | SUNXI_GPIO_F_START = SUNXI_GPIO_NEXT(SUNXI_GPIO_E), //160 107 | SUNXI_GPIO_G_START = SUNXI_GPIO_NEXT(SUNXI_GPIO_F), //192 108 | // BY CHOW ADD 109 | SUNXI_GPIO_H_START = SUNXI_GPIO_NEXT(SUNXI_GPIO_G), //224 110 | SUNXI_GPIO_I_START = SUNXI_GPIO_NEXT(SUNXI_GPIO_H), //256 111 | SUNXI_GPIO_J_START = SUNXI_GPIO_NEXT(SUNXI_GPIO_I), //288 112 | SUNXI_GPIO_K_START = SUNXI_GPIO_NEXT(SUNXI_GPIO_J), //320 113 | SUNXI_GPIO_L_START = SUNXI_GPIO_NEXT(SUNXI_GPIO_K), //352 114 | SUNXI_GPIO_M_START = SUNXI_GPIO_NEXT(SUNXI_GPIO_L), //384 115 | SUNXI_GPIO_N_START = SUNXI_GPIO_NEXT(SUNXI_GPIO_M), //448 116 | SUNXI_GPIO_O_START = SUNXI_GPIO_NEXT(SUNXI_GPIO_N), //448+32 117 | 118 | 119 | }; 120 | 121 | /* SUNXI GPIO number definitions */ 122 | #define SUNXI_GPA(_nr) (SUNXI_GPIO_A_START + (_nr)) 123 | #define SUNXI_GPB(_nr) (SUNXI_GPIO_B_START + (_nr)) 124 | #define SUNXI_GPC(_nr) (SUNXI_GPIO_C_START + (_nr)) 125 | #define SUNXI_GPD(_nr) (SUNXI_GPIO_D_START + (_nr)) 126 | #define SUNXI_GPE(_nr) (SUNXI_GPIO_E_START + (_nr)) 127 | #define SUNXI_GPF(_nr) (SUNXI_GPIO_F_START + (_nr)) 128 | #define SUNXI_GPG(_nr) (SUNXI_GPIO_G_START + (_nr)) 129 | #define SUNXI_GPH(_nr) (SUNXI_GPIO_H_START + (_nr)) 130 | #define SUNXI_GPI(_nr) (SUNXI_GPIO_I_START + (_nr)) 131 | //add by chow 132 | #define SUNXI_GPJ(_nr) (SUNXI_GPIO_J_START + (_nr)) 133 | #define SUNXI_GPK(_nr) (SUNXI_GPIO_K_START + (_nr)) 134 | #define SUNXI_GPL(_nr) (SUNXI_GPIO_L_START + (_nr)) 135 | #define SUNXI_GPM(_nr) (SUNXI_GPIO_M_START + (_nr)) 136 | #define SUNXI_GPN(_nr) (SUNXI_GPIO_N_START + (_nr)) 137 | #define SUNXI_GPO(_nr) (SUNXI_GPIO_O_START + (_nr)) 138 | 139 | 140 | 141 | /* GPIO pin function config */ 142 | #define SUNXI_GPIO_INPUT (0) 143 | #define SUNXI_GPIO_OUTPUT (1) 144 | #define SUNXI_GPIO_PER (2) 145 | 146 | #define SUNXI_PULL_NONE (0) 147 | #define SUNXI_PULL_UP (1) 148 | #define SUNXI_PULL_DOWN (2) 149 | 150 | extern int sunxi_gpio_input(unsigned int pin); 151 | extern int sunxi_gpio_init(void); 152 | extern int sunxi_gpio_set_cfgpin(unsigned int pin, unsigned int val); 153 | extern int sunxi_gpio_get_cfgpin(unsigned int pin); 154 | extern int sunxi_gpio_output(unsigned int pin, unsigned int val); 155 | extern int sunxi_gpio_pullup(unsigned int pin, unsigned int pull); 156 | 157 | 158 | extern unsigned int SUNXI_PIO_BASE; 159 | #endif // _GPIO_LIB_H_ 160 | -------------------------------------------------------------------------------- /pyA20/utilities/color.py: -------------------------------------------------------------------------------- 1 | __author__ = 'stefan' 2 | 3 | 4 | class Colors: 5 | def __init__(self): 6 | self = self 7 | 8 | def test(self): 9 | print "Regular" 10 | print self.Black + "Black" + self.Color_Off 11 | print self.Red + "Red" + self.Color_Off 12 | print self.Green + "Green" + self.Color_Off 13 | print self.Yellow + "Yellow" + self.Color_Off 14 | print self.Blue + "Blue" + self.Color_Off 15 | print self.Purple + "Purple" + self.Color_Off 16 | print self.Cyan + "Cyan" + self.Color_Off 17 | print self.White + "White" + self.Color_Off 18 | print "" 19 | 20 | print "Bold" 21 | print self.BBlack + "BBlack" + self.Color_Off 22 | print self.BRed + "BRed" + self.Color_Off 23 | print self.BGreen + "BGreen" + self.Color_Off 24 | print self.BYellow + "BYellow" + self.Color_Off 25 | print self.BBlue + "BBlue" + self.Color_Off 26 | print self.BPurple + "BPurple" + self.Color_Off 27 | print self.BCyan + "BCyan" + self.Color_Off 28 | print self.BWhite + "BWhite" + self.Color_Off 29 | print "" 30 | 31 | print "Underline" 32 | print self.UBlack + "UBlack" + self.Color_Off 33 | print self.URed + "URed" + self.Color_Off 34 | print self.UGreen + "UGreen" + self.Color_Off 35 | print self.UYellow + "UYellow" + self.Color_Off 36 | print self.UBlue + "UBlue" + self.Color_Off 37 | print self.UPurple + "UPurple" + self.Color_Off 38 | print self.UCyan + "UCyan" + self.Color_Off 39 | print self.UWhite + "UWhite" + self.Color_Off 40 | print "" 41 | 42 | print "Background" 43 | print self.On_Black + "On_Black" + self.Color_Off 44 | print self.On_Red + "On_Red" + self.Color_Off 45 | print self.On_Green + "On_Green" + self.Color_Off 46 | print self.On_Yellow + "On_Yellow" + self.Color_Off 47 | print self.On_Blue + "On_Blue" + self.Color_Off 48 | print self.On_Purple + "On_Purple" + self.Color_Off 49 | print self.On_Cyan + "On_Cyan" + self.Color_Off 50 | print self.On_White + "On_White" + self.Color_Off 51 | print "" 52 | 53 | print "High Intensity" 54 | print self.IBlack + "IBlack" + self.Color_Off 55 | print self.IRed + "IRed" + self.Color_Off 56 | print self.IGreen + "IGreen" + self.Color_Off 57 | print self.IYellow + "IYellow" + self.Color_Off 58 | print self.IBlue + "IBlue" + self.Color_Off 59 | print self.IPurple + "IPurple" + self.Color_Off 60 | print self.ICyan + "ICyan" + self.Color_Off 61 | print self.IWhite + "IWhite" + self.Color_Off 62 | print "" 63 | 64 | print "Bold High Intensity" 65 | print self.BIBlack + "BIBlack" + self.Color_Off 66 | print self.BIRed + "BIRed" + self.Color_Off 67 | print self.BIGreen + "BIGreen" + self.Color_Off 68 | print self.BIYellow + "BIYellow" + self.Color_Off 69 | print self.BIBlue + "BIBlue" + self.Color_Off 70 | print self.BIPurple + "BIPurple" + self.Color_Off 71 | print self.BICyan + "BICyan" + self.Color_Off 72 | print self.BIWhite + "BIWhite" + self.Color_Off 73 | print "" 74 | 75 | print "High Intensity backgrounds" 76 | print self.On_IBlack + "On_IBlack" + self.Color_Off 77 | print self.On_IRed + "On_IRed" + self.Color_Off 78 | print self.On_IGreen + "On_IGreen" + self.Color_Off 79 | print self.On_IYellow + "On_IYellow" + self.Color_Off 80 | print self.On_IBlue + "On_IBlue" + self.Color_Off 81 | print self.On_IPurple + "On_IPurple" + self.Color_Off 82 | print self.On_ICyan + "On_ICyan" + self.Color_Off 83 | print self.On_IWhite + "On_IWhite" + self.Color_Off 84 | print "" 85 | 86 | # Reset 87 | Color_Off = '\033[0m' # Text Reset 88 | 89 | Black = '\033[0;30m' # Black 90 | Red = '\033[0;31m' # Red 91 | Green = '\033[0;32m' # Green 92 | Yellow = '\033[0;33m' # Yellow 93 | Blue = '\033[0;34m' # Blue 94 | Purple = '\033[0;35m' # Purple 95 | Cyan = '\033[0;36m' # Cyan 96 | White = '\033[0;37m' # White 97 | 98 | # Bold 99 | BBlack = '\033[1;30m' # Black 100 | BRed = '\033[1;31m' # Red 101 | BGreen = '\033[1;32m' # Green 102 | BYellow = '\033[1;33m' # Yellow 103 | BBlue = '\033[1;34m' # Blue 104 | BPurple = '\033[1;35m' # Purple 105 | BCyan = '\033[1;36m' # Cyan 106 | BWhite = '\033[1;37m' # White 107 | 108 | # Underline 109 | UBlack = '\033[4;30m' # Black 110 | URed = '\033[4;31m' # Red 111 | UGreen = '\033[4;32m' # Green 112 | UYellow = '\033[4;33m' # Yellow 113 | UBlue = '\033[4;34m' # Blue 114 | UPurple = '\033[4;35m' # Purple 115 | UCyan = '\033[4;36m' # Cyan 116 | UWhite = '\033[4;37m' # White 117 | 118 | # Background 119 | On_Black = '\033[40m' # Black 120 | On_Red = '\033[41m' # Red 121 | On_Green = '\033[42m' # Green 122 | On_Yellow = '\033[43m' # Yellow 123 | On_Blue = '\033[44m' # Blue 124 | On_Purple = '\033[45m' # Purple 125 | On_Cyan = '\033[46m' # Cyan 126 | On_White = '\033[47m' # White 127 | 128 | # High Intensity 129 | IBlack = '\033[0;90m' # Black 130 | IRed = '\033[0;91m' # Red 131 | IGreen = '\033[0;92m' # Green 132 | IYellow = '\033[0;93m' # Yellow 133 | IBlue = '\033[0;94m' # Blue 134 | IPurple = '\033[0;95m' # Purple 135 | ICyan = '\033[0;96m' # Cyan 136 | IWhite = '\033[0;97m' # White 137 | 138 | # Bold High Intensity 139 | BIBlack = '\033[1;90m' # Black 140 | BIRed = '\033[1;91m' # Red 141 | BIGreen = '\033[1;92m' # Green 142 | BIYellow = '\033[1;93m' # Yellow 143 | BIBlue = '\033[1;94m' # Blue 144 | BIPurple = '\033[1;95m' # Purple 145 | BICyan = '\033[1;96m' # Cyan 146 | BIWhite = '\033[1;97m' # White 147 | 148 | # High Intensity backgrounds 149 | On_IBlack = '\033[0;100m' # Black 150 | On_IRed = '\033[0;101m' # Red 151 | On_IGreen = '\033[0;102m' # Green 152 | On_IYellow = '\033[0;103m' # Yellow 153 | On_IBlue = '\033[0;104m' # Blue 154 | On_IPurple = '\033[0;105m' # Purple 155 | On_ICyan = '\033[0;106m' # Cyan 156 | On_IWhite = '\033[0;107m' # White -------------------------------------------------------------------------------- /pyA20/i2c/i2c.c: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * This file is part of pyA20. 4 | * i2c.c is python I2C extension. 5 | * 6 | * Copyright (c) 2014 Stefan Mavrodiev @ OLIMEX LTD, 7 | * 8 | * pyA20 is free software; you can redistribute it and/or modify 9 | * it under the terms of the GNU General Public License as published by 10 | * the Free Software Foundation; either version 2 of the License, or 11 | * (at your option) any later version. 12 | * 13 | * This program is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | * GNU General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU General Public License 19 | * along with this program; if not, write to the Free Software 20 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 21 | * MA 02110-1301, USA. 22 | */ 23 | 24 | #include "Python.h" 25 | 26 | #if PY_MAJOR_VERSION >= 3 27 | #define PyInt_FromLong PyLong_FromLong 28 | #define PyInt_AsLong PyLong_AsLong 29 | #endif 30 | 31 | #include "i2c_lib.h" 32 | 33 | /* Define some global variables */ 34 | char bus[30]; 35 | int address; 36 | int fd; 37 | 38 | /** 39 | * Initialize module by giving bus name. 40 | * 41 | * @param self 42 | * @param args string with the name of the i2c bus 43 | * @return none 44 | */ 45 | static PyObject* py_init(PyObject* self, PyObject* args) { 46 | 47 | char *temp; 48 | 49 | /* Parse arguments */ 50 | if (!PyArg_ParseTuple(args, "s", &temp)) { 51 | return NULL; 52 | } 53 | 54 | /* Copy name to the global variable */ 55 | strcpy(bus, temp); 56 | 57 | Py_RETURN_NONE; 58 | } 59 | 60 | /** 61 | * Read n bytes from i2c-bus 62 | * 63 | * @param self 64 | * @param args number of bytes to read 65 | * @return tuple containing the read bytes 66 | */ 67 | static PyObject* py_read(PyObject* self, PyObject* args) { 68 | 69 | int bytes; 70 | int i; 71 | 72 | PyObject *pylist = 0; 73 | PyObject *item = 0; 74 | 75 | /* Parse arguments */ 76 | if (!PyArg_ParseTuple(args, "i", &bytes)) { 77 | return NULL; 78 | } 79 | 80 | /* If bytes are <= 0 this could cause segmentation fault */ 81 | if (bytes <= 0) { 82 | PyErr_SetString(PyExc_ValueError, "i2c read: invalid number of bytes to read"); 83 | return NULL; 84 | } 85 | 86 | /* Allocate memory for the temp buffer */ 87 | uint8_t *read_buffer = (uint8_t *) malloc(bytes * sizeof (uint8_t)); 88 | 89 | 90 | /* Read bytes and check return status */ 91 | if (i2c_read(fd, read_buffer, bytes) < 0) { 92 | Py_DECREF(pylist); 93 | // Py_DECREF(item); 94 | free(read_buffer); 95 | return PyErr_SetFromErrno(PyExc_IOError); 96 | } 97 | 98 | /* Make new list with size n bytes */ 99 | pylist = PyList_New(bytes); 100 | 101 | /* Fill list with data from read_buffer */ 102 | if (pylist != NULL) { 103 | for (i = 0; i < bytes; i++) { 104 | item = PyInt_FromLong(read_buffer[i]); 105 | PyList_SET_ITEM(pylist, i, item); 106 | } 107 | } 108 | 109 | /* Cleanup */ 110 | free(read_buffer); 111 | // Py_DECREF(item); 112 | 113 | /* Return list */ 114 | return pylist; 115 | } 116 | 117 | /** 118 | * Open I2C device 119 | * 120 | * @param self 121 | * @param args 122 | * @return 123 | */ 124 | static PyObject* py_open(PyObject* self, PyObject* args) { 125 | 126 | /* Parse arguments */ 127 | if (!PyArg_ParseTuple(args, "i", &address)) { 128 | return NULL; 129 | } 130 | 131 | /* Open slave device*/ 132 | fd = i2c_open(bus, address); 133 | if (fd < 0) { 134 | return PyErr_SetFromErrno(PyExc_IOError); 135 | } 136 | 137 | Py_RETURN_NONE; 138 | } 139 | 140 | /** 141 | * Write bytes to I2C slave device 142 | * 143 | * @param self 144 | * @param args bytes to send 145 | * @return none 146 | */ 147 | static PyObject* py_write(PyObject* self, PyObject* args) { 148 | 149 | PyObject *list = 0; 150 | PyObject *item = 0; 151 | 152 | /* Parse arguments */ 153 | if (!PyArg_ParseTuple(args, "O!", &PyList_Type, &list)) { 154 | return NULL; 155 | } 156 | 157 | /* Get length of the list */ 158 | uint8_t n = PyList_Size(list); 159 | 160 | 161 | /* Allocate memory */ 162 | uint8_t *buffer = (uint8_t*)malloc(n * sizeof(uint8_t)); 163 | 164 | /* Populate output buffer */ 165 | uint8_t i; 166 | for (i = 0; i < n; i++) { 167 | item = PyList_GetItem(list, i); 168 | buffer[i] = (unsigned char) PyInt_AsLong(item); 169 | } 170 | 171 | /* Send data */ 172 | if (i2c_send(fd, buffer, n) < 0) { 173 | return PyErr_SetFromErrno(PyExc_IOError); 174 | } 175 | 176 | /* Do cleanup */ 177 | free(buffer); 178 | Py_DECREF(list); 179 | // Py_DECREF(item); 180 | 181 | Py_RETURN_NONE; 182 | } 183 | 184 | /** 185 | * Close communication with I2C slave device 186 | * 187 | * @param self 188 | * @param args none 189 | * @return none 190 | */ 191 | static PyObject* py_close(PyObject* self, PyObject *args) { 192 | 193 | /* Close file descriptor */ 194 | if (i2c_close(fd) < 0) { 195 | return PyErr_SetFromErrno(PyExc_IOError); 196 | } 197 | Py_RETURN_NONE; 198 | } 199 | 200 | static PyMethodDef module_methods[] = { 201 | {"init", py_init, METH_VARARGS, "Initialize module"}, 202 | {"open", py_open, METH_VARARGS, "Open file descriptor"}, 203 | {"close", py_close, METH_NOARGS, "Close file descriptor"}, 204 | {"read", py_read, METH_VARARGS, "Read n bytes from I2C bus"}, 205 | {"write", py_write, METH_VARARGS, "Write n bytes to I2C bus"}, 206 | {NULL, NULL, 0, NULL} 207 | }; 208 | 209 | #if PY_MAJOR_VERSION >= 3 210 | static struct PyModuleDef module_def = { 211 | PyModuleDef_HEAD_INIT, 212 | "i2c", 213 | NULL, 214 | -1, 215 | module_methods 216 | }; 217 | #endif 218 | 219 | PyMODINIT_FUNC 220 | #if PY_MAJOR_VERSION >= 3 221 | PyInit_i2c(void) { 222 | #else 223 | initi2c(void) { 224 | #endif 225 | 226 | PyObject* module = NULL; 227 | 228 | #if PY_MAJOR_VERSION >= 3 229 | module = PyModule_Create(&module_def); 230 | #else 231 | module = Py_InitModule("i2c", module_methods); 232 | #endif 233 | 234 | 235 | if (module == NULL) 236 | #if PY_MAJOR_VERSION >= 3 237 | return NULL; 238 | #else 239 | return; 240 | #endif 241 | 242 | #if PY_MAJOR_VERSION >= 3 243 | return module; 244 | #else 245 | return; 246 | #endif 247 | 248 | } 249 | 250 | 251 | 252 | -------------------------------------------------------------------------------- /pyA20/gpio/gpio.c: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * This file is part of pyA20. 4 | * gpio.c is python GPIO extension. 5 | * 6 | * Copyright (c) 2014 Stefan Mavrodiev @ OLIMEX LTD, 7 | * 8 | * pyA20 is free software; you can redistribute it and/or modify 9 | * it under the terms of the GNU General Public License as published by 10 | * the Free Software Foundation; either version 2 of the License, or 11 | * (at your option) any later version. 12 | * 13 | * This program is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | * GNU General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU General Public License 19 | * along with this program; if not, write to the Free Software 20 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 21 | * MA 02110-1301, USA. 22 | */ 23 | 24 | 25 | #include "Python.h" 26 | #include "gpio_lib.h" 27 | 28 | /** 29 | * Set output value of GPIO. Pin must be configured as output or else raises 30 | * exception. For high output level - 1, low - 0. 31 | * 32 | * @param self 33 | * @param args Tuple that holds GPIO number and value 34 | * @return none 35 | */ 36 | static PyObject* py_output(PyObject* self, PyObject* args) { 37 | 38 | int gpio; 39 | int value; 40 | 41 | /* Parse arguments. Two integers are required. */ 42 | if (!PyArg_ParseTuple(args, "ii", &gpio, &value)) 43 | return NULL; 44 | 45 | /* Set output value and check return status. */ 46 | if (sunxi_gpio_output(gpio, value) < 0) { 47 | return PyErr_SetFromErrno(PyExc_IOError); 48 | } 49 | 50 | Py_RETURN_NONE; 51 | } 52 | 53 | /** 54 | * Read value of the pin configured as input. If its output raises exception. 55 | * 56 | * @param self 57 | * @param args GPIO number 58 | * @return value of the given pin 59 | */ 60 | static PyObject* py_input(PyObject* self, PyObject* args) { 61 | 62 | int gpio; 63 | int ret; 64 | 65 | /* Parse argument. One integer is required */ 66 | if (!PyArg_ParseTuple(args, "i", &gpio)) 67 | return NULL; 68 | 69 | /* Read value */ 70 | ret = sunxi_gpio_input(gpio); 71 | if (ret < 0) { 72 | return PyErr_SetFromErrno(PyExc_IOError); 73 | } 74 | 75 | /* Return read value */ 76 | return Py_BuildValue("i", ret); 77 | } 78 | 79 | /** 80 | * Set configuration. See A20 datasheet for correct values. 81 | * 82 | * @param self 83 | * @param args GPIO number and configuration value 84 | * @return none 85 | */ 86 | static PyObject* py_setcfg(PyObject* self, PyObject* args) { 87 | 88 | int gpio; 89 | int cfg; 90 | 91 | /* Parse arguments. Require two integers for GPIO number and configuration */ 92 | if (!PyArg_ParseTuple(args, "ii", &gpio, &cfg)) 93 | return NULL; 94 | 95 | /* Set configuration and check return status */ 96 | if (sunxi_gpio_set_cfgpin(gpio, cfg) < 0) { 97 | return PyErr_SetFromErrno(PyExc_IOError); 98 | } 99 | 100 | Py_RETURN_NONE; 101 | } 102 | 103 | /** 104 | * Read current configuration of GPIO. 105 | * 106 | * @param self 107 | * @param args GPIO number 108 | * @return current configuration 109 | */ 110 | static PyObject* py_getcfg(PyObject* self, PyObject* args) { 111 | 112 | int gpio; 113 | int ret; 114 | 115 | /* Parse arguments */ 116 | if (!PyArg_ParseTuple(args, "i", &gpio)) 117 | return NULL; 118 | 119 | /* Read configuration*/ 120 | ret = sunxi_gpio_get_cfgpin(gpio); 121 | if (ret < 0) { 122 | return PyErr_SetFromErrno(PyExc_IOError); 123 | } 124 | 125 | /* Return configuration */ 126 | return Py_BuildValue("i", ret); 127 | } 128 | 129 | /** 130 | * 131 | * Make initial initialization of the extention. This is done by map physical 132 | * memory to the virtual and thus gaining access to the memory. From there we 133 | * can do anything. 134 | * 135 | * @return none 136 | */ 137 | static PyObject* py_init(PyObject* self, PyObject* args) { 138 | 139 | if(sunxi_gpio_init() < 0){ 140 | return PyErr_SetFromErrno(PyExc_IOError); 141 | } 142 | 143 | Py_RETURN_NONE; 144 | } 145 | 146 | /** 147 | * Set pull-up/pull-down on pin defined as input. 148 | * 149 | * @param self 150 | * @param args 151 | * @return 152 | */ 153 | static PyObject* py_pullup(PyObject* self, PyObject* args) { 154 | 155 | int gpio; 156 | int pull; 157 | 158 | /* Parse arguments */ 159 | if(!PyArg_ParseTuple(args, "ii", &gpio, &pull)) 160 | return NULL; 161 | 162 | /* Set pull-up */ 163 | if(sunxi_gpio_pullup(gpio, pull) < 0){ 164 | return PyErr_SetFromErrno(PyExc_IOError); 165 | } 166 | 167 | Py_RETURN_NONE; 168 | } 169 | 170 | 171 | /* Define module methods */ 172 | static PyMethodDef module_methods[] = { 173 | {"init", py_init, METH_NOARGS, "Initialize module"}, 174 | {"setcfg", py_setcfg, METH_VARARGS, "Set pin function"}, 175 | {"getcfg", py_getcfg, METH_VARARGS, "Get pin function"}, 176 | {"output", py_output, METH_VARARGS, "Set output state"}, 177 | {"pullup", py_pullup, METH_VARARGS, "Set pull-up/pull-down"}, 178 | {"input", py_input, METH_VARARGS, "Get input state"}, 179 | {NULL, NULL, 0, NULL} 180 | }; 181 | 182 | #if PY_MAJOR_VERSION >= 3 183 | static struct PyModuleDef module_def = { 184 | PyModuleDef_HEAD_INIT, 185 | "gpio", 186 | NULL, 187 | -1, 188 | module_methods 189 | }; 190 | #endif 191 | 192 | PyMODINIT_FUNC 193 | #if PY_MAJOR_VERSION >= 3 194 | PyInit_gpio(void) { 195 | #else 196 | initgpio(void) { 197 | #endif 198 | 199 | PyObject* module = NULL; 200 | 201 | 202 | #if PY_MAJOR_VERSION >= 3 203 | module = PyModule_Create(&module_def); 204 | #else 205 | module = Py_InitModule("gpio", module_methods); 206 | #endif 207 | 208 | 209 | if (module == NULL) 210 | #if PY_MAJOR_VERSION >= 3 211 | return NULL; 212 | #else 213 | return; 214 | #endif 215 | 216 | PyModule_AddObject(module, "HIGH", Py_BuildValue("i", 1)); 217 | PyModule_AddObject(module, "LOW", Py_BuildValue("i", 0)); 218 | PyModule_AddObject(module, "INPUT", Py_BuildValue("i", SUNXI_GPIO_INPUT)); 219 | PyModule_AddObject(module, "OUTPUT", Py_BuildValue("i", SUNXI_GPIO_OUTPUT)); 220 | 221 | PyModule_AddObject(module, "PULLUP", Py_BuildValue("i", SUNXI_PULL_UP)); 222 | PyModule_AddObject(module, "PULLDOWN", Py_BuildValue("i", SUNXI_PULL_DOWN)); 223 | 224 | 225 | #if PY_MAJOR_VERSION >= 3 226 | return module; 227 | #else 228 | return; 229 | #endif 230 | } -------------------------------------------------------------------------------- /PKG-INFO: -------------------------------------------------------------------------------- 1 | Metadata-Version: 1.1 2 | Name: pyA20 3 | Version: 0.2.1 4 | Summary: Control GPIO, I2C and SPI 5 | Home-page: https://www.olimex.com/ 6 | Author: Stefan Mavrodiev 7 | Author-email: support@olimex.com 8 | License: MIT 9 | Description: This package provide methods for controlling GPIO pins, I2C and SPI buses. 10 | This is written for A20-OLinuXino-MICRO, but it can be used with other boards. If you do 11 | this we cannot guarantee proper operation of the module. Before using this 12 | package we recommend reading the article at olimex wiki: 13 | 14 | https://www.olimex.com/wiki/A20-OLinuXino-MICRO 15 | 16 | When using GPIO make sure that the desired gpio is not used by another periphery. 17 | 18 | GPIO METHODS 19 | ============ 20 | 21 | init() - Make initialization of the module. Always must be called first. 22 | getcfg() - Read current configuration of gpio. 23 | setcfg() - Write configuration to gpio. 24 | input() - Return current value of gpio. 25 | output() - Set output value. 26 | pullup() - Set pull-up/pull-down. 27 | 28 | 29 | The available constants are: 30 | 31 | NAME - EQUALS TO 32 | ==== ========= 33 | HIGH -> 1 34 | LOW -> 0 35 | INPUT -> 0 36 | OUPTUT -> 1 37 | PULLUP -> 1 38 | PULLDOWN -> 2 39 | 40 | 41 | The gpio are named two ways: 42 | 43 | By port name: PH0, PG2, PE10, etc. 44 | These can be imported from port module: 45 | 46 | >>> from pyA20.gpio import port 47 | >>> dir(port) 48 | 49 | By connector name and pin number: gpio2p12, gpio3p8, lcdp18, uext1p3 and etc. 50 | These can be imported from connector module: 51 | 52 | >>> from pyA20.gpio import connector 53 | >>> dir(connector) 54 | 55 | Generally these constants are just an offset in the memory from the base GPIO address, so they can 56 | be assigned to a number type variable. 57 | 58 | >>> led = port.PH2 59 | >>> print led 60 | 226 61 | 62 | 63 | 64 | I2C METHODS 65 | =========== 66 | 67 | init() - Make initialization of the module 68 | open() - Begin communication with slave device 69 | read() - Read from slave device 70 | write() - Write data to slave device 71 | close() - End communication with slave device 72 | 73 | 74 | SPI METHODS 75 | =========== 76 | 77 | open() - Open SPI bus with given configuration 78 | read() - Read data from slave device without write 79 | write() - Write data to slave device without read 80 | xfer() - Do write and after that read 81 | close() - Close SPI bus 82 | 83 | 84 | 85 | Examples 86 | ======== 87 | 88 | GPIO:: 89 | 90 | #!/usr/bin/env python 91 | 92 | from pyA20.gpio import gpio 93 | from pyA20.gpio import port 94 | from pyA20.gpio import connector 95 | 96 | gpio.init() #Initialize module. Always called first 97 | 98 | gpio.setcfg(port.PG9, gpio.OUTPUT) #Configure LED1 as output 99 | gpio.setcfg(port.PG9, 1) #This is the same as above 100 | 101 | gpio.setcfg(port.PE11, gpio.INPUT) #Configure PE11 as input 102 | gpio.setcfg(port.PE11, 0) #Same as above 103 | 104 | gpio.pullup(port.PE11, 0) #Clear pullups 105 | gpio.pullup(port.PE11, gpio.PULLDOWN) #Enable pull-down 106 | gpio.pullup(port.PE11, gpio.PULLUP) #Enable pull-up 107 | 108 | while True: 109 | if gpio.input(port.PE11) == 1: 110 | gpio.output(port.PG9, gpio.LOW) 111 | gpio.output(port.PG9, 0) 112 | else: 113 | gpio.output(port.PG9, gpio.HIGH) 114 | gpio.output(port.PG9, 1) 115 | 116 | 117 | I2C:: 118 | 119 | #!/usr/bin/env python 120 | 121 | from pyA20 import i2c 122 | 123 | i2c.init("/dev/i2c-2") #Initialize module to use /dev/i2c-2 124 | i2c.open(0x55) #The slave device address is 0x55 125 | 126 | #If we want to write to some register 127 | i2c.write([0xAA, 0x20]) #Write 0x20 to register 0xAA 128 | i2c.write([0xAA, 0x10, 0x11, 0x12]) #Do continuous write with start address 0xAA 129 | 130 | #If we want to do write and read 131 | i2c.write([0xAA]) #Set address at 0xAA register 132 | value = i2c.read(1) #Read 1 byte with start address 0xAA 133 | 134 | i2c.close() #End communication with slave device 135 | 136 | 137 | SPI:: 138 | 139 | #!/usr/bin/env python 140 | 141 | from pyA20 import spi 142 | 143 | spi.open("/dev/spidev2.0") 144 | #Open SPI device with default settings 145 | # mode : 0 146 | # speed : 100000kHz 147 | # delay : 0 148 | # bits-per-word: 8 149 | 150 | #Different ways to open device 151 | spi.open("/dev/spidev2.0", mode=1) 152 | spi.open("/dev/spidev2.0", mode=2, delay=0) 153 | spi.open("/dev/spidev2.0", mode=3, delay=0, bits_per_word=8) 154 | spi.open("/dev/spidev2.0", mode=0, delay=0, bits_per_word=8, speed=100000) 155 | 156 | spi.write([0x01, 0x02]) #Write 2 bytes to slave device 157 | spi.read(2) #Read 2 bytes from slave device 158 | spi.xfer([0x01, 0x02], 2) #Write 2 byte and then read 2 bytes. 159 | 160 | spi.close() #Close SPI bus 161 | 162 | 163 | It's important that you run your python script as root! 164 | 165 | 166 | Changelog 167 | ========= 168 | * pyA20 0.2.1 (30 JUN 2015) 169 | * Fixed gpio1 connector constants 170 | * Fixed issue with SPI xfer function 171 | 172 | * pyA20 0.2.0 (02 SEP 2014) 173 | * Updated to enable SPI and I2C control 174 | * GPIO constant in separate modules 175 | * Added example files 176 | * Added support for Python3 177 | 178 | Platform: UNKNOWN 179 | Classifier: Development Status :: 3 - Alpha 180 | Classifier: Environment :: Console 181 | Classifier: Intended Audience :: Developers 182 | Classifier: Intended Audience :: Education 183 | Classifier: License :: OSI Approved :: MIT License 184 | Classifier: Operating System :: POSIX :: Linux 185 | Classifier: Programming Language :: Python 186 | Classifier: Topic :: Home Automation 187 | Classifier: Topic :: Software Development :: Embedded Systems 188 | -------------------------------------------------------------------------------- /pyA20/spi/spi.c: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * This file is part of pyA20. 4 | * spi.c is python SPI extension. 5 | * 6 | * Copyright (c) 2014 Stefan Mavrodiev @ OLIMEX LTD, 7 | * 8 | * pyA20 is free software; you can redistribute it and/or modify 9 | * it under the terms of the GNU General Public License as published by 10 | * the Free Software Foundation; either version 2 of the License, or 11 | * (at your option) any later version. 12 | * 13 | * This program is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | * GNU General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU General Public License 19 | * along with this program; if not, write to the Free Software 20 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 21 | * MA 02110-1301, USA. 22 | */ 23 | 24 | #include "Python.h" 25 | 26 | #if PY_MAJOR_VERSION >= 3 27 | #define PyInt_FromLong PyLong_FromLong 28 | #define PyInt_AsLong PyLong_AsLong 29 | #endif 30 | 31 | 32 | #include "spi_lib.h" 33 | #include "../utilities/color.h" 34 | 35 | #include 36 | #include 37 | #include 38 | #include 39 | #include 40 | 41 | int fd; 42 | 43 | #ifdef __DEBUG 44 | #define debug(format, args...) printf("%s", CYAN); printf(format, args); printf("%s", ESC); 45 | #else 46 | #define debug(...) ((void)0) 47 | #endif 48 | 49 | 50 | /** 51 | * Read n bytes from slave device 52 | * 53 | * @param self 54 | * @param args number of bytes 55 | * @return tuple with read elements 56 | */ 57 | static PyObject* py_read(PyObject *self, PyObject* args){ 58 | 59 | PyObject *rx_list = 0; 60 | PyObject *item = 0; 61 | uint8_t rx_len = 0; 62 | 63 | /* Parse arguments */ 64 | if(!PyArg_ParseTuple(args, "i", &rx_len)){ 65 | return NULL; 66 | } 67 | 68 | /* Alocate memmory for buffer*/ 69 | uint8_t *rx_buffer = (uint8_t*)malloc(rx_len * sizeof(uint8_t)); 70 | memset(rx_buffer, 0, sizeof(uint8_t)*rx_len); 71 | 72 | /* Read from device*/ 73 | if(spi_read(fd, rx_buffer, rx_len) < 0){ 74 | return PyErr_SetFromErrno(PyExc_IOError); 75 | } 76 | 77 | /* Make list */ 78 | rx_list = PyList_New(rx_len); 79 | 80 | /* Populate list */ 81 | uint8_t i; 82 | for(i = 0; i < rx_len; i++){ 83 | item = PyInt_FromLong(rx_buffer[i]); 84 | PyList_SET_ITEM(rx_list, i, item); 85 | } 86 | 87 | /* Do cleanup*/ 88 | free(rx_buffer); 89 | //Py_DECREF(item); 90 | 91 | /* Return list */ 92 | return rx_list; 93 | } 94 | 95 | /** 96 | * Write bytes to slave device 97 | * 98 | * @param self 99 | * @param args Tuple with data to write 100 | * @return none 101 | */ 102 | static PyObject* py_write(PyObject *self, PyObject* args){ 103 | 104 | PyObject *tx_list; 105 | PyObject *item = 0; 106 | uint8_t tx_len = 0; 107 | 108 | /* Parse arguments */ 109 | if(!PyArg_ParseTuple(args, "O!", &PyList_Type, &tx_list)){ 110 | return NULL; 111 | } 112 | 113 | /* Get length of list */ 114 | tx_len = PyList_Size(tx_list); 115 | 116 | /* Allocate memory for output buffer */ 117 | uint8_t *tx_buffer = (uint8_t *)malloc(tx_len * sizeof(uint8_t)); 118 | memset(tx_buffer, 0, sizeof(uint8_t)); 119 | 120 | /* Populate output buffer */ 121 | int i; 122 | for(i = 0; i < tx_len; i++){ 123 | item = PyList_GetItem(tx_list, i); 124 | tx_buffer[i] = (uint8_t)PyInt_AsLong(item); 125 | } 126 | 127 | /* Send data */ 128 | if(spi_write(fd, tx_buffer, tx_len) < 0){ 129 | return PyErr_SetFromErrno(PyExc_IOError); 130 | } 131 | 132 | /* Do cleanup */ 133 | free(tx_buffer); 134 | 135 | //Py_DECREF(item); 136 | Py_DECREF(tx_list); 137 | 138 | Py_RETURN_NONE; 139 | } 140 | 141 | 142 | /** 143 | * Do transfer of data to slave device 144 | * 145 | * @param self 146 | * @param args tuple of data to read and 147 | * @return list with read data 148 | */ 149 | static PyObject* py_xfer(PyObject* self, PyObject* args){ 150 | 151 | PyObject *tx_list = 0; 152 | PyObject *rx_list = 0; 153 | PyObject *item = 0; 154 | 155 | uint8_t tx_len; 156 | uint8_t rx_len; 157 | 158 | /* Parse arguments */ 159 | if(!PyArg_ParseTuple(args, "O!i", &PyList_Type, &tx_list, &rx_len)){ 160 | return NULL; 161 | } 162 | 163 | /* Get length of output data */ 164 | tx_len = PyList_Size(tx_list); 165 | 166 | /* Allocate memory for sending */ 167 | uint8_t* tx_buffer; 168 | uint8_t* rx_buffer; 169 | 170 | tx_buffer = (uint8_t *)malloc(tx_len * sizeof(uint8_t)); 171 | rx_buffer = (uint8_t *)malloc(rx_len * sizeof(uint8_t)); 172 | 173 | memset(rx_buffer, 0, sizeof(uint8_t)*rx_len); 174 | 175 | /* Populate both output buffer */ 176 | int i; 177 | for(i = 0; i < tx_len; i++){ 178 | item = PyList_GetItem(tx_list, i); 179 | tx_buffer[i] = (uint8_t)PyInt_AsLong(item); 180 | } 181 | 182 | /* Do the transaction */ 183 | if(spi_xfer(fd, tx_buffer, tx_len, rx_buffer, rx_len) < 0){ 184 | return PyErr_SetFromErrno(PyExc_IOError); 185 | } 186 | 187 | /* Make new list*/ 188 | rx_list = PyList_New(rx_len); 189 | 190 | /* Populate the new list */ 191 | for(i = 0; i < rx_len; i++){ 192 | item = PyInt_FromLong(rx_buffer[i]); 193 | PyList_SET_ITEM(rx_list, i, item); 194 | } 195 | 196 | /* Do cleanup */ 197 | free(tx_buffer); 198 | free(rx_buffer); 199 | 200 | Py_DECREF(tx_list); 201 | //Py_DECREF(item); 202 | 203 | return rx_list; 204 | } 205 | 206 | /** 207 | * Open SPI device with given configuration 208 | * 209 | * @param self 210 | * @param args 211 | * @param kwargs 212 | * @return none 213 | */ 214 | static PyObject* py_open(PyObject* self, PyObject* args, PyObject* kwargs){ 215 | 216 | int ret; 217 | char *device; 218 | spi_config_t config = {0}; 219 | 220 | /* Set default values */ 221 | config.mode = 0; 222 | config.bits_per_word = 8; 223 | config.speed = 100000; 224 | config.delay = 0; 225 | 226 | /* Define keywords */ 227 | static char *kwlist [] = { 228 | "device", "mode", "bits_per_word", "speed", "delay", NULL 229 | }; 230 | 231 | /* Parse arguments */ 232 | if(!PyArg_ParseTupleAndKeywords( 233 | args, kwargs, "s|iiii", kwlist, 234 | &device, 235 | &config.mode, 236 | &config.bits_per_word, 237 | &config.speed, 238 | &config.delay)){ 239 | return NULL; 240 | } 241 | 242 | /* Open the device */ 243 | ret = spi_open(device, config); 244 | 245 | if(ret < 0 ){ 246 | return PyErr_SetFromErrno(PyExc_IOError); 247 | }else{ 248 | fd = ret; 249 | } 250 | 251 | Py_RETURN_NONE; 252 | } 253 | 254 | /** 255 | * Close file descriptor for SPI bus 256 | * 257 | * @param self 258 | * @param args 259 | * @return none 260 | */ 261 | static PyObject* py_close(PyObject* self, PyObject* args){ 262 | 263 | int ret; 264 | 265 | ret = spi_close(fd); 266 | if(ret < 0){ 267 | return PyErr_SetFromErrno(PyExc_IOError); 268 | }else{ 269 | fd = 0; 270 | } 271 | 272 | Py_RETURN_NONE; 273 | } 274 | PyMethodDef module_methods[] = { 275 | {"open", (PyCFunction)py_open, METH_VARARGS | METH_KEYWORDS, "Open file dssescriptor"}, 276 | {"xfer", py_xfer, METH_VARARGS, "Transfer data"}, 277 | {"write", py_write, METH_VARARGS, "Write data"}, 278 | {"read", py_read, METH_VARARGS, "Read data"}, 279 | {"close", py_close, METH_NOARGS, "Close file descriptor"}, 280 | {NULL, NULL, 0, NULL} 281 | }; 282 | 283 | #if PY_MAJOR_VERSION >= 3 284 | static struct PyModuleDef module_def = { 285 | PyModuleDef_HEAD_INIT, 286 | "spi", 287 | NULL, 288 | -1, 289 | module_methods 290 | }; 291 | #endif 292 | 293 | PyMODINIT_FUNC 294 | #if PY_MAJOR_VERSION >= 3 295 | PyInit_spi(void) { 296 | #else 297 | initspi(void) { 298 | #endif 299 | #pragma GCC diagnostic ignored "-Wunused-but-set-variable" 300 | PyObject* module = NULL; 301 | 302 | 303 | #if PY_MAJOR_VERSION >= 3 304 | module = PyModule_Create(&module_def); 305 | #else 306 | module = Py_InitModule("spi", module_methods); 307 | #endif 308 | 309 | 310 | #if PY_MAJOR_VERSION >= 3 311 | return module; 312 | #else 313 | return; 314 | #endif 315 | 316 | } 317 | -------------------------------------------------------------------------------- /pyA20/gpio/mapping.h.backA20.h: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * This file is part of pyA20. 4 | * mapping.h is python GPIO extension. 5 | * 6 | * Copyright (c) 2014 Stefan Mavrodiev @ OLIMEX LTD, 7 | * 8 | * pyA20 is free software; you can redistribute it and/or modify 9 | * it under the terms of the GNU General Public License as published by 10 | * the Free Software Foundation; either version 2 of the License, or 11 | * (at your option) any later version. 12 | * 13 | * This program is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | * GNU General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU General Public License 19 | * along with this program; if not, write to the Free Software 20 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 21 | * MA 02110-1301, USA. 22 | */ 23 | 24 | #ifndef __MAPPING_H 25 | #define __MAPPING_H 26 | 27 | #include "gpio_lib.h" 28 | 29 | /** 30 | Structure that describe all gpio 31 | */ 32 | typedef struct _pin { 33 | char name[10]; // The processor pin 34 | int offset; // Memory offset for the pin 35 | int pin_number; // Number on the connector 36 | }pin_t; 37 | 38 | typedef struct _gpio { 39 | char connector_name[10]; 40 | pin_t pins[41]; 41 | }gpio_t; 42 | 43 | 44 | gpio_t gpio[] = { 45 | {"lcd", 46 | { 47 | { "PD16", SUNXI_GPD(16), 5 }, 48 | { "PD17", SUNXI_GPD(17), 6 }, 49 | { "PD18", SUNXI_GPD(18), 7 }, 50 | { "PD19", SUNXI_GPD(19), 8 }, 51 | { "PD20", SUNXI_GPD(20), 9 }, 52 | { "PD21", SUNXI_GPD(21), 10 }, 53 | { "PD22", SUNXI_GPD(22), 11 }, 54 | { "PD23", SUNXI_GPD(23), 12 }, 55 | { "PD8", SUNXI_GPD(8), 13 }, 56 | { "PD9", SUNXI_GPD(9), 14 }, 57 | { "PD10", SUNXI_GPD(10), 15 }, 58 | { "PD11", SUNXI_GPD(11), 16 }, 59 | { "PD12", SUNXI_GPD(12), 17 }, 60 | { "PD13", SUNXI_GPD(13), 18 }, 61 | { "PD14", SUNXI_GPD(14), 19 }, 62 | { "PD15", SUNXI_GPD(15), 20 }, 63 | { "PD0", SUNXI_GPD(0), 21 }, 64 | { "PD1", SUNXI_GPD(1), 22 }, 65 | { "PD2", SUNXI_GPD(2), 23 }, 66 | { "PD3", SUNXI_GPD(3), 24 }, 67 | { "PD4", SUNXI_GPD(4), 25 }, 68 | { "PD5", SUNXI_GPD(5), 26 }, 69 | { "PD6", SUNXI_GPD(6), 27 }, 70 | { "PD7", SUNXI_GPD(7), 28 }, 71 | { "PD26", SUNXI_GPD(26), 29 }, 72 | { "PD27", SUNXI_GPD(27), 30 }, 73 | { "PD24", SUNXI_GPD(24), 31 }, 74 | { "PD25", SUNXI_GPD(25), 32 }, 75 | { "PH8", SUNXI_GPH(8), 35 }, 76 | { "PB2", SUNXI_GPB(2), 36 }, 77 | { 78 | { 0, 0, 0} 79 | }, 80 | } 81 | }, 82 | /* 83 | #define PIN_PG0 SUNXI_GPG(0) 84 | #define PIN_PG1 SUNXI_GPG(1) 85 | #define PIN_PG2 SUNXI_GPG(2) 86 | #define PIN_PG3 SUNXI_GPG(3) 87 | #define PIN_PG4 SUNXI_GPG(4) 88 | #define PIN_PG5 SUNXI_GPG(5) 89 | #define PIN_PG6 SUNXI_GPG(6) 90 | #define PIN_PG7 SUNXI_GPG(7) 91 | #define PIN_PG8 SUNXI_GPG(8) 92 | #define PIN_PG9 SUNXI_GPG(9) 93 | #define PIN_PG10 SUNXI_GPG(10) 94 | #define PIN_PG11 SUNXI_GPG(11) 95 | */ {"gpio1", 96 | { 97 | { "PG0", SUNXI_GPG(0), 5 }, 98 | { "PG1", SUNXI_GPG(1), 7 }, 99 | { "PG2", SUNXI_GPG(2), 9 }, 100 | { "PG3", SUNXI_GPG(3), 11 }, 101 | { "PG4", SUNXI_GPG(4), 13 }, 102 | { "PG5", SUNXI_GPG(5), 15 }, 103 | { "PG6", SUNXI_GPG(6), 17 }, 104 | { "PG7", SUNXI_GPG(7), 19 }, 105 | { "PG8", SUNXI_GPG(8), 21 }, 106 | { "PG9", SUNXI_GPG(9), 23 }, 107 | { "PG10", SUNXI_GPG(10), 25 }, 108 | { "PG11", SUNXI_GPG(11), 27 }, 109 | { 110 | { 0, 0, 0} 111 | }, 112 | } 113 | }, 114 | 115 | /* 116 | //GPIO 2 117 | #define PIN_PE0 SUNXI_GPE(0) 118 | #define PIN_PE1 SUNXI_GPE(1) 119 | #define PIN_PI0 SUNXI_GPI(0) 120 | #define PIN_PE2 SUNXI_GPE(2) 121 | #define PIN_PI1 SUNXI_GPI(1) 122 | #define PIN_PE3 SUNXI_GPE(3) 123 | #define PIN_PI2 SUNXI_GPI(2) 124 | #define PIN_PE4 SUNXI_GPE(4) 125 | #define PIN_PI3 SUNXI_GPI(3) 126 | #define PIN_PE5 SUNXI_GPE(5) 127 | #define PIN_PI10 SUNXI_GPI(10) 128 | #define PIN_PE6 SUNXI_GPE(6) 129 | #define PIN_PI11 SUNXI_GPI(11) 130 | #define PIN_PE7 SUNXI_GPE(7) 131 | #define PIN_PC3 SUNXI_GPC(3) 132 | #define PIN_PE8 SUNXI_GPE(8) 133 | #define PIN_PC7 SUNXI_GPC(7) 134 | #define PIN_PE9 SUNXI_GPE(9) 135 | #define PIN_PC16 SUNXI_GPC(16) 136 | #define PIN_PE10 SUNXI_GPE(10) 137 | #define PIN_PC17 SUNXI_GPC(17) 138 | #define PIN_PE11 SUNXI_GPE(11) 139 | #define PIN_PC18 SUNXI_GPC(18) 140 | #define PIN_PI14 SUNXI_GPI(14) 141 | #define PIN_PC23 SUNXI_GPC(23) 142 | #define PIN_PI15 SUNXI_GPI(15) 143 | #define PIN_PC24 SUNXI_GPC(24) 144 | #define PIN_PB23 SUNXI_GPB(23) 145 | #define PIN_PB22 SUNXI_GPB(22) 146 | */ 147 | {"gpio2", 148 | { 149 | { "PE0", SUNXI_GPE(0), 6 }, 150 | { "PE1", SUNXI_GPE(1), 8 }, 151 | { "PI0", SUNXI_GPI(0), 9 }, 152 | { "PE2", SUNXI_GPE(2), 10 }, 153 | { "PI1", SUNXI_GPI(1), 11 }, 154 | { "PE3", SUNXI_GPE(3), 12 }, 155 | { "PI2", SUNXI_GPI(2), 13 }, 156 | { "PE4", SUNXI_GPE(4), 14 }, 157 | { "PI3", SUNXI_GPI(3), 15 }, 158 | { "PE5", SUNXI_GPE(5), 16 }, 159 | { "PI10", SUNXI_GPI(10), 17 }, 160 | { "PE6", SUNXI_GPE(6), 18 }, 161 | { "PI11", SUNXI_GPI(11), 19 }, 162 | { "PE7", SUNXI_GPE(7), 20 }, 163 | { "PC3", SUNXI_GPC(3), 21 }, 164 | { "PE8", SUNXI_GPE(8), 22 }, 165 | { "PC7", SUNXI_GPC(7), 23 }, 166 | { "PE9", SUNXI_GPE(9), 24 }, 167 | { "PC16", SUNXI_GPC(16), 25 }, 168 | { "PE10", SUNXI_GPE(10), 26 }, 169 | { "PC17", SUNXI_GPC(17), 27 }, 170 | { "PE11", SUNXI_GPE(11), 28 }, 171 | { "PC18", SUNXI_GPC(18), 29 }, 172 | { "PI14", SUNXI_GPI(14), 30 }, 173 | { "PC23", SUNXI_GPC(23), 31 }, 174 | { "PI15", SUNXI_GPI(15), 32 }, 175 | { "PC24", SUNXI_GPC(24), 33 }, 176 | { "PB23", SUNXI_GPB(23), 34 }, 177 | { "PB22", SUNXI_GPB(22), 36 }, 178 | { 179 | { 0, 0, 0} 180 | }, 181 | } 182 | }, 183 | 184 | /* 185 | //GPIO 3 186 | #define PIN_PH0 SUNXI_GPH(0) 187 | #define PIN_PB3 SUNXI_GPB(3) 188 | #define PIN_PH2 SUNXI_GPH(2) 189 | #define PIN_PB4 SUNXI_GPB(4) 190 | #define PIN_PH7 SUNXI_GPH(7) 191 | #define PIN_PB5 SUNXI_GPB(5) 192 | #define PIN_PH9 SUNXI_GPH(9) 193 | #define PIN_PB6 SUNXI_GPB(6) 194 | #define PIN_PH10 SUNXI_GPH(10) 195 | #define PIN_PB7 SUNXI_GPB(7) 196 | #define PIN_PH11 SUNXI_GPH(11) 197 | #define PIN_PB8 SUNXI_GPB(8) 198 | #define PIN_PH12 SUNXI_GPH(12) 199 | #define PIN_PB10 SUNXI_GPB(10) 200 | #define PIN_PH13 SUNXI_GPH(13) 201 | #define PIN_PB11 SUNXI_GPB(11) 202 | #define PIN_PH14 SUNXI_GPH(14) 203 | #define PIN_PB12 SUNXI_GPB(12) 204 | #define PIN_PH15 SUNXI_GPH(15) 205 | #define PIN_PB13 SUNXI_GPB(13) 206 | #define PIN_PH16 SUNXI_GPH(16) 207 | #define PIN_PB14 SUNXI_GPB(14) 208 | #define PIN_PH17 SUNXI_GPH(17) 209 | #define PIN_PB15 SUNXI_GPB(15) 210 | #define PIN_PH18 SUNXI_GPH(18) 211 | #define PIN_PB16 SUNXI_GPB(16) 212 | #define PIN_PH19 SUNXI_GPH(19) 213 | #define PIN_PB17 SUNXI_GPB(17) 214 | #define PIN_PH20 SUNXI_GPH(20) 215 | #define PIN_PH24 SUNXI_GPH(24) 216 | #define PIN_PH21 SUNXI_GPH(21) 217 | #define PIN_PH25 SUNXI_GPH(25) 218 | #define PIN_PH22 SUNXI_GPH(22) 219 | #define PIN_PH26 SUNXI_GPH(26) 220 | #define PIN_PH23 SUNXI_GPH(23) 221 | #define PIN_PH27 SUNXI_GPH(27) 222 | */ 223 | {"gpio3", 224 | { 225 | { "PH0", SUNXI_GPH(0), 5 }, 226 | { "PB3", SUNXI_GPB(3), 6 }, 227 | { "PH2", SUNXI_GPH(2), 7 }, 228 | { "PB4", SUNXI_GPB(4), 8 }, 229 | { "PH7", SUNXI_GPH(7), 9 }, 230 | { "PB5", SUNXI_GPB(5), 10 }, 231 | { "PH9", SUNXI_GPH(9), 11 }, 232 | { "PB6", SUNXI_GPB(6), 12 }, 233 | { "PH10", SUNXI_GPH(10), 13 }, 234 | { "PB7", SUNXI_GPB(7), 14 }, 235 | { "PH11", SUNXI_GPH(11), 15 }, 236 | { "PB8", SUNXI_GPB(8), 16 }, 237 | { "PH12", SUNXI_GPH(12), 17 }, 238 | { "PB10", SUNXI_GPB(10), 18 }, 239 | { "PH13", SUNXI_GPH(13), 19 }, 240 | { "PB11", SUNXI_GPB(11), 20 }, 241 | { "PH14", SUNXI_GPH(14), 21 }, 242 | { "PB12", SUNXI_GPB(12), 22 }, 243 | { "PH15", SUNXI_GPH(15), 23 }, 244 | { "PB13", SUNXI_GPB(13), 24 }, 245 | { "PH16", SUNXI_GPH(16), 25 }, 246 | { "PB14", SUNXI_GPB(14), 26 }, 247 | { "PH17", SUNXI_GPH(17), 27 }, 248 | { "PB15", SUNXI_GPB(15), 28 }, 249 | { "PH18", SUNXI_GPH(18), 29 }, 250 | { "PB16", SUNXI_GPB(16), 30 }, 251 | { "PH19", SUNXI_GPH(19), 31 }, 252 | { "PB17", SUNXI_GPB(17), 32 }, 253 | { "PH20", SUNXI_GPH(20), 33 }, 254 | { "PH24", SUNXI_GPH(24), 34 }, 255 | { "PH21", SUNXI_GPH(21), 35 }, 256 | { "PH25", SUNXI_GPH(25), 36 }, 257 | { "PH22", SUNXI_GPH(22), 37 }, 258 | { "PH26", SUNXI_GPH(26), 38 }, 259 | { "PH23", SUNXI_GPH(23), 39 }, 260 | { "PH27", SUNXI_GPH(27), 40 }, 261 | { 262 | { 0, 0, 0} 263 | }, 264 | } 265 | }, 266 | 267 | 268 | {"uext1", 269 | { 270 | { "PI12", SUNXI_GPI(12), 3 }, 271 | { "PI13", SUNXI_GPI(13), 4 }, 272 | { "PB20", SUNXI_GPB(20), 5 }, 273 | { "PB21", SUNXI_GPB(21), 6 }, 274 | { "PC22", SUNXI_GPC(22), 7 }, 275 | { "PC21", SUNXI_GPC(21), 8 }, 276 | { "PC20", SUNXI_GPC(20), 9 }, 277 | { "PC19", SUNXI_GPC(19), 10 }, 278 | { 279 | { 0, 0, 0} 280 | }, 281 | } 282 | }, 283 | 284 | {"uext2", 285 | { 286 | { "PI20", SUNXI_GPI(20), 3 }, 287 | { "PI21", SUNXI_GPI(21), 4 }, 288 | { "PB18", SUNXI_GPB(18), 5 }, 289 | { "PB19", SUNXI_GPB(19), 6 }, 290 | { "PI19", SUNXI_GPI(19), 7 }, 291 | { "PI18", SUNXI_GPI(18), 8 }, 292 | { "PI17", SUNXI_GPI(17), 9 }, 293 | { "PI16", SUNXI_GPI(16), 10 }, 294 | { 295 | { 0, 0, 0} 296 | }, 297 | } 298 | }, 299 | }; 300 | 301 | 302 | 303 | #endif 304 | --------------------------------------------------------------------------------