microbit: added BLE UART service

Added a serial implementation for bluetooth, needs a review at a later date.
master
James Devine 7 years ago
parent 728604423f
commit b5c8714ea3

@ -2,6 +2,7 @@
#define EXTERNAL_EVENTS_H
#define MICROBIT_ID_BLE 1000
#define MICROBIT_ID_BLE_UART 1001
#include "MESEvents.h"

@ -0,0 +1,247 @@
#ifndef MICROBIT_UART_SERVICE_H
#define MICROBIT_UART_SERVICE_H
#include "mbed.h"
#include "ble/UUID.h"
#include "ble/BLE.h"
#include "MicroBitConfig.h"
#include "MicroBitSerial.h"
#define MICROBIT_UART_S_DEFAULT_BUF_SIZE 20
#define MICROBIT_UART_S_EVT_DELIM_MATCH 1
#define MICROBIT_UART_S_EVT_HEAD_MATCH 2
#define MICROBIT_UART_S_EVT_RX_FULL 3
class MicroBitUARTService
{
uint8_t* rxBuffer;
uint8_t* txBuffer;
uint8_t rxBufferHead;
uint8_t rxBufferTail;
uint8_t rxBufferSize;
uint8_t txBufferSize;
uint32_t txCharacteristicHandle;
// Bluetooth stack we're running on.
BLEDevice &ble;
//delimeters used for matching on receive.
ManagedString delimeters;
//a variable used when a user calls the eventAfter() method.
int rxBuffHeadMatch;
/**
* A callback function for whenever a Bluetooth device writes to our TX characteristic.
*/
void onDataWritten(const GattWriteCallbackParams *params);
/**
* An internal method that copies values from a circular buffer to a linear buffer.
*
* @param circularBuff a pointer to the source circular buffer
* @param circularBuffSize the size of the circular buffer
* @param linearBuff a pointer to the destination linear buffer
* @param tailPosition the tail position in the circular buffer you want to copy from
* @param headPosition the head position in the circular buffer you want to copy to
*
* @note this method assumes that the linear buffer has the appropriate amount of
* memory to contain the copy operation
*/
void circularCopy(uint8_t *circularBuff, uint8_t circularBuffSize, uint8_t *linearBuff, uint16_t tailPosition, uint16_t headPosition);
public:
/**
* Constructor for the UARTService.
* @param _ble an instance of BLEDevice
* @param rxBufferSize the size of the rxBuffer
* @param txBufferSize the size of the txBuffer
*
* @note defaults to 20
*/
MicroBitUARTService(BLEDevice &_ble, uint8_t rxBufferSize = MICROBIT_UART_S_DEFAULT_BUF_SIZE, uint8_t txBufferSize = MICROBIT_UART_S_DEFAULT_BUF_SIZE);
/**
* Retreives a single character from our RxBuffer.
*
* @param mode the selected mode, one of: ASYNC, SYNC_SPINWAIT, SYNC_SLEEP. Each mode
* gives a different behaviour:
*
* ASYNC - Will attempt to read a single character, and return immediately
*
* SYNC_SPINWAIT - will return MICROBIT_INVALID_PARAMETER
*
* SYNC_SLEEP - Will configure the event and block the current fiber until the
* event is received.
*
* @return MICROBIT_INVALID_PARAMETER if the mode given is SYNC_SPINWAIT, a character or MICROBIT_NO_DATA
*/
int getc(MicroBitSerialMode mode = SYNC_SLEEP);
/**
* places a single character into our transmission buffer,
*
* @param c the character to transmit
*
* @return the number of characters written (0, or 1).
*/
int putc(char c);
/**
* Copies characters into the buffer used for Transmitting to the central device.
*
* @param buf a buffer containing length number of bytes.
* @param length the size of the buffer.
*
* @return the number of characters copied into the buffer
*
* @note no modes for sending are available at the moment, due to interrupt overhead.
*/
int send(const uint8_t *buf, int length);
/**
* Copies characters into the buffer used for Transmitting to the central device.
*
* @param s the string to transmit
*
* @return the number of characters copied into the buffer
*
* @note no modes for sending are available at the moment, due to interrupt overhead.
*/
int send(ManagedString s);
/**
* Reads a number of characters from the rxBuffer and fills user given buffer.
*
* @param buf a pointer to a buffer of len bytes.
* @param len the size of the user allocated buffer
* @param mode the selected mode, one of: ASYNC, SYNC_SPINWAIT, SYNC_SLEEP. Each mode
* gives a different behaviour:
*
* ASYNC - Will attempt to read all available characters, and return immediately
* until the buffer limit is reached
*
* SYNC_SPINWAIT - will return MICROBIT_INVALID_PARAMETER
*
* SYNC_SLEEP - Will first of all determine whether the given number of characters
* are available in our buffer, if not, it will set an event and sleep
* until the number of characters are avaialable.
*
* @return the number of characters digested
*/
int read(uint8_t *buf, int len, MicroBitSerialMode mode = SYNC_SLEEP);
/**
* Reads a number of characters from the rxBuffer and returns them as a ManagedString
*
* @param len the number of characters to read.
* @param mode the selected mode, one of: ASYNC, SYNC_SPINWAIT, SYNC_SLEEP. Each mode
* gives a different behaviour:
*
* ASYNC - Will attempt to read all available characters, and return immediately
* until the buffer limit is reached
*
* SYNC_SPINWAIT - will return MICROBIT_INVALID_PARAMETER
*
* SYNC_SLEEP - Will first of all determine whether the given number of characters
* are available in our buffer, if not, it will set an event and sleep
* until the number of characters are avaialable.
*
* @return an empty ManagedString on error, or a ManagedString containing characters
*/
ManagedString read(int len, MicroBitSerialMode mode = SYNC_SLEEP);
/**
* Reads characters until a character matches one of the given delimeters
*
* @param delimeters the number of characters to match against
* @param mode the selected mode, one of: ASYNC, SYNC_SPINWAIT, SYNC_SLEEP. Each mode
* gives a different behaviour:
*
* ASYNC - Will attempt read the immediate buffer, and look for a match.
* If there isn't, an empty ManagedString will be returned.
*
* SYNC_SPINWAIT - will return MICROBIT_INVALID_PARAMETER
*
* SYNC_SLEEP - Will first of all consider the characters in the immediate buffer,
* if a match is not found, it will block on an event, fired when a
* character is matched.
*
* @return an empty ManagedString on error, or a ManagedString containing characters
*/
ManagedString readUntil(ManagedString delimeters, MicroBitSerialMode mode = SYNC_SLEEP);
/**
* Configures an event to be fired on a match with one of the delimeters.
*
* @param delimeters the characters to match received characters against e.g. ManagedString("\r\n")
* @param mode the selected mode, one of: ASYNC, SYNC_SPINWAIT, SYNC_SLEEP. Each mode
* gives a different behaviour:
*
* ASYNC - Will configure the event and return immediately.
*
* SYNC_SPINWAIT - will return MICROBIT_INVALID_PARAMETER
*
* SYNC_SLEEP - Will configure the event and block the current fiber until the
* event is received.
*
* @return MICROBIT_INVALID_PARAMETER if the mode given is SYNC_SPINWAIT, otherwise MICROBIT_OK.
*
* @note delimeters are matched on a per byte basis.
*/
int eventOn(ManagedString delimeters, MicroBitSerialMode mode = ASYNC);
/**
* Configures an event to be fired after "len" characters.
*
* @param len the number of characters to wait before triggering the event
* @param mode the selected mode, one of: ASYNC, SYNC_SPINWAIT, SYNC_SLEEP. Each mode
* gives a different behaviour:
*
* ASYNC - Will configure the event and return immediately.
*
* SYNC_SPINWAIT - will return MICROBIT_INVALID_PARAMETER
*
* SYNC_SLEEP - Will configure the event and block the current fiber until the
* event is received.
*
* @return MICROBIT_INVALID_PARAMETER if the mode given is SYNC_SPINWAIT, otherwise MICROBIT_OK.
*/
int eventAfter(int len, MicroBitSerialMode mode = ASYNC);
/**
* Determines if we have space in our rxBuff.
*
* @return 1 if we have space, 0 if we do not.
*/
int isReadable();
/**
* @return The currently buffered number of bytes in our rxBuff.
*/
int rxBufferedSize();
/**
* @return The currently buffered number of bytes in our txBuff.
*/
int txBufferedSize();
};
extern const uint8_t UARTServiceBaseUUID[UUID::LENGTH_OF_LONG_UUID];
extern const uint16_t UARTServiceShortUUID;
extern const uint16_t UARTServiceTXCharacteristicShortUUID;
extern const uint16_t UARTServiceRXCharacteristicShortUUID;
extern const uint8_t UARTServiceUUID[UUID::LENGTH_OF_LONG_UUID];
extern const uint8_t UARTServiceUUID_reversed[UUID::LENGTH_OF_LONG_UUID];
extern const uint8_t UARTServiceTXCharacteristicUUID[UUID::LENGTH_OF_LONG_UUID];
extern const uint8_t UARTServiceRXCharacteristicUUID[UUID::LENGTH_OF_LONG_UUID];
#endif

