Project

General

Profile

Statistics
| Revision:

root / trunk / code / projects / diagnostic_station / station / comm_server.c @ 1208

History | View | Annotate | Download (9.15 KB)

1 1182 deffi
#include "comm_server.h"
2 1169 deffi
3 1171 deffi
#include <avr/pgmspace.h>
4 1198 deffi
#include <string.h>
5 1171 deffi
6 1183 deffi
#include "global.h"
7 1185 deffi
#include "tests.h"
8 1183 deffi
9
// ##############
10
// ## Settings ##
11
// ##############
12
13 1198 deffi
//#define comm_server_debug
14 1183 deffi
15
// ###############
16
// ## Constants ##
17
// ###############
18
19 1171 deffi
#define buffer_size 120
20
21 1198 deffi
// Put all symbolic string constants into the program memory because else all of them would be copied into the RAM (see
22
// the avr-libc documentation, chapter "Data in Program Space").
23 1171 deffi
24 1198 deffi
// Commands
25
const char command_ping          [] PROGMEM = "ping"       ;
26
const char command_start_test    [] PROGMEM = "start_test" ;
27
const char command_all           [] PROGMEM = "all"        ;
28
const char command_comm          [] PROGMEM = "comm"       ;
29
const char command_bom           [] PROGMEM = "bom"        ;
30
const char command_rangefinder   [] PROGMEM = "rangefinder";
31
const char command_motor         [] PROGMEM = "motor"      ;
32
const char command_encoder       [] PROGMEM = "encoder"    ;
33
const char command_help          [] PROGMEM = "help"       ;
34
35
// Help
36
const char help_text          [] PROGMEM =
37
        "# Available commands:" NL
38
        "#   - help" NL
39
        "#   - ping" NL
40
        "#   - start_test all" NL
41
        "#   - start_test comm" NL
42
        "#   - start_test bom all|<num> (0..15)" NL
43
        "#   - start_test rangefinder all|<num> (?..?)" NL
44
        "#   - start_test motor all|<num> (1..2)" NL
45
        "#   - start_test encoder all|<num> (1..2)" NL
46
        ;
