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
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
|
/*
* Copyright (C) 1995 Advanced RISC Machines Limited. All rights reserved.
*
* This software may be freely used, copied, modified, and distributed
* provided that the above copyright notice is preserved in all copies of the
* software.
*/
/*-*-C-*-
*
* $Revision: 1.3 $
* $Date: 2004/12/27 14:00:54 $
*
* Project: ANGEL
*
* Title: Character based packet transmission engine
*/
#include <stdarg.h> /* ANSI varargs support */
#include "angel.h" /* Angel system definitions */
#include "angel_endian.h" /* Endian independant memory access macros */
#include "crc.h" /* crc generation definitions and headers */
#include "rxtx.h"
#include "channels.h"
#include "buffers.h"
#include "logging.h"
/* definitions to describe the engines state */
#define N_STX 0x0 /* first 2 bits for N_ */
#define N_BODY 0x1
#define N_ETX 0x2
#define N_IDLE 0x3
#define N_MASK 0x3 /* mask for the Encapsulator state */
#define E_PLAIN (0x0 << 2) /* 3rd bit for E_ */
#define E_ESC (0x1 << 2) /* 3rd bit for E_ */
#define E_MASK (0x1 << 2) /* mask for the Escaper state */
#define F_HEAD (0x0 << 3) /* 4th and 5th bits for F_ */
#define F_DATA (0x1 << 3)
#define F_CRC (0x1 << 4)
#define F_MASK (0x3 << 3) /* mask for the Escaper state */
static unsigned char escape(unsigned char ch_in, struct te_state *txstate);
void Angel_TxEngineInit(const struct re_config *txconfig,
const struct data_packet *packet,
struct te_state *txstate){
IGNORE(packet);
txstate->tx_state = N_STX | E_PLAIN | F_HEAD;
txstate->field_c = 0;
txstate->encoded = 0;
txstate->config = txconfig;
txstate->crc = 0;
}
te_status Angel_TxEngine(const struct data_packet *packet,
struct te_state *txstate,
unsigned char *tx_ch){
/* TODO: gaurd on long/bad packets */
/*
* encapsulate the packet, framing has been moved from a seperate
* function into the encapsulation routine as it needed too much
* inherited state for it to be sensibly located elsewhere
*/
switch ((txstate->tx_state) & N_MASK){
case N_STX:
#ifdef DO_TRACE
__rt_trace("txe-stx ");
#endif
txstate->tx_state = (txstate->tx_state & ~N_MASK) | N_BODY;
*tx_ch = txstate->config->stx;
txstate->field_c = 3; /* set up for the header */
txstate->crc = startCRC32; /* set up basic crc */
return TS_IN_PKT;
case N_BODY:{
switch (txstate->tx_state & F_MASK) {
case F_HEAD:
#ifdef DO_TRACE
__rt_trace("txe-head ");
#endif
if (txstate->field_c == 3) {
/* send type */
*tx_ch = escape(packet->type, txstate);
return TS_IN_PKT;
}
else {
*tx_ch = escape((packet->len >> (txstate->field_c - 1) * 8) & 0xff,
txstate);
if (txstate->field_c == 0) {
/* move on to the next state */
txstate->tx_state = (txstate->tx_state & ~F_MASK) | F_DATA;
txstate->field_c = packet->len;
}
return TS_IN_PKT;
}
case F_DATA:
#ifdef DO_TRACE
__rt_trace("txe-data ");
#endif
*tx_ch = escape(packet->data[packet->len - txstate->field_c], txstate);
if (txstate->field_c == 0) {
/* move on to the next state */
txstate->tx_state = (txstate->tx_state & ~F_MASK) | F_CRC;
txstate->field_c = 4;
}
return TS_IN_PKT;
case F_CRC:
#ifdef DO_TRACE
__rt_trace("txe-crc ");
#endif
*tx_ch = escape((txstate->crc >> ((txstate->field_c - 1) * 8)) & 0xff,
txstate);
if (txstate->field_c == 0) {
#ifdef DO_TRACE
__rt_trace("txe crc = 0x%x\n", txstate->crc);
#endif
/* move on to the next state */
txstate->tx_state = (txstate->tx_state & ~N_MASK) | N_ETX;
}
return TS_IN_PKT;
}
}
case N_ETX:
#ifdef DO_TRACE
__rt_trace("txe-etx\n");
#endif
txstate->tx_state = (txstate->tx_state & ~N_MASK) | N_IDLE;
*tx_ch = txstate->config->etx;
return TS_DONE_PKT;
default:
#ifdef DEBUG
__rt_info("tx default\n");
#endif
txstate->tx_state = (txstate->tx_state & ~N_MASK) | N_IDLE;
return TS_IDLE;
}
/* stop a silly -Wall warning */
return (te_status)-1;
}
/*
* crc generation occurs in the escape function because it is the only
* place where we know that we're putting a real char into the buffer
* rather than an escaped one.
* We must be careful here not to update the crc when we're sending it
*/
static unsigned char escape(unsigned char ch_in, struct te_state *txstate) {
if (((txstate->tx_state) & E_MASK) == E_ESC) {
/* char has been escaped so send the real char */
#ifdef DO_TRACE
__rt_trace("txe-echar ");
#endif
txstate->tx_state = (txstate->tx_state & ~E_MASK) | E_PLAIN;
txstate->field_c--;
if ((txstate->tx_state & F_MASK) != F_CRC)
txstate->crc = crc32( &ch_in, 1, txstate->crc);
return ch_in | serial_ESCAPE;
}
if ((ch_in < 32) && ((txstate->config->esc_set & (1 << ch_in)) != 0)) {
/* char needs escaping */
#ifdef DO_TRACE
__rt_trace("txe-esc ");
#endif
txstate->tx_state = (txstate->tx_state & ~E_MASK) | E_ESC;
return txstate->config->esc;
}
/* must be a char that can be sent plain */
txstate->field_c--;
if ((txstate->tx_state & F_MASK) != F_CRC)
txstate->crc = crc32(&ch_in, 1, txstate->crc);
return ch_in;
}
/* EOF tx.c */
|