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
@@ -0,0 +1,70 @@
1
+ class I2cEeprom < ArduinoPlugin
2
+
3
+ # RAD plugins are c methods, directives, external variables and assignments and calls
4
+ # that may be added to the main setup method
5
+ # function prototypes not needed since we generate them automatically
6
+
7
+ # directives, external variables and setup assignments and calls can be added rails style (not c style)
8
+
9
+
10
+ # add to directives
11
+ plugin_directives "#define BUF_SIZE 32"
12
+
13
+
14
+ # add to external variables
15
+ external_variables "byte i2cbuf[BUF_SIZE];"
16
+
17
+ # add the following to the setup method
18
+ # add_to_setup
19
+
20
+ void i2c_eeprom_write_byte( int deviceaddress, unsigned int eeaddress, byte data ) {
21
+ int rdata = data;
22
+ Wire.beginTransmission(deviceaddress);
23
+ Wire.send((int)(eeaddress >> 8)); // Address High Byte
24
+ Wire.send((int)(eeaddress & 0xFF)); // Address Low Byte
25
+ Wire.send(rdata);
26
+ Wire.endTransmission();
27
+ }
28
+
29
+ // Address is a page address, 6-bit (63). More and end will wrap around
30
+ // But data can be maximum of 28 bytes, because the Wire library has a buffer of 32 bytes
31
+
32
+ void i2c_eeprom_write_page( int deviceaddress, unsigned int eeaddresspage, byte* data, byte length ) {
33
+ Wire.beginTransmission(deviceaddress);
34
+ Wire.send((int)(eeaddresspage >> 8)); // Address High Byte
35
+ Wire.send((int)(eeaddresspage & 0xFF)); // Address Low Byte
36
+ byte c;
37
+ for ( c = 0; c < length; c++)
38
+ Wire.send(data[c]);
39
+ Wire.endTransmission();
40
+ delay(10); // need some delay
41
+ }
42
+
43
+ byte i2c_eeprom_read_byte( int deviceaddress, unsigned int eeaddress ) {
44
+ byte rdata = 0xFF;
45
+ Wire.beginTransmission(deviceaddress);
46
+ Wire.send((int)(eeaddress >> 8)); // Address High Byte
47
+ Wire.send((int)(eeaddress & 0xFF)); // Address Low Byte
48
+ Wire.endTransmission();
49
+ Wire.requestFrom(deviceaddress,1);
50
+ if (Wire.available()) rdata = Wire.receive();
51
+ return rdata;
52
+ }
53
+
54
+ // should not read more than 28 bytes at a time!
55
+
56
+ void i2c_eeprom_read_buffer( int deviceaddress, unsigned int eeaddress, byte *buffer, int length ) {
57
+ Wire.beginTransmission(deviceaddress);
58
+ Wire.send((int)(eeaddress >> 8)); // Address High Byte
59
+ Wire.send((int)(eeaddress & 0xFF)); // Address Low Byte
60
+ Wire.endTransmission();
61
+ Wire.requestFrom(deviceaddress,length);
62
+ //int c = 0;
63
+ for ( int c = 0; c < length; c++ )
64
+ if (Wire.available()) buffer[c] = Wire.receive();
65
+ }
66
+
67
+
68
+
69
+
70
+ end
@@ -54,6 +54,7 @@ def initialize #:nodoc:
54
54
  # $plugin_methods_hash = $plugin_methods_hash || {} ### new
55
55
  # $plugins_to_load = $plugins_to_load || [] ### new
56
56
  $add_to_setup = $add_to_setup || []
57
+ $load_libraries = $load_libraries || []
57
58
 
58
59
 
59
60
  end
@@ -65,6 +66,10 @@ end
65
66
  # if the sketch has them, we include the plugins in the build...
66
67
  # otherwise not..
67
68
 
69
+ def include_wire
70
+ $load_libraries << "Wire" unless $load_libraries.include?("Wire")
71
+ end
72
+
68
73
 
69
74
  def add_to_setup(*args)
70
75
  if args
@@ -96,6 +101,24 @@ end
96
101
  end
97
102
  end
98
103
 
104
+ def add_blink_m_struct
105
+ $plugin_structs[:blink_m] = <<-STR
106
+ typedef struct _blinkm_script_line {
107
+ uint8_t dur;
108
+ uint8_t cmd[4]; // cmd,arg1,arg2,arg3
109
+ } blinkm_script_line;
110
+ STR
111
+ end
112
+
113
+ def self.add_blink_m_struct
114
+ $plugin_structs[:blink_m] = <<-STR
115
+ typedef struct _blinkm_script_line {
116
+ uint8_t dur;
117
+ uint8_t cmd[4]; // cmd,arg1,arg2,arg3
118
+ } blinkm_script_line;
119
+ STR
120
+ end
121
+
99
122
  def add_debounce_struct
100
123
  $plugin_structs[:debounce] = <<-STR
