led and backlight
This commit is contained in:
@@ -0,0 +1,6 @@
|
||||
[build]
|
||||
target = "riscv32imac-unknown-none-elf"
|
||||
|
||||
[target.riscv32imac-unknown-none-elf]
|
||||
runner = "espflash flash --monitor"
|
||||
rustflags = ["-C", "link-arg=-Tlinkall.x"]
|
||||
@@ -0,0 +1 @@
|
||||
/target
|
||||
Generated
+1463
File diff suppressed because it is too large
Load Diff
+20
@@ -0,0 +1,20 @@
|
||||
[package]
|
||||
name = "espboard"
|
||||
version = "0.1.0"
|
||||
edition = "2024"
|
||||
|
||||
[dependencies]
|
||||
esp-backtrace = { version = "0.20.0", features = ["esp32c6", "println", "panic-handler"] }
|
||||
esp-bootloader-esp-idf = { version = "0.6.0", features = ["esp32c6"] }
|
||||
esp-hal = { version = "1.2.0", features = ["esp32c6", "unstable"] }
|
||||
esp-hal-smartled = { version = "0.18", default-features = false, features = ["esp32c6"] }
|
||||
esp-println = { version = "0.18.0", default-features = false, features = ["esp32c6", "jtag-serial"] }
|
||||
smart-leds = "0.4"
|
||||
smart-leds-trait = "0.3"
|
||||
|
||||
[profile.dev]
|
||||
codegen-units = 1
|
||||
incremental = false
|
||||
|
||||
[profile.release]
|
||||
codegen-units = 1
|
||||
@@ -0,0 +1,50 @@
|
||||
use esp_hal::gpio::interconnect::PeripheralOutput;
|
||||
use esp_hal::gpio::DriveMode;
|
||||
use esp_hal::ledc::channel::{self, Channel, ChannelIFace};
|
||||
use esp_hal::ledc::timer::TimerIFace;
|
||||
use esp_hal::ledc::LowSpeed;
|
||||
|
||||
/// Maximum duty cycle percentage. The board documentation warns against
|
||||
/// running the display above 50% brightness, so `level = 1.0` maps to this.
|
||||
const MAX_DUTY_PCT: u8 = 50;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum Error {
|
||||
Channel(channel::Error),
|
||||
}
|
||||
|
||||
impl From<channel::Error> for Error {
|
||||
fn from(e: channel::Error) -> Self {
|
||||
Error::Channel(e)
|
||||
}
|
||||
}
|
||||
|
||||
/// Backlight PWM driver. The channel holds a reference to the caller-owned
|
||||
/// timer, so this type's lifetime is bounded by the timer's lifetime.
|
||||
pub struct LcdBacklight<'a> {
|
||||
channel: Channel<'a, LowSpeed>,
|
||||
}
|
||||
|
||||
impl<'a> LcdBacklight<'a> {
|
||||
pub fn new(
|
||||
timer: &'a dyn TimerIFace<LowSpeed>,
|
||||
pin: impl PeripheralOutput<'a>,
|
||||
) -> Result<Self, Error> {
|
||||
let mut channel = Channel::new(channel::Number::Channel0, pin);
|
||||
channel.configure(channel::config::Config {
|
||||
timer,
|
||||
duty_pct: 0,
|
||||
drive_mode: DriveMode::PushPull,
|
||||
})?;
|
||||
Ok(Self { channel })
|
||||
}
|
||||
|
||||
/// Set the backlight level from `0.0` (off) to `1.0` (maximum).
|
||||
///
|
||||
/// `1.0` is scaled to a 50% duty cycle, the maximum brightness the board
|
||||
/// documentation recommends.
|
||||
pub fn set_level(&mut self, level: f32) -> Result<(), Error> {
|
||||
let duty_pct = ((level.clamp(0.0, 1.0) * MAX_DUTY_PCT as f32) + 0.5) as u8;
|
||||
self.channel.set_duty(duty_pct).map_err(Error::Channel)
|
||||
}
|
||||
}
|
||||
+42
@@ -0,0 +1,42 @@
|
||||
use esp_hal::gpio::interconnect::PeripheralOutput;
|
||||
use esp_hal::rmt::TxChannelCreator;
|
||||
use esp_hal::time::Rate;
|
||||
use esp_hal::Blocking;
|
||||
use esp_hal_smartled::{RmtSmartLeds, WS2812_TIMING, buffer_size, color_order};
|
||||
use smart_leds_trait::{RGB8, SmartLedsWrite};
|
||||
|
||||
const RMT_FREQ: Rate = Rate::from_mhz(80);
|
||||
|
||||
type SmartLed = RmtSmartLeds<'static, { buffer_size::<RGB8>(1) }, Blocking, RGB8, color_order::Grb>;
|
||||
|
||||
pub struct RgbLed {
|
||||
led: SmartLed,
|
||||
}
|
||||
|
||||
impl RgbLed {
|
||||
pub fn new(
|
||||
channel: impl TxChannelCreator<'static, Blocking>,
|
||||
pin: impl PeripheralOutput<'static>,
|
||||
) -> Result<Self, esp_hal_smartled::Error> {
|
||||
Ok(Self {
|
||||
led: SmartLed::new_with_memsize(WS2812_TIMING, channel, pin, 2, RMT_FREQ)?,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn set_color(
|
||||
&mut self,
|
||||
r: u8,
|
||||
g: u8,
|
||||
b: u8,
|
||||
) -> Result<(), esp_hal_smartled::AdapterError> {
|
||||
self.led.write([RGB8 { r, g, b }])
|
||||
}
|
||||
|
||||
pub fn set_rgb(&mut self, rgb: RGB8) -> Result<(), esp_hal_smartled::AdapterError> {
|
||||
self.led.write([rgb])
|
||||
}
|
||||
|
||||
pub fn off(&mut self) -> Result<(), esp_hal_smartled::AdapterError> {
|
||||
self.set_color(0, 0, 0)
|
||||
}
|
||||
}
|
||||
+69
@@ -0,0 +1,69 @@
|
||||
#![no_std]
|
||||
#![no_main]
|
||||
|
||||
mod backlight;
|
||||
mod led;
|
||||
|
||||
use esp_backtrace as _;
|
||||
use esp_bootloader_esp_idf::esp_app_desc;
|
||||
use esp_hal::ledc::timer::{self, TimerIFace};
|
||||
use esp_hal::ledc::{LSGlobalClkSource, Ledc, LowSpeed};
|
||||
use esp_hal::{init, rmt::Rmt, time::Rate, Config};
|
||||
use esp_println::println;
|
||||
use smart_leds::hsv::{hsv2rgb, Hsv};
|
||||
use smart_leds::{brightness, gamma};
|
||||
|
||||
esp_app_desc!();
|
||||
|
||||
#[esp_hal::main]
|
||||
fn main() -> ! {
|
||||
let peripherals = init(Config::default());
|
||||
|
||||
let mut led = {
|
||||
let rmt = Rmt::new(peripherals.RMT, Rate::from_mhz(80)).expect("Failed to init RMT");
|
||||
led::RgbLed::new(rmt.channel0, peripherals.GPIO8).expect("Failed to init RGB LED")
|
||||
};
|
||||
|
||||
let mut ledc = Ledc::new(peripherals.LEDC);
|
||||
ledc.set_global_slow_clock(LSGlobalClkSource::APBClk);
|
||||
let mut timer = ledc.timer::<LowSpeed>(timer::Number::Timer0);
|
||||
timer
|
||||
.configure(timer::config::Config {
|
||||
duty: timer::config::Duty::Duty8Bit,
|
||||
clock_source: timer::LSClockSource::APBClk,
|
||||
frequency: Rate::from_khz(5),
|
||||
})
|
||||
.expect("Failed to configure backlight timer");
|
||||
let mut backlight =
|
||||
backlight::LcdBacklight::new(&timer, peripherals.GPIO22).expect("Failed to init backlight");
|
||||
|
||||
let delay = esp_hal::delay::Delay::new();
|
||||
|
||||
let levels = [1.0f32, 0.75, 0.5, 0.25, 0.0, 0.5];
|
||||
let mut level_idx = 0;
|
||||
|
||||
loop {
|
||||
for hue in 0..=255 {
|
||||
let rgb = hsv2rgb(Hsv {
|
||||
hue,
|
||||
sat: 255,
|
||||
val: 255,
|
||||
});
|
||||
let lit = brightness(gamma(core::iter::once(rgb)), 40)
|
||||
.next()
|
||||
.unwrap();
|
||||
led.set_rgb(lit).unwrap();
|
||||
|
||||
if hue % 32 == 0 {
|
||||
println!("hue {hue}: ({}, {}, {})", lit.r, lit.g, lit.b);
|
||||
}
|
||||
|
||||
delay.delay_millis(10);
|
||||
}
|
||||
|
||||
let level = levels[level_idx % levels.len()];
|
||||
backlight.set_level(level).unwrap();
|
||||
println!("backlight level: {level}");
|
||||
level_idx += 1;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user