1
|
|
2
|
#include <stdint.h>
|
3
|
#include <stdio.h>
|
4
|
#include <sys/types.h>
|
5
|
|
6
|
#include "soft_uart.h"
|
7
|
|
8
|
static inline uint32_t samples_per_etu(struct suart_data *su)
|
9
|
{
|
10
|
return su->samplerate / su->recip_etu;
|
11
|
}
|
12
|
|
13
|
static const char *state_strings[] = {
|
14
|
[WAIT_RESET] = "WAIT_RESET",
|
15
|
[IN_RESET] = "IN_RESET",
|
16
|
[WAIT_START_FALLEDGE] = "WAIT_START_FALLEDGE",
|
17
|
[WAIT_START_ETU07] = "WAIT_START_ETU07",
|
18
|
[RX_BITS] = "RX_BITS",
|
19
|
[POST_RX_WAIT_HIGH] = "POST_RX_WAIT_HIGH",
|
20
|
};
|
21
|
|
22
|
static void change_state(struct suart_data *su, enum suart_state new_state)
|
23
|
{
|
24
|
printf("State change: %s -> %s\n", state_strings[su->state], state_strings[new_state]);
|
25
|
su->state = new_state;
|
26
|
}
|
27
|
|
28
|
/* According to ISO/IEC 7816-3 Section 6.1.2 */
|
29
|
int suart_process_sample_bit(struct suart_data *suart, uint8_t clk_bit, uint8_t rst_bit, uint8_t sample_bit)
|
30
|
{
|
31
|
uint32_t samp_per_etu = samples_per_etu(suart);
|
32
|
uint8_t next_bit;
|
33
|
|
34
|
if (rst_bit == 0 && suart->state != IN_RESET) {
|
35
|
change_state(suart, IN_RESET);
|
36
|
/* FIXME: reset some other things? */
|
37
|
}
|
38
|
|
39
|
switch (suart->state) {
|
40
|
case WAIT_RESET:
|
41
|
if (rst_bit == 0)
|
42
|
change_state(suart, IN_RESET);
|
43
|
break;
|
44
|
case IN_RESET:
|
45
|
if (rst_bit == 1)
|
46
|
change_state(suart, WAIT_START_FALLEDGE);
|
47
|
break;
|
48
|
case WAIT_START_FALLEDGE:
|
49
|
if (sample_bit == 0) {
|
50
|
suart->sample_after_sbit = 0;
|
51
|
suart->bits_pending = suart->num_bits + 1;
|
52
|
change_state(suart, WAIT_START_ETU07);
|
53
|
}
|
54
|
break;
|
55
|
case WAIT_START_ETU07:
|
56
|
if (suart->sample_after_sbit > (samp_per_etu/2)+1) {
|
57
|
if (sample_bit != 0) {
|
58
|
printf("!!!!!!!!!!!!!!!!!!!!! start bit after 0.7 * ETU no longer low\n");
|
59
|
} else {
|
60
|
change_state(suart, RX_BITS);
|
61
|
suart->rx_char = 0;
|
62
|
}
|
63
|
}
|
64
|
/* else stay in this state until the condition is true */
|
65
|
break;
|
66
|
case RX_BITS:
|
67
|
next_bit = suart->num_bits+1 - suart->bits_pending;
|
68
|
#if 0
|
69
|
printf("\tRX_BITS: IO = %u, next_bit = %u, sample_after_sbit = %u, samp_per_etu = %u, required_after_sbit = %u\n",
|
70
|
sample_bit, next_bit, suart->sample_after_sbit, samp_per_etu,
|
71
|
(samp_per_etu/2) + ((next_bit+1) * samp_per_etu));
|
72
|
#endif
|
73
|
if (suart->sample_after_sbit > (samp_per_etu/2) + ((next_bit+1) * samp_per_etu)) {
|
74
|
/* check if this is the parity bit */
|
75
|
//printf("new_bit = %u\n", sample_bit);
|
76
|
if (next_bit == suart->num_bits) {
|
77
|
/* FIXME calculate parity */
|
78
|
} else {
|
79
|
/* an actual data bit */
|
80
|
/* Section 6.1.4.1 */
|
81
|
if (suart->convention == INVERSE_CONVENTION) {
|
82
|
if (sample_bit == 1)
|
83
|
sample_bit = 0x00;
|
84
|
else
|
85
|
sample_bit = 0x80;
|
86
|
/* shift existing patter one to the right */
|
87
|
suart->rx_char = suart->rx_char >> 1;
|
88
|
/* mask in the additional bit */
|
89
|
suart->rx_char |= sample_bit;
|
90
|
} else {
|
91
|
suart->rx_char |= (sample_bit << next_bit);
|
92
|
}
|
93
|
}
|
94
|
suart->bits_pending--;
|
95
|
}
|
96
|
|
97
|
if (suart->bits_pending == 0) {
|
98
|
|
99
|
/* output the character that we decoded */
|
100
|
printf("Output Byte: %02x\n", suart->rx_char);
|
101
|
|
102
|
change_state(suart, POST_RX_WAIT_HIGH);
|
103
|
}
|
104
|
break;
|
105
|
case POST_RX_WAIT_HIGH:
|
106
|
if (sample_bit == 0x01) {
|
107
|
/* return to initial state */
|
108
|
change_state(suart, WAIT_START_FALLEDGE);
|
109
|
}
|
110
|
break;
|
111
|
}
|
112
|
suart->sample_after_sbit++;
|
113
|
}
|
114
|
|
115
|
void suart_init(struct suart_data *su)
|
116
|
{
|
117
|
su->state = WAIT_RESET;
|
118
|
su->convention = DIRECT_CONVENTION;
|
119
|
printf("Samplerate = %u\n", su->samplerate);
|
120
|
printf("etu = 1 / %u\n", su->recip_etu);
|
121
|
printf("samp_per_etu = %u\n", samples_per_etu(su));
|
122
|
}
|