Skip to content

Commit

Permalink
[New component] HiFiBerry Sound Card & OnOff SHIM (#2169)
Browse files Browse the repository at this point in the history
* Add components folder to installation and docs. First component is hifiberry sound card

* Allow for all hifiberry boards

* Disabling HDMI Audio

* Finalize HiFiBerry doc

* Refer to Pi Pinout for convenience

* Enable ALSA config as an option as well

* Allow script to be run multiple times

* Add OnOff SHIM as component

* Make script more robust based on PR comments

* Update hifiberry soundcard options

* Automate soundcard detection for asound.conf

* use /boot/config based on debian version

* Reorganize a few things

* some bugfixes

* Final fixes

* Optimize case

* Update docs

* Uninstall option

* fix: Remove option was not reachable

* fix: enable sudo

* fix: make I/O fail silently

* feat: Introduce 1-line installation

* feat: outsource onboard_sound as its own option

* refactor: remove alsa config

* fix: update case function

* fix: adding some thens

* fix: some iterations did not work

* fix: adding another sudo

* refactor: get_key_by_item_number for associated arrays

* refactor: remove last bits of alsa

* fix: final touches

* fix: add missing removal only option

* fix: outsource example_usage for 1-line install

* fix: condition for 1-line installation

* fix: another fix for if conditions

* refactor: move 1-line installation down

* gs

* another fix

* fix: write array check differently

* refactor: final touches

* feat: enable silent mode for check_existing_hifiberry

* fix: reintroduce sudo check

* fix: documentation

* fix: final touches again

* fix: remove is_sudo again

* fix: Remove last sudo occurrences

* fix: bullet proof

* Make bash files executable

* fix: Update documentation

* fix: 1-line path does not worj

* Update documentation/builders/components/soundcards/hifiberry.md

Co-authored-by: s-martin <[email protected]>

* Update documentation/builders/components/soundcards/hifiberry.md

Co-authored-by: s-martin <[email protected]>

* Update documentation/builders/components/soundcards/hifiberry.md

Co-authored-by: s-martin <[email protected]>

* fix: Update regex for commented code

* Adding OnOff Shim resource
  • Loading branch information
pabera authored Jan 16, 2024
1 parent 6e9e4f7 commit 03e6197
Show file tree
Hide file tree
Showing 7 changed files with 296 additions and 13 deletions.
6 changes: 6 additions & 0 deletions documentation/builders/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,12 @@
* [Card Database](./card-database.md)
* [Troubleshooting](./troubleshooting.md)

## Components
* [Power](./components/power/)
* [OnOff SHIM for safe power on/off](./components/power/onoff-shim.md)
* [Soundcards](./components/soundcards/)
* [HiFiBerry Boards](./components/soundcards/hifiberry.md)

## Advanced

* [Bluetooth (and audio buttons)](./bluetooth-audio-buttons.md)
Expand Down
36 changes: 36 additions & 0 deletions documentation/builders/components/power/onoff-shim.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# OnOff SHIM by Pimorino

The OnOff SHIM from Pimorino allows you to savely start and shutdown your Raspberry Pi through a button. While you can switch of your Phoniebox via an RFID Card (through an RPC command), it is difficult to switch it on again without cutting the physical power supply.

## Installation

To install the software, open a terminal and type the following command to run the one-line-installer. A reboot will be required once the installation is finished.

> [!NOTE]
> The installation will ask you a few questions. You can safely answer with the default response.
```
curl https://get.pimoroni.com/onoffshim | bash
```

* [Source](https://shop.pimoroni.com/products/onoff-shim?variant=41102600138)

## How to manually wire OnOff SHIM

The OnOff SHIM comes with a 12-PIN header which needs soldering. If you want to spare some GPIO pins for other purposes, you can individually wire the OnOff SHIM with the Raspberry Pi. Below you can find a table of Pins to be connected.

| Board pin name | Board pin | Physical RPi pin | RPi pin name |
|----------------|-----------|------------------|--------------|
| 3.3V | 1 | 1, 17 | 3V3 power |
| 5V | 2 | 2 | 5V power |
| 5V | 4 | 4 | 5V power |
| GND | 6 | 6, 9, 20, 25 | Ground |
| GPLCLK0 | 7 | 7 | GPIO4 |
| GPIO17 | 11 | 11 | GPIO17 |

* More information can be found here: https://pinout.xyz/pinout/onoff_shim

## Assembly options

![](https://cdn.review-images.pimoroni.com/upload-b6276a310ccfbeae93a2d13ec19ab83b-1617096824.jpg?width=640)

49 changes: 49 additions & 0 deletions documentation/builders/components/soundcards/hifiberry.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
# HiFiBerry

The installation script works for the most common set of HiFiBerry boards but also other "DAC" related sound cards like `I2S PCM5102A DAC`.

## Automatic setup

Run the following command to install any HiFiBerry board. Make sure you reboot your device afterwards.

```bash
cd ~/RPi-Jukebox-RFID/installation/components
./setup_hifiberry.sh
```

If you know you HifiBerry Board identifier, you can run the script as a 1-liner as well

```bash
./setup_hifiberry.sh enable hifiberry-dac
```

If you like to disable your HiFiberry Sound card and enable onboard sound, run the following command


```bash
./setup_hifiberry.sh disable
```

## Additional information

If you like to understand what's happening under the hood, feel free to check the [install script](../../../../installation/components/setup_hifiberry.sh).

The setup is based on [HiFiBerry's instructions](https://www.hifiberry.com/docs/software/configuring-linux-3-18-x/).

## How to manually wire your HiFiBerry board

Most HiFiBerry boards come with 40-pin header that you can directly attach to your Pi. This idles many GPIO pins that may be required for other inputs to be attached (like GPIO buttons or RFID). You can also connect your HiFiBerry board separately. The following table show cases the pins required.

* [Raspberry Pi Pinout](https://github.com/raspberrypi/documentation/blob/develop/documentation/asciidoc/computers/os/using-gpio.adoc)

| Board pin name | Board pin | Physical RPi pin | RPi pin name |
|----------------|-----------|------------------|--------------|
| 3.3V | 1 | 1, 17 | 3V3 power |
| 5V | 2 | 2, 4 | 5V power |
| GND | 6 | 6, 9, 20, 25 | Ground |
| PCM_CLK | 12 | 12 | GPIO18 |
| PCM_FS | 36 | 36 | GPIO19 |
| PCM_DIN | 38 | 38 | GPIO20 |
| PCM_DOUT | 40 | 40 | GPIO21 |

You can find more information about manually wiring [here](https://forum-raspberrypi.de/forum/thread/44967-kein-ton-ueber-hifiberry-miniamp-am-rpi-4/?postID=401305#post401305).
2 changes: 1 addition & 1 deletion documentation/developers/docker.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ need to adapt some of those commands to your needs.
## Prerequisites

1. Install required software: Docker, Compose and pulseaudio
* Check installations guide for [Mac](#mac), [Windows](#windows) or [Linux](#linux)
* Check installation guide for [Mac](#mac), [Windows](#windows) or [Linux](#linux)

2. Pull the Jukebox repository:

Expand Down
119 changes: 119 additions & 0 deletions installation/components/setup_hifiberry.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
#!/usr/bin/env bash

# This script follows the official HiFiBerry documentation
# https://www.hifiberry.com/docs/software/configuring-linux-3-18-x/

source ../includes/02_helpers.sh

script_name=$(basename "$0")
boot_config_path=$(get_boot_config_path)

declare -A hifiberry_map=(
["hifiberry-dac"]="DAC (HiFiBerry MiniAmp, I2S PCM5102A DAC)"
["hifiberry-dacplus"]="HiFiBerry DAC+ Standard/Pro/Amp2"
["hifiberry-dacplushd"]="HiFiBerry DAC2 HD"
["hifiberry-dacplusadc"]="HiFiBerry DAC+ ADC"
["hifiberry-dacplusadcpro"]="HiFiBerry DAC+ ADC Pro"
["hifiberry-digi"]="HiFiBerry Digi+"
["hifiberry-digi-pro"]="HiFiBerry Digi+ Pro"
["hifiberry-amp"]="HiFiBerry Amp+ (not Amp2)"
["hifiberry-amp3"]="HiFiBerry Amp3"
)

example_usage() {
for key in "${!hifiberry_map[@]}"; do
description="${hifiberry_map[$key]}"
echo "$key) $description"
done
echo "Example usage: ./${script_name} enable hifiberry-dac"
}

enable_hifiberry() {
echo "Enabling HiFiBerry board..."
grep -qxF "^dtoverlay=$1" "$boot_config_path" || echo "dtoverlay=$1" | sudo tee -a "$boot_config_path" > /dev/null
./../options/onboard_sound.sh disable
}

disable_hifiberry() {
echo "Removing existing HiFiBerry configuration..."
sudo sed -i '/^dtoverlay=hifiberry-/d' "$boot_config_path"
./../options/onboard_sound.sh enable
}

check_existing_hifiberry() {
existing_config=$(grep '^dtoverlay=hifiberry-' "$boot_config_path")
if [ ! -z "$existing_config" ]; then
if [ "$1" = "silent" ]; then
disable_hifiberry
return 0
fi

echo "Existing HiFiBerry configuration detected: $existing_config"
read -p "Do you want to proceed with a new configuration? This will remove the existing one. (Y/n): " choice
case $choice in
[nN][oO]|[nN])
echo "Exiting without making changes.";
exit;;
*)
disable_hifiberry;
return 0;;
esac
fi
}

# 1-line installation
if [ $# -ge 1 ]; then
if [[ "$1" != "enable" && "$1" != "disable" ]] || [[ "$1" == "enable" && -z "$2" ]]; then
echo "Error: Invalid arguments provided.
Usage: ./${script_name} <status> <hifiberry-board>
where <status> can be 'enable' or 'disable'.
The following board options exist:"
example_usage
exit 1
fi

if [ "$1" == "enable" ]; then
if [[ -v hifiberry_map["$2"] ]]; then
check_existing_hifiberry "silent"
enable_hifiberry "$2"
exit 1
fi

echo "'$2' is not a valid option. You can choose from:"
example_usage
exit 1
fi

disable_hifiberry
exit 1
fi

# Guided installation
board_count=${#hifiberry_map[@]}
counter=1

echo "Select your HiFiBerry board:"
for key in "${!hifiberry_map[@]}"; do
description="${hifiberry_map[$key]}"
echo "$counter) $description"
((counter++))
done
echo "0) Remove existing HiFiBerry configuration"

read -p "Enter your choice (0-$board_count): " choice
case $choice in
[0])
disable_hifiberry;
;;
[1-$board_count])
selected_board=$(get_key_by_item_number hifiberry_map "$choice")
check_existing_hifiberry
enable_hifiberry "$selected_board";
;;
*)
echo "Invalid selection. Exiting.";
exit 1;;
esac

echo "Configuration complete. Please restart your device."
70 changes: 58 additions & 12 deletions installation/includes/02_helpers.sh
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,21 @@ show_slow_hardware_message() {
fi
}

# Get key by item number of associated array
get_key_by_item_number() {
local -n array="$1"
local item_number="$2"
local count=0

for key in "${!array[@]}"; do
((count++))
if [ "$count" -eq "$item_number" ]; then
echo "$key"
return
fi
done
}

# $1->start, $2->end
calc_runtime_and_print() {
runtime=$(($2-$1))
Expand Down Expand Up @@ -46,18 +61,49 @@ run_with_log_frame() {
}

get_architecture() {
local arch=""
if [ "$(uname -m)" = "armv7l" ]; then
arch="armv7"
elif [ "$(uname -m)" = "armv6l" ]; then
arch="armv6"
elif [ "$(uname -m)" = "aarch64" ]; then
arch="arm64"
else
arch="$(uname -m)"
fi

echo $arch
local arch=""
if [ "$(uname -m)" = "armv7l" ]; then
arch="armv7"
elif [ "$(uname -m)" = "armv6l" ]; then
arch="armv6"
elif [ "$(uname -m)" = "aarch64" ]; then
arch="arm64"
else
arch="$(uname -m)"
fi

echo $arch
}

is_raspian() {
if [[ $( . /etc/os-release; printf '%s\n' "$ID"; ) == *"raspbian"* ]]; then
echo true
else
echo false
fi
}

get_debian_version_number() {
source /etc/os-release
echo "$VERSION_ID"
}

get_boot_config_path() {
if [ "$(is_raspian)" = true ]; then
local debian_version_number=$(get_debian_version_number)

# Bullseye and lower
if [ "$debian_version_number" -le 11 ]; then
echo "/boot/config.txt"
# Bookworm and higher
elif [ "$debian_version_number" -ge 12 ]; then
echo "/boot/firmware/config.txt"
else
echo "unknown"
fi
else
echo "unknown"
fi
}

validate_url() {
Expand Down
27 changes: 27 additions & 0 deletions installation/options/onboard_sound.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
#!/usr/bin/env bash
source ../includes/02_helpers.sh
script_name=$(basename "$0")
boot_config_path=$(get_boot_config_path)

if [ -z "$1" ] || { [ "$1" != "enable" ] && [ "$1" != "disable" ]; }; then
echo "Error: Invalid or no argument provided.
Usage: ./${script_name} <arg>
where <arg> can be 'enable' or 'disable'"
exit 1
fi

arg="$1"

if [ "$arg" = "enable" ]; then
echo "Enabling Onboard Sound..."
sudo sed -i "s/^\(dtparam=\([^,]*,\)*\)audio=\(off\|false\|no\|0\)\(.*\)/\1audio=on\4/g" "$boot_config_path"
sudo sed -i '/^dtoverlay=vc4-fkms-v3d/{s/,audio=off//g;}' "$boot_config_path"
sudo sed -i '/^dtoverlay=vc4-kms-v3d/{s/,noaudio//g;}' "$boot_config_path"
elif [ "$arg" = "disable" ]; then
echo "Disabling Onboard Sound..."
sudo sed -i "s/^\(dtparam=\([^,]*,\)*\)audio=\(on\|true\|yes\|1\)\(.*\)/\1audio=off\4/g" "$boot_config_path"
sudo sed -i '/^dtoverlay=vc4-fkms-v3d/{s/,audio=off//g;s/$/,audio=off/g;}' "$boot_config_path"
sudo sed -i '/^dtoverlay=vc4-kms-v3d/{s/,noaudio//g;s/$/,noaudio/g;}' "$boot_config_path"
fi

# TODO Test

0 comments on commit 03e6197

Please sign in to comment.