Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add refactored support for Sparkfun Pro Micro #178

Merged
merged 8 commits into from
May 1, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ jobs:
name: arduino-leonardo
- type: board
name: arduino-mega2560
- type: board
name: sparkfun-promicro
- type: mcu
name: atmega1280
spec: atmega1280
Expand Down
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ members = [
"examples/arduino-mega2560",
"examples/arduino-nano",
"examples/arduino-uno",
"examples/sparkfun-promicro",
]
exclude = [
# The RAVEDUDE! Yeah!
Expand Down
1 change: 1 addition & 0 deletions arduino-hal/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ arduino-leonardo = ["mcu-atmega", "atmega-hal/atmega32u4", "board-selected"]
arduino-mega2560 = ["mcu-atmega", "atmega-hal/atmega2560", "board-selected"]
arduino-nano = ["mcu-atmega", "atmega-hal/atmega328p", "atmega-hal/enable-extra-adc", "board-selected"]
arduino-uno = ["mcu-atmega", "atmega-hal/atmega328p", "board-selected"]
sparkfun-promicro = ["mcu-atmega", "atmega-hal/atmega32u4", "board-selected"]

[dependencies]
cfg-if = "1"
Expand Down
1 change: 1 addition & 0 deletions arduino-hal/src/clock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ pub(crate) mod default {
feature = "arduino-mega2560",
feature = "arduino-nano",
feature = "arduino-uno",
feature = "sparkfun-promicro",
))]
pub type DefaultClock = avr_hal_generic::clock::MHz16;
}
3 changes: 2 additions & 1 deletion arduino-hal/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ compile_error!(
* arduino-mega2560
* arduino-nano
* arduino-uno
* sparkfun-promicro
"
);

Expand Down Expand Up @@ -109,7 +110,7 @@ macro_rules! pins {
};
}

#[cfg(any(feature = "arduino-leonardo"))]
#[cfg(any(feature = "arduino-leonardo", feature = "sparkfun-promicro"))]
#[macro_export]
macro_rules! default_serial {
($p:expr, $pins:expr, $baud:expr) => {
Expand Down
4 changes: 4 additions & 0 deletions arduino-hal/src/port/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,7 @@ pub use mega2560::*;
mod uno;
#[cfg(any(feature = "arduino-nano", feature = "arduino-uno"))]
pub use uno::*;
#[cfg(feature = "sparkfun-promicro")]
mod promicro;
#[cfg(feature = "sparkfun-promicro")]
pub use promicro::*;
98 changes: 98 additions & 0 deletions arduino-hal/src/port/promicro.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
pub use atmega_hal::port::mode;
pub use atmega_hal::port::Pin;

avr_hal_generic::renamed_pins! {
type Pin = Pin;

pub struct Pins from atmega_hal::Pins {
/// `D0` / `RX`
///
/// * `RX` (UART)
/// * `INT2`: External Interrupt
pub d0: atmega_hal::port::PD2 = pd2,
/// `D1` / `TX`
///
/// * `TX` (UART)
/// * `INT3`: External Interrupt
pub d1: atmega_hal::port::PD3 = pd3,
/// `D2` / `SDA`
///
/// * `SDA`: i2c/twi data
/// * `INT1`: External Interrupt
pub d2: atmega_hal::port::PD1 = pd1,
/// `D3` / `SCL`
///
/// * **PWM**: [atmega32u4_hal::timer::Timer0Pwm]
/// * `SCL`: i2c/twi clock
/// * `INT0`: External Interrupt
/// * `OC0B`: Output Compare Channel `B` for Timer/Counter0
pub d3: atmega_hal::port::PD0 = pd0,
/// `D4`
pub d4: atmega_hal::port::PD4 = pd4,
/// `D5`
///
/// * **PWM**: [atmega32u4_hal::timer::Timer3Pwm]
/// * `OC3A`: Output Compare Channel `A` for Timer/Counter3
/// * `#OC4A`: Inverted Output Compare Channel `A` for Timer/Counter4 (Not implemented)
pub d5: atmega_hal::port::PC6 = pc6,
/// `D6`
///
/// * **PWM**: [atmega32u4_hal::timer::Timer4Pwm]
/// * `OC4D`: Output Compare Channel `D` for Timer/Counter4
pub d6: atmega_hal::port::PD7 = pd7,
/// `D7`
///
/// * `INT6`: External Interrupt
pub d7: atmega_hal::port::PE6 = pe6,
/// `D8`
pub d8: atmega_hal::port::PB4 = pb4,
/// `D9`
///
/// * **PWM**: [atmega32u4_hal::timer::Timer1Pwm]
/// * `OC1A`: Output Compare Channel `A` for Timer/Counter1
/// * `#OC4B`: Inverted Output Compare Channel `B` for Timer/Counter4 (Not implemented)
pub d9: atmega_hal::port::PB5 = pb5,
/// `D10`
///
/// * **PWM**: [atmega32u4_hal::timer::Timer1Pwm]
/// * `OC1B`: Output Compare Channel `B` for Timer/Counter1
/// * `OC4B`: Output Compare Channel `B` for Timer/Counter4 (Not implemented)
pub d10: atmega_hal::port::PB6 = pb6,
/// `RX`
///
/// Led for indicating inbound data. Also the CS pin.
pub led_rx: atmega_hal::port::PB0 = pb0,
/// `TX`
///
/// Led for indicating outbound data
pub led_tx: atmega_hal::port::PD5 = pd5,
/// `SCLK`
///
/// ICSP SCLK pin
pub sck: atmega_hal::port::PB1 = pb1,
/// `MOSI`
///
/// ICSP MOSI pin
pub mosi: atmega_hal::port::PB2 = pb2,
/// `MISO`
///
/// ICSP MISO pin
pub miso: atmega_hal::port::PB3 = pb3,
/// `A0`
///
/// * `ADC7` channel
pub a0: atmega_hal::port::PF7 = pf7,
/// `A1`
///
/// * `ADC6` channel
pub a1: atmega_hal::port::PF6 = pf6,
/// `A2`
///
/// * `ADC5` channel
pub a2: atmega_hal::port::PF5 = pf5,
/// `A3`
///
/// * `ADC4` channel
pub a3: atmega_hal::port::PF4 = pf4,
}
}
8 changes: 8 additions & 0 deletions examples/sparkfun-promicro/.cargo/config.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
[build]
target = "../../avr-specs/avr-atmega32u4.json"

[target.'cfg(target_arch = "avr")']
runner = "ravedude promicro"

[unstable]
build-std = ["core"]
16 changes: 16 additions & 0 deletions examples/sparkfun-promicro/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
[package]
name = "sparkfun-promicro-examples"
version = "0.0.0"
authors = ["Rahix <rahix@rahix.de>"]
edition = "2018"
publish = false

[dependencies]
panic-halt = "0.2.0"
ufmt = "0.1.0"
nb = "0.1.2"
embedded-hal = "0.2.3"

[dependencies.arduino-hal]
path = "../../arduino-hal/"
features = ["sparkfun-promicro"]
46 changes: 46 additions & 0 deletions examples/sparkfun-promicro/src/bin/promicro-adc.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
#![no_std]
#![no_main]

use arduino_hal::prelude::*;
use panic_halt as _;

use arduino_hal::adc;

#[arduino_hal::entry]
fn main() -> ! {
let dp = arduino_hal::Peripherals::take().unwrap();
let pins = arduino_hal::pins!(dp);
let mut serial = arduino_hal::default_serial!(dp, pins, 57600);

let mut adc = arduino_hal::Adc::new(dp.ADC, Default::default());

let (vbg, gnd, tmp) = (
adc.read_blocking(&adc::channel::Vbg),
adc.read_blocking(&adc::channel::Gnd),
adc.read_blocking(&adc::channel::Temperature),
);
ufmt::uwriteln!(&mut serial, "Vbandgap: {}", vbg).void_unwrap();
ufmt::uwriteln!(&mut serial, "Ground: {}", gnd).void_unwrap();
ufmt::uwriteln!(&mut serial, "Temperature: {}", tmp).void_unwrap();

let a0 = pins.a0.into_analog_input(&mut adc);
let a1 = pins.a1.into_analog_input(&mut adc);
let a2 = pins.a2.into_analog_input(&mut adc);
let a3 = pins.a3.into_analog_input(&mut adc);

loop {
let values = [
a0.analog_read(&mut adc),
a1.analog_read(&mut adc),
a2.analog_read(&mut adc),
a3.analog_read(&mut adc),
];

for (i, v) in values.iter().enumerate() {
ufmt::uwrite!(&mut serial, "A{}: {} ", i, v).void_unwrap();
}

ufmt::uwriteln!(&mut serial, "").void_unwrap();
arduino_hal::delay_ms(1000);
}
}
22 changes: 22 additions & 0 deletions examples/sparkfun-promicro/src/bin/promicro-blink.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
#![no_std]
#![no_main]

use panic_halt as _;

#[arduino_hal::entry]
fn main() -> ! {
let dp = arduino_hal::Peripherals::take().unwrap();
let pins = arduino_hal::pins!(dp);

let mut led1 = pins.led_rx.into_output();
let mut led2 = pins.led_tx.into_output();

loop {
led1.set_high();
led2.set_low();
arduino_hal::delay_ms(300);
led1.set_low();
led2.set_high();
arduino_hal::delay_ms(300);
}
}
26 changes: 26 additions & 0 deletions examples/sparkfun-promicro/src/bin/promicro-i2cdetect.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
#![no_std]
#![no_main]

use arduino_hal::prelude::*;
use panic_halt as _;

#[arduino_hal::entry]
fn main() -> ! {
let dp = arduino_hal::Peripherals::take().unwrap();
let pins = arduino_hal::pins!(dp);
let mut serial = arduino_hal::default_serial!(dp, pins, 57600);

let mut i2c = arduino_hal::I2c::new(
dp.TWI,
pins.d2.into_pull_up_input(),
pins.d3.into_pull_up_input(),
50000,
);

ufmt::uwriteln!(&mut serial, "Write direction test:\r").void_unwrap();
i2c.i2cdetect(&mut serial, arduino_hal::i2c::Direction::Write).void_unwrap();
ufmt::uwriteln!(&mut serial, "\r\nRead direction test:\r").void_unwrap();
i2c.i2cdetect(&mut serial, arduino_hal::i2c::Direction::Read).void_unwrap();

loop {}
}
50 changes: 50 additions & 0 deletions examples/sparkfun-promicro/src/bin/promicro-spi-feedback.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
//! This example demonstrates how to set up a SPI interface and communicate
//! over it. The physical hardware configuation consists of connecting a
//! jumper directly from pin `~11` to pin `~12`.
//!
//! Once this program is written to the board, the serial output can be
//! accessed with
//!
//! ```
//! sudo screen /dev/ttyACM0 57600
//! ```
//!
//! You should see it output the line `data: 15` repeatedly (aka 0b00001111).
//! If the output you see is `data: 255`, you may need to check your jumper.

#![no_std]
#![no_main]

use arduino_hal::prelude::*;
use arduino_hal::spi;
use embedded_hal::spi::FullDuplex;
use panic_halt as _;

#[arduino_hal::entry]
fn main() -> ! {
let dp = arduino_hal::Peripherals::take().unwrap();
let pins = arduino_hal::pins!(dp);

// set up serial interface for text output
let mut serial = arduino_hal::default_serial!(dp, pins, 57600);

// Create SPI interface.
let (mut spi, _) = arduino_hal::Spi::new(
dp.SPI,
pins.sck.into_output(),
pins.mosi.into_output(),
pins.miso.into_pull_up_input(),
pins.led_rx.into_output(),
spi::Settings::default(),
);

loop {
// Send a byte
nb::block!(spi.send(0b00001111)).void_unwrap();
// Because MISO is connected to MOSI, the read data should be the same
let data = nb::block!(spi.read()).void_unwrap();

ufmt::uwriteln!(&mut serial, "data: {}\r", data).void_unwrap();
arduino_hal::delay_ms(1000);
}
}
24 changes: 24 additions & 0 deletions examples/sparkfun-promicro/src/bin/promicro-usart.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
#![no_std]
#![no_main]

use arduino_hal::prelude::*;
use panic_halt as _;

use embedded_hal::serial::Read;

#[arduino_hal::entry]
fn main() -> ! {
let dp = arduino_hal::Peripherals::take().unwrap();
let pins = arduino_hal::pins!(dp);
let mut serial = arduino_hal::default_serial!(dp, pins, 57600);

ufmt::uwriteln!(&mut serial, "Hello from Arduino!\r").void_unwrap();

loop {
// Read a byte from the serial connection
let b = nb::block!(serial.read()).void_unwrap();

// Answer
ufmt::uwriteln!(&mut serial, "Got {}!\r", b).void_unwrap();
}
}
31 changes: 31 additions & 0 deletions ravedude/src/board.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ pub fn get_board(board: &str) -> Option<Box<dyn Board>> {
"leonardo" => Box::new(ArduinoLeonardo),
"mega2560" => Box::new(ArduinoMega2560),
"diecimila" => Box::new(ArduinoDiecimila),
"promicro" => Box::new(SparkFunProMicro),
_ => return None,
})
}
Expand Down Expand Up @@ -180,3 +181,33 @@ impl Board for ArduinoDiecimila {
None
}
}

struct SparkFunProMicro;

impl Board for SparkFunProMicro {
fn display_name(&self) -> &str {
"SparkFun Pro Micro"
}

fn needs_reset(&self) -> bool {
true
}

fn avrdude_options(&self) -> avrdude::AvrdudeOptions {
avrdude::AvrdudeOptions {
programmer: "avr109",
partno: "atmega32u4",
baudrate: None,
do_chip_erase: true,
}
}

fn guess_port(&self) -> Option<std::path::PathBuf> {
find_port_from_vid_pid_list(&[
(0x1B4F, 0x9205), //5V
(0x1B4F, 0x9206), //5V
(0x1B4F, 0x9203), //3.3V
(0x1B4F, 0x9204), //3.3V
])
}
}