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,63 @@
1
+ $tables = {}
2
+
3
+ class CreateLookup < Base
4
+ Arbol.add_mapped_class(
5
+ 'create_lookup',
6
+ CreateLookup,
7
+ nil
8
+ )
9
+
10
+ attr_accessor :identifier
11
+ attr_accessor :value
12
+
13
+ def initialize(params)
14
+ super(params)
15
+ @identifier = params[:identifier]
16
+ unless $tables.has_key?(@identifier)
17
+ $tables[@identifier] = params[:value]
18
+ @value = params[:value]
19
+ else
20
+ raise "duplicate table definition #{params[:name]}"
21
+ end
22
+ end
23
+
24
+ def param_keys
25
+ []
26
+ end
27
+
28
+ def arduino_code
29
+ []
30
+ end
31
+
32
+ def top_level_scope_code
33
+ [
34
+ "long #{@identifier}[#{@value.length}][3] = #{table_to_cplusplus_array(@value)};"
35
+ ]
36
+ end
37
+
38
+ def table_to_cplusplus_array(t)
39
+ "{#{t.map {|f| f.to_s.gsub(/\[/, '{').gsub(/\]/, '}') }.join(',')}}"
40
+ end
41
+ end
42
+
43
+
44
+ def resolve_lookup(val)
45
+ puts val
46
+ puts val.class
47
+ raise "table definition must be an array" unless val.class == Array
48
+ val.map do |v|
49
+ case
50
+ when [Integer, Float].include?(v.class)
51
+ then 3.times.map { scale_correctly(v) }
52
+ when v.class == Array then v.map { |i| scale_correctly(i) }
53
+ end
54
+ end
55
+ end
56
+
57
+ def create_table_ref(identifier, value)
58
+ h = ArbolHash.new
59
+ h[:type] = 'create_lookup'
60
+ h[:identifier] = identifier
61
+ h[:value] = resolve_lookup(value)
62
+ h
63
+ end
@@ -0,0 +1,48 @@
1
+ $refs = {}
2
+ $refs_frame_optimized = {}
3
+
4
+ class CreateRef < Base
5
+ Arbol.add_mapped_class('create_ref', CreateRef, nil)
6
+ attr_accessor :identifier
7
+ attr_accessor :value
8
+
9
+ def initialize(params)
10
+ super(params)
11
+ @identifier = params[:identifier]
12
+ resolve_frame_optimized
13
+ unless $refs.has_key?(@identifier)
14
+ $refs[@identifier] = @name
15
+ $refs_frame_optimized[@identifier] = @frame_optimized
16
+ else
17
+ raise "duplicate ref definition #{params[:name]}"
18
+ end
19
+ end
20
+
21
+ def param_keys
22
+ [:value]
23
+ end
24
+
25
+ def arduino_code
26
+ []
27
+ end
28
+
29
+ def top_level_scope_code
30
+ [
31
+ "long *#{@name} = #{@value.name};"
32
+ ]
33
+ end
34
+ end
35
+
36
+ def create_ref(identifier, value)
37
+ h = ArbolHash.new
38
+ if value.class == ArbolTable
39
+ h[:type] = 'create_lookup'
40
+ h[:identifier] = identifier
41
+ h[:value] = resolve_lookup(value.table)
42
+ else
43
+ h[:type] = 'create_ref'
44
+ h[:identifier] = identifier
45
+ h[:value] = resolve(value)
46
+ end
47
+ h
48
+ end
@@ -0,0 +1,73 @@
1
+ class Crossfade < Base
2
+ Arbol.add_mapped_class(
3
+ 'crossfade',
4
+ Crossfade,
5
+ %{void crossfade(long fader[3], long channel1[3], long channel2[3], long out[3]) {
6
+ out[0] = long_mult(INTEGER_SCALE - 1 - fader[0], channel1[0]) + long_mult(fader[0], channel2[0]);
7
+ out[1] = long_mult(INTEGER_SCALE - 1 - fader[1], channel1[1]) + long_mult(fader[1], channel2[1]);
8
+ out[2] = long_mult(INTEGER_SCALE - 1 - fader[2], channel1[2]) + long_mult(fader[2], channel2[2]);
9
+ }}
10
+ )
11
+
12
+ attr_accessor :fader
13
+ attr_accessor :channel1
14
+ attr_accessor :channel2
15
+
16
+ def param_keys
17
+ [:fader, :channel1, :channel2]
18
+ end
19
+
20
+ def arduino_code
21
+ unless @frame_optimized
22
+ [
23
+ "crossfade(#{@fader.name}, #{@channel1.name}, #{@channel2.name}, #{@name});"
24
+ ]
25
+ else
26
+ []
27
+ end
28
+ end
29
+
30
+ def cycle_level_arduino_code
31
+ if @frame_optimized
32
+ [
33
+ "crossfade(#{@fader.name}, #{@channel1.name}, #{@channel2.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 crossfade
51
+ %{--
52
+ ### crossfade(fader, channel1, channel2)
53
+
54
+ * **fader** - fade amount between channels
55
+ * **channel1** - channel1
56
+ * **channel2** - channel2
57
+
58
+ Returns a mix of channels 1 and 2 based on the fader amount between 0-~1.0.
59
+
60
+ }
61
+ end
62
+
63
+ end
64
+ end
65
+
66
+ def crossfade(fader, channel1, channel2)
67
+ h = ArbolHash.new
68
+ h[:type] = 'crossfade'
69
+ h[:fader] = resolve(fader)
70
+ h[:channel1] = resolve(channel1)
71
+ h[:channel2] = resolve(channel2)
72
+ h
73
+ end
@@ -0,0 +1,70 @@
1
+ class Divide < Base
2
+ Arbol.add_mapped_class(
3
+ 'divide',
4
+ Divide,
5
+ %{void divide(long numerator[3], long denominator[3], long out[3]) {
6
+ out[0] = long_div(numerator[0], denominator[0]);
7
+ out[1] = long_div(numerator[1], denominator[1]);
8
+ out[2] = long_div(numerator[2], denominator[2]);
9
+ }}
10
+ )
11
+
12
+ attr_accessor :numerator
13
+ attr_accessor :denominator
14
+
15
+ def param_keys
16
+ [:numerator, :denominator]
17
+ end
18
+
19
+ def arduino_code
20
+ unless @frame_optimized
21
+ [
22
+ "divide(#{@numerator.name}, #{@denominator.name}, #{@name});"
23
+ ]
24
+ else
25
+ []
26
+ end
27
+ end
28
+
29
+ def cycle_level_arduino_code
30
+ if @frame_optimized
31
+ [
32
+ "divide(#{@numerator.name}, #{@denominator.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 divide
50
+ %{--
51
+ ### divide(numerator, denominator)
52
+
53
+ * **numerator**
54
+ * **denominator**
55
+
56
+ Division. Also accepts the form `numerator / denominator`.
57
+
58
+ }
59
+ end
60
+
61
+ end
62
+ end
63
+
64
+ def divide(numerator, denominator)
65
+ h = ArbolHash.new
66
+ h[:type] = 'add'
67
+ h[:numerator] = resolve(numerator)
68
+ h[:denominator] = resolve(denominator)
69
+ h
70
+ end
@@ -0,0 +1,65 @@
1
+ class Feedback < Base
2
+ Arbol.add_mapped_class(
3
+ 'feedback',
4
+ Feedback,
5
+ %{void feedback(int pixel, long input[3], long feedback[3], long storage[][3], long out[3]) {
6
+ out[0] = max(input[0], storage[pixel][0]);
7
+ out[1] = max(input[1], storage[pixel][1]);
8
+ out[2] = max(input[2], storage[pixel][2]);
9
+ storage[pixel][0] = constrain(long_mult(out[0], feedback[0]), 0, INTEGER_SCALE);
10
+ storage[pixel][1] = constrain(long_mult(out[1], feedback[1]), 0, INTEGER_SCALE);
11
+ storage[pixel][2] = constrain(long_mult(out[2], feedback[2]), 0, INTEGER_SCALE);
12
+ }}
13
+ )
14
+
15
+ attr_accessor :input
16
+ attr_accessor :feedback
17
+
18
+ def initialize(params)
19
+ super(params)
20
+ @frame_optimized = false
21
+ end
22
+
23
+ def param_keys
24
+ [:input, :feedback]
25
+ end
26
+
27
+ def arduino_code
28
+ [
29
+ "feedback(i, #{@input.name}, #{@feedback.name}, #{@name}_storage, #{@name});"
30
+ ]
31
+ end
32
+
33
+ def top_level_scope_code
34
+ [
35
+ "long #{@name}[3];",
36
+ "long #{@name}_storage[PIXEL_COUNT][3];"
37
+ ]
38
+ end
39
+ end
40
+
41
+ module Arbol
42
+ class Documentation
43
+
44
+ def feedback
45
+ %{--
46
+ ### feedback(input, feedback)
47
+
48
+ * **input**
49
+ * **feedback**
50
+
51
+ Returns the greatest of the input or the feedback value.
52
+
53
+ }
54
+ end
55
+
56
+ end
57
+ end
58
+
59
+ def feedback(input, feedback)
60
+ h = ArbolHash.new
61
+ h[:type] = 'feedback'
62
+ h[:input] = resolve(input)
63
+ h[:feedback] = resolve(feedback)
64
+ h
65
+ end
@@ -0,0 +1,69 @@
1
+ class FeedbackOffset < Base
2
+ Arbol.add_mapped_class(
3
+ 'feedback_offset',
4
+ FeedbackOffset,
5
+ %{void feedback_offset(int pixel, int pixel_count, long input[3], long feedback[3], long offset[3], long storage[][3], long out[3]) {
6
+ out[0] = max(input[0], storage[(pixel + long_mult(offset[0], pixel_count)) % pixel_count][0]);
7
+ out[1] = max(input[1], storage[(pixel + long_mult(offset[1], pixel_count)) % pixel_count][1]);
8
+ out[2] = max(input[2], storage[(pixel + long_mult(offset[2], pixel_count)) % pixel_count][2]);
9
+ storage[pixel][0] = constrain(long_mult(out[0], feedback[0]), 0, INTEGER_SCALE);
10
+ storage[pixel][1] = constrain(long_mult(out[1], feedback[1]), 0, INTEGER_SCALE);
11
+ storage[pixel][2] = constrain(long_mult(out[2], feedback[2]), 0, INTEGER_SCALE);
12
+ }}
13
+ )
14
+
15
+ attr_accessor :input
16
+ attr_accessor :feedback
17
+ attr_accessor :offset
18
+
19
+ def initialize(params)
20
+ super(params)
21
+ @frame_optimized = false
22
+ end
23
+
24
+ def param_keys
25
+ [:input, :feedback, :offset]
26
+ end
27
+
28
+ def arduino_code
29
+ [
30
+ "feedback_offset(i, PIXEL_COUNT, #{@input.name}, #{@feedback.name}, #{@offset.name}, #{@name}_storage, #{@name});"
31
+ ]
32
+ end
33
+
34
+ def top_level_scope_code
35
+ [
36
+ "long #{@name}[3];",
37
+ "long #{@name}_storage[PIXEL_COUNT][3];"
38
+ ]
39
+ end
40
+ end
41
+
42
+ module Arbol
43
+ class Documentation
44
+
45
+ def feedback_offset
46
+ %{--
47
+ ### feedback\_offset(input, feedback, offset)
48
+
49
+ * **input**
50
+ * **feedback**
51
+ * **offset**
52
+
53
+ Returns the greatest of the input or the feedback value at the offset (0-~1.0)
54
+ from the current pixel.
55
+
56
+ }
57
+ end
58
+
59
+ end
60
+ end
61
+
62
+ def feedback_offset(input, feedback, offset)
63
+ h = ArbolHash.new
64
+ h[:type] = 'feedback_offset'
65
+ h[:input] = resolve(input)
66
+ h[:feedback] = resolve(feedback)
67
+ h[:offset] = resolve(offset)
68
+ h
69
+ end
@@ -0,0 +1,61 @@
1
+ class Gamma < Base
2
+ Arbol.add_mapped_class(
3
+ 'gamma',
4
+ Gamma,
5
+ %{long neopix_gamma[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 2, 2, 3, 4, 4, 5, 6, 7, 8, 9, 10, 12, 13, 15, 16, 18, 20, 22, 24, 26, 28, 31, 33, 36, 39, 42, 45, 48, 51, 55, 59, 62, 66, 71, 75, 79, 84, 89, 94, 99, 104, 110, 116, 122, 128, 134, 140, 147, 154, 161, 168, 176, 184, 192, 200, 208, 217, 225, 234, 244, 253, 263, 273, 283, 293, 304, 315, 326, 338, 349, 361, 373, 386, 398, 411, 425, 438, 452, 466, 480, 495, 510, 525, 541, 556, 572, 589, 605, 622, 640, 657, 675, 693, 712, 730, 750, 769, 789, 809, 829, 850, 871, 892, 914, 936, 959, 981, 1004, 1028, 1052, 1076, 1100, 1125, 1150, 1176, 1202, 1228, 1255, 1282, 1309, 1337, 1365, 1393, 1422, 1452, 1481, 1511, 1542, 1572, 1604, 1635, 1667, 1700, 1733, 1766, 1799, 1833, 1868, 1903, 1938, 1974, 2010, 2046, 2083, 2121, 2158, 2197, 2235, 2274, 2314, 2354, 2394, 2435, 2476, 2518, 2560, 2603, 2646, 2690, 2734, 2778, 2823, 2869, 2915, 2961, 3008, 3055, 3103, 3151, 3200, 3249, 3299, 3349, 3399, 3451, 3502, 3554, 3607, 3660, 3714, 3768, 3823, 3878, 3933, 3990, 4046, 4103, 4161, 4219, 4278, 4337, 4397, 4458, 4518, 4580, 4642, 4704, 4767, 4831, 4895, 4959, 5025, 5090, 5157, 5223, 5291, 5359, 5427, 5496, 5566, 5636, 5707, 5778, 5850, 5922, 5995, 6069, 6143, 6218, 6293, 6369, 6446, 6523, 6601, 6679, 6758, 6837, 6917, 6998, 7079, 7161, 7244, 7327, 7410, 7495, 7580, 7665, 7751, 7838, 7926, 8014, 8102};
6
+
7
+ long INTEGER_SCALE_MINUS_ONE = INTEGER_SCALE - 1;
8
+ void gamma(long input[3], long out[3]) {
9
+ out[0] = neopix_gamma[map(input[0], 0, INTEGER_SCALE_MINUS_ONE, 0, 255) ];
10
+ out[1] = neopix_gamma[map(input[1], 0, INTEGER_SCALE_MINUS_ONE, 0, 255) ];
11
+ out[2] = neopix_gamma[map(input[2], 0, INTEGER_SCALE_MINUS_ONE, 0, 255) ];
12
+ }}
13
+ )
14
+
15
+ attr_accessor :input
16
+
17
+ def initialize(params)
18
+ super(params)
19
+ @frame_optimized = false
20
+ end
21
+
22
+ def param_keys
23
+ [:input]
24
+ end
25
+
26
+ def arduino_code
27
+ [
28
+ "gamma(#{@input.name}, #{@name});"
29
+ ]
30
+ end
31
+
32
+ def top_level_scope_code
33
+ [
34
+ "long #{@name}[3];"
35
+ ]
36
+ end
37
+ end
38
+
39
+ module Arbol
40
+ class Documentation
41
+
42
+ def gamma
43
+ %{--
44
+ ### gamma(input)
45
+
46
+ * **input**
47
+
48
+ Returns gamma corrected input. This makes the colors look much better.
49
+
50
+ }
51
+ end
52
+
53
+ end
54
+ end
55
+
56
+ def gamma(input)
57
+ h = ArbolHash.new
58
+ h[:type] = 'gamma'
59
+ h[:input] = resolve(input)
60
+ h
61
+ end