-
Notifications
You must be signed in to change notification settings - Fork 3
/
rI2CRX.c
280 lines (237 loc) · 7 KB
/
rI2CRX.c
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
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
#include "rI2CRX.h"
#include <stdint.h>
#include "string.h"
#include <stdio.h>
#include <stdlib.h>
#include "teensyByteOrder.h"
uint8_t buffer[I2C_BUFFER_SIZE];
uint16_t bufferBegin;
uint16_t bufferLength;
void(*rI2CRX_frameRXBeginCB)();
void(*rI2CRX_recvDecParamCB)(struct rI2CRX_decParam decParam);
void(*rI2CRX_frameRXEndCB)();
void processBuffer();
int processFrame(uint8_t *frameBuffer, uint16_t length);
void receiveParam(uint8_t type, uint16_t index, uint64_t rawData);
void rI2CRX_begin()
{
bufferLength = 0;
bufferBegin = 0;
rI2CRX_frameRXBeginCB = NULL;
rI2CRX_recvDecParamCB = NULL;
rI2CRX_frameRXEndCB = NULL;
}
void rI2CRX_receiveBytes(uint8_t* data, uint16_t length)
{
int i = 0;
if (length > I2C_BUFFER_SIZE)
return; //somehthing's not right, drop this data and hope we catch up
else {}//All is well, continue on
//Got some bad data at some point
if (bufferLength + length > I2C_BUFFER_SIZE)
{
bufferLength = 0;
bufferBegin = 0;
}
for (i = 0; i < length; i++)
buffer[(i + bufferBegin + bufferLength)%I2C_BUFFER_SIZE] = data[i];
bufferLength += length;
//See if there's enough data for a full frame
if (bufferLength >= 8){
processBuffer();
}
else
{
//Not enough data for a full frame, do nothing
}
}
void processBuffer()
{
uint8_t frameBuffer[I2C_BUFFER_SIZE];
int i = 0;
int bufferBeginJump = 0;
//Search for a full frame
for (i = 0; i < (bufferLength-1); i++)
{
//Is this a start code?
if (buffer[(bufferBegin + i) % I2C_BUFFER_SIZE] == I2C_CONTROL_CHAR && buffer[((bufferBegin + i + 1) % I2C_BUFFER_SIZE)] == I2C_FRAME_START)
{
//See if we should have the whole header yet
if (i + 5 < bufferLength)
{
//Grab the length of the frame from the header
uint16_t frameLength = buffer[(bufferBegin + i + 2) % I2C_BUFFER_SIZE];
int headerLength = 4;
if (frameLength == I2C_CONTROL_CHAR){
frameLength = frameLength * 256 + buffer[(bufferBegin + i + 4) % I2C_BUFFER_SIZE];
headerLength++;
if (buffer[(bufferBegin + i + 4) % I2C_BUFFER_SIZE] == I2C_CONTROL_CHAR)
headerLength++;
}
else
frameLength = frameLength*256 + buffer[(bufferBegin + i + 3) % I2C_BUFFER_SIZE];
//See if we have the end of the frame in the buffer yet
if (i + headerLength + frameLength <= bufferLength)
{
//Copy the frame into a flat buffer
//This step isn't 100% necessary but it does make processing the frame a bit easier to follow
int x;
for (x = 0; x < (frameLength + headerLength); x++)
{
frameBuffer[x] = buffer[(x+i+bufferBegin) % I2C_BUFFER_SIZE];
}
//Process the frame!
if (processFrame(frameBuffer, frameLength + 4)){
i += frameLength + headerLength;
bufferBeginJump += headerLength + frameLength;
}
}
else{
//We have a start code, but not enough data for a full frame yet
i = bufferLength;
}
}
else{
//Don't have the full header yet, nothing to do for now
i = bufferLength - 1;
}
}
else{
//Not sure what we got sent, but it's not a start code so advance the buffer.
bufferBeginJump++;
}
}
bufferBegin += bufferBeginJump;
bufferBegin = bufferBegin % I2C_BUFFER_SIZE;
bufferLength -= bufferBeginJump;
}
int processFrame(uint8_t *frameBuffer, uint16_t length)
{
//Check the start and end headers
if (frameBuffer[0] != I2C_CONTROL_CHAR || frameBuffer[1] != I2C_FRAME_START || frameBuffer[length - 4] != I2C_CONTROL_CHAR || frameBuffer[length - 3] != I2C_FRAME_END)
return 0;
int i = 0;
uint8_t checksum = 0;
for (i = 0; i < length-4; i++)
checksum ^= frameBuffer[i];
if (frameBuffer[length - 2] != checksum){
return 0;
}
else {} //All good, continue on
if (rI2CRX_frameRXBeginCB != NULL)
rI2CRX_frameRXBeginCB();
//Shorten any escaped data now that we've isolated a single frame
for (i = 2; i < length-1; i++)
{
if (frameBuffer[i] == I2C_CONTROL_CHAR && frameBuffer[i + 1] == I2C_CONTROL_CHAR)
{
int x;
for (x = i + 1; x < length - 1; x++)
{
frameBuffer[x] = frameBuffer[x + 1];
}
frameBuffer[length - 1] = 0x00;
}
else{}//no escaped data here, continue on.
}
uint16_t position = 4;
uint64_t rawData;
while (position < length)
{
if (frameBuffer[position] == 0xD5)
{
position++;
switch (frameBuffer[position])
{
case I2C_PARAMETER_START:
{
position++;
int dataType = frameBuffer[position] & 0x0F;
uint8_t dataSize = (frameBuffer[position] & 0xF0) / 16;
if (dataType == 1 || dataType == 2 || dataType == 3)
{
rawData = 0;
//safety check for memcopy
if (dataSize <= 8){
memcpy(&rawData, &frameBuffer[position + 3], dataSize);
}
else{ break; } //Somethings not right
receiveParam(frameBuffer[position], frameBuffer[position + 1] * 256 + frameBuffer[position+2], rawData);
}
else if (dataType == 0){
}
else{}
position += dataSize+3;
}
break;
case I2C_FRAME_END:
if (rI2CRX_frameRXEndCB != NULL)
rI2CRX_frameRXEndCB();
return 1;
}
}
else{
//Should report an error
position++;
}
}
rI2CRX_frameRXEndCB();
return 1;
}
int8_t temp_1byte;
int16_t temp_2byte;
int32_t temp_4byte;
int64_t temp_8byte;
void receiveParam(uint8_t type, uint16_t index, uint64_t rawData)
{
struct rI2CRX_decParam receivedParam;
receivedParam.index = index;
receivedParam.type = type;
switch (type)
{
case 0x11: receivedParam.val = &temp_1byte;
*((int8_t*)receivedParam.val) = (int8_t)rawData;
receivedParam.length = 1;
break;
case 0x12: receivedParam.val = &temp_1byte;
*((uint8_t*)receivedParam.val) = (uint8_t)rawData;
receivedParam.length = 1;
break;
case 0x21: receivedParam.val = &temp_2byte;
*((int16_t*)receivedParam.val) = (int16_t)ntohs((uint16_t)rawData);
receivedParam.length = 2;
break;
case 0x22: receivedParam.val = &temp_2byte;
*((uint16_t*)receivedParam.val) = ntohs((uint16_t)rawData);
receivedParam.length = 2;
break;
case 0x41: receivedParam.val = &temp_4byte;
*((int32_t*)receivedParam.val) = ntohl((uint32_t)rawData);
receivedParam.length = 4;
break;
case 0x42: receivedParam.val = &temp_4byte;
*((uint32_t*)receivedParam.val) = ntohl((uint32_t)rawData);
receivedParam.length = 4;
break;
case 0x81: receivedParam.val = &temp_8byte;
*((int64_t*)receivedParam.val) = (uint64_t)be64toh((uint64_t)rawData);
receivedParam.length = 8;
break;
case 0x82: receivedParam.val = &temp_8byte;
*((uint64_t*)receivedParam.val) = be64toh((uint64_t)rawData);
receivedParam.length = 8;
break;
case 0x43: receivedParam.val = &temp_4byte;
*((int32_t*)receivedParam.val) = ntohl((uint32_t)rawData);
//memcpy(receivedParam.val, &rawData, 4);
receivedParam.length = 4;
break;
case 0x83: receivedParam.val = &temp_8byte;
*((uint64_t*)receivedParam.val) = be64toh((uint64_t)rawData);
//memcpy(receivedParam.val, &rawData, 8);
receivedParam.length = 8;
break;
default:return;
}
rI2CRX_recvDecParamCB(receivedParam);
}