 389ff92cc1
			
		
	
	
		389ff92cc1
		
			
		
	
	
	
	
		
			
			* Makefile, Scripts: new linter * About: remove ID from IC * Firmware: remove double define for DIVC/DIVR * Scripts: check folder names too. Docker: replace syntax check with make lint. * Reformat Sources and Migrate to new file naming convention * Docker: symlink clang-format-12 to clang-format * Add coding style guide
		
			
				
	
	
		
			224 lines
		
	
	
		
			6.8 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			224 lines
		
	
	
		
			6.8 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| #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* pinD0 = &gpio_ext_pa4;
 | |
| const GpioPin* 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;
 | |
|     __disable_irq();
 | |
|     ret = DoWiegandConversion();
 | |
|     __enable_irq();
 | |
|     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;
 | |
| 
 | |
|     hal_gpio_init_simple(pinD0, GpioModeInterruptFall); // Set D0 pin as input
 | |
|     hal_gpio_init_simple(pinD1, GpioModeInterruptFall); // Set D1 pin as input
 | |
| 
 | |
|     hal_gpio_add_int_callback(pinD0, input_isr_d0, this);
 | |
|     hal_gpio_add_int_callback(pinD1, input_isr_d1, this);
 | |
| }
 | |
| 
 | |
| void WIEGAND::end() {
 | |
|     hal_gpio_remove_int_callback(pinD0);
 | |
|     hal_gpio_remove_int_callback(pinD1);
 | |
| 
 | |
|     hal_gpio_init_simple(pinD0, GpioModeAnalog);
 | |
|     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;
 | |
| } |