arduino_hal/
lib.rs

1#![no_std]
2#![feature(doc_cfg)]
3
4//! `arduino-hal`
5//! =============
6//! Common HAL (hardware abstraction layer) for Arduino boards.
7//!
8//! **Note**: This version of the documentation was built for
9#![cfg_attr(feature = "arduino-diecimila", doc = "**Arduino Diecimila**.")]
10#![cfg_attr(feature = "arduino-leonardo", doc = "**Arduino Leonardo**.")]
11#![cfg_attr(feature = "arduino-mega2560", doc = "**Arduino Mega 2560**.")]
12#![cfg_attr(feature = "arduino-mega1280", doc = "**Arduino Mega 1280**.")]
13#![cfg_attr(feature = "arduino-micro", doc = "**Arduino Micro**.")]
14#![cfg_attr(feature = "arduino-nano", doc = "**Arduino Nano**.")]
15#![cfg_attr(feature = "arduino-uno", doc = "**Arduino Uno**.")]
16#![cfg_attr(feature = "sparkfun-promicro", doc = "**SparkFun ProMicro**.")]
17#![cfg_attr(
18    feature = "sparkfun-promini-3v3",
19    doc = "**SparkFun ProMini 3.3V (8MHz)**."
20)]
21#![cfg_attr(
22    feature = "sparkfun-promini-5v",
23    doc = "**SparkFun ProMini 5V (16MHz)**."
24)]
25#![cfg_attr(feature = "trinket-pro", doc = "**Trinket Pro**.")]
26#![cfg_attr(feature = "trinket", doc = "**Trinket**.")]
27#![cfg_attr(feature = "nano168", doc = "**Nano clone (ATmega168)**.")]
28//! This means that only items which are available for this board are visible.  If you are using a
29//! different board, try building the documentation locally with
30//!
31//! ```text
32//! cargo doc --open
33//! ```
34//!
35//! in your project (where `arduino-hal` is included with the feature-flag for your board).
36//!
37//! ## Usage
38//! For setting up a new project, the [`avr-hal-template`](https://github.com/Rahix/avr-hal-template)
39//! is the recommended baseline.  Applications should be built ontop of the following skeleton:
40//!
41//! ```no_run
42//! #![no_std]
43//! #![no_main]
44//!
45//! use panic_halt as _;
46//!
47//! #[arduino_hal::entry]
48//! fn main() -> ! {
49//!     let dp = arduino_hal::Peripherals::take().unwrap();
50//!     let pins = arduino_hal::pins!(dp);
51//!
52//!     loop { }
53//! }
54//! ```
55//!
56//! For examples, please check the `avr-hal` examples: <https://github.com/Rahix/avr-hal/tree/main/examples>
57
58#[cfg(not(feature = "board-selected"))]
59compile_error!(
60    "This crate requires you to specify your target Arduino board as a feature.
61
62    Please select one of the following
63
64    * arduino-diecimila
65    * arduino-leonardo
66    * arduino-mega2560
67    * arduino-mega1280
68    * arduino-micro
69    * arduino-nano
70    * arduino-uno
71    * sparkfun-promicro
72    * sparkfun-promini-3v3
73    * sparkfun-promini-5v
74    * trinket-pro
75    * trinket
76    * nano168
77    "
78);
79
80/// Attribute to declare the entry point of the program
81///
82/// Exactly one entry point must be declared in the entire dependency tree.
83///
84/// ```
85/// #[arduino_hal::entry]
86/// fn main() -> ! {
87///     // ...
88/// }
89/// ```
90///
91/// The entry function must have a signature of `[unsafe] fn() -> !`.
92///
93/// This macro is a reexport of [`avr_device::entry`].  It is only available when the `rt`
94/// (runtime) feature is selected (it is by default).
95#[cfg(any(feature = "rt", doc))]
96#[doc(cfg(feature = "rt"))]
97pub use avr_device::entry;
98
99/// Reexport of the [`avr_device`](https://docs.rs/avr-device) crate.
100///
101/// This makes items such as `avr_device::interrupt` available without depending
102/// on `avr-device` directly and keeping its version in sync manually.
103pub use avr_device;
104
105#[doc(no_inline)]
106#[cfg(feature = "mcu-atmega")]
107pub use atmega_hal as hal;
108#[doc(no_inline)]
109#[cfg(feature = "mcu-atmega")]
110pub use atmega_hal::pac;
111
112#[doc(no_inline)]
113#[cfg(feature = "mcu-attiny")]
114pub use attiny_hal as hal;
115#[doc(no_inline)]
116#[cfg(feature = "mcu-attiny")]
117pub use attiny_hal::pac;
118
119#[doc(no_inline)]
120#[cfg(feature = "board-selected")]
121pub use hal::Peripherals;
122
123#[cfg(feature = "board-selected")]
124pub mod clock;
125#[cfg(feature = "board-selected")]
126pub use clock::default::DefaultClock;
127
128#[cfg(feature = "board-selected")]
129mod delay;
130#[cfg(feature = "board-selected")]
131pub use delay::{delay_ms, delay_ns, delay_us, Delay};
132
133#[cfg(feature = "board-selected")]
134pub mod port;
135
136#[doc(no_inline)]
137#[cfg(feature = "board-selected")]
138pub use port::Pins;
139
140/// Analog to Digital converter.
141#[cfg(feature = "mcu-atmega")]
142pub mod adc {
143    pub use crate::hal::adc::{
144        channel, AdcChannel, AdcOps, AdcSettings, Channel, ClockDivider, ReferenceVoltage,
145    };
146
147    /// Check the [`avr_hal_generic::adc::Adc`] documentation.
148    pub type Adc = crate::hal::Adc<crate::DefaultClock>;
149}
150#[doc(no_inline)]
151#[cfg(feature = "mcu-atmega")]
152pub use adc::Adc;
153
154/// I2C bus controller.
155#[cfg(feature = "mcu-atmega")]
156pub mod i2c {
157    pub use crate::hal::i2c::*;
158
159    pub type I2c = crate::hal::i2c::I2c<crate::DefaultClock>;
160}
161#[doc(no_inline)]
162#[cfg(feature = "mcu-atmega")]
163pub use i2c::I2c;
164
165/// SPI controller.
166#[cfg(feature = "mcu-atmega")]
167pub mod spi {
168    pub use crate::hal::spi::*;
169
170    pub type Spi = crate::hal::spi::Spi;
171}
172#[doc(no_inline)]
173#[cfg(feature = "mcu-atmega")]
174pub use spi::Spi;
175
176#[cfg(feature = "mcu-atmega")]
177pub mod usart {
178    pub use crate::hal::usart::{Baudrate, UsartOps};
179
180    pub type Usart<USART, RX, TX> = crate::hal::usart::Usart<USART, RX, TX, crate::DefaultClock>;
181    pub type UsartWriter<USART, RX, TX> =
182        crate::hal::usart::UsartWriter<USART, RX, TX, crate::DefaultClock>;
183    pub type UsartReader<USART, RX, TX> =
184        crate::hal::usart::UsartReader<USART, RX, TX, crate::DefaultClock>;
185}
186
187#[doc(no_inline)]
188#[cfg(feature = "mcu-atmega")]
189pub use usart::Usart;
190
191#[cfg(feature = "board-selected")]
192pub mod eeprom {
193    pub use crate::hal::eeprom::{Eeprom, EepromOps, OutOfBoundsError};
194}
195#[doc(no_inline)]
196#[cfg(feature = "board-selected")]
197pub use eeprom::Eeprom;
198
199#[cfg(feature = "board-selected")]
200pub mod simple_pwm {
201    #[cfg(feature = "mcu-atmega")]
202    pub use atmega_hal::simple_pwm::*;
203
204    #[cfg(feature = "mcu-attiny")]
205    pub use attiny_hal::simple_pwm::*;
206}
207
208#[cfg(feature = "mcu-atmega")]
209pub mod prelude {
210    pub use crate::hal::prelude::*;
211
212    cfg_if::cfg_if! {
213        if #[cfg(any(
214            feature = "arduino-diecimila",
215            feature = "arduino-mega2560",
216            feature = "arduino-mega1280",
217            feature = "arduino-uno"
218        ))] {
219            pub use crate::hal::usart::BaudrateArduinoExt as _;
220        } else {
221            pub use crate::hal::usart::BaudrateExt as _;
222        }
223    }
224}
225
226/// Convenience macro to instantiate the [`Pins`] struct for this board.
227///
228/// # Example
229/// ```no_run
230/// let dp = arduino_hal::Peripherals::take().unwrap();
231/// let pins = arduino_hal::pins!(dp);
232/// ```
233#[cfg(feature = "board-selected")]
234#[macro_export]
235macro_rules! pins {
236    ($p:expr) => {
237        $crate::Pins::with_mcu_pins($crate::hal::pins!($p))
238    };
239}
240
241/// Convenience macro to instantiate the [`Usart`] driver for this board.
242///
243/// # Example
244/// ```no_run
245/// let dp = arduino_hal::Peripherals::take().unwrap();
246/// let pins = arduino_hal::pins!(dp);
247/// let serial = arduino_hal::default_serial!(dp, pins, 57600);
248/// ```
249#[cfg(any(feature = "arduino-leonardo", feature = "arduino-micro"))]
250#[macro_export]
251macro_rules! default_serial {
252    ($p:expr, $pins:expr, $baud:expr) => {
253        $crate::Usart::new(
254            $p.USART1,
255            $pins.d0,
256            $pins.d1.into_output(),
257            $crate::hal::usart::BaudrateExt::into_baudrate($baud),
258        )
259    };
260}
261
262/// Convenience macro to instantiate the [`Usart`] driver for this board.
263///
264/// # Example
265/// ```no_run
266/// let dp = arduino_hal::Peripherals::take().unwrap();
267/// let pins = arduino_hal::pins!(dp);
268/// let serial = arduino_hal::default_serial!(dp, pins, 57600);
269/// ```
270#[cfg(any(feature = "sparkfun-promicro"))]
271#[macro_export]
272macro_rules! default_serial {
273    ($p:expr, $pins:expr, $baud:expr) => {
274        $crate::Usart::new(
275            $p.USART1,
276            $pins.rx,
277            $pins.tx.into_output(),
278            $crate::hal::usart::BaudrateExt::into_baudrate($baud),
279        )
280    };
281}
282
283/// Convenience macro to instantiate the [`Usart`] driver for this board.
284///
285/// # Example
286/// ```no_run
287/// let dp = arduino_hal::Peripherals::take().unwrap();
288/// let pins = arduino_hal::pins!(dp);
289/// let serial = arduino_hal::default_serial!(dp, pins, 57600);
290/// ```
291///
292/// This is equivalent to manually configuring the driver:
293///
294/// ```no_run
295/// let dp = arduino_hal::Peripherals::take().unwrap();
296/// let pins = arduino_hal::pins!(dp);
297/// let serial = arduino_hal::Usart::new(
298///     dp.USART1,
299///     pins.d0,
300///     pins.d1.into_output(),
301///     // See src/usart.rs for why some boards use the BaudrateArduinoExt trait
302///     // instead of BaudrateExt.
303///     arduino_hal::hal::usart::BaudrateArduinoExt::into_baudrate(57600),
304/// );
305/// ```
306#[cfg(any(
307    feature = "arduino-diecimila",
308    feature = "arduino-mega2560",
309    feature = "arduino-mega1280",
310    feature = "arduino-uno"
311))]
312#[macro_export]
313macro_rules! default_serial {
314    ($p:expr, $pins:expr, $baud:expr) => {
315        $crate::Usart::new(
316            $p.USART0,
317            $pins.d0,
318            $pins.d1.into_output(),
319            // See comment in avr-hal-generic/src/usart.rs for why these boards use the
320            // BaudrateArduinoExt trait instead of BaudrateExt
321            $crate::hal::usart::BaudrateArduinoExt::into_baudrate($baud),
322        )
323    };
324}
325
326/// Convenience macro to instantiate the [`Usart`] driver for this board.
327///
328/// # Example
329/// ```no_run
330/// let dp = arduino_hal::Peripherals::take().unwrap();
331/// let pins = arduino_hal::pins!(dp);
332/// let serial = arduino_hal::default_serial!(dp, pins, 57600);
333/// ```
334#[cfg(any(
335    feature = "arduino-nano",
336    feature = "nano168",
337    feature = "sparkfun-promini-3v3",
338    feature = "sparkfun-promini-5v",
339))]
340#[macro_export]
341macro_rules! default_serial {
342    ($p:expr, $pins:expr, $baud:expr) => {
343        $crate::Usart::new(
344            $p.USART0,
345            $pins.d0,
346            $pins.d1.into_output(),
347            $crate::hal::usart::BaudrateExt::into_baudrate($baud),
348        )
349    };
350}