Update third_party/libtock-drivers to support OpenSK.

This commit is contained in:
Guillaume Endignoux
2020-07-10 10:11:07 +02:00
parent 5f1fcaedf5
commit 467121c962
9 changed files with 414 additions and 857 deletions

View File

@@ -1,7 +1,5 @@
use crate::result::OutOfRangeError;
use crate::result::TockResult;
use crate::syscalls::command;
use core::marker::PhantomData;
use crate::result::{OtherError, TockError, TockResult};
use libtock_core::syscalls;
const DRIVER_NUMBER: usize = 0x00002;
@@ -12,64 +10,70 @@ mod command_nr {
pub const TOGGLE: usize = 3;
}
#[non_exhaustive]
pub struct LedsDriverFactory;
pub struct Led {
led_num: usize,
}
impl LedsDriverFactory {
pub fn init_driver(&mut self) -> TockResult<LedsDriver> {
let driver = LedsDriver {
num_leds: command(DRIVER_NUMBER, command_nr::COUNT, 0, 0)?,
lifetime: PhantomData,
};
Ok(driver)
pub fn count() -> TockResult<usize> {
let count = syscalls::command(DRIVER_NUMBER, command_nr::COUNT, 0, 0)?;
Ok(count)
}
pub fn get(led_num: usize) -> TockResult<Led> {
let led_count = count()?;
if led_num < led_count {
Ok(Led { led_num })
} else {
Err(TockError::Other(OtherError::OutOfRange))
}
}
pub struct LedsDriver<'a> {
num_leds: usize,
lifetime: PhantomData<&'a ()>,
pub fn all() -> TockResult<LedIter> {
let led_count = count()?;
Ok(LedIter {
curr_led: 0,
led_count,
})
}
impl<'a> LedsDriver<'a> {
pub fn num_leds(&self) -> usize {
self.num_leds
}
pub fn leds(&self) -> Leds {
Leds {
num_leds: self.num_leds,
curr_led: 0,
lifetime: PhantomData,
}
}
/// Returns the led at 0-based index `led_num`
pub fn get(&self, led_num: usize) -> Result<Led, OutOfRangeError> {
if led_num < self.num_leds {
Ok(Led {
led_num,
lifetime: PhantomData,
})
impl Led {
pub fn set_state(&self, state: bool) -> TockResult<()> {
if state {
self.on()
} else {
Err(OutOfRangeError)
self.off()
}
}
pub fn on(&self) -> TockResult<()> {
syscalls::command(DRIVER_NUMBER, command_nr::ON, self.led_num, 0)?;
Ok(())
}
pub fn off(&self) -> TockResult<()> {
syscalls::command(DRIVER_NUMBER, command_nr::OFF, self.led_num, 0)?;
Ok(())
}
pub fn toggle(&self) -> TockResult<()> {
syscalls::command(DRIVER_NUMBER, command_nr::TOGGLE, self.led_num, 0)?;
Ok(())
}
}
pub struct Leds<'a> {
num_leds: usize,
#[derive(Copy, Clone)]
pub struct LedIter {
curr_led: usize,
lifetime: PhantomData<&'a ()>,
led_count: usize,
}
impl<'a> Iterator for Leds<'a> {
type Item = Led<'a>;
impl Iterator for LedIter {
type Item = Led;
fn next(&mut self) -> Option<Self::Item> {
if self.curr_led < self.num_leds {
if self.curr_led < self.led_count {
let item = Led {
led_num: self.curr_led,
lifetime: PhantomData,
};
self.curr_led += 1;
Some(item)
@@ -78,84 +82,3 @@ impl<'a> Iterator for Leds<'a> {
}
}
}
pub struct Led<'a> {
led_num: usize,
lifetime: PhantomData<&'a ()>,
}
impl<'a> Led<'a> {
pub fn led_num(&self) -> usize {
self.led_num
}
pub fn set(&self, state: impl Into<LedState>) -> TockResult<()> {
match state.into() {
LedState::On => self.on(),
LedState::Off => self.off(),
}
}
pub fn on(&self) -> TockResult<()> {
command(DRIVER_NUMBER, command_nr::ON, self.led_num, 0)?;
Ok(())
}
pub fn off(&self) -> TockResult<()> {
command(DRIVER_NUMBER, command_nr::OFF, self.led_num, 0)?;
Ok(())
}
pub fn toggle(&self) -> TockResult<()> {
command(DRIVER_NUMBER, command_nr::TOGGLE, self.led_num, 0)?;
Ok(())
}
}
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub enum LedState {
On,
Off,
}
impl From<bool> for LedState {
fn from(from_value: bool) -> Self {
if from_value {
LedState::On
} else {
LedState::Off
}
}
}
#[cfg(test)]
mod test {
use super::command_nr;
use super::DRIVER_NUMBER;
use crate::result::TockResult;
use crate::syscalls;
use crate::syscalls::raw::Event;
#[test]
pub fn single_led_can_be_enabled() {
let events = syscalls::raw::run_recording_events::<TockResult<()>, _>(|next_return| {
let mut drivers = unsafe { crate::drivers::retrieve_drivers_unsafe() };
next_return.set(1);
let leds_driver = drivers.leds.init_driver()?;
next_return.set(0);
let led = leds_driver.get(0)?;
led.on()?;
Ok(())
});
assert_eq!(
events,
vec![
Event::Command(DRIVER_NUMBER, command_nr::COUNT, 0, 0),
Event::Command(DRIVER_NUMBER, command_nr::ON, 0, 0),
]
);
}
}