/**
  * 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);
}
Пример #3
0
/**
  * 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;
    }
}
Пример #6
0
/**
  * 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);
}
Пример #7
0
 //% blockId="control_device_name" block="device name" weight=10 blockGap=8
 //% advanced=true
 StringData* deviceName() {
     return ManagedString(microbit_friendly_name()).leakData();
 }
Пример #8
0
/**
  * 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();
}