Recovery and restoration service:frontea online,corp.

Recovery and restoration service:frontea online,corp.

Deep Abyss Audio (10) Core’1 – Mission Command Layer Pro‑Audio Spec PopoDAC (USB DAC) DIY Series

‹ 2026/01/04 ›

Good evening.

This is the 10th installment, and from here on we finally step into the core—the true heart of the system.

(…Honestly, Core alone could become its own multi‑part series.)


Latest PopoDAC Completion Status

At this point, PopoDAC has reached:

180% completion against Windows

99.95% completion against iPhone


And to jump straight to the conclusion of the entire PopoDAC series:

This is the specification at which I consider PopoDAC “complete.”


“But there’s still 0.05% missing, isn’t there?”

Yes.

I left that 0.05% on purpose—as a kind of memorial.

It’s not something I gave up on.


After tracing the system down to its deepest layers, repeating measurements and adjustments, and refining my understanding, I eventually realized:

There is no longer any meaningful reason to pursue 100% against iPhone.

I’ll explain why somewhere later in the series.


PopoDAC Core Architecture (Paxa‑spec.)

Alright—time to drop the hammer and reveal the Core (the main citadel).


Core Architecture Overview

The PopoDAC Core Architecture is built as:


A centrally‑controlled, independent 3‑phase drive × 8‑module system,

rotating with completely lock‑free inter‑phase operation.


Every functional block is arranged with strict PAXA‑spec discipline and structural clarity.


At this point…

There is simply no way this thing won’t fly.


PopoDAC Core Architecture – Module List

Expressed as a structured list, the PopoDAC Core Architecture consists of the following components:


Mission Command Layer

- Module 1: Startup and Igniter(System boot and ignition)


Guidance & Navigation Control

- Module 2: Real-Time Sensor(Real‑time observation)

- Module 3: Timeline Adjuster(Time‑axis correction)

- Module 4: Feedback Uplinker(Upstream feedback link)


Telemetry Downlink Receiver

- Module 5: Data Telemetry Receiver(Downlink data processing)


Timeline Dynamics Processor

- Module 6: Velocity Vector Stabilizer(Stabilization of temporal velocity vectors)

- Module 7: Timeline Interpolation(Time‑axis interpolation)

- Module 8: Timeline Thruster(Time‑axis propulsion output)


Honestly… it looks almost too cool.


With these eight modules arranged across three layers and operating in proper coordination, the system can lock itself onto the MASTER TIMELINE—the true physical time axis—and drive the speakers accordingly.


What is SOF?

Before diving into the module explanations, there is one extremely important topic I intentionally did not cover in the UAC chapter.

This is the right moment to address it.


SOF — Start Of Frame  

This is the literal heartbeat of the USB protocol.


Most people—probably 99%—believe that SOF is an absolute 1 ms boundary in UAC1 or an absolute 125 µs boundary in UAC2.


But before we can correctly understand the MASTER TIMELINE, we need to clear up this misconception.

This is likely the most important and most misunderstood topic in the entire series.

(If you’ve endured the series up to this point, or if you just happened to stumble in here out of curiosity—you’re in for a very lucky chapter.)


Let’s look at the diagram.

The first half shows a simple operation: copying a file from a PC to a USB flash drive.

Windows, being kind, shows you the transfer speed, the number of bytes transferred, and even a graph.

You’ve seen that graph before.

The transfer speed fluctuates—waves up and down—while the file continues to copy until completion.

And the only thing every human on Earth cares about is:

“Does the copied data match the original?”


That’s it.


The wavy transfer behavior is normal.

It happens not only in USB but in almost every I/O system.

And nobody worries about it.

People care about the total copy time and whether the result is correct.


Now consider a USB DAC.

A USB DAC is still a USB device.

UAC is not exempt from USB’s fundamental constraints.

In fact, UAC is bound by the parent USB specification.


Even if the host sends audio data—UAC1 or UAC2 doesn’t matter—the transfer still progresses through the same fluctuating timing.


So even if your I2S side has a high‑precision MCLK, if the host and the DAC are not timeline‑locked, the DAC is effectively performing music inside a fluctuating time field.


If you add a high‑precision MCLK without linking timelines, you may reduce jitter, but the musical timeline is still wobbling.


The result:

  • Clear sound, but unstable musical flow
  • Listening fatigue
  • Image distortion
  • Localization drift
  • And in some cases, even channel swapping under certain conditions


So what is SOF really?

SOF guarantees only one thing:

“Frame boundary and packet alignment at each interval.”


That’s it.


People think 1 ms / 125 µs is an absolute timekeeper.

But in reality, SOF is merely a boundary notification, not a guarantee of time precision.

Which is why it fluctuates.


Why is it designed this way?

“Isn’t this just bad implementation?”

No.


USB was designed as the successor to RS‑232 and other PC peripherals.

