neo_rad 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (146) hide show
  1. checksums.yaml +7 -0
  2. data/History.txt +112 -0
  3. data/License.txt +282 -0
  4. data/Manifest.txt +144 -0
  5. data/README.rdoc +1 -0
  6. data/Rakefile +142 -0
  7. data/bin/rad +302 -0
  8. data/lib/examples/add_hysteresis.rb +13 -0
  9. data/lib/examples/basic_blink.rb +10 -0
  10. data/lib/examples/blink_m_address_assignment.rb +104 -0
  11. data/lib/examples/blink_m_hello.rb +14 -0
  12. data/lib/examples/blink_m_multi.rb +61 -0
  13. data/lib/examples/blink_with_serial.rb +16 -0
  14. data/lib/examples/configure_pa_lcd_boot.rb +91 -0
  15. data/lib/examples/debounce_methods.rb +49 -0
  16. data/lib/examples/external_variable_fu.rb +26 -0
  17. data/lib/examples/external_variables.rb +32 -0
  18. data/lib/examples/first_sound.rb +23 -0
  19. data/lib/examples/frequency_generator.rb +30 -0
  20. data/lib/examples/hello_array.rb +48 -0
  21. data/lib/examples/hello_array2.rb +112 -0
  22. data/lib/examples/hello_array_eeprom.rb +59 -0
  23. data/lib/examples/hello_clock.rb +84 -0
  24. data/lib/examples/hello_eeprom.rb +51 -0
  25. data/lib/examples/hello_eeprom_lcdpa.rb +81 -0
  26. data/lib/examples/hello_format_print.rb +94 -0
  27. data/lib/examples/hello_lcd_charset.rb +75 -0
  28. data/lib/examples/hello_pa_lcd.rb +59 -0
  29. data/lib/examples/hello_servos.rb +88 -0
  30. data/lib/examples/hello_spectra_sound.rb +38 -0
  31. data/lib/examples/hello_world.rb +11 -0
  32. data/lib/examples/hello_xbee.rb +12 -0
  33. data/lib/examples/hysteresis_duel.rb +39 -0
  34. data/lib/examples/i2c_with_clock_chip.rb +124 -0
  35. data/lib/examples/midi_beat_box.rb +86 -0
  36. data/lib/examples/midi_scales.rb +94 -0
  37. data/lib/examples/motor_knob.rb +30 -0
  38. data/lib/examples/servo_buttons.rb +23 -0
  39. data/lib/examples/servo_calibrate_continuous.rb +92 -0
  40. data/lib/examples/servo_throttle.rb +40 -0
  41. data/lib/examples/software_serial.rb +10 -0
  42. data/lib/examples/sparkfun_lcd.rb +48 -0
  43. data/lib/examples/spectra_soft_pot.rb +34 -0
  44. data/lib/examples/times_method.rb +8 -0
  45. data/lib/examples/toggle.rb +10 -0
  46. data/lib/examples/twitter.rb +57 -0
  47. data/lib/examples/two_wire.rb +14 -0
  48. data/lib/libraries/AFSoftSerial/AFSoftSerial.cpp +321 -0
  49. data/lib/libraries/AFSoftSerial/AFSoftSerial.h +61 -0
  50. data/lib/libraries/AFSoftSerial/keywords.txt +18 -0
  51. data/lib/libraries/AF_XPort/AF_XPort.cpp +166 -0
  52. data/lib/libraries/AF_XPort/AF_XPort.h +48 -0
  53. data/lib/libraries/DS1307/DS1307.cpp +162 -0
  54. data/lib/libraries/DS1307/DS1307.h +66 -0
  55. data/lib/libraries/DS1307/keywords.txt +18 -0
  56. data/lib/libraries/FrequencyTimer2/FrequencyTimer2.cpp +144 -0
  57. data/lib/libraries/FrequencyTimer2/FrequencyTimer2.h +42 -0
  58. data/lib/libraries/FrequencyTimer2/keywords.txt +22 -0
  59. data/lib/libraries/I2CEEPROM/I2CEEPROM.cpp +120 -0
  60. data/lib/libraries/I2CEEPROM/I2CEEPROM.h +70 -0
  61. data/lib/libraries/I2CEEPROM/keywords.txt +21 -0
  62. data/lib/libraries/LoopTimer/LoopTimer.cpp +35 -0
  63. data/lib/libraries/LoopTimer/LoopTimer.h +34 -0
  64. data/lib/libraries/LoopTimer/keywords.txt +27 -0
  65. data/lib/libraries/OneWire/OneWire.cpp +194 -0
  66. data/lib/libraries/OneWire/OneWire.h +63 -0
  67. data/lib/libraries/OneWire/keywords.txt +35 -0
  68. data/lib/libraries/OneWire/readme.txt +13 -0
  69. data/lib/libraries/SWSerLCDpa/SWSerLCDpa.cpp +296 -0
  70. data/lib/libraries/SWSerLCDpa/SWSerLCDpa.h +69 -0
  71. data/lib/libraries/SWSerLCDsf/SWSerLCDsf.cpp +311 -0
  72. data/lib/libraries/SWSerLCDsf/SWSerLCDsf.h +67 -0
  73. data/lib/libraries/Servo/Servo.cpp +192 -0
  74. data/lib/libraries/Servo/Servo.h +61 -0
  75. data/lib/libraries/Stepper/Stepper.cpp +220 -0
  76. data/lib/libraries/Stepper/Stepper.h +86 -0
  77. data/lib/libraries/Stepper/keywords.txt +28 -0
  78. data/lib/libraries/Wire/Wire.cpp +262 -0
  79. data/lib/libraries/Wire/Wire.h +67 -0
  80. data/lib/libraries/Wire/keywords.txt +31 -0
  81. data/lib/libraries/Wire/twi.h +57 -0
  82. data/lib/libraries/Wire/utility/twi.c +449 -0
  83. data/lib/libraries/Wire/utility/twi.h +57 -0
  84. data/lib/plugins/bitwise_ops.rb +54 -0
  85. data/lib/plugins/blink.rb +25 -0
  86. data/lib/plugins/blink_m.rb +356 -0
  87. data/lib/plugins/debounce.rb +138 -0
  88. data/lib/plugins/debug_output_to_lcd.rb +71 -0
  89. data/lib/plugins/hysteresis.rb +52 -0
  90. data/lib/plugins/input_output_state.rb +84 -0
  91. data/lib/plugins/lcd_padding.rb +58 -0
  92. data/lib/plugins/mem_test.rb +37 -0
  93. data/lib/plugins/midi.rb +60 -0
  94. data/lib/plugins/parallax_ping.rb +50 -0
  95. data/lib/plugins/servo_pulse.rb +31 -0
  96. data/lib/plugins/servo_setup.rb +86 -0
  97. data/lib/plugins/smoother.rb +54 -0
  98. data/lib/plugins/spark_fun_serial_lcd.rb +100 -0
  99. data/lib/plugins/spectra_symbol.rb +79 -0
  100. data/lib/plugins/twitter_connect.rb +145 -0
  101. data/lib/rad/README.rdoc +5 -0
  102. data/lib/rad/arduino_plugin.rb +246 -0
  103. data/lib/rad/arduino_sketch.rb +628 -0
  104. data/lib/rad/darwin_installer.rb +23 -0
  105. data/lib/rad/generators/makefile/makefile.erb +243 -0
  106. data/lib/rad/generators/makefile/makefile.rb +38 -0
  107. data/lib/rad/hardware_library.rb +813 -0
  108. data/lib/rad/init.rb +15 -0
  109. data/lib/rad/linux_installer.rb +132 -0
  110. data/lib/rad/progressbar.rb +236 -0
  111. data/lib/rad/rad_processor.rb +128 -0
  112. data/lib/rad/rad_rewriter.rb +94 -0
  113. data/lib/rad/rad_type_checker.rb +26 -0
  114. data/lib/rad/sim/arduino_sketch.rb +57 -0
  115. data/lib/rad/sketch_compiler.rb +47 -0
  116. data/lib/rad/tasks/build_and_make.rake +210 -0
  117. data/lib/rad/tasks/rad.rb +2 -0
  118. data/lib/rad/todo.txt +13 -0
  119. data/lib/rad/variable_processing.rb +153 -0
  120. data/lib/rad/version.rb +9 -0
  121. data/lib/rad.rb +5 -0
  122. data/scripts/txt2html +67 -0
  123. data/setup.rb +1585 -0
  124. data/spec/examples/hello_world.rb +11 -0
  125. data/spec/examples/serial_motor.rb +12 -0
  126. data/spec/models/arduino_sketch_spec.rb +82 -0
  127. data/spec/models/sketch_compiler_spec.rb +96 -0
  128. data/spec/models/spec_helper.rb +2 -0
  129. data/spec/sim/hello_world_spec.rb +42 -0
  130. data/spec/spec.opts +1 -0
  131. data/test/hello_world_test/Makefile +436 -0
  132. data/test/hello_world_test/hello_world.cpp +23 -0
  133. data/test/test_array_processing.rb +179 -0
  134. data/test/test_plugin_loading.rb +151 -0
  135. data/test/test_translation_post_processing.rb +185 -0
  136. data/test/test_variable_processing.rb +238 -0
  137. data/website/examples/assembler_test.rb.html +73 -0
  138. data/website/examples/gps_reader.rb.html +39 -0
  139. data/website/examples/hello_world.rb.html +38 -0
  140. data/website/examples/serial_motor.rb.html +41 -0
  141. data/website/index.html +178 -0
  142. data/website/index.txt +64 -0
  143. data/website/javascripts/rounded_corners_lite.inc.js +285 -0
  144. data/website/stylesheets/screen.css +169 -0
  145. data/website/template.rhtml +48 -0
  146. 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