101
124
  struct debounce {
@@ -160,7 +183,7 @@ end
160
183
  ## need a test for this
161
184
  ## fails on string interpolation, but since ruby_to_c also currently fails ...
162
185
  sketch_string = sketch_string.gsub(/#(?!\{.*\}).*/, "")
163
- plugin_signatures << plugin_string.scan(/^\s((int|void|unsigned|long|short|uint8_t|static).*\(.*\))/)
186
+ plugin_signatures << plugin_string.scan(/^\s*(((#{PLUGIN_C_VAR_TYPES})\s*)+\w*\(.*\))/)
164
187
  # gather just the method name and then add to #plugin_methods_hash
165
188
  plugin_signatures[0].map {|sig| "#{sig[0]}"}.each {|m| plugin_methods << m.gsub!(/^.*\s(\w*)\(.*\)/, '\1')}
166
189
  # we don't know the methods yet, so...
@@ -182,13 +205,13 @@ end
182
205
  first_process = plugin_string
183
206
  # todo: need to add plugin names to the methods, so we can add them as comments in the c code
184
207
  # gather the c methods
185
- $plugin_methods << first_process.scan(/^\s*(((int|void|unsigned|long|short|uint8_t|static).*\)).*(\n.*)*^\s*\})/)
186
- plugin_signatures << first_process.scan(/^\s((int|void|unsigned|long|short|uint8_t|static).*\(.*\))/)
208
+ $plugin_methods << first_process.scan(/^\s*(((#{PLUGIN_C_VAR_TYPES}).*\)).*(\n.*)*^\s*\})/)
209
+ plugin_signatures << first_process.scan(/^\s((#{PLUGIN_C_VAR_TYPES}).*\(.*\))/)
187
210
  $plugin_signatures << plugin_signatures[0].map {|sig| "#{sig[0]};"}
188
211
  ## strip out the methods and pass it back
189
212
  result = plugin_string
190
213
  # strip out the c methods so we have only ruby before eval
191
- result.gsub(/^\s*(int|void|unsigned|long|short|uint8_t|static).*(\n.*)*^\s*\}/, "" )
214
+ result.gsub(/^\s*(#{PLUGIN_C_VAR_TYPES}).*(\n.*)*^\s*\}/, "" )
192
215
 
193
216
  end
194
217
 
@@ -153,23 +153,24 @@
153
153
  #
154
154
 
155
155
  class ArduinoSketch
156
- @@servo_inc = FALSE # flag to indicate this library instance has been created at least once - BBR
157
- @@slcdpa_inc = FALSE # same
158
- @@slcdsf_inc = FALSE # same
159
- @@swser_inc = FALSE # same
160
- @@frequency_inc = FALSE # same
156
+
157
+ include ExternalVariableProcessing
158
+
159
+ # find another way to do this
160
+ @@frequency_inc = FALSE
161
+ @@twowire_inc = FALSE
161
162
 
162
163
  def initialize #:nodoc:
163
164
  @servo_settings = [] # need modular way to add this
164
165
  @debounce_settings = [] # need modular way to add this
165
166
  @servo_pins = []
166
167
  @debounce_pins = []
167
- @@array_vars = []
168
- @@external_vars =[]
168
+ $external_array_vars = []
169
+ $external_vars =[]
169
170
  $external_var_identifiers = []
170
171
  $sketch_methods = []
171
- $load_libraries = []
172
- $include_wire = false
172
+ $load_libraries ||= []
173
+ $defines ||= []
173
174
 
174
175
  @declarations = []
175
176
  @pin_modes = {:output => [], :input => []}
@@ -249,19 +250,19 @@ class ArduinoSketch
249
250
  if v.split(",")[0] == "char"
250
251
  ## default is 40 characters
251
252
  if v.split(",")[2]
252
- @@external_vars << "#{v.split(",")[0]}* #{k}[#{v.split(",")[2].lstrip}];"
253
+ $external_vars << "#{v.split(",")[0]}* #{k}[#{v.split(",")[2].lstrip}];"
253
254
  else
254
- @@external_vars << "#{v.split(",")[0]} #{k}[40] = \"#{v.split(",")[1].lstrip}\";"
255
+ $external_vars << "#{v.split(",")[0]} #{k}[40] = \"#{v.split(",")[1].lstrip}\";"
255
256
  end
256
257
  else
257
- @@external_vars << "#{v.split(",")[0]} #{k} =#{v.split(",")[1]};"
258
+ $external_vars << "#{v.split(",")[0]} #{k} =#{v.split(",")[1]};"
258
259
  end
259
260
  else
260
261
  if v.split(",")[0] == "char"
261
- @@external_vars << "#{v.split(",")[0]} #{k}[40];"
262
+ $external_vars << "#{v.split(",")[0]} #{k}[40];"
262
263
  else
263
264
 
264
- @@external_vars << "#{v.split(",")[0]} #{k};"
265
+ $external_vars << "#{v.split(",")[0]} #{k};"
265
266
  end
266
267
  end
267
268
  # check chars work here
@@ -270,7 +271,7 @@ class ArduinoSketch
270
271
  end
271
272
  end
272
273
 
273
-
274
+ # phasing this out
274
275
  def add_to_setup(*args)
275
276
  if args
276
277
  args.each do |arg|
@@ -279,17 +280,70 @@ class ArduinoSketch
279
280
  end
280
281
  end
281
282
 
282
- # work in progress
283
+ # phasing this out
283
284
  def external_arrays(*args)
284
285
  if args
285
286
  args.each do |arg|
286
- @@array_vars << arg
287
+ $external_array_vars << arg
287
288
  end
288
289
  end
289
290
 
290
291
  end
292
+
293
+ # array "char buffer[32]"
294
+ # result: char buffer[32];
295
+ # array "char buffer[32]"
296
+ # result: char buffer[32];
297
+ # todo
298
+ # need to feed array external array identifiers to rtc if they are in plugins or libraries
299
+ def array(arg)
300
+ if arg
301
+ arg = arg.chomp.rstrip.lstrip
302
+ name = arg.scan(/\s*(\w*)\[\d*\]?/).first.first
303
+ if /\w*\[\d*\]\s*\=\s*\{(.*)\}/ =~ arg
304
+ assignment = arg.scan(/\w*\[\d*\]\s*\=\s*\{(.*)\}/).first.first
305
+ array_size = assignment.split(",").length
306
+ if /\[(\s*)\]/ =~ arg
307
+ arg.gsub!(/(\[\d*\])/, "[#{array_size}]")
308
+ end
309
+ end
310
+ arg = arg.scan(/^((\s*|\w*)*\s*\w*\[\d*\])?/).first.first
311
+ arg = "#{arg};" unless arg[-1,1] == ";"
312
+ $external_var_identifiers << name unless $external_var_identifiers.include?(name)
313
+ # add array_name declaration
314
+ $external_array_vars << arg unless $external_array_vars.include?(arg)
315
+ end
316
+ end
317
+
318
+ # define "DS1307_SEC 0"
319
+ # result: #define DS1307_SEC 0
320
+ def define(arg)
321
+ if arg
322
+ arg = arg.chomp.rstrip.lstrip
323
+ arg = "#define #{arg}"
324
+ $defines << arg
325
+ end
326
+ end
327
+
328
+ # need better location.. module?
329
+ def self.add_to_setup(meth)
330
+ meth = meth.gsub("setup", "additional_setup")
331
+ post_process_ruby_to_c_methods(meth)
332
+ end
333
+
334
+ def self.post_process_ruby_to_c_methods(e)
335
+ clean_c_methods = []
336
+ # need to take a look at the \(unsigned in the line below not sure if we are really trying to catch something like that
337
+ if e !~ /^\s*(#{C_VAR_TYPES})(\W{1,6}|\(unsigned\()(#{$external_var_identifiers.join("|")})/ || $external_var_identifiers.empty?
338
+ # use the list of identifers the external_vars method of the sketch and remove the parens the ruby2c sometime adds to variables
339
+ # keep an eye on the gsub!.. are we getting nil errors
340
+ e.gsub!(/((#{$external_var_identifiers.join("|")})\(\))/, '\2') unless $external_var_identifiers.empty?
341
+ clean_c_methods << e
342
+ end
343
+ return clean_c_methods.join( "\n" )
344
+ end
291
345
 
292
- # Confiugre a single pin for output and setup a method to refer to that pin, i.e.:
346
+ # Configure a single pin for output and setup a method to refer to that pin, i.e.:
293
347
  #
294
348
  # output_pin 7, :as => :led
295
349
  #
@@ -322,11 +376,28 @@ class ArduinoSketch
322
376
  return
323
377
  when :freq_out || :freq_gen || :frequency_generator
324
378
  frequency_timer(num, opts)
325
- return
379
+ return
380
+ when :i2c
381
+ two_wire(num, opts) unless @@twowire_inc
382
+ return #
383
+ when :i2c_eeprom
384
+ two_wire(num, opts) unless @@twowire_inc
385
+ return #
386
+ when :i2c_ds1307
387
+ two_wire(num, opts) unless @@twowire_inc
388
+ ds1307(num, opts)
389
+ return #
390
+ when :i2c_blinkm
391
+ two_wire(num, opts) unless @@twowire_inc
392
+ blinkm
393
+ return #
394
+ when :onewire
395
+ one_wire(num, opts)
396
+ return #
326
397
  else
327
- raise ArgumentError, "today's device choices are: :servo, :original_servo_setup, :pa_lcd, :sf_lcd, and :freq_out, got #{opts[:device]}"
398
+ raise ArgumentError, "today's device choices are: :servo, :original_servo_setup, :pa_lcd, :sf_lcd, :freq_out,:i2c, :i2c_eeprom, :i2c_ds1307, and :i2c_blinkm got #{opts[:device]}"
399
+ end
328
400
  end
329
- end
330
401
 
331
402
  # remove the next 14 lines as soon as documentation on new :device => :servo option is out
332
403
 
@@ -454,7 +525,7 @@ class ArduinoSketch
454
525
  # transitioning to :device => :button syntax
455
526
  if opts[:latch] || opts[:device] == :button
456
527
  if opts[:device] == :button
457
- opts[:latch] ||= :on
528
+ opts[:latch] ||= :off
458
529
  end
459
530
  # add debounce settings to dbce struct array
460
531
  ArduinoPlugin.add_debounce_struct
@@ -499,7 +570,7 @@ class ArduinoSketch
499
570
  end
500
571
 
501
572
  # Treat a pair of digital I/O pins as a serial line. See: http://www.arduino.cc/en/Tutorial/SoftwareSerial
502
- def software_serial(rx, tx, opts={})
573
+ def software_serial(rx, tx, opts={})
503
574
  raise ArgumentError, "can only define rx from Fixnum, got #{rx.class}" unless rx.is_a?(Fixnum)
504
575
  raise ArgumentError, "can only define tx from Fixnum, got #{tx.class}" unless tx.is_a?(Fixnum)
505
576
 
@@ -512,6 +583,7 @@ class ArduinoSketch
512
583
  accessor << "SoftwareSerial& #{opts[ :as ]}() {"
513
584
  accessor << "\treturn _#{opts[ :as ]};"
514
585
  accessor << "}"
586
+ @@swser_inc ||= FALSE
515
587
  if (@@swser_inc == FALSE) # on second instance this stuff can't be repeated
516
588
  @@swser_inc = TRUE
517
589
  accessor << "int read(SoftwareSerial& s) {"
@@ -552,6 +624,7 @@ class ArduinoSketch
552
624
  accessor << "SWSerLCDpa& #{opts[ :as ]}() {"
553
625
  accessor << "\treturn _#{opts[ :as ]};"
554
626
  accessor << "}"
627
+ @@slcdpa_inc ||= FALSE
555
628
  if (@@slcdpa_inc == FALSE) # on second instance this stuff can't be repeated - BBR
556
629
  @@slcdpa_inc = TRUE
557
630
  accessor << "void print( SWSerLCDpa& s, uint8_t b ) {"
@@ -634,7 +707,7 @@ class ArduinoSketch
634
707
 
635
708
  @signatures << "SWSerLCDpa& #{opts[ :as ]}();"
636
709
 
637
- @other_setup << "_#{opts[ :as ]}.begin(#{rate});"
710
+ @other_setup << "\t_#{opts[ :as ]}.begin(#{rate});"
638
711
  end
639
712
  end
640
713
 
@@ -654,6 +727,7 @@ class ArduinoSketch
654
727
  accessor << "SWSerLCDsf& #{opts[ :as ]}() {"
655
728
  accessor << "\treturn _#{opts[ :as ]};"
656
729
  accessor << "}"
730
+ @@slcdsf_inc ||= FALSE # assign only if nil
657
731
  if (@@slcdsf_inc == FALSE) # on second instance this stuff can't be repeated - BBR
658
732
  @@slcdsf_inc = TRUE
659
733
  accessor << "void print( SWSerLCDsf& s, uint8_t b ) {"
@@ -706,16 +780,14 @@ class ArduinoSketch
706
780
 
707
781
  @signatures << "SWSerLCDsf& #{opts[ :as ]}();"
708
782
 
709
- @other_setup << "_#{opts[ :as ]}.begin(#{rate});"
783
+ @other_setup << "\t_#{opts[ :as ]}.begin(#{rate});"
710
784
  end
711
785
  end
712
786
 
713
787
 
714
788
 
715
-
716
-
717
- def servo(spin, opts={}) # servo motor routines # how about pin instead of spin
718
- raise ArgumentError, "can only define spin from Fixnum, got #{spin.class}" unless spin.is_a?(Fixnum)
789
+ def servo(pin, opts={}) # servo motor routines #
790
+ raise ArgumentError, "can only define pin from Fixnum, got #{pin.class}" unless pin.is_a?(Fixnum)
719
791
 
720
792
  minp = opts[:min] ? opts[:min] : 544
721
793
  maxp = opts[:max] ? opts[:max] : 2400
@@ -727,7 +799,7 @@ class ArduinoSketch
727
799
  accessor << "Servo& #{opts[ :as ]}() {"
728
800
  accessor << "\treturn _#{opts[ :as ]};"
729
801
  accessor << "}"
730
-
802
+ @@servo_inc ||= FALSE
731
803
  if (@@servo_inc == FALSE) # on second instance this stuff can't be repeated - BBR
732
804
  @@servo_inc = TRUE
733
805
  accessor << "void detach( Servo& s ) {"
@@ -754,16 +826,17 @@ class ArduinoSketch
754
826
 
755
827
  @signatures << "Servo& #{opts[ :as ]}();"
756
828
 
757
- @other_setup << "\t_#{opts[ :as ]}.attach(#{spin}, #{opts[:position]}, #{minp}, #{maxp});" if opts[:position]
758
- @other_setup << "\t_#{opts[ :as ]}.attach(#{spin}, #{minp}, #{maxp});" unless opts[:position]
829
+ @other_setup << "\t_#{opts[ :as ]}.attach(#{pin}, #{opts[:position]}, #{minp}, #{maxp});" if opts[:position]
830
+ @other_setup << "\t_#{opts[ :as ]}.attach(#{pin}, #{minp}, #{maxp});" unless opts[:position]
759
831
 
760
832
  end
761
833
  end
762
834
 
763
- def frequency_timer(pin, opts={}) # frequency timer routines
764
-
835
+ def frequency_timer(pin, opts={}) # frequency timer routines
836
+
765
837
  raise ArgumentError, "can only define pin from Fixnum, got #{pin.class}" unless pin.is_a?(Fixnum)
766
838
  raise ArgumentError, "only pin 11 may be used for freq_out, got #{pin}" unless pin == 11
839
+
767
840
  if opts[:enable]
768
841
  raise ArgumentError, "enable option must include the frequency or period option" unless opts[:frequency] || opts[:period]
769
842
  end
@@ -777,28 +850,29 @@ class ArduinoSketch
777
850
 
778
851
  if opts[:as]
779
852
 
853
+ @@frequency_inc = TRUE
780
854
  @declarations << "FrequencyTimer2 _#{opts[ :as ]} = FrequencyTimer2();"
781
855
  accessor = []
782
856
  $load_libraries << "FrequencyTimer2"
783
857
  accessor << "FrequencyTimer2& #{opts[ :as ]}() {"
784
858
  accessor << "\treturn _#{opts[ :as ]};"
785
859
  accessor << "}"
786
-
787
- if (@@frequency_inc == FALSE) # on second instance this stuff can't be repeated - BBR
788
- @@frequency_inc = TRUE
789
- accessor << "void set_frequency( FrequencyTimer2& s, int b ) {"
790
- accessor << "\treturn s.setPeriod( 1000000L/b );"
791
- accessor << "}"
792
- accessor << "void set_period( FrequencyTimer2& s, int b ) {"
793
- accessor << "\treturn s.setPeriod( b );"
794
- accessor << "}"
795
- accessor << "void enable( FrequencyTimer2& s ) {"
796
- accessor << "\treturn s.enable();"
797
- accessor << "}"
798
- accessor << "void disable( FrequencyTimer2& s ) {"
799
- accessor << "\treturn s.disable();"
800
- accessor << "}"
801
- end
860
+ # add ||=
861
+ # if (@@frequency_inc == FALSE) # on second instance this stuff can't be repeated - BBR
862
+ # @@frequency_inc = TRUE
863
+ accessor << "void set_frequency( FrequencyTimer2& s, int b ) {"
864
+ accessor << "\treturn s.setPeriod( 1000000L/b );"
865
+ accessor << "}"
866
+ accessor << "void set_period( FrequencyTimer2& s, int b ) {"
867
+ accessor << "\treturn s.setPeriod( b );"
868
+ accessor << "}"
869
+ accessor << "void enable( FrequencyTimer2& s ) {"
870
+ accessor << "\treturn s.enable();"
871
+ accessor << "}"
872
+ accessor << "void disable( FrequencyTimer2& s ) {"
873
+ accessor << "\treturn s.disable();"
874
+ accessor << "}"
875
+ # end
802
876
 
803
877
  @accessors << accessor.join( "\n" )
804
878
 
@@ -810,119 +884,284 @@ class ArduinoSketch
810
884
  @other_setup << "\tFrequencyTimer2::enable();" if opts[:enable] == :true
811
885
  end
812
886
  end
813
-
814
887
 
815
-
816
-
888
+ def one_wire(pin, opts={})
889
+ raise ArgumentError, "can only define pin from Fixnum, got #{pin.class}" unless pin.is_a?(Fixnum)
890
+
891
+ if opts[:as]
892
+ @declarations << "OneWire _#{opts[ :as ]} = OneWire(#{pin});"
893
+ accessor = []
894
+ $load_libraries << "OneWire"
895
+ accessor << "OneWire& #{opts[ :as ]}() {"
896
+ accessor << "\treturn _#{opts[ :as ]};"
897
+ accessor << "}"
898
+ @@onewire_inc ||= FALSE
899
+ if (@@onewire_inc == FALSE) # on second instance this stuff can't be repeated - BBR
900
+ @@onewire_inc = TRUE
901
+ accessor << "uint8_t reset(OneWire& s) {"
902
+ accessor << "\treturn s.reset();"
903
+ accessor << "}"
904
+ accessor << "void skip(OneWire& s) {"
905
+ accessor << "\treturn s.skip();"
906
+ accessor << "}"
907
+ accessor << "void write(OneWire& s, uint8_t v, uint8_t p = 0) {" # "power = 0" ?????
908
+ accessor << "\treturn s.write( v, p );"
909
+ accessor << "}"
910
+ accessor << "uint8_t read(OneWire& s) {"
911
+ accessor << "\treturn s.read();"
912
+ accessor << "}"
913
+ accessor << "void write_bit( OneWire& s, uint8_t b ) {"
914
+ accessor << "\treturn s.write_bit( b );"
915
+ accessor << "}"
916
+ accessor << "uint8_t read_bit(OneWire& s) {"
917
+ accessor << "\treturn s.read_bit();"
918
+ accessor << "}"
919
+ accessor << "void depower(OneWire& s) {"
920
+ accessor << "\treturn s.depower();"
921
+ accessor << "}"
922
+ end
923
+ @accessors << accessor.join( "\n" )
924
+
925
+ @signatures << "OneWire& #{opts[ :as ]}();"
926
+ end
927
+ end
928
+
929
+ def two_wire (pin, opts={}) # i2c Two-Wire
930
+
931
+ raise ArgumentError, "can only define pin from Fixnum, got #{pin.class}" unless pin.is_a?(Fixnum)
932
+ raise ArgumentError, "only pin 19 may be used for i2c, got #{pin}" unless pin == 19
933
+
934
+ if opts[:as]
935
+
936
+ @@twowire_inc = TRUE
937
+ @declarations << "TwoWire _wire = TwoWire();"
938
+ # @declarations << "TwoWire _#{opts[ :as ]} = TwoWire();"
939
+ accessor = []
940
+ $load_libraries << "Wire"
941
+ accessor << "TwoWire& wire() {"
942
+ accessor << "\treturn _wire;"
943
+ # accessor << "TwoWire& #{opts[ :as ]}() {"
944
+ # accessor << "\treturn _#{opts[ :as ]};"
945
+ accessor << "}"
946
+ accessor << "void begin( TwoWire& s) {"
947
+ accessor << "\treturn s.begin();"
948
+ accessor << "}"
949
+ accessor << "void begin( TwoWire& s, uint8_t a) {"
950
+ accessor << "\treturn s.begin(a);"
951
+ accessor << "}"
952
+ accessor << "void begin( TwoWire& s, int a) {"
953
+ accessor << "\treturn s.begin(a);"
954
+ accessor << "}"
955
+ accessor << "void beginTransmission( TwoWire& s, uint8_t a ) {"
956
+ accessor << "\treturn s.beginTransmission( a );"
957
+ accessor << "}"
958
+ accessor << "void beginTransmission( TwoWire& s, int a ) {"
959
+ accessor << "\treturn s.beginTransmission( a );"
960
+ accessor << "}"
961
+ accessor << "void endTransmission( TwoWire& s ) {"
962
+ accessor << "\treturn s.endTransmission();"
963
+ accessor << "}"
964
+ accessor << "void requestFrom( TwoWire& s, uint8_t a, uint8_t q) {"
965
+ accessor << "\treturn s.requestFrom( a, q );"
966
+ accessor << "}"
967
+ accessor << "void requestFrom( TwoWire& s, int a, int q) {"
968
+ accessor << "\treturn s.requestFrom( a, q );"
969
+ accessor << "}"
970
+ accessor << "void send( TwoWire& s, uint8_t d) {"
971
+ accessor << "\treturn s.send(d);"
972
+ accessor << "}"
973
+ accessor << "void send( TwoWire& s, int d) {"
974
+ accessor << "\treturn s.send(d);"
975
+ accessor << "}"
976
+ accessor << "void send( TwoWire& s, char* d) {"
977
+ accessor << "\treturn s.send(d);"
978
+ accessor << "}"
979
+ accessor << "void send( TwoWire& s, uint8_t* d, uint8_t q) {"
980
+ accessor << "\treturn s.send( d, q );"
981
+ accessor << "}"
982
+ accessor << "uint8_t available( TwoWire& s) {"
983
+ accessor << "\treturn s.available();"
984
+ accessor << "}"
985
+ accessor << "uint8_t receive( TwoWire& s) {"
986
+ accessor << "\treturn s.receive();"
987
+ accessor << "}"
988
+
989
+ @accessors << accessor.join( "\n" )
990
+
991
+ @signatures << "TwoWire& wire();"
992
+ # @signatures << "TwoWire& #{opts[ :as ]}();"
993
+
994
+ @other_setup << "\t_wire.begin();" if opts[:enable] == :true
995
+ # @other_setup << "\t_#{opts[ :as ]}.begin();" if opts[:enable] == :true
996
+
997
+ end
998
+ end
999
+
1000
+ def ds1307(pin, opts={}) # DS1307 motor routines
1001
+ raise ArgumentError, "can only define pin from Fixnum, got #{pin.class}" unless pin.is_a?(Fixnum)
1002
+ raise ArgumentError, "only pin 19 may be used for i2c, got #{pin}" unless pin == 19
1003
+ # raise ArgumentError, "only one DS1307 may be used for i2c" if @@ds1307_inc == :true
1004
+
1005
+ if opts[:as]
1006
+ @@ds1307_inc = TRUE
1007
+ @declarations << "DS1307 _#{opts[ :as ]} = DS1307();"
1008
+ accessor = []
1009
+ $load_libraries << "DS1307"
1010
+ accessor << "DS1307& #{opts[ :as ]}() {"
1011
+ accessor << "\treturn _#{opts[ :as ]};"
1012
+ accessor << "}"
1013
+ accessor << "int get( DS1307& s, int b, boolean r ) {"
1014
+ accessor << "\treturn s.get( b, r );"
1015
+ accessor << "}"
1016
+ accessor << "void set( DS1307& s, int b, int r ) {"
1017
+ accessor << "\treturn s.set( b, r );"
1018
+ accessor << "}"
1019
+ accessor << "void start( DS1307& s ) {"
1020
+ accessor << "\treturn s.start();"
1021
+ accessor << "}"
1022
+ accessor << "void stop( DS1307& s ) {"
1023
+ accessor << "\treturn s.stop();"
1024
+ accessor << "}"
1025
+
1026
+ @accessors << accessor.join( "\n" )
1027
+
1028
+ @signatures << "DS1307& #{opts[ :as ]}();"
1029
+ @other_setup << "\t_#{opts[ :as ]}.start();" if opts[:rtcstart]
1030
+
1031
+ end
1032
+ end
1033
+
1034
+
1035
+
1036
+ def blinkm
1037
+
1038
+ end
1039
+
1040
+
1041
+
1042
+
817
1043
  def compose_setup #:nodoc: also composes headers and signatures
1044
+
1045
+ declarations = []
1046
+ plugin_directives = []
1047
+ signatures = []
1048
+ external_vars = []
1049
+ setup = []
1050
+ additional_setup =[]
1051
+ helpers = []
1052
+ main = []
818
1053
  result = []
819
1054
 
820
- result << comment_box( "Auto-generated by RAD" )
1055
+ declarations << comment_box( "Auto-generated by RAD" )
821
1056
 
822
- result << "#include <WProgram.h>\n"
823
- result << "#include <SoftwareSerial.h>\n"
824
- result << "#include <Wire.h>\n" if $include_wire == true ##
825
- $load_libraries.each { |lib| result << "#include <#{lib}.h>" } unless $load_libraries.nil?
1057
+ declarations << "#include <WProgram.h>\n"
1058
+ declarations << "#include <SoftwareSerial.h>\n"
1059
+ $load_libraries.each { |lib| declarations << "#include <#{lib}.h>" } unless $load_libraries.nil?
1060
+ $defines.each { |d| declarations << d }
826
1061
 
827
- result << comment_box( 'plugin directives' )
828
- $plugin_directives.each {|dir| result << dir } unless $plugin_directives.nil? || $plugin_directives.empty?
1062
+ plugin_directives << comment_box( 'plugin directives' )
1063
+ $plugin_directives.each {|dir| plugin_directives << dir } unless $plugin_directives.nil? || $plugin_directives.empty?
829
1064
 
830
- result << comment_box( 'method signatures' )
831
- result << "void loop();"
832
- result << "void setup();"
833
- result << "// sketch signatures"
834
- @signatures.each {|sig| result << sig}
835
- result << "// sketch signatures"
836
- result << "// plugin signatures"
837
- $plugin_signatures.each {|sig| result << sig } unless $plugin_signatures.nil? || $plugin_signatures.empty?
838
- result << "\n" + comment_box( "plugin external variables" )
839
- $plugin_external_variables.each { |meth| result << meth } unless $plugin_external_variables.nil? || $plugin_external_variables.empty?
1065
+ signatures << comment_box( 'method signatures' )
1066
+ signatures << "void loop();"
1067
+ signatures << "void setup();"
1068
+ signatures << "// sketch signatures"
1069
+ @signatures.each {|sig| signatures << sig}
1070
+ signatures << "// plugin signatures"
1071
+ $plugin_signatures.each {|sig| signatures << sig } unless $plugin_signatures.nil? || $plugin_signatures.empty?
1072
+ external_vars << "\n" + comment_box( "plugin external variables" )
1073
+ $plugin_external_variables.each { |meth| external_vars << meth } unless $plugin_external_variables.nil? || $plugin_external_variables.empty?
840
1074
 
841
- result << "\n" + comment_box( "plugin structs" )
842
- $plugin_structs.each { |k,v| result << v } unless $plugin_structs.nil? || $plugin_structs.empty?
1075
+ signatures << "\n" + comment_box( "plugin structs" )
1076
+ $plugin_structs.each { |k,v| signatures << v } unless $plugin_structs.nil? || $plugin_structs.empty?
843
1077
 
844
- result << "\n" + comment_box( "sketch external variables" )
1078
+ external_vars << "\n" + comment_box( "sketch external variables" )
845
1079
 
846
- @@external_vars.each {|cv| result << "#{cv}"}
847
- result << ""
848
- result << "// servo_settings array"
1080
+ $external_vars.each {|v| external_vars << v }
1081
+ external_vars << ""
1082
+ external_vars << "// servo_settings array"
849
1083
 
850
1084
  array_size = @servo_settings.empty? ? 1 : @servo_pins.max + 1 # conserve space if no variables needed
851
- result << "struct servo serv[#{array_size}] = { #{@servo_settings.join(", ")} };" if $plugin_structs[:servo]
852
- result << ""
1085
+ external_vars << "struct servo serv[#{array_size}] = { #{@servo_settings.join(", ")} };" if $plugin_structs[:servo]
1086
+ external_vars << ""
853
1087
 
854
- result << "// debounce array"
1088
+ external_vars << "// debounce array"
855
1089
  array_size = @debounce_settings.empty? ? 1 : @debounce_pins.max + 1 # conserve space if no variables needed
856
- result << "struct debounce dbce[#{array_size}] = { #{@debounce_settings.join(", ")} };" if $plugin_structs[:debounce]
857
- result << ""
1090
+ external_vars << "struct debounce dbce[#{array_size}] = { #{@debounce_settings.join(", ")} };" if $plugin_structs[:debounce]
1091
+ external_vars << ""
858
1092
 
859
- @@array_vars.each { |var| result << var } if @@array_vars
1093
+ $external_array_vars.each { |var| external_vars << var } if $external_array_vars
860
1094
 
861
- result << "\n" + comment_box( "variable and accessors" )
862
- @declarations.each {|dec| result << dec}
863
- result << ""
864
- @accessors.each {|ac| result << ac}
1095
+ external_vars << "\n" + comment_box( "variable and accessors" )
1096
+ @declarations.each {|dec| external_vars << dec}
1097
+ external_vars << ""
1098
+ @accessors.each {|ac| external_vars << ac}
865
1099
 
866
- result << "\n" + comment_box( "assembler declarations" )
1100
+ # fix naming
1101
+ external_vars << "\n" + comment_box( "assembler declarations" )
867
1102
  unless @assembler_declarations.empty?
868
- result << <<-CODE
1103
+ external_vars << <<-CODE
869
1104
  extern "C" {
870
1105
  #{@assembler_declarations.join("\n")}
871
1106
  }
872
1107
  CODE
873
1108
  end
874
1109
 
875
- result << "\n" + comment_box( "setup" )
876
- result << "void setup() {"
877
- result << "\t// pin modes"
1110
+ external_vars << "\n" + comment_box( "setup" )
1111
+ setup << "void setup() {"
1112
+ setup << "\t// pin modes"
878
1113
 
879
1114
  @pin_modes.each do |k,v|
880
1115
  v.each do |value|
881
- result << "\tpinMode(#{value}, #{k.to_s.upcase});"
1116
+ setup << "\tpinMode(#{value}, #{k.to_s.upcase});"
882
1117
  end
883
1118
  end
884
1119
 
885
1120
  @pullups.each do |pin|
886
- result << "\tdigitalWrite( #{pin}, HIGH ); // enable pull-up resistor for input"
1121
+ setup << "\tdigitalWrite( #{pin}, HIGH ); // enable pull-up resistor for input"
887
1122
  end
888
1123
 
889
1124
  unless $add_to_setup.nil? || $add_to_setup.empty?
890
- result << "\t// setup from plugins via add_to_setup method"
891
- $add_to_setup.each {|item| result << "\t#{item}"}
1125
+ setup << "\t// setup from plugins via add_to_setup method"
1126
+ $add_to_setup.each {|item| setup << "\t#{item}"}
892
1127
  end
893
1128
 
894
1129
  unless @other_setup.empty?
895
- result << "\t// other setup"
896
- result << @other_setup.join( "\n" )
1130
+ setup << "\t// other setup"
1131
+ setup << @other_setup.join( "\n" )
897
1132
  end
898
1133
 
899
- result << "}\n"
1134
+ additional_setup << "}\n"
900
1135
 
901
- result << comment_box( "helper methods" )
902
- result << "\n// RAD built-in helpers"
903
- result << @helper_methods.lstrip
1136
+ helpers << comment_box( "helper methods" )
1137
+ helpers << "\n// RAD built-in helpers"
1138
+ helpers << @helper_methods.lstrip
904
1139
 
905
- result << "\n" + comment_box( "plugin methods" )
1140
+ helpers << "\n" + comment_box( "plugin methods" )
906
1141
  # need to add plugin name to this...
907
- $plugin_methods.each { |meth| result << "#{meth[0][0]}\n" } unless $plugin_methods.nil? || $plugin_methods.empty?
1142
+ $plugin_methods.each { |meth| helpers << "#{meth[0][0]}\n" } unless $plugin_methods.nil? || $plugin_methods.empty?
908
1143
 
909
- result << "\n// serial helpers"
910
- result << serial_boilerplate.lstrip
1144
+ helpers << "\n// serial helpers"
1145
+ helpers << serial_boilerplate.lstrip
911
1146
 
912
- result << "\n" + comment_box( "main() function" )
913
- result << "int main() {"
914
- result << "\tinit();"
915
- result << "\tsetup();"
916
- result << "\tfor( ;; ) { loop(); }"
917
- result << "\treturn 0;"
918
- result << "}"
1147
+ main << "\n" + comment_box( "main() function" )
1148
+ main << "int main() {"
1149
+ main << "\tinit();"
1150
+ main << "\tsetup();"
1151
+ main << "\tfor( ;; ) { loop(); }"
1152
+ main << "\treturn 0;"
1153
+ main << "}"
1154
+
1155
+ main << "\n" + comment_box( "loop! Autogenerated by RubyToC, sorry it's ugly." )
919
1156
 
920
- result << "\n" + comment_box( "loop! Autogenerated by RubyToC, sorry it's ugly." )
1157
+ return [declarations, plugin_directives, signatures, external_vars, setup, additional_setup, helpers, main]
921
1158
 
922
- return result.join( "\n" )
923
1159
  end
924
1160
 
925
1161
 
1162
+
1163
+
1164
+
926
1165
  # Write inline assembler code. 'Name' is a symbol representing the name of the function to be defined in the assembly code; 'signature' is the function signature for the function being defined; and 'code' is the assembly code itself (both of these last two arguments are strings). See an example here: http://rad.rubyforge.org/examples/assembler_test.html
927
1166
  def assembler(name, signature, code)
928
1167
  @assembler_declarations << signature
@@ -943,7 +1182,7 @@ class ArduinoSketch
943
1182
  def self.pre_process(sketch_string) #:nodoc:
944
1183
  result = sketch_string
945
1184
  # add external vars to each method (needed for better translation, will be removed in make:upload)
946
- result.gsub!(/(^\s*def\s.\w*(\(.*\))?)/, '\1' + " \n #{@@external_vars.join(" \n ")}" )
1185
+ result.gsub!(/(^\s*def\s.\w*(\(.*\))?)/, '\1' + " \n #{$external_vars.join(" \n ")}" )
947
1186
  # gather method names
948
1187
  sketch_methods = result.scan(/^\s*def\s.\w*/)
949
1188
  sketch_methods.each {|m| $sketch_methods << m.gsub(/\s*def\s*/, "") }