Eddystone test using modified DAL

Dependencies:   BLE_API mbed-dev-bin nRF51822

Dependents:   microbit-eddystone

Fork of microbit-dal by Lancaster University

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers MicroBitRadioDatagram.cpp Source File

MicroBitRadioDatagram.cpp

00001 /*
00002 The MIT License (MIT)
00003 
00004 Copyright (c) 2016 British Broadcasting Corporation.
00005 This software is provided by Lancaster University by arrangement with the BBC.
00006 
00007 Permission is hereby granted, free of charge, to any person obtaining a
00008 copy of this software and associated documentation files (the "Software"),
00009 to deal in the Software without restriction, including without limitation
00010 the rights to use, copy, modify, merge, publish, distribute, sublicense,
00011 and/or sell copies of the Software, and to permit persons to whom the
00012 Software is furnished to do so, subject to the following conditions:
00013 
00014 The above copyright notice and this permission notice shall be included in
00015 all copies or substantial portions of the Software.
00016 
00017 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
00018 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
00019 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
00020 THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
00021 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
00022 FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
00023 DEALINGS IN THE SOFTWARE.
00024 */
00025 
00026 #include "MicroBitConfig.h"
00027 #include "MicroBitRadio.h"
00028 
00029 /**
00030   * Provides a simple broadcast radio abstraction, built upon the raw nrf51822 RADIO module.
00031   *
00032   * This class provides the ability to broadcast simple text or binary messages to other micro:bits in the vicinity
00033   * It is envisaged that this would provide the basis for children to experiment with building their own, simple,
00034   * custom protocols.
00035   *
00036   * @note This API does not contain any form of encryption, authentication or authorisation. Its purpose is solely for use as a
00037   * teaching aid to demonstrate how simple communications operates, and to provide a sandpit through which learning can take place.
00038   * For serious applications, BLE should be considered a substantially more secure alternative.
00039   */
00040 
00041 /**
00042 * Constructor.
00043 *
00044 * Creates an instance of a MicroBitRadioDatagram which offers the ability
00045 * to broadcast simple text or binary messages to other micro:bits in the vicinity
00046 *
00047 * @param r The underlying radio module used to send and receive data.
00048 */
00049 MicroBitRadioDatagram::MicroBitRadioDatagram(MicroBitRadio &r) : radio(r)
00050 {
00051     this->rxQueue = NULL;
00052 }
00053 
00054 /**
00055   * Retrieves packet payload data into the given buffer.
00056   *
00057   * If a data packet is already available, then it will be returned immediately to the caller.
00058   * If no data is available then MICROBIT_INVALID_PARAMETER is returned.
00059   *
00060   * @param buf A pointer to a valid memory location where the received data is to be stored
00061   *
00062   * @param len The maximum amount of data that can safely be stored in 'buf'
00063   *
00064   * @return The length of the data stored, or MICROBIT_INVALID_PARAMETER if no data is available, or the memory regions provided are invalid.
00065   */
00066 int MicroBitRadioDatagram::recv(uint8_t *buf, int len)
00067 {
00068     if (buf == NULL || rxQueue == NULL || len < 0)
00069         return MICROBIT_INVALID_PARAMETER;
00070 
00071     // Take the first buffer from the queue.
00072     FrameBuffer *p = rxQueue;
00073     rxQueue = rxQueue->next;
00074 
00075     int l = min(len, p->length - (MICROBIT_RADIO_HEADER_SIZE - 1));
00076 
00077     // Fill in the buffer provided, if possible.
00078     memcpy(buf, p->payload, l);
00079 
00080     delete p;
00081     return l;
00082 }
00083 
00084 /**
00085   * Retreives packet payload data into the given buffer.
00086   *
00087   * If a data packet is already available, then it will be returned immediately to the caller
00088   * in the form of a PacketBuffer.
00089   *
00090   * @return the data received, or an empty PacketBuffer if no data is available.
00091   */
00092 PacketBuffer MicroBitRadioDatagram::recv()
00093 {
00094     if (rxQueue == NULL)
00095         return PacketBuffer::EmptyPacket;
00096 
00097     FrameBuffer *p = rxQueue;
00098     rxQueue = rxQueue->next;
00099 
00100     PacketBuffer packet(p->payload, p->length - (MICROBIT_RADIO_HEADER_SIZE - 1), p->rssi);
00101 
00102     delete p;
00103     return packet;
00104 }
00105 
00106 /**
00107   * Transmits the given buffer onto the broadcast radio.
00108   *
00109   * This is a synchronous call that will wait until the transmission of the packet
00110   * has completed before returning.
00111   *
00112   * @param buffer The packet contents to transmit.
00113   *
00114   * @param len The number of bytes to transmit.
00115   *
00116   * @return MICROBIT_OK on success, or MICROBIT_INVALID_PARAMETER if the buffer is invalid,
00117   *         or the number of bytes to transmit is greater than `MICROBIT_RADIO_MAX_PACKET_SIZE + MICROBIT_RADIO_HEADER_SIZE`.
00118   */
00119 int MicroBitRadioDatagram::send(uint8_t *buffer, int len)
00120 {
00121     if (buffer == NULL || len < 0 || len > MICROBIT_RADIO_MAX_PACKET_SIZE + MICROBIT_RADIO_HEADER_SIZE - 1)
00122         return MICROBIT_INVALID_PARAMETER;
00123 
00124     FrameBuffer buf;
00125 
00126     buf.length = len + MICROBIT_RADIO_HEADER_SIZE - 1;
00127     buf.version = 1;
00128     buf.group = 0;
00129     buf.protocol = MICROBIT_RADIO_PROTOCOL_DATAGRAM;
00130     memcpy(buf.payload, buffer, len);
00131 
00132     return radio.send(&buf);
00133 }
00134 
00135 /**
00136   * Transmits the given string onto the broadcast radio.
00137   *
00138   * This is a synchronous call that will wait until the transmission of the packet
00139   * has completed before returning.
00140   *
00141   * @param data The packet contents to transmit.
00142   *
00143   * @return MICROBIT_OK on success, or MICROBIT_INVALID_PARAMETER if the buffer is invalid,
00144   *         or the number of bytes to transmit is greater than `MICROBIT_RADIO_MAX_PACKET_SIZE + MICROBIT_RADIO_HEADER_SIZE`.
00145   */
00146 int MicroBitRadioDatagram::send(PacketBuffer data)
00147 {
00148     return send((uint8_t *)data.getBytes(), data.length());
00149 }
00150 
00151 /**
00152   * Transmits the given string onto the broadcast radio.
00153   *
00154   * This is a synchronous call that will wait until the transmission of the packet
00155   * has completed before returning.
00156   *
00157   * @param data The packet contents to transmit.
00158   *
00159   * @return MICROBIT_OK on success, or MICROBIT_INVALID_PARAMETER if the buffer is invalid,
00160   *         or the number of bytes to transmit is greater than `MICROBIT_RADIO_MAX_PACKET_SIZE + MICROBIT_RADIO_HEADER_SIZE`.
00161   */
00162 int MicroBitRadioDatagram::send(ManagedString data)
00163 {
00164     return send((uint8_t *)data.toCharArray(), data.length());
00165 }
00166 
00167 /**
00168   * Protocol handler callback. This is called when the radio receives a packet marked as a datagram.
00169   *
00170   * This function process this packet, and queues it for user reception.
00171   */
00172 void MicroBitRadioDatagram::packetReceived()
00173 {
00174     FrameBuffer *packet = radio.recv();
00175     int queueDepth = 0;
00176 
00177     // We add to the tail of the queue to preserve causal ordering.
00178     packet->next = NULL;
00179 
00180     if (rxQueue == NULL)
00181     {
00182         rxQueue = packet;
00183     }
00184     else
00185     {
00186         FrameBuffer *p = rxQueue;
00187         while (p->next != NULL)
00188         {
00189             p = p->next;
00190             queueDepth++;
00191         }
00192 
00193         if (queueDepth >= MICROBIT_RADIO_MAXIMUM_RX_BUFFERS)
00194         {
00195             delete packet;
00196             return;
00197         }
00198 
00199         p->next = packet;
00200     }
00201 
00202     MicroBitEvent(MICROBIT_ID_RADIO, MICROBIT_RADIO_EVT_DATAGRAM);
00203 }