Browse Source

developed a very simple functional DSP VM for the LED strip

master
Weird Constructor 1 year ago
parent
commit
4dbc1bd033
  1. 272
      ws2812_bl_ctrl/src/main.rs

272
ws2812_bl_ctrl/src/main.rs

@ -80,6 +80,15 @@ pub fn hsv2rgb(hue: f32, sat: f32, val: f32) -> (f32, f32, f32) {
(r_ + m, g_ + m, b_ + m)
}
pub fn hsvt2rgb_u8(hsv: (f32, f32, f32)) -> (u8, u8, u8) {
let r = hsv2rgb(hsv.0, hsv.1, hsv.2);
(
(r.0 * 255.0) as u8,
(r.1 * 255.0) as u8,
(r.2 * 255.0) as u8
)
}
pub fn hsv2rgb_u8(h: f32, s: f32, v: f32) -> (u8, u8, u8) {
let r = hsv2rgb(h, s, v);
(
@ -89,6 +98,198 @@ pub fn hsv2rgb_u8(h: f32, s: f32, v: f32) -> (u8, u8, u8) {
)
}
pub fn hex2u8(hx: &[u8]) -> Result<u8, ()> {
if hx.len() < 2 {
return Err(());
}
let mut res = 0;
for (i, byte) in hx[0..2].iter().enumerate() {
let val =
match byte {
b'0' => 0,
b'1' => 1,
b'2' => 2,
b'3' => 3,
b'4' => 4,
b'5' => 5,
b'6' => 6,
b'7' => 7,
b'8' => 8,
b'9' => 9,
b'a' | b'A' => 10,
b'b' | b'B' => 11,
b'c' | b'C' => 12,
b'd' | b'D' => 13,
b'e' | b'E' => 14,
b'f' | b'F' => 15,
_ => 0,
};
let val = if i <= 0 { val << 4 } else { val };
res |= val;
}
Ok(res)
}
pub fn hex2u16(hx: &[u8]) -> Result<u16, ()> {
if hx.len() < 4 {
return Err(());
}
let mut res = 0u16;
for (i, byte) in hx[0..4].iter().enumerate() {
let val =
match byte {
b'0' => 0,
b'1' => 1,
b'2' => 2,
b'3' => 3,
b'4' => 4,
b'5' => 5,
b'6' => 6,
b'7' => 7,
b'8' => 8,
b'9' => 9,
b'a' | b'A' => 10,
b'b' | b'B' => 11,
b'c' | b'C' => 12,
b'd' | b'D' => 13,
b'e' | b'E' => 14,
b'f' | b'F' => 15,
_ => 0,
};
let val =
match i {
0 => val << 12,
1 => val << 8,
2 => val << 4,
3 | _ => val,
};
res |= val;
}
Ok(res)
}
pub fn hex2f32(hx: &[u8]) -> Result<f32, ()> {
Ok(hex2u8(hx)? as f32 / 255.0)
}
pub fn get_color(code: &[u8]) -> Result<((f32, f32, f32), usize), ()> {
if code.len() < 6 {
return Err(());
}
let h = hex2f32(&code[0..2])? * 360.0;
let s = hex2f32(&code[2..4])?;
let v = hex2f32(&code[4..6])?;
Ok(((h, s, v), 6))
}
pub fn rd_val(code: &[u8], led_idx: u16, r: u32) -> Result<(u32, usize), ()> {
let res =
match code[0] {
b'r' => (r, 1),
b'l' => (led_idx as u32, 1),
b'_' => (hex2u16(&code[1..])? as u32, 5),
_ => (hex2u8(&code[0..])? as u32, 2),
};
Ok(res)
}
// code like:
// #c44ffff c00ffff ceeffff L0009; %l03!
// ; /l06 %r02 +r01 !
pub fn exec_wledcode(dt: f32, code: &[u8], strip: &mut [RGB8]) -> Result<(), ()> {
let mut regs : [(f32, f32, f32); 256] = [(0.0, 0.0, 0.0); 256];
let mut rp = 0;
let mut pc : usize = 0;
let mut sptr = 0;
for i in 0..strip.len() {
strip[i] = (0, 0, 0).into();
}
let mut slen = 0;
while pc < code.len() {
let op = code[pc];
pc += 1;
match op {
// c HHHHHH - Set current color register to color (hex)
b'c' => {
let (clr, len) = get_color(&code[pc..])?;
pc += len;
regs[rp] = clr;
rp += 1;
},
b'L' => {
slen = hex2u16(&code[pc..])?;
},
b';' => { break; },
_ => {},
}
}
let start_pc = pc;
for led_idx in 0..slen {
let mut r : u32 = 0;
pc = start_pc;
while pc < code.len() {
let op = code[pc];
pc += 1;
info!("[{}] {}", led_idx, core::char::from_u32(op as u32).unwrap());
match op {
b'%' => {
let (a, len) = rd_val(&code[pc..], led_idx, r)?;
pc += len;
let (b, len) = rd_val(&code[pc..], led_idx, r)?;
pc += len;
r = a % b;
},
b'+' => {
let (a, len) = rd_val(&code[pc..], led_idx, r)?;
pc += len;
let (b, len) = rd_val(&code[pc..], led_idx, r)?;
pc += len;
r = a.wrapping_add(b);
},
b'-' => {
let (a, len) = rd_val(&code[pc..], led_idx, r)?;
pc += len;
let (b, len) = rd_val(&code[pc..], led_idx, r)?;
pc += len;
r = a.wrapping_sub(b);
},
b'/' => {
let (a, len) = rd_val(&code[pc..], led_idx, r)?;
pc += len;
let (b, len) = rd_val(&code[pc..], led_idx, r)?;
pc += len;
r = a / b;
},
b'r' => {
let (new_r, len) = rd_val(&code[pc..], led_idx, r)?;
r = new_r;
pc += len;
},
_ => { },
}
}
strip[led_idx as usize] = hsvt2rgb_u8(regs[r as usize]).into();
}
Ok(())
}
#[entry]
fn main() -> ! {
info!("Program start");
@ -198,38 +399,39 @@ fn main() -> ! {
let mut leds : [RGB8; LEN] = [(0,0,0).into(); LEN];
let real_len = 9;
let mut code_accum : [u8; 1024] = [0u8; 1024];
let mut wcode_ptr = 0;
let mut wcode_len = 0;
loop {
if uart.uart_is_readable() {
let mut buf = [0u8; 100];
if let Ok(len) = uart.read_raw(&mut buf) {
let s = core::str::from_utf8(&buf[0..len]).unwrap();
info!("Recv: [{}]", s);
}
info!("Recv({}): [{}]", len, s);
if buf[0] == b'r' {
for l in leds.iter_mut() {
*l = hsv2rgb_u8(0.0, 1.0, 1.0).into();
}
} else if buf[0] == b'y' {
for l in leds.iter_mut() {
*l = hsv2rgb_u8(60.0, 1.0, 1.0).into();
}
} else if buf[0] == b'w' {
for l in leds.iter_mut() {
*l = hsv2rgb_u8(0.0, 0.0, 1.0).into();
for b in buf[0..len].iter() {
match *b {
b'#' => { wcode_len = 0; wcode_ptr = 0; },
b'!' => { wcode_len = wcode_ptr; },
_ => { code_accum[wcode_ptr] = *b; wcode_ptr += 1; }
}
}
} else {
for l in leds.iter_mut() {
*l = hsv2rgb_u8(90.0, 1.0, 1.0).into();
if wcode_len == 0 {
continue;
}
}
}
let vbrightness = limit_to_milliamp(&leds[0..real_len], max_ma);
info!("Bright={}", vbrightness);
ws.write(brightness(leds.iter().copied(), vbrightness)).unwrap();
if let Err(_) = exec_wledcode(0.0, &code_accum[0..wcode_len], &mut leds[..]) {
info!("err!");
}
delay.start(16.milliseconds());
let vbrightness = limit_to_milliamp(&leds[0..real_len], max_ma);
//d// info!("Bright={}", vbrightness);
ws.write(brightness(leds.iter().copied(), vbrightness)).unwrap();
delay.start((2 * 16).milliseconds());
let _ = nb::block!(delay.wait());
}
}
@ -256,3 +458,31 @@ pub fn limit_to_milliamp(leds: &[RGB8], max_milliamp: f32) -> u8 {
// }
// slice[slice.len() - 1] = first;
//}
// if buf[0] == '%' {
// match buf[0] {
// }
// wcode_ptr = 0;
// } el
//
// if buf[0] == b'r' {
// for l in leds.iter_mut() {
// *l = hsv2rgb_u8(0.0, 1.0, 1.0).into();
// }
// } else if buf[0] == b'y' {
// for l in leds.iter_mut() {
// *l = hsv2rgb_u8(60.0, 1.0, 1.0).into();
// }
// } else if buf[0] == b'w' {
// for l in leds.iter_mut() {
// *l = hsv2rgb_u8(0.0, 0.0, 1.0).into();
// }
// } else if buf[0] == b'm' {
// for l in leds.iter_mut() {
// *l = hsv2rgb_u8(300.0, 1.0, 1.0).into();
// }
// } else {
// for l in leds.iter_mut() {
// *l = hsv2rgb_u8(90.0, 1.0, 1.0).into();
// }
// }

Loading…
Cancel
Save