workshop 0.0.1
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.
- checksums.yaml +7 -0
- data/.gitignore +18 -0
- data/.rspec +2 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +23 -0
- data/Rakefile +1 -0
- data/bin/workshop +3 -0
- data/examples/blink/Rakefile +15 -0
- data/examples/blink/config/com_port.yml +2 -0
- data/examples/blink/src/blink.cpp +30 -0
- data/lib/workshop.rb +18 -0
- data/lib/workshop/arduino.rb +34 -0
- data/lib/workshop/builder.rb +199 -0
- data/lib/workshop/cli.rb +23 -0
- data/lib/workshop/project.rb +99 -0
- data/lib/workshop/project/configuration.rb +71 -0
- data/lib/workshop/project/configuration/build.rb +18 -0
- data/lib/workshop/project/configuration/upload.rb +15 -0
- data/lib/workshop/project/setup.rb +76 -0
- data/lib/workshop/tasks.rb +64 -0
- data/lib/workshop/templates/Rakefile.erb +13 -0
- data/lib/workshop/templates/blink.cpp +30 -0
- data/lib/workshop/tools.rb +56 -0
- data/lib/workshop/uploader.rb +35 -0
- data/lib/workshop/version.rb +3 -0
- data/spec/arduino_spec.rb +31 -0
- data/spec/build_configuration_spec.rb +52 -0
- data/spec/builder_spec.rb +159 -0
- data/spec/configuration_spec.rb +38 -0
- data/spec/project_spec.rb +29 -0
- data/spec/spec_helper.rb +8 -0
- data/spec/tools_spec.rb +33 -0
- data/spec/upload_configuration_spec.rb +9 -0
- data/workshop.gemspec +31 -0
- metadata +186 -0
@@ -0,0 +1,71 @@
|
|
1
|
+
module Workshop
|
2
|
+
class Project
|
3
|
+
class Configuration
|
4
|
+
attr_accessor :arduino_app_directory, :project_name, :source_directory, :build, :upload,
|
5
|
+
:build_directory, :main_filename, :libraries
|
6
|
+
|
7
|
+
def initialize
|
8
|
+
self.arduino_app_directory = '/Applications/Arduino.app'
|
9
|
+
self.project_name = default_project_name
|
10
|
+
self.source_directory = default_source_directory
|
11
|
+
self.build_directory = default_build_directory
|
12
|
+
self.libraries = []
|
13
|
+
self.build = Build.new
|
14
|
+
self.upload = Upload.new
|
15
|
+
end
|
16
|
+
|
17
|
+
def includes
|
18
|
+
build.includes
|
19
|
+
end
|
20
|
+
|
21
|
+
def default_project_name
|
22
|
+
app_directory.split('/').last.parameterize.underscore
|
23
|
+
end
|
24
|
+
|
25
|
+
def default_build_directory
|
26
|
+
app_directory + '/build'
|
27
|
+
end
|
28
|
+
|
29
|
+
def default_source_directory
|
30
|
+
app_directory + '/src'
|
31
|
+
end
|
32
|
+
|
33
|
+
def app_directory
|
34
|
+
Dir.pwd
|
35
|
+
end
|
36
|
+
|
37
|
+
def build_core
|
38
|
+
build.core
|
39
|
+
end
|
40
|
+
|
41
|
+
def build_variant
|
42
|
+
build.variant
|
43
|
+
end
|
44
|
+
|
45
|
+
def build_mcu
|
46
|
+
build.mcu
|
47
|
+
end
|
48
|
+
|
49
|
+
def build_f_cpu
|
50
|
+
build.f_cpu
|
51
|
+
end
|
52
|
+
|
53
|
+
def build_vid
|
54
|
+
build.vid
|
55
|
+
end
|
56
|
+
|
57
|
+
def build_pid
|
58
|
+
build.pid
|
59
|
+
end
|
60
|
+
|
61
|
+
def upload_protocol
|
62
|
+
upload.protocol
|
63
|
+
end
|
64
|
+
|
65
|
+
def upload_speed
|
66
|
+
upload.speed
|
67
|
+
end
|
68
|
+
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module Workshop
|
2
|
+
class Project
|
3
|
+
class Configuration
|
4
|
+
class Build
|
5
|
+
attr_accessor :mcu, :core, :variant, :f_cpu, :vid, :pid, :libraries, :includes
|
6
|
+
|
7
|
+
def initialize
|
8
|
+
self.mcu = 'atmega328p'
|
9
|
+
self.core = 'arduino'
|
10
|
+
self.variant = 'standard'
|
11
|
+
self.f_cpu = '8000000L'
|
12
|
+
self.libraries = []
|
13
|
+
self.includes = []
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,76 @@
|
|
1
|
+
module Workshop
|
2
|
+
class Project
|
3
|
+
class Setup
|
4
|
+
attr_accessor :project_name, :base_directory
|
5
|
+
|
6
|
+
def initialize(base_directory, project_name)
|
7
|
+
self.base_directory = base_directory
|
8
|
+
self.project_name = project_name
|
9
|
+
end
|
10
|
+
|
11
|
+
def run
|
12
|
+
create_base_directory
|
13
|
+
create_sub_directories
|
14
|
+
create_rakefile
|
15
|
+
copy_blink_app
|
16
|
+
end
|
17
|
+
|
18
|
+
def log_create(name)
|
19
|
+
puts "create #{name}".colorize(:green)
|
20
|
+
end
|
21
|
+
|
22
|
+
def relative(path)
|
23
|
+
to = Pathname.new(path)
|
24
|
+
from = Pathname.new(base_directory)
|
25
|
+
rel = to.relative_path_from(from)
|
26
|
+
rel.to_s
|
27
|
+
end
|
28
|
+
|
29
|
+
def create_base_directory
|
30
|
+
if Dir.exist?(base_directory)
|
31
|
+
puts "folder already exists"
|
32
|
+
else
|
33
|
+
log_create(relative(base_directory))
|
34
|
+
Dir.mkdir(base_directory)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def create_sub_directories
|
39
|
+
['src', 'config'].each do |dirname|
|
40
|
+
dir = base_directory + '/' + dirname
|
41
|
+
log_create(relative(dir))
|
42
|
+
Dir.mkdir(dir)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def resolve_file(file)
|
47
|
+
dir = File.dirname(__FILE__)
|
48
|
+
File.join(dir, file)
|
49
|
+
end
|
50
|
+
|
51
|
+
def read_file(file)
|
52
|
+
File.read(resolve_file(file))
|
53
|
+
end
|
54
|
+
|
55
|
+
def write_file(file, contents)
|
56
|
+
log_create(file)
|
57
|
+
File.open(base_directory + '/' + file, 'w') do |file|
|
58
|
+
file.puts contents
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
def create_rakefile
|
63
|
+
template = ERB.new(read_file('../templates/Rakefile.erb'))
|
64
|
+
rakefile = template.result(binding)
|
65
|
+
write_file('Rakefile', rakefile)
|
66
|
+
end
|
67
|
+
|
68
|
+
def copy_blink_app
|
69
|
+
file = read_file('../templates/blink.cpp')
|
70
|
+
write_file('src/' + project_name + '.cpp', file)
|
71
|
+
end
|
72
|
+
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
@@ -0,0 +1,64 @@
|
|
1
|
+
module Workshop
|
2
|
+
class Tasks
|
3
|
+
include Rake::DSL
|
4
|
+
def initialize(builder, uploader)
|
5
|
+
|
6
|
+
desc 'create build directory'
|
7
|
+
task :init do
|
8
|
+
builder.create_build_directory
|
9
|
+
end
|
10
|
+
|
11
|
+
desc 'compile core, variant, and app source code'
|
12
|
+
task :compile => [:init] do
|
13
|
+
builder.compile
|
14
|
+
end
|
15
|
+
|
16
|
+
desc 'create archive from core, variant, and app source (except main loop file)'
|
17
|
+
task :archive => [:compile] do
|
18
|
+
builder.archive
|
19
|
+
end
|
20
|
+
|
21
|
+
desc 'link archive and main loop object file'
|
22
|
+
task :link => [:archive] do
|
23
|
+
builder.link
|
24
|
+
end
|
25
|
+
|
26
|
+
desc 'create eeprom file'
|
27
|
+
task :eeprom => [:link] do
|
28
|
+
builder.create_eeprom
|
29
|
+
end
|
30
|
+
|
31
|
+
desc 'create compiled *.hex file'
|
32
|
+
task :hex => [:link] do
|
33
|
+
builder.create_hex
|
34
|
+
end
|
35
|
+
|
36
|
+
desc 'delete build directory'
|
37
|
+
task :clean do
|
38
|
+
puts "Removing the build directory"
|
39
|
+
builder.clean
|
40
|
+
end
|
41
|
+
|
42
|
+
desc 'upload *.hex file to arduino'
|
43
|
+
task :upload => [:build] do
|
44
|
+
uploader.upload
|
45
|
+
end
|
46
|
+
|
47
|
+
desc 'open a console to the arduino (ctrl-a ctrl-| to exit)'
|
48
|
+
task :console do
|
49
|
+
sh "screen #{uploader.com_port} 9600"
|
50
|
+
end
|
51
|
+
|
52
|
+
desc 'build *.hex and eeprom files'
|
53
|
+
task :build => [:hex, :eeprom]
|
54
|
+
|
55
|
+
desc 'find connected arduino and update config/com_port.yml with port'
|
56
|
+
task :find do
|
57
|
+
# TODO - find COM port and create config/com_port.yml
|
58
|
+
end
|
59
|
+
|
60
|
+
desc 'build application'
|
61
|
+
task :default => :build
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
require 'workshop'
|
2
|
+
|
3
|
+
Workshop::Project.configure do |config|
|
4
|
+
config.project_name = '<%= project_name %>'
|
5
|
+
config.build.mcu = 'atmega328p'
|
6
|
+
config.build.core = 'arduino'
|
7
|
+
config.build.variant = 'standard'
|
8
|
+
# config.build.vid = '0x0000'
|
9
|
+
# config.build.pid = '0x0000'
|
10
|
+
config.build.f_cpu = '16000000L'
|
11
|
+
config.upload.protocol = 'arduino'
|
12
|
+
config.upload.speed = 57600
|
13
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
#line 1 "Blink.ino"
|
2
|
+
/*
|
3
|
+
Blink
|
4
|
+
Turns on an LED on for one second, then off for one second, repeatedly.
|
5
|
+
|
6
|
+
This example code is in the public domain.
|
7
|
+
*/
|
8
|
+
|
9
|
+
// Pin 13 has an LED connected on most Arduino boards.
|
10
|
+
// give it a name:
|
11
|
+
#include "Arduino.h"
|
12
|
+
void setup();
|
13
|
+
void loop();
|
14
|
+
#line 10
|
15
|
+
int led = 13;
|
16
|
+
|
17
|
+
// the setup routine runs once when you press reset:
|
18
|
+
void setup() {
|
19
|
+
// initialize the digital pin as an output.
|
20
|
+
pinMode(led, OUTPUT);
|
21
|
+
}
|
22
|
+
|
23
|
+
// the loop routine runs over and over again forever:
|
24
|
+
void loop() {
|
25
|
+
digitalWrite(led, HIGH); // turn the LED on (HIGH is the voltage level)
|
26
|
+
delay(100); // wait for a second
|
27
|
+
digitalWrite(led, LOW); // turn the LED off by making the voltage LOW
|
28
|
+
delay(100); // wait for a second
|
29
|
+
}
|
30
|
+
|
@@ -0,0 +1,56 @@
|
|
1
|
+
module Workshop
|
2
|
+
class Tools
|
3
|
+
attr_accessor :hardware_directory
|
4
|
+
|
5
|
+
def initialize(hardware_directory)
|
6
|
+
self.hardware_directory = hardware_directory
|
7
|
+
end
|
8
|
+
|
9
|
+
def tools_directory
|
10
|
+
hardware_directory + '/tools'
|
11
|
+
end
|
12
|
+
|
13
|
+
def bin_directory
|
14
|
+
tools_directory + '/avr/bin'
|
15
|
+
end
|
16
|
+
|
17
|
+
def etc_directory
|
18
|
+
tools_directory + '/avr/etc'
|
19
|
+
end
|
20
|
+
|
21
|
+
def avr_gcc
|
22
|
+
bin_directory + '/avr-gcc'
|
23
|
+
end
|
24
|
+
|
25
|
+
def avr_gpp
|
26
|
+
bin_directory + '/avr-g++'
|
27
|
+
end
|
28
|
+
|
29
|
+
def avr_ar
|
30
|
+
bin_directory + '/avr-ar'
|
31
|
+
end
|
32
|
+
|
33
|
+
def avr_objcopy
|
34
|
+
bin_directory + '/avr-objcopy'
|
35
|
+
end
|
36
|
+
|
37
|
+
def avrdude
|
38
|
+
bin_directory + '/avrdude'
|
39
|
+
end
|
40
|
+
|
41
|
+
def avrdude_config
|
42
|
+
etc_directory + '/avrdude.conf'
|
43
|
+
end
|
44
|
+
|
45
|
+
def compiler_for_extendion
|
46
|
+
@_extension_map ||= {
|
47
|
+
'.c' => avr_gcc,
|
48
|
+
'.cpp' => avr_gpp
|
49
|
+
}
|
50
|
+
end
|
51
|
+
|
52
|
+
def compiler(filename)
|
53
|
+
compiler_for_extendion[File.extname(filename)]
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
module Workshop
|
2
|
+
class Uploader
|
3
|
+
include FileUtils
|
4
|
+
attr_accessor :project, :tools, :hex_filename
|
5
|
+
|
6
|
+
def initialize(project, hex_filename)
|
7
|
+
self.project = project
|
8
|
+
self.tools = Workshop::Tools.new project.arduino_hardware_directory
|
9
|
+
self.hex_filename = hex_filename
|
10
|
+
end
|
11
|
+
|
12
|
+
def com_port
|
13
|
+
project.com_port
|
14
|
+
end
|
15
|
+
|
16
|
+
def upload_command
|
17
|
+
[
|
18
|
+
tools.avrdude,
|
19
|
+
"-C #{tools.avrdude_config}",
|
20
|
+
"-v -v -v -v -v -v",
|
21
|
+
"-p #{project.build_mcu}",
|
22
|
+
"-c #{project.programmer}",
|
23
|
+
"-P #{project.com_port}",
|
24
|
+
"-b #{project.baud_rate}",
|
25
|
+
"-D",
|
26
|
+
"-Uflash:w:#{hex_filename}:i"
|
27
|
+
].join(' ')
|
28
|
+
end
|
29
|
+
|
30
|
+
def upload
|
31
|
+
sh upload_command
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Workshop::Arduino do
|
4
|
+
context 'arduino app is at "/app" and the core is set to "arduino"' do
|
5
|
+
let(:config) do
|
6
|
+
double(:configuration).tap do |config|
|
7
|
+
config.stub(:arduino_app_directory).and_return('/app')
|
8
|
+
config.stub(:build_core).and_return('arduino')
|
9
|
+
end
|
10
|
+
end
|
11
|
+
subject do
|
12
|
+
Workshop::Arduino.new(config).tap do |arduino|
|
13
|
+
arduino.stub(:hardware_path).and_return('/hardware')
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
describe '#hardware_directory' do
|
18
|
+
it 'returns "/app/hardware"' do
|
19
|
+
expected = "/app/hardware"
|
20
|
+
expect(subject.hardware_directory).to eq(expected)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
describe '#core_directory' do
|
25
|
+
it 'returns "/app/hardware/arduino/cores/arduino"' do
|
26
|
+
expected = "/app/hardware/arduino/cores/arduino"
|
27
|
+
expect(subject.core_directory).to eq(expected)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Workshop::Project::Configuration::Build do
|
4
|
+
|
5
|
+
describe '#mcu' do
|
6
|
+
it 'returns "atmega328p" as the default mcu' do
|
7
|
+
expect(subject.mcu).to eq('atmega328p')
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
describe '#core' do
|
12
|
+
it 'returns "arduino" as the default core' do
|
13
|
+
expect(subject.core).to eq('arduino')
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
describe '#variant' do
|
18
|
+
it 'returns "standard" as the default variant' do
|
19
|
+
expect(subject.variant).to eq('standard')
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
describe '#f_cpu' do
|
24
|
+
it 'returns "8000000L" as the default cpu frequency' do
|
25
|
+
expect(subject.f_cpu).to eq('8000000L')
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
describe '#vid' do
|
30
|
+
it 'returns nil as the default vid' do
|
31
|
+
expect(subject.vid).to eq(nil)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
describe '#pid' do
|
36
|
+
it 'returns nil as the default pid' do
|
37
|
+
expect(subject.pid).to eq(nil)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
describe '#libraries' do
|
42
|
+
it 'initialized with an empty array of libraries' do
|
43
|
+
expect(subject.libraries).to eq([])
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
describe '#includes' do
|
48
|
+
it 'initialized with an empty array of includes' do
|
49
|
+
expect(subject.includes).to eq([])
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|