| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224 |
- #include "wiegand.h"
- #include <furi.h>
- #include <furi_hal.h>
- volatile unsigned long WIEGAND::_cardTempHigh = 0;
- volatile unsigned long WIEGAND::_cardTemp = 0;
- volatile unsigned long WIEGAND::_lastWiegand = 0;
- unsigned long WIEGAND::_code = 0;
- unsigned long WIEGAND::_codeHigh = 0;
- volatile int WIEGAND::_bitCount = 0;
- int WIEGAND::_wiegandType = 0;
- constexpr uint32_t clocks_in_ms = 64 * 1000;
- const GpioPin* const pinD0 = &gpio_ext_pa4;
- const GpioPin* const pinD1 = &gpio_ext_pa7;
- WIEGAND::WIEGAND() {
- }
- unsigned long WIEGAND::getCode() {
- return _code;
- }
- unsigned long WIEGAND::getCodeHigh() {
- return _codeHigh;
- }
- int WIEGAND::getWiegandType() {
- return _wiegandType;
- }
- bool WIEGAND::available() {
- bool ret;
- FURI_CRITICAL_ENTER();
- ret = DoWiegandConversion();
- FURI_CRITICAL_EXIT();
- return ret;
- }
- static void input_isr_d0(void* _ctx) {
- WIEGAND* _this = static_cast<WIEGAND*>(_ctx);
- _this->ReadD0();
- }
- static void input_isr_d1(void* _ctx) {
- WIEGAND* _this = static_cast<WIEGAND*>(_ctx);
- _this->ReadD1();
- }
- void WIEGAND::begin() {
- _lastWiegand = 0;
- _cardTempHigh = 0;
- _cardTemp = 0;
- _code = 0;
- _wiegandType = 0;
- _bitCount = 0;
- furi_hal_gpio_init_simple(pinD0, GpioModeInterruptFall); // Set D0 pin as input
- furi_hal_gpio_init_simple(pinD1, GpioModeInterruptFall); // Set D1 pin as input
- furi_hal_gpio_add_int_callback(pinD0, input_isr_d0, this);
- furi_hal_gpio_add_int_callback(pinD1, input_isr_d1, this);
- }
- void WIEGAND::end() {
- furi_hal_gpio_remove_int_callback(pinD0);
- furi_hal_gpio_remove_int_callback(pinD1);
- furi_hal_gpio_init_simple(pinD0, GpioModeAnalog);
- furi_hal_gpio_init_simple(pinD1, GpioModeAnalog);
- }
- void WIEGAND::ReadD0() {
- _bitCount++; // Increament bit count for Interrupt connected to D0
- if(_bitCount > 31) // If bit count more than 31, process high bits
- {
- _cardTempHigh |= ((0x80000000 & _cardTemp) >> 31); // shift value to high bits
- _cardTempHigh <<= 1;
- _cardTemp <<= 1;
- } else {
- _cardTemp <<= 1; // D0 represent binary 0, so just left shift card data
- }
- _lastWiegand = DWT->CYCCNT; // Keep track of last wiegand bit received
- }
- void WIEGAND::ReadD1() {
- _bitCount++; // Increment bit count for Interrupt connected to D1
- if(_bitCount > 31) // If bit count more than 31, process high bits
- {
- _cardTempHigh |= ((0x80000000 & _cardTemp) >> 31); // shift value to high bits
- _cardTempHigh <<= 1;
- _cardTemp |= 1;
- _cardTemp <<= 1;
- } else {
- _cardTemp |= 1; // D1 represent binary 1, so OR card data with 1 then
- _cardTemp <<= 1; // left shift card data
- }
- _lastWiegand = DWT->CYCCNT; // Keep track of last wiegand bit received
- }
- unsigned long WIEGAND::GetCardId(
- volatile unsigned long* codehigh,
- volatile unsigned long* codelow,
- char bitlength) {
- if(bitlength == 26) // EM tag
- return (*codelow & 0x1FFFFFE) >> 1;
- if(bitlength == 24) return (*codelow & 0x7FFFFE) >> 1;
- if(bitlength == 34) // Mifare
- {
- *codehigh = *codehigh & 0x03; // only need the 2 LSB of the codehigh
- *codehigh <<= 30; // shift 2 LSB to MSB
- *codelow >>= 1;
- return *codehigh | *codelow;
- }
- if(bitlength == 32) {
- return (*codelow & 0x7FFFFFFE) >> 1;
- }
- return *codelow; // EM tag or Mifare without parity bits
- }
- char translateEnterEscapeKeyPress(char originalKeyPress) {
- switch(originalKeyPress) {
- case 0x0b: // 11 or * key
- return 0x0d; // 13 or ASCII ENTER
- case 0x0a: // 10 or # key
- return 0x1b; // 27 or ASCII ESCAPE
- default:
- return originalKeyPress;
- }
- }
- bool WIEGAND::DoWiegandConversion() {
- unsigned long cardID;
- unsigned long sysTick = DWT->CYCCNT;
- if((sysTick - _lastWiegand) >
- (25 * clocks_in_ms)) // if no more signal coming through after 25ms
- {
- if((_bitCount == 24) || (_bitCount == 26) || (_bitCount == 32) || (_bitCount == 34) ||
- (_bitCount == 37) || (_bitCount == 40) || (_bitCount == 8) ||
- (_bitCount ==
- 4)) // bitCount for keypress=4 or 8, Wiegand 26=24 or 26, Wiegand 34=32 or 34
- {
- _codeHigh = 0;
- // shift right 1 bit to get back the real value - interrupt done 1 left shift in advance
- _cardTemp >>= 1;
- // bit count more than 32 bits, shift high bits right to make adjustment
- if(_bitCount > 32) _cardTempHigh >>= 1;
- if(_bitCount == 8) // keypress wiegand with integrity
- {
- // 8-bit Wiegand keyboard data, high nibble is the "NOT" of low nibble
- // eg if key 1 pressed, data=E1 in binary 11100001 , high nibble=1110 , low nibble = 0001
- char highNibble = (_cardTemp & 0xf0) >> 4;
- char lowNibble = (_cardTemp & 0x0f);
- _wiegandType = _bitCount;
- _bitCount = 0;
- _cardTemp = 0;
- _cardTempHigh = 0;
- if(lowNibble ==
- (~highNibble & 0x0f)) // check if low nibble matches the "NOT" of high nibble.
- {
- _code = (int)translateEnterEscapeKeyPress(lowNibble);
- return true;
- } else {
- _lastWiegand = sysTick;
- _bitCount = 0;
- _cardTemp = 0;
- _cardTempHigh = 0;
- return false;
- }
- // TODO: Handle validation failure case!
- } else if(4 == _bitCount) {
- // 4-bit Wiegand codes have no data integrity check so we just
- // read the LOW nibble.
- _code = (int)translateEnterEscapeKeyPress(_cardTemp & 0x0000000F);
- _wiegandType = _bitCount;
- _bitCount = 0;
- _cardTemp = 0;
- _cardTempHigh = 0;
- return true;
- } else if(40 == _bitCount) {
- _cardTempHigh >>= 1;
- _code = _cardTemp;
- _codeHigh = _cardTempHigh;
- _wiegandType = _bitCount;
- _bitCount = 0;
- _cardTemp = 0;
- _cardTempHigh = 0;
- return true;
- } else {
- // wiegand 26 or wiegand 34
- cardID = GetCardId(&_cardTempHigh, &_cardTemp, _bitCount);
- _wiegandType = _bitCount;
- _bitCount = 0;
- _cardTemp = 0;
- _cardTempHigh = 0;
- _code = cardID;
- return true;
- }
- } else {
- // well time over 25 ms and bitCount !=8 , !=26, !=34 , must be noise or nothing then.
- _lastWiegand = sysTick;
- _bitCount = 0;
- _cardTemp = 0;
- _cardTempHigh = 0;
- return false;
- }
- } else
- return false;
- }
|