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