Introduction
An Impinj® Monza® 4E tag chip will backscatter only 96-bits of EPC data by default, although the chip supports the storage of up to 496-bits of data in its EPC memory bank. So how do you change the amount of EPC data that a Gen2 compliant RFID tag (Gen2 tag) backscatters during inventory?
The amount of data that a Gen2 tag backscatters during an inventory round is defined by the value of the EPC Length bit-field in the Protocol-control word (PC Bits, or Stored PC) contained in word 1 of the EPC memory region, no matter how much data can be stored in the EPC memory bank of a tag chip.
After describing the layout and function of the PC Bits word within a Gen2 RFID tag chip EPC memory bank, this document describes how to use the EPC Length field of the PC Bits word in an Impinj Monza Gen2 RFID tag chip to control how much data from the EPC memory region is backscattered during inventory. Based on the WriteEpc project that comes with the Impinj Octane SDK examples, this document describes how to read, modify and write the contents of the PC Bits word using the Impinj Octane SDK. A technique for storing “hidden” data in the EPC memory bank will also be described.
PC Bits - the Theory
Each Gen2 tag includes non-volatile memory broken up into four independently addressable regions:
- Reserved memory
- EPC memory
- Tag identifier (TID) memory
- User memory.
Each memory region is accessed in 16-bit chunks, or words, starting at word 0.
The PC Bits are included within the layout of the EPC memory region.
Layout of EPC Memory Region
Both the EPC data and the PC Bits are Stored in the tag EPC memory region, in addition to a 16-bit cyclic redundancy check (CRC-16) error detection code. As shown in the figure below, word 0 of the EPC memory region contains the CRC-16, word 1 contains the PC Bits, and the EPC data backscattered during the inventory process starts at word 2. The total number of words available to store EPC data is dependent on the actual tag chip used to make the Gen2 tag:
The PC Bits in word 1 are further subdivided into a number of bit fields:
The values of each of these bit fields can be interpreted using the following table:
Gen2 RFID tag EPC Memory Region Protocol Control word layout
EPC Length (L) | These bits contain a binary value indicating the number of words of EPC data that will be backscattered during inventory, no matter how many words of EPC data the tag chip supports; a value of 00000b means a zero-length EPC is backscattered, a value of 00110 means that a 6-word EPC is backscattered (typical default value), and a value of 11111b means a 31-word (496-bit) EPC is backscattered. NOTE:- if the XI bit has a value of 1b, then the maximum allowable value of this field is 11101b, meaning a 29-word (464-bit) EPC. |
User Memory Indicator bit (UMI) | This bit operates in 2 modes; fixed or computed. Fixed – fixed by the tag chip manufacturer; if the tag does not have User Memory then this bit is set to 0b, if the tag does support User Memory then this bit is set to 1b. Computed – computed by the tag chip both at power-up and when the first word of user memory is written to. Contains the logical OR of bits 03h – 07h in word 0 of User Memory; if the Tag does not have user memory allocated then the logical OR result is 0b. Monza chips with User Memory operate in computed mode. |
Extended Protocol Control Word 1 Present Indicator bit (XI) | This bit identifies whether an Extended Protocol Control Word 1 (XPC_W1) exists in word 21 of EPC Memory. If the Extended Protocol Control (XPC) is not supported by a tag chip, this bit is fixed to 0b by the tag chip manufacturer, as it is with Monza tags. If XPC is supported by a tag chip, then the value of the XI bit is determined by the tag at power up and when the value of XPC_W1 is changed. When T = 0b, contains the logical OR of bits 00h - 07h or 00h - 08 h (manufacturer’s choice) of XPC_W1. When T=1b, contains the logical OR of all of the bits of XPC_W1. |
Numering System Identifier Toggle bit (T) | This bit identifies whether the data in the EPC data area conforms to a GS1 EPCGlobal™ (set to 0b) or an ISO/IEC 15961 coding scheme (set to 1b). The actual coding scheme is identified in the RFU or AFI bit field. |
Reserved for Future Use, or Application Family Identifier (RFU or AFI) | These bits are set to 0b when T is set to 0b. Otherwise, when T is set to 1b, it is the responsibility of the encoder application to assign a header value to these bits to identify the application family to which the EPC data applies, per the following table. |
Bit Field
|
Meaning
|
---|
PC Bits - the Practice
For Monza specific tag chips, in order to change the number of EPC words that are backscattered during inventory, the encoder application needs to modify the EPC Length (L) bit field of the PC Bits. As not all of options controlled by the PC Bits word are actually writable, this needs to be done as a read-modify-write operation so that only the value of L is modified. In addition, when writing to the PC Bits word, no other words in EPC memory can be accessed at the same time. This means that when new EPC data requires a change in the PC Bits, two tag operations are required; one to write the new EPC data, and one to update the PC Bits word.
The practice of updating the value of L in the PC Bits with the Octane SDK 3.2 involves the following simple steps:
- Obtaining the EPC and PC Bits during tag inventory
- Write the new EPC to the tag
- If the new EPC is a different size, update the PC Bits on the tag.
Obtaining the Current PC Bits During Inventory
This is achieved simply by setting the IncludePCBits flag in the reader settings report configuration, as demonstrated in the following example code:
Settings settings = reader.QueryDefaultSettings(); // Tell the reader to include the Protocol Control // bits in all tag reports. We will need to modify // the PC bits if we change the length of the EPC. settings.Report.IncludePcBits = true; // Enable antenna #1. Disable all others. settings.Antennas.DisableAll(); settings.Antennas.GetAntenna(1).IsEnabled = true; // Apply the newly modified settings. reader.ApplySettings(settings);
Writing a new EPC to a tag using ProgramEpc()
The following is an example procedure, ProgramEpc(), that comes from the WriteEpc project that comes with the Impinj Octane SDK 3.2 examples. It serves as an excellent example of how to program a new EPC into a tag, changing the PC Bits EPC Length (L) field, if necessary. The parameter usage is as follows:
- currentEpc – a Hex String representation of the EPC currently stored on the tag, e.g. “AAAA BBBB CCCC DDDD EEEE FFFF”.
- currentPcBits – the value of the PCBits currently stored on the tag, e.g. 12288 (0x3000).
- newEpc – the new EPC to program into the tag.
NOTE:- The currentEpc and currentPcBits parameters are normally obtained from the tag inventory report when the IncludePCBitsreport flag is set. Within a tag inventory report, the results for each tag are contained within the Tag[] array, where both Epc and PcBits are data members for each individual tag object. The Epc data member is stored as a list of 16-bit ushort values, so when this data is passed to the ProgramEpc() procedure, the Epc value needs to be passed using the ToHexString() modifier, e.g. myTagData.ToHexString(). |
In the ProgramEpc() procedure below, the new EPC is programmed into the tag using the tag operation writeEpc. If there is a size difference between the old and new EPCs that requires a change to the PC Bits L field, then an additional tag operation writePc is created to perform this update. Note that the PcBits.AdjustPcBits() helper is used to modify only the EPC Length field of the original PC Bits data word. Both the writeEpc and writePc operations are then passed to the reader as a sequence so that both the EPC data and PC Bits updates are performed as individual tag operations.
static void ProgramEpc(string currentEpc, ushort currentPcBits, string newEpc) { // Check that the specified EPCs are a valid length if ((currentEpc.Length % 4 != 0) || (newEpc.Length % 4 != 0)) throw new Exception("EPCs must be a multiple of 16 bits (4 hex chars)"); Console.WriteLine("Adding a write operation to change the EPC from :"); Console.WriteLine("{0} to {1}\n", currentEpc, newEpc); // Create a tag operation sequence. // You can add multiple read, write, lock, kill and QT // operations to this sequence. TagOpSequence seq = new TagOpSequence(); // Specify a target tag based on the EPC. seq.TargetTag.MemoryBank = MemoryBank.Epc; seq.TargetTag.BitPointer = BitPointers.Epc; seq.TargetTag.Data = currentEpc; // If you are using Monza 4, Monza 5 or Monza X tag chips, // uncomment these two lines. This enables 32-bit block writes // which significantly improves write performance. //seq.BlockWriteEnabled = true; //seq.BlockWriteWordCount = 2; // Create a tag write operation to change the EPC. TagWriteOp writeEpc = new TagWriteOp(); // Set an ID so we can tell when this operation has executed. writeEpc.Id = EPC_OP_ID; // Write to EPC memory writeEpc.MemoryBank = MemoryBank.Epc; // Specify the new EPC data writeEpc.Data = TagData.FromHexString(newEpc); // Starting writing at word 2 (word 0 = CRC, word 1 = PC bits) writeEpc.WordPointer = WordPointers.Epc; // Add this tag write op to the tag operation sequence. seq.Ops.Add(writeEpc); // Is the new EPC a different length than the current EPC? if (currentEpc.Length != newEpc.Length) { // We need adjust the PC bits and write them back to the // tag because the length of the EPC has changed. // Adjust the PC bits (4 hex characters per word). ushort newEpcLenWords = (ushort)(newEpc.Length / 4); ushort newPcBits = PcBits.AdjustPcBits(currentPcBits, newEpcLenWords); Console.WriteLine("Adding a write operation to change the PC bits from :"); Console.WriteLine("{0} to {1}\n", currentPcBits.ToString("X4"), newPcBits.ToString("X4")); TagWriteOp writePc = new TagWriteOp(); writePc.Id = PC_BITS_OP_ID; // The PC bits are in the EPC memory bank. writePc.MemoryBank = MemoryBank.Epc; // Specify the data to write (the modified PC bits). writePc.Data = TagData.FromWord(newPcBits); // Start writing at the start of the PC bits. writePc.WordPointer = WordPointers.PcBits; // Add this tag write op to the tag operation sequence. seq.Ops.Add(writePc); } // Add the tag operation sequence to the reader. // The reader supports multiple sequences. reader.AddOpSequence(seq); }
Storing out-of-band data in EPC memory
The amount of EPC data that a tag backscatters during inventory does not always reflect the amount of data that can be stored in the EPC memory bank. If the number of words that can be stored in the EPC data bank is larger than the number that the PC Bits word states will be backscattered, then it is possible to store extra out-of-band, or "hidden" data in the EPC memory space. For example, if you are using a tag based on a Monza 4E tag chip that supports the maximum possible EPC memory size, or 496 bits, and that the tag is currently configured to backscatter a 96-bit EPC, this leaves a possible 400 extra bits to store data in, from words 6 to 31. So how does one write data (e.g. “1234 5678 98AB CDEF”) and then retrieve it from this extra memory? Writing this data is achieved using an explicit write operation into the EPC memory region, such as in the following example code:
// Create a tag operation sequence. // You can add multiple read, write, lock, kill and QT // operations to this sequence. TagOpSequence seq = new TagOpSequence(); // Specify a target tag based on the EPC. seq.TargetTag.MemoryBank = MemoryBank.Epc; seq.TargetTag.BitPointer = BitPointers.Epc; seq.TargetTag.Data = currentEpc; // If you are using Monza 4, Monza 5 or Monza X tag chips, // uncomment these two lines. This enables 32-bit block writes // which significantly improves write performance. //seq.BlockWriteEnabled = true; //seq.BlockWriteWordCount = 2; // Create a tag write operation to change the EPC. TagWriteOp writeEpc = new TagWriteOp(); // Set an ID so we can tell when this operation has executed. writeEpc.Id = EPC_OP_ID; // Write to EPC memory writeEpc.MemoryBank = MemoryBank.Epc; // Specify the new EPC data writeEpc.Data = TagData.FromHexString(“1234 5678 98AB CDEF”); // Starting writing at word 6 writeEpc.WordPointer = 6; // Add this tag write op to the tag operation sequence. seq.Ops.Add(writeEpc); // Add the tag operation sequence to the reader. // The reader supports multiple sequences. reader.AddOpSequence(seq);
Similarly, reading this data can also be achieved using an explicit read operation to read data in the EPC memory region, such as in the following example code:
// Create a tag operation sequence. // You can add multiple read, write, lock, kill and QT // operations to this sequence. TagOpSequence seq = new TagOpSequence(); // Create a tag read operation. TagReadOp readOp = new TagReadOp(); // Read from EPC memory readOp.MemoryBank = MemoryBank.Epc; // Read four (16-bit) words readOp.WordCount = 4; // Starting at word 6 readOp.WordPointer = 6; // Add this tag read op to the tag operation sequence. seq.Ops.Add(readOp); // Add the tag operation sequence to the reader. // The reader supports multiple sequences. reader.AddOpSequence(seq);
By using explicit write and read operations to the words of the EPC memory region that are not included in the backscattered EPC data during inventory, it is possible to store extra “hidden” data in the EPC memory region.
Comments
Article is closed for comments.