main.c 18.6 KB
Newer Older
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
/*
 * Copyright (C) 2008, 2009, 2010 Kaspar Schleiser <kaspar@schleiser.de>
 * Copyright (C) 2013 INRIA
 * Copyright (C) 2013 Ludwig Knüpfer <ludwig.knuepfer@fu-berlin.de>
 *
 * This file is subject to the terms and conditions of the GNU Lesser
 * General Public License v2.1. See the file LICENSE in the top level
 * directory for more details.
 */

/**
 * @ingroup     examples
 * @{
 *
 * @file
 * @brief       Default application that shows a lot of functionality of RIOT
 *
 * @author      Kaspar Schleiser <kaspar@schleiser.de>
 * @author      Oliver Hahm <oliver.hahm@inria.fr>
 * @author      Ludwig Knüpfer <ludwig.knuepfer@fu-berlin.de>
 *
 * @}
 */

#include <stdio.h>
#include <string.h>

#include "msg.h"
#include "thread.h"
#include "shell.h"
#include "shell_commands.h"
#include "xtimer.h"
#include "net/gnrc.h"
#include "net/gnrc/netreg.h"
#include "net/gnrc/netif/ieee802154.h"
36
#include "periph/i2c.h"
37
38

#define SEND_INTERVAL (1)
39
40
#define RCV_QUEUE_SIZE (8)
#define MAX_PAYLOAD_LENGTH (32)
41
#define MAGIC_STRING "IBREVAL\0"
42

43
44
#define SHELL_BUFFER_SIZE (256)

45
46
47
48
#ifndef NODE_ID
#error NODE_ID undefined
#endif

Robert Hartung's avatar
Robert Hartung committed
49
/// 512 required for samr21-xpro, 256 sufficient for INGA and telosb
50
51
52
53
54
55
56
57
58
59
60
#ifdef BOARD_SAMR21_XPRO
char dump_thread_stack[1024+256];
char send_thread_stack[1024+256];
#else
char dump_thread_stack[512+256];
char send_thread_stack[512+256];
#endif
//static msg_t dump_thread_msg_queue[RCV_QUEUE_SIZE];
//static msg_t send_thread_msg_queue[RCV_QUEUE_SIZE];

char line_buf[SHELL_BUFFER_SIZE];
61

Robert Hartung's avatar
Robert Hartung committed
62
typedef struct /*__attribute__((packed))*/ {
63
    char magic_string[8];
64
    uint8_t node_id;
Robert Hartung's avatar
Robert Hartung committed
65
    uint8_t seq_nr;
66
    uint8_t temp;
Robert Hartung's avatar
Robert Hartung committed
67
    uint8_t payload_length;
68
69
70
    uint8_t payload[MAX_PAYLOAD_LENGTH];
} eval_message_t;

Robert Hartung's avatar
Robert Hartung committed
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
static eval_message_t eval_message = { .node_id = NODE_ID, .payload_length = 5, .payload = "Hello\0", .magic_string = MAGIC_STRING, .seq_nr = 0 };

kernel_pid_t send_thread_pid = 0;

/**
 * Sends a packet via the network interface
 * 
 * tx [count [delay]]
 * - count: Number of packets to send
 * - delay: Delay in µS between the packets
 */
int shell_tx(int argc, char** argv) {
    (void)argc;
    (void)argv;
    uint8_t count = 1;
    uint32_t delay = 100000; // 100000us = 100ms
    if(argc > 1) {
        count = atoi(argv[1]);
    }
    if(argc > 2) {
        delay = (uint32_t)atol(argv[2]);
    }
    msg_t msg;
    msg.type = 1337;
    msg.content.value = 0;
    //printf("Sending %u packets every %luus\n", count, delay);
    while(count-- > 0) {
        msg_send(&msg, send_thread_pid);
        xtimer_usleep( delay );
    }
    return 0;
}

int shell_payload(int argc, char** argv) {
    /// argv[0] is the function name
    if(argc == 1) {
        printf("Payload is: '%s'\n", eval_message.payload);
    } else {
        strcpy((char*)eval_message.payload, argv[1]);
        eval_message.payload_length = strlen(argv[1]);
111
        //eval_message.payload_length = strncpy( (char*)eval_message.payload, argv[1], MAX_PAYLOAD_LENGTH);
Robert Hartung's avatar
Robert Hartung committed
112
113
114
115
    }
    return 0;
}

