micro:bit - 이벤트

OS/micro:bit 2018.02.24 11:32 Posted by 파란크리스마스

MicroBitRadioEvent.h

    /**
      * Associates the given event with the radio channel.
      *
      * Once registered, all events matching the given registration sent to this micro:bit's
      * default EventModel will be automatically retransmitted on the radio.
      *
      * @param id The id of the event to register.
      *
      * @param value the value of the event to register.
      *
      * @return MICROBIT_OK on success, or MICROBIT_NO_RESOURCES if no default EventModel is available.
      *
      * @note The wildcards MICROBIT_ID_ANY and MICROBIT_EVT_ANY can also be in place of the
      *       id and value fields.
      */
    int listen(uint16_t id, uint16_t value);

    /**
      * Associates the given event with the radio channel.
      *
      * Once registered, all events matching the given registration sent to the given
      * EventModel will be automatically retransmitted on the radio.
      *
      * @param id The id of the events to register.
      *
      * @param value the value of the event to register.
      *
      * @param eventBus The EventModel to listen for events on.
      *
      * @return MICROBIT_OK on success.
      *
      * @note The wildcards MICROBIT_ID_ANY and MICROBIT_EVT_ANY can also be in place of the
      *       id and value fields.
      */
    int listen(uint16_t id, uint16_t value, EventModel &eventBus);

MicroBitMessageBus.cpp

/**
  * Queues the given event to be sent to all registered recipients.
  *
  * @param evt The event to send.
  *
  * @code
  * MicroBitMessageBus bus;
  *
  * // Creates and sends the MicroBitEvent using bus.
  * MicrobitEvent evt(MICROBIT_ID_BUTTON_A, MICROBIT_BUTTON_EVT_CLICK);
  *
  * // Creates the MicrobitEvent, but delays the sending of that event.
  * MicrobitEvent evt1(MICROBIT_ID_BUTTON_A, MICROBIT_BUTTON_EVT_CLICK, CREATE_ONLY);
  *
  * bus.send(evt1);
  *
  * // This has the same effect!
  * evt1.fire()
  * @endcode
  */
int MicroBitMessageBus::send(MicroBitEvent evt)
{
    // We simply queue processing of the event until we're scheduled in normal thread context.
    // We do this to avoid the possibility of executing event handler code in IRQ context, which may bring
    // hidden race conditions to kids code. Queuing all events ensures causal ordering (total ordering in fact).
    this->queueEvent(evt);
    return MICROBIT_OK;
}

MicroBitFiber.cpp

/**
  * Blocks the calling thread until the specified event is raised.
  * The calling thread will be immediateley descheduled, and placed onto a
  * wait queue until the requested event is received.
  *
  * @param id The ID field of the event to listen for (e.g. MICROBIT_ID_BUTTON_A)
  *
  * @param value The value of the event to listen for (e.g. MICROBIT_BUTTON_EVT_CLICK)
  *
  * @return MICROBIT_OK, or MICROBIT_NOT_SUPPORTED if the fiber scheduler is not running, or associated with an EventModel.
  *
  * @code
  * fiber_wait_for_event(MICROBIT_ID_BUTTON_A, MICROBIT_BUTTON_EVT_CLICK);
  * @endcode
  *
  * @note the fiber will not be be made runnable until after the event is raised, but there
  * are no guarantees precisely when the fiber will next be scheduled.
  */
int fiber_wait_for_event(uint16_t id, uint16_t value)
{
    int ret = fiber_wake_on_event(id, value);

    if(ret == MICROBIT_OK)
        schedule();

	return ret;
}

/**
  * Configures the fiber context for the current fiber to block on an event ID
  * and value, but does not deschedule the fiber.
  *
  * @param id The ID field of the event to listen for (e.g. MICROBIT_ID_BUTTON_A)
  *
  * @param value The value of the event to listen for (e.g. MICROBIT_BUTTON_EVT_CLICK)
  *
  * @return MICROBIT_OK, or MICROBIT_NOT_SUPPORTED if the fiber scheduler is not running, or associated with an EventModel.
  *
  * @code
  * fiber_wake_on_event(MICROBIT_ID_BUTTON_A, MICROBIT_BUTTON_EVT_CLICK);
  *
  * //perform some time critical operation.
  *
  * //deschedule the current fiber manually, waiting for the previously configured event.
  * schedule();
  * @endcode
  */
int fiber_wake_on_event(uint16_t id, uint16_t value)
{
    Fiber *f = currentFiber;

	if (messageBus == NULL || !fiber_scheduler_running())
		return MICROBIT_NOT_SUPPORTED;

    // Sleep is a blocking call, so if we're in a fork on block context,
    // it's time to spawn a new fiber...
    if (currentFiber->flags & MICROBIT_FIBER_FLAG_FOB)
    {
        // Allocate a TCB from the new fiber. This will come from the tread pool if availiable,
        // else a new one will be allocated on the heap.
        forkedFiber = getFiberContext();

        // If we're out of memory, there's nothing we can do.
        // keep running in the context of the current thread as a best effort.
        if (forkedFiber != NULL)
        {
            f = forkedFiber;
            dequeue_fiber(f);
            queue_fiber(f, &runQueue);
            schedule();
        }
    }

    // Encode the event data in the context field. It's handy having a 32 bit core. :-)
    f->context = value << 16 | id;

    // Remove ourselves from the run queue
    dequeue_fiber(f);

    // Add ourselves to the sleep queue. We maintain strict ordering here to reduce lookup times.
    queue_fiber(f, &waitQueue);

    // Register to receive this event, so we can wake up the fiber when it happens.
    // Special case for the notify channel, as we always stay registered for that.
    if (id != MICROBIT_ID_NOTIFY && id != MICROBIT_ID_NOTIFY_ONE)
        messageBus->listen(id, value, scheduler_event, MESSAGE_BUS_LISTENER_IMMEDIATE);

    return MICROBIT_OK;
}

이벤트 메소드 구현

void onButtonA(MicroBitEvent e)
{
  uBit.display.scroll("A");
}

리스너 등록

  // listen for user button interactions
  uBit.messageBus.listen(MICROBIT_ID_BUTTON_A, MICROBIT_BUTTON_EVT_CLICK, onButtonA);
  uBit.messageBus.listen(MICROBIT_ID_BUTTON_B, MICROBIT_BUTTON_EVT_CLICK, onButtonB);
  uBit.messageBus.listen(MICROBIT_ID_BUTTON_AB, MICROBIT_BUTTON_EVT_CLICK, onButtonAB);


 

티스토리 툴바