atduskgreg-rad 0.2.5
Sign up to get free protection for your applications and to get access to all the features.
- data/History.txt +104 -0
- data/License.txt +282 -0
- data/Manifest.txt +142 -0
- data/README.rdoc +55 -0
- data/Rakefile +142 -0
- data/bin/hello_world_test/Makefile +436 -0
- data/bin/hello_world_test/hello_world.cpp +23 -0
- data/bin/rad +302 -0
- data/lib/examples/add_hysteresis.rb +13 -0
- data/lib/examples/basic_blink.rb +10 -0
- data/lib/examples/blink_m_address_assignment.rb +104 -0
- data/lib/examples/blink_m_hello.rb +14 -0
- data/lib/examples/blink_m_multi.rb +61 -0
- data/lib/examples/blink_with_serial.rb +16 -0
- data/lib/examples/configure_pa_lcd_boot.rb +91 -0
- data/lib/examples/debounce_methods.rb +49 -0
- data/lib/examples/external_variable_fu.rb +26 -0
- data/lib/examples/external_variables.rb +32 -0
- data/lib/examples/first_sound.rb +23 -0
- data/lib/examples/frequency_generator.rb +30 -0
- data/lib/examples/hello_array.rb +48 -0
- data/lib/examples/hello_array2.rb +79 -0
- data/lib/examples/hello_array_eeprom.rb +59 -0
- data/lib/examples/hello_clock.rb +84 -0
- data/lib/examples/hello_eeprom.rb +51 -0
- data/lib/examples/hello_eeprom_lcdpa.rb +81 -0
- data/lib/examples/hello_format_print.rb +94 -0
- data/lib/examples/hello_lcd_charset.rb +75 -0
- data/lib/examples/hello_pa_lcd.rb +59 -0
- data/lib/examples/hello_servos.rb +88 -0
- data/lib/examples/hello_spectra_sound.rb +38 -0
- data/lib/examples/hello_world.rb +11 -0
- data/lib/examples/hello_xbee.rb +12 -0
- data/lib/examples/hysteresis_duel.rb +39 -0
- data/lib/examples/i2c_with_clock_chip.rb +124 -0
- data/lib/examples/midi_beat_box.rb +86 -0
- data/lib/examples/midi_scales.rb +94 -0
- data/lib/examples/motor_knob.rb +30 -0
- data/lib/examples/servo_buttons.rb +23 -0
- data/lib/examples/servo_calibrate_continuous.rb +92 -0
- data/lib/examples/servo_throttle.rb +40 -0
- data/lib/examples/software_serial.rb +10 -0
- data/lib/examples/sparkfun_lcd.rb +48 -0
- data/lib/examples/spectra_soft_pot.rb +34 -0
- data/lib/examples/times_method.rb +8 -0
- data/lib/examples/toggle.rb +10 -0
- data/lib/examples/twitter.rb +57 -0
- data/lib/examples/two_wire.rb +14 -0
- data/lib/libraries/AFSoftSerial/AFSoftSerial.cpp +321 -0
- data/lib/libraries/AFSoftSerial/AFSoftSerial.h +61 -0
- data/lib/libraries/AFSoftSerial/keywords.txt +18 -0
- data/lib/libraries/AF_XPort/AF_XPort.cpp +166 -0
- data/lib/libraries/AF_XPort/AF_XPort.h +48 -0
- data/lib/libraries/DS1307/DS1307.cpp +162 -0
- data/lib/libraries/DS1307/DS1307.h +66 -0
- data/lib/libraries/DS1307/keywords.txt +18 -0
- data/lib/libraries/FrequencyTimer2/FrequencyTimer2.cpp +144 -0
- data/lib/libraries/FrequencyTimer2/FrequencyTimer2.h +42 -0
- data/lib/libraries/FrequencyTimer2/keywords.txt +22 -0
- data/lib/libraries/I2CEEPROM/I2CEEPROM.cpp +120 -0
- data/lib/libraries/I2CEEPROM/I2CEEPROM.h +70 -0
- data/lib/libraries/I2CEEPROM/keywords.txt +21 -0
- data/lib/libraries/LoopTimer/LoopTimer.cpp +35 -0
- data/lib/libraries/LoopTimer/LoopTimer.h +34 -0
- data/lib/libraries/LoopTimer/keywords.txt +27 -0
- data/lib/libraries/OneWire/OneWire.cpp +194 -0
- data/lib/libraries/OneWire/OneWire.h +63 -0
- data/lib/libraries/OneWire/keywords.txt +35 -0
- data/lib/libraries/OneWire/readme.txt +13 -0
- data/lib/libraries/SWSerLCDpa/SWSerLCDpa.cpp +296 -0
- data/lib/libraries/SWSerLCDpa/SWSerLCDpa.h +69 -0
- data/lib/libraries/SWSerLCDsf/SWSerLCDsf.cpp +311 -0
- data/lib/libraries/SWSerLCDsf/SWSerLCDsf.h +67 -0
- data/lib/libraries/Servo/Servo.cpp +192 -0
- data/lib/libraries/Servo/Servo.h +61 -0
- data/lib/libraries/Stepper/Stepper.cpp +220 -0
- data/lib/libraries/Stepper/Stepper.h +86 -0
- data/lib/libraries/Stepper/keywords.txt +28 -0
- data/lib/libraries/Wire/Wire.cpp +262 -0
- data/lib/libraries/Wire/Wire.h +67 -0
- data/lib/libraries/Wire/keywords.txt +31 -0
- data/lib/libraries/Wire/twi.h +57 -0
- data/lib/libraries/Wire/utility/twi.c +449 -0
- data/lib/libraries/Wire/utility/twi.h +57 -0
- data/lib/plugins/bitwise_ops.rb +54 -0
- data/lib/plugins/blink.rb +25 -0
- data/lib/plugins/blink_m.rb +356 -0
- data/lib/plugins/debounce.rb +138 -0
- data/lib/plugins/debug_output_to_lcd.rb +71 -0
- data/lib/plugins/hysteresis.rb +52 -0
- data/lib/plugins/input_output_state.rb +84 -0
- data/lib/plugins/lcd_padding.rb +58 -0
- data/lib/plugins/mem_test.rb +37 -0
- data/lib/plugins/midi.rb +60 -0
- data/lib/plugins/parallax_ping.rb +50 -0
- data/lib/plugins/servo_pulse.rb +31 -0
- data/lib/plugins/servo_setup.rb +86 -0
- data/lib/plugins/smoother.rb +54 -0
- data/lib/plugins/spark_fun_serial_lcd.rb +100 -0
- data/lib/plugins/spectra_symbol.rb +79 -0
- data/lib/plugins/twitter_connect.rb +145 -0
- data/lib/rad.rb +5 -0
- data/lib/rad/README.rdoc +5 -0
- data/lib/rad/arduino_plugin.rb +246 -0
- data/lib/rad/arduino_sketch.rb +627 -0
- data/lib/rad/generators/makefile/makefile.erb +243 -0
- data/lib/rad/generators/makefile/makefile.rb +38 -0
- data/lib/rad/hardware_library.rb +813 -0
- data/lib/rad/init.rb +14 -0
- data/lib/rad/progressbar.rb +236 -0
- data/lib/rad/rad_processor.rb +128 -0
- data/lib/rad/rad_rewriter.rb +94 -0
- data/lib/rad/rad_type_checker.rb +26 -0
- data/lib/rad/sim/arduino_sketch.rb +57 -0
- data/lib/rad/sketch_compiler.rb +47 -0
- data/lib/rad/tasks/build_and_make.rake +210 -0
- data/lib/rad/tasks/rad.rb +2 -0
- data/lib/rad/todo.txt +13 -0
- data/lib/rad/variable_processing.rb +153 -0
- data/lib/rad/version.rb +9 -0
- data/scripts/txt2html +67 -0
- data/setup.rb +1585 -0
- data/spec/examples/hello_world.rb +11 -0
- data/spec/examples/serial_motor.rb +12 -0
- data/spec/models/arduino_sketch_spec.rb +82 -0
- data/spec/models/sketch_compiler_spec.rb +96 -0
- data/spec/models/spec_helper.rb +2 -0
- data/spec/sim/hello_world_spec.rb +42 -0
- data/spec/spec.opts +1 -0
- data/test/test_array_processing.rb +179 -0
- data/test/test_plugin_loading.rb +151 -0
- data/test/test_translation_post_processing.rb +185 -0
- data/test/test_variable_processing.rb +238 -0
- data/website/examples/assembler_test.rb.html +73 -0
- data/website/examples/gps_reader.rb.html +39 -0
- data/website/examples/hello_world.rb.html +38 -0
- data/website/examples/serial_motor.rb.html +41 -0
- data/website/index.html +178 -0
- data/website/index.txt +64 -0
- data/website/javascripts/rounded_corners_lite.inc.js +285 -0
- data/website/stylesheets/screen.css +169 -0
- data/website/template.rhtml +48 -0
- metadata +217 -0
@@ -0,0 +1,26 @@
|
|
1
|
+
require 'ruby_to_ansi_c'
|
2
|
+
|
3
|
+
class RADTypeChecker < TypeChecker
|
4
|
+
|
5
|
+
def process_const(exp)
|
6
|
+
c = exp.shift
|
7
|
+
if c.to_s =~ /^[A-Z]/ then
|
8
|
+
# TODO: validate that it really is a const?
|
9
|
+
# uber hackery
|
10
|
+
# since constants are defined in the arduino_sketch define method and
|
11
|
+
# we can't inject them into the methods
|
12
|
+
# transport them here with a $define_types hash
|
13
|
+
|
14
|
+
$define_types.each do |k,v|
|
15
|
+
if k == c.to_s
|
16
|
+
@const_type = eval "Type.#{v}"
|
17
|
+
end
|
18
|
+
end
|
19
|
+
return t(:const, c, @const_type)
|
20
|
+
else
|
21
|
+
raise "I don't know what to do with const #{c.inspect}. It doesn't look like a class."
|
22
|
+
end
|
23
|
+
raise "need to finish process_const in #{self.class}"
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
ON = true
|
2
|
+
OFF = !ON
|
3
|
+
HIGH = ON
|
4
|
+
LOW = !HIGH
|
5
|
+
|
6
|
+
class ArduinoSketch
|
7
|
+
attr_accessor :pins
|
8
|
+
|
9
|
+
def initialize
|
10
|
+
@pins = self.class.instance_variable_get("@pins")
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.output_pin(num, opts)
|
14
|
+
module_eval "@pins ||= []"
|
15
|
+
module_eval do
|
16
|
+
@pins << Pin.new( num, :type => :output )
|
17
|
+
end
|
18
|
+
|
19
|
+
if opts[:as]
|
20
|
+
module_eval <<-CODE
|
21
|
+
def #{opts[:as]}
|
22
|
+
pins.select{|p| p.num == #{num}}.first
|
23
|
+
end
|
24
|
+
CODE
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def loop
|
29
|
+
end
|
30
|
+
|
31
|
+
def digitalWrite( pin, value )
|
32
|
+
to_change = pins.select{|p| p.num == pin.num}.first
|
33
|
+
to_change.value = value
|
34
|
+
end
|
35
|
+
|
36
|
+
def delay( millis )
|
37
|
+
end
|
38
|
+
|
39
|
+
# def serial_read
|
40
|
+
# end
|
41
|
+
|
42
|
+
# def serial_available
|
43
|
+
# end
|
44
|
+
|
45
|
+
# def blink
|
46
|
+
# end
|
47
|
+
end
|
48
|
+
|
49
|
+
class Pin
|
50
|
+
attr_accessor :num, :type, :value
|
51
|
+
|
52
|
+
def initialize num, opts
|
53
|
+
@num = num
|
54
|
+
@type = opts[:type]
|
55
|
+
@value = opts[:value] || false
|
56
|
+
end
|
57
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
# TODO:
|
2
|
+
# compilation
|
3
|
+
# gather pieces of code we need as strings
|
4
|
+
# translate non-loop methods
|
5
|
+
# do plugin stuff
|
6
|
+
# deal with examples/ exception
|
7
|
+
# manage upload process
|
8
|
+
# compose_setup should move in here entirely
|
9
|
+
|
10
|
+
# require 'arduino_sketch'
|
11
|
+
|
12
|
+
class SketchCompiler
|
13
|
+
attr_accessor :path, :body, :klass, :target_dir, :name
|
14
|
+
|
15
|
+
def initialize path_to_sketch
|
16
|
+
@path = File.expand_path(path_to_sketch)
|
17
|
+
@body = open(@path).read
|
18
|
+
@name = @path.split("/").last.split(".").first
|
19
|
+
@klass = @name.split(".").first.split("_").collect{|c| c.capitalize}.join("")
|
20
|
+
@target_dir = parent_dir
|
21
|
+
end
|
22
|
+
|
23
|
+
def parent_dir
|
24
|
+
self.path.split("/")[0..@path.split("/").length-2].join("/")
|
25
|
+
end
|
26
|
+
|
27
|
+
def build_dir
|
28
|
+
"#{self.target_dir}/#{self.name}"
|
29
|
+
end
|
30
|
+
|
31
|
+
def create_build_dir! optional_path_prefix=nil
|
32
|
+
self.target_dir = optional_path_prefix if optional_path_prefix
|
33
|
+
mkdir_p build_dir
|
34
|
+
end
|
35
|
+
|
36
|
+
def process_constants
|
37
|
+
self.body.gsub!("HIGH", "1")
|
38
|
+
self.body.gsub!("LOW", "0")
|
39
|
+
self.body.gsub!("ON", "1")
|
40
|
+
self.body.gsub!("OFF", "0")
|
41
|
+
end
|
42
|
+
|
43
|
+
def sketch_methods
|
44
|
+
self.body.scan(/^\s*def\s.\w*/).collect{ |m| m.gsub(/\s*def\s*/, "") }
|
45
|
+
end
|
46
|
+
|
47
|
+
end
|
@@ -0,0 +1,210 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + "/../init.rb")
|
2
|
+
require 'ruby_to_ansi_c'
|
3
|
+
|
4
|
+
C_VAR_TYPES = "unsigned|int|long|double|str|char|byte|bool"
|
5
|
+
|
6
|
+
# incredibly primitive tests
|
7
|
+
# rake test:compile or rake test:upload
|
8
|
+
# runs through all sketches in the example directory
|
9
|
+
|
10
|
+
def run_tests(sketch, type)
|
11
|
+
sh %{rake make:#{type} sketch=examples/#{sketch}}
|
12
|
+
end
|
13
|
+
|
14
|
+
namespace :test do
|
15
|
+
|
16
|
+
desc "iterate through all the sketches in the example directory"
|
17
|
+
task :upload => :gather do
|
18
|
+
@examples.each {|e| run_tests(e, "upload")}
|
19
|
+
end
|
20
|
+
|
21
|
+
task :compile => :gather do
|
22
|
+
|
23
|
+
@examples.each {|e| run_tests(e, "compile")}
|
24
|
+
end
|
25
|
+
|
26
|
+
desc "gather all tests"
|
27
|
+
task :gather do # => "make:upload" do
|
28
|
+
@examples = []
|
29
|
+
if ENV['sketch']
|
30
|
+
@examples << ENV['sketch']
|
31
|
+
else
|
32
|
+
Dir.entries( File.expand_path("#{RAD_ROOT}/examples/") ).each do |f|
|
33
|
+
@examples << f.split('.').first if (f =~ /\.rb$/)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
39
|
+
|
40
|
+
|
41
|
+
namespace :make do
|
42
|
+
|
43
|
+
desc "compile the sketch and then upload it to your Arduino board"
|
44
|
+
task :upload => :compile do
|
45
|
+
if Makefile.hardware_params['physical_reset']
|
46
|
+
puts "Reset the Arduino and hit enter.\n==If your board doesn't need it, you can turn off this prompt in config/software.yml=="
|
47
|
+
STDIN.gets.chomp
|
48
|
+
end
|
49
|
+
sh %{cd #{@sketch.build_dir}; make upload}
|
50
|
+
end
|
51
|
+
|
52
|
+
desc "generate a makefile and use it to compile the .cpp"
|
53
|
+
task :compile => [:clean_sketch_dir, "build:sketch"] do # should also depend on "build:sketch"
|
54
|
+
Makefile.compose_for_sketch( @sketch.build_dir )
|
55
|
+
|
56
|
+
# not allowed? sh %{export PATH=#{Makefile.software_params[:arduino_root]}/tools/avr/bin:$PATH}
|
57
|
+
sh %{cd #{@sketch.build_dir}; make depend; make}
|
58
|
+
end
|
59
|
+
|
60
|
+
desc "generate a makefile and use it to compile the .cpp using the current .cpp file"
|
61
|
+
task :compile_cpp => ["build:sketch_dir", "build:gather_required_plugins", "build:plugin_setup", "build:setup", :clean_sketch_dir] do # should also depend on "build:sketch"
|
62
|
+
Makefile.compose_for_sketch( @sketch.build_dir )
|
63
|
+
# not allowed? sh %{export PATH=#{Makefile.software_params[:arduino_root]}/tools/avr/bin:$PATH}
|
64
|
+
sh %{cd #{@sketch.build_dir}; make depend; make}
|
65
|
+
end
|
66
|
+
|
67
|
+
desc "generate a makefile and use it to compile the .cpp and upload it using current .cpp file"
|
68
|
+
task :upload_cpp => ["build:sketch_dir", "build:gather_required_plugins", "build:plugin_setup", "build:setup", :clean_sketch_dir] do # should also depend on "build:sketch"
|
69
|
+
Makefile.compose_for_sketch( @sketch.build_dir )
|
70
|
+
# not allowed? sh %{export PATH=#{Makefile.software_params[:arduino_root]}/tools/avr/bin:$PATH}
|
71
|
+
sh %{cd #{@sketch.build_dir}; make depend; make upload}
|
72
|
+
end
|
73
|
+
|
74
|
+
task :clean_sketch_dir => ["build:file_list", "build:sketch_dir"] do
|
75
|
+
FileList.new(Dir.entries("#{@sketch.build_dir}")).exclude("#{@sketch.name}.cpp").exclude(/^\./).each do |f|
|
76
|
+
sh %{rm #{@sketch.build_dir}/#{f}}
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
end
|
81
|
+
|
82
|
+
namespace :build do
|
83
|
+
|
84
|
+
desc "actually build the sketch"
|
85
|
+
task :sketch => [:file_list, :sketch_dir, :gather_required_plugins, :plugin_setup, :setup] do
|
86
|
+
c_methods = []
|
87
|
+
sketch_signatures = []
|
88
|
+
# until we better understand RubyToC let's see what's happening on errors
|
89
|
+
@sketch.sketch_methods.each do |meth|
|
90
|
+
raw_rtc_meth = RADProcessor.translate(constantize(@sketch.klass), meth)
|
91
|
+
puts "Translator Error: #{raw_rtc_meth.inspect}" if raw_rtc_meth =~ /\/\/ ERROR:/
|
92
|
+
c_methods << raw_rtc_meth unless meth == "setup"
|
93
|
+
# treat the setup method differently
|
94
|
+
@additional_setup = [] if meth == "setup"
|
95
|
+
raw_rtc_meth.each {|m| @additional_setup << ArduinoSketch.add_to_setup(m) } if meth == "setup"
|
96
|
+
end
|
97
|
+
c_methods.each {|meth| sketch_signatures << "#{meth.scan(/^\w*\s?\*?\n.*\)/)[0].gsub("\n", " ")};" }
|
98
|
+
clean_c_methods = []
|
99
|
+
# remove external variables that were previously injected
|
100
|
+
c_methods.join("\n").each { |meth| clean_c_methods << ArduinoSketch.post_process_ruby_to_c_methods(meth) }
|
101
|
+
c_methods_with_timer = clean_c_methods.join.gsub(/loop\(\)\s\{/,"loop() {")
|
102
|
+
# last chance to add/change setup
|
103
|
+
@setup[2] << sketch_signatures.join("\n") unless sketch_signatures.empty?
|
104
|
+
# add special setup method to existing setup if present
|
105
|
+
if @additional_setup
|
106
|
+
@setup[2] << "void additional_setup();" # declaration
|
107
|
+
@setup[4] << "\tadditional_setup();" # call from setup
|
108
|
+
@setup[5] << @additional_setup.join("") #
|
109
|
+
end
|
110
|
+
result = "#{@setup.join( "\n" )}\n#{c_methods_with_timer}\n"
|
111
|
+
File.open("#{@sketch.build_dir}/#{@sketch.name}.cpp", "w"){|f| f << result}
|
112
|
+
end
|
113
|
+
|
114
|
+
# needs to write the library include and the method signatures
|
115
|
+
desc "build setup function"
|
116
|
+
task :setup do
|
117
|
+
eval "class #{@sketch.klass} < ArduinoSketch; end;"
|
118
|
+
|
119
|
+
@@as = HardwareLibrary.new
|
120
|
+
|
121
|
+
delegate_methods = @@as.methods - Object.new.methods
|
122
|
+
delegate_methods.reject!{|m| m == "compose_setup"}
|
123
|
+
|
124
|
+
delegate_methods.each do |meth|
|
125
|
+
constantize(@sketch.klass).module_eval <<-CODE
|
126
|
+
def self.#{meth}(*args)
|
127
|
+
@@as.#{meth}(*args)
|
128
|
+
end
|
129
|
+
CODE
|
130
|
+
end
|
131
|
+
# allow variable declaration without quotes: @foo = int
|
132
|
+
["long","unsigned","int","byte","short"].each do |type|
|
133
|
+
constantize(@sketch.klass).module_eval <<-CODE
|
134
|
+
def self.#{type}
|
135
|
+
return "#{type}"
|
136
|
+
end
|
137
|
+
CODE
|
138
|
+
end
|
139
|
+
|
140
|
+
@sketch.process_constants
|
141
|
+
|
142
|
+
eval ArduinoSketch.pre_process(@sketch.body)
|
143
|
+
@@as.process_external_vars(constantize(@sketch.klass))
|
144
|
+
@setup = @@as.compose_setup
|
145
|
+
end
|
146
|
+
|
147
|
+
desc "add plugin methods"
|
148
|
+
task :plugin_setup do
|
149
|
+
$plugins_to_load.each do |name|
|
150
|
+
klass = name.split(".").first.split("_").collect{|c| c.capitalize}.join("")
|
151
|
+
eval "class #{klass} < ArduinoPlugin; end;"
|
152
|
+
|
153
|
+
@@ps = ArduinoPlugin.new
|
154
|
+
plugin_delegate_methods = @@ps.methods - Object.new.methods
|
155
|
+
plugin_delegate_methods.reject!{|m| m == "compose_setup"}
|
156
|
+
|
157
|
+
plugin_delegate_methods.each do |meth|
|
158
|
+
constantize(klass).module_eval <<-CODE
|
159
|
+
def self.#{meth}(*args)
|
160
|
+
@@ps.#{meth}(*args)
|
161
|
+
end
|
162
|
+
CODE
|
163
|
+
end
|
164
|
+
|
165
|
+
eval ArduinoPlugin.process(File.read("vendor/plugins/#{name}"))
|
166
|
+
|
167
|
+
end
|
168
|
+
@@no_plugins = ArduinoPlugin.new if @plugin_names.empty?
|
169
|
+
end
|
170
|
+
|
171
|
+
desc "determine which plugins to load based on use of methods in sketch"
|
172
|
+
task :gather_required_plugins do
|
173
|
+
@plugin_names.each do |name|
|
174
|
+
ArduinoPlugin.check_for_plugin_use(@sketch.body, File.read("vendor/plugins/#{name}"), name )
|
175
|
+
end
|
176
|
+
puts "#{$plugins_to_load.length} of #{$plugin_methods_hash.length} plugins are being loaded: #{$plugins_to_load.join(", ")}"
|
177
|
+
end
|
178
|
+
|
179
|
+
desc "setup target directory named after your sketch class"
|
180
|
+
task :sketch_dir => [:file_list] do
|
181
|
+
@sketch.create_build_dir!
|
182
|
+
end
|
183
|
+
|
184
|
+
task :file_list do
|
185
|
+
# take another look at this, since if the root directory name is changed, everything breaks
|
186
|
+
# perhaps we generate a constant when the project is generated an pop it here or in the init file
|
187
|
+
if ENV['sketch']
|
188
|
+
@sketch = SketchCompiler.new File.expand_path("#{ENV['sketch']}.rb")
|
189
|
+
else
|
190
|
+
# assume the only .rb file in the sketch dir is the sketch:
|
191
|
+
@sketch = SketchCompiler.new Dir.glob("#{File.expand_path(File.dirname(__FILE__))}/../../../*.rb").first
|
192
|
+
end
|
193
|
+
|
194
|
+
@plugin_names = []
|
195
|
+
Dir.entries( File.expand_path("#{RAD_ROOT}/vendor/plugins/") ).each do |f|
|
196
|
+
if (f =~ /\.rb$/)
|
197
|
+
@plugin_names << f
|
198
|
+
end
|
199
|
+
end
|
200
|
+
end
|
201
|
+
end
|
202
|
+
|
203
|
+
#yoinked from Rails
|
204
|
+
def constantize(camel_cased_word)
|
205
|
+
unless /\A(?:::)?([A-Z]\w*(?:::[A-Z]\w*)*)\z/ =~ camel_cased_word
|
206
|
+
raise NameError, "#{camel_cased_word.inspect} is not a valid constant name!"
|
207
|
+
end
|
208
|
+
|
209
|
+
Object.module_eval("::#{$1}", __FILE__, __LINE__)
|
210
|
+
end
|
data/lib/rad/todo.txt
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
TODO:
|
2
|
+
=====
|
3
|
+
|
4
|
+
Future:
|
5
|
+
- complete library system: script/install library some_library
|
6
|
+
- bin/rad:
|
7
|
+
- setup and use a ~/.rad for new project defaults
|
8
|
+
- put repository on git
|
9
|
+
- project gallery (examples with movies)
|
10
|
+
- testing framework
|
11
|
+
- implement wire lib
|
12
|
+
- subclasses of ArduinoSketch (should just work, but what are they for?)
|
13
|
+
- simulator
|
@@ -0,0 +1,153 @@
|
|
1
|
+
module ExternalVariableProcessing
|
2
|
+
# issues
|
3
|
+
# testing
|
4
|
+
# add checking for colon
|
5
|
+
|
6
|
+
|
7
|
+
## need to clean this up
|
8
|
+
## need to test
|
9
|
+
def process_external_vars(klass)
|
10
|
+
vars = eval "#{klass}.instance_variables"
|
11
|
+
local_vars = []
|
12
|
+
vars.each { |v| local_vars << ":#{v.gsub("@", "")}" }
|
13
|
+
loc_vars = local_vars.join(", ")
|
14
|
+
# add accessors
|
15
|
+
klass.module_eval "class << self; attr_accessor #{loc_vars} end"
|
16
|
+
local_vars.each do |symbol|
|
17
|
+
name = symbol.gsub(":","")
|
18
|
+
t_var = eval "#{klass}.#{name}"
|
19
|
+
pre_process_vars(name, t_var)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
|
24
|
+
def pre_process_vars(name, var)
|
25
|
+
# puts
|
26
|
+
# puts
|
27
|
+
case var
|
28
|
+
when Integer
|
29
|
+
# puts "pre_process: #{name}, #{var}, #{var.inspect} got #{var.class} 29"
|
30
|
+
value = var
|
31
|
+
type = "int"
|
32
|
+
post_process_vars(name, type, value)
|
33
|
+
when Float
|
34
|
+
# puts "pre_process: #{name}, #{var}, #{var.inspect} got #{var.class} 34"
|
35
|
+
value = var
|
36
|
+
type = "float"
|
37
|
+
post_process_vars(name, type, value)
|
38
|
+
when String
|
39
|
+
# puts "pre_process: #{name}, #{var.inspect} got #{var.class} on 39"
|
40
|
+
if var.match(",").nil? && var =~ /long|byte|unsigned|int|short/
|
41
|
+
# puts "pre_process #{name}, #{var.inspect} got #{var.class} level three sublevel"
|
42
|
+
type = var
|
43
|
+
value = nil
|
44
|
+
post_process_vars(name, type, value)
|
45
|
+
else
|
46
|
+
value = var.split(",").first.lstrip
|
47
|
+
type = var.split(",")[1].nil? ? nil : var.split(",")[1].lstrip
|
48
|
+
translate_variables( name , type, value )
|
49
|
+
end
|
50
|
+
when TrueClass
|
51
|
+
# puts "pre_process: #{name}, #{var}, #{var.inspect} got #{var.class} on 50"
|
52
|
+
value = 1
|
53
|
+
type = "bool"
|
54
|
+
post_process_vars(name, type, value)
|
55
|
+
when FalseClass
|
56
|
+
# puts "pre_process: #{name}, #{var}, #{var.inspect} got #{var.class} on 55"
|
57
|
+
value = 0
|
58
|
+
type = "bool"
|
59
|
+
post_process_vars(name, type, value)
|
60
|
+
when Array
|
61
|
+
post_process_arrays(name, var)
|
62
|
+
else
|
63
|
+
raise ArgumentError, "not sure what to do here... got #{name} with value #{var} which is a #{var.class}"
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
|
68
|
+
def translate_variables(name, type = nil, value = nil)
|
69
|
+
|
70
|
+
unless type.nil?
|
71
|
+
check_variable_type(type)
|
72
|
+
end
|
73
|
+
|
74
|
+
# classify the values
|
75
|
+
if value.class == Fixnum
|
76
|
+
# puts "translate_variables: #{name}, #{value}, #{type} is a fixnum, got #{value.class} on 74"
|
77
|
+
elsif value.class == Float
|
78
|
+
# puts "translate_variables: #{name}, #{value}, #{type} is a float, got #{value.class} on 76"
|
79
|
+
elsif value =~ /^-(\d|x)*$/
|
80
|
+
value = value.to_i
|
81
|
+
type = "int" if type.nil?
|
82
|
+
elsif value =~ /^-(\d|\.|x)*$/
|
83
|
+
value = value.to_f
|
84
|
+
unless type.nil?
|
85
|
+
raise ArgumentError, "#{value} should be a float got #{type}" unless type == "float"
|
86
|
+
end
|
87
|
+
type = "float" if type.nil?
|
88
|
+
|
89
|
+
elsif value[0,1] !~ /\d/
|
90
|
+
# puts value[0,1]
|
91
|
+
# puts "translate_variables: #{name}, #{value}, #{type} is a number of some type, got #{value.class} on 79"
|
92
|
+
type = "char*"
|
93
|
+
value = "\"#{value}\""
|
94
|
+
elsif value !~ /(\.|x)/
|
95
|
+
# puts "translate_variables: #{name}, #{value}, #{type} is an integer, got #{value.class} on 83"
|
96
|
+
value = value.to_i
|
97
|
+
type = "int" if type.nil?
|
98
|
+
elsif value =~ /(\d*\.\d*)/ # and no
|
99
|
+
# puts "translate_variables: #{name}, #{value}, #{type} is a float, got #{value.class} on 87"
|
100
|
+
value = value.to_f
|
101
|
+
type = "float"
|
102
|
+
elsif value =~ /0x\d\d/
|
103
|
+
# puts "translate_variables: #{name}, #{value}, #{type} is a byte, got #{value.class} on 91"
|
104
|
+
type = "byte"
|
105
|
+
else
|
106
|
+
raise ArgumentError, "not sure what to do with a value of #{value} with a type like #{type}"
|
107
|
+
end
|
108
|
+
|
109
|
+
post_process_vars(name, type, value)
|
110
|
+
end
|
111
|
+
|
112
|
+
|
113
|
+
|
114
|
+
def post_process_vars(name, type, value = nil)
|
115
|
+
value = " = #{value}" if value
|
116
|
+
$external_var_identifiers << "__#{name}" unless $external_var_identifiers.include?("__#{name}")
|
117
|
+
$external_vars << "#{type} __#{name}#{value};"
|
118
|
+
end
|
119
|
+
|
120
|
+
def post_process_arrays(name, var)
|
121
|
+
type = c_type(var[0])
|
122
|
+
$array_types[name] = type
|
123
|
+
assignment = var.inspect.gsub("[","{").gsub("]","}")
|
124
|
+
c_style_array = "#{type} __#{name}[] = #{assignment};"
|
125
|
+
$external_var_identifiers << "__#{name}" unless $external_var_identifiers.include?("__#{name}")
|
126
|
+
$external_array_vars << c_style_array unless $external_array_vars.include?(c_style_array)
|
127
|
+
end
|
128
|
+
|
129
|
+
def check_variable_type(type)
|
130
|
+
unless type =~ /#{C_VAR_TYPES}/
|
131
|
+
raise ArgumentError, "the following variable types are supported \n #{C_VAR_TYPES.gsub("|",", ")} got #{type}"
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
def c_type(typ)
|
136
|
+
type =
|
137
|
+
case typ
|
138
|
+
when Integer
|
139
|
+
"int"
|
140
|
+
when String
|
141
|
+
"char*"
|
142
|
+
when TrueClass
|
143
|
+
"bool"
|
144
|
+
when FalseClass
|
145
|
+
"bool"
|
146
|
+
else
|
147
|
+
raise "Bug! Unknown type #{typ.inspect} in c_type"
|
148
|
+
end
|
149
|
+
|
150
|
+
type
|
151
|
+
end
|
152
|
+
|
153
|
+
end
|