]> git.tdb.fi Git - r2c2.git/blob - source/libr2c2/arducontrol.h
Read power state from arducontrol device on startup
[r2c2.git] / source / libr2c2 / arducontrol.h
1 #ifndef LIBR2C2_ARDUCONTROL_H_
2 #define LIBR2C2_ARDUCONTROL_H_
3
4 #include <msp/core/mutex.h>
5 #include <msp/core/thread.h>
6 #include <msp/io/serial.h>
7 #include <msp/time/timedelta.h>
8 #include <msp/time/timestamp.h>
9 #include "driver.h"
10
11 namespace R2C2 {
12
13 class ArduControl: public Driver
14 {
15 private:
16         enum Command
17         {
18                 POWER_ON = 0x01,
19                 POWER_OFF = 0x02,
20                 READ_POWER_STATE = 0x03,
21                 READ_TRACK_CURRENT = 0x08,
22                 SET_OVERCURRENT_LIMIT = 0x09,
23                 READ_INPUT_VOLTAGE = 0x0A,
24                 MOTOROLA_SPEED = 0x11,
25                 MOTOROLA_REVERSE = 0x12,
26                 MOTOROLA_SPEED_DIRECTION = 0x13,
27                 MOTOROLA_SPEED_FUNCTION = 0x14,
28                 MOTOROLA_SOLENOID = 0x15,
29                 S88_READ = 0x30,
30                 COMMAND_OK = 0x80,
31                 RECEIVE_OVERRUN = 0x81,
32                 FRAMING_ERROR = 0x82,
33                 INVALID_COMMAND = 0x83,
34                 LENGTH_ERROR = 0x84,
35                 INVALID_VALUE = 0x85,
36                 OVERCURRENT = 0xA0,
37                 TRACK_CURRENT = 0xC0,
38                 INPUT_VOLTAGE = 0xC1,
39                 POWER_STATE = 0xC2,
40                 S88_DATA = 0xD0
41         };
42
43         struct Tag
44         {
45                 enum Type
46                 {
47                         NONE,
48                         GENERAL,
49                         LOCOMOTIVE,
50                         ACCESSORY,
51                         SENSOR
52                 };
53
54                 Type type;
55                 unsigned char command;
56                 unsigned short serial;
57                 unsigned id;
58
59                 Tag();
60
61                 operator bool() const { return type!=NONE; }
62         };
63
64         enum GeneralCommand
65         {
66                 POWER
67         };
68
69         enum Protocol
70         {
71                 MM
72         };
73
74         struct ProtocolInfo
75         {
76                 unsigned max_address;
77                 unsigned max_speed;
78                 unsigned max_func;
79         };
80
81         template<typename T>
82         struct ControlledVariable
83         {
84                 T current;
85                 T pending;
86                 unsigned short serial;
87
88                 ControlledVariable(): current(), pending(), serial(0) { }
89                 ControlledVariable(T v): current(v), pending(v), serial(0) { }
90
91                 bool set(T v) { if(v==pending) return false; pending = v; ++serial; return true; }
92                 bool commit(unsigned short s) { if(s!=serial) return false; current = pending; return true; }
93
94                 operator T() const { return current; }
95         };
96
97         struct Locomotive
98         {
99                 enum Command
100                 {
101                         SPEED,
102                         REVERSE,
103                         FUNCTIONS
104                 };
105
106                 unsigned id;
107                 Protocol proto;
108                 unsigned address;
109                 ControlledVariable<unsigned> speed;
110                 ControlledVariable<bool> reverse;
111                 ControlledVariable<unsigned> funcs;
112                 unsigned last_change_age;
113
114                 Locomotive(Protocol, unsigned);
115
116                 unsigned create_speed_dir_command(char *) const;
117                 unsigned create_speed_func_command(unsigned, char *) const;
118         };
119
120         struct Accessory
121         {
122                 enum Kind
123                 {
124                         TURNOUT,
125                         SIGNAL
126                 };
127
128                 enum Command
129                 {
130                         ACTIVATE,
131                         DEACTIVATE
132                 };
133
134                 Kind kind;
135                 unsigned address;
136                 unsigned bits;
137                 ControlledVariable<unsigned> state;
138                 unsigned target;
139                 Msp::Time::TimeDelta active_time;
140
141                 Accessory(Kind, unsigned, unsigned);
142
143                 unsigned create_state_command(unsigned, bool, char *) const;
144         };
145
146         struct Sensor
147         {
148                 enum Command
149                 {
150                         STATE
151                 };
152
153                 unsigned address;
154                 ControlledVariable<bool> state;
155
156                 Sensor(unsigned);
157         };
158
159         class ControlThread: public Msp::Thread
160         {
161         private:
162                 ArduControl &control;
163                 bool done;
164
165         public:
166                 ControlThread(ArduControl &);
167
168                 void exit();
169         private:
170                 virtual void main();
171         };
172
173         struct QueuedCommand
174         {
175                 Tag tag;
176                 char command[15];
177                 unsigned char length;
178
179                 QueuedCommand();
180                 QueuedCommand(GeneralCommand);
181                 QueuedCommand(Locomotive &, Locomotive::Command, unsigned = 0);
182                 QueuedCommand(Accessory &, Accessory::Command, unsigned = 0);
183         };
184
185         typedef std::map<unsigned, Locomotive> LocomotiveMap;
186         typedef std::list<Locomotive *> LocomotivePtrList;
187         typedef std::map<unsigned, Accessory> AccessoryMap;
188         typedef std::list<Accessory *> AccessoryPtrList;
189         typedef std::map<unsigned, Sensor> SensorMap;
190
191         Msp::IO::Serial serial;
192         bool debug;
193
194         ControlledVariable<bool> power;
195
196         LocomotiveMap locomotives;
197         LocomotivePtrList refresh_cycle;
198         LocomotivePtrList::iterator next_refresh;
199         unsigned refresh_counter;
200         AccessoryMap accessories;
201         AccessoryPtrList accessory_queue;
202         Accessory *active_accessory;
203         Msp::Time::TimeStamp off_timeout;
204         std::list<QueuedCommand> command_queue;
205         std::list<Tag> completed_commands;
206
207         SensorMap sensors;
208         unsigned n_s88_octets;
209
210         Msp::Mutex mutex;
211         ControlThread thread;
212
213         static ProtocolInfo protocol_info[2];
214
215 public:
216         ArduControl(const std::string &);
217         ~ArduControl();
218
219         virtual void set_power(bool);
220         virtual bool get_power() const { return power; }
221         virtual void halt(bool);
222         virtual bool is_halted() const { return false; }
223
224         virtual const char *enumerate_protocols(unsigned) const;
225 private:
226         static Protocol map_protocol(const std::string &);
227 public:
228         virtual unsigned get_protocol_speed_steps(const std::string &) const;
229
230         virtual unsigned add_loco(unsigned, const std::string &, const VehicleType &);
231         virtual void remove_loco(unsigned);
232         virtual void set_loco_speed(unsigned, unsigned);
233         virtual void set_loco_reverse(unsigned, bool);
234         virtual void set_loco_function(unsigned, unsigned, bool);
235 private:
236         void add_loco_to_refresh(Locomotive &);
237         void remove_loco_from_refresh(Locomotive &);
238         Locomotive *get_loco_to_refresh();
239         void advance_next_refresh();
240
241 public:
242         virtual unsigned add_turnout(unsigned, const TrackType &);
243         virtual void remove_turnout(unsigned);
244         virtual void set_turnout(unsigned, unsigned);
245         virtual unsigned get_turnout(unsigned) const;
246
247         virtual unsigned add_signal(unsigned, const SignalType &);
248         virtual void remove_signal(unsigned);
249         virtual void set_signal(unsigned, unsigned);
250         virtual unsigned get_signal(unsigned) const;
251
252 private:
253         unsigned add_accessory(Accessory::Kind, unsigned, unsigned);
254         void remove_accessory(Accessory::Kind, unsigned);
255         void set_accessory(Accessory::Kind, unsigned, unsigned);
256         unsigned get_accessory(Accessory::Kind, unsigned) const;
257
258 public:
259         virtual unsigned add_sensor(unsigned);
260         virtual void remove_sensor(unsigned);
261         virtual void set_sensor(unsigned, bool) { }
262         virtual bool get_sensor(unsigned) const;
263
264         virtual void tick();
265         virtual void flush();
266
267 private:
268         void push_command(const QueuedCommand &);
269         bool pop_command(QueuedCommand &);
270         void push_completed_tag(const Tag &);
271         Tag pop_completed_tag();
272 };
273
274 } // namespace R2C2
275
276 #endif