madrona-rad 0.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (48) hide show
  1. data/History.txt +75 -0
  2. data/License.txt +282 -0
  3. data/Manifest.txt +47 -0
  4. data/README.rdoc +51 -0
  5. data/Rakefile +139 -0
  6. data/bin/rad +197 -0
  7. data/lib/libraries/SWSerLCDpa/SWSerLCDpa.cpp +267 -0
  8. data/lib/libraries/SWSerLCDpa/SWSerLCDpa.h +64 -0
  9. data/lib/libraries/SWSerLCDsf/SWSerLCDsf.cpp +254 -0
  10. data/lib/libraries/SWSerLCDsf/SWSerLCDsf.h +57 -0
  11. data/lib/libraries/Servo/Servo.cpp +152 -0
  12. data/lib/libraries/Servo/Servo.h +33 -0
  13. data/lib/libraries/Servo/keywords.txt +25 -0
  14. data/lib/plugins/debounce.rb +116 -0
  15. data/lib/plugins/debug_output_to_lcd.rb +71 -0
  16. data/lib/plugins/input_output_state.rb +84 -0
  17. data/lib/plugins/mem_test.rb +37 -0
  18. data/lib/plugins/servo_pulse.rb +31 -0
  19. data/lib/plugins/servo_setup.rb +86 -0
  20. data/lib/plugins/smoother.rb +54 -0
  21. data/lib/plugins/spark_fun_serial_lcd.rb +100 -0
  22. data/lib/rad/arduino_plugin.rb +202 -0
  23. data/lib/rad/arduino_sketch.rb +952 -0
  24. data/lib/rad/generators/makefile/makefile.erb +243 -0
  25. data/lib/rad/generators/makefile/makefile.rb +39 -0
  26. data/lib/rad/init.rb +12 -0
  27. data/lib/rad/rad_processor.rb +66 -0
  28. data/lib/rad/rad_rewriter.rb +94 -0
  29. data/lib/rad/tasks/build_and_make.rake +159 -0
  30. data/lib/rad/tasks/rad.rb +2 -0
  31. data/lib/rad/todo.txt +13 -0
  32. data/lib/rad/version.rb +9 -0
  33. data/lib/rad.rb +5 -0
  34. data/scripts/txt2html +67 -0
  35. data/setup.rb +1585 -0
  36. data/spec/models/arduino_sketch_spec.rb +82 -0
  37. data/spec/models/spec_helper.rb +2 -0
  38. data/spec/spec.opts +1 -0
  39. data/website/examples/assembler_test.rb.html +73 -0
  40. data/website/examples/gps_reader.rb.html +39 -0
  41. data/website/examples/hello_world.rb.html +38 -0
  42. data/website/examples/serial_motor.rb.html +41 -0
  43. data/website/index.html +177 -0
  44. data/website/index.txt +64 -0
  45. data/website/javascripts/rounded_corners_lite.inc.js +285 -0
  46. data/website/stylesheets/screen.css +169 -0
  47. data/website/template.rhtml +48 -0
  48. metadata +120 -0
