From: Limor "Ladyada" Fried Date: Thu, 28 Jun 2018 19:03:29 +0000 (-0700) Subject: Merge pull request #13 from tannewt/raspi X-Git-Tag: 0.1.0 X-Git-Url: https://git.ayoreis.com/Adafruit_Blinka-hackapet.git/commitdiff_plain/09422b62c65b439c46f0f15178f541ea30e88423?hp=f8fda4a76906791017ac9004b76837ce80699be7 Merge pull request #13 from tannewt/raspi Raspi --- diff --git a/.travis.yml b/.travis.yml index 252c176..98cdc4d 100755 --- a/.travis.yml +++ b/.travis.yml @@ -1,8 +1,3 @@ -# This is a common .travis.yml for generating library release zip files for -# CircuitPython library releases using circuitpython-build-tools. -# See https://github.com/adafruit/circuitpython-build-tools for detailed setup -# instructions. - dist: trusty sudo: false language: python @@ -13,14 +8,6 @@ cache: pip: true deploy: - - provider: releases - api_key: $GITHUB_TOKEN - file_glob: true - file: bundles/* - skip_cleanup: true - overwrite: true - on: - tags: true - provider: pypi user: adafruit-travis password: @@ -29,10 +16,10 @@ deploy: tags: true install: + - pip install -r requirements.txt - pip install pylint circuitpython-build-tools Sphinx sphinx-rtd-theme script: - pylint src/**/*.py - ([[ ! -d "examples" ]] || pylint --disable=missing-docstring,invalid-name,bad-whitespace examples/*.py) - - circuitpython-build-bundles --filename_prefix adafruit-circuitpython-blinka --library_location . - cd docs && sphinx-build -E -W -b html . _build/html diff --git a/README.rst b/README.rst old mode 100644 new mode 100755 index 127131d..e94a478 --- a/README.rst +++ b/README.rst @@ -9,8 +9,8 @@ Introduction :target: https://discord.gg/nBQh6qu :alt: Discord -.. image:: https://travis-ci.org/adafruit/Adafruit_Micropython_Blinka.svg?branch=master - :target: https://travis-ci.org/adafruit/Adafruit__Micropython_Blinka +.. image:: https://travis-ci.org/adafruit/Adafruit_Blinka.svg?branch=master + :target: https://travis-ci.org/adafruit/Adafruit_Blinka :alt: Build Status This repository contains a selection of packages mirroring the CircuitPython API @@ -32,13 +32,13 @@ are running Micropython. Since corresponding packages should be built-in to any CircuitPython image, they have no value on a device already running CircuitPython and would likely conflict in unhappy ways. The test suites in the test/src folder under **testing.universal** are by design -intended to run on *either* CircuitPython *or* Micropython+compatibility layer to prove conformance. +intended to run on *either* CircuitPython *or* Micropython+compatibility layer to prove conformance. Usage Example ============= At the time of writing (`git:7fc1f8ab `_), -the following sequence runs through some basic testing of the digitalio compatibility layer... +the following sequence runs through some basic testing of the digitalio compatibility layer... .. code-block:: python @@ -52,7 +52,7 @@ Contributing ============ Contributions are welcome! Please read our `Code of Conduct -`_ +`_ before contributing to help this project stay welcoming. Building locally diff --git a/examples/pi_busio_i2c.py b/examples/pi_busio_i2c.py new file mode 100755 index 0000000..93f59e6 --- /dev/null +++ b/examples/pi_busio_i2c.py @@ -0,0 +1,27 @@ +import time +import board +import busio + +print("hello blinka!") + +i2c = busio.I2C(board.SCL, board.SDA) + +print("I2C devices found: ", [hex(i) for i in i2c.scan()]) + +if not 0x18 in i2c.scan(): + print("Didn't find MCP9808") + exit() + +def temp_c(data): + value = data[0] << 8 | data[1] + temp = (value & 0xFFF) / 16.0 + if value & 0x1000: + temp -= 256.0 + return temp + +while True: + i2c.writeto(0x18, bytes([0x05]), stop=False) + result = bytearray(2) + i2c.readfrom_into(0x18, result) + print(temp_c(result)) + time.sleep(0.5) diff --git a/examples/pi_busio_spi.py b/examples/pi_busio_spi.py new file mode 100755 index 0000000..e0592e9 --- /dev/null +++ b/examples/pi_busio_spi.py @@ -0,0 +1,13 @@ +import time +import board +import busio + +spi = busio.SPI(board.SCLK, board.MOSI, board.MISO) +while not spi.try_lock(): + pass +spi.configure(baudrate=16000000) +spi.unlock() + +while True: + spi.write(bytes([x for x in range(64)])) + time.sleep(0.1) diff --git a/examples/pi_digitalio.py b/examples/pi_digitalio.py new file mode 100755 index 0000000..7c6a622 --- /dev/null +++ b/examples/pi_digitalio.py @@ -0,0 +1,16 @@ +import time +import board +import digitalio + +print("hello blinka!") + +led = digitalio.DigitalInOut(board.D4) +led.direction = digitalio.Direction.OUTPUT + +button = digitalio.DigitalInOut(board.D18) +button.direction = digitalio.Direction.INPUT +button.pull = digitalio.Pull.DOWN + +while True: + led.value = button.value + time.sleep(0.1) diff --git a/examples/piblinka.py b/examples/piblinka.py new file mode 100755 index 0000000..56978a4 --- /dev/null +++ b/examples/piblinka.py @@ -0,0 +1,27 @@ +import sys +import time +from adafruit_blinka.agnostic import board as agnostic_board +import board +import digitalio + +#from Adafruit_GPIO import Platform +#print("Platform = ", Platform.platform_detect(), Platform.pi_version()) + +print("hello blinka!") + +print("Found system type: %s (sys.plaform %s implementation %s) " % + (agnostic_board, sys.platform, sys.implementation.name)) + +print("board contents: ", dir(board)) + + +led = digitalio.DigitalInOut(board.D4) +led.direction = digitalio.Direction.OUTPUT + +button = digitalio.DigitalInOut(board.D18) +button.direction = digitalio.Direction.INPUT +button.pull = digitalio.Pull.DOWN + +while True: + led.value = button.value + time.sleep(0.1) diff --git a/requirements.txt b/requirements.txt new file mode 100755 index 0000000..8bd5314 --- /dev/null +++ b/requirements.txt @@ -0,0 +1 @@ +Adafruit-GPIO diff --git a/setup.py b/setup.py old mode 100644 new mode 100755 index 26933ef..370f556 --- a/setup.py +++ b/setup.py @@ -21,9 +21,8 @@ REQUIRES_PYTHON = '>=3.6.0' VERSION = None # What packages are required for this module to be executed? -REQUIRED = [ - # 'requests', 'maya', 'records', -] +with open('requirements.txt') as f: + requirements = f.read().splitlines() here = os.path.abspath(os.path.dirname(__file__)) @@ -106,7 +105,7 @@ setup( # entry_points={ # 'console_scripts': ['mycli=mymodule:cli'], # }, - install_requires=REQUIRED, + install_requires=requirements, include_package_data=True, license='MIT', classifiers=[ diff --git a/src/adafruit_blinka/agnostic/__init__.py b/src/adafruit_blinka/agnostic/__init__.py index 8d60cff..89d0646 100755 --- a/src/adafruit_blinka/agnostic/__init__.py +++ b/src/adafruit_blinka/agnostic/__init__.py @@ -4,10 +4,7 @@ environment is established, can choose various routes to make available and re-export common modules and operations, depending on platform support """ -import gc import sys -gc.collect() - # We intentionally are patching into this namespace as module names so skip the name check. # pylint: disable=invalid-name @@ -22,10 +19,18 @@ if microcontroller is not None: elif microcontroller == "pyboard": microcontroller = "stm32" board = "pyboard" + elif microcontroller == "linux": + from Adafruit_GPIO import Platform + if Platform.platform_detect() == Platform.RASPBERRY_PI: + if Platform.pi_version() == 1: + board = "raspi_1" + elif Platform.pi_version() == 2: + board = "raspi_2" + elif Platform.pi_version() == 3: + board = "raspi_3" implementation = sys.implementation.name if implementation == "micropython": from utime import sleep -elif implementation == "circuitpython": +elif implementation == "circuitpython" or implementation == "cpython": from time import sleep -gc.collect() diff --git a/src/adafruit_blinka/board/raspi_23.py b/src/adafruit_blinka/board/raspi_23.py new file mode 100644 index 0000000..fd0f370 --- /dev/null +++ b/src/adafruit_blinka/board/raspi_23.py @@ -0,0 +1,18 @@ +from adafruit_blinka.microcontroller.raspi_23 import pin + +SDA = pin.SDA +SCL = pin.SCL +D2 = pin.D2 +D3 = pin.D3 +D4 = pin.D4 +D9 = pin.D9 +D10 = pin.D10 +D11 = pin.D11 +MISO = pin.D9 +MOSI = pin.D10 +SCLK = pin.D11 +D14 = pin.D14 +D15 = pin.D15 +D17 = pin.D17 +D18 = pin.D18 +D19 = pin.D19 diff --git a/src/adafruit_blinka/microcontroller/raspi_23/__init__.py b/src/adafruit_blinka/microcontroller/raspi_23/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/src/adafruit_blinka/microcontroller/raspi_23/i2c.py b/src/adafruit_blinka/microcontroller/raspi_23/i2c.py new file mode 100644 index 0000000..edac8db --- /dev/null +++ b/src/adafruit_blinka/microcontroller/raspi_23/i2c.py @@ -0,0 +1,41 @@ +import Adafruit_PureIO.smbus as smbus +import time + +class I2C: + MASTER = 0 + SLAVE = 1 + _baudrate = None + _mode = None + _i2c_bus = None + + def __init__(self, bus_num, mode=MASTER, baudrate=None): + if mode != self.MASTER: + raise NotImplementedError("Only I2C Master supported!") + _mode = self.MASTER + + #if baudrate != None: + # print("I2C frequency is not settable in python, ignoring!") + + try: + self._i2c_bus = smbus.SMBus(bus_num) + except FileNotFoundError: + raise RuntimeError("I2C Bus #%d not found, check if enabled in config!" % bus_num) + + def scan(self): + """Try to read a byte from each address, if you get an OSError it means the device isnt there""" + found = [] + for addr in range(0,0x80): + try: + self._i2c_bus.read_byte(addr) + except OSError: + continue + found.append(addr) + return found + + def writeto(self, address, buffer, stop=True): + self._i2c_bus.write_bytes(address, buffer) + + def readfrom_into(self, address, buffer, stop=True): + readin = self._i2c_bus.read_bytes(address, len(buffer)) + for i in range(len(buffer)): + buffer[i] = readin[i] diff --git a/src/adafruit_blinka/microcontroller/raspi_23/pin.py b/src/adafruit_blinka/microcontroller/raspi_23/pin.py new file mode 100644 index 0000000..4cca6ee --- /dev/null +++ b/src/adafruit_blinka/microcontroller/raspi_23/pin.py @@ -0,0 +1,99 @@ +import RPi.GPIO as GPIO +GPIO.setmode(GPIO.BCM) + +# Pins dont exist in CPython so...lets make our own! +class Pin: + IN = 0 + OUT = 1 + LOW = 0 + HIGH = 1 + PULL_NONE = 0 + PULL_UP = 1 + PULL_DOWN = 2 + + id = None + _value = LOW + _mode = IN + + def __init__(self, bcm_number): + self.id = bcm_number + + def __repr__(self): + return str(self.id) + + def __eq__(self, other): + return self.id == other + + def init(self, mode=IN, pull=None): + if mode != None: + if mode == self.IN: + self._mode = self.IN + GPIO.setup(self.id, GPIO.IN) + elif mode == self.OUT: + self._mode = self.OUT + GPIO.setup(self.id, GPIO.OUT) + else: + raise RuntimeError("Invalid mode for pin: %s" % self.id) + if pull != None: + if self._mode != self.IN: + raise RuntimeError("Cannot set pull resistor on output") + if pull == self.PULL_UP: + GPIO.setup(self.id, GPIO.IN, pull_up_down=GPIO.PUD_UP) + elif pull == self.PULL_DOWN: + GPIO.setup(self.id, GPIO.IN, pull_up_down=GPIO.PUD_DOWN) + else: + raise RuntimeError("Invalid pull for pin: %s" % self.id) + + def value(self, val=None): + if val != None: + if val == self.LOW: + self._value = val + GPIO.output(self.id, val) + elif val == self.HIGH: + self._value = val + GPIO.output(self.id, val) + else: + raise RuntimeError("Invalid value for pin") + else: + return GPIO.input(self.id) + +SDA = Pin(2) +SCL = Pin(3) +D2 = Pin(2) +D3 = Pin(3) +D4 = Pin(4) +D9 = Pin(9) +D10 = Pin(10) +D11 = Pin(11) +MISO = Pin(9) +MOSI = Pin(10) +SCLK = Pin(11) +D14 = Pin(14) +D15 = Pin(15) +TXD = Pin(14) +RXD = Pin(15) +D17 = Pin(17) +D18 = Pin(18) +D19 = Pin(19) +D20 = Pin(20) +MISO_2 = Pin(19) +MOSI_2 = Pin(20) +SCLK_2 = Pin(21) +D21 = Pin(21) +D22 = Pin(22) +D23 = Pin(23) +D24 = Pin(24) +D27 = Pin(27) + +# ordered as spiId, sckId, mosiId, misoId +spiPorts = ((0, SCLK, MOSI, MISO), (1, SCLK_2, MOSI_2, MISO_2)) + +# ordered as uartId, txId, rxId +uartPorts = ( + (1, TXD, RXD), +) + +i2cPorts = ( + (1, SCL, SDA), +) + diff --git a/src/adafruit_blinka/microcontroller/raspi_23/spi.py b/src/adafruit_blinka/microcontroller/raspi_23/spi.py new file mode 100644 index 0000000..d6627c6 --- /dev/null +++ b/src/adafruit_blinka/microcontroller/raspi_23/spi.py @@ -0,0 +1,47 @@ +import spidev +import time + +class SPI: + MSB = 0 + LSB = 1 + CPHA = 1 + CPOL = 2 + + baudrate = 100000 + mode = 0 + bits = 8 + + def __init__(self, portid): + self._port = portid + self._spi = spidev.SpiDev() + + def init(self, baudrate=100000, polarity=0, phase=0, bits=8, + firstbit=MSB, sck=None, mosi=None, miso=None): + mode = 0 + if polarity: + mode |= CPOL + if phase: + mode |= CPHA + + self.clock_pin = sck + self.mosi_pin = mosi + self.miso_pin = miso + self.baudrate = baudrate + self.mode = mode + self.bits = bits + + def write(self, buf): + if not buf: + return + try: + + self._spi.open(self._port, 0) + self._spi.no_cs = True + self._spi.max_speed_hz = self.baudrate + self._spi.mode = self.mode + self._spi.bits_per_word = self.bits + self._spi.writebytes([x for x in buf]) + self._spi.close() + except FileNotFoundError as not_found: + print("Could not open SPI device - check if SPI is enabled in kernel!") + raise diff --git a/src/board.py b/src/board.py index d1c04c4..b941174 100755 --- a/src/board.py +++ b/src/board.py @@ -37,6 +37,8 @@ elif board == "nodemcu": from adafruit_blinka.board.nodemcu import * elif board == "pyboard": from adafruit_blinka.board.pyboard import * +elif board == "raspi_2" or board == "raspi_3": + from adafruit_blinka.board.raspi_23 import * elif "sphinx" in sys.modules: pass else: diff --git a/src/busio.py b/src/busio.py index 6c5e76f..915547a 100755 --- a/src/busio.py +++ b/src/busio.py @@ -8,6 +8,7 @@ See `CircuitPython:busio` in CircuitPython for more details. """ from adafruit_blinka import Enum, Lockable, agnostic +from adafruit_blinka.agnostic import board as boardId class I2C(Lockable): def __init__(self, scl, sda, frequency=400000): @@ -15,11 +16,14 @@ class I2C(Lockable): def init(self, scl, sda, frequency): self.deinit() - from machine import I2C as _I2C + if boardId == "raspi_3" or boardId == "raspi_2": + from adafruit_blinka.microcontroller.raspi_23.i2c import I2C as _I2C + else: + from machine import I2C as _I2C from microcontroller.pin import i2cPorts for portId, portScl, portSda in i2cPorts: if scl == portScl and sda == portSda: - self._i2c = I2C(portId, mode=_I2C.MASTER, baudrate=frequency) + self._i2c = _I2C(portId, mode=_I2C.MASTER, baudrate=frequency) break else: raise NotImplementedError("No Hardware I2C on (scl,sda)={}\nValid UART ports".format( @@ -59,27 +63,38 @@ class I2C(Lockable): class SPI(Lockable): def __init__(self, clock, MOSI=None, MISO=None): + self.deinit() + if boardId == "raspi_3" or boardId == "raspi_2": + from adafruit_blinka.microcontroller.raspi_23.spi import SPI as _SPI + else: + from machine import SPI as _SPI from microcontroller.pin import spiPorts for portId, portSck, portMosi, portMiso in spiPorts: if clock == portSck and MOSI == portMosi and MISO == portMiso: - self._spi = SPI(portId) + self._spi = _SPI(portId) self._pins = (portSck, portMosi, portMiso) break else: raise NotImplementedError( - "No Hardware SPI on (clock, MOSI, MISO)={}\nValid SPI ports:{}". + "No Hardware SPI on (SCLK, MOSI, MISO)={}\nValid SPI ports:{}". format((clock, MOSI, MISO), spiPorts)) def configure(self, baudrate=100000, polarity=0, phase=0, bits=8): - if self._locked: + if boardId == "raspi_3" or boardId == "raspi_2": + from adafruit_blinka.microcontroller.raspi_23.spi import SPI as _SPI + from adafruit_blinka.microcontroller.raspi_23.pin import Pin + else: + from machine import SPI as _SPI from machine import Pin + + if self._locked: # TODO check if #init ignores MOSI=None rather than unsetting, to save _pinIds attribute self._spi.init( baudrate=baudrate, polarity=polarity, phase=phase, bits=bits, - firstbit=SPI.MSB, + firstbit=_SPI.MSB, sck=Pin(self._pins[0].id), mosi=Pin(self._pins[1].id), miso=Pin(self._pins[2].id) diff --git a/src/digitalio.py b/src/digitalio.py index 8fb5385..84aeebd 100755 --- a/src/digitalio.py +++ b/src/digitalio.py @@ -7,8 +7,11 @@ See `CircuitPython:digitalio` in CircuitPython for more details. * Author(s): cefn """ -from machine import Pin from adafruit_blinka.agnostic import board as boardId +if boardId == "raspi_3" or boardId == "raspi_2": + from adafruit_blinka.microcontroller.raspi_23.pin import Pin +else: + from machine import Pin from adafruit_blinka import Enum, ContextManaged class DriveMode(Enum): diff --git a/src/microcontroller/__init__.py b/src/microcontroller/__init__.py index 5957a91..c22a03c 100755 --- a/src/microcontroller/__init__.py +++ b/src/microcontroller/__init__.py @@ -1,6 +1,7 @@ """Microcontroller pins""" from adafruit_blinka import Enum, agnostic +from adafruit_blinka.agnostic import board as board_id class Pin(Enum): """Reference Pin object""" @@ -26,5 +27,10 @@ if agnostic.microcontroller == "esp8266": from adafruit_blinka.microcontroller.esp8266 import * elif agnostic.microcontroller == "stm32": from adafruit_blinka.microcontroller.stm32 import * +elif agnostic.microcontroller == "linux": + if board_id == "raspi_3" or board_id == "raspi_2": + from adafruit_blinka.microcontroller.raspi_23 import * + else: + raise NotImplementedError("Board not supported: ", board_id) else: - raise NotImplementedError("Microcontroller not supported") + raise NotImplementedError("Microcontroller not supported: ", agnostic.microcontroller) diff --git a/src/microcontroller/pin.py b/src/microcontroller/pin.py index 2109544..5c58dfc 100755 --- a/src/microcontroller/pin.py +++ b/src/microcontroller/pin.py @@ -9,5 +9,10 @@ if agnostic.microcontroller == "esp8266": from adafruit_blinka.microcontroller.esp8266.pin import * elif agnostic.microcontroller == "stm32": from adafruit_blinka.microcontroller.stm32.pin import * +elif agnostic.microcontroller == "linux": + if agnostic.board == "raspi_3" or agnostic.board == "raspi_2": + from adafruit_blinka.microcontroller.raspi_23.pin import * + else: + raise NotImplementedError("Board not supported: ", agnostic.board) else: raise NotImplementedError("Microcontroller not supported") diff --git a/src/micropython.py b/src/micropython.py new file mode 100644 index 0000000..7aaaca6 --- /dev/null +++ b/src/micropython.py @@ -0,0 +1,3 @@ +class const: + def __new__(self, x): + return x