capsules_core/virtualizers/
virtual_adc.rs1use kernel::collections::list::{List, ListLink, ListNode};
10use kernel::hil;
11use kernel::utilities::cells::OptionalCell;
12use kernel::ErrorCode;
13
14pub struct MuxAdc<'a, A: hil::adc::Adc<'a>> {
16 adc: &'a A,
17 devices: List<'a, AdcDevice<'a, A>>,
18 inflight: OptionalCell<&'a AdcDevice<'a, A>>,
19}
20
21impl<'a, A: hil::adc::Adc<'a>> hil::adc::Client for MuxAdc<'a, A> {
22 fn sample_ready(&self, sample: u16) {
23 self.inflight.take().map(|inflight| {
24 for node in self.devices.iter() {
25 if node.channel == inflight.channel {
26 node.operation.take().map(|operation| match operation {
27 Operation::OneSample => {
28 node.client.map(|client| client.sample_ready(sample))
29 }
30 });
31 }
32 }
33 });
34 self.do_next_op();
35 }
36}
37
38impl<'a, A: hil::adc::Adc<'a>> MuxAdc<'a, A> {
39 pub const fn new(adc: &'a A) -> MuxAdc<'a, A> {
40 MuxAdc {
41 adc,
42 devices: List::new(),
43 inflight: OptionalCell::empty(),
44 }
45 }
46
47 fn do_next_op(&self) {
48 if self.inflight.is_none() {
49 let mnode = self.devices.iter().find(|node| node.operation.is_some());
50 mnode.map(|node| {
51 let started = node.operation.map_or(false, |operation| match operation {
52 Operation::OneSample => {
53 let _ = self.adc.sample(&node.channel);
54 true
55 }
56 });
57 if started {
58 self.inflight.set(node);
59 } else {
60 self.do_next_op();
61 }
62 });
63 }
64 }
65
66 pub fn get_resolution_bits(&self) -> usize {
67 self.adc.get_resolution_bits()
68 }
69
70 pub fn get_voltage_reference_mv(&self) -> Option<usize> {
71 self.adc.get_voltage_reference_mv()
72 }
73}
74
75#[derive(Copy, Clone, PartialEq)]
76pub(crate) enum Operation {
77 OneSample,
78}
79
80pub struct AdcDevice<'a, A: hil::adc::Adc<'a>> {
82 mux: &'a MuxAdc<'a, A>,
83 channel: A::Channel,
84 operation: OptionalCell<Operation>,
85 next: ListLink<'a, AdcDevice<'a, A>>,
86 client: OptionalCell<&'a dyn hil::adc::Client>,
87}
88
89impl<'a, A: hil::adc::Adc<'a>> AdcDevice<'a, A> {
90 pub const fn new(mux: &'a MuxAdc<'a, A>, channel: A::Channel) -> AdcDevice<'a, A> {
91 let adc_user = AdcDevice {
92 mux,
93 channel,
94 operation: OptionalCell::empty(),
95 next: ListLink::empty(),
96 client: OptionalCell::empty(),
97 };
98 adc_user
99 }
100
101 pub fn add_to_mux(&'a self) {
102 self.mux.devices.push_head(self);
103 }
104}
105
106impl<'a, A: hil::adc::Adc<'a>> ListNode<'a, AdcDevice<'a, A>> for AdcDevice<'a, A> {
107 fn next(&'a self) -> &'a ListLink<'a, AdcDevice<'a, A>> {
108 &self.next
109 }
110}
111
112impl<'a, A: hil::adc::Adc<'a>> hil::adc::AdcChannel<'a> for AdcDevice<'a, A> {
113 fn sample(&self) -> Result<(), ErrorCode> {
114 self.operation.set(Operation::OneSample);
115 self.mux.do_next_op();
116 Ok(())
117 }
118
119 fn stop_sampling(&self) -> Result<(), ErrorCode> {
120 self.operation.clear();
121 self.mux.do_next_op();
122 Ok(())
123 }
124
125 fn sample_continuous(&self) -> Result<(), ErrorCode> {
126 Err(ErrorCode::NOSUPPORT)
127 }
128
129 fn get_resolution_bits(&self) -> usize {
130 self.mux.get_resolution_bits()
131 }
132
133 fn get_voltage_reference_mv(&self) -> Option<usize> {
134 self.mux.get_voltage_reference_mv()
135 }
136 fn set_client(&self, client: &'a dyn hil::adc::Client) {
137 self.client.set(client);
138 }
139}