/** * A way of dynamically configuring the serial instance to use pins other than USBTX and USBRX. * * @param tx the new transmission pin. * * @param rx the new reception pin. * * @return MICROBIT_SERIAL_IN_USE if another fiber is currently transmitting or receiving, otherwise MICROBIT_OK. */ int MicroBitSerial::redirect(PinName tx, PinName rx) { if(txInUse() || rxInUse()) return MICROBIT_SERIAL_IN_USE; lockTx(); lockRx(); if(txBufferedSize() > 0) detach(Serial::TxIrq); detach(Serial::RxIrq); serial_free(&_serial); serial_init(&_serial, tx, rx); attach(this, &MicroBitSerial::dataReceived, Serial::RxIrq); if(txBufferedSize() > 0) attach(this, &MicroBitSerial::dataWritten, Serial::TxIrq); this->baud(this->baudrate); unlockRx(); unlockTx(); return MICROBIT_OK; }
/** * An internal method that either spin waits if mode is set to SYNC_SPINWAIT * or puts the fiber to sleep if the mode is set to SYNC_SLEEP * * @param mode the selected mode, one of: ASYNC, SYNC_SPINWAIT, SYNC_SLEEP */ void MicroBitSerial::send(MicroBitSerialMode mode) { if(mode == SYNC_SPINWAIT) while(txBufferedSize() > 0); if(mode == SYNC_SLEEP) fiber_sleep(0); }
/** * 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. * @param mode the selected mode, one of: ASYNC, SYNC_SPINWAIT, SYNC_SLEEP. Each mode * gives a different behaviour: * * ASYNC - Will copy as many characters as it can into the buffer for transmission, * and return control to the user. * * SYNC_SPINWAIT - will return MICROBIT_INVALID_PARAMETER * * SYNC_SLEEP - Will perform a cooperative blocking wait until all * given characters have been received by the connected * device. * * @return the number of characters written, or MICROBIT_NOT_SUPPORTED if there is * no connected device, or the connected device has not enabled indications. */ int MicroBitUARTService::send(const uint8_t *buf, int length, MicroBitSerialMode mode) { if(length < 1 || mode == SYNC_SPINWAIT) return MICROBIT_INVALID_PARAMETER; bool updatesEnabled = false; ble.gattServer().areUpdatesEnabled(*txCharacteristic, &updatesEnabled); if(!ble.getGapState().connected && !updatesEnabled) return MICROBIT_NOT_SUPPORTED; int bytesWritten = 0; while(bytesWritten < length && ble.getGapState().connected && updatesEnabled) { for(int bufferIterator = bytesWritten; bufferIterator < length; bufferIterator++) { int nextHead = (txBufferHead + 1) % txBufferSize; if(nextHead != txBufferTail) { txBuffer[txBufferHead] = buf[bufferIterator]; txBufferHead = nextHead; bytesWritten++; } } int size = txBufferedSize(); uint8_t temp[size]; memclr(&temp, size); circularCopy(txBuffer, txBufferSize, temp, txBufferTail, txBufferHead); if(mode == SYNC_SLEEP) fiber_wake_on_event(MICROBIT_ID_NOTIFY, MICROBIT_UART_S_EVT_TX_EMPTY); ble.gattServer().write(txCharacteristic->getValueAttribute().getHandle(), temp, size); if(mode == SYNC_SLEEP) schedule(); else break; ble.gattServer().areUpdatesEnabled(*txCharacteristic, &updatesEnabled); } return bytesWritten; }