116
117
118
119
120
121
122
123
int shell_memdump(int argc, char** argv) {
    (void) argc;
    (void) argv;
    //irq_disable();
    /// TODO(rh): dump memory
    const uint8_t *addr = (const uint8_t*)0x1800;
    while(addr < (const uint8_t*)0x2600) {
        uint8_t i = 0;
124
        printf("%04X: ",(unsigned int)addr);
125
        while(i<0xF) {
126
            printf("%02X ", (unsigned int)(*(addr+i)));
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
            i++;
        }
        i = 0;
        while(i<0xF) {
            char c = *(addr+i);
            printf("%c", (c >= ' ' && c <= '~') ? c : '.');
            i++;
        }
        addr += 0xF;
        puts("");
    }
    //irq_enable();
    return 0;
}

142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
#ifdef BOARD_INGA_BLUE
int shell_temp(int argc, char** argv) {
    (void) argc;
    (void) argv;

    // uint8_t result;
    uint8_t result[2];

	i2c_acquire(0);
    //i2c_read_reg(0, 0x48, 0x00, &result);
	i2c_read_regs(0, 0x48, 0x00, result, 2);
	i2c_release(0);
    //uint16_t temp = (result[0] << 8) | (result[1] >> 4);
	//printf("temperature is %d %d\n", result[0], result[1]);
    //printf("temperature=%u\n", temp);
    printf("temperature=%u.%d\n", result[0], (result[1]>>4) );

    return 0;
}
#endif

Robert Hartung's avatar
Robert Hartung committed
163
164
165
shell_command_t eval_shell_commands[] = {
    {"tx", "Sends packets", shell_tx},
    {"payload", "Sets or prints the payload", shell_payload},
166
    {"memdump", "Prints the memory", shell_memdump},
167
168
169
#ifdef BOARD_INGA_BLUE
    {"temp", "Read temperatur", shell_temp},
#endif
Robert Hartung's avatar
Robert Hartung committed
170
171
    {NULL, NULL, NULL}
};
172

173
/*
174
175
176
177
178
179
180
static void _dump(gnrc_pktsnip_t *pkt) {
    gnrc_pktsnip_t *snip = pkt;
    gnrc_pktsnip_t *payload = NULL;
    uint8_t *data;
    eval_message_t *packet;
    gnrc_netif_hdr_t *hdr;
    uint8_t len;
181
182
183
184
    char serialbuffer[256];

    printf("serialbuffer: from %p to %p\n", serialbuffer, serialbuffer+256);
    
185
186
187
188
189
190
191
192
    // printf("_dump: %d %d\n", gnrc_netreg_num(GNRC_NETTYPE_UNDEF, 0), gnrc_netreg_num(GNRC_NETTYPE_NETIF, 0));
    while(snip != NULL) {
        switch(snip->type)  {
            case GNRC_NETTYPE_UNDEF :
                payload = snip;
            break;
            case GNRC_NETTYPE_NETIF :
                hdr = snip->data;
Robert Hartung's avatar
Robert Hartung committed
193
194
                //printf("HDR: %d %d %d\n", hdr->rssi, hdr->lqi, hdr->crc_valid);
                //puts("OK");
195
                
196
197
                packet = (eval_message_t*)payload->data;
                
Robert Hartung's avatar
Robert Hartung committed
198
199
                if(hdr->crc_valid) {
                    if(strcmp(packet->magic_string, MAGIC_STRING) == 0) {
200
                        puts("<magic:found");
Robert Hartung's avatar
Robert Hartung committed
201
                        int length = sprintf(serialbuffer, "%u|%u|%d|%u", packet->node_id, packet->seq_nr, hdr->rssi, hdr->lqi);
202
203
204
205
206
207
208
209
210
211
                        if(length > 0) {
                            printf("<magic:ok=%u/%u\n", length, strlen( serialbuffer ));
                            uint8_t sum = 0;
                            for(uint8_t i=0; i<length; i++) {
                                sum += serialbuffer[i];
                            }
                            printf("<%s=%02X\n", serialbuffer, sum);
                        }
                        else {
                            printf("<magic:length_error:%d\n", length);
Robert Hartung's avatar
Robert Hartung committed
212
213
                        }
                    } else {
214
                        printf("<valid\n");
Robert Hartung's avatar
Robert Hartung committed
215
216
                        /// This is another packet, ignore it!
                    }
217
                } else {
218
                    /// Make sure a corrupt packet does not exceed payload size
219
                    len = payload->size;
Robert Hartung's avatar
Robert Hartung committed
220
221
                    if(len > sizeof(eval_message_t)) {
                        len = sizeof(eval_message_t);
222
                    }
223
                    /// Pointer to data
224
                    data = (uint8_t*)payload->data;
Robert Hartung's avatar
Robert Hartung committed
225
226
227
                    uint8_t i,
                            sum = 0,
                            length = 0;
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
                    int tmp;
                    tmp = snprintf(&serialbuffer[length], sizeof(serialbuffer) - length, "%d|%u|%u|", hdr->rssi, hdr->lqi, len);
                    if(tmp > 0) {
                        length += tmp;
                        /// Print each single byte
                        for(i=0; i<len; i++) {
                            /// Even though " %02X" is only three characters long, we need to pass 4 because of the null terminator for the string!
                            tmp = snprintf(&serialbuffer[length], sizeof(serialbuffer) - length, " %02X", data[i]);
                            if(tmp > 0) {
                                length += tmp;
                            } else {
                                puts("!length error 2");
                                break;
                            }
                        }
Robert Hartung's avatar
Robert Hartung committed
243

244
245
                        for(i=0; i<length; i++) {
                            sum += serialbuffer[i];
246
                        }
247
248
249
                        printf("<%s=%02X\n", serialbuffer, sum);
                    } else {
                        puts("!length error 1");
250
251
252
253
254
255
256
257
258
259
260
                    }
                }
            break;
            default :
                printf("snip of type %d\n", snip->type);
            break;
        }
        snip = snip->next;
    }
    gnrc_pktbuf_release(pkt);
}
261
262
263
*/

