[FL-1449] Indala reading and writing (#616)
* Rfid: indala 40134 validation and decoding * Rfid: show indala info * Rfid: decoder to output comparator signal on gpio pins * Rfid: working indala 40134 decoder * HAL: added function to change rfid timer parameters on the fly * RFID: Indala reading, card detection, card verification * Rfid: indala writing
This commit is contained in:
		
							parent
							
								
									fb80f9537f
								
							
						
					
					
						commit
						6926cf8b7e
					
				
							
								
								
									
										15
									
								
								applications/lfrfid/helpers/decoder-gpio-out.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								applications/lfrfid/helpers/decoder-gpio-out.cpp
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,15 @@ | |||||||
|  | #include "decoder-gpio-out.h" | ||||||
|  | #include <furi.h> | ||||||
|  | #include <api-hal.h> | ||||||
|  | 
 | ||||||
|  | void DecoderGpioOut::process_front(bool polarity, uint32_t time) { | ||||||
|  |     hal_gpio_write(&gpio_ext_pa7, polarity); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | DecoderGpioOut::DecoderGpioOut() { | ||||||
|  |     hal_gpio_init_simple(&gpio_ext_pa7, GpioModeOutputPushPull); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | DecoderGpioOut::~DecoderGpioOut() { | ||||||
|  |     hal_gpio_init_simple(&gpio_ext_pa7, GpioModeAnalog); | ||||||
|  | } | ||||||
							
								
								
									
										14
									
								
								applications/lfrfid/helpers/decoder-gpio-out.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								applications/lfrfid/helpers/decoder-gpio-out.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,14 @@ | |||||||
|  | #pragma once | ||||||
|  | #include <stdint.h> | ||||||
|  | #include <atomic> | ||||||
|  | 
 | ||||||
|  | class DecoderGpioOut { | ||||||
|  | public: | ||||||
|  |     void process_front(bool polarity, uint32_t time); | ||||||
|  | 
 | ||||||
|  |     DecoderGpioOut(); | ||||||
|  |     ~DecoderGpioOut(); | ||||||
|  | 
 | ||||||
|  | private: | ||||||
|  |     void reset_state(); | ||||||
|  | }; | ||||||
| @ -2,18 +2,24 @@ | |||||||
| #include <api-hal.h> | #include <api-hal.h> | ||||||
| 
 | 
 | ||||||
| constexpr uint32_t clocks_in_us = 64; | constexpr uint32_t clocks_in_us = 64; | ||||||
| 
 | constexpr uint32_t us_per_bit = 255; | ||||||
| constexpr uint32_t min_time_us = 25 * clocks_in_us; |  | ||||||
| constexpr uint32_t mid_time_us = 45 * clocks_in_us; |  | ||||||
| constexpr uint32_t max_time_us = 90 * clocks_in_us; |  | ||||||
| 
 | 
 | ||||||
| bool DecoderIndala::read(uint8_t* data, uint8_t data_size) { | bool DecoderIndala::read(uint8_t* data, uint8_t data_size) { | ||||||
|     bool result = false; |     bool result = false; | ||||||
| 
 | 
 | ||||||
|     if(ready) { |     if(ready) { | ||||||
|         result = true; |         result = true; | ||||||
|         printf("IND %02X %02X %02X\r\n", facility, (uint8_t)(number >> 8), (uint8_t)number); |         if(cursed_data_valid) { | ||||||
|         ready = false; |             indala.decode( | ||||||
|  |                 reinterpret_cast<const uint8_t*>(&cursed_raw_data), | ||||||
|  |                 sizeof(uint64_t), | ||||||
|  |                 data, | ||||||
|  |                 data_size); | ||||||
|  |         } else { | ||||||
|  |             indala.decode( | ||||||
|  |                 reinterpret_cast<const uint8_t*>(&raw_data), sizeof(uint64_t), data, data_size); | ||||||
|  |         } | ||||||
|  |         reset_state(); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     return result; |     return result; | ||||||
| @ -22,149 +28,49 @@ bool DecoderIndala::read(uint8_t* data, uint8_t data_size) { | |||||||
| void DecoderIndala::process_front(bool polarity, uint32_t time) { | void DecoderIndala::process_front(bool polarity, uint32_t time) { | ||||||
|     if(ready) return; |     if(ready) return; | ||||||
| 
 | 
 | ||||||
|     if(polarity == false) { |     process_internal(polarity, time, &raw_data); | ||||||
|         last_pulse_time = time; |     if(ready) return; | ||||||
|     } else { |  | ||||||
|         last_pulse_time += time; |  | ||||||
|         pulse_count++; |  | ||||||
| 
 | 
 | ||||||
|         if(last_pulse_time > min_time_us && last_pulse_time < max_time_us) { |     if(polarity) { | ||||||
|             if(last_pulse_time > mid_time_us) { |         time = time + 110; | ||||||
|                 bool last_data = !(readed_data & 1); |     } else { | ||||||
|                 pulse_count = 0; |         time = time - 110; | ||||||
|                 readed_data = (readed_data << 1) | last_data; |     } | ||||||
|                 verify(); | 
 | ||||||
|             } else if((pulse_count % 16) == 0) { |     process_internal(!polarity, time, &cursed_raw_data); | ||||||
|                 bool last_data = readed_data & 1; |     if(ready) { | ||||||
|                 pulse_count = 0; |         cursed_data_valid = true; | ||||||
|                 readed_data = (readed_data << 1) | last_data; |     } | ||||||
|                 verify(); | } | ||||||
|  | 
 | ||||||
|  | void DecoderIndala::process_internal(bool polarity, uint32_t time, uint64_t* data) { | ||||||
|  |     time /= clocks_in_us; | ||||||
|  |     time += (us_per_bit / 2); | ||||||
|  | 
 | ||||||
|  |     uint32_t bit_count = (time / us_per_bit); | ||||||
|  | 
 | ||||||
|  |     if(bit_count < 64) { | ||||||
|  |         for(uint32_t i = 0; i < bit_count; i++) { | ||||||
|  |             *data = (*data << 1) | polarity; | ||||||
|  | 
 | ||||||
|  |             if((*data >> 32) == 0xa0000000ULL) { | ||||||
|  |                 if(indala.can_be_decoded( | ||||||
|  |                        reinterpret_cast<const uint8_t*>(data), sizeof(uint64_t))) { | ||||||
|  |                     ready = true; | ||||||
|  |                     break; | ||||||
|  |                 } | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| DecoderIndala::DecoderIndala() { | DecoderIndala::DecoderIndala() { | ||||||
|  |     reset_state(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void DecoderIndala::reset_state() { | void DecoderIndala::reset_state() { | ||||||
| } |     raw_data = 0; | ||||||
| 
 |     cursed_raw_data = 0; | ||||||
| void DecoderIndala::verify() { |     ready = false; | ||||||
|     // verify inverse
 |     cursed_data_valid = false; | ||||||
|     readed_data = ~readed_data; |  | ||||||
|     verify_inner(); |  | ||||||
| 
 |  | ||||||
|     // verify normal
 |  | ||||||
|     readed_data = ~readed_data; |  | ||||||
|     verify_inner(); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| typedef union { |  | ||||||
|     uint64_t raw; |  | ||||||
|     struct __attribute__((packed)) { |  | ||||||
|         uint8_t static0 : 3; |  | ||||||
|         uint8_t checksum : 2; |  | ||||||
|         uint8_t static1 : 2; |  | ||||||
|         uint8_t y14 : 1; |  | ||||||
| 
 |  | ||||||
|         uint8_t x8 : 1; |  | ||||||
|         uint8_t x1 : 1; |  | ||||||
|         uint8_t y13 : 1; |  | ||||||
|         uint8_t static2 : 1; |  | ||||||
|         uint8_t y12 : 1; |  | ||||||
|         uint8_t x6 : 1; |  | ||||||
|         uint8_t y5 : 1; |  | ||||||
|         uint8_t y8 : 1; |  | ||||||
| 
 |  | ||||||
|         uint8_t y15 : 1; |  | ||||||
|         uint8_t x2 : 1; |  | ||||||
|         uint8_t x5 : 1; |  | ||||||
|         uint8_t x4 : 1; |  | ||||||
|         uint8_t y9 : 1; |  | ||||||
|         uint8_t y2 : 1; |  | ||||||
|         uint8_t x3 : 1; |  | ||||||
|         uint8_t y3 : 1; |  | ||||||
| 
 |  | ||||||
|         uint8_t y1 : 1; |  | ||||||
|         uint8_t y16 : 1; |  | ||||||
|         uint8_t y4 : 1; |  | ||||||
|         uint8_t x7 : 1; |  | ||||||
|         uint8_t p2 : 1; |  | ||||||
|         uint8_t y11 : 1; |  | ||||||
|         uint8_t y6 : 1; |  | ||||||
|         uint8_t y7 : 1; |  | ||||||
| 
 |  | ||||||
|         uint8_t p1 : 1; |  | ||||||
|         uint8_t y10 : 1; |  | ||||||
|         uint32_t preamble : 30; |  | ||||||
|     }; |  | ||||||
| } IndalaFormat; |  | ||||||
| 
 |  | ||||||
| void DecoderIndala::verify_inner() { |  | ||||||
|     IndalaFormat id; |  | ||||||
|     id.raw = readed_data; |  | ||||||
| 
 |  | ||||||
|     // preamble
 |  | ||||||
|     //if((data >> 34) != 0b000000000000000000000000000001) return;
 |  | ||||||
|     if(id.preamble != 1) return; |  | ||||||
| 
 |  | ||||||
|     // static data bits
 |  | ||||||
|     //if((data & 0b100001100111) != 0b101) return;
 |  | ||||||
|     if(id.static2 != 0 && id.static1 != 0 && id.static0 != 0b101) return; |  | ||||||
| 
 |  | ||||||
|     // Indala checksum
 |  | ||||||
|     uint8_t sum_to_check = id.y2 + id.y4 + id.y7 + id.y8 + id.y10 + id.y11 + id.y14 + id.y16; |  | ||||||
| 
 |  | ||||||
|     if(sum_to_check % 2 == 0) { |  | ||||||
|         if(id.checksum != 0b10) return; |  | ||||||
|     } else { |  | ||||||
|         if(id.checksum != 0b01) return; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     // read facility number
 |  | ||||||
|     facility = (id.x1 << 7) + (id.x2 << 6) + (id.x3 << 5) + (id.x4 << 4) + (id.x5 << 3) + |  | ||||||
|                (id.x6 << 2) + (id.x7 << 1) + (id.x8 << 0); |  | ||||||
| 
 |  | ||||||
|     // read serial number
 |  | ||||||
|     number = (id.y1 << 15) + (id.y2 << 14) + (id.y3 << 13) + (id.y4 << 12) + (id.y5 << 11) + |  | ||||||
|              (id.y6 << 10) + (id.y7 << 9) + (id.y8 << 8) + (id.y9 << 7) + (id.y10 << 6) + |  | ||||||
|              (id.y11 << 5) + (id.y12 << 4) + (id.y13 << 3) + (id.y14 << 2) + (id.y15 << 1) + |  | ||||||
|              (id.y16 << 0); |  | ||||||
| 
 |  | ||||||
|     // Wiegand checksum left
 |  | ||||||
|     sum_to_check = 0; |  | ||||||
|     for(int8_t i = 0; i < 8; i--) { |  | ||||||
|         if((facility >> i) & 1) { |  | ||||||
|             sum_to_check += 1; |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     for(int8_t i = 0; i < 4; i--) { |  | ||||||
|         if((number >> i) & 1) { |  | ||||||
|             sum_to_check += 1; |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     if(id.p1) { |  | ||||||
|         sum_to_check += 1; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     if((sum_to_check % 2) == 1) return; |  | ||||||
| 
 |  | ||||||
|     // Wiegand checksum right
 |  | ||||||
|     sum_to_check = 0; |  | ||||||
|     for(int8_t i = 0; i < 12; i--) { |  | ||||||
|         if((number >> (i + 4)) & 1) { |  | ||||||
|             sum_to_check += 1; |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     if(id.p2) { |  | ||||||
|         sum_to_check += 1; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     if((sum_to_check % 2) != 1) return; |  | ||||||
| 
 |  | ||||||
|     ready = true; |  | ||||||
| } | } | ||||||
| @ -2,27 +2,24 @@ | |||||||
| #include <stdint.h> | #include <stdint.h> | ||||||
| #include <limits.h> | #include <limits.h> | ||||||
| #include <atomic> | #include <atomic> | ||||||
|  | #include "protocols/protocol-indala-40134.h" | ||||||
| 
 | 
 | ||||||
| class DecoderIndala { | class DecoderIndala { | ||||||
| public: | public: | ||||||
|     bool read(uint8_t* data, uint8_t data_size); |     bool read(uint8_t* data, uint8_t data_size); | ||||||
|     void process_front(bool polarity, uint32_t time); |     void process_front(bool polarity, uint32_t time); | ||||||
| 
 | 
 | ||||||
|  |     void process_internal(bool polarity, uint32_t time, uint64_t* data); | ||||||
|  | 
 | ||||||
|     DecoderIndala(); |     DecoderIndala(); | ||||||
| 
 | 
 | ||||||
| private: | private: | ||||||
|     void reset_state(); |     void reset_state(); | ||||||
| 
 | 
 | ||||||
|     void verify(); |     uint64_t raw_data; | ||||||
|     void verify_inner(); |     uint64_t cursed_raw_data; | ||||||
| 
 |  | ||||||
|     uint32_t last_pulse_time = 0; |  | ||||||
|     uint32_t pulse_count = 0; |  | ||||||
|     uint32_t overall_pulse_count = 0; |  | ||||||
| 
 |  | ||||||
|     uint64_t readed_data = 0; |  | ||||||
| 
 | 
 | ||||||
|     std::atomic<bool> ready; |     std::atomic<bool> ready; | ||||||
|     uint8_t facility = 0; |     std::atomic<bool> cursed_data_valid; | ||||||
|     uint16_t number = 0; |     ProtocolIndala40134 indala; | ||||||
| }; | }; | ||||||
| @ -12,6 +12,11 @@ static void set_bit(bool bit, uint8_t position, Indala40134CardData* card_data) | |||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | static bool get_bit(uint8_t position, const Indala40134CardData* card_data) { | ||||||
|  |     position = (sizeof(Indala40134CardData) * 8) - 1 - position; | ||||||
|  |     return (*card_data >> position) & 1; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| uint8_t ProtocolIndala40134::get_encoded_data_size() { | uint8_t ProtocolIndala40134::get_encoded_data_size() { | ||||||
|     return sizeof(Indala40134CardData); |     return sizeof(Indala40134CardData); | ||||||
| } | } | ||||||
| @ -110,6 +115,46 @@ void ProtocolIndala40134::encode( | |||||||
|     memcpy(encoded_data, &card_data, get_encoded_data_size()); |     memcpy(encoded_data, &card_data, get_encoded_data_size()); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | // factory code
 | ||||||
|  | static uint8_t get_fc(const Indala40134CardData* card_data) { | ||||||
|  |     uint8_t fc = 0; | ||||||
|  | 
 | ||||||
|  |     fc = fc << 1 | get_bit(57, card_data); | ||||||
|  |     fc = fc << 1 | get_bit(49, card_data); | ||||||
|  |     fc = fc << 1 | get_bit(44, card_data); | ||||||
|  |     fc = fc << 1 | get_bit(47, card_data); | ||||||
|  |     fc = fc << 1 | get_bit(48, card_data); | ||||||
|  |     fc = fc << 1 | get_bit(53, card_data); | ||||||
|  |     fc = fc << 1 | get_bit(39, card_data); | ||||||
|  |     fc = fc << 1 | get_bit(58, card_data); | ||||||
|  | 
 | ||||||
|  |     return fc; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // card number
 | ||||||
|  | static uint16_t get_cn(const Indala40134CardData* card_data) { | ||||||
|  |     uint16_t cn = 0; | ||||||
|  | 
 | ||||||
|  |     cn = cn << 1 | get_bit(42, card_data); | ||||||
|  |     cn = cn << 1 | get_bit(45, card_data); | ||||||
|  |     cn = cn << 1 | get_bit(43, card_data); | ||||||
|  |     cn = cn << 1 | get_bit(40, card_data); | ||||||
|  |     cn = cn << 1 | get_bit(52, card_data); | ||||||
|  |     cn = cn << 1 | get_bit(36, card_data); | ||||||
|  |     cn = cn << 1 | get_bit(35, card_data); | ||||||
|  |     cn = cn << 1 | get_bit(51, card_data); | ||||||
|  |     cn = cn << 1 | get_bit(46, card_data); | ||||||
|  |     cn = cn << 1 | get_bit(33, card_data); | ||||||
|  |     cn = cn << 1 | get_bit(37, card_data); | ||||||
|  |     cn = cn << 1 | get_bit(54, card_data); | ||||||
|  |     cn = cn << 1 | get_bit(56, card_data); | ||||||
|  |     cn = cn << 1 | get_bit(59, card_data); | ||||||
|  |     cn = cn << 1 | get_bit(50, card_data); | ||||||
|  |     cn = cn << 1 | get_bit(41, card_data); | ||||||
|  | 
 | ||||||
|  |     return cn; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| void ProtocolIndala40134::decode( | void ProtocolIndala40134::decode( | ||||||
|     const uint8_t* encoded_data, |     const uint8_t* encoded_data, | ||||||
|     const uint8_t encoded_data_size, |     const uint8_t encoded_data_size, | ||||||
| @ -117,15 +162,76 @@ void ProtocolIndala40134::decode( | |||||||
|     const uint8_t decoded_data_size) { |     const uint8_t decoded_data_size) { | ||||||
|     furi_check(decoded_data_size >= get_decoded_data_size()); |     furi_check(decoded_data_size >= get_decoded_data_size()); | ||||||
|     furi_check(encoded_data_size >= get_encoded_data_size()); |     furi_check(encoded_data_size >= get_encoded_data_size()); | ||||||
|     // TODO implement decoding
 | 
 | ||||||
|     furi_check(0); |     const Indala40134CardData* card_data = | ||||||
|  |         reinterpret_cast<const Indala40134CardData*>(encoded_data); | ||||||
|  | 
 | ||||||
|  |     uint8_t fc = get_fc(card_data); | ||||||
|  |     uint16_t card = get_cn(card_data); | ||||||
|  | 
 | ||||||
|  |     decoded_data[0] = fc; | ||||||
|  |     decoded_data[1] = card >> 8; | ||||||
|  |     decoded_data[2] = card; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| bool ProtocolIndala40134::can_be_decoded( | bool ProtocolIndala40134::can_be_decoded( | ||||||
|     const uint8_t* encoded_data, |     const uint8_t* encoded_data, | ||||||
|     const uint8_t encoded_data_size) { |     const uint8_t encoded_data_size) { | ||||||
|     furi_check(encoded_data_size >= get_encoded_data_size()); |     furi_check(encoded_data_size >= get_encoded_data_size()); | ||||||
|     // TODO implement decoding
 |     bool can_be_decoded = false; | ||||||
|     furi_check(0); | 
 | ||||||
|     return false; |     const Indala40134CardData* card_data = | ||||||
|  |         reinterpret_cast<const Indala40134CardData*>(encoded_data); | ||||||
|  | 
 | ||||||
|  |     do { | ||||||
|  |         // preambula
 | ||||||
|  |         if((*card_data >> 32) != 0xa0000000UL) break; | ||||||
|  | 
 | ||||||
|  |         // data
 | ||||||
|  |         const uint32_t fc_and_card = get_fc(card_data) << 16 | get_cn(card_data); | ||||||
|  | 
 | ||||||
|  |         // checksum
 | ||||||
|  |         const uint8_t checksum = get_bit(62, card_data) << 1 | get_bit(63, card_data); | ||||||
|  |         uint8_t checksum_sum = 0; | ||||||
|  |         checksum_sum += ((fc_and_card >> 14) & 1); | ||||||
|  |         checksum_sum += ((fc_and_card >> 12) & 1); | ||||||
|  |         checksum_sum += ((fc_and_card >> 9) & 1); | ||||||
|  |         checksum_sum += ((fc_and_card >> 8) & 1); | ||||||
|  |         checksum_sum += ((fc_and_card >> 6) & 1); | ||||||
|  |         checksum_sum += ((fc_and_card >> 5) & 1); | ||||||
|  |         checksum_sum += ((fc_and_card >> 2) & 1); | ||||||
|  |         checksum_sum += ((fc_and_card >> 0) & 1); | ||||||
|  |         checksum_sum = checksum_sum & 0b1; | ||||||
|  | 
 | ||||||
|  |         if(checksum_sum == 1 && checksum == 0b01) { | ||||||
|  |         } else if(checksum_sum == 0 && checksum == 0b10) { | ||||||
|  |         } else { | ||||||
|  |             break; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         // wiegand parity bits
 | ||||||
|  |         // even parity sum calculation (high 12 bits of data)
 | ||||||
|  |         const bool even_parity = get_bit(34, card_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++; | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |         if(even_parity_sum % 2 != even_parity) break; | ||||||
|  | 
 | ||||||
|  |         // odd parity sum calculation (low 12 bits of data)
 | ||||||
|  |         const bool odd_parity = get_bit(38, card_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++; | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |         if(odd_parity_sum % 2 != odd_parity) break; | ||||||
|  | 
 | ||||||
|  |         can_be_decoded = true; | ||||||
|  |     } while(false); | ||||||
|  | 
 | ||||||
|  |     return can_be_decoded; | ||||||
| } | } | ||||||
| @ -17,19 +17,47 @@ struct RfidReaderAccessor { | |||||||
| 
 | 
 | ||||||
| void RfidReader::decode(bool polarity) { | void RfidReader::decode(bool polarity) { | ||||||
|     uint32_t current_dwt_value = DWT->CYCCNT; |     uint32_t current_dwt_value = DWT->CYCCNT; | ||||||
|  |     uint32_t period = current_dwt_value - last_dwt_value; | ||||||
|  |     last_dwt_value = current_dwt_value; | ||||||
| 
 | 
 | ||||||
|  |     //decoder_gpio_out.process_front(polarity, period);
 | ||||||
|     switch(type) { |     switch(type) { | ||||||
|     case Type::Normal: |     case Type::Normal: | ||||||
|         decoder_em.process_front(polarity, current_dwt_value - last_dwt_value); |         decoder_em.process_front(polarity, period); | ||||||
|         decoder_hid26.process_front(polarity, current_dwt_value - last_dwt_value); |         decoder_hid26.process_front(polarity, period); | ||||||
|         //decoder_indala.process_front(polarity, current_dwt_value - last_dwt_value);
 |  | ||||||
|         //decoder_analyzer.process_front(polarity, current_dwt_value - last_dwt_value);
 |  | ||||||
| 
 |  | ||||||
|         last_dwt_value = current_dwt_value; |  | ||||||
|         break; |         break; | ||||||
|     case Type::Indala: |     case Type::Indala: | ||||||
|  |         decoder_em.process_front(polarity, period); | ||||||
|  |         decoder_hid26.process_front(polarity, period); | ||||||
|  |         decoder_indala.process_front(polarity, period); | ||||||
|         break; |         break; | ||||||
|     } |     } | ||||||
|  | 
 | ||||||
|  |     detect_ticks++; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | bool RfidReader::switch_timer_elapsed() { | ||||||
|  |     const uint32_t seconds_to_switch = osKernelGetTickFreq() * 2.0f; | ||||||
|  |     return (osKernelGetTickCount() - switch_os_tick_last) > seconds_to_switch; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void RfidReader::switch_timer_reset() { | ||||||
|  |     switch_os_tick_last = osKernelGetTickCount(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void RfidReader::switch_mode() { | ||||||
|  |     switch(type) { | ||||||
|  |     case Type::Normal: | ||||||
|  |         type = Type::Indala; | ||||||
|  |         api_hal_rfid_change_read_config(62500.0f, 0.25f); | ||||||
|  |         break; | ||||||
|  |     case Type::Indala: | ||||||
|  |         type = Type::Normal; | ||||||
|  |         api_hal_rfid_change_read_config(125000.0f, 0.5f); | ||||||
|  |         break; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     switch_timer_reset(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static void comparator_trigger_callback(void* hcomp, void* comp_ctx) { | static void comparator_trigger_callback(void* hcomp, void* comp_ctx) { | ||||||
| @ -45,47 +73,103 @@ static void comparator_trigger_callback(void* hcomp, void* comp_ctx) { | |||||||
| RfidReader::RfidReader() { | RfidReader::RfidReader() { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void RfidReader::start(Type _type) { | void RfidReader::start() { | ||||||
|     type = _type; |     type = Type::Normal; | ||||||
| 
 | 
 | ||||||
|     start_gpio(); |     api_hal_rfid_pins_read(); | ||||||
|  |     api_hal_rfid_tim_read(125000, 0.5); | ||||||
|  |     api_hal_rfid_tim_read_start(); | ||||||
|  |     start_comparator(); | ||||||
|  | 
 | ||||||
|  |     switch_timer_reset(); | ||||||
|  |     last_readed_count = 0; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void RfidReader::start_forced(RfidReader::Type _type) { | ||||||
|  |     type = _type; | ||||||
|     switch(type) { |     switch(type) { | ||||||
|     case Type::Normal: |     case Type::Normal: | ||||||
|         start_timer(); |         start(); | ||||||
|         break; |         break; | ||||||
|     case Type::Indala: |     case Type::Indala: | ||||||
|         start_timer_indala(); |         api_hal_rfid_pins_read(); | ||||||
|  |         api_hal_rfid_tim_read(62500.0f, 0.25f); | ||||||
|  |         api_hal_rfid_tim_read_start(); | ||||||
|  |         start_comparator(); | ||||||
|  | 
 | ||||||
|  |         switch_timer_reset(); | ||||||
|  |         last_readed_count = 0; | ||||||
|         break; |         break; | ||||||
|     } |     } | ||||||
| 
 |  | ||||||
|     start_comparator(); |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void RfidReader::stop() { | void RfidReader::stop() { | ||||||
|     stop_gpio(); |     api_hal_rfid_pins_reset(); | ||||||
|     stop_timer(); |     api_hal_rfid_tim_read_stop(); | ||||||
|  |     api_hal_rfid_tim_reset(); | ||||||
|     stop_comparator(); |     stop_comparator(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| bool RfidReader::read(LfrfidKeyType* type, uint8_t* data, uint8_t data_size) { | bool RfidReader::read(LfrfidKeyType* _type, uint8_t* data, uint8_t data_size) { | ||||||
|     bool result = false; |     bool result = false; | ||||||
|  |     bool something_readed = false; | ||||||
| 
 | 
 | ||||||
|  |     // reading
 | ||||||
|     if(decoder_em.read(data, data_size)) { |     if(decoder_em.read(data, data_size)) { | ||||||
|         *type = LfrfidKeyType::KeyEM4100; |         *_type = LfrfidKeyType::KeyEM4100; | ||||||
|         result = true; |         something_readed = true; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     if(decoder_hid26.read(data, data_size)) { |     if(decoder_hid26.read(data, data_size)) { | ||||||
|         *type = LfrfidKeyType::KeyH10301; |         *_type = LfrfidKeyType::KeyH10301; | ||||||
|         result = true; |         something_readed = true; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     //decoder_indala.read(NULL, 0);
 |     if(decoder_indala.read(data, data_size)) { | ||||||
|     //decoder_analyzer.read(NULL, 0);
 |         *_type = LfrfidKeyType::KeyI40134; | ||||||
|  |         something_readed = true; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     // validation
 | ||||||
|  |     if(something_readed) { | ||||||
|  |         switch_timer_reset(); | ||||||
|  | 
 | ||||||
|  |         if(last_readed_type == *_type && memcmp(last_readed_data, data, data_size) == 0) { | ||||||
|  |             last_readed_count = last_readed_count + 1; | ||||||
|  | 
 | ||||||
|  |             if(last_readed_count > 2) { | ||||||
|  |                 result = true; | ||||||
|  |             } | ||||||
|  |         } else { | ||||||
|  |             last_readed_type = *_type; | ||||||
|  |             memcpy(last_readed_data, data, data_size); | ||||||
|  |             last_readed_count = 0; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     // mode switching
 | ||||||
|  |     if(switch_timer_elapsed()) { | ||||||
|  |         switch_mode(); | ||||||
|  |         last_readed_count = 0; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     return result; |     return result; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | bool RfidReader::detect() { | ||||||
|  |     bool detected = false; | ||||||
|  |     if(detect_ticks > 10) { | ||||||
|  |         detected = true; | ||||||
|  |     } | ||||||
|  |     detect_ticks = 0; | ||||||
|  | 
 | ||||||
|  |     return detected; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | bool RfidReader::any_read() { | ||||||
|  |     return last_readed_count > 0; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| void RfidReader::start_comparator(void) { | void RfidReader::start_comparator(void) { | ||||||
|     api_interrupt_add(comparator_trigger_callback, InterruptTypeComparatorTrigger, this); |     api_interrupt_add(comparator_trigger_callback, InterruptTypeComparatorTrigger, this); | ||||||
|     last_dwt_value = DWT->CYCCNT; |     last_dwt_value = DWT->CYCCNT; | ||||||
| @ -93,7 +177,7 @@ void RfidReader::start_comparator(void) { | |||||||
|     hcomp1.Init.InputMinus = COMP_INPUT_MINUS_1_2VREFINT; |     hcomp1.Init.InputMinus = COMP_INPUT_MINUS_1_2VREFINT; | ||||||
|     hcomp1.Init.InputPlus = COMP_INPUT_PLUS_IO1; |     hcomp1.Init.InputPlus = COMP_INPUT_PLUS_IO1; | ||||||
|     hcomp1.Init.OutputPol = COMP_OUTPUTPOL_NONINVERTED; |     hcomp1.Init.OutputPol = COMP_OUTPUTPOL_NONINVERTED; | ||||||
|     hcomp1.Init.Hysteresis = COMP_HYSTERESIS_LOW; |     hcomp1.Init.Hysteresis = COMP_HYSTERESIS_HIGH; | ||||||
|     hcomp1.Init.BlankingSrce = COMP_BLANKINGSRC_NONE; |     hcomp1.Init.BlankingSrce = COMP_BLANKINGSRC_NONE; | ||||||
|     hcomp1.Init.Mode = COMP_POWERMODE_MEDIUMSPEED; |     hcomp1.Init.Mode = COMP_POWERMODE_MEDIUMSPEED; | ||||||
|     hcomp1.Init.WindowMode = COMP_WINDOWMODE_DISABLE; |     hcomp1.Init.WindowMode = COMP_WINDOWMODE_DISABLE; | ||||||
| @ -105,30 +189,7 @@ void RfidReader::start_comparator(void) { | |||||||
|     HAL_COMP_Start(&hcomp1); |     HAL_COMP_Start(&hcomp1); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void RfidReader::start_timer(void) { |  | ||||||
|     api_hal_rfid_tim_read(125000, 0.5); |  | ||||||
|     api_hal_rfid_tim_read_start(); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void RfidReader::start_timer_indala(void) { |  | ||||||
|     api_hal_rfid_tim_read(62500, 0.25); |  | ||||||
|     api_hal_rfid_tim_read_start(); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void RfidReader::start_gpio(void) { |  | ||||||
|     api_hal_rfid_pins_read(); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void RfidReader::stop_comparator(void) { | void RfidReader::stop_comparator(void) { | ||||||
|     HAL_COMP_Stop(&hcomp1); |     HAL_COMP_Stop(&hcomp1); | ||||||
|     api_interrupt_remove(comparator_trigger_callback, InterruptTypeComparatorTrigger); |     api_interrupt_remove(comparator_trigger_callback, InterruptTypeComparatorTrigger); | ||||||
| } | } | ||||||
| 
 |  | ||||||
| void RfidReader::stop_timer(void) { |  | ||||||
|     api_hal_rfid_tim_read_stop(); |  | ||||||
|     api_hal_rfid_tim_reset(); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void RfidReader::stop_gpio(void) { |  | ||||||
|     api_hal_rfid_pins_reset(); |  | ||||||
| } |  | ||||||
| @ -1,5 +1,6 @@ | |||||||
| #pragma once | #pragma once | ||||||
| #include "decoder-analyzer.h" | //#include "decoder-analyzer.h"
 | ||||||
|  | #include "decoder-gpio-out.h" | ||||||
| #include "decoder-emmarine.h" | #include "decoder-emmarine.h" | ||||||
| #include "decoder-hid26.h" | #include "decoder-hid26.h" | ||||||
| #include "decoder-indala.h" | #include "decoder-indala.h" | ||||||
| @ -13,14 +14,19 @@ public: | |||||||
|     }; |     }; | ||||||
| 
 | 
 | ||||||
|     RfidReader(); |     RfidReader(); | ||||||
|     void start(Type type); |     void start(); | ||||||
|  |     void start_forced(RfidReader::Type type); | ||||||
|     void stop(); |     void stop(); | ||||||
|     bool read(LfrfidKeyType* type, uint8_t* data, uint8_t data_size); |     bool read(LfrfidKeyType* type, uint8_t* data, uint8_t data_size); | ||||||
| 
 | 
 | ||||||
|  |     bool detect(); | ||||||
|  |     bool any_read(); | ||||||
|  | 
 | ||||||
| private: | private: | ||||||
|     friend struct RfidReaderAccessor; |     friend struct RfidReaderAccessor; | ||||||
| 
 | 
 | ||||||
|     //DecoderAnalyzer decoder_analyzer;
 |     //DecoderAnalyzer decoder_analyzer;
 | ||||||
|  |     //DecoderGpioOut decoder_gpio_out;
 | ||||||
|     DecoderEMMarine decoder_em; |     DecoderEMMarine decoder_em; | ||||||
|     DecoderHID26 decoder_hid26; |     DecoderHID26 decoder_hid26; | ||||||
|     DecoderIndala decoder_indala; |     DecoderIndala decoder_indala; | ||||||
| @ -28,14 +34,20 @@ private: | |||||||
|     uint32_t last_dwt_value; |     uint32_t last_dwt_value; | ||||||
| 
 | 
 | ||||||
|     void start_comparator(void); |     void start_comparator(void); | ||||||
|     void start_timer(void); |  | ||||||
|     void start_timer_indala(void); |  | ||||||
|     void start_gpio(void); |  | ||||||
|     void stop_comparator(void); |     void stop_comparator(void); | ||||||
|     void stop_timer(void); |  | ||||||
|     void stop_gpio(void); |  | ||||||
| 
 | 
 | ||||||
|     void decode(bool polarity); |     void decode(bool polarity); | ||||||
| 
 | 
 | ||||||
|  |     uint32_t detect_ticks; | ||||||
|  | 
 | ||||||
|  |     uint32_t switch_os_tick_last; | ||||||
|  |     bool switch_timer_elapsed(); | ||||||
|  |     void switch_timer_reset(); | ||||||
|  |     void switch_mode(); | ||||||
|  | 
 | ||||||
|  |     LfrfidKeyType last_readed_type; | ||||||
|  |     uint8_t last_readed_data[LFRFID_KEY_SIZE]; | ||||||
|  |     uint8_t last_readed_count; | ||||||
|  | 
 | ||||||
|     Type type = Type::Normal; |     Type type = Type::Normal; | ||||||
| }; | }; | ||||||
|  | |||||||
| @ -7,7 +7,7 @@ RfidWorker::~RfidWorker() { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void RfidWorker::start_read() { | void RfidWorker::start_read() { | ||||||
|     reader.start(RfidReader::Type::Normal); |     reader.start(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| bool RfidWorker::read() { | bool RfidWorker::read() { | ||||||
| @ -25,6 +25,14 @@ bool RfidWorker::read() { | |||||||
|     return result; |     return result; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | bool RfidWorker::detect() { | ||||||
|  |     return reader.detect(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | bool RfidWorker::any_read() { | ||||||
|  |     return reader.any_read(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
| void RfidWorker::stop_read() { | void RfidWorker::stop_read() { | ||||||
|     reader.stop(); |     reader.stop(); | ||||||
| } | } | ||||||
| @ -36,7 +44,7 @@ void RfidWorker::start_write() { | |||||||
| 
 | 
 | ||||||
|     write_sequence->do_every_tick(1, std::bind(&RfidWorker::sq_write, this)); |     write_sequence->do_every_tick(1, std::bind(&RfidWorker::sq_write, this)); | ||||||
|     write_sequence->do_after_tick(2, std::bind(&RfidWorker::sq_write_start_validate, this)); |     write_sequence->do_after_tick(2, std::bind(&RfidWorker::sq_write_start_validate, this)); | ||||||
|     write_sequence->do_after_tick(15, std::bind(&RfidWorker::sq_write_validate, this)); |     write_sequence->do_every_tick(30, std::bind(&RfidWorker::sq_write_validate, this)); | ||||||
|     write_sequence->do_every_tick(1, std::bind(&RfidWorker::sq_write_stop_validate, this)); |     write_sequence->do_every_tick(1, std::bind(&RfidWorker::sq_write_stop_validate, this)); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| @ -59,26 +67,37 @@ void RfidWorker::stop_emulate() { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void RfidWorker::sq_write() { | void RfidWorker::sq_write() { | ||||||
|     // TODO expand this
 |     for(size_t i = 0; i < 5; i++) { | ||||||
|     switch(key.get_type()) { |         switch(key.get_type()) { | ||||||
|     case LfrfidKeyType::KeyEM4100: |         case LfrfidKeyType::KeyEM4100: | ||||||
|         writer.start(); |             writer.start(); | ||||||
|         writer.write_em(key.get_data()); |             writer.write_em(key.get_data()); | ||||||
|         writer.stop(); |             writer.stop(); | ||||||
|         break; |             break; | ||||||
|     case LfrfidKeyType::KeyH10301: |         case LfrfidKeyType::KeyH10301: | ||||||
|         writer.start(); |             writer.start(); | ||||||
|         writer.write_hid(key.get_data()); |             writer.write_hid(key.get_data()); | ||||||
|         writer.stop(); |             writer.stop(); | ||||||
|         break; |             break; | ||||||
| 
 |         case LfrfidKeyType::KeyI40134: | ||||||
|     default: |             writer.start(); | ||||||
|         break; |             writer.write_indala(key.get_data()); | ||||||
|  |             writer.stop(); | ||||||
|  |             break; | ||||||
|  |         } | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void RfidWorker::sq_write_start_validate() { | void RfidWorker::sq_write_start_validate() { | ||||||
|     reader.start(RfidReader::Type::Normal); |     switch(key.get_type()) { | ||||||
|  |     case LfrfidKeyType::KeyEM4100: | ||||||
|  |     case LfrfidKeyType::KeyH10301: | ||||||
|  |         reader.start_forced(RfidReader::Type::Normal); | ||||||
|  |         break; | ||||||
|  |     case LfrfidKeyType::KeyI40134: | ||||||
|  |         reader.start_forced(RfidReader::Type::Indala); | ||||||
|  |         break; | ||||||
|  |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void RfidWorker::sq_write_validate() { | void RfidWorker::sq_write_validate() { | ||||||
| @ -88,7 +107,11 @@ void RfidWorker::sq_write_validate() { | |||||||
| 
 | 
 | ||||||
|     bool result = reader.read(&type, data, data_size); |     bool result = reader.read(&type, data, data_size); | ||||||
| 
 | 
 | ||||||
|     if(result) { |     if(result && (write_result != WriteResult::Ok)) { | ||||||
|  |         if(validate_counts > (5 * 60)) { | ||||||
|  |             write_result = WriteResult::NotWritable; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|         if(type == key.get_type()) { |         if(type == key.get_type()) { | ||||||
|             if(memcmp(data, key.get_data(), key.get_type_data_count()) == 0) { |             if(memcmp(data, key.get_data(), key.get_type_data_count()) == 0) { | ||||||
|                 write_result = WriteResult::Ok; |                 write_result = WriteResult::Ok; | ||||||
| @ -99,10 +122,6 @@ void RfidWorker::sq_write_validate() { | |||||||
|         } else { |         } else { | ||||||
|             validate_counts++; |             validate_counts++; | ||||||
|         } |         } | ||||||
| 
 |  | ||||||
|         if(validate_counts > 5) { |  | ||||||
|             write_result = WriteResult::NotWritable; |  | ||||||
|         } |  | ||||||
|     }; |     }; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -13,6 +13,8 @@ public: | |||||||
| 
 | 
 | ||||||
|     void start_read(); |     void start_read(); | ||||||
|     bool read(); |     bool read(); | ||||||
|  |     bool detect(); | ||||||
|  |     bool any_read(); | ||||||
|     void stop_read(); |     void stop_read(); | ||||||
| 
 | 
 | ||||||
|     enum class WriteResult : uint8_t { |     enum class WriteResult : uint8_t { | ||||||
|  | |||||||
| @ -2,6 +2,7 @@ | |||||||
| #include <api-hal.h> | #include <api-hal.h> | ||||||
| #include "protocols/protocol-emmarin.h" | #include "protocols/protocol-emmarin.h" | ||||||
| #include "protocols/protocol-hid-h10301.h" | #include "protocols/protocol-hid-h10301.h" | ||||||
|  | #include "protocols/protocol-indala-40134.h" | ||||||
| 
 | 
 | ||||||
| extern COMP_HandleTypeDef hcomp1; | extern COMP_HandleTypeDef hcomp1; | ||||||
| 
 | 
 | ||||||
| @ -115,7 +116,7 @@ void RfidWriter::write_em(const uint8_t em_data[5]) { | |||||||
|     ProtocolEMMarin em_card; |     ProtocolEMMarin em_card; | ||||||
|     uint64_t em_encoded_data; |     uint64_t em_encoded_data; | ||||||
|     em_card.encode(em_data, 5, reinterpret_cast<uint8_t*>(&em_encoded_data), sizeof(uint64_t)); |     em_card.encode(em_data, 5, reinterpret_cast<uint8_t*>(&em_encoded_data), sizeof(uint64_t)); | ||||||
|     const uint32_t em_config_block_data = 0b01100000000101001000000001000000; |     const uint32_t em_config_block_data = 0b00000000000101001000000001000000; | ||||||
| 
 | 
 | ||||||
|     __disable_irq(); |     __disable_irq(); | ||||||
|     write_block(0, 0, false, em_config_block_data); |     write_block(0, 0, false, em_config_block_data); | ||||||
| @ -140,3 +141,19 @@ void RfidWriter::write_hid(const uint8_t hid_data[3]) { | |||||||
|     write_reset(); |     write_reset(); | ||||||
|     __enable_irq(); |     __enable_irq(); | ||||||
| } | } | ||||||
|  | 
 | ||||||
|  | void RfidWriter::write_indala(const uint8_t indala_data[3]) { | ||||||
|  |     ProtocolIndala40134 indala_card; | ||||||
|  |     uint32_t card_data[2]; | ||||||
|  |     indala_card.encode( | ||||||
|  |         indala_data, 3, reinterpret_cast<uint8_t*>(&card_data), sizeof(card_data) * 2); | ||||||
|  | 
 | ||||||
|  |     const uint32_t indala_config_block_data = 0b00000000000010000001000001000000; | ||||||
|  | 
 | ||||||
|  |     __disable_irq(); | ||||||
|  |     write_block(0, 0, false, indala_config_block_data); | ||||||
|  |     write_block(0, 1, false, card_data[0]); | ||||||
|  |     write_block(0, 2, false, card_data[1]); | ||||||
|  |     write_reset(); | ||||||
|  |     __enable_irq(); | ||||||
|  | } | ||||||
|  | |||||||
| @ -9,6 +9,7 @@ public: | |||||||
|     void stop(); |     void stop(); | ||||||
|     void write_em(const uint8_t em_data[5]); |     void write_em(const uint8_t em_data[5]); | ||||||
|     void write_hid(const uint8_t hid_data[3]); |     void write_hid(const uint8_t hid_data[3]); | ||||||
|  |     void write_indala(const uint8_t indala_data[3]); | ||||||
| 
 | 
 | ||||||
| private: | private: | ||||||
|     void write_gap(uint32_t gap_time); |     void write_gap(uint32_t gap_time); | ||||||
|  | |||||||
| @ -46,7 +46,7 @@ bool lfrfid_cli_get_key_type(string_t data, LfrfidKeyType* type) { | |||||||
| 
 | 
 | ||||||
| void lfrfid_cli_read(Cli* cli) { | void lfrfid_cli_read(Cli* cli) { | ||||||
|     RfidReader reader; |     RfidReader reader; | ||||||
|     reader.start(RfidReader::Type::Normal); |     reader.start(); | ||||||
| 
 | 
 | ||||||
|     static const uint8_t data_size = LFRFID_KEY_SIZE; |     static const uint8_t data_size = LFRFID_KEY_SIZE; | ||||||
|     uint8_t data[data_size] = {0}; |     uint8_t data[data_size] = {0}; | ||||||
|  | |||||||
| @ -55,6 +55,7 @@ void LfRfidAppSceneReadSuccess::on_enter(LfRfidApp* app, bool need_restore) { | |||||||
|             string_get_cstr(string[2]), 68, 47, AlignLeft, AlignBottom, FontSecondary); |             string_get_cstr(string[2]), 68, 47, AlignLeft, AlignBottom, FontSecondary); | ||||||
|         break; |         break; | ||||||
|     case LfrfidKeyType::KeyH10301: |     case LfrfidKeyType::KeyH10301: | ||||||
|  |     case LfrfidKeyType::KeyI40134: | ||||||
|         line_1_text->set_text("HEX:", 65, 23, AlignRight, AlignBottom, FontSecondary); |         line_1_text->set_text("HEX:", 65, 23, AlignRight, AlignBottom, FontSecondary); | ||||||
|         line_2_text->set_text("FC:", 65, 35, AlignRight, AlignBottom, FontSecondary); |         line_2_text->set_text("FC:", 65, 35, AlignRight, AlignBottom, FontSecondary); | ||||||
|         line_3_text->set_text("Card:", 65, 47, AlignRight, AlignBottom, FontSecondary); |         line_3_text->set_text("Card:", 65, 47, AlignRight, AlignBottom, FontSecondary); | ||||||
| @ -73,9 +74,6 @@ void LfRfidAppSceneReadSuccess::on_enter(LfRfidApp* app, bool need_restore) { | |||||||
|         line_3_value->set_text( |         line_3_value->set_text( | ||||||
|             string_get_cstr(string[2]), 68, 47, AlignLeft, AlignBottom, FontSecondary); |             string_get_cstr(string[2]), 68, 47, AlignLeft, AlignBottom, FontSecondary); | ||||||
|         break; |         break; | ||||||
|     case LfrfidKeyType::KeyI40134: |  | ||||||
|         //TODO implement when we can read Indala
 |  | ||||||
|         break; |  | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     app->view_controller.switch_to<ContainerVM>(); |     app->view_controller.switch_to<ContainerVM>(); | ||||||
|  | |||||||
| @ -18,7 +18,13 @@ bool LfRfidAppSceneRead::on_event(LfRfidApp* app, LfRfidApp::Event* event) { | |||||||
|             notification_message(app->notification, &sequence_success); |             notification_message(app->notification, &sequence_success); | ||||||
|             app->scene_controller.switch_to_next_scene(LfRfidApp::SceneType::ReadSuccess); |             app->scene_controller.switch_to_next_scene(LfRfidApp::SceneType::ReadSuccess); | ||||||
|         } else { |         } else { | ||||||
|             notification_message(app->notification, &sequence_blink_red_10); |             if(app->worker.any_read()) { | ||||||
|  |                 notification_message(app->notification, &sequence_blink_green_10); | ||||||
|  |             } else if(app->worker.detect()) { | ||||||
|  |                 notification_message(app->notification, &sequence_blink_blue_10); | ||||||
|  |             } else { | ||||||
|  |                 notification_message(app->notification, &sequence_blink_red_10); | ||||||
|  |             } | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -105,6 +105,13 @@ void api_hal_rfid_set_read_period(uint32_t period); | |||||||
|  */ |  */ | ||||||
| void api_hal_rfid_set_read_pulse(uint32_t pulse); | void api_hal_rfid_set_read_pulse(uint32_t pulse); | ||||||
| 
 | 
 | ||||||
|  | /**
 | ||||||
|  |  * Сhanges the configuration of the RFID timer "on a fly" | ||||||
|  |  * @param freq new frequency | ||||||
|  |  * @param duty_cycle new duty cycle | ||||||
|  |  */ | ||||||
|  | void api_hal_rfid_change_read_config(float freq, float duty_cycle); | ||||||
|  | 
 | ||||||
| #ifdef __cplusplus | #ifdef __cplusplus | ||||||
| } | } | ||||||
| #endif | #endif | ||||||
| @ -270,3 +270,9 @@ void api_hal_rfid_set_read_pulse(uint32_t pulse) { | |||||||
|         break; |         break; | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  | 
 | ||||||
|  | void api_hal_rfid_change_read_config(float freq, float duty_cycle) { | ||||||
|  |     uint32_t period = (uint32_t)((SystemCoreClock) / freq) - 1; | ||||||
|  |     api_hal_rfid_set_read_period(period); | ||||||
|  |     api_hal_rfid_set_read_pulse(period * duty_cycle); | ||||||
|  | } | ||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 SG
						SG