Contiki 2.6
|
00001 /* 00002 * Copyright (c) 2010, Mariano Alvira <mar@devl.org> and other contributors 00003 * to the MC1322x project (http://mc1322x.devl.org) and Contiki. 00004 * 00005 * All rights reserved. 00006 * 00007 * Redistribution and use in source and binary forms, with or without 00008 * modification, are permitted provided that the following conditions 00009 * are met: 00010 * 1. Redistributions of source code must retain the above copyright 00011 * notice, this list of conditions and the following disclaimer. 00012 * 2. Redistributions in binary form must reproduce the above copyright 00013 * notice, this list of conditions and the following disclaimer in the 00014 * documentation and/or other materials provided with the distribution. 00015 * 3. Neither the name of the Institute nor the names of its contributors 00016 * may be used to endorse or promote products derived from this software 00017 * without specific prior written permission. 00018 * 00019 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 00020 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 00021 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 00022 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 00023 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 00024 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 00025 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 00026 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 00027 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 00028 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 00029 * SUCH DAMAGE. 00030 * 00031 * This file is part of the Contiki OS. 00032 * 00033 * 00034 */ 00035 00036 #include <stdint.h> 00037 #include <stdio.h> 00038 #include <string.h> 00039 00040 /* contiki */ 00041 #include "radio.h" 00042 #include "sys/process.h" 00043 #include "net/packetbuf.h" 00044 #include "net/netstack.h" 00045 00046 #include "mc1322x.h" 00047 #include "contiki-conf.h" 00048 00049 #define CONTIKI_MACA_DEBUG 0 00050 #if CONTIKI_MACA_DEBUG 00051 #define PRINTF(...) printf(__VA_ARGS__) 00052 #else 00053 #define PRINTF(...) 00054 #endif 00055 00056 #ifndef CONTIKI_MACA_PREPEND_BYTE 00057 #define CONTIKI_MACA_PREPEND_BYTE 0xff 00058 #endif 00059 00060 #ifndef BLOCKING_TX 00061 #define BLOCKING_TX 1 00062 #endif 00063 00064 static volatile uint8_t tx_complete; 00065 static volatile uint8_t tx_status; 00066 00067 /* contiki mac driver */ 00068 00069 int contiki_maca_init(void); 00070 int contiki_maca_on_request(void); 00071 int contiki_maca_off_request(void); 00072 int contiki_maca_read(void *buf, unsigned short bufsize); 00073 int contiki_maca_prepare(const void *payload, unsigned short payload_len); 00074 int contiki_maca_transmit(unsigned short transmit_len); 00075 int contiki_maca_send(const void *payload, unsigned short payload_len); 00076 int contiki_maca_channel_clear(void); 00077 int contiki_maca_receiving_packet(void); 00078 int contiki_maca_pending_packet(void); 00079 00080 const struct radio_driver contiki_maca_driver = 00081 { 00082 .init = contiki_maca_init, 00083 .prepare = contiki_maca_prepare, 00084 .transmit = contiki_maca_transmit, 00085 .send = contiki_maca_send, 00086 .read = contiki_maca_read, 00087 .receiving_packet = contiki_maca_receiving_packet, 00088 .pending_packet = contiki_maca_pending_packet, 00089 .channel_clear = contiki_maca_channel_clear, 00090 .on = contiki_maca_on_request, 00091 .off = contiki_maca_off_request, 00092 }; 00093 00094 static volatile uint8_t contiki_maca_request_on = 0; 00095 static volatile uint8_t contiki_maca_request_off = 0; 00096 00097 static process_event_t event_data_ready; 00098 00099 static volatile packet_t prepped_p; 00100 00101 int contiki_maca_init(void) { 00102 // trim_xtal(); 00103 // vreg_init(); 00104 // contiki_maca_init(); 00105 // set_channel(0); /* channel 11 */ 00106 // set_power(0x12); /* 0x12 is the highest, not documented */ 00107 return 1; 00108 } 00109 00110 /* CCA not implemented */ 00111 int contiki_maca_channel_clear(void) { 00112 return 1; 00113 } 00114 00115 /* not sure how to check if a reception is in progress */ 00116 int contiki_maca_receiving_packet(void) { 00117 return 0; 00118 } 00119 00120 int contiki_maca_pending_packet(void) { 00121 if (rx_head != NULL) { 00122 return 1; 00123 } else { 00124 return 0; 00125 } 00126 } 00127 00128 int contiki_maca_on_request(void) { 00129 contiki_maca_request_on = 1; 00130 contiki_maca_request_off = 0; 00131 return 1; 00132 } 00133 00134 int contiki_maca_off_request(void) { 00135 contiki_maca_request_on = 0; 00136 contiki_maca_request_off = 1; 00137 return 1; 00138 } 00139 00140 /* it appears that the mc1332x radio cannot */ 00141 /* receive packets where the last three bits of the first byte */ 00142 /* is equal to 2 --- even in promiscuous mode */ 00143 int contiki_maca_read(void *buf, unsigned short bufsize) { 00144 volatile uint32_t i; 00145 volatile packet_t *p; 00146 00147 if((p = rx_packet())) { 00148 PRINTF("maca read"); 00149 #if CONTIKI_MACA_RAW_MODE 00150 /* offset + 1 and size - 1 to strip the raw mode prepended byte */ 00151 /* work around since maca can't receive acks bigger than five bytes */ 00152 PRINTF(" raw mode"); 00153 p->length -= 1; 00154 p->offset += 1; 00155 #endif 00156 PRINTF(": p->length 0x%0x bufsize 0x%0x \n\r", p->length, bufsize); 00157 if((p->length) < bufsize) bufsize = (p->length); 00158 memcpy(buf, (uint8_t *)(p->data + p->offset), bufsize); 00159 packetbuf_set_attr(PACKETBUF_ATTR_LINK_QUALITY,p->lqi); 00160 packetbuf_set_attr(PACKETBUF_ATTR_TIMESTAMP,p->rx_time); 00161 #if CONTIKI_MACA_DEBUG 00162 for( i = p->offset ; i < (bufsize + p->offset) ; i++) { 00163 PRINTF(" %02x",p->data[i]); 00164 } 00165 #endif 00166 PRINTF("\n\r"); 00167 free_packet(p); 00168 return bufsize; 00169 } else { 00170 return 0; 00171 } 00172 } 00173 00174 /* copies a payload into the prepped packet */ 00175 /* transmit sends the prepped packet everytime it is called */ 00176 /* Contiki may call prepare once and then transmit several times to send */ 00177 /* the same packet repeatedly */ 00178 int contiki_maca_prepare(const void *payload, unsigned short payload_len) { 00179 volatile int i; 00180 00181 PRINTF("contiki maca prepare"); 00182 #if CONTIKI_MACA_RAW_MODE 00183 prepped_p.offset = 1; 00184 prepped_p.length = payload_len + 1; 00185 #else 00186 prepped_p.offset = 0; 00187 prepped_p.length = payload_len; 00188 #endif 00189 if(payload_len > MAX_PACKET_SIZE) return RADIO_TX_ERR; 00190 memcpy((uint8_t *)(prepped_p.data + prepped_p.offset), payload, payload_len); 00191 #if CONTIKI_MACA_RAW_MODE 00192 prepped_p.offset = 0; 00193 prepped_p.data[0] = CONTIKI_MACA_PREPEND_BYTE; 00194 PRINTF(" raw mode"); 00195 #endif 00196 #if CONTIKI_MACA_DEBUG 00197 PRINTF(": sending %d bytes\n\r", payload_len); 00198 for(i = prepped_p.offset ; i < (prepped_p.length + prepped_p.offset); i++) { 00199 PRINTF(" %02x",prepped_p.data[i]); 00200 } 00201 PRINTF("\n\r"); 00202 #endif 00203 00204 return RADIO_TX_OK; 00205 00206 } 00207 00208 /* gets a packet from the radio (if available), */ 00209 /* copies the prepared packet prepped_p */ 00210 /* and transmits it */ 00211 int contiki_maca_transmit(unsigned short transmit_len) { 00212 volatile packet_t *p; 00213 00214 PRINTF("contiki maca transmit\n\r"); 00215 #if BLOCKING_TX 00216 tx_complete = 0; 00217 #endif 00218 if(p = get_free_packet()) { 00219 p->offset = prepped_p.offset; 00220 p->length = prepped_p.length; 00221 memcpy((uint8_t *)(p->data + p->offset), 00222 (const uint8_t *)(prepped_p.data + prepped_p.offset), 00223 prepped_p.length); 00224 tx_packet(p); 00225 } else { 00226 PRINTF("couldn't get free packet for transmit\n\r"); 00227 return RADIO_TX_ERR; 00228 } 00229 00230 #if BLOCKING_TX 00231 /* block until tx_complete, set by contiki_maca_tx_callback */ 00232 while(!tx_complete && (tx_head != 0)); 00233 #endif 00234 } 00235 00236 int contiki_maca_send(const void *payload, unsigned short payload_len) { 00237 contiki_maca_prepare(payload, payload_len); 00238 contiki_maca_transmit(payload_len); 00239 switch(tx_status) { 00240 case SUCCESS: 00241 case CRC_FAILED: /* CRC_FAILED is usually an ack */ 00242 PRINTF("TXOK\n\r"); 00243 return RADIO_TX_OK; 00244 case NO_ACK: 00245 PRINTF("NOACK\n\r"); 00246 return RADIO_TX_NOACK; 00247 default: 00248 PRINTF("TXERR\n\r"); 00249 return RADIO_TX_ERR; 00250 } 00251 } 00252 00253 PROCESS(contiki_maca_process, "maca process"); 00254 PROCESS_THREAD(contiki_maca_process, ev, data) 00255 { 00256 volatile uint32_t i; 00257 int len; 00258 00259 PROCESS_BEGIN(); 00260 00261 while (1) { 00262 PROCESS_YIELD(); 00263 00264 /* check if there is a request to turn the radio on or off */ 00265 if(contiki_maca_request_on == 1) { 00266 contiki_maca_request_on = 0; 00267 // maca_on(); 00268 } 00269 00270 if(contiki_maca_request_off == 1) { 00271 contiki_maca_request_off = 0; 00272 // maca_off(); 00273 } 00274 00275 if (rx_head != NULL) { 00276 packetbuf_clear(); 00277 len = contiki_maca_read(packetbuf_dataptr(), PACKETBUF_SIZE); 00278 if(len > 0) { 00279 packetbuf_set_datalen(len); 00280 NETSTACK_RDC.input(); 00281 } 00282 } 00283 /* Call ourself again to handle remaining packets in the queue */ 00284 if (rx_head != NULL) { 00285 process_poll(&contiki_maca_process); 00286 } 00287 00288 }; 00289 00290 PROCESS_END(); 00291 } 00292 00293 void maca_rx_callback(volatile packet_t *p __attribute((unused))) { 00294 process_poll(&contiki_maca_process); 00295 } 00296 00297 00298 #if BLOCKING_TX 00299 void maca_tx_callback(volatile packet_t *p __attribute((unused))) { 00300 tx_complete = 1; 00301 tx_status = p->status; 00302 } 00303 #endif