static char serialbuffer[256];
264
265
266
267

void *dump_thread(void *arg)
{
    (void) arg;
268
    msg_t dump_thread_msg_queue[RCV_QUEUE_SIZE];
269
270
271
272
273
274
    msg_init_queue(dump_thread_msg_queue, RCV_QUEUE_SIZE);

    gnrc_netreg_entry_t me_reg = GNRC_NETREG_ENTRY_INIT_PID(GNRC_NETREG_DEMUX_CTX_ALL, sched_active_pid);
    gnrc_netreg_register(GNRC_NETTYPE_UNDEF, &me_reg);

    msg_t msg;
275
276
277
278
279
280
281
282
    gnrc_pktsnip_t *snip = NULL;
    gnrc_pktsnip_t *payload = NULL;
    uint8_t *data;
    eval_message_t *packet;
    gnrc_netif_hdr_t *hdr;
    uint8_t len;
    memset(serialbuffer, sizeof(serialbuffer), 0x00);

283
284
285
286
287
288
289
290
    while(1) {
        if(msg_receive(&msg) != 1) {
            puts("Unable to receive message");
            continue;
        }
        //printf("[dump_thread] message received: %d\n", msg.type);
        switch(msg.type) {
            case GNRC_NETAPI_MSG_TYPE_RCV :
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
                //irq_disable();
                //_dump( msg.content.ptr );

                snip = msg.content.ptr;
                payload = NULL;
                
                // printf("_dump: %d %d\n", gnrc_netreg_num(GNRC_NETTYPE_UNDEF, 0), gnrc_netreg_num(GNRC_NETTYPE_NETIF, 0));
                while(snip != NULL) {
                    switch(snip->type)  {
                        case GNRC_NETTYPE_UNDEF :
                            payload = snip;
                        break;
                        case GNRC_NETTYPE_NETIF :
                            hdr = snip->data;
                            //printf("HDR: %d %d %d\n", hdr->rssi, hdr->lqi, hdr->crc_valid);
                            //puts("OK");
                            if(payload == NULL) {
                                puts("!whoops? NULL pointer");
                            }
                            packet = (eval_message_t*)payload->data;
                            
                            if(hdr->crc_valid) {
                                if(strcmp(packet->magic_string, MAGIC_STRING) == 0) {
                                    puts("<magic:found");
                                    int length = sprintf(serialbuffer, "%u|%u|%d|%u", packet->node_id, packet->seq_nr, hdr->rssi, hdr->lqi);
                                    if(length > 0) {
                                        printf("<magic:ok=%u/%u\n", length, strlen( serialbuffer ));
                                        uint8_t sum = 0;
                                        for(uint8_t i=0; i<length; i++) {
                                            sum += serialbuffer[i];
                                        }
                                        printf("<%s=%02X\n", serialbuffer, sum);
                                    }
                                    else {
                                        printf("<magic:length_error:%d\n", length);
                                    }
                                } else {
                                    printf("<valid\n");
                                    /// This is another packet, ignore it!
                                }
                            } else {
                                /* Make sure a corrupt packet does not exceed payload size */
                                len = payload->size;
                                if(len > sizeof(eval_message_t)) {
                                    len = sizeof(eval_message_t);
                                }
                                /* Pointer to data */
                                data = (uint8_t*)payload->data;
                                uint8_t i,
                                        sum = 0,
                                        length = 0;
                                int tmp;
                                tmp = snprintf(&serialbuffer[length], sizeof(serialbuffer) - length, "%d|%u|%u|", hdr->rssi, hdr->lqi, len);
                                if(tmp > 0) {
                                    length += tmp;
                                    /* Print each single byte */
                                    for(i=0; i<len; i++) {
                                        /// Even though " %02X" is only three characters long, we need to pass 4 because of the null terminator for the string!
                                        tmp = snprintf(&serialbuffer[length], sizeof(serialbuffer) - length, " %02X", data[i]);
                                        if(tmp > 0) {
                                            length += tmp;
                                        } else {
                                            puts("!length error 2");
                                            break;
                                        }
                                    }

                                    for(i=0; i<length; i++) {
                                        sum += serialbuffer[i];
                                    }
                                    printf("<%s=%02X\n", serialbuffer, sum);
                                } else {
                                    puts("!length error 1");
                                }
                            }
                        break;
                        default :
                            printf("snip of type %d\n", snip->type);
                        break;
                    }
                    snip = snip->next;
                }
                gnrc_pktbuf_release(msg.content.ptr);

                //irq_enable();
376
377
378
            break;
            default :
                puts("ERROR: Unknown message type???");
379
                //gnrc_pktbuf_release( msg.content.ptr );
380
381
382
383
384
385
386
            break;
        }
    }
    puts("END OF dump_thread");
    return NULL;
}

