betabrite 0.0.2 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.autotest +7 -0
- data/EXAMPLES +28 -73
- data/History.txt +16 -0
- data/Manifest.txt +35 -0
- data/{README → README.txt} +58 -52
- data/Rakefile +11 -0
- data/lib/betabrite.rb +6 -120
- data/lib/betabrite/autotest.rb +43 -0
- data/lib/betabrite/base.rb +86 -0
- data/lib/betabrite/files.rb +4 -0
- data/lib/betabrite/files/dots.rb +24 -0
- data/lib/betabrite/files/file_dsl.rb +18 -0
- data/lib/betabrite/files/string.rb +22 -0
- data/lib/betabrite/files/text.rb +122 -0
- data/lib/{memory → betabrite}/memory.rb +27 -5
- data/lib/betabrite/serial.rb +28 -0
- data/lib/{string.rb → betabrite/string.rb} +41 -15
- data/lib/betabrite/usb.rb +64 -0
- data/script/alloc.rb +21 -0
- data/script/clear_memory.rb +16 -0
- data/script/client.rb +39 -0
- data/script/dots_file.rb +35 -0
- data/script/server.rb +12 -0
- data/script/sign_test.rb +17 -0
- data/script/stock_alloc.rb +81 -0
- data/script/stock_client.rb +40 -0
- data/script/stockdata.rb +65 -0
- data/test/helper.rb +6 -0
- data/test/{tc_many_mem.rb → test_many_mem.rb} +6 -10
- data/test/{tc_memory.rb → test_memory.rb} +11 -24
- data/test/{tc_set_string.rb → test_set_string.rb} +5 -9
- data/test/test_string.rb +34 -0
- data/test/test_text_file.rb +19 -0
- data/test/test_usb_betabrite.rb +94 -0
- metadata +94 -60
- data/CHANGELOG +0 -10
- data/NOTES +0 -29
- data/lib/bb_version.rb +0 -3
- data/lib/files/dotsfile.rb +0 -24
- data/lib/files/stringfile.rb +0 -22
- data/lib/files/textfile.rb +0 -114
- data/test/bb_override.rb +0 -5
- data/test/tc_string.rb +0 -20
- data/test/tc_text_file.rb +0 -18
- data/test/ts_bb.rb +0 -7
@@ -0,0 +1,43 @@
|
|
1
|
+
require 'betabrite'
|
2
|
+
|
3
|
+
module Autotest::BetaBrite
|
4
|
+
@@first_run = true
|
5
|
+
|
6
|
+
def self.hook(klass, *args, &block)
|
7
|
+
Autotest.add_hook :ran_command do |at|
|
8
|
+
if at.results.last =~ /^.* (\d+) failures, (\d+) errors$/
|
9
|
+
bb = klass.new(*args) do |sign|
|
10
|
+
sign.allocate do |memory|
|
11
|
+
memory.text('A', 4096)
|
12
|
+
memory.string('0', 128)
|
13
|
+
memory.string('1', 128)
|
14
|
+
end
|
15
|
+
|
16
|
+
failures = BetaBrite::String.new("#{$1} failures").red
|
17
|
+
errors = BetaBrite::String.new("#{$2} errors").red
|
18
|
+
failures.green if $1 == '0'
|
19
|
+
errors.green if $2 == '0'
|
20
|
+
block.call(failures, errors) if block
|
21
|
+
|
22
|
+
sign.stringfile('0') do
|
23
|
+
print failures
|
24
|
+
end
|
25
|
+
sign.stringfile('1') do
|
26
|
+
print errors
|
27
|
+
end
|
28
|
+
|
29
|
+
if @@first_run
|
30
|
+
sign.textfile do
|
31
|
+
print stringfile('0')
|
32
|
+
print " "
|
33
|
+
print stringfile('1')
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
bb.write_memory! if @@first_run
|
38
|
+
bb.write!
|
39
|
+
@@first_run = false if @@first_run
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,86 @@
|
|
1
|
+
module BetaBrite
|
2
|
+
VERSION = '1.0.0'
|
3
|
+
|
4
|
+
class Base
|
5
|
+
include BetaBrite::Files
|
6
|
+
|
7
|
+
# = Synopsis
|
8
|
+
# This class assembles all packets (different files) and yields the data
|
9
|
+
# that needs to be written back to the caller of the BetaBrite#write method.
|
10
|
+
HEADER = [ 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 ]
|
11
|
+
STX = 0x02.chr
|
12
|
+
ETX = 0x03.chr
|
13
|
+
EOT = 0x04.chr
|
14
|
+
ESC = 0x1b.chr
|
15
|
+
DLE = 0x10.chr
|
16
|
+
STRING = 0x14.chr
|
17
|
+
CR = 0x0d.chr
|
18
|
+
MEMORY_CODE = "E$"
|
19
|
+
|
20
|
+
# Beta Brite sign
|
21
|
+
SIGN_TYPE = 0x5a.chr
|
22
|
+
|
23
|
+
attr_accessor :sleep_time
|
24
|
+
attr_reader :string_files, :text_files, :dots_files, :memory
|
25
|
+
|
26
|
+
def initialize
|
27
|
+
# Default address is "00" which means broadcast to all signs
|
28
|
+
@sign_address = [ 0x30, 0x30 ]
|
29
|
+
@string_files = []
|
30
|
+
@text_files = []
|
31
|
+
@dots_files = []
|
32
|
+
@memory = []
|
33
|
+
|
34
|
+
# This shouldn't change except for unit testing
|
35
|
+
@sleep_time = 0
|
36
|
+
yield self if block_given?
|
37
|
+
end
|
38
|
+
|
39
|
+
def textfile(label = 'A', &block)
|
40
|
+
@text_files << Text.new(label, &block)
|
41
|
+
end
|
42
|
+
|
43
|
+
def stringfile(label, message = nil, &block)
|
44
|
+
@string_files << Files::String.new(label, message, &block)
|
45
|
+
end
|
46
|
+
|
47
|
+
def dotsfile(label, rows = nil, columns = nil, picture = nil, &block)
|
48
|
+
@dots_files << Dots.new(label, rows, columns, picture,&block)
|
49
|
+
end
|
50
|
+
|
51
|
+
def allocate(&block)
|
52
|
+
@memory.push(*(BetaBrite::Memory::Factory.find(&block)))
|
53
|
+
end
|
54
|
+
|
55
|
+
def clear_memory!
|
56
|
+
@memory = []
|
57
|
+
self.write_memory!
|
58
|
+
end
|
59
|
+
|
60
|
+
# Get the message to be sent to the sign
|
61
|
+
def message
|
62
|
+
header +
|
63
|
+
@text_files.each { |tf| tf.to_s }.join('') +
|
64
|
+
@string_files.each { |tf| tf.to_s }.join('') +
|
65
|
+
@dots_files.each { |tf| tf.to_s }.join('') +
|
66
|
+
tail
|
67
|
+
end
|
68
|
+
|
69
|
+
def memory_message
|
70
|
+
"#{header}#{STX}#{MEMORY_CODE}#{@memory.map { |packet| packet.to_s }.join('')}#{tail}"
|
71
|
+
end
|
72
|
+
|
73
|
+
private
|
74
|
+
|
75
|
+
def header
|
76
|
+
header_str = HEADER.collect { |a| a.chr }.join
|
77
|
+
"#{header_str}#{SIGN_TYPE}#{@sign_address.collect { |a| a.chr }.join}"
|
78
|
+
end
|
79
|
+
alias :inspect :header
|
80
|
+
public :inspect
|
81
|
+
|
82
|
+
def tail
|
83
|
+
EOT
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module BetaBrite
|
2
|
+
module Files
|
3
|
+
class Dots
|
4
|
+
COMMAND_CODE = 0x49.chr
|
5
|
+
|
6
|
+
attr_accessor :label, :rows, :columns, :picture
|
7
|
+
|
8
|
+
def initialize(label, rows, columns, picture, &block)
|
9
|
+
@label = label
|
10
|
+
@rows = rows
|
11
|
+
@columns = columns
|
12
|
+
@picture = picture
|
13
|
+
instance_eval(&block) if block
|
14
|
+
end
|
15
|
+
|
16
|
+
def to_s
|
17
|
+
string = "#{BetaBrite::Base::STX}#{COMMAND_CODE}#{@label.to_s}" +
|
18
|
+
"#{sprintf('%02x', @rows)}#{sprintf('%02x', @columns)}" +
|
19
|
+
"#{picture.join(BetaBrite::Base::CR)}#{BetaBrite::Base::CR}"
|
20
|
+
end
|
21
|
+
alias :to_str :to_s
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module BetaBrite
|
2
|
+
module FileDSL
|
3
|
+
def print(some_string)
|
4
|
+
@message = @message ? @message + some_string : some_string
|
5
|
+
end
|
6
|
+
|
7
|
+
def string(some_string)
|
8
|
+
BetaBrite::String.new(some_string)
|
9
|
+
end
|
10
|
+
|
11
|
+
::BetaBrite::String.constants.each do |constant|
|
12
|
+
next unless constant =~ /^[A-Z_]*$/
|
13
|
+
define_method(:"#{constant.downcase}") do
|
14
|
+
::BetaBrite::String.const_get(constant)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module BetaBrite
|
2
|
+
module Files
|
3
|
+
class String
|
4
|
+
COMMAND_CODE = 'G'
|
5
|
+
|
6
|
+
attr_accessor :label, :message
|
7
|
+
include BetaBrite::FileDSL
|
8
|
+
|
9
|
+
def initialize(label = nil, message = nil, &block)
|
10
|
+
@label = label
|
11
|
+
@message = message
|
12
|
+
instance_eval(&block) if block
|
13
|
+
end
|
14
|
+
|
15
|
+
def to_s
|
16
|
+
"#{BetaBrite::Base::STX}#{COMMAND_CODE}#{@label.to_s}" +
|
17
|
+
"#{@message.to_s}#{BetaBrite::Base::ETX}"
|
18
|
+
end
|
19
|
+
alias :to_str :to_s
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,122 @@
|
|
1
|
+
module BetaBrite
|
2
|
+
module Files
|
3
|
+
class Text
|
4
|
+
WRITE = 0x41.chr
|
5
|
+
READ = 0x42.chr
|
6
|
+
|
7
|
+
class Position
|
8
|
+
MIDDLE = 0x20.chr
|
9
|
+
TOP = 0x22.chr
|
10
|
+
BOTTOM = 0x26.chr
|
11
|
+
FILL = 0x30.chr
|
12
|
+
LEFT = 0x31.chr
|
13
|
+
RIGHT = 0x32.chr
|
14
|
+
end
|
15
|
+
|
16
|
+
class Mode
|
17
|
+
# Standard Modes
|
18
|
+
ROTATE = 0x61.chr # Message travels right to left
|
19
|
+
HOLD = 0x62.chr # Message remains stationary
|
20
|
+
FLASH = 0x63.chr # Message remains stationary and flashes
|
21
|
+
ROLL_UP = 0x65.chr # Message is pushed up by new message
|
22
|
+
ROLL_DOWN = 0x66.chr # Message is pushed down by new message
|
23
|
+
ROLL_LEFT = 0x67.chr # Message is pushed left by a new message
|
24
|
+
ROLL_RIGHT = 0x68.chr # Message is pushed right by a new message
|
25
|
+
WIPE_UP = 0x69.chr # Message is wiped over bottom to top
|
26
|
+
WIPE_DOWN = 0x6A.chr # Message is wiped over top to bottom
|
27
|
+
WIPE_LEFT = 0x6B.chr # Message is wiped over right to left
|
28
|
+
WIPE_RIGHT = 0x6C.chr # Message is wiped over left to right
|
29
|
+
SCROLL = 0x6D.chr # New message pushes up if 2 line sign
|
30
|
+
AUTOMODE = 0x6F.chr # Various modes are called automatically
|
31
|
+
ROLL_IN = 0x70.chr # Message pushed toward center of display
|
32
|
+
ROLL_OUT = 0x71.chr # Message pushed away from center of display
|
33
|
+
WIPE_IN = 0x72.chr # Message wiped over in inward motion
|
34
|
+
WIPE_OUT = 0x73.chr # Message wiped over in outward motion
|
35
|
+
COMPRESSED_ROTATE = 0x74.chr # Left to right, chars half normal width
|
36
|
+
EXPLODE = 0x75.chr # Message flies apart (Alpha 3.0)
|
37
|
+
CLOCK = 0x76.chr # Wipe in clockwise direction (Alpha 3.0)
|
38
|
+
|
39
|
+
# Special Modes
|
40
|
+
TWINKLE = 0x6E.chr << 0x30.chr # Message will twinkle
|
41
|
+
SPARKLE = 0x6E.chr << 0x31.chr # Message will sparkle
|
42
|
+
SNOW = 0x6E.chr << 0x32.chr # Message will snow
|
43
|
+
INTERLOCK = 0x6E.chr << 0x33.chr # Message will interlock
|
44
|
+
SWITCH = 0x6E.chr << 0x34.chr # Message will switch
|
45
|
+
SLIDE = 0x6E.chr << 0x35.chr # Message will slide
|
46
|
+
SPRAY = 0x6E.chr << 0x36.chr # Message will spray across
|
47
|
+
STARBURST = 0x6E.chr << 0x37.chr # Explodes message to screen
|
48
|
+
WELCOME = 0x6E.chr << 0x38.chr # The world "Welcome" is written
|
49
|
+
SLOT_MACHINE= 0x6E.chr << 0x39.chr # Slot Machine shows up
|
50
|
+
NEWS_FLASH = 0x6E.chr << 0x3A.chr # News flash animation
|
51
|
+
TRUMPET = 0x6E.chr << 0x3B.chr # Trumpet animation
|
52
|
+
CYCLE_COLORS= 0x6E.chr << 0x43.chr # Color changes from one to another
|
53
|
+
|
54
|
+
# Special Graphics
|
55
|
+
THANK_YOU = [0x6E, 0x53].pack('C*') # "Thank You" in script
|
56
|
+
FLAG = [0x6E, 0x54].pack('C*') # American Flag
|
57
|
+
NO_SMOKING = [0x6E, 0x55].pack('C*') # No smoking
|
58
|
+
DRINK_DRIVE = [0x6E, 0x56].pack('C*') # Don't drink and drive
|
59
|
+
ANIMAL_ANIM = [0x6E, 0x57].pack('C*') # Animal animation
|
60
|
+
FIREWORKS = [0x6E, 0x58].pack('C*') # Fireworks animation
|
61
|
+
BALLOONS = [0x6E, 0x59].pack('C*') # Balloon animation
|
62
|
+
CHERRY_BOMB = [0x6E, 0x5A].pack('C*') # A bomb animation or a smile
|
63
|
+
SMILE = [0x6E, 0x5A].pack('C*') # A bomb animation or a smile
|
64
|
+
end
|
65
|
+
|
66
|
+
attr_accessor :label, :position, :mode, :message
|
67
|
+
|
68
|
+
include BetaBrite::FileDSL
|
69
|
+
|
70
|
+
def initialize(label = 'A', &block)
|
71
|
+
@position = Position::MIDDLE
|
72
|
+
@label = label
|
73
|
+
@message = nil
|
74
|
+
@mode = Mode::ROTATE
|
75
|
+
instance_eval(&block) if block
|
76
|
+
end
|
77
|
+
|
78
|
+
def stringfile(label)
|
79
|
+
"#{BetaBrite::Base::DLE}#{label}"
|
80
|
+
end
|
81
|
+
|
82
|
+
def dotsfile(label)
|
83
|
+
"#{BetaBrite::Base::STRING}#{label}"
|
84
|
+
end
|
85
|
+
|
86
|
+
def to_s
|
87
|
+
"#{combine}#{checksum(combine)}"
|
88
|
+
end
|
89
|
+
|
90
|
+
def checksum(string)
|
91
|
+
total = 0
|
92
|
+
0.upto(string.length - 1) do |i|
|
93
|
+
total += string[i]
|
94
|
+
end
|
95
|
+
|
96
|
+
sprintf("%04x", total).upcase
|
97
|
+
end
|
98
|
+
|
99
|
+
Mode.constants.each do |constant|
|
100
|
+
next unless constant =~ /^[A-Z_]*$/
|
101
|
+
define_method(:"#{constant.downcase}") do
|
102
|
+
@mode = Mode.const_get(constant)
|
103
|
+
self
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
Position.constants.each do |constant|
|
108
|
+
next unless constant =~ /^[A-Z_]*$/
|
109
|
+
define_method(:"#{constant.downcase}") do
|
110
|
+
@position = Position.const_get(constant)
|
111
|
+
self
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
private
|
116
|
+
def combine
|
117
|
+
"#{BetaBrite::Base::STX}#{WRITE}#{@label}#{BetaBrite::Base::ESC}" +
|
118
|
+
"#{@position}#{@mode}#{@message}#{BetaBrite::Base::ETX}"
|
119
|
+
end
|
120
|
+
end
|
121
|
+
end
|
122
|
+
end
|
@@ -1,4 +1,4 @@
|
|
1
|
-
|
1
|
+
module BetaBrite
|
2
2
|
class Memory
|
3
3
|
COMMAND_CODE = "E$"
|
4
4
|
TEXT = 'A'
|
@@ -7,7 +7,7 @@ class BetaBrite
|
|
7
7
|
LOCKED = 'L'
|
8
8
|
UNLOCKED = 'U'
|
9
9
|
def self.clear
|
10
|
-
BetaBrite::STX << COMMAND_CODE
|
10
|
+
BetaBrite::Base::STX << COMMAND_CODE
|
11
11
|
end
|
12
12
|
|
13
13
|
attr_accessor :label, :type, :locked, :size, :time
|
@@ -27,12 +27,34 @@ class BetaBrite
|
|
27
27
|
end
|
28
28
|
|
29
29
|
def format
|
30
|
-
#
|
31
|
-
@label << @type << @locked << @size.upcase << @time
|
30
|
+
"#{@label}#{@type}#{@locked}#{@size.upcase}#{@time}"
|
32
31
|
end
|
33
32
|
|
34
33
|
alias :to_s :format
|
35
34
|
|
35
|
+
class Factory
|
36
|
+
attr_reader :memory_list
|
37
|
+
class << self
|
38
|
+
def find(&block)
|
39
|
+
@memory_list = []
|
40
|
+
instance_eval(&block)
|
41
|
+
@memory_list
|
42
|
+
end
|
43
|
+
|
44
|
+
def string(label, size)
|
45
|
+
@memory_list << String.new(label, size)
|
46
|
+
end
|
47
|
+
|
48
|
+
def text(label, size)
|
49
|
+
@memory_list << Text.new(label, size)
|
50
|
+
end
|
51
|
+
|
52
|
+
def dots(label, rows, columns)
|
53
|
+
@memory_list << Dots.new(label, rows, columns)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
36
58
|
class String < Memory
|
37
59
|
def initialize(label, size)
|
38
60
|
super( :label => label,
|
@@ -69,7 +91,7 @@ class BetaBrite
|
|
69
91
|
|
70
92
|
class Clear < Memory
|
71
93
|
def to_s
|
72
|
-
"#{BetaBrite::STX}#{COMMAND_CODE}"
|
94
|
+
"#{BetaBrite::Base::STX}#{COMMAND_CODE}"
|
73
95
|
end
|
74
96
|
end
|
75
97
|
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module BetaBrite
|
2
|
+
class Serial < Base
|
3
|
+
def initialize(serialport)
|
4
|
+
@serialport = serialport
|
5
|
+
super()
|
6
|
+
end
|
7
|
+
|
8
|
+
def write_memory!
|
9
|
+
sp = SerialPort.new(@serialport, 9600, 8, 1, SerialPort::NONE)
|
10
|
+
characters = 0
|
11
|
+
memory_message.split(//).each do |chr|
|
12
|
+
sleep 1 if characters < 6
|
13
|
+
sp.write chr
|
14
|
+
characters += 1
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def write!
|
19
|
+
sp = SerialPort.new(@serialport, 9600, 8, 1, SerialPort::NONE)
|
20
|
+
characters = 0
|
21
|
+
message.split(//).each do |chr|
|
22
|
+
sleep 1 if characters < 6
|
23
|
+
sp.write chr
|
24
|
+
characters += 1
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -1,4 +1,4 @@
|
|
1
|
-
|
1
|
+
module BetaBrite
|
2
2
|
# This class encapsulates a string and attributes about the string such as
|
3
3
|
# color, character set, and also contains special characters.
|
4
4
|
class String
|
@@ -54,6 +54,18 @@ class BetaBrite
|
|
54
54
|
end
|
55
55
|
attr_accessor :color, :charset, :string
|
56
56
|
|
57
|
+
class << self
|
58
|
+
# Break up a string into betabrite strings
|
59
|
+
def parse(string)
|
60
|
+
string.split(/#{0x1a.chr}/).select { |s|
|
61
|
+
s.length > 0
|
62
|
+
}.map { |s|
|
63
|
+
data = /(.)#{0x1c.chr}Z?([^Z]{6}|[^Z])(.*)$/.match(s)
|
64
|
+
new(data[3], :color => data[2], :charset => data[1])
|
65
|
+
}
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
57
69
|
def initialize(string, opts = {})
|
58
70
|
args = { :color => Color::GREEN,
|
59
71
|
:charset => CharSet::SEVEN_HIGH
|
@@ -64,25 +76,39 @@ class BetaBrite
|
|
64
76
|
yield self if block_given?
|
65
77
|
end
|
66
78
|
|
67
|
-
def
|
68
|
-
|
79
|
+
def +(other)
|
80
|
+
self.to_s + other.to_s
|
69
81
|
end
|
70
82
|
|
71
|
-
def
|
72
|
-
|
73
|
-
|
83
|
+
def rgb(rgb_color)
|
84
|
+
self.color = "#{rgb_color}"
|
85
|
+
self
|
86
|
+
end
|
74
87
|
|
75
|
-
|
88
|
+
def to_s
|
89
|
+
"#{0x1a.chr}#{@charset}#{0x1c.chr}" +
|
90
|
+
(@color.length > 1 ? "Z#{@color}" : "#{@color}") +
|
91
|
+
"#{@string}"
|
92
|
+
end
|
93
|
+
alias :to_str :to_s
|
94
|
+
|
95
|
+
Color.constants.each do |constant|
|
96
|
+
next unless constant =~ /^[A-Z_]*$/
|
97
|
+
define_method(:"#{constant.downcase}") do
|
98
|
+
@color = Color.const_get(constant)
|
99
|
+
self
|
100
|
+
end
|
101
|
+
define_method(:"#{constant.downcase}?") do
|
102
|
+
@color == Color.const_get(constant)
|
103
|
+
end
|
104
|
+
end
|
76
105
|
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
raise ArgumentError, "no constant #{args.first.upcase}", caller
|
83
|
-
end
|
106
|
+
CharSet.constants.each do |constant|
|
107
|
+
next unless constant =~ /^[A-Z_]*$/
|
108
|
+
define_method(:"#{constant.downcase}") do
|
109
|
+
@charset = CharSet.const_get(constant)
|
110
|
+
self
|
84
111
|
end
|
85
|
-
super
|
86
112
|
end
|
87
113
|
end
|
88
114
|
end
|