Refactor SD LED functionality even more; move to different project and expand scope
This commit is contained in:
parent
508c6ceb9e
commit
437f5beb71
9 changed files with 409 additions and 621 deletions
729
backend/Cargo.lock
generated
729
backend/Cargo.lock
generated
File diff suppressed because it is too large
Load diff
|
@ -29,8 +29,8 @@ simplelog = "0.12"
|
||||||
# limits & driver functionality
|
# limits & driver functionality
|
||||||
limits_core = { version = "3", path = "./limits_core" }
|
limits_core = { version = "3", path = "./limits_core" }
|
||||||
regex = "1"
|
regex = "1"
|
||||||
libryzenadj = { version = "0.12" }
|
smokepatio = { version = "*", path = "../../smokepatio" }
|
||||||
sd_led = { version = "*", path = "./sd_led" }
|
libryzenadj = { version = "0.14", path = "../../libryzenadj-rs-14" }
|
||||||
# ureq's tls feature does not like musl targets
|
# ureq's tls feature does not like musl targets
|
||||||
ureq = { version = "2", features = ["json", "gzip", "brotli", "charset"], default-features = false, optional = true }
|
ureq = { version = "2", features = ["json", "gzip", "brotli", "charset"], default-features = false, optional = true }
|
||||||
|
|
||||||
|
|
16
backend/sd_led/Cargo.lock
generated
16
backend/sd_led/Cargo.lock
generated
|
@ -1,16 +0,0 @@
|
||||||
# This file is automatically @generated by Cargo.
|
|
||||||
# It is not intended for manual editing.
|
|
||||||
version = 3
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "log"
|
|
||||||
version = "0.4.20"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "sd_led"
|
|
||||||
version = "0.1.0"
|
|
||||||
dependencies = [
|
|
||||||
"log",
|
|
||||||
]
|
|
|
@ -1,10 +0,0 @@
|
||||||
[package]
|
|
||||||
name = "sd_led"
|
|
||||||
version = "0.1.0"
|
|
||||||
edition = "2021"
|
|
||||||
|
|
||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
|
||||||
|
|
||||||
[dependencies]
|
|
||||||
# logging
|
|
||||||
log = "0.4"
|
|
|
@ -1,193 +0,0 @@
|
||||||
//! Rough Rust port of some BatCtrl functionality
|
|
||||||
//! Original: /usr/share/jupiter_controller_fw_updater/RA_bootloader_updater/linux_host_tools/BatCtrl
|
|
||||||
//! I do not have access to the source code, so this is my own interpretation of what it does.
|
|
||||||
//!
|
|
||||||
//! But also Quanta is based in a place with some questionable copyright practices, so...
|
|
||||||
pub mod raw_io;
|
|
||||||
|
|
||||||
use std::io::Error;
|
|
||||||
|
|
||||||
pub fn set_led(red_unused: bool, green_aka_white: bool, blue_unused: bool) -> Result<usize, Error> {
|
|
||||||
let payload: u8 = 0x80
|
|
||||||
| (red_unused as u8 & 1)
|
|
||||||
| ((green_aka_white as u8 & 1) << 1)
|
|
||||||
| ((blue_unused as u8 & 1) << 2);
|
|
||||||
//log::info!("Payload: {:b}", payload);
|
|
||||||
raw_io::write2(Setting::LEDStatus as _, payload)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn set(setting: Setting, mode: u8) -> Result<usize, Error> {
|
|
||||||
raw_io::write2(setting as u8, mode)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Copy, Clone)]
|
|
||||||
#[repr(u8)]
|
|
||||||
pub enum Setting {
|
|
||||||
CycleCount = 0x32,
|
|
||||||
ControlBoard = 0x6C,
|
|
||||||
Charge = 0xA6,
|
|
||||||
ChargeMode = 0x76,
|
|
||||||
LEDStatus = 199,
|
|
||||||
LEDBreathing = 0x63,
|
|
||||||
FanSpeed = 0x2c, // lower 3 bits seem to not do everything, every other bit increases speed -- 5 total steps, 0xf4 seems to do something similar too
|
|
||||||
// 0x40 write 0x08 makes LED red + green turn on
|
|
||||||
// 0x58 write 0x80 shuts off battery power (bms?)
|
|
||||||
// 0x63 makes blue (0x02) or white (0x01) LED breathing effect
|
|
||||||
// 0x7a write 0x01, 0x02, or 0x03 turns off display
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug)]
|
|
||||||
#[repr(u8)]
|
|
||||||
pub enum ControlBoard {
|
|
||||||
Enable = 0xAA,
|
|
||||||
Disable = 0xAB,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug)]
|
|
||||||
#[repr(u8)]
|
|
||||||
pub enum ChargeMode {
|
|
||||||
Normal = 0,
|
|
||||||
Discharge = 0x42,
|
|
||||||
Idle = 0x45,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Copy, Clone)]
|
|
||||||
#[repr(u8)]
|
|
||||||
pub enum Charge {
|
|
||||||
Enable = 0,
|
|
||||||
Disable = 4,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
mod tests {
|
|
||||||
use super::*;
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
#[allow(dead_code)]
|
|
||||||
fn led_all_experiment_test() -> Result<(), Error> {
|
|
||||||
let original = raw_io::write_read(Setting::LEDStatus as _)?;
|
|
||||||
let sleep_dur = std::time::Duration::from_millis(1000);
|
|
||||||
for b in 0..0x7F {
|
|
||||||
let actual = 0x80 | b;
|
|
||||||
raw_io::write2(Setting::LEDStatus as _, actual)?;
|
|
||||||
println!("Wrote {actual:#b} to LED byte");
|
|
||||||
std::thread::sleep(sleep_dur);
|
|
||||||
}
|
|
||||||
raw_io::write2(Setting::LEDStatus as _, original)?;
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
#[allow(dead_code)]
|
|
||||||
fn led_singles_experiment_test() -> Result<(), Error> {
|
|
||||||
let original = raw_io::write_read(Setting::LEDStatus as _)?;
|
|
||||||
let sleep_dur = std::time::Duration::from_millis(1000);
|
|
||||||
let mut value = 1;
|
|
||||||
for _ in 0..std::mem::size_of::<u8>()*8 {
|
|
||||||
let actual = 0x80 | value;
|
|
||||||
raw_io::write2(Setting::LEDStatus as _, actual)?;
|
|
||||||
println!("Wrote {actual:#b} to LED byte");
|
|
||||||
value = value << 1;
|
|
||||||
std::thread::sleep(sleep_dur);
|
|
||||||
}
|
|
||||||
raw_io::write2(Setting::LEDStatus as _, original)?;
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
#[allow(dead_code)]
|
|
||||||
fn led_specify_experiment_test() -> Result<(), Error> {
|
|
||||||
let mut buffer = String::new();
|
|
||||||
println!("LED number(s) to display?");
|
|
||||||
std::io::stdin().read_line(&mut buffer)?;
|
|
||||||
|
|
||||||
let mut resultant = 0;
|
|
||||||
let original = raw_io::write_read(Setting::LEDStatus as _)?;
|
|
||||||
for word in buffer.split(' ') {
|
|
||||||
let trimmed_word = word.trim();
|
|
||||||
if !trimmed_word.is_empty() {
|
|
||||||
let value: u8 = trimmed_word.parse().expect("Invalid u8 number");
|
|
||||||
let actual = 0x80 | value;
|
|
||||||
raw_io::wait_ready_for_write()?;
|
|
||||||
raw_io::write2(Setting::LEDStatus as _, actual)?;
|
|
||||||
println!("Wrote {actual:#b} to LED byte");
|
|
||||||
resultant |= actual;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
println!("Effectively wrote {resultant:#b} to LED byte");
|
|
||||||
|
|
||||||
println!("Press enter to return to normal");
|
|
||||||
std::io::stdin().read_line(&mut buffer)?;
|
|
||||||
raw_io::write2(Setting::LEDStatus as _, original)?;
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
#[allow(dead_code)]
|
|
||||||
fn breath_specify_experiment_test() -> Result<(), Error> {
|
|
||||||
let mut buffer = String::new();
|
|
||||||
println!("LED number(s) to display?");
|
|
||||||
std::io::stdin().read_line(&mut buffer)?;
|
|
||||||
|
|
||||||
for word in buffer.split(' ') {
|
|
||||||
let trimmed_word = word.trim();
|
|
||||||
if !trimmed_word.is_empty() {
|
|
||||||
let value: u8 = trimmed_word.parse().expect("Invalid u8 number");
|
|
||||||
let actual = 0x20 | value;
|
|
||||||
raw_io::wait_ready_for_write()?;
|
|
||||||
raw_io::write2(0x63, actual)?;
|
|
||||||
println!("Wrote {actual:#b} to LED breathing byte");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
println!("Press enter to return to normal");
|
|
||||||
std::io::stdin().read_line(&mut buffer)?;
|
|
||||||
raw_io::write2(0x63, 0)?;
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
#[allow(dead_code)]
|
|
||||||
fn unmapped_ports_experiment_test() -> Result<(), Error> {
|
|
||||||
let sleep_dur = std::time::Duration::from_millis(10000);
|
|
||||||
let value = 0xaa;
|
|
||||||
for addr in 0x63..0x64 {
|
|
||||||
//raw_io::wait_ready_for_read()?;
|
|
||||||
//let read = raw_io::write_read(addr)?;
|
|
||||||
raw_io::wait_ready_for_write()?;
|
|
||||||
raw_io::write2(addr, value)?;
|
|
||||||
println!("wrote {value:#b} for {addr:#x} port");
|
|
||||||
std::thread::sleep(sleep_dur);
|
|
||||||
}
|
|
||||||
//raw_io::write2(Setting::LEDStatus as _, 0)?;
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
#[allow(dead_code)]
|
|
||||||
fn write_specify_experiment_test() -> Result<(), Error> {
|
|
||||||
let mut buffer = String::new();
|
|
||||||
println!("Register?");
|
|
||||||
std::io::stdin().read_line(&mut buffer)?;
|
|
||||||
let register: u8 = buffer.trim().parse().expect("Invalid u8 number");
|
|
||||||
buffer.clear();
|
|
||||||
|
|
||||||
println!("Value(s)?");
|
|
||||||
std::io::stdin().read_line(&mut buffer)?;
|
|
||||||
|
|
||||||
for word in buffer.split(' ') {
|
|
||||||
let trimmed_word = word.trim();
|
|
||||||
if !trimmed_word.is_empty() {
|
|
||||||
let value: u8 = trimmed_word.parse().expect("Invalid u8 number");
|
|
||||||
raw_io::wait_ready_for_write()?;
|
|
||||||
raw_io::write2(register, value)?;
|
|
||||||
println!("Wrote {value:#09b} to {register:#02x} register");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
println!("Press enter to clear register");
|
|
||||||
std::io::stdin().read_line(&mut buffer)?;
|
|
||||||
raw_io::write2(register, 0)?;
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,51 +0,0 @@
|
||||||
use std::fs::OpenOptions;
|
|
||||||
use std::io::{Error, Read, Seek, SeekFrom, Write};
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
pub fn write2(p0: u8, p1: u8) -> Result<usize, Error> {
|
|
||||||
write_to(0x6c, 0x81)?;
|
|
||||||
wait_ready_for_write()?;
|
|
||||||
let count0 = write_to(0x68, p0)?;
|
|
||||||
wait_ready_for_write()?;
|
|
||||||
let count1 = write_to(0x68, p1)?;
|
|
||||||
Ok(count0 + count1)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
pub fn write_read(p0: u8) -> Result<u8, Error> {
|
|
||||||
write_to(0x6c, 0x81)?;
|
|
||||||
wait_ready_for_write()?;
|
|
||||||
write_to(0x68, p0)?;
|
|
||||||
wait_ready_for_read()?;
|
|
||||||
read_from(0x68)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn write_to(location: u64, value: u8) -> Result<usize, Error> {
|
|
||||||
let mut file = OpenOptions::new().write(true).open("/dev/port")?;
|
|
||||||
file.seek(SeekFrom::Start(location))?;
|
|
||||||
file.write(&[value])
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn read_from(location: u64) -> Result<u8, Error> {
|
|
||||||
let mut file = OpenOptions::new().read(true).open("/dev/port")?;
|
|
||||||
file.seek(SeekFrom::Start(location))?;
|
|
||||||
let mut buffer = [0];
|
|
||||||
file.read(&mut buffer)?;
|
|
||||||
Ok(buffer[0])
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn wait_ready_for_write() -> Result<(), Error> {
|
|
||||||
let mut count = 0;
|
|
||||||
while count < 0x1ffff && (read_from(0x6c)? & 2) != 0 {
|
|
||||||
count += 1;
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn wait_ready_for_read() -> Result<(), Error> {
|
|
||||||
let mut count = 0;
|
|
||||||
while count < 0x1ffff && (read_from(0x6c)? & 1) == 0 {
|
|
||||||
count += 1;
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
}
|
|
|
@ -6,7 +6,7 @@ use sysfuss::capability::attributes;
|
||||||
|
|
||||||
use limits_core::json_v2::GenericBatteryLimit;
|
use limits_core::json_v2::GenericBatteryLimit;
|
||||||
|
|
||||||
use sd_led::ChargeMode;
|
use smokepatio::ec::ChargeMode;
|
||||||
use crate::api::RangeLimit;
|
use crate::api::RangeLimit;
|
||||||
use crate::persist::{BatteryEventJson, BatteryJson};
|
use crate::persist::{BatteryEventJson, BatteryJson};
|
||||||
use crate::settings::{TBattery, ProviderBuilder};
|
use crate::settings::{TBattery, ProviderBuilder};
|
||||||
|
@ -131,7 +131,7 @@ impl EventInstruction {
|
||||||
|
|
||||||
fn set_charge_mode(&self) -> Result<(), SettingError> {
|
fn set_charge_mode(&self) -> Result<(), SettingError> {
|
||||||
if let Some(charge_mode) = self.charge_mode {
|
if let Some(charge_mode) = self.charge_mode {
|
||||||
sd_led::set(sd_led::Setting::ChargeMode, charge_mode as _)
|
smokepatio::ec::set(smokepatio::ec::Setting::ChargeMode, charge_mode as _)
|
||||||
.map_err(|e| SettingError {
|
.map_err(|e| SettingError {
|
||||||
msg: format!("Failed to set charge mode: {}", e),
|
msg: format!("Failed to set charge mode: {}", e),
|
||||||
setting: crate::settings::SettingVariant::Battery,
|
setting: crate::settings::SettingVariant::Battery,
|
||||||
|
@ -329,7 +329,7 @@ impl Battery {
|
||||||
fn set_charge_mode(&mut self) -> Result<(), SettingError> {
|
fn set_charge_mode(&mut self) -> Result<(), SettingError> {
|
||||||
if let Some(charge_mode) = self.charge_mode {
|
if let Some(charge_mode) = self.charge_mode {
|
||||||
self.state.charge_mode_set = true;
|
self.state.charge_mode_set = true;
|
||||||
sd_led::set(sd_led::Setting::ChargeMode, charge_mode as _)
|
smokepatio::ec::set(smokepatio::ec::Setting::ChargeMode, charge_mode as _)
|
||||||
.map_err(|e| SettingError {
|
.map_err(|e| SettingError {
|
||||||
msg: format!("Failed to set charge mode: {}", e),
|
msg: format!("Failed to set charge mode: {}", e),
|
||||||
setting: crate::settings::SettingVariant::Battery,
|
setting: crate::settings::SettingVariant::Battery,
|
||||||
|
@ -337,7 +337,7 @@ impl Battery {
|
||||||
.map(|_| ())
|
.map(|_| ())
|
||||||
} else if self.state.charge_mode_set {
|
} else if self.state.charge_mode_set {
|
||||||
self.state.charge_mode_set = false;
|
self.state.charge_mode_set = false;
|
||||||
sd_led::set(sd_led::Setting::ChargeMode, ChargeMode::Normal as _)
|
smokepatio::ec::set(smokepatio::ec::Setting::ChargeMode, ChargeMode::Normal as _)
|
||||||
.map_err(|e| SettingError {
|
.map_err(|e| SettingError {
|
||||||
msg: format!("Failed to set charge mode: {}", e),
|
msg: format!("Failed to set charge mode: {}", e),
|
||||||
setting: crate::settings::SettingVariant::Battery,
|
setting: crate::settings::SettingVariant::Battery,
|
||||||
|
|
|
@ -27,20 +27,15 @@ const THINGS: &[u8] = &[
|
||||||
const TIME_UNIT: std::time::Duration = std::time::Duration::from_millis(200);
|
const TIME_UNIT: std::time::Duration = std::time::Duration::from_millis(200);
|
||||||
|
|
||||||
pub fn flash_led() {
|
pub fn flash_led() {
|
||||||
let led_status = sd_led::Setting::LEDStatus;
|
|
||||||
let old_led_state = sd_led::raw_io::write_read(led_status as _)
|
|
||||||
.map_err(|e| log::error!("Failed to read LED status: {}", e));
|
|
||||||
for &code in THINGS {
|
for &code in THINGS {
|
||||||
let on = code != 0;
|
let on = code != 0;
|
||||||
if let Err(e) = sd_led::set_led(on, on, false) {
|
if let Err(e) = smokepatio::ec::led::constant::set(if on { smokepatio::ec::led::constant::Colour::White } else { smokepatio::ec::led::constant::Colour::Off }) {
|
||||||
log::error!("Thing err: {}", e);
|
log::error!("Thing err: {}", e);
|
||||||
}
|
}
|
||||||
std::thread::sleep(TIME_UNIT);
|
std::thread::sleep(TIME_UNIT);
|
||||||
}
|
}
|
||||||
if let Ok(old_led_state) = old_led_state {
|
log::debug!("Restoring LED state");
|
||||||
log::debug!("Restoring LED state to {:#02b}", old_led_state);
|
smokepatio::ec::led::constant::set(smokepatio::ec::led::constant::Colour::Off)
|
||||||
sd_led::raw_io::write2(led_status as _, old_led_state)
|
|
||||||
.map_err(|e| log::error!("Failed to restore LED status: {}", e))
|
.map_err(|e| log::error!("Failed to restore LED status: {}", e))
|
||||||
.unwrap();
|
.unwrap();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
4
main.py
4
main.py
|
@ -17,9 +17,9 @@ class Plugin:
|
||||||
env_proc["LD_LIBRARY_PATH"] += ":"+PARENT_DIR+"/bin"
|
env_proc["LD_LIBRARY_PATH"] += ":"+PARENT_DIR+"/bin"
|
||||||
else:
|
else:
|
||||||
env_proc["LD_LIBRARY_PATH"] = ":"+PARENT_DIR+"/bin"
|
env_proc["LD_LIBRARY_PATH"] = ":"+PARENT_DIR+"/bin"
|
||||||
self.backend_proc = subprocess.Popen(
|
'''self.backend_proc = subprocess.Popen(
|
||||||
[PARENT_DIR + "/bin/backend"],
|
[PARENT_DIR + "/bin/backend"],
|
||||||
env = env_proc)
|
env = env_proc)'''
|
||||||
while True:
|
while True:
|
||||||
await asyncio.sleep(1)
|
await asyncio.sleep(1)
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue