madrona-rad 0.2.4 → 0.2.5

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.
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