Skip to content

Commit

Permalink
chore: ws2812 gpio demo for ch32v003
Browse files Browse the repository at this point in the history
  • Loading branch information
andelf committed Jun 2, 2024
1 parent d2a028f commit 4ba1bce
Show file tree
Hide file tree
Showing 2 changed files with 185 additions and 1 deletion.
2 changes: 1 addition & 1 deletion examples/ch32v003/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ embassy-executor = { version = "0.5.0", features = [
] }
embassy-time = { version = "0.3.0" }

qingke-rt = "0.2.1"
qingke-rt = { version = "0.2.1", features = ["highcode"] }
qingke = "0.2.0"
# qingke-rt = { version = "0.2.0", path = "../../../qingke/qingke-rt" }
# qingke = { version = "0.2.0", path = "../../../qingke" }
Expand Down
184 changes: 184 additions & 0 deletions examples/ch32v003/src/bin/gpio_ws2812.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,184 @@
#![no_std]
#![no_main]
#![feature(type_alias_impl_trait)]

use ch32_hal as hal;
use ch32_hal::gpio::Output;
use ch32_hal::timer::simple_pwm::SimplePwm;
use hal::delay::Delay;
use hal::println;
use hal::time::Hertz;
use hal::timer::complementary_pwm::{ComplementaryPwm, ComplementaryPwmPin};
use hal::timer::low_level::CountingMode;
use hal::timer::simple_pwm::PwmPin;
use qingke_rt::highcode;

pub const RGB_UNIT_MAX: f32 = 255.0;
pub const HUE_MAX: f32 = 360.0;
pub const PERCENT_MAX: f32 = 100.0;
pub const RATIO_MAX: f32 = 1.0;
pub const ALL_MIN: f32 = 0.0;

const ONE: f32 = 1.0;
const TWO: f32 = 2.0;
const SIX: f32 = 6.0;

const ONE_THIRD: f32 = ONE / 3.0;
const TWO_THIRD: f32 = TWO / 3.0;

pub fn bound(r: f32, entire: f32) -> f32 {
let mut n = r;
loop {
let less = n < ALL_MIN;
let bigger = n > entire;
if !less && !bigger {
break n;
}
if less {
n += entire;
} else {
n -= entire;
}
}
}

pub fn bound_ratio(r: f32) -> f32 {
bound(r, RATIO_MAX)
}

fn calc_rgb_unit(unit: f32, temp1: f32, temp2: f32) -> f32 {
let mut result = temp2;
if SIX * unit < ONE {
result = temp2 + (temp1 - temp2) * SIX * unit
} else if TWO * unit < ONE {
result = temp1
} else if 3.0 * unit < TWO {
result = temp2 + (temp1 - temp2) * (TWO_THIRD - unit) * SIX
}
result * RGB_UNIT_MAX
}

/// hsl: [1.0, 1.0, 1.0] -> [255.0, 255.0, 255.0]
pub fn hsl_to_rgb(hsl: [f32; 3]) -> [f32; 3] {
let [h, s, l]: [f32; 3] = hsl;
if s == 0.0 {
let unit = RGB_UNIT_MAX * l;
return [unit, unit, unit];
}

let temp1 = if l < 0.5 { l * (ONE + s) } else { l + s - l * s };

let temp2 = TWO * l - temp1;
let hue = h;

let temp_r = bound_ratio(hue + ONE_THIRD);
let temp_g = bound_ratio(hue);
let temp_b = bound_ratio(hue - ONE_THIRD);

let r = calc_rgb_unit(temp_r, temp1, temp2);
let g = calc_rgb_unit(temp_g, temp1, temp2);
let b = calc_rgb_unit(temp_b, temp1, temp2);
[r, g, b]
}

struct WS2812 {
pin: Output<'static>,
}

impl WS2812 {
pub fn new(pin: Output<'static>) -> Self {
Self { pin }
}

pub fn reset(&mut self) {
self.pin.set_low();
Delay.delay_us(50);
}

// tune values to get 800kHz
// duty cycle 33% and 66%
#[highcode]
pub fn test(&mut self) {
loop {
self.pin.set_high();
qingke::riscv::asm::delay(18);
self.pin.set_low();
qingke::riscv::asm::delay(7);
}
}

#[highcode]
pub fn set_color(&mut self, mut color: u32) {
for i in (0..24).rev() {
if color & (1 << i) == 0 {
self.pin.set_high();
qingke::riscv::asm::delay(8);
self.pin.set_low();
qingke::riscv::asm::delay(16);
} else {
self.pin.set_high();
qingke::riscv::asm::delay(18);
self.pin.set_low();
qingke::riscv::asm::delay(7);
}
}

self.pin.set_low();
qingke::riscv::asm::delay(8 * 50);
}
}

#[qingke_rt::entry]
fn main() -> ! {
hal::debug::SDIPrint::enable();
let mut config = hal::Config::default();

config.rcc = hal::rcc::Config::SYSCLK_FREQ_48MHZ_HSI;
let p = hal::init(config);

let ws2812 = Output::new(p.PA2, hal::gpio::Level::Low, Default::default());

let mut ws2812 = WS2812::new(ws2812);

let mut i = 0;

// loop {
// ws2812.test();
// }

loop {
for h in 0..360 {
// hsl_to_rgb([h as f32 / 360.0, 0.900, 0.500])
let rgb = hsl_to_rgb([h as f32 / 360.0, 0.900, 0.500]);
// to GRB
let color = ((rgb[1] as u32) << 16) | ((rgb[0] as u32) << 8) | (rgb[2] as u32);


ws2812.set_color(color);

Delay.delay_ms(20);
}
}

loop {
ws2812.set_color(0x000000);
// ws2812.pin.set_low();
// ws2812.reset();

// Shift random

if i > 0xffffff {
i = 0;
}

println!("toggle! {:06x}", i);
Delay.delay_ms(10);
}
}

#[panic_handler]
fn panic(info: &core::panic::PanicInfo) -> ! {
let _ = hal::println!("\n\n\n{}", info);

loop {}
}

0 comments on commit 4ba1bce

Please sign in to comment.