madrona-rad 0.2.2
Sign up to get free protection for your applications and to get access to all the features.
- data/History.txt +75 -0
- data/License.txt +282 -0
- data/Manifest.txt +47 -0
- data/README.rdoc +51 -0
- data/Rakefile +139 -0
- data/bin/rad +197 -0
- data/lib/libraries/SWSerLCDpa/SWSerLCDpa.cpp +267 -0
- data/lib/libraries/SWSerLCDpa/SWSerLCDpa.h +64 -0
- data/lib/libraries/SWSerLCDsf/SWSerLCDsf.cpp +254 -0
- data/lib/libraries/SWSerLCDsf/SWSerLCDsf.h +57 -0
- data/lib/libraries/Servo/Servo.cpp +152 -0
- data/lib/libraries/Servo/Servo.h +33 -0
- data/lib/libraries/Servo/keywords.txt +25 -0
- data/lib/plugins/debounce.rb +116 -0
- data/lib/plugins/debug_output_to_lcd.rb +71 -0
- data/lib/plugins/input_output_state.rb +84 -0
- data/lib/plugins/mem_test.rb +37 -0
- data/lib/plugins/servo_pulse.rb +31 -0
- data/lib/plugins/servo_setup.rb +86 -0
- data/lib/plugins/smoother.rb +54 -0
- data/lib/plugins/spark_fun_serial_lcd.rb +100 -0
- data/lib/rad/arduino_plugin.rb +202 -0
- data/lib/rad/arduino_sketch.rb +952 -0
- data/lib/rad/generators/makefile/makefile.erb +243 -0
- data/lib/rad/generators/makefile/makefile.rb +39 -0
- data/lib/rad/init.rb +12 -0
- data/lib/rad/rad_processor.rb +66 -0
- data/lib/rad/rad_rewriter.rb +94 -0
- data/lib/rad/tasks/build_and_make.rake +159 -0
- data/lib/rad/tasks/rad.rb +2 -0
- data/lib/rad/todo.txt +13 -0
- data/lib/rad/version.rb +9 -0
- data/lib/rad.rb +5 -0
- data/scripts/txt2html +67 -0
- data/setup.rb +1585 -0
- data/spec/models/arduino_sketch_spec.rb +82 -0
- data/spec/models/spec_helper.rb +2 -0
- data/spec/spec.opts +1 -0
- data/website/examples/assembler_test.rb.html +73 -0
- data/website/examples/gps_reader.rb.html +39 -0
- data/website/examples/hello_world.rb.html +38 -0
- data/website/examples/serial_motor.rb.html +41 -0
- data/website/index.html +177 -0
- data/website/index.txt +64 -0
- data/website/javascripts/rounded_corners_lite.inc.js +285 -0
- data/website/stylesheets/screen.css +169 -0
- data/website/template.rhtml +48 -0
- metadata +120 -0
@@ -0,0 +1,952 @@
|
|
1
|
+
# ArduinoSketch is the main access point for working with RAD. Sub-classes of ArduinoSketch have access to a wide array of convenient class methods (documented below) for doing the most common kinds of setup needed when programming the Arduino such as configuring input and output pins and establishing serial connections. Here is the canonical 'hello world' example of blinking a single LED in RAD:
|
2
|
+
#
|
3
|
+
# class HelloWorld < ArduinoSketch
|
4
|
+
# output_pin 13, :as => :led
|
5
|
+
#
|
6
|
+
# def loop
|
7
|
+
# blink 13, 500
|
8
|
+
# end
|
9
|
+
# end
|
10
|
+
#
|
11
|
+
# As you can see from this example, your ArduinoSketch sub-class can be dividied into two-parts: class methods for doing configuration and a loop method which will be run repeatedly at the Arduino's clock rate. Documentation for the various available class methods is below. The ArduinoSketch base class is designed to work with a series of rake tasks to automatically translate your loop method into C++ for compilation by the Arduino toolchain (see link://files/lib/rad/tasks/build_and_make_rake.html for details). See http://rad.rubyforge.org/examples for lots more examples of usage.
|
12
|
+
#
|
13
|
+
# ==Arduino built-in methods
|
14
|
+
# Thanks to this translation process you can take advantage of the complete Arduino software API (full docs here: http://www.arduino.cc/en/Reference/HomePage). What follows is the core of a RAD-Arduino dictionary for translating between RAD methods and the Arduino functionality they invoke, N.B. many Arduino methods have been left out (including the libraries for Time, Math, and Random Numbers, as the translation between them and their RAD counterparts should be relatively straightforward after perusing the examples here). For further details on each method, visit their Arduino documenation.
|
15
|
+
#
|
16
|
+
# <b>Digital I/O</b>
|
17
|
+
#
|
18
|
+
# digital_write(pin, value)
|
19
|
+
#
|
20
|
+
# Arduino method: digitalWrite(pin, value)
|
21
|
+
#
|
22
|
+
# Description: "Ouputs either HIGH or LOW at a specified pin."
|
23
|
+
#
|
24
|
+
# Documentation: http://www.arduino.cc/en/Reference/DigitalWrite
|
25
|
+
#
|
26
|
+
# digital_read(pin)
|
27
|
+
#
|
28
|
+
# Arduino method: digitalRead(pin)
|
29
|
+
#
|
30
|
+
# Description: "Reads the value from a specified pin, it will be either HIGH or LOW."
|
31
|
+
#
|
32
|
+
# Documentation: http://www.arduino.cc/en/Reference/DigitalRead
|
33
|
+
#
|
34
|
+
# <b>Analog I/O</b>
|
35
|
+
#
|
36
|
+
# analog_read(pin)
|
37
|
+
#
|
38
|
+
# Arduino method: analogRead(pin)
|
39
|
+
#
|
40
|
+
# Description: "Reads the value from the specified analog pin. The Arduino board contains a 6 channel
|
41
|
+
# (8 channels on the Mini), 10-bit analog to digital converter. This means that it will map input
|
42
|
+
# voltages between 0 and 5 volts into integer values between 0 and 1023. This yields a resolution
|
43
|
+
# between readings of: 5 volts / 1024 units or, .0049 volts (4.9 mV) per unit. It takes about 100
|
44
|
+
# us (0.0001 s) to read an analog input, so the maximum reading rate is about 10,000 times a second."
|
45
|
+
#
|
46
|
+
# Documentation: http://www.arduino.cc/en/Reference/AnalogRead
|
47
|
+
#
|
48
|
+
# analog_write(pin, value)
|
49
|
+
#
|
50
|
+
# Arduino method: analogWrite(pin, value)
|
51
|
+
#
|
52
|
+
# Description: "Writes an analog value (PWM wave) to a pin. On newer Arduino boards (including the Mini
|
53
|
+
# and BT) with the ATmega168 chip, this function works on pins 3, 5, 6, 9, 10, and 11. Older USB and
|
54
|
+
# serial Arduino boards with an ATmega8 only support analogWrite() on pins 9, 10, and 11. Can be used
|
55
|
+
# to light a LED at varying brightnesses or drive a motor at various speeds. After a call to analogWrite,
|
56
|
+
# the pin will generate a steady wave until the next call to analogWrite (or a call to digitalRead or
|
57
|
+
# digitalWrite on the same pin)."
|
58
|
+
#
|
59
|
+
# Documentation: http://www.arduino.cc/en/Reference/AnalogWrite
|
60
|
+
#
|
61
|
+
# <b>Serial Communication</b>
|
62
|
+
#
|
63
|
+
# serial_available()
|
64
|
+
#
|
65
|
+
# Arduino method: Serial.available()
|
66
|
+
#
|
67
|
+
# Description: "Get the number of bytes (characters) available for reading over the serial port.
|
68
|
+
# Returns the number of bytes available to read in the serial buffer, or 0 if none are
|
69
|
+
# available. If any data has come in, Serial.available() will be greater than 0. The serial buffer
|
70
|
+
# can hold up to 128 bytes."
|
71
|
+
#
|
72
|
+
# Documentation: http://www.arduino.cc/en/Serial/Available
|
73
|
+
#
|
74
|
+
# serial_read()
|
75
|
+
#
|
76
|
+
# Arduino method: Serial.read()
|
77
|
+
#
|
78
|
+
# Description: "Reads incoming serial data and returns the first byte of incoming serial data
|
79
|
+
# available (or -1 if no data is available)"
|
80
|
+
#
|
81
|
+
# Documentation: http://www.arduino.cc/en/Serial/Read
|
82
|
+
#
|
83
|
+
# serial_print(data)
|
84
|
+
#
|
85
|
+
# Arduino method: Serial.print(data)
|
86
|
+
#
|
87
|
+
# Description: "Prints data to the serial port."
|
88
|
+
#
|
89
|
+
# Documentation: http://www.arduino.cc/en/Serial/Print
|
90
|
+
#
|
91
|
+
# serial_println(data)
|
92
|
+
#
|
93
|
+
# Arduino method: Serial.println(data)
|
94
|
+
#
|
95
|
+
# Description: "Prints a data to the serial port, followed by a carriage return character
|
96
|
+
# (ASCII 13, or '\r') and a newline character (ASCII 10, or '\n'). This command takes the
|
97
|
+
# same forms as Serial.print():"
|
98
|
+
#
|
99
|
+
# Documentation: http://www.arduino.cc/en/Serial/Println
|
100
|
+
#
|
101
|
+
# serial_flush()
|
102
|
+
#
|
103
|
+
# Arduino method: Serial.flush()
|
104
|
+
#
|
105
|
+
# Description: "Flushes the buffer of incoming serial data. That is, any call to Serial.read()
|
106
|
+
# or Serial.available() will return only data received after the most recent call
|
107
|
+
# to Serial.flush()."
|
108
|
+
#
|
109
|
+
# Documentation: http://www.arduino.cc/en/Serial/Flush
|
110
|
+
#
|
111
|
+
# June 25, 2008
|
112
|
+
# Added a new external variable method which keeps track
|
113
|
+
# external_vars :sensor_position => "int, 0", :feedback => "int", :pulseTime => "unsigned long, 0"
|
114
|
+
#
|
115
|
+
# added ability to write additional methods besides loop in the sketch
|
116
|
+
# since there is quite a bit of work to do with the c translation, it is easy to write a method that
|
117
|
+
# won't compile or even translate into c, but for basics, it works.
|
118
|
+
# Note: stay basic and mindful that c is picky about variables and must make a decision
|
119
|
+
# which will not always be what you want
|
120
|
+
# also: for now, don't leave empty methods (something like foo = 1 cures this)
|
121
|
+
#
|
122
|
+
# Example:
|
123
|
+
#
|
124
|
+
# class HelloMethods < ArduinoSketch
|
125
|
+
# output_pin 13, :as => :led
|
126
|
+
#
|
127
|
+
# def loop
|
128
|
+
# blink_it
|
129
|
+
# end
|
130
|
+
|
131
|
+
# def blink_it
|
132
|
+
# blink 13, 500
|
133
|
+
# end
|
134
|
+
#
|
135
|
+
# end
|
136
|
+
#
|
137
|
+
#
|
138
|
+
# added pin methods for servos and latching which generate an array of structs to contain setup and status
|
139
|
+
# input_pin 12, :as => :back_off_button, :latch => :off
|
140
|
+
# input_pin 8, :as => :red_button, :latch => :off # adjust is optional with default set to 200
|
141
|
+
#
|
142
|
+
# added add_to_setup method that takes a string of c code and adds it to setup
|
143
|
+
# colons are options and will be added if not present
|
144
|
+
# no translation from ruby for now
|
145
|
+
#
|
146
|
+
# example:
|
147
|
+
#
|
148
|
+
# add_to_setup "call_my_new_method();", "call_another();"
|
149
|
+
#
|
150
|
+
# added some checking to c translation that (hopefully) makes it a bit more predictable
|
151
|
+
# most notably, we keep track of all external variables and let the translator know they exist
|
152
|
+
#
|
153
|
+
#
|
154
|
+
|
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
|
+
|
161
|
+
def initialize #:nodoc:
|
162
|
+
@servo_settings = [] # need modular way to add this
|
163
|
+
@debounce_settings = [] # need modular way to add this
|
164
|
+
@servo_pins = []
|
165
|
+
@debounce_pins = []
|
166
|
+
@@array_vars = []
|
167
|
+
@@external_vars =[]
|
168
|
+
$external_var_identifiers = []
|
169
|
+
$sketch_methods = []
|
170
|
+
|
171
|
+
@declarations = []
|
172
|
+
@pin_modes = {:output => [], :input => []}
|
173
|
+
@pullups = []
|
174
|
+
@other_setup = [] # specifically, Serial.begin
|
175
|
+
@assembler_declarations = []
|
176
|
+
@accessors = []
|
177
|
+
@signatures = ["void blink();", "int main();", "void track_total_loop_time(void);", "unsigned long find_total_loop_time(void);"]
|
178
|
+
|
179
|
+
helper_methods = []
|
180
|
+
helper_methods << "void blink(int pin, int ms) {"
|
181
|
+
helper_methods << "\tdigitalWrite( pin, HIGH );"
|
182
|
+
helper_methods << "\tdelay( ms );"
|
183
|
+
helper_methods << "\tdigitalWrite( pin, LOW );"
|
184
|
+
helper_methods << "\tdelay( ms );"
|
185
|
+
helper_methods << "}"
|
186
|
+
helper_methods << "void track_total_loop_time(void)"
|
187
|
+
helper_methods << "{"
|
188
|
+
helper_methods << "\ttotal_loop_time = millis() - start_loop_time;"
|
189
|
+
helper_methods << "\tstart_loop_time = millis();"
|
190
|
+
helper_methods << "}"
|
191
|
+
helper_methods << "unsigned long find_total_loop_time(void)"
|
192
|
+
helper_methods << "{"
|
193
|
+
helper_methods << "\nreturn total_loop_time;"
|
194
|
+
helper_methods << "}"
|
195
|
+
@helper_methods = helper_methods.join( "\n" )
|
196
|
+
|
197
|
+
@declarations << "unsigned long start_loop_time = 0;"
|
198
|
+
@declarations << "unsigned long total_loop_time = 0;"
|
199
|
+
end
|
200
|
+
|
201
|
+
# Setup variables outside of the loop. Does some magic based on type of arguments. Subject to renaming. Use with caution.
|
202
|
+
def vars(opts={})
|
203
|
+
opts.each do |k,v|
|
204
|
+
if v.class == Symbol
|
205
|
+
@declarations << "#{v} _#{k};"
|
206
|
+
@accessors << <<-CODE
|
207
|
+
#{v} #{k}(){
|
208
|
+
\treturn _#{k};
|
209
|
+
}
|
210
|
+
CODE
|
211
|
+
else
|
212
|
+
type = case v
|
213
|
+
when Integer
|
214
|
+
"int"
|
215
|
+
when String
|
216
|
+
"char*"
|
217
|
+
when TrueClass
|
218
|
+
"bool"
|
219
|
+
when FalseClass
|
220
|
+
"bool"
|
221
|
+
end
|
222
|
+
|
223
|
+
@declarations << "#{type} _#{k} = #{v};"
|
224
|
+
@accessors << <<-CODE
|
225
|
+
#{type} #{k}(){
|
226
|
+
\treturn _#{k};
|
227
|
+
}
|
228
|
+
CODE
|
229
|
+
end
|
230
|
+
end
|
231
|
+
end
|
232
|
+
|
233
|
+
|
234
|
+
# a different way to setup external variables outside the loop
|
235
|
+
#
|
236
|
+
# in addition to being added to the c file as external variables:
|
237
|
+
# we fake ruby2c out by adding them to internal vars for ruby2c processing
|
238
|
+
# but we don't include then in the cpp loop
|
239
|
+
# then, we use the indentiers to remove any parens that ruby2c adds
|
240
|
+
# this resolves ruby2c's habit of converting variables to methods
|
241
|
+
# need tests and ability to add custom char length
|
242
|
+
def external_vars(opts={})
|
243
|
+
if opts
|
244
|
+
opts.each do |k,v|
|
245
|
+
if v.include? ","
|
246
|
+
if v.split(",")[0] == "char"
|
247
|
+
## default is 40 characters
|
248
|
+
if v.split(",")[2]
|
249
|
+
@@external_vars << "#{v.split(",")[0]}* #{k}[#{v.split(",")[2].lstrip}];"
|
250
|
+
else
|
251
|
+
@@external_vars << "#{v.split(",")[0]} #{k}[40] = \"#{v.split(",")[1].lstrip}\";"
|
252
|
+
end
|
253
|
+
else
|
254
|
+
@@external_vars << "#{v.split(",")[0]} #{k} =#{v.split(",")[1]};"
|
255
|
+
end
|
256
|
+
else
|
257
|
+
if v.split(",")[0] == "char"
|
258
|
+
@@external_vars << "#{v.split(",")[0]} #{k}[40];"
|
259
|
+
else
|
260
|
+
|
261
|
+
@@external_vars << "#{v.split(",")[0]} #{k};"
|
262
|
+
end
|
263
|
+
end
|
264
|
+
# check chars work here
|
265
|
+
$external_var_identifiers << k
|
266
|
+
end
|
267
|
+
end
|
268
|
+
end
|
269
|
+
|
270
|
+
|
271
|
+
def add_to_setup(*args)
|
272
|
+
if args
|
273
|
+
args.each do |arg|
|
274
|
+
$add_to_setup << arg
|
275
|
+
end
|
276
|
+
end
|
277
|
+
end
|
278
|
+
|
279
|
+
# work in progress
|
280
|
+
def external_arrays(*args)
|
281
|
+
if args
|
282
|
+
args.each do |arg|
|
283
|
+
@@array_vars << arg
|
284
|
+
end
|
285
|
+
end
|
286
|
+
|
287
|
+
end
|
288
|
+
|
289
|
+
# Confiugre a single pin for output and setup a method to refer to that pin, i.e.:
|
290
|
+
#
|
291
|
+
# output_pin 7, :as => :led
|
292
|
+
#
|
293
|
+
# would configure pin 7 as an output and let you refer to it from the then on by calling
|
294
|
+
# the `led` method in your loop like so:
|
295
|
+
#
|
296
|
+
# def loop
|
297
|
+
# digital_write led, ON
|
298
|
+
# end
|
299
|
+
#
|
300
|
+
def output_pin(num, opts={})
|
301
|
+
raise ArgumentError, "can only define pin from Fixnum, got #{num.class}" unless num.is_a?(Fixnum)
|
302
|
+
@pin_modes[:output] << num
|
303
|
+
if opts[:as]
|
304
|
+
if opts[:device]
|
305
|
+
case opts[:device]
|
306
|
+
when :servo
|
307
|
+
new_servo_setup(num, opts)
|
308
|
+
return # don't use declarations, accessor, signatures below
|
309
|
+
when :orig_servo
|
310
|
+
orig_servo_setup(num, opts)
|
311
|
+
when :lcd || :LCD
|
312
|
+
lcd_setup(num, opts)
|
313
|
+
return
|
314
|
+
when :pa_lcd || :pa_LCD
|
315
|
+
pa_lcd_setup(num, opts)
|
316
|
+
return
|
317
|
+
when :sf_lcd || :sf_LCD
|
318
|
+
sf_lcd_setup(num, opts)
|
319
|
+
return
|
320
|
+
end
|
321
|
+
end
|
322
|
+
|
323
|
+
# remove the next 14 lines as soon as documentation on new :device => :servo option is out
|
324
|
+
|
325
|
+
if opts[:min] && opts[:max]
|
326
|
+
ArduinoPlugin.add_servo_struct
|
327
|
+
@servo_pins << num
|
328
|
+
refresh = opts[:refresh] ? opts[:refresh] : 200
|
329
|
+
@servo_settings << "serv[#{num}].pin = #{num}, serv[#{num}].pulseWidth = 0, serv[#{num}].lastPulse = 0, serv[#{num}].startPulse = 0, serv[#{num}].refreshTime = #{refresh}, serv[#{num}].min = #{opts[:min]}, serv[#{num}].max = #{opts[:max]} "
|
330
|
+
unless opts[:device]
|
331
|
+
puts "#{"*"*80} \n using :max and :min to instantiate a servo is deprecated\n use :device => :servo instead\n#{"*"*80}"
|
332
|
+
end
|
333
|
+
else
|
334
|
+
raise ArgumentError, "two are required for each servo: min & max" if opts[:min] || opts[:max]
|
335
|
+
raise ArgumentError, "refresh is an optional servo parameter, don't forget min & max" if opts[:refresh]
|
336
|
+
end
|
337
|
+
|
338
|
+
# add state variables for outputs with :state => :on or :off -- useful for toggling a light with output_toggle -- need to make this more modular
|
339
|
+
if opts[:state]
|
340
|
+
# add debounce settings to dbce struct array
|
341
|
+
ArduinoPlugin.add_debounce_struct
|
342
|
+
@debounce_pins << num
|
343
|
+
state = opts[:latch] == :on ? 1 : 0
|
344
|
+
prev = opts[:latch] == :on ? 0 : 1
|
345
|
+
adjust = opts[:adjust] ? opts[:adjust] : 200
|
346
|
+
@debounce_settings << "dbce[#{num}].state = #{state}, dbce[#{num}].read = 0, dbce[#{num}].prev = #{prev}, dbce[#{num}].time = 0, dbce[#{num}].adjust = #{adjust}"
|
347
|
+
end
|
348
|
+
|
349
|
+
@declarations << "int _#{opts[ :as ]} = #{num};"
|
350
|
+
|
351
|
+
accessor = []
|
352
|
+
accessor << "int #{opts[ :as ]}() {"
|
353
|
+
accessor << "\treturn _#{opts[ :as ]};"
|
354
|
+
accessor << "}"
|
355
|
+
@accessors << accessor.join( "\n" )
|
356
|
+
|
357
|
+
@signatures << "int #{opts[ :as ]}();"
|
358
|
+
end
|
359
|
+
end
|
360
|
+
|
361
|
+
# Like ArduinoSketch#output_pin but configure more than one output pin simultaneously. Takes an array of pin numbers.
|
362
|
+
def output_pins(nums)
|
363
|
+
ar = Array(nums)
|
364
|
+
ar.each {|n| output_pin(n)}
|
365
|
+
end
|
366
|
+
|
367
|
+
### tuck the following five methods into private once they are solid
|
368
|
+
|
369
|
+
def orig_servo_setup(num, opts)
|
370
|
+
ArduinoPlugin.add_servo_struct
|
371
|
+
@servo_pins << num
|
372
|
+
refresh = opts[:refresh] ? opts[:refresh] : 200
|
373
|
+
min = opts[:min] ? opts[:min] : 700
|
374
|
+
max = opts[:min] ? opts[:max] : 2200
|
375
|
+
@servo_settings << "serv[#{num}].pin = #{num}, serv[#{num}].pulseWidth = 0, serv[#{num}].lastPulse = 0, serv[#{num}].startPulse = 0, serv[#{num}].refreshTime = #{refresh}, serv[#{num}].min = #{min}, serv[#{num}].max = #{max} "
|
376
|
+
end
|
377
|
+
|
378
|
+
# use the servo library
|
379
|
+
def new_servo_setup(num, opts)
|
380
|
+
opts[:minp] = opts[:min] ? opts[:min] : 544
|
381
|
+
opts[:maxp] = opts[:max] ? opts[:max] : 2400
|
382
|
+
servo(num, opts)
|
383
|
+
# move this to better place ...
|
384
|
+
# should probably go along with servo code into plugin
|
385
|
+
@declarations << "void servo_refresh(void);"
|
386
|
+
helper_methods = []
|
387
|
+
helper_methods << "void servo_refresh(void)"
|
388
|
+
helper_methods << "{"
|
389
|
+
helper_methods << "\tServo::refresh();"
|
390
|
+
helper_methods << "}"
|
391
|
+
@helper_methods += "\n#{helper_methods.join("\n")}"
|
392
|
+
end
|
393
|
+
|
394
|
+
## this won't work at all... no pins
|
395
|
+
# need help
|
396
|
+
def lcd_setup(num, opts)
|
397
|
+
# move to plugin and load plugin
|
398
|
+
# what's the default rate?
|
399
|
+
opts[:rate] ||= 9600
|
400
|
+
rate = opts[:rate] ? opts[:rate] : 9600
|
401
|
+
swser_LCD(num, opts)
|
402
|
+
end
|
403
|
+
|
404
|
+
# use the pa lcd library
|
405
|
+
def pa_lcd_setup(num, opts)
|
406
|
+
# move to plugin and load plugin
|
407
|
+
# what's the default?
|
408
|
+
opts[:rate] ||= 9600
|
409
|
+
rate = opts[:rate] ? opts[:rate] : 9600
|
410
|
+
swser_LCDpa(num, opts)
|
411
|
+
end
|
412
|
+
|
413
|
+
# use the sf (sparkfun) library
|
414
|
+
def sf_lcd_setup(num, opts)
|
415
|
+
# move to plugin and load plugin
|
416
|
+
opts[:rate] ||= 9600
|
417
|
+
rate = opts[:rate] ? opts[:rate] : 9600
|
418
|
+
swser_LCDsf(num, opts)
|
419
|
+
end
|
420
|
+
|
421
|
+
|
422
|
+
# Confiugre a single pin for input and setup a method to refer to that pin, i.e.:
|
423
|
+
#
|
424
|
+
# input_pin 3, :as => :button
|
425
|
+
#
|
426
|
+
# would configure pin 3 as an input and let you refer to it from the then on by calling
|
427
|
+
# the `button` method in your loop like so:
|
428
|
+
#
|
429
|
+
# def loop
|
430
|
+
# digital_write led if digital_read button
|
431
|
+
# end
|
432
|
+
#
|
433
|
+
def input_pin(num, opts={})
|
434
|
+
raise ArgumentError, "can only define pin from Fixnum, got #{num.class}" unless num.is_a?(Fixnum)
|
435
|
+
@pin_modes[:input] << num
|
436
|
+
if opts[:as]
|
437
|
+
# transitioning to :device => :button syntax
|
438
|
+
if opts[:latch] || opts[:device] == :button
|
439
|
+
if opts[:device] == :button
|
440
|
+
opts[:latch] ||= :on
|
441
|
+
end
|
442
|
+
# add debounce settings to dbce struct array
|
443
|
+
ArduinoPlugin.add_debounce_struct
|
444
|
+
@debounce_pins << num
|
445
|
+
state = opts[:latch] == :on ? 1 : 0
|
446
|
+
prev = opts[:latch] == :on ? 0 : 1
|
447
|
+
adjust = opts[:adjust] ? opts[:adjust] : 200
|
448
|
+
@debounce_settings << "dbce[#{num}].state = #{state}, dbce[#{num}].read = 0, dbce[#{num}].prev = #{prev}, dbce[#{num}].time = 0, dbce[#{num}].adjust = #{adjust}"
|
449
|
+
end
|
450
|
+
@declarations << "int _#{opts[ :as ]} = #{num};"
|
451
|
+
|
452
|
+
accessor = []
|
453
|
+
accessor << "int #{opts[ :as ]}() {"
|
454
|
+
accessor << "\treturn _#{opts[ :as ]};"
|
455
|
+
accessor << "}"
|
456
|
+
@accessors << accessor.join( "\n" )
|
457
|
+
|
458
|
+
@signatures << "int #{opts[ :as ]}();"
|
459
|
+
end
|
460
|
+
@pullups << num if opts[:as]
|
461
|
+
end
|
462
|
+
|
463
|
+
# Like ArduinoSketch#input_pin but configure more than one input pin simultaneously. Takes an array of pin numbers.
|
464
|
+
def input_pins(nums)
|
465
|
+
ar = Array(nums)
|
466
|
+
ar.each {|n| input_pin(n)}
|
467
|
+
end
|
468
|
+
|
469
|
+
def add(st) #:nodoc:
|
470
|
+
@helper_methods << "\n#{st}\n"
|
471
|
+
end
|
472
|
+
|
473
|
+
# Configure Arduino for serial communication. Optionally, set the baud rate:
|
474
|
+
#
|
475
|
+
# serial_begin :rate => 2400
|
476
|
+
#
|
477
|
+
# default is 9600. See http://www.arduino.cc/en/Serial/Begin for more details.
|
478
|
+
#
|
479
|
+
def serial_begin(opts={})
|
480
|
+
rate = opts[:rate] ? opts[:rate] : 9600
|
481
|
+
@other_setup << "Serial.begin(#{rate});"
|
482
|
+
end
|
483
|
+
|
484
|
+
# Treat a pair of digital I/O pins as a serial line. See: http://www.arduino.cc/en/Tutorial/SoftwareSerial
|
485
|
+
def software_serial(rx, tx, opts={})
|
486
|
+
raise ArgumentError, "can only define rx from Fixnum, got #{rx.class}" unless rx.is_a?(Fixnum)
|
487
|
+
raise ArgumentError, "can only define tx from Fixnum, got #{tx.class}" unless tx.is_a?(Fixnum)
|
488
|
+
|
489
|
+
output_pin(tx)
|
490
|
+
|
491
|
+
rate = opts[:rate] ? opts[:rate] : 9600
|
492
|
+
if opts[:as]
|
493
|
+
@declarations << "SoftwareSerial _#{opts[ :as ]} = SoftwareSerial(#{rx}, #{tx});"
|
494
|
+
accessor = []
|
495
|
+
accessor << "SoftwareSerial& #{opts[ :as ]}() {"
|
496
|
+
accessor << "\treturn _#{opts[ :as ]};"
|
497
|
+
accessor << "}"
|
498
|
+
if (@@swser_inc == FALSE) # on second instance this stuff can't be repeated
|
499
|
+
@@swser_inc = TRUE
|
500
|
+
accessor << "int read(SoftwareSerial& s) {"
|
501
|
+
accessor << "\treturn s.read();"
|
502
|
+
accessor << "}"
|
503
|
+
accessor << "void println( SoftwareSerial& s, char* str ) {"
|
504
|
+
accessor << "\treturn s.println( str );"
|
505
|
+
accessor << "}"
|
506
|
+
accessor << "void print( SoftwareSerial& s, char* str ) {"
|
507
|
+
accessor << "\treturn s.print( str );"
|
508
|
+
accessor << "}"
|
509
|
+
accessor << "void println( SoftwareSerial& s, int i ) {"
|
510
|
+
accessor << "\treturn s.println( i );"
|
511
|
+
accessor << "}"
|
512
|
+
accessor << "void print( SoftwareSerial& s, int i ) {"
|
513
|
+
accessor << "\treturn s.print( i );"
|
514
|
+
accessor << "}"
|
515
|
+
end
|
516
|
+
@accessors << accessor.join( "\n" )
|
517
|
+
|
518
|
+
@signatures << "SoftwareSerial& #{opts[ :as ]}();"
|
519
|
+
|
520
|
+
@other_setup << "_#{opts[ :as ]}.begin(#{rate});"
|
521
|
+
end
|
522
|
+
end
|
523
|
+
|
524
|
+
def swser_LCDpa(tx, opts={})
|
525
|
+
raise ArgumentError, "can only define tx from Fixnum, got #{tx.class}" unless tx.is_a?(Fixnum)
|
526
|
+
output_pin(tx)
|
527
|
+
|
528
|
+
|
529
|
+
rate = opts[:rate] ? opts[:rate] : 9600
|
530
|
+
geometry = opts[:geometry] ? opts[:geometry] : 0
|
531
|
+
if opts[:as]
|
532
|
+
@declarations << "SWSerLCDpa _#{opts[ :as ]} = SWSerLCDpa(#{tx}, #{geometry});"
|
533
|
+
accessor = []
|
534
|
+
accessor << "SWSerLCDpa& #{opts[ :as ]}() {"
|
535
|
+
accessor << "\treturn _#{opts[ :as ]};"
|
536
|
+
accessor << "}"
|
537
|
+
if (@@slcdpa_inc == FALSE) # on second instance this stuff can't be repeated - BBR
|
538
|
+
@@slcdpa_inc = TRUE
|
539
|
+
accessor << "void print( SWSerLCDpa& s, uint8_t b ) {"
|
540
|
+
accessor << "\treturn s.print( b );"
|
541
|
+
accessor << "}"
|
542
|
+
accessor << "void print( SWSerLCDpa& s, const char *str ) {"
|
543
|
+
accessor << "\treturn s.print( str );"
|
544
|
+
accessor << "}"
|
545
|
+
accessor << "void print( SWSerLCDpa& s, char c ) {"
|
546
|
+
accessor << "\treturn s.print( c );"
|
547
|
+
accessor << "}"
|
548
|
+
accessor << "void print( SWSerLCDpa& s, int i ) {"
|
549
|
+
accessor << "\treturn s.print( i );"
|
550
|
+
accessor << "}"
|
551
|
+
accessor << "void print( SWSerLCDpa& s, unsigned int i ) {"
|
552
|
+
accessor << "\treturn s.print( i );"
|
553
|
+
accessor << "}"
|
554
|
+
accessor << "void print( SWSerLCDpa& s, long i ) {"
|
555
|
+
accessor << "\treturn s.print( i );"
|
556
|
+
accessor << "}"
|
557
|
+
accessor << "void print( SWSerLCDpa& s, unsigned long i ) {"
|
558
|
+
accessor << "\treturn s.print( i );"
|
559
|
+
accessor << "}"
|
560
|
+
accessor << "void print( SWSerLCDpa& s, long i, int b ) {"
|
561
|
+
accessor << "\treturn s.print( i, b );"
|
562
|
+
accessor << "}"
|
563
|
+
accessor << "void println( SWSerLCDpa& s, char* str ) {"
|
564
|
+
accessor << "\treturn s.println( str );"
|
565
|
+
accessor << "}"
|
566
|
+
accessor << "void print( SWSerLCDpa& s, char* str ) {"
|
567
|
+
accessor << "\treturn s.print( str );"
|
568
|
+
accessor << "}"
|
569
|
+
accessor << "void println(SWSerLCDpa& s) {"
|
570
|
+
accessor << "\treturn s.println();"
|
571
|
+
accessor << "}"
|
572
|
+
accessor << "void clearscr(SWSerLCDpa& s) {"
|
573
|
+
accessor << "\treturn s.clearscr();"
|
574
|
+
accessor << "}"
|
575
|
+
accessor << "void home(SWSerLCDpa& s) {"
|
576
|
+
accessor << "\treturn s.home();"
|
577
|
+
accessor << "}"
|
578
|
+
accessor << "void setgeo( SWSerLCDpa& s, int i ) {"
|
579
|
+
accessor << "\treturn s.setgeo( i );"
|
580
|
+
accessor << "}"
|
581
|
+
accessor << "void setintensity( SWSerLCDpa& s, int i ) {"
|
582
|
+
accessor << "\treturn s.setintensity( i );"
|
583
|
+
accessor << "}"
|
584
|
+
accessor << "void intoBignum(SWSerLCDpa& s) {"
|
585
|
+
accessor << "\treturn s.intoBignum();"
|
586
|
+
accessor << "}"
|
587
|
+
accessor << "void outofBignum(SWSerLCDpa& s) {"
|
588
|
+
accessor << "\treturn s.outofBignum();"
|
589
|
+
accessor << "}"
|
590
|
+
accessor << "void setxy( SWSerLCDpa& s, int x, int y) {"
|
591
|
+
accessor << "\treturn s.setxy( x, y );"
|
592
|
+
accessor << "}"
|
593
|
+
accessor << "void println( SWSerLCDpa& s, char c ) {"
|
594
|
+
accessor << "\treturn s.println( c );"
|
595
|
+
accessor << "}"
|
596
|
+
accessor << "void println( SWSerLCDpa& s, const char c[] ) {"
|
597
|
+
accessor << "\treturn s.println( c );"
|
598
|
+
accessor << "}"
|
599
|
+
accessor << "void println( SWSerLCDpa& s, uint8_t b ) {"
|
600
|
+
accessor << "\treturn s.println( b );"
|
601
|
+
accessor << "}"
|
602
|
+
accessor << "void println( SWSerLCDpa& s, int i ) {"
|
603
|
+
accessor << "\treturn s.println( i );"
|
604
|
+
accessor << "}"
|
605
|
+
accessor << "void println( SWSerLCDpa& s, long i ) {"
|
606
|
+
accessor << "\treturn s.println( i );"
|
607
|
+
accessor << "}"
|
608
|
+
accessor << "void println( SWSerLCDpa& s, unsigned long i ) {"
|
609
|
+
accessor << "\treturn s.println( i );"
|
610
|
+
accessor << "}"
|
611
|
+
accessor << "void println( SWSerLCDpa& s, long i, int b ) {"
|
612
|
+
accessor << "\treturn s.println( i, b );"
|
613
|
+
accessor << "}"
|
614
|
+
end
|
615
|
+
@accessors << accessor.join( "\n" )
|
616
|
+
|
617
|
+
@signatures << "SWSerLCDpa& #{opts[ :as ]}();"
|
618
|
+
|
619
|
+
@other_setup << "_#{opts[ :as ]}.begin(#{rate});"
|
620
|
+
end
|
621
|
+
end
|
622
|
+
|
623
|
+
|
624
|
+
|
625
|
+
def swser_LCDsf(tx, opts={})
|
626
|
+
raise ArgumentError, "can only define tx from Fixnum, got #{tx.class}" unless tx.is_a?(Fixnum)
|
627
|
+
output_pin(tx)
|
628
|
+
|
629
|
+
|
630
|
+
rate = opts[:rate] ? opts[:rate] : 9600
|
631
|
+
geometry = opts[:geometry] ? opts[:geometry] : 0
|
632
|
+
if opts[:as]
|
633
|
+
@declarations << "SWSerLCDsf _#{opts[ :as ]} = SWSerLCDsf(#{tx}, #{geometry});"
|
634
|
+
accessor = []
|
635
|
+
accessor << "SWSerLCDsf& #{opts[ :as ]}() {"
|
636
|
+
accessor << "\treturn _#{opts[ :as ]};"
|
637
|
+
accessor << "}"
|
638
|
+
if (@@slcdsf_inc == FALSE) # on second instance this stuff can't be repeated - BBR
|
639
|
+
@@slcdsf_inc = TRUE
|
640
|
+
accessor << "void print( SWSerLCDsf& s, uint8_t b ) {"
|
641
|
+
accessor << "\treturn s.print( b );"
|
642
|
+
accessor << "}"
|
643
|
+
accessor << "void print( SWSerLCDsf& s, const char *str ) {"
|
644
|
+
accessor << "\treturn s.print( str );"
|
645
|
+
accessor << "}"
|
646
|
+
accessor << "void print( SWSerLCDsf& s, char c ) {"
|
647
|
+
accessor << "\treturn s.print( c );"
|
648
|
+
accessor << "}"
|
649
|
+
accessor << "void print( SWSerLCDsf& s, int i ) {"
|
650
|
+
accessor << "\treturn s.print( i );"
|
651
|
+
accessor << "}"
|
652
|
+
accessor << "void print( SWSerLCDsf& s, unsigned int i ) {"
|
653
|
+
accessor << "\treturn s.print( i );"
|
654
|
+
accessor << "}"
|
655
|
+
accessor << "void print( SWSerLCDsf& s, long i ) {"
|
656
|
+
accessor << "\treturn s.print( i );"
|
657
|
+
accessor << "}"
|
658
|
+
accessor << "void print( SWSerLCDsf& s, unsigned long i ) {"
|
659
|
+
accessor << "\treturn s.print( i );"
|
660
|
+
accessor << "}"
|
661
|
+
accessor << "void print( SWSerLCDsf& s, long i, int b ) {"
|
662
|
+
accessor << "\treturn s.print( i, b );"
|
663
|
+
accessor << "}"
|
664
|
+
accessor << "void print( SWSerLCDsf& s, char* str ) {"
|
665
|
+
accessor << "\treturn s.print( str );"
|
666
|
+
accessor << "}"
|
667
|
+
accessor << "void clearscr(SWSerLCDsf& s) {"
|
668
|
+
accessor << "\treturn s.clearscr();"
|
669
|
+
accessor << "}"
|
670
|
+
accessor << "void home(SWSerLCDsf& s) {"
|
671
|
+
accessor << "\treturn s.home();"
|
672
|
+
accessor << "}"
|
673
|
+
accessor << "void setgeo( SWSerLCDsf& s, int i ) {"
|
674
|
+
accessor << "\treturn s.setgeo( i );"
|
675
|
+
accessor << "}"
|
676
|
+
accessor << "void setintensity( SWSerLCDsf& s, int i ) {"
|
677
|
+
accessor << "\treturn s.setintensity( i );"
|
678
|
+
accessor << "}"
|
679
|
+
accessor << "void setxy( SWSerLCDsf& s, int x, int y) {"
|
680
|
+
accessor << "\treturn s.setxy( x, y );"
|
681
|
+
accessor << "}"
|
682
|
+
accessor << "void setcmd( SWSerLCDsf& s, uint8_t a, uint8_t b) {"
|
683
|
+
accessor << "\treturn s.setcmd( a, b );"
|
684
|
+
accessor << "}"
|
685
|
+
end
|
686
|
+
@accessors << accessor.join( "\n" )
|
687
|
+
|
688
|
+
@signatures << "SWSerLCDsf& #{opts[ :as ]}();"
|
689
|
+
|
690
|
+
@other_setup << "_#{opts[ :as ]}.begin(#{rate});"
|
691
|
+
end
|
692
|
+
end
|
693
|
+
|
694
|
+
|
695
|
+
|
696
|
+
|
697
|
+
|
698
|
+
def servo(spin, opts={}) # servo motor routines # how about pin instead of spin
|
699
|
+
raise ArgumentError, "can only define spin from Fixnum, got #{spin.class}" unless spin.is_a?(Fixnum)
|
700
|
+
|
701
|
+
minp = opts[:minp] ? opts[:minp] : 544
|
702
|
+
maxp = opts[:maxp] ? opts[:maxp] : 2400
|
703
|
+
|
704
|
+
if opts[:as]
|
705
|
+
@declarations << "Servo _#{opts[ :as ]} = Servo();"
|
706
|
+
accessor = []
|
707
|
+
accessor << "Servo& #{opts[ :as ]}() {"
|
708
|
+
accessor << "\treturn _#{opts[ :as ]};"
|
709
|
+
accessor << "}"
|
710
|
+
|
711
|
+
if (@@servo_inc == FALSE) # on second instance this stuff can't be repeated - BBR
|
712
|
+
@@servo_inc = TRUE
|
713
|
+
accessor << "void detach( Servo& s ) {"
|
714
|
+
accessor << "\treturn s.detach();"
|
715
|
+
accessor << "}"
|
716
|
+
accessor << "void position( Servo& s, int b ) {"
|
717
|
+
accessor << "\treturn s.position( b );"
|
718
|
+
accessor << "}"
|
719
|
+
accessor << "void speed( Servo& s, int b ) {"
|
720
|
+
accessor << "\treturn s.speed( b );"
|
721
|
+
accessor << "}"
|
722
|
+
accessor << "uint8_t read( Servo& s ) {"
|
723
|
+
accessor << "\treturn s.read();"
|
724
|
+
accessor << "}"
|
725
|
+
accessor << "uint8_t attached( Servo& s ) {"
|
726
|
+
accessor << "\treturn s.attached();"
|
727
|
+
accessor << "}"
|
728
|
+
accessor << "static void refresh( Servo& s ) {"
|
729
|
+
accessor << "\treturn s.refresh();"
|
730
|
+
accessor << "}"
|
731
|
+
end
|
732
|
+
|
733
|
+
@accessors << accessor.join( "\n" )
|
734
|
+
|
735
|
+
@signatures << "Servo& #{opts[ :as ]}();"
|
736
|
+
|
737
|
+
@other_setup << "_#{opts[ :as ]}.attach(#{spin}, #{minp}, #{maxp});"
|
738
|
+
|
739
|
+
end
|
740
|
+
end
|
741
|
+
|
742
|
+
|
743
|
+
|
744
|
+
def compose_setup #:nodoc: also composes headers and signatures
|
745
|
+
result = []
|
746
|
+
|
747
|
+
result << comment_box( "Auto-generated by RAD" )
|
748
|
+
|
749
|
+
result << "#include <WProgram.h>\n"
|
750
|
+
result << "#include <SoftwareSerial.h>\n"
|
751
|
+
result << "#include <SWSerLCDpa.h>"
|
752
|
+
result << "#include <SWSerLCDsf.h>"
|
753
|
+
result << "#include <Servo.h>"
|
754
|
+
|
755
|
+
result << comment_box( 'plugin directives' )
|
756
|
+
$plugin_directives.each {|dir| result << dir } unless $plugin_directives.nil? || $plugin_directives.empty?
|
757
|
+
|
758
|
+
result << comment_box( 'method signatures' )
|
759
|
+
result << "void loop();"
|
760
|
+
result << "void setup();"
|
761
|
+
result << "// sketch signatures"
|
762
|
+
@signatures.each {|sig| result << sig}
|
763
|
+
result << "// sketch signatures"
|
764
|
+
result << "// plugin signatures"
|
765
|
+
$plugin_signatures.each {|sig| result << sig } unless $plugin_signatures.nil? || $plugin_signatures.empty?
|
766
|
+
result << "\n" + comment_box( "plugin external variables" )
|
767
|
+
$plugin_external_variables.each { |meth| result << meth } unless $plugin_external_variables.nil? || $plugin_external_variables.empty?
|
768
|
+
|
769
|
+
result << "\n" + comment_box( "plugin structs" )
|
770
|
+
$plugin_structs.each { |k,v| result << v } unless $plugin_structs.nil? || $plugin_structs.empty?
|
771
|
+
|
772
|
+
result << "\n" + comment_box( "sketch external variables" )
|
773
|
+
|
774
|
+
@@external_vars.each {|cv| result << "#{cv}"}
|
775
|
+
result << ""
|
776
|
+
result << "// servo_settings array"
|
777
|
+
|
778
|
+
array_size = @servo_settings.empty? ? 1 : @servo_pins.max + 1 # conserve space if no variables needed
|
779
|
+
result << "struct servo serv[#{array_size}] = { #{@servo_settings.join(", ")} };" if $plugin_structs[:servo]
|
780
|
+
result << ""
|
781
|
+
|
782
|
+
result << "// debounce array"
|
783
|
+
array_size = @debounce_settings.empty? ? 1 : @debounce_pins.max + 1 # conserve space if no variables needed
|
784
|
+
result << "struct debounce dbce[#{array_size}] = { #{@debounce_settings.join(", ")} };" if $plugin_structs[:debounce]
|
785
|
+
result << ""
|
786
|
+
|
787
|
+
@@array_vars.each { |var| result << var } if @@array_vars
|
788
|
+
|
789
|
+
result << "\n" + comment_box( "variable and accessors" )
|
790
|
+
@declarations.each {|dec| result << dec}
|
791
|
+
result << ""
|
792
|
+
@accessors.each {|ac| result << ac}
|
793
|
+
|
794
|
+
result << "\n" + comment_box( "assembler declarations" )
|
795
|
+
unless @assembler_declarations.empty?
|
796
|
+
result << <<-CODE
|
797
|
+
extern "C" {
|
798
|
+
#{@assembler_declarations.join("\n")}
|
799
|
+
}
|
800
|
+
CODE
|
801
|
+
end
|
802
|
+
|
803
|
+
result << "\n" + comment_box( "setup" )
|
804
|
+
result << "void setup() {"
|
805
|
+
result << "\t// pin modes"
|
806
|
+
|
807
|
+
@pin_modes.each do |k,v|
|
808
|
+
v.each do |value|
|
809
|
+
result << "\tpinMode(#{value}, #{k.to_s.upcase});"
|
810
|
+
end
|
811
|
+
end
|
812
|
+
|
813
|
+
@pullups.each do |pin|
|
814
|
+
result << "\tdigitalWrite( #{pin}, HIGH ); // enable pull-up resistor for input"
|
815
|
+
end
|
816
|
+
|
817
|
+
unless $add_to_setup.nil? || $add_to_setup.empty?
|
818
|
+
result << "\t// setup from plugins via add_to_setup method"
|
819
|
+
$add_to_setup.each {|item| result << "\t#{item}"}
|
820
|
+
end
|
821
|
+
|
822
|
+
unless @other_setup.empty?
|
823
|
+
result << "\t// other setup"
|
824
|
+
result << @other_setup.join( "\n" )
|
825
|
+
end
|
826
|
+
|
827
|
+
result << "}\n"
|
828
|
+
|
829
|
+
result << comment_box( "helper methods" )
|
830
|
+
result << "\n// RAD built-in helpers"
|
831
|
+
result << @helper_methods.lstrip
|
832
|
+
|
833
|
+
result << "\n" + comment_box( "plugin methods" )
|
834
|
+
# need to add plugin name to this...
|
835
|
+
$plugin_methods.each { |meth| result << "#{meth[0][0]}\n" } unless $plugin_methods.nil? || $plugin_methods.empty?
|
836
|
+
|
837
|
+
result << "\n// serial helpers"
|
838
|
+
result << serial_boilerplate.lstrip
|
839
|
+
|
840
|
+
result << "\n" + comment_box( "main() function" )
|
841
|
+
result << "int main() {"
|
842
|
+
result << "\tinit();"
|
843
|
+
result << "\tsetup();"
|
844
|
+
result << "\tfor( ;; ) { loop(); }"
|
845
|
+
result << "\treturn 0;"
|
846
|
+
result << "}"
|
847
|
+
|
848
|
+
result << "\n" + comment_box( "loop! Autogenerated by RubyToC, sorry it's ugly." )
|
849
|
+
|
850
|
+
return result.join( "\n" )
|
851
|
+
end
|
852
|
+
|
853
|
+
|
854
|
+
# 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
|
855
|
+
def assembler(name, signature, code)
|
856
|
+
@assembler_declarations << signature
|
857
|
+
assembler_code = <<-CODE
|
858
|
+
.file "#{name}.S"
|
859
|
+
.arch #{Makefile.hardware_params['mcu']}
|
860
|
+
.global __do_copy_data
|
861
|
+
.global __do_clear_bss
|
862
|
+
.text
|
863
|
+
.global #{name}
|
864
|
+
.type #{name}, @function
|
865
|
+
#{code}
|
866
|
+
CODE
|
867
|
+
|
868
|
+
File.open(File.expand_path("#{RAD_ROOT}") + "/#{PROJECT_DIR_NAME}/#{name}.S", "w"){|f| f << assembler_code}
|
869
|
+
end
|
870
|
+
|
871
|
+
def self.pre_process(sketch_string) #:nodoc:
|
872
|
+
result = sketch_string
|
873
|
+
# add external vars to each method (needed for better translation, will be removed in make:upload)
|
874
|
+
result.gsub!(/(^\s*def\s.\w*(\(.*\))?)/, '\1' + " \n #{@@external_vars.join(" \n ")}" )
|
875
|
+
# gather method names
|
876
|
+
sketch_methods = result.scan(/^\s*def\s.\w*/)
|
877
|
+
sketch_methods.each {|m| $sketch_methods << m.gsub(/\s*def\s*/, "") }
|
878
|
+
|
879
|
+
result.gsub!("HIGH", "1")
|
880
|
+
result.gsub!("LOW", "0")
|
881
|
+
result.gsub!("ON", "1")
|
882
|
+
result.gsub!("OFF", "0")
|
883
|
+
result
|
884
|
+
end
|
885
|
+
|
886
|
+
private
|
887
|
+
|
888
|
+
def serial_boilerplate #:nodoc:
|
889
|
+
out = []
|
890
|
+
out << "int serial_available() {"
|
891
|
+
out << "\treturn (Serial.available() > 0);"
|
892
|
+
out << "}"
|
893
|
+
|
894
|
+
out << "char serial_read() {"
|
895
|
+
out << "\treturn (char) Serial.read();"
|
896
|
+
out << "}"
|
897
|
+
|
898
|
+
out << "void serial_flush() {"
|
899
|
+
out << "\treturn Serial.flush();"
|
900
|
+
out << "}"
|
901
|
+
|
902
|
+
out << "void serial_print( char str ) {"
|
903
|
+
out << "\treturn Serial.print( str );"
|
904
|
+
out << "}"
|
905
|
+
|
906
|
+
out << "void serial_print( char* str ) {"
|
907
|
+
out << "\treturn Serial.print( str );"
|
908
|
+
out << "}"
|
909
|
+
|
910
|
+
out << "void serial_print( int i ) {"
|
911
|
+
out << "\treturn Serial.print( i );"
|
912
|
+
out << "}"
|
913
|
+
|
914
|
+
out << "void serial_print( long i ) {"
|
915
|
+
out << "\treturn Serial.print( i );"
|
916
|
+
out << "}"
|
917
|
+
|
918
|
+
out << "void serial_println( char* str ) {"
|
919
|
+
out << "\treturn Serial.println( str );"
|
920
|
+
out << "}"
|
921
|
+
|
922
|
+
out << "void serial_println( char str ) {"
|
923
|
+
out << "\treturn Serial.println( str );"
|
924
|
+
out << "}"
|
925
|
+
|
926
|
+
out << "void serial_println( int i ) {"
|
927
|
+
out << "\treturn Serial.println( i );"
|
928
|
+
out << "}"
|
929
|
+
|
930
|
+
out << "void serial_println( long i ) {"
|
931
|
+
out << "\treturn Serial.println( i );"
|
932
|
+
out << "}"
|
933
|
+
|
934
|
+
## added to support millis
|
935
|
+
out << "void serial_print( unsigned long i ) {"
|
936
|
+
out << "\treturn Serial.print( i );"
|
937
|
+
out << "}"
|
938
|
+
|
939
|
+
return out.join( "\n" )
|
940
|
+
end
|
941
|
+
|
942
|
+
def comment_box( content ) #:nodoc:
|
943
|
+
out = []
|
944
|
+
out << "/" * 74
|
945
|
+
out << "// " + content
|
946
|
+
out << "/" * 74
|
947
|
+
|
948
|
+
return out.join( "\n" )
|
949
|
+
end
|
950
|
+
|
951
|
+
|
952
|
+
end
|