Forked from
Robert Hartung / ieee802154-radio-eval
1 commit behind, 2 commits ahead of the upstream repository.
-
Torben Petersen authoredTorben Petersen authored
main.c 18.69 KiB
/*
* 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 SEND_INTERVAL (1)
#define RCV_QUEUE_SIZE (8)
#define MAX_PAYLOAD_LENGTH (32)
#define MAGIC_STRING "IBREVAL\0"
#define SHELL_BUFFER_SIZE (256)
#ifndef NODE_ID
#error NODE_ID undefined
#endif
/// 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];
typedef struct /*__attribute__((packed))*/ {
char magic_string[8];
uint8_t node_id;
uint8_t seq_nr;
uint8_t temp;
uint8_t payload_length;
uint8_t payload[MAX_PAYLOAD_LENGTH];
} eval_message_t;
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);
}
return 0;
}
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, 0);
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
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
{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;
//printf("HDR: %d %d %d\n", hdr->rssi, hdr->lqi, hdr->crc_valid);
//puts("OK");
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(pkt);
}
*/
static char serialbuffer[256];
void *dump_thread(void *arg)
{
(void) arg;
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 );
break;
}
}
puts("END OF dump_thread");
return NULL;
}
static char serialbuffer2[32];
void *send_thread(void *arg)
{
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;
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];
msg_init_queue(send_thread_msg_queue, RCV_QUEUE_SIZE);
msg_t msg;
memset(serialbuffer, sizeof(serialbuffer2), 0x00);
while(1) {
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;
}
xtimer_sleep(SEND_INTERVAL);
*/
//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);
gnrc_pktbuf_release(pkt);
} else {
//irq_disable();
uint8_t sum = 0;
uint8_t length = snprintf(serialbuffer2, sizeof(serialbuffer2), "%u", eval_message.seq_nr);
for(uint8_t i=0; i<length; i++) {
sum += serialbuffer2[i];
}
printf(">%s=%02X\n", serialbuffer2, sum);
//irq_enable();
}
}
return NULL;
}
int main(void)
{
(void) puts("Welcome to RIOT!");
/// +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(I2C_DEV(0));
#if defined(BOARD_INGA_BLUE) || defined(BOARD_INGA_RED)
i2c_init(I2C_DEV(0));
#endif
//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");
}
else {
puts("Unable to find netif");
}
(void) puts("Welcome to RIOT!");
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);
return 0;
}