From 68ff3ebd0073097de84fc55b22047cb5b9d98db7 Mon Sep 17 00:00:00 2001 From: "Jan \"Yenya\" Kasprzak" <kas@fi.muni.cz> Date: Thu, 2 Dec 2010 01:59:11 +0100 Subject: [PATCH] Proof-of-concept GUI --- SCX/Reader.pm | 20 +- gui.pl | 122 ++++++++++ slotcarman.glade | 600 +++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 737 insertions(+), 5 deletions(-) create mode 100755 gui.pl create mode 100644 slotcarman.glade diff --git a/SCX/Reader.pm b/SCX/Reader.pm index 1b7c44f..5a98a6d 100644 --- a/SCX/Reader.pm +++ b/SCX/Reader.pm @@ -82,13 +82,23 @@ sub read { my @bad_bytes; - while (@bytes >= $PACKET_SIZE) { - if ($bytes[0] != 0x55 || $bytes[9] != 0x05 - || SCX::CRC::digest(@bytes[0..7]) != $bytes[8]) { + while (@bytes >= 2) { + if ($bytes[0] != 0x55) { push @bad_bytes, shift @bytes; next; } + my $cmd = $bytes[1]; + my $packet_size = $cmd >= 0x40 && $cmd <= 0x46 ? 4 : 9; + last if @bytes <= $packet_size; + + if ($bytes[$packet_size] != 0x05 + || SCX::CRC::digest(@bytes[0..$packet_size-2]) + != $bytes[$packet_size-1]) { + push @bad_bytes, shift @bytes; + next; + } + if (@bad_bytes) { $self->{logfh}->print("Cannot parse bytes", (map { sprintf(' %02x', $_) } @bad_bytes), @@ -97,8 +107,8 @@ sub read { } $self->{logfh}->print("Callback\n"); - &{ $self->{callback} }(@bytes[1..7]); - splice @bytes, 0, 10; + &{ $self->{callback} }(@bytes[1..$packet_size]); + splice @bytes, 0, $packet_size+1; } if (@bad_bytes) { $self->{logfh}->print("Cannot parse bytes", diff --git a/gui.pl b/gui.pl new file mode 100755 index 0000000..5e1411a --- /dev/null +++ b/gui.pl @@ -0,0 +1,122 @@ +#!/usr/bin/perl -w + +use strict; +use utf8; + +use Gtk2 '-init'; +use Glib qw(TRUE FALSE); + +use SCX::Reader; + +my @controllers = (0, 0, 0, 0, 0, 0); + +my $builder = Gtk2::Builder->new; +$builder->add_from_file('slotcarman.glade'); + +my $window = $builder->get_object('slotcarman'); + +$builder->connect_signals(undef); +$window->show(); + +sub quit { + Gtk2->main_quit; + return FALSE; +} + +my $reader = SCX::Reader->new({ + portname => '/dev/ttyUSB0', + logfile => 'log', + callback => \&do_packet, +}); + +sub scx_read { + my $event = shift; + + $reader->read(); + return TRUE; +} + +Glib::IO->add_watch(fileno($reader->fh), 'in', \&scx_read, 1); + +Gtk2->main(); + +sub do_packet { + my (@data) = @_; + + if ($data[0] == 0xff) { # controller status + for my $controller (1..6) { + my $byte = $data[$controller]; + next if defined $controllers[$controller-1] + && $controllers[$controller-1] == $byte; + $controllers[$controller-1] = $byte; + + my $progressbar = $builder->get_object( + 'progressbar_controller'.$controller); + if ($byte == 0xaa) { + $progressbar->set_text('inactive'); + $progressbar->set_fraction(0); + next; + } + my $light = !($byte & 0x20); + my $backbutton = !($byte & 0x10); + my $speed = $byte & 0x0f; + + my $text = ($backbutton ? '+' : '') . $speed; + $progressbar->set_text($text); + $progressbar->set_fraction($speed / 12); + } + } elsif ($data[0] == 0xd6) { # fuel status + my @fuel = (0, + $data[1] >> 4, $data[1] & 0x0f, + $data[2] >> 4, $data[2] & 0x0f, + $data[3] >> 4, $data[3] & 0x0f, + ); + for my $car (1..6) { + next if defined $controllers[$car-1] + &&$controllers[$car-1] == $fuel[$car]; + + my $progressbar = $builder->get_object( + 'progressbar_fuel'.$car); + $progressbar->set_fraction($fuel[$car]/8); + } + } else { + print "Unknown packet", + (map { sprintf(" %02x", $_) } @data), "\n"; + } +} + +__END__ +use Gtk2 '-init'; + +my $window = Gtk2::Window->new('toplevel'); +$window->signal_connect(delete_event => sub { Gtk2->main_quit; return FALSE }); +$window->set_title("Slot Cars Manager"); + +$window->set_border_width(10); + +my $button = Gtk2::Button->new("Button 1"); +$button->signal_connect(clicked => \&callback, 'button 1'); + +my $box1 = Gtk2::HBox->new(FALSE, 0); +$window->add($box1); +$box1->pack_start($button, TRUE, TRUE, 0); + +$button->show; +$button = Gtk2::Button->new("Button 2"); +$button->signal_connect(clicked => \&callback, 'button 2'); +$box1->pack_start($button, TRUE, TRUE, 0); + +$button->show; +$box1->show; +$window->show; + +Gtk2->main(); + + +sub callback +{ + my ($button, $data) = @_; + + print "Hello again - $data was pressed\n"; +} + diff --git a/slotcarman.glade b/slotcarman.glade new file mode 100644 index 0000000..45c33e0 --- /dev/null +++ b/slotcarman.glade @@ -0,0 +1,600 @@ +<?xml version="1.0" encoding="UTF-8"?> +<interface> + <requires lib="gtk+" version="2.20"/> + <!-- interface-naming-policy project-wide --> + <object class="GtkWindow" id="slotcarman"> + <property name="title" translatable="yes">Slot Cars Race Manager</property> + <child> + <object class="GtkVBox" id="vbox1"> + <property name="visible">True</property> + <child> + <object class="GtkMenuBar" id="menubar1"> + <property name="visible">True</property> + <child> + <object class="GtkMenuItem" id="menuitem1"> + <property name="visible">True</property> + <property name="use_action_appearance">False</property> + <property name="label" translatable="yes">_File</property> + <property name="use_underline">True</property> + <child type="submenu"> + <object class="GtkMenu" id="menu1"> + <property name="visible">True</property> + <child> + <object class="GtkImageMenuItem" id="imagemenuitem1"> + <property name="label">gtk-new</property> + <property name="visible">True</property> + <property name="use_action_appearance">False</property> + <property name="use_underline">True</property> + <property name="use_stock">True</property> + </object> + </child> + <child> + <object class="GtkImageMenuItem" id="imagemenuitem2"> + <property name="label">gtk-open</property> + <property name="visible">True</property> + <property name="use_action_appearance">False</property> + <property name="use_underline">True</property> + <property name="use_stock">True</property> + </object> + </child> + <child> + <object class="GtkImageMenuItem" id="imagemenuitem3"> + <property name="label">gtk-save</property> + <property name="visible">True</property> + <property name="use_action_appearance">False</property> + <property name="use_underline">True</property> + <property name="use_stock">True</property> + </object> + </child> + <child> + <object class="GtkImageMenuItem" id="imagemenuitem4"> + <property name="label">gtk-save-as</property> + <property name="visible">True</property> + <property name="use_action_appearance">False</property> + <property name="use_underline">True</property> + <property name="use_stock">True</property> + </object> + </child> + <child> + <object class="GtkSeparatorMenuItem" id="separatormenuitem1"> + <property name="visible">True</property> + <property name="use_action_appearance">False</property> + </object> + </child> + <child> + <object class="GtkImageMenuItem" id="imagemenuitem5"> + <property name="label">gtk-quit</property> + <property name="visible">True</property> + <property name="use_action_appearance">False</property> + <property name="use_underline">True</property> + <property name="use_stock">True</property> + <signal name="activate" handler="quit" swapped="no"/> + </object> + </child> + </object> + </child> + </object> + </child> + <child> + <object class="GtkMenuItem" id="menuitem2"> + <property name="visible">True</property> + <property name="use_action_appearance">False</property> + <property name="label" translatable="yes">_Edit</property> + <property name="use_underline">True</property> + <child type="submenu"> + <object class="GtkMenu" id="menu2"> + <property name="visible">True</property> + <child> + <object class="GtkImageMenuItem" id="imagemenuitem6"> + <property name="label">gtk-cut</property> + <property name="visible">True</property> + <property name="use_action_appearance">False</property> + <property name="use_underline">True</property> + <property name="use_stock">True</property> + </object> + </child> + <child> + <object class="GtkImageMenuItem" id="imagemenuitem7"> + <property name="label">gtk-copy</property> + <property name="visible">True</property> + <property name="use_action_appearance">False</property> + <property name="use_underline">True</property> + <property name="use_stock">True</property> + </object> + </child> + <child> + <object class="GtkImageMenuItem" id="imagemenuitem8"> + <property name="label">gtk-paste</property> + <property name="visible">True</property> + <property name="use_action_appearance">False</property> + <property name="use_underline">True</property> + <property name="use_stock">True</property> + </object> + </child> + <child> + <object class="GtkImageMenuItem" id="imagemenuitem9"> + <property name="label">gtk-delete</property> + <property name="visible">True</property> + <property name="use_action_appearance">False</property> + <property name="use_underline">True</property> + <property name="use_stock">True</property> + </object> + </child> + </object> + </child> + </object> + </child> + <child> + <object class="GtkMenuItem" id="menuitem3"> + <property name="visible">True</property> + <property name="use_action_appearance">False</property> + <property name="label" translatable="yes">_View</property> + <property name="use_underline">True</property> + </object> + </child> + <child> + <object class="GtkMenuItem" id="menuitem4"> + <property name="visible">True</property> + <property name="use_action_appearance">False</property> + <property name="label" translatable="yes">_Help</property> + <property name="use_underline">True</property> + <child type="submenu"> + <object class="GtkMenu" id="menu3"> + <property name="visible">True</property> + <child> + <object class="GtkImageMenuItem" id="imagemenuitem10"> + <property name="label">gtk-about</property> + <property name="visible">True</property> + <property name="use_action_appearance">False</property> + <property name="use_underline">True</property> + <property name="use_stock">True</property> + <signal name="activate" handler="about" swapped="no"/> + </object> + </child> + </object> + </child> + </object> + </child> + </object> + <packing> + <property name="expand">False</property> + <property name="position">0</property> + </packing> + </child> + <child> + <object class="GtkTable" id="table1"> + <property name="visible">True</property> + <property name="n_rows">7</property> + <property name="n_columns">11</property> + <child> + <object class="GtkLabel" id="label_pos1"> + <property name="visible">True</property> + <property name="label" translatable="yes"><span weight="ultrabold" size="large">1</span></property> + <property name="use_markup">True</property> + <property name="justify">right</property> + <property name="width_chars">1</property> + <property name="single_line_mode">True</property> + </object> + <packing> + <property name="top_attach">1</property> + <property name="bottom_attach">2</property> + </packing> + </child> + <child> + <object class="GtkLabel" id="label_pos2"> + <property name="visible">True</property> + <property name="label" translatable="yes"><span weight="ultrabold" size="large">2</span></property> + <property name="use_markup">True</property> + <property name="justify">right</property> + <property name="width_chars">1</property> + <property name="single_line_mode">True</property> + </object> + <packing> + <property name="top_attach">2</property> + <property name="bottom_attach">3</property> + </packing> + </child> + <child> + <object class="GtkLabel" id="label_pos3"> + <property name="visible">True</property> + <property name="yalign">0.50999999046325684</property> + <property name="label" translatable="yes"><span weight="ultrabold" size="large">3</span></property> + <property name="use_markup">True</property> + <property name="justify">right</property> + <property name="width_chars">1</property> + <property name="single_line_mode">True</property> + </object> + <packing> + <property name="top_attach">3</property> + <property name="bottom_attach">4</property> + </packing> + </child> + <child> + <object class="GtkLabel" id="label_pos4"> + <property name="visible">True</property> + <property name="label" translatable="yes"><span weight="ultrabold" size="large">4</span></property> + <property name="use_markup">True</property> + <property name="justify">right</property> + <property name="width_chars">1</property> + <property name="single_line_mode">True</property> + </object> + <packing> + <property name="top_attach">4</property> + <property name="bottom_attach">5</property> + </packing> + </child> + <child> + <object class="GtkLabel" id="label_pos5"> + <property name="visible">True</property> + <property name="label" translatable="yes"><span weight="ultrabold" size="large">5</span></property> + <property name="use_markup">True</property> + <property name="justify">right</property> + <property name="width_chars">1</property> + <property name="single_line_mode">True</property> + </object> + <packing> + <property name="top_attach">5</property> + <property name="bottom_attach">6</property> + </packing> + </child> + <child> + <object class="GtkLabel" id="label_pos6"> + <property name="visible">True</property> + <property name="label" translatable="yes"><span weight="ultrabold" size="large">6</span></property> + <property name="use_markup">True</property> + <property name="justify">right</property> + <property name="width_chars">1</property> + <property name="single_line_mode">True</property> + </object> + <packing> + <property name="top_attach">6</property> + <property name="bottom_attach">7</property> + </packing> + </child> + <child> + <object class="GtkLabel" id="label_name1"> + <property name="visible">True</property> + <property name="label" translatable="yes">Ivi</property> + <property name="ellipsize">end</property> + <property name="width_chars">25</property> + <property name="single_line_mode">True</property> + </object> + <packing> + <property name="left_attach">1</property> + <property name="right_attach">2</property> + <property name="top_attach">1</property> + <property name="bottom_attach">2</property> + </packing> + </child> + <child> + <placeholder/> + </child> + <child> + <placeholder/> + </child> + <child> + <placeholder/> + </child> + <child> + <placeholder/> + </child> + <child> + <placeholder/> + </child> + <child> + <placeholder/> + </child> + <child> + <placeholder/> + </child> + <child> + <placeholder/> + </child> + <child> + <placeholder/> + </child> + <child> + <placeholder/> + </child> + <child> + <placeholder/> + </child> + <child> + <placeholder/> + </child> + <child> + <placeholder/> + </child> + <child> + <placeholder/> + </child> + <child> + <placeholder/> + </child> + <child> + <placeholder/> + </child> + <child> + <placeholder/> + </child> + <child> + <placeholder/> + </child> + <child> + <placeholder/> + </child> + <child> + <placeholder/> + </child> + <child> + <placeholder/> + </child> + <child> + <placeholder/> + </child> + <child> + <placeholder/> + </child> + <child> + <placeholder/> + </child> + <child> + <placeholder/> + </child> + <child> + <placeholder/> + </child> + <child> + <placeholder/> + </child> + <child> + <placeholder/> + </child> + <child> + <placeholder/> + </child> + <child> + <placeholder/> + </child> + <child> + <placeholder/> + </child> + <child> + <placeholder/> + </child> + <child> + <placeholder/> + </child> + <child> + <placeholder/> + </child> + <child> + <placeholder/> + </child> + <child> + <placeholder/> + </child> + <child> + <placeholder/> + </child> + <child> + <placeholder/> + </child> + <child> + <placeholder/> + </child> + <child> + <placeholder/> + </child> + <child> + <placeholder/> + </child> + <child> + <placeholder/> + </child> + <child> + <placeholder/> + </child> + <child> + <placeholder/> + </child> + <child> + <placeholder/> + </child> + <child> + <placeholder/> + </child> + <child> + <placeholder/> + </child> + <child> + <placeholder/> + </child> + <child> + <placeholder/> + </child> + <child> + <placeholder/> + </child> + <child> + <placeholder/> + </child> + <child> + <placeholder/> + </child> + <child> + <placeholder/> + </child> + <child> + <placeholder/> + </child> + <child> + <placeholder/> + </child> + <child> + <placeholder/> + </child> + <child> + <placeholder/> + </child> + <child> + <placeholder/> + </child> + <child> + <object class="GtkProgressBar" id="progressbar_fuel1"> + <property name="visible">True</property> + </object> + <packing> + <property name="left_attach">10</property> + <property name="right_attach">11</property> + <property name="top_attach">1</property> + <property name="bottom_attach">2</property> + </packing> + </child> + <child> + <object class="GtkProgressBar" id="progressbar_fuel2"> + <property name="visible">True</property> + </object> + <packing> + <property name="left_attach">10</property> + <property name="right_attach">11</property> + <property name="top_attach">2</property> + <property name="bottom_attach">3</property> + </packing> + </child> + <child> + <object class="GtkProgressBar" id="progressbar_fuel3"> + <property name="visible">True</property> + </object> + <packing> + <property name="left_attach">10</property> + <property name="right_attach">11</property> + <property name="top_attach">3</property> + <property name="bottom_attach">4</property> + </packing> + </child> + <child> + <object class="GtkProgressBar" id="progressbar_fuel4"> + <property name="visible">True</property> + </object> + <packing> + <property name="left_attach">10</property> + <property name="right_attach">11</property> + <property name="top_attach">4</property> + <property name="bottom_attach">5</property> + </packing> + </child> + <child> + <object class="GtkProgressBar" id="progressbar_fuel5"> + <property name="visible">True</property> + </object> + <packing> + <property name="left_attach">10</property> + <property name="right_attach">11</property> + <property name="top_attach">5</property> + <property name="bottom_attach">6</property> + </packing> + </child> + <child> + <object class="GtkProgressBar" id="progressbar_fuel6"> + <property name="visible">True</property> + </object> + <packing> + <property name="left_attach">10</property> + <property name="right_attach">11</property> + <property name="top_attach">6</property> + <property name="bottom_attach">7</property> + </packing> + </child> + <child> + <object class="GtkProgressBar" id="progressbar_controller1"> + <property name="visible">True</property> + <property name="orientation">bottom-to-top</property> + </object> + <packing> + <property name="left_attach">8</property> + <property name="right_attach">9</property> + <property name="top_attach">1</property> + <property name="bottom_attach">2</property> + </packing> + </child> + <child> + <object class="GtkProgressBar" id="progressbar_controller2"> + <property name="visible">True</property> + <property name="orientation">bottom-to-top</property> + </object> + <packing> + <property name="left_attach">8</property> + <property name="right_attach">9</property> + <property name="top_attach">2</property> + <property name="bottom_attach">3</property> + </packing> + </child> + <child> + <object class="GtkProgressBar" id="progressbar_controller3"> + <property name="visible">True</property> + <property name="orientation">bottom-to-top</property> + </object> + <packing> + <property name="left_attach">8</property> + <property name="right_attach">9</property> + <property name="top_attach">3</property> + <property name="bottom_attach">4</property> + </packing> + </child> + <child> + <object class="GtkProgressBar" id="progressbar_controller4"> + <property name="visible">True</property> + <property name="orientation">bottom-to-top</property> + </object> + <packing> + <property name="left_attach">8</property> + <property name="right_attach">9</property> + <property name="top_attach">4</property> + <property name="bottom_attach">5</property> + </packing> + </child> + <child> + <object class="GtkProgressBar" id="progressbar_controller5"> + <property name="visible">True</property> + <property name="orientation">bottom-to-top</property> + </object> + <packing> + <property name="left_attach">8</property> + <property name="right_attach">9</property> + <property name="top_attach">5</property> + <property name="bottom_attach">6</property> + </packing> + </child> + <child> + <object class="GtkProgressBar" id="progressbar_controller6"> + <property name="visible">True</property> + <property name="orientation">bottom-to-top</property> + </object> + <packing> + <property name="left_attach">8</property> + <property name="right_attach">9</property> + <property name="top_attach">6</property> + <property name="bottom_attach">7</property> + </packing> + </child> + </object> + <packing> + <property name="position">1</property> + </packing> + </child> + <child> + <object class="GtkStatusbar" id="statusbar1"> + <property name="visible">True</property> + <property name="spacing">2</property> + <property name="has_resize_grip">False</property> + </object> + <packing> + <property name="expand">False</property> + <property name="position">2</property> + </packing> + </child> + </object> + </child> + </object> +</interface> -- 2.43.5