]> Repositories - Adafruit_Blinka-hackapet.git/blob - src/adafruit_blinka/microcontroller/bcm283x/pin.py
Update pin.py
[Adafruit_Blinka-hackapet.git] / src / adafruit_blinka / microcontroller / bcm283x / pin.py
1 # SPDX-FileCopyrightText: 2021 Melissa LeBlanc-Williams for Adafruit Industries
2 #
3 # SPDX-License-Identifier: MIT
4 """Broadcom BCM283x pin names"""
5 from pathlib import Path
6 import lgpio
7
8 def _get_gpiochip():
9     """
10     Determines the handle of the GPIO chip device to access.
11
12     iterate through sysfs  to find a GPIO chip device with a driver known to be
13     used for userspace GPIO access.
14     """
15     for dev in Path('/sys/bus/gpio/devices').glob('gpiochip*'):
16         drivers = set((dev / 'of_node/compatible').read_text().split('\0'))
17         #   check if driver names are intended for userspace control
18         if drivers & {'raspberrypi,rp1-gpio',
19                       'raspberrypi,bcm2835-gpio',
20                       'raspberrypi,bcm2711-gpio'}:
21             return lgpio.gpiochip_open(int(dev.name[-1]))
22     # return chip0 as a fallback
23     return lgpio.gpiochip_open(0)
24
25
26 CHIP = _get_gpiochip()
27
28
29 class Pin:
30     """Pins dont exist in CPython so...lets make our own!"""
31
32     LOW = 0
33     HIGH = 1
34     OFF = LOW
35     ON = HIGH
36
37     # values of lg mode constants
38     PULL_NONE = 0x80
39     PULL_UP = 0x20
40     PULL_DOWN = 0x40
41     ACTIVE_LOW = 0x02
42
43     # drive mode lg constants
44     OPEN_DRAIN = 0x04
45     IN = 0x0100
46     OUT = 0x0200
47
48     # LG mode constants
49     _LG_ALERT = 0x400
50     _LG_GROUP = 0x800
51     _LG_MODES = IN | OUT | _LG_ALERT | _LG_GROUP
52     _LG_PULLS = PULL_NONE | PULL_UP | PULL_NONE | ACTIVE_LOW
53     _LG_DRIVES = OPEN_DRAIN
54
55     id = None
56     _value = LOW
57     _mode = IN
58
59     # we want exceptions
60     lgpio.exceptions = True
61
62     def __init__(self, bcm_number):
63         self.id = bcm_number              # pylint: disable=invalid-name
64
65     def __repr__(self):
66         return str(self.id)
67
68     def __eq__(self, other):
69         return self.id == other
70
71     def init(self, mode=IN, pull=None):
72         """Initialize the Pin"""
73         if mode is not None:
74             if mode == Pin.IN:
75                 self._mode = Pin.IN
76                 self._set_gpio_mode_in()
77             elif mode == self.OUT:
78                 self._mode = Pin.OUT
79                 Pin._check_result(lgpio.gpio_claim_output(CHIP, self.id,
80                                   Pin.LOW))
81             else:
82                 raise RuntimeError(f"Invalid mode for pin: {self.id}")
83         if pull is not None:
84             if self._mode != Pin.IN:
85                 raise RuntimeError("Can only set pull resistor on input")
86             if pull in {Pin.PULL_UP, Pin.PULL_DOWN, Pin.PULL_NONE}:
87                 self._set_gpio_mode_in(lflags=pull)
88             else:
89                 raise RuntimeError(f"Invalid pull for pin: {self.id}")
90
91     def value(self, val=None):
92         """Set or return the Pin Value"""
93         if val is not None:
94             if val == Pin.LOW:
95                 self._value = val
96                 Pin._check_result(lgpio.gpio_write(CHIP, self.id, val))
97             elif val == Pin.HIGH:
98                 self._value = val
99                 Pin._check_result(lgpio.gpio_write(CHIP, self.id, val))
100             else:
101                 raise RuntimeError("Invalid value for pin")
102             return None
103         return Pin._check_result(lgpio.gpio_read(CHIP, self.id))
104
105     @staticmethod
106     def _check_result(result):
107         """
108         convert any result other than zero to a text message and pass it back
109         as a runtime exception.  Typical usage:  use the lgpio call as the
110         argument.
111         """
112         if result < 0:
113             raise RuntimeError(lgpio.error_text(result))
114         return result
115
116     def _set_gpio_mode_in(self, lflags=0):
117         """
118         claim a gpio as input, or modify the flags (PULL_UP, PULL_DOWN, ... )
119         """
120         # This gpio_free may seem redundant, but is required when
121         #  changing the line-flags of an already acquired input line
122         try:
123             lgpio.gpio_free(CHIP, self.id)
124         except lgpio.error:
125             pass
126         Pin._check_result(lgpio.gpio_claim_input(CHIP, self.id, lFlags=lflags))
127
128
129 D0 = Pin(0)
130 D1 = Pin(1)
131
132 D2 = Pin(2)
133 SDA = Pin(2)
134 D3 = Pin(3)
135 SCL = Pin(3)
136
137 D4 = Pin(4)
138 D5 = Pin(5)
139 D6 = Pin(6)
140
141 D7 = Pin(7)
142 CE1 = Pin(7)
143 D8 = Pin(8)
144 CE0 = Pin(8)
145 D9 = Pin(9)
146 MISO = Pin(9)
147 D10 = Pin(10)
148 MOSI = Pin(10)
149 D11 = Pin(11)
150 SCLK = Pin(11)  # Raspberry Pi naming
151 SCK = Pin(11)  # CircuitPython naming
152
153 D12 = Pin(12)
154 D13 = Pin(13)
155
156 D14 = Pin(14)
157 TXD = Pin(14)
158 D15 = Pin(15)
159 RXD = Pin(15)
160
161 D16 = Pin(16)
162 D17 = Pin(17)
163 D18 = Pin(18)
164 D19 = Pin(19)
165 MISO_1 = Pin(19)
166 D20 = Pin(20)
167 MOSI_1 = Pin(20)
168 D21 = Pin(21)
169 SCLK_1 = Pin(21)
170 SCK_1 = Pin(21)
171 D22 = Pin(22)
172 D23 = Pin(23)
173 D24 = Pin(24)
174 D25 = Pin(25)
175 D26 = Pin(26)
176 D27 = Pin(27)
177 D28 = Pin(28)
178 D29 = Pin(29)
179 D30 = Pin(30)
180 D31 = Pin(31)
181 D32 = Pin(32)
182 D33 = Pin(33)
183 D34 = Pin(34)
184 D35 = Pin(35)
185 D36 = Pin(36)
186 D37 = Pin(37)
187 D38 = Pin(38)
188 D39 = Pin(39)
189 D40 = Pin(40)
190 MISO_2 = Pin(40)
191 D41 = Pin(41)
192 MOSI_2 = Pin(41)
193 D42 = Pin(42)
194 SCLK_2 = Pin(42)
195 SCK_2 = Pin(43)
196 D43 = Pin(43)
197 D44 = Pin(44)
198 D45 = Pin(45)
199
200 # ordered as spiId, sckId, mosiId, misoId
201 spiPorts = (
202     (0, SCLK, MOSI, MISO),
203     (1, SCLK_1, MOSI_1, MISO_1),
204     (2, SCLK_2, MOSI_2, MISO_2),
205 )
206
207 # ordered as uartId, txId, rxId
208 uartPorts = ((1, TXD, RXD),)
209
210 # These are the known hardware I2C ports / pins.
211 # For software I2C ports created with the i2c-gpio overlay, see:
212 #     https://github.com/adafruit/Adafruit_Python_Extended_Bus
213 i2cPorts = (
214     (1, SCL, SDA),
215     (0, D1, D0),  # both pi 1 and pi 2 i2c ports!
216 )