knx
ETS configurable knx-stack
table_object.cpp
Go to the documentation of this file.
1 #include <string.h>
2 
3 #include "table_object.h"
4 #include "bits.h"
5 #include "memory.h"
6 #include "callback_property.h"
7 #include "data_property.h"
8 
10 uint8_t TableObject::_tableUnloadCount = 0;
11 
13 {
14  _beforeTablesUnload = func;
15 }
16 
18 {
19  return _beforeTablesUnload;
20 }
21 
22 TableObject::TableObject(Memory& memory, uint32_t staticTableAdr, uint32_t staticTableSize)
23  : _memory(memory)
24 {
25  _staticTableAdr = staticTableAdr;
26  _staticTableSize = staticTableSize;
27 }
28 
30 {}
31 
33 {
34  if (newState == LS_LOADED && _tableUnloadCount > 0)
35  _tableUnloadCount--;
36 
37  if (_tableUnloadCount > 0)
38  return;
39 
40  if (newState == LS_UNLOADED)
41  {
42  _tableUnloadCount++;
43 
44  if (_beforeTablesUnload != 0)
46  }
47 }
48 
50 {
51  return _state;
52 }
53 
54 void TableObject::loadState(LoadState newState)
55 {
56  if (newState == _state)
57  return;
58 
59  beforeStateChange(newState);
60  _state = newState;
61 }
62 
63 
64 uint8_t* TableObject::save(uint8_t* buffer)
65 {
66  //println("TableObject::save");
67  allocTableStatic();
68 
69  buffer = pushByte(_state, buffer);
70 
71  buffer = pushInt(_size, buffer);
72 
73  if (_data)
74  buffer = pushInt(_memory.toRelative(_data), buffer);
75  else
76  buffer = pushInt(0, buffer);
77 
78  return InterfaceObject::save(buffer);
79 }
80 
81 
82 const uint8_t* TableObject::restore(const uint8_t* buffer)
83 {
84  //println("TableObject::restore");
85 
86  uint8_t state = 0;
87  buffer = popByte(state, buffer);
88  _state = (LoadState)state;
89 
90  buffer = popInt(_size, buffer);
91 
92  uint32_t relativeAddress = 0;
93  buffer = popInt(relativeAddress, buffer);
94  //println(relativeAddress);
95 
96  if (relativeAddress != 0)
97  _data = _memory.toAbsolute(relativeAddress);
98  else
99  _data = 0;
100 
101  //println((uint32_t)_data);
102  return InterfaceObject::restore(buffer);
103 }
104 
105 uint32_t TableObject::tableReference()
106 {
107  return (uint32_t)_memory.toRelative(_data);
108 }
109 
110 bool TableObject::allocTable(uint32_t size, bool doFill, uint8_t fillByte)
111 {
112  if (_staticTableAdr)
113  return false;
114 
115  if (_data)
116  {
117  _memory.freeMemory(_data);
118  _data = 0;
119  }
120 
121  if (size == 0)
122  return true;
123 
124  _data = _memory.allocMemory(size);
125 
126  if (!_data)
127  return false;
128 
129  if (doFill)
130  {
131  uint32_t addr = _memory.toRelative(_data);
132 
133  for (uint32_t i = 0; i < size; i++)
134  _memory.writeMemory(addr + i, 1, &fillByte);
135  }
136 
137  _size = size;
138 
139  return true;
140 }
141 
142 
143 void TableObject::allocTableStatic()
144 {
145  if (_staticTableAdr && !_data)
146  {
147  _data = _memory.toAbsolute(_staticTableAdr);
148  _size = _staticTableSize;
149  _memory.addNewUsedBlock(_data, _size);
150  }
151 }
152 
153 void TableObject::loadEvent(const uint8_t* data)
154 {
155  //printHex("TableObject::loadEvent 0x", data, 10);
156  switch (_state)
157  {
158  case LS_UNLOADED:
159  loadEventUnloaded(data);
160  break;
161 
162  case LS_LOADING:
163  loadEventLoading(data);
164  break;
165 
166  case LS_LOADED:
167  loadEventLoaded(data);
168  break;
169 
170  case LS_ERROR:
171  loadEventError(data);
172  break;
173 
174  default:
175  /* do nothing */
176  break;
177  }
178 }
179 
180 void TableObject::loadEventUnloaded(const uint8_t* data)
181 {
182  uint8_t event = data[0];
183 
184  switch (event)
185  {
186  case LE_NOOP:
187  case LE_LOAD_COMPLETED:
189  case LE_UNLOAD:
190  break;
191 
192  case LE_START_LOADING:
194  break;
195 
196  default:
199  }
200 }
201 
202 void TableObject::loadEventLoading(const uint8_t* data)
203 {
204  uint8_t event = data[0];
205 
206  switch (event)
207  {
208  case LE_NOOP:
209  case LE_START_LOADING:
210  break;
211 
212  case LE_LOAD_COMPLETED:
215  break;
216 
217  case LE_UNLOAD:
219  break;
220 
222  additionalLoadControls(data);
223  break;
224 
225  default:
228  }
229 }
230 
231 void TableObject::loadEventLoaded(const uint8_t* data)
232 {
233  uint8_t event = data[0];
234 
235  switch (event)
236  {
237  case LE_NOOP:
238  case LE_LOAD_COMPLETED:
239  break;
240 
241  case LE_START_LOADING:
243  break;
244 
245  case LE_UNLOAD:
247 
248  //free nv memory
249  if (_data)
250  {
251  if (!_staticTableAdr)
252  {
253  _memory.freeMemory(_data);
254  _data = 0;
255  }
256  }
257 
258  break;
259 
263  break;
264 
265  default:
268  }
269 }
270 
271 void TableObject::loadEventError(const uint8_t* data)
272 {
273  uint8_t event = data[0];
274 
275  switch (event)
276  {
277  case LE_NOOP:
278  case LE_LOAD_COMPLETED:
280  case LE_START_LOADING:
281  break;
282 
283  case LE_UNLOAD:
285  break;
286 
287  default:
290  }
291 }
292 
293 void TableObject::additionalLoadControls(const uint8_t* data)
294 {
295  if (data[1] != 0x0B) // Data Relative Allocation
296  {
299  return;
300  }
301 
302  size_t size = ((data[2] << 24) | (data[3] << 16) | (data[4] << 8) | data[5]);
303  bool doFill = data[6] == 0x1;
304  uint8_t fillByte = data[7];
305 
306  if (!allocTable(size, doFill, fillByte))
307  {
310  }
311 }
312 
314 {
315  return _data;
316 }
317 
319 {
320  uint8_t data = errorCode;
322  prop->write(data);
323 }
324 
326 {
327  return 5 + InterfaceObject::saveSize() + sizeof(_size);
328 }
329 
330 void TableObject::initializeProperties(size_t propertiesSize, Property** properties)
331 {
332  Property* ownProperties[] =
333  {
335  [](TableObject * obj, uint16_t start, uint8_t count, uint8_t* data) -> uint8_t {
336  if (start == 0)
337  {
338  uint16_t currentNoOfElements = 1;
339  pushWord(currentNoOfElements, data);
340  return 1;
341  }
342 
343  data[0] = obj->_state;
344  return 1;
345  },
346  [](TableObject * obj, uint16_t start, uint8_t count, const uint8_t* data) -> uint8_t {
347  obj->loadEvent(data);
348  return 1;
349  })
350  };
351 
352  uint8_t ownPropertiesCount = sizeof(ownProperties) / sizeof(Property*);
353 
354  uint8_t propertyCount = propertiesSize / sizeof(Property*);
355  uint8_t allPropertiesCount = propertyCount + ownPropertiesCount;
356 
357  Property* allProperties[allPropertiesCount];
358  memcpy(allProperties, properties, propertiesSize);
359  memcpy(allProperties + propertyCount, ownProperties, sizeof(ownProperties));
360 
361  if (_staticTableAdr)
362  InterfaceObject::initializeProperties(sizeof(allProperties), allProperties);
363  else
364  initializeDynTableProperties(sizeof(allProperties), allProperties);
365 }
366 
367 void TableObject::initializeDynTableProperties(size_t propertiesSize, Property** properties)
368 {
369  Property* ownProperties[] =
370  {
372  [](TableObject * obj, uint16_t start, uint8_t count, uint8_t* data) -> uint8_t {
373  if (start == 0)
374  {
375  uint16_t currentNoOfElements = 1;
376  pushWord(currentNoOfElements, data);
377  return 1;
378  }
379 
380  if (obj->_state == LS_UNLOADED)
381  pushInt(0, data);
382  else
383  pushInt(obj->tableReference(), data);
384  return 1;
385  }),
387  [](TableObject * obj, uint16_t start, uint8_t count, uint8_t* data) -> uint8_t {
388  if (obj->_state != LS_LOADED)
389  return 0; // need to check return code for invalid
390 
391  uint32_t segmentSize = obj->_size;
392  uint16_t crc16 = crc16Ccitt(obj->data(), segmentSize);
393 
394  pushInt(segmentSize, data); // Segment size
395  pushByte(0x00, data + 4); // CRC control byte -> 0: always valid
396  pushByte(0xFF, data + 5); // Read access 4 bits + Write access 4 bits
397  pushWord(crc16, data + 6); // CRC-16 CCITT of data
398 
399  return 1;
400  }),
401  new DataProperty(PID_ERROR_CODE, false, PDT_ENUM8, 1, ReadLv3 | WriteLv0, (uint8_t)E_NO_FAULT)
402  };
403 
404  uint8_t ownPropertiesCount = sizeof(ownProperties) / sizeof(Property*);
405 
406  uint8_t propertyCount = propertiesSize / sizeof(Property*);
407  uint8_t allPropertiesCount = propertyCount + ownPropertiesCount;
408 
409  Property* allProperties[allPropertiesCount];
410  memcpy(allProperties, properties, propertiesSize);
411  memcpy(allProperties + propertyCount, ownProperties, sizeof(ownProperties));
412 
413  InterfaceObject::initializeProperties(sizeof(allProperties), allProperties);
414 }
const uint8_t * popByte(uint8_t &b, const uint8_t *data)
Definition: bits.cpp:4
uint8_t * pushInt(uint32_t i, uint8_t *data)
Definition: bits.cpp:72
uint8_t * pushWord(uint16_t w, uint8_t *data)
Definition: bits.cpp:64
uint8_t * pushByte(uint8_t b, uint8_t *data)
Definition: bits.cpp:57
const uint8_t * popInt(uint32_t &i, const uint8_t *data)
Definition: bits.cpp:41
uint16_t crc16Ccitt(uint8_t *input, uint16_t length)
Definition: bits.cpp:133
uint8_t * save(uint8_t *buffer) override
This method is called when the object should save its state to the buffer.
const uint8_t * restore(const uint8_t *buffer) override
This method is called when the object should restore its state from the buffer.
virtual void state(PropertyID id, uint8_t *data, uint8_t length, uint8_t *resultData, uint8_t &resultLength)
Get state of a function property of the interface object.
virtual void initializeProperties(size_t propertiesSize, Property **properties)
Intializes the Property-array the the supplied values.
uint16_t saveSize() override
Property * property(PropertyID id)
Gets property with PropertyID id if it exists and nullptr otherwise.
Definition: memory.h:37
void freeMemory(uint8_t *ptr)
Definition: memory.cpp:279
uint8_t * toAbsolute(uint32_t relativeAddress)
Definition: memory.cpp:326
uint32_t toRelative(uint8_t *absoluteAddress)
Definition: memory.cpp:332
void saveMemory()
Definition: memory.cpp:198
uint8_t * allocMemory(size_t size)
Definition: memory.cpp:230
void writeMemory()
Definition: memory.cpp:137
virtual uint8_t write(uint16_t start, uint8_t count, const uint8_t *data)=0
This class provides common functionality for interface objects that are configured by ETS with MemorW...
Definition: table_object.h:13
void initializeProperties(size_t propertiesSize, Property **properties) override
Intializes the Property-array the the supplied values.
LoadState loadState()
This method returns the LoadState of the interface object.
Memory & _memory
Definition: table_object.h:60
virtual ~TableObject()
The destructor.
static BeforeTablesUnloadCallback _beforeTablesUnload
Definition: table_object.h:58
static BeforeTablesUnloadCallback beforeTablesUnloadCallback()
uint8_t * data()
returns the internal data of the interface object.
virtual void beforeStateChange(LoadState &newState)
This method is called before the interface object enters a new LoadState.
void errorCode(ErrorCode errorCode)
Set the reason for a state change failure.
const uint8_t * restore(const uint8_t *buffer) override
This method is called when the object should restore its state from the buffer.
uint16_t saveSize() override
TableObject(Memory &memory, uint32_t staticTableAdr=0, uint32_t staticTableSize=0)
The constuctor.
uint8_t * save(uint8_t *buffer) override
This method is called when the object should save its state to the buffer.
@ LE_START_LOADING
Definition: property.h:210
@ LE_LOAD_COMPLETED
Definition: property.h:211
@ LE_NOOP
Definition: property.h:209
@ LE_UNLOAD
Definition: property.h:213
@ LE_ADDITIONAL_LOAD_CONTROLS
Definition: property.h:212
@ PID_ERROR_CODE
Definition: property.h:88
@ PID_TABLE_REFERENCE
Definition: property.h:75
@ PID_LOAD_STATE_CONTROL
Definition: property.h:73
@ PID_MCB_TABLE
Definition: property.h:87
ErrorCode
Definition: property.h:218
@ E_NO_FAULT
Definition: property.h:219
@ E_GOT_UNDEF_LOAD_CMD
Definition: property.h:233
@ E_MAX_TABLE_LENGTH_EXEEDED
Definition: property.h:232
@ E_INVALID_OPCODE
Definition: property.h:230
@ PDT_CONTROL
length: 1 read, 10 write
Definition: property.h:18
@ PDT_GENERIC_08
length: 8
Definition: property.h:42
@ PDT_UNSIGNED_LONG
length: 4
Definition: property.h:27
@ PDT_ENUM8
length: 3
Definition: property.h:61
@ WriteLv0
Definition: property.h:247
@ WriteLv3
Definition: property.h:250
@ ReadLv3
Definition: property.h:246
LoadState
Definition: property.h:198
@ LS_LOADED
Definition: property.h:200
@ LS_UNLOADED
Definition: property.h:199
@ LS_LOADING
Definition: property.h:201
@ LS_ERROR
Definition: property.h:202
void(* BeforeTablesUnloadCallback)()
Definition: table_object.h:7