use crate::{Date, Time};
#[derive(Debug)]
pub struct Power;
impl Power {
pub fn begin(&mut self) -> bool {
unsafe { m5unified_sys::m5u_power_begin() }
}
pub fn pmic_type(&self) -> PowerType {
PowerType::from_raw(unsafe { m5unified_sys::m5u_power_get_type() as i32 })
}
pub fn battery_level(&self) -> Option<u8> {
let level = unsafe { m5unified_sys::m5u_battery_level() };
if (0..=100).contains(&level) {
Some(level as u8)
} else {
None
}
}
pub fn battery_voltage_mv(&self) -> Option<u16> {
let mv = unsafe { m5unified_sys::m5u_battery_voltage_mv() };
(mv >= 0).then_some(mv as u16)
}
pub fn vbus_voltage_mv(&self) -> Option<u16> {
let mv = unsafe { m5unified_sys::m5u_power_get_vbus_voltage_mv() };
(mv >= 0).then_some(mv as u16)
}
pub fn battery_current_ma(&self) -> i32 {
unsafe { m5unified_sys::m5u_power_get_battery_current_ma() as i32 }
}
pub fn ext_voltage_mv(&self, port_mask: ExtPortMask) -> f32 {
unsafe { m5unified_sys::m5u_power_get_ext_voltage_mv(port_mask.bits()) }
}
pub fn ext_current_ma(&self, port_mask: ExtPortMask) -> f32 {
unsafe { m5unified_sys::m5u_power_get_ext_current_ma(port_mask.bits()) }
}
pub fn charge_state(&self) -> ChargeState {
ChargeState::from_raw(unsafe { m5unified_sys::m5u_power_get_charge_state() as i32 })
}
pub fn is_charging(&self) -> bool {
unsafe { m5unified_sys::m5u_power_is_charging() }
}
pub fn set_led(&mut self, brightness: u8) {
unsafe { m5unified_sys::m5u_power_set_led(brightness) }
}
pub fn set_ext_output(&mut self, enable: bool, port_mask: ExtPortMask) {
unsafe { m5unified_sys::m5u_power_set_ext_output(enable, port_mask.bits()) }
}
pub fn set_ext_power(&mut self, enable: bool) {
self.set_ext_output(enable, ExtPortMask::ALL)
}
pub fn ext_output(&self) -> bool {
unsafe { m5unified_sys::m5u_power_get_ext_output() }
}
pub fn set_usb_output(&mut self, enable: bool) {
unsafe { m5unified_sys::m5u_power_set_usb_output(enable) }
}
pub fn usb_output(&self) -> bool {
unsafe { m5unified_sys::m5u_power_get_usb_output() }
}
pub fn set_battery_charge(&mut self, enable: bool) {
unsafe { m5unified_sys::m5u_power_set_battery_charge(enable) }
}
pub fn set_charge_current_ma(&mut self, max_ma: u16) {
unsafe { m5unified_sys::m5u_power_set_charge_current(max_ma) }
}
pub fn set_charge_voltage_mv(&mut self, max_mv: u16) {
unsafe { m5unified_sys::m5u_power_set_charge_voltage(max_mv) }
}
pub fn key_state(&self) -> u8 {
unsafe { m5unified_sys::m5u_power_get_key_state() }
}
pub fn set_ext_port_bus_config(&mut self, config: ExtPortBusConfig) {
let raw = config.to_raw();
unsafe { m5unified_sys::m5u_power_set_ext_port_bus_config(&raw) }
}
pub fn set_vibration(&mut self, level: u8) {
unsafe { m5unified_sys::m5u_power_set_vibration(level) }
}
pub fn power_off(&mut self) {
unsafe { m5unified_sys::m5u_power_power_off() }
}
pub fn timer_sleep_seconds(&mut self, seconds: i32) {
unsafe { m5unified_sys::m5u_power_timer_sleep_seconds(seconds) }
}
pub fn timer_sleep_time(&mut self, time: Time) {
let raw = time.to_raw();
unsafe { m5unified_sys::m5u_power_timer_sleep_time(&raw) }
}
pub fn timer_sleep_date_time(&mut self, date: Date, time: Time) {
let date = date.to_raw();
let time = time.to_raw();
unsafe { m5unified_sys::m5u_power_timer_sleep_date_time(&date, &time) }
}
pub fn deep_sleep_us(&mut self, micro_seconds: u64, touch_wakeup: bool) {
unsafe { m5unified_sys::m5u_power_deep_sleep_us(micro_seconds, touch_wakeup) }
}
pub fn light_sleep_us(&mut self, micro_seconds: u64, touch_wakeup: bool) {
unsafe { m5unified_sys::m5u_power_light_sleep_us(micro_seconds, touch_wakeup) }
}
pub fn axp192(&self) -> Axp192 {
Axp192
}
pub fn axp2101(&self) -> Axp2101 {
Axp2101
}
pub fn aw32001(&self) -> Aw32001 {
Aw32001
}
pub fn bq27220(&self) -> Bq27220 {
Bq27220
}
pub fn ina226(&self) -> Ina226 {
Ina226
}
pub fn ina3221(&self, index: usize) -> Ina3221 {
Ina3221 { index }
}
pub fn ip5306(&self) -> Ip5306 {
Ip5306
}
pub fn py32pmic(&self) -> Py32Pmic {
Py32Pmic
}
}
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub struct ExtPortBusConfig {
pub voltage_mv: u16,
pub current_limit_ma: u8,
pub enable: bool,
pub direction_output: bool,
}
impl ExtPortBusConfig {
fn to_raw(self) -> m5unified_sys::m5u_power_ext_port_bus_t {
m5unified_sys::m5u_power_ext_port_bus_t {
voltage_mv: self.voltage_mv,
current_limit_ma: self.current_limit_ma,
enable: self.enable,
direction_output: self.direction_output,
}
}
}
impl Default for ExtPortBusConfig {
fn default() -> Self {
Self {
voltage_mv: 5_000,
current_limit_ma: 0,
enable: false,
direction_output: false,
}
}
}
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub enum PowerType {
Unknown,
Adc,
Axp192,
Ip5306,
Axp2101,
Aw32001,
Py32Pmic,
M5Pm1,
Raw(i32),
}
impl PowerType {
pub const fn from_raw(raw: i32) -> Self {
match raw {
0 => Self::Unknown,
1 => Self::Adc,
2 => Self::Axp192,
3 => Self::Ip5306,
4 => Self::Axp2101,
5 => Self::Aw32001,
6 => Self::Py32Pmic,
7 => Self::M5Pm1,
other => Self::Raw(other),
}
}
pub const fn raw(self) -> i32 {
match self {
Self::Unknown => 0,
Self::Adc => 1,
Self::Axp192 => 2,
Self::Ip5306 => 3,
Self::Axp2101 => 4,
Self::Aw32001 => 5,
Self::Py32Pmic => 6,
Self::M5Pm1 => 7,
Self::Raw(raw) => raw,
}
}
}
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub enum ChargeState {
Discharging,
Charging,
Unknown,
Raw(i32),
}
impl ChargeState {
pub const fn from_raw(raw: i32) -> Self {
match raw {
0 => Self::Discharging,
1 => Self::Charging,
2 => Self::Unknown,
other => Self::Raw(other),
}
}
pub const fn raw(self) -> i32 {
match self {
Self::Discharging => 0,
Self::Charging => 1,
Self::Unknown => 2,
Self::Raw(raw) => raw,
}
}
}
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub enum Axp192PekPress {
None,
Long,
Short,
Both,
Raw(u8),
}
impl Axp192PekPress {
pub const fn from_raw(raw: u8) -> Self {
match raw {
0 => Self::None,
1 => Self::Long,
2 => Self::Short,
3 => Self::Both,
other => Self::Raw(other),
}
}
pub const fn raw(self) -> u8 {
match self {
Self::None => 0,
Self::Long => 1,
Self::Short => 2,
Self::Both => 3,
Self::Raw(raw) => raw,
}
}
}
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub enum Axp2101ChargeStatus {
Unavailable,
Discharging,
Standby,
Charging,
Raw(i32),
}
impl Axp2101ChargeStatus {
pub const fn from_raw(raw: i32) -> Self {
match raw {
-2 => Self::Unavailable,
-1 => Self::Discharging,
0 => Self::Standby,
1 => Self::Charging,
other => Self::Raw(other),
}
}
pub const fn raw(self) -> i32 {
match self {
Self::Unavailable => -2,
Self::Discharging => -1,
Self::Standby => 0,
Self::Charging => 1,
Self::Raw(raw) => raw,
}
}
}
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub enum Axp2101PekPress {
None,
Long,
Short,
Both,
Raw(u8),
}
impl Axp2101PekPress {
pub const fn from_raw(raw: u8) -> Self {
match raw {
0 => Self::None,
1 => Self::Long,
2 => Self::Short,
3 => Self::Both,
other => Self::Raw(other),
}
}
pub const fn raw(self) -> u8 {
match self {
Self::None => 0,
Self::Long => 1,
Self::Short => 2,
Self::Both => 3,
Self::Raw(raw) => raw,
}
}
}
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub enum Aw32001ChargeStatus {
Unknown,
NotCharging,
PreCharge,
Charging,
ChargeDone,
Raw(i32),
}
impl Aw32001ChargeStatus {
pub const fn from_raw(raw: i32) -> Self {
match raw {
-1 => Self::Unknown,
0 => Self::NotCharging,
1 => Self::PreCharge,
2 => Self::Charging,
3 => Self::ChargeDone,
other => Self::Raw(other),
}
}
pub const fn raw(self) -> i32 {
match self {
Self::Unknown => -1,
Self::NotCharging => 0,
Self::PreCharge => 1,
Self::Charging => 2,
Self::ChargeDone => 3,
Self::Raw(raw) => raw,
}
}
}
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub enum Py32PmicPekPress {
None,
Short,
Raw(u8),
}
impl Py32PmicPekPress {
pub const fn from_raw(raw: u8) -> Self {
match raw {
0 => Self::None,
2 => Self::Short,
other => Self::Raw(other),
}
}
pub const fn raw(self) -> u8 {
match self {
Self::None => 0,
Self::Short => 2,
Self::Raw(raw) => raw,
}
}
}
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub enum Ina226Sampling {
Rate1,
Rate4,
Rate16,
Rate64,
Rate128,
Rate256,
Rate512,
Rate1024,
Raw(u8),
}
impl Ina226Sampling {
pub const fn from_raw(raw: u8) -> Self {
match raw {
0 => Self::Rate1,
1 => Self::Rate4,
2 => Self::Rate16,
3 => Self::Rate64,
4 => Self::Rate128,
5 => Self::Rate256,
6 => Self::Rate512,
7 => Self::Rate1024,
other => Self::Raw(other),
}
}
pub const fn raw(self) -> u8 {
match self {
Self::Rate1 => 0,
Self::Rate4 => 1,
Self::Rate16 => 2,
Self::Rate64 => 3,
Self::Rate128 => 4,
Self::Rate256 => 5,
Self::Rate512 => 6,
Self::Rate1024 => 7,
Self::Raw(raw) => raw,
}
}
}
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub enum Ina226ConversionTime {
Us140,
Us204,
Us332,
Us588,
Us1100,
Us2116,
Us4156,
Us8244,
Raw(u8),
}
impl Ina226ConversionTime {
pub const fn from_raw(raw: u8) -> Self {
match raw {
0 => Self::Us140,
1 => Self::Us204,
2 => Self::Us332,
3 => Self::Us588,
4 => Self::Us1100,
5 => Self::Us2116,
6 => Self::Us4156,
7 => Self::Us8244,
other => Self::Raw(other),
}
}
pub const fn raw(self) -> u8 {
match self {
Self::Us140 => 0,
Self::Us204 => 1,
Self::Us332 => 2,
Self::Us588 => 3,
Self::Us1100 => 4,
Self::Us2116 => 5,
Self::Us4156 => 6,
Self::Us8244 => 7,
Self::Raw(raw) => raw,
}
}
}
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub enum Ina226Mode {
PowerDown,
ShuntVoltageSingle,
BusVoltageSingle,
ShuntAndBusSingle,
ShuntVoltage,
BusVoltage,
ShuntAndBus,
Raw(u8),
}
impl Ina226Mode {
pub const fn from_raw(raw: u8) -> Self {
match raw {
0 => Self::PowerDown,
1 => Self::ShuntVoltageSingle,
2 => Self::BusVoltageSingle,
3 => Self::ShuntAndBusSingle,
5 => Self::ShuntVoltage,
6 => Self::BusVoltage,
7 => Self::ShuntAndBus,
other => Self::Raw(other),
}
}
pub const fn raw(self) -> u8 {
match self {
Self::PowerDown => 0,
Self::ShuntVoltageSingle => 1,
Self::BusVoltageSingle => 2,
Self::ShuntAndBusSingle => 3,
Self::ShuntVoltage => 5,
Self::BusVoltage => 6,
Self::ShuntAndBus => 7,
Self::Raw(raw) => raw,
}
}
}
#[derive(Debug, Copy, Clone, PartialEq)]
pub struct Ina226Config {
pub shunt_res_ohm: f32,
pub max_expected_current_a: f32,
pub sampling_rate: Ina226Sampling,
pub shunt_conversion_time: Ina226ConversionTime,
pub bus_conversion_time: Ina226ConversionTime,
pub mode: Ina226Mode,
}
impl Ina226Config {
fn to_raw(self) -> m5unified_sys::m5u_power_ina226_config_t {
m5unified_sys::m5u_power_ina226_config_t {
shunt_res: self.shunt_res_ohm,
max_expected_current: self.max_expected_current_a,
sampling_rate: self.sampling_rate.raw(),
shunt_conversion_time: self.shunt_conversion_time.raw(),
bus_conversion_time: self.bus_conversion_time.raw(),
mode: self.mode.raw(),
}
}
}
impl Default for Ina226Config {
fn default() -> Self {
Self {
shunt_res_ohm: 0.1,
max_expected_current_a: 2.0,
sampling_rate: Ina226Sampling::Rate16,
shunt_conversion_time: Ina226ConversionTime::Us1100,
bus_conversion_time: Ina226ConversionTime::Us1100,
mode: Ina226Mode::ShuntAndBus,
}
}
}
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub struct ExtPortMask(u16);
impl ExtPortMask {
pub const NONE: Self = Self(0);
pub const PA: Self = Self(1 << 0);
pub const PB1: Self = Self(1 << 1);
pub const PB2: Self = Self(1 << 2);
pub const PC1: Self = Self(1 << 3);
pub const PC2: Self = Self(1 << 4);
pub const USB: Self = Self(1 << 5);
pub const PWR485: Self = Self(1 << 6);
pub const PWRCAN: Self = Self(1 << 7);
pub const MAIN: Self = Self(1 << 15);
pub const ALL: Self = Self(0x00FF);
pub const fn from_bits(bits: u16) -> Self {
Self(bits)
}
pub const fn bits(self) -> u16 {
self.0
}
}
impl Default for ExtPortMask {
fn default() -> Self {
Self::NONE
}
}
impl core::ops::BitOr for ExtPortMask {
type Output = Self;
fn bitor(self, rhs: Self) -> Self::Output {
Self(self.0 | rhs.0)
}
}
impl core::ops::BitOrAssign for ExtPortMask {
fn bitor_assign(&mut self, rhs: Self) {
self.0 |= rhs.0;
}
}
impl core::ops::BitAnd for ExtPortMask {
type Output = Self;
fn bitand(self, rhs: Self) -> Self::Output {
Self(self.0 & rhs.0)
}
}
impl core::ops::BitAndAssign for ExtPortMask {
fn bitand_assign(&mut self, rhs: Self) {
self.0 &= rhs.0;
}
}
#[derive(Debug)]
pub struct Axp192;
impl Axp192 {
pub fn begin(&self) -> bool {
unsafe { m5unified_sys::m5u_power_axp192_begin() }
}
pub fn battery_level(&self) -> Option<u8> {
let level = unsafe { m5unified_sys::m5u_power_axp192_get_battery_level() };
if (0..=100).contains(&level) {
Some(level as u8)
} else {
None
}
}
pub fn set_battery_charge(&self, enable: bool) -> bool {
unsafe { m5unified_sys::m5u_power_axp192_set_battery_charge(enable) }
}
pub fn set_charge_current_ma(&self, max_ma: u16) -> bool {
unsafe { m5unified_sys::m5u_power_axp192_set_charge_current(max_ma) }
}
pub fn set_charge_voltage_mv(&self, max_mv: u16) -> bool {
unsafe { m5unified_sys::m5u_power_axp192_set_charge_voltage(max_mv) }
}
pub fn is_charging(&self) -> bool {
unsafe { m5unified_sys::m5u_power_axp192_is_charging() }
}
fn voltage_raw(voltage_mv: Option<u16>) -> i32 {
voltage_mv.map(i32::from).unwrap_or(-1)
}
fn set_dcdc(&self, channel: u8, voltage_mv: Option<u16>) -> bool {
unsafe { m5unified_sys::m5u_power_axp192_set_dcdc(channel, Self::voltage_raw(voltage_mv)) }
}
fn set_ldo(&self, channel: u8, voltage_mv: Option<u16>) -> bool {
unsafe { m5unified_sys::m5u_power_axp192_set_ldo(channel, Self::voltage_raw(voltage_mv)) }
}
pub fn set_dcdc1_mv(&self, voltage_mv: Option<u16>) -> bool {
self.set_dcdc(1, voltage_mv)
}
pub fn set_dcdc2_mv(&self, voltage_mv: Option<u16>) -> bool {
self.set_dcdc(2, voltage_mv)
}
pub fn set_dcdc3_mv(&self, voltage_mv: Option<u16>) -> bool {
self.set_dcdc(3, voltage_mv)
}
pub fn set_ldo0_mv(&self, voltage_mv: Option<u16>) -> bool {
self.set_ldo(0, voltage_mv)
}
pub fn set_ldo2_mv(&self, voltage_mv: Option<u16>) -> bool {
self.set_ldo(2, voltage_mv)
}
pub fn set_ldo3_mv(&self, voltage_mv: Option<u16>) -> bool {
self.set_ldo(3, voltage_mv)
}
pub fn set_gpio(&self, gpio_num: u8, state: bool) -> bool {
unsafe { m5unified_sys::m5u_power_axp192_set_gpio(gpio_num, state) }
}
pub fn set_gpio0(&self, state: bool) -> bool {
self.set_gpio(0, state)
}
pub fn set_gpio1(&self, state: bool) -> bool {
self.set_gpio(1, state)
}
pub fn set_gpio2(&self, state: bool) -> bool {
self.set_gpio(2, state)
}
pub fn set_gpio3(&self, state: bool) -> bool {
self.set_gpio(3, state)
}
pub fn set_gpio4(&self, state: bool) -> bool {
self.set_gpio(4, state)
}
pub fn power_off(&self) -> bool {
unsafe { m5unified_sys::m5u_power_axp192_power_off() }
}
pub fn set_adc_state(&self, enable: bool) -> bool {
unsafe { m5unified_sys::m5u_power_axp192_set_adc_state(enable) }
}
pub fn set_adc_rate(&self, rate: u8) -> bool {
unsafe { m5unified_sys::m5u_power_axp192_set_adc_rate(rate) }
}
pub fn set_exten(&self, enable: bool) -> bool {
unsafe { m5unified_sys::m5u_power_axp192_set_exten(enable) }
}
pub fn set_backup(&self, enable: bool) -> bool {
unsafe { m5unified_sys::m5u_power_axp192_set_backup(enable) }
}
pub fn is_acin(&self) -> bool {
unsafe { m5unified_sys::m5u_power_axp192_is_acin() }
}
pub fn is_vbus(&self) -> bool {
unsafe { m5unified_sys::m5u_power_axp192_is_vbus() }
}
pub fn battery_present(&self) -> bool {
unsafe { m5unified_sys::m5u_power_axp192_get_bat_state() }
}
pub fn exten(&self) -> bool {
unsafe { m5unified_sys::m5u_power_axp192_get_exten() }
}
pub fn battery_voltage_v(&self) -> f32 {
unsafe { m5unified_sys::m5u_power_axp192_get_battery_voltage_v() }
}
pub fn battery_discharge_current_ma(&self) -> f32 {
unsafe { m5unified_sys::m5u_power_axp192_get_battery_discharge_current_ma() }
}
pub fn battery_charge_current_ma(&self) -> f32 {
unsafe { m5unified_sys::m5u_power_axp192_get_battery_charge_current_ma() }
}
pub fn battery_power_mw(&self) -> f32 {
unsafe { m5unified_sys::m5u_power_axp192_get_battery_power_mw() }
}
pub fn acin_voltage_v(&self) -> f32 {
unsafe { m5unified_sys::m5u_power_axp192_get_acin_voltage_v() }
}
pub fn acin_current_ma(&self) -> f32 {
unsafe { m5unified_sys::m5u_power_axp192_get_acin_current_ma() }
}
pub fn vbus_voltage_v(&self) -> f32 {
unsafe { m5unified_sys::m5u_power_axp192_get_vbus_voltage_v() }
}
pub fn vbus_current_ma(&self) -> f32 {
unsafe { m5unified_sys::m5u_power_axp192_get_vbus_current_ma() }
}
pub fn aps_voltage_v(&self) -> f32 {
unsafe { m5unified_sys::m5u_power_axp192_get_aps_voltage_v() }
}
pub fn internal_temperature_c(&self) -> f32 {
unsafe { m5unified_sys::m5u_power_axp192_get_internal_temperature_c() }
}
pub fn pek_press(&self) -> Axp192PekPress {
Axp192PekPress::from_raw(unsafe { m5unified_sys::m5u_power_axp192_get_pek_press() })
}
}
#[derive(Debug)]
pub struct Aw32001;
impl Aw32001 {
pub fn begin(&self) -> bool {
unsafe { m5unified_sys::m5u_power_aw32001_begin() }
}
pub fn set_battery_charge(&self, enable: bool) -> bool {
unsafe { m5unified_sys::m5u_power_aw32001_set_battery_charge(enable) }
}
pub fn set_charge_current_ma(&self, max_ma: u16) -> bool {
unsafe { m5unified_sys::m5u_power_aw32001_set_charge_current(max_ma) }
}
pub fn set_charge_voltage_mv(&self, max_mv: u16) -> bool {
unsafe { m5unified_sys::m5u_power_aw32001_set_charge_voltage(max_mv) }
}
pub fn is_charging(&self) -> bool {
unsafe { m5unified_sys::m5u_power_aw32001_is_charging() }
}
pub fn charge_current_ma(&self) -> Option<u16> {
let current = unsafe { m5unified_sys::m5u_power_aw32001_get_charge_current() };
(current != 0).then_some(current)
}
pub fn charge_voltage_mv(&self) -> Option<u16> {
let voltage = unsafe { m5unified_sys::m5u_power_aw32001_get_charge_voltage() };
(voltage != 0).then_some(voltage)
}
pub fn charge_status(&self) -> Aw32001ChargeStatus {
Aw32001ChargeStatus::from_raw(unsafe {
m5unified_sys::m5u_power_aw32001_get_charge_status()
})
}
}
#[derive(Debug)]
pub struct Bq27220;
impl Bq27220 {
pub fn begin(&self) -> bool {
unsafe { m5unified_sys::m5u_power_bq27220_begin() }
}
pub fn current_ma(&self) -> i16 {
unsafe { m5unified_sys::m5u_power_bq27220_get_current_ma() }
}
pub fn voltage_mv(&self) -> i16 {
unsafe { m5unified_sys::m5u_power_bq27220_get_voltage_mv() }
}
pub fn current_a(&self) -> f32 {
unsafe { m5unified_sys::m5u_power_bq27220_get_current_a() }
}
pub fn voltage_v(&self) -> f32 {
unsafe { m5unified_sys::m5u_power_bq27220_get_voltage_v() }
}
}
#[derive(Debug)]
pub struct Ina226;
impl Ina226 {
pub fn begin(&self) -> bool {
unsafe { m5unified_sys::m5u_power_ina226_begin() }
}
pub fn configure(&self, config: Ina226Config) -> bool {
let raw = config.to_raw();
unsafe { m5unified_sys::m5u_power_ina226_config(&raw) }
}
pub fn bus_voltage_v(&self) -> f32 {
unsafe { m5unified_sys::m5u_power_ina226_get_bus_voltage_v() }
}
pub fn shunt_voltage_v(&self) -> f32 {
unsafe { m5unified_sys::m5u_power_ina226_get_shunt_voltage_v() }
}
pub fn shunt_current_a(&self) -> f32 {
unsafe { m5unified_sys::m5u_power_ina226_get_shunt_current_a() }
}
pub fn power_w(&self) -> f32 {
unsafe { m5unified_sys::m5u_power_ina226_get_power_w() }
}
}
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub struct Ina3221 {
index: usize,
}
impl Ina3221 {
pub const CHANNEL_COUNT: usize = 3;
pub const fn index(&self) -> usize {
self.index
}
pub fn begin(&self) -> bool {
unsafe { m5unified_sys::m5u_power_ina3221_begin(self.index) }
}
pub fn set_shunt_res_milliohm(&self, channel: usize, res: u32) -> bool {
unsafe {
m5unified_sys::m5u_power_ina3221_set_shunt_res(
self.index,
Self::channel_raw(channel),
res,
)
}
}
pub fn bus_voltage_v(&self, channel: usize) -> f32 {
unsafe {
m5unified_sys::m5u_power_ina3221_get_bus_voltage_v(
self.index,
Self::channel_raw(channel),
)
}
}
pub fn shunt_voltage_v(&self, channel: usize) -> f32 {
unsafe {
m5unified_sys::m5u_power_ina3221_get_shunt_voltage_v(
self.index,
Self::channel_raw(channel),
)
}
}
pub fn current_a(&self, channel: usize) -> f32 {
unsafe {
m5unified_sys::m5u_power_ina3221_get_current_a(self.index, Self::channel_raw(channel))
}
}
pub fn bus_voltage_mv(&self, channel: usize) -> i32 {
unsafe {
m5unified_sys::m5u_power_ina3221_get_bus_voltage_mv(
self.index,
Self::channel_raw(channel),
)
}
}
pub fn shunt_voltage_mv(&self, channel: usize) -> i32 {
unsafe {
m5unified_sys::m5u_power_ina3221_get_shunt_voltage_mv(
self.index,
Self::channel_raw(channel),
)
}
}
fn channel_raw(channel: usize) -> u8 {
if channel > u8::MAX as usize {
u8::MAX
} else {
channel as u8
}
}
}
#[derive(Debug)]
pub struct Ip5306;
impl Ip5306 {
pub fn begin(&self) -> bool {
unsafe { m5unified_sys::m5u_power_ip5306_begin() }
}
pub fn battery_level(&self) -> Option<u8> {
let level = unsafe { m5unified_sys::m5u_power_ip5306_get_battery_level() };
if (0..=100).contains(&level) {
Some(level as u8)
} else {
None
}
}
pub fn set_battery_charge(&self, enable: bool) -> bool {
unsafe { m5unified_sys::m5u_power_ip5306_set_battery_charge(enable) }
}
pub fn set_charge_current_ma(&self, max_ma: u16) -> bool {
unsafe { m5unified_sys::m5u_power_ip5306_set_charge_current(max_ma) }
}
pub fn set_charge_voltage_mv(&self, max_mv: u16) -> bool {
unsafe { m5unified_sys::m5u_power_ip5306_set_charge_voltage(max_mv) }
}
pub fn is_charging(&self) -> bool {
unsafe { m5unified_sys::m5u_power_ip5306_is_charging() }
}
pub fn set_power_boost_keep_on(&self, enable: bool) -> bool {
unsafe { m5unified_sys::m5u_power_ip5306_set_power_boost_keep_on(enable) }
}
}
#[derive(Debug)]
pub struct Py32Pmic;
impl Py32Pmic {
pub fn begin(&self) -> bool {
unsafe { m5unified_sys::m5u_power_py32pmic_begin() }
}
pub fn set_ext_output(&self, enable: bool) -> bool {
unsafe { m5unified_sys::m5u_power_py32pmic_set_ext_output(enable) }
}
pub fn set_battery_charge(&self, enable: bool) -> bool {
unsafe { m5unified_sys::m5u_power_py32pmic_set_battery_charge(enable) }
}
pub fn set_charge_current_ma(&self, max_ma: u16) -> bool {
unsafe { m5unified_sys::m5u_power_py32pmic_set_charge_current(max_ma) }
}
pub fn set_charge_voltage_mv(&self, max_mv: u16) -> bool {
unsafe { m5unified_sys::m5u_power_py32pmic_set_charge_voltage(max_mv) }
}
pub fn is_charging(&self) -> bool {
unsafe { m5unified_sys::m5u_power_py32pmic_is_charging() }
}
pub fn charge_current_ma(&self) -> Option<u16> {
let current = unsafe { m5unified_sys::m5u_power_py32pmic_get_charge_current() };
(current != 0).then_some(current)
}
pub fn charge_voltage_mv(&self) -> Option<u16> {
let voltage = unsafe { m5unified_sys::m5u_power_py32pmic_get_charge_voltage() };
(voltage != 0).then_some(voltage)
}
pub fn pek_press(&self) -> Py32PmicPekPress {
Py32PmicPekPress::from_raw(unsafe { m5unified_sys::m5u_power_py32pmic_get_pek_press() })
}
pub fn power_off(&self) -> bool {
unsafe { m5unified_sys::m5u_power_py32pmic_power_off() }
}
}
#[derive(Debug)]
pub struct Axp2101;
impl Axp2101 {
const LDO_KIND_ALDO: i32 = 0;
const LDO_KIND_BLDO: i32 = 1;
const LDO_KIND_DLDO: i32 = 2;
pub const IRQ_ALL: u64 = u64::MAX;
pub const IRQ_BAT_WORK_UNDER_TEMP: u64 = 1 << 0;
pub const IRQ_BAT_WORK_OVER_TEMP: u64 = 1 << 1;
pub const IRQ_BAT_CHG_UNDER_TEMP: u64 = 1 << 2;
pub const IRQ_BAT_CHG_OVER_TEMP: u64 = 1 << 3;
pub const IRQ_GAUGE_NEW_SOC: u64 = 1 << 4;
pub const IRQ_GAUGE_WDT_TIMEOUT: u64 = 1 << 5;
pub const IRQ_WARNING_LEVEL1: u64 = 1 << 6;
pub const IRQ_WARNING_LEVEL2: u64 = 1 << 7;
pub const IRQ_PKEY_POSITIVE_EDGE: u64 = 1 << 8;
pub const IRQ_PKEY_NEGATIVE_EDGE: u64 = 1 << 9;
pub const IRQ_PKEY_LONG_PRESS: u64 = 1 << 10;
pub const IRQ_PKEY_SHORT_PRESS: u64 = 1 << 11;
pub const IRQ_BAT_REMOVE: u64 = 1 << 12;
pub const IRQ_BAT_INSERT: u64 = 1 << 13;
pub const IRQ_VBUS_REMOVE: u64 = 1 << 14;
pub const IRQ_VBUS_INSERT: u64 = 1 << 15;
pub const IRQ_BAT_OVER_VOLTAGE: u64 = 1 << 16;
pub const IRQ_CHARGER_TIMER: u64 = 1 << 17;
pub const IRQ_DIE_OVER_TEMP: u64 = 1 << 18;
pub const IRQ_BAT_CHG_START: u64 = 1 << 19;
pub const IRQ_BAT_CHG_DONE: u64 = 1 << 20;
pub const IRQ_BATFET_OVER_CURR: u64 = 1 << 21;
pub const IRQ_LDO_OVER_CURR: u64 = 1 << 22;
pub const IRQ_WDT_EXPIRE: u64 = 1 << 23;
pub fn begin(&self) -> bool {
unsafe { m5unified_sys::m5u_power_axp2101_begin() }
}
pub fn battery_level(&self) -> Option<u8> {
let level = unsafe { m5unified_sys::m5u_power_axp2101_get_battery_level() };
if (0..=100).contains(&level) {
Some(level as u8)
} else {
None
}
}
pub fn set_battery_charge(&self, enable: bool) -> bool {
unsafe { m5unified_sys::m5u_power_axp2101_set_battery_charge(enable) }
}
pub fn set_pre_charge_current_ma(&self, max_ma: u16) -> bool {
unsafe { m5unified_sys::m5u_power_axp2101_set_pre_charge_current(max_ma) }
}
pub fn set_charge_current_ma(&self, max_ma: u16) -> bool {
unsafe { m5unified_sys::m5u_power_axp2101_set_charge_current(max_ma) }
}
pub fn set_charge_voltage_mv(&self, max_mv: u16) -> bool {
unsafe { m5unified_sys::m5u_power_axp2101_set_charge_voltage(max_mv) }
}
pub fn charge_status(&self) -> Axp2101ChargeStatus {
Axp2101ChargeStatus::from_raw(unsafe {
m5unified_sys::m5u_power_axp2101_get_charge_status()
})
}
pub fn is_charging(&self) -> bool {
unsafe { m5unified_sys::m5u_power_axp2101_is_charging() }
}
fn set_ldo(&self, kind: i32, channel: i32, voltage_mv: Option<u16>) -> bool {
let voltage_mv = voltage_mv.map(i32::from).unwrap_or(-1);
unsafe { m5unified_sys::m5u_power_axp2101_set_ldo(kind, channel, voltage_mv) }
}
fn ldo_enabled(&self, kind: i32, channel: i32) -> bool {
unsafe { m5unified_sys::m5u_power_axp2101_get_ldo_enabled(kind, channel) }
}
pub fn set_aldo1_mv(&self, voltage_mv: Option<u16>) -> bool {
self.set_ldo(Self::LDO_KIND_ALDO, 1, voltage_mv)
}
pub fn set_aldo2_mv(&self, voltage_mv: Option<u16>) -> bool {
self.set_ldo(Self::LDO_KIND_ALDO, 2, voltage_mv)
}
pub fn set_aldo3_mv(&self, voltage_mv: Option<u16>) -> bool {
self.set_ldo(Self::LDO_KIND_ALDO, 3, voltage_mv)
}
pub fn set_aldo4_mv(&self, voltage_mv: Option<u16>) -> bool {
self.set_ldo(Self::LDO_KIND_ALDO, 4, voltage_mv)
}
pub fn set_bldo1_mv(&self, voltage_mv: Option<u16>) -> bool {
self.set_ldo(Self::LDO_KIND_BLDO, 1, voltage_mv)
}
pub fn set_bldo2_mv(&self, voltage_mv: Option<u16>) -> bool {
self.set_ldo(Self::LDO_KIND_BLDO, 2, voltage_mv)
}
pub fn set_dldo1_mv(&self, voltage_mv: Option<u16>) -> bool {
self.set_ldo(Self::LDO_KIND_DLDO, 1, voltage_mv)
}
pub fn set_dldo2_mv(&self, voltage_mv: Option<u16>) -> bool {
self.set_ldo(Self::LDO_KIND_DLDO, 2, voltage_mv)
}
pub fn aldo1_enabled(&self) -> bool {
self.ldo_enabled(Self::LDO_KIND_ALDO, 1)
}
pub fn aldo2_enabled(&self) -> bool {
self.ldo_enabled(Self::LDO_KIND_ALDO, 2)
}
pub fn aldo3_enabled(&self) -> bool {
self.ldo_enabled(Self::LDO_KIND_ALDO, 3)
}
pub fn aldo4_enabled(&self) -> bool {
self.ldo_enabled(Self::LDO_KIND_ALDO, 4)
}
pub fn bldo1_enabled(&self) -> bool {
self.ldo_enabled(Self::LDO_KIND_BLDO, 1)
}
pub fn bldo2_enabled(&self) -> bool {
self.ldo_enabled(Self::LDO_KIND_BLDO, 2)
}
pub fn power_off(&self) -> bool {
unsafe { m5unified_sys::m5u_power_axp2101_power_off() }
}
pub fn set_adc_state(&self, enable: bool) -> bool {
unsafe { m5unified_sys::m5u_power_axp2101_set_adc_state(enable) }
}
pub fn set_adc_rate(&self, rate: u8) -> bool {
unsafe { m5unified_sys::m5u_power_axp2101_set_adc_rate(rate) }
}
pub fn set_backup(&self, enable: bool) -> bool {
unsafe { m5unified_sys::m5u_power_axp2101_set_backup(enable) }
}
pub fn is_acin(&self) -> bool {
unsafe { m5unified_sys::m5u_power_axp2101_is_acin() }
}
pub fn is_vbus(&self) -> bool {
unsafe { m5unified_sys::m5u_power_axp2101_is_vbus() }
}
pub fn battery_present(&self) -> bool {
unsafe { m5unified_sys::m5u_power_axp2101_get_bat_state() }
}
pub fn battery_voltage_v(&self) -> f32 {
unsafe { m5unified_sys::m5u_power_axp2101_get_battery_voltage_v() }
}
pub fn battery_discharge_current_ma(&self) -> f32 {
unsafe { m5unified_sys::m5u_power_axp2101_get_battery_discharge_current_ma() }
}
pub fn battery_charge_current_ma(&self) -> f32 {
unsafe { m5unified_sys::m5u_power_axp2101_get_battery_charge_current_ma() }
}
pub fn battery_power_mw(&self) -> f32 {
unsafe { m5unified_sys::m5u_power_axp2101_get_battery_power_mw() }
}
pub fn acin_voltage_v(&self) -> f32 {
unsafe { m5unified_sys::m5u_power_axp2101_get_acin_voltage_v() }
}
pub fn acin_current_ma(&self) -> f32 {
unsafe { m5unified_sys::m5u_power_axp2101_get_acin_current_ma() }
}
pub fn vbus_voltage_v(&self) -> f32 {
unsafe { m5unified_sys::m5u_power_axp2101_get_vbus_voltage_v() }
}
pub fn vbus_current_ma(&self) -> f32 {
unsafe { m5unified_sys::m5u_power_axp2101_get_vbus_current_ma() }
}
pub fn ts_voltage_v(&self) -> f32 {
unsafe { m5unified_sys::m5u_power_axp2101_get_ts_voltage_v() }
}
pub fn aps_voltage_v(&self) -> f32 {
unsafe { m5unified_sys::m5u_power_axp2101_get_aps_voltage_v() }
}
pub fn internal_temperature_c(&self) -> f32 {
unsafe { m5unified_sys::m5u_power_axp2101_get_internal_temperature_c() }
}
pub fn pek_press(&self) -> Axp2101PekPress {
Axp2101PekPress::from_raw(unsafe { m5unified_sys::m5u_power_axp2101_get_pek_press() })
}
pub fn disable_irq(&self, mask: u64) -> bool {
unsafe { m5unified_sys::m5u_power_axp2101_disable_irq(mask) }
}
pub fn enable_irq(&self, mask: u64) -> bool {
unsafe { m5unified_sys::m5u_power_axp2101_enable_irq(mask) }
}
pub fn clear_irq_statuses(&self) -> bool {
unsafe { m5unified_sys::m5u_power_axp2101_clear_irq_statuses() }
}
pub fn irq_statuses(&self) -> Axp2101IrqStatus {
Axp2101IrqStatus::from_status_register_order(unsafe {
m5unified_sys::m5u_power_axp2101_get_irq_statuses()
})
}
}
#[derive(Debug, Copy, Clone, Default, PartialEq, Eq)]
pub struct Axp2101IrqStatus {
pub raw: u64,
}
impl Axp2101IrqStatus {
fn from_status_register_order(raw: u64) -> Self {
Self {
raw: ((raw >> 16) & 0xFF) | (raw & 0xFF00) | ((raw & 0xFF) << 16),
}
}
pub fn contains(&self, mask: u64) -> bool {
self.raw & mask != 0
}
pub fn is_empty(&self) -> bool {
self.raw == 0
}
pub fn battery_work_under_temperature(&self) -> bool {
self.contains(Axp2101::IRQ_BAT_WORK_UNDER_TEMP)
}
pub fn battery_work_over_temperature(&self) -> bool {
self.contains(Axp2101::IRQ_BAT_WORK_OVER_TEMP)
}
pub fn battery_charger_under_temperature(&self) -> bool {
self.contains(Axp2101::IRQ_BAT_CHG_UNDER_TEMP)
}
pub fn battery_charger_over_temperature(&self) -> bool {
self.contains(Axp2101::IRQ_BAT_CHG_OVER_TEMP)
}
pub fn gauge_new_soc(&self) -> bool {
self.contains(Axp2101::IRQ_GAUGE_NEW_SOC)
}
pub fn gauge_watchdog_timeout(&self) -> bool {
self.contains(Axp2101::IRQ_GAUGE_WDT_TIMEOUT)
}
pub fn warning_level1(&self) -> bool {
self.contains(Axp2101::IRQ_WARNING_LEVEL1)
}
pub fn warning_level2(&self) -> bool {
self.contains(Axp2101::IRQ_WARNING_LEVEL2)
}
pub fn pkey_positive_edge(&self) -> bool {
self.contains(Axp2101::IRQ_PKEY_POSITIVE_EDGE)
}
pub fn pkey_negative_edge(&self) -> bool {
self.contains(Axp2101::IRQ_PKEY_NEGATIVE_EDGE)
}
pub fn pkey_long_press(&self) -> bool {
self.contains(Axp2101::IRQ_PKEY_LONG_PRESS)
}
pub fn pkey_short_press(&self) -> bool {
self.contains(Axp2101::IRQ_PKEY_SHORT_PRESS)
}
pub fn battery_remove(&self) -> bool {
self.contains(Axp2101::IRQ_BAT_REMOVE)
}
pub fn battery_insert(&self) -> bool {
self.contains(Axp2101::IRQ_BAT_INSERT)
}
pub fn vbus_insert(&self) -> bool {
self.contains(Axp2101::IRQ_VBUS_INSERT)
}
pub fn vbus_remove(&self) -> bool {
self.contains(Axp2101::IRQ_VBUS_REMOVE)
}
pub fn battery_over_voltage(&self) -> bool {
self.contains(Axp2101::IRQ_BAT_OVER_VOLTAGE)
}
pub fn charger_timer_expired(&self) -> bool {
self.contains(Axp2101::IRQ_CHARGER_TIMER)
}
pub fn die_over_temperature(&self) -> bool {
self.contains(Axp2101::IRQ_DIE_OVER_TEMP)
}
pub fn battery_charge_start(&self) -> bool {
self.contains(Axp2101::IRQ_BAT_CHG_START)
}
pub fn battery_charge_done(&self) -> bool {
self.contains(Axp2101::IRQ_BAT_CHG_DONE)
}
pub fn batfet_over_current(&self) -> bool {
self.contains(Axp2101::IRQ_BATFET_OVER_CURR)
}
pub fn ldo_over_current(&self) -> bool {
self.contains(Axp2101::IRQ_LDO_OVER_CURR)
}
pub fn watchdog_expired(&self) -> bool {
self.contains(Axp2101::IRQ_WDT_EXPIRE)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn axp2101_status_register_order_is_normalized_to_irq_masks() {
let upstream_raw = (0b0000_0101_u64 << 16) | (0b1000_0000_u64 << 8) | 0b0100_0000_u64;
let status = Axp2101IrqStatus::from_status_register_order(upstream_raw);
assert!(status.battery_work_under_temperature());
assert!(status.battery_charger_under_temperature());
assert!(status.vbus_insert());
assert!(status.ldo_over_current());
assert!(!status.battery_work_over_temperature());
}
}