387
388
static char serialbuffer2[32];

389
390
void *send_thread(void *arg)
{
391
    gnrc_netif_t *ieee802154_netif = arg;
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415

    /*
    struct iovec vector[2];
    uint8_t hdr[IEEE802154_MAX_HDR_LEN];
    uint8_t src[2] = {1,1};
    uint8_t dst[2] = {0xFF, 0xFF};
    //uint8_t pan[2] = {0x12, 0x34};
    le_uint16_t pan = {.u16 = 0x1234};
    uint8_t seq = 0;

    int res = ieee802154_set_frame_hdr(hdr, src, 2, dst, 2, pan, pan, NETDEV_IEEE802154_RAW | IEEE802154_FCF_TYPE_DATA, seq);

    vector[0].iov_base = hdr;
    vector[0].iov_len = (size_t)res;

    vector[1].iov_base = data;
    vector[1].iov_len = size;
    */

    size_t addr_len = 0;
    uint8_t addr[GNRC_NETIF_L2ADDR_MAXLEN];
    gnrc_pktsnip_t *pkt, *hdr;
    gnrc_netif_hdr_t *nethdr;

416
417
    netopt_enable_t enable = true;
    netopt_enable_t disable = false;
418
419
    int ret;
    ret = gnrc_netapi_set(ieee802154_netif->pid, NETOPT_PROMISCUOUSMODE, 0, &enable, sizeof(netopt_enable_t));
420
421
422
    if(ret < 0) {
        puts("Unable to set promiscous mode");
    }
423
    ret = gnrc_netapi_set(ieee802154_netif->pid, NETOPT_AUTOACK, 0, &disable, sizeof(netopt_enable_t));
424
425
426
    if(ret < 0) {
        puts("Unable to disable auto ack");
    }
427
    ret = gnrc_netapi_set(ieee802154_netif->pid, NETOPT_CSMA, 0, &disable, sizeof(netopt_enable_t));
428
429
430
    if(ret < 0) {
        puts("Unable to disable CSMA");
    }
431
432
433

    uint8_t retrans = 0;
    ret = gnrc_netapi_set(ieee802154_netif->pid, NETOPT_RETRANS, 0, &retrans, sizeof(retrans));
434
435
436
    if(ret < 0) {
        puts("Unable to set retrans = 0");
    }
437
438
439

    int8_t retries = 7;
    ret = gnrc_netapi_set(ieee802154_netif->pid, NETOPT_CSMA_RETRIES, 0, &retries, sizeof(retries));
440
441
442
    if(ret < 0) {
        puts("Unable to set CSMA retries = 0");
    }
Robert Hartung's avatar
Robert Hartung committed
443

444
    uint8_t flags = 0 | GNRC_NETIF_HDR_FLAGS_BROADCAST;
Robert Hartung's avatar
Robert Hartung committed
445
446
    eval_message.payload_length = snprintf((char*)eval_message.payload, MAX_PAYLOAD_LENGTH, "Hello from %2d", NODE_ID);

447
    msg_t send_thread_msg_queue[RCV_QUEUE_SIZE];
Robert Hartung's avatar
Robert Hartung committed
448
449
    msg_init_queue(send_thread_msg_queue, RCV_QUEUE_SIZE);
    msg_t msg;
450
451
    
    memset(serialbuffer, sizeof(serialbuffer2), 0x00);
452
453
    
    while(1) {
Robert Hartung's avatar
Robert Hartung committed
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
        msg_receive(&msg);
        (void)msg;

        /*
        //printf("[dump_thread] message received: %d\n", msg.type);
        switch(msg.type) {
            case GNRC_NETAPI_MSG_TYPE_RCV :
                _dump( msg.content.ptr );
            break;
            default :
                puts("ERROR: Unknown message type???");
                /// gnrc_pktbuf_release( msg.content.ptr );
            break;
        }

469
        xtimer_sleep(SEND_INTERVAL);	
Robert Hartung's avatar
Robert Hartung committed
470
        */
471

Robert Hartung's avatar
Robert Hartung committed
472
473
474
475
476
477
        //printf("send... %d", sizeof(eval_message) - MAX_PAYLOAD_LENGTH + payload_length);
        //printf("send...");
        /* Prepare packet */
        eval_message.seq_nr += 1;
        
        pkt = gnrc_pktbuf_add(NULL, &eval_message, sizeof(eval_message) - MAX_PAYLOAD_LENGTH + eval_message.payload_length, GNRC_NETTYPE_UNDEF);
478
479
480
481
482
483
484
485
486
487
488
489
490
491
        if (pkt == NULL) {
            puts("ERROR: packet buffer full");
            return NULL;
        }

        hdr = gnrc_netif_hdr_build(NULL, 0, addr, addr_len);
        if (hdr == NULL) {
            puts("ERROR: packet buffer full");
            gnrc_pktbuf_release(pkt);
            return NULL;
        }
        LL_PREPEND(pkt, hdr);
        nethdr = (gnrc_netif_hdr_t *)hdr->data;
        nethdr->flags = flags;
492
493
494
        ret = gnrc_netapi_send(ieee802154_netif->pid, pkt);
        if (ret < 1) {
            printf("ERROR: unable to send: %d\n", ret);
495
496
            gnrc_pktbuf_release(pkt);
        } else {
497
            //irq_disable();
Robert Hartung's avatar
Robert Hartung committed
498
            uint8_t sum = 0;
499
            uint8_t length = snprintf(serialbuffer2, sizeof(serialbuffer2), "%u", eval_message.seq_nr);
Robert Hartung's avatar
Robert Hartung committed
500
            for(uint8_t i=0; i<length; i++) {
501
                sum += serialbuffer2[i];
Robert Hartung's avatar
Robert Hartung committed
502
            }
503
504
            printf(">%s=%02X\n", serialbuffer2, sum);
            //irq_enable();
505
506
507
508
509
510
511
512
        }
    }
    return NULL;
}

