V25 controller overview

Stepped attenuator and preamp controller

The V25 is a digitally controlled, 2 channel analog stereo passive stepped attenuator and preamp controller. Unlike most audio attenuation technology the V25 utilizes light dependent resistors (LDRs) for both attenuation and in lieu of conventional relays for input switching.

The V25 Preamp Controller (Rev A) was released in April, 2017 and subsequently 2 minor hardware revisions have been made.

Noteworthy features of the V25 include the following:

  • Smooth 100 steps of attenuation over a 60 dB range at ~0.6 dB per step
  • Input switching of up to 6 stero inputs
  • 2 units can be combined for balanced audo
  • Fully remote controllable via simple infrared Apple remote
  • Manually controllable via rotary encoder/pushbutton with limitations
  • Smooth muting
  • Left/right channel balance
  • LDRs employed both for attenuation and input switching
  • Built-in self-contained LDR calibration of replaceable plug-in LDR modules
  • High contrast 256×64 bit white-on-black OLED display with interactive menu structure

The V25 board is shown below with annotation of the key components and control interface points. Please refer to V25 Specifications section for more detail.

V25 preamp controller port - annotated

Powered passive preamp attenuator

The V25 is powered by a nominal 12V supply (not included) which is coverted to both 5V and 3.3V for use within the board. The power drives an embedded ARM microcontroller and its interfaces with a remote control receiver, serial comm ports, trigger outputs, USB port, OLED display, and most significantly the LDRs themselves which contain light emitting diodes to modulate their vaiable resistance.

The V25 is classified as a unity gain “passive” preamp device with no active amplification or buffering of the audio signal. That means there is no direct connection to, or manipulation of, the audio signal by a power supply. Despite the sophistication of the V25 design, each audio channel signal “sees” only a voltage divider composed of 2 LDRs in a classic series/shunt L-Pad configuration that emulates a potentiometer.


There are currently 3 hardware versions of the V25 board designated as A, B and C with A being the original board as shown above. The version letter is printed on the V25 board on the left side under the name of the board.

The differences between these versions relate solely to the display interfaces and the USB interface. These differences are summarized in the table below. All 3 versions utilize the same firmware which recognizes these differences.

Criteria Version AVersion BVersion C
7 segment display Yes | J3 headerYes | J3 headerYes | via individual signals from OLED J9 header
OLED display interface (J9)Yes | parallelYes | serial SPIYes | serial SPI
Serial (SPI) interface voltage to 7 segment display header (J3)5V3.3VN/A
USB header 5V VBus pin powerered by boardNo YesYes

OLED display | J9

The OLED Display Module (sold separately) is a highly interactive, easy to use, intuitive, menu driven user control interface for configuring and controlling the V25. Today, the OLED display continues to be an integral part of the interactive control of the V25 stepped attenuator and preamp controller. The V25 continues to also be capable of driving a pair of Tortuga Audio’s legacy dual 2 digit 7-segment display modules.

The OLED display connects to the V25 via a 14 pin ribbon cable to the V25.J9 header.

Please refer to a separate document on the OLED display for more detail on its interface.

OLED display module - front view


Multi-channel configuration | J7

The V25 is designed to allow multiple V25 boards to be daisy-chained together for multi-channel audio. Here are the characteristics of the V25 multi-channel system:

  • The first board in the daisy-chain is designated the master board
  • The master board interconnect to a slave board (if there is one) with a data link
  • The master V25 board is in charge, receives control inputs, drives the visual display, and passes commands to the first slave
  • Additional slaves connect to only one upstream and one downstream slave (the daisy-chain)
  • Communications between boards is bi-directional using a pair of independent UART 2-wire serial data links
  • Any V25 board can be a master or slave. No special jumpers or settings are required.
  • There is overall left/right channel balance control in a multi-channel arrangement but currently no individual channel volume adjustment.

V25 master slave serial data link diagram

Dual board balanced audio

Balanced stereo audio is a minimal example of using the V25 in a multi-channel audio application.  Balanced stereo audio requires two V25 boards – 4 channels. Balanced audio input and output wiring is described in another section/topic on DIY audio information.

External control via UART | J7

The V25 Preamp Controller Board can be controlled by interfacing it with any PC, microcontroller or programmable device that’s equipped with standard UART serial communications hardware or the equivalent in software. External UART TX and RX signals can connect to the V25  J7.RX2 and J7.TX2 pins respectively.

In order to have reliable UART communications the user should be mindful that both devices share a common ground.

UART Protocol

The UARTs used by the V25 are part of the V25’s microcontroller. They utilize data receipt interrupts, and are considered extremely accurate and reliable. The V25 employs the following UART communications configuration.

  • Baud Rate: 115,200 bps
  • Stop Bits: 1 stop bit
  • Parity: none
  • Data bits: 8
  • Flow Control: none

UART control commands

The control commands available to an external controller are defined in the table below. Collectively these commands should allow for the comprehensive control of the V25 even in the absence of any visual feedback from the V25.

The user accepts all risks in using an external controller and commands to control their V25 controller. These commands are subject to change without notification.   

Command ValueCommand NameDesciption>
0_power_toggletoggles the on/off state of the controller
1_turnonturns controller on if it's off otherwise ignores
2_turnoffturns controller off if its on otherwise ignores
3_raiseresponse depends on controller mode - by default it raises volume 1 step
4_lowerresponse depends on controller mode - by default it lowers volume 1 step
5_leftresponse depends on controller mode - by default it shifts volume balance 1 step to the left
6_rightresponse depends on controller mode - by default it shifts volume balance 1 step to the right
7_enter* volume adjust mode - blinks display
* other modes - locks in any changes and reverts to default volume adjust mode
8** reserved ** don't use
9** reserved ** don't use
10** reserved **don't use
11_menu_volswitches controller to default volume adjust mode
12_menu_inputswitches controller to input adjust mode
13_menu_displayswitches controller to display adjust mode
14_menu_volmaxswitches controller to max volume on input change adjust mode
15_menu_impedswitches controller to impedance adjust mode
16_menu_calswitches controller to auto calibration mode
17_mute_toggletoggles mute state of controller
18_mutemutes the volume if not already muted
19_mute_switchmutes controller, then switches to new input (slow mode only), and then unmutes controller
20_unmuteunmutes the volume if it's currently muted
21_refreshrefreshes display based on current mode
22_showdisplay info associated with current mode
23** reserved ** don't use
24** reserved ** don't use
25** reserved ** don't use)
26** reserved ** don't use
27** reserved ** don't use
28** reserved ** don't use
29** reserved ** don't use
30** reserved ** don't use
31_send_vol* 2 bytes : command + value
* value = volume level 0-99
32_send_volbias* 2 bytes : command + value
* value = volume bias between -20 and+20
33_send_volmax* 2 bytes : command + value
* value = max volume upon input change between 1 and 99
(99 essentially defeats this safely feature)
34_send_input* 2 bytes : command + value
* value = input number between 1 and 6
_send_imped_index* 2 bytes : command + value
* value = impedance index number between 1 and 5
36_send_imped_level* 2 bytes : command + value
* value = impedance level between 1 and 99
(must run autocal after changing level before change becomes active)
37** reserved ** don't use


Was this helpful?