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.
- 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