knx
ETS configurable knx-stack
association_table_object.cpp
Go to the documentation of this file.
1 #include <cstring>
2 
4 #include "bits.h"
5 #include "data_property.h"
6 
7 using namespace std;
8 
10  : TableObject(memory)
11 {
12  Property* properties[] =
13  {
15  new DataProperty(PID_TABLE, false, PDT_GENERIC_04, 65535, ReadLv3 | WriteLv0) //FIXME: implement correctly
16  };
17 
18  TableObject::initializeProperties(sizeof(properties), properties);
19 }
20 
21 uint16_t AssociationTableObject::entryCount()
22 {
23  return ntohs(_tableData[0]);
24 }
25 
26 uint16_t AssociationTableObject::getTSAP(uint16_t idx)
27 {
28  if (idx >= entryCount())
29  return 0;
30 
31  return ntohs(_tableData[2 * idx + 1]);
32 }
33 
34 uint16_t AssociationTableObject::getASAP(uint16_t idx)
35 {
36  if (idx >= entryCount())
37  return 0;
38 
39  return ntohs(_tableData[2 * idx + 2]);
40 }
41 
42 // after any table change the table is checked if it allows
43 // binary search access. If not, sortedEntryCount stays 0,
44 // otherwise sortedEntryCount represents size of bin search array
45 void AssociationTableObject::prepareBinarySearch()
46 {
47  sortedEntryCount = 0;
48 #ifdef USE_BINSEARCH
49  uint16_t lastASAP = 0;
50  uint16_t currentASAP = 0;
51  uint16_t lookupIdx = 0;
52  uint16_t lookupASAP = 0;
53 
54  // we iterate through all ASAP
55  // the first n ASAP are sorted (strictly increasing number), these are assigning sending TSAP
56  // the remaining ASAP have to be all repetitions, otherwise we set sortedEntryCount to 0, which forces linear search
57  if (_tableData != nullptr)
58  {
59  for (uint16_t idx = 0; idx < entryCount(); idx++)
60  {
61  currentASAP = getASAP(idx);
62 
63  if (sortedEntryCount)
64  {
65  // look if the remaining ASAP exist in the previously sorted list.
66  while (lookupIdx < sortedEntryCount)
67  {
68  lookupASAP = getASAP(lookupIdx);
69 
70  if (currentASAP <= lookupASAP)
71  break; // while
72  else
73  lookupIdx++;
74  }
75 
76  if (currentASAP < lookupASAP || lookupIdx >= sortedEntryCount)
77  {
78  // a new ASAP found, we force linear search
79  sortedEntryCount = 0;
80  break; // for
81  }
82  }
83  else
84  {
85  // check for strictly increasing ASAP
86  if (currentASAP > lastASAP)
87  lastASAP = currentASAP;
88  else
89  {
90  sortedEntryCount = idx; // last found index indicates end of sorted list
91  idx--; // current item has to be handled as remaining ASAP
92  }
93  }
94  }
95 
96  // in case complete table is strictly increasing
97  if (lookupIdx == 0 && sortedEntryCount == 0)
98  sortedEntryCount = entryCount();
99  }
100 
101 #endif
102 }
103 
104 const uint8_t* AssociationTableObject::restore(const uint8_t* buffer)
105 {
106  buffer = TableObject::restore(buffer);
107  _tableData = (uint16_t*)data();
108  prepareBinarySearch();
109  return buffer;
110 }
111 
112 // return type is int32 so that we can return uint16 and -1
114 {
115  // sortedEntryCount is determined in prepareBinarySearch()
116  // if ETS provides strictly increasing numbers for ASAP
117  // represents the size of the array to search
118  if (sortedEntryCount)
119  {
120  uint16_t low = 0;
121  uint16_t high = sortedEntryCount - 1;
122 
123  while (low <= high)
124  {
125  uint16_t i = (low + high) / 2;
126  uint16_t asap_i = getASAP(i);
127 
128  if (asap_i == asap)
129  return getTSAP(i);
130 
131  if (asap_i > asap)
132  high = i - 1;
133  else
134  low = i + 1 ;
135  }
136  }
137  else
138  {
139  // if ASAP numbers are not strictly increasing linear seach is used
140  for (uint16_t i = 0; i < entryCount(); i++)
141  if (getASAP(i) == asap)
142  return getTSAP(i);
143  }
144 
145  return -1;
146 }
147 
149 {
151 
152  if (newState != LS_LOADED)
153  return;
154 
155  _tableData = (uint16_t*)data();
156  prepareBinarySearch();
157 }
158 
159 int32_t AssociationTableObject::nextAsap(uint16_t tsap, uint16_t& startIdx)
160 {
161  uint16_t entries = entryCount();
162 
163  for (uint16_t i = startIdx; i < entries; i++)
164  {
165  startIdx = i + 1;
166 
167  if (getTSAP(i) == tsap)
168  {
169  return getASAP(i);
170  }
171  }
172 
173  return -1;
174 }
int32_t translateAsap(uint16_t asap)
const uint8_t * restore(const uint8_t *buffer) override
This method is called when the object should restore its state from the buffer.
void beforeStateChange(LoadState &newState) override
This method is called before the interface object enters a new LoadState.
int32_t nextAsap(uint16_t tsap, uint16_t &startIdx)
Definition: memory.h:37
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.
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.
const uint8_t * restore(const uint8_t *buffer) override
This method is called when the object should restore its state from the buffer.
@ OT_ASSOC_TABLE
Association table object.
@ PID_OBJECT_TYPE
Interface Object Type independent Properties.
Definition: property.h:72
@ PID_TABLE
Definition: property.h:85
@ PDT_GENERIC_04
length: 4
Definition: property.h:38
@ PDT_UNSIGNED_INT
length: 2
Definition: property.h:22
@ WriteLv0
Definition: property.h:247
@ ReadLv3
Definition: property.h:246
LoadState
Definition: property.h:198
@ LS_LOADED
Definition: property.h:200