betabrite 0.0.2 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (45) hide show
  1. data/.autotest +7 -0
  2. data/EXAMPLES +28 -73
  3. data/History.txt +16 -0
  4. data/Manifest.txt +35 -0
  5. data/{README → README.txt} +58 -52
  6. data/Rakefile +11 -0
  7. data/lib/betabrite.rb +6 -120
  8. data/lib/betabrite/autotest.rb +43 -0
  9. data/lib/betabrite/base.rb +86 -0
  10. data/lib/betabrite/files.rb +4 -0
  11. data/lib/betabrite/files/dots.rb +24 -0
  12. data/lib/betabrite/files/file_dsl.rb +18 -0
  13. data/lib/betabrite/files/string.rb +22 -0
  14. data/lib/betabrite/files/text.rb +122 -0
  15. data/lib/{memory → betabrite}/memory.rb +27 -5
  16. data/lib/betabrite/serial.rb +28 -0
  17. data/lib/{string.rb → betabrite/string.rb} +41 -15
  18. data/lib/betabrite/usb.rb +64 -0
  19. data/script/alloc.rb +21 -0
  20. data/script/clear_memory.rb +16 -0
  21. data/script/client.rb +39 -0
  22. data/script/dots_file.rb +35 -0
  23. data/script/server.rb +12 -0
  24. data/script/sign_test.rb +17 -0
  25. data/script/stock_alloc.rb +81 -0
  26. data/script/stock_client.rb +40 -0
  27. data/script/stockdata.rb +65 -0
  28. data/test/helper.rb +6 -0
  29. data/test/{tc_many_mem.rb → test_many_mem.rb} +6 -10
  30. data/test/{tc_memory.rb → test_memory.rb} +11 -24
  31. data/test/{tc_set_string.rb → test_set_string.rb} +5 -9
  32. data/test/test_string.rb +34 -0
  33. data/test/test_text_file.rb +19 -0
  34. data/test/test_usb_betabrite.rb +94 -0
  35. metadata +94 -60
  36. data/CHANGELOG +0 -10
  37. data/NOTES +0 -29
  38. data/lib/bb_version.rb +0 -3
  39. data/lib/files/dotsfile.rb +0 -24
  40. data/lib/files/stringfile.rb +0 -22
  41. data/lib/files/textfile.rb +0 -114
  42. data/test/bb_override.rb +0 -5
  43. data/test/tc_string.rb +0 -20
  44. data/test/tc_text_file.rb +0 -18
  45. 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,4 @@
1
+ require 'betabrite/files/file_dsl'
2
+ require 'betabrite/files/string'
3
+ require 'betabrite/files/text'
4
+ require 'betabrite/files/dots'
@@ -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
- class BetaBrite
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
- #BetaBrite::STX << COMMAND_CODE << @label << @type << @locked <<
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
- class BetaBrite
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 to_s
68
- "#{0x1a.chr}#{@charset}#{0x1c.chr}#{@color}#{@string}"
79
+ def +(other)
80
+ self.to_s + other.to_s
69
81
  end
70
82
 
71
- def method_missing(sym, *args)
72
- if args.length > 0 && sym.to_s =~ /^set_(color|charset)$/
73
- class_name = $1
83
+ def rgb(rgb_color)
84
+ self.color = "#{rgb_color}"
85
+ self
86
+ end
74
87
 
75
- const_sym = class_name == 'color' ? :Color : :CharSet
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
- klass = self.class.const_get const_sym
78
- if klass.const_defined? args.first.upcase.to_sym
79
- return send("#{class_name}=".to_sym,
80
- klass.const_get(args.first.upcase.to_sym))
81
- else
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