Library for HopeRF RFM22 / RFM22B transceiver module ported to mbed. Original Software from Mike McCauley (mikem@open.com.au) . See http://www.open.com.au/mikem/arduino/RF22/

Dependents:   RF22_MAX_test_Send Geofence_receiver Geofence_sender Geofence_sender ... more

More Info about RFM22-modules like connecting and a demo-program see RF22-Notebook

Committer:
charly
Date:
Mon Sep 02 20:32:54 2013 +0000
Revision:
9:4002a2c117cc
Parent:
5:0386600f3408
removed DEBUG-LEDs LED1 .. LED4 as they make problems on other platforms (KL25Z)

Who changed what in which revision?

UserRevisionLine numberNew contents of line
charly 0:79c6d0071c4c 1 // RF22ReliableDatagram.cpp
charly 0:79c6d0071c4c 2 //
charly 0:79c6d0071c4c 3 // Define addressed datagram
charly 1:813d4f57d630 4 //
charly 1:813d4f57d630 5 // Part of the Arduino RF22 library for operating with HopeRF RF22 compatible transceivers
charly 0:79c6d0071c4c 6 // (see http://www.hoperf.com)
charly 1:813d4f57d630 7 // RF22Datagram will be received only by the addressed node or all nodes within range if the
charly 0:79c6d0071c4c 8 // to address is RF22_BROADCAST_ADDRESS
charly 0:79c6d0071c4c 9 //
charly 0:79c6d0071c4c 10 // Author: Mike McCauley (mikem@open.com.au)
charly 0:79c6d0071c4c 11 // Copyright (C) 2011 Mike McCauley
charly 0:79c6d0071c4c 12 // $Id: RF22ReliableDatagram.cpp,v 1.8 2011/02/15 01:18:03 mikem Exp $
charly 0:79c6d0071c4c 13 // ported to mbed by Karl Zweimueller
charly 0:79c6d0071c4c 14
charly 0:79c6d0071c4c 15 #include <RF22ReliableDatagram.h>
charly 0:79c6d0071c4c 16 //#include <SPI.h>
charly 0:79c6d0071c4c 17
charly 0:79c6d0071c4c 18
charly 0:79c6d0071c4c 19 ////////////////////////////////////////////////////////////////////
charly 0:79c6d0071c4c 20 // Constructors
charly 1:813d4f57d630 21 RF22ReliableDatagram::RF22ReliableDatagram(uint8_t thisAddress ,PinName slaveSelectPin , PinName mosi, PinName miso, PinName sclk, PinName interrupt )
charly 1:813d4f57d630 22 : RF22Datagram(thisAddress ,slaveSelectPin , mosi, miso, sclk, interrupt ) {
charly 0:79c6d0071c4c 23 _retransmissions = 0;
charly 0:79c6d0071c4c 24 _lastSequenceNumber = 0;
charly 0:79c6d0071c4c 25 _timeout = 200;
charly 0:79c6d0071c4c 26 _retries = 3;
charly 0:79c6d0071c4c 27 }
charly 0:79c6d0071c4c 28
charly 0:79c6d0071c4c 29 ////////////////////////////////////////////////////////////////////
charly 0:79c6d0071c4c 30 // Public methods
charly 5:0386600f3408 31 void RF22ReliableDatagram::setTimeout(uint16_t timeout)
charly 5:0386600f3408 32 {
charly 0:79c6d0071c4c 33 _timeout = timeout;
charly 0:79c6d0071c4c 34 }
charly 0:79c6d0071c4c 35
charly 0:79c6d0071c4c 36 ////////////////////////////////////////////////////////////////////
charly 5:0386600f3408 37 void RF22ReliableDatagram::setRetries(uint8_t retries)
charly 5:0386600f3408 38 {
charly 0:79c6d0071c4c 39 _retries = retries;
charly 0:79c6d0071c4c 40 }
charly 0:79c6d0071c4c 41
charly 0:79c6d0071c4c 42 ////////////////////////////////////////////////////////////////////
charly 5:0386600f3408 43 boolean RF22ReliableDatagram::sendtoWait(uint8_t* buf, uint8_t len, uint8_t address)
charly 5:0386600f3408 44 {
charly 0:79c6d0071c4c 45 // Assemble the message
charly 0:79c6d0071c4c 46 uint8_t thisSequenceNumber = ++_lastSequenceNumber;
charly 0:79c6d0071c4c 47
charly 0:79c6d0071c4c 48 Timer t;
charly 1:813d4f57d630 49
charly 0:79c6d0071c4c 50 uint8_t retries = 0;
charly 5:0386600f3408 51 while (retries++ <= _retries)
charly 5:0386600f3408 52 {
charly 1:813d4f57d630 53 setHeaderId(thisSequenceNumber);
charly 1:813d4f57d630 54 setHeaderFlags(0);
charly 1:813d4f57d630 55 sendto(buf, len, address);
charly 1:813d4f57d630 56 waitPacketSent();
charly 0:79c6d0071c4c 57
charly 1:813d4f57d630 58 // Never wait for ACKS to broadcasts:
charly 1:813d4f57d630 59 if (address == RF22_BROADCAST_ADDRESS)
charly 1:813d4f57d630 60 return true;
charly 0:79c6d0071c4c 61
charly 1:813d4f57d630 62 if (retries > 1)
charly 1:813d4f57d630 63 _retransmissions++;
charly 1:813d4f57d630 64 t.start();
charly 1:813d4f57d630 65 unsigned long thisSendTime = t.read_ms(); // Timeout does not include original transmit time
charly 0:79c6d0071c4c 66
charly 0:79c6d0071c4c 67
charly 1:813d4f57d630 68 // Compute a new timeout, random between _timeout and _timeout*2
charly 5:0386600f3408 69 // This is to prevent collisions on every retransmit
charly 1:813d4f57d630 70 // if 2 nodes try to transmit at the same time
charly 1:813d4f57d630 71 uint16_t timeout = _timeout + (_timeout * (rand() % 100) / 100);
charly 5:0386600f3408 72 while (t.read_ms() < (thisSendTime + timeout))
charly 5:0386600f3408 73 {
charly 1:813d4f57d630 74 if (available()) {
charly 1:813d4f57d630 75 clearRxBuf(); // Not using recv, so clear it ourselves
charly 1:813d4f57d630 76 uint8_t from = headerFrom();
charly 1:813d4f57d630 77 uint8_t to = headerTo();
charly 1:813d4f57d630 78 uint8_t id = headerId();
charly 1:813d4f57d630 79 uint8_t flags = headerFlags();
charly 1:813d4f57d630 80 // Now have a message: is it our ACK?
charly 1:813d4f57d630 81 if ( from == address
charly 1:813d4f57d630 82 && to == _thisAddress
charly 1:813d4f57d630 83 && (flags & RF22_FLAGS_ACK)
charly 5:0386600f3408 84 && (id == thisSequenceNumber))
charly 5:0386600f3408 85 {
charly 1:813d4f57d630 86 // Its the ACK we are waiting for
charly 1:813d4f57d630 87 return true;
charly 5:0386600f3408 88 }
charly 5:0386600f3408 89 else if ( !(flags & RF22_FLAGS_ACK)
charly 5:0386600f3408 90 && (id == _seenIds[from]))
charly 5:0386600f3408 91 {
charly 1:813d4f57d630 92 // This is a request we have already received. ACK it again
charly 1:813d4f57d630 93 acknowledge(id, from);
charly 1:813d4f57d630 94 }
charly 1:813d4f57d630 95 // Else discard it
charly 1:813d4f57d630 96 }
charly 1:813d4f57d630 97 // Not the one we are waiting for, maybe keep waiting until timeout exhausted
charly 0:79c6d0071c4c 98 }
charly 1:813d4f57d630 99 // Timeout exhausted, maybe retry
charly 0:79c6d0071c4c 100 }
charly 0:79c6d0071c4c 101 return false;
charly 0:79c6d0071c4c 102 }
charly 0:79c6d0071c4c 103
charly 0:79c6d0071c4c 104 ////////////////////////////////////////////////////////////////////
charly 5:0386600f3408 105 boolean RF22ReliableDatagram::recvfromAck(uint8_t* buf, uint8_t* len, uint8_t* from, uint8_t* to, uint8_t* id, uint8_t* flags)
charly 5:0386600f3408 106 {
charly 0:79c6d0071c4c 107 uint8_t _from;
charly 0:79c6d0071c4c 108 uint8_t _to;
charly 0:79c6d0071c4c 109 uint8_t _id;
charly 0:79c6d0071c4c 110 uint8_t _flags;
charly 0:79c6d0071c4c 111 // Get the message before its clobbered by the ACK (shared rx anfd tx buffer in RF22
charly 5:0386600f3408 112 if (available() && recvfrom(buf, len, &_from, &_to, &_id, &_flags))
charly 5:0386600f3408 113 {
charly 1:813d4f57d630 114 // Never ACK an ACK
charly 5:0386600f3408 115 if (!(_flags & RF22_FLAGS_ACK))
charly 5:0386600f3408 116 {
charly 1:813d4f57d630 117 // Its a normal message for this node, not an ACK
charly 5:0386600f3408 118 if (_to != RF22_BROADCAST_ADDRESS)
charly 5:0386600f3408 119 {
charly 1:813d4f57d630 120 // Its not a broadcast, so ACK it
charly 1:813d4f57d630 121 // Acknowledge message with ACK set in flags and ID set to received ID
charly 1:813d4f57d630 122 acknowledge(_id, _from);
charly 1:813d4f57d630 123 }
charly 1:813d4f57d630 124 // If we have not seen this message before, then we are interested in it
charly 5:0386600f3408 125 if (_id != _seenIds[_from])
charly 5:0386600f3408 126 {
charly 1:813d4f57d630 127 if (from) *from = _from;
charly 1:813d4f57d630 128 if (to) *to = _to;
charly 1:813d4f57d630 129 if (id) *id = _id;
charly 1:813d4f57d630 130 if (flags) *flags = _flags;
charly 1:813d4f57d630 131 _seenIds[_from] = _id;
charly 1:813d4f57d630 132 return true;
charly 1:813d4f57d630 133 }
charly 1:813d4f57d630 134 // Else just re-ack it and wait for a new one
charly 0:79c6d0071c4c 135 }
charly 0:79c6d0071c4c 136 }
charly 0:79c6d0071c4c 137 // No message for us available
charly 0:79c6d0071c4c 138 return false;
charly 0:79c6d0071c4c 139 }
charly 0:79c6d0071c4c 140
charly 1:813d4f57d630 141 boolean RF22ReliableDatagram::recvfromAckTimeout(uint8_t* buf, uint8_t* len, uint16_t timeout, uint8_t* from, uint8_t* to, uint8_t* id, uint8_t* flags) {
charly 0:79c6d0071c4c 142 Timer t;
charly 0:79c6d0071c4c 143 unsigned long endtime = t.read_ms() + timeout;
charly 0:79c6d0071c4c 144 while (t.read_ms() < endtime)
charly 1:813d4f57d630 145 if (recvfromAck(buf, len, from, to, id, flags))
charly 1:813d4f57d630 146 return true;
charly 0:79c6d0071c4c 147 return false;
charly 0:79c6d0071c4c 148 }
charly 0:79c6d0071c4c 149
charly 5:0386600f3408 150 uint16_t RF22ReliableDatagram::retransmissions()
charly 5:0386600f3408 151 {
charly 0:79c6d0071c4c 152 return _retransmissions;
charly 0:79c6d0071c4c 153 }
charly 0:79c6d0071c4c 154
charly 5:0386600f3408 155 void RF22ReliableDatagram::acknowledge(uint8_t id, uint8_t from)
charly 5:0386600f3408 156 {
charly 0:79c6d0071c4c 157 setHeaderId(id);
charly 0:79c6d0071c4c 158 setHeaderFlags(RF22_FLAGS_ACK);
charly 0:79c6d0071c4c 159 // We would prefer to send a zero length ACK,
charly 0:79c6d0071c4c 160 // but if an RF22 receives a 0 length message with a CRC error, it will never receive
charly 0:79c6d0071c4c 161 // a 0 length message again, until its reset, which makes everything hang :-(
charly 0:79c6d0071c4c 162 // So we send an ACK of 1 octet
charly 0:79c6d0071c4c 163 // REVISIT: should we send the RSSI for the information of the sender?
charly 0:79c6d0071c4c 164 uint8_t ack = '!';
charly 1:813d4f57d630 165 sendto(&ack, sizeof(ack), from);
charly 0:79c6d0071c4c 166 waitPacketSent();
charly 0:79c6d0071c4c 167 }