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,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
|
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
|
data/lib/rad/version.rb
ADDED