[FL-2627] Flipper applications: SDK, build and debug system (#1387)
* Added support for running applications from SD card (FAPs - Flipper Application Packages) * Added plugin_dist target for fbt to build FAPs * All apps of type FlipperAppType.EXTERNAL and FlipperAppType.PLUGIN are built as FAPs by default * Updated VSCode configuration for new fbt features - re-deploy stock configuration to use them * Added debugging support for FAPs with fbt debug & VSCode * Added public firmware API with automated versioning Co-authored-by: hedger <hedger@users.noreply.github.com> Co-authored-by: SG <who.just.the.doctor@gmail.com> Co-authored-by: あく <alleteam@gmail.com>
This commit is contained in:
		
							
								
								
									
										224
									
								
								applications/debug/accessor/helpers/wiegand.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										224
									
								
								applications/debug/accessor/helpers/wiegand.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,224 @@ | ||||
| #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; | ||||
| } | ||||
							
								
								
									
										30
									
								
								applications/debug/accessor/helpers/wiegand.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										30
									
								
								applications/debug/accessor/helpers/wiegand.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,30 @@ | ||||
| #pragma once | ||||
|  | ||||
| class WIEGAND { | ||||
| public: | ||||
|     WIEGAND(); | ||||
|     void begin(); | ||||
|     void end(); | ||||
|     bool available(); | ||||
|     unsigned long getCode(); | ||||
|     unsigned long getCodeHigh(); | ||||
|     int getWiegandType(); | ||||
|  | ||||
|     static void ReadD0(); | ||||
|     static void ReadD1(); | ||||
|  | ||||
| private: | ||||
|     static bool DoWiegandConversion(); | ||||
|     static unsigned long GetCardId( | ||||
|         volatile unsigned long* codehigh, | ||||
|         volatile unsigned long* codelow, | ||||
|         char bitlength); | ||||
|  | ||||
|     static volatile unsigned long _cardTempHigh; | ||||
|     static volatile unsigned long _cardTemp; | ||||
|     static volatile unsigned long _lastWiegand; | ||||
|     static volatile int _bitCount; | ||||
|     static int _wiegandType; | ||||
|     static unsigned long _code; | ||||
|     static unsigned long _codeHigh; | ||||
| }; | ||||
		Reference in New Issue
	
	Block a user