天天看點

L3總線協定及時序示意代碼

    CODEC目前實作内部寄存器的操作一般有SPI、IIC和L3.這裡介紹L3.

    L3接口實際上是一種串行接口,它由3根信号線組成,完成處理器和C0DEC之間的資料和控制信号交換.DAl341TS就是采用L3接口.

    L3DATA:處理器接口資料線; 

    L3MODE:處理器接口模式信号線;

    L3CLOCK:處理器接口時鐘信号線.

    一般而言,一款CPU的硬體音頻系統一般帶有L3接口,否則隻能用GPIO模拟了.

    L3總線有寫位址和資料之分,對于寫位址L3MODE為L(0),寫資料L3MODE為H(1),時鐘和模式開始都應該為1,資料線開始為0.先寫位址在些資料,先發低位在發高位.

     當發起資料通訊時,一般選標明位址模式,接下來就是資料傳輸.

    以UDA1341TS為例,位址模式:

L3總線協定及時序示意代碼

        下面根據此時序圖寫出示意代碼.根據時序圖寫代碼,首先要學會看時序圖.是以,需要注意下面的知識點:       

1.時序圖從左到右看,有箭頭的地方表示有時序的要求,即需要寫代碼;
2.每一次電平變化都應該有時序的要求;
3.箭頭都是匹對的,左右對向為一組,兩箭頭之間便是狀态保持時間,這對應代碼适當的延時;
           

        根據上述三點,從左到右,成對看箭頭.

        首先L3CLOCK為高電平,L3MODE為高電平;L3MODE變為低之前,必須保持th時間段的狀态保持:

L3CLOCK = 1;
L3MODE = 1;
udelay(th);
L3MODE = 0;
           

        L3MODE拉低之後,L3CLOCK不能立馬拉低,還需要保持tsu時間段的狀态保持:

udelay(tsu);
L3CLOCK = 0;
           

        與此同時,L3DATA輸出一個位的資料.此時L3CLOCK要變成高電平之前,需要保持tsu時間段的狀态保持,資料才穩定:

L3DATA = X(X = 0,1);
udelay(tsu);
L3CLOCK = 1;
           

        L3CLOCK變成高電平後,需要保持th時間段的狀态,保證資料被讀取:

udelay(th);
           

        當一個位元組被傳輸完之後,L3MODE被拉高之前,L3CLOCK需要th時間段的高電平狀态保持:

L3CLOCK = 1;
L3MODE = 1;
           

        當L3MODE被拉高之後,L3CLOCK不能立馬拉氏.還需要tsu時間段的高電平狀态保持:

udelay(tsu);
           

        至此,形成了1Byte的周期.

       是以,完整的時序示意代碼如下:

L3CLOCK = 1;
L3MODE = 1;
udelay(th);
L3MODE = 0;
udelay(tsu);

for(i = 0; i < 8; ++i)
{
    L3CLOCK = 0;
    L3DATA = X(X = 0,1);
    udelay(tsu);
    L3CLOCK = 1;
    udelay(th);
}
    L3MODE = 1;
    udelay(tsu);
           

       對應核心代碼sound/soc/codecs/l3.c:

int l3_write(struct l3_pins *adap, u8 addr, u8 *data, int len)
{
	adap->setclk(1);
	adap->setmode(1);
	udelay(adap->mode);

	adap->setmode(0);
	udelay(adap->mode_setup);
	sendbyte(adap, addr);
	udelay(adap->mode_hold);

}
           

        其中,sendbyte()函數如下:

static void sendbyte(struct l3_pins *adap, unsigned int byte)
{
	int i;

	for (i = 0; i < 8; i++) {
		adap->setclk(0);
		udelay(adap->data_hold);
		adap->setdat(byte & 1);
		udelay(adap->data_setup);
		adap->setclk(1);
		udelay(adap->clock_high);
		byte >>= 1;
	}
}
           

        l3_write()函數在接下來的sendbytes()函數完成了示意代碼中L3MODE = 1;udelay(tsu);是以,沒有在上述分析中表現出這樣的代碼.

        資料模式:

L3總線協定及時序示意代碼

    當然,可以将位址後位址後面緊随的資料一并批量傳輸:

L3總線協定及時序示意代碼

        大體講述此時序圖的意義.L3MODE為低時L3DATA傳輸的是位址資料;當L3MODE為高時,L3DATA傳輸的是資料資訊.每8個bit之間需要tstp時間段的延時.可以一次性完成2個Byte的資料傳輸.

        對應sound/soc/codecs/l3.c:

/*
 * Send a set of bytes to the chip.  We need to pulse the MODE line
 * between each byte, but never at the start nor at the end of the
 * transfer.
 */
static void sendbytes(struct l3_pins *adap, const u8 *buf,
		      int len)
{
	int i;

	for (i = 0; i < len; i++) {
		if (i) {
			udelay(adap->mode_hold);
			adap->setmode(0);
			udelay(adap->mode);
		}
		adap->setmode(1);
		udelay(adap->mode_setup);
		sendbyte(adap, buf[i]);
	}
}
           

繼續閱讀