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
@@ -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*/, "") }