174 lines
7.5 KiB
C++
174 lines
7.5 KiB
C++
#ifndef MICROBIT_RADIO_H
|
|
#define MICROBIT_RADIO_H
|
|
|
|
#include "mbed.h"
|
|
|
|
/**
|
|
* Provides a simple broadcast radio abstraction, built upon the raw nrf51822 RADIO module.
|
|
*
|
|
* The nrf51822 RADIO module supports a number of proprietary modes of operation in addition to the typical BLE usage.
|
|
* This class uses one of these modes to enable simple, point to multipoint communication directly between micro:bits.
|
|
*
|
|
* TODO: The protocols implemented here do not currently perform any significant form of energy management,
|
|
* which means that they will consume far more energy than their BLE equivalent. Later versions of the protocol
|
|
* should look to address this through energy efficient broadcast techniques / sleep scheduling. In particular, the GLOSSY
|
|
* approach to efficienct rebroadcast and network synchronisation would likely provide an effective future step.
|
|
*
|
|
* TODO: Meshing should also be considered - again a GLOSSY approach may be effective here, and highly complementary to
|
|
* the master/slave arachitecture of BLE.
|
|
*
|
|
* TODO: This implementation only operates whilst the BLE stack is disabled. The nrf51822 provides a timeslot API to allow
|
|
* BLE to cohabit with other protocols. Future work to allow this colocation would be benefical, and would also allow for the
|
|
* creation of wireless BLE bridges.
|
|
*
|
|
* NOTE: This API does not contain any form of encryption, authentication or authorization. It's purpose is solely for use as a
|
|
* teaching aid to demonstrate how simple communications operates, and to provide a sandpit through which learning can take place.
|
|
* For serious applications, BLE should be considered a substantially more secure alternative.
|
|
*/
|
|
|
|
// Status Flags
|
|
#define MICROBIT_RADIO_STATUS_INITIALISED 0x0001
|
|
|
|
// Default configuration values
|
|
#define MICROBIT_RADIO_BASE_ADDRESS 0x75626974
|
|
#define MICROBIT_RADIO_DEFAULT_GROUP 0
|
|
#define MICROBIT_RADIO_DEFAULT_TX_POWER 6
|
|
#define MICROBIT_RADIO_DEFAULT_FREQUENCY 7
|
|
#define MICROBIT_RADIO_MAX_PACKET_SIZE 32
|
|
#define MICROBIT_RADIO_HEADER_SIZE 4
|
|
#define MICROBIT_RADIO_MAXIMUM_RX_BUFFERS 4
|
|
|
|
// Known Protocol Numbers
|
|
#define MICROBIT_RADIO_PROTOCOL_DATAGRAM 1 // A simple, single frame datagram. a little like UDP but with smaller packets. :-)
|
|
#define MICROBIT_RADIO_PROTOCOL_EVENTBUS 2 // Transparent propogation of events from one micro:bit to another.
|
|
|
|
// Events
|
|
#define MICROBIT_RADIO_EVT_DATAGRAM 1 // Event to signal that a new datagram has been received.
|
|
|
|
struct PacketBuffer
|
|
{
|
|
uint8_t length; // The length of the remaining bytes in the packet. includes protocol/version/group fields, excluding the length field itself.
|
|
uint8_t version; // Protocol version code.
|
|
uint8_t group; // ID of the group to which this packet belongs.
|
|
uint8_t protocol; // Inner protocol number c.f. those issued by IANA for IP protocols
|
|
|
|
uint8_t payload[MICROBIT_RADIO_MAX_PACKET_SIZE]; // User / higher layer protocol data
|
|
PacketBuffer *next; // Linkage, to allow this and other protocols to queue packets pending processing.
|
|
};
|
|
|
|
#include "MicroBitRadioDatagram.h"
|
|
#include "MicroBitRadioEvent.h"
|
|
|
|
class MicroBitRadio : MicroBitComponent
|
|
{
|
|
uint8_t group; // The radio group to which this micro:bit belongs.
|
|
uint8_t queueDepth; // The number of packets in the receiver queue.
|
|
PacketBuffer *rxQueue; // A linear list of incoming packets, queued awaiting processing.
|
|
PacketBuffer *rxBuf; // A pointer to the buffer being actively used by the RADIO hardware.
|
|
|
|
public:
|
|
MicroBitRadioDatagram datagram; // A simple datagram service.
|
|
MicroBitRadioEvent event; // A simple event handling service.
|
|
static MicroBitRadio *instance; // A singleton reference, used purely by the interrupt service routine.
|
|
|
|
/**
|
|
* Constructor.
|
|
*
|
|
* Initialise the MicroBitRadio. Note that this class is demand activated, so most resources are only
|
|
* committed if send/recv or event registrations calls are made.
|
|
*/
|
|
MicroBitRadio(uint16_t id);
|
|
|
|
/**
|
|
* Change the output power level of the transmitter to the given value.
|
|
*
|
|
* @param power a value in the range 0..7, where 0 is the lowest power and 7 is the highest.
|
|
* @return MICROBIT_OK on success, or MICROBIT_INVALID_PARAMETER if the value is out of range.
|
|
*
|
|
*/
|
|
int setTransmitPower(int power);
|
|
|
|
/**
|
|
* Change the transmission and reception band of the radio to the given channel
|
|
*
|
|
* @param band a frequency band in the range 0 - 100. Each step is 1MHz wide, based at 2400MHz.
|
|
* @return MICROBIT_OK on success, or MICROBIT_INVALID_PARAMETER if the value is out of range.
|
|
*
|
|
*/
|
|
int setFrequencyBand(int band);
|
|
|
|
/**
|
|
* Retrieve a pointer to the currently allocated recieve buffer. This is the area of memory
|
|
* actively being used by the radio hardware to store incoming data.
|
|
*
|
|
* @return a pointer to the current receive buffer
|
|
*/
|
|
PacketBuffer* getRxBuf();
|
|
|
|
/**
|
|
* Attempt to queue a buffer received by the radio hardware, if sufficient space is available.
|
|
*
|
|
* @return MICROBIT_OK on success, or MICROBIT_NO_RESOURCES if a replacement receiver buffer
|
|
* could not be allocated (either by policy or memory exhaustion).
|
|
*/
|
|
int queueRxBuf();
|
|
|
|
/**
|
|
* Initialises the radio for use as a multipoint sender/receiver
|
|
* @return MICROBIT_OK on success, MICROBIT_NOT_SUPPORTED if SoftDevice is enabled.
|
|
*/
|
|
int enable();
|
|
|
|
/**
|
|
* Disables the radio for use as a multipoint sender/receiver.
|
|
* @return MICROBIT_OK on success, MICROBIT_NOT_SUPPORTED if SoftDevice is enabled.
|
|
*/
|
|
int disable();
|
|
|
|
/**
|
|
* Sets the radio to listen to packets sent with the given group id.
|
|
*
|
|
* @param group The group to join. A micro:bit can only listen to one group ID at any time.
|
|
* @return MICROBIT_OK on success.
|
|
*/
|
|
int setGroup(uint8_t group);
|
|
|
|
/**
|
|
* A background, low priority callback that is triggered whenever the processor is idle.
|
|
* Here, we empty our queue of received packets, and pass them onto higher level protocol handlers.
|
|
*
|
|
* We provide optimised handling of well known, simple protocols and events on the MicroBitMessageBus
|
|
* to provide extensibility to other protocols that may be written in the future.
|
|
*/
|
|
virtual void idleTick();
|
|
|
|
/**
|
|
* Determines the number of packets ready to be processed.
|
|
* @return The number of packets in the receive buffer.
|
|
*/
|
|
int dataReady();
|
|
|
|
/**
|
|
* Retrieves the next packet from the receive buffer.
|
|
* If a data packet is available, then it will be returned immediately to
|
|
* the caller. This call will also dequeue the buffer.
|
|
*
|
|
* NOTE: Once recv() has been called, it is the callers resposibility to
|
|
* delete the buffer when appropriate.
|
|
*
|
|
* @return The buffer containing the the packet. If no data is available, NULL is returned.
|
|
*/
|
|
PacketBuffer* recv();
|
|
|
|
/**
|
|
* Transmits the given buffer onto the broadcast radio.
|
|
* The call will wait until the transmission of the packet has completed before returning.
|
|
*
|
|
* @param data The packet contents to transmit.
|
|
* @return MICROBIT_OK on success.
|
|
*/
|
|
int send(PacketBuffer *buffer);
|
|
};
|
|
|
|
#endif
|