Skip to content

Commit 60ec7b7

Browse files
Merge pull request #86 from FrameworkComputer/feb25-accel
Add accelerometer support
2 parents 4ff42b8 + 742f2c8 commit 60ec7b7

File tree

1 file changed

+105
-6
lines changed

1 file changed

+105
-6
lines changed

framework_lib/src/power.rs

Lines changed: 105 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -54,12 +54,13 @@ const EC_MEMMAP_BATT_SERIAL: u16 = 0x70; // Battery Serial Number String
5454
const EC_MEMMAP_BATT_TYPE: u16 = 0x78; // Battery Type String
5555
const EC_MEMMAP_ALS: u16 = 0x80; // ALS readings in lux (2 X 16 bits)
5656
// Unused 0x84 - 0x8f
57-
const _EC_MEMMAP_ACC_STATUS: u16 = 0x90; // Accelerometer status (8 bits )
58-
// Unused 0x91
59-
const _EC_MEMMAP_ACC_DATA: u16 = 0x92; // Accelerometers data 0x92 - 0x9f
60-
// 0x92: u16Lid Angle if available, LID_ANGLE_UNRELIABLE otherwise
61-
// 0x94 - 0x99: u161st Accelerometer
62-
// 0x9a - 0x9f: u162nd Accelerometer
57+
const EC_MEMMAP_ACC_STATUS: u16 = 0x90; // Accelerometer status (8 bits )
58+
// Unused 0x91
59+
const EC_MEMMAP_ACC_DATA: u16 = 0x92; // Accelerometers data 0x92 - 0x9f
60+
// 0x92: u16Lid Angle if available, LID_ANGLE_UNRELIABLE otherwise
61+
// 0x94 - 0x99: u161st Accelerometer
62+
// 0x9a - 0x9f: u162nd Accelerometer
63+
const LID_ANGLE_UNRELIABLE: u16 = 500;
6364
const _EC_MEMMAP_GYRO_DATA: u16 = 0xa0; // Gyroscope data 0xa0 - 0xa5
6465
// Unused 0xa6 - 0xdf
6566

@@ -163,6 +164,53 @@ impl From<PowerInfo> for ReducedPowerInfo {
163164
}
164165
}
165166

