neo_rad 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/History.txt +112 -0
- data/License.txt +282 -0
- data/Manifest.txt +144 -0
- data/README.rdoc +1 -0
- data/Rakefile +142 -0
- data/bin/rad +302 -0
- data/lib/examples/add_hysteresis.rb +13 -0
- data/lib/examples/basic_blink.rb +10 -0
- data/lib/examples/blink_m_address_assignment.rb +104 -0
- data/lib/examples/blink_m_hello.rb +14 -0
- data/lib/examples/blink_m_multi.rb +61 -0
- data/lib/examples/blink_with_serial.rb +16 -0
- data/lib/examples/configure_pa_lcd_boot.rb +91 -0
- data/lib/examples/debounce_methods.rb +49 -0
- data/lib/examples/external_variable_fu.rb +26 -0
- data/lib/examples/external_variables.rb +32 -0
- data/lib/examples/first_sound.rb +23 -0
- data/lib/examples/frequency_generator.rb +30 -0
- data/lib/examples/hello_array.rb +48 -0
- data/lib/examples/hello_array2.rb +112 -0
- data/lib/examples/hello_array_eeprom.rb +59 -0
- data/lib/examples/hello_clock.rb +84 -0
- data/lib/examples/hello_eeprom.rb +51 -0
- data/lib/examples/hello_eeprom_lcdpa.rb +81 -0
- data/lib/examples/hello_format_print.rb +94 -0
- data/lib/examples/hello_lcd_charset.rb +75 -0
- data/lib/examples/hello_pa_lcd.rb +59 -0
- data/lib/examples/hello_servos.rb +88 -0
- data/lib/examples/hello_spectra_sound.rb +38 -0
- data/lib/examples/hello_world.rb +11 -0
- data/lib/examples/hello_xbee.rb +12 -0
- data/lib/examples/hysteresis_duel.rb +39 -0
- data/lib/examples/i2c_with_clock_chip.rb +124 -0
- data/lib/examples/midi_beat_box.rb +86 -0
- data/lib/examples/midi_scales.rb +94 -0
- data/lib/examples/motor_knob.rb +30 -0
- data/lib/examples/servo_buttons.rb +23 -0
- data/lib/examples/servo_calibrate_continuous.rb +92 -0
- data/lib/examples/servo_throttle.rb +40 -0
- data/lib/examples/software_serial.rb +10 -0
- data/lib/examples/sparkfun_lcd.rb +48 -0
- data/lib/examples/spectra_soft_pot.rb +34 -0
- data/lib/examples/times_method.rb +8 -0
- data/lib/examples/toggle.rb +10 -0
- data/lib/examples/twitter.rb +57 -0
- data/lib/examples/two_wire.rb +14 -0
- data/lib/libraries/AFSoftSerial/AFSoftSerial.cpp +321 -0
- data/lib/libraries/AFSoftSerial/AFSoftSerial.h +61 -0
- data/lib/libraries/AFSoftSerial/keywords.txt +18 -0
- data/lib/libraries/AF_XPort/AF_XPort.cpp +166 -0
- data/lib/libraries/AF_XPort/AF_XPort.h +48 -0
- data/lib/libraries/DS1307/DS1307.cpp +162 -0
- data/lib/libraries/DS1307/DS1307.h +66 -0
- data/lib/libraries/DS1307/keywords.txt +18 -0
- data/lib/libraries/FrequencyTimer2/FrequencyTimer2.cpp +144 -0
- data/lib/libraries/FrequencyTimer2/FrequencyTimer2.h +42 -0
- data/lib/libraries/FrequencyTimer2/keywords.txt +22 -0
- data/lib/libraries/I2CEEPROM/I2CEEPROM.cpp +120 -0
- data/lib/libraries/I2CEEPROM/I2CEEPROM.h +70 -0
- data/lib/libraries/I2CEEPROM/keywords.txt +21 -0
- data/lib/libraries/LoopTimer/LoopTimer.cpp +35 -0
- data/lib/libraries/LoopTimer/LoopTimer.h +34 -0
- data/lib/libraries/LoopTimer/keywords.txt +27 -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/SWSerLCDpa/SWSerLCDpa.cpp +296 -0
- data/lib/libraries/SWSerLCDpa/SWSerLCDpa.h +69 -0
- data/lib/libraries/SWSerLCDsf/SWSerLCDsf.cpp +311 -0
- data/lib/libraries/SWSerLCDsf/SWSerLCDsf.h +67 -0
- data/lib/libraries/Servo/Servo.cpp +192 -0
- data/lib/libraries/Servo/Servo.h +61 -0
- data/lib/libraries/Stepper/Stepper.cpp +220 -0
- data/lib/libraries/Stepper/Stepper.h +86 -0
- data/lib/libraries/Stepper/keywords.txt +28 -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/libraries/Wire/utility/twi.c +449 -0
- data/lib/libraries/Wire/utility/twi.h +57 -0
- data/lib/plugins/bitwise_ops.rb +54 -0
- data/lib/plugins/blink.rb +25 -0
- data/lib/plugins/blink_m.rb +356 -0
- data/lib/plugins/debounce.rb +138 -0
- data/lib/plugins/debug_output_to_lcd.rb +71 -0
- data/lib/plugins/hysteresis.rb +52 -0
- data/lib/plugins/input_output_state.rb +84 -0
- data/lib/plugins/lcd_padding.rb +58 -0
- data/lib/plugins/mem_test.rb +37 -0
- data/lib/plugins/midi.rb +60 -0
- data/lib/plugins/parallax_ping.rb +50 -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/plugins/spectra_symbol.rb +79 -0
- data/lib/plugins/twitter_connect.rb +145 -0
- data/lib/rad/README.rdoc +5 -0
- data/lib/rad/arduino_plugin.rb +246 -0
- data/lib/rad/arduino_sketch.rb +628 -0
- data/lib/rad/darwin_installer.rb +23 -0
- data/lib/rad/generators/makefile/makefile.erb +243 -0
- data/lib/rad/generators/makefile/makefile.rb +38 -0
- data/lib/rad/hardware_library.rb +813 -0
- data/lib/rad/init.rb +15 -0
- data/lib/rad/linux_installer.rb +132 -0
- data/lib/rad/progressbar.rb +236 -0
- data/lib/rad/rad_processor.rb +128 -0
- data/lib/rad/rad_rewriter.rb +94 -0
- data/lib/rad/rad_type_checker.rb +26 -0
- data/lib/rad/sim/arduino_sketch.rb +57 -0
- data/lib/rad/sketch_compiler.rb +47 -0
- data/lib/rad/tasks/build_and_make.rake +210 -0
- data/lib/rad/tasks/rad.rb +2 -0
- data/lib/rad/todo.txt +13 -0
- data/lib/rad/variable_processing.rb +153 -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/examples/hello_world.rb +11 -0
- data/spec/examples/serial_motor.rb +12 -0
- data/spec/models/arduino_sketch_spec.rb +82 -0
- data/spec/models/sketch_compiler_spec.rb +96 -0
- data/spec/models/spec_helper.rb +2 -0
- data/spec/sim/hello_world_spec.rb +42 -0
- data/spec/spec.opts +1 -0
- data/test/hello_world_test/Makefile +436 -0
- data/test/hello_world_test/hello_world.cpp +23 -0
- data/test/test_array_processing.rb +179 -0
- data/test/test_plugin_loading.rb +151 -0
- data/test/test_translation_post_processing.rb +185 -0
- data/test/test_variable_processing.rb +238 -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 +178 -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 +222 -0
@@ -0,0 +1,628 @@
|
|
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
|
+
|
157
|
+
include ExternalVariableProcessing
|
158
|
+
|
159
|
+
# find another way to do this
|
160
|
+
@@twowire_inc = FALSE
|
161
|
+
@@hwserial_inc = FALSE
|
162
|
+
|
163
|
+
|
164
|
+
def initialize #:nodoc:
|
165
|
+
@servo_settings = [] # need modular way to add this
|
166
|
+
@debounce_settings = [] # need modular way to add this
|
167
|
+
@hysteresis_settings = []
|
168
|
+
@spectra_settings = []
|
169
|
+
@servo_pins = []
|
170
|
+
@debounce_pins = []
|
171
|
+
@hysteresis_pins = []
|
172
|
+
@spectra_pins = []
|
173
|
+
$external_array_vars = []
|
174
|
+
$external_vars =[]
|
175
|
+
$external_var_identifiers = []
|
176
|
+
$sketch_methods = []
|
177
|
+
$load_libraries ||= []
|
178
|
+
$defines ||= []
|
179
|
+
$define_types = {}
|
180
|
+
$array_types = {}
|
181
|
+
$array_index_helpers = ('a'..'zz').to_a
|
182
|
+
|
183
|
+
@declarations = []
|
184
|
+
@pin_modes = {:output => [], :input => []}
|
185
|
+
@pullups = []
|
186
|
+
@other_setup = [] # specifically, Serial.begin
|
187
|
+
@assembler_declarations = []
|
188
|
+
@accessors = []
|
189
|
+
@signatures = ["int main();"]
|
190
|
+
|
191
|
+
helper_methods = []
|
192
|
+
@helper_methods = helper_methods.join( "\n" )
|
193
|
+
|
194
|
+
end
|
195
|
+
|
196
|
+
|
197
|
+
|
198
|
+
# array "char buffer[32]"
|
199
|
+
# result: char buffer[32];
|
200
|
+
# array "char buffer[32]"
|
201
|
+
# result: char buffer[32];
|
202
|
+
# todo
|
203
|
+
# need to feed array external array identifiers to rtc if they are in plugins or libraries, (not so sure about this will do more testing)
|
204
|
+
def array(arg)
|
205
|
+
if arg
|
206
|
+
arg = arg.chomp.rstrip.lstrip
|
207
|
+
arg.sub!("@","__")
|
208
|
+
name = arg.scan(/\s*(\w*)\[\d*\]?/).first.first
|
209
|
+
# help rad_processor do a better job with array types
|
210
|
+
types = ["int", "long", "char*", "unsigned int", "unsigned long", "byte", "bool", "float" ]
|
211
|
+
types.each_with_index do |type, i|
|
212
|
+
@type = types[i] if /#{type}/ =~ arg
|
213
|
+
end
|
214
|
+
raise ArgumentError, "type not currently supported.. got: #{arg}. Currently supporting #{types.join(", ")}" unless @type
|
215
|
+
|
216
|
+
arg = "#{arg};" unless arg[-1,1] == ";"
|
217
|
+
$array_types[name] = @type
|
218
|
+
@type = nil
|
219
|
+
$external_var_identifiers << name unless $external_var_identifiers.include?(name)
|
220
|
+
# add array_name declaration
|
221
|
+
$external_array_vars << arg unless $external_array_vars.include?(arg)
|
222
|
+
end
|
223
|
+
end
|
224
|
+
|
225
|
+
# define "DS1307_SEC 0"
|
226
|
+
# result: #define DS1307_SEC 0
|
227
|
+
# note we send the constant identifiers and type to our rad_type_checker
|
228
|
+
# however, it only knows about long, float, str....
|
229
|
+
# so we don't send ints ...yet..
|
230
|
+
# need more testing
|
231
|
+
def define(arg)
|
232
|
+
if arg
|
233
|
+
arg = arg.chomp.rstrip.lstrip
|
234
|
+
name = arg.split(" ").first
|
235
|
+
value = arg.gsub!("#{name} ","")
|
236
|
+
# negative
|
237
|
+
if value =~ /^-(\d|x)*$/
|
238
|
+
type = "long"
|
239
|
+
# negative float
|
240
|
+
elsif value =~ /^-(\d|\.|x)*$/
|
241
|
+
type = "float"
|
242
|
+
elsif value =~ /[a-zA-Z]/
|
243
|
+
type = "str"
|
244
|
+
value = "\"#{value}\""
|
245
|
+
elsif value !~ /(\.|x)/
|
246
|
+
type = "long"
|
247
|
+
elsif value =~ /(\d*\.\d*)/ # and no
|
248
|
+
type = "float"
|
249
|
+
elsif value =~ /0x\d\d/
|
250
|
+
type = "byte"
|
251
|
+
else
|
252
|
+
raise ArgumentError, "opps, could not determine the define type, got #{value}"
|
253
|
+
end
|
254
|
+
$define_types[name] = type
|
255
|
+
arg = "#define #{name} #{value}"
|
256
|
+
$defines << arg
|
257
|
+
dummy_for_testing = arg, type
|
258
|
+
end
|
259
|
+
end
|
260
|
+
|
261
|
+
# Configure a single pin for output and setup a method to refer to that pin, i.e.:
|
262
|
+
#
|
263
|
+
# output_pin 7, :as => :led
|
264
|
+
#
|
265
|
+
# would configure pin 7 as an output and let you refer to it from the then on by calling
|
266
|
+
# the `led` method in your loop like so:
|
267
|
+
#
|
268
|
+
# def loop
|
269
|
+
# digital_write led, ON
|
270
|
+
# end
|
271
|
+
#
|
272
|
+
def output_pin(num, opts={})
|
273
|
+
raise ArgumentError, "can only define pin from Fixnum, got #{num.class}" unless num.is_a?(Fixnum)
|
274
|
+
@pin_modes[:output] << num
|
275
|
+
if opts[:as]
|
276
|
+
if opts[:device]
|
277
|
+
case opts[:device]
|
278
|
+
when :servo
|
279
|
+
servo_setup(num, opts)
|
280
|
+
return # don't use declarations, accessor, signatures below
|
281
|
+
when :pa_lcd || :pa_LCD
|
282
|
+
pa_lcd_setup(num, opts)
|
283
|
+
return
|
284
|
+
when :sf_lcd || :sf_LCD
|
285
|
+
sf_lcd_setup(num, opts)
|
286
|
+
return
|
287
|
+
when :freq_out || :freq_gen || :frequency_generator
|
288
|
+
frequency_timer(num, opts)
|
289
|
+
return
|
290
|
+
when :i2c
|
291
|
+
two_wire(num, opts) unless @@twowire_inc
|
292
|
+
return #
|
293
|
+
when :i2c_eeprom
|
294
|
+
two_wire(num, opts) unless @@twowire_inc
|
295
|
+
i2c_eeprom(num, opts)
|
296
|
+
return #
|
297
|
+
when :i2c_ds1307
|
298
|
+
two_wire(num, opts) unless @@twowire_inc
|
299
|
+
ds1307(num, opts)
|
300
|
+
return #
|
301
|
+
when :i2c_blinkm
|
302
|
+
two_wire(num, opts) unless @@twowire_inc
|
303
|
+
blinkm
|
304
|
+
return #
|
305
|
+
when :onewire
|
306
|
+
one_wire(num, opts)
|
307
|
+
return #
|
308
|
+
when :ethernet
|
309
|
+
ethernet(num, opts)
|
310
|
+
return #
|
311
|
+
else
|
312
|
+
raise ArgumentError, "today's device choices are: :servo, :pa_lcd, :sf_lcd, :freq_out,:i2c, :i2c_eeprom, :i2c_ds1307, and :i2c_blinkm got #{opts[:device]}"
|
313
|
+
end
|
314
|
+
end
|
315
|
+
|
316
|
+
# add state variables for outputs with :state => :on or :off -- useful for toggling a light with output_toggle -- need to make this more modular
|
317
|
+
if opts[:state]
|
318
|
+
# add debounce settings to dbce struct array
|
319
|
+
ArduinoPlugin.add_debounce_struct
|
320
|
+
@debounce_pins << num
|
321
|
+
state = opts[:latch] == :on ? 1 : 0
|
322
|
+
prev = opts[:latch] == :on ? 0 : 1
|
323
|
+
adjust = opts[:adjust] ? opts[:adjust] : 200
|
324
|
+
@debounce_settings << "dbce[#{num}].state = #{state}, dbce[#{num}].read = 0, dbce[#{num}].prev = #{prev}, dbce[#{num}].time = 0, dbce[#{num}].adjust = #{adjust}"
|
325
|
+
end
|
326
|
+
|
327
|
+
@declarations << "int _#{opts[ :as ]} = #{num};"
|
328
|
+
|
329
|
+
accessor = []
|
330
|
+
accessor << "int #{opts[ :as ]}() {"
|
331
|
+
accessor << "\treturn _#{opts[ :as ]};"
|
332
|
+
accessor << "}"
|
333
|
+
@accessors << accessor.join( "\n" )
|
334
|
+
|
335
|
+
@signatures << "int #{opts[ :as ]}();"
|
336
|
+
end
|
337
|
+
end
|
338
|
+
|
339
|
+
|
340
|
+
# Configure a single pin for input and setup a method to refer to that pin, i.e.:
|
341
|
+
#
|
342
|
+
# input_pin 3, :as => :button
|
343
|
+
#
|
344
|
+
# would configure pin 3 as an input and let you refer to it from the then on by calling
|
345
|
+
# the `button` method in your loop like so:
|
346
|
+
#
|
347
|
+
# def loop
|
348
|
+
# digital_write led if digital_read button
|
349
|
+
# end
|
350
|
+
#
|
351
|
+
def input_pin(num, opts={})
|
352
|
+
raise ArgumentError, "can only define pin from Fixnum, got #{num.class}" unless num.is_a?(Fixnum)
|
353
|
+
@pin_modes[:input] << num
|
354
|
+
if opts[:as]
|
355
|
+
# transitioning to :device => :button syntax
|
356
|
+
if opts[:latch] || opts[:device] == :button
|
357
|
+
if opts[:device] == :button
|
358
|
+
opts[:latch] ||= :off
|
359
|
+
end
|
360
|
+
# add debounce settings to dbce struct array
|
361
|
+
ArduinoPlugin.add_debounce_struct
|
362
|
+
@debounce_pins << num
|
363
|
+
state = opts[:latch] == :on ? 1 : 0
|
364
|
+
prev = opts[:latch] == :on ? 0 : 1
|
365
|
+
adjust = opts[:adjust] ? opts[:adjust] : 200
|
366
|
+
@debounce_settings << "dbce[#{num}].state = #{state}, dbce[#{num}].read = 0, dbce[#{num}].prev = #{prev}, dbce[#{num}].time = 0, dbce[#{num}].adjust = #{adjust}"
|
367
|
+
end
|
368
|
+
if opts[:device] == :sensor
|
369
|
+
ArduinoPlugin.add_sensor_struct
|
370
|
+
count = @hysteresis_pins.length
|
371
|
+
@hysteresis_pins << num
|
372
|
+
@hysteresis_settings << "hyst[#{count}].pin = #{num}, hyst[#{count}].state = 0"
|
373
|
+
end
|
374
|
+
if opts[:device] == :spectra
|
375
|
+
ArduinoPlugin.add_spectra_struct
|
376
|
+
count = @spectra_pins.length
|
377
|
+
@spectra_pins << num
|
378
|
+
@spectra_settings << "spec[#{count}].pin = #{num}, spec[#{count}].state = 10, spec[#{count}].r1 = 0, spec[#{count}].r2 = 0, spec[#{count}].r3 = 0"
|
379
|
+
end
|
380
|
+
@declarations << "int _#{opts[ :as ]} = #{num};"
|
381
|
+
|
382
|
+
accessor = []
|
383
|
+
accessor << "int #{opts[ :as ]}() {"
|
384
|
+
accessor << "\treturn _#{opts[ :as ]};"
|
385
|
+
accessor << "}"
|
386
|
+
@accessors << accessor.join( "\n" )
|
387
|
+
|
388
|
+
@signatures << "int #{opts[ :as ]}();"
|
389
|
+
end
|
390
|
+
@pullups << num if opts[:as]
|
391
|
+
end
|
392
|
+
|
393
|
+
# Like ArduinoSketch#input_pin but configure more than one input pin simultaneously. Takes an array of pin numbers.
|
394
|
+
def input_pins(nums)
|
395
|
+
ar = Array(nums)
|
396
|
+
ar.each {|n| input_pin(n)}
|
397
|
+
end
|
398
|
+
|
399
|
+
def add(st) #:nodoc:
|
400
|
+
@helper_methods << "\n#{st}\n"
|
401
|
+
end
|
402
|
+
|
403
|
+
# Configure Arduino for serial communication. Optionally, set the baud rate:
|
404
|
+
#
|
405
|
+
# serial_begin :rate => 2400
|
406
|
+
#
|
407
|
+
# default is 9600. See http://www.arduino.cc/en/Serial/Begin for more details.
|
408
|
+
#
|
409
|
+
def serial_begin(opts={})
|
410
|
+
rate = opts[:rate] ? opts[:rate] : 9600
|
411
|
+
@other_setup << "Serial.begin(#{rate});"
|
412
|
+
@@hwserial_inc = TRUE
|
413
|
+
end
|
414
|
+
|
415
|
+
|
416
|
+
def formatted_print(opts={})
|
417
|
+
|
418
|
+
buffer_size = opts[:buffer_size] ? opts[:buffer_size] : 64
|
419
|
+
|
420
|
+
if opts[:as]
|
421
|
+
@@sprintf_inc ||= FALSE
|
422
|
+
if @@sprintf_inc == FALSE
|
423
|
+
@@sprintf_inc = TRUE
|
424
|
+
accessor = []
|
425
|
+
accessor << "\n#undef int\n#include <stdio.h>"
|
426
|
+
accessor << "#define write_line(...) sprintf(#{opts[:as]},__VA_ARGS__);"
|
427
|
+
@accessors << accessor.join( "\n" )
|
428
|
+
array("char #{opts[:as]}[#{buffer_size}]")
|
429
|
+
end
|
430
|
+
end
|
431
|
+
end
|
432
|
+
|
433
|
+
|
434
|
+
|
435
|
+
|
436
|
+
def compose_setup #:nodoc: also composes headers and signatures
|
437
|
+
|
438
|
+
declarations = []
|
439
|
+
plugin_directives = []
|
440
|
+
signatures = []
|
441
|
+
external_vars = []
|
442
|
+
setup = []
|
443
|
+
additional_setup =[]
|
444
|
+
helpers = []
|
445
|
+
main = []
|
446
|
+
result = []
|
447
|
+
|
448
|
+
declarations << comment_box( "Auto-generated by RAD" )
|
449
|
+
|
450
|
+
declarations << "#include <WProgram.h>\n"
|
451
|
+
declarations << "#include <SoftwareSerial.h>\n"
|
452
|
+
$load_libraries.each { |lib| declarations << "#include <#{lib}.h>" } unless $load_libraries.nil?
|
453
|
+
$defines.each { |d| declarations << d }
|
454
|
+
|
455
|
+
plugin_directives << comment_box( 'plugin directives' )
|
456
|
+
$plugin_directives.each {|dir| plugin_directives << dir } unless $plugin_directives.nil? || $plugin_directives.empty?
|
457
|
+
|
458
|
+
signatures << comment_box( 'method signatures' )
|
459
|
+
signatures << "void loop();"
|
460
|
+
signatures << "void setup();"
|
461
|
+
signatures << "// sketch signatures"
|
462
|
+
@signatures.each {|sig| signatures << sig}
|
463
|
+
signatures << "// plugin signatures"
|
464
|
+
$plugin_signatures.each {|sig| signatures << sig } unless $plugin_signatures.nil? || $plugin_signatures.empty?
|
465
|
+
external_vars << "\n" + comment_box( "plugin external variables" )
|
466
|
+
$plugin_external_variables.each { |meth| external_vars << meth } unless $plugin_external_variables.nil? || $plugin_external_variables.empty?
|
467
|
+
|
468
|
+
signatures << "\n" + comment_box( "plugin structs" )
|
469
|
+
$plugin_structs.each { |k,v| signatures << v } unless $plugin_structs.nil? || $plugin_structs.empty?
|
470
|
+
|
471
|
+
external_vars << "\n" + comment_box( "sketch external variables" )
|
472
|
+
|
473
|
+
$external_vars.each {|v| external_vars << v }
|
474
|
+
external_vars << ""
|
475
|
+
external_vars << "// servo_settings array"
|
476
|
+
|
477
|
+
array_size = @servo_settings.empty? ? 1 : @servo_pins.max + 1 # conserve space if no variables needed
|
478
|
+
external_vars << "struct servo serv[#{array_size}] = { #{@servo_settings.join(", ")} };" if $plugin_structs[:servo]
|
479
|
+
external_vars << ""
|
480
|
+
|
481
|
+
external_vars << "// debounce array"
|
482
|
+
array_size = @debounce_settings.empty? ? 1 : @debounce_pins.max + 1 # conserve space if no variables needed
|
483
|
+
external_vars << "struct debounce dbce[#{array_size}] = { #{@debounce_settings.join(", ")} };" if $plugin_structs[:debounce]
|
484
|
+
external_vars << ""
|
485
|
+
|
486
|
+
external_vars << "// hysteresis array"
|
487
|
+
h_array_size = @hysteresis_settings.empty? ? 1 : @hysteresis_pins.length + 1 # conserve space if no variables needed
|
488
|
+
external_vars << "struct hysteresis hyst[#{h_array_size}] = { #{@hysteresis_settings.join(", ")} };" if $plugin_structs[:sensor]
|
489
|
+
external_vars << ""
|
490
|
+
|
491
|
+
external_vars << "// spectrasymbol soft pot array"
|
492
|
+
sp_array_size = @spectra_settings.empty? ? 1 : @spectra_pins.length + 1 # conserve space if no variables needed
|
493
|
+
external_vars << "struct spectra spec[#{sp_array_size}] = { #{@spectra_settings.join(", ")} };" if $plugin_structs[:spectra]
|
494
|
+
external_vars << ""
|
495
|
+
|
496
|
+
$external_array_vars.each { |var| external_vars << var } if $external_array_vars
|
497
|
+
|
498
|
+
external_vars << "\n" + comment_box( "variable and accessors" )
|
499
|
+
@declarations.each {|dec| external_vars << dec}
|
500
|
+
external_vars << ""
|
501
|
+
@accessors.each {|ac| external_vars << ac}
|
502
|
+
|
503
|
+
# fix naming
|
504
|
+
external_vars << "\n" + comment_box( "assembler declarations" )
|
505
|
+
unless @assembler_declarations.empty?
|
506
|
+
external_vars << <<-CODE
|
507
|
+
extern "C" {
|
508
|
+
#{@assembler_declarations.join("\n")}
|
509
|
+
}
|
510
|
+
CODE
|
511
|
+
end
|
512
|
+
|
513
|
+
external_vars << "\n" + comment_box( "setup" )
|
514
|
+
setup << "void setup() {"
|
515
|
+
setup << "\t// pin modes"
|
516
|
+
|
517
|
+
@pin_modes.each do |k,v|
|
518
|
+
v.each do |value|
|
519
|
+
setup << "\tpinMode(#{value}, #{k.to_s.upcase});"
|
520
|
+
end
|
521
|
+
end
|
522
|
+
|
523
|
+
@pullups.each do |pin|
|
524
|
+
setup << "\tdigitalWrite( #{pin}, HIGH ); // enable pull-up resistor for input"
|
525
|
+
end
|
526
|
+
|
527
|
+
unless $add_to_setup.nil? || $add_to_setup.empty?
|
528
|
+
setup << "\t// setup from plugins via add_to_setup method"
|
529
|
+
$add_to_setup.each {|item| setup << "\t#{item}"}
|
530
|
+
end
|
531
|
+
|
532
|
+
unless @other_setup.empty?
|
533
|
+
setup << "\t// other setup"
|
534
|
+
setup << @other_setup.join( "\n" )
|
535
|
+
end
|
536
|
+
|
537
|
+
additional_setup << "}\n"
|
538
|
+
|
539
|
+
helpers << comment_box( "helper methods" )
|
540
|
+
helpers << "\n// RAD built-in helpers"
|
541
|
+
helpers << @helper_methods.lstrip
|
542
|
+
|
543
|
+
helpers << "\n" + comment_box( "plugin methods" )
|
544
|
+
# need to add plugin name to this...
|
545
|
+
$plugin_methods.each { |meth| helpers << "#{meth[0][0]}\n" } unless $plugin_methods.nil? || $plugin_methods.empty?
|
546
|
+
|
547
|
+
if @@hwserial_inc == TRUE
|
548
|
+
helpers << "\n// serial helpers"
|
549
|
+
helpers << serial_boilerplate.lstrip
|
550
|
+
end
|
551
|
+
|
552
|
+
main << "\n" + comment_box( "main() function" )
|
553
|
+
main << "int main() {"
|
554
|
+
main << "\tinit();"
|
555
|
+
main << "\tsetup();"
|
556
|
+
main << "\tfor( ;; ) { loop(); }"
|
557
|
+
main << "\treturn 0;"
|
558
|
+
main << "}"
|
559
|
+
|
560
|
+
main << "\n" + comment_box( "loop! Autogenerated by RubyToC, sorry it's ugly." )
|
561
|
+
|
562
|
+
return [declarations, plugin_directives, signatures, external_vars, setup, additional_setup, helpers, main]
|
563
|
+
|
564
|
+
end
|
565
|
+
|
566
|
+
|
567
|
+
# 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
|
568
|
+
def assembler(name, signature, code)
|
569
|
+
@assembler_declarations << signature
|
570
|
+
assembler_code = <<-CODE
|
571
|
+
.file "#{name}.S"
|
572
|
+
.arch #{Makefile.hardware_params['mcu']}
|
573
|
+
.global __do_copy_data
|
574
|
+
.global __do_clear_bss
|
575
|
+
.text
|
576
|
+
.global #{name}
|
577
|
+
.type #{name}, @function
|
578
|
+
#{code}
|
579
|
+
CODE
|
580
|
+
|
581
|
+
File.open(File.expand_path("#{RAD_ROOT}") + "/#{PROJECT_DIR_NAME}/#{name}.S", "w"){|f| f << assembler_code}
|
582
|
+
end
|
583
|
+
|
584
|
+
def self.pre_process(sketch_string) #:nodoc:
|
585
|
+
result = sketch_string
|
586
|
+
# add external vars to each method (needed for better translation, will be removed in make:upload)
|
587
|
+
result.gsub!(/(^\s*def\s.\w*(\(.*\))?)/, '\1' + " \n #{$external_vars.join(" \n ")}" )
|
588
|
+
# gather method names
|
589
|
+
sketch_methods = result.scan(/^\s*def\s.\w*/)
|
590
|
+
sketch_methods.each {|m| $sketch_methods << m.gsub(/\s*def\s*/, "") }
|
591
|
+
|
592
|
+
result.gsub!("HIGH", "1")
|
593
|
+
result.gsub!("LOW", "0")
|
594
|
+
result.gsub!("ON", "1")
|
595
|
+
result.gsub!("OFF", "0")
|
596
|
+
result
|
597
|
+
end
|
598
|
+
|
599
|
+
def self.add_to_setup(meth)
|
600
|
+
meth = meth.gsub("setup", "additional_setup")
|
601
|
+
post_process_ruby_to_c_methods(meth)
|
602
|
+
end
|
603
|
+
|
604
|
+
def self.post_process_ruby_to_c_methods(e)
|
605
|
+
clean_c_methods = []
|
606
|
+
# need to take a look at the \(unsigned in the line below not sure if we are really trying to catch something like that
|
607
|
+
if e !~ /^\s*(#{C_VAR_TYPES})(\W{1,6}|\(unsigned\()(#{$external_var_identifiers.join("|")})/ || $external_var_identifiers.empty?
|
608
|
+
# use the list of identifers the external_vars method of the sketch and remove the parens the ruby2c sometime adds to variables
|
609
|
+
# keep an eye on the gsub!.. are we getting nil errors
|
610
|
+
# and more recently, the \b
|
611
|
+
e.gsub!(/\b((#{$external_var_identifiers.join("|")})\(\))/, '\2') unless $external_var_identifiers.empty?
|
612
|
+
clean_c_methods << e
|
613
|
+
end
|
614
|
+
return clean_c_methods.join( "\n" )
|
615
|
+
end
|
616
|
+
|
617
|
+
|
618
|
+
def comment_box( content ) #:nodoc:
|
619
|
+
out = []
|
620
|
+
out << "/" * 74
|
621
|
+
out << "// " + content
|
622
|
+
out << "/" * 74
|
623
|
+
|
624
|
+
return out.join( "\n" )
|
625
|
+
end
|
626
|
+
|
627
|
+
|
628
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
class DarwinInstaller
|
2
|
+
def self.install!
|
3
|
+
puts "Downloading arduino-0012 for Mac from Arduino.cc"
|
4
|
+
File.open("/Applications/arduino-0012.zip", "w") do |file|
|
5
|
+
pbar = nil
|
6
|
+
file << open("http://www.arduino.cc/files/arduino-0012-mac.zip",
|
7
|
+
:content_length_proc => lambda {|t|
|
8
|
+
if t && 0 < t
|
9
|
+
pbar = ProgressBar.new(" Progress", t)
|
10
|
+
pbar.file_transfer_mode
|
11
|
+
end
|
12
|
+
},
|
13
|
+
:progress_proc => lambda {|s|
|
14
|
+
pbar.set s if pbar
|
15
|
+
}).read
|
16
|
+
pbar.finish
|
17
|
+
end
|
18
|
+
puts "Unzipping..."
|
19
|
+
`cd /Applications; unzip arduino-0012.zip`
|
20
|
+
`rm /Applications/arduino-0012.zip`
|
21
|
+
puts "installed Arduino here: /Applications/arduino-0012"
|
22
|
+
end
|
23
|
+
end
|