-
Notifications
You must be signed in to change notification settings - Fork 0
/
sim.rb
132 lines (110 loc) · 2.87 KB
/
sim.rb
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
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
require 'ncurses'
require 'optparse'
@mode = :WS2801
def get_color(r, g, b)
return Ncurses::COLOR_PAIR("#{r > 0 ? 1 : 0}#{g > 0 ? 1: 0}#{b > 0 ? 1 : 0}".to_i(2))
end
def set_pixel(x, y, r, g, b)
Ncurses::attrset(get_color(r, g, b))
Ncurses::mvaddstr(y, x, " ")
end
def set_buffer(x, y, r, g, b)
if @buffer.nil?
@buffer = []
end
@buffer.push({ coord: [x, y], color: [r, g, b] })
end
def pixelx(i)
if ((i - (i % 12)) / 12) % 2 == 0
i % 12
else
11 - (i % 12)
end
end
def pixely(i)
(i - (i % 12)) / 12
end
def draw_pixel(buf)
if buf.map(&:nil?).inject(false) { |n,p| n || p }
puts "Not enough bytes"
else
if @mode != :WS2801
set_pixel(pixelx(buf[0]), pixely(buf[0]), buf[1], buf[2], buf[3])
else
set_buffer(pixelx(buf[0]), pixely(buf[0]), buf[1], buf[2], buf[3])
end
end
buf.clear
end
def draw_screen()
return if @buffer.nil?
@buffer.each do |data|
set_pixel(data[:coord][0], data[:coord][1], data[:color][0], data[:color][1], data[:color][2])
end
@buffer = []
end
def process_byte(io, buf)
byte = io.getbyte
case byte
when 0xFF then draw_pixel(buf)
when 0xFE then draw_screen()
else
buf.push(byte)
end
end
options = {}
parser = OptionParser.new do |opts|
opts.banner = "Usage: sim.rb [options] PIPE"
opts.on("-m", "--mode [WS2801]", "Select simulation mode (WS2801|WS2812)") do |m|
raise "Unknown mode: #{m}" unless [ "WS2801", "WS2812" ].include?(m)
@mode = m.to_sym
end
end
parser.parse!(ARGV)
if ARGV[0].nil?
puts parser.banner
exit 1
end
serial_pipe = ARGV[0]
if !File.exists?(serial_pipe) or !File.pipe?(serial_pipe)
puts "File #{serial_pipe} is not a valid pipe or does not exist"
exit 1
end
begin
Ncurses::initscr()
Ncurses::noecho()
Ncurses::cbreak()
Ncurses::nodelay(Ncurses::stdscr, TRUE)
Ncurses::curs_set(0)
if !(Ncurses::has_colors?())
raise "Colours no available :("
end
if (Ncurses.COLS < 12) or (Ncurses.LINES < 14)
raise "Screen too small!"
end
Ncurses::start_color()
Ncurses::init_pair(0, Ncurses::COLOR_BLACK, Ncurses::COLOR_BLACK)
Ncurses::init_pair(1, Ncurses::COLOR_BLUE, Ncurses::COLOR_BLUE)
Ncurses::init_pair(2, Ncurses::COLOR_GREEN, Ncurses::COLOR_GREEN)
Ncurses::init_pair(3, Ncurses::COLOR_CYAN, Ncurses::COLOR_CYAN)
Ncurses::init_pair(4, Ncurses::COLOR_RED, Ncurses::COLOR_RED)
Ncurses::init_pair(5, Ncurses::COLOR_MAGENTA, Ncurses::COLOR_MAGENTA)
Ncurses::init_pair(6, Ncurses::COLOR_YELLOW, Ncurses::COLOR_YELLOW)
Ncurses::init_pair(7, Ncurses::COLOR_WHITE, Ncurses::COLOR_WHITE)
io = File.open(serial_pipe, "r+")
buf = []
while (:restart)
process_byte(io, buf)
if ((ch = Ncurses::getch()) != Ncurses::ERR)
if (ch == Ncurses::KEY_RESIZE)
Ncurses::erase()
window_size_changed = true
else
break
end
end
end
ensure
Ncurses::curs_set(1)
Ncurses::endwin()
end