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.
- data/History.txt +10 -0
- data/Manifest.txt +26 -0
- data/bin/rad +28 -36
- data/lib/examples/blink_m_hello.rb +14 -0
- data/lib/examples/debounce_methods.rb +49 -0
- data/lib/examples/external_variable_fu.rb +24 -0
- data/lib/examples/external_variables.rb +31 -0
- data/lib/examples/hello_eeprom.rb +54 -0
- data/lib/examples/i2c_with_clock_chip.rb +124 -0
- data/lib/examples/two_wire.rb +14 -0
- data/lib/libraries/DS1307/DS1307.cpp +161 -0
- data/lib/libraries/DS1307/DS1307.h +64 -0
- data/lib/libraries/DS1307/keywords.txt +18 -0
- data/lib/libraries/OneWire/OneWire.cpp +194 -0
- data/lib/libraries/OneWire/OneWire.h +63 -0
- data/lib/libraries/OneWire/keywords.txt +35 -0
- data/lib/libraries/OneWire/readme.txt +13 -0
- data/lib/libraries/Wire/Wire.cpp +262 -0
- data/lib/libraries/Wire/Wire.h +67 -0
- data/lib/libraries/Wire/keywords.txt +31 -0
- data/lib/libraries/Wire/twi.h +57 -0
- data/lib/plugins/bitwise_ops.rb +54 -0
- data/lib/plugins/blink_m.rb +304 -6
- data/lib/plugins/debounce.rb +46 -24
- data/lib/plugins/i2c_eeprom.rb +70 -0
- data/lib/rad/arduino_plugin.rb +27 -4
- data/lib/rad/arduino_sketch.rb +354 -115
- data/lib/rad/generators/makefile/makefile.erb +2 -2
- data/lib/rad/generators/makefile/makefile.rb +5 -9
- data/lib/rad/init.rb +3 -1
- data/lib/rad/rad_processor.rb +11 -0
- data/lib/rad/rad_rewriter.rb +1 -1
- data/lib/rad/tasks/build_and_make.rake +25 -12
- data/lib/rad/variable_processing.rb +116 -0
- data/lib/test/test_array_processing.rb +78 -0
- data/lib/test/test_variable_processing.rb +188 -0
- 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
|
data/lib/rad/arduino_plugin.rb
CHANGED
@@ -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((
|
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*(((
|
186
|
-
plugin_signatures << first_process.scan(/^\s((
|
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*(
|
214
|
+
result.gsub(/^\s*(#{PLUGIN_C_VAR_TYPES}).*(\n.*)*^\s*\}/, "" )
|
192
215
|
|
193
216
|
end
|
194
217
|
|
data/lib/rad/arduino_sketch.rb
CHANGED
@@ -153,23 +153,24 @@
|
|
153
153
|
#
|
154
154
|
|
155
155
|
class ArduinoSketch
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
@@frequency_inc = FALSE
|
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
|
-
|
168
|
-
|
168
|
+
$external_array_vars = []
|
169
|
+
$external_vars =[]
|
169
170
|
$external_var_identifiers = []
|
170
171
|
$sketch_methods = []
|
171
|
-
$load_libraries
|
172
|
-
$
|
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
|
-
|
253
|
+
$external_vars << "#{v.split(",")[0]}* #{k}[#{v.split(",")[2].lstrip}];"
|
253
254
|
else
|
254
|
-
|
255
|
+
$external_vars << "#{v.split(",")[0]} #{k}[40] = \"#{v.split(",")[1].lstrip}\";"
|
255
256
|
end
|
256
257
|
else
|
257
|
-
|
258
|
+
$external_vars << "#{v.split(",")[0]} #{k} =#{v.split(",")[1]};"
|
258
259
|
end
|
259
260
|
else
|
260
261
|
if v.split(",")[0] == "char"
|
261
|
-
|
262
|
+
$external_vars << "#{v.split(",")[0]} #{k}[40];"
|
262
263
|
else
|
263
264
|
|
264
|
-
|
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
|
-
#
|
283
|
+
# phasing this out
|
283
284
|
def external_arrays(*args)
|
284
285
|
if args
|
285
286
|
args.each do |arg|
|
286
|
-
|
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
|
-
#
|
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
|
-
|
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
|
-
|
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] ||= :
|
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
|
-
|
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 << "
|
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 << "
|
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(#{
|
758
|
-
@other_setup << "\t_#{opts[ :as ]}.attach(#{
|
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
|
-
|
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
|
-
|
788
|
-
|
789
|
-
|
790
|
-
|
791
|
-
|
792
|
-
|
793
|
-
|
794
|
-
|
795
|
-
|
796
|
-
|
797
|
-
|
798
|
-
|
799
|
-
|
800
|
-
|
801
|
-
|
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
|
-
|
1055
|
+
declarations << comment_box( "Auto-generated by RAD" )
|
821
1056
|
|
822
|
-
|
823
|
-
|
824
|
-
|
825
|
-
$
|
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
|
-
|
828
|
-
$plugin_directives.each {|dir|
|
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
|
-
|
831
|
-
|
832
|
-
|
833
|
-
|
834
|
-
@signatures.each {|sig|
|
835
|
-
|
836
|
-
|
837
|
-
|
838
|
-
|
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
|
-
|
842
|
-
$plugin_structs.each { |k,v|
|
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
|
-
|
1078
|
+
external_vars << "\n" + comment_box( "sketch external variables" )
|
845
1079
|
|
846
|
-
|
847
|
-
|
848
|
-
|
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
|
-
|
852
|
-
|
1085
|
+
external_vars << "struct servo serv[#{array_size}] = { #{@servo_settings.join(", ")} };" if $plugin_structs[:servo]
|
1086
|
+
external_vars << ""
|
853
1087
|
|
854
|
-
|
1088
|
+
external_vars << "// debounce array"
|
855
1089
|
array_size = @debounce_settings.empty? ? 1 : @debounce_pins.max + 1 # conserve space if no variables needed
|
856
|
-
|
857
|
-
|
1090
|
+
external_vars << "struct debounce dbce[#{array_size}] = { #{@debounce_settings.join(", ")} };" if $plugin_structs[:debounce]
|
1091
|
+
external_vars << ""
|
858
1092
|
|
859
|
-
|
1093
|
+
$external_array_vars.each { |var| external_vars << var } if $external_array_vars
|
860
1094
|
|
861
|
-
|
862
|
-
@declarations.each {|dec|
|
863
|
-
|
864
|
-
@accessors.each {|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
|
-
|
1100
|
+
# fix naming
|
1101
|
+
external_vars << "\n" + comment_box( "assembler declarations" )
|
867
1102
|
unless @assembler_declarations.empty?
|
868
|
-
|
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
|
-
|
876
|
-
|
877
|
-
|
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
|
-
|
1116
|
+
setup << "\tpinMode(#{value}, #{k.to_s.upcase});"
|
882
1117
|
end
|
883
1118
|
end
|
884
1119
|
|
885
1120
|
@pullups.each do |pin|
|
886
|
-
|
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
|
-
|
891
|
-
$add_to_setup.each {|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
|
-
|
896
|
-
|
1130
|
+
setup << "\t// other setup"
|
1131
|
+
setup << @other_setup.join( "\n" )
|
897
1132
|
end
|
898
1133
|
|
899
|
-
|
1134
|
+
additional_setup << "}\n"
|
900
1135
|
|
901
|
-
|
902
|
-
|
903
|
-
|
1136
|
+
helpers << comment_box( "helper methods" )
|
1137
|
+
helpers << "\n// RAD built-in helpers"
|
1138
|
+
helpers << @helper_methods.lstrip
|
904
1139
|
|
905
|
-
|
1140
|
+
helpers << "\n" + comment_box( "plugin methods" )
|
906
1141
|
# need to add plugin name to this...
|
907
|
-
$plugin_methods.each { |meth|
|
1142
|
+
$plugin_methods.each { |meth| helpers << "#{meth[0][0]}\n" } unless $plugin_methods.nil? || $plugin_methods.empty?
|
908
1143
|
|
909
|
-
|
910
|
-
|
1144
|
+
helpers << "\n// serial helpers"
|
1145
|
+
helpers << serial_boilerplate.lstrip
|
911
1146
|
|
912
|
-
|
913
|
-
|
914
|
-
|
915
|
-
|
916
|
-
|
917
|
-
|
918
|
-
|
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
|
-
|
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 #{
|
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*/, "") }
|