The tags and networking protocol used in the simulator are based on the EPC Class-1 Generation-2 UHF RFID Protocol specification. The simulator models only the link layer aspects of the spec, ignoring the physical layer except through the setting of various delay values. Differences from the spec are explained in the sections that follow.
The only non-volatile storage holds an electronic product code (EPC) that is unique to the tag. The EPC is held in a bit addressable memory (a Java BitMemory object). The default configuration makes it 64 bits long, but is easily changed by redefiningEPCLen
incomponent.RFIDTag
. The EPC is the only thing in the simulated "Memory", using the terms from the specificationTags have (only) four other internal values:
One implication of this is that there is only a single "session" (using terminology from the spec) implemented in the simulated system.
- Current state
Tags can be in one of four states: Ready, Arbitrate, Reply, and Acknowledged. Their state is not directly accessible to the reader. (There is no directive that will cause a tag to send its state to the reader.)
- Selected Bit (SL)
A single bit that can be set or flipped by the reader using a Select directive, and that is used as a guard in the execution of Query, QueryAdjust, and QueryRep directives.
- Inventoried Bit (INV)
A single bit, also assignable by the reader using Select and used as a guard for query directives. It is flipped by the tag itself if it receives a Query, QueryAdjust, or QueryRep directive while in the Acknowledged state.
- 16-bit random
A 16-bit random number generated by the tag, accessible to the reader only through the RN16/ACK frame exchange.
Only forms of the Select, Query, QueryAdj, QueryRep, and ACK frames from the reader to the tags have been implemented. Fields in the spec's frames that have no meaning in the simulator (e.g., those pertaining to sessions) have been omitted. Other fields have had their lengths shortened, due to having fewer possible values in the simulator than the spec. The variable length frame type field of the spec has been replaced with a constant length field, to simplify all of our lives (but, okay, especially mine).Specific frame formats are given in the javadoc for each concrete frame class in the simulator code.
Tags also send frames back to the reader. These frames have no header, and so no frame type field. The reader knows the type because at most one type is a valid response to whatever frame the reader just sent (and tags send frames only in response to something the reader sent).
The two responses implemented are RN16 (response to any of the query directives) and EPC (response to an ACK).
The spec carefully applies CRCs to frames. Some have it, some don't. Two different length CRCs are used (5- and 16-bit).The default configuration of the simulator applies CRC-16 codes to all frames, in both directions. It assumes that these provide 100% reliable error detection.
The one option you have for changing "the hardware" is the per-frame-type choice of whether or not to transmit a CRC.
You can turn off the CRC field for any frame by setting a static class variable to false. (For example, for the ACK frame you set
frame.AckFrame.ackFrameHasCRC
to false by modifying its initialization inAckFrame.java
.) Turning CRC's off makes frames shorter, so they take less time to deliver.When a frame contains a CRC, the simulator will signal the corruption of any bit (due to the BER) to the receiver, by returning
true
from theisCorrupted()
method of frame. When the frame dosn't contain CRCs, the simulator randomly flips its bits (with probability determined by the BER). Whether or not this can be detected is context specific. (For example, if a frame type bit is flipped and the frame type is undefined, the tags will notice this and do nothing.) Additionally, in some cases an unnoticed flipped bit is not a problem, while in others it is. That affects how inclined you might be to attach CRCs to specific types of frames.
The simulation infrastructure callsRFIDReader.inventory()
, which then sits in a loop until an exception is thrown indicating that the time allowed to inventory the tags has expired. Pretty much all your code goes there (replacing what is already there rather than modifying it, most likely). The only exception that comes to mind right now has to do with the optional and trivial change required to drop CRC fields in some frame types.Your code should sit in a loop sending frames and, optionally, examining any reply. It sends the frame using a
component.RFIDChannel
, which iterates over the tags, randomly corrupted the originally sent frame as it hands it to each tag. Each tag makes whatever state transition is required and optionally hands a reply frame back to the channel. The channel collects all replies. If there are none, it returnsnull
to theRFIDReader
that invoked it. If there is one, it applies the BER to it. If the reply frame carries a CRC, it is marked as corrupted. It then hands the reply back to theRFIDReader
. Finally, if there is more than one reply, the channel hands aCollisionFrame
back to the reader.CollisionFrame
s are always marked as corrupted, so the reader 100% reliably detects collisions.
RFIDChannel
to run in debugging
mode by calling its setDebug()
method. In that mode
it prints a tiny bit of information for each frame put into the air
(in both directions). That can be a lot of information, and causes
an enormous slowdown in execution speed even when directed to a file,
but it's sometimes useful.
COLLISION
frame.
COLLISIONSZ
is the average number of frames involved in each
collision.
Finally, TIMEOUTS
is the average number of times the reader
was expecting a reply frame but didn't get anything back
(not even a collision).
Timeouts are somewhat cheap, as the time at which the first reply bit should
be coming back is tightly bounded by the spec. (They're shorter than
the time that would have been required to send back the reply frame,
for instance.)
You can either live with it being slow (being slow is a downside of using simulation, in general), or you can change the implementation to run faster, while still being correct. In particular, first take a random sample from the distribution of the number of corrupted bits, and if it's non-zero, pick that many bits in the frame to flip. That should be about 1/BER times faster than what is done now.