BeoLink Control: Decoding & Sending With ESP32 & Beo4
Hey guys! Ever wanted to dive deep into controlling your Bang & Olufsen (B&O) gear using an ESP32 and your Beo4 remote? This guide is your starting point! We'll explore how to send those crucial "Link bits" to get your system humming, and tackle some coding challenges along the way. It's perfect for a rainy day project, or if you just like tinkering with cool tech. So, let's get started!
Understanding the Beo4 and BeoLink Basics
How to Send Link Bits with Beo4?
First things first, let's make sure your Beo4 remote is ready to roll. The goal is to send Link bits, which tell your B&O system to perform specific actions. Here's the deal:
- Check for the "LINK" Command: Grab your Beo4 remote and press the "LIST" button several times. Keep an eye on the display. If "LINK" appears, you're in luck! Your remote already knows about the Link command. If not, you might need to add it. Check your Beo4 manual (page 10 of the PDF [https://beomanuals.com/manuals/Beolink/Remote controls/Bang-Olufsen-Beo_4-Owners-Manual-2.pdf]) for instructions on how to add "LINK" to the list of commands.
- Activating the Link: Once "LINK" is available on your Beo4's display, you're ready to send Link bits. Simply press "LIST" until "LINK" appears, and then select the desired function, such as "TV". This action will trigger the Link bit transmission.
What are Link Bits? And Why Do They Matter?
Link bits are special signals sent by your Beo4 that control various functions across your B&O system. They enable you to do things like:
- Synchronize audio and video: Start and stop playback across multiple rooms or devices.
- Control sources: Switch between different audio and video sources.
- Activate BeoLink features: Use features like multiroom audio.
In short, Link bits unlock the full potential of your B&O setup, allowing for seamless control and integration.
Important Note
Keep in mind that the exact functionality of Link bits can vary depending on your B&O equipment. Different devices may respond to different Link commands. So, it's a good idea to consult your device manuals for details.
Delving into the Code: The Challenge of Sending Link Bits
Now, let's talk about the nitty-gritty of sending these Link bits with an ESP32. This involves capturing the signals from your Beo4, decoding them, and then transmitting them. In the examples you will see later we are going to delve a bit into this.
The Code: Decoding and Sending the Link Bits
The Initial Approach: Repeatable Codes and State Machines
In the earlier versions of the code, a state machine was used to handle the different aspects of the signal. Here's how it was intended to work, using the pwStart
pulse as the separation point for splitting long frames:
uint32_t preBit = (pulseCodes[0] == pcSame) ? 1 : 0;
And also:
data = beoCode;
This approach aimed to correctly identify and process the Link bits by checking the initial pulse codes. The preBit
variable would determine the initial bit value based on the pcSame
condition.
The New Approach: Challenges and Adjustments
The newer version of the code, as found in this commit [https://github.com/aanban/esp32_beo4/commit/d07c762d8d085d66b0051171da51572827e94e1a], changes things up. It sets the signal_range_max_ns
to 10ms, and uses start and stop pulses to delimit the signal. This is where things get tricky. The initial bit is missing and the FSM doesn't recognize the change, leading to the preBit
being incorrect.
The Problem: Missing First Bit
The core issue is that the new version of the code doesn't correctly capture the very first bit of the Link command. This leads to misinterpretation by the FSM (Finite State Machine) used for decoding the signals. This is also where the issue started. Here's an example of the issues:
-
Old Data:
0:1 1:2 2:2 3:2 4:2 5:2 6:2 7:2 8:3 9:2 10:1 11:2 12:3 13:1 14:2 15:3 16:2 17:4 beo4_task: 130193 audio phono-on Master 0:2 1:1 2:2 3:2 4:2 5:2 6:2 7:2 8:3 9:2 10:1 11:2 12:3 13:1 14:2 15:3 16:2 17:4 beo4_task: 130193 audio phono-on Link
-
New Data:
0:2 1:2 2:2 3:2 4:2 5:2 6:2 7:3 8:2 9:1 10:2 11:3 12:1 13:2 14:3 15:2 16:4 beo4_task: 130193 audio phono-on Master 0:1 1:2 2:2 3:2 4:2 5:2 6:2 7:3 8:2 9:1 10:2 11:3 12:1 13:2 14:3 15:2 16:4 beo4_task: 130193 audio phono-on Link
Notice how the first value is sometimes 1
or 2
. This inconsistency leads to the decoding problems.
A Workaround: A Less Elegant but Functional Solution
Since the new version has some issues, a workaround was used to address the missing first bit. Here's the approach:
// start with the right bit (this has no effect in the FSM but looks clear for next line)
uint32_t preBit = (beoData[0] == 1) ? 1 : 0;
...
// set the beocode to 1 or 0 depending on linkBit bevor loop to the beoData
beoCode = preBit;
for (int16_t ic = 0; ic < 16; ic++) {
...
}
// on the end copy the beoCode to data and do not override the left bit. beoCode should be already well formed
//data = ((uint32_t)n_sym << 16) + (beoCode & 0xffff);
data = beoCode;
This approach sets the preBit
according to beoData[0]
. It makes it look like the preBit
has an effect in the FSM. The workaround ensures the Link bit is set correctly before processing the remaining data. It also ensures that beoCode
is correctly formed before it is copied to data
.
The Code in Detail
Let's break down the code snippets more specifically. This code sets up the system to work with Link bits:
-
Initialization:
- The code begins by defining
preBit
. The crucial step is to evaluatebeoData[0]
. This is critical in determining the initial state of the signal.
- The code begins by defining
-
Setting the Link Bit:
- Inside the main processing loop, the
beoCode
variable is initialized withpreBit
. This prepares the code for the main loop.
- Inside the main processing loop, the
-
Data Processing:
- The loop then iterates through the data and processes the 16 bits that are to be sent.
-
Finalization:
- Finally, the code copies the
beoCode
todata
. This ensures that the Link bit is correctly set within the final data. This step is where thebeoCode
is copied to data without overriding the bit in the left.
- Finally, the code copies the
This ensures that the first bit is set to the right value, making sure that the system can recognize the incoming signals correctly.
Identifying the Link Command
After all the coding, you can check if the received code is a Link command:
const uint8_t beo_src_is_link(uint32_t beo_code) {
return (beo_code >> 16) & 0xFF;
}
This function checks the source of the command by shifting the code right by 16 bits and performing a bitwise AND with 0xFF. This isolates the relevant portion of the code, letting you verify if the command is from a Link device.
The Results: Verifying the Link Command
Here's an example of the output after sending the Link command, along with the source check, using the beo_src_is_link
function:
Serial.printf("beo4_task: %04x %s %s %d\n", beo4Code, beo_src_tbl(beo4Code), beo_cmd_tbl(beo4Code), beo_src_is_link(beo4Code));
This outputs:
beo4_task: 0080 video tv-on 0
beo4_task: 0058 video list 0
beo4_task: 10080 video tv-on 1
Here, the beo_src_is_link(beo4Code)
function returns 1
if the command is a Link command and 0
if it is not. The output shows the tv-on
command with source 1
, which means it is a Link command.
Important Note on Data Changes
Also, note that the data format in the new version has changed. TV was 120080
in the old version, but is now 0080
. This means you'll need to adjust the code to correctly interpret the new data format.
Conclusion: Control Your B&O with Confidence
So there you have it, guys! By understanding the basics of the Beo4 and Link commands, and by diving into the code (and the workarounds), you can send those Link bits to control your B&O system. It might require a little tweaking, but the possibilities are huge. This project can lead to a completely customized remote control experience, allowing you to control your entire entertainment setup with precision.
Next Steps
- Experiment: Try different commands and see how your system responds.
- Refine: Fine-tune the code for optimal performance and reliability.
- Integrate: Integrate this code with other ESP32 projects to create a complete smart home solution. Have fun playing with your B&O setup! Let me know how it goes and if you have any questions!
B.R.