-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathr305Parser.c
170 lines (150 loc) · 5.72 KB
/
r305Parser.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
/**
* \file
* \brief Implementation of r305Parser functions
*
*/
#include "r305Parser.h"
#include <inttypes.h>
/**
* @brief Get default package structure filled with given parameters.
* @param pid data_package::pid byte to define type of package of the package from \link PID \endlink definitions.
* @param length data_package::length Parameter of package, use \link Length \endlink definitions.
* @param data data_package::data Array of bytes to set as data of the package.
* @return data_package structure with defaults settings and specified configurations.
*/
void getBasePackage(data_package *package, uint8_t pid, uint16_t length,
uint8_t* data) {
uint16_t i = 0;
package->header = DEFAULT_HEADER;
package->address = DEFAULT_ADDRESS;
package->pid = pid;
package->length = length;
package->data_size = package->length - sizeof(package->checksum);
for (i = 0; i < package->data_size; i++) {
package->data[package->data_size - i - 1] = data[i];
}
autoSetChecksum(package);
autoSetPackageSize(package);
stringyfyPackage(package);
package->ack_command_code = package->data[package->data_size];
}
uint16_t autoSetChecksum(data_package *package) {
uint16_t i = 0;
package->checksum = (uint16_t) package->pid + (uint16_t) package->length;
for (i = 0; i < package->length - sizeof(package->checksum); i++) {
package->checksum += (uint16_t) package->data[i];
}
return package->checksum;
}
/**
* @brief Calculate and set data_package::package_size parameter.
* @param package pointer to a data_package.
* @return Calculated size of package.
*/
uint32_t autoSetPackageSize(data_package *package) {
package->package_size = sizeof(package->header) + sizeof(package->address)
+ sizeof(package->pid) + sizeof(package->length) + package->length;
return package->package_size;
}
/**
* @brief Convert data_package structure to byte string and set data_package::package_string parameter.
* @param package pointer to a data_package.
* @return byte string of input data_package.
*/
uint8_t* stringyfyPackage(data_package *package) {
uint16_t i = 0;
package->package_string[0] = package->header >> 8;
package->package_string[1] = package->header;
package->package_string[2] = package->address >> 8 * 3;
package->package_string[3] = package->address >> 8 * 2;
package->package_string[4] = package->address >> 8 * 1;
package->package_string[5] = package->address;
package->package_string[6] = package->pid;
package->package_string[7] = package->length >> 8;
package->package_string[8] = package->length;
for (i = 0; i < package->data_size; i++) {
package->package_string[i + 9] = package->data[package->length
- sizeof(package->checksum) - 1 - i];
}
package->package_string[i + 9] = package->checksum >> 8;
package->package_string[i + 10] = package->checksum;
return package->package_string;
}
/**
* @brief Load complete data_package structure from byte string.
* @param package_string Input byte string.
* @param package Pointer to data_package to load.
* @return
* -1: if checksum match.
* -0: if checksum mismatch.
*/
uint8_t loadPackage(uint8_t* package_string, data_package *package) {
uint16_t i = 0;
package->header = (uint16_t) package_string[0] << 8
| (uint16_t) package_string[1];
package->address = (uint32_t) package_string[2] << 8 * 3
| (uint32_t) package_string[3] << 8 * 2
| (uint32_t) package_string[4] << 8 * 1
| (uint32_t) package_string[5];
package->pid = (uint8_t) package_string[6];
package->length = (uint16_t) package_string[7] << 8
| (uint16_t) package_string[8];
package->data_size = package->length - sizeof(package->checksum);
for (i = 0; i < package->data_size; i++) {
//UART reads Highest byte first
// package->length - sizeof(package->checksum) -1 to get the highest byte
package->data[package->data_size - 1 - i] = package_string[9 + i];
}
autoSetChecksum(package);
autoSetPackageSize(package);
// Copy string
for (i = 0; i < package->package_size; i++) {
package->package_string[i] = package_string[i];
}
package->ack_command_code = package->data[package->data_size];
if (((uint16_t) package_string[9 + i] << 8
| (uint16_t) package_string[10 + i]) != package->checksum) {
return 0; // Checksum doesn't match
} else {
return 1; // Checksum match
}
}
/**
* @fn void Write_fn(uint8_t* str,uint32_t size)
* @brief callback function to write byte string.
* @param str byte string to send. data_package::package_string is passed
* @param size size of byte string. data_package::package_size is passed
*/
/**
* @brief Send data_package using callback function Write_fn.
* @param package data_package to be sent.
* @param Write_fn callback function
*
*/
// The argument Write_fn should be a function with arguments (uint8_t*,uint32_t) of which
// First argument is array of bytes to be sent using that function.
// Second argument is the size of the array.
void sendPackage(data_package *package, void (*Write_fn)(uint8_t*, uint32_t)) {
autoSetChecksum(package);
autoSetPackageSize(package);
Write_fn(package->package_string, package->package_size);
}
/**
* @brief
* @param package data_package to load received data.
* @param size No. of bytes to receive. For most of ACK package use LEN_ACK* + 9.
* @param Read_fn callback function to read data bytes.
* @return
* 1: for valid package.
* 0: for invalid package.
* @sa \link LengthACK \endlink
*/
// The argument Read_fn should be a function with arguments (uint8_t*,uint32_t) of which
// First argument is array of bytes to be received using that function
// Second argument is the size of the array.
int recvPackage(data_package *package, uint16_t size,
void (*Read_fn)(uint8_t*, uint32_t)) {
uint8_t tmp_package_string[256];
Read_fn(tmp_package_string, (uint32_t) size);
return loadPackage(tmp_package_string, package);
}