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,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