@ -3,5 +3,6 @@
#define MICROBIT_DISPLAY_EVT_FREE 1
#define MICROBIT_SERIAL_EVT_TX_EMPTY 2
#define MICROBIT_UART_S_EVT_TX_EMPTY 3
#endif

@ -50,6 +50,7 @@ set(YOTTA_AUTO_MICROBIT-DAL_CPP_FILES
"bluetooth/MicroBitLEDService.cpp"
"bluetooth/MicroBitMagnetometerService.cpp"
"bluetooth/MicroBitTemperatureService.cpp"
"bluetooth/MicroBitUARTService.cpp"
)
execute_process(WORKING_DIRECTORY "../../yotta_modules/${PROJECT_NAME}" COMMAND "git" "log" "--pretty=format:%h" "-n" "1" OUTPUT_VARIABLE git_hash)

@ -0,0 +1,508 @@
#include "ble/UUID.h"
#include "ExternalEvents.h"
#include "MicroBitUARTService.h"
#include "MicroBitFiber.h"
#include "ErrorNo.h"
#include "NotifyEvents.h"
static uint8_t txBufferHead = 0;
static uint8_t txBufferTail = 0;
static GattCharacteristic* rxCharacteristic = NULL;
/**
* A callback function for whenever a Bluetooth device consumes our RX Buffer
*/
void on_confirmation_received_callback(uint16_t handle)
{
#if CONFIG_ENABLED(MICROBIT_DBG)
SERIAL_DEBUG.printf("RECEIVED!! %d \r\n",handle);
#endif
if(handle == rxCharacteristic->getValueAttribute().getHandle())
{
txBufferTail = txBufferHead;
MicroBitEvent(MICROBIT_ID_NOTIFY, MICROBIT_UART_S_EVT_TX_EMPTY);
}
}
/**
* Constructor for the UARTService.
* @param _ble an instance of BLEDevice
* @param rxBufferSize the size of the rxBuffer
* @param txBufferSize the size of the txBuffer
*
* @note defaults to 20
*/
MicroBitUARTService::MicroBitUARTService(BLEDevice &_ble, uint8_t rxBufferSize, uint8_t txBufferSize) : ble(_ble)
{
txBuffer = (uint8_t *)malloc(txBufferSize);
rxBuffer = (uint8_t *)malloc(rxBufferSize);
rxBufferHead = 0;
rxBufferTail = 0;
this->rxBufferSize = rxBufferSize;
txBufferHead = 0;
txBufferTail = 0;
this->txBufferSize = txBufferSize;
GattCharacteristic txCharacteristic(UARTServiceTXCharacteristicUUID, rxBuffer, 1, rxBufferSize, GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_WRITE | GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_WRITE_WITHOUT_RESPONSE);
rxCharacteristic = new GattCharacteristic(UARTServiceRXCharacteristicUUID, txBuffer, 1, txBufferSize, GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_INDICATE);
GattCharacteristic *charTable[] = {&txCharacteristic, rxCharacteristic};
GattService uartService(UARTServiceUUID, charTable, sizeof(charTable) / sizeof(GattCharacteristic *));
_ble.addService(uartService);
this->txCharacteristicHandle = txCharacteristic.getValueAttribute().getHandle();
_ble.gattServer().onDataWritten(this, &MicroBitUARTService::onDataWritten);
_ble.gattServer().onConfirmationReceived(on_confirmation_received_callback);
}
/**
* A callback function for whenever a Bluetooth device writes to our TX characteristic.
*/
void MicroBitUARTService::onDataWritten(const GattWriteCallbackParams *params) {
if (params->handle == this->txCharacteristicHandle)
{
uint16_t bytesWritten = params->len;
for(int byteIterator = 0; byteIterator < bytesWritten; byteIterator++)
{
int newHead = (rxBufferHead + 1) % rxBufferSize;
if(newHead != rxBufferTail)
{
char c = params->data[byteIterator];
int delimeterOffset = 0;
int delimLength = this->delimeters.length();
//iterate through our delimeters (if any) to see if there is a match
while(delimeterOffset < delimLength)
{
//fire an event if there is to block any waiting fibers
if(this->delimeters.charAt(delimeterOffset) == c)
MicroBitEvent(MICROBIT_ID_BLE_UART, MICROBIT_UART_S_EVT_DELIM_MATCH);
delimeterOffset++;
}
rxBuffer[rxBufferHead] = c;
rxBufferHead = newHead;
if(rxBufferHead == rxBuffHeadMatch)
{
rxBuffHeadMatch = -1;
MicroBitEvent(MICROBIT_ID_BLE_UART, MICROBIT_UART_S_EVT_HEAD_MATCH);
}
}
else
MicroBitEvent(MICROBIT_ID_BLE_UART, MICROBIT_UART_S_EVT_RX_FULL);
}
}
}
/**
* An internal method that copies values from a circular buffer to a linear buffer.
*
* @param circularBuff a pointer to the source circular buffer
* @param circularBuffSize the size of the circular buffer
* @param linearBuff a pointer to the destination linear buffer
* @param tailPosition the tail position in the circular buffer you want to copy from
* @param headPosition the head position in the circular buffer you want to copy to
*
* @note this method assumes that the linear buffer has the appropriate amount of
* memory to contain the copy operation
*/
void MicroBitUARTService::circularCopy(uint8_t *circularBuff, uint8_t circularBuffSize, uint8_t *linearBuff, uint16_t tailPosition, uint16_t headPosition)
{
int toBuffIndex = 0;
while(tailPosition != headPosition)
{
linearBuff[toBuffIndex++] = circularBuff[tailPosition];
tailPosition = (tailPosition + 1) % circularBuffSize;
}
}
/**
* Retreives a single character from our RxBuffer.
*
* @param mode the selected mode, one of: ASYNC, SYNC_SPINWAIT, SYNC_SLEEP. Each mode
* gives a different behaviour:
*
* ASYNC - Will attempt to read a single character, and return immediately
*
* SYNC_SPINWAIT - will return MICROBIT_INVALID_PARAMETER
*
* SYNC_SLEEP - Will configure the event and block the current fiber until the
* event is received.
*
* @return MICROBIT_INVALID_PARAMETER if the mode given is SYNC_SPINWAIT, a character or MICROBIT_NO_DATA
*/
int MicroBitUARTService::getc(MicroBitSerialMode mode)
{
if(mode == SYNC_SPINWAIT)
return MICROBIT_INVALID_PARAMETER;
if(mode == ASYNC)
{
if(!isReadable())
return MICROBIT_NO_DATA;
}
if(mode == SYNC_SLEEP)
{
if(!isReadable())
eventAfter(1, mode);
}
char c = rxBuffer[rxBufferTail];
rxBufferTail = (rxBufferTail + 1) % rxBufferSize;
return c;
}
/**
* places a single character into our transmission buffer,
*
* @param c the character to transmit
*
* @return the number of characters written (0, or 1).
*/
int MicroBitUARTService::putc(char c)
{
return (send((uint8_t *)&c, 1) == 1) ? 1 : EOF;
}
/**
* Copies characters into the buffer used for Transmitting to the central device.
*
* @param buf a buffer containing length number of bytes.
* @param length the size of the buffer.
*
* @return the number of characters copied into the buffer
*
* @note no modes for sending are available at the moment, due to interrupt overhead.
*/
int MicroBitUARTService::send(const uint8_t *buf, int length)
{
if(length < 1)
return MICROBIT_INVALID_PARAMETER;
int bytesWritten = 0;
if (ble.getGapState().connected) {
for(int bufferIterator = 0; bufferIterator < length; bufferIterator++)
{
int nextHead = (txBufferHead + 1) % txBufferSize;
if(nextHead != txBufferTail)
{
txBuffer[txBufferHead] = buf[bufferIterator];
txBufferHead = nextHead;
bytesWritten++;
}
}
int size = txBufferedSize();
#if CONFIG_ENABLED(MICROBIT_DBG)
SERIAL_DEBUG.printf("tx size: %d", size);
#endif
uint8_t temp[size] = { 0 };
circularCopy(txBuffer, txBufferSize, temp, txBufferTail, txBufferHead);
#if CONFIG_ENABLED(MICROBIT_DBG)
for(int i = 0; i < size; i++)
SERIAL_DEBUG.printf("%c",temp[i]);
#endif
ble.gattServer().write(rxCharacteristic->getValueAttribute().getHandle(), temp, size);
}
#if CONFIG_ENABLED(MICROBIT_DBG)
SERIAL_DEBUG.printf("written: %d \r\n",bytesWritten);
#endif
return bytesWritten;
}
/**
* Copies characters into the buffer used for Transmitting to the central device.
*
* @param s the string to transmit
*
* @return the number of characters copied into the buffer
*
* @note no modes for sending are available at the moment, due to interrupt overhead.
*/
int MicroBitUARTService::send(ManagedString s)
{
return send((uint8_t *)s.toCharArray(), s.length());
}
/**
* Reads a number of characters from the rxBuffer and fills user given buffer.
*
* @param buf a pointer to a buffer of len bytes.
* @param len the size of the user allocated buffer
* @param mode the selected mode, one of: ASYNC, SYNC_SPINWAIT, SYNC_SLEEP. Each mode
* gives a different behaviour:
*
* ASYNC - Will attempt to read all available characters, and return immediately
* until the buffer limit is reached
*
* SYNC_SPINWAIT - will return MICROBIT_INVALID_PARAMETER
*
* SYNC_SLEEP - Will first of all determine whether the given number of characters
* are available in our buffer, if not, it will set an event and sleep
* until the number of characters are avaialable.
*
* @return the number of characters digested
*/
int MicroBitUARTService::read(uint8_t *buf, int len, MicroBitSerialMode mode)
{
if(mode == SYNC_SPINWAIT)
return MICROBIT_INVALID_PARAMETER;
int i = 0;
if(mode == ASYNC)
{
int c;
while((c = getc(mode)) > 0 && i < len)
{
buf[i] = c;
i++;
}
}
if(mode == SYNC_SLEEP)
{
if(len > rxBufferedSize())
eventAfter(len - rxBufferedSize(), mode);
while(i < len)
{
buf[i] = (char)getc(mode);
i++;
}
}
return i;
}
/**
* Reads a number of characters from the rxBuffer and returns them as a ManagedString
*
* @param len the number of characters to read.
* @param mode the selected mode, one of: ASYNC, SYNC_SPINWAIT, SYNC_SLEEP. Each mode
* gives a different behaviour:
*
* ASYNC - Will attempt to read all available characters, and return immediately
* until the buffer limit is reached
*
* SYNC_SPINWAIT - will return MICROBIT_INVALID_PARAMETER
*
* SYNC_SLEEP - Will first of all determine whether the given number of characters
* are available in our buffer, if not, it will set an event and sleep
* until the number of characters are avaialable.
*
* @return an empty ManagedString on error, or a ManagedString containing characters
*/
ManagedString MicroBitUARTService::read(int len, MicroBitSerialMode mode)
{
uint8_t buf[len + 1] = { 0 };
int ret = read(buf, len, mode);
if(ret < 1)
return ManagedString();
return ManagedString((const char *)buf);
}
/**
* Reads characters until a character matches one of the given delimeters
*
* @param delimeters the number of characters to match against
* @param mode the selected mode, one of: ASYNC, SYNC_SPINWAIT, SYNC_SLEEP. Each mode
* gives a different behaviour:
*
* ASYNC - Will attempt read the immediate buffer, and look for a match.
* If there isn't, an empty ManagedString will be returned.
*
* SYNC_SPINWAIT - will return MICROBIT_INVALID_PARAMETER
*
* SYNC_SLEEP - Will first of all consider the characters in the immediate buffer,
* if a match is not found, it will block on an event, fired when a
* character is matched.
*
* @return an empty ManagedString on error, or a ManagedString containing characters
*/
ManagedString MicroBitUARTService::readUntil(ManagedString delimeters, MicroBitSerialMode mode)
{
if(mode == SYNC_SPINWAIT)
return MICROBIT_INVALID_PARAMETER;
int localTail = rxBufferTail;
int preservedTail = rxBufferTail;
int foundIndex = -1;
//ASYNC mode just iterates through our stored characters checking for any matches.
while(localTail != rxBufferHead && foundIndex == -1)
{
//we use localTail to prevent modification of the actual tail.
char c = rxBuffer[localTail];
for(int delimeterIterator = 0; delimeterIterator < delimeters.length(); delimeterIterator++)
if(delimeters.charAt(delimeterIterator) == c)
foundIndex = localTail;
localTail = (localTail + 1) % rxBufferSize;
}
//if our mode is SYNC_SLEEP, we set up an event to be fired when we see a
//matching character.
if(mode == SYNC_SLEEP && foundIndex == -1)
{
eventOn(delimeters, mode);
foundIndex = rxBufferHead - 1;
this->delimeters = ManagedString();
}
if(foundIndex >= 0)
{
//calculate our local buffer size
int localBuffSize = (preservedTail > foundIndex) ? (rxBufferSize - preservedTail) + foundIndex : foundIndex - preservedTail;
uint8_t localBuff[localBuffSize + 1] = { 0 };
circularCopy(rxBuffer, rxBufferSize, localBuff, preservedTail, foundIndex);
//plus one for the character we listened for...
rxBufferTail = (rxBufferTail + localBuffSize + 1) % rxBufferSize;
return ManagedString((char *)localBuff, localBuffSize);
}
return ManagedString();
}
/**
* Configures an event to be fired on a match with one of the delimeters.
*
* @param delimeters the characters to match received characters against e.g. ManagedString("\r\n")
* @param mode the selected mode, one of: ASYNC, SYNC_SPINWAIT, SYNC_SLEEP. Each mode
* gives a different behaviour:
*
* ASYNC - Will configure the event and return immediately.
*
* SYNC_SPINWAIT - will return MICROBIT_INVALID_PARAMETER
*
* SYNC_SLEEP - Will configure the event and block the current fiber until the
* event is received.
*
* @return MICROBIT_INVALID_PARAMETER if the mode given is SYNC_SPINWAIT, otherwise MICROBIT_OK.
*
* @note delimeters are matched on a per byte basis.
*/
int MicroBitUARTService::eventOn(ManagedString delimeters, MicroBitSerialMode mode)
{
if(mode == SYNC_SPINWAIT)
return MICROBIT_INVALID_PARAMETER;
//configure our head match...
this->delimeters = delimeters;
//block!
if(mode == SYNC_SLEEP)
fiber_wait_for_event(MICROBIT_ID_BLE_UART, MICROBIT_UART_S_EVT_DELIM_MATCH);
return MICROBIT_OK;
}
/**
* Configures an event to be fired after "len" characters.
*
* @param len the number of characters to wait before triggering the event
* @param mode the selected mode, one of: ASYNC, SYNC_SPINWAIT, SYNC_SLEEP. Each mode
* gives a different behaviour:
*
* ASYNC - Will configure the event and return immediately.
*
* SYNC_SPINWAIT - will return MICROBIT_INVALID_PARAMETER
*
* SYNC_SLEEP - Will configure the event and block the current fiber until the
* event is received.
*
* @return MICROBIT_INVALID_PARAMETER if the mode given is SYNC_SPINWAIT, otherwise MICROBIT_OK.
*/
int MicroBitUARTService::eventAfter(int len, MicroBitSerialMode mode)
{
if(mode == SYNC_SPINWAIT)
return MICROBIT_INVALID_PARAMETER;
//configure our head match...
this->rxBuffHeadMatch = (rxBufferHead + len) % rxBufferSize;
//block!
if(mode == SYNC_SLEEP)
fiber_wait_for_event(MICROBIT_ID_BLE_UART, MICROBIT_UART_S_EVT_HEAD_MATCH);
return MICROBIT_OK;
}
/**
* Determines if we have space in our rxBuff.
*
* @return 1 if we have space, 0 if we do not.
*
* @note the reason we do not wrap the super's readable() method is so that we
* don't interfere with communities that use manual calls to uBit.serial.readable()
*/
int MicroBitUARTService::isReadable()
{
return (rxBufferTail != rxBufferHead) ? 1 : 0;
}
/**
* @return The currently buffered number of bytes in our rxBuff.
*/
int MicroBitUARTService::rxBufferedSize()
{
if(rxBufferTail > rxBufferHead)
return (rxBufferSize - rxBufferTail) + rxBufferHead;
return rxBufferHead - rxBufferTail;
}
/**
* @return The currently buffered number of bytes in our txBuff.
*/
int MicroBitUARTService::txBufferedSize()
{
if(txBufferTail > txBufferHead)
return (txBufferSize - txBufferTail) + txBufferHead;
return txBufferHead - txBufferTail;
}
Loading…
Cancel
Save