ESP8266 軟件實現 Delta-sigma(ΔΣ)調製器 並經過I2S接口輸出PDM信號

  本文提出一種徹底由「軟件定義」的Delta-sigma調製器,用於取代硬件生成PDM(Pulse Density Modulation信號,從而下降成本。緩存

  該方案在低成本音頻應用中具備必定價值:經過調研咱們發現:在一些方案中,音頻DAC的成本居然與主控芯片成本至關,而加入PA電路後成本則更高。這些應用並不要求極高的音頻性能,在少許硬件輔助的狀況下,軟件定義的數模轉換器徹底能夠勝任過去由純硬件完成的工做。函數

  本文針對該問題給出的方案以下:一、利用軟件實現delta-sigma調製器;二、利用普通的I2S接口輸出PDM信號;三、經過簡單的RC低通濾波器還原出模擬音頻信號。這種方法在保證原始音質和較低的CPU運算負載的前提下,取消了DAC芯片並簡化了後級PA電路,進一步優化了成本。性能

  該方案在espressif公司的ESP8266平臺上測試經過。測試

 

1、一階Delta-sigma(ΔΣ)調製器的黑盒模型優化

  Delta-sigma(ΔΣ)調製器是Delta-sigma模數轉換器的核心部件,以下所示爲其最簡的一階形式的具體實現。ui

  爲了便於說明問題,咱們先暫時將其視做黑盒。因而,從A/D的角度看,它將輸入的模擬量調製爲1bit脈衝流,從而實現模擬到數字的轉換;而從D/A的角度看,調製輸出的脈衝通過低通濾波後便可還原回模擬信號,這是本方案的基礎所在。spa

 

1、一階Delta-sigma(ΔΣ)調製器的實現原理設計

  爲了更加清楚地描述整個調製器的工做過程,咱們在具體實現的基礎上,從Z域模型的角度去研究:code

 

  首先,由於轉換精度是有限的,這就不可避免地引入量化噪聲e(Z):blog

  e(Z) = y(Z) - x(Z)

  若是能將量化噪聲減小到必定範圍,則y(Z)能表明x(Z),從而實現調製。

  Delta-sigma使用了過採樣(即以遠高於Nyquist頻率的採樣率R*Fs/2進行採樣),過採樣後本來均勻分佈在0 ~ Fs/2頻帶內的量化噪聲被分散到了0 ~ R*Fs/2的頻帶上,所以減少了基帶內的量化噪聲。

  但有了過採樣還遠遠不夠,還有必要進行噪聲整形。因爲積分器的存在,調製器的傳輸函數爲:

  y(Z) = x(Z) + (1-Z-1)e(Z)

  輸出對量化噪聲e(Z)呈高通形式,這就實現了量化噪聲的整形。

  經過上述方法,量化噪聲基本趨向了高頻段並遠離基帶,經過一個低通濾波器便可基本濾除這些多餘的噪聲。

 

  從另外一種角度也能夠解釋調製器的工做原理。對整個調製過程作整體分析,咱們看到積分器的輸入爲:

  x(Z) - X'(Z)

  即系統對量化偏差進行了積分,其結果是:調製輸出積分後的波形不斷向着輸入波形逼近,這也許就是Delta-sigma的原理所在。

 

  爲了更加形象地瞭解delta-sigma調製器的工做狀態,咱們回到上面所提到的具體實現。輸入初相位0的正弦信號,在一個週期內各個節點的時域波形以下:

 

  觀察其中1-Bit DAC的波形,在模擬輸入爲Vref+的時間附近, 調製輸出大部分爲1(圖中未畫出,參考「1-Bit DAC」波形);而在模擬輸入爲Vref-的時間附近,調製輸出大部分爲0。同時還能夠看到,在模擬輸入爲0的時間附近,調製輸出不斷在0,1間振盪,這正是PDM(脈衝密度調製)這個名字的由來。

 

2、提升SNR

  SNR(信噪比)是評估轉換器性能的重要指標。

  對於L階的delta-sigma調製器,其理想信噪比有以下定量計算公式:

 

  SNR(dB) = 6.02N + 10lg(2L + 1) + 10(2L + 1)lg R - 10L

  其中N爲量化位數,R爲過採樣比。

  

  一階的Delta-sigma調製器SNR尚達不到音頻應用的水平,所以須要經過改進設計提升SNR。

  從上式能夠看出,若要提升信噪比,能夠增長調製器的階數L、量化位數N、或者過採樣比R。

  因爲咱們使用的I2S接口支持的時鐘頻率有限,經過提升時鐘頻率來減小量化噪聲不是一個頗有效的辦法,所以考慮採用更高的量化位數來下降對採樣率的要求,但受制於運算性能,難以作到很高的量化精度。

  綜上可知,增長調製器階數是最有效的方法。固然階數必須合理設置,由於提升階數後,系統的穩定性也下降了,同時也增長了CPU的運算負載。

 

3、二階Delta-sigma調製器

  基於上面的考慮,咱們採用二階調製器。一個典型的二階調製器以下圖所示:

  固然,也能夠採用高於2階的delta-sigma調製器,但難以像上面這樣經過簡單地增長積分器實現它們。系統的複雜度增長了。

 

4、軟件實現二階Delta-sigma調製器

  如今咱們要以「軟件定義」的方式去實現上文所描述的二階調製器。

  注意到鎖存器(latch)在電路中的做用:連續的信號流在時鐘的做用下離散化了,所以硬件的每一個時鐘週期對應到軟件中即執行一趟處理函數,更新狀態並將本次結果緩存起來。換句話說,硬件的每一個時鐘週期都對應於軟件執行一遍處理函數。由於軟件不是按調製頻率運行的(比調製頻率快得多),是非實時的,須要引入緩存來確保硬件能以正確的時鐘頻率還原調製結果——I2S按調製時鐘的節拍依次輸出緩存內容,從而還原結果。

  這裏採用C語言完成DSP。

1 int32_t w;                     /* Data Flow path */
2 static int i1v = 0, i2v = 0;   /* Integrator 1 and 2 */
3 static int latch_reg = 0;      /* Latch */

  對每一個調製週期的處理過程以下。對輸入電平的採樣幀w迭代n次可得出任意採樣率的調製輸出。

 1 #define HW (32767)
 2 
 3 [Input: w]
 4 
 5 if (latch_reg > 0) w -= HW; else w += HW; /* Difference 1 */
 6 w += i1v; i1v = w; /* Integrator 1 */
 7 if (latch_reg > 0) w -= HW; else w += HW; /* Difference 2 */
 8 w += i2v; i2v = w; /* Integrator 2 */
 9 latch_reg = w;   /* Latch */
10 b = (w > 0);     /* Comparator */
11 
12 [Output to bitstream: b]

 

  如今假設咱們對每一採樣迭代32次,則調製器的採樣頻率可經過以下方法計算:

    Fs = Fs(Input) * 32,其中Fs(Input)爲輸入數字信號的原始採樣率。

  例如:對於PCM音頻數據,若原始採樣率爲48kHz,則該delta-sigma調製器的時鐘頻率可達:

    Fs = 48kHz * 32 = 1.536MHz

  則要求I2S總線的BCLK時鐘頻率至少達到:

    Fmin = Fs = 1.536MHz

 

5、ESP8266的I2S輸出端口

  因爲I2S接口具備串行數據連續傳輸而不斷流的特性,所以I2S接口可用於輸出delta-sigma調製器的PDM脈衝流。除I2S接口外,其它具備連續串行輸出特性的接口也能夠承擔輸出比特流的工做,本文僅以I2S接口爲例說明。

  由於I2S最初的設計目的並非輸出PDM脈衝流,具體實現須要一些變通:

 

  首先將I2S的傳輸格式配置爲16bit x 2chs(雙聲道),則每一個傳送週期可發送32個比特位。

  Delta-sigma調製輸出的PDM脈衝流是連續的,須要按每32個比特一組的分法切分爲若干字節,而後「假裝」成4字節的PCM音頻採樣數據,經過DMA傳輸到I2S模塊,而I2S模塊再將假裝的PCM採樣串行化輸出,最終咱們即可以從芯片的SDAT端口獲得完整的脈衝流信號。

  寫入I2S模塊的數據會預先壓入FIFO緩衝器(硬件爲咱們隱藏了細節),在I2S時鐘的驅動下,I2S會以慢於寫的速率從FIFO取出數據,從而能夠保證輸出脈衝流的連續性。

  以上即是對於I2S端口輸出PDM脈衝流的分析。

 

  接下來講明完整的代碼實現。函數samp_to_delta_sigma(s)實現了將每一個電平採樣s調製爲32bit脈衝流:

 1 int32_t
 2 samp_to_delta_sigma(short s)
 3 {
 4   int w;
 5   static int i1v = 0, i2v = 0;
 6   static int latch_reg = 0;
 7 
 8   int i;
 9   int32_t val=0;
10   
11   for (i=0; i<32; i++)
12    {
13       val<<=1;
14       w=s;
15       if (latch_reg > 0) w -= HW; else w += HW; /* Difference 1 */
16       w += i1v; i1v = w; /* Integrator 1 */
17       if (latch_reg > 0) w -= HW; else w += HW; /* Difference 2 */
18       w += i2v; i2v = w; /* Integrator 2 */
19       latch_reg = w;   /* Latch */
20       if (w > 0) val|=1; /* comparator */
21     }
22   return val;
23 }

 

  有了脈衝流,接下來考慮如何將其輸出到硬件上。本文采用espressif提供的I2S驅動庫,它提供了三個函數:I2sInit()用於初始化I2S接口,I2sSetRate()用於設置採樣率,i2sPushSample用於向緩衝區中壓入數據。

 

  以下爲一個調用調製器的實例,核心代碼只有4行,該實例調製採樣率爲48kHz的PCM音頻信號並輸出PDM.

  其中:size = 音頻採樣幀數,s是一塊連續內存,存儲全部音頻採樣(short類型)。

1 I2sInit();
2 I2sSetRate(48000, 0);
3 
4 for(i=0; i < size; i++)
5   i2sPushSample( samp_to_delta_sigma(s[i]) );

   對於每一個輸入信號採樣s:經過調用i2sPushSample( samp_to_delta_sigma(s) )便可實現調製輸出。

 

6、CPU負載評估 

  仍以原始採樣率爲48kHz的PCM音頻數據爲例,從第五節已經得出,FIFO輸出側(I2S端口)最小帶寬爲 W1 = 1.536 * 10^(6) / 1024^2 ≈ 1.5 (MBits/s)。對於FIFO輸入側(軟件調製器),爲便於計算,先設CPU執行一次samp_to_delta_sigma()函數的平均用時爲T0 (s),則軟件調製的輸出帶寬爲 W2 = 32 / T0 / 1024^2 (MBits/s)

  若系統能穩定工做,則要求I2S端口實際帶寬Wf與W一、W2知足以下關係(正常狀況下W1 = Wf,以確保正確還原比特流信號的時鐘頻率):

    W1 <= Wf < W2

  一旦條件知足,CPU將獲得空閒時間:

    Tfree = 1 / [(W2 - Wf) * 1024^2] (s)

  這是由於系統運行中,除起始狀態外FIFO將永遠保持非空狀態。Tfree能夠表明用於運行其它任務的空閒時間長度(包括任務調度切換的時間)。若其它操做佔用超過Tfree的運行時間,則可能致使FIFO輸入側帶寬不足,從而形成FIFO下溢出,使得輸出中斷。

  T0的決定因素很是複雜,須要取平均值T0,將T0代入上式便可得出近似的Tfree時間。

 

7、後級電路

  一、可經過簡單的一階RC低通濾波器,直接從I2S接口得出模擬信號,從而省去成本較高的DAC芯片。

 

  二、在要求功率較小的狀況下(例如驅動小型揚聲器或者耳機),徹底能夠對輸出脈衝流進行簡單緩衝後,接入揚聲器發聲。

 

  三、加入簡單的功率輸出和濾波電路,便可實現Class-D數字功放,以下圖所示。

 

  最後,將該方案擴展到非音頻的應用是可行的,但只能在對信號的帶寬,精度等的要求都不嚴格的場合使用。

相關文章
相關標籤/搜索