|
|
|
@ -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();
|
|
|
|
|
// }
|
|
|
|
|
// }
|
|
|
|
|