-
Notifications
You must be signed in to change notification settings - Fork 2
/
checkraw.c
262 lines (216 loc) · 6.87 KB
/
checkraw.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
/*
mini prg to write a command to write and read the vynmea chips
*/
#include <stdio.h> // standard input / output functions
#include <stdint.h>
#include <stdlib.h>
#include <string.h> // string function definitions
#include <unistd.h> // UNIX standard function definitions
#include <fcntl.h> // File control definitions
#include <errno.h> // Error number definitions
#include "gps.h"
#include "gpsd.h"
#include "driver_vyspi.h"
#include "bits.h"
#define MAX_PACKET_LENGTH 516 /* 7 + 506 + 3 */
typedef enum {
complete = 0,
error = 1,
incomplete = 2
} nmea2000_state;
uint32_t frameCounter;
struct nmea2000_packet_t {
uint16_t idx;
uint32_t ptr;
uint32_t fast_packet_len;
uint8_t outbuffer[MAX_PACKET_LENGTH*2 + 1];
uint32_t outbuflen;
uint32_t pgn;
uint32_t state;
uint32_t frame_count;
uint32_t packet_count;
uint32_t error_count;
uint32_t cancel_count;
uint32_t packet_transfer_count;
};
struct nmea2000_packet_t nmea2000_packet;
uint32_t n2k_fixed_fast_list[] = {
126464,
126996,
127489,
128275, // distance log as provided by DST800
129540,
129542,
129793,
129794,
129798,
129802,
129809,
129810,
130935, // observed in AIS
130842, // observed in AIS
262161,
262384,
262386, // observed when testing ROT with actisense
0
};
void gpsd_throttled_report(const int errlevel UNUSED, const char * buf UNUSED) {}
void gpsd_report(const int debuglevel, const int errlevel, const char *fmt, ...)
/* our version of the logger */
{
if(debuglevel < errlevel)
return;
va_list ap;
va_start(ap, fmt);
gpsd_labeled_report(debuglevel, LOG_ERROR - 1, errlevel, "gpsd:", fmt, ap);
va_end(ap);
}
void gpsd_external_report(const int debuglevel UNUSED, const int errlevel UNUSED,
const char *fmt UNUSED, ...) {
}
ssize_t gpsd_write(struct gps_device_t *session,
const char *buf,
const size_t len)
/* pass low-level data to devices, echoing it to the log window */
{
return gpsd_serial_write(session, buf, len);
}
void nmea2000_parsemsg(struct gps_device_t *session,
uint32_t pgn, uint8_t * bin, uint16_t binlen,
struct nmea2000_packet_t * packet) {
uint8_t l2;
uint8_t fast = 0;
uint16_t cnt = 0;
frameCounter++;
cnt = 0;
while(n2k_fixed_fast_list[cnt] > 0) {
if(pgn == n2k_fixed_fast_list[cnt]) {
fast = 1;
break;
}
cnt++;
}
gpsd_report(session->context->debug, LOG_RAW,
"Parse transmission pgn= %u with len= %u\n", pgn, binlen);
// is this a fast transmission (list of pgn from gpsd)
if(fast && (binlen == 9)) {
if((bin[0] & 0x1f) == 0) {
// start of fast transmission
// count cancled other fast transfers
if((packet->pgn == 0) && (packet->state == incomplete))
packet->cancel_count++;
packet->fast_packet_len = bin[1];
packet->idx = bin[0];
packet->ptr = 0;
packet->idx += 1;
packet->pgn = 0; // use this sign for whole fast trans being done
packet->state = incomplete;
for (l2=2;l2<8;l2++) {
packet->outbuffer[packet->ptr++]= bin[l2];
}
gpsd_report(session->context->debug, LOG_SPIN,
"Start of fast transmission pgn= %u with len %u\n", pgn, packet->fast_packet_len);
} else if(bin[0] == packet->idx) {
packet->state = incomplete;
for (l2=1;l2<8;l2++) {
if (packet->fast_packet_len > packet->ptr) {
packet->outbuffer[packet->ptr++] = bin[l2];
}
}
if (packet->ptr == packet->fast_packet_len) {
packet->outbuflen = packet->fast_packet_len;
packet->fast_packet_len = 0;
packet->pgn = pgn;
packet->state = complete;
packet->packet_count++;
gpsd_report(session->context->debug, LOG_IO,
"Complete fast transmission pgn= %u with length %u\n",
pgn, packet->outbuflen);
} else {
packet->idx += 1;
}
} else {
// error
// packetError = packet->idx;
gpsd_report(session->context->debug, LOG_ERROR,
"Error N2K cnt = %d, idx = %u, d[0] = %u\n",
packet->packet_count, packet->idx, bin[0]);
packet->idx = 0;
packet->fast_packet_len = 0;
packet->state = error;
packet->error_count++;
}
} else {
// single transmission
gpsd_report(session->context->debug, LOG_IO,
"Single transmission pgn= %u\n", pgn);
// count cancled fast transfers
if((packet->pgn == 0) && (packet->state == incomplete))
packet->cancel_count++;
packet->ptr = 0;
for (l2=0;l2<binlen;l2++) {
packet->outbuffer[packet->ptr++]= bin[l2];
}
packet->idx = 0;
packet->outbuflen = binlen;
packet->fast_packet_len = 0;
packet->pgn = pgn;
packet->state = complete;
packet->packet_count++;
}
packet->frame_count++;
}
void decodeline(struct gps_device_t *session, char * line) {
const int LEN = 255;
uint8_t bin[LEN];
uint32_t stdid, extid, pgn;
uint8_t prio, saddr, daddr;
int binlen = 0;
const char *hexchar = "0123456789abcdef";
binlen = gpsd_hexpack(line, bin, LEN);
stdid = getleu32(bin, 0);
extid = getleu32(bin, 4);
saddr = (uint8_t)(extid & 0xff);
pgn = (extid >> 8) & 0x1ffff;
prio = (uint8_t)((extid >> 26) & 0x7);
// PDU1 messages with bits 0x0000ff000 between 0x00 to 0xef and make use of dest and source address
// PDU2 messages from 0xf0 to 0xff are intended to be broadcasts
if (((pgn & 0xff00) >> 8) < 0xf0) {
daddr = (uint8_t)(pgn & 0xff);
pgn = pgn & 0x01ff00;
} else {
daddr = (uint8_t)0xff;
}
gpsd_report(session->context->debug, LOG_INF, "s: %u, d: %u, p: %u - %u\n", saddr, daddr, prio, pgn);
}
int main(int argc, char * argv[]) {
uint8_t opts = 0;
char c;
char n2kSequence[255];
int loglevel = 5;
struct gps_device_t session;
struct gps_context_t context;
opterr = 0;
n2kSequence[0] = '\0';
while ((c = getopt(argc, argv, "b:")) != -1) {
switch (c) {
case 'b':
strncpy(n2kSequence, optarg, 255);
printf("n2k %s\n", n2kSequence);
opts++;
break;
case 'd':
loglevel = atoi(optarg);
printf("n2k loglevel %d\n", loglevel);
opts++;
break;
default:
abort ();
}
}
context.debug = loglevel;
session.context = &context;
gpsd_init(&session, &context, "pseudo");
decodeline(&session, n2kSequence);
return 0;
}