madrona-rad 0.2.4 → 0.2.5

Sign up to get free protection for your applications and to get access to all the features.
Files changed (37) hide show
  1. data/History.txt +10 -0
  2. data/Manifest.txt +26 -0
  3. data/bin/rad +28 -36
  4. data/lib/examples/blink_m_hello.rb +14 -0
  5. data/lib/examples/debounce_methods.rb +49 -0
  6. data/lib/examples/external_variable_fu.rb +24 -0
  7. data/lib/examples/external_variables.rb +31 -0
  8. data/lib/examples/hello_eeprom.rb +54 -0
  9. data/lib/examples/i2c_with_clock_chip.rb +124 -0
  10. data/lib/examples/two_wire.rb +14 -0
  11. data/lib/libraries/DS1307/DS1307.cpp +161 -0
  12. data/lib/libraries/DS1307/DS1307.h +64 -0
  13. data/lib/libraries/DS1307/keywords.txt +18 -0
  14. data/lib/libraries/OneWire/OneWire.cpp +194 -0
  15. data/lib/libraries/OneWire/OneWire.h +63 -0
  16. data/lib/libraries/OneWire/keywords.txt +35 -0
  17. data/lib/libraries/OneWire/readme.txt +13 -0
  18. data/lib/libraries/Wire/Wire.cpp +262 -0
  19. data/lib/libraries/Wire/Wire.h +67 -0
  20. data/lib/libraries/Wire/keywords.txt +31 -0
  21. data/lib/libraries/Wire/twi.h +57 -0
  22. data/lib/plugins/bitwise_ops.rb +54 -0
  23. data/lib/plugins/blink_m.rb +304 -6
  24. data/lib/plugins/debounce.rb +46 -24
  25. data/lib/plugins/i2c_eeprom.rb +70 -0
  26. data/lib/rad/arduino_plugin.rb +27 -4
  27. data/lib/rad/arduino_sketch.rb +354 -115
  28. data/lib/rad/generators/makefile/makefile.erb +2 -2
  29. data/lib/rad/generators/makefile/makefile.rb +5 -9
  30. data/lib/rad/init.rb +3 -1
  31. data/lib/rad/rad_processor.rb +11 -0
  32. data/lib/rad/rad_rewriter.rb +1 -1
  33. data/lib/rad/tasks/build_and_make.rake +25 -12
  34. data/lib/rad/variable_processing.rb +116 -0
  35. data/lib/test/test_array_processing.rb +78 -0
  36. data/lib/test/test_variable_processing.rb +188 -0
  37. metadata +29 -3
@@ -92,8 +92,8 @@ CDEFS = -DF_CPU=$(F_CPU)
92
92
  CXXDEFS = -DF_CPU=$(F_CPU)
93
93
 
94
94
  # Place -I options here
95
- CINCS = -I$(ARDUINO) -I$(SOFTWARE_SERIAL)<% params['libraries'].each do |l| %> -I$(LIBRARY_ROOT)/<%= l %><% end %> <%= params['wire_h'] %>
96
- +CXXINCS = -I$(ARDUINO) -I$(SOFTWARE_SERIAL)<% params['libraries'].each do |l| %> -I$(LIBRARY_ROOT)/<%= l %><% end %> <%= params['wire_h'] %>
95
+ CINCS = -I$(ARDUINO) -I$(SOFTWARE_SERIAL)<% params['libraries'].each do |l| %> -I$(LIBRARY_ROOT)/<%= l %><% end %>
96
+ +CXXINCS = -I$(ARDUINO) -I$(SOFTWARE_SERIAL)<% params['libraries'].each do |l| %> -I$(LIBRARY_ROOT)/<%= l %><% end %>
97
97
 
98
98
  # Compiler flag to set the C Standard level.
99
99
  # c89 - "ANSI" C
@@ -8,13 +8,13 @@ class Makefile
8
8
  def compose_for_sketch(sketch_name)
9
9
  params = hardware_params.merge software_params
10
10
  params['target'] = sketch_name.split("/").last
11
-
12
- params['wire_h'] = $include_wire == true ? "-I#{params['arduino_root']}/hardware/libraries/Wire/" : ""
13
- params['twi_c'] = $include_wire == true ? "#{params['arduino_root']}/hardware/libraries/Wire/utility/twi.c" : ""
14
-
11
+
15
12
  params['libraries_root'] = "#{File.expand_path(RAD_ROOT)}/vendor/libraries"
16
13
  params['libraries'] = $load_libraries # load only libraries used
