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