embedded_hal/
lib.rs

1//! A Hardware Abstraction Layer (HAL) for embedded systems
2//!
3//! **NOTE** This HAL is still is active development. Expect the traits presented here to be
4//! tweaked, split or be replaced wholesale before being stabilized, i.e. before hitting the 1.0.0
5//! release. That being said there's a part of the HAL that's currently considered unproven and is
6//! hidden behind an "unproven" Cargo feature. This API is even more volatile and it's exempt from
7//! semver rules: it can change in a non-backward compatible fashion or even disappear in between
8//! patch releases.
9//!
10//! # Design goals
11//!
12//! The HAL
13//!
14//! - Must *erase* device specific details. Neither register, register blocks or magic values should
15//! appear in the API.
16//!
17//! - Must be generic *within* a device and *across* devices. The API to use a serial interface must
18//! be the same regardless of whether the implementation uses the USART1 or UART4 peripheral of a
19//! device or the UART0 peripheral of another device.
20//!
21//! - Where possible must *not* be tied to a specific asynchronous model. The API should be usable
22//! in blocking mode, with the `futures` model, with an async/await model or with a callback model.
23//! (cf. the [`nb`] crate)
24//!
25//! - Must be minimal, and thus easy to implement and zero cost, yet highly composable. People that
26//! want higher level abstraction should *prefer to use this HAL* rather than *re-implement*
27//! register manipulation code.
28//!
29//! - Serve as a foundation for building an ecosystem of platform agnostic drivers. Here driver
30//! means a library crate that lets a target platform interface an external device like a digital
31//! sensor or a wireless transceiver. The advantage of this system is that by writing the driver as
32//! a generic library on top of `embedded-hal` driver authors can support any number of target
33//! platforms (e.g. Cortex-M microcontrollers, AVR microcontrollers, embedded Linux, etc.). The
34//! advantage for application developers is that by adopting `embedded-hal` they can unlock all
35//! these drivers for their platform.
36//!
37//! # Out of scope
38//!
39//! - Initialization and configuration stuff like "ensure this serial interface and that SPI
40//! interface are not using the same pins". The HAL will focus on *doing I/O*.
41//!
42//! # Reference implementation
43//!
44//! The [`stm32f30x-hal`] crate contains a reference implementation of this HAL.
45//!
46//! [`stm32f30x-hal`]: https://crates.io/crates/stm32f30x-hal/0.1.0
47//!
48//! # Platform agnostic drivers
49//!
50//! You can find platform agnostic drivers built on top of `embedded-hal` on crates.io by [searching
51//! for the *embedded-hal* keyword](https://crates.io/keywords/embedded-hal).
52//!
53//! If you writing a platform agnostic driver yourself you are highly encouraged to [add the
54//! embedded-hal keyword](https://doc.rust-lang.org/cargo/reference/manifest.html#package-metadata)
55//! to your crate before publishing it!
56//!
57//! # Detailed design
58//!
59//! ## Traits
60//!
61//! The HAL is specified as traits to allow generic programming. These traits make use of the
62//! [`nb`][] crate (*please go read that crate documentation before continuing*) to abstract over
63//! the asynchronous model and to also provide a blocking operation mode.
64//!
65//! [`nb`]: https://crates.io/crates/nb
66//!
67//! Here's how a HAL trait may look like:
68//!
69//! ```
70//! extern crate nb;
71//!
72//! /// A serial interface
73//! pub trait Serial {
74//!     /// Error type associated to this serial interface
75//!     type Error;
76//!
77//!     /// Reads a single byte
78//!     fn read(&mut self) -> nb::Result<u8, Self::Error>;
79//!
80//!     /// Writes a single byte
81//!     fn write(&mut self, byte: u8) -> nb::Result<(), Self::Error>;
82//! }
83//! ```
84//!
85//! The `nb::Result` enum is used to add a [`WouldBlock`] variant to the errors
86//! of the serial interface. As explained in the documentation of the `nb` crate this single API,
87//! when paired with the macros in the `nb` crate, can operate in a blocking manner, or in a
88//! non-blocking manner compatible with `futures` and with the `await!` operator.
89//!
90//! [`WouldBlock`]: https://docs.rs/nb/0.1.0/nb/enum.Error.html
91//!
92//! Some traits, like the one shown below, may expose possibly blocking APIs that can't fail. In
93//! those cases `nb::Result<_, Void>` is used.
94//!
95//! ```
96//! extern crate nb;
97//! extern crate void;
98//!
99//! use void::Void;
100//!
101//! /// A count down timer
102//! pub trait CountDown {
103//!     // ..
104//!
105//!     /// "waits" until the count down is over
106//!     fn wait(&mut self) -> nb::Result<(), Void>;
107//! }
108//!
109//! # fn main() {}
110//! ```
111//!
112//! ## Suggested implementation
113//!
114//! The HAL traits should be implemented for device crates generated via [`svd2rust`] to maximize
115//! code reuse.
116//!
117//! [`svd2rust`]: https://crates.io/crates/svd2rust
118//!
119//! Shown below is an implementation of some of the HAL traits for the [`stm32f30x`] crate. This
120//! single implementation will work for *any* microcontroller in the STM32F30x family.
121//!
122//! [`stm32f30x`]: https://crates.io/crates/stm32f30x
123//!
124//! ```
125//! // crate: stm32f30x-hal
126//! // An implementation of the `embedded-hal` traits for STM32F30x microcontrollers
127//!
128//! extern crate embedded_hal as hal;
129//! extern crate nb;
130//!
131//! // device crate
132//! extern crate stm32f30x;
133//!
134//! use stm32f30x::USART1;
135//!
136//! /// A serial interface
137//! // NOTE generic over the USART peripheral
138//! pub struct Serial<USART> { usart: USART }
139//!
140//! // convenience type alias
141//! pub type Serial1 = Serial<USART1>;
142//!
143//! /// Serial interface error
144//! pub enum Error {
145//!     /// Buffer overrun
146//!     Overrun,
147//!     // omitted: other error variants
148//! }
149//!
150//! impl hal::serial::Read<u8> for Serial<USART1> {
151//!     type Error = Error;
152//!
153//!     fn read(&mut self) -> nb::Result<u8, Error> {
154//!         // read the status register
155//!         let isr = self.usart.isr.read();
156//!
157//!         if isr.ore().bit_is_set() {
158//!             // Error: Buffer overrun
159//!             Err(nb::Error::Other(Error::Overrun))
160//!         }
161//!         // omitted: checks for other errors
162//!         else if isr.rxne().bit_is_set() {
163//!             // Data available: read the data register
164//!             Ok(self.usart.rdr.read().bits() as u8)
165//!         } else {
166//!             // No data available yet
167//!             Err(nb::Error::WouldBlock)
168//!         }
169//!     }
170//! }
171//!
172//! impl hal::serial::Write<u8> for Serial<USART1> {
173//!     type Error = Error;
174//!
175//!     fn write(&mut self, byte: u8) -> nb::Result<(), Error> {
176//!         // Similar to the `read` implementation
177//!         # Ok(())
178//!     }
179//!
180//!     fn flush(&mut self) -> nb::Result<(), Error> {
181//!         // Similar to the `read` implementation
182//!         # Ok(())
183//!     }
184//! }
185//!
186//! # fn main() {}
187//! ```
188//!
189//! ## Intended usage
190//!
191//! Thanks to the [`nb`] crate the HAL API can be used in a blocking manner,
192//! with `futures` or with the `await` operator using the [`block!`],
193//! [`try_nb!`] and [`await!`] macros respectively.
194//!
195//! [`block!`]: https://docs.rs/nb/0.1.0/nb/macro.block.html
196//! [`try_nb!`]: https://docs.rs/nb/0.1.0/nb/index.html#how-to-use-this-crate
197//! [`await!`]: https://docs.rs/nb/0.1.0/nb/index.html#how-to-use-this-crate
198//!
199//! ### Blocking mode
200//!
201//! An example of sending a string over the serial interface in a blocking
202//! fashion:
203//!
204//! ```
205//! extern crate embedded_hal;
206//! #[macro_use(block)]
207//! extern crate nb;
208//!
209//! use stm32f30x_hal::Serial1;
210//! use embedded_hal::serial::Write;
211//!
212//! # fn main() {
213//! let mut serial: Serial1 = {
214//!     // ..
215//! #   Serial1
216//! };
217//!
218//! for byte in b"Hello, world!" {
219//!     // NOTE `block!` blocks until `serial.write()` completes and returns
220//!     // `Result<(), Error>`
221//!     block!(serial.write(*byte)).unwrap();
222//! }
223//! # }
224//!
225//! # mod stm32f30x_hal {
226//! #     extern crate void;
227//! #     use self::void::Void;
228//! #     pub struct Serial1;
229//! #     impl Serial1 {
230//! #         pub fn write(&mut self, _: u8) -> ::nb::Result<(), Void> {
231//! #             Ok(())
232//! #         }
233//! #     }
234//! # }
235//! ```
236//!
237//! ### `futures`
238//!
239//! An example of running two tasks concurrently. First task: blink an LED every
240//! second. Second task: loop back data over the serial interface.
241//!
242//! ```
243//! extern crate embedded_hal as hal;
244//! extern crate futures;
245//! extern crate void;
246//!
247//! #[macro_use(try_nb)]
248//! extern crate nb;
249//!
250//! use hal::prelude::*;
251//! use futures::{
252//!     future,
253//!     Async,
254//!     Future,
255//! };
256//! use futures::future::Loop;
257//! use stm32f30x_hal::{Led, Serial1, Timer6};
258//! use void::Void;
259//!
260//! /// `futures` version of `CountDown.wait`
261//! ///
262//! /// This returns a future that must be polled to completion
263//! fn wait<T>(mut timer: T) -> impl Future<Item = T, Error = Void>
264//! where
265//!     T: hal::timer::CountDown,
266//! {
267//!     let mut timer = Some(timer);
268//!     future::poll_fn(move || {
269//!         try_nb!(timer.as_mut().unwrap().wait());
270//!
271//!         Ok(Async::Ready(timer.take().unwrap()))
272//!     })
273//! }
274//!
275//! /// `futures` version of `Serial.read`
276//! ///
277//! /// This returns a future that must be polled to completion
278//! fn read<S>(mut serial: S) -> impl Future<Item = (S, u8), Error = S::Error>
279//! where
280//!     S: hal::serial::Read<u8>,
281//! {
282//!     let mut serial = Some(serial);
283//!     future::poll_fn(move || {
284//!         let byte = try_nb!(serial.as_mut().unwrap().read());
285//!
286//!         Ok(Async::Ready((serial.take().unwrap(), byte)))
287//!     })
288//! }
289//!
290//! /// `futures` version of `Serial.write`
291//! ///
292//! /// This returns a future that must be polled to completion
293//! fn write<S>(mut serial: S, byte: u8) -> impl Future<Item = S, Error = S::Error>
294//! where
295//!     S: hal::serial::Write<u8>,
296//! {
297//!     let mut serial = Some(serial);
298//!     future::poll_fn(move || {
299//!         try_nb!(serial.as_mut().unwrap().write(byte));
300//!
301//!         Ok(Async::Ready(serial.take().unwrap()))
302//!     })
303//! }
304//!
305//! fn main() {
306//!     // HAL implementers
307//!     let timer: Timer6 = {
308//!         // ..
309//! #       Timer6
310//!     };
311//!     let serial: Serial1 = {
312//!         // ..
313//! #       Serial1
314//!     };
315//!     let led: Led = {
316//!         // ..
317//! #       Led
318//!     };
319//!
320//!     // Tasks
321//!     let mut blinky = future::loop_fn::<_, (), _, _>(
322//!         (led, timer, true),
323//!         |(mut led, mut timer, state)| {
324//!             wait(timer).map(move |timer| {
325//!                 if state {
326//!                     led.on();
327//!                 } else {
328//!                     led.off();
329//!                 }
330//!
331//!                 Loop::Continue((led, timer, !state))
332//!             })
333//!         });
334//!
335//!     let mut loopback = future::loop_fn::<_, (), _, _>(serial, |mut serial| {
336//!         read(serial).and_then(|(serial, byte)| {
337//!             write(serial, byte)
338//!         }).map(|serial| {
339//!             Loop::Continue(serial)
340//!         })
341//!     });
342//!
343//!     // Event loop
344//!     loop {
345//!         blinky.poll().unwrap(); // NOTE(unwrap) E = Void
346//!         loopback.poll().unwrap();
347//! #       break;
348//!     }
349//! }
350//!
351//! # mod stm32f30x_hal {
352//! #     extern crate void;
353//! #     use self::void::Void;
354//! #     pub struct Timer6;
355//! #     impl ::hal::timer::CountDown for Timer6 {
356//! #         type Time = ();
357//! #
358//! #         fn start<T>(&mut self, _: T) where T: Into<()> {}
359//! #         fn wait(&mut self) -> ::nb::Result<(), Void> { Err(::nb::Error::WouldBlock) }
360//! #     }
361//! #
362//! #     pub struct Serial1;
363//! #     impl ::hal::serial::Read<u8> for Serial1 {
364//! #         type Error = Void;
365//! #         fn read(&mut self) -> ::nb::Result<u8, Void> { Err(::nb::Error::WouldBlock) }
366//! #     }
367//! #     impl ::hal::serial::Write<u8> for Serial1 {
368//! #         type Error = Void;
369//! #         fn flush(&mut self) -> ::nb::Result<(), Void> { Err(::nb::Error::WouldBlock) }
370//! #         fn write(&mut self, _: u8) -> ::nb::Result<(), Void> { Err(::nb::Error::WouldBlock) }
371//! #     }
372//! #
373//! #     pub struct Led;
374//! #     impl Led {
375//! #         pub fn off(&mut self) {}
376//! #         pub fn on(&mut self) {}
377//! #     }
378//! # }
379//! ```
380//!
381//! ### `await`
382//!
383//! Same example as above but using `await!` instead of `futures`.
384//!
385//! ```
386//! #![feature(generator_trait)]
387//! #![feature(generators)]
388//!
389//! extern crate embedded_hal as hal;
390//!
391//! #[macro_use(await)]
392//! extern crate nb;
393//!
394//! use std::ops::Generator;
395//! use std::pin::Pin;
396//!
397//! use hal::prelude::*;
398//! use stm32f30x_hal::{Led, Serial1, Timer6};
399//!
400//! fn main() {
401//!     // HAL implementers
402//!     let mut timer: Timer6 = {
403//!         // ..
404//! #       Timer6
405//!     };
406//!     let mut serial: Serial1 = {
407//!         // ..
408//! #       Serial1
409//!     };
410//!     let mut led: Led = {
411//!         // ..
412//! #       Led
413//!     };
414//!
415//!     // Tasks
416//!     let mut blinky = (move || {
417//!         let mut state = false;
418//!         loop {
419//!             // `await!` means "suspend / yield here" instead of "block until
420//!             // completion"
421//!             await!(timer.wait()).unwrap(); // NOTE(unwrap) E = Void
422//!
423//!             state = !state;
424//!
425//!             if state {
426//!                 led.on();
427//!             } else {
428//!                 led.off();
429//!             }
430//!         }
431//!     });
432//!
433//!     let mut loopback = (move || {
434//!         loop {
435//!             let byte = await!(serial.read()).unwrap();
436//!             await!(serial.write(byte)).unwrap();
437//!         }
438//!     });
439//!
440//!     // Event loop
441//!     loop {
442//!         Pin::new(&mut blinky).resume(());
443//!         Pin::new(&mut loopback).resume(());
444//!         # break;
445//!     }
446//! }
447//!
448//! # mod stm32f30x_hal {
449//! #   extern crate void;
450//! #   use self::void::Void;
451//! #   pub struct Serial1;
452//! #   impl Serial1 {
453//! #       pub fn read(&mut self) -> ::nb::Result<u8, Void> { Err(::nb::Error::WouldBlock) }
454//! #       pub fn write(&mut self, _: u8) -> ::nb::Result<(), Void> { Err(::nb::Error::WouldBlock) }
455//! #   }
456//! #   pub struct Timer6;
457//! #   impl Timer6 {
458//! #       pub fn wait(&mut self) -> ::nb::Result<(), Void> { Err(::nb::Error::WouldBlock) }
459//! #   }
460//! #   pub struct Led;
461//! #   impl Led {
462//! #       pub fn off(&mut self) {}
463//! #       pub fn on(&mut self) {}
464//! #   }
465//! # }
466//! ```
467//!
468//! ## Generic programming and higher level abstractions
469//!
470//! The core of the HAL has been kept minimal on purpose to encourage building **generic** higher
471//! level abstractions on top of it. Some higher level abstractions that pick an asynchronous model
472//! or that have blocking behavior and that are deemed useful to build other abstractions can be
473//! found in the `blocking` module and, in the future, in the `futures` and `async` modules.
474//!
475//! Some examples:
476//!
477//! **NOTE** All the functions shown below could have been written as trait
478//! methods with default implementation to allow specialization, but they have
479//! been written as functions to keep things simple.
480//!
481//! - Write a whole buffer to a serial device in blocking a fashion.
482//!
483//! ```
484//! extern crate embedded_hal as hal;
485//! #[macro_use(block)]
486//! extern crate nb;
487//!
488//! use hal::prelude::*;
489//!
490//! fn write_all<S>(serial: &mut S, buffer: &[u8]) -> Result<(), S::Error>
491//! where
492//!     S: hal::serial::Write<u8>
493//! {
494//!     for &byte in buffer {
495//!         block!(serial.write(byte))?;
496//!     }
497//!
498//!     Ok(())
499//! }
500//!
501//! # fn main() {}
502//! ```
503//!
504//! - Blocking serial read with timeout
505//!
506//! ```
507//! extern crate embedded_hal as hal;
508//! extern crate nb;
509//!
510//! use hal::prelude::*;
511//!
512//! enum Error<E> {
513//!     /// Serial interface error
514//!     Serial(E),
515//!     TimedOut,
516//! }
517//!
518//! fn read_with_timeout<S, T>(
519//!     serial: &mut S,
520//!     timer: &mut T,
521//!     timeout: T::Time,
522//! ) -> Result<u8, Error<S::Error>>
523//! where
524//!     T: hal::timer::CountDown,
525//!     S: hal::serial::Read<u8>,
526//! {
527//!     timer.start(timeout);
528//!
529//!     loop {
530//!         match serial.read() {
531//!             // raise error
532//!             Err(nb::Error::Other(e)) => return Err(Error::Serial(e)),
533//!             Err(nb::Error::WouldBlock) => {
534//!                 // no data available yet, check the timer below
535//!             },
536//!             Ok(byte) => return Ok(byte),
537//!         }
538//!
539//!         match timer.wait() {
540//!             Err(nb::Error::Other(e)) => {
541//!                 // The error type specified by `timer.wait()` is `!`, which
542//!                 // means no error can actually occur. The Rust compiler
543//!                 // still forces us to provide this match arm, though.
544//!                 unreachable!()
545//!             },
546//!             // no timeout yet, try again
547//!             Err(nb::Error::WouldBlock) => continue,
548//!             Ok(()) => return Err(Error::TimedOut),
549//!         }
550//!     }
551//! }
552//!
553//! # fn main() {}
554//! ```
555//!
556//! - Asynchronous SPI transfer
557//!
558//! ```
559//! #![feature(conservative_impl_trait)]
560//! #![feature(generators)]
561//! #![feature(generator_trait)]
562//!
563//! extern crate embedded_hal as hal;
564//! #[macro_use(await)]
565//! extern crate nb;
566//!
567//! use std::ops::Generator;
568//!
569//! /// Transfers a byte buffer of size N
570//! ///
571//! /// Returns the same byte buffer but filled with the data received from the
572//! /// slave device
573//! fn transfer<S, B>(
574//!     mut spi: S,
575//!     mut buffer: [u8; 16], // NOTE this should be generic over the size of the array
576//! ) -> impl Generator<Return = Result<(S, [u8; 16]), S::Error>, Yield = ()>
577//! where
578//!     S: hal::spi::FullDuplex<u8>,
579//! {
580//!     move || {
581//!         let n = buffer.len();
582//!         for i in 0..n {
583//!             await!(spi.send(buffer[i]))?;
584//!             buffer[i] = await!(spi.read())?;
585//!         }
586//!
587//!         Ok((spi, buffer))
588//!     }
589//! }
590//!
591//! # fn main() {}
592//! ```
593//!
594//! - Buffered serial interface with periodic flushing in interrupt handler
595//!
596//! ```
597//! extern crate embedded_hal as hal;
598//! extern crate nb;
599//! extern crate void;
600//!
601//! use hal::prelude::*;
602//! use void::Void;
603//!
604//! fn flush<S>(serial: &mut S, cb: &mut CircularBuffer)
605//! where
606//!     S: hal::serial::Write<u8, Error = Void>,
607//! {
608//!     loop {
609//!         if let Some(byte) = cb.peek() {
610//!             match serial.write(*byte) {
611//!                 Err(nb::Error::Other(_)) => unreachable!(),
612//!                 Err(nb::Error::WouldBlock) => return,
613//!                 Ok(()) => {}, // keep flushing data
614//!             }
615//!         }
616//!
617//!         cb.pop();
618//!     }
619//! }
620//!
621//! // The stuff below could be in some other crate
622//!
623//! /// Global singleton
624//! pub struct BufferedSerial1;
625//!
626//! // NOTE private
627//! static BUFFER1: Mutex<CircularBuffer> = {
628//!     // ..
629//! #   Mutex(CircularBuffer)
630//! };
631//! static SERIAL1: Mutex<Serial1> = {
632//!     // ..
633//! #   Mutex(Serial1)
634//! };
635//!
636//! impl BufferedSerial1 {
637//!     pub fn write(&self, byte: u8) {
638//!         self.write_all(&[byte])
639//!     }
640//!
641//!     pub fn write_all(&self, bytes: &[u8]) {
642//!         let mut buffer = BUFFER1.lock();
643//!         for byte in bytes {
644//!             buffer.push(*byte).expect("buffer overrun");
645//!         }
646//!         // omitted: pend / enable interrupt_handler
647//!     }
648//! }
649//!
650//! fn interrupt_handler() {
651//!     let mut serial = SERIAL1.lock();
652//!     let mut buffer = BUFFER1.lock();
653//!
654//!     flush(&mut *serial, &mut buffer);
655//! }
656//!
657//! # struct Mutex<T>(T);
658//! # impl<T> Mutex<T> {
659//! #     fn lock(&self) -> RefMut<T> { unimplemented!() }
660//! # }
661//! # struct RefMut<'a, T>(&'a mut T) where T: 'a;
662//! # impl<'a, T> ::std::ops::Deref for RefMut<'a, T> {
663//! #     type Target = T;
664//! #     fn deref(&self) -> &T { self.0 }
665//! # }
666//! # impl<'a, T> ::std::ops::DerefMut for RefMut<'a, T> {
667//! #     fn deref_mut(&mut self) -> &mut T { self.0 }
668//! # }
669//! # struct Serial1;
670//! # impl ::hal::serial::Write<u8> for Serial1 {
671//! #   type Error = Void;
672//! #   fn write(&mut self, _: u8) -> nb::Result<(), Void> { Err(::nb::Error::WouldBlock) }
673//! #   fn flush(&mut self) -> nb::Result<(), Void> { Err(::nb::Error::WouldBlock) }
674//! # }
675//! # struct CircularBuffer;
676//! # impl CircularBuffer {
677//! #   pub fn peek(&mut self) -> Option<&u8> { None }
678//! #   pub fn pop(&mut self) -> Option<u8> { None }
679//! #   pub fn push(&mut self, _: u8) -> Result<(), ()> { Ok(()) }
680//! # }
681//!
682//! # fn main() {}
683//! ```
684
685#![deny(missing_docs)]
686#![no_std]
687
688#[macro_use]
689extern crate nb;
690extern crate void;
691
692pub mod adc;
693pub mod blocking;
694pub mod can;
695pub mod digital;
696pub mod fmt;
697pub mod prelude;
698pub mod serial;
699pub mod spi;
700pub mod timer;
701pub mod watchdog;
702
703/// Input capture
704///
705/// *This trait is available if embedded-hal is built with the `"unproven"` feature.*
706///
707/// # Examples
708///
709/// You can use this interface to measure the period of (quasi) periodic signals
710/// / events
711///
712/// ```
713/// extern crate embedded_hal as hal;
714/// #[macro_use(block)]
715/// extern crate nb;
716///
717/// use hal::prelude::*;
718///
719/// fn main() {
720///     let mut capture: Capture1 = {
721///         // ..
722/// #       Capture1
723///     };
724///
725///     capture.set_resolution(1.ms());
726///
727///     let before = block!(capture.capture(Channel::_1)).unwrap();
728///     let after = block!(capture.capture(Channel::_1)).unwrap();
729///
730///     let period = after.wrapping_sub(before);
731///
732///     println!("Period: {} ms", period);
733/// }
734///
735/// # extern crate void;
736/// # use void::Void;
737/// # struct MilliSeconds(u32);
738/// # trait U32Ext { fn ms(self) -> MilliSeconds; }
739/// # impl U32Ext for u32 { fn ms(self) -> MilliSeconds { MilliSeconds(self) } }
740/// # struct Capture1;
741/// # enum Channel { _1 }
742/// # impl hal::Capture for Capture1 {
743/// #     type Capture = u16;
744/// #     type Channel = Channel;
745/// #     type Error = Void;
746/// #     type Time = MilliSeconds;
747/// #     fn capture(&mut self, _: Channel) -> ::nb::Result<u16, Void> { Ok(0) }
748/// #     fn disable(&mut self, _: Channel) { unimplemented!() }
749/// #     fn enable(&mut self, _: Channel) { unimplemented!() }
750/// #     fn get_resolution(&self) -> MilliSeconds { unimplemented!() }
751/// #     fn set_resolution<T>(&mut self, _: T) where T: Into<MilliSeconds> {}
752/// # }
753/// ```
754#[cfg(feature = "unproven")]
755// reason: pre-singletons API. With singletons a `CapturePin` (cf. `PwmPin`) trait seems more
756// appropriate
757pub trait Capture {
758    /// Enumeration of `Capture` errors
759    ///
760    /// Possible errors:
761    ///
762    /// - *overcapture*, the previous capture value was overwritten because it
763    ///   was not read in a timely manner
764    type Error;
765
766    /// Enumeration of channels that can be used with this `Capture` interface
767    ///
768    /// If your `Capture` interface has no channels you can use the type `()`
769    /// here
770    type Channel;
771
772    /// A time unit that can be converted into a human time unit (e.g. seconds)
773    type Time;
774
775    /// The type of the value returned by `capture`
776    type Capture;
777
778    /// "Waits" for a transition in the capture `channel` and returns the value
779    /// of counter at that instant
780    ///
781    /// NOTE that you must multiply the returned value by the *resolution* of
782    /// this `Capture` interface to get a human time unit (e.g. seconds)
783    fn capture(&mut self, channel: Self::Channel) -> nb::Result<Self::Capture, Self::Error>;
784
785    /// Disables a capture `channel`
786    fn disable(&mut self, channel: Self::Channel);
787
788    /// Enables a capture `channel`
789    fn enable(&mut self, channel: Self::Channel);
790
791    /// Returns the current resolution
792    fn get_resolution(&self) -> Self::Time;
793
794    /// Sets the resolution of the capture timer
795    fn set_resolution<R>(&mut self, resolution: R)
796    where
797        R: Into<Self::Time>;
798}
799
800/// Pulse Width Modulation
801///
802/// *This trait is available if embedded-hal is built with the `"unproven"` feature.*
803///
804/// # Examples
805///
806/// Use this interface to control the power output of some actuator
807///
808/// ```
809/// extern crate embedded_hal as hal;
810///
811/// use hal::prelude::*;
812///
813/// fn main() {
814///     let mut pwm: Pwm1 = {
815///         // ..
816/// #       Pwm1
817///     };
818///
819///     pwm.set_period(1.khz());
820///
821///     let max_duty = pwm.get_max_duty();
822///
823///     // brightest LED
824///     pwm.set_duty(Channel::_1, max_duty);
825///
826///     // dimmer LED
827///     pwm.set_duty(Channel::_2, max_duty / 4);
828/// }
829///
830/// # struct KiloHertz(u32);
831/// # trait U32Ext { fn khz(self) -> KiloHertz; }
832/// # impl U32Ext for u32 { fn khz(self) -> KiloHertz { KiloHertz(self) } }
833/// # enum Channel { _1, _2 }
834/// # struct Pwm1;
835/// # impl hal::Pwm for Pwm1 {
836/// #     type Channel = Channel;
837/// #     type Time = KiloHertz;
838/// #     type Duty = u16;
839/// #     fn disable(&mut self, _: Channel) { unimplemented!() }
840/// #     fn enable(&mut self, _: Channel) { unimplemented!() }
841/// #     fn get_duty(&self, _: Channel) -> u16 { unimplemented!() }
842/// #     fn get_max_duty(&self) -> u16 { 0 }
843/// #     fn set_duty(&mut self, _: Channel, _: u16) {}
844/// #     fn get_period(&self) -> KiloHertz { unimplemented!() }
845/// #     fn set_period<T>(&mut self, _: T) where T: Into<KiloHertz> {}
846/// # }
847/// ```
848#[cfg(feature = "unproven")]
849// reason: pre-singletons API. The `PwmPin` trait seems more useful because it models independent
850// PWM channels. Here a certain number of channels are multiplexed in a single implementer.
851pub trait Pwm {
852    /// Enumeration of channels that can be used with this `Pwm` interface
853    ///
854    /// If your `Pwm` interface has no channels you can use the type `()`
855    /// here
856    type Channel;
857
858    /// A time unit that can be converted into a human time unit (e.g. seconds)
859    type Time;
860
861    /// Type for the `duty` methods
862    ///
863    /// The implementer is free to choose a float / percentage representation
864    /// (e.g. `0.0 .. 1.0`) or an integer representation (e.g. `0 .. 65535`)
865    type Duty;
866
867    /// Disables a PWM `channel`
868    fn disable(&mut self, channel: Self::Channel);
869
870    /// Enables a PWM `channel`
871    fn enable(&mut self, channel: Self::Channel);
872
873    /// Returns the current PWM period
874    fn get_period(&self) -> Self::Time;
875
876    /// Returns the current duty cycle
877    fn get_duty(&self, channel: Self::Channel) -> Self::Duty;
878
879    /// Returns the maximum duty cycle value
880    fn get_max_duty(&self) -> Self::Duty;
881
882    /// Sets a new duty cycle
883    fn set_duty(&mut self, channel: Self::Channel, duty: Self::Duty);
884
885    /// Sets a new PWM period
886    fn set_period<P>(&mut self, period: P)
887    where
888        P: Into<Self::Time>;
889}
890
891/// A single PWM channel / pin
892///
893/// See `Pwm` for details
894pub trait PwmPin {
895    /// Type for the `duty` methods
896    ///
897    /// The implementer is free to choose a float / percentage representation
898    /// (e.g. `0.0 .. 1.0`) or an integer representation (e.g. `0 .. 65535`)
899    type Duty;
900
901    /// Disables a PWM `channel`
902    fn disable(&mut self);
903
904    /// Enables a PWM `channel`
905    fn enable(&mut self);
906
907    /// Returns the current duty cycle
908    fn get_duty(&self) -> Self::Duty;
909
910    /// Returns the maximum duty cycle value
911    fn get_max_duty(&self) -> Self::Duty;
912
913    /// Sets a new duty cycle
914    fn set_duty(&mut self, duty: Self::Duty);
915}
916
917/// Quadrature encoder interface
918///
919/// *This trait is available if embedded-hal is built with the `"unproven"` feature.*
920///
921/// # Examples
922///
923/// You can use this interface to measure the speed of a motor
924///
925/// ```
926/// extern crate embedded_hal as hal;
927/// #[macro_use(block)]
928/// extern crate nb;
929///
930/// use hal::prelude::*;
931///
932/// fn main() {
933///     let mut qei: Qei1 = {
934///         // ..
935/// #       Qei1
936///     };
937///     let mut timer: Timer6 = {
938///         // ..
939/// #       Timer6
940///     };
941///
942///
943///     let before = qei.count();
944///     timer.start(1.s());
945///     block!(timer.wait());
946///     let after = qei.count();
947///
948///     let speed = after.wrapping_sub(before);
949///     println!("Speed: {} pulses per second", speed);
950/// }
951///
952/// # extern crate void;
953/// # use void::Void;
954/// # struct Seconds(u32);
955/// # trait U32Ext { fn s(self) -> Seconds; }
956/// # impl U32Ext for u32 { fn s(self) -> Seconds { Seconds(self) } }
957/// # struct Qei1;
958/// # impl hal::Qei for Qei1 {
959/// #     type Count = u16;
960/// #     fn count(&self) -> u16 { 0 }
961/// #     fn direction(&self) -> ::hal::Direction { unimplemented!() }
962/// # }
963/// # struct Timer6;
964/// # impl hal::timer::CountDown for Timer6 {
965/// #     type Time = Seconds;
966/// #     fn start<T>(&mut self, _: T) where T: Into<Seconds> {}
967/// #     fn wait(&mut self) -> ::nb::Result<(), Void> { Ok(()) }
968/// # }
969/// ```
970#[cfg(feature = "unproven")]
971// reason: needs to be re-evaluated in the new singletons world. At the very least this needs a
972// reference implementation
973pub trait Qei {
974    /// The type of the value returned by `count`
975    type Count;
976
977    /// Returns the current pulse count of the encoder
978    fn count(&self) -> Self::Count;
979
980    /// Returns the count direction
981    fn direction(&self) -> Direction;
982}
983
984/// Count direction
985///
986/// *This enumeration is available if embedded-hal is built with the `"unproven"` feature.*
987#[derive(Clone, Copy, Debug, Eq, PartialEq)]
988#[cfg(feature = "unproven")]
989// reason: part of the unproven `Qei` interface
990pub enum Direction {
991    /// 3, 2, 1
992    Downcounting,
993    /// 1, 2, 3
994    Upcounting,
995}
996
997mod private {
998    pub trait Sealed {}
999}