1 module rivald.cycle;
2 
3 // 
4 // Rivald
5 // 
6 import rivald.error;
7 import rivald.util;
8 import rivald.values;
9 
10 // 
11 // Std
12 // 
13 import std.bitmanip : nativeToLittleEndian;
14 import std.exception : enforce;
15 
16 /// Point representation
17 struct Point
18 {
19     // color
20     ubyte red;
21     ubyte green;
22     ubyte blue;
23     // relative position in the cycle
24     ubyte pos;
25 }
26 
27 /// Cycle representation
28 class Cycle
29 {
30     private:
31     ubyte led = Led.LOGO;
32     ushort duration = 5000;
33     bool repeat = true;
34     ubyte trigger_buttons;
35     Point[] points; 
36 
37     public:
38 
39     /**
40      * Cycle constructor
41      *
42      * Params:
43      *      led =   Led ID (0 or 1)
44      */
45     this(ubyte led)
46     {
47         enforce!RivalError(led == Led.LOGO || led == Led.WHEEL, "Invalid Led ID.");
48 
49         this.led = led;
50     }
51 
52     /**
53      * Sets the points
54      *
55      * Params:
56      *      points =    Points in the cycle
57      */
58     void setPoints(Point[] points)
59     {
60         this.points = points;
61     }
62 
63     /**
64      * Sets the duration
65      *
66      * Params:
67      *      duration =  Duration of the cycle
68      */
69     void setDuration(ushort duration)
70     {
71         this.duration = duration;
72     }
73 
74     /**
75      * Sets the repeat bool
76      *
77      * Params:
78      *      repeat =    If cycle repeats
79      */
80     void setRepeat(bool repeat)
81     {
82         this.repeat = repeat;
83     }
84 
85     /**
86      * Sets the trigger buttons
87      *
88      * Params:
89      *      buttons =   Button representation
90      *
91      * https://github.com/FFY00/rival310-re/blob/master/5B.md
92      */
93     void setDuration(ubyte buttons)
94     {
95         this.trigger_buttons = buttons;
96     }
97 
98     /**
99      * Contructs the buffer
100      *
101      * Returns: Contructed buffer
102      *
103      * https://github.com/FFY00/rival310-re/blob/master/5B.md
104      */
105     ubyte[Size.LONG] getBuffer()
106     {
107         ubyte[Size.LONG] buf;
108 
109         buf[0] = Command.LED;
110         buf[2] = led;
111 
112         if(!repeat)
113             buf[19] = 1;
114 
115         buf[27] = cast(ubyte) points.length;
116 
117         bool first_point;
118         ubyte i;
119         ushort cycle_size;
120         CYCLE: foreach(point; points)
121         {
122             if(!first_point)
123             {
124                 buf[28] = point.red;
125                 buf[29] = point.green;
126                 buf[30] = point.blue;
127                 first_point = true;
128             }
129 
130             buf[31 + (i * 4)] = point.red;
131             buf[32 + (i * 4)] = point.green;
132             buf[33 + (i * 4)] = point.blue;
133             buf[34 + (i * 4)] = point.pos;
134 
135             cycle_size += point.pos;
136 
137             if(cycle_size >= 255)
138                 break CYCLE;
139 
140             i++;
141         }
142 
143         duration = cast(short) min_threshold(duration, buf[27] * 330);
144         ubyte[2] dur = nativeToLittleEndian(duration);
145         buf[3] = dur[0];
146         buf[4] = dur[1];
147 
148         return buf;
149     }
150 
151 }