nimphea/nimphea_ui_events

Source   Edit  

UI Event Queue System

This module wraps libDaisy's UI event queue system for handling user input events. The event queue is thread-safe (uses ScopedIrqBlocker) and can be safely accessed from interrupt handlers.

Features:

  • Button press/release events with double-click detection
  • Encoder rotation events with increment tracking
  • Potentiometer/slider movement events
  • Activity tracking (user started/stopped interaction)
  • Thread-safe FIFO queue (256 event capacity)

Wrapped Header: ui/UiEventQueue.h

Example - Basic event processing:

import nimphea_ui_events

var eventQueue = initUiEventQueue()

# In button interrupt handler:
eventQueue.addButtonPressed(0, 1, false)  # button 0, single press

# In main loop:
while not eventQueue.isQueueEmpty():
  var evt = eventQueue.getAndRemoveNextEvent()
  if evt.eventType == EventType.buttonPressed:
    echo "Button ", evt.asButtonPressed.id, " pressed"

Example - Double-click detection:

var evt = eventQueue.getAndRemoveNextEvent()
if evt.eventType == EventType.buttonPressed:
  if evt.asButtonPressed.numSuccessivePresses == 2:
    echo "Double click detected!"

Example - Encoder events:

var evt = eventQueue.getAndRemoveNextEvent()
if evt.eventType == EventType.encoderTurned:
  let increments = evt.asEncoderTurned.increments
  echo "Encoder turned ", increments, " steps"

Invalid button ID constantInvalid encoder ID constantInvalid potentiometer ID constantEvent type enumerationActivity state for controlsEvent structure - wraps C++ Event with union Access the union field based on eventType (e.g. evt.asButtonPressed.id)UI Event Queue

Types

ActivityType {.importcpp: "daisy::UiEventQueue::Event::ActivityType", size: 1.} = enum
  inactive,                 ## Control is actively being used
  active
Control is not being used Source   Edit  
ButtonPressedData {.bycopy.} = object
  id* {.importc.}: uint16
  numSuccessivePresses* {.importc.}: uint16
  isRetriggering* {.importc.}: bool
Source   Edit  
ButtonReleasedData {.bycopy.} = object
  id* {.importc.}: uint16
Source   Edit  
EncoderActivityData {.bycopy.} = object
  id* {.importc.}: uint16
  newActivityType* {.importc.}: ActivityType
Source   Edit  
EncoderTurnedData {.bycopy.} = object
  id* {.importc.}: uint16
  increments* {.importc.}: int16
  stepsPerRev* {.importc.}: uint16
Source   Edit  
Event {.importcpp: "daisy::UiEventQueue::Event", bycopy.} = object
  eventType* {.importc: "type".}: EventType
  asButtonPressed* {.importc.}: ButtonPressedData
  asButtonReleased* {.importc.}: ButtonReleasedData
  asEncoderTurned* {.importc.}: EncoderTurnedData
  asEncoderActivityChanged* {.importc.}: EncoderActivityData
  asPotMoved* {.importc.}: PotMovedData
  asPotActivityChanged* {.importc.}: PotActivityData
Type of event (use this to determine which union field to access) Source   Edit  
EventType {.importcpp: "daisy::UiEventQueue::Event::EventType", size: 1.} = enum
  invalid,                  ## Button was pressed
  buttonPressed,            ## Button was released
  buttonReleased,           ## Encoder was turned
  encoderTurned,            ## Encoder activity changed (user started/stopped turning)
  encoderActivityChanged,   ## Potentiometer was moved
  potMoved,                 ## Potentiometer activity changed (user started/stopped moving)
  potActivityChanged
Invalid event (returned when queue is empty) Source   Edit  
PotActivityData {.bycopy.} = object
  id* {.importc.}: uint16
  newActivityType* {.importc.}: ActivityType
Source   Edit  
PotMovedData {.bycopy.} = object
  id* {.importc.}: uint16
  newPosition* {.importc.}: cfloat
Source   Edit  
UiEventQueue {.importcpp: "daisy::UiEventQueue", header: "ui/UiEventQueue.h".} = object
Thread-safe FIFO queue for UI events. Safe to add events from interrupt handlers. Source   Edit  

Consts

INVALID_BUTTON_ID = 65535'u16
Source   Edit  
INVALID_ENCODER_ID = 65535'u16
Source   Edit  
INVALID_POT_ID = 65535'u16
Source   Edit  

Procs

proc addButtonPressed(this: var UiEventQueue; buttonId: uint16;
                      numSuccessivePresses: uint16; isRetriggering = false) {.
    importcpp: "#.AddButtonPressed(#, #, #)", ...raises: [], tags: [], forbids: [].}

Add button pressed event to queue

Parameters:

  • buttonId - Unique button identifier
  • numSuccessivePresses - Number of successive presses (1 = single, 2 = double, etc.)
  • isRetriggering - True if auto-retriggered while held down
Source   Edit  
proc addButtonReleased(this: var UiEventQueue; buttonId: uint16) {.
    importcpp: "#.AddButtonReleased(#)", ...raises: [], tags: [], forbids: [].}
Add button released event to queue Source   Edit  
proc addEncoderActivityChanged(this: var UiEventQueue; encoderId: uint16;
                               isActive: bool) {.
    importcpp: "#.AddEncoderActivityChanged(#, #)", ...raises: [], tags: [],
    forbids: [].}

Add encoder activity changed event to queue

Parameters:

  • encoderId - Unique encoder identifier
  • isActive - True if user started turning, false if stopped
Source   Edit  
proc addEncoderTurned(this: var UiEventQueue; encoderId: uint16;
                      increments: int16; stepsPerRev: uint16) {.
    importcpp: "#.AddEncoderTurned(#, #, #)", ...raises: [], tags: [], forbids: [].}

Add encoder turned event to queue

Parameters:

  • encoderId - Unique encoder identifier
  • increments - Number of steps (positive = CW, negative = CCW)
  • stepsPerRev - Total steps per full revolution
Source   Edit  
proc addPotActivityChanged(this: var UiEventQueue; potId: uint16; isActive: bool) {.
    importcpp: "#.AddPotActivityChanged(#, #)", ...raises: [], tags: [],
    forbids: [].}

Add potentiometer activity changed event to queue

Parameters:

  • potId - Unique potentiometer identifier
  • isActive - True if user started moving, false if stopped
Source   Edit  
proc addPotMoved(this: var UiEventQueue; potId: uint16; newPosition: cfloat) {.
    importcpp: "#.AddPotMoved(#, #)", ...raises: [], tags: [], forbids: [].}

Add potentiometer moved event to queue

Parameters:

  • potId - Unique potentiometer identifier
  • newPosition - New position (0.0 to 1.0)
Source   Edit  
proc getAndRemoveNextEvent(this: var UiEventQueue): Event {.
    importcpp: "#.GetAndRemoveNextEvent()", ...raises: [], tags: [], forbids: [].}
Remove and return next event from queue. Returns event with eventType = invalid if queue is empty. Source   Edit  
proc initUiEventQueue(): UiEventQueue {.importcpp: "daisy::UiEventQueue()",
                                        ...raises: [], tags: [], forbids: [].}
Create new empty event queue Source   Edit  
proc isQueueEmpty(this: var UiEventQueue): bool {.importcpp: "#.IsQueueEmpty()",
    ...raises: [], tags: [], forbids: [].}
Returns true if no events are in the queue Source   Edit