#![no_std]
pub mod audio;
#[cfg(feature = "ble")]
pub mod ble;
pub mod bsp;
pub mod display;
#[cfg(feature = "env")]
pub mod env;
pub mod imu;
pub mod input;
pub mod motion;
pub mod power;
pub mod sprite;
pub mod storage;
pub mod touch;
pub mod ui;
#[cfg(feature = "wifi")]
pub mod wifi;
#[cfg(feature = "ble")]
use crate::ble::Ble;
#[cfg(any(feature = "wifi", feature = "ble"))]
use crate::bsp::RadioRuntimeResources;
#[cfg(feature = "wifi")]
use crate::bsp::WifiResources;
use crate::bsp::{
BoardInitError, ButtonLevels, NessoBuzzer, NessoDisplay, NessoI2c, NessoN1, NessoN1Board,
};
use crate::imu::{Acceleration, Bmi270, Gyroscope};
use crate::power::{BatteryStatus, Power};
use crate::storage::{EspFlashSettingsStore, SettingsPartition};
use crate::touch::{Touch, TouchEvent, TouchState};
#[cfg(feature = "wifi")]
use crate::wifi::EspRadioWifi;
use esp_hal::delay::Delay;
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum NessoError {
Board(BoardInitError),
Touch,
Imu,
Power,
FlashUnavailable,
Storage,
#[cfg(feature = "wifi")]
WifiUnavailable,
#[cfg(feature = "ble")]
BleUnavailable,
#[cfg(any(feature = "wifi", feature = "ble"))]
RadioRuntimeUnavailable,
ImuNotInitialized,
Input,
}
pub struct Nesso {
pub display: NessoDisplay,
pub audio: NessoBuzzer,
i2c: NessoI2c,
#[cfg(feature = "wifi")]
wifi: Option<WifiResources>,
#[cfg(feature = "ble")]
ble: Option<crate::bsp::BleResources>,
#[cfg(any(feature = "wifi", feature = "ble"))]
radio_runtime: Option<RadioRuntimeResources>,
flash: Option<esp_hal::peripherals::FLASH<'static>>,
imu_initialized: bool,
previous_touch: TouchState,
}
impl Nesso {
pub fn new(peripherals: esp_hal::peripherals::Peripherals) -> Result<Self, NessoError> {
let parts = NessoN1Board::new(peripherals)
.into_core_parts()
.map_err(NessoError::Board)?;
let nesso = Self {
display: parts.display,
audio: parts.buzzer,
i2c: parts.i2c,
#[cfg(feature = "wifi")]
wifi: Some(parts.wifi),
#[cfg(feature = "ble")]
ble: Some(parts.ble),
#[cfg(any(feature = "wifi", feature = "ble"))]
radio_runtime: Some(parts.radio_runtime),
flash: Some(parts.flash),
imu_initialized: false,
previous_touch: TouchState::default(),
};
Ok(nesso)
}
pub fn init_imu(&mut self) -> Result<(), NessoError> {
Bmi270::new(&mut self.i2c, Delay::new())
.init()
.map_err(|_| NessoError::Imu)?;
self.imu_initialized = true;
Ok(())
}
pub fn touch_state(&mut self) -> Result<TouchState, NessoError> {
Touch::new(&mut self.i2c)
.read_state()
.map_err(|_| NessoError::Touch)
}
pub fn touch_event(&mut self) -> Result<TouchEvent, NessoError> {
let current = self.touch_state()?;
let event = match (self.previous_touch.primary(), current.primary()) {
(None, Some(point)) => TouchEvent::Pressed(point),
(Some(_), None) => TouchEvent::Released,
(Some(previous), Some(point)) if previous != point => TouchEvent::Moved(point),
_ => TouchEvent::Idle,
};
self.previous_touch = current;
Ok(event)
}
pub fn init_buttons(&mut self) -> Result<(), NessoError> {
NessoN1::init_button_inputs(&mut self.i2c).map_err(|_| NessoError::Input)
}
pub fn button_levels(&mut self) -> Result<ButtonLevels, NessoError> {
NessoN1::read_button_levels(&mut self.i2c).map_err(|_| NessoError::Input)
}
pub fn acceleration(&mut self) -> Result<Acceleration, NessoError> {
if !self.imu_initialized {
return Err(NessoError::ImuNotInitialized);
}
Bmi270::new(&mut self.i2c, Delay::new())
.acceleration()
.map_err(|_| NessoError::Imu)
}
pub fn gyroscope(&mut self) -> Result<Gyroscope, NessoError> {
if !self.imu_initialized {
return Err(NessoError::ImuNotInitialized);
}
Bmi270::new(&mut self.i2c, Delay::new())
.gyroscope()
.map_err(|_| NessoError::Imu)
}
pub fn battery_status(&mut self) -> Result<BatteryStatus, NessoError> {
Power::new(&mut self.i2c)
.battery_status()
.map_err(|_| NessoError::Power)
}
#[cfg(feature = "wifi")]
pub fn init_wifi(&mut self) -> Result<EspRadioWifi, NessoError> {
let wifi = self.wifi.take().ok_or(NessoError::WifiUnavailable)?;
let runtime = self
.radio_runtime
.take()
.ok_or(NessoError::RadioRuntimeUnavailable)?;
Ok(EspRadioWifi::new(wifi, runtime))
}
#[cfg(feature = "ble")]
pub fn init_ble(&mut self) -> Result<Ble, NessoError> {
let ble = self.ble.take().ok_or(NessoError::BleUnavailable)?;
let runtime = self
.radio_runtime
.take()
.ok_or(NessoError::RadioRuntimeUnavailable)?;
Ok(Ble::new(ble, runtime))
}
pub fn take_default_flash_settings(
&mut self,
) -> Result<EspFlashSettingsStore<'static>, NessoError> {
self.take_flash_settings_partition(SettingsPartition::DEFAULT)
}
pub fn take_flash_settings_partition(
&mut self,
partition: SettingsPartition,
) -> Result<EspFlashSettingsStore<'static>, NessoError> {
let flash = self.flash.take().ok_or(NessoError::FlashUnavailable)?;
EspFlashSettingsStore::from_partition(flash, partition).map_err(|_| NessoError::Storage)
}
pub fn take_flash_settings(
&mut self,
offset: u32,
) -> Result<EspFlashSettingsStore<'static>, NessoError> {
let flash = self.flash.take().ok_or(NessoError::FlashUnavailable)?;
Ok(EspFlashSettingsStore::from_flash(flash, offset))
}
}