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:
Sat Apr 27 23:37:01 2019 +0000
Revision:
0:4929608f96d0
Child:
2:2c72a6b13593
first commit

Who changed what in which revision?

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