madrona-rad 0.2.7 → 0.3.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (74) hide show
  1. data/History.txt +6 -15
  2. data/Manifest.txt +38 -5
  3. data/README.rdoc +19 -7
  4. data/Rakefile +4 -3
  5. data/bin/rad +214 -130
  6. data/lib/examples/basic_blink.rb +10 -0
  7. data/lib/examples/blink_with_serial.rb +16 -0
  8. data/lib/examples/external_variable_fu.rb +21 -19
  9. data/lib/examples/external_variables.rb +0 -3
  10. data/lib/examples/hello_array2.rb +34 -1
  11. data/lib/examples/hello_array_eeprom.rb +4 -6
  12. data/lib/examples/hello_clock.rb +84 -0
  13. data/lib/examples/hello_eeprom.rb +3 -3
  14. data/lib/examples/hello_eeprom_lcdpa.rb +2 -2
  15. data/lib/examples/hello_format_print.rb +94 -0
  16. data/lib/examples/hello_spectra_sound.rb +38 -0
  17. data/lib/examples/hello_world.rb +3 -3
  18. data/lib/examples/hello_xbee.rb +12 -0
  19. data/lib/examples/midi_beat_box.rb +86 -0
  20. data/lib/examples/midi_scales.rb +94 -0
  21. data/lib/examples/servo_throttle.rb +11 -8
  22. data/lib/examples/software_serial.rb +10 -0
  23. data/lib/examples/twitter.rb +57 -0
  24. data/lib/libraries/AFSoftSerial/AFSoftSerial.cpp +321 -0
  25. data/lib/libraries/AFSoftSerial/AFSoftSerial.h +61 -0
  26. data/lib/libraries/{Servo → AFSoftSerial}/keywords.txt +18 -25
  27. data/lib/libraries/AF_XPort/AF_XPort.cpp +166 -0
  28. data/lib/libraries/AF_XPort/AF_XPort.h +48 -0
  29. data/lib/libraries/DS1307/DS1307.cpp +10 -9
  30. data/lib/libraries/DS1307/DS1307.h +6 -4
  31. data/lib/libraries/I2CEEPROM/I2CEEPROM.cpp +120 -0
  32. data/lib/libraries/I2CEEPROM/I2CEEPROM.h +70 -0
  33. data/lib/libraries/I2CEEPROM/keywords.txt +21 -0
  34. data/lib/libraries/LoopTimer/LoopTimer.cpp +35 -0
  35. data/lib/libraries/LoopTimer/LoopTimer.h +34 -0
  36. data/lib/libraries/LoopTimer/keywords.txt +27 -0
  37. data/lib/libraries/SWSerLCDpa/SWSerLCDpa.cpp +42 -48
  38. data/lib/libraries/SWSerLCDpa/SWSerLCDpa.h +11 -12
  39. data/lib/libraries/SWSerLCDsf/SWSerLCDsf.cpp +38 -0
  40. data/lib/libraries/SWSerLCDsf/SWSerLCDsf.h +9 -2
  41. data/lib/plugins/blink.rb +25 -0
  42. data/lib/plugins/blink_m.rb +3 -3
  43. data/lib/plugins/lcd_padding.rb +19 -0
  44. data/lib/plugins/midi.rb +60 -0
  45. data/lib/plugins/parallax_ping.rb +50 -0
  46. data/lib/plugins/servo_setup.rb +1 -1
  47. data/lib/plugins/twitter_connect.rb +145 -0
  48. data/lib/rad/README.rdoc +5 -0
  49. data/lib/rad/arduino_sketch.rb +91 -904
  50. data/lib/rad/darwin_installer.rb +23 -0
  51. data/lib/rad/generators/makefile/makefile.erb +1 -1
  52. data/lib/rad/generators/makefile/makefile.rb +3 -3
  53. data/lib/rad/hardware_library.rb +813 -0
  54. data/lib/rad/init.rb +4 -2
  55. data/lib/rad/linux_installer.rb +132 -0
  56. data/lib/rad/progressbar.rb +236 -0
  57. data/lib/rad/rad_processor.rb +56 -9
  58. data/lib/rad/rad_rewriter.rb +7 -2
  59. data/lib/rad/rad_type_checker.rb +1 -1
  60. data/lib/rad/sketch_compiler.rb +47 -0
  61. data/lib/rad/tasks/build_and_make.rake +41 -48
  62. data/lib/rad/version.rb +2 -2
  63. data/spec/examples/hello_world.rb +11 -0
  64. data/spec/examples/serial_motor.rb +12 -0
  65. data/spec/models/sketch_compiler_spec.rb +96 -0
  66. data/spec/sim/hello_world_spec.rb +0 -0
  67. data/test/hello_world_test/Makefile +436 -0
  68. data/test/hello_world_test/hello_world.cpp +23 -0
  69. data/test/test_array_processing.rb +1 -1
  70. data/test/test_plugin_loading.rb +1 -1
  71. data/test/test_translation_post_processing.rb +14 -70
  72. metadata +52 -39
  73. data/lib/examples/orig_servo_throttle.rb +0 -39
  74. data/lib/plugins/i2c_eeprom.rb +0 -70
