]> Repositories - Adafruit_Blinka-hackapet.git/blob - src/adafruit_blinka/microcontroller/generic_agnostic_board/pin.py
77eb4b0f60bfbdc88d95a007cd3fb743ad7e8a5d
[Adafruit_Blinka-hackapet.git] / src / adafruit_blinka / microcontroller / generic_agnostic_board / pin.py
1 # SPDX-FileCopyrightText: 2024 Melissa LeBlanc-Williams for Adafruit Industries
2 #
3 # SPDX-License-Identifier: MIT
4 """generic_agnostic_board pin interface"""
5 import random
6
7
8 class Pin:
9     """A basic Pin class for use with generic_agnostic_board"""
10
11     # pin modes
12     OUT = 0
13     IN = 1
14     ADC = 2
15     DAC = 3
16     # pin values
17     LOW = 0
18     HIGH = 1
19
20     def return_toggle(self):
21         """Returns the pin's expected value, toggling between True and False"""
22         toggle_state = not self.previous_value
23         return toggle_state
24
25     def return_false(self):
26         """Returns the pin's expected value, False"""
27         return False
28
29     def return_true(self):
30         """Returns the pin's expected value, True"""
31         return True
32
33     def return_random_int(self):
34         """Returns a random integer"""
35         return random.randint(0, 65535)
36
37     def return_fixed_int_pi(self):
38         """Returns the first five digits of Pi, 31415"""
39         return 31415
40
41     def __init__(self, pin_id=None):
42         self.id = pin_id
43         self._mode = None
44         self.previous_value = None
45         self.current_value = None
46         # TODO: Can we simplify the pin behavior dict and the pin map dict?
47         # mapping of pin definition names to expected behavior
48         self.expected_pin_behavior = {
49             "Dx_INPUT_TRUE": self.return_true,
50             "Dx_INPUT_FALSE": self.return_false,
51             "Dx_INPUT_TRUE_THEN_FALSE": self.return_toggle,
52             "Dx_INPUT_TRUE_PULL_UP": self.return_true,
53             "Dx_INPUT_TRUE_PULL_DOWN": self.return_true,
54             "Dx_OUTPUT_TRUE": self.return_true,
55             "Dx_OUTPUT_FALSE": self.return_false,
56             "Ax_INPUT_RAND_INT": self.return_random_int,
57         }
58         # mapping of pin numbers to pin definition names
59         self.pin_number_to_pin_definition_name = {
60             0: "Dx_INPUT_TRUE",
61             1: "Dx_INPUT_FALSE",
62             2: "Dx_INPUT_TRUE_PULL_UP",
63             3: "Dx_INPUT_TRUE_PULL_DOWN",
64             4: "Dx_OUTPUT_TRUE",
65             5: "Dx_OUTPUT_FALSE",
66             6: "NEOPIXEL",
67             7: "Ax_INPUT_RAND_INT",
68             8: "Ax_INPUT_FIXED_INT_PI",
69             9: "Ax_OUTPUT_WAVE_SINE",
70             10: "Ax_OUTPUT_WAVE_SAWTOOTH",
71         }
72
73     def init(self, mode=IN, pull=None):
74         """Initialize the Pin"""
75         if self.id is None:
76             raise RuntimeError("Can not init a None type pin.")
77         if pull is not None:
78             raise NotImplementedError("Internal pullups and pulldowns not supported")
79         self._mode = mode
80
81     def write(self, new_value):
82         """Saves the new_value to the pin for subsequent calls to .value"""
83         self.previous_value = self.current_value
84         self.current_value = new_value
85
86     def read(self):
87         """Returns the pin's expected value."""
88         self.previous_value = self.current_value
89         # lookup the pin id's name from the mapping
90         pin_name = self.pin_number_to_pin_definition_name.get(self.id)
91         if pin_name:
92             self.current_value = self.expected_pin_behavior[pin_name]()
93         else:  # default to False if the pin is not in the mapping
94             self.current_value = False
95         return self.current_value
96
97     def value(self, val=None):
98         """Set or return the Pin Value"""
99         # Digital In / Out
100         if self._mode in (Pin.IN, Pin.OUT):
101             # digital read
102             if val is None:
103                 return self.read()
104             # digital write
105             if val in (Pin.LOW, Pin.HIGH):
106                 return self.write(val)
107             # nope
108             raise ValueError("Invalid value for pin.")
109         # Analog In
110         if self._mode == Pin.ADC:
111             if val is None:
112                 return self.read()
113             # read only
114             raise AttributeError("'AnalogIn' object has no attribute 'value'")
115         # Analog Out
116         if self._mode == Pin.DAC:
117             if val is None:
118                 # write only
119                 raise AttributeError("unreadable attribute")
120             self.write(val)
121             return None
122         raise RuntimeError(
123             "No action for mode {} with value {}".format(self._mode, val)
124         )
125
126
127 # create pin instances for each pin
128 D0 = Pin(0)
129 D1 = Pin(1)
130 D2 = Pin(2)
131 D3 = Pin(3)
132 D4 = Pin(4)
133 D5 = Pin(5)
134 # Special "digital" pins
135 D6 = Pin(6)
136 # Analog pins
137 A0 = Pin(7)
138 A1 = Pin(8)
139 A2 = Pin(9)
140 A3 = Pin(10)
141
142 # I2C pins
143 SDA = Pin()
144 SCL = Pin()
145
146 # SPI pins
147 SCLK = Pin()
148 SCK = Pin()
149 MOSI = Pin()
150 MISO = Pin()
151 CS = Pin()
152
153 # UART pins
154 UART_TX = Pin()
155 UART_RX = Pin()