playdate_controls/
peripherals.rs

1use core::ffi::c_float;
2use sys::ffi::PDButtons;
3use sys::ffi::PDPeripherals;
4use crate::api;
5
6
7/// Peripherals
8#[derive(Debug, Clone, Copy)]
9pub struct Peripherals<Api = api::Default>(Api);
10
11impl Peripherals<api::Default> {
12	/// Creates default [`Peripherals`] without type parameter requirement.
13	///
14	/// Uses ZST [`api::Default`].
15	#[allow(non_snake_case)]
16	pub fn Default() -> Self { Self(Default::default()) }
17}
18
19impl Peripherals<api::Cache> {
20	/// Creates [`Peripherals`] without type parameter requirement.
21	///
22	/// Uses [`api::Cache`].
23	#[allow(non_snake_case)]
24	pub fn Cached() -> Self { Self(Default::default()) }
25}
26
27impl<Api: Default + api::Api> Default for Peripherals<Api> {
28	fn default() -> Self { Self(Default::default()) }
29}
30
31impl<Api: Default + api::Api> Peripherals<Api> {
32	pub fn new() -> Self { Self(Default::default()) }
33}
34
35impl<Api: api::Api> Peripherals<Api> {
36	pub const fn new_with(api: Api) -> Self { Self(api) }
37}
38
39impl<Api: api::Api> Peripherals<Api> where Api: Copy {
40	pub const fn accelerometer(&self) -> Accelerometer<Api> { Accelerometer(self.0) }
41	pub const fn buttons(&self) -> Buttons<Api> { Buttons(self.0) }
42	pub const fn crank(&self) -> Crank<Api> { Crank(self.0) }
43}
44
45impl<Api: api::Api> Peripherals<Api> {
46	/// Enables specified peripheral.
47	///
48	/// Equivalent to [`sys::ffi::playdate_sys::setPeripheralsEnabled`]
49	#[doc(alias = "sys::ffi::playdate_sys::setPeripheralsEnabled")]
50	pub fn enable(&self, value: PDPeripherals) {
51		let f = self.0.set_peripherals_enabled();
52		unsafe { f(value) }
53	}
54
55	/// By default, the accelerometer is disabled to save (a small amount of) power.
56	///
57	/// To use a peripheral, it must first be enabled via this function.
58	///
59	/// Accelerometer data is not available until the next update cycle after it’s enabled.
60	///
61	/// Equivalent to [`sys::ffi::playdate_sys::setPeripheralsEnabled`]
62	#[doc(alias = "sys::ffi::playdate_sys::setPeripheralsEnabled")]
63	#[inline(always)]
64	pub fn enable_accelerometer(&self) { self.enable(Peripherals::Accelerometer) }
65
66	/// Enables all peripherals.
67	///
68	/// Equivalent to [`sys::ffi::playdate_sys::setPeripheralsEnabled`]
69	#[doc(alias = "sys::ffi::playdate_sys::setPeripheralsEnabled")]
70	#[inline(always)]
71	pub fn enable_all(&self) { self.enable(Peripherals::All) }
72
73	/// Disables all peripherals.
74	///
75	/// Equivalent to [`sys::ffi::playdate_sys::setPeripheralsEnabled`]
76	#[doc(alias = "sys::ffi::playdate_sys::setPeripheralsEnabled")]
77	#[inline(always)]
78	pub fn disable_all(&self) { self.enable(Peripherals::None) }
79}
80
81impl Peripherals<api::Default> {
82	#![allow(non_upper_case_globals)]
83	pub const None: PDPeripherals = PDPeripherals::kNone;
84	pub const Accelerometer: PDPeripherals = PDPeripherals::kAccelerometer;
85	pub const All: PDPeripherals = PDPeripherals::kAllPeripherals;
86}
87
88
89// TODO: SystemExt should be const_trait
90pub trait SystemExt<Api: api::Api + Copy> {
91	fn peripherals(&self) -> Peripherals<Api>;
92	fn accelerometer(&self) -> Accelerometer<Api>;
93	fn buttons(&self) -> Buttons<Api>;
94	fn crank(&self) -> Crank<Api>;
95}
96
97impl<Api: system::api::Api + api::Api + Copy> SystemExt<Api> for system::System<Api> {
98	fn peripherals(&self) -> Peripherals<Api> { Peripherals::new_with(self.inner()) }
99	fn accelerometer(&self) -> Accelerometer<Api> { Accelerometer::new_with(self.inner()) }
100	fn buttons(&self) -> Buttons<Api> { Buttons::new_with(self.inner()) }
101	fn crank(&self) -> Crank<Api> { Crank::new_with(self.inner()) }
102}
103
104
105/// Accelerometer
106#[derive(Debug, Clone, Copy)]
107pub struct Accelerometer<Api = api::Default>(Api);
108
109impl Accelerometer<api::Default> {
110	/// Creates default [`Accelerometer`] without type parameter requirement.
111	///
112	/// Uses ZST [`api::Default`].
113	#[allow(non_snake_case)]
114	pub fn Default() -> Self { Self(Default::default()) }
115}
116
117impl Accelerometer<api::Cache> {
118	/// Creates [`Accelerometer`] without type parameter requirement.
119	///
120	/// Uses [`api::Cache`].
121	#[allow(non_snake_case)]
122	pub fn Cached() -> Self { Self(Default::default()) }
123}
124
125impl<Api: Default + api::Api> Default for Accelerometer<Api> {
126	fn default() -> Self { Self(Default::default()) }
127}
128
129impl<Api: Default + api::Api> Accelerometer<Api> {
130	pub fn new() -> Self { Self(Default::default()) }
131}
132
133impl<Api: api::Api> Accelerometer<Api> {
134	pub const fn new_with(api: Api) -> Self { Self(api) }
135}
136
137impl<Api: api::Api> Accelerometer<Api> {
138	/// Enables accelerometer only.
139	///
140	/// By default, the accelerometer is disabled to save (a small amount of) power.
141	///
142	/// To use a peripheral, it must first be enabled via this function.
143	///
144	/// Accelerometer data is not available until the next update cycle after it’s enabled.
145	///
146	/// Equivalent to [`sys::ffi::playdate_sys::setPeripheralsEnabled`].
147	#[doc(alias = "sys::ffi::playdate_sys::setPeripheralsEnabled")]
148	pub fn enable(&self) {
149		let f = self.0.set_peripherals_enabled();
150		unsafe { f(Peripherals::Accelerometer) }
151	}
152
153	/// ⚠️ Disables all peripherals including accelerometer.
154	///
155	/// Currently it doesn't matter because there's just one peripheral - accelerometer.
156	///
157	/// Equivalent to [`sys::ffi::playdate_sys::setPeripheralsEnabled`].
158	#[doc(alias = "sys::ffi::playdate_sys::setPeripheralsEnabled")]
159	pub fn disable(&self) {
160		let f = self.0.set_peripherals_enabled();
161		unsafe { f(Peripherals::None) }
162	}
163
164	/// Returns `(x, y, z)` accelerometer data.
165	///
166	/// Equivalent to [`sys::ffi::playdate_sys::getAccelerometer`].
167	#[doc(alias = "sys::ffi::playdate_sys::getAccelerometer")]
168	pub fn get(&self) -> (c_float, c_float, c_float) {
169		let mut outx: c_float = 0.0;
170		let mut outy: c_float = 0.0;
171		let mut outz: c_float = 0.0;
172
173		let f = self.0.get_accelerometer();
174		unsafe { f(&mut outx, &mut outy, &mut outz) };
175		(outx, outy, outz)
176	}
177
178	/// Gets accelerometer data directly to `x`, `y` and `z`.
179	///
180	/// Equivalent to [`sys::ffi::playdate_sys::getAccelerometer`].
181	#[doc(alias = "sys::ffi::playdate_sys::getAccelerometer")]
182	pub fn get_to(&self, outx: &mut c_float, outy: &mut c_float, outz: &mut c_float) {
183		let f = self.0.get_accelerometer();
184		unsafe { f(outx, outy, outz) }
185	}
186}
187
188
189/// Buttons
190#[derive(Debug, Clone, Copy)]
191pub struct Buttons<Api = api::Default>(Api);
192
193impl Buttons<api::Default> {
194	/// Creates default [`Buttons`] without type parameter requirement.
195	///
196	/// Uses ZST [`api::Default`].
197	#[allow(non_snake_case)]
198	pub fn Default() -> Self { Self(Default::default()) }
199}
200
201impl Buttons<api::Cache> {
202	/// Creates [`Buttons`] without type parameter requirement.
203	///
204	/// Uses [`api::Cache`].
205	#[allow(non_snake_case)]
206	pub fn Cached() -> Self { Self(Default::default()) }
207}
208
209impl<Api: Default + api::Api> Default for Buttons<Api> {
210	fn default() -> Self { Self(Default::default()) }
211}
212
213impl<Api: Default + api::Api> Buttons<Api> {
214	pub fn new() -> Self { Self(Default::default()) }
215}
216
217impl<Api: api::Api> Buttons<Api> {
218	pub const fn new_with(api: Api) -> Self { Self(api) }
219}
220
221impl<Api: api::Api> Buttons<Api> {
222	/// Returns the current buttons [`State`].
223	///
224	/// Equivalent to [`sys::ffi::playdate_sys::getButtonState`].
225	#[doc(alias = "sys::ffi::playdate_sys::getButtonState")]
226	pub fn get(&self) -> State {
227		let mut current = PDButtons(0);
228		let mut pushed = PDButtons(0);
229		let mut released = PDButtons(0);
230
231		let f = self.0.get_button_state();
232		unsafe { f(&mut current, &mut pushed, &mut released) }
233
234		State { current,
235		        pushed,
236		        released }
237	}
238
239	/// Writes the current buttons state to given [`State`].
240	///
241	/// Updates all (current, pushed and released).
242	///
243	/// Equivalent to [`sys::ffi::playdate_sys::getButtonState`].
244	#[doc(alias = "sys::ffi::playdate_sys::getButtonState")]
245	pub fn get_to(&self, state: &mut State) {
246		let f = self.0.get_button_state();
247		unsafe { f(&mut state.current, &mut state.pushed, &mut state.released) }
248	}
249
250	/// Writes the current buttons state to given references.
251	///
252	/// Equivalent to [`sys::ffi::playdate_sys::getButtonState`].
253	#[doc(alias = "sys::ffi::playdate_sys::getButtonState")]
254	pub fn get_to_raw(&self, current: &mut PDButtons, pushed: &mut PDButtons, released: &mut PDButtons) {
255		let f = self.0.get_button_state();
256		unsafe { f(current, pushed, released) }
257	}
258
259	/// Equivalent to [`sys::ffi::playdate_sys::getButtonState`].
260	#[doc(alias = "sys::ffi::playdate_sys::getButtonState")]
261	///
262	/// Requests & returns only `current` part of state, see [Self::current]
263	pub fn current(&self) -> PDButtons {
264		use core::ptr::null_mut;
265
266		let mut current = PDButtons(0);
267		let f = self.0.get_button_state();
268		unsafe { f(&mut current, null_mut(), null_mut()) }
269		current
270	}
271
272	/// Equivalent to [`sys::ffi::playdate_sys::getButtonState`].
273	#[doc(alias = "sys::ffi::playdate_sys::getButtonState")]
274	///
275	/// Requests & returns only `current` part of state, see [Self::pushed]
276	pub fn pushed(&self) -> PDButtons {
277		use core::ptr::null_mut;
278
279		let mut pushed = PDButtons(0);
280
281		let f = self.0.get_button_state();
282		unsafe { f(null_mut(), &mut pushed, null_mut()) }
283
284		pushed
285	}
286
287	/// Equivalent to [`sys::ffi::playdate_sys::getButtonState`].
288	#[doc(alias = "sys::ffi::playdate_sys::getButtonState")]
289	///
290	/// Requests & returns only `current` part of state, see [Self::released]
291	pub fn released(&self) -> PDButtons {
292		use core::ptr::null_mut;
293
294		let mut released = PDButtons(0);
295
296		let f = self.0.get_button_state();
297		unsafe { f(null_mut(), null_mut(), &mut released) }
298
299		released
300	}
301}
302
303/// Represents buttons state.
304///
305/// * `current` indicates which buttons are currently down.
306/// * `pushed` and `released` reflects which buttons were pushed or released over the previous update cycle.
307///
308/// Note: at the nominal frame rate of 50 ms, fast button presses can be missed if you just poll the instantaneous state.
309pub struct State {
310	/// Indicating which buttons are __currently down__.
311	pub current: PDButtons,
312	/// Reflect which buttons were pushed over the previous update cycle.
313	/// See [struct doc][Self].
314	pub pushed: PDButtons,
315	/// Reflect which buttons were released over the previous update cycle.
316	/// See [struct doc][Self].
317	pub released: PDButtons,
318}
319
320
321impl core::fmt::Debug for State {
322	fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
323		use crate::buttons::PDButtonsFmt;
324
325		f.debug_struct("Buttons")
326		 .field("current", &self.current.display())
327		 .field("pushed", &self.pushed.display())
328		 .field("released", &self.released.display())
329		 .finish()
330	}
331}
332
333
334/// Crank
335#[derive(Debug, Clone, Copy)]
336pub struct Crank<Api = api::Default>(Api);
337
338impl Crank<api::Default> {
339	/// Creates default [`Crank`] without type parameter requirement.
340	///
341	/// Uses ZST [`api::Default`].
342	#[allow(non_snake_case)]
343	pub fn Default() -> Self { Self(Default::default()) }
344}
345
346impl Crank<api::Cache> {
347	/// Creates [`Crank`] without type parameter requirement.
348	///
349	/// Uses [`api::Cache`].
350	#[allow(non_snake_case)]
351	pub fn Cached() -> Self { Self(Default::default()) }
352}
353
354impl<Api: Default + api::Api> Default for Crank<Api> {
355	fn default() -> Self { Self(Default::default()) }
356}
357
358impl<Api: Default + api::Api> Crank<Api> {
359	pub fn new() -> Self { Self(Default::default()) }
360}
361
362impl<Api: api::Api> Crank<Api> {
363	pub const fn new_with(api: Api) -> Self { Self(api) }
364}
365
366impl<Api: api::Api> Crank<Api> {
367	/// Returns boolean indicating whether or not the crank is folded into the unit.
368	///
369	/// Equivalent to [`sys::ffi::playdate_sys::isCrankDocked`].
370	#[doc(alias = "sys::ffi::playdate_sys::isCrankDocked")]
371	pub fn docked(&self) -> bool {
372		let f = self.0.is_crank_docked();
373		unsafe { f() == 1 }
374	}
375
376	/// Returns the current position of the crank, in the range 0-360.
377	/// Zero is pointing up, and the value increases as the crank moves clockwise, as viewed from the right side of the device.
378	///
379	/// Equivalent to [`sys::ffi::playdate_sys::getCrankAngle`].
380	#[doc(alias = "sys::ffi::playdate_sys::getCrankAngle")]
381	pub fn angle(&self) -> c_float {
382		let f = self.0.get_crank_angle();
383		unsafe { f() }
384	}
385
386	/// Returns the angle change of the crank since the last time this function was called.
387	/// Negative values are anti-clockwise.
388	///
389	/// Equivalent to [`sys::ffi::playdate_sys::getCrankChange`].
390	#[doc(alias = "sys::ffi::playdate_sys::getCrankChange")]
391	pub fn change(&self) -> c_float {
392		let f = self.0.get_crank_change();
393		unsafe { f() }
394	}
395
396	/// Returns the previous value for this setting.
397	///
398	/// Equivalent to [`sys::ffi::playdate_sys::setCrankSoundsDisabled`].
399	#[doc(alias = "sys::ffi::playdate_sys::setCrankSoundsDisabled")]
400	pub fn disable_sounds(&self, disable: bool) -> bool {
401		let f = self.0.set_crank_sounds_disabled();
402		unsafe { f(disable as _) == 1 }
403	}
404}