int nrf24l01p_set_address_width(const nrf24l01p_t *dev, nrf24l01p_aw_t aw) { char aw_setup; nrf24l01p_read_reg(dev, REG_SETUP_AW, &aw_setup); xtimer_spin(DELAY_AFTER_FUNC_TICKS); switch (aw) { case NRF24L01P_AW_3BYTE: aw_setup &= ~(3); aw_setup |= 1; break; case NRF24L01P_AW_4BYTE: aw_setup &= ~(3); aw_setup |= 2; break; case NRF24L01P_AW_5BYTE: aw_setup &= ~(3); aw_setup |= 3; break; default: return -1; } return nrf24l01p_write_reg(dev, REG_SETUP_AW, aw_setup); }
void nrf24l01p_transmit(const nrf24l01p_t *dev) { gpio_set(dev->ce); xtimer_usleep(DELAY_CE_HIGH_US); /* at least 10 us high */ gpio_clear(dev->ce); xtimer_spin(DELAY_CHANGE_TXRX_TICKS); }
int nrf24l01p_read_payload(nrf24l01p_t *dev, char *answer, unsigned int size) { int status; /* Acquire exclusive access to the bus. */ spi_acquire(dev->spi); gpio_clear(dev->cs); xtimer_spin(DELAY_CS_TOGGLE_TICKS); status = spi_transfer_regs(dev->spi, CMD_R_RX_PAYLOAD, 0, answer, size); xtimer_spin(DELAY_CS_TOGGLE_TICKS); gpio_set(dev->cs); xtimer_spin(DELAY_AFTER_FUNC_TICKS); /* Release the bus for other threads. */ spi_release(dev->spi); return status; }
int nrf24l01p_set_tx_address(nrf24l01p_t *dev, char *saddr, unsigned int length) { int status; /* Acquire exclusive access to the bus. */ spi_acquire(dev->spi); gpio_clear(dev->cs); xtimer_spin(DELAY_CS_TOGGLE_TICKS); status = spi_transfer_regs(dev->spi, (CMD_W_REGISTER | (REGISTER_MASK & REG_TX_ADDR)), saddr, NULL, length); /* address width is 5 byte */ xtimer_spin(DELAY_CS_TOGGLE_TICKS); gpio_set(dev->cs); /* Release the bus for other threads. */ spi_release(dev->spi); xtimer_spin(DELAY_AFTER_FUNC_TICKS); return status; }
int nrf24l01p_read_reg(nrf24l01p_t *dev, char reg, char *answer) { int status; /* Acquire exclusive access to the bus. */ spi_acquire(dev->spi); gpio_clear(dev->cs); xtimer_spin(DELAY_CS_TOGGLE_TICKS); status = spi_transfer_reg(dev->spi, (CMD_R_REGISTER | (REGISTER_MASK & reg)), CMD_NOP, answer); xtimer_spin(DELAY_CS_TOGGLE_TICKS); gpio_set(dev->cs); /* Release the bus for other threads. */ spi_release(dev->spi); xtimer_spin(DELAY_AFTER_FUNC_TICKS); return status; }
int nrf24l01p_read_payload(const nrf24l01p_t *dev, char *answer, unsigned int size) { /* Acquire exclusive access to the bus. */ spi_acquire(dev->spi, dev->cs, SPI_MODE, SPI_CLK); spi_transfer_regs(dev->spi, dev->cs, CMD_R_RX_PAYLOAD, NULL, answer, size); xtimer_spin(DELAY_AFTER_FUNC_TICKS); /* Release the bus for other threads. */ spi_release(dev->spi); return 0; }
int nrf24l01p_preload(nrf24l01p_t *dev, char *data, unsigned int size) { int status; size = (size <= 32) ? size : 32; /* Acquire exclusive access to the bus. */ spi_acquire(dev->spi); gpio_clear(dev->cs); xtimer_spin(DELAY_CS_TOGGLE_TICKS); status = spi_transfer_regs(dev->spi, CMD_W_TX_PAYLOAD, data, NULL, size); xtimer_spin(DELAY_CS_TOGGLE_TICKS); gpio_set(dev->cs); /* Release the bus for other threads. */ spi_release(dev->spi); xtimer_spin(DELAY_AFTER_FUNC_TICKS); return status; }
int nrf24l01p_write_reg(const nrf24l01p_t *dev, char reg, char write) { /* Acquire exclusive access to the bus. */ spi_acquire(dev->spi, dev->cs, SPI_MODE, SPI_CLK); spi_transfer_reg(dev->spi, dev->cs, (CMD_W_REGISTER | (REGISTER_MASK & reg)), (uint8_t)write); /* Release the bus for other threads. */ spi_release(dev->spi); xtimer_spin(DELAY_AFTER_FUNC_TICKS); return 0; }
int nrf24l01p_read_reg(const nrf24l01p_t *dev, char reg, char *answer) { /* Acquire exclusive access to the bus. */ spi_acquire(dev->spi, dev->cs, SPI_MODE, SPI_CLK); *answer = (char)spi_transfer_reg(dev->spi, dev->cs, (CMD_R_REGISTER | (REGISTER_MASK & reg)), CMD_NOP); /* Release the bus for other threads. */ spi_release(dev->spi); xtimer_spin(DELAY_AFTER_FUNC_TICKS); return 0; }
int nrf24l01p_preload(const nrf24l01p_t *dev, char *data, unsigned int size) { size = (size <= 32) ? size : 32; /* Acquire exclusive access to the bus. */ spi_acquire(dev->spi, dev->cs, SPI_MODE, SPI_CLK); spi_transfer_regs(dev->spi, dev->cs, CMD_W_TX_PAYLOAD, data, NULL, size); /* Release the bus for other threads. */ spi_release(dev->spi); xtimer_spin(DELAY_AFTER_FUNC_TICKS); return 0; }
int nrf24l01p_set_tx_address(const nrf24l01p_t *dev, const char *saddr, unsigned int length) { /* Acquire exclusive access to the bus. */ spi_acquire(dev->spi, dev->cs, SPI_MODE, SPI_CLK); spi_transfer_regs(dev->spi, dev->cs, (CMD_W_REGISTER | (REGISTER_MASK & REG_TX_ADDR)), saddr, NULL, length); /* Release the bus for other threads. */ spi_release(dev->spi); xtimer_spin(DELAY_AFTER_FUNC_TICKS); return (int)length; }
static int nvram_spi_write(nvram_t *dev, uint8_t *src, uint32_t dst, size_t len) { nvram_spi_params_t *spi_dev = (nvram_spi_params_t *) dev->extra; int status; union { uint32_t u32; char c[4]; } addr; /* Address is expected by the device as big-endian, i.e. network byte order, * we utilize the network byte order macros here. */ addr.u32 = HTONL(dst); /* Acquire exclusive bus access */ spi_acquire(spi_dev->spi); /* Assert CS */ gpio_clear(spi_dev->cs); /* Enable writes */ status = spi_transfer_byte(spi_dev->spi, NVRAM_SPI_CMD_WREN, NULL); if (status < 0) { return status; } /* Release CS */ gpio_set(spi_dev->cs); xtimer_spin(NVRAM_SPI_CS_TOGGLE_TICKS); /* Re-assert CS */ gpio_clear(spi_dev->cs); /* Write command and address */ status = spi_transfer_regs(spi_dev->spi, NVRAM_SPI_CMD_WRITE, &addr.c[sizeof(addr.c) - spi_dev->address_count], NULL, spi_dev->address_count); if (status < 0) { return status; } /* Keep holding CS and write data */ status = spi_transfer_bytes(spi_dev->spi, (char *)src, NULL, len); if (status < 0) { return status; } /* Release CS */ gpio_set(spi_dev->cs); /* Release exclusive bus access */ spi_release(spi_dev->spi); return status; }
void xtimer_set(xtimer_t *timer, uint32_t offset) { DEBUG("timer_set(): offset=%" PRIu32 " now=%" PRIu32 " (%" PRIu32 ")\n", offset, xtimer_now(), _xtimer_now()); if (!timer->callback) { DEBUG("timer_set(): timer has no callback.\n"); return; } xtimer_remove(timer); uint32_t target = xtimer_now() + offset; if (offset < XTIMER_BACKOFF) { xtimer_spin(offset); _shoot(timer); } else { _xtimer_set_absolute(timer, target); } }
static int nvram_spi_write_9bit_addr(nvram_t *dev, uint8_t *src, uint32_t dst, size_t len) { nvram_spi_params_t *spi_dev = (nvram_spi_params_t *) dev->extra; int status; uint8_t cmd; uint8_t addr; cmd = NVRAM_SPI_CMD_WRITE; /* The upper address bit is mixed into the command byte on certain devices, * probably just to save a byte in the SPI transfer protocol. */ if (dst > 0xff) { cmd |= 0x08; } /* LSB of address */ addr = (dst & 0xff); spi_acquire(spi_dev->spi); gpio_clear(spi_dev->cs); /* Enable writes */ status = spi_transfer_byte(spi_dev->spi, NVRAM_SPI_CMD_WREN, NULL); if (status < 0) { return status; } gpio_set(spi_dev->cs); xtimer_spin(NVRAM_SPI_CS_TOGGLE_TICKS); gpio_clear(spi_dev->cs); /* Write command and address */ status = spi_transfer_reg(spi_dev->spi, cmd, addr, NULL); if (status < 0) { return status; } /* Keep holding CS and write data */ status = spi_transfer_bytes(spi_dev->spi, (char *)src, NULL, len); if (status < 0) { return status; } gpio_set(spi_dev->cs); spi_release(spi_dev->spi); /* status contains the number of bytes actually written to the SPI bus. */ return status; }
int nrf24l01p_init(nrf24l01p_t *dev, spi_t spi, gpio_t ce, gpio_t cs, gpio_t irq) { int status; static const char INITIAL_TX_ADDRESS[] = {0xe7, 0xe7, 0xe7, 0xe7, 0xe7,}; static const char INITIAL_RX_ADDRESS[] = {0xe7, 0xe7, 0xe7, 0xe7, 0xe7,}; dev->spi = spi; dev->ce = ce; dev->cs = cs; dev->irq = irq; dev->listener = KERNEL_PID_UNDEF; /* Init CE pin */ gpio_init(dev->ce, GPIO_OUT); /* Init CS pin */ spi_init_cs(dev->spi, dev->cs); /* Init IRQ pin */ gpio_init_int(dev->irq, GPIO_IN_PU, GPIO_FALLING, nrf24l01p_rx_cb, dev); /* Test the SPI connection */ if (spi_acquire(dev->spi, dev->cs, SPI_MODE, SPI_CLK) != SPI_OK) { DEBUG("error: unable to acquire SPI bus with given params\n"); return -1; } spi_release(dev->spi); xtimer_spin(DELAY_AFTER_FUNC_TICKS); /* Flush TX FIFIO */ status = nrf24l01p_flush_tx_fifo(dev); if (status < 0) { return status; } /* Flush RX FIFIO */ status = nrf24l01p_flush_rx_fifo(dev); if (status < 0) { return status; } /* Setup adress width */ status = nrf24l01p_set_address_width(dev, NRF24L01P_AW_5BYTE); if (status < 0) { return status; } /* Setup payload width */ status = nrf24l01p_set_payload_width(dev, NRF24L01P_PIPE0, NRF24L01P_MAX_DATA_LENGTH); if (status < 0) { return status; } /* Set RF channel */ status = nrf24l01p_set_channel(dev, INITIAL_RF_CHANNEL); if (status < 0) { return status; } /* Set RF power */ status = nrf24l01p_set_power(dev, INITIAL_RX_POWER_0dB); if (status < 0) { return status; } /* Set RF datarate */ status = nrf24l01p_set_datarate(dev, NRF24L01P_DR_250KBS); if (status < 0) { return status; } /* Set TX Address */ status = nrf24l01p_set_tx_address(dev, INITIAL_TX_ADDRESS, INITIAL_ADDRESS_WIDTH); if (status < 0) { return status; } /* Set RX Adress */ status = nrf24l01p_set_rx_address(dev, NRF24L01P_PIPE0, INITIAL_RX_ADDRESS, INITIAL_ADDRESS_WIDTH); if (status < 0) { return status; } /* Reset auto ack for all pipes */ status = nrf24l01p_disable_all_auto_ack(dev); if (status < 0) { return status; } /* Setup Auto ACK and retransmission */ status = nrf24l01p_setup_auto_ack(dev, NRF24L01P_PIPE0, NRF24L01P_RETR_750US, 15); if (status < 0) { return status; } /* Setup CRC */ status = nrf24l01p_enable_crc(dev, NRF24L01P_CRC_2BYTE); if (status < 0) { return status; } /* Reset all interrupt flags */ status = nrf24l01p_reset_all_interrupts(dev); if (status < 0) { return status; } return nrf24l01p_on(dev); }
int nrf24l01p_init(nrf24l01p_t *dev, spi_t spi, gpio_t ce, gpio_t cs, gpio_t irq) { int status; char INITIAL_TX_ADDRESS[] = {0xe7, 0xe7, 0xe7, 0xe7, 0xe7,}; char INITIAL_RX_ADDRESS[] = {0xe7, 0xe7, 0xe7, 0xe7, 0xe7,}; dev->spi = spi; dev->ce = ce; dev->cs = cs; dev->irq = irq; dev->listener = KERNEL_PID_UNDEF; /* Init CE pin */ gpio_init(dev->ce, GPIO_DIR_OUT, GPIO_NOPULL); /* Init CS pin */ gpio_init(dev->cs, GPIO_DIR_OUT, GPIO_NOPULL); gpio_set(dev->cs); /* Init IRQ pin */ gpio_init_int(dev->irq, GPIO_PULLUP, GPIO_FALLING, nrf24l01p_rx_cb, dev); /* Init SPI */ spi_poweron(dev->spi); spi_acquire(dev->spi); status = spi_init_master(dev->spi, SPI_CONF_FIRST_RISING, SPI_SPEED_400KHZ); spi_release(dev->spi); if (status < 0) { return status; } xtimer_spin(DELAY_AFTER_FUNC_TICKS); /* Flush TX FIFIO */ status = nrf24l01p_flush_tx_fifo(dev); if (status < 0) { return status; } /* Flush RX FIFIO */ status = nrf24l01p_flush_rx_fifo(dev); if (status < 0) { return status; } /* Setup adress width */ status = nrf24l01p_set_address_width(dev, NRF24L01P_AW_5BYTE); if (status < 0) { return status; } /* Setup payload width */ status = nrf24l01p_set_payload_width(dev, NRF24L01P_PIPE0, NRF24L01P_MAX_DATA_LENGTH); if (status < 0) { return status; } /* Set RF channel */ status = nrf24l01p_set_channel(dev, INITIAL_RF_CHANNEL); if (status < 0) { return status; } /* Set RF power */ status = nrf24l01p_set_power(dev, INITIAL_RX_POWER_0dB); if (status < 0) { return status; } /* Set RF datarate */ status = nrf24l01p_set_datarate(dev, NRF24L01P_DR_250KBS); if (status < 0) { return status; } /* Set TX Address */ status = nrf24l01p_set_tx_address(dev, INITIAL_TX_ADDRESS, INITIAL_ADDRESS_WIDTH); if (status < 0) { return status; } /* Set RX Adress */ status = nrf24l01p_set_rx_address(dev, NRF24L01P_PIPE0, INITIAL_RX_ADDRESS, INITIAL_ADDRESS_WIDTH); if (status < 0) { return status; } /* Reset auto ack for all pipes */ status = nrf24l01p_disable_all_auto_ack(dev); if (status < 0) { return status; } /* Setup Auto ACK and retransmission */ status = nrf24l01p_setup_auto_ack(dev, NRF24L01P_PIPE0, NRF24L01P_RETR_750US, 15); if (status < 0) { return status; } /* Setup CRC */ status = nrf24l01p_enable_crc(dev, NRF24L01P_CRC_2BYTE); if (status < 0) { return status; } /* Reset all interrupt flags */ status = nrf24l01p_reset_all_interrupts(dev); if (status < 0) { return status; } return nrf24l01p_on(dev); }
void nrf24l01p_stop(const nrf24l01p_t *dev) { xtimer_spin(DELAY_CS_TOGGLE_TICKS); gpio_clear(dev->ce); }