/* This file is part of LED Pattern Editor. * * Copyright (C) 2010 Philipp Zabel * * LED Pattern Editor is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * LED Pattern Editor is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with LED Pattern Editor. If not, see . */ class LedPatternRX51 : LedPattern { public string led_map; public List engine1; public List engine2; public void parse (string line) { string[] key_value = line.split ("="); if (key_value.length != 2) { print ("pattern line does not contain '=': %s\n", line); return; } string[] p = key_value[1].split (";"); if (p.length != 6) { print ("pattern does not contain 6 components: %d\n", p.length); return; } if (p[4].length > 16*4 || p[5].length > 16*4) { print ("pattern too long!\n"); return; } name = key_value[0]; priority = p[0].to_int (); screen_on = p[1].to_int (); timeout = p[2].to_int (); led_map = p[3]; engine1 = parse_pattern (p[4]); engine2 = parse_pattern (p[5]); if (engine1.first ().data.code != 0x9d80) { print ("engine1 pattern doesn't start with refresh mux command\n"); } if (engine2.first ().data.code != 0x9d80) { print ("engine2 pattern doesn't start with refresh mux command\n"); } on_changed (); } private List parse_pattern (string pattern) { var list = new List (); var length = pattern.length; if (length % 4 != 0) return list; char *p = ((char*) pattern) + length - 4; while (p >= (char*) pattern) { var command = new LedCommandRX51.with_code ((uint16) ((string) p).to_ulong (null, 16)); command.changed.connect (on_changed); list.prepend (command); p[0] = '\0'; p -= 4; } return list; } public string dump () { return "%s=%d;%d;%d;%s;%s;%s".printf (name, priority, screen_on, timeout, led_map, dump_pattern (engine1), dump_pattern (engine2)); } private string dump_pattern (List list) { string result = ""; foreach (LedCommandRX51 command in list) { result += "%04x".printf (command.code); } return result; } public LedPatternRX51 copy () { var pattern = new LedPatternRX51 (); pattern.name = name.dup (); pattern.priority = priority; pattern.screen_on = screen_on; pattern.timeout = timeout; pattern.duration = duration; pattern.led_map = led_map; pattern.engine1 = deep_copy (pattern, engine1); pattern.engine2 = deep_copy (pattern, engine2); return pattern; } public List deep_copy (LedPatternRX51 pattern, List list) { var list2 = new List (); foreach (LedCommandRX51 command in list) { var command2 = command.copy (); command2.changed.connect (pattern.on_changed); list2.append (command2); } return list2; } public void replace_with (LedPatternRX51 pattern) { name = pattern.name; priority = pattern.priority; screen_on = pattern.screen_on; timeout = pattern.timeout; duration = pattern.duration; led_map = pattern.led_map; engine1 = deep_copy (this, pattern.engine1); engine2 = deep_copy (this, pattern.engine2); changed (); } void on_changed () { // calculate timing and level info double time = 0; int level = 0; foreach (LedCommandRX51 command in engine1) { command.time = time; time += command.duration; if (command.type == CommandType.SET_PWM) { level = command.level; } else { command.level = level; level += command.steps; } if (level < 0) level = 0; if (level > 255) level = 255; } duration = time; changed (); } } class LedCommandRX51 : LedCommand { public uint16 code; public LedCommandRX51 () { } public LedCommandRX51.with_code (uint16 _code) { code = _code; if ((code & 0x8000) == 0) { if (code == 0x0000) { type = CommandType.REPEAT; } else if ((code & 0x3e00) != 0) { type = CommandType.RAMP_WAIT; steps = code & 0xff; step_time = code >> 9; if ((code & 0x4000) == 0) step_time = (code >> 9) * 0.49; else { step_time = ((code & 0x3e00) >> 9) * 15.6; } duration = step_time * (steps + 1); if ((code & 0x100) != 0) steps = -steps; } else { type = CommandType.SET_PWM; level = code & 0xff; } } else { if (code == 0x9d80) type = CommandType.RESET_MUX; if (code == 0xc000) type = CommandType.STOP; //if (code == 0xe0??) // type = CommandType.TRIGGER_WAIT; } } public override void set_pwm (int _level) { code = 0x4000 | _level; base.set_pwm (_level); } public override void ramp_wait (double _step_time, int _steps) requires (_step_time >= 0.49) { int step_time; if (_step_time <= 31*0.49) { step_time = (int) ((_step_time + 0.001) / 0.49); code = (uint16) step_time << 9; _step_time = step_time * 0.49; } else if (_step_time <= 31*15.6) { step_time = (int) ((_step_time + 0.01) / 15.6); code = 0x4000 | (step_time << 9); _step_time = step_time * 15.6; } else { return; } if (_steps < 0) { code |= 0x100 | (-_steps); } else { code |= _steps; } base.ramp_wait (_step_time, _steps); } public LedCommandRX51 copy () { var command = new LedCommandRX51 (); command.type = type; command.time = time; command.step_time = step_time; command.duration = duration; command.level = level; command.steps = steps; command.code = code; return command; } }