1 /* This file is part of LED Pattern Editor.
3 * Copyright (C) 2010 Philipp Zabel
5 * LED Pattern Editor is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
10 * LED Pattern Editor is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with LED Pattern Editor. If not, see <http://www.gnu.org/licenses/>.
19 class LedPatternRX44 : LedPattern {
20 public List<LedCommandRX44> engine_r;
21 public List<LedCommandRX44> engine_g;
22 public List<LedCommandRX44> engine_b;
24 public override bool parse (string line) {
25 string[] key_value = line.split ("=");
27 if (key_value.length != 2) {
28 print ("pattern line does not contain '=': %s\n", line);
32 string[] p = key_value[1].split (";");
34 print ("pattern does not contain 6 components: %d\n", p.length);
38 if (p[3].length > 16*4 || p[4].length > 16*4 || p[5].length > 16*4) {
39 print ("pattern too long!\n");
44 priority = p[0].to_int ();
45 screen_on = p[1].to_int ();
46 timeout = p[2].to_int ();
47 engine_r = parse_pattern (p[3]);
48 engine_g = parse_pattern (p[4]);
49 engine_b = parse_pattern (p[5]);
55 private List<LedCommandRX44> parse_pattern (string pattern) {
56 var list = new List<LedCommandRX44> ();
57 var length = pattern.length;
62 char *p = ((char*) pattern) + length - 4;
63 while (p >= (char*) pattern) {
64 var command = new LedCommandRX44.with_code ((uint16) ((string) p).to_ulong (null, 16));
65 command.changed.connect (on_changed);
66 list.prepend (command);
74 public override string dump () {
75 return "%s=%d;%d;%d;%s;%s;%s".printf (name, priority, screen_on, timeout,
76 dump_pattern (engine_r), dump_pattern (engine_g), dump_pattern (engine_b));
79 private string dump_pattern (List<LedCommandRX44> list) {
81 foreach (LedCommandRX44 command in list) {
82 result += "%04x".printf (command.code);
87 public LedPatternRX44 copy () {
88 var pattern = new LedPatternRX44 ();
90 pattern.name = name.dup ();
91 pattern.priority = priority;
92 pattern.screen_on = screen_on;
93 pattern.timeout = timeout;
95 pattern.duration = duration;
97 pattern.engine_r = deep_copy (pattern, engine_r);
98 pattern.engine_g = deep_copy (pattern, engine_g);
99 pattern.engine_b = deep_copy (pattern, engine_b);
104 public List<LedCommandRX44> deep_copy (LedPatternRX44 pattern, List<LedCommandRX44> list) {
105 var list2 = new List<LedCommandRX44> ();
107 foreach (LedCommandRX44 command in list) {
108 var command2 = command.copy ();
109 command2.changed.connect (pattern.on_changed);
110 list2.append (command2);
116 public void replace_with (LedPatternRX44 pattern) {
118 priority = pattern.priority;
119 screen_on = pattern.screen_on;
120 timeout = pattern.timeout;
122 duration = pattern.duration;
124 engine_r = deep_copy (this, pattern.engine_r);
125 engine_g = deep_copy (this, pattern.engine_g);
126 engine_b = deep_copy (this, pattern.engine_b);
131 public void on_changed () {
132 bool unresolved = calculate_timing ();
134 unresolved = calculate_timing ();
136 Hildon.Banner.show_information (null, null, "Timing unresolved");
140 private bool calculate_timing () {
141 bool unresolved = false;
142 // Calculate timing and level info for red engine
145 foreach (LedCommandRX44 command in engine_r) {
147 if (command.type == CommandType.SET_PWM) {
148 level = command.level;
150 command.level = level;
151 level += command.steps;
153 if (command.type == CommandType.TRIGGER &&
154 (command.code & 0x0180) != 0) {
155 command.duration = wait_for_trigger (time, engine_g);
156 if (command.duration == 0)
158 command.duration += 16 * LedCommandRX44.CYCLE_TIME_MS;
160 time += command.duration;
167 // Calculate timing and level info for green engine
170 foreach (LedCommandRX44 command in engine_g) {
172 if (command.type == CommandType.SET_PWM) {
173 level = command.level;
175 command.level = level;
176 level += command.steps;
178 if (command.type == CommandType.TRIGGER &&
179 (command.code & 0x0180) != 0) {
180 command.duration = wait_for_trigger (time, engine_r);
181 if (command.duration == 0)
183 command.duration += 16 * LedCommandRX44.CYCLE_TIME_MS;
185 time += command.duration;
196 double wait_for_trigger (double time, List<LedCommandRX44> engine) {
199 foreach (LedCommandRX44 command in engine) {
200 duration = command.time + command.duration;
201 if (command.type == CommandType.TRIGGER &&
202 (command.code & 0x0006) != 0 && command.time > time) {
203 return command.time - time;
205 if (command.type == CommandType.GO_TO_START) {
210 if (repeat) foreach (LedCommandRX44 command in engine) {
211 if (command.type == CommandType.TRIGGER &&
212 (command.code & 0x0006) != 0 && (duration + command.time) > time) {
213 return duration + command.time - time;
220 class LedCommandRX44 : LedCommand {
221 internal const double CYCLE_TIME_MS = 1000.0 / 32768.0;
225 public LedCommandRX44 () {
228 public LedCommandRX44.with_code (uint16 _code) {
230 duration = 16 * CYCLE_TIME_MS;
231 if ((code & 0x8000) == 0) {
232 if (code == 0x0000) {
233 type = CommandType.GO_TO_START;
234 } else if ((code & 0x3e00) != 0) {
235 type = CommandType.RAMP_WAIT;
237 step_time = code >> 8;
238 if ((code & 0x4000) == 0)
239 step_time = (code >> 9) * 16 * CYCLE_TIME_MS;
241 step_time = ((code & 0x3e00) >> 9) * 512 * CYCLE_TIME_MS;
243 duration = step_time * (steps + 1);
244 if ((code & 0x80) != 0)
247 type = CommandType.SET_PWM;
251 if ((code & ~0x1f8f) == 0xa000) {
252 type = CommandType.BRANCH;
253 // 0x1f80: (loop count - 1) << 7
254 // 0x000f: step number
255 } else if ((code & ~0x1800) == 0xc000) {
256 type = CommandType.END;
258 if ((code & 0x0800) != 0) // Reset
260 } else if ((code & ~ 0x13fe) == 0xe000) {
261 type = CommandType.TRIGGER;
263 // 0x0380: wait B G R
270 public override void set_pwm (int _level) {
271 code = 0x4000 | _level;
272 base.set_pwm (_level);
275 public override void ramp_wait (double _step_time, int _steps) requires (_step_time >= (16 * CYCLE_TIME_MS)) {
277 if (_step_time < 32 * (16 * CYCLE_TIME_MS)) {
278 step_time = (int) ((_step_time + 0.001) / (16 * CYCLE_TIME_MS));
279 code = (uint16) step_time << 8;
280 _step_time = step_time * (16 * CYCLE_TIME_MS);
281 } else if (_step_time < 32*(512 * CYCLE_TIME_MS)) {
282 step_time = (int) ((_step_time + 0.001) / (512 * CYCLE_TIME_MS));
283 code = 0x4000 | (step_time << 8);
284 _step_time = step_time * (512 * CYCLE_TIME_MS);
289 code |= 0x80 | (-_steps);
293 base.ramp_wait (_step_time, _steps);
296 public override void go_to_start () {
301 public override void end (bool reset) {
308 public LedCommandRX44 copy () {
309 var command = new LedCommandRX44 ();
313 command.step_time = step_time;
314 command.duration = duration;
315 command.level = level;
316 command.steps = steps;