예제 #1
0
/**
  * Broadcasts an event onto the defult EventModel indicating that the
  * current animation has completed.
  */
void MicroBitDisplay::sendAnimationCompleteEvent()
{
    // Signal that we've completed an animation.
    MicroBitEvent(id,MICROBIT_DISPLAY_EVT_ANIMATION_COMPLETE);

    // Wake up a fiber that was blocked on the animation (if any).
    MicroBitEvent(MICROBIT_ID_NOTIFY_ONE, MICROBIT_DISPLAY_EVT_FREE);
}
/**
  * Protocol handler callback. This is called when the radio receives a packet marked as a datagram.
  *
  * This function process this packet, and queues it for user reception.
  */
void MicroBitRadioDatagram::packetReceived()
{
    FrameBuffer *packet = radio.recv();
    int queueDepth = 0;

    // We add to the tail of the queue to preserve causal ordering.
    packet->next = NULL;

    if (rxQueue == NULL)
    {
        rxQueue = packet;
    }
    else
    {
        FrameBuffer *p = rxQueue;
        while (p->next != NULL)
        {
            p = p->next;
            queueDepth++;
        }

        if (queueDepth >= MICROBIT_RADIO_MAXIMUM_RX_BUFFERS)
        {
            delete packet;
            return;
        }

        p->next = packet;
    }

    MicroBitEvent(MICROBIT_ID_RADIO, MICROBIT_RADIO_EVT_DATAGRAM);
}
예제 #3
0
void setMode() {
    if (ticker)
    {
        ticker->detach();
        ticker = NULL;
    }
    uBit.messageBus.ignore(MICROBIT_ID_GESTURE, MICROBIT_EVT_ANY, onGesture);

    switch(currentMode) {
        case ALWAYS_ON:
            uBit.display.print(lshift);
            uBit.display.setBrightness(255);
            break;
        case CYCLING:
            uBit.display.print(lshift);
            uBit.display.setBrightness(10);
            ticker = new Ticker();
            ticker->attach_us(changeBrightness, 250 * 1000);
            break;
        case TILT:
            uBit.display.setBrightness(255);
            uBit.messageBus.listen(MICROBIT_ID_GESTURE, MICROBIT_EVT_ANY, onGesture);
            onGesture(MicroBitEvent(MICROBIT_ID_GESTURE, uBit.accelerometer.getGesture()));
            break;
    }
}
예제 #4
0
/**
  * A background, low priority callback that is triggered whenever the processor is idle.
  * Here, we empty our queue of received packets, and pass them onto higher level protocol handlers.
  */
void MicroBitRadio::idleTick()
{
    // Walk the list of packets and process each one.
    while(rxQueue)
    {
        FrameBuffer *p = rxQueue;

        switch (p->protocol)
        {
        case MICROBIT_RADIO_PROTOCOL_DATAGRAM:
            datagram.packetReceived();
            break;

        case MICROBIT_RADIO_PROTOCOL_EVENTBUS:
            event.packetReceived();
            break;

        default:
            MicroBitEvent(MICROBIT_ID_RADIO_DATA_READY, p->protocol);
        }

        // If the packet was processed, it will have been recv'd, and taken from the queue.
        // If this was a packet for an unknown protocol, it will still be there, so simply free it.
        if (p == rxQueue)
        {
            recv();
            delete p;
        }
    }
}
/**
  * A callback function for whenever a Bluetooth device consumes our TX Buffer
  */
void on_confirmation(uint16_t handle)
{
    if(handle == txCharacteristic->getValueAttribute().getHandle())
    {
        txBufferTail = txBufferHead;
        MicroBitEvent(MICROBIT_ID_NOTIFY, MICROBIT_UART_S_EVT_TX_EMPTY);
    }
}
예제 #6
0
/**
  * Resets the current given animation.
  */
void MicroBitDisplay::stopAnimation()
{
    // Reset any ongoing animation.
    if (animationMode != ANIMATION_MODE_NONE)
    {
        animationMode = ANIMATION_MODE_NONE;

        // Indicate that we've completed an animation.
        MicroBitEvent(id,MICROBIT_DISPLAY_EVT_ANIMATION_COMPLETE);

        // Wake up aall fibers that may blocked on the animation (if any).
        MicroBitEvent(MICROBIT_ID_NOTIFY, MICROBIT_DISPLAY_EVT_FREE);
    }

    // Clear the display and setup the animation timers.
    this->image.clear();
}
/**
  * Callback when a BLE GATT disconnect occurs.
  */
