2016-11-30 06:55:37 +01:00
|
|
|
#include "pxt.h"
|
2016-04-02 07:00:42 +02:00
|
|
|
|
2019-12-02 05:58:26 +01:00
|
|
|
#define MICROBIT_SERIAL_READ_BUFFER_LENGTH 64
|
|
|
|
|
|
|
|
// make sure USB_TX and USB_RX don't overlap with other pin ids
|
2016-10-19 06:36:42 +02:00
|
|
|
enum SerialPin {
|
2019-12-02 05:58:26 +01:00
|
|
|
P0 = MICROBIT_ID_IO_P0,
|
|
|
|
P1 = MICROBIT_ID_IO_P1,
|
|
|
|
P2 = MICROBIT_ID_IO_P2,
|
|
|
|
P8 = MICROBIT_ID_IO_P8,
|
|
|
|
P12 = MICROBIT_ID_IO_P12,
|
|
|
|
P13 = MICROBIT_ID_IO_P13,
|
|
|
|
P14 = MICROBIT_ID_IO_P14,
|
|
|
|
P15 = MICROBIT_ID_IO_P15,
|
|
|
|
P16 = MICROBIT_ID_IO_P16,
|
|
|
|
USB_TX = 1001,
|
|
|
|
USB_RX = 1002
|
2016-05-26 20:07:09 +02:00
|
|
|
};
|
|
|
|
|
2016-10-19 06:36:42 +02:00
|
|
|
enum BaudRate {
|
2016-05-26 20:07:09 +02:00
|
|
|
//% block=115200
|
|
|
|
BaudRate115200 = 115200,
|
2017-02-18 15:32:21 +01:00
|
|
|
//% block=57600
|
2019-12-02 05:58:26 +01:00
|
|
|
BaudRate57600 = 57600,
|
|
|
|
//% block=38400
|
|
|
|
BaudRate38400 = 38400,
|
|
|
|
//% block=31250
|
|
|
|
BaudRate31250 = 31250,
|
|
|
|
//% block=28800
|
|
|
|
BaudRate28800 = 28800,
|
|
|
|
//% block=19200
|
|
|
|
BaudRate19200 = 19200,
|
|
|
|
//% block=14400
|
|
|
|
BaudRate14400 = 14400,
|
2016-05-26 20:07:09 +02:00
|
|
|
//% block=9600
|
2019-12-02 05:58:26 +01:00
|
|
|
BaudRate9600 = 9600,
|
|
|
|
//% block=4800
|
|
|
|
BaudRate4800 = 4800,
|
|
|
|
//% block=2400
|
|
|
|
BaudRate2400 = 2400,
|
|
|
|
//% block=1200
|
|
|
|
BaudRate1200 = 1200
|
2016-05-26 20:07:09 +02:00
|
|
|
};
|
|
|
|
|
2016-10-19 06:36:42 +02:00
|
|
|
enum Delimiters {
|
|
|
|
//% block="new line"
|
|
|
|
NewLine = 1,
|
|
|
|
//% block=","
|
|
|
|
Comma = 2,
|
|
|
|
//% block="$"
|
|
|
|
Dollar = 3,
|
|
|
|
//% block=":"
|
|
|
|
Colon = 4,
|
|
|
|
//% block="."
|
|
|
|
Fullstop = 5,
|
|
|
|
//% block="#"
|
|
|
|
Hash = 6,
|
|
|
|
};
|
|
|
|
|
2019-12-02 05:58:26 +01:00
|
|
|
//% weight=2 color=#002050 icon="\uf287"
|
2016-10-11 22:48:25 +02:00
|
|
|
//% advanced=true
|
2016-04-02 07:00:42 +02:00
|
|
|
namespace serial {
|
|
|
|
// note that at least one // followed by % is needed per declaration!
|
2016-10-11 22:48:25 +02:00
|
|
|
|
2016-04-02 07:00:42 +02:00
|
|
|
/**
|
2019-12-02 05:58:26 +01:00
|
|
|
* Read a line of text from the serial port and return the buffer when the delimiter is met.
|
2016-10-19 06:36:42 +02:00
|
|
|
* @param delimiter text delimiter that separates each text chunk
|
2016-04-02 07:00:42 +02:00
|
|
|
*/
|
2016-10-19 06:36:42 +02:00
|
|
|
//% help=serial/read-until
|
|
|
|
//% blockId=serial_read_until block="serial|read until %delimiter=serial_delimiter_conv"
|
|
|
|
//% weight=19
|
2019-12-02 05:58:26 +01:00
|
|
|
String readUntil(String delimiter) {
|
|
|
|
return PSTR(uBit.serial.readUntil(MSTR(delimiter)));
|
2016-04-02 07:00:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2019-12-02 05:58:26 +01:00
|
|
|
* Read the buffered received data as a string
|
2017-01-10 19:26:44 +01:00
|
|
|
*/
|
2019-12-02 05:58:26 +01:00
|
|
|
//% help=serial/read-string
|
2017-01-10 19:26:44 +01:00
|
|
|
//% blockId=serial_read_buffer block="serial|read string"
|
|
|
|
//% weight=18
|
2019-12-02 05:58:26 +01:00
|
|
|
String readString() {
|
2017-01-10 19:26:44 +01:00
|
|
|
int n = uBit.serial.getRxBufferSize();
|
2019-12-02 05:58:26 +01:00
|
|
|
if (n == 0) return mkString("", 0);
|
|
|
|
return PSTR(uBit.serial.read(n, MicroBitSerialMode::ASYNC));
|
2016-04-02 07:00:42 +02:00
|
|
|
}
|
2016-10-11 22:48:25 +02:00
|
|
|
|
2016-05-17 18:36:01 +02:00
|
|
|
/**
|
2019-12-02 05:58:26 +01:00
|
|
|
* Register an event to be fired when one of the delimiter is matched.
|
2017-01-10 19:26:44 +01:00
|
|
|
* @param delimiters the characters to match received characters against.
|
2016-05-17 18:36:01 +02:00
|
|
|
*/
|
2017-01-10 19:26:44 +01:00
|
|
|
//% help=serial/on-data-received
|
|
|
|
//% weight=18 blockId=serial_on_data_received block="serial|on data received %delimiters=serial_delimiter_conv"
|
2019-12-02 05:58:26 +01:00
|
|
|
void onDataReceived(String delimiters, Action body) {
|
|
|
|
uBit.serial.eventOn(MSTR(delimiters));
|
2016-05-17 18:36:01 +02:00
|
|
|
registerWithDal(MICROBIT_ID_SERIAL, MICROBIT_SERIAL_EVT_DELIM_MATCH, body);
|
2017-01-10 19:26:44 +01:00
|
|
|
// lazy initialization of serial buffers
|
|
|
|
uBit.serial.read(MicroBitSerialMode::ASYNC);
|
2016-05-17 18:36:01 +02:00
|
|
|
}
|
2016-10-11 22:48:25 +02:00
|
|
|
|
2016-10-19 06:36:42 +02:00
|
|
|
/**
|
2019-12-02 05:58:26 +01:00
|
|
|
* Send a piece of text through the serial connection.
|
2016-10-19 06:36:42 +02:00
|
|
|
*/
|
|
|
|
//% help=serial/write-string
|
2019-12-02 05:58:26 +01:00
|
|
|
//% weight=87 blockGap=8
|
2016-10-19 06:36:42 +02:00
|
|
|
//% blockId=serial_writestring block="serial|write string %text"
|
2019-12-02 05:58:26 +01:00
|
|
|
//% text.shadowOptions.toString=true
|
|
|
|
void writeString(String text) {
|
|
|
|
if (!text) return;
|
|
|
|
|
|
|
|
uBit.serial.send(MSTR(text));
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Send a buffer through serial connection
|
|
|
|
*/
|
|
|
|
//% blockId=serial_writebuffer block="serial|write buffer %buffer=serial_readbuffer"
|
|
|
|
//% help=serial/write-buffer advanced=true weight=6
|
|
|
|
void writeBuffer(Buffer buffer) {
|
|
|
|
if (!buffer) return;
|
|
|
|
|
|
|
|
uBit.serial.send(buffer->data, buffer->length);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Read multiple characters from the receive buffer. Pause until enough characters are present.
|
|
|
|
* @param length default buffer length, eg: 64
|
|
|
|
*/
|
|
|
|
//% blockId=serial_readbuffer block="serial|read buffer %length"
|
|
|
|
//% help=serial/read-buffer advanced=true weight=5
|
|
|
|
Buffer readBuffer(int length) {
|
|
|
|
if (length <= 0)
|
|
|
|
length = MICROBIT_SERIAL_READ_BUFFER_LENGTH;
|
|
|
|
|
|
|
|
auto buf = mkBuffer(NULL, length);
|
|
|
|
int read = uBit.serial.read(buf->data, buf->length);
|
|
|
|
if (read != length) {
|
|
|
|
auto prev = buf;
|
|
|
|
buf = mkBuffer(buf->data, read);
|
|
|
|
decrRC(prev);
|
|
|
|
}
|
|
|
|
|
|
|
|
return buf;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool tryResolvePin(SerialPin p, PinName& name) {
|
|
|
|
switch(p) {
|
|
|
|
case SerialPin::USB_TX: name = USBTX; return true;
|
|
|
|
case SerialPin::USB_RX: name = USBRX; return true;
|
|
|
|
default:
|
|
|
|
auto pin = getPin(p);
|
|
|
|
if (NULL != pin) {
|
|
|
|
name = pin->name;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
2016-10-19 06:36:42 +02:00
|
|
|
}
|
|
|
|
|
2016-05-26 20:07:09 +02:00
|
|
|
/**
|
2019-12-02 05:58:26 +01:00
|
|
|
* Set the serial input and output to use pins instead of the USB connection.
|
|
|
|
* @param tx the new transmission pin, eg: SerialPin.P0
|
2017-02-12 10:26:32 +01:00
|
|
|
* @param rx the new reception pin, eg: SerialPin.P1
|
|
|
|
* @param rate the new baud rate. eg: 115200
|
2016-05-26 20:07:09 +02:00
|
|
|
*/
|
|
|
|
//% weight=10
|
2019-12-02 05:58:26 +01:00
|
|
|
//% help=serial/redirect
|
2016-10-19 06:36:42 +02:00
|
|
|
//% blockId=serial_redirect block="serial|redirect to|TX %tx|RX %rx|at baud rate %rate"
|
2016-05-26 20:07:09 +02:00
|
|
|
//% blockExternalInputs=1
|
2019-12-02 05:58:26 +01:00
|
|
|
//% tx.fieldEditor="gridpicker" tx.fieldOptions.columns=3
|
|
|
|
//% tx.fieldOptions.tooltips="false"
|
|
|
|
//% rx.fieldEditor="gridpicker" rx.fieldOptions.columns=3
|
|
|
|
//% rx.fieldOptions.tooltips="false"
|
|
|
|
//% blockGap=8
|
2016-05-26 20:07:09 +02:00
|
|
|
void redirect(SerialPin tx, SerialPin rx, BaudRate rate) {
|
2019-12-02 05:58:26 +01:00
|
|
|
PinName txn;
|
|
|
|
PinName rxn;
|
|
|
|
if (tryResolvePin(tx, txn) && tryResolvePin(rx, rxn))
|
|
|
|
uBit.serial.redirect(txn, rxn);
|
2016-05-26 20:07:09 +02:00
|
|
|
uBit.serial.baud((int)rate);
|
|
|
|
}
|
2019-12-02 05:58:26 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Direct the serial input and output to use the USB connection.
|
|
|
|
*/
|
|
|
|
//% weight=9 help=serial/redirect-to-usb
|
|
|
|
//% blockId=serial_redirect_to_usb block="serial|redirect to USB"
|
|
|
|
void redirectToUSB() {
|
|
|
|
uBit.serial.redirect(USBTX, USBRX);
|
|
|
|
uBit.serial.baud(115200);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Sets the size of the RX buffer in bytes
|
|
|
|
* @param size length of the rx buffer in bytes, eg: 32
|
|
|
|
*/
|
|
|
|
//% help=serial/set-rx-buffer-size
|
|
|
|
//% blockId=serialSetRxBufferSize block="serial set rx buffer size to $size"
|
|
|
|
//% advanced=true
|
|
|
|
void setRxBufferSize(uint8_t size) {
|
|
|
|
uBit.serial.setRxBufferSize(size);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Sets the size of the TX buffer in bytes
|
|
|
|
* @param size length of the tx buffer in bytes, eg: 32
|
|
|
|
*/
|
|
|
|
//% help=serial/set-tx-buffer-size
|
|
|
|
//% blockId=serialSetTxBufferSize block="serial set tx buffer size to $size"
|
|
|
|
//% advanced=true
|
|
|
|
void setTxBufferSize(uint8_t size) {
|
|
|
|
uBit.serial.setTxBufferSize(size);
|
|
|
|
}
|
2016-07-20 07:21:15 +02:00
|
|
|
}
|