From d4220593b0f2a424fd67128ba96be8e1e68b36c7 Mon Sep 17 00:00:00 2001 From: Peli de Halleux Date: Tue, 10 Jan 2017 10:26:44 -0800 Subject: [PATCH] Serial events (#337) * added "serial->on data received" * updated info * updated docs * added readline to read entire buffer * lazy initialize of serial buffers * init async on event * updated docs --- docs/reference/serial.md | 3 +++ docs/reference/serial/on-data-received.md | 29 ++++++++++++++++++++++ docs/reference/serial/read-string.md | 27 ++++++++++++++++++++ libs/core/_locales/core-jsdoc-strings.json | 4 ++- libs/core/_locales/core-strings.json | 2 ++ libs/core/serial.cpp | 25 +++++++++++-------- libs/core/serial.ts | 16 ++++++------ libs/core/shims.d.ts | 17 +++++++++---- sim/state/serial.ts | 12 +++------ 9 files changed, 102 insertions(+), 33 deletions(-) create mode 100644 docs/reference/serial/on-data-received.md create mode 100644 docs/reference/serial/read-string.md diff --git a/docs/reference/serial.md b/docs/reference/serial.md index 84abf7e1..ad8820e5 100644 --- a/docs/reference/serial.md +++ b/docs/reference/serial.md @@ -7,8 +7,11 @@ serial.writeLine(""); serial.writeNumber(0); serial.writeValue("x", 0); serial.writeString(""); +serial.readUntil(","); serial.readLine(); +serial.readString(); serial.redirect(SerialPin.P0, SerialPin.P0, BaudRate.BaudRate115200); +serial.onDataReceived(",", () => {}) ``` ### See Also diff --git a/docs/reference/serial/on-data-received.md b/docs/reference/serial/on-data-received.md new file mode 100644 index 00000000..de2a6888 --- /dev/null +++ b/docs/reference/serial/on-data-received.md @@ -0,0 +1,29 @@ +# Serial On Data Received + +Registers an event to be fired when one of the delimiter is matched. + + +```sig +serial.onDataReceived(",", () => {}) +``` + +### Parameters + +* `delimiters` is a [string](/reference/types/string) containing any of the character to match + +### Example + +Read values separated by `,`: + +```blocks +serial.onDataReceived(serial.delimiters(Delimiters.Comma), () => { + basic.showString(serial.readUntil(serial.delimiters(Delimiters.Comma))) +}) +``` + +### See also + +[serial](/device/serial), +[serial write line](/reference/serial/write-line), +[serial write value](/reference/serial/write-value) + diff --git a/docs/reference/serial/read-string.md b/docs/reference/serial/read-string.md new file mode 100644 index 00000000..5f3861f5 --- /dev/null +++ b/docs/reference/serial/read-string.md @@ -0,0 +1,27 @@ +# Serial Read String + +Read the buffered serial data as a string + +```sig +serial.readString(); +``` + +### Returns + +* a [string](/reference/types/string) containing input from the serial port. Empty if no data available. + +### Example + +The following program scrolls text on the screen as it arrives from serial. + +```blocks +basic.forever(() => { + basic.showString(serial.readString()); +}); +``` + +### See also + +[serial](/device/serial), +[serial write line](/reference/serial/write-line), +[serial write value](/reference/serial/write-value) diff --git a/libs/core/_locales/core-jsdoc-strings.json b/libs/core/_locales/core-jsdoc-strings.json index 75227da1..2a9ac5d3 100644 --- a/libs/core/_locales/core-jsdoc-strings.json +++ b/libs/core/_locales/core-jsdoc-strings.json @@ -238,8 +238,10 @@ "pins.spiWrite|param|value": "Data to be sent to the SPI slave", "serial": "Reading and writing data over a serial connection.", "serial.delimiters": "Returns the delimiter corresponding string", - "serial.onLineReceived": "Registers an event to be fired when a line has been received", + "serial.onDataReceived": "Registers an event to be fired when one of the delimiter is matched.", + "serial.onDataReceived|param|delimiters": "the characters to match received characters against.", "serial.readLine": "Reads a line of text from the serial port.", + "serial.readString": "Reads the buffered received data as a string", "serial.readUntil": "Reads a line of text from the serial port and returns the buffer when the delimiter is met.", "serial.readUntil|param|delimiter": "text delimiter that separates each text chunk", "serial.redirect": "Dynamically configuring the serial instance to use pins other than USBTX and USBRX.", diff --git a/libs/core/_locales/core-strings.json b/libs/core/_locales/core-strings.json index 6cefb87f..5e5444b0 100644 --- a/libs/core/_locales/core-strings.json +++ b/libs/core/_locales/core-strings.json @@ -181,7 +181,9 @@ "pins.spiWrite|block": "spi write %value", "pins|block": "pins", "serial.delimiters|block": "%del", + "serial.onDataReceived|block": "serial|on data received %delimiters=serial_delimiter_conv", "serial.readLine|block": "serial|read line", + "serial.readString|block": "serial|read string", "serial.readUntil|block": "serial|read until %delimiter=serial_delimiter_conv", "serial.redirect|block": "serial|redirect to|TX %tx|RX %rx|at baud rate %rate", "serial.writeLine|block": "serial|write line %text", diff --git a/libs/core/serial.cpp b/libs/core/serial.cpp index 6b8052c8..bf7f3811 100644 --- a/libs/core/serial.cpp +++ b/libs/core/serial.cpp @@ -51,24 +51,27 @@ namespace serial { } /** - * Reads a line of text from the serial port. - */ - //% help=serial/read-line - //% blockId=serial_read_line block="serial|read line" - //% weight=20 blockGap=8 - StringData* readLine() { - return readUntil(ManagedString("\n").leakData()); + * Reads the buffered received data as a string + */ + //% blockId=serial_read_buffer block="serial|read string" + //% weight=18 + StringData* readString() { + int n = uBit.serial.getRxBufferSize(); + if (n == 0) return ManagedString("").leakData(); + return ManagedString(uBit.serial.read(n, MicroBitSerialMode::ASYNC)).leakData(); } /** - * Registers an event to be fired when one of the delimiter is matched - * @param delimiters the characters to match received characters against. eg:"\n" + * Registers an event to be fired when one of the delimiter is matched. + * @param delimiters the characters to match received characters against. */ - // help=serial/on-data-received - // weight=18 + //% help=serial/on-data-received + //% weight=18 blockId=serial_on_data_received block="serial|on data received %delimiters=serial_delimiter_conv" void onDataReceived(StringData* delimiters, Action body) { uBit.serial.eventOn(ManagedString(delimiters)); registerWithDal(MICROBIT_ID_SERIAL, MICROBIT_SERIAL_EVT_DELIM_MATCH, body); + // lazy initialization of serial buffers + uBit.serial.read(MicroBitSerialMode::ASYNC); } /** diff --git a/libs/core/serial.ts b/libs/core/serial.ts index ba7651a6..fbcdc1fc 100644 --- a/libs/core/serial.ts +++ b/libs/core/serial.ts @@ -38,20 +38,20 @@ namespace serial { } /** - * Registers an event to be fired when a line has been received - */ - // help=serial/on-line-received - // blockId=serial_on_line_received block="serial on line received" - // weight=21 blockGap=8 - export function onLineReceived(body: Action): void { - // serial.onDataReceived("\n", body); + * Reads a line of text from the serial port. + */ + //% help=serial/read-line + //% blockId=serial_read_line block="serial|read line" + //% weight=20 blockGap=8 + export function readLine(): string { + return serial.readUntil(delimiters(Delimiters.NewLine)); } /** * Returns the delimiter corresponding string */ //% blockId="serial_delimiter_conv" block="%del" - //% weight=1 + //% weight=1 blockHidden=true export function delimiters(del: Delimiters): string { // even though it might not look like, this is more // (memory) efficient than the C++ implementation, because the diff --git a/libs/core/shims.d.ts b/libs/core/shims.d.ts index 546d2d14..dfd6a74d 100644 --- a/libs/core/shims.d.ts +++ b/libs/core/shims.d.ts @@ -715,12 +715,19 @@ declare namespace serial { function readUntil(delimiter: string): string; /** - * Reads a line of text from the serial port. + * Reads the buffered received data as a string */ - //% help=serial/read-line - //% blockId=serial_read_line block="serial|read line" - //% weight=20 blockGap=8 shim=serial::readLine - function readLine(): string; + //% blockId=serial_read_buffer block="serial|read string" + //% weight=18 shim=serial::readString + function readString(): string; + + /** + * Registers an event to be fired when one of the delimiter is matched. + * @param delimiters the characters to match received characters against. + */ + //% help=serial/on-data-received + //% weight=18 blockId=serial_on_data_received block="serial|on data received %delimiters=serial_delimiter_conv" shim=serial::onDataReceived + function onDataReceived(delimiters: string, body: () => void): void; /** * Sends a piece of text through Serial connection. diff --git a/sim/state/serial.ts b/sim/state/serial.ts index 5f6e1b4d..518d067e 100644 --- a/sim/state/serial.ts +++ b/sim/state/serial.ts @@ -35,18 +35,14 @@ namespace pxsim.serial { board().writeSerial(s); } + export function readUntil(del: string): string { + return readString(); + } + export function readString(): string { return board().serialState.readSerial(); } - export function readLine(): string { - return board().serialState.readSerial(); - } - - export function readUntil(del: string): string { - return readLine(); - } - export function onDataReceived(delimiters: string, handler: RefAction) { let b = board(); b.bus.listen(DAL.MICROBIT_ID_SERIAL, DAL.MICROBIT_SERIAL_EVT_DELIM_MATCH, handler);