class LedCommandWidget : Gtk.HBox {
private const double CYCLE_TIME_MS = 1000.0 / 32768.0;
- LedCommand command;
+ LedPatternRX51 pattern;
+ unowned List<LedCommandRX51> engine;
+ LedCommandRX51 command;
- public LedCommandWidget (LedCommand _command) {
+ public LedCommandWidget (LedPatternRX51 _pattern, List<LedCommandRX51> _engine,
+ LedCommandRX51 _command) {
homogeneous = true;
+ pattern = _pattern;
+ engine = _engine;
command = _command;
- string text = "";
+ var button = new Hildon.Button (Hildon.SizeType.FINGER_HEIGHT,
+ Hildon.ButtonArrangement.VERTICAL);
+ button.set_style (Hildon.ButtonStyle.PICKER);
+ button.set_alignment (0, 0.5f, 0, 0.5f);
+
switch (command.type) {
case CommandType.UNKNOWN:
- LedCommandRX51 cmd = command as LedCommandRX51;
- if (cmd != null)
- text = "??? (0x%04x)".printf (cmd.code);
- else
- text = "???";
+ button.set_title ("???");
+ button.set_value ("0x%04x".printf (command.code));
+ button.set_sensitive (false);
break;
case CommandType.RAMP_WAIT:
- text = "Ramp / Wait";
+ button.set_title ((command.steps != 0) ? "Ramp" : "Wait");
+ button.set_value ((command.steps != 0) ?
+ "%+d steps, %.2f ms each".printf (command.steps,
+ command.step_time) :
+ "%.2f ms".printf (command.duration));
+ button.clicked.connect (on_ramp_wait_clicked);
break;
case CommandType.SET_PWM:
- text = "Set PWM";
+ button.set_title ("Set PWM");
+ button.set_value ("Level = %d".printf (command.level));
+ button.clicked.connect (on_set_pwm_clicked);
break;
case CommandType.RESET_MUX:
- text = "Reset Mux";
+ button.set_title ("Reset Mux");
break;
case CommandType.GO_TO_START:
- text = "Go To Start";
+ button.set_title ("Go To Start");
+ button.set_value ("");
+ button.clicked.connect (on_end_or_go_to_start_clicked);
break;
case CommandType.BRANCH:
- text = "Branch";
+ button.set_title ("Branch");
+ button.set_value ("0x%04x".printf (command.code));
+ button.set_sensitive (false);
break;
case CommandType.END:
- text = "End";
+ button.set_title ("End");
+ button.set_value ((command.steps == -255) ? "Reset" : "Hold");
+ button.clicked.connect (on_end_or_go_to_start_clicked);
break;
case CommandType.TRIGGER:
- text = "Trigger";
+ button.set_title ("Trigger");
+ string text = "";
+ if (0x0100 in command.code)
+ text += "wait 2 ";
+ if (0x0004 in command.code)
+ text += "set 2 ";
+ if (0x0080 in command.code)
+ text += "wait 1 ";
+ if (0x0002 in command.code)
+ text += "set 1 ";
+ if ((command.code & ~0xe186) != 0) {
+ text = "Unsupported: 0x%04x".printf (command.code);
+ button.set_sensitive (false);
+ }
+ button.set_value (text);
+ button.clicked.connect (on_trigger_clicked);
break;
}
+ pack_start (button, true, true, 0);
+ }
- var label = new Gtk.Label (text);
- label.set_alignment (0.0f, 0.5f);
- pack_start (label, true, true, 0);
+ private void on_ramp_wait_clicked (Gtk.Button source) {
+ double old_step_time = command.step_time;
+ int old_steps = command.steps;
+ var dialog = new Gtk.Dialog ();
+ dialog.set_title ("Ramp / Wait");
- switch (command.type) {
- case CommandType.RAMP_WAIT:
- var selector = new Hildon.TouchSelector.text ();
- for (int i = 1; i <= 31; i++)
- selector.append_text ("%.2f ms".printf (i * (16 * CYCLE_TIME_MS)));
- for (int i = 1; i <= 31; i++)
- selector.append_text ("%.1f ms".printf (i * (512 * CYCLE_TIME_MS)));
- var picker = new Hildon.PickerButton (Hildon.SizeType.FINGER_HEIGHT,
- Hildon.ButtonArrangement.VERTICAL);
- picker.set_title ("Step time");
- picker.set_selector (selector);
- int j;
- if (command.step_time <= 31*(16 * CYCLE_TIME_MS))
- j = (int) ((command.step_time + 0.001) / (16 * CYCLE_TIME_MS)) - 1;
+ var content = (Gtk.VBox) dialog.get_content_area ();
+
+ var lpv = new LedPatternView (pattern);
+ lpv.set_size_request (-1, 70);
+ content.pack_start (lpv, true, true, 0);
+
+ var scale1 = new Gtk.HScale.with_range (1, 62, 1);
+ int v = (int) (command.step_time / 16 / CYCLE_TIME_MS);
+ if (v > 62)
+ v /= 32;
+ scale1.set_value (v);
+ scale1.format_value.connect ((v) => {
+ if (v < 32)
+ return "%.2f ms".printf (v * 16 * CYCLE_TIME_MS);
else
- j = (int) ((command.step_time + 0.01) / (512 * CYCLE_TIME_MS)) + 30;
- picker.set_active (j);
- picker.value_changed.connect ((s) => {
- double step_time;
- int i = s.get_active ();
- if (i < 31)
- step_time = (i + 1) * (16 * CYCLE_TIME_MS);
- else
- step_time = (i - 30) * (512 * CYCLE_TIME_MS);
- command.ramp_wait (step_time, command.steps);
- });
- pack_start (picker, true, true, 0);
-
- selector = new Hildon.TouchSelector.text ();
- for (int i = -255; i < 256; i++)
- selector.append_text ("%+d".printf (i));
- picker = new Hildon.PickerButton (Hildon.SizeType.FINGER_HEIGHT,
- Hildon.ButtonArrangement.VERTICAL);
- picker.set_title ("Steps");
- picker.set_selector (selector);
- picker.set_active (command.steps + 255);
- picker.value_changed.connect ((s) => {
- int steps = s.get_active () - 255;
- command.ramp_wait (command.step_time, steps);
- });
- pack_start (picker, true, true, 0);
- break;
- case CommandType.SET_PWM:
- label = new Gtk.Label ("");
- pack_start (label, true, true, 0);
- var selector = new Hildon.TouchSelector.text ();
- for (int i = 0; i < 256; i++)
- selector.append_text ("%d".printf (i));
- var picker = new Hildon.PickerButton (Hildon.SizeType.FINGER_HEIGHT,
- Hildon.ButtonArrangement.VERTICAL);
- picker.set_title ("Level");
- picker.set_selector (selector);
- picker.set_active (command.level);
- picker.value_changed.connect ((s) => {
- int level = s.get_active ();
- command.set_pwm (level);
- });
- pack_start (picker, true, true, 0);
- break;
- case CommandType.END:
- var check = new Hildon.CheckButton (Hildon.SizeType.FINGER_HEIGHT);
- check.set_label ("Reset");
- check.set_active (command.steps == -255);
- check.toggled.connect ((s) => {
- command.steps = s.get_active () ? -255 : 0;
- command.changed ();
- });
- pack_start (check, true, true, 0);
- label = new Gtk.Label ("");
- pack_start (label, true, true, 0);
- break;
- case CommandType.UNKNOWN:
- case CommandType.RESET_MUX:
- case CommandType.GO_TO_START:
- case CommandType.BRANCH:
- case CommandType.TRIGGER:
- label = new Gtk.Label ("");
- pack_start (label, true, true, 0);
- label = new Gtk.Label ("");
- pack_start (label, true, true, 0);
- break;
+ return "%.1f ms".printf ((v - 31) * 512 * CYCLE_TIME_MS);
+ });
+ scale1.value_changed.connect ((s) => {
+ int val = (int) s.get_value ();
+ if (val < 32)
+ command.ramp_wait (val * 16 * CYCLE_TIME_MS, command.steps);
+ else
+ command.ramp_wait ((val - 31) * 512 * CYCLE_TIME_MS, command.steps);
+ });
+ content.pack_start (scale1, true, true, 0);
+
+ var hbox = new Gtk.HBox (false, 0);
+ var hbox2 = new Gtk.HBox (true, 0);
+ var radio_inc = (Gtk.RadioButton) Hildon.gtk_radio_button_new (Hildon.SizeType.FINGER_HEIGHT, null);
+ radio_inc.set_mode (false);
+ radio_inc.set_label ("+");
+ hbox2.pack_start (radio_inc, false, false, 0);
+ var radio_dec = (Gtk.RadioButton) Hildon.gtk_radio_button_new_from_widget (Hildon.SizeType.FINGER_HEIGHT, radio_inc);
+ radio_dec.set_mode (false);
+ radio_dec.set_label ("-");
+ bool sign = command.steps < 0;
+ radio_dec.set_active (sign);
+ radio_dec.toggled.connect ((s) => {
+ sign = s.get_active ();
+ if (sign != (command.steps < 0))
+ command.ramp_wait (command.step_time, -command.steps);
+ });
+ hbox2.pack_start (radio_dec, false, false, 0);
+ hbox.pack_start (hbox2, false, false, 0);
+ var scale2 = new Gtk.HScale.with_range (0, 255, 1);
+ scale2.set_value ((command.steps < 0) ? -command.steps : command.steps);
+ scale2.set_value_pos (Gtk.PositionType.RIGHT);
+ scale2.format_value.connect ((v) => {
+ return "%+d".printf (sign ? -(int) v : (int) v);
+ });
+ scale2.value_changed.connect ((s) => {
+ if (sign)
+ command.ramp_wait (command.step_time, -(int) scale2.get_value ());
+ else
+ command.ramp_wait (command.step_time, (int) scale2.get_value ());
+ });
+ hbox.pack_start (scale2, true, true, 0);
+ content.pack_start (hbox, false, false, 0);
+
+ content.show_all ();
+ dialog.add_button ("Delete", 1);
+ dialog.add_button ("Done", Gtk.ResponseType.OK);
+
+ int response = dialog.run ();
+ if (response == Gtk.ResponseType.OK) {
+ var button = source as Hildon.Button;
+ button.set_title ((command.steps != 0) ? "Ramp" : "Wait");
+ button.set_value ((command.steps != 0) ?
+ "%+d steps, %.2f ms each".printf (command.steps,
+ command.step_time) :
+ "%.2f ms".printf (command.duration));
+ } else if (response == 1) {
+ engine.remove (command);
+ engine.first ().data.changed ();
+ this.destroy ();
+ } else {
+ command.ramp_wait (old_step_time, old_steps);
+ }
+ dialog.destroy ();
+ }
+
+ private void on_set_pwm_clicked (Gtk.Button source) {
+ int old_level = command.level;
+ var dialog = new Gtk.Dialog ();
+ dialog.set_title ("Set PWM");
+
+ var content = (Gtk.VBox) dialog.get_content_area ();
+
+ var lpv = new LedPatternView (pattern);
+ lpv.set_size_request (-1, 70);
+ content.pack_start (lpv, true, true, 0);
+
+ var scale = new Gtk.HScale.with_range (0, 255, 1);
+ scale.set_value (command.level);
+ scale.value_changed.connect ((s) => {
+ command.set_pwm ((int) s.get_value ());
+ });
+ content.pack_start (scale, true, true, 0);
+
+ content.show_all ();
+ dialog.add_button ("Delete", 1);
+ dialog.add_button ("Done", Gtk.ResponseType.OK);
+
+ int response = dialog.run ();
+ if (response == Gtk.ResponseType.OK) {
+ command.set_pwm ((int) scale.get_value ());
+
+ var button = source as Hildon.Button;
+ button.set_value ("Level = %d".printf (command.level));
+ } else if (response == 1) {
+ engine.remove (command);
+ engine.first ().data.changed ();
+ this.destroy ();
+ } else {
+ command.set_pwm (old_level);
+ }
+ dialog.destroy ();
+ }
+
+ private void on_end_or_go_to_start_clicked (Gtk.Button source) {
+ CommandType old_type = command.type;
+ int old_steps = command.steps;
+ uint16 old_code = command.code;
+ var dialog = new Gtk.Dialog ();
+ if (command.type == CommandType.END)
+ dialog.set_title ("End");
+ else
+ dialog.set_title ("Go To Start");
+
+ var content = (Gtk.VBox) dialog.get_content_area ();
+
+ var lpv = new LedPatternView (pattern);
+ lpv.set_size_request (-1, 70);
+ content.pack_start (lpv, true, true, 0);
+
+ var hbox = new Gtk.HBox (true, 0);
+ var radio_end = (Gtk.RadioButton) Hildon.gtk_radio_button_new (Hildon.SizeType.FINGER_HEIGHT, null);
+ radio_end.set_mode (false);
+ radio_end.set_label ("End");
+ hbox.pack_start (radio_end, true, true, 0);
+ var radio_go_to_start = (Gtk.RadioButton) Hildon.gtk_radio_button_new_from_widget (Hildon.SizeType.FINGER_HEIGHT, radio_end);
+ radio_go_to_start.set_mode (false);
+ radio_go_to_start.set_label ("Go To Start");
+ hbox.pack_start (radio_go_to_start, true, true, 0);
+ content.pack_start (hbox, true, true, 0);
+
+ hbox = new Gtk.HBox (true, 0);
+ var radio_hold = (Gtk.RadioButton) Hildon.gtk_radio_button_new (Hildon.SizeType.FINGER_HEIGHT, null);
+ radio_hold.set_mode (false);
+ radio_hold.set_label ("Hold");
+ hbox.pack_start (radio_hold, true, true, 0);
+ var radio_reset = (Gtk.RadioButton) Hildon.gtk_radio_button_new_from_widget (Hildon.SizeType.FINGER_HEIGHT, radio_hold);
+ radio_reset.set_mode (false);
+ radio_reset.set_label ("Reset");
+ hbox.pack_start (radio_reset, true, true, 0);
+ content.pack_start (hbox, true, true, 0);
+
+ if (command.type == CommandType.END)
+ radio_end.set_active (true);
+ else
+ radio_go_to_start.set_active (true);
+ radio_hold.set_sensitive (command.type == CommandType.END);
+ radio_reset.set_sensitive (command.type == CommandType.END);
+ radio_reset.set_active (command.steps == -255);
+
+ radio_end.toggled.connect ((s) => {
+ if (s.get_active ()) {
+ command.end (radio_reset.get_active ());
+ radio_hold.set_sensitive (true);
+ radio_reset.set_sensitive (true);
+ dialog.set_title ("End");
+ } else {
+ command.go_to_start ();
+ radio_hold.set_sensitive (false);
+ radio_reset.set_sensitive (false);
+ dialog.set_title ("Go To Start");
+ }
+ command.changed ();
+ });
+ radio_reset.toggled.connect ((s) => {
+ if (command.type == CommandType.END) {
+ command.end (s.get_active ());
+ }
+ });
+
+ content.show_all ();
+ dialog.add_button ("Delete", 1);
+ dialog.add_button ("Done", Gtk.ResponseType.OK);
+
+ int response = dialog.run ();
+ if (response == Gtk.ResponseType.OK) {
+ var button = source as Hildon.Button;
+ button.set_value ((command.type == CommandType.END) ?
+ "End" : "Go To Start");
+ button.set_value ((command.type == CommandType.END) ?
+ ((command.steps == -255) ? "Reset" : "Hold") : "");
+ } else if (response == 1) {
+ engine.remove (command);
+ engine.first ().data.changed ();
+ this.destroy ();
+ } else {
+ command.type = old_type;
+ command.steps = old_steps;
+ command.code = old_code;
+ command.changed ();
+ }
+ dialog.destroy ();
+ }
+
+ private void on_trigger_clicked (Gtk.Button source) {
+ uint16 old_code = command.code;
+ var dialog = new Gtk.Dialog ();
+ dialog.set_title ("Trigger");
+
+ var content = (Gtk.VBox) dialog.get_content_area ();
+
+ var lpv = new LedPatternView (pattern);
+ lpv.set_size_request (-1, 70);
+ content.pack_start (lpv, true, true, 0);
+
+ var check = new Hildon.CheckButton (Hildon.SizeType.FINGER_HEIGHT);
+ check.set_label ("Set trigger");
+ if ((command.code & 0x0006) != 0)
+ check.set_active (true);
+ check.toggled.connect ((s) => {
+ int bit = (engine == pattern.engine1) ? 0x0004 : 0x0002;
+ if (s.get_active ())
+ command.code |= bit;
+ else
+ command.code &= ~bit;
+ command.changed ();
+ });
+ content.pack_start (check, true, true, 0);
+
+ check = new Hildon.CheckButton (Hildon.SizeType.FINGER_HEIGHT);
+ check.set_label ("Wait for trigger");
+ if ((command.code & 0x0180) != 0)
+ check.set_active (true);
+ check.toggled.connect ((s) => {
+ int bit = (engine == pattern.engine1) ? 0x0100 : 0x0080;
+ if (s.get_active ())
+ command.code |= bit;
+ else
+ command.code &= ~bit;
+ command.changed ();
+ });
+ content.pack_start (check, true, true, 0);
+
+ content.show_all ();
+ dialog.add_button ("Delete", 1);
+ dialog.add_button ("Done", Gtk.ResponseType.OK);
+
+ int response = dialog.run ();
+ if (response == Gtk.ResponseType.OK) {
+ var button = source as Hildon.Button;
+ string text = "";
+ if (0x0100 in command.code)
+ text += "wait 2 ";
+ if (0x0004 in command.code)
+ text += "set 2 ";
+ if (0x0080 in command.code)
+ text += "wait 1 ";
+ if (0x0002 in command.code)
+ text += "set 1 ";
+ if ((command.code & ~0xe186) != 0) {
+ text = "Unsupported: 0x%04x".printf (command.code);
+ button.set_sensitive (false);
+ }
+ button.set_value (text);
+ } else if (response == 1) {
+ engine.remove (command);
+ engine.first ().data.changed ();
+ this.destroy ();
+ } else {
+ command.code = old_code;
+ command.changed ();
}
+ dialog.destroy ();
}
}
*/
class LedPatternRX51 : LedPattern {
- public string led_map;
+ public LedColor color1;
+ public LedColor color2;
public List<LedCommandRX51> engine1;
public List<LedCommandRX51> engine2;
priority = p[0].to_int ();
screen_on = p[1].to_int ();
timeout = p[2].to_int ();
- led_map = p[3];
+ parse_led_map (p[3], out color1, out color2);
engine1 = parse_pattern (p[4]);
engine2 = parse_pattern (p[5]);
on_changed ();
}
+ private void parse_led_map (string led_map, out LedColor color1, out LedColor color2) {
+ color1 = LedColor.OFF;
+ color2 = LedColor.OFF;
+ if ("r" in led_map)
+ color1 |= LedColor.R;
+ if ("g" in led_map)
+ color1 |= LedColor.G;
+ if ("b" in led_map)
+ color1 |= LedColor.B;
+ if ("R" in led_map)
+ color2 |= LedColor.R;
+ if ("G" in led_map)
+ color2 |= LedColor.G;
+ if ("B" in led_map)
+ color2 |= LedColor.B;
+ }
+
private List<LedCommandRX51> parse_pattern (string pattern) {
var list = new List<LedCommandRX51> ();
var length = pattern.length;
}
public string dump () {
- return "%s=%d;%d;%d;%s;%s;%s".printf (name, priority, screen_on, timeout, led_map,
+ return "%s=%d;%d;%d;%s;%s;%s".printf (name, priority, screen_on, timeout, dump_led_map (),
dump_pattern (engine1), dump_pattern (engine2));
}
+ private string dump_led_map () {
+ string led_map = "";
+ if (LedColor.R in color1)
+ led_map += "r";
+ if (LedColor.R in color2)
+ led_map += "R";
+ if (LedColor.G in color1)
+ led_map += "g";
+ if (LedColor.G in color2)
+ led_map += "G";
+ if (LedColor.B in color1)
+ led_map += "b";
+ if (LedColor.B in color2)
+ led_map += "B";
+ return led_map;
+ }
+
private string dump_pattern (List<LedCommandRX51> list) {
string result = "";
foreach (LedCommandRX51 command in list) {
pattern.duration = duration;
- pattern.led_map = led_map;
+ pattern.color1 = color1;
+ pattern.color2 = color2;
pattern.engine1 = deep_copy (pattern, engine1);
pattern.engine2 = deep_copy (pattern, engine2);
duration = pattern.duration;
- led_map = pattern.led_map;
+ color1 = pattern.color1;
+ color2 = pattern.color2;
engine1 = deep_copy (this, pattern.engine1);
engine2 = deep_copy (this, pattern.engine2);
changed ();
}
- void on_changed () {
- // calculate timing and level info
+ public void on_changed () {
+ bool unresolved = calculate_timing ();
+ if (unresolved)
+ unresolved = calculate_timing ();
+ if (unresolved)
+ Hildon.Banner.show_information (null, null, "Timing unresolved");
+ changed ();
+ }
+
+ private bool calculate_timing () {
+ bool unresolved = false;
+ // Calculate timing and level info for engine 1
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 (command.type == CommandType.TRIGGER &&
+ (command.code & 0x0180) != 0) {
+ command.duration = wait_for_trigger (time, engine2);
+ if (command.duration == 0)
+ unresolved = true;
+ command.duration += 16 * LedCommandRX51.CYCLE_TIME_MS;
+ }
+ time += command.duration;
if (level < 0)
level = 0;
if (level > 255)
level = 255;
}
duration = time;
- changed ();
+ // Calculate timing and level info for engine 2
+ time = 0;
+ level = 0;
+ foreach (LedCommandRX51 command in engine2) {
+ command.time = time;
+ if (command.type == CommandType.SET_PWM) {
+ level = command.level;
+ } else {
+ command.level = level;
+ level += command.steps;
+ }
+ if (command.type == CommandType.TRIGGER &&
+ (command.code & 0x0180) != 0) {
+ command.duration = wait_for_trigger (time, engine1);
+ if (command.duration == 0)
+ unresolved = true;
+ command.duration += 16 * LedCommandRX51.CYCLE_TIME_MS;
+ }
+ time += command.duration;
+ if (level < 0)
+ level = 0;
+ if (level > 255)
+ level = 255;
+ }
+ if (time > duration)
+ duration = time;
+ return unresolved;
+ }
+
+ double wait_for_trigger (double time, List<LedCommandRX51> engine) {
+ double duration = 0;
+ bool repeat = false;
+ foreach (LedCommandRX51 command in engine) {
+ duration = command.time + command.duration;
+ if (command.type == CommandType.TRIGGER &&
+ (command.code & 0x0006) != 0 && command.time > time) {
+ return command.time - time;
+ }
+ if (command.type == CommandType.GO_TO_START) {
+ repeat = true;
+ break;
+ }
+ }
+ if (repeat) foreach (LedCommandRX51 command in engine) {
+ if (command.type == CommandType.TRIGGER &&
+ (command.code & 0x0006) != 0 && (duration + command.time) > time) {
+ return duration + command.time - time;
+ }
+ }
+ return 0;
}
}
class LedCommandRX51 : LedCommand {
- private const double CYCLE_TIME_MS = 1000.0 / 32768.0;
+ internal const double CYCLE_TIME_MS = 1000.0 / 32768.0;
public uint16 code;
// 0x1000: interrupt
if ((code & 0x0800) != 0) // Reset
steps = -255;
- } else if ((code & ~ 0x13f0) == 0xe000) {
+ } else if ((code & ~ 0x13fe) == 0xe000) {
type = CommandType.TRIGGER;
// 0x1000: wait ext
// 0x0380: wait B G R
// 0x0040: set ext
- // ??: set B G R
+ // 0x000e: set B G R
}
}
}
public override void ramp_wait (double _step_time, int _steps) requires (_step_time >= (16 * CYCLE_TIME_MS)) {
int step_time;
- if (_step_time <= 31 * (16 * CYCLE_TIME_MS)) {
+ if (_step_time < 32 * (16 * CYCLE_TIME_MS)) {
step_time = (int) ((_step_time + 0.001) / (16 * CYCLE_TIME_MS));
code = (uint16) step_time << 9;
_step_time = step_time * (16 * CYCLE_TIME_MS);
- } else if (_step_time <= 31*(512 * CYCLE_TIME_MS)) {
- step_time = (int) ((_step_time + 0.01) / (512 * CYCLE_TIME_MS));
+ } else if (_step_time < 32*(512 * CYCLE_TIME_MS)) {
+ step_time = (int) ((_step_time + 0.001) / (512 * CYCLE_TIME_MS));
code = 0x4000 | (step_time << 9);
_step_time = step_time * (512 * CYCLE_TIME_MS);
} else {
base.ramp_wait (_step_time, _steps);
}
+ public override void go_to_start () {
+ code = 0x0000;
+ base.go_to_start ();
+ }
+
+ public override void end (bool reset) {
+ code = 0xc000;
+ if (reset)
+ code |= 0x0800;
+ base.end (reset);
+ }
+
public LedCommandRX51 copy () {
var command = new LedCommandRX51 ();
ctx.stroke ();
if (pattern != null) {
- ctx.new_path ();
+ if (pattern.color1 != LedColor.OFF)
+ draw_pattern (ctx, width, height,
+ pattern.color1, pattern.engine1);
+ if (pattern.color2 != LedColor.OFF)
+ draw_pattern (ctx, width, height,
+ pattern.color2, pattern.engine2);
+ }
+ return true;
+ }
- if (pattern.led_map == "r") {
- ctx.set_source_rgb (1, 0, 0);
- } else if (pattern.led_map == "g") {
- ctx.set_source_rgb (0, 1, 0);
- } else if (pattern.led_map == "b") {
- ctx.set_source_rgb (0, 0, 1);
- } else if (pattern.led_map == "rg") {
- ctx.set_source_rgb (1, 1, 0);
- } else if (pattern.led_map == "rb") {
- ctx.set_source_rgb (1, 0, 1);
- } else if (pattern.led_map == "gb") {
- ctx.set_source_rgb (0, 1, 1);
- } else if (pattern.led_map == "rgb") {
- ctx.set_source_rgb (1, 1, 1);
- } else {
- ctx.set_source_rgb (0.75, 0.75, 0.75);
+ private void draw_pattern (Cairo.Context ctx, int width, int height, LedColor color,
+ List<LedCommandRX51> engine) {
+ double pps = width / duration; // pixel per second
+
+ ctx.new_path ();
+
+ ctx.set_operator (Cairo.Operator.ADD);
+
+ ctx.set_source_rgb ((LedColor.R in color) ? 1.0 : 0.0,
+ (LedColor.G in color) ? 1.0 : 0.0,
+ (LedColor.B in color) ? 1.0 : 0.0);
+ ctx.set_line_width (3.0);
+
+ double x = 0, y = 0;
+ foreach (LedCommand command in engine) {
+ x = command.time * pps/1000.0;
+ y = (255 - command.level) * (height - 1)/255.0;
+ switch (command.type) {
+ case CommandType.RAMP_WAIT:
+ case CommandType.TRIGGER:
+ x += command.duration * pps/1000.0;
+ y -= command.steps * (height - 1)/255.0;
+ if (y < 0)
+ y = 0;
+ if (y > (height - 1))
+ y = height - 1;
+ ctx.line_to (x, y);
+ break;
+ default:
+ ctx.line_to (x, y);
+ break;
}
- ctx.set_line_width (3.0);
-
- double x = 0, y = 0;
- foreach (LedCommand command in pattern.engine1) {
- x = command.time * pps/1000.0;
- y = (255 - command.level) * (height - 1)/255.0;
- switch (command.type) {
- case CommandType.RAMP_WAIT:
- x += command.duration * pps/1000.0;
- y -= command.steps * (height - 1)/255.0;
- if (y < 0)
- y = 0;
- if (y > (height - 1))
- y = height - 1;
- ctx.line_to (x, y);
- break;
- default:
- ctx.line_to (x, y);
- break;
- }
+ }
+ ctx.stroke ();
+
+ ctx.set_source_rgb ((LedColor.R in color) ? 0.75 : 0.0,
+ (LedColor.G in color) ? 0.75 : 0.0,
+ (LedColor.B in color) ? 0.75 : 0.0);
+ ctx.set_line_width (1.0);
+
+ LedCommandRX51 last_command = null;
+ foreach (LedCommandRX51 command in engine) {
+ if (command.type == CommandType.END ||
+ command.type == CommandType.GO_TO_START) {
+ last_command = command;
+ break;
}
- ctx.stroke ();
+ }
+ if (last_command == null)
+ return;
+
+ if (last_command.type == CommandType.END) {
+ ctx.new_path ();
- if (pattern.led_map == "r") {
- ctx.set_source_rgb (0.75, 0, 0);
- } else if (pattern.led_map == "g") {
- ctx.set_source_rgb (0, 0.75, 0);
- } else if (pattern.led_map == "b") {
- ctx.set_source_rgb (0, 0, 0.75);
- } else if (pattern.led_map == "rg") {
- ctx.set_source_rgb (0.75, 0.75, 0);
- } else if (pattern.led_map == "rb") {
- ctx.set_source_rgb (0.75, 0, 0.75);
- } else if (pattern.led_map == "gb") {
- ctx.set_source_rgb (0, 0.75, 0.75);
- } else if (pattern.led_map == "rgb") {
- ctx.set_source_rgb (0.75, 0.75, 0.75);
+ ctx.move_to (x, y);
+ if (last_command.steps == -255) {
+ ctx.line_to (x, height - 0.5);
+ ctx.line_to (width - 0.5, height - 0.5);
} else {
- ctx.set_source_rgb (0.66, 0.66, 0.66);
- }
- ctx.set_line_width (1.0);
-
- CommandType type = CommandType.UNKNOWN;
- int steps = 0;
- foreach (LedCommandRX51 command in pattern.engine1) {
- if (command.type == CommandType.END ||
- command.type == CommandType.GO_TO_START) {
- type = command.type;
- steps = command.steps;
- break;
- }
+ ctx.line_to (width - 0.5, y);
}
- if (type == CommandType.END) {
- ctx.new_path ();
+ ctx.stroke ();
+ }
+ var engine_duration = last_command.time + last_command.duration;
+ if (last_command.type == CommandType.GO_TO_START && engine_duration >= 3 * 0.49) {
+ ctx.new_path ();
+ for (double offset = engine_duration; (offset * pps/1000.0) <= width; offset += engine_duration) {
ctx.move_to (x, y);
- if (steps == -255) {
- ctx.line_to (x, height - 0.5);
- ctx.line_to (width - 0.5, height - 0.5);
- } else {
- ctx.line_to (width - 0.5, y);
- }
-
- ctx.stroke ();
- }
- if (type == CommandType.GO_TO_START && pattern.duration >= 3 * 0.49) {
- ctx.new_path ();
-
- for (double offset = pattern.duration; (offset * pps/1000.0) <= width; offset += pattern.duration) {
- ctx.move_to (x, y);
- foreach (LedCommand command in pattern.engine1) {
- x = (command.time + offset) * pps/1000.0;
- y = (255 - command.level) * (height - 1)/255.0;
- if (x >= width)
- break;
- switch (command.type) {
- case CommandType.RAMP_WAIT:
- x += command.duration * pps/1000.0;
- y -= command.steps * (height - 1)/255.0;
- if (y < 0)
- y = 0;
- if (y > (height - 1))
- y = height - 1;
- ctx.line_to (x, y);
- break;
- default:
- ctx.line_to (x, y);
- break;
- }
+ foreach (LedCommand command in engine) {
+ x = (command.time + offset) * pps/1000.0;
+ y = (255 - command.level) * (height - 1)/255.0;
+ if (x >= width)
+ break;
+ switch (command.type) {
+ case CommandType.RAMP_WAIT:
+ case CommandType.TRIGGER:
+ x += command.duration * pps/1000.0;
+ y -= command.steps * (height - 1)/255.0;
+ if (y < 0)
+ y = 0;
+ if (y > (height - 1))
+ y = height - 1;
+ ctx.line_to (x, y);
+ break;
+ default:
+ ctx.line_to (x, y);
+ break;
}
}
-
- ctx.stroke ();
}
- if (type == CommandType.GO_TO_START && pattern.duration < 3 * 0.49) {
- ctx.new_path ();
+ ctx.stroke ();
+ }
+ if (last_command.type == CommandType.GO_TO_START && engine_duration < 3 * 0.49) {
+ ctx.new_path ();
- ctx.move_to (x, y);
- ctx.line_to (width - 0.5, y);
- ctx.stroke ();
- }
+ ctx.move_to (x, y);
+ ctx.line_to (width - 0.5, y);
+
+ ctx.stroke ();
}
- return true;
}
public void update () {
changed ();
}
+ public virtual void go_to_start () {
+ type = CommandType.GO_TO_START;
+ changed ();
+ }
+
+ public virtual void end (bool reset) {
+ type = CommandType.END;
+ steps = reset ? -255 : 0;
+ changed ();
+ }
+
public signal void changed ();
}
LedPatternView lpv;
LedPatternRX51 pattern;
+ LedColorButton led_color1;
+ LedColorButton led_color2;
+ Gtk.Widget list1;
+ Gtk.Widget list2;
+
public LedProgramDialog (LedPatternRX51 _pattern) {
pattern = _pattern;
set_title ("LED pattern editor - " +
lpv.set_size_request (-1, 70);
content.pack_start (lpv, false, false, 0);
- var pannable = new Hildon.PannableArea ();
- var vbox = new Gtk.VBox (false, 0);
-
- foreach (LedCommand command in lpv.pattern.engine1) {
- var command_widget = new LedCommandWidget (command);
-
- vbox.pack_start (command_widget, false, false, 0);
- }
-
- pannable.add_with_viewport (vbox);
- content.pack_start (pannable, true, true, 0);
+ var hbox = new Gtk.HBox (true, 0);
+ list1 = led_command_list (1);
+ hbox.pack_start (list1, true, true, 0);
+ list2 = led_command_list (2);
+ hbox.pack_start (list2, true, true, 0);
+ content.pack_start (hbox, true, true, 0);
content.show_all ();
-
- var led_color = new LedColorButton.with_map (lpv.pattern.led_map);
- led_color.clicked.connect (on_color_clicked);
- add_action_widget (led_color, 2);
- action_area.set_child_secondary (led_color, true);
+ list2.hide ();
+
+ hbox = new Gtk.HBox (true, 0);
+ led_color1 = new LedColorButton.with_color (lpv.pattern.color1);
+ led_color1.clicked.connect (on_color1_clicked);
+ hbox.pack_start (led_color1, true, true, 0);
+ led_color2 = new LedColorButton.with_color (lpv.pattern.color2);
+ led_color2.clicked.connect (on_color2_clicked);
+ hbox.pack_start (led_color2, true, true, 0);
+ add_action_widget (hbox, 2);
+ action_area.set_child_secondary (hbox, true);
+
+ hbox = new Gtk.HBox (true, 0);
+ var radio = (Gtk.RadioButton) Hildon.gtk_radio_button_new (Hildon.SizeType.FINGER_HEIGHT, null);
+ radio.set_mode (false);
+ radio.set_label ("1");
+ radio.set_active (true);
+ radio.toggled.connect (on_engine1_toggled);
+ hbox.pack_start (radio, true, true, 0);
+ radio = (Gtk.RadioButton) Hildon.gtk_radio_button_new_from_widget (Hildon.SizeType.FINGER_HEIGHT, radio);
+ radio.set_mode (false);
+ radio.set_label ("2");
+ radio.toggled.connect (on_engine2_toggled);
+ hbox.pack_start (radio, true, true, 0);
+ add_action_widget (hbox, 2);
+ action_area.set_child_secondary (hbox, true);
action_area.show_all ();
response.connect (on_response);
}
+ private Gtk.Widget led_command_list (int engine) {
+ var pannable = new Hildon.PannableArea ();
+ var vbox = new Gtk.VBox (false, 0);
+
+ var label = new Gtk.Label ("Engine %d:".printf (engine));
+ label.set_alignment (0, 0.5f);
+ vbox.pack_start (label, false, false, 0);
+
+ unowned List<LedCommandRX51> list = (engine == 1) ?
+ lpv.pattern.engine1 : lpv.pattern.engine2;
+ foreach (LedCommandRX51 command in list) {
+ if (command.type == CommandType.RESET_MUX)
+ continue;
+ var command_widget = new LedCommandWidget (lpv.pattern, list,
+ command);
+
+ vbox.pack_start (command_widget, false, false, 0);
+ }
+
+ var button = new Gtk.Button.with_label ("New command");
+ Hildon.gtk_widget_set_theme_size (button, Hildon.SizeType.FINGER_HEIGHT);
+ button.clicked.connect (on_new_command_clicked);
+ vbox.pack_end (button, false, false, 0);
+
+ pannable.add_with_viewport (vbox);
+ return pannable;
+ }
+
void on_response (int response) {
if (response == 1) {
Timeout.add (200, delayed_spawn);
return false;
}
- void on_color_clicked (Gtk.Button button) {
+ void on_color1_clicked (Gtk.Button button) {
var dialog = new LedColorDialog ();
int response = dialog.run ();
if (response > 0) {
- ((LedColorButton) button).set_color ((LedColor) response);
- switch ((LedColor) response) {
- case LedColor.R:
- lpv.pattern.led_map = "r";
- break;
- case LedColor.G:
- lpv.pattern.led_map = "g";
+ LedColor color = (LedColor) response;
+ led_color1.set_color (color);
+ lpv.pattern.color1 = color;
+ color = led_color2.get_color () & ~response;
+ led_color2.set_color (color);
+ lpv.pattern.color2 = color;
+ lpv.pattern.changed ();
+ }
+ dialog.destroy ();
+ }
+
+ void on_color2_clicked (Gtk.Button button) {
+ var dialog = new LedColorDialog ();
+ int response = dialog.run ();
+ if (response > 0) {
+ LedColor color = (LedColor) response;
+ led_color2.set_color (color);
+ lpv.pattern.color2 = color;
+ color = led_color1.get_color () & ~response;
+ led_color1.set_color (color);
+ lpv.pattern.color1 = color;
+ lpv.pattern.changed ();
+ }
+ dialog.destroy ();
+ }
+
+ void on_engine1_toggled (Gtk.ToggleButton source) {
+ if (source.get_active ())
+ list1.show ();
+ else
+ list1.hide ();
+ }
+
+ void on_engine2_toggled (Gtk.ToggleButton source) {
+ if (source.get_active ())
+ list2.show ();
+ else
+ list2.hide ();
+ }
+
+ void on_new_command_clicked (Gtk.Button button) {
+ var widget = button.parent.parent.parent;
+ unowned List<LedCommandRX51> engine;
+ if (widget == list1) {
+ engine = lpv.pattern.engine1;
+ } else if (widget == list2) {
+ engine = lpv.pattern.engine2;
+ } else {
+ return;
+ }
+
+ var dialog = new Hildon.PickerDialog (this);
+ dialog.set_title ("New command");
+
+ var touch_selector = new Hildon.TouchSelector.text ();
+ touch_selector.append_text ("Set PWM");
+ touch_selector.append_text ("Ramp");
+ touch_selector.append_text ("Wait");
+ touch_selector.append_text ("Trigger");
+ touch_selector.append_text ("Go To Start");
+ touch_selector.append_text ("End");
+ dialog.set_selector (touch_selector);
+
+ int response = dialog.run ();
+ if (response == Gtk.ResponseType.OK) {
+ var command = new LedCommandRX51 ();
+ LedCommandRX51 last_command = engine.last ().data;
+ engine.append (command);
+ command.changed.connect (lpv.pattern.on_changed);
+
+ switch (touch_selector.get_active (0)) {
+ case 0:
+ command.set_pwm (127);
break;
- case LedColor.B:
- lpv.pattern.led_map = "b";
+ case 1:
+ if (last_command.type == CommandType.RAMP_WAIT) {
+ command.ramp_wait (last_command.step_time,
+ -last_command.steps);
+ } else if (last_command.level > 0) {
+ command.ramp_wait (125.0 / last_command.level,
+ -last_command.level);
+ } else {
+ command.ramp_wait (0.49, 255);
+ }
break;
- case LedColor.RG:
- lpv.pattern.led_map = "rg";
+ case 2:
+ command.ramp_wait (100.0, 0);
break;
- case LedColor.RB:
- lpv.pattern.led_map = "rb";
+ case 3:
+ command.type = CommandType.TRIGGER;
+ command.code = 0xe000;
+ command.changed ();
break;
- case LedColor.GB:
- lpv.pattern.led_map = "gb";
+ case 4:
+ command.go_to_start ();
break;
- case LedColor.RGB:
- lpv.pattern.led_map = "rgb";
+ case 5:
+ command.end (false);
break;
}
- lpv.pattern.changed ();
+ var vbox = (Gtk.VBox) button.parent;
+ var command_widget = new LedCommandWidget (lpv.pattern, engine,
+ command);
+ vbox.pack_start (command_widget, false, false, 0);
+ command_widget.show_all ();
+
}
dialog.destroy ();
}