microbit-dal/source/MicroBitSerial.cpp

187 lines
4.1 KiB
C++
Raw Normal View History

#include "MicroBit.h"
#include "mbed.h"
/**
* Constructor.
* Create an instance of MicroBitSerial
*
* @param tx the Pin to be used for transmission
* @param rx the Pin to be used for receiving data
*
* Example:
* @code
* MicroBitSerial serial(USBTX, USBRX);
* @endcode
* @note the default baud rate is 115200
*/
MicroBitSerial::MicroBitSerial(PinName tx, PinName rx) : Serial(tx,rx)
{
this->baud(MICROBIT_SERIAL_DEFAULT_BAUD_RATE);
}
/**
* Sends a managed string over serial.
*
* @param s the ManagedString to send
*
* Example:
* @code
* uBit.serial.printString("abc123");
* @endcode
*/
void MicroBitSerial::sendString(ManagedString s)
{
const int len = s.length();
const char *data = s.toCharArray();
Serial::write(data,len);
}
/**
* Reads a ManagedString from serial
*
* @param len the buffer size for the string, default is defined by MICROBIT_SERIAL_BUFFER_SIZE
*
* Example:
* @code
* uBit.serial.readString();
* @endcode
*
* @note this member function will wait until either the buffer is full, or a \n is received
*/
ManagedString MicroBitSerial::readString(int len)
{
if(len < 3)
len = 3;
char buffer[len];
memset(buffer, 0, sizeof(buffer));
int length = readChars(buffer,len);
if(length == 0)
return ManagedString();
//add in a null terminator so bad things don't happen with ManagedString
buffer[length] = '\0';
return ManagedString(buffer);
}
/**
* Sends a MicroBitImage over serial in csv format.
*
* @param i the instance of MicroBitImage you would like to send.
*
* Example:
* @code
* const uint8_t heart[] = { 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 0, 0, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, }; // a cute heart
* MicroBitImage i(10,5,heart);
* uBit.serial.sendImage(i);
* @endcode
*/
void MicroBitSerial::sendImage(MicroBitImage i)
{
sendString(i.toString());
}
/**
* Reads a MicroBitImage over serial, in csv format.
*
*
* @return a MicroBitImage with the format described over serial
*
* Example:
* @code
* MicroBitImage i = uBit.serial.readImage(5,5);
* @endcode
*
* Example Serial Format:
* @code
* 0,10x0a0,10x0a // 0x0a is a LF terminal which is used as a delimeter
* @endcode
* @note this will finish once the dimensions are met.
*/
MicroBitImage MicroBitSerial::readImage(int width, int height)
{
int rowLength = width * 2;
int len = rowLength * height;
char buffer[len + 1];
memset(buffer, 0, sizeof(buffer));
//add in a null terminator so bad things don't happen with MicroBitImage
buffer[len] = '\0';
for(int i = 0; i < height; i++)
{
int offset = i * rowLength;
readChars(&buffer[offset],len - offset);
buffer[(offset + rowLength) - 1] = '\n';
}
return MicroBitImage(buffer);
}
/**
* Sends the current pixel values, byte-per-pixel, over serial
*
* Example:
* @code
* uBit.serial.sendDisplayState();
* @endcode
*/
void MicroBitSerial::sendDisplayState()
{
for(int i = 0; i < MICROBIT_DISPLAY_HEIGHT; i++)
for(int j = 0; j < MICROBIT_DISPLAY_WIDTH; j++)
_putc(uBit.display.image.getPixelValue(j,i));
}
/**
* Reads pixel values, byte-per-pixel, from serial, and sets the display.
*
* Example:
* @code
* uBit.serial.readDisplayState();
* @endcode
*/
void MicroBitSerial::readDisplayState()
{
for(int i = 0; i < MICROBIT_DISPLAY_HEIGHT; i++)
for(int j = 0; j < MICROBIT_DISPLAY_WIDTH; j++)
{
int c = _getc();
uBit.display.image.setPixelValue(j,i,c);
}
}
ssize_t MicroBitSerial::readChars(void* buffer, size_t length, char eof) {
char* ptr = (char*)buffer;
char* end = ptr + length;
int eofAscii = (int)eof;
while (ptr != end) {
int c = _getc();
//check EOF
if (c == eofAscii)
break;
//store the character
*ptr++ = c;
}
return ptr - (const char*)buffer;
}