Radio communication with NRF24
ssRadio.cpp
- Committer:
- gume
- Date:
- 2017-10-06
- Revision:
- 0:9f5a444886a8
File content as of revision 0:9f5a444886a8:
#include "ssRadio.h" //#include "printf.h" SSRadio::SSRadio(SPI *spi, NodeConfig *config) : rf24(spi, config->cePin, config->csnPin) { this->config = config; this->myAddress = config->nodeId; this->gatewayAddress = ((uint64_t)config->netPrefix << 16) + config->gwId; this->sendSlot = -1; this->freeSlot = -1; this->slot_ms = 4; this->onConnect = NULL; this->onDisconnect = NULL; this->onReceiveData = NULL; } void SSRadio::init() { rf24.begin(); rf24.enableDynamicAck(); rf24.enableDynamicPayloads(); rf24.setCRCLength(RF24_CRC_16); rf24.openReadingPipe(0, config->syncAddress); rf24.openReadingPipe(1, ((uint64_t)config->netPrefix << 16) + config->nodeId); rf24.setAutoAck(0, false); // Disable autoACK on broadcast rf24.setAutoAck(1, true); // Ensure autoACK is enabled on data/control rf24.setChannel(config->channel); rf24.setPALevel(config->paLevel); rf24.setDataRate(config->dataRate); txCounter = 0; rxCounter = 0; txQueueLength = 0; rxQueueLength = 0; rf24.startListening(); // IF_SERIAL_DEBUG(rf24.printDetails()); } bool SSRadio::isRunning() { return rf24.isChipConnected(); } void SSRadio::loop() { // Checking incoming frames uint8_t pipenum; if (rf24.available(&pipenum)) { IF_SERIAL_DEBUG(Serial.println(F("Incoming packet."))); uint8_t ps = rf24.getDynamicPayloadSize(); if (ps > 0) { rf24.read(packetRx, ps); if (pipenum == 0) { receiveSyncFrame(packetRx, ps); } else { receiveDataFrame(packetRx, ps); } } } long now = us_ticker_read() / 1000; // Check the queues bool sent = false; if (txQueueLength > 0) { if (sendSlot > -1) { // There is a timeslot now for the transmission if ((now > lastSync + sendSlot * slot_ms) && (now < lastSync + (sendSlot + 1) * slot_ms)) { instantData(txQueue + 2, txQueue[1], txQueue[0]); //Serial.println("sendSlot"); sent = true; } } else if (freeSlot > 0) { // When freeSlot is not 0 (nobody is scheduled), then send in the free slot if ((now >= lastSync + freeSlot * slot_ms) && (now <= lastSync + (freeSlot + 1) * slot_ms)) { instantData(txQueue + 2, txQueue[1], txQueue[0]); //Serial.println("freeSlot"); sent = true; } } else { // No sync or no others, send immediately instantData(txQueue + 2, txQueue[1], txQueue[0]); //Serial.println("Other"); sent = true; } if (sent) { // Move in the queue; txQueueLength--; if (txQueueLength > 0) memcpy(txQueue, txQueue + 30, txQueueLength * 30); } } // Scheduled tasks if (now > lastSync + 1000) { // last Sync was really long ago sendSlot = -1; freeSlot = -1; } } void SSRadio::receiveSyncFrame(uint8_t *frame, uint8_t size) { lastSync = us_ticker_read() / 1000; // Find self address to get the sending slot uint16_t *nodes = (uint16_t*) frame; sendSlot = -1; //Serial.println("Sync"); //Serial.println(size); uint8_t i = 0; while ((i < size / 2) && (nodes[i] != 0)) { //Serial.println(nodes[i]); if (nodes[i] == myAddress) { sendSlot = i; } i++; } if (nodes[i] == 0) { freeSlot = i; } } void SSRadio::receiveDataFrame(uint8_t *frame, uint8_t size) { Packet *p = (Packet*) frame; IF_SERIAL_DEBUG(Serial.println(F("Data frame received."))); if (onReceiveData) { IF_SERIAL_DEBUG(Serial.println(F("Calling onReceiveData."))); (*onReceiveData)(p->fields.payload, p->fields.type, size - 4); } } bool SSRadio::sendData(uint8_t *data, uint16_t type, uint8_t size) { if (txQueueLength == QUEUELEN) return false; // Queue is full uint8_t *frame = txQueue + txQueueLength * 30; frame[0] = size; frame[1] = type & 0xff; // !!! SHOULD be FIXED for extended types memcpy(frame + 2, data, size); txQueueLength ++; return true; } bool SSRadio::instantData(uint8_t *data, uint16_t type, uint8_t size) { Packet p; p.fields.address = myAddress; p.fields.type = type & 0xff; p.fields.counter = txCounter ++; memcpy(p.fields.payload, data, size); IF_SERIAL_DEBUG(Serial.println(F("Sending data."))); rf24.stopListening(); rf24.setRetries(0, 5); rf24.openWritingPipe(gatewayAddress); bool ok = rf24.write(p.raw, size + 4); rf24.startListening(); if (ok) IF_SERIAL_DEBUG(Serial.println("Success.")); else IF_SERIAL_DEBUG(Serial.println("Fail!")); return ok; } void SSRadio::setOnReceiveData(void (*f)(uint8_t *data, uint16_t type, uint8_t len)) { onReceiveData = f; }