nimphea/dev/neotrellis

Search:
Group by:
Source   Edit  

NeoTrellis 4x4 RGB Button Pad Module

Nim wrapper for the Adafruit NeoTrellis 4x4 RGB keypad.

The NeoTrellis is a 4x4 grid of elastomer buttons with individually addressable RGB NeoPixel LEDs underneath. It combines capacitive touch sensing with vibrant RGB lighting, perfect for creating custom controllers and MIDI interfaces.

Features:

  • 16 elastomer buttons (4x4 grid) with capacitive touch sensing
  • 16 individually addressable RGB NeoPixels
  • Key event detection (press/release with rising/falling edge)
  • Callback support for key events
  • I2C interface only
  • Based on Seesaw firmware

Example:

import nimphea
import nimphea/dev/neotrellis

var trellis: NeoTrellisI2C
var config: NeoTrellisConfig

# Configure I2C transport
config.transport_config.address = NEO_TRELLIS_ADDR
config.transport_config.periph = I2C_PERIPH_1
config.transport_config.speed = I2C_400KHZ
config.transport_config.scl = seed.GetPin(11)  # PB8
config.transport_config.sda = seed.GetPin(12)  # PB9

if trellis.init(config) == NEOTRELLIS_OK:
  # Activate all keys to detect rising and falling edges
  for x in 0..3:
    for y in 0..3:
      trellis.activateKey(x, y, RISING, true)
      trellis.activateKey(x, y, FALLING, true)
  
  while true:
    trellis.process()  # Read events and update state
    
    for i in 0..15:
      if trellis.getRising(i):
        # Button i was just pressed
        trellis.pixels.setPixelColor(i, 255, 0, 0)  # Red
      if trellis.getFalling(i):
        # Button i was just released
        trellis.pixels.setPixelColor(i, 0, 0, 0)    # Off
    
    trellis.pixels.show()

Types

KeyEvent {.importcpp: "daisy::NeoTrellis<daisy::NeoTrellisI2CTransport>::keyEvent",
           bycopy.} = object
  reg* {.importcpp: "reg".}: uint16
Key event structure Source   Edit  
NeoPixelI2C {.importcpp: "daisy::NeoPixelI2C", bycopy.} = object
NeoPixel I2C controller (from dev/neopixel.h) Source   Edit  
NeoPixelI2CConfig {.importcpp: "daisy::NeoPixelI2C::Config", bycopy.} = object
NeoPixel I2C configuration (from dev/neopixel.h) Source   Edit  
NeoTrellisConfig {.importcpp: "daisy::NeoTrellisI2C::Config", bycopy.} = object
  transport_config* {.importcpp: "transport_config".}: NeoTrellisI2CTransportConfig
  pixels_conf* {.importcpp: "pixels_conf".}: NeoPixelI2CConfig
NeoTrellis device configuration Source   Edit  
NeoTrellisI2C {.importcpp: "daisy::NeoTrellisI2C", bycopy.} = object
  pixels* {.importcpp: "pixels".}: NeoPixelI2C
NeoTrellis device with I2C transport Source   Edit  
NeoTrellisI2CTransport {.importcpp: "daisy::NeoTrellisI2CTransport", bycopy.} = object
I2C transport for NeoTrellis Source   Edit  
NeoTrellisI2CTransportConfig {.importcpp: "daisy::NeoTrellisI2CTransport::Config",
                               bycopy.} = object
  periph* {.importcpp: "periph".}: I2CPeripheral
  speed* {.importcpp: "speed".}: I2CSpeed
  scl* {.importcpp: "scl".}: Pin
  sda* {.importcpp: "sda".}: Pin
  address* {.importcpp: "address".}: uint8
I2C transport configuration Source   Edit  
NeoTrellisKeypadEdge {.importcpp: "daisy::NeoTrellis<daisy::NeoTrellisI2CTransport>::KeypadEdge",
                       size: 4.} = enum
  NEO_TRELLIS_HIGH = 0,     ## Key is currently high
  NEO_TRELLIS_LOW = 1,      ## Key is currently low
  NEO_TRELLIS_FALLING = 2,  ## Falling edge (key released)
  NEO_TRELLIS_RISING = 3     ## Rising edge (key pressed)
