Skip to content

Commit e199972

Browse files
authored
Merge pull request #51 from brentru/mock-pwmout-digitalio
DigitalIO Class for ESP32SPI
2 parents 868dd5e + 8599c01 commit e199972

File tree

1 file changed

+209
-0
lines changed

1 file changed

+209
-0
lines changed

adafruit_esp32spi/digitalio.py

Lines changed: 209 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,209 @@
1+
# The MIT License (MIT)
2+
#
3+
# Copyright (c) 2019 Brent Rubell for Adafruit Industries
4+
#
5+
# Permission is hereby granted, free of charge, to any person obtaining a copy
6+
# of this software and associated documentation files (the "Software"), to deal
7+
# in the Software without restriction, including without limitation the rights
8+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
# copies of the Software, and to permit persons to whom the Software is
10+
# furnished to do so, subject to the following conditions:
11+
#
12+
# The above copyright notice and this permission notice shall be included in
13+
# all copies or substantial portions of the Software.
14+
#
15+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21+
# THE SOFTWARE.
22+
"""
23+
`digitalio`
24+
==============================
25+
DigitalIO for ESP32 over SPI.
26+
27+
* Author(s): Brent Rubell, based on Adafruit_Blinka digitalio implementation
28+
and bcm283x Pin implementation.
29+
https://github.com/adafruit/Adafruit_Blinka/blob/master/src/adafruit_blinka/microcontroller/bcm283x/pin.py
30+
https://github.com/adafruit/Adafruit_Blinka/blob/master/src/digitalio.py
31+
"""
32+
from micropython import const
33+
34+
class Pin:
35+
"""
36+
Implementation of CircuitPython API Pin Handling
37+
for ESP32SPI.
38+
39+
:param int esp_pin: Valid ESP32 GPIO Pin, predefined in ESP32_GPIO_PINS.
40+
:param ESP_SPIcontrol esp: The ESP object we are using.
41+
42+
NOTE: This class does not currently implement reading digital pins
43+
or the use of internal pull-up resistors.
44+
"""
45+
#pylint: disable=invalid-name
46+
IN = const(0x00)
47+
OUT = const(0x01)
48+
LOW = const(0x00)
49+
HIGH = const(0x01)
50+
_value = LOW
51+
_mode = IN
52+
pin_id = None
53+
54+
ESP32_GPIO_PINS = set([0, 1, 2, 4, 5,
55+
12, 13, 14, 15,
56+
16, 17, 18, 19,
57+
21, 22, 23, 25,
58+
26, 27, 32, 33])
59+
60+
def __init__(self, esp_pin, esp):
61+
if esp_pin in self.ESP32_GPIO_PINS:
62+
self.pin_id = esp_pin
63+
else:
64+
raise AttributeError("Pin %d is not a valid ESP32 GPIO Pin."%esp_pin)
65+
self._esp = esp
66+
67+
def init(self, mode=IN):
68+
"""Initalizes a pre-defined pin.
69+
:param mode: Pin mode (IN, OUT, LOW, HIGH). Defaults to IN.
70+
"""
71+
if mode is not None:
72+
if mode == self.IN:
73+
self._mode = self.IN
74+
self._esp.set_pin_mode(self.pin_id, 0)
75+
elif mode == self.OUT:
76+
self._mode = self.OUT
77+
self._esp.set_pin_mode(self.pin_id, 1)
78+
else:
79+
raise RuntimeError("Invalid mode defined")
80+
81+
def value(self, val=None):
82+
"""Sets ESP32 Pin GPIO output mode.
83+
:param val: Pin output level (LOW, HIGH)
84+
"""
85+
if val is not None:
86+
if val == self.LOW:
87+
self._value = val
88+
self._esp.set_digital_write(self.pin_id, 0)
89+
elif val == self.HIGH:
90+
self._value = val
91+
self._esp.set_digital_write(self.pin_id, 1)
92+
else:
93+
raise RuntimeError("Invalid value for pin")
94+
else:
95+
raise NotImplementedError("digitalRead not currently implemented in esp32spi")
96+
97+
def __repr__(self):
98+
return str(self.pin_id)
99+
100+
# pylint: disable = too-few-public-methods
101+
class DriveMode():
102+
"""DriveMode Enum."""
103+
PUSH_PULL = None
104+
OPEN_DRAIN = None
105+
DriveMode.PUSH_PULL = DriveMode()
106+
DriveMode.OPEN_DRAIN = DriveMode()
107+
108+
109+
class Direction():
110+
"""DriveMode Enum."""
111+
INPUT = None
112+
OUTPUT = None
113+
Direction.INPUT = Direction()
114+
Direction.OUTPUT = Direction()
115+
116+
117+
class DigitalInOut():
118+
"""Implementation of DigitalIO module for ESP32SPI.
119+
120+
:param ESP_SPIcontrol esp: The ESP object we are using.
121+
:param int pin: Valid ESP32 GPIO Pin, predefined in ESP32_GPIO_PINS.
122+
"""
123+
_pin = None
124+
#pylint: disable = attribute-defined-outside-init
125+
def __init__(self, esp, pin):
126+
self._esp = esp
127+
self._pin = Pin(pin, self._esp)
128+
self.direction = Direction.INPUT
129+
130+
def __enter__(self):
131+
return self
132+
133+
def __exit__(self, exception_type, exception_value, traceback):
134+
self.deinit()
135+
136+
def deinit(self):
137+
"""De-initializes the pin object."""
138+
self._pin = None
139+
140+
def switch_to_output(self, value=False, drive_mode=DriveMode.PUSH_PULL):
141+
"""Set the drive mode and value and then switch to writing out digital values.
142+
:param bool value: Default mode to set upon switching.
143+
:param DriveMode drive_mode: Drive mode for the output.
144+
"""
145+
self._direction = Direction.OUTPUT
146+
self._drive_mode = drive_mode
147+
self.value = value
148+
149+
def switch_to_input(self, pull=None):
150+
"""Sets the pull and then switch to read in digital values.
151+
:param Pull pull: Pull configuration for the input.
152+
"""
153+
raise NotImplementedError("Digital reads are not currently supported in ESP32SPI.")
154+
155+
@property
156+
def direction(self):
157+
"""Returns the pin's direction."""
158+
return self.__direction
159+
160+
@direction.setter
161+
def direction(self, pin_dir):
162+
"""Sets the direction of the pin.
163+
:param Direction dir: Pin direction (Direction.OUTPUT or Direction.INPUT)
164+
"""
165+
self.__direction = pin_dir
166+
if pin_dir is Direction.OUTPUT:
167+
self._pin.init(mode=Pin.OUT)
168+
self.value = False
169+
self.drive_mode = DriveMode.PUSH_PULL
170+
elif pin_dir is Direction.INPUT:
171+
self._pin.init(mode=Pin.IN)
172+
else:
173+
raise AttributeError("Not a Direction")
174+
175+
@property
176+
def value(self):
177+
"""Returns the digital logic level value of the pin."""
178+
return self._pin.value() is 1
179+
180+
@value.setter
181+
def value(self, val):
182+
"""Sets the digital logic level of the pin.
183+
:param type value: Pin logic level.
184+
:param int value: Pin logic level. 1 is logic high, 0 is logic low.
185+
:param bool value: Pin logic level. True is logic high, False is logic low.
186+
"""
187+
if self.direction is Direction.OUTPUT:
188+
self._pin.value(1 if val else 0)
189+
else:
190+
raise AttributeError("Not an output")
191+
192+
@property
193+
def drive_mode(self):
194+
"""Returns pin drive mode."""
195+
if self.direction is Direction.OUTPUT:
196+
return self._drive_mode
197+
raise AttributeError("Not an output")
198+
199+
@drive_mode.setter
200+
def drive_mode(self, mode):
201+
"""Sets the pin drive mode.
202+
:param DriveMode mode: Defines the drive mode when outputting digital values.
203+
Either PUSH_PULL or OPEN_DRAIN
204+
"""
205+
self.__drive_mode = mode
206+
if mode is DriveMode.OPEN_DRAIN:
207+
raise NotImplementedError('Drive mode %s not implemented in ESP32SPI.'%mode)
208+
elif mode is DriveMode.PUSH_PULL:
209+
self._pin.init(mode=Pin.OUT)

0 commit comments

Comments
 (0)