RRG-Proxmark3/doc/md/em4x70/arbitrary_lf_em_commands.md
Henry Gabryjelski 21ad101ff5 Major update to EM4x70 support:
1. Rework how communications with tag occur.
    a. bitstream to be sent to the tag is now fully pre-generated.
    b. bits sent and received are logged with start / end times.

2. Support built-in `hw dbg` for controlling verbosity of debug output

The new bitstream generation and logging has exposed a surprising legacy behavior ... each of the command that sent additional data (beyond the command) were:
* inserting an extra RM zero bit
* force-enabling command parity is used

This was not expected.  However, this PR maintains the behavior of the existing code.

TODO: Root-cause why the third RM bit is needed.  Fix code to remove that hack.

TODO: change the arm/client interface to ONLY use arrays of bytes, with well-defined content endianness, to avoid this problem.
2025-03-16 01:05:55 -07:00

148 lines
4.7 KiB
Markdown

# arbitrary lf em commands
Goals:
1. Improved logging of `lf em` commands and responses
2. Greater certainty in command sequences
3. Easier testing of new commands
## Methodology
This is documenting the actual commands used by existing code. Phases include:
* Document the existing command sequences
* Document the existing logging APIs
* Define small set of timing-sensitive functions as abstractions
* Implement the abstractions
* Add logging
The goal is to improve logging and debugging, and allow easily testing new LF commands.
## EM4x70 (aka ID48, aka Megamos)
Only six command sequences currently used:
#define EM4X70_COMMAND_ID 0x01
#define EM4X70_COMMAND_UM1 0x02
#define EM4X70_COMMAND_AUTH 0x03
#define EM4X70_COMMAND_PIN 0x04
#define EM4X70_COMMAND_WRITE 0x05
#define EM4X70_COMMAND_UM2 0x07
### ID Command
Wait for `LIW` (listen window), and start transmission at next `LIW`:
source | bits | comment
----------|---------|---------
tag | LIW | listen window sync
reader | `0b00` | RM
reader | `0b001` | CMD
reader | `0b1` | command parity bit
tag | HEADER | HEADER (0b1111'1111'1111'0000)
tag | 32-bits | ID (D31..D0)
tag | LIW | tag reverts to be ready for next command
### UM1 Command
source | bits | comment
----------|---------|---------
tag | LIW | listen window
reader | `0b00` | RM
reader | `0b010` | CMD
reader | `0b1` | command parity bit
tag | 16-bits | HEADER
tag | 32-bits | UM1 data
tag | LIW | tag reverts to be ready for next command
### UM2 Command
source | bits | comment
----------|---------|---------
tag | LIW | listen window
reader | `0b00` | RM
reader | `0b111` | CMD
reader | `0b1` | command parity bit
tag | 16-bits | HEADER
tag | 64-bits | UM2 data
tag | LIW | tag reverts to be ready for next command
### Auth Command
source | bits | comment
----------|---------|---------
tag | LIW | listen window
reader | `0b00` | RM
reader | `0b011` | CMD
reader | `0b0` | command parity bit
reader | 56-bits | RN
reader | 7-bits | Tdiv == 0b0000000 (always zero)
reader | 28-bits | f(RN)
tag | 16-bits | HEADER
tag | 20-bits | g(RN)
tag | LIW | tag reverts to be ready for next command
### Write Word
source | bits | comment
----------|---------|---------
tag | LIW | listen window
reader | `0b00` | RM
reader | `0b101` | CMD
reader | `0b0` | command parity bit
reader | 4-bits | address/block to write
reader | 1-bit | address/block parity bit
reader | 25-bits | 5x5 data w/ row and column parity
tag | ACK | Wait (TWA) for ACK ... time to wait before searching for ACK
tag | ACK | Wait (WEE) for ACK ... time to wait before searching for ACK
tag | LIW | tag reverts to be ready for next command
### PIN Command
source | bits | comment
----------|---------|---------
tag | LIW | listen window
reader | `0b00` | RM
reader | `0b100` | CMD
reader | `0b1` | command parity bit
reader | 32-bits | ID of the tag
reader | 32-bits | PIN
tag | ACK | Wait (TWALB) for ACK ... time to wait before searching for ACK
tag | HEADER | DELAYED (TWEE) header ... time to wait before searching for header
tag | 32-bits | ID of the tag
tag | LIW | tag reverts to be ready for next command
### Abstraction required
Possible items to abstract:
* bits to send: quantity of bits to be sent + storage containing those bits
* bits to receive: expected bits to receive + storage to receive those bits
* LIW: special-case handling to synchronize next command
* ACK: special-case handling to wait for ACK
* HEADER: special-case handling to wait for HEADER
* DELAY: ticks to delay before processing next item
Special handling required for:
* `HEADER` --> 12-bits of zero, 4-bits of one. Consider a timeout: if tag disappears, no pulse found, while sometimes expect long time before HEADER appears (as in SEND_PIN). Read of header may miss the first few bits during transition, so need to special-case handling of this detection.
* `LIW` --> Timing-sensitive, syncs reader with tag ... reader must send during 32 period where chip's modulator is ON.
* `ACK` --> This is currently a time-to-delay.
Should this be a maximum time to wait for ACK?
Currently, could sit waiting for long time
if no tag present, as `check_ack()` has no timeout.
```C
WaitTicks(EM4X70_T_TAG_TWA);
if (check_ack())
WaitTicks(EM4X70_T_TAG_WEE);
if (check_ack())
return PM3_SUCCESS;
```