arbol 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (42) hide show
  1. checksums.yaml +7 -0
  2. data/bin/arbol +25 -0
  3. data/lib/arbol.rb +45 -0
  4. data/lib/base.rb +397 -0
  5. data/lib/builder.rb +102 -0
  6. data/lib/documentation.rb +19 -0
  7. data/lib/dsl.rb +168 -0
  8. data/lib/functions/add.rb +70 -0
  9. data/lib/functions/add_constrain.rb +70 -0
  10. data/lib/functions/add_modulo.rb +70 -0
  11. data/lib/functions/analog_pin.rb +316 -0
  12. data/lib/functions/choose.rb +74 -0
  13. data/lib/functions/const.rb +63 -0
  14. data/lib/functions/create_lookup.rb +63 -0
  15. data/lib/functions/create_ref.rb +48 -0
  16. data/lib/functions/crossfade.rb +73 -0
  17. data/lib/functions/divide.rb +70 -0
  18. data/lib/functions/feedback.rb +65 -0
  19. data/lib/functions/feedback_offset.rb +69 -0
  20. data/lib/functions/gamma.rb +61 -0
  21. data/lib/functions/greater_than.rb +70 -0
  22. data/lib/functions/greater_than_equals.rb +70 -0
  23. data/lib/functions/lamp_phase.rb +39 -0
  24. data/lib/functions/less_than.rb +70 -0
  25. data/lib/functions/less_than_equals.rb +70 -0
  26. data/lib/functions/lfo_square.rb +68 -0
  27. data/lib/functions/lfo_triangle.rb +72 -0
  28. data/lib/functions/lookup.rb +86 -0
  29. data/lib/functions/max.rb +70 -0
  30. data/lib/functions/min.rb +70 -0
  31. data/lib/functions/minus.rb +70 -0
  32. data/lib/functions/modulo.rb +70 -0
  33. data/lib/functions/noise.rb +49 -0
  34. data/lib/functions/noise_pixel.rb +49 -0
  35. data/lib/functions/phasor.rb +96 -0
  36. data/lib/functions/ref.rb +34 -0
  37. data/lib/functions/scale.rb +71 -0
  38. data/lib/functions/table.rb +16 -0
  39. data/lib/functions/times.rb +70 -0
  40. data/lib/functions/triangle.rb +69 -0
  41. data/lib/templates/arduino_library.ino.erb +75 -0
  42. metadata +84 -0
