Skip to content
Snippets Groups Projects
main.c 18.6 KiB
Newer Older
  • Learn to ignore specific revisions
  • /*
     * 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"
    
    #include "periph/i2c.h"
    
    #define RCV_QUEUE_SIZE (8)
    #define MAX_PAYLOAD_LENGTH (32)
    
    #define MAGIC_STRING "IBREVAL\0"
    
    #define SHELL_BUFFER_SIZE (256)
    
    
    Robert Hartung's avatar
    Robert Hartung committed
    /// 512 required for samr21-xpro, 256 sufficient for INGA and telosb
    
    #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];
    
    Robert Hartung's avatar
    Robert Hartung committed
    typedef struct /*__attribute__((packed))*/ {
    
    Robert Hartung's avatar
    Robert Hartung committed
        uint8_t seq_nr;
    
    Robert Hartung's avatar
    Robert Hartung committed
        uint8_t payload_length;
    
        uint8_t payload[MAX_PAYLOAD_LENGTH];
    } eval_message_t;
    
    
    Robert Hartung's avatar
    Robert Hartung committed
    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]);
    
            //eval_message.payload_length = strncpy( (char*)eval_message.payload, argv[1], MAX_PAYLOAD_LENGTH);
    
    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;
    
            printf("%04X: ",(unsigned int)addr);
    
            while(i<0xF) {
    
                printf("%02X ", (unsigned int)(*(addr+i)));
    
                i++;
            }
            i = 0;
            while(i<0xF) {
                char c = *(addr+i);
                printf("%c", (c >= ' ' && c <= '~') ? c : '.');
                i++;
            }
            addr += 0xF;
            puts("");
        }
        //irq_enable();
        return 0;
    }
    
    
    #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
    shell_command_t eval_shell_commands[] = {
        {"tx", "Sends packets", shell_tx},
        {"payload", "Sets or prints the payload", shell_payload},
    
        {"memdump", "Prints the memory", shell_memdump},
    
    #ifdef BOARD_INGA_BLUE
        {"temp", "Read temperatur", shell_temp},
    #endif
    
    Robert Hartung's avatar
    Robert Hartung committed
        {NULL, NULL, NULL}
    };
    
    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;
    
        char serialbuffer[256];
    
        printf("serialbuffer: from %p to %p\n", serialbuffer, serialbuffer+256);
        
    
        // 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
                    //printf("HDR: %d %d %d\n", hdr->rssi, hdr->lqi, hdr->crc_valid);
                    //puts("OK");
    
    Robert Hartung's avatar
    Robert Hartung committed
                    if(hdr->crc_valid) {
                        if(strcmp(packet->magic_string, MAGIC_STRING) == 0) {
    
                            puts("<magic:found");
    
    Robert Hartung's avatar
    Robert Hartung committed
                            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);
    
    Robert Hartung's avatar
    Robert Hartung committed
                            }
                        } else {
    
                            printf("<valid\n");
    
    Robert Hartung's avatar
    Robert Hartung committed
                            /// This is another packet, ignore it!
                        }
    
                        /// Make sure a corrupt packet does not exceed payload size
    
    Robert Hartung's avatar
    Robert Hartung committed
                        if(len > sizeof(eval_message_t)) {
                            len = sizeof(eval_message_t);
    
                        /// Pointer to data
    
    Robert Hartung's avatar
    Robert Hartung committed
                        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(pkt);
    }
    
    */
    
    static char serialbuffer[256];
    
        msg_t dump_thread_msg_queue[RCV_QUEUE_SIZE];
    
        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;
    
        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);
    
    
        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 :
    
                    //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();
    
                break;
                default :
                    puts("ERROR: Unknown message type???");
    
                    //gnrc_pktbuf_release( msg.content.ptr );
    
    static char serialbuffer2[32];
    
    
        gnrc_netif_t *ieee802154_netif = arg;
    
    
        /*
        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;
    
    
        netopt_enable_t enable = true;
        netopt_enable_t disable = false;
    
        int ret;
        ret = gnrc_netapi_set(ieee802154_netif->pid, NETOPT_PROMISCUOUSMODE, 0, &enable, sizeof(netopt_enable_t));
    
        if(ret < 0) {
            puts("Unable to set promiscous mode");
        }
    
        ret = gnrc_netapi_set(ieee802154_netif->pid, NETOPT_AUTOACK, 0, &disable, sizeof(netopt_enable_t));
    
        if(ret < 0) {
            puts("Unable to disable auto ack");
        }
    
        ret = gnrc_netapi_set(ieee802154_netif->pid, NETOPT_CSMA, 0, &disable, sizeof(netopt_enable_t));
    
        if(ret < 0) {
            puts("Unable to disable CSMA");
        }
    
    
        uint8_t retrans = 0;
        ret = gnrc_netapi_set(ieee802154_netif->pid, NETOPT_RETRANS, 0, &retrans, sizeof(retrans));
    
        if(ret < 0) {
            puts("Unable to set retrans = 0");
        }
    
    
        int8_t retries = 7;
        ret = gnrc_netapi_set(ieee802154_netif->pid, NETOPT_CSMA_RETRIES, 0, &retries, sizeof(retries));
    
        if(ret < 0) {
            puts("Unable to set CSMA retries = 0");
        }
    
        uint8_t flags = 0 | GNRC_NETIF_HDR_FLAGS_BROADCAST;
    
    Robert Hartung's avatar
    Robert Hartung committed
        eval_message.payload_length = snprintf((char*)eval_message.payload, MAX_PAYLOAD_LENGTH, "Hello from %2d", NODE_ID);
    
    
        msg_t send_thread_msg_queue[RCV_QUEUE_SIZE];
    
    Robert Hartung's avatar
    Robert Hartung committed
        msg_init_queue(send_thread_msg_queue, RCV_QUEUE_SIZE);
        msg_t msg;
    
        
        memset(serialbuffer, sizeof(serialbuffer2), 0x00);
    
    Robert Hartung's avatar
    Robert Hartung committed
            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;
            }
    
    
    Robert Hartung's avatar
    Robert Hartung committed
            */
    
    Robert Hartung's avatar
    Robert Hartung committed
            //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);
    
            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;
    
            ret = gnrc_netapi_send(ieee802154_netif->pid, pkt);
            if (ret < 1) {
                printf("ERROR: unable to send: %d\n", ret);
    
                //irq_disable();
    
    Robert Hartung's avatar
    Robert Hartung committed
                uint8_t sum = 0;
    
                uint8_t length = snprintf(serialbuffer2, sizeof(serialbuffer2), "%u", eval_message.seq_nr);
    
    Robert Hartung's avatar
    Robert Hartung committed
                for(uint8_t i=0; i<length; i++) {
    
                    sum += serialbuffer2[i];
    
                printf(">%s=%02X\n", serialbuffer2, sum);
                //irq_enable();
    
            }
        }
        return NULL;
    }
    
    int main(void)
    {
        /// +1 -> INGA working, but TelosB/Sky not
    
        thread_create(dump_thread_stack, sizeof(dump_thread_stack), THREAD_PRIORITY_MAIN + 1, THREAD_CREATE_STACKTEST, dump_thread, NULL, "dump_thread");
    
    
        int res = i2c_init_master(I2C_DEV(0), 2);
        printf("i2c init: %s\n", res == 0 ? "OK\n" : "FAILED\n");
    
        
        gnrc_netif_t *netif = NULL;
        if((netif = gnrc_netif_iter(netif))) {
    
            gnrc_netif_t *ieee802154_netif = netif;
    
            printf("Found gnrc netif: %d %d\n", netif->pid, ieee802154_netif->pid);
    
            /// +2 -> INGA working, but TelosB/Sky not
    
            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");
    
        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);