arbol 0.0.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.
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: []