data/lib/rad/init.rb CHANGED
@@ -5,10 +5,12 @@ unless defined?(PROJECT_DIR_NAME)
5
5
  PROJECT_DIR_NAME = a[a.length-1]
6
6
  end
7
7
 
8
- PLUGIN_C_VAR_TYPES = "int|void|unsigned|long|short|uint8_t|static|byte|char\\*"
8
+ PLUGIN_C_VAR_TYPES = "int|void|unsigned|long|short|uint8_t|static|byte|char\\*|uint8_t"
9
9
 
10
+ gem "ParseTree", "~>3.0.4"
11
+ gem "ruby2c", "~>1.0.0.6"
10
12
 
11
- %w(generators/makefile/makefile.rb rad_processor.rb rad_rewriter.rb rad_type_checker.rb variable_processing.rb arduino_sketch.rb arduino_plugin.rb tasks/rad.rb).each do |path|
13
+ %w(generators/makefile/makefile.rb rad_processor.rb rad_rewriter.rb rad_type_checker.rb variable_processing.rb arduino_sketch.rb arduino_plugin.rb hardware_library.rb tasks/rad.rb sketch_compiler.rb).each do |path|
12
14
  require File.expand_path("#{RAD_ROOT}/vendor/rad/#{path}")
13
15
  end
14
16
 