static void bleDisconnectionCallback(const Gap::DisconnectionCallbackParams_t *reason)
{
    MicroBitEvent(MICROBIT_ID_BLE,MICROBIT_BLE_EVT_DISCONNECTED);

    storeSystemAttributes(reason->handle);

    if (manager)
	    manager->advertise();
}
예제 #8
0
/**
  * An internal interrupt callback for MicroBitSerial configured for when a
  * character is received.
  *
  * Each time a character is received fill our circular buffer!
  */
void MicroBitSerial::dataReceived()
{
    if(!(status & MICROBIT_SERIAL_RX_BUFF_INIT))
        return;

    //get the received character
    char c = getc();

    int delimeterOffset = 0;
    int delimLength = this->delimeters.length();

    //iterate through our delimeters (if any) to see if there is a match
    while(delimeterOffset < delimLength)
    {
        //fire an event if there is to block any waiting fibers
        if(this->delimeters.charAt(delimeterOffset) == c)
            MicroBitEvent(MICROBIT_ID_SERIAL, MICROBIT_SERIAL_EVT_DELIM_MATCH);

        delimeterOffset++;
    }

    uint16_t newHead = (rxBuffHead + 1) % rxBuffSize;

    //look ahead to our newHead value to see if we are about to collide with the tail
    if(newHead != rxBuffTail)
    {
        //if we are not, store the character, and update our actual head.
        this->rxBuff[rxBuffHead] = c;
        rxBuffHead = newHead;

        //if we have any fibers waiting for a specific number of characters, unblock them
        if(rxBuffHeadMatch >= 0)
            if(rxBuffHead == rxBuffHeadMatch)
            {
                rxBuffHeadMatch = -1;
                MicroBitEvent(MICROBIT_ID_SERIAL, MICROBIT_SERIAL_EVT_HEAD_MATCH);
            }
    }
    else
        //otherwise, our buffer is full, send an event to the user...
        MicroBitEvent(MICROBIT_ID_SERIAL, MICROBIT_SERIAL_EVT_RX_FULL);
}
/**
  * A callback function for whenever a Bluetooth device writes to our RX characteristic.
  */
void MicroBitUARTService::onDataWritten(const GattWriteCallbackParams *params) {
    if (params->handle == this->rxCharacteristicHandle)
    {
        uint16_t bytesWritten = params->len;

        for(int byteIterator = 0; byteIterator <  bytesWritten; byteIterator++)
        {
            int newHead = (rxBufferHead + 1) % rxBufferSize;

            if(newHead != rxBufferTail)
            {
                char c = params->data[byteIterator];

                int delimeterOffset = 0;
                int delimLength = this->delimeters.length();

                //iterate through our delimeters (if any) to see if there is a match
                while(delimeterOffset < delimLength)
                {
                    //fire an event if there is to block any waiting fibers
                    if(this->delimeters.charAt(delimeterOffset) == c)
                        MicroBitEvent(MICROBIT_ID_BLE_UART, MICROBIT_UART_S_EVT_DELIM_MATCH);

                    delimeterOffset++;
                }

                rxBuffer[rxBufferHead] = c;

                rxBufferHead = newHead;

                if(rxBufferHead == rxBuffHeadMatch)
                {
                    rxBuffHeadMatch = -1;
                    MicroBitEvent(MICROBIT_ID_BLE_UART, MICROBIT_UART_S_EVT_HEAD_MATCH);
                }
            }
            else
                MicroBitEvent(MICROBIT_ID_BLE_UART, MICROBIT_UART_S_EVT_RX_FULL);
        }
    }
}
예제 #10
0
void MicroBitDisplay::renderWithLightSense()
{
    //reset the row counts and bit mask when we have hit the max.
    if(strobeRow == matrixMap.rows + 1)
    {
        MicroBitEvent(id, MICROBIT_DISPLAY_EVT_LIGHT_SENSE);
        strobeRow = 0;
    }
    else
    {
        render();
        this->animationUpdate();

        // Move on to the next row.
        strobeRow++;
    }

}
예제 #11
0
/**
  * An internal interrupt callback for MicroBitSerial.
  *
  * Each time the Serial module's buffer is empty, write a character if we have
  * characters to write.
  */
