/*---------------------------------------------------------------------------*/ PROCESS_THREAD(cc2420_process, ev, data) { PROCESS_BEGIN(); PRINTF("cc2420_process: started\n"); while(1) { PROCESS_YIELD_UNTIL(ev == PROCESS_EVENT_POLL); #if CC2420_TIMETABLE_PROFILING TIMETABLE_TIMESTAMP(cc2420_timetable, "poll"); #endif /* CC2420_TIMETABLE_PROFILING */ if(receiver_callback != NULL) { PRINTF("cc2420_process: calling receiver callback\n"); receiver_callback(&cc2420_driver); #if CC2420_TIMETABLE_PROFILING TIMETABLE_TIMESTAMP(cc2420_timetable, "end"); timetable_aggregate_compute_detailed(&aggregate_time, &cc2420_timetable); timetable_clear(&cc2420_timetable); #endif /* CC2420_TIMETABLE_PROFILING */ } else { PRINTF("cc2420_process not receiving function\n"); flushrx(); } } PROCESS_END(); }
/*---------------------------------------------------------------------------*/ int cc2420_init(void) { uint16_t reg; { int s = splhigh(); cc2420_arch_init(); /* Initalize ports and SPI. */ CC2420_DISABLE_FIFOP_INT(); CC2420_FIFOP_INT_INIT(); splx(s); } /* Turn on voltage regulator and reset. */ SET_VREG_ACTIVE(); BUSYWAIT_UNTIL(0, RTIMER_SECOND / 100); SET_RESET_ACTIVE(); BUSYWAIT_UNTIL(0, RTIMER_SECOND / 100); SET_RESET_INACTIVE(); BUSYWAIT_UNTIL(0, RTIMER_SECOND / 100); pan = 0xffff; addr = 0x0000; BUSYWAIT_UNTIL(0, RTIMER_SECOND / 100); powerup(); configure(); flushrx(); process_start(&cc2420_process, NULL); return 1; }
static void on(void) { ENERGEST_ON(ENERGEST_TYPE_LISTEN); PRINTF("on\n"); receive_on = 1; ENABLE_FIFOP_INT(); strobe(CC2420_SRXON); flushrx(); }
static void off(void) { /* PRINTF("off\n");*/ receive_on = 0; /* Wait for transmission to end before turning radio off. */ BUSYWAIT_UNTIL(!(status() & BV(CC2520_TX_ACTIVE)), RTIMER_SECOND / 10); ENERGEST_OFF(ENERGEST_TYPE_LISTEN); strobe(CC2520_INS_SRFOFF); CC2520_DISABLE_FIFOP_INT(); if(!CC2520_FIFOP_IS_1) { flushrx(); } }
static void configure(void) { uint16_t reg; BUSYWAIT_UNTIL(status() & (BV(CC2420_XOSC16M_STABLE)), RTIMER_SECOND / 100); /* Turn on/off automatic packet acknowledgment and address decoding. */ reg = getreg(CC2420_MDMCTRL0); #if CC2420_CONF_AUTOACK reg |= AUTOACK | ADR_DECODE; #else reg &= ~(AUTOACK | ADR_DECODE); #endif /* CC2420_CONF_AUTOACK */ setreg(CC2420_MDMCTRL0, reg); /* Set transmission turnaround time to the lower setting (8 symbols = 0.128 ms) instead of the default (12 symbols = 0.192 ms). */ /* reg = getreg(CC2420_TXCTRL); reg &= ~(1 << 13); setreg(CC2420_TXCTRL, reg);*/ /* Change default values as recomended in the data sheet, */ /* correlation threshold = 20, RX bandpass filter = 1.3uA. */ setreg(CC2420_MDMCTRL1, CORR_THR(20)); reg = getreg(CC2420_RXCTRL1); reg |= RXBPF_LOCUR; setreg(CC2420_RXCTRL1, reg); /* Set the FIFOP threshold to maximum. */ setreg(CC2420_IOCFG0, FIFOP_THR(127)); /* Turn off "Security enable" (page 32). */ reg = getreg(CC2420_SECCTRL0); reg &= ~RXFIFO_PROTECTION; setreg(CC2420_SECCTRL0, reg); cc2420_set_pan_addr(pan, addr, NULL); cc2420_set_channel(channel); flushrx(); }
/*---------------------------------------------------------------------------*/ static int cc2520_read(void *buf, unsigned short bufsize) { uint8_t footer[2]; uint8_t len; if(!CC2520_FIFOP_IS_1) { return 0; } GET_LOCK(); cc2520_packets_read++; getrxbyte(&len); if(len > CC2520_MAX_PACKET_LEN) { /* Oops, we must be out of sync. */ flushrx(); RIMESTATS_ADD(badsynch); RELEASE_LOCK(); return 0; } if(len <= FOOTER_LEN) { flushrx(); RIMESTATS_ADD(tooshort); RELEASE_LOCK(); return 0; } if(len - FOOTER_LEN > bufsize) { flushrx(); RIMESTATS_ADD(toolong); RELEASE_LOCK(); return 0; } getrxdata(buf, len - FOOTER_LEN); getrxdata(footer, FOOTER_LEN); if(footer[1] & FOOTER1_CRC_OK) { cc2520_last_rssi = footer[0]; cc2520_last_correlation = footer[1] & FOOTER1_CORRELATION; packetbuf_set_attr(PACKETBUF_ATTR_RSSI, cc2520_last_rssi); packetbuf_set_attr(PACKETBUF_ATTR_LINK_QUALITY, cc2520_last_correlation); RIMESTATS_ADD(llrx); } else { RIMESTATS_ADD(badcrc); len = FOOTER_LEN; } if(CC2520_FIFOP_IS_1) { if(!CC2520_FIFO_IS_1) { /* Clean up in case of FIFO overflow! This happens for every * full length frame and is signaled by FIFOP = 1 and FIFO = * 0. */ flushrx(); } else { /* Another packet has been received and needs attention. */ process_poll(&cc2520_process); } } RELEASE_LOCK(); if(len < FOOTER_LEN) { return 0; } return len - FOOTER_LEN; }
/*---------------------------------------------------------------------------*/ int cc2520_init(void) { { int s = splhigh(); cc2520_arch_init(); /* Initalize ports and SPI. */ CC2520_DISABLE_FIFOP_INT(); CC2520_FIFOP_INT_INIT(); splx(s); } SET_VREG_INACTIVE(); clock_delay(250); /* Turn on voltage regulator and reset. */ SET_VREG_ACTIVE(); clock_delay(250); SET_RESET_ACTIVE(); clock_delay(127); SET_RESET_INACTIVE(); clock_delay(125); /* Turn on the crystal oscillator. */ strobe(CC2520_INS_SXOSCON); clock_delay(125); BUSYWAIT_UNTIL(status() & (BV(CC2520_XOSC16M_STABLE)), RTIMER_SECOND / 100); /* Change default values as recommended in the data sheet, */ /* correlation threshold = 20, RX bandpass filter = 1.3uA.*/ setreg(CC2520_TXCTRL, 0x94); setreg(CC2520_TXPOWER, 0x13); // Output power 1 dBm /* valeurs de TXPOWER 0x03 -> -18 dBm 0x2C -> -7 dBm 0x88 -> -4 dBm 0x81 -> -2 dBm 0x32 -> 0 dBm 0x13 -> 1 dBm 0x32 -> 0 dBm 0x13 -> 1 dBm 0xAB -> 2 dBm 0xF2 -> 3 dBm 0xF7 -> 5 dBm */ setreg(CC2520_CCACTRL0, 0xF8); // CCA treshold -80dBm // Recommended RX settings setreg(CC2520_MDMCTRL0, 0x84); // Controls modem setreg(CC2520_MDMCTRL1, 0x14); // Controls modem setreg(CC2520_RXCTRL, 0x3F); // Adjust currents in RX related analog modules setreg(CC2520_FSCTRL, 0x5A); // Adjust currents in synthesizer. setreg(CC2520_FSCAL1, 0x2B); // Adjust currents in VCO setreg(CC2520_AGCCTRL1, 0x11); // Adjust target value for AGC control loop setreg(CC2520_AGCCTRL2, 0xEB); // Disable external clock setreg(CC2520_EXTCLOCK, 0x00); // Tune ADC performance setreg(CC2520_ADCTEST0, 0x10); setreg(CC2520_ADCTEST1, 0x0E); setreg(CC2520_ADCTEST2, 0x03); /* Set auto CRC on frame. */ #if CC2520_CONF_AUTOACK setreg(CC2520_FRMCTRL0, AUTOCRC | AUTOACK); setreg(CC2520_FRMFILT0, FRAME_MAX_VERSION|FRAME_FILTER_ENABLE); #else /* setreg(CC2520_FRMCTRL0, 0x60); */ setreg(CC2520_FRMCTRL0, AUTOCRC); /* Disable filter on @ (remove if you want to address specific wismote) */ setreg(CC2520_FRMFILT0, 0x00); #endif /* CC2520_CONF_AUTOACK */ /* SET_RXENMASK_ON_TX */ setreg(CC2520_FRMCTRL1, 1); /* Set FIFOP threshold to maximum .*/ setreg(CC2520_FIFOPCTRL, FIFOP_THR(0x7F)); cc2520_set_pan_addr(0xffff, 0x0000, NULL); cc2520_set_channel(26); flushrx(); process_start(&cc2520_process, NULL); return 1; }
/*---------------------------------------------------------------------------*/ static int cc2420_read(void *buf, unsigned short bufsize) { uint8_t footer[2]; uint8_t len; #if CC2420_CONF_CHECKSUM uint16_t checksum; #endif /* CC2420_CONF_CHECKSUM */ if(!CC2420_FIFOP_IS_1) { return 0; } /* if(!pending) { return 0; }*/ pending = 0; GET_LOCK(); cc2420_packets_read++; getrxbyte(&len); if(len > CC2420_MAX_PACKET_LEN) { /* Oops, we must be out of sync. */ flushrx(); RIMESTATS_ADD(badsynch); RELEASE_LOCK(); return 0; } if(len <= AUX_LEN) { flushrx(); RIMESTATS_ADD(tooshort); RELEASE_LOCK(); return 0; } if(len - AUX_LEN > bufsize) { flushrx(); RIMESTATS_ADD(toolong); RELEASE_LOCK(); return 0; } getrxdata(buf, len - AUX_LEN); #if CC2420_CONF_CHECKSUM getrxdata(&checksum, CHECKSUM_LEN); #endif /* CC2420_CONF_CHECKSUM */ getrxdata(footer, FOOTER_LEN); #if CC2420_CONF_CHECKSUM if(checksum != crc16_data(buf, len - AUX_LEN, 0)) { PRINTF("checksum failed 0x%04x != 0x%04x\n", checksum, crc16_data(buf, len - AUX_LEN, 0)); } if(footer[1] & FOOTER1_CRC_OK && checksum == crc16_data(buf, len - AUX_LEN, 0)) { #else if(footer[1] & FOOTER1_CRC_OK) { #endif /* CC2420_CONF_CHECKSUM */ cc2420_last_rssi = footer[0]; cc2420_last_correlation = footer[1] & FOOTER1_CORRELATION; packetbuf_set_attr(PACKETBUF_ATTR_RSSI, cc2420_last_rssi); packetbuf_set_attr(PACKETBUF_ATTR_LINK_QUALITY, cc2420_last_correlation); RIMESTATS_ADD(llrx); } else { RIMESTATS_ADD(badcrc); len = AUX_LEN; } if(CC2420_FIFOP_IS_1) { if(!CC2420_FIFO_IS_1) { /* Clean up in case of FIFO overflow! This happens for every * full length frame and is signaled by FIFOP = 1 and FIFO = * 0. */ flushrx(); } else { /* Another packet has been received and needs attention. */ process_poll(&cc2420_process); } } RELEASE_LOCK(); if(len < AUX_LEN) { return 0; } return len - AUX_LEN; } /*---------------------------------------------------------------------------*/ void cc2420_set_txpower(uint8_t power) { GET_LOCK(); set_txpower(power); RELEASE_LOCK(); }
/*---------------------------------------------------------------------------*/ int cc2420_init(void) { uint16_t reg; { int s = splhigh(); cc2420_arch_init(); /* Initalize ports and SPI. */ CC2420_DISABLE_FIFOP_INT(); CC2420_FIFOP_INT_INIT(); splx(s); } /* Turn on voltage regulator and reset. */ SET_VREG_ACTIVE(); //clock_delay(250); OK SET_RESET_ACTIVE(); clock_delay(127); SET_RESET_INACTIVE(); //clock_delay(125); OK /* Turn on the crystal oscillator. */ strobe(CC2420_SXOSCON); /* Turn on/off automatic packet acknowledgment and address decoding. */ reg = getreg(CC2420_MDMCTRL0); #if CC2420_CONF_AUTOACK reg |= AUTOACK | ADR_DECODE; #else reg &= ~(AUTOACK | ADR_DECODE); #endif /* CC2420_CONF_AUTOACK */ setreg(CC2420_MDMCTRL0, reg); /* Set transmission turnaround time to the lower setting (8 symbols = 0.128 ms) instead of the default (12 symbols = 0.192 ms). */ /* reg = getreg(CC2420_TXCTRL); reg &= ~(1 << 13); setreg(CC2420_TXCTRL, reg);*/ /* Change default values as recomended in the data sheet, */ /* correlation threshold = 20, RX bandpass filter = 1.3uA. */ setreg(CC2420_MDMCTRL1, CORR_THR(20)); reg = getreg(CC2420_RXCTRL1); reg |= RXBPF_LOCUR; setreg(CC2420_RXCTRL1, reg); /* Set the FIFOP threshold to maximum. */ setreg(CC2420_IOCFG0, FIFOP_THR(127)); /* Turn off "Security enable" (page 32). */ reg = getreg(CC2420_SECCTRL0); reg &= ~RXFIFO_PROTECTION; setreg(CC2420_SECCTRL0, reg); cc2420_set_pan_addr(0xffff, 0x0000, NULL); cc2420_set_channel(26); flushrx(); process_start(&cc2420_process, NULL); return 1; }
/*---------------------------------------------------------------------------*/ int cc2420_read(void *buf, unsigned short bufsize) { uint8_t footer[2]; uint8_t len; uint16_t checksum; struct timestamp t; if(!FIFOP_IS_1) { /* If FIFOP is 0, there is no packet in the RXFIFO. */ return 0; } if(interrupt_time_set) { #if CC2420_CONF_TIMESTAMPS cc2420_time_of_arrival = interrupt_time; #endif /* CC2420_CONF_TIMESTAMPS */ interrupt_time_set = 0; } else { cc2420_time_of_arrival = 0; } cc2420_time_of_departure = 0; GET_LOCK(); getrxbyte(&len); if(len > CC2420_MAX_PACKET_LEN) { /* Oops, we must be out of sync. */ flushrx(); RIMESTATS_ADD(badsynch); RELEASE_LOCK(); return 0; } if(len <= AUX_LEN) { flushrx(); RIMESTATS_ADD(tooshort); RELEASE_LOCK(); return 0; } if(len - AUX_LEN > bufsize) { flushrx(); RIMESTATS_ADD(toolong); RELEASE_LOCK(); return 0; } getrxdata(buf, len - AUX_LEN); getrxdata(&checksum, CHECKSUM_LEN); getrxdata(&t, TIMESTAMP_LEN); getrxdata(footer, FOOTER_LEN); if(footer[1] & FOOTER1_CRC_OK && checksum == crc16_data(buf, len - AUX_LEN, 0)) { cc2420_last_rssi = footer[0]; cc2420_last_correlation = footer[1] & FOOTER1_CORRELATION; RIMESTATS_ADD(llrx); #if CC2420_CONF_TIMESTAMPS cc2420_time_of_departure = t.time + setup_time_for_transmission + (total_time_for_transmission * (len - 2)) / total_transmission_len; cc2420_authority_level_of_sender = t.authority_level; #endif /* CC2420_CONF_TIMESTAMPS */ } else { RIMESTATS_ADD(badcrc); len = AUX_LEN; } /* Clean up in case of FIFO overflow! This happens for every full * length frame and is signaled by FIFOP = 1 and FIFO = 0. */ if(FIFOP_IS_1 && !FIFO_IS_1) { /* printf("cc2420_read: FIFOP_IS_1 1\n");*/ flushrx(); } else if(FIFOP_IS_1) { /* Another packet has been received and needs attention. */ process_poll(&cc2420_process); } RELEASE_LOCK(); if(len < AUX_LEN) { return 0; } return len - AUX_LEN; }
int main(void) { nvmType_t type=0; nvmErr_t err; volatile uint8_t c; volatile uint32_t i; volatile uint32_t buf[4]; volatile uint32_t len=0; volatile uint32_t state = SCAN_X; volatile uint32_t addr,data; uart_init(UART1, 115200); disable_irq(UART1); vreg_init(); dbg_putstr("Detecting internal nvm\n\r"); err = nvm_detect(gNvmInternalInterface_c, &type); dbg_putstr("nvm_detect returned: 0x"); dbg_put_hex(err); dbg_putstr(" type is: 0x"); dbg_put_hex32(type); dbg_putstr("\n\r"); err = nvm_read(gNvmInternalInterface_c, type, (uint8_t *)nvm_base, NVM_BASE, 0x100); dbg_putstr("nvm_read returned: 0x"); dbg_put_hex(err); dbg_putstr("\n\r"); /* erase the flash */ nvm_setsvar(0); err = nvm_erase(gNvmInternalInterface_c, type, 0x40000000); dbg_putstr("nvm_erase returned: 0x"); dbg_put_hex(err); dbg_putstr("\n\r"); dbg_putstr(" type is: 0x"); dbg_put_hex32(type); dbg_putstr("\n\r"); err = nvm_write(gNvmInternalInterface_c, type, (uint8_t *)nvm_base, NVM_BASE, 0x100); dbg_putstr("nvm_write returned: 0x"); dbg_put_hex(err); dbg_putstr("\n\r"); /* say we are ready */ len = 0; putstr("ready"); flushrx(); /* read the length */ for(i=0; i<4; i++) { c = uart1_getc(); /* bail if the first byte of the length is zero */ len += (c<<(i*8)); } dbg_putstr("len: "); dbg_put_hex32(len); dbg_putstr("\n\r"); dbg_putstr(" type is: 0x"); dbg_put_hex32(type); dbg_putstr("\n\r"); putstr("flasher done\n\r"); state = SCAN_X; addr=0; while((c=getc())) { if(state == SCAN_X) { /* read until we see an 'x' */ if(c==0) { break; } if(c!='x'){ continue; } /* go to read_chars once we have an 'x' */ state = READ_CHARS; i = 0; } if(state == READ_CHARS) { /* read all the chars up to a ',' */ ((uint8_t *)buf)[i++] = c; /* after reading a ',' */ /* goto PROCESS state */ if((c == ',') || (c == 0)) { state = PROCESS; } } if(state == PROCESS) { if(addr==0) { /*interpret the string as the starting address */ addr = to_u32(buf); } else { /* string is data to write */ data = to_u32(buf); putstr("writing addr "); put_hex32(NVM_BASE+addr); putstr(" data "); put_hex32(data); err = nvm_write(gNvmInternalInterface_c, type, (uint8_t *)&data, NVM_BASE+addr, 4); addr += 4; putstr(" err "); put_hex32(err); putstr("\n\r"); } /* look for the next 'x' */ state=SCAN_X; } } putstr("process flasher done\n\r"); while(1) {continue;}; }
void main(void) { nvmType_t type=0; nvmErr_t err; volatile uint8_t c; volatile uint32_t i; volatile uint32_t buf[4]; volatile uint32_t len=0; volatile uint32_t state = SCAN_X; volatile uint32_t addr,data; uart_init(INC, MOD, SAMP); disable_irq(UART1); vreg_init(); dbg_putstr("Detecting internal nvm\n\r"); err = nvm_detect(gNvmInternalInterface_c, &type); dbg_putstr("nvm_detect returned: 0x"); dbg_put_hex(err); dbg_putstr(" type is: 0x"); dbg_put_hex32(type); dbg_putstr("\n\r"); /* erase the flash */ err = nvm_erase(gNvmInternalInterface_c, type, 0x7fffffff); dbg_putstr("nvm_erase returned: 0x"); dbg_put_hex(err); dbg_putstr("\n\r"); dbg_putstr(" type is: 0x"); dbg_put_hex32(type); dbg_putstr("\n\r"); /* say we are ready */ len = 0; putstr("ready"); flushrx(); /* read the length */ for(i=0; i<4; i++) { c = uart1_getc(); /* bail if the first byte of the length is zero */ len += (c<<(i*8)); } dbg_putstr("len: "); dbg_put_hex32(len); dbg_putstr("\n\r"); /* write the OKOK magic */ #if BOOT_OK ((uint8_t *)buf)[0] = 'O'; ((uint8_t *)buf)[1] = 'K'; ((uint8_t *)buf)[2] = 'O'; ((uint8_t *)buf)[3] = 'K'; #elif BOOT_SECURE ((uint8_t *)buf)[0] = 'S'; ((uint8_t *)buf)[1] = 'E'; ((uint8_t *)buf)[2] = 'C'; ((uint8_t *)buf)[3] = 'U'; #else ((uint8_t *)buf)[0] = 'N'; ((uint8_t *)buf)[1] = 'O'; ((uint8_t *)buf)[2] = 'N'; ((uint8_t *)buf)[3] = 'O'; #endif dbg_putstr(" type is: 0x"); dbg_put_hex32(type); dbg_putstr("\n\r"); /* don't make a valid boot image if the received length is zero */ if(len == 0) { ((uint8_t *)buf)[0] = 'N'; ((uint8_t *)buf)[1] = 'O'; ((uint8_t *)buf)[2] = 'N'; ((uint8_t *)buf)[3] = 'O'; } err = nvm_write(gNvmInternalInterface_c, type, (uint8_t *)buf, 0, 4); dbg_putstr("nvm_write returned: 0x"); dbg_put_hex(err); dbg_putstr("\n\r"); /* write the length */ err = nvm_write(gNvmInternalInterface_c, type, (uint8_t *)&len, 4, 4); /* read a byte, write a byte */ for(i=0; i<len; i++) { c = getc(); err = nvm_write(gNvmInternalInterface_c, type, (uint8_t *)&c, 8+i, 1); } putstr("flasher done\n\r"); state = SCAN_X; addr=0; while((c=getc())) { if(state == SCAN_X) { /* read until we see an 'x' */ if(c==0) { break; } if(c!='x'){ continue; } /* go to read_chars once we have an 'x' */ state = READ_CHARS; i = 0; } if(state == READ_CHARS) { /* read all the chars up to a ',' */ ((uint8_t *)buf)[i++] = c; /* after reading a ',' */ /* goto PROCESS state */ if((c == ',') || (c == 0)) { state = PROCESS; } } if(state == PROCESS) { if(addr==0) { /*interpret the string as the starting address */ addr = to_u32(buf); } else { /* string is data to write */ data = to_u32(buf); putstr("writing addr "); put_hex32(addr); putstr(" data "); put_hex32(data); putstr("\n\r"); err = nvm_write(gNvmInternalInterface_c, 1, (uint8_t *)&data, addr, 4); addr += 4; } /* look for the next 'x' */ state=SCAN_X; } } while(1) {continue;}; }
/** * The CC1101 interrupt handler: called by the hardware interrupt * handler, which is defined as part of the cc1101-arch interface. */ int cc1101_rx_interrupt(void) { /* NB: This function may be called both from an rx interrupt and from cc1101_process */ uint8_t rxbytes, s; if(radio_on_or_off == OFF) { return 0; } #if DEBUG printf("-"); #endif /* DEBUG */ if(SPI_IS_LOCKED()) { #if DEBUG printf("/%d", spi_locked); #endif /* DEBUG */ process_poll(&cc1101_process); return 1; } LOCK_SPI(); s = state(); if(s == CC1101_STATE_RXFIFO_OVERFLOW) { burst_read(CC1101_RXBYTES, &rxbytes, 1); #if DEBUG printf("irqflush\n"); printf("rxbytes 0x%02x\n", rxbytes); #endif /* DEBUG */ flushrx(); RELEASE_SPI(); return 0; } if(s == CC1101_STATE_TXFIFO_UNDERFLOW) { #if DEBUG printf("irqflushtx\n"); #endif /* DEBUG */ strobe(CC1101_SFTX); strobe(CC1101_SRX); RELEASE_SPI(); return 0; } if(is_receiving() && timer_expired(&rxstate.timer)) { #if DEBUG printf("Packet expired, flushing fifo\n"); #endif /* DEBUG */ flushrx(); RELEASE_SPI(); return 0; } #define RX_OVERFLOW 0x80 /* Read each byte from the RXFIFO and put it into the input_byte() function, which takes care of the reception logic. */ do { uint8_t byte; int i, numbytes; rxbytes = read_rxbytes(); if(rxbytes & RX_OVERFLOW) { #if DEBUG printf("ovf\n"); leds_off(LEDS_GREEN;) #endif /* DEBUG */ flushrx(); process_poll(&cc1101_process); RELEASE_SPI(); return 1; }
/*---------------------------------------------------------------------------*/ static int input_byte(uint8_t byte) { int crc; if(timer_expired(&rxstate.timer)) { restart_input(); } PT_BEGIN(&rxstate.pt); /* The first incoming byte is the length of the packet. */ rxstate.receiving = 1; rxstate.len = byte; if(byte == 0) { #if DEBUG printf("Bad len 0, state %d rxbytes %d\n", state(), read_rxbytes()); #endif /* DEBUG */ flushrx(); PT_EXIT(&rxstate.pt); } timer_set(&rxstate.timer, PACKET_LIFETIME); for(rxstate.ptr = 0; rxstate.ptr < rxstate.len; rxstate.ptr++) { /* Wait for the next data byte to be received. */ PT_YIELD(&rxstate.pt); rxstate.buf[rxstate.ptr] = byte; } /* Receive two more bytes from the FIFO: the RSSI value and the LQI/CRC */ PT_YIELD(&rxstate.pt); rxstate.buf[rxstate.ptr] = byte; rxstate.ptr++; PT_YIELD(&rxstate.pt); rxstate.buf[rxstate.ptr] = byte; crc = (byte & 0x80); rxstate.ptr++; if(crc == 0) { #if DEBUG printf("bad crc\n"); #endif /* DEBUG */ flushrx(); } else if(packet_rx_len > 0) { #if DEBUG printf("Packet in the buffer (%d), dropping %d bytes\n", packet_rx_len, rxstate.len); #endif /* DEBUG */ flushrx(); process_poll(&cc1101_process); } else if(rxstate.len < ACK_LEN) { /* Drop packets that are way too small: less than ACK_LEN (3) bytes long. */ #if DEBUG printf("!"); #endif /* DEBUG */ } else { /* Read out the first three bytes to determine if we should send an ACK or not. */ /* Send a link-layer ACK before reading the full packet. */ if(rxstate.len >= ACK_LEN) { /* Try to parse the incoming frame as a 802.15.4 header. */ frame802154_t info154; if(frame802154_parse(rxstate.buf, rxstate.len, &info154) != 0) { /* XXX Potential optimization here: we could check if the frame is destined for us, or for the broadcast address and discard the packet if it isn't for us. */ if(1) { /* For dataframes that has the ACK request bit set and that is destined for us, we send an ack. */ if(info154.fcf.frame_type == FRAME802154_DATAFRAME && info154.fcf.ack_required != 0 && rimeaddr_cmp((rimeaddr_t *)&info154.dest_addr, &rimeaddr_node_addr)) { send_ack(info154.seq); /* Make sure that we don't put the radio in the IDLE state before the ACK has been fully transmitted. */ BUSYWAIT_UNTIL((state() != CC1101_STATE_TX), RTIMER_SECOND / 10); ENERGEST_OFF(ENERGEST_TYPE_TRANSMIT); ENERGEST_ON(ENERGEST_TYPE_LISTEN); if(state() == CC1101_STATE_TX) { #if DEBUG printf("didn't end ack tx (in %d, txbytes %d)\n", state(), txbytes()); #endif /* DEBUG */ check_txfifo(); flushrx(); } } memcpy((void *)packet_rx, rxstate.buf, rxstate.len + AUX_LEN); packet_rx_len = rxstate.len + AUX_LEN; /* including AUX */ process_poll(&cc1101_process); #if DEBUG printf("#"); #endif /* DEBUG */ } } } } rxstate.receiving = 0; PT_END(&rxstate.pt); }