int main(void)
{
    /// +1 -> INGA working, but TelosB/Sky not
513
    thread_create(dump_thread_stack, sizeof(dump_thread_stack), THREAD_PRIORITY_MAIN + 1, THREAD_CREATE_STACKTEST, dump_thread, NULL, "dump_thread");
514
515
516

    int res = i2c_init_master(I2C_DEV(0), 2);
    printf("i2c init: %s\n", res == 0 ? "OK\n" : "FAILED\n");
517
518
519
    
    gnrc_netif_t *netif = NULL;
    if((netif = gnrc_netif_iter(netif))) {
520
        gnrc_netif_t *ieee802154_netif = netif;
521
        printf("Found gnrc netif: %d %d\n", netif->pid, ieee802154_netif->pid);
522
        /// +2 -> INGA working, but TelosB/Sky not
523
        send_thread_pid = thread_create(send_thread_stack, sizeof(send_thread_stack), THREAD_PRIORITY_MAIN + 2, THREAD_CREATE_STACKTEST, send_thread, ieee802154_netif, "send_thread");
524
525
    }
    else {
526
527
        puts("Unable to find netif");
    }
528
    
529
    (void) puts("Welcome to RIOT!");
530
531
532
533
534
535
536
    printf("This is node %d.\n", NODE_ID);

    printf("line_buf from %p to %p\n", line_buf, line_buf + sizeof(line_buf));
    printf("serialbuffer: from %p to %p\n", serialbuffer, serialbuffer+sizeof(serialbuffer));
    printf("serialbuffer2: from %p to %p\n", serialbuffer2, serialbuffer2+sizeof(serialbuffer2));

    shell_run(eval_shell_commands, line_buf, SHELL_BUFFER_SIZE);
537
538

    return 0;
539
}