void MicroBitSerial::dataWritten()
{
    if(txBuffTail == txBuffHead || !(status & MICROBIT_SERIAL_TX_BUFF_INIT))
        return;

    //send our current char
    putc(txBuff[txBuffTail]);

    uint16_t nextTail = (txBuffTail + 1) % txBuffSize;

    //unblock any waiting fibers that are waiting for transmission to finish.
    if(nextTail == txBuffHead)
    {
        MicroBitEvent(MICROBIT_ID_NOTIFY, MICROBIT_SERIAL_EVT_TX_EMPTY);
        detach(Serial::TxIrq);
    }

    //update our tail!
    txBuffTail = nextTail;
}
/**
  * Add the given MicroBitListener to the list of event handlers, unconditionally.
  *
  * @param listener The MicroBitListener to add.
  *
  * @return MICROBIT_OK if the listener is valid, MICROBIT_INVALID_PARAMETER otherwise.
  */
int MicroBitMessageBus::add(MicroBitListener *newListener)
{
	MicroBitListener *l, *p;
    int methodCallback;

	//handler can't be NULL!
	if (newListener == NULL)
		return MICROBIT_INVALID_PARAMETER;

	l = listeners;

	// Firstly, we treat a listener as an idempotent operation. Ensure we don't already have this handler
	// registered in a that will already capture these events. If we do, silently ignore.

    // We always check the ID, VALUE and CB_METHOD fields.
    // If we have a callback to a method, check the cb_method class. Otherwise, the cb function point is sufficient.
    while (l != NULL)
    {
        methodCallback = (newListener->flags & MESSAGE_BUS_LISTENER_METHOD) && (l->flags & MESSAGE_BUS_LISTENER_METHOD);

        if (l->id == newListener->id && l->value == newListener->value && (methodCallback ? *l->cb_method == *newListener->cb_method : l->cb == newListener->cb))
        {
            // We have a perfect match for this event listener already registered.
            // If it's marked for deletion, we simply resurrect the listener, and we're done.
            // Either way, we return an error code, as the *new* listener should be released...
            if(l->flags & MESSAGE_BUS_LISTENER_DELETING)
                l->flags &= ~MESSAGE_BUS_LISTENER_DELETING;

            return MICROBIT_NOT_SUPPORTED;
        }

        l = l->next;
    }

    // We have a valid, new event handler. Add it to the list.
	// if listeners is null - we can automatically add this listener to the list at the beginning...
	if (listeners == NULL)
	{
		listeners = newListener;
        MicroBitEvent(MICROBIT_ID_MESSAGE_BUS_LISTENER, newListener->id);

		return MICROBIT_OK;
	}

	// We maintain an ordered list of listeners.
	// The chain is held stictly in increasing order of ID (first level), then value code (second level).
	// Find the correct point in the chain for this event.
	// Adding a listener is a rare occurance, so we just walk the list...

	p = listeners;
	l = listeners;

	while (l != NULL && l->id < newListener->id)
	{
		p = l;
		l = l->next;
	}

	while (l != NULL && l->id == newListener->id && l->value < newListener->value)
	{
		p = l;
		l = l->next;
	}

	//add at front of list
	if (p == listeners && (newListener->id < p->id || (p->id == newListener->id && p->value > newListener->value)))
	{
		newListener->next = p;

		//this new listener is now the front!
		listeners = newListener;
	}

	//add after p
	else
	{
		newListener->next = p->next;
		p->next = newListener;
	}

    MicroBitEvent(MICROBIT_ID_MESSAGE_BUS_LISTENER, newListener->id);
    return MICROBIT_OK;
}
/**
  * Callback when a BLE connection is established.
  */
static void bleConnectionCallback(const Gap::ConnectionCallbackParams_t*)
{
    MicroBitEvent(MICROBIT_ID_BLE,MICROBIT_BLE_EVT_CONNECTED);
}