void ieee802frame154_dump( TiFrame * f ) { int8 len; TiIEEE802Frame154Descriptor meta; len = frame_length(f); if (len > 0) { dbc_putchar( '>' ); dbc_n8toa( len ); ieee802frame154_open( &meta ); if (ieee802frame154_parse(&meta, frame_startptr(f), frame_length(f))) { dbc_putchar( ':' ); dbc_write_n8toa( frame_startptr(f), len ); dbc_putchar( 0xFC ); dbc_putchar( '\r' ); dbc_putchar( '\n' ); } else{ // if parsing failed, then we also output the data dbc_putchar( 0xFC ); dbc_write_n8toa( frame_startptr(f), len ); dbc_putchar( '\r' ); dbc_putchar( '\n' ); } } else{ // If the f doesn't contain any data, then still output some flag for indication. dbc_putchar( 0xFB ); dbc_putchar( 0xFB ); } }
/** * Check whether there's some frame arrivaled. This function can be called anytime. */ uintx aloha_recv( TiAloha * mac, TiFrame * frame, uint8 option ) { const uint8 HEADER_SIZE = 12, TAIL_SIZE = 2; uint8 count; char * ptr=NULL; // move the frame current layer to mac protocol related layer. the default layer // only contains the data (mac payload) rather than mac frame. frame_skipouter( frame, HEADER_SIZE, TAIL_SIZE ); // assert: the skipouter must be success count = _aloha_tryrecv( mac, frame_startptr(frame), frame_capacity(frame), option ); if (count > 0) { // the first byte in the frame buffer is the length byte. it represents the // MPDU length. after received the frame, we first check whether this is an // incomplete frame or not. if it's an bad frame, then we should ignore it. // ptr = frame_startptr(frame); if (*ptr == count-1) { // get the pointer to the frame control field according to 802.15.4 frame format // we need to check whether the current frame is a DATA type frame. // only the DATA type frame will be transfered to upper layers. The other types, // such as COMMAND, BEACON and ACK will be ignored here. // buf[0] is the length byte. buf[1] and buf[2] are frame control bytes. ptr ++; if (FCF_FRAMETYPE(*(ptr)) != FCF_FRAMETYPE_DATA) { count = 0; } else{ frame_setlength( frame, count ); frame_setcapacity( frame, count ); } } } frame_moveinner( frame ); if (count > 0) { frame_setlength( frame, count - HEADER_SIZE - TAIL_SIZE ); frame_setcapacity( frame, count - HEADER_SIZE - TAIL_SIZE ); } else{ frame_setlength( frame, 0 ); } aloha_evolve( mac, NULL ); return count; }
/* Broadcast a frame in the network. In most cases, the frame should be able to * reach every node in the network, but no guarantee about this. */ uintx flood_broadcast( TiFloodNetwork * net, TiFrame * frame, uint8 option ) { uintx count=0; uintx i = 0;//todo char * pc; /* This function will try to put the frame into TiFloodNetwork's internal TX buffer. * The real sending processing is in flood_evolve(). */ i = frame_length( frame);//todo if (frame_empty(net->txque)) { net->txque->option = option; count = frame_totalcopyfrom( net->txque, frame ); frame_skipouter( net->txque, 4, 0 );//todo 执行这一局后frame_length又变回0了! frame_setlength( net->txque,(i+4));//todo // assert( frame_skipouter must be success ); pc = frame_startptr( net->txque ); PACKET_SET_HOPCOUNT( pc,0 ); PACKET_SET_MAX_HOPCOUNT(pc , CONFIG_FLOOD_MAX_COUNT ); PACKET_SET_CURSEQID(pc, net->seqid ); } flood_evolve( net, NULL ); return count; }
void _output_frame( TiFrame * frame, TiUartAdapter * uart ) { static TiIEEE802Frame154Descriptor m_desc; TiIEEE802Frame154Descriptor * desc; if (frame_totallength(frame) > 0) { dbc_putchar( '>' ); dbc_n8toa( frame_totallength(frame) ); desc = ieee802frame154_open( &m_desc ); // ? if (ieee802frame154_parse(desc, frame_startptr(frame), frame_length(frame))) if (ieee802frame154_parse(desc, frame_startptr(frame), frame_capacity(frame))) { // if the frame received is parsed successfully, then output it to the // computer through debugging channel //ieee802frame154_set_sequence( desc, seqid ++ ); //ieee802frame154_set_panto( desc, CONFIG_ALOHA_DEFAULT_PANID ); //ieee802frame154_set_shortaddrto( desc, CONFIG_ALOHA_REMOTE_ADDRESS ); //ieee802frame154_set_panfrom( desc, CONFIG_ALOHA_PANID); //ieee802frame154_set_shortaddrfrom( desc, CONFIG_ALOHA_LOCAL_ADDRESS ); // todo: you can output more // reference frame_dump() in rtl_frame.c dbc_n8toa( ieee802frame154_sequence(desc) ); dbc_putchar( ':' ); dbc_write( frame_startptr(frame), frame_capacity(frame) ); } else{ // if the frame received is parsed failed, then output the error frame // to the computer through debugging channel dbc_putchar( 'X' ); dbc_putchar( ':' ); dbc_write( frame_startptr(frame), frame_capacity(frame) ); } dbc_putchar( '\r' ); dbc_putchar( '\n' ); } }
void ieee802frame154_dump( TiFrame * f ) { int8 len; TiIEEE802Frame154Descriptor meta; len = frame_length(f); if (len > 0) { dbc_putchar( 0xFA ); dbc_putchar( 0xFA ); dbc_putchar( frame_curlayer(f) ); dbc_putchar( len ); // if the frame received is parsed successfully, then output it to the // computer through debugging channel // ieee802frame154_open( &meta ); if (ieee802frame154_parse(&meta, frame_startptr(f), frame_length(f))) { // todo: you can output more // reference frame_dump() in rtl_frame.c dbc_putchar( 0xFB ); dbc_write( frame_startptr(f), len ); dbc_putchar( 0xFC ); } else{ // if parsing failed, then we also output the data dbc_putchar( 0xFC ); dbc_write( frame_startptr(f), len ); } } else{ // If the f doesn't contain any data, then still output some flag for indication. dbc_putchar( 0xFB ); dbc_putchar( 0xFB ); } }
int main(void) { uint16 value, count; uint8 len; char * request; char * response; char * payload; char * msg = "welcome to node..."; TiTimerAdapter * timeradapter; TiTimerManager * vtm; TiTimer * mac_timer; TiCc2420Adapter * cc; TiFrameRxTxInterface * rxtx; TiNioAcceptor * nac; TiAloha * mac; TiAdcAdapter * adc; TiLumSensor * lum; TiDataTreeNetwork * dtp; TiFrame * rxbuf; TiFrame * txbuf; target_init(); led_open(); led_on( LED_ALL ); hal_delay( 500 ); led_off( LED_ALL ); rtl_init( (void *)dbio_open(38400), (TiFunDebugIoPutChar)dbio_putchar, (TiFunDebugIoGetChar)dbio_getchar, hal_assert_report ); dbc_write( msg, strlen(msg) ); timeradapter = timer_construct( (void *)(&m_timeradapter), sizeof(m_timeradapter) ); vtm = vtm_construct( (void*)&m_vtm, sizeof(m_vtm) ); cc = cc2420_construct( (char *)(&m_cc), sizeof(TiCc2420Adapter) ); nac = nac_construct( &m_nacmem[0], NAC_SIZE ); mac = aloha_construct( (char *)(&m_aloha), sizeof(TiAloha) ); dtp = dtp_construct( (char *)(&m_dtp), sizeof(TiDataTreeNetwork) ); adc = adc_construct( (void *)&m_adc, sizeof(TiAdcAdapter) ); lum = lum_construct( (void *)&m_lum, sizeof(TiLumSensor) ); txbuf = frame_open( (char*)(&m_txbuf), FRAME_HOPESIZE(MAX_IEEE802FRAME154_SIZE), 3, 20, 0 ); rxbuf = frame_open( (char*)(&m_rxbuf), FRAME_HOPESIZE(MAX_IEEE802FRAME154_SIZE), 3, 20, 0 ); // timeradapter is used by the vtm(virtual timer manager). vtm require to enable the // period interrupt modal of vtm //timeradapter = timer_open( timeradapter, 0, NULL, NULL, 0x01 ); vtm = vtm_open( vtm, timeradapter, CONFIG_VTM_RESOLUTION ); cc = cc2420_open(cc, 0, NULL, NULL, 0x00 ); rxtx = cc2420_interface( cc, &m_rxtx ); mac_timer = vtm_apply( vtm ); mac_timer = vti_open( mac_timer, NULL, mac_timer); hal_assert( rxtx != NULL ); nac = nac_open( nac, rxtx, CONFIG_NIOACCEPTOR_RXQUE_CAPACITY, CONFIG_NIOACCEPTOR_TXQUE_CAPACITY); hal_assert( nac != NULL ); mac = aloha_open( mac, rxtx,nac, CONFIG_NODE_CHANNEL, CONFIG_NODE_PANID, CONFIG_NODE_ADDRESS,mac_timer, NULL, NULL,0x01); adc = adc_open( adc, 0, NULL, NULL, 0 ); lum = lum_open( lum, 0, adc ); dtp = dtp_open( dtp, mac, CONFIG_NODE_ADDRESS, NULL, NULL, 0x00 ); //todo cc2420_setchannel( cc, CONFIG_NODE_CHANNEL ); cc2420_setrxmode( cc ); // enable RX mode cc2420_setpanid( cc, CONFIG_NODE_PANID ); // network identifier, seems no use in sniffer mode cc2420_setshortaddress( cc, CONFIG_NODE_ADDRESS ); // in network address, seems no use in sniffer mode cc2420_enable_autoack( cc ); //todo cc2420_settxpower( cc, CC2420_POWER_1);//cc2420_settxpower( cc, CC2420_POWER_2); cc2420_enable_autoack( cc ); // ledtune = ledtune_construct( (void*)(&m_ledtune), sizeof(m_ledtune), vti ); // ledtune = ledtune_open( ledtune ); /* assert: all the above open() functions return non NULL values */ hal_assert((timeradapter != NULL) && (cc != NULL) && (mac != NULL) && (adc != NULL) && (lum != NULL) && (rxbuf != NULL) && (txbuf != NULL) && (dtp != NULL)); hal_enable_interrupts(); dtp->state = DTP_STATE_IDLE;//todo for testing 临时用这一句必须删掉 //todo for testing //dtp->root = 0x01;//todo for testing //dtp->parent = 0x03;//todo for testing /* while ( 1)//todo for testing { response = frame_startptr( txbuf ); value = lum_value( lum ); payload = DTP_PAYLOAD_PTR(response); payload[0] = 0x13; payload[1] = 0x14; if (dtp_send_response(dtp, txbuf, 0x01) > 0) { led_toggle( LED_RED);//todo for testing } dtp_evolve( dtp, NULL ); hal_delay( 2000);//todo for testing } */ while(1) { /* Only the following two kinds of frames will be put into "rxbuf" by dtp_recv() * - broadcast frames. the destination address of these frames are 0xFFFF. * - destination is the current node. */ //dbo_putchar(0x33); len = dtp_recv( dtp, rxbuf, 0x00 ); if (len > 0) { //ieee802frame154_dump( rxbuf); request = frame_startptr( rxbuf ); switch (DTP_CMDTYPE(request)) { /* if the frame is DTP_DATA_REQUEST, then the node will measure the data and * encapsulate the data into the txbuf, which is a TiOpenFrame and sent it back. */ case DTP_DATA_REQUEST: //payload = DTP_PAYLOAD_PTR( frame_startptr(txbuf) ); //ledtune_write( ledtune, MAKE_WORD(payload[1], payload[0]) ); // response frame = PHY Length 1B // + Frame Control 2B // + Sequence No 1B // + Destination Pan & Address 4B // + Source Pan & Address 4B // + DTP Section 15B //opf_cast( txbuf, 50, OPF_DEF_FRAMECONTROL_DATA_ACK ); response = frame_startptr( txbuf ); value = lum_value( lum ); DTP_SET_MAX_HOPCOUNT( response,0x03);//todo for testing payload = DTP_PAYLOAD_PTR(response); //payload[0] = 0x17;//todo 第三个节点数据 //payload[1] = 0x18;//todo 第三个节点数据 //payload[1] = 0x13; //payload[2] = 0x14; payload[1] = 0x15;//todo 另一个节点 payload[2] = 0x16;//todo 另一个节点 /* call dtp_send_response() to send the data in txbuf out. * * modified by zhangwei on 20091230 * - Bug fix. In the past, there's no delay between two adjacent * dtp_send_response() calls. This policy is too ambitious and this * node will occupy the whole time so that the other nodes will lost * chances to send, or encounter much higher frame collision probabilities. * so I add a little time delay here. * Attention the delay time here shouldn't be too large because * we don't want the hal_delay() to occupy all the CPU time. If this * occurs, it may lead to unnecessary frame lossing. */ // try some times until the RESPONSE is successfully sent for (count=0; count<10; count++) { //hal_delay( 500); if (dtp_send_response(dtp, txbuf, 0x03) > 0) { led_toggle( LED_RED);//todo for testing break; } //hal_delay( 50 ); } break; default: //hal_assert(false); break; } } nac_evolve( nac,NULL);//todo for tesitng aloha_evolve( mac,NULL);//todo for testing dtp_evolve( dtp, NULL ); hal_delay( 50 ); } }
void ieee802frame154_dumpframe( TiFrame * frame ) { frame_movelowest(frame); ieee802frame154_dumpmembuf(frame_startptr(frame), frame_length(frame)); }
void tinymac_recvnode(void) { TiCc2420Adapter * cc; TiFrameRxTxInterface * rxtx;; TiTinyMAC * mac; TiTimerAdapter *timer; TiFrame * rxbuf; char * msg = "welcome to tinymac recv test..."; int len=0; target_init(); // flash the led to indicate the software is successfully running now. // led_open(); led_on( LED_ALL ); hal_delay( 500 ); led_off( LED_ALL ); led_on( LED_RED ); // initialize the runtime library for debugging input/output and assertion // hal_assert_report is defined in module "hal_assert" // //dbo_open( 38400 ); rtl_init( (void *)dbio_open(38400), (TiFunDebugIoPutChar)dbio_putchar, (TiFunDebugIoGetChar)dbio_getchar, hal_assert_report ); dbc_putchar( 0xF0 ); dbc_mem( msg, strlen(msg) ); cc = cc2420_construct( (void *)(&m_cc), sizeof(TiCc2420Adapter) ); mac = tinymac_construct((char *)(&m_tiny), sizeof(TiTinyMAC)); timer= timer_construct((char *)(&m_timer),sizeof(TiTimerAdapter)); #ifdef CONFIG_TSET_LISTENER // cc = cc2420_open( cc, 0, _aloha_listener, NULL, 0x00 ); cc = cc2420_open( cc, 0, tinymac_evolve, mac, 0x00 ); rxtx = cc2420_interface( cc, &m_rxtx ); mac = tinymac_open( mac, rxtx, CONFIG_CHANNEL, CONFIG_PANID, CONFIG_LOCAL_ADDRESS, timer, _tinymac_listener, NULL,0x00 ); #endif #ifndef CONFIG_TSET_LISTENER cc = cc2420_open( cc, 0, NULL, NULL, 0x00 ); rxtx = cc2420_interface( cc, &m_rxtx ); mac = tinymac_open( mac, rxtx, CONFIG_CHANNEL, CONFIG_PANID, CONFIG_LOCAL_ADDRESS, NULL, NULL,0x00 ); #endif cc2420_setchannel( cc, CONFIG_CHANNEL ); cc2420_setrxmode( cc ); // enable RX mode cc2420_setpanid( cc, CONFIG_PANID ); // network identifier, seems no use in sniffer mode cc2420_setshortaddress( cc, CONFIG_LOCAL_ADDRESS ); // in network address, seems no use in sniffer mode cc2420_enable_autoack( cc ); #ifdef CONFIG_TEST_ADDRESSRECOGNITION cc2420_enable_addrdecode( cc ); #else cc2420_disable_addrdecode( cc ); #endif #ifdef CONFIG_TEST_ACK cc2420_enable_autoack( cc ); #endif rxbuf = frame_open( (char*)(&m_rxbufmem), FRAME_HOPESIZE(MAX_IEEE802FRAME154_SIZE), 3, 20, 0 ); #ifdef CONFIG_TEST_ACK //fcf = OPF_DEF_FRAMECONTROL_DATA_ACK; #else //fcf = OPF_DEF_FRAMECONTROL_DATA_NOACK; #endif hal_enable_interrupts(); /* Wait for listener action. The listener function will be called by the TiCc2420Adapter * object when a frame arrives */ #ifdef CONFIG_TEST_LISTENER while (1) {} #endif /* Query the TiCc2420Adapter object if there's no listener */ #ifndef CONFIG_TEST_LISTENER while(1) { frame_reset( rxbuf, 3, 20, 0 ); len = tinymac_recv( mac, rxbuf, 0x00 ); if (len > 0) { dbc_putchar( 0xF3 ); dbc_mem( frame_startptr(rxbuf), frame_length(rxbuf) ); //frame_moveouter( rxbuf ); //_output_frame( rxbuf, NULL ); //frame_moveinner( rxbuf ); led_off( LED_RED ); /* warning: You shouldn't wait too long in the while loop, or else * you may encounter frame loss. However, the program should still * work properly even the delay time is an arbitrary value. No error * are allowed in this case. */ //hal_delay( 500 ); led_toggle( LED_RED ); //hal_delay( 500 ); } tinymac_evolve(mac, NULL ); } #endif frame_close( rxbuf ); tinymac_close( mac ); cc2420_close( cc ); }
/* this function can be used as TiCc2420Adapter's listener directly. so you can get * to know when a new frame arrives through the event's id. however, the TiCc2420Adapter's * listener is fired by ISR. so we don't suggest using aloha_evolve() as TiCc2420Adapter's * listener directly. * * the evolve() function also behaviors like a thread. */ void aloha_evolve( void * macptr, TiEvent * e ) { TiAloha * mac = (TiAloha *)macptr; mac->rxtx->evolve( mac->rxtx, NULL ); // try sending the frame in mac->txbuf. if sending successfully, then transfer // to IDLE state. if failed, then still in WAITFOR_SENDING state. switch (mac->state) { case ALOHA_STATE_BACKOFF: if (vti_expired(mac->timer)) { // if _aloha_trysend() returns positive value, then it means the frame // has been sent successfully. if it returns negative value, then it means // the frame has reached its maximum retry count. // // in the above two cases, the state should transfer to IDLE state. // if the frame is failed sending and need retry, then _alohs_trysend() will // return 0; // @modified by zhangwei on 2010.08.20 // there're three cases for the result of _aloha_trysend(). if it return // positive value, then it means the frame has been sent successfully. // if it return 0, then means it sends nothing and you should retry the // sending again. if it returns negtive value, then it means this frame // has reached its maximum number retry count and should report sending // failure. // _aloha_trysend(mac, frame_startptr(mac->txbuf), frame_capacity(mac->txbuf), mac->sendoption ); } break; case ALOHA_STATE_IDLE: break; case ALOHA_STATE_SLEEPING: /* if (e->id = wakeuprequest) { phy_wakeup(); mac->state = ADTALOHA_IDLE; } */ default: break; } // attention the following process can occur in any state. if (e != NULL) { switch (e->id) { case EVENT_DATA_ARRIVAL: if (mac->listener != NULL) { mac->listener( mac->lisowner, e ); } break; /* case ADTALOHA_EVENT_SHUTDOWN_REQUEST: // no matter what the current state is, then you can do shutdown vti_stop(); phy_shutdown(); mac->state = SHUTDOWN; break; case ADTALOHA_EVENT_STARTUP_REQUEST: if (mac->state == SHUTDOWN) { phy_startup(); mac->state = IDLE; } */ default: break; } } return; }
uintx aloha_broadcast( TiAloha * mac, TiFrame * frame, uint8 option ) { uintx ret=0; TiIEEE802Frame154Descriptor * desc; switch (mac->state) { case ALOHA_STATE_IDLE: frame_totalcopyfrom( mac->txbuf, frame ); // according to 802.15.4 specification: // header 12 B = 1B frame length (required by the transceiver driver currently) // + 2B frame control + 1B sequence number + 2B destination pan + 2B destination address // + 2B source pan + 2B source address // frame_skipouter( mac->txbuf, 12, 2 ); desc = ieee802frame154_format( &(mac->desc), frame_startptr(frame), frame_capacity(frame), FRAME154_DEF_FRAMECONTROL_DATA_NOACK ); rtl_assert( desc != NULL ); ieee802frame154_set_sequence( desc, mac->seqid ); ieee802frame154_set_panto( desc, mac->panto ); ieee802frame154_set_shortaddrto( desc, FRAME154_BROADCAST_ADDRESS ); ieee802frame154_set_panfrom( desc, mac->panfrom ); ieee802frame154_set_shortaddrfrom( desc, mac->shortaddrfrom ); // char * fcf; // char * shortaddrto; // fcf = frame_startptr(frame); // shortaddrto = (char*)(frame_startptr(frame)) + 3; // todo: according to IEEE 802.15.4 format, 加几?请参考15.4文档确认 // for broadcasting frames, we don't need acknowledgements. so we clear the ACK // REQUEST bit in the frame control field. // refer to 802.15.4 protocol format // // fcf ++; // (*fcf) &= 0xFA; // TODO: this value should changed according to 802.15.4 format // 0xFFFFFFFF the broadcast address according to 802.15.4 protocol format // attention: we only set the destination short address field to broadcast address. // the destination pan keeps unchanged. // // *shortaddrto ++ = 0xFF; // *shortaddrto ++ = 0xFF; //frame_moveinner( mac->txbuf ); mac->sendoption = option; // standard aloha protocol behavior #ifdef CONFIG_ALOHA_STANDARD if (mac->rxtx->ischnclear(mac)) { _aloha_trysend( mac, frame_startptr(mac->txbuf), frame_capacity(mac->txbuf), option ); } else{ mac->backoff = rand_uint8( CONFIG_ALOHA_MAX_BACKOFF ); mac->retry = 0; vti_setinterval( mac->timer, mac->backoff, 0 ); vti_start( mac->timer ); mac->state = ALOHA_STATE_BACKOFF; } #endif // optimized aloha protocol behavior. it will insert a random delay before // sending to decrease the probability of conflictions. // wait for a random period before really start the transmission #ifdef CONFIG_ALOHA_STANDARD mac->backoff = rand_uint8( CONFIG_ALOHA_MAX_BACKOFF ); mac->retry = 0; vti_setinterval( mac->timer, mac->backoff, 0 ); vti_start( mac->timer ); mac->state = ALOHA_STATE_BACKOFF; #endif ret = frame_capacity( mac->txbuf ); aloha_evolve( mac, NULL ); break; case ALOHA_STATE_BACKOFF: // in this state, there's already a frame pending inside the aloha object. // you have no better choice but wait for this frame to be processed. // aloha_evolve( mac, NULL ); ret = 0; break; case ALOHA_STATE_SLEEPING: default: // currently, this version implementation will ignore any frame sending request // if the mac component is still in sleeping state. you should wakeup it and // then retry aloha_send() again. ret = 0; break; } return ret; }
uintx aloha_send( TiAloha * mac, TiFrame * frame, uint8 option ) { TiIEEE802Frame154Descriptor * desc; uintx ret=0; switch (mac->state) { case ALOHA_STATE_IDLE: frame_totalcopyfrom( mac->txbuf, frame ); // according to 802.15.4 specification: // header 12 B = 1B frame length (required by the transceiver driver currently) // + 2B frame control + 1B sequence number + 2B destination pan + 2B destination address // + 2B source pan + 2B source address // //frame_dump(mac->txbuf); frame_skipouter( mac->txbuf, 12, 2 ); desc = ieee802frame154_format( &(mac->desc), frame_startptr(mac->txbuf), frame_capacity(mac->txbuf), FRAME154_DEF_FRAMECONTROL_DATA ); rtl_assert( desc != NULL ); ieee802frame154_set_sequence( desc, mac->seqid ); ieee802frame154_set_panto( desc, mac->panto ); ieee802frame154_set_shortaddrto( desc, mac->shortaddrto ); ieee802frame154_set_panfrom( desc, mac->panfrom ); ieee802frame154_set_shortaddrfrom( desc, mac->shortaddrfrom ); //frame_moveinner( mac->txbuf ); mac->sendoption = option; // standard aloha protocol behavior #ifdef CONFIG_ALOHA_STANDARD /* * @modified by XuFuzhen on 2010.09.29 * - bug fix. should replace frame_length() here with frame_capacity() */ if (mac->rxtx->ischnclear(mac)) { _aloha_trysend( mac, frame_startptr(mac->txbuf), frame_capacity(mac->txbuf), option ); } else{ mac->backoff = rand_uint8( CONFIG_ALOHA_MAX_BACKOFF ); mac->retry = 0; vti_setinterval( mac->timer, mac->backoff, 0 ); vti_start( mac->timer ); mac->state = ALOHA_STATE_BACKOFF; } #endif // optimized aloha protocol behavior. it will insert a random delay before // sending to decrease the probability of conflictions. // wait for a random period before really start the transmission #ifndef CONFIG_ALOHA_STANDARD mac->backoff = rand_uint8( CONFIG_ALOHA_MAX_BACKOFF ); mac->retry = 0; vti_setinterval( mac->timer, mac->backoff, 0 ); vti_start( mac->timer ); mac->state = ALOHA_STATE_BACKOFF; #endif /* @modified by openwsn on 2010.08.30 * - bug fix. you should place the frame_length() call before aloha_evolve() * because aloha_evolve() may send mac->txbuf and clear it. this will cause * frame_length() returns 0 instead of the real frame length. * * @modified by XuFuzhen on 2010.09.29 * - bug fix. should replace frame_length() here with frame_capacity() */ ret = frame_capacity( mac->txbuf ); aloha_evolve( mac, NULL ); break; case ALOHA_STATE_BACKOFF: // in this state, there's already a frame pending inside the aloha object. // you have no better choice but wait for this frame to be processed. // aloha_evolve( mac, NULL ); ret = 0; break; case ALOHA_STATE_SLEEPING: default: // currently, this version implementation will ignore any frame sending request // if the mac component is still in sleeping state. you should wakeup it and // then retry aloha_send() again. ret = 0; break; } return ret; }
//#if (TEST_CHOICE == 1) void recvnode1(void) { TiCc2420Adapter * cc; char * msg = "welcome to recvnode..."; TiFrame * rxbuf; uint8 len; target_init(); HAL_SET_PIN_DIRECTIONS(); wdt_disable(); led_open(); led_on( LED_RED ); hal_delay( 500 ); led_off( LED_ALL ); rtl_init( (void *)dbio_open(38400), (TiFunDebugIoPutChar)dbio_putchar, (TiFunDebugIoGetChar)dbio_getchar, hal_assert_report ); dbc_mem( msg, strlen(msg) ); cc = cc2420_construct( (void *)(&g_cc), sizeof(TiCc2420Adapter) ); cc2420_open( cc, 0, NULL, NULL, 0x00 ); cc2420_setchannel( cc, DEFAULT_CHANNEL ); cc2420_setrxmode( cc ); //Enable RX cc2420_enable_addrdecode( cc ); //使能地址译码 //cc2420_disable_addrdecode(cc); #ifdef TEST_ACK cc2420_enable_autoack(cc); #endif cc2420_setpanid( cc, PANID ); //网络标识 cc2420_setshortaddress( cc, LOCAL_ADDRESS ); //网内标识 rxbuf = frame_open( (char*)(&m_rxbuf), FRAME_HOPESIZE(MAX_IEEE802FRAME154_SIZE), 0, 0, 0 ); hal_enable_interrupts(); // when use this scan mode to receive data, interrupt should be disable; otherwise the data will be // read twice and in the second time there are no data actually which leads to a assert. // Attention: in this scan mode, MCU always try to read and in my test it is faster than the transmission of data. // Thus, after 4 times, there no data at all, and the MCU still want to read, which lead to an assert. So we'd better // not use this scan mode. while(1) { frame_reset( rxbuf,0,0,0); cc2420_evolve( cc ); //len = cc2420_read( cc, frame_startptr( rxbuf), frame_capacity( rxbuf), 0x00 ); len = cc2420_read( cc, frame_startptr(rxbuf), frame_capacity(rxbuf), 0x00 ); if ( len) { frame_setlength( rxbuf,len); dbc_write( frame_startptr( rxbuf), len ); led_toggle( LED_GREEN); } //len = cc2420_read( cc, (char*)(&buf[0]), BUF_SIZE, 0x00 ); /* if (len >= 5) { // output this frame to the computer through uart dbo_write( (char*)(&buf[0]), len ); }*/ } }
/* This function receive event from other services/objects and drive the evolution * of the TiFloodNetwork service. * * This function can also be the listener of the MAC layer, Though it's not mandatory. * * @attention: * This function cannot run in the interrupt mode. */ void flood_evolve( void * netptr, TiEvent * e ) { TiFloodNetwork * net = (TiFloodNetwork *)netptr; uint8 len, count, cur_hopcount, max_hopcount; bool done = true, cont= false; char * pc; aloha_evolve( net->mac,e ); // This event is sent from MAC layer. // // @todo // Currently, all the frames from MAC layer will submitted the listener function. // Actually, this isn't necessary. Only those to this node should submitted to // the listener. // if (e->id == EVENT_DATA_ARRIVAL) { if (net->listener != NULL) { net->listener( net->lisowner, e ); return; } } do{ switch (net->state) { // IDLE is the initial and default state of this state machine. case FLOOD_STATE_IDLE: // Check if the TX queue is empty. If not then try to send the frame. if (!frame_empty(net->txque)) { len = aloha_broadcast( net->mac, net->txque, net->txque->option ); if (len > 0) { frame_bufferclear( net->txque ); } // @attention // @todo: if the aloha_send() is non-blocked operation, then you should // transfer to FLOOD_STATE_WAITFOR_TXREPLY state to wait. You should empty // the buffer only when this service receives the reply from MAC layer. //net->state = FLOOD_STATE_WAIT_TXREPLY done = true; } // Check if the RX queue is empty, then try to receive one from MAC layer if ((frame_empty(net->rxbuf)) && frame_empty(net->rxque)) { cont = true; count = aloha_recv( net->mac, net->rxbuf, 0x00 ); if (count <= 0) cont = false; // Check: whether the same frame has already been received. This // is by searching it in the cache. If it cannot find it in the // cache, then put the frame in the cache. // // @modified by zhangwei on 2011.03.14 // - we use the first 4 bytes in the frame (which is essentially // the header of flood protocol as the key to visit the cache. // if (cont) { if (flood_cache_visit( net->cache, (char*)frame_startptr(net->rxbuf) ))//todo 我将CONFIG_FLOOD_CACHE_CAPACITY改成了1原先为8,不改的话不再接收新的帧. { frame_bufferclear( net->rxbuf ); cont = false; } } if (cont) { frame_totalcopyto( net->rxbuf, net->rxque ); // Check whether this frame has reaches its maximum hopcount. // Discard this frame if this is true. char * pc; pc = frame_startptr( net->rxbuf); cur_hopcount = PACKET_CUR_HOPCOUNT( pc ); max_hopcount = PACKET_MAX_HOPCOUNT( pc); cur_hopcount ++; if (cur_hopcount > max_hopcount) frame_bufferclear( net->rxbuf ); else PACKET_SET_HOPCOUNT( pc, cur_hopcount ); } done = true; } // Check whether there's frame pending for forwarding if ((!frame_empty(net->rxbuf)) && frame_empty(net->txque)) { pc = frame_startptr( net->txque); // move the frame from rxbuf to txque. For efficiency reasons, this is implmented // by switching the two pointers. _switch_ptr( &(net->rxbuf), &(net->txque) ); // @attention // generally, you should change the frame in "txque" with the PAN id // and BROADCAST_ADDRESS configured in this flood component. However, // here we assume the low level medium access protocol helps us to do so. cur_hopcount = PACKET_CUR_HOPCOUNT( pc ); PACKET_SET_HOPCOUNT( pc, cur_hopcount++ ); done = false; } break; // This's the state waiting for MAC layer's reply. The sending process of the // MAC layer may last for quite a long time due to re-transmission. Only at the // end of the transmission, the MAC layer does possible to notify the NET layer // the transmission results of the sending request. // /*case FLOOD_STATE_WAITFOR_TXREPLY: ioresult = aloha_ioresult(net->mac); if ioresult == IDLE|TXDONE { opf_clear( net->txque ); net->state = FLOOD_STATE_IDLE; } // if ioresult indicate there's error or failure // report to the master program by call net->listener net->state = FLOOD_STATE_IDLE; break;*/ default: net->state = FLOOD_STATE_IDLE; } }while (!done); return; }