From d4bc8781d9cd9b8540f64743d91e5784cfdd57a7 Mon Sep 17 00:00:00 2001 From: trivernis Date: Sat, 2 May 2020 14:40:23 +0200 Subject: [PATCH] Add run loop for runtime - Add send instruction to send the rgb values to the strip (since setting them and sending them is bs) - Remove sending behaviour from rgb registers --- README.md | 3 +- src/bin/lsambler.rs | 5 +- src/bin/lsvm.rs | 26 +++++++ src/ledstrip_controller.rs | 7 +- src/registers.rs | 51 ++++--------- src/runtime.rs | 142 ++++++++++++++++++++++++++++--------- src/tokens.rs | 141 +++++++++++++++++++++++------------- 7 files changed, 252 insertions(+), 123 deletions(-) diff --git a/README.md b/README.md index 8369ef9..7aedf87 100644 --- a/README.md +++ b/README.md @@ -28,6 +28,7 @@ A virtual machine for controlling a wifi led strip. | je (rgd, rgi, rgl) | jumps to rgl if rgd == rgi | 0x22 | | pause (rgd) | pauses for rgd milliseconds | 0xF0 | | cmd (rgd) | executes the command in rgd | 0xF1 | +| send (rcr, rcg, rcb) | sends the values stored in the color registers to the strip | 0xF2 ### Registers @@ -44,7 +45,7 @@ A virtual machine for controlling a wifi led strip. | rgl | label | 4 bytes | 0x09 | - changing the state register results in turning the strip on/off -- changing the r/g/b registers results in changing the color +- the rcr, rcg and rcb registers store the rgb value of the strip - the rgd register is the default register for storing data - the rgp register stores a pointer to "memory" space - the rgi register stores the input for operations that require two input values diff --git a/src/bin/lsambler.rs b/src/bin/lsambler.rs index afef969..d403993 100644 --- a/src/bin/lsambler.rs +++ b/src/bin/lsambler.rs @@ -1,8 +1,8 @@ use ledstrip_vm::registers::get_register_code_by_name; use ledstrip_vm::tokens::{ AddToken, ClearToken, CmdToken, CopyToken, DivToken, ExitToken, GotoToken, JeToken, JgToken, - JlToken, LabelToken, LoadToken, LshToken, ModToken, MulToken, PauseToken, RshToken, SetToken, - SubToken, Token, WriteToken, + JlToken, LabelToken, LoadToken, LshToken, ModToken, MulToken, PauseToken, RshToken, SendToken, + SetToken, SubToken, Token, WriteToken, }; use std::fs::{read_to_string, File}; use std::io; @@ -92,6 +92,7 @@ fn get_token(line: &str) -> Option> { "je" => some_box!(JeToken), "pause" => some_box!(PauseToken), "cmd" => some_box!(CmdToken), + "send" => some_box!(SendToken), _ => None, } } diff --git a/src/bin/lsvm.rs b/src/bin/lsvm.rs index b6faf34..0b3c716 100644 --- a/src/bin/lsvm.rs +++ b/src/bin/lsvm.rs @@ -1,5 +1,31 @@ +use ledstrip_vm::runtime::Runtime; +use std::fs::read; use std::io; +use structopt::StructOpt; + +#[derive(StructOpt, Debug)] +struct Opts { + #[structopt(short = "i", name = "input")] + input_file: String, + + #[structopt(short = "a", name = "address")] + ip: String, + + #[structopt(short = "p", name = "port")] + port: usize, +} fn main() -> io::Result<()> { + let opts: Opts = Opts::from_args(); + let bytecode = read(opts.input_file)?; + + let mut runtime = Runtime::new(&opts.ip, opts.port); + runtime.parse_bytecode(bytecode); + + match runtime.run() { + Ok(code) => println!("Runtime exited with code {}", code), + Err(e) => println!("Runtime exited with error {:?}", e), + } + Ok(()) } diff --git a/src/ledstrip_controller.rs b/src/ledstrip_controller.rs index c979e03..da11e94 100644 --- a/src/ledstrip_controller.rs +++ b/src/ledstrip_controller.rs @@ -27,6 +27,7 @@ pub enum ProgramStripCommand { SevenJumping = 0x38, } +#[derive(Debug)] pub struct LedStripController { stream: TcpStream, pub r: u8, @@ -78,7 +79,11 @@ impl LedStripController { fn create_message(data: &[u8]) -> Vec { let mut data = data.clone().to_vec(); data.append(&mut vec![0x0f]); - data.push(data.iter().sum::() & 255); + let mut sum = 0u128; + for i in &data { + sum += *i as u128; + } + data.push(sum as u8 & 255); data } diff --git a/src/registers.rs b/src/registers.rs index a1c418c..21d45b3 100644 --- a/src/registers.rs +++ b/src/registers.rs @@ -41,42 +41,48 @@ pub trait Register { fn get(&self) -> T; } +#[derive(Debug, Clone)] pub struct Rcs { value: bool, strip_controller: Rc>, } +#[derive(Debug, Clone)] pub struct Rcr { value: u8, - strip_controller: Rc>, } +#[derive(Debug, Clone)] pub struct Rcg { value: u8, - strip_controller: Rc>, } +#[derive(Debug, Clone)] pub struct Rcb { value: u8, - strip_controller: Rc>, } +#[derive(Debug, Clone)] pub struct Rgd { value: u32, } +#[derive(Debug, Clone)] pub struct Rgp { value: u32, } +#[derive(Debug, Clone)] pub struct Rgi { value: u32, } +#[derive(Debug, Clone)] pub struct Rgo { value: u32, } +#[derive(Debug, Clone)] pub struct Rgl { value: u32, } @@ -91,29 +97,20 @@ impl Rcs { } impl Rcr { - pub fn new(strip_controller: Rc>) -> Self { - Self { - value: 0, - strip_controller, - } + pub fn new() -> Self { + Self { value: 0 } } } impl Rcg { - pub fn new(strip_controller: Rc>) -> Self { - Self { - value: 0, - strip_controller, - } + pub fn new() -> Self { + Self { value: 0 } } } impl Rcb { - pub fn new(strip_controller: Rc>) -> Self { - Self { - value: 0, - strip_controller, - } + pub fn new() -> Self { + Self { value: 0 } } } @@ -169,12 +166,6 @@ impl Register for Rcs { impl Register for Rcr { fn set(&mut self, value: u8) { self.value = value; - let mut controller = self.strip_controller.borrow_mut(); - let g = controller.g; - let b = controller.b; - controller - .send_rgb_color(self.value, g, b) - .expect("failed send rgb color"); } fn get(&self) -> u8 { @@ -185,12 +176,6 @@ impl Register for Rcr { impl Register for Rcg { fn set(&mut self, value: u8) { self.value = value; - let mut controller = self.strip_controller.borrow_mut(); - let r = controller.r; - let b = controller.b; - controller - .send_rgb_color(r, self.value, b) - .expect("failed to send rgb color"); } fn get(&self) -> u8 { @@ -201,12 +186,6 @@ impl Register for Rcg { impl Register for Rcb { fn set(&mut self, value: u8) { self.value = value; - let mut controller = self.strip_controller.borrow_mut(); - let r = controller.r; - let g = controller.g; - controller - .send_rgb_color(r, g, self.value) - .expect("failed to send rgb color") } fn get(&self) -> u8 { diff --git a/src/runtime.rs b/src/runtime.rs index 33ae0f5..6de30f4 100644 --- a/src/runtime.rs +++ b/src/runtime.rs @@ -1,15 +1,20 @@ -use crate::ledstrip_controller::LedStripController; -use crate::ledstrip_controller::ProgramStripCommand::RedGradual; +use crate::ledstrip_controller::{LedStripController, StateStripCommand}; use crate::registers::{ - Rcb, Rcg, Rcr, Rcs, Register, Rgd, Rgi, Rgl, Rgo, Rgp, RCB, RCG, RCR, RCS, RGD, RGI, RGL, RGO, - RGP, + Rcb, Rcg, Rcr, Rcs, Register, Rgd, Rgi, Rgl, Rgo, Rgp, RCB, RCG, RCR, RGD, RGI, RGL, RGO, RGP, }; -use crate::tokens::Token; -use std::cell::{Ref, RefCell}; +use crate::tokens::{ + AddToken, ClearToken, CmdToken, CopyToken, DivToken, ExitToken, FromBytecode, GotoToken, + JeToken, JgToken, JlToken, LabelToken, LoadToken, LshToken, ModToken, MulToken, PauseToken, + RshToken, SendToken, SetToken, SubToken, Token, WriteToken, T_ADD, T_CLEAR, T_CMD, T_COPY, + T_DIV, T_EXIT, T_GOTO, T_JE, T_JG, T_JL, T_LABEL, T_LOAD, T_LSH, T_MOD, T_MUL, T_PAUSE, T_RSH, + T_SEND, T_SET, T_SUB, T_WRITE, +}; +use std::cell::RefCell; use std::collections::HashMap; use std::io; use std::rc::Rc; +#[derive(Clone)] pub struct Runtime { pub rcs: Rcs, pub rcr: Rcr, @@ -21,31 +26,31 @@ pub struct Runtime { pub rgo: Rgo, pub rgl: Rgl, pub memory: HashMap, - text: Vec>, - labels: HashMap, - strip_controller: Rc>, + text: Rc>>>, + labels: HashMap, + pub strip_controller: Rc>, exit: Option, - current_index: u128, + current_index: usize, } impl Runtime { pub fn new(ip: &str, port: usize) -> Self { let controller = LedStripController::new(ip, port) .expect("failed to establish a connection to the led strip"); - let mut controller = Rc::new(RefCell::new(controller)); + let controller = Rc::new(RefCell::new(controller)); Self { rcs: Rcs::new(controller.clone()), - rcr: Rcr::new(controller.clone()), - rcg: Rcg::new(controller.clone()), - rcb: Rcb::new(controller.clone()), + rcr: Rcr::new(), + rcg: Rcg::new(), + rcb: Rcb::new(), rgd: Rgd::new(), rgp: Rgp::new(), rgi: Rgi::new(), rgo: Rgo::new(), rgl: Rgl::new(), memory: HashMap::new(), - text: Vec::new(), + text: Rc::new(RefCell::new(Vec::new())), labels: HashMap::new(), strip_controller: controller, exit: None, @@ -53,26 +58,97 @@ impl Runtime { } } - pub fn exit(&mut self, code: u8) { - self.exit = Some(code); + /// Parses a vector containing the bytecode into a vector of tokens + /// that can be executed + pub fn parse_bytecode(&mut self, bytecode: Vec) { + let mut code_iter = bytecode.iter(); + + while let Some(instruction) = code_iter.next() { + match *instruction { + T_EXIT => self + .text + .borrow_mut() + .push(Box::new(ExitToken::from_bytecode(&[ + instruction, + code_iter.next().unwrap(), + ]))), + T_SET => self + .text + .borrow_mut() + .push(Box::new(SetToken::from_bytecode(&[ + instruction, + code_iter.next().unwrap(), + code_iter.next().unwrap(), + ]))), + T_COPY => self + .text + .borrow_mut() + .push(Box::new(CopyToken::from_bytecode(&[ + instruction, + code_iter.next().unwrap(), + code_iter.next().unwrap(), + ]))), + T_LOAD => self.text.borrow_mut().push(Box::new(LoadToken)), + T_CLEAR => self + .text + .borrow_mut() + .push(Box::new(ClearToken::from_bytecode(&[ + instruction, + code_iter.next().unwrap(), + ]))), + T_WRITE => self.text.borrow_mut().push(Box::new(WriteToken)), + T_LABEL => self.text.borrow_mut().push(Box::new(LabelToken)), + T_GOTO => self.text.borrow_mut().push(Box::new(GotoToken)), + T_ADD => self.text.borrow_mut().push(Box::new(AddToken)), + T_SUB => self.text.borrow_mut().push(Box::new(SubToken)), + T_MUL => self.text.borrow_mut().push(Box::new(MulToken)), + T_DIV => self.text.borrow_mut().push(Box::new(DivToken)), + T_MOD => self.text.borrow_mut().push(Box::new(ModToken)), + T_LSH => self.text.borrow_mut().push(Box::new(LshToken)), + T_RSH => self.text.borrow_mut().push(Box::new(RshToken)), + T_JG => self.text.borrow_mut().push(Box::new(JgToken)), + T_JL => self.text.borrow_mut().push(Box::new(JlToken)), + T_JE => self.text.borrow_mut().push(Box::new(JeToken)), + T_PAUSE => self.text.borrow_mut().push(Box::new(PauseToken)), + T_CMD => self.text.borrow_mut().push(Box::new(CmdToken)), + T_SEND => self.text.borrow_mut().push(Box::new(SendToken)), + _ => panic!("unknown instruction {}", instruction), + }; + } } - /* - pub fn get_register(&mut self, code: u8) -> Option<&mut impl Register> { - match code { - RCS => Some(&mut self.rcs), - RCR => Some(&mut self.rcr), - RCG => Some(&mut self.rcg), - RCB => Some(&mut self.rcb), - RGD => Some(&mut self.rgd), - RGP => Some(&mut self.rgp), - RGI => Some(&mut self.rgi), - RGO => Some(&mut self.rgo), - RGL => Some(&mut self.rgl), - _ => None, + /// Executes the text stored in the runtime + pub fn run(&mut self) -> io::Result { + let text_ref = self.text.clone(); + let text = text_ref.borrow_mut(); + while self.current_index < text.len() { + let token = text.get(self.current_index).unwrap(); + token.invoke(self)?; + + if let Some(code) = self.exit { + self.strip_controller + .borrow_mut() + .set_state(StateStripCommand::Off) + .unwrap(); + return Ok(0); + } + + self.current_index += 1; } - }*/ + self.strip_controller + .borrow_mut() + .set_state(StateStripCommand::Off) + .unwrap(); + Ok(0) + } + + /// Exists the program with a specified error code + pub fn exit(&mut self, code: u8) { + self.exit = Some(code); + } + + /// Returns the 1byte register referenced by the code pub fn get_1byte_register(&mut self, code: u8) -> Option>> { match code { RCR => Some(Box::new(&mut self.rcr)), @@ -82,6 +158,7 @@ impl Runtime { } } + /// Returns the 4byte register referenced by the code pub fn get_4byte_register(&mut self, code: u8) -> Option>> { match code { RGD => Some(Box::new(&mut self.rgd)), @@ -95,9 +172,10 @@ impl Runtime { /// Creates a new label at the current position pub fn create_label(&mut self, id: u32) { - self.labels.insert(id, self.current_index + 1); + self.labels.insert(id, self.current_index); } + /// Jumps to a specified label pub fn jump(&mut self, label: u32) -> io::Result<()> { self.current_index = *self .labels diff --git a/src/tokens.rs b/src/tokens.rs index d4cc3b0..ec29dfc 100644 --- a/src/tokens.rs +++ b/src/tokens.rs @@ -1,32 +1,31 @@ use crate::registers::{Register, RCS}; use crate::runtime::Runtime; -use std::borrow::BorrowMut; use std::io; -use std::panic::resume_unwind; use std::thread::sleep; use std::time::Duration; -const T_NOP: u8 = 0x00; -const T_EXIT: u8 = 0x01; -const T_SET: u8 = 0x02; -const T_COPY: u8 = 0x03; -const T_LOAD: u8 = 0x04; -const T_CLEAR: u8 = 0x05; -const T_WRITE: u8 = 0x06; -const T_LABEL: u8 = 0x07; -const T_GOTO: u8 = 0x08; -const T_ADD: u8 = 0x10; -const T_SUB: u8 = 0x11; -const T_MUL: u8 = 0x12; -const T_DIV: u8 = 0x13; -const T_MOD: u8 = 0x14; -const T_LSH: u8 = 0x15; -const T_RSH: u8 = 0x16; -const T_JG: u8 = 0x20; -const T_JL: u8 = 0x21; -const T_JE: u8 = 0x22; -const T_PAUSE: u8 = 0xF0; -const T_CMD: u8 = 0xF1; +pub const T_NOP: u8 = 0x00; +pub const T_EXIT: u8 = 0x01; +pub const T_SET: u8 = 0x02; +pub const T_COPY: u8 = 0x03; +pub const T_LOAD: u8 = 0x04; +pub const T_CLEAR: u8 = 0x05; +pub const T_WRITE: u8 = 0x06; +pub const T_LABEL: u8 = 0x07; +pub const T_GOTO: u8 = 0x08; +pub const T_ADD: u8 = 0x10; +pub const T_SUB: u8 = 0x11; +pub const T_MUL: u8 = 0x12; +pub const T_DIV: u8 = 0x13; +pub const T_MOD: u8 = 0x14; +pub const T_LSH: u8 = 0x15; +pub const T_RSH: u8 = 0x16; +pub const T_JG: u8 = 0x20; +pub const T_JL: u8 = 0x21; +pub const T_JE: u8 = 0x22; +pub const T_PAUSE: u8 = 0xF0; +pub const T_CMD: u8 = 0xF1; +pub const T_SEND: u8 = 0xF2; pub trait Token { fn to_bytecode(&self) -> Vec; @@ -34,9 +33,10 @@ pub trait Token { } pub trait FromBytecode { - fn from_bytecode(code: &[u8]) -> Self; + fn from_bytecode(code: &[&u8]) -> Self; } +#[derive(Debug, Clone)] pub struct NopToken; impl Token for NopToken { @@ -49,11 +49,12 @@ impl Token for NopToken { } impl FromBytecode for NopToken { - fn from_bytecode(_: &[u8]) -> Self { + fn from_bytecode(_: &[&u8]) -> Self { Self } } +#[derive(Debug, Clone)] pub struct ExitToken { pub register: u8, } @@ -79,11 +80,12 @@ impl Token for ExitToken { } impl FromBytecode for ExitToken { - fn from_bytecode(code: &[u8]) -> Self { - Self { register: code[1] } + fn from_bytecode(code: &[&u8]) -> Self { + Self { register: *code[1] } } } +#[derive(Debug, Clone)] pub struct SetToken { pub value: u8, pub register: u8, @@ -108,14 +110,15 @@ impl Token for SetToken { } impl FromBytecode for SetToken { - fn from_bytecode(code: &[u8]) -> Self { + fn from_bytecode(code: &[&u8]) -> Self { Self { - value: code[1], - register: code[2], + value: *code[1], + register: *code[2], } } } +#[derive(Debug, Clone)] pub struct CopyToken { pub register_1: u8, pub register_2: u8, @@ -148,14 +151,15 @@ impl Token for CopyToken { } impl FromBytecode for CopyToken { - fn from_bytecode(code: &[u8]) -> Self { + fn from_bytecode(code: &[&u8]) -> Self { Self { - register_1: code[1], - register_2: code[2], + register_1: *code[1], + register_2: *code[2], } } } +#[derive(Debug, Clone)] pub struct LoadToken; impl Token for LoadToken { @@ -176,11 +180,12 @@ impl Token for LoadToken { } impl FromBytecode for LoadToken { - fn from_bytecode(_: &[u8]) -> Self { + fn from_bytecode(_: &[&u8]) -> Self { Self } } +#[derive(Debug, Clone)] pub struct ClearToken { pub register: u8, } @@ -204,11 +209,12 @@ impl Token for ClearToken { } impl FromBytecode for ClearToken { - fn from_bytecode(code: &[u8]) -> Self { - Self { register: code[1] } + fn from_bytecode(code: &[&u8]) -> Self { + Self { register: *code[1] } } } +#[derive(Debug, Clone)] pub struct WriteToken; impl Token for WriteToken { @@ -224,11 +230,12 @@ impl Token for WriteToken { } impl FromBytecode for WriteToken { - fn from_bytecode(_: &[u8]) -> Self { + fn from_bytecode(_: &[&u8]) -> Self { Self } } +#[derive(Debug, Clone)] pub struct LabelToken; impl Token for LabelToken { @@ -244,11 +251,12 @@ impl Token for LabelToken { } impl FromBytecode for LabelToken { - fn from_bytecode(_: &[u8]) -> Self { + fn from_bytecode(_: &[&u8]) -> Self { Self } } +#[derive(Debug, Clone)] pub struct GotoToken; impl Token for GotoToken { @@ -262,11 +270,12 @@ impl Token for GotoToken { } impl FromBytecode for GotoToken { - fn from_bytecode(_: &[u8]) -> Self { + fn from_bytecode(_: &[&u8]) -> Self { Self } } +#[derive(Debug, Clone)] pub struct AddToken; impl Token for AddToken { @@ -282,11 +291,12 @@ impl Token for AddToken { } impl FromBytecode for AddToken { - fn from_bytecode(_: &[u8]) -> Self { + fn from_bytecode(_: &[&u8]) -> Self { Self } } +#[derive(Debug, Clone)] pub struct SubToken; impl Token for SubToken { @@ -302,11 +312,12 @@ impl Token for SubToken { } impl FromBytecode for SubToken { - fn from_bytecode(_: &[u8]) -> Self { + fn from_bytecode(_: &[&u8]) -> Self { Self } } +#[derive(Debug, Clone)] pub struct MulToken; impl Token for MulToken { @@ -322,11 +333,12 @@ impl Token for MulToken { } impl FromBytecode for MulToken { - fn from_bytecode(_: &[u8]) -> Self { + fn from_bytecode(_: &[&u8]) -> Self { Self } } +#[derive(Debug, Clone)] pub struct DivToken; impl Token for DivToken { @@ -342,11 +354,12 @@ impl Token for DivToken { } impl FromBytecode for DivToken { - fn from_bytecode(_: &[u8]) -> Self { + fn from_bytecode(_: &[&u8]) -> Self { Self } } +#[derive(Debug, Clone)] pub struct ModToken; impl Token for ModToken { @@ -362,11 +375,12 @@ impl Token for ModToken { } impl FromBytecode for ModToken { - fn from_bytecode(_: &[u8]) -> Self { + fn from_bytecode(_: &[&u8]) -> Self { Self } } +#[derive(Debug, Clone)] pub struct LshToken; impl Token for LshToken { @@ -382,11 +396,12 @@ impl Token for LshToken { } impl FromBytecode for LshToken { - fn from_bytecode(_: &[u8]) -> Self { + fn from_bytecode(_: &[&u8]) -> Self { Self } } +#[derive(Debug, Clone)] pub struct RshToken; impl Token for RshToken { @@ -402,11 +417,12 @@ impl Token for RshToken { } impl FromBytecode for RshToken { - fn from_bytecode(_: &[u8]) -> Self { + fn from_bytecode(_: &[&u8]) -> Self { Self } } +#[derive(Debug, Clone)] pub struct JgToken; impl Token for JgToken { @@ -424,11 +440,12 @@ impl Token for JgToken { } impl FromBytecode for JgToken { - fn from_bytecode(_: &[u8]) -> Self { + fn from_bytecode(_: &[&u8]) -> Self { Self } } +#[derive(Debug, Clone)] pub struct JlToken; impl Token for JlToken { @@ -446,11 +463,12 @@ impl Token for JlToken { } impl FromBytecode for JlToken { - fn from_bytecode(_: &[u8]) -> Self { + fn from_bytecode(_: &[&u8]) -> Self { Self } } +#[derive(Debug, Clone)] pub struct JeToken; impl Token for JeToken { @@ -468,11 +486,12 @@ impl Token for JeToken { } impl FromBytecode for JeToken { - fn from_bytecode(_: &[u8]) -> Self { + fn from_bytecode(_: &[&u8]) -> Self { Self } } +#[derive(Debug, Clone)] pub struct PauseToken; impl Token for PauseToken { @@ -488,11 +507,12 @@ impl Token for PauseToken { } impl FromBytecode for PauseToken { - fn from_bytecode(_: &[u8]) -> Self { + fn from_bytecode(_: &[&u8]) -> Self { Self } } +#[derive(Debug, Clone)] pub struct CmdToken; impl Token for CmdToken { @@ -508,7 +528,26 @@ impl Token for CmdToken { } impl FromBytecode for CmdToken { - fn from_bytecode(_: &[u8]) -> Self { + fn from_bytecode(_: &[&u8]) -> Self { Self } } + +pub struct SendToken; + +impl Token for SendToken { + fn to_bytecode(&self) -> Vec { + vec![T_SEND] + } + + fn invoke(&self, runtime: &mut Runtime) -> io::Result<()> { + let r = runtime.rcr.get(); + let g = runtime.rcg.get(); + let b = runtime.rcb.get(); + + runtime + .strip_controller + .borrow_mut() + .send_rgb_color(r, g, b) + } +}