@@ -0,0 +1,96 @@
1
+ class Phasor < Base
2
+ Arbol.add_mapped_class(
3
+ 'phasor',
4
+ Phasor,
5
+ %{void phasor(long mils, long cycle[3], long out[3]) {
6
+ out[0] = long_div((mils % cycle[0]), cycle[0]);
7
+ out[1] = long_div((mils % cycle[1]), cycle[1]);
8
+ out[2] = long_div((mils % cycle[2]), cycle[2]);
9
+ }}
10
+ )
11
+ attr_accessor :cycles
12
+
13
+ def param_keys
14
+ [:cycles]
15
+ end
16
+
17
+ def arduino_code
18
+ unless @frame_optimized
19
+ [
20
+ "phasor(mils, #{@cycles.name}, #{@name});"
21
+ ]
22
+ else
23
+ []
24
+ end
25
+ end
26
+
27
+ def cycle_level_arduino_code
28
+ if @frame_optimized
29
+ [
30
+ "phasor(mils, #{@cycles.name}, #{@name});"
31
+ ]
32
+ else
33
+ []
34
+ end
35
+ end
36
+
37
+ def top_level_scope_code
38
+ [
39
+ "long #{@name}[3];"
40
+ ]
41
+ end
42
+ end
43
+
44
+ module Arbol
45
+ class Documentation
46
+
47
+ def phasor
48
+ %{--
49
+ ### phasor(cycle_ms)
50
+
51
+ * **cycle_ms**
52
+
53
+ Outputs a ramp wave from 0-~1.0 over a period of cycle_ms milliseconds.
54
+
55
+ `phasor` is very important because it highlights a key way to bring motion into
56
+ the system. There are many ways of using phasor.
57
+
58
+ ```
59
+ # go from 0-~1.0 over a period of 10 seconds:
60
+ phasor(10000)
61
+
62
+ # each of the three channels goes from 0-~1.0 at different millisecond intervals:
63
+ phasor([1000, 1100, 1200])
64
+
65
+ # phasor is input into a triangle function, which then creates a triangle
66
+ # wave that goes from 0-~1.0-0 over a period of 5 seconds specified
67
+ # to the phasor
68
+ tri = triangle(phasor(5000))
69
+
70
+ # multiple two triangles together to to get a pointy triangle
71
+ tri_squared = tri * tri
72
+
73
+ # using `lamp_phase` function in conjunction with `add_constrain` you can
74
+ # create motion in the lamps.
75
+
76
+ strip(
77
+ 512, # 512 pixels
78
+ 0, # attached to pin 0
79
+ add_constrain(
80
+ lamp_phase,
81
+ phasor([1000, 1200, 1300])
82
+ )
83
+ ```
84
+
85
+ }
86
+ end
87
+
88
+ end
89
+ end
90
+
91
+ def phasor(cycles)
92
+ h = ArbolHash.new
93
+ h[:type] = 'phasor'
94
+ h[:cycles] = resolve(cycles)
95
+ h
96
+ end
@@ -0,0 +1,34 @@
1
+ class Ref < Base
2
+ Arbol.add_mapped_class('ref', Ref, nil)
3
+ attr_accessor :identifier
4
+ attr_accessor :ref_name
5
+
6
+ def initialize(params)
7
+ super(params)
8
+ @identifier = params[:identifier]
9
+ if $refs.has_key?(@identifier)
10
+ @ref_name = $refs[@identifier]
11
+ @frame_optimized = $refs_frame_optimized[@identifier]
12
+ else
13
+ raise "non-existant ref #{@identifier}"
14
+ end
15
+ end
16
+
17
+ def arduino_code
18
+ [
19
+ ]
20
+ end
21
+
22
+ def top_level_scope_code
23
+ [
24
+ "long *#{@name} = #{@ref_name};"
25
+ ]
26
+ end
27
+ end
28
+
29
+ def ref(identifier)
30
+ h = ArbolHash.new
31
+ h[:type] = 'ref'
32
+ h[:identifier] = identifier
33
+ h
34
+ end
@@ -0,0 +1,71 @@
1
+ class Scale < Base
2
+ Arbol.add_mapped_class(
3
+ 'scale',
4
+ Scale,
5
+ %{void scale(long input[3], long lo_in[3], long hi_in[3], long lo_out[3], long hi_out[3], long out[3]) {
6
+ out[0] = map(input[0], lo_in[0], hi_in[0], lo_out[0], hi_out[0]);
7
+ out[1] = map(input[1], lo_in[1], hi_in[1], lo_out[1], hi_out[1]);
8
+ out[2] = map(input[2], lo_in[2], hi_in[2], lo_out[2], hi_out[2]);
9
+ }}
10
+ )
11
+
12
+ attr_accessor :input
13
+ attr_accessor :lo_in
14
+ attr_accessor :hi_in
15
+ attr_accessor :lo_out
16
+ attr_accessor :hi_out
17
+
18
+ def param_keys
19
+ [:input, :lo_in, :hi_in, :lo_out, :hi_out]
20
+ end
21
+
22
+ def arduino_code
23
+ unless @frame_optimized
24
+ [
25
+ "scale(#{@input.name}, #{@lo_in.name}, #{@hi_in.name}, #{@lo_out.name}, #{@hi_out.name}, #{@name});"
26
+ ]
27
+ else
28
+ []
29
+ end
30
+ end
31
+
32
+ def cycle_level_arduino_code
33
+ if @frame_optimized
34
+ [
35
+ "scale(#{@input.name}, #{@lo_in.name}, #{@hi_in.name}, #{@lo_out.name}, #{@hi_out.name}, #{@name});"
36
+ ]
37
+ else
38
+ []
39
+ end
40
+ end
41
+
42
+ def top_level_scope_code
43
+ [
44
+ "long #{@name}[3];"
45
+ ]
46
+ end
47
+ end
48
+
49
+ module Arbol
50
+ class Documentation
51
+
52
+ def scale
53
+ %{--
54
+ ### scale needs doc
55
+
56
+ }
57
+ end
58
+
59
+ end
60
+ end
61
+
62
+ def scale(input, lo_in, hi_in, lo_out, hi_out)
63
+ h = ArbolHash.new
64
+ h[:type] = 'scale'
65
+ h[:input] = resolve(input)
66
+ h[:lo_in] = resolve(lo_in)
67
+ h[:hi_in] = resolve(hi_in)
68
+ h[:lo_out] = resolve(lo_out)
69
+ h[:hi_out] = resolve(hi_out)
70
+ h
71
+ end
@@ -0,0 +1,16 @@
1
+ class ArbolTable
2
+ attr_accessor :table
3
+
4
+ def initialize(tbl)
5
+ @table = tbl
6
+ end
7
+ end
8
+
9
+
10
+ # really this is just a pass through for arrays
11
+ # used in lookup table creation
12
+ def table(contents)
13
+ if contents.class == Array
14
+ ArbolTable.new(contents)
15
+ end
16
+ end
@@ -0,0 +1,70 @@
1
+ class Times < Base
2
+ Arbol.add_mapped_class(
3
+ 'times',
4
+ Times,
5
+ %{void times(long op1[3], long op2[3], long out[3]) {
6
+ out[0] = long_mult(op1[0], op2[0]);
7
+ out[1] = long_mult(op1[1], op2[1]);
8
+ out[2] = long_mult(op1[2], op2[2]);
9
+ }}
10
+ )
11
+
12
+ attr_accessor :op1
13
+ attr_accessor :op2
14
+
15
+ def param_keys
16
+ [:op1, :op2]
17
+ end
18
+
19
+ def arduino_code
20
+ unless @frame_optimized
21
+ [
22
+ "times(#{@op1.name}, #{@op2.name}, #{@name});"
23
+ ]
24
+ else
25
+ []
26
+ end
27
+ end
28
+
29
+ def cycle_level_arduino_code
30
+ if @frame_optimized
31
+ [
32
+ "times(#{@op1.name}, #{@op2.name}, #{@name});"
33
+ ]
34
+ else
35
+ []
36
+ end
37
+ end
38
+
39
+ def top_level_scope_code
40
+ [
41
+ "long #{@name}[3];",
42
+ ]
43
+ end
44
+ end
45
+
46
+ module Arbol
47
+ class Documentation
48
+
49
+ def times
50
+ %{--
51
+ ### times(operator1, operator2)
52
+
53
+ * **operator1**
54
+ * **operator2**
55
+
56
+ Multiplication of the two operators. Can also be used with the form `operator1 * operator2`.
57
+
58
+ }
59
+ end
60
+
61
+ end
62
+ end
63
+
64
+ def times(op1, op2)
65
+ h = ArbolHash.new
66
+ h[:type] = 'times'
67
+ h[:op1] = resolve(op1)
68
+ h[:op2] = resolve(op2)
69
+ h
70
+ end
@@ -0,0 +1,69 @@
1
+ class PhaseTriangle < Base
2
+ Arbol.add_mapped_class(
3
+ 'triangle',
4
+ PhaseTriangle,
5
+ %{//long twice_int_scale_vec[3] = {long(INTEGER_SCALE * 2), long(INTEGER_SCALE * 2), long(INTEGER_SCALE * 2)};
6
+ void triangle(long mils, long phase[3], long out[3]) {
7
+ long times_result[3];
8
+ times(phase, twice_int_scale_vec, times_result);
9
+ if(times_result[0] > INTEGER_SCALE) { out[0] = (twice_int_scale_vec[0] - times_result[0]); } else { out[0] = times_result[0]; }
10
+ if(times_result[1] > INTEGER_SCALE) { out[1] = (twice_int_scale_vec[1] - times_result[1]); } else { out[1] = times_result[1]; }
11
+ if(times_result[2] > INTEGER_SCALE) { out[2] = (twice_int_scale_vec[2] - times_result[2]); } else { out[2] = times_result[2]; }
12
+ }}
13
+ )
14
+ attr_accessor :phase
15
+
16
+ def param_keys
17
+ [:phase]
18
+ end
19
+
20
+ def arduino_code
21
+ unless @frame_optimized
22
+ [
23
+ "triangle(mils, #{@phase.name}, #{@name});"
24
+ ]
25
+ else
26
+ []
27
+ end
28
+ end
29
+
30
+ def cycle_level_arduino_code
31
+ if @frame_optimized
32
+ [
33
+ "triangle(mils, #{@phase.name}, #{@name});"
34
+ ]
35
+ else
36
+ []
37
+ end
38
+ end
39
+
40
+ def top_level_scope_code
41
+ [
42
+ "long #{@name}[3];",
43
+ ]
44
+ end
45
+ end
46
+
47
+ module Arbol
48
+ class Documentation
49
+
50
+ def triangle
51
+ %{--
52
+ ### triangle(phase)
53
+
54
+ * **phase**
55
+
56
+ `phase` input 0.0-1.0 input is transformed into a triangle.
57
+
58
+ }
59
+ end
60
+
61
+ end
62
+ end
63
+
64
+ def triangle(phase)
65
+ h = ArbolHash.new
66
+ h[:type] = 'triangle'
67
+ h[:phase] = resolve(phase)
68
+ h
69
+ end
@@ -0,0 +1,75 @@
1
+ #include <malloc.h>
2
+ #include <Thread.h>
3
+ #include <Adafruit_NeoPixel_ZeroDMA.h>
4
+
5
+ #define INTEGER_SCALE <%= integer_scale %>
6
+ #define PIXEL_COUNT <%= pixels %>
7
+
8
+ long long_div(long numerator, long denominator)
9
+ {
10
+ return (numerator * INTEGER_SCALE) / denominator;
11
+ }
12
+
13
+ long long_mult(long op1, long op2)
14
+ {
15
+ return op1 * op2 / INTEGER_SCALE;
16
+ }
17
+
18
+ byte byte_mult(byte op1, byte op2)
19
+ {
20
+ return (byte)((uint16_t)op1 * (uint16_t)op2 / (uint16_t)INTEGER_SCALE);
21
+ }
22
+
23
+ int neoPixelPin = <%= pin %>;
24
+ int pixelCount = PIXEL_COUNT;
25
+
26
+
27
+ <%= code %>
28
+
29
+ //END OF ARBOL LIBRARY
30
+
31
+ // Instatiate the NeoPixel from the library
32
+ Adafruit_NeoPixel_ZeroDMA strip = Adafruit_NeoPixel_ZeroDMA(pixelCount, neoPixelPin, NEO_GRB + NEO_KHZ800);
33
+
34
+ Thread calculate_strip_thread = Thread();
35
+
36
+ void setup() {
37
+ analogReadResolution(12);
38
+
39
+ calculate_strip_thread.setInterval(33);
40
+ calculate_strip_thread.onRun(calculate_strip);
41
+ strip.begin();
42
+ }
43
+
44
+ void loop() {
45
+ if(calculate_strip_thread.shouldRun()) calculate_strip_thread.run();
46
+ }
47
+
48
+ // beginning of top level scope definition
49
+
50
+ <%= tls %>
51
+
52
+ // end of top level scope definition
53
+
54
+ void calculate_strip() {
55
+ long mils = millis();
56
+ for (int i=0; i < pixelCount; i++) {
57
+ long this_phase = long_div(i, pixelCount - 1);
58
+ if(i == 0) {
59
+ // beginning of code that executes once per frame
60
+
61
+ <%= cycle %>
62
+
63
+ //
64
+ }
65
+ // beginning of code that executes for every pixel
66
+
67
+ <%= body %>
68
+
69
+ // end of generated code
70
+ }
71
+ strip.show();
72
+ }
73
+
74
+
75
+
metadata ADDED
@@ -0,0 +1,84 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: arbol
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.2
5
+ platform: ruby
6
+ authors:
7
+ - jeremy winters
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2018-07-07 00:00:00.000000000 Z
12
+ dependencies: []
13
+ description: define DSP-like function chains for your lights
14
+ email: jeremyranierwinters@gmail.com
15
+ executables:
16
+ - arbol
17
+ extensions: []
18
+ extra_rdoc_files: []
19
+ files:
20
+ - bin/arbol
21
+ - lib/arbol.rb
22
+ - lib/base.rb
23
+ - lib/builder.rb
24
+ - lib/documentation.rb
25
+ - lib/dsl.rb
26
+ - lib/functions/add.rb
27
+ - lib/functions/add_constrain.rb
28
+ - lib/functions/add_modulo.rb
29
+ - lib/functions/analog_pin.rb
30
+ - lib/functions/choose.rb
31
+ - lib/functions/const.rb
32
+ - lib/functions/create_lookup.rb
33
+ - lib/functions/create_ref.rb
34
+ - lib/functions/crossfade.rb
35
+ - lib/functions/divide.rb
36
+ - lib/functions/feedback.rb
37
+ - lib/functions/feedback_offset.rb
38
+ - lib/functions/gamma.rb
39
+ - lib/functions/greater_than.rb
40
+ - lib/functions/greater_than_equals.rb
41
+ - lib/functions/lamp_phase.rb
42
+ - lib/functions/less_than.rb
43
+ - lib/functions/less_than_equals.rb
44
+ - lib/functions/lfo_square.rb
45
+ - lib/functions/lfo_triangle.rb
46
+ - lib/functions/lookup.rb
47
+ - lib/functions/max.rb
48
+ - lib/functions/min.rb
49
+ - lib/functions/minus.rb
50
+ - lib/functions/modulo.rb
51
+ - lib/functions/noise.rb
52
+ - lib/functions/noise_pixel.rb
53
+ - lib/functions/phasor.rb
54
+ - lib/functions/ref.rb
55
+ - lib/functions/scale.rb
56
+ - lib/functions/table.rb
57
+ - lib/functions/times.rb
58
+ - lib/functions/triangle.rb
59
+ - lib/templates/arduino_library.ino.erb
60
+ homepage: https://www.github.com
61
+ licenses:
62
+ - MIT
63
+ metadata: {}
64
+ post_install_message:
65
+ rdoc_options: []
66
+ require_paths:
67
+ - lib
68
+ required_ruby_version: !ruby/object:Gem::Requirement
69
+ requirements:
70
+ - - ">="
71
+ - !ruby/object:Gem::Version
72
+ version: '2.4'
73
+ required_rubygems_version: !ruby/object:Gem::Requirement
74
+ requirements:
75
+ - - ">="
76
+ - !ruby/object:Gem::Version
77
+ version: '0'
78
+ requirements: []
79
+ rubyforge_project:
80
+ rubygems_version: 2.6.13
81
+ signing_key:
82
+ specification_version: 4
83
+ summary: functional streams for neopixel strips
84
+ test_files: []