[FL-1059] T5577 write (#463)
* Api-hal-gpio: extend init functions * App Lfrfid: separate protocol layer * App Lfrfid: write EM key scene * App Lfrfid: syntax fix
This commit is contained in:
		
							parent
							
								
									588480831a
								
							
						
					
					
						commit
						618ddfcd04
					
				| @ -20,84 +20,13 @@ void DecoderEMMarine::reset_state() { | ||||
|         manchester_saved_state, ManchesterEventReset, &manchester_saved_state, nullptr); | ||||
| } | ||||
| 
 | ||||
| void printEM_raw(uint64_t data) { | ||||
|     // header
 | ||||
|     for(uint8_t i = 0; i < 9; i++) { | ||||
|         printf("%u ", data & (1LLU << 63) ? 1 : 0); | ||||
|         data = data << 1; | ||||
|     } | ||||
|     printf("\r\n"); | ||||
| 
 | ||||
|     // nibbles
 | ||||
|     for(uint8_t r = 0; r < 11; r++) { | ||||
|         printf("        "); | ||||
|         uint8_t value = 0; | ||||
|         for(uint8_t i = 0; i < 5; i++) { | ||||
|             printf("%u ", data & (1LLU << 63) ? 1 : 0); | ||||
|             if(i < 4) value = (value << 1) | (data & (1LLU << 63) ? 1 : 0); | ||||
|             data = data << 1; | ||||
|         } | ||||
|         printf("0x%X", value); | ||||
|         printf("\r\n"); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| void printEM_data(uint64_t data) { | ||||
|     printf("EM "); | ||||
| 
 | ||||
|     // header
 | ||||
|     for(uint8_t i = 0; i < 9; i++) { | ||||
|         data = data << 1; | ||||
|     } | ||||
| 
 | ||||
|     // nibbles
 | ||||
|     for(uint8_t r = 0; r < EM_ROW_COUNT; r++) { | ||||
|         uint8_t value = 0; | ||||
|         for(uint8_t i = 0; i < 5; i++) { | ||||
|             if(i < 4) value = (value << 1) | (data & (1LLU << 63) ? 1 : 0); | ||||
|             data = data << 1; | ||||
|         } | ||||
|         printf("%X", value); | ||||
|         if(r % 2) printf(" "); | ||||
|     } | ||||
|     printf("\r\n"); | ||||
| } | ||||
| 
 | ||||
| void copyEM_data(uint64_t data, uint8_t* result, uint8_t result_size) { | ||||
|     furi_assert(result_size >= 5); | ||||
|     uint8_t result_index = 0; | ||||
| 
 | ||||
|     // clean result
 | ||||
|     memset(result, 0, result_size); | ||||
| 
 | ||||
|     // header
 | ||||
|     for(uint8_t i = 0; i < 9; i++) { | ||||
|         data = data << 1; | ||||
|     } | ||||
| 
 | ||||
|     // nibbles
 | ||||
|     uint8_t value = 0; | ||||
|     for(uint8_t r = 0; r < EM_ROW_COUNT; r++) { | ||||
|         uint8_t nibble = 0; | ||||
|         for(uint8_t i = 0; i < 5; i++) { | ||||
|             if(i < 4) nibble = (nibble << 1) | (data & (1LLU << 63) ? 1 : 0); | ||||
|             data = data << 1; | ||||
|         } | ||||
|         value = (value << 4) | nibble; | ||||
|         if(r % 2) { | ||||
|             result[result_index] |= value; | ||||
|             result_index++; | ||||
|             value = 0; | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| bool DecoderEMMarine::read(uint8_t* data, uint8_t data_size) { | ||||
|     bool result = false; | ||||
| 
 | ||||
|     if(ready) { | ||||
|         result = true; | ||||
|         copyEM_data(readed_data, data, data_size); | ||||
|         em_marine.decode( | ||||
|             reinterpret_cast<const uint8_t*>(&readed_data), sizeof(uint64_t), data, data_size); | ||||
|         ready = false; | ||||
|     } | ||||
| 
 | ||||
| @ -132,37 +61,8 @@ void DecoderEMMarine::process_front(bool polarity, uint32_t time) { | ||||
|         if(data_ok) { | ||||
|             readed_data = (readed_data << 1) | data; | ||||
| 
 | ||||
|             // header and stop bit
 | ||||
|             if((readed_data & EM_HEADER_AND_STOP_MASK) != EM_HEADER_AND_STOP_DATA) return; | ||||
| 
 | ||||
|             // row parity
 | ||||
|             for(uint8_t i = 0; i < EM_ROW_COUNT; i++) { | ||||
|                 uint8_t parity_sum = 0; | ||||
| 
 | ||||
|                 for(uint8_t j = 0; j < 5; j++) { | ||||
|                     parity_sum += (readed_data >> (EM_FIRST_ROW_POS - i * 5 + j)) & 1; | ||||
|                 } | ||||
| 
 | ||||
|                 if((parity_sum % 2)) { | ||||
|                     return; | ||||
|                 } | ||||
|             } | ||||
| 
 | ||||
|             // columns parity
 | ||||
|             for(uint8_t i = 0; i < 4; i++) { | ||||
|                 uint8_t parity_sum = 0; | ||||
| 
 | ||||
|                 for(uint8_t j = 0; j < EM_ROW_COUNT + 1; j++) { | ||||
|                     parity_sum += (readed_data >> (EM_COLUMN_POS - i + j * 5)) & 1; | ||||
|                 } | ||||
| 
 | ||||
|                 if((parity_sum % 2)) { | ||||
|                     return; | ||||
|                 } | ||||
|             } | ||||
| 
 | ||||
|             // checks ok
 | ||||
|             ready = true; | ||||
|             ready = em_marine.can_be_decoded( | ||||
|                 reinterpret_cast<const uint8_t*>(&readed_data), sizeof(uint64_t)); | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| @ -2,7 +2,7 @@ | ||||
| #include <stdint.h> | ||||
| #include <atomic> | ||||
| #include "manchester-decoder.h" | ||||
| 
 | ||||
| #include "protocols/protocol-emmarin.h" | ||||
| class DecoderEMMarine { | ||||
| public: | ||||
|     bool read(uint8_t* data, uint8_t data_size); | ||||
| @ -17,4 +17,5 @@ private: | ||||
|     std::atomic<bool> ready; | ||||
| 
 | ||||
|     ManchesterState manchester_saved_state; | ||||
|     ProtocolEMMarin em_marine; | ||||
| }; | ||||
|  | ||||
| @ -17,11 +17,8 @@ bool DecoderHID26::read(uint8_t* data, uint8_t data_size) { | ||||
| 
 | ||||
|     if(ready) { | ||||
|         result = true; | ||||
|         data[0] = facility; | ||||
|         data[1] = (uint8_t)(number >> 8); | ||||
|         data[2] = (uint8_t)number; | ||||
| 
 | ||||
|         //printf("HID %02X %02X %02X\r\n", facility, (uint8_t)(number >> 8), (uint8_t)number);
 | ||||
|         hid.decode( | ||||
|             reinterpret_cast<const uint8_t*>(&stored_data), sizeof(uint32_t) * 3, data, data_size); | ||||
|         ready = false; | ||||
|     } | ||||
| 
 | ||||
| @ -87,94 +84,10 @@ void DecoderHID26::store_data(bool data) { | ||||
|     stored_data[0] = (stored_data[0] << 1) | ((stored_data[1] >> 31) & 1); | ||||
|     stored_data[1] = (stored_data[1] << 1) | ((stored_data[2] >> 31) & 1); | ||||
|     stored_data[2] = (stored_data[2] << 1) | data; | ||||
|     validate_stored_data(); | ||||
| } | ||||
| 
 | ||||
| void DecoderHID26::validate_stored_data() { | ||||
|     // packet preamble
 | ||||
|     // raw data
 | ||||
|     if(*(reinterpret_cast<uint8_t*>(stored_data) + 3) != 0x1D) { | ||||
|         return; | ||||
|     } | ||||
| 
 | ||||
|     // encoded company/oem
 | ||||
|     // coded with 01 = 0, 10 = 1 transitions
 | ||||
|     // stored in word 0
 | ||||
|     if((*stored_data >> 10 & 0x3FFF) != 0x1556) { | ||||
|         return; | ||||
|     } | ||||
| 
 | ||||
|     // encoded format/length
 | ||||
|     // coded with 01 = 0, 10 = 1 transitions
 | ||||
|     // stored in word 0 and word 1
 | ||||
|     if((((*stored_data & 0x3FF) << 12) | ((*(stored_data + 1) >> 20) & 0xFFF)) != 0x155556) { | ||||
|         return; | ||||
|     } | ||||
| 
 | ||||
|     // data decoding
 | ||||
|     uint32_t result = 0; | ||||
| 
 | ||||
|     // decode from word 1
 | ||||
|     // coded with 01 = 0, 10 = 1 transitions
 | ||||
|     for(int8_t i = 9; i >= 0; i--) { | ||||
|         switch((*(stored_data + 1) >> (2 * i)) & 0b11) { | ||||
|         case 0b01: | ||||
|             result = (result << 1) | 0; | ||||
|             break; | ||||
|         case 0b10: | ||||
|             result = (result << 1) | 1; | ||||
|             break; | ||||
|         default: | ||||
|             return; | ||||
|             break; | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     // decode from word 2
 | ||||
|     // coded with 01 = 0, 10 = 1 transitions
 | ||||
|     for(int8_t i = 15; i >= 0; i--) { | ||||
|         switch((*(stored_data + 2) >> (2 * i)) & 0b11) { | ||||
|         case 0b01: | ||||
|             result = (result << 1) | 0; | ||||
|             break; | ||||
|         case 0b10: | ||||
|             result = (result << 1) | 1; | ||||
|             break; | ||||
|         default: | ||||
|             return; | ||||
|             break; | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     // store decoded data
 | ||||
|     facility = result >> 17; | ||||
|     number = result >> 1; | ||||
| 
 | ||||
|     // trailing parity (odd) test
 | ||||
|     uint8_t parity_sum = 0; | ||||
|     for(int8_t i = 0; i < 13; i++) { | ||||
|         if(((result >> i) & 1) == 1) { | ||||
|             parity_sum++; | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     if((parity_sum % 2) != 1) { | ||||
|         return; | ||||
|     } | ||||
| 
 | ||||
|     // leading parity (even) test
 | ||||
|     parity_sum = 0; | ||||
|     for(int8_t i = 13; i < 26; i++) { | ||||
|         if(((result >> i) & 1) == 1) { | ||||
|             parity_sum++; | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     if((parity_sum % 2) == 1) { | ||||
|         return; | ||||
|     } | ||||
| 
 | ||||
|     if(hid.can_be_decoded(reinterpret_cast<const uint8_t*>(&stored_data), sizeof(uint32_t) * 3)) { | ||||
|         ready = true; | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| void DecoderHID26::reset_state() { | ||||
|  | ||||
| @ -1,6 +1,7 @@ | ||||
| #pragma once | ||||
| #include <stdint.h> | ||||
| #include <atomic> | ||||
| #include "protocols/protocol-hid-h10301.h" | ||||
| 
 | ||||
| class DecoderHID26 { | ||||
| public: | ||||
| @ -15,12 +16,9 @@ private: | ||||
| 
 | ||||
|     uint32_t stored_data[3] = {0, 0, 0}; | ||||
|     void store_data(bool data); | ||||
|     void validate_stored_data(); | ||||
| 
 | ||||
|     uint8_t facility = 0; | ||||
|     uint16_t number = 0; | ||||
| 
 | ||||
|     std::atomic<bool> ready; | ||||
| 
 | ||||
|     void reset_state(); | ||||
|     ProtocolHID10301 hid; | ||||
| }; | ||||
| @ -1,48 +1,14 @@ | ||||
| #include "encoder-emmarine.h" | ||||
| #include "protocols/protocol-emmarin.h" | ||||
| #include <furi.h> | ||||
| 
 | ||||
| void EncoderEM::init(const uint8_t* data, const uint8_t data_size) { | ||||
|     furi_check(data_size == 5); | ||||
|     ProtocolEMMarin em_marin; | ||||
|     em_marin.encode(data, data_size, reinterpret_cast<uint8_t*>(&card_data), sizeof(uint64_t)); | ||||
| 
 | ||||
|     // header
 | ||||
|     card_data = 0b111111111; | ||||
| 
 | ||||
|     // data
 | ||||
|     for(uint8_t i = 0; i < 5; i++) { | ||||
|         write_nibble(false, data[i]); | ||||
|         write_nibble(true, data[i]); | ||||
|     } | ||||
| 
 | ||||
|     // column parity and stop bit
 | ||||
|     uint8_t parity_sum; | ||||
| 
 | ||||
|     for(uint8_t c = 0; c < 4; c++) { | ||||
|         parity_sum = 0; | ||||
|         for(uint8_t i = 1; i <= 10; i++) { | ||||
|             uint8_t parity_bit = (card_data >> (i * 5 - 1)) & 1; | ||||
|             parity_sum += parity_bit; | ||||
|         } | ||||
|         card_data = (card_data << 1) | ((parity_sum % 2) & 1); | ||||
|     } | ||||
| 
 | ||||
|     // stop bit
 | ||||
|     card_data = (card_data << 1) | 0; | ||||
|     card_data_index = 0; | ||||
| } | ||||
| 
 | ||||
| void EncoderEM::write_nibble(bool low_nibble, uint8_t data) { | ||||
|     uint8_t parity_sum = 0; | ||||
|     uint8_t start = 0; | ||||
|     if(!low_nibble) start = 4; | ||||
| 
 | ||||
|     for(int8_t i = (start + 3); i >= start; i--) { | ||||
|         parity_sum += (data >> i) & 1; | ||||
|         card_data = (card_data << 1) | ((data >> i) & 1); | ||||
|     } | ||||
| 
 | ||||
|     card_data = (card_data << 1) | ((parity_sum % 2) & 1); | ||||
| } | ||||
| 
 | ||||
| // data transmitted as manchester encoding
 | ||||
| // 0 - high2low
 | ||||
| // 1 - low2high
 | ||||
|  | ||||
| @ -19,5 +19,4 @@ private: | ||||
| 
 | ||||
|     uint64_t card_data; | ||||
|     uint8_t card_data_index; | ||||
|     void write_nibble(bool low_nibble, uint8_t data); | ||||
| }; | ||||
| @ -1,73 +1,10 @@ | ||||
| #include "encoder-hid-h10301.h" | ||||
| #include "protocols/protocol-hid-h10301.h" | ||||
| #include <furi.h> | ||||
| 
 | ||||
| void EncoderHID_H10301::init(const uint8_t* data, const uint8_t data_size) { | ||||
|     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); | ||||
|     ProtocolHID10301 hid; | ||||
|     hid.encode(data, data_size, reinterpret_cast<uint8_t*>(&card_data), sizeof(card_data) * 3); | ||||
| 
 | ||||
|     card_data_index = 0; | ||||
|     bit_index = 0; | ||||
|  | ||||
| @ -1,102 +1,16 @@ | ||||
| #include "encoder-indala-40134.h" | ||||
| #include "protocols/protocol-indala-40134.h" | ||||
| #include <furi.h> | ||||
| 
 | ||||
| void EncoderIndala_40134::init(const uint8_t* data, const uint8_t data_size) { | ||||
|     furi_check(data_size == 3); | ||||
|     uint32_t fc_and_card = (data[0] << 16) | (data[1] << 8) | data[2]; | ||||
| 
 | ||||
|     card_data = 0; | ||||
| 
 | ||||
|     // preamble
 | ||||
|     set_bit(1, 0); | ||||
|     set_bit(1, 2); | ||||
|     set_bit(1, 32); | ||||
| 
 | ||||
|     // factory code
 | ||||
|     set_bit(((fc_and_card >> 23) & 1), 57); | ||||
|     set_bit(((fc_and_card >> 22) & 1), 49); | ||||
|     set_bit(((fc_and_card >> 21) & 1), 44); | ||||
|     set_bit(((fc_and_card >> 20) & 1), 47); | ||||
|     set_bit(((fc_and_card >> 19) & 1), 48); | ||||
|     set_bit(((fc_and_card >> 18) & 1), 53); | ||||
|     set_bit(((fc_and_card >> 17) & 1), 39); | ||||
|     set_bit(((fc_and_card >> 16) & 1), 58); | ||||
| 
 | ||||
|     // card number
 | ||||
|     set_bit(((fc_and_card >> 15) & 1), 42); | ||||
|     set_bit(((fc_and_card >> 14) & 1), 45); | ||||
|     set_bit(((fc_and_card >> 13) & 1), 43); | ||||
|     set_bit(((fc_and_card >> 12) & 1), 40); | ||||
|     set_bit(((fc_and_card >> 11) & 1), 52); | ||||
|     set_bit(((fc_and_card >> 10) & 1), 36); | ||||
|     set_bit(((fc_and_card >> 9) & 1), 35); | ||||
|     set_bit(((fc_and_card >> 8) & 1), 51); | ||||
|     set_bit(((fc_and_card >> 7) & 1), 46); | ||||
|     set_bit(((fc_and_card >> 6) & 1), 33); | ||||
|     set_bit(((fc_and_card >> 5) & 1), 37); | ||||
|     set_bit(((fc_and_card >> 4) & 1), 54); | ||||
|     set_bit(((fc_and_card >> 3) & 1), 56); | ||||
|     set_bit(((fc_and_card >> 2) & 1), 59); | ||||
|     set_bit(((fc_and_card >> 1) & 1), 50); | ||||
|     set_bit(((fc_and_card >> 0) & 1), 41); | ||||
| 
 | ||||
|     // checksum
 | ||||
|     uint8_t checksum = 0; | ||||
|     checksum += ((fc_and_card >> 14) & 1); | ||||
|     checksum += ((fc_and_card >> 12) & 1); | ||||
|     checksum += ((fc_and_card >> 9) & 1); | ||||
|     checksum += ((fc_and_card >> 8) & 1); | ||||
|     checksum += ((fc_and_card >> 6) & 1); | ||||
|     checksum += ((fc_and_card >> 5) & 1); | ||||
|     checksum += ((fc_and_card >> 2) & 1); | ||||
|     checksum += ((fc_and_card >> 0) & 1); | ||||
| 
 | ||||
|     // wiegand parity bits
 | ||||
|     // 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_and_card >> 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_and_card >> i) & 1) == 1) { | ||||
|             odd_parity_sum++; | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     // even parity bit
 | ||||
|     set_bit((even_parity_sum % 2), 34); | ||||
| 
 | ||||
|     // odd parity bit
 | ||||
|     set_bit((odd_parity_sum % 2), 38); | ||||
| 
 | ||||
|     // checksum
 | ||||
|     if((checksum & 1) == 1) { | ||||
|         set_bit(0, 62); | ||||
|         set_bit(1, 63); | ||||
|     } else { | ||||
|         set_bit(1, 62); | ||||
|         set_bit(0, 63); | ||||
|     } | ||||
|     ProtocolIndala40134 indala; | ||||
|     indala.encode(data, data_size, reinterpret_cast<uint8_t*>(&card_data), sizeof(card_data)); | ||||
| 
 | ||||
|     last_bit = card_data & 1; | ||||
|     card_data_index = 0; | ||||
|     current_polarity = true; | ||||
| } | ||||
| 
 | ||||
| void EncoderIndala_40134::set_bit(bool bit, uint8_t position) { | ||||
|     position = 63 - position; | ||||
|     if(bit) { | ||||
|         card_data |= 1ull << position; | ||||
|     } else { | ||||
|         card_data &= ~(1ull << position); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| void EncoderIndala_40134::get_next(bool* polarity, uint16_t* period, uint16_t* pulse) { | ||||
|     *period = 2; | ||||
|     *pulse = 1; | ||||
|  | ||||
| @ -20,6 +20,4 @@ private: | ||||
|     bool last_bit; | ||||
|     bool current_polarity; | ||||
|     static const uint8_t clock_per_bit = 16; | ||||
| 
 | ||||
|     void set_bit(bool bit, uint8_t position); | ||||
| }; | ||||
| @ -6,4 +6,5 @@ static const uint8_t LFRFID_KEY_SIZE = 8; | ||||
| enum class LfrfidKeyType : uint8_t { | ||||
|     KeyEmarine, | ||||
|     KeyHID, | ||||
|     KeyIndala, | ||||
| }; | ||||
							
								
								
									
										150
									
								
								applications/lf-rfid/helpers/protocols/protocol-emmarin.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										150
									
								
								applications/lf-rfid/helpers/protocols/protocol-emmarin.cpp
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,150 @@ | ||||
| #include "protocol-emmarin.h" | ||||
| #include <furi.h> | ||||
| 
 | ||||
| #define EM_HEADER_POS 55 | ||||
| #define EM_HEADER_MASK (0x1FFLLU << EM_HEADER_POS) | ||||
| 
 | ||||
| #define EM_FIRST_ROW_POS 50 | ||||
| 
 | ||||
| #define EM_ROW_COUNT 10 | ||||
| #define EM_COLUMN_COUNT 4 | ||||
| #define EM_BITS_PER_ROW_COUNT (EM_COLUMN_COUNT + 1) | ||||
| 
 | ||||
| #define EM_COLUMN_POS 4 | ||||
| #define EM_STOP_POS 0 | ||||
| #define EM_STOP_MASK (0x1LLU << EM_STOP_POS) | ||||
| 
 | ||||
| #define EM_HEADER_AND_STOP_MASK (EM_HEADER_MASK | EM_STOP_MASK) | ||||
| #define EM_HEADER_AND_STOP_DATA (EM_HEADER_MASK) | ||||
| 
 | ||||
| typedef uint64_t EMMarinCardData; | ||||
| 
 | ||||
| void write_nibble(bool low_nibble, uint8_t data, EMMarinCardData* card_data) { | ||||
|     uint8_t parity_sum = 0; | ||||
|     uint8_t start = 0; | ||||
|     if(!low_nibble) start = 4; | ||||
| 
 | ||||
|     for(int8_t i = (start + 3); i >= start; i--) { | ||||
|         parity_sum += (data >> i) & 1; | ||||
|         *card_data = (*card_data << 1) | ((data >> i) & 1); | ||||
|     } | ||||
| 
 | ||||
|     *card_data = (*card_data << 1) | ((parity_sum % 2) & 1); | ||||
| } | ||||
| 
 | ||||
| uint8_t ProtocolEMMarin::get_encoded_data_size() { | ||||
|     return sizeof(EMMarinCardData); | ||||
| } | ||||
| 
 | ||||
| uint8_t ProtocolEMMarin::get_decoded_data_size() { | ||||
|     return 5; | ||||
| } | ||||
| 
 | ||||
| void ProtocolEMMarin::encode( | ||||
|     const uint8_t* decoded_data, | ||||
|     const uint8_t decoded_data_size, | ||||
|     uint8_t* encoded_data, | ||||
|     const uint8_t encoded_data_size) { | ||||
|     furi_check(decoded_data_size >= get_decoded_data_size()); | ||||
|     furi_check(encoded_data_size >= get_encoded_data_size()); | ||||
| 
 | ||||
|     EMMarinCardData card_data; | ||||
| 
 | ||||
|     // header
 | ||||
|     card_data = 0b111111111; | ||||
| 
 | ||||
|     // data
 | ||||
|     for(uint8_t i = 0; i < get_decoded_data_size(); i++) { | ||||
|         write_nibble(false, decoded_data[i], &card_data); | ||||
|         write_nibble(true, decoded_data[i], &card_data); | ||||
|     } | ||||
| 
 | ||||
|     // column parity and stop bit
 | ||||
|     uint8_t parity_sum; | ||||
| 
 | ||||
|     for(uint8_t c = 0; c < EM_COLUMN_COUNT; c++) { | ||||
|         parity_sum = 0; | ||||
|         for(uint8_t i = 1; i <= EM_ROW_COUNT; i++) { | ||||
|             uint8_t parity_bit = (card_data >> (i * EM_BITS_PER_ROW_COUNT - 1)) & 1; | ||||
|             parity_sum += parity_bit; | ||||
|         } | ||||
|         card_data = (card_data << 1) | ((parity_sum % 2) & 1); | ||||
|     } | ||||
| 
 | ||||
|     // stop bit
 | ||||
|     card_data = (card_data << 1) | 0; | ||||
| 
 | ||||
|     memcpy(encoded_data, &card_data, get_encoded_data_size()); | ||||
| } | ||||
| 
 | ||||
| void ProtocolEMMarin::decode( | ||||
|     const uint8_t* encoded_data, | ||||
|     const uint8_t encoded_data_size, | ||||
|     uint8_t* decoded_data, | ||||
|     const uint8_t decoded_data_size) { | ||||
|     furi_check(decoded_data_size >= get_decoded_data_size()); | ||||
|     furi_check(encoded_data_size >= get_encoded_data_size()); | ||||
| 
 | ||||
|     uint8_t decoded_data_index = 0; | ||||
|     EMMarinCardData card_data = *(reinterpret_cast<const EMMarinCardData*>(encoded_data)); | ||||
| 
 | ||||
|     // clean result
 | ||||
|     memset(decoded_data, 0, decoded_data_size); | ||||
| 
 | ||||
|     // header
 | ||||
|     for(uint8_t i = 0; i < 9; i++) { | ||||
|         card_data = card_data << 1; | ||||
|     } | ||||
| 
 | ||||
|     // nibbles
 | ||||
|     uint8_t value = 0; | ||||
|     for(uint8_t r = 0; r < EM_ROW_COUNT; r++) { | ||||
|         uint8_t nibble = 0; | ||||
|         for(uint8_t i = 0; i < 5; i++) { | ||||
|             if(i < 4) nibble = (nibble << 1) | (card_data & (1LLU << 63) ? 1 : 0); | ||||
|             card_data = card_data << 1; | ||||
|         } | ||||
|         value = (value << 4) | nibble; | ||||
|         if(r % 2) { | ||||
|             decoded_data[decoded_data_index] |= value; | ||||
|             decoded_data_index++; | ||||
|             value = 0; | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| bool ProtocolEMMarin::can_be_decoded(const uint8_t* encoded_data, const uint8_t encoded_data_size) { | ||||
|     furi_check(encoded_data_size >= get_encoded_data_size()); | ||||
|     const EMMarinCardData* card_data = reinterpret_cast<const EMMarinCardData*>(encoded_data); | ||||
| 
 | ||||
|     // check header and stop bit
 | ||||
|     if((*card_data & EM_HEADER_AND_STOP_MASK) != EM_HEADER_AND_STOP_DATA) return false; | ||||
| 
 | ||||
|     // check row parity
 | ||||
|     for(uint8_t i = 0; i < EM_ROW_COUNT; i++) { | ||||
|         uint8_t parity_sum = 0; | ||||
| 
 | ||||
|         for(uint8_t j = 0; j < EM_BITS_PER_ROW_COUNT; j++) { | ||||
|             parity_sum += (*card_data >> (EM_FIRST_ROW_POS - i * EM_BITS_PER_ROW_COUNT + j)) & 1; | ||||
|         } | ||||
| 
 | ||||
|         if((parity_sum % 2)) { | ||||
|             return false; | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     // check columns parity
 | ||||
|     for(uint8_t i = 0; i < EM_COLUMN_COUNT; i++) { | ||||
|         uint8_t parity_sum = 0; | ||||
| 
 | ||||
|         for(uint8_t j = 0; j < EM_ROW_COUNT + 1; j++) { | ||||
|             parity_sum += (*card_data >> (EM_COLUMN_POS - i + j * EM_BITS_PER_ROW_COUNT)) & 1; | ||||
|         } | ||||
| 
 | ||||
|         if((parity_sum % 2)) { | ||||
|             return false; | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     return true; | ||||
| } | ||||
							
								
								
									
										22
									
								
								applications/lf-rfid/helpers/protocols/protocol-emmarin.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								applications/lf-rfid/helpers/protocols/protocol-emmarin.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,22 @@ | ||||
| #pragma once | ||||
| #include "protocol-generic.h" | ||||
| 
 | ||||
| class ProtocolEMMarin : public ProtocolGeneric { | ||||
| public: | ||||
|     uint8_t get_encoded_data_size() final; | ||||
|     uint8_t get_decoded_data_size() final; | ||||
| 
 | ||||
|     void encode( | ||||
|         const uint8_t* decoded_data, | ||||
|         const uint8_t decoded_data_size, | ||||
|         uint8_t* encoded_data, | ||||
|         const uint8_t encoded_data_size) final; | ||||
| 
 | ||||
|     void decode( | ||||
|         const uint8_t* encoded_data, | ||||
|         const uint8_t encoded_data_size, | ||||
|         uint8_t* decoded_data, | ||||
|         const uint8_t decoded_data_size) final; | ||||
| 
 | ||||
|     bool can_be_decoded(const uint8_t* encoded_data, const uint8_t encoded_data_size) final; | ||||
| }; | ||||
							
								
								
									
										60
									
								
								applications/lf-rfid/helpers/protocols/protocol-generic.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										60
									
								
								applications/lf-rfid/helpers/protocols/protocol-generic.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,60 @@ | ||||
| #pragma once | ||||
| #include "stdint.h" | ||||
| #include "stdbool.h" | ||||
| 
 | ||||
| class ProtocolGeneric { | ||||
| public: | ||||
|     /**
 | ||||
|      * @brief Get the encoded data size | ||||
|      *  | ||||
|      * @return uint8_t size of encoded data in bytes | ||||
|      */ | ||||
|     virtual uint8_t get_encoded_data_size() = 0; | ||||
| 
 | ||||
|     /**
 | ||||
|      * @brief Get the decoded data size | ||||
|      *  | ||||
|      * @return uint8_t size of decoded data in bytes | ||||
|      */ | ||||
|     virtual uint8_t get_decoded_data_size() = 0; | ||||
| 
 | ||||
|     /**
 | ||||
|      * @brief encode decoded data | ||||
|      *  | ||||
|      * @param decoded_data  | ||||
|      * @param decoded_data_size  | ||||
|      * @param encoded_data  | ||||
|      * @param encoded_data_size  | ||||
|      */ | ||||
|     virtual void encode( | ||||
|         const uint8_t* decoded_data, | ||||
|         const uint8_t decoded_data_size, | ||||
|         uint8_t* encoded_data, | ||||
|         const uint8_t encoded_data_size) = 0; | ||||
| 
 | ||||
|     /**
 | ||||
|      * @brief decode encoded data | ||||
|      *  | ||||
|      * @param encoded_data  | ||||
|      * @param encoded_data_size  | ||||
|      * @param decoded_data  | ||||
|      * @param decoded_data_size  | ||||
|      */ | ||||
|     virtual void decode( | ||||
|         const uint8_t* encoded_data, | ||||
|         const uint8_t encoded_data_size, | ||||
|         uint8_t* decoded_data, | ||||
|         const uint8_t decoded_data_size) = 0; | ||||
| 
 | ||||
|     /**
 | ||||
|      * @brief fast check that data can be correctly decoded | ||||
|      *  | ||||
|      * @param encoded_data  | ||||
|      * @param encoded_data_size  | ||||
|      * @return true - can be correctly decoded | ||||
|      * @return false - cannot be correctly decoded | ||||
|      */ | ||||
|     virtual bool can_be_decoded(const uint8_t* encoded_data, const uint8_t encoded_data_size) = 0; | ||||
| 
 | ||||
|     virtual ~ProtocolGeneric(){}; | ||||
| }; | ||||
							
								
								
									
										238
									
								
								applications/lf-rfid/helpers/protocols/protocol-hid-h10301.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										238
									
								
								applications/lf-rfid/helpers/protocols/protocol-hid-h10301.cpp
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,238 @@ | ||||
| #include "protocol-hid-h10301.h" | ||||
| #include <furi.h> | ||||
| 
 | ||||
| typedef uint32_t HID10301CardData; | ||||
| constexpr uint8_t HID10301Count = 3; | ||||
| constexpr uint8_t HID10301BitSize = sizeof(HID10301CardData) * 8; | ||||
| 
 | ||||
| static void write_raw_bit(bool bit, uint8_t position, HID10301CardData* card_data) { | ||||
|     if(bit) { | ||||
|         card_data[position / HID10301BitSize] |= | ||||
|             1UL << (HID10301BitSize - (position % HID10301BitSize) - 1); | ||||
|     } else { | ||||
|         card_data[position / (sizeof(HID10301CardData) * 8)] &= | ||||
|             ~(1UL << (HID10301BitSize - (position % HID10301BitSize) - 1)); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| static void write_bit(bool bit, uint8_t position, HID10301CardData* card_data) { | ||||
|     write_raw_bit(bit, position + 0, card_data); | ||||
|     write_raw_bit(!bit, position + 1, card_data); | ||||
| } | ||||
| 
 | ||||
| uint8_t ProtocolHID10301::get_encoded_data_size() { | ||||
|     return sizeof(HID10301CardData) * HID10301Count; | ||||
| } | ||||
| 
 | ||||
| uint8_t ProtocolHID10301::get_decoded_data_size() { | ||||
|     return 3; | ||||
| } | ||||
| 
 | ||||
| void ProtocolHID10301::encode( | ||||
|     const uint8_t* decoded_data, | ||||
|     const uint8_t decoded_data_size, | ||||
|     uint8_t* encoded_data, | ||||
|     const uint8_t encoded_data_size) { | ||||
|     furi_check(decoded_data_size >= get_decoded_data_size()); | ||||
|     furi_check(encoded_data_size >= get_encoded_data_size()); | ||||
| 
 | ||||
|     HID10301CardData card_data[HID10301Count] = {0, 0, 0}; | ||||
| 
 | ||||
|     uint32_t fc_cn = (decoded_data[0] << 16) | (decoded_data[1] << 8) | decoded_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, card_data); | ||||
|     write_raw_bit(0, 1, card_data); | ||||
|     write_raw_bit(0, 2, card_data); | ||||
|     write_raw_bit(1, 3, card_data); | ||||
|     write_raw_bit(1, 4, card_data); | ||||
|     write_raw_bit(1, 5, card_data); | ||||
|     write_raw_bit(0, 6, card_data); | ||||
|     write_raw_bit(1, 7, card_data); | ||||
| 
 | ||||
|     // company / OEM code 1
 | ||||
|     write_bit(0, 8, card_data); | ||||
|     write_bit(0, 10, card_data); | ||||
|     write_bit(0, 12, card_data); | ||||
|     write_bit(0, 14, card_data); | ||||
|     write_bit(0, 16, card_data); | ||||
|     write_bit(0, 18, card_data); | ||||
|     write_bit(1, 20, card_data); | ||||
| 
 | ||||
|     // card format / length 1
 | ||||
|     write_bit(0, 22, card_data); | ||||
|     write_bit(0, 24, card_data); | ||||
|     write_bit(0, 26, card_data); | ||||
|     write_bit(0, 28, card_data); | ||||
|     write_bit(0, 30, card_data); | ||||
|     write_bit(0, 32, card_data); | ||||
|     write_bit(0, 34, card_data); | ||||
|     write_bit(0, 36, card_data); | ||||
|     write_bit(0, 38, card_data); | ||||
|     write_bit(0, 40, card_data); | ||||
|     write_bit(1, 42, card_data); | ||||
| 
 | ||||
|     // even parity bit
 | ||||
|     write_bit((even_parity_sum % 2), 44, card_data); | ||||
| 
 | ||||
|     // data
 | ||||
|     for(uint8_t i = 0; i < 24; i++) { | ||||
|         write_bit((fc_cn >> (23 - i)) & 1, 46 + (i * 2), card_data); | ||||
|     } | ||||
| 
 | ||||
|     // odd parity bit
 | ||||
|     write_bit((odd_parity_sum % 2), 94, card_data); | ||||
| 
 | ||||
|     memcpy(encoded_data, &card_data, get_encoded_data_size()); | ||||
| } | ||||
| 
 | ||||
| void ProtocolHID10301::decode( | ||||
|     const uint8_t* encoded_data, | ||||
|     const uint8_t encoded_data_size, | ||||
|     uint8_t* decoded_data, | ||||
|     const uint8_t decoded_data_size) { | ||||
|     furi_check(decoded_data_size >= get_decoded_data_size()); | ||||
|     furi_check(encoded_data_size >= get_encoded_data_size()); | ||||
| 
 | ||||
|     const HID10301CardData* card_data = reinterpret_cast<const HID10301CardData*>(encoded_data); | ||||
| 
 | ||||
|     // data decoding
 | ||||
|     uint32_t result = 0; | ||||
| 
 | ||||
|     // decode from word 1
 | ||||
|     // coded with 01 = 0, 10 = 1 transitions
 | ||||
|     for(int8_t i = 9; i >= 0; i--) { | ||||
|         switch((*(card_data + 1) >> (2 * i)) & 0b11) { | ||||
|         case 0b01: | ||||
|             result = (result << 1) | 0; | ||||
|             break; | ||||
|         case 0b10: | ||||
|             result = (result << 1) | 1; | ||||
|             break; | ||||
|         default: | ||||
|             break; | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     // decode from word 2
 | ||||
|     // coded with 01 = 0, 10 = 1 transitions
 | ||||
|     for(int8_t i = 15; i >= 0; i--) { | ||||
|         switch((*(card_data + 2) >> (2 * i)) & 0b11) { | ||||
|         case 0b01: | ||||
|             result = (result << 1) | 0; | ||||
|             break; | ||||
|         case 0b10: | ||||
|             result = (result << 1) | 1; | ||||
|             break; | ||||
|         default: | ||||
|             break; | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     uint8_t data[3] = {(uint8_t)(result >> 17), (uint8_t)(result >> 9), (uint8_t)(result >> 1)}; | ||||
| 
 | ||||
|     memcpy(decoded_data, &data, get_decoded_data_size()); | ||||
| } | ||||
| 
 | ||||
| bool ProtocolHID10301::can_be_decoded(const uint8_t* encoded_data, const uint8_t encoded_data_size) { | ||||
|     furi_check(encoded_data_size >= get_encoded_data_size()); | ||||
| 
 | ||||
|     const HID10301CardData* card_data = reinterpret_cast<const HID10301CardData*>(encoded_data); | ||||
| 
 | ||||
|     // packet preamble
 | ||||
|     // raw data
 | ||||
|     if(*(encoded_data + 3) != 0x1D) { | ||||
|         return false; | ||||
|     } | ||||
| 
 | ||||
|     // encoded company/oem
 | ||||
|     // coded with 01 = 0, 10 = 1 transitions
 | ||||
|     // stored in word 0
 | ||||
|     if((*card_data >> 10 & 0x3FFF) != 0x1556) { | ||||
|         return false; | ||||
|     } | ||||
| 
 | ||||
|     // encoded format/length
 | ||||
|     // coded with 01 = 0, 10 = 1 transitions
 | ||||
|     // stored in word 0 and word 1
 | ||||
|     if((((*card_data & 0x3FF) << 12) | ((*(card_data + 1) >> 20) & 0xFFF)) != 0x155556) { | ||||
|         return false; | ||||
|     } | ||||
| 
 | ||||
|     // data decoding
 | ||||
|     uint32_t result = 0; | ||||
| 
 | ||||
|     // decode from word 1
 | ||||
|     // coded with 01 = 0, 10 = 1 transitions
 | ||||
|     for(int8_t i = 9; i >= 0; i--) { | ||||
|         switch((*(card_data + 1) >> (2 * i)) & 0b11) { | ||||
|         case 0b01: | ||||
|             result = (result << 1) | 0; | ||||
|             break; | ||||
|         case 0b10: | ||||
|             result = (result << 1) | 1; | ||||
|             break; | ||||
|         default: | ||||
|             return false; | ||||
|             break; | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     // decode from word 2
 | ||||
|     // coded with 01 = 0, 10 = 1 transitions
 | ||||
|     for(int8_t i = 15; i >= 0; i--) { | ||||
|         switch((*(card_data + 2) >> (2 * i)) & 0b11) { | ||||
|         case 0b01: | ||||
|             result = (result << 1) | 0; | ||||
|             break; | ||||
|         case 0b10: | ||||
|             result = (result << 1) | 1; | ||||
|             break; | ||||
|         default: | ||||
|             return false; | ||||
|             break; | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     // trailing parity (odd) test
 | ||||
|     uint8_t parity_sum = 0; | ||||
|     for(int8_t i = 0; i < 13; i++) { | ||||
|         if(((result >> i) & 1) == 1) { | ||||
|             parity_sum++; | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     if((parity_sum % 2) != 1) { | ||||
|         return false; | ||||
|     } | ||||
| 
 | ||||
|     // leading parity (even) test
 | ||||
|     parity_sum = 0; | ||||
|     for(int8_t i = 13; i < 26; i++) { | ||||
|         if(((result >> i) & 1) == 1) { | ||||
|             parity_sum++; | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     if((parity_sum % 2) == 1) { | ||||
|         return false; | ||||
|     } | ||||
| 
 | ||||
|     return true; | ||||
| } | ||||
							
								
								
									
										22
									
								
								applications/lf-rfid/helpers/protocols/protocol-hid-h10301.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								applications/lf-rfid/helpers/protocols/protocol-hid-h10301.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,22 @@ | ||||
| #pragma once | ||||
| #include "protocol-generic.h" | ||||
| 
 | ||||
| class ProtocolHID10301 : public ProtocolGeneric { | ||||
| public: | ||||
|     uint8_t get_encoded_data_size() final; | ||||
|     uint8_t get_decoded_data_size() final; | ||||
| 
 | ||||
|     void encode( | ||||
|         const uint8_t* decoded_data, | ||||
|         const uint8_t decoded_data_size, | ||||
|         uint8_t* encoded_data, | ||||
|         const uint8_t encoded_data_size) final; | ||||
| 
 | ||||
|     void decode( | ||||
|         const uint8_t* encoded_data, | ||||
|         const uint8_t encoded_data_size, | ||||
|         uint8_t* decoded_data, | ||||
|         const uint8_t decoded_data_size) final; | ||||
| 
 | ||||
|     bool can_be_decoded(const uint8_t* encoded_data, const uint8_t encoded_data_size) final; | ||||
| }; | ||||
							
								
								
									
										131
									
								
								applications/lf-rfid/helpers/protocols/protocol-indala-40134.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										131
									
								
								applications/lf-rfid/helpers/protocols/protocol-indala-40134.cpp
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,131 @@ | ||||
| #include "protocol-indala-40134.h" | ||||
| #include <furi.h> | ||||
| 
 | ||||
| typedef uint64_t Indala40134CardData; | ||||
| 
 | ||||
| static void set_bit(bool bit, uint8_t position, Indala40134CardData* card_data) { | ||||
|     position = (sizeof(Indala40134CardData) * 8) - 1 - position; | ||||
|     if(bit) { | ||||
|         *card_data |= 1ull << position; | ||||
|     } else { | ||||
|         *card_data &= ~(1ull << position); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| uint8_t ProtocolIndala40134::get_encoded_data_size() { | ||||
|     return sizeof(Indala40134CardData); | ||||
| } | ||||
| 
 | ||||
| uint8_t ProtocolIndala40134::get_decoded_data_size() { | ||||
|     return 3; | ||||
| } | ||||
| 
 | ||||
| void ProtocolIndala40134::encode( | ||||
|     const uint8_t* decoded_data, | ||||
|     const uint8_t decoded_data_size, | ||||
|     uint8_t* encoded_data, | ||||
|     const uint8_t encoded_data_size) { | ||||
|     furi_check(decoded_data_size >= get_decoded_data_size()); | ||||
|     furi_check(encoded_data_size >= get_encoded_data_size()); | ||||
| 
 | ||||
|     uint32_t fc_and_card = (decoded_data[0] << 16) | (decoded_data[1] << 8) | decoded_data[2]; | ||||
|     Indala40134CardData card_data = 0; | ||||
| 
 | ||||
|     // preamble
 | ||||
|     set_bit(1, 0, &card_data); | ||||
|     set_bit(1, 2, &card_data); | ||||
|     set_bit(1, 32, &card_data); | ||||
| 
 | ||||
|     // factory code
 | ||||
|     set_bit(((fc_and_card >> 23) & 1), 57, &card_data); | ||||
|     set_bit(((fc_and_card >> 22) & 1), 49, &card_data); | ||||
|     set_bit(((fc_and_card >> 21) & 1), 44, &card_data); | ||||
|     set_bit(((fc_and_card >> 20) & 1), 47, &card_data); | ||||
|     set_bit(((fc_and_card >> 19) & 1), 48, &card_data); | ||||
|     set_bit(((fc_and_card >> 18) & 1), 53, &card_data); | ||||
|     set_bit(((fc_and_card >> 17) & 1), 39, &card_data); | ||||
|     set_bit(((fc_and_card >> 16) & 1), 58, &card_data); | ||||
| 
 | ||||
|     // card number
 | ||||
|     set_bit(((fc_and_card >> 15) & 1), 42, &card_data); | ||||
|     set_bit(((fc_and_card >> 14) & 1), 45, &card_data); | ||||
|     set_bit(((fc_and_card >> 13) & 1), 43, &card_data); | ||||
|     set_bit(((fc_and_card >> 12) & 1), 40, &card_data); | ||||
|     set_bit(((fc_and_card >> 11) & 1), 52, &card_data); | ||||
|     set_bit(((fc_and_card >> 10) & 1), 36, &card_data); | ||||
|     set_bit(((fc_and_card >> 9) & 1), 35, &card_data); | ||||
|     set_bit(((fc_and_card >> 8) & 1), 51, &card_data); | ||||
|     set_bit(((fc_and_card >> 7) & 1), 46, &card_data); | ||||
|     set_bit(((fc_and_card >> 6) & 1), 33, &card_data); | ||||
|     set_bit(((fc_and_card >> 5) & 1), 37, &card_data); | ||||
|     set_bit(((fc_and_card >> 4) & 1), 54, &card_data); | ||||
|     set_bit(((fc_and_card >> 3) & 1), 56, &card_data); | ||||
|     set_bit(((fc_and_card >> 2) & 1), 59, &card_data); | ||||
|     set_bit(((fc_and_card >> 1) & 1), 50, &card_data); | ||||
|     set_bit(((fc_and_card >> 0) & 1), 41, &card_data); | ||||
| 
 | ||||
|     // checksum
 | ||||
|     uint8_t checksum = 0; | ||||
|     checksum += ((fc_and_card >> 14) & 1); | ||||
|     checksum += ((fc_and_card >> 12) & 1); | ||||
|     checksum += ((fc_and_card >> 9) & 1); | ||||
|     checksum += ((fc_and_card >> 8) & 1); | ||||
|     checksum += ((fc_and_card >> 6) & 1); | ||||
|     checksum += ((fc_and_card >> 5) & 1); | ||||
|     checksum += ((fc_and_card >> 2) & 1); | ||||
|     checksum += ((fc_and_card >> 0) & 1); | ||||
| 
 | ||||
|     // wiegand parity bits
 | ||||
|     // 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_and_card >> 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_and_card >> i) & 1) == 1) { | ||||
|             odd_parity_sum++; | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     // even parity bit
 | ||||
|     set_bit((even_parity_sum % 2), 34, &card_data); | ||||
| 
 | ||||
|     // odd parity bit
 | ||||
|     set_bit((odd_parity_sum % 2), 38, &card_data); | ||||
| 
 | ||||
|     // checksum
 | ||||
|     if((checksum & 1) == 1) { | ||||
|         set_bit(0, 62, &card_data); | ||||
|         set_bit(1, 63, &card_data); | ||||
|     } else { | ||||
|         set_bit(1, 62, &card_data); | ||||
|         set_bit(0, 63, &card_data); | ||||
|     } | ||||
| 
 | ||||
|     memcpy(encoded_data, &card_data, get_encoded_data_size()); | ||||
| } | ||||
| 
 | ||||
| void ProtocolIndala40134::decode( | ||||
|     const uint8_t* encoded_data, | ||||
|     const uint8_t encoded_data_size, | ||||
|     uint8_t* decoded_data, | ||||
|     const uint8_t decoded_data_size) { | ||||
|     furi_check(decoded_data_size >= get_decoded_data_size()); | ||||
|     furi_check(encoded_data_size >= get_encoded_data_size()); | ||||
|     // TODO implement decoding
 | ||||
|     furi_check(0); | ||||
| } | ||||
| 
 | ||||
| bool ProtocolIndala40134::can_be_decoded( | ||||
|     const uint8_t* encoded_data, | ||||
|     const uint8_t encoded_data_size) { | ||||
|     furi_check(encoded_data_size >= get_encoded_data_size()); | ||||
|     // TODO implement decoding
 | ||||
|     furi_check(0); | ||||
|     return false; | ||||
| } | ||||
| @ -0,0 +1,22 @@ | ||||
| #pragma once | ||||
| #include "protocol-generic.h" | ||||
| 
 | ||||
| class ProtocolIndala40134 : public ProtocolGeneric { | ||||
| public: | ||||
|     uint8_t get_encoded_data_size() final; | ||||
|     uint8_t get_decoded_data_size() final; | ||||
| 
 | ||||
|     void encode( | ||||
|         const uint8_t* decoded_data, | ||||
|         const uint8_t decoded_data_size, | ||||
|         uint8_t* encoded_data, | ||||
|         const uint8_t encoded_data_size) final; | ||||
| 
 | ||||
|     void decode( | ||||
|         const uint8_t* encoded_data, | ||||
|         const uint8_t encoded_data_size, | ||||
|         uint8_t* decoded_data, | ||||
|         const uint8_t decoded_data_size) final; | ||||
| 
 | ||||
|     bool can_be_decoded(const uint8_t* encoded_data, const uint8_t encoded_data_size) final; | ||||
| }; | ||||
							
								
								
									
										118
									
								
								applications/lf-rfid/helpers/rfid-writer.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										118
									
								
								applications/lf-rfid/helpers/rfid-writer.cpp
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,118 @@ | ||||
| #include "rfid-writer.h" | ||||
| #include <api-hal.h> | ||||
| #include "protocols/protocol-emmarin.h" | ||||
| 
 | ||||
| extern COMP_HandleTypeDef hcomp1; | ||||
| 
 | ||||
| /**
 | ||||
|  * @brief all timings are specified in field clocks (field clock = 125 kHz, 8 us) | ||||
|  *  | ||||
|  */ | ||||
| class T55xxTiming { | ||||
| public: | ||||
|     constexpr static const uint16_t wait_time = 400; | ||||
|     constexpr static const uint8_t start_gap = 15; | ||||
|     constexpr static const uint8_t write_gap = 10; | ||||
|     constexpr static const uint8_t data_0 = 24; | ||||
|     constexpr static const uint8_t data_1 = 56; | ||||
|     constexpr static const uint16_t program = 700; | ||||
| }; | ||||
| 
 | ||||
| class T55xxCmd { | ||||
| public: | ||||
|     constexpr static const uint8_t opcode_page_0 = 0b10; | ||||
|     constexpr static const uint8_t opcode_page_1 = 0b11; | ||||
|     constexpr static const uint8_t opcode_reset = 0b00; | ||||
| }; | ||||
| 
 | ||||
| RfidWriter::RfidWriter() { | ||||
| } | ||||
| 
 | ||||
| RfidWriter::~RfidWriter() { | ||||
| } | ||||
| 
 | ||||
| void RfidWriter::start() { | ||||
|     api_hal_rfid_tim_read(125000, 0.5); | ||||
|     api_hal_rfid_pins_read(); | ||||
| } | ||||
| 
 | ||||
| void RfidWriter::stop() { | ||||
|     api_hal_rfid_tim_read_stop(); | ||||
|     api_hal_rfid_tim_reset(); | ||||
|     api_hal_rfid_pins_reset(); | ||||
| } | ||||
| 
 | ||||
| void RfidWriter::write_gap(uint32_t gap_time) { | ||||
|     api_hal_rfid_tim_read_stop(); | ||||
|     delay_us(gap_time * 8); | ||||
|     api_hal_rfid_tim_read_start(); | ||||
| } | ||||
| 
 | ||||
| void RfidWriter::write_bit(bool value) { | ||||
|     if(value) { | ||||
|         delay_us(T55xxTiming::data_1 * 8); | ||||
|     } else { | ||||
|         delay_us(T55xxTiming::data_0 * 8); | ||||
|     } | ||||
|     write_gap(T55xxTiming::write_gap); | ||||
| } | ||||
| 
 | ||||
| void RfidWriter::write_byte(uint8_t value) { | ||||
|     for(uint8_t i = 0; i < 8; i++) { | ||||
|         write_bit((value >> i) & 1); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| void RfidWriter::write_block(uint8_t page, uint8_t block, bool lock_bit, uint32_t data) { | ||||
|     // wait to power card
 | ||||
|     api_hal_rfid_tim_read_start(); | ||||
|     delay_us(T55xxTiming::wait_time * 8); | ||||
| 
 | ||||
|     // start gap
 | ||||
|     write_gap(T55xxTiming::start_gap); | ||||
| 
 | ||||
|     // opcode
 | ||||
|     switch(page) { | ||||
|     case 0: | ||||
|         write_bit(1); | ||||
|         write_bit(0); | ||||
|         break; | ||||
|     case 1: | ||||
|         write_bit(1); | ||||
|         write_bit(1); | ||||
|         break; | ||||
|     default: | ||||
|         furi_check(false); | ||||
|         break; | ||||
|     } | ||||
| 
 | ||||
|     // lock bit
 | ||||
|     write_bit(lock_bit); | ||||
| 
 | ||||
|     // data
 | ||||
|     for(uint8_t i = 0; i < 32; i++) { | ||||
|         write_bit((data >> (31 - i)) & 1); | ||||
|     } | ||||
| 
 | ||||
|     // block address
 | ||||
|     write_bit((block >> 2) & 1); | ||||
|     write_bit((block >> 1) & 1); | ||||
|     write_bit((block >> 0) & 1); | ||||
| 
 | ||||
|     delay_us(T55xxTiming::program * 8); | ||||
| 
 | ||||
|     api_hal_rfid_tim_read_stop(); | ||||
| } | ||||
| 
 | ||||
| void RfidWriter::write_em(uint8_t em_data[5]) { | ||||
|     ProtocolEMMarin em_card; | ||||
|     uint64_t em_encoded_data; | ||||
|     em_card.encode(em_data, 5, reinterpret_cast<uint8_t*>(&em_encoded_data), sizeof(uint64_t)); | ||||
|     uint32_t em_config_block_data = 0b01100000000101001000000001000000; | ||||
| 
 | ||||
|     __disable_irq(); | ||||
|     write_block(0, 0, false, em_config_block_data); | ||||
|     write_block(0, 1, false, em_encoded_data); | ||||
|     write_block(0, 2, false, em_encoded_data >> 32); | ||||
|     __enable_irq(); | ||||
| } | ||||
							
								
								
									
										17
									
								
								applications/lf-rfid/helpers/rfid-writer.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								applications/lf-rfid/helpers/rfid-writer.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,17 @@ | ||||
| #pragma once | ||||
| #include "stdint.h" | ||||
| 
 | ||||
| class RfidWriter { | ||||
| public: | ||||
|     RfidWriter(); | ||||
|     ~RfidWriter(); | ||||
|     void start(); | ||||
|     void stop(); | ||||
|     void write_em(uint8_t em_data[5]); | ||||
| 
 | ||||
| private: | ||||
|     void write_gap(uint32_t gap_time); | ||||
|     void write_bit(bool value); | ||||
|     void write_byte(uint8_t value); | ||||
|     void write_block(uint8_t page, uint8_t block, bool lock_bit, uint32_t data); | ||||
| }; | ||||
| @ -144,3 +144,7 @@ RfidReader* LfrfidApp::get_reader() { | ||||
| RfidTimerEmulator* LfrfidApp::get_emulator() { | ||||
|     return &emulator; | ||||
| } | ||||
| 
 | ||||
| RfidWriter* LfrfidApp::get_writer() { | ||||
|     return &writer; | ||||
| } | ||||
| @ -10,6 +10,7 @@ | ||||
| #include "scene/lf-rfid-scene-read-normal.h" | ||||
| #include "scene/lf-rfid-scene-read-indala.h" | ||||
| #include "scene/lf-rfid-scene-tune.h" | ||||
| #include "scene/lf-rfid-scene-write.h" | ||||
| 
 | ||||
| #include "helpers/rfid-reader.h" | ||||
| #include "helpers/rfid-timer-emulator.h" | ||||
| @ -30,6 +31,7 @@ public: | ||||
|         EmulateHID, | ||||
|         EmulateEM, | ||||
|         Tune, | ||||
|         Write, | ||||
|     }; | ||||
| 
 | ||||
|     LfrfidAppViewManager* get_view_manager(); | ||||
| @ -49,6 +51,7 @@ public: | ||||
| 
 | ||||
|     RfidReader* get_reader(); | ||||
|     RfidTimerEmulator* get_emulator(); | ||||
|     RfidWriter* get_writer(); | ||||
| 
 | ||||
| private: | ||||
|     std::list<Scene> previous_scenes_list = {Scene::Exit}; | ||||
| @ -63,6 +66,7 @@ private: | ||||
|         {Scene::EmulateHID, new LfrfidSceneEmulateHID()}, | ||||
|         {Scene::EmulateEM, new LfrfidSceneEmulateEMMarine()}, | ||||
|         {Scene::Tune, new LfrfidSceneTune()}, | ||||
|         {Scene::Write, new LfrfidSceneWrite()}, | ||||
|     }; | ||||
| 
 | ||||
|     static const uint8_t text_store_size = 128; | ||||
| @ -70,4 +74,5 @@ private: | ||||
| 
 | ||||
|     RfidReader reader; | ||||
|     RfidTimerEmulator emulator; | ||||
|     RfidWriter writer; | ||||
| }; | ||||
| @ -55,6 +55,15 @@ bool LfrfidSceneReadNormal::on_event(LfrfidApp* app, LfrfidEvent* event) { | ||||
|                     data[2], | ||||
|                     success_reads); | ||||
|                 break; | ||||
|             case LfrfidKeyType::KeyIndala: | ||||
|                 app->set_text_store( | ||||
|                     "[IND] %02X %02X %02X\n" | ||||
|                     "count: %u", | ||||
|                     data[0], | ||||
|                     data[1], | ||||
|                     data[2], | ||||
|                     success_reads); | ||||
|                 break; | ||||
|             } | ||||
|             popup_set_text( | ||||
|                 app->get_view_manager()->get_popup(), | ||||
|  | ||||
| @ -5,6 +5,7 @@ | ||||
| #include <callback-connector.h> | ||||
| 
 | ||||
| typedef enum { | ||||
|     SubmenuIndexWrite, | ||||
|     SubmenuIndexReadNormal, | ||||
|     SubmenuIndexReadIndala, | ||||
|     SubmenuIndexEmulateEM, | ||||
| @ -18,6 +19,7 @@ void LfrfidSceneStart::on_enter(LfrfidApp* app) { | ||||
|     Submenu* submenu = view_manager->get_submenu(); | ||||
|     auto callback = cbc::obtain_connector(this, &LfrfidSceneStart::submenu_callback); | ||||
| 
 | ||||
|     submenu_add_item(submenu, "Write T5577", SubmenuIndexWrite, callback, app); | ||||
|     submenu_add_item(submenu, "Read Normal", SubmenuIndexReadNormal, callback, app); | ||||
|     submenu_add_item(submenu, "Read Indala", SubmenuIndexReadIndala, callback, app); | ||||
|     submenu_add_item(submenu, "Emulate EM", SubmenuIndexEmulateEM, callback, app); | ||||
| @ -33,6 +35,9 @@ bool LfrfidSceneStart::on_event(LfrfidApp* app, LfrfidEvent* event) { | ||||
| 
 | ||||
|     if(event->type == LfrfidEvent::Type::MenuSelected) { | ||||
|         switch(event->payload.menu_index) { | ||||
|         case SubmenuIndexWrite: | ||||
|             app->switch_to_next_scene(LfrfidApp::Scene::Write); | ||||
|             break; | ||||
|         case SubmenuIndexReadNormal: | ||||
|             app->switch_to_next_scene(LfrfidApp::Scene::ReadNormal); | ||||
|             break; | ||||
|  | ||||
							
								
								
									
										70
									
								
								applications/lf-rfid/scene/lf-rfid-scene-write.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										70
									
								
								applications/lf-rfid/scene/lf-rfid-scene-write.cpp
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,70 @@ | ||||
| #include "lf-rfid-scene-write.h" | ||||
| 
 | ||||
| #include "../lf-rfid-app.h" | ||||
| #include "../lf-rfid-view-manager.h" | ||||
| #include "../lf-rfid-event.h" | ||||
| #include "../helpers/key-info.h" | ||||
| 
 | ||||
| void LfrfidSceneWrite::on_enter(LfrfidApp* app) { | ||||
|     LfrfidAppViewManager* view_manager = app->get_view_manager(); | ||||
| 
 | ||||
|     Popup* popup = view_manager->get_popup(); | ||||
|     popup_set_header(popup, "LF-RFID", 64, 16, AlignCenter, AlignBottom); | ||||
|     app->set_text_store("Writing..."); | ||||
|     popup_set_text(popup, app->get_text_store(), 64, 22, AlignCenter, AlignTop); | ||||
| 
 | ||||
|     view_manager->switch_to(LfrfidAppViewManager::ViewType::Popup); | ||||
| 
 | ||||
|     timing_index = 0; | ||||
| } | ||||
| 
 | ||||
| bool LfrfidSceneWrite::on_event(LfrfidApp* app, LfrfidEvent* event) { | ||||
|     bool consumed = false; | ||||
| 
 | ||||
|     // TODO move read\write logic to key worker
 | ||||
| 
 | ||||
|     bool readed = false; | ||||
|     uint8_t em_data[5] = {0x1A, 0x2B, 0xC3, 0xD4, 0xE5}; | ||||
| 
 | ||||
|     if(timing_index == 0) { | ||||
|         app->get_reader()->stop(); | ||||
|         app->get_writer()->start(); | ||||
|         app->get_writer()->write_em(em_data); | ||||
|         app->get_writer()->stop(); | ||||
|         delay(100); | ||||
|         app->get_reader()->start(RfidReader::Type::Normal); | ||||
|     } else { | ||||
|         uint8_t data[LFRFID_KEY_SIZE]; | ||||
|         LfrfidKeyType type; | ||||
| 
 | ||||
|         app->get_reader()->read(&type, data, LFRFID_KEY_SIZE); | ||||
|         if(type == LfrfidKeyType::KeyEmarine) { | ||||
|             if(memcmp(em_data, data, 5) == 0) { | ||||
|                 readed = true; | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     if(readed) { | ||||
|         app->set_text_store("Writed!"); | ||||
|         app->notify_green_blink(); | ||||
|     } else { | ||||
|         app->set_text_store("Writing [1A 2B C3 D4 E5]"); | ||||
|         timing_index++; | ||||
|         if(timing_index == 4) { | ||||
|             timing_index = 0; | ||||
|         } | ||||
|     } | ||||
|     popup_set_text( | ||||
|         app->get_view_manager()->get_popup(), app->get_text_store(), 64, 22, AlignCenter, AlignTop); | ||||
| 
 | ||||
|     return consumed; | ||||
| } | ||||
| 
 | ||||
| void LfrfidSceneWrite::on_exit(LfrfidApp* app) { | ||||
|     LfrfidAppViewManager* view_manager = app->get_view_manager(); | ||||
| 
 | ||||
|     Popup* popup = view_manager->get_popup(); | ||||
|     popup_set_header(popup, NULL, 0, 0, AlignCenter, AlignBottom); | ||||
|     popup_set_text(popup, NULL, 0, 0, AlignCenter, AlignTop); | ||||
| } | ||||
							
								
								
									
										14
									
								
								applications/lf-rfid/scene/lf-rfid-scene-write.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								applications/lf-rfid/scene/lf-rfid-scene-write.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,14 @@ | ||||
| #pragma once | ||||
| #include "lf-rfid-scene-generic.h" | ||||
| #include "../helpers/key-info.h" | ||||
| #include "../helpers/rfid-writer.h" | ||||
| 
 | ||||
| class LfrfidSceneWrite : public LfrfidScene { | ||||
| public: | ||||
|     void on_enter(LfrfidApp* app) final; | ||||
|     bool on_event(LfrfidApp* app, LfrfidEvent* event) final; | ||||
|     void on_exit(LfrfidApp* app) final; | ||||
| 
 | ||||
| private: | ||||
|     uint8_t timing_index; | ||||
| }; | ||||
| @ -41,11 +41,28 @@ static uint8_t hal_gpio_get_pin_num(const GpioPin* gpio) { | ||||
|     return pin_num; | ||||
| } | ||||
| 
 | ||||
| void hal_gpio_init_simple(const GpioPin* gpio, const GpioMode mode) { | ||||
|     hal_gpio_init(gpio, mode, GpioPullNo, GpioSpeedLow); | ||||
| } | ||||
| 
 | ||||
| void hal_gpio_init( | ||||
|     const GpioPin* gpio, | ||||
|     const GpioMode mode, | ||||
|     const GpioPull pull, | ||||
|     const GpioSpeed speed) { | ||||
|     // we cannot set alternate mode in this function
 | ||||
|     furi_assert(mode != GpioModeAltFunctionPushPull); | ||||
|     furi_assert(mode != GpioModeAltFunctionOpenDrain); | ||||
| 
 | ||||
|     hal_gpio_init_ex(gpio, mode, GpioPullNo, GpioSpeedLow, GpioAltFnUnused); | ||||
| } | ||||
| 
 | ||||
| void hal_gpio_init_ex( | ||||
|     const GpioPin* gpio, | ||||
|     const GpioMode mode, | ||||
|     const GpioPull pull, | ||||
|     const GpioSpeed speed, | ||||
|     const GpioAltFn alt_fn) { | ||||
|     uint32_t sys_exti_port = GET_SYSCFG_EXTI_PORT(gpio->port); | ||||
|     uint32_t sys_exti_line = GET_SYSCFG_EXTI_LINE(gpio->pin); | ||||
|     uint32_t exti_line = GET_EXTI_LINE(gpio->pin); | ||||
| @ -112,18 +129,8 @@ void hal_gpio_init( | ||||
|             LL_GPIO_SetPinMode(gpio->port, gpio->pin, LL_GPIO_MODE_ANALOG); | ||||
|         } | ||||
|     } | ||||
|     __enable_irq(); | ||||
| } | ||||
| 
 | ||||
| void hal_gpio_init_alt( | ||||
|     const GpioPin* gpio, | ||||
|     const GpioMode mode, | ||||
|     const GpioPull pull, | ||||
|     const GpioSpeed speed, | ||||
|     const GpioAltFn alt_fn) { | ||||
|     hal_gpio_init(gpio, mode, pull, speed); | ||||
| 
 | ||||
|     __disable_irq(); | ||||
|     if(mode == GpioModeAltFunctionPushPull || mode == GpioModeAltFunctionOpenDrain) { | ||||
|         // enable alternate mode
 | ||||
|         LL_GPIO_SetPinMode(gpio->port, gpio->pin, LL_GPIO_MODE_ALTERNATE); | ||||
| 
 | ||||
| @ -133,6 +140,8 @@ void hal_gpio_init_alt( | ||||
|         } else { | ||||
|             LL_GPIO_SetAFPin_8_15(gpio->port, gpio->pin, alt_fn); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     __enable_irq(); | ||||
| } | ||||
| 
 | ||||
|  | ||||
| @ -153,6 +153,8 @@ typedef enum { | ||||
|     GpioAltFn14LPTIM2 = 14, /*!< LPTIM2 Alternate Function mapping */ | ||||
| 
 | ||||
|     GpioAltFn15EVENTOUT = 15, /*!< EVENTOUT Alternate Function mapping */ | ||||
| 
 | ||||
|     GpioAltFnUnused = 16, /*!< just dummy value */ | ||||
| } GpioAltFn; | ||||
| 
 | ||||
| /**
 | ||||
| @ -164,7 +166,14 @@ typedef struct { | ||||
| } GpioPin; | ||||
| 
 | ||||
| /**
 | ||||
|  * GPIO initialization function | ||||
|  * GPIO initialization function, simple version | ||||
|  * @param gpio  GpioPin | ||||
|  * @param mode  GpioMode | ||||
|  */ | ||||
| void hal_gpio_init_simple(const GpioPin* gpio, const GpioMode mode); | ||||
| 
 | ||||
| /**
 | ||||
|  * GPIO initialization function, normal version | ||||
|  * @param gpio  GpioPin | ||||
|  * @param mode  GpioMode | ||||
|  * @param pull  GpioPull | ||||
| @ -177,14 +186,14 @@ void hal_gpio_init( | ||||
|     const GpioSpeed speed); | ||||
| 
 | ||||
| /**
 | ||||
|  * GPIO initialization with alternative function | ||||
|  * GPIO initialization function, extended version | ||||
|  * @param gpio  GpioPin | ||||
|  * @param mode  GpioMode | ||||
|  * @param pull  GpioPull | ||||
|  * @param speed GpioSpeed | ||||
|  * @param alt_fn GpioAltFn | ||||
|  */ | ||||
| void hal_gpio_init_alt( | ||||
| void hal_gpio_init_ex( | ||||
|     const GpioPin* gpio, | ||||
|     const GpioMode mode, | ||||
|     const GpioPull pull, | ||||
|  | ||||
| @ -21,8 +21,8 @@ void api_hal_rfid_pins_emulate() { | ||||
|     api_hal_ibutton_pin_low(); | ||||
| 
 | ||||
|     // pull pin to timer out
 | ||||
|     hal_gpio_init_alt( | ||||
|         &gpio_rfid_pull, GpioModeOutputPushPull, GpioSpeedLow, GpioPullNo, GpioAltFn1TIM1); | ||||
|     hal_gpio_init_ex( | ||||
|         &gpio_rfid_pull, GpioModeAltFunctionPushPull, GpioSpeedLow, GpioPullNo, GpioAltFn1TIM1); | ||||
| 
 | ||||
|     // pull rfid antenna from carrier side
 | ||||
|     hal_gpio_init(&gpio_rfid_carrier_out, GpioModeOutputPushPull, GpioSpeedLow, GpioPullNo); | ||||
| @ -39,8 +39,12 @@ void api_hal_rfid_pins_read() { | ||||
|     hal_gpio_write(&gpio_rfid_pull, false); | ||||
| 
 | ||||
|     // carrier pin to timer out
 | ||||
|     hal_gpio_init_alt( | ||||
|         &gpio_rfid_carrier_out, GpioModeOutputPushPull, GpioSpeedLow, GpioPullNo, GpioAltFn1TIM1); | ||||
|     hal_gpio_init_ex( | ||||
|         &gpio_rfid_carrier_out, | ||||
|         GpioModeAltFunctionPushPull, | ||||
|         GpioSpeedLow, | ||||
|         GpioPullNo, | ||||
|         GpioAltFn1TIM1); | ||||
| 
 | ||||
|     // comparator in
 | ||||
|     hal_gpio_init(&gpio_rfid_data_in, GpioModeAnalog, GpioSpeedLow, GpioPullNo); | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 SG
						SG