/** * Reads characters until a character matches one of the given delimeters * * @param delimeters the number of characters to match against * @param mode the selected mode, one of: ASYNC, SYNC_SPINWAIT, SYNC_SLEEP. Each mode * gives a different behaviour: * * ASYNC - Will attempt read the immediate buffer, and look for a match. * If there isn't, an empty ManagedString will be returned. * * SYNC_SPINWAIT - will return MICROBIT_INVALID_PARAMETER * * SYNC_SLEEP - Will first of all consider the characters in the immediate buffer, * if a match is not found, it will block on an event, fired when a * character is matched. * * @return an empty ManagedString on error, or a ManagedString containing characters */ ManagedString MicroBitUARTService::readUntil(ManagedString delimeters, MicroBitSerialMode mode) { if(mode == SYNC_SPINWAIT) return MICROBIT_INVALID_PARAMETER; int localTail = rxBufferTail; int preservedTail = rxBufferTail; int foundIndex = -1; //ASYNC mode just iterates through our stored characters checking for any matches. while(localTail != rxBufferHead && foundIndex == -1) { //we use localTail to prevent modification of the actual tail. char c = rxBuffer[localTail]; for(int delimeterIterator = 0; delimeterIterator < delimeters.length(); delimeterIterator++) if(delimeters.charAt(delimeterIterator) == c) foundIndex = localTail; localTail = (localTail + 1) % rxBufferSize; } //if our mode is SYNC_SLEEP, we set up an event to be fired when we see a //matching character. if(mode == SYNC_SLEEP && foundIndex == -1) { eventOn(delimeters, mode); foundIndex = rxBufferHead - 1; this->delimeters = ManagedString(); } if(foundIndex >= 0) { //calculate our local buffer size int localBuffSize = (preservedTail > foundIndex) ? (rxBufferSize - preservedTail) + foundIndex : foundIndex - preservedTail; uint8_t localBuff[localBuffSize + 1]; memclr(&localBuff, localBuffSize + 1); circularCopy(rxBuffer, rxBufferSize, localBuff, preservedTail, foundIndex); //plus one for the character we listened for... rxBufferTail = (rxBufferTail + localBuffSize + 1) % rxBufferSize; return ManagedString((char *)localBuff, localBuffSize); } return ManagedString(); }
/** * Reads a number of characters from the rxBuffer and returns them as a ManagedString * * @param len the number of characters to read. * @param mode the selected mode, one of: ASYNC, SYNC_SPINWAIT, SYNC_SLEEP. Each mode * gives a different behaviour: * * ASYNC - Will attempt to read all available characters, and return immediately * until the buffer limit is reached * * SYNC_SPINWAIT - will return MICROBIT_INVALID_PARAMETER * * SYNC_SLEEP - Will first of all determine whether the given number of characters * are available in our buffer, if not, it will set an event and sleep * until the number of characters are avaialable. * * @return an empty ManagedString on error, or a ManagedString containing characters */ ManagedString MicroBitUARTService::read(int len, MicroBitSerialMode mode) { uint8_t buf[len + 1]; memclr(&buf, len + 1); int ret = read(buf, len, mode); if(ret < 1) return ManagedString(); return ManagedString((const char *)buf); }
/** * Reads multiple characters from the rxBuff and returns them as a ManagedString * * @param size the number of characters to read. * * @param mode the selected mode, one of: ASYNC, SYNC_SPINWAIT, SYNC_SLEEP. Each mode * gives a different behaviour: * * ASYNC - If the desired number of characters are available, this will return * a ManagedString with the expected size. Otherwise, it will read however * many characters there are available. * * SYNC_SPINWAIT - If the desired number of characters are available, this will return * a ManagedString with the expected size. Otherwise, this method will spin * (lock up the processor) until the desired number of characters have been read. * * SYNC_SLEEP - If the desired number of characters are available, this will return * a ManagedString with the expected size. Otherwise, the calling fiber sleeps * until the desired number of characters have been read. * * Defaults to SYNC_SLEEP. * * @return A ManagedString, or an empty ManagedString if an error was encountered during the read. */ ManagedString MicroBitSerial::read(int size, MicroBitSerialMode mode) { uint8_t buff[size + 1]; memclr(&buff, size + 1); int returnedSize = read((uint8_t *)buff, size, mode); if(returnedSize <= 0) return ManagedString(); return ManagedString((char *)buff, returnedSize); }
/** * Set the value that is used to offset the raw silicon temperature. * * @param offset the offset for the silicon temperature * * @return MICROBIT_OK on success */ int MicroBitThermometer::setOffset(int offset) { if(this->storage != NULL) this->storage->put(ManagedString("tempCal"), (uint8_t *)&offset, sizeof(int)); this->offset = offset; return MICROBIT_OK; }
/** * Constructor. * Create new MicroBitThermometer that gives an indication of the current temperature. * * @param _storage an instance of MicroBitStorage used to persist temperature offset data * * @param id the unique EventModel id of this component. Defaults to MICROBIT_ID_THERMOMETER. * * @code * MicroBitStorage storage; * MicroBitThermometer thermometer(storage); * @endcode */ MicroBitThermometer::MicroBitThermometer(MicroBitStorage& _storage, uint16_t id) : storage(&_storage) { this->id = id; this->samplePeriod = MICROBIT_THERMOMETER_PERIOD; this->sampleTime = 0; this->offset = 0; KeyValuePair *tempCalibration = storage->get(ManagedString("tempCal")); if(tempCalibration != NULL) { memcpy(&offset, tempCalibration->value, sizeof(int16_t)); delete tempCalibration; } }
/** * Converts the bitmap to a csv ManagedString. * * @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.printString(i.toString()); // "0,1,0,1,0,0,0,0,0,0\n..." * @endcode */ ManagedString MicroBitImage::toString() { //width including commans and \n * height int stringSize = getSize() * 2; //plus one for string terminator char parseBuffer[stringSize + 1]; parseBuffer[stringSize] = '\0'; uint8_t *bitmapPtr = getBitmap(); int parseIndex = 0; int widthCount = 0; while (parseIndex < stringSize) { if(*bitmapPtr) parseBuffer[parseIndex] = '1'; else parseBuffer[parseIndex] = '0'; parseIndex++; if(widthCount == getWidth()-1) { parseBuffer[parseIndex] = '\n'; widthCount = 0; } else { parseBuffer[parseIndex] = ','; widthCount++; } parseIndex++; bitmapPtr++; } return ManagedString(parseBuffer); }
//% blockId="control_device_name" block="device name" weight=10 blockGap=8 //% advanced=true StringData* deviceName() { return ManagedString(microbit_friendly_name()).leakData(); }
/** * Reads until one of the delimeters matches a character in the rxBuff * * @param delimeters a ManagedString containing a sequence of delimeter characters e.g. ManagedString("\r\n") * * @param mode the selected mode, one of: ASYNC, SYNC_SPINWAIT, SYNC_SLEEP. Each mode * gives a different behaviour: * * ASYNC - If one of the delimeters matches a character already in the rxBuff * this method will return a ManagedString up to the delimeter. * Otherwise, it will return an Empty ManagedString. * * SYNC_SPINWAIT - If one of the delimeters matches a character already in the rxBuff * this method will return a ManagedString up to the delimeter. * Otherwise, this method will spin (lock up the processor) until a * received character matches one of the delimeters. * * SYNC_SLEEP - If one of the delimeters matches a character already in the rxBuff * this method will return a ManagedString up to the delimeter. * Otherwise, the calling fiber sleeps until a character matching one * of the delimeters is seen. * * Defaults to SYNC_SLEEP. * * @return A ManagedString containing the characters up to a delimeter, or an Empty ManagedString, * if another fiber is currently using this instance for reception. * * @note delimeters are matched on a per byte basis. */ ManagedString MicroBitSerial::readUntil(ManagedString delimeters, MicroBitSerialMode mode) { if(rxInUse()) return ManagedString(); //lazy initialisation of our rx buffer if(!(status & MICROBIT_SERIAL_RX_BUFF_INIT)) { int result = initialiseRx(); if(result != MICROBIT_OK) return result; } lockRx(); int localTail = rxBuffTail; int preservedTail = rxBuffTail; int foundIndex = -1; //ASYNC mode just iterates through our stored characters checking for any matches. while(localTail != rxBuffHead && foundIndex == -1) { //we use localTail to prevent modification of the actual tail. char c = rxBuff[localTail]; for(int delimeterIterator = 0; delimeterIterator < delimeters.length(); delimeterIterator++) if(delimeters.charAt(delimeterIterator) == c) foundIndex = localTail; localTail = (localTail + 1) % rxBuffSize; } //if our mode is SYNC_SPINWAIT and we didn't see any matching characters in our buffer //spin until we find a match! if(mode == SYNC_SPINWAIT) { while(foundIndex == -1) { while(localTail == rxBuffHead); char c = rxBuff[localTail]; for(int delimeterIterator = 0; delimeterIterator < delimeters.length(); delimeterIterator++) if(delimeters.charAt(delimeterIterator) == c) foundIndex = localTail; localTail = (localTail + 1) % rxBuffSize; } } //if our mode is SYNC_SLEEP, we set up an event to be fired when we see a //matching character. if(mode == SYNC_SLEEP && foundIndex == -1) { eventOn(delimeters, mode); foundIndex = rxBuffHead - 1; this->delimeters = ManagedString(); } if(foundIndex >= 0) { //calculate our local buffer size int localBuffSize = (preservedTail > foundIndex) ? (rxBuffSize - preservedTail) + foundIndex : foundIndex - preservedTail; uint8_t localBuff[localBuffSize + 1]; memclr(&localBuff, localBuffSize + 1); circularCopy(rxBuff, rxBuffSize, localBuff, preservedTail, foundIndex); //plus one for the character we listened for... rxBuffTail = (rxBuffTail + localBuffSize + 1) % rxBuffSize; unlockRx(); return ManagedString((char *)localBuff, localBuffSize); } unlockRx(); return ManagedString(); }