]> git.tdb.fi Git - r2c2.git/blobdiff - source/serial/serial.cpp
Add a program for serial port control and associated Arduino firmware
[r2c2.git] / source / serial / serial.cpp
diff --git a/source/serial/serial.cpp b/source/serial/serial.cpp
new file mode 100644 (file)
index 0000000..2766752
--- /dev/null
@@ -0,0 +1,130 @@
+/* $Id$
+
+This file is part of the MSP Märklin suite
+Copyright © 2010  Mikkosoft Productions, Mikko Rasa
+Distributed under the GPL
+*/
+
+#include <msp/net/resolve.h>
+#include "serial.h"
+
+#include <msp/io/print.h>
+
+using namespace std;
+using namespace Msp;
+using namespace Marklin;
+       
+Application::RegApp<Serial> Serial::reg;
+
+Serial::Serial(int, char **argv):
+       client(catalogue),
+       serial_port(argv[2]),
+       train(0),
+       rx_fill(0)
+{
+       DataFile::load(catalogue, "locos.dat");
+
+       client.use_event_dispatcher(event_disp);
+       client.signal_train_added.connect(sigc::mem_fun(this, &Serial::train_added));
+       client.signal_error.connect(sigc::mem_fun(this, &Serial::error));
+
+       string addr_str = argv[1];
+       if(addr_str.find(':')==string::npos)
+               addr_str += ":8315";
+       Net::SockAddr *addr = Net::resolve(addr_str);
+       client.connect(*addr);
+       delete addr;
+
+       serial_port.set_parameters("9600,8N1");
+       event_disp.add(serial_port);
+       serial_port.signal_data_available.connect(sigc::mem_fun(this, &Serial::data_available));
+}
+
+void Serial::tick()
+{
+       event_disp.tick();
+}
+
+void Serial::train_added(NetTrain &t)
+{
+       if(!train)
+               set_train(&t);
+}
+
+void Serial::error(const string &e)
+{
+       IO::print("%s\n", e);
+}
+
+void Serial::set_train(NetTrain *t)
+{
+       train = t;
+       serial_port.write(format("A%02d", train->get_address()));
+}
+
+void Serial::next_train()
+{
+       const map<unsigned, NetTrain *> &trains = client.get_trains();
+
+       map<unsigned, NetTrain *>::const_iterator i = trains.find(train->get_address());
+       ++i;
+       if(i==trains.end())
+               i = trains.begin();
+
+       set_train(i->second);
+}
+
+void Serial::prev_train()
+{
+       const map<unsigned, NetTrain *> &trains = client.get_trains();
+
+       map<unsigned, NetTrain *>::const_iterator i = trains.find(train->get_address());
+       if(i==trains.begin())
+               i = trains.end();
+       --i;
+
+       set_train(i->second);
+}
+
+void Serial::data_available()
+{
+       char c;
+       serial_port.read(&c, 1);
+       if(rx_fill==0)
+       {
+               if(c=='S' || c=='H' || c=='L')
+                       rx_buf[rx_fill++] = c;
+               else if(c=='R')
+               {
+                       IO::print("Reverse\n");
+                       train->set_reverse(!train->get_reverse());
+               }
+               else if(c=='N')
+                       next_train();
+               else if(c=='P')
+                       prev_train();
+       }
+       else
+       {
+               rx_buf[rx_fill++] = c;
+               if(rx_buf[0]=='H' && rx_fill==2)
+               {
+                       train->set_function(rx_buf[1]-'0', true);
+                       IO::print("Func %d on\n", rx_buf[1]-'0');
+                       rx_fill = 0;
+               }
+               else if(rx_buf[0]=='L' && rx_fill==2)
+               {
+                       train->set_function(rx_buf[1]-'0', false);
+                       IO::print("Func %d off\n", rx_buf[1]-'0');
+                       rx_fill = 0;
+               }
+               else if(rx_buf[0]=='S' && rx_fill==3)
+               {
+                       unsigned speed = (rx_buf[1]-'0')*10+(rx_buf[2]-'0');
+                       IO::print("Set speed %d\n", speed);
+                       train->set_speed(speed);
+                       rx_fill = 0;
+               }
+       }
+}