Open Lighting Architecture  Latest Git
DmxTriWidget.h
1 /*
2  * This program is free software; you can redistribute it and/or modify
3  * it under the terms of the GNU General Public License as published by
4  * the Free Software Foundation; either version 2 of the License, or
5  * (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  * GNU Library General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software
14  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
15  *
16  * DmxTriWidget.h
17  * The Jese DMX-TRI/RDM-TRI widget.
18  * Copyright (C) 2010 Simon Newton
19  */
20 
21 #ifndef PLUGINS_USBPRO_DMXTRIWIDGET_H_
22 #define PLUGINS_USBPRO_DMXTRIWIDGET_H_
23 
24 #include <map>
25 #include <string>
26 #include <queue>
27 #include "ola/Callback.h"
28 #include "ola/DmxBuffer.h"
31 #include "ola/rdm/UIDSet.h"
32 #include "ola/thread/SchedulerInterface.h"
33 #include "plugins/usbpro/BaseUsbProWidget.h"
34 
35 namespace ola {
36 namespace plugin {
37 namespace usbpro {
38 
39 /*
40  * A DMX TRI Widget implementation. We separate the Widget from the
41  * implementation so we can leverage the QueueingRDMController.
42  */
45  public:
47  ola::io::ConnectedDescriptor *descriptor,
48  bool use_raw_rdm);
50 
51  void UseRawRDM(bool use_raw_rdm) { m_use_raw_rdm = use_raw_rdm; }
52 
53  void Stop();
54 
55  bool SendDMX(const DmxBuffer &buffer);
57  ola::rdm::RDMCallback *on_complete);
60 
61  private:
62  typedef enum {
63  SINGLE_TX_COMMAND_ID = 0x21,
64  DISCOVER_AUTO_COMMAND_ID = 0x33,
65  DISCOVER_STATUS_COMMAND_ID = 0x34,
66  REMOTE_UID_COMMAND_ID = 0x35,
67  RAW_RDM_COMMAND_ID = 0x37,
68  REMOTE_GET_COMMAND_ID = 0x38,
69  REMOTE_SET_COMMAND_ID = 0x39,
70  QUEUED_GET_COMMAND_ID = 0x3a,
71  SET_FILTER_COMMAND_ID = 0x3d,
72 
73  RESERVED_COMMAND_ID = 0xff,
74  } TriCommandId;
75 
76  typedef enum {
77  NO_DISCOVERY_ACTION,
78  DISCOVER_AUTO_REQUIRED,
79  DISCOVER_STATUS_REQUIRED,
80  FETCH_UID_REQUIRED,
81  } TriDiscoveryState;
82 
83  typedef std::map<ola::rdm::UID, uint8_t> UIDToIndexMap;
84 
86  UIDToIndexMap m_uid_index_map;
87  uint8_t m_uid_count;
88  uint16_t m_last_esta_id;
89  bool m_use_raw_rdm;
90 
91  // State for sending DMX
92  DmxBuffer m_outgoing_dmx;
93 
94  // State for handling RDM discovery
95  ola::thread::timeout_id m_disc_stat_timeout_id;
96  ola::rdm::RDMDiscoveryCallback *m_discovery_callback;
97  TriDiscoveryState m_discovery_state;
98 
99  // State for sending RDM Gets/Sets
100  // This holds pointers to the RDMRequest and Callback that is queued or in
101  // flight.
102  ola::rdm::RDMCallback *m_rdm_request_callback;
103  std::auto_ptr<ola::rdm::RDMRequest> m_pending_rdm_request;
104  uint8_t m_transaction_number;
105  // The command id that we expect to see in the response.
106  uint8_t m_last_command, m_expected_command;
107 
108  void SendDMXBuffer();
109  void SendQueuedRDMCommand();
110  void RunDiscoveryCallback(ola::rdm::RDMDiscoveryCallback *callback);
111  bool CheckDiscoveryStatus();
112  void HandleMessage(uint8_t label,
113  const uint8_t *data,
114  unsigned int length);
115  void SendDiscoveryAuto();
116  void SendDiscoveryStat();
117  void FetchNextUID();
118  void SendRawRDMRequest();
119  void DispatchRequest();
120  void DispatchQueuedGet();
121  void StopDiscovery();
122 
123  void HandleSingleTXResponse(uint8_t return_code);
124  void HandleDiscoveryAutoResponse(uint8_t return_code,
125  const uint8_t *data,
126  unsigned int length);
127  void HandleDiscoverStatResponse(uint8_t return_code,
128  const uint8_t *data,
129  unsigned int length);
130  void HandleRemoteUIDResponse(uint8_t return_code,
131  const uint8_t *data,
132  unsigned int length);
133  void HandleRawRDMResponse(uint8_t return_code,
134  const uint8_t *data,
135  unsigned int length);
136  void HandleRemoteRDMResponse(uint8_t return_code,
137  const uint8_t *data,
138  unsigned int length);
139  void HandleQueuedGetResponse(uint8_t return_code,
140  const uint8_t *data,
141  unsigned int length);
142  void HandleGenericRDMResponse(uint8_t return_code,
143  uint16_t pid,
144  const uint8_t *data,
145  unsigned int length);
146  void HandleSetFilterResponse(uint8_t return_code,
147  const uint8_t *data,
148  unsigned int length);
149  bool PendingTransaction() const;
150  void MaybeSendNextRequest();
151  void HandleRDMError(ola::rdm::RDMStatusCode error_code);
152  bool SendCommandToTRI(uint8_t label, const uint8_t *data,
153  unsigned int length);
154  bool TriToOlaReturnCode(uint8_t return_code,
156  bool ReturnCodeToNackReason(uint8_t return_code,
157  ola::rdm::rdm_nack_reason *reason);
158 
159  typedef enum {
160  EC_NO_ERROR = 0,
161  EC_CONSTRAINT = 1,
162  EC_UNKNOWN_COMMAND = 2,
163  EC_INVALID_OPTION = 3,
164  EC_FRAME_FORMAT = 4,
165  EC_DATA_TOO_LONG = 5,
166  EC_DATA_MISSING = 6,
167  EC_SYSTEM_MODE = 7,
168  EC_SYSTEM_BUSY = 8,
169  EC_DATA_CHECKSUM = 0x0a,
170  EC_INCOMPATIBLE = 0x0b,
171  EC_RESPONSE_TIME = 0x10,
172  EC_RESPONSE_WAIT = 0x11,
173  EC_RESPONSE_MORE = 0x12,
174  EC_RESPONSE_TRANSACTION = 0x13,
175  EC_RESPONSE_SUB_DEVICE = 0x14,
176  EC_RESPONSE_FORMAT = 0x15,
177  EC_RESPONSE_CHECKSUM = 0x16,
178  EC_RESPONSE_NONE = 0x18,
179  EC_RESPONSE_IDENTITY = 0x1a,
180  EC_RESPONSE_MUTE = 0x1b,
181  EC_RESPONSE_DISCOVERY = 0x1c,
182  EC_RESPONSE_UNEXPECTED = 0x1d,
183  EC_UNKNOWN_PID = 0x20,
184  EC_FORMAT_ERROR = 0x21,
185  EC_HARDWARE_FAULT = 0x22,
186  EC_PROXY_REJECT = 0x23,
187  EC_WRITE_PROTECT = 0x24,
188  EC_UNSUPPORTED_COMMAND_CLASS = 0x25,
189  EC_OUT_OF_RANGE = 0x26,
190  EC_BUFFER_FULL = 0x27,
191  EC_FRAME_OVERFLOW = 0x28,
192  EC_SUBDEVICE_UNKNOWN = 0x29,
193  EC_PROXY_BUFFER_FULL = 0x2a, // this isn't included in the docs
194  EC_ACTION_NOT_SUPPORTED = 0x2b, // this is a guess
195  EC_ENDPOINT_NUMBER_INVALID = 0x2c, // this is a guess
196  EC_INVALID_ENDPOINT_MODE = 0x2d, // this is a guess
197  EC_UNKNOWN_UID = 0x2e, // this is a guess
198  EC_UNKNOWN_SCOPE = 0x2f, // this is a guess
199  EC_INVALID_STATIC_CONFIG_TYPE = 0x30, // this is a guess
200  EC_INVALID_IPV4_ADDRESS = 0x31, // this is a guess
201  EC_INVALID_IPV6_ADDRESS = 0x32, // this is a guess
202  EC_INVALID_PORT = 0x33 // this is a guess
203  } dmx_tri_error_codes;
204  // TODO(Peter): try and test the guessed values
205 
206  static const unsigned int DATA_OFFSET = 2; // first two bytes are CI & RC
207  static const uint8_t EXTENDED_COMMAND_LABEL = 88; // 'X'
208 
209  // The ms delay between checking on the RDM discovery process
210  static const unsigned int RDM_STATUS_INTERVAL_MS = 100;
211 };
212 
213 
214 /*
215  * A DMX TRI Widget
216  */
219  public:
221  ola::io::ConnectedDescriptor *descriptor,
222  unsigned int queue_size = 20,
223  bool use_raw_rdm = false);
224  ~DmxTriWidget();
225  void UseRawRDM(bool use_raw_rdm) { m_impl->UseRawRDM(use_raw_rdm); }
226 
227  void Stop() { m_impl->Stop(); }
228 
229  bool SendDMX(const DmxBuffer &buffer) const {
230  return m_impl->SendDMX(buffer);
231  }
232 
234  ola::rdm::RDMCallback *on_complete) {
235  m_controller->SendRDMRequest(request, on_complete);
236  }
237 
239  m_controller->RunFullDiscovery(callback);
240  }
241 
243  m_controller->RunIncrementalDiscovery(callback);
244  }
245 
246  ola::io::ConnectedDescriptor *GetDescriptor() const {
247  return m_impl->GetDescriptor();
248  }
249 
250  private:
251  // we need to control the order of construction & destruction here so these
252  // are pointers.
253  DmxTriWidgetImpl *m_impl;
255 
256  void ResumeRDMCommands() {
257  m_controller->Resume();
258  }
259 };
260 } // namespace usbpro
261 } // namespace plugin
262 } // namespace ola
263 #endif // PLUGINS_USBPRO_DMXTRIWIDGET_H_
Definitions and Interfaces to implement an RDMController that sends a single message at a time...
void Stop()
Definition: DmxTriWidget.cpp:96
void SendRDMRequest(ola::rdm::RDMRequest *request, ola::rdm::RDMCallback *on_complete)
Send a RDM command.
Definition: DmxTriWidget.h:233
RDMStatusCode
RDM Status Codes.
Definition: RDMResponseCodes.h:45
bool SendDMX(const DmxBuffer &buffer)
Definition: DmxTriWidget.cpp:119
void RunFullDiscovery(ola::rdm::RDMDiscoveryCallback *callback)
Definition: DmxTriWidget.cpp:162
void Resume()
Definition: QueueingRDMController.cpp:87
A BidirectionalFileDescriptor that also generates notifications when closed.
Definition: Descriptor.h:282
Definition: DmxTriWidget.h:43
The interface that can send RDM commands, as well as perform discovery operations.
Definition: RDMControllerInterface.h:104
RDM Commands that represent requests (GET, SET or DISCOVER).
Definition: RDMCommand.h:234
void RunIncrementalDiscovery(ola::rdm::RDMDiscoveryCallback *callback)
Definition: DmxTriWidget.cpp:171
Used to hold a single universe of DMX data.
Definition: DmxBuffer.h:49
Definition: BaseUsbProWidget.h:40
A set of UIDs.
void * timeout_id
A timeout handle which can later be used to cancel a timeout.
Definition: SchedulerInterface.h:34
A class used to hold a single universe of DMX data.
void RunIncrementalDiscovery(ola::rdm::RDMDiscoveryCallback *callback)
Start an incremental discovery operation.
Definition: DmxTriWidget.h:242
void SendRDMRequest(ola::rdm::RDMRequest *request, ola::rdm::RDMCallback *on_complete)
Send a RDM command.
Definition: DmxTriWidget.cpp:136
An RDM Controller that queues messages and only sends a single message at a time. ...
Definition: SerialWidgetInterface.h:38
The base class for all 1 argument callbacks.
Definition: Callback.h:982
Definition: QueueingRDMController.h:88
Definition: DmxTriWidget.h:217
The namespace containing all OLA symbols.
Definition: Credentials.cpp:44
Allows Callbacks to be scheduled to run after a specified interval.
Definition: SchedulerInterface.h:46
void RunFullDiscovery(ola::rdm::RDMDiscoveryCallback *callback)
Start a full discovery operation.
Definition: DmxTriWidget.h:238