# Hardware Support > Original: [Hardware support](https://tttapa.github.io/Control-Surface/Doxygen/db/dd3/group__AH__ExtIO.html) Hardware utilities in the `AH::` namespace for debouncing, filtering, and encoder reading. ## Button Debounced button with state machine: ```cpp pico AH::Button btn {5}; btn.begin(); // In loop: btn.update(); if (btn.getState() == AH::Button::Falling) // pressed if (btn.getState() == AH::Button::Rising) // released ``` States: `Pressed`, `Released`, `Falling` (just pressed), `Rising` (just released). ## FilteredAnalog EMA-filtered analog input with hysteresis to reduce noise: ```cpp pico AH::FilteredAnalog<10> pot {26}; // 10-bit, GPIO 26 // In loop: if (pot.update()) uint16_t value = pot.getValue(); ``` ## AHEncoder Interrupt-driven quadrature rotary encoder: ```cpp pico AH::AHEncoder enc {0, 1}; // pin A, pin B enc.begin(); // In loop: int32_t delta = enc.read(); enc.write(0); // reset position ``` ## GPIO on RP2xxx cs-midi uses pico-sdk GPIO directly. Pin numbers are GPIO numbers (0-29 on RP2040, 0-47 on RP2350). - Buttons use internal pull-ups (active low) - ADC pins: GPIO 26-29 (ADC0-ADC3) - Encoder pins: any GPIO with interrupt capability (all pins on RP2xxx) ## Extended I/O Hardware expanders (MCP23017, MAX7219, shift registers) are not yet ported from Control Surface. Use direct GPIO pins for all inputs and outputs.