This library reads Wiegand, saving it into a buffer, calling a callback function after it is full or a timeout is reached.

Dependents:   mbed-os-wiegand-example

This library reads Wiegand, saving it into a buffer, calling a callback function after it is full or a timeout is reached. Data can be extracted as :

  • Raw
  • Base 10 Integer
  • Base 10 String
  • Base 16 String

Always call reset after saving Wiegand data.

It automatically calibrates the timeout during the first reading unless specified.

Timeout can be set using setTimout, units are in milliseconds (first call stopCalibrating()).

EventQueue is required for deferring from ISR, it is possible to dispatch the EventQueue from the mainQueue or any other thread.

Committer:
goymame
Date:
Thu May 16 22:12:19 2019 +0000
Revision:
3:ea5e0ab156b5
Parent:
2:2c72a6b13593
New update bits function

Who changed what in which revision?

UserRevisionLine numberNew contents of line
goymame 0:4929608f96d0 1 #include "wiegand.h"
goymame 0:4929608f96d0 2
goymame 3:ea5e0ab156b5 3 Wiegand::Wiegand(PinName d0, PinName d1, EventQueue* eventQueue, unsigned char id) :
goymame 3:ea5e0ab156b5 4 _d0(d0), _d1(d1), _eventQueue(eventQueue), _id(id){
goymame 0:4929608f96d0 5 _transmissionTimeout = 100000;
goymame 0:4929608f96d0 6 _d0.fall(callback(this, &Wiegand::_data0ISR));
goymame 0:4929608f96d0 7 _d1.fall(callback(this, &Wiegand::_data1ISR));
goymame 0:4929608f96d0 8 startCalibrating();
goymame 0:4929608f96d0 9 }
goymame 0:4929608f96d0 10
goymame 0:4929608f96d0 11 Wiegand::~Wiegand(){
goymame 0:4929608f96d0 12 delete[] _buffer;
goymame 0:4929608f96d0 13 delete[] _interPulseGapBuffer;
goymame 0:4929608f96d0 14 }
goymame 0:4929608f96d0 15
goymame 2:2c72a6b13593 16 void Wiegand::attach(Callback<void(Wiegand *WiegandObj)> wiegandCallback){
goymame 2:2c72a6b13593 17 _callback = wiegandCallback;
goymame 2:2c72a6b13593 18 }
goymame 2:2c72a6b13593 19
goymame 0:4929608f96d0 20 void Wiegand::calibrateTimeout(void){
goymame 0:4929608f96d0 21 unsigned int interPulseGapAvg = 0;
goymame 0:4929608f96d0 22 for( int i = 1; i < _bits; i++)
goymame 0:4929608f96d0 23 interPulseGapAvg += _interPulseGapBuffer[i];
goymame 0:4929608f96d0 24 interPulseGapAvg /= _bits - 1 ;
goymame 0:4929608f96d0 25 _transmissionTimeout = interPulseGapAvg * 10 ;
goymame 0:4929608f96d0 26 }
goymame 0:4929608f96d0 27
goymame 0:4929608f96d0 28 void Wiegand::_data0ISR(void){
goymame 0:4929608f96d0 29 _timeout.detach();
goymame 2:2c72a6b13593 30 if (_autoCalibration){
goymame 0:4929608f96d0 31 _interPulseGapTimer.stop();
goymame 0:4929608f96d0 32 _interPulseGapBuffer[_bitsRead] = _interPulseGapTimer.read_us();
goymame 0:4929608f96d0 33 _interPulseGapTimer.reset();
goymame 0:4929608f96d0 34 }
goymame 0:4929608f96d0 35 _bitsRead++;
goymame 3:ea5e0ab156b5 36 _shift_left(_buffer,_bufferSize,1);
goymame 0:4929608f96d0 37 if (_bitsRead == _bits)
goymame 0:4929608f96d0 38 _onWiegandISR();
goymame 2:2c72a6b13593 39 else
goymame 0:4929608f96d0 40 _timeout.attach_us(callback(this, &Wiegand::_onWiegandISR), _transmissionTimeout);
goymame 0:4929608f96d0 41 }
goymame 0:4929608f96d0 42
goymame 0:4929608f96d0 43 void Wiegand::_data0ISRRise(void){
goymame 0:4929608f96d0 44 _interPulseGapTimer.start();
goymame 0:4929608f96d0 45 }
goymame 0:4929608f96d0 46
goymame 0:4929608f96d0 47 void Wiegand::_data1ISR(void){
goymame 0:4929608f96d0 48 _timeout.detach();
goymame 2:2c72a6b13593 49 if (_autoCalibration){
goymame 0:4929608f96d0 50 _interPulseGapTimer.stop();
goymame 0:4929608f96d0 51 _interPulseGapBuffer[_bitsRead] = _interPulseGapTimer.read_us();
goymame 0:4929608f96d0 52 _interPulseGapTimer.reset();
goymame 0:4929608f96d0 53 }
goymame 0:4929608f96d0 54 _shift_left(_buffer,_bufferSize,1);
goymame 0:4929608f96d0 55 _buffer[_bufferSize-1] |=1;
goymame 2:2c72a6b13593 56 _bitsRead++;
goymame 0:4929608f96d0 57 if (_bitsRead == _bits)
goymame 0:4929608f96d0 58 _onWiegandISR();
goymame 0:4929608f96d0 59 else
goymame 0:4929608f96d0 60 _timeout.attach_us(callback(this, &Wiegand::_onWiegandISR), _transmissionTimeout);
goymame 0:4929608f96d0 61 }
goymame 0:4929608f96d0 62
goymame 0:4929608f96d0 63 void Wiegand::_data1ISRRise(void){
goymame 0:4929608f96d0 64 _interPulseGapTimer.start();
goymame 0:4929608f96d0 65 }
goymame 0:4929608f96d0 66
goymame 0:4929608f96d0 67 unsigned char Wiegand::getDecDigits(){
goymame 0:4929608f96d0 68 return _decDigits;
goymame 0:4929608f96d0 69 }
goymame 0:4929608f96d0 70
goymame 0:4929608f96d0 71 void Wiegand::getDecString(volatile char* decString){
goymame 0:4929608f96d0 72 long double rawInt = getRawInt();
goymame 0:4929608f96d0 73 if (!rawInt) return;
goymame 0:4929608f96d0 74 volatile char* rawString = new volatile char [_decDigits+1];
goymame 0:4929608f96d0 75 memset((char*)rawString,'\0',_decDigits);
goymame 0:4929608f96d0 76 int result = snprintf ( (char*)rawString, _decDigits+1, "%.0Lf", rawInt);
goymame 0:4929608f96d0 77 if (result > 0 && result < _decDigits+1)
goymame 0:4929608f96d0 78 for(int j=0; j < _decDigits; ++j)
goymame 0:4929608f96d0 79 decString[j] = rawString[j];
goymame 0:4929608f96d0 80 delete[] rawString;
goymame 0:4929608f96d0 81 }
goymame 0:4929608f96d0 82
goymame 0:4929608f96d0 83 unsigned char Wiegand::getHexDigits(){
goymame 0:4929608f96d0 84 return _hexDigits;
goymame 0:4929608f96d0 85 }
goymame 0:4929608f96d0 86
goymame 0:4929608f96d0 87 void Wiegand::getHexString(volatile char* hexString){
goymame 0:4929608f96d0 88 long double rawInt = getRawInt();
goymame 0:4929608f96d0 89 if (!rawInt) return;
goymame 0:4929608f96d0 90 volatile char* hexadecimalNumber = new volatile char [_hexDigits+1];
goymame 0:4929608f96d0 91 memset((char*)hexadecimalNumber,'\0',_hexDigits+1);
goymame 0:4929608f96d0 92 unsigned long long int quotient = rawInt;
goymame 0:4929608f96d0 93 int i=_hexDigits ,temp = 0;
goymame 0:4929608f96d0 94 volatile unsigned char counter = 0;
goymame 0:4929608f96d0 95 while(quotient!=0) {
goymame 0:4929608f96d0 96 counter++;
goymame 0:4929608f96d0 97 temp = quotient % 16;
goymame 0:4929608f96d0 98 if( temp < 10)
goymame 0:4929608f96d0 99 temp = temp + 48;
goymame 0:4929608f96d0 100 else
goymame 0:4929608f96d0 101 temp = temp + 55;
goymame 0:4929608f96d0 102 hexadecimalNumber[--i] = temp;
goymame 0:4929608f96d0 103 quotient = quotient / 16;
goymame 0:4929608f96d0 104 }
goymame 0:4929608f96d0 105 if (counter < _hexDigits){
goymame 0:4929608f96d0 106 unsigned char difference = _hexDigits - counter;
goymame 0:4929608f96d0 107 for(int j = 0 ; j < counter; j++){
goymame 0:4929608f96d0 108 hexadecimalNumber[ j ] = hexadecimalNumber[ j + difference ];
goymame 0:4929608f96d0 109 hexadecimalNumber[ j + (_hexDigits - counter) ] = '\0';
goymame 0:4929608f96d0 110 }
goymame 0:4929608f96d0 111 }
goymame 0:4929608f96d0 112 strcpy ( (char*)hexString,(char*)hexadecimalNumber );
goymame 0:4929608f96d0 113 delete[] hexadecimalNumber;
goymame 0:4929608f96d0 114 }
goymame 0:4929608f96d0 115
goymame 2:2c72a6b13593 116 unsigned char Wiegand::getId(){
goymame 2:2c72a6b13593 117 return _id;
goymame 2:2c72a6b13593 118 }
goymame 2:2c72a6b13593 119
goymame 0:4929608f96d0 120 uint8_t * Wiegand::getRaw(void){
goymame 0:4929608f96d0 121 return _buffer;
goymame 0:4929608f96d0 122 }
goymame 0:4929608f96d0 123
goymame 0:4929608f96d0 124 long double Wiegand::getRawInt(void){
goymame 0:4929608f96d0 125 long double rawInt = 0;
goymame 0:4929608f96d0 126 unsigned char countdown = _bits - 1 ;
goymame 0:4929608f96d0 127 uint8_t* tempBuffer = new uint8_t [1];
goymame 0:4929608f96d0 128 memset((unsigned char *)tempBuffer, 0, 1);
goymame 0:4929608f96d0 129 for (unsigned int i=0; i < _bufferSize;i++){
goymame 0:4929608f96d0 130 tempBuffer[0] = _buffer[i];
goymame 0:4929608f96d0 131 for(int x=0; x<8;x++) {
goymame 0:4929608f96d0 132 if(tempBuffer[0] & 0x80)
goymame 0:4929608f96d0 133 rawInt += pow((long double)2,countdown);
goymame 0:4929608f96d0 134 tempBuffer[0]<<=1;
goymame 0:4929608f96d0 135 countdown--;
goymame 0:4929608f96d0 136 }
goymame 0:4929608f96d0 137 }
goymame 0:4929608f96d0 138 delete[] tempBuffer;
goymame 0:4929608f96d0 139 return rawInt;
goymame 0:4929608f96d0 140 }
goymame 0:4929608f96d0 141
goymame 0:4929608f96d0 142 unsigned int Wiegand::getTimeout(void){
goymame 0:4929608f96d0 143 return _transmissionTimeout;
goymame 0:4929608f96d0 144 }
goymame 0:4929608f96d0 145
goymame 0:4929608f96d0 146 void Wiegand::_onWiegandISR(void){
goymame 0:4929608f96d0 147 _eventQueue->call(callback(this, &Wiegand::_onWiegandNonISR));
goymame 0:4929608f96d0 148 }
goymame 0:4929608f96d0 149
goymame 0:4929608f96d0 150 void Wiegand::_onWiegandNonISR(void){
goymame 0:4929608f96d0 151 if (_autoCalibration){
goymame 0:4929608f96d0 152 stopCalibrating();
goymame 0:4929608f96d0 153 calibrateTimeout();
goymame 0:4929608f96d0 154 }
goymame 2:2c72a6b13593 155 _callback(this);
goymame 0:4929608f96d0 156 }
goymame 0:4929608f96d0 157
goymame 0:4929608f96d0 158 void Wiegand::reset(void){
goymame 0:4929608f96d0 159 memset((unsigned char *)_buffer, 0, _bufferSize);
goymame 0:4929608f96d0 160 _bitsRead = 0;
goymame 0:4929608f96d0 161 }
goymame 0:4929608f96d0 162
goymame 3:ea5e0ab156b5 163 void Wiegand::setBits(unsigned char bits){
goymame 3:ea5e0ab156b5 164 _bits = bits;
goymame 3:ea5e0ab156b5 165 _bufferSize = (_bits/8);
goymame 3:ea5e0ab156b5 166 if((_bits % 8) >0)
goymame 3:ea5e0ab156b5 167 _bufferSize++;
goymame 3:ea5e0ab156b5 168 _hexDigits = (_bits/4);
goymame 3:ea5e0ab156b5 169 if((_bits % 4) >0)
goymame 3:ea5e0ab156b5 170 _hexDigits++;
goymame 3:ea5e0ab156b5 171 unsigned long long int maxNumber = 0;
goymame 3:ea5e0ab156b5 172 for(int i = 0; i < _bits; i++)
goymame 3:ea5e0ab156b5 173 maxNumber += pow((long double)2,i);
goymame 3:ea5e0ab156b5 174 _decDigits = 0;
goymame 3:ea5e0ab156b5 175 do { maxNumber /= 10; _decDigits++; } while(maxNumber != 0);
goymame 3:ea5e0ab156b5 176 _buffer = new uint8_t [_bufferSize];
goymame 3:ea5e0ab156b5 177 reset();
goymame 3:ea5e0ab156b5 178 }
goymame 3:ea5e0ab156b5 179
goymame 0:4929608f96d0 180 void Wiegand::setTimeout(unsigned int time){
goymame 0:4929608f96d0 181 _transmissionTimeout = time * 1000;
goymame 0:4929608f96d0 182 }
goymame 0:4929608f96d0 183
goymame 0:4929608f96d0 184 void Wiegand::_shift_left(volatile unsigned char *ar, int size, int shift){
goymame 3:ea5e0ab156b5 185 while (shift--) {
goymame 3:ea5e0ab156b5 186 int carry = 0;
goymame 0:4929608f96d0 187 int lastElement = size-1;
goymame 3:ea5e0ab156b5 188 for (int i = 0; i < size; i++) {
goymame 0:4929608f96d0 189 if (i!=lastElement) {
goymame 0:4929608f96d0 190 carry = (ar[i+1] & 0x80) ? 1 : 0;
goymame 0:4929608f96d0 191 ar[i] = carry | (ar[i]<<1);
goymame 0:4929608f96d0 192 }
goymame 0:4929608f96d0 193 else {
goymame 0:4929608f96d0 194 ar[i] <<=1;
goymame 0:4929608f96d0 195 }
goymame 0:4929608f96d0 196 }
goymame 0:4929608f96d0 197 }
goymame 0:4929608f96d0 198 }
goymame 0:4929608f96d0 199
goymame 0:4929608f96d0 200 void Wiegand::startCalibrating(void){
goymame 0:4929608f96d0 201 _autoCalibration = true;
goymame 0:4929608f96d0 202 _d0.rise(callback(this, &Wiegand::_data0ISRRise));
goymame 0:4929608f96d0 203 _d1.rise(callback(this, &Wiegand::_data1ISRRise));
goymame 0:4929608f96d0 204 _interPulseGapBuffer = new volatile int [_bits];
goymame 0:4929608f96d0 205 }
goymame 0:4929608f96d0 206
goymame 0:4929608f96d0 207 void Wiegand::stopCalibrating(){
goymame 0:4929608f96d0 208 _autoCalibration = false;
goymame 0:4929608f96d0 209 _interPulseGapTimer.stop();
goymame 0:4929608f96d0 210 _d0.rise(0);
goymame 0:4929608f96d0 211 _d1.rise(0);
goymame 0:4929608f96d0 212 delete[] _interPulseGapBuffer;
goymame 0:4929608f96d0 213 }