PDU.h
Go to the documentation of this file.
1 
20 #pragma once
21 
22 #include "Exception.h"
23 #include "Function.h"
24 
25 namespace IO
26 {
27 namespace Modbus
28 {
29 #define ATTR_PACKED __attribute__((aligned(1), packed))
30 
47 struct PDU {
48  /*
49  * Data is packed as some fields are misaligned.
50  *
51  * MODBUS sends 16-bit values MSB first, so appropriate byte-swapping is handled by the driver.
52  * Other than that, the data is un-modified.
53  */
54  union Data {
55  // For exception response
57 
58  // ReadCoils = 0x01
59  union ReadCoils {
63  };
64 
67  uint8_t coilStatus[250];
68  static constexpr uint16_t MaxCoils{sizeof(coilStatus) * 8};
69 
70  void setCoil(uint16_t coil, bool value)
71  {
72  if(coil < MaxCoils) {
73  setBit(coilStatus, coil, value);
74  }
75  }
76 
77  void setCount(uint16_t count)
78  {
79  byteCount = (count + 7) / 8;
80  }
81 
82  // This figure may be larger than the actual coil count
84  {
85  return byteCount * 8;
86  }
87  };
88 
91  };
93 
94  // ReadDiscreteInputs = 0x02
99  };
100 
103  uint8_t inputStatus[250];
104  static constexpr uint16_t MaxInputs{sizeof(inputStatus) * 8};
105 
106  void setInput(uint16_t input, bool value)
107  {
108  if(input < MaxInputs) {
109  setBit(inputStatus, input, value);
110  }
111  }
112 
113  void setCount(uint16_t count)
114  {
115  byteCount = (count + 7) / 8;
116  }
117 
118  // This figure may be larger than the actual input count
120  {
121  return byteCount * 8;
122  }
123  };
124 
127  };
129 
130  // 16-bit access
131  // ReadHoldingRegisters = 0x03,
136  };
137 
139  static constexpr uint16_t MaxRegisters{250 / 2};
141  uint16_t values[MaxRegisters];
142 
143  void setCount(uint16_t count)
144  {
145  byteCount = count * 2;
146  }
147 
149  {
150  return byteCount / 2;
151  }
152  };
153 
156  };
158 
159  // ReadInputRegisters = 0x04,
164  };
165 
167  static constexpr uint16_t MaxRegisters{250 / 2};
169  uint16_t values[MaxRegisters];
170 
171  void setCount(uint16_t count)
172  {
173  byteCount = std::min(count, MaxRegisters) * 2;
174  }
175 
177  {
178  return byteCount / 2;
179  }
180  };
181 
184  };
186 
187  // WriteSingleCoil = 0x05,
190  enum State : uint16_t {
191  state_off = 0x0000,
192  state_on = 0xFF00,
193  };
194 
197  };
198 
199  using Response = Request;
200 
203  };
205 
206  // WriteSingleRegister = 0x06,
211  };
212 
213  using Response = Request;
214 
217  };
219 
220  // ReadExceptionStatus = 0x07,
224  };
225 
227  };
229 
230  // GetComEventCounter = 0x0b,
235  };
236 
238  };
240 
241  // GetComEventLog = 0x0c,
244  static constexpr uint16_t MaxEvents{64};
249  uint8_t events[MaxEvents];
250 
252  {
253  eventCount = std::min(count, MaxEvents);
254  byteCount = 7 + eventCount;
255  }
256  };
257 
259  };
261 
262  // WriteMultipleCoils = 0x0f,
268  uint8_t values[246];
269  static constexpr uint16_t MaxCoils{sizeof(values) * 8};
270 
271  void setCoil(uint16_t coil, bool state)
272  {
273  if(coil < MaxCoils) {
274  setBit(values, coil, state);
275  }
276  }
277 
278  void setCount(uint16_t count)
279  {
280  quantityOfOutputs = std::min(count, MaxCoils);
281  byteCount = (quantityOfOutputs + 7) / 8;
282  }
283  };
284 
288  };
289 
292  };
294 
295  // WriteMultipleRegisters = 0x10,
298  static constexpr uint16_t MaxRegisters{123};
302  uint16_t values[MaxRegisters];
303 
304  void setCount(uint16_t count)
305  {
306  quantityOfRegisters = std::min(count, MaxRegisters);
307  byteCount = quantityOfRegisters * 2;
308  }
309  };
310 
314  };
315 
318  };
320 
321  // ReportServerId = 0x11,
325  runstatus_off = 0x00,
326  runstatus_on = 0xFF,
327  };
328 
332  uint8_t data[248];
333 
334  void setCount(uint8_t dataSize)
335  {
336  byteCount = 2 + dataSize;
337  }
338 
340  {
341  return byteCount - 2;
342  }
343  };
344 
346  };
348 
349  // MaskWriteRegister = 0x16,
355  };
356  using Response = Request;
357 
360  };
362 
363  // ReadWriteMultipleRegisters = 0x17,
366  static constexpr uint16_t MaxWriteRegisters{121};
372  uint16_t writeValues[MaxWriteRegisters];
373 
375  {
376  quantityToWrite = std::min(count, MaxWriteRegisters);
377  writeByteCount = quantityToWrite * 2;
378  }
379  };
381  static constexpr uint16_t MaxReadRegisters{125};
383  uint16_t values[MaxReadRegisters];
384 
385  void setCount(uint16_t count)
386  {
387  byteCount = count * 2;
388  }
389 
391  {
392  return byteCount / 2;
393  }
394  };
395 
398  };
400  };
401 
402  Function function() const
403  {
404  return Function(functionCode & 0x7f);
405  }
406 
407  void setFunction(Function function)
408  {
409  functionCode = uint8_t(function);
410  }
411 
413  {
414  functionCode |= 0x80;
415  data.exceptionCode = uint8_t(exception);
416  }
417 
418  bool exceptionFlag() const
419  {
420  return functionCode & 0x80;
421  }
422 
424  {
426  }
427 
432  void swapRequestByteOrder();
433  void swapResponseByteOrder();
441  size_t getRequestSize() const
442  {
443  return 1 + getRequestDataSize(); // function + data
444  }
445 
446  size_t getResponseSize() const
447  {
448  return 1 + getResponseDataSize(); // function + data
449  }
452  /* Structure content */
453 
456 
457 private:
458  size_t getRequestDataSize() const;
459  size_t getResponseDataSize() const;
460 
461  static void setBit(uint8_t* values, uint16_t number, bool state)
462  {
463  uint8_t mask = 1 << (number % 8);
464  if(state) {
465  values[number / 8] |= mask;
466  } else {
467  values[number / 8] &= ~mask;
468  }
469  }
470 };
471 
472 static_assert(offsetof(PDU, data) == 1, "PDU alignment error");
473 
474 } // namespace Modbus
475 } // namespace IO
size_t getRequestSize() const
Definition: PDU.h:441
Protocol Data Unit.
Definition: PDU.h:47
Response response
Definition: PDU.h:345
MaskWriteRegister maskWriteRegister
Definition: PDU.h:361
Response response
Definition: PDU.h:155
Response response
Definition: PDU.h:226
size_t getResponseSize() const
Definition: PDU.h:446
Function
Definition: IOControl/include/IO/Modbus/Function.h:47
void setCount(uint16_t count)
Definition: PDU.h:77
uint16_t getCount() const
Definition: PDU.h:390
uint8_t getCount() const
Definition: PDU.h:339
#define ATTR_PACKED
Definition: PDU.h:29
uint16_t getCount() const
Definition: PDU.h:119
Response response
Definition: PDU.h:317
uint8_t byteCount
Calculated.
Definition: PDU.h:301
ReadExceptionStatus readExceptionStatus
Definition: PDU.h:228
uint16_t startAddress
Definition: PDU.h:61
Request request
Definition: PDU.h:89
Request request
Definition: PDU.h:290
uint16_t quantityOfRegisters
Definition: PDU.h:163
uint16_t quantityOfCoils
Definition: PDU.h:62
uint8_t exceptionCode
Definition: PDU.h:56
Exception
Modbus exception codes returned in response packets.
Definition: Exception.h:31
Definition: IOControl/include/IO/Controller.h:25
uint16_t getCount() const
Definition: PDU.h:148
uint16_t eventCount
Definition: PDU.h:247
void setFunction(Function function)
Definition: PDU.h:407
uint8_t byteCount
Calculated.
Definition: PDU.h:245
GetComEventLog getComEventLog
Definition: PDU.h:260
Response response
Definition: PDU.h:202
ReadDiscreteInputs readDiscreteInputs
Definition: PDU.h:128
uint16_t quantityOfOutputs
Definition: PDU.h:266
WriteMultipleCoils writeMultipleCoils
Definition: PDU.h:293
void swapRequestByteOrder()
void setCount(uint16_t count)
Definition: PDU.h:171
void setCount(uint16_t count)
Definition: PDU.h:113
uint16_t getCount() const
Definition: PDU.h:83
void swapResponseByteOrder()
Request request
Definition: PDU.h:125
Request request
Definition: PDU.h:154
Exception exception() const
Definition: PDU.h:423
bool exceptionFlag() const
Definition: PDU.h:418
GetComEventCounter getComEventCounter
Definition: PDU.h:239
void setInput(uint16_t input, bool value)
Definition: PDU.h:106
uint8_t functionCode
Definition: PDU.h:454
void setCount(uint8_t dataSize)
Definition: PDU.h:334
void setWriteCount(uint16_t count)
Definition: PDU.h:374
uint16_t getCount() const
Definition: PDU.h:176
uint8_t writeByteCount
Calculated.
Definition: PDU.h:371
uint8_t byteCount
Use setCount()
Definition: PDU.h:66
void setCount(uint16_t count)
Definition: PDU.h:143
Response response
Definition: PDU.h:359
void setCoil(uint16_t coil, bool value)
Definition: PDU.h:70
uint8_t byteCount
Calculated.
Definition: PDU.h:140
Response response
Definition: PDU.h:216
Request request
Definition: PDU.h:182
Request request
Definition: PDU.h:316
Request request
Definition: PDU.h:201
Response response
Definition: PDU.h:291
ReadHoldingRegisters readHoldingRegisters
Definition: PDU.h:157
Response response
Definition: PDU.h:90
ReadWriteMultipleRegisters readWriteMultipleRegisters
Definition: PDU.h:399
void setCount(uint16_t count)
Definition: PDU.h:304
Response response
Definition: PDU.h:183
Request request
Definition: PDU.h:215
void setCoil(uint16_t coil, bool state)
Definition: PDU.h:271
WriteSingleRegister writeSingleRegister
Definition: PDU.h:218
Response response
Definition: PDU.h:126
WriteSingleCoil writeSingleCoil
Definition: PDU.h:204
ReportServerId reportServerId
Definition: PDU.h:347
Data data
Definition: PDU.h:455
Definition: PDU.h:54
void setException(Exception exception)
Definition: PDU.h:412
No exception, transaction completed normally.
uint16_t outputAddress
Definition: PDU.h:195
WriteMultipleRegisters writeMultipleRegisters
Definition: PDU.h:319
Request request
Definition: PDU.h:358
uint8_t byteCount
Calculated.
Definition: PDU.h:168
Response response
Definition: PDU.h:258
void setCount(uint16_t count)
Definition: PDU.h:385
Response response
Definition: PDU.h:237
uint8_t byteCount
Calculated.
Definition: PDU.h:102
RunStatus runStatus
Definition: PDU.h:331
uint16_t quantityOfOutputs
Definition: PDU.h:287
uint8_t byteCount
Calculated.
Definition: PDU.h:267
uint16_t quantityOfRegisters
Definition: PDU.h:135
void setCount(uint16_t count)
Definition: PDU.h:278
ReadCoils readCoils
Definition: PDU.h:92
ReadInputRegisters readInputRegisters
Definition: PDU.h:185
uint16_t messageCount
Definition: PDU.h:248
void setEventCount(uint16_t count)
Definition: PDU.h:251