mag_helpers.c 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241
  1. #include "mag_helpers.h"
  2. #define GPIO_PIN_A &gpio_ext_pa6
  3. #define GPIO_PIN_B &gpio_ext_pa7
  4. #define RFID_PIN &gpio_rfid_carrier_out
  5. #define ZERO_PREFIX 25 // n zeros prefix
  6. #define ZERO_BETWEEN 53 // n zeros between tracks
  7. #define ZERO_SUFFIX 25 // n zeros suffix
  8. #define US_CLOCK 240
  9. #define US_INTERPACKET 10
  10. // bits per char on a given track
  11. const uint8_t bitlen[] = {7, 5, 5};
  12. // char offset by track
  13. const int sublen[] = {32, 48, 48};
  14. uint8_t bit_dir = 0;
  15. void play_bit_rfid(uint8_t send_bit) {
  16. // internal TX over RFID coil
  17. bit_dir ^= 1;
  18. furi_hal_gpio_write(RFID_PIN, bit_dir);
  19. furi_delay_us(US_CLOCK);
  20. if(send_bit) {
  21. bit_dir ^= 1;
  22. furi_hal_gpio_write(RFID_PIN, bit_dir);
  23. }
  24. furi_delay_us(US_CLOCK);
  25. furi_delay_us(US_INTERPACKET);
  26. }
  27. /*static void play_bit_gpio(uint8_t send_bit) {
  28. // external TX over motor driver wired to PIN_A and PIN_B
  29. bit_dir ^= 1;
  30. furi_hal_gpio_write(GPIO_PIN_A, bit_dir);
  31. furi_hal_gpio_write(GPIO_PIN_B, !bit_dir);
  32. furi_delay_us(US_CLOCK);
  33. if(send_bit) {
  34. bit_dir ^= 1;
  35. furi_hal_gpio_write(GPIO_PIN_A, bit_dir);
  36. furi_hal_gpio_write(GPIO_PIN_B, !bit_dir);
  37. }
  38. furi_delay_us(US_CLOCK);
  39. furi_delay_us(US_INTERPACKET);
  40. }*/
  41. void rfid_tx_init() {
  42. // initialize RFID system for TX
  43. furi_hal_power_enable_otg();
  44. furi_hal_ibutton_start_drive();
  45. furi_hal_ibutton_pin_low();
  46. // Initializing at GpioSpeedLow seems sufficient for our needs; no improvements seen by increasing speed setting
  47. // this doesn't seem to make a difference, leaving it in
  48. furi_hal_gpio_init(&gpio_rfid_data_in, GpioModeOutputPushPull, GpioPullNo, GpioSpeedLow);
  49. furi_hal_gpio_write(&gpio_rfid_data_in, false);
  50. // false->ground RFID antenna; true->don't ground
  51. // skotopes (RFID dev) say normally you'd want RFID_PULL in high for signal forming, while modulating RFID_OUT
  52. // dunaevai135 had it low in their old code. Leaving low, as it doesn't seem to make a difference on my janky antenna
  53. furi_hal_gpio_init(&gpio_nfc_irq_rfid_pull, GpioModeOutputPushPull, GpioPullNo, GpioSpeedLow);
  54. furi_hal_gpio_write(&gpio_nfc_irq_rfid_pull, false);
  55. furi_hal_gpio_init(RFID_PIN, GpioModeOutputPushPull, GpioPullNo, GpioSpeedLow);
  56. // confirm this delay is needed / sufficient? legacy from hackathon...
  57. furi_delay_ms(300);
  58. }
  59. void rfid_tx_reset() {
  60. // reset RFID system
  61. furi_hal_gpio_write(RFID_PIN, 0);
  62. furi_hal_rfid_pins_reset();
  63. furi_hal_power_disable_otg();
  64. }
  65. /*
  66. static void gpio_tx_init() {
  67. furi_hal_power_enable_otg();
  68. gpio_item_configure_all_pins(GpioModeOutputPushPull);
  69. }
  70. static void gpio_tx_reset() {
  71. gpio_item_set_pin(PIN_A, 0);
  72. gpio_item_set_pin(PIN_B, 0);
  73. gpio_item_set_pin(ENABLE_PIN, 0);
  74. gpio_item_configure_all_pins(GpioModeAnalog);
  75. furi_hal_power_disable_otg();
  76. }
  77. */
  78. void track_to_bits(uint8_t* bit_array, const char* track_data, uint8_t track_index) {
  79. // convert individual track to bits
  80. int tmp, crc, lrc = 0;
  81. int i = 0;
  82. // convert track data to bits
  83. for(uint8_t j = 0; track_data[i] != '\0'; j++) {
  84. crc = 1;
  85. tmp = track_data[j] - sublen[track_index];
  86. for(uint8_t k = 0; k < bitlen[track_index] - 1; k++) {
  87. crc ^= tmp & 1;
  88. lrc ^= (tmp & 1) << k;
  89. bit_array[i] = tmp & 1;
  90. i++;
  91. tmp >>= 1;
  92. }
  93. bit_array[i] = crc;
  94. i++;
  95. }
  96. // finish calculating final "byte" (LRC)
  97. tmp = lrc;
  98. crc = 1;
  99. for(uint8_t j = 0; j < bitlen[track_index] - 1; j++) {
  100. crc ^= tmp & 1;
  101. bit_array[i] = tmp & 1;
  102. i++;
  103. tmp >>= 1;
  104. }
  105. bit_array[i] = crc;
  106. i++;
  107. // My makeshift end sentinel. All other values 0/1
  108. bit_array[i] = 2;
  109. i++;
  110. //bool is_correct_length = (i == (strlen(track_data) * bitlen[track_index]));
  111. //furi_assert(is_correct_length);
  112. }
  113. void mag_spoof_single_track_rfid(FuriString* track_str, uint8_t track_index) {
  114. // Quick testing...
  115. rfid_tx_init();
  116. size_t from;
  117. size_t to;
  118. // TODO ';' in first track case
  119. if(track_index == 0) {
  120. from = furi_string_search_char(track_str, '%');
  121. to = furi_string_search_char(track_str, '?', from);
  122. } else if(track_index == 1) {
  123. from = furi_string_search_char(track_str, ';');
  124. to = furi_string_search_char(track_str, '?', from);
  125. } else {
  126. from = 0;
  127. to = furi_string_size(track_str);
  128. }
  129. if(from >= to) {
  130. return;
  131. }
  132. furi_string_mid(track_str, from, to - from + 1);
  133. const char* data = furi_string_get_cstr(track_str);
  134. uint8_t bit_array[(strlen(data) * bitlen[track_index]) + 1];
  135. track_to_bits(bit_array, data, track_index);
  136. FURI_CRITICAL_ENTER();
  137. for(uint8_t i = 0; i < ZERO_PREFIX; i++) play_bit_rfid(0);
  138. for(uint8_t i = 0; bit_array[i] != 2; i++) play_bit_rfid(bit_array[i] & 1);
  139. for(uint8_t i = 0; i < ZERO_SUFFIX; i++) play_bit_rfid(0);
  140. FURI_CRITICAL_EXIT();
  141. rfid_tx_reset();
  142. }
  143. void mag_spoof_two_track_rfid(FuriString* track1, FuriString* track2) {
  144. // Quick testing...
  145. rfid_tx_init();
  146. const char* data1 = furi_string_get_cstr(track1);
  147. uint8_t bit_array1[(strlen(data1) * bitlen[0]) + 1];
  148. const char* data2 = furi_string_get_cstr(track2);
  149. uint8_t bit_array2[(strlen(data2) * bitlen[1]) + 1];
  150. track_to_bits(bit_array1, data1, 0);
  151. track_to_bits(bit_array2, data2, 1);
  152. FURI_CRITICAL_ENTER();
  153. for(uint8_t i = 0; i < ZERO_PREFIX; i++) play_bit_rfid(0);
  154. for(uint8_t i = 0; bit_array1[i] != 2; i++) play_bit_rfid(bit_array1[i] & 1);
  155. for(uint8_t i = 0; i < ZERO_BETWEEN; i++) play_bit_rfid(0);
  156. for(uint8_t i = 0; bit_array2[i] != 2; i++) play_bit_rfid(bit_array2[i] & 1);
  157. for(uint8_t i = 0; i < ZERO_SUFFIX; i++) play_bit_rfid(0);
  158. FURI_CRITICAL_EXIT();
  159. rfid_tx_reset();
  160. }
  161. //// @antirez's code from protoview for bitmapping. May want to refactor to use this...
  162. /* Set the 'bitpos' bit to value 'val', in the specified bitmap
  163. * 'b' of len 'blen'.
  164. * Out of range bits will silently be discarded. */
  165. void set_bit(uint8_t* b, uint32_t blen, uint32_t bitpos, bool val) {
  166. uint32_t byte = bitpos / 8;
  167. uint32_t bit = bitpos & 7;
  168. if(byte >= blen) return;
  169. if(val)
  170. b[byte] |= 1 << bit;
  171. else
  172. b[byte] &= ~(1 << bit);
  173. }
  174. /* Get the bit 'bitpos' of the bitmap 'b' of 'blen' bytes.
  175. * Out of range bits return false (not bit set). */
  176. bool get_bit(uint8_t* b, uint32_t blen, uint32_t bitpos) {
  177. uint32_t byte = bitpos / 8;
  178. uint32_t bit = bitpos & 7;
  179. if(byte >= blen) return 0;
  180. return (b[byte] & (1 << bit)) != 0;
  181. }
  182. /*uint32_t convert_signal_to_bits(uint8_t *b, uint32_t blen, RawSamplesBuffer *s, uint32_t idx, uint32_t count, uint32_t rate) {
  183. if (rate == 0) return 0; // We can't perform the conversion.
  184. uint32_t bitpos = 0;
  185. for (uint32_t j = 0; j < count; j++) {
  186. uint32_t dur;
  187. bool level;
  188. raw_samples_get(s, j+idx, &level, &dur);
  189. uint32_t numbits = dur / rate; // full bits that surely fit.
  190. uint32_t rest = dur % rate; // How much we are left with.
  191. if (rest > rate/2) numbits++; // There is another one.
  192. while(numbits--) set_bit(b,blen,bitpos++,s[j].level);
  193. }
  194. return bitpos;
  195. }*/