///|
pub let page_vendor : Int = 0xFF00
///|
pub let page_sensor : Int = 0x0020
///|
pub let usage_accel : Int = 3
///|
pub let usage_gyro : Int = 9
///|
pub let usage_als : Int = 4
///|
pub let usage_lid : Int = 138
///|
pub let imu_report_len : Int = 22
///|
pub let imu_decimation : Int = 8
///|
pub let imu_data_offset : Int = 6
///|
pub let als_report_len : Int = 122
///|
pub let lid_report_len : Int = 3
///|
pub let report_buf_size : Int = 4096
///|
pub let report_interval_us : Int = 1000
///|
pub let ring_cap : Int = 8000
///|
pub let ring_entry : Int = 12
///|
pub let shm_header : Int = 16
///|
pub let shm_size : Int = shm_header + ring_cap * ring_entry
///|
pub let snap_header : Int = 8
///|
pub let accel_scale : Double = 65536.0
///|
pub let gyro_scale : Double = 65536.0
///|
pub let shm_name_accel : String = "vib_detect_shm"
///|
pub let shm_name_gyro : String = "vib_detect_shm_gyro"
///|
pub let shm_name_als : String = "vib_detect_shm_als"
///|
pub let shm_name_lid : String = "vib_detect_shm_lid"
///|
pub let als_size : Int = snap_header + als_report_len
///|
pub let lid_size : Int = snap_header + 4
///|
#borrow(report)
extern "c" fn parse_imu_x_ffi(report : Bytes) -> Int = "asa_parse_imu_x"
///|
#borrow(report)
extern "c" fn parse_imu_y_ffi(report : Bytes) -> Int = "asa_parse_imu_y"
///|
#borrow(report)
extern "c" fn parse_imu_z_ffi(report : Bytes) -> Int = "asa_parse_imu_z"
///|
#borrow(report)
extern "c" fn parse_lid_angle_ffi(report : Bytes) -> Float = "asa_parse_lid_angle"
///|
pub fn parse_imu_report(report : Bytes) -> (Int, Int, Int) {
(parse_imu_x_ffi(report), parse_imu_y_ffi(report), parse_imu_z_ffi(report))
}
///|
pub fn parse_lid_angle(report : Bytes) -> Float? {
let angle = parse_lid_angle_ffi(report)
if angle < 0.0 {
None
} else {
Some(angle)
}
}
///|
extern "c" fn get_euid_ffi() -> Int = "asa_geteuid"
///|
extern "c" fn run_sensord_ffi() -> Int = "asa_run_sensord"
///|
pub fn run_sensord() -> Unit raise {
guard get_euid_ffi() == 0 else {
fail("sensord requires root privileges, run with: sudo moon run cmd/main")
}
let rc = run_sensord_ffi()
guard rc == 0 else { fail("sensord failed with native exit code \{rc}") }
}
///|
extern "c" fn sleep_seconds_ffi(seconds : Int) -> Int = "asa_sleep_seconds"
///|
extern "c" fn start_sensord_background_ffi() -> Int = "asa_start_sensord_background"
///|
extern "c" fn stop_sensord_background_ffi(pid : Int) -> Int = "asa_stop_sensord_background"
///|
extern "c" fn read_accel_shm_ffi() -> Bytes = "asa_read_accel_shm"
///|
extern "c" fn read_gyro_shm_ffi() -> Bytes = "asa_read_gyro_shm"
///|
extern "c" fn read_als_shm_ffi() -> Bytes = "asa_read_als_shm"
///|
extern "c" fn lid_count_ffi() -> Int = "asa_lid_count"
///|
extern "c" fn lid_angle_latest_ffi() -> Float = "asa_lid_angle_latest"
///|
pub fn sleep_seconds(seconds : Int) -> Unit {
let _ = sleep_seconds_ffi(seconds)
}
///|
pub fn start_sensord_background() -> Int raise {
guard get_euid_ffi() == 0 else {
fail("sensord requires root privileges, run with: sudo moon run example")
}
let pid = start_sensord_background_ffi()
guard pid > 0 else { fail("failed to start sensord background process") }
pid
}
///|
pub fn stop_sensord_background(pid : Int) -> Unit {
let _ = stop_sensord_background_ffi(pid)
}
///|
fn ring_latest(raw : Bytes) -> (Int, Int, Int, Int)? {
match raw[:] {
[
u32le(write_idx),
u32le(total_lo),
u32le(total_hi),
u32le(_),
bytes(96000, ring),
..,
] => {
let total = if total_hi > 0U || total_lo > 0x7FFFFFFFU {
0x7FFFFFFF
} else {
total_lo.reinterpret_as_int()
}
if total <= 0 {
None
} else {
let latest_idx = (write_idx.reinterpret_as_int() + ring_cap - 1) %
ring_cap
let entry_off = latest_idx * ring_entry
match ring[entry_off:entry_off + ring_entry] {
[i32le(x), i32le(y), i32le(z)] => Some((total, x, y, z))
_ => None
}
}
}
_ => None
}
}
///|
pub fn accel_latest() -> (Int, Int, Int, Int)? {
ring_latest(read_accel_shm_ffi())
}
///|
pub fn gyro_latest() -> (Int, Int, Int, Int)? {
ring_latest(read_gyro_shm_ffi())
}
///|
pub fn als_latest_words() -> (Int, Int, Int, Int, Int)? {
let raw = read_als_shm_ffi()
match raw[:] {
[u32le(total), u32le(_), bytes(122, payload)] =>
if total == 0U {
None
} else {
match payload {
[i32le(w0), i32le(w1), i32le(w2), i32le(w3), ..] =>
Some((total.reinterpret_as_int(), w0, w1, w2, w3))
_ => None
}
}
_ => None
}
}
///|
pub fn lid_latest() -> (Int, Float)? {
let total = lid_count_ffi()
let angle = lid_angle_latest_ffi()
if total <= 0 || angle < 0.0 {
None
} else {
Some((total, angle))
}
}