Attempting to publish a tree

Dependencies:   BLE_API mbed-dev-bin nRF51822

Fork of microbit-dal by Lancaster University

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers MicroBitSerial.h Source File

MicroBitSerial.h

00001 /*
00002 The MIT License (MIT)
00003 
00004 Copyright (c) 2016 British Broadcasting Corporation.
00005 This software is provided by Lancaster University by arrangement with the BBC.
00006 
00007 Permission is hereby granted, free of charge, to any person obtaining a
00008 copy of this software and associated documentation files (the "Software"),
00009 to deal in the Software without restriction, including without limitation
00010 the rights to use, copy, modify, merge, publish, distribute, sublicense,
00011 and/or sell copies of the Software, and to permit persons to whom the
00012 Software is furnished to do so, subject to the following conditions:
00013 
00014 The above copyright notice and this permission notice shall be included in
00015 all copies or substantial portions of the Software.
00016 
00017 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
00018 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
00019 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
00020 THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
00021 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
00022 FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
00023 DEALINGS IN THE SOFTWARE.
00024 */
00025 
00026 #ifndef MICROBIT_SERIAL_H
00027 #define MICROBIT_SERIAL_H
00028 
00029 #include "mbed.h"
00030 #include "ManagedString.h"
00031 
00032 #define MICROBIT_SERIAL_DEFAULT_BAUD_RATE   115200
00033 #define MICROBIT_SERIAL_DEFAULT_BUFFER_SIZE 20
00034 
00035 #define MICROBIT_SERIAL_EVT_DELIM_MATCH     1
00036 #define MICROBIT_SERIAL_EVT_HEAD_MATCH      2
00037 #define MICROBIT_SERIAL_EVT_RX_FULL         3
00038 
00039 #define MICROBIT_SERIAL_RX_IN_USE           1
00040 #define MICROBIT_SERIAL_TX_IN_USE           2
00041 #define MICROBIT_SERIAL_RX_BUFF_INIT        4
00042 #define MICROBIT_SERIAL_TX_BUFF_INIT        8
00043 
00044 
00045 enum MicroBitSerialMode
00046 {
00047     ASYNC,
00048     SYNC_SPINWAIT,
00049     SYNC_SLEEP
00050 };
00051 
00052 /**
00053   * Class definition for MicroBitSerial.
00054   *
00055   * Represents an instance of RawSerial which accepts micro:bit specific data types.
00056   */
00057 class MicroBitSerial : public RawSerial
00058 {
00059 
00060     //holds that state of the mutex locks for all MicroBitSerial instances.
00061     static uint8_t status;
00062 
00063     //holds the state of the baudrate for all MicroBitSerial instances.
00064     static int baudrate;
00065 
00066     //delimeters used for matching on receive.
00067     ManagedString delimeters;
00068 
00069     //a variable used when a user calls the eventAfter() method.
00070     int rxBuffHeadMatch;
00071 
00072     uint8_t *rxBuff;
00073     uint8_t rxBuffSize;
00074     volatile uint16_t rxBuffHead;
00075     uint16_t rxBuffTail;
00076 
00077 
00078     uint8_t *txBuff;
00079     uint8_t txBuffSize;
00080     uint16_t txBuffHead;
00081     volatile uint16_t txBuffTail;
00082 
00083     /**
00084       * An internal interrupt callback for MicroBitSerial configured for when a
00085       * character is received.
00086       *
00087       * Each time a character is received fill our circular buffer!
00088       */
00089     void dataReceived();
00090 
00091     /**
00092       * An internal interrupt callback for MicroBitSerial.
00093       *
00094       * Each time the Serial module's buffer is empty, write a character if we have
00095       * characters to write.
00096       */
00097     void dataWritten();
00098 
00099     /**
00100       * An internal method to configure an interrupt on tx buffer and also
00101       * a best effort copy operation to move bytes from a user buffer to our txBuff
00102       *
00103       * @param string a pointer to the first character of the users' buffer.
00104       *
00105       * @param len the length of the string, and ultimately the maximum number of bytes
00106       *        that will be copied dependent on the state of txBuff
00107       *
00108       * @return the number of bytes copied into the buffer.
00109       */
00110     int setTxInterrupt(uint8_t *string, int len);
00111 
00112     /**
00113       * Locks the mutex so that others can't use this serial instance for reception
00114       */
00115     void lockRx();
00116 
00117     /**
00118       * Locks the mutex so that others can't use this serial instance for transmission
00119       */
00120     void lockTx();
00121 
00122     /**
00123       * Unlocks the mutex so that others can use this serial instance for reception
00124       */
00125     void unlockRx();
00126 
00127     /**
00128       * Unlocks the mutex so that others can use this serial instance for transmission
00129       */
00130     void unlockTx();
00131 
00132     /**
00133       * We do not want to always have our buffers initialised, especially if users to not
00134       * use them. We only bring them up on demand.
00135       */
00136     int initialiseRx();
00137 
00138     /**
00139       * We do not want to always have our buffers initialised, especially if users to not
00140       * use them. We only bring them up on demand.
00141       */
00142     int initialiseTx();
00143 
00144     /**
00145       * An internal method that either spin waits if mode is set to SYNC_SPINWAIT
00146       * or puts the fiber to sleep if the mode is set to SYNC_SLEEP
00147       *
00148       * @param mode the selected mode, one of: ASYNC, SYNC_SPINWAIT, SYNC_SLEEP
00149       */
00150     void send(MicroBitSerialMode mode);
00151 
00152     /**
00153       * Reads a single character from the rxBuff
00154       *
00155       * @param mode the selected mode, one of: ASYNC, SYNC_SPINWAIT, SYNC_SLEEP. Each mode
00156       *        gives a different behaviour:
00157       *
00158       *            ASYNC - A character is read from the rxBuff if available, if there
00159       *                    are no characters to be read, a value of zero is returned immediately.
00160       *
00161       *            SYNC_SPINWAIT - A character is read from the rxBuff if available, if there
00162       *                            are no characters to be read, this method will spin
00163       *                            (lock up the processor) until a character is available.
00164       *
00165       *            SYNC_SLEEP - A character is read from the rxBuff if available, if there
00166       *                         are no characters to be read, the calling fiber sleeps
00167       *                         until there is a character available.
00168       *
00169       *         Defaults to SYNC_SLEEP.
00170       *
00171       * @return a character from the circular buffer, or MICROBIT_NO_DATA is there
00172       *         are no characters in the buffer.
00173       */
00174     int getChar(MicroBitSerialMode mode);
00175 
00176     /**
00177       * An internal method that copies values from a circular buffer to a linear buffer.
00178       *
00179       * @param circularBuff a pointer to the source circular buffer
00180       *
00181       * @param circularBuffSize the size of the circular buffer
00182       *
00183       * @param linearBuff a pointer to the destination linear buffer
00184       *
00185       * @param tailPosition the tail position in the circular buffer you want to copy from
00186       *
00187       * @param headPosition the head position in the circular buffer you want to copy to
00188       *
00189       * @note this method assumes that the linear buffer has the appropriate amount of
00190       *       memory to contain the copy operation
00191       */
00192     void circularCopy(uint8_t *circularBuff, uint8_t circularBuffSize, uint8_t *linearBuff, uint16_t tailPosition, uint16_t headPosition);
00193 
00194     public:
00195 
00196     /**
00197       * Constructor.
00198       * Create an instance of MicroBitSerial
00199       *
00200       * @param tx the Pin to be used for transmission
00201       *
00202       * @param rx the Pin to be used for receiving data
00203       *
00204       * @param rxBufferSize the size of the buffer to be used for receiving bytes
00205       *
00206       * @param txBufferSize the size of the buffer to be used for transmitting bytes
00207       *
00208       * @code
00209       * MicroBitSerial serial(USBTX, USBRX);
00210       * @endcode
00211       * @note the default baud rate is 115200. More API details can be found:
00212       *       -https://github.com/mbedmicro/mbed/blob/master/libraries/mbed/api/SerialBase.h
00213       *       -https://github.com/mbedmicro/mbed/blob/master/libraries/mbed/api/RawSerial.h
00214       *
00215       *       Buffers aren't allocated until the first send or receive respectively.
00216       */
00217     MicroBitSerial(PinName tx, PinName rx, uint8_t rxBufferSize = MICROBIT_SERIAL_DEFAULT_BUFFER_SIZE, uint8_t txBufferSize = MICROBIT_SERIAL_DEFAULT_BUFFER_SIZE);
00218 
00219     /**
00220       * Sends a single character over the serial line.
00221       *
00222       * @param c the character to send
00223       *
00224       * @param mode the selected mode, one of: ASYNC, SYNC_SPINWAIT, SYNC_SLEEP. Each mode
00225       *        gives a different behaviour:
00226       *
00227       *            ASYNC - the character is copied into the txBuff and returns immediately.
00228       *
00229       *            SYNC_SPINWAIT - the character is copied into the txBuff and this method
00230       *                            will spin (lock up the processor) until the character has
00231       *                            been sent.
00232       *
00233       *            SYNC_SLEEP - the character is copied into the txBuff and the fiber sleeps
00234       *                         until the character has been sent. This allows other fibers
00235       *                         to continue execution.
00236       *
00237       *         Defaults to SYNC_SLEEP.
00238       *
00239       * @return the number of bytes written, or MICROBIT_SERIAL_IN_USE if another fiber
00240       *         is using the serial instance for transmission.
00241       */
00242     int sendChar(char c, MicroBitSerialMode mode = MICROBIT_DEFAULT_SERIAL_MODE);
00243 
00244     /**
00245       * Sends a ManagedString over the serial line.
00246       *
00247       * @param s the string to send
00248       *
00249       * @param mode the selected mode, one of: ASYNC, SYNC_SPINWAIT, SYNC_SLEEP. Each mode
00250       *        gives a different behaviour:
00251       *
00252       *            ASYNC - bytes are copied into the txBuff and returns immediately.
00253       *
00254       *            SYNC_SPINWAIT - bytes are copied into the txBuff and this method
00255       *                            will spin (lock up the processor) until all bytes
00256       *                            have been sent.
00257       *
00258       *            SYNC_SLEEP - bytes are copied into the txBuff and the fiber sleeps
00259       *                         until all bytes have been sent. This allows other fibers
00260       *                         to continue execution.
00261       *
00262       *         Defaults to SYNC_SLEEP.
00263       *
00264       * @return the number of bytes written, or MICROBIT_SERIAL_IN_USE if another fiber
00265       *         is using the serial instance for transmission.
00266       */
00267     int send(ManagedString s, MicroBitSerialMode mode = MICROBIT_DEFAULT_SERIAL_MODE);
00268 
00269     /**
00270       * Sends a buffer of known length over the serial line.
00271       *
00272       * @param buffer a pointer to the first character of the buffer
00273       *
00274       * @param len the number of bytes that are safely available to read.
00275       *
00276       * @param mode the selected mode, one of: ASYNC, SYNC_SPINWAIT, SYNC_SLEEP. Each mode
00277       *        gives a different behaviour:
00278       *
00279       *            ASYNC - bytes are copied into the txBuff and returns immediately.
00280       *
00281       *            SYNC_SPINWAIT - bytes are copied into the txBuff and this method
00282       *                            will spin (lock up the processor) until all bytes
00283       *                            have been sent.
00284       *
00285       *            SYNC_SLEEP - bytes are copied into the txBuff and the fiber sleeps
00286       *                         until all bytes have been sent. This allows other fibers
00287       *                         to continue execution.
00288       *
00289       *         Defaults to SYNC_SLEEP.
00290       *
00291       * @return the number of bytes written, or MICROBIT_SERIAL_IN_USE if another fiber
00292       *         is using the serial instance for transmission.
00293       */
00294     int send(uint8_t *buffer, int bufferLen, MicroBitSerialMode mode = MICROBIT_DEFAULT_SERIAL_MODE);
00295 
00296     /**
00297       * Reads a single character from the rxBuff
00298       *
00299       * @param mode the selected mode, one of: ASYNC, SYNC_SPINWAIT, SYNC_SLEEP. Each mode
00300       *        gives a different behaviour:
00301       *
00302       *            ASYNC - A character is read from the rxBuff if available, if there
00303       *                    are no characters to be read, a value of MICROBIT_NO_DATA is returned immediately.
00304       *
00305       *            SYNC_SPINWAIT - A character is read from the rxBuff if available, if there
00306       *                            are no characters to be read, this method will spin
00307       *                            (lock up the processor) until a character is available.
00308       *
00309       *            SYNC_SLEEP - A character is read from the rxBuff if available, if there
00310       *                         are no characters to be read, the calling fiber sleeps
00311       *                         until there is a character available.
00312       *
00313       *         Defaults to SYNC_SLEEP.
00314       *
00315       * @return a character, MICROBIT_SERIAL_IN_USE if another fiber is using the serial instance for reception,
00316       *         MICROBIT_NO_RESOURCES if buffer allocation did not complete successfully, or MICROBIT_NO_DATA if
00317       *         the rx buffer is empty and the mode given is ASYNC.
00318       */
00319     int read(MicroBitSerialMode mode = MICROBIT_DEFAULT_SERIAL_MODE);
00320 
00321     /**
00322       * Reads multiple characters from the rxBuff and returns them as a ManagedString
00323       *
00324       * @param size the number of characters to read.
00325       *
00326       * @param mode the selected mode, one of: ASYNC, SYNC_SPINWAIT, SYNC_SLEEP. Each mode
00327       *        gives a different behaviour:
00328       *
00329       *            ASYNC - If the desired number of characters are available, this will return
00330       *                    a ManagedString with the expected size. Otherwise, it will read however
00331       *                    many characters there are available.
00332       *
00333       *            SYNC_SPINWAIT - If the desired number of characters are available, this will return
00334       *                            a ManagedString with the expected size. Otherwise, this method will spin
00335       *                            (lock up the processor) until the desired number of characters have been read.
00336       *
00337       *            SYNC_SLEEP - If the desired number of characters are available, this will return
00338       *                         a ManagedString with the expected size. Otherwise, the calling fiber sleeps
00339       *                         until the desired number of characters have been read.
00340       *
00341       *         Defaults to SYNC_SLEEP.
00342       *
00343       * @return A ManagedString, or an empty ManagedString if an error was encountered during the read.
00344       */
00345     ManagedString read(int size, MicroBitSerialMode mode = MICROBIT_DEFAULT_SERIAL_MODE);
00346 
00347     /**
00348       * Reads multiple characters from the rxBuff and fills a user buffer.
00349       *
00350       * @param buffer a pointer to a user allocated buffer.
00351       *
00352       * @param bufferLen the amount of data that can be safely stored
00353       *
00354       * @param mode the selected mode, one of: ASYNC, SYNC_SPINWAIT, SYNC_SLEEP. Each mode
00355       *        gives a different behaviour:
00356       *
00357       *            ASYNC - If the desired number of characters are available, this will fill
00358       *                    the given buffer. Otherwise, it will fill the buffer with however
00359       *                    many characters there are available.
00360       *
00361       *            SYNC_SPINWAIT - If the desired number of characters are available, this will fill
00362       *                            the given buffer. Otherwise, this method will spin (lock up the processor)
00363       *                            and fill the buffer until the desired number of characters have been read.
00364       *
00365       *            SYNC_SLEEP - If the desired number of characters are available, this will fill
00366       *                         the given buffer. Otherwise, the calling fiber sleeps
00367       *                         until the desired number of characters have been read.
00368       *
00369       *         Defaults to SYNC_SLEEP.
00370       *
00371       * @return the number of characters read, or MICROBIT_SERIAL_IN_USE if another fiber
00372       *         is using the instance for receiving.
00373       */
00374     int read(uint8_t *buffer, int bufferLen, MicroBitSerialMode mode = MICROBIT_DEFAULT_SERIAL_MODE);
00375 
00376     /**
00377       * Reads until one of the delimeters matches a character in the rxBuff
00378       *
00379       * @param delimeters a ManagedString containing a sequence of delimeter characters e.g. ManagedString("\r\n")
00380       *
00381       * @param mode the selected mode, one of: ASYNC, SYNC_SPINWAIT, SYNC_SLEEP. Each mode
00382       *        gives a different behaviour:
00383       *
00384       *            ASYNC - If one of the delimeters matches a character already in the rxBuff
00385       *                    this method will return a ManagedString up to the delimeter.
00386       *                    Otherwise, it will return an Empty ManagedString.
00387       *
00388       *            SYNC_SPINWAIT - If one of the delimeters matches a character already in the rxBuff
00389       *                            this method will return a ManagedString up to the delimeter.
00390       *                            Otherwise, this method will spin (lock up the processor) until a
00391       *                            received character matches one of the delimeters.
00392       *
00393       *            SYNC_SLEEP - If one of the delimeters matches a character already in the rxBuff
00394       *                         this method will return a ManagedString up to the delimeter.
00395       *                         Otherwise, the calling fiber sleeps until a character matching one
00396       *                         of the delimeters is seen.
00397       *
00398       *         Defaults to SYNC_SLEEP.
00399       *
00400       * @return A ManagedString containing the characters up to a delimeter, or an Empty ManagedString,
00401       *         if another fiber is currently using this instance for reception.
00402       *
00403       * @note delimeters are matched on a per byte basis.
00404       */
00405     ManagedString readUntil(ManagedString delimeters, MicroBitSerialMode mode = MICROBIT_DEFAULT_SERIAL_MODE);
00406 
00407     /**
00408       * A wrapper around the inherited method "baud" so we can trap the baud rate
00409       * as it changes and restore it if redirect() is called.
00410       *
00411       * @param baudrate the new baudrate. See:
00412       *         - https://github.com/mbedmicro/mbed/blob/master/libraries/mbed/targets/hal/TARGET_NORDIC/TARGET_MCU_NRF51822/serial_api.c
00413       *        for permitted baud rates.
00414       *
00415       * @return MICROBIT_INVALID_PARAMETER if baud rate is less than 0, otherwise MICROBIT_OK.
00416       *
00417       * @note the underlying implementation chooses the first allowable rate at or above that requested.
00418       */
00419     void baud(int baudrate);
00420 
00421     /**
00422       * A way of dynamically configuring the serial instance to use pins other than USBTX and USBRX.
00423       *
00424       * @param tx the new transmission pin.
00425       *
00426       * @param rx the new reception pin.
00427       *
00428       * @return MICROBIT_SERIAL_IN_USE if another fiber is currently transmitting or receiving, otherwise MICROBIT_OK.
00429       */
00430     int redirect(PinName tx, PinName rx);
00431 
00432     /**
00433       * Configures an event to be fired after "len" characters.
00434       *
00435       * @param len the number of characters to wait before triggering the event.
00436       *
00437       * @param mode the selected mode, one of: ASYNC, SYNC_SPINWAIT, SYNC_SLEEP. Each mode
00438       *        gives a different behaviour:
00439       *
00440       *            ASYNC - Will configure the event and return immediately.
00441       *
00442       *            SYNC_SPINWAIT - will return MICROBIT_INVALID_PARAMETER
00443       *
00444       *            SYNC_SLEEP - Will configure the event and block the current fiber until the
00445       *                         event is received.
00446       *
00447       * @return MICROBIT_INVALID_PARAMETER if the mode given is SYNC_SPINWAIT, otherwise MICROBIT_OK.
00448       */
00449     int eventAfter(int len, MicroBitSerialMode mode = ASYNC);
00450 
00451     /**
00452       * Configures an event to be fired on a match with one of the delimeters.
00453       *
00454       * @param delimeters the characters to match received characters against e.g. ManagedString("\r\n")
00455       *
00456       * @param mode the selected mode, one of: ASYNC, SYNC_SPINWAIT, SYNC_SLEEP. Each mode
00457       *        gives a different behaviour:
00458       *
00459       *            ASYNC - Will configure the event and return immediately.
00460       *
00461       *            SYNC_SPINWAIT - will return MICROBIT_INVALID_PARAMETER
00462       *
00463       *            SYNC_SLEEP - Will configure the event and block the current fiber until the
00464       *                         event is received.
00465       *
00466       * @return MICROBIT_INVALID_PARAMETER if the mode given is SYNC_SPINWAIT, otherwise MICROBIT_OK.
00467       *
00468       * @note delimeters are matched on a per byte basis.
00469       */
00470     int eventOn(ManagedString delimeters, MicroBitSerialMode mode = ASYNC);
00471 
00472     /**
00473       * Determines whether there is any data waiting in our Rx buffer.
00474       *
00475       * @return 1 if we have space, 0 if we do not.
00476       *
00477       * @note We do not wrap the super's readable() method as we don't want to
00478       *       interfere with communities that use manual calls to serial.readable().
00479       */
00480     int isReadable();
00481 
00482     /**
00483       * Determines if we have space in our txBuff.
00484       *
00485       * @return 1 if we have space, 0 if we do not.
00486       *
00487       * @note We do not wrap the super's writeable() method as we don't want to
00488       *       interfere with communities that use manual calls to serial.writeable().
00489       */
00490     int isWriteable();
00491 
00492     /**
00493       * Reconfigures the size of our rxBuff
00494       *
00495       * @param size the new size for our rxBuff
00496       *
00497       * @return MICROBIT_SERIAL_IN_USE if another fiber is currently using this instance
00498       *         for reception, otherwise MICROBIT_OK.
00499       */
00500     int setRxBufferSize(uint8_t size);
00501 
00502     /**
00503       * Reconfigures the size of our txBuff
00504       *
00505       * @param size the new size for our txBuff
00506       *
00507       * @return MICROBIT_SERIAL_IN_USE if another fiber is currently using this instance
00508       *         for transmission, otherwise MICROBIT_OK.
00509       */
00510     int setTxBufferSize(uint8_t size);
00511 
00512     /**
00513       * The size of our rx buffer in bytes.
00514       *
00515       * @return the current size of rxBuff in bytes
00516       */
00517     int getRxBufferSize();
00518 
00519     /**
00520       * The size of our tx buffer in bytes.
00521       *
00522       * @return the current size of txBuff in bytes
00523       */
00524     int getTxBufferSize();
00525 
00526     /**
00527       * Sets the tail to match the head of our circular buffer for reception,
00528       * effectively clearing the reception buffer.
00529       *
00530       * @return MICROBIT_SERIAL_IN_USE if another fiber is currently using this instance
00531       *         for reception, otherwise MICROBIT_OK.
00532       */
00533     int clearRxBuffer();
00534 
00535     /**
00536       * Sets the tail to match the head of our circular buffer for transmission,
00537       * effectively clearing the transmission buffer.
00538       *
00539       * @return MICROBIT_SERIAL_IN_USE if another fiber is currently using this instance
00540       *         for transmission, otherwise MICROBIT_OK.
00541       */
00542     int clearTxBuffer();
00543 
00544     /**
00545       * The number of bytes currently stored in our rx buffer waiting to be digested,
00546       * by the user.
00547       *
00548       * @return The currently buffered number of bytes in our rxBuff.
00549       */
00550     int rxBufferedSize();
00551 
00552     /**
00553       * The number of bytes currently stored in our tx buffer waiting to be transmitted
00554       * by the hardware.
00555       *
00556       * @return The currently buffered number of bytes in our txBuff.
00557       */
00558     int txBufferedSize();
00559 
00560     /**
00561       * Determines if the serial bus is currently in use by another fiber for reception.
00562       *
00563       * @return The state of our mutex lock for reception.
00564       *
00565       * @note Only one fiber can call read at a time
00566       */
00567     int rxInUse();
00568 
00569     /**
00570       * Determines if the serial bus is currently in use by another fiber for transmission.
00571       *
00572       * @return The state of our mutex lock for transmition.
00573       *
00574       * @note Only one fiber can call send at a time
00575       */
00576     int txInUse();
00577 
00578     /**
00579       * Detaches a previously configured interrupt
00580       *
00581       * @param interruptType one of Serial::RxIrq or Serial::TxIrq
00582       */
00583     void detach(Serial::IrqType interuptType);
00584 
00585 };
00586 
00587 #endif