17
14
 
15
+ # needed along with ugly hack of including another copy of twi.h in wire, when using the Wire.h library
16
+ params['twi_c'] = $load_libraries.include?("Wire") ? "#{params['arduino_root']}/hardware/libraries/Wire/utility/twi.c" : ""
17
+
18
18
  params['asm_files'] = Dir.entries( File.expand_path(RAD_ROOT) + "/" + PROJECT_DIR_NAME ).select{|e| e =~ /\.S/}
19
19
 
20
20
  e = ERB.new File.read("#{File.dirname(__FILE__)}/makefile.erb")
@@ -23,11 +23,7 @@ class Makefile
23
23
  f << e.result(binding)
24
24
  end
25
25
  end
26
-
27
- # def libraries
28
- # Dir.entries("#{RAD_ROOT}/vendor/libraries").select{|e| !(e =~ /\./)}
29
- # end
30
-
26
+
31
27
  def hardware_params
32
28
  return @hardware_params if @hardware_params
33
29
  return @hardware_params = YAML.load_file( "#{RAD_ROOT}/config/hardware.yml")
data/lib/rad/init.rb CHANGED
@@ -5,8 +5,10 @@ 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"
8
9
 
9
- %w(generators/makefile/makefile.rb rad_processor.rb rad_rewriter.rb arduino_sketch.rb arduino_plugin.rb tasks/rad.rb).each do |path|
10
+
11
+ %w(generators/makefile/makefile.rb rad_processor.rb rad_rewriter.rb variable_processing.rb arduino_sketch.rb arduino_plugin.rb tasks/rad.rb).each do |path|
10
12
  require File.expand_path("#{RAD_ROOT}/vendor/rad/#{path}")
11
13
  end
12
14
 
@@ -24,6 +24,17 @@ class RADProcessor < RubyToAnsiC
24
24
  end
25
25
  @translator
26
26
  end
27
+
28
+ def process_iasgn(exp)
29
+ name = exp.shift
30
+ val = process exp.shift
31
+ "__#{name.to_s.sub(/^@/, '')} = #{val}"
32
+ end
33
+
34
+ def process_ivar(exp)
35
+ name = exp.shift
36
+ "__#{name.to_s.sub(/^@/, '')}"
37
+ end
27
38
 
28
39
  def process_lasgn(exp)
29
40
  out = ""
