bitsy_lang/sim/ext/
video.rs

1use super::*;
2
3#[derive(Debug)]
4pub struct Video {
5    signal: u8,
6    hsync: bool,
7    vsync: bool,
8    frame_buffer: String,
9    disabled: bool,
10    initialized: bool,
11}
12
13impl Video {
14    pub fn new() -> Video {
15        Video {
16            signal: 0,
17            hsync: false,
18            vsync: false,
19            frame_buffer: String::new(),
20            disabled: false,
21            initialized: false,
22        }
23    }
24
25    pub fn disable(&mut self) {
26        self.disabled = true;
27    }
28}
29
30impl ExtInstance for Video {
31    fn incoming_ports(&self) -> Vec<PortName> { vec!["signal".to_string(), "hsync".to_string(), "vsync".to_string()] }
32
33    fn update(&mut self, portname: &PortName, value: value::Value) -> Vec<(PortName, value::Value)> {
34        if value.is_x() {
35            return vec![];
36        }
37        if portname == "signal" {
38            self.signal = value.try_into().unwrap();
39        } else if portname == "hsync" {
40            self.hsync = value.try_into().unwrap();
41        } else if portname == "vsync" {
42            self.vsync = value.try_into().unwrap();
43        }
44        vec![]
45    }
46
47    fn clock(&mut self) -> Vec<(PortName, Value)> {
48        if !self.disabled {
49            use std::fmt::Write;
50            let c: char = " ░▒▓".chars().collect::<Vec<char>>()[self.signal as usize];
51
52            write!(self.frame_buffer, "{c}{c}").unwrap();
53            if self.hsync {
54                writeln!(self.frame_buffer).unwrap();
55            }
56
57            if self.vsync {
58                std::thread::sleep(std::time::Duration::from_millis(30));
59
60                // clear screen
61                print!("\x1B[2J");
62
63                // move cursor to the upper left corner
64                print!("\x1B[H");
65
66                println!("{}", self.frame_buffer);
67                self.frame_buffer.clear();
68            }
69        }
70        vec![]
71    }
72
73    fn reset(&mut self) -> Vec<(PortName, Value)>{
74        if !self.disabled {
75            if !self.initialized {
76                ctrlc::set_handler(move || {
77                    // show the cursor
78                    println!("\x1B[?25h");
79                    std::process::exit(0);
80                }).unwrap();
81            }
82
83            // hide the cursor
84            print!("\x1B[?25l");
85
86            // clear the screen
87            print!("\x1B[2J");
88        }
89
90        self.initialized = true;
91
92        vec![]
93    }
94}