as3993 ST25RU3993 Firmware
gen2.c
Go to the documentation of this file.
1 /*
2  *****************************************************************************
3  * AS3993/ST25RU3993 Firmware tech@eleckits.com http://iot.eleckits.com *
4  * STMicroelectronics ST25RU3993 is an EPC Class 1 Gen 2 RFID reader IC *
5  * *
6  * IMPORTANT - PLEASE READ CAREFULLY BEFORE COPYING, INSTALLING OR USING *
7  * THE SOFTWARE. *
8  * *
9  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS *
10  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT *
11  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS *
12  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT *
13  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, *
14  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT *
15  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, *
16  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY *
17  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT *
18  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE *
19  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
20  *****************************************************************************
21  */
30 #include "as3993_config.h"
31 #include "platform.h"
32 #include "as3993.h"
33 #include "logger.h"
34 #include "timer.h"
35 #include "gen2.h"
36 #include "string.h"
37 
39 #define EPCDEBUG 0
40 
41 #if EPCDEBUG && (USE_LOGGER == LOGGER_ON)
42 #define EPCLOG dbgLog
43 #define EPCLOGDUMP dbgHexDump
44 #else
45 //if debugging is disabled set empty log functions.
46 #define EPCLOG(...)
47 #define EPCLOGDUMP(...)
48 #endif
49 
50 /*EPC Commands */
52 #define EPC_QUERYREP 0
53 
54 #define EPC_ACK 1
55 
56 #define EPC_QUERY 0x08
57 
58 #define EPC_QUERYADJUST 0x09
59 
60 #define EPC_SELECT 0x0A
61 
62 #define EPC_NAK 0xC0
63 
64 #define EPC_REQRN 0xC1
65 
66 #define EPC_READ 0xC2
67 
68 #define EPC_WRITE 0xC3
69 
70 #define EPC_KILL 0xC4
71 
72 #define EPC_LOCK 0xC5
73 
74 #define EPC_ACCESS 0xC6
75 
76 #define EPC_BLOCKWRITE 0xC7
77 
78 #define EPC_BLOCKERASE 0xC8
79 
80 #define EPC_BLOCKPERMALOCK 0xC9
81 
82 #define GEN2_RESET_TIMEOUT 10
83 /*------------------------------------------------------------------------- */
84 /* local types */
85 /*------------------------------------------------------------------------- */
86 
87 struct gen2InternalConfig{
88  struct gen2Config config;
89  u8 DR; /* Division ratio */
90  u8 no_resp_time; /* value for AS3993_REG_RXNORESPONSEWAITTIME */
91 };
92 
93 /*------------------------------------------------------------------------- */
94 /*global variables */
95 /*------------------------------------------------------------------------- */
96 
101 static u8 buf_[8+EPCLENGTH+PCLENGTH+CRCLENGTH]; /*8->tx_length+EPCcommand+wordptr+wordcount+handle+broken byte */
102 
103 static struct gen2InternalConfig gen2IntConfig;
104 
105 /*------------------------------------------------------------------------- */
106 /* local prototypes */
107 /*------------------------------------------------------------------------- */
108 
109 
110 /*------------------------------------------------------------------------- */
120 static s8 gen2ReqRNHandleChar(u8 const * handle, u8 *dest_handle);
121 
122 static u8 gen2InsertEBV(u32 value, u8 *p, u8 bitpos)
123 {
124  u8 ebv[5];
125  u8 ebvlen;
126  u32ToEbv(value, ebv, &ebvlen);
127  insertBitStream(p, ebv, ebvlen, bitpos);
128  return ebvlen;
129 }
130 
131 static void gen2GetAgcRssi(u8 *agc, u8 *rssi)
132 {
133  u8 buf[2];
134  as3993ContinuousRead(AS3993_REG_AGCANDSTATUS, 2, buf);
135  *agc = buf[0];
136  *rssi = buf[1];
137 }
138 /*------------------------------------------------------------------------- */
139 /* global functions */
140 /*------------------------------------------------------------------------- */
141 
142 void gen2Select(struct gen2SelectParams *p)
143 {
144 #if !RUN_ON_AS3980 // no select on AS3980 available
145  u16 len = p->mask_len;
146  u8 ebvLen;
147  u16 rxbits = 1;
148  u8 *mask = p->mask;
149  u8 j,i;
150  u8 resp_null;
151  u8 jLeftBits;
152  u8 posTruncbit;
153  as3993ClrResponse();
154  memset(buf_,0,sizeof(buf_));
155 
156  buf_[0] = ((EPC_SELECT<<4)&0xF0) | ((p->target<<1)&0x0E) | ((p->action>>2)&0x01);
157  buf_[1] = ((p->action<<6)&0xC0) | ((p->mem_bank<<4)&0x30);
158  ebvLen = gen2InsertEBV(p->mask_address, buf_+1, 4);
159  buf_[1+ebvLen] = ((p->mask_len>>4)&0x0F);
160  buf_[2+ebvLen] = ((p->mask_len<<4)&0xF0);
161 
162  i = 2+ebvLen; /* the counter set to last buffer location */
163  for (j = len; j >= 8 ; j -= 8, mask++)
164  {
165  buf_[i] |= 0x0F & (*mask >> 4);
166  i++;
167  buf_[i] = 0xF0 & (*mask << 4);
168  }
169 
170  if (j == 0)
171  {
172  buf_[i] |= ((p->truncation<<3)&0x08)/*Truncate*/;
173  }
174  else // if length is not dividable by 8
175  { jLeftBits = 0xFF << (8-j);
176 
177  buf_[i] |= (jLeftBits >> 4) & (*mask >> 4);
178  buf_[i+1] = (jLeftBits << 4) & (*mask << 4);
179  // add truncation bit
180  posTruncbit = (p->truncation & 0x01) <<(7-j);
181  buf_[i] |= (posTruncbit >> 4) ;
182  buf_[i+1] |= (posTruncbit << 4) ;
183  }
184 
185  len += 21 + ebvLen * 8; /* Add the bits for EPC command before continuing */
186 
187  /* Pseudo 1-bit receival with small timeout to have AS3993 state machine
188  finished and avoiding spurious interrupts (no response) */
189  as3993TxRxGen2Bytes(AS3993_CMD_TRANSMCRC, buf_, len, &resp_null, &rxbits, 1, 0, 1);
190 #endif
191 }
192 
193 static void gen2PrepareQueryCmd(u8 *buf, u8 q)
194 {
195  buf[0] = ((gen2IntConfig.DR<<5)&0x20)/*DR*/ |
196  ((gen2IntConfig.config.miller<<3)&0x18)/*M*/ |
197  ((gen2IntConfig.config.trext<<2)&0x04)/*TREXT*/ |
198  ((gen2IntConfig.config.sel<<0)&0x03)/*SEL*/;
199  buf[1] = ((gen2IntConfig.config.session<<6)&0xC0)/*SESSION*/ |
200  ((gen2IntConfig.config.target<<5)&0x20)/*TARGET*/ |
201  ((q<<1)&0x1E)/*Q*/;
202 
203 }
204 
205 s8 gen2QueryMeasureRSSI(u8 *agc, u8 *log_rssis, s8 *irssi, s8 *qrssi)
206 {
207  u16 rxlen;
208  u8 rn16[2];
209  s8 ret = 0;
210  u8 reg;
211  uint i = 100;
212 
213  reg = as3993SingleRead(AS3993_REG_MEASUREMENTCONTROL);
214 
215  /*********************************************************************************/
216  /* Send simple query command, make the tag react immediately */
217  /*********************************************************************************/
218  gen2PrepareQueryCmd(buf_, 0);
219  rxlen = 16;
220  ret = as3993TxRxGen2Bytes(AS3993_CMD_QUERY,buf_,16,NULL,&rxlen,gen2IntConfig.no_resp_time,0,1);
221 
222  if (ret)
223  {
224  return ret;
225  }
226 
227  while (i--)
228  { /* Check rx_status, if 1 receive is in progress/has started */
229  if (0x40 & as3993SingleRead(AS3993_REG_FIFOSTATUS)) break;
230  }
231 
232  gen2GetAgcRssi(agc, log_rssis);
233  as3993SingleWrite(AS3993_REG_MEASUREMENTCONTROL, (reg & ~0xf) | 0xb );
234  *irssi = as3993GetADC(); /* RSSI I level */
235  as3993SingleWrite(AS3993_REG_MEASUREMENTCONTROL, (reg & ~0xf) | 0xc );
236  *qrssi = as3993GetADC(); /* RSSI Q level */
237 
238  rxlen = 16;
239  ret = as3993TxRxGen2Bytes(0,NULL,NULL,rn16,&rxlen,gen2IntConfig.no_resp_time,0,0);
240 
241  return ret;
242 }
243 
244 /*
245  * Sends a Query, QueryRep or QueryAdjust command and checks for replies from tags.
246  * If a tag is found, the Ack command is sent. If fast mode is not enabled the Reg_RN
247  * command will be sent after receiving the Ack reply.\n
248  * All of the data which is retrieved from the tag is written into parameter tag.
249  * \param tag The reply data of the tag is written into this data structure
250  * \param qCommand The command which should be sent. Should be Query, QueryRep or QueryAdjust
251  * \param q Q as specified in the Gen2 spec
252  * \param fast If fast mode is activated no Req_RN command will be sent after receiving the
253  * Ack reply. If no QueryRep, QueryAdjust or Reg_RN is sent to the tag within T2 the tag will
254  * go back to arbitrate state.
255  * \param followCommand The command which will be sent after a slot has been processed
256  * successfully (valid tag response). Usually this will be used to send a QueryRep
257  * immediately after receiving a tag response to trigger a change of the current
258  * session flag.
259  * \return 1 if one tag has been succesfully read, 0 if no response in slot, -1 if error occured (collision)
260  */
261 static s8 gen2Slot(Tag *tag, u8 qCommand, u8 q, BOOL fast, u8 followCommand)
262 {
263  u16 rxlen;
264  s8 ret = 0;
265 
266  /*********************************************************************************/
267  /* 1. Send proper query command */
268  /*********************************************************************************/
269  rxlen = 16;
270  switch (qCommand)
271  {
272  case AS3993_CMD_QUERY:
273  gen2PrepareQueryCmd(buf_, q);
274  ret = as3993TxRxGen2Bytes(AS3993_CMD_QUERY,buf_,16,tag->rn16,&rxlen,gen2IntConfig.no_resp_time,AS3993_CMD_ACK,1);
275  break;
276  case 0: //query rep has already been sent
277  ret = as3993TxRxGen2Bytes(0,NULL,0,tag->rn16,&rxlen,gen2IntConfig.no_resp_time,AS3993_CMD_ACK,1);
278  break;
279  default:
280  ret = as3993TxRxGen2Bytes(qCommand,NULL,0,tag->rn16,&rxlen,gen2IntConfig.no_resp_time,AS3993_CMD_ACK,1);
281  }
282  if (ret == AS3993_ERR_NORES)
283  {
284  EPCLOG(" query -> noresp\n");
285  return 0;
286  }
287  if (ret < 0)
288  {
289  EPCLOG(" query -> err %hhx\n", ret);
290  return -1;
291  }
292 
293  /*********************************************************************************/
294  /* 2. Sent ACK, Receive pc, epc, send REQRN immediately after FIFO has the data */
295  /*********************************************************************************/
296  rxlen = sizeof(buf_)*8; //receive all data, length auto-calculated by AS3993
297  ret = as3993TxRxGen2Bytes(0,buf_,0,buf_,&rxlen,gen2IntConfig.no_resp_time,fast?followCommand:AS3993_CMD_REQRN,0);
298  tag->pc[0] = buf_[0];
299  tag->pc[1] = buf_[1];
300  if (ret < 0 || rxlen < 16)
301  {
302  EPCLOG(" ack rx rest(pc=%hhx) -> err %hhx\n", tag->pc[0], ret);
303  return -1;
304  }
305 #if RUN_ON_AS3980
306  tag->epclen = (rxlen+7)/8-4; //on AS3980 crc is in the fifo, omit it.
307 #else
308  tag->epclen = (rxlen+7)/8-2;
309 #endif
310  if(tag->epclen > EPCLENGTH)
311  tag->epclen = EPCLENGTH;
312  memcpy(tag->epc, buf_+2, tag->epclen);
313 
314  if (fast)
315  {
316  gen2GetAgcRssi(&tag->agc, &tag->rssi);
317  if (((tag->pc[0] & 0xF8) >> 2) != tag->epclen)
318  {
319  return -1;
320  }
321  return 1;
322  }
323  /*********************************************************************************/
324  /* 3. Receive the two bytes handle */
325  /*********************************************************************************/
326  rxlen = 32;
327  ret = as3993TxRxGen2Bytes(0,NULL,0,tag->handle,&rxlen,gen2IntConfig.no_resp_time,followCommand,0);
328  gen2GetAgcRssi(&tag->agc, &tag->rssi);
329  if (ret < 0)
330  {
331  EPCLOG(" reqrn -> err %hhx\n", ret);
332  return -1;
333  }
334  if (((tag->pc[0] & 0xF8) >> 2) != tag->epclen)
335  {
336  EPCLOG(" reqrn -> err %hhx\n", ret);
337  return -1;
338  }
339  return 1;
340 }
341 
342 
345 static s8 gen2SlotAutoAck(Tag *tag, u8 qCommand, u8 q, BOOL fast, u8 followCommand)
346 {
347  u16 rxlen;
348  s8 ret = 0;
349 
350  /*********************************************************************************/
351  /* 1. Send proper query command */
352  /*********************************************************************************/
353  rxlen = sizeof(buf_)*8; //receive all data, length auto-calculated by AS3993
354  switch (qCommand)
355  {
356  case AS3993_CMD_QUERY:
357  gen2PrepareQueryCmd(buf_, q);
358  ret = as3993TxRxGen2Bytes(AS3993_CMD_QUERY,buf_,16,buf_,&rxlen,gen2IntConfig.no_resp_time,fast?followCommand:0,0);
359  break;
360  case 0:
361  ret = as3993TxRxGen2Bytes(0,NULL,0,buf_,&rxlen,gen2IntConfig.no_resp_time,fast?followCommand:0,0);
362  break;
363  default:
364  ret = as3993TxRxGen2Bytes(qCommand,NULL,0,buf_,&rxlen,gen2IntConfig.no_resp_time,fast?followCommand:0,0);
365  }
366  if (ret == AS3993_ERR_NORES)
367  {
368  EPCLOG(" query -> noresp\n");
369  return 0;
370  }
371 
372  /*********************************************************************************/
373  /* 2. ACK was sent automatically, pc and epc already received */
374  /*********************************************************************************/
375  tag->pc[0] = buf_[0];
376  tag->pc[1] = buf_[1];
377  if (ret < 0 || rxlen < 16)
378  {
379  EPCLOG(" auto ack rx (pc=%hhx) -> err %hhx\n", tag->pc[0], ret);
380  return -1;
381  }
382 #if RUN_ON_AS3980
383  tag->epclen = (rxlen+7)/8-4; //on AS3980 crc is in the fifo, omit it.
384 #else
385  tag->epclen = (rxlen+7)/8-2;
386 #endif
387  if(tag->epclen > EPCLENGTH)
388  tag->epclen = EPCLENGTH;
389  memcpy(tag->epc, buf_+2, tag->epclen);
390 
391  if (fast)
392  {
393  gen2GetAgcRssi(&tag->agc, &tag->rssi);
394  if (((tag->pc[0] & 0xF8) >> 2) != tag->epclen)
395  {
396  return -1;
397  }
398  return 1;
399  }
400 
401  /*********************************************************************************/
402  /* 4. Receive the two bytes handle */
403  /*********************************************************************************/
404  rxlen = 32;
405  ret = as3993TxRxGen2Bytes(0,NULL,0,tag->handle,&rxlen,gen2IntConfig.no_resp_time,followCommand,0);
406  gen2GetAgcRssi(&tag->agc, &tag->rssi);
407  if (ret < 0)
408  {
409  EPCLOG(" reqrn -> err %hhx\n", ret);
410  return -1;
411  }
412 
413  if (((tag->pc[0] & 0xF8) >> 2) != tag->epclen)
414  {
415  return -1;
416  }
417  return 1;
418 }
419 
420 /*------------------------------------------------------------------------- */
421 static s8 gen2ReqRNHandleChar(u8 const * handle, u8 *dest_handle)
422 {
423  s8 ret;
424  u16 rxbits = 32;
425 
426  buf_[0] = EPC_REQRN; /*Command REQRN */
427  buf_[1] = handle[0];
428  buf_[2] = handle[1];
429 
430  ret = as3993TxRxGen2Bytes(AS3993_CMD_TRANSMCRC,buf_,24,dest_handle,&rxbits,gen2IntConfig.no_resp_time,0,1);
431 
432  if (ret < 0) return GEN2_ERR_REQRN;
433 
434  return GEN2_OK;
435 }
436 
437 /*------------------------------------------------------------------------- */
438 s8 gen2AccessTag(Tag const * tag, u8 const * password)
439 {
440  s8 ret;
441  s8 error;
442  u8 count;
443  u16 rxcount;
444  u8 tagResponse[5];
445  u8 temp_rn16[2];
446 
447  for (count = 0; count < 2; count++)
448  {
449  error = gen2ReqRNHandleChar(tag->handle, temp_rn16);
450  if (error)
451  {
452  return(error);
453  }
454 
455  buf_[0] = EPC_ACCESS;
456  buf_[1] = password[0] ^ temp_rn16[0];
457  buf_[2] = password[1] ^ temp_rn16[1];
458  buf_[3] = tag->handle[0];
459  buf_[4] = tag->handle[1];
460 
461  rxcount = 32;
462  ret = as3993TxRxGen2Bytes(AS3993_CMD_TRANSMCRC,buf_,40,tagResponse,&rxcount,gen2IntConfig.no_resp_time,0,1);
463  if (ret < 0)
464  {
465  EPCLOG("access failed, tx-ret: %hhx\n", ret);
466  return GEN2_ERR_ACCESS;
467  }
468  password += 2; /* Increase pointer by two to fetch the next bytes;- */
469 
470  if ((tagResponse[1] != tag->handle[1]) ||
471  (tagResponse[0] != tag->handle[0]))
472  {
473  EPCLOG("handle not correct\n");
474  return GEN2_ERR_ACCESS;
475  }
476 #if EPCDEBUG
477  if (count ==0) EPCLOG("first part of access ok\n");
478  if (count ==1) EPCLOG("second part of access ok\n");
479 #endif
480  }
481  return ret;
482 }
483 
484 /*------------------------------------------------------------------------- */
485 s8 gen2LockTag(Tag *tag, const u8 *mask_action, u8 *tag_reply)
486 {
487  s8 ret;
488 #if EPCDEBUG
489  u8 count;
490 #endif
491  u16 rxbits = 32+1;
492 
493  *tag_reply = 0xa5;
494 
495  buf_[0] = EPC_LOCK; /*Command EPC_LOCK */
496 
497  buf_[1] = mask_action[0];
498  buf_[2] = mask_action[1];
499 
500  buf_[3] = ((mask_action[2] ) & 0xF0);
501  insertBitStream(&buf_[3], tag->handle, 2, 4);
502 
503 #if EPCDEBUG
504  EPCLOG("lock code\n");
505  for (count=0; count<6; count++)
506  {
507  EPCLOG("%hhx ",buf_[count]);
508  }
509  EPCLOG("\n");
510 #endif
511 
512  ret = as3993TxRxGen2Bytes(AS3993_CMD_TRANSMCRCEHEAD, buf_, 44, buf_, &rxbits, 0xff, 0, 1);
513 
514  if (ERR_CHIP_HEADER == ret && rxbits) *tag_reply = buf_[0];
515  return ret;
516 }
517 
518 /*------------------------------------------------------------------------- */
519 s8 gen2KillTag(Tag const * tag, u8 const * password, u8 rfu, u8 recom, u8* tag_error)
520 {
521  s8 error;
522  u8 count;
523  u8 temp_rn16[2];
524  u16 rxbits = 32;
525  u8 cmd = AS3993_CMD_TRANSMCRC;/* first command has no header Bit */
526  u8 no_resp_time = gen2IntConfig.no_resp_time;
527 
528  *tag_error = 0xa5;
529  for (count = 0; count < 2; count++)
530  {
531  error = gen2ReqRNHandleChar(tag->handle, temp_rn16);
532  if (error)
533  {
534  break;
535  }
536 
537  if (count==1)
538  { /* Values for second part of kill */
539  cmd = AS3993_CMD_TRANSMCRCEHEAD; /* expect header bit */
540  rxbits = 32 + 1; /* add header bit */
541  rfu = recom; /* different data for rfu/recom */
542  no_resp_time = 0xff; /* waiting time up to 20ms */
543  }
544 
545  buf_[0] = EPC_KILL;
546 
547  buf_[1] = password[0] ^ temp_rn16[0];
548  buf_[2] = password[1] ^ temp_rn16[1];
549 
550  buf_[3] = ((rfu << 5) & 0xE0);
551  insertBitStream(&buf_[3], tag->handle, 2, 5);
552 
553  error = as3993TxRxGen2Bytes(cmd, buf_, 43, buf_, &rxbits, no_resp_time, 0, 1);
554 
555  if ( error )
556  {
557  break;
558  }
559  password += 2;
560  }
561  if(ERR_CHIP_HEADER == error && rxbits) *tag_error = buf_[0];
562  return error;
563 }
564 
565 /*------------------------------------------------------------------------- */
566 s8 gen2WriteWordToTag(Tag const * tag, u8 memBank, u32 wordPtr,
567  u8 const * databuf, u8 * tag_error)
568 {
569  s8 error;
570  u8 datab;
571  s8 ret;
572  u8 ebvlen;
573  u8 temp_rn16[2];
574  u16 rxbits = 32+1;
575  *tag_error = 0xa5;
576 
577  error = gen2ReqRNHandleChar(tag->handle, temp_rn16);
578  EPCLOG("wDtT %hx%hx->%hhx%hhx\n",wordPtr,databuf[0],databuf[1]);
579  if (error)
580  {
581  EPCLOG("reqrn error\n");
582  return(error);
583  }
584 
585  buf_[0] = EPC_WRITE; /*Command EPC_WRITE */
586 
587  buf_[1] = (memBank << 6) & 0xC0;
588  ebvlen = gen2InsertEBV(wordPtr, &buf_[1], 6);
589 
590  datab = databuf[0] ^ temp_rn16[0];
591  buf_[1+ebvlen] |= ((datab >> 2) & 0x3F);
592  buf_[2+ebvlen] = (datab << 6) & 0xC0;
593 
594  datab = databuf[1] ^ temp_rn16[1];
595  buf_[2+ebvlen] |= ((datab >> 2) & 0x3F);
596  buf_[3+ebvlen] = (datab << 6) & 0xC0;
597 
598  insertBitStream(&buf_[3+ebvlen], tag->handle, 2, 6);
599 
600  ret = as3993TxRxGen2Bytes(AS3993_CMD_TRANSMCRCEHEAD, buf_, 42+8*ebvlen, buf_, &rxbits, 0xff, 0, 1);
601 
602  if (ERR_CHIP_HEADER == ret && rxbits) *tag_error = buf_[0];
603  EPCLOG(" smo %hhx\n",ret);
604  EPCLOG(" handle %hhx %hhx\n",tag->handle[0],tag->handle[1]);
605  EPCLOG(" buf_ %hhx %hhx\n",buf_[0],buf_[1]);
606  EPCLOG(" rxbits = %hx\n",rxbits);
607  return ret;
608 }
609 
610 /*------------------------------------------------------------------------- */
611 s8 gen2ReadFromTag(Tag *tag, u8 memBank, u32 wordPtr,
612  u8 wordCount, u8 *destbuf)
613 {
614  u16 bit_count = (wordCount * 2 + 4) * 8 + 1; /* + 2 bytes rn16 + 2bytes crc + 1 header bit */
615  s8 ret;
616  u8 ebvlen;
617 
618  buf_[0] = EPC_READ; /*Command EPC_READ */
619  buf_[1] = (memBank << 6) & 0xC0;
620  ebvlen = gen2InsertEBV(wordPtr, &buf_[1], 6);
621  buf_[1+ebvlen] |= ((wordCount >> 2) & 0x3F);
622  buf_[2+ebvlen] = (wordCount << 6) & 0xC0;
623  insertBitStream(&buf_[2+ebvlen], tag->handle, 2, 6);
624 
625  ret = as3993TxRxGen2Bytes(AS3993_CMD_TRANSMCRCEHEAD, buf_, 34+8*ebvlen, destbuf, &bit_count, gen2IntConfig.no_resp_time, 0, 1);
626 
627  EPCLOG("bank=%hhx, w=%hx%hx, wc = %hhx ret=%hhx\n",memBank,wordPtr,wordCount,ret);
628  EPCLOGDUMP(destbuf,wordCount*2);
629  return ret;
630 }
631 
632 void gen2PrintGen2Settings()
633 {
634  u8 buf[9];
635  as3993ContinuousRead(AS3993_REG_PROTOCOLCTRL, 9, buf);
636  LOG("Gen2 registers:\n");
637  LOGDUMP(buf, 9);
638 
639 }
640 
641 /*------------------------------------------------------------------------------ */
642 void gen2PrintEPC(Tag *tag)
643 {
644  u16 count;
645  EPCLOG("Print PC %hhx %hhx\n",tag->pc[0], tag->pc[1]);
646  EPCLOG("Print EPC, len= %hhx \n", tag->epclen);
647  for (count=0; count<(tag->epclen); count++)
648  {
649  EPCLOG("%hhx ",tag->epc[count]);
650  }
651  EPCLOG("\n");
652 }
653 
654 /*------------------------------------------------------------------------- */
655 void gen2PrintTagInfo(Tag *tag, u8 epclen, u8 tagNr)
656 {
657  u8 count = 0;
658 
659  EPCLOG("TAG %hhx:\n",tagNr);
660  EPCLOG("RN16: %hhx %hhx\n",tag->rn16[1]
661  ,tag->rn16[0]);
662  EPCLOG("Number of read bytes: %d\n",epclen+2);
663  EPCLOG("PC: %hhx %hhx", tag->pc[1]
664  , tag->pc[0]);
665  EPCLOG("EPC: ");
666  while (count < epclen)
667  {
668  EPCLOG("%hhx ",tag->epc[count]);
669  count++;
670  }
671  EPCLOG("\n");
672 
673  EPCLOG("EPCLEN (bytes): %hhd\n",tag->epclen);
674 
675  EPCLOG("HANDLE: %hhx %hhx\n", tag->handle[0]
676  , tag->handle[1]);
677 }
678 
680  , u8 maxtags
681  , u8 q
682  , u8 addRounds
683  , u8 queryAdjustUpTh
684  , u8 queryAdjustDownTh
685  , BOOL (*cbContinueScanning)(void)
686  , BOOL singulate
687  , BOOL toggleSession
688  , s8 (*followTagCommand)(Tag *tag)
689  )
690 {
691  u16 num_of_tags = 0;
692  u8 i = 0;
693  u8 cmd = AS3993_CMD_QUERY;
694  u8 followCmd = 0;
695  u8 rounds = addRounds + 1;// One round for Query Command* the maximal number of rounds performed */
696 
697 #if !RUN_ON_AS3980
698  u16 collisions = 0;
699  u16 slot_count;
700 
701  if (toggleSession)
702  followCmd = AS3993_CMD_QUERYREP;
703 #else
704  rounds = 1;
705 #endif
706 
707  if (followTagCommand != NULL)
708  {
709  followCmd = 0; //no follow Command
710  singulate = 1; // not fast
711  }
713  as3993ContinuousRead(AS3993_REG_IRQSTATUS1, 2, &buf_[0]); // ensure that IRQ bits are reset
714  as3993ClrResponse();
715 
716  EPCLOG("Searching for Tags, maxtags=%hhd, q=%hhd\n",maxtags,q);
717  EPCLOG("-------------------------------\n");
718 
719  for (i=0; i < maxtags; i++) /*Reseting the TAGLIST */
720  {
721  tags_[i].rn16[0] = 0;
722  tags_[i].rn16[1] = 0;
723  tags_[i].epclen=0;
724  }
725 
726 
727 #if RUN_ON_AS3980
728  if ( gen2Slot(tags_+num_of_tags, cmd, q, !singulate, followCmd) == 1)
729  {
730  if (followTagCommand != NULL)
731  {
732  followTagCommand(tags_+num_of_tags);
733  }
734  num_of_tags++;
735  }
736 #else
737 
738 
739  do
740  {
741  BOOL goOn;
742  collisions = 0;
743  slot_count = 1UL<<q; /*get the maximum slot_count */
744  do
745  {
746  if (num_of_tags >= maxtags)
747  {/* ERROR it is not possible to store more than maxtags Tags */
748  break;
749  }
750  EPCLOG("next slot, command: %x\n", cmd);
751  slot_count--;
752 
753  if ((cmd == AS3993_CMD_QUERYADJUSTUP) || (cmd == AS3993_CMD_QUERYADJUSTNIC) ||(cmd == AS3993_CMD_QUERYADJUSTDOWN)) // T4 Time
754  {
755  //delay_us(210); // If there was a Query Rep Command ongoing, wait time added
756  if (gen2IntConfig.config.tari == TARI_25) // TODO: change delay dependent on Tx one length
757  {
758  delay_us(150); // Tx_one_length = 2
759  }
760  else if (gen2IntConfig.config.tari == TARI_125)
761  {
762  delay_us(75);// Tx_one_length = 2
763  }
764  else //(gen2IntConfig.config.tari = TARI_625)
765  {
766  delay_us(38);// Tx_one_length = 2
767  }
768  as3993ClrResponse(); // clear also TX IRQ
769  }
770 
771  switch (gen2Slot(tags_+num_of_tags, cmd, q, !singulate, followCmd))
772  {
773  case -1:
774  //EPCLOG("collision\n");
775  collisions++;
776  cmd = AS3993_CMD_QUERYREP;
777  break;
778  case 1:
779  if (followCmd)
780  cmd = 0; // query_rep has already been sent as followCmd
781  else
782  cmd = AS3993_CMD_QUERYREP;
783  if (followTagCommand != NULL)
784  {
785  followTagCommand(tags_+num_of_tags);
786  cmd = AS3993_CMD_QUERYREP;
787  }
788  num_of_tags++;
789  break;
790  case 0:
791  //EPCLOG("NO EPC response -> empty Slot\n");
792  cmd = AS3993_CMD_QUERYREP;
793  break;
794  default:
795  break;
796  }
797  goOn = cbContinueScanning();
798  } while (slot_count && goOn );
799  rounds--;
800  EPCLOG("q=%hhx, collisions=%x, num_of_tags=%x",q,collisions,num_of_tags);
801  if (cmd == 0) // if Query Rep was already send
802  {
803  as3993WaitForResponse(RESP_TXIRQ);
804  as3993ClrResponse();
805  }
806 
807  if( collisions )
808  {
809  if(( collisions >= (1UL<<q) * (queryAdjustUpTh/100))&& (q <8) )
810  {
811  q++;
812  EPCLOG("->++\n");
813  cmd = AS3993_CMD_QUERYADJUSTUP;
814  }
815  else if( collisions < (1UL<<q) * (queryAdjustDownTh/100) )
816  {
817  q--;
818  EPCLOG("->--\n");
819  cmd = AS3993_CMD_QUERYADJUSTDOWN;
820  }
821  else
822  {
823  EPCLOG("->==\n");
824  cmd = AS3993_CMD_QUERYADJUSTNIC;
825  }
826  }
827  else
828  {
829  EPCLOG("->!!\n");
830  rounds = 0;
831  }
832 
833  }while(num_of_tags < maxtags && rounds && cbContinueScanning() );
834 #endif
835 
836  // If a tag is found in the last slot of an inventory round, follow Command QueryRep will be executed.
837  // Add some time to send this command to the tag over the field.
838  // If function will be left to early and field will be switched off the tag will not invert the inventoried flag.
839  // Problem especially for S2 and S3.
840  // If there was a follow Tag Command a Query Rep. has to be sent to invert the session flag.
841 #if RUN_ON_AS3993
842  if (followTagCommand == NULL)
843  {
844  delay_us(150);
845  }
846  else
847  {
848  as3993SingleCommand(AS3993_CMD_QUERYREP);
849  as3993WaitForResponse(RESP_TXIRQ);
850  as3993ClrResponse();
851  }
852 #endif
853 #if EPCDEBUG
854  EPCLOG("-------------------------------\n");
855  EPCLOG("%hx Tags found", num_of_tags);
856  EPCLOG("\n");
857 #endif
858  return num_of_tags;
859 }
860 
862  , u8 maxtags
863  , u8 q
864  , BOOL (*cbContinueScanning)(void)
865  , BOOL singulate
866  , BOOL toggleSession
867  , s8 (*followTagCommand)(Tag *tag)
868  )
869 {
870  u16 num_of_tags = 0;
871 
872  u16 slot_count;
873  u8 i = 0;
874  u8 cmd = AS3993_CMD_QUERY;
875  u8 followCmd = 0;
876  u8 autoAck;
877 
878 #if !RUN_ON_AS3980
879  u16 collisions = 0;
880  BOOL goOn = 1;
881 
882  if (toggleSession)
883  followCmd = AS3993_CMD_QUERYREP;
884 #endif
885 
886  EPCLOG("Searching for Tags with autoACK, maxtags=%hhd, q=%hhd\n",maxtags, q);
887  EPCLOG("-------------------------------\n");
888 
889  if (followTagCommand != NULL)
890  {
891  followCmd = 0; //no follow Command
892  singulate = 1; // not fast
893  }
895  as3993ContinuousRead(AS3993_REG_IRQSTATUS1, 2, &buf_[0]); // ensure that IRQ bits are reset
896  as3993ClrResponse();
897 
898  //configure autoACK mode
899  autoAck = as3993SingleRead(AS3993_REG_PROTOCOLCTRL);
900  autoAck &= ~0x30;
901  if (singulate)
902  autoAck |= 0x20;
903  else
904  autoAck |= 0x10;
905  as3993SingleWrite(AS3993_REG_PROTOCOLCTRL, autoAck);
906 
907  for (i=0; i < maxtags; i++) /*Reseting the TAGLIST */
908  {
909  tags_[i].rn16[0] = 0;
910  tags_[i].rn16[1] = 0;
911  tags_[i].epclen=0;
912  }
913 
914  slot_count = 1UL<<q; /*get the maximum slot_count */
915 
916 #if RUN_ON_AS3980
917 
918  if (gen2SlotAutoAck(tags_+num_of_tags, cmd, q, !singulate, followCmd) == 1)
919  {
920  if (followTagCommand != NULL)
921  {
922  followTagCommand(tags_+num_of_tags);
923  }
924  num_of_tags++;
925  }
926 #else
927  do
928  {
929  if (num_of_tags >= maxtags)
930  {/* ERROR it is not possible to store more than maxtags Tags */
931  break;
932  }
933  slot_count--;
934  switch (gen2SlotAutoAck(tags_+num_of_tags, cmd, q, !singulate, followCmd))
935  {
936  case -1:
937  //EPCLOG("collision\n");
938  collisions++;
939  cmd = AS3993_CMD_QUERYREP;
940  break;
941  case 1:
942 
943  if (followCmd)
944  cmd = 0;
945  else
946  cmd = AS3993_CMD_QUERYREP;
947  if (followTagCommand != NULL)
948  {
949  followTagCommand(tags_+num_of_tags);
950  cmd = AS3993_CMD_QUERYREP;
951  }
952  num_of_tags++;
953  break;
954  case 0:
955  //EPCLOG("NO EPC response -> empty Slot\n");
956  cmd = AS3993_CMD_QUERYREP;
957  break;
958  default:
959  break;
960  }
961  goOn = cbContinueScanning();
962  } while (slot_count && goOn );
963 #endif
964  //unset autoACK mode again
965  autoAck = as3993SingleRead(AS3993_REG_PROTOCOLCTRL);
966  autoAck &= ~0x30;
967  as3993SingleWrite(AS3993_REG_PROTOCOLCTRL, autoAck);
968 
969  // If a tag is found in the last slot of an inventory round, follow Command QueryRep will be executed.
970  // Add some time to send this command to the tag over the field.
971  // If function will be left to early and field will be switched off the tag will not invert the inventoried flag.
972  // Problem especially for S2 and S3.
973  // If there was a follow Tag Command a Query Rep. has to be sent to invert the session flag.
974 #if RUN_ON_AS3993
975  if (followTagCommand == NULL)
976  {
977  delay_us(150);
978  }
979  else
980  {
981  as3993SingleCommand(AS3993_CMD_QUERYREP);
982  as3993WaitForResponse(RESP_TXIRQ);
983  as3993ClrResponse();
984  }
985 #endif
986 #if EPCDEBUG
987  EPCLOG("-------------------------------\n");
988  EPCLOG("%hx Tags found", num_of_tags);
989  EPCLOG("\n");
990 #endif
991  return num_of_tags;
992 }
993 
994 void gen2Configure(const struct gen2Config *config)
995 {
996  /* depending on link frequency setting adjust */
997  /* registers 01, 02, 03, 04, 05, 06, 07, 08 and 09 */
998  u8 reg[9];
999  u8 session = config->session;
1000  gen2IntConfig.DR = 1;
1001  gen2IntConfig.config = *config;
1002  if (session > GEN2_IINV_S3)
1003  session = GEN2_IINV_S0; /* limit SL and invalid settings */
1004  if (gen2IntConfig.config.miller == GEN2_COD_FM0 || gen2IntConfig.config.miller == GEN2_COD_MILLER2)
1005  gen2IntConfig.config.trext = TREXT_ON;
1006 
1007  switch (config->linkFreq) {
1008  case GEN2_LF_640: /* 640kHz */
1009  reg[0] = 0x20; /* AS3993_REG_TXOPTIONS */
1010  reg[1] = 0xF0; /* AS3993_REG_RXOPTIONS */
1011  reg[2] = 0x01; /* AS3993_REG_TRCALHIGH */
1012  reg[3] = 0x4D; /* AS3993_REG_TRCALLOW */
1013  reg[4] = 0x03; /* AS3993_REG_AUTOACKTIMER */
1014  reg[5] = 0x02; /* AS3993_REG_RXNORESPONSEWAITTIME */
1015  if (gen2IntConfig.config.tari == TARI_25)
1016  reg[6] = 0x02; /* AS3993_REG_RXWAITTIME */
1017  else if (gen2IntConfig.config.tari == TARI_625)
1018  reg[6] = 0x02; /* AS3993_REG_RXWAITTIME */
1019  else
1020  reg[6] = 0x01; /* AS3993_REG_RXWAITTIME */
1021 
1022  if (gen2IntConfig.config.miller > GEN2_COD_MILLER2)
1023  reg[7] = 0x04; /* AS3993_REG_RXFILTER */
1024  else
1025  reg[7] = 0x07; /* AS3993_REG_RXFILTER */
1026  break;
1027  case GEN2_LF_320: /* 320kHz */
1028  reg[0] = 0x20;
1029  reg[1] = 0xC0;
1030  if (gen2IntConfig.config.tari == TARI_625) /* if Tari = 6.25us */
1031  { /* TRcal = 25us */
1032  gen2IntConfig.DR = 0;
1033  reg[2] = 0x00;
1034  reg[3] = 0xFA;
1035  } else
1036  { /* TRcal = 66.7us */
1037  reg[2] = 0x02;
1038  reg[3] = 0x9B;
1039  }
1040  reg[4] = 0x04;
1041  reg[5] = 0x03;
1042  if (gen2IntConfig.config.tari == TARI_25)
1043  reg[6] = 0x05;
1044  else if (gen2IntConfig.config.tari == TARI_125)
1045  reg[6] = 0x05;
1046  else
1047  reg[6] = 0x04;
1048 
1049  if (gen2IntConfig.config.miller > GEN2_COD_MILLER2)
1050  reg[7] = 0x24; /* AS3993_REG_RXFILTER */
1051  else
1052  reg[7] = 0x27; /* AS3993_REG_RXFILTER */
1053  break;
1054  case GEN2_LF_256: /* 256kHz */
1055  reg[0] = 0x20;
1056  reg[1] = 0x90;
1057  if (gen2IntConfig.config.tari == TARI_625) /* Tari = 6.25us */
1058  { /* TRcal = 31.3us */
1059  gen2IntConfig.DR = 0;
1060  reg[2] = 0x01;
1061  reg[3] = 0x39;
1062  }
1063  else /* Tari = 25us or 12.5us */
1064  { /* TRcal = 83.3us */
1065  reg[2] = 0x03;
1066  reg[3] = 0x41;
1067  }
1068  reg[4] = 0x05;
1069  reg[5] = 0x05;
1070  if (gen2IntConfig.config.tari == TARI_25)
1071  reg[6] = 0x0B;
1072  else
1073  reg[6] = 0x05;
1074 
1075  if (gen2IntConfig.config.miller > GEN2_COD_MILLER2)
1076  reg[7] = 0x34; /* AS3993_REG_RXFILTER */
1077  else if((gen2IntConfig.config.miller == GEN2_COD_MILLER2) && (gen2IntConfig.config.trext == TREXT_ON))
1078  reg[7] = 0x27; /* AS3993_REG_RXFILTER */
1079  else
1080  reg[7] = 0x37; /* AS3993_REG_RXFILTER */
1081  break;
1082  case GEN2_LF_213: /* 213.3kHz */
1083  reg[0] = 0x20;
1084  reg[1] = 0x80;
1085  if (gen2IntConfig.config.tari == TARI_625) /* Tari = 6.25us */
1086  { /* TRcal = 37.5us */
1087  gen2IntConfig.DR = 0;
1088  reg[2] = 0x01;
1089  reg[3] = 0x77;
1090  }
1091  else
1092  { /* TRcal = 100us */
1093  reg[2] = 0x03;
1094  reg[3] = 0xE8;
1095  }
1096  reg[4] = 0x06;
1097  reg[5] = 0x05;
1098  if (gen2IntConfig.config.tari == TARI_25)
1099  reg[6] = 0x0B;
1100  else
1101  reg[6] = 0x06;
1102 
1103  if (gen2IntConfig.config.miller > GEN2_COD_MILLER2)
1104  reg[7] = 0x34; /* AS3993_REG_RXFILTER */
1105  else
1106  reg[7] = 0x37; /* AS3993_REG_RXFILTER */
1107  break;
1108  case GEN2_LF_160: /* 160kHz */
1109  reg[0] = 0x20;
1110  reg[1] = 0x60;
1111  if (gen2IntConfig.config.tari == TARI_125) /* Tari = 12.5us */
1112  { /* TRcal = 50us */
1113  gen2IntConfig.DR = 0;
1114  reg[2] = 0x01;
1115  reg[3] = 0xF4;
1116  }
1117  else
1118  { /* TRcal = 1333.3us */
1119  reg[2] = 0x05;
1120  reg[3] = 0x35;
1121  }
1122  reg[4] = 0x0A;
1123  reg[5] = 0x05;
1124  if (gen2IntConfig.config.tari == TARI_25)
1125  reg[6] = 0x0B;
1126  if (gen2IntConfig.config.tari == TARI_125)
1127  reg[6] = 0x09;
1128  else
1129  reg[6] = 0x08;
1130 
1131  if (gen2IntConfig.config.miller == GEN2_COD_FM0)
1132  reg[7] = 0x90; /* AS3993_REG_RXFILTER */
1133  else if((gen2IntConfig.config.miller == GEN2_COD_MILLER2) && (gen2IntConfig.config.trext == TREXT_ON))
1134  reg[7] = 0x27; /* AS3993_REG_RXFILTER */
1135  else
1136  reg[7] = 0x3F; /* AS3993_REG_RXFILTER */
1137  break;
1138  case GEN2_LF_40: /* 40kHz */
1139  reg[0] = 0x30; /* AS3993_REG_TXOPTIONS */
1140  reg[1] = 0x00; /* AS3993_REG_RXOPTIONS */
1141  reg[2] = 0x07; /* AS3993_REG_TRCALHIGH */
1142  reg[3] = 0xD0; /* AS3993_REG_TRCALLOW */
1143  reg[4] = 0x3F; /* AS3993_REG_AUTOACKTIMER */
1144  reg[5] = 0x0C; /* AS3993_REG_RXNORESPONSEWAITTIME */
1145  reg[6] = 0x24; /* AS3993_REG_RXWAITTIME */
1146  reg[7] = 0xFF; /* AS3993_REG_RXFILTER */
1147  gen2IntConfig.DR = 0;
1148  break;
1149  default:
1150  return; /* use preset settings */
1151  }
1152  reg[0] |= gen2IntConfig.config.tari;
1153  reg[1] = (reg[1] & ~0x0F)
1154  | gen2IntConfig.config.miller
1155  | (gen2IntConfig.config.trext<<3);
1156 
1157  gen2IntConfig.no_resp_time = reg[5];
1158  /* Modify only the gen2 relevant settings */
1159  as3993ContinuousWrite(AS3993_REG_TXOPTIONS, reg+0, 8);
1160 
1161  reg[0] = as3993SingleRead(AS3993_REG_TXSETTING);
1162  reg[0] = (reg[0] & ~0x03) | gen2IntConfig.config.session;
1163  as3993SingleWrite(AS3993_REG_TXSETTING, reg[0]);
1164  reg[0] = as3993SingleRead(AS3993_REG_PROTOCOLCTRL);
1165  reg[0] = reg[0] & ~0x07;
1166  as3993SingleWrite(AS3993_REG_PROTOCOLCTRL, reg[0]);
1167 }
1168 
1169 void gen2Open(const struct gen2Config * config)
1170 {
1171  gen2Configure( config );
1172 }
1173 
1174 void gen2Close(void)
1175 {
1176 }
1177 
1178 struct gen2Config *getGen2IntConfig()
1179 {
1180  return &(gen2IntConfig.config);
1181 }
s8 as3993TxRxGen2Bytes(u8 cmd, u8 *txbuf, u16 txbits, u8 *rxbuf, u16 *rxbits, u8 norestime, u8 followCmd, u8 waitTxIrq)
Definition: as3993.c:1180
u8 rn16[2]
Definition: as3993_public.h:61
#define GEN2_LF_640
Definition: gen2.h:118
Declaration of low level functions provided by the as3993 series chips.
static s8 gen2SlotAutoAck(Tag *tag, u8 qCommand, u8 q, BOOL fast, u8 followCommand)
Definition: gen2.c:345
s8 gen2LockTag(Tag *tag, const u8 *mask_action, u8 *tag_reply)
Definition: gen2.c:485
void as3993WaitForResponse(u16 waitMask)
Definition: as3993.c:543
void insertBitStream(u8 *dest, u8 const *source, u8 len, u8 bitpos)
Definition: global.c:71
s8 as3993GetADC(void)
Definition: as3993.c:1116
#define EPC_SELECT
Definition: gen2.c:60
s8 gen2KillTag(Tag const *tag, u8 const *password, u8 rfu, u8 recom, u8 *tag_error)
Definition: gen2.c:519
unsigned gen2SearchForTags(Tag *tags_, u8 maxtags, u8 q, u8 addRounds, u8 queryAdjustUpTh, u8 queryAdjustDownTh, BOOL(*cbContinueScanning)(void), BOOL singulate, BOOL toggleSession, s8(*followTagCommand)(Tag *tag))
Definition: gen2.c:679
#define GEN2_COD_FM0
Definition: gen2.h:121
u8 epc[EPCLENGTH]
Definition: as3993_public.h:66
#define EPC_REQRN
Definition: gen2.c:64
This file provides platform (board) specific macros and declarations.
static u8 num_of_tags
unsigned gen2SearchForTagsAutoAck(Tag *tags_, u8 maxtags, u8 q, BOOL(*cbContinueScanning)(void), BOOL singulate, BOOL toggleSession, s8(*followTagCommand)(Tag *tag))
Definition: gen2.c:861
void gen2PrintTagInfo(Tag *tag, u8 epclen, u8 tagNr)
Definition: gen2.c:655
This file is the include file for the timer.c file.
#define TARI_625
Definition: gen2.h:131
#define CRCLENGTH
Definition: global.h:71
void as3993ContinuousWrite(u8 address, u8 *buf, s8 len)
Definition: as3993.c:492
void gen2Close(void)
Close a session.
Definition: gen2.c:1174
s8 gen2AccessTag(Tag const *tag, u8 const *password)
Definition: gen2.c:438
void gen2Configure(const struct gen2Config *config)
Set the link frequency.
Definition: gen2.c:994
static s8 gen2ReqRNHandleChar(u8 const *handle, u8 *dest_handle)
Definition: gen2.c:421
#define EPC_WRITE
Definition: gen2.c:68
#define EPC_LOCK
Definition: gen2.c:72
#define EPCLOG(...)
Definition: gen2.c:46
void as3993SingleWrite(u8 address, u8 value)
Definition: as3993.c:500
struct gen2Config * getGen2IntConfig()
Returns the Gen2 Configuration.
Definition: gen2.c:1178
s8 gen2QueryMeasureRSSI(u8 *agc, u8 *log_rssis, s8 *irssi, s8 *qrssi)
Perform a gen2 QUERY command and measure received signal strength.
Definition: gen2.c:205
void u32ToEbv(u32 value, u8 *ebv, u8 *len)
Definition: global.c:39
s8 gen2WriteWordToTag(Tag const *tag, u8 memBank, u32 wordPtr, u8 const *databuf, u8 *tag_error)
Definition: gen2.c:566
#define LOG(...)
Definition: logger.h:119
#define GEN2_LF_40
Definition: gen2.h:113
void gen2Select(struct gen2SelectParams *p)
Definition: gen2.c:142
#define GEN2_ERR_ACCESS
Definition: gen2.h:181
#define TARI_125
Definition: gen2.h:132
u8 pc[2]
Definition: as3993_public.h:64
void as3993AntennaPower(u8 on)
Definition: as3993.c:875
#define GEN2_IINV_S3
Definition: gen2.h:169
#define GEN2_IINV_S0
Definition: gen2.h:163
#define GEN2_LF_213
Definition: gen2.h:115
Configuration file for all AS99x firmware.
#define LOGDUMP(...)
Definition: logger.h:120
Tag tags_[MAXTAG]
#define GEN2_COD_MILLER2
Definition: gen2.h:122
void gen2Open(const struct gen2Config *config)
Open a session.
Definition: gen2.c:1169
void as3993SingleCommand(u8 command)
Definition: as3993.c:448
u8 as3993SingleRead(u8 address)
Definition: as3993.c:475
#define GEN2_ERR_REQRN
Definition: gen2.h:180
#define EPCLENGTH
Definition: global.h:65
serial output log declaration file
#define TARI_25
Definition: gen2.h:133
#define EPC_ACCESS
Definition: gen2.c:74
#define PCLENGTH
Definition: global.h:69
#define GEN2_LF_256
Definition: gen2.h:116
u8 handle[2]
Definition: as3993_public.h:70
#define GEN2_LF_160
Definition: gen2.h:114
#define GEN2_OK
Definition: gen2.h:179
#define EPCLOGDUMP(...)
Definition: gen2.c:47
#define EPC_READ
Definition: gen2.c:66
#define TREXT_ON
Definition: gen2.h:128
#define EPC_KILL
Definition: gen2.c:70
This file provides declarations for functions for the GEN2 aka ISO6c protocol.
static u8 buf_[8+EPCLENGTH+PCLENGTH+CRCLENGTH]
Definition: gen2.c:101
void as3993ContinuousRead(u8 address, s8 len, u8 *readbuf)
Definition: as3993.c:456
#define GEN2_LF_320
Definition: gen2.h:117
s8 gen2ReadFromTag(Tag *tag, u8 memBank, u32 wordPtr, u8 wordCount, u8 *destbuf)
Definition: gen2.c:611