]> git.zerfleddert.de Git - proxmark3-svn/blame - armsrc/pcf7931.c
Fix #912
[proxmark3-svn] / armsrc / pcf7931.c
CommitLineData
d10e08ae 1#include "proxmark3.h"
2#include "apps.h"
867e10a5 3#include "usb_cdc.h"
d10e08ae 4#include "lfsampling.h"
5#include "pcf7931.h"
b8e461ff 6#include "util.h"
d10e08ae 7#include "string.h"
fc52fbd4 8#include "fpgaloader.h"
d10e08ae 9
10#define T0_PCF 8 //period for the pcf7931 in us
11#define ALLOC 16
12
818e15b0
S
13size_t DemodPCF7931(uint8_t **outBlocks) {
14 uint8_t bits[256] = {0x00};
d10e08ae 15 uint8_t blocks[8][16];
818e15b0 16 uint8_t *dest = BigBuf_get_addr();
caaa4293 17
d10e08ae 18 int GraphTraceLen = BigBuf_max_traceLen();
818e15b0 19 if (GraphTraceLen > 18000)
d10e08ae 20 GraphTraceLen = 18000;
caaa4293 21
d10e08ae 22 int i, j, lastval, bitidx, half_switch;
23 int clock = 64;
24 int tolerance = clock / 8;
25 int pmc, block_done;
26 int lc, warnings = 0;
818e15b0 27 size_t num_blocks = 0;
d10e08ae 28 int lmin=128, lmax=128;
29 uint8_t dir;
3cec7061 30 //clear read buffer
29b75739 31 BigBuf_Clear_keep_EM();
d10e08ae 32
33 LFSetupFPGAForADC(95, true);
34 DoAcquisition_default(0, true);
35
36 lmin = 64;
37 lmax = 192;
38
39 i = 2;
40
41 /* Find first local max/min */
818e15b0 42 if(dest[1] > dest[0]) {
d10e08ae 43 while(i < GraphTraceLen) {
818e15b0 44 if( !(dest[i] > dest[i-1]) && dest[i] > lmax)
d10e08ae 45 break;
46 i++;
47 }
48 dir = 0;
818e15b0 49 } else {
d10e08ae 50 while(i < GraphTraceLen) {
818e15b0 51 if( !(dest[i] < dest[i-1]) && dest[i] < lmin)
d10e08ae 52 break;
53 i++;
54 }
55 dir = 1;
56 }
57
58 lastval = i++;
59 half_switch = 0;
60 pmc = 0;
61 block_done = 0;
62
818e15b0
S
63 for (bitidx = 0; i < GraphTraceLen; i++) {
64 if ((dest[i-1] > dest[i] && dir == 1 && dest[i] > lmax) || (dest[i-1] < dest[i] && dir == 0 && dest[i] < lmin)) {
d10e08ae 65 lc = i - lastval;
66 lastval = i;
67
68 // Switch depending on lc length:
69 // Tolerance is 1/8 of clock rate (arbitrary)
cf194819 70 if (ABS(lc-clock/4) < tolerance) {
d10e08ae 71 // 16T0
72 if((i - pmc) == lc) { /* 16T0 was previous one */
73 /* It's a PMC ! */
74 i += (128+127+16+32+33+16)-1;
75 lastval = i;
76 pmc = 0;
77 block_done = 1;
818e15b0 78 } else {
d10e08ae 79 pmc = i;
80 }
cf194819 81 } else if (ABS(lc-clock/2) < tolerance) {
d10e08ae 82 // 32TO
83 if((i - pmc) == lc) { /* 16T0 was previous one */
84 /* It's a PMC ! */
85 i += (128+127+16+32+33)-1;
86 lastval = i;
87 pmc = 0;
88 block_done = 1;
818e15b0
S
89 } else if(half_switch == 1) {
90 bits[bitidx++] = 0;
d10e08ae 91 half_switch = 0;
92 }
93 else
94 half_switch++;
cf194819 95 } else if (ABS(lc-clock) < tolerance) {
d10e08ae 96 // 64TO
818e15b0 97 bits[bitidx++] = 1;
d10e08ae 98 } else {
99 // Error
818e15b0 100 if (++warnings > 10) {
d10e08ae 101 Dbprintf("Error: too many detection errors, aborting.");
102 return 0;
103 }
104 }
105
106 if(block_done == 1) {
107 if(bitidx == 128) {
818e15b0
S
108 for(j = 0; j < 16; ++j) {
109 blocks[num_blocks][j] =
110 128 * bits[j*8 + 7]+
caaa4293 111 64 * bits[j*8 + 6] +
818e15b0
S
112 32 * bits[j*8 + 5] +
113 16 * bits[j*8 + 4] +
114 8 * bits[j*8 + 3] +
115 4 * bits[j*8 + 2] +
116 2 * bits[j*8 + 1] +
117 bits[j*8]
118 ;
d10e08ae 119 }
120 num_blocks++;
121 }
122 bitidx = 0;
123 block_done = 0;
124 half_switch = 0;
125 }
126 if(i < GraphTraceLen)
818e15b0 127 dir = (dest[i-1] > dest[i]) ? 0 : 1;
d10e08ae 128 }
129 if(bitidx==255)
130 bitidx=0;
131 warnings = 0;
132 if(num_blocks == 4) break;
133 }
818e15b0 134 memcpy(outBlocks, blocks, 16 * num_blocks);
d10e08ae 135 return num_blocks;
136}
137
818e15b0
S
138bool IsBlock0PCF7931(uint8_t *block) {
139 // assuming all RFU bits are set to 0
140 // if PAC is enabled password is set to 0
141 if (block[7] == 0x01)
142 {
143 if (!memcmp(block, "\x00\x00\x00\x00\x00\x00\x00", 7) && !memcmp(block+9, "\x00\x00\x00\x00\x00\x00\x00", 7))
144 return true;
145 }
146 else if (block[7] == 0x00)
147 {
148 if (!memcmp(block+9, "\x00\x00\x00\x00\x00\x00\x00", 7))
149 return true;
150 }
151 return false;
d10e08ae 152}
153
818e15b0
S
154bool IsBlock1PCF7931(uint8_t *block) {
155 // assuming all RFU bits are set to 0
cfa9c98d
S
156
157 uint8_t rb1 = block[14] & 0x80;
158 uint8_t rfb = block[14] & 0x7f;
159 uint8_t rlb = block[15];
160
818e15b0 161 if (block[10] == 0 && block[11] == 0 && block[12] == 0 && block[13] == 0)
cfa9c98d
S
162 // block 1 is sent only if (RLB >= 1 && RFB <= 1) or RB1 enabled
163 if(rfb <= rlb && rfb <= 9 && rlb <= 9 && ((rfb <= 1 && rlb >= 1) || rb1))
818e15b0 164 return true;
d10e08ae 165
818e15b0 166 return false;
d10e08ae 167}
168
169void ReadPCF7931() {
818e15b0 170 int found_blocks = 0; // successfully read blocks
caaa4293 171 int max_blocks = 8; // readable blocks
818e15b0 172 uint8_t memory_blocks[8][17]; // PCF content
caaa4293 173
818e15b0
S
174 uint8_t single_blocks[8][17]; // PFC blocks with unknown position
175 int single_blocks_cnt = 0;
d10e08ae 176
caaa4293 177 size_t n = 0; // transmitted blocks
818e15b0 178 uint8_t tmp_blocks[4][16]; // temporary read buffer
caaa4293 179
818e15b0
S
180 uint8_t found_0_1 = 0; // flag: blocks 0 and 1 were found
181 int errors = 0; // error counter
182 int tries = 0; // tries counter
caaa4293 183
818e15b0
S
184 memset(memory_blocks, 0, 8*17*sizeof(uint8_t));
185 memset(single_blocks, 0, 8*17*sizeof(uint8_t));
caaa4293 186
818e15b0 187 int i = 0, j = 0;
d10e08ae 188
189 do {
818e15b0 190 i = 0;
caaa4293 191
818e15b0
S
192 memset(tmp_blocks, 0, 4*16*sizeof(uint8_t));
193 n = DemodPCF7931((uint8_t**)tmp_blocks);
d10e08ae 194 if(!n)
818e15b0 195 ++errors;
caaa4293 196
197 // exit if no block is received
818e15b0 198 if (errors >= 10 && found_blocks == 0 && single_blocks_cnt == 0) {
d10e08ae 199 Dbprintf("Error, no tag or bad tag");
200 return;
201 }
cfa9c98d 202
caaa4293 203 // exit if too many errors during reading
818e15b0 204 if (tries > 50 && (2*errors > tries)) {
d10e08ae 205 Dbprintf("Error reading the tag");
206 Dbprintf("Here is the partial content");
207 goto end;
208 }
caaa4293 209
818e15b0
S
210 // our logic breaks if we don't get at least two blocks
211 if (n < 2) {
cfa9c98d 212 // skip if all 0s block or no blocks
818e15b0
S
213 if (n == 0 || !memcmp(tmp_blocks[0], "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 16))
214 continue;
215
cfa9c98d 216 // add block to single blocks list
818e15b0
S
217 if (single_blocks_cnt < max_blocks) {
218 for (i = 0; i < single_blocks_cnt; ++i) {
219 if (!memcmp(single_blocks[i], tmp_blocks[0], 16)) {
220 j = 1;
d10e08ae 221 break;
222 }
223 }
818e15b0
S
224 if (j != 1) {
225 memcpy(single_blocks[single_blocks_cnt], tmp_blocks[0], 16);
cfa9c98d 226 print_result("got single block", single_blocks[single_blocks_cnt], 16);
818e15b0
S
227 single_blocks_cnt++;
228 }
229 j = 0;
d10e08ae 230 }
818e15b0
S
231 ++tries;
232 continue;
caaa4293 233 }
234
235 Dbprintf("(dbg) got %d blocks (%d/%d found) (%d tries, %d errors)", n, found_blocks, (max_blocks == 0 ? found_blocks : max_blocks), tries, errors);
cfa9c98d
S
236 for (i = 0; i < n; ++i)
237 {
238 print_result("got consecutive blocks", tmp_blocks[i], 16);
239 }
818e15b0
S
240
241 i = 0;
caaa4293 242 if(!found_0_1) {
818e15b0
S
243 while (i < n - 1) {
244 if (IsBlock0PCF7931(tmp_blocks[i]) && IsBlock1PCF7931(tmp_blocks[i+1])) {
245 found_0_1 = 1;
246 memcpy(memory_blocks[0], tmp_blocks[i], 16);
247 memcpy(memory_blocks[1], tmp_blocks[i+1], 16);
248 memory_blocks[0][ALLOC] = memory_blocks[1][ALLOC] = 1;
249 // block 1 tells how many blocks are going to be sent
250 max_blocks = MAX((memory_blocks[1][14] & 0x7f), memory_blocks[1][15]) + 1;
251 found_blocks = 2;
caaa4293 252
818e15b0 253 Dbprintf("Found blocks 0 and 1. PCF is transmitting %d blocks.", max_blocks);
caaa4293 254
818e15b0
S
255 // handle the following blocks
256 for (j = i + 2; j < n; ++j) {
257 memcpy(memory_blocks[found_blocks], tmp_blocks[j], 16);
258 memory_blocks[found_blocks][ALLOC] = 1;
259 ++found_blocks;
260 }
261 break;
262 }
263 ++i;
264 }
265 } else {
266 // Trying to re-order blocks
267 // Look for identical block in memory blocks
268 while (i < n-1) {
269 // skip all zeroes blocks
270 if (memcmp(tmp_blocks[i], "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 16)) {
271 for (j = 1; j < max_blocks - 1; ++j) {
272 if (!memcmp(tmp_blocks[i], memory_blocks[j], 16) && !memory_blocks[j+1][ALLOC]) {
273 memcpy(memory_blocks[j+1], tmp_blocks[i+1], 16);
274 memory_blocks[j+1][ALLOC] = 1;
275 if (++found_blocks >= max_blocks) goto end;
276 }
277 }
278 }
279 if (memcmp(tmp_blocks[i+1], "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 16)) {
280 for (j = 0; j < max_blocks; ++j) {
281 if (!memcmp(tmp_blocks[i+1], memory_blocks[j], 16) && !memory_blocks[(j == 0 ? max_blocks : j) -1][ALLOC]) {
282 if (j == 0) {
283 memcpy(memory_blocks[max_blocks - 1], tmp_blocks[i], 16);
284 memory_blocks[max_blocks - 1][ALLOC] = 1;
285 } else {
286 memcpy(memory_blocks[j-1], tmp_blocks[i], 16);
287 memory_blocks[j-1][ALLOC] = 1;
d10e08ae 288 }
818e15b0 289 if (++found_blocks >= max_blocks) goto end;
d10e08ae 290 }
291 }
292 }
818e15b0 293 ++i;
d10e08ae 294 }
295 }
818e15b0
S
296 ++tries;
297 if (BUTTON_PRESS()) {
298 Dbprintf("Button pressed, stopping.");
299 goto end;
300 }
301 }
cfa9c98d 302 while (found_blocks < max_blocks);
818e15b0 303
d10e08ae 304 end:
305 Dbprintf("-----------------------------------------");
306 Dbprintf("Memory content:");
307 Dbprintf("-----------------------------------------");
818e15b0
S
308 for (i = 0; i < max_blocks; ++i) {
309 if (memory_blocks[i][ALLOC])
310 print_result("Block", memory_blocks[i], 16);
d10e08ae 311 else
312 Dbprintf("<missing block %d>", i);
313 }
314 Dbprintf("-----------------------------------------");
caaa4293 315
818e15b0
S
316 if (found_blocks < max_blocks) {
317 Dbprintf("-----------------------------------------");
318 Dbprintf("Blocks with unknown position:");
319 Dbprintf("-----------------------------------------");
320 for (i = 0; i < single_blocks_cnt; ++i)
321 print_result("Block", single_blocks[i], 16);
caaa4293 322
818e15b0
S
323 Dbprintf("-----------------------------------------");
324 }
7cfc777b 325 cmd_send(CMD_ACK,0,0,0,0,0);
d10e08ae 326}
327
818e15b0 328static void RealWritePCF7931(uint8_t *pass, uint16_t init_delay, int32_t l, int32_t p, uint8_t address, uint8_t byte, uint8_t data) {
d10e08ae 329 uint32_t tab[1024]={0}; // data times frame
330 uint32_t u = 0;
331 uint8_t parity = 0;
332 bool comp = 0;
333
334 //BUILD OF THE DATA FRAME
d10e08ae 335 //alimentation of the tag (time for initializing)
336 AddPatternPCF7931(init_delay, 0, 8192/2*T0_PCF, tab);
d10e08ae 337 AddPatternPCF7931(8192/2*T0_PCF + 319*T0_PCF+70, 3*T0_PCF, 29*T0_PCF, tab);
d10e08ae 338 //password indication bit
339 AddBitPCF7931(1, tab, l, p);
818e15b0
S
340 // password (on 56 bits)
341 AddBytePCF7931(pass[0], tab, l, p);
342 AddBytePCF7931(pass[1], tab, l, p);
343 AddBytePCF7931(pass[2], tab, l, p);
344 AddBytePCF7931(pass[3], tab, l, p);
345 AddBytePCF7931(pass[4], tab, l, p);
346 AddBytePCF7931(pass[5], tab, l, p);
347 AddBytePCF7931(pass[6], tab, l, p);
d10e08ae 348 //programming mode (0 or 1)
349 AddBitPCF7931(0, tab, l, p);
caaa4293 350
d10e08ae 351 //block adress on 6 bits
818e15b0 352 for (u = 0; u < 6; ++u) {
caaa4293 353 if (address & (1 << u)) { // bit 1
818e15b0 354 ++parity;
d10e08ae 355 AddBitPCF7931(1, tab, l, p);
caaa4293 356 } else { // bit 0
d10e08ae 357 AddBitPCF7931(0, tab, l, p);
358 }
359 }
caaa4293 360
d10e08ae 361 //byte address on 4 bits
818e15b0 362 for (u = 0; u < 4; ++u)
d10e08ae 363 {
caaa4293 364 if (byte & (1 << u)) { // bit 1
d10e08ae 365 parity++;
366 AddBitPCF7931(1, tab, l, p);
d10e08ae 367 }
caaa4293 368 else // bit 0
818e15b0 369 AddBitPCF7931(0, tab, l, p);
d10e08ae 370 }
caaa4293 371
d10e08ae 372 //data on 8 bits
d10e08ae 373 for (u=0; u<8; u++)
374 {
caaa4293 375 if (data&(1<<u)) { // bit 1
d10e08ae 376 parity++;
377 AddBitPCF7931(1, tab, l, p);
caaa4293 378 }
379 else //bit 0
d10e08ae 380 AddBitPCF7931(0, tab, l, p);
d10e08ae 381 }
382
d10e08ae 383 //parity bit
818e15b0 384 if ((parity % 2) == 0)
caaa4293 385 AddBitPCF7931(0, tab, l, p); //even parity
818e15b0 386 else
d10e08ae 387 AddBitPCF7931(1, tab, l, p);//odd parity
d10e08ae 388
389 //time access memory
390 AddPatternPCF7931(5120+2680, 0, 0, tab);
391
392 //conversion of the scale time
818e15b0
S
393 for (u = 0; u < 500; ++u)
394 tab[u] = (tab[u] * 3) / 2;
d10e08ae 395
396 //compennsation of the counter reload
818e15b0 397 while (!comp) {
d10e08ae 398 comp = 1;
818e15b0
S
399 for (u = 0; tab[u] != 0; ++u)
400 if(tab[u] > 0xFFFF) {
d10e08ae 401 tab[u] -= 0xFFFF;
402 comp = 0;
403 }
d10e08ae 404 }
405
406 SendCmdPCF7931(tab);
407}
408
818e15b0
S
409void BruteForcePCF7931(uint64_t password, uint8_t tries, uint16_t init_delay, int32_t l, int32_t p) {
410 uint8_t i = 0;
411 uint8_t pass_array[7];
caaa4293 412
818e15b0
S
413 while (password < 0x00FFFFFFFFFFFFFF) {
414 if (BUTTON_PRESS()) {
415 Dbprintf("Button pressed, stopping bruteforce ...");
416 return;
417 }
caaa4293 418
419 num_to_bytes(password, 7, pass_array);
818e15b0
S
420
421 Dbprintf("Trying: %02x %02x %02x %02x %02x %02x %02x ...",
422 pass_array[0],
423 pass_array[1],
424 pass_array[2],
425 pass_array[3],
426 pass_array[4],
427 pass_array[5],
428 pass_array[6]);
caaa4293 429
818e15b0
S
430 for (i = 0; i < tries; ++i)
431 RealWritePCF7931
432 (
433 pass_array,
434 init_delay,
435 l,
436 p,
437 0,
438 7,
439 0x01
440 );
caaa4293 441
442 ++password;
818e15b0
S
443 }
444}
445
446/* Write on a byte of a PCF7931 tag
447 * @param address : address of the block to write
448 @param byte : address of the byte to write
caaa4293 449 @param data : data to write
818e15b0
S
450 */
451void WritePCF7931(uint8_t pass1, uint8_t pass2, uint8_t pass3, uint8_t pass4, uint8_t pass5, uint8_t pass6, uint8_t pass7, uint16_t init_delay, int32_t l, int32_t p, uint8_t address, uint8_t byte, uint8_t data) {
452 Dbprintf("Initialization delay : %d us", init_delay);
453 Dbprintf("Offsets : %d us on the low pulses width, %d us on the low pulses positions", l, p);
454 Dbprintf("Password (LSB first on each byte): %02x %02x %02x %02x %02x %02x %02x", pass1, pass2, pass3, pass4, pass5, pass6, pass7);
455 Dbprintf("Block address : %02x", address);
456 Dbprintf("Byte address : %02x", byte);
457 Dbprintf("Data : %02x", data);
caaa4293 458
818e15b0 459 uint8_t password[7] = {pass1, pass2, pass3, pass4, pass5, pass6, pass7};
caaa4293 460
818e15b0
S
461 RealWritePCF7931 (password, init_delay, l, p, address, byte, data);
462}
463
d10e08ae 464
465
466/* Send a trame to a PCF7931 tags
467 * @param tab : array of the data frame
468 */
469
818e15b0 470void SendCmdPCF7931(uint32_t * tab) {
d10e08ae 471 uint16_t u=0;
472 uint16_t tempo=0;
473
818e15b0 474 Dbprintf("Sending data frame ...");
d10e08ae 475
476 FpgaDownloadAndGo(FPGA_BITSTREAM_LF);
d10e08ae 477 FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz
d10e08ae 478 FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_PASSTHRU );
479
480 LED_A_ON();
481
482 // steal this pin from the SSP and use it to control the modulation
483 AT91C_BASE_PIOA->PIO_PER = GPIO_SSC_DOUT;
484 AT91C_BASE_PIOA->PIO_OER = GPIO_SSC_DOUT;
485
486 //initialization of the timer
487 AT91C_BASE_PMC->PMC_PCER |= (0x1 << 12) | (0x1 << 13) | (0x1 << 14);
488 AT91C_BASE_TCB->TCB_BMR = AT91C_TCB_TC0XC0S_NONE | AT91C_TCB_TC1XC1S_TIOA0 | AT91C_TCB_TC2XC2S_NONE;
489 AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKDIS; // timer disable
490 AT91C_BASE_TC0->TC_CMR = AT91C_TC_CLKS_TIMER_DIV3_CLOCK; //clock at 48/32 MHz
491 AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKEN;
492 AT91C_BASE_TCB->TCB_BCR = 1;
493
d10e08ae 494 tempo = AT91C_BASE_TC0->TC_CV;
818e15b0 495 for (u = 0; tab[u] != 0; u += 3) {
d10e08ae 496 // modulate antenna
497 HIGH(GPIO_SSC_DOUT);
818e15b0 498 while(tempo != tab[u])
d10e08ae 499 tempo = AT91C_BASE_TC0->TC_CV;
caaa4293 500
d10e08ae 501 // stop modulating antenna
502 LOW(GPIO_SSC_DOUT);
818e15b0 503 while(tempo != tab[u+1])
d10e08ae 504 tempo = AT91C_BASE_TC0->TC_CV;
d10e08ae 505
506 // modulate antenna
507 HIGH(GPIO_SSC_DOUT);
818e15b0 508 while(tempo != tab[u+2])
d10e08ae 509 tempo = AT91C_BASE_TC0->TC_CV;
d10e08ae 510 }
511
512 LED_A_OFF();
513 FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
514 SpinDelay(200);
515
d10e08ae 516 AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKDIS; // timer disable
818e15b0 517 DbpString("Data frame sent (multiple sends may be needed)");
d10e08ae 518 LED(0xFFFF, 1000);
519}
520
521
caaa4293 522/* Add a byte for building the data frame of PCF7931 tags
d10e08ae 523 * @param b : byte to add
524 * @param tab : array of the data frame
525 * @param l : offset on low pulse width
526 * @param p : offset on low pulse positioning
527 */
818e15b0 528bool AddBytePCF7931(uint8_t byte, uint32_t * tab, int32_t l, int32_t p) {
d10e08ae 529 uint32_t u;
818e15b0 530 for (u = 0; u < 8; ++u) {
caaa4293 531 if (byte & (1 << u)) { //bit is 1
d10e08ae 532 if(AddBitPCF7931(1, tab, l, p)==1)return 1;
818e15b0 533 } else { //bit is 0
d10e08ae 534 if(AddBitPCF7931(0, tab, l, p)==1)return 1;
535 }
536 }
537
538 return 0;
539}
540
caaa4293 541/* Add a bits for building the data frame of PCF7931 tags
d10e08ae 542 * @param b : bit to add
543 * @param tab : array of the data frame
544 * @param l : offset on low pulse width
545 * @param p : offset on low pulse positioning
546 */
818e15b0 547bool AddBitPCF7931(bool b, uint32_t * tab, int32_t l, int32_t p) {
d10e08ae 548 uint8_t u = 0;
549
818e15b0 550 for (u = 0; tab[u] != 0; u += 3){} //we put the cursor at the last value of the array
d10e08ae 551
caaa4293 552 if (b == 1) { //add a bit 1
553 if (u == 0) tab[u] = 34 * T0_PCF + p;
554 else tab[u] = 34 * T0_PCF + tab[u-1] + p;
d10e08ae 555
818e15b0
S
556 tab[u+1] = 6 * T0_PCF+tab[u] + l;
557 tab[u+2] = 88 * T0_PCF+tab[u + 1] - l - p;
d10e08ae 558 return 0;
caaa4293 559 } else { //add a bit 0
d10e08ae 560
caaa4293 561 if (u == 0) tab[u] = 98 * T0_PCF + p;
562 else tab[u] = 98 * T0_PCF + tab[u-1] + p;
d10e08ae 563
818e15b0
S
564 tab[u + 1] = 6 * T0_PCF + tab[u] + l;
565 tab[u + 2] = 24 * T0_PCF + tab[u + 1] - l - p;
d10e08ae 566 return 0;
567 }
caaa4293 568
d10e08ae 569 return 1;
570}
571
572/* Add a custom pattern in the data frame
573 * @param a : delay of the first high pulse
574 * @param b : delay of the low pulse
575 * @param c : delay of the last high pulse
576 * @param tab : array of the data frame
577 */
818e15b0 578bool AddPatternPCF7931(uint32_t a, uint32_t b, uint32_t c, uint32_t * tab) {
d10e08ae 579 uint32_t u = 0;
818e15b0 580 for(u = 0; tab[u] != 0; u += 3){} //we put the cursor at the last value of the array
d10e08ae 581
caaa4293 582 if (u == 0) tab[u] = a;
583 else tab[u] = a + tab[u - 1];
d10e08ae 584
818e15b0
S
585 tab[u + 1] = b + tab[u];
586 tab[u + 2] = c + tab[u + 1];
d10e08ae 587
588 return 0;
589}
Impressum, Datenschutz