Skip to content

Work in progress. Updated as I go along!


Our bedroom music is a Roon endpoint based on the following equipment:

  • a Raspberry Pi 3 microcomputer, with on-board 2.4 GHz Wi-Fi, running DietPi Linux and Roon Bridge
  • a HifiBerry AMP2 add-on board, a 32 bit, 384 kHz capable PCM DAC with a 35 W class D amplifier
  • a 65 W (18 V, 3.34 A) switch mode power supply brick that powers everything
  • a pair of Wharfedale Diamond 9.1 bookshelf speakers, turned white
  • 2.5 mm2 OFC speaker cables

Most of the equipment is hidden under the bed, with only the speakers visible. Volume control is through the Roon Remote application on the laptops or mobile devices.

It's quite "naked", though!

I'd like to get the following improvements:

  • Use Wi-Fi on the 5 GHz band, 2.4 GHz is too crowded in our building, interferences are killing network performance. It's difficult to play standard CD quality music during the evening, forget high-resolution music
  • Have an enclosure that is not too geeky-looking and able to have all sorts of sockets fitted
  • Proper speaker binding terminals, no geeky screw-in stuff, but practical 4mm banana plugs
  • Physical volume and mute button, something that controls volume the good old way
  • Infrared volume and mute remote control (and maybe reboot/power off)
  • All that while fitting within a budget as close to zero as possible!




Here is a list of all the parts used:

  • 1x USB Wi-Fi adapater, N, 5 GHz
  • 1x small wooden box, from Sainsbury's downstairs - Enclosure - £6
  • 1x 5.5 mm x 2.1mm DC power jack female, barrel, panel mount - Power input - £2.77 for a pack of 5
  • 4x binding posts, screw type, 4 mm, panel speaker connectors - Easy speakers connection - £6.95
  • 4x Sewell Strike 4mm banana plugs - for the speaker cables - £0 (I had spares)
  • 1x rotary encoder with switch - Will control the volume/mute - £2
  • 1x silver solid aluminium volume knob - £3
  • 1x infrared sensor (Vishay IR sensor - 38KHz - TSOP4838) - £2
  • 1x small remote control - £0 (had one, unused, from a TV tuner)
  • 20x 3" female/female Jumper wires - £2
  • 1x 3.5mm mini jack chassis panel Mount Stereo Headphone Input Socket Connector - For the infrared sensor connection - £1.89
  • 1x 3 m 3.5 mm male/male stereo jack cable - For the infrared sensor - £2.78
  • 1x kit of various diameters of black heat shrink tubing - Will insulate connections and make things look tidy - £1.79
  • 4x standoffs and screws - For mounting the Raspberry Pi - £0 (I had spares)

5 GHz USB Wifi

I bought a TP-Link Archer T2U adapter. It's is a dual band (2.4 and 5 GHz) A/B/G/N/AC model. I just need 5 GHz N at home.

Linux support is not stellar. I had to manually compile a specific driver and force the use of the access point's 5 GHz radio (BSSID) through wpa_supplicant.conf:

ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev
freq_list=5180 5200 5220 5240

32 bit, 384 kHz PCM audio is now flawlessly streaming at any time of the day!


Wood preparation

I've unscrewed all the lock and hinges and treated the wood with Restor-A-Finish and Feed-N-Wax. This gave the grain a bit of a better look and will hopefully keep the finish more durable. Needless to say, this is very crap wood!




The Raspberry Pi and the very efficient class D amp do not generate much heat. This is not a reason to leave them in a completely closed box.

Holes on the top:

There will be holes on the bottom later. Rubber feet elevate the box and will allow air circulation.


Speaker terminals

Four 10 mm holes later...

Power connector


Volume knob


The rotary encoder is mounted on the top plate, dead center. The box is deep enough, there will be no pin in close proximity with the Raspberry Pi below.

Three pins are used for the rotary encoder (volume), two pins for the push button (mute/un-mute).



I used this python script. I had to adapt it with the GPIO pins I've used and change the mixer from PCM to Digital.

It works like a charm!

Infrared sensor and connector


An 8 mm hole later, top middle position...


LIRC is used for understanding the remote input, IREXEC is used to take action on button presses, using amixer.

The LIRC configuration has dramatically changed in recent versions of Raspbian, making the guides commonly found on the Internet rather misleading.

Here is what needs to be done:

First, add the dtoverlay info in /boot/config.txt (/Dietpi/config.txt in DietPi), there will be no manual loading of any module:


Edit file /etc/lirc/lirc_options.conf and change from:

driver = devinput
device = auto


driver = default
device = /dev/lirc0

You can test that data in coming in with:

systemctl stop lircd.socket
systemctl stop lircd.service
mode2 --driver default --device /dev/lirc0

Delete or suffix (.dist) the existing remote configuration file(s) in /etc/lirc/lircd.conf.d/

Get the know nomenclature for button names:

irrecord --list-namespace

Create a remote configuration file using:

irrecord -d /dev/lirc0

The output file in /etc/lirc/lircd.conf.d/ will be buggy, removing the last column of number for each key normally works.

Mine looks like that after modification:

begin remote

name  credit_card
bits           32
eps            30
aeps          100

header       9148  4520
one           596  1682
zero          596   573
ptrail        591
repeat       9152  2277
gap          108401
toggle_bit_mask 0x0
frequency    38000

begin codes
KEY_POWER                0x00FFB24D
KEY_SELECT               0x00FF2AD5
KEY_MUTE                 0x00FF6897
KEY_RECORD               0x00FF32CD
KEY_TIME                 0x00FF30CF
KEY_CHANNELUP            0x00FFA05F
KEY_VOLUMEUP             0x00FF7887
KEY_VOLUMEDOWN           0x00FF50AF
KEY_SCREEN               0x00FF02FD
KEY_PREVIOUS             0x00FF38C7
KEY_0                    0x00FF48B7
KEY_1                    0x00FF906F
KEY_2                    0x00FFB847
KEY_3                    0x00FFF807
KEY_4                    0x00FFB04F
KEY_5                    0x00FF9867
KEY_6                    0x00FFD827
KEY_7                    0x00FF8877
KEY_8                    0x00FFA857
KEY_9                    0x00FFE817
end codes

end remote

Test that it's working with


I'm using the following /etc/lirc/irexec.lircrc global configuration to control amixer on button presses:

prog = irexec
remote = credit_card
button = KEY_MUTE
repeat = 0
config = amixer sset Digital toggle > /dev/null

prog = irexec
remote = credit_card
repeat = 1
config = amixer sset Digital 1%+ > /devnull

prog = irexec
remote = credit_card
repeat = 1
config = amixer sset Digital 1%- > /dev/null

prog = irexec
remote = credit_card
button = KEY_SCREEN
repeat = 0
config = wget -O /dev/null -o /dev/null

prog = irexec
remote = credit_card
repeat = 0
config = wget -O /dev/null -o /dev/null

prog = irexec
remote = credit_card
repeat = 0
config = wget -O /dev/null -o /dev/null


Technical test with alsamixer:

Practical test with Roon:

I am using amixer commands to control the volume level, including a mute toggle, and HTTP Calls for Roon APIs to control Play/Pause, Next and Previous track though wget.

Raspberry Pi

Standoffs and screws ready for mounting on the thin bottom board of the box, followe by four 2.5 mm holes: