diff --git a/CHANGELOG.md b/CHANGELOG.md index 5860ce21..775e0437 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/). ### Added +- `ws2812_spi` example [#363] - `AsRef/AsMut` and `Output> <-> Input>` [#356] @@ -78,6 +79,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/). [#355]: https://github.com/stm32-rs/stm32f4xx-hal/pull/355 [#356]: https://github.com/stm32-rs/stm32f4xx-hal/pull/356 [#357]: https://github.com/stm32-rs/stm32f4xx-hal/pull/357 +[#363]: https://github.com/stm32-rs/stm32f4xx-hal/pull/363 ### Changed diff --git a/Cargo.toml b/Cargo.toml index 95041a58..954a3526 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -61,6 +61,8 @@ st7789 = "0.6.1" panic-rtt-core = "0.2.1" display-interface-spi = "0.4" ist7920 = "0.1.0" +smart-leds = "0.3.0" +ws2812-spi = { version = "0.4.0", features = [] } [features] device-selected = [] diff --git a/examples/analog-stopwatch-with-spi-ssd1306.rs b/examples/analog-stopwatch-with-spi-ssd1306.rs index dedfc2d3..461417e8 100644 --- a/examples/analog-stopwatch-with-spi-ssd1306.rs +++ b/examples/analog-stopwatch-with-spi-ssd1306.rs @@ -102,7 +102,7 @@ fn main() -> ! { polarity: Polarity::IdleLow, phase: Phase::CaptureOnFirstTransition, }, - stm32f4xx_hal::time::KiloHertz(2000).into(), + 2000.khz(), clocks, ); diff --git a/examples/ws2812_spi.rs b/examples/ws2812_spi.rs new file mode 100644 index 00000000..80d2b671 --- /dev/null +++ b/examples/ws2812_spi.rs @@ -0,0 +1,63 @@ +#![deny(unsafe_code)] +#![no_main] +#![no_std] + +use panic_halt as _; +use stm32f4xx_hal as hal; + +use cortex_m_rt::entry; +use hal::{gpio::NoPin, pac, prelude::*, spi::Spi}; +use smart_leds::{brightness, hsv::RGB8, SmartLedsWrite}; +use ws2812_spi as ws2812; + +#[entry] +fn main() -> ! { + let dp = pac::Peripherals::take().expect("cannot take peripherals"); + let cp = cortex_m::Peripherals::take().expect("cannot take core peripherals"); + + // Configure APB bus clock to 56MHz, cause ws2812b requires 3.5Mbps SPI + let rcc = dp.RCC.constrain(); + let clocks = rcc.cfgr.sysclk(56.mhz()).freeze(); + + let mut delay = hal::delay::Delay::new(cp.SYST, &clocks); + let gpioa = dp.GPIOA.split(); + let gpioc = dp.GPIOC.split(); + + let spi = Spi::new( + dp.SPI1, + (gpioa.pa5, NoPin, gpioa.pa7), + ws2812::MODE, + 3500.khz(), + clocks, + ); + + let mut ws = ws2812::Ws2812::new(spi); + + const NUM_LEDS: usize = 8; + let mut data = [RGB8::default(); NUM_LEDS]; + + loop { + for j in 0..(256 * 5) { + for i in 0..NUM_LEDS { + data[i] = wheel((((i * 256) as u16 / NUM_LEDS as u16 + j as u16) & 255) as u8); + } + ws.write(brightness(data.iter().cloned(), 32)).unwrap(); + delay.delay_ms(5u8); + } + } +} + +/// Input a value 0 to 255 to get a color value +/// The colours are a transition r - g - b - back to r. +fn wheel(mut wheel_pos: u8) -> RGB8 { + wheel_pos = 255 - wheel_pos; + if wheel_pos < 85 { + return (255 - wheel_pos * 3, 0, wheel_pos * 3).into(); + } + if wheel_pos < 170 { + wheel_pos -= 85; + return (0, wheel_pos * 3, 255 - wheel_pos * 3).into(); + } + wheel_pos -= 170; + (wheel_pos * 3, 255 - wheel_pos * 3, 0).into() +} diff --git a/src/spi.rs b/src/spi.rs index 38b10b29..a830bac6 100644 --- a/src/spi.rs +++ b/src/spi.rs @@ -414,7 +414,7 @@ macro_rules! spi { spi: $SPI, pins: (SCK, MISO, MOSI), mode: Mode, - freq: Hertz, + freq: impl Into, clocks: Clocks, ) -> Spi<$SPI, (SCK, MISO, MOSI), TransferModeNormal> { Self::new(spi, pins, mode, freq, clocks) @@ -450,7 +450,7 @@ where spi: SPI, mut pins: (SCK, MISO, MOSI), mode: Mode, - freq: Hertz, + freq: impl Into, clocks: Clocks, ) -> Self { unsafe { @@ -469,7 +469,7 @@ where pins, transfer_mode: TransferModeNormal, } - .pre_init(mode, freq, SPI::get_frequency(&clocks)) + .pre_init(mode, freq.into(), SPI::get_frequency(&clocks)) .init() } @@ -492,7 +492,7 @@ where spi: SPI, mut pins: (SCK, MISO, MOSI), mode: Mode, - freq: Hertz, + freq: impl Into, clocks: Clocks, ) -> Self { unsafe { @@ -511,7 +511,7 @@ where pins, transfer_mode: TransferModeBidi, } - .pre_init(mode, freq, SPI::get_frequency(&clocks)) + .pre_init(mode, freq.into(), SPI::get_frequency(&clocks)) .init() }