//-------------------------------------------------------------------------------------------------- // Send payload data via RF //------------------------------------------------------------------------------------------------- void tools_rfwrite (byte myNodeID, const void* ptr, uint8_t len) { if(tools_ack()){ for (byte i = 0; i <= RETRY_LIMIT; ++i) { // tx and wait for ack up to RETRY_LIMIT times rf12_sleep(-1); // Wake up RF module while (!rf12_canSend()) rf12_recvDone(); rf12_sendStart(RF12_HDR_ACK, ptr, len); rf12_sendWait(2); // Wait for RF to finish sending while in standby mode byte acked = waitForAck(myNodeID); // Wait for ACK rf12_sleep(0); // Put RF module to sleep if (acked) { return; } // Return if ACK received Sleepy::loseSomeTime(RETRY_PERIOD * 1000); // If no ack received wait and try again } } else { rf12_sleep(-1); // Wake up RF module while (!rf12_canSend()) rf12_recvDone(); rf12_sendStart(0, ptr, len); rf12_sendWait(2); // Wait for RF to finish sending while in standby mode rf12_sleep(0); // Put RF module to sleep return; } }
void forwardPacket() { // make copies, because rf12_* will change in next rf12_recvDone byte hdr = rf12_hdr, len = rf12_len; if (config.multi_node) { // special case: insert original header (src node ID) as first data byte // careful with max-length packets in multi-node mode: drop last byte! // this is necessary because we're inserting an extra byte at the front if (len >= sizeof buf) --len; buf[0]= hdr; } memcpy(buf + config.multi_node, (void*) rf12_data, len); // save these for later as well, same reason as above byte wantsAck = RF12_WANTS_ACK, ackReply = RF12_ACK_REPLY; if (config.acks_enable) { // if we're not supposed to send back ACKs, then don't ask for 'em wantsAck = false; hdr &= ~ RF12_HDR_ACK; } Serial.print("\n[*]"); // switch to outgoing group rf12_initialize(config.out_node, code2type(config.freq), config.out_group); // send our packet, once possible while (!rf12_canSend()) rf12_recvDone(); rf12_sendStart(hdr, buf, len + config.multi_node, 1); if (wantsAck) { ackTimer.set(100); // wait up to 100 ms for a valid ack packet wantsAck = false; while (!wantsAck && !ackTimer.poll()) wantsAck = rf12_recvDone() && rf12_crc == 0; } // switch back to incoming group rf12_initialize(config.in_node, code2type(config.freq), config.in_group); if (wantsAck) { // copy ack packet to our temp buffer, same reason as above len = rf12_len; memcpy(buf, (void*) rf12_data, rf12_len); // send ACK packet back, once possible while (!rf12_canSend()) rf12_recvDone(); rf12_sendStart(ackReply, buf, len, 1); } }
/// @details /// Needs to be called often to keep the easy transmission mechanism going, /// i.e. once per millisecond or more in normal use. Failure to poll frequently /// enough is relatively harmless but may lead to lost acknowledgements. /// @returns 1 = an ack has been received with actual data in it, use rf12len /// and rf12data to access it. 0 = there is nothing to do, the last /// send has been ack'ed or more than 8 re-transmits have failed. /// -1 = still sending or waiting for an ack to come in /// @note To be used in combination with rf12_easyInit() and rf12_easySend(). char rf12_easyPoll () { if (rf12_recvDone() && rf12_crc == 0) { byte myAddr = nodeid & RF12_HDR_MASK; if (rf12_hdr == (RF12_HDR_CTL | RF12_HDR_DST | myAddr)) { ezPending = 0; ezNextSend[0] = 0; // flags succesful packet send if (rf12_len > 0) return 1; } } if (ezPending > 0) { // new data sends should not happen less than ezInterval seconds apart // ... whereas retries should not happen less than RETRY_MS apart byte newData = ezPending == RETRIES; long now = millis(); if (now >= ezNextSend[newData] && rf12_canSend()) { ezNextSend[0] = now + RETRY_MS; // must send new data packets at least ezInterval seconds apart // ezInterval == 0 is a special case: // for the 868 MHz band: enforce 1% max bandwidth constraint // for other bands: use 100 msec, i.e. max 10 packets/second if (newData) ezNextSend[1] = now + (ezInterval > 0 ? 1000L * ezInterval : (nodeid >> 6) == RF12_868MHZ ? 13 * (ezSendLen + 10) : 100); rf12_sendStart(RF12_HDR_ACK, ezSendBuf, ezSendLen); --ezPending; }
boolean AQERF_Base::pair(){ uint32_t current_time = millis(); boolean pairing_done = false; if (rf12_recvDone()) { // incoming data is present if(0 == rf12_crc){ // otherwise the data is unreliable if(pairingRxCallback != 0){ pairingRxCallback(packet); } } } if(current_time < end_time){ if(current_time - previous_time > PAIRING_BROADCAST_INTERVAL_MS) { previous_time = current_time; need_to_send = 1; } if(need_to_send && rf12_canSend()){ rf12_sendStart(0, packet, AQERF_BASE_STATION_ADVERTISEMENT_PACKET_LENGTH); need_to_send = 0; } pairing_done = false; } else{ pairing_done = true; } return pairing_done; }
void trace_flush(bool force=false) { if (force && trace_cnt > 0 || trace_cnt >= TRACE/2) { if (rf12_canSend()) { trace_buf[0] = LOG_MODULE; rf12_sendStart(node_id, trace_buf, trace_cnt+1); trace_cnt = 0; } } }
uint8_t AQERF_Remote::pair(){ // try this for a period of time up to the pairing duration uint8_t return_value = 0; uint8_t rx_base_station_address[6]; uint8_t comparison = 0; eeprom_read_block(base_station_address, (const void *) AQERF_EEPROM_LAST_KNOWN_BASE_ADDRESS, 6); for(uint32_t ii = 0; ii < AQERF_PAIRING_DURATION_MS; ii++){ if (rf12_recvDone()) { // incoming data is present if(0 == rf12_crc){ // otherwise the data is unreliable if(AQERF_PACKET_TYPE_BASE_STATION_ADVERTISEMENT == rf12_data[AQERF_PACKET_TYPE_OFFSET]){ // we have a pairing ... // store the advertised base address in RAM and EEPROM memcpy(rx_base_station_address, (const void *) (rf12_data + AQERF_BASE_ADDRESS_OFFSET), AQERF_BASE_ADDRESS_LENGTH); // ping back to the base to let it know you are all set by echoing the packet with your address memcpy(packet + AQERF_BASE_ADDRESS_OFFSET, unit_address, AQERF_BASE_ADDRESS_LENGTH); delay(200); while(!rf12_canSend()){ rf12_recvDone(); } rf12_sendStart(0, packet, AQERF_BASE_STATION_ADVERTISEMENT_PACKET_LENGTH); //for(uint8_t jj = 0; jj < 100; jj++){ // rf12_recvDone(); // ensures the packet gets sent //} Serial.println(F("Sent ACK")); //Store the base_station_address to EEPROM comparison = 1; for(uint8_t jj = 0; jj < 6; jj++){ if(rx_base_station_address[jj] != base_station_address[jj]){ comparison = 0; } } if(comparison == 0){ Serial.println(F("Overwriting EEPROM")); eeprom_write_block(rx_base_station_address, (void *) AQERF_EEPROM_LAST_KNOWN_BASE_ADDRESS, 6); eeprom_read_block(base_station_address, (const void *) AQERF_EEPROM_LAST_KNOWN_BASE_ADDRESS, 6); } return_value = 1; } } } delay(1); } return return_value; }
// Broadcast a new packet, this is what user code should call void Net::bcast(uint8_t len) { #ifndef NET_NONE if (bufCnt >= NET_PKT) return; // error? buf[bufCnt].len = len; buf[bufCnt].hdr = node_id; bufCnt++; // if there was no packet queued just go ahead and send the new one if (bufCnt == 1 && rf12_canSend()) { doSend(); } #endif }
void loop() { for (int i = 0; i < NUM_COUNTERS; i++) { // loop through the counters // read the counter input pin: counterState[i] = digitalRead(counterPin[i]); // compare the counterState to its previous state if (counterState[i] != lastCounterState[i]) { if (counterState[i] == LOW) { digitalWrite(LED1, HIGH); // if the current state is HIGH then the button // wend from off to on: #ifdef DEBUG_ENABLED Serial.print(i); Serial.println(" LOW"); #endif payload.active_counter = i; counterMillis[i] = millis(); payload.counter_millis = counterMillis[i]; if (counterMillis[i] - lastCounterMillis[i] > 90) { // send a packet while (!rf12_canSend()) rf12_recvDone(); // send as broadcast, payload will be encrypted rf12_sendStart(0, &payload, sizeof(payload)); rf12_sendWait(1); } lastCounterMillis[i] = counterMillis[i]; #ifdef DEBUG_ENABLED } else { // transision from LOW to HIGH means the pulse is over // we're not interested in that Serial.print(i); Serial.println(" HIGH"); #endif } Serial.println(); } // save the current state as the last state, //for next time through the loop lastCounterState[i] = counterState[i]; if (led1Timer.poll(90)) { digitalWrite(LED1, LOW); } } wdt_reset(); }
bool RF12Module::Send(byte destination, byte* message, uint8_t sendLen, bool needAck) { if (rf12_canSend()) { byte header = needAck ? RF12_HDR_ACK : 0; if (destination) header |= RF12_HDR_DST | destination; rf12_sendStart(header, message, sendLen); rf12_sendWait(1); return true; } else { // What must we do... return false; } }
// raw form of send where full header gets passed-in void Net::rawSend(uint8_t len, uint8_t hdr) { #ifndef NET_NONE if (bufCnt >= NET_PKT) return; // error? buf[bufCnt].len = len; buf[bufCnt].hdr = hdr; bufCnt++; // if there was no packet queued just go ahead and send the new one trace('>'); if (bufCnt == 1) { if (rf12_canSend()) { doSend(); } else { trace('-'); //Serial.println(F("Cannot send")); } } #endif }
boolean AQERF_Base::pair(void){ uint32_t current_time = millis(); boolean pairing_done = false; if(current_time < end_time){ rf12_recvDone(); if(current_time - previous_time > PAIRING_BROADCAST_INTERVAL_MS) { previous_time = current_time; need_to_send = 1; } if(rf12_canSend() && need_to_send){ rf12_sendStart(0, packet, AQERF_BASE_STATION_ADVERTISEMENT_PACKET_LENGTH); need_to_send = 0; } pairing_done = false; } else{ pairing_done = true; } return pairing_done; }
void sendTempPacket() { digitalWrite(PIN_LED, HIGH); #define N 512 #define PIN_TEMP1 2 #define PIN_TEMP2 3 long t1 = 0; long t2 = 0; Serial.print("["); for (int i = 0; i < N; i++) { if (rf12_recvDone() && rf12_crc == 0) { forwardPacket(); } t1 += analogRead(PIN_TEMP1); t2 += analogRead(PIN_TEMP2); } Serial.print(t1 / N * 3300 / 1024); Serial.print(" "); Serial.print(t2 / N * 3300 / 1024); Serial.print(" "); //long t = ((l2 - l1) * 3300) / 4096; long t = (t2 - t1) * 3300 * 10 / N / 1024; Serial.print(t); rf12_initialize(config.out_node, code2type(config.freq), config.out_group); Serial.print(" *"); payload[4] = 1; *((int*)(payload + 5)) = (int) t; // send our packet, once possible while (!rf12_canSend()) rf12_recvDone(); Serial.print(" *"); rf12_sendStart(0, payload, sizeof payload, 1); Serial.println("]"); digitalWrite(PIN_LED, LOW); }
void sendPulsePacket() { cli(); volatile unsigned long long pulsesNow = pulses; volatile unsigned long noiseNow = noise; sei(); Serial.print("("); Serial.print(millis()); Serial.print(")"); digitalWrite(PIN_LED, HIGH); Serial.print("[P:"); Serial.print((unsigned long)pulsesNow); Serial.print(","); Serial.print(noise); pulsePayload[4] = 4; *((unsigned long long*)(pulsePayload + 5)) = pulsesNow; *((unsigned long*)(pulsePayload + 13)) = noiseNow; // send our packet, once possible while (!rf12_canSend()) rf12_recvDone(); Serial.print(" *"); rf12_sendStart(0, pulsePayload, sizeof pulsePayload, 1); Serial.println("]"); digitalWrite(PIN_LED, LOW); }
/// @details /// Wait until transmission is possible, then start it as soon as possible. /// @note This uses a (brief) busy loop and will discard any incoming packets. /// @param hdr The header contains information about the destination of the /// packet to send, and flags such as whether this should be /// acknowledged - or if it actually is an acknowledgement. /// @param ptr Pointer to the data to send as packet. /// @param len Number of data bytes to send. Must be in the range 0 .. 65. void rf12_sendNow (uint8_t hdr, const void* ptr, uint8_t len) { while (!rf12_canSend()) rf12_recvDone(); // keep the driver state machine going, ignore incoming rf12_sendStart(hdr, ptr, len); }
// must be called often to keep the driver moving uint8_t AQERF_Remote::clearToSend(void){ rf12_recvDone(); return rf12_canSend(); }