]> Repositories - Adafruit_Blinka-hackapet.git/blob - src/adafruit_blinka/microcontroller/generic_agnostic_board/PWMOut.py
rm GPIO undef
[Adafruit_Blinka-hackapet.git] / src / adafruit_blinka / microcontroller / generic_agnostic_board / PWMOut.py
1 # SPDX-FileCopyrightText: 2024 Brent Rubell for Adafruit Industries
2 #
3 # SPDX-License-Identifier: MIT
4 """Mock PWMOut Wrapper for Generic Agnostic Board"""
5
6 class PWMError(IOError):
7     """Base class for PWM errors."""
8
9
10 class PWMOut:
11     """Pulse Width Modulation Output Class"""
12
13     def __init__(self, pin, *, frequency=500, duty_cycle=0, variable_frequency=False):
14         self._pwmpin = None
15         self._period = 0
16         self._open(pin, duty_cycle, frequency, variable_frequency)
17
18     def __del__(self):
19         self.deinit()
20
21     def __enter__(self):
22         return self
23
24     def __exit__(self, t, value, traceback):
25         self.deinit()
26
27     def _open(self, pin, duty=0, freq=500, variable_frequency=False):
28         self._pin = pin
29
30         if variable_frequency:
31             print("Variable Frequency is not supported, continuing without it...")
32
33         # set frequency
34         self.frequency = freq
35         # set duty
36         self.duty_cycle = duty
37
38         self.enabled = True
39
40     def deinit(self):
41         """Deinit the PWM."""
42         if self._pwmpin is not None:
43             self._pwmpin = None
44
45     def _is_deinited(self):
46         if self._pwmpin is None:
47             raise ValueError(
48                 "Object has been deinitialize and can no longer "
49                 "be used. Create a new object."
50             )
51
52     @property
53     def period(self):
54         """Get or set the PWM's output period in seconds.
55
56         Raises:
57             PWMError: if an I/O or OS error occurs.
58             TypeError: if value type is not int or float.
59
60         :type: int, float
61         """
62         return 1.0 / self.frequency
63
64     @period.setter
65     def period(self, period):
66         if not isinstance(period, (int, float)):
67             raise TypeError("Invalid period type, should be int or float.")
68
69         self.frequency = 1.0 / period
70
71     @property
72     def duty_cycle(self):
73         """Get or set the PWM's output duty cycle which is the fraction of
74         each pulse which is high. 16-bit
75
76         Raises:
77             PWMError: if an I/O or OS error occurs.
78             TypeError: if value type is not int or float.
79             ValueError: if value is out of bounds of 0.0 to 1.0.
80
81         :type: int, float
82         """
83         return int(self._duty_cycle * 65535)
84
85     @duty_cycle.setter
86     def duty_cycle(self, duty_cycle):
87         if not isinstance(duty_cycle, (int, float)):
88             raise TypeError("Invalid duty cycle type, should be int or float.")
89
90         if not 0 <= duty_cycle <= 65535:
91             raise ValueError("Invalid duty cycle value, should be between 0 and 65535")
92
93         # convert from 16-bit
94         duty_cycle /= 65535.0
95
96         self._duty_cycle = duty_cycle
97
98     @property
99     def frequency(self):
100         """Get or set the PWM's output frequency in Hertz.
101
102         Raises:
103             PWMError: if an I/O or OS error occurs.
104             TypeError: if value type is not int or float.
105
106         :type: int, float
107         """
108
109         return self._frequency
110
111     @frequency.setter
112     def frequency(self, frequency):
113         if not isinstance(frequency, (int, float)):
114             raise TypeError("Invalid frequency type, should be int or float.")
115
116         self._frequency = frequency
117
118     @property
119     def enabled(self):
120         """Get or set the PWM's output enabled state.
121
122         Raises:
123             PWMError: if an I/O or OS error occurs.
124             TypeError: if value type is not bool.
125
126         :type: bool
127         """
128         return self._enabled
129
130     @enabled.setter
131     def enabled(self, value):
132         if not isinstance(value, bool):
133             raise TypeError("Invalid enabled type, should be string.")
134
135         self._enabled = value
136
137     # String representation
138     def __str__(self):
139         return "pin %s (freq=%f Hz, duty_cycle=%f%%)" % (
140             self._pin,
141             self.frequency,
142             self.duty_cycle,
143         )