]> Repositories - Adafruit_Blinka-hackapet.git/blob - src/adafruit_blinka/microcontroller/generic_agnostic_board/pin.py
add square wave generation
[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 # Values for sine wave analog output
8 # (data points = 20, amplitude=100, frequency=1)
9 sine_wave = [
10     0,
11     31,
12     59,
13     81,
14     95,
15     100,
16     95,
17     81,
18     59,
19     31,
20     0,
21     -31,
22     -59,
23     -81,
24     -95,
25     -100,
26     -95,
27     -81,
28     -59,
29     -31,
30 ]
31
32 # Values for a square wave analog output
33 # (data points = 20, amplitude=100)
34 square_wave_int = [
35     100,
36     -100,
37     100,
38     -100,
39     100,
40     -100,
41     100,
42     -100,
43     100,
44     -100,
45     100,
46     -100,
47     100,
48     -100,
49     100,
50     -100,
51     100,
52     -100,
53     100,
54     -100
55 ]
56
57 class Pin:
58     """A basic Pin class for use with generic_agnostic_board"""
59
60     # pin modes
61     OUT = 0
62     IN = 1
63     ADC = 2
64     DAC = 3
65     # pin values
66     LOW = 0
67     HIGH = 1
68     # pin pulls
69     PULL_NONE = 0
70     PULL_UP = 1
71     PULL_DOWN = 2
72
73     def return_toggle(self):
74         """Returns the pin's expected value, toggling between True and False"""
75         toggle_state = not self.previous_value
76         return toggle_state
77
78     def return_false(self):
79         """Returns the pin's expected value, False"""
80         return False
81
82     def return_true(self):
83         """Returns the pin's expected value, True"""
84         return True
85
86     def return_random_int(self):
87         """Returns a random integer"""
88         return random.randint(0, 65535)
89
90     def return_fixed_int_pi(self):
91         """Returns the first five digits of Pi, 31415"""
92         return 31415
93
94     def return_sine_wave(self):
95         """Returns the next value in the sine wave"""
96         if self._wave_idx is None:
97             self._wave_idx = 0
98         else:
99             self._wave_idx = (self._wave_idx + 1) % len(sine_wave)
100         return sine_wave[self._wave_idx]
101
102     def return_square_wave(self):
103         """Returns the next value in the square wave"""
104         if self._wave_idx is None:
105             self._wave_idx = 0
106         else:
107             self._wave_idx = (self._wave_idx + 1) % len(square_wave_int)
108         return square_wave_int[self._wave_idx]
109
110     def __init__(self, pin_id=None):
111         self.id = pin_id
112         self._mode = None
113         self._pull = None
114         self.previous_value = False
115         self.current_value = None
116         self._wave_idx = None
117
118         # mapping of pin definition names to expected behavior
119         self.pin_behavior = {
120             0: self.return_true,  # Dx_INPUT_TRUE
121             1: self.return_false,  # Dx_INPUT_FALSE
122             2: self.return_true,  # Dx_INPUT_TRUE_PULL_UP
123             3: self.return_true,  # Dx_INPUT_TRUE_PULL_DOWN
124             4: self.return_true,  # Dx_OUTPUT
125             7: self.return_random_int,  # Ax_INPUT_RAND_INT
126             8: self.return_fixed_int_pi,  # Ax_INPUT_FIXED_INT_PI
127             9: self.return_sine_wave,  # Ax_OUTPUT_WAVE_SINE
128             10: self.return_square_wave,  # Ax_OUTPUT_WAVE_SAWTOOTH
129             11: self.return_toggle  # Dx_INPUT_TOGGLE
130         }
131
132     def init(self, mode=IN, pull=None):
133         """Initialize the Pin"""
134         if self.id is None:
135             raise RuntimeError("Can not init a None type pin.")
136         pull = Pin.PULL_NONE if pull is None else pull
137         self._pull = pull
138         self._mode = mode
139
140     def write(self, new_value):
141         """Saves the new_value to the pin for subsequent calls to .value"""
142         self.previous_value = self.current_value
143         self.current_value = new_value
144
145     def read(self):
146         """Returns the pin's expected value."""
147         self.previous_value = self.current_value
148         # perform a lookup on the pin_behavior dict to get the value
149         self.current_value = self.pin_behavior.get(self.id)()
150
151         # is pin a pull up and pin is LOW?
152         if self._pull == Pin.PULL_UP and self.current_value == False:
153             self.current_value = False
154         # is pin a pull down and pin is HIGH?
155         if self._pull == Pin.PULL_DOWN and self.current_value == True:
156             self.current_value = False
157         return self.current_value
158
159     def value(self, val=None):
160         """Set or return the Pin Value"""
161         # Digital In / Out
162         if self._mode in (Pin.IN, Pin.OUT):
163             # digital read
164             if val is None:
165                 return self.read()
166             # digital write
167             if val in (Pin.LOW, Pin.HIGH):
168                 return self.write(val)
169             # nope
170             raise ValueError("Invalid value for pin.")
171         # Analog In
172         if self._mode == Pin.ADC:
173             if val is None:
174                 return self.read()
175             # read only
176             raise AttributeError("'AnalogIn' object has no attribute 'value'")
177         # Analog Out
178         if self._mode == Pin.DAC:
179             if val is None:
180                 # write only
181                 raise AttributeError("unreadable attribute")
182             self.write(val)
183             return None
184         raise RuntimeError(
185             "No action for mode {} with value {}".format(self._mode, val)
186         )
187
188
189 # create pin instances for each pin
190 D0 = Pin(0)
191 D1 = Pin(1)
192 D2 = Pin(2)
193 D3 = Pin(3)
194 D4 = Pin(4)
195 # Special "digital" pins
196 D6 = Pin(6)
197 # Analog pins
198 A0 = Pin(7)
199 A1 = Pin(8)
200 A2 = Pin(9)
201 A3 = Pin(10)
202
203 D7 = Pin(11)
204
205 # I2C pins
206 SDA = Pin()
207 SCL = Pin()
208
209 # SPI pins
210 SCLK = Pin()
211 SCK = Pin()
212 MOSI = Pin()
213 MISO = Pin()
214 CS = Pin()
215
216 # UART pins
217 UART_TX = Pin()
218 UART_RX = Pin()