phidget/devices/
digital_output.rs1use crate::{Phidget, Result, ReturnCode};
14use phidget_sys::{self as ffi, PhidgetDigitalOutputHandle, PhidgetHandle};
15use std::{
16 ffi::{c_int, c_void},
17 mem, ptr,
18};
19
20pub type AttachCallback = dyn Fn(&mut DigitalOutput) + Send + 'static;
22
23pub type DetachCallback = dyn Fn(&mut DigitalOutput) + Send + 'static;
25
26pub struct DigitalOutput {
28 chan: PhidgetDigitalOutputHandle,
30 attach_cb: Option<*mut c_void>,
32 detach_cb: Option<*mut c_void>,
34}
35
36impl DigitalOutput {
37 pub fn new() -> Self {
39 let mut chan: PhidgetDigitalOutputHandle = ptr::null_mut();
40 unsafe {
41 ffi::PhidgetDigitalOutput_create(&mut chan);
42 }
43 Self::from(chan)
44 }
45
46 unsafe extern "C" fn on_attach(phid: PhidgetHandle, ctx: *mut c_void) {
48 if !ctx.is_null() {
49 let cb: &mut Box<AttachCallback> = &mut *(ctx as *mut _);
50 let mut sensor = Self::from(phid as PhidgetDigitalOutputHandle);
51 cb(&mut sensor);
52 mem::forget(sensor);
53 }
54 }
55
56 unsafe extern "C" fn on_detach(phid: PhidgetHandle, ctx: *mut c_void) {
58 if !ctx.is_null() {
59 let cb: &mut Box<DetachCallback> = &mut *(ctx as *mut _);
60 let mut sensor = Self::from(phid as PhidgetDigitalOutputHandle);
61 cb(&mut sensor);
62 mem::forget(sensor);
63 }
64 }
65
66 pub fn as_channel(&self) -> &PhidgetDigitalOutputHandle {
68 &self.chan
69 }
70
71 pub fn set_enable_failsafe(&self, failsafe_time: u32) -> Result<()> {
73 ReturnCode::result(unsafe {
74 ffi::PhidgetDigitalOutput_enableFailsafe(self.chan, failsafe_time)
75 })?;
76 Ok(())
77 }
78 pub fn set_reset_failsafe(&self) -> Result<()> {
80 ReturnCode::result(unsafe { ffi::PhidgetDigitalOutput_resetFailsafe(self.chan) })?;
81 Ok(())
82 }
83
84 pub fn set_duty_cycle(&self, duty_cycle: f64) -> Result<()> {
88 ReturnCode::result(unsafe {
89 ffi::PhidgetDigitalOutput_setDutyCycle(self.chan, duty_cycle)
90 })?;
91 Ok(())
92 }
93
94 pub fn duty_cycle(&self) -> Result<f64> {
96 let mut value = 0.0;
97 ReturnCode::result(unsafe {
98 ffi::PhidgetDigitalOutput_getDutyCycle(self.chan, &mut value)
99 })?;
100 Ok(value)
101 }
102
103 pub fn min_duty_cycle(&self) -> Result<f64> {
105 let mut value = 0.0;
106 ReturnCode::result(unsafe {
107 ffi::PhidgetDigitalOutput_getMinDutyCycle(self.chan, &mut value)
108 })?;
109 Ok(value)
110 }
111
112 pub fn max_duty_cycle(&self) -> Result<f64> {
114 let mut value = 0.0;
115 ReturnCode::result(unsafe {
116 ffi::PhidgetDigitalOutput_getMaxDutyCycle(self.chan, &mut value)
117 })?;
118 Ok(value)
119 }
120
121 pub fn min_failsafe_time(&self) -> Result<u32> {
123 let mut value = 0;
124 ReturnCode::result(unsafe {
125 ffi::PhidgetDigitalOutput_getMinFailsafeTime(self.chan, &mut value)
126 })?;
127 Ok(value)
128 }
129
130 pub fn max_failsafe_time(&self) -> Result<u32> {
132 let mut value = 0;
133 ReturnCode::result(unsafe {
134 ffi::PhidgetDigitalOutput_getMaxFailsafeTime(self.chan, &mut value)
135 })?;
136 Ok(value)
137 }
138
139 pub fn set_frequency(&self, frequency: f64) -> Result<()> {
141 ReturnCode::result(unsafe {
142 ffi::PhidgetDigitalOutput_setFrequency(self.chan, frequency)
143 })?;
144 Ok(())
145 }
146
147 pub fn frequency(&self) -> Result<f64> {
149 let mut value = 0.0;
150 ReturnCode::result(unsafe {
151 ffi::PhidgetDigitalOutput_getFrequency(self.chan, &mut value)
152 })?;
153 Ok(value)
154 }
155
156 pub fn min_frequency(&self) -> Result<f64> {
158 let mut value = 0.0;
159 ReturnCode::result(unsafe {
160 ffi::PhidgetDigitalOutput_getMinFrequency(self.chan, &mut value)
161 })?;
162 Ok(value)
163 }
164
165 pub fn max_frequency(&self) -> Result<f64> {
167 let mut value = 0.0;
168 ReturnCode::result(unsafe {
169 ffi::PhidgetDigitalOutput_getMaxFrequency(self.chan, &mut value)
170 })?;
171 Ok(value)
172 }
173
174 pub fn set_led_current_limit(&self, led_current_limit: f64) -> Result<()> {
176 ReturnCode::result(unsafe {
177 ffi::PhidgetDigitalOutput_setLEDCurrentLimit(self.chan, led_current_limit)
178 })?;
179 Ok(())
180 }
181
182 pub fn led_current_limit(&self) -> Result<f64> {
184 let mut value = 0.0;
185 ReturnCode::result(unsafe {
186 ffi::PhidgetDigitalOutput_getLEDCurrentLimit(self.chan, &mut value)
187 })?;
188 Ok(value)
189 }
190
191 pub fn min_led_current_limit(&self) -> Result<f64> {
193 let mut value = 0.0;
194 ReturnCode::result(unsafe {
195 ffi::PhidgetDigitalOutput_getMinLEDCurrentLimit(self.chan, &mut value)
196 })?;
197 Ok(value)
198 }
199
200 pub fn max_led_current_limit(&self) -> Result<f64> {
202 let mut value = 0.0;
203 ReturnCode::result(unsafe {
204 ffi::PhidgetDigitalOutput_getMaxLEDCurrentLimit(self.chan, &mut value)
205 })?;
206 Ok(value)
207 }
208
209 pub fn led_forward_voltage(&self) -> Result<u32> {
211 let mut value: ffi::PhidgetDigitalOutput_LEDForwardVoltage = 0;
212 ReturnCode::result(unsafe {
213 ffi::PhidgetDigitalOutput_getLEDForwardVoltage(self.chan, &mut value)
214 })?;
215 Ok(value)
216 }
217
218 pub fn set_state(&self, state: u8) -> Result<()> {
221 ReturnCode::result(unsafe { ffi::PhidgetDigitalOutput_setState(self.chan, state as c_int) })
222 }
223
224 pub fn state(&self) -> Result<u8> {
226 let mut value = 0;
227 ReturnCode::result(unsafe { ffi::PhidgetDigitalOutput_getState(self.chan, &mut value) })?;
228 Ok(value as u8)
229 }
230
231 pub fn set_on_attach_handler<F>(&mut self, cb: F) -> Result<()>
233 where
234 F: Fn(&mut DigitalOutput) + Send + 'static,
235 {
236 let cb: Box<Box<AttachCallback>> = Box::new(Box::new(cb));
238 let ctx = Box::into_raw(cb) as *mut c_void;
239
240 ReturnCode::result(unsafe {
241 ffi::Phidget_setOnAttachHandler(self.as_mut_handle(), Some(Self::on_attach), ctx)
242 })?;
243 self.attach_cb = Some(ctx);
244 Ok(())
245 }
246
247 pub fn set_on_detach_handler<F>(&mut self, cb: F) -> Result<()>
249 where
250 F: Fn(&mut DigitalOutput) + Send + 'static,
251 {
252 let cb: Box<Box<DetachCallback>> = Box::new(Box::new(cb));
254 let ctx = Box::into_raw(cb) as *mut c_void;
255
256 ReturnCode::result(unsafe {
257 ffi::Phidget_setOnDetachHandler(self.as_mut_handle(), Some(Self::on_detach), ctx)
258 })?;
259 self.detach_cb = Some(ctx);
260 Ok(())
261 }
262}
263
264impl Phidget for DigitalOutput {
265 fn as_mut_handle(&mut self) -> PhidgetHandle {
266 self.chan as PhidgetHandle
267 }
268 fn as_handle(&self) -> PhidgetHandle {
269 self.chan as PhidgetHandle
270 }
271}
272
273unsafe impl Send for DigitalOutput {}
274
275impl Default for DigitalOutput {
276 fn default() -> Self {
277 Self::new()
278 }
279}
280
281impl From<PhidgetDigitalOutputHandle> for DigitalOutput {
282 fn from(chan: PhidgetDigitalOutputHandle) -> Self {
283 Self {
284 chan,
285 attach_cb: None,
286 detach_cb: None,
287 }
288 }
289}
290
291impl Drop for DigitalOutput {
292 fn drop(&mut self) {
293 if let Ok(true) = self.is_open() {
294 let _ = self.close();
295 }
296 unsafe {
297 ffi::PhidgetDigitalOutput_delete(&mut self.chan);
298 crate::drop_cb::<AttachCallback>(self.attach_cb.take());
299 crate::drop_cb::<DetachCallback>(self.detach_cb.take());
300 }
301 }
302}