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:
Tue Feb 14 19:39:36 2012 +0000
Revision:
0:79c6d0071c4c
Child:
1:813d4f57d630
Initial Port - Quick and Dirty !!!

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