void cc2420_on(void) { if (receive_on) return; receive_on = 1; cc2420_strobe(CC2420_SRXON); cc2420_strobe(CC2420_SFLUSHRX); ENABLE_FIFOP_INT(); }
int cc2420_rx(cc2420_t *dev, uint8_t *buf, size_t max_len, void *info) { (void)info; uint8_t len; uint8_t crc_corr; /* without a provided buffer, only readout the length and return it */ if (buf == NULL) { /* get the packet length (without dropping it) (first byte in RX FIFO) */ cc2420_ram_read(dev, CC2420_RAM_RXFIFO, &len, 1); len -= 2; /* subtract RSSI and FCF */ DEBUG("cc2420: recv: packet of length %i in RX FIFO\n", (int)len); } else { /* read length byte */ cc2420_fifo_read(dev, &len, 1); len -= 2; /* subtract RSSI and FCF */ /* if a buffer is given, read (and drop) the packet */ len = (len > max_len) ? max_len : len; /* read fifo contents */ DEBUG("cc2420: recv: reading %i byte of the packet\n", (int)len); cc2420_fifo_read(dev, buf, len); int8_t rssi; cc2420_fifo_read(dev, (uint8_t*)&rssi, 1); DEBUG("cc2420: recv: RSSI is %i\n", (int)rssi); /* fetch and check if CRC_OK bit (MSB) is set */ cc2420_fifo_read(dev, &crc_corr, 1); if (!(crc_corr & 0x80)) { DEBUG("cc2420: recv: CRC_OK bit not set, dropping packet\n"); /* drop the corrupted frame from the RXFIFO */ len = 0; } if (info != NULL) { netdev_ieee802154_rx_info_t *radio_info = info; radio_info->rssi = CC2420_RSSI_OFFSET + rssi; radio_info->lqi = crc_corr & CC2420_CRCCOR_COR_MASK; } /* finally flush the FIFO */ cc2420_strobe(dev, CC2420_STROBE_FLUSHRX); cc2420_strobe(dev, CC2420_STROBE_FLUSHRX); } return (int)len; }
size_t cc2420_tx_prepare(cc2420_t *dev, const iolist_t *iolist) { size_t pkt_len = 2; /* include the FCS (frame check sequence) */ /* wait for any ongoing transmissions to be finished */ DEBUG("cc2420: tx_exec: waiting for any ongoing transmission\n"); while (cc2420_get_state(dev) & NETOPT_STATE_TX) {} /* get and check the length of the packet */ for (const iolist_t *iol = iolist; iol; iol = iol->iol_next) { pkt_len += iol->iol_len; } if (pkt_len >= CC2420_PKT_MAXLEN) { DEBUG("cc2420: tx_prep: unable to send, pkt too large\n"); return 0; } /* flush TX FIFO and write new packet to it */ cc2420_strobe(dev, CC2420_STROBE_FLUSHTX); /* push packet length to TX FIFO */ cc2420_fifo_write(dev, (uint8_t *)&pkt_len, 1); /* push packet to TX FIFO */ for (const iolist_t *iol = iolist; iol; iol = iol->iol_next) { cc2420_fifo_write(dev, iol->iol_base, iol->iol_len); } DEBUG("cc2420: tx_prep: loaded %i byte into the TX FIFO\n", (int)pkt_len); return pkt_len; }
/* * Request packet to be sent using CSMA-CA. Requires that RSSI is * valid. * * Return UIP_FW_DROPPED on failure. */ int cc2420_resend(void) { unsigned i; if (FIFOP_IS_1 && !FIFO_IS_1) { process_poll(&cc2420_process); PRINTF("rxfifo overflow!\n"); } /* The TX FIFO can only hold one packet! Make sure to not overrun * FIFO by waiting for transmission to start here and synchronizing * with the CC2420_TX_ACTIVE check in cc2420_send. * * Note that we may have to wait up to 320 us (20 symbols) before * transmission starts. */ #ifdef TMOTE_SKY #define LOOP_20_SYMBOLS 100 /* 326us (msp430 @ 2.4576MHz) */ #elif __AVR__ #define LOOP_20_SYMBOLS 500 /* XXX */ #endif if (CCA_IS_1) { cc2420_strobe(CC2420_STXONCCA); for (i = LOOP_20_SYMBOLS; i > 0; i--) if (SFD_IS_1) { if (cc2420_status() & BV(CC2420_TX_ACTIVE)) return UIP_FW_OK; /* Transmission has started. */ else break; /* We must be receiving. */ } } return UIP_FW_DROPPED; /* Transmission never started! */ }
void cc2420_tx_exec(cc2420_t *dev) { /* trigger the transmission */ if (dev->options & CC2420_OPT_TELL_TX_START) { dev->netdev.netdev.event_callback(&dev->netdev.netdev, NETDEV_EVENT_TX_STARTED); } DEBUG("cc2420: tx_exec: TX_START\n"); if (dev->options & CC2420_OPT_CSMA) { DEBUG("cc2420: tx_exec: triggering TX with CCA\n"); cc2420_strobe(dev, CC2420_STROBE_TXONCCA); } else { DEBUG("cc2420: tx_exec: triggering TX without CCA\n"); cc2420_strobe(dev, CC2420_STROBE_TXON); } }
void cc2420_init(int tpid) { uint16_t reg; transceiver_pid = tpid; cc2420_spi_init(); hwtimer_wait(CC2420_WAIT_TIME); cc2420_reset(); cc2420_strobe(CC2420_STROBE_XOSCON); //enable crystal while((cc2420_strobe(NOBYTE) & 0x40) == 0); //wait for crystal to be stable hwtimer_wait(CC2420_WAIT_TIME); reg = cc2420_read_reg(CC2420_REG_MDMCTRL0); reg |= CC2420_ADR_DECODE; //enable adr decode reg |= CC2420_AUTOACK; //enable auto ack reg |= CC2420_AUTOCRC; //enable auto crc reg &= ~(CC2420_RES_FRM_MODE); //disable reserved frames cc2420_write_reg(CC2420_REG_MDMCTRL0, reg); /* Change default values as recomended in the data sheet, */ /* RX bandpass filter = 1.3uA. */ reg = cc2420_read_reg(CC2420_REG_RXCTRL1); reg |= CC2420_RXBPF_LOCUR; cc2420_write_reg(CC2420_REG_RXCTRL1, reg); /* Set the FIFOP threshold to maximum. */ cc2420_write_reg(CC2420_REG_IOCFG0, 127); /* Turn off "Security enable" (page 32). */ reg = cc2420_read_reg(CC2420_REG_SECCTRL0); reg &= ~CC2420_RXFIFO_PROTECTION; cc2420_write_reg(CC2420_REG_SECCTRL0, reg); /* set output power to 0dbm */ cc2420_write_reg(CC2420_REG_TXCTRL, 0xA0FF); cc2420_set_channel(CC2420_DEFAULT_CHANNR); cc2420_set_pan(0x1111); DEBUG("CC2420 initialized and set to channel %i and pan %i\n", radio_channel, radio_pan); cc2420_init_interrupts(); cc2420_switch_to_rx(); }
void cc2420_off(void) { u8_t spiStatusByte; if (receive_on == 0) return; receive_on = 0; /* Wait for transmission to end before turning radio off. */ do { spiStatusByte = cc2420_status(); } while (spiStatusByte & BV(CC2420_TX_ACTIVE)); cc2420_strobe(CC2420_SRFOFF); DISABLE_FIFOP_INT(); }
void cc2420_init(void) { u16_t reg; { int s = splhigh(); __cc2420_arch_init(); /* Initalize ports and SPI. */ DISABLE_FIFOP_INT(); 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. */ cc2420_strobe(CC2420_SXOSCON); /* Turn on automatic packet acknowledgment. */ reg = cc2420_getreg(CC2420_MDMCTRL0); reg |= AUTOACK; cc2420_setreg(CC2420_MDMCTRL0, reg); /* Change default values as recomended in the data sheet, */ /* correlation threshold = 20, RX bandpass filter = 1.3uA. */ cc2420_setreg(CC2420_MDMCTRL1, CORR_THR(20)); reg = cc2420_getreg(CC2420_RXCTRL1); reg |= RXBPF_LOCUR; cc2420_setreg(CC2420_RXCTRL1, reg); /* Set the FIFOP threshold to maximum. */ cc2420_setreg(CC2420_IOCFG0, FIFOP_THR(127)); /* Turn off "Security enable" (page 32). */ reg = cc2420_getreg(CC2420_SECCTRL0); reg &= ~RXFIFO_PROTECTION; cc2420_setreg(CC2420_SECCTRL0, reg); cc2420_set_chan_pan_addr(11, 0xffff, 0x0000, NULL); }
int cc2420_send(struct hdr_802_15 *hdr, u8_t hdr_len, const u8_t *payload, u8_t payload_len) { u8_t spiStatusByte; int s; /* struct hdr_802_15::len shall *not* be counted, thus the -1. * 2 == sizeof(footer). */ if (((hdr_len - 1) + payload_len + 2) > MAX_PACKET_LEN) return -1; /* This code uses the CC2420 CCA (Clear Channel Assessment) to * implement Carrier Sense Multiple Access with Collision Avoidance * (CSMA-CA) and requires the receiver to be enabled and ready. */ if (!receive_on) return -2; /* Wait for previous transmission to finish and RSSI. */ do { spiStatusByte = cc2420_status(); if (!(spiStatusByte & BV(CC2420_RSSI_VALID))) /* RSSI needed by CCA */ continue; } while (spiStatusByte & BV(CC2420_TX_ACTIVE)); hdr->dst_pan = pan_id; /* Not at fixed position! xxx/bg */ last_dst = hdr->dst; /* Not dst either. */ last_used_seq++; hdr->seq = last_used_seq; cc2420_ack_received = 0; /* Write packet to TX FIFO, appending FCS if AUTOCRC is enabled. */ cc2420_strobe(CC2420_SFLUSHTX); /* Cancel send that never started. */ s = splhigh(); FASTSPI_WRITE_FIFO(hdr, hdr_len); FASTSPI_WRITE_FIFO(payload, payload_len); splx(s); /* Send stuff from FIFO now! */ process_post_synch(&cc2420_retransmit_process, PROCESS_EVENT_MSG, NULL); return UIP_FW_OK; }
void cc2420_rxoverflow_irq(void) { cc2420_strobe(CC2420_STROBE_FLUSHRX); //Datasheets says do this twice... cc2420_strobe(CC2420_STROBE_FLUSHRX); }
void cc2420_switch_to_rx(void) { cc2420_strobe(CC2420_STROBE_RFOFF); cc2420_strobe(CC2420_STROBE_FLUSHRX); cc2420_strobe(CC2420_STROBE_FLUSHRX); cc2420_strobe(CC2420_STROBE_RXON); }
PROCESS_THREAD(cc2420_process, ev, data) { PROCESS_BEGIN(); process_start(&cc2420_retransmit_process, NULL); while (1) { unsigned len; int s; PROCESS_YIELD(); len = rx_fifo_remaining_bytes; if (len > 0) { /* Read payload and two bytes of footer */ if ((len - 2) > (UIP_BUFSIZE - UIP_LLH_LEN) || len < 2) { PRINTF("cc2420_process too big len=%d\n", len); s = splhigh(); FASTSPI_READ_FIFO_GARBAGE(len); rx_fifo_remaining_bytes = 0; /* RX FIFO emptied! */ splx(s); len = 0; } else { u8_t footer[2]; uip_len = 0; s = splhigh(); if (len > 2) FASTSPI_READ_FIFO_NO_WAIT(&uip_buf[UIP_LLH_LEN], len - 2); FASTSPI_READ_FIFO_NO_WAIT(footer, 2); rx_fifo_remaining_bytes = 0; /* RX FIFO emptied! */ splx(s); if (footer[1] & FOOTER1_CRC_OK) { cc2420_last_rssi = footer[0]; cc2420_last_correlation = footer[1] & FOOTER1_CORRELATION; if ((h.fc0 & FC0_TYPE_MASK) == FC0_TYPE_DATA) uip_len = len - 2; } } } if (len == 2) PRINTF("recv data_ack\n"); /* 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) { cc2420_strobe(CC2420_SFLUSHRX); cc2420_strobe(CC2420_SFLUSHRX); } if (FIFOP_IS_1) { s = splhigh(); __cc2420_intr(); /* Fake interrupt! */ splx(s); } if (len == 2) { /* A DATA ACK packet. */ if (last_dst == h.src) cc2420_ack_received = 1; neigbour_update(h.src, 0); } else if (len > 2 && uip_len > 0 && uip_len == (((u16_t)(BUF->len[0]) << 8) + BUF->len[1])) { /* * If we are the unique receiver send DATA ACK. */ if (h.dst == 0xffff && uip_ipaddr_cmp(&BUF->destipaddr, &uip_hostaddr)) cc2420_send_data_ack(h.src); leds_toggle(LEDS_GREEN); cc2420_is_input = 1; tcpip_input(); cc2420_is_input = 0; leds_toggle(LEDS_GREEN); } } PROCESS_END(); }