blob: 7d351dfa34caa345981439afe2e191e1b5af1441 [file] [log] [blame]
use crate::callback::CallbackSubscription;
use crate::callback::Consumer;
use crate::result::TockResult;
use crate::shared_memory::SharedMemory;
use crate::syscalls;
use core::marker::PhantomData;
pub const DRIVER_NUMBER: usize = 0x0005;
pub const BUFFER_SIZE: usize = 128;
mod command_nr {
pub const COUNT: usize = 0;
pub const START: usize = 1;
pub const START_REPEAT: usize = 2;
pub const START_REPEAT_BUFFER: usize = 3;
pub const START_REPEAT_BUFFER_ALT: usize = 4;
pub const STOP: usize = 5;
}
mod subscribe_nr {
pub const SUBSCRIBE_CALLBACK: usize = 0;
}
mod allow_nr {
pub const BUFFER: usize = 0;
pub const BUFFER_ALT: usize = 1;
}
#[non_exhaustive]
pub struct AdcDriverFactory;
impl AdcDriverFactory {
pub fn init_driver(&mut self) -> TockResult<Adc> {
let adc = Adc {
// num_channels
num_channels: syscalls::command(DRIVER_NUMBER, command_nr::COUNT, 0, 0)?,
lifetime: PhantomData,
};
Ok(adc)
}
}
pub struct AdcBuffer {
// TODO: make this generic if possible with the driver impl
buffer: [u8; BUFFER_SIZE],
}
impl Default for AdcBuffer {
fn default() -> Self {
AdcBuffer {
buffer: [0; BUFFER_SIZE],
}
}
}
pub struct Adc<'a> {
num_channels: usize,
lifetime: PhantomData<&'a ()>,
}
struct AdcEventConsumer;
impl<CB: FnMut(usize, usize)> Consumer<CB> for AdcEventConsumer {
fn consume(data: &mut CB, _: usize, channel: usize, value: usize) {
data(channel, value);
}
}
impl<'a> Adc<'a> {
pub fn init_buffer(&self, buffer: &'a mut AdcBuffer) -> TockResult<SharedMemory> {
syscalls::allow(DRIVER_NUMBER, allow_nr::BUFFER, &mut buffer.buffer).map_err(Into::into)
}
pub fn init_alt_buffer(&self, alt_buffer: &'a mut AdcBuffer) -> TockResult<SharedMemory> {
syscalls::allow(DRIVER_NUMBER, allow_nr::BUFFER_ALT, &mut alt_buffer.buffer)
.map_err(Into::into)
}
/// Return the number of available channels
pub fn count(&self) -> usize {
self.num_channels
}
pub fn subscribe<CB: FnMut(usize, usize)>(
&self,
callback: &'a mut CB,
) -> TockResult<CallbackSubscription> {
syscalls::subscribe::<AdcEventConsumer, _>(
DRIVER_NUMBER,
subscribe_nr::SUBSCRIBE_CALLBACK,
callback,
)
.map_err(Into::into)
}
/// Start a single sample of channel
pub fn sample(&self, channel: usize) -> TockResult<()> {
syscalls::command(DRIVER_NUMBER, command_nr::START, channel, 0)?;
Ok(())
}
/// Start continuous sampling of channel
pub fn sample_continuous(&self, channel: usize) -> TockResult<()> {
syscalls::command(DRIVER_NUMBER, command_nr::START_REPEAT, channel, 0)?;
Ok(())
}
/// Start continuous sampling to first buffer
pub fn sample_continuous_buffered(&self, channel: usize, frequency: usize) -> TockResult<()> {
syscalls::command(
DRIVER_NUMBER,
command_nr::START_REPEAT_BUFFER,
channel,
frequency,
)?;
Ok(())
}
/// Start continuous sampling to alternating buffer
pub fn sample_continuous_buffered_alt(
&self,
channel: usize,
frequency: usize,
) -> TockResult<()> {
syscalls::command(
DRIVER_NUMBER,
command_nr::START_REPEAT_BUFFER_ALT,
channel,
frequency,
)?;
Ok(())
}
/// Stop any started sampling operation
pub fn stop(&self) -> TockResult<()> {
syscalls::command(DRIVER_NUMBER, command_nr::STOP, 0, 0)?;
Ok(())
}
}
impl<'a> Drop for Adc<'a> {
fn drop(&mut self) {
let _ = self.stop();
}
}