ctdma_mac.c
00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034 #include "contiki.h"
00035 #include "net/mac/ctdma_mac.h"
00036 #include "net/packetbuf.h"
00037 #include "net/uip-fw.h"
00038 #include "sys/ctimer.h"
00039 #include "net/rime.h"
00040 #include "lib/memb.h"
00041 #include "lib/list.h"
00042 #include "dev/leds.h"
00043 #include "node-id.h"
00044
00045 #include <string.h>
00046 #include <stdio.h>
00047
00048 #define DEBUG 1
00049 #if DEBUG
00050 #define DLEDS_ON(x) leds_on(x)
00051 #define DLEDS_OFF(x) leds_off(x)
00052 #define DLEDS_TOGGLE(x) leds_toggle(x)
00053 #define PRINTF(...) printf(__VA_ARGS__)
00054 #else
00055 #define DLEDS_ON(x)
00056 #define DLEDS_OFF(x)
00057 #define DLEDS_TOGGLE(x)
00058 #define PRINTF(...)
00059 #endif
00060
00061
00062 #define NR_SLOTS 3
00063 #define SLOT_LENGTH (CLOCK_SECOND/3)
00064 #define GUARD_PERIOD (CLOCK_SECOND/12)
00065
00066 #define MY_SLOT (node_id % NR_SLOTS)
00067 #define PERIOD_LENGTH CLOCK_SECOND
00068
00069
00070 #define NUM_PACKETS 8
00071 uint8_t lastqueued = 0;
00072 uint8_t nextsend = 0;
00073 uint8_t freeslot = 0;
00074 struct queuebuf* data[NUM_PACKETS];
00075 int id[NUM_PACKETS];
00076
00077 static struct ctimer ctimer;
00078 uint8_t timer_on = 0;
00079
00080 static const struct radio_driver *radio;
00081 static void (* receiver_callback)(const struct mac_driver *);
00082 static int id_counter = 0;
00083 static int sent_counter = 0;
00084
00085
00086 static void
00087 transmitter(void *ptr)
00088 {
00089 clock_time_t now, rest, period_start, slot_start;
00090
00091
00092 now = clock_time();
00093 rest = now % PERIOD_LENGTH;
00094 period_start = now - rest;
00095 slot_start = period_start + MY_SLOT*SLOT_LENGTH;
00096
00097
00098 if (now < slot_start ||
00099 now > slot_start + SLOT_LENGTH - GUARD_PERIOD)
00100 {
00101 PRINTF("TIMER We are outside our slot: %u != [%u,%u]\n", now, slot_start, slot_start + SLOT_LENGTH);
00102 while (now > slot_start + SLOT_LENGTH - GUARD_PERIOD)
00103 {
00104 slot_start += PERIOD_LENGTH;
00105 }
00106
00107 PRINTF("TIMER Rescheduling until %u\n", slot_start);
00108 ctimer_set(&ctimer, slot_start - clock_time(), transmitter, NULL);
00109 return;
00110 }
00111
00112
00113 while (nextsend != freeslot)
00114 {
00115 PRINTF("RADIO Transmitting packet #%i\n", id[nextsend]);
00116 if(!radio->send(
00117 queuebuf_dataptr(data[nextsend]),
00118 queuebuf_datalen(data[nextsend])))
00119 {
00120 sent_counter++;
00121 PRINTF("RADIO Transmit OK for #%i, total=%i\n", id[nextsend], sent_counter);
00122 DLEDS_TOGGLE(LEDS_GREEN);
00123 }
00124 else
00125 {
00126 PRINTF("RADIO Transmit failed for #%i, total=%i\n", id[nextsend], sent_counter);
00127 DLEDS_TOGGLE(LEDS_RED);
00128 }
00129
00130 nextsend = (nextsend + 1) % NUM_PACKETS;
00131
00132
00133 if (clock_time() > slot_start + SLOT_LENGTH - GUARD_PERIOD)
00134 {
00135 PRINTF("TIMER No more time to transmit\n");
00136 break;
00137 }
00138 }
00139
00140
00141 slot_start += PERIOD_LENGTH;
00142 PRINTF("TIMER Rescheduling until %u\n", slot_start);
00143 ctimer_set(&ctimer, slot_start - clock_time(), transmitter, NULL);
00144 }
00145
00146 static int
00147 send(void)
00148 {
00149 id_counter++;
00150
00151
00152 while (lastqueued != nextsend)
00153 {
00154 PRINTF("BUFFER Cleaning up packet #%i\n", id[lastqueued]);
00155 queuebuf_free(data[lastqueued]);
00156 data[lastqueued] = NULL;
00157
00158 lastqueued = (lastqueued + 1) % NUM_PACKETS;
00159 }
00160
00161 if ((freeslot + 1) % NUM_PACKETS == lastqueued)
00162 {
00163 PRINTF("BUFFER Buffer full, dropping packet #%i\n", (id_counter+1));
00164 return UIP_FW_DROPPED;
00165 }
00166
00167
00168 data[freeslot] = queuebuf_new_from_packetbuf();
00169 id[freeslot] = id_counter;
00170 if (data[freeslot] == NULL)
00171 {
00172 PRINTF("BUFFER Queuebuffer full, dropping packet #%i\n", id[freeslot]);
00173 return UIP_FW_DROPPED;
00174 }
00175 PRINTF("BUFFER Wrote packet #%i to buffer \n", id[freeslot]);
00176
00177 freeslot = (freeslot + 1) % NUM_PACKETS;
00178
00179 if (!timer_on)
00180 {
00181 PRINTF("TIMER Starting timer\n");
00182 ctimer_set(&ctimer, CLOCK_SECOND, transmitter, NULL);
00183 timer_on = 1;
00184 }
00185
00186 return UIP_FW_OK;
00187 }
00188
00189 static void
00190 input(const struct radio_driver *d)
00191 {
00192 receiver_callback(&ctdma_mac_driver);
00193 }
00194
00195 static int
00196 read(void)
00197 {
00198 int len;
00199 packetbuf_clear();
00200 len = radio->read(packetbuf_dataptr(), PACKETBUF_SIZE);
00201 packetbuf_set_datalen(len);
00202 return len;
00203 }
00204
00205 static void
00206 set_receive_function(void (* recv)(const struct mac_driver *))
00207 {
00208 receiver_callback = recv;
00209 }
00210
00211 static int
00212 on(void)
00213 {
00214 return radio->on();
00215 }
00216
00217 static int
00218 off(int keep_radio_on)
00219 {
00220 if(keep_radio_on) {
00221 return radio->on();
00222 } else {
00223 return radio->off();
00224 }
00225 }
00226
00227 const struct mac_driver *
00228 ctdma_mac_init(const struct radio_driver *d)
00229 {
00230 int i;
00231 for (i=0; i < NUM_PACKETS; i++)
00232 {
00233 data[i] = NULL;
00234 }
00235
00236 radio = d;
00237 radio->set_receive_function(input);
00238 radio->on();
00239 return &ctdma_mac_driver;
00240 }
00241
00242 const struct mac_driver ctdma_mac_driver = {
00243 "CTDMA",
00244 ctdma_mac_init,
00245 send,
00246 read,
00247 set_receive_function,
00248 on,
00249 off,
00250 };