betabrite 0.0.2 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|