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
pull/1/head
trivernis 5 years ago
parent 1d3b54ff7f
commit d4bc8781d9

@ -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

@ -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<Box<dyn Token>> {
"je" => some_box!(JeToken),
"pause" => some_box!(PauseToken),
"cmd" => some_box!(CmdToken),
"send" => some_box!(SendToken),
_ => None,
}
}

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

@ -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<u8> {
let mut data = data.clone().to_vec();
data.append(&mut vec![0x0f]);
data.push(data.iter().sum::<u8>() & 255);
let mut sum = 0u128;
for i in &data {
sum += *i as u128;
}
data.push(sum as u8 & 255);
data
}

@ -41,42 +41,48 @@ pub trait Register<T> {
fn get(&self) -> T;
}
#[derive(Debug, Clone)]
pub struct Rcs {
value: bool,
strip_controller: Rc<RefCell<LedStripController>>,
}
#[derive(Debug, Clone)]
pub struct Rcr {
value: u8,
strip_controller: Rc<RefCell<LedStripController>>,
}
#[derive(Debug, Clone)]
pub struct Rcg {
value: u8,
strip_controller: Rc<RefCell<LedStripController>>,
}
#[derive(Debug, Clone)]
pub struct Rcb {
value: u8,
strip_controller: Rc<RefCell<LedStripController>>,
}
#[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<RefCell<LedStripController>>) -> Self {
Self {
value: 0,
strip_controller,
}
pub fn new() -> Self {
Self { value: 0 }
}
}
impl Rcg {
pub fn new(strip_controller: Rc<RefCell<LedStripController>>) -> Self {
Self {
value: 0,
strip_controller,
}
pub fn new() -> Self {
Self { value: 0 }
}
}
impl Rcb {
pub fn new(strip_controller: Rc<RefCell<LedStripController>>) -> Self {
Self {
value: 0,
strip_controller,
}
pub fn new() -> Self {
Self { value: 0 }
}
}
@ -169,12 +166,6 @@ impl Register<bool> for Rcs {
impl Register<u8> 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<u8> for Rcr {
impl Register<u8> 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<u8> for Rcg {
impl Register<u8> 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 {

@ -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<u32, u32>,
text: Vec<Box<dyn Token>>,
labels: HashMap<u32, u128>,
strip_controller: Rc<RefCell<LedStripController>>,
text: Rc<RefCell<Vec<Box<dyn Token>>>>,
labels: HashMap<u32, usize>,
pub strip_controller: Rc<RefCell<LedStripController>>,
exit: Option<u8>,
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<u8>) {
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<T>(&mut self, code: u8) -> Option<&mut impl Register<T>> {
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<u8> {
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<Box<&mut dyn Register<u8>>> {
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<Box<&mut dyn Register<u32>>> {
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

@ -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<u8>;
@ -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<u8> {
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)
}
}

Loading…
Cancel
Save