@@ -0,0 +1,243 @@
1
+ # Arduino makefile
2
+ #
3
+ # This makefile allows you to build sketches from the command line
4
+ # without the Arduino environment (or Java).
5
+ #
6
+ # The Arduino environment does preliminary processing on a sketch before
7
+ # compiling it. If you're using this makefile instead, you'll need to do
8
+ # a few things differently:
9
+ #
10
+ # - Give your program's file a .cpp extension (e.g. foo.cpp).
11
+ #
12
+ # - Put this line at top of your code: #include <WProgram.h>
13
+ #
14
+ # - Write prototypes for all your functions (or define them before you
15
+ # call them). A prototype declares the types of parameters a
16
+ # function will take and what type of value it will return. This
17
+ # means that you can have a call to a function before the definition
18
+ # of the function. A function prototype looks like the first line of
19
+ # the function, with a semi-colon at the end. For example:
20
+ # int digitalRead(int pin);
21
+ #
22
+ # - Write a main() function for your program that returns an int, calls
23
+ # init() and setup() once (in that order), and then calls loop()
24
+ # repeatedly():
25
+ #
26
+ # int main()
27
+ # {
28
+ # init();
29
+ # setup();
30
+ #
31
+ # for (;;)
32
+ # loop();
33
+ #
34
+ # return 0;
35
+ # }
36
+ #
37
+ # Instructions for using the makefile:
38
+ #
39
+ # 1. Copy this file into the folder with your sketch.
40
+ #
41
+ # 2. Below, modify the line containing "TARGET" to refer to the name of
42
+ # of your program's file without an extension (e.g. TARGET = foo).
43
+ #
44
+ # 3. Modify the line containg "ARDUINO" to point the directory that
45
+ # contains the Arduino core (for normal Arduino installations, this
46
+ # is the hardware/cores/arduino sub-directory).
47
+ #
48
+ # 4. Modify the line containing "PORT" to refer to the filename
49
+ # representing the USB or serial connection to your Arduino board
50
+ # (e.g. PORT = /dev/tty.USB0). If the exact name of this file
51
+ # changes, you can use * as a wildcard (e.g. PORT = /dev/tty.USB*).
52
+ #
53
+ # 5. At the command line, change to the directory containing your
54
+ # program's file and the makefile.
55
+ #
56
+ # 6. Type "make" and press enter to compile/verify your program.
57
+ #
58
+ # 7. Type "make upload", reset your Arduino board, and press enter to
59
+ # upload your program to the Arduino board.
60
+ #
61
+ # $Id$
62
+
63
+ PORT = <%= params['serial_port'] %>
64
+ TARGET = <%= params['target'] %>
65
+ ARDUINO = <%= params['arduino_root'] %>/hardware/cores/arduino
66
+ SOFTWARE_SERIAL = <%= params['arduino_root'] %>/hardware/libraries/SoftwareSerial
67
+ LIBRARY_ROOT = <%= params['libraries_root'] %>
68
+ SRC = $(ARDUINO)/pins_arduino.c $(ARDUINO)/wiring.c \
69
+ $(ARDUINO)/wiring_analog.c $(ARDUINO)/wiring_digital.c \
70
+ $(ARDUINO)/wiring_pulse.c $(ARDUINO)/wiring_serial.c \
71
+ $(ARDUINO)/wiring_shift.c $(ARDUINO)/WInterrupts.c
72
+ CXXSRC = $(ARDUINO)/HardwareSerial.cpp $(SOFTWARE_SERIAL)/SoftwareSerial.cpp<%= params['libraries'].collect{|l| " $(LIBRARY_ROOT)/#{ l }/#{l }.cpp"}.join('') %>
73
+ MCU = <%= params['mcu'] %>
74
+ <% if params['asm_files'] %>ASRC = <%= params['asm_files'].join(' ') %><% end %>
75
+ F_CPU = 16000000
76
+ FORMAT = ihex
77
+ UPLOAD_RATE = 19200
78
+ BIN_DIR = <%= params['arduino_root'] %>/hardware/tools/avr/bin
79
+
80
+ # Name of this Makefile (used for "make depend").
81
+ MAKEFILE = Makefile
82
+
83
+ # Debugging format.
84
+ # Native formats for AVR-GCC's -g are stabs [default], or dwarf-2.
85
+ # AVR (extended) COFF requires stabs, plus an avr-objcopy run.
86
+ DEBUG = stabs
87
+
88
+ OPT = s
89
+
90
+ # Place -D or -U options here
91
+ CDEFS = -DF_CPU=$(F_CPU)
92
+ CXXDEFS = -DF_CPU=$(F_CPU)
93
+
94
+ # Place -I options here
95
+ CINCS = -I$(ARDUINO) -I$(SOFTWARE_SERIAL)<% params['libraries'].each do |l| %> -I$(LIBRARY_ROOT)/<%= l %><% end %>
96
+ +CXXINCS = -I$(ARDUINO) -I$(SOFTWARE_SERIAL)<% params['libraries'].each do |l| %> -I$(LIBRARY_ROOT)/<%= l %><% end %>
97
+
98
+ # Compiler flag to set the C Standard level.
99
+ # c89 - "ANSI" C
100
+ # gnu89 - c89 plus GCC extensions
101
+ # c99 - ISO C99 standard (not yet fully implemented)
102
+ # gnu99 - c99 plus GCC extensions
103
+ CSTANDARD = -std=gnu99
104
+ CDEBUG = -g$(DEBUG)
105
+ CWARN = -Wall -Wstrict-prototypes
106
+ CTUNING = -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums
107
+ #CEXTRA = -Wa,-adhlns=$(<:.c=.lst)
108
+
109
+ CFLAGS = $(CDEBUG) $(CDEFS) $(CINCS) -O$(OPT) $(CWARN) $(CSTANDARD) $(CEXTRA)
110
+ CXXFLAGS = $(CDEFS) $(CINCS) -O$(OPT)
111
+ #ASFLAGS = -Wa,-adhlns=$(<:.S=.lst),-gstabs
112
+ LDFLAGS = -lm
113
+
114
+
115
+ # Programming support using avrdude. Settings and variables.
116
+ AVRDUDE_PROGRAMMER = stk500
117
+ AVRDUDE_PORT = $(PORT)
118
+ AVRDUDE_WRITE_FLASH = -U flash:w:$(TARGET).hex
119
+ AVRDUDE_FLAGS = -F -p $(MCU) -P $(AVRDUDE_PORT) -c $(AVRDUDE_PROGRAMMER) \
120
+ -b $(UPLOAD_RATE) -C <%= params['arduino_root'] %>/hardware/tools/avr/etc/avrdude.conf
121
+
122
+ # Program settings
123
+ CC = $(BIN_DIR)/avr-gcc
124
+ CXX = $(BIN_DIR)/avr-g++
125
+ OBJCOPY = $(BIN_DIR)/avr-objcopy
126
+ OBJDUMP = $(BIN_DIR)/avr-objdump
127
+ AR = $(BIN_DIR)/avr-ar
128
+ SIZE = $(BIN_DIR)/avr-size
129
+ NM = $(BIN_DIR)/avr-nm
130
+ AVRDUDE = $(BIN_DIR)/avrdude
131
+ REMOVE = rm -f
132
+ MV = mv -f
133
+
134
+ # Define all object files.
135
+ OBJ = $(SRC:.c=.o) $(CXXSRC:.cpp=.o) $(ASRC:.S=.o)
136
+
137
+ # Define all listing files.
138
+ LST = $(ASRC:.S=.lst) $(CXXSRC:.cpp=.lst) $(SRC:.c=.lst)
139
+
140
+ # Combine all necessary flags and optional flags.
141
+ # Add target processor to flags.
142
+ ALL_CFLAGS = -mmcu=$(MCU) -I. $(CFLAGS)
143
+ ALL_CXXFLAGS = -mmcu=$(MCU) -I. $(CXXFLAGS)
144
+ ALL_ASFLAGS = -mmcu=$(MCU) -I. -x assembler-with-cpp $(ASFLAGS)
145
+
146
+
147
+ # Default target.
148
+ all: build
149
+
150
+ build: elf hex
151
+
152
+ elf: $(TARGET).elf
153
+ hex: $(TARGET).hex
154
+ eep: $(TARGET).eep
155
+ lss: $(TARGET).lss
156
+ sym: $(TARGET).sym
157
+
158
+ # Program the device.
159
+ upload: $(TARGET).hex
160
+ $(AVRDUDE) $(AVRDUDE_FLAGS) $(AVRDUDE_WRITE_FLASH)
161
+
162
+
163
+
164
+
165
+ # Convert ELF to COFF for use in debugging / simulating in AVR Studio or VMLAB.
166
+ COFFCONVERT=$(OBJCOPY) --debugging \
167
+ --change-section-address .data-0x800000 \
168
+ --change-section-address .bss-0x800000 \
169
+ --change-section-address .noinit-0x800000 \
170
+ --change-section-address .eeprom-0x810000
171
+
172
+
173
+ coff: $(TARGET).elf
174
+ $(COFFCONVERT) -O coff-avr $(TARGET).elf $(TARGET).cof
175
+
176
+
177
+ extcoff: $(TARGET).elf
178
+ $(COFFCONVERT) -O coff-ext-avr $(TARGET).elf $(TARGET).cof
179
+
180
+
181
+ .SUFFIXES: .elf .hex .eep .lss .sym
182
+
183
+ .elf.hex:
184
+ $(OBJCOPY) -O $(FORMAT) -R .eeprom $< $@
185
+
186
+ .elf.eep:
187
+ -$(OBJCOPY) -j .eeprom --set-section-flags=.eeprom="alloc,load" \
188
+ --change-section-lma .eeprom=0 -O $(FORMAT) $< $@
189
+
190
+ # Create extended listing file from ELF output file.
191
+ .elf.lss:
192
+ $(OBJDUMP) -h -S $< > $@
193
+
194
+ # Create a symbol table from ELF output file.
195
+ .elf.sym:
196
+ $(NM) -n $< > $@
197
+
198
+
199
+ core.a: $(OBJ)
200
+ @for i in $(OBJ); do echo $(AR) rcs core.a $$i; $(AR) rcs core.a $$i; done
201
+
202
+ # Link: create ELF output file from library.
203
+ $(TARGET).elf: core.a
204
+ $(CC) $(ALL_CFLAGS) -o $@ $(TARGET).cpp -L. core.a $(LDFLAGS)
205
+
206
+ # Compile: create object files from C++ source files.
207
+ .cpp.o:
208
+ $(CXX) -c $(ALL_CXXFLAGS) $< -o $@
209
+
210
+ # Compile: create object files from C source files.
211
+ .c.o:
212
+ $(CC) -c $(ALL_CFLAGS) $< -o $@
213
+
214
+
215
+ # Compile: create assembler files from C source files.
216
+ .c.s:
217
+ $(CC) -S $(ALL_CFLAGS) $< -o $@
218
+
219
+
220
+ # Assemble: create object files from assembler source files.
221
+ .S.o:
222
+ $(CC) -c $(ALL_ASFLAGS) $< -o $@
223
+
224
+
225
+
226
+ # Target: clean project.
227
+ clean:
228
+ $(REMOVE) $(TARGET).hex $(TARGET).eep $(TARGET).cof $(TARGET).elf \
229
+ $(TARGET).map $(TARGET).sym $(TARGET).lss core.a \
230
+ $(OBJ) $(LST) $(SRC:.c=.s) $(SRC:.c=.d) $(CXXSRC:.cpp=.s) $(CXXSRC:.cpp=.d)
231
+
232
+ depend:
233
+ if grep '^# DO NOT DELETE' $(MAKEFILE) >/dev/null; \
234
+ then \
235
+ sed -e '/^# DO NOT DELETE/,$$d' $(MAKEFILE) > \
236
+ $(MAKEFILE).$$$$ && \
237
+ $(MV) $(MAKEFILE).$$$$ $(MAKEFILE); \
238
+ fi
239
+ echo '# DO NOT DELETE THIS LINE -- make depend depends on it.' \
240
+ >> $(MAKEFILE); \
241
+ $(CC) -M -mmcu=$(MCU) $(CDEFS) $(CINCS) $(SRC) $(ASRC) >> $(MAKEFILE)
242
+
243
+ .PHONY: all build elf hex eep lss sym program coff extcoff clean depend
@@ -0,0 +1,39 @@
1
+ require 'erb'
2
+ require 'yaml'
3
+
4
+ class Makefile
5
+ class << self
6
+
7
+ # build the sketch Makefile for the given template based on the values in its software and hardware config files
8
+ def compose_for_sketch(sketch_name)
9
+ params = hardware_params.merge software_params
10
+ params['target'] = sketch_name
11
+
12
+ params['libraries_root'] = "#{File.expand_path(RAD_ROOT)}/vendor/libraries"
13
+ params['libraries'] = libraries
14
+
15
+ params['asm_files'] = Dir.entries( File.expand_path(RAD_ROOT) + "/" + PROJECT_DIR_NAME ).select{|e| e =~ /\.S/}
16
+
17
+ e = ERB.new File.read("#{File.dirname(__FILE__)}/makefile.erb")
18
+
19
+ File.open("#{RAD_ROOT}/#{sketch_name}/Makefile", "w") do |f|
20
+ f << e.result(binding)
21
+ end
22
+ end
23
+
24
+ def libraries
25
+ Dir.entries("#{RAD_ROOT}/vendor/libraries").select{|e| !(e =~ /\./)}
26
+ end
27
+
28
+ def hardware_params
29
+ return @hardware_params if @hardware_params
30
+ return @hardware_params = YAML.load_file( "#{RAD_ROOT}/config/hardware.yml")
31
+ end
32
+
33
+ def software_params
34
+ return @software_params if @software_params
35
+ return @software_params = YAML.load_file( "#{RAD_ROOT}/config/software.yml" )
36
+ end
37
+
38
+ end
39
+ end
data/lib/rad/init.rb ADDED
@@ -0,0 +1,12 @@
1
+ RAD_ROOT = "#{File.dirname(__FILE__)}/../.." unless defined?(RAD_ROOT)
2
+
3
+ unless defined?(PROJECT_DIR_NAME)
4
+ a = File.expand_path(File.expand_path("#{RAD_ROOT}")).split("/")
5
+ PROJECT_DIR_NAME = a[a.length-1]
6
+ end
7
+
8
+
9
+ %w(generators/makefile/makefile.rb rad_processor.rb rad_rewriter.rb arduino_sketch.rb arduino_plugin.rb tasks/rad.rb).each do |path|
10
+ require File.expand_path("#{RAD_ROOT}/vendor/rad/#{path}")
11
+ end
12
+
@@ -0,0 +1,66 @@
1
+ require 'ruby_to_ansi_c'
2
+
3
+ class RADProcessor < RubyToAnsiC
4
+
5
+ def self.translator
6
+ unless defined? @translator then
7
+ @translator = CompositeSexpProcessor.new
8
+ @translator << RADRewriter.new
9
+ @translator << TypeChecker.new
10
+ @translator << R2CRewriter.new
11
+ @translator << self.new
12
+ @translator.on_error_in(:defn) do |processor, exp, err|
13
+ result = processor.expected.new
14
+ case result
15
+ when Array then
16
+ result << :error
17
+ end
18
+ msg = "// ERROR: #{err.class}: #{err}"
19
+ msg += " in #{exp.inspect}" unless exp.nil? or $TESTING
20
+ msg += " from #{caller.join(', ')}" unless $TESTING
21
+ result << msg
22
+ result
23
+ end
24
+ end
25
+ @translator
26
+ end
27
+
28
+ def process_lasgn(exp)
29
+ out = ""
30
+
31
+ var = exp.shift
32
+ value = exp.shift
33
+ # grab the size of the args, if any, before process converts to a string
34
+ arg_count = 0
35
+ arg_count = value.length - 1 if value.first == :array
36
+ args = value
37
+
38
+ exp_type = exp.sexp_type
39
+ @env.add var.to_sym, exp_type
40
+ var_type = self.class.c_type exp_type
41
+
42
+ if exp_type.list? then
43
+ assert_type args, :array
44
+
45
+ raise "array must be of one type" unless args.sexp_type == Type.homo
46
+
47
+ # HACK: until we figure out properly what to do w/ zarray
48
+ # before we know what its type is, we will default to long.
49
+ array_type = args.sexp_types.empty? ? 'void *' : self.class.c_type(args.sexp_types.first)
50
+ # we can fix array here..
51
+ args.shift # :arglist
52
+ out << "#{var} = (#{array_type}) malloc(sizeof(#{array_type}) * #{args.length});\n"
53
+ args.each_with_index do |o,i|
54
+ out << "#{var}[#{i}] = #{process o};\n"
55
+ end
56
+ else
57
+ out << "#{var} = #{process args}"
58
+ end
59
+
60
+ out.sub!(/;\n\Z/, '')
61
+
62
+ return out
63
+ end
64
+
65
+
66
+ end
@@ -0,0 +1,94 @@
1
+ require 'ruby_to_ansi_c'
2
+
3
+ class RADRewriter < Rewriter
4
+
5
+ def process_iter(exp)
6
+ call = process exp.shift
7
+ var = process exp.shift
8
+ body = process exp.shift
9
+
10
+ var = s(:dasgn_curr, Unique.next) if var.nil?
11
+
12
+ assert_type call, :call
13
+
14
+ if call[2] != :each then # TODO: fix call[n] (api)
15
+ call.shift # :call
16
+ lhs = call.shift
17
+ method_name = call.shift
18
+
19
+ case method_name
20
+ when :downto then
21
+ var.shift #
22
+ start_value = lhs
23
+ finish_value = call.pop.pop # not sure about this
24
+ var_name = var.shift
25
+ body.find_and_replace_all(:dvar, :lvar)
26
+ result = s(:dummy,
27
+ s(:lasgn, var_name, start_value),
28
+ s(:while,
29
+ s(:call, s(:lvar, var_name), :>=,
30
+ s(:arglist, finish_value)),
31
+ s(:block,
32
+ body,
33
+ s(:lasgn, var_name,
34
+ s(:call, s(:lvar, var_name), :-,
35
+ s(:arglist, s(:lit, 1))))), true))
36
+ when :upto then
37
+ # REFACTOR: completely duped from above and direction changed
38
+ var.shift #
39
+ start_value = lhs
40
+ finish_value = call.pop.pop # not sure about this
41
+ var_name = var.shift
42
+ body.find_and_replace_all(:dvar, :lvar)
43
+ result = s(:dummy,
44
+ s(:lasgn, var_name, start_value),
45
+ s(:while,
46
+ s(:call, s(:lvar, var_name), :<=,
47
+ s(:arglist, finish_value)),
48
+ s(:block,
49
+ body,
50
+ s(:lasgn, var_name,
51
+ s(:call, s(:lvar, var_name), :+,
52
+ s(:arglist, s(:lit, 1))))), true))
53
+ when :times then
54
+ # REFACTOR: mostly duped from above and gave default start value of 0
55
+ # and a finish value that was the start value above
56
+ var.shift
57
+ start_value = s(:lit, 0)
58
+ finish_value = lhs
59
+ var_name = var.shift
60
+ body.find_and_replace_all(:dvar, :lvar)
61
+ result = s(:dummy,
62
+ s(:lasgn, var_name, start_value),
63
+ s(:while,
64
+ s(:call, s(:lvar, var_name), :<=,
65
+ s(:arglist, finish_value)),
66
+ s(:block,
67
+ body,
68
+ s(:lasgn, var_name,
69
+ s(:call, s(:lvar, var_name), :+,
70
+ s(:arglist, s(:lit, 1))))), true))
71
+ when :define_method then
72
+ # BEFORE: [:iter, [:call, nil, :define_method, [:array, [:lit, :bmethod_added]]], [:dasgn_curr, :x], [:call, [:dvar, :x], :+, [:array, [:lit, 1]]]]
73
+ # we want to get it rewritten for the scope/block context, so:
74
+ # - throw call away
75
+ # - rewrite to args
76
+ # - plop body into a scope
77
+ # AFTER: [:block, [:args, :x], [:call, [:lvar, :x], :+, [:arglist, [:lit, 1]]]]
78
+ var.find_and_replace_all(:dasgn_curr, :args)
79
+ body.find_and_replace_all(:dvar, :lvar)
80
+ result = s(:block, var, body)
81
+ else
82
+ # HACK we butchered call up top
83
+ result = s(:iter, s(:call, lhs, method_name, call.shift), var, body)
84
+ end
85
+ else
86
+ if var.nil? then
87
+ var = s(:lvar, Unique.next)
88
+ end
89
+
90
+ s(:iter, call, var, body)
91
+ end
92
+ end
93
+
94
+ end
@@ -0,0 +1,159 @@
1
+ require File.expand_path(File.dirname(__FILE__) + "/../init.rb")
2
+ require 'ruby_to_ansi_c'
3
+
4
+ C_VAR_TYPES = "unsigned|int|long|double|str|char"
5
+
6
+ namespace :make do
7
+
8
+ desc "compile the sketch and then upload it to your Arduino board"
9
+ task :upload => :compile do
10
+ if Makefile.hardware_params['physical_reset']
11
+ puts "Reset the Arduino and hit enter.\n==If your board doesn't need it, you can turn off this prompt in config/software.yml=="
12
+ STDIN.gets.chomp
13
+ end
14
+ sh %{cd #{RAD_ROOT}/#{@sketch_name}; make upload}
15
+ end
16
+
17
+ desc "generate a makefile and use it to compile the .cpp"
18
+ task :compile => [:clean_sketch_dir, "build:sketch"] do # should also depend on "build:sketch"
19
+ Makefile.compose_for_sketch( @sketch_name )
20
+ # not allowed? sh %{export PATH=#{Makefile.software_params[:arduino_root]}/tools/avr/bin:$PATH}
21
+ sh %{cd #{RAD_ROOT}/#{@sketch_name}; make depend; make}
22
+ end
23
+
24
+ desc "generate a makefile and use it to compile the .cpp using the current .cpp file"
25
+ task :compile_cpp => ["build:sketch_dir", :clean_sketch_dir] do # should also depend on "build:sketch"
26
+ Makefile.compose_for_sketch( @sketch_name )
27
+ # not allowed? sh %{export PATH=#{Makefile.software_params[:arduino_root]}/tools/avr/bin:$PATH}
28
+ sh %{cd #{RAD_ROOT}/#{@sketch_name}; make depend; make}
29
+ end
30
+
31
+ desc "generate a makefile and use it to compile the .cpp and upload it using current .cpp file"
32
+ task :upload_cpp => ["build:sketch_dir", :clean_sketch_dir] do # should also depend on "build:sketch"
33
+ Makefile.compose_for_sketch( @sketch_name )
34
+ # not allowed? sh %{export PATH=#{Makefile.software_params[:arduino_root]}/tools/avr/bin:$PATH}
35
+ sh %{cd #{RAD_ROOT}/#{@sketch_name}; make depend; make upload}
36
+ end
37
+
38
+ task :clean_sketch_dir => ["build:file_list", "build:sketch_dir"] do
39
+ @sketch_name = @sketch_class.split(".").first
40
+ FileList.new(Dir.entries("#{RAD_ROOT}/#{@sketch_name}")).exclude("#{@sketch_name}.cpp").exclude(/^\./).each do |f|
41
+ sh %{rm #{RAD_ROOT}/#{@sketch_name}/#{f}}
42
+ end
43
+ end
44
+ end
45
+
46
+ namespace :build do
47
+
48
+ desc "actually build the sketch"
49
+ task :sketch => [:file_list, :sketch_dir, :gather_required_plugins, :plugin_setup, :setup] do
50
+ klass = @sketch_class.split(".").first.split("_").collect{|c| c.capitalize}.join("")
51
+ eval ArduinoSketch.pre_process(File.read(@sketch_class))
52
+ c_methods = []
53
+ sketch_signatures = []
54
+ $sketch_methods.each {|m| c_methods << RADProcessor.translate(constantize(klass), m) }
55
+ c_methods.each {|meth| sketch_signatures << "#{meth.scan(/^\w*\s?\*?\n.*\)/)[0].gsub("\n", " ")};" }
56
+ clean_c_methods = []
57
+ c_methods.join("\n").each_with_index do |e,i|
58
+ # need to take a look at the \(unsigned in the line below not sure if we are really trying to catch something like that
59
+ if e !~ /^\s*(#{C_VAR_TYPES})(\W{1,6}|\(unsigned\()(#{$external_var_identifiers.join("|")})/ || $external_var_identifiers.empty?
60
+ # use the list of identifers the external_vars method of the sketch and remove the parens the ruby2c sometime adds to variables
61
+ e.gsub(/((#{$external_var_identifiers.join("|")})\(\))/, '\2') unless $external_var_identifiers.empty?
62
+ clean_c_methods << e
63
+ end
64
+ end
65
+ c_methods_with_timer = clean_c_methods.join.gsub(/loop\(\)\s\{/,"loop() {\ntrack_total_loop_time();")
66
+ @setup.gsub!("// sketch signatures", "// sketch signatures\n#{ sketch_signatures.join("\n")}") unless sketch_signatures.empty?
67
+ result = "#{@setup}\n#{c_methods_with_timer}\n"
68
+ name = @sketch_class.split(".").first
69
+ File.open("#{name}/#{name}.cpp", "w"){|f| f << result}
70
+ end
71
+
72
+ # needs to write the library include and the method signatures
73
+ desc "build setup function"
74
+ task :setup do
75
+ klass = @sketch_class.split(".").first.split("_").collect{|c| c.capitalize}.join("")
76
+ eval "class #{klass} < ArduinoSketch; end;"
77
+
78
+ @@as = ArduinoSketch.new
79
+
80
+ delegate_methods = @@as.methods - Object.new.methods
81
+ delegate_methods.reject!{|m| m == "compose_setup"}
82
+
83
+ delegate_methods.each do |meth|
84
+ constantize(klass).module_eval <<-CODE
85
+ def self.#{meth}(*args)
86
+ @@as.#{meth}(*args)
87
+ end
88
+ CODE
89
+ end
90
+ eval File.read(@sketch_class)
91
+ @setup = @@as.compose_setup
92
+ end
93
+
94
+ desc "add plugin methods"
95
+ task :plugin_setup do
96
+ $plugins_to_load.each do |name|
97
+ klass = name.split(".").first.split("_").collect{|c| c.capitalize}.join("")
98
+ eval "class #{klass} < ArduinoPlugin; end;"
99
+
100
+ @@ps = ArduinoPlugin.new
101
+ plugin_delegate_methods = @@ps.methods - Object.new.methods
102
+ plugin_delegate_methods.reject!{|m| m == "compose_setup"}
103
+
104
+ plugin_delegate_methods.each do |meth|
105
+ constantize(klass).module_eval <<-CODE
106
+ def self.#{meth}(*args)
107
+ @@ps.#{meth}(*args)
108
+ end
109
+ CODE
110
+ end
111
+
112
+ eval ArduinoPlugin.process(File.read("vendor/plugins/#{name}"))
113
+
114
+ end
115
+ @@no_plugins = ArduinoPlugin.new if @plugin_names.empty?
116
+ end
117
+
118
+ desc "determine which plugins to load based on use of methods in sketch"
119
+ task :gather_required_plugins do
120
+ @plugin_names.each do |name|
121
+ ArduinoPlugin.check_for_plugin_use(File.read(@sketch_class), File.read("vendor/plugins/#{name}"), name )
122
+ end
123
+ puts "#{$plugins_to_load.length} of #{$plugin_methods_hash.length} plugins are being loaded: #{$plugins_to_load.join(", ")}"
124
+ end
125
+
126
+ desc "setup target directory named after your sketch class"
127
+ task :sketch_dir => [:file_list] do
128
+ mkdir_p "#{@sketch_class.split(".").first}"
129
+ end
130
+
131
+ task :file_list do
132
+ # take another look at this, since if the root directory name is changed, everything breaks
133
+ # perhaps we generate a constant when the project is generated an pop it here or in the init file
134
+ @sketch_directory = File.expand_path("#{File.dirname(__FILE__)}/../../../").split("/").last
135
+ # multiple sketches are possible with rake make:upload sketch=new_sketch
136
+ @sketch_class = ENV['sketch'] ? "#{ENV['sketch']}.rb" : "#{@sketch_directory}.rb"
137
+ @file_names = []
138
+ @plugin_names = []
139
+ Dir.entries( File.expand_path(RAD_ROOT) ).each do |f|
140
+ if (f =~ /\.rb$/)
141
+ @file_names << f
142
+ end
143
+ end
144
+ Dir.entries( File.expand_path("#{RAD_ROOT}/vendor/plugins/") ).each do |f|
145
+ if (f =~ /\.rb$/)
146
+ @plugin_names << f
147
+ end
148
+ end
149
+ end
150
+ end
151
+
152
+ #yoinked from Rails
153
+ def constantize(camel_cased_word)
154
+ unless /\A(?:::)?([A-Z]\w*(?:::[A-Z]\w*)*)\z/ =~ camel_cased_word
155
+ raise NameError, "#{camel_cased_word.inspect} is not a valid constant name!"
156
+ end
157
+
158
+ Object.module_eval("::#{$1}", __FILE__, __LINE__)
159
+ end
@@ -0,0 +1,2 @@
1
+ require 'rake'
2
+ Dir["#{File.dirname(__FILE__)}/*.rake"].each { |ext| load ext }
data/lib/rad/todo.txt ADDED
@@ -0,0 +1,13 @@
1
+ TODO:
2
+ =====
3
+
4
+ Future:
5
+ - complete library system: script/install library some_library
6
+ - bin/rad:
7
+ - setup and use a ~/.rad for new project defaults
8
+ - put repository on git
9
+ - project gallery (examples with movies)
10
+ - testing framework
11
+ - implement wire lib
12
+ - subclasses of ArduinoSketch (should just work, but what are they for?)
13
+ - simulator
@@ -0,0 +1,9 @@
1
+ module Rad #:nodoc:
2
+ module VERSION #:nodoc:
3
+ MAJOR = 0
4
+ MINOR = 2
5
+ TINY = 2
6
+
7
+ STRING = [MAJOR, MINOR, TINY].join('.')
8
+ end
9
+ end
data/lib/rad.rb ADDED
@@ -0,0 +1,5 @@
1
+ module Rad
2
+ end
3
+
4
+ require 'rad/version'
5
+ require 'rad/init'