/* This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * */ /* Copyright (c) 2015 King Kévin */ /* This library allows to communicate with a nordic semiconductor nRF24L01 2.4GHz single chip transceiver * this library uses the SPI bus and requires interrupts to handle the IRQ */ #include // Standard Integer Types #include // General utilities #include // Boolean #include // Memory utilities #include // AVR device-specific IO definitions #include // Interrupts #include // SPI functions #include // nRF24L01 configuration #include // Standard IO facilities #include // Program Space Utilities #if defined(IRQ_DDR) && defined(IRQ_IO) /* if the nRF24L01 is initialized with interrupts, watch for nrf_activity to go true * once true, check if transmission or reception happened using nrf24_activity(), then nrf24_tx_activity() or nrf24_rx_activity() * you can then check is transmission succeeded using nrf24_tx_succeeded() * or get the received data using nrf24_rx_data() * set it to false after checks are done */ volatile bool nrf24_flag = false; #endif /* stay in RX mode to receive data */ bool rx = false; /* initialize the nRF24L01 */ void nrf24_init() { // configure SPI spi_init(); // SPI is used to communicate with the nRF24L01 // configure IO CE_DDR |= (1<125) { return; } /* verify there is space in the FIFO */ uint8_t cmd[2]; // command cmd[0] = 0x20+0x05; // W_REGISTER command + RF_CH register cmd[1] = channel; // set channel spi_transfer_wait(cmd,sizeof(cmd)); // write RF_CH } /* transmit with of bytes (max 32 bytes) * returns false if input is corrupted or FIFO is already full * returns true after payload is written */ bool nrf24_transmit(uint8_t* payload, uint8_t length) { if (payload==NULL || length==0 || length>32) { // ensure data and size is valid return false; } /* check if TX FIFO is full */ uint8_t cmd[2]; // command cmd[0] = 0x00+0x17; // R_REGISTER command + FIFO_STATUS register spi_transfer_wait(cmd,sizeof(cmd)); // read FIFO status if (cmd[1]&(1<<5)) { // TX_FULL return false; } /* go into TX mode */ cmd[0] = 0x00+0x00; // R_REGISTER command + CONFIG register spi_transfer_wait(cmd,sizeof(cmd)); // read config cmd[0] = 0x20+0x00; // W_REGISTER command + CONFIG register cmd[1] &= ~(1<<0); // set PRIM_RX to 0 (PTX) spi_transfer_wait(cmd,sizeof(cmd)); // write config to got in PTX mode /* write TX payload */ uint8_t* tx = calloc(length+1,sizeof(uint8_t)); tx[0] = 0xa0; // W_TX_PAYLOAD command memcpy(&tx[1],payload,length); // copy data spi_transfer_wait(tx,length+1); // write TX payload /* start transmission */ CE_PORT |= (1< pointer * returns size of received data * returns 0 if no data is available * write maximum in (max payload size is 32) */ uint8_t nrf24_rx_payload(uint8_t* payload, uint8_t size) { uint8_t to_return = 0; // the size of the data uint8_t cmd[2]; // SPI nFR24L01 command cmd[0] = 0x60; // R_RX_PL_WID command spi_transfer_wait(cmd,2); // get size (and STATUS) if ((cmd[0]&0x0e)==0x0e) { // RX_FIFO empty based on RX_P_NO to_return = 0; // no data is available } else if (cmd[1]>32) { // something is wrong cmd[0] = 0xe2; // FLUSH_RX command spi_transfer_wait(cmd,1); // flush, as suggested by the note to_return = 0; } else { // data is available to_return = cmd[1]; if (to_return>size) { // avoid buffer overflow to_return = size; } // go into RX mode cmd[0] = 0x00+0x00; // R_REGISTER command + CONFIG register spi_transfer_wait(cmd,2); // read config cmd[0] = 0x20+0x00; // W_REGISTER command + CONFIG register cmd[1] |= (1<<0); // set PRIM_RX to 1 (PRX) spi_transfer_wait(cmd,2); // write config to got in PRX mode // read RX payload uint8_t* data = calloc(to_return+1,sizeof(uint8_t)); // re-allocated memory to get data data[0] = 0x61; // R_RX_PAYLOAD command spi_transfer_wait(data,to_return+1); // read FIFO (automatically deleted) memcpy(payload,&data[1],to_return); // copy payload free(data); // clean memory data = NULL; // clean memory } return to_return; }