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.
wiegand.cpp
- Committer:
- goymame
- Date:
- 2019-05-08
- Revision:
- 2:2c72a6b13593
- Parent:
- 0:4929608f96d0
- Child:
- 3:ea5e0ab156b5
File content as of revision 2:2c72a6b13593:
#include "wiegand.h" Wiegand::Wiegand(PinName d0, PinName d1, EventQueue* eventQueue, unsigned char bits, unsigned char id) : _d0(d0), _d1(d1), _eventQueue(eventQueue), _bits(bits), _id(id){ _bufferSize = (_bits/8); if((_bits % 8) >0) _bufferSize++; _hexDigits = (_bits/4); if((_bits % 4) >0) _hexDigits++; unsigned long long int maxNumber = 0; for(int i = 0; i < _bits; i++) maxNumber += pow((long double)2,i); _decDigits = 0; do { maxNumber /= 10; _decDigits++; } while(maxNumber != 0); _transmissionTimeout = 100000; _buffer = new uint8_t [_bufferSize]; _d0.fall(callback(this, &Wiegand::_data0ISR)); _d1.fall(callback(this, &Wiegand::_data1ISR)); startCalibrating(); reset(); } Wiegand::~Wiegand(){ delete[] _buffer; delete[] _interPulseGapBuffer; } void Wiegand::attach(Callback<void(Wiegand *WiegandObj)> wiegandCallback){ _callback = wiegandCallback; } void Wiegand::calibrateTimeout(void){ unsigned int interPulseGapAvg = 0; for( int i = 1; i < _bits; i++) interPulseGapAvg += _interPulseGapBuffer[i]; interPulseGapAvg /= _bits - 1 ; _transmissionTimeout = interPulseGapAvg * 10 ; } void Wiegand::_data0ISR(void){ _timeout.detach(); if (_autoCalibration){ _interPulseGapTimer.stop(); _interPulseGapBuffer[_bitsRead] = _interPulseGapTimer.read_us(); _interPulseGapTimer.reset(); } _bitsRead++; _shift_left(_buffer,_bufferSize,1); // shift 0 into buffer if (_bitsRead == _bits) _onWiegandISR(); else _timeout.attach_us(callback(this, &Wiegand::_onWiegandISR), _transmissionTimeout); } void Wiegand::_data0ISRRise(void){ _interPulseGapTimer.start(); } void Wiegand::_data1ISR(void){ _timeout.detach(); if (_autoCalibration){ _interPulseGapTimer.stop(); _interPulseGapBuffer[_bitsRead] = _interPulseGapTimer.read_us(); _interPulseGapTimer.reset(); } _shift_left(_buffer,_bufferSize,1); _buffer[_bufferSize-1] |=1; _bitsRead++; if (_bitsRead == _bits) _onWiegandISR(); else _timeout.attach_us(callback(this, &Wiegand::_onWiegandISR), _transmissionTimeout); } void Wiegand::_data1ISRRise(void){ _interPulseGapTimer.start(); } unsigned char Wiegand::getDecDigits(){ return _decDigits; } void Wiegand::getDecString(volatile char* decString){ long double rawInt = getRawInt(); if (!rawInt) return; volatile char* rawString = new volatile char [_decDigits+1]; memset((char*)rawString,'\0',_decDigits); int result = snprintf ( (char*)rawString, _decDigits+1, "%.0Lf", rawInt); if (result > 0 && result < _decDigits+1) for(int j=0; j < _decDigits; ++j) decString[j] = rawString[j]; delete[] rawString; } unsigned char Wiegand::getHexDigits(){ return _hexDigits; } void Wiegand::getHexString(volatile char* hexString){ long double rawInt = getRawInt(); if (!rawInt) return; volatile char* hexadecimalNumber = new volatile char [_hexDigits+1]; memset((char*)hexadecimalNumber,'\0',_hexDigits+1); unsigned long long int quotient = rawInt; int i=_hexDigits ,temp = 0; volatile unsigned char counter = 0; while(quotient!=0) { counter++; temp = quotient % 16; if( temp < 10) temp = temp + 48; else temp = temp + 55; hexadecimalNumber[--i] = temp; quotient = quotient / 16; } //shift array left if string is smaller than array if (counter < _hexDigits){ unsigned char difference = _hexDigits - counter; for(int j = 0 ; j < counter; j++){ hexadecimalNumber[ j ] = hexadecimalNumber[ j + difference ]; hexadecimalNumber[ j + (_hexDigits - counter) ] = '\0'; } } strcpy ( (char*)hexString,(char*)hexadecimalNumber ); delete[] hexadecimalNumber; } unsigned char Wiegand::getId(){ return _id; } uint8_t * Wiegand::getRaw(void){ return _buffer; } long double Wiegand::getRawInt(void){ long double rawInt = 0; unsigned char countdown = _bits - 1 ; uint8_t* tempBuffer = new uint8_t [1]; memset((unsigned char *)tempBuffer, 0, 1); for (unsigned int i=0; i < _bufferSize;i++){ tempBuffer[0] = _buffer[i]; for(int x=0; x<8;x++) { if(tempBuffer[0] & 0x80) rawInt += pow((long double)2,countdown); tempBuffer[0]<<=1; countdown--; } } delete[] tempBuffer; return rawInt; } unsigned int Wiegand::getTimeout(void){ return _transmissionTimeout; } void Wiegand::_onWiegandISR(void){ _eventQueue->call(callback(this, &Wiegand::_onWiegandNonISR)); } void Wiegand::_onWiegandNonISR(void){ if (_autoCalibration){ stopCalibrating(); calibrateTimeout(); } _callback(this); } void Wiegand::reset(void){ memset((unsigned char *)_buffer, 0, _bufferSize); _bitsRead = 0; } void Wiegand::setTimeout(unsigned int time){ _transmissionTimeout = time * 1000; } void Wiegand::_shift_left(volatile unsigned char *ar, int size, int shift){ while (shift--) { // for each bit to shift ... int carry = 0; // clear the initial carry bit. int lastElement = size-1; for (int i = 0; i < size; i++) { // for each element of the array, from low byte to high byte if (i!=lastElement) { carry = (ar[i+1] & 0x80) ? 1 : 0; ar[i] = carry | (ar[i]<<1); } else { ar[i] <<=1; } } } } void Wiegand::startCalibrating(void){ _autoCalibration = true; _d0.rise(callback(this, &Wiegand::_data0ISRRise)); _d1.rise(callback(this, &Wiegand::_data1ISRRise)); _interPulseGapBuffer = new volatile int [_bits]; } void Wiegand::stopCalibrating(){ _autoCalibration = false; _interPulseGapTimer.stop(); _d0.rise(0); _d1.rise(0); delete[] _interPulseGapBuffer; }