Skip to content

Instantly share code, notes, and snippets.

@nathansamson
Created August 21, 2022 14:22
Show Gist options
  • Save nathansamson/8ff4efbcd11043bcfda6a3e7cf2d01ea to your computer and use it in GitHub Desktop.
Save nathansamson/8ff4efbcd11043bcfda6a3e7cf2d01ea to your computer and use it in GitHub Desktop.
[package]
name = "fri3d-badge"
version = "0.1.0"
authors = ["Nathan Samson <nathan@nathansamson.be>"]
edition = "2021"
resolver = "2"
[profile.release]
opt-level = "s"
[profile.dev]
debug = true # Symbols are nice and they don't increase the size on Flash
opt-level = "z"
[features]
pio = ["esp-idf-sys/pio"]
[dependencies]
esp-idf-sys = { version = "0.31.6", features = ["binstart"] }
esp-idf-hal = "0.38"
embedded-hal = "=1.0.0-alpha.8"
embedded-hal-0-2 = { package = "embedded-hal", version = "0.2.7", features = ["unproven"] }
embedded-graphics = "0.7.1"
# mipidsi = "0.2.1"
st7789 = { version="0.6.1" }
display-interface-spi = "*"
smart-leds = "0.3.0"
ws2812-esp32-rmt-driver = { version = "0.4.0", features = ["smart-leds-trait"] }
[build-dependencies]
embuild = "0.29"
anyhow = "1"
use std::thread;
use embedded_hal_0_2::blocking::delay::DelayMs;
use std::{borrow::Borrow, sync::Arc, time::Duration};
use embedded_hal_0_2::digital::v2::OutputPin;
use esp_idf_hal::delay::FreeRtos;
use esp_idf_hal::ledc::{config::TimerConfig, Channel, Timer};
use esp_idf_hal::peripherals::Peripherals;
use esp_idf_hal::prelude::*;
use esp_idf_hal::ledc::Resolution::Bits10;
use ws2812_esp32_rmt_driver::Ws2812Esp32Rmt;
use smart_leds::{RGB, colors};
use embedded_graphics::{
pixelcolor::Rgb565, prelude::*, primitives::{Rectangle, PrimitiveStyleBuilder},
};
use fri3d_badge::effects;
use fri3d_badge::led_strip;
use fri3d_badge::effects::Effect;
use esp_idf_sys as _; // If using the `binstart` feature of `esp-idf-sys`, always keep this module imported
fn blink_leds() {
const N: usize = 5;
let mut ws = Ws2812Esp32Rmt::new(0, 2).unwrap();
let mut led_strip_colors = led_strip::LedStrip::<N>::new();
let mut color = led_strip::Color::from(RGB::new(0, 0, 255));
color.set_brightness(50);
let mut i: u8 = 0;
loop {
effects::FillEffect::new(color).apply::<N>(led_strip_colors.get_mut_slice::<N>(0));
led_strip_colors.write(&mut ws);
color = led_strip::Color::from(RGB::new(i / 2, i / 2, 255 - i));
color.set_brightness(50);
i = (i + 1) % (255);
println!("FILLING LED WITH {}", i);
FreeRtos.delay_ms(100 as u32);
}
}
fn play_music<T: esp_idf_hal::ledc::HwTimer, C: esp_idf_hal::ledc::HwChannel, P: esp_idf_hal::gpio::OutputPin>
(mut ledc_timer: T, mut ledc_channel: C, mut pin32: P) {
let max_duty = 0x1FF;
let notes = [ 659.25f32, 587.33, 369.99, 415.3, 554.37, 493.88, 293.66, 329.63, 493.88, 440.0, 277.18, 329.63, 440.0 ];
let lengths = [ 1, 1, 2, 2, 1, 1, 2, 2, 1, 1, 2, 2, 6 ];
loop {
for i in 0..13 {
let config = TimerConfig::default().frequency(((notes[i]).round() as u32).into()).resolution(Bits10);
let timer = Timer::new(ledc_timer, &config).unwrap();
let mut channel = Channel::new(ledc_channel, &timer, pin32).unwrap();
println!("Note {} freq = {}", i, notes[i]);
channel.set_duty(255).unwrap();
//channel.enable();
FreeRtos.delay_ms(120 * lengths[i] as u32);
(ledc_channel, pin32) = channel.release().unwrap();
ledc_timer = timer.release().unwrap();
}
FreeRtos.delay_ms(2000 as u32);
}
}
fn main() {
// Temporary. Will disappear once ESP-IDF 4.4 is released, but for now it is necessary to call this function once,
// or else some patches to the runtime implemented by esp-idf-sys might not link properly.
esp_idf_sys::link_patches();
println!("Hello, world!");
println!("Configuring output channel");
let peripherals = Peripherals::take().unwrap();
let mut ledc_timer = peripherals.ledc.timer0;
let mut ledc_channel = peripherals.ledc.channel0;
let mut pin32 = peripherals.pins.gpio32;
let led_threads_handle = thread::spawn(blink_leds);
// let music_thread_handle = thread::spawn(move || { play_music(ledc_timer, ledc_channel, pin32); });
let config = <esp_idf_hal::spi::config::Config as Default>::default().baudrate(32.MHz().into()).data_mode(embedded_hal::spi::MODE_0);
let spi = esp_idf_hal::spi::Master::<esp_idf_hal::spi::SPI3, _, _, _, esp_idf_hal::gpio::Gpio5<esp_idf_hal::gpio::Unknown>>::new(
peripherals.spi3,
esp_idf_hal::spi::Pins {
sclk: peripherals.pins.gpio18,
sdo: peripherals.pins.gpio23,
sdi: Some(peripherals.pins.gpio19),
cs: None,
},
config,
)
.unwrap();
let lcd_dc = peripherals.pins.gpio33.into_output().unwrap();
let lcd_rst = peripherals.pins.gpio26.into_output().unwrap();
let lcd_cs = peripherals.pins.gpio5.into_output().unwrap();
let mut led_bl = peripherals.pins.gpio12.into_output().unwrap();
led_bl.set_high();
let di = display_interface_spi::SPIInterface::new(spi, lcd_dc, lcd_cs);
println!("SPI CONFIG DONE");
// let mut lcd = mipidsi::Display::st7789_without_rst(di);
let mut lcd = mipidsi::Display::st7789(di, lcd_rst);
let mut delay = esp_idf_hal::delay::Ets;
println!("INIT S");
lcd.init(
&mut delay,
mipidsi::DisplayOptions {
orientation: mipidsi::Orientation::PortraitInverted(false),
invert_vertical_refresh: false,
color_order: Default::default(),
invert_horizontal_refresh: false,
},
).unwrap();
// let mut lcd = st7789::ST7789::new(di, lcd_rst, 240, 240);
// lcd.set_orientation(st7789::Orientation::Portrait).unwrap();
// let mut delay = esp_idf_hal::delay::Ets;
// lcd.init(&mut delay).unwrap();
println!("INITED");
lcd.clear(Rgb565::BLUE);
println!("CLEAR");
// let Size { width, height } = lcd.size();
// let pattern = (0..height as i32).flat_map(|y| {
// (0..width as i32).map(move |x| {
// let dx = x - width as i32 / 2;
// let dy = y - height as i32 / 2;
// if dx * dx * 2 + dy * dy < 40 * 40 {
// c1
// } else {
// c2
// }
// })
// });
// lcd.set_pixels(0, 0, width as u16, height as u16, pattern);
let style = PrimitiveStyleBuilder::new()
.stroke_color(Rgb565::RED)
.stroke_width(3)
.fill_color(Rgb565::GREEN)
.build();
Rectangle::new(Point::new(30, 20), Size::new(10, 15))
.into_styled(style)
.draw(&mut lcd).unwrap();
// Rectangle with translation applied
Rectangle::new(Point::new(30, 20), Size::new(10, 15))
.translate(Point::new(-20, -10))
.into_styled(style)
.draw(&mut lcd).unwrap();
println!("DONE");
// Since both threads are endless loops its probably not necessary to join both but anyhow
// music_thread_handle.join();
led_threads_handle.join();
}
use std::thread;
use embedded_hal_0_2::blocking::delay::DelayMs;
use std::{borrow::Borrow, sync::Arc, time::Duration};
use embedded_hal_0_2::digital::v2::OutputPin;
use esp_idf_hal::delay::FreeRtos;
use esp_idf_hal::ledc::{config::TimerConfig, Channel, Timer};
use esp_idf_hal::peripherals::Peripherals;
use esp_idf_hal::prelude::*;
use esp_idf_hal::ledc::Resolution::Bits10;
use ws2812_esp32_rmt_driver::Ws2812Esp32Rmt;
use smart_leds::{RGB, colors};
use embedded_graphics::{
pixelcolor::Rgb565, prelude::*, primitives::{Rectangle, PrimitiveStyleBuilder},
};
use fri3d_badge::effects;
use fri3d_badge::led_strip;
use fri3d_badge::effects::Effect;
use esp_idf_sys as _; // If using the `binstart` feature of `esp-idf-sys`, always keep this module imported
fn blink_leds() {
const N: usize = 5;
let mut ws = Ws2812Esp32Rmt::new(0, 2).unwrap();
let mut led_strip_colors = led_strip::LedStrip::<N>::new();
let mut color = led_strip::Color::from(RGB::new(0, 0, 255));
color.set_brightness(50);
let mut i: u8 = 0;
loop {
effects::FillEffect::new(color).apply::<N>(led_strip_colors.get_mut_slice::<N>(0));
led_strip_colors.write(&mut ws);
color = led_strip::Color::from(RGB::new(i / 2, i / 2, 255 - i));
color.set_brightness(50);
i = (i + 1) % (255);
println!("FILLING LED WITH {}", i);
FreeRtos.delay_ms(100 as u32);
}
}
fn play_music<T: esp_idf_hal::ledc::HwTimer, C: esp_idf_hal::ledc::HwChannel, P: esp_idf_hal::gpio::OutputPin>
(mut ledc_timer: T, mut ledc_channel: C, mut pin32: P) {
let max_duty = 0x1FF;
let notes = [ 659.25f32, 587.33, 369.99, 415.3, 554.37, 493.88, 293.66, 329.63, 493.88, 440.0, 277.18, 329.63, 440.0 ];
let lengths = [ 1, 1, 2, 2, 1, 1, 2, 2, 1, 1, 2, 2, 6 ];
loop {
for i in 0..13 {
let config = TimerConfig::default().frequency(((notes[i]).round() as u32).into()).resolution(Bits10);
let timer = Timer::new(ledc_timer, &config).unwrap();
let mut channel = Channel::new(ledc_channel, &timer, pin32).unwrap();
println!("Note {} freq = {}", i, notes[i]);
channel.set_duty(255).unwrap();
//channel.enable();
FreeRtos.delay_ms(120 * lengths[i] as u32);
(ledc_channel, pin32) = channel.release().unwrap();
ledc_timer = timer.release().unwrap();
}
FreeRtos.delay_ms(2000 as u32);
}
}
fn main() {
// Temporary. Will disappear once ESP-IDF 4.4 is released, but for now it is necessary to call this function once,
// or else some patches to the runtime implemented by esp-idf-sys might not link properly.
esp_idf_sys::link_patches();
println!("Hello, world!");
println!("Configuring output channel");
let peripherals = Peripherals::take().unwrap();
let mut ledc_timer = peripherals.ledc.timer0;
let mut ledc_channel = peripherals.ledc.channel0;
let mut pin32 = peripherals.pins.gpio32;
let led_threads_handle = thread::spawn(blink_leds);
// let music_thread_handle = thread::spawn(move || { play_music(ledc_timer, ledc_channel, pin32); });
let config = <esp_idf_hal::spi::config::Config as Default>::default().baudrate(32.MHz().into()).data_mode(embedded_hal::spi::MODE_0);
let spi = esp_idf_hal::spi::Master::<esp_idf_hal::spi::SPI3, _, _, _, esp_idf_hal::gpio::Gpio5<esp_idf_hal::gpio::Unknown>>::new(
peripherals.spi3,
esp_idf_hal::spi::Pins {
sclk: peripherals.pins.gpio18,
sdo: peripherals.pins.gpio23,
sdi: Some(peripherals.pins.gpio19),
cs: None,
},
config,
)
.unwrap();
let lcd_dc = peripherals.pins.gpio33.into_output().unwrap();
let lcd_rst = peripherals.pins.gpio26.into_output().unwrap();
let lcd_cs = peripherals.pins.gpio5.into_output().unwrap();
let mut led_bl = peripherals.pins.gpio12.into_output().unwrap();
led_bl.set_high();
let di = display_interface_spi::SPIInterface::new(spi, lcd_dc, lcd_cs);
println!("SPI CONFIG DONE");
// let mut lcd = mipidsi::Display::st7789_without_rst(di);
// let mut lcd = mipidsi::Display::st7789(di, lcd_rst);
// let mut delay = esp_idf_hal::delay::Ets;
// println!("INIT S");
// lcd.init(
// &mut delay,
// mipidsi::DisplayOptions {
// orientation: mipidsi::Orientation::PortraitInverted(false),
// invert_vertical_refresh: false,
// color_order: Default::default(),
// invert_horizontal_refresh: false,
// },
// ).unwrap();
let mut lcd = st7789::ST7789::new(di, lcd_rst, 240, 240);
lcd.set_orientation(st7789::Orientation::Portrait).unwrap();
let mut delay = esp_idf_hal::delay::Ets;
lcd.init(&mut delay).unwrap();
println!("INITED");
lcd.clear(Rgb565::BLUE);
println!("CLEAR");
// let Size { width, height } = lcd.size();
// let pattern = (0..height as i32).flat_map(|y| {
// (0..width as i32).map(move |x| {
// let dx = x - width as i32 / 2;
// let dy = y - height as i32 / 2;
// if dx * dx * 2 + dy * dy < 40 * 40 {
// c1
// } else {
// c2
// }
// })
// });
// lcd.set_pixels(0, 0, width as u16, height as u16, pattern);
let style = PrimitiveStyleBuilder::new()
.stroke_color(Rgb565::RED)
.stroke_width(3)
.fill_color(Rgb565::GREEN)
.build();
Rectangle::new(Point::new(30, 20), Size::new(10, 15))
.into_styled(style)
.draw(&mut lcd).unwrap();
// Rectangle with translation applied
Rectangle::new(Point::new(30, 20), Size::new(10, 15))
.translate(Point::new(-20, -10))
.into_styled(style)
.draw(&mut lcd).unwrap();
println!("DONE");
// Since both threads are endless loops its probably not necessary to join both but anyhow
// music_thread_handle.join();
led_threads_handle.join();
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment