summaryrefslogtreecommitdiff
path: root/openpicc/application/iso14443a_manchester.c
blob: 9822c60f53ca966fc4dece6a4222dc56fc549439 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
/* ISO14443A Manchester encoder for OpenPICC
 * (C) 2006 by Harald Welte <hwelte@hmw-consulting.de>
 * (C) 2007 by Henryk Plötz <henryk@ploetzli.ch>
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by 
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 */


/*
 * 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	0000000000000000	0000000000000000	0x0000
 *
 * 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	0x0000

#include <errno.h>
#include <string.h>
#include "openpicc.h"
#include "iso14443_layer3a.h"
#include "iso14443a_manchester.h"

enum parity {
	PARITY_NONE, /* Don't add a parity bit */
	ODD_PARITY, EVEN_PARITY, /* Calculate parity */
	PARITY_0, PARITY_1 /* Set fixed parity */
};

static inline void manchester_enc_byte(u_int16_t **s16, const u_int8_t data, const enum parity parity)
{
	int i;
	u_int8_t sum_1 = 0;
	u_int16_t *samples16 = *s16;

	/* append 8 sample blobs, one for each bit */
	for (i = 0; i < 8; i++) {
		if (data & (1 << i)) {
			*(samples16) = MANCHESTER_SEQ_D;
			sum_1++;
		} else {
			*(samples16) = MANCHESTER_SEQ_E;
		}
		samples16++;
	}
	if(parity != PARITY_NONE) {
		/* Append parity */
		u_int8_t par=0;
		switch(parity) {
			case PARITY_NONE: break;
			case PARITY_0: par = 0; break;
			case PARITY_1: par = 1; break;
			case ODD_PARITY:  par = (sum_1 & 0x1) ? 0 : 1; break;
			case EVEN_PARITY: par = (sum_1 & 0x1) ? 1 : 0; break;
		}
		if (par)
			*(samples16) = MANCHESTER_SEQ_D;
		else
			*(samples16) = MANCHESTER_SEQ_E;
		samples16++;
	}
	*s16 = samples16;
}

int manchester_encode(u_int8_t *sample_buf, u_int16_t sample_buf_len, 
		      const iso14443_frame *frame)
{
	unsigned int i, enc_size;
	u_int16_t *samples16;
	
	if(frame->type != TYPE_A) return -EINVAL;
	if(frame->parameters.a.format != STANDARD_FRAME) return -EINVAL; /* AC not implemented yet */
	
	/* One bit data is 16 bit is 2 byte modulation data */
	enc_size = 1 /* SOF */ 
		+ frame->numbytes * ((frame->parameters.a.parity != NO_PARITY) ? 9 : 8) /* bits per byte */
		+ 1 /* EOF */;
	enc_size = enc_size /* in bits */ * 2 /* bytes modulation data per bit raw data*/;

	if (sample_buf_len < enc_size)
		return -EINVAL;
	
	memset(sample_buf, 0, enc_size);
	
	samples16 = (u_int16_t*)sample_buf;

	/* SOF */
	*(samples16++) = MANCHESTER_SEQ_D;
	
	if(frame->parameters.a.parity == NO_PARITY)
		for (i = 0; i < frame->numbytes; i++)
			manchester_enc_byte(&samples16, frame->data[i], PARITY_NONE);
	else if(frame->parameters.a.parity == GIVEN_PARITY)
		for (i = 0; i < frame->numbytes; i++)
			manchester_enc_byte(&samples16, frame->data[i], 
				(frame->parity[i/8]&(1<<(i%8))) ?PARITY_1:PARITY_0);
	else if(frame->parameters.a.parity == PARITY)
		for (i = 0; i < frame->numbytes; i++)
			manchester_enc_byte(&samples16, frame->data[i], ODD_PARITY);
		
	/* EOF */
	*(samples16++) = MANCHESTER_SEQ_F;

	return enc_size;
}

#if 0
/* Broken? */
#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);

}
#endif
personal git repositories of Harald Welte. Your mileage may vary