From fa94cecf1fc4e99c9f84cef2d45462a09f6249ff Mon Sep 17 00:00:00 2001 From: Oliver Hahm Date: Thu, 14 Apr 2011 13:47:24 +0200 Subject: [PATCH 01/10] [core mutex] * fixed bug from r5b3209ea --- core/mutex.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/core/mutex.c b/core/mutex.c index a9d4722ea3..3b28c543a4 100644 --- a/core/mutex.c +++ b/core/mutex.c @@ -103,6 +103,13 @@ void mutex_wake_waiters(struct mutex_t *mutex, int flags) { DEBUG("%s: waking up waiters.\n", fk_thread->name); queue_node_t *next = queue_remove_head(&(mutex->queue)); + + /* queue is empty */ + if (!next) { + mutex->val = 0; + return; + } + tcb* process = (tcb*)next->data; sched_set_status(process, STATUS_PENDING); From 90ad73e0f8690410c5bed441065539a0af3e940e Mon Sep 17 00:00:00 2001 From: Oliver Hahm Date: Thu, 14 Apr 2011 13:49:18 +0200 Subject: [PATCH 02/10] [sys shell shell_commands] * added missing header include --- sys/shell/shell_commands.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sys/shell/shell_commands.c b/sys/shell/shell_commands.c index 5223597d6c..932516a4b8 100644 --- a/sys/shell/shell_commands.c +++ b/sys/shell/shell_commands.c @@ -1,4 +1,5 @@ #include +#include const shell_command_t _shell_command_list[] = { #ifdef MODULE_PS From c1a1ea405a597df8ad2dfb781bb3df452366e3aa Mon Sep 17 00:00:00 2001 From: Oliver Hahm Date: Thu, 14 Apr 2011 13:52:46 +0200 Subject: [PATCH 03/10] [projects WEAtHeR_stable] * initial commit for WEAtHeR project in stable branch --- projects/WEAtHeR_stable/Jamfile | 5 + projects/WEAtHeR_stable/main.c | 401 ++++++++++++++++++ .../WEAtHeR_stable/protocol_msg_gateway.c | 78 ++++ .../WEAtHeR_stable/protocol_msg_gateway.h | 18 + projects/WEAtHeR_stable/tests/hello-world | 13 + projects/WEAtHeR_stable/weather_cc1100.c | 43 ++ projects/WEAtHeR_stable/weather_protocol.h | 43 ++ projects/WEAtHeR_stable/weather_routing.c | 86 ++++ projects/WEAtHeR_stable/weather_routing.h | 18 + projects/WEAtHeR_stable/weather_rtc.c | 42 ++ 10 files changed, 747 insertions(+) create mode 100644 projects/WEAtHeR_stable/Jamfile create mode 100644 projects/WEAtHeR_stable/main.c create mode 100644 projects/WEAtHeR_stable/protocol_msg_gateway.c create mode 100644 projects/WEAtHeR_stable/protocol_msg_gateway.h create mode 100755 projects/WEAtHeR_stable/tests/hello-world create mode 100644 projects/WEAtHeR_stable/weather_cc1100.c create mode 100644 projects/WEAtHeR_stable/weather_protocol.h create mode 100644 projects/WEAtHeR_stable/weather_routing.c create mode 100644 projects/WEAtHeR_stable/weather_routing.h create mode 100644 projects/WEAtHeR_stable/weather_rtc.c diff --git a/projects/WEAtHeR_stable/Jamfile b/projects/WEAtHeR_stable/Jamfile new file mode 100644 index 0000000000..0771f19058 --- /dev/null +++ b/projects/WEAtHeR_stable/Jamfile @@ -0,0 +1,5 @@ +SubDir TOP projects WEAtHeR_stable ; + +Module WEAtHeR_stable : main.c weather_routing.c protocol_msg_gateway.c weather_cc1100.c weather_rtc.c : ltc4150 cc110x sht11 gpioint shell shell_commands posix_io uart0 auto_init rtc ; + +UseModule WEAtHeR_stable ; diff --git a/projects/WEAtHeR_stable/main.c b/projects/WEAtHeR_stable/main.c new file mode 100644 index 0000000000..2f885b07a9 --- /dev/null +++ b/projects/WEAtHeR_stable/main.c @@ -0,0 +1,401 @@ +/* stdlib includes */ +#include +#include +#include +#include + +/* core includes */ +#include +#include +#include +#include + +//#define ENABLE_DEBUG +#include + +/* sensors and actors */ +#include +#include +#include + +/* shell */ +#include +#include +#include + +/* transceiver */ +#include +#include + +/* real time clock */ +#include + +/* application header */ +#include "weather_routing.h" +#include "weather_protocol.h" +#include "protocol_msg_gateway.h" + +/* some local defines */ +#define SECOND (1000 * 1000) +#define MINUTE (1 * SECOND) + +/* size of weather data packet without hop list */ +#define EMPTY_WDP_SIZE (sizeof(weather_data_pkt_t) - MAX_HOP_LIST) + +/* default values */ +#define DEFAULT_INTERVAL (5 * SECOND) + +/* stack space for threads */ +#define SHELL_STACK_SIZE (4048) +#define PH_STACK_SIZE (4048) + + +char shell_stack_buffer[SHELL_STACK_SIZE]; +char ph_stack_buffer[PH_STACK_SIZE]; + +/* per default acting only as relay */ +static uint8_t data_sink = 0; +static uint8_t data_src = 0; + +cib_t cib; +uint16_t pkts_processed = 0; + +static uint32_t sending_interval = DEFAULT_INTERVAL; + +extern uint8_t gossip_probability; +extern void _cc110x_get_set_address_handler(char *addr); +extern void _cc110x_get_set_channel_handler(char *chan); +extern void _date_handler(char* c); + +/* function prototypes */ +static void weather_send(char* unused); +static void weather_sink(char* unused); +static void set_interval(char* interval); +static void set_probability(char* prob); +static void print_cc1100_info(char* unused); +static void stat_handler(char* unused); + +int shell_readc() { + char c = 0; + posix_read(uart0_handler_pid, &c, 1); + return c; +} + +void shell_putchar(int c) { + putchar(c); +} + +/* shell commands */ +shell_t shell; +const shell_command_t sc[] = { + {"sender", weather_send}, + {"sink", weather_sink}, + {"int", set_interval}, + {"prob", set_probability}, + {"cc1100", print_cc1100_info}, + {"addr", _cc110x_get_set_address_handler}, + {"date", _date_handler}, + {"stats", stat_handler}, + {NULL, NULL}}; + +static void shell_runner(void) { + posix_open(uart0_handler_pid, 0); + shell_init(&shell, shell_readc, shell_putchar); + shell.command_list = sc; + shell_run(&shell); +} + +static void weather_send(char* unused) { + if (data_src) { + data_src = 0; + puts("Disabling data source mode."); + } + else { + data_src = 1; + puts("Enabling data source mode."); + } +} + +static void weather_sink(char* unused) { + if (data_sink) { + data_sink = 0; + puts("Disabling data sink mode."); + } + else { + data_sink = 1; + puts("Enabling data sink mode."); + } +} + +static void set_interval(char* interval) { + uint16_t a; + + a = atoi(interval+4); + if (strlen(interval) > 4) { + printf("[WEAtHeR] Set interval to %u\n ", a); + sending_interval = a * SECOND; + } + else { + printf("[WEAtHeR] Current interval is %lu\n ", (sending_interval / SECOND)); + } +} + +static void set_probability(char* prob) { + uint16_t a; + + a = atoi(prob+4); + if (strlen(prob) > 4) { + printf("[WEAtHeR] Set probability to %hu\n ", a); + gossip_probability = a; + } + else { + printf("[WEAtHeR] Current probability is %hu\n ", gossip_probability); + } +} + +static void print_cc1100_info(char* unused) { + puts("=================================================="); + cc1100_print_statistic(); + puts("--------------------------------------------------"); + cc1100_print_config(); + puts("=================================================="); +} + +static void stat_handler(char* unused) { + extern uint16_t pkts_received; + extern uint16_t pkts_success; + extern uint16_t pkts_dup; + extern uint16_t pkts_dropped; + printf(" ::::::::::::::::::::::::::: \n"); + printf(" :: Packets received: %u ::\n", pkts_received); + printf(" :: Packets processed: %u ::\n", pkts_processed); + printf(" :: Packets success: %u ::\n", pkts_success); + printf(" :: Packets dup: %u ::\n", pkts_dup); + printf(" :: Packets dropped: %u ::\n", pkts_dropped); + printf(" ::::::::::::::::::::::::::: \n"); +} + +/* packet handling */ +static void handle_packet(void* msg, int msg_size, packet_info_t* packet_info) { + pkts_processed++; + weather_packet_header_t *header = (weather_packet_header_t*) msg; + + printf("\n\t Pkt received from phy: %u (%u bytes)\n" + "\t -> SEQ: %u | TYPE: %u | SRC: %hu \n\n", + packet_info->phy_src, + msg_size, + header->seq_nr, + header->type, + header->src + ); + /* packet origins at current node, just ignore it */ + if (header->src == cc1100_get_address()) { + return; + } + /* while not acting as sink and packet contains data, route the packet */ + if (!data_sink) { + if (header->type == WEATHER_DATA) { + weather_data_pkt_t* wdp = (weather_data_pkt_t*) msg; + DEBUG("$0;%hu;%hu;%lu;%u;%.2f;%.2f;%.2f;%.2f\n", + header->src, + 0, + wdp->timestamp, + 0, + wdp->temperature, + wdp->relhum, + wdp->relhum_temp, + wdp->energy); + DEBUG("Not for me, routing, baby!\n"); + route_packet(msg, msg_size); + } + + return; + } + + /* if current node acts as sink, handle packet */ + switch (header->type) { + case WEATHER_HELLO: { + if (msg_size < sizeof(weather_hello_pkt_t)) { + puts("Bad hello packet received."); + } else { + puts("Hello packet received - no handler implemented"); + } + break; + } + case WEATHER_CHAT: { + puts("\n*================================================================================*"); + printf("\tCHAT MESSAGE from %hu: %s\n\n", packet_info->phy_src, ((weather_chat_pkt_t*) msg)->mesg); + puts("*================================================================================*\n"); + break; + } + case WEATHER_DATA: { + weather_data_pkt_t* wdp = (weather_data_pkt_t*) msg; + uint8_t i; + time_t local_time = rtc_time(NULL); + if (update_sources(header->src, wdp->timestamp)) { + printf("$1;%hu;%u;%lu;%lu;%.2f;%.2f;%.2f;%.2f;", + header->src, + cc1100_get_address(), + wdp->timestamp, + local_time, + wdp->temperature, + wdp->relhum, + wdp->relhum_temp, + wdp->energy); + for (i = 0; i < wdp->hop_counter; i++) { + printf("%03u-", wdp->hops[i]); + } + puts(""); + } + break; + } + default: { + printf("Unknown packet type \"%i\" received.\n", header->type); + } + } +} + +/* endless loop for packet handling +static void protocol_handler_thread(void) { + msg m; + puts("Protocol handler thread started."); + + while(1) { + msg_receive(&m); + + packet_t packet; + int pos = m.content.value; + packet = packet_buffer[pos]; + + handle_packet(packet.payload, packet.msg_size, &(packet.packet_info)); + DEBUG("Packet handler done\n"); + } +} +*/ + +static void protocol_handler_thread(void) { + packet_t packet; + int n = -1; + while (1) { + n = cib_get(&cib); + if (n >= 0) { + packet = packet_buffer[n]; + handle_packet(packet.payload, packet.msg_size, &(packet.packet_info)); + } + else { + thread_sleep(); + } + } +} + +int main(void) { + weather_data_pkt_t wdp; + sht11_val_t sht11_val; + + /* initialize variables */ + uint8_t success = 0; + int sending_state = 0; + gossip_probability = FLOODING_PROB; + cib_init(&cib, PACKET_BUFFER_SIZE); + + /* fill some fields of the packet */ + wdp.header.seq_nr = 0; + wdp.header.type = WEATHER_DATA; + wdp.hop_counter = 1; + + /* set initial channel */ + cc1100_set_channel(15); + + /* boot screen */ + puts(""); + puts("WEAtHeR: Wireless Energy-Aware mulTi-Hop sEnsor Reading. V.4.4"); + puts(""); + printf("Sending interval: %lu\n", sending_interval / SECOND); + extern int cc1100_phy_calc_wor_settings(uint16_t m); + printf("Burst count: %i\n", cc1100_phy_calc_wor_settings(T_RX_INTERVAL)); + + /* start shell */ + thread_create(SHELL_STACK_SIZE, PRIORITY_MAIN-1, CREATE_STACKTEST, shell_runner, "shell"); + + /* initialize message gateway */ + init_protocol_msg_gateway(); + /* create thread for radio packet handling */ + int pid = thread_create(PH_STACK_SIZE, PRIORITY_MAIN-2, CREATE_STACKTEST, protocol_handler_thread, "protocol_handler"); + set_protocol_handler_thread(pid); + + /* start coulomb counter and RTC */ + ltc4150_start(); + rtc_enable(); + + /* loop forever */ + while (1) { + DEBUG("Measurement in progress...\n"); +#ifndef ENABLE_DEBUG + success = sht11_read_sensor(&sht11_val, HUMIDITY|TEMPERATURE); +#else + success = 1; + sht11_val.temperature = 1; + sht11_val.relhum = 2; + sht11_val.relhum_temp = 3; +#endif + DEBUG("...done.\n"); + + wdp.timestamp = rtc_time(NULL); + DEBUG("Timestamp filled\n"); + + if (data_src) { + wdp.header.src = cc1100_get_address(); + DEBUG("Src filled\n"); + wdp.energy = ltc4150_get_total_mAh(); + DEBUG("Energy filled\n"); + + if (!success) { + printf("error;error;error\n"); + } + else { + wdp.temperature = sht11_val.temperature; + wdp.relhum = sht11_val.relhum; + wdp.relhum_temp = sht11_val.relhum_temp; + wdp.hops[0] = cc1100_get_address(); + DEBUG("Ready for sending\n"); + /* send packet with one entry in hop list */ + sending_state = cc1100_send_csmaca(0, WEATHER_PROTOCOL_NR, 0, (char*)&wdp, (EMPTY_WDP_SIZE + 1)); + if (sending_state > 0) { + DEBUG("Sending %lu bytes.\n", (EMPTY_WDP_SIZE + 1)); + wdp.header.seq_nr++; + } + else { + printf("Error on sending packet with code %i!\n", sending_state); + } + } + } + else { + LED_RED_TOGGLE; + } + + if (!success) { + printf("error;error;error\n"); + } + else { +#ifdef ENABLE_DEBUG_CC1100 + puts("=================================================="); + cc1100_print_statistic(); + puts("--------------------------------------------------"); + cc1100_print_config(); + puts("=================================================="); +#endif + + printf("$0;%hu;%hu;%lu;%u;%.2f;%.2f;%.2f;%.2f\n", + cc1100_get_address(), + 0, + wdp.timestamp, + 0, + sht11_val.temperature, + sht11_val.relhum, + sht11_val.relhum_temp, + ltc4150_get_total_mAh()); + } + hwtimer_wait(sending_interval); + } + puts("Something went wrong."); +} diff --git a/projects/WEAtHeR_stable/protocol_msg_gateway.c b/projects/WEAtHeR_stable/protocol_msg_gateway.c new file mode 100644 index 0000000000..38325654cc --- /dev/null +++ b/projects/WEAtHeR_stable/protocol_msg_gateway.c @@ -0,0 +1,78 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "protocol_msg_gateway.h" +#include "weather_protocol.h" + +#define NUM_PROTOCOL_HANDLER_PIDS 8 + +static uint16_t protocol_handler_pid; + +uint16_t pkts_received = 0; + +packet_t packet_buffer[PACKET_BUFFER_SIZE]; + +static void protocol_msg_gateway(void* payload, int msg_size, packet_info_t* packet_info) { + int n = -1; + extern cib_t cib; + + pkts_received++; + if (!cc1100_get_address()) { + puts("No address configured, not processing incoming packet"); + return; + } + + if (protocol_handler_pid <= 0) { + puts("protocol_handler(): received packet without protocol handler. msg dropped."); + return; + } +/* + int mypos = packet_buffer_next++; + if (packet_buffer_next == PACKET_BUFFER_SIZE) packet_buffer_next = 0; +*/ + n = cib_put(&cib); + + if (n != -1) { + packet_t *p = &(packet_buffer[n]); + p->packet_info = *packet_info; + p->msg_size = msg_size; + memcpy(p->payload, payload, msg_size); + } + else { + puts("Buffer full!"); + return; + } + + +/* + m.type = 0; + m.content.value = mypos; + int success = msg_send_int(&m, protocol_handler_pid); + if (! success) { + // should set timer to retry. Dropping pkt for now. + DEBUG("protocol_handler(): msg dropped."); + } +*/ + + thread_wakeup(protocol_handler_pid); +} + +void init_protocol_msg_gateway() { + puts("Init protocol msg gateway"); + cc1100_set_packet_handler(WEATHER_PROTOCOL_NR, protocol_msg_gateway); +} + +int set_protocol_handler_thread(int pid) { + protocol_handler_pid = pid; + return 0; +} diff --git a/projects/WEAtHeR_stable/protocol_msg_gateway.h b/projects/WEAtHeR_stable/protocol_msg_gateway.h new file mode 100644 index 0000000000..dd190da99f --- /dev/null +++ b/projects/WEAtHeR_stable/protocol_msg_gateway.h @@ -0,0 +1,18 @@ +#ifndef __PROTOCOL_MSG_GATEWAY_H +#define __PROTOCOL_MSG_GATEWAY_H + +#define PACKET_BUFFER_SIZE 32 +#define MAXIMUM_PAYLOAD_SIZE 64 + +typedef struct { + packet_info_t packet_info; + unsigned int msg_size; + char payload[MAXIMUM_PAYLOAD_SIZE]; +} packet_t; + +void init_protocol_msg_gateway(); +int set_protocol_handler_thread(int pid); + +extern packet_t packet_buffer[PACKET_BUFFER_SIZE]; + +#endif /* __PROTOCOL_MSG_GATEWAY_H */ diff --git a/projects/WEAtHeR_stable/tests/hello-world b/projects/WEAtHeR_stable/tests/hello-world new file mode 100755 index 0000000000..acde8265fe --- /dev/null +++ b/projects/WEAtHeR_stable/tests/hello-world @@ -0,0 +1,13 @@ +#!/usr/bin/expect + +set timeout 5 + +spawn pseudoterm $env(PORT) + +expect { + "Hello World!" {} + timeout { exit 1 } +} + +puts "\nTest successful!\n" + diff --git a/projects/WEAtHeR_stable/weather_cc1100.c b/projects/WEAtHeR_stable/weather_cc1100.c new file mode 100644 index 0000000000..b9542e3b72 --- /dev/null +++ b/projects/WEAtHeR_stable/weather_cc1100.c @@ -0,0 +1,43 @@ +#include +#include +#include +#include + +#ifdef MODULE_CC110X + +void _cc110x_get_set_address_handler(char *addr) { + int16_t a; + + a = atoi(addr+5); + if (strlen(addr) > 5) { + printf("[cc110x] Setting address %i ... ", a); + cc1100_set_address((radio_address_t)a); + if (cc1100_get_address() == (radio_address_t)a) { + puts("[OK]"); + } else { + puts("Error!"); + } + } + else { + printf("[cc1100] Got address: %i\n", cc1100_get_address()); + } +} + +void _cc110x_get_set_channel_handler(char *addr) { + int16_t a; + + a = atoi(addr+5); + if (strlen(addr) > 5) { + printf("[cc110x] Setting channel %i...", a); + cc1100_set_channel(a); + if (cc1100_get_channel() == a) { + puts("OK"); + } else { + puts("Error!"); + } + } + else { + printf("[cc1100] Got address: %i\n", cc1100_get_channel()); + } +} +#endif diff --git a/projects/WEAtHeR_stable/weather_protocol.h b/projects/WEAtHeR_stable/weather_protocol.h new file mode 100644 index 0000000000..8785fd0264 --- /dev/null +++ b/projects/WEAtHeR_stable/weather_protocol.h @@ -0,0 +1,43 @@ +#ifndef WEATHER_PROTOCOL_H_ +#define WEATHER_PROTOCOL_H_ + +#include +#include + +#define WEATHER_PROTOCOL_NR 6 +#define MAX_HOP_LIST (11) + +typedef enum { + WEATHER_HELLO, + WEATHER_CHAT, + WEATHER_DATA +} packet_types; + +typedef struct { + uint16_t seq_nr; + uint8_t src; + uint8_t type; +} weather_packet_header_t; + +typedef struct __attribute__ ((packed)) { + weather_packet_header_t header; +} weather_hello_pkt_t; + +typedef struct { + weather_packet_header_t header; + uint8_t len; + char mesg[40]; +} weather_chat_pkt_t; + +typedef struct __attribute__ ((packed)) { + weather_packet_header_t header; + time_t timestamp; + double temperature; + double relhum; + double relhum_temp; + double energy; + uint8_t hop_counter; + uint8_t hops[MAX_HOP_LIST]; +} weather_data_pkt_t; + +#endif diff --git a/projects/WEAtHeR_stable/weather_routing.c b/projects/WEAtHeR_stable/weather_routing.c new file mode 100644 index 0000000000..af252838f4 --- /dev/null +++ b/projects/WEAtHeR_stable/weather_routing.c @@ -0,0 +1,86 @@ +#include +#include +#include +#include +#include + +#include "weather_protocol.h" +#include "weather_routing.h" + +//#define ENABLE_DEBUG +#include + +uint8_t gossip_probability; + +uint16_t pkts_dup = 0; +uint16_t pkts_success = 0; +uint16_t pkts_dropped = 0; + +static source_timestamp_t sources[MAX_SOURCES]; + +uint8_t update_sources(uint8_t id, time_t timestamp) { + uint8_t i; + + DEBUG("updating sources list\n"); + for (i = 0; i < MAX_SOURCES; i++) { + /* source id found */ + if (sources[i].id == id) { + DEBUG("source already known, comparing timestamps: %04lX : %04lX\n", sources[i].timestamp, timestamp); + /* more current timestamp received, updating */ + if (sources[i].timestamp < timestamp) { + sources[i].timestamp = timestamp; + pkts_success++; + return 1; + } + /* timestamp too old, discard this packet */ + else { + pkts_dup++; + DEBUG("Timestamp too old, discarding"); + return 0; + } + } + /* source id not yet stored creating new entry */ + else if (!sources[i].id) { + puts("got to know a new source"); + sources[i].id = id; + sources[i].timestamp = timestamp; + pkts_success++; + return 1; + } + } + pkts_dropped++; + puts("No more sources could be stored!"); + return 0; +} + +void route_packet(void* msg, int msg_size) { + weather_packet_header_t *header = (weather_packet_header_t*) msg; + weather_data_pkt_t* wdp = NULL; + int state = 0; + + if (header->type == WEATHER_DATA) { + wdp = (weather_data_pkt_t*) msg; + if (!update_sources(wdp->header.src, wdp->timestamp)) { + return; + } + } + + if ((100.0 * rand()/(double) RAND_MAX) <= gossip_probability) { + DEBUG("Broadcasting packet..."); + /* if broadcasting weather data, append current hop */ + if (wdp != NULL) { + if (wdp->hop_counter < MAX_HOP_LIST) { + wdp->hops[wdp->hop_counter] = cc1100_get_address(); + wdp->hop_counter++; + } + } + state = cc1100_send_csmaca(0, WEATHER_PROTOCOL_NR, 0, (char*)msg, msg_size); + if (state > 0) { + DEBUG("successful!"); + } + else { + DEBUG("failed with code %i!\n", state); + } + } +} + diff --git a/projects/WEAtHeR_stable/weather_routing.h b/projects/WEAtHeR_stable/weather_routing.h new file mode 100644 index 0000000000..df0aeee7d4 --- /dev/null +++ b/projects/WEAtHeR_stable/weather_routing.h @@ -0,0 +1,18 @@ +#ifndef WEATHER_ROUTING_H +#define WEATHER_ROUTING_H + +#include + +#define FLOODING_PROB (100) +#define MAX_SOURCES (20) +#define MAX_INTERVAL (5 * 60) + +typedef struct { + uint8_t id; + time_t timestamp; +} source_timestamp_t; + +void route_packet(void* msg, int msg_size); +uint8_t update_sources(uint8_t id, time_t timestamp); + +#endif /* WEATHER_ROUTING_H */ diff --git a/projects/WEAtHeR_stable/weather_rtc.c b/projects/WEAtHeR_stable/weather_rtc.c new file mode 100644 index 0000000000..88e1b0b15a --- /dev/null +++ b/projects/WEAtHeR_stable/weather_rtc.c @@ -0,0 +1,42 @@ +#include +#include +#include + +#ifdef MODULE_RTC +#include + + +void _gettime_handler(void) { + struct tm now; + rtc_get_localtime(&now); + + printf("%s", asctime(&now)); +} + +void _settime_handler(char* c) { + time_t now; + int res; + + res = sscanf(c, "date %lu", &now); + + if (res < 1) { + printf("Usage: date \n"); + return; + } + else { + puts("OK"); + } + + rtc_set(now); +} + +void _date_handler(char* c) { + if (strlen(c) == 4) { + _gettime_handler(); + } + else { + _settime_handler(c); + } +} + +#endif From 808b24db7fa8d5e0221b8566dc6f9876edb8b861 Mon Sep 17 00:00:00 2001 From: Oliver Hahm Date: Fri, 13 May 2011 15:36:31 +0200 Subject: [PATCH 04/10] [projects WEAtHeR_stable] * added per thread consumption --- projects/WEAtHeR_stable/Jamfile | 3 ++- projects/WEAtHeR_stable/main.c | 16 +++++++++++----- 2 files changed, 13 insertions(+), 6 deletions(-) diff --git a/projects/WEAtHeR_stable/Jamfile b/projects/WEAtHeR_stable/Jamfile index 0771f19058..590cdfbafe 100644 --- a/projects/WEAtHeR_stable/Jamfile +++ b/projects/WEAtHeR_stable/Jamfile @@ -1,5 +1,6 @@ SubDir TOP projects WEAtHeR_stable ; -Module WEAtHeR_stable : main.c weather_routing.c protocol_msg_gateway.c weather_cc1100.c weather_rtc.c : ltc4150 cc110x sht11 gpioint shell shell_commands posix_io uart0 auto_init rtc ; +Module WEAtHeR_stable : main.c weather_routing.c protocol_msg_gateway.c +weather_cc1100.c weather_rtc.c : ltc4150 cc110x sht11 gpioint shell shell_commands posix_io uart0 auto_init rtc ps ; UseModule WEAtHeR_stable ; diff --git a/projects/WEAtHeR_stable/main.c b/projects/WEAtHeR_stable/main.c index 2f885b07a9..ad7fc34558 100644 --- a/projects/WEAtHeR_stable/main.c +++ b/projects/WEAtHeR_stable/main.c @@ -9,6 +9,7 @@ #include #include #include +#include //#define ENABLE_DEBUG #include @@ -43,7 +44,7 @@ #define EMPTY_WDP_SIZE (sizeof(weather_data_pkt_t) - MAX_HOP_LIST) /* default values */ -#define DEFAULT_INTERVAL (5 * SECOND) +#define DEFAULT_INTERVAL (30 * SECOND) /* stack space for threads */ #define SHELL_STACK_SIZE (4048) @@ -196,7 +197,7 @@ static void handle_packet(void* msg, int msg_size, packet_info_t* packet_info) { if (!data_sink) { if (header->type == WEATHER_DATA) { weather_data_pkt_t* wdp = (weather_data_pkt_t*) msg; - DEBUG("$0;%hu;%hu;%lu;%u;%.2f;%.2f;%.2f;%.2f\n", + DEBUG("$0;%hu;%hu;%lu;%u;%.2f;%.2f;%.2f;%.2f;%.2f\n", header->src, 0, wdp->timestamp, @@ -204,7 +205,9 @@ static void handle_packet(void* msg, int msg_size, packet_info_t* packet_info) { wdp->temperature, wdp->relhum, wdp->relhum_temp, - wdp->energy); + wdp->energy, + pidlist[0].energy, + pidlist[1].energy); DEBUG("Not for me, routing, baby!\n"); route_packet(msg, msg_size); } @@ -385,7 +388,8 @@ int main(void) { puts("=================================================="); #endif - printf("$0;%hu;%hu;%lu;%u;%.2f;%.2f;%.2f;%.2f\n", + //thread_print_all(); + printf("$0;%hu;%hu;%lu;%u;%.2f;%.2f;%.2f;%.2f;%.2f;%.2f\n", cc1100_get_address(), 0, wdp.timestamp, @@ -393,7 +397,9 @@ int main(void) { sht11_val.temperature, sht11_val.relhum, sht11_val.relhum_temp, - ltc4150_get_total_mAh()); + ltc4150_get_total_mAh(), + pidlist[0].energy, + pidlist[1].energy); } hwtimer_wait(sending_interval); } From 1eecd131160723a8647238146245e07c19549954 Mon Sep 17 00:00:00 2001 From: Oliver Hahm Date: Tue, 30 Aug 2011 17:40:38 +0200 Subject: [PATCH 05/10] * introduced empty function _fini() for codesourcery --- cpu/arm_common/syscalls.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/cpu/arm_common/syscalls.c b/cpu/arm_common/syscalls.c index a1e583f4a1..a2430a061b 100644 --- a/cpu/arm_common/syscalls.c +++ b/cpu/arm_common/syscalls.c @@ -237,3 +237,5 @@ int _kill_r(struct _reent *r, int pid, int sig) return -1; } /*---------------------------------------------------------------------------*/ + +void _fini(void) {} From a5d1d6d26ba21b67b688cc11c2d988cbf55b8651 Mon Sep 17 00:00:00 2001 From: Oliver Hahm Date: Wed, 5 Oct 2011 15:13:34 +0200 Subject: [PATCH 06/10] [core scheduler] * added optional callback for scheduler timing statistics --- core/scheduler.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/core/scheduler.c b/core/scheduler.c index 279bb456a2..c314b17a48 100644 --- a/core/scheduler.c +++ b/core/scheduler.c @@ -15,6 +15,7 @@ #include #include +#include "hwtimer.h" #include "scheduler.h" #include "kernel.h" #include "kernel_intern.h" @@ -26,10 +27,16 @@ volatile int num_tasks = 0; +uint8_t last_pid = 0xFF; + clist_node_t *runqueues[SCHED_PRIO_LEVELS]; static uint32_t runqueue_bitcache = 0; +void sched_register_cb(void (*callback)(uint32_t, uint32_t)); + + #if SCHEDSTATISTICS + static void (*sched_cb)(uint32_t timestamp, uint32_t value) = NULL; schedstat pidlist[MAXTHREADS]; #endif @@ -106,6 +113,12 @@ void fk_schedule() { // break; // } // } +#if SCHEDSTATISTICS + if ((sched_cb) && (my_fk_thread->pid != last_pid)) { + sched_cb(hwtimer_now(), my_fk_thread->pid); + last_pid = my_fk_thread->pid; + } +#endif } DEBUG("scheduler: next task: %s\n", my_fk_thread->name); @@ -124,6 +137,11 @@ void fk_schedule() { DEBUG("scheduler: done.\n"); } +#if SCHEDSTATISTICS +void sched_register_cb(void (*callback)(uint32_t, uint32_t)) { + sched_cb = callback; +} +#endif void sched_set_status(tcb *process, unsigned int status) { if (status & STATUS_ON_RUNQUEUE) { From 824f7bcb609f71ff7697d6cf7298c828cb9c03d6 Mon Sep 17 00:00:00 2001 From: Oliver Hahm Date: Wed, 5 Oct 2011 15:14:56 +0200 Subject: [PATCH 07/10] [drivers include ltc4150] * fixed typo (merged from master) --- drivers/include/ltc4150.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/include/ltc4150.h b/drivers/include/ltc4150.h index e7fbad663f..b024f4b5cd 100644 --- a/drivers/include/ltc4150.h +++ b/drivers/include/ltc4150.h @@ -8,7 +8,7 @@ void ltc4150_start(); void ltc4150_stop(); double ltc4150_get_current_mA(); -double ltc4150_get_total_mA(); +double ltc4150_get_total_mAh(); double ltc4150_get_avg_mA(); #endif /* __LTC4150_H */ From 3a4c88c63725f609f6afdf783ce4dc10c5206ea1 Mon Sep 17 00:00:00 2001 From: Oliver Hahm Date: Wed, 5 Oct 2011 15:28:25 +0200 Subject: [PATCH 08/10] [sys shell shell_commands] * added missing function prototype --- sys/shell/shell_commands.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/sys/shell/shell_commands.c b/sys/shell/shell_commands.c index 932516a4b8..88b95c30fd 100644 --- a/sys/shell/shell_commands.c +++ b/sys/shell/shell_commands.c @@ -1,9 +1,13 @@ #include #include +#ifdef MODULE_PS + extern void _ps_handler(char* unused); +#endif + const shell_command_t _shell_command_list[] = { #ifdef MODULE_PS - {"ps", ps_handler}, + {"ps", _ps_handler}, #endif {NULL, NULL} }; From 4dd4ca03548a382f5146659d3526fad9dc415a82 Mon Sep 17 00:00:00 2001 From: Oliver Hahm Date: Wed, 5 Oct 2011 15:30:59 +0200 Subject: [PATCH 09/10] [projects OHM] * otto is in da house --- projects/OHM/Jamfile | 7 + projects/OHM/cib.c | 43 +++ projects/OHM/cib.h | 15 + projects/OHM/main.c | 474 ++++++++++++++++++++++++++++ projects/OHM/ohm.h | 30 ++ projects/OHM/ohm_cc1100.c | 43 +++ projects/OHM/ohm_ltc4150.c | 117 +++++++ projects/OHM/ohm_protocol.h | 44 +++ projects/OHM/ohm_routing.c | 86 +++++ projects/OHM/ohm_routing.h | 18 ++ projects/OHM/ohm_rtc.c | 42 +++ projects/OHM/profiling.c | 29 ++ projects/OHM/protocol_msg_gateway.c | 78 +++++ projects/OHM/protocol_msg_gateway.h | 18 ++ projects/OHM/tests/hello-world | 13 + 15 files changed, 1057 insertions(+) create mode 100644 projects/OHM/Jamfile create mode 100644 projects/OHM/cib.c create mode 100644 projects/OHM/cib.h create mode 100644 projects/OHM/main.c create mode 100644 projects/OHM/ohm.h create mode 100644 projects/OHM/ohm_cc1100.c create mode 100644 projects/OHM/ohm_ltc4150.c create mode 100644 projects/OHM/ohm_protocol.h create mode 100644 projects/OHM/ohm_routing.c create mode 100644 projects/OHM/ohm_routing.h create mode 100644 projects/OHM/ohm_rtc.c create mode 100644 projects/OHM/profiling.c create mode 100644 projects/OHM/protocol_msg_gateway.c create mode 100644 projects/OHM/protocol_msg_gateway.h create mode 100755 projects/OHM/tests/hello-world diff --git a/projects/OHM/Jamfile b/projects/OHM/Jamfile new file mode 100644 index 0000000000..f1fb1c4be9 --- /dev/null +++ b/projects/OHM/Jamfile @@ -0,0 +1,7 @@ +SubDir TOP projects OHM ; + +CCFLAGS += -DSCHEDSTATISTICS ; + +Module OHM : profiling.c main.c ohm_routing.c protocol_msg_gateway.c ohm_cc1100.c ohm_rtc.c ohm_ltc4150.c : cc110x sht11 gpioint shell shell_commands posix_io uart0 auto_init rtc ps board_ltc4150 ; + +UseModule OHM ; diff --git a/projects/OHM/cib.c b/projects/OHM/cib.c new file mode 100644 index 0000000000..b588fe671e --- /dev/null +++ b/projects/OHM/cib.c @@ -0,0 +1,43 @@ +#include + +void cib_init(cib_t *cib, unsigned int size) { + cib->read_count = 0; + cib->write_count = 0; + cib->complement = 0-size; +} + +int cib_avail (cib_t *cib) { + return cib->write_count - cib->read_count; +} + +int cib_get(cib_t *cib) { + int avail = cib_avail (cib); + + if (avail > 0) { + return cib->read_count++ & ~cib->complement; + } + + return -1; +} + +int cib_put(cib_t *cib) { + int avail = cib_avail (cib); + + if ((int)(avail + cib->complement) < 0 ) { + return cib->write_count++ & ~(cib->complement); + } + + return -1; +} + +/* +int main() { + cib_t cib; + + cib_init(&cib, 0); + + int res = cib_get(&cib); + + printf("%i\n", res); +} +*/ diff --git a/projects/OHM/cib.h b/projects/OHM/cib.h new file mode 100644 index 0000000000..7ef179280d --- /dev/null +++ b/projects/OHM/cib.h @@ -0,0 +1,15 @@ +#ifndef __CIB_H +#define __CIB_H + +typedef struct cib_t { + unsigned int read_count; + unsigned int write_count; + unsigned int complement; +} cib_t; + +void cib_init(cib_t *cib, unsigned int size); +int cib_get(cib_t *cib); +int cib_put(cib_t *cib); +int cib_avail(cib_t *cib); + +#endif /* __CIB_H */ diff --git a/projects/OHM/main.c b/projects/OHM/main.c new file mode 100644 index 0000000000..b6870ab4fd --- /dev/null +++ b/projects/OHM/main.c @@ -0,0 +1,474 @@ +/* stdlib includes */ +#include +#include +#include +#include + +/* core includes */ +#include +#include +#include +#include +#include + +//#define ENABLE_DEBUG +#include + +/* sensors and actors */ +#include +#include +#include + +/* shell */ +#include +#include +#include + +/* transceiver */ +#include +#include + +/* real time clock */ +#include + +/* application header */ +#include "ohm.h" +#include "ohm_routing.h" +#include "ohm_protocol.h" +#include "protocol_msg_gateway.h" + +/* some local defines */ +#define SECOND (1000 * 1000) +#define MINUTE (1 * SECOND) + +/* size of ohm data packet without hop list */ +#define EMPTY_WDP_SIZE (sizeof(ohm_data_pkt_t) - MAX_HOP_LIST) + +/* default values */ +#define DEFAULT_INTERVAL (5 * SECOND) + +/* stack space for threads */ +#define SHELL_STACK_SIZE (2048) +#define PH_STACK_SIZE (2048) + +/* debugging pins */ +#define P10_TOGGLE (FIO1PIN ^= BIT0) +#define P11_TOGGLE (FIO1PIN ^= BIT1) +#define P14_TOGGLE (FIO1PIN ^= BIT4) + +char shell_stack_buffer[SHELL_STACK_SIZE]; +char ph_stack_buffer[PH_STACK_SIZE]; + +/* Coulomb, thread and function measurement buffers */ +volatile uint32_t cb_buf[MAX_TICK_BUF_SIZE]; +volatile uint32_t *cb_buf_ptr; +volatile ohm_measurement_t thread_buf[MAX_THREAD_BUF_SIZE]; +volatile ohm_measurement_t *thread_buf_ptr; +volatile ohm_measurement_t func_buf[MAX_FUNC_BUF_SIZE]; +volatile ohm_measurement_t *func_buf_ptr; + +uint32_t otto_says = 0; +uint8_t measure_pause = 1; + +/* per default acting only as relay */ +static uint8_t data_sink = 0; +static uint8_t data_src = 0; + +cib_t cib; +uint16_t pkts_processed = 0; + +static uint32_t sending_interval = DEFAULT_INTERVAL; + +extern uint8_t gossip_probability; +extern void _cc110x_get_set_address_handler(char *addr); +extern void _cc110x_get_set_channel_handler(char *chan); +extern void _date_handler(char* c); + +/* function prototypes */ +static void ohm_send(char* unused); +static void ohm_sink(char* unused); +static void set_interval(char* interval); +static void set_probability(char* prob); +static void print_cc1100_info(char* unused); +static void stat_handler(char* unused); + +int shell_readc() { + char c = 0; + posix_read(uart0_handler_pid, &c, 1); + return c; +} + +void shell_putchar(int c) { + putchar(c); +} + +/* shell commands */ +shell_t shell; +const shell_command_t sc[] = { + {"sender", ohm_send}, + {"sink", ohm_sink}, + {"int", set_interval}, + {"prob", set_probability}, + {"cc1100", print_cc1100_info}, + {"addr", _cc110x_get_set_address_handler}, + {"date", _date_handler}, + {"stats", stat_handler}, + {NULL, NULL}}; + +static void shell_runner(void) { + posix_open(uart0_handler_pid, 0); + shell_init(&shell, shell_readc, shell_putchar); + shell.command_list = sc; + shell_run(&shell); +} + +static void ohm_send(char* unused) { + if (data_src) { + data_src = 0; + puts("Disabling data source mode."); + } + else { + data_src = 1; + puts("Enabling data source mode."); + } +} + +static void ohm_sink(char* unused) { + if (data_sink) { + data_sink = 0; + puts("Disabling data sink mode."); + } + else { + data_sink = 1; + puts("Enabling data sink mode."); + } +} + +static void set_interval(char* interval) { + uint16_t a; + + a = atoi(interval+4); + if (strlen(interval) > 4) { + printf("[WEAtHeR] Set interval to %u\n ", a); + sending_interval = a * SECOND; + } + else { + printf("[WEAtHeR] Current interval is %lu\n ", (sending_interval / SECOND)); + } +} + +static void set_probability(char* prob) { + uint16_t a; + + a = atoi(prob+4); + if (strlen(prob) > 4) { + printf("[WEAtHeR] Set probability to %hu\n ", a); + gossip_probability = a; + } + else { + printf("[WEAtHeR] Current probability is %hu\n ", gossip_probability); + } +} + +static void print_cc1100_info(char* unused) { + puts("=================================================="); + cc1100_print_statistic(); + puts("--------------------------------------------------"); + cc1100_print_config(); + puts("=================================================="); +} + +static void stat_handler(char* unused) { + extern uint16_t pkts_received; + extern uint16_t pkts_success; + extern uint16_t pkts_dup; + extern uint16_t pkts_dropped; + printf(" ::::::::::::::::::::::::::: \n"); + printf(" :: Packets received: %u ::\n", pkts_received); + printf(" :: Packets processed: %u ::\n", pkts_processed); + printf(" :: Packets success: %u ::\n", pkts_success); + printf(" :: Packets dup: %u ::\n", pkts_dup); + printf(" :: Packets dropped: %u ::\n", pkts_dropped); + printf(" ::::::::::::::::::::::::::: \n"); +} + +void otto(uint32_t timestamp, uint32_t value) { + uint16_t i, j; + + if (measure_pause) { + return; + } +// printf("tbp: %p\n", thread_buf_ptr); + thread_buf_ptr->timestamp = timestamp; + thread_buf_ptr->value = value; + if (((thread_buf_ptr++) - thread_buf) > CRIT_THREAD_BUF_SIZE) { + /* output */ + otto_says = 1; + } + if (otto_says) { + measure_pause = 1; + /* + printf("Otto says: %lX\n", otto_says); + + printf("Coulomb buffer is filled with %lu entries\n", (cb_buf_ptr - cb_buf)); + printf("Thread buffer is filled with %lu entries\n", (thread_buf_ptr - thread_buf)); + j = 0; + for (i = 0; i < (cb_buf_ptr - cb_buf); i++) { + for (; j < (thread_buf_ptr - thread_buf); j++) { + if (thread_buf[j].timestamp > cb_buf[i]) break; + printf("T;%04lX;%04lX\n", thread_buf[j].timestamp, thread_buf[j].value); + } + printf("C;%04lX\n", cb_buf[i]); + } + for (; j < (thread_buf_ptr - thread_buf); j++) { + printf("T;%04lX;%04lX\n", thread_buf[j].timestamp, thread_buf[j].value); + } + cb_buf_ptr = cb_buf; + thread_buf_ptr = thread_buf; + + printf("Function buffer is filled with %lu entries\n", (func_buf_ptr - func_buf)); + */ +/* for (i = 0; i < (func_buf_ptr - func_buf); i++) { + printf("F;%04lX;%04lX\n", func_buf[i].timestamp, func_buf[i].value); + }*/ + func_buf_ptr = func_buf; + + otto_says = 0; + measure_pause = 0; + } + + //printf("tbp: %p\n", thread_buf_ptr); +} + +/* packet handling */ +static void handle_packet(void* msg, int msg_size, packet_info_t* packet_info) { + pkts_processed++; + ohm_packet_header_t *header = (ohm_packet_header_t*) msg; + + printf("\n\t Pkt received from phy: %u (%u bytes)\n" + "\t -> SEQ: %u | TYPE: %u | SRC: %hu \n\n", + packet_info->phy_src, + msg_size, + header->seq_nr, + header->type, + header->src + ); + /* packet origins at current node, just ignore it */ + if (header->src == cc1100_get_address()) { + return; + } + /* while not acting as sink and packet contains data, route the packet */ + if (!data_sink) { + if (header->type == OHM_DATA) { + ohm_data_pkt_t* odp = (ohm_data_pkt_t*) msg; + DEBUG("$0;%hu;%hu;%lu;%u;%.2f;%.2f;%.2f\n", + header->src, + 0, + odp->timestamp, + 0, + odp->temperature, + odp->relhum, + odp->relhum_temp, + odp->energy + ) + DEBUG("Not for me, routing, baby!\n"); + route_packet(msg, msg_size); + } + + return; + } + + /* if current node acts as sink, handle packet */ + switch (header->type) { + case OHM_HELLO: { + if (msg_size < sizeof(ohm_hello_pkt_t)) { + puts("Bad hello packet received."); + } else { + puts("Hello packet received - no handler implemented"); + } + break; + } + case OHM_CHAT: { + puts("\n*================================================================================*"); + printf("\tCHAT MESSAGE from %hu: %s\n\n", packet_info->phy_src, ((ohm_chat_pkt_t*) msg)->mesg); + puts("*================================================================================*\n"); + break; + } + case OHM_DATA: { + ohm_data_pkt_t* odp = (ohm_data_pkt_t*) msg; + uint8_t i; + time_t local_time = rtc_time(NULL); + if (update_sources(header->src, odp->timestamp)) { + printf("$1;%hu;%u;%lu;%lu;%.2f;%.2f;%.2f;%.2f;", + header->src, + cc1100_get_address(), + odp->timestamp, + local_time, + odp->temperature, + odp->relhum, + odp->relhum_temp, + odp->energy); + for (i = 0; i < odp->hop_counter; i++) { + printf("%03u-", odp->hops[i]); + } + puts(""); + } + break; + } + default: { + printf("Unknown packet type \"%i\" received.\n", header->type); + } + } +} + +static void protocol_handler_thread(void) { + puts("Start protocol handler thread"); + packet_t packet; + int n = -1; + while (1) { + n = cib_get(&cib); + if (n >= 0) { + packet = packet_buffer[n]; + handle_packet(packet.payload, packet.msg_size, &(packet.packet_info)); + } + else { + thread_sleep(); + } + } +} + +int main(void) { + FIO1DIR |= BIT0; + FIO1DIR |= BIT1; + FIO1DIR |= BIT4; + + ohm_data_pkt_t odp; + sht11_val_t sht11_val; + + /* initialize variables */ + uint8_t success = 0; + int sending_state = 0; + gossip_probability = FLOODING_PROB; + cib_init(&cib, PACKET_BUFFER_SIZE); + + cb_buf_ptr = cb_buf; + thread_buf_ptr = thread_buf; + func_buf_ptr = func_buf; + + /* register thread switch callback */ + void sched_register_cb(void (*callback)(uint32_t, uint32_t)); + sched_register_cb(otto); + + /* fill some fields of the packet */ + odp.header.seq_nr = 0; + odp.header.type = OHM_DATA; + odp.hop_counter = 1; + + /* set initial channel */ + cc1100_set_channel(15); + + /* boot screen */ + puts(""); + puts("WEAtHeR: Wireless Energy-Aware mulTi-Hop sEnsor Reading. V.4.4"); + puts(""); + printf("Sending interval: %lu\n", sending_interval / SECOND); + extern int cc1100_phy_calc_wor_settings(uint16_t m); + printf("Burst count: %i\n", cc1100_phy_calc_wor_settings(T_RX_INTERVAL)); + + printf(" Coulomb buffer size: %u\n", CRIT_TICK_BUF_SIZE); + printf(" Thread buffer size: %u\n", CRIT_THREAD_BUF_SIZE); + printf(" Function buffer size: %u\n", CRIT_FUNC_BUF_SIZE); + + /* start shell */ + thread_create(SHELL_STACK_SIZE, PRIORITY_MAIN-1, CREATE_STACKTEST, shell_runner, "shell"); + + measure_pause = 0; + + /* initialize message gateway */ + init_protocol_msg_gateway(); + /* create thread for radio packet handling */ + int pid = thread_create(PH_STACK_SIZE, PRIORITY_MAIN-2, CREATE_STACKTEST, protocol_handler_thread, "protocol_handler"); + set_protocol_handler_thread(pid); + + /* start coulomb counter and RTC */ + ltc4150_start(); + rtc_enable(); + + /* loop forever */ + while (1) { + DEBUG("Measurement in progress...\n"); +#ifndef ENABLE_DEBUG + P14_TOGGLE; + success = sht11_read_sensor(&sht11_val, HUMIDITY|TEMPERATURE); + P14_TOGGLE; +#else + success = 1; + sht11_val.temperature = 1; + sht11_val.relhum = 2; + sht11_val.relhum_temp = 3; +#endif + DEBUG("...done.\n"); + + odp.timestamp = rtc_time(NULL); + DEBUG("Timestamp filled\n"); + + if (data_src) { + odp.header.src = cc1100_get_address(); + DEBUG("Src filled\n"); + odp.energy = ltc4150_get_total_mAh(); + DEBUG("Energy filled\n"); + + if (!success) { + printf("error;error;error\n"); + } + else { + odp.temperature = sht11_val.temperature; + odp.relhum = sht11_val.relhum; + odp.relhum_temp = sht11_val.relhum_temp; + odp.hops[0] = cc1100_get_address(); + DEBUG("Ready for sending\n"); + /* send packet with one entry in hop list */ + P11_TOGGLE; + sending_state = cc1100_send_csmaca(0, OHM_PROTOCOL_NR, 0, (char*)&odp, (EMPTY_WDP_SIZE + 1)); + P11_TOGGLE; + if (sending_state > 0) { + DEBUG("Sending %lu bytes.\n", (EMPTY_WDP_SIZE + 1)); + odp.header.seq_nr++; + } + else { + printf("Error on sending packet with code %i!\n", sending_state); + } + } + } + else { + //LED_RED_TOGGLE; + } + + if (!success) { + printf("error;error;error\n"); + } + else { +#ifdef ENABLE_DEBUG_CC1100 + puts("=================================================="); + cc1100_print_statistic(); + puts("--------------------------------------------------"); + cc1100_print_config(); + puts("=================================================="); +#endif + + thread_print_all(); + printf("$0;%hu;%hu;%lu;%u;%.2f;%.2f;%.2f;%.2f\n", + cc1100_get_address(), + 0, + odp.timestamp, + 0, + sht11_val.temperature, + sht11_val.relhum, + sht11_val.relhum_temp, + ltc4150_get_total_mAh() + ); + } + hwtimer_wait(sending_interval); + } + puts("Something went wrong."); +} diff --git a/projects/OHM/ohm.h b/projects/OHM/ohm.h new file mode 100644 index 0000000000..d296dad57d --- /dev/null +++ b/projects/OHM/ohm.h @@ -0,0 +1,30 @@ +#ifndef OHM_H +#define OHM_H + +#include + +#define MAX_TICK_BUF_SIZE (256) +#define CRIT_TICK_BUF_SIZE (MAX_TICK_BUF_SIZE * 80/100) + +#define MAX_THREAD_BUF_SIZE (1024) +#define CRIT_THREAD_BUF_SIZE (MAX_THREAD_BUF_SIZE * 50/100) + +#define MAX_FUNC_BUF_SIZE (4048) +#define CRIT_FUNC_BUF_SIZE (MAX_FUNC_BUF_SIZE * 50/100) + +#define OHM_LTC_TICK (0xFFFF) + +typedef enum { + OHM_DT_LTC, + OHM_DT_THREAD, + OHM_DT_FUNCTION +} ohm_datatype_t; + +typedef struct { + uint32_t timestamp; + uint32_t value; +} ohm_measurement_t; + +void otto(uint32_t timestamp, uint32_t value); + +#endif /* OHM_H */ diff --git a/projects/OHM/ohm_cc1100.c b/projects/OHM/ohm_cc1100.c new file mode 100644 index 0000000000..b9542e3b72 --- /dev/null +++ b/projects/OHM/ohm_cc1100.c @@ -0,0 +1,43 @@ +#include +#include +#include +#include + +#ifdef MODULE_CC110X + +void _cc110x_get_set_address_handler(char *addr) { + int16_t a; + + a = atoi(addr+5); + if (strlen(addr) > 5) { + printf("[cc110x] Setting address %i ... ", a); + cc1100_set_address((radio_address_t)a); + if (cc1100_get_address() == (radio_address_t)a) { + puts("[OK]"); + } else { + puts("Error!"); + } + } + else { + printf("[cc1100] Got address: %i\n", cc1100_get_address()); + } +} + +void _cc110x_get_set_channel_handler(char *addr) { + int16_t a; + + a = atoi(addr+5); + if (strlen(addr) > 5) { + printf("[cc110x] Setting channel %i...", a); + cc1100_set_channel(a); + if (cc1100_get_channel() == a) { + puts("OK"); + } else { + puts("Error!"); + } + } + else { + printf("[cc1100] Got address: %i\n", cc1100_get_channel()); + } +} +#endif diff --git a/projects/OHM/ohm_ltc4150.c b/projects/OHM/ohm_ltc4150.c new file mode 100644 index 0000000000..c02cf713fa --- /dev/null +++ b/projects/OHM/ohm_ltc4150.c @@ -0,0 +1,117 @@ +/****************************************************************************** +Copyright 2008-2009, Freie Universitaet Berlin (FUB). All rights reserved. + +These sources were developed at the Freie Universitaet Berlin, Computer Systems +and Telematics group (http://cst.mi.fu-berlin.de). +------------------------------------------------------------------------------- +This file is part of FeuerWare. + +This program is free software: you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free Software +Foundation, either version 3 of the License, or (at your option) any later +version. + +FeuerWare is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License along with +this program. If not, see http://www.gnu.org/licenses/ . +-------------------------------------------------------------------------------- +For further information and questions please use the web site + http://scatterweb.mi.fu-berlin.de +and the mailinglist (subscription via web site) + scatterweb@lists.spline.inf.fu-berlin.de +*******************************************************************************/ + +/** + * @ingroup ltc4150 + * @{ + */ + +/** + * @file + * @brief LTC4150 Coulomb Counter + * + * @author Freie Universität Berlin, Computer Systems & Telematics, FeuerWhere project + * @author Heiko Will + * @author Kaspar Schleiser + */ + +#include +#include +#include "ltc4150_arch.h" +#include "board.h" +#include "ohm.h" + +static volatile unsigned long int_count; +static unsigned int last_int_time; +static unsigned int last_int_duration; +static unsigned int start_time; + +static double int_to_coulomb(int ints) { + return ((double)ints) / (_GFH * _R_SENSE); +} + +static double coulomb_to_mA(double coulomb){ + return (coulomb * 1000) / 3600; +} + +uint32_t ltc4150_get_last_int_duration_us() { + return HWTIMER_TICKS_TO_US(last_int_duration); +} + +double ltc4150_get_current_mA() { + return 1000000000/(ltc4150_get_last_int_duration_us()*(_GFH * _R_SENSE)); +} + +double ltc4150_get_total_mAh() { + return coulomb_to_mA(int_to_coulomb(int_count)); +} + +double ltc4150_get_avg_mA() { + return (int_to_coulomb(int_count)*1000000000)/HWTIMER_TICKS_TO_US(last_int_time - start_time); +} + +unsigned long ltc4150_get_intcount() { + return int_count; +} + +void ltc4150_init() { + ltc4150_arch_init(); +} + +void ltc4150_start() { + ltc4150_disable_int(); + int_count = 0; + uint32_t now = hwtimer_now(); + ltc4150_sync_blocking(); + start_time = now; + last_int_time = now; + ltc4150_enable_int(); +} + +void ltc4150_stop() { + ltc4150_disable_int(); +} + +void ltc4150_interrupt() +{ + extern uint32_t *cb_buf_ptr; + uint32_t now = hwtimer_now(); + + if (now >= last_int_time) { + last_int_duration = now - last_int_time; + } else { + last_int_duration = (0-1) - last_int_time + now + 1; + } + + last_int_time = now; + int_count++; + + *cb_buf_ptr = hwtimer_now(); + cb_buf_ptr++; + // LED_GREEN_TOGGLE; +} + +/** @} */ diff --git a/projects/OHM/ohm_protocol.h b/projects/OHM/ohm_protocol.h new file mode 100644 index 0000000000..5b17268797 --- /dev/null +++ b/projects/OHM/ohm_protocol.h @@ -0,0 +1,44 @@ +#ifndef OHM_PROTOCOL_H_ +#define OHM_PROTOCOL_H_ + +#include +#include +#include + +#define OHM_PROTOCOL_NR 6 +#define MAX_HOP_LIST (11) + +typedef enum { + OHM_HELLO, + OHM_CHAT, + OHM_DATA +} packet_types; + +typedef struct { + uint16_t seq_nr; + uint8_t src; + uint8_t type; +} ohm_packet_header_t; + +typedef struct __attribute__ ((packed)) { + ohm_packet_header_t header; +} ohm_hello_pkt_t; + +typedef struct { + ohm_packet_header_t header; + uint8_t len; + char mesg[40]; +} ohm_chat_pkt_t; + +typedef struct __attribute__ ((packed)) { + ohm_packet_header_t header; + time_t timestamp; + double temperature; + double relhum; + double relhum_temp; + double energy; + uint8_t hop_counter; + uint8_t hops[MAX_HOP_LIST]; +} ohm_data_pkt_t; + +#endif diff --git a/projects/OHM/ohm_routing.c b/projects/OHM/ohm_routing.c new file mode 100644 index 0000000000..1068768b1a --- /dev/null +++ b/projects/OHM/ohm_routing.c @@ -0,0 +1,86 @@ +#include +#include +#include +#include +#include + +#include "ohm_protocol.h" +#include "ohm_routing.h" + +//#define ENABLE_DEBUG +#include + +uint8_t gossip_probability; + +uint16_t pkts_dup = 0; +uint16_t pkts_success = 0; +uint16_t pkts_dropped = 0; + +static source_timestamp_t sources[MAX_SOURCES]; + +uint8_t update_sources(uint8_t id, time_t timestamp) { + uint8_t i; + + DEBUG("updating sources list\n"); + for (i = 0; i < MAX_SOURCES; i++) { + /* source id found */ + if (sources[i].id == id) { + DEBUG("source already known, comparing timestamps: %04lX : %04lX\n", sources[i].timestamp, timestamp); + /* more current timestamp received, updating */ + if (sources[i].timestamp < timestamp) { + sources[i].timestamp = timestamp; + pkts_success++; + return 1; + } + /* timestamp too old, discard this packet */ + else { + pkts_dup++; + DEBUG("Timestamp too old, discarding"); + return 0; + } + } + /* source id not yet stored creating new entry */ + else if (!sources[i].id) { + puts("got to know a new source"); + sources[i].id = id; + sources[i].timestamp = timestamp; + pkts_success++; + return 1; + } + } + pkts_dropped++; + puts("No more sources could be stored!"); + return 0; +} + +void route_packet(void* msg, int msg_size) { + ohm_packet_header_t *header = (ohm_packet_header_t*) msg; + ohm_data_pkt_t* wdp = NULL; + int state = 0; + + if (header->type == OHM_DATA) { + wdp = (ohm_data_pkt_t*) msg; + if (!update_sources(wdp->header.src, wdp->timestamp)) { + return; + } + } + + if ((100.0 * rand()/(double) RAND_MAX) <= gossip_probability) { + DEBUG("Broadcasting packet..."); + /* if broadcasting ohm data, append current hop */ + if (wdp != NULL) { + if (wdp->hop_counter < MAX_HOP_LIST) { + wdp->hops[wdp->hop_counter] = cc1100_get_address(); + wdp->hop_counter++; + } + } + state = cc1100_send_csmaca(0, OHM_PROTOCOL_NR, 0, (char*)msg, msg_size); + if (state > 0) { + DEBUG("successful!"); + } + else { + DEBUG("failed with code %i!\n", state); + } + } +} + diff --git a/projects/OHM/ohm_routing.h b/projects/OHM/ohm_routing.h new file mode 100644 index 0000000000..df0aeee7d4 --- /dev/null +++ b/projects/OHM/ohm_routing.h @@ -0,0 +1,18 @@ +#ifndef WEATHER_ROUTING_H +#define WEATHER_ROUTING_H + +#include + +#define FLOODING_PROB (100) +#define MAX_SOURCES (20) +#define MAX_INTERVAL (5 * 60) + +typedef struct { + uint8_t id; + time_t timestamp; +} source_timestamp_t; + +void route_packet(void* msg, int msg_size); +uint8_t update_sources(uint8_t id, time_t timestamp); + +#endif /* WEATHER_ROUTING_H */ diff --git a/projects/OHM/ohm_rtc.c b/projects/OHM/ohm_rtc.c new file mode 100644 index 0000000000..88e1b0b15a --- /dev/null +++ b/projects/OHM/ohm_rtc.c @@ -0,0 +1,42 @@ +#include +#include +#include + +#ifdef MODULE_RTC +#include + + +void _gettime_handler(void) { + struct tm now; + rtc_get_localtime(&now); + + printf("%s", asctime(&now)); +} + +void _settime_handler(char* c) { + time_t now; + int res; + + res = sscanf(c, "date %lu", &now); + + if (res < 1) { + printf("Usage: date \n"); + return; + } + else { + puts("OK"); + } + + rtc_set(now); +} + +void _date_handler(char* c) { + if (strlen(c) == 4) { + _gettime_handler(); + } + else { + _settime_handler(c); + } +} + +#endif diff --git a/projects/OHM/profiling.c b/projects/OHM/profiling.c new file mode 100644 index 0000000000..35355f1739 --- /dev/null +++ b/projects/OHM/profiling.c @@ -0,0 +1,29 @@ +#include "cpu.h" +#include "ohm.h" + +#define TIMER_REG (T0TC) +#define P10_TOGGLE (FIO1PIN ^= BIT0) + +void __attribute__((__no_instrument_function__)) __cyg_profile_func_enter (void *func, void *caller) { + extern ohm_measurement_t *func_buf_ptr; + extern ohm_measurement_t func_buf[]; + + extern uint32_t otto_says; + extern uint8_t measure_pause; + + P10_TOGGLE; + if (measure_pause) { + return; + } + func_buf_ptr->timestamp = TIMER_REG; + func_buf_ptr->value = (uint32_t) func; + + if ((++func_buf_ptr - func_buf) > ((uint32_t) CRIT_FUNC_BUF_SIZE)) { + /* output */ + //otto_says = (func_buf_ptr - func_buf); + otto_says = (uint32_t) func_buf; + } +} + +void __attribute__((__no_instrument_function__)) __cyg_profile_func_exit (void *func, void *caller) { +} diff --git a/projects/OHM/protocol_msg_gateway.c b/projects/OHM/protocol_msg_gateway.c new file mode 100644 index 0000000000..58b2398e83 --- /dev/null +++ b/projects/OHM/protocol_msg_gateway.c @@ -0,0 +1,78 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "protocol_msg_gateway.h" +#include "ohm_protocol.h" + +#define NUM_PROTOCOL_HANDLER_PIDS 8 + +static uint16_t protocol_handler_pid; + +uint16_t pkts_received = 0; + +packet_t packet_buffer[PACKET_BUFFER_SIZE]; + +static void protocol_msg_gateway(void* payload, int msg_size, packet_info_t* packet_info) { + int n = -1; + extern cib_t cib; + + pkts_received++; + if (!cc1100_get_address()) { + puts("No address configured, not processing incoming packet"); + return; + } + + if (protocol_handler_pid <= 0) { + puts("protocol_handler(): received packet without protocol handler. msg dropped."); + return; + } +/* + int mypos = packet_buffer_next++; + if (packet_buffer_next == PACKET_BUFFER_SIZE) packet_buffer_next = 0; +*/ + n = cib_put(&cib); + + if (n != -1) { + packet_t *p = &(packet_buffer[n]); + p->packet_info = *packet_info; + p->msg_size = msg_size; + memcpy(p->payload, payload, msg_size); + } + else { + puts("Buffer full!"); + return; + } + + +/* + m.type = 0; + m.content.value = mypos; + int success = msg_send_int(&m, protocol_handler_pid); + if (! success) { + // should set timer to retry. Dropping pkt for now. + DEBUG("protocol_handler(): msg dropped."); + } +*/ + + thread_wakeup(protocol_handler_pid); +} + +void init_protocol_msg_gateway() { + puts("Init protocol msg gateway"); + cc1100_set_packet_handler(OHM_PROTOCOL_NR, protocol_msg_gateway); +} + +int set_protocol_handler_thread(int pid) { + protocol_handler_pid = pid; + return 0; +} diff --git a/projects/OHM/protocol_msg_gateway.h b/projects/OHM/protocol_msg_gateway.h new file mode 100644 index 0000000000..dd190da99f --- /dev/null +++ b/projects/OHM/protocol_msg_gateway.h @@ -0,0 +1,18 @@ +#ifndef __PROTOCOL_MSG_GATEWAY_H +#define __PROTOCOL_MSG_GATEWAY_H + +#define PACKET_BUFFER_SIZE 32 +#define MAXIMUM_PAYLOAD_SIZE 64 + +typedef struct { + packet_info_t packet_info; + unsigned int msg_size; + char payload[MAXIMUM_PAYLOAD_SIZE]; +} packet_t; + +void init_protocol_msg_gateway(); +int set_protocol_handler_thread(int pid); + +extern packet_t packet_buffer[PACKET_BUFFER_SIZE]; + +#endif /* __PROTOCOL_MSG_GATEWAY_H */ diff --git a/projects/OHM/tests/hello-world b/projects/OHM/tests/hello-world new file mode 100755 index 0000000000..acde8265fe --- /dev/null +++ b/projects/OHM/tests/hello-world @@ -0,0 +1,13 @@ +#!/usr/bin/expect + +set timeout 5 + +spawn pseudoterm $env(PORT) + +expect { + "Hello World!" {} + timeout { exit 1 } +} + +puts "\nTest successful!\n" + From 2919cc18c84c53e1aedb6c7e3f39162635b5ab70 Mon Sep 17 00:00:00 2001 From: Oliver Hahm Date: Wed, 5 Oct 2011 15:35:46 +0200 Subject: [PATCH 10/10] [projects OHM and WEAtHeR] * moved WOR setting from cc1100 driver to project --- projects/OHM/main.c | 2 ++ projects/WEAtHeR_stable/main.c | 2 ++ 2 files changed, 4 insertions(+) diff --git a/projects/OHM/main.c b/projects/OHM/main.c index b6870ab4fd..fab3e26f97 100644 --- a/projects/OHM/main.c +++ b/projects/OHM/main.c @@ -37,6 +37,8 @@ #include "ohm_protocol.h" #include "protocol_msg_gateway.h" +#define CC1100_RADIO_MODE CC1100_MODE_WOR + /* some local defines */ #define SECOND (1000 * 1000) #define MINUTE (1 * SECOND) diff --git a/projects/WEAtHeR_stable/main.c b/projects/WEAtHeR_stable/main.c index ad7fc34558..1ff7aab8a2 100644 --- a/projects/WEAtHeR_stable/main.c +++ b/projects/WEAtHeR_stable/main.c @@ -36,6 +36,8 @@ #include "weather_protocol.h" #include "protocol_msg_gateway.h" +#define CC1100_RADIO_MODE CC1100_MODE_WOR + /* some local defines */ #define SECOND (1000 * 1000) #define MINUTE (1 * SECOND)