47
48
49 1183 deffi
// ####################
50
// ## Initialization ##
51
// ####################
52
53 1182 deffi
void comm_server_init ()
54 1169 deffi
{
55
        usb_init ();
56
}
57
58
59 1183 deffi
// ########################
60
// ## Message processing ##
61
// ########################
62 1171 deffi
63 1198 deffi
static char *find_next_parameter (char *p)
64
{
65
        // Advance p until a blank or the terminating zero is found.
66
        while ((*p)!=' ' && (*p)!=0) p++;
67
68
        // Advance p until a non-blank (including the terminating zero) is found.
69
        while (*p==' ') p++;
70
71
        // We have found the next parameter unless p points to the terminating zero.
72
        if (*p==0)
73
                return NULL;
74
        else
75
                return p;
76
}
77
78 1182 deffi
/** Check if the buffer starts with the given text, followed by a space */
79 1198 deffi
static bool serial_match (PGM_P text, const char *buffer)
80 1182 deffi
{
81 1183 deffi
        uint8_t text_len=strlen_P (text);
82 1198 deffi
        uint8_t buffer_len=strlen (buffer);
83 1182 deffi
84
        // If the buffer is shorter than the text, there is no match
85 1198 deffi
        if (buffer_len<text_len) return false;
86 1182 deffi
87
        // If the buffer is longer than the text, it must have a space at position after the text
88 1198 deffi
        if (buffer_len>text_len && buffer[text_len]!=' ') return false;
89 1182 deffi
90 1183 deffi
        // Test for match
91
        if (strncmp_P ((char *)buffer, text, text_len)==0) return true;
92
93
        return false;
94
}
95 1182 deffi
96 1202 deffi
static bool serial_number_u8 (uint8_t *num, const char *buffer)
97
{
98
        uint8_t result=0;
99
100
        // Iterate over the buffer
101
        while (1)
102
        {
103
                // Look at the character
104
                char c=*buffer;
105 1182 deffi
106 1202 deffi
                if (c>='0' && c<='9')
107
                {
108
                        // It's a digit. Process it.
109
                        result*=10;
110
                        result+=(c-'0');
111
                }
112
                else if (c==' ' || c==0)
113
                {
114
                        // It's a space or a terminating zero, which means that the paramter is a valid number.
115
                        *num=result;
116
                        return true;
117
                }
118
                else
119
                {
120
                        // It's a different character, which means that the parameter is not a number.
121
                        return false;
122
                }
123
124
                // Move to the next byte
125
                buffer++;
126
        }
127
}
128 1182 deffi
129 1183 deffi
130 1185 deffi
131
132 1202 deffi
133
134 1183 deffi
// ########################
135
// ## Messages (sending) ##
136
// ########################
137
138
void server_send_finished ()
139
{
140
        usb_puts ("finished");
141 1182 deffi
}
142
143 1202 deffi
// ##########################
144
// ## Messages (Receiving) ##
145
// ##########################
146 1182 deffi
147 1202 deffi
static void unhandled_parameters (char *buffer)
148
{
149
        usb_puts ("# Warning: unhandled parameters: [");
150
        usb_puts (buffer);
151
        usb_puts ("]" NL);
152
}
153
154
static void parameter_missing (void)
155
{
156
        usb_puts ("# Parameter missing" NL);
157
}
158
159
160 1185 deffi
// ######################
161
// ## Message handlers ##
162
// ######################
163
164 1202 deffi
165 1198 deffi
static void handle_message_ping (char *buffer)
166 1185 deffi
{
167
        usb_puts ("pong" NL);
168
        orbs_set (255, 127, 0, 0, 255, 0);
169
        delay_ms (400);
170
        orbs_set (0, 255, 0, 255, 127, 0);
171
}
172
173 1202 deffi
static void handle_message_start_test_all (char *buffer)
174 1185 deffi
{
175 1202 deffi
        test_all ();
176
}
177
178
static void handle_message_start_test_comm (char *buffer)
179
{
180
        test_comm ();
181
}
182
183
static void handle_message_start_test_component (char *buffer, void (*test_all_fn)(void), void (*test_one_fn)(uint8_t))
184
{
185
        // Find the next parameter
186 1198 deffi
        buffer=find_next_parameter (buffer);
187
188 1202 deffi
        // Initialize a buffer for the component number
189
        uint8_t num=0;
190
191 1198 deffi
        if (!buffer)
192 1202 deffi
                // No paramter found (we could also interpret that as implicit "all")
193
                parameter_missing ();
194 1198 deffi
        else if (serial_match (command_all, buffer))
195 1202 deffi
                // The paramter is "all". Call the all-tests function
196
                test_all_fn ();
197
        else if (serial_number_u8 (&num, buffer))
198
                // The paramter is a number. Call the one-test function
199
                test_one_fn (num);
200 1198 deffi
        else
201 1202 deffi
                // Unknwon parameter
202
                unhandled_parameters (buffer);
203 1185 deffi
}
204
205 1202 deffi
static void test_bom_helper (uint8_t num)
206
{
207
        test_bom (num, true, true);
208
}
209
210
static void test_bom_all_helper (void)
211
{
212
        test_bom_all (true, true);
213
}
214
215
static void handle_message_start_test_bom (char *buffer)
216
{
217
        handle_message_start_test_component (buffer, test_bom_all_helper, test_bom_helper);
218
}
219
220
static void handle_message_start_test_rangefinder (char *buffer)
221
{
222
        handle_message_start_test_component (buffer, test_rangefinder_all, test_rangefinder);
223
}
224
225
static void handle_message_start_test_motor (char *buffer)
226
{
227
        handle_message_start_test_component (buffer, test_motor_all, test_motor);
228
}
229
230
static void handle_message_start_test_encoder (char *buffer)
231
{
232
        handle_message_start_test_component (buffer, test_encoder_all, test_encoder);
233
}
234
235
static void handle_message_start_test (char *buffer)
236
{
237
        // TODO add required comm test
238
        buffer=find_next_parameter (buffer);
239
        if (!buffer)                                         parameter_missing ();
240
        else if (serial_match (command_all        , buffer)) handle_message_start_test_all         (buffer);
241
        else if (serial_match (command_comm       , buffer)) handle_message_start_test_comm        (buffer);
242
        else if (serial_match (command_bom        , buffer)) handle_message_start_test_bom         (buffer);
243
        else if (serial_match (command_rangefinder, buffer)) handle_message_start_test_rangefinder (buffer);
244
        else if (serial_match (command_motor      , buffer)) handle_message_start_test_motor       (buffer);
245
        else if (serial_match (command_encoder    , buffer)) handle_message_start_test_encoder     (buffer);
246
        else                                                 unhandled_parameters (buffer);
247
}
248
249 1198 deffi
static void handle_message_help (char *buffer)
250
{
251 1208 deffi
        usb_puts_P (help_text);
252 1198 deffi
}
253 1185 deffi
254 1198 deffi
255 1183 deffi
// ##########################
256
// ## Messages (receiving) ##
257
// ##########################
258
259 1198 deffi
/** message is 0 terminated */
260
static void handle_message (char *message)
261 1171 deffi
{
262 1183 deffi
#ifdef comm_server_debug
263 1185 deffi
        // Output: "# Received a message, size <size>: [<message>]"
264 1183 deffi
        usb_puts ("# Received a message, size ");
265 1171 deffi
        usb_puti(size);
266 1183 deffi
        usb_puts (": [");
267
        usb_puts ((char *)message);
268
        usb_puts ("]" NL);
269
#endif
270 1171 deffi
271 1185 deffi
        bool handled=false;
272 1198 deffi
        if (serial_match (command_ping      , message)) { handle_message_ping       (message); handled=true; }
273
        if (serial_match (command_start_test, message)) { handle_message_start_test (message); handled=true; }
274
        if (serial_match (command_help      , message)) { handle_message_help       (message); handled=true; }
275 1185 deffi
        // More messages go here
276
277
        if (!handled)
278
        {
279
                usb_puts ("# Warning: unhandled message: [");
280
                usb_puts ((char *)message);
281
                usb_puts ("]" NL);
282
        }
283 1171 deffi
}
284
285
286 1185 deffi
// ###############
287
// ## Debugging ##
288
// ###############
289 1171 deffi
290 1182 deffi
void byte_transmission_test (void)
291
{
292
        uint8_t c;
293
294
        while (1)
295
        {
296
                c=usb_getc ();
297
                usb_puts ("[");
298
                usb_puti (c);
299
                usb_puts ("] ");
300
        }
301
}
302 1171 deffi
303
304 1185 deffi
// ###############
305
// ## Main loop ##
306
// ###############
307
308 1204 deffi
static void ready ()
309
{
310
        usb_puts ("# Ready" NL);
311
}
312
313 1171 deffi
void server_main (void)
314
{
315 1198 deffi
        char buffer[buffer_size];
316 1171 deffi
        uint8_t c;
317
        uint8_t buffer_fill=0;
318 1182 deffi
319
        //byte_transmission_test (); // Does not return
320
321 1185 deffi
        usb_puts (NL);
322
        usb_puts ("# Diagnostic station server mode" NL);
323 1204 deffi
324
        ready ();
325 1171 deffi
326
        while (1)
327
        {
328
                // Do nothing until we receive a byte (this function will return 0 when a character has been read)
329 1182 deffi
                // (Yes, we could use the blocking function for now, but we may need the non-blocking later)
330 1183 deffi
                while (usb_getc_nb ((char *)&c));
331 1171 deffi
332
                if (c=='\r' || c=='\n')
333
                {
334 1182 deffi
                        // A newline character was received. This terminates the message.
335 1171 deffi
336 1182 deffi
                        // Empty lines are ignored.
337
                        if (buffer_fill>0)
338
                        {
339
                                // Add a terminating 0 to the buffer so the string functions won't try to read outside the buffer.
340
                                buffer[buffer_fill]=0;
341
342
                                // Handle the message.
343 1198 deffi
                                handle_message (buffer);
344 1204 deffi
345 1182 deffi
                                // Reset the buffer
346
                                buffer_fill=0;
347
                        }
348 1204 deffi
349
                        // TODO do better, make a function get_message?
350
                        ready ();
351 1171 deffi
                }
352 1202 deffi
                else if (c==8)
353
                {
354
                        // Backspace
355
                        // Of course, the server will never send one, but it's convenient to have for debugging.
356
                        if (buffer_fill>0) --buffer_fill;
357
                }
358 1182 deffi
                else
359
                {
360
                        // If there is enough space left in the buffer, add the character we just received. Leave one byte for a
361
                        // terminating 0. If there is not enough space in the buffer, the rest of the message is ignored.
362
                        if (buffer_fill<buffer_size-1)
363
                        {
364
                                buffer[buffer_fill]=c;
365
                                ++buffer_fill;
366
                        }
367
                }
368
369 1171 deffi
        }
370
}