Key event edge types Source   Edit  
NeoTrellisResult {.importcpp: "daisy::NeoTrellis<daisy::NeoTrellisI2CTransport>::Result",
                   size: 4.} = enum
  NEOTRELLIS_OK = 0,        ## Success
  NEOTRELLIS_ERR = 1         ## Error
Operation result Source   Edit  
TrellisCallback = proc (evt: KeyEvent) {.cdecl.}
Callback function type for key events Source   Edit  

Consts

NEO_TRELLIS_ADDR = 0x2E'u8
Default I2C address Source   Edit  
NEO_TRELLIS_NUM_COLS = 4'i32
Number of columns Source   Edit  
NEO_TRELLIS_NUM_KEYS = 16'i32
Total number of keys (4x4) Source   Edit  
NEO_TRELLIS_NUM_ROWS = 4'i32
Number of rows Source   Edit  

Procs

proc activateKey(this: var NeoTrellisI2C; x: uint8; y: uint8; edge: uint8;
                 enable: bool) {.importcpp: "#.ActivateKey(#, #, #, #)",
                                 header: "dev/neotrellis.h", ...raises: [],
                                 tags: [], forbids: [].}

Activate or deactivate a key event

Parameters:

  • x - Column index (0-3, 0 is leftmost)
  • y - Row index (0-3, 0 is topmost)
  • edge - Edge sensitivity (NEO_TRELLIS_RISING, NEO_TRELLIS_FALLING, etc.)
  • enable - true to enable event, false to disable
Source   Edit  
proc clear(this: var NeoPixelI2C) {.importcpp: "#.Clear()",
                                    header: "dev/neopixel.h", ...raises: [],
                                    tags: [], forbids: [].}
Clear all pixels (set to off/black) Source   Edit  
proc enableKeypadInterrupt(this: var NeoTrellisI2C) {.
    importcpp: "#.EnableKeypadInterrupt()", header: "dev/neotrellis.h",
    ...raises: [], tags: [], forbids: [].}

Enable keypad interrupt

Enables the interrupt that fires when events are in the FIFO.

Source   Edit  
proc getFalling(this: var NeoTrellisI2C; idx: uint8): bool {.
    importcpp: "#.GetFalling(#)", header: "dev/neotrellis.h", ...raises: [],
    tags: [], forbids: [].}

Check if a key was just released (falling edge)

Clears the falling flag after reading. Updated by process() function.

Parameters:

  • idx - Key index (0-15)

Returns: true if just released

Source   Edit  
proc getKeypadCount(this: var NeoTrellisI2C): uint8 {.
    importcpp: "#.GetKeypadCount()", header: "dev/neotrellis.h", ...raises: [],
    tags: [], forbids: [].}

Get the number of events in the FIFO

Returns: Number of events waiting to be read

Source   Edit  
proc getRising(this: var NeoTrellisI2C; idx: uint8): bool {.
    importcpp: "#.GetRising(#)", header: "dev/neotrellis.h", ...raises: [],
    tags: [], forbids: [].}

Check if a key was just pressed (rising edge)

Clears the rising flag after reading. Updated by process() function.

Parameters:

  • idx - Key index (0-15)

Returns: true if just pressed

Source   Edit  
proc getState(this: var NeoTrellisI2C; idx: uint8): bool {.
    importcpp: "#.GetState(#)", header: "dev/neotrellis.h", ...raises: [],
    tags: [], forbids: [].}

Check if a key is currently pressed

Updated by process() function.

Parameters:

  • idx - Key index (0-15)

Returns: true if pressed, false if released

Source   Edit  
proc getTransportError(this: var NeoTrellisI2C): NeoTrellisResult {.
    importcpp: "#.GetTransportError()", header: "dev/neotrellis.h", ...raises: [],
    tags: [], forbids: [].}

Get and reset the transport error flag

Returns: NEOTRELLIS_ERR if error occurred, NEOTRELLIS_OK otherwise

Source   Edit  
proc init(this: var NeoTrellisI2C; config: NeoTrellisConfig): NeoTrellisResult {.
    importcpp: "#.Init(#)", header: "dev/neotrellis.h", ...raises: [], tags: [],
    forbids: [].}

Initialize the NeoTrellis device

Parameters:

  • config - Configuration struct with transport settings

Returns: NEOTRELLIS_OK on success, NEOTRELLIS_ERR on failure

