[FL-1057] Low frequency RFID app [HID Encoder] (#445)
* App Lfrfid: hid26 timer stage * App Lfrfid: hid26 encoder * fully removed old lf-rfid app * fix codeowners
This commit is contained in:
		
							parent
							
								
									46bc515c6a
								
							
						
					
					
						commit
						469e2dffec
					
				
							
								
								
									
										4
									
								
								.github/CODEOWNERS
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										4
									
								
								.github/CODEOWNERS
									
									
									
									
										vendored
									
									
								
							| @ -78,6 +78,10 @@ lib/onewire/** @DrZlo13 | |||||||
| 
 | 
 | ||||||
| applications/irda/** @DrZlo13 | applications/irda/** @DrZlo13 | ||||||
| 
 | 
 | ||||||
|  | # LF-Rfid | ||||||
|  | 
 | ||||||
|  | applications/lf-rfid/** @DrZlo13 | ||||||
|  | 
 | ||||||
| # Menu | # Menu | ||||||
| 
 | 
 | ||||||
| applications/menu/** @skotopes | applications/menu/** @skotopes | ||||||
|  | |||||||
| @ -1,71 +0,0 @@ | |||||||
| #include <furi.h> |  | ||||||
| #include <api-hal.h> |  | ||||||
| 
 |  | ||||||
| void prepare_data(uint32_t ID, uint32_t VENDOR, uint8_t* data) { |  | ||||||
|     uint8_t value[10]; |  | ||||||
| 
 |  | ||||||
|     // vendor rows (4 bit in a row)
 |  | ||||||
|     value[0] = (VENDOR >> 4) & 0xF; |  | ||||||
|     value[1] = VENDOR & 0xF; |  | ||||||
| 
 |  | ||||||
|     const uint8_t ROW_SIZE = 4; |  | ||||||
|     const uint8_t HEADER_SIZE = 9; |  | ||||||
| 
 |  | ||||||
|     // ID rows (4 bit in a row)
 |  | ||||||
|     for(int i = 0; i < 8; i++) { |  | ||||||
|         value[i + 2] = (ID >> (28 - i * ROW_SIZE)) & 0xF; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     for(uint8_t i = 0; i < HEADER_SIZE; i++) { |  | ||||||
|         data[i] = 1; // header
 |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     for(uint8_t i = 0; i < 10; i++) { // data
 |  | ||||||
|         for(uint8_t j = 0; j < ROW_SIZE; j++) { |  | ||||||
|             data[HEADER_SIZE + i * (ROW_SIZE + 1) + j] = (value[i] >> ((ROW_SIZE - 1) - j)) & 1; |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         // row parity
 |  | ||||||
|         data[HEADER_SIZE + i * (ROW_SIZE + 1) + ROW_SIZE] = |  | ||||||
|             (data[HEADER_SIZE + i * (ROW_SIZE + 1) + 0] + |  | ||||||
|              data[HEADER_SIZE + i * (ROW_SIZE + 1) + 1] + |  | ||||||
|              data[HEADER_SIZE + i * (ROW_SIZE + 1) + 2] + |  | ||||||
|              data[HEADER_SIZE + i * (ROW_SIZE + 1) + 3]) % |  | ||||||
|             2; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     for(uint8_t i = 0; i < ROW_SIZE; i++) { //checksum
 |  | ||||||
|         uint8_t checksum = 0; |  | ||||||
|         for(uint8_t j = 0; j < 10; j++) { |  | ||||||
|             checksum += data[HEADER_SIZE + i + j * (ROW_SIZE + 1)]; |  | ||||||
|         } |  | ||||||
|         data[i + 59] = checksum % 2; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     data[63] = 0; // stop bit
 |  | ||||||
| 
 |  | ||||||
|     /*
 |  | ||||||
|     printf("em data: "); |  | ||||||
|     for(uint8_t i = 0; i < 64; i++) { |  | ||||||
|         printf("%d ", data[i]); |  | ||||||
|     } |  | ||||||
|     printf("\r\n"); |  | ||||||
|     */ |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void em4100_emulation(uint8_t* data, GpioPin* pin) { |  | ||||||
|     taskENTER_CRITICAL(); |  | ||||||
|     hal_gpio_write(pin, true); |  | ||||||
| 
 |  | ||||||
|     for(uint8_t i = 0; i < 8; i++) { |  | ||||||
|         for(uint8_t j = 0; j < 64; j++) { |  | ||||||
|             delay_us(260); |  | ||||||
|             hal_gpio_write(pin, data[j]); |  | ||||||
|             delay_us(260); |  | ||||||
|             hal_gpio_write(pin, !data[j]); |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     hal_gpio_write(pin, false); |  | ||||||
|     taskEXIT_CRITICAL(); |  | ||||||
| } |  | ||||||
| @ -2,12 +2,124 @@ | |||||||
| #include <furi.h> | #include <furi.h> | ||||||
| 
 | 
 | ||||||
| void EncoderHID::init(const uint8_t* data, const uint8_t data_size) { | void EncoderHID::init(const uint8_t* data, const uint8_t data_size) { | ||||||
|     card_data = 0b1010000000000000000000000000000010011101111110011001001001010010; |     furi_check(data_size == 3); | ||||||
|  | 
 | ||||||
|  |     card_data[0] = 0; | ||||||
|  |     card_data[1] = 0; | ||||||
|  |     card_data[2] = 0; | ||||||
|  | 
 | ||||||
|  |     uint32_t fc_cn = (data[0] << 16) | (data[1] << 8) | data[2]; | ||||||
|  | 
 | ||||||
|  |     // even parity sum calculation (high 12 bits of data)
 | ||||||
|  |     uint8_t even_parity_sum = 0; | ||||||
|  |     for(int8_t i = 12; i < 24; i++) { | ||||||
|  |         if(((fc_cn >> i) & 1) == 1) { | ||||||
|  |             even_parity_sum++; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     // odd parity sum calculation (low 12 bits of data)
 | ||||||
|  |     uint8_t odd_parity_sum = 1; | ||||||
|  |     for(int8_t i = 0; i < 12; i++) { | ||||||
|  |         if(((fc_cn >> i) & 1) == 1) { | ||||||
|  |             odd_parity_sum++; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     // 0x1D preamble
 | ||||||
|  |     write_raw_bit(0, 0); | ||||||
|  |     write_raw_bit(0, 1); | ||||||
|  |     write_raw_bit(0, 2); | ||||||
|  |     write_raw_bit(1, 3); | ||||||
|  |     write_raw_bit(1, 4); | ||||||
|  |     write_raw_bit(1, 5); | ||||||
|  |     write_raw_bit(0, 6); | ||||||
|  |     write_raw_bit(1, 7); | ||||||
|  | 
 | ||||||
|  |     // company / OEM code 1
 | ||||||
|  |     write_bit(0, 8); | ||||||
|  |     write_bit(0, 10); | ||||||
|  |     write_bit(0, 12); | ||||||
|  |     write_bit(0, 14); | ||||||
|  |     write_bit(0, 16); | ||||||
|  |     write_bit(0, 18); | ||||||
|  |     write_bit(1, 20); | ||||||
|  | 
 | ||||||
|  |     // card format / length 1
 | ||||||
|  |     write_bit(0, 22); | ||||||
|  |     write_bit(0, 24); | ||||||
|  |     write_bit(0, 26); | ||||||
|  |     write_bit(0, 28); | ||||||
|  |     write_bit(0, 30); | ||||||
|  |     write_bit(0, 32); | ||||||
|  |     write_bit(0, 34); | ||||||
|  |     write_bit(0, 36); | ||||||
|  |     write_bit(0, 38); | ||||||
|  |     write_bit(0, 40); | ||||||
|  |     write_bit(1, 42); | ||||||
|  | 
 | ||||||
|  |     // even parity bit
 | ||||||
|  |     write_bit((even_parity_sum % 2), 44); | ||||||
|  | 
 | ||||||
|  |     // data
 | ||||||
|  |     for(uint8_t i = 0; i < 24; i++) { | ||||||
|  |         write_bit((fc_cn >> (23 - i)) & 1, 46 + (i * 2)); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     // odd parity bit
 | ||||||
|  |     write_bit((odd_parity_sum % 2), 94); | ||||||
|  | 
 | ||||||
|     card_data_index = 0; |     card_data_index = 0; | ||||||
|  |     bit_index = 0; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void EncoderHID::write_bit(bool bit, uint8_t position) { | ||||||
|  |     write_raw_bit(bit, position + 0); | ||||||
|  |     write_raw_bit(!bit, position + 1); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void EncoderHID::write_raw_bit(bool bit, uint8_t position) { | ||||||
|  |     if(bit) { | ||||||
|  |         card_data[position / 32] |= 1UL << (31 - (position % 32)); | ||||||
|  |     } else { | ||||||
|  |         card_data[position / 32] &= ~(1UL << (31 - (position % 32))); | ||||||
|  |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void EncoderHID::get_next(bool* polarity, uint16_t* period, uint16_t* pulse) { | void EncoderHID::get_next(bool* polarity, uint16_t* period, uint16_t* pulse) { | ||||||
|     *period = 100; |     // hid 0 is 6 cycles by 8 clocks
 | ||||||
|     *pulse = 50; |     const uint8_t hid_0_period = 8; | ||||||
|  |     const uint8_t hid_0_count = 6; | ||||||
|  |     // hid 1 is 5 cycles by 10 clocks
 | ||||||
|  |     const uint8_t hid_1_period = 10; | ||||||
|  |     const uint8_t hid_1_count = 5; | ||||||
|  | 
 | ||||||
|  |     bool bit = (card_data[card_data_index / 32] >> (31 - (card_data_index % 32))) & 1; | ||||||
|  | 
 | ||||||
|     *polarity = true; |     *polarity = true; | ||||||
|  |     if(bit) { | ||||||
|  |         *period = hid_1_period; | ||||||
|  |         *pulse = hid_1_period / 2; | ||||||
|  | 
 | ||||||
|  |         bit_index++; | ||||||
|  |         if(bit_index >= hid_1_count) { | ||||||
|  |             bit_index = 0; | ||||||
|  |             card_data_index++; | ||||||
|  |             if(card_data_index >= (32 * card_data_max)) { | ||||||
|  |                 card_data_index = 0; | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |     } else { | ||||||
|  |         *period = hid_0_period; | ||||||
|  |         *pulse = hid_0_period / 2; | ||||||
|  | 
 | ||||||
|  |         bit_index++; | ||||||
|  |         if(bit_index >= hid_0_count) { | ||||||
|  |             bit_index = 0; | ||||||
|  |             card_data_index++; | ||||||
|  |             if(card_data_index >= (32 * card_data_max)) { | ||||||
|  |                 card_data_index = 0; | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |     } | ||||||
| } | } | ||||||
|  | |||||||
| @ -14,6 +14,11 @@ public: | |||||||
|     void get_next(bool* polarity, uint16_t* period, uint16_t* pulse) final; |     void get_next(bool* polarity, uint16_t* period, uint16_t* pulse) final; | ||||||
| 
 | 
 | ||||||
| private: | private: | ||||||
|     uint64_t card_data; |     static const uint8_t card_data_max = 3; | ||||||
|  |     uint32_t card_data[card_data_max]; | ||||||
|     uint8_t card_data_index; |     uint8_t card_data_index; | ||||||
|  |     uint8_t bit_index; | ||||||
|  | 
 | ||||||
|  |     void write_bit(bool bit, uint8_t position); | ||||||
|  |     void write_raw_bit(bool bit, uint8_t position); | ||||||
| }; | }; | ||||||
| @ -341,13 +341,14 @@ void RfidTimerEmulator::start(Type type) { | |||||||
|     if(encoders.count(type)) { |     if(encoders.count(type)) { | ||||||
|         current_encoder = encoders.find(type)->second; |         current_encoder = encoders.find(type)->second; | ||||||
|         uint8_t em_data[5] = {0x53, 0x00, 0x5F, 0xB3, 0xC2}; |         uint8_t em_data[5] = {0x53, 0x00, 0x5F, 0xB3, 0xC2}; | ||||||
|  |         uint8_t hid_data[3] = {0xED, 0x87, 0x70}; | ||||||
| 
 | 
 | ||||||
|         switch(type) { |         switch(type) { | ||||||
|         case Type::EM: |         case Type::EM: | ||||||
|             current_encoder->init(em_data, 5); |             current_encoder->init(em_data, 5); | ||||||
|             break; |             break; | ||||||
|         case Type::HID: |         case Type::HID: | ||||||
|             current_encoder->init(nullptr, 3); |             current_encoder->init(hid_data, 3); | ||||||
|             break; |             break; | ||||||
|         case Type::Indala: |         case Type::Indala: | ||||||
|             current_encoder->init(nullptr, 5); |             current_encoder->init(nullptr, 5); | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 SG
						SG