The host is a multitasking machine meant to do everything at once.

Speed is desired, but strict real‑time determinism would make it unusable for general computing.


Thus, USB prioritizes:

Packet integrity over real‑time precision.


This is why USBDACs historically struggled with real‑time performance and why DSD was explored as a workaround.


PopoDAC, however, takes the opposite approach:

It measures the real physical clock, detects real‑time behavior, and reconstructs the true TIMELINE.


This is the philosophy behind the PopoDAC Core Architecture.

(Sorry for the density… this chapter is a heavy one.)


Mission Command Layer

Returning to the main thread—

For the first Core chapter, we begin with the implementation of the MCL (Mission Command Layer), which is invoked from the system’s MainLoop.

Module1 Igniter

One of the most important responsibilities of the MCL is Module 1: Igniter.

This module performs the initialization and ignition of all 3 phases × 8 modules.

(And yes, MCL also handles shutdown, but we’ll skip that explanation here.)


Ignition occurs when the USB host enables ALT1 (UAC Output Endpoint) and notifies the device.

Therefore, the entry point is the callback:

tud_audio_set_itf_cb


i2s_prime_and_enable

static void i2s_prime_and_enable(i2s_chan_handle_t handle)

{

    // Initialize monitoring parameters

    g_ddc.ddc_ring_looses = 0;

    g_ddc.ddc_ring_wl = 0.0f;

    g_ddc.ddc_rx_size = 0,

    g_ddc.ddc_tx_size = 0,


    // Initialize PCNT counter

    normal_fscount(&g_cnt_ideal); // Set normal position


    // Initialize clock reference values

    g_cnt_ideal.last_fb = (1 << 14),   // Q14 = 1.0

    g_cnt_ideal.acc_q14 = 0,

    g_cnt_ideal.delta_fb_q = 0,

    g_cnt_ideal.source_clock_ratio = 1.0f,  // Initial ASRC ratio


    // Prepare I2S launch pad

    g_ddc.i2s_starting  = true;

    g_ddc.i2s_start_ms  = xTaskGetTickCount();

    g_ddc.counter_warmup_rollout = false;

    g_ddc.i2s_src_locked = false;

    g_ddc.i2s_src_lockcount = 0;

    g_ddc.i2s_src_phase_ratio = 1.0f;

    g_ddc.i2s_src_smooth_ratio = 1.0f;

    g_ddc.i2s_src_phase = 0;

    g_ddc.i2s_src_in_idx = 0;

    g_ddc.i2s_src_prev_consumed = -1;

    g_ddc.i2s_pcnt_delta_hz = 0;


    // Prepare UAC feedback engine

    g_ddc.uac_fb_inverval_count = 0;

    g_ddc.uac_fb_started = false;

    g_ddc.uac_fb_start_pending = true;   // Important

    g_ddc.uac_fb_locked = false;

    g_ddc.uac_fb_lockcount = 0;

    g_ddc.uac_long_err_mHz = 0;


    // Clear any remaining audio buffer

    rb_dropall(&g_audio_ring);


    // Reboot count timer

    gptimer_stop(g_gptimer);

    gptimer_start(g_gptimer);


    // Now enable to start DMA

    i2s_channel_enable(handle);

}


Flow Explanation

The flow is clean and straightforward.


Among the three phases, I2S is the last to be activated.

Before that, the Timer phase (Guidance & Navigation Control) is initialized and begins its prime‑roll sequence.


The UAC phase (Telemetry Downlink Receiver) is always active under TinyUSB, so once the callback returns, it immediately begins providing buffers.


A subtle but important point:

i2s_channel_enable() must be executed every time ALT1 opens.


In other words:

The I2S phase (Timeline Dynamics Processor) must start and stop in sync with the UAC Output Endpoint (ALT1).


This is mandatory for any DIY USB DAC.


“Can’t I just leave I2S enabled after i2s_init?”

No.

It will “work,” but it is still wrong.


ALT1 open/close signals represent stream boundary notifications.


What is a stream boundary?

Definitions vary, but conceptually:

  • The transition between tracks
  • In YouTube, the switch between programs
  • Any point where the host resets its transfer state


If ALT1 does not close between tracks, the timing drift accumulated in the previous track will leak into the next one.

To prevent this, the USB host resets its internal state by closing ALT1, reducing the load for the next track.

This behavior depends on both OS‑level drivers and application‑level logic, so it’s not guaranteed per track,


but:


When ALT1 closes, the host wants to reset the transfer.

We should use that opportunity to reset our side as well.


Therefore:

I2S start/stop must follow the Output EP open/close.

It’s extra work, but it is the correct approach.


Next Time

That’s it for Module 1.

Next time, we’ll cover the UAC phase (Telemetry Downlink Processing).


Stay tuned—this is where things get even more interesting.