pedalboard 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.rspec +1 -0
- data/.rvmrc +1 -0
- data/.travis.yml +9 -0
- data/Gemfile +3 -0
- data/Gemfile.lock +65 -0
- data/README.md +25 -0
- data/bin/pedalboard +6 -0
- data/du/Dino.cpp +257 -0
- data/du/Dino.h +85 -0
- data/du/du.ino +19 -0
- data/examples/main_stage.rb +57 -0
- data/lib/pedalboard.rb +22 -0
- data/lib/pedalboard/cli.rb +21 -0
- data/lib/pedalboard/commands.rb +44 -0
- data/lib/pedalboard/components/base_component.rb +20 -0
- data/lib/pedalboard/components/led.rb +28 -0
- data/lib/pedalboard/components/pedal.rb +52 -0
- data/lib/pedalboard/components/pot.rb +78 -0
- data/lib/pedalboard/device.rb +32 -0
- data/lib/pedalboard/dsl_parser.rb +25 -0
- data/lib/pedalboard/version.rb +11 -0
- data/pedalboard.gemspec +27 -0
- data/spec/spec_helper.rb +5 -0
- data/spec/unit/pedalboard/cli_spec.rb +40 -0
- data/spec/unit/pedalboard/components/led_spec.rb +43 -0
- data/spec/unit/pedalboard/components/pedal_spec.rb +34 -0
- data/spec/unit/pedalboard/components/pot_spec.rb +54 -0
- data/spec/unit/pedalboard/device_spec.rb +47 -0
- data/spec/unit/pedalboard/dsl_parser_spec.rb +64 -0
- data/spec/unit/pedalboard_spec.rb +79 -0
- metadata +165 -0
data/du/du.ino
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
#include "Dino.h"
|
2
|
+
#include <Servo.h>
|
3
|
+
Dino dino;
|
4
|
+
|
5
|
+
// Dino.h doesn't handle TXRX. Setup a function to tell it to write to Serial.
|
6
|
+
void writeResponse(char *response) { Serial.print(response); Serial.print("\n"); }
|
7
|
+
void (*writeCallback)(char *str) = writeResponse;
|
8
|
+
|
9
|
+
void setup() {
|
10
|
+
Serial.begin(115200);
|
11
|
+
dino.setupWrite(writeCallback);
|
12
|
+
}
|
13
|
+
|
14
|
+
void loop() {
|
15
|
+
while(Serial.available() > 0) dino.parse(Serial.read());
|
16
|
+
dino.updateListeners();
|
17
|
+
Serial.flush();
|
18
|
+
}
|
19
|
+
|
@@ -0,0 +1,57 @@
|
|
1
|
+
led1 = nil
|
2
|
+
led2 = nil
|
3
|
+
led3 = nil
|
4
|
+
led4 = nil
|
5
|
+
|
6
|
+
altled1 = nil
|
7
|
+
altled2 = nil
|
8
|
+
altled3 = nil
|
9
|
+
altled4 = nil
|
10
|
+
|
11
|
+
pot pin: 'A0',
|
12
|
+
change: ->(value) { set_volume(value) }
|
13
|
+
|
14
|
+
pedal pin: 2,
|
15
|
+
press: ->{ patch 1 },
|
16
|
+
long_press: ->{ patch 4 }
|
17
|
+
|
18
|
+
pedal pin: 3,
|
19
|
+
press: ->{ patch 2 },
|
20
|
+
long_press: ->{ patch 5 }
|
21
|
+
|
22
|
+
pedal pin: 4,
|
23
|
+
press: ->{ patch 3 },
|
24
|
+
long_press: ->{ patch 6 }
|
25
|
+
|
26
|
+
pedal pin: 5,
|
27
|
+
press: ->{ next_set },
|
28
|
+
long_press: ->{ previous_set }
|
29
|
+
|
30
|
+
led1 = led pin: 6
|
31
|
+
led2 = led pin: 11
|
32
|
+
led3 = led pin: 8
|
33
|
+
led4 = led pin: 9
|
34
|
+
|
35
|
+
altled1 = led pin: 10
|
36
|
+
altled2 = led pin: 7
|
37
|
+
altled3 = led pin: 12
|
38
|
+
altled4 = led pin: 13
|
39
|
+
|
40
|
+
MIDI.using(pedalboard.midi_input, pedalboard.midi_output) do
|
41
|
+
receive do |message|
|
42
|
+
if message.index == 22
|
43
|
+
begin
|
44
|
+
led1.light_if message.value == 1
|
45
|
+
led2.light_if message.value == 2
|
46
|
+
led3.light_if message.value == 3
|
47
|
+
|
48
|
+
altled1.light_if message.value == 4
|
49
|
+
altled2.light_if message.value == 5
|
50
|
+
altled3.light_if message.value == 6
|
51
|
+
rescue Exception => e
|
52
|
+
puts e.message
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
data/lib/pedalboard.rb
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
require_relative 'pedalboard/cli'
|
2
|
+
require_relative 'pedalboard/dsl_parser'
|
3
|
+
require_relative 'pedalboard/device'
|
4
|
+
|
5
|
+
require_relative 'pedalboard/components/led'
|
6
|
+
require_relative 'pedalboard/components/pedal'
|
7
|
+
require_relative 'pedalboard/components/pot'
|
8
|
+
|
9
|
+
module Pedalboard
|
10
|
+
def self.create opts={}, &block
|
11
|
+
device_class = opts.delete(:device_class) { Device }
|
12
|
+
dsl_parser = opts.delete(:dsl_parser) { DSLParser }
|
13
|
+
|
14
|
+
parser = dsl_parser.new(
|
15
|
+
device_class.new(opts)
|
16
|
+
)
|
17
|
+
|
18
|
+
parser.instance_exec(&block) if block_given?
|
19
|
+
|
20
|
+
return parser.pedalboard
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require 'mixlib/cli'
|
2
|
+
|
3
|
+
require_relative '../pedalboard'
|
4
|
+
|
5
|
+
module Pedalboard
|
6
|
+
class CLI
|
7
|
+
include Mixlib::CLI
|
8
|
+
|
9
|
+
def create_device filename
|
10
|
+
contents = File.open(filename).read
|
11
|
+
Pedalboard.create do
|
12
|
+
eval contents
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def run args
|
17
|
+
options = parse_options(args)
|
18
|
+
options.each { |file| create_device file }
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
module Pedalboard
|
2
|
+
class Commands
|
3
|
+
NOTES = [
|
4
|
+
'c1', 'd1', 'e1',
|
5
|
+
'f1', 'g1', 'a1'
|
6
|
+
]
|
7
|
+
|
8
|
+
attr_reader :pedalboard
|
9
|
+
|
10
|
+
def initialize opts={}
|
11
|
+
@pedalboard = opts.fetch(:pedalboard) { }
|
12
|
+
end
|
13
|
+
|
14
|
+
def patch number
|
15
|
+
midi do
|
16
|
+
note NOTES[number - 1]
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def next_set
|
21
|
+
midi do
|
22
|
+
note 'b1'
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def previous_set
|
27
|
+
midi do
|
28
|
+
note 'c2'
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def set_volume value
|
33
|
+
midi do
|
34
|
+
cc 7, value
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def midi &block
|
39
|
+
MIDI.using(pedalboard.midi_input, pedalboard.midi_output) do
|
40
|
+
instance_exec &block
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
require_relative '../commands'
|
2
|
+
|
3
|
+
module Pedalboard; module Components
|
4
|
+
class BaseComponent
|
5
|
+
attr_reader :pin, :pedalboard
|
6
|
+
|
7
|
+
def initialize opts={}
|
8
|
+
@pin = opts.fetch(:pin) {}
|
9
|
+
@pedalboard = opts.fetch(:pedalboard) {}
|
10
|
+
@dino_component = opts.fetch(:dino_component) {}
|
11
|
+
end
|
12
|
+
|
13
|
+
private
|
14
|
+
def run_command command, *args
|
15
|
+
Commands.new(
|
16
|
+
pedalboard: pedalboard
|
17
|
+
).instance_exec *args, &command
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end; end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
require 'dino/components/base_component'
|
2
|
+
require 'dino/components/led'
|
3
|
+
|
4
|
+
require_relative 'base_component'
|
5
|
+
|
6
|
+
module Pedalboard; module Components
|
7
|
+
class Led < BaseComponent
|
8
|
+
def light_if condition
|
9
|
+
condition ? on : off
|
10
|
+
end
|
11
|
+
|
12
|
+
def off
|
13
|
+
dino_component.send :off
|
14
|
+
end
|
15
|
+
|
16
|
+
def on
|
17
|
+
dino_component.send :on
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
def dino_component
|
22
|
+
@dino_component ||= Dino::Components::Led.new(
|
23
|
+
pin: pin,
|
24
|
+
board: pedalboard.board
|
25
|
+
)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end; end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
require 'dino/components/base_component'
|
2
|
+
require 'dino/components/button'
|
3
|
+
|
4
|
+
require_relative 'base_component'
|
5
|
+
|
6
|
+
module Pedalboard; module Components
|
7
|
+
class Pedal < BaseComponent
|
8
|
+
LONG_TIME = 0.4
|
9
|
+
|
10
|
+
attr_reader :press, :long_press
|
11
|
+
|
12
|
+
def initialize opts={}
|
13
|
+
super opts
|
14
|
+
|
15
|
+
@press = opts.fetch(:press) { ->{} }
|
16
|
+
@long_press = opts.fetch(:long_press) { ->{} }
|
17
|
+
|
18
|
+
configure_dino_component
|
19
|
+
end
|
20
|
+
|
21
|
+
def configure_dino_component
|
22
|
+
dino_component.down do
|
23
|
+
begin
|
24
|
+
@start_time = Time.now
|
25
|
+
rescue Exception => e
|
26
|
+
puts e.message
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
dino_component.up do
|
31
|
+
begin
|
32
|
+
interval = Time.now - @start_time
|
33
|
+
if interval > LONG_TIME
|
34
|
+
run_command long_press
|
35
|
+
else
|
36
|
+
run_command press
|
37
|
+
end
|
38
|
+
rescue Exception => e
|
39
|
+
puts e.message
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
private
|
45
|
+
def dino_component
|
46
|
+
@dino_component ||= Dino::Components::Button.new(
|
47
|
+
pin: pin,
|
48
|
+
board: pedalboard.board
|
49
|
+
)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end; end
|
@@ -0,0 +1,78 @@
|
|
1
|
+
require 'dino/components/base_component'
|
2
|
+
require 'dino/components/sensor'
|
3
|
+
|
4
|
+
require_relative 'base_component'
|
5
|
+
|
6
|
+
module Pedalboard; module Components
|
7
|
+
class Pot < BaseComponent
|
8
|
+
TOLERANCE = 2
|
9
|
+
|
10
|
+
UPPER_LIMIT = 127
|
11
|
+
LOWER_LIMIT = 0
|
12
|
+
|
13
|
+
attr_reader :change, :inverted,
|
14
|
+
:lower_limit, :upper_limit,
|
15
|
+
:tolerance
|
16
|
+
|
17
|
+
attr_accessor :value
|
18
|
+
|
19
|
+
def initialize opts={}
|
20
|
+
super opts
|
21
|
+
|
22
|
+
@change = opts.fetch(:change) { ->(value) {} }
|
23
|
+
@lower_limit = opts.fetch(:lower_limit) { LOWER_LIMIT }
|
24
|
+
@upper_limit = opts.fetch(:upper_limit) { UPPER_LIMIT }
|
25
|
+
@tolerance = opts.fetch(:tolerance) { TOLERANCE }
|
26
|
+
@inverted = opts.fetch(:inverted) { false }
|
27
|
+
@value = lower_limit
|
28
|
+
|
29
|
+
configure_dino_component
|
30
|
+
end
|
31
|
+
|
32
|
+
private
|
33
|
+
def configure_dino_component
|
34
|
+
dino_component.when_data_received do |value|
|
35
|
+
begin
|
36
|
+
new_value = normalised(value)
|
37
|
+
if significant_change?(new_value)
|
38
|
+
@value = new_value
|
39
|
+
run_command(change, new_value)
|
40
|
+
end
|
41
|
+
rescue Exception => e
|
42
|
+
puts e.message
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def dino_component
|
48
|
+
@dino_component ||= Dino::Components::Sensor.new(
|
49
|
+
pin: pin,
|
50
|
+
board: pedalboard.board
|
51
|
+
)
|
52
|
+
end
|
53
|
+
|
54
|
+
def normalised received_value
|
55
|
+
normalised_value = (
|
56
|
+
(received_value.to_i / 1024.0) *
|
57
|
+
(upper_limit - lower_limit)
|
58
|
+
).to_i + lower_limit
|
59
|
+
normalised_value = upper_limit - normalised_value if inverted
|
60
|
+
normalised_value
|
61
|
+
end
|
62
|
+
|
63
|
+
def range_to_ignore
|
64
|
+
min = value - tolerance
|
65
|
+
max = value + tolerance
|
66
|
+
(min..max).to_a
|
67
|
+
end
|
68
|
+
|
69
|
+
def significant_change? new_value
|
70
|
+
if new_value != value
|
71
|
+
return true if new_value == lower_limit
|
72
|
+
return true if new_value == upper_limit
|
73
|
+
end
|
74
|
+
|
75
|
+
!range_to_ignore.include?(new_value)
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end; end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
require 'dino'
|
2
|
+
require 'micromidi'
|
3
|
+
|
4
|
+
module Pedalboard
|
5
|
+
class Device
|
6
|
+
|
7
|
+
attr_reader :components, :board, :midi_output, :midi_input
|
8
|
+
|
9
|
+
def initialize opts={}
|
10
|
+
@components = []
|
11
|
+
@connection = opts.fetch(:connection) { Dino::TxRx::Serial.new }
|
12
|
+
@board = opts.fetch(:board) { Dino::Board.new(connection) }
|
13
|
+
@midi_output = opts.fetch(:midi_output) { UniMIDI::Output.gets }
|
14
|
+
@midi_input = opts.fetch(:midi_input) { UniMIDI::Input.gets }
|
15
|
+
end
|
16
|
+
|
17
|
+
def add_component type, opts={}
|
18
|
+
opts[:pedalboard] = self
|
19
|
+
component = eval(component_class(type))
|
20
|
+
.new(opts)
|
21
|
+
components << component
|
22
|
+
component
|
23
|
+
end
|
24
|
+
|
25
|
+
private
|
26
|
+
attr_reader :connection
|
27
|
+
|
28
|
+
def component_class type
|
29
|
+
"Pedalboard::Components::#{type.capitalize}"
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module Pedalboard
|
2
|
+
class DSLParser
|
3
|
+
attr_reader :pedalboard
|
4
|
+
|
5
|
+
def initialize pedalboard
|
6
|
+
@pedalboard = pedalboard
|
7
|
+
end
|
8
|
+
|
9
|
+
def led *args
|
10
|
+
@pedalboard.add_component :led, *args
|
11
|
+
end
|
12
|
+
|
13
|
+
def pedal *args
|
14
|
+
@pedalboard.add_component :pedal, *args
|
15
|
+
end
|
16
|
+
|
17
|
+
def pot *args
|
18
|
+
@pedalboard.add_component :pot, *args
|
19
|
+
end
|
20
|
+
|
21
|
+
def board
|
22
|
+
self.pedalboard.board
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
data/pedalboard.gemspec
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
$:.push File.expand_path('../lib', __FILE__)
|
2
|
+
require 'pedalboard/version'
|
3
|
+
|
4
|
+
Gem::Specification.new do |s|
|
5
|
+
s.name = 'pedalboard'
|
6
|
+
s.version = Pedalboard.version
|
7
|
+
s.platform = Gem::Platform::RUBY
|
8
|
+
s.date = '2014-05-04'
|
9
|
+
s.summary = 'Easy Arduino MIDI pedalboard'
|
10
|
+
s.description = 'Quick and easy prototyping for Arduino-based MIDI pedalboards'
|
11
|
+
s.authors = ['Adam Phillips']
|
12
|
+
s.email = 'adam@29ways.co.uk'
|
13
|
+
s.homepage = 'https://github.com/adamphillips/pedalboard'
|
14
|
+
|
15
|
+
s.files = `git ls-files`.split("\n")
|
16
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
17
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
18
|
+
s.require_paths = ["lib"]
|
19
|
+
|
20
|
+
s.add_runtime_dependency 'dino'
|
21
|
+
s.add_runtime_dependency 'micromidi'
|
22
|
+
s.add_runtime_dependency 'mixlib-cli'
|
23
|
+
|
24
|
+
s.add_development_dependency 'rspec'
|
25
|
+
s.add_development_dependency 'pry'
|
26
|
+
s.add_development_dependency 'codeclimate-test-reporter'
|
27
|
+
end
|