Source   Edit  
proc initNeoTrellisConfig(): NeoTrellisConfig {.constructor,
    importcpp: "daisy::NeoTrellisI2C::Config(@)", header: "dev/neotrellis.h".}
Initialize device config with defaults Source   Edit  
proc initNeoTrellisI2CTransportConfig(): NeoTrellisI2CTransportConfig {.
    constructor, importcpp: "daisy::NeoTrellisI2CTransport::Config(@)",
    header: "dev/neotrellis.h".}
Initialize I2C transport config with defaults Source   Edit  
proc process(this: var NeoTrellisI2C; polling: bool = true) {.
    importcpp: "#.Process(#)", header: "dev/neotrellis.h", ...raises: [], tags: [],
    forbids: [].}

Read all events from the FIFO and update state

Call this regularly to process key events and update rising/falling states.

Parameters:

  • polling - true if not using interrupt pin, false if using interrupt (default: true)
Source   Edit  
proc read8(this: var NeoTrellisI2C; reg_high: uint8; reg_low: uint8; delay: cint): uint8 {.
    importcpp: "#.Read8(#, #, #)", header: "dev/neotrellis.h", ...raises: [],
    tags: [], forbids: [].}

Read an 8-bit value from a register

Parameters:

  • reg_high - High byte of register address
  • reg_low - Low byte of register address
  • delay - Delay in microseconds before reading

Returns: 8-bit register value

Source   Edit  
proc registerCallback(this: var NeoTrellisI2C; x: uint8; y: uint8;
                      cb: TrellisCallback) {.
    importcpp: "#.RegisterCallback(#, #, #)", header: "dev/neotrellis.h",
    ...raises: [], tags: [], forbids: [].}

Register a callback for a key

Parameters:

  • x - Column index (0-3)
  • y - Row index (0-3)
  • cb - Callback function to call when event detected
Source   Edit  
proc setKeypadEvent(this: var NeoTrellisI2C; key: uint8; edge: uint8;
                    enable: bool) {.importcpp: "#.SetKeypadEvent(#, #, #)",
                                    header: "dev/neotrellis.h", ...raises: [],
                                    tags: [], forbids: [].}

Activate or deactivate a key event by key number

Parameters:

  • key - Key number (0-15)
  • edge - Edge sensitivity
  • enable - true to enable, false to disable
Source   Edit  
proc setPixelColor(this: var NeoPixelI2C; pixel: uint16; r: uint8; g: uint8;
                   b: uint8) {.importcpp: "#.SetPixelColor(#, #, #, #)",
                               header: "dev/neopixel.h", ...raises: [], tags: [],
                               forbids: [].}

Set a pixel's RGB color

Parameters:

  • pixel - Pixel index (0-15 for NeoTrellis)
  • r - Red value (0-255)
  • g - Green value (0-255)
  • b - Blue value (0-255)
Source   Edit  
proc show(this: var NeoPixelI2C) {.importcpp: "#.Show()",
                                   header: "dev/neopixel.h", ...raises: [],
                                   tags: [], forbids: [].}

Update all pixels with buffered color values

Must be called after setPixelColor() to actually display the colors.

Source   Edit  
proc swReset(this: var NeoTrellisI2C) {.importcpp: "#.SWReset()",
                                        header: "dev/neotrellis.h", ...raises: [],
                                        tags: [], forbids: [].}

Perform a software reset

Resets all Seesaw registers to default values.

Source   Edit  
proc unregisterCallback(this: var NeoTrellisI2C; x: uint8; y: uint8) {.
    importcpp: "#.UnregisterCallback(#, #)", header: "dev/neotrellis.h",
    ...raises: [], tags: [], forbids: [].}

Unregister a callback for a key

Parameters:

  • x - Column index (0-3)
  • y - Row index (0-3)
Source   Edit  
proc write8(this: var NeoTrellisI2C; reg_high: uint8; reg_low: uint8;
            value: uint8) {.importcpp: "#.Write8(#, #, #)",
                            header: "dev/neotrellis.h", ...raises: [], tags: [],
                            forbids: [].}

Write an 8-bit value to a register

Parameters:

  • reg_high - High byte of register address
  • reg_low - Low byte of register address
  • value - Value to write
Source   Edit