diff --git a/ctru-rs/examples/camera-image.rs b/ctru-rs/examples/camera-image.rs index 30938ce..8395883 100644 --- a/ctru-rs/examples/camera-image.rs +++ b/ctru-rs/examples/camera-image.rs @@ -83,7 +83,7 @@ fn main() { .take_picture(&mut buf, WAIT_TIMEOUT) .expect("Failed to take picture"); - let image_size = camera.final_view_size(); + let (width, height) = camera.final_view_size(); // Play the normal shutter sound. cam.play_shutter_sound(ShutterSound::Normal) @@ -96,16 +96,16 @@ fn main() { rotate_image_to_screen( &buf, left_side.raw_framebuffer().ptr, - image_size.0 as usize, - image_size.1 as usize, + width as usize, + height as usize, ); // Rotate the right image and correctly display it on the screen. rotate_image_to_screen( &buf[len / 2..], right_side.raw_framebuffer().ptr, - image_size.0 as usize, - image_size.1 as usize, + width as usize, + height as usize, ); } diff --git a/ctru-rs/examples/movement.rs b/ctru-rs/examples/movement.rs index a0aa2c8..1cbefc1 100644 --- a/ctru-rs/examples/movement.rs +++ b/ctru-rs/examples/movement.rs @@ -19,8 +19,10 @@ fn main() { // Activate the accelerometer and the gyroscope. // Because of the complex nature of the movement sensors, they aren't activated by default with the `Hid` service. // However, they can simply be turned on and off whenever necessary. - hid.set_accelerometer(true); - hid.set_gyroscope(true); + hid.set_accelerometer(true) + .expect("Couldn't activate accelerometer"); + hid.set_gyroscope(true) + .expect("Couldn't activate gyroscope"); while apt.main_loop() { // Scan all the controller inputs. @@ -34,13 +36,17 @@ fn main() { // Be careful: reading without activating the sensors (as done before this loop) will result in a panic. println!( "\x1b[3;0HAcceleration: {:?} ", - hid.accelerometer_vector() - .expect("could not retrieve acceleration vector") + Into::<(i16, i16, i16)>::into( + hid.accelerometer_vector() + .expect("could not retrieve acceleration vector") + ) ); println!( "\x1b[4;0HGyroscope angular rate: {:?} ", - hid.gyroscope_rate() - .expect("could not retrieve angular rate") + Into::<(i16, i16, i16)>::into( + hid.gyroscope_rate() + .expect("could not retrieve angular rate") + ) ); gfx.wait_for_vblank(); diff --git a/ctru-rs/src/console.rs b/ctru-rs/src/console.rs index f88e11b..5c9fba1 100644 --- a/ctru-rs/src/console.rs +++ b/ctru-rs/src/console.rs @@ -209,7 +209,7 @@ impl<'screen> Console<'screen> { /// /// # Example /// - /// ```no_run + /// ``` /// # use std::error::Error; /// # fn main() -> Result<(), Box> { /// # @@ -264,7 +264,7 @@ impl<'screen> Console<'screen> { /// /// # Example /// - /// ```no_run + /// ``` /// # use std::error::Error; /// # fn main() -> Result<(), Box> { /// # @@ -288,14 +288,14 @@ impl<'screen> Console<'screen> { pub fn reset_window(&mut self) { let width = self.max_width(); - unsafe { consoleSetWindow(self.context.as_mut(), 0, 0, width.into(), 30) }; + self.set_window(0, 0, width, 30).unwrap(); } /// Returns this [`Console`]'s maximum character width depending on the screen used. /// /// # Example /// - /// ```no_run + /// ``` /// # use std::error::Error; /// # fn main() -> Result<(), Box> { /// # diff --git a/ctru-rs/src/lib.rs b/ctru-rs/src/lib.rs index a57cc00..f1569bb 100644 --- a/ctru-rs/src/lib.rs +++ b/ctru-rs/src/lib.rs @@ -76,7 +76,6 @@ pub fn use_panic_handler() { /// When `test` is enabled, this function will be ignored. #[cfg(not(test))] fn panic_hook_setup() { - use crate::services::hid::KeyPad; use std::panic::PanicInfo; let main_thread = std::thread::current().id(); @@ -88,27 +87,9 @@ fn panic_hook_setup() { // Only for panics in the main thread if main_thread == std::thread::current().id() && console::Console::exists() { - println!("\nPress SELECT to exit the software"); + println!("\nThe software will exit in 5 seconds"); - // Due to how the Hid service operates, we can't safely use 2 handles to it at the same time. - // Furthermore, the panic hook runs before the panic cleanup is done, which means that any other handles - // to the service will still be alive during this process. - // Regardless, we can "unsafely" spin up a new instance, since the module won't be used any further from the main process, - // which is going to get cleaned up right after this loop. - unsafe { - let _ = ctru_sys::hidInit(); - - loop { - ctru_sys::hidScanInput(); - let keys = ctru_sys::hidKeysDown(); - - if KeyPad::from_bits_truncate(keys).contains(KeyPad::SELECT) { - break; - } - } - - ctru_sys::hidExit(); - } + std::thread::sleep(std::time::Duration::from_secs(5)); } }); std::panic::set_hook(new_hook); diff --git a/ctru-rs/src/services/cam.rs b/ctru-rs/src/services/cam.rs index 3dd52ef..1964cb9 100644 --- a/ctru-rs/src/services/cam.rs +++ b/ctru-rs/src/services/cam.rs @@ -633,7 +633,7 @@ pub trait Camera: private::ConfigurableCamera { /// /// # Example /// - /// ```no_run + /// ``` /// # use std::error::Error; /// # fn main() -> Result<(), Box> { /// # diff --git a/ctru-rs/src/services/gfx.rs b/ctru-rs/src/services/gfx.rs index 25830a6..8c8764a 100644 --- a/ctru-rs/src/services/gfx.rs +++ b/ctru-rs/src/services/gfx.rs @@ -350,11 +350,11 @@ impl Gfx { /// By initializing the [`Gfx`] service as such, all functionality that relies on CPU manipulation of the framebuffers will /// be completely unavailable (usually resulting in an ARM panic if wrongly used). /// - /// Things such as [`Console`](crate::console::Console) and [`Screen::raw_framebuffer()`] will result in ARM exceptions. + /// Usage of functionality such as [`Console`](crate::console::Console) and [`Screen::raw_framebuffer()`] will result in ARM exceptions. /// /// # Example /// - /// ```no_run + /// ``` /// # use std::error::Error; /// # fn main() -> Result<(), Box> { /// # diff --git a/ctru-rs/src/services/hid.rs b/ctru-rs/src/services/hid.rs index 4997158..36588b0 100644 --- a/ctru-rs/src/services/hid.rs +++ b/ctru-rs/src/services/hid.rs @@ -81,6 +81,7 @@ bitflags! { } /// Error enum for generic errors within the [`Hid`] service. +#[non_exhaustive] #[derive(Copy, Clone, Debug, PartialEq, Eq)] pub enum Error { /// An attempt was made to access the accelerometer while disabled. @@ -89,6 +90,28 @@ pub enum Error { UnavailableGyroscope, } +/// Representation of the acceleration vector read by the accelerometer. +/// +/// Have a look at [`Hid::enable_accelerometer()`] for more information. +#[allow(missing_docs)] +#[derive(Default, Copy, Clone, Debug, PartialEq, Eq)] +pub struct Acceleration { + x: i16, + y: i16, + z: i16, +} + +/// Representation of the angular rate read by the gyroscope. +/// +/// Have a look at [`Hid::enable_gyroscope())`] for more information. +#[allow(missing_docs)] +#[derive(Default, Copy, Clone, Debug, PartialEq, Eq)] +pub struct AngularRate { + roll: i16, + pitch: i16, + yaw: i16, +} + /// Handle to the HID service. pub struct Hid { active_accelerometer: bool, @@ -336,7 +359,7 @@ impl Hid { /// /// # Example /// - /// ```no_run + /// ``` /// # use std::error::Error; /// # fn main() -> Result<(), Box> { /// # @@ -365,7 +388,7 @@ impl Hid { /// /// # Example /// - /// ```no_run + /// ``` /// # use std::error::Error; /// # fn main() -> Result<(), Box> { /// # @@ -373,28 +396,30 @@ impl Hid { /// let mut hid = Hid::new()?; /// /// // The accelerometer will start to register movements. - /// hid.set_accelerometer(true); + /// hid.set_accelerometer(true).unwrap(); /// # /// # Ok(()) /// # } /// ``` #[doc(alias = "HIDUSER_EnableAccelerometer")] #[doc(alias = "HIDUSER_DisableAccelerometer")] - pub fn set_accelerometer(&mut self, enabled: bool) { + pub fn set_accelerometer(&mut self, enabled: bool) -> crate::Result<()> { if enabled { - let _ = unsafe { ctru_sys::HIDUSER_EnableAccelerometer() }; + ResultCode(unsafe { ctru_sys::HIDUSER_EnableAccelerometer() })?; } else { - let _ = unsafe { ctru_sys::HIDUSER_DisableAccelerometer() }; + ResultCode(unsafe { ctru_sys::HIDUSER_DisableAccelerometer() })?; } self.active_accelerometer = enabled; + + Ok(()) } /// Activate/deactivate the console's gyroscopic sensor. /// /// # Example /// - /// ```no_run + /// ``` /// # use std::error::Error; /// # fn main() -> Result<(), Box> { /// # @@ -402,24 +427,26 @@ impl Hid { /// let mut hid = Hid::new()?; /// /// // The gyroscope will start to register positions. - /// hid.set_gyroscope(true); + /// hid.set_gyroscope(true).unwrap(); /// # /// # Ok(()) /// # } /// ``` #[doc(alias = "HIDUSER_EnableGyroscope")] #[doc(alias = "HIDUSER_DisableGyroscope")] - pub fn set_gyroscope(&mut self, enabled: bool) { + pub fn set_gyroscope(&mut self, enabled: bool) -> crate::Result<()> { if enabled { - let _ = unsafe { ctru_sys::HIDUSER_EnableGyroscope() }; + ResultCode(unsafe { ctru_sys::HIDUSER_EnableGyroscope() })?; } else { - let _ = unsafe { ctru_sys::HIDUSER_DisableGyroscope() }; + ResultCode(unsafe { ctru_sys::HIDUSER_DisableGyroscope() })?; } self.active_gyroscope = enabled; + + Ok(()) } - /// Returns the acceleration vector (x,y,z) registered by the accelerometer. + /// Returns the acceleration vector (x, y, z) registered by the accelerometer. /// /// # Errors /// @@ -428,7 +455,7 @@ impl Hid { /// /// # Example /// - /// ```no_run + /// ``` /// # use std::error::Error; /// # fn main() -> Result<(), Box> { /// # @@ -436,7 +463,7 @@ impl Hid { /// let mut hid = Hid::new()?; /// /// // The accelerometer will start to register movements. - /// hid.set_accelerometer(true); + /// hid.set_accelerometer(true).unwrap(); /// /// // It's necessary to run `scan_input()` to update the accelerometer's readings. /// hid.scan_input(); @@ -448,7 +475,7 @@ impl Hid { /// # } /// ``` #[doc(alias = "hidAccelRead")] - pub fn accelerometer_vector(&self) -> Result<(i16, i16, i16), Error> { + pub fn accelerometer_vector(&self) -> Result { if !self.active_accelerometer { return Err(Error::UnavailableAccelerometer); } @@ -459,10 +486,14 @@ impl Hid { ctru_sys::hidAccelRead(&mut res); } - Ok((res.x, res.y, res.z)) + Ok(Acceleration { + x: res.x, + y: res.y, + z: res.z, + }) } - /// Returns the angular rate (roll,pitch,yaw) registered by the gyroscope. + /// Returns the angular rate registered by the gyroscope. /// /// # Errors /// @@ -471,7 +502,7 @@ impl Hid { /// /// # Example /// - /// ```no_run + /// ``` /// # use std::error::Error; /// # fn main() -> Result<(), Box> { /// # @@ -479,7 +510,7 @@ impl Hid { /// let mut hid = Hid::new()?; /// /// // The gyroscope will start to register positions. - /// hid.set_gyroscope(true); + /// hid.set_gyroscope(true).unwrap(); /// /// // It's necessary to run `scan_input()` to update the gyroscope's readings. /// hid.scan_input(); @@ -491,7 +522,7 @@ impl Hid { /// # } /// ``` #[doc(alias = "hidGyroRead")] - pub fn gyroscope_rate(&self) -> Result<(i16, i16, i16), Error> { + pub fn gyroscope_rate(&self) -> Result { if !self.active_gyroscope { return Err(Error::UnavailableGyroscope); } @@ -502,7 +533,23 @@ impl Hid { ctru_sys::hidGyroRead(&mut res); } - Ok((res.x, res.y, res.z)) + Ok(AngularRate { + roll: res.x, + pitch: res.y, + yaw: res.z, + }) + } +} + +impl From for (i16, i16, i16) { + fn from(value: Acceleration) -> (i16, i16, i16) { + (value.x, value.y, value.z) + } +} + +impl From for (i16, i16, i16) { + fn from(value: AngularRate) -> (i16, i16, i16) { + (value.roll, value.pitch, value.yaw) } } diff --git a/ctru-rs/src/services/ndsp/mod.rs b/ctru-rs/src/services/ndsp/mod.rs index 4176f70..3e96184 100644 --- a/ctru-rs/src/services/ndsp/mod.rs +++ b/ctru-rs/src/services/ndsp/mod.rs @@ -85,6 +85,7 @@ pub enum InterpolationType { } /// Errors returned by [`ndsp`](self) functions. +#[non_exhaustive] #[derive(Copy, Clone, Debug, PartialEq, Eq)] pub enum Error { /// Channel with the specified ID does not exist.