1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
|
const FONT_WIDTH = 8 # glyph width in pixels
const FONT_HEIGHT = 16 # glyph height in pixels (8x16 vga bitmap font)
const FG_COLOR = 0xd0d0d0
const BG_COLOR = 0x101018
const CURSOR_COLOR = 0x50fa7b
global console = {
column = 0, row = 0, scale = 1, shown = :false, cursor_x = 0, cursor_y = 0, blink = 0,
# cell size in pixels at the current zoom
cell_width = fn(self) FONT_WIDTH * self.scale,
cell_height = fn(self) FONT_HEIGHT * self.scale,
columns = fn(self) fb_width() / self:cell_width(),
rows = fn(self) fb_height() / self:cell_height(),
draw_glyph = fn(self, column, row, character) do
const origin_x = column * self:cell_width()
const origin_y = row * self:cell_height()
fill_rect(origin_x, origin_y, self:cell_width(), self:cell_height(), BG_COLOR) # clear the cell
const code = character:ascii()
if code < 32 return :nil
if code > 127 return :nil
const glyph = FONT[code - 32]
for glyph_row in 0..FONT_HEIGHT do
const bits = glyph[glyph_row]
for glyph_col in 0..FONT_WIDTH do
if (bits shr glyph_col) band 1 == 1 fill_rect(origin_x + glyph_col * self.scale, origin_y + glyph_row * self.scale, self.scale, self.scale, FG_COLOR)
end
end
end,
newline = fn(self) do
self.column = 0
self.row += 1
if self.row >= self:rows() do
fb_scroll(self:cell_height(), BG_COLOR)
self.row = self:rows() - 1
end
end,
# we dont do shift/cntrl, thats a job for future me lmao
# NOTE: future me kinda delt with it, i was mad drunk
putc = fn(self, character) do
const code = character:ascii()
if code == 10 do self:newline() return :nil end # \n
if code == 13 do self.column = 0 return :nil end # \r
if code == 8 do # backspace: move left
if self.column > 0 self.column -= 1
return :nil
end
if code < 32 return :nil
self:draw_glyph(self.column, self.row, character)
self.column += 1
if self.column >= self:columns() self:newline()
end,
clear = fn(self) do
fill_rect(0, 0, fb_width(), fb_height(), BG_COLOR)
self.column = 0
self.row = 0
end,
cursor_clear = fn(self) do
if self.shown do
fill_rect(self.cursor_x * self:cell_width(), self.cursor_y * self:cell_height(), self:cell_width(), self:cell_height(), BG_COLOR)
self.shown = :false
end
end,
cursor_show = fn(self) do
self.cursor_x = self.column
self.cursor_y = self.row
fill_rect(self.cursor_x * self:cell_width(), self.cursor_y * self:cell_height(), self:cell_width(), self:cell_height(), CURSOR_COLOR)
self.shown = :true
end,
# render every byte the serial mirror has buffered
drain = fn(self) do
let byte = serial_next()
while byte >= 0 do self:putc(string.of_ascii(byte)) byte = serial_next() end
end,
}
global puts = fn(text) serial_puts(text)
global flush_console = fn() do
console:cursor_clear()
console:drain()
console.blink = 0
console:cursor_show()
end
global on_tick = fn(ticks) do
let byte = serial_next()
if byte >= 0 do
console:cursor_clear()
console:putc(string.of_ascii(byte))
console:drain()
console.blink = 0
console:cursor_show()
return :nil
end
if proc_exited() do
console:cursor_clear()
puts("% ")
console:drain()
console.blink = 0
console:cursor_show()
return :nil
end
console.blink += 1
if console.blink >= 50 do
console.blink = 0
if console.shown console:cursor_clear() else console:cursor_show()
end
end
|