FastArduino v1.10
C++ library to build fast but small Arduino/AVR projects
Loading...
Searching...
No Matches
wiegand.h
Go to the documentation of this file.
1// Copyright 2016-2023 Jean-Francois Poilpret
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
16
21#ifndef WIEGAND_H
22#define WIEGAND_H
23
24#include "../utilities.h"
25
26namespace devices
27{
31 namespace protocols
32 {
33 }
34}
35
36namespace devices::protocols
37{
56 class Wiegand
57 {
58 public:
63 using DATA_TYPE = uint32_t;
64
71 static constexpr uint8_t DATA_BITS = 24;
72
78 {
79 reset_();
80 }
81
93 void reset()
94 {
95 synchronized reset_();
96 }
97
109 void reset_()
110 {
111 buffer_ = 0UL;
112 current_ = &data_[DATA_BYTES - 1];
113 mask_ = INITIAL_MASK;
114 }
115
127 bool available_() const
128 {
129 return count_ == FRAME_BITS;
130 }
131
144 bool valid_() const
145 {
146 uint32_t data = data24_;
147
148 // 1. check parity on first 12 bits
149 if (parity1_ != parity(PARITY1_HIGH_BIT_INDEX, data)) return false;
150
151 // 2. check parity on last 12 bits
152 if (parity2_ == parity(PARITY2_HIGH_BIT_INDEX, data)) return false;
153
154 return true;
155 }
156
171 {
172 return data24_;
173 }
174
185 {
186 // This is a 0
187 // Check if frame is finished (do not add any bit)
188 if (available_()) return;
189 // check if parity1
190 if (count_ == PARITY1_BIT_FRAME_INDEX)
191 parity1_ = false;
192 else if (count_ == PARITY2_BIT_FRAME_INDEX)
193 parity2_ = false;
194 else
195 {
196 // Normal data bit, update mask and byte to write
197 mask_ >>= 1;
198 if (mask_ == 0)
199 {
200 mask_ = INITIAL_MASK;
201 --current_;
202 }
203 }
204 // Update bits count
205 ++count_;
206 }
207
218 {
219 // This is a 1
220 // Check if frame is finished (do not add any bit)
221 if (available_()) return;
222 // check if parity1
223 if (count_ == PARITY1_BIT_FRAME_INDEX)
224 parity1_ = true;
225 // check if parity2
226 else if (count_ == PARITY2_BIT_FRAME_INDEX)
227 parity2_ = true;
228 // Normal data bit (1 only), store it
229 else
230 {
231 *current_ |= mask_;
232 // Update mask and byte to write
233 mask_ >>= 1;
234 if (mask_ == 0)
235 {
236 mask_ = INITIAL_MASK;
237 --current_;
238 }
239 }
240 // Update bits count
241 ++count_;
242 }
243
244 private:
245 // Positions in stream of parity bits
246 static constexpr uint8_t FRAME_BITS = 26;
247 static constexpr uint8_t PARITY1_BIT_FRAME_INDEX = 0;
248 static constexpr uint8_t PARITY2_BIT_FRAME_INDEX = 25;
249
250 static constexpr uint8_t PARITY_BITS_COUNT = 12;
251 static constexpr uint8_t PARITY1_HIGH_BIT_INDEX = 23;
252 static constexpr uint8_t PARITY2_HIGH_BIT_INDEX = 11;
253
254 static constexpr uint8_t INITIAL_MASK = 0x80;
255 static constexpr uint8_t DATA_BYTES = DATA_BITS / 8;
256
257 static bool parity(uint8_t start, uint32_t buffer)
258 {
259 uint8_t count = 0;
260 uint8_t size = PARITY_BITS_COUNT;
261 uint32_t mask = 1UL << start;
262 while (size-- != 0)
263 {
264 if (buffer & mask) ++count;
265 mask >>= 1;
266 }
267 return (count % 2);
268 }
269
270 union
271 {
272 // Used to clear all in one instruction
273 uint32_t buffer_;
274 struct
275 {
276 // Used to store bits, byte after byte
277 uint8_t data_[DATA_BYTES];
278 // Count of received bits (including parity bits)
279 uint8_t count_;
280 };
281 struct
282 {
283 // Used to access the actual 24-bits data
284 uint32_t data24_ : DATA_BITS;
285 uint32_t :8;
286 };
287 };
288 // Points to current read byte in data_[]
289 uint8_t* current_;
290 // Mask for current read bit
291 uint8_t mask_;
292 // First parity bit read (even)
293 bool parity1_;
294 // Last parity bit read (odd)
295 bool parity2_;
296 };
297}
298
299#endif /* WIEGAND_H */
Supporting class for the Wiegand 26 bits protocol (used by many access control devices).
Definition: wiegand.h:57
Wiegand()
Construct a new Wiegand instance to be sued by an access control device.
Definition: wiegand.h:77
bool available_() const
Check if data is available, i.e.
Definition: wiegand.h:127
DATA_TYPE get_data_() const
Get data read from access control device.
Definition: wiegand.h:170
static constexpr uint8_t DATA_BITS
The actual number of bits of data in DATA_TYPE.
Definition: wiegand.h:71
void reset_()
Reset current read state of this instance.
Definition: wiegand.h:109
bool valid_() const
Check if current data is valid, i.e.
Definition: wiegand.h:144
void reset()
Reset current read state of this instance.
Definition: wiegand.h:93
void on_falling_data0()
Your device shall call this method whenever DATA0 line level is falling to 0, which means a 0 bit mus...
Definition: wiegand.h:184
void on_falling_data1()
Your device shall call this method whenever DATA1 line level is falling to 0, which means a 1 bit mus...
Definition: wiegand.h:217
uint32_t DATA_TYPE
The data type used to return data read from the access control device.
Definition: wiegand.h:63
Defines utility classes to implement various protocols used in several devices, like Wiegand.
Definition: wiegand.h:32
Defines all API for all external devices supported by FastArduino.