167+
#[derive(Debug, Clone, PartialEq, Eq)]
168+
pub struct AccelData {
169+
pub x: i16,
170+
pub y: i16,
171+
pub z: i16,
172+
}
173+
impl From<Vec<u8>> for AccelData {
174+
fn from(t: Vec<u8>) -> Self {
175+
Self {
176+
x: i16::from_le_bytes([t[0], t[1]]),
177+
y: i16::from_le_bytes([t[2], t[3]]),
178+
z: i16::from_le_bytes([t[4], t[5]]),
179+
}
180+
}
181+
}
182+
impl fmt::Display for AccelData {
183+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
184+
let quarter: f32 = 0xFFFF as f32 / 4.0;
185+
let x = (self.x as f32) / quarter;
186+
let y = (self.y as f32) / quarter;
187+
let z = (self.z as f32) / quarter;
188+
write!(f, "X: {:.2}G Y: {:.2}G, Z: {:.2}G", x, y, z)
189+
}
190+
}
191+
192+
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
193+
pub enum LidAngle {
194+
Angle(u16),
195+
Unreliable,
196+
}
197+
impl From<u16> for LidAngle {
198+
fn from(a: u16) -> Self {
199+
match a {
200+
LID_ANGLE_UNRELIABLE => Self::Unreliable,
201+
_ => Self::Angle(a),
202+
}
203+
}
204+
}
205+
impl fmt::Display for LidAngle {
206+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
207+
match self {
208+
Self::Angle(deg) => write!(f, "{}", deg),
209+
Self::Unreliable => write!(f, "Unreliable"),
210+
}
211+
}
212+
}
213+
166214
fn read_string(ec: &CrosEc, address: u16) -> String {
167215
let bytes = ec.read_memory(address, EC_MEMMAP_TEXT_MAX).unwrap();
168216
String::from_utf8_lossy(bytes.as_slice()).replace(['\0'], "")
@@ -197,9 +245,60 @@ pub fn get_als_reading(ec: &CrosEc) -> Option<u32> {
197245
Some(u32::from_le_bytes([als[0], als[1], als[2], als[3]]))
198246
}
199247

248+
pub fn get_accel_data(ec: &CrosEc) -> (AccelData, AccelData, LidAngle) {
249+
// bit 4 = busy
250+
// bit 7 = present
251+
// #define EC_MEMMAP_ACC_STATUS_SAMPLE_ID_MASK 0x0f
252+
let _acc_status = ec.read_memory(EC_MEMMAP_ACC_STATUS, 0x01).unwrap()[0];
253+
// While busy, keep reading
254+
255+
let lid_angle = ec.read_memory(EC_MEMMAP_ACC_DATA, 0x02).unwrap();
256+
let lid_angle = u16::from_le_bytes([lid_angle[0], lid_angle[1]]);
257+
let accel_1 = ec.read_memory(EC_MEMMAP_ACC_DATA + 2, 0x06).unwrap();
258+
let accel_2 = ec.read_memory(EC_MEMMAP_ACC_DATA + 8, 0x06).unwrap();
259+
260+
// TODO: Make sure we got a new sample
261+
// println!(" Status Bit: {} 0x{:X}", acc_status, acc_status);
262+
// println!(" Present: {}", (acc_status & 0x80) > 0);
263+
// println!(" Busy: {}", (acc_status & 0x8) > 0);
264+
(
265+
AccelData::from(accel_1),
266+
AccelData::from(accel_2),
267+
LidAngle::from(lid_angle),
268+
)
269+
}
270+
200271
pub fn print_sensors(ec: &CrosEc) {
201272
let als_int = get_als_reading(ec).unwrap();
202273
println!("ALS: {:>4} Lux", als_int);
274+
275+
// bit 4 = busy
276+
// bit 7 = present
277+
// #define EC_MEMMAP_ACC_STATUS_SAMPLE_ID_MASK 0x0f
278+
let acc_status = ec.read_memory(EC_MEMMAP_ACC_STATUS, 0x01).unwrap()[0];
279+
// While busy, keep reading
280+
281+
let lid_angle = ec.read_memory(EC_MEMMAP_ACC_DATA, 0x02).unwrap();
282+
let lid_angle = u16::from_le_bytes([lid_angle[0], lid_angle[1]]);
283+
let accel_1 = ec.read_memory(EC_MEMMAP_ACC_DATA + 2, 0x06).unwrap();
284+
let accel_2 = ec.read_memory(EC_MEMMAP_ACC_DATA + 8, 0x06).unwrap();
285+
286+
println!("Accelerometers:");
287+
println!(" Status Bit: {} 0x{:X}", acc_status, acc_status);
288+
println!(" Present: {}", (acc_status & 0x80) > 0);
289+
println!(" Busy: {}", (acc_status & 0x8) > 0);
290+
print!(" Lid Angle: ");
291+
if lid_angle == LID_ANGLE_UNRELIABLE {
292+
println!("Unreliable");
293+
} else {
294+
println!("{} Deg", lid_angle);
295+
}
296+
println!(" Sensor 1: {}", AccelData::from(accel_1));
297+
println!(" Sensor 2: {}", AccelData::from(accel_2));
298+
// Accelerometers
299+
// Lid Angle: 26 Deg
300+
// Sensor 1: 00.00 X 00.00 Y 00.00 Z
301+
// Sensor 2: 00.00 X 00.00 Y 00.00 Z
203302
}
204303

205304
pub fn print_thermal(ec: &CrosEc) {

0 commit comments

Comments
 (0)