diff options
author | (no author) <(no author)@6dc7ffe9-61d6-0310-9af1-9938baff3ed1> | 2006-08-23 20:17:30 +0000 |
---|---|---|
committer | (no author) <(no author)@6dc7ffe9-61d6-0310-9af1-9938baff3ed1> | 2006-08-23 20:17:30 +0000 |
commit | 548ec55ec2a4b3c8e5b00081beacb71ab277ee13 (patch) | |
tree | c22587d75a687287dd7e99fe8772ac82c216077a | |
parent | 0ba41a67844085561faf8b58decc6b32b375c5bb (diff) |
some initial code for PICC side
git-svn-id: https://svn.openpcd.org:2342/trunk@118 6dc7ffe9-61d6-0310-9af1-9938baff3ed1
-rw-r--r-- | openpcd/firmware/src/picc/decoder.c | 62 | ||||
-rw-r--r-- | openpcd/firmware/src/picc/decoder.h | 32 | ||||
-rw-r--r-- | openpcd/firmware/src/picc/decoder_miller.c | 111 | ||||
-rw-r--r-- | openpcd/firmware/src/picc/decoder_nrzl.c | 89 | ||||
-rw-r--r-- | openpcd/firmware/src/picc/iso14443a_manchester.c | 106 | ||||
-rw-r--r-- | openpcd/firmware/src/picc/piccsim.h | 23 |
6 files changed, 423 insertions, 0 deletions
diff --git a/openpcd/firmware/src/picc/decoder.c b/openpcd/firmware/src/picc/decoder.c new file mode 100644 index 0000000..2ca051f --- /dev/null +++ b/openpcd/firmware/src/picc/decoder.c @@ -0,0 +1,62 @@ +/* Decoder Core for OpenPCD / OpenPICC + * (C) 2006 by Harald Welte <hwelte@hmw-consulting.de> + */ + +#include <sys/types.h> +#include "decoder.h" + +static struct decoder_algo *decoder_algo[DECODER_NUM_ALGOS]; + +static int get_next_data(struct decoder_state *st, u_int8_t *data) +{ + u_int8_t parity_sample; + u_int32_t bytesample; + + bytesample = st->algo->get_next_bytesample(st, &parity_sample); + + return st->algo->decode_sample(bytesample, data); +} + +/* iterate over sample buffer (size N bytes) and decode data */ +int decoder_decode(u_int8_t algo, const char *sample_buf, + int sample_buf_size, char *data_buf) +{ + int ret; + struct decoder_state st; + + if (algo >= DECODER_NUM_ALGOS) + return -EINVAL; + + st.buf = sample_buf; + st.buf32 = (u_int32_t *) st.buf; + st.bit_ofs = 0; + st.algo = decoder_algo[algo]; + + for (i = 0; i < (sample_buf_size*8)/st.algo->bits_per_sampled_char; + i++) { + ret = get_next_data(&st, &data_buf[i]); + if (ret < 0) { + DEBUGPCR("decoder error %d at data byte %u", + ret, i); + return ret; + } + } + + return i+1; +} + +int decoder_register(int algo, struct decoder_algo *algo) +{ + if (algo >= DECODER_NUM_ALGOS) + return -EINVAL; + + decoder_algos[algo] = algo; + + return 0; +} + +int decoder_init(void) +{ + decoder_register(DECODER_MILLER, &miller_decoder); + decoder_register(DECODER_NRZL, &nrzl_decoder); +} diff --git a/openpcd/firmware/src/picc/decoder.h b/openpcd/firmware/src/picc/decoder.h new file mode 100644 index 0000000..950efd2 --- /dev/null +++ b/openpcd/firmware/src/picc/decoder.h @@ -0,0 +1,32 @@ +#ifndef _DECODER_H +#define _DECODER_H + +struct decoder_state; + +struct decoder_algo { + u_int8_t oversampling_rate; + u_int8_t bits_per_sampled_char; + u_int8_t bytesample_mask; + int (*decode_sample)(const u_int32_t sample, u_int8_t data); + u_int32_t (*get_next_bytesample)(struct decoder_state *st, u_int8_t *parity_sample); +}; + +struct decoder_state { + struct decoder_algo *algo; + u_int8_t bit_ofs; + const char *buf; + const u_int32_t *buf32; +}; + +extern int decoder_register(int algo, struct decoder_algo *algo); +extern int decoder_decode(u_int8_t algo, const char *sample_buf, + int sample_buf_size, char *data_buf); + +#define DECODER_MILLER 0 +#define DECODER_NRZL 1 +#define DECODER_NUM_ALGOS 2 + +extern struct decoder_algo nrzl_decoder; +extern struct decoder_algo miller_decoder; + +#endif diff --git a/openpcd/firmware/src/picc/decoder_miller.c b/openpcd/firmware/src/picc/decoder_miller.c new file mode 100644 index 0000000..4036511 --- /dev/null +++ b/openpcd/firmware/src/picc/decoder_miller.c @@ -0,0 +1,111 @@ +/* + * ISO14443A modified Miller decoder + * (C) 2006 by Harald Welte <hwelte@hmw-consulting.de> + * + * LSB First LSB hex + * Sequence X 0010 0100 0x4 + * Sequence Y 0000 0000 0x0 + * Sequence Z 1000 0001 0x1 + * + * Logic 1 Sequence X + * Logic 0 Sequence Y with two exceptions: + * - if there are more contiguous 0, Z used from second one + * - if the first bit after SOF is 0, sequence Z used for all contig 0's + * SOF Sequence Z + * EOF Logic 0 followed by Sequence Y + * + * cmd hex bits symbols hex (quad-sampled) + * + * REQA 0x26 S 0110010 E Z ZXXYZXY ZY 0x10410441 + * WUPA 0x52 S 0100101 E Z ZXYZXYX YY 0x04041041 + * + * SOF is 'eaten' by SSC start condition (Compare 0). Remaining bits are + * mirrored, e.g. samples for LSB of first byte are & 0xf + * + */ + +#include <sys/types.h> +#include "decoder.h" + + +#define OVERSAMPLING_RATE 4 + +/* definitions for four-times oversampling */ +#define SEQ_X 0x4 +#define SEQ_Y 0x0 +#define SEQ_Z 0x1 + +/* decode a single sampled bit */ +static u_int8_t miller_decode_sampled_bit(u_int32_t sampled_bit) +{ + switch (sampled_bit) { + case SEQ_X: + return 1; + break; + case SEQ_Z: + case SEQ_Y: + return 0; + break; + default: + DEBUGP("unknown sequence sample `%x' ", bit_sample); + return 2; + break; + } +} + +/* decode a single 32bit data sample of an 8bit miller encoded word */ +static int miller_decode_sample(u_int32_t sample, u_int8_t *data) +{ + u_int8_t ret = 0; + int err, i; + + for (i = 0; i < sizeof(sample)/OVERSAMPLING_RATE; i++) { + u_int8_t bit = miller_decode_sampled_bit(sample & 0xf); + + if (bit == 1) + ret |= 1; + /* else do nothing since ret was initialized with 0 */ + + /* skip shifting in case of last data bit */ + if (i == sizeof(sample)/OVERSAMPLING_RATE) + break; + + sample = sample >> OVERSAMPLING_RATE; + ret = ret << 1; + } + + *data = ret; + + return ret; +} + +static u_int32_t get_next_bytesample(struct decoder_state *ms, + u_int8_t *parity_sample) +{ + u_int32_t ret = 0; + u_int8_t parity_sample; + + /* get remaining bits from the current word */ + ret = *(ms->buf32) >> ms->bit_ofs; + /* move to next word */ + ms->buf32++; + + /* if required, get remaining bits from next word */ + if (bit_ofs) + ret |= *(ms->buf32) << (32 - ms->bit_ofs); + + *parity_sample = (*(ms->buf32) >> ms->bit_ofs & 0xf); + + /* increment bit offset (modulo 32) */ + ms->bit_ofs = (ms->bit_ofs + OVERSAMPLING_RATE) % 32; + + return ret; +} + +static struct decoder_algo miller_decoder = { + .oversampling_rate = OVERSAMPLING_RATE, + .bits_per_sampled_char = 9 * OVERSAMPLING_RATE, + .bytesample_mask = 0xffffffff, + .decode_sample = &miller_decode_sample, + .get_next_bytesample = &get_next_bytesample, +}; diff --git a/openpcd/firmware/src/picc/decoder_nrzl.c b/openpcd/firmware/src/picc/decoder_nrzl.c new file mode 100644 index 0000000..bb297db --- /dev/null +++ b/openpcd/firmware/src/picc/decoder_nrzl.c @@ -0,0 +1,89 @@ +/* ISO 14443 B Rx (PCD->PICC) implementation + * (C) 2006 by Harald Welte <hwelte@hmw-consulting.de> + * + * speed(kbps) 106 212 424 848 + * etu 128/fc 64/fc 32/fc 16/fc + * etu(usec) 9.4 4.7 2.35 1.18 + * + * NRZ-L coding with logic level + * + * logic 1: carrier high field amplitude (no modulation) + * logic 0: carrier low field amplitude + * + * Character transmission format: + * start bit: logic 0 + * data: eight bits, lsb first + * stop bit logic 1 + * + * Frame Format: + * + * SOF char [EGT char, ...] EOF + * + * SOF: falling edge, 10..11 etu '0', rising edge in 1etu, 2..3etu '1' + * EGT: between 0 and 57uS + * EOF: falling edge, 10..11 etu '0', rising edge in 1etu + * + * + * Sampling + * - sample once per bit clock, exactly in the middle of it + * - synchronize CARRIER_DIV TC0 to first falling edge + * - Configure CARRIER_DIV RA compare (rising edge) to be at + * etu/2 carrier clocks. + * - problem: SOF 12..14etu length, therefore we cannot specify + * SOF as full start condition and then sample with 10bit + * frames :( + * + */ + +#include <sys/types.h> +#include "decoder.h" + +/* currently this code will only work with oversampling_rate == 1 */ +#define OVERSAMPLING_RATE 1 + +static u_int32_t get_next_bytesample(struct decoder_state *st, + u_int8_t *parity_sample) +{ + u_int32_t ret = 0; + u_int8_t bits_per_sampled_char = st->algo->bits_per_sampled_char; + u_int8_t bytesample_mask = st->algo->bytesample_mask; + + /* FIXME: shift start and stop bit into parity_sample and just + * return plain 8-bit data word */ + + /* first part of 10-databit bytesample */ + ret = (*(st->buf32) >> st->bit_ofs) & bytesample_mask; + + if (st->bit_ofs > 32 - bits_per_sampled_char) { + /* second half of 10-databit bytesample */ + st->buf32++; + ret |= (*(st->buf32) << (32 - st->bit_ofs)); + } + st->bit_ofs = (st->bit_ofs + bits_per_sampled_char) % 32; + + return ret & bytesample_mask; +} + +static int nrzl_decode_sample(const u_int32_t sample, u_int8_t data) +{ + *data = (sample >> 1) & 0xff; + + if (!(sample & 0x01)) { + DEBUGPCRF("invalid start bit 0!"); + return -EIO; + } + if (sample & 0x20) { + DEBUGPCRF("invalid stop bit 1!"); + return -EIO; + } + + return 0; +} + +static struct decoder_algo nrzl_decoder = { + .oversampling_rate = OVERSAMPLING_RATE, + .bits_per_sampled_char = 10 * OVERSAMPLING_RATE, + .bytesample_mask = 0x3ff; + .decode_sample = &nrzl_decode_sample, + .get_next_bytesample = &get_next_bytesample, +}; diff --git a/openpcd/firmware/src/picc/iso14443a_manchester.c b/openpcd/firmware/src/picc/iso14443a_manchester.c new file mode 100644 index 0000000..aca832c --- /dev/null +++ b/openpcd/firmware/src/picc/iso14443a_manchester.c @@ -0,0 +1,106 @@ +/* + * ISO14443A Manchester encoder + * (C) 2006 by Harald Welte <hwelte@hmw-consulting.de> + * + * Definitions for 106kBps, at sampling clock 1695kHz + * + * bit sample pattern for one bit cycle + * MSB first LSB first hex LSB first + * Sequence D 1010101000000000 0000000001010101 0x0055 + * Sequence E 0000000010101010 0101010100000000 0x5500 + * Sequence F 1010101010101010 0101010101010101 0x5555 + * + * Logic 1 Sequence D + * Logic 0 Sequence E + * SOF Sequence D + * EOF Sequence F + * + * 212/424/848kBps: BPSK. + * + * SOF: 32 subcarrier clocks + bit '0' + * + * SOF: hex LSB first: 0x55555555 55555555 + bit '0' + * + * EOF: even parity of last byte (!) + * + */ + +#define MANCHESTER_SEQ_D 0x0055 +#define MANCHESTER_SEQ_E 0x5500 +#define MANCHESTER_SEQ_F 0x5555 + +static u_int32_t manchester_sample_size(u_int8_t frame_bytelen) +{ + /* 16 bits (2 bytes) per bit => 16 bytes samples per data byte, + * plus 16bit (2 bytes) parity per data byte + * plus 16bit (2 bytes) SOF plus 16bit (2 bytes) EOF */ + return (frame_bytelen*18) + 2 + 2; + + /* this results in a maximum samples-per-frame size of 4612 bytes + * for a 256byte frame */ +} + +struct manch_enc_state { + const char *data; + char *samples; + u_int16_t *samples16; +}; + +static void manchester_enc_byte(struct manch_enc_state *mencs, u_int8_t data) +{ + int i; + u_int8_t sum_1 = 0; + + /* append 8 sample blobs, one for each bit */ + for (i = 0; i < 8; i++) { + if (data & (1 << i)) { + *(mencs->samples16) = MANCHESTER_SEQ_D; + sum_1++; + } else { + *(mencs->samples16) = MANCHESTER_SEQ_E; + } + mencs->samples16++ + } + /* append odd parity */ + if (sum_1 & 0x01) + *(mencs->samples16) = MANCHESTER_SEQ_E; + else + *(mencs->samples16) = MANCHESTER_SEQ_D; + mencs->samples16++ +} + +int manchester_encode(char *sample_buf, u_int16_t sample_buf_len, + const char *data, u_int8_t data_len) +{ + int i, enc_size; + struct manch_enc_state mencs + + enc_size = manchester_sample_size(data_len); + + if (sample_buf_len < enc_size) + return -EINVAL; + + /* SOF */ + *(mencs.samples16++) = MANCHESTER_SEQ_D; + + for (i = 0; i < data_len; i++) + manchester_enc_byte(mencs, data[i]); + + /* EOF */ + *(mencs.samples16++) = MANCHESTER_SEQ_F; + + return enc_size; +} + +#define BPSK_SPEED_212 + + +static u_int32_t bpsk_sample_size(u_int8_t frame_bytelen) + +int bpsk_encode(char *sample_buf, u_int16_t sample_buf_len, + const char *data, u_int8_t data_len) +{ + /* burst of 32 sub carrier cycles */ + memset(sample_buf, 0x55, 8); + +} diff --git a/openpcd/firmware/src/picc/piccsim.h b/openpcd/firmware/src/picc/piccsim.h new file mode 100644 index 0000000..34c7bf0 --- /dev/null +++ b/openpcd/firmware/src/picc/piccsim.h @@ -0,0 +1,23 @@ + +#include <librfdi/rfid_layer2_iso14443a.h> + +struct piccsim_state { + enum rfid_layer2_id l2prot; + unsigned char uid[10]; + u_int8_t uid_len; + union { + struct { + enum iso14443a_state state; + enum iso14443a_level level; + u_int32_t flags; + } iso14443a; + struct { + } iso14443b; + } l2; + + union { + u_int32_t flags; + } proto; +} + +#define PICCSIM_PROT_F_AUTO_WTX 0x01 |