@@ -61,7 +61,7 @@ class RADRewriter < Rewriter
61
61
  result = s(:dummy,
62
62
  s(:lasgn, var_name, start_value),
63
63
  s(:while,
64
- s(:call, s(:lvar, var_name), :<=,
64
+ s(:call, s(:lvar, var_name), :<,
65
65
  s(:arglist, finish_value)),
66
66
  s(:block,
67
67
  body,
@@ -89,22 +89,25 @@ namespace :build do
89
89
  $sketch_methods.each do |meth|
90
90
  raw_rtc_meth = RADProcessor.translate(constantize(klass), meth)
91
91
  puts "Translator Error: #{raw_rtc_meth.inspect}" if raw_rtc_meth[0..8] == "// ERROR:"
92
- c_methods << raw_rtc_meth
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"
93
96
  end
94
- #$sketch_methods.each {|m| c_methods << RADProcessor.translate(constantize(klass), m) }
95
97
  c_methods.each {|meth| sketch_signatures << "#{meth.scan(/^\w*\s?\*?\n.*\)/)[0].gsub("\n", " ")};" }
96
98
  clean_c_methods = []
97
- c_methods.join("\n").each_with_index do |e,i|
98
- # need to take a look at the \(unsigned in the line below not sure if we are really trying to catch something like that
99
- if e !~ /^\s*(#{C_VAR_TYPES})(\W{1,6}|\(unsigned\()(#{$external_var_identifiers.join("|")})/ || $external_var_identifiers.empty?
100
- # use the list of identifers the external_vars method of the sketch and remove the parens the ruby2c sometime adds to variables
101
- e.gsub(/((#{$external_var_identifiers.join("|")})\(\))/, '\2') unless $external_var_identifiers.empty?
102
- clean_c_methods << e
103
- end
104
- end
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) }
105
101
  c_methods_with_timer = clean_c_methods.join.gsub(/loop\(\)\s\{/,"loop() {\ntrack_total_loop_time();")
106
- @setup.gsub!("// sketch signatures", "// sketch signatures\n#{ sketch_signatures.join("\n")}") unless sketch_signatures.empty?
107
- result = "#{@setup}\n#{c_methods_with_timer}\n"
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] << "additional_setup();" # call from setup
108
+ @setup[5] << @additional_setup.join("") #
109
+ end
110
+ result = "#{@setup.join( "\n" )}\n#{c_methods_with_timer}\n"
108
111
  name = @sketch_class.split(".").first
109
112
  File.open("#{@test_dir}#{name}/#{name}.cpp", "w"){|f| f << result}
110
113
  end
@@ -127,7 +130,16 @@ namespace :build do
127
130
  end
128
131
  CODE
129
132
  end
133
+ # allow variable declaration without quotes: @foo = int
134
+ ["long","unsigned","int","byte","short"].each do |type|
135
+ constantize(klass).module_eval <<-CODE
136
+ def self.#{type}
137
+ return "#{type}"
138
+ end
139
+ CODE
140
+ end
130
141
  eval File.read(@test_dir + @sketch_class)
142
+ @@as.process_external_vars(constantize(klass))
131
143
  @setup = @@as.compose_setup
132
144
  end
133
145
 
@@ -180,6 +192,7 @@ namespace :build do
180
192
  @test_dir = "examples/"
181
193
  end
182
194
  @sketch_class = ENV['sketch'] ? "#{ENV['sketch']}.rb" : "#{@sketch_directory}.rb"
195
+ $sketch_file_location = @test_dir + @sketch_class
183
196
  @file_names = []
184
197
  @plugin_names = []
185
198
  Dir.entries( File.expand_path(RAD_ROOT) ).each do |f|
@@ -0,0 +1,116 @@
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
+ return
46
+ end
47
+ value = var.split(",").first.lstrip
48
+ type = var.split(",")[1].nil? ? nil : var.split(",")[1].lstrip
49
+ translate_variables( name , type, value )
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
+ else
61
+ raise ArgumentError, "error message here.. got #{name}"
62
+ end
63
+
64
+
65
+ end
66
+
67
+ def translate_variables(name, type = nil, value = nil)
68
+
69
+ unless type.nil?
70
+ check_variable_type(type)
71
+ end
72
+
73
+ # classify the values
74
+ if value.class == Fixnum
75
+ # puts "translate_variables: #{name}, #{value}, #{type} is a fixnum, got #{value.class} on 74"
76
+ elsif value.class == Float
77
+ # puts "translate_variables: #{name}, #{value}, #{type} is a float, got #{value.class} on 76"
78
+ elsif value[0,1] !~ /\d/
79
+ # puts value[0,1]
80
+ # puts "translate_variables: #{name}, #{value}, #{type} is a number of some type, got #{value.class} on 79"
81
+ type = "char*"
82
+ value = "\"#{value}\""
83
+ elsif value !~ /(\.|x)/
84
+ # puts "translate_variables: #{name}, #{value}, #{type} is an integer, got #{value.class} on 83"
85
+ value = value.to_i
86
+ type = "int" if type.nil?
87
+ elsif value =~ /(\d*\.\d*)/ # and no
88
+ # puts "translate_variables: #{name}, #{value}, #{type} is a float, got #{value.class} on 87"
89
+ value = value.to_f
90
+ type = "float"
91
+ elsif value =~ /0x\d\d/
92
+ # puts "translate_variables: #{name}, #{value}, #{type} is a byte, got #{value.class} on 91"
93
+ type = "byte"
94
+ else
95
+ raise ArgumentError, "not sure what to do with a value of #{value} with a type like #{type}"
96
+ end
97
+
98
+ post_process_vars(name, type, value)
99
+ end
100
+
101
+
102
+
103
+ def post_process_vars(name, type, value = nil)
104
+ value = " = #{value}" if value
105
+
106
+ $external_var_identifiers << "__#{name}" unless $external_var_identifiers.include?("__#{name}")
107
+ $external_vars << "#{type} __#{name}#{value};"
108
+ end
109
+
110
+ def check_variable_type(type)
111
+ unless type =~ /#{C_VAR_TYPES}/
112
+ raise ArgumentError, "the following variable types are supported \n #{C_VAR_TYPES.gsub("|",", ")} got #{type}"
113
+ end
114
+ end
115
+
116
+ end
@@ -0,0 +1,78 @@
1
+ #!/usr/local/bin/ruby -w
2
+
3
+ $TESTING = true
4
+
5
+ # need to tell it where we are
6
+ # lets review these
7
+ C_VAR_TYPES = "int|void|unsigned|long|short|uint8_t|static|byte|float"
8
+ require 'vendor/rad/variable_processing'
9
+ require 'vendor/rad/arduino_sketch'
10
+ require 'test/unit'
11
+
12
+
13
+
14
+ class TestArrayProcessing < Test::Unit::TestCase
15
+
16
+ def setup
17
+ @t = ArduinoSketch.new
18
+ # vars
19
+ end
20
+
21
+ def test_int_array
22
+ name = "foo_a"
23
+ value_string = 1
24
+ expected = "int tomatoes[];"
25
+ result = @t.array("int tomatoes[]")
26
+ assert_equal(expected, result[0])
27
+ end
28
+
29
+ def test_int_array_with_semi
30
+ name = "foo_a"
31
+ value_string = 1
32
+ expected = "int tomatoes[];"
33
+ result = @t.array("int tomatoes[];")
34
+ assert_equal(expected, result[0])
35
+ end
36
+
37
+ def test_int_array_with_assignment
38
+ name = "foo_a"
39
+ value_string = 1
40
+ expected = "int tomatoes[4];"
41
+ result = @t.array("int tomatoes[] = {1,2,3,4}")
42
+ assert_equal(expected, result[0])
43
+ end
44
+
45
+ def test_int_array_with_assignment_and_semi
46
+ name = "foo_a"
47
+ value_string = 1
48
+ expected = "int tomatoes[3];"
49
+ result = @t.array("int tomatoes[] = {1,2,3};")
50
+ assert_equal(expected, result[0])
51
+ end
52
+
53
+ def test_unsigned_int_array
54
+ name = "foo_a"
55
+ value_string = 1
56
+ expected = "unsigned int tomatoes[];"
57
+ result = @t.array("unsigned int tomatoes[]")
58
+ assert_equal(expected, result[0])
59
+ end
60
+
61
+ def test_unsigned_int_array_with_assignment
62
+ name = "foo_a"
63
+ value_string = 1
64
+ expected = "unsigned int tomatoes[3];"
65
+ result = @t.array("unsigned int tomatoes[] = {1,2,3};")
66
+ assert_equal(expected, result[0])
67
+ end
68
+
69
+
70
+
71
+
72
+
73
+
74
+
75
+
76
+ # question for brian... do we need variable assignment with no value when
77
+ # we have "" and 0
78
+ end
@@ -0,0 +1,188 @@
1
+ #!/usr/local/bin/ruby -w
2
+
3
+ $TESTING = true
4
+
5
+ # need to tell it where we are
6
+ # lets review these
7
+ C_VAR_TYPES = "int|void|unsigned|long|short|uint8_t|static|byte|float"
8
+ require 'vendor/rad/variable_processing'
9
+ require 'vendor/rad/arduino_sketch'
10
+ require 'test/unit'
11
+
12
+
13
+
14
+ class TestVariableProcessing < Test::Unit::TestCase
15
+
16
+ def setup
17
+ @t = ArduinoSketch.new
18
+ end
19
+
20
+ # question for brian... do we need variable assignment with no value when
21
+ # we have "" and 0
22
+
23
+
24
+
25
+ def test_int_as_int
26
+ name = "foo_a"
27
+ value_string = 1
28
+ expected = "int __foo_a = 1;"
29
+ result = @t.pre_process_vars(name, value_string)
30
+ assert_equal(expected, result[0])
31
+ end
32
+
33
+ def test_string_as_int
34
+ name = "foo_b"
35
+ value_string = "1"
36
+ expected = "int __foo_b = 1;"
37
+ result = @t.pre_process_vars(name, value_string)
38
+ assert_equal(expected, result[0])
39
+ end
40
+
41
+ def test_float_as_float
42
+ name = "foo_c"
43
+ value_string = 0.10
44
+ expected = "float __foo_c = 0.1;"
45
+ result = @t.pre_process_vars(name, value_string)
46
+ assert_equal(expected, result[0])
47
+ end
48
+
49
+ def test_string_as_float
50
+ name = "foo_d"
51
+ value_string = "0.10"
52
+ expected = "float __foo_d = 0.1;"
53
+ result = @t.pre_process_vars(name, value_string)
54
+ assert_equal(expected, result[0])
55
+ end
56
+
57
+ def test_byte # would this to return hex
58
+ name = "foo_f"
59
+ value_string = 0x00
60
+ expected = "int __foo_f = 0;"
61
+ result = @t.pre_process_vars(name, value_string)
62
+ assert_equal(expected, result[0])
63
+ end
64
+
65
+ def test_byte_with_string_input
66
+ name = "foo_g"
67
+ value_string = "0x00"
68
+ expected = "byte __foo_g = 0x00;"
69
+ result = @t.pre_process_vars(name, value_string)
70
+ assert_equal(expected, result[0])
71
+ end
72
+
73
+ def test_string
74
+ name = "foo_h"
75
+ value_string = "arduino"
76
+ expected = "char* __foo_h = \"arduino\";"
77
+ result = @t.pre_process_vars(name, value_string)
78
+ assert_equal(expected, result[0])
79
+ end
80
+
81
+ def test_int_with_type
82
+ name = "foo_i"
83
+ value_string = "int"
84
+ expected = "long __foo_i;"
85
+ result = @t.pre_process_vars(name, value_string)
86
+ assert_equal(expected, result[0])
87
+ end
88
+
89
+ def test_odd_name
90
+ name = "bacon_j"
91
+ value_string = "arduino"
92
+ expected = "char* __bacon_j = \"arduino\";"
93
+ result = @t.pre_process_vars(name, value_string)
94
+ assert_equal(expected, result[0])
95
+ end
96
+
97
+ def test_int_with_type
98
+ name = "foo_k"
99
+ value_string = "2, int"
100
+ expected = "int __foo_k = 2;"
101
+ result = @t.pre_process_vars(name, value_string)
102
+ assert_equal(expected, result[0])
103
+ end
104
+
105
+ def test_int_with_long
106
+ name = "foo_l"
107
+ value_string = "2, int"
108
+ expected = "int __foo_l = 2;"
109
+ result = @t.pre_process_vars(name, value_string)
110
+ assert_equal(expected, result[0])
111
+ end
112
+
113
+ def test_int_with_byte
114
+ name = "foo_m"
115
+ value_string = "2, byte"
116
+ expected = "byte __foo_m = 2;"
117
+ result = @t.pre_process_vars(name, value_string)
118
+ assert_equal(expected, result[0])
119
+ end
120
+
121
+ def test_int_with_unsigned_int
122
+ name = "foo_n"
123
+ value_string = "2, unsigned int"
124
+ expected = "unsigned int __foo_n = 2;"
125
+ result = @t.pre_process_vars(name, value_string)
126
+ assert_equal(expected, result[0])
127
+ end
128
+
129
+ def test_int_with_unsigned_long
130
+ name = "foo_o"
131
+ value_string = "2, unsigned long"
132
+ expected = "unsigned long __foo_o = 2;"
133
+ result = @t.pre_process_vars(name, value_string)
134
+ assert_equal(expected, result[0])
135
+ end
136
+
137
+ def test_int_with_unsigned_long
138
+ name = "foo_p"
139
+ value_string = "2, long unsigned"
140
+ expected = "long unsigned __foo_p = 2;"
141
+ result = @t.pre_process_vars(name, value_string)
142
+ assert_equal(expected, result[0])
143
+ end
144
+
145
+ def test_int_with_short_int
146
+ name = "foo_q"
147
+ value_string = "2, short int"
148
+ expected = "short int __foo_q = 2;"
149
+ result = @t.pre_process_vars(name, value_string)
150
+ assert_equal(expected, result[0])
151
+ end
152
+
153
+ def test_int_with_unsigned_short_int
154
+ name = "foo_r"
155
+ value_string = "2, unsigned short int"
156
+ expected = "unsigned short int __foo_r = 2;"
157
+ result = @t.pre_process_vars(name, value_string)
158
+ assert_equal(expected, result[0])
159
+ end
160
+
161
+ def test_float_with_type
162
+ name = "foo_s"
163
+ value_string = "2.0, float"
164
+ expected = "float __foo_s = 2.0;"
165
+ result = @t.pre_process_vars(name, value_string)
166
+ assert_equal(expected, result[0])
167
+ end
168
+
169
+ def test_true
170
+ name = "foo_t"
171
+ value_string = true
172
+ expected = "bool __foo_t = 1;"
173
+ result = @t.pre_process_vars(name, value_string)
174
+ assert_equal(expected, result[0])
175
+ end
176
+
177
+ def test_false
178
+ name = "foo_v"
179
+ value_string = false
180
+ expected = "bool __foo_v = 0;"
181
+ result = @t.pre_process_vars(name, value_string)
182
+ assert_equal(expected, result[0])
183
+ end
184
+
185
+
186
+
187
+
188
+ end