@@ -0,0 +1,132 @@
1
+ class LinuxInstaller
2
+
3
+ # this is the thing we actually run to make something happen
4
+ def self.install!
5
+ puts "Welcome to the RAD Linux Installer!"
6
+ puts "-----------------------------------"
7
+ puts "Let's begin."
8
+ puts
9
+
10
+ check_or_warn_for_usb_driver
11
+
12
+ # of course we need rubygems
13
+ # maybe just rely on the user installing rubygems, because the ubuntu one sux
14
+ #check_or_install_package("rubygems")
15
+ #%x{gem update --system}
16
+
17
+ # we need java to make this ship float
18
+ check_or_nag_package("sun-java5-jre")
19
+
20
+ # remove a package that interferes with the arduino usb/serial driver
21
+ check_or_remove_package("brltty")
22
+
23
+ # install pre-requisites
24
+ check_or_install_package("binutils-avr")
25
+ check_or_install_package("gcc-avr")
26
+ check_or_install_package("avr-libc")
27
+ check_or_install_package("unzip")
28
+ check_or_install_package("wget")
29
+
30
+ # remove a probably out of date avrdude
31
+ check_or_remove_package("avrdude")
32
+
33
+ # install pre-requisites for avrdude if we wanted to build from source
34
+ # nah, it comes with the arduino binary
35
+ #check_or_install_package("gcc")
36
+ #check_or_install_package("bison")
37
+ #check_or_install_package("flex")
38
+ check_or_install_arduino
39
+ end
40
+
41
+ def self.check_or_install_package(package_name)
42
+ package = %x{dpkg --get-selections | grep #{package_name}}
43
+ if package.include?("\tinstall")
44
+ puts "#{package_name} installed!"
45
+ else
46
+ puts "installing #{package_name}..."
47
+ %x{apt-get install -y #{package_name}}
48
+ end
49
+ end
50
+
51
+ def self.check_or_nag_package(package_name, custom_msg = nil)
52
+ package = %x{dpkg --get-selections | grep #{package_name}}
53
+ if package.include?("\tinstall")
54
+ puts "#{package_name} installed!"
55
+ else
56
+ puts "you will need to manually install #{package_name}! use the command below."
57
+ if custom_msg
58
+ puts custom_msg
59
+ else
60
+ puts "sudo apt-get install #{package_name}"
61
+ end
62
+ exit
63
+ end
64
+ end
65
+
66
+ def self.check_or_remove_package(package_name)
67
+ package = %x{dpkg --get-selections | grep #{package_name}}
68
+
69
+ #an easier way to check for installed packages?
70
+ if package.include?("\tinstall")
71
+ puts "removing #{package_name}..."
72
+ %x{apt-get remove -y #{package_name}}
73
+ else
74
+ puts "#{package_name} previously uninstalled!"
75
+ end
76
+ end
77
+
78
+ def self.check_or_warn_for_usb_driver
79
+
80
+ # check if usb device recognized by system
81
+ puts "Please plug in your arduino to your usb port... [hit enter to continue]"
82
+ STDIN.gets # we patiently wait
83
+
84
+ usb = %x{dmesg | tail | grep "FTDI USB Serial" | grep -c "now attached"}
85
+
86
+ if usb.to_i == 0
87
+ # maybe we can be nice here and offer to download and install the driver package
88
+ puts "the system is not recognizing your usb-serial driver, please re-install"
89
+ exit
90
+ end
91
+ end
92
+
93
+ def self.check_or_install_arduino
94
+ if File.exist?("/usr/local/arduino-0012")
95
+ puts "arduino software previously installed at /usr/local/arduino-0012 !"
96
+ else
97
+ puts "installing arduino software..."
98
+ %x{cd /usr/local/; wget http://arduino.cc/files/arduino-0012-linux.tgz}
99
+ %x{tar -C /usr/local -xzf /usr/local/arduino-0012-linux.tgz}
100
+
101
+ %x{ln -s /usr/local/arduino-0012/arduino ~/Desktop/arduino}
102
+
103
+ # gotta patch it so it can run from command line or anywhere
104
+ arduino_file = File.open("/usr/local/arduino-0012/arduino") {|f| f.read}
105
+ new_doc = arduino_file.split("\n")
106
+ new_doc[1] = "cd /usr/local/arduino-0012"
107
+ File.open("/usr/local/arduino-0012/arduino", "w") {|f| f.puts new_doc }
108
+
109
+ %x{mkdir -p /usr/local/arduino-0012/hardware/tools/avr/bin}
110
+ # there is a difference from what the makefile expects to where it is
111
+ %x{ln -s /usr/bin/avr-gcc /usr/local/arduino-0012/hardware/tools/avr/bin/avr-gcc}
112
+ %x{ln -s /usr/bin/avr-g++ /usr/local/arduino-0012/hardware/tools/avr/bin/avr-g++}
113
+ %x{ln -s /usr/bin/avr-ar /usr/local/arduino-0012/hardware/tools/avr/bin/avr-ar}
114
+ %x{ln -s /usr/bin/avr-objcopy /usr/local/arduino-0012/hardware/tools/avr/bin/avr-objcopy}
115
+ %x{ln -s /usr/local/arduino-0012/hardware/tools/avrdude /usr/local/arduino-0012/hardware/tools/avr/bin/avrdude}
116
+ %x{ln -s /usr/local/arduino-0012/hardware/tools/avrdude.conf /usr/local/arduino-0012/hardware/tools/avr/etc/avrdude.conf}
117
+
118
+
119
+ puts
120
+ puts "************************************************************************"
121
+ puts "** please add /usr/local/arduino-0012 to your path! **"
122
+ puts "** you will also need to run sudo update-alternatives --config java **"
123
+ puts "** to choose java-1.50-sun as the default java **"
124
+ puts "************************************************************************"
125
+ puts
126
+ end
127
+
128
+ end
129
+ end
130
+
131
+
132
+
@@ -0,0 +1,236 @@
1
+ #
2
+ # Ruby/ProgressBar - a text progress bar library
3
+ #
4
+ # Copyright (C) 2001-2005 Satoru Takabayashi <satoru@namazu.org>
5
+ # All rights reserved.
6
+ # This is free software with ABSOLUTELY NO WARRANTY.
7
+ #
8
+ # You can redistribute it and/or modify it under the terms
9
+ # of Ruby's license.
10
+ #
11
+
12
+ class ProgressBar
13
+ VERSION = "0.9"
14
+
15
+ def initialize (title, total, out = STDERR)
16
+ @title = title
17
+ @total = total
18
+ @out = out
19
+ @terminal_width = 80
20
+ @bar_mark = "o"
21
+ @current = 0
22
+ @previous = 0
23
+ @finished_p = false
24
+ @start_time = Time.now
25
+ @previous_time = @start_time
26
+ @title_width = 14
27
+ @format = "%-#{@title_width}s %3d%% %s %s"
28
+ @format_arguments = [:title, :percentage, :bar, :stat]
29
+ clear
30
+ show
31
+ end
32
+ attr_reader :title
33
+ attr_reader :current
34
+ attr_reader :total
35
+ attr_accessor :start_time
36
+
37
+ private
38
+ def fmt_bar
39
+ bar_width = do_percentage * @terminal_width / 100
40
+ sprintf("|%s%s|",
41
+ @bar_mark * bar_width,
42
+ " " * (@terminal_width - bar_width))
43
+ end
44
+
45
+ def fmt_percentage
46
+ do_percentage
47
+ end
48
+
49
+ def fmt_stat
50
+ if @finished_p then elapsed else eta end
51
+ end
52
+
53
+ def fmt_stat_for_file_transfer
54
+ if @finished_p then
55
+ sprintf("%s %s %s", bytes, transfer_rate, elapsed)
56
+ else
57
+ sprintf("%s %s %s", bytes, transfer_rate, eta)
58
+ end
59
+ end
60
+
61
+ def fmt_title
62
+ @title[0,(@title_width - 1)] + ":"
63
+ end
64
+
65
+ def convert_bytes (bytes)
66
+ if bytes < 1024
67
+ sprintf("%6dB", bytes)
68
+ elsif bytes < 1024 * 1000 # 1000kb
69
+ sprintf("%5.1fKB", bytes.to_f / 1024)
70
+ elsif bytes < 1024 * 1024 * 1000 # 1000mb
71
+ sprintf("%5.1fMB", bytes.to_f / 1024 / 1024)
72
+ else
73
+ sprintf("%5.1fGB", bytes.to_f / 1024 / 1024 / 1024)
74
+ end
75
+ end
76
+
77
+ def transfer_rate
78
+ bytes_per_second = @current.to_f / (Time.now - @start_time)
79
+ sprintf("%s/s", convert_bytes(bytes_per_second))
80
+ end
81
+
82
+ def bytes
83
+ convert_bytes(@current)
84
+ end
85
+
86
+ def format_time (t)
87
+ t = t.to_i
88
+ sec = t % 60
89
+ min = (t / 60) % 60
90
+ hour = t / 3600
91
+ sprintf("%02d:%02d:%02d", hour, min, sec);
92
+ end
93
+
94
+ # ETA stands for Estimated Time of Arrival.
95
+ def eta
96
+ if @current == 0
97
+ "ETA: --:--:--"
98
+ else
99
+ elapsed = Time.now - @start_time
100
+ eta = elapsed * @total / @current - elapsed;
101
+ sprintf("ETA: %s", format_time(eta))
102
+ end
103
+ end
104
+
105
+ def elapsed
106
+ elapsed = Time.now - @start_time
107
+ sprintf("Time: %s", format_time(elapsed))
108
+ end
109
+
110
+ def eol
111
+ if @finished_p then "\n" else "\r" end
112
+ end
113
+
114
+ def do_percentage
115
+ if @total.zero?
116
+ 100
117
+ else
118
+ @current * 100 / @total
119
+ end
120
+ end
121
+
122
+ def get_width
123
+ # FIXME: I don't know how portable it is.
124
+ default_width = 80
125
+ begin
126
+ tiocgwinsz = 0x5413
127
+ data = [0, 0, 0, 0].pack("SSSS")
128
+ if @out.ioctl(tiocgwinsz, data) >= 0 then
129
+ rows, cols, xpixels, ypixels = data.unpack("SSSS")
130
+ if cols >= 0 then cols else default_width end
131
+ else
132
+ default_width
133
+ end
134
+ rescue Exception
135
+ default_width
136
+ end
137
+ end
138
+
139
+ def show
140
+ arguments = @format_arguments.map {|method|
141
+ method = sprintf("fmt_%s", method)
142
+ send(method)
143
+ }
144
+ line = sprintf(@format, *arguments)
145
+
146
+ width = get_width
147
+ if line.length == width - 1
148
+ @out.print(line + eol)
149
+ @out.flush
150
+ elsif line.length >= width
151
+ @terminal_width = [@terminal_width - (line.length - width + 1), 0].max
152
+ if @terminal_width == 0 then @out.print(line + eol) else show end
153
+ else # line.length < width - 1
154
+ @terminal_width += width - line.length + 1
155
+ show
156
+ end
157
+ @previous_time = Time.now
158
+ end
159
+
160
+ def show_if_needed
161
+ if @total.zero?
162
+ cur_percentage = 100
163
+ prev_percentage = 0
164
+ else
165
+ cur_percentage = (@current * 100 / @total).to_i
166
+ prev_percentage = (@previous * 100 / @total).to_i
167
+ end
168
+
169
+ # Use "!=" instead of ">" to support negative changes
170
+ if cur_percentage != prev_percentage ||
171
+ Time.now - @previous_time >= 1 || @finished_p
172
+ show
173
+ end
174
+ end
175
+
176
+ public
177
+ def clear
178
+ @out.print "\r"
179
+ @out.print(" " * (get_width - 1))
180
+ @out.print "\r"
181
+ end
182
+
183
+ def finish
184
+ @current = @total
185
+ @finished_p = true
186
+ show
187
+ end
188
+
189
+ def finished?
190
+ @finished_p
191
+ end
192
+
193
+ def file_transfer_mode
194
+ @format_arguments = [:title, :percentage, :bar, :stat_for_file_transfer]
195
+ end
196
+
197
+ def format= (format)
198
+ @format = format
199
+ end
200
+
201
+ def format_arguments= (arguments)
202
+ @format_arguments = arguments
203
+ end
204
+
205
+ def halt
206
+ @finished_p = true
207
+ show
208
+ end
209
+
210
+ def inc (step = 1)
211
+ @current += step
212
+ @current = @total if @current > @total
213
+ show_if_needed
214
+ @previous = @current
215
+ end
216
+
217
+ def set (count)
218
+ if count < 0 || count > @total
219
+ raise "invalid count: #{count} (total: #{@total})"
220
+ end
221
+ @current = count
222
+ show_if_needed
223
+ @previous = @current
224
+ end
225
+
226
+ def inspect
227
+ "#<ProgressBar:#{@current}/#{@total}>"
228
+ end
229
+ end
230
+
231
+ class ReversedProgressBar < ProgressBar
232
+ def do_percentage
233
+ 100 - super
234
+ end
235
+ end
236
+
@@ -1,14 +1,54 @@
1
+ require 'rubygems'
1
2
  require 'ruby_to_ansi_c'
2
3
 
4
+ # HACK: you should require your dependencies
5
+ $array_index_helpers ||= ('a'..'zzz').to_a
6
+
7
+ class Environment # HACK until ruby_parser is re-released
8
+ alias :old_all :all
9
+ def all
10
+ idx = @dyn.index(false) || 0
11
+ @env[0..idx].reverse.inject { |env, scope| env.merge scope }
12
+ end
13
+ end
14
+
3
15
  class RADProcessor < RubyToAnsiC
4
16
 
17
+ @translator = nil
18
+
19
+ # REFACTOR: rename to self.process
20
+ def self.translate file, klass, method
21
+ sexp = RubyParser.new.process File.read(file), file
22
+ sexp = s(:block, sexp) unless sexp.sexp_type == :block
23
+
24
+ # this sucks... but it finds the class and method within the tree
25
+ # it doesn't currently deal with class methods or anything special
26
+ # AT ALL.
27
+
28
+ k_sexp = sexp.find_nodes(:class).find { |k|
29
+ k[1] == klass
30
+ }
31
+
32
+ body = k_sexp.scope
33
+ body = body.block if body.block # RubyParser bug?
34
+
35
+ m = body.find_nodes(:defn).find { |m|
36
+ m[1] == method
37
+ } rescue nil
38
+
39
+ @translator = nil # HACK
40
+
41
+ self.translator.process m if m
42
+ end
43
+
5
44
  def self.translator
6
- unless defined? @translator then
45
+ unless @translator then
7
46
  @translator = CompositeSexpProcessor.new
8
47
  @translator << RADRewriter.new
9
48
  @translator << RADTypeChecker.new
10
- @translator << R2CRewriter.new
49
+ # HACK: more harm than good @translator << CRewriter.new
11
50
  @translator << self.new
51
+
12
52
  @translator.on_error_in(:defn) do |processor, exp, err|
13
53
  result = processor.expected.new
14
54
  case result
@@ -21,6 +61,7 @@ class RADProcessor < RubyToAnsiC
21
61
  result << msg
22
62
  result
23
63
  end
64
+
24
65
  end
25
66
  @translator
26
67
  end
@@ -79,12 +120,8 @@ class RADProcessor < RubyToAnsiC
79
120
 
80
121
  def process_lasgn(exp)
81
122
  out = ""
82
-
83
123
  var = exp.shift
84
- value = exp.shift
85
- # grab the size of the args, if any, before process converts to a string
86
- arg_count = 0
87
- arg_count = value.length - 1 if value.first == :array
124
+ value = exp.shift # HACK FUCK || s(:array) # HACK?
88
125
  args = value
89
126
 
90
127
  exp_type = exp.sexp_type
@@ -106,13 +143,23 @@ class RADProcessor < RubyToAnsiC
106
143
  out << "#{var}[#{i}] = #{process o};\n"
107
144
  end
108
145
  else
109
- out << "#{var} = #{process args}"
146
+ out << "#{var}"
147
+ out << " = #{process args}" if args
110
148
  end
111
149
 
112
150
  out.sub!(/;\n\Z/, '')
113
151
 
114
152
  return out
115
153
  end
154
+
155
+ def process_str(exp)
156
+ s = exp.shift.gsub(/\n/, '\\n')
157
+ if s.size == 1
158
+ return "\'#{s}\'"
159
+ else
160
+ return "\"#{s}\""
161
+ end
162
+ end
116
163
 
117
164
 
118
- end
165
+ end