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}