Hacked some more on this.
This commit is contained in:
parent
4f8f02e146
commit
c05d696b5c
2 changed files with 197 additions and 4 deletions
13
README.md
Normal file
13
README.md
Normal file
|
@ -0,0 +1,13 @@
|
|||
# ttylia - Julia fractals on tty
|
||||
|
||||
This is intended to write the output to a DIGITAL VT220 terminal.
|
||||
|
||||
```
|
||||
sudo chown $USER /dev/ttyUSB0
|
||||
stty -F /dev/ttyUSB0 raw 19200
|
||||
cargo run > /dev/ttyUSB0
|
||||
```
|
||||
|
||||
Note: 19200 bits per second gives about 2 frames per second (a frame
|
||||
is 40x24 chars, a char is 8 data bits + start and stop bit, so 10
|
||||
bits).
|
188
src/main.rs
188
src/main.rs
|
@ -1,9 +1,17 @@
|
|||
use num_complex::Complex32;
|
||||
use std::{io::{self, Write}, thread::sleep, time::{Duration, Instant}};
|
||||
|
||||
const CHARS: &[u8; 33] = b"@. .,:;-~+*i=xom\\//11II77OO77MMMM";
|
||||
const CHARS: &[u8; 13] = b"\xA1\xA2\xA3\xA4\xA5\xA6\xA7\xA8\xA9\xA9\xA9\xA9\xA9";
|
||||
|
||||
fn main() {
|
||||
const CSI: u8 = b'\x9b'; // Start of control sequence, equivalent to "\x1B["
|
||||
|
||||
fn csi(code: &[u8]) -> Vec<u8> {
|
||||
let mut res = vec![CSI]; // or vec![0x1B, b'['] for 7-bit compat.
|
||||
res.extend(code);
|
||||
res
|
||||
}
|
||||
|
||||
fn main() -> Result<(), io::Error> {
|
||||
const WIDTH: u16 = 40;
|
||||
const HEIGHT: u16 = 24;
|
||||
const SY: f32 = 3.2 / (HEIGHT as f32);
|
||||
|
@ -17,10 +25,22 @@ fn main() {
|
|||
let mut rotor = Complex32 { re: 1., im: frame_time.as_secs_f32() * 0.2 };
|
||||
let mut frame = 0;
|
||||
let mut out = io::stdout().lock();
|
||||
out.write_all(b"\x1B[2J").unwrap();
|
||||
|
||||
out.write_all(&csi(b"2J"))?;
|
||||
out.write_all(&csi(b"?25l"))?;
|
||||
out.write_all(b"\x1B)@\x1B~")?; // Enable custom character set
|
||||
define_pixels(&mut out);
|
||||
//out.write_all(b"\r\n\x1B#6 Hello \xA0\xA1\xA2\xA3\xA4\xA5\xA6 World\r\n").unwrap();
|
||||
//return;
|
||||
|
||||
loop {
|
||||
let frame_start = Instant::now();
|
||||
c *= rotor;
|
||||
/*eprintln!("{:.4} / {:+.4} {:+.4} / {:+.4}",
|
||||
c.l1_norm(),
|
||||
(c.l1_norm() - 1.),
|
||||
(rotor.l1_norm() - 1.),
|
||||
(c.l1_norm() - 1.) * (rotor.l1_norm() - 1.));*/
|
||||
if c.norm_sqr() > 2. {
|
||||
rotor *= (1. / rotor.norm_sqr()).sqrt();
|
||||
}
|
||||
|
@ -61,9 +81,169 @@ fn main() {
|
|||
}
|
||||
}
|
||||
|
||||
fn define_pixels(out: &mut impl Write) {
|
||||
let chars = [
|
||||
chardef([
|
||||
0b1111_1110,
|
||||
0b1111_1110,
|
||||
0b1111_1110,
|
||||
0b1111_1110,
|
||||
0b1111_1110,
|
||||
0b1111_1110,
|
||||
0b1111_1110,
|
||||
0b1111_1110,
|
||||
0b1111_1110,
|
||||
0b0000_0000,
|
||||
]),
|
||||
chardef([
|
||||
0b0000_0000,
|
||||
0b0000_0000,
|
||||
0b0000_0000,
|
||||
0b0000_0000,
|
||||
0b0000_0000,
|
||||
0b0000_0000,
|
||||
0b0000_0000,
|
||||
0b0000_0000,
|
||||
0b0000_0000,
|
||||
0b0000_0000,
|
||||
]),
|
||||
chardef([ // 1 pixel
|
||||
0b0000_0000,
|
||||
0b0000_0000,
|
||||
0b0000_0000,
|
||||
0b0000_0000,
|
||||
0b0001_0000,
|
||||
0b0000_0000,
|
||||
0b0000_0000,
|
||||
0b0000_0000,
|
||||
0b0000_0000,
|
||||
0b0000_0000,
|
||||
]),
|
||||
chardef([ // 4 pixels
|
||||
0b0000_0000,
|
||||
0b0000_0000,
|
||||
0b0000_0000,
|
||||
0b0010_1000,
|
||||
0b0000_0000,
|
||||
0b0010_1000,
|
||||
0b0000_0000,
|
||||
0b0000_0000,
|
||||
0b0000_0000,
|
||||
0b0000_0000,
|
||||
]),
|
||||
chardef([ // 5 pixels
|
||||
0b0000_0000,
|
||||
0b0000_0000,
|
||||
0b0100_0100,
|
||||
0b0000_0000,
|
||||
0b0001_0000,
|
||||
0b0000_0000,
|
||||
0b0100_0100,
|
||||
0b0000_0000,
|
||||
0b0000_0000,
|
||||
0b0000_0000,
|
||||
]),
|
||||
chardef([ // 6 pixels
|
||||
0b0000_0000,
|
||||
0b0100_1000,
|
||||
0b0000_0000,
|
||||
0b0000_0000,
|
||||
0b0100_1000,
|
||||
0b0000_0000,
|
||||
0b0000_0000,
|
||||
0b0100_1000,
|
||||
0b0000_0000,
|
||||
0b0000_0000,
|
||||
]),
|
||||
chardef([ // 9 pixels
|
||||
0b0000_0010,
|
||||
0b0001_0000,
|
||||
0b1000_0000,
|
||||
0b0000_0010,
|
||||
0b0001_0000,
|
||||
0b1000_0000,
|
||||
0b0000_0010,
|
||||
0b0001_0000,
|
||||
0b1000_0000,
|
||||
0b0000_0000,
|
||||
]),
|
||||
chardef([ // half
|
||||
0b1010_1010,
|
||||
0b0101_0100,
|
||||
0b1010_1010,
|
||||
0b0101_0100,
|
||||
0b1010_1010,
|
||||
0b0101_0100,
|
||||
0b1010_1010,
|
||||
0b0101_0100,
|
||||
0b1010_1010,
|
||||
0b0000_0000,
|
||||
]),
|
||||
chardef([
|
||||
0b1010_1010,
|
||||
0b0111_0100,
|
||||
0b1010_1010,
|
||||
0b0101_1100,
|
||||
0b1110_1010,
|
||||
0b0101_0100,
|
||||
0b1010_1010,
|
||||
0b0101_1100,
|
||||
0b1010_1010,
|
||||
0b0000_0000,
|
||||
]),
|
||||
chardef([
|
||||
0b1110_1110,
|
||||
0b0111_0110,
|
||||
0b1011_1010,
|
||||
0b0101_0100,
|
||||
0b1010_1010,
|
||||
0b0101_0100,
|
||||
0b1010_1010,
|
||||
0b0101_0100,
|
||||
0b1010_1010,
|
||||
0b0000_0000,
|
||||
]),
|
||||
];
|
||||
//eprintln!("Defining {} chars", chars.len());
|
||||
//eprintln!("Def: {chars:?}");
|
||||
out.write_all(b"\x1BP1;1;1{@").unwrap();
|
||||
if let Some((first, rest)) = chars.split_first() {
|
||||
out.write_all(first).unwrap();
|
||||
for ch in rest {
|
||||
out.write_all(b";").unwrap();
|
||||
out.write_all(ch).unwrap();
|
||||
}
|
||||
}
|
||||
out.write_all(b"\x1B\\").unwrap();
|
||||
}
|
||||
|
||||
fn chardef(bits: [u8; 10]) -> [u8;17] {
|
||||
let mut result = [0;17];
|
||||
for y in 0..6 {
|
||||
for x in 0..8 {
|
||||
if bits[y] & (0b10000000 >> x) > 0 {
|
||||
result[x] |= 1 << y;
|
||||
}
|
||||
}
|
||||
}
|
||||
for y in 0..4 {
|
||||
for x in 0..8 {
|
||||
if bits[y+6] & (0b10000000 >> x) > 0 {
|
||||
result[9 + x] |= 1 << y;
|
||||
}
|
||||
}
|
||||
}
|
||||
for c in &mut result {
|
||||
*c += b'?';
|
||||
}
|
||||
result[8] = b'/';
|
||||
//eprintln!("chardef2: {}", String::from_utf8_lossy(&result));
|
||||
result
|
||||
}
|
||||
|
||||
|
||||
fn pixel(i: u8) -> u8 {
|
||||
CHARS[usize::from(i)]
|
||||
// u32::from_be_bytes([0xff, i * 6, i + i / 2, i.saturating_mul(8)])
|
||||
}
|
||||
|
||||
fn julia(z: Complex32, c: Complex32, max_i: u8) -> u8 {
|
||||
|
|
Loading…
Add table
Reference in a new issue